aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CREDITS16
-rw-r--r--Documentation/ABI/removed/raw1394_legacy_isochronous16
-rw-r--r--Documentation/ABI/testing/sysfs-bus-usb13
-rw-r--r--Documentation/BUG-HUNTING24
-rw-r--r--Documentation/DMA-mapping.txt103
-rw-r--r--Documentation/DocBook/kernel-api.tmpl66
-rw-r--r--Documentation/HOWTO28
-rw-r--r--Documentation/SM501.txt66
-rw-r--r--Documentation/SubmitChecklist6
-rw-r--r--Documentation/SubmittingPatches63
-rw-r--r--Documentation/atomic_ops.txt2
-rw-r--r--Documentation/blackfin/kgdb.txt155
-rw-r--r--Documentation/block/barrier.txt16
-rw-r--r--Documentation/driver-model/platform.txt40
-rw-r--r--Documentation/feature-removal-schedule.txt76
-rw-r--r--Documentation/filesystems/tmpfs.txt10
-rw-r--r--Documentation/firmware_class/README2
-rw-r--r--Documentation/firmware_class/firmware_sample_driver.c2
-rw-r--r--Documentation/firmware_class/firmware_sample_firmware_class.c6
-rw-r--r--Documentation/hrtimer/timer_stats.txt7
-rw-r--r--Documentation/i2c/busses/i2c-i8014
-rw-r--r--Documentation/i2c/busses/i2c-piix42
-rw-r--r--Documentation/i2c/busses/i2c-taos-evm46
-rw-r--r--Documentation/i2c/chips/max68752
-rw-r--r--Documentation/i2c/chips/x120538
-rw-r--r--Documentation/i2c/summary2
-rw-r--r--Documentation/i2c/writing-clients2
-rw-r--r--Documentation/i386/zero-page.txt1
-rw-r--r--Documentation/ia64/aliasing-test.c28
-rw-r--r--Documentation/ia64/aliasing.txt12
-rw-r--r--Documentation/kernel-parameters.txt90
-rw-r--r--Documentation/networking/00-INDEX5
-rw-r--r--Documentation/networking/cxacru.txt84
-rw-r--r--Documentation/networking/ip-sysctl.txt9
-rw-r--r--Documentation/networking/l2tp.txt169
-rw-r--r--Documentation/networking/mac80211-injection.txt59
-rw-r--r--Documentation/networking/multiqueue.txt111
-rw-r--r--Documentation/networking/netdevices.txt38
-rw-r--r--Documentation/networking/radiotap-headers.txt152
-rw-r--r--Documentation/networking/sk98lin.txt568
-rw-r--r--Documentation/networking/spider_net.txt204
-rw-r--r--Documentation/networking/xfrm_sysctl.txt4
-rw-r--r--Documentation/pci.txt8
-rw-r--r--Documentation/power/pci.txt37
-rw-r--r--Documentation/power/swsusp.txt3
-rw-r--r--Documentation/power_supply_class.txt167
-rw-r--r--Documentation/powerpc/booting-without-of.txt59
-rw-r--r--Documentation/sched-design-CFS.txt119
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt1
-rw-r--r--Documentation/sysctl/vm.txt15
-rw-r--r--Documentation/sysfs-rules.txt166
-rw-r--r--Documentation/thinkpad-acpi.txt25
-rw-r--r--Documentation/usb/dma.txt52
-rw-r--r--Documentation/usb/persist.txt156
-rw-r--r--Documentation/vm/slub.txt135
-rw-r--r--Documentation/volatile-considered-harmful.txt119
-rw-r--r--Documentation/watchdog/pcwd-watchdog.txt8
-rw-r--r--Documentation/watchdog/watchdog-api.txt236
-rw-r--r--Documentation/watchdog/watchdog.txt94
-rw-r--r--Documentation/watchdog/wdt.txt43
-rw-r--r--MAINTAINERS217
-rw-r--r--Makefile4
-rw-r--r--arch/alpha/Kconfig45
-rw-r--r--arch/alpha/boot/tools/mkbb.c2
-rw-r--r--arch/alpha/kernel/console.c70
-rw-r--r--arch/alpha/kernel/core_marvel.c43
-rw-r--r--arch/alpha/kernel/core_titan.c70
-rw-r--r--arch/alpha/kernel/core_tsunami.c24
-rw-r--r--arch/alpha/kernel/pci_iommu.c32
-rw-r--r--arch/alpha/kernel/proto.h9
-rw-r--r--arch/alpha/kernel/sys_dp264.c11
-rw-r--r--arch/alpha/kernel/sys_marvel.c4
-rw-r--r--arch/alpha/kernel/sys_titan.c2
-rw-r--r--arch/alpha/lib/csum_ipv6_magic.S51
-rw-r--r--arch/alpha/lib/ev6-csum_ipv6_magic.S42
-rw-r--r--arch/arm/Kconfig10
-rw-r--r--arch/arm/boot/.gitignore3
-rw-r--r--arch/arm/boot/compressed/.gitignore1
-rw-r--r--arch/arm/boot/compressed/Makefile13
-rw-r--r--arch/arm/boot/compressed/head-xscale.S5
-rw-r--r--arch/arm/boot/compressed/head.S99
-rw-r--r--arch/arm/common/locomo.c11
-rw-r--r--arch/arm/common/sa1111.c13
-rw-r--r--arch/arm/common/sharpsl_pm.c2
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/head-common.S40
-rw-r--r--arch/arm/kernel/head.S7
-rw-r--r--arch/arm/kernel/process.c69
-rw-r--r--arch/arm/kernel/setup.c6
-rw-r--r--arch/arm/kernel/sys_arm.c13
-rw-r--r--arch/arm/kernel/traps.c22
-rw-r--r--arch/arm/mach-at91/board-sam9261ek.c130
-rw-r--r--arch/arm/mach-at91/board-sam9263ek.c64
-rw-r--r--arch/arm/mach-at91/clock.c5
-rw-r--r--arch/arm/mach-at91/pm.c15
-rw-r--r--arch/arm/mach-davinci/Makefile3
-rw-r--r--arch/arm/mach-davinci/board-evm.c2
-rw-r--r--arch/arm/mach-davinci/clock.c323
-rw-r--r--arch/arm/mach-davinci/clock.h33
-rw-r--r--arch/arm/mach-davinci/gpio.c286
-rw-r--r--arch/arm/mach-davinci/io.c6
-rw-r--r--arch/arm/mach-davinci/mux.c41
-rw-r--r--arch/arm/mach-davinci/psc.c87
-rw-r--r--arch/arm/mach-imx/generic.c118
-rw-r--r--arch/arm/mach-imx/time.c121
-rw-r--r--arch/arm/mach-iop13xx/setup.c217
-rw-r--r--arch/arm/mach-iop13xx/tpmi.c32
-rw-r--r--arch/arm/mach-iop32x/glantank.c2
-rw-r--r--arch/arm/mach-iop32x/iq31244.c5
-rw-r--r--arch/arm/mach-iop32x/iq80321.c3
-rw-r--r--arch/arm/mach-iop32x/n2100.c2
-rw-r--r--arch/arm/mach-iop33x/iq80331.c3
-rw-r--r--arch/arm/mach-iop33x/iq80332.c3
-rw-r--r--arch/arm/mach-ixp4xx/Kconfig16
-rw-r--r--arch/arm/mach-ixp4xx/Makefile4
-rw-r--r--arch/arm/mach-ixp4xx/gateway7001-pci.c63
-rw-r--r--arch/arm/mach-ixp4xx/gateway7001-setup.c108
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-pci.c8
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c96
-rw-r--r--arch/arm/mach-ixp4xx/wg302v2-pci.c63
-rw-r--r--arch/arm/mach-ixp4xx/wg302v2-setup.c109
-rw-r--r--arch/arm/mach-ks8695/Makefile2
-rw-r--r--arch/arm/mach-ks8695/gpio.c218
-rw-r--r--arch/arm/mach-pxa/clock.c15
-rw-r--r--arch/arm/mach-pxa/corgi.c7
-rw-r--r--arch/arm/mach-pxa/devices.h11
-rw-r--r--arch/arm/mach-pxa/dma.c44
-rw-r--r--arch/arm/mach-pxa/generic.c93
-rw-r--r--arch/arm/mach-pxa/generic.h6
-rw-r--r--arch/arm/mach-pxa/idp.c3
-rw-r--r--arch/arm/mach-pxa/irq.c106
-rw-r--r--arch/arm/mach-pxa/lpd270.c3
-rw-r--r--arch/arm/mach-pxa/lubbock.c3
-rw-r--r--arch/arm/mach-pxa/mainstone.c3
-rw-r--r--arch/arm/mach-pxa/pm.c47
-rw-r--r--arch/arm/mach-pxa/poodle.c3
-rw-r--r--arch/arm/mach-pxa/pxa25x.c62
-rw-r--r--arch/arm/mach-pxa/pxa27x.c82
-rw-r--r--arch/arm/mach-pxa/spitz.c7
-rw-r--r--arch/arm/mach-pxa/time.c9
-rw-r--r--arch/arm/mach-pxa/tosa.c4
-rw-r--r--arch/arm/mach-pxa/trizeps4.c3
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c59
-rw-r--r--arch/arm/mach-s3c2440/mach-anubis.c145
-rw-r--r--arch/arm/mach-s3c2440/mach-osiris.c96
-rw-r--r--arch/arm/mach-sa1100/neponset.c15
-rw-r--r--arch/arm/mach-sa1100/pm.c9
-rw-r--r--arch/arm/mach-sa1100/time.c24
-rw-r--r--arch/arm/mach-versatile/pci.c5
-rw-r--r--arch/arm/mm/alignment.c2
-rw-r--r--arch/arm/mm/ioremap.c10
-rw-r--r--arch/arm/mm/mmu.c4
-rw-r--r--arch/arm/oprofile/op_model_mpcore.c2
-rw-r--r--arch/arm/plat-iop/Makefile2
-rw-r--r--arch/arm/plat-iop/adma.c209
-rw-r--r--arch/arm/vfp/entry.S4
-rw-r--r--arch/arm/vfp/vfpmodule.c5
-rw-r--r--arch/avr32/boards/atngw100/setup.c3
-rw-r--r--arch/avr32/boards/atstk1000/atstk1002.c1
-rw-r--r--arch/avr32/configs/atngw100_defconfig152
-rw-r--r--arch/avr32/configs/atstk1002_defconfig180
-rw-r--r--arch/avr32/mach-at32ap/at32ap7000.c12
-rw-r--r--arch/avr32/mm/cache.c14
-rw-r--r--arch/avr32/mm/fault.c2
-rw-r--r--arch/blackfin/Kconfig100
-rw-r--r--arch/blackfin/Makefile23
-rw-r--r--arch/blackfin/boot/Makefile3
-rw-r--r--arch/blackfin/configs/BF533-EZKIT_defconfig251
-rw-r--r--arch/blackfin/configs/BF533-STAMP_defconfig110
-rw-r--r--arch/blackfin/configs/BF537-STAMP_defconfig116
-rw-r--r--arch/blackfin/configs/BF548-EZKIT_defconfig (renamed from arch/blackfin/defconfig)587
-rw-r--r--arch/blackfin/configs/BF561-EZKIT_defconfig202
-rw-r--r--arch/blackfin/configs/PNAV-10_defconfig130
-rw-r--r--arch/blackfin/kernel/Makefile7
-rw-r--r--arch/blackfin/kernel/asm-offsets.c7
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c257
-rw-r--r--arch/blackfin/kernel/bfin_gpio.c25
-rw-r--r--arch/blackfin/kernel/bfin_ksyms.c5
-rw-r--r--arch/blackfin/kernel/cacheinit.c66
-rw-r--r--arch/blackfin/kernel/cplbinit.c433
-rw-r--r--arch/blackfin/kernel/dma-mapping.c13
-rw-r--r--arch/blackfin/kernel/dualcore_test.c6
-rw-r--r--arch/blackfin/kernel/entry.S5
-rw-r--r--arch/blackfin/kernel/fixed_code.S132
-rw-r--r--arch/blackfin/kernel/flat.c55
-rw-r--r--arch/blackfin/kernel/irqchip.c4
-rw-r--r--arch/blackfin/kernel/kgdb.c421
-rw-r--r--arch/blackfin/kernel/module.c32
-rw-r--r--arch/blackfin/kernel/process.c75
-rw-r--r--arch/blackfin/kernel/ptrace.c6
-rw-r--r--arch/blackfin/kernel/setup.c398
-rw-r--r--arch/blackfin/kernel/signal.c10
-rw-r--r--arch/blackfin/kernel/sys_bfin.c8
-rw-r--r--arch/blackfin/kernel/time.c4
-rw-r--r--arch/blackfin/kernel/traps.c200
-rw-r--r--arch/blackfin/kernel/vmlinux.lds.S170
-rw-r--r--arch/blackfin/lib/divsi3.S3
-rw-r--r--arch/blackfin/lib/ins.S4
-rw-r--r--arch/blackfin/lib/memchr.S2
-rw-r--r--arch/blackfin/lib/memcmp.S7
-rw-r--r--arch/blackfin/lib/memcpy.S15
-rw-r--r--arch/blackfin/lib/memmove.S19
-rw-r--r--arch/blackfin/lib/memset.S2
-rw-r--r--arch/blackfin/lib/modsi3.S2
-rw-r--r--arch/blackfin/lib/outs.S3
-rw-r--r--arch/blackfin/lib/smulsi3_highpart.S2
-rw-r--r--arch/blackfin/lib/strcmp.c3
-rw-r--r--arch/blackfin/lib/strcpy.c3
-rw-r--r--arch/blackfin/lib/strncmp.c3
-rw-r--r--arch/blackfin/lib/strncpy.c3
-rw-r--r--arch/blackfin/lib/udivsi3.S2
-rw-r--r--arch/blackfin/lib/umodsi3.S4
-rw-r--r--arch/blackfin/lib/umulsi3_highpart.S2
-rw-r--r--arch/blackfin/mach-bf533/Makefile4
-rw-r--r--arch/blackfin/mach-bf533/boards/cm_bf533.c16
-rw-r--r--arch/blackfin/mach-bf533/boards/ezkit.c10
-rw-r--r--arch/blackfin/mach-bf533/boards/generic_board.c6
-rw-r--r--arch/blackfin/mach-bf533/boards/stamp.c30
-rw-r--r--arch/blackfin/mach-bf533/cpu.c3
-rw-r--r--arch/blackfin/mach-bf533/dma.c95
-rw-r--r--arch/blackfin/mach-bf533/head.S35
-rw-r--r--arch/blackfin/mach-bf533/ints-priority.c4
-rw-r--r--arch/blackfin/mach-bf537/Makefile2
-rw-r--r--arch/blackfin/mach-bf537/boards/cm_bf537.c16
-rw-r--r--arch/blackfin/mach-bf537/boards/eth_mac.c5
-rw-r--r--arch/blackfin/mach-bf537/boards/generic_board.c38
-rw-r--r--arch/blackfin/mach-bf537/boards/pnav10.c56
-rw-r--r--arch/blackfin/mach-bf537/boards/stamp.c79
-rw-r--r--arch/blackfin/mach-bf537/dma.c115
-rw-r--r--arch/blackfin/mach-bf537/head.S41
-rw-r--r--arch/blackfin/mach-bf537/ints-priority.c4
-rw-r--r--arch/blackfin/mach-bf548/Kconfig316
-rw-r--r--arch/blackfin/mach-bf548/Makefile9
-rw-r--r--arch/blackfin/mach-bf548/boards/Makefile5
-rw-r--r--arch/blackfin/mach-bf548/boards/ezkit.c114
-rw-r--r--arch/blackfin/mach-bf548/boards/led.S172
-rw-r--r--arch/blackfin/mach-bf548/cpu.c159
-rw-r--r--arch/blackfin/mach-bf548/dma.c156
-rw-r--r--arch/blackfin/mach-bf548/gpio.c323
-rw-r--r--arch/blackfin/mach-bf548/head.S512
-rw-r--r--arch/blackfin/mach-bf548/ints-priority.c137
-rw-r--r--arch/blackfin/mach-bf561/Makefile2
-rw-r--r--arch/blackfin/mach-bf561/boards/cm_bf561.c36
-rw-r--r--arch/blackfin/mach-bf561/boards/ezkit.c33
-rw-r--r--arch/blackfin/mach-bf561/boards/generic_board.c6
-rw-r--r--arch/blackfin/mach-bf561/boards/tepla.c6
-rw-r--r--arch/blackfin/mach-bf561/coreb.c18
-rw-r--r--arch/blackfin/mach-bf561/dma.c131
-rw-r--r--arch/blackfin/mach-bf561/head.S39
-rw-r--r--arch/blackfin/mach-bf561/ints-priority.c4
-rw-r--r--arch/blackfin/mach-common/Makefile4
-rw-r--r--arch/blackfin/mach-common/cache.S30
-rw-r--r--arch/blackfin/mach-common/cacheinit.S89
-rw-r--r--arch/blackfin/mach-common/cplbhdlr.S4
-rw-r--r--arch/blackfin/mach-common/cplbinfo.c15
-rw-r--r--arch/blackfin/mach-common/cplbmgr.S1
-rw-r--r--arch/blackfin/mach-common/entry.S90
-rw-r--r--arch/blackfin/mach-common/interrupt.S12
-rw-r--r--arch/blackfin/mach-common/ints-priority-dc.c15
-rw-r--r--arch/blackfin/mach-common/ints-priority-sc.c407
-rw-r--r--arch/blackfin/mach-common/lock.S4
-rw-r--r--arch/blackfin/mach-common/pm.c6
-rw-r--r--arch/blackfin/mm/blackfin_sram.c115
-rw-r--r--arch/blackfin/mm/init.c57
-rw-r--r--arch/blackfin/oprofile/common.c6
-rw-r--r--arch/blackfin/oprofile/op_model_bf533.c6
-rw-r--r--arch/blackfin/oprofile/timer_int.c3
-rw-r--r--arch/h8300/kernel/sys_h8300.c4
-rw-r--r--arch/h8300/kernel/traps.c2
-rw-r--r--arch/i386/Kconfig6
-rw-r--r--arch/i386/Kconfig.cpu8
-rw-r--r--arch/i386/boot/Makefile48
-rw-r--r--arch/i386/boot/a20.c161
-rw-r--r--arch/i386/boot/apm.c97
-rw-r--r--arch/i386/boot/bitops.h45
-rw-r--r--arch/i386/boot/boot.h296
-rw-r--r--arch/i386/boot/bootsect.S98
-rw-r--r--arch/i386/boot/cmdline.c97
-rw-r--r--arch/i386/boot/code16gcc.h15
-rw-r--r--arch/i386/boot/compressed/Makefile7
-rw-r--r--arch/i386/boot/compressed/head.S6
-rw-r--r--arch/i386/boot/copy.S101
-rw-r--r--arch/i386/boot/cpu.c69
-rw-r--r--arch/i386/boot/cpucheck.c267
-rw-r--r--arch/i386/boot/edd.S231
-rw-r--r--arch/i386/boot/edd.c196
-rw-r--r--arch/i386/boot/header.S283
-rw-r--r--arch/i386/boot/main.c161
-rw-r--r--arch/i386/boot/mca.c43
-rw-r--r--arch/i386/boot/memory.c99
-rw-r--r--arch/i386/boot/pm.c170
-rw-r--r--arch/i386/boot/pmjump.S54
-rw-r--r--arch/i386/boot/printf.c307
-rw-r--r--arch/i386/boot/setup.S1075
-rw-r--r--arch/i386/boot/setup.ld54
-rw-r--r--arch/i386/boot/string.c52
-rw-r--r--arch/i386/boot/tools/build.c160
-rw-r--r--arch/i386/boot/tty.c112
-rw-r--r--arch/i386/boot/version.c23
-rw-r--r--arch/i386/boot/vesa.h79
-rw-r--r--arch/i386/boot/video-bios.c125
-rw-r--r--arch/i386/boot/video-vesa.c284
-rw-r--r--arch/i386/boot/video-vga.c260
-rw-r--r--arch/i386/boot/video.S2043
-rw-r--r--arch/i386/boot/video.c456
-rw-r--r--arch/i386/boot/video.h145
-rw-r--r--arch/i386/boot/voyager.c46
-rw-r--r--arch/i386/kernel/acpi/boot.c21
-rw-r--r--arch/i386/kernel/acpi/wakeup.S2
-rw-r--r--arch/i386/kernel/cpu/Makefile2
-rw-r--r--arch/i386/kernel/cpu/addon_cpuid_features.c50
-rw-r--r--arch/i386/kernel/cpu/common.c2
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig31
-rw-r--r--arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c13
-rw-r--r--arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c6
-rw-r--r--arch/i386/kernel/cpu/cpufreq/gx-suspmod.c4
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c216
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.h12
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c29
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c276
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-ich.c4
-rw-r--r--arch/i386/kernel/cpu/mtrr/cyrix.c4
-rw-r--r--arch/i386/kernel/cpu/mtrr/generic.c12
-rw-r--r--arch/i386/kernel/cpu/mtrr/main.c11
-rw-r--r--arch/i386/kernel/cpu/perfctr-watchdog.c61
-rw-r--r--arch/i386/kernel/cpu/proc.c21
-rw-r--r--arch/i386/kernel/e820.c2
-rw-r--r--arch/i386/kernel/entry.S8
-rw-r--r--arch/i386/kernel/microcode.c2
-rw-r--r--arch/i386/kernel/pci-dma.c27
-rw-r--r--arch/i386/kernel/quirks.c5
-rw-r--r--arch/i386/kernel/reboot.c8
-rw-r--r--arch/i386/kernel/reboot_fixups.c13
-rw-r--r--arch/i386/kernel/setup.c12
-rw-r--r--arch/i386/kernel/smpboot.c13
-rw-r--r--arch/i386/kernel/tsc.c9
-rw-r--r--arch/i386/kernel/verify_cpu.S94
-rw-r--r--arch/i386/kernel/vmi.c1
-rw-r--r--arch/i386/mach-es7000/es7000plat.c48
-rw-r--r--arch/i386/mach-visws/traps.c4
-rw-r--r--arch/i386/math-emu/fpu_entry.c2
-rw-r--r--arch/i386/mm/fault.c5
-rw-r--r--arch/i386/mm/init.c3
-rw-r--r--arch/i386/mm/pageattr.c30
-rw-r--r--arch/i386/oprofile/nmi_int.c12
-rw-r--r--arch/i386/pci/fixup.c20
-rw-r--r--arch/ia64/Kconfig6
-rw-r--r--arch/ia64/kernel/gate.S1
-rw-r--r--arch/ia64/kernel/mca.c60
-rw-r--r--arch/ia64/kernel/mca_asm.S12
-rw-r--r--arch/ia64/kernel/mca_drv_asm.S6
-rw-r--r--arch/ia64/kernel/process.c3
-rw-r--r--arch/ia64/kernel/setup.c6
-rw-r--r--arch/ia64/kernel/time.c1
-rw-r--r--arch/ia64/kernel/unwind.c16
-rw-r--r--arch/ia64/mm/hugetlbpage.c3
-rw-r--r--arch/ia64/mm/tlb.c2
-rw-r--r--arch/ia64/pci/pci.c22
-rw-r--r--arch/ia64/sn/kernel/io_acpi_init.c17
-rw-r--r--arch/ia64/sn/kernel/io_init.c20
-rw-r--r--arch/ia64/sn/kernel/tiocx.c2
-rw-r--r--arch/ia64/sn/kernel/xp_nofault.S3
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c9
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c4
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c4
-rw-r--r--arch/m68k/Kconfig16
-rw-r--r--arch/m68k/Makefile1
-rw-r--r--arch/m68k/kernel/Makefile3
-rw-r--r--arch/m68k/kernel/module.c31
-rw-r--r--arch/m68k/kernel/module.lds7
-rw-r--r--arch/m68k/kernel/setup.c37
-rw-r--r--arch/m68k/kernel/vmlinux-std.lds5
-rw-r--r--arch/m68k/kernel/vmlinux-sun3.lds5
-rw-r--r--arch/m68k/mac/debug.c2
-rw-r--r--arch/m68k/mm/init.c119
-rw-r--r--arch/m68k/mm/memory.c73
-rw-r--r--arch/m68k/mm/motorola.c104
-rw-r--r--arch/m68k/sun3/config.c2
-rw-r--r--arch/m68knommu/platform/5307/timers.c10
-rw-r--r--arch/mips/Kconfig230
-rw-r--r--arch/mips/Kconfig.debug2
-rw-r--r--arch/mips/Makefile84
-rw-r--r--arch/mips/au1000/common/gpio.c124
-rw-r--r--arch/mips/au1000/common/platform.c2
-rw-r--r--arch/mips/au1000/common/setup.c9
-rw-r--r--arch/mips/au1000/common/time.c29
-rw-r--r--arch/mips/au1000/pb1100/init.c2
-rw-r--r--arch/mips/au1000/pb1200/board_setup.c9
-rw-r--r--arch/mips/au1000/pb1500/board_setup.c2
-rw-r--r--arch/mips/cobalt/pci.c1
-rw-r--r--arch/mips/configs/atlas_defconfig4
-rw-r--r--arch/mips/configs/bigsur_defconfig4
-rw-r--r--arch/mips/configs/capcella_defconfig4
-rw-r--r--arch/mips/configs/cobalt_defconfig502
-rw-r--r--arch/mips/configs/db1000_defconfig4
-rw-r--r--arch/mips/configs/db1100_defconfig4
-rw-r--r--arch/mips/configs/db1200_defconfig4
-rw-r--r--arch/mips/configs/db1500_defconfig4
-rw-r--r--arch/mips/configs/db1550_defconfig4
-rw-r--r--arch/mips/configs/ddb5477_defconfig4
-rw-r--r--arch/mips/configs/decstation_defconfig4
-rw-r--r--arch/mips/configs/e55_defconfig4
-rw-r--r--arch/mips/configs/emma2rh_defconfig7
-rw-r--r--arch/mips/configs/ev64120_defconfig985
-rw-r--r--arch/mips/configs/excite_defconfig4
-rw-r--r--arch/mips/configs/fulong_defconfig1765
-rw-r--r--arch/mips/configs/ip22_defconfig4
-rw-r--r--arch/mips/configs/ip27_defconfig4
-rw-r--r--arch/mips/configs/ip32_defconfig4
-rw-r--r--arch/mips/configs/jazz_defconfig6
-rw-r--r--arch/mips/configs/jmr3927_defconfig4
-rw-r--r--arch/mips/configs/lasat200_defconfig1118
-rw-r--r--arch/mips/configs/malta_defconfig4
-rw-r--r--arch/mips/configs/mipssim_defconfig37
-rw-r--r--arch/mips/configs/mpc30x_defconfig4
-rw-r--r--arch/mips/configs/msp71xx_defconfig (renamed from arch/mips/configs/ocelot_3_defconfig)972
-rw-r--r--arch/mips/configs/ocelot_c_defconfig982
-rw-r--r--arch/mips/configs/ocelot_defconfig4
-rw-r--r--arch/mips/configs/pb1100_defconfig4
-rw-r--r--arch/mips/configs/pb1500_defconfig4
-rw-r--r--arch/mips/configs/pb1550_defconfig4
-rw-r--r--arch/mips/configs/pnx8550-jbs_defconfig4
-rw-r--r--arch/mips/configs/pnx8550-stb810_defconfig4
-rw-r--r--arch/mips/configs/qemu_defconfig6
-rw-r--r--arch/mips/configs/rbhma4200_defconfig4
-rw-r--r--arch/mips/configs/rbhma4500_defconfig945
-rw-r--r--arch/mips/configs/rm200_defconfig6
-rw-r--r--arch/mips/configs/sb1250-swarm_defconfig4
-rw-r--r--arch/mips/configs/sead_defconfig4
-rw-r--r--arch/mips/configs/tb0219_defconfig4
-rw-r--r--arch/mips/configs/tb0226_defconfig4
-rw-r--r--arch/mips/configs/tb0287_defconfig4
-rw-r--r--arch/mips/configs/workpad_defconfig4
-rw-r--r--arch/mips/configs/wrppmc_defconfig4
-rw-r--r--arch/mips/configs/yosemite_defconfig6
-rw-r--r--arch/mips/ddb5xxx/ddb5477/Makefile3
-rw-r--r--arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c49
-rw-r--r--arch/mips/dec/prom/console.c32
-rw-r--r--arch/mips/dec/prom/init.c5
-rw-r--r--arch/mips/dec/reset.c10
-rw-r--r--arch/mips/defconfig4
-rw-r--r--arch/mips/emma2rh/markeins/setup.c24
-rw-r--r--arch/mips/gt64120/ev64120/Kconfig3
-rw-r--r--arch/mips/gt64120/ev64120/Makefile9
-rw-r--r--arch/mips/gt64120/ev64120/irq.c116
-rw-r--r--arch/mips/gt64120/ev64120/promcon.c48
-rw-r--r--arch/mips/gt64120/ev64120/reset.c45
-rw-r--r--arch/mips/gt64120/ev64120/serialGT.c212
-rw-r--r--arch/mips/gt64120/ev64120/setup.c99
-rw-r--r--arch/mips/gt64120/momenco_ocelot/Makefile2
-rw-r--r--arch/mips/gt64120/momenco_ocelot/ocelot-platform.c46
-rw-r--r--arch/mips/gt64120/wrppmc/setup.c4
-rw-r--r--arch/mips/jazz/Makefile2
-rw-r--r--arch/mips/jazz/jazz-platform.c60
-rw-r--r--arch/mips/jazz/setup.c2
-rw-r--r--arch/mips/jmr3927/rbhma3100/kgdb_io.c2
-rw-r--r--arch/mips/kernel/8250-platform.c47
-rw-r--r--arch/mips/kernel/Makefile19
-rw-r--r--arch/mips/kernel/branch.c5
-rw-r--r--arch/mips/kernel/cpu-probe.c57
-rw-r--r--arch/mips/kernel/entry.S2
-rw-r--r--arch/mips/kernel/genex.S2
-rw-r--r--arch/mips/kernel/head.S10
-rw-r--r--arch/mips/kernel/irq-mv6434x.c111
-rw-r--r--arch/mips/kernel/linux32.c10
-rw-r--r--arch/mips/kernel/mips-mt-fpaff.c176
-rw-r--r--arch/mips/kernel/mips-mt.c205
-rw-r--r--arch/mips/kernel/pcspeaker.c (renamed from arch/mips/kernel/i8253.c)0
-rw-r--r--arch/mips/kernel/proc.c2
-rw-r--r--arch/mips/kernel/process.c4
-rw-r--r--arch/mips/kernel/r4k_switch.S9
-rw-r--r--arch/mips/kernel/scall32-o32.S6
-rw-r--r--arch/mips/kernel/scall64-64.S4
-rw-r--r--arch/mips/kernel/scall64-n32.S6
-rw-r--r--arch/mips/kernel/scall64-o32.S6
-rw-r--r--arch/mips/kernel/setup.c16
-rw-r--r--arch/mips/kernel/signal32.c62
-rw-r--r--arch/mips/kernel/signal_n32.c6
-rw-r--r--arch/mips/kernel/smp-mt.c16
-rw-r--r--arch/mips/kernel/smp.c15
-rw-r--r--arch/mips/kernel/smtc-asm.S3
-rw-r--r--arch/mips/kernel/smtc.c12
-rw-r--r--arch/mips/kernel/syscall.c5
-rw-r--r--arch/mips/kernel/time.c49
-rw-r--r--arch/mips/kernel/traps.c134
-rw-r--r--arch/mips/kernel/unaligned.c41
-rw-r--r--arch/mips/kernel/vpe.c4
-rw-r--r--arch/mips/lasat/Kconfig15
-rw-r--r--arch/mips/lasat/Makefile14
-rw-r--r--arch/mips/lasat/at93c.c148
-rw-r--r--arch/mips/lasat/at93c.h18
-rw-r--r--arch/mips/lasat/ds1603.c183
-rw-r--r--arch/mips/lasat/ds1603.h33
-rw-r--r--arch/mips/lasat/image/Makefile53
-rw-r--r--arch/mips/lasat/image/head.S31
-rw-r--r--arch/mips/lasat/image/romscript.normal23
-rw-r--r--arch/mips/lasat/interrupt.c130
-rw-r--r--arch/mips/lasat/lasat_board.c279
-rw-r--r--arch/mips/lasat/lasat_models.h63
-rw-r--r--arch/mips/lasat/picvue.c240
-rw-r--r--arch/mips/lasat/picvue.h48
-rw-r--r--arch/mips/lasat/picvue_proc.c186
-rw-r--r--arch/mips/lasat/prom.c117
-rw-r--r--arch/mips/lasat/prom.h5
-rw-r--r--arch/mips/lasat/reset.c69
-rw-r--r--arch/mips/lasat/setup.c182
-rw-r--r--arch/mips/lasat/sysctl.c441
-rw-r--r--arch/mips/lasat/sysctl.h24
-rw-r--r--arch/mips/lemote/lm2e/Makefile7
-rw-r--r--arch/mips/lemote/lm2e/bonito-irq.c74
-rw-r--r--arch/mips/lemote/lm2e/dbg_io.c146
-rw-r--r--arch/mips/lemote/lm2e/irq.c145
-rw-r--r--arch/mips/lemote/lm2e/mem.c23
-rw-r--r--arch/mips/lemote/lm2e/pci.c93
-rw-r--r--arch/mips/lemote/lm2e/prom.c104
-rw-r--r--arch/mips/lemote/lm2e/reset.c41
-rw-r--r--arch/mips/lemote/lm2e/setup.c134
-rw-r--r--arch/mips/lib-32/Makefile23
-rw-r--r--arch/mips/lib-32/dump_tlb.c242
-rw-r--r--arch/mips/lib-32/r3k_dump_tlb.c182
-rw-r--r--arch/mips/lib-32/watch.S60
-rw-r--r--arch/mips/lib-64/Makefile23
-rw-r--r--arch/mips/lib-64/dump_tlb.c216
-rw-r--r--arch/mips/lib-64/watch.S57
-rw-r--r--arch/mips/lib/Makefile21
-rw-r--r--arch/mips/lib/dump_tlb.c101
-rw-r--r--arch/mips/lib/r3k_dump_tlb.c63
-rw-r--r--arch/mips/lib/ucmpdi2.c2
-rw-r--r--arch/mips/lib/uncached.c1
-rw-r--r--arch/mips/math-emu/cp1emu.c53
-rw-r--r--arch/mips/math-emu/dsemul.c12
-rw-r--r--arch/mips/mips-boards/atlas/atlas_int.c13
-rw-r--r--arch/mips/mips-boards/atlas/atlas_setup.c2
-rw-r--r--arch/mips/mips-boards/generic/display.c24
-rw-r--r--arch/mips/mips-boards/generic/init.c62
-rw-r--r--arch/mips/mips-boards/generic/pci.c20
-rw-r--r--arch/mips/mips-boards/generic/time.c142
-rw-r--r--arch/mips/mips-boards/malta/Makefile3
-rw-r--r--arch/mips/mips-boards/malta/malta_int.c56
-rw-r--r--arch/mips/mips-boards/malta/malta_platform.c65
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c10
-rw-r--r--arch/mips/mips-boards/sead/sead_int.c2
-rw-r--r--arch/mips/mips-boards/sead/sead_setup.c4
-rw-r--r--arch/mips/mips-boards/sim/sim_int.c2
-rw-r--r--arch/mips/mipssim/Makefile (renamed from arch/mips/mips-boards/sim/Makefile)0
-rw-r--r--arch/mips/mipssim/sim_cmdline.c (renamed from arch/mips/mips-boards/sim/sim_cmdline.c)0
-rw-r--r--arch/mips/mipssim/sim_console.c (renamed from arch/mips/mips-boards/sim/sim_console.c)2
-rw-r--r--arch/mips/mipssim/sim_int.c88
-rw-r--r--arch/mips/mipssim/sim_mem.c (renamed from arch/mips/mips-boards/sim/sim_mem.c)2
-rw-r--r--arch/mips/mipssim/sim_platform.c (renamed from arch/mips/mips-boards/sim/sim_platform.c)0
-rw-r--r--arch/mips/mipssim/sim_setup.c (renamed from arch/mips/mips-boards/sim/sim_setup.c)10
-rw-r--r--arch/mips/mipssim/sim_smp.c (renamed from arch/mips/mips-boards/sim/sim_smp.c)18
-rw-r--r--arch/mips/mipssim/sim_time.c (renamed from arch/mips/mips-boards/sim/sim_time.c)37
-rw-r--r--arch/mips/mm/Makefile1
-rw-r--r--arch/mips/mm/c-r4k.c54
-rw-r--r--arch/mips/mm/c-sb1.c2
-rw-r--r--arch/mips/mm/cache.c10
-rw-r--r--arch/mips/mm/dma-default.c5
-rw-r--r--arch/mips/mm/tlb-r4k.c23
-rw-r--r--arch/mips/mm/tlbex.c8
-rw-r--r--arch/mips/momentum/ocelot_3/Makefile8
-rw-r--r--arch/mips/momentum/ocelot_3/irq.c109
-rw-r--r--arch/mips/momentum/ocelot_3/platform.c208
-rw-r--r--arch/mips/momentum/ocelot_3/prom.c189
-rw-r--r--arch/mips/momentum/ocelot_3/reset.c59
-rw-r--r--arch/mips/momentum/ocelot_3/setup.c398
-rw-r--r--arch/mips/momentum/ocelot_c/Makefile8
-rw-r--r--arch/mips/momentum/ocelot_c/cpci-irq.c100
-rw-r--r--arch/mips/momentum/ocelot_c/dbg_io.c121
-rw-r--r--arch/mips/momentum/ocelot_c/irq.c107
-rw-r--r--arch/mips/momentum/ocelot_c/platform.c183
-rw-r--r--arch/mips/momentum/ocelot_c/prom.c183
-rw-r--r--arch/mips/momentum/ocelot_c/reset.c58
-rw-r--r--arch/mips/momentum/ocelot_c/setup.c362
-rw-r--r--arch/mips/momentum/ocelot_c/uart-irq.c91
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c7
-rw-r--r--arch/mips/pci/Makefile12
-rw-r--r--arch/mips/pci/fixup-atlas.c2
-rw-r--r--arch/mips/pci/fixup-au1000.c2
-rw-r--r--arch/mips/pci/fixup-capcella.c2
-rw-r--r--arch/mips/pci/fixup-cobalt.c12
-rw-r--r--arch/mips/pci/fixup-emma2rh.c2
-rw-r--r--arch/mips/pci/fixup-excite.c2
-rw-r--r--arch/mips/pci/fixup-ip32.c2
-rw-r--r--arch/mips/pci/fixup-jmr3927.c2
-rw-r--r--arch/mips/pci/fixup-lm2e.c242
-rw-r--r--arch/mips/pci/fixup-malta.c2
-rw-r--r--arch/mips/pci/fixup-mpc30x.c2
-rw-r--r--arch/mips/pci/fixup-ocelot-c.c41
-rw-r--r--arch/mips/pci/fixup-ocelot3.c41
-rw-r--r--arch/mips/pci/fixup-pmcmsp.c216
-rw-r--r--arch/mips/pci/fixup-pnx8550.c2
-rw-r--r--arch/mips/pci/fixup-rbtx4927.c2
-rw-r--r--arch/mips/pci/fixup-sni.c2
-rw-r--r--arch/mips/pci/fixup-tb0219.c2
-rw-r--r--arch/mips/pci/fixup-tb0226.c2
-rw-r--r--arch/mips/pci/fixup-tb0287.c2
-rw-r--r--arch/mips/pci/fixup-tx4938.c2
-rw-r--r--arch/mips/pci/fixup-vr4133.c2
-rw-r--r--arch/mips/pci/fixup-wrppmc.c2
-rw-r--r--arch/mips/pci/fixup-yosemite.c2
-rw-r--r--arch/mips/pci/ops-bonito64.c88
-rw-r--r--arch/mips/pci/ops-marvell.c93
-rw-r--r--arch/mips/pci/ops-nile4.c147
-rw-r--r--arch/mips/pci/ops-pmcmsp.c994
-rw-r--r--arch/mips/pci/ops-tx4938.c80
-rw-r--r--arch/mips/pci/pci-bcm1480.c3
-rw-r--r--arch/mips/pci/pci-dac.c79
-rw-r--r--arch/mips/pci/pci-ddb5477.c2
-rw-r--r--arch/mips/pci/pci-ev64120.c22
-rw-r--r--arch/mips/pci/pci-ip27.c2
-rw-r--r--arch/mips/pci/pci-lasat.c91
-rw-r--r--arch/mips/pci/pci-ocelot-c.c145
-rw-r--r--arch/mips/pci/pci-ocelot.c14
-rw-r--r--arch/mips/pci/pci-sb1250.c2
-rw-r--r--arch/mips/pci/pci.c2
-rw-r--r--arch/mips/philips/pnx8550/common/platform.c2
-rw-r--r--arch/mips/philips/pnx8550/common/proc.c30
-rw-r--r--arch/mips/pmc-sierra/Kconfig46
-rw-r--r--arch/mips/pmc-sierra/msp71xx/Makefile11
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_elb.c (renamed from arch/mips/momentum/ocelot_c/ocelot_c_fpga.h)53
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c179
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_irq.c124
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c134
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c109
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_pci.c (renamed from arch/mips/momentum/ocelot_3/ocelot_3_fpga.h)57
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_prom.c566
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_setup.c256
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_time.c94
-rw-r--r--arch/mips/pmc-sierra/msp71xx/msp_usb.c150
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c2
-rw-r--r--arch/mips/qemu/q-irq.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-reset.c6
-rw-r--r--arch/mips/sgi-ip27/ip27-berr.c1
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c2
-rw-r--r--arch/mips/sgi-ip32/ip32-platform.c52
-rw-r--r--arch/mips/sgi-ip32/ip32-setup.c36
-rw-r--r--arch/mips/sibyte/cfe/setup.c6
-rw-r--r--arch/mips/sibyte/swarm/time.c244
-rw-r--r--arch/mips/sni/Makefile2
-rw-r--r--arch/mips/sni/a20r.c39
-rw-r--r--arch/mips/sni/ds1216.c81
-rw-r--r--arch/mips/sni/pcimt.c44
-rw-r--r--arch/mips/sni/pcit.c26
-rw-r--r--arch/mips/sni/rm200.c36
-rw-r--r--arch/mips/sni/setup.c33
-rw-r--r--arch/mips/sni/sniprom.c5
-rw-r--r--arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c19
-rw-r--r--arch/mips/tx4938/common/Makefile2
-rw-r--r--arch/mips/tx4938/common/rtc_rx5c348.c192
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/Makefile2
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/irq.c6
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/setup.c306
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c261
-rw-r--r--arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c164
-rw-r--r--arch/mips/vr41xx/common/Makefile2
-rw-r--r--arch/mips/vr41xx/common/giu.c122
-rw-r--r--arch/mips/vr41xx/common/rtc.c117
-rw-r--r--arch/mips/vr41xx/common/siu.c120
-rw-r--r--arch/parisc/hpux/fs.c5
-rw-r--r--arch/parisc/kernel/entry.S40
-rw-r--r--arch/parisc/kernel/firmware.c4
-rw-r--r--arch/parisc/kernel/hardware.c14
-rw-r--r--arch/parisc/kernel/hpmc.S5
-rw-r--r--arch/parisc/kernel/irq.c26
-rw-r--r--arch/parisc/kernel/pci-dma.c94
-rw-r--r--arch/parisc/kernel/perf.c18
-rw-r--r--arch/parisc/kernel/process.c4
-rw-r--r--arch/parisc/kernel/processor.c14
-rw-r--r--arch/parisc/kernel/setup.c5
-rw-r--r--arch/parisc/kernel/signal32.h2
-rw-r--r--arch/parisc/kernel/smp.c8
-rw-r--r--arch/parisc/kernel/sys_parisc32.c13
-rw-r--r--arch/parisc/kernel/syscall.S12
-rw-r--r--arch/parisc/kernel/syscall_table.S16
-rw-r--r--arch/parisc/kernel/time.c2
-rw-r--r--arch/parisc/kernel/traps.c9
-rw-r--r--arch/parisc/kernel/unwind.c47
-rw-r--r--arch/parisc/math-emu/dbl_float.h4
-rw-r--r--arch/parisc/math-emu/dfsqrt.c2
-rw-r--r--arch/parisc/math-emu/sfsqrt.c2
-rw-r--r--arch/parisc/math-emu/sgl_float.h4
-rw-r--r--arch/parisc/mm/init.c10
-rw-r--r--arch/powerpc/Kconfig6
-rw-r--r--arch/powerpc/Makefile1
-rw-r--r--arch/powerpc/boot/Makefile22
-rw-r--r--arch/powerpc/boot/crt0.S1
-rwxr-xr-xarch/powerpc/boot/wrapper4
-rw-r--r--arch/powerpc/configs/cell_defconfig243
-rw-r--r--arch/powerpc/configs/celleb_defconfig169
-rw-r--r--arch/powerpc/configs/chrp32_defconfig353
-rw-r--r--arch/powerpc/configs/ebony_defconfig138
-rw-r--r--arch/powerpc/configs/g5_defconfig342
-rw-r--r--arch/powerpc/configs/holly_defconfig125
-rw-r--r--arch/powerpc/configs/iseries_defconfig36
-rw-r--r--arch/powerpc/configs/linkstation_defconfig384
-rw-r--r--arch/powerpc/configs/lite5200_defconfig182
-rw-r--r--arch/powerpc/configs/maple_defconfig248
-rw-r--r--arch/powerpc/configs/mpc7448_hpc2_defconfig212
-rw-r--r--arch/powerpc/configs/mpc8272_ads_defconfig293
-rw-r--r--arch/powerpc/configs/mpc8313_rdb_defconfig310
-rw-r--r--arch/powerpc/configs/mpc832x_mds_defconfig176
-rw-r--r--arch/powerpc/configs/mpc832x_rdb_defconfig229
-rw-r--r--arch/powerpc/configs/mpc834x_itx_defconfig265
-rw-r--r--arch/powerpc/configs/mpc834x_itxgp_defconfig232
-rw-r--r--arch/powerpc/configs/mpc834x_mds_defconfig195
-rw-r--r--arch/powerpc/configs/mpc836x_mds_defconfig176
-rw-r--r--arch/powerpc/configs/mpc8540_ads_defconfig201
-rw-r--r--arch/powerpc/configs/mpc8544_ds_defconfig193
-rw-r--r--arch/powerpc/configs/mpc8560_ads_defconfig201
-rw-r--r--arch/powerpc/configs/mpc8568mds_defconfig191
-rw-r--r--arch/powerpc/configs/mpc85xx_cds_defconfig206
-rw-r--r--arch/powerpc/configs/mpc8641_hpcn_defconfig200
-rw-r--r--arch/powerpc/configs/mpc866_ads_defconfig213
-rw-r--r--arch/powerpc/configs/mpc885_ads_defconfig222
-rw-r--r--arch/powerpc/configs/pasemi_defconfig58
-rw-r--r--arch/powerpc/configs/pmac32_defconfig375
-rw-r--r--arch/powerpc/configs/ppc64_defconfig460
-rw-r--r--arch/powerpc/configs/prpmc2800_defconfig98
-rw-r--r--arch/powerpc/configs/ps3_defconfig79
-rw-r--r--arch/powerpc/configs/pseries_defconfig387
-rw-r--r--arch/powerpc/kernel/irq.c12
-rw-r--r--arch/powerpc/kernel/of_platform.c2
-rw-r--r--arch/powerpc/kernel/pci_32.c4
-rw-r--r--arch/powerpc/kernel/pci_64.c6
-rw-r--r--arch/powerpc/kernel/prom.c11
-rw-r--r--arch/powerpc/kernel/ptrace.c2
-rw-r--r--arch/powerpc/kernel/signal_64.c10
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c9
-rw-r--r--arch/powerpc/kernel/udbg.c8
-rw-r--r--arch/powerpc/kernel/vdso32/gettimeofday.S4
-rw-r--r--arch/powerpc/kernel/vdso64/gettimeofday.S7
-rw-r--r--arch/powerpc/lib/rheap.c48
-rw-r--r--arch/powerpc/mm/fault.c5
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c48
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c4
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c57
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c62
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c161
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h2
-rw-r--r--arch/powerpc/platforms/celleb/Makefile2
-rw-r--r--arch/powerpc/platforms/pasemi/idle.c1
-rw-r--r--arch/powerpc/platforms/pasemi/iommu.c8
-rw-r--r--arch/powerpc/platforms/powermac/setup.c16
-rw-r--r--arch/powerpc/platforms/powermac/smp.c1
-rw-r--r--arch/powerpc/platforms/ps3/interrupt.c1
-rw-r--r--arch/powerpc/platforms/pseries/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/xics.c10
-rw-r--r--arch/ppc/8260_io/enet.c4
-rw-r--r--arch/ppc/8260_io/fcc_enet.c4
-rw-r--r--arch/ppc/8xx_io/enet.c4
-rw-r--r--arch/ppc/8xx_io/fec.c2
-rw-r--r--arch/ppc/Kconfig6
-rw-r--r--arch/ppc/kernel/pci.c6
-rw-r--r--arch/ppc/syslib/ibm_ocp.c1
-rw-r--r--arch/ppc/syslib/mv64x60.c1
-rw-r--r--arch/ppc/syslib/qspan_pci.c4
-rw-r--r--arch/s390/Makefile2
-rw-r--r--arch/s390/appldata/appldata_base.c5
-rw-r--r--arch/s390/crypto/crypt_s390.h2
-rw-r--r--arch/s390/hypfs/hypfs_diag.c17
-rw-r--r--arch/s390/kernel/debug.c22
-rw-r--r--arch/s390/kernel/early.c45
-rw-r--r--arch/s390/kernel/entry.S15
-rw-r--r--arch/s390/kernel/entry64.S15
-rw-r--r--arch/s390/kernel/ipl.c29
-rw-r--r--arch/s390/kernel/process.c6
-rw-r--r--arch/s390/kernel/setup.c5
-rw-r--r--arch/s390/kernel/smp.c69
-rw-r--r--arch/s390/kernel/time.c4
-rw-r--r--arch/s390/kernel/traps.c9
-rw-r--r--arch/s390/kernel/vtime.c4
-rw-r--r--arch/s390/lib/Makefile4
-rw-r--r--arch/sh/Makefile2
-rw-r--r--arch/sh/boards/se/73180/setup.c4
-rw-r--r--arch/sh/boards/superh/microdev/irq.c1
-rw-r--r--arch/sh/cchips/voyagergx/irq.c13
-rw-r--r--arch/sh/drivers/dma/dma-api.c1
-rw-r--r--arch/sh/kernel/cf-enabler.c6
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S3
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4-202.c2
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c1
-rw-r--r--arch/sh/kernel/signal.c9
-rw-r--r--arch/sh/kernel/smp.c2
-rw-r--r--arch/sh/kernel/timers/timer.c5
-rw-r--r--arch/sh/kernel/traps.c3
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall.c1
-rw-r--r--arch/sh/mm/ioremap.c1
-rw-r--r--arch/sh64/kernel/pci_sh5.c8
-rw-r--r--arch/sh64/kernel/signal.c1
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc/kernel/smp.c10
-rw-r--r--arch/sparc/lib/atomic32.c4
-rw-r--r--arch/sparc64/Kconfig15
-rw-r--r--arch/sparc64/kernel/Makefile4
-rw-r--r--arch/sparc64/kernel/entry.S99
-rw-r--r--arch/sparc64/kernel/irq.c141
-rw-r--r--arch/sparc64/kernel/mdesc.c53
-rw-r--r--arch/sparc64/kernel/of_device.c19
-rw-r--r--arch/sparc64/kernel/pci.c98
-rw-r--r--arch/sparc64/kernel/pci_common.c12
-rw-r--r--arch/sparc64/kernel/pci_sabre.c17
-rw-r--r--arch/sparc64/kernel/prom.c59
-rw-r--r--arch/sparc64/kernel/sbus.c54
-rw-r--r--arch/sparc64/kernel/setup.c19
-rw-r--r--arch/sparc64/kernel/smp.c48
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c2
-rw-r--r--arch/sparc64/kernel/sysfs.c297
-rw-r--r--arch/sparc64/kernel/vmlinux.lds.S11
-rw-r--r--arch/um/Kconfig1
-rw-r--r--arch/um/drivers/line.c1
-rw-r--r--arch/um/drivers/stderr_console.c1
-rw-r--r--arch/um/drivers/ubd_kern.c1
-rw-r--r--arch/um/include/common-offsets.h1
-rw-r--r--arch/um/kernel/exitcode.c39
-rw-r--r--arch/um/os-Linux/main.c4
-rw-r--r--arch/um/os-Linux/skas/mem.c13
-rw-r--r--arch/um/os-Linux/skas/process.c13
-rw-r--r--arch/um/os-Linux/start_up.c7
-rw-r--r--arch/x86_64/Kconfig4
-rw-r--r--arch/x86_64/boot/Makefile136
-rw-r--r--arch/x86_64/boot/bootsect.S98
-rw-r--r--arch/x86_64/boot/compressed/Makefile9
-rw-r--r--arch/x86_64/boot/compressed/head.S6
-rw-r--r--arch/x86_64/boot/install.sh2
-rw-r--r--arch/x86_64/boot/mtools.conf.in17
-rw-r--r--arch/x86_64/boot/setup.S826
-rw-r--r--arch/x86_64/boot/tools/build.c185
-rw-r--r--arch/x86_64/ia32/ia32entry.S6
-rw-r--r--arch/x86_64/ia32/sys_ia32.c19
-rw-r--r--arch/x86_64/kernel/Makefile2
-rw-r--r--arch/x86_64/kernel/cpufreq/Kconfig6
-rw-r--r--arch/x86_64/kernel/entry.S7
-rw-r--r--arch/x86_64/kernel/io_apic.c1
-rw-r--r--arch/x86_64/kernel/irq.c32
-rw-r--r--arch/x86_64/kernel/mce.c6
-rw-r--r--arch/x86_64/kernel/pci-dma.c15
-rw-r--r--arch/x86_64/kernel/setup.c21
-rw-r--r--arch/x86_64/kernel/setup64.c3
-rw-r--r--arch/x86_64/kernel/traps.c3
-rw-r--r--arch/x86_64/kernel/verify_cpu.S22
-rw-r--r--arch/x86_64/mm/fault.c6
-rw-r--r--arch/x86_64/mm/init.c13
-rw-r--r--arch/x86_64/mm/pageattr.c7
-rw-r--r--arch/xtensa/kernel/asm-offsets.c1
-rw-r--r--arch/xtensa/kernel/entry.S36
-rw-r--r--arch/xtensa/kernel/head.S19
-rw-r--r--arch/xtensa/kernel/pci.c2
-rw-r--r--arch/xtensa/kernel/setup.c1
-rw-r--r--arch/xtensa/kernel/signal.c795
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S78
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c11
-rw-r--r--arch/xtensa/lib/strncpy_user.S33
-rw-r--r--arch/xtensa/lib/strnlen_user.S33
-rw-r--r--arch/xtensa/mm/init.c2
-rw-r--r--arch/xtensa/platform-iss/network.c2
-rw-r--r--block/Kconfig4
-rw-r--r--block/cfq-iosched.c39
-rw-r--r--block/elevator.c13
-rw-r--r--block/ll_rw_blk.c22
-rw-r--r--crypto/Kconfig16
-rw-r--r--crypto/Makefile6
-rw-r--r--crypto/ablkcipher.c31
-rw-r--r--crypto/algapi.c4
-rw-r--r--crypto/api.c2
-rw-r--r--crypto/async_tx/Kconfig16
-rw-r--r--crypto/async_tx/Makefile4
-rw-r--r--crypto/async_tx/async_memcpy.c131
-rw-r--r--crypto/async_tx/async_memset.c109
-rw-r--r--crypto/async_tx/async_tx.c497
-rw-r--r--crypto/async_tx/async_xor.c327
-rw-r--r--crypto/blkcipher.c25
-rw-r--r--crypto/cipher.c33
-rw-r--r--crypto/cryptd.c4
-rw-r--r--crypto/hash.c38
-rw-r--r--crypto/xor.c (renamed from drivers/md/xor.c)55
-rw-r--r--drivers/Kconfig4
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acorn/block/fd1772.c2
-rw-r--r--drivers/acorn/block/mfmhd.c13
-rw-r--r--drivers/acpi/asus_acpi.c5
-rw-r--r--drivers/acpi/numa.c2
-rw-r--r--drivers/acpi/osl.c118
-rw-r--r--drivers/acpi/processor_core.c7
-rw-r--r--drivers/acpi/processor_idle.c10
-rw-r--r--drivers/acpi/tables/tbinstal.c8
-rw-r--r--drivers/acpi/thermal.c20
-rw-r--r--drivers/acpi/toshiba_acpi.c4
-rw-r--r--drivers/acpi/utilities/utcopy.c120
-rw-r--r--drivers/acpi/utilities/uteval.c28
-rw-r--r--drivers/acpi/utilities/utobject.c42
-rw-r--r--drivers/acpi/utilities/utxface.c4
-rw-r--r--drivers/ata/Kconfig15
-rw-r--r--drivers/ata/ahci.c185
-rw-r--r--drivers/ata/ata_generic.c6
-rw-r--r--drivers/ata/ata_piix.c43
-rw-r--r--drivers/ata/libata-acpi.c914
-rw-r--r--drivers/ata/libata-core.c316
-rw-r--r--drivers/ata/libata-eh.c114
-rw-r--r--drivers/ata/libata-scsi.c87
-rw-r--r--drivers/ata/libata-sff.c330
-rw-r--r--drivers/ata/libata.h18
-rw-r--r--drivers/ata/pata_ali.c60
-rw-r--r--drivers/ata/pata_amd.c44
-rw-r--r--drivers/ata/pata_artop.c6
-rw-r--r--drivers/ata/pata_atiixp.c3
-rw-r--r--drivers/ata/pata_cmd640.c2
-rw-r--r--drivers/ata/pata_cmd64x.c12
-rw-r--r--drivers/ata/pata_cs5520.c9
-rw-r--r--drivers/ata/pata_cs5530.c10
-rw-r--r--drivers/ata/pata_cs5535.c4
-rw-r--r--drivers/ata/pata_cypress.c2
-rw-r--r--drivers/ata/pata_efar.c2
-rw-r--r--drivers/ata/pata_hpt366.c4
-rw-r--r--drivers/ata/pata_hpt37x.c22
-rw-r--r--drivers/ata/pata_hpt3x2n.c4
-rw-r--r--drivers/ata/pata_hpt3x3.c95
-rw-r--r--drivers/ata/pata_icside.c2
-rw-r--r--drivers/ata/pata_isapnp.c1
-rw-r--r--drivers/ata/pata_it8213.c4
-rw-r--r--drivers/ata/pata_it821x.c24
-rw-r--r--drivers/ata/pata_ixp4xx_cf.c76
-rw-r--r--drivers/ata/pata_jmicron.c4
-rw-r--r--drivers/ata/pata_marvell.c8
-rw-r--r--drivers/ata/pata_mpc52xx.c18
-rw-r--r--drivers/ata/pata_netcell.c4
-rw-r--r--drivers/ata/pata_ns87410.c2
-rw-r--r--drivers/ata/pata_oldpiix.c2
-rw-r--r--drivers/ata/pata_opti.c2
-rw-r--r--drivers/ata/pata_optidma.c4
-rw-r--r--drivers/ata/pata_pcmcia.c2
-rw-r--r--drivers/ata/pata_pdc2027x.c11
-rw-r--r--drivers/ata/pata_pdc202xx_old.c10
-rw-r--r--drivers/ata/pata_platform.c6
-rw-r--r--drivers/ata/pata_radisys.c2
-rw-r--r--drivers/ata/pata_rz1000.c2
-rw-r--r--drivers/ata/pata_sc1200.c6
-rw-r--r--drivers/ata/pata_scc.c54
-rw-r--r--drivers/ata/pata_serverworks.c17
-rw-r--r--drivers/ata/pata_sil680.c21
-rw-r--r--drivers/ata/pata_sis.c71
-rw-r--r--drivers/ata/pata_sl82c105.c9
-rw-r--r--drivers/ata/pata_triflex.c2
-rw-r--r--drivers/ata/pata_via.c26
-rw-r--r--drivers/ata/pdc_adma.c20
-rw-r--r--drivers/ata/sata_inic162x.c13
-rw-r--r--drivers/ata/sata_mv.c941
-rw-r--r--drivers/ata/sata_nv.c3
-rw-r--r--drivers/ata/sata_promise.c126
-rw-r--r--drivers/ata/sata_qstor.c2
-rw-r--r--drivers/ata/sata_sil.c13
-rw-r--r--drivers/ata/sata_sil24.c8
-rw-r--r--drivers/ata/sata_sis.c43
-rw-r--r--drivers/ata/sata_svw.c15
-rw-r--r--drivers/ata/sata_sx4.c168
-rw-r--r--drivers/ata/sata_uli.c4
-rw-r--r--drivers/ata/sata_via.c12
-rw-r--r--drivers/ata/sata_vsc.c2
-rw-r--r--drivers/ata/sis.h2
-rw-r--r--drivers/atm/Kconfig2
-rw-r--r--drivers/atm/eni.c9
-rw-r--r--drivers/atm/firestream.c17
-rw-r--r--drivers/atm/idt77252.c13
-rw-r--r--drivers/atm/iphase.c11
-rw-r--r--drivers/atm/lanai.c27
-rw-r--r--drivers/atm/zatm.c6
-rw-r--r--drivers/auxdisplay/Kconfig4
-rw-r--r--drivers/auxdisplay/cfag12864bfb.c8
-rw-r--r--drivers/base/attribute_container.c1
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/bus.c24
-rw-r--r--drivers/base/class.c105
-rw-r--r--drivers/base/core.c68
-rw-r--r--drivers/base/dd.c34
-rw-r--r--drivers/base/devres.c2
-rw-r--r--drivers/base/firmware_class.c10
-rw-r--r--drivers/base/power/main.c44
-rw-r--r--drivers/base/power/power.h4
-rw-r--r--drivers/base/power/resume.c23
-rw-r--r--drivers/base/power/runtime.c12
-rw-r--r--drivers/base/power/suspend.c72
-rw-r--r--drivers/base/sys.c24
-rw-r--r--drivers/block/Kconfig44
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/acsi.c1825
-rw-r--r--drivers/block/amiflop.c2
-rw-r--r--drivers/block/cciss.c2
-rw-r--r--drivers/block/loop.c164
-rw-r--r--drivers/block/nbd.c2
-rw-r--r--drivers/block/pktcdvd.c3
-rw-r--r--drivers/block/ub.c12
-rw-r--r--drivers/bluetooth/hci_usb.c88
-rw-r--r--drivers/bluetooth/hci_usb.h5
-rw-r--r--drivers/bluetooth/hci_vhci.c6
-rw-r--r--drivers/cdrom/Kconfig213
-rw-r--r--drivers/cdrom/Makefile10
-rw-r--r--drivers/cdrom/aztcd.c2492
-rw-r--r--drivers/cdrom/aztcd.h162
-rw-r--r--drivers/cdrom/cdrom.c216
-rw-r--r--drivers/cdrom/cdu31a.c3251
-rw-r--r--drivers/cdrom/cdu31a.h411
-rw-r--r--drivers/cdrom/cm206.c1594
-rw-r--r--drivers/cdrom/cm206.h171
-rw-r--r--drivers/cdrom/gscd.c1029
-rw-r--r--drivers/cdrom/gscd.h108
-rw-r--r--drivers/cdrom/isp16.c374
-rw-r--r--drivers/cdrom/isp16.h72
-rw-r--r--drivers/cdrom/mcdx.c1943
-rw-r--r--drivers/cdrom/mcdx.h185
-rw-r--r--drivers/cdrom/optcd.c2105
-rw-r--r--drivers/cdrom/optcd.h52
-rw-r--r--drivers/cdrom/sbpcd.c5966
-rw-r--r--drivers/cdrom/sbpcd.h839
-rw-r--r--drivers/cdrom/sjcd.c1815
-rw-r--r--drivers/cdrom/sjcd.h181
-rw-r--r--drivers/cdrom/sonycd535.c1689
-rw-r--r--drivers/cdrom/sonycd535.h183
-rw-r--r--drivers/char/Kconfig16
-rw-r--r--drivers/char/agp/agp.h6
-rw-r--r--drivers/char/agp/amd-k7-agp.c4
-rw-r--r--drivers/char/agp/amd64-agp.c6
-rw-r--r--drivers/char/agp/backend.c2
-rw-r--r--drivers/char/agp/intel-agp.c582
-rw-r--r--drivers/char/drm/drm_drawable.c41
-rw-r--r--drivers/char/drm/drm_pciids.h14
-rw-r--r--drivers/char/drm/i915_dma.c90
-rw-r--r--drivers/char/drm/i915_drm.h5
-rw-r--r--drivers/char/drm/i915_drv.h2
-rw-r--r--drivers/char/drm/i915_irq.c2
-rw-r--r--drivers/char/drm/radeon_ioc32.c31
-rw-r--r--drivers/char/drm/sis_drv.h8
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c10
-rw-r--r--drivers/char/keyboard.c4
-rw-r--r--drivers/char/mem.c9
-rw-r--r--drivers/char/n_tty.c1
-rw-r--r--drivers/char/random.c2
-rw-r--r--drivers/char/stallion.c88
-rw-r--r--drivers/char/sx.c4
-rw-r--r--drivers/char/tty_io.c17
-rw-r--r--drivers/char/vr41xx_giu.c132
-rw-r--r--drivers/char/vt.c18
-rw-r--r--drivers/char/watchdog/Kconfig7
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c2
-rw-r--r--drivers/char/watchdog/ks8695_wdt.c308
-rw-r--r--drivers/clocksource/acpi_pm.c5
-rw-r--r--drivers/cpufreq/cpufreq.c47
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c30
-rw-r--r--drivers/cpufreq/cpufreq_stats.c3
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c25
-rw-r--r--drivers/cpufreq/freq_table.c1
-rw-r--r--drivers/dma/Kconfig12
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/dmaengine.c419
-rw-r--r--drivers/dma/ioatdma.c377
-rw-r--r--drivers/dma/ioatdma.h16
-rw-r--r--drivers/dma/ioatdma_io.h118
-rw-r--r--drivers/dma/iop-adma.c1467
-rw-r--r--drivers/firewire/Kconfig65
-rw-r--r--drivers/firewire/fw-card.c12
-rw-r--r--drivers/firewire/fw-cdev.c38
-rw-r--r--drivers/firewire/fw-device.c38
-rw-r--r--drivers/firewire/fw-device.h2
-rw-r--r--drivers/firewire/fw-ohci.c193
-rw-r--r--drivers/firewire/fw-sbp2.c170
-rw-r--r--drivers/firewire/fw-topology.c66
-rw-r--r--drivers/firewire/fw-topology.h25
-rw-r--r--drivers/firewire/fw-transaction.h3
-rw-r--r--drivers/firmware/Kconfig9
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/dcdbas.c10
-rw-r--r--drivers/firmware/dcdbas.h3
-rw-r--r--drivers/firmware/dell_rbu.c31
-rw-r--r--drivers/firmware/dmi-id.c222
-rw-r--r--drivers/firmware/dmi_scan.c73
-rw-r--r--drivers/firmware/edd.c2
-rw-r--r--drivers/firmware/efivars.c6
-rw-r--r--drivers/hid/Kconfig10
-rw-r--r--drivers/hid/hid-core.c93
-rw-r--r--drivers/hid/hid-debug.c15
-rw-r--r--drivers/hid/hid-input.c125
-rw-r--r--drivers/hid/usbhid/hid-core.c120
-rw-r--r--drivers/hid/usbhid/hid-lgff.c10
-rw-r--r--drivers/hid/usbhid/hid-pidff.c1
-rw-r--r--drivers/hid/usbhid/hid-quirks.c185
-rw-r--r--drivers/hid/usbhid/hid-tmff.c2
-rw-r--r--drivers/hid/usbhid/hid-zpff.c8
-rw-r--r--drivers/hid/usbhid/hiddev.c2
-rw-r--r--drivers/hid/usbhid/usbkbd.c6
-rw-r--r--drivers/hwmon/coretemp.c1
-rw-r--r--drivers/i2c/algos/Kconfig4
-rw-r--r--drivers/i2c/busses/Kconfig33
-rw-r--r--drivers/i2c/busses/Makefile3
-rw-r--r--drivers/i2c/busses/i2c-acorn.c2
-rw-r--r--drivers/i2c/busses/i2c-gpio.c12
-rw-r--r--drivers/i2c/busses/i2c-i801.c249
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c3
-rw-r--r--drivers/i2c/busses/i2c-mpc.c26
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c3
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c44
-rw-r--r--drivers/i2c/busses/i2c-piix4.c4
-rw-r--r--drivers/i2c/busses/i2c-pmcmsp.c653
-rw-r--r--drivers/i2c/busses/i2c-powermac.c3
-rw-r--r--drivers/i2c/busses/i2c-pxa.c9
-rw-r--r--drivers/i2c/busses/i2c-rpx.c101
-rw-r--r--drivers/i2c/busses/i2c-savage4.c21
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c27
-rw-r--r--drivers/i2c/busses/i2c-taos-evm.c330
-rw-r--r--drivers/i2c/busses/i2c-viapro.c5
-rw-r--r--drivers/i2c/busses/scx200_acb.c16
-rw-r--r--drivers/i2c/chips/Kconfig35
-rw-r--r--drivers/i2c/chips/Makefile2
-rw-r--r--drivers/i2c/chips/ds1682.c259
-rw-r--r--drivers/i2c/chips/eeprom.c10
-rw-r--r--drivers/i2c/chips/max6875.c7
-rw-r--r--drivers/i2c/chips/tsl2550.c460
-rw-r--r--drivers/i2c/i2c-core.c25
-rw-r--r--drivers/i2c/i2c-dev.c9
-rw-r--r--drivers/ide/arm/icside.c18
-rw-r--r--drivers/ide/cris/ide-cris.c2
-rw-r--r--drivers/ide/ide-cd.c6
-rw-r--r--drivers/ide/ide-cd.h2
-rw-r--r--drivers/ide/ide-disk.c20
-rw-r--r--drivers/ide/ide-dma.c110
-rw-r--r--drivers/ide/ide-io.c4
-rw-r--r--drivers/ide/ide-iops.c8
-rw-r--r--drivers/ide/ide-probe.c26
-rw-r--r--drivers/ide/ide-proc.c34
-rw-r--r--drivers/ide/ide-taskfile.c12
-rw-r--r--drivers/ide/ide-timing.h56
-rw-r--r--drivers/ide/ide.c45
-rw-r--r--drivers/ide/legacy/hd.c78
-rw-r--r--drivers/ide/legacy/macide.c14
-rw-r--r--drivers/ide/legacy/qd65xx.c3
-rw-r--r--drivers/ide/mips/au1xxx-ide.c24
-rw-r--r--drivers/ide/pci/aec62xx.c119
-rw-r--r--drivers/ide/pci/alim15x3.c80
-rw-r--r--drivers/ide/pci/amd74xx.c145
-rw-r--r--drivers/ide/pci/atiixp.c5
-rw-r--r--drivers/ide/pci/cmd64x.c139
-rw-r--r--drivers/ide/pci/cs5530.c2
-rw-r--r--drivers/ide/pci/cs5535.c6
-rw-r--r--drivers/ide/pci/generic.c37
-rw-r--r--drivers/ide/pci/hpt366.c201
-rw-r--r--drivers/ide/pci/it8213.c8
-rw-r--r--drivers/ide/pci/it821x.c44
-rw-r--r--drivers/ide/pci/jmicron.c20
-rw-r--r--drivers/ide/pci/pdc202xx_new.c19
-rw-r--r--drivers/ide/pci/pdc202xx_old.c35
-rw-r--r--drivers/ide/pci/piix.c51
-rw-r--r--drivers/ide/pci/scc_pata.c2
-rw-r--r--drivers/ide/pci/serverworks.c103
-rw-r--r--drivers/ide/pci/sgiioc4.c20
-rw-r--r--drivers/ide/pci/siimage.c18
-rw-r--r--drivers/ide/pci/sis5513.c43
-rw-r--r--drivers/ide/pci/sl82c105.c24
-rw-r--r--drivers/ide/pci/slc90e66.c5
-rw-r--r--drivers/ide/pci/tc86c001.c4
-rw-r--r--drivers/ide/pci/via82cxxx.c184
-rw-r--r--drivers/ide/ppc/pmac.c42
-rw-r--r--drivers/ide/setup-pci.c10
-rw-r--r--drivers/ieee1394/dv1394.c8
-rw-r--r--drivers/ieee1394/eth1394.c25
-rw-r--r--drivers/ieee1394/highlevel.c45
-rw-r--r--drivers/ieee1394/highlevel.h16
-rw-r--r--drivers/ieee1394/hosts.c11
-rw-r--r--drivers/ieee1394/hosts.h10
-rw-r--r--drivers/ieee1394/ieee1394_core.c8
-rw-r--r--drivers/ieee1394/ieee1394_core.h15
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c30
-rw-r--r--drivers/ieee1394/ieee1394_transactions.h2
-rw-r--r--drivers/ieee1394/nodemgr.c194
-rw-r--r--drivers/ieee1394/nodemgr.h5
-rw-r--r--drivers/ieee1394/ohci1394.c272
-rw-r--r--drivers/ieee1394/ohci1394.h14
-rw-r--r--drivers/ieee1394/pcilynx.c16
-rw-r--r--drivers/ieee1394/raw1394-private.h5
-rw-r--r--drivers/ieee1394/raw1394.c364
-rw-r--r--drivers/ieee1394/raw1394.h4
-rw-r--r--drivers/ieee1394/sbp2.c46
-rw-r--r--drivers/ieee1394/sbp2.h2
-rw-r--r--drivers/ieee1394/video1394.c10
-rw-r--r--drivers/infiniband/Kconfig15
-rw-r--r--drivers/infiniband/core/agent.c19
-rw-r--r--drivers/infiniband/core/cm.c247
-rw-r--r--drivers/infiniband/core/cm_msgs.h1
-rw-r--r--drivers/infiniband/core/cma.c5
-rw-r--r--drivers/infiniband/core/mad.c50
-rw-r--r--drivers/infiniband/core/multicast.c2
-rw-r--r--drivers/infiniband/core/sa.h2
-rw-r--r--drivers/infiniband/core/sa_query.c87
-rw-r--r--drivers/infiniband/core/smi.c16
-rw-r--r--drivers/infiniband/core/smi.h2
-rw-r--r--drivers/infiniband/core/sysfs.c3
-rw-r--r--drivers/infiniband/core/ucm.c1
-rw-r--r--drivers/infiniband/core/umem.c17
-rw-r--r--drivers/infiniband/hw/amso1100/Kconfig2
-rw-r--r--drivers/infiniband/hw/amso1100/c2.c2
-rw-r--r--drivers/infiniband/hw/cxgb3/Kconfig2
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_hal.c6
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_wr.h3
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c108
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.h1
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c7
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_qp.c7
-rw-r--r--drivers/infiniband/hw/ehca/Kconfig2
-rw-r--r--drivers/infiniband/hw/ehca/ehca_av.c6
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes.h75
-rw-r--r--drivers/infiniband/hw/ehca/ehca_classes_pSeries.h4
-rw-r--r--drivers/infiniband/hw/ehca/ehca_cq.c50
-rw-r--r--drivers/infiniband/hw/ehca/ehca_hca.c61
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.c140
-rw-r--r--drivers/infiniband/hw/ehca/ehca_irq.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_iverbs.h18
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c98
-rw-r--r--drivers/infiniband/hw/ehca/ehca_qp.c751
-rw-r--r--drivers/infiniband/hw/ehca/ehca_reqs.c85
-rw-r--r--drivers/infiniband/hw/ehca/ehca_tools.h1
-rw-r--r--drivers/infiniband/hw/ehca/ehca_uverbs.c13
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.c58
-rw-r--r--drivers/infiniband/hw/ehca/hcp_if.h1
-rw-r--r--drivers/infiniband/hw/ehca/hipz_hw.h19
-rw-r--r--drivers/infiniband/hw/ehca/ipz_pt_fn.h28
-rw-r--r--drivers/infiniband/hw/ipath/Kconfig2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_common.h33
-rw-r--r--drivers/infiniband/hw/ipath/ipath_cq.c7
-rw-r--r--drivers/infiniband/hw/ipath/ipath_debug.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_diag.c41
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c196
-rw-r--r--drivers/infiniband/hw/ipath/ipath_eeprom.c303
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c205
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c9
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6110.c101
-rw-r--r--drivers/infiniband/hw/ipath/ipath_iba6120.c92
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c26
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c141
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h85
-rw-r--r--drivers/infiniband/hw/ipath/ipath_keys.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_layer.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_layer.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mad.c11
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mmap.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_mr.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_qp.c19
-rw-r--r--drivers/infiniband/hw/ipath/ipath_rc.c116
-rw-r--r--drivers/infiniband/hw/ipath/ipath_registers.h2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ruc.c36
-rw-r--r--drivers/infiniband/hw/ipath/ipath_srq.c4
-rw-r--r--drivers/infiniband/hw/ipath/ipath_stats.c25
-rw-r--r--drivers/infiniband/hw/ipath/ipath_sysfs.c43
-rw-r--r--drivers/infiniband/hw/ipath/ipath_uc.c9
-rw-r--r--drivers/infiniband/hw/ipath/ipath_ud.c6
-rw-r--r--drivers/infiniband/hw/ipath/ipath_user_pages.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.c29
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs.h3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_verbs_mcast.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_wc_ppc64.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_wc_x86_64.c29
-rw-r--r--drivers/infiniband/hw/mlx4/Kconfig1
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c19
-rw-r--r--drivers/infiniband/hw/mlx4/main.c24
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h9
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c360
-rw-r--r--drivers/infiniband/hw/mlx4/srq.c18
-rw-r--r--drivers/infiniband/hw/mlx4/user.h9
-rw-r--r--drivers/infiniband/hw/mthca/Kconfig2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_allocator.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/Kconfig2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c50
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c33
-rw-r--r--drivers/infiniband/ulp/iser/Kconfig2
-rw-r--r--drivers/infiniband/ulp/srp/Kconfig2
-rw-r--r--drivers/input/Kconfig13
-rw-r--r--drivers/input/Makefile1
-rw-r--r--drivers/input/evdev.c86
-rw-r--r--drivers/input/input-polldev.c (renamed from drivers/input/misc/input-polldev.c)0
-rw-r--r--drivers/input/input.c136
-rw-r--r--drivers/input/joydev.c86
-rw-r--r--drivers/input/joystick/Kconfig7
-rw-r--r--drivers/input/joystick/db9.c2
-rw-r--r--drivers/input/joystick/grip_mp.c4
-rw-r--r--drivers/input/joystick/xpad.c281
-rw-r--r--drivers/input/keyboard/Kconfig3
-rw-r--r--drivers/input/keyboard/atkbd.c51
-rw-r--r--drivers/input/keyboard/pxa27x_keyboard.c8
-rw-r--r--drivers/input/misc/Kconfig17
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/wistron_btns.c359
-rw-r--r--drivers/input/mouse/Kconfig18
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/gpio_mouse.c196
-rw-r--r--drivers/input/mouse/psmouse-base.c29
-rw-r--r--drivers/input/mouse/psmouse.h2
-rw-r--r--drivers/input/mousedev.c242
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h29
-rw-r--r--drivers/input/serio/serio.c2
-rw-r--r--drivers/input/serio/serio_raw.c2
-rw-r--r--drivers/input/tablet/aiptek.c991
-rw-r--r--drivers/input/tablet/wacom.h8
-rw-r--r--drivers/input/tablet/wacom_sys.c6
-rw-r--r--drivers/input/tablet/wacom_wac.c47
-rw-r--r--drivers/input/tablet/wacom_wac.h1
-rw-r--r--drivers/input/touchscreen/Kconfig6
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c77
-rw-r--r--drivers/input/tsdev.c92
-rw-r--r--drivers/isdn/Kconfig9
-rw-r--r--drivers/isdn/hardware/eicon/diva_didd.c2
-rw-r--r--drivers/isdn/hardware/eicon/divasfunc.c4
-rw-r--r--drivers/isdn/hisax/bkm_a8.c4
-rw-r--r--drivers/isdn/i4l/isdn_tty.c3
-rw-r--r--drivers/kvm/kvm.h3
-rw-r--r--drivers/kvm/kvm_main.c22
-rw-r--r--drivers/kvm/vmx.c14
-rw-r--r--drivers/macintosh/Kconfig4
-rw-r--r--drivers/macintosh/windfarm_core.c2
-rw-r--r--drivers/macintosh/windfarm_smu_sat.c28
-rw-r--r--drivers/md/Kconfig8
-rw-r--r--drivers/md/Makefile6
-rw-r--r--drivers/md/dm-bio-list.h4
-rw-r--r--drivers/md/dm-crypt.c33
-rw-r--r--drivers/md/dm-delay.c23
-rw-r--r--drivers/md/dm-exception-store.c76
-rw-r--r--drivers/md/dm-io.c5
-rw-r--r--drivers/md/dm-mpath-rdac.c700
-rw-r--r--drivers/md/dm-mpath.c34
-rw-r--r--drivers/md/dm-raid1.c75
-rw-r--r--drivers/md/dm-round-robin.c2
-rw-r--r--drivers/md/dm-snap.c116
-rw-r--r--drivers/md/dm-snap.h6
-rw-r--r--drivers/md/dm.c33
-rw-r--r--drivers/md/dm.h40
-rw-r--r--drivers/md/kcopyd.c11
-rw-r--r--drivers/md/md.c2
-rw-r--r--drivers/md/raid1.c21
-rw-r--r--drivers/md/raid10.c6
-rw-r--r--drivers/md/raid5.c2727
-rw-r--r--drivers/media/common/Kconfig1
-rw-r--r--drivers/media/dvb/Kconfig2
-rw-r--r--drivers/media/dvb/b2c2/Makefile7
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c67
-rw-r--r--drivers/media/dvb/frontends/tda10086.c21
-rw-r--r--drivers/media/dvb/frontends/tda826x.c4
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c2
-rw-r--r--drivers/media/radio/Kconfig2
-rw-r--r--drivers/media/radio/radio-gemtek-pci.c4
-rw-r--r--drivers/media/video/Kconfig4
-rw-r--r--drivers/media/video/bt8xx/bttv-driver.c13
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-cards.h2
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.c1
-rw-r--r--drivers/media/video/ivtv/ivtv-driver.h16
-rw-r--r--drivers/media/video/ivtv/ivtv-fileops.c16
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c45
-rw-r--r--drivers/media/video/ivtv/ivtv-irq.c204
-rw-r--r--drivers/media/video/ivtv/ivtv-queue.c31
-rw-r--r--drivers/media/video/ivtv/ivtv-queue.h39
-rw-r--r--drivers/media/video/ivtv/ivtv-streams.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.c2
-rw-r--r--drivers/media/video/ivtv/ivtv-vbi.h2
-rw-r--r--drivers/media/video/meye.c4
-rw-r--r--drivers/media/video/saa7111.c49
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c2
-rw-r--r--drivers/media/video/usbvision/usbvision-core.c82
-rw-r--r--drivers/media/video/usbvision/usbvision.h1
-rw-r--r--drivers/message/fusion/mptspi.c8
-rw-r--r--drivers/mfd/sm501.c173
-rw-r--r--drivers/mfd/ucb1x00-ts.c7
-rw-r--r--drivers/misc/Kconfig14
-rw-r--r--drivers/misc/Makefile2
-rw-r--r--drivers/misc/asus-laptop.c3
-rw-r--r--drivers/misc/blink.c27
-rw-r--r--drivers/misc/eeprom_93cx6.c241
-rw-r--r--drivers/misc/msi-laptop.c44
-rw-r--r--drivers/misc/thinkpad_acpi.c17
-rw-r--r--drivers/misc/thinkpad_acpi.h6
-rw-r--r--drivers/misc/tifm_7xx1.c2
-rw-r--r--drivers/mmc/card/Kconfig18
-rw-r--r--drivers/mmc/card/block.c7
-rw-r--r--drivers/mmc/card/queue.c191
-rw-r--r--drivers/mmc/card/queue.h7
-rw-r--r--drivers/mmc/core/Makefile3
-rw-r--r--drivers/mmc/core/bus.c253
-rw-r--r--drivers/mmc/core/bus.h22
-rw-r--r--drivers/mmc/core/core.c147
-rw-r--r--drivers/mmc/core/core.h8
-rw-r--r--drivers/mmc/core/host.c156
-rw-r--r--drivers/mmc/core/host.h18
-rw-r--r--drivers/mmc/core/mmc.c65
-rw-r--r--drivers/mmc/core/sd.c104
-rw-r--r--drivers/mmc/core/sysfs.c347
-rw-r--r--drivers/mmc/core/sysfs.h19
-rw-r--r--drivers/mmc/host/at91_mci.c222
-rw-r--r--drivers/mmc/host/au1xmmc.c3
-rw-r--r--drivers/mmc/host/omap.c24
-rw-r--r--drivers/mmc/host/pxamci.h22
-rw-r--r--drivers/mmc/host/sdhci.c10
-rw-r--r--drivers/mtd/Makefile3
-rw-r--r--drivers/mtd/devices/docprobe.c2
-rw-r--r--drivers/mtd/devices/pmc551.c2
-rw-r--r--drivers/mtd/maps/Kconfig6
-rw-r--r--drivers/mtd/maps/Makefile1
-rw-r--r--drivers/mtd/maps/lasat.c103
-rw-r--r--drivers/mtd/maps/uclinux.c5
-rw-r--r--drivers/mtd/mtdsuper.c232
-rw-r--r--drivers/mtd/nand/autcpu12.c2
-rw-r--r--drivers/mtd/nand/diskonchip.c2
-rw-r--r--drivers/mtd/nand/ppchameleonevb.c6
-rw-r--r--drivers/net/3c523.c2
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/7990.c4
-rw-r--r--drivers/net/8139cp.c35
-rw-r--r--drivers/net/8139too.c9
-rw-r--r--drivers/net/8390.h11
-rw-r--r--drivers/net/Kconfig324
-rw-r--r--drivers/net/Makefile7
-rw-r--r--drivers/net/a2065.c4
-rw-r--r--drivers/net/acenic.c25
-rw-r--r--drivers/net/acenic.h1
-rw-r--r--drivers/net/amd8111e.c13
-rw-r--r--drivers/net/amd8111e.h2
-rw-r--r--drivers/net/ariadne.c2
-rw-r--r--drivers/net/arm/Kconfig12
-rw-r--r--drivers/net/arm/am79c961a.c2
-rw-r--r--drivers/net/arm/ep93xx_eth.c2
-rw-r--r--drivers/net/atari_pamsnet.c62
-rw-r--r--drivers/net/atl1/atl1.h1
-rw-r--r--drivers/net/atl1/atl1_main.c40
-rw-r--r--drivers/net/au1000_eth.c6
-rw-r--r--drivers/net/ax88796.c952
-rw-r--r--drivers/net/b44.c56
-rw-r--r--drivers/net/b44.h2
-rw-r--r--drivers/net/bnx2.c580
-rw-r--r--drivers/net/bnx2.h67
-rw-r--r--drivers/net/bonding/bond_3ad.c9
-rw-r--r--drivers/net/bonding/bond_main.c18
-rw-r--r--drivers/net/bonding/bond_sysfs.c2
-rw-r--r--drivers/net/bonding/bonding.h6
-rw-r--r--drivers/net/cassini.c14
-rw-r--r--drivers/net/chelsio/cxgb2.c10
-rw-r--r--drivers/net/cxgb3/adapter.h38
-rw-r--r--drivers/net/cxgb3/ael1002.c10
-rw-r--r--drivers/net/cxgb3/common.h28
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c70
-rw-r--r--drivers/net/cxgb3/regs.h17
-rw-r--r--drivers/net/cxgb3/sge.c426
-rw-r--r--drivers/net/cxgb3/t3_hw.c128
-rw-r--r--drivers/net/cxgb3/version.h2
-rw-r--r--drivers/net/cxgb3/xgmac.c100
-rw-r--r--drivers/net/dl2k.c7
-rw-r--r--drivers/net/dl2k.h1
-rw-r--r--drivers/net/dm9000.c17
-rw-r--r--drivers/net/dummy.c82
-rw-r--r--drivers/net/e100.c92
-rw-r--r--drivers/net/e1000/e1000_main.c14
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/ehea/ehea.h20
-rw-r--r--drivers/net/ehea/ehea_hw.h24
-rw-r--r--drivers/net/ehea/ehea_main.c67
-rw-r--r--drivers/net/ehea/ehea_qmr.c56
-rw-r--r--drivers/net/epic100.c2
-rw-r--r--drivers/net/fealnx.c4
-rw-r--r--drivers/net/fec.c2
-rw-r--r--drivers/net/fec_8xx/Kconfig2
-rw-r--r--drivers/net/fec_8xx/fec_main.c2
-rw-r--r--drivers/net/forcedeth.c16
-rw-r--r--drivers/net/fs_enet/Kconfig2
-rw-r--r--drivers/net/gianfar.c45
-rw-r--r--drivers/net/gianfar.h6
-rw-r--r--drivers/net/gianfar_mii.c55
-rw-r--r--drivers/net/hamachi.c4
-rw-r--r--drivers/net/hp100.c2
-rw-r--r--drivers/net/ibmveth.c82
-rw-r--r--drivers/net/ifb.c78
-rw-r--r--drivers/net/ioc3-eth.c41
-rw-r--r--drivers/net/irda/irport.c2
-rw-r--r--drivers/net/irda/kingsun-sir.c4
-rw-r--r--drivers/net/irda/smsc-ircc2.c16
-rw-r--r--drivers/net/irda/vlsi_ir.c27
-rw-r--r--drivers/net/irda/vlsi_ir.h2
-rw-r--r--drivers/net/ixp2000/ixpdev.c4
-rw-r--r--drivers/net/lance.c4
-rw-r--r--drivers/net/lasi_82596.c1461
-rw-r--r--drivers/net/lib82596.c1434
-rw-r--r--drivers/net/macmace.c2
-rw-r--r--drivers/net/macvlan.c496
-rw-r--r--drivers/net/mipsnet.c2
-rw-r--r--drivers/net/mlx4/cq.c2
-rw-r--r--drivers/net/mlx4/eq.c4
-rw-r--r--drivers/net/mlx4/fw.c132
-rw-r--r--drivers/net/mlx4/fw.h11
-rw-r--r--drivers/net/mlx4/intf.c3
-rw-r--r--drivers/net/mlx4/main.c19
-rw-r--r--drivers/net/mlx4/mlx4.h1
-rw-r--r--drivers/net/mlx4/mr.c8
-rw-r--r--drivers/net/mlx4/qp.c24
-rw-r--r--drivers/net/mlx4/srq.c30
-rw-r--r--drivers/net/myri10ge/myri10ge.c35
-rw-r--r--drivers/net/natsemi.c6
-rw-r--r--drivers/net/netxen/netxen_nic.h161
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c8
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h2
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c45
-rw-r--r--drivers/net/netxen/netxen_nic_init.c95
-rw-r--r--drivers/net/netxen/netxen_nic_isr.c24
-rw-r--r--drivers/net/netxen/netxen_nic_main.c272
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c14
-rw-r--r--drivers/net/netxen/netxen_nic_phan_reg.h14
-rw-r--r--drivers/net/ni52.c2
-rw-r--r--drivers/net/ni65.c4
-rw-r--r--drivers/net/ns83820.c16
-rw-r--r--drivers/net/pasemi_mac.c2
-rw-r--r--drivers/net/pci-skeleton.c2
-rw-r--r--drivers/net/pcmcia/3c589_cs.c2
-rw-r--r--drivers/net/pcmcia/Kconfig2
-rw-r--r--drivers/net/pcmcia/axnet_cs.c7
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c23
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c11
-rw-r--r--drivers/net/pcnet32.c4
-rw-r--r--drivers/net/phy/Kconfig5
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/icplus.c134
-rw-r--r--drivers/net/phy/marvell.c185
-rw-r--r--drivers/net/phy/mdio_bus.c3
-rw-r--r--drivers/net/phy/vitesse.c2
-rw-r--r--drivers/net/ppp_generic.c13
-rw-r--r--drivers/net/pppol2tp.c2486
-rw-r--r--drivers/net/ps3_gelic_net.c1576
-rw-r--r--drivers/net/ps3_gelic_net.h239
-rwxr-xr-xdrivers/net/qla3xxx.c35
-rw-r--r--drivers/net/r8169.c955
-rw-r--r--drivers/net/rrunner.c2
-rw-r--r--drivers/net/s2io.c169
-rw-r--r--drivers/net/s2io.h7
-rw-r--r--drivers/net/saa9730.c4
-rw-r--r--drivers/net/sb1250-mac.c2
-rw-r--r--drivers/net/sgiseeq.c2
-rw-r--r--drivers/net/sis190.c2
-rw-r--r--drivers/net/sis900.c2
-rw-r--r--drivers/net/sk98lin/Makefile87
-rw-r--r--drivers/net/sk98lin/h/lm80.h179
-rw-r--r--drivers/net/sk98lin/h/skaddr.h285
-rw-r--r--drivers/net/sk98lin/h/skcsum.h213
-rw-r--r--drivers/net/sk98lin/h/skdebug.h74
-rw-r--r--drivers/net/sk98lin/h/skdrv1st.h188
-rw-r--r--drivers/net/sk98lin/h/skdrv2nd.h447
-rw-r--r--drivers/net/sk98lin/h/skerror.h55
-rw-r--r--drivers/net/sk98lin/h/skgedrv.h51
-rw-r--r--drivers/net/sk98lin/h/skgehw.h2126
-rw-r--r--drivers/net/sk98lin/h/skgehwt.h48
-rw-r--r--drivers/net/sk98lin/h/skgei2c.h210
-rw-r--r--drivers/net/sk98lin/h/skgeinit.h797
-rw-r--r--drivers/net/sk98lin/h/skgepnm2.h334
-rw-r--r--drivers/net/sk98lin/h/skgepnmi.h962
-rw-r--r--drivers/net/sk98lin/h/skgesirq.h110
-rw-r--r--drivers/net/sk98lin/h/ski2c.h174
-rw-r--r--drivers/net/sk98lin/h/skqueue.h94
-rw-r--r--drivers/net/sk98lin/h/skrlmt.h438
-rw-r--r--drivers/net/sk98lin/h/sktimer.h63
-rw-r--r--drivers/net/sk98lin/h/sktypes.h69
-rw-r--r--drivers/net/sk98lin/h/skversion.h38
-rw-r--r--drivers/net/sk98lin/h/skvpd.h248
-rw-r--r--drivers/net/sk98lin/h/xmac_ii.h1579
-rw-r--r--drivers/net/sk98lin/skaddr.c1788
-rw-r--r--drivers/net/sk98lin/skdim.c742
-rw-r--r--drivers/net/sk98lin/skethtool.c628
-rw-r--r--drivers/net/sk98lin/skge.c5211
-rw-r--r--drivers/net/sk98lin/skgehwt.c171
-rw-r--r--drivers/net/sk98lin/skgeinit.c2005
-rw-r--r--drivers/net/sk98lin/skgemib.c1075
-rw-r--r--drivers/net/sk98lin/skgepnmi.c8210
-rw-r--r--drivers/net/sk98lin/skgesirq.c2229
-rw-r--r--drivers/net/sk98lin/ski2c.c1296
-rw-r--r--drivers/net/sk98lin/sklm80.c141
-rw-r--r--drivers/net/sk98lin/skqueue.c179
-rw-r--r--drivers/net/sk98lin/skrlmt.c3257
-rw-r--r--drivers/net/sk98lin/sktimer.c250
-rw-r--r--drivers/net/sk98lin/skvpd.c1091
-rw-r--r--drivers/net/sk98lin/skxmac2.c4160
-rw-r--r--drivers/net/skfp/smt.c2
-rw-r--r--drivers/net/sky2.c696
-rw-r--r--drivers/net/sky2.h167
-rw-r--r--drivers/net/smc91x.h7
-rw-r--r--drivers/net/sni_82596.c185
-rw-r--r--drivers/net/spider_net.c402
-rw-r--r--drivers/net/spider_net.h29
-rw-r--r--drivers/net/spider_net_ethtool.c21
-rw-r--r--drivers/net/starfire.c6
-rw-r--r--drivers/net/sun3_82586.c2
-rw-r--r--drivers/net/sun3lance.c5
-rw-r--r--drivers/net/sunbmac.c2
-rw-r--r--drivers/net/sundance.c9
-rw-r--r--drivers/net/sunhme.c10
-rw-r--r--drivers/net/sunlance.c4
-rw-r--r--drivers/net/sunqe.c4
-rw-r--r--drivers/net/tc35815.c50
-rw-r--r--drivers/net/tg3.c161
-rw-r--r--drivers/net/tg3.h9
-rw-r--r--drivers/net/tlan.c5
-rw-r--r--drivers/net/tokenring/3c359.c2
-rw-r--r--drivers/net/tulip/Kconfig27
-rw-r--r--drivers/net/tulip/de2104x.c1
-rw-r--r--drivers/net/tulip/de4x5.c106
-rw-r--r--drivers/net/tulip/de4x5.h9
-rw-r--r--drivers/net/tulip/dmfe.c26
-rw-r--r--drivers/net/tulip/interrupt.c8
-rw-r--r--drivers/net/tulip/tulip_core.c15
-rw-r--r--drivers/net/tulip/winbond-840.c2
-rw-r--r--drivers/net/tulip/xircom_cb.c7
-rw-r--r--drivers/net/tulip/xircom_tulip_cb.c8
-rw-r--r--drivers/net/tun.c15
-rw-r--r--drivers/net/typhoon.c20
-rw-r--r--drivers/net/ucc_geth.c2
-rw-r--r--drivers/net/usb/Kconfig4
-rw-r--r--drivers/net/usb/catc.c2
-rw-r--r--drivers/net/usb/cdc_ether.c8
-rw-r--r--drivers/net/usb/dm9601.c11
-rw-r--r--drivers/net/usb/kaweth.c2
-rw-r--r--drivers/net/usb/usbnet.c87
-rw-r--r--drivers/net/usb/usbnet.h10
-rw-r--r--drivers/net/via-rhine.c17
-rw-r--r--drivers/net/via-velocity.c5
-rw-r--r--drivers/net/wan/pc300_drv.c4
-rw-r--r--drivers/net/wan/pc300too.c2
-rw-r--r--drivers/net/wan/pci200syn.c2
-rw-r--r--drivers/net/wireless/Kconfig31
-rw-r--r--drivers/net/wireless/Makefile3
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c6
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_phy.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c34
-rw-r--r--drivers/net/wireless/hostap/hostap_config.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c4
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c7
-rw-r--r--drivers/net/wireless/hostap/hostap_plx.c8
-rw-r--r--drivers/net/wireless/libertas/11d.c152
-rw-r--r--drivers/net/wireless/libertas/11d.h6
-rw-r--r--drivers/net/wireless/libertas/Makefile6
-rw-r--r--drivers/net/wireless/libertas/README289
-rw-r--r--drivers/net/wireless/libertas/assoc.c382
-rw-r--r--drivers/net/wireless/libertas/assoc.h10
-rw-r--r--drivers/net/wireless/libertas/cmd.c567
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c397
-rw-r--r--drivers/net/wireless/libertas/debugfs.c432
-rw-r--r--drivers/net/wireless/libertas/decl.h20
-rw-r--r--drivers/net/wireless/libertas/defs.h101
-rw-r--r--drivers/net/wireless/libertas/dev.h99
-rw-r--r--drivers/net/wireless/libertas/ethtool.c55
-rw-r--r--drivers/net/wireless/libertas/fw.c111
-rw-r--r--drivers/net/wireless/libertas/fw.h13
-rw-r--r--drivers/net/wireless/libertas/host.h17
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h394
-rw-r--r--drivers/net/wireless/libertas/if_bootcmd.c6
-rw-r--r--drivers/net/wireless/libertas/if_usb.c448
-rw-r--r--drivers/net/wireless/libertas/if_usb.h32
-rw-r--r--drivers/net/wireless/libertas/ioctl.c991
-rw-r--r--drivers/net/wireless/libertas/join.c464
-rw-r--r--drivers/net/wireless/libertas/join.h13
-rw-r--r--drivers/net/wireless/libertas/main.c696
-rw-r--r--drivers/net/wireless/libertas/rx.c64
-rw-r--r--drivers/net/wireless/libertas/sbi.h40
-rw-r--r--drivers/net/wireless/libertas/scan.c1562
-rw-r--r--drivers/net/wireless/libertas/scan.h81
-rw-r--r--drivers/net/wireless/libertas/thread.h8
-rw-r--r--drivers/net/wireless/libertas/tx.c74
-rw-r--r--drivers/net/wireless/libertas/types.h63
-rw-r--r--drivers/net/wireless/libertas/wext.c900
-rw-r--r--drivers/net/wireless/libertas/wext.h44
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c4
-rw-r--r--drivers/net/wireless/rtl8187.h145
-rw-r--r--drivers/net/wireless/rtl8187_dev.c731
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.c745
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.h44
-rw-r--r--drivers/net/wireless/rtl818x.h226
-rw-r--r--drivers/net/wireless/wl3501_cs.c2
-rw-r--r--drivers/net/wireless/zd1211rw/Makefile2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.c21
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.h28
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al2230.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al7230b.c1
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_uw2453.c534
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c3
-rw-r--r--drivers/net/yellowfin.c2
-rw-r--r--drivers/parisc/ccio-dma.c14
-rw-r--r--drivers/parisc/eisa.c4
-rw-r--r--drivers/parisc/iommu-helpers.h4
-rw-r--r--drivers/parisc/led.c6
-rw-r--r--drivers/parisc/pdc_stable.c6
-rw-r--r--drivers/parisc/power.c1
-rw-r--r--drivers/parisc/sba_iommu.c6
-rw-r--r--drivers/parisc/superio.c8
-rw-r--r--drivers/parport/parport_gsc.c2
-rw-r--r--drivers/pci/Makefile4
-rw-r--r--drivers/pci/hotplug/acpiphp.h1
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c6
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c53
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c7
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c66
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c12
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c12
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c191
-rw-r--r--drivers/pci/msi.c12
-rw-r--r--drivers/pci/pci-acpi.c8
-rw-r--r--drivers/pci/pci-sysfs.c33
-rw-r--r--drivers/pci/pci.c200
-rw-r--r--drivers/pci/pcie/aer/Kconfig2
-rw-r--r--drivers/pci/pcie/aer/Makefile3
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c2
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h14
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c36
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c34
-rw-r--r--drivers/pci/probe.c5
-rw-r--r--drivers/pci/proc.c1
-rw-r--r--drivers/pci/quirks.c50
-rw-r--r--drivers/pci/rom.c73
-rw-r--r--drivers/pci/search.c10
-rw-r--r--drivers/pci/setup-bus.c8
-rw-r--r--drivers/pci/syscall.c20
-rw-r--r--drivers/pcmcia/at91_cf.c13
-rw-r--r--drivers/pcmcia/socket_sysfs.c10
-rw-r--r--drivers/pnp/quirks.c107
-rw-r--r--drivers/power/Kconfig52
-rw-r--r--drivers/power/Makefile22
-rw-r--r--drivers/power/apm_power.c243
-rw-r--r--drivers/power/ds2760_battery.c470
-rw-r--r--drivers/power/olpc_battery.c352
-rw-r--r--drivers/power/pda_power.c261
-rw-r--r--drivers/power/pmu_battery.c215
-rw-r--r--drivers/power/power_supply.h42
-rw-r--r--drivers/power/power_supply_core.c168
-rw-r--r--drivers/power/power_supply_leds.c176
-rw-r--r--drivers/power/power_supply_sysfs.c299
-rw-r--r--drivers/rapidio/rio-sysfs.c7
-rw-r--r--drivers/rtc/rtc-cmos.c13
-rw-r--r--drivers/rtc/rtc-ds1553.c11
-rw-r--r--drivers/rtc/rtc-ds1742.c11
-rw-r--r--drivers/rtc/rtc-vr41xx.c186
-rw-r--r--drivers/rtc/rtc-x1205.c5
-rw-r--r--drivers/s390/block/dasd_eer.c16
-rw-r--r--drivers/s390/block/dasd_proc.c4
-rw-r--r--drivers/s390/char/raw3270.c10
-rw-r--r--drivers/s390/char/sclp.h12
-rw-r--r--drivers/s390/char/sclp_chp.c4
-rw-r--r--drivers/s390/char/sclp_info.c117
-rw-r--r--drivers/s390/char/vmcp.c13
-rw-r--r--drivers/s390/char/vmlogrdr.c4
-rw-r--r--drivers/s390/char/zcore.c5
-rw-r--r--drivers/s390/cio/chp.c12
-rw-r--r--drivers/s390/cio/device.c49
-rw-r--r--drivers/s390/cio/device_fsm.c6
-rw-r--r--drivers/s390/cio/device_id.c22
-rw-r--r--drivers/s390/crypto/ap_bus.c98
-rw-r--r--drivers/s390/crypto/ap_bus.h11
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c27
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c40
-rw-r--r--drivers/s390/net/claw.c13
-rw-r--r--drivers/s390/net/netiucv.c23
-rw-r--r--drivers/s390/net/qeth_eddp.c3
-rw-r--r--drivers/s390/net/qeth_main.c52
-rw-r--r--drivers/s390/net/qeth_sys.c2
-rw-r--r--drivers/sbus/char/flash.c1
-rw-r--r--drivers/scsi/Kconfig3
-rw-r--r--drivers/scsi/NCR5380.c2
-rw-r--r--drivers/scsi/aacraid/linit.c22
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c9
-rw-r--r--drivers/scsi/arcmsr/arcmsr_attr.c18
-rw-r--r--drivers/scsi/atari_NCR5380.c44
-rw-r--r--drivers/scsi/esp_scsi.c1
-rw-r--r--drivers/scsi/ide-scsi.c2
-rw-r--r--drivers/scsi/ipr.c40
-rw-r--r--drivers/scsi/ips.c9
-rw-r--r--drivers/scsi/libsas/sas_expander.c17
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c14
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c5
-rw-r--r--drivers/scsi/nsp32.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c56
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c2
-rw-r--r--drivers/scsi/scsi_scan.c9
-rw-r--r--drivers/serial/Kconfig48
-rw-r--r--drivers/serial/amba-pl010.c4
-rw-r--r--drivers/serial/bfin_5xx.c201
-rw-r--r--drivers/serial/jsm/jsm_driver.c2
-rw-r--r--drivers/serial/mpsc.c3
-rw-r--r--drivers/serial/serial_cs.c4
-rw-r--r--drivers/serial/vr41xx_siu.c143
-rw-r--r--drivers/spi/at25.c7
-rw-r--r--drivers/spi/atmel_spi.c8
-rw-r--r--drivers/spi/spi.c2
-rw-r--r--drivers/spi/spi_bfin5xx.c17
-rw-r--r--drivers/spi/spi_imx.c3
-rw-r--r--drivers/tc/zs.c18
-rw-r--r--drivers/usb/Kconfig10
-rw-r--r--drivers/usb/Makefile2
-rw-r--r--drivers/usb/atm/cxacru.c125
-rw-r--r--drivers/usb/class/cdc-acm.c3
-rw-r--r--drivers/usb/class/usblp.c621
-rw-r--r--drivers/usb/core/Kconfig47
-rw-r--r--drivers/usb/core/config.c78
-rw-r--r--drivers/usb/core/devices.c26
-rw-r--r--drivers/usb/core/driver.c162
-rw-r--r--drivers/usb/core/file.c29
-rw-r--r--drivers/usb/core/generic.c29
-rw-r--r--drivers/usb/core/hcd-pci.c3
-rw-r--r--drivers/usb/core/hcd.c126
-rw-r--r--drivers/usb/core/hcd.h14
-rw-r--r--drivers/usb/core/hub.c650
-rw-r--r--drivers/usb/core/message.c38
-rw-r--r--drivers/usb/core/quirks.c18
-rw-r--r--drivers/usb/core/sysfs.c109
-rw-r--r--drivers/usb/core/urb.c105
-rw-r--r--drivers/usb/core/usb.c12
-rw-r--r--drivers/usb/core/usb.h14
-rw-r--r--drivers/usb/gadget/Kconfig53
-rw-r--r--drivers/usb/gadget/Makefile6
-rw-r--r--drivers/usb/gadget/at91_udc.c21
-rw-r--r--drivers/usb/gadget/dummy_hcd.c39
-rw-r--r--drivers/usb/gadget/epautoconf.c2
-rw-r--r--drivers/usb/gadget/ether.c8
-rw-r--r--drivers/usb/gadget/file_storage.c34
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.c99
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h4
-rw-r--r--drivers/usb/gadget/gadget_chips.h27
-rw-r--r--drivers/usb/gadget/gmidi.c8
-rw-r--r--drivers/usb/gadget/goku_udc.c84
-rw-r--r--drivers/usb/gadget/goku_udc.h10
-rw-r--r--drivers/usb/gadget/inode.c16
-rw-r--r--drivers/usb/gadget/lh7a40x_udc.c27
-rw-r--r--drivers/usb/gadget/m66592-udc.c1634
-rw-r--r--drivers/usb/gadget/m66592-udc.h577
-rw-r--r--drivers/usb/gadget/net2280.c105
-rw-r--r--drivers/usb/gadget/omap_udc.c114
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c473
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.h48
-rw-r--r--drivers/usb/gadget/rndis.c199
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c2045
-rw-r--r--drivers/usb/gadget/s3c2410_udc.h110
-rw-r--r--drivers/usb/gadget/serial.c14
-rw-r--r--drivers/usb/gadget/zero.c9
-rw-r--r--drivers/usb/host/Kconfig28
-rw-r--r--drivers/usb/host/Makefile2
-rw-r--r--drivers/usb/host/ehci-dbg.c183
-rw-r--r--drivers/usb/host/ehci-fsl.c10
-rw-r--r--drivers/usb/host/ehci-hcd.c118
-rw-r--r--drivers/usb/host/ehci-hub.c122
-rw-r--r--drivers/usb/host/ehci-mem.c27
-rw-r--r--drivers/usb/host/ehci-pci.c10
-rw-r--r--drivers/usb/host/ehci-ppc-soc.c182
-rw-r--r--drivers/usb/host/ehci-ps3.c86
-rw-r--r--drivers/usb/host/ehci-q.c96
-rw-r--r--drivers/usb/host/ehci-sched.c339
-rw-r--r--drivers/usb/host/ehci.h234
-rw-r--r--drivers/usb/host/ohci-dbg.c4
-rw-r--r--drivers/usb/host/ohci-hcd.c92
-rw-r--r--drivers/usb/host/ohci-hub.c7
-rw-r--r--drivers/usb/host/ohci-mem.c1
-rw-r--r--drivers/usb/host/ohci-pci.c57
-rw-r--r--drivers/usb/host/ohci-pnx4008.c2
-rw-r--r--drivers/usb/host/ohci-ps3.c87
-rw-r--r--drivers/usb/host/ohci.h2
-rw-r--r--drivers/usb/host/r8a66597-hcd.c2244
-rw-r--r--drivers/usb/host/r8a66597.h634
-rw-r--r--drivers/usb/host/uhci-hcd.c5
-rw-r--r--drivers/usb/misc/adutux.c31
-rw-r--r--drivers/usb/misc/auerswald.c6
-rw-r--r--drivers/usb/misc/berry_charge.c35
-rw-r--r--drivers/usb/misc/idmouse.c54
-rw-r--r--drivers/usb/misc/iowarrior.c33
-rw-r--r--drivers/usb/misc/ldusb.c33
-rw-r--r--drivers/usb/misc/legousbtower.c24
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb.c38
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c25
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_init.h2
-rw-r--r--drivers/usb/misc/usblcd.c89
-rw-r--r--drivers/usb/misc/uss720.c2
-rw-r--r--drivers/usb/mon/mon_bin.c34
-rw-r--r--drivers/usb/mon/mon_main.c14
-rw-r--r--drivers/usb/mon/mon_text.c29
-rw-r--r--drivers/usb/mon/usb_mon.h7
-rw-r--r--drivers/usb/serial/Kconfig10
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/aircable.c16
-rw-r--r--drivers/usb/serial/airprime.c10
-rw-r--r--drivers/usb/serial/ark3116.c61
-rw-r--r--drivers/usb/serial/belkin_sa.c78
-rw-r--r--drivers/usb/serial/cyberjack.c17
-rw-r--r--drivers/usb/serial/cypress_m8.c18
-rw-r--r--drivers/usb/serial/digi_acceleport.c99
-rw-r--r--drivers/usb/serial/empeg.c14
-rw-r--r--drivers/usb/serial/ftdi_sio.c120
-rw-r--r--drivers/usb/serial/ftdi_sio.h1
-rw-r--r--drivers/usb/serial/garmin_gps.c47
-rw-r--r--drivers/usb/serial/generic.c97
-rw-r--r--drivers/usb/serial/io_edgeport.c44
-rw-r--r--drivers/usb/serial/io_fw_down3.h1460
-rw-r--r--drivers/usb/serial/io_ti.c124
-rw-r--r--drivers/usb/serial/io_usbvend.h12
-rw-r--r--drivers/usb/serial/ipaq.c14
-rw-r--r--drivers/usb/serial/ipw.c12
-rw-r--r--drivers/usb/serial/ir-usb.c154
-rw-r--r--drivers/usb/serial/keyspan.c456
-rw-r--r--drivers/usb/serial/keyspan.h74
-rw-r--r--drivers/usb/serial/keyspan_pda.c17
-rw-r--r--drivers/usb/serial/keyspan_usa67msg.h254
-rw-r--r--drivers/usb/serial/kl5kusb105.c22
-rw-r--r--drivers/usb/serial/kobil_sct.c26
-rw-r--r--drivers/usb/serial/mct_u232.c149
-rw-r--r--drivers/usb/serial/mct_u232.h15
-rw-r--r--drivers/usb/serial/mos7720.c43
-rw-r--r--drivers/usb/serial/mos7840.c106
-rw-r--r--drivers/usb/serial/navman.c7
-rw-r--r--drivers/usb/serial/omninet.c20
-rw-r--r--drivers/usb/serial/option.c40
-rw-r--r--drivers/usb/serial/oti6858.c1342
-rw-r--r--drivers/usb/serial/oti6858.h15
-rw-r--r--drivers/usb/serial/pl2303.c90
-rw-r--r--drivers/usb/serial/safe_serial.c6
-rw-r--r--drivers/usb/serial/sierra.c371
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c54
-rw-r--r--drivers/usb/serial/usb-serial.c35
-rw-r--r--drivers/usb/serial/visor.c64
-rw-r--r--drivers/usb/serial/whiteheat.c122
-rw-r--r--drivers/usb/storage/scsiglue.c21
-rw-r--r--drivers/usb/storage/unusual_devs.h209
-rw-r--r--drivers/usb/storage/usb.c91
-rw-r--r--drivers/usb/storage/usb.h1
-rw-r--r--drivers/usb/usb-skeleton.c151
-rw-r--r--drivers/video/Kconfig6
-rw-r--r--drivers/video/arkfb.c3
-rw-r--r--drivers/video/aty/atyfb_base.c17
-rw-r--r--drivers/video/aty/radeon_base.c10
-rw-r--r--drivers/video/backlight/backlight.c2
-rw-r--r--drivers/video/backlight/lcd.c2
-rw-r--r--drivers/video/chipsfb.c6
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/Makefile2
-rw-r--r--drivers/video/console/fbcon.h1
-rw-r--r--drivers/video/console/sticore.c50
-rw-r--r--drivers/video/ffb.c4
-rw-r--r--drivers/video/kyro/STG4000InitDevice.c5
-rw-r--r--drivers/video/matrox/matroxfb_base.c4
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.h2
-rw-r--r--drivers/video/neofb.c30
-rw-r--r--drivers/video/pm3fb.c2
-rw-r--r--drivers/video/sis/sis_main.c2
-rw-r--r--drivers/video/skeletonfb.c31
-rw-r--r--drivers/video/sstfb.c2
-rw-r--r--drivers/video/sunxvr2500.c17
-rw-r--r--drivers/video/sunxvr500.c6
-rw-r--r--drivers/video/tgafb.c3
-rw-r--r--drivers/video/vt8623fb.c3
-rw-r--r--drivers/w1/slaves/Kconfig13
-rw-r--r--drivers/w1/slaves/Makefile1
-rw-r--r--drivers/w1/slaves/w1_ds2433.c11
-rw-r--r--drivers/w1/slaves/w1_ds2760.c213
-rw-r--r--drivers/w1/slaves/w1_ds2760.h50
-rw-r--r--drivers/w1/slaves/w1_therm.c14
-rw-r--r--drivers/w1/w1.c14
-rw-r--r--drivers/w1/w1_family.h1
-rw-r--r--drivers/zorro/zorro-sysfs.c6
-rw-r--r--fs/9p/9p.h375
-rw-r--r--fs/9p/Makefile6
-rw-r--r--fs/9p/conv.h50
-rw-r--r--fs/9p/debug.h77
-rw-r--r--fs/9p/error.c93
-rw-r--r--fs/9p/fcall.c427
-rw-r--r--fs/9p/fid.c168
-rw-r--r--fs/9p/fid.h43
-rw-r--r--fs/9p/trans_fd.c308
-rw-r--r--fs/9p/v9fs.c293
-rw-r--r--fs/9p/v9fs.h32
-rw-r--r--fs/9p/v9fs_vfs.h6
-rw-r--r--fs/9p/vfs_addr.c57
-rw-r--r--fs/9p/vfs_dentry.c37
-rw-r--r--fs/9p/vfs_dir.c155
-rw-r--r--fs/9p/vfs_file.c166
-rw-r--r--fs/9p/vfs_inode.c754
-rw-r--r--fs/9p/vfs_super.c93
-rw-r--r--fs/Kconfig2
-rw-r--r--fs/adfs/file.c2
-rw-r--r--fs/affs/file.c2
-rw-r--r--fs/afs/file.c2
-rw-r--r--fs/afs/internal.h2
-rw-r--r--fs/bad_inode.c7
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/binfmt_elf.c7
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/bio.c2
-rw-r--r--fs/block_dev.c1
-rw-r--r--fs/cifs/cifs_debug.c252
-rw-r--r--fs/cifs/cifs_unicode.c12
-rw-r--r--fs/cifs/cifsfs.c10
-rw-r--r--fs/cifs/cifssmb.c4
-rw-r--r--fs/cifs/connect.c16
-rw-r--r--fs/cifs/dir.c184
-rw-r--r--fs/cifs/fcntl.c46
-rw-r--r--fs/cifs/inode.c5
-rw-r--r--fs/cifs/ioctl.c29
-rw-r--r--fs/cifs/rfc1002pdu.h2
-rw-r--r--fs/coda/dir.c2
-rw-r--r--fs/coda/file.c11
-rw-r--r--fs/debugfs/inode.c63
-rw-r--r--fs/direct-io.c2
-rw-r--r--fs/dlm/Kconfig2
-rw-r--r--fs/dlm/Makefile1
-rw-r--r--fs/dlm/config.c25
-rw-r--r--fs/dlm/config.h1
-rw-r--r--fs/dlm/debug_fs.c186
-rw-r--r--fs/dlm/dlm_internal.h17
-rw-r--r--fs/dlm/lock.c470
-rw-r--r--fs/dlm/lock.h13
-rw-r--r--fs/dlm/lockspace.c86
-rw-r--r--fs/dlm/lowcomms.c23
-rw-r--r--fs/dlm/main.c11
-rw-r--r--fs/dlm/member.c11
-rw-r--r--fs/dlm/netlink.c153
-rw-r--r--fs/dlm/rcom.c13
-rw-r--r--fs/dlm/recoverd.c4
-rw-r--r--fs/dlm/user.c129
-rw-r--r--fs/ecryptfs/ecryptfs_kernel.h2
-rw-r--r--fs/ecryptfs/file.c15
-rw-r--r--fs/ecryptfs/inode.c66
-rw-r--r--fs/ecryptfs/main.c2
-rw-r--r--fs/ecryptfs/mmap.c55
-rw-r--r--fs/ext2/file.c2
-rw-r--r--fs/ext2/super.c9
-rw-r--r--fs/ext3/file.c1
-rw-r--r--fs/ext3/inode.c4
-rw-r--r--fs/ext4/balloc.c6
-rw-r--r--fs/ext4/extents.c148
-rw-r--r--fs/ext4/file.c1
-rw-r--r--fs/ext4/inode.c8
-rw-r--r--fs/ext4/namei.c4
-rw-r--r--fs/ext4/super.c2
-rw-r--r--fs/fat/file.c2
-rw-r--r--fs/fuse/file.c4
-rw-r--r--fs/fuse/inode.c3
-rw-r--r--fs/gfs2/Makefile2
-rw-r--r--fs/gfs2/bmap.c23
-rw-r--r--fs/gfs2/daemon.c11
-rw-r--r--fs/gfs2/dir.c69
-rw-r--r--fs/gfs2/dir.h9
-rw-r--r--fs/gfs2/eattr.c14
-rw-r--r--fs/gfs2/glock.c123
-rw-r--r--fs/gfs2/glock.h1
-rw-r--r--fs/gfs2/glops.c2
-rw-r--r--fs/gfs2/incore.h81
-rw-r--r--fs/gfs2/inode.c288
-rw-r--r--fs/gfs2/inode.h30
-rw-r--r--fs/gfs2/locking/dlm/lock.c11
-rw-r--r--fs/gfs2/locking/dlm/lock_dlm.h2
-rw-r--r--fs/gfs2/locking/dlm/mount.c2
-rw-r--r--fs/gfs2/locking/dlm/plock.c8
-rw-r--r--fs/gfs2/locking/dlm/thread.c11
-rw-r--r--fs/gfs2/log.c129
-rw-r--r--fs/gfs2/lops.c49
-rw-r--r--fs/gfs2/lops.h23
-rw-r--r--fs/gfs2/meta_io.c8
-rw-r--r--fs/gfs2/meta_io.h2
-rw-r--r--fs/gfs2/mount.c25
-rw-r--r--fs/gfs2/ondisk.c251
-rw-r--r--fs/gfs2/ops_address.c69
-rw-r--r--fs/gfs2/ops_address.h2
-rw-r--r--fs/gfs2/ops_dentry.c24
-rw-r--r--fs/gfs2/ops_export.c65
-rw-r--r--fs/gfs2/ops_export.h22
-rw-r--r--fs/gfs2/ops_file.c5
-rw-r--r--fs/gfs2/ops_fstype.c33
-rw-r--r--fs/gfs2/ops_fstype.h1
-rw-r--r--fs/gfs2/ops_inode.c30
-rw-r--r--fs/gfs2/ops_super.c8
-rw-r--r--fs/gfs2/ops_vm.c2
-rw-r--r--fs/gfs2/quota.c57
-rw-r--r--fs/gfs2/recovery.c22
-rw-r--r--fs/gfs2/rgrp.c377
-rw-r--r--fs/gfs2/rgrp.h1
-rw-r--r--fs/gfs2/super.c79
-rw-r--r--fs/gfs2/super.h2
-rw-r--r--fs/gfs2/util.c6
-rw-r--r--fs/hfs/inode.c2
-rw-r--r--fs/hfsplus/inode.c2
-rw-r--r--fs/hostfs/hostfs_kern.c2
-rw-r--r--fs/hpfs/file.c2
-rw-r--r--fs/hugetlbfs/inode.c7
-rw-r--r--fs/ioctl.c14
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/readinode.c45
-rw-r--r--fs/jffs2/super.c194
-rw-r--r--fs/jffs2/xattr.c6
-rw-r--r--fs/jfs/endian24.h2
-rw-r--r--fs/jfs/file.c1
-rw-r--r--fs/jfs/jfs_debug.c28
-rw-r--r--fs/jfs/jfs_debug.h2
-rw-r--r--fs/jfs/jfs_dinode.h42
-rw-r--r--fs/jfs/jfs_dmap.c419
-rw-r--r--fs/jfs/jfs_dmap.h118
-rw-r--r--fs/jfs/jfs_dtree.c105
-rw-r--r--fs/jfs/jfs_dtree.h2
-rw-r--r--fs/jfs/jfs_extent.c102
-rw-r--r--fs/jfs/jfs_filsys.h13
-rw-r--r--fs/jfs/jfs_imap.c296
-rw-r--r--fs/jfs/jfs_imap.h98
-rw-r--r--fs/jfs/jfs_incore.h4
-rw-r--r--fs/jfs/jfs_logmgr.c90
-rw-r--r--fs/jfs/jfs_logmgr.h26
-rw-r--r--fs/jfs/jfs_metapage.c3
-rw-r--r--fs/jfs/jfs_mount.c6
-rw-r--r--fs/jfs/jfs_txnmgr.c302
-rw-r--r--fs/jfs/jfs_txnmgr.h2
-rw-r--r--fs/jfs/jfs_types.h20
-rw-r--r--fs/jfs/jfs_umount.c2
-rw-r--r--fs/jfs/jfs_xtree.c428
-rw-r--r--fs/jfs/jfs_xtree.h48
-rw-r--r--fs/jfs/namei.c26
-rw-r--r--fs/jfs/resize.c48
-rw-r--r--fs/jfs/xattr.c9
-rw-r--r--fs/lockd/host.c39
-rw-r--r--fs/lockd/mon.c2
-rw-r--r--fs/lockd/svc.c6
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/nfs/Makefile4
-rw-r--r--fs/nfs/client.c28
-rw-r--r--fs/nfs/delegation.c186
-rw-r--r--fs/nfs/delegation.h26
-rw-r--r--fs/nfs/dir.c16
-rw-r--r--fs/nfs/direct.c34
-rw-r--r--fs/nfs/file.c15
-rw-r--r--fs/nfs/inode.c73
-rw-r--r--fs/nfs/internal.h4
-rw-r--r--fs/nfs/mount_clnt.c169
-rw-r--r--fs/nfs/nfs2xdr.c6
-rw-r--r--fs/nfs/nfs3proc.c4
-rw-r--r--fs/nfs/nfs3xdr.c8
-rw-r--r--fs/nfs/nfs4_fs.h40
-rw-r--r--fs/nfs/nfs4proc.c760
-rw-r--r--fs/nfs/nfs4state.c310
-rw-r--r--fs/nfs/nfs4xdr.c126
-rw-r--r--fs/nfs/nfsroot.c5
-rw-r--r--fs/nfs/pagelist.c60
-rw-r--r--fs/nfs/read.c40
-rw-r--r--fs/nfs/super.c1189
-rw-r--r--fs/nfs/write.c149
-rw-r--r--fs/nfsd/nfs4callback.c18
-rw-r--r--fs/nfsd/nfs4state.c1
-rw-r--r--fs/nfsd/vfs.c46
-rw-r--r--fs/ntfs/file.c2
-rw-r--r--fs/ntfs/inode.c2
-rw-r--r--fs/ocfs2/aops.c20
-rw-r--r--fs/ocfs2/cluster/masklog.c4
-rw-r--r--fs/ocfs2/file.c18
-rw-r--r--fs/partitions/check.c1
-rw-r--r--fs/partitions/ibm.c167
-rw-r--r--fs/pipe.c70
-rw-r--r--fs/proc/array.c59
-rw-r--r--fs/proc/base.c71
-rw-r--r--fs/qnx4/file.c2
-rw-r--r--fs/ramfs/file-mmu.c2
-rw-r--r--fs/ramfs/file-nommu.c7
-rw-r--r--fs/read_write.c20
-rw-r--r--fs/reiserfs/file.c1
-rw-r--r--fs/seq_file.c34
-rw-r--r--fs/signalfd.c3
-rw-r--r--fs/smbfs/file.c9
-rw-r--r--fs/splice.c538
-rw-r--r--fs/sync.c8
-rw-r--r--fs/sysfs/bin.c195
-rw-r--r--fs/sysfs/dir.c1297
-rw-r--r--fs/sysfs/file.c379
-rw-r--r--fs/sysfs/group.c55
-rw-r--r--fs/sysfs/inode.c206
-rw-r--r--fs/sysfs/mount.c37
-rw-r--r--fs/sysfs/symlink.c150
-rw-r--r--fs/sysfs/sysfs.h169
-rw-r--r--fs/sysv/file.c2
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/udf/inode.c23
-rw-r--r--fs/udf/super.c2
-rw-r--r--fs/udf/truncate.c79
-rw-r--r--fs/udf/udfdecl.h1
-rw-r--r--fs/ufs/file.c2
-rw-r--r--fs/utimes.c13
-rw-r--r--fs/xfs/Makefile-linux-2.62
-rw-r--r--fs/xfs/linux-2.6/kmem.h19
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c43
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c59
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c37
-rw-r--r--fs/xfs/linux-2.6/xfs_globals.c1
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c321
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c46
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h3
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c5
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_sysctl.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h15
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h11
-rw-r--r--fs/xfs/quota/xfs_qm.c9
-rw-r--r--fs/xfs/xfs.h1
-rw-r--r--fs/xfs/xfs_ag.h9
-rw-r--r--fs/xfs/xfs_alloc.c101
-rw-r--r--fs/xfs/xfs_alloc.h6
-rw-r--r--fs/xfs/xfs_alloc_btree.c20
-rw-r--r--fs/xfs/xfs_bit.c91
-rw-r--r--fs/xfs/xfs_bit.h4
-rw-r--r--fs/xfs/xfs_bmap.c369
-rw-r--r--fs/xfs/xfs_bmap.h6
-rw-r--r--fs/xfs/xfs_bmap_btree.c88
-rw-r--r--fs/xfs/xfs_btree.h32
-rw-r--r--fs/xfs/xfs_buf_item.c4
-rw-r--r--fs/xfs/xfs_clnt.h2
-rw-r--r--fs/xfs/xfs_dinode.h4
-rw-r--r--fs/xfs/xfs_dir2.c12
-rw-r--r--fs/xfs/xfs_dir2_block.c98
-rw-r--r--fs/xfs/xfs_dir2_block.h2
-rw-r--r--fs/xfs/xfs_dir2_data.c54
-rw-r--r--fs/xfs/xfs_dir2_data.h12
-rw-r--r--fs/xfs/xfs_dir2_leaf.c106
-rw-r--r--fs/xfs/xfs_dir2_leaf.h29
-rw-r--r--fs/xfs/xfs_dir2_node.c66
-rw-r--r--fs/xfs/xfs_dir2_node.h4
-rw-r--r--fs/xfs/xfs_dir2_sf.c204
-rw-r--r--fs/xfs/xfs_dir2_sf.h20
-rw-r--r--fs/xfs/xfs_filestream.c771
-rw-r--r--fs/xfs/xfs_filestream.h136
-rw-r--r--fs/xfs/xfs_fs.h2
-rw-r--r--fs/xfs/xfs_fsops.c17
-rw-r--r--fs/xfs/xfs_ialloc.c28
-rw-r--r--fs/xfs/xfs_ialloc.h10
-rw-r--r--fs/xfs/xfs_inode.c39
-rw-r--r--fs/xfs/xfs_inode.h16
-rw-r--r--fs/xfs/xfs_iomap.c41
-rw-r--r--fs/xfs/xfs_itable.c42
-rw-r--r--fs/xfs/xfs_itable.h20
-rw-r--r--fs/xfs/xfs_log.c41
-rw-r--r--fs/xfs/xfs_log_recover.c8
-rw-r--r--fs/xfs/xfs_mount.c237
-rw-r--r--fs/xfs/xfs_mount.h15
-rw-r--r--fs/xfs/xfs_mru_cache.c608
-rw-r--r--fs/xfs/xfs_mru_cache.h57
-rw-r--r--fs/xfs/xfs_rtalloc.c4
-rw-r--r--fs/xfs/xfs_rw.h36
-rw-r--r--fs/xfs/xfs_sb.h16
-rw-r--r--fs/xfs/xfs_trans.c125
-rw-r--r--fs/xfs/xfs_trans.h3
-rw-r--r--fs/xfs/xfs_vfsops.c159
-rw-r--r--fs/xfs/xfs_vnodeops.c122
-rw-r--r--include/acpi/acpi_numa.h2
-rw-r--r--include/acpi/acpiosxf.h3
-rw-r--r--include/acpi/acpixf.h2
-rw-r--r--include/acpi/acutils.h2
-rw-r--r--include/asm-alpha/core_t2.h26
-rw-r--r--include/asm-alpha/core_titan.h7
-rw-r--r--include/asm-alpha/core_tsunami.h15
-rw-r--r--include/asm-alpha/core_wildfire.h2
-rw-r--r--include/asm-alpha/pci.h29
-rw-r--r--include/asm-alpha/vga.h31
-rw-r--r--include/asm-arm/Kbuild2
-rw-r--r--include/asm-arm/arch-at91/at91_dbgu.h13
-rw-r--r--include/asm-arm/arch-at91/at91_shdwc.h4
-rw-r--r--include/asm-arm/arch-at91/at91_wdt.h2
-rw-r--r--include/asm-arm/arch-at91/at91x40.h55
-rw-r--r--include/asm-arm/arch-at91/cpu.h5
-rw-r--r--include/asm-arm/arch-at91/hardware.h17
-rw-r--r--include/asm-arm/arch-at91/timex.h5
-rw-r--r--include/asm-arm/arch-at91/uncompress.h4
-rw-r--r--include/asm-arm/arch-davinci/clock.h22
-rw-r--r--include/asm-arm/arch-davinci/gpio.h156
-rw-r--r--include/asm-arm/arch-davinci/hardware.h38
-rw-r--r--include/asm-arm/arch-davinci/mux.h55
-rw-r--r--include/asm-arm/arch-imx/gpio.h102
-rw-r--r--include/asm-arm/arch-imx/imx-regs.h2
-rw-r--r--include/asm-arm/arch-iop13xx/adma.h544
-rw-r--r--include/asm-arm/arch-iop13xx/iop13xx.h38
-rw-r--r--include/asm-arm/arch-iop32x/adma.h5
-rw-r--r--include/asm-arm/arch-iop33x/adma.h5
-rw-r--r--include/asm-arm/arch-ixp4xx/ixdp425.h4
-rw-r--r--include/asm-arm/arch-ixp4xx/udc.h22
-rw-r--r--include/asm-arm/arch-ixp4xx/uncompress.h5
-rw-r--r--include/asm-arm/arch-ks8695/gpio.h79
-rw-r--r--include/asm-arm/arch-pxa/dma.h22
-rw-r--r--include/asm-arm/arch-pxa/entry-macro.S30
-rw-r--r--include/asm-arm/arch-pxa/gpio.h3
-rw-r--r--include/asm-arm/arch-pxa/hardware.h36
-rw-r--r--include/asm-arm/arch-pxa/irqs.h26
-rw-r--r--include/asm-arm/arch-pxa/pm.h1
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h22
-rw-r--r--include/asm-arm/arch-pxa/udc.h33
-rw-r--r--include/asm-arm/arch-s3c2410/anubis-cpld.h4
-rw-r--r--include/asm-arm/arch-s3c2410/anubis-map.h10
-rw-r--r--include/asm-arm/arch-s3c2410/osiris-cpld.h19
-rw-r--r--include/asm-arm/arch-s3c2410/osiris-map.h19
-rw-r--r--include/asm-arm/elf.h23
-rw-r--r--include/asm-arm/hardware/iop3xx-adma.h892
-rw-r--r--include/asm-arm/hardware/iop3xx.h68
-rw-r--r--include/asm-arm/hardware/iop_adma.h118
-rw-r--r--include/asm-arm/hwcap.h28
-rw-r--r--include/asm-arm/linkage.h4
-rw-r--r--include/asm-arm/pci.h9
-rw-r--r--include/asm-arm/ptrace.h19
-rw-r--r--include/asm-arm/unistd.h1
-rw-r--r--include/asm-arm26/termbits.h12
-rw-r--r--include/asm-avr32/arch-at32ap/gpio.h2
-rw-r--r--include/asm-avr32/cache.h9
-rw-r--r--include/asm-avr32/termbits.h11
-rw-r--r--include/asm-blackfin/Kbuild2
-rw-r--r--include/asm-blackfin/bfin-global.h12
-rw-r--r--include/asm-blackfin/blackfin.h39
-rw-r--r--include/asm-blackfin/cplbinit.h133
-rw-r--r--include/asm-blackfin/dma-mapping.h2
-rw-r--r--include/asm-blackfin/fixed_code.h20
-rw-r--r--include/asm-blackfin/gpio.h59
-rw-r--r--include/asm-blackfin/hardirq.h4
-rw-r--r--include/asm-blackfin/io.h6
-rw-r--r--include/asm-blackfin/kgdb.h183
-rw-r--r--include/asm-blackfin/mach-bf533/anomaly.h84
-rw-r--r--include/asm-blackfin/mach-bf533/bfin_serial_5xx.h2
-rw-r--r--include/asm-blackfin/mach-bf533/dma.h3
-rw-r--r--include/asm-blackfin/mach-bf533/portmux.h65
-rw-r--r--include/asm-blackfin/mach-bf537/anomaly.h21
-rw-r--r--include/asm-blackfin/mach-bf537/dma.h3
-rw-r--r--include/asm-blackfin/mach-bf537/portmux.h109
-rw-r--r--include/asm-blackfin/mach-bf548/anomaly.h74
-rw-r--r--include/asm-blackfin/mach-bf548/bf548.h271
-rw-r--r--include/asm-blackfin/mach-bf548/bfin_serial_5xx.h193
-rw-r--r--include/asm-blackfin/mach-bf548/blackfin.h168
-rw-r--r--include/asm-blackfin/mach-bf548/cdefBF54x_base.h72
-rw-r--r--include/asm-blackfin/mach-bf548/defBF542.h281
-rw-r--r--include/asm-blackfin/mach-bf548/defBF544.h60
-rw-r--r--include/asm-blackfin/mach-bf548/defBF548.h341
-rw-r--r--include/asm-blackfin/mach-bf548/defBF549.h763
-rw-r--r--include/asm-blackfin/mach-bf548/defBF54x_base.h1366
-rw-r--r--include/asm-blackfin/mach-bf548/dma.h73
-rw-r--r--include/asm-blackfin/mach-bf548/gpio.h216
-rw-r--r--include/asm-blackfin/mach-bf548/irq.h467
-rw-r--r--include/asm-blackfin/mach-bf548/mem_init.h189
-rw-r--r--include/asm-blackfin/mach-bf548/mem_map.h97
-rw-r--r--include/asm-blackfin/mach-bf548/portmux.h270
-rw-r--r--include/asm-blackfin/mach-bf561/bfin_serial_5xx.h2
-rw-r--r--include/asm-blackfin/mach-bf561/cdefBF561.h9
-rw-r--r--include/asm-blackfin/mach-bf561/dma.h3
-rw-r--r--include/asm-blackfin/mach-bf561/portmux.h87
-rw-r--r--include/asm-blackfin/mach-common/cdef_LPBlackfin.h8
-rw-r--r--include/asm-blackfin/mach-common/def_LPBlackfin.h22
-rw-r--r--include/asm-blackfin/macros.h95
-rw-r--r--include/asm-blackfin/mman.h2
-rw-r--r--include/asm-blackfin/page.h4
-rw-r--r--include/asm-blackfin/portmux.h1133
-rw-r--r--include/asm-blackfin/processor.h4
-rw-r--r--include/asm-blackfin/termbits.h11
-rw-r--r--include/asm-blackfin/trace.h52
-rw-r--r--include/asm-blackfin/unistd.h3
-rw-r--r--include/asm-cris/pci.h36
-rw-r--r--include/asm-cris/termbits.h11
-rw-r--r--include/asm-frv/pci.h7
-rw-r--r--include/asm-frv/pgtable.h2
-rw-r--r--include/asm-frv/system.h1
-rw-r--r--include/asm-frv/termbits.h11
-rw-r--r--include/asm-frv/uaccess.h2
-rw-r--r--include/asm-generic/bitops/sched.h21
-rw-r--r--include/asm-generic/pgtable.h17
-rw-r--r--include/asm-generic/vmlinux.lds.h10
-rw-r--r--include/asm-h8300/pci.h4
-rw-r--r--include/asm-h8300/processor.h2
-rw-r--r--include/asm-h8300/termbits.h11
-rw-r--r--include/asm-i386/boot.h6
-rw-r--r--include/asm-i386/bootparam.h85
-rw-r--r--include/asm-i386/cpufeature.h26
-rw-r--r--include/asm-i386/dma-mapping.h6
-rw-r--r--include/asm-i386/e820.h14
-rw-r--r--include/asm-i386/mach-es7000/mach_apic.h4
-rw-r--r--include/asm-i386/mach-es7000/mach_mpparse.h6
-rw-r--r--include/asm-i386/paravirt.h2
-rw-r--r--include/asm-i386/pci.h37
-rw-r--r--include/asm-i386/pgtable.h34
-rw-r--r--include/asm-i386/processor.h1
-rw-r--r--include/asm-i386/required-features.h39
-rw-r--r--include/asm-i386/setup.h10
-rw-r--r--include/asm-ia64/mca.h1
-rw-r--r--include/asm-ia64/pci.h22
-rw-r--r--include/asm-ia64/pgtable.h25
-rw-r--r--include/asm-ia64/sn/sn_sal.h24
-rw-r--r--include/asm-ia64/termbits.h11
-rw-r--r--include/asm-m32r/termbits.h11
-rw-r--r--include/asm-m68k/mmzone.h9
-rw-r--r--include/asm-m68k/module.h34
-rw-r--r--include/asm-m68k/motorola_pgtable.h10
-rw-r--r--include/asm-m68k/page.h77
-rw-r--r--include/asm-m68k/pci.h4
-rw-r--r--include/asm-m68k/pgalloc.h3
-rw-r--r--include/asm-m68k/pgtable.h17
-rw-r--r--include/asm-m68k/sun3_pgtable.h4
-rw-r--r--include/asm-m68k/termbits.h11
-rw-r--r--include/asm-m68k/virtconvert.h49
-rw-r--r--include/asm-m68knommu/pci.h10
-rw-r--r--include/asm-mips/addrspace.h28
-rw-r--r--include/asm-mips/asmmacro.h15
-rw-r--r--include/asm-mips/bitops.h53
-rw-r--r--include/asm-mips/bootinfo.h36
-rw-r--r--include/asm-mips/cacheops.h4
-rw-r--r--include/asm-mips/compat-signal.h62
-rw-r--r--include/asm-mips/compat.h3
-rw-r--r--include/asm-mips/cpu-features.h4
-rw-r--r--include/asm-mips/cpu.h21
-rw-r--r--include/asm-mips/div64.h9
-rw-r--r--include/asm-mips/gpio.h6
-rw-r--r--include/asm-mips/io.h11
-rw-r--r--include/asm-mips/irq.h11
-rw-r--r--include/asm-mips/lasat/ds1603.h18
-rw-r--r--include/asm-mips/lasat/eeprom.h17
-rw-r--r--include/asm-mips/lasat/head.h22
-rw-r--r--include/asm-mips/lasat/lasat.h253
-rw-r--r--include/asm-mips/lasat/lasatint.h12
-rw-r--r--include/asm-mips/lasat/picvue.h15
-rw-r--r--include/asm-mips/lasat/serial.h13
-rw-r--r--include/asm-mips/mach-au1x00/au1xxx_gpio.h20
-rw-r--r--include/asm-mips/mach-au1x00/au1xxx_ide.h28
-rw-r--r--include/asm-mips/mach-au1x00/gpio.h69
-rw-r--r--include/asm-mips/mach-au1x00/ioremap.h11
-rw-r--r--include/asm-mips/mach-cobalt/cobalt.h5
-rw-r--r--include/asm-mips/mach-ev64120/mach-gt64120.h62
-rw-r--r--include/asm-mips/mach-generic/gpio.h15
-rw-r--r--include/asm-mips/mach-generic/ioremap.h11
-rw-r--r--include/asm-mips/mach-generic/spaces.h64
-rw-r--r--include/asm-mips/mach-ip22/spaces.h33
-rw-r--r--include/asm-mips/mach-ip27/spaces.h9
-rw-r--r--include/asm-mips/mach-ip32/dma-coherence.h6
-rw-r--r--include/asm-mips/mach-ip32/spaces.h36
-rw-r--r--include/asm-mips/mach-jmr3927/ioremap.h38
-rw-r--r--include/asm-mips/mach-lasat/mach-gt64120.h27
-rw-r--r--include/asm-mips/mach-lemote/dma-coherence.h42
-rw-r--r--include/asm-mips/mach-lemote/mc146818rtc.h36
-rw-r--r--include/asm-mips/mach-mips/kernel-entry-init.h52
-rw-r--r--include/asm-mips/mach-mipssim/cpu-feature-overrides.h (renamed from include/asm-mips/mach-sim/cpu-feature-overrides.h)0
-rw-r--r--include/asm-mips/mach-ocelot3/cpu-feature-overrides.h48
-rw-r--r--include/asm-mips/mach-tx49xx/ioremap.h43
-rw-r--r--include/asm-mips/mips-boards/atlasint.h6
-rw-r--r--include/asm-mips/mips-boards/bonito64.h7
-rw-r--r--include/asm-mips/mips-boards/generic.h22
-rw-r--r--include/asm-mips/mips-boards/maltaint.h6
-rw-r--r--include/asm-mips/mips-boards/msc01_pci.h1
-rw-r--r--include/asm-mips/mips-boards/prom.h1
-rw-r--r--include/asm-mips/mips-boards/seadint.h7
-rw-r--r--include/asm-mips/mips-boards/simint.h4
-rw-r--r--include/asm-mips/mipsregs.h61
-rw-r--r--include/asm-mips/module.h11
-rw-r--r--include/asm-mips/nile4.h310
-rw-r--r--include/asm-mips/page.h21
-rw-r--r--include/asm-mips/pci.h20
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h151
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_int.h43
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_pci.h205
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_prom.h176
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_regops.h236
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_regs.h667
-rw-r--r--include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h141
-rw-r--r--include/asm-mips/processor.h92
-rw-r--r--include/asm-mips/ptrace.h2
-rw-r--r--include/asm-mips/rtc.h73
-rw-r--r--include/asm-mips/serial.h155
-rw-r--r--include/asm-mips/smp.h7
-rw-r--r--include/asm-mips/sni.h3
-rw-r--r--include/asm-mips/stackframe.h52
-rw-r--r--include/asm-mips/system.h14
-rw-r--r--include/asm-mips/termbits.h11
-rw-r--r--include/asm-mips/tlbdebug.h4
-rw-r--r--include/asm-mips/tx4938/rbtx4938.h6
-rw-r--r--include/asm-mips/tx4938/spi.h56
-rw-r--r--include/asm-mips/unistd.h41
-rw-r--r--include/asm-mips/vr41xx/giu.h9
-rw-r--r--include/asm-mips/vr41xx/siu.h2
-rw-r--r--include/asm-mips/war.h31
-rw-r--r--include/asm-mips/watch.h35
-rw-r--r--include/asm-parisc/hardware.h5
-rw-r--r--include/asm-parisc/linkage.h5
-rw-r--r--include/asm-parisc/pci.h7
-rw-r--r--include/asm-parisc/processor.h8
-rw-r--r--include/asm-parisc/system.h1
-rw-r--r--include/asm-parisc/termbits.h11
-rw-r--r--include/asm-parisc/unistd.h13
-rw-r--r--include/asm-powerpc/dma-mapping.h1
-rw-r--r--include/asm-powerpc/irq.h5
-rw-r--r--include/asm-powerpc/pci.h20
-rw-r--r--include/asm-powerpc/pgalloc-64.h3
-rw-r--r--include/asm-powerpc/pgtable-ppc32.h12
-rw-r--r--include/asm-powerpc/pgtable-ppc64.h12
-rw-r--r--include/asm-powerpc/systbl.h1
-rw-r--r--include/asm-powerpc/tlb.h9
-rw-r--r--include/asm-powerpc/unistd.h3
-rw-r--r--include/asm-ppc/pci.h8
-rw-r--r--include/asm-ppc/pgtable.h12
-rw-r--r--include/asm-s390/atomic.h4
-rw-r--r--include/asm-s390/cmb.h1
-rw-r--r--include/asm-s390/pgtable.h7
-rw-r--r--include/asm-s390/processor.h9
-rw-r--r--include/asm-s390/ptrace.h9
-rw-r--r--include/asm-s390/sclp.h47
-rw-r--r--include/asm-s390/sfp-machine.h6
-rw-r--r--include/asm-s390/sfp-util.h11
-rw-r--r--include/asm-s390/termbits.h11
-rw-r--r--include/asm-sh/cpu-sh4/freq.h3
-rw-r--r--include/asm-sh/dma.h1
-rw-r--r--include/asm-sh/io.h6
-rw-r--r--include/asm-sh/pci.h9
-rw-r--r--include/asm-sh/se73180.h11
-rw-r--r--include/asm-sh/smp.h2
-rw-r--r--include/asm-sh/spinlock.h8
-rw-r--r--include/asm-sh/spinlock_types.h4
-rw-r--r--include/asm-sh/termbits.h11
-rw-r--r--include/asm-sh64/pci.h9
-rw-r--r--include/asm-sparc/pci.h6
-rw-r--r--include/asm-sparc/pgtable.h11
-rw-r--r--include/asm-sparc64/cpudata.h2
-rw-r--r--include/asm-sparc64/dma-mapping.h125
-rw-r--r--include/asm-sparc64/hypervisor.h181
-rw-r--r--include/asm-sparc64/irq.h1
-rw-r--r--include/asm-sparc64/mdesc.h1
-rw-r--r--include/asm-sparc64/parport.h5
-rw-r--r--include/asm-sparc64/pci.h47
-rw-r--r--include/asm-sparc64/smp.h2
-rw-r--r--include/asm-sparc64/tlb.h1
-rw-r--r--include/asm-sparc64/topology.h13
-rw-r--r--include/asm-um/a.out.h1
-rw-r--r--include/asm-um/bug.h2
-rw-r--r--include/asm-um/common.lds.S2
-rw-r--r--include/asm-um/paravirt.h6
-rw-r--r--include/asm-v850/pci.h4
-rw-r--r--include/asm-v850/rte_cb.h1
-rw-r--r--include/asm-v850/termbits.h11
-rw-r--r--include/asm-x86_64/alternative.h68
-rw-r--r--include/asm-x86_64/boot.h16
-rw-r--r--include/asm-x86_64/bootparam.h1
-rw-r--r--include/asm-x86_64/cpufeature.h115
-rw-r--r--include/asm-x86_64/e820.h4
-rw-r--r--include/asm-x86_64/pci.h44
-rw-r--r--include/asm-x86_64/pgtable.h14
-rw-r--r--include/asm-x86_64/processor.h3
-rw-r--r--include/asm-x86_64/required-features.h46
-rw-r--r--include/asm-x86_64/segment.h8
-rw-r--r--include/asm-x86_64/unistd.h4
-rw-r--r--include/asm-xtensa/bitops.h69
-rw-r--r--include/asm-xtensa/byteorder.h3
-rw-r--r--include/asm-xtensa/coprocessor.h8
-rw-r--r--include/asm-xtensa/div64.h15
-rw-r--r--include/asm-xtensa/elf.h3
-rw-r--r--include/asm-xtensa/fcntl.h100
-rw-r--r--include/asm-xtensa/mmu_context.h1
-rw-r--r--include/asm-xtensa/page.h2
-rw-r--r--include/asm-xtensa/param.h4
-rw-r--r--include/asm-xtensa/pci.h7
-rw-r--r--include/asm-xtensa/ptrace.h8
-rw-r--r--include/asm-xtensa/shmparam.h2
-rw-r--r--include/asm-xtensa/sigcontext.h24
-rw-r--r--include/asm-xtensa/termbits.h11
-rw-r--r--include/asm-xtensa/thread_info.h2
-rw-r--r--include/asm-xtensa/unistd.h4
-rw-r--r--include/linux/Kbuild5
-rw-r--r--include/linux/aer.h10
-rw-r--r--include/linux/async_tx.h156
-rw-r--r--include/linux/ata.h33
-rw-r--r--include/linux/blkdev.h5
-rw-r--r--include/linux/bootmem.h1
-rw-r--r--include/linux/console_struct.h5
-rw-r--r--include/linux/crypto.h20
-rw-r--r--include/linux/debugfs.h9
-rw-r--r--include/linux/device.h5
-rw-r--r--include/linux/dlm.h14
-rw-r--r--include/linux/dlm_device.h22
-rw-r--r--include/linux/dlm_netlink.h56
-rw-r--r--include/linux/dmaengine.h293
-rw-r--r--include/linux/dmi.h8
-rw-r--r--include/linux/edd.h4
-rw-r--r--include/linux/eeprom_93cx6.h72
-rw-r--r--include/linux/errno.h7
-rw-r--r--include/linux/etherdevice.h9
-rw-r--r--include/linux/ethtool.h1
-rw-r--r--include/linux/eventfd.h3
-rw-r--r--include/linux/ext4_fs.h33
-rw-r--r--include/linux/ext4_fs_extents.h5
-rw-r--r--include/linux/ext4_fs_i.h6
-rw-r--r--include/linux/fb.h1
-rw-r--r--include/linux/firewire-cdev.h311
-rw-r--r--include/linux/fs.h35
-rw-r--r--include/linux/futex.h9
-rw-r--r--include/linux/gfs2_ondisk.h142
-rw-r--r--include/linux/gpio_mouse.h61
-rw-r--r--include/linux/hardirq.h13
-rw-r--r--include/linux/hid.h56
-rw-r--r--include/linux/hugetlb.h4
-rw-r--r--include/linux/i2c.h19
-rw-r--r--include/linux/ide.h19
-rw-r--r--include/linux/idr.h29
-rw-r--r--include/linux/ieee80211.h11
-rw-r--r--include/linux/if_link.h47
-rw-r--r--include/linux/if_macvlan.h9
-rw-r--r--include/linux/if_ppp.h16
-rw-r--r--include/linux/if_pppol2tp.h69
-rw-r--r--include/linux/if_pppox.h16
-rw-r--r--include/linux/if_tun.h2
-rw-r--r--include/linux/if_vlan.h19
-rw-r--r--include/linux/inetdevice.h104
-rw-r--r--include/linux/input.h163
-rw-r--r--include/linux/ioprio.h6
-rw-r--r--include/linux/ip_mp_alg.h22
-rw-r--r--include/linux/ipv6.h13
-rw-r--r--include/linux/irda.h28
-rw-r--r--include/linux/kallsyms.h1
-rw-r--r--include/linux/kernel.h12
-rw-r--r--include/linux/kobject.h9
-rw-r--r--include/linux/ktime.h22
-rw-r--r--include/linux/libata.h53
-rw-r--r--include/linux/lockd/lockd.h1
-rw-r--r--include/linux/lzo.h44
-rw-r--r--include/linux/mlx4/cmd.h1
-rw-r--r--include/linux/mlx4/device.h15
-rw-r--r--include/linux/mlx4/qp.h7
-rw-r--r--include/linux/mm.h4
-rw-r--r--include/linux/mtd/super.h30
-rw-r--r--include/linux/mv643xx.h4
-rw-r--r--include/linux/netdevice.h178
-rw-r--r--include/linux/netfilter.h3
-rw-r--r--include/linux/netfilter/nf_conntrack_pptp.h2
-rw-r--r--include/linux/netfilter/x_tables.h36
-rw-r--r--include/linux/netfilter/xt_connlimit.h17
-rw-r--r--include/linux/netfilter/xt_u32.h40
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h20
-rw-r--r--include/linux/netfilter_ipv4/ipt_CLUSTERIP.h4
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h10
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs4_mount.h3
-rw-r--r--include/linux/nfs_fs.h28
-rw-r--r--include/linux/nfs_fs_sb.h8
-rw-r--r--include/linux/nfs_mount.h3
-rw-r--r--include/linux/nfs_page.h25
-rw-r--r--include/linux/nfs_xdr.h5
-rw-r--r--include/linux/pata_platform.h5
-rw-r--r--include/linux/pci.h28
-rw-r--r--include/linux/pci_ids.h88
-rw-r--r--include/linux/pda_power.h31
-rw-r--r--include/linux/pipe_fs_i.h147
-rw-r--r--include/linux/pkt_cls.h17
-rw-r--r--include/linux/pkt_sched.h9
-rw-r--r--include/linux/pm.h67
-rw-r--r--include/linux/power_supply.h180
-rw-r--r--include/linux/raid/raid5.h97
-rw-r--r--include/linux/raid/xor.h5
-rw-r--r--include/linux/rfkill.h2
-rw-r--r--include/linux/rtnetlink.h20
-rw-r--r--include/linux/sched.h252
-rw-r--r--include/linux/screen_info.h9
-rw-r--r--include/linux/security.h17
-rw-r--r--include/linux/seq_file.h11
-rw-r--r--include/linux/serial_core.h1
-rw-r--r--include/linux/serio.h1
-rw-r--r--include/linux/skbuff.h71
-rw-r--r--include/linux/slab.h4
-rw-r--r--include/linux/slub_def.h38
-rw-r--r--include/linux/sm501-regs.h8
-rw-r--r--include/linux/socket.h1
-rw-r--r--include/linux/spi/spi.h20
-rw-r--r--include/linux/splice.h73
-rw-r--r--include/linux/sunrpc/auth.h48
-rw-r--r--include/linux/sunrpc/auth_gss.h6
-rw-r--r--include/linux/sunrpc/clnt.h33
-rw-r--r--include/linux/sunrpc/gss_api.h2
-rw-r--r--include/linux/sunrpc/rpc_pipe_fs.h2
-rw-r--r--include/linux/sunrpc/sched.h6
-rw-r--r--include/linux/sunrpc/svc.h2
-rw-r--r--include/linux/sunrpc/svcsock.h1
-rw-r--r--include/linux/sunrpc/xprt.h16
-rw-r--r--include/linux/syscalls.h2
-rw-r--r--include/linux/sysdev.h3
-rw-r--r--include/linux/sysfs.h43
-rw-r--r--include/linux/topology.h14
-rw-r--r--include/linux/udp.h6
-rw-r--r--include/linux/usb.h85
-rw-r--r--include/linux/usb/Kbuild1
-rw-r--r--include/linux/usb/gadgetfs.h (renamed from include/linux/usb_gadgetfs.h)24
-rw-r--r--include/linux/usb/quirks.h3
-rw-r--r--include/linux/usb/serial.h7
-rw-r--r--include/linux/usb_gadget.h48
-rw-r--r--include/linux/videodev2.h7
-rw-r--r--include/linux/wait.h16
-rw-r--r--include/net/9p/9p.h417
-rw-r--r--include/net/9p/client.h80
-rw-r--r--include/net/9p/conn.h (renamed from fs/9p/mux.h)42
-rw-r--r--include/net/9p/transport.h (renamed from fs/9p/transport.h)28
-rw-r--r--include/net/act_api.h32
-rw-r--r--include/net/addrconf.h2
-rw-r--r--include/net/af_unix.h11
-rw-r--r--include/net/ax88796.h27
-rw-r--r--include/net/bluetooth/hci.h18
-rw-r--r--include/net/bluetooth/hci_core.h5
-rw-r--r--include/net/bluetooth/rfcomm.h1
-rw-r--r--include/net/cfg80211.h38
-rw-r--r--include/net/cipso_ipv4.h20
-rw-r--r--include/net/dn.h1
-rw-r--r--include/net/dst.h1
-rw-r--r--include/net/fib_rules.h2
-rw-r--r--include/net/flow.h4
-rw-r--r--include/net/genetlink.h2
-rw-r--r--include/net/inet_timewait_sock.h3
-rw-r--r--include/net/ip.h1
-rw-r--r--include/net/ip_fib.h18
-rw-r--r--include/net/ip_mp_alg.h96
-rw-r--r--include/net/ipv6.h4
-rw-r--r--include/net/irda/irda.h3
-rw-r--r--include/net/irda/irlap.h19
-rw-r--r--include/net/iucv/af_iucv.h1
-rw-r--r--include/net/mac80211.h22
-rw-r--r--include/net/mip6.h4
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h25
-rw-r--r--include/net/netfilter/ipv6/nf_conntrack_ipv6.h2
-rw-r--r--include/net/netfilter/nf_conntrack.h70
-rw-r--r--include/net/netfilter/nf_conntrack_core.h11
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h17
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h42
-rw-r--r--include/net/netfilter/nf_conntrack_extend.h85
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h16
-rw-r--r--include/net/netfilter/nf_conntrack_l3proto.h10
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h78
-rw-r--r--include/net/netfilter/nf_nat.h28
-rw-r--r--include/net/netfilter/nf_nat_core.h1
-rw-r--r--include/net/netlabel.h14
-rw-r--r--include/net/netlink.h96
-rw-r--r--include/net/pkt_cls.h10
-rw-r--r--include/net/pkt_sched.h4
-rw-r--r--include/net/rawv6.h9
-rw-r--r--include/net/route.h3
-rw-r--r--include/net/rtnetlink.h58
-rw-r--r--include/net/sch_generic.h2
-rw-r--r--include/net/sctp/sctp.h7
-rw-r--r--include/net/sctp/structs.h7
-rw-r--r--include/net/sock.h2
-rw-r--r--include/net/tcp.h6
-rw-r--r--include/net/tipc/tipc_port.h6
-rw-r--r--include/net/udp.h9
-rw-r--r--include/net/udplite.h2
-rw-r--r--include/net/xfrm.h28
-rw-r--r--include/pcmcia/ciscode.h2
-rw-r--r--include/rdma/ib_cm.h1
-rw-r--r--include/rdma/ib_mad.h3
-rw-r--r--include/sound/version.h4
-rw-r--r--init/Kconfig2
-rw-r--r--init/main.c5
-rw-r--r--ipc/compat.c2
-rw-r--r--ipc/shm.c15
-rw-r--r--kernel/auditfilter.c2
-rw-r--r--kernel/cpuset.c2
-rw-r--r--kernel/delayacct.c10
-rw-r--r--kernel/exit.c29
-rw-r--r--kernel/fork.c4
-rw-r--r--kernel/futex.c668
-rw-r--r--kernel/futex_compat.c8
-rw-r--r--kernel/module.c9
-rw-r--r--kernel/nsproxy.c10
-rw-r--r--kernel/params.c1
-rw-r--r--kernel/posix-cpu-timers.c34
-rw-r--r--kernel/posix-timers.c35
-rw-r--r--kernel/power/main.c6
-rw-r--r--kernel/power/user.c4
-rw-r--r--kernel/relay.c218
-rw-r--r--kernel/rtmutex.c65
-rw-r--r--kernel/rtmutex_common.h34
-rw-r--r--kernel/sched.c3136
-rw-r--r--kernel/sched_debug.c275
-rw-r--r--kernel/sched_fair.c1131
-rw-r--r--kernel/sched_idletask.c71
-rw-r--r--kernel/sched_rt.c255
-rw-r--r--kernel/sched_stats.h235
-rw-r--r--kernel/signal.c24
-rw-r--r--kernel/softirq.c1
-rw-r--r--kernel/sysctl.c90
-rw-r--r--kernel/time/ntp.c2
-rw-r--r--kernel/time/timer_stats.c44
-rw-r--r--lib/Kconfig6
-rw-r--r--lib/Kconfig.debug14
-rw-r--r--lib/Makefile2
-rw-r--r--lib/hexdump.c149
-rw-r--r--lib/idr.c332
-rw-r--r--lib/kobject.c29
-rw-r--r--lib/lzo/Makefile5
-rw-r--r--lib/lzo/lzo1x_compress.c226
-rw-r--r--lib/lzo/lzo1x_decompress.c254
-rw-r--r--lib/lzo/lzodefs.h43
-rw-r--r--lib/radix-tree.c1
-rw-r--r--mm/filemap.c21
-rw-r--r--mm/filemap_xip.c22
-rw-r--r--mm/hugetlb.c7
-rw-r--r--mm/memory.c13
-rw-r--r--mm/memory_hotplug.c2
-rw-r--r--mm/mmap.c13
-rw-r--r--mm/mremap.c13
-rw-r--r--mm/nommu.c2
-rw-r--r--mm/page_alloc.c4
-rw-r--r--mm/rmap.c24
-rw-r--r--mm/shmem.c44
-rw-r--r--mm/slab.c35
-rw-r--r--mm/slub.c85
-rw-r--r--mm/sparse.c53
-rw-r--r--mm/vmstat.c2
-rw-r--r--net/802/tr.c2
-rw-r--r--net/8021q/Makefile2
-rw-r--r--net/8021q/vlan.c503
-rw-r--r--net/8021q/vlan.h25
-rw-r--r--net/8021q/vlan_dev.c378
-rw-r--r--net/8021q/vlan_netlink.c243
-rw-r--r--net/8021q/vlanproc.c6
-rw-r--r--net/9p/Kconfig21
-rw-r--r--net/9p/Makefile13
-rw-r--r--net/9p/client.c965
-rw-r--r--net/9p/conv.c (renamed from fs/9p/conv.c)424
-rw-r--r--net/9p/error.c (renamed from fs/9p/error.h)79
-rw-r--r--net/9p/fcprint.c (renamed from fs/9p/fcprint.c)187
-rw-r--r--net/9p/mod.c85
-rw-r--r--net/9p/mux.c (renamed from fs/9p/mux.c)515
-rw-r--r--net/9p/sysctl.c86
-rw-r--r--net/9p/trans_fd.c363
-rw-r--r--net/9p/util.c125
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile2
-rw-r--r--net/appletalk/aarp.c2
-rw-r--r--net/appletalk/atalk_proc.c6
-rw-r--r--net/atm/br2684.c24
-rw-r--r--net/atm/clip.c2
-rw-r--r--net/atm/lec.c2
-rw-r--r--net/atm/mpoa_proc.c2
-rw-r--r--net/atm/proc.c10
-rw-r--r--net/ax25/af_ax25.c2
-rw-r--r--net/ax25/ax25_route.c2
-rw-r--r--net/ax25/ax25_uid.c2
-rw-r--r--net/bluetooth/hci_conn.c51
-rw-r--r--net/bluetooth/hci_core.c100
-rw-r--r--net/bluetooth/hci_event.c29
-rw-r--r--net/bluetooth/hidp/core.c18
-rw-r--r--net/bluetooth/rfcomm/tty.c34
-rw-r--r--net/bridge/br_fdb.c14
-rw-r--r--net/bridge/br_if.c10
-rw-r--r--net/bridge/br_stp.c3
-rw-r--r--net/bridge/br_stp_timer.c2
-rw-r--r--net/bridge/br_sysfs_br.c8
-rw-r--r--net/bridge/br_sysfs_if.c3
-rw-r--r--net/bridge/netfilter/ebtables.c4
-rw-r--r--net/core/dev.c435
-rw-r--r--net/core/dev_mcast.c198
-rw-r--r--net/core/dst.c17
-rw-r--r--net/core/ethtool.c12
-rw-r--r--net/core/gen_estimator.c3
-rw-r--r--net/core/neighbour.c4
-rw-r--r--net/core/netevent.c1
-rw-r--r--net/core/netpoll.c44
-rw-r--r--net/core/pktgen.c249
-rw-r--r--net/core/rtnetlink.c476
-rw-r--r--net/core/skbuff.c21
-rw-r--r--net/core/sock.c44
-rw-r--r--net/core/sysctl_net_core.c9
-rw-r--r--net/core/utils.c6
-rw-r--r--net/dccp/ccids/ccid3.c212
-rw-r--r--net/dccp/ccids/ccid3.h5
-rw-r--r--net/dccp/ccids/lib/loss_interval.c246
-rw-r--r--net/dccp/ccids/lib/loss_interval.h46
-rw-r--r--net/dccp/dccp.h4
-rw-r--r--net/dccp/ipv6.c20
-rw-r--r--net/dccp/probe.c2
-rw-r--r--net/decnet/af_decnet.c2
-rw-r--r--net/decnet/dn_dev.c7
-rw-r--r--net/decnet/dn_neigh.c2
-rw-r--r--net/decnet/dn_route.c2
-rw-r--r--net/decnet/dn_rules.c2
-rw-r--r--net/ethernet/eth.c12
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c32
-rw-r--r--net/ipv4/Kconfig42
-rw-r--r--net/ipv4/Makefile5
-rw-r--r--net/ipv4/af_inet.c3
-rw-r--r--net/ipv4/ah4.c1
-rw-r--r--net/ipv4/arp.c13
-rw-r--r--net/ipv4/cipso_ipv4.c64
-rw-r--r--net/ipv4/datagram.c6
-rw-r--r--net/ipv4/devinet.c415
-rw-r--r--net/ipv4/esp4.c1
-rw-r--r--net/ipv4/fib_frontend.c17
-rw-r--r--net/ipv4/fib_rules.c2
-rw-r--r--net/ipv4/fib_semantics.c16
-rw-r--r--net/ipv4/icmp.c15
-rw-r--r--net/ipv4/igmp.c18
-rw-r--r--net/ipv4/inet_connection_sock.c4
-rw-r--r--net/ipv4/inet_timewait_sock.c5
-rw-r--r--net/ipv4/ip_gre.c3
-rw-r--r--net/ipv4/ip_output.c10
-rw-r--r--net/ipv4/ipcomp.c1
-rw-r--r--net/ipv4/ipip.c3
-rw-r--r--net/ipv4/ipmr.c23
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_conn.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_ctl.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c41
-rw-r--r--net/ipv4/multipath.c55
-rw-r--r--net/ipv4/multipath_drr.c249
-rw-r--r--net/ipv4/multipath_random.c114
-rw-r--r--net/ipv4/multipath_rr.c95
-rw-r--r--net/ipv4/multipath_wrandom.c329
-rw-r--r--net/ipv4/netfilter/Kconfig2
-rw-r--r--net/ipv4/netfilter/arp_tables.c8
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c10
-rw-r--r--net/ipv4/netfilter/ip_tables.c258
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c118
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c36
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c56
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c30
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c23
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c20
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c30
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c69
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c8
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c14
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c68
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c14
-rw-r--r--net/ipv4/netfilter/ipt_ah.c25
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c59
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c50
-rw-r--r--net/ipv4/netfilter/ipt_owner.c20
-rw-r--r--net/ipv4/netfilter/ipt_recent.c45
-rw-r--r--net/ipv4/netfilter/ipt_tos.c6
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c26
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c74
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c112
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c71
-rw-r--r--net/ipv4/netfilter/nf_nat_amanda.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c127
-rw-r--r--net/ipv4/netfilter/nf_nat_ftp.c18
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c121
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c59
-rw-r--r--net/ipv4/netfilter/nf_nat_irc.c17
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c43
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_gre.c17
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c48
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c18
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c47
-rw-r--r--net/ipv4/netfilter/nf_nat_tftp.c2
-rw-r--r--net/ipv4/proc.c2
-rw-r--r--net/ipv4/route.c275
-rw-r--r--net/ipv4/sysctl_net_ipv4.c6
-rw-r--r--net/ipv4/tcp.c42
-rw-r--r--net/ipv4/tcp_bic.c2
-rw-r--r--net/ipv4/tcp_cubic.c2
-rw-r--r--net/ipv4/tcp_illinois.c3
-rw-r--r--net/ipv4/tcp_input.c26
-rw-r--r--net/ipv4/tcp_ipv4.c29
-rw-r--r--net/ipv4/tcp_lp.c3
-rw-r--r--net/ipv4/tcp_output.c8
-rw-r--r--net/ipv4/tcp_probe.c194
-rw-r--r--net/ipv4/tcp_timer.c8
-rw-r--r--net/ipv4/tcp_vegas.c3
-rw-r--r--net/ipv4/tcp_veno.c3
-rw-r--r--net/ipv4/udp.c386
-rw-r--r--net/ipv4/udp_impl.h6
-rw-r--r--net/ipv4/udplite.c7
-rw-r--r--net/ipv4/xfrm4_input.c120
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c2
-rw-r--r--net/ipv4/xfrm4_tunnel.c1
-rw-r--r--net/ipv6/Kconfig2
-rw-r--r--net/ipv6/Makefile2
-rw-r--r--net/ipv6/addrconf.c48
-rw-r--r--net/ipv6/af_inet6.c10
-rw-r--r--net/ipv6/ah6.c15
-rw-r--r--net/ipv6/anycast.c2
-rw-r--r--net/ipv6/datagram.c5
-rw-r--r--net/ipv6/esp6.c1
-rw-r--r--net/ipv6/exthdrs.c140
-rw-r--r--net/ipv6/fib6_rules.c2
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/ip6_fib.c9
-rw-r--r--net/ipv6/ip6_flowlabel.c2
-rw-r--r--net/ipv6/ip6_output.c6
-rw-r--r--net/ipv6/ip6_tunnel.c4
-rw-r--r--net/ipv6/ipcomp6.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c15
-rw-r--r--net/ipv6/mcast.c4
-rw-r--r--net/ipv6/mip6.c24
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c202
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c14
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c57
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c45
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c82
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c20
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c111
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c88
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c22
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c22
-rw-r--r--net/ipv6/netfilter/ip6t_mh.c30
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c26
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c134
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c6
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c6
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c59
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c61
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c52
-rw-r--r--net/ipv6/raw.c40
-rw-r--r--net/ipv6/route.c2
-rw-r--r--net/ipv6/sit.c3
-rw-r--r--net/ipv6/tcp_ipv6.c22
-rw-r--r--net/ipv6/udp.c21
-rw-r--r--net/ipv6/udp_impl.h2
-rw-r--r--net/ipv6/udplite.c2
-rw-r--r--net/ipv6/xfrm6_input.c6
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c1
-rw-r--r--net/ipv6/xfrm6_policy.c4
-rw-r--r--net/ipv6/xfrm6_state.c4
-rw-r--r--net/ipv6/xfrm6_tunnel.c1
-rw-r--r--net/ipx/ipx_proc.c6
-rw-r--r--net/irda/Makefile2
-rw-r--r--net/irda/discovery.c2
-rw-r--r--net/irda/ircomm/ircomm_core.c2
-rw-r--r--net/irda/iriap.c2
-rw-r--r--net/irda/irlan/irlan_common.c2
-rw-r--r--net/irda/irlap.c2
-rw-r--r--net/irda/irlap_event.c28
-rw-r--r--net/irda/irlap_frame.c10
-rw-r--r--net/irda/irlmp.c2
-rw-r--r--net/irda/irmod.c48
-rw-r--r--net/irda/irnetlink.c170
-rw-r--r--net/irda/irttp.c31
-rw-r--r--net/iucv/Kconfig8
-rw-r--r--net/iucv/af_iucv.c16
-rw-r--r--net/iucv/iucv.c5
-rw-r--r--net/key/af_key.c10
-rw-r--r--net/llc/llc_proc.c4
-rw-r--r--net/mac80211/debugfs.c2
-rw-r--r--net/mac80211/debugfs_netdev.c2
-rw-r--r--net/mac80211/hostapd_ioctl.h8
-rw-r--r--net/mac80211/ieee80211.c455
-rw-r--r--net/mac80211/ieee80211_common.h9
-rw-r--r--net/mac80211/ieee80211_i.h14
-rw-r--r--net/mac80211/ieee80211_iface.c3
-rw-r--r--net/mac80211/ieee80211_ioctl.c265
-rw-r--r--net/mac80211/ieee80211_sta.c114
-rw-r--r--net/mac80211/rc80211_simple.c20
-rw-r--r--net/netfilter/Kconfig42
-rw-r--r--net/netfilter/Makefile6
-rw-r--r--net/netfilter/core.c10
-rw-r--r--net/netfilter/nf_conntrack_amanda.c29
-rw-r--r--net/netfilter/nf_conntrack_core.c558
-rw-r--r--net/netfilter/nf_conntrack_ecache.c16
-rw-r--r--net/netfilter/nf_conntrack_expect.c371
-rw-r--r--net/netfilter/nf_conntrack_extend.c195
-rw-r--r--net/netfilter/nf_conntrack_ftp.c143
-rw-r--r--net/netfilter/nf_conntrack_h323_asn1.c22
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c307
-rw-r--r--net/netfilter/nf_conntrack_helper.c133
-rw-r--r--net/netfilter/nf_conntrack_irc.c39
-rw-r--r--net/netfilter/nf_conntrack_l3proto_generic.c22
-rw-r--r--net/netfilter/nf_conntrack_netbios_ns.c12
-rw-r--r--net/netfilter/nf_conntrack_netlink.c211
-rw-r--r--net/netfilter/nf_conntrack_pptp.c120
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c32
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c99
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c133
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c4
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c266
-rw-r--r--net/netfilter/nf_conntrack_sane.c45
-rw-r--r--net/netfilter/nf_conntrack_sip.c40
-rw-r--r--net/netfilter/nf_conntrack_standalone.c47
-rw-r--r--net/netfilter/nf_conntrack_tftp.c32
-rw-r--r--net/netfilter/nf_log.c2
-rw-r--r--net/netfilter/nf_queue.c59
-rw-r--r--net/netfilter/nfnetlink_log.c2
-rw-r--r--net/netfilter/nfnetlink_queue.c6
-rw-r--r--net/netfilter/x_tables.c11
-rw-r--r--net/netfilter/xt_CLASSIFY.c2
-rw-r--r--net/netfilter/xt_CONNMARK.c18
-rw-r--r--net/netfilter/xt_CONNSECMARK.c18
-rw-r--r--net/netfilter/xt_DSCP.c18
-rw-r--r--net/netfilter/xt_MARK.c24
-rw-r--r--net/netfilter/xt_NFLOG.c12
-rw-r--r--net/netfilter/xt_NFQUEUE.c2
-rw-r--r--net/netfilter/xt_NOTRACK.c2
-rw-r--r--net/netfilter/xt_SECMARK.c26
-rw-r--r--net/netfilter/xt_TCPMSS.c28
-rw-r--r--net/netfilter/xt_TRACE.c53
-rw-r--r--net/netfilter/xt_comment.c8
-rw-r--r--net/netfilter/xt_connbytes.c32
-rw-r--r--net/netfilter/xt_connlimit.c313
-rw-r--r--net/netfilter/xt_connmark.c26
-rw-r--r--net/netfilter/xt_conntrack.c42
-rw-r--r--net/netfilter/xt_dccp.c50
-rw-r--r--net/netfilter/xt_dscp.c48
-rw-r--r--net/netfilter/xt_esp.c24
-rw-r--r--net/netfilter/xt_hashlimit.c65
-rw-r--r--net/netfilter/xt_helper.c61
-rw-r--r--net/netfilter/xt_length.c14
-rw-r--r--net/netfilter/xt_limit.c23
-rw-r--r--net/netfilter/xt_mac.c16
-rw-r--r--net/netfilter/xt_mark.c16
-rw-r--r--net/netfilter/xt_multiport.c54
-rw-r--r--net/netfilter/xt_physdev.c48
-rw-r--r--net/netfilter/xt_pkttype.c10
-rw-r--r--net/netfilter/xt_policy.c50
-rw-r--r--net/netfilter/xt_quota.c21
-rw-r--r--net/netfilter/xt_realm.c8
-rw-r--r--net/netfilter/xt_sctp.c61
-rw-r--r--net/netfilter/xt_state.c20
-rw-r--r--net/netfilter/xt_statistic.c20
-rw-r--r--net/netfilter/xt_string.c38
-rw-r--r--net/netfilter/xt_tcpmss.c10
-rw-r--r--net/netfilter/xt_tcpudp.c63
-rw-r--r--net/netfilter/xt_u32.c135
-rw-r--r--net/netlabel/netlabel_cipso_v4.c2
-rw-r--r--net/netlabel/netlabel_kapi.c43
-rw-r--r--net/netlabel/netlabel_mgmt.c2
-rw-r--r--net/netlabel/netlabel_unlabeled.c2
-rw-r--r--net/netlink/af_netlink.c2
-rw-r--r--net/netlink/attr.c19
-rw-r--r--net/netlink/genetlink.c2
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/netrom/nr_route.c4
-rw-r--r--net/packet/af_packet.c58
-rw-r--r--net/rfkill/rfkill-input.c2
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/rose/rose_route.c6
-rw-r--r--net/rxrpc/ar-connection.c2
-rw-r--r--net/rxrpc/ar-output.c5
-rw-r--r--net/rxrpc/ar-proc.c52
-rw-r--r--net/sched/Kconfig31
-rw-r--r--net/sched/Makefile1
-rw-r--r--net/sched/act_api.c23
-rw-r--r--net/sched/act_gact.c11
-rw-r--r--net/sched/act_ipt.c12
-rw-r--r--net/sched/act_mirred.c12
-rw-r--r--net/sched/act_pedit.c14
-rw-r--r--net/sched/act_police.c278
-rw-r--r--net/sched/act_simple.c1
-rw-r--r--net/sched/cls_api.c50
-rw-r--r--net/sched/cls_basic.c1
-rw-r--r--net/sched/cls_fw.c19
-rw-r--r--net/sched/cls_route.c20
-rw-r--r--net/sched/cls_rsvp.c17
-rw-r--r--net/sched/cls_rsvp6.c16
-rw-r--r--net/sched/cls_tcindex.c3
-rw-r--r--net/sched/cls_u32.c21
-rw-r--r--net/sched/em_cmp.c1
-rw-r--r--net/sched/em_meta.c2
-rw-r--r--net/sched/em_nbyte.c2
-rw-r--r--net/sched/em_text.c2
-rw-r--r--net/sched/em_u32.c2
-rw-r--r--net/sched/ematch.c15
-rw-r--r--net/sched/sch_api.c91
-rw-r--r--net/sched/sch_atm.c480
-rw-r--r--net/sched/sch_blackhole.c1
-rw-r--r--net/sched/sch_cbq.c90
-rw-r--r--net/sched/sch_dsmark.c35
-rw-r--r--net/sched/sch_fifo.c1
-rw-r--r--net/sched/sch_generic.c222
-rw-r--r--net/sched/sch_gred.c1
-rw-r--r--net/sched/sch_hfsc.c24
-rw-r--r--net/sched/sch_htb.c126
-rw-r--r--net/sched/sch_ingress.c28
-rw-r--r--net/sched/sch_netem.c2
-rw-r--r--net/sched/sch_prio.c145
-rw-r--r--net/sched/sch_red.c1
-rw-r--r--net/sched/sch_sfq.c18
-rw-r--r--net/sched/sch_tbf.c21
-rw-r--r--net/sched/sch_teql.c24
-rw-r--r--net/sctp/associola.c4
-rw-r--r--net/sctp/debug.c8
-rw-r--r--net/sctp/input.c24
-rw-r--r--net/sctp/ipv6.c4
-rw-r--r--net/sctp/proc.c4
-rw-r--r--net/sctp/sm_statetable.c2
-rw-r--r--net/sctp/socket.c163
-rw-r--r--net/sctp/transport.c39
-rw-r--r--net/sunrpc/auth.c370
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c349
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c2
-rw-r--r--net/sunrpc/auth_gss/gss_spkm3_mech.c2
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c2
-rw-r--r--net/sunrpc/auth_null.c10
-rw-r--r--net/sunrpc/auth_unix.c54
-rw-r--r--net/sunrpc/cache.c2
-rw-r--r--net/sunrpc/clnt.c371
-rw-r--r--net/sunrpc/rpc_pipe.c80
-rw-r--r--net/sunrpc/rpcb_clnt.c65
-rw-r--r--net/sunrpc/sched.c209
-rw-r--r--net/sunrpc/sunrpc_syms.c8
-rw-r--r--net/sunrpc/svc.c2
-rw-r--r--net/sunrpc/svcsock.c20
-rw-r--r--net/sunrpc/xprt.c19
-rw-r--r--net/sunrpc/xprtsock.c81
-rw-r--r--net/tipc/eth_media.c11
-rw-r--r--net/tipc/link.c16
-rw-r--r--net/tipc/netlink.c2
-rw-r--r--net/tipc/port.c10
-rw-r--r--net/tipc/port.h6
-rw-r--r--net/tipc/socket.c80
-rw-r--r--net/unix/af_unix.c148
-rw-r--r--net/unix/garbage.c325
-rw-r--r--net/wanrouter/wanmain.c2
-rw-r--r--net/wanrouter/wanproc.c4
-rw-r--r--net/wireless/Makefile2
-rw-r--r--net/wireless/radiotap.c257
-rw-r--r--net/wireless/sysfs.c2
-rw-r--r--net/x25/x25_proc.c6
-rw-r--r--net/xfrm/xfrm_policy.c66
-rw-r--r--net/xfrm/xfrm_state.c94
-rw-r--r--net/xfrm/xfrm_user.c9
-rw-r--r--scripts/Makefile.headersinst2
-rwxr-xr-xscripts/checkpatch.pl982
-rwxr-xr-xscripts/checksyscalls.sh5
-rw-r--r--scripts/mod/modpost.c2
-rw-r--r--security/dummy.c6
-rw-r--r--security/security.c1
-rw-r--r--security/selinux/avc.c12
-rw-r--r--security/selinux/hooks.c21
-rw-r--r--security/selinux/include/av_perm_to_string.h1
-rw-r--r--security/selinux/include/av_permissions.h1
-rw-r--r--security/selinux/include/avc.h6
-rw-r--r--security/selinux/include/class_to_string.h1
-rw-r--r--security/selinux/include/flask.h1
-rw-r--r--security/selinux/include/security.h4
-rw-r--r--security/selinux/netlabel.c36
-rw-r--r--security/selinux/selinuxfs.c269
-rw-r--r--security/selinux/ss/policydb.c7
-rw-r--r--security/selinux/ss/services.c144
-rw-r--r--sound/arm/pxa2xx-ac97.c2
-rw-r--r--sound/arm/sa11xx-uda1341.c2
-rw-r--r--sound/drivers/mts64.c2
-rw-r--r--sound/isa/opl3sa2.c2
-rw-r--r--sound/oss/emu10k1/main.c2
-rw-r--r--sound/oss/es1371.c2
-rw-r--r--sound/oss/sb_card.c2
-rw-r--r--sound/pci/ali5451/ali5451.c8
-rw-r--r--sound/pci/atiixp.c6
-rw-r--r--sound/pci/atiixp_modem.c5
-rw-r--r--sound/pci/au88x0/au88x0.c6
-rw-r--r--sound/pci/ca0106/ca0106.h1
-rw-r--r--sound/pci/ca0106/ca0106_main.c5
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c4
-rw-r--r--sound/pci/emu10k1/emu10k1x.c2
-rw-r--r--sound/pci/ens1370.c4
-rw-r--r--sound/pci/fm801.c4
-rw-r--r--sound/pci/hda/hda_codec.c13
-rw-r--r--sound/pci/hda/hda_local.h2
-rw-r--r--sound/pci/hda/patch_conexant.c48
-rw-r--r--sound/pci/hda/patch_realtek.c5
-rw-r--r--sound/pci/hda/patch_si3054.c2
-rw-r--r--sound/pci/hda/patch_sigmatel.c64
-rw-r--r--sound/pci/ice1712/prodigy192.c2
-rw-r--r--sound/pci/via82xx.c14
-rw-r--r--sound/pci/via82xx_modem.c4
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c2
-rw-r--r--sound/ppc/beep.c10
-rw-r--r--sound/ppc/pmac.c8
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c2
3266 files changed, 136610 insertions, 151182 deletions
diff --git a/CREDITS b/CREDITS
index 273d72b610c..79fd13dbb8e 100644
--- a/CREDITS
+++ b/CREDITS
@@ -3301,14 +3301,6 @@ S: 12725 SW Millikan Way, Suite 400
S: Beaverton, Oregon 97005
S: USA
-N: Li Yang
-E: leoli@freescale.com
-D: Freescale Highspeed USB device driver
-D: Freescale QE SoC support and Ethernet driver
-S: B-1206 Jingmao Guojigongyu
-S: 16 Baliqiao Nanjie, Beijing 101100
-S: People's Repulic of China
-
N: Marcelo Tosatti
E: marcelo@kvack.org
D: v2.4 kernel maintainer
@@ -3726,6 +3718,14 @@ S: 542 West 112th Street, 5N
S: New York, New York 10025
S: USA
+N: Li Yang
+E: leoli@freescale.com
+D: Freescale Highspeed USB device driver
+D: Freescale QE SoC support and Ethernet driver
+S: B-1206 Jingmao Guojigongyu
+S: 16 Baliqiao Nanjie, Beijing 101100
+S: People's Repulic of China
+
N: Victor Yodaiken
E: yodaiken@fsmlabs.com
D: RTLinux (RealTime Linux)
diff --git a/Documentation/ABI/removed/raw1394_legacy_isochronous b/Documentation/ABI/removed/raw1394_legacy_isochronous
new file mode 100644
index 00000000000..1b629622d88
--- /dev/null
+++ b/Documentation/ABI/removed/raw1394_legacy_isochronous
@@ -0,0 +1,16 @@
+What: legacy isochronous ABI of raw1394 (1st generation iso ABI)
+Date: June 2007 (scheduled), removed in kernel v2.6.23
+Contact: linux1394-devel@lists.sourceforge.net
+Description:
+ The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
+ been deprecated for quite some time. They are very inefficient as they
+ come with high interrupt load and several layers of callbacks for each
+ packet. Because of these deficiencies, the video1394 and dv1394 drivers
+ and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
+
+Users:
+ libraw1394 users via the long deprecated API raw1394_iso_write,
+ raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
+
+ libdc1394, which optionally uses these old libraw1394 calls
+ alternatively to the more efficient video1394 ABI
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index f9937add033..9734577d171 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -39,3 +39,16 @@ Description:
If you want to suspend a device immediately but leave it
free to wake up in response to I/O requests, you should
write "0" to power/autosuspend.
+
+What: /sys/bus/usb/devices/.../power/persist
+Date: May 2007
+KernelVersion: 2.6.23
+Contact: Alan Stern <stern@rowland.harvard.edu>
+Description:
+ If CONFIG_USB_PERSIST is set, then each USB device directory
+ will contain a file named power/persist. The file holds a
+ boolean value (0 or 1) indicating whether or not the
+ "USB-Persist" facility is enabled for the device. Since the
+ facility is inherently dangerous, it is disabled by default
+ for all devices except hubs. For more information, see
+ Documentation/usb/persist.txt.
diff --git a/Documentation/BUG-HUNTING b/Documentation/BUG-HUNTING
index 65b97e1dbf7..35f5bd24333 100644
--- a/Documentation/BUG-HUNTING
+++ b/Documentation/BUG-HUNTING
@@ -191,6 +191,30 @@ e.g. crash dump output as shown by Dave Miller.
> mov 0x8(%ebp), %ebx ! %ebx = skb->sk
> mov 0x13c(%ebx), %eax ! %eax = inet_sk(sk)->opt
+In addition, you can use GDB to figure out the exact file and line
+number of the OOPS from the vmlinux file. If you have
+CONFIG_DEBUG_INFO enabled, you can simply copy the EIP value from the
+OOPS:
+
+ EIP: 0060:[<c021e50e>] Not tainted VLI
+
+And use GDB to translate that to human-readable form:
+
+ gdb vmlinux
+ (gdb) l *0xc021e50e
+
+If you don't have CONFIG_DEBUG_INFO enabled, you use the function
+offset from the OOPS:
+
+ EIP is at vt_ioctl+0xda8/0x1482
+
+And recompile the kernel with CONFIG_DEBUG_INFO enabled:
+
+ make vmlinux
+ gdb vmlinux
+ (gdb) p vt_ioctl
+ (gdb) l *(0x<address of vt_ioctl> + 0xda8)
+
Another very useful option of the Kernel Hacking section in menuconfig is
Debug memory allocations. This will help you see whether data has been
initialised and not set before use etc. To see the values that get assigned
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt
index 028614cdd06..e07f2530326 100644
--- a/Documentation/DMA-mapping.txt
+++ b/Documentation/DMA-mapping.txt
@@ -664,109 +664,6 @@ It is that simple.
Well, not for some odd devices. See the next section for information
about that.
- DAC Addressing for Address Space Hungry Devices
-
-There exists a class of devices which do not mesh well with the PCI
-DMA mapping API. By definition these "mappings" are a finite
-resource. The number of total available mappings per bus is platform
-specific, but there will always be a reasonable amount.
-
-What is "reasonable"? Reasonable means that networking and block I/O
-devices need not worry about using too many mappings.
-
-As an example of a problematic device, consider compute cluster cards.
-They can potentially need to access gigabytes of memory at once via
-DMA. Dynamic mappings are unsuitable for this kind of access pattern.
-
-To this end we've provided a small API by which a device driver
-may use DAC cycles to directly address all of physical memory.
-Not all platforms support this, but most do. It is easy to determine
-whether the platform will work properly at probe time.
-
-First, understand that there may be a SEVERE performance penalty for
-using these interfaces on some platforms. Therefore, you MUST only
-use these interfaces if it is absolutely required. %99 of devices can
-use the normal APIs without any problems.
-
-Note that for streaming type mappings you must either use these
-interfaces, or the dynamic mapping interfaces above. You may not mix
-usage of both for the same device. Such an act is illegal and is
-guaranteed to put a banana in your tailpipe.
-
-However, consistent mappings may in fact be used in conjunction with
-these interfaces. Remember that, as defined, consistent mappings are
-always going to be SAC addressable.
-
-The first thing your driver needs to do is query the PCI platform
-layer if it is capable of handling your devices DAC addressing
-capabilities:
-
- int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
-
-You may not use the following interfaces if this routine fails.
-
-Next, DMA addresses using this API are kept track of using the
-dma64_addr_t type. It is guaranteed to be big enough to hold any
-DAC address the platform layer will give to you from the following
-routines. If you have consistent mappings as well, you still
-use plain dma_addr_t to keep track of those.
-
-All mappings obtained here will be direct. The mappings are not
-translated, and this is the purpose of this dialect of the DMA API.
-
-All routines work with page/offset pairs. This is the _ONLY_ way to
-portably refer to any piece of memory. If you have a cpu pointer
-(which may be validly DMA'd too) you may easily obtain the page
-and offset using something like this:
-
- struct page *page = virt_to_page(ptr);
- unsigned long offset = offset_in_page(ptr);
-
-Here are the interfaces:
-
- dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
- struct page *page,
- unsigned long offset,
- int direction);
-
-The DAC address for the tuple PAGE/OFFSET are returned. The direction
-argument is the same as for pci_{map,unmap}_single(). The same rules
-for cpu/device access apply here as for the streaming mapping
-interfaces. To reiterate:
-
- The cpu may touch the buffer before pci_dac_page_to_dma.
- The device may touch the buffer after pci_dac_page_to_dma
- is made, but the cpu may NOT.
-
-When the DMA transfer is complete, invoke:
-
- void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
- dma64_addr_t dma_addr,
- size_t len, int direction);
-
-This must be done before the CPU looks at the buffer again.
-This interface behaves identically to pci_dma_sync_{single,sg}_for_cpu().
-
-And likewise, if you wish to let the device get back at the buffer after
-the cpu has read/written it, invoke:
-
- void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
- dma64_addr_t dma_addr,
- size_t len, int direction);
-
-before letting the device access the DMA area again.
-
-If you need to get back to the PAGE/OFFSET tuple from a dma64_addr_t
-the following interfaces are provided:
-
- struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
- dma64_addr_t dma_addr);
- unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
- dma64_addr_t dma_addr);
-
-This is possible with the DAC interfaces purely because they are
-not translated in any way.
-
Optimizing Unmap State Space Consumption
On many platforms, pci_unmap_{single,page}() is simply a nop.
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 38f88b6ae40..46bcff2849b 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -643,4 +643,70 @@ X!Idrivers/video/console/fonts.c
!Edrivers/spi/spi.c
</chapter>
+ <chapter id="i2c">
+ <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
+
+ <para>
+ I<superscript>2</superscript>C (or without fancy typography, "I2C")
+ is an acronym for the "Inter-IC" bus, a simple bus protocol which is
+ widely used where low data rate communications suffice.
+ Since it's also a licensed trademark, some vendors use another
+ name (such as "Two-Wire Interface", TWI) for the same bus.
+ I2C only needs two signals (SCL for clock, SDA for data), conserving
+ board real estate and minimizing signal quality issues.
+ Most I2C devices use seven bit addresses, and bus speeds of up
+ to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
+ found wide use.
+ I2C is a multi-master bus; open drain signaling is used to
+ arbitrate between masters, as well as to handshake and to
+ synchronize clocks from slower clients.
+ </para>
+
+ <para>
+ The Linux I2C programming interfaces support only the master
+ side of bus interactions, not the slave side.
+ The programming interface is structured around two kinds of driver,
+ and two kinds of device.
+ An I2C "Adapter Driver" abstracts the controller hardware; it binds
+ to a physical device (perhaps a PCI device or platform_device) and
+ exposes a <structname>struct i2c_adapter</structname> representing
+ each I2C bus segment it manages.
+ On each I2C bus segment will be I2C devices represented by a
+ <structname>struct i2c_client</structname>. Those devices will
+ be bound to a <structname>struct i2c_driver</structname>,
+ which should follow the standard Linux driver model.
+ (At this writing, a legacy model is more widely used.)
+ There are functions to perform various I2C protocol operations; at
+ this writing all such functions are usable only from task context.
+ </para>
+
+ <para>
+ The System Management Bus (SMBus) is a sibling protocol. Most SMBus
+ systems are also I2C conformant. The electrical constraints are
+ tighter for SMBus, and it standardizes particular protocol messages
+ and idioms. Controllers that support I2C can also support most
+ SMBus operations, but SMBus controllers don't support all the protocol
+ options that an I2C controller will.
+ There are functions to perform various SMBus protocol operations,
+ either using I2C primitives or by issuing SMBus commands to
+ i2c_adapter devices which don't support those I2C operations.
+ </para>
+
+!Iinclude/linux/i2c.h
+!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
+!Edrivers/i2c/i2c-core.c
+ </chapter>
+
+ <chapter id="splice">
+ <title>splice API</title>
+ <para>)
+ splice is a method for moving blocks of data around inside the
+ kernel, without continually transferring it between the kernel
+ and user space.
+ </para>
+!Iinclude/linux/splice.h
+!Ffs/splice.c
+ </chapter>
+
+
</book>
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index ced9207bedc..98e2701c746 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -322,39 +322,34 @@ kernel releases as described above.
Here is a list of some of the different kernel trees available:
git trees:
- Kbuild development tree, Sam Ravnborg <sam@ravnborg.org>
- kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
+ git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
- ACPI development tree, Len Brown <len.brown@intel.com>
- kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
+ git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
- Block development tree, Jens Axboe <axboe@suse.de>
- kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
+ git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
- DRM development tree, Dave Airlie <airlied@linux.ie>
- kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+ git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
- ia64 development tree, Tony Luck <tony.luck@intel.com>
- kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
-
- - ieee1394 development tree, Jody McIntyre <scjody@modernduck.com>
- kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
+ git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
- infiniband, Roland Dreier <rolandd@cisco.com>
- kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
+ git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
- libata, Jeff Garzik <jgarzik@pobox.com>
- kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
+ git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
- network drivers, Jeff Garzik <jgarzik@pobox.com>
- kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
+ git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
- pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
- kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
+ git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
- SCSI, James Bottomley <James.Bottomley@SteelEye.com>
- kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
-
- Other git kernel trees can be found listed at http://kernel.org/git
+ git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
quilt trees:
- USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
@@ -362,6 +357,9 @@ Here is a list of some of the different kernel trees available:
- x86-64, partly i386, Andi Kleen <ak@suse.de>
ftp.firstfloor.org:/pub/ak/x86_64/quilt/
+ Other kernel trees can be found listed at http://git.kernel.org/ and in
+ the MAINTAINERS file.
+
Bug Reporting
-------------
diff --git a/Documentation/SM501.txt b/Documentation/SM501.txt
new file mode 100644
index 00000000000..3a1bd95d376
--- /dev/null
+++ b/Documentation/SM501.txt
@@ -0,0 +1,66 @@
+ SM501 Driver
+ ============
+
+Copyright 2006, 2007 Simtec Electronics
+
+Core
+----
+
+The core driver in drivers/mfd provides common services for the
+drivers which manage the specific hardware blocks. These services
+include locking for common registers, clock control and resource
+management.
+
+The core registers drivers for both PCI and generic bus based
+chips via the platform device and driver system.
+
+On detection of a device, the core initialises the chip (which may
+be specified by the platform data) and then exports the selected
+peripheral set as platform devices for the specific drivers.
+
+The core re-uses the platform device system as the platform device
+system provides enough features to support the drivers without the
+need to create a new bus-type and the associated code to go with it.
+
+
+Resources
+---------
+
+Each peripheral has a view of the device which is implicitly narrowed to
+the specific set of resources that peripheral requires in order to
+function correctly.
+
+The centralised memory allocation allows the driver to ensure that the
+maximum possible resource allocation can be made to the video subsystem
+as this is by-far the most resource-sensitive of the on-chip functions.
+
+The primary issue with memory allocation is that of moving the video
+buffers once a display mode is chosen. Indeed when a video mode change
+occurs the memory footprint of the video subsystem changes.
+
+Since video memory is difficult to move without changing the display
+(unless sufficient contiguous memory can be provided for the old and new
+modes simultaneously) the video driver fully utilises the memory area
+given to it by aligning fb0 to the start of the area and fb1 to the end
+of it. Any memory left over in the middle is used for the acceleration
+functions, which are transient and thus their location is less critical
+as it can be moved.
+
+
+Configuration
+-------------
+
+The platform device driver uses a set of platform data to pass
+configurations through to the core and the subsidiary drivers
+so that there can be support for more than one system carrying
+an SM501 built into a single kernel image.
+
+The PCI driver assumes that the PCI card behaves as per the Silicon
+Motion reference design.
+
+There is an errata (AB-5) affecting the selection of the
+of the M1XCLK and M1CLK frequencies. These two clocks
+must be sourced from the same PLL, although they can then
+be divided down individually. If this is not set, then SM501 may
+lock and hang the whole system. The driver will refuse to
+attach if the PLL selection is different.
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 3af3e65cf43..6ebffb57e3d 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -84,3 +84,9 @@ kernel patches.
24: Avoid whitespace damage such as indenting with spaces or whitespace
at the end of lines. You can test this by feeding the patch to
"git apply --check --whitespace=error-all"
+
+25: Check your patch for general style as detailed in
+ Documentation/CodingStyle. Check for trivial violations with the
+ patch style checker prior to submission (scripts/checkpatch.pl).
+ You should be able to justify all violations that remain in
+ your patch.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index a417b25fb1a..0958e97d4bf 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -118,7 +118,20 @@ then only post say 15 or so at a time and wait for review and integration.
-4) Select e-mail destination.
+4) Style check your changes.
+
+Check your patch for basic style violations, details of which can be
+found in Documentation/CodingStyle. Failure to do so simply wastes
+the reviewers time and will get your patch rejected, probabally
+without even being read.
+
+At a minimum you should check your patches with the patch style
+checker prior to submission (scripts/patchcheck.pl). You should
+be able to justify all violations that remain in your patch.
+
+
+
+5) Select e-mail destination.
Look through the MAINTAINERS file and the source code, and determine
if your change applies to a specific subsystem of the kernel, with
@@ -146,7 +159,7 @@ discussed should the patch then be submitted to Linus.
-5) Select your CC (e-mail carbon copy) list.
+6) Select your CC (e-mail carbon copy) list.
Unless you have a reason NOT to do so, CC linux-kernel@vger.kernel.org.
@@ -187,8 +200,7 @@ URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
-
-6) No MIME, no links, no compression, no attachments. Just plain text.
+7) No MIME, no links, no compression, no attachments. Just plain text.
Linus and other kernel developers need to be able to read and comment
on the changes you are submitting. It is important for a kernel
@@ -223,9 +235,9 @@ pref("mailnews.display.disable_format_flowed_support", true);
-7) E-mail size.
+8) E-mail size.
-When sending patches to Linus, always follow step #6.
+When sending patches to Linus, always follow step #7.
Large changes are not appropriate for mailing lists, and some
maintainers. If your patch, uncompressed, exceeds 40 kB in size,
@@ -234,7 +246,7 @@ server, and provide instead a URL (link) pointing to your patch.
-8) Name your kernel version.
+9) Name your kernel version.
It is important to note, either in the subject line or in the patch
description, the kernel version to which this patch applies.
@@ -244,7 +256,7 @@ Linus will not apply it.
-9) Don't get discouraged. Re-submit.
+10) Don't get discouraged. Re-submit.
After you have submitted your change, be patient and wait. If Linus
likes your change and applies it, it will appear in the next version
@@ -270,7 +282,7 @@ When in doubt, solicit comments on linux-kernel mailing list.
-10) Include PATCH in the subject
+11) Include PATCH in the subject
Due to high e-mail traffic to Linus, and to linux-kernel, it is common
convention to prefix your subject line with [PATCH]. This lets Linus
@@ -279,7 +291,7 @@ e-mail discussions.
-11) Sign your work
+12) Sign your work
To improve tracking of who did what, especially with patches that can
percolate to their final resting place in the kernel through several
@@ -328,7 +340,32 @@ now, but you can do this to mark internal company procedures or just
point out some special detail about the sign-off.
-12) The canonical patch format
+13) When to use Acked-by:
+
+The Signed-off-by: tag indicates that the signer was involved in the
+development of the patch, or that he/she was in the patch's delivery path.
+
+If a person was not directly involved in the preparation or handling of a
+patch but wishes to signify and record their approval of it then they can
+arrange to have an Acked-by: line added to the patch's changelog.
+
+Acked-by: is often used by the maintainer of the affected code when that
+maintainer neither contributed to nor forwarded the patch.
+
+Acked-by: is not as formal as Signed-off-by:. It is a record that the acker
+has at least reviewed the patch and has indicated acceptance. Hence patch
+mergers will sometimes manually convert an acker's "yep, looks good to me"
+into an Acked-by:.
+
+Acked-by: does not necessarily indicate acknowledgement of the entire patch.
+For example, if a patch affects multiple subsystems and has an Acked-by: from
+one subsystem maintainer then this usually indicates acknowledgement of just
+the part which affects that maintainer's code. Judgement should be used here.
+ When in doubt people should refer to the original discussion in the mailing
+list archives.
+
+
+14) The canonical patch format
The canonical patch subject line is:
@@ -427,6 +464,10 @@ section Linus Computer Science 101.
Nuff said. If your code deviates too much from this, it is likely
to be rejected without further review, and without comment.
+Check your patches with the patch style checker prior to submission
+(scripts/checkpatch.pl). You should be able to justify all
+violations that remain in your patch.
+
2) #ifdefs are ugly
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt
index 2a63d5662a9..05851e9982e 100644
--- a/Documentation/atomic_ops.txt
+++ b/Documentation/atomic_ops.txt
@@ -149,7 +149,7 @@ defined which accomplish this:
void smp_mb__before_atomic_dec(void);
void smp_mb__after_atomic_dec(void);
void smp_mb__before_atomic_inc(void);
- void smp_mb__after_atomic_dec(void);
+ void smp_mb__after_atomic_inc(void);
For example, smp_mb__before_atomic_dec() can be used like so:
diff --git a/Documentation/blackfin/kgdb.txt b/Documentation/blackfin/kgdb.txt
new file mode 100644
index 00000000000..84f6a484ae9
--- /dev/null
+++ b/Documentation/blackfin/kgdb.txt
@@ -0,0 +1,155 @@
+ A Simple Guide to Configure KGDB
+
+ Sonic Zhang <sonic.zhang@analog.com>
+ Aug. 24th 2006
+
+
+This KGDB patch enables the kernel developer to do source level debugging on
+the kernel for the Blackfin architecture. The debugging works over either the
+ethernet interface or one of the uarts. Both software breakpoints and
+hardware breakpoints are supported in this version.
+http://docs.blackfin.uclinux.org/doku.php?id=kgdb
+
+
+2 known issues:
+1. This bug:
+ http://blackfin.uclinux.org/tracker/index.php?func=detail&aid=544&group_id=18&atid=145
+ The GDB client for Blackfin uClinux causes incorrect values of local
+ variables to be displayed when the user breaks the running of kernel in GDB.
+2. Because of a hardware bug in Blackfin 533 v1.0.3:
+ 05000067 - Watchpoints (Hardware Breakpoints) are not supported
+ Hardware breakpoints cannot be set properly.
+
+
+Debug over Ethernet:
+
+1. Compile and install the cross platform version of gdb for blackfin, which
+ can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel. Select the menuconfig option under
+ "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+ With this selected, option "Full Symbolic/Source Debugging support" and
+ "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over (Ethernet)". Add "kgdboe=@target-IP/,@host-IP/" to
+ the option "Compiled-in Kernel Boot Parameter" under "Kernel hacking".
+
+4. Connect minicom to the serial port and boot the kernel image.
+
+5. Configure the IP "/> ifconfig eth0 target-IP"
+
+6. Start GDB client "bfin-elf-gdb vmlinux".
+
+7. Connect to the target "(gdb) target remote udp:target-IP:6443".
+
+8. Set software breakpoint "(gdb) break sys_open".
+
+9. Continue "(gdb) c".
+
+10. Run ls in the target console "/> ls".
+
+11. Breakpoint hits. "Breakpoint 1: sys_open(..."
+
+12. Display local variables and function paramters.
+ (*) This operation gives wrong results, see known issue 1.
+
+13. Single stepping "(gdb) si".
+
+14. Remove breakpoint 1. "(gdb) del 1"
+
+15. Set hardware breakpoint "(gdb) hbreak sys_open".
+
+16. Continue "(gdb) c".
+
+17. Run ls in the target console "/> ls".
+
+18. Hardware breakpoint hits. "Breakpoint 1: sys_open(...".
+ (*) This hardware breakpoint will not be hit, see known issue 2.
+
+19. Continue "(gdb) c".
+
+20. Interrupt the target in GDB "Ctrl+C".
+
+21. Detach from the target "(gdb) detach".
+
+22. Exit GDB "(gdb) quit".
+
+
+Debug over the UART:
+
+1. Compile and install the cross platform version of gdb for blackfin, which
+ can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel. Select the menuconfig option under
+ "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+ With this selected, option "Full Symbolic/Source Debugging support" and
+ "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over (UART)". Set "KGDB: UART port number" to be
+ a different one from the console. Don't forget to change the mode of
+ blackfin serial driver to PIO. Otherwise kgdb works incorrectly on UART.
+
+4. If you want connect to kgdb when the kernel boots, enable
+ "KGDB: Wait for gdb connection early"
+
+5. Compile kernel.
+
+6. Connect minicom to the serial port of the console and boot the kernel image.
+
+7. Start GDB client "bfin-elf-gdb vmlinux".
+
+8. Set the baud rate in GDB "(gdb) set remotebaud 57600".
+
+9. Connect to the target on the second serial port "(gdb) target remote /dev/ttyS1".
+
+10. Set software breakpoint "(gdb) break sys_open".
+
+11. Continue "(gdb) c".
+
+12. Run ls in the target console "/> ls".
+
+13. A breakpoint is hit. "Breakpoint 1: sys_open(..."
+
+14. All other operations are the same as that in KGDB over Ethernet.
+
+
+Debug over the same UART as console:
+
+1. Compile and install the cross platform version of gdb for blackfin, which
+ can be found at $(BINROOT)/bfin-elf-gdb.
+
+2. Apply this patch to the 2.6.x kernel. Select the menuconfig option under
+ "Kernel hacking" -> "Kernel debugging" -> "KGDB: kernel debug with remote gdb".
+ With this selected, option "Full Symbolic/Source Debugging support" and
+ "Compile the kernel with frame pointers" are also selected.
+
+3. Select option "KGDB: connect over UART". Set "KGDB: UART port number" to console.
+ Don't forget to change the mode of blackfin serial driver to PIO.
+ Otherwise kgdb works incorrectly on UART.
+
+4. If you want connect to kgdb when the kernel boots, enable
+ "KGDB: Wait for gdb connection early"
+
+5. Connect minicom to the serial port and boot the kernel image.
+
+6. (Optional) Ask target to wait for gdb connection by entering Ctrl+A. In minicom, you should enter Ctrl+A+A.
+
+7. Start GDB client "bfin-elf-gdb vmlinux".
+
+8. Set the baud rate in GDB "(gdb) set remotebaud 57600".
+
+9. Connect to the target "(gdb) target remote /dev/ttyS0".
+
+10. Set software breakpoint "(gdb) break sys_open".
+
+11. Continue "(gdb) c". Then enter Ctrl+C twice to stop GDB connection.
+
+12. Run ls in the target console "/> ls". Dummy string can be seen on the console.
+
+13. Then connect the gdb to target again. "(gdb) target remote /dev/ttyS0".
+ Now you will find a breakpoint is hit. "Breakpoint 1: sys_open(..."
+
+14. All other operations are the same as that in KGDB over Ethernet. The only
+ difference is that after continue command in GDB, please stop GDB
+ connection by 2 "Ctrl+C"s and connect again after breakpoints are hit or
+ Ctrl+A is entered.
diff --git a/Documentation/block/barrier.txt b/Documentation/block/barrier.txt
index a272c3db809..7d279f2f5bb 100644
--- a/Documentation/block/barrier.txt
+++ b/Documentation/block/barrier.txt
@@ -82,23 +82,12 @@ including draining and flushing.
typedef void (prepare_flush_fn)(request_queue_t *q, struct request *rq);
int blk_queue_ordered(request_queue_t *q, unsigned ordered,
- prepare_flush_fn *prepare_flush_fn,
- unsigned gfp_mask);
-
-int blk_queue_ordered_locked(request_queue_t *q, unsigned ordered,
- prepare_flush_fn *prepare_flush_fn,
- unsigned gfp_mask);
-
-The only difference between the two functions is whether or not the
-caller is holding q->queue_lock on entry. The latter expects the
-caller is holding the lock.
+ prepare_flush_fn *prepare_flush_fn);
@q : the queue in question
@ordered : the ordered mode the driver/device supports
@prepare_flush_fn : this function should prepare @rq such that it
flushes cache to physical medium when executed
-@gfp_mask : gfp_mask used when allocating data structures
- for ordered processing
For example, SCSI disk driver's prepare_flush_fn looks like the
following.
@@ -106,9 +95,10 @@ following.
static void sd_prepare_flush(request_queue_t *q, struct request *rq)
{
memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->flags |= REQ_BLOCK_PC;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->timeout = SD_TIMEOUT;
rq->cmd[0] = SYNCHRONIZE_CACHE;
+ rq->cmd_len = 10;
}
The following seven ordered modes are supported. The following table
diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
index 19c4a6e1367..2a97320ee17 100644
--- a/Documentation/driver-model/platform.txt
+++ b/Documentation/driver-model/platform.txt
@@ -96,6 +96,46 @@ System setup also associates those clocks with the device, so that that
calls to clk_get(&pdev->dev, clock_name) return them as needed.
+Legacy Drivers: Device Probing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some drivers are not fully converted to the driver model, because they take
+on a non-driver role: the driver registers its platform device, rather than
+leaving that for system infrastructure. Such drivers can't be hotplugged
+or coldplugged, since those mechanisms require device creation to be in a
+different system component than the driver.
+
+The only "good" reason for this is to handle older system designs which, like
+original IBM PCs, rely on error-prone "probe-the-hardware" models for hardware
+configuration. Newer systems have largely abandoned that model, in favor of
+bus-level support for dynamic configuration (PCI, USB), or device tables
+provided by the boot firmware (e.g. PNPACPI on x86). There are too many
+conflicting options about what might be where, and even educated guesses by
+an operating system will be wrong often enough to make trouble.
+
+This style of driver is discouraged. If you're updating such a driver,
+please try to move the device enumeration to a more appropriate location,
+outside the driver. This will usually be cleanup, since such drivers
+tend to already have "normal" modes, such as ones using device nodes that
+were created by PNP or by platform device setup.
+
+None the less, there are some APIs to support such legacy drivers. Avoid
+using these calls except with such hotplug-deficient drivers.
+
+ struct platform_device *platform_device_alloc(
+ char *name, unsigned id);
+
+You can use platform_device_alloc() to dynamically allocate a device, which
+you will then initialize with resources and platform_device_register().
+A better solution is usually:
+
+ struct platform_device *platform_device_register_simple(
+ char *name, unsigned id,
+ struct resource *res, unsigned nres);
+
+You can use platform_device_register_simple() as a one-step call to allocate
+and register a device.
+
+
Device Naming and Driver Binding
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The platform_device.dev.bus_id is the canonical name for the devices.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 2d7ea85075b..092c65dd35c 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -49,16 +49,6 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
-What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
-When: June 2007
-Why: Deprecated in favour of the more efficient and robust rawiso interface.
- Affected are applications which use the deprecated part of libraw1394
- (raw1394_iso_write, raw1394_start_iso_write, raw1394_start_iso_rcv,
- raw1394_stop_iso_rcv) or bypass libraw1394.
-Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
-
----------------------------
-
What: old NCR53C9x driver
When: October 2007
Why: Replaced by the much better esp_scsi driver. Actual low-level
@@ -70,6 +60,7 @@ Who: David Miller <davem@davemloft.net>
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
When: December 2006
+Files: include/linux/video_decoder.h
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
series. The old API have lots of drawbacks and don't provide enough
means to work with all video and audio standards. The newer API is
@@ -103,6 +94,7 @@ Who: Dominik Brodowski <linux@brodo.de>
What: remove EXPORT_SYMBOL(kernel_thread)
When: August 2006
Files: arch/*/kernel/*_ksyms.c
+Funcs: kernel_thread
Why: kernel_thread is a low-level implementation detail. Drivers should
use the <linux/kthread.h> API instead which shields them from
implementation details and provides a higherlevel interface that
@@ -204,28 +196,6 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
-What: ACPI hooks (X86_SPEEDSTEP_CENTRINO_ACPI) in speedstep-centrino driver
-When: December 2006
-Why: Speedstep-centrino driver with ACPI hooks and acpi-cpufreq driver are
- functionally very much similar. They talk to ACPI in same way. Only
- difference between them is the way they do frequency transitions.
- One uses MSRs and the other one uses IO ports. Functionaliy of
- speedstep_centrino with ACPI hooks is now merged into acpi-cpufreq.
- That means one common driver will support all Intel Enhanced Speedstep
- capable CPUs. That means less confusion over name of
- speedstep-centrino driver (with that driver supposed to be used on
- non-centrino platforms). That means less duplication of code and
- less maintenance effort and no possibility of these two drivers
- going out of sync.
- Current users of speedstep_centrino with ACPI hooks are requested to
- switch over to acpi-cpufreq driver. speedstep-centrino will continue
- to work using older non-ACPI static table based scheme even after this
- date.
-
-Who: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
-
----------------------------
-
What: /sys/firmware/acpi/namespace
When: 2.6.21
Why: The ACPI namespace is effectively the symbol list for
@@ -256,14 +226,6 @@ Who: Len Brown <len.brown@intel.com>
---------------------------
-What: sk98lin network driver
-When: July 2007
-Why: In kernel tree version of driver is unmaintained. Sk98lin driver
- replaced by the skge driver.
-Who: Stephen Hemminger <shemminger@osdl.org>
-
----------------------------
-
What: Compaq touchscreen device emulation
When: Oct 2007
Files: drivers/input/tsdev.c
@@ -278,25 +240,6 @@ Who: Richard Purdie <rpurdie@rpsys.net>
---------------------------
-What: Multipath cached routing support in ipv4
-When: in 2.6.23
-Why: Code was merged, then submitter immediately disappeared leaving
- us with no maintainer and lots of bugs. The code should not have
- been merged in the first place, and many aspects of it's
- implementation are blocking more critical core networking
- development. It's marked EXPERIMENTAL and no distribution
- enables it because it cause obscure crashes due to unfixable bugs
- (interfaces don't return errors so memory allocation can't be
- handled, calling contexts of these interfaces make handling
- errors impossible too because they get called after we've
- totally commited to creating a route object, for example).
- This problem has existed for years and no forward progress
- has ever been made, and nobody steps up to try and salvage
- this code, so we're going to finally just get rid of it.
-Who: David S. Miller <davem@davemloft.net>
-
----------------------------
-
What: read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
When: December 2007
Why: These functions are a leftover from 2.4 times. They have several
@@ -346,3 +289,18 @@ Who: Tejun Heo <htejun@gmail.com>
---------------------------
+What: Legacy RTC drivers (under drivers/i2c/chips)
+When: November 2007
+Why: Obsolete. We have a RTC subsystem with better drivers.
+Who: Jean Delvare <khali@linux-fr.org>
+
+---------------------------
+
+What: iptables SAME target
+When: 1.1. 2008
+Files: net/ipv4/netfilter/ipt_SAME.c, include/linux/netfilter_ipv4/ipt_SAME.h
+Why: Obsolete for multiple years now, NAT core provides the same behaviour.
+ Unfixable broken wrt. 32/64 bit cleanness.
+Who: Patrick McHardy <kaber@trash.net>
+
+---------------------------
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 6dd050878a2..145e4408635 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -94,10 +94,10 @@ largest node numbers in the range. For example, mpol=bind:0-3,5,7,9-15
Note that trying to mount a tmpfs with an mpol option will fail if the
running kernel does not support NUMA; and will fail if its nodelist
-specifies a node >= MAX_NUMNODES. If your system relies on that tmpfs
-being mounted, but from time to time runs a kernel built without NUMA
-capability (perhaps a safe recovery kernel), or configured to support
-fewer nodes, then it is advisable to omit the mpol option from automatic
+specifies a node which is not online. If your system relies on that
+tmpfs being mounted, but from time to time runs a kernel built without
+NUMA capability (perhaps a safe recovery kernel), or with fewer nodes
+online, then it is advisable to omit the mpol option from automatic
mount options. It can be added later, when the tmpfs is already mounted
on MountPoint, by 'mount -o remount,mpol=Policy:NodeList MountPoint'.
@@ -121,4 +121,4 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
Author:
Christoph Rohland <cr@sap.com>, 1.12.01
Updated:
- Hugh Dickins <hugh@veritas.com>, 19 February 2006
+ Hugh Dickins <hugh@veritas.com>, 4 June 2007
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README
index e9cc8bb26f7..c3480aa66ba 100644
--- a/Documentation/firmware_class/README
+++ b/Documentation/firmware_class/README
@@ -1,7 +1,7 @@
request_firmware() hotplug interface:
------------------------------------
- Copyright (C) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ Copyright (C) 2003 Manuel Estrada Sainz
Why:
---
diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c
index 87feccdb5c9..6865cbe075e 100644
--- a/Documentation/firmware_class/firmware_sample_driver.c
+++ b/Documentation/firmware_class/firmware_sample_driver.c
@@ -1,7 +1,7 @@
/*
* firmware_sample_driver.c -
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* Sample code on how to use request_firmware() from drivers.
*
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
index 9e1b0e4051c..fba943aacf9 100644
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c
@@ -1,7 +1,7 @@
/*
* firmware_sample_firmware_class.c -
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* NOTE: This is just a probe of concept, if you think that your driver would
* be well served by this mechanism please contact me first.
@@ -19,7 +19,7 @@
#include <linux/firmware.h>
-MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
+MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
MODULE_LICENSE("GPL");
@@ -78,6 +78,7 @@ static CLASS_DEVICE_ATTR(loading, 0644,
firmware_loading_show, firmware_loading_store);
static ssize_t firmware_data_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct class_device *class_dev = to_class_dev(kobj);
@@ -88,6 +89,7 @@ static ssize_t firmware_data_read(struct kobject *kobj,
return count;
}
static ssize_t firmware_data_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct class_device *class_dev = to_class_dev(kobj);
diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
index 27f782e3593..22b0814d0ad 100644
--- a/Documentation/hrtimer/timer_stats.txt
+++ b/Documentation/hrtimer/timer_stats.txt
@@ -2,9 +2,10 @@ timer_stats - timer usage statistics
------------------------------------
timer_stats is a debugging facility to make the timer (ab)usage in a Linux
-system visible to kernel and userspace developers. It is not intended for
-production usage as it adds significant overhead to the (hr)timer code and the
-(hr)timer data structures.
+system visible to kernel and userspace developers. If enabled in the config
+but not used it has almost zero runtime overhead, and a relatively small
+data structure overhead. Even if collection is enabled runtime all the
+locking is per-CPU and lookup is hashed.
timer_stats should be used by kernel and userspace developers to verify that
their code does not make unduly use of timers. This helps to avoid unnecessary
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index c34f0db78a3..fe6406f2f9a 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -5,8 +5,8 @@ Supported adapters:
'810' and '810E' chipsets)
* Intel 82801BA (ICH2 - part of the '815E' chipset)
* Intel 82801CA/CAM (ICH3)
- * Intel 82801DB (ICH4) (HW PEC supported, 32 byte buffer not supported)
- * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
+ * Intel 82801DB (ICH4) (HW PEC supported)
+ * Intel 82801EB/ER (ICH5) (HW PEC supported)
* Intel 6300ESB
* Intel 82801FB/FR/FW/FRW (ICH6)
* Intel 82801G (ICH7)
diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
index 7cbe43fa270..fa0c786a8bf 100644
--- a/Documentation/i2c/busses/i2c-piix4
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -6,7 +6,7 @@ Supported adapters:
Datasheet: Publicly available at the Intel website
* ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
Datasheet: Only available via NDA from ServerWorks
- * ATI IXP200, IXP300, IXP400 and SB600 southbridges
+ * ATI IXP200, IXP300, IXP400, SB600 and SB700 southbridges
Datasheet: Not publicly available
* Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
Datasheet: Publicly available at the SMSC website http://www.smsc.com
diff --git a/Documentation/i2c/busses/i2c-taos-evm b/Documentation/i2c/busses/i2c-taos-evm
new file mode 100644
index 00000000000..9146e33be6d
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-taos-evm
@@ -0,0 +1,46 @@
+Kernel driver i2c-taos-evm
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+This is a driver for the evaluation modules for TAOS I2C/SMBus chips.
+The modules include an SMBus master with limited capabilities, which can
+be controlled over the serial port. Virtually all evaluation modules
+are supported, but a few lines of code need to be added for each new
+module to instantiate the right I2C chip on the bus. Obviously, a driver
+for the chip in question is also needed.
+
+Currently supported devices are:
+
+* TAOS TSL2550 EVM
+
+For addtional information on TAOS products, please see
+ http://www.taosinc.com/
+
+
+Using this driver
+-----------------
+
+In order to use this driver, you'll need the serport driver, and the
+inputattach tool, which is part of the input-utils package. The following
+commands will tell the kernel that you have a TAOS EVM on the first
+serial port:
+
+# modprobe serport
+# inputattach --taos-evm /dev/ttyS0
+
+
+Technical details
+-----------------
+
+Only 4 SMBus transaction types are supported by the TAOS evaluation
+modules:
+* Receive Byte
+* Send Byte
+* Read Byte
+* Write Byte
+
+The communication protocol is text-based and pretty simple. It is
+described in a PDF document on the CD which comes with the evaluation
+module. The communication is rather slow, because the serial port has
+to operate at 1200 bps. However, I don't think this is a big concern in
+practice, as these modules are meant for evaluation and testing only.
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
index 96fec562a8e..a0cd8af2f40 100644
--- a/Documentation/i2c/chips/max6875
+++ b/Documentation/i2c/chips/max6875
@@ -99,7 +99,7 @@ And then read the data
or
- count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
+ count = i2c_smbus_read_i2c_block_data(fd, 0x84, 16, buffer);
The block read should read 16 bytes.
0x84 is the block read command.
diff --git a/Documentation/i2c/chips/x1205 b/Documentation/i2c/chips/x1205
deleted file mode 100644
index 09407c991fe..00000000000
--- a/Documentation/i2c/chips/x1205
+++ /dev/null
@@ -1,38 +0,0 @@
-Kernel driver x1205
-===================
-
-Supported chips:
- * Xicor X1205 RTC
- Prefix: 'x1205'
- Addresses scanned: none
- Datasheet: http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
-
-Authors:
- Karen Spearel <kas11@tampabay.rr.com>,
- Alessandro Zummo <a.zummo@towertech.it>
-
-Description
------------
-
-This module aims to provide complete access to the Xicor X1205 RTC.
-Recently Xicor has merged with Intersil, but the chip is
-still sold under the Xicor brand.
-
-This chip is located at address 0x6f and uses a 2-byte register addressing.
-Two bytes need to be written to read a single register, while most
-other chips just require one and take the second one as the data
-to be written. To prevent corrupting unknown chips, the user must
-explicitely set the probe parameter.
-
-example:
-
-modprobe x1205 probe=0,0x6f
-
-The module supports one more option, hctosys, which is used to set the
-software clock from the x1205. On systems where the x1205 is the
-only hardware rtc, this parameter could be used to achieve a correct
-date/time earlier in the system boot sequence.
-
-example:
-
-modprobe x1205 probe=0,0x6f hctosys=1
diff --git a/Documentation/i2c/summary b/Documentation/i2c/summary
index aea60bf7e8f..003c7319b8c 100644
--- a/Documentation/i2c/summary
+++ b/Documentation/i2c/summary
@@ -67,7 +67,6 @@ i2c-proc: The /proc/sys/dev/sensors interface for device (client) drivers
Algorithm drivers
-----------------
-i2c-algo-8xx: An algorithm for CPM's I2C device in Motorola 8xx processors (NOT BUILT BY DEFAULT)
i2c-algo-bit: A bit-banging algorithm
i2c-algo-pcf: A PCF 8584 style algorithm
i2c-algo-ibm_ocp: An algorithm for the I2C device in IBM 4xx processors (NOT BUILT BY DEFAULT)
@@ -81,6 +80,5 @@ i2c-pcf-epp: PCF8584 on a EPP parallel port (uses i2c-algo-pcf) (NOT mkpatch
i2c-philips-par: Philips style parallel port adapter (uses i2c-algo-bit)
i2c-adap-ibm_ocp: IBM 4xx processor I2C device (uses i2c-algo-ibm_ocp) (NOT BUILT BY DEFAULT)
i2c-pport: Primitive parallel port adapter (uses i2c-algo-bit)
-i2c-rpx: RPX board Motorola 8xx I2C device (uses i2c-algo-8xx) (NOT BUILT BY DEFAULT)
i2c-velleman: Velleman K8000 parallel port adapter (uses i2c-algo-bit)
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 3d8d36b0ad1..2c170032bf3 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -571,7 +571,7 @@ SMBus communication
u8 command, u8 length,
u8 *values);
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
- u8 command, u8 *values);
+ u8 command, u8 length, u8 *values);
These ones were removed in Linux 2.6.10 because they had no users, but could
be added back later if needed:
diff --git a/Documentation/i386/zero-page.txt b/Documentation/i386/zero-page.txt
index c04a421f4a7..75b3680c41e 100644
--- a/Documentation/i386/zero-page.txt
+++ b/Documentation/i386/zero-page.txt
@@ -37,6 +37,7 @@ Offset Type Description
0x1d0 unsigned long EFI memory descriptor map pointer
0x1d4 unsigned long EFI memory descriptor map size
0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb
+0x1e4 unsigned long Scratch field for the kernel setup code
0x1e8 char number of entries in E820MAP (below)
0x1e9 unsigned char number of entries in EDDBUF (below)
0x1ea unsigned char number of entries in EDD_MBR_SIG_BUFFER (below)
diff --git a/Documentation/ia64/aliasing-test.c b/Documentation/ia64/aliasing-test.c
index 3153167b41c..773a814d409 100644
--- a/Documentation/ia64/aliasing-test.c
+++ b/Documentation/ia64/aliasing-test.c
@@ -19,6 +19,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <linux/pci.h>
int sum;
@@ -34,13 +35,19 @@ int map_mem(char *path, off_t offset, size_t length, int touch)
return -1;
}
+ if (fnmatch("/proc/bus/pci/*", path, 0) == 0) {
+ rc = ioctl(fd, PCIIOC_MMAP_IS_MEM);
+ if (rc == -1)
+ perror("PCIIOC_MMAP_IS_MEM ioctl");
+ }
+
addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
if (addr == MAP_FAILED)
return 1;
if (touch) {
c = (int *) addr;
- while (c < (int *) (offset + length))
+ while (c < (int *) (addr + length))
sum += *c++;
}
@@ -54,7 +61,7 @@ int map_mem(char *path, off_t offset, size_t length, int touch)
return 0;
}
-int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
+int scan_tree(char *path, char *file, off_t offset, size_t length, int touch)
{
struct dirent **namelist;
char *name, *path2;
@@ -93,7 +100,7 @@ int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
} else {
r = lstat(path2, &buf);
if (r == 0 && S_ISDIR(buf.st_mode)) {
- rc = scan_sysfs(path2, file, offset, length, touch);
+ rc = scan_tree(path2, file, offset, length, touch);
if (rc < 0)
return rc;
}
@@ -197,7 +204,7 @@ skip:
return rc;
}
-main()
+int main()
{
int rc;
@@ -238,10 +245,15 @@ main()
else
fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
- scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
- scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
- scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
- scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
+ scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
+ scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
+ scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
+ scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
scan_rom("/sys/devices", "rom");
+
+ scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1);
+ scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
+ scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
+ scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
}
diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt
index 9a431a7d0f5..aa3e953f0f7 100644
--- a/Documentation/ia64/aliasing.txt
+++ b/Documentation/ia64/aliasing.txt
@@ -112,6 +112,18 @@ POTENTIAL ATTRIBUTE ALIASING CASES
The /dev/mem mmap constraints apply.
+ mmap of /proc/bus/pci/.../??.?
+
+ This is an MMIO mmap of PCI functions, which additionally may or
+ may not be requested as using the WC attribute.
+
+ If WC is requested, and the region in kern_memmap is either WC
+ or UC, and the EFI memory map designates the region as WC, then
+ the WC mapping is allowed.
+
+ Otherwise, the user mapping must use the same attribute as the
+ kernel mapping.
+
read/write of /dev/mem
This uses copy_from_user(), which implicitly uses a kernel
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index aae2282600c..4d880b3d1f3 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -170,7 +170,10 @@ and is between 256 and 4096 characters. It is defined in the file
acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS
Format: To spoof as Windows 98: ="Microsoft Windows"
- acpi_osi= [HW,ACPI] empty param disables _OSI
+ acpi_osi= [HW,ACPI] Modify list of supported OS interface strings
+ acpi_osi="string1" # add string1 -- only one string
+ acpi_osi="!string2" # remove built-in string2
+ acpi_osi= # disable all strings
acpi_serialize [HW,ACPI] force serialization of AML methods
@@ -220,11 +223,6 @@ and is between 256 and 4096 characters. It is defined in the file
acpi_fake_ecdt [HW,ACPI] Workaround failure due to BIOS lacking ECDT
- acpi_generic_hotkey [HW,ACPI]
- Allow consolidated generic hotkey driver to
- override platform specific driver.
- See also Documentation/acpi-hotkey.txt.
-
acpi_pm_good [IA-32,X86-64]
Override the pmtimer bug detection: force the kernel
to assume that this machine's pmtimer latches its value
@@ -1016,49 +1014,6 @@ and is between 256 and 4096 characters. It is defined in the file
mga= [HW,DRM]
- migration_cost=
- [KNL,SMP] debug: override scheduler migration costs
- Format: <level-1-usecs>,<level-2-usecs>,...
- This debugging option can be used to override the
- default scheduler migration cost matrix. The numbers
- are indexed by 'CPU domain distance'.
- E.g. migration_cost=1000,2000,3000 on an SMT NUMA
- box will set up an intra-core migration cost of
- 1 msec, an inter-core migration cost of 2 msecs,
- and an inter-node migration cost of 3 msecs.
-
- WARNING: using the wrong values here can break
- scheduler performance, so it's only for scheduler
- development purposes, not production environments.
-
- migration_debug=
- [KNL,SMP] migration cost auto-detect verbosity
- Format=<0|1|2>
- If a system's migration matrix reported at bootup
- seems erroneous then this option can be used to
- increase verbosity of the detection process.
- We default to 0 (no extra messages), 1 will print
- some more information, and 2 will be really
- verbose (probably only useful if you also have a
- serial console attached to the system).
-
- migration_factor=
- [KNL,SMP] multiply/divide migration costs by a factor
- Format=<percent>
- This debug option can be used to proportionally
- increase or decrease the auto-detected migration
- costs for all entries of the migration matrix.
- E.g. migration_factor=150 will increase migration
- costs by 50%. (and thus the scheduler will be less
- eager migrating cache-hot tasks)
- migration_factor=80 will decrease migration costs
- by 20%. (thus the scheduler will be more eager to
- migrate tasks)
-
- WARNING: using the wrong values here can break
- scheduler performance, so it's only for scheduler
- development purposes, not production environments.
-
mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
@@ -1132,9 +1087,9 @@ and is between 256 and 4096 characters. It is defined in the file
when set.
Format: <int>
- noaliencache [MM, NUMA] Disables the allcoation of alien caches in
- the slab allocator. Saves per-node memory, but will
- impact performance on real NUMA hardware.
+ noaliencache [MM, NUMA, SLAB] Disables the allocation of alien
+ caches in the slab allocator. Saves per-node memory,
+ but will impact performance.
noalign [KNL,ARM]
@@ -1613,6 +1568,37 @@ and is between 256 and 4096 characters. It is defined in the file
slram= [HW,MTD]
+ slub_debug [MM, SLUB]
+ Enabling slub_debug allows one to determine the culprit
+ if slab objects become corrupted. Enabling slub_debug
+ creates guard zones around objects and poisons objects
+ when not in use. Also tracks the last alloc / free.
+ For more information see Documentation/vm/slub.txt.
+
+ slub_max_order= [MM, SLUB]
+ Determines the maximum allowed order for slabs. Setting
+ this too high may cause fragmentation.
+ For more information see Documentation/vm/slub.txt.
+
+ slub_min_objects= [MM, SLUB]
+ The minimum objects per slab. SLUB will increase the
+ slab order up to slub_max_order to generate a
+ sufficiently big slab to satisfy the number of objects.
+ The higher the number of objects the smaller the overhead
+ of tracking slabs.
+ For more information see Documentation/vm/slub.txt.
+
+ slub_min_order= [MM, SLUB]
+ Determines the mininum page order for slabs. Must be
+ lower than slub_max_order
+ For more information see Documentation/vm/slub.txt.
+
+ slub_nomerge [MM, SLUB]
+ Disable merging of slabs of similar size. May be
+ necessary if there is some reason to distinguish
+ allocs to different slabs.
+ For more information see Documentation/vm/slub.txt.
+
smart2= [HW]
Format: <io1>[,<io2>[,...,<io8>]]
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index e06b6e3c1db..d63f480afb7 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -32,6 +32,8 @@ cops.txt
- info on the COPS LocalTalk Linux driver
cs89x0.txt
- the Crystal LAN (CS8900/20-based) Ethernet ISA adapter driver
+cxacru.txt
+ - Conexant AccessRunner USB ADSL Modem
de4x5.txt
- the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
decnet.txt
@@ -94,9 +96,6 @@ routing.txt
- the new routing mechanism
shaper.txt
- info on the module that can shape/limit transmitted traffic.
-sk98lin.txt
- - Marvell Yukon Chipset / SysKonnect SK-98xx compliant Gigabit
- Ethernet Adapter family driver info
skfp.txt
- SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
smc9.txt
diff --git a/Documentation/networking/cxacru.txt b/Documentation/networking/cxacru.txt
new file mode 100644
index 00000000000..b074681a963
--- /dev/null
+++ b/Documentation/networking/cxacru.txt
@@ -0,0 +1,84 @@
+Firmware is required for this device: http://accessrunner.sourceforge.net/
+
+While it is capable of managing/maintaining the ADSL connection without the
+module loaded, the device will sometimes stop responding after unloading the
+driver and it is necessary to unplug/remove power to the device to fix this.
+
+Detected devices will appear as ATM devices named "cxacru". In /sys/class/atm/
+these are directories named cxacruN where N is the device number. A symlink
+named device points to the USB interface device's directory which contains
+several sysfs attribute files for retrieving device statistics:
+
+* adsl_controller_version
+
+* adsl_headend
+* adsl_headend_environment
+ Information about the remote headend.
+
+* downstream_attenuation (dB)
+* downstream_bits_per_frame
+* downstream_rate (kbps)
+* downstream_snr_margin (dB)
+ Downstream stats.
+
+* upstream_attenuation (dB)
+* upstream_bits_per_frame
+* upstream_rate (kbps)
+* upstream_snr_margin (dB)
+* transmitter_power (dBm/Hz)
+ Upstream stats.
+
+* downstream_crc_errors
+* downstream_fec_errors
+* downstream_hec_errors
+* upstream_crc_errors
+* upstream_fec_errors
+* upstream_hec_errors
+ Error counts.
+
+* line_startable
+ Indicates that ADSL support on the device
+ is/can be enabled, see adsl_start.
+
+* line_status
+ "initialising"
+ "down"
+ "attempting to activate"
+ "training"
+ "channel analysis"
+ "exchange"
+ "waiting"
+ "up"
+
+ Changes between "down" and "attempting to activate"
+ if there is no signal.
+
+* link_status
+ "not connected"
+ "connected"
+ "lost"
+
+* mac_address
+
+* modulation
+ "ANSI T1.413"
+ "ITU-T G.992.1 (G.DMT)"
+ "ITU-T G.992.2 (G.LITE)"
+
+* startup_attempts
+ Count of total attempts to initialise ADSL.
+
+To enable/disable ADSL, the following can be written to the adsl_state file:
+ "start"
+ "stop
+ "restart" (stops, waits 1.5s, then starts)
+ "poll" (used to resume status polling if it was disabled due to failure)
+
+Changes in adsl/line state are reported via kernel log messages:
+ [4942145.150704] ATM dev 0: ADSL state: running
+ [4942243.663766] ATM dev 0: ADSL line: down
+ [4942249.665075] ATM dev 0: ADSL line: attempting to activate
+ [4942253.654954] ATM dev 0: ADSL line: training
+ [4942255.666387] ATM dev 0: ADSL line: channel analysis
+ [4942259.656262] ATM dev 0: ADSL line: exchange
+ [2635357.696901] ATM dev 0: ADSL line: up (8128 kb/s down | 832 kb/s up)
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index af6a63ab902..32c2e9da5f3 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -433,6 +433,12 @@ tcp_workaround_signed_windows - BOOLEAN
not receive a window scaling option from them.
Default: 0
+tcp_dma_copybreak - INTEGER
+ Lower limit, in bytes, of the size of socket reads that will be
+ offloaded to a DMA copy engine, if one is present in the system
+ and CONFIG_NET_DMA is enabled.
+ Default: 4096
+
CIPSOv4 Variables:
cipso_cache_enable - BOOLEAN
@@ -874,8 +880,7 @@ accept_redirects - BOOLEAN
accept_source_route - INTEGER
Accept source routing (routing extension header).
- > 0: Accept routing header.
- = 0: Accept only routing header type 2.
+ >= 0: Accept only routing header type 2.
< 0: Do not accept routing header.
Default: 0
diff --git a/Documentation/networking/l2tp.txt b/Documentation/networking/l2tp.txt
new file mode 100644
index 00000000000..2451f551c50
--- /dev/null
+++ b/Documentation/networking/l2tp.txt
@@ -0,0 +1,169 @@
+This brief document describes how to use the kernel's PPPoL2TP driver
+to provide L2TP functionality. L2TP is a protocol that tunnels one or
+more PPP sessions over a UDP tunnel. It is commonly used for VPNs
+(L2TP/IPSec) and by ISPs to tunnel subscriber PPP sessions over an IP
+network infrastructure.
+
+Design
+======
+
+The PPPoL2TP driver, drivers/net/pppol2tp.c, provides a mechanism by
+which PPP frames carried through an L2TP session are passed through
+the kernel's PPP subsystem. The standard PPP daemon, pppd, handles all
+PPP interaction with the peer. PPP network interfaces are created for
+each local PPP endpoint.
+
+The L2TP protocol http://www.faqs.org/rfcs/rfc2661.html defines L2TP
+control and data frames. L2TP control frames carry messages between
+L2TP clients/servers and are used to setup / teardown tunnels and
+sessions. An L2TP client or server is implemented in userspace and
+will use a regular UDP socket per tunnel. L2TP data frames carry PPP
+frames, which may be PPP control or PPP data. The kernel's PPP
+subsystem arranges for PPP control frames to be delivered to pppd,
+while data frames are forwarded as usual.
+
+Each tunnel and session within a tunnel is assigned a unique tunnel_id
+and session_id. These ids are carried in the L2TP header of every
+control and data packet. The pppol2tp driver uses them to lookup
+internal tunnel and/or session contexts. Zero tunnel / session ids are
+treated specially - zero ids are never assigned to tunnels or sessions
+in the network. In the driver, the tunnel context keeps a pointer to
+the tunnel UDP socket. The session context keeps a pointer to the
+PPPoL2TP socket, as well as other data that lets the driver interface
+to the kernel PPP subsystem.
+
+Note that the pppol2tp kernel driver handles only L2TP data frames;
+L2TP control frames are simply passed up to userspace in the UDP
+tunnel socket. The kernel handles all datapath aspects of the
+protocol, including data packet resequencing (if enabled).
+
+There are a number of requirements on the userspace L2TP daemon in
+order to use the pppol2tp driver.
+
+1. Use a UDP socket per tunnel.
+
+2. Create a single PPPoL2TP socket per tunnel bound to a special null
+ session id. This is used only for communicating with the driver but
+ must remain open while the tunnel is active. Opening this tunnel
+ management socket causes the driver to mark the tunnel socket as an
+ L2TP UDP encapsulation socket and flags it for use by the
+ referenced tunnel id. This hooks up the UDP receive path via
+ udp_encap_rcv() in net/ipv4/udp.c. PPP data frames are never passed
+ in this special PPPoX socket.
+
+3. Create a PPPoL2TP socket per L2TP session. This is typically done
+ by starting pppd with the pppol2tp plugin and appropriate
+ arguments. A PPPoL2TP tunnel management socket (Step 2) must be
+ created before the first PPPoL2TP session socket is created.
+
+When creating PPPoL2TP sockets, the application provides information
+to the driver about the socket in a socket connect() call. Source and
+destination tunnel and session ids are provided, as well as the file
+descriptor of a UDP socket. See struct pppol2tp_addr in
+include/linux/if_ppp.h. Note that zero tunnel / session ids are
+treated specially. When creating the per-tunnel PPPoL2TP management
+socket in Step 2 above, zero source and destination session ids are
+specified, which tells the driver to prepare the supplied UDP file
+descriptor for use as an L2TP tunnel socket.
+
+Userspace may control behavior of the tunnel or session using
+setsockopt and ioctl on the PPPoX socket. The following socket
+options are supported:-
+
+DEBUG - bitmask of debug message categories. See below.
+SENDSEQ - 0 => don't send packets with sequence numbers
+ 1 => send packets with sequence numbers
+RECVSEQ - 0 => receive packet sequence numbers are optional
+ 1 => drop receive packets without sequence numbers
+LNSMODE - 0 => act as LAC.
+ 1 => act as LNS.
+REORDERTO - reorder timeout (in millisecs). If 0, don't try to reorder.
+
+Only the DEBUG option is supported by the special tunnel management
+PPPoX socket.
+
+In addition to the standard PPP ioctls, a PPPIOCGL2TPSTATS is provided
+to retrieve tunnel and session statistics from the kernel using the
+PPPoX socket of the appropriate tunnel or session.
+
+Debugging
+=========
+
+The driver supports a flexible debug scheme where kernel trace
+messages may be optionally enabled per tunnel and per session. Care is
+needed when debugging a live system since the messages are not
+rate-limited and a busy system could be swamped. Userspace uses
+setsockopt on the PPPoX socket to set a debug mask.
+
+The following debug mask bits are available:
+
+PPPOL2TP_MSG_DEBUG verbose debug (if compiled in)
+PPPOL2TP_MSG_CONTROL userspace - kernel interface
+PPPOL2TP_MSG_SEQ sequence numbers handling
+PPPOL2TP_MSG_DATA data packets
+
+Sample Userspace Code
+=====================
+
+1. Create tunnel management PPPoX socket
+
+ kernel_fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
+ if (kernel_fd >= 0) {
+ struct sockaddr_pppol2tp sax;
+ struct sockaddr_in const *peer_addr;
+
+ peer_addr = l2tp_tunnel_get_peer_addr(tunnel);
+ memset(&sax, 0, sizeof(sax));
+ sax.sa_family = AF_PPPOX;
+ sax.sa_protocol = PX_PROTO_OL2TP;
+ sax.pppol2tp.fd = udp_fd; /* fd of tunnel UDP socket */
+ sax.pppol2tp.addr.sin_addr.s_addr = peer_addr->sin_addr.s_addr;
+ sax.pppol2tp.addr.sin_port = peer_addr->sin_port;
+ sax.pppol2tp.addr.sin_family = AF_INET;
+ sax.pppol2tp.s_tunnel = tunnel_id;
+ sax.pppol2tp.s_session = 0; /* special case: mgmt socket */
+ sax.pppol2tp.d_tunnel = 0;
+ sax.pppol2tp.d_session = 0; /* special case: mgmt socket */
+
+ if(connect(kernel_fd, (struct sockaddr *)&sax, sizeof(sax) ) < 0 ) {
+ perror("connect failed");
+ result = -errno;
+ goto err;
+ }
+ }
+
+2. Create session PPPoX data socket
+
+ struct sockaddr_pppol2tp sax;
+ int fd;
+
+ /* Note, the target socket must be bound already, else it will not be ready */
+ sax.sa_family = AF_PPPOX;
+ sax.sa_protocol = PX_PROTO_OL2TP;
+ sax.pppol2tp.fd = tunnel_fd;
+ sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr;
+ sax.pppol2tp.addr.sin_port = addr->sin_port;
+ sax.pppol2tp.addr.sin_family = AF_INET;
+ sax.pppol2tp.s_tunnel = tunnel_id;
+ sax.pppol2tp.s_session = session_id;
+ sax.pppol2tp.d_tunnel = peer_tunnel_id;
+ sax.pppol2tp.d_session = peer_session_id;
+
+ /* session_fd is the fd of the session's PPPoL2TP socket.
+ * tunnel_fd is the fd of the tunnel UDP socket.
+ */
+ fd = connect(session_fd, (struct sockaddr *)&sax, sizeof(sax));
+ if (fd < 0 ) {
+ return -errno;
+ }
+ return 0;
+
+Miscellanous
+============
+
+The PPPoL2TP driver was developed as part of the OpenL2TP project by
+Katalix Systems Ltd. OpenL2TP is a full-featured L2TP client / server,
+designed from the ground up to have the L2TP datapath in the
+kernel. The project also implemented the pppol2tp plugin for pppd
+which allows pppd to use the kernel driver. Details can be found at
+http://openl2tp.sourceforge.net.
diff --git a/Documentation/networking/mac80211-injection.txt b/Documentation/networking/mac80211-injection.txt
new file mode 100644
index 00000000000..53ef7a06f49
--- /dev/null
+++ b/Documentation/networking/mac80211-injection.txt
@@ -0,0 +1,59 @@
+How to use packet injection with mac80211
+=========================================
+
+mac80211 now allows arbitrary packets to be injected down any Monitor Mode
+interface from userland. The packet you inject needs to be composed in the
+following format:
+
+ [ radiotap header ]
+ [ ieee80211 header ]
+ [ payload ]
+
+The radiotap format is discussed in
+./Documentation/networking/radiotap-headers.txt.
+
+Despite 13 radiotap argument types are currently defined, most only make sense
+to appear on received packets. Currently three kinds of argument are used by
+the injection code, although it knows to skip any other arguments that are
+present (facilitating replay of captured radiotap headers directly):
+
+ - IEEE80211_RADIOTAP_RATE - u8 arg in 500kbps units (0x02 --> 1Mbps)
+
+ - IEEE80211_RADIOTAP_ANTENNA - u8 arg, 0x00 = ant1, 0x01 = ant2
+
+ - IEEE80211_RADIOTAP_DBM_TX_POWER - u8 arg, dBm
+
+Here is an example valid radiotap header defining these three parameters
+
+ 0x00, 0x00, // <-- radiotap version
+ 0x0b, 0x00, // <- radiotap header length
+ 0x04, 0x0c, 0x00, 0x00, // <-- bitmap
+ 0x6c, // <-- rate
+ 0x0c, //<-- tx power
+ 0x01 //<-- antenna
+
+The ieee80211 header follows immediately afterwards, looking for example like
+this:
+
+ 0x08, 0x01, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
+ 0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
+ 0x10, 0x86
+
+Then lastly there is the payload.
+
+After composing the packet contents, it is sent by send()-ing it to a logical
+mac80211 interface that is in Monitor mode. Libpcap can also be used,
+(which is easier than doing the work to bind the socket to the right
+interface), along the following lines:
+
+ ppcap = pcap_open_live(szInterfaceName, 800, 1, 20, szErrbuf);
+...
+ r = pcap_inject(ppcap, u8aSendBuffer, nLength);
+
+You can also find sources for a complete inject test applet here:
+
+http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer
+
+Andy Green <andy@warmcat.com>
diff --git a/Documentation/networking/multiqueue.txt b/Documentation/networking/multiqueue.txt
new file mode 100644
index 00000000000..00b60cce222
--- /dev/null
+++ b/Documentation/networking/multiqueue.txt
@@ -0,0 +1,111 @@
+
+ HOWTO for multiqueue network device support
+ ===========================================
+
+Section 1: Base driver requirements for implementing multiqueue support
+Section 2: Qdisc support for multiqueue devices
+Section 3: Brief howto using PRIO or RR for multiqueue devices
+
+
+Intro: Kernel support for multiqueue devices
+---------------------------------------------------------
+
+Kernel support for multiqueue devices is only an API that is presented to the
+netdevice layer for base drivers to implement. This feature is part of the
+core networking stack, and all network devices will be running on the
+multiqueue-aware stack. If a base driver only has one queue, then these
+changes are transparent to that driver.
+
+
+Section 1: Base driver requirements for implementing multiqueue support
+-----------------------------------------------------------------------
+
+Base drivers are required to use the new alloc_etherdev_mq() or
+alloc_netdev_mq() functions to allocate the subqueues for the device. The
+underlying kernel API will take care of the allocation and deallocation of
+the subqueue memory, as well as netdev configuration of where the queues
+exist in memory.
+
+The base driver will also need to manage the queues as it does the global
+netdev->queue_lock today. Therefore base drivers should use the
+netif_{start|stop|wake}_subqueue() functions to manage each queue while the
+device is still operational. netdev->queue_lock is still used when the device
+comes online or when it's completely shut down (unregister_netdev(), etc.).
+
+Finally, the base driver should indicate that it is a multiqueue device. The
+feature flag NETIF_F_MULTI_QUEUE should be added to the netdev->features
+bitmap on device initialization. Below is an example from e1000:
+
+#ifdef CONFIG_E1000_MQ
+ if ( (adapter->hw.mac.type == e1000_82571) ||
+ (adapter->hw.mac.type == e1000_82572) ||
+ (adapter->hw.mac.type == e1000_80003es2lan))
+ netdev->features |= NETIF_F_MULTI_QUEUE;
+#endif
+
+
+Section 2: Qdisc support for multiqueue devices
+-----------------------------------------------
+
+Currently two qdiscs support multiqueue devices. A new round-robin qdisc,
+sch_rr, and sch_prio. The qdisc is responsible for classifying the skb's to
+bands and queues, and will store the queue mapping into skb->queue_mapping.
+Use this field in the base driver to determine which queue to send the skb
+to.
+
+sch_rr has been added for hardware that doesn't want scheduling policies from
+software, so it's a straight round-robin qdisc. It uses the same syntax and
+classification priomap that sch_prio uses, so it should be intuitive to
+configure for people who've used sch_prio.
+
+The PRIO qdisc naturally plugs into a multiqueue device. If PRIO has been
+built with NET_SCH_PRIO_MQ, then upon load, it will make sure the number of
+bands requested is equal to the number of queues on the hardware. If they
+are equal, it sets a one-to-one mapping up between the queues and bands. If
+they're not equal, it will not load the qdisc. This is the same behavior
+for RR. Once the association is made, any skb that is classified will have
+skb->queue_mapping set, which will allow the driver to properly queue skb's
+to multiple queues.
+
+
+Section 3: Brief howto using PRIO and RR for multiqueue devices
+---------------------------------------------------------------
+
+The userspace command 'tc,' part of the iproute2 package, is used to configure
+qdiscs. To add the PRIO qdisc to your network device, assuming the device is
+called eth0, run the following command:
+
+# tc qdisc add dev eth0 root handle 1: prio bands 4 multiqueue
+
+This will create 4 bands, 0 being highest priority, and associate those bands
+to the queues on your NIC. Assuming eth0 has 4 Tx queues, the band mapping
+would look like:
+
+band 0 => queue 0
+band 1 => queue 1
+band 2 => queue 2
+band 3 => queue 3
+
+Traffic will begin flowing through each queue if your TOS values are assigning
+traffic across the various bands. For example, ssh traffic will always try to
+go out band 0 based on TOS -> Linux priority conversion (realtime traffic),
+so it will be sent out queue 0. ICMP traffic (pings) fall into the "normal"
+traffic classification, which is band 1. Therefore pings will be send out
+queue 1 on the NIC.
+
+Note the use of the multiqueue keyword. This is only in versions of iproute2
+that support multiqueue networking devices; if this is omitted when loading
+a qdisc onto a multiqueue device, the qdisc will load and operate the same
+if it were loaded onto a single-queue device (i.e. - sends all traffic to
+queue 0).
+
+Another alternative to multiqueue band allocation can be done by using the
+multiqueue option and specify 0 bands. If this is the case, the qdisc will
+allocate the number of bands to equal the number of queues that the device
+reports, and bring the qdisc online.
+
+The behavior of tc filters remains the same, where it will override TOS priority
+classification.
+
+
+Author: Peter P. Waskiewicz Jr. <peter.p.waskiewicz.jr@intel.com>
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index ce1361f9524..37869295fc7 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -20,6 +20,30 @@ private data which gets freed when the network device is freed. If
separately allocated data is attached to the network device
(dev->priv) then it is up to the module exit handler to free that.
+MTU
+===
+Each network device has a Maximum Transfer Unit. The MTU does not
+include any link layer protocol overhead. Upper layer protocols must
+not pass a socket buffer (skb) to a device to transmit with more data
+than the mtu. The MTU does not include link layer header overhead, so
+for example on Ethernet if the standard MTU is 1500 bytes used, the
+actual skb will contain up to 1514 bytes because of the Ethernet
+header. Devices should allow for the 4 byte VLAN header as well.
+
+Segmentation Offload (GSO, TSO) is an exception to this rule. The
+upper layer protocol may pass a large socket buffer to the device
+transmit routine, and the device will break that up into separate
+packets based on the current MTU.
+
+MTU is symmetrical and applies both to receive and transmit. A device
+must be able to receive at least the maximum size packet allowed by
+the MTU. A network device may use the MTU as mechanism to size receive
+buffers, but the device should allow packets with VLAN header. With
+standard Ethernet mtu of 1500 bytes, the device should allow up to
+1518 byte packets (1500 + 14 header + 4 tag). The device may either:
+drop, truncate, or pass up oversize packets, but dropping oversize
+packets is preferred.
+
struct net_device synchronization rules
=======================================
@@ -43,16 +67,17 @@ dev->get_stats:
dev->hard_start_xmit:
Synchronization: netif_tx_lock spinlock.
+
When the driver sets NETIF_F_LLTX in dev->features this will be
called without holding netif_tx_lock. In this case the driver
has to lock by itself when needed. It is recommended to use a try lock
- for this and return -1 when the spin lock fails.
+ for this and return NETDEV_TX_LOCKED when the spin lock fails.
The locking there should also properly protect against
- set_multicast_list
- Context: Process with BHs disabled or BH (timer).
- Notes: netif_queue_stopped() is guaranteed false
- Interrupts must be enabled when calling hard_start_xmit.
- (Interrupts must also be enabled when enabling the BH handler.)
+ set_multicast_list.
+
+ Context: Process with BHs disabled or BH (timer),
+ will be called with interrupts disabled by netconsole.
+
Return codes:
o NETDEV_TX_OK everything ok.
o NETDEV_TX_BUSY Cannot transmit packet, try later
@@ -74,4 +99,5 @@ dev->poll:
Synchronization: __LINK_STATE_RX_SCHED bit in dev->state. See
dev_close code and comments in net/core/dev.c for more info.
Context: softirq
+ will be called with interrupts disabled by netconsole.
diff --git a/Documentation/networking/radiotap-headers.txt b/Documentation/networking/radiotap-headers.txt
new file mode 100644
index 00000000000..953331c7984
--- /dev/null
+++ b/Documentation/networking/radiotap-headers.txt
@@ -0,0 +1,152 @@
+How to use radiotap headers
+===========================
+
+Pointer to the radiotap include file
+------------------------------------
+
+Radiotap headers are variable-length and extensible, you can get most of the
+information you need to know on them from:
+
+./include/net/ieee80211_radiotap.h
+
+This document gives an overview and warns on some corner cases.
+
+
+Structure of the header
+-----------------------
+
+There is a fixed portion at the start which contains a u32 bitmap that defines
+if the possible argument associated with that bit is present or not. So if b0
+of the it_present member of ieee80211_radiotap_header is set, it means that
+the header for argument index 0 (IEEE80211_RADIOTAP_TSFT) is present in the
+argument area.
+
+ < 8-byte ieee80211_radiotap_header >
+ [ <possible argument bitmap extensions ... > ]
+ [ <argument> ... ]
+
+At the moment there are only 13 possible argument indexes defined, but in case
+we run out of space in the u32 it_present member, it is defined that b31 set
+indicates that there is another u32 bitmap following (shown as "possible
+argument bitmap extensions..." above), and the start of the arguments is moved
+forward 4 bytes each time.
+
+Note also that the it_len member __le16 is set to the total number of bytes
+covered by the ieee80211_radiotap_header and any arguments following.
+
+
+Requirements for arguments
+--------------------------
+
+After the fixed part of the header, the arguments follow for each argument
+index whose matching bit is set in the it_present member of
+ieee80211_radiotap_header.
+
+ - the arguments are all stored little-endian!
+
+ - the argument payload for a given argument index has a fixed size. So
+ IEEE80211_RADIOTAP_TSFT being present always indicates an 8-byte argument is
+ present. See the comments in ./include/net/ieee80211_radiotap.h for a nice
+ breakdown of all the argument sizes
+
+ - the arguments must be aligned to a boundary of the argument size using
+ padding. So a u16 argument must start on the next u16 boundary if it isn't
+ already on one, a u32 must start on the next u32 boundary and so on.
+
+ - "alignment" is relative to the start of the ieee80211_radiotap_header, ie,
+ the first byte of the radiotap header. The absolute alignment of that first
+ byte isn't defined. So even if the whole radiotap header is starting at, eg,
+ address 0x00000003, still the first byte of the radiotap header is treated as
+ 0 for alignment purposes.
+
+ - the above point that there may be no absolute alignment for multibyte
+ entities in the fixed radiotap header or the argument region means that you
+ have to take special evasive action when trying to access these multibyte
+ entities. Some arches like Blackfin cannot deal with an attempt to
+ dereference, eg, a u16 pointer that is pointing to an odd address. Instead
+ you have to use a kernel API get_unaligned() to dereference the pointer,
+ which will do it bytewise on the arches that require that.
+
+ - The arguments for a given argument index can be a compound of multiple types
+ together. For example IEEE80211_RADIOTAP_CHANNEL has an argument payload
+ consisting of two u16s of total length 4. When this happens, the padding
+ rule is applied dealing with a u16, NOT dealing with a 4-byte single entity.
+
+
+Example valid radiotap header
+-----------------------------
+
+ 0x00, 0x00, // <-- radiotap version + pad byte
+ 0x0b, 0x00, // <- radiotap header length
+ 0x04, 0x0c, 0x00, 0x00, // <-- bitmap
+ 0x6c, // <-- rate (in 500kHz units)
+ 0x0c, //<-- tx power
+ 0x01 //<-- antenna
+
+
+Using the Radiotap Parser
+-------------------------
+
+If you are having to parse a radiotap struct, you can radically simplify the
+job by using the radiotap parser that lives in net/wireless/radiotap.c and has
+its prototypes available in include/net/cfg80211.h. You use it like this:
+
+#include <net/cfg80211.h>
+
+/* buf points to the start of the radiotap header part */
+
+int MyFunction(u8 * buf, int buflen)
+{
+ int pkt_rate_100kHz = 0, antenna = 0, pwr = 0;
+ struct ieee80211_radiotap_iterator iterator;
+ int ret = ieee80211_radiotap_iterator_init(&iterator, buf, buflen);
+
+ while (!ret) {
+
+ ret = ieee80211_radiotap_iterator_next(&iterator);
+
+ if (ret)
+ continue;
+
+ /* see if this argument is something we can use */
+
+ switch (iterator.this_arg_index) {
+ /*
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned. Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ */
+ case IEEE80211_RADIOTAP_RATE:
+ /* radiotap "rate" u8 is in
+ * 500kbps units, eg, 0x02=1Mbps
+ */
+ pkt_rate_100kHz = (*iterator.this_arg) * 5;
+ break;
+
+ case IEEE80211_RADIOTAP_ANTENNA:
+ /* radiotap uses 0 for 1st ant */
+ antenna = *iterator.this_arg);
+ break;
+
+ case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ pwr = *iterator.this_arg;
+ break;
+
+ default:
+ break;
+ }
+ } /* while more rt headers */
+
+ if (ret != -ENOENT)
+ return TXRX_DROP;
+
+ /* discard the radiotap header part */
+ buf += iterator.max_length;
+ buflen -= iterator.max_length;
+
+ ...
+
+}
+
+Andy Green <andy@warmcat.com>
diff --git a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt
deleted file mode 100644
index 8590a954df1..00000000000
--- a/Documentation/networking/sk98lin.txt
+++ /dev/null
@@ -1,568 +0,0 @@
-(C)Copyright 1999-2004 Marvell(R).
-All rights reserved
-===========================================================================
-
-sk98lin.txt created 13-Feb-2004
-
-Readme File for sk98lin v6.23
-Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX
-
-This file contains
- 1 Overview
- 2 Required Files
- 3 Installation
- 3.1 Driver Installation
- 3.2 Inclusion of adapter at system start
- 4 Driver Parameters
- 4.1 Per-Port Parameters
- 4.2 Adapter Parameters
- 5 Large Frame Support
- 6 VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
- 7 Troubleshooting
-
-===========================================================================
-
-
-1 Overview
-===========
-
-The sk98lin driver supports the Marvell Yukon and SysKonnect
-SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter on Linux. It has
-been tested with Linux on Intel/x86 machines.
-***
-
-
-2 Required Files
-=================
-
-The linux kernel source.
-No additional files required.
-***
-
-
-3 Installation
-===============
-
-It is recommended to download the latest version of the driver from the
-SysKonnect web site www.syskonnect.com. If you have downloaded the latest
-driver, the Linux kernel has to be patched before the driver can be
-installed. For details on how to patch a Linux kernel, refer to the
-patch.txt file.
-
-3.1 Driver Installation
-------------------------
-
-The following steps describe the actions that are required to install
-the driver and to start it manually. These steps should be carried
-out for the initial driver setup. Once confirmed to be ok, they can
-be included in the system start.
-
-NOTE 1: To perform the following tasks you need 'root' access.
-
-NOTE 2: In case of problems, please read the section "Troubleshooting"
- below.
-
-The driver can either be integrated into the kernel or it can be compiled
-as a module. Select the appropriate option during the kernel
-configuration.
-
-Compile/use the driver as a module
-----------------------------------
-To compile the driver, go to the directory /usr/src/linux and
-execute the command "make menuconfig" or "make xconfig" and proceed as
-follows:
-
-To integrate the driver permanently into the kernel, proceed as follows:
-
-1. Select the menu "Network device support" and then "Ethernet(1000Mbit)"
-2. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support"
- with (*)
-3. Build a new kernel when the configuration of the above options is
- finished.
-4. Install the new kernel.
-5. Reboot your system.
-
-To use the driver as a module, proceed as follows:
-
-1. Enable 'loadable module support' in the kernel.
-2. For automatic driver start, enable the 'Kernel module loader'.
-3. Select the menu "Network device support" and then "Ethernet(1000Mbit)"
-4. Mark "Marvell Yukon Chipset / SysKonnect SK-98xx family support"
- with (M)
-5. Execute the command "make modules".
-6. Execute the command "make modules_install".
- The appropriate modules will be installed.
-7. Reboot your system.
-
-
-Load the module manually
-------------------------
-To load the module manually, proceed as follows:
-
-1. Enter "modprobe sk98lin".
-2. If a Marvell Yukon or SysKonnect SK-98xx adapter is installed in
- your computer and you have a /proc file system, execute the command:
- "ls /proc/net/sk98lin/"
- This should produce an output containing a line with the following
- format:
- eth0 eth1 ...
- which indicates that your adapter has been found and initialized.
-
- NOTE 1: If you have more than one Marvell Yukon or SysKonnect SK-98xx
- adapter installed, the adapters will be listed as 'eth0',
- 'eth1', 'eth2', etc.
- For each adapter, repeat steps 3 and 4 below.
-
- NOTE 2: If you have other Ethernet adapters installed, your Marvell
- Yukon or SysKonnect SK-98xx adapter will be mapped to the
- next available number, e.g. 'eth1'. The mapping is executed
- automatically.
- The module installation message (displayed either in a system
- log file or on the console) prints a line for each adapter
- found containing the corresponding 'ethX'.
-
-3. Select an IP address and assign it to the respective adapter by
- entering:
- ifconfig eth0 <ip-address>
- With this command, the adapter is connected to the Ethernet.
-
- SK-98xx Gigabit Ethernet Server Adapters: The yellow LED on the adapter
- is now active, the link status LED of the primary port is active and
- the link status LED of the secondary port (on dual port adapters) is
- blinking (if the ports are connected to a switch or hub).
- SK-98xx V2.0 Gigabit Ethernet Adapters: The link status LED is active.
- In addition, you will receive a status message on the console stating
- "ethX: network connection up using port Y" and showing the selected
- connection parameters (x stands for the ethernet device number
- (0,1,2, etc), y stands for the port name (A or B)).
-
- NOTE: If you are in doubt about IP addresses, ask your network
- administrator for assistance.
-
-4. Your adapter should now be fully operational.
- Use 'ping <otherstation>' to verify the connection to other computers
- on your network.
-5. To check the adapter configuration view /proc/net/sk98lin/[devicename].
- For example by executing:
- "cat /proc/net/sk98lin/eth0"
-
-Unload the module
------------------
-To stop and unload the driver modules, proceed as follows:
-
-1. Execute the command "ifconfig eth0 down".
-2. Execute the command "rmmod sk98lin".
-
-3.2 Inclusion of adapter at system start
------------------------------------------
-
-Since a large number of different Linux distributions are
-available, we are unable to describe a general installation procedure
-for the driver module.
-Because the driver is now integrated in the kernel, installation should
-be easy, using the standard mechanism of your distribution.
-Refer to the distribution's manual for installation of ethernet adapters.
-
-***
-
-4 Driver Parameters
-====================
-
-Parameters can be set at the command line after the module has been
-loaded with the command 'modprobe'.
-In some distributions, the configuration tools are able to pass parameters
-to the driver module.
-
-If you use the kernel module loader, you can set driver parameters
-in the file /etc/modprobe.conf (or /etc/modules.conf in 2.4 or earlier).
-To set the driver parameters in this file, proceed as follows:
-
-1. Insert a line of the form :
- options sk98lin ...
- For "...", the same syntax is required as described for the command
- line parameters of modprobe below.
-2. To activate the new parameters, either reboot your computer
- or
- unload and reload the driver.
- The syntax of the driver parameters is:
-
- modprobe sk98lin parameter=value1[,value2[,value3...]]
-
- where value1 refers to the first adapter, value2 to the second etc.
-
-NOTE: All parameters are case sensitive. Write them exactly as shown
- below.
-
-Example:
-Suppose you have two adapters. You want to set auto-negotiation
-on the first adapter to ON and on the second adapter to OFF.
-You also want to set DuplexCapabilities on the first adapter
-to FULL, and on the second adapter to HALF.
-Then, you must enter:
-
- modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half
-
-NOTE: The number of adapters that can be configured this way is
- limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM).
- The current limit is 16. If you happen to install
- more adapters, adjust this and recompile.
-
-
-4.1 Per-Port Parameters
-------------------------
-
-These settings are available for each port on the adapter.
-In the following description, '?' stands for the port for
-which you set the parameter (A or B).
-
-Speed
------
-Parameter: Speed_?
-Values: 10, 100, 1000, Auto
-Default: Auto
-
-This parameter is used to set the speed capabilities. It is only valid
-for the SK-98xx V2.0 copper adapters.
-Usually, the speed is negotiated between the two ports during link
-establishment. If this fails, a port can be forced to a specific setting
-with this parameter.
-
-Auto-Negotiation
-----------------
-Parameter: AutoNeg_?
-Values: On, Off, Sense
-Default: On
-
-The "Sense"-mode automatically detects whether the link partner supports
-auto-negotiation or not.
-
-Duplex Capabilities
--------------------
-Parameter: DupCap_?
-Values: Half, Full, Both
-Default: Both
-
-This parameters is only relevant if auto-negotiation for this port is
-not set to "Sense". If auto-negotiation is set to "On", all three values
-are possible. If it is set to "Off", only "Full" and "Half" are allowed.
-This parameter is useful if your link partner does not support all
-possible combinations.
-
-Flow Control
-------------
-Parameter: FlowCtrl_?
-Values: Sym, SymOrRem, LocSend, None
-Default: SymOrRem
-
-This parameter can be used to set the flow control capabilities the
-port reports during auto-negotiation. It can be set for each port
-individually.
-Possible modes:
- -- Sym = Symmetric: both link partners are allowed to send
- PAUSE frames
- -- SymOrRem = SymmetricOrRemote: both or only remote partner
- are allowed to send PAUSE frames
- -- LocSend = LocalSend: only local link partner is allowed
- to send PAUSE frames
- -- None = no link partner is allowed to send PAUSE frames
-
-NOTE: This parameter is ignored if auto-negotiation is set to "Off".
-
-Role in Master-Slave-Negotiation (1000Base-T only)
---------------------------------------------------
-Parameter: Role_?
-Values: Auto, Master, Slave
-Default: Auto
-
-This parameter is only valid for the SK-9821 and SK-9822 adapters.
-For two 1000Base-T ports to communicate, one must take the role of the
-master (providing timing information), while the other must be the
-slave. Usually, this is negotiated between the two ports during link
-establishment. If this fails, a port can be forced to a specific setting
-with this parameter.
-
-
-4.2 Adapter Parameters
------------------------
-
-Connection Type (SK-98xx V2.0 copper adapters only)
----------------
-Parameter: ConType
-Values: Auto, 100FD, 100HD, 10FD, 10HD
-Default: Auto
-
-The parameter 'ConType' is a combination of all five per-port parameters
-within one single parameter. This simplifies the configuration of both ports
-of an adapter card! The different values of this variable reflect the most
-meaningful combinations of port parameters.
-
-The following table shows the values of 'ConType' and the corresponding
-combinations of the per-port parameters:
-
- ConType | DupCap AutoNeg FlowCtrl Role Speed
- ----------+------------------------------------------------------
- Auto | Both On SymOrRem Auto Auto
- 100FD | Full Off None Auto (ignored) 100
- 100HD | Half Off None Auto (ignored) 100
- 10FD | Full Off None Auto (ignored) 10
- 10HD | Half Off None Auto (ignored) 10
-
-Stating any other port parameter together with this 'ConType' variable
-will result in a merged configuration of those settings. This due to
-the fact, that the per-port parameters (e.g. Speed_? ) have a higher
-priority than the combined variable 'ConType'.
-
-NOTE: This parameter is always used on both ports of the adapter card.
-
-Interrupt Moderation
---------------------
-Parameter: Moderation
-Values: None, Static, Dynamic
-Default: None
-
-Interrupt moderation is employed to limit the maximum number of interrupts
-the driver has to serve. That is, one or more interrupts (which indicate any
-transmit or receive packet to be processed) are queued until the driver
-processes them. When queued interrupts are to be served, is determined by the
-'IntsPerSec' parameter, which is explained later below.
-
-Possible modes:
-
- -- None - No interrupt moderation is applied on the adapter card.
- Therefore, each transmit or receive interrupt is served immediately
- as soon as it appears on the interrupt line of the adapter card.
-
- -- Static - Interrupt moderation is applied on the adapter card.
- All transmit and receive interrupts are queued until a complete
- moderation interval ends. If such a moderation interval ends, all
- queued interrupts are processed in one big bunch without any delay.
- The term 'static' reflects the fact, that interrupt moderation is
- always enabled, regardless how much network load is currently
- passing via a particular interface. In addition, the duration of
- the moderation interval has a fixed length that never changes while
- the driver is operational.
-
- -- Dynamic - Interrupt moderation might be applied on the adapter card,
- depending on the load of the system. If the driver detects that the
- system load is too high, the driver tries to shield the system against
- too much network load by enabling interrupt moderation. If - at a later
- time - the CPU utilization decreases again (or if the network load is
- negligible) the interrupt moderation will automatically be disabled.
-
-Interrupt moderation should be used when the driver has to handle one or more
-interfaces with a high network load, which - as a consequence - leads also to a
-high CPU utilization. When moderation is applied in such high network load
-situations, CPU load might be reduced by 20-30%.
-
-NOTE: The drawback of using interrupt moderation is an increase of the round-
-trip-time (RTT), due to the queueing and serving of interrupts at dedicated
-moderation times.
-
-Interrupts per second
----------------------
-Parameter: IntsPerSec
-Values: 30...40000 (interrupts per second)
-Default: 2000
-
-This parameter is only used if either static or dynamic interrupt moderation
-is used on a network adapter card. Using this parameter if no moderation is
-applied will lead to no action performed.
-
-This parameter determines the length of any interrupt moderation interval.
-Assuming that static interrupt moderation is to be used, an 'IntsPerSec'
-parameter value of 2000 will lead to an interrupt moderation interval of
-500 microseconds.
-
-NOTE: The duration of the moderation interval is to be chosen with care.
-At first glance, selecting a very long duration (e.g. only 100 interrupts per
-second) seems to be meaningful, but the increase of packet-processing delay
-is tremendous. On the other hand, selecting a very short moderation time might
-compensate the use of any moderation being applied.
-
-
-Preferred Port
---------------
-Parameter: PrefPort
-Values: A, B
-Default: A
-
-This is used to force the preferred port to A or B (on dual-port network
-adapters). The preferred port is the one that is used if both are detected
-as fully functional.
-
-RLMT Mode (Redundant Link Management Technology)
-------------------------------------------------
-Parameter: RlmtMode
-Values: CheckLinkState,CheckLocalPort, CheckSeg, DualNet
-Default: CheckLinkState
-
-RLMT monitors the status of the port. If the link of the active port
-fails, RLMT switches immediately to the standby link. The virtual link is
-maintained as long as at least one 'physical' link is up.
-
-Possible modes:
-
- -- CheckLinkState - Check link state only: RLMT uses the link state
- reported by the adapter hardware for each individual port to
- determine whether a port can be used for all network traffic or
- not.
-
- -- CheckLocalPort - In this mode, RLMT monitors the network path
- between the two ports of an adapter by regularly exchanging packets
- between them. This mode requires a network configuration in which
- the two ports are able to "see" each other (i.e. there must not be
- any router between the ports).
-
- -- CheckSeg - Check local port and segmentation: This mode supports the
- same functions as the CheckLocalPort mode and additionally checks
- network segmentation between the ports. Therefore, this mode is only
- to be used if Gigabit Ethernet switches are installed on the network
- that have been configured to use the Spanning Tree protocol.
-
- -- DualNet - In this mode, ports A and B are used as separate devices.
- If you have a dual port adapter, port A will be configured as eth0
- and port B as eth1. Both ports can be used independently with
- distinct IP addresses. The preferred port setting is not used.
- RLMT is turned off.
-
-NOTE: RLMT modes CLP and CLPSS are designed to operate in configurations
- where a network path between the ports on one adapter exists.
- Moreover, they are not designed to work where adapters are connected
- back-to-back.
-***
-
-
-5 Large Frame Support
-======================
-
-The driver supports large frames (also called jumbo frames). Using large
-frames can result in an improved throughput if transferring large amounts
-of data.
-To enable large frames, set the MTU (maximum transfer unit) of the
-interface to the desired value (up to 9000), execute the following
-command:
- ifconfig eth0 mtu 9000
-This will only work if you have two adapters connected back-to-back
-or if you use a switch that supports large frames. When using a switch,
-it should be configured to allow large frames and auto-negotiation should
-be set to OFF. The setting must be configured on all adapters that can be
-reached by the large frames. If one adapter is not set to receive large
-frames, it will simply drop them.
-
-You can switch back to the standard ethernet frame size by executing the
-following command:
- ifconfig eth0 mtu 1500
-
-To permanently configure this setting, add a script with the 'ifconfig'
-line to the system startup sequence (named something like "S99sk98lin"
-in /etc/rc.d/rc2.d).
-***
-
-
-6 VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
-==================================================================
-
-The Marvell Yukon/SysKonnect Linux drivers are able to support VLAN and
-Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad.
-These features are only available after installation of open source
-modules available on the Internet:
-For VLAN go to: http://www.candelatech.com/~greear/vlan.html
-For Link Aggregation go to: http://www.st.rim.or.jp/~yumo
-
-NOTE: SysKonnect GmbH does not offer any support for these open source
- modules and does not take the responsibility for any kind of
- failures or problems arising in connection with these modules.
-
-NOTE: Configuring Link Aggregation on a SysKonnect dual link adapter may
- cause problems when unloading the driver.
-
-
-7 Troubleshooting
-==================
-
-If any problems occur during the installation process, check the
-following list:
-
-
-Problem: The SK-98xx adapter cannot be found by the driver.
-Solution: In /proc/pci search for the following entry:
- 'Ethernet controller: SysKonnect SK-98xx ...'
- If this entry exists, the SK-98xx or SK-98xx V2.0 adapter has
- been found by the system and should be operational.
- If this entry does not exist or if the file '/proc/pci' is not
- found, there may be a hardware problem or the PCI support may
- not be enabled in your kernel.
- The adapter can be checked using the diagnostics program which
- is available on the SysKonnect web site:
- www.syskonnect.com
-
- Some COMPAQ machines have problems dealing with PCI under Linux.
- This problem is described in the 'PCI howto' document
- (included in some distributions or available from the
- web, e.g. at 'www.linux.org').
-
-
-Problem: Programs such as 'ifconfig' or 'route' cannot be found or the
- error message 'Operation not permitted' is displayed.
-Reason: You are not logged in as user 'root'.
-Solution: Logout and login as 'root' or change to 'root' via 'su'.
-
-
-Problem: Upon use of the command 'ping <address>' the message
- "ping: sendto: Network is unreachable" is displayed.
-Reason: Your route is not set correctly.
-Solution: If you are using RedHat, you probably forgot to set up the
- route in the 'network configuration'.
- Check the existing routes with the 'route' command and check
- if an entry for 'eth0' exists, and if so, if it is set correctly.
-
-
-Problem: The driver can be started, the adapter is connected to the
- network, but you cannot receive or transmit any packets;
- e.g. 'ping' does not work.
-Reason: There is an incorrect route in your routing table.
-Solution: Check the routing table with the command 'route' and read the
- manual help pages dealing with routes (enter 'man route').
-
-NOTE: Although the 2.2.x kernel versions generate the routing entry
- automatically, problems of this kind may occur here as well. We've
- come across a situation in which the driver started correctly at
- system start, but after the driver has been removed and reloaded,
- the route of the adapter's network pointed to the 'dummy0'device
- and had to be corrected manually.
-
-
-Problem: Your computer should act as a router between multiple
- IP subnetworks (using multiple adapters), but computers in
- other subnetworks cannot be reached.
-Reason: Either the router's kernel is not configured for IP forwarding
- or the routing table and gateway configuration of at least one
- computer is not working.
-
-Problem: Upon driver start, the following error message is displayed:
- "eth0: -- ERROR --
- Class: internal Software error
- Nr: 0xcc
- Msg: SkGeInitPort() cannot init running ports"
-Reason: You are using a driver compiled for single processor machines
- on a multiprocessor machine with SMP (Symmetric MultiProcessor)
- kernel.
-Solution: Configure your kernel appropriately and recompile the kernel or
- the modules.
-
-
-
-If your problem is not listed here, please contact SysKonnect's technical
-support for help (linux@syskonnect.de).
-When contacting our technical support, please ensure that the following
-information is available:
-- System Manufacturer and HW Informations (CPU, Memory... )
-- PCI-Boards in your system
-- Distribution
-- Kernel version
-- Driver version
-***
-
-
-
-***End of Readme File***
diff --git a/Documentation/networking/spider_net.txt b/Documentation/networking/spider_net.txt
new file mode 100644
index 00000000000..4b4adb8eb14
--- /dev/null
+++ b/Documentation/networking/spider_net.txt
@@ -0,0 +1,204 @@
+
+ The Spidernet Device Driver
+ ===========================
+
+Written by Linas Vepstas <linas@austin.ibm.com>
+
+Version of 7 June 2007
+
+Abstract
+========
+This document sketches the structure of portions of the spidernet
+device driver in the Linux kernel tree. The spidernet is a gigabit
+ethernet device built into the Toshiba southbridge commonly used
+in the SONY Playstation 3 and the IBM QS20 Cell blade.
+
+The Structure of the RX Ring.
+=============================
+The receive (RX) ring is a circular linked list of RX descriptors,
+together with three pointers into the ring that are used to manage its
+contents.
+
+The elements of the ring are called "descriptors" or "descrs"; they
+describe the received data. This includes a pointer to a buffer
+containing the received data, the buffer size, and various status bits.
+
+There are three primary states that a descriptor can be in: "empty",
+"full" and "not-in-use". An "empty" or "ready" descriptor is ready
+to receive data from the hardware. A "full" descriptor has data in it,
+and is waiting to be emptied and processed by the OS. A "not-in-use"
+descriptor is neither empty or full; it is simply not ready. It may
+not even have a data buffer in it, or is otherwise unusable.
+
+During normal operation, on device startup, the OS (specifically, the
+spidernet device driver) allocates a set of RX descriptors and RX
+buffers. These are all marked "empty", ready to receive data. This
+ring is handed off to the hardware, which sequentially fills in the
+buffers, and marks them "full". The OS follows up, taking the full
+buffers, processing them, and re-marking them empty.
+
+This filling and emptying is managed by three pointers, the "head"
+and "tail" pointers, managed by the OS, and a hardware current
+descriptor pointer (GDACTDPA). The GDACTDPA points at the descr
+currently being filled. When this descr is filled, the hardware
+marks it full, and advances the GDACTDPA by one. Thus, when there is
+flowing RX traffic, every descr behind it should be marked "full",
+and everything in front of it should be "empty". If the hardware
+discovers that the current descr is not empty, it will signal an
+interrupt, and halt processing.
+
+The tail pointer tails or trails the hardware pointer. When the
+hardware is ahead, the tail pointer will be pointing at a "full"
+descr. The OS will process this descr, and then mark it "not-in-use",
+and advance the tail pointer. Thus, when there is flowing RX traffic,
+all of the descrs in front of the tail pointer should be "full", and
+all of those behind it should be "not-in-use". When RX traffic is not
+flowing, then the tail pointer can catch up to the hardware pointer.
+The OS will then note that the current tail is "empty", and halt
+processing.
+
+The head pointer (somewhat mis-named) follows after the tail pointer.
+When traffic is flowing, then the head pointer will be pointing at
+a "not-in-use" descr. The OS will perform various housekeeping duties
+on this descr. This includes allocating a new data buffer and
+dma-mapping it so as to make it visible to the hardware. The OS will
+then mark the descr as "empty", ready to receive data. Thus, when there
+is flowing RX traffic, everything in front of the head pointer should
+be "not-in-use", and everything behind it should be "empty". If no
+RX traffic is flowing, then the head pointer can catch up to the tail
+pointer, at which point the OS will notice that the head descr is
+"empty", and it will halt processing.
+
+Thus, in an idle system, the GDACTDPA, tail and head pointers will
+all be pointing at the same descr, which should be "empty". All of the
+other descrs in the ring should be "empty" as well.
+
+The show_rx_chain() routine will print out the the locations of the
+GDACTDPA, tail and head pointers. It will also summarize the contents
+of the ring, starting at the tail pointer, and listing the status
+of the descrs that follow.
+
+A typical example of the output, for a nearly idle system, might be
+
+net eth1: Total number of descrs=256
+net eth1: Chain tail located at descr=20
+net eth1: Chain head is at 20
+net eth1: HW curr desc (GDACTDPA) is at 21
+net eth1: Have 1 descrs with stat=x40800101
+net eth1: HW next desc (GDACNEXTDA) is at 22
+net eth1: Last 255 descrs with stat=xa0800000
+
+In the above, the hardware has filled in one descr, number 20. Both
+head and tail are pointing at 20, because it has not yet been emptied.
+Meanwhile, hw is pointing at 21, which is free.
+
+The "Have nnn decrs" refers to the descr starting at the tail: in this
+case, nnn=1 descr, starting at descr 20. The "Last nnn descrs" refers
+to all of the rest of the descrs, from the last status change. The "nnn"
+is a count of how many descrs have exactly the same status.
+
+The status x4... corresponds to "full" and status xa... corresponds
+to "empty". The actual value printed is RXCOMST_A.
+
+In the device driver source code, a different set of names are
+used for these same concepts, so that
+
+"empty" == SPIDER_NET_DESCR_CARDOWNED == 0xa
+"full" == SPIDER_NET_DESCR_FRAME_END == 0x4
+"not in use" == SPIDER_NET_DESCR_NOT_IN_USE == 0xf
+
+
+The RX RAM full bug/feature
+===========================
+
+As long as the OS can empty out the RX buffers at a rate faster than
+the hardware can fill them, there is no problem. If, for some reason,
+the OS fails to empty the RX ring fast enough, the hardware GDACTDPA
+pointer will catch up to the head, notice the not-empty condition,
+ad stop. However, RX packets may still continue arriving on the wire.
+The spidernet chip can save some limited number of these in local RAM.
+When this local ram fills up, the spider chip will issue an interrupt
+indicating this (GHIINT0STS will show ERRINT, and the GRMFLLINT bit
+will be set in GHIINT1STS). When the RX ram full condition occurs,
+a certain bug/feature is triggered that has to be specially handled.
+This section describes the special handling for this condition.
+
+When the OS finally has a chance to run, it will empty out the RX ring.
+In particular, it will clear the descriptor on which the hardware had
+stopped. However, once the hardware has decided that a certain
+descriptor is invalid, it will not restart at that descriptor; instead
+it will restart at the next descr. This potentially will lead to a
+deadlock condition, as the tail pointer will be pointing at this descr,
+which, from the OS point of view, is empty; the OS will be waiting for
+this descr to be filled. However, the hardware has skipped this descr,
+and is filling the next descrs. Since the OS doesn't see this, there
+is a potential deadlock, with the OS waiting for one descr to fill,
+while the hardware is waiting for a different set of descrs to become
+empty.
+
+A call to show_rx_chain() at this point indicates the nature of the
+problem. A typical print when the network is hung shows the following:
+
+net eth1: Spider RX RAM full, incoming packets might be discarded!
+net eth1: Total number of descrs=256
+net eth1: Chain tail located at descr=255
+net eth1: Chain head is at 255
+net eth1: HW curr desc (GDACTDPA) is at 0
+net eth1: Have 1 descrs with stat=xa0800000
+net eth1: HW next desc (GDACNEXTDA) is at 1
+net eth1: Have 127 descrs with stat=x40800101
+net eth1: Have 1 descrs with stat=x40800001
+net eth1: Have 126 descrs with stat=x40800101
+net eth1: Last 1 descrs with stat=xa0800000
+
+Both the tail and head pointers are pointing at descr 255, which is
+marked xa... which is "empty". Thus, from the OS point of view, there
+is nothing to be done. In particular, there is the implicit assumption
+that everything in front of the "empty" descr must surely also be empty,
+as explained in the last section. The OS is waiting for descr 255 to
+become non-empty, which, in this case, will never happen.
+
+The HW pointer is at descr 0. This descr is marked 0x4.. or "full".
+Since its already full, the hardware can do nothing more, and thus has
+halted processing. Notice that descrs 0 through 254 are all marked
+"full", while descr 254 and 255 are empty. (The "Last 1 descrs" is
+descr 254, since tail was at 255.) Thus, the system is deadlocked,
+and there can be no forward progress; the OS thinks there's nothing
+to do, and the hardware has nowhere to put incoming data.
+
+This bug/feature is worked around with the spider_net_resync_head_ptr()
+routine. When the driver receives RX interrupts, but an examination
+of the RX chain seems to show it is empty, then it is probable that
+the hardware has skipped a descr or two (sometimes dozens under heavy
+network conditions). The spider_net_resync_head_ptr() subroutine will
+search the ring for the next full descr, and the driver will resume
+operations there. Since this will leave "holes" in the ring, there
+is also a spider_net_resync_tail_ptr() that will skip over such holes.
+
+As of this writing, the spider_net_resync() strategy seems to work very
+well, even under heavy network loads.
+
+
+The TX ring
+===========
+The TX ring uses a low-watermark interrupt scheme to make sure that
+the TX queue is appropriately serviced for large packet sizes.
+
+For packet sizes greater than about 1KBytes, the kernel can fill
+the TX ring quicker than the device can drain it. Once the ring
+is full, the netdev is stopped. When there is room in the ring,
+the netdev needs to be reawakened, so that more TX packets are placed
+in the ring. The hardware can empty the ring about four times per jiffy,
+so its not appropriate to wait for the poll routine to refill, since
+the poll routine runs only once per jiffy. The low-watermark mechanism
+marks a descr about 1/4th of the way from the bottom of the queue, so
+that an interrupt is generated when the descr is processed. This
+interrupt wakes up the netdev, which can then refill the queue.
+For large packets, this mechanism generates a relatively small number
+of interrupts, about 1K/sec. For smaller packets, this will drop to zero
+interrupts, as the hardware can empty the queue faster than the kernel
+can fill it.
+
+
+ ======= END OF DOCUMENT ========
+
diff --git a/Documentation/networking/xfrm_sysctl.txt b/Documentation/networking/xfrm_sysctl.txt
new file mode 100644
index 00000000000..5bbd16792fe
--- /dev/null
+++ b/Documentation/networking/xfrm_sysctl.txt
@@ -0,0 +1,4 @@
+/proc/sys/net/core/xfrm_* Variables:
+
+xfrm_acq_expires - INTEGER
+ default 30 - hard timeout in seconds for acquire requests
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index d38261b6790..7754f5aea4e 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -113,9 +113,6 @@ initialization with a pointer to a structure describing the driver
(Please see Documentation/power/pci.txt for descriptions
of PCI Power Management and the related functions.)
- enable_wake Enable device to generate wake events from a low power
- state.
-
shutdown Hook into reboot_notifier_list (kernel/sys.c).
Intended to stop any idling DMA operations.
Useful for enabling wake-on-lan (NIC) or changing
@@ -299,7 +296,10 @@ If the PCI device can use the PCI Memory-Write-Invalidate transaction,
call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
and also ensures that the cache line size register is set correctly.
Check the return value of pci_set_mwi() as not all architectures
-or chip-sets may support Memory-Write-Invalidate.
+or chip-sets may support Memory-Write-Invalidate. Alternatively,
+if Mem-Wr-Inval would be nice to have but is not required, call
+pci_try_set_mwi() to have the system do its best effort at enabling
+Mem-Wr-Inval.
3.2 Request MMIO/IOP resources
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index e00b099a4b8..dd8fe43888d 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -164,7 +164,6 @@ struct pci_driver:
int (*suspend) (struct pci_dev *dev, pm_message_t state);
int (*resume) (struct pci_dev *dev);
- int (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable);
suspend
@@ -251,42 +250,6 @@ The driver should update the current_state field in its pci_dev structure in
this function, except for PM-capable devices when pci_set_power_state is used.
-enable_wake
------------
-
-Usage:
-
-if (dev->driver && dev->driver->enable_wake)
- dev->driver->enable_wake(dev,state,enable);
-
-This callback is generally only relevant for devices that support the PCI PM
-spec and have the ability to generate a PME# (Power Management Event Signal)
-to wake the system up. (However, it is possible that a device may support
-some non-standard way of generating a wake event on sleep.)
-
-Bits 15:11 of the PMC (Power Mgmt Capabilities) Register in a device's
-PM Capabilities describe what power states the device supports generating a
-wake event from:
-
-+------------------+
-| Bit | State |
-+------------------+
-| 11 | D0 |
-| 12 | D1 |
-| 13 | D2 |
-| 14 | D3hot |
-| 15 | D3cold |
-+------------------+
-
-A device can use this to enable wake events:
-
- pci_enable_wake(dev,state,enable);
-
-Note that to enable PME# from D3cold, a value of 4 should be passed to
-pci_enable_wake (since it uses an index into a bitmask). If a driver gets
-a request to enable wake events from D3, two calls should be made to
-pci_enable_wake (one for both D3hot and D3cold).
-
A reference implementation
-------------------------
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 5b8d6953f05..152b510d1bb 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -393,6 +393,9 @@ safest thing is to unmount all filesystems on removable media (such USB,
Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays)
before suspending; then remount them after resuming.
+There is a work-around for this problem. For more information, see
+Documentation/usb/persist.txt.
+
Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
compiled with the similar configuration files. Anyway I found that
suspend to disk (and resume) is much slower on 2.6.16 compared to
diff --git a/Documentation/power_supply_class.txt b/Documentation/power_supply_class.txt
new file mode 100644
index 00000000000..9758cf433c0
--- /dev/null
+++ b/Documentation/power_supply_class.txt
@@ -0,0 +1,167 @@
+Linux power supply class
+========================
+
+Synopsis
+~~~~~~~~
+Power supply class used to represent battery, UPS, AC or DC power supply
+properties to user-space.
+
+It defines core set of attributes, which should be applicable to (almost)
+every power supply out there. Attributes are available via sysfs and uevent
+interfaces.
+
+Each attribute has well defined meaning, up to unit of measure used. While
+the attributes provided are believed to be universally applicable to any
+power supply, specific monitoring hardware may not be able to provide them
+all, so any of them may be skipped.
+
+Power supply class is extensible, and allows to define drivers own attributes.
+The core attribute set is subject to the standard Linux evolution (i.e.
+if it will be found that some attribute is applicable to many power supply
+types or their drivers, it can be added to the core set).
+
+It also integrates with LED framework, for the purpose of providing
+typically expected feedback of battery charging/fully charged status and
+AC/USB power supply online status. (Note that specific details of the
+indication (including whether to use it at all) are fully controllable by
+user and/or specific machine defaults, per design principles of LED
+framework).
+
+
+Attributes/properties
+~~~~~~~~~~~~~~~~~~~~~
+Power supply class has predefined set of attributes, this eliminates code
+duplication across drivers. Power supply class insist on reusing its
+predefined attributes *and* their units.
+
+So, userspace gets predictable set of attributes and their units for any
+kind of power supply, and can process/present them to a user in consistent
+manner. Results for different power supplies and machines are also directly
+comparable.
+
+See drivers/power/ds2760_battery.c and drivers/power/pda_power.c for the
+example how to declare and handle attributes.
+
+
+Units
+~~~~~
+Quoting include/linux/power_supply.h:
+
+ All voltages, currents, charges, energies, time and temperatures in µV,
+ µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ stated. It's driver's job to convert its raw values to units in which
+ this class operates.
+
+
+Attributes/properties detailed
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+~ ~ ~ ~ ~ ~ ~ Charge/Energy/Capacity - how to not confuse ~ ~ ~ ~ ~ ~ ~
+~ ~
+~ Because both "charge" (µAh) and "energy" (µWh) represents "capacity" ~
+~ of battery, this class distinguish these terms. Don't mix them! ~
+~ ~
+~ CHARGE_* attributes represents capacity in µAh only. ~
+~ ENERGY_* attributes represents capacity in µWh only. ~
+~ CAPACITY attribute represents capacity in *percents*, from 0 to 100. ~
+~ ~
+~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+Postfixes:
+_AVG - *hardware* averaged value, use it if your hardware is really able to
+report averaged values.
+_NOW - momentary/instantaneous values.
+
+STATUS - this attribute represents operating status (charging, full,
+discharging (i.e. powering a load), etc.). This corresponds to
+BATTERY_STATUS_* values, as defined in battery.h.
+
+HEALTH - represents health of the battery, values corresponds to
+POWER_SUPPLY_HEALTH_*, defined in battery.h.
+
+VOLTAGE_MAX_DESIGN, VOLTAGE_MIN_DESIGN - design values for maximal and
+minimal power supply voltages. Maximal/minimal means values of voltages
+when battery considered "full"/"empty" at normal conditions. Yes, there is
+no direct relation between voltage and battery capacity, but some dumb
+batteries use voltage for very approximated calculation of capacity.
+Battery driver also can use this attribute just to inform userspace
+about maximal and minimal voltage thresholds of a given battery.
+
+CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when
+battery considered full/empty.
+
+ENERGY_FULL_DESIGN, ENERGY_EMPTY_DESIGN - same as above but for energy.
+
+CHARGE_FULL, CHARGE_EMPTY - These attributes means "last remembered value
+of charge when battery became full/empty". It also could mean "value of
+charge when battery considered full/empty at given conditions (temperature,
+age)". I.e. these attributes represents real thresholds, not design values.
+
+ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
+
+CAPACITY - capacity in percents.
+CAPACITY_LEVEL - capacity level. This corresponds to
+POWER_SUPPLY_CAPACITY_LEVEL_*.
+
+TEMP - temperature of the power supply.
+TEMP_AMBIENT - ambient temperature.
+
+TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e.
+while battery powers a load)
+TIME_TO_FULL - seconds left for battery to be considered full (i.e.
+while battery is charging)
+
+
+Battery <-> external power supply interaction
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Often power supplies are acting as supplies and supplicants at the same
+time. Batteries are good example. So, batteries usually care if they're
+externally powered or not.
+
+For that case, power supply class implements notification mechanism for
+batteries.
+
+External power supply (AC) lists supplicants (batteries) names in
+"supplied_to" struct member, and each power_supply_changed() call
+issued by external power supply will notify supplicants via
+external_power_changed callback.
+
+
+QA
+~~
+Q: Where is POWER_SUPPLY_PROP_XYZ attribute?
+A: If you cannot find attribute suitable for your driver needs, feel free
+ to add it and send patch along with your driver.
+
+ The attributes available currently are the ones currently provided by the
+ drivers written.
+
+ Good candidates to add in future: model/part#, cycle_time, manufacturer,
+ etc.
+
+
+Q: I have some very specific attribute (e.g. battery color), should I add
+ this attribute to standard ones?
+A: Most likely, no. Such attribute can be placed in the driver itself, if
+ it is useful. Of course, if the attribute in question applicable to
+ large set of batteries, provided by many drivers, and/or comes from
+ some general battery specification/standard, it may be a candidate to
+ be added to the core attribute set.
+
+
+Q: Suppose, my battery monitoring chip/firmware does not provides capacity
+ in percents, but provides charge_{now,full,empty}. Should I calculate
+ percentage capacity manually, inside the driver, and register CAPACITY
+ attribute? The same question about time_to_empty/time_to_full.
+A: Most likely, no. This class is designed to export properties which are
+ directly measurable by the specific hardware available.
+
+ Inferring not available properties using some heuristics or mathematical
+ model is not subject of work for a battery driver. Such functionality
+ should be factored out, and in fact, apm_power, the driver to serve
+ legacy APM API on top of power supply class, uses a simple heuristic of
+ approximating remaining battery capacity based on its charge, current,
+ voltage and so on. But full-fledged battery model is likely not subject
+ for kernel at all, as it would require floating point calculation to deal
+ with things like differential equations and Kalman filters. This is
+ better be handled by batteryd/libbattery, yet to be written.
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt
index b49ce169a63..d42d98107d4 100644
--- a/Documentation/powerpc/booting-without-of.txt
+++ b/Documentation/powerpc/booting-without-of.txt
@@ -1,7 +1,6 @@
Booting the Linux/ppc kernel without Open Firmware
--------------------------------------------------
-
(c) 2005 Benjamin Herrenschmidt <benh at kernel.crashing.org>,
IBM Corp.
(c) 2005 Becky Bruce <becky.bruce at freescale.com>,
@@ -9,6 +8,62 @@
(c) 2006 MontaVista Software, Inc.
Flash chip node definition
+Table of Contents
+=================
+
+ I - Introduction
+ 1) Entry point for arch/powerpc
+ 2) Board support
+
+ II - The DT block format
+ 1) Header
+ 2) Device tree generalities
+ 3) Device tree "structure" block
+ 4) Device tree "strings" block
+
+ III - Required content of the device tree
+ 1) Note about cells and address representation
+ 2) Note about "compatible" properties
+ 3) Note about "name" properties
+ 4) Note about node and property names and character set
+ 5) Required nodes and properties
+ a) The root node
+ b) The /cpus node
+ c) The /cpus/* nodes
+ d) the /memory node(s)
+ e) The /chosen node
+ f) the /soc<SOCname> node
+
+ IV - "dtc", the device tree compiler
+
+ V - Recommendations for a bootloader
+
+ VI - System-on-a-chip devices and nodes
+ 1) Defining child nodes of an SOC
+ 2) Representing devices without a current OF specification
+ a) MDIO IO device
+ c) PHY nodes
+ b) Gianfar-compatible ethernet nodes
+ d) Interrupt controllers
+ e) I2C
+ f) Freescale SOC USB controllers
+ g) Freescale SOC SEC Security Engines
+ h) Board Control and Status (BCSR)
+ i) Freescale QUICC Engine module (QE)
+ g) Flash chip nodes
+
+ VII - Specifying interrupt information for devices
+ 1) interrupts property
+ 2) interrupt-parent property
+ 3) OpenPIC Interrupt Controllers
+ 4) ISA Interrupt Controllers
+
+ Appendix A - Sample SOC node for MPC8540
+
+
+Revision Information
+====================
+
May 18, 2005: Rev 0.1 - Initial draft, no chapter III yet.
May 19, 2005: Rev 0.2 - Add chapter III and bits & pieces here or
@@ -1687,7 +1742,7 @@ platforms are moved over to use the flattened-device-tree model.
};
};
- g) Flash chip nodes
+ j) Flash chip nodes
Flash chips (Memory Technology Devices) are often used for solid state
file systems on embedded devices.
diff --git a/Documentation/sched-design-CFS.txt b/Documentation/sched-design-CFS.txt
new file mode 100644
index 00000000000..16feebb7bdc
--- /dev/null
+++ b/Documentation/sched-design-CFS.txt
@@ -0,0 +1,119 @@
+
+This is the CFS scheduler.
+
+80% of CFS's design can be summed up in a single sentence: CFS basically
+models an "ideal, precise multi-tasking CPU" on real hardware.
+
+"Ideal multi-tasking CPU" is a (non-existent :-)) CPU that has 100%
+physical power and which can run each task at precise equal speed, in
+parallel, each at 1/nr_running speed. For example: if there are 2 tasks
+running then it runs each at 50% physical power - totally in parallel.
+
+On real hardware, we can run only a single task at once, so while that
+one task runs, the other tasks that are waiting for the CPU are at a
+disadvantage - the current task gets an unfair amount of CPU time. In
+CFS this fairness imbalance is expressed and tracked via the per-task
+p->wait_runtime (nanosec-unit) value. "wait_runtime" is the amount of
+time the task should now run on the CPU for it to become completely fair
+and balanced.
+
+( small detail: on 'ideal' hardware, the p->wait_runtime value would
+ always be zero - no task would ever get 'out of balance' from the
+ 'ideal' share of CPU time. )
+
+CFS's task picking logic is based on this p->wait_runtime value and it
+is thus very simple: it always tries to run the task with the largest
+p->wait_runtime value. In other words, CFS tries to run the task with
+the 'gravest need' for more CPU time. So CFS always tries to split up
+CPU time between runnable tasks as close to 'ideal multitasking
+hardware' as possible.
+
+Most of the rest of CFS's design just falls out of this really simple
+concept, with a few add-on embellishments like nice levels,
+multiprocessing and various algorithm variants to recognize sleepers.
+
+In practice it works like this: the system runs a task a bit, and when
+the task schedules (or a scheduler tick happens) the task's CPU usage is
+'accounted for': the (small) time it just spent using the physical CPU
+is deducted from p->wait_runtime. [minus the 'fair share' it would have
+gotten anyway]. Once p->wait_runtime gets low enough so that another
+task becomes the 'leftmost task' of the time-ordered rbtree it maintains
+(plus a small amount of 'granularity' distance relative to the leftmost
+task so that we do not over-schedule tasks and trash the cache) then the
+new leftmost task is picked and the current task is preempted.
+
+The rq->fair_clock value tracks the 'CPU time a runnable task would have
+fairly gotten, had it been runnable during that time'. So by using
+rq->fair_clock values we can accurately timestamp and measure the
+'expected CPU time' a task should have gotten. All runnable tasks are
+sorted in the rbtree by the "rq->fair_clock - p->wait_runtime" key, and
+CFS picks the 'leftmost' task and sticks to it. As the system progresses
+forwards, newly woken tasks are put into the tree more and more to the
+right - slowly but surely giving a chance for every task to become the
+'leftmost task' and thus get on the CPU within a deterministic amount of
+time.
+
+Some implementation details:
+
+ - the introduction of Scheduling Classes: an extensible hierarchy of
+ scheduler modules. These modules encapsulate scheduling policy
+ details and are handled by the scheduler core without the core
+ code assuming about them too much.
+
+ - sched_fair.c implements the 'CFS desktop scheduler': it is a
+ replacement for the vanilla scheduler's SCHED_OTHER interactivity
+ code.
+
+ I'd like to give credit to Con Kolivas for the general approach here:
+ he has proven via RSDL/SD that 'fair scheduling' is possible and that
+ it results in better desktop scheduling. Kudos Con!
+
+ The CFS patch uses a completely different approach and implementation
+ from RSDL/SD. My goal was to make CFS's interactivity quality exceed
+ that of RSDL/SD, which is a high standard to meet :-) Testing
+ feedback is welcome to decide this one way or another. [ and, in any
+ case, all of SD's logic could be added via a kernel/sched_sd.c module
+ as well, if Con is interested in such an approach. ]
+
+ CFS's design is quite radical: it does not use runqueues, it uses a
+ time-ordered rbtree to build a 'timeline' of future task execution,
+ and thus has no 'array switch' artifacts (by which both the vanilla
+ scheduler and RSDL/SD are affected).
+
+ CFS uses nanosecond granularity accounting and does not rely on any
+ jiffies or other HZ detail. Thus the CFS scheduler has no notion of
+ 'timeslices' and has no heuristics whatsoever. There is only one
+ central tunable:
+
+ /proc/sys/kernel/sched_granularity_ns
+
+ which can be used to tune the scheduler from 'desktop' (low
+ latencies) to 'server' (good batching) workloads. It defaults to a
+ setting suitable for desktop workloads. SCHED_BATCH is handled by the
+ CFS scheduler module too.
+
+ Due to its design, the CFS scheduler is not prone to any of the
+ 'attacks' that exist today against the heuristics of the stock
+ scheduler: fiftyp.c, thud.c, chew.c, ring-test.c, massive_intr.c all
+ work fine and do not impact interactivity and produce the expected
+ behavior.
+
+ the CFS scheduler has a much stronger handling of nice levels and
+ SCHED_BATCH: both types of workloads should be isolated much more
+ agressively than under the vanilla scheduler.
+
+ ( another detail: due to nanosec accounting and timeline sorting,
+ sched_yield() support is very simple under CFS, and in fact under
+ CFS sched_yield() behaves much better than under any other
+ scheduler i have tested so far. )
+
+ - sched_rt.c implements SCHED_FIFO and SCHED_RR semantics, in a simpler
+ way than the vanilla scheduler does. It uses 100 runqueues (for all
+ 100 RT priority levels, instead of 140 in the vanilla scheduler)
+ and it needs no expired array.
+
+ - reworked/sanitized SMP load-balancing: the runqueue-walking
+ assumptions are gone from the load-balancing code now, and
+ iterators of the scheduling modules are used. The balancing code got
+ quite a bit simpler as a result.
+
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 57b878cc393..355ff0a2bb7 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -917,6 +917,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
ref Reference board, base config
m2-2 Some Gateway MX series laptops
m6 Some Gateway NX series laptops
+ pa6 Gateway NX860 series
STAC9227/9228/9229/927x
ref Reference board
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 1d192565e18..8cfca173d4b 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -31,6 +31,7 @@ Currently, these files are in /proc/sys/vm:
- min_unmapped_ratio
- min_slab_ratio
- panic_on_oom
+- mmap_min_address
==============================================================
@@ -216,3 +217,17 @@ above-mentioned.
The default value is 0.
1 and 2 are for failover of clustering. Please select either
according to your policy of failover.
+
+==============================================================
+
+mmap_min_addr
+
+This file indicates the amount of address space which a user process will
+be restricted from mmaping. Since kernel null dereference bugs could
+accidentally operate based on the information in the first couple of pages
+of memory userspace processes should not be allowed to write to them. By
+default this value is set to 0 and no protections will be enforced by the
+security module. Setting this value to something like 64k will allow the
+vast majority of applications to work correctly and provide defense in depth
+against future potential kernel bugs.
+
diff --git a/Documentation/sysfs-rules.txt b/Documentation/sysfs-rules.txt
new file mode 100644
index 00000000000..42861bb0bc9
--- /dev/null
+++ b/Documentation/sysfs-rules.txt
@@ -0,0 +1,166 @@
+Rules on how to access information in the Linux kernel sysfs
+
+The kernel exported sysfs exports internal kernel implementation-details
+and depends on internal kernel structures and layout. It is agreed upon
+by the kernel developers that the Linux kernel does not provide a stable
+internal API. As sysfs is a direct export of kernel internal
+structures, the sysfs interface can not provide a stable interface eighter,
+it may always change along with internal kernel changes.
+
+To minimize the risk of breaking users of sysfs, which are in most cases
+low-level userspace applications, with a new kernel release, the users
+of sysfs must follow some rules to use an as abstract-as-possible way to
+access this filesystem. The current udev and HAL programs already
+implement this and users are encouraged to plug, if possible, into the
+abstractions these programs provide instead of accessing sysfs
+directly.
+
+But if you really do want or need to access sysfs directly, please follow
+the following rules and then your programs should work with future
+versions of the sysfs interface.
+
+- Do not use libsysfs
+ It makes assumptions about sysfs which are not true. Its API does not
+ offer any abstraction, it exposes all the kernel driver-core
+ implementation details in its own API. Therefore it is not better than
+ reading directories and opening the files yourself.
+ Also, it is not actively maintained, in the sense of reflecting the
+ current kernel-development. The goal of providing a stable interface
+ to sysfs has failed, it causes more problems, than it solves. It
+ violates many of the rules in this document.
+
+- sysfs is always at /sys
+ Parsing /proc/mounts is a waste of time. Other mount points are a
+ system configuration bug you should not try to solve. For test cases,
+ possibly support a SYSFS_PATH environment variable to overwrite the
+ applications behavior, but never try to search for sysfs. Never try
+ to mount it, if you are not an early boot script.
+
+- devices are only "devices"
+ There is no such thing like class-, bus-, physical devices,
+ interfaces, and such that you can rely on in userspace. Everything is
+ just simply a "device". Class-, bus-, physical, ... types are just
+ kernel implementation details, which should not be expected by
+ applications that look for devices in sysfs.
+
+ The properties of a device are:
+ o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0)
+ - identical to the DEVPATH value in the event sent from the kernel
+ at device creation and removal
+ - the unique key to the device at that point in time
+ - the kernels path to the device-directory without the leading
+ /sys, and always starting with with a slash
+ - all elements of a devpath must be real directories. Symlinks
+ pointing to /sys/devices must always be resolved to their real
+ target, and the target path must be used to access the device.
+ That way the devpath to the device matches the devpath of the
+ kernel used at event time.
+ - using or exposing symlink values as elements in a devpath string
+ is a bug in the application
+
+ o kernel name (sda, tty, 0000:00:1f.2, ...)
+ - a directory name, identical to the last element of the devpath
+ - applications need to handle spaces and characters like '!' in
+ the name
+
+ o subsystem (block, tty, pci, ...)
+ - simple string, never a path or a link
+ - retrieved by reading the "subsystem"-link and using only the
+ last element of the target path
+
+ o driver (tg3, ata_piix, uhci_hcd)
+ - a simple string, which may contain spaces, never a path or a
+ link
+ - it is retrieved by reading the "driver"-link and using only the
+ last element of the target path
+ - devices which do not have "driver"-link, just do not have a
+ driver; copying the driver value in a child device context, is a
+ bug in the application
+
+ o attributes
+ - the files in the device directory or files below a subdirectories
+ of the same device directory
+ - accessing attributes reached by a symlink pointing to another device,
+ like the "device"-link, is a bug in the application
+
+ Everything else is just a kernel driver-core implementation detail,
+ that should not be assumed to be stable across kernel releases.
+
+- Properties of parent devices never belong into a child device.
+ Always look at the parent devices themselves for determining device
+ context properties. If the device 'eth0' or 'sda' does not have a
+ "driver"-link, then this device does not have a driver. Its value is empty.
+ Never copy any property of the parent-device into a child-device. Parent
+ device-properties may change dynamically without any notice to the
+ child device.
+
+- Hierarchy in a single device-tree
+ There is only one valid place in sysfs where hierarchy can be examined
+ and this is below: /sys/devices.
+ It is planned, that all device directories will end up in the tree
+ below this directory.
+
+- Classification by subsystem
+ There are currently three places for classification of devices:
+ /sys/block, /sys/class and /sys/bus. It is planned that these will
+ not contain any device-directories themselves, but only flat lists of
+ symlinks pointing to the unified /sys/devices tree.
+ All three places have completely different rules on how to access
+ device information. It is planned to merge all three
+ classification-directories into one place at /sys/subsystem,
+ following the layout of the bus-directories. All buses and
+ classes, including the converted block-subsystem, will show up
+ there.
+ The devices belonging to a subsystem will create a symlink in the
+ "devices" directory at /sys/subsystem/<name>/devices.
+
+ If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
+ ignored. If it does not exist, you have always to scan all three
+ places, as the kernel is free to move a subsystem from one place to
+ the other, as long as the devices are still reachable by the same
+ subsystem name.
+
+ Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or
+ /sys/block and /sys/class/block are not interchangeable, is a bug in
+ the application.
+
+- Block
+ The converted block-subsystem at /sys/class/block, or
+ /sys/subsystem/block will contain the links for disks and partitions
+ at the same level, never in a hierarchy. Assuming the block-subsytem to
+ contain only disks and not partition-devices in the same flat list is
+ a bug in the application.
+
+- "device"-link and <subsystem>:<kernel name>-links
+ Never depend on the "device"-link. The "device"-link is a workaround
+ for the old layout, where class-devices are not created in
+ /sys/devices/ like the bus-devices. If the link-resolving of a
+ device-directory does not end in /sys/devices/, you can use the
+ "device"-link to find the parent devices in /sys/devices/. That is the
+ single valid use of the "device"-link, it must never appear in any
+ path as an element. Assuming the existence of the "device"-link for
+ a device in /sys/devices/ is a bug in the application.
+ Accessing /sys/class/net/eth0/device is a bug in the application.
+
+ Never depend on the class-specific links back to the /sys/class
+ directory. These links are also a workaround for the design mistake
+ that class-devices are not created in /sys/devices. If a device
+ directory does not contain directories for child devices, these links
+ may be used to find the child devices in /sys/class. That is the single
+ valid use of these links, they must never appear in any path as an
+ element. Assuming the existence of these links for devices which are
+ real child device directories in the /sys/devices tree, is a bug in
+ the application.
+
+ It is planned to remove all these links when when all class-device
+ directories live in /sys/devices.
+
+- Position of devices along device chain can change.
+ Never depend on a specific parent device position in the devpath,
+ or the chain of parent devices. The kernel is free to insert devices into
+ the chain. You must always request the parent device you are looking for
+ by its subsystem value. You need to walk up the chain until you find
+ the device that matches the expected subsystem. Depending on a specific
+ position of a parent device, or exposing relative paths, using "../" to
+ access the chain of parents, is a bug in the application.
+
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt
index 2d4803359a0..9e6b94face4 100644
--- a/Documentation/thinkpad-acpi.txt
+++ b/Documentation/thinkpad-acpi.txt
@@ -138,7 +138,7 @@ Hot keys
--------
procfs: /proc/acpi/ibm/hotkey
-sysfs device attribute: hotkey/*
+sysfs device attribute: hotkey_*
Without this driver, only the Fn-F4 key (sleep button) generates an
ACPI event. With the driver loaded, the hotkey feature enabled and the
@@ -196,10 +196,7 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file:
sysfs notes:
- The hot keys attributes are in a hotkey/ subdirectory off the
- thinkpad device.
-
- bios_enabled:
+ hotkey_bios_enabled:
Returns the status of the hot keys feature when
thinkpad-acpi was loaded. Upon module unload, the hot
key feature status will be restored to this value.
@@ -207,19 +204,19 @@ sysfs notes:
0: hot keys were disabled
1: hot keys were enabled
- bios_mask:
+ hotkey_bios_mask:
Returns the hot keys mask when thinkpad-acpi was loaded.
Upon module unload, the hot keys mask will be restored
to this value.
- enable:
+ hotkey_enable:
Enables/disables the hot keys feature, and reports
current status of the hot keys feature.
0: disables the hot keys feature / feature disabled
1: enables the hot keys feature / feature enabled
- mask:
+ hotkey_mask:
bit mask to enable ACPI event generation for each hot
key (see above). Returns the current status of the hot
keys mask, and allows one to modify it.
@@ -229,7 +226,7 @@ Bluetooth
---------
procfs: /proc/acpi/ibm/bluetooth
-sysfs device attribute: bluetooth/enable
+sysfs device attribute: bluetooth_enable
This feature shows the presence and current state of a ThinkPad
Bluetooth device in the internal ThinkPad CDC slot.
@@ -244,7 +241,7 @@ If Bluetooth is installed, the following commands can be used:
Sysfs notes:
If the Bluetooth CDC card is installed, it can be enabled /
- disabled through the "bluetooth/enable" thinkpad-acpi device
+ disabled through the "bluetooth_enable" thinkpad-acpi device
attribute, and its current status can also be queried.
enable:
@@ -252,7 +249,7 @@ Sysfs notes:
1: enables Bluetooth / Bluetooth is enabled.
Note: this interface will be probably be superseeded by the
- generic rfkill class.
+ generic rfkill class, so it is NOT to be considered stable yet.
Video output control -- /proc/acpi/ibm/video
--------------------------------------------
@@ -898,7 +895,7 @@ EXPERIMENTAL: WAN
-----------------
procfs: /proc/acpi/ibm/wan
-sysfs device attribute: wwan/enable
+sysfs device attribute: wwan_enable
This feature is marked EXPERIMENTAL because the implementation
directly accesses hardware registers and may not work as expected. USE
@@ -921,7 +918,7 @@ If the W-WAN card is installed, the following commands can be used:
Sysfs notes:
If the W-WAN card is installed, it can be enabled /
- disabled through the "wwan/enable" thinkpad-acpi device
+ disabled through the "wwan_enable" thinkpad-acpi device
attribute, and its current status can also be queried.
enable:
@@ -929,7 +926,7 @@ Sysfs notes:
1: enables WWAN card / WWAN card is enabled.
Note: this interface will be probably be superseeded by the
- generic rfkill class.
+ generic rfkill class, so it is NOT to be considered stable yet.
Multiple Commands, Module Parameters
------------------------------------
diff --git a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt
index 62844aeba69..e8b50b7de9d 100644
--- a/Documentation/usb/dma.txt
+++ b/Documentation/usb/dma.txt
@@ -32,12 +32,15 @@ ELIMINATING COPIES
It's good to avoid making CPUs copy data needlessly. The costs can add up,
and effects like cache-trashing can impose subtle penalties.
-- When you're allocating a buffer for DMA purposes anyway, use the buffer
- primitives. Think of them as kmalloc and kfree that give you the right
- kind of addresses to store in urb->transfer_buffer and urb->transfer_dma,
- while guaranteeing that no hidden copies through DMA "bounce" buffers will
- slow things down. You'd also set URB_NO_TRANSFER_DMA_MAP in
- urb->transfer_flags:
+- If you're doing lots of small data transfers from the same buffer all
+ the time, that can really burn up resources on systems which use an
+ IOMMU to manage the DMA mappings. It can cost MUCH more to set up and
+ tear down the IOMMU mappings with each request than perform the I/O!
+
+ For those specific cases, USB has primitives to allocate less expensive
+ memory. They work like kmalloc and kfree versions that give you the right
+ kind of addresses to store in urb->transfer_buffer and urb->transfer_dma.
+ You'd also set URB_NO_TRANSFER_DMA_MAP in urb->transfer_flags:
void *usb_buffer_alloc (struct usb_device *dev, size_t size,
int mem_flags, dma_addr_t *dma);
@@ -45,6 +48,10 @@ and effects like cache-trashing can impose subtle penalties.
void usb_buffer_free (struct usb_device *dev, size_t size,
void *addr, dma_addr_t dma);
+ Most drivers should *NOT* be using these primitives; they don't need
+ to use this type of memory ("dma-coherent"), and memory returned from
+ kmalloc() will work just fine.
+
For control transfers you can use the buffer primitives or not for each
of the transfer buffer and setup buffer independently. Set the flag bits
URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP to indicate which
@@ -54,29 +61,39 @@ and effects like cache-trashing can impose subtle penalties.
The memory buffer returned is "dma-coherent"; sometimes you might need to
force a consistent memory access ordering by using memory barriers. It's
not using a streaming DMA mapping, so it's good for small transfers on
- systems where the I/O would otherwise tie up an IOMMU mapping. (See
+ systems where the I/O would otherwise thrash an IOMMU mapping. (See
Documentation/DMA-mapping.txt for definitions of "coherent" and "streaming"
DMA mappings.)
Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
space-efficient.
+ On most systems the memory returned will be uncached, because the
+ semantics of dma-coherent memory require either bypassing CPU caches
+ or using cache hardware with bus-snooping support. While x86 hardware
+ has such bus-snooping, many other systems use software to flush cache
+ lines to prevent DMA conflicts.
+
- Devices on some EHCI controllers could handle DMA to/from high memory.
- Driver probe() routines can notice this using a generic DMA call, then
- tell higher level code (network, scsi, etc) about it like this:
- if (dma_supported (&intf->dev, 0xffffffffffffffffULL))
- net->features |= NETIF_F_HIGHDMA;
+ Unfortunately, the current Linux DMA infrastructure doesn't have a sane
+ way to expose these capabilities ... and in any case, HIGHMEM is mostly a
+ design wart specific to x86_32. So your best bet is to ensure you never
+ pass a highmem buffer into a USB driver. That's easy; it's the default
+ behavior. Just don't override it; e.g. with NETIF_F_HIGHDMA.
- That can eliminate dma bounce buffering of requests that originate (or
- terminate) in high memory, in cases where the buffers aren't allocated
- with usb_buffer_alloc() but instead are dma-mapped.
+ This may force your callers to do some bounce buffering, copying from
+ high memory to "normal" DMA memory. If you can come up with a good way
+ to fix this issue (for x86_32 machines with over 1 GByte of memory),
+ feel free to submit patches.
WORKING WITH EXISTING BUFFERS
Existing buffers aren't usable for DMA without first being mapped into the
-DMA address space of the device.
+DMA address space of the device. However, most buffers passed to your
+driver can safely be used with such DMA mapping. (See the first section
+of DMA-mapping.txt, titled "What memory is DMA-able?")
- When you're using scatterlists, you can map everything at once. On some
systems, this kicks in an IOMMU and turns the scatterlists into single
@@ -114,3 +131,8 @@ DMA address space of the device.
The calls manage urb->transfer_dma for you, and set URB_NO_TRANSFER_DMA_MAP
so that usbcore won't map or unmap the buffer. The same goes for
urb->setup_dma and URB_NO_SETUP_DMA_MAP for control requests.
+
+Note that several of those interfaces are currently commented out, since
+they don't have current users. See the source code. Other than the dmasync
+calls (where the underlying DMA primitives have changed), most of them can
+easily be commented back in if you want to use them.
diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
new file mode 100644
index 00000000000..df54d645cbb
--- /dev/null
+++ b/Documentation/usb/persist.txt
@@ -0,0 +1,156 @@
+ USB device persistence during system suspend
+
+ Alan Stern <stern@rowland.harvard.edu>
+
+ September 2, 2006 (Updated May 29, 2007)
+
+
+ What is the problem?
+
+According to the USB specification, when a USB bus is suspended the
+bus must continue to supply suspend current (around 1-5 mA). This
+is so that devices can maintain their internal state and hubs can
+detect connect-change events (devices being plugged in or unplugged).
+The technical term is "power session".
+
+If a USB device's power session is interrupted then the system is
+required to behave as though the device has been unplugged. It's a
+conservative approach; in the absence of suspend current the computer
+has no way to know what has actually happened. Perhaps the same
+device is still attached or perhaps it was removed and a different
+device plugged into the port. The system must assume the worst.
+
+By default, Linux behaves according to the spec. If a USB host
+controller loses power during a system suspend, then when the system
+wakes up all the devices attached to that controller are treated as
+though they had disconnected. This is always safe and it is the
+"officially correct" thing to do.
+
+For many sorts of devices this behavior doesn't matter in the least.
+If the kernel wants to believe that your USB keyboard was unplugged
+while the system was asleep and a new keyboard was plugged in when the
+system woke up, who cares? It'll still work the same when you type on
+it.
+
+Unfortunately problems _can_ arise, particularly with mass-storage
+devices. The effect is exactly the same as if the device really had
+been unplugged while the system was suspended. If you had a mounted
+filesystem on the device, you're out of luck -- everything in that
+filesystem is now inaccessible. This is especially annoying if your
+root filesystem was located on the device, since your system will
+instantly crash.
+
+Loss of power isn't the only mechanism to worry about. Anything that
+interrupts a power session will have the same effect. For example,
+even though suspend current may have been maintained while the system
+was asleep, on many systems during the initial stages of wakeup the
+firmware (i.e., the BIOS) resets the motherboard's USB host
+controllers. Result: all the power sessions are destroyed and again
+it's as though you had unplugged all the USB devices. Yes, it's
+entirely the BIOS's fault, but that doesn't do _you_ any good unless
+you can convince the BIOS supplier to fix the problem (lots of luck!).
+
+On many systems the USB host controllers will get reset after a
+suspend-to-RAM. On almost all systems, no suspend current is
+available during hibernation (also known as swsusp or suspend-to-disk).
+You can check the kernel log after resuming to see if either of these
+has happened; look for lines saying "root hub lost power or was reset".
+
+In practice, people are forced to unmount any filesystems on a USB
+device before suspending. If the root filesystem is on a USB device,
+the system can't be suspended at all. (All right, it _can_ be
+suspended -- but it will crash as soon as it wakes up, which isn't
+much better.)
+
+
+ What is the solution?
+
+Setting CONFIG_USB_PERSIST will cause the kernel to work around these
+issues. It enables a mode in which the core USB device data
+structures are allowed to persist across a power-session disruption.
+It works like this. If the kernel sees that a USB host controller is
+not in the expected state during resume (i.e., if the controller was
+reset or otherwise had lost power) then it applies a persistence check
+to each of the USB devices below that controller for which the
+"persist" attribute is set. It doesn't try to resume the device; that
+can't work once the power session is gone. Instead it issues a USB
+port reset and then re-enumerates the device. (This is exactly the
+same thing that happens whenever a USB device is reset.) If the
+re-enumeration shows that the device now attached to that port has the
+same descriptors as before, including the Vendor and Product IDs, then
+the kernel continues to use the same device structure. In effect, the
+kernel treats the device as though it had merely been reset instead of
+unplugged.
+
+If no device is now attached to the port, or if the descriptors are
+different from what the kernel remembers, then the treatment is what
+you would expect. The kernel destroys the old device structure and
+behaves as though the old device had been unplugged and a new device
+plugged in, just as it would without the CONFIG_USB_PERSIST option.
+
+The end result is that the USB device remains available and usable.
+Filesystem mounts and memory mappings are unaffected, and the world is
+now a good and happy place.
+
+Note that even when CONFIG_USB_PERSIST is set, the "persist" feature
+will be applied only to those devices for which it is enabled. You
+can enable the feature by doing (as root):
+
+ echo 1 >/sys/bus/usb/devices/.../power/persist
+
+where the "..." should be filled in the with the device's ID. Disable
+the feature by writing 0 instead of 1. For hubs the feature is
+automatically and permanently enabled, so you only have to worry about
+setting it for devices where it really matters.
+
+
+ Is this the best solution?
+
+Perhaps not. Arguably, keeping track of mounted filesystems and
+memory mappings across device disconnects should be handled by a
+centralized Logical Volume Manager. Such a solution would allow you
+to plug in a USB flash device, create a persistent volume associated
+with it, unplug the flash device, plug it back in later, and still
+have the same persistent volume associated with the device. As such
+it would be more far-reaching than CONFIG_USB_PERSIST.
+
+On the other hand, writing a persistent volume manager would be a big
+job and using it would require significant input from the user. This
+solution is much quicker and easier -- and it exists now, a giant
+point in its favor!
+
+Furthermore, the USB_PERSIST option applies to _all_ USB devices, not
+just mass-storage devices. It might turn out to be equally useful for
+other device types, such as network interfaces.
+
+
+ WARNING: Using CONFIG_USB_PERSIST can be dangerous!!
+
+When recovering an interrupted power session the kernel does its best
+to make sure the USB device hasn't been changed; that is, the same
+device is still plugged into the port as before. But the checks
+aren't guaranteed to be 100% accurate.
+
+If you replace one USB device with another of the same type (same
+manufacturer, same IDs, and so on) there's an excellent chance the
+kernel won't detect the change. Serial numbers and other strings are
+not compared. In many cases it wouldn't help if they were, because
+manufacturers frequently omit serial numbers entirely in their
+devices.
+
+Furthermore it's quite possible to leave a USB device exactly the same
+while changing its media. If you replace the flash memory card in a
+USB card reader while the system is asleep, the kernel will have no
+way to know you did it. The kernel will assume that nothing has
+happened and will continue to use the partition tables, inodes, and
+memory mappings for the old card.
+
+If the kernel gets fooled in this way, it's almost certain to cause
+data corruption and to crash your system. You'll have no one to blame
+but yourself.
+
+YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK!
+
+That having been said, most of the time there shouldn't be any trouble
+at all. The "persist" feature can be extremely useful. Make the most
+of it.
diff --git a/Documentation/vm/slub.txt b/Documentation/vm/slub.txt
index 727c8d81aea..1523320abd8 100644
--- a/Documentation/vm/slub.txt
+++ b/Documentation/vm/slub.txt
@@ -1,13 +1,9 @@
Short users guide for SLUB
--------------------------
-First of all slub should transparently replace SLAB. If you enable
-SLUB then everything should work the same (Note the word "should".
-There is likely not much value in that word at this point).
-
The basic philosophy of SLUB is very different from SLAB. SLAB
requires rebuilding the kernel to activate debug options for all
-SLABS. SLUB always includes full debugging but its off by default.
+slab caches. SLUB always includes full debugging but it is off by default.
SLUB can enable debugging only for selected slabs in order to avoid
an impact on overall system performance which may make a bug more
difficult to find.
@@ -76,13 +72,28 @@ of objects.
Careful with tracing: It may spew out lots of information and never stop if
used on the wrong slab.
-SLAB Merging
+Slab merging
------------
-If no debugging is specified then SLUB may merge similar slabs together
+If no debug options are specified then SLUB may merge similar slabs together
in order to reduce overhead and increase cache hotness of objects.
slabinfo -a displays which slabs were merged together.
+Slab validation
+---------------
+
+SLUB can validate all object if the kernel was booted with slub_debug. In
+order to do so you must have the slabinfo tool. Then you can do
+
+slabinfo -v
+
+which will test all objects. Output will be generated to the syslog.
+
+This also works in a more limited way if boot was without slab debug.
+In that case slabinfo -v simply tests all reachable objects. Usually
+these are in the cpu slabs and the partial slabs. Full slabs are not
+tracked by SLUB in a non debug situation.
+
Getting more performance
------------------------
@@ -91,9 +102,9 @@ list_lock once in a while to deal with partial slabs. That overhead is
governed by the order of the allocation for each slab. The allocations
can be influenced by kernel parameters:
-slub_min_objects=x (default 8)
+slub_min_objects=x (default 4)
slub_min_order=x (default 0)
-slub_max_order=x (default 4)
+slub_max_order=x (default 1)
slub_min_objects allows to specify how many objects must at least fit
into one slab in order for the allocation order to be acceptable.
@@ -109,5 +120,107 @@ longer be checked. This is useful to avoid SLUB trying to generate
super large order pages to fit slub_min_objects of a slab cache with
large object sizes into one high order page.
-
-Christoph Lameter, <clameter@sgi.com>, April 10, 2007
+SLUB Debug output
+-----------------
+
+Here is a sample of slub debug output:
+
+*** SLUB kmalloc-8: Redzone Active@0xc90f6d20 slab 0xc528c530 offset=3360 flags=0x400000c3 inuse=61 freelist=0xc90f6d58
+ Bytes b4 0xc90f6d10: 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ
+ Object 0xc90f6d20: 31 30 31 39 2e 30 30 35 1019.005
+ Redzone 0xc90f6d28: 00 cc cc cc .
+FreePointer 0xc90f6d2c -> 0xc90f6d58
+Last alloc: get_modalias+0x61/0xf5 jiffies_ago=53 cpu=1 pid=554
+Filler 0xc90f6d50: 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZ
+ [<c010523d>] dump_trace+0x63/0x1eb
+ [<c01053df>] show_trace_log_lvl+0x1a/0x2f
+ [<c010601d>] show_trace+0x12/0x14
+ [<c0106035>] dump_stack+0x16/0x18
+ [<c017e0fa>] object_err+0x143/0x14b
+ [<c017e2cc>] check_object+0x66/0x234
+ [<c017eb43>] __slab_free+0x239/0x384
+ [<c017f446>] kfree+0xa6/0xc6
+ [<c02e2335>] get_modalias+0xb9/0xf5
+ [<c02e23b7>] dmi_dev_uevent+0x27/0x3c
+ [<c027866a>] dev_uevent+0x1ad/0x1da
+ [<c0205024>] kobject_uevent_env+0x20a/0x45b
+ [<c020527f>] kobject_uevent+0xa/0xf
+ [<c02779f1>] store_uevent+0x4f/0x58
+ [<c027758e>] dev_attr_store+0x29/0x2f
+ [<c01bec4f>] sysfs_write_file+0x16e/0x19c
+ [<c0183ba7>] vfs_write+0xd1/0x15a
+ [<c01841d7>] sys_write+0x3d/0x72
+ [<c0104112>] sysenter_past_esp+0x5f/0x99
+ [<b7f7b410>] 0xb7f7b410
+ =======================
+@@@ SLUB kmalloc-8: Restoring redzone (0xcc) from 0xc90f6d28-0xc90f6d2b
+
+
+
+If SLUB encounters a corrupted object then it will perform the following
+actions:
+
+1. Isolation and report of the issue
+
+This will be a message in the system log starting with
+
+*** SLUB <slab cache affected>: <What went wrong>@<object address>
+offset=<offset of object into slab> flags=<slabflags>
+inuse=<objects in use in this slab> freelist=<first free object in slab>
+
+2. Report on how the problem was dealt with in order to ensure the continued
+operation of the system.
+
+These are messages in the system log beginning with
+
+@@@ SLUB <slab cache affected>: <corrective action taken>
+
+
+In the above sample SLUB found that the Redzone of an active object has
+been overwritten. Here a string of 8 characters was written into a slab that
+has the length of 8 characters. However, a 8 character string needs a
+terminating 0. That zero has overwritten the first byte of the Redzone field.
+After reporting the details of the issue encountered the @@@ SLUB message
+tell us that SLUB has restored the redzone to its proper value and then
+system operations continue.
+
+Various types of lines can follow the @@@ SLUB line:
+
+Bytes b4 <address> : <bytes>
+ Show a few bytes before the object where the problem was detected.
+ Can be useful if the corruption does not stop with the start of the
+ object.
+
+Object <address> : <bytes>
+ The bytes of the object. If the object is inactive then the bytes
+ typically contain poisoning values. Any non-poison value shows a
+ corruption by a write after free.
+
+Redzone <address> : <bytes>
+ The redzone following the object. The redzone is used to detect
+ writes after the object. All bytes should always have the same
+ value. If there is any deviation then it is due to a write after
+ the object boundary.
+
+Freepointer
+ The pointer to the next free object in the slab. May become
+ corrupted if overwriting continues after the red zone.
+
+Last alloc:
+Last free:
+ Shows the address from which the object was allocated/freed last.
+ We note the pid, the time and the CPU that did so. This is usually
+ the most useful information to figure out where things went wrong.
+ Here get_modalias() did an kmalloc(8) instead of a kmalloc(9).
+
+Filler <address> : <bytes>
+ Unused data to fill up the space in order to get the next object
+ properly aligned. In the debug case we make sure that there are
+ at least 4 bytes of filler. This allow for the detection of writes
+ before the object.
+
+Following the filler will be a stackdump. That stackdump describes the
+location where the error was detected. The cause of the corruption is more
+likely to be found by looking at the information about the last alloc / free.
+
+Christoph Lameter, <clameter@sgi.com>, May 23, 2007
diff --git a/Documentation/volatile-considered-harmful.txt b/Documentation/volatile-considered-harmful.txt
new file mode 100644
index 00000000000..10c2e411cca
--- /dev/null
+++ b/Documentation/volatile-considered-harmful.txt
@@ -0,0 +1,119 @@
+Why the "volatile" type class should not be used
+------------------------------------------------
+
+C programmers have often taken volatile to mean that the variable could be
+changed outside of the current thread of execution; as a result, they are
+sometimes tempted to use it in kernel code when shared data structures are
+being used. In other words, they have been known to treat volatile types
+as a sort of easy atomic variable, which they are not. The use of volatile in
+kernel code is almost never correct; this document describes why.
+
+The key point to understand with regard to volatile is that its purpose is
+to suppress optimization, which is almost never what one really wants to
+do. In the kernel, one must protect shared data structures against
+unwanted concurrent access, which is very much a different task. The
+process of protecting against unwanted concurrency will also avoid almost
+all optimization-related problems in a more efficient way.
+
+Like volatile, the kernel primitives which make concurrent access to data
+safe (spinlocks, mutexes, memory barriers, etc.) are designed to prevent
+unwanted optimization. If they are being used properly, there will be no
+need to use volatile as well. If volatile is still necessary, there is
+almost certainly a bug in the code somewhere. In properly-written kernel
+code, volatile can only serve to slow things down.
+
+Consider a typical block of kernel code:
+
+ spin_lock(&the_lock);
+ do_something_on(&shared_data);
+ do_something_else_with(&shared_data);
+ spin_unlock(&the_lock);
+
+If all the code follows the locking rules, the value of shared_data cannot
+change unexpectedly while the_lock is held. Any other code which might
+want to play with that data will be waiting on the lock. The spinlock
+primitives act as memory barriers - they are explicitly written to do so -
+meaning that data accesses will not be optimized across them. So the
+compiler might think it knows what will be in shared_data, but the
+spin_lock() call, since it acts as a memory barrier, will force it to
+forget anything it knows. There will be no optimization problems with
+accesses to that data.
+
+If shared_data were declared volatile, the locking would still be
+necessary. But the compiler would also be prevented from optimizing access
+to shared_data _within_ the critical section, when we know that nobody else
+can be working with it. While the lock is held, shared_data is not
+volatile. When dealing with shared data, proper locking makes volatile
+unnecessary - and potentially harmful.
+
+The volatile storage class was originally meant for memory-mapped I/O
+registers. Within the kernel, register accesses, too, should be protected
+by locks, but one also does not want the compiler "optimizing" register
+accesses within a critical section. But, within the kernel, I/O memory
+accesses are always done through accessor functions; accessing I/O memory
+directly through pointers is frowned upon and does not work on all
+architectures. Those accessors are written to prevent unwanted
+optimization, so, once again, volatile is unnecessary.
+
+Another situation where one might be tempted to use volatile is
+when the processor is busy-waiting on the value of a variable. The right
+way to perform a busy wait is:
+
+ while (my_variable != what_i_want)
+ cpu_relax();
+
+The cpu_relax() call can lower CPU power consumption or yield to a
+hyperthreaded twin processor; it also happens to serve as a memory barrier,
+so, once again, volatile is unnecessary. Of course, busy-waiting is
+generally an anti-social act to begin with.
+
+There are still a few rare situations where volatile makes sense in the
+kernel:
+
+ - The above-mentioned accessor functions might use volatile on
+ architectures where direct I/O memory access does work. Essentially,
+ each accessor call becomes a little critical section on its own and
+ ensures that the access happens as expected by the programmer.
+
+ - Inline assembly code which changes memory, but which has no other
+ visible side effects, risks being deleted by GCC. Adding the volatile
+ keyword to asm statements will prevent this removal.
+
+ - The jiffies variable is special in that it can have a different value
+ every time it is referenced, but it can be read without any special
+ locking. So jiffies can be volatile, but the addition of other
+ variables of this type is strongly frowned upon. Jiffies is considered
+ to be a "stupid legacy" issue (Linus's words) in this regard; fixing it
+ would be more trouble than it is worth.
+
+ - Pointers to data structures in coherent memory which might be modified
+ by I/O devices can, sometimes, legitimately be volatile. A ring buffer
+ used by a network adapter, where that adapter changes pointers to
+ indicate which descriptors have been processed, is an example of this
+ type of situation.
+
+For most code, none of the above justifications for volatile apply. As a
+result, the use of volatile is likely to be seen as a bug and will bring
+additional scrutiny to the code. Developers who are tempted to use
+volatile should take a step back and think about what they are truly trying
+to accomplish.
+
+Patches to remove volatile variables are generally welcome - as long as
+they come with a justification which shows that the concurrency issues have
+been properly thought through.
+
+
+NOTES
+-----
+
+[1] http://lwn.net/Articles/233481/
+[2] http://lwn.net/Articles/233482/
+
+CREDITS
+-------
+
+Original impetus and research by Randy Dunlap
+Written by Jonathan Corbet
+Improvements via coments from Satyam Sharma, Johannes Stezenbach, Jesper
+ Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, and Stefan
+ Richter.
diff --git a/Documentation/watchdog/pcwd-watchdog.txt b/Documentation/watchdog/pcwd-watchdog.txt
index d9ee6336c1d..4f68052395c 100644
--- a/Documentation/watchdog/pcwd-watchdog.txt
+++ b/Documentation/watchdog/pcwd-watchdog.txt
@@ -1,3 +1,5 @@
+Last reviewed: 10/05/2007
+
Berkshire Products PC Watchdog Card
Support for ISA Cards Revision A and C
Documentation and Driver by Ken Hollis <kenji@bitgate.com>
@@ -14,8 +16,8 @@
The Watchdog Driver will automatically find your watchdog card, and will
attach a running driver for use with that card. After the watchdog
- drivers have initialized, you can then talk to the card using the PC
- Watchdog program, available from http://ftp.bitgate.com/pcwd/.
+ drivers have initialized, you can then talk to the card using a PC
+ Watchdog program.
I suggest putting a "watchdog -d" before the beginning of an fsck, and
a "watchdog -e -t 1" immediately after the end of an fsck. (Remember
@@ -62,5 +64,3 @@
-- Ken Hollis
(kenji@bitgate.com)
-(This documentation may be out of date. Check
- http://ftp.bitgate.com/pcwd/ for the absolute latest additions.)
diff --git a/Documentation/watchdog/watchdog-api.txt b/Documentation/watchdog/watchdog-api.txt
index 8d16f6f3c4e..bb7cb1d31ec 100644
--- a/Documentation/watchdog/watchdog-api.txt
+++ b/Documentation/watchdog/watchdog-api.txt
@@ -1,3 +1,6 @@
+Last reviewed: 10/05/2007
+
+
The Linux Watchdog driver API.
Copyright 2002 Christer Weingel <wingel@nano-system.com>
@@ -22,7 +25,7 @@ the system. If userspace fails (RAM error, kernel bug, whatever), the
notifications cease to occur, and the hardware watchdog will reset the
system (causing a reboot) after the timeout occurs.
-The Linux watchdog API is a rather AD hoc construction and different
+The Linux watchdog API is a rather ad-hoc construction and different
drivers implement different, and sometimes incompatible, parts of it.
This file is an attempt to document the existing usage and allow
future driver writers to use it as a reference.
@@ -46,14 +49,16 @@ some of the drivers support the configuration option "Disable watchdog
shutdown on close", CONFIG_WATCHDOG_NOWAYOUT. If it is set to Y when
compiling the kernel, there is no way of disabling the watchdog once
it has been started. So, if the watchdog daemon crashes, the system
-will reboot after the timeout has passed.
+will reboot after the timeout has passed. Watchdog devices also usually
+support the nowayout module parameter so that this option can be controlled
+at runtime.
-Some other drivers will not disable the watchdog, unless a specific
-magic character 'V' has been sent /dev/watchdog just before closing
-the file. If the userspace daemon closes the file without sending
-this special character, the driver will assume that the daemon (and
-userspace in general) died, and will stop pinging the watchdog without
-disabling it first. This will then cause a reboot.
+Drivers will not disable the watchdog, unless a specific magic character 'V'
+has been sent /dev/watchdog just before closing the file. If the userspace
+daemon closes the file without sending this special character, the driver
+will assume that the daemon (and userspace in general) died, and will stop
+pinging the watchdog without disabling it first. This will then cause a
+reboot if the watchdog is not re-opened in sufficient time.
The ioctl API:
@@ -227,218 +232,3 @@ The following options are available:
[FIXME -- better explanations]
-Implementations in the current drivers in the kernel tree:
-
-Here I have tried to summarize what the different drivers support and
-where they do strange things compared to the other drivers.
-
-acquirewdt.c -- Acquire Single Board Computer
-
- This driver has a hardcoded timeout of 1 minute
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns KEEPALIVEPING. GETSTATUS will return 1 if
- the device is open, 0 if not. [FIXME -- isn't this rather
- silly? To be able to use the ioctl, the device must be open
- and so GETSTATUS will always return 1].
-
-advantechwdt.c -- Advantech Single Board Computer
-
- Timeout that defaults to 60 seconds, supports SETTIMEOUT.
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT.
- The GETSTATUS call returns if the device is open or not.
- [FIXME -- silliness again?]
-
-booke_wdt.c -- PowerPC BookE Watchdog Timer
-
- Timeout default varies according to frequency, supports
- SETTIMEOUT
-
- Watchdog cannot be turned off, CONFIG_WATCHDOG_NOWAYOUT
- does not make sense
-
- GETSUPPORT returns the watchdog_info struct, and
- GETSTATUS returns the supported options. GETBOOTSTATUS
- returns a 1 if the last reset was caused by the
- watchdog and a 0 otherwise. This watchdog cannot be
- disabled once it has been started. The wdt_period kernel
- parameter selects which bit of the time base changing
- from 0->1 will trigger the watchdog exception. Changing
- the timeout from the ioctl calls will change the
- wdt_period as defined above. Finally if you would like to
- replace the default Watchdog Handler you can implement the
- WatchdogHandler() function in your own code.
-
-eurotechwdt.c -- Eurotech CPU-1220/1410
-
- The timeout can be set using the SETTIMEOUT ioctl and defaults
- to 60 seconds.
-
- Also has a module parameter "ev", event type which controls
- what should happen on a timeout, the string "int" or anything
- else that causes a reboot. [FIXME -- better description]
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns CARDRESET and WDIOF_SETTIMEOUT but
- GETSTATUS is not supported and GETBOOTSTATUS just returns 0.
-
-i810-tco.c -- Intel 810 chipset
-
- Also has support for a lot of other i8x0 stuff, but the
- watchdog is one of the things.
-
- The timeout is set using the module parameter "i810_margin",
- which is in steps of 0.6 seconds where 2<i810_margin<64. The
- driver supports the SETTIMEOUT ioctl.
-
- Supports CONFIG_WATCHDOG_NOWAYOUT.
-
- GETSUPPORT returns WDIOF_SETTIMEOUT. The GETSTATUS call
- returns some kind of timer value which ist not compatible with
- the other drivers. GETBOOT status returns some kind of
- hardware specific boot status. [FIXME -- describe this]
-
-ib700wdt.c -- IB700 Single Board Computer
-
- Default timeout of 30 seconds and the timeout is settable
- using the SETTIMEOUT ioctl. Note that only a few timeout
- values are supported.
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT.
- The GETSTATUS call returns if the device is open or not.
- [FIXME -- silliness again?]
-
-machzwd.c -- MachZ ZF-Logic
-
- Hardcoded timeout of 10 seconds
-
- Has a module parameter "action" that controls what happens
- when the timeout runs out which can be 0 = RESET (default),
- 1 = SMI, 2 = NMI, 3 = SCI.
-
- Supports CONFIG_WATCHDOG_NOWAYOUT and the magic character
- 'V' close handling.
-
- GETSUPPORT returns WDIOF_KEEPALIVEPING, and the GETSTATUS call
- returns if the device is open or not. [FIXME -- silliness
- again?]
-
-mixcomwd.c -- MixCom Watchdog
-
- [FIXME -- I'm unable to tell what the timeout is]
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns WDIOF_KEEPALIVEPING, GETSTATUS returns if
- the device is opened or not [FIXME -- I'm not really sure how
- this works, there seems to be some magic connected to
- CONFIG_WATCHDOG_NOWAYOUT]
-
-pcwd.c -- Berkshire PC Watchdog
-
- Hardcoded timeout of 1.5 seconds
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns WDIOF_OVERHEAT|WDIOF_CARDRESET and both
- GETSTATUS and GETBOOTSTATUS return something useful.
-
- The SETOPTIONS call can be used to enable and disable the card
- and to ask the driver to call panic if the system overheats.
-
-sbc60xxwdt.c -- 60xx Single Board Computer
-
- Hardcoded timeout of 10 seconds
-
- Does not support CONFIG_WATCHDOG_NOWAYOUT, but has the magic
- character 'V' close handling.
-
- No bits set in GETSUPPORT
-
-scx200.c -- National SCx200 CPUs
-
- Not in the kernel yet.
-
- The timeout is set using a module parameter "margin" which
- defaults to 60 seconds. The timeout can also be set using
- SETTIMEOUT and read using GETTIMEOUT.
-
- Supports a module parameter "nowayout" that is initialized
- with the value of CONFIG_WATCHDOG_NOWAYOUT. Also supports the
- magic character 'V' handling.
-
-shwdt.c -- SuperH 3/4 processors
-
- [FIXME -- I'm unable to tell what the timeout is]
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns WDIOF_KEEPALIVEPING, and the GETSTATUS call
- returns if the device is open or not. [FIXME -- silliness
- again?]
-
-softdog.c -- Software watchdog
-
- The timeout is set with the module parameter "soft_margin"
- which defaults to 60 seconds, the timeout is also settable
- using the SETTIMEOUT ioctl.
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- WDIOF_SETTIMEOUT bit set in GETSUPPORT
-
-w83877f_wdt.c -- W83877F Computer
-
- Hardcoded timeout of 30 seconds
-
- Does not support CONFIG_WATCHDOG_NOWAYOUT, but has the magic
- character 'V' close handling.
-
- No bits set in GETSUPPORT
-
-w83627hf_wdt.c -- w83627hf watchdog
-
- Timeout that defaults to 60 seconds, supports SETTIMEOUT.
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns WDIOF_KEEPALIVEPING and WDIOF_SETTIMEOUT.
- The GETSTATUS call returns if the device is open or not.
-
-wdt.c -- ICS WDT500/501 ISA and
-wdt_pci.c -- ICS WDT500/501 PCI
-
- Default timeout of 60 seconds. The timeout is also settable
- using the SETTIMEOUT ioctl.
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- GETSUPPORT returns with bits set depending on the actual
- card. The WDT501 supports a lot of external monitoring, the
- WDT500 much less.
-
-wdt285.c -- Footbridge watchdog
-
- The timeout is set with the module parameter "soft_margin"
- which defaults to 60 seconds. The timeout is also settable
- using the SETTIMEOUT ioctl.
-
- Does not support CONFIG_WATCHDOG_NOWAYOUT
-
- WDIOF_SETTIMEOUT bit set in GETSUPPORT
-
-wdt977.c -- Netwinder W83977AF chip
-
- Hardcoded timeout of 3 minutes
-
- Supports CONFIG_WATCHDOG_NOWAYOUT
-
- Does not support any ioctls at all.
-
diff --git a/Documentation/watchdog/watchdog.txt b/Documentation/watchdog/watchdog.txt
deleted file mode 100644
index 4b1ff69cc19..00000000000
--- a/Documentation/watchdog/watchdog.txt
+++ /dev/null
@@ -1,94 +0,0 @@
- Watchdog Timer Interfaces For The Linux Operating System
-
- Alan Cox <alan@lxorguk.ukuu.org.uk>
-
- Custom Linux Driver And Program Development
-
-
-The following watchdog drivers are currently implemented:
-
- ICS WDT501-P
- ICS WDT501-P (no fan tachometer)
- ICS WDT500-P
- Software Only
- SA1100 Internal Watchdog
- Berkshire Products PC Watchdog Revision A & C (by Ken Hollis)
-
-
-All six interfaces provide /dev/watchdog, which when open must be written
-to within a timeout or the machine will reboot. Each write delays the reboot
-time another timeout. In the case of the software watchdog the ability to
-reboot will depend on the state of the machines and interrupts. The hardware
-boards physically pull the machine down off their own onboard timers and
-will reboot from almost anything.
-
-A second temperature monitoring interface is available on the WDT501P cards
-and some Berkshire cards. This provides /dev/temperature. This is the machine
-internal temperature in degrees Fahrenheit. Each read returns a single byte
-giving the temperature.
-
-The third interface logs kernel messages on additional alert events.
-
-Both software and hardware watchdog drivers are available in the standard
-kernel. If you are using the software watchdog, you probably also want
-to use "panic=60" as a boot argument as well.
-
-The wdt card cannot be safely probed for. Instead you need to pass
-wdt=ioaddr,irq as a boot parameter - eg "wdt=0x240,11".
-
-The SA1100 watchdog module can be configured with the "sa1100_margin"
-commandline argument which specifies timeout value in seconds.
-
-The i810 TCO watchdog modules can be configured with the "i810_margin"
-commandline argument which specifies the counter initial value. The counter
-is decremented every 0.6 seconds and default to 50 (30 seconds). Values can
-range between 3 and 63.
-
-The i810 TCO watchdog driver also implements the WDIOC_GETSTATUS and
-WDIOC_GETBOOTSTATUS ioctl()s. WDIOC_GETSTATUS returns the actual counter value
-and WDIOC_GETBOOTSTATUS returns the value of TCO2 Status Register (see Intel's
-documentation for the 82801AA and 82801AB datasheet).
-
-Features
---------
- WDT501P WDT500P Software Berkshire i810 TCO SA1100WD
-Reboot Timer X X X X X X
-External Reboot X X o o o X
-I/O Port Monitor o o o X o o
-Temperature X o o X o o
-Fan Speed X o o o o o
-Power Under X o o o o o
-Power Over X o o o o o
-Overheat X o o o o o
-
-The external event interfaces on the WDT boards are not currently supported.
-Minor numbers are however allocated for it.
-
-
-Example Watchdog Driver: see Documentation/watchdog/src/watchdog-simple.c
-
-
-Contact Information
-
-People keep asking about the WDT watchdog timer hardware: The phone contacts
-for Industrial Computer Source are:
-
-Industrial Computer Source
-http://www.indcompsrc.com
-ICS Advent, San Diego
-6260 Sequence Dr.
-San Diego, CA 92121-4371
-Phone (858) 677-0877
-FAX: (858) 677-0895
->
-ICS Advent Europe, UK
-Oving Road
-Chichester,
-West Sussex,
-PO19 4ET, UK
-Phone: 00.44.1243.533900
-
-
-and please mention Linux when enquiring.
-
-For full information about the PCWD cards see the pcwd-watchdog.txt document.
diff --git a/Documentation/watchdog/wdt.txt b/Documentation/watchdog/wdt.txt
new file mode 100644
index 00000000000..03fd756d976
--- /dev/null
+++ b/Documentation/watchdog/wdt.txt
@@ -0,0 +1,43 @@
+Last Reviewed: 10/05/2007
+
+ WDT Watchdog Timer Interfaces For The Linux Operating System
+ Alan Cox <alan@lxorguk.ukuu.org.uk>
+
+ ICS WDT501-P
+ ICS WDT501-P (no fan tachometer)
+ ICS WDT500-P
+
+All the interfaces provide /dev/watchdog, which when open must be written
+to within a timeout or the machine will reboot. Each write delays the reboot
+time another timeout. In the case of the software watchdog the ability to
+reboot will depend on the state of the machines and interrupts. The hardware
+boards physically pull the machine down off their own onboard timers and
+will reboot from almost anything.
+
+A second temperature monitoring interface is available on the WDT501P cards
+This provides /dev/temperature. This is the machine internal temperature in
+degrees Fahrenheit. Each read returns a single byte giving the temperature.
+
+The third interface logs kernel messages on additional alert events.
+
+The wdt card cannot be safely probed for. Instead you need to pass
+wdt=ioaddr,irq as a boot parameter - eg "wdt=0x240,11".
+
+Features
+--------
+ WDT501P WDT500P
+Reboot Timer X X
+External Reboot X X
+I/O Port Monitor o o
+Temperature X o
+Fan Speed X o
+Power Under X o
+Power Over X o
+Overheat X o
+
+The external event interfaces on the WDT boards are not currently supported.
+Minor numbers are however allocated for it.
+
+
+Example Watchdog Driver: see Documentation/watchdog/src/watchdog-simple.c
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 4cc17b993b6..360eb581953 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -30,8 +30,11 @@ trivial patch so apply some common sense.
job the maintainers (and especially Linus) do is to keep things
looking the same. Sometimes this means that the clever hack in
your driver to get around a problem actually needs to become a
- generalized kernel feature ready for next time. See
- Documentation/CodingStyle for guidance here.
+ generalized kernel feature ready for next time.
+
+ PLEASE check your patch with the automated style checker
+ (scripts/checkpatch.pl) to catch trival style violations.
+ See Documentation/CodingStyle for guidance here.
PLEASE try to include any credit lines you want added with the
patch. It avoids people being missed off by mistake and makes
@@ -312,10 +315,9 @@ M: zippel@linux-m68k.org
S: Maintained
AGPGART DRIVER
-P: Dave Jones
-M: davej@codemonkey.org.uk
-W: http://www.codemonkey.org.uk/projects/agp/
-T: git kernel.org:/pub/scm/linux/kernel/git/davej/agpgart.git
+P: David Airlie
+M: airlied@linux.ie
+T: git kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
S: Maintained
AHA152X SCSI DRIVER
@@ -368,7 +370,7 @@ P: Tom Tucker
M: tom@opengridcomputing.com
P: Steve Wise
M: swise@opengridcomputing.com
-L: openib-general@openib.org
+L: general@lists.openfabrics.org
S: Maintained
AOA (Apple Onboard Audio) ALSA DRIVER
@@ -720,42 +722,52 @@ M: rpurdie@rpsys.net
S: Maintained
BLACKFIN ARCHITECTURE
-P: Aubrey Li
-M: aubrey.li@analog.com
-P: Bernd Schmidt
-M: bernd.schmidt@analog.com
-P: Bryan Wu
-M: bryan.wu@analog.com
-P: Grace Pan
-M: grace.pan@analog.com
-P: Michael Hennerich
-M: michael.hennerich@analog.com
-P: Mike Frysinger
-M: michael.frysinger@analog.com
-P: Jane Lv
-M: jane.lv@analog.com
-P: Jerry Zeng
-M: jerry.zeng@analog.com
-P: Jie Zhang
-M: jie.zhang@analog.com
-P: Robin Getz
-M: robin.getz@analog.com
-P: Roy Huang
-M: roy.huang@analog.com
-P: Sonic Zhang
-M: sonic.zhang@analog.com
-P: Yi Li
-M: yi.li@analog.com
-L: uclinux-dist-devel@blackfin.uclinux.org
-W: http://blackfin.uclinux.org
-S: Supported
+P: Aubrey Li
+M: aubrey.li@analog.com
+P: Bernd Schmidt
+M: bernd.schmidt@analog.com
+P: Bryan Wu
+M: bryan.wu@analog.com
+P: Grace Pan
+M: grace.pan@analog.com
+P: Marc Hoffman
+M: marc.hoffman@analog.com
+P: Michael Hennerich
+M: michael.hennerich@analog.com
+P: Mike Frysinger
+M: michael.frysinger@analog.com
+P: Jerry Zeng
+M: jerry.zeng@analog.com
+P: Jie Zhang
+M: jie.zhang@analog.com
+P: Robin Getz
+M: robin.getz@analog.com
+P: Roy Huang
+M: roy.huang@analog.com
+P: Sonic Zhang
+M: sonic.zhang@analog.com
+P: Vivi Li
+M: vivi.li@analog.com
+P: Yi Li
+M: yi.li@analog.com
+L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W: http://blackfin.uclinux.org
+S: Supported
+
+BLACKFIN RTC DRIVER
+P: Mike Frysinger
+M: michael.frysinger@analog.com
+M: vapier.adi@gmail.com
+L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W: http://blackfin.uclinux.org
+S: Supported
BLACKFIN SERIAL DRIVER
-P: Aubrey Li
-M: aubrey.li@analog.com
-L: uclinux-dist-devel@blackfin.uclinux.org
-W: http://blackfin.uclinux.org
-S: Supported
+P: Aubrey Li
+M: aubrey.li@analog.com
+L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
+W: http://blackfin.uclinux.org
+S: Supported
BAYCOM/HDLCDRV DRIVERS FOR AX.25
P: Thomas Sailer
@@ -779,11 +791,6 @@ M: rathamahata@php4.ru
L: linux-kernel@vger.kernel.org
S: Maintained
-BERKSHIRE PRODUCTS PC WATCHDOG DRIVER
-P: Kenji Hollis
-W: http://ftp.bitgate.com/pcwd/
-S: Maintained
-
BFS FILE SYSTEM
P: Tigran A. Aivazian
M: tigran@aivazian.fsnet.co.uk
@@ -972,6 +979,15 @@ M: johannes@sipsolutions.net
L: linux-wireless@vger.kernel.org
S: Maintained
+CHECKPATCH
+P: Andy Whitcroft
+M: apw@shadowen.org
+P: Randy Dunlap
+M: rdunlap@xenotime.net
+P: Joel Schopp
+M: jschopp@austin.ibm.com
+S: Supported
+
COMMON INTERNET FILE SYSTEM (CIFS)
P: Steve French
M: sfrench@samba.org
@@ -1379,7 +1395,7 @@ P: Hoang-Nam Nguyen
M: hnguyen@de.ibm.com
P: Christoph Raisch
M: raisch@de.ibm.com
-L: openib-general@openib.org
+L: general@lists.openfabrics.org
S: Supported
EMU10K1 SOUND DRIVER
@@ -1475,6 +1491,13 @@ L: linux-usb-devel@lists.sourceforge.net
L: linuxppc-embedded@ozlabs.org
S: Maintained
+FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
+P: Li Yang
+M: leoli@freescale.com
+L: netdev@vger.kernel.org
+L: linuxppc-embedded@ozlabs.org
+S: Maintained
+
FILE LOCKING (flock() and fcntl()/lockf())
P: Matthew Wilcox
M: matthew@wil.cx
@@ -1486,6 +1509,14 @@ P: Alexander Viro
M: viro@zeniv.linux.org.uk
S: Maintained
+FIREWIRE SUBSYSTEM
+P: Kristian Hoegsberg, Stefan Richter
+M: krh@redhat.com, stefanr@s5r6.in-berlin.de
+L: linux1394-devel@lists.sourceforge.net
+W: http://www.linux1394.org/
+T: git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
+S: Maintained
+
FIRMWARE LOADER (request_firmware)
L: linux-kernel@vger.kernel.org
S: Orphan
@@ -1718,8 +1749,8 @@ T: http://www.harbaum.org/till/i2c_tiny_usb
S: Maintained
i386 BOOT CODE
-P: Riley H. Williams
-M: Riley@Williams.Name
+P: H. Peter Anvin
+M: hpa@zytor.com
L: Linux-Kernel@vger.kernel.org
S: Maintained
@@ -1818,13 +1849,13 @@ M: rolandd@cisco.com
P: Sean Hefty
M: mshefty@ichips.intel.com
P: Hal Rosenstock
-M: halr@voltaire.com
-L: openib-general@openib.org
+M: hal.rosenstock@gmail.com
+L: general@lists.openfabrics.org
W: http://www.openib.org/
T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
S: Supported
-INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
+INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
P: Dmitry Torokhov
M: dmitry.torokhov@gmail.com
M: dtor@mail.ru
@@ -1957,9 +1988,10 @@ M: jjciarla@raiz.uncu.edu.ar
S: Maintained
IPATH DRIVER:
-P: Bryan O'Sullivan
-M: support@pathscale.com
-L: openib-general@openib.org
+P: Arthur Jones
+M: infinipath@qlogic.com
+L: general@lists.openfabrics.org
+T: git git://git.qlogic.com/ipath-linux-2.6
S: Supported
IPMI SUBSYSTEM
@@ -2069,7 +2101,7 @@ S: Maintained
KERNEL JANITORS
P: Several
-L: kernel-janitors@lists.linux-foundation.org
+L: kernel-janitors@vger.kernel.org
W: http://www.kerneljanitors.org/
S: Maintained
@@ -2298,6 +2330,12 @@ W: http://linuxwireless.org/
T: git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git
S: Maintained
+MACVLAN DRIVER
+P: Patrick McHardy
+M: kaber@trash.net
+L: netdev@vger.kernel.org
+S: Maintained
+
MARVELL YUKON / SYSKONNECT DRIVER
P: Mirko Lindner
M: mlindner@syskonnect.de
@@ -2782,11 +2820,6 @@ P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
S: Supported
-PCI HOTPLUG COMPAQ DRIVER
-P: Greg Kroah-Hartman
-M: greg@kroah.com
-S: Maintained
-
PCIE HOTPLUG DRIVER
P: Kristen Carlson Accardi
M: kristen.c.accardi@intel.com
@@ -2871,6 +2904,11 @@ P: Michal Ostrowski
M: mostrows@speakeasy.net
S: Maintained
+PPP OVER L2TP
+P: James Chapman
+M: jchapman@katalix.com
+S: Maintained
+
PREEMPTIBLE KERNEL
P: Robert Love
M: rml@tech9.net
@@ -2880,8 +2918,8 @@ W: ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel
S: Supported
PRISM54 WIRELESS DRIVER
-P: Prism54 Development Team
-M: developers@islsm.org
+P: Luis R. Rodriguez
+M: mcgrof@gmail.com
L: linux-wireless@vger.kernel.org
W: http://prism54.org
S: Maintained
@@ -2898,6 +2936,13 @@ M: mikpe@it.uu.se
L: linux-ide@vger.kernel.org
S: Maintained
+PS3 NETWORK SUPPORT
+P: Masakazu Mokuno
+M: mokuno@sm.sony.co.jp
+L: netdev@vger.kernel.org
+L: cbe-oss-dev@ozlabs.org
+S: Supported
+
PS3 PLATFORM SUPPORT
P: Geoff Levand
M: geoffrey.levand@am.sony.com
@@ -2998,7 +3043,7 @@ S: Maintained
REISERFS FILE SYSTEM
P: Hans Reiser
M: reiserfs-dev@namesys.com
-L: reiserfs-list@namesys.com
+L: reiserfs-devel@vger.kernel.org
W: http://www.namesys.com
S: Supported
@@ -3017,6 +3062,16 @@ S: Maintained
RISCOM8 DRIVER
S: Orphan
+RTL818X WIRELESS DRIVER
+P: Michael Wu
+M: flamingice@sourmilk.net
+P: Andrea Merello
+M: andreamrl@tiscali.it
+L: linux-wireless@vger.kernel.org
+W: http://linuxwireless.org/
+T: git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
+S: Maintained
+
S3 SAVAGE FRAMEBUFFER DRIVER
P: Antonino Daplas
M: adaplas@gmail.com
@@ -3525,7 +3580,7 @@ S: Maintained
TULIP NETWORK DRIVER
P: Valerie Henson
-M: val_henson@linux.intel.com
+M: val@nmt.edu
L: tulip-users@lists.sourceforge.net
W: http://sourceforge.net/projects/tulip/
S: Maintained
@@ -3586,7 +3641,7 @@ W: http://www.kroah.com/linux-usb/
USB DAVICOM DM9601 DRIVER
P: Peter Korsgaard
M: jacmet@sunsite.dk
-L: linux-usb-devel@lists.sourceforge.net
+L: netdev@vger.kernel.org
W: http://www.linux-usb.org/usbnet
S: Maintained
@@ -3670,23 +3725,23 @@ S: Maintained
USB PEGASUS DRIVER
P: Petko Manolov
M: petkan@users.sourceforge.net
-L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
+L: netdev@vger.kernel.org
W: http://pegasus2.sourceforge.net/
S: Maintained
-USB PRINTER DRIVER
-P: Vojtech Pavlik
-M: vojtech@suse.cz
+USB PRINTER DRIVER (usblp)
+P: Pete Zaitcev
+M: zaitcev@redhat.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
-S: Maintained
+S: Supported
USB RTL8150 DRIVER
P: Petko Manolov
M: petkan@users.sourceforge.net
-L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
+L: netdev@vger.kernel.org
W: http://pegasus2.sourceforge.net/
S: Maintained
@@ -3797,7 +3852,7 @@ S: Maintained
USB "USBNET" DRIVER FRAMEWORK
P: David Brownell
M: dbrownell@users.sourceforge.net
-L: linux-usb-devel@lists.sourceforge.net
+L: netdev@vger.kernel.org
W: http://www.linux-usb.org/usbnet
S: Maintained
@@ -3877,10 +3932,6 @@ S: Maintained
UCLINUX FOR NEC V850
P: Miles Bader
-M: uclinux-v850@lsi.nec.co.jp
-W: http://www.ic.nec.co.jp/micro/uclinux/eng/
-W: http://www.ee.nec.de/uclinux/
-S: Supported
UCLINUX FOR RENESAS H8/300
P: Yoshinori Sato
@@ -3889,10 +3940,10 @@ W: http://uclinux-h8.sourceforge.jp/
S: Supported
UFS FILESYSTEM
-P: Evgeniy Dushistov
-M: dushistov@mail.ru
-L: linux-kernel@vger.kernel.org
-S: Maintained
+P: Evgeniy Dushistov
+M: dushistov@mail.ru
+L: linux-kernel@vger.kernel.org
+S: Maintained
USB DIAMOND RIO500 DRIVER
P: Cesar Miquel
@@ -3994,11 +4045,11 @@ S: Supported
XFS FILESYSTEM
P: Silicon Graphics Inc
-P: Tim Shimmin, David Chatterton
+P: Tim Shimmin
M: xfs-masters@oss.sgi.com
L: xfs@oss.sgi.com
W: http://oss.sgi.com/projects/xfs
-T: git git://oss.sgi.com:8090/xfs/xfs-2.6
+T: git git://oss.sgi.com:8090/xfs/xfs-2.6.git
S: Supported
XILINX UARTLITE SERIAL DRIVER
diff --git a/Makefile b/Makefile
index 562a90902cf..de4f8f7d396 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 22
-EXTRAVERSION = -rc3
-NAME = Jeff Thinks I Should Change This, But To What?
+EXTRAVERSION =
+NAME = Holy Dancing Manatees, Batman!
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 770f717bd25..2a85dc33907 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -83,22 +83,20 @@ choice
check out the Linux/Alpha FAQ, accessible on the WWW from
<http://www.alphalinux.org/>. In summary:
- Alcor/Alpha-XLT AS 600
+ Alcor/Alpha-XLT AS 600, AS 500, XL-300, XL-366
Alpha-XL XL-233, XL-266
AlphaBook1 Alpha laptop
Avanti AS 200, AS 205, AS 250, AS 255, AS 300, AS 400
Cabriolet AlphaPC64, AlphaPCI64
- DP264 DP264
+ DP264 DP264 / DS20 / ES40 / DS10 / DS10L
EB164 EB164 21164 evaluation board
EB64+ EB64+ 21064 evaluation board
EB66 EB66 21066 evaluation board
EB66+ EB66+ 21066 evaluation board
- Jensen DECpc 150, DEC 2000 model 300,
- DEC 2000 model 500
+ Jensen DECpc 150, DEC 2000 models 300, 500
LX164 AlphaPC164-LX
Lynx AS 2100A
- Miata Personal Workstation 433a, 433au, 500a,
- 500au, 600a, or 600au
+ Miata Personal Workstation 433/500/600 a/au
Marvel AlphaServer ES47 / ES80 / GS1280
Mikasa AS 1000
Noname AXPpci33, UDB (Multia)
@@ -108,9 +106,9 @@ choice
Ruffian RPX164-2, AlphaPC164-UX, AlphaPC164-BX
SX164 AlphaPC164-SX
Sable AS 2000, AS 2100
- Shark DS 20L
- Takara Takara
- Titan AlphaServer ES45 / DS25
+ Shark DS 20L
+ Takara Takara (OEM)
+ Titan AlphaServer ES45 / DS25 / DS15
Wildfire AlphaServer GS 40/80/160/320
If you don't know what to do, choose "generic".
@@ -329,6 +327,9 @@ config PCI_DOMAINS
bool
default y
+config PCI_SYSCALL
+ def_bool PCI
+
config ALPHA_CORE_AGP
bool
depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
@@ -481,6 +482,15 @@ config ALPHA_BROKEN_IRQ_MASK
depends on ALPHA_GENERIC || ALPHA_PC164
default y
+config VGA_HOSE
+ bool
+ depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL || ALPHA_TSUNAMI
+ default y
+ help
+ Support VGA on an arbitrary hose; needed for several platforms
+ which always have multiple hoses, and whose consoles support it.
+
+
config ALPHA_SRM
bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME
default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
@@ -537,10 +547,14 @@ config HAVE_DEC_LOCK
default y
config NR_CPUS
- int "Maximum number of CPUs (2-64)"
- range 2 64
+ int "Maximum number of CPUs (2-32)"
+ range 2 32
depends on SMP
- default "64"
+ default "32" if ALPHA_GENERIC || ALPHA_MARVEL
+ default "4" if !ALPHA_GENERIC && !ALPHA_MARVEL
+ help
+ MARVEL support can handle a maximum of 32 CPUs, all the others
+ with working support have a maximum of 4 CPUs.
config ARCH_DISCONTIGMEM_ENABLE
bool "Discontiguous Memory Support (EXPERIMENTAL)"
@@ -644,6 +658,13 @@ source "arch/alpha/oprofile/Kconfig"
source "arch/alpha/Kconfig.debug"
+# DUMMY_CONSOLE may be defined in drivers/video/console/Kconfig
+# but we also need it if VGA_HOSE is set
+config DUMMY_CONSOLE
+ bool
+ depends on VGA_HOSE
+ default y
+
source "security/Kconfig"
source "crypto/Kconfig"
diff --git a/arch/alpha/boot/tools/mkbb.c b/arch/alpha/boot/tools/mkbb.c
index 23c7190b047..632a7fd6d7d 100644
--- a/arch/alpha/boot/tools/mkbb.c
+++ b/arch/alpha/boot/tools/mkbb.c
@@ -81,7 +81,7 @@ typedef union __bootblock {
#define bootblock_label __u1.__label
#define bootblock_checksum __u2.__checksum
-main(int argc, char ** argv)
+int main(int argc, char ** argv)
{
bootblock bootblock_from_disk;
bootblock bootloader_image;
diff --git a/arch/alpha/kernel/console.c b/arch/alpha/kernel/console.c
index f313b34939b..da711e37fc9 100644
--- a/arch/alpha/kernel/console.c
+++ b/arch/alpha/kernel/console.c
@@ -9,16 +9,20 @@
#include <linux/init.h>
#include <linux/tty.h>
#include <linux/console.h>
+#include <linux/vt.h>
#include <asm/vga.h>
#include <asm/machvec.h>
+#include "pci_impl.h"
+
#ifdef CONFIG_VGA_HOSE
-/*
- * Externally-visible vga hose bases
- */
-unsigned long __vga_hose_io_base = 0; /* base for default hose */
-unsigned long __vga_hose_mem_base = 0; /* base for default hose */
+struct pci_controller *pci_vga_hose;
+static struct resource alpha_vga = {
+ .name = "alpha-vga+",
+ .start = 0x3C0,
+ .end = 0x3DF
+};
static struct pci_controller * __init
default_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
@@ -30,36 +34,58 @@ default_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
}
void __init
-set_vga_hose(struct pci_controller *hose)
-{
- if (hose) {
- __vga_hose_io_base = hose->io_space->start;
- __vga_hose_mem_base = hose->mem_space->start;
- }
-}
-
-void __init
locate_and_init_vga(void *(*sel_func)(void *, void *))
{
struct pci_controller *hose = NULL;
struct pci_dev *dev = NULL;
+ /* Default the select function */
if (!sel_func) sel_func = (void *)default_vga_hose_select;
+ /* Find the console VGA device */
for(dev=NULL; (dev=pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, dev));) {
- if (!hose) hose = dev->sysdata;
- else hose = sel_func(hose, dev->sysdata);
+ if (!hose)
+ hose = dev->sysdata;
+ else
+ hose = sel_func(hose, dev->sysdata);
}
- /* Did we already inititialize the correct one? */
- if (conswitchp == &vga_con &&
- __vga_hose_io_base == hose->io_space->start &&
- __vga_hose_mem_base == hose->mem_space->start)
+ /* Did we already initialize the correct one? Is there one? */
+ if (!hose || (conswitchp == &vga_con && pci_vga_hose == hose))
return;
- /* Set the VGA hose and init the new console */
- set_vga_hose(hose);
+ /* Create a new VGA ioport resource WRT the hose it is on. */
+ alpha_vga.start += hose->io_space->start;
+ alpha_vga.end += hose->io_space->start;
+ request_resource(hose->io_space, &alpha_vga);
+
+ /* Set the VGA hose and init the new console. */
+ pci_vga_hose = hose;
take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1);
}
+void __init
+find_console_vga_hose(void)
+{
+ u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
+
+ if (pu64[7] == 3) { /* TERM_TYPE == graphics */
+ struct pci_controller *hose;
+ int h = (pu64[30] >> 24) & 0xff; /* console hose # */
+
+ /*
+ * Our hose numbering DOES match the console's, so find
+ * the right one...
+ */
+ for (hose = hose_head; hose; hose = hose->next) {
+ if (hose->index == h) break;
+ }
+
+ if (hose) {
+ printk("Console graphics on hose %d\n", h);
+ pci_vga_hose = hose;
+ }
+ }
+}
+
#endif
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
index 7f6a98455e7..f10d2eddd2c 100644
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -25,6 +25,7 @@
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/rtc.h>
+#include <asm/vga.h>
#include "proto.h"
#include "pci_impl.h"
@@ -367,9 +368,8 @@ marvel_io7_present(gct6_node *node)
}
static void __init
-marvel_init_vga_hose(void)
+marvel_find_console_vga_hose(void)
{
-#ifdef CONFIG_VGA_HOSE
u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
if (pu64[7] == 3) { /* TERM_TYPE == graphics */
@@ -403,7 +403,6 @@ marvel_init_vga_hose(void)
pci_vga_hose = hose;
}
}
-#endif /* CONFIG_VGA_HOSE */
}
gct6_search_struct gct_wanted_node_list[] = {
@@ -459,7 +458,7 @@ marvel_init_arch(void)
marvel_init_io7(io7);
/* Check for graphic console location (if any). */
- marvel_init_vga_hose();
+ marvel_find_console_vga_hose();
}
void
@@ -684,9 +683,6 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write)
/*
* IO map support.
*/
-
-#define __marvel_is_mem_vga(a) (((a) >= 0xa0000) && ((a) <= 0xc0000))
-
void __iomem *
marvel_ioremap(unsigned long addr, unsigned long size)
{
@@ -698,13 +694,9 @@ marvel_ioremap(unsigned long addr, unsigned long size)
unsigned long pfn;
/*
- * Adjust the addr.
+ * Adjust the address.
*/
-#ifdef CONFIG_VGA_HOSE
- if (pci_vga_hose && __marvel_is_mem_vga(addr)) {
- addr += pci_vga_hose->mem_space->start;
- }
-#endif
+ FIXUP_MEMADDR_VGA(addr);
/*
* Find the hose.
@@ -781,7 +773,9 @@ marvel_ioremap(unsigned long addr, unsigned long size)
return (void __iomem *) vaddr;
}
- return NULL;
+ /* Assume it was already a reasonable address */
+ vaddr = baddr + hose->mem_space->start;
+ return (void __iomem *) vaddr;
}
void
@@ -803,21 +797,12 @@ marvel_is_mmio(const volatile void __iomem *xaddr)
return (addr & 0xFF000000UL) == 0;
}
-#define __marvel_is_port_vga(a) \
- (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
#define __marvel_is_port_kbd(a) (((a) == 0x60) || ((a) == 0x64))
#define __marvel_is_port_rtc(a) (((a) == 0x70) || ((a) == 0x71))
void __iomem *marvel_ioportmap (unsigned long addr)
{
- if (__marvel_is_port_rtc (addr) || __marvel_is_port_kbd(addr))
- ;
-#ifdef CONFIG_VGA_HOSE
- else if (__marvel_is_port_vga (addr) && pci_vga_hose)
- addr += pci_vga_hose->io_space->start;
-#endif
- else
- return NULL;
+ FIXUP_IOADDR_VGA(addr);
return (void __iomem *)addr;
}
@@ -829,8 +814,14 @@ marvel_ioread8(void __iomem *xaddr)
return 0;
else if (__marvel_is_port_rtc(addr))
return __marvel_rtc_io(0, addr, 0);
- else
+ else if (marvel_is_ioaddr(addr))
return __kernel_ldbu(*(vucp)addr);
+ else
+ /* this should catch other legacy addresses
+ that would normally fail on MARVEL,
+ because there really is nothing there...
+ */
+ return ~0;
}
void
@@ -841,7 +832,7 @@ marvel_iowrite8(u8 b, void __iomem *xaddr)
return;
else if (__marvel_is_port_rtc(addr))
__marvel_rtc_io(b, addr, 1);
- else
+ else if (marvel_is_ioaddr(addr))
__kernel_stb(b, *(vucp)addr);
}
diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
index 3662fef7db9..819326627b9 100644
--- a/arch/alpha/kernel/core_titan.c
+++ b/arch/alpha/kernel/core_titan.c
@@ -21,6 +21,7 @@
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
+#include <asm/vga.h>
#include "proto.h"
#include "pci_impl.h"
@@ -35,6 +36,11 @@ struct
} saved_config[4] __attribute__((common));
/*
+ * Is PChip 1 present? No need to query it more than once.
+ */
+static int titan_pchip1_present;
+
+/*
* BIOS32-style PCI interface:
*/
@@ -344,43 +350,17 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
static void __init
titan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
{
- int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
+ titan_pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
/* Init the ports in hose order... */
titan_init_one_pachip_port(&pachip0->g_port, 0); /* hose 0 */
- if (pchip1_present)
+ if (titan_pchip1_present)
titan_init_one_pachip_port(&pachip1->g_port, 1);/* hose 1 */
titan_init_one_pachip_port(&pachip0->a_port, 2); /* hose 2 */
- if (pchip1_present)
+ if (titan_pchip1_present)
titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */
}
-static void __init
-titan_init_vga_hose(void)
-{
-#ifdef CONFIG_VGA_HOSE
- u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
-
- if (pu64[7] == 3) { /* TERM_TYPE == graphics */
- struct pci_controller *hose;
- int h = (pu64[30] >> 24) & 0xff; /* console hose # */
-
- /*
- * Our hose numbering matches the console's, so just find
- * the right one...
- */
- for (hose = hose_head; hose; hose = hose->next) {
- if (hose->index == h) break;
- }
-
- if (hose) {
- printk("Console graphics on hose %d\n", hose->index);
- pci_vga_hose = hose;
- }
- }
-#endif /* CONFIG_VGA_HOSE */
-}
-
void __init
titan_init_arch(void)
{
@@ -406,6 +386,7 @@ titan_init_arch(void)
/* With multiple PCI busses, we play with I/O as physical addrs. */
ioport_resource.end = ~0UL;
+ iomem_resource.end = ~0UL;
/* PCI DMA Direct Mapping is 1GB at 2GB. */
__direct_map_base = 0x80000000;
@@ -415,7 +396,7 @@ titan_init_arch(void)
titan_init_pachips(TITAN_pachip0, TITAN_pachip1);
/* Check for graphic console location (if any). */
- titan_init_vga_hose();
+ find_console_vga_hose();
}
static void
@@ -441,9 +422,7 @@ titan_kill_one_pachip_port(titan_pachip_port *port, int index)
static void
titan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
{
- int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
-
- if (pchip1_present) {
+ if (titan_pchip1_present) {
titan_kill_one_pachip_port(&pachip1->g_port, 1);
titan_kill_one_pachip_port(&pachip1->a_port, 3);
}
@@ -463,6 +442,14 @@ titan_kill_arch(int mode)
*/
void __iomem *
+titan_ioportmap(unsigned long addr)
+{
+ FIXUP_IOADDR_VGA(addr);
+ return (void __iomem *)(addr + TITAN_IO_BIAS);
+}
+
+
+void __iomem *
titan_ioremap(unsigned long addr, unsigned long size)
{
int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT;
@@ -475,14 +462,12 @@ titan_ioremap(unsigned long addr, unsigned long size)
unsigned long pfn;
/*
- * Adjust the addr.
+ * Adjust the address and hose, if necessary.
*/
-#ifdef CONFIG_VGA_HOSE
- if (pci_vga_hose && __titan_is_mem_vga(addr)) {
+ if (pci_vga_hose && __is_mem_vga(addr)) {
h = pci_vga_hose->index;
addr += pci_vga_hose->mem_space->start;
}
-#endif
/*
* Find the hose.
@@ -521,8 +506,10 @@ titan_ioremap(unsigned long addr, unsigned long size)
* Map it
*/
area = get_vm_area(size, VM_IOREMAP);
- if (!area)
+ if (!area) {
+ printk("ioremap failed... no vm_area...\n");
return NULL;
+ }
ptes = hose->sg_pci->ptes;
for (vaddr = (unsigned long)area->addr;
@@ -539,7 +526,7 @@ titan_ioremap(unsigned long addr, unsigned long size)
if (__alpha_remap_area_pages(vaddr,
pfn << PAGE_SHIFT,
PAGE_SIZE, 0)) {
- printk("FAILED to map...\n");
+ printk("FAILED to remap_area_pages...\n");
vfree(area->addr);
return NULL;
}
@@ -551,7 +538,8 @@ titan_ioremap(unsigned long addr, unsigned long size)
return (void __iomem *) vaddr;
}
- return NULL;
+ /* Assume a legacy (read: VGA) address, and return appropriately. */
+ return (void __iomem *)(addr + TITAN_MEM_BIAS);
}
void
@@ -574,6 +562,7 @@ titan_is_mmio(const volatile void __iomem *xaddr)
}
#ifndef CONFIG_ALPHA_GENERIC
+EXPORT_SYMBOL(titan_ioportmap);
EXPORT_SYMBOL(titan_ioremap);
EXPORT_SYMBOL(titan_iounmap);
EXPORT_SYMBOL(titan_is_mmio);
@@ -750,6 +739,7 @@ titan_agp_info(void)
if (titan_query_agp(port))
hosenum = 2;
if (hosenum < 0 &&
+ titan_pchip1_present &&
titan_query_agp(port = &TITAN_pachip1->a_port))
hosenum = 3;
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index ce623c6e55e..ef91e09590d 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -19,6 +19,7 @@
#include <asm/ptrace.h>
#include <asm/smp.h>
+#include <asm/vga.h>
#include "proto.h"
#include "pci_impl.h"
@@ -349,6 +350,26 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
tsunami_pci_tbi(hose, 0, -1);
}
+
+void __iomem *
+tsunami_ioportmap(unsigned long addr)
+{
+ FIXUP_IOADDR_VGA(addr);
+ return (void __iomem *)(addr + TSUNAMI_IO_BIAS);
+}
+
+void __iomem *
+tsunami_ioremap(unsigned long addr, unsigned long size)
+{
+ FIXUP_MEMADDR_VGA(addr);
+ return (void __iomem *)(addr + TSUNAMI_MEM_BIAS);
+}
+
+#ifndef CONFIG_ALPHA_GENERIC
+EXPORT_SYMBOL(tsunami_ioportmap);
+EXPORT_SYMBOL(tsunami_ioremap);
+#endif
+
void __init
tsunami_init_arch(void)
{
@@ -393,6 +414,9 @@ tsunami_init_arch(void)
tsunami_init_one_pchip(TSUNAMI_pchip0, 0);
if (TSUNAMI_cchip->csc.csr & 1L<<14)
tsunami_init_one_pchip(TSUNAMI_pchip1, 1);
+
+ /* Check for graphic console location (if any). */
+ find_console_vga_hose();
}
static void
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 28c84e55feb..6b07f89a72c 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -207,6 +207,10 @@ iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
p[i] = 0;
}
+/* True if the machine supports DAC addressing, and DEV can
+ make use of it given MASK. */
+static int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
+
/* Map a single buffer of the indicated size for PCI DMA in streaming
mode. The 32-bit PCI bus mastering address to use is returned.
Once the device is given the dma address, the device owns this memory
@@ -897,7 +901,7 @@ iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
/* True if the machine supports DAC addressing, and DEV can
make use of it given MASK. */
-int
+static int
pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
{
dma64_addr_t dac_offset = alpha_mv.pci_dac_offset;
@@ -917,32 +921,6 @@ pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
return ok;
}
-EXPORT_SYMBOL(pci_dac_dma_supported);
-
-dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page,
- unsigned long offset, int direction)
-{
- return (alpha_mv.pci_dac_offset
- + __pa(page_address(page))
- + (dma64_addr_t) offset);
-}
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- unsigned long paddr = (dma_addr & PAGE_MASK) - alpha_mv.pci_dac_offset;
- return virt_to_page(__va(paddr));
-}
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- return (dma_addr & ~PAGE_MASK);
-}
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
/* Helper for generic DMA-mapping functions. */
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 95912ecc65e..708d5ca8778 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -108,6 +108,15 @@ extern int wildfire_cpuid_to_nid(int);
extern unsigned long wildfire_node_mem_start(int);
extern unsigned long wildfire_node_mem_size(int);
+/* console.c */
+#ifdef CONFIG_VGA_HOSE
+extern void find_console_vga_hose(void);
+extern void locate_and_init_vga(void *(*)(void *, void *));
+#else
+static inline void find_console_vga_hose(void) { }
+static inline void locate_and_init_vga(void *(*sel_func)(void *, void *)) { }
+#endif
+
/* setup.c */
extern unsigned long srm_hae;
extern int boot_cpuid;
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 85d2f933dd0..c71b0fd7a61 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -543,6 +543,7 @@ dp264_init_pci(void)
{
common_init_pci();
SMC669_Init(0);
+ locate_and_init_vga(NULL);
}
static void __init
@@ -551,6 +552,14 @@ monet_init_pci(void)
common_init_pci();
SMC669_Init(1);
es1888_init();
+ locate_and_init_vga(NULL);
+}
+
+static void __init
+clipper_init_pci(void)
+{
+ common_init_pci();
+ locate_and_init_vga(NULL);
}
static void __init
@@ -655,7 +664,7 @@ struct alpha_machine_vector clipper_mv __initmv = {
.init_arch = tsunami_init_arch,
.init_irq = clipper_init_irq,
.init_rtc = common_init_rtc,
- .init_pci = common_init_pci,
+ .init_pci = clipper_init_pci,
.kill_arch = tsunami_kill_arch,
.pci_map_irq = clipper_map_irq,
.pci_swizzle = common_swizzle,
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index e349f03b830..0bcb968cb60 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -22,6 +22,7 @@
#include <asm/core_marvel.h>
#include <asm/hwrpb.h>
#include <asm/tlbflush.h>
+#include <asm/vga.h>
#include "proto.h"
#include "err_impl.h"
@@ -412,10 +413,7 @@ marvel_init_pci(void)
pci_probe_only = 1;
common_init_pci();
-
-#ifdef CONFIG_VGA_HOSE
locate_and_init_vga(NULL);
-#endif
/* Clear any io7 errors. */
for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; )
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
index f009b7bc094..1d3c1398c42 100644
--- a/arch/alpha/kernel/sys_titan.c
+++ b/arch/alpha/kernel/sys_titan.c
@@ -331,9 +331,7 @@ titan_init_pci(void)
pci_probe_only = 1;
common_init_pci();
SMC669_Init(0);
-#ifdef CONFIG_VGA_HOSE
locate_and_init_vga(NULL);
-#endif
}
diff --git a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S
index e09748dbf2e..2c2acb96deb 100644
--- a/arch/alpha/lib/csum_ipv6_magic.S
+++ b/arch/alpha/lib/csum_ipv6_magic.S
@@ -7,6 +7,9 @@
* __u32 len,
* unsigned short proto,
* unsigned int csum);
+ *
+ * Misalignment handling (which costs 16 instructions / 8 cycles)
+ * added by Ivan Kokshaysky <ink@jurassic.park.msu.ru>
*/
.globl csum_ipv6_magic
@@ -16,37 +19,57 @@
csum_ipv6_magic:
.prologue 0
- ldq $0,0($16) # e0 : load src & dst addr words
+ ldq_u $0,0($16) # e0 : load src & dst addr words
zapnot $20,15,$20 # .. e1 : zero extend incoming csum
extqh $18,1,$4 # e0 : byte swap len & proto while we wait
- ldq $1,8($16) # .. e1 :
+ ldq_u $21,7($16) # .. e1 : handle misalignment
extbl $18,1,$5 # e0 :
- ldq $2,0($17) # .. e1 :
+ ldq_u $1,8($16) # .. e1 :
extbl $18,2,$6 # e0 :
- ldq $3,8($17) # .. e1 :
+ ldq_u $22,15($16) # .. e1 :
extbl $18,3,$18 # e0 :
+ ldq_u $2,0($17) # .. e1 :
sra $4,32,$4 # e0 :
+ ldq_u $23,7($17) # .. e1 :
+
+ extql $0,$16,$0 # e0 :
+ ldq_u $3,8($17) # .. e1 :
+ extqh $21,$16,$21 # e0 :
+ ldq_u $24,15($17) # .. e1 :
+
sll $5,16,$5 # e0 :
+ or $0,$21,$0 # .. e1 : 1st src word complete
+ extql $1,$16,$1 # e0 :
addq $20,$0,$20 # .. e1 : begin summing the words
- sll $6,8,$6 # e0 :
+ extqh $22,$16,$22 # e0 :
cmpult $20,$0,$0 # .. e1 :
- extwh $19,7,$7 # e0 :
- or $4,$18,$18 # .. e1 :
+ sll $6,8,$6 # e0 :
+ or $1,$22,$1 # .. e1 : 2nd src word complete
- extbl $19,1,$19 # e0 :
+ extql $2,$17,$2 # e0 :
+ or $4,$18,$18 # .. e1 :
+ extqh $23,$17,$23 # e0 :
or $5,$6,$5 # .. e1 :
- or $18,$5,$18 # e0 : len complete
- or $19,$7,$19 # .. e1 :
- sll $19,48,$19 # e0 :
+ extql $3,$17,$3 # e0 :
+ or $2,$23,$2 # .. e1 : 1st dst word complete
+ extqh $24,$17,$24 # e0 :
+ or $18,$5,$18 # .. e1 : len complete
+
+ extwh $19,7,$7 # e0 :
+ or $3,$24,$3 # .. e1 : 2nd dst word complete
+ extbl $19,1,$19 # e0 :
addq $20,$1,$20 # .. e1 :
- sra $19,32,$19 # e0 : proto complete
+
+ or $19,$7,$19 # e0 :
cmpult $20,$1,$1 # .. e1 :
+ sll $19,48,$19 # e0 :
+ nop # .. e0 :
- nop # e0 :
+ sra $19,32,$19 # e0 : proto complete
addq $20,$2,$20 # .. e1 :
cmpult $20,$2,$2 # e0 :
addq $20,$3,$20 # .. e1 :
@@ -84,7 +107,7 @@ csum_ipv6_magic:
extwl $0,2,$1 # e0 : fold 17-bit value
zapnot $0,3,$0 # .. e1 :
addq $0,$1,$0 # e0 :
- not $0,$0 # e1 : and complement.
+ not $0,$0 # .. e1 : and complement.
zapnot $0,3,$0 # e0 :
ret # .. e1 :
diff --git a/arch/alpha/lib/ev6-csum_ipv6_magic.S b/arch/alpha/lib/ev6-csum_ipv6_magic.S
index de1948a6911..fc0bc399f87 100644
--- a/arch/alpha/lib/ev6-csum_ipv6_magic.S
+++ b/arch/alpha/lib/ev6-csum_ipv6_magic.S
@@ -46,6 +46,10 @@
* add the 3 low ushorts together, generating a uint
* a final add of the 2 lower ushorts
* truncating the result.
+ *
+ * Misalignment handling added by Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+ * The cost is 16 instructions (~8 cycles), including two extra loads which
+ * may cause additional delay in rare cases (load-load replay traps).
*/
.globl csum_ipv6_magic
@@ -55,25 +59,45 @@
csum_ipv6_magic:
.prologue 0
- ldq $0,0($16) # L : Latency: 3
+ ldq_u $0,0($16) # L : Latency: 3
inslh $18,7,$4 # U : 0000000000AABBCC
- ldq $1,8($16) # L : Latency: 3
+ ldq_u $1,8($16) # L : Latency: 3
sll $19,8,$7 # U : U L U L : 0x00000000 00aabb00
+ and $16,7,$6 # E : src misalignment
+ ldq_u $5,15($16) # L : Latency: 3
zapnot $20,15,$20 # U : zero extend incoming csum
- ldq $2,0($17) # L : Latency: 3
- sll $19,24,$19 # U : U L L U : 0x000000aa bb000000
+ ldq_u $2,0($17) # L : U L U L : Latency: 3
+
+ extql $0,$6,$0 # U :
+ extqh $1,$6,$22 # U :
+ ldq_u $3,8($17) # L : Latency: 3
+ sll $19,24,$19 # U : U U L U : 0x000000aa bb000000
+
+ cmoveq $6,$31,$22 # E : src aligned?
+ ldq_u $23,15($17) # L : Latency: 3
inswl $18,3,$18 # U : 000000CCDD000000
+ addl $19,$7,$19 # E : U L U L : <sign bits>bbaabb00
- ldq $3,8($17) # L : Latency: 3
- bis $18,$4,$18 # E : 000000CCDDAABBCC
- addl $19,$7,$19 # E : <sign bits>bbaabb00
- nop # E : U L U L
+ or $0,$22,$0 # E : 1st src word complete
+ extql $1,$6,$1 # U :
+ or $18,$4,$18 # E : 000000CCDDAABBCC
+ extqh $5,$6,$5 # U : L U L U
+ and $17,7,$6 # E : dst misalignment
+ extql $2,$6,$2 # U :
+ or $1,$5,$1 # E : 2nd src word complete
+ extqh $3,$6,$22 # U : L U L U :
+
+ cmoveq $6,$31,$22 # E : dst aligned?
+ extql $3,$6,$3 # U :
addq $20,$0,$20 # E : begin summing the words
+ extqh $23,$6,$23 # U : L U L U :
+
srl $18,16,$4 # U : 0000000000CCDDAA
+ or $2,$22,$2 # E : 1st dst word complete
zap $19,0x3,$19 # U : <sign bits>bbaa0000
- nop # E : L U U L
+ or $3,$23,$3 # E : U L U L : 2nd dst word complete
cmpult $20,$0,$0 # E :
addq $20,$1,$20 # E :
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 50d9f3e4e0f..a44c6da9bf8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -241,6 +241,9 @@ config ARCH_H720X
config ARCH_IMX
bool "IMX"
+ select GENERIC_GPIO
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
help
Support for Motorola's i.MX family of processors (MX1, MXL).
@@ -308,6 +311,7 @@ config ARCH_L7200
config ARCH_KS8695
bool "Micrel/Kendin KS8695"
+ select GENERIC_GPIO
help
Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
System-on-Chip devices.
@@ -384,6 +388,7 @@ config ARCH_DAVINCI
bool "TI DaVinci"
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
+ select GENERIC_GPIO
help
Support for TI's DaVinci platform.
@@ -531,6 +536,9 @@ config PCI
information about which PCI hardware does work under Linux and which
doesn't.
+config PCI_SYSCALL
+ def_bool PCI
+
# Select the host bridge type
config PCI_HOST_VIA82C505
bool
@@ -1034,6 +1042,8 @@ source "drivers/mmc/Kconfig"
source "drivers/rtc/Kconfig"
+source "drivers/dma/Kconfig"
+
endmenu
source "fs/Kconfig"
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
index 171a0853caf..ce1c5ff746e 100644
--- a/arch/arm/boot/.gitignore
+++ b/arch/arm/boot/.gitignore
@@ -1,2 +1,5 @@
Image
zImage
+xipImage
+bootpImage
+uImage
diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore
index aefee20cbf9..b15f927a592 100644
--- a/arch/arm/boot/compressed/.gitignore
+++ b/arch/arm/boot/compressed/.gitignore
@@ -1 +1,2 @@
piggy.gz
+font.c
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index adddc713168..a1f1691b67f 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -6,15 +6,13 @@
HEAD = head.o
OBJS = misc.o
-FONTC = drivers/video/console/font_acorn_8x8.c
-
-FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o)
+FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
#
# Architecture dependencies
#
ifeq ($(CONFIG_ARCH_ACORN),y)
-OBJS += ll_char_wr.o $(FONT)
+OBJS += ll_char_wr.o font.o
endif
ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -73,7 +71,7 @@ endif
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
-targets := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \
+targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \
head.o misc.o $(OBJS)
EXTRA_CFLAGS := -fpic
EXTRA_AFLAGS :=
@@ -105,7 +103,10 @@ $(obj)/piggy.gz: $(obj)/../Image FORCE
$(obj)/piggy.o: $(obj)/piggy.gz FORCE
-CFLAGS_font_acorn_8x8.o := -Dstatic=
+CFLAGS_font.o := -Dstatic=
+
+$(obj)/font.c: $(FONTC)
+ $(call cmd,shipped)
$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
@sed "$(SEDFLAGS)" < $< > $@
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
index 73c5d9e0201..236bbe57831 100644
--- a/arch/arm/boot/compressed/head-xscale.S
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -41,11 +41,6 @@ __XScale_start:
mov r7, #MACH_TYPE_COTULLA_IDP
#endif
-#ifdef CONFIG_MACH_GTWX5715
- mov r7, #(MACH_TYPE_GTWX5715 & 0xff)
- orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
-#endif
-
#ifdef CONFIG_ARCH_IXP2000
mov r1, #-1
mov r0, #0xd6000000
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 2568d311be2..d7fb5ee1637 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -247,7 +247,7 @@ not_relocated: mov r0, #0
mov r3, r7
bl decompress_kernel
- add r0, r0, #127
+ add r0, r0, #127 + 128 @ alignment + stack
bic r0, r0, #127 @ align the kernel length
/*
* r0 = decompressed kernel length
@@ -269,6 +269,7 @@ not_relocated: mov r0, #0
stmia r1!, {r9 - r14}
cmp r2, r3
blo 1b
+ add sp, r1, #128 @ relocate the stack
bl cache_clean_flush
add pc, r5, r0 @ call relocation code
@@ -435,6 +436,28 @@ __armv4_mmu_cache_on:
mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
mov pc, r12
+__armv7_mmu_cache_on:
+ mov r12, lr
+ mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0
+ tst r11, #0xf @ VMSA
+ blne __setup_mmu
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
+ tst r11, #0xf @ VMSA
+ mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
+ mrc p15, 0, r0, c1, c0, 0 @ read control reg
+ orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement
+ orr r0, r0, #0x003c @ write buffer
+ orrne r0, r0, #1 @ MMU enabled
+ movne r1, #-1
+ mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
+ mcrne p15, 0, r1, c3, c0, 0 @ load domain access control
+ mcr p15, 0, r0, c1, c0, 0 @ load control register
+ mrc p15, 0, r0, c1, c0, 0 @ and read it back
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 4 @ ISB
+ mov pc, r12
+
__arm6_mmu_cache_on:
mov r12, lr
bl __setup_mmu
@@ -476,6 +499,7 @@ __common_mmu_cache_on:
*/
.align 5
reloc_start: add r9, r5, r0
+ sub r9, r9, #128 @ do not copy the stack
debug_reloc_start
mov r1, r4
1:
@@ -486,6 +510,7 @@ reloc_start: add r9, r5, r0
cmp r5, r9
blo 1b
+ add sp, r1, #128 @ relocate the stack
debug_reloc_end
call_kernel: bl cache_clean_flush
@@ -619,11 +644,17 @@ proc_types:
b __armv4_mmu_cache_flush
.word 0x0007b000 @ ARMv6
- .word 0x0007f000
+ .word 0x000ff000
b __armv4_mmu_cache_on
b __armv4_mmu_cache_off
b __armv6_mmu_cache_flush
+ .word 0x000f0000 @ new CPU Id
+ .word 0x000f0000
+ b __armv7_mmu_cache_on
+ b __armv7_mmu_cache_off
+ b __armv7_mmu_cache_flush
+
.word 0 @ unrecognised type
.word 0
mov pc, lr
@@ -671,6 +702,16 @@ __armv4_mmu_cache_off:
mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4
mov pc, lr
+__armv7_mmu_cache_off:
+ mrc p15, 0, r0, c1, c0
+ bic r0, r0, #0x000d
+ mcr p15, 0, r0, c1, c0 @ turn MMU and cache off
+ mov r12, lr
+ bl __armv7_mmu_cache_flush
+ mov r0, #0
+ mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB
+ mov pc, r12
+
__arm6_mmu_cache_off:
mov r0, #0x00000030 @ ARM6 control reg.
b __armv3_mmu_cache_off
@@ -727,6 +768,59 @@ __armv6_mmu_cache_flush:
mcr p15, 0, r1, c7, c10, 4 @ drain WB
mov pc, lr
+__armv7_mmu_cache_flush:
+ mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1
+ tst r10, #0xf << 16 @ hierarchical cache (ARMv7)
+ beq hierarchical
+ mov r10, #0
+ mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D
+ b iflush
+hierarchical:
+ stmfd sp!, {r0-r5, r7, r9-r11}
+ mrc p15, 1, r0, c0, c0, 1 @ read clidr
+ ands r3, r0, #0x7000000 @ extract loc from clidr
+ mov r3, r3, lsr #23 @ left align loc bit field
+ beq finished @ if loc is 0, then no need to clean
+ mov r10, #0 @ start clean at cache level 0
+loop1:
+ add r2, r10, r10, lsr #1 @ work out 3x current cache level
+ mov r1, r0, lsr r2 @ extract cache type bits from clidr
+ and r1, r1, #7 @ mask of the bits for current cache only
+ cmp r1, #2 @ see what cache we have at this level
+ blt skip @ skip if no cache, or just i-cache
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ mcr p15, 0, r10, c7, c5, 4 @ isb to sych the new cssr&csidr
+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
+ and r2, r1, #7 @ extract the length of the cache lines
+ add r2, r2, #4 @ add 4 (line length offset)
+ ldr r4, =0x3ff
+ ands r4, r4, r1, lsr #3 @ find maximum number on the way size
+ .word 0xe16f5f14 @ clz r5, r4 - find bit position of way size increment
+ ldr r7, =0x7fff
+ ands r7, r7, r1, lsr #13 @ extract max number of the index size
+loop2:
+ mov r9, r4 @ create working copy of max way size
+loop3:
+ orr r11, r10, r9, lsl r5 @ factor way and cache number into r11
+ orr r11, r11, r7, lsl r2 @ factor index number into r11
+ mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
+ subs r9, r9, #1 @ decrement the way
+ bge loop3
+ subs r7, r7, #1 @ decrement the index
+ bge loop2
+skip:
+ add r10, r10, #2 @ increment cache number
+ cmp r3, r10
+ bgt loop1
+finished:
+ mov r10, #0 @ swith back to cache level 0
+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
+ ldmfd sp!, {r0-r5, r7, r9-r11}
+iflush:
+ mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB
+ mcr p15, 0, r10, c7, c10, 4 @ drain WB
+ mov pc, lr
+
__armv4_mmu_cache_flush:
mov r2, #64*1024 @ default: 32K dcache size (*2)
mov r11, #32 @ default: 32 byte line size
@@ -833,6 +927,7 @@ memdump: mov r12, r0
mov pc, r10
#endif
+ .ltorg
reloc_end:
.align
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index cfe6f4650bc..ae21755872e 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -60,6 +60,9 @@ struct locomo {
unsigned int irq;
spinlock_t lock;
void __iomem *base;
+#ifdef CONFIG_PM
+ void *saved_state;
+#endif
};
struct locomo_dev_info {
@@ -565,7 +568,7 @@ static int locomo_suspend(struct platform_device *dev, pm_message_t state)
if (!save)
return -ENOMEM;
- dev->dev.power.saved_state = (void *) save;
+ lchip->saved_state = save;
spin_lock_irqsave(&lchip->lock, flags);
@@ -605,8 +608,8 @@ static int locomo_resume(struct platform_device *dev)
struct locomo_save_data *save;
unsigned long r;
unsigned long flags;
-
- save = (struct locomo_save_data *) dev->dev.power.saved_state;
+
+ save = lchip->saved_state;
if (!save)
return 0;
@@ -628,6 +631,8 @@ static int locomo_resume(struct platform_device *dev)
locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD);
spin_unlock_irqrestore(&lchip->lock, flags);
+
+ lchip->saved_state = NULL;
kfree(save);
return 0;
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 798bbfccafb..eb06d0b2cb7 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -51,6 +51,9 @@ struct sa1111 {
int irq;
spinlock_t lock;
void __iomem *base;
+#ifdef CONFIG_PM
+ void *saved_state;
+#endif
};
/*
@@ -822,7 +825,7 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (!save)
return -ENOMEM;
- dev->dev.power.saved_state = save;
+ sachip->saved_state = save;
spin_lock_irqsave(&sachip->lock, flags);
@@ -878,7 +881,7 @@ static int sa1111_resume(struct platform_device *dev)
unsigned long flags, id;
void __iomem *base;
- save = (struct sa1111_save_data *)dev->dev.power.saved_state;
+ save = sachip->saved_state;
if (!save)
return 0;
@@ -923,7 +926,7 @@ static int sa1111_resume(struct platform_device *dev)
spin_unlock_irqrestore(&sachip->lock, flags);
- dev->dev.power.saved_state = NULL;
+ sachip->saved_state = NULL;
kfree(save);
return 0;
@@ -958,8 +961,8 @@ static int sa1111_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
#ifdef CONFIG_PM
- kfree(pdev->dev.power.saved_state);
- pdev->dev.power.saved_state = NULL;
+ kfree(sachip->saved_state);
+ sachip->saved_state = NULL;
#endif
}
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 3bf3a927ae2..111a7fa5deb 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -766,9 +766,7 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info)
}
static struct pm_ops sharpsl_pm_ops = {
- .prepare = pxa_pm_prepare,
.enter = corgi_pxa_pm_enter,
- .finish = pxa_pm_finish,
.valid = pm_valid_only_mem,
};
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 19326d7cdeb..a98d0c933db 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -350,7 +350,7 @@
CALL(sys_set_robust_list)
CALL(sys_get_robust_list)
/* 340 */ CALL(sys_splice)
- CALL(sys_arm_sync_file_range)
+ CALL(sys_sync_file_range2)
CALL(sys_tee)
CALL(sys_vmsplice)
CALL(sys_move_pages)
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index a52da0ddb43..024a9cf469b 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -20,7 +20,8 @@ __switch_data:
.long _end @ r7
.long processor_id @ r4
.long __machine_arch_type @ r5
- .long cr_alignment @ r6
+ .long __atags_pointer @ r6
+ .long cr_alignment @ r7
.long init_thread_union + THREAD_START_SP @ sp
/*
@@ -29,6 +30,7 @@ __switch_data:
*
* r0 = cp#15 control register
* r1 = machine ID
+ * r2 = atags pointer
* r9 = processor ID
*/
.type __mmap_switched, %function
@@ -47,11 +49,12 @@ __mmap_switched:
strcc fp, [r6],#4
bcc 1b
- ldmia r3, {r4, r5, r6, sp}
+ ldmia r3, {r4, r5, r6, r7, sp}
str r9, [r4] @ Save processor ID
str r1, [r5] @ Save machine type
+ str r2, [r6] @ Save atags pointer
bic r4, r0, #CR_A @ Clear 'A' bit
- stmia r6, {r0, r4} @ Save control register values
+ stmia r7, {r0, r4} @ Save control register values
b start_kernel
/*
@@ -215,3 +218,34 @@ ENTRY(lookup_machine_type)
bl __lookup_machine_type
mov r0, r5
ldmfd sp!, {r4 - r6, pc}
+
+/* Determine validity of the r2 atags pointer. The heuristic requires
+ * that the pointer be aligned, in the first 16k of physical RAM and
+ * that the ATAG_CORE marker is first and present. Future revisions
+ * of this function may be more lenient with the physical address and
+ * may also be able to move the ATAGS block if necessary.
+ *
+ * r8 = machinfo
+ *
+ * Returns:
+ * r2 either valid atags pointer, or zero
+ * r5, r6 corrupted
+ */
+
+ .type __vet_atags, %function
+__vet_atags:
+ tst r2, #0x3 @ aligned?
+ bne 1f
+
+ ldr r5, [r2, #0] @ is first tag ATAG_CORE?
+ subs r5, r5, #ATAG_CORE_SIZE
+ bne 1f
+ ldr r5, [r2, #4]
+ ldr r6, =ATAG_CORE
+ cmp r5, r6
+ bne 1f
+
+ mov pc, lr @ atag pointer is ok
+
+1: mov r2, #0
+ mov pc, lr
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 41f98b4ba2e..7898cbc9861 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -29,6 +29,10 @@
#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)
#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET)
+#define ATAG_CORE 0x54410001
+#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
+
+
/*
* swapper_pg_dir is the virtual address of the initial page table.
* We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must
@@ -61,7 +65,7 @@
*
* This is normally called from the decompressor code. The requirements
* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
- * r1 = machine nr.
+ * r1 = machine nr, r2 = atags pointer.
*
* This code is mostly position independent, so if you link the kernel at
* 0xc0008000, you call this at __pa(0xc0008000).
@@ -85,6 +89,7 @@ ENTRY(stext)
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
+ bl __vet_atags
bl __create_page_tables
/*
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 5d6e6523598..93b7f8e22dc 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -28,6 +28,7 @@
#include <linux/elfcore.h>
#include <linux/pm.h>
#include <linux/tick.h>
+#include <linux/utsname.h>
#include <asm/leds.h>
#include <asm/processor.h>
@@ -43,6 +44,10 @@ static const char *processor_modes[] = {
"UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
};
+static const char *isa_modes[] = {
+ "ARM" , "Thumb" , "Jazelle", "ThumbEE"
+};
+
extern void setup_mm_for_reboot(char mode);
static volatile int hlt_counter;
@@ -199,16 +204,19 @@ void machine_restart(char * __unused)
void __show_regs(struct pt_regs *regs)
{
- unsigned long flags = condition_codes(regs);
+ unsigned long flags;
+ char buf[64];
- printk("CPU: %d\n", smp_processor_id());
+ printk("CPU: %d %s (%s %.*s)\n",
+ smp_processor_id(), print_tainted(), init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
print_symbol("PC is at %s\n", instruction_pointer(regs));
print_symbol("LR is at %s\n", regs->ARM_lr);
- printk("pc : [<%08lx>] lr : [<%08lx>] %s\n"
+ printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n"
"sp : %08lx ip : %08lx fp : %08lx\n",
- instruction_pointer(regs),
- regs->ARM_lr, print_tainted(), regs->ARM_sp,
- regs->ARM_ip, regs->ARM_fp);
+ regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr,
+ regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
printk("r10: %08lx r9 : %08lx r8 : %08lx\n",
regs->ARM_r10, regs->ARM_r9,
regs->ARM_r8);
@@ -218,36 +226,39 @@ void __show_regs(struct pt_regs *regs)
printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
regs->ARM_r3, regs->ARM_r2,
regs->ARM_r1, regs->ARM_r0);
- printk("Flags: %c%c%c%c",
- flags & PSR_N_BIT ? 'N' : 'n',
- flags & PSR_Z_BIT ? 'Z' : 'z',
- flags & PSR_C_BIT ? 'C' : 'c',
- flags & PSR_V_BIT ? 'V' : 'v');
- printk(" IRQs o%s FIQs o%s Mode %s%s Segment %s\n",
- interrupts_enabled(regs) ? "n" : "ff",
+
+ flags = regs->ARM_cpsr;
+ buf[0] = flags & PSR_N_BIT ? 'N' : 'n';
+ buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
+ buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
+ buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
+ buf[4] = '\0';
+
+ printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n",
+ buf, interrupts_enabled(regs) ? "n" : "ff",
fast_interrupts_enabled(regs) ? "n" : "ff",
processor_modes[processor_mode(regs)],
- thumb_mode(regs) ? " (T)" : "",
+ isa_modes[isa_mode(regs)],
get_fs() == get_ds() ? "kernel" : "user");
-#if CONFIG_CPU_CP15
+#ifdef CONFIG_CPU_CP15
{
unsigned int ctrl;
- __asm__ (
- " mrc p15, 0, %0, c1, c0\n"
- : "=r" (ctrl));
- printk("Control: %04X\n", ctrl);
- }
+
+ buf[0] = '\0';
#ifdef CONFIG_CPU_CP15_MMU
- {
- unsigned int transbase, dac;
- __asm__ (
- " mrc p15, 0, %0, c2, c0\n"
- " mrc p15, 0, %1, c3, c0\n"
- : "=r" (transbase), "=r" (dac));
- printk("Table: %08X DAC: %08X\n",
- transbase, dac);
- }
+ {
+ unsigned int transbase, dac;
+ asm("mrc p15, 0, %0, c2, c0\n\t"
+ "mrc p15, 0, %1, c3, c0\n"
+ : "=r" (transbase), "=r" (dac));
+ snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x",
+ transbase, dac);
+ }
#endif
+ asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl));
+
+ printk("Control: %08x%s\n", ctrl, buf);
+ }
#endif
}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 650eac1bc0a..5be2e987b84 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -63,6 +63,8 @@ unsigned int processor_id;
unsigned int __machine_arch_type;
EXPORT_SYMBOL(__machine_arch_type);
+unsigned int __atags_pointer __initdata;
+
unsigned int system_rev;
EXPORT_SYMBOL(system_rev);
@@ -780,7 +782,9 @@ void __init setup_arch(char **cmdline_p)
if (mdesc->soft_reboot)
reboot_setup("s");
- if (mdesc->boot_params)
+ if (__atags_pointer)
+ tags = phys_to_virt(__atags_pointer);
+ else if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
/*
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 1ca2d5174fc..4d25e49a14f 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -328,16 +328,3 @@ asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
{
return sys_fadvise64_64(fd, offset, len, advice);
}
-
-/*
- * Yet more syscall fsckage - we can't fit sys_sync_file_range's
- * arguments into the available registers with EABI. So, let's
- * create an ARM specific syscall for this which has _sane_
- * arguments. (This incidentally also has an ABI-independent
- * argument layout.)
- */
-asmlinkage long sys_arm_sync_file_range(int fd, unsigned int flags,
- loff_t offset, loff_t nbytes)
-{
- return sys_sync_file_range(fd, offset, nbytes, flags);
-}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 10ff36e4e41..237f4999b9a 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -181,9 +181,7 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
void dump_stack(void)
{
-#ifdef CONFIG_DEBUG_ERRORS
__backtrace();
-#endif
}
EXPORT_SYMBOL(dump_stack);
@@ -204,12 +202,24 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
barrier();
}
+#ifdef CONFIG_PREEMPT
+#define S_PREEMPT " PREEMPT"
+#else
+#define S_PREEMPT ""
+#endif
+#ifdef CONFIG_SMP
+#define S_SMP " SMP"
+#else
+#define S_SMP ""
+#endif
+
static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
{
struct task_struct *tsk = thread->task;
static int die_counter;
- printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter);
+ printk("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
+ str, err, ++die_counter);
print_modules();
__show_regs(regs);
printk("Process %s (pid: %d, stack limit = 0x%p)\n",
@@ -232,6 +242,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
{
struct thread_info *thread = current_thread_info();
+ oops_enter();
+
console_verbose();
spin_lock_irq(&die_lock);
bust_spinlocks(1);
@@ -239,9 +251,13 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
bust_spinlocks(0);
spin_unlock_irq(&die_lock);
+ if (in_interrupt())
+ panic("Fatal exception in interrupt");
+
if (panic_on_oops)
panic("Fatal exception");
+ oops_exit();
do_exit(SIGSEGV);
}
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 26ca8ab3f62..42e172cb0f4 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -27,6 +27,11 @@
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/dm9000.h>
+#include <linux/fb.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <video/atmel_lcdc.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@@ -271,6 +276,127 @@ static struct spi_board_info ek_spi_devices[] = {
};
+/*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+ {
+ .name = "TX09D50VM1CCA @ 60",
+ .refresh = 60,
+ .xres = 240, .yres = 320,
+ .pixclock = KHZ2PICOS(4965),
+
+ .left_margin = 1, .right_margin = 33,
+ .upper_margin = 1, .lower_margin = 0,
+ .hsync_len = 5, .vsync_len = 1,
+
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+ .manufacturer = "HIT",
+ .monitor = "TX09D50VM1CCA",
+
+ .modedb = at91_tft_vga_modes,
+ .modedb_len = ARRAY_SIZE(at91_tft_vga_modes),
+ .hfmin = 15000,
+ .hfmax = 64000,
+ .vfmin = 50,
+ .vfmax = 150,
+};
+
+#define AT91SAM9261_DEFAULT_LCDCON2 (ATMEL_LCDC_MEMOR_LITTLE \
+ | ATMEL_LCDC_DISTYPE_TFT \
+ | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+ if (on)
+ at91_set_gpio_value(AT91_PIN_PA12, 0); /* power up */
+ else
+ at91_set_gpio_value(AT91_PIN_PA12, 1); /* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+ .default_bpp = 16,
+ .default_dmacon = ATMEL_LCDC_DMAEN,
+ .default_lcdcon2 = AT91SAM9261_DEFAULT_LCDCON2,
+ .default_monspecs = &at91fb_default_monspecs,
+ .atmel_lcdfb_power_control = at91_lcdc_power_control,
+ .guard_time = 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+ {
+ .gpio = AT91_PIN_PA27,
+ .keycode = BTN_0,
+ .desc = "Button 0",
+ .active_low = 1,
+ },
+ {
+ .gpio = AT91_PIN_PA26,
+ .keycode = BTN_1,
+ .desc = "Button 1",
+ .active_low = 1,
+ },
+ {
+ .gpio = AT91_PIN_PA25,
+ .keycode = BTN_2,
+ .desc = "Button 2",
+ .active_low = 1,
+ },
+ {
+ .gpio = AT91_PIN_PA24,
+ .keycode = BTN_3,
+ .desc = "Button 3",
+ .active_low = 1,
+ }
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+ .buttons = ek_buttons,
+ .nbuttons = ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .num_resources = 0,
+ .dev = {
+ .platform_data = &ek_button_data,
+ }
+};
+
+static void __init ek_add_device_buttons(void)
+{
+ at91_set_gpio_input(AT91_PIN_PB27, 0); /* btn0 */
+ at91_set_deglitch(AT91_PIN_PB27, 1);
+ at91_set_gpio_input(AT91_PIN_PB26, 0); /* btn1 */
+ at91_set_deglitch(AT91_PIN_PB26, 1);
+ at91_set_gpio_input(AT91_PIN_PB25, 0); /* btn2 */
+ at91_set_deglitch(AT91_PIN_PB25, 1);
+ at91_set_gpio_input(AT91_PIN_PB24, 0); /* btn3 */
+ at91_set_deglitch(AT91_PIN_PB24, 1);
+
+ platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
static void __init ek_board_init(void)
{
/* Serial */
@@ -296,6 +422,10 @@ static void __init ek_board_init(void)
/* MMC */
at91_add_device_mmc(0, &ek_mmc_data);
#endif
+ /* LCD Controller */
+ at91_add_device_lcdc(&ek_lcdc_data);
+ /* Push Buttons */
+ ek_add_device_buttons();
}
MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index c164c8e58ae..2a1cc73390b 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -26,6 +26,9 @@
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
+#include <linux/fb.h>
+
+#include <video/atmel_lcdc.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@@ -202,6 +205,65 @@ static struct at91_nand_data __initdata ek_nand_data = {
/*
+ * LCD Controller
+ */
+#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
+static struct fb_videomode at91_tft_vga_modes[] = {
+ {
+ .name = "TX09D50VM1CCA @ 60",
+ .refresh = 60,
+ .xres = 240, .yres = 320,
+ .pixclock = KHZ2PICOS(4965),
+
+ .left_margin = 1, .right_margin = 33,
+ .upper_margin = 1, .lower_margin = 0,
+ .hsync_len = 5, .vsync_len = 1,
+
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED,
+ },
+};
+
+static struct fb_monspecs at91fb_default_monspecs = {
+ .manufacturer = "HIT",
+ .monitor = "TX09D70VM1CCA",
+
+ .modedb = at91_tft_vga_modes,
+ .modedb_len = ARRAY_SIZE(at91_tft_vga_modes),
+ .hfmin = 15000,
+ .hfmax = 64000,
+ .vfmin = 50,
+ .vfmax = 150,
+};
+
+#define AT91SAM9263_DEFAULT_LCDCON2 (ATMEL_LCDC_MEMOR_LITTLE \
+ | ATMEL_LCDC_DISTYPE_TFT \
+ | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE)
+
+static void at91_lcdc_power_control(int on)
+{
+ if (on)
+ at91_set_gpio_value(AT91_PIN_PD12, 0); /* power up */
+ else
+ at91_set_gpio_value(AT91_PIN_PD12, 1); /* power down */
+}
+
+/* Driver datas */
+static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+ .default_bpp = 16,
+ .default_dmacon = ATMEL_LCDC_DMAEN,
+ .default_lcdcon2 = AT91SAM9263_DEFAULT_LCDCON2,
+ .default_monspecs = &at91fb_default_monspecs,
+ .atmel_lcdfb_power_control = at91_lcdc_power_control,
+ .guard_time = 1,
+};
+
+#else
+static struct atmel_lcdfb_info __initdata ek_lcdc_data;
+#endif
+
+
+/*
* AC97
*/
static struct atmel_ac97_data ek_ac97_data = {
@@ -230,6 +292,8 @@ static void __init ek_board_init(void)
at91_add_device_nand(&ek_nand_data);
/* I2C */
at91_add_device_i2c();
+ /* LCD Controller */
+ at91_add_device_lcdc(&ek_lcdc_data);
/* AC97 */
at91_add_device_ac97(&ek_ac97_data);
}
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 06c9a0507d0..848efb2a4eb 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -364,19 +364,14 @@ static int at91_clk_show(struct seq_file *s, void *unused)
{
u32 scsr, pcsr, sr;
struct clk *clk;
- unsigned i;
seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR));
-
seq_printf(s, "MOR = %8x\n", at91_sys_read(AT91_CKGR_MOR));
seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
-
seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
- for (i = 0; i < 4; i++)
- seq_printf(s, "PCK%d = %8x\n", i, at91_sys_read(AT91_PMC_PCKR(i)));
seq_printf(s, "SR = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
seq_printf(s, "\n");
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index ff8db29e989..ddf9184d561 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -53,7 +53,7 @@ static suspend_state_t target_state;
/*
* Called after processes are frozen, but before we shutdown devices.
*/
-static int at91_pm_prepare(suspend_state_t state)
+static int at91_pm_set_target(suspend_state_t state)
{
target_state = state;
return 0;
@@ -76,12 +76,11 @@ static int at91_pm_verify_clocks(void)
pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
return 0;
}
- } else if (cpu_is_at91sam9260()) {
-#warning "Check SAM9260 USB clocks"
- } else if (cpu_is_at91sam9261()) {
-#warning "Check SAM9261 USB clocks"
- } else if (cpu_is_at91sam9263()) {
-#warning "Check SAM9263 USB clocks"
+ } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()) {
+ if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) {
+ pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+ return 0;
+ }
}
#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
@@ -202,7 +201,7 @@ error:
static struct pm_ops at91_pm_ops ={
.valid = at91_pm_valid_state,
- .prepare = at91_pm_prepare,
+ .set_target = at91_pm_set_target,
.enter = at91_pm_enter,
};
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index a8f88cd2990..99ac2e55774 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -4,7 +4,8 @@
#
# Common objects
-obj-y := time.o irq.o serial.o io.o id.o psc.o
+obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \
+ gpio.o mux.o
# Board specific
obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c
index 633c12e4304..9e4024c4965 100644
--- a/arch/arm/mach-davinci/board-evm.c
+++ b/arch/arm/mach-davinci/board-evm.c
@@ -32,6 +32,7 @@
void __init davinci_psc_init(void);
void __init davinci_irq_init(void);
void __init davinci_map_common_io(void);
+void __init davinci_init_common_hw(void);
/* NOR Flash base address set to CS0 by default */
#define NOR_FLASH_PHYS 0x02000000
@@ -116,6 +117,7 @@ static __init void davinci_evm_init(void)
static __init void davinci_evm_irq_init(void)
{
+ davinci_init_common_hw();
davinci_irq_init();
}
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
new file mode 100644
index 00000000000..139ceaa35e2
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.c
@@ -0,0 +1,323 @@
+/*
+ * TI DaVinci clock config file
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/psc.h>
+#include "clock.h"
+
+/* PLL/Reset register offsets */
+#define PLLM 0x110
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clockfw_lock);
+
+static unsigned int commonrate;
+static unsigned int armrate;
+static unsigned int fixedrate = 27000000; /* 27 MHZ */
+
+extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
+
+/*
+ * Returns a clock. Note that we first try to use device id on the bus
+ * and clock name. If this fails, we try to use clock name only.
+ */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ struct clk *p, *clk = ERR_PTR(-ENOENT);
+ int idno;
+
+ if (dev == NULL || dev->bus != &platform_bus_type)
+ idno = -1;
+ else
+ idno = to_platform_device(dev)->id;
+
+ mutex_lock(&clocks_mutex);
+
+ list_for_each_entry(p, &clocks, node) {
+ if (p->id == idno &&
+ strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+ clk = p;
+ goto found;
+ }
+ }
+
+ list_for_each_entry(p, &clocks, node) {
+ if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+
+found:
+ mutex_unlock(&clocks_mutex);
+
+ return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+ if (clk && !IS_ERR(clk))
+ module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+static int __clk_enable(struct clk *clk)
+{
+ if (clk->flags & ALWAYS_ENABLED)
+ return 0;
+
+ davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
+ return 0;
+}
+
+static void __clk_disable(struct clk *clk)
+{
+ if (clk->usecount)
+ return;
+
+ davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
+}
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
+ if (clk->usecount++ == 0) {
+ spin_lock_irqsave(&clockfw_lock, flags);
+ ret = __clk_enable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
+ if (clk->usecount > 0 && !(--clk->usecount)) {
+ spin_lock_irqsave(&clockfw_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+ }
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
+ return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
+ return *(clk->rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
+ /* changing the clk rate is not supported */
+ return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return -EINVAL;
+
+ mutex_lock(&clocks_mutex);
+ list_add(&clk->node, &clocks);
+ mutex_unlock(&clocks_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
+ mutex_lock(&clocks_mutex);
+ list_del(&clk->node);
+ mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static struct clk davinci_clks[] = {
+ {
+ .name = "ARMCLK",
+ .rate = &armrate,
+ .lpsc = -1,
+ .flags = ALWAYS_ENABLED,
+ },
+ {
+ .name = "UART",
+ .rate = &fixedrate,
+ .lpsc = DAVINCI_LPSC_UART0,
+ },
+ {
+ .name = "EMACCLK",
+ .rate = &commonrate,
+ .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
+ },
+ {
+ .name = "I2CCLK",
+ .rate = &fixedrate,
+ .lpsc = DAVINCI_LPSC_I2C,
+ },
+ {
+ .name = "IDECLK",
+ .rate = &commonrate,
+ .lpsc = DAVINCI_LPSC_ATA,
+ },
+ {
+ .name = "McBSPCLK",
+ .rate = &commonrate,
+ .lpsc = DAVINCI_LPSC_McBSP,
+ },
+ {
+ .name = "MMCSDCLK",
+ .rate = &commonrate,
+ .lpsc = DAVINCI_LPSC_MMC_SD,
+ },
+ {
+ .name = "SPICLK",
+ .rate = &commonrate,
+ .lpsc = DAVINCI_LPSC_SPI,
+ },
+ {
+ .name = "gpio",
+ .rate = &commonrate,
+ .lpsc = DAVINCI_LPSC_GPIO,
+ },
+ {
+ .name = "AEMIFCLK",
+ .rate = &commonrate,
+ .lpsc = DAVINCI_LPSC_AEMIF,
+ .usecount = 1,
+ }
+};
+
+int __init davinci_clk_init(void)
+{
+ struct clk *clkp;
+ int count = 0;
+ u32 pll_mult;
+
+ pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
+ commonrate = ((pll_mult + 1) * 27000000) / 6;
+ armrate = ((pll_mult + 1) * 27000000) / 2;
+
+ for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
+ count++, clkp++) {
+ clk_register(clkp);
+
+ /* Turn on clocks that have been enabled in the
+ * table above */
+ if (clkp->usecount)
+ clk_enable(clkp);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return NULL;
+}
+
+static void davinci_ck_stop(struct seq_file *m, void *v)
+{
+}
+
+static int davinci_ck_show(struct seq_file *m, void *v)
+{
+ struct clk *cp;
+
+ list_for_each_entry(cp, &clocks, node)
+ seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
+
+ return 0;
+}
+
+static struct seq_operations davinci_ck_op = {
+ .start = davinci_ck_start,
+ .next = davinci_ck_next,
+ .stop = davinci_ck_stop,
+ .show = davinci_ck_show
+};
+
+static int davinci_ck_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &davinci_ck_op);
+}
+
+static struct file_operations proc_davinci_ck_operations = {
+ .open = davinci_ck_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init davinci_ck_proc_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ entry = create_proc_entry("davinci_clocks", 0, NULL);
+ if (entry)
+ entry->proc_fops = &proc_davinci_ck_operations;
+ return 0;
+
+}
+__initcall(davinci_ck_proc_init);
+#endif /* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
new file mode 100644
index 00000000000..ed47079a52e
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.h
@@ -0,0 +1,33 @@
+/*
+ * TI DaVinci clock definitions
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_DAVINCI_CLOCK_H
+#define __ARCH_ARM_DAVINCI_CLOCK_H
+
+struct clk {
+ struct list_head node;
+ struct module *owner;
+ const char *name;
+ unsigned int *rate;
+ int id;
+ __s8 usecount;
+ __u8 flags;
+ __u8 lpsc;
+};
+
+/* Clock flags */
+#define RATE_CKCTL 1
+#define RATE_FIXED 2
+#define RATE_PROPAGATES 4
+#define VIRTUAL_CLOCK 8
+#define ALWAYS_ENABLED 16
+#define ENABLE_REG_32BIT 32
+
+#endif
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
new file mode 100644
index 00000000000..9c67886e718
--- /dev/null
+++ b/arch/arm/mach-davinci/gpio.c
@@ -0,0 +1,286 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/gpio.h>
+
+#include <asm/mach/irq.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
+
+int gpio_request(unsigned gpio, const char *tag)
+{
+ if (gpio >= DAVINCI_N_GPIO)
+ return -EINVAL;
+
+ if (test_and_set_bit(gpio, gpio_in_use))
+ return -EBUSY;
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+ if (gpio >= DAVINCI_N_GPIO)
+ return;
+
+ clear_bit(gpio, gpio_in_use);
+}
+EXPORT_SYMBOL(gpio_free);
+
+/* create a non-inlined version */
+static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
+{
+ return __gpio_to_controller(gpio);
+}
+
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+void __gpio_set(unsigned gpio, int value)
+{
+ struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+ __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
+}
+EXPORT_SYMBOL(__gpio_set);
+
+
+/*
+ * Read the pin's value (works even if it's set up as output);
+ * returns zero/nonzero.
+ *
+ * Note that changes are synched to the GPIO clock, so reading values back
+ * right after you've set them may give old values.
+ */
+int __gpio_get(unsigned gpio)
+{
+ struct gpio_controller *__iomem g = gpio2controller(gpio);
+
+ return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+EXPORT_SYMBOL(__gpio_get);
+
+
+/*--------------------------------------------------------------------------*/
+
+/*
+ * board setup code *MUST* set PINMUX0 and PINMUX1 as
+ * needed, and enable the GPIO clock.
+ */
+
+int gpio_direction_input(unsigned gpio)
+{
+ struct gpio_controller *__iomem g = gpio2controller(gpio);
+ u32 temp;
+ u32 mask;
+
+ if (!g)
+ return -EINVAL;
+
+ spin_lock(&gpio_lock);
+ mask = __gpio_mask(gpio);
+ temp = __raw_readl(&g->dir);
+ temp |= mask;
+ __raw_writel(temp, &g->dir);
+ spin_unlock(&gpio_lock);
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ struct gpio_controller *__iomem g = gpio2controller(gpio);
+ u32 temp;
+ u32 mask;
+
+ if (!g)
+ return -EINVAL;
+
+ spin_lock(&gpio_lock);
+ mask = __gpio_mask(gpio);
+ temp = __raw_readl(&g->dir);
+ temp &= ~mask;
+ __raw_writel(mask, value ? &g->set_data : &g->clr_data);
+ __raw_writel(temp, &g->dir);
+ spin_unlock(&gpio_lock);
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+ * We expect irqs will normally be set up as input pins, but they can also be
+ * used as output pins ... which is convenient for testing.
+ *
+ * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition
+ * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have
+ * a good way to hook those up ...
+ *
+ * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
+ * serve as EDMA event triggers.
+ */
+
+static void gpio_irq_disable(unsigned irq)
+{
+ struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+ u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+ __raw_writel(mask, &g->clr_falling);
+ __raw_writel(mask, &g->clr_rising);
+}
+
+static void gpio_irq_enable(unsigned irq)
+{
+ struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+ u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+ if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
+ __raw_writel(mask, &g->set_falling);
+ if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
+ __raw_writel(mask, &g->set_rising);
+}
+
+static int gpio_irq_type(unsigned irq, unsigned trigger)
+{
+ struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+ u32 mask = __gpio_mask(irq_to_gpio(irq));
+
+ if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+ return -EINVAL;
+
+ irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
+ irq_desc[irq].status |= trigger;
+
+ __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
+ ? &g->set_falling : &g->clr_falling);
+ __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
+ ? &g->set_rising : &g->clr_rising);
+ return 0;
+}
+
+static struct irq_chip gpio_irqchip = {
+ .name = "GPIO",
+ .enable = gpio_irq_enable,
+ .disable = gpio_irq_disable,
+ .set_type = gpio_irq_type,
+};
+
+static void
+gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+ struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+ u32 mask = 0xffff;
+
+ /* we only care about one bank */
+ if (irq & 1)
+ mask <<= 16;
+
+ /* temporarily mask (level sensitive) parent IRQ */
+ desc->chip->ack(irq);
+ while (1) {
+ u32 status;
+ struct irq_desc *gpio;
+ int n;
+ int res;
+
+ /* ack any irqs */
+ status = __raw_readl(&g->intstat) & mask;
+ if (!status)
+ break;
+ __raw_writel(status, &g->intstat);
+ if (irq & 1)
+ status >>= 16;
+
+ /* now demux them to the right lowlevel handler */
+ n = (int)get_irq_data(irq);
+ gpio = &irq_desc[n];
+ while (status) {
+ res = ffs(status);
+ n += res;
+ gpio += res;
+ desc_handle_irq(n - 1, gpio - 1);
+ status >>= res;
+ }
+ }
+ desc->chip->unmask(irq);
+ /* now it may re-trigger */
+}
+
+/*
+ * NOTE: for suspend/resume, probably best to make a sysdev (and class)
+ * with its suspend/resume calls hooking into the results of the set_wake()
+ * calls ... so if no gpios are wakeup events the clock can be disabled,
+ * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
+ * can be set appropriately for GPIOV33 pins.
+ */
+
+static int __init davinci_gpio_irq_setup(void)
+{
+ unsigned gpio, irq, bank;
+ struct clk *clk;
+
+ clk = clk_get(NULL, "gpio");
+ if (IS_ERR(clk)) {
+ printk(KERN_ERR "Error %ld getting gpio clock?\n",
+ PTR_ERR(clk));
+ return 0;
+ }
+
+ clk_enable(clk);
+
+ for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
+ gpio < DAVINCI_N_GPIO; bank++) {
+ struct gpio_controller *__iomem g = gpio2controller(gpio);
+ unsigned i;
+
+ __raw_writel(~0, &g->clr_falling);
+ __raw_writel(~0, &g->clr_rising);
+
+ /* set up all irqs in this bank */
+ set_irq_chained_handler(bank, gpio_irq_handler);
+ set_irq_chip_data(bank, g);
+ set_irq_data(bank, (void *)irq);
+
+ for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
+ i++, irq++, gpio++) {
+ set_irq_chip(irq, &gpio_irqchip);
+ set_irq_chip_data(irq, g);
+ set_irq_handler(irq, handle_simple_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+ }
+
+ /* BINTEN -- per-bank interrupt enable. genirq would also let these
+ * bits be set/cleared dynamically.
+ */
+ __raw_writel(0x1f, (void *__iomem)
+ IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
+
+ printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
+
+ return 0;
+}
+
+arch_initcall(davinci_gpio_irq_setup);
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
index 87fae6fb6ec..47787ff84a6 100644
--- a/arch/arm/mach-davinci/io.c
+++ b/arch/arm/mach-davinci/io.c
@@ -17,6 +17,7 @@
#include <asm/memory.h>
#include <asm/mach/map.h>
+#include <asm/arch/clock.h>
extern void davinci_check_revision(void);
@@ -49,3 +50,8 @@ void __init davinci_map_common_io(void)
*/
davinci_check_revision();
}
+
+void __init davinci_init_common_hw(void)
+{
+ davinci_clk_init();
+}
diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c
new file mode 100644
index 00000000000..92d26bd305b
--- /dev/null
+++ b/arch/arm/mach-davinci/mux.c
@@ -0,0 +1,41 @@
+/*
+ * DaVinci pin multiplexing configurations
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+
+#include <asm/arch/mux.h>
+
+/* System control register offsets */
+#define PINMUX0 0x00
+#define PINMUX1 0x04
+
+static DEFINE_SPINLOCK(mux_lock);
+
+void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
+{
+ u32 pinmux, muxreg = PINMUX0;
+
+ if (mux >= DAVINCI_MUX_LEVEL2) {
+ muxreg = PINMUX1;
+ mux -= DAVINCI_MUX_LEVEL2;
+ }
+
+ spin_lock(&mux_lock);
+ pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+ if (enable)
+ pinmux |= (1 << mux);
+ else
+ pinmux &= ~(1 << mux);
+ davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
+ spin_unlock(&mux_lock);
+}
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index e1b0050283a..1334416559a 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -25,39 +25,40 @@
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/psc.h>
+#include <asm/arch/mux.h>
-#define PTCMD __REG(0x01C41120)
-#define PDSTAT __REG(0x01C41200)
-#define PDCTL1 __REG(0x01C41304)
-#define EPCPR __REG(0x01C41070)
-#define PTSTAT __REG(0x01C41128)
+/* PSC register offsets */
+#define EPCPR 0x070
+#define PTCMD 0x120
+#define PTSTAT 0x128
+#define PDSTAT 0x200
+#define PDCTL1 0x304
+#define MDSTAT 0x800
+#define MDCTL 0xA00
-#define MDSTAT IO_ADDRESS(0x01C41800)
-#define MDCTL IO_ADDRESS(0x01C41A00)
-
-#define PINMUX0 __REG(0x01c40000)
-#define PINMUX1 __REG(0x01c40004)
-#define VDD3P3V_PWDN __REG(0x01C40048)
+/* System control register offsets */
+#define VDD3P3V_PWDN 0x48
static void davinci_psc_mux(unsigned int id)
{
switch (id) {
case DAVINCI_LPSC_ATA:
- PINMUX0 |= (1 << 17) | (1 << 16);
+ davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
+ davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
break;
case DAVINCI_LPSC_MMC_SD:
/* VDD power manupulations are done in U-Boot for CPMAC
* so applies to MMC as well
*/
/*Set up the pull regiter for MMC */
- VDD3P3V_PWDN = 0x0;
- PINMUX1 &= (~(1 << 9));
+ davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
+ davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
break;
case DAVINCI_LPSC_I2C:
- PINMUX1 |= (1 << 7);
+ davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
break;
case DAVINCI_LPSC_McBSP:
- PINMUX1 |= (1 << 10);
+ davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
break;
default:
break;
@@ -67,33 +68,59 @@ static void davinci_psc_mux(unsigned int id)
/* Enable or disable a PSC domain */
void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
{
- volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id);
- volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
+ u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
if (id < 0)
return;
+ mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
if (enable)
- *mdctl |= 0x00000003; /* Enable Module */
+ mdctl |= 0x00000003; /* Enable Module */
else
- *mdctl &= 0xFFFFFFF2; /* Disable Module */
+ mdctl &= 0xFFFFFFF2; /* Disable Module */
+ davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
+
+ pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
+ if ((pdstat & 0x00000001) == 0) {
+ pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ pdctl1 |= 0x1;
+ davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+
+ ptcmd = 1 << domain;
+ davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
- if ((PDSTAT & 0x00000001) == 0) {
- PDCTL1 |= 0x1;
- PTCMD = (1 << domain);
- while ((((EPCPR >> domain) & 1) == 0));
+ do {
+ epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+ EPCPR);
+ } while ((((epcpr >> domain) & 1) == 0));
- PDCTL1 |= 0x100;
- while (!(((PTSTAT >> domain) & 1) == 0));
+ pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ pdctl1 |= 0x100;
+ davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+
+ do {
+ ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+ PTSTAT);
+ } while (!(((ptstat >> domain) & 1) == 0));
} else {
- PTCMD = (1 << domain);
- while (!(((PTSTAT >> domain) & 1) == 0));
+ ptcmd = 1 << domain;
+ davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+
+ do {
+ ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+ PTSTAT);
+ } while (!(((ptstat >> domain) & 1) == 0));
}
if (enable)
- while (!((*mdstat & 0x0000001F) == 0x3));
+ mdstat_mask = 0x3;
else
- while (!((*mdstat & 0x0000001F) == 0x2));
+ mdstat_mask = 0x2;
+
+ do {
+ mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+ MDSTAT + 4 * id);
+ } while (!((mdstat & 0x0000001F) == mdstat_mask));
if (enable)
davinci_psc_mux(id);
diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c
index 1c474cf709c..a58b678006d 100644
--- a/arch/arm/mach-imx/generic.c
+++ b/arch/arm/mach-imx/generic.c
@@ -28,12 +28,16 @@
#include <linux/module.h>
#include <linux/string.h>
+#include <asm/errno.h>
#include <asm/arch/imxfb.h>
#include <asm/hardware.h>
#include <asm/arch/imx-regs.h>
#include <asm/mach/map.h>
#include <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
void imx_gpio_mode(int gpio_mode)
{
@@ -95,6 +99,120 @@ void imx_gpio_mode(int gpio_mode)
EXPORT_SYMBOL(imx_gpio_mode);
+int imx_gpio_request(unsigned gpio, const char *label)
+{
+ if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+ printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
+ gpio, label ? label : "?");
+ return -EINVAL;
+
+ if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
+ printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
+ gpio, label ? label : "?");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_request);
+
+void imx_gpio_free(unsigned gpio)
+{
+ if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+ return;
+
+ clear_bit(gpio, imx_gpio_alloc_map);
+}
+
+EXPORT_SYMBOL(imx_gpio_free);
+
+int imx_gpio_direction_input(unsigned gpio)
+{
+ imx_gpio_mode(gpio| GPIO_IN);
+ return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_input);
+
+int imx_gpio_direction_output(unsigned gpio, int value)
+{
+ imx_gpio_set_value(gpio, value);
+ imx_gpio_mode(gpio| GPIO_OUT);
+ return 0;
+}
+
+EXPORT_SYMBOL(imx_gpio_direction_output);
+
+int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+ int alloc_mode, const char *label)
+{
+ const int *p = pin_list;
+ int i;
+ unsigned gpio;
+ unsigned mode;
+
+ for (i = 0; i < count; i++) {
+ gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+ mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+ if (gpio >= (GPIO_PORT_MAX + 1) * 32)
+ goto setup_error;
+
+ if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
+ imx_gpio_free(gpio);
+ else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
+ if (imx_gpio_request(gpio, label))
+ if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+ goto setup_error;
+
+ if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
+ IMX_GPIO_ALLOC_MODE_RELEASE)))
+ imx_gpio_mode(gpio | mode);
+
+ p++;
+ }
+ return 0;
+
+setup_error:
+ if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
+ IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+ return -EINVAL;
+
+ while (p != pin_list) {
+ p--;
+ gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+ imx_gpio_free(gpio);
+ }
+
+ return -EINVAL;
+}
+
+EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
+
+void __imx_gpio_set_value(unsigned gpio, int value)
+{
+ imx_gpio_set_value_inline(gpio, value);
+}
+
+EXPORT_SYMBOL(__imx_gpio_set_value);
+
+int imx_gpio_to_irq(unsigned gpio)
+{
+ return IRQ_GPIOA(0) + gpio;
+}
+
+EXPORT_SYMBOL(imx_gpio_to_irq);
+
+int imx_irq_to_gpio(unsigned irq)
+{
+ if (irq < IRQ_GPIOA(0))
+ return -EINVAL;
+ return irq - IRQ_GPIOA(0);
+}
+
+EXPORT_SYMBOL(imx_irq_to_gpio);
+
/*
* get the system pll clock in Hz
*
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 6960a9d0421..010f6fa984a 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2000-2001 Deep Blue Solutions
* Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ * Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.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
@@ -15,6 +16,7 @@
#include <linux/irq.h>
#include <linux/time.h>
#include <linux/clocksource.h>
+#include <linux/clockchips.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -25,7 +27,8 @@
/* Use timer 1 as system timer */
#define TIMER_BASE IMX_TIM1_BASE
-static unsigned long evt_diff;
+static struct clock_event_device clockevent_imx;
+static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
/*
* IRQ handler for the timer
@@ -33,25 +36,20 @@ static unsigned long evt_diff;
static irqreturn_t
imx_timer_interrupt(int irq, void *dev_id)
{
+ struct clock_event_device *evt = &clockevent_imx;
uint32_t tstat;
+ irqreturn_t ret = IRQ_NONE;
/* clear the interrupt */
tstat = IMX_TSTAT(TIMER_BASE);
IMX_TSTAT(TIMER_BASE) = 0;
if (tstat & TSTAT_COMP) {
- do {
-
- write_seqlock(&xtime_lock);
- timer_tick();
- write_sequnlock(&xtime_lock);
- IMX_TCMP(TIMER_BASE) += evt_diff;
-
- } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE)
- - IMX_TCN(TIMER_BASE)) < 0));
+ evt->event_handler(evt);
+ ret = IRQ_HANDLED;
}
- return IRQ_HANDLED;
+ return ret;
}
static struct irqaction imx_timer_irq = {
@@ -70,10 +68,8 @@ static void __init imx_timer_hardware_init(void)
*/
IMX_TCTL(TIMER_BASE) = 0;
IMX_TPRER(TIMER_BASE) = 0;
- IMX_TCMP(TIMER_BASE) = LATCH - 1;
- IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN;
- evt_diff = LATCH;
+ IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN;
}
cycle_t imx_get_cycles(void)
@@ -99,11 +95,108 @@ static int __init imx_clocksource_init(void)
return 0;
}
+static int imx_set_next_event(unsigned long evt,
+ struct clock_event_device *unused)
+{
+ unsigned long tcmp;
+
+ tcmp = IMX_TCN(TIMER_BASE) + evt;
+ IMX_TCMP(TIMER_BASE) = tcmp;
+
+ return (int32_t)(tcmp - IMX_TCN(TIMER_BASE)) < 0 ? -ETIME : 0;
+}
+
+#ifdef DEBUG
+static const char *clock_event_mode_label[]={
+ [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
+ [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT",
+ [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
+ [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED"
+};
+#endif /*DEBUG*/
+
+static void imx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
+{
+ unsigned long flags;
+
+ /*
+ * The timer interrupt generation is disabled at least
+ * for enough time to call imx_set_next_event()
+ */
+ local_irq_save(flags);
+ /* Disable interrupt in GPT module */
+ IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN;
+ if (mode != clockevent_mode) {
+ /* Set event time into far-far future */
+ IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3;
+ /* Clear pending interrupt */
+ IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP;
+ }
+
+#ifdef DEBUG
+ printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n",
+ clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]);
+#endif /*DEBUG*/
+
+ /* Remember timer mode */
+ clockevent_mode = mode;
+ local_irq_restore(flags);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n");
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ /*
+ * Do not put overhead of interrupt enable/disable into
+ * imx_set_next_event(), the core has about 4 minutes
+ * to call imx_set_next_event() or shutdown clock after
+ * mode switching
+ */
+ local_irq_save(flags);
+ IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN;
+ local_irq_restore(flags);
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ /* Left event sources disabled, no more interrupts appears */
+ break;
+ }
+}
+
+static struct clock_event_device clockevent_imx = {
+ .name = "imx_timer1",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .set_mode = imx_set_mode,
+ .set_next_event = imx_set_next_event,
+ .rating = 200,
+};
+
+static int __init imx_clockevent_init(void)
+{
+ clockevent_imx.mult = div_sc(imx_get_perclk1(), NSEC_PER_SEC,
+ clockevent_imx.shift);
+ clockevent_imx.max_delta_ns =
+ clockevent_delta2ns(0xfffffffe, &clockevent_imx);
+ clockevent_imx.min_delta_ns =
+ clockevent_delta2ns(0xf, &clockevent_imx);
+
+ clockevent_imx.cpumask = cpumask_of_cpu(0);
+
+ clockevents_register_device(&clockevent_imx);
+
+ return 0;
+}
+
+
static void __init imx_timer_init(void)
{
imx_timer_hardware_init();
imx_clocksource_init();
+ imx_clockevent_init();
+
/*
* Make irqs happen for the system timer
*/
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index bc4871553f6..bfe0c87e339 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -25,6 +25,7 @@
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/hardware/iop_adma.h>
#define IOP13XX_UART_XTAL 33334000
#define IOP13XX_SETUP_DEBUG 0
@@ -236,19 +237,143 @@ static unsigned long iq8134x_probe_flash_size(void)
}
#endif
+/* ADMA Channels */
+static struct resource iop13xx_adma_0_resources[] = {
+ [0] = {
+ .start = IOP13XX_ADMA_PHYS_BASE(0),
+ .end = IOP13XX_ADMA_UPPER_PA(0),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_IOP13XX_ADMA0_EOT,
+ .end = IRQ_IOP13XX_ADMA0_EOT,
+ .flags = IORESOURCE_IRQ
+ },
+ [2] = {
+ .start = IRQ_IOP13XX_ADMA0_EOC,
+ .end = IRQ_IOP13XX_ADMA0_EOC,
+ .flags = IORESOURCE_IRQ
+ },
+ [3] = {
+ .start = IRQ_IOP13XX_ADMA0_ERR,
+ .end = IRQ_IOP13XX_ADMA0_ERR,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct resource iop13xx_adma_1_resources[] = {
+ [0] = {
+ .start = IOP13XX_ADMA_PHYS_BASE(1),
+ .end = IOP13XX_ADMA_UPPER_PA(1),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_IOP13XX_ADMA1_EOT,
+ .end = IRQ_IOP13XX_ADMA1_EOT,
+ .flags = IORESOURCE_IRQ
+ },
+ [2] = {
+ .start = IRQ_IOP13XX_ADMA1_EOC,
+ .end = IRQ_IOP13XX_ADMA1_EOC,
+ .flags = IORESOURCE_IRQ
+ },
+ [3] = {
+ .start = IRQ_IOP13XX_ADMA1_ERR,
+ .end = IRQ_IOP13XX_ADMA1_ERR,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct resource iop13xx_adma_2_resources[] = {
+ [0] = {
+ .start = IOP13XX_ADMA_PHYS_BASE(2),
+ .end = IOP13XX_ADMA_UPPER_PA(2),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_IOP13XX_ADMA2_EOT,
+ .end = IRQ_IOP13XX_ADMA2_EOT,
+ .flags = IORESOURCE_IRQ
+ },
+ [2] = {
+ .start = IRQ_IOP13XX_ADMA2_EOC,
+ .end = IRQ_IOP13XX_ADMA2_EOC,
+ .flags = IORESOURCE_IRQ
+ },
+ [3] = {
+ .start = IRQ_IOP13XX_ADMA2_ERR,
+ .end = IRQ_IOP13XX_ADMA2_ERR,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static u64 iop13xx_adma_dmamask = DMA_64BIT_MASK;
+static struct iop_adma_platform_data iop13xx_adma_0_data = {
+ .hw_id = 0,
+ .pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop13xx_adma_1_data = {
+ .hw_id = 1,
+ .pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop13xx_adma_2_data = {
+ .hw_id = 2,
+ .pool_size = PAGE_SIZE,
+};
+
+/* The ids are fixed up later in iop13xx_platform_init */
+static struct platform_device iop13xx_adma_0_channel = {
+ .name = "iop-adma",
+ .id = 0,
+ .num_resources = 4,
+ .resource = iop13xx_adma_0_resources,
+ .dev = {
+ .dma_mask = &iop13xx_adma_dmamask,
+ .coherent_dma_mask = DMA_64BIT_MASK,
+ .platform_data = (void *) &iop13xx_adma_0_data,
+ },
+};
+
+static struct platform_device iop13xx_adma_1_channel = {
+ .name = "iop-adma",
+ .id = 0,
+ .num_resources = 4,
+ .resource = iop13xx_adma_1_resources,
+ .dev = {
+ .dma_mask = &iop13xx_adma_dmamask,
+ .coherent_dma_mask = DMA_64BIT_MASK,
+ .platform_data = (void *) &iop13xx_adma_1_data,
+ },
+};
+
+static struct platform_device iop13xx_adma_2_channel = {
+ .name = "iop-adma",
+ .id = 0,
+ .num_resources = 4,
+ .resource = iop13xx_adma_2_resources,
+ .dev = {
+ .dma_mask = &iop13xx_adma_dmamask,
+ .coherent_dma_mask = DMA_64BIT_MASK,
+ .platform_data = (void *) &iop13xx_adma_2_data,
+ },
+};
+
void __init iop13xx_map_io(void)
{
/* Initialize the Static Page Table maps */
iotable_init(iop13xx_std_desc, ARRAY_SIZE(iop13xx_std_desc));
}
-static int init_uart = 0;
-static int init_i2c = 0;
+static int init_uart;
+static int init_i2c;
+static int init_adma;
void __init iop13xx_platform_init(void)
{
int i;
- u32 uart_idx, i2c_idx, plat_idx;
+ u32 uart_idx, i2c_idx, adma_idx, plat_idx;
struct platform_device *iop13xx_devices[IQ81340_MAX_PLAT_DEVICES];
/* set the bases so we can read the device id */
@@ -294,6 +419,12 @@ void __init iop13xx_platform_init(void)
}
}
+ if (init_adma == IOP13XX_INIT_ADMA_DEFAULT) {
+ init_adma |= IOP13XX_INIT_ADMA_0;
+ init_adma |= IOP13XX_INIT_ADMA_1;
+ init_adma |= IOP13XX_INIT_ADMA_2;
+ }
+
plat_idx = 0;
uart_idx = 0;
i2c_idx = 0;
@@ -332,6 +463,56 @@ void __init iop13xx_platform_init(void)
}
}
+ /* initialize adma channel ids and capabilities */
+ adma_idx = 0;
+ for (i = 0; i < IQ81340_NUM_ADMA; i++) {
+ struct iop_adma_platform_data *plat_data;
+ if ((init_adma & (1 << i)) && IOP13XX_SETUP_DEBUG)
+ printk(KERN_INFO
+ "Adding adma%d to platform device list\n", i);
+ switch (init_adma & (1 << i)) {
+ case IOP13XX_INIT_ADMA_0:
+ iop13xx_adma_0_channel.id = adma_idx++;
+ iop13xx_devices[plat_idx++] = &iop13xx_adma_0_channel;
+ plat_data = &iop13xx_adma_0_data;
+ dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+ dma_cap_set(DMA_XOR, plat_data->cap_mask);
+ dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+ dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+ dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+ dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+ dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+ break;
+ case IOP13XX_INIT_ADMA_1:
+ iop13xx_adma_1_channel.id = adma_idx++;
+ iop13xx_devices[plat_idx++] = &iop13xx_adma_1_channel;
+ plat_data = &iop13xx_adma_1_data;
+ dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+ dma_cap_set(DMA_XOR, plat_data->cap_mask);
+ dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+ dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+ dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+ dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+ dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+ break;
+ case IOP13XX_INIT_ADMA_2:
+ iop13xx_adma_2_channel.id = adma_idx++;
+ iop13xx_devices[plat_idx++] = &iop13xx_adma_2_channel;
+ plat_data = &iop13xx_adma_2_data;
+ dma_cap_set(DMA_MEMCPY, plat_data->cap_mask);
+ dma_cap_set(DMA_XOR, plat_data->cap_mask);
+ dma_cap_set(DMA_DUAL_XOR, plat_data->cap_mask);
+ dma_cap_set(DMA_ZERO_SUM, plat_data->cap_mask);
+ dma_cap_set(DMA_MEMSET, plat_data->cap_mask);
+ dma_cap_set(DMA_MEMCPY_CRC32C, plat_data->cap_mask);
+ dma_cap_set(DMA_INTERRUPT, plat_data->cap_mask);
+ dma_cap_set(DMA_PQ_XOR, plat_data->cap_mask);
+ dma_cap_set(DMA_PQ_UPDATE, plat_data->cap_mask);
+ dma_cap_set(DMA_PQ_ZERO_SUM, plat_data->cap_mask);
+ break;
+ }
+ }
+
#ifdef CONFIG_MTD_PHYSMAP
iq8134x_flash_resource.end = iq8134x_flash_resource.start +
iq8134x_probe_flash_size() - 1;
@@ -399,5 +580,35 @@ static int __init iop13xx_init_i2c_setup(char *str)
return 1;
}
+static int __init iop13xx_init_adma_setup(char *str)
+{
+ if (str) {
+ while (*str != '\0') {
+ switch (*str) {
+ case '0':
+ init_adma |= IOP13XX_INIT_ADMA_0;
+ break;
+ case '1':
+ init_adma |= IOP13XX_INIT_ADMA_1;
+ break;
+ case '2':
+ init_adma |= IOP13XX_INIT_ADMA_2;
+ break;
+ case ',':
+ case '=':
+ break;
+ default:
+ PRINTK("\"iop13xx_init_adma\" malformed"
+ " at character: \'%c\'", *str);
+ *(str + 1) = '\0';
+ init_adma = IOP13XX_INIT_ADMA_DEFAULT;
+ }
+ str++;
+ }
+ }
+ return 1;
+}
+
+__setup("iop13xx_init_adma", iop13xx_init_adma_setup);
__setup("iop13xx_init_uart", iop13xx_init_uart_setup);
__setup("iop13xx_init_i2c", iop13xx_init_i2c_setup);
diff --git a/arch/arm/mach-iop13xx/tpmi.c b/arch/arm/mach-iop13xx/tpmi.c
index d3dc278213d..2476347ea62 100644
--- a/arch/arm/mach-iop13xx/tpmi.c
+++ b/arch/arm/mach-iop13xx/tpmi.c
@@ -29,13 +29,15 @@
#define IOP13XX_TPMI_MMR(dev) IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
#define IOP13XX_TPMI_MEM(dev) IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
#define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
+#define IOP13XX_TPMI_IOP_CTRL(dev) (IOP13XX_TPMI_CTRL(dev) + 0x2000)
#define IOP13XX_TPMI_MMR_SIZE (SZ_4K - 1)
#define IOP13XX_TPMI_MEM_SIZE (255)
#define IOP13XX_TPMI_MEM_CTRL (SZ_1K - 1)
#define IOP13XX_TPMI_RESOURCE_MMR 0
#define IOP13XX_TPMI_RESOURCE_MEM 1
#define IOP13XX_TPMI_RESOURCE_CTRL 2
-#define IOP13XX_TPMI_RESOURCE_IRQ 3
+#define IOP13XX_TPMI_RESOURCE_IOP_CTRL 3
+#define IOP13XX_TPMI_RESOURCE_IRQ 4
static struct resource iop13xx_tpmi_0_resources[] = {
[IOP13XX_TPMI_RESOURCE_MMR] = {
@@ -53,6 +55,11 @@ static struct resource iop13xx_tpmi_0_resources[] = {
.end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
.flags = IORESOURCE_MEM,
},
+ [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+ .start = IOP13XX_TPMI_IOP_CTRL(0),
+ .end = IOP13XX_TPMI_IOP_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
+ .flags = IORESOURCE_MEM,
+ },
[IOP13XX_TPMI_RESOURCE_IRQ] = {
.start = IRQ_IOP13XX_TPMI0_OUT,
.end = IRQ_IOP13XX_TPMI0_OUT,
@@ -76,6 +83,11 @@ static struct resource iop13xx_tpmi_1_resources[] = {
.end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
.flags = IORESOURCE_MEM,
},
+ [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+ .start = IOP13XX_TPMI_IOP_CTRL(1),
+ .end = IOP13XX_TPMI_IOP_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
+ .flags = IORESOURCE_MEM,
+ },
[IOP13XX_TPMI_RESOURCE_IRQ] = {
.start = IRQ_IOP13XX_TPMI1_OUT,
.end = IRQ_IOP13XX_TPMI1_OUT,
@@ -99,6 +111,11 @@ static struct resource iop13xx_tpmi_2_resources[] = {
.end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
.flags = IORESOURCE_MEM,
},
+ [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+ .start = IOP13XX_TPMI_IOP_CTRL(2),
+ .end = IOP13XX_TPMI_IOP_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
+ .flags = IORESOURCE_MEM,
+ },
[IOP13XX_TPMI_RESOURCE_IRQ] = {
.start = IRQ_IOP13XX_TPMI2_OUT,
.end = IRQ_IOP13XX_TPMI2_OUT,
@@ -122,6 +139,11 @@ static struct resource iop13xx_tpmi_3_resources[] = {
.end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
.flags = IORESOURCE_MEM,
},
+ [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = {
+ .start = IOP13XX_TPMI_IOP_CTRL(3),
+ .end = IOP13XX_TPMI_IOP_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
+ .flags = IORESOURCE_MEM,
+ },
[IOP13XX_TPMI_RESOURCE_IRQ] = {
.start = IRQ_IOP13XX_TPMI3_OUT,
.end = IRQ_IOP13XX_TPMI3_OUT,
@@ -133,7 +155,7 @@ u64 iop13xx_tpmi_mask = DMA_64BIT_MASK;
static struct platform_device iop13xx_tpmi_0_device = {
.name = "iop-tpmi",
.id = 0,
- .num_resources = 4,
+ .num_resources = ARRAY_SIZE(iop13xx_tpmi_0_resources),
.resource = iop13xx_tpmi_0_resources,
.dev = {
.dma_mask = &iop13xx_tpmi_mask,
@@ -144,7 +166,7 @@ static struct platform_device iop13xx_tpmi_0_device = {
static struct platform_device iop13xx_tpmi_1_device = {
.name = "iop-tpmi",
.id = 1,
- .num_resources = 4,
+ .num_resources = ARRAY_SIZE(iop13xx_tpmi_1_resources),
.resource = iop13xx_tpmi_1_resources,
.dev = {
.dma_mask = &iop13xx_tpmi_mask,
@@ -155,7 +177,7 @@ static struct platform_device iop13xx_tpmi_1_device = {
static struct platform_device iop13xx_tpmi_2_device = {
.name = "iop-tpmi",
.id = 2,
- .num_resources = 4,
+ .num_resources = ARRAY_SIZE(iop13xx_tpmi_2_resources),
.resource = iop13xx_tpmi_2_resources,
.dev = {
.dma_mask = &iop13xx_tpmi_mask,
@@ -166,7 +188,7 @@ static struct platform_device iop13xx_tpmi_2_device = {
static struct platform_device iop13xx_tpmi_3_device = {
.name = "iop-tpmi",
.id = 3,
- .num_resources = 4,
+ .num_resources = ARRAY_SIZE(iop13xx_tpmi_3_resources),
.resource = iop13xx_tpmi_3_resources,
.dev = {
.dma_mask = &iop13xx_tpmi_mask,
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 5776fd88411..2b086ab2668 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -180,6 +180,8 @@ static void __init glantank_init_machine(void)
platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&glantank_flash_device);
platform_device_register(&glantank_serial_device);
+ platform_device_register(&iop3xx_dma_0_channel);
+ platform_device_register(&iop3xx_dma_1_channel);
pm_power_off = glantank_power_off;
}
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index d4eefbea1fe..98cfa1cd6bd 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -298,9 +298,14 @@ static void __init iq31244_init_machine(void)
platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&iq31244_flash_device);
platform_device_register(&iq31244_serial_device);
+ platform_device_register(&iop3xx_dma_0_channel);
+ platform_device_register(&iop3xx_dma_1_channel);
if (is_ep80219())
pm_power_off = ep80219_power_off;
+
+ if (!is_80219())
+ platform_device_register(&iop3xx_aau_channel);
}
static int __init force_ep80219_setup(char *str)
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index 8d9f49164a8..18ad29f213b 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -181,6 +181,9 @@ static void __init iq80321_init_machine(void)
platform_device_register(&iop3xx_i2c1_device);
platform_device_register(&iq80321_flash_device);
platform_device_register(&iq80321_serial_device);
+ platform_device_register(&iop3xx_dma_0_channel);
+ platform_device_register(&iop3xx_dma_1_channel);
+ platform_device_register(&iop3xx_aau_channel);
}
MACHINE_START(IQ80321, "Intel IQ80321")
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index d55005d6478..390a97d39e5 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -245,6 +245,8 @@ static void __init n2100_init_machine(void)
platform_device_register(&iop3xx_i2c0_device);
platform_device_register(&n2100_flash_device);
platform_device_register(&n2100_serial_device);
+ platform_device_register(&iop3xx_dma_0_channel);
+ platform_device_register(&iop3xx_dma_1_channel);
pm_power_off = n2100_power_off;
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index 2b063180687..433188ebff2 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -136,6 +136,9 @@ static void __init iq80331_init_machine(void)
platform_device_register(&iop33x_uart0_device);
platform_device_register(&iop33x_uart1_device);
platform_device_register(&iq80331_flash_device);
+ platform_device_register(&iop3xx_dma_0_channel);
+ platform_device_register(&iop3xx_dma_1_channel);
+ platform_device_register(&iop3xx_aau_channel);
}
MACHINE_START(IQ80331, "Intel IQ80331")
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index 7889ce3cb08..416c09564cc 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -136,6 +136,9 @@ static void __init iq80332_init_machine(void)
platform_device_register(&iop33x_uart0_device);
platform_device_register(&iop33x_uart1_device);
platform_device_register(&iq80332_flash_device);
+ platform_device_register(&iop3xx_dma_0_channel);
+ platform_device_register(&iop3xx_dma_1_channel);
+ platform_device_register(&iop3xx_aau_channel);
}
MACHINE_START(IQ80332, "Intel IQ80332")
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 060909870b5..61b2dfcb89d 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -41,6 +41,22 @@ config ARCH_ADI_COYOTE
Engineering Coyote Gateway Reference Platform. For more
information on this platform, see <file:Documentation/arm/IXP4xx>.
+config MACH_GATEWAY7001
+ bool "Gateway 7001"
+ select PCI
+ help
+ Say 'Y' here if you want your kernel to support Gateway's
+ 7001 Access Point. For more information on this platform,
+ see http://openwrt.org
+
+config MACH_WG302V2
+ bool "Netgear WG302 v2 / WAG302 v2"
+ select PCI
+ help
+ Say 'Y' here if you want your kernel to support Netgear's
+ WG302 v2 or WAG302 v2 Access Points. For more information
+ on this platform, see http://openwrt.org
+
config ARCH_IXDP425
bool "IXDP425"
help
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 3b87c47e06c..77e00ade558 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -13,6 +13,8 @@ obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o
obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o
obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o
obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o
+obj-pci-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o
+obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o
obj-y += common.o
@@ -24,5 +26,7 @@ obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o
obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o
obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o
obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o dsmg600-power.o
+obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o
+obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o
obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o
diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c
new file mode 100644
index 00000000000..6abf568322d
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/gateway7001-pci.c
+ *
+ * PCI setup routines for Gateway 7001
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ * Copyright (C) 2002 Jungo Software Technologies.
+ * Copyright (C) 2003 MontaVista Softwrae, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init gateway7001_pci_preinit(void)
+{
+ set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW);
+ set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW);
+
+ ixp4xx_pci_preinit();
+}
+
+static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (slot == 1)
+ return IRQ_IXP4XX_GPIO11;
+ else if (slot == 2)
+ return IRQ_IXP4XX_GPIO10;
+ else return -1;
+}
+
+struct hw_pci gateway7001_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = gateway7001_pci_preinit,
+ .swizzle = pci_std_swizzle,
+ .setup = ixp4xx_setup,
+ .scan = ixp4xx_scan_bus,
+ .map_irq = gateway7001_map_irq,
+};
+
+int __init gateway7001_pci_init(void)
+{
+ if (machine_is_gateway7001())
+ pci_common_init(&gateway7001_pci);
+ return 0;
+}
+
+subsys_initcall(gateway7001_pci_init);
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
new file mode 100644
index 00000000000..37876832e14
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -0,0 +1,108 @@
+/*
+ * arch/arm/mach-ixp4xx/gateway7001-setup.c
+ *
+ * Board setup for the Gateway 7001 board
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <Kaloz@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data gateway7001_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+};
+
+static struct resource gateway7001_flash_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device gateway7001_flash = {
+ .name = "IXP4XX-Flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &gateway7001_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &gateway7001_flash_resource,
+};
+
+static struct resource gateway7001_uart_resource = {
+ .start = IXP4XX_UART2_BASE_PHYS,
+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port gateway7001_uart_data[] = {
+ {
+ .mapbase = IXP4XX_UART2_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ },
+ { },
+};
+
+static struct platform_device gateway7001_uart = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = gateway7001_uart_data,
+ },
+ .num_resources = 1,
+ .resource = &gateway7001_uart_resource,
+};
+
+static struct platform_device *gateway7001_devices[] __initdata = {
+ &gateway7001_flash,
+ &gateway7001_uart
+};
+
+static void __init gateway7001_init(void)
+{
+ ixp4xx_sys_init();
+
+ gateway7001_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+ gateway7001_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+ platform_add_devices(gateway7001_devices, ARRAY_SIZE(gateway7001_devices));
+}
+
+#ifdef CONFIG_MACH_GATEWAY7001
+MACHINE_START(GATEWAY7001, "Gateway 7001 AP")
+ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .boot_params = 0x0100,
+ .init_machine = gateway7001_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
index a66484b63d3..0d5a4245582 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
@@ -25,17 +25,13 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/irq.h>
+
#include <asm/mach-types.h>
#include <asm/hardware.h>
-#include <asm/irq.h>
#include <asm/arch/gtwx5715.h>
#include <asm/mach/pci.h>
-extern void ixp4xx_pci_preinit(void);
-extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
-extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
-
-
/*
* The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
* Slot 0 isn't actually populated with a card connector but
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index ec4f07950ec..d5008d8fc9a 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -15,6 +15,10 @@
#include <linux/tty.h>
#include <linux/serial_8250.h>
#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -24,6 +28,7 @@
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
+#include <asm/delay.h>
static struct flash_platform_data ixdp425_flash_data = {
.map_name = "cfi_probe",
@@ -44,6 +49,77 @@ static struct platform_device ixdp425_flash = {
.resource = &ixdp425_flash_resource,
};
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+ defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+
+#ifdef CONFIG_MTD_PARTITIONS
+const char *part_probes[] = { "cmdlinepart", NULL };
+
+static struct mtd_partition ixdp425_partitions[] = {
+ {
+ .name = "ixp400 NAND FS 0",
+ .offset = 0,
+ .size = SZ_8M
+ }, {
+ .name = "ixp400 NAND FS 1",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL
+ },
+};
+#endif
+
+static void
+ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+ int offset = (int)this->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ if (ctrl & NAND_NCE) {
+ gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_LOW);
+ udelay(5);
+ } else
+ gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_HIGH);
+
+ offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0;
+ offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0;
+ this->priv = (void *)offset;
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W + offset);
+}
+
+static struct platform_nand_data ixdp425_flash_nand_data = {
+ .chip = {
+ .chip_delay = 30,
+ .options = NAND_NO_AUTOINCR,
+#ifdef CONFIG_MTD_PARTITIONS
+ .part_probe_types = part_probes,
+ .partitions = ixdp425_partitions,
+ .nr_partitions = ARRAY_SIZE(ixdp425_partitions),
+#endif
+ },
+ .ctrl = {
+ .cmd_ctrl = ixdp425_flash_nand_cmd_ctrl
+ }
+};
+
+static struct resource ixdp425_flash_nand_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp425_flash_nand = {
+ .name = "gen_nand",
+ .id = -1,
+ .dev = {
+ .platform_data = &ixdp425_flash_nand_data,
+ },
+ .num_resources = 1,
+ .resource = &ixdp425_flash_nand_resource,
+};
+#endif /* CONFIG_MTD_NAND_PLATFORM */
+
static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = {
.sda_pin = IXDP425_SDA_PIN,
.scl_pin = IXDP425_SCL_PIN,
@@ -104,6 +180,10 @@ static struct platform_device ixdp425_uart = {
static struct platform_device *ixdp425_devices[] __initdata = {
&ixdp425_i2c_controller,
&ixdp425_flash,
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+ defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+ &ixdp425_flash_nand,
+#endif
&ixdp425_uart
};
@@ -115,6 +195,22 @@ static void __init ixdp425_init(void)
ixdp425_flash_resource.end =
IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+#if defined(CONFIG_MTD_NAND_PLATFORM) || \
+ defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
+ ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3),
+ ixdp425_flash_nand_resource.end = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1;
+
+ gpio_line_config(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_OUT);
+
+ /* Configure expansion bus for NAND Flash */
+ *IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN |
+ IXP4XX_EXP_BUS_STROBE_T(1) | /* extend by 1 clock */
+ IXP4XX_EXP_BUS_CYCLES(0) | /* Intel cycles */
+ IXP4XX_EXP_BUS_SIZE(0) | /* 512bytes addr space*/
+ IXP4XX_EXP_BUS_WR_EN |
+ IXP4XX_EXP_BUS_BYTE_EN; /* 8 bit data bus */
+#endif
+
if (cpu_is_ixp43x()) {
ixdp425_uart.num_resources = 1;
ixdp425_uart_data[1].flags = 0;
diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c
new file mode 100644
index 00000000000..6588f2c758e
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arch/mach-ixp4xx/wg302v2-pci.c
+ *
+ * PCI setup routines for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * based on coyote-pci.c:
+ * Copyright (C) 2002 Jungo Software Technologies.
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ *
+ * Maintainer: Imre Kaloz <kaloz@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/pci.h>
+
+void __init wg302v2_pci_preinit(void)
+{
+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW);
+ set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW);
+
+ ixp4xx_pci_preinit();
+}
+
+static int __init wg302v2_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (slot == 1)
+ return IRQ_IXP4XX_GPIO8;
+ else if (slot == 2)
+ return IRQ_IXP4XX_GPIO9;
+ else return -1;
+}
+
+struct hw_pci wg302v2_pci __initdata = {
+ .nr_controllers = 1,
+ .preinit = wg302v2_pci_preinit,
+ .swizzle = pci_std_swizzle,
+ .setup = ixp4xx_setup,
+ .scan = ixp4xx_scan_bus,
+ .map_irq = wg302v2_map_irq,
+};
+
+int __init wg302v2_pci_init(void)
+{
+ if (machine_is_wg302v2())
+ pci_common_init(&wg302v2_pci);
+ return 0;
+}
+
+subsys_initcall(wg302v2_pci_init);
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
new file mode 100644
index 00000000000..f7e09ad804e
--- /dev/null
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -0,0 +1,109 @@
+/*
+ * arch/arm/mach-ixp4xx/wg302-setup.c
+ *
+ * Board setup for the Netgear WG302 v2 and WAG302 v2
+ *
+ * Copyright (C) 2007 Imre Kaloz <Kaloz@openwrt.org>
+ *
+ * based on coyote-setup.c:
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
+ *
+ * Author: Imre Kaloz <kaloz@openwrt.org>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+#include <linux/serial_8250.h>
+#include <linux/slab.h>
+
+#include <asm/types.h>
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+
+static struct flash_platform_data wg302v2_flash_data = {
+ .map_name = "cfi_probe",
+ .width = 2,
+};
+
+static struct resource wg302v2_flash_resource = {
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device wg302v2_flash = {
+ .name = "IXP4XX-Flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &wg302v2_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &wg302v2_flash_resource,
+};
+
+static struct resource wg302v2_uart_resource = {
+ .start = IXP4XX_UART2_BASE_PHYS,
+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port wg302v2_uart_data[] = {
+ {
+ .mapbase = IXP4XX_UART2_BASE_PHYS,
+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+ .irq = IRQ_IXP4XX_UART2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ .uartclk = IXP4XX_UART_XTAL,
+ },
+ { },
+};
+
+static struct platform_device wg302v2_uart = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = wg302v2_uart_data,
+ },
+ .num_resources = 1,
+ .resource = &wg302v2_uart_resource,
+};
+
+static struct platform_device *wg302v2_devices[] __initdata = {
+ &wg302v2_flash,
+ &wg302v2_uart,
+};
+
+static void __init wg302v2_init(void)
+{
+ ixp4xx_sys_init();
+
+ wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+ wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1;
+
+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
+ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+ platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices));
+}
+
+#ifdef CONFIG_MACH_WG302V2
+MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2")
+ /* Maintainer: Imre Kaloz <kaloz@openwrt.org> */
+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
+ .map_io = ixp4xx_map_io,
+ .init_irq = ixp4xx_init_irq,
+ .timer = &ixp4xx_timer,
+ .boot_params = 0x0100,
+ .init_machine = wg302v2_init,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
index 56b7d337333..2a07a281fa8 100644
--- a/arch/arm/mach-ks8695/Makefile
+++ b/arch/arm/mach-ks8695/Makefile
@@ -3,7 +3,7 @@
# Makefile for KS8695 architecture support
#
-obj-y := cpu.o irq.o time.o devices.o
+obj-y := cpu.o irq.o time.o gpio.o devices.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c
new file mode 100644
index 00000000000..b1aa3cb3d4a
--- /dev/null
+++ b/arch/arm/mach-ks8695/gpio.c
@@ -0,0 +1,218 @@
+/*
+ * arch/arm/mach-ks8695/gpio.c
+ *
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/gpio.h>
+
+/*
+ * Configure a GPIO line for either GPIO function, or its internal
+ * function (Interrupt, Timer, etc).
+ */
+static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio)
+{
+ unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
+ unsigned long x, flags;
+
+ if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */
+ return;
+
+ local_irq_save(flags);
+
+ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
+ if (gpio) /* GPIO: set bit to 0 */
+ x &= ~enable[pin];
+ else /* Internal function: set bit to 1 */
+ x |= enable[pin];
+ __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
+
+ local_irq_restore(flags);
+}
+
+
+static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
+{
+ unsigned long x, flags;
+
+ if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ /* set pin as input */
+ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+ x &= ~IOPM_(pin);
+ __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+ local_irq_restore(flags);
+
+ /* Set IRQ triggering type */
+ set_irq_type(gpio_irq[pin], type);
+
+ /* enable interrupt mode */
+ ks8695_gpio_mode(pin, 0);
+
+ return 0;
+}
+EXPORT_SYMBOL(ks8695_gpio_interrupt);
+
+
+
+/* .... Generic GPIO interface .............................................. */
+
+/*
+ * Configure the GPIO line as an input.
+ */
+int __init_or_module gpio_direction_input(unsigned int pin)
+{
+ unsigned long x, flags;
+
+ if (pin > KS8695_GPIO_15)
+ return -EINVAL;
+
+ /* set pin to GPIO mode */
+ ks8695_gpio_mode(pin, 1);
+
+ local_irq_save(flags);
+
+ /* set pin as input */
+ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+ x &= ~IOPM_(pin);
+ __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state)
+{
+ unsigned long x, flags;
+
+ if (pin > KS8695_GPIO_15)
+ return -EINVAL;
+
+ /* set pin to GPIO mode */
+ ks8695_gpio_mode(pin, 1);
+
+ local_irq_save(flags);
+
+ /* set line state */
+ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+ if (state)
+ x |= (1 << pin);
+ else
+ x &= ~(1 << pin);
+ __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+ /* set pin as output */
+ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
+ x |= IOPM_(pin);
+ __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+
+/*
+ * Set the state of an output GPIO line.
+ */
+void gpio_set_value(unsigned int pin, unsigned int state)
+{
+ unsigned long x, flags;
+
+ if (pin > KS8695_GPIO_15)
+ return;
+
+ local_irq_save(flags);
+
+ /* set output line state */
+ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+ if (state)
+ x |= (1 << pin);
+ else
+ x &= ~(1 << pin);
+ __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+
+/*
+ * Read the state of a GPIO line.
+ */
+int gpio_get_value(unsigned int pin)
+{
+ unsigned long x;
+
+ if (pin > KS8695_GPIO_15)
+ return -EINVAL;
+
+ x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
+ return (x & (1 << pin)) != 0;
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+int gpio_to_irq(unsigned int pin)
+{
+ if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
+ return -EINVAL;
+
+ return gpio_irq[pin];
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq)
+{
+ if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3))
+ return -EINVAL;
+
+ return (irq - KS8695_IRQ_EXTERN0);
+}
+EXPORT_SYMBOL(irq_to_gpio);
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 8f7c90a0593..34a31caa6f9 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -12,7 +12,6 @@
#include <asm/arch/pxa-regs.h>
#include <asm/hardware.h>
-#include <asm/semaphore.h>
struct clk {
struct list_head node;
@@ -25,21 +24,21 @@ struct clk {
};
static LIST_HEAD(clocks);
-static DECLARE_MUTEX(clocks_sem);
+static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clocks_lock);
struct clk *clk_get(struct device *dev, const char *id)
{
struct clk *p, *clk = ERR_PTR(-ENOENT);
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_for_each_entry(p, &clocks, node) {
if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
clk = p;
break;
}
}
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return clk;
}
@@ -101,18 +100,18 @@ static struct clk clk_gpio27 = {
int clk_register(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
return 0;
}
EXPORT_SYMBOL(clk_register);
void clk_unregister(struct clk *clk)
{
- down(&clocks_sem);
+ mutex_lock(&clocks_mutex);
list_del(&clk->node);
- up(&clocks_sem);
+ mutex_unlock(&clocks_mutex);
}
EXPORT_SYMBOL(clk_unregister);
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index a1a900d1666..aab27297b3c 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -44,6 +44,7 @@
#include <asm/hardware/scoop.h>
#include "generic.h"
+#include "devices.h"
#include "sharpsl.h"
@@ -368,7 +369,7 @@ MACHINE_START(CORGI, "SHARP Corgi")
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
.map_io = pxa_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa25x_init_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
@@ -380,7 +381,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd")
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
.map_io = pxa_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa25x_init_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
@@ -392,7 +393,7 @@ MACHINE_START(HUSKY, "SHARP Husky")
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_corgi,
.map_io = pxa_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa25x_init_irq,
.init_machine = corgi_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
new file mode 100644
index 00000000000..9a6faff8e5a
--- /dev/null
+++ b/arch/arm/mach-pxa/devices.h
@@ -0,0 +1,11 @@
+extern struct platform_device pxamci_device;
+extern struct platform_device pxaudc_device;
+extern struct platform_device pxafb_device;
+extern struct platform_device ffuart_device;
+extern struct platform_device btuart_device;
+extern struct platform_device stuart_device;
+extern struct platform_device hwuart_device;
+extern struct platform_device pxai2c_device;
+extern struct platform_device pxai2s_device;
+extern struct platform_device pxaficp_device;
+extern struct platform_device pxartc_device;
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 4440babe7b9..93c4f31f127 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -25,12 +25,15 @@
#include <asm/arch/pxa-regs.h>
-static struct dma_channel {
+struct dma_channel {
char *name;
+ pxa_dma_prio prio;
void (*irq_handler)(int, void *);
void *data;
-} dma_channels[PXA_DMA_CHANNELS];
+};
+static struct dma_channel *dma_channels;
+static int num_dma_channels;
int pxa_request_dma (char *name, pxa_dma_prio prio,
void (*irq_handler)(int, void *),
@@ -47,8 +50,9 @@ int pxa_request_dma (char *name, pxa_dma_prio prio,
do {
/* try grabbing a DMA channel with the requested priority */
- pxa_for_each_dma_prio (i, prio) {
- if (!dma_channels[i].name) {
+ for (i = 0; i < num_dma_channels; i++) {
+ if ((dma_channels[i].prio == prio) &&
+ !dma_channels[i].name) {
found = 1;
break;
}
@@ -91,7 +95,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
{
int i, dint = DINT;
- for (i = 0; i < PXA_DMA_CHANNELS; i++) {
+ for (i = 0; i < num_dma_channels; i++) {
if (dint & (1 << i)) {
struct dma_channel *channel = &dma_channels[i];
if (channel->name && channel->irq_handler) {
@@ -109,18 +113,32 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __init pxa_dma_init (void)
+int __init pxa_init_dma(int num_ch)
{
- int ret;
+ int i, ret;
- ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
- if (ret)
+ dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);
+ if (dma_channels == NULL)
+ return -ENOMEM;
+
+ ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);
+ if (ret) {
printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n");
- return ret;
-}
+ kfree(dma_channels);
+ return ret;
+ }
-arch_initcall(pxa_dma_init);
+ /* dma channel priorities on pxa2xx processors:
+ * ch 0 - 3, 16 - 19 <--> (0) DMA_PRIO_HIGH
+ * ch 4 - 7, 20 - 23 <--> (1) DMA_PRIO_MEDIUM
+ * ch 8 - 15, 24 - 31 <--> (2) DMA_PRIO_LOW
+ */
+ for (i = 0; i < num_ch; i++)
+ dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);
+
+ num_dma_channels = num_ch;
+ return 0;
+}
EXPORT_SYMBOL(pxa_request_dma);
EXPORT_SYMBOL(pxa_free_dma);
-
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 64b08b744f9..296539b6359 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -43,6 +43,7 @@
#include <asm/arch/irda.h>
#include <asm/arch/i2c.h>
+#include "devices.h"
#include "generic.h"
/*
@@ -242,7 +243,7 @@ static struct resource pxamci_resources[] = {
static u64 pxamci_dmamask = 0xffffffffUL;
-static struct platform_device pxamci_device = {
+struct platform_device pxamci_device = {
.name = "pxa2xx-mci",
.id = -1,
.dev = {
@@ -281,7 +282,7 @@ static struct resource pxa2xx_udc_resources[] = {
static u64 udc_dma_mask = ~(u32)0;
-static struct platform_device udc_device = {
+struct platform_device pxaudc_device = {
.name = "pxa2xx-udc",
.id = -1,
.resource = pxa2xx_udc_resources,
@@ -307,7 +308,7 @@ static struct resource pxafb_resources[] = {
static u64 fb_dma_mask = ~(u64)0;
-static struct platform_device pxafb_device = {
+struct platform_device pxafb_device = {
.name = "pxa2xx-fb",
.id = -1,
.dev = {
@@ -328,24 +329,24 @@ void __init set_pxa_fb_parent(struct device *parent_dev)
pxafb_device.dev.parent = parent_dev;
}
-static struct platform_device ffuart_device = {
+struct platform_device ffuart_device = {
.name = "pxa2xx-uart",
.id = 0,
};
-static struct platform_device btuart_device = {
+struct platform_device btuart_device = {
.name = "pxa2xx-uart",
.id = 1,
};
-static struct platform_device stuart_device = {
+struct platform_device stuart_device = {
.name = "pxa2xx-uart",
.id = 2,
};
-static struct platform_device hwuart_device = {
+struct platform_device hwuart_device = {
.name = "pxa2xx-uart",
.id = 3,
};
-static struct resource i2c_resources[] = {
+static struct resource pxai2c_resources[] = {
{
.start = 0x40301680,
.end = 0x403016a3,
@@ -357,40 +358,19 @@ static struct resource i2c_resources[] = {
},
};
-static struct platform_device i2c_device = {
+struct platform_device pxai2c_device = {
.name = "pxa2xx-i2c",
.id = 0,
- .resource = i2c_resources,
- .num_resources = ARRAY_SIZE(i2c_resources),
+ .resource = pxai2c_resources,
+ .num_resources = ARRAY_SIZE(pxai2c_resources),
};
-#ifdef CONFIG_PXA27x
-static struct resource i2c_power_resources[] = {
- {
- .start = 0x40f00180,
- .end = 0x40f001a3,
- .flags = IORESOURCE_MEM,
- }, {
- .start = IRQ_PWRI2C,
- .end = IRQ_PWRI2C,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device i2c_power_device = {
- .name = "pxa2xx-i2c",
- .id = 1,
- .resource = i2c_power_resources,
- .num_resources = ARRAY_SIZE(i2c_resources),
-};
-#endif
-
void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
{
- i2c_device.dev.platform_data = info;
+ pxai2c_device.dev.platform_data = info;
}
-static struct resource i2s_resources[] = {
+static struct resource pxai2s_resources[] = {
{
.start = 0x40400000,
.end = 0x40400083,
@@ -402,16 +382,16 @@ static struct resource i2s_resources[] = {
},
};
-static struct platform_device i2s_device = {
+struct platform_device pxai2s_device = {
.name = "pxa2xx-i2s",
.id = -1,
- .resource = i2s_resources,
- .num_resources = ARRAY_SIZE(i2s_resources),
+ .resource = pxai2s_resources,
+ .num_resources = ARRAY_SIZE(pxai2s_resources),
};
static u64 pxaficp_dmamask = ~(u32)0;
-static struct platform_device pxaficp_device = {
+struct platform_device pxaficp_device = {
.name = "pxa2xx-ir",
.id = -1,
.dev = {
@@ -425,42 +405,7 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
pxaficp_device.dev.platform_data = info;
}
-static struct platform_device pxartc_device = {
+struct platform_device pxartc_device = {
.name = "sa1100-rtc",
.id = -1,
};
-
-static struct platform_device *devices[] __initdata = {
- &pxamci_device,
- &udc_device,
- &pxafb_device,
- &ffuart_device,
- &btuart_device,
- &stuart_device,
- &pxaficp_device,
- &i2c_device,
-#ifdef CONFIG_PXA27x
- &i2c_power_device,
-#endif
- &i2s_device,
- &pxartc_device,
-};
-
-static int __init pxa_init(void)
-{
- int cpuid, ret;
-
- ret = platform_add_devices(devices, ARRAY_SIZE(devices));
- if (ret)
- return ret;
-
- /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
- cpuid = read_cpuid(CPUID_ID);
- if (((cpuid >> 4) & 0xfff) == 0x2d0 ||
- ((cpuid >> 4) & 0xfff) == 0x290)
- ret = platform_device_register(&hwuart_device);
-
- return ret;
-}
-
-subsys_initcall(pxa_init);
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index e54a8dd63c1..91ab2ad8b34 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -12,8 +12,12 @@
struct sys_timer;
extern struct sys_timer pxa_timer;
+extern void __init pxa_init_irq_low(void);
+extern void __init pxa_init_irq_high(void);
+extern void __init pxa_init_irq_gpio(int gpio_nr);
+extern void __init pxa25x_init_irq(void);
+extern void __init pxa27x_init_irq(void);
extern void __init pxa_map_io(void);
-extern void __init pxa_init_irq(void);
extern unsigned int get_clk_frequency_khz(int info);
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 64df44043a6..465108da285 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -38,6 +38,7 @@
#include <asm/arch/mmc.h>
#include "generic.h"
+#include "devices.h"
/* TODO:
* - add pxa2xx_audio_ops_t device structure
@@ -152,7 +153,7 @@ static void __init idp_init(void)
static void __init idp_init_irq(void)
{
- pxa_init_irq();
+ pxa25x_init_irq();
set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
}
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 4619d5fe606..4b867b0789d 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -30,12 +30,12 @@
static void pxa_mask_low_irq(unsigned int irq)
{
- ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
+ ICMR &= ~(1 << irq);
}
static void pxa_unmask_low_irq(unsigned int irq)
{
- ICMR |= (1 << (irq + PXA_IRQ_SKIP));
+ ICMR |= (1 << irq);
}
static int pxa_set_wake(unsigned int irq, unsigned int on)
@@ -67,7 +67,27 @@ static struct irq_chip pxa_internal_chip_low = {
.set_wake = pxa_set_wake,
};
-#if PXA_INTERNAL_IRQS > 32
+void __init pxa_init_irq_low(void)
+{
+ int irq;
+
+ /* disable all IRQs */
+ ICMR = 0;
+
+ /* all IRQs are IRQ, not FIQ */
+ ICLR = 0;
+
+ /* only unmasked interrupts kick us out of idle */
+ ICCR = 1;
+
+ for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) {
+ set_irq_chip(irq, &pxa_internal_chip_low);
+ set_irq_handler(irq, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+}
+
+#ifdef CONFIG_PXA27x
/*
* This is for the second set of internal IRQs as found on the PXA27x.
@@ -75,12 +95,12 @@ static struct irq_chip pxa_internal_chip_low = {
static void pxa_mask_high_irq(unsigned int irq)
{
- ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
+ ICMR2 &= ~(1 << (irq - 32));
}
static void pxa_unmask_high_irq(unsigned int irq)
{
- ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
+ ICMR2 |= (1 << (irq - 32));
}
static struct irq_chip pxa_internal_chip_high = {
@@ -90,6 +110,19 @@ static struct irq_chip pxa_internal_chip_high = {
.unmask = pxa_unmask_high_irq,
};
+void __init pxa_init_irq_high(void)
+{
+ int irq;
+
+ ICMR2 = 0;
+ ICLR2 = 0;
+
+ for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) {
+ set_irq_chip(irq, &pxa_internal_chip_high);
+ set_irq_handler(irq, handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+}
#endif
/* Note that if an input/irq line ever gets changed to an output during
@@ -217,7 +250,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
do {
loop = 0;
- mask = GEDR0 & ~3;
+ mask = GEDR0 & GPIO_IRQ_mask[0] & ~3;
if (mask) {
GEDR0 = mask;
irq = IRQ_GPIO(2);
@@ -233,7 +266,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
loop = 1;
}
- mask = GEDR1;
+ mask = GEDR1 & GPIO_IRQ_mask[1];
if (mask) {
GEDR1 = mask;
irq = IRQ_GPIO(32);
@@ -248,7 +281,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
loop = 1;
}
- mask = GEDR2;
+ mask = GEDR2 & GPIO_IRQ_mask[2];
if (mask) {
GEDR2 = mask;
irq = IRQ_GPIO(64);
@@ -263,8 +296,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
loop = 1;
}
-#if PXA_LAST_GPIO >= 96
- mask = GEDR3;
+ mask = GEDR3 & GPIO_IRQ_mask[3];
if (mask) {
GEDR3 = mask;
irq = IRQ_GPIO(96);
@@ -278,7 +310,6 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
} while (mask);
loop = 1;
}
-#endif
} while (loop);
}
@@ -314,64 +345,27 @@ static struct irq_chip pxa_muxed_gpio_chip = {
.set_wake = pxa_set_gpio_wake,
};
-
-void __init pxa_init_irq(void)
+void __init pxa_init_irq_gpio(int gpio_nr)
{
- int irq;
-
- /* disable all IRQs */
- ICMR = 0;
-
- /* all IRQs are IRQ, not FIQ */
- ICLR = 0;
+ int irq, i;
/* clear all GPIO edge detects */
- GFER0 = 0;
- GFER1 = 0;
- GFER2 = 0;
- GRER0 = 0;
- GRER1 = 0;
- GRER2 = 0;
- GEDR0 = GEDR0;
- GEDR1 = GEDR1;
- GEDR2 = GEDR2;
-
-#ifdef CONFIG_PXA27x
- /* And similarly for the extra regs on the PXA27x */
- ICMR2 = 0;
- ICLR2 = 0;
- GFER3 = 0;
- GRER3 = 0;
- GEDR3 = GEDR3;
-#endif
-
- /* only unmasked interrupts kick us out of idle */
- ICCR = 1;
+ for (i = 0; i < gpio_nr; i += 32) {
+ GFER(i) = 0;
+ GRER(i) = 0;
+ GEDR(i) = GEDR(i);
+ }
/* GPIO 0 and 1 must have their mask bit always set */
GPIO_IRQ_mask[0] = 3;
- for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
- set_irq_chip(irq, &pxa_internal_chip_low);
- set_irq_handler(irq, handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-
-#if PXA_INTERNAL_IRQS > 32
- for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
- set_irq_chip(irq, &pxa_internal_chip_high);
- set_irq_handler(irq, handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-#endif
-
for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
set_irq_chip(irq, &pxa_low_gpio_chip);
set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
- for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
+ for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(gpio_nr); irq++) {
set_irq_chip(irq, &pxa_muxed_gpio_chip);
set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index e3097664ffe..26116440a7c 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -46,6 +46,7 @@
#include <asm/arch/ohci.h>
#include "generic.h"
+#include "devices.h"
static unsigned int lpd270_irq_enabled;
@@ -97,7 +98,7 @@ static void __init lpd270_init_irq(void)
{
int irq;
- pxa_init_irq();
+ pxa27x_init_irq();
__raw_writew(0, LPD270_INT_MASK);
__raw_writew(0, LPD270_INT_STATUS);
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 6377b2e29ff..e70048fd00a 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -48,6 +48,7 @@
#include <asm/arch/mmc.h>
#include "generic.h"
+#include "devices.h"
#define LUB_MISC_WR __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080)
@@ -103,7 +104,7 @@ static void __init lubbock_init_irq(void)
{
int irq;
- pxa_init_irq();
+ pxa25x_init_irq();
/* setup extra lubbock irqs */
for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index ed99a81b98f..b02c79c7e6a 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -46,6 +46,7 @@
#include <asm/arch/ohci.h>
#include "generic.h"
+#include "devices.h"
static unsigned long mainstone_irq_enabled;
@@ -89,7 +90,7 @@ static void __init mainstone_init_irq(void)
{
int irq;
- pxa_init_irq();
+ pxa27x_init_irq();
/* setup extra Mainstone irqs */
for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 6bf15ae7384..e66dbc26add 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -77,7 +77,6 @@ int pxa_pm_enter(suspend_state_t state)
{
unsigned long sleep_save[SLEEP_SAVE_SIZE];
unsigned long checksum = 0;
- struct timespec delta, rtc;
int i;
extern void pxa_cpu_pm_enter(suspend_state_t state);
@@ -87,11 +86,6 @@ int pxa_pm_enter(suspend_state_t state)
iwmmxt_task_disable(NULL);
#endif
- /* preserve current time */
- rtc.tv_sec = RCNR;
- rtc.tv_nsec = 0;
- save_time_delta(&delta, &rtc);
-
SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
@@ -183,10 +177,6 @@ int pxa_pm_enter(suspend_state_t state)
RESTORE(PSTR);
- /* restore current time */
- rtc.tv_sec = RCNR;
- restore_time_delta(&delta, &rtc);
-
#ifdef DEBUG
printk(KERN_DEBUG "*** made it back from resume\n");
#endif
@@ -200,40 +190,3 @@ unsigned long sleep_phys_sp(void *sp)
{
return virt_to_phys(sp);
}
-
-/*
- * Called after processes are frozen, but before we shut down devices.
- */
-int pxa_pm_prepare(suspend_state_t state)
-{
- extern int pxa_cpu_pm_prepare(suspend_state_t state);
-
- return pxa_cpu_pm_prepare(state);
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_prepare);
-
-/*
- * Called after devices are re-setup, but before processes are thawed.
- */
-int pxa_pm_finish(suspend_state_t state)
-{
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(pxa_pm_finish);
-
-static struct pm_ops pxa_pm_ops = {
- .prepare = pxa_pm_prepare,
- .enter = pxa_pm_enter,
- .finish = pxa_pm_finish,
- .valid = pm_valid_only_mem,
-};
-
-static int __init pxa_pm_init(void)
-{
- pm_set_ops(&pxa_pm_ops);
- return 0;
-}
-
-device_initcall(pxa_pm_init);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 34fb80b3702..655668d4d0e 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -45,6 +45,7 @@
#include <asm/mach/sharpsl_param.h>
#include "generic.h"
+#include "devices.h"
#include "sharpsl.h"
static struct resource poodle_scoop_resources[] = {
@@ -412,7 +413,7 @@ MACHINE_START(POODLE, "SHARP Poodle")
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_poodle,
.map_io = pxa_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa25x_init_irq,
.timer = &pxa_timer,
.init_machine = poodle_init,
MACHINE_END
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index c1f21739bf7..f36ca448338 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -19,12 +19,17 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/platform_device.h>
#include <linux/pm.h>
#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
#include <asm/arch/pxa-regs.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
#include "generic.h"
+#include "devices.h"
/*
* Various clock factors driven by the CCCR register.
@@ -105,18 +110,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
#ifdef CONFIG_PM
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
- switch (state) {
- case PM_SUSPEND_MEM:
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
void pxa_cpu_pm_enter(suspend_state_t state)
{
extern void pxa_cpu_suspend(unsigned int);
@@ -133,4 +126,49 @@ void pxa_cpu_pm_enter(suspend_state_t state)
}
}
+static struct pm_ops pxa25x_pm_ops = {
+ .enter = pxa_pm_enter,
+ .valid = pm_valid_only_mem,
+};
+#endif
+
+void __init pxa25x_init_irq(void)
+{
+ pxa_init_irq_low();
+ pxa_init_irq_gpio(85);
+}
+
+static struct platform_device *pxa25x_devices[] __initdata = {
+ &pxamci_device,
+ &pxaudc_device,
+ &pxafb_device,
+ &ffuart_device,
+ &btuart_device,
+ &stuart_device,
+ &pxai2c_device,
+ &pxai2s_device,
+ &pxaficp_device,
+ &pxartc_device,
+};
+
+static int __init pxa25x_init(void)
+{
+ int ret = 0;
+
+ if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
+ if ((ret = pxa_init_dma(16)))
+ return ret;
+#ifdef CONFIG_PM
+ pm_set_ops(&pxa25x_pm_ops);
#endif
+ ret = platform_add_devices(pxa25x_devices,
+ ARRAY_SIZE(pxa25x_devices));
+ }
+ /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
+ if (cpu_is_pxa25x())
+ ret = platform_device_register(&hwuart_device);
+
+ return ret;
+}
+
+subsys_initcall(pxa25x_init);
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index c64bab49efc..aa5bb02c897 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -19,10 +19,14 @@
#include <asm/hardware.h>
#include <asm/irq.h>
+#include <asm/arch/irqs.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/ohci.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/dma.h>
#include "generic.h"
+#include "devices.h"
/* Crystal clock: 13MHz */
#define BASE_CLK 13000000
@@ -122,17 +126,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
#ifdef CONFIG_PM
-int pxa_cpu_pm_prepare(suspend_state_t state)
-{
- switch (state) {
- case PM_SUSPEND_MEM:
- case PM_SUSPEND_STANDBY:
- return 0;
- default:
- return -EINVAL;
- }
-}
-
void pxa_cpu_pm_enter(suspend_state_t state)
{
extern void pxa_cpu_standby(void);
@@ -140,9 +133,9 @@ void pxa_cpu_pm_enter(suspend_state_t state)
extern void pxa_cpu_resume(void);
if (state == PM_SUSPEND_STANDBY)
- CKEN = CKEN_MEMC | CKEN_OSTIMER | CKEN_LCD | CKEN_PWM0;
+ CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER) | (1 << CKEN_LCD) | (1 << CKEN_PWM0);
else
- CKEN = CKEN_MEMC | CKEN_OSTIMER;
+ CKEN = (1 << CKEN_MEMC) | (1 << CKEN_OSTIMER);
/* ensure voltage-change sequencer not initiated, which hangs */
PCFR &= ~PCFR_FVC;
@@ -162,6 +155,15 @@ void pxa_cpu_pm_enter(suspend_state_t state)
}
}
+static int pxa27x_pm_valid(suspend_state_t state)
+{
+ return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY;
+}
+
+static struct pm_ops pxa27x_pm_ops = {
+ .enter = pxa_pm_enter,
+ .valid = pxa27x_pm_valid,
+};
#endif
/*
@@ -183,7 +185,7 @@ static struct resource pxa27x_ohci_resources[] = {
},
};
-static struct platform_device ohci_device = {
+static struct platform_device pxaohci_device = {
.name = "pxa27x-ohci",
.id = -1,
.dev = {
@@ -196,16 +198,62 @@ static struct platform_device ohci_device = {
void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
{
- ohci_device.dev.platform_data = info;
+ pxaohci_device.dev.platform_data = info;
}
+static struct resource i2c_power_resources[] = {
+ {
+ .start = 0x40f00180,
+ .end = 0x40f001a3,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_PWRI2C,
+ .end = IRQ_PWRI2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device pxai2c_power_device = {
+ .name = "pxa2xx-i2c",
+ .id = 1,
+ .resource = i2c_power_resources,
+ .num_resources = ARRAY_SIZE(i2c_power_resources),
+};
+
static struct platform_device *devices[] __initdata = {
- &ohci_device,
+ &pxamci_device,
+ &pxaudc_device,
+ &pxafb_device,
+ &ffuart_device,
+ &btuart_device,
+ &stuart_device,
+ &pxai2c_device,
+ &pxai2c_power_device,
+ &pxai2s_device,
+ &pxaficp_device,
+ &pxartc_device,
+ &pxaohci_device,
};
+void __init pxa27x_init_irq(void)
+{
+ pxa_init_irq_low();
+ pxa_init_irq_high();
+ pxa_init_irq_gpio(128);
+}
+
static int __init pxa27x_init(void)
{
- return platform_add_devices(devices, ARRAY_SIZE(devices));
+ int ret = 0;
+ if (cpu_is_pxa27x()) {
+ if ((ret = pxa_init_dma(32)))
+ return ret;
+#ifdef CONFIG_PM
+ pm_set_ops(&pxa27x_pm_ops);
+#endif
+ ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+ }
+ return ret;
}
subsys_initcall(pxa27x_init);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 3cbac63bed3..bae47e145de 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -48,6 +48,7 @@
#include <asm/hardware/scoop.h>
#include "generic.h"
+#include "devices.h"
#include "sharpsl.h"
/*
@@ -560,7 +561,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_spitz,
.map_io = pxa_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa27x_init_irq,
.init_machine = spitz_init,
.timer = &pxa_timer,
MACHINE_END
@@ -572,7 +573,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_spitz,
.map_io = pxa_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa27x_init_irq,
.init_machine = spitz_init,
.timer = &pxa_timer,
MACHINE_END
@@ -584,7 +585,7 @@ MACHINE_START(AKITA, "SHARP Akita")
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_spitz,
.map_io = pxa_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa27x_init_irq,
.init_machine = akita_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 5248abe334d..6f91fd2d061 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -30,11 +30,6 @@
#include <asm/arch/pxa-regs.h>
-static inline unsigned long pxa_get_rtc_time(void)
-{
- return RCNR;
-}
-
static int pxa_set_rtc(void)
{
unsigned long current_time = xtime.tv_sec;
@@ -122,10 +117,6 @@ static void __init pxa_timer_init(void)
set_rtc = pxa_set_rtc;
- tv.tv_nsec = 0;
- tv.tv_sec = pxa_get_rtc_time();
- do_settimeofday(&tv);
-
OIER = 0; /* disable any timer interrupts */
OSSR = 0xf; /* clear status on all timers */
setup_irq(IRQ_OST0, &pxa_timer_irq);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 72738771fb5..240fd042083 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -42,7 +42,7 @@
#include <asm/mach/sharpsl_param.h>
#include "generic.h"
-
+#include "devices.h"
/*
* SCOOP Device
@@ -332,7 +332,7 @@ MACHINE_START(TOSA, "SHARP Tosa")
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
.fixup = fixup_tosa,
.map_io = pxa_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa25x_init_irq,
.init_machine = tosa_init,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 28c79bd0a3a..e4ba43bdf85 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -49,6 +49,7 @@
#include <asm/arch/ohci.h>
#include "generic.h"
+#include "devices.h"
/********************************************************************************************
* ONBOARD FLASH
@@ -503,7 +504,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
.boot_params = TRIZEPS4_SDRAM_BASE + 0x100,
.init_machine = trizeps4_init,
.map_io = trizeps4_map_io,
- .init_irq = pxa_init_irq,
+ .init_irq = pxa27x_init_irq,
.timer = &pxa_timer,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index f01de807b72..8b52ea95d4f 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -20,6 +20,8 @@
#include <linux/platform_device.h>
#include <linux/dm9000.h>
+#include <net/ax88796.h>
+
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
@@ -409,6 +411,61 @@ static struct s3c2410_platform_i2c bast_i2c_info = {
.max_freq = 130*1000,
};
+/* Asix AX88796 10/100 ethernet controller */
+
+static struct ax_plat_data bast_asix_platdata = {
+ .flags = AXFLG_MAC_FROMDEV,
+ .wordlength = 2,
+ .dcr_val = 0x48,
+ .rcr_val = 0x40,
+};
+
+static struct resource bast_asix_resource[] = {
+ [0] = {
+ .start = S3C2410_CS5 + BAST_PA_ASIXNET,
+ .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20) - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
+ .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20),
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = IRQ_ASIX,
+ .end = IRQ_ASIX,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device bast_device_asix = {
+ .name = "ax88796",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bast_asix_resource),
+ .resource = bast_asix_resource,
+ .dev = {
+ .platform_data = &bast_asix_platdata
+ }
+};
+
+/* Asix AX88796 10/100 ethernet controller parallel port */
+
+static struct resource bast_asixpp_resource[] = {
+ [0] = {
+ .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20),
+ .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1b * 0x20) - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device bast_device_axpp = {
+ .name = "ax88796-pp",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bast_asixpp_resource),
+ .resource = bast_asixpp_resource,
+};
+
+/* LCD/VGA controller */
static struct s3c2410fb_mach_info __initdata bast_lcd_info = {
.width = 640,
@@ -453,6 +510,8 @@ static struct platform_device *bast_devices[] __initdata = {
&s3c_device_nand,
&bast_device_nor,
&bast_device_dm9k,
+ &bast_device_asix,
+ &bast_device_axpp,
&bast_sio,
};
diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c
index b5d387ef37e..29c163d300d 100644
--- a/arch/arm/mach-s3c2440/mach-anubis.c
+++ b/arch/arm/mach-s3c2440/mach-anubis.c
@@ -18,6 +18,9 @@
#include <linux/serial_core.h>
#include <linux/platform_device.h>
+#include <linux/sm501.h>
+#include <linux/sm501-regs.h>
+
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
@@ -42,6 +45,8 @@
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
+#include <net/ax88796.h>
+
#include <asm/plat-s3c24xx/clock.h>
#include <asm/plat-s3c24xx/devs.h>
#include <asm/plat-s3c24xx/cpu.h>
@@ -76,8 +81,8 @@ static struct map_desc anubis_iodesc[] __initdata = {
.length = SZ_4K,
.type = MT_DEVICE,
}, {
- .virtual = (u32)ANUBIS_VA_CTRL2,
- .pfn = __phys_to_pfn(ANUBIS_PA_CTRL2),
+ .virtual = (u32)ANUBIS_VA_IDREG,
+ .pfn = __phys_to_pfn(ANUBIS_PA_IDREG),
.length = SZ_4K,
.type = MT_DEVICE,
},
@@ -153,6 +158,29 @@ static struct mtd_partition anubis_default_nand_part[] = {
}
};
+static struct mtd_partition anubis_default_nand_part_large[] = {
+ [0] = {
+ .name = "Boot Agent",
+ .size = SZ_128K,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "/boot",
+ .size = SZ_4M - SZ_128K,
+ .offset = SZ_128K,
+ },
+ [2] = {
+ .name = "user1",
+ .offset = SZ_4M,
+ .size = SZ_32M - SZ_4M,
+ },
+ [3] = {
+ .name = "user2",
+ .offset = SZ_32M,
+ .size = MTDPART_SIZ_FULL,
+ }
+};
+
/* the Anubis has 3 selectable slots for nand-flash, the two
* on-board chip areas, as well as the external slot.
*
@@ -260,6 +288,104 @@ static struct platform_device anubis_device_ide1 = {
.resource = anubis_ide1_resource,
};
+/* Asix AX88796 10/100 ethernet controller */
+
+static struct ax_plat_data anubis_asix_platdata = {
+ .flags = AXFLG_MAC_FROMDEV,
+ .wordlength = 2,
+ .dcr_val = 0x48,
+ .rcr_val = 0x40,
+};
+
+static struct resource anubis_asix_resource[] = {
+ [0] = {
+ .start = S3C2410_CS5,
+ .end = S3C2410_CS5 + (0x20 * 0x20) -1,
+ .flags = IORESOURCE_MEM
+ },
+ [1] = {
+ .start = IRQ_ASIX,
+ .end = IRQ_ASIX,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device anubis_device_asix = {
+ .name = "ax88796",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(anubis_asix_resource),
+ .resource = anubis_asix_resource,
+ .dev = {
+ .platform_data = &anubis_asix_platdata,
+ }
+};
+
+/* SM501 */
+
+static struct resource anubis_sm501_resource[] = {
+ [0] = {
+ .start = S3C2410_CS2,
+ .end = S3C2410_CS2 + SZ_8M,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = S3C2410_CS2 + SZ_64M - SZ_2M,
+ .end = S3C2410_CS2 + SZ_64M - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = IRQ_EINT0,
+ .end = IRQ_EINT0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct sm501_initdata anubis_sm501_initdata = {
+ .gpio_high = {
+ .set = 0x3F000000, /* 24bit panel */
+ .mask = 0x0,
+ },
+ .misc_timing = {
+ .set = 0x010100, /* SDRAM timing */
+ .mask = 0x1F1F00,
+ },
+ .misc_control = {
+ .set = SM501_MISC_PNL_24BIT,
+ .mask = 0,
+ },
+
+ /* set the SDRAM and bus clocks */
+ .mclk = 72 * MHZ,
+ .m1xclk = 144 * MHZ,
+};
+
+static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = {
+ [0] = {
+ .pin_scl = 44,
+ .pin_sda = 45,
+ },
+ [1] = {
+ .pin_scl = 40,
+ .pin_sda = 41,
+ },
+};
+
+static struct sm501_platdata anubis_sm501_platdata = {
+ .init = &anubis_sm501_initdata,
+ .gpio_i2c = anubis_sm501_gpio_i2c,
+ .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c),
+};
+
+static struct platform_device anubis_device_sm501 = {
+ .name = "sm501",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(anubis_sm501_resource),
+ .resource = anubis_sm501_resource,
+ .dev = {
+ .platform_data = &anubis_sm501_platdata,
+ },
+};
+
/* Standard Anubis devices */
static struct platform_device *anubis_devices[] __initdata = {
@@ -271,6 +397,8 @@ static struct platform_device *anubis_devices[] __initdata = {
&s3c_device_nand,
&anubis_device_ide0,
&anubis_device_ide1,
+ &anubis_device_asix,
+ &anubis_device_sm501,
};
static struct clk *anubis_clocks[] = {
@@ -304,8 +432,17 @@ static void __init anubis_map_io(void)
s3c24xx_init_clocks(0);
s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
- /* ensure that the GPIO is setup */
- s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+ /* check for the newer revision boards with large page nand */
+
+ if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) {
+ printk(KERN_INFO "ANUBIS-B detected (revision %d)\n",
+ __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK);
+ anubis_nand_sets[0].partitions = anubis_default_nand_part_large;
+ anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
+ } else {
+ /* ensure that the GPIO is setup */
+ s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+ }
}
static void __init anubis_init(void)
diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c
index 4d6c7a574c1..89f4c9c5777 100644
--- a/arch/arm/mach-s3c2440/mach-osiris.c
+++ b/arch/arm/mach-s3c2440/mach-osiris.c
@@ -16,6 +16,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/sysdev.h>
#include <linux/serial_core.h>
#include <asm/mach/arch.h>
@@ -65,6 +66,11 @@ static struct map_desc osiris_iodesc[] __initdata = {
/* CPLD control registers */
{
+ .virtual = (u32)OSIRIS_VA_CTRL0,
+ .pfn = __phys_to_pfn(OSIRIS_PA_CTRL0),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
+ }, {
.virtual = (u32)OSIRIS_VA_CTRL1,
.pfn = __phys_to_pfn(OSIRIS_PA_CTRL1),
.length = SZ_16K,
@@ -74,6 +80,11 @@ static struct map_desc osiris_iodesc[] __initdata = {
.pfn = __phys_to_pfn(OSIRIS_PA_CTRL2),
.length = SZ_16K,
.type = MT_DEVICE,
+ }, {
+ .virtual = (u32)OSIRIS_VA_IDREG,
+ .pfn = __phys_to_pfn(OSIRIS_PA_IDREG),
+ .length = SZ_16K,
+ .type = MT_DEVICE,
},
};
@@ -155,6 +166,29 @@ static struct mtd_partition osiris_default_nand_part[] = {
}
};
+static struct mtd_partition osiris_default_nand_part_large[] = {
+ [0] = {
+ .name = "Boot Agent",
+ .size = SZ_128K,
+ .offset = 0,
+ },
+ [1] = {
+ .name = "/boot",
+ .size = SZ_4M - SZ_128K,
+ .offset = SZ_128K,
+ },
+ [2] = {
+ .name = "user1",
+ .offset = SZ_4M,
+ .size = SZ_32M - SZ_4M,
+ },
+ [3] = {
+ .name = "user2",
+ .offset = SZ_32M,
+ .size = MTDPART_SIZ_FULL,
+ }
+};
+
/* the Osiris has 3 selectable slots for nand-flash, the two
* on-board chip areas, as well as the external slot.
*
@@ -195,13 +229,13 @@ static void osiris_nand_select(struct s3c2410_nand_set *set, int slot)
pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n",
slot, set, set->nr_map);
- tmp = __raw_readb(OSIRIS_VA_CTRL1);
- tmp &= ~OSIRIS_CTRL1_NANDSEL;
+ tmp = __raw_readb(OSIRIS_VA_CTRL0);
+ tmp &= ~OSIRIS_CTRL0_NANDSEL;
tmp |= slot;
- pr_debug("osiris_nand: ctrl1 now %02x\n", tmp);
+ pr_debug("osiris_nand: ctrl0 now %02x\n", tmp);
- __raw_writeb(tmp, OSIRIS_VA_CTRL1);
+ __raw_writeb(tmp, OSIRIS_VA_CTRL0);
}
static struct s3c2410_platform_nand osiris_nand_info = {
@@ -235,10 +269,45 @@ static struct platform_device osiris_pcmcia = {
.resource = osiris_pcmcia_resource,
};
+/* Osiris power management device */
+
+#ifdef CONFIG_PM
+static unsigned char pm_osiris_ctrl0;
+
+static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state)
+{
+ pm_osiris_ctrl0 = __raw_readb(OSIRIS_VA_CTRL0);
+ return 0;
+}
+
+static int osiris_pm_resume(struct sys_device *sd)
+{
+ if (pm_osiris_ctrl0 & OSIRIS_CTRL0_FIX8)
+ __raw_writeb(OSIRIS_CTRL1_FIX8, OSIRIS_VA_CTRL1);
+
+ return 0;
+}
+
+#else
+#define osiris_pm_suspend NULL
+#define osiris_pm_resume NULL
+#endif
+
+static struct sysdev_class osiris_pm_sysclass = {
+ set_kset_name("mach-osiris"),
+ .suspend = osiris_pm_suspend,
+ .resume = osiris_pm_resume,
+};
+
+static struct sys_device osiris_pm_sysdev = {
+ .cls = &osiris_pm_sysclass,
+};
+
/* Standard Osiris devices */
static struct platform_device *osiris_devices[] __initdata = {
&s3c_device_i2c,
+ &s3c_device_wdt,
&s3c_device_nand,
&osiris_pcmcia,
};
@@ -276,18 +345,30 @@ static void __init osiris_map_io(void)
s3c24xx_init_clocks(0);
s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
+ /* check for the newer revision boards with large page nand */
+
+ if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) {
+ printk(KERN_INFO "OSIRIS-B detected (revision %d)\n",
+ __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK);
+ osiris_nand_sets[0].partitions = osiris_default_nand_part_large;
+ osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
+ } else {
+ /* write-protect line to the NAND */
+ s3c2410_gpio_setpin(S3C2410_GPA0, 1);
+ }
+
/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
local_irq_save(flags);
__raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON);
local_irq_restore(flags);
-
- /* write-protect line to the NAND */
- s3c2410_gpio_setpin(S3C2410_GPA0, 1);
}
static void __init osiris_init(void)
{
+ sysdev_class_register(&osiris_pm_sysclass);
+ sysdev_register(&osiris_pm_sysdev);
+
platform_add_devices(osiris_devices, ARRAY_SIZE(osiris_devices));
};
@@ -299,5 +380,6 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS")
.map_io = osiris_map_io,
.init_machine = osiris_init,
.init_irq = s3c24xx_init_irq,
+ .init_machine = osiris_init,
.timer = &s3c24xx_timer,
MACHINE_END
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 4cbf9468f65..3a0a1ee2542 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -185,28 +185,21 @@ static int __devinit neponset_probe(struct platform_device *dev)
/*
* LDM power management.
*/
+static unsigned int neponset_saved_state;
+
static int neponset_suspend(struct platform_device *dev, pm_message_t state)
{
/*
* Save state.
*/
- if (!dev->dev.power.saved_state)
- dev->dev.power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
- if (!dev->dev.power.saved_state)
- return -ENOMEM;
-
- *(unsigned int *)dev->dev.power.saved_state = NCR_0;
+ neponset_saved_state = NCR_0;
return 0;
}
static int neponset_resume(struct platform_device *dev)
{
- if (dev->dev.power.saved_state) {
- NCR_0 = *(unsigned int *)dev->dev.power.saved_state;
- kfree(dev->dev.power.saved_state);
- dev->dev.power.saved_state = NULL;
- }
+ NCR_0 = neponset_saved_state;
return 0;
}
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index d674cf34315..01a37d3c072 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -57,12 +57,7 @@ enum { SLEEP_SAVE_SP = 0,
static int sa11x0_pm_enter(suspend_state_t state)
{
unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
- struct timespec delta, rtc;
- /* preserve current time */
- rtc.tv_sec = RCNR;
- rtc.tv_nsec = 0;
- save_time_delta(&delta, &rtc);
gpio = GPLR;
/* save vital registers */
@@ -119,10 +114,6 @@ static int sa11x0_pm_enter(suspend_state_t state)
*/
PSSR = PSSR_PH;
- /* restore current time */
- rtc.tv_sec = RCNR;
- restore_time_delta(&delta, &rtc);
-
return 0;
}
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 29cb0c1604a..fdf7b016e7a 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -21,25 +21,6 @@
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
-static unsigned long __init sa1100_get_rtc_time(void)
-{
- /*
- * According to the manual we should be able to let RTTR be zero
- * and then a default divisor for a 32.768KHz clock is used.
- * Apparently this doesn't work, at least for my SA1110 rev 5.
- * If the clock divider is uninitialized then reset it to the
- * default value to get the 1Hz clock.
- */
- if (RTTR == 0) {
- RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
- printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n");
- /* The current RTC value probably doesn't make sense either */
- RCNR = 0;
- return 0;
- }
- return RCNR;
-}
-
static int sa1100_set_rtc(void)
{
unsigned long current_time = xtime.tv_sec;
@@ -117,15 +98,10 @@ static struct irqaction sa1100_timer_irq = {
static void __init sa1100_timer_init(void)
{
- struct timespec tv;
unsigned long flags;
set_rtc = sa1100_set_rtc;
- tv.tv_nsec = 0;
- tv.tv_sec = sa1100_get_rtc_time();
- do_settimeofday(&tv);
-
OIER = 0; /* disable any timer interrupts */
OSSR = 0xf; /* clear status on all timers */
setup_irq(IRQ_OST0, &sa1100_timer_irq);
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index ba58223f12b..ca829015943 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -117,7 +117,10 @@ static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int wh
} else {
switch (size) {
case 1:
- v = __raw_readb(addr);
+ v = __raw_readl(addr);
+ if (where & 2) v >>= 16;
+ if (where & 1) v >>= 8;
+ v &= 0xff;
break;
case 2:
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 36440c89958..074b7cb0774 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -630,7 +630,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
fs = get_fs();
set_fs(KERNEL_DS);
- if thumb_mode(regs) {
+ if (thumb_mode(regs)) {
fault = __get_user(tinstr, (u16 *)(instrptr & ~1));
if (!(fault))
instr = thumb2arm(tinstr);
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index f3ade18862a..75952779ce1 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -280,7 +280,10 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
if (!type)
return NULL;
- size = PAGE_ALIGN(size);
+ /*
+ * Page align the mapping size, taking account of any offset.
+ */
+ size = PAGE_ALIGN(offset + size);
area = get_vm_area(size, VM_IOREMAP);
if (!area)
@@ -325,11 +328,6 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
if (!size || last_addr < phys_addr)
return NULL;
- /*
- * Page align the mapping size
- */
- size = PAGE_ALIGN(last_addr + 1) - phys_addr;
-
return __arm_ioremap_pfn(pfn, offset, size, mtype);
}
EXPORT_SYMBOL(__arm_ioremap);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 02e050ae59f..3b5e47dc0c9 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -527,9 +527,9 @@ void __init create_mapping(struct map_desc *md)
return;
}
- addr = md->virtual;
+ addr = md->virtual & PAGE_MASK;
phys = (unsigned long)__pfn_to_phys(md->pfn);
- length = PAGE_ALIGN(md->length);
+ length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c
index 7791da791f5..75bae067922 100644
--- a/arch/arm/oprofile/op_model_mpcore.c
+++ b/arch/arm/oprofile/op_model_mpcore.c
@@ -200,8 +200,10 @@ static int em_call_function(int (*fn)(void))
data.fn = fn;
data.ret = 0;
+ preempt_disable();
smp_call_function(em_func, &data, 1, 1);
em_func(&data);
+ preempt_enable();
return data.ret;
}
diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile
index 4d2b1da3cd8..36bff032595 100644
--- a/arch/arm/plat-iop/Makefile
+++ b/arch/arm/plat-iop/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_ARCH_IOP32X) += setup.o
obj-$(CONFIG_ARCH_IOP32X) += time.o
obj-$(CONFIG_ARCH_IOP32X) += io.o
obj-$(CONFIG_ARCH_IOP32X) += cp6.o
+obj-$(CONFIG_ARCH_IOP32X) += adma.o
# IOP33X
obj-$(CONFIG_ARCH_IOP33X) += gpio.o
@@ -21,6 +22,7 @@ obj-$(CONFIG_ARCH_IOP33X) += setup.o
obj-$(CONFIG_ARCH_IOP33X) += time.o
obj-$(CONFIG_ARCH_IOP33X) += io.o
obj-$(CONFIG_ARCH_IOP33X) += cp6.o
+obj-$(CONFIG_ARCH_IOP33X) += adma.o
# IOP13XX
obj-$(CONFIG_ARCH_IOP13XX) += cp6.o
diff --git a/arch/arm/plat-iop/adma.c b/arch/arm/plat-iop/adma.c
new file mode 100644
index 00000000000..53c5e9a52eb
--- /dev/null
+++ b/arch/arm/plat-iop/adma.c
@@ -0,0 +1,209 @@
+/*
+ * platform device definitions for the iop3xx dma/xor engines
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * 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/platform_device.h>
+#include <asm/hardware/iop3xx.h>
+#include <linux/dma-mapping.h>
+#include <asm/arch/adma.h>
+#include <asm/hardware/iop_adma.h>
+
+#ifdef CONFIG_ARCH_IOP32X
+#define IRQ_DMA0_EOT IRQ_IOP32X_DMA0_EOT
+#define IRQ_DMA0_EOC IRQ_IOP32X_DMA0_EOC
+#define IRQ_DMA0_ERR IRQ_IOP32X_DMA0_ERR
+
+#define IRQ_DMA1_EOT IRQ_IOP32X_DMA1_EOT
+#define IRQ_DMA1_EOC IRQ_IOP32X_DMA1_EOC
+#define IRQ_DMA1_ERR IRQ_IOP32X_DMA1_ERR
+
+#define IRQ_AA_EOT IRQ_IOP32X_AA_EOT
+#define IRQ_AA_EOC IRQ_IOP32X_AA_EOC
+#define IRQ_AA_ERR IRQ_IOP32X_AA_ERR
+#endif
+#ifdef CONFIG_ARCH_IOP33X
+#define IRQ_DMA0_EOT IRQ_IOP33X_DMA0_EOT
+#define IRQ_DMA0_EOC IRQ_IOP33X_DMA0_EOC
+#define IRQ_DMA0_ERR IRQ_IOP33X_DMA0_ERR
+
+#define IRQ_DMA1_EOT IRQ_IOP33X_DMA1_EOT
+#define IRQ_DMA1_EOC IRQ_IOP33X_DMA1_EOC
+#define IRQ_DMA1_ERR IRQ_IOP33X_DMA1_ERR
+
+#define IRQ_AA_EOT IRQ_IOP33X_AA_EOT
+#define IRQ_AA_EOC IRQ_IOP33X_AA_EOC
+#define IRQ_AA_ERR IRQ_IOP33X_AA_ERR
+#endif
+/* AAU and DMA Channels */
+static struct resource iop3xx_dma_0_resources[] = {
+ [0] = {
+ .start = IOP3XX_DMA_PHYS_BASE(0),
+ .end = IOP3XX_DMA_UPPER_PA(0),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_DMA0_EOT,
+ .end = IRQ_DMA0_EOT,
+ .flags = IORESOURCE_IRQ
+ },
+ [2] = {
+ .start = IRQ_DMA0_EOC,
+ .end = IRQ_DMA0_EOC,
+ .flags = IORESOURCE_IRQ
+ },
+ [3] = {
+ .start = IRQ_DMA0_ERR,
+ .end = IRQ_DMA0_ERR,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct resource iop3xx_dma_1_resources[] = {
+ [0] = {
+ .start = IOP3XX_DMA_PHYS_BASE(1),
+ .end = IOP3XX_DMA_UPPER_PA(1),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_DMA1_EOT,
+ .end = IRQ_DMA1_EOT,
+ .flags = IORESOURCE_IRQ
+ },
+ [2] = {
+ .start = IRQ_DMA1_EOC,
+ .end = IRQ_DMA1_EOC,
+ .flags = IORESOURCE_IRQ
+ },
+ [3] = {
+ .start = IRQ_DMA1_ERR,
+ .end = IRQ_DMA1_ERR,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+
+static struct resource iop3xx_aau_resources[] = {
+ [0] = {
+ .start = IOP3XX_AAU_PHYS_BASE,
+ .end = IOP3XX_AAU_UPPER_PA,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_AA_EOT,
+ .end = IRQ_AA_EOT,
+ .flags = IORESOURCE_IRQ
+ },
+ [2] = {
+ .start = IRQ_AA_EOC,
+ .end = IRQ_AA_EOC,
+ .flags = IORESOURCE_IRQ
+ },
+ [3] = {
+ .start = IRQ_AA_ERR,
+ .end = IRQ_AA_ERR,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static u64 iop3xx_adma_dmamask = DMA_32BIT_MASK;
+
+static struct iop_adma_platform_data iop3xx_dma_0_data = {
+ .hw_id = DMA0_ID,
+ .pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop3xx_dma_1_data = {
+ .hw_id = DMA1_ID,
+ .pool_size = PAGE_SIZE,
+};
+
+static struct iop_adma_platform_data iop3xx_aau_data = {
+ .hw_id = AAU_ID,
+ .pool_size = 3 * PAGE_SIZE,
+};
+
+struct platform_device iop3xx_dma_0_channel = {
+ .name = "iop-adma",
+ .id = 0,
+ .num_resources = 4,
+ .resource = iop3xx_dma_0_resources,
+ .dev = {
+ .dma_mask = &iop3xx_adma_dmamask,
+ .coherent_dma_mask = DMA_64BIT_MASK,
+ .platform_data = (void *) &iop3xx_dma_0_data,
+ },
+};
+
+struct platform_device iop3xx_dma_1_channel = {
+ .name = "iop-adma",
+ .id = 1,
+ .num_resources = 4,
+ .resource = iop3xx_dma_1_resources,
+ .dev = {
+ .dma_mask = &iop3xx_adma_dmamask,
+ .coherent_dma_mask = DMA_64BIT_MASK,
+ .platform_data = (void *) &iop3xx_dma_1_data,
+ },
+};
+
+struct platform_device iop3xx_aau_channel = {
+ .name = "iop-adma",
+ .id = 2,
+ .num_resources = 4,
+ .resource = iop3xx_aau_resources,
+ .dev = {
+ .dma_mask = &iop3xx_adma_dmamask,
+ .coherent_dma_mask = DMA_64BIT_MASK,
+ .platform_data = (void *) &iop3xx_aau_data,
+ },
+};
+
+static int __init iop3xx_adma_cap_init(void)
+{
+ #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
+ dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
+ dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
+ #else
+ dma_cap_set(DMA_MEMCPY, iop3xx_dma_0_data.cap_mask);
+ dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_0_data.cap_mask);
+ dma_cap_set(DMA_INTERRUPT, iop3xx_dma_0_data.cap_mask);
+ #endif
+
+ #ifdef CONFIG_ARCH_IOP32X /* the 32x DMA does not perform CRC32C */
+ dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
+ dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
+ #else
+ dma_cap_set(DMA_MEMCPY, iop3xx_dma_1_data.cap_mask);
+ dma_cap_set(DMA_MEMCPY_CRC32C, iop3xx_dma_1_data.cap_mask);
+ dma_cap_set(DMA_INTERRUPT, iop3xx_dma_1_data.cap_mask);
+ #endif
+
+ #ifdef CONFIG_ARCH_IOP32X /* the 32x AAU does not perform zero sum */
+ dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
+ dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
+ dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
+ #else
+ dma_cap_set(DMA_XOR, iop3xx_aau_data.cap_mask);
+ dma_cap_set(DMA_ZERO_SUM, iop3xx_aau_data.cap_mask);
+ dma_cap_set(DMA_MEMSET, iop3xx_aau_data.cap_mask);
+ dma_cap_set(DMA_INTERRUPT, iop3xx_aau_data.cap_mask);
+ #endif
+
+ return 0;
+}
+
+arch_initcall(iop3xx_adma_cap_init);
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index ca2a5ad19ea..806ce26d524 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -29,6 +29,10 @@ do_vfp:
add r10, r10, #TI_VFPSTATE @ r10 = workspace
ldr pc, [r4] @ call VFP entry point
+ENTRY(vfp_null_entry)
+ mov pc, lr
+ENDPROC(vfp_null_entry)
+
.LCvfp:
.word vfp_vector
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index f1e5951dc72..1106b5f9cf1 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -26,8 +26,9 @@
*/
void vfp_testing_entry(void);
void vfp_support_entry(void);
+void vfp_null_entry(void);
-void (*vfp_vector)(void) = vfp_testing_entry;
+void (*vfp_vector)(void) = vfp_null_entry;
union vfp_state *last_VFP_context[NR_CPUS];
/*
@@ -321,8 +322,10 @@ static int __init vfp_init(void)
* The handler is already setup to just log calls, so
* we just need to read the VFPSID register.
*/
+ vfp_vector = vfp_testing_entry;
vfpsid = fmrx(FPSID);
barrier();
+ vfp_vector = vfp_null_entry;
printk(KERN_INFO "VFP support v0.3: ");
if (VFP_arch) {
diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c
index 9bc37d4f668..6c4dc0a00e9 100644
--- a/arch/avr32/boards/atngw100/setup.c
+++ b/arch/avr32/boards/atngw100/setup.c
@@ -94,9 +94,6 @@ static void __init set_hw_addr(struct platform_device *pdev)
clk_put(pclk);
}
-struct platform_device *at32_usart_map[1];
-unsigned int at32_nr_usarts = 1;
-
void __init setup_board(void)
{
at32_map_usart(1, 0); /* USART 1: /dev/ttyS0, DB9 */
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
index fe1dbe2e28f..e253e86a1a3 100644
--- a/arch/avr32/boards/atstk1000/atstk1002.c
+++ b/arch/avr32/boards/atstk1000/atstk1002.c
@@ -42,6 +42,7 @@ static struct spi_board_info spi0_board_info[] __initdata = {
.modalias = "ltv350qv",
.max_speed_hz = 16000000,
.chip_select = 1,
+ .mode = SPI_MODE_3,
},
};
diff --git a/arch/avr32/configs/atngw100_defconfig b/arch/avr32/configs/atngw100_defconfig
index c254ffcfa45..49493ad3b5a 100644
--- a/arch/avr32/configs/atngw100_defconfig
+++ b/arch/avr32/configs/atngw100_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc6
-# Thu Apr 12 16:35:07 2007
+# Linux kernel version: 2.6.22-rc5
+# Sat Jun 23 15:40:05 2007
#
CONFIG_AVR32=y
CONFIG_GENERIC_GPIO=y
@@ -40,6 +40,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -57,14 +58,20 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
# CONFIG_BASE_FULL is not set
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -148,6 +155,7 @@ CONFIG_CMDLINE=""
#
# Bus options
#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -168,7 +176,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -212,14 +219,11 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
@@ -242,8 +246,6 @@ CONFIG_NETFILTER=y
#
# CONFIG_NETFILTER_NETLINK is not set
CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CT_ACCT=y
CONFIG_NF_CONNTRACK_MARK=y
@@ -357,20 +359,8 @@ CONFIG_IP6_NF_TARGET_REJECT=m
CONFIG_IP6_NF_MANGLE=m
CONFIG_IP6_NF_TARGET_HL=m
CONFIG_IP6_NF_RAW=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -397,7 +387,16 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -417,10 +416,6 @@ CONFIG_STANDALONE=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -464,7 +459,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -492,16 +486,13 @@ CONFIG_MTD_DATAFLASH=y
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -530,10 +521,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -542,10 +530,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -554,19 +538,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_MD is not set
#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -574,10 +545,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -586,27 +553,14 @@ CONFIG_TUN=m
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_MACB=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -671,15 +625,10 @@ CONFIG_UNIX98_PTYS=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -687,10 +636,6 @@ CONFIG_UNIX98_PTYS=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -710,17 +655,13 @@ CONFIG_SPI_ATMEL=y
# SPI Protocol Masters
#
# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
# Multifunction device drivers
@@ -731,16 +672,19 @@ CONFIG_SPI_ATMEL=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
#
@@ -763,10 +707,6 @@ CONFIG_SPI_ATMEL=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -809,14 +749,6 @@ CONFIG_SPI_ATMEL=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -911,6 +843,7 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -993,11 +926,9 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
@@ -1044,6 +975,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
@@ -1072,6 +1004,7 @@ CONFIG_CRYPTO_DEFLATE=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
@@ -1083,3 +1016,4 @@ CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/avr32/configs/atstk1002_defconfig b/arch/avr32/configs/atstk1002_defconfig
index 77dace9d54b..3b977fdbaa7 100644
--- a/arch/avr32/configs/atstk1002_defconfig
+++ b/arch/avr32/configs/atstk1002_defconfig
@@ -1,9 +1,10 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc6
-# Fri Jan 26 13:12:59 2007
+# Linux kernel version: 2.6.22-rc5
+# Sat Jun 23 15:32:08 2007
#
CONFIG_AVR32=y
+CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_GENERIC_IRQ_PROBE=y
@@ -13,6 +14,7 @@ CONFIG_GENERIC_TIME=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_BUG=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -30,19 +32,22 @@ CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
+# CONFIG_TASK_XACCT is not set
# CONFIG_UTS_NS is not set
CONFIG_AUDIT=y
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-# CONFIG_TASK_XACCT is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
@@ -55,14 +60,20 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
# CONFIG_BASE_FULL is not set
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -105,7 +116,15 @@ CONFIG_PLATFORM_AT32AP=y
CONFIG_CPU_AT32AP7000=y
CONFIG_BOARD_ATSTK1002=y
CONFIG_BOARD_ATSTK1000=y
+# CONFIG_BOARD_ATNGW100 is not set
CONFIG_LOADER_U_BOOT=y
+
+#
+# Atmel AVR32 AP options
+#
+# CONFIG_AP7000_32_BIT_SMC is not set
+CONFIG_AP7000_16_BIT_SMC=y
+# CONFIG_AP7000_8_BIT_SMC is not set
CONFIG_LOAD_ADDRESS=0x10000000
CONFIG_ENTRY_ADDRESS=0x90000000
CONFIG_PHYS_OFFSET=0x10000000
@@ -127,6 +146,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
# CONFIG_OWNERSHIP_TRACE is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
@@ -138,6 +158,7 @@ CONFIG_CMDLINE=""
#
# Bus options
#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -158,7 +179,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
@@ -194,20 +214,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -233,7 +241,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -246,16 +263,13 @@ CONFIG_STANDALONE=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -299,7 +313,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -325,16 +338,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -344,6 +354,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -356,18 +367,13 @@ CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -376,10 +382,6 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -388,19 +390,6 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -408,10 +397,6 @@ CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -420,27 +405,14 @@ CONFIG_TUN=m
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_MACB=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
CONFIG_PPP=m
# CONFIG_PPP_MULTILINK is not set
@@ -505,15 +477,10 @@ CONFIG_UNIX98_PTYS=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -521,10 +488,6 @@ CONFIG_UNIX98_PTYS=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -537,29 +500,31 @@ CONFIG_UNIX98_PTYS=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -581,10 +546,6 @@ CONFIG_UNIX98_PTYS=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -627,10 +588,6 @@ CONFIG_UNIX98_PTYS=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=m
@@ -712,8 +669,20 @@ CONFIG_JFFS2_RTIME=y
#
# Network File Systems
#
-# CONFIG_NFS_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
@@ -787,15 +756,14 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -806,6 +774,7 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FRAME_POINTER=y
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_KPROBES is not set
#
@@ -825,10 +794,13 @@ CONFIG_FORCED_INLINING=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_AUDIT_GENERIC=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/avr32/mach-at32ap/at32ap7000.c b/arch/avr32/mach-at32ap/at32ap7000.c
index 1d2bf347a1d..4dda42d3f6d 100644
--- a/arch/avr32/mach-at32ap/at32ap7000.c
+++ b/arch/avr32/mach-at32ap/at32ap7000.c
@@ -9,6 +9,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
#include <asm/io.h>
@@ -45,19 +46,30 @@
.flags = IORESOURCE_IRQ, \
}
+/* REVISIT these assume *every* device supports DMA, but several
+ * don't ... tc, smc, pio, rtc, watchdog, pwm, ps2, and more.
+ */
#define DEFINE_DEV(_name, _id) \
+static u64 _name##_id##_dma_mask = DMA_32BIT_MASK; \
static struct platform_device _name##_id##_device = { \
.name = #_name, \
.id = _id, \
+ .dev = { \
+ .dma_mask = &_name##_id##_dma_mask, \
+ .coherent_dma_mask = DMA_32BIT_MASK, \
+ }, \
.resource = _name##_id##_resource, \
.num_resources = ARRAY_SIZE(_name##_id##_resource), \
}
#define DEFINE_DEV_DATA(_name, _id) \
+static u64 _name##_id##_dma_mask = DMA_32BIT_MASK; \
static struct platform_device _name##_id##_device = { \
.name = #_name, \
.id = _id, \
.dev = { \
+ .dma_mask = &_name##_id##_dma_mask, \
.platform_data = &_name##_id##_data, \
+ .coherent_dma_mask = DMA_32BIT_MASK, \
}, \
.resource = _name##_id##_resource, \
.num_resources = ARRAY_SIZE(_name##_id##_resource), \
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c
index 8f7b1c3cd0f..c1233c615e6 100644
--- a/arch/avr32/mm/cache.c
+++ b/arch/avr32/mm/cache.c
@@ -23,7 +23,6 @@
void invalidate_dcache_region(void *start, size_t size)
{
unsigned long v, begin, end, linesz, mask;
- int flush = 0;
linesz = boot_cpu_data.dcache.linesz;
mask = linesz - 1;
@@ -32,24 +31,21 @@ void invalidate_dcache_region(void *start, size_t size)
* instead of invalidating ... never discard valid data!
*/
begin = (unsigned long)start;
- end = begin + size - 1;
+ end = begin + size;
if (begin & mask) {
flush_dcache_line(start);
begin += linesz;
- flush = 1;
}
- if ((end & mask) != mask) {
+ if (end & mask) {
flush_dcache_line((void *)end);
- end -= linesz;
- flush = 1;
+ end &= ~mask;
}
/* remaining cachelines only need invalidation */
- for (v = begin; v <= end; v += linesz)
+ for (v = begin; v < end; v += linesz)
invalidate_dcache_line((void *)v);
- if (flush)
- flush_write_buffer();
+ flush_write_buffer();
}
void clean_dcache_region(void *start, size_t size)
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
index e011f1ce187..4b2495285d9 100644
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -158,7 +158,7 @@ bad_area:
up_read(&mm->mmap_sem);
if (user_mode(regs)) {
- if (exception_trace)
+ if (exception_trace && printk_ratelimit())
printk("%s%s[%d]: segfault at %08lx pc %08lx "
"sp %08lx ecr %lu\n",
is_init(tsk) ? KERN_EMERG : KERN_INFO,
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index b1b111bb2f3..017defaa525 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -71,6 +71,7 @@ config GENERIC_CALIBRATE_DELAY
config IRQCHIP_DEMUX_GPIO
bool
+ depends on (BF53x || BF561 || BF54x)
default y
source "init/Kconfig"
@@ -114,6 +115,26 @@ config BF537
help
BF537 Processor Support.
+config BF542
+ bool "BF542"
+ help
+ BF542 Processor Support.
+
+config BF544
+ bool "BF544"
+ help
+ BF544 Processor Support.
+
+config BF548
+ bool "BF548"
+ help
+ BF548 Processor Support.
+
+config BF549
+ bool "BF549"
+ help
+ BF549 Processor Support.
+
config BF561
bool "BF561"
help
@@ -125,6 +146,11 @@ choice
prompt "Silicon Rev"
default BF_REV_0_2 if BF537
default BF_REV_0_3 if BF533
+ default BF_REV_0_0 if BF549
+
+config BF_REV_0_0
+ bool "0.0"
+ depends on (BF549)
config BF_REV_0_2
bool "0.2"
@@ -142,8 +168,24 @@ config BF_REV_0_5
bool "0.5"
depends on (BF561 || BF533 || BF532 || BF531)
+config BF_REV_ANY
+ bool "any"
+
+config BF_REV_NONE
+ bool "none"
+
endchoice
+config BF53x
+ bool
+ depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537)
+ default y
+
+config BF54x
+ bool
+ depends on (BF542 || BF544 || BF548 || BF549)
+ default y
+
config BFIN_DUAL_CORE
bool
depends on (BF561)
@@ -192,6 +234,12 @@ config BFIN537_BLUETECHNIX_CM
help
CM-BF537 support for EVAL- and DEV-Board.
+config BFIN548_EZKIT
+ bool "BF548-EZKIT"
+ depends on (BF548 || BF549)
+ help
+ BFIN548-EZKIT board Support.
+
config BFIN561_BLUETECHNIX_CM
bool "Bluetechnix CM-BF561"
depends on (BF561)
@@ -259,6 +307,7 @@ config BFIN_SHARED_FLASH_ENET
source "arch/blackfin/mach-bf533/Kconfig"
source "arch/blackfin/mach-bf561/Kconfig"
source "arch/blackfin/mach-bf537/Kconfig"
+source "arch/blackfin/mach-bf548/Kconfig"
menu "Board customizations"
@@ -394,41 +443,6 @@ config BFIN_IDLE_LED_PIN
default 0x08 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 2)
default 0x10 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 3)
-comment "Console UART Setup"
-
-choice
- prompt "Baud Rate"
- default BAUD_57600
-config BAUD_9600
- bool "9600"
-config BAUD_19200
- bool "19200"
-config BAUD_38400
- bool "38400"
-config BAUD_57600
- bool "57600"
-config BAUD_115200
- bool "115200"
-endchoice
-
-choice
- prompt "Parity"
- default BAUD_NO_PARITY
-config BAUD_NO_PARITY
- bool "No Parity"
-config BAUD_PARITY
- bool "Parity"
-endchoice
-
-choice
- prompt "Stop Bits"
- default BAUD_1_STOPBIT
-config BAUD_1_STOPBIT
- bool "1"
-config BAUD_2_STOPBIT
- bool "2"
-endchoice
-
endmenu
@@ -526,7 +540,8 @@ config IP_CHECKSUM_L1
config CACHELINE_ALIGNED_L1
bool "Locate cacheline_aligned data to L1 Data Memory"
- default y
+ default y if !BF54x
+ default n if BF54x
depends on !BF531
help
If enabled cacheline_anligned data is linked
@@ -570,9 +585,17 @@ endchoice
source "mm/Kconfig"
+config LARGE_ALLOCS
+ bool "Allow allocating large blocks (> 1MB) of memory"
+ help
+ Allow the slab memory allocator to keep chains for very large
+ memory sizes - upto 32MB. You may need this if your system has
+ a lot of RAM, and you need to able to allocate very large
+ contiguous chunks. If unsure, say N.
+
config BFIN_DMA_5XX
bool "Enable DMA Support"
- depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561)
+ depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561 || BF54x)
default y
help
DMA driver for BF5xx.
@@ -715,6 +738,7 @@ config C_AMCKEN
config C_CDPRIO
bool "DMA has priority over core for ext. accesses"
+ depends on !BF54x
default n
config C_B0PEN
@@ -868,7 +892,7 @@ endchoice
endmenu
-if (BF537 || BF533)
+if (BF537 || BF533 || BF54x)
menu "CPU Frequency scaling"
diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
index 75e89c32475..1b75672dfc8 100644
--- a/arch/blackfin/Makefile
+++ b/arch/blackfin/Makefile
@@ -24,10 +24,33 @@ machine-$(CONFIG_BF533) := bf533
machine-$(CONFIG_BF534) := bf537
machine-$(CONFIG_BF536) := bf537
machine-$(CONFIG_BF537) := bf537
+machine-$(CONFIG_BF548) := bf548
+machine-$(CONFIG_BF549) := bf548
machine-$(CONFIG_BF561) := bf561
MACHINE := $(machine-y)
export MACHINE
+cpu-$(CONFIG_BF531) := bf531
+cpu-$(CONFIG_BF532) := bf532
+cpu-$(CONFIG_BF533) := bf533
+cpu-$(CONFIG_BF534) := bf534
+cpu-$(CONFIG_BF536) := bf536
+cpu-$(CONFIG_BF537) := bf537
+cpu-$(CONFIG_BF548) := bf548
+cpu-$(CONFIG_BF549) := bf549
+cpu-$(CONFIG_BF561) := bf561
+
+rev-$(CONFIG_BF_REV_0_0) := 0.0
+rev-$(CONFIG_BF_REV_0_1) := 0.1
+rev-$(CONFIG_BF_REV_0_2) := 0.2
+rev-$(CONFIG_BF_REV_0_3) := 0.3
+rev-$(CONFIG_BF_REV_0_4) := 0.4
+rev-$(CONFIG_BF_REV_0_5) := 0.5
+rev-$(CONFIG_BF_REV_NONE) := none
+rev-$(CONFIG_BF_REV_ANY) := any
+
+CFLAGS += -mcpu=$(cpu-y)-$(rev-y)
+AFLAGS += -mcpu=$(cpu-y)-$(rev-y)
head-y := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
diff --git a/arch/blackfin/boot/Makefile b/arch/blackfin/boot/Makefile
index 49e8098d4c2..8cd33560e81 100644
--- a/arch/blackfin/boot/Makefile
+++ b/arch/blackfin/boot/Makefile
@@ -13,7 +13,8 @@ extra-y += vmlinux.bin vmlinux.gz
quiet_cmd_uimage = UIMAGE $@
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
- -C gzip -a $(CONFIG_BOOT_LOAD) -e $(CONFIG_BOOT_LOAD) -n 'Linux-$(KERNELRELEASE)' \
+ -C gzip -n 'Linux-$(KERNELRELEASE)' -a $(CONFIG_BOOT_LOAD) \
+ -e $(shell $(NM) vmlinux | awk '$$NF == "__start" {print $$1}') \
-d $< $@
$(obj)/vmlinux.bin: vmlinux FORCE
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
index 377c8e05e4a..1cf1ab28dc6 100644
--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -1,20 +1,21 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19.3
+# Linux kernel version: 2.6.21.5
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
CONFIG_BFIN=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_UCLINUX=y
CONFIG_FORCE_MAX_ZONEORDER=14
CONFIG_IRQCHIP_DEMUX_GPIO=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -33,13 +34,16 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -54,9 +58,7 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_EPOLL=y
CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_LIMIT_PAGECACHE is not set
CONFIG_BUDDY=y
# CONFIG_NP2 is not set
CONFIG_SLAB=y
@@ -80,7 +82,9 @@ CONFIG_KMOD=y
# Block layer
#
CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -109,22 +113,31 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF532 is not set
CONFIG_BF533=y
# CONFIG_BF534 is not set
-# CONFIG_BF535 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_2 is not set
CONFIG_BF_REV_0_3=y
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
CONFIG_BFIN_SINGLE_CORE=y
CONFIG_BFIN533_EZKIT=y
# CONFIG_BFIN533_STAMP is not set
# CONFIG_BFIN537_STAMP is not set
# CONFIG_BFIN533_BLUETECHNIX_CM is not set
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
# CONFIG_BFIN561_BLUETECHNIX_CM is not set
# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
# CONFIG_PNAV10 is not set
# CONFIG_GENERIC_BOARD is not set
CONFIG_MEM_MT48LC16M16A2TG_75=y
@@ -168,6 +181,7 @@ CONFIG_WDTIMER=13
#
# Board customizations
#
+# CONFIG_CMDLINE_BOOL is not set
#
# Board Setup
@@ -178,19 +192,6 @@ CONFIG_MEM_ADD_WIDTH=9
CONFIG_BOOT_LOAD=0x1000
#
-# Console UART Setup
-#
-# CONFIG_BAUD_9600 is not set
-# CONFIG_BAUD_19200 is not set
-# CONFIG_BAUD_38400 is not set
-CONFIG_BAUD_57600=y
-# CONFIG_BAUD_115200 is not set
-CONFIG_BAUD_NO_PARITY=y
-# CONFIG_BAUD_PARITY is not set
-CONFIG_BAUD_1_STOPBIT=y
-# CONFIG_BAUD_2_STOPBIT is not set
-
-#
# Blackfin Kernel Optimizations
#
@@ -199,6 +200,7 @@ CONFIG_BAUD_1_STOPBIT=y
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
@@ -217,6 +219,7 @@ CONFIG_MEMSET_L1=y
CONFIG_MEMCPY_L1=y
CONFIG_SYS_BFIN_SPINLOCK_L1=y
# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
CONFIG_RAMKERNEL=y
@@ -230,6 +233,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
@@ -302,7 +306,7 @@ CONFIG_BINFMT_ZFLAT=y
# Power management options
#
CONFIG_PM=y
-CONFIG_PM_LEGACY=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
# CONFIG_PM_SYSFS_DEPRECATED is not set
CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
@@ -330,6 +334,7 @@ CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -356,6 +361,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -399,7 +405,48 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
# CONFIG_BT is not set
# CONFIG_IEEE80211 is not set
@@ -434,6 +481,7 @@ CONFIG_MTD_PARTITIONS=y
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
@@ -489,6 +537,8 @@ CONFIG_BFIN_FLASH_BANK_3=0x7BB0
#
# Self-contained MTD device drivers
#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
@@ -519,6 +569,7 @@ CONFIG_BFIN_FLASH_BANK_3=0x7BB0
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -530,14 +581,12 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -594,6 +643,7 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
#
# Ethernet (1000 Mbit)
@@ -636,7 +686,26 @@ CONFIG_SMC91X=y
#
# Input device support
#
-# CONFIG_INPUT is not set
+CONFIG_INPUT=m
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
# Hardware I/O ports
@@ -649,12 +718,14 @@ CONFIG_SMC91X=y
#
# CONFIG_AD9960 is not set
# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF533_PFLAGS is not set
+# CONFIG_BF5xx_PFLAGS is not set
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BF5xx_TIMERS is not set
# CONFIG_BF5xx_PPI is not set
-# CONFIG_BFIN_SPORT is not set
+CONFIG_BFIN_SPORT=y
# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_FBDMA is not set
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -691,16 +762,19 @@ CONFIG_UNIX98_PTYS=y
#
# Watchdog Cards
#
-# CONFIG_WATCHDOG is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
CONFIG_HW_RANDOM=y
# CONFIG_GEN_RTC is not set
CONFIG_BLACKFIN_DPMC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
@@ -716,8 +790,19 @@ CONFIG_BLACKFIN_DPMC=y
#
# SPI support
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
#
# Dallas's 1-wire bus
@@ -731,10 +816,17 @@ CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -747,9 +839,8 @@ CONFIG_HWMON=y
#
# Graphics support
#
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
#
# Sound
@@ -757,6 +848,12 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -776,6 +873,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
# MMC/SD Card support
#
+# CONFIG_SPI_MMC is not set
# CONFIG_MMC is not set
#
@@ -821,8 +919,10 @@ CONFIG_RTC_INTF_DEV=y
#
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_V3020 is not set
CONFIG_RTC_DRV_BFIN=y
@@ -840,6 +940,14 @@ CONFIG_RTC_DRV_BFIN=y
#
#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
# PBX support
#
# CONFIG_PBX is not set
@@ -847,13 +955,9 @@ CONFIG_RTC_DRV_BFIN=y
#
# File systems
#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
-CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
@@ -862,7 +966,8 @@ CONFIG_FS_MBCACHE=y
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
-# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
@@ -913,7 +1018,6 @@ CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
-# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=m
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -945,7 +1049,8 @@ CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -961,7 +1066,51 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-# CONFIG_NLS is not set
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
#
# Profiling support
@@ -975,19 +1124,16 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_BOOTPARAM is not set
-# CONFIG_NO_KERNEL_MSG is not set
CONFIG_CPLB_INFO=y
-# CONFIG_NO_ACCESS_CHECK is not set
+CONFIG_ACCESS_CHECK=y
#
# Security options
@@ -995,7 +1141,7 @@ CONFIG_CPLB_INFO=y
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
# CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+CONFIG_SECURITY_CAPABILITIES=m
#
# Cryptographic options
@@ -1005,10 +1151,13 @@ CONFIG_SECURITY_CAPABILITIES=y
#
# Library routines
#
-# CONFIG_CRC_CCITT is not set
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index 14a948c288a..64b7f1b3b2a 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20.4
+# Linux kernel version: 2.6.21.5
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
CONFIG_BFIN=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -33,6 +34,7 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -41,6 +43,7 @@ CONFIG_SYSVIPC=y
# CONFIG_IKCONFIG is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -55,9 +58,7 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_EPOLL=y
CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_LIMIT_PAGECACHE is not set
CONFIG_BUDDY=y
# CONFIG_NP2 is not set
CONFIG_SLAB=y
@@ -114,19 +115,29 @@ CONFIG_BF533=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_2 is not set
CONFIG_BF_REV_0_3=y
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
CONFIG_BFIN_SINGLE_CORE=y
# CONFIG_BFIN533_EZKIT is not set
CONFIG_BFIN533_STAMP=y
# CONFIG_BFIN537_STAMP is not set
# CONFIG_BFIN533_BLUETECHNIX_CM is not set
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
# CONFIG_BFIN561_BLUETECHNIX_CM is not set
# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
# CONFIG_PNAV10 is not set
# CONFIG_GENERIC_BOARD is not set
CONFIG_MEM_MT48LC64M4A2FB_7E=y
@@ -193,19 +204,6 @@ CONFIG_BFIN_IDLE_LED_PORT=0xFFC00700
CONFIG_BFIN_IDLE_LED_DPORT=0xFFC00730
#
-# Console UART Setup
-#
-# CONFIG_BAUD_9600 is not set
-# CONFIG_BAUD_19200 is not set
-# CONFIG_BAUD_38400 is not set
-CONFIG_BAUD_57600=y
-# CONFIG_BAUD_115200 is not set
-CONFIG_BAUD_NO_PARITY=y
-# CONFIG_BAUD_PARITY is not set
-CONFIG_BAUD_1_STOPBIT=y
-# CONFIG_BAUD_2_STOPBIT is not set
-
-#
# Blackfin Kernel Optimizations
#
@@ -233,6 +231,7 @@ CONFIG_MEMSET_L1=y
CONFIG_MEMCPY_L1=y
CONFIG_SYS_BFIN_SPINLOCK_L1=y
# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
CONFIG_RAMKERNEL=y
@@ -246,6 +245,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
@@ -318,7 +318,7 @@ CONFIG_BINFMT_ZFLAT=y
# Power management options
#
CONFIG_PM=y
-CONFIG_PM_LEGACY=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
# CONFIG_PM_SYSFS_DEPRECATED is not set
CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
@@ -346,6 +346,7 @@ CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -580,6 +581,7 @@ CONFIG_BFIN_FLASH_BANK_3=0x7BB0
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -591,14 +593,12 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -655,6 +655,7 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
#
# Ethernet (1000 Mbit)
@@ -733,7 +734,7 @@ CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=39
#
# CONFIG_AD9960 is not set
# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF533_PFLAGS is not set
+# CONFIG_BF5xx_PFLAGS is not set
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BF5xx_TIMERS is not set
# CONFIG_BF5xx_PPI is not set
@@ -742,6 +743,8 @@ CONFIG_BFIN_SPORT=y
CONFIG_TWI_LCD=m
CONFIG_TWI_LCD_SLAVE_ADDR=34
# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_TEA5764 is not set
+# CONFIG_BF5xx_FBDMA is not set
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -778,7 +781,14 @@ CONFIG_UNIX98_PTYS=y
#
# Watchdog Cards
#
-# CONFIG_WATCHDOG is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
CONFIG_HW_RANDOM=y
# CONFIG_GEN_RTC is not set
CONFIG_BLACKFIN_DPMC=y
@@ -840,12 +850,13 @@ CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
+CONFIG_SPI_BFIN=y
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-CONFIG_SPI_BFIN=y
+# CONFIG_SPI_AT25 is not set
#
# Dallas's 1-wire bus
@@ -861,6 +872,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
@@ -900,6 +912,11 @@ CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -912,15 +929,22 @@ CONFIG_HWMON=y
#
# Graphics support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
CONFIG_FB=m
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
CONFIG_FB_CFB_FILLRECT=m
CONFIG_FB_CFB_COPYAREA=m
CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
CONFIG_FB_BFIN_7171=m
CONFIG_FB_BFIN_7393=m
CONFIG_NTSC=y
@@ -938,7 +962,6 @@ CONFIG_ADV7393_1XMEM=y
# Logo configuration
#
# CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -971,6 +994,26 @@ CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_MPU401 is not set
#
+# ALSA Blackfin devices
+#
+CONFIG_SND_BLACKFIN_AD1836=m
+CONFIG_SND_BLACKFIN_AD1836_TDM=y
+# CONFIG_SND_BLACKFIN_AD1836_I2S is not set
+CONFIG_SND_BLACKFIN_AD1836_MULSUB=y
+# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set
+CONFIG_SND_BLACKFIN_AD1981B=m
+CONFIG_SND_BLACKFIN_SPORT=0
+CONFIG_SND_BLACKFIN_SPI_PFBIT=4
+CONFIG_SND_BFIN_AD73311=m
+CONFIG_SND_BFIN_SPORT=0
+CONFIG_SND_BFIN_AD73311_SE=4
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
# Open Sound System
#
# CONFIG_SOUND_PRIME is not set
@@ -979,6 +1022,7 @@ CONFIG_SND_VERBOSE_PROCFS=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -1051,7 +1095,6 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_M48T86 is not set
@@ -1074,6 +1117,10 @@ CONFIG_RTC_DRV_BFIN=y
#
#
+# Auxiliary Display support
+#
+
+#
# Virtualization
#
@@ -1085,13 +1132,9 @@ CONFIG_RTC_DRV_BFIN=y
#
# File systems
#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
-CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
@@ -1103,7 +1146,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1275,7 +1318,7 @@ CONFIG_ACCESS_CHECK=y
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
# CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+CONFIG_SECURITY_CAPABILITIES=m
#
# Cryptographic options
@@ -1293,4 +1336,5 @@ CONFIG_CRC32=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index 8ed67dc450f..ccf09dc09a1 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20.4
+# Linux kernel version: 2.6.21.5
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
CONFIG_BFIN=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -33,6 +34,7 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -41,6 +43,7 @@ CONFIG_SYSVIPC=y
# CONFIG_IKCONFIG is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -55,9 +58,7 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_EPOLL=y
CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_LIMIT_PAGECACHE is not set
CONFIG_BUDDY=y
# CONFIG_NP2 is not set
CONFIG_SLAB=y
@@ -114,19 +115,29 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
CONFIG_BF537=y
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
CONFIG_BF_REV_0_2=y
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
CONFIG_BFIN_SINGLE_CORE=y
# CONFIG_BFIN533_EZKIT is not set
# CONFIG_BFIN533_STAMP is not set
CONFIG_BFIN537_STAMP=y
# CONFIG_BFIN533_BLUETECHNIX_CM is not set
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
# CONFIG_BFIN561_BLUETECHNIX_CM is not set
# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
# CONFIG_PNAV10 is not set
# CONFIG_GENERIC_BOARD is not set
CONFIG_MEM_MT48LC32M8A2_75=y
@@ -196,19 +207,6 @@ CONFIG_MEM_ADD_WIDTH=10
CONFIG_BOOT_LOAD=0x1000
#
-# Console UART Setup
-#
-# CONFIG_BAUD_9600 is not set
-# CONFIG_BAUD_19200 is not set
-# CONFIG_BAUD_38400 is not set
-CONFIG_BAUD_57600=y
-# CONFIG_BAUD_115200 is not set
-CONFIG_BAUD_NO_PARITY=y
-# CONFIG_BAUD_PARITY is not set
-CONFIG_BAUD_1_STOPBIT=y
-# CONFIG_BAUD_2_STOPBIT is not set
-
-#
# Blackfin Kernel Optimizations
#
@@ -236,6 +234,7 @@ CONFIG_MEMSET_L1=y
CONFIG_MEMCPY_L1=y
CONFIG_SYS_BFIN_SPINLOCK_L1=y
# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
CONFIG_RAMKERNEL=y
@@ -249,6 +248,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
@@ -321,7 +321,7 @@ CONFIG_BINFMT_ZFLAT=y
# Power management options
#
CONFIG_PM=y
-CONFIG_PM_LEGACY=y
+# CONFIG_PM_LEGACY is not set
# CONFIG_PM_DEBUG is not set
# CONFIG_PM_SYSFS_DEPRECATED is not set
CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
@@ -349,6 +349,7 @@ CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -593,6 +594,7 @@ CONFIG_MTD_NAND_IDS=m
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -604,14 +606,12 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -673,6 +673,7 @@ CONFIG_BFIN_MAC_USE_L1=y
CONFIG_BFIN_TX_DESC_NUM=10
CONFIG_BFIN_RX_DESC_NUM=20
# CONFIG_BFIN_MAC_RMII is not set
+# CONFIG_SMSC911X is not set
#
# Ethernet (1000 Mbit)
@@ -751,7 +752,7 @@ CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
#
# CONFIG_AD9960 is not set
# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF533_PFLAGS is not set
+# CONFIG_BF5xx_PFLAGS is not set
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BF5xx_TIMERS is not set
# CONFIG_BF5xx_PPI is not set
@@ -760,6 +761,8 @@ CONFIG_BFIN_SPORT=y
CONFIG_TWI_LCD=m
CONFIG_TWI_LCD_SLAVE_ADDR=34
# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_TEA5764 is not set
+# CONFIG_BF5xx_FBDMA is not set
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -804,7 +807,14 @@ CONFIG_CAN_BLACKFIN=m
#
# Watchdog Cards
#
-# CONFIG_WATCHDOG is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
CONFIG_HW_RANDOM=y
# CONFIG_GEN_RTC is not set
CONFIG_BLACKFIN_DPMC=y
@@ -868,12 +878,13 @@ CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
+CONFIG_SPI_BFIN=y
# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
-CONFIG_SPI_BFIN=y
+# CONFIG_SPI_AT25 is not set
#
# Dallas's 1-wire bus
@@ -889,6 +900,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
@@ -928,6 +940,11 @@ CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -940,15 +957,24 @@ CONFIG_HWMON=y
#
# Graphics support
#
-CONFIG_FIRMWARE_EDID=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_LCD_CLASS_DEVICE=m
CONFIG_FB=m
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
CONFIG_FB_CFB_FILLRECT=m
CONFIG_FB_CFB_COPYAREA=m
CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
CONFIG_FB_BFIN_7171=m
CONFIG_FB_BFIN_7393=m
CONFIG_NTSC=y
@@ -970,11 +996,6 @@ CONFIG_LQ035_SLAVE_ADDR=0x58
# Logo configuration
#
# CONFIG_LOGO is not set
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
#
# Sound
@@ -1007,6 +1028,26 @@ CONFIG_SND_VERBOSE_PROCFS=y
# CONFIG_SND_MPU401 is not set
#
+# ALSA Blackfin devices
+#
+CONFIG_SND_BLACKFIN_AD1836=m
+CONFIG_SND_BLACKFIN_AD1836_TDM=y
+# CONFIG_SND_BLACKFIN_AD1836_I2S is not set
+CONFIG_SND_BLACKFIN_AD1836_MULSUB=y
+# CONFIG_SND_BLACKFIN_AD1836_5P1 is not set
+CONFIG_SND_BLACKFIN_AD1981B=m
+CONFIG_SND_BLACKFIN_SPORT=0
+CONFIG_SND_BLACKFIN_SPI_PFBIT=4
+CONFIG_SND_BFIN_AD73311=m
+CONFIG_SND_BFIN_SPORT=0
+CONFIG_SND_BFIN_AD73311_SE=4
+
+#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
# Open Sound System
#
# CONFIG_SOUND_PRIME is not set
@@ -1015,6 +1056,7 @@ CONFIG_SND_VERBOSE_PROCFS=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -1087,7 +1129,6 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_M48T86 is not set
@@ -1110,6 +1151,10 @@ CONFIG_RTC_DRV_BFIN=y
#
#
+# Auxiliary Display support
+#
+
+#
# Virtualization
#
@@ -1121,13 +1166,9 @@ CONFIG_RTC_DRV_BFIN=y
#
# File systems
#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
-CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
@@ -1139,7 +1180,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -1311,7 +1352,7 @@ CONFIG_ACCESS_CHECK=y
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
# CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+CONFIG_SECURITY_CAPABILITIES=m
#
# Cryptographic options
@@ -1329,4 +1370,5 @@ CONFIG_CRC32=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index a513fbe3956..ac8390fafa9 100644
--- a/arch/blackfin/defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -1,12 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20.4
+# Linux kernel version: 2.6.21.5
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
CONFIG_BFIN=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -33,6 +34,7 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -41,6 +43,7 @@ CONFIG_SYSVIPC=y
# CONFIG_IKCONFIG is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -48,6 +51,7 @@ CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -55,10 +59,7 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_EPOLL=y
CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_LIMIT_PAGECACHE is not set
-CONFIG_BUDDY=y
# CONFIG_NP2 is not set
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
@@ -113,35 +114,57 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF533 is not set
# CONFIG_BF534 is not set
# CONFIG_BF536 is not set
-CONFIG_BF537=y
+# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+CONFIG_BF549=y
# CONFIG_BF561 is not set
-CONFIG_BF_REV_0_2=y
+CONFIG_BF_REV_0_0=y
+# CONFIG_BF_REV_0_2 is not set
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF54x=y
CONFIG_BFIN_SINGLE_CORE=y
# CONFIG_BFIN533_EZKIT is not set
# CONFIG_BFIN533_STAMP is not set
-CONFIG_BFIN537_STAMP=y
+# CONFIG_BFIN537_STAMP is not set
# CONFIG_BFIN533_BLUETECHNIX_CM is not set
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+CONFIG_BFIN548_EZKIT=y
# CONFIG_BFIN561_BLUETECHNIX_CM is not set
# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
# CONFIG_PNAV10 is not set
# CONFIG_GENERIC_BOARD is not set
-CONFIG_MEM_MT48LC32M8A2_75=y
CONFIG_IRQ_PLL_WAKEUP=7
+CONFIG_IRQ_TIMER0=11
+CONFIG_IRQ_TIMER1=11
+CONFIG_IRQ_TIMER2=11
+CONFIG_IRQ_TIMER3=11
+CONFIG_IRQ_TIMER4=11
+CONFIG_IRQ_TIMER5=11
+CONFIG_IRQ_TIMER6=11
+CONFIG_IRQ_TIMER7=11
+CONFIG_IRQ_TIMER8=11
+CONFIG_IRQ_TIMER9=11
+CONFIG_IRQ_TIMER10=11
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
#
-# BF537 Specific Configuration
-#
-
-#
-# PORT F/G Selection
+# BF548 Specific Configuration
#
-CONFIG_BF537_PORT_F=y
-# CONFIG_BF537_PORT_G is not set
-# CONFIG_BF537_PORT_H is not set
#
# Interrupt Priority Assignment
@@ -150,37 +173,73 @@ CONFIG_BF537_PORT_F=y
#
# Priority
#
-CONFIG_IRQ_DMA_ERROR=7
-CONFIG_IRQ_ERROR=7
-CONFIG_IRQ_RTC=8
-CONFIG_IRQ_PPI=8
-CONFIG_IRQ_SPORT0_RX=9
-CONFIG_IRQ_SPORT0_TX=9
-CONFIG_IRQ_SPORT1_RX=9
-CONFIG_IRQ_SPORT1_TX=9
-CONFIG_IRQ_TWI=10
-CONFIG_IRQ_SPI=10
-CONFIG_IRQ_UART0_RX=10
-CONFIG_IRQ_UART0_TX=10
-CONFIG_IRQ_UART1_RX=10
-CONFIG_IRQ_UART1_TX=10
-CONFIG_IRQ_CAN_RX=11
-CONFIG_IRQ_CAN_TX=11
-CONFIG_IRQ_MAC_RX=11
-CONFIG_IRQ_MAC_TX=11
-CONFIG_IRQ_TMR0=12
-CONFIG_IRQ_TMR1=12
-CONFIG_IRQ_TMR2=12
-CONFIG_IRQ_TMR3=12
-CONFIG_IRQ_TMR4=12
-CONFIG_IRQ_TMR5=12
-CONFIG_IRQ_TMR6=12
-CONFIG_IRQ_TMR7=12
-CONFIG_IRQ_PROG_INTA=12
-CONFIG_IRQ_PORTG_INTB=12
-CONFIG_IRQ_MEM_DMA0=13
-CONFIG_IRQ_MEM_DMA1=13
-CONFIG_IRQ_WATCH=13
+CONFIG_IRQ_DMAC0_ERR=7
+CONFIG_IRQ_EPPI0_ERR=7
+CONFIG_IRQ_SPORT0_ERR=7
+CONFIG_IRQ_SPORT1_ERR=7
+CONFIG_IRQ_SPI0_ERR=7
+CONFIG_IRQ_UART0_ERR=7
+CONFIG_IRQ_EPPI0=8
+CONFIG_IRQ_SPI0=10
+CONFIG_IRQ_PINT0=12
+CONFIG_IRQ_PINT1=12
+CONFIG_IRQ_MDMAS0=13
+CONFIG_IRQ_MDMAS1=13
+CONFIG_IRQ_WATCHDOG=13
+CONFIG_IRQ_DMAC1_ERR=7
+CONFIG_IRQ_SPORT2_ERR=7
+CONFIG_IRQ_SPORT3_ERR=7
+CONFIG_IRQ_MXVR_DATA=7
+CONFIG_IRQ_SPI1_ERR=7
+CONFIG_IRQ_SPI2_ERR=7
+CONFIG_IRQ_UART1_ERR=7
+CONFIG_IRQ_UART2_ERR=7
+CONFIG_IRQ_CAN0_ERR=7
+CONFIG_IRQ_SPORT2_RX=9
+CONFIG_IRQ_SPORT2_TX=9
+CONFIG_IRQ_SPORT3_RX=9
+CONFIG_IRQ_SPORT3_TX=9
+CONFIG_IRQ_EPPI1=9
+CONFIG_IRQ_EPPI2=9
+CONFIG_IRQ_SPI1=10
+CONFIG_IRQ_SPI2=10
+CONFIG_IRQ_ATAPI_RX=10
+CONFIG_IRQ_ATAPI_TX=10
+CONFIG_IRQ_TWI0=11
+CONFIG_IRQ_TWI1=11
+CONFIG_IRQ_CAN0_RX=11
+CONFIG_IRQ_CAN0_TX=11
+CONFIG_IRQ_MDMAS2=13
+CONFIG_IRQ_MDMAS3=13
+CONFIG_IRQ_MXVR_ERR=11
+CONFIG_IRQ_MXVR_MSG=11
+CONFIG_IRQ_MXVR_PKT=11
+CONFIG_IRQ_EPPI1_ERR=7
+CONFIG_IRQ_EPPI2_ERR=7
+CONFIG_IRQ_UART3_ERR=7
+CONFIG_IRQ_HOST_ERR=7
+CONFIG_IRQ_PIXC_ERR=7
+CONFIG_IRQ_NFC_ERR=7
+CONFIG_IRQ_ATAPI_ERR=7
+CONFIG_IRQ_CAN1_ERR=7
+CONFIG_IRQ_HS_DMA_ERR=7
+CONFIG_IRQ_PIXC_IN0=8
+CONFIG_IRQ_PIXC_IN1=8
+CONFIG_IRQ_PIXC_OUT=8
+CONFIG_IRQ_SDH=8
+CONFIG_IRQ_CNT=8
+CONFIG_IRQ_KEY=8
+CONFIG_IRQ_CAN1_RX=11
+CONFIG_IRQ_CAN1_TX=11
+CONFIG_IRQ_SDH_MASK0=11
+CONFIG_IRQ_SDH_MASK1=11
+CONFIG_IRQ_USB_INT0=11
+CONFIG_IRQ_USB_INT1=11
+CONFIG_IRQ_USB_INT2=11
+CONFIG_IRQ_USB_DMA=11
+CONFIG_IRQ_OTPSEC=11
+CONFIG_IRQ_PINT2=11
+CONFIG_IRQ_PINT3=11
#
# Board customizations
@@ -196,19 +255,6 @@ CONFIG_MEM_ADD_WIDTH=10
CONFIG_BOOT_LOAD=0x1000
#
-# Console UART Setup
-#
-# CONFIG_BAUD_9600 is not set
-# CONFIG_BAUD_19200 is not set
-# CONFIG_BAUD_38400 is not set
-CONFIG_BAUD_57600=y
-# CONFIG_BAUD_115200 is not set
-CONFIG_BAUD_NO_PARITY=y
-# CONFIG_BAUD_PARITY is not set
-CONFIG_BAUD_1_STOPBIT=y
-# CONFIG_BAUD_2_STOPBIT is not set
-
-#
# Blackfin Kernel Optimizations
#
@@ -236,6 +282,7 @@ CONFIG_MEMSET_L1=y
CONFIG_MEMCPY_L1=y
CONFIG_SYS_BFIN_SPINLOCK_L1=y
# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
CONFIG_RAMKERNEL=y
@@ -249,6 +296,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
@@ -320,14 +368,7 @@ CONFIG_BINFMT_ZFLAT=y
#
# Power management options
#
-CONFIG_PM=y
-CONFIG_PM_LEGACY=y
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
-# CONFIG_PM_WAKEUP_BY_GPIO is not set
-# CONFIG_PM_WAKEUP_GPIO_API is not set
-CONFIG_PM_WAKEUP_SIC_IWR=0x80000000
+# CONFIG_PM is not set
#
# CPU Frequency scaling
@@ -349,6 +390,7 @@ CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -419,48 +461,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
-CONFIG_IRDA=m
-
-#
-# IrDA protocols
-#
-CONFIG_IRLAN=m
-CONFIG_IRCOMM=m
-# CONFIG_IRDA_ULTRA is not set
-
-#
-# IrDA options
-#
-CONFIG_IRDA_CACHE_LAST_LSAP=y
-# CONFIG_IRDA_FAST_RR is not set
-# CONFIG_IRDA_DEBUG is not set
-
-#
-# Infrared-port device drivers
-#
-
-#
-# SIR device drivers
-#
-CONFIG_IRTTY_SIR=m
-
-#
-# Dongle support
-#
-# CONFIG_DONGLE is not set
-
-#
-# Old SIR device drivers
-#
-# CONFIG_IRPORT_SIR is not set
-
-#
-# Old Serial dongle support
-#
-
-#
-# FIR device drivers
-#
+# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_IEEE80211 is not set
@@ -474,6 +475,8 @@ CONFIG_IRTTY_SIR=m
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
@@ -494,7 +497,7 @@ CONFIG_MTD_PARTITIONS=y
#
# User Modules And Translation Layers
#
-CONFIG_MTD_CHAR=m
+# CONFIG_MTD_CHAR is not set
CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
@@ -507,9 +510,7 @@ CONFIG_MTD_BLOCK=y
# RAM/ROM/Flash chip drivers
#
# CONFIG_MTD_CFI is not set
-CONFIG_MTD_JEDECPROBE=m
-CONFIG_MTD_GEN_PROBE=m
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
@@ -520,12 +521,8 @@ CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_MW320D=m
CONFIG_MTD_RAM=y
-CONFIG_MTD_ROM=m
+# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
# CONFIG_MTD_OBSOLETE_CHIPS is not set
@@ -533,26 +530,13 @@ CONFIG_MTD_ROM=m
# Mapping drivers for chip access
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_BF5xx=m
-CONFIG_BFIN_FLASH_SIZE=0x400000
-CONFIG_EBIU_FLASH_BASE=0x20000000
-
-#
-# FLASH_EBIU_AMBCTL Control
-#
-CONFIG_BFIN_FLASH_BANK_0=0x7BB0
-CONFIG_BFIN_FLASH_BANK_1=0x7BB0
-CONFIG_BFIN_FLASH_BANK_2=0x7BB0
-CONFIG_BFIN_FLASH_BANK_3=0x7BB0
+# CONFIG_MTD_BF5xx is not set
CONFIG_MTD_UCLINUX=y
# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
#
-# CONFIG_MTD_DATAFLASH is not set
-# CONFIG_MTD_M25P80 is not set
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
@@ -568,17 +552,7 @@ CONFIG_MTD_UCLINUX=y
#
# NAND Flash Device Drivers
#
-CONFIG_MTD_NAND=m
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-# CONFIG_MTD_NAND_ECC_SMC is not set
-CONFIG_MTD_NAND_BFIN=m
-CONFIG_BFIN_NAND_BASE=0x20212000
-CONFIG_BFIN_NAND_CLE=2
-CONFIG_BFIN_NAND_ALE=1
-CONFIG_BFIN_NAND_READY=3
-CONFIG_MTD_NAND_IDS=m
-# CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND is not set
#
# OneNAND Flash Device Drivers
@@ -593,6 +567,7 @@ CONFIG_MTD_NAND_IDS=m
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -604,14 +579,12 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -668,11 +641,7 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_SMC91X is not set
-CONFIG_BFIN_MAC=y
-CONFIG_BFIN_MAC_USE_L1=y
-CONFIG_BFIN_TX_DESC_NUM=10
-CONFIG_BFIN_RX_DESC_NUM=20
-# CONFIG_BFIN_MAC_RMII is not set
+# CONFIG_SMSC911X is not set
#
# Ethernet (1000 Mbit)
@@ -724,7 +693,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set
#
@@ -737,8 +706,6 @@ CONFIG_INPUT_EVDEV=m
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_UINPUT is not set
# CONFIG_BF53X_PFBUTTONS is not set
-CONFIG_TWI_KEYPAD=m
-CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
#
# Hardware I/O ports
@@ -751,15 +718,13 @@ CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
#
# CONFIG_AD9960 is not set
# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF533_PFLAGS is not set
+# CONFIG_BF5xx_PFLAGS is not set
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BF5xx_TIMERS is not set
# CONFIG_BF5xx_PPI is not set
-CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_SPORT is not set
# CONFIG_BFIN_TIMER_LATENCY is not set
-CONFIG_TWI_LCD=m
-CONFIG_TWI_LCD_SLAVE_ADDR=34
-# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_FBDMA is not set
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -773,11 +738,13 @@ CONFIG_TWI_LCD_SLAVE_ADDR=34
#
CONFIG_SERIAL_BFIN=y
CONFIG_SERIAL_BFIN_CONSOLE=y
-CONFIG_SERIAL_BFIN_DMA=y
-# CONFIG_SERIAL_BFIN_PIO is not set
-CONFIG_SERIAL_BFIN_UART0=y
-# CONFIG_BFIN_UART0_CTSRTS is not set
-# CONFIG_SERIAL_BFIN_UART1 is not set
+# CONFIG_SERIAL_BFIN_DMA is not set
+CONFIG_SERIAL_BFIN_PIO=y
+# CONFIG_SERIAL_BFIN_UART0 is not set
+CONFIG_SERIAL_BFIN_UART1=y
+# CONFIG_BFIN_UART1_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART2 is not set
+# CONFIG_SERIAL_BFIN_UART3 is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_BFIN_SPORT is not set
@@ -787,14 +754,7 @@ CONFIG_UNIX98_PTYS=y
#
# CAN, the car bus and industrial fieldbus
#
-CONFIG_CAN4LINUX=y
-
-#
-# linux embedded drivers
-#
-# CONFIG_CAN_MCF5282 is not set
-# CONFIG_CAN_UNCTWINCAN is not set
-CONFIG_CAN_BLACKFIN=m
+# CONFIG_CAN4LINUX is not set
#
# IPMI
@@ -807,7 +767,6 @@ CONFIG_CAN_BLACKFIN=m
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_GEN_RTC is not set
-CONFIG_BLACKFIN_DPMC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -820,59 +779,13 @@ CONFIG_BLACKFIN_DPMC=y
#
# I2C support
#
-CONFIG_I2C=m
-CONFIG_I2C_CHARDEV=m
-
-#
-# I2C Algorithms
-#
-# CONFIG_I2C_ALGOBIT is not set
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_BLACKFIN_GPIO is not set
-# CONFIG_I2C_BLACKFIN_TWI is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_SENSORS_DS1337 is not set
-# CONFIG_SENSORS_DS1374 is not set
-CONFIG_SENSORS_AD5252=m
-# CONFIG_SENSORS_EEPROM is not set
-# CONFIG_SENSORS_PCF8574 is not set
-# CONFIG_SENSORS_PCF8575 is not set
-# CONFIG_SENSORS_PCA9543 is not set
-# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_I2C is not set
#
# SPI support
#
-CONFIG_SPI=y
-CONFIG_SPI_MASTER=y
-
-#
-# SPI Master Controller Drivers
-#
-# CONFIG_SPI_BITBANG is not set
-
-#
-# SPI Protocol Masters
-#
-CONFIG_SPI_BFIN=y
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
#
# Dallas's 1-wire bus
@@ -885,48 +798,17 @@ CONFIG_SPI_BFIN=y
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -939,77 +821,19 @@ CONFIG_HWMON=y
#
# Graphics support
#
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB=m
-CONFIG_FB_CFB_FILLRECT=m
-CONFIG_FB_CFB_COPYAREA=m
-CONFIG_FB_CFB_IMAGEBLIT=m
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-CONFIG_FB_BFIN_7171=m
-CONFIG_FB_BFIN_7393=m
-CONFIG_NTSC=y
-# CONFIG_PAL is not set
-# CONFIG_NTSC_640x480 is not set
-# CONFIG_PAL_640x480 is not set
-# CONFIG_NTSC_YCBCR is not set
-# CONFIG_PAL_YCBCR is not set
-CONFIG_ADV7393_1XMEM=y
-# CONFIG_ADV7393_2XMEM is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
#
# Sound
#
-CONFIG_SOUND=m
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=m
-CONFIG_SND_TIMER=m
-CONFIG_SND_PCM=m
-# CONFIG_SND_SEQUENCER is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_PCM_OSS_PLUGINS=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
-CONFIG_SND_VERBOSE_PROCFS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
+# CONFIG_SOUND is not set
#
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -1031,7 +855,6 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
# MMC/SD Card support
#
-# CONFIG_SPI_MMC is not set
# CONFIG_MMC is not set
#
@@ -1075,19 +898,10 @@ CONFIG_RTC_INTF_DEV=y
#
# RTC drivers
#
-# CONFIG_RTC_DRV_X1205 is not set
-# CONFIG_RTC_DRV_DS1307 is not set
# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
-# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
-# CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_TEST is not set
-# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_V3020 is not set
CONFIG_RTC_DRV_BFIN=y
@@ -1105,6 +919,10 @@ CONFIG_RTC_DRV_BFIN=y
#
#
+# Auxiliary Display support
+#
+
+#
# Virtualization
#
@@ -1173,25 +991,8 @@ CONFIG_RAMFS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-CONFIG_YAFFS_FS=m
-CONFIG_YAFFS_YAFFS1=y
-# CONFIG_YAFFS_DOES_ECC is not set
-CONFIG_YAFFS_YAFFS2=y
-CONFIG_YAFFS_AUTO_YAFFS2=y
-# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
-CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
-# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
-# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
-CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
-CONFIG_JFFS2_FS=m
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_YAFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
@@ -1202,20 +1003,9 @@ CONFIG_JFFS2_RTIME=y
#
# Network File Systems
#
-CONFIG_NFS_FS=m
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
-CONFIG_LOCKD=m
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=m
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -1231,46 +1021,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=m
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
#
# Distributed Lock Manager
@@ -1287,13 +1038,35 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+CONFIG_DEBUG_HWERR=y
+# CONFIG_DEBUG_ICACHE_CHECK is not set
+# CONFIG_DEBUG_KERNEL_START is not set
# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
@@ -1317,11 +1090,11 @@ CONFIG_SECURITY_CAPABILITIES=y
# Library routines
#
CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
+# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index e32ca2072cb..51c0b6f9779 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -1,20 +1,21 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19.3
+# Linux kernel version: 2.6.21.5
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
CONFIG_BFIN=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_UCLINUX=y
CONFIG_FORCE_MAX_ZONEORDER=14
CONFIG_IRQCHIP_DEMUX_GPIO=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -33,18 +34,21 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
-# CONFIG_UID16 is not set
+CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -54,9 +58,7 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_EPOLL=y
CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3
-# CONFIG_LIMIT_PAGECACHE is not set
CONFIG_BUDDY=y
# CONFIG_NP2 is not set
CONFIG_SLAB=y
@@ -80,7 +82,9 @@ CONFIG_KMOD=y
# Block layer
#
CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -109,22 +113,30 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF532 is not set
# CONFIG_BF533 is not set
# CONFIG_BF534 is not set
-# CONFIG_BF535 is not set
# CONFIG_BF536 is not set
# CONFIG_BF537 is not set
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
CONFIG_BF561=y
+# CONFIG_BF_REV_0_0 is not set
# CONFIG_BF_REV_0_2 is not set
CONFIG_BF_REV_0_3=y
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
CONFIG_BFIN_DUAL_CORE=y
# CONFIG_BFIN533_EZKIT is not set
# CONFIG_BFIN533_STAMP is not set
# CONFIG_BFIN537_STAMP is not set
# CONFIG_BFIN533_BLUETECHNIX_CM is not set
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
# CONFIG_BFIN561_BLUETECHNIX_CM is not set
CONFIG_BFIN561_EZKIT=y
+# CONFIG_BFIN561_TEPLA is not set
# CONFIG_PNAV10 is not set
# CONFIG_GENERIC_BOARD is not set
CONFIG_MEM_MT48LC16M16A2TG_75=y
@@ -214,6 +226,7 @@ CONFIG_IRQ_WDTIMER=13
#
# Board customizations
#
+# CONFIG_CMDLINE_BOOL is not set
#
# Board Setup
@@ -224,19 +237,6 @@ CONFIG_MEM_ADD_WIDTH=9
CONFIG_BOOT_LOAD=0x1000
#
-# Console UART Setup
-#
-# CONFIG_BAUD_9600 is not set
-# CONFIG_BAUD_19200 is not set
-# CONFIG_BAUD_38400 is not set
-CONFIG_BAUD_57600=y
-# CONFIG_BAUD_115200 is not set
-CONFIG_BAUD_NO_PARITY=y
-# CONFIG_BAUD_PARITY is not set
-CONFIG_BAUD_1_STOPBIT=y
-# CONFIG_BAUD_2_STOPBIT is not set
-
-#
# Blackfin Kernel Optimizations
#
@@ -245,6 +245,7 @@ CONFIG_BAUD_1_STOPBIT=y
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
@@ -263,6 +264,7 @@ CONFIG_MEMSET_L1=y
CONFIG_MEMCPY_L1=y
CONFIG_SYS_BFIN_SPINLOCK_L1=y
# CONFIG_IP_CHECKSUM_L1 is not set
+CONFIG_CACHELINE_ALIGNED_L1=y
# CONFIG_SYSCALL_TAB_L1 is not set
# CONFIG_CPLB_SWITCH_TAB_L1 is not set
CONFIG_RAMKERNEL=y
@@ -276,6 +278,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
@@ -368,6 +371,7 @@ CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -394,6 +398,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -437,7 +442,48 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
# CONFIG_BT is not set
# CONFIG_IEEE80211 is not set
@@ -472,6 +518,7 @@ CONFIG_MTD_PARTITIONS=y
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
@@ -528,6 +575,8 @@ CONFIG_BFIN_FLASH_BANK_3=0x7BB0
#
# Self-contained MTD device drivers
#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
@@ -558,6 +607,7 @@ CONFIG_BFIN_FLASH_BANK_3=0x7BB0
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -569,14 +619,12 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -633,6 +681,7 @@ CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
CONFIG_SMC91X=y
+# CONFIG_SMSC911X is not set
#
# Ethernet (1000 Mbit)
@@ -675,7 +724,26 @@ CONFIG_SMC91X=y
#
# Input device support
#
-# CONFIG_INPUT is not set
+CONFIG_INPUT=m
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
#
# Hardware I/O ports
@@ -688,12 +756,14 @@ CONFIG_SMC91X=y
#
# CONFIG_AD9960 is not set
# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF533_PFLAGS is not set
+# CONFIG_BF5xx_PFLAGS is not set
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BF5xx_TIMERS is not set
# CONFIG_BF5xx_PPI is not set
# CONFIG_BFIN_SPORT is not set
# CONFIG_BFIN_TIMER_LATENCY is not set
+# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_FBDMA is not set
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -730,16 +800,18 @@ CONFIG_UNIX98_PTYS=y
#
# Watchdog Cards
#
-# CONFIG_WATCHDOG is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_BFIN_WDT=y
CONFIG_HW_RANDOM=y
# CONFIG_GEN_RTC is not set
-# CONFIG_BLACKFIN_DPMC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
@@ -755,8 +827,19 @@ CONFIG_HW_RANDOM=y
#
# SPI support
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
#
# Dallas's 1-wire bus
@@ -770,10 +853,17 @@ CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_VT1211 is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -786,9 +876,8 @@ CONFIG_HWMON=y
#
# Graphics support
#
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
#
# Sound
@@ -796,6 +885,12 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -815,6 +910,7 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
# MMC/SD Card support
#
+# CONFIG_SPI_MMC is not set
# CONFIG_MMC is not set
#
@@ -857,6 +953,14 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
# PBX support
#
# CONFIG_PBX is not set
@@ -864,13 +968,9 @@ CONFIG_USB_ARCH_HAS_HCD=y
#
# File systems
#
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-# CONFIG_EXT2_FS_POSIX_ACL is not set
-# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
-CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
@@ -882,7 +982,7 @@ CONFIG_FS_MBCACHE=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
@@ -931,7 +1031,6 @@ CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
-# CONFIG_JFFS_FS is not set
CONFIG_JFFS2_FS=m
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -1022,6 +1121,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1033,20 +1137,17 @@ CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
CONFIG_DEBUG_HUNT_FOR_ZERO=y
# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
# CONFIG_DUAL_CORE_TEST_MODULE is not set
-# CONFIG_BOOTPARAM is not set
-# CONFIG_NO_KERNEL_MSG is not set
CONFIG_CPLB_INFO=y
-# CONFIG_NO_ACCESS_CHECK is not set
+CONFIG_ACCESS_CHECK=y
#
# Security options
@@ -1054,7 +1155,7 @@ CONFIG_CPLB_INFO=y
# CONFIG_KEYS is not set
CONFIG_SECURITY=y
# CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=y
+CONFIG_SECURITY_CAPABILITIES=m
#
# Cryptographic options
@@ -1064,10 +1165,13 @@ CONFIG_SECURITY_CAPABILITIES=y
#
# Library routines
#
-# CONFIG_CRC_CCITT is not set
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/configs/PNAV-10_defconfig b/arch/blackfin/configs/PNAV-10_defconfig
index 97b4ffa2b4a..983ed181c89 100644
--- a/arch/blackfin/configs/PNAV-10_defconfig
+++ b/arch/blackfin/configs/PNAV-10_defconfig
@@ -1,20 +1,21 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19.3
+# Linux kernel version: 2.6.21.5
#
# CONFIG_MMU is not set
# CONFIG_FPU is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
CONFIG_BLACKFIN=y
+CONFIG_ZONE_DMA=y
CONFIG_BFIN=y
CONFIG_SEMAPHORE_SLEEPERS=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+# CONFIG_GENERIC_TIME is not set
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_UCLINUX=y
CONFIG_FORCE_MAX_ZONEORDER=14
CONFIG_IRQCHIP_DEMUX_GPIO=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -33,14 +34,16 @@ CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -54,9 +57,7 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_EPOLL=y
CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=9
-# CONFIG_LIMIT_PAGECACHE is not set
CONFIG_BUDDY=y
# CONFIG_NP2 is not set
CONFIG_SLAB=y
@@ -80,7 +81,9 @@ CONFIG_KMOD=y
# Block layer
#
CONFIG_BLOCK=y
+# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
#
# IO Schedulers
@@ -109,22 +112,31 @@ CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_BF532 is not set
# CONFIG_BF533 is not set
# CONFIG_BF534 is not set
-# CONFIG_BF535 is not set
# CONFIG_BF536 is not set
CONFIG_BF537=y
+# CONFIG_BF542 is not set
+# CONFIG_BF544 is not set
+# CONFIG_BF548 is not set
+# CONFIG_BF549 is not set
# CONFIG_BF561 is not set
+# CONFIG_BF_REV_0_0 is not set
CONFIG_BF_REV_0_2=y
# CONFIG_BF_REV_0_3 is not set
# CONFIG_BF_REV_0_4 is not set
# CONFIG_BF_REV_0_5 is not set
+# CONFIG_BF_REV_ANY is not set
+# CONFIG_BF_REV_NONE is not set
+CONFIG_BF53x=y
CONFIG_BFIN_SINGLE_CORE=y
# CONFIG_BFIN533_EZKIT is not set
# CONFIG_BFIN533_STAMP is not set
# CONFIG_BFIN537_STAMP is not set
# CONFIG_BFIN533_BLUETECHNIX_CM is not set
# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN548_EZKIT is not set
# CONFIG_BFIN561_BLUETECHNIX_CM is not set
# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_BFIN561_TEPLA is not set
CONFIG_PNAV10=y
# CONFIG_GENERIC_BOARD is not set
CONFIG_MEM_MT48LC32M8A2_75=y
@@ -183,6 +195,7 @@ CONFIG_IRQ_WATCH=13
#
# Board customizations
#
+# CONFIG_CMDLINE_BOOL is not set
#
# Board Setup
@@ -193,19 +206,6 @@ CONFIG_MEM_ADD_WIDTH=10
CONFIG_BOOT_LOAD=0x1000
#
-# Console UART Setup
-#
-# CONFIG_BAUD_9600 is not set
-# CONFIG_BAUD_19200 is not set
-# CONFIG_BAUD_38400 is not set
-# CONFIG_BAUD_57600 is not set
-CONFIG_BAUD_115200=y
-CONFIG_BAUD_NO_PARITY=y
-# CONFIG_BAUD_PARITY is not set
-CONFIG_BAUD_1_STOPBIT=y
-# CONFIG_BAUD_2_STOPBIT is not set
-
-#
# Blackfin Kernel Optimizations
#
@@ -214,6 +214,7 @@ CONFIG_BAUD_1_STOPBIT=y
#
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
@@ -232,6 +233,7 @@ CONFIG_MEMSET_L1=y
CONFIG_MEMCPY_L1=y
CONFIG_SYS_BFIN_SPINLOCK_L1=y
CONFIG_IP_CHECKSUM_L1=y
+CONFIG_CACHELINE_ALIGNED_L1=y
CONFIG_SYSCALL_TAB_L1=y
CONFIG_CPLB_SWITCH_TAB_L1=y
CONFIG_RAMKERNEL=y
@@ -245,6 +247,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_LARGE_ALLOCS=y
CONFIG_BFIN_DMA_5XX=y
# CONFIG_DMA_UNCACHED_2M is not set
@@ -338,6 +341,7 @@ CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -364,6 +368,7 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
@@ -442,6 +447,7 @@ CONFIG_MTD_PARTITIONS=y
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
@@ -522,6 +528,7 @@ CONFIG_MTD_NAND_IDS=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -533,14 +540,12 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -602,6 +607,7 @@ CONFIG_BFIN_MAC=y
CONFIG_BFIN_TX_DESC_NUM=100
CONFIG_BFIN_RX_DESC_NUM=100
CONFIG_BFIN_MAC_RMII=y
+# CONFIG_SMSC911X is not set
#
# Ethernet (1000 Mbit)
@@ -674,6 +680,7 @@ CONFIG_TOUCHSCREEN_AD7877=y
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_UCB1400 is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
# CONFIG_BF53X_PFBUTTONS is not set
@@ -690,7 +697,7 @@ CONFIG_INPUT_UINPUT=y
#
# CONFIG_AD9960 is not set
# CONFIG_SPI_ADC_BF533 is not set
-# CONFIG_BF533_PFLAGS is not set
+# CONFIG_BF5xx_PFLAGS is not set
# CONFIG_BF5xx_PPIFCD is not set
# CONFIG_BF5xx_TIMERS is not set
# CONFIG_BF5xx_PPI is not set
@@ -699,6 +706,8 @@ CONFIG_BFIN_SPORT=y
CONFIG_TWI_LCD=m
CONFIG_TWI_LCD_SLAVE_ADDR=34
# CONFIG_AD5304 is not set
+# CONFIG_BF5xx_TEA5764 is not set
+# CONFIG_BF5xx_FBDMA is not set
# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -747,13 +756,8 @@ CONFIG_CAN_BLACKFIN=m
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_GEN_RTC is not set
-CONFIG_BLACKFIN_DPMC=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
@@ -777,9 +781,9 @@ CONFIG_I2C_CHARDEV=y
#
# I2C Hardware Bus support
#
-# CONFIG_I2C_BFIN_GPIO is not set
-CONFIG_I2C_BFIN_TWI=y
-CONFIG_TWICLK_KHZ=50
+# CONFIG_I2C_BLACKFIN_GPIO is not set
+CONFIG_I2C_BLACKFIN_TWI=y
+CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_STUB is not set
@@ -812,12 +816,13 @@ CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
-# CONFIG_SPI_BITBANG is not set
CONFIG_SPI_BFIN=y
+# CONFIG_SPI_BITBANG is not set
#
# SPI Protocol Masters
#
+# CONFIG_SPI_AT25 is not set
#
# Dallas's 1-wire bus
@@ -833,6 +838,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
@@ -857,6 +863,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -864,12 +871,18 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
@@ -882,15 +895,24 @@ CONFIG_HWMON=y
#
# Graphics support
#
-CONFIG_FIRMWARE_EDID=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_BFIN_7171 is not set
# CONFIG_FB_BFIN_7393 is not set
CONFIG_FB_BF537_LQ035=y
@@ -904,11 +926,6 @@ CONFIG_FB_BFIN_LANDSCAPE=y
# Logo configuration
#
# CONFIG_LOGO is not set
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_LCD_DEVICE=y
#
# Sound
@@ -946,14 +963,24 @@ CONFIG_SND_BLACKFIN_AD1981B=m
# CONFIG_SND_BFIN_AD73311 is not set
#
+# SoC audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
# Open Sound System
#
CONFIG_SOUND_PRIME=y
-CONFIG_OSS_OBSOLETE_DRIVER=y
+# CONFIG_OBSOLETE_OSS is not set
# CONFIG_SOUND_MSNDCLAS is not set
# CONFIG_SOUND_MSNDPIN is not set
#
+# HID Devices
+#
+# CONFIG_HID is not set
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1024,7 +1051,6 @@ CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_DRV_DS1672 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
# CONFIG_RTC_DRV_RS5C372 is not set
# CONFIG_RTC_DRV_M48T86 is not set
@@ -1047,6 +1073,14 @@ CONFIG_RTC_DRV_BFIN=y
#
#
+# Auxiliary Display support
+#
+
+#
+# Virtualization
+#
+
+#
# PBX support
#
# CONFIG_PBX is not set
@@ -1121,7 +1155,6 @@ CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
-# CONFIG_JFFS_FS is not set
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
@@ -1204,6 +1237,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_UTF8 is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
# Profiling support
#
# CONFIG_PROFILING is not set
@@ -1215,19 +1253,16 @@ CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
-# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SERIAL_EARLY_INIT is not set
# CONFIG_DEBUG_HUNT_FOR_ZERO is not set
# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
-# CONFIG_BOOTPARAM is not set
-# CONFIG_NO_KERNEL_MSG is not set
# CONFIG_CPLB_INFO is not set
-# CONFIG_NO_ACCESS_CHECK is not set
+# CONFIG_ACCESS_CHECK is not set
#
# Security options
@@ -1245,9 +1280,12 @@ CONFIG_SECURITY_CAPABILITIES=y
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index f3b7d2f9d49..f429ebc3a96 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -6,9 +6,12 @@ extra-y := init_task.o vmlinux.lds
obj-y := \
entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
- sys_bfin.o time.o traps.o irqchip.o dma-mapping.o bfin_gpio.o \
- flat.o
+ sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
+ fixed_code.o cplbinit.o cacheinit.o
+obj-$(CONFIG_BF53x) += bfin_gpio.o
+obj-$(CONFIG_BF561) += bfin_gpio.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o
obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o
+obj-$(CONFIG_KGDB) += kgdb.o
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
index e455f450450..b56b2741cde 100644
--- a/arch/blackfin/kernel/asm-offsets.c
+++ b/arch/blackfin/kernel/asm-offsets.c
@@ -32,11 +32,10 @@
#include <linux/kernel_stat.h>
#include <linux/ptrace.h>
#include <linux/hardirq.h>
-#include <asm/irq.h>
-#include <asm/thread_info.h>
+#include <linux/irq.h>
+#include <linux/thread_info.h>
-#define DEFINE(sym, val) \
- asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
int main(void)
{
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 0ccb0dc3f83..7cf02f02a1d 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -34,6 +34,7 @@
#include <linux/kernel.h>
#include <linux/param.h>
+#include <asm/blackfin.h>
#include <asm/dma.h>
#include <asm/cacheflush.h>
@@ -45,67 +46,6 @@
***************************************************************************/
static struct dma_channel dma_ch[MAX_BLACKFIN_DMA_CHANNEL];
-#if defined (CONFIG_BF561)
-static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
- (struct dma_register *) DMA1_0_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_1_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_2_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_3_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_4_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_5_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_6_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_7_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_8_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_9_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_10_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_11_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_0_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_1_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_2_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_3_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_4_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_5_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_6_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_7_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_8_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_9_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_10_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_11_NEXT_DESC_PTR,
- (struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
- (struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
- (struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
- (struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
- (struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
- (struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
- (struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
- (struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
- (struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
- (struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
- (struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
- (struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
-};
-#else
-static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
- (struct dma_register *) DMA0_NEXT_DESC_PTR,
- (struct dma_register *) DMA1_NEXT_DESC_PTR,
- (struct dma_register *) DMA2_NEXT_DESC_PTR,
- (struct dma_register *) DMA3_NEXT_DESC_PTR,
- (struct dma_register *) DMA4_NEXT_DESC_PTR,
- (struct dma_register *) DMA5_NEXT_DESC_PTR,
- (struct dma_register *) DMA6_NEXT_DESC_PTR,
- (struct dma_register *) DMA7_NEXT_DESC_PTR,
-#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
- (struct dma_register *) DMA8_NEXT_DESC_PTR,
- (struct dma_register *) DMA9_NEXT_DESC_PTR,
- (struct dma_register *) DMA10_NEXT_DESC_PTR,
- (struct dma_register *) DMA11_NEXT_DESC_PTR,
-#endif
- (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
- (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
- (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
- (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
-};
-#endif
/*------------------------------------------------------------------------------
* Set the Buffer Clear bit in the Configuration register of specific DMA
@@ -138,149 +78,6 @@ static int __init blackfin_dma_init(void)
arch_initcall(blackfin_dma_init);
-/*
- * Form the channel find the irq number for that channel.
- */
-#if !defined(CONFIG_BF561)
-
-static int bf533_channel2irq(unsigned int channel)
-{
- int ret_irq = -1;
-
- switch (channel) {
- case CH_PPI:
- ret_irq = IRQ_PPI;
- break;
-
-#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
- case CH_EMAC_RX:
- ret_irq = IRQ_MAC_RX;
- break;
-
- case CH_EMAC_TX:
- ret_irq = IRQ_MAC_TX;
- break;
-
- case CH_UART1_RX:
- ret_irq = IRQ_UART1_RX;
- break;
-
- case CH_UART1_TX:
- ret_irq = IRQ_UART1_TX;
- break;
-#endif
-
- case CH_SPORT0_RX:
- ret_irq = IRQ_SPORT0_RX;
- break;
-
- case CH_SPORT0_TX:
- ret_irq = IRQ_SPORT0_TX;
- break;
-
- case CH_SPORT1_RX:
- ret_irq = IRQ_SPORT1_RX;
- break;
-
- case CH_SPORT1_TX:
- ret_irq = IRQ_SPORT1_TX;
- break;
-
- case CH_SPI:
- ret_irq = IRQ_SPI;
- break;
-
- case CH_UART_RX:
- ret_irq = IRQ_UART_RX;
- break;
-
- case CH_UART_TX:
- ret_irq = IRQ_UART_TX;
- break;
-
- case CH_MEM_STREAM0_SRC:
- case CH_MEM_STREAM0_DEST:
- ret_irq = IRQ_MEM_DMA0;
- break;
-
- case CH_MEM_STREAM1_SRC:
- case CH_MEM_STREAM1_DEST:
- ret_irq = IRQ_MEM_DMA1;
- break;
- }
- return ret_irq;
-}
-
-# define channel2irq(channel) bf533_channel2irq(channel)
-
-#else
-
-static int bf561_channel2irq(unsigned int channel)
-{
- int ret_irq = -1;
-
- switch (channel) {
- case CH_PPI0:
- ret_irq = IRQ_PPI0;
- break;
- case CH_PPI1:
- ret_irq = IRQ_PPI1;
- break;
- case CH_SPORT0_RX:
- ret_irq = IRQ_SPORT0_RX;
- break;
- case CH_SPORT0_TX:
- ret_irq = IRQ_SPORT0_TX;
- break;
- case CH_SPORT1_RX:
- ret_irq = IRQ_SPORT1_RX;
- break;
- case CH_SPORT1_TX:
- ret_irq = IRQ_SPORT1_TX;
- break;
- case CH_SPI:
- ret_irq = IRQ_SPI;
- break;
- case CH_UART_RX:
- ret_irq = IRQ_UART_RX;
- break;
- case CH_UART_TX:
- ret_irq = IRQ_UART_TX;
- break;
-
- case CH_MEM_STREAM0_SRC:
- case CH_MEM_STREAM0_DEST:
- ret_irq = IRQ_MEM_DMA0;
- break;
- case CH_MEM_STREAM1_SRC:
- case CH_MEM_STREAM1_DEST:
- ret_irq = IRQ_MEM_DMA1;
- break;
- case CH_MEM_STREAM2_SRC:
- case CH_MEM_STREAM2_DEST:
- ret_irq = IRQ_MEM_DMA2;
- break;
- case CH_MEM_STREAM3_SRC:
- case CH_MEM_STREAM3_DEST:
- ret_irq = IRQ_MEM_DMA3;
- break;
-
- case CH_IMEM_STREAM0_SRC:
- case CH_IMEM_STREAM0_DEST:
- ret_irq = IRQ_IMEM_DMA0;
- break;
- case CH_IMEM_STREAM1_SRC:
- case CH_IMEM_STREAM1_DEST:
- ret_irq = IRQ_IMEM_DMA1;
- break;
- }
- return ret_irq;
-}
-
-# define channel2irq(channel) bf561_channel2irq(channel)
-
-#endif
-
/*------------------------------------------------------------------------------
* Request the specific DMA channel from the system.
*-----------------------------------------------------------------------------*/
@@ -535,7 +332,7 @@ set_bfin_dma_config(char direction, char flow_mode,
}
EXPORT_SYMBOL(set_bfin_dma_config);
-void set_dma_sg(unsigned int channel, struct dmasg * sg, int nr_sg)
+void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg)
{
BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
&& channel < MAX_BLACKFIN_DMA_CHANNEL));
@@ -595,7 +392,7 @@ unsigned short get_dma_curr_ycount(unsigned int channel)
}
EXPORT_SYMBOL(get_dma_curr_ycount);
-void *_dma_memcpy(void *dest, const void *src, size_t size)
+static void *__dma_memcpy(void *dest, const void *src, size_t size)
{
int direction; /* 1 - address decrease, 0 - address increase */
int flag_align; /* 1 - address aligned, 0 - address unaligned */
@@ -604,7 +401,7 @@ void *_dma_memcpy(void *dest, const void *src, size_t size)
if (size <= 0)
return NULL;
-
+
local_irq_save(flags);
if ((unsigned long)src < memory_end)
@@ -744,11 +541,10 @@ void *dma_memcpy(void *dest, const void *src, size_t size)
bulk = (size >> 16) << 16;
rest = size - bulk;
if (bulk)
- _dma_memcpy(dest, src, bulk);
- addr = _dma_memcpy(dest+bulk, src+bulk, rest);
+ __dma_memcpy(dest, src, bulk);
+ addr = __dma_memcpy(dest+bulk, src+bulk, rest);
return addr;
}
-
EXPORT_SYMBOL(dma_memcpy);
void *safe_dma_memcpy(void *dest, const void *src, size_t size)
@@ -761,14 +557,13 @@ EXPORT_SYMBOL(safe_dma_memcpy);
void dma_outsb(void __iomem *addr, const void *buf, unsigned short len)
{
-
unsigned long flags;
-
+
local_irq_save(flags);
-
- blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
- bfin_write_MDMA_D0_START_ADDR(addr);
+ blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+ bfin_write_MDMA_D0_START_ADDR(addr);
bfin_write_MDMA_D0_X_COUNT(len);
bfin_write_MDMA_D0_X_MODIFY(0);
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -796,9 +591,9 @@ EXPORT_SYMBOL(dma_outsb);
void dma_insb(const void __iomem *addr, void *buf, unsigned short len)
{
unsigned long flags;
-
+
local_irq_save(flags);
- bfin_write_MDMA_D0_START_ADDR(buf);
+ bfin_write_MDMA_D0_START_ADDR(buf);
bfin_write_MDMA_D0_X_COUNT(len);
bfin_write_MDMA_D0_X_MODIFY(1);
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -827,12 +622,12 @@ EXPORT_SYMBOL(dma_insb);
void dma_outsw(void __iomem *addr, const void *buf, unsigned short len)
{
unsigned long flags;
-
+
local_irq_save(flags);
-
- blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
- bfin_write_MDMA_D0_START_ADDR(addr);
+ blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+ bfin_write_MDMA_D0_START_ADDR(addr);
bfin_write_MDMA_D0_X_COUNT(len);
bfin_write_MDMA_D0_X_MODIFY(0);
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -859,10 +654,10 @@ EXPORT_SYMBOL(dma_outsw);
void dma_insw(const void __iomem *addr, void *buf, unsigned short len)
{
unsigned long flags;
-
+
local_irq_save(flags);
-
- bfin_write_MDMA_D0_START_ADDR(buf);
+
+ bfin_write_MDMA_D0_START_ADDR(buf);
bfin_write_MDMA_D0_X_COUNT(len);
bfin_write_MDMA_D0_X_MODIFY(2);
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -891,12 +686,12 @@ EXPORT_SYMBOL(dma_insw);
void dma_outsl(void __iomem *addr, const void *buf, unsigned short len)
{
unsigned long flags;
-
+
local_irq_save(flags);
-
- blackfin_dcache_flush_range((unsigned int)buf,(unsigned int)(buf) + len);
- bfin_write_MDMA_D0_START_ADDR(addr);
+ blackfin_dcache_flush_range((unsigned int)buf, (unsigned int)(buf) + len);
+
+ bfin_write_MDMA_D0_START_ADDR(addr);
bfin_write_MDMA_D0_X_COUNT(len);
bfin_write_MDMA_D0_X_MODIFY(0);
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
@@ -923,10 +718,10 @@ EXPORT_SYMBOL(dma_outsl);
void dma_insl(const void __iomem *addr, void *buf, unsigned short len)
{
unsigned long flags;
-
+
local_irq_save(flags);
-
- bfin_write_MDMA_D0_START_ADDR(buf);
+
+ bfin_write_MDMA_D0_START_ADDR(buf);
bfin_write_MDMA_D0_X_COUNT(len);
bfin_write_MDMA_D0_X_MODIFY(4);
bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c
index 3f49fae1cb1..bafcfa52142 100644
--- a/arch/blackfin/kernel/bfin_gpio.c
+++ b/arch/blackfin/kernel/bfin_gpio.c
@@ -138,7 +138,7 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INT
inline int check_gpio(unsigned short gpio)
{
- if (gpio > MAX_BLACKFIN_GPIOS)
+ if (gpio >= MAX_BLACKFIN_GPIOS)
return -EINVAL;
return 0;
}
@@ -162,7 +162,7 @@ static void port_setup(unsigned short gpio, unsigned short usage)
static void default_gpio(unsigned short gpio)
{
- unsigned short bank,bitmask;
+ unsigned short bank, bitmask;
bank = gpio_bank(gpio);
bitmask = gpio_bit(gpio);
@@ -183,7 +183,7 @@ static int __init bfin_gpio_init(void)
printk(KERN_INFO "Blackfin GPIO Controller\n");
- for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE)
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE)
reserved_map[gpio_bank(i)] = 0;
#if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
@@ -478,7 +478,7 @@ u32 gpio_pm_setup(void)
u32 sic_iwr = 0;
u16 bank, mask, i, gpio;
- for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
mask = wakeup_map[gpio_bank(i)];
bank = gpio_bank(i);
@@ -494,19 +494,24 @@ u32 gpio_pm_setup(void)
gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir;
gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge;
gpio_bank_saved[bank].both = gpio_bankb[bank]->both;
+ gpio_bank_saved[bank].reserved = reserved_map[bank];
gpio = i;
while (mask) {
if (mask & 1) {
- bfin_gpio_wakeup_type(gpio, wakeup_flags_map[gpio]);
+ reserved_map[gpio_bank(gpio)] |=
+ gpio_bit(gpio);
+ bfin_gpio_wakeup_type(gpio,
+ wakeup_flags_map[gpio]);
set_gpio_data(gpio, 0); /*Clear*/
}
gpio++;
mask >>= 1;
}
- sic_iwr |= 1 << (sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));
+ sic_iwr |= 1 <<
+ (sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));
gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];
}
}
@@ -517,12 +522,11 @@ u32 gpio_pm_setup(void)
return IWR_ENABLE_ALL;
}
-
void gpio_pm_restore(void)
{
u16 bank, mask, i;
- for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) {
mask = wakeup_map[gpio_bank(i)];
bank = gpio_bank(i);
@@ -535,6 +539,9 @@ void gpio_pm_restore(void)
gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge;
gpio_bankb[bank]->both = gpio_bank_saved[bank].both;
+
+ reserved_map[bank] = gpio_bank_saved[bank].reserved;
+
}
gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;
@@ -583,7 +590,6 @@ int gpio_request(unsigned short gpio, const char *label)
}
EXPORT_SYMBOL(gpio_request);
-
void gpio_free(unsigned short gpio)
{
unsigned long flags;
@@ -608,7 +614,6 @@ void gpio_free(unsigned short gpio)
}
EXPORT_SYMBOL(gpio_free);
-
void gpio_direction_input(unsigned short gpio)
{
unsigned long flags;
diff --git a/arch/blackfin/kernel/bfin_ksyms.c b/arch/blackfin/kernel/bfin_ksyms.c
index f64ecb638fa..70455949cfd 100644
--- a/arch/blackfin/kernel/bfin_ksyms.c
+++ b/arch/blackfin/kernel/bfin_ksyms.c
@@ -28,10 +28,11 @@
*/
#include <linux/module.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
+#include <linux/uaccess.h>
+
#include <asm/checksum.h>
#include <asm/cacheflush.h>
-#include <asm/uaccess.h>
/* platform dependent support */
diff --git a/arch/blackfin/kernel/cacheinit.c b/arch/blackfin/kernel/cacheinit.c
new file mode 100644
index 00000000000..4d41a40e813
--- /dev/null
+++ b/arch/blackfin/kernel/cacheinit.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/cpu.h>
+
+#include <asm/cacheflush.h>
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+
+#if defined(CONFIG_BLKFIN_CACHE)
+void bfin_icache_init(void)
+{
+ unsigned long *table = icplb_table;
+ unsigned long ctrl;
+ int i;
+
+ for (i = 0; i < MAX_CPLBS; i++) {
+ unsigned long addr = *table++;
+ unsigned long data = *table++;
+ if (addr == (unsigned long)-1)
+ break;
+ bfin_write32(ICPLB_ADDR0 + i * 4, addr);
+ bfin_write32(ICPLB_DATA0 + i * 4, data);
+ }
+ ctrl = bfin_read_IMEM_CONTROL();
+ ctrl |= IMC | ENICPLB;
+ bfin_write_IMEM_CONTROL(ctrl);
+}
+#endif
+
+#if defined(CONFIG_BLKFIN_DCACHE)
+void bfin_dcache_init(void)
+{
+ unsigned long *table = dcplb_table;
+ unsigned long ctrl;
+ int i;
+
+ for (i = 0; i < MAX_CPLBS; i++) {
+ unsigned long addr = *table++;
+ unsigned long data = *table++;
+ if (addr == (unsigned long)-1)
+ break;
+ bfin_write32(DCPLB_ADDR0 + i * 4, addr);
+ bfin_write32(DCPLB_DATA0 + i * 4, data);
+ }
+ ctrl = bfin_read_DMEM_CONTROL();
+ ctrl |= DMEM_CNTR;
+ bfin_write_DMEM_CONTROL(ctrl);
+}
+#endif
diff --git a/arch/blackfin/kernel/cplbinit.c b/arch/blackfin/kernel/cplbinit.c
new file mode 100644
index 00000000000..bbdb403fcb5
--- /dev/null
+++ b/arch/blackfin/kernel/cplbinit.c
@@ -0,0 +1,433 @@
+/*
+ * Blackfin CPLB initialization
+ *
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/module.h>
+
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+
+u_long icplb_table[MAX_CPLBS+1];
+u_long dcplb_table[MAX_CPLBS+1];
+
+#ifdef CONFIG_CPLB_SWITCH_TAB_L1
+u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
+u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
+
+#ifdef CONFIG_CPLB_INFO
+u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
+u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
+#endif /* CONFIG_CPLB_INFO */
+
+#else
+
+u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
+u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
+
+#ifdef CONFIG_CPLB_INFO
+u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
+u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
+#endif /* CONFIG_CPLB_INFO */
+
+#endif /*CONFIG_CPLB_SWITCH_TAB_L1*/
+
+struct s_cplb {
+ struct cplb_tab init_i;
+ struct cplb_tab init_d;
+ struct cplb_tab switch_i;
+ struct cplb_tab switch_d;
+};
+
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+static struct cplb_desc cplb_data[] = {
+ {
+ .start = 0,
+ .end = SIZE_1K,
+ .psize = SIZE_1K,
+ .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
+ .i_conf = SDRAM_OOPS,
+ .d_conf = SDRAM_OOPS,
+#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
+ .valid = 1,
+#else
+ .valid = 0,
+#endif
+ .name = "ZERO Pointer Saveguard",
+ },
+ {
+ .start = L1_CODE_START,
+ .end = L1_CODE_START + L1_CODE_LENGTH,
+ .psize = SIZE_4M,
+ .attr = INITIAL_T | SWITCH_T | I_CPLB,
+ .i_conf = L1_IMEMORY,
+ .d_conf = 0,
+ .valid = 1,
+ .name = "L1 I-Memory",
+ },
+ {
+ .start = L1_DATA_A_START,
+ .end = L1_DATA_B_START + L1_DATA_B_LENGTH,
+ .psize = SIZE_4M,
+ .attr = INITIAL_T | SWITCH_T | D_CPLB,
+ .i_conf = 0,
+ .d_conf = L1_DMEMORY,
+#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
+ .valid = 1,
+#else
+ .valid = 0,
+#endif
+ .name = "L1 D-Memory",
+ },
+ {
+ .start = 0,
+ .end = 0, /* dynamic */
+ .psize = 0,
+ .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
+ .i_conf = SDRAM_IGENERIC,
+ .d_conf = SDRAM_DGENERIC,
+ .valid = 1,
+ .name = "SDRAM Kernel",
+ },
+ {
+ .start = 0, /* dynamic */
+ .end = 0, /* dynamic */
+ .psize = 0,
+ .attr = INITIAL_T | SWITCH_T | D_CPLB,
+ .i_conf = SDRAM_IGENERIC,
+ .d_conf = SDRAM_DNON_CHBL,
+ .valid = 1,
+ .name = "SDRAM RAM MTD",
+ },
+ {
+ .start = 0, /* dynamic */
+ .end = 0, /* dynamic */
+ .psize = SIZE_1M,
+ .attr = INITIAL_T | SWITCH_T | D_CPLB,
+ .d_conf = SDRAM_DNON_CHBL,
+ .valid = 1,
+ .name = "SDRAM Uncached DMA ZONE",
+ },
+ {
+ .start = 0, /* dynamic */
+ .end = 0, /* dynamic */
+ .psize = 0,
+ .attr = SWITCH_T | D_CPLB,
+ .i_conf = 0, /* dynamic */
+ .d_conf = 0, /* dynamic */
+ .valid = 1,
+ .name = "SDRAM Reserved Memory",
+ },
+ {
+ .start = ASYNC_BANK0_BASE,
+ .end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
+ .psize = 0,
+ .attr = SWITCH_T | D_CPLB,
+ .d_conf = SDRAM_EBIU,
+ .valid = 1,
+ .name = "ASYNC Memory",
+ },
+ {
+#if defined(CONFIG_BF561)
+ .start = L2_SRAM,
+ .end = L2_SRAM_END,
+ .psize = SIZE_1M,
+ .attr = SWITCH_T | D_CPLB,
+ .i_conf = L2_MEMORY,
+ .d_conf = L2_MEMORY,
+ .valid = 1,
+#else
+ .valid = 0,
+#endif
+ .name = "L2 Memory",
+ }
+};
+
+static u16 __init lock_kernel_check(u32 start, u32 end)
+{
+ if ((start <= (u32) _stext && end >= (u32) _end)
+ || (start >= (u32) _stext && end <= (u32) _end))
+ return IN_KERNEL;
+ return 0;
+}
+
+static unsigned short __init
+fill_cplbtab(struct cplb_tab *table,
+ unsigned long start, unsigned long end,
+ unsigned long block_size, unsigned long cplb_data)
+{
+ int i;
+
+ switch (block_size) {
+ case SIZE_4M:
+ i = 3;
+ break;
+ case SIZE_1M:
+ i = 2;
+ break;
+ case SIZE_4K:
+ i = 1;
+ break;
+ case SIZE_1K:
+ default:
+ i = 0;
+ break;
+ }
+
+ cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
+
+ while ((start < end) && (table->pos < table->size)) {
+
+ table->tab[table->pos++] = start;
+
+ if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
+ table->tab[table->pos++] =
+ cplb_data | CPLB_LOCK | CPLB_DIRTY;
+ else
+ table->tab[table->pos++] = cplb_data;
+
+ start += block_size;
+ }
+ return 0;
+}
+
+static unsigned short __init
+close_cplbtab(struct cplb_tab *table)
+{
+
+ while (table->pos < table->size) {
+
+ table->tab[table->pos++] = 0;
+ table->tab[table->pos++] = 0; /* !CPLB_VALID */
+ }
+ return 0;
+}
+
+/* helper function */
+static void __fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+{
+ if (cplb_data[i].psize) {
+ fill_cplbtab(t,
+ cplb_data[i].start,
+ cplb_data[i].end,
+ cplb_data[i].psize,
+ cplb_data[i].i_conf);
+ } else {
+#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+ if (i == SDRAM_KERN) {
+ fill_cplbtab(t,
+ cplb_data[i].start,
+ cplb_data[i].end,
+ SIZE_4M,
+ cplb_data[i].i_conf);
+ } else
+#endif
+ {
+ fill_cplbtab(t,
+ cplb_data[i].start,
+ a_start,
+ SIZE_1M,
+ cplb_data[i].i_conf);
+ fill_cplbtab(t,
+ a_start,
+ a_end,
+ SIZE_4M,
+ cplb_data[i].i_conf);
+ fill_cplbtab(t, a_end,
+ cplb_data[i].end,
+ SIZE_1M,
+ cplb_data[i].i_conf);
+ }
+ }
+}
+
+static void __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
+{
+ if (cplb_data[i].psize) {
+ fill_cplbtab(t,
+ cplb_data[i].start,
+ cplb_data[i].end,
+ cplb_data[i].psize,
+ cplb_data[i].d_conf);
+ } else {
+ fill_cplbtab(t,
+ cplb_data[i].start,
+ a_start, SIZE_1M,
+ cplb_data[i].d_conf);
+ fill_cplbtab(t, a_start,
+ a_end, SIZE_4M,
+ cplb_data[i].d_conf);
+ fill_cplbtab(t, a_end,
+ cplb_data[i].end,
+ SIZE_1M,
+ cplb_data[i].d_conf);
+ }
+}
+
+void __init generate_cpl_tables(void)
+{
+
+ u16 i, j, process;
+ u32 a_start, a_end, as, ae, as_1m;
+
+ struct cplb_tab *t_i = NULL;
+ struct cplb_tab *t_d = NULL;
+ struct s_cplb cplb;
+
+ cplb.init_i.size = MAX_CPLBS;
+ cplb.init_d.size = MAX_CPLBS;
+ cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
+ cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
+
+ cplb.init_i.pos = 0;
+ cplb.init_d.pos = 0;
+ cplb.switch_i.pos = 0;
+ cplb.switch_d.pos = 0;
+
+ cplb.init_i.tab = icplb_table;
+ cplb.init_d.tab = dcplb_table;
+ cplb.switch_i.tab = ipdt_table;
+ cplb.switch_d.tab = dpdt_table;
+
+ cplb_data[SDRAM_KERN].end = memory_end;
+
+#ifdef CONFIG_MTD_UCLINUX
+ cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
+ cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
+ cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
+# if defined(CONFIG_ROMFS_FS)
+ cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
+
+ /*
+ * The ROMFS_FS size is often not multiple of 1MB.
+ * This can cause multiple CPLB sets covering the same memory area.
+ * This will then cause multiple CPLB hit exceptions.
+ * Workaround: We ensure a contiguous memory area by extending the kernel
+ * memory section over the mtd section.
+ * For ROMFS_FS memory must be covered with ICPLBs anyways.
+ * So there is no difference between kernel and mtd memory setup.
+ */
+
+ cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
+ cplb_data[SDRAM_RAM_MTD].valid = 0;
+
+# endif
+#else
+ cplb_data[SDRAM_RAM_MTD].valid = 0;
+#endif
+
+ cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
+ cplb_data[SDRAM_DMAZ].end = _ramend;
+
+ cplb_data[RES_MEM].start = _ramend;
+ cplb_data[RES_MEM].end = physical_mem_end;
+
+ if (reserved_mem_dcache_on)
+ cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
+ else
+ cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
+
+ if (reserved_mem_icache_on)
+ cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
+ else
+ cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
+
+ for (i = ZERO_P; i <= L2_MEM; i++) {
+ if (!cplb_data[i].valid)
+ continue;
+
+ as_1m = cplb_data[i].start % SIZE_1M;
+
+ /* We need to make sure all sections are properly 1M aligned
+ * However between Kernel Memory and the Kernel mtd section, depending on the
+ * rootfs size, there can be overlapping memory areas.
+ */
+
+ if (as_1m && i != L1I_MEM && i != L1D_MEM) {
+#ifdef CONFIG_MTD_UCLINUX
+ if (i == SDRAM_RAM_MTD) {
+ if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
+ cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
+ else
+ cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
+ } else
+#endif
+ printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
+ cplb_data[i].name, cplb_data[i].start);
+ }
+
+ as = cplb_data[i].start % SIZE_4M;
+ ae = cplb_data[i].end % SIZE_4M;
+
+ if (as)
+ a_start = cplb_data[i].start + (SIZE_4M - (as));
+ else
+ a_start = cplb_data[i].start;
+
+ a_end = cplb_data[i].end - ae;
+
+ for (j = INITIAL_T; j <= SWITCH_T; j++) {
+
+ switch (j) {
+ case INITIAL_T:
+ if (cplb_data[i].attr & INITIAL_T) {
+ t_i = &cplb.init_i;
+ t_d = &cplb.init_d;
+ process = 1;
+ } else
+ process = 0;
+ break;
+ case SWITCH_T:
+ if (cplb_data[i].attr & SWITCH_T) {
+ t_i = &cplb.switch_i;
+ t_d = &cplb.switch_d;
+ process = 1;
+ } else
+ process = 0;
+ break;
+ default:
+ process = 0;
+ break;
+ }
+
+ if (!process)
+ continue;
+ if (cplb_data[i].attr & I_CPLB)
+ __fill_code_cplbtab(t_i, i, a_start, a_end);
+
+ if (cplb_data[i].attr & D_CPLB)
+ __fill_data_cplbtab(t_d, i, a_start, a_end);
+ }
+ }
+
+/* close tables */
+
+ close_cplbtab(&cplb.init_i);
+ close_cplbtab(&cplb.init_d);
+
+ cplb.init_i.tab[cplb.init_i.pos] = -1;
+ cplb.init_d.tab[cplb.init_d.pos] = -1;
+ cplb.switch_i.tab[cplb.switch_i.pos] = -1;
+ cplb.switch_d.tab[cplb.switch_d.pos] = -1;
+
+}
+
+#endif
+
diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c
index 539eb24e062..ea48d5b13f1 100644
--- a/arch/blackfin/kernel/dma-mapping.c
+++ b/arch/blackfin/kernel/dma-mapping.c
@@ -34,8 +34,8 @@
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/io.h>
#include <asm/cacheflush.h>
-#include <asm/io.h>
#include <asm/bfin-global.h>
static spinlock_t dma_page_lock;
@@ -159,10 +159,13 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
BUG_ON(direction == DMA_NONE);
- for (i = 0; i < nents; i++)
- invalidate_dcache_range(sg_dma_address(&sg[i]),
- sg_dma_address(&sg[i]) +
- sg_dma_len(&sg[i]));
+ for (i = 0; i < nents; i++, sg++) {
+ sg->dma_address = page_address(sg->page) + sg->offset;
+
+ invalidate_dcache_range(sg_dma_address(sg),
+ sg_dma_address(sg) +
+ sg_dma_len(sg));
+ }
return nents;
}
diff --git a/arch/blackfin/kernel/dualcore_test.c b/arch/blackfin/kernel/dualcore_test.c
index 8b89c99f9df..0fcba74840b 100644
--- a/arch/blackfin/kernel/dualcore_test.c
+++ b/arch/blackfin/kernel/dualcore_test.c
@@ -30,19 +30,19 @@
#include <linux/init.h>
#include <linux/module.h>
-static int *testarg = (int*)0xfeb00000;
+static int *testarg = (int *)0xfeb00000;
static int test_init(void)
{
*testarg = 1;
- printk("Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
+ printk(KERN_INFO "Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
*testarg, testarg);
return 0;
}
static void test_exit(void)
{
- printk("Dual core test module removed: testarg = [%d]\n", *testarg);
+ printk(KERN_INFO "Dual core test module removed: testarg = [%d]\n", *testarg);
}
module_init(test_init);
diff --git a/arch/blackfin/kernel/entry.S b/arch/blackfin/kernel/entry.S
index 5880b270bd5..65c5ba4260b 100644
--- a/arch/blackfin/kernel/entry.S
+++ b/arch/blackfin/kernel/entry.S
@@ -58,10 +58,12 @@ ENTRY(_ret_from_fork)
RESTORE_ALL_SYS
p0 = reti;
jump (p0);
+ENDPROC(_ret_from_fork)
ENTRY(_sys_fork)
r0 = -EINVAL;
rts;
+ENDPROC(_sys_fork)
ENTRY(_sys_vfork)
r0 = sp;
@@ -72,6 +74,7 @@ ENTRY(_sys_vfork)
SP += 12;
rets = [sp++];
rts;
+ENDPROC(_sys_vfork)
ENTRY(_sys_clone)
r0 = sp;
@@ -82,6 +85,7 @@ ENTRY(_sys_clone)
SP += 12;
rets = [sp++];
rts;
+ENDPROC(_sys_clone)
ENTRY(_sys_rt_sigreturn)
r0 = sp;
@@ -92,3 +96,4 @@ ENTRY(_sys_rt_sigreturn)
SP += 12;
rets = [sp++];
rts;
+ENDPROC(_sys_rt_sigreturn)
diff --git a/arch/blackfin/kernel/fixed_code.S b/arch/blackfin/kernel/fixed_code.S
new file mode 100644
index 00000000000..d8b1ebc7099
--- /dev/null
+++ b/arch/blackfin/kernel/fixed_code.S
@@ -0,0 +1,132 @@
+/*
+ * This file contains sequences of code that will be copied to a
+ * fixed location, defined in <asm/atomic_seq.h>. The interrupt
+ * handlers ensure that these sequences appear to be atomic when
+ * executed from userspace.
+ * These are aligned to 16 bytes, so that we have some space to replace
+ * these sequences with something else (e.g. kernel traps if we ever do
+ * BF561 SMP).
+ */
+#include <linux/linkage.h>
+#include <linux/unistd.h>
+#include <asm/entry.h>
+
+.text
+ENTRY(_fixed_code_start)
+
+.align 16
+ENTRY(_sigreturn_stub)
+ P0 = __NR_rt_sigreturn;
+ EXCPT 0;
+ /* Speculative execution paranoia. */
+0: JUMP.S 0b;
+ENDPROC (_sigreturn_stub)
+
+.align 16
+ /*
+ * Atomic swap, 8 bit.
+ * Inputs: P0: memory address to use
+ * R1: value to store
+ * Output: R0: old contents of the memory address, zero extended.
+ */
+ENTRY(_atomic_xchg32)
+ R0 = [P0];
+ [P0] = R1;
+ rts;
+ENDPROC (_atomic_xchg32)
+
+.align 16
+ /*
+ * Compare and swap, 32 bit.
+ * Inputs: P0: memory address to use
+ * R1: compare value
+ * R2: new value to store
+ * The new value is stored if the contents of the memory
+ * address is equal to the compare value.
+ * Output: R0: old contents of the memory address.
+ */
+ENTRY(_atomic_cas32)
+ R0 = [P0];
+ CC = R0 == R1;
+ IF !CC JUMP 1f;
+ [P0] = R2;
+1:
+ rts;
+ENDPROC (_atomic_cas32)
+
+.align 16
+ /*
+ * Atomic add, 32 bit.
+ * Inputs: P0: memory address to use
+ * R0: value to add
+ * Outputs: R0: new contents of the memory address.
+ * R1: previous contents of the memory address.
+ */
+ENTRY(_atomic_add32)
+ R1 = [P0];
+ R0 = R1 + R0;
+ [P0] = R0;
+ rts;
+ENDPROC (_atomic_add32)
+
+.align 16
+ /*
+ * Atomic sub, 32 bit.
+ * Inputs: P0: memory address to use
+ * R0: value to subtract
+ * Outputs: R0: new contents of the memory address.
+ * R1: previous contents of the memory address.
+ */
+ENTRY(_atomic_sub32)
+ R1 = [P0];
+ R0 = R1 - R0;
+ [P0] = R0;
+ rts;
+ENDPROC (_atomic_sub32)
+
+.align 16
+ /*
+ * Atomic ior, 32 bit.
+ * Inputs: P0: memory address to use
+ * R0: value to ior
+ * Outputs: R0: new contents of the memory address.
+ * R1: previous contents of the memory address.
+ */
+ENTRY(_atomic_ior32)
+ R1 = [P0];
+ R0 = R1 | R0;
+ [P0] = R0;
+ rts;
+ENDPROC (_atomic_ior32)
+
+.align 16
+ /*
+ * Atomic ior, 32 bit.
+ * Inputs: P0: memory address to use
+ * R0: value to ior
+ * Outputs: R0: new contents of the memory address.
+ * R1: previous contents of the memory address.
+ */
+ENTRY(_atomic_and32)
+ R1 = [P0];
+ R0 = R1 & R0;
+ [P0] = R0;
+ rts;
+ENDPROC (_atomic_ior32)
+
+.align 16
+ /*
+ * Atomic ior, 32 bit.
+ * Inputs: P0: memory address to use
+ * R0: value to ior
+ * Outputs: R0: new contents of the memory address.
+ * R1: previous contents of the memory address.
+ */
+ENTRY(_atomic_xor32)
+ R1 = [P0];
+ R0 = R1 ^ R0;
+ [P0] = R0;
+ rts;
+ENDPROC (_atomic_ior32)
+
+ENTRY(_fixed_code_end)
diff --git a/arch/blackfin/kernel/flat.c b/arch/blackfin/kernel/flat.c
index a92587b628b..d188b243053 100644
--- a/arch/blackfin/kernel/flat.c
+++ b/arch/blackfin/kernel/flat.c
@@ -36,24 +36,22 @@ unsigned long bfin_get_addr_from_rp(unsigned long *ptr,
unsigned long val;
switch (type) {
- case FLAT_BFIN_RELOC_TYPE_16_BIT:
- case FLAT_BFIN_RELOC_TYPE_16H_BIT:
- usptr = (unsigned short *)ptr;
- pr_debug("*usptr = %x", get_unaligned(usptr));
- val = get_unaligned(usptr);
- val += *persistent;
- break;
+ case FLAT_BFIN_RELOC_TYPE_16_BIT:
+ case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+ usptr = (unsigned short *)ptr;
+ pr_debug("*usptr = %x", get_unaligned(usptr));
+ val = get_unaligned(usptr);
+ val += *persistent;
+ break;
- case FLAT_BFIN_RELOC_TYPE_32_BIT:
- pr_debug("*ptr = %lx", get_unaligned(ptr));
- val = get_unaligned(ptr);
- break;
+ case FLAT_BFIN_RELOC_TYPE_32_BIT:
+ pr_debug("*ptr = %lx", get_unaligned(ptr));
+ val = get_unaligned(ptr);
+ break;
- default:
- pr_debug("BINFMT_FLAT: Unknown relocation type %x\n",
- type);
-
- return 0;
+ default:
+ pr_debug("BINFMT_FLAT: Unknown relocation type %x\n", type);
+ return 0;
}
/*
@@ -81,21 +79,20 @@ void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
int type = (relval >> 26) & 7;
switch (type) {
- case FLAT_BFIN_RELOC_TYPE_16_BIT:
- put_unaligned(addr, usptr);
- pr_debug("new value %x at %p", get_unaligned(usptr),
- usptr);
- break;
+ case FLAT_BFIN_RELOC_TYPE_16_BIT:
+ put_unaligned(addr, usptr);
+ pr_debug("new value %x at %p", get_unaligned(usptr), usptr);
+ break;
- case FLAT_BFIN_RELOC_TYPE_16H_BIT:
- put_unaligned(addr >> 16, usptr);
- pr_debug("new value %x", get_unaligned(usptr));
- break;
+ case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+ put_unaligned(addr >> 16, usptr);
+ pr_debug("new value %x", get_unaligned(usptr));
+ break;
- case FLAT_BFIN_RELOC_TYPE_32_BIT:
- put_unaligned(addr, ptr);
- pr_debug("new ptr =%lx", get_unaligned(ptr));
- break;
+ case FLAT_BFIN_RELOC_TYPE_32_BIT:
+ put_unaligned(addr, ptr);
+ pr_debug("new ptr =%lx", get_unaligned(ptr));
+ break;
}
}
EXPORT_SYMBOL(bfin_put_addr_at_rp);
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
index df5bf022cf7..1fc001c7abd 100644
--- a/arch/blackfin/kernel/irqchip.c
+++ b/arch/blackfin/kernel/irqchip.c
@@ -82,7 +82,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, ", %s", action->name);
seq_putc(p, '\n');
- unlock:
+ unlock:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
} else if (i == NR_IRQS) {
seq_printf(p, "Err: %10lu\n", irq_err_count);
@@ -91,7 +91,7 @@ int show_interrupts(struct seq_file *p, void *v)
}
/*
- * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
+ * do_IRQ handles all hardware IRQs. Decoded IRQs should not
* come via this function. Instead, they should provide their
* own 'handler'
*/
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
new file mode 100644
index 00000000000..a9c15515bfd
--- /dev/null
+++ b/arch/blackfin/kernel/kgdb.c
@@ -0,0 +1,421 @@
+/*
+ * File: arch/blackfin/kernel/kgdb.c
+ * Based on:
+ * Author: Sonic Zhang
+ *
+ * Created:
+ * Description:
+ *
+ * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
+ *
+ * Modified:
+ * Copyright 2005-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/ptrace.h> /* for linux pt_regs struct */
+#include <linux/kgdb.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/debugger.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/blackfin.h>
+
+/* Put the error code here just in case the user cares. */
+int gdb_bf533errcode;
+/* Likewise, the vector number here (since GDB only gets the signal
+ number through the usual means, and that's not very specific). */
+int gdb_bf533vector = -1;
+
+#if KGDB_MAX_NO_CPUS != 8
+#error change the definition of slavecpulocks
+#endif
+
+void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+ gdb_regs[BFIN_R0] = regs->r0;
+ gdb_regs[BFIN_R1] = regs->r1;
+ gdb_regs[BFIN_R2] = regs->r2;
+ gdb_regs[BFIN_R3] = regs->r3;
+ gdb_regs[BFIN_R4] = regs->r4;
+ gdb_regs[BFIN_R5] = regs->r5;
+ gdb_regs[BFIN_R6] = regs->r6;
+ gdb_regs[BFIN_R7] = regs->r7;
+ gdb_regs[BFIN_P0] = regs->p0;
+ gdb_regs[BFIN_P1] = regs->p1;
+ gdb_regs[BFIN_P2] = regs->p2;
+ gdb_regs[BFIN_P3] = regs->p3;
+ gdb_regs[BFIN_P4] = regs->p4;
+ gdb_regs[BFIN_P5] = regs->p5;
+ gdb_regs[BFIN_SP] = regs->reserved;
+ gdb_regs[BFIN_FP] = regs->fp;
+ gdb_regs[BFIN_I0] = regs->i0;
+ gdb_regs[BFIN_I1] = regs->i1;
+ gdb_regs[BFIN_I2] = regs->i2;
+ gdb_regs[BFIN_I3] = regs->i3;
+ gdb_regs[BFIN_M0] = regs->m0;
+ gdb_regs[BFIN_M1] = regs->m1;
+ gdb_regs[BFIN_M2] = regs->m2;
+ gdb_regs[BFIN_M3] = regs->m3;
+ gdb_regs[BFIN_B0] = regs->b0;
+ gdb_regs[BFIN_B1] = regs->b1;
+ gdb_regs[BFIN_B2] = regs->b2;
+ gdb_regs[BFIN_B3] = regs->b3;
+ gdb_regs[BFIN_L0] = regs->l0;
+ gdb_regs[BFIN_L1] = regs->l1;
+ gdb_regs[BFIN_L2] = regs->l2;
+ gdb_regs[BFIN_L3] = regs->l3;
+ gdb_regs[BFIN_A0_DOT_X] = regs->a0x;
+ gdb_regs[BFIN_A0_DOT_W] = regs->a0w;
+ gdb_regs[BFIN_A1_DOT_X] = regs->a1x;
+ gdb_regs[BFIN_A1_DOT_W] = regs->a1w;
+ gdb_regs[BFIN_ASTAT] = regs->astat;
+ gdb_regs[BFIN_RETS] = regs->rets;
+ gdb_regs[BFIN_LC0] = regs->lc0;
+ gdb_regs[BFIN_LT0] = regs->lt0;
+ gdb_regs[BFIN_LB0] = regs->lb0;
+ gdb_regs[BFIN_LC1] = regs->lc1;
+ gdb_regs[BFIN_LT1] = regs->lt1;
+ gdb_regs[BFIN_LB1] = regs->lb1;
+ gdb_regs[BFIN_CYCLES] = 0;
+ gdb_regs[BFIN_CYCLES2] = 0;
+ gdb_regs[BFIN_USP] = regs->usp;
+ gdb_regs[BFIN_SEQSTAT] = regs->seqstat;
+ gdb_regs[BFIN_SYSCFG] = regs->syscfg;
+ gdb_regs[BFIN_RETI] = regs->pc;
+ gdb_regs[BFIN_RETX] = regs->retx;
+ gdb_regs[BFIN_RETN] = regs->retn;
+ gdb_regs[BFIN_RETE] = regs->rete;
+ gdb_regs[BFIN_PC] = regs->pc;
+ gdb_regs[BFIN_CC] = 0;
+ gdb_regs[BFIN_EXTRA1] = 0;
+ gdb_regs[BFIN_EXTRA2] = 0;
+ gdb_regs[BFIN_EXTRA3] = 0;
+ gdb_regs[BFIN_IPEND] = regs->ipend;
+}
+
+/*
+ * Extracts ebp, esp and eip values understandable by gdb from the values
+ * saved by switch_to.
+ * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
+ * prior to entering switch_to is 8 greater then the value that is saved.
+ * If switch_to changes, change following code appropriately.
+ */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+{
+ gdb_regs[BFIN_SP] = p->thread.ksp;
+ gdb_regs[BFIN_PC] = p->thread.pc;
+ gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat;
+}
+
+void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+ regs->r0 = gdb_regs[BFIN_R0];
+ regs->r1 = gdb_regs[BFIN_R1];
+ regs->r2 = gdb_regs[BFIN_R2];
+ regs->r3 = gdb_regs[BFIN_R3];
+ regs->r4 = gdb_regs[BFIN_R4];
+ regs->r5 = gdb_regs[BFIN_R5];
+ regs->r6 = gdb_regs[BFIN_R6];
+ regs->r7 = gdb_regs[BFIN_R7];
+ regs->p0 = gdb_regs[BFIN_P0];
+ regs->p1 = gdb_regs[BFIN_P1];
+ regs->p2 = gdb_regs[BFIN_P2];
+ regs->p3 = gdb_regs[BFIN_P3];
+ regs->p4 = gdb_regs[BFIN_P4];
+ regs->p5 = gdb_regs[BFIN_P5];
+ regs->fp = gdb_regs[BFIN_FP];
+ regs->i0 = gdb_regs[BFIN_I0];
+ regs->i1 = gdb_regs[BFIN_I1];
+ regs->i2 = gdb_regs[BFIN_I2];
+ regs->i3 = gdb_regs[BFIN_I3];
+ regs->m0 = gdb_regs[BFIN_M0];
+ regs->m1 = gdb_regs[BFIN_M1];
+ regs->m2 = gdb_regs[BFIN_M2];
+ regs->m3 = gdb_regs[BFIN_M3];
+ regs->b0 = gdb_regs[BFIN_B0];
+ regs->b1 = gdb_regs[BFIN_B1];
+ regs->b2 = gdb_regs[BFIN_B2];
+ regs->b3 = gdb_regs[BFIN_B3];
+ regs->l0 = gdb_regs[BFIN_L0];
+ regs->l1 = gdb_regs[BFIN_L1];
+ regs->l2 = gdb_regs[BFIN_L2];
+ regs->l3 = gdb_regs[BFIN_L3];
+ regs->a0x = gdb_regs[BFIN_A0_DOT_X];
+ regs->a0w = gdb_regs[BFIN_A0_DOT_W];
+ regs->a1x = gdb_regs[BFIN_A1_DOT_X];
+ regs->a1w = gdb_regs[BFIN_A1_DOT_W];
+ regs->rets = gdb_regs[BFIN_RETS];
+ regs->lc0 = gdb_regs[BFIN_LC0];
+ regs->lt0 = gdb_regs[BFIN_LT0];
+ regs->lb0 = gdb_regs[BFIN_LB0];
+ regs->lc1 = gdb_regs[BFIN_LC1];
+ regs->lt1 = gdb_regs[BFIN_LT1];
+ regs->lb1 = gdb_regs[BFIN_LB1];
+ regs->usp = gdb_regs[BFIN_USP];
+ regs->syscfg = gdb_regs[BFIN_SYSCFG];
+ regs->retx = gdb_regs[BFIN_PC];
+ regs->retn = gdb_regs[BFIN_RETN];
+ regs->rete = gdb_regs[BFIN_RETE];
+ regs->pc = gdb_regs[BFIN_PC];
+
+#if 0 /* can't change these */
+ regs->astat = gdb_regs[BFIN_ASTAT];
+ regs->seqstat = gdb_regs[BFIN_SEQSTAT];
+ regs->ipend = gdb_regs[BFIN_IPEND];
+#endif
+}
+
+struct hw_breakpoint {
+ unsigned int occupied:1;
+ unsigned int skip:1;
+ unsigned int enabled:1;
+ unsigned int type:1;
+ unsigned int dataacc:2;
+ unsigned short count;
+ unsigned int addr;
+} breakinfo[HW_BREAKPOINT_NUM];
+
+int kgdb_arch_init(void)
+{
+ kgdb_remove_all_hw_break();
+ return 0;
+}
+
+int kgdb_set_hw_break(unsigned long addr)
+{
+ int breakno;
+ for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
+ if (!breakinfo[breakno].occupied) {
+ breakinfo[breakno].occupied = 1;
+ breakinfo[breakno].enabled = 1;
+ breakinfo[breakno].type = 1;
+ breakinfo[breakno].addr = addr;
+ return 0;
+ }
+
+ return -ENOSPC;
+}
+
+int kgdb_remove_hw_break(unsigned long addr)
+{
+ int breakno;
+ for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++)
+ if (breakinfo[breakno].addr == addr)
+ memset(&(breakinfo[breakno]), 0, sizeof(struct hw_breakpoint));
+
+ return 0;
+}
+
+void kgdb_remove_all_hw_break(void)
+{
+ memset(breakinfo, 0, sizeof(struct hw_breakpoint)*8);
+}
+
+/*
+void kgdb_show_info(void)
+{
+ printk(KERN_DEBUG "hwd: wpia0=0x%x, wpiacnt0=%d, wpiactl=0x%x, wpstat=0x%x\n",
+ bfin_read_WPIA0(), bfin_read_WPIACNT0(),
+ bfin_read_WPIACTL(), bfin_read_WPSTAT());
+}
+*/
+
+void kgdb_correct_hw_break(void)
+{
+ int breakno;
+ int correctit;
+ uint32_t wpdactl = bfin_read_WPDACTL();
+
+ correctit = 0;
+ for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) {
+ if (breakinfo[breakno].type == 1) {
+ switch (breakno) {
+ case 0:
+ if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) {
+ correctit = 1;
+ wpdactl &= ~(WPIREN01|EMUSW0);
+ wpdactl |= WPIAEN0|WPICNTEN0;
+ bfin_write_WPIA0(breakinfo[breakno].addr);
+ bfin_write_WPIACNT0(breakinfo[breakno].skip);
+ } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) {
+ correctit = 1;
+ wpdactl &= ~WPIAEN0;
+ }
+ break;
+
+ case 1:
+ if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) {
+ correctit = 1;
+ wpdactl &= ~(WPIREN01|EMUSW1);
+ wpdactl |= WPIAEN1|WPICNTEN1;
+ bfin_write_WPIA1(breakinfo[breakno].addr);
+ bfin_write_WPIACNT1(breakinfo[breakno].skip);
+ } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) {
+ correctit = 1;
+ wpdactl &= ~WPIAEN1;
+ }
+ break;
+
+ case 2:
+ if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) {
+ correctit = 1;
+ wpdactl &= ~(WPIREN23|EMUSW2);
+ wpdactl |= WPIAEN2|WPICNTEN2;
+ bfin_write_WPIA2(breakinfo[breakno].addr);
+ bfin_write_WPIACNT2(breakinfo[breakno].skip);
+ } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) {
+ correctit = 1;
+ wpdactl &= ~WPIAEN2;
+ }
+ break;
+
+ case 3:
+ if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) {
+ correctit = 1;
+ wpdactl &= ~(WPIREN23|EMUSW3);
+ wpdactl |= WPIAEN3|WPICNTEN3;
+ bfin_write_WPIA3(breakinfo[breakno].addr);
+ bfin_write_WPIACNT3(breakinfo[breakno].skip);
+ } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) {
+ correctit = 1;
+ wpdactl &= ~WPIAEN3;
+ }
+ break;
+ case 4:
+ if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) {
+ correctit = 1;
+ wpdactl &= ~(WPIREN45|EMUSW4);
+ wpdactl |= WPIAEN4|WPICNTEN4;
+ bfin_write_WPIA4(breakinfo[breakno].addr);
+ bfin_write_WPIACNT4(breakinfo[breakno].skip);
+ } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) {
+ correctit = 1;
+ wpdactl &= ~WPIAEN4;
+ }
+ break;
+ case 5:
+ if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) {
+ correctit = 1;
+ wpdactl &= ~(WPIREN45|EMUSW5);
+ wpdactl |= WPIAEN5|WPICNTEN5;
+ bfin_write_WPIA5(breakinfo[breakno].addr);
+ bfin_write_WPIACNT5(breakinfo[breakno].skip);
+ } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) {
+ correctit = 1;
+ wpdactl &= ~WPIAEN5;
+ }
+ break;
+ }
+ }
+ }
+ if (correctit) {
+ wpdactl &= ~WPAND;
+ wpdactl |= WPPWR;
+ /*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/
+ bfin_write_WPDACTL(wpdactl);
+ CSYNC();
+ /*kgdb_show_info();*/
+ }
+}
+
+void kgdb_disable_hw_debug(struct pt_regs *regs)
+{
+ /* Disable hardware debugging while we are in kgdb */
+ bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1);
+ CSYNC();
+}
+
+void kgdb_post_master_code(struct pt_regs *regs, int eVector, int err_code)
+{
+ /* Master processor is completely in the debugger */
+ gdb_bf533vector = eVector;
+ gdb_bf533errcode = err_code;
+}
+
+int kgdb_arch_handle_exception(int exceptionVector, int signo,
+ int err_code, char *remcom_in_buffer,
+ char *remcom_out_buffer,
+ struct pt_regs *linux_regs)
+{
+ long addr;
+ long breakno;
+ char *ptr;
+ int newPC;
+ int wp_status;
+
+ switch (remcom_in_buffer[0]) {
+ case 'c':
+ case 's':
+ if (kgdb_contthread && kgdb_contthread != current) {
+ strcpy(remcom_out_buffer, "E00");
+ break;
+ }
+
+ kgdb_contthread = NULL;
+
+ /* try to read optional parameter, pc unchanged if no parm */
+ ptr = &remcom_in_buffer[1];
+ if (kgdb_hex2long(&ptr, &addr)) {
+ linux_regs->retx = addr;
+ }
+ newPC = linux_regs->retx;
+
+ /* clear the trace bit */
+ linux_regs->syscfg &= 0xfffffffe;
+
+ /* set the trace bit if we're stepping */
+ if (remcom_in_buffer[0] == 's') {
+ linux_regs->syscfg |= 0x1;
+ debugger_step = 1;
+ }
+
+ wp_status = bfin_read_WPSTAT();
+ CSYNC();
+
+ if (exceptionVector == VEC_WATCH) {
+ for (breakno = 0; breakno < 6; ++breakno) {
+ if (wp_status & (1 << breakno)) {
+ breakinfo->skip = 1;
+ break;
+ }
+ }
+ }
+ kgdb_correct_hw_break();
+
+ bfin_write_WPSTAT(0);
+
+ return 0;
+ } /* switch */
+ return -1; /* this means that we do not want to exit from the handler */
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+ .gdb_bpt_instr = {0xa1},
+ .flags = KGDB_HW_BREAKPOINT,
+};
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index 372f756f1ad..8b9fe29d03f 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -165,8 +165,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
for (s = sechdrs; s < sechdrs_end; ++s) {
if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
- ((strcmp(".text", secstrings + s->sh_name)==0) &&
- (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) {
+ ((strcmp(".text", secstrings + s->sh_name) == 0) &&
+ (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) {
mod->arch.text_l1 = s;
dest = l1_inst_sram_alloc(s->sh_size);
if (dest == NULL) {
@@ -179,9 +179,9 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
s->sh_flags &= ~SHF_ALLOC;
s->sh_addr = (unsigned long)dest;
}
- if ((strcmp(".l1.data", secstrings + s->sh_name) == 0)||
- ((strcmp(".data", secstrings + s->sh_name)==0) &&
- (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+ if ((strcmp(".l1.data", secstrings + s->sh_name) == 0) ||
+ ((strcmp(".data", secstrings + s->sh_name) == 0) &&
+ (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
mod->arch.data_a_l1 = s;
dest = l1_data_sram_alloc(s->sh_size);
if (dest == NULL) {
@@ -195,8 +195,8 @@ module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
s->sh_addr = (unsigned long)dest;
}
if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
- ((strcmp(".bss", secstrings + s->sh_name)==0) &&
- (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+ ((strcmp(".bss", secstrings + s->sh_name) == 0) &&
+ (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
mod->arch.bss_a_l1 = s;
dest = l1_data_sram_alloc(s->sh_size);
if (dest == NULL) {
@@ -326,7 +326,7 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
pr_debug("before %x after %x\n", *location16,
(value & 0xffff));
tmp = (value & 0xffff);
- if((unsigned long)location16 >= L1_CODE_START) {
+ if ((unsigned long)location16 >= L1_CODE_START) {
dma_memcpy(location16, &tmp, 2);
} else
*location16 = tmp;
@@ -335,7 +335,7 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
pr_debug("before %x after %x\n", *location16,
((value >> 16) & 0xffff));
tmp = ((value >> 16) & 0xffff);
- if((unsigned long)location16 >= L1_CODE_START) {
+ if ((unsigned long)location16 >= L1_CODE_START) {
dma_memcpy(location16, &tmp, 2);
} else
*location16 = tmp;
@@ -404,8 +404,8 @@ module_finalize(const Elf_Ehdr * hdr,
continue;
if ((sechdrs[i].sh_type == SHT_RELA) &&
- ((strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0)||
- ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
+ ((strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
+ ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
(hdr->e_flags & FLG_CODE_IN_L1)))) {
apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
symindex, i, mod);
@@ -417,13 +417,13 @@ module_finalize(const Elf_Ehdr * hdr,
void module_arch_cleanup(struct module *mod)
{
if ((mod->arch.text_l1) && (mod->arch.text_l1->sh_addr))
- l1_inst_sram_free((void*)mod->arch.text_l1->sh_addr);
+ l1_inst_sram_free((void *)mod->arch.text_l1->sh_addr);
if ((mod->arch.data_a_l1) && (mod->arch.data_a_l1->sh_addr))
- l1_data_sram_free((void*)mod->arch.data_a_l1->sh_addr);
+ l1_data_sram_free((void *)mod->arch.data_a_l1->sh_addr);
if ((mod->arch.bss_a_l1) && (mod->arch.bss_a_l1->sh_addr))
- l1_data_sram_free((void*)mod->arch.bss_a_l1->sh_addr);
+ l1_data_sram_free((void *)mod->arch.bss_a_l1->sh_addr);
if ((mod->arch.data_b_l1) && (mod->arch.data_b_l1->sh_addr))
- l1_data_B_sram_free((void*)mod->arch.data_b_l1->sh_addr);
+ l1_data_B_sram_free((void *)mod->arch.data_b_l1->sh_addr);
if ((mod->arch.bss_b_l1) && (mod->arch.bss_b_l1->sh_addr))
- l1_data_B_sram_free((void*)mod->arch.bss_b_l1->sh_addr);
+ l1_data_B_sram_free((void *)mod->arch.bss_b_l1->sh_addr);
}
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 3eff7439d8d..5a51dd6ab28 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -32,9 +32,10 @@
#include <linux/unistd.h>
#include <linux/user.h>
#include <linux/a.out.h>
+#include <linux/uaccess.h>
#include <asm/blackfin.h>
-#include <asm/uaccess.h>
+#include <asm/fixed_code.h>
#define LED_ON 0
#define LED_OFF 1
@@ -173,8 +174,8 @@ void show_regs(struct pt_regs *regs)
printk(KERN_NOTICE "R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n",
regs->r4, regs->r5, regs->r6, regs->r7);
- if (!(regs->ipend))
- printk("USP: %08lx\n", rdusp());
+ if (!regs->ipend)
+ printk(KERN_NOTICE "USP: %08lx\n", rdusp());
}
/* Fill in the fpu structure for a core dump. */
@@ -322,7 +323,7 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp)
goto out;
error = do_execve(filename, argv, envp, regs);
putname(filename);
- out:
+ out:
unlock_kernel();
return error;
}
@@ -350,13 +351,77 @@ unsigned long get_wchan(struct task_struct *p)
return 0;
}
+void finish_atomic_sections (struct pt_regs *regs)
+{
+ if (regs->pc < ATOMIC_SEQS_START || regs->pc >= ATOMIC_SEQS_END)
+ return;
+
+ switch (regs->pc) {
+ case ATOMIC_XCHG32 + 2:
+ put_user(regs->r1, (int *)regs->p0);
+ regs->pc += 2;
+ break;
+
+ case ATOMIC_CAS32 + 2:
+ case ATOMIC_CAS32 + 4:
+ if (regs->r0 == regs->r1)
+ put_user(regs->r2, (int *)regs->p0);
+ regs->pc = ATOMIC_CAS32 + 8;
+ break;
+ case ATOMIC_CAS32 + 6:
+ put_user(regs->r2, (int *)regs->p0);
+ regs->pc += 2;
+ break;
+
+ case ATOMIC_ADD32 + 2:
+ regs->r0 = regs->r1 + regs->r0;
+ /* fall through */
+ case ATOMIC_ADD32 + 4:
+ put_user(regs->r0, (int *)regs->p0);
+ regs->pc = ATOMIC_ADD32 + 6;
+ break;
+
+ case ATOMIC_SUB32 + 2:
+ regs->r0 = regs->r1 - regs->r0;
+ /* fall through */
+ case ATOMIC_SUB32 + 4:
+ put_user(regs->r0, (int *)regs->p0);
+ regs->pc = ATOMIC_SUB32 + 6;
+ break;
+
+ case ATOMIC_IOR32 + 2:
+ regs->r0 = regs->r1 | regs->r0;
+ /* fall through */
+ case ATOMIC_IOR32 + 4:
+ put_user(regs->r0, (int *)regs->p0);
+ regs->pc = ATOMIC_IOR32 + 6;
+ break;
+
+ case ATOMIC_AND32 + 2:
+ regs->r0 = regs->r1 & regs->r0;
+ /* fall through */
+ case ATOMIC_AND32 + 4:
+ put_user(regs->r0, (int *)regs->p0);
+ regs->pc = ATOMIC_AND32 + 6;
+ break;
+
+ case ATOMIC_XOR32 + 2:
+ regs->r0 = regs->r1 ^ regs->r0;
+ /* fall through */
+ case ATOMIC_XOR32 + 4:
+ put_user(regs->r0, (int *)regs->p0);
+ regs->pc = ATOMIC_XOR32 + 6;
+ break;
+ }
+}
+
#if defined(CONFIG_ACCESS_CHECK)
int _access_ok(unsigned long addr, unsigned long size)
{
if (addr > (addr + size))
return 0;
- if (segment_eq(get_fs(),KERNEL_DS))
+ if (segment_eq(get_fs(), KERNEL_DS))
return 1;
#ifdef CONFIG_MTD_UCLINUX
if (addr >= memory_start && (addr + size) <= memory_end)
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c
index e718bb4a1ef..ed800c7456d 100644
--- a/arch/blackfin/kernel/ptrace.c
+++ b/arch/blackfin/kernel/ptrace.c
@@ -36,8 +36,8 @@
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/signal.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -122,7 +122,7 @@ static inline long get_reg(struct task_struct *task, int regno)
static inline int
put_reg(struct task_struct *task, int regno, unsigned long data)
{
- char * reg_ptr;
+ char *reg_ptr;
struct pt_regs *regs =
(struct pt_regs *)((unsigned long)task_stack_page(task) +
@@ -146,7 +146,7 @@ put_reg(struct task_struct *task, int regno, unsigned long data)
break;
default:
if (regno <= 216)
- *(long *)(reg_ptr + regno) = data;
+ *(long *)(reg_ptr + regno) = data;
}
return 0;
}
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 02dc7430192..f59dcee7bae 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -42,6 +42,7 @@
#include <asm/cacheflush.h>
#include <asm/blackfin.h>
#include <asm/cplbinit.h>
+#include <asm/fixed_code.h>
u16 _bfin_swrst;
@@ -61,11 +62,7 @@ EXPORT_SYMBOL(memory_mtd_start);
EXPORT_SYMBOL(mtd_size);
#endif
-char command_line[COMMAND_LINE_SIZE];
-
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-static void generate_cpl_tables(void);
-#endif
+char __initdata command_line[COMMAND_LINE_SIZE];
void __init bf53x_cache_init(void)
{
@@ -90,7 +87,7 @@ void __init bf53x_cache_init(void)
#endif
}
-void bf53x_relocate_l1_mem(void)
+void __init bf53x_relocate_l1_mem(void)
{
unsigned long l1_code_length;
unsigned long l1_data_a_length;
@@ -197,6 +194,17 @@ void __init setup_arch(char **cmdline_p)
/* this give a chance to get printk() working before crash. */
#endif
+ printk(KERN_INFO "Hardware Trace ");
+ if (bfin_read_TBUFCTL() & 0x1 )
+ printk("Active ");
+ else
+ printk("Off ");
+ if (bfin_read_TBUFCTL() & 0x2)
+ printk("and Enabled\n");
+ else
+ printk("and Disabled\n");
+
+
#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
/* we need to initialize the Flashrom device here since we might
* do things with flash early on in the boot
@@ -205,7 +213,6 @@ void __init setup_arch(char **cmdline_p)
#endif
#if defined(CONFIG_CMDLINE_BOOL)
- memset(command_line, 0, sizeof(command_line));
strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line));
command_line[sizeof(command_line) - 1] = 0;
#endif
@@ -213,7 +220,7 @@ void __init setup_arch(char **cmdline_p)
/* Keep a copy of command line */
*cmdline_p = &command_line[0];
memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
- boot_command_line[COMMAND_LINE_SIZE - 1] = 0;
+ boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
/* setup memory defaults from the user config */
physical_mem_end = 0;
@@ -308,10 +315,20 @@ void __init setup_arch(char **cmdline_p)
init_leds();
printk(KERN_INFO "Blackfin support (C) 2004-2007 Analog Devices, Inc.\n");
- printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid());
- if (bfin_revid() != bfin_compiled_revid())
- printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
- bfin_compiled_revid(), bfin_revid());
+ if (bfin_compiled_revid() == 0xffff)
+ printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU);
+ else if (bfin_compiled_revid() == -1)
+ printk(KERN_INFO "Compiled for ADSP-%s Rev none\n", CPU);
+ else
+ printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid());
+ if (bfin_revid() != bfin_compiled_revid()) {
+ if (bfin_compiled_revid() == -1)
+ printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n",
+ bfin_revid());
+ else if (bfin_compiled_revid() != 0xffff)
+ printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
+ bfin_compiled_revid(), bfin_revid());
+ }
if (bfin_revid() < SUPPORTED_REVID)
printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
CPU, bfin_revid());
@@ -330,9 +347,10 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_INFO "Memory map:\n"
KERN_INFO " text = 0x%p-0x%p\n"
- KERN_INFO " init = 0x%p-0x%p\n"
+ KERN_INFO " rodata = 0x%p-0x%p\n"
KERN_INFO " data = 0x%p-0x%p\n"
- KERN_INFO " stack = 0x%p-0x%p\n"
+ KERN_INFO " stack = 0x%p-0x%p\n"
+ KERN_INFO " init = 0x%p-0x%p\n"
KERN_INFO " bss = 0x%p-0x%p\n"
KERN_INFO " available = 0x%p-0x%p\n"
#ifdef CONFIG_MTD_UCLINUX
@@ -342,16 +360,17 @@ void __init setup_arch(char **cmdline_p)
KERN_INFO " DMA Zone = 0x%p-0x%p\n"
#endif
, _stext, _etext,
- __init_begin, __init_end,
+ __start_rodata, __end_rodata,
_sdata, _edata,
- (void*)&init_thread_union, (void*)((int)(&init_thread_union) + 0x2000),
+ (void *)&init_thread_union, (void *)((int)(&init_thread_union) + 0x2000),
+ __init_begin, __init_end,
__bss_start, __bss_stop,
- (void*)_ramstart, (void*)memory_end
+ (void *)_ramstart, (void *)memory_end
#ifdef CONFIG_MTD_UCLINUX
- , (void*)memory_mtd_start, (void*)(memory_mtd_start + mtd_size)
+ , (void *)memory_mtd_start, (void *)(memory_mtd_start + mtd_size)
#endif
#if DMA_UNCACHED_REGION > 0
- , (void*)(_ramend - DMA_UNCACHED_REGION), (void*)(_ramend)
+ , (void *)(_ramend - DMA_UNCACHED_REGION), (void *)(_ramend)
#endif
);
@@ -377,11 +396,11 @@ void __init setup_arch(char **cmdline_p)
/* check the size of the l1 area */
l1_length = _etext_l1 - _stext_l1;
if (l1_length > L1_CODE_LENGTH)
- panic("L1 memory overflow\n");
+ panic("L1 code memory overflow\n");
l1_length = _ebss_l1 - _sdata_l1;
if (l1_length > L1_DATA_A_LENGTH)
- panic("L1 memory overflow\n");
+ panic("L1 data memory overflow\n");
#ifdef BF561_FAMILY
_bfin_swrst = bfin_read_SICA_SWRST();
@@ -389,10 +408,28 @@ void __init setup_arch(char **cmdline_p)
_bfin_swrst = bfin_read_SWRST();
#endif
- bf53x_cache_init();
+ /* Copy atomic sequences to their fixed location, and sanity check that
+ these locations are the ones that we advertise to userspace. */
+ memcpy((void *)FIXED_CODE_START, &fixed_code_start,
+ FIXED_CODE_END - FIXED_CODE_START);
+ BUG_ON((char *)&sigreturn_stub - (char *)&fixed_code_start
+ != SIGRETURN_STUB - FIXED_CODE_START);
+ BUG_ON((char *)&atomic_xchg32 - (char *)&fixed_code_start
+ != ATOMIC_XCHG32 - FIXED_CODE_START);
+ BUG_ON((char *)&atomic_cas32 - (char *)&fixed_code_start
+ != ATOMIC_CAS32 - FIXED_CODE_START);
+ BUG_ON((char *)&atomic_add32 - (char *)&fixed_code_start
+ != ATOMIC_ADD32 - FIXED_CODE_START);
+ BUG_ON((char *)&atomic_sub32 - (char *)&fixed_code_start
+ != ATOMIC_SUB32 - FIXED_CODE_START);
+ BUG_ON((char *)&atomic_ior32 - (char *)&fixed_code_start
+ != ATOMIC_IOR32 - FIXED_CODE_START);
+ BUG_ON((char *)&atomic_and32 - (char *)&fixed_code_start
+ != ATOMIC_AND32 - FIXED_CODE_START);
+ BUG_ON((char *)&atomic_xor32 - (char *)&fixed_code_start
+ != ATOMIC_XOR32 - FIXED_CODE_START);
- printk(KERN_INFO "Hardware Trace Enabled\n");
- bfin_write_TBUFCTL(0x03);
+ bf53x_cache_init();
}
static int __init topology_init(void)
@@ -410,278 +447,7 @@ static int __init topology_init(void)
subsys_initcall(topology_init);
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-u16 lock_kernel_check(u32 start, u32 end)
-{
- if ((start <= (u32) _stext && end >= (u32) _end)
- || (start >= (u32) _stext && end <= (u32) _end))
- return IN_KERNEL;
- return 0;
-}
-
-static unsigned short __init
-fill_cplbtab(struct cplb_tab *table,
- unsigned long start, unsigned long end,
- unsigned long block_size, unsigned long cplb_data)
-{
- int i;
-
- switch (block_size) {
- case SIZE_4M:
- i = 3;
- break;
- case SIZE_1M:
- i = 2;
- break;
- case SIZE_4K:
- i = 1;
- break;
- case SIZE_1K:
- default:
- i = 0;
- break;
- }
-
- cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
-
- while ((start < end) && (table->pos < table->size)) {
-
- table->tab[table->pos++] = start;
-
- if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
- table->tab[table->pos++] =
- cplb_data | CPLB_LOCK | CPLB_DIRTY;
- else
- table->tab[table->pos++] = cplb_data;
-
- start += block_size;
- }
- return 0;
-}
-
-static unsigned short __init
-close_cplbtab(struct cplb_tab *table)
-{
-
- while (table->pos < table->size) {
-
- table->tab[table->pos++] = 0;
- table->tab[table->pos++] = 0; /* !CPLB_VALID */
- }
- return 0;
-}
-
-static void __init generate_cpl_tables(void)
-{
-
- u16 i, j, process;
- u32 a_start, a_end, as, ae, as_1m;
-
- struct cplb_tab *t_i = NULL;
- struct cplb_tab *t_d = NULL;
- struct s_cplb cplb;
-
- cplb.init_i.size = MAX_CPLBS;
- cplb.init_d.size = MAX_CPLBS;
- cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
- cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
-
- cplb.init_i.pos = 0;
- cplb.init_d.pos = 0;
- cplb.switch_i.pos = 0;
- cplb.switch_d.pos = 0;
-
- cplb.init_i.tab = icplb_table;
- cplb.init_d.tab = dcplb_table;
- cplb.switch_i.tab = ipdt_table;
- cplb.switch_d.tab = dpdt_table;
-
- cplb_data[SDRAM_KERN].end = memory_end;
-
-#ifdef CONFIG_MTD_UCLINUX
- cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
- cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
- cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
-# if defined(CONFIG_ROMFS_FS)
- cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
-
- /*
- * The ROMFS_FS size is often not multiple of 1MB.
- * This can cause multiple CPLB sets covering the same memory area.
- * This will then cause multiple CPLB hit exceptions.
- * Workaround: We ensure a contiguous memory area by extending the kernel
- * memory section over the mtd section.
- * For ROMFS_FS memory must be covered with ICPLBs anyways.
- * So there is no difference between kernel and mtd memory setup.
- */
-
- cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
- cplb_data[SDRAM_RAM_MTD].valid = 0;
-
-# endif
-#else
- cplb_data[SDRAM_RAM_MTD].valid = 0;
-#endif
-
- cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
- cplb_data[SDRAM_DMAZ].end = _ramend;
-
- cplb_data[RES_MEM].start = _ramend;
- cplb_data[RES_MEM].end = physical_mem_end;
-
- if (reserved_mem_dcache_on)
- cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
- else
- cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
-
- if (reserved_mem_icache_on)
- cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
- else
- cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
-
- for (i = ZERO_P; i <= L2_MEM; i++) {
-
- if (cplb_data[i].valid) {
-
- as_1m = cplb_data[i].start % SIZE_1M;
-
- /* We need to make sure all sections are properly 1M aligned
- * However between Kernel Memory and the Kernel mtd section, depending on the
- * rootfs size, there can be overlapping memory areas.
- */
-
- if (as_1m && i!=L1I_MEM && i!=L1D_MEM) {
-#ifdef CONFIG_MTD_UCLINUX
- if (i == SDRAM_RAM_MTD) {
- if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
- cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
- else
- cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
- } else
-#endif
- printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
- cplb_data[i].name, cplb_data[i].start);
- }
-
- as = cplb_data[i].start % SIZE_4M;
- ae = cplb_data[i].end % SIZE_4M;
-
- if (as)
- a_start = cplb_data[i].start + (SIZE_4M - (as));
- else
- a_start = cplb_data[i].start;
-
- a_end = cplb_data[i].end - ae;
-
- for (j = INITIAL_T; j <= SWITCH_T; j++) {
-
- switch (j) {
- case INITIAL_T:
- if (cplb_data[i].attr & INITIAL_T) {
- t_i = &cplb.init_i;
- t_d = &cplb.init_d;
- process = 1;
- } else
- process = 0;
- break;
- case SWITCH_T:
- if (cplb_data[i].attr & SWITCH_T) {
- t_i = &cplb.switch_i;
- t_d = &cplb.switch_d;
- process = 1;
- } else
- process = 0;
- break;
- default:
- process = 0;
- break;
- }
-
- if (process) {
- if (cplb_data[i].attr & I_CPLB) {
-
- if (cplb_data[i].psize) {
- fill_cplbtab(t_i,
- cplb_data[i].start,
- cplb_data[i].end,
- cplb_data[i].psize,
- cplb_data[i].i_conf);
- } else {
- /*icplb_table */
-#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
- if (i == SDRAM_KERN) {
- fill_cplbtab(t_i,
- cplb_data[i].start,
- cplb_data[i].end,
- SIZE_4M,
- cplb_data[i].i_conf);
- } else
-#endif
- {
- fill_cplbtab(t_i,
- cplb_data[i].start,
- a_start,
- SIZE_1M,
- cplb_data[i].i_conf);
- fill_cplbtab(t_i,
- a_start,
- a_end,
- SIZE_4M,
- cplb_data[i].i_conf);
- fill_cplbtab(t_i, a_end,
- cplb_data[i].end,
- SIZE_1M,
- cplb_data[i].i_conf);
- }
- }
-
- }
- if (cplb_data[i].attr & D_CPLB) {
-
- if (cplb_data[i].psize) {
- fill_cplbtab(t_d,
- cplb_data[i].start,
- cplb_data[i].end,
- cplb_data[i].psize,
- cplb_data[i].d_conf);
- } else {
-/*dcplb_table*/
- fill_cplbtab(t_d,
- cplb_data[i].start,
- a_start, SIZE_1M,
- cplb_data[i].d_conf);
- fill_cplbtab(t_d, a_start,
- a_end, SIZE_4M,
- cplb_data[i].d_conf);
- fill_cplbtab(t_d, a_end,
- cplb_data[i].end,
- SIZE_1M,
- cplb_data[i].d_conf);
-
- }
-
- }
- }
- }
-
- }
- }
-
-/* close tables */
-
- close_cplbtab(&cplb.init_i);
- close_cplbtab(&cplb.init_d);
-
- cplb.init_i.tab[cplb.init_i.pos] = -1;
- cplb.init_d.tab[cplb.init_d.pos] = -1;
- cplb.switch_i.tab[cplb.switch_i.pos] = -1;
- cplb.switch_d.tab[cplb.switch_d.pos] = -1;
-
-}
-
-#endif
-
-static inline u_long get_vco(void)
+static u_long get_vco(void)
{
u_long msel;
u_long vco;
@@ -710,7 +476,6 @@ u_long get_cclk(void)
return get_vco() / ssel;
return get_vco() >> csel;
}
-
EXPORT_SYMBOL(get_cclk);
/* Get the System clock */
@@ -729,7 +494,6 @@ u_long get_sclk(void)
return get_vco() / ssel;
}
-
EXPORT_SYMBOL(get_sclk);
/*
@@ -784,23 +548,23 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "D-CACHE:\tOFF\n");
- switch(bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
- case ACACHE_BSRAM:
- seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
- dcache_size = 16;
- dsup_banks = 1;
- break;
- case ACACHE_BCACHE:
- seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
- dcache_size = 32;
- dsup_banks = 2;
- break;
- case ASRAM_BSRAM:
- seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
- dcache_size = 0;
- dsup_banks = 0;
- break;
- default:
+ switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
+ case ACACHE_BSRAM:
+ seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
+ dcache_size = 16;
+ dsup_banks = 1;
+ break;
+ case ACACHE_BCACHE:
+ seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
+ dcache_size = 32;
+ dsup_banks = 2;
+ break;
+ case ASRAM_BSRAM:
+ seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
+ dcache_size = 0;
+ dsup_banks = 0;
+ break;
+ default:
break;
}
@@ -889,8 +653,8 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-void cmdline_init(unsigned long r0)
+void __init cmdline_init(const char *r0)
{
if (r0)
- strncpy(command_line, (char *)r0, COMMAND_LINE_SIZE);
+ strncpy(command_line, r0, COMMAND_LINE_SIZE);
}
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
index 316e65c3439..5564c9588aa 100644
--- a/arch/blackfin/kernel/signal.c
+++ b/arch/blackfin/kernel/signal.c
@@ -34,8 +34,8 @@
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/freezer.h>
+#include <linux/uaccess.h>
-#include <asm/uaccess.h>
#include <asm/cacheflush.h>
#include <asm/ucontext.h>
@@ -124,7 +124,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
return r0;
- badframe:
+ badframe:
force_sig(SIGSEGV, current);
return 0;
}
@@ -239,7 +239,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
return 0;
- give_sigsegv:
+ give_sigsegv:
if (sig == SIGSEGV)
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV, current);
@@ -263,7 +263,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
}
/* fallthrough */
case -ERESTARTNOINTR:
- do_restart:
+ do_restart:
regs->p0 = regs->orig_p0;
regs->r0 = regs->orig_r0;
regs->pc -= 2;
@@ -341,7 +341,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
return;
}
-no_signal:
+ no_signal:
/* Did we come from a system call? */
if (regs->orig_p0 >= 0)
/* Restart the system call - no handlers present */
diff --git a/arch/blackfin/kernel/sys_bfin.c b/arch/blackfin/kernel/sys_bfin.c
index f436e6743f5..f5e1ae3d170 100644
--- a/arch/blackfin/kernel/sys_bfin.c
+++ b/arch/blackfin/kernel/sys_bfin.c
@@ -37,12 +37,12 @@
#include <linux/syscalls.h>
#include <linux/mman.h>
#include <linux/file.h>
+#include <linux/uaccess.h>
+#include <linux/ipc.h>
+#include <linux/unistd.h>
#include <asm/cacheflush.h>
-#include <asm/uaccess.h>
-#include <asm/ipc.h>
#include <asm/dma.h>
-#include <asm/unistd.h>
/*
* sys_pipe() is the normal C calling standard for creating
@@ -83,7 +83,7 @@ do_mmap2(unsigned long addr, unsigned long len,
if (file)
fput(file);
- out:
+ out:
return error;
}
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index f578176b6d9..beef057bd1d 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -87,7 +87,7 @@ void __init init_leds(void)
static inline void do_leds(void)
{
static unsigned int count = 50;
- static int flag = 0;
+ static int flag;
unsigned short tmp = 0;
if (--count == 0) {
@@ -200,7 +200,7 @@ irqreturn_t timer_interrupt(int irq, void *dummy)__attribute__((l1_text));
irqreturn_t timer_interrupt(int irq, void *dummy)
{
/* last time the cmos clock got updated */
- static long last_rtc_update = 0;
+ static long last_rtc_update;
write_seqlock(&xtime_lock);
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 9932edee8cb..3909f5b3553 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -27,15 +27,15 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
#include <asm/traps.h>
#include <asm/cacheflush.h>
#include <asm/blackfin.h>
-#include <asm/uaccess.h>
#include <asm/irq_handler.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kallsyms.h>
+#include <asm/trace.h>
#ifdef CONFIG_KGDB
# include <linux/debugger.h>
@@ -76,7 +76,7 @@ static int printk_address(unsigned long address)
if (!modname)
modname = delim = "";
return printk("<0x%p> { %s%s%s%s + 0x%lx }",
- (void*)address, delim, modname, delim, symname,
+ (void *)address, delim, modname, delim, symname,
(unsigned long)offset);
}
@@ -119,7 +119,7 @@ static int printk_address(unsigned long address)
write_unlock_irq(&tasklist_lock);
return printk("<0x%p> [ %s + 0x%lx ]",
- (void*)address, name, offset);
+ (void *)address, name, offset);
}
vml = vml->next;
@@ -128,19 +128,9 @@ static int printk_address(unsigned long address)
write_unlock_irq(&tasklist_lock);
/* we were unable to find this address anywhere */
- return printk("[<0x%p>]", (void*)address);
+ return printk("[<0x%p>]", (void *)address);
}
-#define trace_buffer_save(x) \
- do { \
- (x) = bfin_read_TBUFCTL(); \
- bfin_write_TBUFCTL((x) & ~TBUFEN); \
- } while (0)
-#define trace_buffer_restore(x) \
- do { \
- bfin_write_TBUFCTL((x)); \
- } while (0)
-
asmlinkage void trap_c(struct pt_regs *fp)
{
int j, sig = 0;
@@ -148,8 +138,15 @@ asmlinkage void trap_c(struct pt_regs *fp)
unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
#ifdef CONFIG_KGDB
-# define CHK_DEBUGGER_TRAP() do { CHK_DEBUGGER(trapnr, sig, info.si_code, fp,); } while (0)
-# define CHK_DEBUGGER_TRAP_MAYBE() do { if (kgdb_connected) CHK_DEBUGGER_TRAP(); } while (0)
+# define CHK_DEBUGGER_TRAP() \
+ do { \
+ CHK_DEBUGGER(trapnr, sig, info.si_code, fp); \
+ } while (0)
+# define CHK_DEBUGGER_TRAP_MAYBE() \
+ do { \
+ if (kgdb_connected) \
+ CHK_DEBUGGER_TRAP(); \
+ } while (0)
#else
# define CHK_DEBUGGER_TRAP() do { } while (0)
# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
@@ -196,15 +193,14 @@ asmlinkage void trap_c(struct pt_regs *fp)
#else
/* 0x02 - User Defined, Caught by default */
#endif
- /* 0x03 - Atomic test and set */
+ /* 0x03 - User Defined, userspace stack overflow */
case VEC_EXCPT03:
info.si_code = SEGV_STACKFLOW;
sig = SIGSEGV;
printk(KERN_EMERG EXC_0x03);
CHK_DEBUGGER_TRAP();
break;
- /* 0x04 - spinlock - handled by _ex_spinlock,
- getting here is an error */
+ /* 0x04 - User Defined, Caught by default */
/* 0x05 - User Defined, Caught by default */
/* 0x06 - User Defined, Caught by default */
/* 0x07 - User Defined, Caught by default */
@@ -297,7 +293,8 @@ asmlinkage void trap_c(struct pt_regs *fp)
info.si_code = ILL_CPLB_MULHIT;
#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
sig = SIGSEGV;
- printk(KERN_EMERG "\n\nNULL pointer access (probably)\n");
+ printk(KERN_EMERG "\n"
+ KERN_EMERG "NULL pointer access (probably)\n");
#else
sig = SIGILL;
printk(KERN_EMERG EXC_0x27);
@@ -418,7 +415,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
if (current->mm) {
fp->pc = current->mm->start_code;
} else {
- printk(KERN_EMERG "I can't return to memory that doesn't exist - bad things happen\n");
+ printk(KERN_EMERG
+ "I can't return to memory that doesn't exist"
+ " - bad things happen\n");
panic("Help - I've fallen and can't get up\n");
}
}
@@ -522,92 +521,113 @@ EXPORT_SYMBOL(dump_stack);
void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
{
if (current->pid) {
- printk("\nCURRENT PROCESS:\n\n");
- printk("COMM=%s PID=%d\n", current->comm, current->pid);
+ printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n"
+ KERN_EMERG "\n");
+ printk(KERN_EMERG "COMM=%s PID=%d\n",
+ current->comm, current->pid);
} else {
printk
- ("\nNo Valid pid - Either things are really messed up, or you are in the kernel\n");
+ (KERN_EMERG "\n" KERN_EMERG
+ "No Valid pid - Either things are really messed up,"
+ " or you are in the kernel\n");
}
if (current->mm) {
- printk("TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
- "BSS = 0x%p-0x%p USER-STACK = 0x%p\n\n",
- (void*)current->mm->start_code,
- (void*)current->mm->end_code,
- (void*)current->mm->start_data,
- (void*)current->mm->end_data,
- (void*)current->mm->end_data,
- (void*)current->mm->brk,
- (void*)current->mm->start_stack);
+ printk(KERN_EMERG "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
+ KERN_EMERG "BSS = 0x%p-0x%p USER-STACK = 0x%p\n"
+ KERN_EMERG "\n",
+ (void *)current->mm->start_code,
+ (void *)current->mm->end_code,
+ (void *)current->mm->start_data,
+ (void *)current->mm->end_data,
+ (void *)current->mm->end_data,
+ (void *)current->mm->brk,
+ (void *)current->mm->start_stack);
}
- printk("return address: 0x%p; contents of [PC-16...PC+8]:\n", retaddr);
- if (retaddr != 0 && retaddr <= (void*)physical_mem_end
+ printk(KERN_EMERG "return address: [0x%p]; contents of:", retaddr);
+ if (retaddr != 0 && retaddr <= (void *)physical_mem_end
#if L1_CODE_LENGTH != 0
/* FIXME: Copy the code out of L1 Instruction SRAM through dma
memcpy. */
- && !(retaddr >= (void*)L1_CODE_START
- && retaddr < (void*)(L1_CODE_START + L1_CODE_LENGTH))
+ && !(retaddr >= (void *)L1_CODE_START
+ && retaddr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
#endif
) {
- int i = 0;
+ int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32;
unsigned short x = 0;
- for (i = -16; i < 8; i++) {
- if (get_user(x, (unsigned short *)retaddr + i))
+ for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) {
+ if (!(i & 0xF))
+ printk(KERN_EMERG "\n" KERN_EMERG
+ "0x%08x: ", i);
+
+ if (get_user(x, (unsigned short *)i))
break;
#ifndef CONFIG_DEBUG_HWERR
/* If one of the last few instructions was a STI
- * it is likily that the error occured awhile ago
+ * it is likely that the error occured awhile ago
* and we just noticed
*/
if (x >= 0x0040 && x <= 0x0047 && i <= 0)
- panic("\n\nWARNING : You should reconfigure the kernel to turn on\n"
- " 'Hardware error interrupt debugging'\n"
- " The rest of this error is meanless\n");
+ panic("\n\nWARNING : You should reconfigure"
+ " the kernel to turn on\n"
+ " 'Hardware error interrupt"
+ " debugging'\n"
+ " The rest of this error"
+ " is meanless\n");
#endif
-
- if (i == -8)
- printk("\n");
- if (i == 0)
- printk("X\n");
- printk("%04x ", x);
+ if (i == (unsigned int)retaddr)
+ printk("[%04x]", x);
+ else
+ printk(" %04x ", x);
}
+ printk("\n" KERN_EMERG "\n");
} else
- printk("Cannot look at the [PC] for it is in unreadable L1 SRAM - sorry\n");
-
- printk("\n\n");
-
- printk("RETE: %08lx RETN: %08lx RETX: %08lx RETS: %08lx\n",
- fp->rete, fp->retn, fp->retx, fp->rets);
- printk("IPEND: %04lx SYSCFG: %04lx\n", fp->ipend, fp->syscfg);
- printk("SEQSTAT: %08lx SP: %08lx\n", (long)fp->seqstat, (long)fp);
- printk("R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n",
- fp->r0, fp->r1, fp->r2, fp->r3);
- printk("R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n",
- fp->r4, fp->r5, fp->r6, fp->r7);
- printk("P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n",
- fp->p0, fp->p1, fp->p2, fp->p3);
- printk("P4: %08lx P5: %08lx FP: %08lx\n", fp->p4, fp->p5, fp->fp);
- printk("A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n",
- fp->a0w, fp->a0x, fp->a1w, fp->a1x);
-
- printk("LB0: %08lx LT0: %08lx LC0: %08lx\n", fp->lb0, fp->lt0,
- fp->lc0);
- printk("LB1: %08lx LT1: %08lx LC1: %08lx\n", fp->lb1, fp->lt1,
- fp->lc1);
- printk("B0: %08lx L0: %08lx M0: %08lx I0: %08lx\n", fp->b0, fp->l0,
- fp->m0, fp->i0);
- printk("B1: %08lx L1: %08lx M1: %08lx I1: %08lx\n", fp->b1, fp->l1,
- fp->m1, fp->i1);
- printk("B2: %08lx L2: %08lx M2: %08lx I2: %08lx\n", fp->b2, fp->l2,
- fp->m2, fp->i2);
- printk("B3: %08lx L3: %08lx M3: %08lx I3: %08lx\n", fp->b3, fp->l3,
- fp->m3, fp->i3);
-
- printk("\nUSP: %08lx ASTAT: %08lx\n", rdusp(), fp->astat);
+ printk(KERN_EMERG
+ "Cannot look at the [PC] for it is"
+ "in unreadable L1 SRAM - sorry\n");
+
+
+ printk(KERN_EMERG
+ "RETE: %08lx RETN: %08lx RETX: %08lx RETS: %08lx\n",
+ fp->rete, fp->retn, fp->retx, fp->rets);
+ printk(KERN_EMERG "IPEND: %04lx SYSCFG: %04lx\n",
+ fp->ipend, fp->syscfg);
+ printk(KERN_EMERG "SEQSTAT: %08lx SP: %08lx\n",
+ (long)fp->seqstat, (long)fp);
+ printk(KERN_EMERG "R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n",
+ fp->r0, fp->r1, fp->r2, fp->r3);
+ printk(KERN_EMERG "R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n",
+ fp->r4, fp->r5, fp->r6, fp->r7);
+ printk(KERN_EMERG "P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n",
+ fp->p0, fp->p1, fp->p2, fp->p3);
+ printk(KERN_EMERG
+ "P4: %08lx P5: %08lx FP: %08lx\n",
+ fp->p4, fp->p5, fp->fp);
+ printk(KERN_EMERG
+ "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n",
+ fp->a0w, fp->a0x, fp->a1w, fp->a1x);
+
+ printk(KERN_EMERG "LB0: %08lx LT0: %08lx LC0: %08lx\n",
+ fp->lb0, fp->lt0, fp->lc0);
+ printk(KERN_EMERG "LB1: %08lx LT1: %08lx LC1: %08lx\n",
+ fp->lb1, fp->lt1, fp->lc1);
+ printk(KERN_EMERG "B0: %08lx L0: %08lx M0: %08lx I0: %08lx\n",
+ fp->b0, fp->l0, fp->m0, fp->i0);
+ printk(KERN_EMERG "B1: %08lx L1: %08lx M1: %08lx I1: %08lx\n",
+ fp->b1, fp->l1, fp->m1, fp->i1);
+ printk(KERN_EMERG "B2: %08lx L2: %08lx M2: %08lx I2: %08lx\n",
+ fp->b2, fp->l2, fp->m2, fp->i2);
+ printk(KERN_EMERG "B3: %08lx L3: %08lx M3: %08lx I3: %08lx\n",
+ fp->b3, fp->l3, fp->m3, fp->i3);
+
+ printk(KERN_EMERG "\n" KERN_EMERG "USP: %08lx ASTAT: %08lx\n",
+ rdusp(), fp->astat);
if ((long)fp->seqstat & SEQSTAT_EXCAUSE) {
- printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
- printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
+ printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n",
+ (void *)bfin_read_DCPLB_FAULT_ADDR());
+ printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n",
+ (void *)bfin_read_ICPLB_FAULT_ADDR());
}
printk("\n\n");
@@ -649,8 +669,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
break;
}
- printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void*)bfin_read_DCPLB_FAULT_ADDR());
- printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void*)bfin_read_ICPLB_FAULT_ADDR());
+ printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
+ printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
dump_bfin_regs(fp, (void *)fp->retx);
dump_stack();
panic("Unrecoverable event\n");
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 86fe6799580..d06f860f479 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -7,7 +7,7 @@
* Description: Master linker script for blackfin architecture
*
* Modified:
- * Copyright 2004-2006 Analog Devices Inc.
+ * Copyright 2004-2007 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -31,98 +31,56 @@
#include <asm-generic/vmlinux.lds.h>
#include <asm/mem_map.h>
-
+#include <asm/page.h>
OUTPUT_FORMAT("elf32-bfin")
ENTRY(__start)
_jiffies = _jiffies_64;
-MEMORY
-{
- ram : ORIGIN = CONFIG_BOOT_LOAD, LENGTH = (CONFIG_MEM_SIZE * 1024 * 1024) - (CONFIG_BOOT_LOAD)
- l1_data_a : ORIGIN = L1_DATA_A_START, LENGTH = L1_DATA_A_LENGTH
- l1_data_b : ORIGIN = L1_DATA_B_START, LENGTH = L1_DATA_B_LENGTH
- l1_code : ORIGIN = L1_CODE_START, LENGTH = L1_CODE_LENGTH
- l1_scratch : ORIGIN = L1_SCRATCH_START, LENGTH = L1_SCRATCH_LENGTH
-}
-
SECTIONS
{
. = CONFIG_BOOT_LOAD;
-
.text :
{
- _text = .;
- __stext = .;
+ __text = .;
+ _text = .;
+ __stext = .;
TEXT_TEXT
SCHED_TEXT
+ LOCK_TEXT
*(.text.lock)
+ *(.fixup)
+
. = ALIGN(16);
- ___start___ex_table = .;
+ ___start___ex_table = .;
*(__ex_table)
- ___stop___ex_table = .;
+ ___stop___ex_table = .;
- *($code)
- *(.rodata)
- *(.rodata.*)
- *(__vermagic) /* Kernel version magic */
- *(.rodata1)
- *(.fixup)
- *(.spinlock.text)
-
- /* Kernel symbol table: Normal symbols */
. = ALIGN(4);
- ___start___ksymtab = .;
- *(__ksymtab)
- ___stop___ksymtab = .;
-
- /* Kernel symbol table: GPL-only symbols */
- ___start___ksymtab_gpl = .;
- *(__ksymtab_gpl)
- ___stop___ksymtab_gpl = .;
-
- /* Kernel symbol table: Normal unused symbols */ \
- ___start___ksymtab_unused = .;
- *(__ksymtab_unused)
- ___stop___ksymtab_unused = .;
-
- /* Kernel symbol table: GPL-only unused symbols */
- ___start___ksymtab_unused_gpl = .;
- *(__ksymtab_unused_gpl)
- ___stop___ksymtab_unused_gpl = .;
-
-
- /* Kernel symbol table: GPL-future symbols */
- ___start___ksymtab_gpl_future = .;
- *(__ksymtab_gpl_future)
- ___stop___ksymtab_gpl_future = .;
-
- /* Kernel symbol table: Normal symbols */
- ___start___kcrctab = .;
- *(__kcrctab)
- ___stop___kcrctab = .;
-
- /* Kernel symbol table: GPL-only symbols */
- ___start___kcrctab_gpl = .;
- *(__kcrctab_gpl)
- ___stop___kcrctab_gpl = .;
-
- /* Kernel symbol table: GPL-future symbols */
- ___start___kcrctab_gpl_future = .;
- *(__kcrctab_gpl_future)
- ___stop___kcrctab_gpl_future = .;
-
- /* Kernel symbol table: strings */
- *(__ksymtab_strings)
-
- . = ALIGN(4);
__etext = .;
- } > ram
+ }
+
+ RODATA
+
+ .data :
+ {
+ . = ALIGN(PAGE_SIZE);
+ __sdata = .;
+ *(.data.init_task)
+ DATA_DATA
+ CONSTRUCTORS
+
+ . = ALIGN(32);
+ *(.data.cacheline_aligned)
+
+ . = ALIGN(PAGE_SIZE);
+ __edata = .;
+ }
+ . = ALIGN(PAGE_SIZE);
+ ___init_begin = .;
.init :
{
- . = ALIGN(4096);
- ___init_begin = .;
__sinittext = .;
*(.init.text)
__einittext = .;
@@ -148,39 +106,39 @@ SECTIONS
*(.init.ramfs)
___initramfs_end = .;
. = ALIGN(4);
- ___init_end = .;
- } > ram
+ }
- __l1_lma_start = .;
+ __l1_lma_start = .;
- .text_l1 :
+ .text_l1 L1_CODE_START : AT(LOADADDR(.init) + SIZEOF(.init))
{
. = ALIGN(4);
- __stext_l1 = .;
+ __stext_l1 = .;
*(.l1.text)
. = ALIGN(4);
- __etext_l1 = .;
- } > l1_code AT > ram
+ __etext_l1 = .;
+ }
- .data_l1 :
+ .data_l1 L1_DATA_A_START : AT(LOADADDR(.text_l1) + SIZEOF(.text_l1))
{
. = ALIGN(4);
- __sdata_l1 = .;
+ __sdata_l1 = .;
*(.l1.data)
- __edata_l1 = .;
+ __edata_l1 = .;
. = ALIGN(4);
- __sbss_l1 = .;
+ __sbss_l1 = .;
*(.l1.bss)
. = ALIGN(32);
*(.data_l1.cacheline_aligned)
. = ALIGN(4);
- __ebss_l1 = .;
- } > l1_data_a AT > ram
- .data_b_l1 :
+ __ebss_l1 = .;
+ }
+
+ .data_b_l1 L1_DATA_B_START : AT(LOADADDR(.data_l1) + SIZEOF(.data_l1))
{
. = ALIGN(4);
__sdata_b_l1 = .;
@@ -193,36 +151,26 @@ SECTIONS
. = ALIGN(4);
__ebss_b_l1 = .;
- } > l1_data_b AT > ram
-
- .data :
- {
- __sdata = .;
- . = ALIGN(0x2000);
- *(.data.init_task)
- DATA_DATA
+ }
- . = ALIGN(32);
- *(.data.cacheline_aligned)
-
- . = ALIGN(0x2000);
- __edata = .;
- } > ram
+ . = LOADADDR(.data_b_l1) + SIZEOF(.data_b_l1);
+ ___init_end = ALIGN(PAGE_SIZE);
- /DISCARD/ : { /* Exit code and data*/
- *(.exit.text)
- *(.exit.data)
- *(.exitcall.exit)
- } > ram
-
- .bss :
+ .bss ___init_end :
{
. = ALIGN(4);
- ___bss_start = .;
+ ___bss_start = .;
*(.bss)
*(COMMON)
. = ALIGN(4);
- ___bss_stop = .;
- __end = . ;
- } > ram
+ ___bss_stop = .;
+ __end = .;
+ }
+
+ /DISCARD/ :
+ {
+ *(.exit.text)
+ *(.exit.data)
+ *(.exitcall.exit)
+ }
}
diff --git a/arch/blackfin/lib/divsi3.S b/arch/blackfin/lib/divsi3.S
index 3e29861852b..2ac59c70dd9 100644
--- a/arch/blackfin/lib/divsi3.S
+++ b/arch/blackfin/lib/divsi3.S
@@ -44,6 +44,7 @@
*/
.global ___divsi3;
+.type ___divsi3, STT_FUNC;
#ifdef CONFIG_ARITHMETIC_OPS_L1
.section .l1.text
@@ -214,3 +215,5 @@ ___divsi3 :
.Lret_zero:
R0 = 0;
RTS;
+
+.size ___divsi3, .-___divsi3
diff --git a/arch/blackfin/lib/ins.S b/arch/blackfin/lib/ins.S
index 7d5e9846311..a17cc77ac36 100644
--- a/arch/blackfin/lib/ins.S
+++ b/arch/blackfin/lib/ins.S
@@ -46,7 +46,7 @@ ENTRY(_insl)
.Llong_loop_e: NOP;
sti R3;
RTS;
-
+ENDPROC(_insl)
ENTRY(_insw)
P0 = R0; /* P0 = port */
@@ -61,6 +61,7 @@ ENTRY(_insw)
.Lword_loop_e: NOP;
sti R3;
RTS;
+ENDPROC(_insw)
ENTRY(_insb)
P0 = R0; /* P0 = port */
@@ -75,3 +76,4 @@ ENTRY(_insb)
.Lbyte_loop_e: NOP;
sti R3;
RTS;
+ENDPROC(_insb)
diff --git a/arch/blackfin/lib/memchr.S b/arch/blackfin/lib/memchr.S
index 498122250d0..5da428134d3 100644
--- a/arch/blackfin/lib/memchr.S
+++ b/arch/blackfin/lib/memchr.S
@@ -67,4 +67,4 @@ ENTRY(_memchr)
R0 += -1;
RTS;
-.size _memchr,.-_memchr
+ENDPROC(_memchr)
diff --git a/arch/blackfin/lib/memcmp.S b/arch/blackfin/lib/memcmp.S
index 5b9502368fc..b88c5d2d1eb 100644
--- a/arch/blackfin/lib/memcmp.S
+++ b/arch/blackfin/lib/memcmp.S
@@ -61,7 +61,12 @@ ENTRY(_memcmp)
LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1;
.Lquad_loop_s:
+#ifdef ANOMALY_05000202
+ R0 = [P0++];
+ R1 = [I0++];
+#else
MNOP || R0 = [P0++] || R1 = [I0++];
+#endif
CC = R0 == R1;
IF !CC JUMP .Lquad_different;
.Lquad_loop_e:
@@ -107,4 +112,4 @@ ENTRY(_memcmp)
P3 = I1;
RTS;
-.size _memcmp,.-_memcmp
+ENDPROC(_memcmp)
diff --git a/arch/blackfin/lib/memcpy.S b/arch/blackfin/lib/memcpy.S
index c1e00eff541..14a5585bbd0 100644
--- a/arch/blackfin/lib/memcpy.S
+++ b/arch/blackfin/lib/memcpy.S
@@ -94,13 +94,20 @@ ENTRY(_memcpy)
.Lmore_than_seven:
/* There's at least eight bytes to copy. */
P2 += -1; /* because we unroll one iteration */
- LSETUP(.Lword_loop, .Lword_loop) LC0=P2;
+ LSETUP(.Lword_loops, .Lword_loope) LC0=P2;
R0 = R1;
I1 = P1;
R3 = [I1++];
-.Lword_loop:
+#ifdef ANOMALY_05000202
+.Lword_loops:
+ [P0++] = R3;
+.Lword_loope:
+ R3 = [I1++];
+#else
+.Lword_loops:
+.Lword_loope:
MNOP || [P0++] = R3 || R3 = [I1++];
-
+#endif
[P0++] = R3;
/* Any remaining bytes to copy? */
R3 = 0x3;
@@ -140,3 +147,5 @@ ENTRY(_memcpy)
B[P0--] = R1;
RTS;
+
+ENDPROC(_memcpy)
diff --git a/arch/blackfin/lib/memmove.S b/arch/blackfin/lib/memmove.S
index 2e5fb7f8df1..6ee6e206e77 100644
--- a/arch/blackfin/lib/memmove.S
+++ b/arch/blackfin/lib/memmove.S
@@ -69,8 +69,17 @@ ENTRY(_memmove)
P2 = R2; /* set remainder */
R1 = [I0++];
- LSETUP (.Lquad_loop, .Lquad_loop) LC0=P1;
-.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++];
+ LSETUP (.Lquad_loops, .Lquad_loope) LC0=P1;
+#ifdef ANOMALY_05000202
+.Lquad_loops:
+ [P0++] = R1;
+.Lquad_loope:
+ R1 = [I0++];
+#else
+.Lquad_loops:
+.Lquad_loope:
+ MNOP || [P0++] = R1 || R1 = [I0++];
+#endif
[P0++] = R1;
CC = P2 == 0; /* any remaining bytes? */
@@ -93,6 +102,10 @@ ENTRY(_memmove)
R1 = B[P3--] (Z);
CC = P2 == 0;
IF CC JUMP .Lno_loop;
+#ifdef ANOMALY_05000245
+ NOP;
+ NOP;
+#endif
LSETUP (.Lol_s, .Lol_e) LC0 = P2;
.Lol_s: B[P0--] = R1;
.Lol_e: R1 = B[P3--] (Z);
@@ -100,4 +113,4 @@ ENTRY(_memmove)
P3 = I1;
RTS;
-.size _memmove,.-_memmove
+ENDPROC(_memmove)
diff --git a/arch/blackfin/lib/memset.S b/arch/blackfin/lib/memset.S
index ba6d047568d..8159136a29e 100644
--- a/arch/blackfin/lib/memset.S
+++ b/arch/blackfin/lib/memset.S
@@ -106,4 +106,4 @@ ENTRY(_memset)
B[P0++] = R1;
JUMP .Laligned;
-.size _memset,.-_memset
+ENDPROC(_memset)
diff --git a/arch/blackfin/lib/modsi3.S b/arch/blackfin/lib/modsi3.S
index 528b8b1ccb3..ca1dd3973b3 100644
--- a/arch/blackfin/lib/modsi3.S
+++ b/arch/blackfin/lib/modsi3.S
@@ -77,3 +77,5 @@ ___modsi3:
R0 = 0;
.LRETURN_R0:
RTS;
+
+.size ___modsi3, .-___modsi3
diff --git a/arch/blackfin/lib/outs.S b/arch/blackfin/lib/outs.S
index f8c876fe893..4c3da8ae094 100644
--- a/arch/blackfin/lib/outs.S
+++ b/arch/blackfin/lib/outs.S
@@ -40,6 +40,7 @@ ENTRY(_outsl)
.Llong_loop_s: R0 = [P1++];
.Llong_loop_e: [P0] = R0;
RTS;
+ENDPROC(_outsl)
ENTRY(_outsw)
P0 = R0; /* P0 = port */
@@ -50,6 +51,7 @@ ENTRY(_outsw)
.Lword_loop_s: R0 = W[P1++];
.Lword_loop_e: W[P0] = R0;
RTS;
+ENDPROC(_outsw)
ENTRY(_outsb)
P0 = R0; /* P0 = port */
@@ -60,3 +62,4 @@ ENTRY(_outsb)
.Lbyte_loop_s: R0 = B[P1++];
.Lbyte_loop_e: B[P0] = R0;
RTS;
+ENDPROC(_outsb)
diff --git a/arch/blackfin/lib/smulsi3_highpart.S b/arch/blackfin/lib/smulsi3_highpart.S
index 10b8f8da576..e383cd3eca5 100644
--- a/arch/blackfin/lib/smulsi3_highpart.S
+++ b/arch/blackfin/lib/smulsi3_highpart.S
@@ -28,3 +28,5 @@ ___smulsi3_highpart:
R0 = R0 + R1;
RTS;
+
+.size ___smulsi3_highpart, .-___smulsi3_highpart
diff --git a/arch/blackfin/lib/strcmp.c b/arch/blackfin/lib/strcmp.c
index 2ad47c4254b..4eeefd86907 100644
--- a/arch/blackfin/lib/strcmp.c
+++ b/arch/blackfin/lib/strcmp.c
@@ -6,6 +6,5 @@
int strcmp(const char *dest, const char *src)
{
- return __inline_strcmp(dest, src);
+ return __inline_strcmp(dest, src);
}
-
diff --git a/arch/blackfin/lib/strcpy.c b/arch/blackfin/lib/strcpy.c
index 4dc835a8a19..534589db725 100644
--- a/arch/blackfin/lib/strcpy.c
+++ b/arch/blackfin/lib/strcpy.c
@@ -6,6 +6,5 @@
char *strcpy(char *dest, const char *src)
{
- return __inline_strcpy(dest, src);
+ return __inline_strcpy(dest, src);
}
-
diff --git a/arch/blackfin/lib/strncmp.c b/arch/blackfin/lib/strncmp.c
index 947bcfe3f3b..d791f120bff 100644
--- a/arch/blackfin/lib/strncmp.c
+++ b/arch/blackfin/lib/strncmp.c
@@ -6,6 +6,5 @@
int strncmp(const char *cs, const char *ct, size_t count)
{
- return __inline_strncmp(cs, ct, count);
+ return __inline_strncmp(cs, ct, count);
}
-
diff --git a/arch/blackfin/lib/strncpy.c b/arch/blackfin/lib/strncpy.c
index 77a9b2e9509..1fecb5c71ff 100644
--- a/arch/blackfin/lib/strncpy.c
+++ b/arch/blackfin/lib/strncpy.c
@@ -6,6 +6,5 @@
char *strncpy(char *dest, const char *src, size_t n)
{
- return __inline_strncpy(dest, src, n);
+ return __inline_strncpy(dest, src, n);
}
-
diff --git a/arch/blackfin/lib/udivsi3.S b/arch/blackfin/lib/udivsi3.S
index d39a1291625..58fd96d7476 100644
--- a/arch/blackfin/lib/udivsi3.S
+++ b/arch/blackfin/lib/udivsi3.S
@@ -296,3 +296,5 @@ ENTRY(___udivsi3)
R1 = R0 - R3;
IF CC R0 = R1;
RTS;
+
+ENDPROC(___udivsi3)
diff --git a/arch/blackfin/lib/umodsi3.S b/arch/blackfin/lib/umodsi3.S
index b55ce96ab89..4f2b76ee762 100644
--- a/arch/blackfin/lib/umodsi3.S
+++ b/arch/blackfin/lib/umodsi3.S
@@ -34,7 +34,9 @@
#endif
.extern ___udivsi3;
+.type ___udivsi3, STT_FUNC;
.globl ___umodsi3
+.type ___umodsi3, STT_FUNC;
___umodsi3:
CC=R0==0;
@@ -64,3 +66,5 @@ ___umodsi3:
R0 = 0;
.LRETURN_R0:
RTS;
+
+.size ___umodsi3, .-___umodsi3
diff --git a/arch/blackfin/lib/umulsi3_highpart.S b/arch/blackfin/lib/umulsi3_highpart.S
index aac8218fb25..67b799351e3 100644
--- a/arch/blackfin/lib/umulsi3_highpart.S
+++ b/arch/blackfin/lib/umulsi3_highpart.S
@@ -21,3 +21,5 @@ ___umulsi3_highpart:
R1 = PACK(R1.l,R0.h);
R0 = R1 + R2;
RTS;
+
+.size ___umulsi3_highpart, .-___umulsi3_highpart
diff --git a/arch/blackfin/mach-bf533/Makefile b/arch/blackfin/mach-bf533/Makefile
index 76d2c2b8579..8cce1736360 100644
--- a/arch/blackfin/mach-bf533/Makefile
+++ b/arch/blackfin/mach-bf533/Makefile
@@ -4,6 +4,6 @@
extra-y := head.o
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
-obj-$(CONFIG_CPU_FREQ_BF533) += cpu.o
+obj-$(CONFIG_CPU_FREQ) += cpu.o
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index 23a7f607df3..4545f363e64 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -1,7 +1,7 @@
/*
* File: arch/blackfin/mach-bf533/boards/cm_bf533.c
* Based on: arch/blackfin/mach-bf533/boards/ezkit.c
- * Author: Aidan Williams <aidan@nicta.com.au> Copright 2005
+ * Author: Aidan Williams <aidan@nicta.com.au> Copyright 2005
*
* Created: 2005
* Description: Board description file
@@ -34,7 +34,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/bfin5xx_spi.h>
/*
@@ -51,11 +51,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
- },{
+ }, {
.name = "kernel",
.size = 0xe0000,
.offset = 0x20000
- },{
+ }, {
.name = "file system",
.size = 0x700000,
.offset = 0x00100000,
@@ -98,7 +98,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.platform_data = &bfin_spi_flash_data,
.controller_data = &spi_flash_chip_info,
.mode = SPI_MODE_3,
- },{
+ }, {
.modalias = "bfin_spi_adc", /* Name of spi_driver for this device */
.max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */
.bus_num = 1, /* Framework bus number */
@@ -145,7 +145,7 @@ static struct resource smc91x_resources[] = {
.start = 0x20200300,
.end = 0x20200300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF0,
.end = IRQ_PF0,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -194,11 +194,11 @@ static struct resource isp1362_hcd_resources[] = {
.start = 0x20308000,
.end = 0x20308000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x20308004,
.end = 0x20308004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF4,
.end = IRQ_PF4,
.flags = IORESOURCE_IRQ,
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index 747298ea907..0000b8f1239 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -1,6 +1,6 @@
/*
* File: arch/blackfin/mach-bf533/ezkit.c
- * Based on: Orginal Work
+ * Based on: Original Work
* Author: Aidan Williams <aidan@nicta.com.au>
*
* Created: 2005
@@ -35,7 +35,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/bfin5xx_spi.h>
/*
@@ -61,7 +61,7 @@ static struct resource smc91x_resources[] = {
.start = 0x20310300,
.end = 0x20310300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF9,
.end = IRQ_PF9,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -85,11 +85,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
- },{
+ }, {
.name = "kernel",
.size = 0xe0000,
.offset = 0x20000
- },{
+ }, {
.name = "file system",
.size = 0x700000,
.offset = 0x00100000,
diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c
index c0f43ccfbfb..9bc1f0d0ab5 100644
--- a/arch/blackfin/mach-bf533/boards/generic_board.c
+++ b/arch/blackfin/mach-bf533/boards/generic_board.c
@@ -30,7 +30,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
/*
* Name the Board for the /proc/cpuinfo
@@ -53,11 +53,11 @@ static struct resource smc91x_resources[] = {
.start = 0x20300300,
.end = 0x20300300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PROG_INTB,
.end = IRQ_PROG_INTB,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- },{
+ }, {
/*
* denotes the flag pin and is used directly if
* CONFIG_IRQCHIP_DEMUX_GPIO is defined.
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index 9a472fe1583..a9143c4cbdc 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -37,7 +37,7 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb_isp1362.h>
#endif
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/bfin5xx_spi.h>
/*
@@ -62,7 +62,7 @@ static struct resource smc91x_resources[] = {
.start = 0x20300300,
.end = 0x20300300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -83,7 +83,7 @@ static struct resource net2272_bfin_resources[] = {
.start = 0x20300000,
.end = 0x20300000 + 0x100,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF10,
.end = IRQ_PF10,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -108,11 +108,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
- },{
+ }, {
.name = "kernel",
.size = 0xe0000,
.offset = 0x20000
- },{
+ }, {
.name = "file system",
.size = 0x700000,
.offset = 0x00100000,
@@ -229,19 +229,19 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_PBX)
{
- .modalias = "fxs-spi",
- .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 1,
- .chip_select = 3,
- .controller_data= &spi_si3xxx_chip_info,
+ .modalias = "fxs-spi",
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 3,
+ .controller_data = &spi_si3xxx_chip_info,
.mode = SPI_MODE_3,
},
{
- .modalias = "fxo-spi",
- .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 1,
- .chip_select = 2,
- .controller_data= &spi_si3xxx_chip_info,
+ .modalias = "fxo-spi",
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 2,
+ .controller_data = &spi_si3xxx_chip_info,
.mode = SPI_MODE_3,
},
#endif
diff --git a/arch/blackfin/mach-bf533/cpu.c b/arch/blackfin/mach-bf533/cpu.c
index 99547c4c290..6fd9cfd0a31 100644
--- a/arch/blackfin/mach-bf533/cpu.c
+++ b/arch/blackfin/mach-bf533/cpu.c
@@ -79,8 +79,7 @@ static int bf533_target(struct cpufreq_policy *policy,
int i;
struct cpufreq_freqs freqs;
- if (cpufreq_frequency_table_target
- (policy, bf533_freq_table, target_freq, relation, &index))
+ if (cpufreq_frequency_table_target(policy, bf533_freq_table, target_freq, relation, &index))
return -EINVAL;
cclk_mhz = bf533_freq_table[index].frequency;
vco_mhz = bf533_freq_table[index].index;
diff --git a/arch/blackfin/mach-bf533/dma.c b/arch/blackfin/mach-bf533/dma.c
new file mode 100644
index 00000000000..6c909cf4f7b
--- /dev/null
+++ b/arch/blackfin/mach-bf533/dma.c
@@ -0,0 +1,95 @@
+/*
+ * File: arch/blackfin/mach-bf533/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA7_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_PPI:
+ ret_irq = IRQ_PPI;
+ break;
+
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+
+ case CH_SPI:
+ ret_irq = IRQ_SPI;
+ break;
+
+ case CH_UART_RX:
+ ret_irq = IRQ_UART_RX;
+ break;
+
+ case CH_UART_TX:
+ ret_irq = IRQ_UART_TX;
+ break;
+
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MEM_DMA0;
+ break;
+
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MEM_DMA1;
+ break;
+ }
+ return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf533/head.S b/arch/blackfin/mach-bf533/head.S
index 4db9e624090..7dd0e9c3a93 100644
--- a/arch/blackfin/mach-bf533/head.S
+++ b/arch/blackfin/mach-bf533/head.S
@@ -28,7 +28,9 @@
*/
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/blackfin.h>
+#include <asm/trace.h>
#if CONFIG_BFIN_KERNEL_CLOCK
#include <asm/mach/mem_init.h>
#endif
@@ -45,19 +47,19 @@
#define INITIAL_STACK 0xFFB01000
-.text
+__INIT
ENTRY(__start)
-ENTRY(__stext)
/* R0: argument of command line string, passed from uboot, save it */
R7 = R0;
- /* Set the SYSCFG register */
+ /* Set the SYSCFG register:
+ * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit)
+ */
R0 = 0x36;
- /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
SYSCFG = R0;
R0 = 0;
- /*Clear Out All the data and pointer Registers*/
+ /* Clear Out All the data and pointer Registers */
R1 = R0;
R2 = R0;
R3 = R0;
@@ -79,7 +81,7 @@ ENTRY(__stext)
L2 = r0;
L3 = r0;
- /* Clear Out All the DAG Registers*/
+ /* Clear Out All the DAG Registers */
B0 = r0;
B1 = r0;
B2 = r0;
@@ -95,6 +97,10 @@ ENTRY(__stext)
M2 = r0;
M3 = r0;
+ trace_buffer_start(p0,r0);
+ P0 = R1;
+ R0 = R1;
+
#if CONFIG_DEBUG_KERNEL_START
/*
@@ -265,6 +271,7 @@ ENTRY(__stext)
.LWAIT_HERE:
jump .LWAIT_HERE;
+ENDPROC(__start)
ENTRY(_real_start)
[ -- sp ] = reti;
@@ -303,7 +310,7 @@ ENTRY(_real_start)
.L_clear_zero:
W[p1++] = r0;
-/* pass the uboot arguments to the global value command line */
+ /* pass the uboot arguments to the global value command line */
R0 = R7;
call _cmdline_init;
@@ -322,7 +329,7 @@ ENTRY(_real_start)
[p1] = r1;
/*
- * load the current thread pointer and stack
+ * load the current thread pointer and stack
*/
r1.l = _init_thread_union;
r1.h = _init_thread_union;
@@ -333,9 +340,10 @@ ENTRY(_real_start)
sp = r1;
usp = sp;
fp = sp;
- call _start_kernel;
-.L_exit:
- jump.s .L_exit;
+ jump.l _start_kernel;
+ENDPROC(_real_start)
+
+__FINIT
.section .l1.text
#if CONFIG_BFIN_KERNEL_CLOCK
@@ -439,12 +447,13 @@ ENTRY(_start_dma_code)
p0.h = hi(SIC_IWR);
p0.l = lo(SIC_IWR);
- r0.l = lo(IWR_ENABLE_ALL)
- r0.h = hi(IWR_ENABLE_ALL)
+ r0.l = lo(IWR_ENABLE_ALL);
+ r0.h = hi(IWR_ENABLE_ALL);
[p0] = r0;
SSYNC;
RTS;
+ENDPROC(_start_dma_code)
#endif /* CONFIG_BFIN_KERNEL_CLOCK */
ENTRY(_bfin_reset)
diff --git a/arch/blackfin/mach-bf533/ints-priority.c b/arch/blackfin/mach-bf533/ints-priority.c
index 36a69334520..7d79e0f9503 100644
--- a/arch/blackfin/mach-bf533/ints-priority.c
+++ b/arch/blackfin/mach-bf533/ints-priority.c
@@ -4,7 +4,7 @@
* Author: Michael Hennerich
*
* Created: ?
- * Description: Set up the interupt priorities
+ * Description: Set up the interrupt priorities
*
* Modified:
* Copyright 2004-2006 Analog Devices Inc.
@@ -28,8 +28,8 @@
*/
#include <linux/module.h>
+#include <linux/irq.h>
#include <asm/blackfin.h>
-#include <asm/irq.h>
void program_IAR(void)
{
diff --git a/arch/blackfin/mach-bf537/Makefile b/arch/blackfin/mach-bf537/Makefile
index f32d44215bb..7e7c9c8ac5b 100644
--- a/arch/blackfin/mach-bf537/Makefile
+++ b/arch/blackfin/mach-bf537/Makefile
@@ -4,6 +4,6 @@
extra-y := head.o
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
obj-$(CONFIG_CPU_FREQ) += cpu.o
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
index 6a60618a78e..a8f947b7275 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -35,7 +35,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/bfin5xx_spi.h>
/*
@@ -53,11 +53,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
- },{
+ }, {
.name = "kernel",
.size = 0xe0000,
.offset = 0x20000
- },{
+ }, {
.name = "file system",
.size = 0x700000,
.offset = 0x00100000,
@@ -202,7 +202,7 @@ static struct resource smc91x_resources[] = {
.start = 0x20200300,
.end = 0x20200300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF14,
.end = IRQ_PF14,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -223,11 +223,11 @@ static struct resource isp1362_hcd_resources[] = {
.start = 0x20308000,
.end = 0x20308000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x20308004,
.end = 0x20308004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PG15,
.end = IRQ_PG15,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -262,7 +262,7 @@ static struct resource net2272_bfin_resources[] = {
.start = 0x20200000,
.end = 0x20200000 + 0x100,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -283,7 +283,7 @@ static struct resource bfin_uart_resources[] = {
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
diff --git a/arch/blackfin/mach-bf537/boards/eth_mac.c b/arch/blackfin/mach-bf537/boards/eth_mac.c
index e129a08d63d..a725cc8a929 100644
--- a/arch/blackfin/mach-bf537/boards/eth_mac.c
+++ b/arch/blackfin/mach-bf537/boards/eth_mac.c
@@ -20,8 +20,7 @@
#include <linux/module.h>
#include <asm/blackfin.h>
-#if defined(CONFIG_GENERIC_BOARD) \
- || defined(CONFIG_BFIN537_STAMP)
+#if defined(CONFIG_GENERIC_BOARD) || defined(CONFIG_BFIN537_STAMP)
/*
* Currently the MAC address is saved in Flash by U-Boot
@@ -43,7 +42,7 @@ void get_bf537_ether_addr(char *addr)
*/
void get_bf537_ether_addr(char *addr)
{
- printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n",__FILE__);
+ printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n", __FILE__);
}
#endif
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 9019c0edbe7..648d984e98d 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -35,9 +35,9 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb_isp1362.h>
-#include <asm/irq.h>
-#include <asm/bfin5xx_spi.h>
+#include <linux/irq.h>
#include <linux/usb_sl811.h>
+#include <asm/bfin5xx_spi.h>
/*
* Name the Board for the /proc/cpuinfo
@@ -54,19 +54,19 @@ static struct resource bfin_pcmcia_cf_resources[] = {
.start = 0x20310000, /* IO PORT */
.end = 0x20312000,
.flags = IORESOURCE_MEM,
- },{
- .start = 0x20311000, /* Attribute Memeory */
+ }, {
+ .start = 0x20311000, /* Attribute Memory */
.end = 0x20311FFF,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PROG_INTA,
.end = IRQ_PROG_INTA,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
- },{
+ }, {
.start = IRQ_PF4,
.end = IRQ_PF4,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
- },{
+ }, {
.start = 6, /* Card Detect PF6 */
.end = 6,
.flags = IORESOURCE_IRQ,
@@ -95,11 +95,11 @@ static struct resource smc91x_resources[] = {
.start = 0x20300300,
.end = 0x20300300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PROG_INTB,
.end = IRQ_PROG_INTB,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- },{
+ }, {
/*
* denotes the flag pin and is used directly if
* CONFIG_IRQCHIP_DEMUX_GPIO is defined.
@@ -123,15 +123,15 @@ static struct resource sl811_hcd_resources[] = {
.start = 0x20340000,
.end = 0x20340000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x20340004,
.end = 0x20340004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PROG_INTA,
.end = IRQ_PROG_INTA,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- },{
+ }, {
.start = IRQ_PF0 + CONFIG_USB_SL811_BFIN_GPIO,
.end = IRQ_PF0 + CONFIG_USB_SL811_BFIN_GPIO,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -179,15 +179,15 @@ static struct resource isp1362_hcd_resources[] = {
.start = 0x20360000,
.end = 0x20360000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x20360004,
.end = 0x20360004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PROG_INTA,
.end = IRQ_PROG_INTA,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- },{
+ }, {
.start = IRQ_PF0 + CONFIG_USB_ISP1362_BFIN_GPIO,
.end = IRQ_PF0 + CONFIG_USB_ISP1362_BFIN_GPIO,
.flags = IORESOURCE_IRQ,
@@ -228,7 +228,7 @@ static struct resource net2272_bfin_resources[] = {
.start = 0x20300000,
.end = 0x20300000 + 0x100,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -253,11 +253,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
- },{
+ }, {
.name = "kernel",
.size = 0xe0000,
.offset = 0x20000
- },{
+ }, {
.name = "file system",
.size = 0x700000,
.offset = 0x00100000,
@@ -375,7 +375,7 @@ static struct resource bfin_uart_resources[] = {
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c
index 40d3a1b70ee..8806f1230f2 100644
--- a/arch/blackfin/mach-bf537/boards/pnav10.c
+++ b/arch/blackfin/mach-bf537/boards/pnav10.c
@@ -37,7 +37,7 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb_isp1362.h>
#endif
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/bfin5xx_spi.h>
#include <linux/usb_sl811.h>
@@ -58,15 +58,15 @@ static struct resource bfin_pcmcia_cf_resources[] = {
.start = 0x20310000, /* IO PORT */
.end = 0x20312000,
.flags = IORESOURCE_MEM,
- },{
- .start = 0x20311000, /* Attribute Memeory */
+ }, {
+ .start = 0x20311000, /* Attribute Memory */
.end = 0x20311FFF,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF4,
.end = IRQ_PF4,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
- },{
+ }, {
.start = 6, /* Card Detect PF6 */
.end = 6,
.flags = IORESOURCE_IRQ,
@@ -95,7 +95,7 @@ static struct resource smc91x_resources[] = {
.start = 0x20300300,
.end = 0x20300300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
@@ -116,11 +116,11 @@ static struct resource sl811_hcd_resources[] = {
.start = 0x20340000,
.end = 0x20340000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x20340004,
.end = 0x20340004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = CONFIG_USB_SL811_BFIN_IRQ,
.end = CONFIG_USB_SL811_BFIN_IRQ,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -167,11 +167,11 @@ static struct resource isp1362_hcd_resources[] = {
.start = 0x20360000,
.end = 0x20360000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x20360004,
.end = 0x20360004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -212,7 +212,7 @@ static struct resource net2272_bfin_resources[] = {
.start = 0x20300000,
.end = 0x20300000 + 0x100,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -238,11 +238,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
- },{
+ }, {
.name = "kernel",
.size = 0xe0000,
.offset = 0x20000
- },{
+ }, {
.name = "file system",
.size = 0x700000,
.offset = 0x00100000,
@@ -294,16 +294,6 @@ static struct bfin5xx_spi_chip spi_mmc_chip_info = {
};
#endif
-#if defined(CONFIG_PBX)
-static struct bfin5xx_spi_chip spi_si3xxx_chip_info = {
- .ctl_reg = 0x4, /* send zero */
- .enable_dma = 0,
- .bits_per_word = 8,
- .cs_change_per_word = 1,
-};
-#endif
-
-
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
.cs_change_per_word = 1,
@@ -392,24 +382,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
.mode = SPI_MODE_3,
},
#endif
-#if defined(CONFIG_PBX)
- {
- .modalias = "fxs-spi",
- .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 1,
- .chip_select = 3,
- .controller_data= &spi_si3xxx_chip_info,
- .mode = SPI_MODE_3,
- },
- {
- .modalias = "fxo-spi",
- .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 1,
- .chip_select = 2,
- .controller_data= &spi_si3xxx_chip_info,
- .mode = SPI_MODE_3,
- },
-#endif
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
{
.modalias = "ad7877",
@@ -451,7 +423,7 @@ static struct resource bfin_uart_resources[] = {
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index ba2f875a7f7..9c43d775651 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -37,12 +37,10 @@
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
#include <linux/usb_isp1362.h>
#endif
-#include <asm/irq.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-#include <asm/bfin5xx_spi.h>
#include <linux/usb_sl811.h>
-
+#include <asm/bfin5xx_spi.h>
#include <linux/spi/ad7877.h>
/*
@@ -85,7 +83,7 @@ static struct platform_device *bfin_isp1761_devices[] = {
int __init bfin_isp1761_init(void)
{
- unsigned int num_devices=ARRAY_SIZE(bfin_isp1761_devices);
+ unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
@@ -107,15 +105,15 @@ static struct resource bfin_pcmcia_cf_resources[] = {
.start = 0x20310000, /* IO PORT */
.end = 0x20312000,
.flags = IORESOURCE_MEM,
- },{
- .start = 0x20311000, /* Attribute Memeory */
+ }, {
+ .start = 0x20311000, /* Attribute Memory */
.end = 0x20311FFF,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF4,
.end = IRQ_PF4,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
- },{
+ }, {
.start = 6, /* Card Detect PF6 */
.end = 6,
.flags = IORESOURCE_IRQ,
@@ -144,7 +142,7 @@ static struct resource smc91x_resources[] = {
.start = 0x20300300,
.end = 0x20300300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
@@ -159,17 +157,39 @@ static struct platform_device smc91x_device = {
};
#endif
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+static struct resource dm9000_resources[] = {
+ [0] = {
+ .start = 0x203FB800,
+ .end = 0x203FB800 + 8,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_PF9,
+ .end = IRQ_PF9,
+ .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE),
+ },
+};
+
+static struct platform_device dm9000_device = {
+ .name = "dm9000",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(dm9000_resources),
+ .resource = dm9000_resources,
+};
+#endif
+
#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE)
static struct resource sl811_hcd_resources[] = {
{
.start = 0x20340000,
.end = 0x20340000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x20340004,
.end = 0x20340004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = CONFIG_USB_SL811_BFIN_IRQ,
.end = CONFIG_USB_SL811_BFIN_IRQ,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -216,11 +236,11 @@ static struct resource isp1362_hcd_resources[] = {
.start = 0x20360000,
.end = 0x20360000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x20360004,
.end = 0x20360004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
.end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -261,7 +281,7 @@ static struct resource net2272_bfin_resources[] = {
.start = 0x20300000,
.end = 0x20300000 + 0x100,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF7,
.end = IRQ_PF7,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -287,11 +307,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
- },{
+ }, {
.name = "kernel",
.size = 0xe0000,
.offset = 0x20000
- },{
+ }, {
.name = "file system",
.size = 0x700000,
.offset = 0x00100000,
@@ -361,7 +381,6 @@ static struct bfin5xx_spi_chip ad5304_chip_info = {
#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
static struct bfin5xx_spi_chip spi_ad7877_chip_info = {
-// .cs_change_per_word = 1,
.enable_dma = 0,
.bits_per_word = 16,
};
@@ -449,19 +468,19 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
#endif
#if defined(CONFIG_PBX)
{
- .modalias = "fxs-spi",
- .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 1,
- .chip_select = 3,
- .controller_data= &spi_si3xxx_chip_info,
+ .modalias = "fxs-spi",
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 3,
+ .controller_data = &spi_si3xxx_chip_info,
.mode = SPI_MODE_3,
},
{
- .modalias = "fxo-spi",
- .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
- .bus_num = 1,
- .chip_select = 2,
- .controller_data= &spi_si3xxx_chip_info,
+ .modalias = "fxo-spi",
+ .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
+ .bus_num = 1,
+ .chip_select = 2,
+ .controller_data = &spi_si3xxx_chip_info,
.mode = SPI_MODE_3,
},
#endif
@@ -516,7 +535,7 @@ static struct resource bfin_uart_resources[] = {
.start = 0xFFC00400,
.end = 0xFFC004FF,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0xFFC02000,
.end = 0xFFC020FF,
.flags = IORESOURCE_MEM,
@@ -571,6 +590,10 @@ static struct platform_device *stamp_devices[] __initdata = {
&smc91x_device,
#endif
+#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
+ &dm9000_device,
+#endif
+
#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
&bfin_mac_device,
#endif
diff --git a/arch/blackfin/mach-bf537/dma.c b/arch/blackfin/mach-bf537/dma.c
new file mode 100644
index 00000000000..706cb97b026
--- /dev/null
+++ b/arch/blackfin/mach-bf537/dma.c
@@ -0,0 +1,115 @@
+/*
+ * File: arch/blackfin/mach-bf537/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA11_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_PPI:
+ ret_irq = IRQ_PPI;
+ break;
+
+ case CH_EMAC_RX:
+ ret_irq = IRQ_MAC_RX;
+ break;
+
+ case CH_EMAC_TX:
+ ret_irq = IRQ_MAC_TX;
+ break;
+
+ case CH_UART1_RX:
+ ret_irq = IRQ_UART1_RX;
+ break;
+
+ case CH_UART1_TX:
+ ret_irq = IRQ_UART1_TX;
+ break;
+
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+
+ case CH_SPI:
+ ret_irq = IRQ_SPI;
+ break;
+
+ case CH_UART_RX:
+ ret_irq = IRQ_UART_RX;
+ break;
+
+ case CH_UART_TX:
+ ret_irq = IRQ_UART_TX;
+ break;
+
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MEM_DMA0;
+ break;
+
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MEM_DMA1;
+ break;
+ }
+ return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf537/head.S b/arch/blackfin/mach-bf537/head.S
index 2c2652bee7e..429c8a1019d 100644
--- a/arch/blackfin/mach-bf537/head.S
+++ b/arch/blackfin/mach-bf537/head.S
@@ -28,7 +28,10 @@
*/
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/blackfin.h>
+#include <asm/trace.h>
+
#if CONFIG_BFIN_KERNEL_CLOCK
#include <asm/mach/mem_init.h>
#endif
@@ -40,20 +43,21 @@
.extern ___bss_start
.extern _bf53x_relocate_l1_mem
-#define INITIAL_STACK 0xFFB01000
+#define INITIAL_STACK 0xFFB01000
-.text
+__INIT
ENTRY(__start)
-ENTRY(__stext)
/* R0: argument of command line string, passed from uboot, save it */
R7 = R0;
- /* Set the SYSCFG register */
+ /* Set the SYSCFG register:
+ * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit)
+ */
R0 = 0x36;
- SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+ SYSCFG = R0;
R0 = 0;
- /* Clear Out All the data and pointer Registers*/
+ /* Clear Out All the data and pointer Registers */
R1 = R0;
R2 = R0;
R3 = R0;
@@ -75,7 +79,7 @@ ENTRY(__stext)
L2 = r0;
L3 = r0;
- /* Clear Out All the DAG Registers*/
+ /* Clear Out All the DAG Registers */
B0 = r0;
B1 = r0;
B2 = r0;
@@ -91,6 +95,10 @@ ENTRY(__stext)
M2 = r0;
M3 = r0;
+ trace_buffer_start(p0,r0);
+ P0 = R1;
+ R0 = R1;
+
/* Turn off the icache */
p0.l = (IMEM_CONTROL & 0xFFFF);
p0.h = (IMEM_CONTROL >> 16);
@@ -191,7 +199,7 @@ ENTRY(__stext)
p0.h = hi(UART_DLL);
p0.l = lo(UART_DLL);
- r0 = 0x00(Z);
+ r0 = 0x0(Z);
w[p0] = r0.L;
ssync;
@@ -218,6 +226,7 @@ ENTRY(__stext)
#if CONFIG_BFIN_KERNEL_CLOCK
call _start_dma_code;
#endif
+
/* Code for initializing Async memory banks */
p2.h = hi(EBIU_AMBCTL1);
@@ -272,6 +281,7 @@ ENTRY(__stext)
.LWAIT_HERE:
jump .LWAIT_HERE;
+ENDPROC(__start)
ENTRY(_real_start)
[ -- sp ] = reti;
@@ -291,7 +301,7 @@ ENTRY(_real_start)
p2.h = ___bss_stop;
r0 = 0;
p2 -= p1;
- lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+ lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
.L_clear_bss:
B[p1++] = r0;
@@ -306,7 +316,7 @@ ENTRY(_real_start)
r0 = r0 >> 1;
p2 = r0;
r0 = 0;
- lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+ lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
.L_clear_zero:
W[p1++] = r0;
@@ -328,9 +338,8 @@ ENTRY(_real_start)
r1 = p3;
[p1] = r1;
-
/*
- * load the current thread pointer and stack
+ * load the current thread pointer and stack
*/
r1.l = _init_thread_union;
r1.h = _init_thread_union;
@@ -341,9 +350,10 @@ ENTRY(_real_start)
sp = r1;
usp = sp;
fp = sp;
- call _start_kernel;
-.L_exit:
- jump.s .L_exit;
+ jump.l _start_kernel;
+ENDPROC(_real_start)
+
+__FINIT
.section .l1.text
#if CONFIG_BFIN_KERNEL_CLOCK
@@ -462,6 +472,7 @@ ENTRY(_start_dma_code)
SSYNC;
RTS;
+ENDPROC(_start_dma_code)
#endif /* CONFIG_BFIN_KERNEL_CLOCK */
ENTRY(_bfin_reset)
diff --git a/arch/blackfin/mach-bf537/ints-priority.c b/arch/blackfin/mach-bf537/ints-priority.c
index fd6308eccbe..a8b915f202e 100644
--- a/arch/blackfin/mach-bf537/ints-priority.c
+++ b/arch/blackfin/mach-bf537/ints-priority.c
@@ -4,7 +4,7 @@
* Author: Michael Hennerich
*
* Created:
- * Description: Set up the interupt priorities
+ * Description: Set up the interrupt priorities
*
* Modified:
* Copyright 2004-2006 Analog Devices Inc.
@@ -28,8 +28,8 @@
*/
#include <linux/module.h>
+#include <linux/irq.h>
#include <asm/blackfin.h>
-#include <asm/irq.h>
void program_IAR(void)
{
diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig
new file mode 100644
index 00000000000..e78b03d56c7
--- /dev/null
+++ b/arch/blackfin/mach-bf548/Kconfig
@@ -0,0 +1,316 @@
+if (BF54x)
+
+menu "BF548 Specific Configuration"
+
+comment "Interrupt Priority Assignment"
+menu "Priority"
+
+config IRQ_PLL_WAKEUP
+ int "IRQ_PLL_WAKEUP"
+ default 7
+config IRQ_DMAC0_ERR
+ int "IRQ_DMAC0_ERR"
+ default 7
+config IRQ_EPPI0_ERR
+ int "IRQ_EPPI0_ERR"
+ default 7
+config IRQ_SPORT0_ERR
+ int "IRQ_SPORT0_ERR"
+ default 7
+config IRQ_SPORT1_ERR
+ int "IRQ_SPORT1_ERR"
+ default 7
+config IRQ_SPI0_ERR
+ int "IRQ_SPI0_ERR"
+ default 7
+config IRQ_UART0_ERR
+ int "IRQ_UART0_ERR"
+ default 7
+config IRQ_RTC
+ int "IRQ_RTC"
+ default 8
+config IRQ_EPPI0
+ int "IRQ_EPPI0"
+ default 8
+config IRQ_SPORT0_RX
+ int "IRQ_SPORT0_RX"
+ default 9
+config IRQ_SPORT0_TX
+ int "IRQ_SPORT0_TX"
+ default 9
+config IRQ_SPORT1_RX
+ int "IRQ_SPORT1_RX"
+ default 9
+config IRQ_SPORT1_TX
+ int "IRQ_SPORT1_TX"
+ default 9
+config IRQ_SPI0
+ int "IRQ_SPI0"
+ default 10
+config IRQ_UART0_RX
+ int "IRQ_UART0_RX"
+ default 10
+config IRQ_UART0_TX
+ int "IRQ_UART0_TX"
+ default 10
+config IRQ_TIMER8
+ int "IRQ_TIMER8"
+ default 11
+config IRQ_TIMER9
+ int "IRQ_TIMER9"
+ default 11
+config IRQ_TIMER10
+ int "IRQ_TIMER10"
+ default 11
+config IRQ_PINT0
+ int "IRQ_PINT0"
+ default 12
+config IRQ_PINT1
+ int "IRQ_PINT0"
+ default 12
+config IRQ_MDMAS0
+ int "IRQ_MDMAS0"
+ default 13
+config IRQ_MDMAS1
+ int "IRQ_DMDMAS1"
+ default 13
+config IRQ_WATCHDOG
+ int "IRQ_WATCHDOG"
+ default 13
+config IRQ_DMAC1_ERR
+ int "IRQ_DMAC1_ERR"
+ default 7
+config IRQ_SPORT2_ERR
+ int "IRQ_SPORT2_ERR"
+ default 7
+config IRQ_SPORT3_ERR
+ int "IRQ_SPORT3_ERR"
+ default 7
+config IRQ_MXVR_DATA
+ int "IRQ MXVR Data"
+ default 7
+config IRQ_SPI1_ERR
+ int "IRQ_SPI1_ERR"
+ default 7
+config IRQ_SPI2_ERR
+ int "IRQ_SPI2_ERR"
+ default 7
+config IRQ_UART1_ERR
+ int "IRQ_UART1_ERR"
+ default 7
+config IRQ_UART2_ERR
+ int "IRQ_UART2_ERR"
+ default 7
+config IRQ_CAN0_ERR
+ int "IRQ_CAN0_ERR"
+ default 7
+config IRQ_SPORT2_RX
+ int "IRQ_SPORT2_RX"
+ default 9
+config IRQ_SPORT2_TX
+ int "IRQ_SPORT2_TX"
+ default 9
+config IRQ_SPORT3_RX
+ int "IRQ_SPORT3_RX"
+ default 9
+config IRQ_SPORT3_TX
+ int "IRQ_SPORT3_TX"
+ default 9
+config IRQ_EPPI1
+ int "IRQ_EPPI1"
+ default 9
+config IRQ_EPPI2
+ int "IRQ_EPPI2"
+ default 9
+config IRQ_SPI1
+ int "IRQ_SPI1"
+ default 10
+config IRQ_SPI2
+ int "IRQ_SPI2"
+ default 10
+config IRQ_UART1_RX
+ int "IRQ_UART1_RX"
+ default 10
+config IRQ_UART1_TX
+ int "IRQ_UART1_TX"
+ default 10
+config IRQ_ATAPI_RX
+ int "IRQ_ATAPI_RX"
+ default 10
+config IRQ_ATAPI_TX
+ int "IRQ_ATAPI_TX"
+ default 10
+config IRQ_TWI0
+ int "IRQ_TWI0"
+ default 11
+config IRQ_TWI1
+ int "IRQ_TWI1"
+ default 11
+config IRQ_CAN0_RX
+ int "IRQ_CAN_RX"
+ default 11
+config IRQ_CAN0_TX
+ int "IRQ_CAN_TX"
+ default 11
+config IRQ_MDMAS2
+ int "IRQ_MDMAS2"
+ default 13
+config IRQ_MDMAS3
+ int "IRQ_DMMAS3"
+ default 13
+config IRQ_MXVR_ERR
+ int "IRQ_MXVR_ERR"
+ default 11
+config IRQ_MXVR_MSG
+ int "IRQ_MXVR_MSG"
+ default 11
+config IRQ_MXVR_PKT
+ int "IRQ_MXVR_PKT"
+ default 11
+config IRQ_EPPI1_ERR
+ int "IRQ_EPPI1_ERR"
+ default 7
+config IRQ_EPPI2_ERR
+ int "IRQ_EPPI2_ERR"
+ default 7
+config IRQ_UART3_ERR
+ int "IRQ_UART3_ERR"
+ default 7
+config IRQ_HOST_ERR
+ int "IRQ_HOST_ERR"
+ default 7
+config IRQ_PIXC_ERR
+ int "IRQ_PIXC_ERR"
+ default 7
+config IRQ_NFC_ERR
+ int "IRQ_NFC_ERR"
+ default 7
+config IRQ_ATAPI_ERR
+ int "IRQ_ATAPI_ERR"
+ default 7
+config IRQ_CAN1_ERR
+ int "IRQ_CAN1_ERR"
+ default 7
+config IRQ_HS_DMA_ERR
+ int "IRQ Handshake DMA Status"
+ default 7
+config IRQ_PIXC_IN0
+ int "IRQ PIXC IN0"
+ default 8
+config IRQ_PIXC_IN1
+ int "IRQ PIXC IN1"
+ default 8
+config IRQ_PIXC_OUT
+ int "IRQ PIXC OUT"
+ default 8
+config IRQ_SDH
+ int "IRQ SDH"
+ default 8
+config IRQ_CNT
+ int "IRQ CNT"
+ default 8
+config IRQ_KEY
+ int "IRQ KEY"
+ default 8
+config IRQ_CAN1_RX
+ int "IRQ CAN1 RX"
+ default 11
+config IRQ_CAN1_TX
+ int "IRQ_CAN1_TX"
+ default 11
+config IRQ_SDH_MASK0
+ int "IRQ_SDH_MASK0"
+ default 11
+config IRQ_SDH_MASK1
+ int "IRQ_SDH_MASK1"
+ default 11
+config IRQ_USB_INT0
+ int "IRQ USB INT0"
+ default 11
+config IRQ_USB_INT1
+ int "IRQ USB INT1"
+ default 11
+config IRQ_USB_INT2
+ int "IRQ USB INT2"
+ default 11
+config IRQ_USB_DMA
+ int "IRQ USB DMA"
+ default 11
+config IRQ_OTPSEC
+ int "IRQ OPTSEC"
+ default 11
+config IRQ_TIMER0
+ int "IRQ_TIMER0"
+ default 11
+config IRQ_TIMER1
+ int "IRQ_TIMER1"
+ default 11
+config IRQ_TIMER2
+ int "IRQ_TIMER2"
+ default 11
+config IRQ_TIMER3
+ int "IRQ_TIMER3"
+ default 11
+config IRQ_TIMER4
+ int "IRQ_TIMER4"
+ default 11
+config IRQ_TIMER5
+ int "IRQ_TIMER5"
+ default 11
+config IRQ_TIMER6
+ int "IRQ_TIMER6"
+ default 11
+config IRQ_TIMER7
+ int "IRQ_TIMER7"
+ default 11
+config IRQ_PINT2
+ int "IRQ_PIN2"
+ default 11
+config IRQ_PINT3
+ int "IRQ_PIN3"
+ default 11
+
+ help
+ Enter the priority numbers between 7-13 ONLY. Others are Reserved.
+ This applies to all the above. It is not recommended to assign the
+ highest priority number 7 to UART or any other device.
+
+endmenu
+
+comment "Pin Interrupt to Port Assignment"
+menu "Assignment"
+
+config PINTx_REASSIGN
+ bool "Reprogram PINT Assignment"
+ default n
+ help
+ The interrupt assignment registers controls the pin-to-interrupt
+ assignment in a byte-wide manner. Each option allows you to select
+ a set of pins (High/Low Byte) of an specific Port being mapped
+ to one of the four PIN Interrupts IRQ_PINTx.
+
+ You shouldn't change any of these unless you know exactly what you're doing.
+ Please consult the Blackfin BF54x Processor Hardware Reference Manual.
+
+config PINT0_ASSIGN
+ hex "PINT0_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x00000101
+config PINT1_ASSIGN
+ hex "PINT1_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x01010000
+config PINT2_ASSIGN
+ hex "PINT2_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x00000101
+config PINT3_ASSIGN
+ hex "PINT3_ASSIGN"
+ depends on PINTx_REASSIGN
+ default 0x02020303
+
+endmenu
+
+endmenu
+
+endif
diff --git a/arch/blackfin/mach-bf548/Makefile b/arch/blackfin/mach-bf548/Makefile
new file mode 100644
index 00000000000..060ad78ebf1
--- /dev/null
+++ b/arch/blackfin/mach-bf548/Makefile
@@ -0,0 +1,9 @@
+#
+# arch/blackfin/mach-bf537/Makefile
+#
+
+extra-y := head.o
+
+obj-y := ints-priority.o dma.o gpio.o
+
+obj-$(CONFIG_CPU_FREQ) += cpu.o
diff --git a/arch/blackfin/mach-bf548/boards/Makefile b/arch/blackfin/mach-bf548/boards/Makefile
new file mode 100644
index 00000000000..486e07c99a5
--- /dev/null
+++ b/arch/blackfin/mach-bf548/boards/Makefile
@@ -0,0 +1,5 @@
+#
+# arch/blackfin/mach-bf548/boards/Makefile
+#
+
+obj-$(CONFIG_BFIN548_EZKIT) += ezkit.o led.o
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
new file mode 100644
index 00000000000..96ad95fab1a
--- /dev/null
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -0,0 +1,114 @@
+/*
+ * File: arch/blackfin/mach-bf548/boards/ezkit.c
+ * Based on: arch/blackfin/mach-bf537/boards/ezkit.c
+ * Author: Aidan Williams <aidan@nicta.com.au>
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2005 National ICT Australia (NICTA)
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/irq.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/bfin5xx_spi.h>
+
+/*
+ * Name the Board for the /proc/cpuinfo
+ */
+char *bfin_board_name = "ADSP-BF548-EZKIT";
+
+/*
+ * Driver needs to know address, irq and flag pin.
+ */
+
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+static struct platform_device rtc_device = {
+ .name = "rtc-bfin",
+ .id = -1,
+};
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+static struct resource bfin_uart_resources[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ {
+ .start = 0xFFC02000,
+ .end = 0xFFC020FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART2
+ {
+ .start = 0xFFC02100,
+ .end = 0xFFC021FF,
+ .flags = IORESOURCE_MEM,
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART3
+ {
+ .start = 0xFFC03100,
+ .end = 0xFFC031FF,
+ },
+#endif
+};
+
+static struct platform_device bfin_uart_device = {
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart_resources),
+ .resource = bfin_uart_resources,
+};
+#endif
+
+static struct platform_device *ezkit_devices[] __initdata = {
+#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE)
+ &rtc_device,
+#endif
+
+#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
+ &bfin_uart_device,
+#endif
+};
+
+static int __init stamp_init(void)
+{
+ printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
+ platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices));
+ return 0;
+}
+
+arch_initcall(stamp_init);
diff --git a/arch/blackfin/mach-bf548/boards/led.S b/arch/blackfin/mach-bf548/boards/led.S
new file mode 100644
index 00000000000..f47daf3770d
--- /dev/null
+++ b/arch/blackfin/mach-bf548/boards/led.S
@@ -0,0 +1,172 @@
+/****************************************************
+ * LED1 ---- PG6 LED2 ---- PG7 *
+ * LED3 ---- PG8 LED4 ---- PG9 *
+ * LED5 ---- PG10 LED6 ---- PG11 *
+ ****************************************************/
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+
+/* All functions in this file save the registers they uses.
+ So there is no need to save any registers before calling them. */
+
+ .text;
+
+/* Initialize LEDs. */
+
+ENTRY(_led_init)
+ LINK 0;
+ [--SP] = P0;
+ [--SP] = R0;
+ [--SP] = R1;
+ [--SP] = R2;
+ R1 = (PG6|PG7|PG8|PG9|PG10|PG11)(Z);
+ R2 = ~R1;
+
+ P0.H = hi(PORTG_FER);
+ P0.L = lo(PORTG_FER);
+ R0 = W[P0](Z);
+ SSYNC;
+ R0 = R0 & R2;
+ W[P0] = R0.L;
+ SSYNC;
+
+ P0.H = hi(PORTG_DIR_SET);
+ P0.L = lo(PORTG_DIR_SET);
+ W[P0] = R1.L;
+ SSYNC;
+
+ P0.H = hi(PORTG_INEN);
+ P0.L = lo(PORTG_INEN);
+ R0 = W[P0](Z);
+ SSYNC;
+ R0 = R0 & R2;
+ W[P0] = R0.L;
+ SSYNC;
+
+ R2 = [SP++];
+ R1 = [SP++];
+ R0 = [SP++];
+ P0 = [SP++];
+ RTS;
+ .size _led_init, .-_led_init
+
+/* Set one LED on. Leave other LEDs unchanged.
+ It expects the LED number passed through R0. */
+
+ENTRY(_led_on)
+ LINK 0;
+ [--SP] = P0;
+ [--SP] = R1;
+ CALL _led_init;
+ R1 = 1;
+ R0 += 5;
+ R1 <<= R0;
+ P0.H = hi(PORTG_SET);
+ P0.L = lo(PORTG_SET);
+ W[P0] = R1.L;
+ SSYNC;
+ R1 = [SP++];
+ P0 = [SP++];
+ UNLINK;
+ RTS;
+ .size _led_on, .-_led_on
+
+/* Set one LED off. Leave other LEDs unchanged. */
+
+ENTRY(_led_off)
+ LINK 0;
+ [--SP] = P0;
+ [--SP] = R1;
+ CALL _led_init;
+ R1 = 1;
+ R0 += 5;
+ R1 <<= R0;
+ P0.H = hi(PORTG_CLEAR);
+ P0.L = lo(PORTG_CLEAR);
+ W[P0] = R1.L;
+ SSYNC;
+ R1 = [SP++];
+ P0 = [SP++];
+ UNLINK;
+ RTS;
+ .size _led_off, .-_led_off
+
+/* Toggle one LED. Leave other LEDs unchanged. */
+
+ENTRY(_led_toggle)
+ LINK 0;
+ [--SP] = P0;
+ [--SP] = R1;
+ CALL _led_init;
+ R1 = 1;
+ R0 += 5;
+ R1 <<= R0;
+ P0.H = hi(PORTG);
+ P0.L = lo(PORTG);
+ R0 = W[P0](Z);
+ SSYNC;
+ R0 = R0 ^ R1;
+ W[P0] = R0.L;
+ SSYNC;
+ R1 = [SP++];
+ P0 = [SP++];
+ UNLINK;
+ RTS;
+ .size _led_toggle, .-_led_toggle
+
+/* Display the number using LEDs in binary format. */
+
+ENTRY(_led_disp_num)
+ LINK 0;
+ [--SP] = P0;
+ [--SP] = R1;
+ [--SP] = R2;
+ CALL _led_init;
+ R1 = 0x3f(X);
+ R0 = R0 & R1;
+ R2 = 6(X);
+ R0 <<= R2;
+ R1 <<= R2;
+ P0.H = hi(PORTG);
+ P0.L = lo(PORTG);
+ R2 = W[P0](Z);
+ SSYNC;
+ R1 = ~R1;
+ R2 = R2 & R1;
+ R2 = R2 | R0;
+ W[P0] = R2.L;
+ SSYNC;
+ R2 = [SP++];
+ R1 = [SP++];
+ P0 = [SP++];
+ UNLINK;
+ RTS;
+ .size _led_disp_num, .-_led_disp_num
+
+/* Toggle the number using LEDs in binary format. */
+
+ENTRY(_led_toggle_num)
+ LINK 0;
+ [--SP] = P0;
+ [--SP] = R1;
+ [--SP] = R2;
+ CALL _led_init;
+ R1 = 0x3f(X);
+ R0 = R0 & R1;
+ R1 = 6(X);
+ R0 <<= R1;
+ P0.H = hi(PORTG);
+ P0.L = lo(PORTG);
+ R1 = W[P0](Z);
+ SSYNC;
+ R1 = R1 ^ R0;
+ W[P0] = R1.L;
+ SSYNC;
+ R2 = [SP++];
+ R1 = [SP++];
+ P0 = [SP++];
+ UNLINK;
+ RTS;
+ .size _led_toggle_num, .-_led_toggle_num
+
diff --git a/arch/blackfin/mach-bf548/cpu.c b/arch/blackfin/mach-bf548/cpu.c
new file mode 100644
index 00000000000..4298a3ccfbf
--- /dev/null
+++ b/arch/blackfin/mach-bf548/cpu.c
@@ -0,0 +1,159 @@
+/*
+ * File: arch/blackfin/mach-bf548/cpu.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: clock scaling for the bf54x
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <asm/dpmc.h>
+#include <linux/fs.h>
+#include <asm/bfin-global.h>
+
+/* CONFIG_CLKIN_HZ=25000000 */
+#define VCO5 (CONFIG_CLKIN_HZ*45)
+#define VCO4 (CONFIG_CLKIN_HZ*36)
+#define VCO3 (CONFIG_CLKIN_HZ*27)
+#define VCO2 (CONFIG_CLKIN_HZ*18)
+#define VCO1 (CONFIG_CLKIN_HZ*9)
+#define VCO(x) VCO##x
+
+#define MFREQ(x) {VCO(x),VCO(x)/4},{VCO(x),VCO(x)/2},{VCO(x),VCO(x)}
+/* frequency */
+static struct cpufreq_frequency_table bf548_freq_table[] = {
+ MFREQ(1),
+ MFREQ(3),
+ {VCO4, VCO4 / 2}, {VCO4, VCO4},
+ MFREQ(5),
+ {0, CPUFREQ_TABLE_END},
+};
+
+/*
+ * dpmc_fops->ioctl()
+ * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+ */
+static int bf548_getfreq(unsigned int cpu)
+{
+ unsigned long cclk_mhz;
+
+ /* The driver only support single cpu */
+ if (cpu == 0)
+ dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz);
+ else
+ cclk_mhz = -1;
+
+ return cclk_mhz;
+}
+
+static int bf548_target(struct cpufreq_policy *policy,
+ unsigned int target_freq, unsigned int relation)
+{
+ unsigned long cclk_mhz;
+ unsigned long vco_mhz;
+ unsigned long flags;
+ unsigned int index;
+ struct cpufreq_freqs freqs;
+
+ if (cpufreq_frequency_table_target(policy, bf548_freq_table, target_freq, relation, &index))
+ return -EINVAL;
+
+ cclk_mhz = bf548_freq_table[index].frequency;
+ vco_mhz = bf548_freq_table[index].index;
+
+ dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz);
+ freqs.old = bf548_getfreq(0);
+ freqs.new = cclk_mhz;
+ freqs.cpu = 0;
+
+ pr_debug("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n",
+ cclk_mhz, vco_mhz, index, target_freq, freqs.old);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ local_irq_save(flags);
+ dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz);
+ local_irq_restore(flags);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ vco_mhz = get_vco();
+ cclk_mhz = get_cclk();
+ return 0;
+}
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
+ */
+static int bf548_verify_speed(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, &bf548_freq_table);
+}
+
+static int __init __bf548_cpu_init(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ /*Now ,only support one cpu */
+ policy->cur = bf548_getfreq(0);
+ cpufreq_frequency_table_get_attr(bf548_freq_table, policy->cpu);
+ return cpufreq_frequency_table_cpuinfo(policy, bf548_freq_table);
+}
+
+static struct freq_attr *bf548_freq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver bf548_driver = {
+ .verify = bf548_verify_speed,
+ .target = bf548_target,
+ .get = bf548_getfreq,
+ .init = __bf548_cpu_init,
+ .name = "bf548",
+ .owner = THIS_MODULE,
+ .attr = bf548_freq_attr,
+};
+
+static int __init bf548_cpu_init(void)
+{
+ return cpufreq_register_driver(&bf548_driver);
+}
+
+static void __exit bf548_cpu_exit(void)
+{
+ cpufreq_unregister_driver(&bf548_driver);
+}
+
+MODULE_AUTHOR("Mickael Kang");
+MODULE_DESCRIPTION("cpufreq driver for BF548 CPU");
+MODULE_LICENSE("GPL");
+
+module_init(bf548_cpu_init);
+module_exit(bf548_cpu_exit);
diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c
new file mode 100644
index 00000000000..a8184113be4
--- /dev/null
+++ b/arch/blackfin/mach-bf548/dma.c
@@ -0,0 +1,156 @@
+/*
+ * File: arch/blackfin/mach-bf561/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+ struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA11_NEXT_DESC_PTR,
+ (struct dma_register *) DMA12_NEXT_DESC_PTR,
+ (struct dma_register *) DMA13_NEXT_DESC_PTR,
+ (struct dma_register *) DMA14_NEXT_DESC_PTR,
+ (struct dma_register *) DMA15_NEXT_DESC_PTR,
+ (struct dma_register *) DMA16_NEXT_DESC_PTR,
+ (struct dma_register *) DMA17_NEXT_DESC_PTR,
+ (struct dma_register *) DMA18_NEXT_DESC_PTR,
+ (struct dma_register *) DMA19_NEXT_DESC_PTR,
+ (struct dma_register *) DMA20_NEXT_DESC_PTR,
+ (struct dma_register *) DMA21_NEXT_DESC_PTR,
+ (struct dma_register *) DMA22_NEXT_DESC_PTR,
+ (struct dma_register *) DMA23_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D2_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S2_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D3_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S3_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ case CH_SPI0:
+ ret_irq = IRQ_SPI0;
+ break;
+ case CH_SPI1:
+ ret_irq = IRQ_SPI1;
+ break;
+ case CH_UART0_RX:
+ ret_irq = IRQ_UART_RX;
+ break;
+ case CH_UART0_TX:
+ ret_irq = IRQ_UART_TX;
+ break;
+ case CH_UART1_RX:
+ ret_irq = IRQ_UART_RX;
+ break;
+ case CH_UART1_TX:
+ ret_irq = IRQ_UART_TX;
+ break;
+ case CH_EPPI0:
+ ret_irq = IRQ_EPPI0;
+ break;
+ case CH_EPPI1:
+ ret_irq = IRQ_EPPI1;
+ break;
+ case CH_EPPI2:
+ ret_irq = IRQ_EPPI2;
+ break;
+ case CH_PIXC_IMAGE:
+ ret_irq = IRQ_PIXC_IN0;
+ break;
+ case CH_PIXC_OVERLAY:
+ ret_irq = IRQ_PIXC_IN1;
+ break;
+ case CH_PIXC_OUTPUT:
+ ret_irq = IRQ_PIXC_OUT;
+ break;
+ case CH_SPORT2_RX:
+ ret_irq = IRQ_SPORT2_RX;
+ break;
+ case CH_SPORT2_TX:
+ ret_irq = IRQ_SPORT2_TX;
+ break;
+ case CH_SPORT3_RX:
+ ret_irq = IRQ_SPORT3_RX;
+ break;
+ case CH_SPORT3_TX:
+ ret_irq = IRQ_SPORT3_TX;
+ break;
+ case CH_SDH:
+ ret_irq = IRQ_SDH;
+ break;
+ case CH_SPI2:
+ ret_irq = IRQ_SPI2;
+ break;
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MDMAS0;
+ break;
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MDMAS1;
+ break;
+ case CH_MEM_STREAM2_SRC:
+ case CH_MEM_STREAM2_DEST:
+ ret_irq = IRQ_MDMAS2;
+ break;
+ case CH_MEM_STREAM3_SRC:
+ case CH_MEM_STREAM3_DEST:
+ ret_irq = IRQ_MDMAS3;
+ break;
+ }
+ return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf548/gpio.c b/arch/blackfin/mach-bf548/gpio.c
new file mode 100644
index 00000000000..0da5f0003b8
--- /dev/null
+++ b/arch/blackfin/mach-bf548/gpio.c
@@ -0,0 +1,323 @@
+/*
+ * File: arch/blackfin/mach-bf548/gpio.c
+ * Based on:
+ * Author: Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description: GPIO Abstraction Layer
+ *
+ * Modified:
+ * Copyright 2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
+#include <linux/irq.h>
+
+static struct gpio_port_t *gpio_array[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+ (struct gpio_port_t *)PORTA_FER,
+ (struct gpio_port_t *)PORTB_FER,
+ (struct gpio_port_t *)PORTC_FER,
+ (struct gpio_port_t *)PORTD_FER,
+ (struct gpio_port_t *)PORTE_FER,
+ (struct gpio_port_t *)PORTF_FER,
+ (struct gpio_port_t *)PORTG_FER,
+ (struct gpio_port_t *)PORTH_FER,
+ (struct gpio_port_t *)PORTI_FER,
+ (struct gpio_port_t *)PORTJ_FER,
+};
+
+static unsigned short reserved_gpio_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned short reserved_peri_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+inline int check_gpio(unsigned short gpio)
+{
+ if (gpio == GPIO_PB15 || gpio == GPIO_PC14 || gpio == GPIO_PC15
+ || gpio == GPIO_PH14 || gpio == GPIO_PH15
+ || gpio == GPIO_PJ14 || gpio == GPIO_PJ15
+ || gpio > MAX_BLACKFIN_GPIOS)
+ return -EINVAL;
+ return 0;
+}
+
+inline void portmux_setup(unsigned short portno, unsigned short function)
+{
+ u32 pmux;
+
+ pmux = gpio_array[gpio_bank(portno)]->port_mux;
+
+ pmux &= ~(0x3 << (2 * gpio_sub_n(portno)));
+ pmux |= (function & 0x3) << (2 * gpio_sub_n(portno));
+
+ gpio_array[gpio_bank(portno)]->port_mux = pmux;
+
+}
+
+inline u16 get_portmux(unsigned short portno)
+{
+ u32 pmux;
+
+ pmux = gpio_array[gpio_bank(portno)]->port_mux;
+
+ return (pmux >> (2 * gpio_sub_n(portno)) & 0x3);
+
+}
+
+static void port_setup(unsigned short gpio, unsigned short usage)
+{
+ if (usage == GPIO_USAGE) {
+ if (gpio_array[gpio_bank(gpio)]->port_fer & gpio_bit(gpio))
+ printk(KERN_WARNING
+ "bfin-gpio: Possible Conflict with Peripheral "
+ "usage and GPIO %d detected!\n", gpio);
+ gpio_array[gpio_bank(gpio)]->port_fer &= ~gpio_bit(gpio);
+ } else
+ gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio);
+ SSYNC();
+}
+
+static int __init bfin_gpio_init(void)
+{
+ printk(KERN_INFO "Blackfin GPIO Controller\n");
+
+ return 0;
+}
+
+arch_initcall(bfin_gpio_init);
+
+int peripheral_request(unsigned short per, const char *label)
+{
+ unsigned long flags;
+ unsigned short ident = P_IDENT(per);
+
+ if (!(per & P_DEFINED))
+ return -ENODEV;
+
+ if (check_gpio(ident) < 0)
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ if (unlikely(reserved_gpio_map[gpio_bank(ident)] & gpio_bit(ident))) {
+ printk(KERN_ERR
+ "%s: Peripheral %d is already reserved as GPIO!\n",
+ __FUNCTION__, per);
+ dump_stack();
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+
+ if (unlikely(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident))) {
+
+ u16 funct = get_portmux(ident);
+
+ if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) {
+ printk(KERN_ERR
+ "%s: Peripheral %d is already reserved!\n",
+ __FUNCTION__, per);
+ dump_stack();
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+ }
+
+ reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident);
+
+ portmux_setup(ident, P_FUNCT2MUX(per));
+ port_setup(ident, PERIPHERAL_USAGE);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(peripheral_request);
+
+int peripheral_request_list(unsigned short per[], const char *label)
+{
+
+ u16 cnt;
+ int ret;
+
+ for (cnt = 0; per[cnt] != 0; cnt++) {
+ ret = peripheral_request(per[cnt], label);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(peripheral_request_list);
+
+void peripheral_free(unsigned short per)
+{
+ unsigned long flags;
+ unsigned short ident = P_IDENT(per);
+
+ if (!(per & P_DEFINED))
+ return;
+
+ if (check_gpio(ident) < 0)
+ return;
+
+ local_irq_save(flags);
+
+ if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) {
+ printk(KERN_ERR "bfin-gpio: Peripheral %d wasn't reserved!\n", per);
+ dump_stack();
+ local_irq_restore(flags);
+ return;
+ }
+
+ if (!(per & P_MAYSHARE)) {
+ port_setup(ident, GPIO_USAGE);
+ }
+
+ reserved_peri_map[gpio_bank(ident)] &= ~gpio_bit(ident);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(peripheral_free);
+
+void peripheral_free_list(unsigned short per[])
+{
+ u16 cnt;
+
+ for (cnt = 0; per[cnt] != 0; cnt++) {
+ peripheral_free(per[cnt]);
+ }
+
+}
+EXPORT_SYMBOL(peripheral_free_list);
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin GPIO Driver
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: Blackfin GPIO Driver API
+*
+* CAUTION:
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+int gpio_request(unsigned short gpio, const char *label)
+{
+ unsigned long flags;
+
+ if (check_gpio(gpio) < 0)
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ if (unlikely(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+ printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio);
+ dump_stack();
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+
+ if (unlikely(reserved_peri_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+ printk(KERN_ERR
+ "bfin-gpio: GPIO %d is already reserved as Peripheral!\n", gpio);
+ dump_stack();
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+
+ reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+
+ local_irq_restore(flags);
+
+ port_setup(gpio, GPIO_USAGE);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned short gpio)
+{
+ unsigned long flags;
+
+ if (check_gpio(gpio) < 0)
+ return;
+
+ local_irq_save(flags);
+
+ if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+ printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
+ dump_stack();
+ local_irq_restore(flags);
+ return;
+ }
+
+ reserved_gpio_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_free);
+
+void gpio_direction_input(unsigned short gpio)
+{
+ unsigned long flags;
+
+ BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+ local_irq_save(flags);
+ gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio);
+ gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+void gpio_direction_output(unsigned short gpio)
+{
+ unsigned long flags;
+
+ BUG_ON(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+ local_irq_save(flags);
+ gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio);
+ gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+void gpio_set_value(unsigned short gpio, unsigned short arg)
+{
+ if (arg)
+ gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio);
+ else
+ gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio);
+
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+unsigned short gpio_get_value(unsigned short gpio)
+{
+ return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio)));
+}
+EXPORT_SYMBOL(gpio_get_value);
diff --git a/arch/blackfin/mach-bf548/head.S b/arch/blackfin/mach-bf548/head.S
new file mode 100644
index 00000000000..06751ae8b85
--- /dev/null
+++ b/arch/blackfin/mach-bf548/head.S
@@ -0,0 +1,512 @@
+/*
+ * File: arch/blackfin/mach-bf548/head.S
+ * Based on: arch/blackfin/mach-bf537/head.S
+ * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne
+ *
+ * Created: 1998
+ * Description: Startup code for Blackfin BF548
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/trace.h>
+#if CONFIG_BFIN_KERNEL_CLOCK
+#include <asm/mach/mem_init.h>
+#endif
+
+.global __rambase
+.global __ramstart
+.global __ramend
+.extern ___bss_stop
+.extern ___bss_start
+.extern _bf53x_relocate_l1_mem
+
+#define INITIAL_STACK 0xFFB01000
+
+.text
+
+ENTRY(__start)
+ENTRY(__stext)
+ /* R0: argument of command line string, passed from uboot, save it */
+ R7 = R0;
+ /* Set the SYSCFG register */
+ R0 = 0x36;
+ SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+ R0 = 0;
+
+ /* Clear Out All the data and pointer Registers*/
+ R1 = R0;
+ R2 = R0;
+ R3 = R0;
+ R4 = R0;
+ R5 = R0;
+ R6 = R0;
+
+ P0 = R0;
+ P1 = R0;
+ P2 = R0;
+ P3 = R0;
+ P4 = R0;
+ P5 = R0;
+
+ LC0 = r0;
+ LC1 = r0;
+ L0 = r0;
+ L1 = r0;
+ L2 = r0;
+ L3 = r0;
+
+ /* Clear Out All the DAG Registers*/
+ B0 = r0;
+ B1 = r0;
+ B2 = r0;
+ B3 = r0;
+
+ I0 = r0;
+ I1 = r0;
+ I2 = r0;
+ I3 = r0;
+
+ M0 = r0;
+ M1 = r0;
+ M2 = r0;
+ M3 = r0;
+
+ trace_buffer_start(p0,r0);
+ P0 = R1;
+ R0 = R1;
+
+ /* Turn off the icache */
+ p0.l = (IMEM_CONTROL & 0xFFFF);
+ p0.h = (IMEM_CONTROL >> 16);
+ R1 = [p0];
+ R0 = ~ENICPLB;
+ R0 = R0 & R1;
+ [p0] = R0;
+ SSYNC;
+
+ /* Turn off the dcache */
+ p0.l = (DMEM_CONTROL & 0xFFFF);
+ p0.h = (DMEM_CONTROL >> 16);
+ R1 = [p0];
+ R0 = ~ENDCPLB;
+ R0 = R0 & R1;
+ [p0] = R0;
+ SSYNC;
+
+ /* Initialize stack pointer */
+ SP.L = LO(INITIAL_STACK);
+ SP.H = HI(INITIAL_STACK);
+ FP = SP;
+ USP = SP;
+
+ /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
+ call _bf53x_relocate_l1_mem;
+#if CONFIG_BFIN_KERNEL_CLOCK
+ call _start_dma_code;
+#endif
+ /* Code for initializing Async memory banks */
+
+ p2.h = hi(EBIU_AMBCTL1);
+ p2.l = lo(EBIU_AMBCTL1);
+ r0.h = hi(AMBCTL1VAL);
+ r0.l = lo(AMBCTL1VAL);
+ [p2] = r0;
+ ssync;
+
+ p2.h = hi(EBIU_AMBCTL0);
+ p2.l = lo(EBIU_AMBCTL0);
+ r0.h = hi(AMBCTL0VAL);
+ r0.l = lo(AMBCTL0VAL);
+ [p2] = r0;
+ ssync;
+
+ p2.h = hi(EBIU_AMGCTL);
+ p2.l = lo(EBIU_AMGCTL);
+ r0 = AMGCTLVAL;
+ w[p2] = r0;
+ ssync;
+
+ /* This section keeps the processor in supervisor mode
+ * during kernel boot. Switches to user mode at end of boot.
+ * See page 3-9 of Hardware Reference manual for documentation.
+ */
+
+ /* EVT15 = _real_start */
+
+ p0.l = lo(EVT15);
+ p0.h = hi(EVT15);
+ p1.l = _real_start;
+ p1.h = _real_start;
+ [p0] = p1;
+ csync;
+
+ p0.l = lo(IMASK);
+ p0.h = hi(IMASK);
+ p1.l = IMASK_IVG15;
+ p1.h = 0x0;
+ [p0] = p1;
+ csync;
+
+ raise 15;
+ p0.l = .LWAIT_HERE;
+ p0.h = .LWAIT_HERE;
+ reti = p0;
+#if defined (ANOMALY_05000281)
+ nop;
+ nop;
+ nop;
+#endif
+ rti;
+
+.LWAIT_HERE:
+ jump .LWAIT_HERE;
+
+ENTRY(_real_start)
+ [ -- sp ] = reti;
+ p0.l = lo(WDOG_CTL);
+ p0.h = hi(WDOG_CTL);
+ r0 = 0xAD6(z);
+ w[p0] = r0; /* watchdog off for now */
+ ssync;
+
+ /* Code update for BSS size == 0
+ * Zero out the bss region.
+ */
+
+ p1.l = ___bss_start;
+ p1.h = ___bss_start;
+ p2.l = ___bss_stop;
+ p2.h = ___bss_stop;
+ r0 = 0;
+ p2 -= p1;
+ lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+.L_clear_bss:
+ B[p1++] = r0;
+
+ /* In case there is a NULL pointer reference
+ * Zero out region before stext
+ */
+
+ p1.l = 0x0;
+ p1.h = 0x0;
+ r0.l = __stext;
+ r0.h = __stext;
+ r0 = r0 >> 1;
+ p2 = r0;
+ r0 = 0;
+ lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+.L_clear_zero:
+ W[p1++] = r0;
+
+ /* pass the uboot arguments to the global value command line */
+ R0 = R7;
+ call _cmdline_init;
+
+ p1.l = __rambase;
+ p1.h = __rambase;
+ r0.l = __sdata;
+ r0.h = __sdata;
+ [p1] = r0;
+
+ p1.l = __ramstart;
+ p1.h = __ramstart;
+ p3.l = ___bss_stop;
+ p3.h = ___bss_stop;
+
+ r1 = p3;
+ [p1] = r1;
+
+
+ /*
+ * load the current thread pointer and stack
+ */
+ r1.l = _init_thread_union;
+ r1.h = _init_thread_union;
+
+ r2.l = 0x2000;
+ r2.h = 0x0000;
+ r1 = r1 + r2;
+ sp = r1;
+ usp = sp;
+ fp = sp;
+ call _start_kernel;
+.L_exit:
+ jump.s .L_exit;
+
+.section .l1.text
+#if CONFIG_BFIN_KERNEL_CLOCK
+ENTRY(_start_dma_code)
+
+ /* Enable PHY CLK buffer output */
+ p0.h = hi(VR_CTL);
+ p0.l = lo(VR_CTL);
+ r0.l = w[p0];
+ bitset(r0, 14);
+ w[p0] = r0.l;
+ ssync;
+
+ p0.h = hi(SIC_IWR);
+ p0.l = lo(SIC_IWR);
+ r0.l = 0x1;
+ r0.h = 0x0;
+ [p0] = r0;
+ SSYNC;
+
+ /*
+ * Set PLL_CTL
+ * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
+ * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
+ * - [7] = output delay (add 200ps of delay to mem signals)
+ * - [6] = input delay (add 200ps of input delay to mem signals)
+ * - [5] = PDWN : 1=All Clocks off
+ * - [3] = STOPCK : 1=Core Clock off
+ * - [1] = PLL_OFF : 1=Disable Power to PLL
+ * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
+ * all other bits set to zero
+ */
+
+ p0.h = hi(PLL_LOCKCNT);
+ p0.l = lo(PLL_LOCKCNT);
+ r0 = 0x300(Z);
+ w[p0] = r0.l;
+ ssync;
+
+ P2.H = hi(EBIU_SDGCTL);
+ P2.L = lo(EBIU_SDGCTL);
+ R0 = [P2];
+ BITSET (R0, 24);
+ [P2] = R0;
+ SSYNC;
+
+ r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
+ r0 = r0 << 9; /* Shift it over, */
+ r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
+ r0 = r1 | r0;
+ r1 = PLL_BYPASS; /* Bypass the PLL? */
+ r1 = r1 << 8; /* Shift it over */
+ r0 = r1 | r0; /* add them all together */
+
+ p0.h = hi(PLL_CTL);
+ p0.l = lo(PLL_CTL); /* Load the address */
+ cli r2; /* Disable interrupts */
+ ssync;
+ w[p0] = r0.l; /* Set the value */
+ idle; /* Wait for the PLL to stablize */
+ sti r2; /* Enable interrupts */
+
+.Lcheck_again:
+ p0.h = hi(PLL_STAT);
+ p0.l = lo(PLL_STAT);
+ R0 = W[P0](Z);
+ CC = BITTST(R0,5);
+ if ! CC jump .Lcheck_again;
+
+ /* Configure SCLK & CCLK Dividers */
+ r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+ p0.h = hi(PLL_DIV);
+ p0.l = lo(PLL_DIV);
+ w[p0] = r0.l;
+ ssync;
+
+ p0.l = lo(EBIU_SDRRC);
+ p0.h = hi(EBIU_SDRRC);
+ r0 = mem_SDRRC;
+ w[p0] = r0.l;
+ ssync;
+
+ p0.l = (EBIU_SDBCTL & 0xFFFF);
+ p0.h = (EBIU_SDBCTL >> 16); /* SDRAM Memory Bank Control Register */
+ r0 = mem_SDBCTL;
+ w[p0] = r0.l;
+ ssync;
+
+ P2.H = hi(EBIU_SDGCTL);
+ P2.L = lo(EBIU_SDGCTL);
+ R0 = [P2];
+ BITCLR (R0, 24);
+ p0.h = hi(EBIU_SDSTAT);
+ p0.l = lo(EBIU_SDSTAT);
+ r2.l = w[p0];
+ cc = bittst(r2,3);
+ if !cc jump .Lskip;
+ NOP;
+ BITSET (R0, 23);
+.Lskip:
+ [P2] = R0;
+ SSYNC;
+
+ R0.L = lo(mem_SDGCTL);
+ R0.H = hi(mem_SDGCTL);
+ R1 = [p2];
+ R1 = R1 | R0;
+ [P2] = R1;
+ SSYNC;
+
+ p0.h = hi(SIC_IWR);
+ p0.l = lo(SIC_IWR);
+ r0.l = lo(IWR_ENABLE_ALL);
+ r0.h = hi(IWR_ENABLE_ALL);
+ [p0] = r0;
+ SSYNC;
+
+ RTS;
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+ENTRY(_bfin_reset)
+ /* No more interrupts to be handled*/
+ CLI R6;
+ SSYNC;
+
+#if defined(CONFIG_MTD_M25P80)
+/*
+ * The following code fix the SPI flash reboot issue,
+ * /CS signal of the chip which is using PF10 return to GPIO mode
+ */
+ p0.h = hi(PORTF_FER);
+ p0.l = lo(PORTF_FER);
+ r0.l = 0x0000;
+ w[p0] = r0.l;
+ SSYNC;
+
+/* /CS return to high */
+ p0.h = hi(PORTFIO);
+ p0.l = lo(PORTFIO);
+ r0.l = 0xFFFF;
+ w[p0] = r0.l;
+ SSYNC;
+
+/* Delay some time, This is necessary */
+ r1.h = 0;
+ r1.l = 0x400;
+ p1 = r1;
+ lsetup (_delay_lab1,_delay_lab1_end ) lc1 = p1;
+_delay_lab1:
+ r0.h = 0;
+ r0.l = 0x8000;
+ p0 = r0;
+ lsetup (_delay_lab0,_delay_lab0_end ) lc0 = p0;
+_delay_lab0:
+ nop;
+_delay_lab0_end:
+ nop;
+_delay_lab1_end:
+ nop;
+#endif
+
+ /* Clear the bits 13-15 in SWRST if they werent cleared */
+ p0.h = hi(SWRST);
+ p0.l = lo(SWRST);
+ csync;
+ r0.l = w[p0];
+
+ /* Clear the IMASK register */
+ p0.h = hi(IMASK);
+ p0.l = lo(IMASK);
+ r0 = 0x0;
+ [p0] = r0;
+
+ /* Clear the ILAT register */
+ p0.h = hi(ILAT);
+ p0.l = lo(ILAT);
+ r0 = [p0];
+ [p0] = r0;
+ SSYNC;
+
+ /* Disable the WDOG TIMER */
+ p0.h = hi(WDOG_CTL);
+ p0.l = lo(WDOG_CTL);
+ r0.l = 0xAD6;
+ w[p0] = r0.l;
+ SSYNC;
+
+ /* Clear the sticky bit incase it is already set */
+ p0.h = hi(WDOG_CTL);
+ p0.l = lo(WDOG_CTL);
+ r0.l = 0x8AD6;
+ w[p0] = r0.l;
+ SSYNC;
+
+ /* Program the count value */
+ R0.l = 0x100;
+ R0.h = 0x0;
+ P0.h = hi(WDOG_CNT);
+ P0.l = lo(WDOG_CNT);
+ [P0] = R0;
+ SSYNC;
+
+ /* Program WDOG_STAT if necessary */
+ P0.h = hi(WDOG_CTL);
+ P0.l = lo(WDOG_CTL);
+ R0 = W[P0](Z);
+ CC = BITTST(R0,1);
+ if !CC JUMP .LWRITESTAT;
+ CC = BITTST(R0,2);
+ if !CC JUMP .LWRITESTAT;
+ JUMP .LSKIP_WRITE;
+
+.LWRITESTAT:
+ /* When watch dog timer is enabled,
+ * a write to STAT will load the contents of CNT to STAT
+ */
+ R0 = 0x0000(z);
+ P0.h = hi(WDOG_STAT);
+ P0.l = lo(WDOG_STAT)
+ [P0] = R0;
+ SSYNC;
+
+.LSKIP_WRITE:
+ /* Enable the reset event */
+ P0.h = hi(WDOG_CTL);
+ P0.l = lo(WDOG_CTL);
+ R0 = W[P0](Z);
+ BITCLR(R0,1);
+ BITCLR(R0,2);
+ W[P0] = R0.L;
+ SSYNC;
+ NOP;
+
+ /* Enable the wdog counter */
+ R0 = W[P0](Z);
+ BITCLR(R0,4);
+ W[P0] = R0.L;
+ SSYNC;
+
+ IDLE;
+
+ RTS;
+
+.data
+
+/*
+ * Set up the usable of RAM stuff. Size of RAM is determined then
+ * an initial stack set up at the end.
+ */
+
+.align 4
+__rambase:
+.long 0
+__ramstart:
+.long 0
+__ramend:
+.long 0
diff --git a/arch/blackfin/mach-bf548/ints-priority.c b/arch/blackfin/mach-bf548/ints-priority.c
new file mode 100644
index 00000000000..cb0ebac53c7
--- /dev/null
+++ b/arch/blackfin/mach-bf548/ints-priority.c
@@ -0,0 +1,137 @@
+/*
+ * File: arch/blackfin/mach-bf537/ints-priority.c
+ * Based on: arch/blackfin/mach-bf533/ints-priority.c
+ * Author: Michael Hennerich
+ *
+ * Created:
+ * Description: Set up the interupt priorities
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <asm/blackfin.h>
+
+void program_IAR(void)
+{
+ /* Program the IAR0 Register with the configured priority */
+ bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) |
+ ((CONFIG_IRQ_DMAC0_ERR - 7) << IRQ_DMAC0_ERR_POS) |
+ ((CONFIG_IRQ_EPPI0_ERR - 7) << IRQ_EPPI0_ERR_POS) |
+ ((CONFIG_IRQ_SPORT0_ERR - 7) << IRQ_SPORT0_ERR_POS) |
+ ((CONFIG_IRQ_SPORT1_ERR - 7) << IRQ_SPORT1_ERR_POS) |
+ ((CONFIG_IRQ_SPI0_ERR - 7) << IRQ_SPI0_ERR_POS) |
+ ((CONFIG_IRQ_UART0_ERR - 7) << IRQ_UART0_ERR_POS) |
+ ((CONFIG_IRQ_RTC - 7) << IRQ_RTC_POS));
+
+ bfin_write_SIC_IAR1(((CONFIG_IRQ_EPPI0 - 7) << IRQ_EPPI0_POS) |
+ ((CONFIG_IRQ_SPORT0_RX - 7) << IRQ_SPORT0_RX_POS) |
+ ((CONFIG_IRQ_SPORT0_TX - 7) << IRQ_SPORT0_TX_POS) |
+ ((CONFIG_IRQ_SPORT1_RX - 7) << IRQ_SPORT1_RX_POS) |
+ ((CONFIG_IRQ_SPORT1_TX - 7) << IRQ_SPORT1_TX_POS) |
+ ((CONFIG_IRQ_SPI0 - 7) << IRQ_SPI0_POS) |
+ ((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) |
+ ((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS));
+
+ bfin_write_SIC_IAR2(((CONFIG_IRQ_TIMER8 - 7) << IRQ_TIMER8_POS) |
+ ((CONFIG_IRQ_TIMER9 - 7) << IRQ_TIMER9_POS) |
+ ((CONFIG_IRQ_PINT0 - 7) << IRQ_PINT0_POS) |
+ ((CONFIG_IRQ_PINT1 - 7) << IRQ_PINT1_POS) |
+ ((CONFIG_IRQ_MDMAS0 - 7) << IRQ_MDMAS0_POS) |
+ ((CONFIG_IRQ_MDMAS1 - 7) << IRQ_MDMAS1_POS) |
+ ((CONFIG_IRQ_WATCHDOG - 7) << IRQ_WATCHDOG_POS));
+
+ bfin_write_SIC_IAR3(((CONFIG_IRQ_DMAC1_ERR - 7) << IRQ_DMAC1_ERR_POS) |
+ ((CONFIG_IRQ_SPORT2_ERR - 7) << IRQ_SPORT2_ERR_POS) |
+ ((CONFIG_IRQ_SPORT3_ERR - 7) << IRQ_SPORT3_ERR_POS) |
+ ((CONFIG_IRQ_MXVR_DATA - 7) << IRQ_MXVR_DATA_POS) |
+ ((CONFIG_IRQ_SPI1_ERR - 7) << IRQ_SPI1_ERR_POS) |
+ ((CONFIG_IRQ_SPI2_ERR - 7) << IRQ_SPI2_ERR_POS) |
+ ((CONFIG_IRQ_UART1_ERR - 7) << IRQ_UART1_ERR_POS) |
+ ((CONFIG_IRQ_UART2_ERR - 7) << IRQ_UART2_ERR_POS));
+
+ bfin_write_SIC_IAR4(((CONFIG_IRQ_CAN0_ERR - 7) << IRQ_CAN0_ERR_POS) |
+ ((CONFIG_IRQ_SPORT2_RX - 7) << IRQ_SPORT2_RX_POS) |
+ ((CONFIG_IRQ_SPORT2_TX - 7) << IRQ_SPORT2_TX_POS) |
+ ((CONFIG_IRQ_SPORT3_RX - 7) << IRQ_SPORT3_RX_POS) |
+ ((CONFIG_IRQ_SPORT3_TX - 7) << IRQ_SPORT3_TX_POS) |
+ ((CONFIG_IRQ_EPPI1 - 7) << IRQ_EPPI1_POS) |
+ ((CONFIG_IRQ_EPPI2 - 7) << IRQ_EPPI2_POS) |
+ ((CONFIG_IRQ_SPI1 - 7) << IRQ_SPI1_POS));
+
+ bfin_write_SIC_IAR5(((CONFIG_IRQ_SPI2 - 7) << IRQ_SPI2_POS) |
+ ((CONFIG_IRQ_UART1_RX - 7) << IRQ_UART1_RX_POS) |
+ ((CONFIG_IRQ_UART1_TX - 7) << IRQ_UART1_TX_POS) |
+ ((CONFIG_IRQ_ATAPI_RX - 7) << IRQ_ATAPI_RX_POS) |
+ ((CONFIG_IRQ_ATAPI_TX - 7) << IRQ_ATAPI_TX_POS) |
+ ((CONFIG_IRQ_TWI0 - 7) << IRQ_TWI0_POS) |
+ ((CONFIG_IRQ_TWI1 - 7) << IRQ_TWI1_POS) |
+ ((CONFIG_IRQ_CAN0_RX - 7) << IRQ_CAN0_RX_POS));
+
+ bfin_write_SIC_IAR6(((CONFIG_IRQ_CAN0_TX - 7) << IRQ_CAN0_TX_POS) |
+ ((CONFIG_IRQ_MDMAS2 - 7) << IRQ_MDMAS2_POS) |
+ ((CONFIG_IRQ_MDMAS3 - 7) << IRQ_MDMAS3_POS) |
+ ((CONFIG_IRQ_MXVR_ERR - 7) << IRQ_MXVR_ERR_POS) |
+ ((CONFIG_IRQ_MXVR_MSG - 7) << IRQ_MXVR_MSG_POS) |
+ ((CONFIG_IRQ_MXVR_PKT - 7) << IRQ_MXVR_PKT_POS) |
+ ((CONFIG_IRQ_EPPI1_ERR - 7) << IRQ_EPPI1_ERR_POS) |
+ ((CONFIG_IRQ_EPPI2_ERR - 7) << IRQ_EPPI2_ERR_POS));
+
+ bfin_write_SIC_IAR7(((CONFIG_IRQ_UART3_ERR - 7) << IRQ_UART3_ERR_POS) |
+ ((CONFIG_IRQ_HOST_ERR - 7) << IRQ_HOST_ERR_POS) |
+ ((CONFIG_IRQ_PIXC_ERR - 7) << IRQ_PIXC_ERR_POS) |
+ ((CONFIG_IRQ_NFC_ERR - 7) << IRQ_NFC_ERR_POS) |
+ ((CONFIG_IRQ_ATAPI_ERR - 7) << IRQ_ATAPI_ERR_POS) |
+ ((CONFIG_IRQ_CAN1_ERR - 7) << IRQ_CAN1_ERR_POS) |
+ ((CONFIG_IRQ_HS_DMA_ERR - 7) << IRQ_HS_DMA_ERR_POS));
+
+ bfin_write_SIC_IAR8(((CONFIG_IRQ_PIXC_IN0 - 7) << IRQ_PIXC_IN1_POS) |
+ ((CONFIG_IRQ_PIXC_IN1 - 7) << IRQ_PIXC_IN1_POS) |
+ ((CONFIG_IRQ_PIXC_OUT - 7) << IRQ_PIXC_OUT_POS) |
+ ((CONFIG_IRQ_SDH - 7) << IRQ_SDH_POS) |
+ ((CONFIG_IRQ_CNT - 7) << IRQ_CNT_POS) |
+ ((CONFIG_IRQ_KEY - 7) << IRQ_KEY_POS) |
+ ((CONFIG_IRQ_CAN1_RX - 7) << IRQ_CAN1_RX_POS) |
+ ((CONFIG_IRQ_CAN1_TX - 7) << IRQ_CAN1_TX_POS));
+
+ bfin_write_SIC_IAR9(((CONFIG_IRQ_SDH_MASK0 - 7) << IRQ_SDH_MASK0_POS) |
+ ((CONFIG_IRQ_SDH_MASK1 - 7) << IRQ_SDH_MASK1_POS) |
+ ((CONFIG_IRQ_USB_INT0 - 7) << IRQ_USB_INT0_POS) |
+ ((CONFIG_IRQ_USB_INT1 - 7) << IRQ_USB_INT1_POS) |
+ ((CONFIG_IRQ_USB_INT2 - 7) << IRQ_USB_INT2_POS) |
+ ((CONFIG_IRQ_USB_DMA - 7) << IRQ_USB_DMA_POS) |
+ ((CONFIG_IRQ_OTPSEC - 7) << IRQ_OTPSEC_POS));
+
+ bfin_write_SIC_IAR10(((CONFIG_IRQ_TIMER0 - 7) << IRQ_TIMER0_POS) |
+ ((CONFIG_IRQ_TIMER1 - 7) << IRQ_TIMER1_POS));
+
+ bfin_write_SIC_IAR11(((CONFIG_IRQ_TIMER2 - 7) << IRQ_TIMER2_POS) |
+ ((CONFIG_IRQ_TIMER3 - 7) << IRQ_TIMER3_POS) |
+ ((CONFIG_IRQ_TIMER4 - 7) << IRQ_TIMER4_POS) |
+ ((CONFIG_IRQ_TIMER5 - 7) << IRQ_TIMER5_POS) |
+ ((CONFIG_IRQ_TIMER6 - 7) << IRQ_TIMER6_POS) |
+ ((CONFIG_IRQ_TIMER7 - 7) << IRQ_TIMER7_POS) |
+ ((CONFIG_IRQ_PINT2 - 7) << IRQ_PINT2_POS) |
+ ((CONFIG_IRQ_PINT3 - 7) << IRQ_PINT3_POS));
+
+ SSYNC();
+}
diff --git a/arch/blackfin/mach-bf561/Makefile b/arch/blackfin/mach-bf561/Makefile
index 57f475a5516..f39235a5578 100644
--- a/arch/blackfin/mach-bf561/Makefile
+++ b/arch/blackfin/mach-bf561/Makefile
@@ -4,6 +4,6 @@
extra-y := head.o
-obj-y := ints-priority.o
+obj-y := ints-priority.o dma.o
obj-$(CONFIG_BF561_COREB) += coreb.o
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 6824e956d15..5b2b544529a 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -1,7 +1,7 @@
/*
* File: arch/blackfin/mach-bf533/boards/cm_bf561.c
* Based on: arch/blackfin/mach-bf533/boards/ezkit.c
- * Author: Aidan Williams <aidan@nicta.com.au> Copright 2005
+ * Author: Aidan Williams <aidan@nicta.com.au> Copyright 2005
*
* Created: 2006
* Description: Board description file
@@ -34,7 +34,7 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/usb_isp1362.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/bfin5xx_spi.h>
/*
@@ -43,7 +43,7 @@
char *bfin_board_name = "Bluetechnix CM BF561";
#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE)
-/* all SPI perpherals info goes here */
+/* all SPI peripherals info goes here */
#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
static struct mtd_partition bfin_spi_flash_partitions[] = {
@@ -52,11 +52,11 @@ static struct mtd_partition bfin_spi_flash_partitions[] = {
.size = 0x00020000,
.offset = 0,
.mask_flags = MTD_CAP_ROM
- },{
+ }, {
.name = "kernel",
.size = 0xe0000,
.offset = 0x20000
- },{
+ }, {
.name = "file system",
.size = 0x700000,
.offset = 0x00100000,
@@ -186,7 +186,7 @@ static struct resource smc91x_resources[] = {
.start = 0x28000300,
.end = 0x28000300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF0,
.end = IRQ_PF0,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -206,11 +206,11 @@ static struct resource isp1362_hcd_resources[] = {
.start = 0x24008000,
.end = 0x24008000,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = 0x24008004,
.end = 0x24008004,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF47,
.end = IRQ_PF47,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
@@ -241,25 +241,25 @@ static struct platform_device isp1362_hcd_device = {
#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
static struct resource bfin_uart_resources[] = {
- {
- .start = 0xFFC00400,
- .end = 0xFFC004FF,
- .flags = IORESOURCE_MEM,
- },
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
};
static struct platform_device bfin_uart_device = {
- .name = "bfin-uart",
- .id = 1,
- .num_resources = ARRAY_SIZE(bfin_uart_resources),
- .resource = bfin_uart_resources,
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart_resources),
+ .resource = bfin_uart_resources,
};
#endif
static struct platform_device *cm_bf561_devices[] __initdata = {
#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
- &bfin_uart_device,
+ &bfin_uart_device,
#endif
#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE)
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 9720b5c307a..724191da20a 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -30,10 +30,9 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
-#include <asm/irq.h>
-#include <asm/bfin5xx_spi.h>
-#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/bfin5xx_spi.h>
/*
* Name the Board for the /proc/cpuinfo
@@ -45,13 +44,13 @@ char *bfin_board_name = "ADDS-BF561-EZKIT";
#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE)
static struct resource bfin_isp1761_resources[] = {
- [0] = {
+ {
.name = "isp1761-regs",
.start = ISP1761_BASE + 0x00000000,
.end = ISP1761_BASE + 0x000fffff,
.flags = IORESOURCE_MEM,
},
- [1] = {
+ {
.start = ISP1761_IRQ,
.end = ISP1761_IRQ,
.flags = IORESOURCE_IRQ,
@@ -71,7 +70,7 @@ static struct platform_device *bfin_isp1761_devices[] = {
int __init bfin_isp1761_init(void)
{
- unsigned int num_devices=ARRAY_SIZE(bfin_isp1761_devices);
+ unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices);
printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__);
set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING);
@@ -98,7 +97,7 @@ static struct resource smc91x_resources[] = {
.start = 0x2C010300,
.end = 0x2C010300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PF9,
.end = IRQ_PF9,
@@ -116,18 +115,18 @@ static struct platform_device smc91x_device = {
#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
static struct resource bfin_uart_resources[] = {
- {
- .start = 0xFFC00400,
- .end = 0xFFC004FF,
- .flags = IORESOURCE_MEM,
- },
+ {
+ .start = 0xFFC00400,
+ .end = 0xFFC004FF,
+ .flags = IORESOURCE_MEM,
+ },
};
static struct platform_device bfin_uart_device = {
- .name = "bfin-uart",
- .id = 1,
- .num_resources = ARRAY_SIZE(bfin_uart_resources),
- .resource = bfin_uart_resources,
+ .name = "bfin-uart",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(bfin_uart_resources),
+ .resource = bfin_uart_resources,
};
#endif
@@ -176,7 +175,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
&spi_bfin_master_device,
#endif
#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
- &bfin_uart_device,
+ &bfin_uart_device,
#endif
};
diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c
index 585ecdd2f6a..4dfea5da674 100644
--- a/arch/blackfin/mach-bf561/boards/generic_board.c
+++ b/arch/blackfin/mach-bf561/boards/generic_board.c
@@ -30,7 +30,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
char *bfin_board_name = "UNKNOWN BOARD";
@@ -43,11 +43,11 @@ static struct resource smc91x_resources[] = {
.start = 0x2C010300,
.end = 0x2C010300 + 16,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PROG_INTB,
.end = IRQ_PROG_INTB,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
- },{
+ }, {
/*
* denotes the flag pin and is used directly if
* CONFIG_IRQCHIP_DEMUX_GPIO is defined.
diff --git a/arch/blackfin/mach-bf561/boards/tepla.c b/arch/blackfin/mach-bf561/boards/tepla.c
index db308c7ccab..c442eb23db5 100644
--- a/arch/blackfin/mach-bf561/boards/tepla.c
+++ b/arch/blackfin/mach-bf561/boards/tepla.c
@@ -14,7 +14,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
char *bfin_board_name = "Tepla-BF561";
@@ -26,11 +26,11 @@ static struct resource smc91x_resources[] = {
.start = 0x2C000300,
.end = 0x2C000320,
.flags = IORESOURCE_MEM,
- },{
+ }, {
.start = IRQ_PROG_INTB,
.end = IRQ_PROG_INTB,
.flags = IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHLEVEL,
- },{
+ }, {
/*
* denotes the flag pin and is used directly if
* CONFIG_IRQCHIP_DEMUX_GPIO is defined.
diff --git a/arch/blackfin/mach-bf561/coreb.c b/arch/blackfin/mach-bf561/coreb.c
index b28582fe083..5d1d21b4c2a 100644
--- a/arch/blackfin/mach-bf561/coreb.c
+++ b/arch/blackfin/mach-bf561/coreb.c
@@ -32,8 +32,8 @@
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/module.h>
+#include <linux/uaccess.h>
#include <asm/dma.h>
-#include <asm/uaccess.h>
#define MODULE_VER "v0.1"
@@ -202,7 +202,7 @@ static int coreb_open(struct inode *inode, struct file *file)
spin_unlock_irq(&coreb_lock);
return 0;
- out_busy:
+ out_busy:
spin_unlock_irq(&coreb_lock);
return -EBUSY;
}
@@ -365,19 +365,19 @@ int __init bf561_coreb_init(void)
printk(KERN_INFO "BF561 Core B driver %s initialized.\n", MODULE_VER);
return 0;
- release_dma_src:
+ release_dma_src:
free_dma(CH_MEM_STREAM2_SRC);
- release_dma_dest:
+ release_dma_dest:
free_dma(CH_MEM_STREAM2_DEST);
- release_data_a_sram:
+ release_data_a_sram:
release_mem_region(0xff400000, 0x8000);
- release_data_b_sram:
+ release_data_b_sram:
release_mem_region(0xff500000, 0x8000);
- release_instruction_b_sram:
+ release_instruction_b_sram:
release_mem_region(0xff610000, 0x4000);
- release_instruction_a_sram:
+ release_instruction_a_sram:
release_mem_region(0xff600000, 0x4000);
- exit:
+ exit:
return -ENOMEM;
}
diff --git a/arch/blackfin/mach-bf561/dma.c b/arch/blackfin/mach-bf561/dma.c
new file mode 100644
index 00000000000..89c65bb0bed
--- /dev/null
+++ b/arch/blackfin/mach-bf561/dma.c
@@ -0,0 +1,131 @@
+/*
+ * File: arch/blackfin/mach-bf561/dma.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <asm/blackfin.h>
+#include <asm/dma.h>
+
+struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA1_0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_11_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_11_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
+};
+
+int channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_PPI0:
+ ret_irq = IRQ_PPI0;
+ break;
+ case CH_PPI1:
+ ret_irq = IRQ_PPI1;
+ break;
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+ case CH_SPI:
+ ret_irq = IRQ_SPI;
+ break;
+ case CH_UART_RX:
+ ret_irq = IRQ_UART_RX;
+ break;
+ case CH_UART_TX:
+ ret_irq = IRQ_UART_TX;
+ break;
+
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MEM_DMA0;
+ break;
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MEM_DMA1;
+ break;
+ case CH_MEM_STREAM2_SRC:
+ case CH_MEM_STREAM2_DEST:
+ ret_irq = IRQ_MEM_DMA2;
+ break;
+ case CH_MEM_STREAM3_SRC:
+ case CH_MEM_STREAM3_DEST:
+ ret_irq = IRQ_MEM_DMA3;
+ break;
+
+ case CH_IMEM_STREAM0_SRC:
+ case CH_IMEM_STREAM0_DEST:
+ ret_irq = IRQ_IMEM_DMA0;
+ break;
+ case CH_IMEM_STREAM1_SRC:
+ case CH_IMEM_STREAM1_DEST:
+ ret_irq = IRQ_IMEM_DMA1;
+ break;
+ }
+ return ret_irq;
+}
diff --git a/arch/blackfin/mach-bf561/head.S b/arch/blackfin/mach-bf561/head.S
index ad9187a866a..2f08bcb2dde 100644
--- a/arch/blackfin/mach-bf561/head.S
+++ b/arch/blackfin/mach-bf561/head.S
@@ -28,7 +28,10 @@
*/
#include <linux/linkage.h>
+#include <linux/init.h>
#include <asm/blackfin.h>
+#include <asm/trace.h>
+
#if CONFIG_BFIN_KERNEL_CLOCK
#include <asm/mach/mem_init.h>
#endif
@@ -42,18 +45,19 @@
#define INITIAL_STACK 0xFFB01000
-.text
+__INIT
ENTRY(__start)
-ENTRY(__stext)
- /* R0: argument of command line string, passed from uboot, save it */
+ /* R0: argument of command line string, passed from uboot, save it */
R7 = R0;
- /* Set the SYSCFG register */
+ /* Set the SYSCFG register:
+ * Enable Cycle Counter and Nesting Of Interrupts (3rd Bit)
+ */
R0 = 0x36;
- SYSCFG = R0; /*Enable Cycle Counter and Nesting Of Interrupts(3rd Bit)*/
+ SYSCFG = R0;
R0 = 0;
- /*Clear Out All the data and pointer Registers*/
+ /* Clear Out All the data and pointer Registers */
R1 = R0;
R2 = R0;
R3 = R0;
@@ -75,7 +79,7 @@ ENTRY(__stext)
L2 = r0;
L3 = r0;
- /* Clear Out All the DAG Registers*/
+ /* Clear Out All the DAG Registers */
B0 = r0;
B1 = r0;
B2 = r0;
@@ -91,6 +95,10 @@ ENTRY(__stext)
M2 = r0;
M3 = r0;
+ trace_buffer_start(p0,r0);
+ P0 = R1;
+ R0 = R1;
+
/* Turn off the icache */
p0.l = (IMEM_CONTROL & 0xFFFF);
p0.h = (IMEM_CONTROL >> 16);
@@ -219,6 +227,7 @@ ENTRY(__stext)
.LWAIT_HERE:
jump .LWAIT_HERE;
+ENDPROC(__start)
ENTRY(_real_start)
[ -- sp ] = reti;
@@ -238,7 +247,7 @@ ENTRY(_real_start)
p2.h = ___bss_stop;
r0 = 0;
p2 -= p1;
- lsetup (.L_clear_bss, .L_clear_bss ) lc0 = p2;
+ lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2;
.L_clear_bss:
B[p1++] = r0;
@@ -253,11 +262,11 @@ ENTRY(_real_start)
r0 = r0 >> 1;
p2 = r0;
r0 = 0;
- lsetup (.L_clear_zero, .L_clear_zero ) lc0 = p2;
+ lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2;
.L_clear_zero:
W[p1++] = r0;
-/* pass the uboot arguments to the global value command line */
+ /* pass the uboot arguments to the global value command line */
R0 = R7;
call _cmdline_init;
@@ -287,9 +296,10 @@ ENTRY(_real_start)
sp = r1;
usp = sp;
fp = sp;
- call _start_kernel;
-.L_exit:
- jump.s .L_exit;
+ jump.l _start_kernel;
+ENDPROC(_real_start)
+
+__FINIT
.section .l1.text
#if CONFIG_BFIN_KERNEL_CLOCK
@@ -350,7 +360,7 @@ ENTRY(_start_dma_code)
if ! CC jump .Lcheck_again;
/* Configure SCLK & CCLK Dividers */
- r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
+ r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
p0.h = hi(PLL_DIV);
p0.l = lo(PLL_DIV);
w[p0] = r0.l;
@@ -391,6 +401,7 @@ ENTRY(_start_dma_code)
SSYNC;
RTS;
+ENDPROC(_start_dma_code)
#endif /* CONFIG_BFIN_KERNEL_CLOCK */
ENTRY(_bfin_reset)
diff --git a/arch/blackfin/mach-bf561/ints-priority.c b/arch/blackfin/mach-bf561/ints-priority.c
index 89c52ff95b2..09b541b0f7c 100644
--- a/arch/blackfin/mach-bf561/ints-priority.c
+++ b/arch/blackfin/mach-bf561/ints-priority.c
@@ -4,7 +4,7 @@
* Author: Michael Hennerich
*
* Created:
- * Description: Set up the interupt priorities
+ * Description: Set up the interrupt priorities
*
* Modified:
* Copyright 2004-2006 Analog Devices Inc.
@@ -28,8 +28,8 @@
*/
#include <linux/module.h>
+#include <linux/irq.h>
#include <asm/blackfin.h>
-#include <asm/irq.h>
void program_IAR(void)
{
diff --git a/arch/blackfin/mach-common/Makefile b/arch/blackfin/mach-common/Makefile
index d3a49073d19..0279ede7039 100644
--- a/arch/blackfin/mach-common/Makefile
+++ b/arch/blackfin/mach-common/Makefile
@@ -4,9 +4,9 @@
obj-y := \
cache.o cacheinit.o cplbhdlr.o cplbmgr.o entry.o \
- interrupt.o lock.o dpmc.o irqpanic.o
+ interrupt.o lock.o irqpanic.o
obj-$(CONFIG_CPLB_INFO) += cplbinfo.o
obj-$(CONFIG_BFIN_SINGLE_CORE) += ints-priority-sc.o
obj-$(CONFIG_BFIN_DUAL_CORE) += ints-priority-dc.o
-obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_PM) += pm.o dpmc.o
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S
index bb9446ef66e..7063795eb7c 100644
--- a/arch/blackfin/mach-common/cache.S
+++ b/arch/blackfin/mach-common/cache.S
@@ -70,6 +70,7 @@ ENTRY(_cache_invalidate)
.Lno_dcache_b:
R7 = [SP++];
RTS;
+ENDPROC(_cache_invalidate)
/* Invalidate the Entire Instruction cache by
* disabling IMC bit
@@ -106,6 +107,8 @@ ENTRY(_invalidate_entire_icache)
( R7:5) = [SP++];
RTS;
+ENDPROC(_invalidate_entire_icache)
+ENDPROC(_icache_invalidate)
/*
* blackfin_cache_flush_range(start, end)
@@ -120,15 +123,16 @@ ENTRY(_blackfin_icache_flush_range)
R2 = R0 & R2;
P0 = R2;
P1 = R1;
- CSYNC;
+ CSYNC(R3);
IFLUSH [P0];
1:
IFLUSH [P0++];
CC = P0 < P1 (iu);
IF CC JUMP 1b (bp);
IFLUSH [P0];
- SSYNC;
+ SSYNC(R3);
RTS;
+ENDPROC(_blackfin_icache_flush_range)
/*
* blackfin_icache_dcache_flush_range(start, end)
@@ -144,7 +148,7 @@ ENTRY(_blackfin_icache_dcache_flush_range)
R2 = R0 & R2;
P0 = R2;
P1 = R1;
- CSYNC;
+ CSYNC(R3);
IFLUSH [P0];
1:
FLUSH [P0];
@@ -153,8 +157,9 @@ ENTRY(_blackfin_icache_dcache_flush_range)
IF CC JUMP 1b (bp);
IFLUSH [P0];
FLUSH [P0];
- SSYNC;
+ SSYNC(R3);
RTS;
+ENDPROC(_blackfin_icache_dcache_flush_range)
/* Throw away all D-cached data in specified region without any obligation to
* write them back. However, we must clean the D-cached entries around the
@@ -169,7 +174,7 @@ ENTRY(_blackfin_dcache_invalidate_range)
R2 = R0 & R2;
P0 = R2;
P1 = R1;
- CSYNC;
+ CSYNC(R3);
FLUSHINV[P0];
1:
FLUSHINV[P0++];
@@ -181,8 +186,9 @@ ENTRY(_blackfin_dcache_invalidate_range)
* so do one more.
*/
FLUSHINV[P0];
- SSYNC;
+ SSYNC(R3);
RTS;
+ENDPROC(_blackfin_dcache_invalidate_range)
/* Invalidate the Entire Data cache by
* clearing DMC[1:0] bits
@@ -221,13 +227,15 @@ ENTRY(_dcache_invalidate)
( R7:6) = [SP++];
RTS;
+ENDPROC(_dcache_invalidate)
+ENDPROC(_invalidate_entire_dcache)
ENTRY(_blackfin_dcache_flush_range)
R2 = -L1_CACHE_BYTES;
R2 = R0 & R2;
P0 = R2;
P1 = R1;
- CSYNC;
+ CSYNC(R3);
FLUSH[P0];
1:
FLUSH[P0++];
@@ -239,15 +247,17 @@ ENTRY(_blackfin_dcache_flush_range)
* one more.
*/
FLUSH[P0];
- SSYNC;
+ SSYNC(R3);
RTS;
+ENDPROC(_blackfin_dcache_flush_range)
ENTRY(_blackfin_dflush_page)
P1 = 1 << (PAGE_SHIFT - L1_CACHE_SHIFT);
P0 = R0;
- CSYNC;
+ CSYNC(R3);
FLUSH[P0];
LSETUP (.Lfl1, .Lfl1) LC0 = P1;
.Lfl1: FLUSH [P0++];
- SSYNC;
+ SSYNC(R3);
RTS;
+ENDPROC(_blackfin_dflush_page)
diff --git a/arch/blackfin/mach-common/cacheinit.S b/arch/blackfin/mach-common/cacheinit.S
index 8c17f099e5e..9d475623b72 100644
--- a/arch/blackfin/mach-common/cacheinit.S
+++ b/arch/blackfin/mach-common/cacheinit.S
@@ -38,100 +38,37 @@
.text
+#ifdef ANOMALY_05000125
#if defined(CONFIG_BLKFIN_CACHE)
-ENTRY(_bfin_icache_init)
+ENTRY(_bfin_write_IMEM_CONTROL)
- /* Initialize Instruction CPLBS */
-
- I0.L = (ICPLB_ADDR0 & 0xFFFF);
- I0.H = (ICPLB_ADDR0 >> 16);
-
- I1.L = (ICPLB_DATA0 & 0xFFFF);
- I1.H = (ICPLB_DATA0 >> 16);
-
- I2.L = _icplb_table;
- I2.H = _icplb_table;
-
- r1 = -1; /* end point comparison */
- r3 = 15; /* max counter */
-
-/* read entries from table */
-
-.Lread_iaddr:
- R0 = [I2++];
- CC = R0 == R1;
- IF CC JUMP .Lidone;
- [I0++] = R0;
-
-.Lread_idata:
- R2 = [I2++];
- [I1++] = R2;
- R3 = R3 + R1;
- CC = R3 == R1;
- IF !CC JUMP .Lread_iaddr;
-
-.Lidone:
/* Enable Instruction Cache */
P0.l = (IMEM_CONTROL & 0xFFFF);
P0.h = (IMEM_CONTROL >> 16);
- R1 = [P0];
- R0 = (IMC | ENICPLB);
- R0 = R0 | R1;
/* Anomaly 05000125 */
- CLI R2;
+ CLI R1;
SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
.align 8;
[P0] = R0;
SSYNC;
- STI R2;
+ STI R1;
RTS;
+
+ENDPROC(_bfin_write_IMEM_CONTROL)
#endif
#if defined(CONFIG_BLKFIN_DCACHE)
-ENTRY(_bfin_dcache_init)
-
- /* Initialize Data CPLBS */
-
- I0.L = (DCPLB_ADDR0 & 0xFFFF);
- I0.H = (DCPLB_ADDR0 >> 16);
-
- I1.L = (DCPLB_DATA0 & 0xFFFF);
- I1.H = (DCPLB_DATA0 >> 16);
-
- I2.L = _dcplb_table;
- I2.H = _dcplb_table;
-
- R1 = -1; /* end point comparison */
- R3 = 15; /* max counter */
-
- /* read entries from table */
-.Lread_daddr:
- R0 = [I2++];
- cc = R0 == R1;
- IF CC JUMP .Lddone;
- [I0++] = R0;
-
-.Lread_ddata:
- R2 = [I2++];
- [I1++] = R2;
- R3 = R3 + R1;
- CC = R3 == R1;
- IF !CC JUMP .Lread_daddr;
-.Lddone:
- P0.L = (DMEM_CONTROL & 0xFFFF);
- P0.H = (DMEM_CONTROL >> 16);
- R1 = [P0];
-
- R0 = DMEM_CNTR;
-
- R0 = R0 | R1;
- /* Anomaly 05000125 */
- CLI R2;
+ENTRY(_bfin_write_DMEM_CONTROL)
+ CLI R1;
SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
.align 8;
[P0] = R0;
SSYNC;
- STI R2;
+ STI R1;
RTS;
+
+ENDPROC(_bfin_write_DMEM_CONTROL)
+#endif
+
#endif
diff --git a/arch/blackfin/mach-common/cplbhdlr.S b/arch/blackfin/mach-common/cplbhdlr.S
index b979067c49e..2f3c72c2399 100644
--- a/arch/blackfin/mach-common/cplbhdlr.S
+++ b/arch/blackfin/mach-common/cplbhdlr.S
@@ -42,8 +42,6 @@
.align 2
-.global __cplb_hdr;
-.type __cplb_hdr, STT_FUNC;
ENTRY(__cplb_hdr)
R2 = SEQSTAT;
@@ -128,3 +126,5 @@ ENTRY(__cplb_hdr)
call _panic_cplb_error;
SP += 12;
JUMP _handle_bad_cplb;
+
+ENDPROC(__cplb_hdr)
diff --git a/arch/blackfin/mach-common/cplbinfo.c b/arch/blackfin/mach-common/cplbinfo.c
index d65fac39d1b..785ca981697 100644
--- a/arch/blackfin/mach-common/cplbinfo.c
+++ b/arch/blackfin/mach-common/cplbinfo.c
@@ -31,11 +31,10 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
#include <asm/current.h>
-#include <asm/uaccess.h>
#include <asm/system.h>
-
#include <asm/cplb.h>
#include <asm/blackfin.h>
@@ -82,7 +81,7 @@ static char *cplb_print_entry(char *buf, int type)
int entry = 0, used_cplb = 0;
if (type == CPLB_I) {
- buf += sprintf(buf, "Instrction CPLB entry:\n");
+ buf += sprintf(buf, "Instruction CPLB entry:\n");
p_addr = ipdt_table;
p_data = ipdt_table + 1;
p_icount = ipdt_swapcount_table;
@@ -92,8 +91,7 @@ static char *cplb_print_entry(char *buf, int type)
} else
buf += sprintf(buf, "Data CPLB entry:\n");
- buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\
-\tiCount\toCount\n");
+ buf += sprintf(buf, "Address\t\tData\tSize\tValid\tLocked\tSwapin\n\tiCount\toCount\n");
while (*p_addr != 0xffffffff) {
entry = cplb_find_entry(cplb_addr, cplb_data, *p_addr, *p_data);
@@ -144,8 +142,7 @@ static int cplbinfo_proc_output(char *buf)
p = buf;
- p += sprintf(p,
- "------------------ CPLB Information ------------------\n\n");
+ p += sprintf(p, "------------------ CPLB Information ------------------\n\n");
if (bfin_read_IMEM_CONTROL() & ENICPLB)
p = cplb_print_entry(p, CPLB_I);
@@ -191,9 +188,9 @@ static int __init cplbinfo_init(void)
{
struct proc_dir_entry *entry;
- if ((entry = create_proc_entry("cplbinfo", 0, NULL)) == NULL) {
+ entry = create_proc_entry("cplbinfo", 0, NULL);
+ if (!entry)
return -ENOMEM;
- }
entry->read_proc = cplbinfo_read_proc;
entry->write_proc = cplbinfo_write_proc;
diff --git a/arch/blackfin/mach-common/cplbmgr.S b/arch/blackfin/mach-common/cplbmgr.S
index f5efc4bc65e..e4b47e09cf1 100644
--- a/arch/blackfin/mach-common/cplbmgr.S
+++ b/arch/blackfin/mach-common/cplbmgr.S
@@ -592,6 +592,7 @@ ENTRY(_cplb_mgr)
( R7:4,P5:3 ) = [SP++];
R0 = CPLB_RELOADED;
RTS;
+ENDPROC(_cplb_mgr)
.data
.align 4;
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 7d0368772cd..d61bba98fb5 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -49,34 +49,15 @@
#include <linux/linkage.h>
+#include <linux/unistd.h>
#include <asm/blackfin.h>
-#include <asm/unistd.h>
#include <asm/errno.h>
#include <asm/thread_info.h> /* TIF_NEED_RESCHED */
#include <asm/asm-offsets.h>
+#include <asm/trace.h>
#include <asm/mach-common/context.S>
-#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
- /*
- * TODO: this should be proper save/restore, but for now
- * we'll just cheat and use 0x1/0x13
- */
-# define DEBUG_START_HWTRACE \
- P5.l = LO(TBUFCTL); \
- P5.h = HI(TBUFCTL); \
- R7 = 0x13; \
- [P5] = R7;
-# define DEBUG_STOP_HWTRACE \
- P5.l = LO(TBUFCTL); \
- P5.h = HI(TBUFCTL); \
- R7 = 0x01; \
- [P5] = R7;
-#else
-# define DEBUG_START_HWTRACE
-# define DEBUG_STOP_HWTRACE
-#endif
-
#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
.section .l1.text
#else
@@ -103,59 +84,34 @@ ENTRY(_ex_dcplb)
if !cc jump _return_from_exception;
/* fall through */
#endif
+ENDPROC(_ex_dcplb)
ENTRY(_ex_icplb)
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
SAVE_ALL_SYS
call __cplb_hdr;
- DEBUG_START_HWTRACE
+ DEBUG_START_HWTRACE(p5, r7)
RESTORE_ALL_SYS
SP = RETN;
rtx;
-
-ENTRY(_ex_spinlock)
- /* Transform this into a syscall - twiddle the syscall vector. */
- p5.l = lo(EVT15);
- p5.h = hi(EVT15);
- r7.l = _spinlock_bh;
- r7.h = _spinlock_bh;
- [p5] = r7;
- csync;
- /* Fall through. */
+ENDPROC(_ex_icplb)
ENTRY(_ex_syscall)
- DEBUG_START_HWTRACE
+ DEBUG_START_HWTRACE(p5, r7)
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
raise 15; /* invoked by TRAP #0, for sys call */
sp = retn;
rtx
-
-ENTRY(_spinlock_bh)
- SAVE_ALL_SYS
- /* To end up here, vector 15 was changed - so we have to change it
- * back.
- */
- p0.l = lo(EVT15);
- p0.h = hi(EVT15);
- p1.l = _evt_system_call;
- p1.h = _evt_system_call;
- [p0] = p1;
- csync;
- r0 = [sp + PT_R0];
- sp += -12;
- call _sys_bfin_spinlock;
- sp += 12;
- [SP + PT_R0] = R0;
- RESTORE_ALL_SYS
- rti;
+ENDPROC(_ex_syscall)
ENTRY(_ex_soft_bp)
r7 = retx;
r7 += -2;
retx = r7;
jump.s _ex_trap_c;
+ENDPROC(_ex_soft_bp)
ENTRY(_ex_single_step)
r7 = retx;
@@ -180,7 +136,7 @@ ENTRY(_ex_single_step)
if !cc jump _ex_trap_c;
_return_from_exception:
- DEBUG_START_HWTRACE
+ DEBUG_START_HWTRACE(p5, r7)
#ifdef ANOMALY_05000257
R7=LC0;
LC0=R7;
@@ -191,6 +147,7 @@ _return_from_exception:
ASTAT = [sp++];
sp = retn;
rtx;
+ENDPROC(_ex_soft_bp)
ENTRY(_handle_bad_cplb)
/* To get here, we just tried and failed to change a CPLB
@@ -201,7 +158,7 @@ ENTRY(_handle_bad_cplb)
* need to make a CPLB exception look like a normal exception
*/
- DEBUG_START_HWTRACE
+ DEBUG_START_HWTRACE(p5, r7)
RESTORE_ALL_SYS
[--sp] = ASTAT;
[--sp] = (R7:6, P5:4);
@@ -244,12 +201,13 @@ ENTRY(_ex_trap_c)
R6 = SEQSTAT;
[P5] = R6;
- DEBUG_START_HWTRACE
+ DEBUG_START_HWTRACE(p5, r7)
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
SP = RETN;
raise 5;
rtx;
+ENDPROC(_ex_trap_c)
ENTRY(_exception_to_level5)
SAVE_ALL_SYS
@@ -314,6 +272,7 @@ ENTRY(_exception_to_level5)
call _ret_from_exception;
RESTORE_ALL_SYS
rti;
+ENDPROC(_exception_to_level5)
ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
/* Since the kernel stack can be anywhere, it's not guaranteed to be
@@ -326,7 +285,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
/* Try to deal with syscalls quickly. */
[--sp] = ASTAT;
[--sp] = (R7:6, P5:4);
- DEBUG_STOP_HWTRACE
+ DEBUG_STOP_HWTRACE(p5, r7)
r7 = SEQSTAT; /* reason code is in bit 5:0 */
r6.l = lo(SEQSTAT_EXCAUSE);
r6.h = hi(SEQSTAT_EXCAUSE);
@@ -342,6 +301,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
r7 = -ENOSYS; /* signextending enough */
[sp + PT_R0] = r7; /* return value from system call */
jump .Lsyscall_really_exit;
+ENDPROC(_trap)
ENTRY(_kernel_execve)
link SIZEOF_PTREGS;
@@ -396,6 +356,7 @@ ENTRY(_kernel_execve)
1:
unlink;
rts;
+ENDPROC(_kernel_execve)
ENTRY(_system_call)
/* Store IPEND */
@@ -503,6 +464,7 @@ ENTRY(_system_call)
r5 = [sp + PT_RESERVED];
rets = r5;
rts;
+ENDPROC(_system_call)
_sys_trace:
call _syscall_trace;
@@ -531,6 +493,7 @@ _sys_trace:
call _syscall_trace;
jump .Lresume_userspace;
+ENDPROC(_sys_trace)
ENTRY(_resume)
/*
@@ -580,6 +543,7 @@ _new_old_task:
* in "new" task.
*/
rts;
+ENDPROC(_resume)
ENTRY(_ret_from_exception)
p2.l = lo(IPEND);
@@ -638,6 +602,7 @@ ENTRY(_ret_from_exception)
syscfg = r0;
5:
rts;
+ENDPROC(_ret_from_exception)
ENTRY(_return_from_int)
/* If someone else already raised IRQ 15, do nothing. */
@@ -680,6 +645,7 @@ ENTRY(_return_from_int)
rti;
2:
rts;
+ENDPROC(_return_from_int)
ENTRY(_lower_to_irq14)
#if defined(ANOMALY_05000281)
@@ -725,6 +691,10 @@ _schedule_and_signal_from_int:
r0 = [p0];
sti r0;
+ r0 = sp;
+ sp += -12;
+ call _finish_atomic_sections;
+ sp += 12;
jump.s .Lresume_userspace;
_schedule_and_signal:
@@ -745,6 +715,7 @@ _schedule_and_signal:
1:
RESTORE_CONTEXT
rti;
+ENDPROC(_lower_to_irq14)
/* Make sure when we start, that the circular buffer is initialized properly
* R0 and P0 are call clobbered, so we can use them here.
@@ -758,6 +729,7 @@ ENTRY(_init_exception_buff)
p0.l = _out_ptr_excause;
[p0] = r0;
rts;
+ENDPROC(_init_exception_buff)
/*
* Put these in the kernel data section - that should always be covered by
@@ -772,14 +744,14 @@ ENTRY(_init_exception_buff)
ALIGN
_extable:
/* entry for each EXCAUSE[5:0]
- * This table bmust be in sync with the table in ./kernel/traps.c
+ * This table must be in sync with the table in ./kernel/traps.c
* EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
*/
.long _ex_syscall; /* 0x00 - User Defined - Linux Syscall */
.long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */
.long _ex_trap_c /* 0x02 - User Defined */
- .long _ex_trap_c /* 0x03 - User Defined - Atomic test and set service */
- .long _ex_spinlock /* 0x04 - User Defined */
+ .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */
+ .long _ex_trap_c /* 0x04 - User Defined */
.long _ex_trap_c /* 0x05 - User Defined */
.long _ex_trap_c /* 0x06 - User Defined */
.long _ex_trap_c /* 0x07 - User Defined */
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index dd45664f0d0..203e2070916 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -34,6 +34,7 @@
#include <linux/linkage.h>
#include <asm/entry.h>
#include <asm/asm-offsets.h>
+#include <asm/trace.h>
#include <asm/mach-common/context.S>
@@ -66,6 +67,7 @@ ENTRY(_evt_emulation)
SP += 12;
/* - GDB stub fills this in by itself (if defined) */
rte;
+ENDPROC(_evt_emulation)
#endif
/* Common interrupt entry code. First we do CLI, then push
@@ -138,7 +140,7 @@ __common_int_entry:
fp = 0;
#endif
-#ifdef ANOMALY_05000283
+#if defined (ANOMALY_05000283) || defined (ANOMALY_05000315)
cc = r7 == r7;
p5.h = 0xffc0;
p5.l = 0x0014;
@@ -169,10 +171,9 @@ ENTRY(_evt_ivhw)
r7.l = W[p5];
1:
#endif
- p0.l = lo(TBUFCTL);
- p0.h = hi(TBUFCTL);
- r0 = 1;
- [p0] = r0;
+
+ trace_buffer_stop(p0, r0);
+
r0 = IRQ_HWERR;
r1 = sp;
@@ -251,3 +252,4 @@ ENTRY(_evt_system_call)
#endif
call _system_call;
jump .Lcommon_restore_context;
+ENDPROC(_evt_system_call)
diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c
index f3cf07036c2..6b9fd03ce83 100644
--- a/arch/blackfin/mach-common/ints-priority-dc.c
+++ b/arch/blackfin/mach-common/ints-priority-dc.c
@@ -4,7 +4,7 @@
* Author:
*
* Created: ?
- * Description: Set up the interupt priorities
+ * Description: Set up the interrupt priorities
*
* Modified:
* 1996 Roman Zippel
@@ -183,7 +183,7 @@ static void bf561_gpio_ack_irq(unsigned int irq)
{
u16 gpionr = irq - IRQ_PF0;
- if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+ if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
set_gpio_data(gpionr, 0);
SSYNC();
}
@@ -193,7 +193,7 @@ static void bf561_gpio_mask_ack_irq(unsigned int irq)
{
u16 gpionr = irq - IRQ_PF0;
- if(gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
+ if (gpio_edge_triggered[gpio_bank(gpionr)] & gpio_bit(gpionr)) {
set_gpio_data(gpionr, 0);
SSYNC();
}
@@ -222,7 +222,7 @@ static unsigned int bf561_gpio_irq_startup(unsigned int irq)
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
ret = gpio_request(gpionr, NULL);
- if(ret)
+ if (ret)
return ret;
}
@@ -262,7 +262,7 @@ static int bf561_gpio_irq_type(unsigned int irq, unsigned int type)
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
ret = gpio_request(gpionr, NULL);
- if(ret)
+ if (ret)
return ret;
}
@@ -371,6 +371,9 @@ int __init init_arch_irq(void)
bfin_write_SICA_IMASK1(SIC_UNMASK_ALL);
SSYNC();
+ bfin_write_SICA_IWR0(IWR_ENABLE_ALL);
+ bfin_write_SICA_IWR1(IWR_ENABLE_ALL);
+
local_irq_disable();
init_exception_buff();
@@ -393,7 +396,7 @@ int __init init_arch_irq(void)
bfin_write_EVT15(evt_system_call);
CSYNC();
- for (irq = 0; irq < SYS_IRQS; irq++) {
+ for (irq = 0; irq <= SYS_IRQS; irq++) {
if (irq <= IRQ_CORETMR)
set_irq_chip(irq, &bf561_core_irqchip);
else
diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c
index 34b62288ec3..28a878c3577 100644
--- a/arch/blackfin/mach-common/ints-priority-sc.c
+++ b/arch/blackfin/mach-common/ints-priority-sc.c
@@ -4,7 +4,7 @@
* Author:
*
* Created: ?
- * Description: Set up the interupt priorities
+ * Description: Set up the interrupt priorities
*
* Modified:
* 1996 Roman Zippel
@@ -13,7 +13,7 @@
* 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
* 2003 Metrowerks/Motorola
* 2003 Bas Vermeulen <bas@buyways.nl>
- * Copyright 2004-2006 Analog Devices Inc.
+ * Copyright 2004-2007 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -65,9 +65,9 @@ atomic_t num_spurious;
struct ivgx {
/* irq number for request_irq, available in mach-bf533/irq.h */
- int irqno;
+ unsigned int irqno;
/* corresponding bit in the SIC_ISR register */
- int isrflag;
+ unsigned int isrflag;
} ivg_table[NR_PERI_INTS];
struct ivg_slice {
@@ -88,17 +88,16 @@ static void __init search_IAR(void)
for (ivg = 0; ivg <= IVG13 - IVG7; ivg++) {
int irqn;
- ivg7_13[ivg].istop = ivg7_13[ivg].ifirst =
- &ivg_table[irq_pos];
+ ivg7_13[ivg].istop = ivg7_13[ivg].ifirst = &ivg_table[irq_pos];
for (irqn = 0; irqn < NR_PERI_INTS; irqn++) {
int iar_shift = (irqn & 7) * 4;
if (ivg ==
(0xf &
- bfin_read32((unsigned long *) SIC_IAR0 +
+ bfin_read32((unsigned long *)SIC_IAR0 +
(irqn >> 3)) >> iar_shift)) {
ivg_table[irq_pos].irqno = IVG7 + irqn;
- ivg_table[irq_pos].isrflag = 1 << irqn;
+ ivg_table[irq_pos].isrflag = 1 << (irqn % 32);
ivg7_13[ivg].istop++;
irq_pos++;
}
@@ -141,15 +140,31 @@ static void bfin_core_unmask_irq(unsigned int irq)
static void bfin_internal_mask_irq(unsigned int irq)
{
+#ifndef CONFIG_BF54x
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() &
~(1 << (irq - (IRQ_CORETMR + 1))));
+#else
+ unsigned mask_bank, mask_bit;
+ mask_bank = (irq - (IRQ_CORETMR + 1)) / 32;
+ mask_bit = (irq - (IRQ_CORETMR + 1)) % 32;
+ bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) &
+ ~(1 << mask_bit));
+#endif
SSYNC();
}
static void bfin_internal_unmask_irq(unsigned int irq)
{
+#ifndef CONFIG_BF54x
bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() |
(1 << (irq - (IRQ_CORETMR + 1))));
+#else
+ unsigned mask_bank, mask_bit;
+ mask_bank = (irq - (IRQ_CORETMR + 1)) / 32;
+ mask_bit = (irq - (IRQ_CORETMR + 1)) % 32;
+ bfin_write_SIC_IMASK(mask_bank, bfin_read_SIC_IMASK(mask_bank) |
+ (1 << mask_bit));
+#endif
SSYNC();
}
@@ -206,7 +221,7 @@ static struct irq_chip bfin_generic_error_irqchip = {
};
static void bfin_demux_error_irq(unsigned int int_err_irq,
- struct irq_desc *intb_desc)
+ struct irq_desc *intb_desc)
{
int irq = 0;
@@ -270,8 +285,8 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
}
pr_debug("IRQ %d:"
- " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
- irq);
+ " MASKED PERIPHERAL ERROR INTERRUPT ASSERTED\n",
+ irq);
}
} else
printk(KERN_ERR
@@ -279,11 +294,10 @@ static void bfin_demux_error_irq(unsigned int int_err_irq,
" INTERRUPT ASSERTED BUT NO SOURCE FOUND\n",
__FUNCTION__, __FILE__, __LINE__);
-
}
#endif /* BF537_GENERIC_ERROR_INT_DEMUX */
-#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && !defined(CONFIG_BF54x)
static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
static unsigned short gpio_edge_triggered[gpio_bank(MAX_BLACKFIN_GPIOS)];
@@ -361,8 +375,7 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
}
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
- IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
- {
+ IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
ret = gpio_request(gpionr, NULL);
if (ret)
@@ -407,7 +420,6 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
return 0;
}
-
static struct irq_chip bfin_gpio_irqchip = {
.ack = bfin_gpio_ack_irq,
.mask = bfin_gpio_mask_irq,
@@ -419,20 +431,20 @@ static struct irq_chip bfin_gpio_irqchip = {
};
static void bfin_demux_gpio_irq(unsigned int intb_irq,
- struct irq_desc *intb_desc)
+ struct irq_desc *intb_desc)
{
u16 i;
+ struct irq_desc *desc;
- for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=16) {
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i += 16) {
int irq = IRQ_PF0 + i;
int flag_d = get_gpiop_data(i);
int mask =
- flag_d & (gpio_enabled[gpio_bank(i)] &
- get_gpiop_maska(i));
+ flag_d & (gpio_enabled[gpio_bank(i)] & get_gpiop_maska(i));
while (mask) {
if (mask & 1) {
- struct irq_desc *desc = irq_desc + irq;
+ desc = irq_desc + irq;
desc->handle_irq(irq, desc);
}
irq++;
@@ -441,6 +453,264 @@ static void bfin_demux_gpio_irq(unsigned int intb_irq,
}
}
+#else /* CONFIG_IRQCHIP_DEMUX_GPIO */
+
+#define NR_PINT_SYS_IRQS 4
+#define NR_PINT_BITS 32
+#define NR_PINTS 160
+#define IRQ_NOT_AVAIL 0xFF
+
+#define PINT_2_BANK(x) ((x) >> 5)
+#define PINT_2_BIT(x) ((x) & 0x1F)
+#define PINT_BIT(x) (1 << (PINT_2_BIT(x)))
+
+static unsigned char irq2pint_lut[NR_PINTS];
+static unsigned char pint2irq_lut[NR_PINT_SYS_IRQS * NR_PINT_BITS];
+
+struct pin_int_t {
+ unsigned int mask_set;
+ unsigned int mask_clear;
+ unsigned int request;
+ unsigned int assign;
+ unsigned int edge_set;
+ unsigned int edge_clear;
+ unsigned int invert_set;
+ unsigned int invert_clear;
+ unsigned int pinstate;
+ unsigned int latch;
+};
+
+static struct pin_int_t *pint[NR_PINT_SYS_IRQS] = {
+ (struct pin_int_t *)PINT0_MASK_SET,
+ (struct pin_int_t *)PINT1_MASK_SET,
+ (struct pin_int_t *)PINT2_MASK_SET,
+ (struct pin_int_t *)PINT3_MASK_SET,
+};
+
+unsigned short get_irq_base(u8 bank, u8 bmap)
+{
+
+ u16 irq_base;
+
+ if (bank < 2) { /*PA-PB */
+ irq_base = IRQ_PA0 + bmap * 16;
+ } else { /*PC-PJ */
+ irq_base = IRQ_PC0 + bmap * 16;
+ }
+
+ return irq_base;
+
+}
+
+ /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
+void init_pint_lut(void)
+{
+ u16 bank, bit, irq_base, bit_pos;
+ u32 pint_assign;
+ u8 bmap;
+
+ memset(irq2pint_lut, IRQ_NOT_AVAIL, sizeof(irq2pint_lut));
+
+ for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {
+
+ pint_assign = pint[bank]->assign;
+
+ for (bit = 0; bit < NR_PINT_BITS; bit++) {
+
+ bmap = (pint_assign >> ((bit / 8) * 8)) & 0xFF;
+
+ irq_base = get_irq_base(bank, bmap);
+
+ irq_base += (bit % 8) + ((bit / 8) & 1 ? 8 : 0);
+ bit_pos = bit + bank * NR_PINT_BITS;
+
+ pint2irq_lut[bit_pos] = irq_base - SYS_IRQS;
+ irq2pint_lut[irq_base - SYS_IRQS] = bit_pos;
+
+ }
+
+ }
+
+}
+
+static unsigned short gpio_enabled[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+static void bfin_gpio_ack_irq(unsigned int irq)
+{
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+ pint[PINT_2_BANK(pint_val)]->request = PINT_BIT(pint_val);
+ SSYNC();
+}
+
+static void bfin_gpio_mask_ack_irq(unsigned int irq)
+{
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 pintbit = PINT_BIT(pint_val);
+ u8 bank = PINT_2_BANK(pint_val);
+
+ pint[bank]->request = pintbit;
+ pint[bank]->mask_clear = pintbit;
+ SSYNC();
+}
+
+static void bfin_gpio_mask_irq(unsigned int irq)
+{
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+ pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
+ SSYNC();
+}
+
+static void bfin_gpio_unmask_irq(unsigned int irq)
+{
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 pintbit = PINT_BIT(pint_val);
+ u8 bank = PINT_2_BANK(pint_val);
+
+ pint[bank]->request = pintbit;
+ pint[bank]->mask_set = pintbit;
+ SSYNC();
+}
+
+static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+{
+ unsigned int ret;
+ u16 gpionr = irq - IRQ_PA0;
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+
+ if (pint_val == IRQ_NOT_AVAIL)
+ return -ENODEV;
+
+ if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+ ret = gpio_request(gpionr, NULL);
+ if (ret)
+ return ret;
+ }
+
+ gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ bfin_gpio_unmask_irq(irq);
+
+ return ret;
+}
+
+static void bfin_gpio_irq_shutdown(unsigned int irq)
+{
+ bfin_gpio_mask_irq(irq);
+ gpio_free(irq - IRQ_PA0);
+ gpio_enabled[gpio_bank(irq - IRQ_PA0)] &= ~gpio_bit(irq - IRQ_PA0);
+}
+
+static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+{
+
+ unsigned int ret;
+ u16 gpionr = irq - IRQ_PA0;
+ u8 pint_val = irq2pint_lut[irq - SYS_IRQS];
+ u32 pintbit = PINT_BIT(pint_val);
+ u8 bank = PINT_2_BANK(pint_val);
+
+ if (pint_val == IRQ_NOT_AVAIL)
+ return -ENODEV;
+
+ if (type == IRQ_TYPE_PROBE) {
+ /* only probe unenabled GPIO interrupt lines */
+ if (gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))
+ return 0;
+ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+ }
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING |
+ IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+ if (!(gpio_enabled[gpio_bank(gpionr)] & gpio_bit(gpionr))) {
+ ret = gpio_request(gpionr, NULL);
+ if (ret)
+ return ret;
+ }
+
+ gpio_enabled[gpio_bank(gpionr)] |= gpio_bit(gpionr);
+ } else {
+ gpio_enabled[gpio_bank(gpionr)] &= ~gpio_bit(gpionr);
+ return 0;
+ }
+
+ gpio_direction_input(gpionr);
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+ pint[bank]->edge_set = pintbit;
+ } else {
+ pint[bank]->edge_clear = pintbit;
+ }
+
+ if ((type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)))
+ pint[bank]->invert_set = pintbit; /* low or falling edge denoted by one */
+ else
+ pint[bank]->invert_set = pintbit; /* high or rising edge denoted by zero */
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+ pint[bank]->invert_set = pintbit;
+ else
+ pint[bank]->invert_set = pintbit;
+
+ SSYNC();
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+ set_irq_handler(irq, handle_edge_irq);
+ else
+ set_irq_handler(irq, handle_level_irq);
+
+ return 0;
+}
+
+static struct irq_chip bfin_gpio_irqchip = {
+ .ack = bfin_gpio_ack_irq,
+ .mask = bfin_gpio_mask_irq,
+ .mask_ack = bfin_gpio_mask_ack_irq,
+ .unmask = bfin_gpio_unmask_irq,
+ .set_type = bfin_gpio_irq_type,
+ .startup = bfin_gpio_irq_startup,
+ .shutdown = bfin_gpio_irq_shutdown
+};
+
+static void bfin_demux_gpio_irq(unsigned int intb_irq,
+ struct irq_desc *intb_desc)
+{
+ u8 bank, pint_val;
+ u32 request, irq;
+ struct irq_desc *desc;
+
+ switch (intb_irq) {
+ case IRQ_PINT0:
+ bank = 0;
+ break;
+ case IRQ_PINT2:
+ bank = 2;
+ break;
+ case IRQ_PINT3:
+ bank = 3;
+ break;
+ case IRQ_PINT1:
+ bank = 1;
+ break;
+ default:
+ return;
+ }
+
+ pint_val = bank * NR_PINT_BITS;
+
+ request = pint[bank]->request;
+
+ while (request) {
+ if (request & 1) {
+ irq = pint2irq_lut[pint_val] + SYS_IRQS;
+ desc = irq_desc + irq;
+ desc->handle_irq(irq, desc);
+ }
+ pint_val++;
+ request >>= 1;
+ }
+
+}
#endif /* CONFIG_IRQCHIP_DEMUX_GPIO */
/*
@@ -452,7 +722,18 @@ int __init init_arch_irq(void)
int irq;
unsigned long ilat = 0;
/* Disable all the peripheral intrs - page 4-29 HW Ref manual */
+#ifdef CONFIG_BF54x
+ bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
+ bfin_write_SIC_IMASK1(SIC_UNMASK_ALL);
+ bfin_write_SIC_IMASK2(SIC_UNMASK_ALL);
+ bfin_write_SIC_IWR0(IWR_ENABLE_ALL);
+ bfin_write_SIC_IWR1(IWR_ENABLE_ALL);
+ bfin_write_SIC_IWR2(IWR_ENABLE_ALL);
+#else
bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
+ bfin_write_SIC_IWR(IWR_ENABLE_ALL);
+#endif
+
SSYNC();
local_irq_disable();
@@ -475,7 +756,18 @@ int __init init_arch_irq(void)
bfin_write_EVT15(evt_system_call);
CSYNC();
- for (irq = 0; irq < SYS_IRQS; irq++) {
+#if defined(CONFIG_IRQCHIP_DEMUX_GPIO) && defined(CONFIG_BF54x)
+#ifdef CONFIG_PINTx_REASSIGN
+ pint[0]->assign = CONFIG_PINT0_ASSIGN;
+ pint[1]->assign = CONFIG_PINT1_ASSIGN;
+ pint[2]->assign = CONFIG_PINT2_ASSIGN;
+ pint[3]->assign = CONFIG_PINT3_ASSIGN;
+#endif
+ /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
+ init_pint_lut();
+#endif
+
+ for (irq = 0; irq <= SYS_IRQS; irq++) {
if (irq <= IRQ_CORETMR)
set_irq_chip(irq, &bfin_core_irqchip);
else
@@ -484,20 +776,42 @@ int __init init_arch_irq(void)
if (irq != IRQ_GENERIC_ERROR) {
#endif
+ switch (irq) {
#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
- if ((irq != IRQ_PROG_INTA) /*PORT F & G MASK_A Interrupt*/
-# if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
- && (irq != IRQ_MAC_RX) /*PORT H MASK_A Interrupt*/
-# endif
- ) {
+#ifndef CONFIG_BF54x
+ case IRQ_PROG_INTA:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+#if defined(BF537_FAMILY) && !(defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
+ case IRQ_MAC_RX:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
#endif
- set_irq_handler(irq, handle_simple_irq);
-#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
- } else {
+#else
+ case IRQ_PINT0:
set_irq_chained_handler(irq,
bfin_demux_gpio_irq);
- }
+ break;
+ case IRQ_PINT1:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+ case IRQ_PINT2:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+ case IRQ_PINT3:
+ set_irq_chained_handler(irq,
+ bfin_demux_gpio_irq);
+ break;
+#endif /*CONFIG_BF54x */
#endif
+ default:
+ set_irq_handler(irq, handle_simple_irq);
+ break;
+ }
#ifdef BF537_GENERIC_ERROR_INT_DEMUX
} else {
@@ -513,7 +827,11 @@ int __init init_arch_irq(void)
#endif
#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#ifndef CONFIG_BF54x
for (irq = IRQ_PF0; irq < NR_IRQS; irq++) {
+#else
+ for (irq = IRQ_PA0; irq < NR_IRQS; irq++) {
+#endif
set_irq_chip(irq, &bfin_gpio_irqchip);
/* if configured as edge, then will be changed to do_edge_IRQ */
set_irq_handler(irq, handle_level_irq);
@@ -526,8 +844,7 @@ int __init init_arch_irq(void)
bfin_write_ILAT(ilat);
CSYNC();
- printk(KERN_INFO
- "Configuring Blackfin Priority Driven Interrupts\n");
+ printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
/* IMASK=xxx is equivalent to STI xx or irq_flags=xx,
* local_irq_enable()
*/
@@ -538,14 +855,13 @@ int __init init_arch_irq(void)
/* Enable interrupts IVG7-15 */
irq_flags = irq_flags | IMASK_IVG15 |
IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
- IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 |
- IMASK_IVGHW;
+ IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
return 0;
}
#ifdef CONFIG_DO_IRQ_L1
-void do_irq(int vec, struct pt_regs *fp)__attribute__((l1_text));
+void do_irq(int vec, struct pt_regs *fp) __attribute__((l1_text));
#endif
void do_irq(int vec, struct pt_regs *fp)
@@ -555,9 +871,25 @@ void do_irq(int vec, struct pt_regs *fp)
} else {
struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
- unsigned long sic_status;
+#ifdef CONFIG_BF54x
+ unsigned long sic_status[3];
SSYNC();
+ sic_status[0] = bfin_read_SIC_ISR(0) & bfin_read_SIC_IMASK(0);
+ sic_status[1] = bfin_read_SIC_ISR(1) & bfin_read_SIC_IMASK(1);
+ sic_status[2] = bfin_read_SIC_ISR(2) & bfin_read_SIC_IMASK(2);
+
+ for (;; ivg++) {
+ if (ivg >= ivg_stop) {
+ atomic_inc(&num_spurious);
+ return;
+ }
+ if (sic_status[(ivg->irqno - IVG7) / 32] & ivg->isrflag)
+ break;
+ }
+#else
+ unsigned long sic_status;
+ SSYNC();
sic_status = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
for (;; ivg++) {
@@ -567,6 +899,7 @@ void do_irq(int vec, struct pt_regs *fp)
} else if (sic_status & ivg->isrflag)
break;
}
+#endif
vec = ivg->irqno;
}
asm_do_IRQ(vec, fp);
diff --git a/arch/blackfin/mach-common/lock.S b/arch/blackfin/mach-common/lock.S
index 2cbb15b3392..386ac8dda07 100644
--- a/arch/blackfin/mach-common/lock.S
+++ b/arch/blackfin/mach-common/lock.S
@@ -155,6 +155,7 @@ ENTRY(_cache_grab_lock)
( R7:0,P5:0 ) = [SP++];
RTS;
+ENDPROC(_cache_grab_lock)
/* After the execution of critical code, the code is now locked into
* the cache way. Now we need to set ILOC.
@@ -186,6 +187,7 @@ ENTRY(_cache_lock)
( R7:0,P5:0 ) = [SP++];
RTS;
+ENDPROC(_cache_lock)
#endif /* BLKFIN_CACHE_LOCK */
@@ -193,7 +195,6 @@ ENTRY(_cache_lock)
*/
ENTRY(_read_iloc)
-
P1.H = (IMEM_CONTROL >> 16);
P1.L = (IMEM_CONTROL & 0xFFFF);
R1 = 0xF;
@@ -202,3 +203,4 @@ ENTRY(_read_iloc)
R0 = R0 & R1;
RTS;
+ENDPROC(_read_iloc)
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index afed5246dd9..1772d8d2c1a 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -35,11 +35,11 @@
#include <linux/pm.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
+#include <linux/io.h>
+#include <linux/irq.h>
-#include <asm/io.h>
#include <asm/dpmc.h>
-#include <asm/irq.h>
-
+#include <asm/gpio.h>
#ifdef CONFIG_PM_WAKEUP_GPIO_POLAR_H
#define WAKEUP_TYPE PM_WAKE_HIGH
diff --git a/arch/blackfin/mm/blackfin_sram.c b/arch/blackfin/mm/blackfin_sram.c
index dd0c6501c42..16c6169ed01 100644
--- a/arch/blackfin/mm/blackfin_sram.c
+++ b/arch/blackfin/mm/blackfin_sram.c
@@ -7,7 +7,7 @@
* Description: SRAM driver for Blackfin ADSP-BF5xx
*
* Modified:
- * Copyright 2004-2006 Analog Devices Inc.
+ * Copyright 2004-2007 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -63,6 +63,7 @@ struct l1_sram_piece {
void *paddr;
int size;
int flag;
+ pid_t pid;
};
static struct l1_sram_piece l1_ssram[CONFIG_L1_MAX_PIECE];
@@ -80,13 +81,13 @@ static struct l1_sram_piece l1_inst_sram[CONFIG_L1_MAX_PIECE];
#endif
/* L1 Scratchpad SRAM initialization function */
-void l1sram_init(void)
+void __init l1sram_init(void)
{
printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
L1_SCRATCH_LENGTH >> 10);
memset(&l1_ssram, 0x00, sizeof(l1_ssram));
- l1_ssram[0].paddr = (void*)L1_SCRATCH_START;
+ l1_ssram[0].paddr = (void *)L1_SCRATCH_START;
l1_ssram[0].size = L1_SCRATCH_LENGTH;
l1_ssram[0].flag = SRAM_SLT_FREE;
@@ -94,42 +95,43 @@ void l1sram_init(void)
spin_lock_init(&l1sram_lock);
}
-void l1_data_sram_init(void)
+void __init l1_data_sram_init(void)
{
#if L1_DATA_A_LENGTH != 0
- printk(KERN_INFO "Blackfin DATA_A SRAM: %d KB\n",
- L1_DATA_A_LENGTH >> 10);
-
memset(&l1_data_A_sram, 0x00, sizeof(l1_data_A_sram));
- l1_data_A_sram[0].paddr = (void*)L1_DATA_A_START +
- (_ebss_l1 - _sdata_l1);
+ l1_data_A_sram[0].paddr = (void *)L1_DATA_A_START +
+ (_ebss_l1 - _sdata_l1);
l1_data_A_sram[0].size = L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
l1_data_A_sram[0].flag = SRAM_SLT_FREE;
+
+ printk(KERN_INFO "Blackfin Data A SRAM: %d KB (%d KB free)\n",
+ L1_DATA_A_LENGTH >> 10, l1_data_A_sram[0].size >> 10);
#endif
#if L1_DATA_B_LENGTH != 0
- printk(KERN_INFO "Blackfin DATA_B SRAM: %d KB\n",
- L1_DATA_B_LENGTH >> 10);
-
memset(&l1_data_B_sram, 0x00, sizeof(l1_data_B_sram));
- l1_data_B_sram[0].paddr = (void*)L1_DATA_B_START;
- l1_data_B_sram[0].size = L1_DATA_B_LENGTH;
+ l1_data_B_sram[0].paddr = (void *)L1_DATA_B_START +
+ (_ebss_b_l1 - _sdata_b_l1);
+ l1_data_B_sram[0].size = L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
l1_data_B_sram[0].flag = SRAM_SLT_FREE;
+
+ printk(KERN_INFO "Blackfin Data B SRAM: %d KB (%d KB free)\n",
+ L1_DATA_B_LENGTH >> 10, l1_data_B_sram[0].size >> 10);
#endif
/* mutex initialize */
spin_lock_init(&l1_data_sram_lock);
}
-void l1_inst_sram_init(void)
+void __init l1_inst_sram_init(void)
{
#if L1_CODE_LENGTH != 0
- printk(KERN_INFO "Blackfin Instruction SRAM: %d KB\n",
- L1_CODE_LENGTH >> 10);
-
memset(&l1_inst_sram, 0x00, sizeof(l1_inst_sram));
- l1_inst_sram[0].paddr = (void*)L1_CODE_START + (_etext_l1 - _stext_l1);
+ l1_inst_sram[0].paddr = (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
l1_inst_sram[0].size = L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
l1_inst_sram[0].flag = SRAM_SLT_FREE;
+
+ printk(KERN_INFO "Blackfin Instruction SRAM: %d KB (%d KB free)\n",
+ L1_CODE_LENGTH >> 10, l1_inst_sram[0].size >> 10);
#endif
/* mutex initialize */
@@ -149,12 +151,13 @@ static void *_l1_sram_alloc(size_t size, struct l1_sram_piece *pfree, int count)
size = (size + 3) & ~3;
/* not use the good method to match the best slot !!! */
- /* search an available memeory slot */
+ /* search an available memory slot */
for (i = 0; i < count; i++) {
if ((pfree[i].flag == SRAM_SLT_FREE)
&& (pfree[i].size >= size)) {
addr = pfree[i].paddr;
pfree[i].flag = SRAM_SLT_ALLOCATED;
+ pfree[i].pid = current->pid;
index = i;
break;
}
@@ -162,10 +165,11 @@ static void *_l1_sram_alloc(size_t size, struct l1_sram_piece *pfree, int count)
if (i >= count)
return NULL;
- /* updated the NULL memeory slot !!! */
+ /* updated the NULL memory slot !!! */
if (pfree[i].size > size) {
for (i = 0; i < count; i++) {
if (pfree[i].flag == SRAM_SLT_NULL) {
+ pfree[i].pid = 0;
pfree[i].flag = SRAM_SLT_FREE;
pfree[i].paddr = addr + size;
pfree[i].size = pfree[index].size - size;
@@ -186,7 +190,7 @@ static void *_l1_sram_alloc_max(struct l1_sram_piece *pfree, int count,
int i, index = -1;
void *addr = NULL;
- /* search an available memeory slot */
+ /* search an available memory slot */
for (i = 0; i < count; i++) {
if (pfree[i].flag == SRAM_SLT_FREE && pfree[i].size > best) {
addr = pfree[i].paddr;
@@ -198,13 +202,15 @@ static void *_l1_sram_alloc_max(struct l1_sram_piece *pfree, int count,
return NULL;
*psize = best;
+ pfree[index].pid = current->pid;
pfree[index].flag = SRAM_SLT_ALLOCATED;
return addr;
}
/* L1 memory free function */
static int _l1_sram_free(const void *addr,
- struct l1_sram_piece *pfree, int count)
+ struct l1_sram_piece *pfree,
+ int count)
{
int i, index = 0;
@@ -222,12 +228,14 @@ static int _l1_sram_free(const void *addr,
if (i >= count)
return -1;
+ pfree[index].pid = 0;
pfree[index].flag = SRAM_SLT_FREE;
/* link the next address slot */
for (i = 0; i < count; i++) {
if (((pfree[index].paddr + pfree[index].size) == pfree[i].paddr)
&& (pfree[i].flag == SRAM_SLT_FREE)) {
+ pfree[i].pid = 0;
pfree[i].flag = SRAM_SLT_NULL;
pfree[index].size += pfree[i].size;
pfree[index].flag = SRAM_SLT_FREE;
@@ -538,3 +546,64 @@ void *sram_alloc_with_lsl(size_t size, unsigned long flags)
return addr;
}
EXPORT_SYMBOL(sram_alloc_with_lsl);
+
+#ifdef CONFIG_PROC_FS
+/* Once we get a real allocator, we'll throw all of this away.
+ * Until then, we need some sort of visibility into the L1 alloc.
+ */
+static void _l1sram_proc_read(char *buf, int *len, const char *desc,
+ struct l1_sram_piece *pfree, const int array_size)
+{
+ int i;
+
+ *len += sprintf(&buf[*len], "--- L1 %-14s Size PID State\n", desc);
+ for (i = 0; i < array_size; ++i) {
+ const char *alloc_type;
+ switch (pfree[i].flag) {
+ case SRAM_SLT_NULL: alloc_type = "NULL"; break;
+ case SRAM_SLT_FREE: alloc_type = "FREE"; break;
+ case SRAM_SLT_ALLOCATED: alloc_type = "ALLOCATED"; break;
+ default: alloc_type = "????"; break;
+ }
+ *len += sprintf(&buf[*len], "%p-%p %8i %4i %s\n",
+ pfree[i].paddr, pfree[i].paddr + pfree[i].size,
+ pfree[i].size, pfree[i].pid, alloc_type);
+ }
+}
+static int l1sram_proc_read(char *buf, char **start, off_t offset, int count,
+ int *eof, void *data)
+{
+ int len = 0;
+
+ _l1sram_proc_read(buf, &len, "Scratchpad",
+ l1_ssram, ARRAY_SIZE(l1_ssram));
+#if L1_DATA_A_LENGTH != 0
+ _l1sram_proc_read(buf, &len, "Data A",
+ l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
+#endif
+#if L1_DATA_B_LENGTH != 0
+ _l1sram_proc_read(buf, &len, "Data B",
+ l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
+#endif
+#if L1_CODE_LENGTH != 0
+ _l1sram_proc_read(buf, &len, "Instruction",
+ l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
+#endif
+
+ return len;
+}
+
+static int __init l1sram_proc_init(void)
+{
+ struct proc_dir_entry *ptr;
+ ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL);
+ if (!ptr) {
+ printk(KERN_WARNING "unable to create /proc/sram\n");
+ return -1;
+ }
+ ptr->owner = THIS_MODULE;
+ ptr->read_proc = l1sram_proc_read;
+ return 0;
+}
+late_initcall(l1sram_proc_init);
+#endif
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c
index d6cf1059560..68459cc052a 100644
--- a/arch/blackfin/mm/init.c
+++ b/arch/blackfin/mm/init.c
@@ -7,7 +7,7 @@
* Description:
*
* Modified:
- * Copyright 2004-2006 Analog Devices Inc.
+ * Copyright 2004-2007 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@@ -29,8 +29,8 @@
#include <linux/swap.h>
#include <linux/bootmem.h>
+#include <linux/uaccess.h>
#include <asm/bfin-global.h>
-#include <asm/uaccess.h>
#include <asm/l1layout.h>
#include "blackfin_sram.h"
@@ -53,7 +53,7 @@ static unsigned long empty_bad_page;
unsigned long empty_zero_page;
-void show_mem(void)
+void __init show_mem(void)
{
unsigned long i;
int free = 0, total = 0, reserved = 0, shared = 0;
@@ -86,7 +86,7 @@ void show_mem(void)
* The parameters are pointers to where to stick the starting and ending
* addresses of available kernel virtual memory.
*/
-void paging_init(void)
+void __init paging_init(void)
{
/*
* make sure start_mem is page aligned, otherwise bootmem and
@@ -125,7 +125,7 @@ void paging_init(void)
}
}
-void mem_init(void)
+void __init mem_init(void)
{
unsigned int codek = 0, datak = 0, initk = 0;
unsigned long tmp;
@@ -168,42 +168,31 @@ void mem_init(void)
}
}
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
- int pages = 0;
- for (; start < end; start += PAGE_SIZE) {
- ClearPageReserved(virt_to_page(start));
- init_page_count(virt_to_page(start));
- free_page(start);
- totalram_pages++;
- pages++;
- }
- printk(KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages);
-}
-#endif
-
-void free_initmem(void)
+static __init void free_init_pages(const char *what, unsigned long begin, unsigned long end)
{
-#ifdef CONFIG_RAMKERNEL
unsigned long addr;
-/*
- * the following code should be cool even if these sections
- * are not page aligned.
- */
- addr = PAGE_ALIGN((unsigned long)(__init_begin));
/* next to check that the page we free is not a partial page */
- for (; addr + PAGE_SIZE < (unsigned long)(__init_end);
- addr += PAGE_SIZE) {
+ for (addr = begin; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
ClearPageReserved(virt_to_page(addr));
init_page_count(virt_to_page(addr));
free_page(addr);
totalram_pages++;
}
- printk(KERN_NOTICE
- "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
- (addr - PAGE_ALIGN((long)__init_begin)) >> 10,
- (int)(PAGE_ALIGN((unsigned long)(__init_begin))),
- (int)(addr - PAGE_SIZE));
+ printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init free_initrd_mem(unsigned long start, unsigned long end)
+{
+ free_init_pages("initrd memory", start, end);
+}
+#endif
+
+void __init free_initmem(void)
+{
+#ifdef CONFIG_RAMKERNEL
+ free_init_pages("unused kernel memory",
+ (unsigned long)(&__init_begin),
+ (unsigned long)(&__init_end));
#endif
}
diff --git a/arch/blackfin/oprofile/common.c b/arch/blackfin/oprofile/common.c
index 009a1700c85..cb8b8d5af34 100644
--- a/arch/blackfin/oprofile/common.c
+++ b/arch/blackfin/oprofile/common.c
@@ -33,12 +33,12 @@
#include <linux/smp.h>
#include <linux/errno.h>
#include <linux/mutex.h>
+#include <linux/ptrace.h>
+#include <linux/irq.h>
+#include <linux/io.h>
-#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/io.h>
#include "op_blackfin.h"
diff --git a/arch/blackfin/oprofile/op_model_bf533.c b/arch/blackfin/oprofile/op_model_bf533.c
index b7a20a006b4..872dffe3362 100644
--- a/arch/blackfin/oprofile/op_model_bf533.c
+++ b/arch/blackfin/oprofile/op_model_bf533.c
@@ -32,12 +32,12 @@
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
-#include <asm/ptrace.h>
+#include <linux/ptrace.h>
+#include <linux/irq.h>
+#include <linux/io.h>
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/io.h>
#include "op_blackfin.h"
diff --git a/arch/blackfin/oprofile/timer_int.c b/arch/blackfin/oprofile/timer_int.c
index 8fba16c846c..6c6f8606af4 100644
--- a/arch/blackfin/oprofile/timer_int.c
+++ b/arch/blackfin/oprofile/timer_int.c
@@ -31,8 +31,7 @@
#include <linux/smp.h>
#include <linux/irq.h>
#include <linux/oprofile.h>
-
-#include <asm/ptrace.h>
+#include <linux/ptrace.h>
static void enable_sys_timer0()
{
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
index 11ba75a0522..de7688cfd57 100644
--- a/arch/h8300/kernel/sys_h8300.c
+++ b/arch/h8300/kernel/sys_h8300.c
@@ -288,9 +288,9 @@ asmlinkage void syscall_print(void *dummy,...)
int kernel_execve(const char *filename, char *const argv[], char *const envp[])
{
register long res __asm__("er0");
+ register char *const *_c __asm__("er3") = envp;
+ register char *const *_b __asm__("er2") = argv;
register const char * _a __asm__("er1") = filename;
- register void *_b __asm__("er2") = argv;
- register void *_c __asm__("er3") = envp;
__asm__ __volatile__ ("mov.l %1,er0\n\t"
"trapa #0\n\t"
: "=r" (res)
diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c
index 300e3279ca5..f97183011c2 100644
--- a/arch/h8300/kernel/traps.c
+++ b/arch/h8300/kernel/traps.c
@@ -136,7 +136,7 @@ void show_stack(struct task_struct *task, unsigned long *esp)
printk("\nCall Trace:");
i = 0;
stack = esp;
- while (((unsigned long)stack & (THREAD_SIZE - 1)) == 0) {
+ while (((unsigned long)stack & (THREAD_SIZE - 1)) != 0) {
addr = *stack++;
/*
* If the address is either in the text segment of the
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 8770a5d0b14..b1b2b30b1b8 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -441,8 +441,8 @@ config X86_REBOOTFIXUPS
this config is intended, is when reboot ends with a stalled/hung
system.
- Currently, the only fixup is for the Geode GX1/CS5530A/TROM2.1.
- combination.
+ Currently, the only fixup is for the Geode machines using
+ CS5530A and CS5536 chipsets.
Say Y if you want to enable the fixup. Currently, it's safe to
enable this option even if you don't need it.
@@ -541,7 +541,7 @@ config HIGHMEM4G
config HIGHMEM64G
bool "64GB"
- depends on X86_CMPXCHG64
+ depends on !M386 && !M486
help
Select this if you have a 32-bit processor and more than 4
gigabytes of physical RAM.
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index d7f6fb0b30f..9cbe76c3aa3 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -299,7 +299,7 @@ config X86_POPAD_OK
config X86_CMPXCHG64
bool
- depends on !M386 && !M486
+ depends on X86_PAE
default y
config X86_ALIGNMENT_16
@@ -344,8 +344,8 @@ config X86_CMOV
depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
default y
-config X86_MINIMUM_CPU_MODEL
+config X86_MINIMUM_CPU_FAMILY
int
- default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP
- default "0"
+ default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK
+ default "3"
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index bfbc32098a4..08678a0a3d1 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -25,27 +25,56 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
#RAMDISK := -DRAMDISK=512
-targets := vmlinux.bin bootsect bootsect.o \
- setup setup.o zImage bzImage
+targets := vmlinux.bin setup.bin setup.elf zImage bzImage
subdir- := compressed
+setup-y += a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
+setup-y += printf.o string.o tty.o video.o version.o voyager.o
+
+# The link order of the video-*.o modules can matter. In particular,
+# video-vga.o *must* be listed first, followed by video-vesa.o.
+# Hardware-specific drivers should follow in the order they should be
+# probed, and video-bios.o should typically be last.
+setup-y += video-vga.o
+setup-y += video-vesa.o
+setup-y += video-bios.o
+
hostprogs-y := tools/build
HOSTCFLAGS_build.o := $(LINUXINCLUDE)
# ---------------------------------------------------------------------------
+# How to compile the 16-bit code. Note we always compile for -march=i386,
+# that way we can complain to the user if the CPU is insufficient.
+cflags-i386 :=
+cflags-x86_64 := -m32
+CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+ $(cflags-$(ARCH)) \
+ -Wall -Wstrict-prototypes \
+ -march=i386 -mregparm=3 \
+ -include $(srctree)/$(src)/code16gcc.h \
+ -fno-strict-aliasing -fomit-frame-pointer \
+ $(call cc-option, -ffreestanding) \
+ $(call cc-option, -fno-toplevel-reorder,\
+ $(call cc-option, -fno-unit-at-a-time)) \
+ $(call cc-option, -fno-stack-protector) \
+ $(call cc-option, -mpreferred-stack-boundary=2)
+AFLAGS := $(CFLAGS) -D__ASSEMBLY__
+
$(obj)/zImage: IMAGE_OFFSET := 0x1000
$(obj)/zImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK)
$(obj)/bzImage: IMAGE_OFFSET := 0x100000
+$(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__
$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
$(obj)/bzImage: BUILDFLAGS := -b
quiet_cmd_image = BUILD $@
-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
+cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \
$(obj)/vmlinux.bin $(ROOT_DEV) > $@
-$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
+$(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \
$(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
@@ -53,12 +82,17 @@ $(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
-LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext
+SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
-$(obj)/setup $(obj)/bootsect: %: %.o FORCE
+LDFLAGS_setup.elf := -T
+$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
$(call if_changed,ld)
+OBJCOPYFLAGS_setup.bin := -O binary
+
+$(obj)/setup.bin: $(obj)/setup.elf FORCE
+ $(call if_changed,objcopy)
+
$(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
diff --git a/arch/i386/boot/a20.c b/arch/i386/boot/a20.c
new file mode 100644
index 00000000000..31348d054fc
--- /dev/null
+++ b/arch/i386/boot/a20.c
@@ -0,0 +1,161 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/a20.c
+ *
+ * Enable A20 gate (return -1 on failure)
+ */
+
+#include "boot.h"
+
+#define MAX_8042_LOOPS 100000
+
+static int empty_8042(void)
+{
+ u8 status;
+ int loops = MAX_8042_LOOPS;
+
+ while (loops--) {
+ io_delay();
+
+ status = inb(0x64);
+ if (status & 1) {
+ /* Read and discard input data */
+ io_delay();
+ (void)inb(0x60);
+ } else if (!(status & 2)) {
+ /* Buffers empty, finished! */
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/* Returns nonzero if the A20 line is enabled. The memory address
+ used as a test is the int $0x80 vector, which should be safe. */
+
+#define A20_TEST_ADDR (4*0x80)
+#define A20_TEST_SHORT 32
+#define A20_TEST_LONG 2097152 /* 2^21 */
+
+static int a20_test(int loops)
+{
+ int ok = 0;
+ int saved, ctr;
+
+ set_fs(0x0000);
+ set_gs(0xffff);
+
+ saved = ctr = rdfs32(A20_TEST_ADDR);
+
+ while (loops--) {
+ wrfs32(++ctr, A20_TEST_ADDR);
+ io_delay(); /* Serialize and make delay constant */
+ ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr;
+ if (ok)
+ break;
+ }
+
+ wrfs32(saved, A20_TEST_ADDR);
+ return ok;
+}
+
+/* Quick test to see if A20 is already enabled */
+static int a20_test_short(void)
+{
+ return a20_test(A20_TEST_SHORT);
+}
+
+/* Longer test that actually waits for A20 to come on line; this
+ is useful when dealing with the KBC or other slow external circuitry. */
+static int a20_test_long(void)
+{
+ return a20_test(A20_TEST_LONG);
+}
+
+static void enable_a20_bios(void)
+{
+ asm volatile("pushfl; int $0x15; popfl"
+ : : "a" ((u16)0x2401));
+}
+
+static void enable_a20_kbc(void)
+{
+ empty_8042();
+
+ outb(0xd1, 0x64); /* Command write */
+ empty_8042();
+
+ outb(0xdf, 0x60); /* A20 on */
+ empty_8042();
+}
+
+static void enable_a20_fast(void)
+{
+ u8 port_a;
+
+ port_a = inb(0x92); /* Configuration port A */
+ port_a |= 0x02; /* Enable A20 */
+ port_a &= ~0x01; /* Do not reset machine */
+ outb(port_a, 0x92);
+}
+
+/*
+ * Actual routine to enable A20; return 0 on ok, -1 on failure
+ */
+
+#define A20_ENABLE_LOOPS 255 /* Number of times to try */
+
+int enable_a20(void)
+{
+ int loops = A20_ENABLE_LOOPS;
+
+#if defined(CONFIG_X86_ELAN)
+ /* Elan croaks if we try to touch the KBC */
+ enable_a20_fast();
+ while (!a20_test_long())
+ ;
+ return 0;
+#elif defined(CONFIG_X86_VOYAGER)
+ /* On Voyager, a20_test() is unsafe? */
+ enable_a20_kbc();
+ return 0;
+#else
+ while (loops--) {
+ /* First, check to see if A20 is already enabled
+ (legacy free, etc.) */
+ if (a20_test_short())
+ return 0;
+
+ /* Next, try the BIOS (INT 0x15, AX=0x2401) */
+ enable_a20_bios();
+ if (a20_test_short())
+ return 0;
+
+ /* Try enabling A20 through the keyboard controller */
+ empty_8042();
+ if (a20_test_short())
+ return 0; /* BIOS worked, but with delayed reaction */
+
+ enable_a20_kbc();
+ if (a20_test_long())
+ return 0;
+
+ /* Finally, try enabling the "fast A20 gate" */
+ enable_a20_fast();
+ if (a20_test_long())
+ return 0;
+ }
+
+ return -1;
+#endif
+}
diff --git a/arch/i386/boot/apm.c b/arch/i386/boot/apm.c
new file mode 100644
index 00000000000..a34087c370c
--- /dev/null
+++ b/arch/i386/boot/apm.c
@@ -0,0 +1,97 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * Original APM BIOS checking by Stephen Rothwell, May 1994
+ * (sfr@canb.auug.org.au)
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/apm.c
+ *
+ * Get APM BIOS information
+ */
+
+#include "boot.h"
+
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+
+int query_apm_bios(void)
+{
+ u16 ax, bx, cx, dx, di;
+ u32 ebx, esi;
+ u8 err;
+
+ /* APM BIOS installation check */
+ ax = 0x5300;
+ bx = cx = 0;
+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
+ : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
+ : : "esi", "edi");
+
+ if (err)
+ return -1; /* No APM BIOS */
+
+ if (bx != 0x504d) /* "PM" signature */
+ return -1;
+
+ if (cx & 0x02) /* 32 bits supported? */
+ return -1;
+
+ /* Disconnect first, just in case */
+ ax = 0x5304;
+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
+ : "+a" (ax)
+ : : "ebx", "ecx", "edx", "esi", "edi");
+
+ /* Paranoia */
+ ebx = esi = 0;
+ cx = dx = di = 0;
+
+ /* 32-bit connect */
+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6"
+ : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx),
+ "+S" (esi), "+D" (di), "=m" (err)
+ : "a" (0x5303));
+
+ boot_params.apm_bios_info.cseg = ax;
+ boot_params.apm_bios_info.offset = ebx;
+ boot_params.apm_bios_info.cseg_16 = cx;
+ boot_params.apm_bios_info.dseg = dx;
+ boot_params.apm_bios_info.cseg_len = (u16)esi;
+ boot_params.apm_bios_info.cseg_16_len = esi >> 16;
+ boot_params.apm_bios_info.dseg_len = di;
+
+ if (err)
+ return -1;
+
+ /* Redo the installation check as the 32-bit connect;
+ some BIOSes return different flags this way... */
+
+ ax = 0x5300;
+ bx = cx = 0;
+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0"
+ : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx)
+ : : "esi", "edi");
+
+ if (err || bx != 0x504d) {
+ /* Failure with 32-bit connect, try to disconect and ignore */
+ ax = 0x5304;
+ bx = 0;
+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp"
+ : "+a" (ax), "+b" (bx)
+ : : "ecx", "edx", "esi", "edi");
+ return -1;
+ }
+
+ boot_params.apm_bios_info.version = ax;
+ boot_params.apm_bios_info.flags = cx;
+ return 0;
+}
+
+#endif
diff --git a/arch/i386/boot/bitops.h b/arch/i386/boot/bitops.h
new file mode 100644
index 00000000000..8dcc8dc7db8
--- /dev/null
+++ b/arch/i386/boot/bitops.h
@@ -0,0 +1,45 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/bitops.h
+ *
+ * Very simple bitops for the boot code.
+ */
+
+#ifndef BOOT_BITOPS_H
+#define BOOT_BITOPS_H
+#define _LINUX_BITOPS_H /* Inhibit inclusion of <linux/bitops.h> */
+
+static inline int constant_test_bit(int nr, const void *addr)
+{
+ const u32 *p = (const u32 *)addr;
+ return ((1UL << (nr & 31)) & (p[nr >> 5])) != 0;
+}
+static inline int variable_test_bit(int nr, const void *addr)
+{
+ u8 v;
+ const u32 *p = (const u32 *)addr;
+
+ asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr));
+ return v;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
+static inline void set_bit(int nr, void *addr)
+{
+ asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr));
+}
+
+#endif /* BOOT_BITOPS_H */
diff --git a/arch/i386/boot/boot.h b/arch/i386/boot/boot.h
new file mode 100644
index 00000000000..0329c4fe4f8
--- /dev/null
+++ b/arch/i386/boot/boot.h
@@ -0,0 +1,296 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/boot.h
+ *
+ * Header file for the real-mode kernel code
+ */
+
+#ifndef BOOT_BOOT_H
+#define BOOT_BOOT_H
+
+#ifndef __ASSEMBLY__
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/edd.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+/* Useful macros */
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+
+extern struct setup_header hdr;
+extern struct boot_params boot_params;
+
+/* Basic port I/O */
+static inline void outb(u8 v, u16 port)
+{
+ asm volatile("outb %0,%1" : : "a" (v), "dN" (port));
+}
+static inline u8 inb(u16 port)
+{
+ u8 v;
+ asm volatile("inb %1,%0" : "=a" (v) : "dN" (port));
+ return v;
+}
+
+static inline void outw(u16 v, u16 port)
+{
+ asm volatile("outw %0,%1" : : "a" (v), "dN" (port));
+}
+static inline u16 inw(u16 port)
+{
+ u16 v;
+ asm volatile("inw %1,%0" : "=a" (v) : "dN" (port));
+ return v;
+}
+
+static inline void outl(u32 v, u16 port)
+{
+ asm volatile("outl %0,%1" : : "a" (v), "dn" (port));
+}
+static inline u32 inl(u32 port)
+{
+ u32 v;
+ asm volatile("inl %1,%0" : "=a" (v) : "dN" (port));
+ return v;
+}
+
+static inline void io_delay(void)
+{
+ const u16 DELAY_PORT = 0x80;
+ asm volatile("outb %%al,%0" : : "dN" (DELAY_PORT));
+}
+
+/* These functions are used to reference data in other segments. */
+
+static inline u16 ds(void)
+{
+ u16 seg;
+ asm("movw %%ds,%0" : "=rm" (seg));
+ return seg;
+}
+
+static inline void set_fs(u16 seg)
+{
+ asm volatile("movw %0,%%fs" : : "rm" (seg));
+}
+static inline u16 fs(void)
+{
+ u16 seg;
+ asm("movw %%fs,%0" : "=rm" (seg));
+ return seg;
+}
+
+static inline void set_gs(u16 seg)
+{
+ asm volatile("movw %0,%%gs" : : "rm" (seg));
+}
+static inline u16 gs(void)
+{
+ u16 seg;
+ asm("movw %%gs,%0" : "=rm" (seg));
+ return seg;
+}
+
+typedef unsigned int addr_t;
+
+static inline u8 rdfs8(addr_t addr)
+{
+ u8 v;
+ asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
+ return v;
+}
+static inline u16 rdfs16(addr_t addr)
+{
+ u16 v;
+ asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+ return v;
+}
+static inline u32 rdfs32(addr_t addr)
+{
+ u32 v;
+ asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+ return v;
+}
+
+static inline void wrfs8(u8 v, addr_t addr)
+{
+ asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v));
+}
+static inline void wrfs16(u16 v, addr_t addr)
+{
+ asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v));
+}
+static inline void wrfs32(u32 v, addr_t addr)
+{
+ asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v));
+}
+
+static inline u8 rdgs8(addr_t addr)
+{
+ u8 v;
+ asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
+ return v;
+}
+static inline u16 rdgs16(addr_t addr)
+{
+ u16 v;
+ asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+ return v;
+}
+static inline u32 rdgs32(addr_t addr)
+{
+ u32 v;
+ asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+ return v;
+}
+
+static inline void wrgs8(u8 v, addr_t addr)
+{
+ asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v));
+}
+static inline void wrgs16(u16 v, addr_t addr)
+{
+ asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v));
+}
+static inline void wrgs32(u32 v, addr_t addr)
+{
+ asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v));
+}
+
+/* Note: these only return true/false, not a signed return value! */
+static inline int memcmp(const void *s1, const void *s2, size_t len)
+{
+ u8 diff;
+ asm("repe; cmpsb; setnz %0"
+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+ return diff;
+}
+
+static inline int memcmp_fs(const void *s1, addr_t s2, size_t len)
+{
+ u8 diff;
+ asm("fs; repe; cmpsb; setnz %0"
+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+ return diff;
+}
+static inline int memcmp_gs(const void *s1, addr_t s2, size_t len)
+{
+ u8 diff;
+ asm("gs; repe; cmpsb; setnz %0"
+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len));
+ return diff;
+}
+
+static inline int isdigit(int ch)
+{
+ return (ch >= '0') && (ch <= '9');
+}
+
+/* Heap -- available for dynamic lists. */
+#define STACK_SIZE 512 /* Minimum number of bytes for stack */
+
+extern char _end[];
+extern char *HEAP;
+extern char *heap_end;
+#define RESET_HEAP() ((void *)( HEAP = _end ))
+static inline char *__get_heap(size_t s, size_t a, size_t n)
+{
+ char *tmp;
+
+ HEAP = (char *)(((size_t)HEAP+(a-1)) & ~(a-1));
+ tmp = HEAP;
+ HEAP += s*n;
+ return tmp;
+}
+#define GET_HEAP(type, n) \
+ ((type *)__get_heap(sizeof(type),__alignof__(type),(n)))
+
+static inline int heap_free(void)
+{
+ return heap_end-HEAP;
+}
+
+/* copy.S */
+
+void copy_to_fs(addr_t dst, void *src, size_t len);
+void *copy_from_fs(void *dst, addr_t src, size_t len);
+void copy_to_gs(addr_t dst, void *src, size_t len);
+void *copy_from_gs(void *dst, addr_t src, size_t len);
+void *memcpy(void *dst, void *src, size_t len);
+void *memset(void *dst, int c, size_t len);
+
+#define memcpy(d,s,l) __builtin_memcpy(d,s,l)
+#define memset(d,c,l) __builtin_memset(d,c,l)
+
+/* a20.c */
+int enable_a20(void);
+
+/* apm.c */
+int query_apm_bios(void);
+
+/* cmdline.c */
+int cmdline_find_option(const char *option, char *buffer, int bufsize);
+
+/* cpu.c, cpucheck.c */
+int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
+int validate_cpu(void);
+
+/* edd.c */
+void query_edd(void);
+
+/* header.S */
+void __attribute__((noreturn)) die(void);
+
+/* mca.c */
+int query_mca(void);
+
+/* memory.c */
+int detect_memory(void);
+
+/* pm.c */
+void __attribute__((noreturn)) go_to_protected_mode(void);
+
+/* pmjump.S */
+void __attribute__((noreturn))
+ protected_mode_jump(u32 entrypoint, u32 bootparams);
+
+/* printf.c */
+int sprintf(char *buf, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list args);
+int printf(const char *fmt, ...);
+
+/* string.c */
+int strcmp(const char *str1, const char *str2);
+size_t strnlen(const char *s, size_t maxlen);
+unsigned int atou(const char *s);
+
+/* tty.c */
+void puts(const char *);
+void putchar(int);
+int getchar(void);
+void kbd_flush(void);
+int getchar_timeout(void);
+
+/* video.c */
+void set_video(void);
+
+/* video-vesa.c */
+void vesa_store_edid(void);
+
+/* voyager.c */
+int query_voyager(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* BOOT_BOOT_H */
diff --git a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
deleted file mode 100644
index 011b7a4993d..00000000000
--- a/arch/i386/boot/bootsect.S
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds
- *
- * modified by Drew Eckhardt
- * modified by Bruce Evans (bde)
- * modified by Chris Noe (May 1999) (as86 -> gas)
- * gutted by H. Peter Anvin (Jan 2003)
- *
- * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
- * addresses must be multiplied by 16 to obtain their respective linear
- * addresses. To avoid confusion, linear addresses are written using leading
- * hex while segment addresses are written as segment:offset.
- *
- */
-
-#include <asm/boot.h>
-
-SETUPSECTS = 4 /* default nr of setup-sectors */
-BOOTSEG = 0x07C0 /* original address of boot-sector */
-INITSEG = DEF_INITSEG /* we move boot here - out of the way */
-SETUPSEG = DEF_SETUPSEG /* setup starts here */
-SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */
-SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */
- /* to be loaded */
-ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */
-SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
-
-#ifndef SVGA_MODE
-#define SVGA_MODE ASK_VGA
-#endif
-
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif
-
-#ifndef ROOT_RDONLY
-#define ROOT_RDONLY 1
-#endif
-
-.code16
-.text
-
-.global _start
-_start:
-
- # Normalize the start address
- jmpl $BOOTSEG, $start2
-
-start2:
- movw %cs, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- movw $0x7c00, %sp
- sti
- cld
-
- movw $bugger_off_msg, %si
-
-msg_loop:
- lodsb
- andb %al, %al
- jz die
- movb $0xe, %ah
- movw $7, %bx
- int $0x10
- jmp msg_loop
-
-die:
- # Allow the user to press a key, then reboot
- xorw %ax, %ax
- int $0x16
- int $0x19
-
- # int 0x19 should never return. In case it does anyway,
- # invoke the BIOS reset code...
- ljmp $0xf000,$0xfff0
-
-
-bugger_off_msg:
- .ascii "Direct booting from floppy is no longer supported.\r\n"
- .ascii "Please use a boot loader program instead.\r\n"
- .ascii "\n"
- .ascii "Remove disk and press any key to reboot . . .\r\n"
- .byte 0
-
-
- # Kernel attributes; used by setup
-
- .org 497
-setup_sects: .byte SETUPSECTS
-root_flags: .word ROOT_RDONLY
-syssize: .word SYSSIZE
-swap_dev: .word SWAP_DEV
-ram_size: .word RAMDISK
-vid_mode: .word SVGA_MODE
-root_dev: .word ROOT_DEV
-boot_flag: .word 0xAA55
diff --git a/arch/i386/boot/cmdline.c b/arch/i386/boot/cmdline.c
new file mode 100644
index 00000000000..34bb778c435
--- /dev/null
+++ b/arch/i386/boot/cmdline.c
@@ -0,0 +1,97 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cmdline.c
+ *
+ * Simple command-line parser for early boot.
+ */
+
+#include "boot.h"
+
+static inline int myisspace(u8 c)
+{
+ return c <= ' '; /* Close enough approximation */
+}
+
+/*
+ * Find a non-boolean option, that is, "option=argument". In accordance
+ * with standard Linux practice, if this option is repeated, this returns
+ * the last instance on the command line.
+ *
+ * Returns the length of the argument (regardless of if it was
+ * truncated to fit in the buffer), or -1 on not found.
+ */
+int cmdline_find_option(const char *option, char *buffer, int bufsize)
+{
+ u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
+ addr_t cptr;
+ char c;
+ int len = -1;
+ const char *opptr = NULL;
+ char *bufptr = buffer;
+ enum {
+ st_wordstart, /* Start of word/after whitespace */
+ st_wordcmp, /* Comparing this word */
+ st_wordskip, /* Miscompare, skip */
+ st_bufcpy /* Copying this to buffer */
+ } state = st_wordstart;
+
+ if (!cmdline_ptr || cmdline_ptr >= 0x100000)
+ return -1; /* No command line, or inaccessible */
+
+ cptr = cmdline_ptr & 0xf;
+ set_fs(cmdline_ptr >> 4);
+
+ while (cptr < 0x10000 && (c = rdfs8(cptr++))) {
+ switch (state) {
+ case st_wordstart:
+ if (myisspace(c))
+ break;
+
+ /* else */
+ state = st_wordcmp;
+ opptr = option;
+ /* fall through */
+
+ case st_wordcmp:
+ if (c == '=' && !*opptr) {
+ len = 0;
+ bufptr = buffer;
+ state = st_bufcpy;
+ } else if (myisspace(c)) {
+ state = st_wordstart;
+ } else if (c != *opptr++) {
+ state = st_wordskip;
+ }
+ break;
+
+ case st_wordskip:
+ if (myisspace(c))
+ state = st_wordstart;
+ break;
+
+ case st_bufcpy:
+ if (myisspace(c)) {
+ state = st_wordstart;
+ } else {
+ if (len < bufsize-1)
+ *bufptr++ = c;
+ len++;
+ }
+ break;
+ }
+ }
+
+ if (bufsize)
+ *bufptr = '\0';
+
+ return len;
+}
diff --git a/arch/i386/boot/code16gcc.h b/arch/i386/boot/code16gcc.h
new file mode 100644
index 00000000000..3bd848093b9
--- /dev/null
+++ b/arch/i386/boot/code16gcc.h
@@ -0,0 +1,15 @@
+/*
+ * code16gcc.h
+ *
+ * This file is -include'd when compiling 16-bit C code.
+ * Note: this asm() needs to be emitted before gcc omits any code.
+ * Depending on gcc version, this requires -fno-unit-at-a-time or
+ * -fno-toplevel-reorder.
+ *
+ * Hopefully gcc will eventually have a real -m16 option so we can
+ * drop this hack long term.
+ */
+
+#ifndef __ASSEMBLY__
+asm(".code16gcc");
+#endif
diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
index a661217f33e..189fa1dbefc 100644
--- a/arch/i386/boot/compressed/Makefile
+++ b/arch/i386/boot/compressed/Makefile
@@ -9,9 +9,14 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o \
EXTRA_AFLAGS := -traditional
LDFLAGS_vmlinux := -T
-CFLAGS_misc.o += -fPIC
hostprogs-y := relocs
+CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
+ -fno-strict-aliasing -fPIC \
+ $(call cc-option,-ffreestanding) \
+ $(call cc-option,-fno-stack-protector)
+LDFLAGS := -m elf_i386
+
$(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index 3517a32aaf4..f35ea223752 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -45,10 +45,10 @@ startup_32:
* at and where we were actually loaded at. This can only be done
* with a short local call on x86. Nothing else will tell us what
* address we are running at. The reserved chunk of the real-mode
- * data at 0x34-0x3f are used as the stack for this calculation.
- * Only 4 bytes are needed.
+ * data at 0x1e4 (defined as a scratch field) are used as the stack
+ * for this calculation. Only 4 bytes are needed.
*/
- leal 0x40(%esi), %esp
+ leal (0x1e4+4)(%esi), %esp
call 1f
1: popl %ebp
subl $1b, %ebp
diff --git a/arch/i386/boot/copy.S b/arch/i386/boot/copy.S
new file mode 100644
index 00000000000..ef127e56a3c
--- /dev/null
+++ b/arch/i386/boot/copy.S
@@ -0,0 +1,101 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/copy.S
+ *
+ * Memory copy routines
+ */
+
+ .code16gcc
+ .text
+
+ .globl memcpy
+ .type memcpy, @function
+memcpy:
+ pushw %si
+ pushw %di
+ movw %ax, %di
+ movw %dx, %si
+ pushw %cx
+ shrw $2, %cx
+ rep; movsl
+ popw %cx
+ andw $3, %cx
+ rep; movsb
+ popw %di
+ popw %si
+ ret
+ .size memcpy, .-memcpy
+
+ .globl memset
+ .type memset, @function
+memset:
+ pushw %di
+ movw %ax, %di
+ movzbl %dl, %eax
+ imull $0x01010101,%eax
+ pushw %cx
+ shrw $2, %cx
+ rep; stosl
+ popw %cx
+ andw $3, %cx
+ rep; stosb
+ popw %di
+ ret
+ .size memset, .-memset
+
+ .globl copy_from_fs
+ .type copy_from_fs, @function
+copy_from_fs:
+ pushw %ds
+ pushw %fs
+ popw %ds
+ call memcpy
+ popw %ds
+ ret
+ .size copy_from_fs, .-copy_from_fs
+
+ .globl copy_to_fs
+ .type copy_to_fs, @function
+copy_to_fs:
+ pushw %es
+ pushw %fs
+ popw %es
+ call memcpy
+ popw %es
+ ret
+ .size copy_to_fs, .-copy_to_fs
+
+#if 0 /* Not currently used, but can be enabled as needed */
+
+ .globl copy_from_gs
+ .type copy_from_gs, @function
+copy_from_gs:
+ pushw %ds
+ pushw %gs
+ popw %ds
+ call memcpy
+ popw %ds
+ ret
+ .size copy_from_gs, .-copy_from_gs
+ .globl copy_to_gs
+
+ .type copy_to_gs, @function
+copy_to_gs:
+ pushw %es
+ pushw %gs
+ popw %es
+ call memcpy
+ popw %es
+ ret
+ .size copy_to_gs, .-copy_to_gs
+
+#endif
diff --git a/arch/i386/boot/cpu.c b/arch/i386/boot/cpu.c
new file mode 100644
index 00000000000..2a5c32da585
--- /dev/null
+++ b/arch/i386/boot/cpu.c
@@ -0,0 +1,69 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cpu.c
+ *
+ * Check for obligatory CPU features and abort if the features are not
+ * present.
+ */
+
+#include "boot.h"
+#include "bitops.h"
+#include <asm/cpufeature.h>
+
+static char *cpu_name(int level)
+{
+ static char buf[6];
+
+ if (level == 64) {
+ return "x86-64";
+ } else {
+ sprintf(buf, "i%d86", level);
+ return buf;
+ }
+}
+
+int validate_cpu(void)
+{
+ u32 *err_flags;
+ int cpu_level, req_level;
+
+ check_cpu(&cpu_level, &req_level, &err_flags);
+
+ if (cpu_level < req_level) {
+ printf("This kernel requires an %s CPU, ",
+ cpu_name(req_level));
+ printf("but only detected an %s CPU.\n",
+ cpu_name(cpu_level));
+ return -1;
+ }
+
+ if (err_flags) {
+ int i, j;
+ puts("This kernel requires the following features "
+ "not present on the CPU:\n");
+
+ for (i = 0; i < NCAPINTS; i++) {
+ u32 e = err_flags[i];
+
+ for (j = 0; j < 32; j++) {
+ if (e & 1)
+ printf("%d:%d ", i, j);
+
+ e >>= 1;
+ }
+ }
+ putchar('\n');
+ return -1;
+ } else {
+ return 0;
+ }
+}
diff --git a/arch/i386/boot/cpucheck.c b/arch/i386/boot/cpucheck.c
new file mode 100644
index 00000000000..8b0f4473b08
--- /dev/null
+++ b/arch/i386/boot/cpucheck.c
@@ -0,0 +1,267 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/cpucheck.c
+ *
+ * Check for obligatory CPU features and abort if the features are not
+ * present. This code should be compilable as 16-, 32- or 64-bit
+ * code, so be very careful with types and inline assembly.
+ *
+ * This code should not contain any messages; that requires an
+ * additional wrapper.
+ *
+ * As written, this code is not safe for inclusion into the kernel
+ * proper (after FPU initialization, in particular).
+ */
+
+#ifdef _SETUP
+# include "boot.h"
+# include "bitops.h"
+#endif
+#include <linux/types.h>
+#include <asm/cpufeature.h>
+#include <asm/processor-flags.h>
+#include <asm/required-features.h>
+#include <asm/msr-index.h>
+
+struct cpu_features {
+ int level; /* Family, or 64 for x86-64 */
+ int model;
+ u32 flags[NCAPINTS];
+};
+
+static struct cpu_features cpu;
+static u32 cpu_vendor[3];
+static u32 err_flags[NCAPINTS];
+
+#ifdef CONFIG_X86_64
+static const int req_level = 64;
+#elif defined(CONFIG_X86_MINIMUM_CPU_FAMILY)
+static const int req_level = CONFIG_X86_MINIMUM_CPU_FAMILY;
+#else
+static const int req_level = 3;
+#endif
+
+static const u32 req_flags[NCAPINTS] =
+{
+ REQUIRED_MASK0,
+ REQUIRED_MASK1,
+ REQUIRED_MASK2,
+ REQUIRED_MASK3,
+ REQUIRED_MASK4,
+ REQUIRED_MASK5,
+ REQUIRED_MASK6,
+ REQUIRED_MASK7,
+};
+
+#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
+
+static int is_amd(void)
+{
+ return cpu_vendor[0] == A32('A','u','t','h') &&
+ cpu_vendor[1] == A32('e','n','t','i') &&
+ cpu_vendor[2] == A32('c','A','M','D');
+}
+
+static int is_centaur(void)
+{
+ return cpu_vendor[0] == A32('C','e','n','t') &&
+ cpu_vendor[1] == A32('a','u','r','H') &&
+ cpu_vendor[2] == A32('a','u','l','s');
+}
+
+static int is_transmeta(void)
+{
+ return cpu_vendor[0] == A32('G','e','n','u') &&
+ cpu_vendor[1] == A32('i','n','e','T') &&
+ cpu_vendor[2] == A32('M','x','8','6');
+}
+
+static int has_fpu(void)
+{
+ u16 fcw = -1, fsw = -1;
+ u32 cr0;
+
+ asm("movl %%cr0,%0" : "=r" (cr0));
+ if (cr0 & (X86_CR0_EM|X86_CR0_TS)) {
+ cr0 &= ~(X86_CR0_EM|X86_CR0_TS);
+ asm volatile("movl %0,%%cr0" : : "r" (cr0));
+ }
+
+ asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw));
+
+ return fsw == 0 && (fcw & 0x103f) == 0x003f;
+}
+
+static int has_eflag(u32 mask)
+{
+ u32 f0, f1;
+
+ asm("pushfl ; "
+ "pushfl ; "
+ "popl %0 ; "
+ "movl %0,%1 ; "
+ "xorl %2,%1 ; "
+ "pushl %1 ; "
+ "popfl ; "
+ "pushfl ; "
+ "popl %1 ; "
+ "popfl"
+ : "=r" (f0), "=r" (f1)
+ : "g" (mask));
+
+ return !!((f0^f1) & mask);
+}
+
+static void get_flags(void)
+{
+ u32 max_intel_level, max_amd_level;
+ u32 tfms;
+
+ if (has_fpu())
+ set_bit(X86_FEATURE_FPU, cpu.flags);
+
+ if (has_eflag(X86_EFLAGS_ID)) {
+ asm("cpuid"
+ : "=a" (max_intel_level),
+ "=b" (cpu_vendor[0]),
+ "=d" (cpu_vendor[1]),
+ "=c" (cpu_vendor[2])
+ : "a" (0));
+
+ if (max_intel_level >= 0x00000001 &&
+ max_intel_level <= 0x0000ffff) {
+ asm("cpuid"
+ : "=a" (tfms),
+ "=c" (cpu.flags[4]),
+ "=d" (cpu.flags[0])
+ : "a" (0x00000001)
+ : "ebx");
+ cpu.level = (tfms >> 8) & 15;
+ cpu.model = (tfms >> 4) & 15;
+ if (cpu.level >= 6)
+ cpu.model += ((tfms >> 16) & 0xf) << 4;
+ }
+
+ asm("cpuid"
+ : "=a" (max_amd_level)
+ : "a" (0x80000000)
+ : "ebx", "ecx", "edx");
+
+ if (max_amd_level >= 0x80000001 &&
+ max_amd_level <= 0x8000ffff) {
+ u32 eax = 0x80000001;
+ asm("cpuid"
+ : "+a" (eax),
+ "=c" (cpu.flags[6]),
+ "=d" (cpu.flags[1])
+ : : "ebx");
+ }
+ }
+}
+
+/* Returns a bitmask of which words we have error bits in */
+static int check_flags(void)
+{
+ u32 err;
+ int i;
+
+ err = 0;
+ for (i = 0; i < NCAPINTS; i++) {
+ err_flags[i] = req_flags[i] & ~cpu.flags[i];
+ if (err_flags[i])
+ err |= 1 << i;
+ }
+
+ return err;
+}
+
+/*
+ * Returns -1 on error.
+ *
+ * *cpu_level is set to the current CPU level; *req_level to the required
+ * level. x86-64 is considered level 64 for this purpose.
+ *
+ * *err_flags_ptr is set to the flags error array if there are flags missing.
+ */
+int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr)
+{
+ int err;
+
+ memset(&cpu.flags, 0, sizeof cpu.flags);
+ cpu.level = 3;
+
+ if (has_eflag(X86_EFLAGS_AC))
+ cpu.level = 4;
+
+ get_flags();
+ err = check_flags();
+
+ if (test_bit(X86_FEATURE_LM, cpu.flags))
+ cpu.level = 64;
+
+ if (err == 0x01 &&
+ !(err_flags[0] &
+ ~((1 << X86_FEATURE_XMM)|(1 << X86_FEATURE_XMM2))) &&
+ is_amd()) {
+ /* If this is an AMD and we're only missing SSE+SSE2, try to
+ turn them on */
+
+ u32 ecx = MSR_K7_HWCR;
+ u32 eax, edx;
+
+ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+ eax &= ~(1 << 15);
+ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+ get_flags(); /* Make sure it really did something */
+ err = check_flags();
+ } else if (err == 0x01 &&
+ !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) &&
+ is_centaur() && cpu.model >= 6) {
+ /* If this is a VIA C3, we might have to enable CX8
+ explicitly */
+
+ u32 ecx = MSR_VIA_FCR;
+ u32 eax, edx;
+
+ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+ eax |= (1<<1)|(1<<7);
+ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+ set_bit(X86_FEATURE_CX8, cpu.flags);
+ err = check_flags();
+ } else if (err == 0x01 && is_transmeta()) {
+ /* Transmeta might have masked feature bits in word 0 */
+
+ u32 ecx = 0x80860004;
+ u32 eax, edx;
+ u32 level = 1;
+
+ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx));
+ asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx));
+ asm("cpuid"
+ : "+a" (level), "=d" (cpu.flags[0])
+ : : "ecx", "ebx");
+ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx));
+
+ err = check_flags();
+ }
+
+ if (err_flags_ptr)
+ *err_flags_ptr = err ? err_flags : NULL;
+ if (cpu_level_ptr)
+ *cpu_level_ptr = cpu.level;
+ if (req_level_ptr)
+ *req_level_ptr = req_level;
+
+ return (cpu.level < req_level || err) ? -1 : 0;
+}
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
deleted file mode 100644
index 34321368011..00000000000
--- a/arch/i386/boot/edd.S
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * BIOS Enhanced Disk Drive support
- * Copyright (C) 2002, 2003, 2004 Dell, Inc.
- * by Matt Domsch <Matt_Domsch@dell.com> October 2002
- * conformant to T13 Committee www.t13.org
- * projects 1572D, 1484D, 1386D, 1226DT
- * disk signature read by Matt Domsch <Matt_Domsch@dell.com>
- * and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
- * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net>
- * March 2004
- * Command line option parsing, Matt Domsch, November 2004
- */
-
-#include <linux/edd.h>
-#include <asm/setup.h>
-
-#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
-
-# It is assumed that %ds == INITSEG here
-
- movb $0, (EDD_MBR_SIG_NR_BUF)
- movb $0, (EDDNR)
-
-# Check the command line for options:
-# edd=of disables EDD completely (edd=off)
-# edd=sk skips the MBR test (edd=skipmbr)
-# edd=on re-enables EDD (edd=on)
-
- pushl %esi
- movw $edd_mbr_sig_start, %di # Default to edd=on
-
- movl %cs:(cmd_line_ptr), %esi
- andl %esi, %esi
- jz old_cl # Old boot protocol?
-
-# Convert to a real-mode pointer in fs:si
- movl %esi, %eax
- shrl $4, %eax
- movw %ax, %fs
- andw $0xf, %si
- jmp have_cl_pointer
-
-# Old-style boot protocol?
-old_cl:
- push %ds # aka INITSEG
- pop %fs
-
- cmpw $0xa33f, (0x20)
- jne done_cl # No command line at all?
- movw (0x22), %si # Pointer relative to INITSEG
-
-# fs:si has the pointer to the command line now
-have_cl_pointer:
-
-# Loop through kernel command line one byte at a time. Just in
-# case the loader is buggy and failed to null-terminate the command line
-# terminate if we get close enough to the end of the segment that we
-# cannot fit "edd=XX"...
-cl_atspace:
- cmpw $-5, %si # Watch for segment wraparound
- jae done_cl
- movl %fs:(%si), %eax
- andb %al, %al # End of line?
- jz done_cl
- cmpl $EDD_CL_EQUALS, %eax
- jz found_edd_equals
- cmpb $0x20, %al # <= space consider whitespace
- ja cl_skipword
- incw %si
- jmp cl_atspace
-
-cl_skipword:
- cmpw $-5, %si # Watch for segment wraparound
- jae done_cl
- movb %fs:(%si), %al # End of string?
- andb %al, %al
- jz done_cl
- cmpb $0x20, %al
- jbe cl_atspace
- incw %si
- jmp cl_skipword
-
-found_edd_equals:
-# only looking at first two characters after equals
-# late overrides early on the command line, so keep going after finding something
- movw %fs:4(%si), %ax
- cmpw $EDD_CL_OFF, %ax # edd=of
- je do_edd_off
- cmpw $EDD_CL_SKIP, %ax # edd=sk
- je do_edd_skipmbr
- cmpw $EDD_CL_ON, %ax # edd=on
- je do_edd_on
- jmp cl_skipword
-do_edd_skipmbr:
- movw $edd_start, %di
- jmp cl_skipword
-do_edd_off:
- movw $edd_done, %di
- jmp cl_skipword
-do_edd_on:
- movw $edd_mbr_sig_start, %di
- jmp cl_skipword
-
-done_cl:
- popl %esi
- jmpw *%di
-
-# Read the first sector of each BIOS disk device and store the 4-byte signature
-edd_mbr_sig_start:
- movb $0x80, %dl # from device 80
- movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx
-edd_mbr_sig_read:
- movl $0xFFFFFFFF, %eax
- movl %eax, (%bx) # assume failure
- pushw %bx
- movb $READ_SECTORS, %ah
- movb $1, %al # read 1 sector
- movb $0, %dh # at head 0
- movw $1, %cx # cylinder 0, sector 0
- pushw %es
- pushw %ds
- popw %es
- movw $EDDBUF, %bx # disk's data goes into EDDBUF
- pushw %dx # work around buggy BIOSes
- stc # work around buggy BIOSes
- int $0x13
- sti # work around buggy BIOSes
- popw %dx
- popw %es
- popw %bx
- jc edd_mbr_sig_done # on failure, we're done.
- cmpb $0, %ah # some BIOSes do not set CF
- jne edd_mbr_sig_done # on failure, we're done.
- movl (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR
- movl %eax, (%bx) # store success
- incb (EDD_MBR_SIG_NR_BUF) # note that we stored something
- incb %dl # increment to next device
- addw $4, %bx # increment sig buffer ptr
- cmpb $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF) # Out of space?
- jb edd_mbr_sig_read # keep looping
-edd_mbr_sig_done:
-
-# Do the BIOS Enhanced Disk Drive calls
-# This consists of two calls:
-# int 13h ah=41h "Check Extensions Present"
-# int 13h ah=48h "Get Device Parameters"
-# int 13h ah=08h "Legacy Get Device Parameters"
-#
-# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use
-# in the boot_params at EDDBUF. The first four bytes of which are
-# used to store the device number, interface support map and version
-# results from fn41. The next four bytes are used to store the legacy
-# cylinders, heads, and sectors from fn08. The following 74 bytes are used to
-# store the results from fn48. Starting from device 80h, fn41, then fn48
-# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE).
-# Then the pointer is incremented to store the data for the next call.
-# This repeats until either a device doesn't exist, or until EDDMAXNR
-# devices have been stored.
-# The one tricky part is that ds:si always points EDDEXTSIZE bytes into
-# the structure, and the fn41 and fn08 results are stored at offsets
-# from there. This removes the need to increment the pointer for
-# every store, and leaves it ready for the fn48 call.
-# A second one-byte buffer, EDDNR, in the boot_params stores
-# the number of BIOS devices which exist, up to EDDMAXNR.
-# In setup.c, copy_edd() stores both boot_params buffers away
-# for later use, as they would get overwritten otherwise.
-# This code is sensitive to the size of the structs in edd.h
-edd_start:
- # %ds points to the bootsector
- # result buffer for fn48
- movw $EDDBUF+EDDEXTSIZE, %si # in ds:si, fn41 results
- # kept just before that
- movb $0x80, %dl # BIOS device 0x80
-
-edd_check_ext:
- movb $CHECKEXTENSIONSPRESENT, %ah # Function 41
- movw $EDDMAGIC1, %bx # magic
- int $0x13 # make the call
- jc edd_done # no more BIOS devices
-
- cmpw $EDDMAGIC2, %bx # is magic right?
- jne edd_next # nope, next...
-
- movb %dl, %ds:-8(%si) # store device number
- movb %ah, %ds:-7(%si) # store version
- movw %cx, %ds:-6(%si) # store extensions
- incb (EDDNR) # note that we stored something
-
-edd_get_device_params:
- movw $EDDPARMSIZE, %ds:(%si) # put size
- movw $0x0, %ds:2(%si) # work around buggy BIOSes
- movb $GETDEVICEPARAMETERS, %ah # Function 48
- int $0x13 # make the call
- # Don't check for fail return
- # it doesn't matter.
-edd_get_legacy_chs:
- xorw %ax, %ax
- movw %ax, %ds:-4(%si)
- movw %ax, %ds:-2(%si)
- # Ralf Brown's Interrupt List says to set ES:DI to
- # 0000h:0000h "to guard against BIOS bugs"
- pushw %es
- movw %ax, %es
- movw %ax, %di
- pushw %dx # legacy call clobbers %dl
- movb $LEGACYGETDEVICEPARAMETERS, %ah # Function 08
- int $0x13 # make the call
- jc edd_legacy_done # failed
- movb %cl, %al # Low 6 bits are max
- andb $0x3F, %al # sector number
- movb %al, %ds:-1(%si) # Record max sect
- movb %dh, %ds:-2(%si) # Record max head number
- movb %ch, %al # Low 8 bits of max cyl
- shr $6, %cl
- movb %cl, %ah # High 2 bits of max cyl
- movw %ax, %ds:-4(%si)
-
-edd_legacy_done:
- popw %dx
- popw %es
- movw %si, %ax # increment si
- addw $EDDPARMSIZE+EDDEXTSIZE, %ax
- movw %ax, %si
-
-edd_next:
- incb %dl # increment to next device
- cmpb $EDDMAXNR, (EDDNR) # Out of space?
- jb edd_check_ext # keep looping
-
-edd_done:
-#endif
diff --git a/arch/i386/boot/edd.c b/arch/i386/boot/edd.c
new file mode 100644
index 00000000000..25a282494f4
--- /dev/null
+++ b/arch/i386/boot/edd.c
@@ -0,0 +1,196 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/edd.c
+ *
+ * Get EDD BIOS disk information
+ */
+
+#include "boot.h"
+#include <linux/edd.h>
+
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+
+struct edd_dapa {
+ u8 pkt_size;
+ u8 rsvd;
+ u16 sector_cnt;
+ u16 buf_off, buf_seg;
+ u64 lba;
+ u64 buf_lin_addr;
+};
+
+/*
+ * Read the MBR (first sector) from a specific device.
+ */
+static int read_mbr(u8 devno, void *buf)
+{
+ struct edd_dapa dapa;
+ u16 ax, bx, cx, dx, si;
+
+ memset(&dapa, 0, sizeof dapa);
+ dapa.pkt_size = sizeof(dapa);
+ dapa.sector_cnt = 1;
+ dapa.buf_off = (size_t)buf;
+ dapa.buf_seg = ds();
+ /* dapa.lba = 0; */
+
+ ax = 0x4200; /* Extended Read */
+ si = (size_t)&dapa;
+ dx = devno;
+ asm("pushfl; stc; int $0x13; setc %%al; popfl"
+ : "+a" (ax), "+S" (si), "+d" (dx)
+ : "m" (dapa)
+ : "ebx", "ecx", "edi", "memory");
+
+ if (!(u8)ax)
+ return 0; /* OK */
+
+ ax = 0x0201; /* Legacy Read, one sector */
+ cx = 0x0001; /* Sector 0-0-1 */
+ dx = devno;
+ bx = (size_t)buf;
+ asm("pushfl; stc; int $0x13; setc %%al; popfl"
+ : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx)
+ : : "esi", "edi", "memory");
+
+ return -(u8)ax; /* 0 or -1 */
+}
+
+static u32 read_mbr_sig(u8 devno, struct edd_info *ei)
+{
+ int sector_size;
+ char *mbrbuf_ptr, *mbrbuf_end;
+ u32 mbrsig;
+ u32 buf_base, mbr_base;
+ extern char _end[];
+ static char mbr_buf[1024];
+
+ sector_size = ei->params.bytes_per_sector;
+ if (!sector_size)
+ sector_size = 512; /* Best available guess */
+
+ buf_base = (ds() << 4) + (u32)&_end;
+ mbr_base = (buf_base+sector_size-1) & ~(sector_size-1);
+ mbrbuf_ptr = mbr_buf + (mbr_base-buf_base);
+ mbrbuf_end = mbrbuf_ptr + sector_size;
+
+ if (!(boot_params.hdr.loadflags & CAN_USE_HEAP))
+ return 0;
+ if (mbrbuf_end > (char *)(size_t)boot_params.hdr.heap_end_ptr)
+ return 0;
+
+ if (read_mbr(devno, mbrbuf_ptr))
+ return 0;
+
+ mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_SIG_OFFSET];
+ return mbrsig;
+}
+
+static int get_edd_info(u8 devno, struct edd_info *ei)
+{
+ u16 ax, bx, cx, dx, di;
+
+ memset(ei, 0, sizeof *ei);
+
+ /* Check Extensions Present */
+
+ ax = 0x4100;
+ bx = EDDMAGIC1;
+ dx = devno;
+ asm("pushfl; stc; int $0x13; setc %%al; popfl"
+ : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx)
+ : : "esi", "edi");
+
+ if ((u8)ax)
+ return -1; /* No extended information */
+
+ if (bx != EDDMAGIC2)
+ return -1;
+
+ ei->device = devno;
+ ei->version = ax >> 8; /* EDD version number */
+ ei->interface_support = cx; /* EDD functionality subsets */
+
+ /* Extended Get Device Parameters */
+
+ ei->params.length = sizeof(ei->params);
+ ax = 0x4800;
+ dx = devno;
+ asm("pushfl; int $0x13; popfl"
+ : "+a" (ax), "+d" (dx)
+ : "S" (&ei->params)
+ : "ebx", "ecx", "edi");
+
+ /* Get legacy CHS parameters */
+
+ /* Ralf Brown recommends setting ES:DI to 0:0 */
+ ax = 0x0800;
+ dx = devno;
+ di = 0;
+ asm("pushw %%es; "
+ "movw %%di,%%es; "
+ "pushfl; stc; int $0x13; setc %%al; popfl; "
+ "popw %%es"
+ : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di)
+ : : "esi");
+
+ if ((u8)ax == 0) {
+ ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2);
+ ei->legacy_max_head = dx >> 8;
+ ei->legacy_sectors_per_track = cx & 0x3f;
+ }
+
+ return 0;
+}
+
+void query_edd(void)
+{
+ char eddarg[8];
+ int do_mbr = 1;
+ int do_edd = 1;
+ int devno;
+ struct edd_info ei, *edp;
+
+ if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) {
+ if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip"))
+ do_mbr = 0;
+ else if (!strcmp(eddarg, "off"))
+ do_edd = 0;
+ }
+
+ edp = (struct edd_info *)boot_params.eddbuf;
+
+ if (!do_edd)
+ return;
+
+ for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) {
+ /*
+ * Scan the BIOS-supported hard disks and query EDD
+ * information...
+ */
+ get_edd_info(devno, &ei);
+
+ if (boot_params.eddbuf_entries < EDDMAXNR) {
+ memcpy(edp, &ei, sizeof ei);
+ edp++;
+ boot_params.eddbuf_entries++;
+ }
+
+ if (do_mbr) {
+ u32 mbr_sig;
+ mbr_sig = read_mbr_sig(devno, &ei);
+ boot_params.edd_mbr_sig_buffer[devno-0x80] = mbr_sig;
+ }
+ }
+}
+
+#endif
diff --git a/arch/i386/boot/header.S b/arch/i386/boot/header.S
new file mode 100644
index 00000000000..6b9923fb6ea
--- /dev/null
+++ b/arch/i386/boot/header.S
@@ -0,0 +1,283 @@
+/*
+ * header.S
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * Based on bootsect.S and setup.S
+ * modified by more people than can be counted
+ *
+ * Rewritten as a common file by H. Peter Anvin (Apr 2007)
+ *
+ * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
+ * addresses must be multiplied by 16 to obtain their respective linear
+ * addresses. To avoid confusion, linear addresses are written using leading
+ * hex while segment addresses are written as segment:offset.
+ *
+ */
+
+#include <asm/segment.h>
+#include <linux/utsrelease.h>
+#include <asm/boot.h>
+#include <asm/e820.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+#include "boot.h"
+
+SETUPSECTS = 4 /* default nr of setup-sectors */
+BOOTSEG = 0x07C0 /* original address of boot-sector */
+SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */
+SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */
+ /* to be loaded */
+ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */
+SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
+
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
+
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif
+
+#ifndef ROOT_RDONLY
+#define ROOT_RDONLY 1
+#endif
+
+ .code16
+ .section ".bstext", "ax"
+
+ .global bootsect_start
+bootsect_start:
+
+ # Normalize the start address
+ ljmp $BOOTSEG, $start2
+
+start2:
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ xorw %sp, %sp
+ sti
+ cld
+
+ movw $bugger_off_msg, %si
+
+msg_loop:
+ lodsb
+ andb %al, %al
+ jz bs_die
+ movb $0xe, %ah
+ movw $7, %bx
+ int $0x10
+ jmp msg_loop
+
+bs_die:
+ # Allow the user to press a key, then reboot
+ xorw %ax, %ax
+ int $0x16
+ int $0x19
+
+ # int 0x19 should never return. In case it does anyway,
+ # invoke the BIOS reset code...
+ ljmp $0xf000,$0xfff0
+
+ .section ".bsdata", "a"
+bugger_off_msg:
+ .ascii "Direct booting from floppy is no longer supported.\r\n"
+ .ascii "Please use a boot loader program instead.\r\n"
+ .ascii "\n"
+ .ascii "Remove disk and press any key to reboot . . .\r\n"
+ .byte 0
+
+
+ # Kernel attributes; used by setup. This is part 1 of the
+ # header, from the old boot sector.
+
+ .section ".header", "a"
+ .globl hdr
+hdr:
+setup_sects: .byte SETUPSECTS
+root_flags: .word ROOT_RDONLY
+syssize: .long SYSSIZE
+ram_size: .word RAMDISK
+vid_mode: .word SVGA_MODE
+root_dev: .word ROOT_DEV
+boot_flag: .word 0xAA55
+
+ # offset 512, entry point
+
+ .globl _start
+_start:
+ # Explicitly enter this as bytes, or the assembler
+ # tries to generate a 3-byte jump here, which causes
+ # everything else to push off to the wrong offset.
+ .byte 0xeb # short (2-byte) jump
+ .byte start_of_setup-1f
+1:
+
+ # Part 2 of the header, from the old setup.S
+
+ .ascii "HdrS" # header signature
+ .word 0x0206 # header version number (>= 0x0105)
+ # or else old loadlin-1.5 will fail)
+ .globl realmode_swtch
+realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
+start_sys_seg: .word SYSSEG
+ .word kernel_version-512 # pointing to kernel version string
+ # above section of header is compatible
+ # with loadlin-1.5 (header v1.5). Don't
+ # change it.
+
+type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin,
+ # Bootlin, SYSLX, bootsect...)
+ # See Documentation/i386/boot.txt for
+ # assigned ids
+
+# flags, unused bits must be zero (RFU) bit within loadflags
+loadflags:
+LOADED_HIGH = 1 # If set, the kernel is loaded high
+CAN_USE_HEAP = 0x80 # If set, the loader also has set
+ # heap_end_ptr to tell how much
+ # space behind setup.S can be used for
+ # heap purposes.
+ # Only the loader knows what is free
+#ifndef __BIG_KERNEL__
+ .byte 0
+#else
+ .byte LOADED_HIGH
+#endif
+
+setup_move_size: .word 0x8000 # size to move, when setup is not
+ # loaded at 0x90000. We will move setup
+ # to 0x90000 then just before jumping
+ # into the kernel. However, only the
+ # loader knows how much data behind
+ # us also needs to be loaded.
+
+code32_start: # here loaders can put a different
+ # start address for 32-bit code.
+#ifndef __BIG_KERNEL__
+ .long 0x1000 # 0x1000 = default for zImage
+#else
+ .long 0x100000 # 0x100000 = default for big kernel
+#endif
+
+ramdisk_image: .long 0 # address of loaded ramdisk image
+ # Here the loader puts the 32-bit
+ # address where it loaded the image.
+ # This only will be read by the kernel.
+
+ramdisk_size: .long 0 # its size in bytes
+
+bootsect_kludge:
+ .long 0 # obsolete
+
+heap_end_ptr: .word _end+1024 # (Header version 0x0201 or later)
+ # space from here (exclusive) down to
+ # end of setup code can be used by setup
+ # for local heap purposes.
+
+pad1: .word 0
+cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
+ # If nonzero, a 32-bit pointer
+ # to the kernel command line.
+ # The command line should be
+ # located between the start of
+ # setup and the end of low
+ # memory (0xa0000), or it may
+ # get overwritten before it
+ # gets read. If this field is
+ # used, there is no longer
+ # anything magical about the
+ # 0x90000 segment; the setup
+ # can be located anywhere in
+ # low memory 0x10000 or higher.
+
+ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
+ # (Header version 0x0203 or later)
+ # The highest safe address for
+ # the contents of an initrd
+
+kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment
+ #required for protected mode
+ #kernel
+#ifdef CONFIG_RELOCATABLE
+relocatable_kernel: .byte 1
+#else
+relocatable_kernel: .byte 0
+#endif
+pad2: .byte 0
+pad3: .word 0
+
+cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line,
+ #added with boot protocol
+ #version 2.06
+
+# End of setup header #####################################################
+
+ .section ".inittext", "ax"
+start_of_setup:
+#ifdef SAFE_RESET_DISK_CONTROLLER
+# Reset the disk controller.
+ movw $0x0000, %ax # Reset disk controller
+ movb $0x80, %dl # All disks
+ int $0x13
+#endif
+
+# We will have entired with %cs = %ds+0x20, normalize %cs so
+# it is on par with the other segments.
+ pushw %ds
+ pushw $setup2
+ lretw
+
+setup2:
+# Force %es = %ds
+ movw %ds, %ax
+ movw %ax, %es
+ cld
+
+# Stack paranoia: align the stack and make sure it is good
+# for both 16- and 32-bit references. In particular, if we
+# were meant to have been using the full 16-bit segment, the
+# caller might have set %sp to zero, which breaks %esp-based
+# references.
+ andw $~3, %sp # dword align (might as well...)
+ jnz 1f
+ movw $0xfffc, %sp # Make sure we're not zero
+1: movzwl %sp, %esp # Clear upper half of %esp
+ sti
+
+# Check signature at end of setup
+ cmpl $0x5a5aaa55, setup_sig
+ jne setup_bad
+
+# Zero the bss
+ movw $__bss_start, %di
+ movw $_end+3, %cx
+ xorl %eax, %eax
+ subw %di, %cx
+ shrw $2, %cx
+ rep; stosl
+
+# Jump to C code (should not return)
+ calll main
+
+# Setup corrupt somehow...
+setup_bad:
+ movl $setup_corrupt, %eax
+ calll puts
+ # Fall through...
+
+ .globl die
+ .type die, @function
+die:
+ hlt
+ jmp die
+
+ .size die, .-due
+
+ .section ".initdata", "a"
+setup_corrupt:
+ .byte 7
+ .string "No setup signature found..."
diff --git a/arch/i386/boot/main.c b/arch/i386/boot/main.c
new file mode 100644
index 00000000000..7f01f96c4fb
--- /dev/null
+++ b/arch/i386/boot/main.c
@@ -0,0 +1,161 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/main.c
+ *
+ * Main module for the real-mode kernel code
+ */
+
+#include "boot.h"
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+char *HEAP = _end;
+char *heap_end = _end; /* Default end of heap = no heap */
+
+/*
+ * Copy the header into the boot parameter block. Since this
+ * screws up the old-style command line protocol, adjust by
+ * filling in the new-style command line pointer instead.
+ */
+#define OLD_CL_MAGIC 0xA33F
+#define OLD_CL_ADDRESS 0x20
+
+static void copy_boot_params(void)
+{
+ struct old_cmdline {
+ u16 cl_magic;
+ u16 cl_offset;
+ };
+ const struct old_cmdline * const oldcmd =
+ (const struct old_cmdline *)OLD_CL_ADDRESS;
+
+ BUILD_BUG_ON(sizeof boot_params != 4096);
+ memcpy(&boot_params.hdr, &hdr, sizeof hdr);
+
+ if (!boot_params.hdr.cmd_line_ptr &&
+ oldcmd->cl_magic == OLD_CL_MAGIC) {
+ /* Old-style command line protocol. */
+ u16 cmdline_seg;
+
+ /* Figure out if the command line falls in the region
+ of memory that an old kernel would have copied up
+ to 0x90000... */
+ if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)
+ cmdline_seg = ds();
+ else
+ cmdline_seg = 0x9000;
+
+ boot_params.hdr.cmd_line_ptr =
+ (cmdline_seg << 4) + oldcmd->cl_offset;
+ }
+}
+
+/*
+ * Set the keyboard repeat rate to maximum. Unclear why this
+ * is done here; this might be possible to kill off as stale code.
+ */
+static void keyboard_set_repeat(void)
+{
+ u16 ax = 0x0305;
+ u16 bx = 0;
+ asm volatile("int $0x16"
+ : "+a" (ax), "+b" (bx)
+ : : "ecx", "edx", "esi", "edi");
+}
+
+/*
+ * Get Intel SpeedStep IST information.
+ */
+static void query_speedstep_ist(void)
+{
+ asm("int $0x15"
+ : "=a" (boot_params.speedstep_info[0]),
+ "=b" (boot_params.speedstep_info[1]),
+ "=c" (boot_params.speedstep_info[2]),
+ "=d" (boot_params.speedstep_info[3])
+ : "a" (0x0000e980), /* IST Support */
+ "d" (0x47534943)); /* Request value */
+}
+
+/*
+ * Tell the BIOS what CPU mode we intend to run in.
+ */
+static void set_bios_mode(void)
+{
+#ifdef CONFIG_X86_64
+ u32 eax, ebx;
+
+ eax = 0xec00;
+ ebx = 2;
+ asm volatile("int $0x15"
+ : "+a" (eax), "+b" (ebx)
+ : : "ecx", "edx", "esi", "edi");
+#endif
+}
+
+void main(void)
+{
+ /* First, copy the boot header into the "zeropage" */
+ copy_boot_params();
+
+ /* End of heap check */
+ if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
+ heap_end = (char *)(boot_params.hdr.heap_end_ptr
+ +0x200-STACK_SIZE);
+ } else {
+ /* Boot protocol 2.00 only, no heap available */
+ puts("WARNING: Ancient bootloader, some functionality "
+ "may be limited!\n");
+ }
+
+ /* Make sure we have all the proper CPU support */
+ if (validate_cpu()) {
+ puts("Unable to boot - please use a kernel appropriate "
+ "for your CPU.\n");
+ die();
+ }
+
+ /* Tell the BIOS what CPU mode we intend to run in. */
+ set_bios_mode();
+
+ /* Detect memory layout */
+ detect_memory();
+
+ /* Set keyboard repeat rate (why?) */
+ keyboard_set_repeat();
+
+ /* Set the video mode */
+ set_video();
+
+ /* Query MCA information */
+ query_mca();
+
+ /* Voyager */
+#ifdef CONFIG_X86_VOYAGER
+ query_voyager();
+#endif
+
+ /* Query SpeedStep IST information */
+ query_speedstep_ist();
+
+ /* Query APM information */
+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+ query_apm_bios();
+#endif
+
+ /* Query EDD information */
+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+ query_edd();
+#endif
+ /* Do the last things and invoke protected mode */
+ go_to_protected_mode();
+}
diff --git a/arch/i386/boot/mca.c b/arch/i386/boot/mca.c
new file mode 100644
index 00000000000..9b68bd1aef1
--- /dev/null
+++ b/arch/i386/boot/mca.c
@@ -0,0 +1,43 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/mca.c
+ *
+ * Get the MCA system description table
+ */
+
+#include "boot.h"
+
+int query_mca(void)
+{
+ u8 err;
+ u16 es, bx, len;
+
+ asm("pushw %%es ; "
+ "int $0x15 ; "
+ "setc %0 ; "
+ "movw %%es, %1 ; "
+ "popw %%es"
+ : "=acdSDm" (err), "=acdSDm" (es), "=b" (bx)
+ : "a" (0xc000));
+
+ if (err)
+ return -1; /* No MCA present */
+
+ set_fs(es);
+ len = rdfs16(bx);
+
+ if (len > sizeof(boot_params.sys_desc_table))
+ len = sizeof(boot_params.sys_desc_table);
+
+ copy_from_fs(&boot_params.sys_desc_table, bx, len);
+ return 0;
+}
diff --git a/arch/i386/boot/memory.c b/arch/i386/boot/memory.c
new file mode 100644
index 00000000000..1a2e62db8be
--- /dev/null
+++ b/arch/i386/boot/memory.c
@@ -0,0 +1,99 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/memory.c
+ *
+ * Memory detection code
+ */
+
+#include "boot.h"
+
+#define SMAP 0x534d4150 /* ASCII "SMAP" */
+
+static int detect_memory_e820(void)
+{
+ u32 next = 0;
+ u32 size, id;
+ u8 err;
+ struct e820entry *desc = boot_params.e820_map;
+
+ do {
+ size = sizeof(struct e820entry);
+ id = SMAP;
+ asm("int $0x15; setc %0"
+ : "=am" (err), "+b" (next), "+d" (id), "+c" (size),
+ "=m" (*desc)
+ : "D" (desc), "a" (0xe820));
+
+ if (err || id != SMAP)
+ break;
+
+ boot_params.e820_entries++;
+ desc++;
+ } while (next && boot_params.e820_entries < E820MAX);
+
+ return boot_params.e820_entries;
+}
+
+static int detect_memory_e801(void)
+{
+ u16 ax, bx, cx, dx;
+ u8 err;
+
+ bx = cx = dx = 0;
+ ax = 0xe801;
+ asm("stc; int $0x15; setc %0"
+ : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
+
+ if (err)
+ return -1;
+
+ /* Do we really need to do this? */
+ if (cx || dx) {
+ ax = cx;
+ bx = dx;
+ }
+
+ if (ax > 15*1024)
+ return -1; /* Bogus! */
+
+ /* This ignores memory above 16MB if we have a memory hole
+ there. If someone actually finds a machine with a memory
+ hole at 16MB and no support for 0E820h they should probably
+ generate a fake e820 map. */
+ boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax;
+
+ return 0;
+}
+
+static int detect_memory_88(void)
+{
+ u16 ax;
+ u8 err;
+
+ ax = 0x8800;
+ asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax));
+
+ boot_params.screen_info.ext_mem_k = ax;
+
+ return -err;
+}
+
+int detect_memory(void)
+{
+ if (detect_memory_e820() > 0)
+ return 0;
+
+ if (!detect_memory_e801())
+ return 0;
+
+ return detect_memory_88();
+}
diff --git a/arch/i386/boot/pm.c b/arch/i386/boot/pm.c
new file mode 100644
index 00000000000..3fa53e15ed7
--- /dev/null
+++ b/arch/i386/boot/pm.c
@@ -0,0 +1,170 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/pm.c
+ *
+ * Prepare the machine for transition to protected mode.
+ */
+
+#include "boot.h"
+#include <asm/segment.h>
+
+/*
+ * Invoke the realmode switch hook if present; otherwise
+ * disable all interrupts.
+ */
+static void realmode_switch_hook(void)
+{
+ if (boot_params.hdr.realmode_swtch) {
+ asm volatile("lcallw *%0"
+ : : "m" (boot_params.hdr.realmode_swtch)
+ : "eax", "ebx", "ecx", "edx");
+ } else {
+ asm volatile("cli");
+ outb(0x80, 0x70); /* Disable NMI */
+ io_delay();
+ }
+}
+
+/*
+ * A zImage kernel is loaded at 0x10000 but wants to run at 0x1000.
+ * A bzImage kernel is loaded and runs at 0x100000.
+ */
+static void move_kernel_around(void)
+{
+ /* Note: rely on the compile-time option here rather than
+ the LOADED_HIGH flag. The Qemu kernel loader unconditionally
+ sets the loadflags to zero. */
+#ifndef __BIG_KERNEL__
+ u16 dst_seg, src_seg;
+ u32 syssize;
+
+ dst_seg = 0x1000 >> 4;
+ src_seg = 0x10000 >> 4;
+ syssize = boot_params.hdr.syssize; /* Size in 16-byte paragraphs */
+
+ while (syssize) {
+ int paras = (syssize >= 0x1000) ? 0x1000 : syssize;
+ int dwords = paras << 2;
+
+ asm volatile("pushw %%es ; "
+ "pushw %%ds ; "
+ "movw %1,%%es ; "
+ "movw %2,%%ds ; "
+ "xorw %%di,%%di ; "
+ "xorw %%si,%%si ; "
+ "rep;movsl ; "
+ "popw %%ds ; "
+ "popw %%es"
+ : "+c" (dwords)
+ : "rm" (dst_seg), "rm" (src_seg)
+ : "esi", "edi");
+
+ syssize -= paras;
+ dst_seg += paras;
+ src_seg += paras;
+ }
+#endif
+}
+
+/*
+ * Disable all interrupts at the legacy PIC.
+ */
+static void mask_all_interrupts(void)
+{
+ outb(0xff, 0xa1); /* Mask all interrupts on the seconday PIC */
+ io_delay();
+ outb(0xfb, 0x21); /* Mask all but cascade on the primary PIC */
+ io_delay();
+}
+
+/*
+ * Reset IGNNE# if asserted in the FPU.
+ */
+static void reset_coprocessor(void)
+{
+ outb(0, 0xf0);
+ io_delay();
+ outb(0, 0xf1);
+ io_delay();
+}
+
+/*
+ * Set up the GDT
+ */
+#define GDT_ENTRY(flags,base,limit) \
+ (((u64)(base & 0xff000000) << 32) | \
+ ((u64)flags << 40) | \
+ ((u64)(limit & 0x00ff0000) << 32) | \
+ ((u64)(base & 0x00ffff00) << 16) | \
+ ((u64)(limit & 0x0000ffff)))
+
+struct gdt_ptr {
+ u16 len;
+ u32 ptr;
+} __attribute__((packed));
+
+static void setup_gdt(void)
+{
+ /* There are machines which are known to not boot with the GDT
+ being 8-byte unaligned. Intel recommends 16 byte alignment. */
+ static const u64 boot_gdt[] __attribute__((aligned(16))) = {
+ /* CS: code, read/execute, 4 GB, base 0 */
+ [GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+ /* DS: data, read/write, 4 GB, base 0 */
+ [GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
+ };
+ struct gdt_ptr gdt;
+
+ gdt.len = sizeof(boot_gdt)-1;
+ gdt.ptr = (u32)&boot_gdt + (ds() << 4);
+
+ asm volatile("lgdtl %0" : : "m" (gdt));
+}
+
+/*
+ * Set up the IDT
+ */
+static void setup_idt(void)
+{
+ static const struct gdt_ptr null_idt = {0, 0};
+ asm volatile("lidtl %0" : : "m" (null_idt));
+}
+
+/*
+ * Actual invocation sequence
+ */
+void go_to_protected_mode(void)
+{
+ /* Hook before leaving real mode, also disables interrupts */
+ realmode_switch_hook();
+
+ /* Move the kernel/setup to their final resting places */
+ move_kernel_around();
+
+ /* Enable the A20 gate */
+ if (enable_a20()) {
+ puts("A20 gate not responding, unable to boot...\n");
+ die();
+ }
+
+ /* Reset coprocessor (IGNNE#) */
+ reset_coprocessor();
+
+ /* Mask all interrupts in the PIC */
+ mask_all_interrupts();
+
+ /* Actual transition to protected mode... */
+ setup_idt();
+ setup_gdt();
+ protected_mode_jump(boot_params.hdr.code32_start,
+ (u32)&boot_params + (ds() << 4));
+}
diff --git a/arch/i386/boot/pmjump.S b/arch/i386/boot/pmjump.S
new file mode 100644
index 00000000000..2e559233725
--- /dev/null
+++ b/arch/i386/boot/pmjump.S
@@ -0,0 +1,54 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/pmjump.S
+ *
+ * The actual transition into protected mode
+ */
+
+#include <asm/boot.h>
+#include <asm/segment.h>
+
+ .text
+
+ .globl protected_mode_jump
+ .type protected_mode_jump, @function
+
+ .code16
+
+/*
+ * void protected_mode_jump(u32 entrypoint, u32 bootparams);
+ */
+protected_mode_jump:
+ xorl %ebx, %ebx # Flag to indicate this is a boot
+ movl %edx, %esi # Pointer to boot_params table
+ movl %eax, 2f # Patch ljmpl instruction
+ jmp 1f # Short jump to flush instruction q.
+
+1:
+ movw $__BOOT_DS, %cx
+
+ movl %cr0, %edx
+ orb $1, %dl # Protected mode (PE) bit
+ movl %edx, %cr0
+
+ movw %cx, %ds
+ movw %cx, %es
+ movw %cx, %fs
+ movw %cx, %gs
+ movw %cx, %ss
+
+ # Jump to the 32-bit entrypoint
+ .byte 0x66, 0xea # ljmpl opcode
+2: .long 0 # offset
+ .word __BOOT_CS # segment
+
+ .size protected_mode_jump, .-protected_mode_jump
diff --git a/arch/i386/boot/printf.c b/arch/i386/boot/printf.c
new file mode 100644
index 00000000000..1a09f9309d3
--- /dev/null
+++ b/arch/i386/boot/printf.c
@@ -0,0 +1,307 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/printf.c
+ *
+ * Oh, it's a waste of space, but oh-so-yummy for debugging. This
+ * version of printf() does not include 64-bit support. "Live with
+ * it."
+ *
+ */
+
+#include "boot.h"
+
+static int skip_atoi(const char **s)
+{
+ int i = 0;
+
+ while (isdigit(**s))
+ i = i * 10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char *number(char *str, long num, int base, int size, int precision,
+ int type)
+{
+ char c, sign, tmp[66];
+ const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ if (type & LARGE)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++] = '0';
+ else
+ while (num != 0)
+ tmp[i++] = digits[do_div(num, base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type & (ZEROPAD + LEFT)))
+ while (size-- > 0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type & SPECIAL) {
+ if (base == 8)
+ *str++ = '0';
+ else if (base == 16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ }
+ if (!(type & LEFT))
+ while (size-- > 0)
+ *str++ = c;
+ while (i < precision--)
+ *str++ = '0';
+ while (i-- > 0)
+ *str++ = tmp[i];
+ while (size-- > 0)
+ *str++ = ' ';
+ return str;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long num;
+ int i, base;
+ char *str;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+
+ for (str = buf; *fmt; ++fmt) {
+ if (*fmt != '%') {
+ *str++ = *fmt;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-':
+ flags |= LEFT;
+ goto repeat;
+ case '+':
+ flags |= PLUS;
+ goto repeat;
+ case ' ':
+ flags |= SPACE;
+ goto repeat;
+ case '#':
+ flags |= SPECIAL;
+ goto repeat;
+ case '0':
+ flags |= ZEROPAD;
+ goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+ qualifier = *fmt;
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT))
+ while (--field_width > 0)
+ *str++ = ' ';
+ *str++ = (unsigned char)va_arg(args, int);
+ while (--field_width > 0)
+ *str++ = ' ';
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ *str++ = ' ';
+ for (i = 0; i < len; ++i)
+ *str++ = *s++;
+ while (len < field_width--)
+ *str++ = ' ';
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2 * sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str,
+ (unsigned long)va_arg(args, void *), 16,
+ field_width, precision, flags);
+ continue;
+
+ case 'n':
+ if (qualifier == 'l') {
+ long *ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else {
+ int *ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ *str++ = '%';
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ *str++ = '%';
+ if (*fmt)
+ *str++ = *fmt;
+ else
+ --fmt;
+ continue;
+ }
+ if (qualifier == 'l')
+ num = va_arg(args, unsigned long);
+ else if (qualifier == 'h') {
+ num = (unsigned short)va_arg(args, int);
+ if (flags & SIGN)
+ num = (short)num;
+ } else if (flags & SIGN)
+ num = va_arg(args, int);
+ else
+ num = va_arg(args, unsigned int);
+ str = number(str, num, base, field_width, precision, flags);
+ }
+ *str = '\0';
+ return str - buf;
+}
+
+int sprintf(char *buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = vsprintf(buf, fmt, args);
+ va_end(args);
+ return i;
+}
+
+int printf(const char *fmt, ...)
+{
+ char printf_buf[1024];
+ va_list args;
+ int printed;
+
+ va_start(args, fmt);
+ printed = vsprintf(printf_buf, fmt, args);
+ va_end(args);
+
+ puts(printf_buf);
+
+ return printed;
+}
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
deleted file mode 100644
index 6dbcc95b212..00000000000
--- a/arch/i386/boot/setup.S
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*
- * setup.S Copyright (C) 1991, 1992 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- * Move PS/2 aux init code to psaux.c
- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *
- * some changes and additional features by Christoph Niemann,
- * March 1993/June 1994 (Christoph.Niemann@linux.org)
- *
- * add APM BIOS checking by Stephen Rothwell, May 1994
- * (sfr@canb.auug.org.au)
- *
- * High load stuff, initrd support and position independency
- * by Hans Lermen & Werner Almesberger, February 1996
- * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
- *
- * Video handling moved to video.S by Martin Mares, March 1996
- * <mj@k332.feld.cvut.cz>
- *
- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
- * parsons) to avoid loadlin confusion, July 1997
- *
- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
- * <stiker@northlink.com>
- *
- * Fix to work around buggy BIOSes which don't use carry bit correctly
- * and/or report extended memory in CX/DX for e801h memory size detection
- * call. As a result the kernel got wrong figures. The int15/e801h docs
- * from Ralf Brown interrupt list seem to indicate AX/BX should be used
- * anyway. So to avoid breaking many machines (presumably there was a reason
- * to orginally use CX/DX instead of AX/BX), we do a kludge to see
- * if CX/DX have been changed in the e801 call and if so use AX/BX .
- * Michael Miller, April 2001 <michaelm@mjmm.org>
- *
- * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
- * by Robert Schwebel, December 2001 <robert@schwebel.de>
- */
-
-#include <asm/segment.h>
-#include <linux/utsrelease.h>
-#include <linux/compile.h>
-#include <asm/boot.h>
-#include <asm/e820.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-
-/* Signature words to ensure LILO loaded us right */
-#define SIG1 0xAA55
-#define SIG2 0x5A5A
-
-INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way
-SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment
- # ... and the former contents of CS
-
-DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020
-
-.code16
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-start:
- jmp trampoline
-
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
- .ascii "HdrS" # header signature
- .word 0x0206 # header version number (>= 0x0105)
- # or else old loadlin-1.5 will fail)
-realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
-start_sys_seg: .word SYSSEG
- .word kernel_version # pointing to kernel version string
- # above section of header is compatible
- # with loadlin-1.5 (header v1.5). Don't
- # change it.
-
-type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin,
- # Bootlin, SYSLX, bootsect...)
- # See Documentation/i386/boot.txt for
- # assigned ids
-
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH = 1 # If set, the kernel is loaded high
-CAN_USE_HEAP = 0x80 # If set, the loader also has set
- # heap_end_ptr to tell how much
- # space behind setup.S can be used for
- # heap purposes.
- # Only the loader knows what is free
-#ifndef __BIG_KERNEL__
- .byte 0
-#else
- .byte LOADED_HIGH
-#endif
-
-setup_move_size: .word 0x8000 # size to move, when setup is not
- # loaded at 0x90000. We will move setup
- # to 0x90000 then just before jumping
- # into the kernel. However, only the
- # loader knows how much data behind
- # us also needs to be loaded.
-
-code32_start: # here loaders can put a different
- # start address for 32-bit code.
-#ifndef __BIG_KERNEL__
- .long 0x1000 # 0x1000 = default for zImage
-#else
- .long 0x100000 # 0x100000 = default for big kernel
-#endif
-
-ramdisk_image: .long 0 # address of loaded ramdisk image
- # Here the loader puts the 32-bit
- # address where it loaded the image.
- # This only will be read by the kernel.
-
-ramdisk_size: .long 0 # its size in bytes
-
-bootsect_kludge:
- .long 0 # obsolete
-
-heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later)
- # space from here (exclusive) down to
- # end of setup code can be used by setup
- # for local heap purposes.
-
-pad1: .word 0
-cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
- # If nonzero, a 32-bit pointer
- # to the kernel command line.
- # The command line should be
- # located between the start of
- # setup and the end of low
- # memory (0xa0000), or it may
- # get overwritten before it
- # gets read. If this field is
- # used, there is no longer
- # anything magical about the
- # 0x90000 segment; the setup
- # can be located anywhere in
- # low memory 0x10000 or higher.
-
-ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
- # (Header version 0x0203 or later)
- # The highest safe address for
- # the contents of an initrd
-
-kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment
- #required for protected mode
- #kernel
-#ifdef CONFIG_RELOCATABLE
-relocatable_kernel: .byte 1
-#else
-relocatable_kernel: .byte 0
-#endif
-pad2: .byte 0
-pad3: .word 0
-
-cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line,
- #added with boot protocol
- #version 2.06
-
-trampoline: call start_of_setup
- .align 16
- # The offset at this point is 0x240
- .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff)
-# End of setup header #####################################################
-
-start_of_setup:
-# Bootlin depends on this being done early
- movw $0x01500, %ax
- movb $0x81, %dl
- int $0x13
-
-#ifdef SAFE_RESET_DISK_CONTROLLER
-# Reset the disk controller.
- movw $0x0000, %ax
- movb $0x80, %dl
- int $0x13
-#endif
-
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
-# Check signature at end of setup
- cmpw $SIG1, setup_sig1
- jne bad_sig
-
- cmpw $SIG2, setup_sig2
- jne bad_sig
-
- jmp good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
- lodsb
- andb %al, %al
- jz fin
-
- call prtchr
- jmp prtstr
-
-fin: ret
-
-# Space printing
-prtsp2: call prtspc # Print double space
-prtspc: movb $0x20, %al # Print single space (note: fall-thru)
-
-# Part of above routine, this one just prints ascii al
-prtchr: pushw %ax
- pushw %cx
- movw $7,%bx
- movw $0x01, %cx
- movb $0x0e, %ah
- int $0x10
- popw %cx
- popw %ax
- ret
-
-beep: movb $0x07, %al
- jmp prtchr
-
-no_sig_mess: .string "No setup signature found ..."
-
-good_sig1:
- jmp good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
- movw %cs, %ax # SETUPSEG
- subw $DELTA_INITSEG, %ax # INITSEG
- movw %ax, %ds
- xorb %bh, %bh
- movb (497), %bl # get setup sect from bootsect
- subw $4, %bx # LILO loads 4 sectors of setup
- shlw $8, %bx # convert to words (1sect=2^8 words)
- movw %bx, %cx
- shrw $3, %bx # convert to segment
- addw $SYSSEG, %bx
- movw %bx, %cs:start_sys_seg
-# Move rest of setup code/data to here
- movw $2048, %di # four sectors loaded by LILO
- subw %si, %si
- pushw %cs
- popw %es
- movw $SYSSEG, %ax
- movw %ax, %ds
- rep
- movsw
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
- cmpw $SIG1, setup_sig1
- jne no_sig
-
- cmpw $SIG2, setup_sig2
- jne no_sig
-
- jmp good_sig
-
-no_sig:
- lea no_sig_mess, %si
- call prtstr
-
-no_sig_loop:
- hlt
- jmp no_sig_loop
-
-good_sig:
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %ds
-# Check if an old loader tries to load a big-kernel
- testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel?
- jz loader_ok # No, no danger for old loaders.
-
- cmpb $0, %cs:type_of_loader # Do we have a loader that
- # can deal with us?
- jnz loader_ok # Yes, continue.
-
- pushw %cs # No, we have an old loader,
- popw %ds # die.
- lea loader_panic_mess, %si
- call prtstr
-
- jmp no_sig_loop
-
-loader_panic_mess: .string "Wrong loader, giving up..."
-
-# check minimum cpuid
-# we do this here because it is the last place we can actually
-# show a user visible error message. Later the video modus
-# might be already messed up.
-loader_ok:
- call verify_cpu
- testl %eax,%eax
- jz cpu_ok
- movw %cs,%ax # aka SETUPSEG
- movw %ax,%ds
- lea cpu_panic_mess,%si
- call prtstr
-1: jmp 1b
-
-cpu_panic_mess:
- .asciz "PANIC: CPU too old for this kernel."
-
-#include "../kernel/verify_cpu.S"
-
-cpu_ok:
-# Get memory size (extended mem, kB)
-
- xorl %eax, %eax
- movl %eax, (0x1e0)
-#ifndef STANDARD_MEMORY_BIOS_CALL
- movb %al, (E820NR)
-# Try three different memory detection schemes. First, try
-# e820h, which lets us assemble a memory map, then try e801h,
-# which returns a 32-bit memory size, and finally 88h, which
-# returns 0-64m
-
-# method E820H:
-# the memory map from hell. e820h returns memory classified into
-# a whole bunch of different types, and allows memory holes and
-# everything. We scan through this memory map and build a list
-# of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
-
-#define SMAP 0x534d4150
-
-meme820:
- xorl %ebx, %ebx # continuation counter
- movw $E820MAP, %di # point into the whitelist
- # so we can have the bios
- # directly write into it.
-
-jmpe820:
- movl $0x0000e820, %eax # e820, upper word zeroed
- movl $SMAP, %edx # ascii 'SMAP'
- movl $20, %ecx # size of the e820rec
- pushw %ds # data record.
- popw %es
- int $0x15 # make the call
- jc bail820 # fall to e801 if it fails
-
- cmpl $SMAP, %eax # check the return is `SMAP'
- jne bail820 # fall to e801 if it fails
-
-# cmpl $1, 16(%di) # is this usable memory?
-# jne again820
-
- # If this is usable memory, we save it by simply advancing %di by
- # sizeof(e820rec).
- #
-good820:
- movb (E820NR), %al # up to 128 entries
- cmpb $E820MAX, %al
- jae bail820
-
- incb (E820NR)
- movw %di, %ax
- addw $20, %ax
- movw %ax, %di
-again820:
- cmpl $0, %ebx # check to see if
- jne jmpe820 # %ebx is set to EOF
-bail820:
-
-
-# method E801H:
-# memory size is in 1k chunksizes, to avoid confusing loadlin.
-# we store the 0xe801 memory size in a completely different place,
-# because it will most likely be longer than 16 bits.
-# (use 1e0 because that's what Larry Augustine uses in his
-# alternative new memory detection scheme, and it's sensible
-# to write everything into the same place.)
-
-meme801:
- stc # fix to work around buggy
- xorw %cx,%cx # BIOSes which don't clear/set
- xorw %dx,%dx # carry on pass/error of
- # e801h memory size call
- # or merely pass cx,dx though
- # without changing them.
- movw $0xe801, %ax
- int $0x15
- jc mem88
-
- cmpw $0x0, %cx # Kludge to handle BIOSes
- jne e801usecxdx # which report their extended
- cmpw $0x0, %dx # memory in AX/BX rather than
- jne e801usecxdx # CX/DX. The spec I have read
- movw %ax, %cx # seems to indicate AX/BX
- movw %bx, %dx # are more reasonable anyway...
-
-e801usecxdx:
- andl $0xffff, %edx # clear sign extend
- shll $6, %edx # and go from 64k to 1k chunks
- movl %edx, (0x1e0) # store extended memory size
- andl $0xffff, %ecx # clear sign extend
- addl %ecx, (0x1e0) # and add lower memory into
- # total size.
-
-# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
-# 64mb, depending on the bios) in ax.
-mem88:
-
-#endif
- movb $0x88, %ah
- int $0x15
- movw %ax, (2)
-
-# Set the keyboard repeat rate to the max
- movw $0x0305, %ax
- xorw %bx, %bx
- int $0x16
-
-# Check for video adapter and its parameters and allow the
-# user to browse video modes.
- call video # NOTE: we need %ds pointing
- # to bootsector
-
-# Get hd0 data...
- xorw %ax, %ax
- movw %ax, %ds
- ldsw (4 * 0x41), %si
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- pushw %ax
- movw %ax, %es
- movw $0x0080, %di
- movw $0x10, %cx
- pushw %cx
- cld
- rep
- movsb
-# Get hd1 data...
- xorw %ax, %ax
- movw %ax, %ds
- ldsw (4 * 0x46), %si
- popw %cx
- popw %es
- movw $0x0090, %di
- rep
- movsb
-# Check that there IS a hd1 :-)
- movw $0x01500, %ax
- movb $0x81, %dl
- int $0x13
- jc no_disk1
-
- cmpb $3, %ah
- je is_disk1
-
-no_disk1:
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %es
- movw $0x0090, %di
- movw $0x10, %cx
- xorw %ax, %ax
- cld
- rep
- stosb
-is_disk1:
-# check for Micro Channel (MCA) bus
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %ds
- xorw %ax, %ax
- movw %ax, (0xa0) # set table length to 0
- movb $0xc0, %ah
- stc
- int $0x15 # moves feature table to es:bx
- jc no_mca
-
- pushw %ds
- movw %es, %ax
- movw %ax, %ds
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %es
- movw %bx, %si
- movw $0xa0, %di
- movw (%si), %cx
- addw $2, %cx # table length is a short
- cmpw $0x10, %cx
- jc sysdesc_ok
-
- movw $0x10, %cx # we keep only first 16 bytes
-sysdesc_ok:
- rep
- movsb
- popw %ds
-no_mca:
-#ifdef CONFIG_X86_VOYAGER
- movb $0xff, 0x40 # flag on config found
- movb $0xc0, %al
- mov $0xff, %ah
- int $0x15 # put voyager config info at es:di
- jc no_voyager
- movw $0x40, %si # place voyager info in apm table
- cld
- movw $7, %cx
-voyager_rep:
- movb %es:(%di), %al
- movb %al,(%si)
- incw %di
- incw %si
- decw %cx
- jnz voyager_rep
-no_voyager:
-#endif
-# Check for PS/2 pointing device
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %ds
- movb $0, (0x1ff) # default is no pointing device
- int $0x11 # int 0x11: equipment list
- testb $0x04, %al # check if mouse installed
- jz no_psmouse
-
- movb $0xAA, (0x1ff) # device present
-no_psmouse:
-
-#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
- movl $0x0000E980, %eax # IST Support
- movl $0x47534943, %edx # Request value
- int $0x15
-
- movl %eax, (96)
- movl %ebx, (100)
- movl %ecx, (104)
- movl %edx, (108)
-#endif
-
-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
-# Then check for an APM BIOS...
- # %ds points to the bootsector
- movw $0, 0x40 # version = 0 means no APM BIOS
- movw $0x05300, %ax # APM BIOS installation check
- xorw %bx, %bx
- int $0x15
- jc done_apm_bios # Nope, no APM BIOS
-
- cmpw $0x0504d, %bx # Check for "PM" signature
- jne done_apm_bios # No signature, no APM BIOS
-
- andw $0x02, %cx # Is 32 bit supported?
- je done_apm_bios # No 32-bit, no (good) APM BIOS
-
- movw $0x05304, %ax # Disconnect first just in case
- xorw %bx, %bx
- int $0x15 # ignore return code
- movw $0x05303, %ax # 32 bit connect
- xorl %ebx, %ebx
- xorw %cx, %cx # paranoia :-)
- xorw %dx, %dx # ...
- xorl %esi, %esi # ...
- xorw %di, %di # ...
- int $0x15
- jc no_32_apm_bios # Ack, error.
-
- movw %ax, (66) # BIOS code segment
- movl %ebx, (68) # BIOS entry point offset
- movw %cx, (72) # BIOS 16 bit code segment
- movw %dx, (74) # BIOS data segment
- movl %esi, (78) # BIOS code segment lengths
- movw %di, (82) # BIOS data segment length
-# Redo the installation check as the 32 bit connect
-# modifies the flags returned on some BIOSs
- movw $0x05300, %ax # APM BIOS installation check
- xorw %bx, %bx
- xorw %cx, %cx # paranoia
- int $0x15
- jc apm_disconnect # error -> shouldn't happen
-
- cmpw $0x0504d, %bx # check for "PM" signature
- jne apm_disconnect # no sig -> shouldn't happen
-
- movw %ax, (64) # record the APM BIOS version
- movw %cx, (76) # and flags
- jmp done_apm_bios
-
-apm_disconnect: # Tidy up
- movw $0x05304, %ax # Disconnect
- xorw %bx, %bx
- int $0x15 # ignore return code
-
- jmp done_apm_bios
-
-no_32_apm_bios:
- andw $0xfffd, (76) # remove 32 bit support bit
-done_apm_bios:
-#endif
-
-#include "edd.S"
-
-# Now we want to move to protected mode ...
- cmpw $0, %cs:realmode_swtch
- jz rmodeswtch_normal
-
- lcall *%cs:realmode_swtch
-
- jmp rmodeswtch_end
-
-rmodeswtch_normal:
- pushw %cs
- call default_switch
-
-rmodeswtch_end:
-# Now we move the system to its rightful place ... but we check if we have a
-# big-kernel. In that case we *must* not move it ...
- testb $LOADED_HIGH, %cs:loadflags
- jz do_move0 # .. then we have a normal low
- # loaded zImage
- # .. or else we have a high
- # loaded bzImage
- jmp end_move # ... and we skip moving
-
-do_move0:
- movw $0x100, %ax # start of destination segment
- movw %cs, %bp # aka SETUPSEG
- subw $DELTA_INITSEG, %bp # aka INITSEG
- movw %cs:start_sys_seg, %bx # start of source segment
- cld
-do_move:
- movw %ax, %es # destination segment
- incb %ah # instead of add ax,#0x100
- movw %bx, %ds # source segment
- addw $0x100, %bx
- subw %di, %di
- subw %si, %si
- movw $0x800, %cx
- rep
- movsw
- cmpw %bp, %bx # assume start_sys_seg > 0x200,
- # so we will perhaps read one
- # page more than needed, but
- # never overwrite INITSEG
- # because destination is a
- # minimum one page below source
- jb do_move
-
-end_move:
-# then we load the segment descriptors
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
-
-# Check whether we need to be downward compatible with version <=201
- cmpl $0, cmd_line_ptr
- jne end_move_self # loader uses version >=202 features
- cmpb $0x20, type_of_loader
- je end_move_self # bootsect loader, we know of it
-
-# Boot loader doesnt support boot protocol version 2.02.
-# If we have our code not at 0x90000, we need to move it there now.
-# We also then need to move the params behind it (commandline)
-# Because we would overwrite the code on the current IP, we move
-# it in two steps, jumping high after the first one.
- movw %cs, %ax
- cmpw $SETUPSEG, %ax
- je end_move_self
-
- cli # make sure we really have
- # interrupts disabled !
- # because after this the stack
- # should not be used
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ss, %dx
- cmpw %ax, %dx
- jb move_self_1
-
- addw $INITSEG, %dx
- subw %ax, %dx # this will go into %ss after
- # the move
-move_self_1:
- movw %ax, %ds
- movw $INITSEG, %ax # real INITSEG
- movw %ax, %es
- movw %cs:setup_move_size, %cx
- std # we have to move up, so we use
- # direction down because the
- # areas may overlap
- movw %cx, %di
- decw %di
- movw %di, %si
- subw $move_self_here+0x200, %cx
- rep
- movsb
- ljmp $SETUPSEG, $move_self_here
-
-move_self_here:
- movw $move_self_here+0x200, %cx
- rep
- movsb
- movw $SETUPSEG, %ax
- movw %ax, %ds
- movw %dx, %ss
-end_move_self: # now we are at the right place
-
-#
-# Enable A20. This is at the very best an annoying procedure.
-# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
-# AMD Elan bug fix by Robert Schwebel.
-#
-
-#if defined(CONFIG_X86_ELAN)
- movb $0x02, %al # alternate A20 gate
- outb %al, $0x92 # this works on SC410/SC520
-a20_elan_wait:
- call a20_test
- jz a20_elan_wait
- jmp a20_done
-#endif
-
-
-A20_TEST_LOOPS = 32 # Iterations per wait
-A20_ENABLE_LOOPS = 255 # Total loops to try
-
-
-#ifndef CONFIG_X86_VOYAGER
-a20_try_loop:
-
- # First, see if we are on a system with no A20 gate.
-a20_none:
- call a20_test
- jnz a20_done
-
- # Next, try the BIOS (INT 0x15, AX=0x2401)
-a20_bios:
- movw $0x2401, %ax
- pushfl # Be paranoid about flags
- int $0x15
- popfl
-
- call a20_test
- jnz a20_done
-
- # Try enabling A20 through the keyboard controller
-#endif /* CONFIG_X86_VOYAGER */
-a20_kbc:
- call empty_8042
-
-#ifndef CONFIG_X86_VOYAGER
- call a20_test # Just in case the BIOS worked
- jnz a20_done # but had a delayed reaction.
-#endif
-
- movb $0xD1, %al # command write
- outb %al, $0x64
- call empty_8042
-
- movb $0xDF, %al # A20 on
- outb %al, $0x60
- call empty_8042
-
-#ifndef CONFIG_X86_VOYAGER
- # Wait until a20 really *is* enabled; it can take a fair amount of
- # time on certain systems; Toshiba Tecras are known to have this
- # problem.
-a20_kbc_wait:
- xorw %cx, %cx
-a20_kbc_wait_loop:
- call a20_test
- jnz a20_done
- loop a20_kbc_wait_loop
-
- # Final attempt: use "configuration port A"
-a20_fast:
- inb $0x92, %al # Configuration Port A
- orb $0x02, %al # "fast A20" version
- andb $0xFE, %al # don't accidentally reset
- outb %al, $0x92
-
- # Wait for configuration port A to take effect
-a20_fast_wait:
- xorw %cx, %cx
-a20_fast_wait_loop:
- call a20_test
- jnz a20_done
- loop a20_fast_wait_loop
-
- # A20 is still not responding. Try frobbing it again.
- #
- decb (a20_tries)
- jnz a20_try_loop
-
- movw $a20_err_msg, %si
- call prtstr
-
-a20_die:
- hlt
- jmp a20_die
-
-a20_tries:
- .byte A20_ENABLE_LOOPS
-
-a20_err_msg:
- .ascii "linux: fatal error: A20 gate not responding!"
- .byte 13, 10, 0
-
- # If we get here, all is good
-a20_done:
-
-#endif /* CONFIG_X86_VOYAGER */
-# set up gdt and idt and 32bit start address
- lidt idt_48 # load idt with 0,0
- xorl %eax, %eax # Compute gdt_base
- movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
- shll $4, %eax
- addl %eax, code32
- addl $gdt, %eax
- movl %eax, (gdt_48+2)
- lgdt gdt_48 # load gdt with whatever is
- # appropriate
-
-# make sure any possible coprocessor is properly reset..
- xorw %ax, %ax
- outb %al, $0xf0
- call delay
-
- outb %al, $0xf1
- call delay
-
-# well, that went ok, I hope. Now we mask all interrupts - the rest
-# is done in init_IRQ().
- movb $0xFF, %al # mask all interrupts for now
- outb %al, $0xA1
- call delay
-
- movb $0xFB, %al # mask all irq's but irq2 which
- outb %al, $0x21 # is cascaded
-
-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-# need no steenking BIOS anyway (except for the initial loading :-).
-# The BIOS-routine wants lots of unnecessary data, and it's less
-# "interesting" anyway. This is how REAL programmers do it.
-#
-# Well, now's the time to actually move into protected mode. To make
-# things as simple as possible, we do no register set-up or anything,
-# we let the gnu-compiled 32-bit programs do that. We just jump to
-# absolute address 0x1000 (or the loader supplied one),
-# in 32-bit protected mode.
-#
-# Note that the short jump isn't strictly needed, although there are
-# reasons why it might be a good idea. It won't hurt in any case.
- movw $1, %ax # protected mode (PE) bit
- lmsw %ax # This is it!
- jmp flush_instr
-
-flush_instr:
- xorw %bx, %bx # Flag to indicate a boot
- xorl %esi, %esi # Pointer to real-mode code
- movw %cs, %si
- subw $DELTA_INITSEG, %si
- shll $4, %esi # Convert to 32-bit pointer
-
-# jump to startup_32 in arch/i386/boot/compressed/head.S
-#
-# NOTE: For high loaded big kernels we need a
-# jmpi 0x100000,__BOOT_CS
-#
-# but we yet haven't reloaded the CS register, so the default size
-# of the target offset still is 16 bit.
-# However, using an operand prefix (0x66), the CPU will properly
-# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
-# Manual, Mixing 16-bit and 32-bit code, page 16-6)
-
- .byte 0x66, 0xea # prefix + jmpi-opcode
-code32: .long startup_32 # will be set to %cs+startup_32
- .word __BOOT_CS
-.code32
-startup_32:
- movl $(__BOOT_DS), %eax
- movl %eax, %ds
- movl %eax, %es
- movl %eax, %fs
- movl %eax, %gs
- movl %eax, %ss
-
- xorl %eax, %eax
-1: incl %eax # check that A20 really IS enabled
- movl %eax, 0x00000000 # loop forever if it isn't
- cmpl %eax, 0x00100000
- je 1b
-
- # Jump to the 32bit entry point
- jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi)
-.code16
-
-# Here's a bunch of information about your current kernel..
-kernel_version: .ascii UTS_RELEASE
- .ascii " ("
- .ascii LINUX_COMPILE_BY
- .ascii "@"
- .ascii LINUX_COMPILE_HOST
- .ascii ") "
- .ascii UTS_VERSION
- .byte 0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
- cli # no interrupts allowed !
- movb $0x80, %al # disable NMI for bootup
- # sequence
- outb %al, $0x70
- lret
-
-
-#ifndef CONFIG_X86_VOYAGER
-# This routine tests whether or not A20 is enabled. If so, it
-# exits with zf = 0.
-#
-# The memory address used, 0x200, is the int $0x80 vector, which
-# should be safe.
-
-A20_TEST_ADDR = 4*0x80
-
-a20_test:
- pushw %cx
- pushw %ax
- xorw %cx, %cx
- movw %cx, %fs # Low memory
- decw %cx
- movw %cx, %gs # High memory area
- movw $A20_TEST_LOOPS, %cx
- movw %fs:(A20_TEST_ADDR), %ax
- pushw %ax
-a20_test_wait:
- incw %ax
- movw %ax, %fs:(A20_TEST_ADDR)
- call delay # Serialize and make delay constant
- cmpw %gs:(A20_TEST_ADDR+0x10), %ax
- loope a20_test_wait
-
- popw %fs:(A20_TEST_ADDR)
- popw %ax
- popw %cx
- ret
-
-#endif /* CONFIG_X86_VOYAGER */
-
-# This routine checks that the keyboard command queue is empty
-# (after emptying the output buffers)
-#
-# Some machines have delusions that the keyboard buffer is always full
-# with no keyboard attached...
-#
-# If there is no keyboard controller, we will usually get 0xff
-# to all the reads. With each IO taking a microsecond and
-# a timeout of 100,000 iterations, this can take about half a
-# second ("delay" == outb to port 0x80). That should be ok,
-# and should also be plenty of time for a real keyboard controller
-# to empty.
-#
-
-empty_8042:
- pushl %ecx
- movl $100000, %ecx
-
-empty_8042_loop:
- decl %ecx
- jz empty_8042_end_loop
-
- call delay
-
- inb $0x64, %al # 8042 status port
- testb $1, %al # output buffer?
- jz no_output
-
- call delay
- inb $0x60, %al # read it
- jmp empty_8042_loop
-
-no_output:
- testb $2, %al # is input buffer full?
- jnz empty_8042_loop # yes - loop
-empty_8042_end_loop:
- popl %ecx
- ret
-
-# Read the cmos clock. Return the seconds in al
-gettime:
- pushw %cx
- movb $0x02, %ah
- int $0x1a
- movb %dh, %al # %dh contains the seconds
- andb $0x0f, %al
- movb %dh, %ah
- movb $0x04, %cl
- shrb %cl, %ah
- aad
- popw %cx
- ret
-
-# Delay is needed after doing I/O
-delay:
- outb %al,$0x80
- ret
-
-# Descriptor tables
-#
-# NOTE: The intel manual says gdt should be sixteen bytes aligned for
-# efficiency reasons. However, there are machines which are known not
-# to boot with misaligned GDTs, so alter this at your peril! If you alter
-# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
-# empty GDT entries (one for NULL and one reserved).
-#
-# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is
-# true for the Voyager Quad CPU card which will not boot without
-# This directive. 16 byte aligment is recommended by intel.
-#
- .align 16
-gdt:
- .fill GDT_ENTRY_BOOT_CS,8,0
-
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9A00 # code read/exec
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9200 # data read/write
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-gdt_end:
- .align 4
-
- .word 0 # alignment byte
-idt_48:
- .word 0 # idt limit = 0
- .word 0, 0 # idt base = 0L
-
- .word 0 # alignment byte
-gdt_48:
- .word gdt_end - gdt - 1 # gdt limit
- .word 0, 0 # gdt base (filled in later)
-
-# Include video setup & detection code
-
-#include "video.S"
-
-# Setup signature -- must be last
-setup_sig1: .word SIG1
-setup_sig2: .word SIG2
-
-# After this point, there is some free space which is used by the video mode
-# handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/arch/i386/boot/setup.ld b/arch/i386/boot/setup.ld
new file mode 100644
index 00000000000..df9234b3a5e
--- /dev/null
+++ b/arch/i386/boot/setup.ld
@@ -0,0 +1,54 @@
+/*
+ * setup.ld
+ *
+ * Linker script for the i386 setup code
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = 0;
+ .bstext : { *(.bstext) }
+ .bsdata : { *(.bsdata) }
+
+ . = 497;
+ .header : { *(.header) }
+ .inittext : { *(.inittext) }
+ .initdata : { *(.initdata) }
+ .text : { *(.text*) }
+
+ . = ALIGN(16);
+ .rodata : { *(.rodata*) }
+
+ .videocards : {
+ video_cards = .;
+ *(.videocards)
+ video_cards_end = .;
+ }
+
+ . = ALIGN(16);
+ .data : { *(.data*) }
+
+ .signature : {
+ setup_sig = .;
+ LONG(0x5a5aaa55)
+ }
+
+
+ . = ALIGN(16);
+ .bss :
+ {
+ __bss_start = .;
+ *(.bss)
+ __bss_end = .;
+ }
+ . = ALIGN(16);
+ _end = .;
+
+ /DISCARD/ : { *(.note*) }
+
+ . = ASSERT(_end <= 0x8000, "Setup too big!");
+ . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!");
+}
diff --git a/arch/i386/boot/string.c b/arch/i386/boot/string.c
new file mode 100644
index 00000000000..481a2209778
--- /dev/null
+++ b/arch/i386/boot/string.c
@@ -0,0 +1,52 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/string.c
+ *
+ * Very basic string functions
+ */
+
+#include "boot.h"
+
+int strcmp(const char *str1, const char *str2)
+{
+ const unsigned char *s1 = (const unsigned char *)str1;
+ const unsigned char *s2 = (const unsigned char *)str2;
+ int delta = 0;
+
+ while (*s1 || *s2) {
+ delta = *s2 - *s1;
+ if (delta)
+ return delta;
+ s1++;
+ s2++;
+ }
+ return 0;
+}
+
+size_t strnlen(const char *s, size_t maxlen)
+{
+ const char *es = s;
+ while (*es && maxlen) {
+ es++;
+ maxlen--;
+ }
+
+ return (es - s);
+}
+
+unsigned int atou(const char *s)
+{
+ unsigned int i = 0;
+ while (isdigit(*s))
+ i = i * 10 + (*s++ - '0');
+ return i;
+}
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
index 05798419a6a..886f47d8a48 100644
--- a/arch/i386/boot/tools/build.c
+++ b/arch/i386/boot/tools/build.c
@@ -1,13 +1,12 @@
/*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1997 Martin Mares
+ * Copyright (C) 2007 H. Peter Anvin
*/
/*
* This file builds a disk-image from three different files:
*
- * - bootsect: compatibility mbr which prints an error message if
- * someone tries to boot the kernel directly.
* - setup: 8086 machine code, sets up system parm
* - system: 80386 code for actual system
*
@@ -21,6 +20,7 @@
* High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
* Cross compiling fixes by Gertjan van Wingerde, July 1996
* Rewritten by Martin Mares, April 1997
+ * Substantially overhauled by H. Peter Anvin, April 2007
*/
#include <stdio.h>
@@ -32,23 +32,25 @@
#include <sys/sysmacros.h>
#include <unistd.h>
#include <fcntl.h>
+#include <sys/mman.h>
#include <asm/boot.h>
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long u32;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
#define DEFAULT_MAJOR_ROOT 0
#define DEFAULT_MINOR_ROOT 0
-/* Minimal number of setup sectors (see also bootsect.S) */
-#define SETUP_SECTS 4
+/* Minimal number of setup sectors */
+#define SETUP_SECT_MIN 5
+#define SETUP_SECT_MAX 64
-byte buf[1024];
-int fd;
+/* This must be large enough to hold the entire setup */
+u8 buf[SETUP_SECT_MAX*512];
int is_big_kernel;
-void die(const char * str, ...)
+static void die(const char * str, ...)
{
va_list args;
va_start(args, str);
@@ -57,15 +59,9 @@ void die(const char * str, ...)
exit(1);
}
-void file_open(const char *name)
+static void usage(void)
{
- if ((fd = open(name, O_RDONLY, 0)) < 0)
- die("Unable to open `%s': %m", name);
-}
-
-void usage(void)
-{
- die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
+ die("Usage: build [-b] setup system [rootdev] [> image]");
}
int main(int argc, char ** argv)
@@ -73,27 +69,30 @@ int main(int argc, char ** argv)
unsigned int i, sz, setup_sectors;
int c;
u32 sys_size;
- byte major_root, minor_root;
+ u8 major_root, minor_root;
struct stat sb;
+ FILE *file;
+ int fd;
+ void *kernel;
if (argc > 2 && !strcmp(argv[1], "-b"))
{
is_big_kernel = 1;
argc--, argv++;
}
- if ((argc < 4) || (argc > 5))
+ if ((argc < 3) || (argc > 4))
usage();
- if (argc > 4) {
- if (!strcmp(argv[4], "CURRENT")) {
+ if (argc > 3) {
+ if (!strcmp(argv[3], "CURRENT")) {
if (stat("/", &sb)) {
perror("/");
die("Couldn't stat /");
}
major_root = major(sb.st_dev);
minor_root = minor(sb.st_dev);
- } else if (strcmp(argv[4], "FLOPPY")) {
- if (stat(argv[4], &sb)) {
- perror(argv[4]);
+ } else if (strcmp(argv[3], "FLOPPY")) {
+ if (stat(argv[3], &sb)) {
+ perror(argv[3]);
die("Couldn't stat root device.");
}
major_root = major(sb.st_rdev);
@@ -108,79 +107,62 @@ int main(int argc, char ** argv)
}
fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
- file_open(argv[1]);
- i = read(fd, buf, sizeof(buf));
- fprintf(stderr,"Boot sector %d bytes.\n",i);
- if (i != 512)
- die("Boot block must be exactly 512 bytes");
+ /* Copy the setup code */
+ file = fopen(argv[1], "r");
+ if (!file)
+ die("Unable to open `%s': %m", argv[1]);
+ c = fread(buf, 1, sizeof(buf), file);
+ if (ferror(file))
+ die("read-error on `setup'");
+ if (c < 1024)
+ die("The setup must be at least 1024 bytes");
if (buf[510] != 0x55 || buf[511] != 0xaa)
die("Boot block hasn't got boot flag (0xAA55)");
+ fclose(file);
+
+ /* Pad unused space with zeros */
+ setup_sectors = (c + 511) / 512;
+ if (setup_sectors < SETUP_SECT_MIN)
+ setup_sectors = SETUP_SECT_MIN;
+ i = setup_sectors*512;
+ memset(buf+c, 0, i-c);
+
+ /* Set the default root device */
buf[508] = minor_root;
buf[509] = major_root;
- if (write(1, buf, 512) != 512)
- die("Write call failed");
- close (fd);
-
- file_open(argv[2]); /* Copy the setup code */
- for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
- if (write(1, buf, c) != c)
- die("Write call failed");
- if (c != 0)
- die("read-error on `setup'");
- close (fd);
-
- setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */
- /* for compatibility with ancient versions of LILO. */
- if (setup_sectors < SETUP_SECTS)
- setup_sectors = SETUP_SECTS;
- fprintf(stderr, "Setup is %d bytes.\n", i);
- memset(buf, 0, sizeof(buf));
- while (i < setup_sectors * 512) {
- c = setup_sectors * 512 - i;
- if (c > sizeof(buf))
- c = sizeof(buf);
- if (write(1, buf, c) != c)
- die("Write call failed");
- i += c;
- }
- file_open(argv[3]);
- if (fstat (fd, &sb))
- die("Unable to stat `%s': %m", argv[3]);
+ fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i);
+
+ /* Open and stat the kernel file */
+ fd = open(argv[2], O_RDONLY);
+ if (fd < 0)
+ die("Unable to open `%s': %m", argv[2]);
+ if (fstat(fd, &sb))
+ die("Unable to stat `%s': %m", argv[2]);
sz = sb.st_size;
- fprintf (stderr, "System is %d kB\n", sz/1024);
+ fprintf (stderr, "System is %d kB\n", (sz+1023)/1024);
+ kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
+ if (kernel == MAP_FAILED)
+ die("Unable to mmap '%s': %m", argv[2]);
sys_size = (sz + 15) / 16;
if (!is_big_kernel && sys_size > DEF_SYSSIZE)
die("System is too big. Try using bzImage or modules.");
- while (sz > 0) {
- int l, n;
-
- l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
- if ((n=read(fd, buf, l)) != l) {
- if (n < 0)
- die("Error reading %s: %m", argv[3]);
- else
- die("%s: Unexpected EOF", argv[3]);
- }
- if (write(1, buf, l) != l)
- die("Write failed");
- sz -= l;
- }
+
+ /* Patch the setup code with the appropriate size parameters */
+ buf[0x1f1] = setup_sectors-1;
+ buf[0x1f4] = sys_size;
+ buf[0x1f5] = sys_size >> 8;
+ buf[0x1f6] = sys_size >> 16;
+ buf[0x1f7] = sys_size >> 24;
+
+ if (fwrite(buf, 1, i, stdout) != i)
+ die("Writing setup failed");
+
+ /* Copy the kernel code */
+ if (fwrite(kernel, 1, sz, stdout) != sz)
+ die("Writing kernel failed");
close(fd);
- if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */
- die("Output: seek failed");
- buf[0] = setup_sectors;
- if (write(1, buf, 1) != 1)
- die("Write of setup sector count failed");
- if (lseek(1, 500, SEEK_SET) != 500)
- die("Output: seek failed");
- buf[0] = (sys_size & 0xff);
- buf[1] = ((sys_size >> 8) & 0xff);
- buf[2] = ((sys_size >> 16) & 0xff);
- buf[3] = ((sys_size >> 24) & 0xff);
- if (write(1, buf, 4) != 4)
- die("Write of image length failed");
-
- return 0; /* Everything is OK */
+ /* Everything is OK */
+ return 0;
}
diff --git a/arch/i386/boot/tty.c b/arch/i386/boot/tty.c
new file mode 100644
index 00000000000..a8db78736b0
--- /dev/null
+++ b/arch/i386/boot/tty.c
@@ -0,0 +1,112 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/tty.c
+ *
+ * Very simple screen I/O
+ * XXX: Probably should add very simple serial I/O?
+ */
+
+#include "boot.h"
+
+/*
+ * These functions are in .inittext so they can be used to signal
+ * error during initialization.
+ */
+
+void __attribute__((section(".inittext"))) putchar(int ch)
+{
+ unsigned char c = ch;
+
+ if (c == '\n')
+ putchar('\r'); /* \n -> \r\n */
+
+ /* int $0x10 is known to have bugs involving touching registers
+ it shouldn't. Be extra conservative... */
+ asm volatile("pushal; int $0x10; popal"
+ : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch));
+}
+
+void __attribute__((section(".inittext"))) puts(const char *str)
+{
+ int n = 0;
+ while (*str) {
+ putchar(*str++);
+ n++;
+ }
+}
+
+/*
+ * Read the CMOS clock through the BIOS, and return the
+ * seconds in BCD.
+ */
+
+static u8 gettime(void)
+{
+ u16 ax = 0x0200;
+ u16 cx, dx;
+
+ asm("int $0x1a"
+ : "+a" (ax), "=c" (cx), "=d" (dx)
+ : : "ebx", "esi", "edi");
+
+ return dx >> 8;
+}
+
+/*
+ * Read from the keyboard
+ */
+int getchar(void)
+{
+ u16 ax = 0;
+ asm("int $0x16" : "+a" (ax));
+
+ return ax & 0xff;
+}
+
+static int kbd_pending(void)
+{
+ u8 pending;
+ asm("int $0x16; setnz %0"
+ : "=rm" (pending)
+ : "a" (0x0100));
+ return pending;
+}
+
+void kbd_flush(void)
+{
+ for (;;) {
+ if (!kbd_pending())
+ break;
+ getchar();
+ }
+}
+
+int getchar_timeout(void)
+{
+ int cnt = 30;
+ int t0, t1;
+
+ t0 = gettime();
+
+ while (cnt) {
+ if (kbd_pending())
+ return getchar();
+
+ t1 = gettime();
+ if (t0 != t1) {
+ cnt--;
+ t0 = t1;
+ }
+ }
+
+ return 0; /* Timeout! */
+}
diff --git a/arch/i386/boot/version.c b/arch/i386/boot/version.c
new file mode 100644
index 00000000000..c61462f7d9a
--- /dev/null
+++ b/arch/i386/boot/version.c
@@ -0,0 +1,23 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/version.c
+ *
+ * Kernel version string
+ */
+
+#include "boot.h"
+#include <linux/utsrelease.h>
+#include <linux/compile.h>
+
+const char kernel_version[] =
+ UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") "
+ UTS_VERSION;
diff --git a/arch/i386/boot/vesa.h b/arch/i386/boot/vesa.h
new file mode 100644
index 00000000000..ff5b73cd406
--- /dev/null
+++ b/arch/i386/boot/vesa.h
@@ -0,0 +1,79 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1999-2007 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef BOOT_VESA_H
+#define BOOT_VESA_H
+
+typedef struct {
+ u16 off, seg;
+} far_ptr;
+
+/* VESA General Information table */
+struct vesa_general_info {
+ u32 signature; /* 0 Magic number = "VESA" */
+ u16 version; /* 4 */
+ far_ptr vendor_string; /* 6 */
+ u32 capabilities; /* 10 */
+ far_ptr video_mode_ptr; /* 14 */
+ u16 total_memory; /* 18 */
+
+ u16 oem_software_rev; /* 20 */
+ far_ptr oem_vendor_name_ptr; /* 22 */
+ far_ptr oem_product_name_ptr; /* 26 */
+ far_ptr oem_product_rev_ptr; /* 30 */
+
+ u8 reserved[222]; /* 34 */
+ u8 oem_data[256]; /* 256 */
+} __attribute__ ((packed));
+
+#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24))
+#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24))
+
+struct vesa_mode_info {
+ u16 mode_attr; /* 0 */
+ u8 win_attr[2]; /* 2 */
+ u16 win_grain; /* 4 */
+ u16 win_size; /* 6 */
+ u16 win_seg[2]; /* 8 */
+ far_ptr win_scheme; /* 12 */
+ u16 logical_scan; /* 16 */
+
+ u16 h_res; /* 18 */
+ u16 v_res; /* 20 */
+ u8 char_width; /* 22 */
+ u8 char_height; /* 23 */
+ u8 memory_planes; /* 24 */
+ u8 bpp; /* 25 */
+ u8 banks; /* 26 */
+ u8 memory_layout; /* 27 */
+ u8 bank_size; /* 28 */
+ u8 image_planes; /* 29 */
+ u8 page_function; /* 30 */
+
+ u8 rmask; /* 31 */
+ u8 rpos; /* 32 */
+ u8 gmask; /* 33 */
+ u8 gpos; /* 34 */
+ u8 bmask; /* 35 */
+ u8 bpos; /* 36 */
+ u8 resv_mask; /* 37 */
+ u8 resv_pos; /* 38 */
+ u8 dcm_info; /* 39 */
+
+ u32 lfb_ptr; /* 40 Linear frame buffer address */
+ u32 offscreen_ptr; /* 44 Offscreen memory address */
+ u16 offscreen_size; /* 48 */
+
+ u8 reserved[206]; /* 50 */
+} __attribute__ ((packed));
+
+#endif /* LIB_SYS_VESA_H */
diff --git a/arch/i386/boot/video-bios.c b/arch/i386/boot/video-bios.c
new file mode 100644
index 00000000000..afea46c500c
--- /dev/null
+++ b/arch/i386/boot/video-bios.c
@@ -0,0 +1,125 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-bios.c
+ *
+ * Standard video BIOS modes
+ *
+ * We have two options for this; silent and scanned.
+ */
+
+#include "boot.h"
+#include "video.h"
+
+__videocard video_bios;
+
+/* Set a conventional BIOS mode */
+static int set_bios_mode(u8 mode);
+
+static int bios_set_mode(struct mode_info *mi)
+{
+ return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS);
+}
+
+static int set_bios_mode(u8 mode)
+{
+ u16 ax;
+ u8 new_mode;
+
+ ax = mode; /* AH=0x00 Set Video Mode */
+ asm volatile(INT10
+ : "+a" (ax)
+ : : "ebx", "ecx", "edx", "esi", "edi");
+
+ ax = 0x0f00; /* Get Current Video Mode */
+ asm volatile(INT10
+ : "+a" (ax)
+ : : "ebx", "ecx", "edx", "esi", "edi");
+
+ do_restore = 1; /* Assume video contents was lost */
+ new_mode = ax & 0x7f; /* Not all BIOSes are clean with the top bit */
+
+ if (new_mode == mode)
+ return 0; /* Mode change OK */
+
+ if (new_mode != boot_params.screen_info.orig_video_mode) {
+ /* Mode setting failed, but we didn't end up where we
+ started. That's bad. Try to revert to the original
+ video mode. */
+ ax = boot_params.screen_info.orig_video_mode;
+ asm volatile(INT10
+ : "+a" (ax)
+ : : "ebx", "ecx", "edx", "esi", "edi");
+ }
+ return -1;
+}
+
+static int bios_probe(void)
+{
+ u8 mode;
+ u8 saved_mode = boot_params.screen_info.orig_video_mode;
+ u16 crtc;
+ struct mode_info *mi;
+ int nmodes = 0;
+
+ if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
+ return 0;
+
+ set_fs(0);
+ crtc = vga_crtc();
+
+ video_bios.modes = GET_HEAP(struct mode_info, 0);
+
+ for (mode = 0x14; mode <= 0x7f; mode++) {
+ if (heap_free() < sizeof(struct mode_info))
+ break;
+
+ if (mode_defined(VIDEO_FIRST_BIOS+mode))
+ continue;
+
+ if (set_bios_mode(mode))
+ continue;
+
+ /* Try to verify that it's a text mode. */
+
+ /* Attribute Controller: make graphics controller disabled */
+ if (in_idx(0x3c0, 0x10) & 0x01)
+ continue;
+
+ /* Graphics Controller: verify Alpha addressing enabled */
+ if (in_idx(0x3ce, 0x06) & 0x01)
+ continue;
+
+ /* CRTC cursor location low should be zero(?) */
+ if (in_idx(crtc, 0x0f))
+ continue;
+
+ mi = GET_HEAP(struct mode_info, 1);
+ mi->mode = VIDEO_FIRST_BIOS+mode;
+ mi->x = rdfs16(0x44a);
+ mi->y = rdfs8(0x484)+1;
+ nmodes++;
+ }
+
+ set_bios_mode(saved_mode);
+
+ return nmodes;
+}
+
+__videocard video_bios =
+{
+ .card_name = "BIOS (scanned)",
+ .probe = bios_probe,
+ .set_mode = bios_set_mode,
+ .unsafe = 1,
+ .xmode_first = VIDEO_FIRST_BIOS,
+ .xmode_n = 0x80,
+};
diff --git a/arch/i386/boot/video-vesa.c b/arch/i386/boot/video-vesa.c
new file mode 100644
index 00000000000..e6aa9eb8d93
--- /dev/null
+++ b/arch/i386/boot/video-vesa.c
@@ -0,0 +1,284 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-vesa.c
+ *
+ * VESA text modes
+ */
+
+#include "boot.h"
+#include "video.h"
+#include "vesa.h"
+
+/* VESA information */
+static struct vesa_general_info vginfo;
+static struct vesa_mode_info vminfo;
+
+__videocard video_vesa;
+
+static void vesa_store_mode_params_graphics(void);
+
+static int vesa_probe(void)
+{
+#if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID)
+ u16 ax;
+ u16 mode;
+ addr_t mode_ptr;
+ struct mode_info *mi;
+ int nmodes = 0;
+
+ video_vesa.modes = GET_HEAP(struct mode_info, 0);
+
+ vginfo.signature = VBE2_MAGIC;
+
+ /* Optimistically assume a VESA BIOS is register-clean... */
+ ax = 0x4f00;
+ asm("int $0x10" : "+a" (ax), "=m" (vginfo) : "D" (&vginfo));
+
+ if (ax != 0x004f ||
+ vginfo.signature != VESA_MAGIC ||
+ vginfo.version < 0x0102)
+ return 0; /* Not present */
+#endif /* CONFIG_VIDEO_VESA || CONFIG_FIRMWARE_EDID */
+#ifdef CONFIG_VIDEO_VESA
+ set_fs(vginfo.video_mode_ptr.seg);
+ mode_ptr = vginfo.video_mode_ptr.off;
+
+ while ((mode = rdfs16(mode_ptr)) != 0xffff) {
+ mode_ptr += 2;
+
+ if (heap_free() < sizeof(struct mode_info))
+ break; /* Heap full, can't save mode info */
+
+ if (mode & ~0x1ff)
+ continue;
+
+ memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
+
+ ax = 0x4f01;
+ asm("int $0x10"
+ : "+a" (ax), "=m" (vminfo)
+ : "c" (mode), "D" (&vminfo));
+
+ if (ax != 0x004f)
+ continue;
+
+ if ((vminfo.mode_attr & 0x15) == 0x05) {
+ /* Text Mode, TTY BIOS supported,
+ supported by hardware */
+ mi = GET_HEAP(struct mode_info, 1);
+ mi->mode = mode + VIDEO_FIRST_VESA;
+ mi->x = vminfo.h_res;
+ mi->y = vminfo.v_res;
+ nmodes++;
+ } else if ((vminfo.mode_attr & 0x99) == 0x99) {
+#ifdef CONFIG_FB
+ /* Graphics mode, color, linear frame buffer
+ supported -- register the mode but hide from
+ the menu. Only do this if framebuffer is
+ configured, however, otherwise the user will
+ be left without a screen. */
+ mi = GET_HEAP(struct mode_info, 1);
+ mi->mode = mode + VIDEO_FIRST_VESA;
+ mi->x = mi->y = 0;
+ nmodes++;
+#endif
+ }
+ }
+
+ return nmodes;
+#else
+ return 0;
+#endif /* CONFIG_VIDEO_VESA */
+}
+
+static int vesa_set_mode(struct mode_info *mode)
+{
+ u16 ax;
+ int is_graphic;
+ u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA;
+
+ memset(&vminfo, 0, sizeof vminfo); /* Just in case... */
+
+ ax = 0x4f01;
+ asm("int $0x10"
+ : "+a" (ax), "=m" (vminfo)
+ : "c" (vesa_mode), "D" (&vminfo));
+
+ if (ax != 0x004f)
+ return -1;
+
+ if ((vminfo.mode_attr & 0x15) == 0x05) {
+ /* It's a supported text mode */
+ is_graphic = 0;
+ } else if ((vminfo.mode_attr & 0x99) == 0x99) {
+ /* It's a graphics mode with linear frame buffer */
+ is_graphic = 1;
+ vesa_mode |= 0x4000; /* Request linear frame buffer */
+ } else {
+ return -1; /* Invalid mode */
+ }
+
+
+ ax = 0x4f02;
+ asm volatile("int $0x10"
+ : "+a" (ax)
+ : "b" (vesa_mode), "D" (0));
+
+ if (ax != 0x004f)
+ return -1;
+
+ graphic_mode = is_graphic;
+ if (!is_graphic) {
+ /* Text mode */
+ force_x = mode->x;
+ force_y = mode->y;
+ do_restore = 1;
+ } else {
+ /* Graphics mode */
+ vesa_store_mode_params_graphics();
+ }
+
+ return 0;
+}
+
+
+/* Switch DAC to 8-bit mode */
+static void vesa_dac_set_8bits(void)
+{
+ u8 dac_size = 6;
+
+ /* If possible, switch the DAC to 8-bit mode */
+ if (vginfo.capabilities & 1) {
+ u16 ax, bx;
+
+ ax = 0x4f08;
+ bx = 0x0800;
+ asm volatile(INT10
+ : "+a" (ax), "+b" (bx)
+ : : "ecx", "edx", "esi", "edi");
+
+ if (ax == 0x004f)
+ dac_size = bx >> 8;
+ }
+
+ /* Set the color sizes to the DAC size, and offsets to 0 */
+ boot_params.screen_info.red_size = dac_size;
+ boot_params.screen_info.green_size = dac_size;
+ boot_params.screen_info.blue_size = dac_size;
+ boot_params.screen_info.rsvd_size = dac_size;
+
+ boot_params.screen_info.red_pos = 0;
+ boot_params.screen_info.green_pos = 0;
+ boot_params.screen_info.blue_pos = 0;
+ boot_params.screen_info.rsvd_pos = 0;
+}
+
+/* Save the VESA protected mode info */
+static void vesa_store_pm_info(void)
+{
+ u16 ax, bx, di, es;
+
+ ax = 0x4f0a;
+ bx = di = 0;
+ asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es"
+ : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di)
+ : : "ecx", "esi");
+
+ if (ax != 0x004f)
+ return;
+
+ boot_params.screen_info.vesapm_seg = es;
+ boot_params.screen_info.vesapm_off = di;
+}
+
+/*
+ * Save video mode parameters for graphics mode
+ */
+static void vesa_store_mode_params_graphics(void)
+{
+ /* Tell the kernel we're in VESA graphics mode */
+ boot_params.screen_info.orig_video_isVGA = 0x23;
+
+ /* Mode parameters */
+ boot_params.screen_info.vesa_attributes = vminfo.mode_attr;
+ boot_params.screen_info.lfb_linelength = vminfo.logical_scan;
+ boot_params.screen_info.lfb_width = vminfo.h_res;
+ boot_params.screen_info.lfb_height = vminfo.v_res;
+ boot_params.screen_info.lfb_depth = vminfo.bpp;
+ boot_params.screen_info.pages = vminfo.image_planes;
+ boot_params.screen_info.lfb_base = vminfo.lfb_ptr;
+ memcpy(&boot_params.screen_info.red_size,
+ &vminfo.rmask, 8);
+
+ /* General parameters */
+ boot_params.screen_info.lfb_size = vginfo.total_memory;
+
+ if (vminfo.bpp <= 8)
+ vesa_dac_set_8bits();
+
+ vesa_store_pm_info();
+}
+
+/*
+ * Save EDID information for the kernel; this is invoked, separately,
+ * after mode-setting.
+ */
+void vesa_store_edid(void)
+{
+#ifdef CONFIG_FIRMWARE_EDID
+ u16 ax, bx, cx, dx, di;
+
+ /* Apparently used as a nonsense token... */
+ memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info);
+
+ if (vginfo.version < 0x0200)
+ return; /* EDID requires VBE 2.0+ */
+
+ ax = 0x4f15; /* VBE DDC */
+ bx = 0x0000; /* Report DDC capabilities */
+ cx = 0; /* Controller 0 */
+ di = 0; /* ES:DI must be 0 by spec */
+
+ /* Note: The VBE DDC spec is different from the main VESA spec;
+ we genuinely have to assume all registers are destroyed here. */
+
+ asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es"
+ : "+a" (ax), "+b" (bx)
+ : "c" (cx), "D" (di)
+ : "esi");
+
+ if (ax != 0x004f)
+ return; /* No EDID */
+
+ /* BH = time in seconds to transfer EDD information */
+ /* BL = DDC level supported */
+
+ ax = 0x4f15; /* VBE DDC */
+ bx = 0x0001; /* Read EDID */
+ cx = 0; /* Controller 0 */
+ dx = 0; /* EDID block number */
+ di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */
+ asm(INT10
+ : "+a" (ax), "+b" (bx), "+d" (dx)
+ : "c" (cx), "D" (di)
+ : "esi");
+#endif /* CONFIG_FIRMWARE_EDID */
+}
+
+__videocard video_vesa =
+{
+ .card_name = "VESA",
+ .probe = vesa_probe,
+ .set_mode = vesa_set_mode,
+ .xmode_first = VIDEO_FIRST_VESA,
+ .xmode_n = 0x200,
+};
diff --git a/arch/i386/boot/video-vga.c b/arch/i386/boot/video-vga.c
new file mode 100644
index 00000000000..700d09a9c9b
--- /dev/null
+++ b/arch/i386/boot/video-vga.c
@@ -0,0 +1,260 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video-vga.c
+ *
+ * Common all-VGA modes
+ */
+
+#include "boot.h"
+#include "video.h"
+
+static struct mode_info vga_modes[] = {
+ { VIDEO_80x25, 80, 25 },
+ { VIDEO_8POINT, 80, 50 },
+ { VIDEO_80x43, 80, 43 },
+ { VIDEO_80x28, 80, 28 },
+ { VIDEO_80x30, 80, 30 },
+ { VIDEO_80x34, 80, 34 },
+ { VIDEO_80x60, 80, 60 },
+};
+
+static struct mode_info ega_modes[] = {
+ { VIDEO_80x25, 80, 25 },
+ { VIDEO_8POINT, 80, 43 },
+};
+
+static struct mode_info cga_modes[] = {
+ { VIDEO_80x25, 80, 25 },
+};
+
+__videocard video_vga;
+
+/* Set basic 80x25 mode */
+static u8 vga_set_basic_mode(void)
+{
+ u16 ax;
+ u8 rows;
+ u8 mode;
+
+#ifdef CONFIG_VIDEO_400_HACK
+ if (adapter >= ADAPTER_VGA) {
+ asm(INT10
+ : : "a" (0x1202), "b" (0x0030)
+ : "ecx", "edx", "esi", "edi");
+ }
+#endif
+
+ ax = 0x0f00;
+ asm(INT10
+ : "+a" (ax)
+ : : "ebx", "ecx", "edx", "esi", "edi");
+
+ mode = (u8)ax;
+
+ set_fs(0);
+ rows = rdfs8(0x484); /* rows minus one */
+
+#ifndef CONFIG_VIDEO_400_HACK
+ if ((ax == 0x5003 || ax == 0x5007) &&
+ (rows == 0 || rows == 24))
+ return mode;
+#endif
+
+ if (mode != 3 && mode != 7)
+ mode = 3;
+
+ /* Set the mode */
+ asm volatile(INT10
+ : : "a" (mode)
+ : "ebx", "ecx", "edx", "esi", "edi");
+ do_restore = 1;
+ return mode;
+}
+
+static void vga_set_8font(void)
+{
+ /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */
+
+ /* Set 8x8 font */
+ asm volatile(INT10 : : "a" (0x1112), "b" (0));
+
+ /* Use alternate print screen */
+ asm volatile(INT10 : : "a" (0x1200), "b" (0x20));
+
+ /* Turn off cursor emulation */
+ asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+
+ /* Cursor is scan lines 6-7 */
+ asm volatile(INT10 : : "a" (0x0100), "c" (0x0607));
+}
+
+static void vga_set_14font(void)
+{
+ /* Set 9x14 font - 80x28 on VGA */
+
+ /* Set 9x14 font */
+ asm volatile(INT10 : : "a" (0x1111), "b" (0));
+
+ /* Turn off cursor emulation */
+ asm volatile(INT10 : : "a" (0x1201), "b" (0x34));
+
+ /* Cursor is scan lines 11-12 */
+ asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c));
+}
+
+static void vga_set_80x43(void)
+{
+ /* Set 80x43 mode on VGA (not EGA) */
+
+ /* Set 350 scans */
+ asm volatile(INT10 : : "a" (0x1201), "b" (0x30));
+
+ /* Reset video mode */
+ asm volatile(INT10 : : "a" (0x0003));
+
+ vga_set_8font();
+}
+
+/* I/O address of the VGA CRTC */
+u16 vga_crtc(void)
+{
+ return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4;
+}
+
+static void vga_set_480_scanlines(int end)
+{
+ u16 crtc;
+ u8 csel;
+
+ crtc = vga_crtc();
+
+ out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */
+ out_idx(0x0b, crtc, 0x06); /* Vertical total */
+ out_idx(0x3e, crtc, 0x07); /* Vertical overflow */
+ out_idx(0xea, crtc, 0x10); /* Vertical sync start */
+ out_idx(end, crtc, 0x12); /* Vertical display end */
+ out_idx(0xe7, crtc, 0x15); /* Vertical blank start */
+ out_idx(0x04, crtc, 0x16); /* Vertical blank end */
+ csel = inb(0x3cc);
+ csel &= 0x0d;
+ csel |= 0xe2;
+ outb(csel, 0x3cc);
+}
+
+static void vga_set_80x30(void)
+{
+ vga_set_480_scanlines(0xdf);
+}
+
+static void vga_set_80x34(void)
+{
+ vga_set_14font();
+ vga_set_480_scanlines(0xdb);
+}
+
+static void vga_set_80x60(void)
+{
+ vga_set_8font();
+ vga_set_480_scanlines(0xdf);
+}
+
+static int vga_set_mode(struct mode_info *mode)
+{
+ /* Set the basic mode */
+ vga_set_basic_mode();
+
+ /* Override a possibly broken BIOS */
+ force_x = mode->x;
+ force_y = mode->y;
+
+ switch (mode->mode) {
+ case VIDEO_80x25:
+ break;
+ case VIDEO_8POINT:
+ vga_set_8font();
+ break;
+ case VIDEO_80x43:
+ vga_set_80x43();
+ break;
+ case VIDEO_80x28:
+ vga_set_14font();
+ break;
+ case VIDEO_80x30:
+ vga_set_80x30();
+ break;
+ case VIDEO_80x34:
+ vga_set_80x34();
+ break;
+ case VIDEO_80x60:
+ vga_set_80x60();
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Note: this probe includes basic information required by all
+ * systems. It should be executed first, by making sure
+ * video-vga.c is listed first in the Makefile.
+ */
+static int vga_probe(void)
+{
+ static const char *card_name[] = {
+ "CGA/MDA/HGC", "EGA", "VGA"
+ };
+ static struct mode_info *mode_lists[] = {
+ cga_modes,
+ ega_modes,
+ vga_modes,
+ };
+ static int mode_count[] = {
+ sizeof(cga_modes)/sizeof(struct mode_info),
+ sizeof(ega_modes)/sizeof(struct mode_info),
+ sizeof(vga_modes)/sizeof(struct mode_info),
+ };
+ u8 vga_flag;
+
+ asm(INT10
+ : "=b" (boot_params.screen_info.orig_video_ega_bx)
+ : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
+ : "ecx", "edx", "esi", "edi");
+
+ /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
+ if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) {
+ /* EGA/VGA */
+ asm(INT10
+ : "=a" (vga_flag)
+ : "a" (0x1a00)
+ : "ebx", "ecx", "edx", "esi", "edi");
+
+ if (vga_flag == 0x1a) {
+ adapter = ADAPTER_VGA;
+ boot_params.screen_info.orig_video_isVGA = 1;
+ } else {
+ adapter = ADAPTER_EGA;
+ }
+ } else {
+ adapter = ADAPTER_CGA;
+ }
+
+ video_vga.modes = mode_lists[adapter];
+ video_vga.card_name = card_name[adapter];
+ return mode_count[adapter];
+}
+
+__videocard video_vga =
+{
+ .card_name = "VGA",
+ .probe = vga_probe,
+ .set_mode = vga_set_mode,
+};
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
deleted file mode 100644
index 8143c9516cb..00000000000
--- a/arch/i386/boot/video.S
+++ /dev/null
@@ -1,2043 +0,0 @@
-/* video.S
- *
- * Display adapter & video mode setup, version 2.13 (14-May-99)
- *
- * Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz>
- * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
- *
- * Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999
- *
- * For further information, look at Documentation/svga.txt.
- *
- */
-
-/* Enable autodetection of SVGA adapters and modes. */
-#undef CONFIG_VIDEO_SVGA
-
-/* Enable autodetection of VESA modes */
-#define CONFIG_VIDEO_VESA
-
-/* Enable compacting of mode table */
-#define CONFIG_VIDEO_COMPACT
-
-/* Retain screen contents when switching modes */
-#define CONFIG_VIDEO_RETAIN
-
-/* Enable local mode list */
-#undef CONFIG_VIDEO_LOCAL
-
-/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
-#undef CONFIG_VIDEO_400_HACK
-
-/* Hack that lets you force specific BIOS mode ID and specific dimensions */
-#undef CONFIG_VIDEO_GFX_HACK
-#define VIDEO_GFX_BIOS_AX 0x4f02 /* 800x600 on ThinkPad */
-#define VIDEO_GFX_BIOS_BX 0x0102
-#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425 /* 100x37 */
-
-/* This code uses an extended set of video mode numbers. These include:
- * Aliases for standard modes
- * NORMAL_VGA (-1)
- * EXTENDED_VGA (-2)
- * ASK_VGA (-3)
- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
- * of compatibility when extending the table. These are between 0x00 and 0xff.
- */
-#define VIDEO_FIRST_MENU 0x0000
-
-/* Standard BIOS video modes (BIOS number + 0x0100) */
-#define VIDEO_FIRST_BIOS 0x0100
-
-/* VESA BIOS video modes (VESA number + 0x0200) */
-#define VIDEO_FIRST_VESA 0x0200
-
-/* Video7 special modes (BIOS number + 0x0900) */
-#define VIDEO_FIRST_V7 0x0900
-
-/* Special video modes */
-#define VIDEO_FIRST_SPECIAL 0x0f00
-#define VIDEO_80x25 0x0f00
-#define VIDEO_8POINT 0x0f01
-#define VIDEO_80x43 0x0f02
-#define VIDEO_80x28 0x0f03
-#define VIDEO_CURRENT_MODE 0x0f04
-#define VIDEO_80x30 0x0f05
-#define VIDEO_80x34 0x0f06
-#define VIDEO_80x60 0x0f07
-#define VIDEO_GFX_HACK 0x0f08
-#define VIDEO_LAST_SPECIAL 0x0f09
-
-/* Video modes given by resolution */
-#define VIDEO_FIRST_RESOLUTION 0x1000
-
-/* The "recalculate timings" flag */
-#define VIDEO_RECALC 0x8000
-
-/* Positions of various video parameters passed to the kernel */
-/* (see also include/linux/tty.h) */
-#define PARAM_CURSOR_POS 0x00
-#define PARAM_VIDEO_PAGE 0x04
-#define PARAM_VIDEO_MODE 0x06
-#define PARAM_VIDEO_COLS 0x07
-#define PARAM_VIDEO_EGA_BX 0x0a
-#define PARAM_VIDEO_LINES 0x0e
-#define PARAM_HAVE_VGA 0x0f
-#define PARAM_FONT_POINTS 0x10
-
-#define PARAM_LFB_WIDTH 0x12
-#define PARAM_LFB_HEIGHT 0x14
-#define PARAM_LFB_DEPTH 0x16
-#define PARAM_LFB_BASE 0x18
-#define PARAM_LFB_SIZE 0x1c
-#define PARAM_LFB_LINELENGTH 0x24
-#define PARAM_LFB_COLORS 0x26
-#define PARAM_VESAPM_SEG 0x2e
-#define PARAM_VESAPM_OFF 0x30
-#define PARAM_LFB_PAGES 0x32
-#define PARAM_VESA_ATTRIB 0x34
-#define PARAM_CAPABILITIES 0x36
-
-/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
-#ifdef CONFIG_VIDEO_RETAIN
-#define DO_STORE call store_screen
-#else
-#define DO_STORE
-#endif /* CONFIG_VIDEO_RETAIN */
-
-# This is the main entry point called by setup.S
-# %ds *must* be pointing to the bootsector
-video: pushw %ds # We use different segments
- pushw %ds # FS contains original DS
- popw %fs
- pushw %cs # DS is equal to CS
- popw %ds
- pushw %cs # ES is equal to CS
- popw %es
- xorw %ax, %ax
- movw %ax, %gs # GS is zero
- cld
- call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA)
-#ifdef CONFIG_VIDEO_SELECT
- movw %fs:(0x01fa), %ax # User selected video mode
- cmpw $ASK_VGA, %ax # Bring up the menu
- jz vid2
-
- call mode_set # Set the mode
- jc vid1
-
- leaw badmdt, %si # Invalid mode ID
- call prtstr
-vid2: call mode_menu
-vid1:
-#ifdef CONFIG_VIDEO_RETAIN
- call restore_screen # Restore screen contents
-#endif /* CONFIG_VIDEO_RETAIN */
- call store_edid
-#endif /* CONFIG_VIDEO_SELECT */
- call mode_params # Store mode parameters
- popw %ds # Restore original DS
- ret
-
-# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
-basic_detect:
- movb $0, %fs:(PARAM_HAVE_VGA)
- movb $0x12, %ah # Check EGA/VGA
- movb $0x10, %bl
- int $0x10
- movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel
- cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card.
- je basret
-
- incb adapter
- movw $0x1a00, %ax # Check EGA or VGA?
- int $0x10
- cmpb $0x1a, %al # 1a means VGA...
- jne basret # anything else is EGA.
-
- incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA
- incb adapter
-basret: ret
-
-# Store the video mode parameters for later usage by the kernel.
-# This is done by asking the BIOS except for the rows/columns
-# parameters in the default 80x25 mode -- these are set directly,
-# because some very obscure BIOSes supply insane values.
-mode_params:
-#ifdef CONFIG_VIDEO_SELECT
- cmpb $0, graphic_mode
- jnz mopar_gr
-#endif
- movb $0x03, %ah # Read cursor position
- xorb %bh, %bh
- int $0x10
- movw %dx, %fs:(PARAM_CURSOR_POS)
- movb $0x0f, %ah # Read page/mode/width
- int $0x10
- movw %bx, %fs:(PARAM_VIDEO_PAGE)
- movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width
- cmpb $0x7, %al # MDA/HGA => segment differs
- jnz mopar0
-
- movw $0xb000, video_segment
-mopar0: movw %gs:(0x485), %ax # Font size
- movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA)
- movw force_size, %ax # Forced size?
- orw %ax, %ax
- jz mopar1
-
- movb %ah, %fs:(PARAM_VIDEO_COLS)
- movb %al, %fs:(PARAM_VIDEO_LINES)
- ret
-
-mopar1: movb $25, %al
- cmpb $0, adapter # If we are on CGA/MDA/HGA, the
- jz mopar2 # screen must have 25 lines.
-
- movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS
- incb %al # location of max lines.
-mopar2: movb %al, %fs:(PARAM_VIDEO_LINES)
- ret
-
-#ifdef CONFIG_VIDEO_SELECT
-# Fetching of VESA frame buffer parameters
-mopar_gr:
- leaw modelist+1024, %di
- movb $0x23, %fs:(PARAM_HAVE_VGA)
- movw 16(%di), %ax
- movw %ax, %fs:(PARAM_LFB_LINELENGTH)
- movw 18(%di), %ax
- movw %ax, %fs:(PARAM_LFB_WIDTH)
- movw 20(%di), %ax
- movw %ax, %fs:(PARAM_LFB_HEIGHT)
- movb 25(%di), %al
- movb $0, %ah
- movw %ax, %fs:(PARAM_LFB_DEPTH)
- movb 29(%di), %al
- movb $0, %ah
- movw %ax, %fs:(PARAM_LFB_PAGES)
- movl 40(%di), %eax
- movl %eax, %fs:(PARAM_LFB_BASE)
- movl 31(%di), %eax
- movl %eax, %fs:(PARAM_LFB_COLORS)
- movl 35(%di), %eax
- movl %eax, %fs:(PARAM_LFB_COLORS+4)
- movw 0(%di), %ax
- movw %ax, %fs:(PARAM_VESA_ATTRIB)
-
-# get video mem size
- leaw modelist+1024, %di
- movw $0x4f00, %ax
- int $0x10
- xorl %eax, %eax
- movw 18(%di), %ax
- movl %eax, %fs:(PARAM_LFB_SIZE)
-
-# store mode capabilities
- movl 10(%di), %eax
- movl %eax, %fs:(PARAM_CAPABILITIES)
-
-# switching the DAC to 8-bit is for <= 8 bpp only
- movw %fs:(PARAM_LFB_DEPTH), %ax
- cmpw $8, %ax
- jg dac_done
-
-# get DAC switching capability
- xorl %eax, %eax
- movb 10(%di), %al
- testb $1, %al
- jz dac_set
-
-# attempt to switch DAC to 8-bit
- movw $0x4f08, %ax
- movw $0x0800, %bx
- int $0x10
- cmpw $0x004f, %ax
- jne dac_set
- movb %bh, dac_size # store actual DAC size
-
-dac_set:
-# set color size to DAC size
- movb dac_size, %al
- movb %al, %fs:(PARAM_LFB_COLORS+0)
- movb %al, %fs:(PARAM_LFB_COLORS+2)
- movb %al, %fs:(PARAM_LFB_COLORS+4)
- movb %al, %fs:(PARAM_LFB_COLORS+6)
-
-# set color offsets to 0
- movb $0, %fs:(PARAM_LFB_COLORS+1)
- movb $0, %fs:(PARAM_LFB_COLORS+3)
- movb $0, %fs:(PARAM_LFB_COLORS+5)
- movb $0, %fs:(PARAM_LFB_COLORS+7)
-
-dac_done:
-# get protected mode interface informations
- movw $0x4f0a, %ax
- xorw %bx, %bx
- xorw %di, %di
- int $0x10
- cmp $0x004f, %ax
- jnz no_pm
-
- movw %es, %fs:(PARAM_VESAPM_SEG)
- movw %di, %fs:(PARAM_VESAPM_OFF)
-no_pm: ret
-
-# The video mode menu
-mode_menu:
- leaw keymsg, %si # "Return/Space/Timeout" message
- call prtstr
- call flush
-nokey: call getkt
-
- cmpb $0x0d, %al # ENTER ?
- je listm # yes - manual mode selection
-
- cmpb $0x20, %al # SPACE ?
- je defmd1 # no - repeat
-
- call beep
- jmp nokey
-
-defmd1: ret # No mode chosen? Default 80x25
-
-listm: call mode_table # List mode table
-listm0: leaw name_bann, %si # Print adapter name
- call prtstr
- movw card_name, %si
- orw %si, %si
- jnz an2
-
- movb adapter, %al
- leaw old_name, %si
- orb %al, %al
- jz an1
-
- leaw ega_name, %si
- decb %al
- jz an1
-
- leaw vga_name, %si
- jmp an1
-
-an2: call prtstr
- leaw svga_name, %si
-an1: call prtstr
- leaw listhdr, %si # Table header
- call prtstr
- movb $0x30, %dl # DL holds mode number
- leaw modelist, %si
-lm1: cmpw $ASK_VGA, (%si) # End?
- jz lm2
-
- movb %dl, %al # Menu selection number
- call prtchr
- call prtsp2
- lodsw
- call prthw # Mode ID
- call prtsp2
- movb 0x1(%si), %al
- call prtdec # Rows
- movb $0x78, %al # the letter 'x'
- call prtchr
- lodsw
- call prtdec # Columns
- movb $0x0d, %al # New line
- call prtchr
- movb $0x0a, %al
- call prtchr
- incb %dl # Next character
- cmpb $0x3a, %dl
- jnz lm1
-
- movb $0x61, %dl
- jmp lm1
-
-lm2: leaw prompt, %si # Mode prompt
- call prtstr
- leaw edit_buf, %di # Editor buffer
-lm3: call getkey
- cmpb $0x0d, %al # Enter?
- jz lment
-
- cmpb $0x08, %al # Backspace?
- jz lmbs
-
- cmpb $0x20, %al # Printable?
- jc lm3
-
- cmpw $edit_buf+4, %di # Enough space?
- jz lm3
-
- stosb
- call prtchr
- jmp lm3
-
-lmbs: cmpw $edit_buf, %di # Backspace
- jz lm3
-
- decw %di
- movb $0x08, %al
- call prtchr
- call prtspc
- movb $0x08, %al
- call prtchr
- jmp lm3
-
-lment: movb $0, (%di)
- leaw crlft, %si
- call prtstr
- leaw edit_buf, %si
- cmpb $0, (%si) # Empty string = default mode
- jz lmdef
-
- cmpb $0, 1(%si) # One character = menu selection
- jz mnusel
-
- cmpw $0x6373, (%si) # "scan" => mode scanning
- jnz lmhx
-
- cmpw $0x6e61, 2(%si)
- jz lmscan
-
-lmhx: xorw %bx, %bx # Else => mode ID in hex
-lmhex: lodsb
- orb %al, %al
- jz lmuse1
-
- subb $0x30, %al
- jc lmbad
-
- cmpb $10, %al
- jc lmhx1
-
- subb $7, %al
- andb $0xdf, %al
- cmpb $10, %al
- jc lmbad
-
- cmpb $16, %al
- jnc lmbad
-
-lmhx1: shlw $4, %bx
- orb %al, %bl
- jmp lmhex
-
-lmuse1: movw %bx, %ax
- jmp lmuse
-
-mnusel: lodsb # Menu selection
- xorb %ah, %ah
- subb $0x30, %al
- jc lmbad
-
- cmpb $10, %al
- jc lmuse
-
- cmpb $0x61-0x30, %al
- jc lmbad
-
- subb $0x61-0x30-10, %al
- cmpb $36, %al
- jnc lmbad
-
-lmuse: call mode_set
- jc lmdef
-
-lmbad: leaw unknt, %si
- call prtstr
- jmp lm2
-lmscan: cmpb $0, adapter # Scanning only on EGA/VGA
- jz lmbad
-
- movw $0, mt_end # Scanning of modes is
- movb $1, scanning # done as new autodetection.
- call mode_table
- jmp listm0
-lmdef: ret
-
-# Additional parts of mode_set... (relative jumps, you know)
-setv7: # Video7 extended modes
- DO_STORE
- subb $VIDEO_FIRST_V7>>8, %bh
- movw $0x6f05, %ax
- int $0x10
- stc
- ret
-
-_setrec: jmp setrec # Ugly...
-_set_80x25: jmp set_80x25
-
-# Aliases for backward compatibility.
-setalias:
- movw $VIDEO_80x25, %ax
- incw %bx
- jz mode_set
-
- movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
- incw %bx
- jnz setbad # Fall-through!
-
-# Setting of user mode (AX=mode ID) => CF=success
-mode_set:
- movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S
- movw %ax, %bx
- cmpb $0xff, %ah
- jz setalias
-
- testb $VIDEO_RECALC>>8, %ah
- jnz _setrec
-
- cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah
- jnc setres
-
- cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
- jz setspc
-
- cmpb $VIDEO_FIRST_V7>>8, %ah
- jz setv7
-
- cmpb $VIDEO_FIRST_VESA>>8, %ah
- jnc check_vesa
-
- orb %ah, %ah
- jz setmenu
-
- decb %ah
- jz setbios
-
-setbad: clc
- movb $0, do_restore # The screen needn't be restored
- ret
-
-setvesa:
- DO_STORE
- subb $VIDEO_FIRST_VESA>>8, %bh
- movw $0x4f02, %ax # VESA BIOS mode set call
- int $0x10
- cmpw $0x004f, %ax # AL=4f if implemented
- jnz setbad # AH=0 if OK
-
- stc
- ret
-
-setbios:
- DO_STORE
- int $0x10 # Standard BIOS mode set call
- pushw %bx
- movb $0x0f, %ah # Check if really set
- int $0x10
- popw %bx
- cmpb %bl, %al
- jnz setbad
-
- stc
- ret
-
-setspc: xorb %bh, %bh # Set special mode
- cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
- jnc setbad
-
- addw %bx, %bx
- jmp *spec_inits(%bx)
-
-setmenu:
- orb %al, %al # 80x25 is an exception
- jz _set_80x25
-
- pushw %bx # Set mode chosen from menu
- call mode_table # Build the mode table
- popw %ax
- shlw $2, %ax
- addw %ax, %si
- cmpw %di, %si
- jnc setbad
-
- movw (%si), %ax # Fetch mode ID
-_m_s: jmp mode_set
-
-setres: pushw %bx # Set mode chosen by resolution
- call mode_table
- popw %bx
- xchgb %bl, %bh
-setr1: lodsw
- cmpw $ASK_VGA, %ax # End of the list?
- jz setbad
-
- lodsw
- cmpw %bx, %ax
- jnz setr1
-
- movw -4(%si), %ax # Fetch mode ID
- jmp _m_s
-
-check_vesa:
-#ifdef CONFIG_FIRMWARE_EDID
- leaw modelist+1024, %di
- movw $0x4f00, %ax
- int $0x10
- cmpw $0x004f, %ax
- jnz setbad
-
- movw 4(%di), %ax
- movw %ax, vbe_version
-#endif
- leaw modelist+1024, %di
- subb $VIDEO_FIRST_VESA>>8, %bh
- movw %bx, %cx # Get mode information structure
- movw $0x4f01, %ax
- int $0x10
- addb $VIDEO_FIRST_VESA>>8, %bh
- cmpw $0x004f, %ax
- jnz setbad
-
- movb (%di), %al # Check capabilities.
- andb $0x19, %al
- cmpb $0x09, %al
- jz setvesa # This is a text mode
-
- movb (%di), %al # Check capabilities.
- andb $0x99, %al
- cmpb $0x99, %al
- jnz _setbad # Doh! No linear frame buffer.
-
- subb $VIDEO_FIRST_VESA>>8, %bh
- orw $0x4000, %bx # Use linear frame buffer
- movw $0x4f02, %ax # VESA BIOS mode set call
- int $0x10
- cmpw $0x004f, %ax # AL=4f if implemented
- jnz _setbad # AH=0 if OK
-
- movb $1, graphic_mode # flag graphic mode
- movb $0, do_restore # no screen restore
- stc
- ret
-
-_setbad: jmp setbad # Ugly...
-
-# Recalculate vertical display end registers -- this fixes various
-# inconsistencies of extended modes on many adapters. Called when
-# the VIDEO_RECALC flag is set in the mode ID.
-
-setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
- call mode_set
- jnc rct3
-
- movw %gs:(0x485), %ax # Font size in pixels
- movb %gs:(0x484), %bl # Number of rows
- incb %bl
- mulb %bl # Number of visible
- decw %ax # scan lines - 1
- movw $0x3d4, %dx
- movw %ax, %bx
- movb $0x12, %al # Lower 8 bits
- movb %bl, %ah
- outw %ax, %dx
- movb $0x07, %al # Bits 8 and 9 in the overflow register
- call inidx
- xchgb %al, %ah
- andb $0xbd, %ah
- shrb %bh
- jnc rct1
- orb $0x02, %ah
-rct1: shrb %bh
- jnc rct2
- orb $0x40, %ah
-rct2: movb $0x07, %al
- outw %ax, %dx
- stc
-rct3: ret
-
-# Table of routines for setting of the special modes.
-spec_inits:
- .word set_80x25
- .word set_8pixel
- .word set_80x43
- .word set_80x28
- .word set_current
- .word set_80x30
- .word set_80x34
- .word set_80x60
- .word set_gfx
-
-# Set the 80x25 mode. If already set, do nothing.
-set_80x25:
- movw $0x5019, force_size # Override possibly broken BIOS
-use_80x25:
-#ifdef CONFIG_VIDEO_400_HACK
- movw $0x1202, %ax # Force 400 scan lines
- movb $0x30, %bl
- int $0x10
-#else
- movb $0x0f, %ah # Get current mode ID
- int $0x10
- cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
- jz st80 # on CGA/MDA/HGA and is also available on EGAM
-
- cmpw $0x5003, %ax # Unknown mode, force 80x25 color
- jnz force3
-
-st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
- jz set80
-
- movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
- orb %al, %al # Some buggy BIOS'es set 0 rows
- jz set80
-
- cmpb $24, %al # It's hopefully correct
- jz set80
-#endif /* CONFIG_VIDEO_400_HACK */
-force3: DO_STORE
- movw $0x0003, %ax # Forced set
- int $0x10
-set80: stc
- ret
-
-# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
-set_8pixel:
- DO_STORE
- call use_80x25 # The base is 80x25
-set_8pt:
- movw $0x1112, %ax # Use 8x8 font
- xorb %bl, %bl
- int $0x10
- movw $0x1200, %ax # Use alternate print screen
- movb $0x20, %bl
- int $0x10
- movw $0x1201, %ax # Turn off cursor emulation
- movb $0x34, %bl
- int $0x10
- movb $0x01, %ah # Define cursor scan lines 6-7
- movw $0x0607, %cx
- int $0x10
-set_current:
- stc
- ret
-
-# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
-# 80x25 mode with 14-point fonts instead of 16-point.
-set_80x28:
- DO_STORE
- call use_80x25 # The base is 80x25
-set14: movw $0x1111, %ax # Use 9x14 font
- xorb %bl, %bl
- int $0x10
- movb $0x01, %ah # Define cursor scan lines 11-12
- movw $0x0b0c, %cx
- int $0x10
- stc
- ret
-
-# Set the 80x43 mode. This mode is works on all VGA's.
-# It's a 350-scanline mode with 8-pixel font.
-set_80x43:
- DO_STORE
- movw $0x1201, %ax # Set 350 scans
- movb $0x30, %bl
- int $0x10
- movw $0x0003, %ax # Reset video mode
- int $0x10
- jmp set_8pt # Use 8-pixel font
-
-# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
-set_80x30:
- call use_80x25 # Start with real 80x25
- DO_STORE
- movw $0x3cc, %dx # Get CRTC port
- inb %dx, %al
- movb $0xd4, %dl
- rorb %al # Mono or color?
- jc set48a
-
- movb $0xb4, %dl
-set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
- call outidx
- movw $0x0b06, %ax # Vertical total
- call outidx
- movw $0x3e07, %ax # (Vertical) overflow
- call outidx
- movw $0xea10, %ax # Vertical sync start
- call outidx
- movw $0xdf12, %ax # Vertical display end
- call outidx
- movw $0xe715, %ax # Vertical blank start
- call outidx
- movw $0x0416, %ax # Vertical blank end
- call outidx
- pushw %dx
- movb $0xcc, %dl # Misc output register (read)
- inb %dx, %al
- movb $0xc2, %dl # (write)
- andb $0x0d, %al # Preserve clock select bits and color bit
- orb $0xe2, %al # Set correct sync polarity
- outb %al, %dx
- popw %dx
- movw $0x501e, force_size
- stc # That's all.
- ret
-
-# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
-set_80x34:
- call set_80x30 # Set 480 scans
- call set14 # And 14-pt font
- movw $0xdb12, %ax # VGA vertical display end
- movw $0x5022, force_size
-setvde: call outidx
- stc
- ret
-
-# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
-set_80x60:
- call set_80x30 # Set 480 scans
- call set_8pt # And 8-pt font
- movw $0xdf12, %ax # VGA vertical display end
- movw $0x503c, force_size
- jmp setvde
-
-# Special hack for ThinkPad graphics
-set_gfx:
-#ifdef CONFIG_VIDEO_GFX_HACK
- movw $VIDEO_GFX_BIOS_AX, %ax
- movw $VIDEO_GFX_BIOS_BX, %bx
- int $0x10
- movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
- stc
-#endif
- ret
-
-#ifdef CONFIG_VIDEO_RETAIN
-
-# Store screen contents to temporary buffer.
-store_screen:
- cmpb $0, do_restore # Already stored?
- jnz stsr
-
- testb $CAN_USE_HEAP, loadflags # Have we space for storing?
- jz stsr
-
- pushw %ax
- pushw %bx
- pushw force_size # Don't force specific size
- movw $0, force_size
- call mode_params # Obtain params of current mode
- popw force_size
- movb %fs:(PARAM_VIDEO_LINES), %ah
- movb %fs:(PARAM_VIDEO_COLS), %al
- movw %ax, %bx # BX=dimensions
- mulb %ah
- movw %ax, %cx # CX=number of characters
- addw %ax, %ax # Calculate image size
- addw $modelist+1024+4, %ax
- cmpw heap_end_ptr, %ax
- jnc sts1 # Unfortunately, out of memory
-
- movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
- leaw modelist+1024, %di
- stosw
- movw %bx, %ax
- stosw
- pushw %ds # Store the screen
- movw video_segment, %ds
- xorw %si, %si
- rep
- movsw
- popw %ds
- incb do_restore # Screen will be restored later
-sts1: popw %bx
- popw %ax
-stsr: ret
-
-# Restore screen contents from temporary buffer.
-restore_screen:
- cmpb $0, do_restore # Has the screen been stored?
- jz res1
-
- call mode_params # Get parameters of current mode
- movb %fs:(PARAM_VIDEO_LINES), %cl
- movb %fs:(PARAM_VIDEO_COLS), %ch
- leaw modelist+1024, %si # Screen buffer
- lodsw # Set cursor position
- movw %ax, %dx
- cmpb %cl, %dh
- jc res2
-
- movb %cl, %dh
- decb %dh
-res2: cmpb %ch, %dl
- jc res3
-
- movb %ch, %dl
- decb %dl
-res3: movb $0x02, %ah
- movb $0x00, %bh
- int $0x10
- lodsw # Display size
- movb %ah, %dl # DL=number of lines
- movb $0, %ah # BX=phys. length of orig. line
- movw %ax, %bx
- cmpb %cl, %dl # Too many?
- jc res4
-
- pushw %ax
- movb %dl, %al
- subb %cl, %al
- mulb %bl
- addw %ax, %si
- addw %ax, %si
- popw %ax
- movb %cl, %dl
-res4: cmpb %ch, %al # Too wide?
- jc res5
-
- movb %ch, %al # AX=width of src. line
-res5: movb $0, %cl
- xchgb %ch, %cl
- movw %cx, %bp # BP=width of dest. line
- pushw %es
- movw video_segment, %es
- xorw %di, %di # Move the data
- addw %bx, %bx # Convert BX and BP to _bytes_
- addw %bp, %bp
-res6: pushw %si
- pushw %di
- movw %ax, %cx
- rep
- movsw
- popw %di
- popw %si
- addw %bp, %di
- addw %bx, %si
- decb %dl
- jnz res6
-
- popw %es # Done
-res1: ret
-#endif /* CONFIG_VIDEO_RETAIN */
-
-# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
-outidx: outb %al, %dx
- pushw %ax
- movb %ah, %al
- incw %dx
- outb %al, %dx
- decw %dx
- popw %ax
- ret
-
-# Build the table of video modes (stored after the setup.S code at the
-# `modelist' label. Each video mode record looks like:
-# .word MODE-ID (our special mode ID (see above))
-# .byte rows (number of rows)
-# .byte columns (number of columns)
-# Returns address of the end of the table in DI, the end is marked
-# with a ASK_VGA ID.
-mode_table:
- movw mt_end, %di # Already filled?
- orw %di, %di
- jnz mtab1x
-
- leaw modelist, %di # Store standard modes:
- movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
- stosl
- movb adapter, %al # CGA/MDA/HGA -- no more modes
- orb %al, %al
- jz mtabe
-
- decb %al
- jnz mtabv
-
- movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
- stosl
- jmp mtabe
-
-mtab1x: jmp mtab1
-
-mtabv: leaw vga_modes, %si # All modes for std VGA
- movw $vga_modes_end-vga_modes, %cx
- rep # I'm unable to use movsw as I don't know how to store a half
- movsb # of the expression above to cx without using explicit shr.
-
- cmpb $0, scanning # Mode scan requested?
- jz mscan1
-
- call mode_scan
-mscan1:
-
-#ifdef CONFIG_VIDEO_LOCAL
- call local_modes
-#endif /* CONFIG_VIDEO_LOCAL */
-
-#ifdef CONFIG_VIDEO_VESA
- call vesa_modes # Detect VESA VGA modes
-#endif /* CONFIG_VIDEO_VESA */
-
-#ifdef CONFIG_VIDEO_SVGA
- cmpb $0, scanning # Bypass when scanning
- jnz mscan2
-
- call svga_modes # Detect SVGA cards & modes
-mscan2:
-#endif /* CONFIG_VIDEO_SVGA */
-
-mtabe:
-
-#ifdef CONFIG_VIDEO_COMPACT
- leaw modelist, %si
- movw %di, %dx
- movw %si, %di
-cmt1: cmpw %dx, %si # Scan all modes
- jz cmt2
-
- leaw modelist, %bx # Find in previous entries
- movw 2(%si), %cx
-cmt3: cmpw %bx, %si
- jz cmt4
-
- cmpw 2(%bx), %cx # Found => don't copy this entry
- jz cmt5
-
- addw $4, %bx
- jmp cmt3
-
-cmt4: movsl # Copy entry
- jmp cmt1
-
-cmt5: addw $4, %si # Skip entry
- jmp cmt1
-
-cmt2:
-#endif /* CONFIG_VIDEO_COMPACT */
-
- movw $ASK_VGA, (%di) # End marker
- movw %di, mt_end
-mtab1: leaw modelist, %si # SI=mode list, DI=list end
-ret0: ret
-
-# Modes usable on all standard VGAs
-vga_modes:
- .word VIDEO_8POINT
- .word 0x5032 # 80x50
- .word VIDEO_80x43
- .word 0x502b # 80x43
- .word VIDEO_80x28
- .word 0x501c # 80x28
- .word VIDEO_80x30
- .word 0x501e # 80x30
- .word VIDEO_80x34
- .word 0x5022 # 80x34
- .word VIDEO_80x60
- .word 0x503c # 80x60
-#ifdef CONFIG_VIDEO_GFX_HACK
- .word VIDEO_GFX_HACK
- .word VIDEO_GFX_DUMMY_RESOLUTION
-#endif
-
-vga_modes_end:
-# Detect VESA modes.
-
-#ifdef CONFIG_VIDEO_VESA
-vesa_modes:
- cmpb $2, adapter # VGA only
- jnz ret0
-
- movw %di, %bp # BP=original mode table end
- addw $0x200, %di # Buffer space
- movw $0x4f00, %ax # VESA Get card info call
- int $0x10
- movw %bp, %di
- cmpw $0x004f, %ax # Successful?
- jnz ret0
-
- cmpw $0x4556, 0x200(%di)
- jnz ret0
-
- cmpw $0x4153, 0x202(%di)
- jnz ret0
-
- movw $vesa_name, card_name # Set name to "VESA VGA"
- pushw %gs
- lgsw 0x20e(%di), %si # GS:SI=mode list
- movw $128, %cx # Iteration limit
-vesa1:
-# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
-# XXX: lodsw %gs:(%si), %ax # Get next mode in the list
- gs; lodsw
- cmpw $0xffff, %ax # End of the table?
- jz vesar
-
- cmpw $0x0080, %ax # Check validity of mode ID
- jc vesa2
-
- orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
- jz vesan # Certain BIOSes report 0x80-0xff!
-
- cmpw $0x0800, %ax
- jnc vesae
-
-vesa2: pushw %cx
- movw %ax, %cx # Get mode information structure
- movw $0x4f01, %ax
- int $0x10
- movw %cx, %bx # BX=mode number
- addb $VIDEO_FIRST_VESA>>8, %bh
- popw %cx
- cmpw $0x004f, %ax
- jnz vesan # Don't report errors (buggy BIOSES)
-
- movb (%di), %al # Check capabilities. We require
- andb $0x19, %al # a color text mode.
- cmpb $0x09, %al
- jnz vesan
-
- cmpw $0xb800, 8(%di) # Standard video memory address required
- jnz vesan
-
- testb $2, (%di) # Mode characteristics supplied?
- movw %bx, (%di) # Store mode number
- jz vesa3
-
- xorw %dx, %dx
- movw 0x12(%di), %bx # Width
- orb %bh, %bh
- jnz vesan
-
- movb %bl, 0x3(%di)
- movw 0x14(%di), %ax # Height
- orb %ah, %ah
- jnz vesan
-
- movb %al, 2(%di)
- mulb %bl
- cmpw $8193, %ax # Small enough for Linux console driver?
- jnc vesan
-
- jmp vesaok
-
-vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
- jc vesan # so it must be a standard VESA mode.
-
- cmpw $5, %bx
- jnc vesan
-
- movw vesa_text_mode_table(%bx), %ax
- movw %ax, 2(%di)
-vesaok: addw $4, %di # The mode is valid. Store it.
-vesan: loop vesa1 # Next mode. Limit exceeded => error
-vesae: leaw vesaer, %si
- call prtstr
- movw %bp, %di # Discard already found modes.
-vesar: popw %gs
- ret
-
-# Dimensions of standard VESA text modes
-vesa_text_mode_table:
- .byte 60, 80 # 0108
- .byte 25, 132 # 0109
- .byte 43, 132 # 010A
- .byte 50, 132 # 010B
- .byte 60, 132 # 010C
-#endif /* CONFIG_VIDEO_VESA */
-
-# Scan for video modes. A bit dirty, but should work.
-mode_scan:
- movw $0x0100, %cx # Start with mode 0
-scm1: movb $0, %ah # Test the mode
- movb %cl, %al
- int $0x10
- movb $0x0f, %ah
- int $0x10
- cmpb %cl, %al
- jnz scm2 # Mode not set
-
- movw $0x3c0, %dx # Test if it's a text mode
- movb $0x10, %al # Mode bits
- call inidx
- andb $0x03, %al
- jnz scm2
-
- movb $0xce, %dl # Another set of mode bits
- movb $0x06, %al
- call inidx
- shrb %al
- jc scm2
-
- movb $0xd4, %dl # Cursor location
- movb $0x0f, %al
- call inidx
- orb %al, %al
- jnz scm2
-
- movw %cx, %ax # Ok, store the mode
- stosw
- movb %gs:(0x484), %al # Number of rows
- incb %al
- stosb
- movw %gs:(0x44a), %ax # Number of columns
- stosb
-scm2: incb %cl
- jns scm1
-
- movw $0x0003, %ax # Return back to mode 3
- int $0x10
- ret
-
-tstidx: outw %ax, %dx # OUT DX,AX and inidx
-inidx: outb %al, %dx # Read from indexed VGA register
- incw %dx # AL=index, DX=index reg port -> AL=data
- inb %dx, %al
- decw %dx
- ret
-
-# Try to detect type of SVGA card and supply (usually approximate) video
-# mode table for it.
-
-#ifdef CONFIG_VIDEO_SVGA
-svga_modes:
- leaw svga_table, %si # Test all known SVGA adapters
-dosvga: lodsw
- movw %ax, %bp # Default mode table
- orw %ax, %ax
- jz didsv1
-
- lodsw # Pointer to test routine
- pushw %si
- pushw %di
- pushw %es
- movw $0xc000, %bx
- movw %bx, %es
- call *%ax # Call test routine
- popw %es
- popw %di
- popw %si
- orw %bp, %bp
- jz dosvga
-
- movw %bp, %si # Found, copy the modes
- movb svga_prefix, %ah
-cpsvga: lodsb
- orb %al, %al
- jz didsv
-
- stosw
- movsw
- jmp cpsvga
-
-didsv: movw %si, card_name # Store pointer to card name
-didsv1: ret
-
-# Table of all known SVGA cards. For each card, we store a pointer to
-# a table of video modes supported by the card and a pointer to a routine
-# used for testing of presence of the card. The video mode table is always
-# followed by the name of the card or the chipset.
-svga_table:
- .word ati_md, ati_test
- .word oak_md, oak_test
- .word paradise_md, paradise_test
- .word realtek_md, realtek_test
- .word s3_md, s3_test
- .word chips_md, chips_test
- .word video7_md, video7_test
- .word cirrus5_md, cirrus5_test
- .word cirrus6_md, cirrus6_test
- .word cirrus1_md, cirrus1_test
- .word ahead_md, ahead_test
- .word everex_md, everex_test
- .word genoa_md, genoa_test
- .word trident_md, trident_test
- .word tseng_md, tseng_test
- .word 0
-
-# Test routines and mode tables:
-
-# S3 - The test algorithm was taken from the SuperProbe package
-# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
-s3_test:
- movw $0x0f35, %cx # we store some constants in cl/ch
- movw $0x03d4, %dx
- movb $0x38, %al
- call inidx
- movb %al, %bh # store current CRT-register 0x38
- movw $0x0038, %ax
- call outidx # disable writing to special regs
- movb %cl, %al # check whether we can write special reg 0x35
- call inidx
- movb %al, %bl # save the current value of CRT reg 0x35
- andb $0xf0, %al # clear bits 0-3
- movb %al, %ah
- movb %cl, %al # and write it to CRT reg 0x35
- call outidx
- call inidx # now read it back
- andb %ch, %al # clear the upper 4 bits
- jz s3_2 # the first test failed. But we have a
-
- movb %bl, %ah # second chance
- movb %cl, %al
- call outidx
- jmp s3_1 # do the other tests
-
-s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
- orb %bl, %ah # set the upper 4 bits of ah with the orig value
- call outidx # write ...
- call inidx # ... and reread
- andb %cl, %al # turn off the upper 4 bits
- pushw %ax
- movb %bl, %ah # restore old value in register 0x35
- movb %cl, %al
- call outidx
- popw %ax
- cmpb %ch, %al # setting lower 4 bits was successful => bad
- je no_s3 # writing is allowed => this is not an S3
-
-s3_1: movw $0x4838, %ax # allow writing to special regs by putting
- call outidx # magic number into CRT-register 0x38
- movb %cl, %al # check whether we can write special reg 0x35
- call inidx
- movb %al, %bl
- andb $0xf0, %al
- movb %al, %ah
- movb %cl, %al
- call outidx
- call inidx
- andb %ch, %al
- jnz no_s3 # no, we can't write => no S3
-
- movw %cx, %ax
- orb %bl, %ah
- call outidx
- call inidx
- andb %ch, %al
- pushw %ax
- movb %bl, %ah # restore old value in register 0x35
- movb %cl, %al
- call outidx
- popw %ax
- cmpb %ch, %al
- jne no_s31 # writing not possible => no S3
- movb $0x30, %al
- call inidx # now get the S3 id ...
- leaw idS3, %di
- movw $0x10, %cx
- repne
- scasb
- je no_s31
-
- movb %bh, %ah
- movb $0x38, %al
- jmp s3rest
-
-no_s3: movb $0x35, %al # restore CRT register 0x35
- movb %bl, %ah
- call outidx
-no_s31: xorw %bp, %bp # Detection failed
-s3rest: movb %bh, %ah
- movb $0x38, %al # restore old value of CRT register 0x38
- jmp outidx
-
-idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
- .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
-
-s3_md: .byte 0x54, 0x2b, 0x84
- .byte 0x55, 0x19, 0x84
- .byte 0
- .ascii "S3"
- .byte 0
-
-# ATI cards.
-ati_test:
- leaw idati, %si
- movw $0x31, %di
- movw $0x09, %cx
- repe
- cmpsb
- je atiok
-
- xorw %bp, %bp
-atiok: ret
-
-idati: .ascii "761295520"
-
-ati_md: .byte 0x23, 0x19, 0x84
- .byte 0x33, 0x2c, 0x84
- .byte 0x22, 0x1e, 0x64
- .byte 0x21, 0x19, 0x64
- .byte 0x58, 0x21, 0x50
- .byte 0x5b, 0x1e, 0x50
- .byte 0
- .ascii "ATI"
- .byte 0
-
-# AHEAD
-ahead_test:
- movw $0x200f, %ax
- movw $0x3ce, %dx
- outw %ax, %dx
- incw %dx
- inb %dx, %al
- cmpb $0x20, %al
- je isahed
-
- cmpb $0x21, %al
- je isahed
-
- xorw %bp, %bp
-isahed: ret
-
-ahead_md:
- .byte 0x22, 0x2c, 0x84
- .byte 0x23, 0x19, 0x84
- .byte 0x24, 0x1c, 0x84
- .byte 0x2f, 0x32, 0xa0
- .byte 0x32, 0x22, 0x50
- .byte 0x34, 0x42, 0x50
- .byte 0
- .ascii "Ahead"
- .byte 0
-
-# Chips & Tech.
-chips_test:
- movw $0x3c3, %dx
- inb %dx, %al
- orb $0x10, %al
- outb %al, %dx
- movw $0x104, %dx
- inb %dx, %al
- movb %al, %bl
- movw $0x3c3, %dx
- inb %dx, %al
- andb $0xef, %al
- outb %al, %dx
- cmpb $0xa5, %bl
- je cantok
-
- xorw %bp, %bp
-cantok: ret
-
-chips_md:
- .byte 0x60, 0x19, 0x84
- .byte 0x61, 0x32, 0x84
- .byte 0
- .ascii "Chips & Technologies"
- .byte 0
-
-# Cirrus Logic 5X0
-cirrus1_test:
- movw $0x3d4, %dx
- movb $0x0c, %al
- outb %al, %dx
- incw %dx
- inb %dx, %al
- movb %al, %bl
- xorb %al, %al
- outb %al, %dx
- decw %dx
- movb $0x1f, %al
- outb %al, %dx
- incw %dx
- inb %dx, %al
- movb %al, %bh
- xorb %ah, %ah
- shlb $4, %al
- movw %ax, %cx
- movb %bh, %al
- shrb $4, %al
- addw %ax, %cx
- shlw $8, %cx
- addw $6, %cx
- movw %cx, %ax
- movw $0x3c4, %dx
- outw %ax, %dx
- incw %dx
- inb %dx, %al
- andb %al, %al
- jnz nocirr
-
- movb %bh, %al
- outb %al, %dx
- inb %dx, %al
- cmpb $0x01, %al
- je iscirr
-
-nocirr: xorw %bp, %bp
-iscirr: movw $0x3d4, %dx
- movb %bl, %al
- xorb %ah, %ah
- shlw $8, %ax
- addw $0x0c, %ax
- outw %ax, %dx
- ret
-
-cirrus1_md:
- .byte 0x1f, 0x19, 0x84
- .byte 0x20, 0x2c, 0x84
- .byte 0x22, 0x1e, 0x84
- .byte 0x31, 0x25, 0x64
- .byte 0
- .ascii "Cirrus Logic 5X0"
- .byte 0
-
-# Cirrus Logic 54XX
-cirrus5_test:
- movw $0x3c4, %dx
- movb $6, %al
- call inidx
- movb %al, %bl # BL=backup
- movw $6, %ax
- call tstidx
- cmpb $0x0f, %al
- jne c5fail
-
- movw $0x1206, %ax
- call tstidx
- cmpb $0x12, %al
- jne c5fail
-
- movb $0x1e, %al
- call inidx
- movb %al, %bh
- movb %bh, %ah
- andb $0xc0, %ah
- movb $0x1e, %al
- call tstidx
- andb $0x3f, %al
- jne c5xx
-
- movb $0x1e, %al
- movb %bh, %ah
- orb $0x3f, %ah
- call tstidx
- xorb $0x3f, %al
- andb $0x3f, %al
-c5xx: pushf
- movb $0x1e, %al
- movb %bh, %ah
- outw %ax, %dx
- popf
- je c5done
-
-c5fail: xorw %bp, %bp
-c5done: movb $6, %al
- movb %bl, %ah
- outw %ax, %dx
- ret
-
-cirrus5_md:
- .byte 0x14, 0x19, 0x84
- .byte 0x54, 0x2b, 0x84
- .byte 0
- .ascii "Cirrus Logic 54XX"
- .byte 0
-
-# Cirrus Logic 64XX -- no known extra modes, but must be identified, because
-# it's misidentified by the Ahead test.
-cirrus6_test:
- movw $0x3ce, %dx
- movb $0x0a, %al
- call inidx
- movb %al, %bl # BL=backup
- movw $0xce0a, %ax
- call tstidx
- orb %al, %al
- jne c2fail
-
- movw $0xec0a, %ax
- call tstidx
- cmpb $0x01, %al
- jne c2fail
-
- movb $0xaa, %al
- call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
- shrb $4, %al
- subb $4, %al
- jz c6done
-
- decb %al
- jz c6done
-
- subb $2, %al
- jz c6done
-
- decb %al
- jz c6done
-
-c2fail: xorw %bp, %bp
-c6done: movb $0x0a, %al
- movb %bl, %ah
- outw %ax, %dx
- ret
-
-cirrus6_md:
- .byte 0
- .ascii "Cirrus Logic 64XX"
- .byte 0
-
-# Everex / Trident
-everex_test:
- movw $0x7000, %ax
- xorw %bx, %bx
- int $0x10
- cmpb $0x70, %al
- jne noevrx
-
- shrw $4, %dx
- cmpw $0x678, %dx
- je evtrid
-
- cmpw $0x236, %dx
- jne evrxok
-
-evtrid: leaw trident_md, %bp
-evrxok: ret
-
-noevrx: xorw %bp, %bp
- ret
-
-everex_md:
- .byte 0x03, 0x22, 0x50
- .byte 0x04, 0x3c, 0x50
- .byte 0x07, 0x2b, 0x64
- .byte 0x08, 0x4b, 0x64
- .byte 0x0a, 0x19, 0x84
- .byte 0x0b, 0x2c, 0x84
- .byte 0x16, 0x1e, 0x50
- .byte 0x18, 0x1b, 0x64
- .byte 0x21, 0x40, 0xa0
- .byte 0x40, 0x1e, 0x84
- .byte 0
- .ascii "Everex/Trident"
- .byte 0
-
-# Genoa.
-genoa_test:
- leaw idgenoa, %si # Check Genoa 'clues'
- xorw %ax, %ax
- movb %es:(0x37), %al
- movw %ax, %di
- movw $0x04, %cx
- decw %si
- decw %di
-l1: incw %si
- incw %di
- movb (%si), %al
- testb %al, %al
- jz l2
-
- cmpb %es:(%di), %al
-l2: loope l1
- orw %cx, %cx
- je isgen
-
- xorw %bp, %bp
-isgen: ret
-
-idgenoa: .byte 0x77, 0x00, 0x99, 0x66
-
-genoa_md:
- .byte 0x58, 0x20, 0x50
- .byte 0x5a, 0x2a, 0x64
- .byte 0x60, 0x19, 0x84
- .byte 0x61, 0x1d, 0x84
- .byte 0x62, 0x20, 0x84
- .byte 0x63, 0x2c, 0x84
- .byte 0x64, 0x3c, 0x84
- .byte 0x6b, 0x4f, 0x64
- .byte 0x72, 0x3c, 0x50
- .byte 0x74, 0x42, 0x50
- .byte 0x78, 0x4b, 0x64
- .byte 0
- .ascii "Genoa"
- .byte 0
-
-# OAK
-oak_test:
- leaw idoakvga, %si
- movw $0x08, %di
- movw $0x08, %cx
- repe
- cmpsb
- je isoak
-
- xorw %bp, %bp
-isoak: ret
-
-idoakvga: .ascii "OAK VGA "
-
-oak_md: .byte 0x4e, 0x3c, 0x50
- .byte 0x4f, 0x3c, 0x84
- .byte 0x50, 0x19, 0x84
- .byte 0x51, 0x2b, 0x84
- .byte 0
- .ascii "OAK"
- .byte 0
-
-# WD Paradise.
-paradise_test:
- leaw idparadise, %si
- movw $0x7d, %di
- movw $0x04, %cx
- repe
- cmpsb
- je ispara
-
- xorw %bp, %bp
-ispara: ret
-
-idparadise: .ascii "VGA="
-
-paradise_md:
- .byte 0x41, 0x22, 0x50
- .byte 0x47, 0x1c, 0x84
- .byte 0x55, 0x19, 0x84
- .byte 0x54, 0x2c, 0x84
- .byte 0
- .ascii "Paradise"
- .byte 0
-
-# Trident.
-trident_test:
- movw $0x3c4, %dx
- movb $0x0e, %al
- outb %al, %dx
- incw %dx
- inb %dx, %al
- xchgb %al, %ah
- xorb %al, %al
- outb %al, %dx
- inb %dx, %al
- xchgb %ah, %al
- movb %al, %bl # Strange thing ... in the book this wasn't
- andb $0x02, %bl # necessary but it worked on my card which
- jz setb2 # is a trident. Without it the screen goes
- # blurred ...
- andb $0xfd, %al
- jmp clrb2
-
-setb2: orb $0x02, %al
-clrb2: outb %al, %dx
- andb $0x0f, %ah
- cmpb $0x02, %ah
- je istrid
-
- xorw %bp, %bp
-istrid: ret
-
-trident_md:
- .byte 0x50, 0x1e, 0x50
- .byte 0x51, 0x2b, 0x50
- .byte 0x52, 0x3c, 0x50
- .byte 0x57, 0x19, 0x84
- .byte 0x58, 0x1e, 0x84
- .byte 0x59, 0x2b, 0x84
- .byte 0x5a, 0x3c, 0x84
- .byte 0
- .ascii "Trident"
- .byte 0
-
-# Tseng.
-tseng_test:
- movw $0x3cd, %dx
- inb %dx, %al # Could things be this simple ! :-)
- movb %al, %bl
- movb $0x55, %al
- outb %al, %dx
- inb %dx, %al
- movb %al, %ah
- movb %bl, %al
- outb %al, %dx
- cmpb $0x55, %ah
- je istsen
-
-isnot: xorw %bp, %bp
-istsen: ret
-
-tseng_md:
- .byte 0x26, 0x3c, 0x50
- .byte 0x2a, 0x28, 0x64
- .byte 0x23, 0x19, 0x84
- .byte 0x24, 0x1c, 0x84
- .byte 0x22, 0x2c, 0x84
- .byte 0x21, 0x3c, 0x84
- .byte 0
- .ascii "Tseng"
- .byte 0
-
-# Video7.
-video7_test:
- movw $0x3cc, %dx
- inb %dx, %al
- movw $0x3b4, %dx
- andb $0x01, %al
- jz even7
-
- movw $0x3d4, %dx
-even7: movb $0x0c, %al
- outb %al, %dx
- incw %dx
- inb %dx, %al
- movb %al, %bl
- movb $0x55, %al
- outb %al, %dx
- inb %dx, %al
- decw %dx
- movb $0x1f, %al
- outb %al, %dx
- incw %dx
- inb %dx, %al
- movb %al, %bh
- decw %dx
- movb $0x0c, %al
- outb %al, %dx
- incw %dx
- movb %bl, %al
- outb %al, %dx
- movb $0x55, %al
- xorb $0xea, %al
- cmpb %bh, %al
- jne isnot
-
- movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
- ret
-
-video7_md:
- .byte 0x40, 0x2b, 0x50
- .byte 0x43, 0x3c, 0x50
- .byte 0x44, 0x3c, 0x64
- .byte 0x41, 0x19, 0x84
- .byte 0x42, 0x2c, 0x84
- .byte 0x45, 0x1c, 0x84
- .byte 0
- .ascii "Video 7"
- .byte 0
-
-# Realtek VGA
-realtek_test:
- leaw idrtvga, %si
- movw $0x45, %di
- movw $0x0b, %cx
- repe
- cmpsb
- je isrt
-
- xorw %bp, %bp
-isrt: ret
-
-idrtvga: .ascii "REALTEK VGA"
-
-realtek_md:
- .byte 0x1a, 0x3c, 0x50
- .byte 0x1b, 0x19, 0x84
- .byte 0x1c, 0x1e, 0x84
- .byte 0x1d, 0x2b, 0x84
- .byte 0x1e, 0x3c, 0x84
- .byte 0
- .ascii "REALTEK"
- .byte 0
-
-#endif /* CONFIG_VIDEO_SVGA */
-
-# User-defined local mode table (VGA only)
-#ifdef CONFIG_VIDEO_LOCAL
-local_modes:
- leaw local_mode_table, %si
-locm1: lodsw
- orw %ax, %ax
- jz locm2
-
- stosw
- movsw
- jmp locm1
-
-locm2: ret
-
-# This is the table of local video modes which can be supplied manually
-# by the user. Each entry consists of mode ID (word) and dimensions
-# (byte for column count and another byte for row count). These modes
-# are placed before all SVGA and VESA modes and override them if table
-# compacting is enabled. The table must end with a zero word followed
-# by NUL-terminated video adapter name.
-local_mode_table:
- .word 0x0100 # Example: 40x25
- .byte 25,40
- .word 0
- .ascii "Local"
- .byte 0
-#endif /* CONFIG_VIDEO_LOCAL */
-
-# Read a key and return the ASCII code in al, scan code in ah
-getkey: xorb %ah, %ah
- int $0x16
- ret
-
-# Read a key with a timeout of 30 seconds.
-# The hardware clock is used to get the time.
-getkt: call gettime
- addb $30, %al # Wait 30 seconds
- cmpb $60, %al
- jl lminute
-
- subb $60, %al
-lminute:
- movb %al, %cl
-again: movb $0x01, %ah
- int $0x16
- jnz getkey # key pressed, so get it
-
- call gettime
- cmpb %cl, %al
- jne again
-
- movb $0x20, %al # timeout, return `space'
- ret
-
-# Flush the keyboard buffer
-flush: movb $0x01, %ah
- int $0x16
- jz empty
-
- xorb %ah, %ah
- int $0x16
- jmp flush
-
-empty: ret
-
-# Print hexadecimal number.
-prthw: pushw %ax
- movb %ah, %al
- call prthb
- popw %ax
-prthb: pushw %ax
- shrb $4, %al
- call prthn
- popw %ax
- andb $0x0f, %al
-prthn: cmpb $0x0a, %al
- jc prth1
-
- addb $0x07, %al
-prth1: addb $0x30, %al
- jmp prtchr
-
-# Print decimal number in al
-prtdec: pushw %ax
- pushw %cx
- xorb %ah, %ah
- movb $0x0a, %cl
- idivb %cl
- cmpb $0x09, %al
- jbe lt100
-
- call prtdec
- jmp skip10
-
-lt100: addb $0x30, %al
- call prtchr
-skip10: movb %ah, %al
- addb $0x30, %al
- call prtchr
- popw %cx
- popw %ax
- ret
-
-store_edid:
-#ifdef CONFIG_FIRMWARE_EDID
- pushw %es # just save all registers
- pushw %ax
- pushw %bx
- pushw %cx
- pushw %dx
- pushw %di
-
- pushw %fs
- popw %es
-
- movl $0x13131313, %eax # memset block with 0x13
- movw $32, %cx
- movw $0x140, %di
- cld
- rep
- stosl
-
- cmpw $0x0200, vbe_version # only do EDID on >= VBE2.0
- jl no_edid
-
- pushw %es # save ES
- xorw %di, %di # Report Capability
- pushw %di
- popw %es # ES:DI must be 0:0
- movw $0x4f15, %ax
- xorw %bx, %bx
- xorw %cx, %cx
- int $0x10
- popw %es # restore ES
-
- cmpb $0x00, %ah # call successful
- jne no_edid
-
- cmpb $0x4f, %al # function supported
- jne no_edid
-
- movw $0x4f15, %ax # do VBE/DDC
- movw $0x01, %bx
- movw $0x00, %cx
- movw $0x00, %dx
- movw $0x140, %di
- int $0x10
-
-no_edid:
- popw %di # restore all registers
- popw %dx
- popw %cx
- popw %bx
- popw %ax
- popw %es
-#endif
- ret
-
-# VIDEO_SELECT-only variables
-mt_end: .word 0 # End of video mode table if built
-edit_buf: .space 6 # Line editor buffer
-card_name: .word 0 # Pointer to adapter name
-scanning: .byte 0 # Performing mode scan
-do_restore: .byte 0 # Screen contents altered during mode change
-svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
-graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
-dac_size: .byte 6 # DAC bit depth
-vbe_version: .word 0 # VBE bios version
-
-# Status messages
-keymsg: .ascii "Press <RETURN> to see video modes available, "
- .ascii "<SPACE> to continue or wait 30 secs"
- .byte 0x0d, 0x0a, 0
-
-listhdr: .byte 0x0d, 0x0a
- .ascii "Mode: COLSxROWS:"
-
-crlft: .byte 0x0d, 0x0a, 0
-
-prompt: .byte 0x0d, 0x0a
- .asciz "Enter mode number or `scan': "
-
-unknt: .asciz "Unknown mode ID. Try again."
-
-badmdt: .ascii "You passed an undefined mode number."
- .byte 0x0d, 0x0a, 0
-
-vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
- .ascii "report to <mj@ucw.cz>."
- .byte 0x0d, 0x0a, 0
-
-old_name: .asciz "CGA/MDA/HGA"
-
-ega_name: .asciz "EGA"
-
-svga_name: .ascii " "
-
-vga_name: .asciz "VGA"
-
-vesa_name: .asciz "VESA"
-
-name_bann: .asciz "Video adapter: "
-#endif /* CONFIG_VIDEO_SELECT */
-
-# Other variables:
-adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
-video_segment: .word 0xb800 # Video memory segment
-force_size: .word 0 # Use this size instead of the one in BIOS vars
diff --git a/arch/i386/boot/video.c b/arch/i386/boot/video.c
new file mode 100644
index 00000000000..3bb3573cd6a
--- /dev/null
+++ b/arch/i386/boot/video.c
@@ -0,0 +1,456 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video.c
+ *
+ * Select video mode
+ */
+
+#include "boot.h"
+#include "video.h"
+#include "vesa.h"
+
+/*
+ * Mode list variables
+ */
+static struct card_info cards[]; /* List of cards to probe for */
+
+/*
+ * Common variables
+ */
+int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
+u16 video_segment;
+int force_x, force_y; /* Don't query the BIOS for cols/rows */
+
+int do_restore = 0; /* Screen contents changed during mode flip */
+int graphic_mode; /* Graphic mode with linear frame buffer */
+
+static void store_cursor_position(void)
+{
+ u16 curpos;
+ u16 ax, bx;
+
+ ax = 0x0300;
+ bx = 0;
+ asm(INT10
+ : "=d" (curpos), "+a" (ax), "+b" (bx)
+ : : "ecx", "esi", "edi");
+
+ boot_params.screen_info.orig_x = curpos;
+ boot_params.screen_info.orig_y = curpos >> 8;
+}
+
+static void store_video_mode(void)
+{
+ u16 ax, page;
+
+ /* N.B.: the saving of the video page here is a bit silly,
+ since we pretty much assume page 0 everywhere. */
+ ax = 0x0f00;
+ asm(INT10
+ : "+a" (ax), "=b" (page)
+ : : "ecx", "edx", "esi", "edi");
+
+ /* Not all BIOSes are clean with respect to the top bit */
+ boot_params.screen_info.orig_video_mode = ax & 0x7f;
+ boot_params.screen_info.orig_video_page = page;
+}
+
+/*
+ * Store the video mode parameters for later usage by the kernel.
+ * This is done by asking the BIOS except for the rows/columns
+ * parameters in the default 80x25 mode -- these are set directly,
+ * because some very obscure BIOSes supply insane values.
+ */
+static void store_mode_params(void)
+{
+ u16 font_size;
+ int x, y;
+
+ /* For graphics mode, it is up to the mode-setting driver
+ (currently only video-vesa.c) to store the parameters */
+ if (graphic_mode)
+ return;
+
+ store_cursor_position();
+ store_video_mode();
+
+ if (boot_params.screen_info.orig_video_mode == 0x07) {
+ /* MDA, HGC, or VGA in monochrome mode */
+ video_segment = 0xb000;
+ } else {
+ /* CGA, EGA, VGA and so forth */
+ video_segment = 0xb800;
+ }
+
+ set_fs(0);
+ font_size = rdfs16(0x485); /* Font size, BIOS area */
+ boot_params.screen_info.orig_video_points = font_size;
+
+ x = rdfs16(0x44a);
+ y = (adapter == ADAPTER_CGA) ? 25 : rdfs8(0x484)+1;
+
+ if (force_x)
+ x = force_x;
+ if (force_y)
+ y = force_y;
+
+ boot_params.screen_info.orig_video_cols = x;
+ boot_params.screen_info.orig_video_lines = y;
+}
+
+/* Probe the video drivers and have them generate their mode lists. */
+static void probe_cards(int unsafe)
+{
+ struct card_info *card;
+ static u8 probed[2];
+
+ if (probed[unsafe])
+ return;
+
+ probed[unsafe] = 1;
+
+ for (card = video_cards; card < video_cards_end; card++) {
+ if (card->unsafe == unsafe) {
+ if (card->probe)
+ card->nmodes = card->probe();
+ else
+ card->nmodes = 0;
+ }
+ }
+}
+
+/* Test if a mode is defined */
+int mode_defined(u16 mode)
+{
+ struct card_info *card;
+ struct mode_info *mi;
+ int i;
+
+ for (card = video_cards; card < video_cards_end; card++) {
+ mi = card->modes;
+ for (i = 0; i < card->nmodes; i++, mi++) {
+ if (mi->mode == mode)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Set mode (without recalc) */
+static int raw_set_mode(u16 mode)
+{
+ int nmode, i;
+ struct card_info *card;
+ struct mode_info *mi;
+
+ /* Drop the recalc bit if set */
+ mode &= ~VIDEO_RECALC;
+
+ /* Scan for mode based on fixed ID, position, or resolution */
+ nmode = 0;
+ for (card = video_cards; card < video_cards_end; card++) {
+ mi = card->modes;
+ for (i = 0; i < card->nmodes; i++, mi++) {
+ int visible = mi->x || mi->y;
+
+ if ((mode == nmode && visible) ||
+ mode == mi->mode ||
+ mode == (mi->y << 8)+mi->x)
+ return card->set_mode(mi);
+
+ if (visible)
+ nmode++;
+ }
+ }
+
+ /* Nothing found? Is it an "exceptional" (unprobed) mode? */
+ for (card = video_cards; card < video_cards_end; card++) {
+ if (mode >= card->xmode_first &&
+ mode < card->xmode_first+card->xmode_n) {
+ struct mode_info mix;
+ mix.mode = mode;
+ mix.x = mix.y = 0;
+ return card->set_mode(&mix);
+ }
+ }
+
+ /* Otherwise, failure... */
+ return -1;
+}
+
+/*
+ * Recalculate the vertical video cutoff (hack!)
+ */
+static void vga_recalc_vertical(void)
+{
+ unsigned int font_size, rows;
+ u16 crtc;
+ u8 ov;
+
+ set_fs(0);
+ font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
+ rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
+
+ rows *= font_size; /* Visible scan lines */
+ rows--; /* ... minus one */
+
+ crtc = vga_crtc();
+
+ out_idx((u8)rows, crtc, 0x12); /* Lower height register */
+ ov = in_idx(crtc, 0x07); /* Overflow register */
+ ov &= 0xbd;
+ ov |= (rows >> (8-1)) & 0x02;
+ ov |= (rows >> (9-6)) & 0x40;
+ out_idx(ov, crtc, 0x07);
+}
+
+/* Set mode (with recalc if specified) */
+static int set_mode(u16 mode)
+{
+ int rv;
+
+ /* Very special mode numbers... */
+ if (mode == VIDEO_CURRENT_MODE)
+ return 0; /* Nothing to do... */
+ else if (mode == NORMAL_VGA)
+ mode = VIDEO_80x25;
+ else if (mode == EXTENDED_VGA)
+ mode = VIDEO_8POINT;
+
+ rv = raw_set_mode(mode);
+ if (rv)
+ return rv;
+
+ if (mode & VIDEO_RECALC)
+ vga_recalc_vertical();
+
+ return 0;
+}
+
+static unsigned int get_entry(void)
+{
+ char entry_buf[4];
+ int i, len = 0;
+ int key;
+ unsigned int v;
+
+ do {
+ key = getchar();
+
+ if (key == '\b') {
+ if (len > 0) {
+ puts("\b \b");
+ len--;
+ }
+ } else if ((key >= '0' && key <= '9') ||
+ (key >= 'A' && key <= 'Z') ||
+ (key >= 'a' && key <= 'z')) {
+ if (len < sizeof entry_buf) {
+ entry_buf[len++] = key;
+ putchar(key);
+ }
+ }
+ } while (key != '\r');
+ putchar('\n');
+
+ if (len == 0)
+ return VIDEO_CURRENT_MODE; /* Default */
+
+ v = 0;
+ for (i = 0; i < len; i++) {
+ v <<= 4;
+ key = entry_buf[i] | 0x20;
+ v += (key > '9') ? key-'a'+10 : key-'0';
+ }
+
+ return v;
+}
+
+static void display_menu(void)
+{
+ struct card_info *card;
+ struct mode_info *mi;
+ char ch;
+ int i;
+
+ puts("Mode: COLSxROWS:\n");
+
+ ch = '0';
+ for (card = video_cards; card < video_cards_end; card++) {
+ mi = card->modes;
+ for (i = 0; i < card->nmodes; i++, mi++) {
+ int visible = mi->x && mi->y;
+ u16 mode_id = mi->mode ? mi->mode :
+ (mi->y << 8)+mi->x;
+
+ if (!visible)
+ continue; /* Hidden mode */
+
+ printf("%c %04X %3dx%-3d %s\n",
+ ch, mode_id, mi->x, mi->y, card->card_name);
+
+ if (ch == '9')
+ ch = 'a';
+ else if (ch == 'z' || ch == ' ')
+ ch = ' '; /* Out of keys... */
+ else
+ ch++;
+ }
+ }
+}
+
+#define H(x) ((x)-'a'+10)
+#define SCAN ((H('s')<<12)+(H('c')<<8)+(H('a')<<4)+H('n'))
+
+static unsigned int mode_menu(void)
+{
+ int key;
+ unsigned int sel;
+
+ puts("Press <ENTER> to see video modes available, "
+ "<SPACE> to continue, or wait 30 sec\n");
+
+ kbd_flush();
+ while (1) {
+ key = getchar_timeout();
+ if (key == ' ' || key == 0)
+ return VIDEO_CURRENT_MODE; /* Default */
+ if (key == '\r')
+ break;
+ putchar('\a'); /* Beep! */
+ }
+
+
+ for (;;) {
+ display_menu();
+
+ puts("Enter a video mode or \"scan\" to scan for "
+ "additional modes: ");
+ sel = get_entry();
+ if (sel != SCAN)
+ return sel;
+
+ probe_cards(1);
+ }
+}
+
+#ifdef CONFIG_VIDEO_RETAIN
+/* Save screen content to the heap */
+struct saved_screen {
+ int x, y;
+ int curx, cury;
+ u16 *data;
+} saved;
+
+static void save_screen(void)
+{
+ /* Should be called after store_mode_params() */
+ saved.x = boot_params.screen_info.orig_video_cols;
+ saved.y = boot_params.screen_info.orig_video_lines;
+ saved.curx = boot_params.screen_info.orig_x;
+ saved.cury = boot_params.screen_info.orig_y;
+
+ if (heap_free() < saved.x*saved.y*sizeof(u16)+512)
+ return; /* Not enough heap to save the screen */
+
+ saved.data = GET_HEAP(u16, saved.x*saved.y);
+
+ set_fs(video_segment);
+ copy_from_fs(saved.data, 0, saved.x*saved.y*sizeof(u16));
+}
+
+static void restore_screen(void)
+{
+ /* Should be called after store_mode_params() */
+ int xs = boot_params.screen_info.orig_video_cols;
+ int ys = boot_params.screen_info.orig_video_lines;
+ int y;
+ addr_t dst = 0;
+ u16 *src = saved.data;
+ u16 ax, bx, dx;
+
+ if (graphic_mode)
+ return; /* Can't restore onto a graphic mode */
+
+ if (!src)
+ return; /* No saved screen contents */
+
+ /* Restore screen contents */
+
+ set_fs(video_segment);
+ for (y = 0; y < ys; y++) {
+ int npad;
+
+ if (y < saved.y) {
+ int copy = (xs < saved.x) ? xs : saved.x;
+ copy_to_fs(dst, src, copy*sizeof(u16));
+ dst += copy*sizeof(u16);
+ src += saved.x;
+ npad = (xs < saved.x) ? 0 : xs-saved.x;
+ } else {
+ npad = xs;
+ }
+
+ /* Writes "npad" blank characters to
+ video_segment:dst and advances dst */
+ asm volatile("pushw %%es ; "
+ "movw %2,%%es ; "
+ "shrw %%cx ; "
+ "jnc 1f ; "
+ "stosw \n\t"
+ "1: rep;stosl ; "
+ "popw %%es"
+ : "+D" (dst), "+c" (npad)
+ : "bdSm" (video_segment),
+ "a" (0x07200720));
+ }
+
+ /* Restore cursor position */
+ ax = 0x0200; /* Set cursor position */
+ bx = 0; /* Page number (<< 8) */
+ dx = (saved.cury << 8)+saved.curx;
+ asm volatile(INT10
+ : "+a" (ax), "+b" (bx), "+d" (dx)
+ : : "ecx", "esi", "edi");
+}
+#else
+#define save_screen() ((void)0)
+#define restore_screen() ((void)0)
+#endif
+
+void set_video(void)
+{
+ u16 mode = boot_params.hdr.vid_mode;
+
+ RESET_HEAP();
+
+ store_mode_params();
+ save_screen();
+ probe_cards(0);
+
+ for (;;) {
+ if (mode == ASK_VGA)
+ mode = mode_menu();
+
+ if (!set_mode(mode))
+ break;
+
+ printf("Undefined video mode number: %x\n", mode);
+ mode = ASK_VGA;
+ }
+ vesa_store_edid();
+ store_mode_params();
+
+ if (do_restore)
+ restore_screen();
+}
diff --git a/arch/i386/boot/video.h b/arch/i386/boot/video.h
new file mode 100644
index 00000000000..29eca1710b2
--- /dev/null
+++ b/arch/i386/boot/video.h
@@ -0,0 +1,145 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/video.h
+ *
+ * Header file for the real-mode video probing code
+ */
+
+#ifndef BOOT_VIDEO_H
+#define BOOT_VIDEO_H
+
+#include <linux/types.h>
+
+/* Enable autodetection of SVGA adapters and modes. */
+#undef CONFIG_VIDEO_SVGA
+
+/* Enable autodetection of VESA modes */
+#define CONFIG_VIDEO_VESA
+
+/* Retain screen contents when switching modes */
+#define CONFIG_VIDEO_RETAIN
+
+/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
+#undef CONFIG_VIDEO_400_HACK
+
+/* This code uses an extended set of video mode numbers. These include:
+ * Aliases for standard modes
+ * NORMAL_VGA (-1)
+ * EXTENDED_VGA (-2)
+ * ASK_VGA (-3)
+ * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+ * of compatibility when extending the table. These are between 0x00 and 0xff.
+ */
+#define VIDEO_FIRST_MENU 0x0000
+
+/* Standard BIOS video modes (BIOS number + 0x0100) */
+#define VIDEO_FIRST_BIOS 0x0100
+
+/* VESA BIOS video modes (VESA number + 0x0200) */
+#define VIDEO_FIRST_VESA 0x0200
+
+/* Video7 special modes (BIOS number + 0x0900) */
+#define VIDEO_FIRST_V7 0x0900
+
+/* Special video modes */
+#define VIDEO_FIRST_SPECIAL 0x0f00
+#define VIDEO_80x25 0x0f00
+#define VIDEO_8POINT 0x0f01
+#define VIDEO_80x43 0x0f02
+#define VIDEO_80x28 0x0f03
+#define VIDEO_CURRENT_MODE 0x0f04
+#define VIDEO_80x30 0x0f05
+#define VIDEO_80x34 0x0f06
+#define VIDEO_80x60 0x0f07
+#define VIDEO_GFX_HACK 0x0f08
+#define VIDEO_LAST_SPECIAL 0x0f09
+
+/* Video modes given by resolution */
+#define VIDEO_FIRST_RESOLUTION 0x1000
+
+/* The "recalculate timings" flag */
+#define VIDEO_RECALC 0x8000
+
+/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
+#ifdef CONFIG_VIDEO_RETAIN
+void store_screen(void);
+#define DO_STORE() store_screen()
+#else
+#define DO_STORE() ((void)0)
+#endif /* CONFIG_VIDEO_RETAIN */
+
+/*
+ * Mode table structures
+ */
+
+struct mode_info {
+ u16 mode; /* Mode number (vga= style) */
+ u8 x, y; /* Width, height */
+};
+
+struct card_info {
+ const char *card_name;
+ int (*set_mode)(struct mode_info *mode);
+ int (*probe)(void);
+ struct mode_info *modes;
+ int nmodes; /* Number of probed modes so far */
+ int unsafe; /* Probing is unsafe, only do after "scan" */
+ u16 xmode_first; /* Unprobed modes to try to call anyway */
+ u16 xmode_n; /* Size of unprobed mode range */
+};
+
+#define __videocard struct card_info __attribute__((section(".videocards")))
+extern struct card_info video_cards[], video_cards_end[];
+
+int mode_defined(u16 mode); /* video.c */
+
+/* Basic video information */
+#define ADAPTER_CGA 0 /* CGA/MDA/HGC */
+#define ADAPTER_EGA 1
+#define ADAPTER_VGA 2
+
+extern int adapter;
+extern u16 video_segment;
+extern int force_x, force_y; /* Don't query the BIOS for cols/rows */
+extern int do_restore; /* Restore screen contents */
+extern int graphic_mode; /* Graphics mode with linear frame buffer */
+
+/*
+ * int $0x10 is notorious for touching registers it shouldn't.
+ * gcc doesn't like %ebp being clobbered, so define it as a push/pop
+ * sequence here.
+ */
+#define INT10 "pushl %%ebp; int $0x10; popl %%ebp"
+
+/* Accessing VGA indexed registers */
+static inline u8 in_idx(u16 port, u8 index)
+{
+ outb(index, port);
+ return inb(port+1);
+}
+
+static inline void out_idx(u8 v, u16 port, u8 index)
+{
+ outw(index+(v << 8), port);
+}
+
+/* Writes a value to an indexed port and then reads the port again */
+static inline u8 tst_idx(u8 v, u16 port, u8 index)
+{
+ out_idx(port, index, v);
+ return in_idx(port, index);
+}
+
+/* Get the I/O port of the VGA CRTC */
+u16 vga_crtc(void); /* video-vga.c */
+
+#endif /* BOOT_VIDEO_H */
diff --git a/arch/i386/boot/voyager.c b/arch/i386/boot/voyager.c
new file mode 100644
index 00000000000..9221614d0db
--- /dev/null
+++ b/arch/i386/boot/voyager.c
@@ -0,0 +1,46 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * arch/i386/boot/voyager.c
+ *
+ * Get the Voyager config information
+ */
+
+#include "boot.h"
+
+#ifdef CONFIG_X86_VOYAGER
+
+int query_voyager(void)
+{
+ u8 err;
+ u16 es, di;
+ /* Abuse the apm_bios_info area for this */
+ u8 *data_ptr = (u8 *)&boot_params.apm_bios_info;
+
+ data_ptr[0] = 0xff; /* Flag on config not found(?) */
+
+ asm("pushw %%es ; "
+ "int $0x15 ; "
+ "setc %0 ; "
+ "movw %%es, %1 ; "
+ "popw %%es"
+ : "=qm" (err), "=rm" (es), "=D" (di)
+ : "a" (0xffc0));
+
+ if (err)
+ return -1; /* Not Voyager */
+
+ set_fs(es);
+ copy_from_fs(data_ptr, di, 7); /* Table is 7 bytes apparently */
+ return 0;
+}
+
+#endif /* CONFIG_X86_VOYAGER */
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 280898b045b..a574cd2c8b6 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -621,8 +621,6 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table)
static int __init acpi_parse_hpet(struct acpi_table_header *table)
{
struct acpi_table_hpet *hpet_tbl;
- struct resource *hpet_res;
- resource_size_t res_start;
hpet_tbl = (struct acpi_table_hpet *)table;
if (!hpet_tbl) {
@@ -636,29 +634,10 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
return -1;
}
-#define HPET_RESOURCE_NAME_SIZE 9
- hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
- if (hpet_res) {
- memset(hpet_res, 0, sizeof(*hpet_res));
- hpet_res->name = (void *)&hpet_res[1];
- hpet_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
- snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE,
- "HPET %u", hpet_tbl->sequence);
- hpet_res->end = (1 * 1024) - 1;
- }
-
hpet_address = hpet_tbl->address.address;
printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
hpet_tbl->id, hpet_address);
- res_start = hpet_address;
-
- if (hpet_res) {
- hpet_res->start = res_start;
- hpet_res->end += res_start;
- insert_resource(&iomem_resource, hpet_res);
- }
-
return 0;
}
#else
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
index b781b38131c..a2295a34b2c 100644
--- a/arch/i386/kernel/acpi/wakeup.S
+++ b/arch/i386/kernel/acpi/wakeup.S
@@ -230,6 +230,7 @@ bogus_magic:
#
ENTRY(acpi_copy_wakeup_routine)
+ pushl %ebx
sgdt saved_gdt
sidt saved_idt
sldt saved_ldt
@@ -263,6 +264,7 @@ ENTRY(acpi_copy_wakeup_routine)
movl %edx, video_flags - wakeup_start (%eax)
movl $0x12345678, real_magic - wakeup_start (%eax)
movl $0x12345678, saved_magic
+ popl %ebx
ret
save_registers:
diff --git a/arch/i386/kernel/cpu/Makefile b/arch/i386/kernel/cpu/Makefile
index 74f27a463db..0b6a8551e9e 100644
--- a/arch/i386/kernel/cpu/Makefile
+++ b/arch/i386/kernel/cpu/Makefile
@@ -8,7 +8,7 @@ obj-y += amd.o
obj-y += cyrix.o
obj-y += centaur.o
obj-y += transmeta.o
-obj-y += intel.o intel_cacheinfo.o
+obj-y += intel.o intel_cacheinfo.o addon_cpuid_features.o
obj-y += rise.o
obj-y += nexgen.o
obj-y += umc.o
diff --git a/arch/i386/kernel/cpu/addon_cpuid_features.c b/arch/i386/kernel/cpu/addon_cpuid_features.c
new file mode 100644
index 00000000000..3e91d3ee26e
--- /dev/null
+++ b/arch/i386/kernel/cpu/addon_cpuid_features.c
@@ -0,0 +1,50 @@
+
+/*
+ * Routines to indentify additional cpu features that are scattered in
+ * cpuid space.
+ */
+
+#include <linux/cpu.h>
+
+#include <asm/processor.h>
+
+struct cpuid_bit {
+ u16 feature;
+ u8 reg;
+ u8 bit;
+ u32 level;
+};
+
+enum cpuid_regs {
+ CR_EAX = 0,
+ CR_ECX,
+ CR_EDX,
+ CR_EBX
+};
+
+void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
+{
+ u32 max_level;
+ u32 regs[4];
+ const struct cpuid_bit *cb;
+
+ static const struct cpuid_bit cpuid_bits[] = {
+ { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 },
+ { 0, 0, 0, 0 }
+ };
+
+ for (cb = cpuid_bits; cb->feature; cb++) {
+
+ /* Verify that the level is valid */
+ max_level = cpuid_eax(cb->level & 0xffff0000);
+ if (max_level < cb->level ||
+ max_level > (cb->level | 0xffff))
+ continue;
+
+ cpuid(cb->level, &regs[CR_EAX], &regs[CR_EBX],
+ &regs[CR_ECX], &regs[CR_EDX]);
+
+ if (regs[cb->reg] & (1 << cb->bit))
+ set_bit(cb->feature, c->x86_capability);
+ }
+}
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 794d593c47e..e5419a9dec8 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -353,6 +353,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
if ( xlvl >= 0x80000004 )
get_model_name(c); /* Default name */
}
+
+ init_scattered_cpuid_features(c);
}
early_intel_workaround(c);
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index e912aae9473..094118ba00d 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -90,10 +90,17 @@ config X86_POWERNOW_K8
If in doubt, say N.
config X86_POWERNOW_K8_ACPI
- bool
- depends on X86_POWERNOW_K8 && ACPI_PROCESSOR
- depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m)
+ bool "ACPI Support"
+ select ACPI_PROCESSOR
+ depends on X86_POWERNOW_K8
default y
+ help
+ This provides access to the K8s Processor Performance States via ACPI.
+ This driver is probably required for CPUFreq to work with multi-socket and
+ SMP systems. It is not required on at least some single-socket yet
+ multi-core systems, even if SMP is enabled.
+
+ It is safe to say Y here.
config X86_GX_SUSPMOD
tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
@@ -109,7 +116,7 @@ config X86_GX_SUSPMOD
config X86_SPEEDSTEP_CENTRINO
tristate "Intel Enhanced SpeedStep"
select CPU_FREQ_TABLE
- select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI)
+ select X86_SPEEDSTEP_CENTRINO_TABLE
help
This adds the CPUFreq driver for Enhanced SpeedStep enabled
mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However,
@@ -121,20 +128,6 @@ config X86_SPEEDSTEP_CENTRINO
If in doubt, say N.
-config X86_SPEEDSTEP_CENTRINO_ACPI
- bool "Use ACPI tables to decode valid frequency/voltage (deprecated)"
- depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR
- depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m)
- help
- This is deprecated and this functionality is now merged into
- acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of
- speedstep_centrino.
- Use primarily the information provided in the BIOS ACPI tables
- to determine valid CPU frequency and voltage pairings. It is
- required for the driver to work on non-Banias CPUs.
-
- If in doubt, say Y.
-
config X86_SPEEDSTEP_CENTRINO_TABLE
bool "Built-in tables for Banias CPUs"
depends on X86_SPEEDSTEP_CENTRINO
@@ -230,7 +223,7 @@ comment "shared options"
config X86_ACPI_CPUFREQ_PROC_INTF
bool "/proc/acpi/processor/../performance interface (deprecated)"
depends on PROC_FS
- depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
+ depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI
help
This enables the deprecated /proc/acpi/processor/../performance
interface. While it is helpful for debugging, the generic,
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 10baa3501ed..18c8b67ea3a 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -167,11 +167,13 @@ static void do_drv_read(struct drv_cmd *cmd)
static void do_drv_write(struct drv_cmd *cmd)
{
- u32 h = 0;
+ u32 lo, hi;
switch (cmd->type) {
case SYSTEM_INTEL_MSR_CAPABLE:
- wrmsr(cmd->addr.msr.reg, cmd->val, h);
+ rdmsr(cmd->addr.msr.reg, lo, hi);
+ lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE);
+ wrmsr(cmd->addr.msr.reg, lo, hi);
break;
case SYSTEM_IO_CAPABLE:
acpi_os_write_port((acpi_io_address)cmd->addr.io.port,
@@ -372,7 +374,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
struct cpufreq_freqs freqs;
cpumask_t online_policy_cpus;
struct drv_cmd cmd;
- unsigned int msr;
unsigned int next_state = 0; /* Index into freq_table */
unsigned int next_perf_state = 0; /* Index into perf table */
unsigned int i;
@@ -417,11 +418,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
case SYSTEM_INTEL_MSR_CAPABLE:
cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
- msr =
- (u32) perf->states[next_perf_state].
- control & INTEL_MSR_RANGE;
- cmd.val = get_cur_val(online_policy_cpus);
- cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr;
+ cmd.val = (u32) perf->states[next_perf_state].control;
break;
case SYSTEM_IO_CAPABLE:
cmd.type = SYSTEM_IO_CAPABLE;
diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
index 0d49d73d1b7..66acd503991 100644
--- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -391,8 +391,6 @@ static struct cpufreq_driver nforce2_driver = {
*/
static unsigned int nforce2_detect_chipset(void)
{
- u8 revision;
-
nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
PCI_DEVICE_ID_NVIDIA_NFORCE2,
PCI_ANY_ID, PCI_ANY_ID, NULL);
@@ -400,10 +398,8 @@ static unsigned int nforce2_detect_chipset(void)
if (nforce2_chipset_dev == NULL)
return -ENODEV;
- pci_read_config_byte(nforce2_chipset_dev, PCI_REVISION_ID, &revision);
-
printk(KERN_INFO "cpufreq: Detected nForce2 chipset revision %X\n",
- revision);
+ nforce2_chipset_dev->revision);
printk(KERN_INFO
"cpufreq: FSB changing is maybe unstable and can lead to crashes and data loss.\n");
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
index 6667e9cceb9..194144539a6 100644
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
@@ -115,7 +115,6 @@ struct gxfreq_params {
u8 pci_suscfg;
u8 pci_pmer1;
u8 pci_pmer2;
- u8 pci_rev;
struct pci_dev *cs55x0;
};
@@ -276,7 +275,7 @@ static void gx_set_cpuspeed(unsigned int khz)
pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */
pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1);
- if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */
+ if (gx_params->cs55x0->revision < 0x10) { /* CS5530(rev 1.2, 1.3) */
suscfg = gx_params->pci_suscfg | SUSMOD;
} else { /* CS5530A,B.. */
suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE;
@@ -471,7 +470,6 @@ static int __init cpufreq_gx_init(void)
pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2));
pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration));
pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration));
- pci_read_config_byte(params->cs55x0, PCI_REVISION_ID, &params->pci_rev);
if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) {
kfree(params);
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index a3df9c039bd..ef8f0bc3fc7 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,6 +29,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/delay.h>
#include <asm/msr.h>
#include <asm/timex.h>
@@ -55,7 +56,6 @@
/* Flags */
#define USE_ACPI_C3 (1 << 1)
#define USE_NORTHBRIDGE (1 << 2)
-#define USE_VT8235 (1 << 3)
static int cpu_model;
static unsigned int numscales=16;
@@ -63,22 +63,19 @@ static unsigned int fsb;
static const struct mV_pos *vrm_mV_table;
static const unsigned char *mV_vrm_table;
-struct f_msr {
- u8 vrm;
- u8 pos;
-};
-static struct f_msr f_msr_table[32];
static unsigned int highest_speed, lowest_speed; /* kHz */
static unsigned int minmult, maxmult;
static int can_scale_voltage;
static struct acpi_processor *pr = NULL;
static struct acpi_processor_cx *cx = NULL;
+static u32 acpi_regs_addr;
static u8 longhaul_flags;
-static u8 longhaul_pos;
+static unsigned int longhaul_index;
/* Module parameters */
static int scale_voltage;
+static int disable_acpi_c3;
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
@@ -144,7 +141,7 @@ static void do_longhaul1(unsigned int clock_ratio_index)
rdmsrl(MSR_VIA_BCR2, bcr2.val);
/* Enable software clock multiplier */
bcr2.bits.ESOFTBF = 1;
- bcr2.bits.CLOCKMUL = clock_ratio_index;
+ bcr2.bits.CLOCKMUL = clock_ratio_index & 0xff;
/* Sync to timer tick */
safe_halt();
@@ -163,14 +160,12 @@ static void do_longhaul1(unsigned int clock_ratio_index)
/* For processor with Longhaul MSR */
-static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
+static void do_powersaver(int cx_address, unsigned int clock_ratio_index,
+ unsigned int dir)
{
union msr_longhaul longhaul;
- u8 dest_pos;
u32 t;
- dest_pos = f_msr_table[clock_ratio_index].pos;
-
rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
/* Setup new frequency */
longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
@@ -178,11 +173,11 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
/* Setup new voltage */
if (can_scale_voltage)
- longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
+ longhaul.bits.SoftVID = (clock_ratio_index >> 8) & 0x1f;
/* Sync to timer tick */
safe_halt();
/* Raise voltage if necessary */
- if (can_scale_voltage && longhaul_pos < dest_pos) {
+ if (can_scale_voltage && dir) {
longhaul.bits.EnableSoftVID = 1;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
/* Change voltage */
@@ -199,7 +194,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
}
longhaul.bits.EnableSoftVID = 0;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
- longhaul_pos = dest_pos;
}
/* Change frequency on next halt or sleep */
@@ -220,7 +214,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
/* Reduce voltage if necessary */
- if (can_scale_voltage && longhaul_pos > dest_pos) {
+ if (can_scale_voltage && !dir) {
longhaul.bits.EnableSoftVID = 1;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
/* Change voltage */
@@ -237,7 +231,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
}
longhaul.bits.EnableSoftVID = 0;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
- longhaul_pos = dest_pos;
}
}
@@ -248,25 +241,28 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
* Sets a new clock ratio.
*/
-static void longhaul_setstate(unsigned int clock_ratio_index)
+static void longhaul_setstate(unsigned int table_index)
{
+ unsigned int clock_ratio_index;
int speed, mult;
struct cpufreq_freqs freqs;
- static unsigned int old_ratio=-1;
unsigned long flags;
unsigned int pic1_mask, pic2_mask;
+ u16 bm_status = 0;
+ u32 bm_timeout = 1000;
+ unsigned int dir = 0;
- if (old_ratio == clock_ratio_index)
- return;
- old_ratio = clock_ratio_index;
-
- mult = clock_ratio[clock_ratio_index];
+ clock_ratio_index = longhaul_table[table_index].index;
+ /* Safety precautions */
+ mult = clock_ratio[clock_ratio_index & 0x1f];
if (mult == -1)
return;
-
speed = calc_speed(mult);
if ((speed > highest_speed) || (speed < lowest_speed))
return;
+ /* Voltage transition before frequency transition? */
+ if (can_scale_voltage && longhaul_index < table_index)
+ dir = 1;
freqs.old = calc_speed(longhaul_get_cpu_mult());
freqs.new = speed;
@@ -285,11 +281,24 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
outb(0xFF,0xA1); /* Overkill */
outb(0xFE,0x21); /* TMR0 only */
+ /* Wait while PCI bus is busy. */
+ if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE
+ || ((pr != NULL) && pr->flags.bm_control))) {
+ bm_status = inw(acpi_regs_addr);
+ bm_status &= 1 << 4;
+ while (bm_status && bm_timeout) {
+ outw(1 << 4, acpi_regs_addr);
+ bm_timeout--;
+ bm_status = inw(acpi_regs_addr);
+ bm_status &= 1 << 4;
+ }
+ }
+
if (longhaul_flags & USE_NORTHBRIDGE) {
/* Disable AGP and PCI arbiters */
outb(3, 0x22);
} else if ((pr != NULL) && pr->flags.bm_control) {
- /* Disable bus master arbitration */
+ /* Disable bus master arbitration */
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
}
switch (longhaul_version) {
@@ -314,9 +323,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
if (longhaul_flags & USE_ACPI_C3) {
/* Don't allow wakeup */
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
- do_powersaver(cx->address, clock_ratio_index);
+ do_powersaver(cx->address, clock_ratio_index, dir);
} else {
- do_powersaver(0, clock_ratio_index);
+ do_powersaver(0, clock_ratio_index, dir);
}
break;
}
@@ -336,6 +345,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
freqs.new = calc_speed(longhaul_get_cpu_mult());
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ if (!bm_timeout)
+ printk(KERN_INFO PFX "Warning: Timeout while waiting for idle PCI bus.\n");
}
/*
@@ -369,7 +381,8 @@ static int guess_fsb(int mult)
static int __init longhaul_get_ranges(void)
{
- unsigned int j, k = 0;
+ unsigned int i, j, k = 0;
+ unsigned int ratio;
int mult;
/* Get current frequency */
@@ -423,8 +436,7 @@ static int __init longhaul_get_ranges(void)
if(!longhaul_table)
return -ENOMEM;
- for (j=0; j < numscales; j++) {
- unsigned int ratio;
+ for (j = 0; j < numscales; j++) {
ratio = clock_ratio[j];
if (ratio == -1)
continue;
@@ -434,13 +446,41 @@ static int __init longhaul_get_ranges(void)
longhaul_table[k].index = j;
k++;
}
+ if (k <= 1) {
+ kfree(longhaul_table);
+ return -ENODEV;
+ }
+ /* Sort */
+ for (j = 0; j < k - 1; j++) {
+ unsigned int min_f, min_i;
+ min_f = longhaul_table[j].frequency;
+ min_i = j;
+ for (i = j + 1; i < k; i++) {
+ if (longhaul_table[i].frequency < min_f) {
+ min_f = longhaul_table[i].frequency;
+ min_i = i;
+ }
+ }
+ if (min_i != j) {
+ unsigned int temp;
+ temp = longhaul_table[j].frequency;
+ longhaul_table[j].frequency = longhaul_table[min_i].frequency;
+ longhaul_table[min_i].frequency = temp;
+ temp = longhaul_table[j].index;
+ longhaul_table[j].index = longhaul_table[min_i].index;
+ longhaul_table[min_i].index = temp;
+ }
+ }
longhaul_table[k].frequency = CPUFREQ_TABLE_END;
- if (!k) {
- kfree (longhaul_table);
- return -EINVAL;
- }
+ /* Find index we are running on */
+ for (j = 0; j < k; j++) {
+ if (clock_ratio[longhaul_table[j].index & 0x1f] == mult) {
+ longhaul_index = j;
+ break;
+ }
+ }
return 0;
}
@@ -448,7 +488,7 @@ static int __init longhaul_get_ranges(void)
static void __init longhaul_setup_voltagescaling(void)
{
union msr_longhaul longhaul;
- struct mV_pos minvid, maxvid;
+ struct mV_pos minvid, maxvid, vid;
unsigned int j, speed, pos, kHz_step, numvscales;
int min_vid_speed;
@@ -459,11 +499,11 @@ static void __init longhaul_setup_voltagescaling(void)
}
if (!longhaul.bits.VRMRev) {
- printk (KERN_INFO PFX "VRM 8.5\n");
+ printk(KERN_INFO PFX "VRM 8.5\n");
vrm_mV_table = &vrm85_mV[0];
mV_vrm_table = &mV_vrm85[0];
} else {
- printk (KERN_INFO PFX "Mobile VRM\n");
+ printk(KERN_INFO PFX "Mobile VRM\n");
if (cpu_model < CPU_NEHEMIAH)
return;
vrm_mV_table = &mobilevrm_mV[0];
@@ -523,7 +563,6 @@ static void __init longhaul_setup_voltagescaling(void)
/* Calculate kHz for one voltage step */
kHz_step = (highest_speed - min_vid_speed) / numvscales;
-
j = 0;
while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
speed = longhaul_table[j].frequency;
@@ -531,15 +570,14 @@ static void __init longhaul_setup_voltagescaling(void)
pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
else
pos = minvid.pos;
- f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
- f_msr_table[longhaul_table[j].index].pos = pos;
+ longhaul_table[j].index |= mV_vrm_table[pos] << 8;
+ vid = vrm_mV_table[mV_vrm_table[pos]];
+ printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", speed, j, vid.mV);
j++;
}
- longhaul_pos = maxvid.pos;
can_scale_voltage = 1;
- printk(KERN_INFO PFX "Voltage scaling enabled. "
- "Use of \"conservative\" governor is highly recommended.\n");
+ printk(KERN_INFO PFX "Voltage scaling enabled.\n");
}
@@ -553,15 +591,44 @@ static int longhaul_target(struct cpufreq_policy *policy,
unsigned int target_freq, unsigned int relation)
{
unsigned int table_index = 0;
- unsigned int new_clock_ratio = 0;
+ unsigned int i;
+ unsigned int dir = 0;
+ u8 vid, current_vid;
if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
return -EINVAL;
- new_clock_ratio = longhaul_table[table_index].index & 0xFF;
-
- longhaul_setstate(new_clock_ratio);
+ /* Don't set same frequency again */
+ if (longhaul_index == table_index)
+ return 0;
+ if (!can_scale_voltage)
+ longhaul_setstate(table_index);
+ else {
+ /* On test system voltage transitions exceeding single
+ * step up or down were turning motherboard off. Both
+ * "ondemand" and "userspace" are unsafe. C7 is doing
+ * this in hardware, C3 is old and we need to do this
+ * in software. */
+ i = longhaul_index;
+ current_vid = (longhaul_table[longhaul_index].index >> 8) & 0x1f;
+ if (table_index > longhaul_index)
+ dir = 1;
+ while (i != table_index) {
+ vid = (longhaul_table[i].index >> 8) & 0x1f;
+ if (vid != current_vid) {
+ longhaul_setstate(i);
+ current_vid = vid;
+ msleep(200);
+ }
+ if (dir)
+ i++;
+ else
+ i--;
+ }
+ longhaul_setstate(table_index);
+ }
+ longhaul_index = table_index;
return 0;
}
@@ -590,11 +657,10 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
static int enable_arbiter_disable(void)
{
struct pci_dev *dev;
- int status;
+ int status = 1;
int reg;
u8 pci_cmd;
- status = 1;
/* Find PLE133 host bridge */
reg = 0x78;
dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
@@ -627,13 +693,17 @@ static int enable_arbiter_disable(void)
return 0;
}
-static int longhaul_setup_vt8235(void)
+static int longhaul_setup_southbridge(void)
{
struct pci_dev *dev;
u8 pci_cmd;
/* Find VT8235 southbridge */
dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
+ if (dev == NULL)
+ /* Find VT8237 southbridge */
+ dev = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_8237, NULL);
if (dev != NULL) {
/* Set transition time to max */
pci_read_config_byte(dev, 0xec, &pci_cmd);
@@ -645,6 +715,14 @@ static int longhaul_setup_vt8235(void)
pci_read_config_byte(dev, 0xe5, &pci_cmd);
pci_cmd |= 1 << 7;
pci_write_config_byte(dev, 0xe5, pci_cmd);
+ /* Get address of ACPI registers block*/
+ pci_read_config_byte(dev, 0x81, &pci_cmd);
+ if (pci_cmd & 1 << 7) {
+ pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
+ acpi_regs_addr &= 0xff00;
+ printk(KERN_INFO PFX "ACPI I/O at 0x%x\n", acpi_regs_addr);
+ }
+
pci_dev_put(dev);
return 1;
}
@@ -657,7 +735,6 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
char *cpuname=NULL;
int ret;
u32 lo, hi;
- int vt8235_present;
/* Check what we have on this motherboard */
switch (c->x86_model) {
@@ -755,7 +832,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
};
/* Doesn't hurt */
- vt8235_present = longhaul_setup_vt8235();
+ longhaul_setup_southbridge();
/* Find ACPI data for processor */
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
@@ -765,35 +842,29 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
/* Check ACPI support for C3 state */
if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
cx = &pr->power.states[ACPI_STATE_C3];
- if (cx->address > 0 && cx->latency <= 1000) {
+ if (cx->address > 0 && cx->latency <= 1000)
longhaul_flags |= USE_ACPI_C3;
- goto print_support_type;
- }
}
+ /* Disable if it isn't working */
+ if (disable_acpi_c3)
+ longhaul_flags &= ~USE_ACPI_C3;
/* Check if northbridge is friendly */
- if (enable_arbiter_disable()) {
+ if (enable_arbiter_disable())
longhaul_flags |= USE_NORTHBRIDGE;
- goto print_support_type;
- }
- /* Use VT8235 southbridge if present */
- if (longhaul_version == TYPE_POWERSAVER && vt8235_present) {
- longhaul_flags |= USE_VT8235;
- goto print_support_type;
- }
+
/* Check ACPI support for bus master arbiter disable */
- if ((pr == NULL) || !(pr->flags.bm_control)) {
+ if (!(longhaul_flags & USE_ACPI_C3
+ || longhaul_flags & USE_NORTHBRIDGE)
+ && ((pr == NULL) || !(pr->flags.bm_control))) {
printk(KERN_ERR PFX
"No ACPI support. Unsupported northbridge.\n");
return -ENODEV;
}
-print_support_type:
if (longhaul_flags & USE_NORTHBRIDGE)
- printk (KERN_INFO PFX "Using northbridge support.\n");
- else if (longhaul_flags & USE_VT8235)
- printk (KERN_INFO PFX "Using VT8235 support.\n");
- else
- printk (KERN_INFO PFX "Using ACPI support.\n");
+ printk(KERN_INFO PFX "Using northbridge support.\n");
+ if (longhaul_flags & USE_ACPI_C3)
+ printk(KERN_INFO PFX "Using ACPI support.\n");
ret = longhaul_get_ranges();
if (ret != 0)
@@ -885,6 +956,9 @@ static void __exit longhaul_exit(void)
kfree(longhaul_table);
}
+module_param (disable_acpi_c3, int, 0644);
+MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
+
module_param (scale_voltage, int, 0644);
MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h
index 102548f1284..4fcc320997d 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.h
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h
@@ -180,7 +180,7 @@ static const int __initdata ezrat_clock_ratio[32] = {
-1, /* 0000 -> RESERVED (10.0x) */
110, /* 0001 -> 11.0x */
- 120, /* 0010 -> 12.0x */
+ -1, /* 0010 -> 12.0x */
-1, /* 0011 -> RESERVED (9.0x)*/
105, /* 0100 -> 10.5x */
115, /* 0101 -> 11.5x */
@@ -237,7 +237,7 @@ static const int __initdata ezrat_eblcr[32] = {
static const int __initdata nehemiah_clock_ratio[32] = {
100, /* 0000 -> 10.0x */
- 160, /* 0001 -> 16.0x */
+ -1, /* 0001 -> 16.0x */
40, /* 0010 -> 4.0x */
90, /* 0011 -> 9.0x */
95, /* 0100 -> 9.5x */
@@ -252,10 +252,10 @@ static const int __initdata nehemiah_clock_ratio[32] = {
75, /* 1101 -> 7.5x */
85, /* 1110 -> 8.5x */
120, /* 1111 -> 12.0x */
- 100, /* 0000 -> 10.0x */
+ -1, /* 0000 -> 10.0x */
110, /* 0001 -> 11.0x */
- 120, /* 0010 -> 12.0x */
- 90, /* 0011 -> 9.0x */
+ -1, /* 0010 -> 12.0x */
+ -1, /* 0011 -> 9.0x */
105, /* 0100 -> 10.5x */
115, /* 0101 -> 11.5x */
125, /* 0110 -> 12.5x */
@@ -267,7 +267,7 @@ static const int __initdata nehemiah_clock_ratio[32] = {
145, /* 1100 -> 14.5x */
155, /* 1101 -> 15.5x */
-1, /* 1110 -> RESERVED (13.0x) */
- 120, /* 1111 -> 12.0x */
+ -1, /* 1111 -> 12.0x */
};
static const int __initdata nehemiah_eblcr[32] = {
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 4ade55c5f33..34ed53a0673 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -599,14 +599,17 @@ static void print_basics(struct powernow_k8_data *data)
for (j = 0; j < data->numps; j++) {
if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
if (cpu_family == CPU_HW_PSTATE) {
- printk(KERN_INFO PFX " %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8,
- (data->powernow_table[j].index & 0xff0000) >> 16,
- data->powernow_table[j].frequency/1000);
+ printk(KERN_INFO PFX " %d : fid 0x%x did 0x%x (%d MHz)\n",
+ j,
+ (data->powernow_table[j].index & 0xff00) >> 8,
+ (data->powernow_table[j].index & 0xff0000) >> 16,
+ data->powernow_table[j].frequency/1000);
} else {
- printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
- data->powernow_table[j].index & 0xff,
- data->powernow_table[j].frequency/1000,
- data->powernow_table[j].index >> 8);
+ printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n",
+ j,
+ data->powernow_table[j].index & 0xff,
+ data->powernow_table[j].frequency/1000,
+ data->powernow_table[j].index >> 8);
}
}
}
@@ -1086,7 +1089,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
if (cpu_family == CPU_HW_PSTATE)
dprintk("targ: curr fid 0x%x, did 0x%x\n",
- data->currfid, data->currvid);
+ data->currfid, data->currdid);
else {
dprintk("targ: curr fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
@@ -1322,16 +1325,22 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
static int __cpuinit powernowk8_init(void)
{
unsigned int i, supported_cpus = 0;
+ unsigned int booted_cores = 1;
for_each_online_cpu(i) {
if (check_supported_cpu(i))
supported_cpus++;
}
+#ifdef CONFIG_SMP
+ booted_cores = cpu_data[0].booted_cores;
+#endif
+
if (supported_cpus == num_online_cpus()) {
printk(KERN_INFO PFX "Found %d %s "
- "processors (" VERSION ")\n", supported_cpus,
- boot_cpu_data.x86_model_id);
+ "processors (%d cpu cores) (" VERSION ")\n",
+ supported_cpus/booted_cores,
+ boot_cpu_data.x86_model_id, supported_cpus);
return cpufreq_register_driver(&cpufreq_amd64_driver);
}
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 35489fd6885..6c5dc2c85ae 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -21,12 +21,6 @@
#include <linux/delay.h>
#include <linux/compiler.h>
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-#include <linux/acpi.h>
-#include <linux/dmi.h>
-#include <acpi/processor.h>
-#endif
-
#include <asm/msr.h>
#include <asm/processor.h>
#include <asm/cpufeature.h>
@@ -257,9 +251,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
/* Matched a non-match */
dprintk("no table support for CPU model \"%s\"\n",
cpu->x86_model_id);
-#ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
- dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
-#endif
+ dprintk("try using the acpi-cpufreq driver\n");
return -ENOENT;
}
@@ -346,213 +338,6 @@ static unsigned int get_cur_freq(unsigned int cpu)
}
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-
-static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
-
-/*
- * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States
- * library
- *
- * Before doing the actual init, we need to do _PSD related setup whenever
- * supported by the BIOS. These are handled by this early_init routine.
- */
-static int centrino_cpu_early_init_acpi(void)
-{
- unsigned int i, j;
- struct acpi_processor_performance *data;
-
- for_each_possible_cpu(i) {
- data = kzalloc(sizeof(struct acpi_processor_performance),
- GFP_KERNEL);
- if (!data) {
- for_each_possible_cpu(j) {
- kfree(acpi_perf_data[j]);
- acpi_perf_data[j] = NULL;
- }
- return (-ENOMEM);
- }
- acpi_perf_data[i] = data;
- }
-
- acpi_processor_preregister_performance(acpi_perf_data);
- return 0;
-}
-
-
-#ifdef CONFIG_SMP
-/*
- * Some BIOSes do SW_ANY coordination internally, either set it up in hw
- * or do it in BIOS firmware and won't inform about it to OS. If not
- * detected, this has a side effect of making CPU run at a different speed
- * than OS intended it to run at. Detect it and handle it cleanly.
- */
-static int bios_with_sw_any_bug;
-static int sw_any_bug_found(struct dmi_system_id *d)
-{
- bios_with_sw_any_bug = 1;
- return 0;
-}
-
-static struct dmi_system_id sw_any_bug_dmi_table[] = {
- {
- .callback = sw_any_bug_found,
- .ident = "Supermicro Server X6DLP",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
- DMI_MATCH(DMI_BIOS_VERSION, "080010"),
- DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
- },
- },
- { }
-};
-#endif
-
-/*
- * centrino_cpu_init_acpi - register with ACPI P-States library
- *
- * Register with the ACPI P-States library (part of drivers/acpi/processor.c)
- * in order to determine correct frequency and voltage pairings by reading
- * the _PSS of the ACPI DSDT or SSDT tables.
- */
-static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
-{
- unsigned long cur_freq;
- int result = 0, i;
- unsigned int cpu = policy->cpu;
- struct acpi_processor_performance *p;
-
- p = acpi_perf_data[cpu];
-
- /* register with ACPI core */
- if (acpi_processor_register_performance(p, cpu)) {
- dprintk(PFX "obtaining ACPI data failed\n");
- return -EIO;
- }
-
- policy->shared_type = p->shared_type;
- /*
- * Will let policy->cpus know about dependency only when software
- * coordination is required.
- */
- if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
- policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
- policy->cpus = p->shared_cpu_map;
- }
-
-#ifdef CONFIG_SMP
- dmi_check_system(sw_any_bug_dmi_table);
- if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
- policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
- policy->cpus = cpu_core_map[cpu];
- }
-#endif
-
- /* verify the acpi_data */
- if (p->state_count <= 1) {
- dprintk("No P-States\n");
- result = -ENODEV;
- goto err_unreg;
- }
-
- if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
- (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
- dprintk("Invalid control/status registers (%x - %x)\n",
- p->control_register.space_id, p->status_register.space_id);
- result = -EIO;
- goto err_unreg;
- }
-
- for (i=0; i<p->state_count; i++) {
- if ((p->states[i].control & INTEL_MSR_RANGE) !=
- (p->states[i].status & INTEL_MSR_RANGE)) {
- dprintk("Different MSR bits in control (%llu) and status (%llu)\n",
- p->states[i].control, p->states[i].status);
- result = -EINVAL;
- goto err_unreg;
- }
-
- if (!p->states[i].core_frequency) {
- dprintk("Zero core frequency for state %u\n", i);
- result = -EINVAL;
- goto err_unreg;
- }
-
- if (p->states[i].core_frequency > p->states[0].core_frequency) {
- dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i,
- p->states[i].core_frequency, p->states[0].core_frequency);
- p->states[i].core_frequency = 0;
- continue;
- }
- }
-
- centrino_model[cpu] = kzalloc(sizeof(struct cpu_model), GFP_KERNEL);
- if (!centrino_model[cpu]) {
- result = -ENOMEM;
- goto err_unreg;
- }
-
- centrino_model[cpu]->model_name=NULL;
- centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000;
- centrino_model[cpu]->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) *
- (p->state_count + 1), GFP_KERNEL);
- if (!centrino_model[cpu]->op_points) {
- result = -ENOMEM;
- goto err_kfree;
- }
-
- for (i=0; i<p->state_count; i++) {
- centrino_model[cpu]->op_points[i].index = p->states[i].control & INTEL_MSR_RANGE;
- centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000;
- dprintk("adding state %i with frequency %u and control value %04x\n",
- i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
- }
- centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END;
-
- cur_freq = get_cur_freq(cpu);
-
- for (i=0; i<p->state_count; i++) {
- if (!p->states[i].core_frequency) {
- dprintk("skipping state %u\n", i);
- centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
- continue;
- }
-
- if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) !=
- (centrino_model[cpu]->op_points[i].frequency)) {
- dprintk("Invalid encoded frequency (%u vs. %u)\n",
- extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0),
- centrino_model[cpu]->op_points[i].frequency);
- result = -EINVAL;
- goto err_kfree_all;
- }
-
- if (cur_freq == centrino_model[cpu]->op_points[i].frequency)
- p->state = i;
- }
-
- /* notify BIOS that we exist */
- acpi_processor_notify_smm(THIS_MODULE);
- printk("speedstep-centrino with X86_SPEEDSTEP_CENTRINO_ACPI "
- "config is deprecated.\n "
- "Use X86_ACPI_CPUFREQ (acpi-cpufreq) instead.\n" );
-
- return 0;
-
- err_kfree_all:
- kfree(centrino_model[cpu]->op_points);
- err_kfree:
- kfree(centrino_model[cpu]);
- err_unreg:
- acpi_processor_unregister_performance(p, cpu);
- dprintk(PFX "invalid ACPI data\n");
- return (result);
-}
-#else
-static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; }
-static inline int centrino_cpu_early_init_acpi(void) { return 0; }
-#endif
-
static int centrino_cpu_init(struct cpufreq_policy *policy)
{
struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
@@ -568,27 +353,25 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC))
centrino_driver.flags |= CPUFREQ_CONST_LOOPS;
- if (centrino_cpu_init_acpi(policy)) {
- if (policy->cpu != 0)
- return -ENODEV;
+ if (policy->cpu != 0)
+ return -ENODEV;
- for (i = 0; i < N_IDS; i++)
- if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
- break;
+ for (i = 0; i < N_IDS; i++)
+ if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
+ break;
- if (i != N_IDS)
- centrino_cpu[policy->cpu] = &cpu_ids[i];
+ if (i != N_IDS)
+ centrino_cpu[policy->cpu] = &cpu_ids[i];
- if (!centrino_cpu[policy->cpu]) {
- dprintk("found unsupported CPU with "
- "Enhanced SpeedStep: send /proc/cpuinfo to "
- MAINTAINER "\n");
- return -ENODEV;
- }
+ if (!centrino_cpu[policy->cpu]) {
+ dprintk("found unsupported CPU with "
+ "Enhanced SpeedStep: send /proc/cpuinfo to "
+ MAINTAINER "\n");
+ return -ENODEV;
+ }
- if (centrino_cpu_init_table(policy)) {
- return -ENODEV;
- }
+ if (centrino_cpu_init_table(policy)) {
+ return -ENODEV;
}
/* Check to see if Enhanced SpeedStep is enabled, and try to
@@ -634,20 +417,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
cpufreq_frequency_table_put_attr(cpu);
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
- if (!centrino_model[cpu]->model_name) {
- static struct acpi_processor_performance *p;
-
- if (acpi_perf_data[cpu]) {
- p = acpi_perf_data[cpu];
- dprintk("unregistering and freeing ACPI data\n");
- acpi_processor_unregister_performance(p, cpu);
- kfree(centrino_model[cpu]->op_points);
- kfree(centrino_model[cpu]);
- }
- }
-#endif
-
centrino_model[cpu] = NULL;
return 0;
@@ -849,25 +618,12 @@ static int __init centrino_init(void)
if (!cpu_has(cpu, X86_FEATURE_EST))
return -ENODEV;
- centrino_cpu_early_init_acpi();
-
return cpufreq_register_driver(&centrino_driver);
}
static void __exit centrino_exit(void)
{
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
- unsigned int j;
-#endif
-
cpufreq_unregister_driver(&centrino_driver);
-
-#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
- for_each_possible_cpu(j) {
- kfree(acpi_perf_data[j]);
- acpi_perf_data[j] = NULL;
- }
-#endif
}
MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>");
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
index 698f980eb44..a5b2346faf1 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
@@ -205,7 +205,6 @@ static unsigned int speedstep_detect_chipset (void)
* host brige. Abort on these systems.
*/
static struct pci_dev *hostbridge;
- u8 rev = 0;
hostbridge = pci_get_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82815_MC,
@@ -216,8 +215,7 @@ static unsigned int speedstep_detect_chipset (void)
if (!hostbridge)
return 2; /* 2-M */
- pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
- if (rev < 5) {
+ if (hostbridge->revision < 5) {
dprintk("hostbridge does not support speedstep\n");
speedstep_chipset_dev = NULL;
pci_dev_put(hostbridge);
diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c
index 9edf5625584..1001f1e0fe6 100644
--- a/arch/i386/kernel/cpu/mtrr/cyrix.c
+++ b/arch/i386/kernel/cpu/mtrr/cyrix.c
@@ -233,12 +233,12 @@ typedef struct {
mtrr_type type;
} arr_state_t;
-static arr_state_t arr_state[8] __devinitdata = {
+static arr_state_t arr_state[8] = {
{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
};
-static unsigned char ccr_state[7] __devinitdata = { 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char ccr_state[7] = { 0, 0, 0, 0, 0, 0, 0 };
static void cyrix_set_all(void)
{
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index c4ebb5126ef..f6e46943e6e 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -42,7 +42,7 @@ static int mtrr_show;
module_param_named(show, mtrr_show, bool, 0);
/* Get the MSR pair relating to a var range */
-static void __init
+static void
get_mtrr_var_range(unsigned int index, struct mtrr_var_range *vr)
{
rdmsr(MTRRphysBase_MSR(index), vr->base_lo, vr->base_hi);
@@ -65,10 +65,11 @@ get_fixed_ranges(mtrr_type * frs)
void mtrr_save_fixed_ranges(void *info)
{
- get_fixed_ranges(mtrr_state.fixed_ranges);
+ if (cpu_has_mtrr)
+ get_fixed_ranges(mtrr_state.fixed_ranges);
}
-static void __cpuinit print_fixed(unsigned base, unsigned step, const mtrr_type*types)
+static void print_fixed(unsigned base, unsigned step, const mtrr_type*types)
{
unsigned i;
@@ -469,11 +470,6 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i
}
}
- if (base < 0x100) {
- printk(KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
- base, size);
- return -EINVAL;
- }
/* Check upper bits of base and last are equal and lower bits are 0
for base and 1 for last */
last = base + size - 1;
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index 1cf466df330..75dc6d5214b 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -229,6 +229,8 @@ static void set_mtrr(unsigned int reg, unsigned long base,
data.smp_size = size;
data.smp_type = type;
atomic_set(&data.count, num_booting_cpus() - 1);
+ /* make sure data.count is visible before unleashing other CPUs */
+ smp_wmb();
atomic_set(&data.gate,0);
/* Start the ball rolling on other CPUs */
@@ -242,6 +244,7 @@ static void set_mtrr(unsigned int reg, unsigned long base,
/* ok, reset count and toggle gate */
atomic_set(&data.count, num_booting_cpus() - 1);
+ smp_wmb();
atomic_set(&data.gate,1);
/* do our MTRR business */
@@ -260,6 +263,7 @@ static void set_mtrr(unsigned int reg, unsigned long base,
cpu_relax();
atomic_set(&data.count, num_booting_cpus() - 1);
+ smp_wmb();
atomic_set(&data.gate,0);
/*
@@ -639,7 +643,7 @@ static struct sysdev_driver mtrr_sysdev_driver = {
* initialized (i.e. before smp_init()).
*
*/
-void mtrr_bp_init(void)
+__init void mtrr_bp_init(void)
{
init_ifs();
@@ -734,10 +738,13 @@ void mtrr_ap_init(void)
*/
void mtrr_save_state(void)
{
- if (smp_processor_id() == 0)
+ int cpu = get_cpu();
+
+ if (cpu == 0)
mtrr_save_fixed_ranges(NULL);
else
smp_call_function_single(0, mtrr_save_fixed_ranges, NULL, 1, 1);
+ put_cpu();
}
static int __init mtrr_init_finialize(void)
diff --git a/arch/i386/kernel/cpu/perfctr-watchdog.c b/arch/i386/kernel/cpu/perfctr-watchdog.c
index 2b04c8f1db6..4d26d514c56 100644
--- a/arch/i386/kernel/cpu/perfctr-watchdog.c
+++ b/arch/i386/kernel/cpu/perfctr-watchdog.c
@@ -28,7 +28,7 @@ struct wd_ops {
void (*unreserve)(void);
int (*setup)(unsigned nmi_hz);
void (*rearm)(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz);
- void (*stop)(void *);
+ void (*stop)(void);
unsigned perfctr;
unsigned evntsel;
u64 checkbit;
@@ -55,14 +55,45 @@ static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
/* converts an msr to an appropriate reservation bit */
static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
{
- return wd_ops ? msr - wd_ops->perfctr : 0;
+ /* returns the bit offset of the performance counter register */
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ return (msr - MSR_K7_PERFCTR0);
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+ return (msr - MSR_ARCH_PERFMON_PERFCTR0);
+
+ switch (boot_cpu_data.x86) {
+ case 6:
+ return (msr - MSR_P6_PERFCTR0);
+ case 15:
+ return (msr - MSR_P4_BPU_PERFCTR0);
+ }
+ }
+ return 0;
}
/* converts an msr to an appropriate reservation bit */
/* returns the bit offset of the event selection register */
static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
{
- return wd_ops ? msr - wd_ops->evntsel : 0;
+ /* returns the bit offset of the event selection register */
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ return (msr - MSR_K7_EVNTSEL0);
+ case X86_VENDOR_INTEL:
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+ return (msr - MSR_ARCH_PERFMON_EVENTSEL0);
+
+ switch (boot_cpu_data.x86) {
+ case 6:
+ return (msr - MSR_P6_EVNTSEL0);
+ case 15:
+ return (msr - MSR_P4_BSU_ESCR0);
+ }
+ }
+ return 0;
+
}
/* checks for a bit availability (hack for oprofile) */
@@ -142,7 +173,7 @@ void disable_lapic_nmi_watchdog(void)
if (atomic_read(&nmi_active) <= 0)
return;
- on_each_cpu(wd_ops->stop, NULL, 0, 1);
+ on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
wd_ops->unreserve();
BUG_ON(atomic_read(&nmi_active) != 0);
@@ -255,7 +286,7 @@ static int setup_k7_watchdog(unsigned nmi_hz)
return 1;
}
-static void single_msr_stop_watchdog(void *arg)
+static void single_msr_stop_watchdog(void)
{
struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
@@ -276,8 +307,8 @@ static int single_msr_reserve(void)
static void single_msr_unreserve(void)
{
- release_evntsel_nmi(wd_ops->perfctr);
- release_perfctr_nmi(wd_ops->evntsel);
+ release_evntsel_nmi(wd_ops->evntsel);
+ release_perfctr_nmi(wd_ops->perfctr);
}
static void single_msr_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
@@ -442,7 +473,7 @@ static int setup_p4_watchdog(unsigned nmi_hz)
return 1;
}
-static void stop_p4_watchdog(void *arg)
+static void stop_p4_watchdog(void)
{
struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
wrmsr(wd->cccr_msr, 0, 0);
@@ -475,10 +506,10 @@ static void p4_unreserve(void)
{
#ifdef CONFIG_SMP
if (smp_num_siblings > 1)
- release_evntsel_nmi(MSR_P4_IQ_PERFCTR1);
+ release_perfctr_nmi(MSR_P4_IQ_PERFCTR1);
#endif
- release_evntsel_nmi(MSR_P4_IQ_PERFCTR0);
- release_perfctr_nmi(MSR_P4_CRU_ESCR0);
+ release_evntsel_nmi(MSR_P4_CRU_ESCR0);
+ release_perfctr_nmi(MSR_P4_IQ_PERFCTR0);
}
static void p4_rearm(struct nmi_watchdog_ctlblk *wd, unsigned nmi_hz)
@@ -614,6 +645,12 @@ int lapic_watchdog_init(unsigned nmi_hz)
probe_nmi_watchdog();
if (!wd_ops)
return -1;
+
+ if (!wd_ops->reserve()) {
+ printk(KERN_ERR
+ "NMI watchdog: cannot reserve perfctrs\n");
+ return -1;
+ }
}
if (!(wd_ops->setup(nmi_hz))) {
@@ -628,7 +665,7 @@ int lapic_watchdog_init(unsigned nmi_hz)
void lapic_watchdog_stop(void)
{
if (wd_ops)
- wd_ops->stop(NULL);
+ wd_ops->stop();
}
unsigned lapic_adjust_nmi_hz(unsigned hz)
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 89d91e6cc97..1e31b6caffb 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -29,7 +29,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL,
- NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow",
+ NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm",
+ "3dnowext", "3dnow",
/* Transmeta-defined */
"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -40,8 +41,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Other (Linux-defined) */
"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
NULL, NULL, NULL, NULL,
- "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "constant_tsc", "up", NULL, "arch_perfmon",
+ "pebs", "bts", NULL, "sync_rdtsc",
+ "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* Intel-defined (#2) */
@@ -57,9 +59,16 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* AMD-defined (#2) */
- "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm",
- "sse4a", "misalignsse",
- "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL,
+ "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy",
+ "altmovcr8", "abm", "sse4a",
+ "misalignsse", "3dnowprefetch",
+ "osvw", "ibs", NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ /* Auxiliary (Linux-defined) */
+ "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
diff --git a/arch/i386/kernel/e820.c b/arch/i386/kernel/e820.c
index 9645bb51f76..fc822a46897 100644
--- a/arch/i386/kernel/e820.c
+++ b/arch/i386/kernel/e820.c
@@ -734,7 +734,7 @@ void __init print_memory_map(char *who)
case E820_NVS:
printk("(ACPI NVS)\n");
break;
- default: printk("type %lu\n", e820.map[i].type);
+ default: printk("type %u\n", e820.map[i].type);
break;
}
}
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index b1f16ee65e4..3c3c220488c 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -367,10 +367,6 @@ ENTRY(system_call)
CFI_ADJUST_CFA_OFFSET 4
SAVE_ALL
GET_THREAD_INFO(%ebp)
- testl $TF_MASK,PT_EFLAGS(%esp)
- jz no_singlestep
- orl $_TIF_SINGLESTEP,TI_flags(%ebp)
-no_singlestep:
# system call tracing in operation / emulation
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
@@ -385,6 +381,10 @@ syscall_exit:
# setting need_resched or sigpending
# between sampling and the iret
TRACE_IRQS_OFF
+ testl $TF_MASK,PT_EFLAGS(%esp) # If tracing set singlestep flag on exit
+ jz no_singlestep
+ orl $_TIF_SINGLESTEP,TI_flags(%ebp)
+no_singlestep:
movl TI_flags(%ebp), %ecx
testw $_TIF_ALLWORK_MASK, %cx # current->work
jne syscall_exit_work
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 83f825f2e2d..d865d041bea 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -478,7 +478,7 @@ static int __init microcode_dev_init (void)
return 0;
}
-static void __exit microcode_dev_exit (void)
+static void microcode_dev_exit (void)
{
misc_deregister(&microcode_dev);
}
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 30b754f7cbe..048f09b6255 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/pci.h>
#include <asm/io.h>
struct dma_coherent_mem {
@@ -148,3 +149,29 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
return mem->virt_base + (pos << PAGE_SHIFT);
}
EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
+
+#ifdef CONFIG_PCI
+/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+
+int forbid_dac;
+EXPORT_SYMBOL(forbid_dac);
+
+static __devinit void via_no_dac(struct pci_dev *dev)
+{
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+ printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+ forbid_dac = 1;
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+
+static int check_iommu(char *s)
+{
+ if (!strcmp(s, "usedac")) {
+ forbid_dac = -1;
+ return 1;
+ }
+ return 0;
+}
+__setup("iommu=", check_iommu);
+#endif
diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c
index 9f6ab1789bb..6722469c263 100644
--- a/arch/i386/kernel/quirks.c
+++ b/arch/i386/kernel/quirks.c
@@ -20,8 +20,6 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
if (rev > 0x9)
return;
- printk(KERN_INFO "Intel E7520/7320/7525 detected.");
-
/* enable access to config space*/
pci_read_config_byte(dev, 0xf4, &config);
pci_write_config_byte(dev, 0xf4, config|0x2);
@@ -30,7 +28,8 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
if (!(word & (1 << 13))) {
- printk(KERN_INFO "Disabling irq balancing and affinity\n");
+ printk(KERN_INFO "Intel E7520/7320/7525 detected. "
+ "Disabling irq balancing and affinity\n");
#ifdef CONFIG_IRQBALANCE
irqbalance_disable("");
#endif
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 50dfc65319c..5513f8d5b5b 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -89,6 +89,14 @@ static int __init set_bios_reboot(struct dmi_system_id *d)
}
static struct dmi_system_id __initdata reboot_dmi_table[] = {
+ { /* Handle problems with rebooting on Dell E520's */
+ .callback = set_bios_reboot,
+ .ident = "Dell E520",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM061"),
+ },
+ },
{ /* Handle problems with rebooting on Dell 1300's */
.callback = set_bios_reboot,
.ident = "Dell PowerEdge 1300",
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 2d78d918340..03e1cce58f4 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -5,12 +5,14 @@
*
* List of supported fixups:
* geode-gx1/cs5530a - Jaya Kumar <jayalk@intworks.biz>
+ * geode-gx/lx/cs5536 - Andres Salomon <dilinger@debian.org>
*
*/
#include <asm/delay.h>
#include <linux/pci.h>
#include <asm/reboot_fixups.h>
+#include <asm/msr.h>
static void cs5530a_warm_reset(struct pci_dev *dev)
{
@@ -21,6 +23,16 @@ static void cs5530a_warm_reset(struct pci_dev *dev)
return;
}
+static void cs5536_warm_reset(struct pci_dev *dev)
+{
+ /*
+ * 6.6.2.12 Soft Reset (DIVIL_SOFT_RESET)
+ * writing 1 to the LSB of this MSR causes a hard reset.
+ */
+ wrmsrl(0x51400017, 1ULL);
+ udelay(50); /* shouldn't get here but be safe and spin a while */
+}
+
struct device_fixup {
unsigned int vendor;
unsigned int device;
@@ -29,6 +41,7 @@ struct device_fixup {
static struct device_fixup fixups_table[] = {
{ PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset },
+{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset },
};
/*
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 698c24fe482..2d61e65eeb5 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -102,19 +102,10 @@ static unsigned int highmem_pages = -1;
/*
* Setup options
*/
-struct drive_info_struct { char dummy[32]; } drive_info;
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \
- defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
-EXPORT_SYMBOL(drive_info);
-#endif
struct screen_info screen_info;
EXPORT_SYMBOL(screen_info);
struct apm_info apm_info;
EXPORT_SYMBOL(apm_info);
-struct sys_desc_table_struct {
- unsigned short length;
- unsigned char table[0];
-};
struct edid_info edid_info;
EXPORT_SYMBOL_GPL(edid_info);
struct ist_info ist_info;
@@ -134,7 +125,7 @@ unsigned long saved_videomode;
static char __initdata command_line[COMMAND_LINE_SIZE];
-unsigned char __initdata boot_params[PARAM_SIZE];
+struct boot_params __initdata boot_params;
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
struct edd edd;
@@ -528,7 +519,6 @@ void __init setup_arch(char **cmdline_p)
#endif
ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
- drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
edid_info = EDID_INFO;
apm_info.bios = APM_BIOS_INFO;
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 08f07a74a9d..0b2954534b8 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -941,18 +941,6 @@ exit:
}
#endif
-static void smp_tune_scheduling(void)
-{
- unsigned long cachesize; /* kB */
-
- if (cpu_khz) {
- cachesize = boot_cpu_data.x86_cache_size;
-
- if (cachesize > 0)
- max_cache_size = cachesize * 1024;
- }
-}
-
/*
* Cycle through the processors sending APIC IPIs to boot each.
*/
@@ -981,7 +969,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
current_thread_info()->cpu = 0;
- smp_tune_scheduling();
set_cpu_sibling_map(0);
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index f64b81f3033..ea63a30ca3e 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -4,6 +4,7 @@
* See comments there for proper credits.
*/
+#include <linux/sched.h>
#include <linux/clocksource.h>
#include <linux/workqueue.h>
#include <linux/cpufreq.h>
@@ -106,8 +107,13 @@ unsigned long long sched_clock(void)
/*
* Fall back to jiffies if there's no TSC available:
+ * ( But note that we still use it if the TSC is marked
+ * unstable. We do this because unlike Time Of Day,
+ * the scheduler clock tolerates small errors and it's
+ * very important for it to be as fast as the platform
+ * can achive it. )
*/
- if (unlikely(!tsc_enabled))
+ if (unlikely(!tsc_enabled && !tsc_unstable))
/* No locking but a rare wrong value is not a big deal: */
return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
@@ -277,6 +283,7 @@ static struct clocksource clocksource_tsc = {
void mark_tsc_unstable(char *reason)
{
+ sched_clock_unstable_event();
if (!tsc_unstable) {
tsc_unstable = 1;
tsc_enabled = 0;
diff --git a/arch/i386/kernel/verify_cpu.S b/arch/i386/kernel/verify_cpu.S
deleted file mode 100644
index f1d1eacf4ab..00000000000
--- a/arch/i386/kernel/verify_cpu.S
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Check if CPU has some minimum CPUID bits
- This runs in 16bit mode so that the caller can still use the BIOS
- to output errors on the screen */
-#include <asm/cpufeature.h>
-#include <asm/msr.h>
-
-verify_cpu:
- pushfl # Save caller passed flags
- pushl $0 # Kill any dangerous flags
- popfl
-
-#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4
- pushfl
- pop %eax
- orl $(1<<18),%eax # try setting AC
- push %eax
- popfl
- pushfl
- popl %eax
- testl $(1<<18),%eax
- jz bad
-#endif
-#if REQUIRED_MASK1 != 0
- pushfl # standard way to check for cpuid
- popl %eax
- movl %eax,%ebx
- xorl $0x200000,%eax
- pushl %eax
- popfl
- pushfl
- popl %eax
- cmpl %eax,%ebx
- pushfl # standard way to check for cpuid
- popl %eax
- movl %eax,%ebx
- xorl $0x200000,%eax
- pushl %eax
- popfl
- pushfl
- popl %eax
- cmpl %eax,%ebx
- jz bad # REQUIRED_MASK1 != 0 requires CPUID
-
- movl $0x0,%eax # See if cpuid 1 is implemented
- cpuid
- cmpl $0x1,%eax
- jb bad # no cpuid 1
-
-#if REQUIRED_MASK1 & NEED_CMPXCHG64
- /* Some VIA C3s need magic MSRs to enable CX64. Do this here */
- cmpl $0x746e6543,%ebx # Cent
- jne 1f
- cmpl $0x48727561,%edx # aurH
- jne 1f
- cmpl $0x736c7561,%ecx # auls
- jne 1f
- movl $1,%eax # check model
- cpuid
- movl %eax,%ebx
- shr $8,%ebx
- andl $0xf,%ebx
- cmp $6,%ebx # check family == 6
- jne 1f
- shr $4,%eax
- andl $0xf,%eax
- cmpl $6,%eax # check model >= 6
- jb 1f
- # assume models >= 6 all support this MSR
- movl $MSR_VIA_FCR,%ecx
- rdmsr
- orl $((1<<1)|(1<<7)),%eax # enable CMPXCHG64 and PGE
- wrmsr
-1:
-#endif
- movl $0x1,%eax # Does the cpu have what it takes
- cpuid
-
-#if CONFIG_X86_MINIMUM_CPU_MODEL > 4
-#error add proper model checking here
-#endif
-
- andl $REQUIRED_MASK1,%edx
- xorl $REQUIRED_MASK1,%edx
- jnz bad
-#endif /* REQUIRED_MASK1 */
-
- popfl
- xor %eax,%eax
- ret
-
-bad:
- popfl
- movl $1,%eax
- ret
diff --git a/arch/i386/kernel/vmi.c b/arch/i386/kernel/vmi.c
index c8726c424b3..c12720d7cbc 100644
--- a/arch/i386/kernel/vmi.c
+++ b/arch/i386/kernel/vmi.c
@@ -27,6 +27,7 @@
#include <linux/bootmem.h>
#include <linux/mm.h>
#include <linux/highmem.h>
+#include <linux/sched.h>
#include <asm/vmi.h>
#include <asm/io.h>
#include <asm/fixmap.h>
diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
index 9be6ceabf04..ab99072d3f9 100644
--- a/arch/i386/mach-es7000/es7000plat.c
+++ b/arch/i386/mach-es7000/es7000plat.c
@@ -40,6 +40,7 @@
#include <asm/smp.h>
#include <asm/apicdef.h>
#include "es7000.h"
+#include <mach_mpparse.h>
/*
* ES7000 Globals
@@ -174,6 +175,53 @@ find_unisys_acpi_oem_table(unsigned long *oem_addr)
}
#endif
+/*
+ * This file also gets compiled if CONFIG_X86_GENERICARCH is set. Generic
+ * arch already has got following function definitions (asm-generic/es7000.c)
+ * hence no need to define these for that case.
+ */
+#ifndef CONFIG_X86_GENERICARCH
+void es7000_sw_apic(void);
+void __init enable_apic_mode(void)
+{
+ es7000_sw_apic();
+ return;
+}
+
+__init int mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid)
+{
+ if (mpc->mpc_oemptr) {
+ struct mp_config_oemtable *oem_table =
+ (struct mp_config_oemtable *)mpc->mpc_oemptr;
+ if (!strncmp(oem, "UNISYS", 6))
+ return parse_unisys_oem((char *)oem_table);
+ }
+ return 0;
+}
+#ifdef CONFIG_ACPI
+/* Hook from generic ACPI tables.c */
+int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+ unsigned long oem_addr;
+ if (!find_unisys_acpi_oem_table(&oem_addr)) {
+ if (es7000_check_dsdt())
+ return parse_unisys_oem((char *)oem_addr);
+ else {
+ setup_unisys();
+ return 1;
+ }
+ }
+ return 0;
+}
+#else
+int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+ return 0;
+}
+#endif
+#endif /* COFIG_X86_GENERICARCH */
+
static void
es7000_spin(int n)
{
diff --git a/arch/i386/mach-visws/traps.c b/arch/i386/mach-visws/traps.c
index 5199bd03254..843b67acf43 100644
--- a/arch/i386/mach-visws/traps.c
+++ b/arch/i386/mach-visws/traps.c
@@ -23,13 +23,13 @@ static __init void lithium_init(void)
set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
if ((li_pcia_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
- (li_pcia_read16(PCI_DEVICE_ID) != PCI_VENDOR_ID_SGI_LITHIUM)) {
+ (li_pcia_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'A');
panic("This machine is not SGI Visual Workstation 320/540");
}
if ((li_pcib_read16(PCI_VENDOR_ID) != PCI_VENDOR_ID_SGI) ||
- (li_pcib_read16(PCI_DEVICE_ID) != PCI_VENDOR_ID_SGI_LITHIUM)) {
+ (li_pcib_read16(PCI_DEVICE_ID) != PCI_DEVICE_ID_SGI_LITHIUM)) {
printk(KERN_EMERG "Lithium hostbridge %c not found\n", 'B');
panic("This machine is not SGI Visual Workstation 320/540");
}
diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c
index ddf8fa3bbd0..1853524c8b5 100644
--- a/arch/i386/math-emu/fpu_entry.c
+++ b/arch/i386/math-emu/fpu_entry.c
@@ -754,7 +754,7 @@ int save_i387_soft(void *s387, struct _fpstate __user * buf)
return -1;
if ( offset )
if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
- return -1
+ return -1;
RE_ENTRANT_CHECK_ON;
return 1;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 29d7d61543a..1ecb3e43b52 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -458,6 +458,11 @@ bad_area:
bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */
if (error_code & 4) {
+ /*
+ * It's possible to have interrupts off here.
+ */
+ local_irq_enable();
+
/*
* Valid to do another page fault here because this one came
* from user space.
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index b22ce8d6b1b..7135946d366 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -799,6 +799,7 @@ void mark_rodata_ro(void)
unsigned long start = PFN_ALIGN(_text);
unsigned long size = PFN_ALIGN(_etext) - start;
+#ifndef CONFIG_KPROBES
#ifdef CONFIG_HOTPLUG_CPU
/* It must still be possible to apply SMP alternatives. */
if (num_possible_cpus() <= 1)
@@ -808,7 +809,7 @@ void mark_rodata_ro(void)
size >> PAGE_SHIFT, PAGE_KERNEL_RX);
printk("Write protecting the kernel text: %luk\n", size >> 10);
}
-
+#endif
start += size;
size = (unsigned long)__end_rodata - start;
change_page_attr(virt_to_page(start),
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index 47bd477c8ec..2eb14a73be9 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -68,14 +68,23 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot,
return base;
}
-static void flush_kernel_map(void *arg)
+static void cache_flush_page(struct page *p)
{
- unsigned long adr = (unsigned long)arg;
+ unsigned long adr = (unsigned long)page_address(p);
+ int i;
+ for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+ asm volatile("clflush (%0)" :: "r" (adr + i));
+}
+
+static void flush_kernel_map(void *arg)
+{
+ struct list_head *lh = (struct list_head *)arg;
+ struct page *p;
- if (adr && cpu_has_clflush) {
- int i;
- for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
- asm volatile("clflush (%0)" :: "r" (adr + i));
+ /* High level code is not ready for clflush yet */
+ if (0 && cpu_has_clflush) {
+ list_for_each_entry (p, lh, lru)
+ cache_flush_page(p);
} else if (boot_cpu_data.x86_model >= 4)
wbinvd();
@@ -181,9 +190,9 @@ __change_page_attr(struct page *page, pgprot_t prot)
return 0;
}
-static inline void flush_map(void *adr)
+static inline void flush_map(struct list_head *l)
{
- on_each_cpu(flush_kernel_map, adr, 1, 1);
+ on_each_cpu(flush_kernel_map, l, 1, 1);
}
/*
@@ -225,11 +234,8 @@ void global_flush_tlb(void)
spin_lock_irq(&cpa_lock);
list_replace_init(&df_list, &l);
spin_unlock_irq(&cpa_lock);
- if (!cpu_has_clflush)
- flush_map(NULL);
+ flush_map(&l);
list_for_each_entry_safe(pg, next, &l, lru) {
- if (cpu_has_clflush)
- flush_map(page_address(pg));
__free_page(pg);
}
}
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index a7c0783b269..11b7a51566a 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -154,7 +154,7 @@ static int allocate_msrs(void)
size_t counters_size = sizeof(struct op_msr) * model->num_counters;
int i;
- for_each_online_cpu(i) {
+ for_each_possible_cpu(i) {
cpu_msrs[i].counters = kmalloc(counters_size, GFP_KERNEL);
if (!cpu_msrs[i].counters) {
success = 0;
@@ -211,8 +211,14 @@ static int nmi_setup(void)
/* Assume saved/restored counters are the same on all CPUs */
model->fill_in_addresses(&cpu_msrs[0]);
for_each_possible_cpu (cpu) {
- if (cpu != 0)
- cpu_msrs[cpu] = cpu_msrs[0];
+ if (cpu != 0) {
+ memcpy(cpu_msrs[cpu].counters, cpu_msrs[0].counters,
+ sizeof(struct op_msr) * model->num_counters);
+
+ memcpy(cpu_msrs[cpu].controls, cpu_msrs[0].controls,
+ sizeof(struct op_msr) * model->num_controls);
+ }
+
}
on_each_cpu(nmi_save_registers, NULL, 0, 1);
on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index b62eafb997b..e7306dbf6c4 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -118,12 +118,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci
static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
{
u8 v;
- u8 revision;
int where = 0x55;
int mask = 0x1f; /* clear bits 5, 6, 7 by default */
- pci_read_config_byte(d, PCI_REVISION_ID, &revision);
-
if (d->device == PCI_DEVICE_ID_VIA_8367_0) {
/* fix pci bus latency issues resulted by NB bios error
it appears on bug free^Wreduced kt266x's bios forces
@@ -133,8 +130,8 @@ static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
where = 0x95; /* the memory write queue timer register is
different for the KT266x's: 0x95 not 0x55 */
} else if (d->device == PCI_DEVICE_ID_VIA_8363_0 &&
- (revision == VIA_8363_KL133_REVISION_ID ||
- revision == VIA_8363_KM133_REVISION_ID)) {
+ (d->revision == VIA_8363_KL133_REVISION_ID ||
+ d->revision == VIA_8363_KM133_REVISION_ID)) {
mask = 0x3f; /* clear only bits 6 and 7; clearing bit 5
causes screen corruption on the KL133/KM133 */
}
@@ -142,7 +139,7 @@ static void pci_fixup_via_northbridge_bug(struct pci_dev *d)
pci_read_config_byte(d, where, &v);
if (v & ~mask) {
printk(KERN_WARNING "Disabling VIA memory write queue (PCI ID %04x, rev %02x): [%02x] %02x & %02x -> %02x\n", \
- d->device, revision, where, v, mask, v & mask);
+ d->device, d->revision, where, v, mask, v & mask);
v &= mask;
pci_write_config_byte(d, where, v);
}
@@ -436,3 +433,14 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
pci_early_fixup_cyrix_5530);
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY,
pci_early_fixup_cyrix_5530);
+
+/*
+ * Siemens Nixdorf AG FSC Multiprocessor Interrupt Controller:
+ * prevent update of the BAR0, which doesn't look like a normal BAR.
+ */
+static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev)
+{
+ dev->resource[0].flags |= IORESOURCE_PCI_FIXED;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015,
+ pci_siemens_interrupt_controller);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index de1bff65996..db9ddff9584 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -520,8 +520,10 @@ config PCI
here unless you are using a simulator without PCI support.
config PCI_DOMAINS
- bool
- default PCI
+ def_bool PCI
+
+config PCI_SYSCALL
+ def_bool PCI
source "drivers/pci/pcie/Kconfig"
diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
index 3274850cf27..74b1ccce4e8 100644
--- a/arch/ia64/kernel/gate.S
+++ b/arch/ia64/kernel/gate.S
@@ -30,6 +30,7 @@
.previous
#define BRL_COND_FSYS_BUBBLE_DOWN(pr) \
[1:](pr)brl.cond.sptk 0; \
+ ;; \
.xdata4 ".data.patch.brl_fsys_bubble_down", 1b-.
GLOBAL_ENTRY(__kernel_syscall_via_break)
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 1ead5ea6c5c..4b5daa3cc0f 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -57,6 +57,9 @@
*
* 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
* Add printing support for MCA/INIT.
+ *
+ * 2007-04-27 Russ Anderson <rja@sgi.com>
+ * Support multiple cpus going through OS_MCA in the same event.
*/
#include <linux/types.h>
#include <linux/init.h>
@@ -96,7 +99,6 @@
#endif
/* Used by mca_asm.S */
-u32 ia64_mca_serialize;
DEFINE_PER_CPU(u64, ia64_mca_data); /* == __per_cpu_mca[smp_processor_id()] */
DEFINE_PER_CPU(u64, ia64_mca_per_cpu_pte); /* PTE to map per-CPU area */
DEFINE_PER_CPU(u64, ia64_mca_pal_pte); /* PTE to map PAL code */
@@ -963,11 +965,12 @@ ia64_mca_modify_original_stack(struct pt_regs *regs,
goto no_mod;
}
+ if (r13 != sos->prev_IA64_KR_CURRENT) {
+ msg = "inconsistent previous current and r13";
+ goto no_mod;
+ }
+
if (!mca_recover_range(ms->pmsa_iip)) {
- if (r13 != sos->prev_IA64_KR_CURRENT) {
- msg = "inconsistent previous current and r13";
- goto no_mod;
- }
if ((r12 - r13) >= KERNEL_STACK_SIZE) {
msg = "inconsistent r12 and r13";
goto no_mod;
@@ -1187,6 +1190,13 @@ all_in:
* further MCA logging is enabled by clearing logs.
* Monarch also has the duty of sending wakeup-IPIs to pull the
* slave processors out of rendezvous spinloop.
+ *
+ * If multiple processors call into OS_MCA, the first will become
+ * the monarch. Subsequent cpus will be recorded in the mca_cpu
+ * bitmask. After the first monarch has processed its MCA, it
+ * will wake up the next cpu in the mca_cpu bitmask and then go
+ * into the rendezvous loop. When all processors have serviced
+ * their MCA, the last monarch frees up the rest of the processors.
*/
void
ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
@@ -1196,16 +1206,32 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
struct task_struct *previous_current;
struct ia64_mca_notify_die nd =
{ .sos = sos, .monarch_cpu = &monarch_cpu };
+ static atomic_t mca_count;
+ static cpumask_t mca_cpu;
+ if (atomic_add_return(1, &mca_count) == 1) {
+ monarch_cpu = cpu;
+ sos->monarch = 1;
+ } else {
+ cpu_set(cpu, mca_cpu);
+ sos->monarch = 0;
+ }
mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d "
"monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch);
previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
- monarch_cpu = cpu;
+
if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0)
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
- ia64_wait_for_slaves(cpu, "MCA");
+ if (sos->monarch) {
+ ia64_wait_for_slaves(cpu, "MCA");
+ } else {
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
+ while (cpu_isset(cpu, mca_cpu))
+ cpu_relax(); /* spin until monarch wakes us */
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+ }
/* Wakeup all the processors which are spinning in the rendezvous loop.
* They will leave SAL, then spin in the OS with interrupts disabled
@@ -1244,6 +1270,26 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
== NOTIFY_STOP)
ia64_mca_spin(__FUNCTION__);
+
+ if (atomic_dec_return(&mca_count) > 0) {
+ int i;
+
+ /* wake up the next monarch cpu,
+ * and put this cpu in the rendez loop.
+ */
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA;
+ for_each_online_cpu(i) {
+ if (cpu_isset(i, mca_cpu)) {
+ monarch_cpu = i;
+ cpu_clear(i, mca_cpu); /* wake next cpu */
+ while (monarch_cpu != -1)
+ cpu_relax(); /* spin until last cpu leaves */
+ ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
+ set_curr_task(cpu, previous_current);
+ return;
+ }
+ }
+ }
set_curr_task(cpu, previous_current);
monarch_cpu = -1;
}
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 8c9c26aa6ae..0f5965fcdf8 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -133,14 +133,6 @@ ia64_do_tlb_purge:
//StartMain////////////////////////////////////////////////////////////////////
ia64_os_mca_dispatch:
- // Serialize all MCA processing
- mov r3=1;;
- LOAD_PHYSICAL(p0,r2,ia64_mca_serialize);;
-ia64_os_mca_spin:
- xchg4 r4=[r2],r3;;
- cmp.ne p6,p0=r4,r0
-(p6) br ia64_os_mca_spin
-
mov r3=IA64_MCA_CPU_MCA_STACK_OFFSET // use the MCA stack
LOAD_PHYSICAL(p0,r2,1f) // return address
mov r19=1 // All MCA events are treated as monarch (for now)
@@ -291,10 +283,6 @@ END(ia64_os_mca_virtual_begin)
mov b0=r12 // SAL_CHECK return address
- // release lock
- LOAD_PHYSICAL(p0,r3,ia64_mca_serialize);;
- st4.rel [r3]=r0
-
br b0
//EndMain//////////////////////////////////////////////////////////////////////
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
index f2d4900751b..3bccb06c8d2 100644
--- a/arch/ia64/kernel/mca_drv_asm.S
+++ b/arch/ia64/kernel/mca_drv_asm.S
@@ -40,7 +40,11 @@ GLOBAL_ENTRY(mca_handler_bhhook)
mov b6=loc1
;;
mov loc1=rp
- ssm psr.i | psr.ic
+ ssm psr.ic
+ ;;
+ srlz.i
+ ;;
+ ssm psr.i
br.call.sptk.many rp=b6 // does not return ...
;;
mov ar.pfs=loc0
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index af73b8dfde2..fa40cba4335 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -513,7 +513,8 @@ copy_thread (int nr, unsigned long clone_flags,
static void
do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg)
{
- unsigned long mask, sp, nat_bits = 0, ip, ar_rnat, urbs_end, cfm;
+ unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm;
+ unsigned long uninitialized_var(ip); /* GCC be quiet */
elf_greg_t *dst = arg;
struct pt_regs *pt;
char nat;
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index eaa6a24bc0b..188fb73c684 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -805,7 +805,6 @@ static void __cpuinit
get_max_cacheline_size (void)
{
unsigned long line_size, max = 1;
- unsigned int cache_size = 0;
u64 l, levels, unique_caches;
pal_cache_config_info_t cci;
s64 status;
@@ -835,8 +834,6 @@ get_max_cacheline_size (void)
line_size = 1 << cci.pcci_line_size;
if (line_size > max)
max = line_size;
- if (cache_size < cci.pcci_cache_size)
- cache_size = cci.pcci_cache_size;
if (!cci.pcci_unified) {
status = ia64_pal_cache_config_info(l,
/* cache_type (instruction)= */ 1,
@@ -853,9 +850,6 @@ get_max_cacheline_size (void)
ia64_i_cache_stride_shift = cci.pcci_stride;
}
out:
-#ifdef CONFIG_SMP
- max_cache_size = max(max_cache_size, cache_size);
-#endif
if (max > ia64_max_cacheline_size)
ia64_max_cacheline_size = max;
}
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index a06667c7acc..3486fe7d6e6 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -18,7 +18,6 @@
#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/efi.h>
-#include <linux/profile.h>
#include <linux/timex.h>
#include <asm/machvec.h>
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index b0b08b5f3ec..c1bdb513181 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1856,11 +1856,19 @@ find_save_locs (struct unw_frame_info *info)
return 0;
}
+static int
+unw_valid(const struct unw_frame_info *info, unsigned long* p)
+{
+ unsigned long loc = (unsigned long)p;
+ return (loc >= info->regstk.limit && loc < info->regstk.top) ||
+ (loc >= info->memstk.top && loc < info->memstk.limit);
+}
+
int
unw_unwind (struct unw_frame_info *info)
{
unsigned long prev_ip, prev_sp, prev_bsp;
- unsigned long ip, pr, num_regs, rp_loc, pfs_loc;
+ unsigned long ip, pr, num_regs;
STAT(unsigned long start, flags;)
int retval;
@@ -1871,8 +1879,7 @@ unw_unwind (struct unw_frame_info *info)
prev_bsp = info->bsp;
/* validate the return IP pointer */
- rp_loc = (unsigned long) info->rp_loc;
- if ((rp_loc < info->regstk.limit) || (rp_loc > info->regstk.top)) {
+ if (!unw_valid(info, info->rp_loc)) {
/* FIXME: should really be level 0 but it occurs too often. KAO */
UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
__FUNCTION__, info->ip);
@@ -1888,8 +1895,7 @@ unw_unwind (struct unw_frame_info *info)
}
/* validate the previous stack frame pointer */
- pfs_loc = (unsigned long) info->pfs_loc;
- if ((pfs_loc < info->regstk.limit) || (pfs_loc > info->regstk.top)) {
+ if (!unw_valid(info, info->pfs_loc)) {
UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1;
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index 1346b7f0539..d22861c5b04 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -15,6 +15,7 @@
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
+#include <linux/log2.h>
#include <asm/mman.h>
#include <asm/pgalloc.h>
#include <asm/tlb.h>
@@ -182,7 +183,7 @@ static int __init hugetlb_setup_sz(char *str)
tr_pages = 0x15557000UL;
size = memparse(str, &str);
- if (*str || (size & (size-1)) || !(tr_pages & size) ||
+ if (*str || !is_power_of_2(size) || !(tr_pages & size) ||
size <= PAGE_SIZE ||
size >= (1UL << PAGE_SHIFT << MAX_ORDER)) {
printk(KERN_WARNING "Invalid huge page size specified\n");
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index fa4e6d4810f..1682fc63903 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -175,7 +175,7 @@ EXPORT_SYMBOL(flush_tlb_range);
void __devinit
ia64_tlb_init (void)
{
- ia64_ptce_info_t ptce_info;
+ ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
unsigned long tr_pgbits;
long status;
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 73696b4a2ee..07d0e92742c 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -591,6 +591,9 @@ int
pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine)
{
+ unsigned long size = vma->vm_end - vma->vm_start;
+ pgprot_t prot;
+
/*
* I/O space cannot be accessed via normal processor loads and
* stores on this platform.
@@ -604,15 +607,24 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
*/
return -EINVAL;
+ if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
+ return -EINVAL;
+
+ prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
+ vma->vm_page_prot);
+
/*
- * Leave vm_pgoff as-is, the PCI space address is the physical
- * address on this platform.
+ * If the user requested WC, the kernel uses UC or WC for this region,
+ * and the chipset supports WC, we can use WC. Otherwise, we have to
+ * use the same attribute the kernel uses.
*/
- if (write_combine && efi_range_is_wc(vma->vm_start,
- vma->vm_end - vma->vm_start))
+ if (write_combine &&
+ ((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC ||
+ (pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) &&
+ efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
else
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_page_prot = prot;
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c
index c6216f454ff..3c7178f5dce 100644
--- a/arch/ia64/sn/kernel/io_acpi_init.c
+++ b/arch/ia64/sn/kernel/io_acpi_init.c
@@ -418,7 +418,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
void __iomem *addr;
struct pcidev_info *pcidev_info = NULL;
struct sn_irq_info *sn_irq_info = NULL;
- size_t size;
+ size_t image_size, size;
if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
panic("%s: Failure obtaining pcidev_info for %s\n",
@@ -428,17 +428,16 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
/*
* A valid ROM image exists and has been shadowed by the
- * PROM. Setup the pci_dev ROM resource to point to
- * the shadowed copy.
+ * PROM. Setup the pci_dev ROM resource with the address
+ * of the shadowed copy, and the actual length of the ROM image.
*/
- size = dev->resource[PCI_ROM_RESOURCE].end -
- dev->resource[PCI_ROM_RESOURCE].start;
- addr =
- ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
- size);
+ size = pci_resource_len(dev, PCI_ROM_RESOURCE);
+ addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
+ size);
+ image_size = pci_get_rom_size(addr, size);
dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
dev->resource[PCI_ROM_RESOURCE].end =
- (unsigned long) addr + size;
+ (unsigned long) addr + image_size - 1;
dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
}
sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 6b10e5d2848..906b93674b7 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -259,9 +259,23 @@ sn_io_slot_fixup(struct pci_dev *dev)
insert_resource(&ioport_resource, &dev->resource[idx]);
else
insert_resource(&iomem_resource, &dev->resource[idx]);
- /* If ROM, mark as shadowed in PROM */
- if (idx == PCI_ROM_RESOURCE)
- dev->resource[idx].flags |= IORESOURCE_ROM_BIOS_COPY;
+ /*
+ * If ROM, set the actual ROM image size, and mark as
+ * shadowed in PROM.
+ */
+ if (idx == PCI_ROM_RESOURCE) {
+ size_t image_size;
+ void __iomem *rom;
+
+ rom = ioremap(pci_resource_start(dev, PCI_ROM_RESOURCE),
+ size + 1);
+ image_size = pci_get_rom_size(rom, size + 1);
+ dev->resource[PCI_ROM_RESOURCE].end =
+ dev->resource[PCI_ROM_RESOURCE].start +
+ image_size - 1;
+ dev->resource[PCI_ROM_RESOURCE].flags |=
+ IORESOURCE_ROM_BIOS_COPY;
+ }
}
/* Create a pci_window in the pci_controller struct for
* each device resource.
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 493380b2c05..5a289e4de83 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -369,7 +369,7 @@ static void tio_corelet_reset(nasid_t nasid, int corelet)
static int is_fpga_tio(int nasid, int *bt)
{
- u16 ioboard_type;
+ u16 uninitialized_var(ioboard_type); /* GCC be quiet */
s64 rc;
rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard_type);
diff --git a/arch/ia64/sn/kernel/xp_nofault.S b/arch/ia64/sn/kernel/xp_nofault.S
index b772543053c..54e8973b6e9 100644
--- a/arch/ia64/sn/kernel/xp_nofault.S
+++ b/arch/ia64/sn/kernel/xp_nofault.S
@@ -21,7 +21,8 @@
xp_nofault_PIOR:
mov r8=r0 // Stage a success return value
ld8.acq r9=[r32];; // PIO Read the specified register
- adds r9=1,r9 // Add to force a consume
+ adds r9=1,r9;; // Add to force consumption
+ or r9=r9,r9;; // Or to force consumption
br.ret.sptk.many b0;; // Return success
.global xp_error_PIOR
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 04a8256017e..42485ad50ce 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -15,6 +15,7 @@
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/sn_sal.h>
+#include <asm/sn/pic.h>
#include <asm/sn/sn2/sn_hwperf.h>
#include "xtalk/xwidgetdev.h"
#include "xtalk/hubdev.h"
@@ -79,7 +80,7 @@ static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus)
{
s64 rc;
- u16 ioboard;
+ u16 uninitialized_var(ioboard); /* GCC be quiet */
nasid_t nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
rc = ia64_sn_sysctl_ioboard_get(nasid, &ioboard);
@@ -130,9 +131,9 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
}
memcpy(soft, prom_bussoft, sizeof(struct pcibus_info));
- soft->pbi_buscommon.bs_base =
- (((u64) soft->pbi_buscommon.
- bs_base << 4) >> 4) | __IA64_UNCACHED_OFFSET;
+ soft->pbi_buscommon.bs_base = (unsigned long)
+ ioremap(REGION_OFFSET(soft->pbi_buscommon.bs_base),
+ sizeof(struct pic));
spin_lock_init(&soft->pbi_lock);
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index b9bedbd6e1d..d798dd4d0dc 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -610,7 +610,9 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
return NULL;
memcpy(tioca_common, prom_bussoft, sizeof(struct tioca_common));
- tioca_common->ca_common.bs_base |= __IA64_UNCACHED_OFFSET;
+ tioca_common->ca_common.bs_base = (unsigned long)
+ ioremap(REGION_OFFSET(tioca_common->ca_common.bs_base),
+ sizeof(struct tioca_common));
/* init kernel-private area */
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index f4c0b961a93..84b72b27e27 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -1002,7 +1002,9 @@ tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
return NULL;
memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common));
- tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET;
+ tioce_common->ce_pcibus.bs_base = (unsigned long)
+ ioremap(REGION_OFFSET(tioce_common->ce_pcibus.bs_base),
+ sizeof(struct tioce_common));
tioce_kern = tioce_kern_init(tioce_common);
if (tioce_kern == NULL) {
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index b8536c7c087..a86e2e9a639 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -355,8 +355,9 @@ config RMW_INSNS
adventurous.
config SINGLE_MEMORY_CHUNK
- bool "Use one physical chunk of memory only"
- depends on ADVANCED && !SUN3
+ bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
+ default y if SUN3
+ select NEED_MULTIPLE_NODES
help
Ignore all but the first contiguous chunk of physical memory for VM
purposes. This will save a few bytes kernel size and may speed up
@@ -377,6 +378,14 @@ config 060_WRITETHROUGH
is hardwired on. The 53c710 SCSI driver is known to suffer from
this problem.
+config ARCH_DISCONTIGMEM_ENABLE
+ def_bool !SINGLE_MEMORY_CHUNK
+
+config NODES_SHIFT
+ int
+ default "3"
+ depends on !SINGLE_MEMORY_CHUNK
+
source "mm/Kconfig"
endmenu
@@ -409,9 +418,6 @@ config STRAM_PROC
help
Say Y here to report ST-RAM usage statistics in /proc/stram.
-config ATARI_KBD_CORE
- bool
-
config HEARTBEAT
bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index c20831a7e1a..aa383a5ea7a 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -19,6 +19,7 @@ COMPILE_ARCH = $(shell uname -m)
# override top level makefile
AS += -m68020
LDFLAGS := -m m68kelf
+LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
ifneq ($(COMPILE_ARCH),$(ARCH))
# prefix for cross-compiling binaries
CROSS_COMPILE = m68k-linux-gnu-
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 0b68ab8d63d..a806208c7fb 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -9,13 +9,12 @@ else
endif
extra-y += vmlinux.lds
-obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \
+obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o devres.o
devres-y = ../../../kernel/irq/devres.o
obj-$(CONFIG_PCI) += bios32.o
-obj-$(CONFIG_MODULES) += module.o
obj-y$(CONFIG_MMU_SUN3) += dma.o # no, it's not a typo
EXTRA_AFLAGS := -traditional
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c
index 3b1a2ff61dd..774862bc697 100644
--- a/arch/m68k/kernel/module.c
+++ b/arch/m68k/kernel/module.c
@@ -1,3 +1,9 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
#include <linux/moduleloader.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
@@ -11,6 +17,8 @@
#define DEBUGP(fmt...)
#endif
+#ifdef CONFIG_MODULES
+
void *module_alloc(unsigned long size)
{
if (size == 0)
@@ -118,11 +126,32 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
- struct module *me)
+ struct module *mod)
{
+ module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
+
return 0;
}
void module_arch_cleanup(struct module *mod)
{
}
+
+#endif /* CONFIG_MODULES */
+
+void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+ struct m68k_fixup_info *end)
+{
+ struct m68k_fixup_info *fixup;
+
+ for (fixup = start; fixup < end; fixup++) {
+ switch (fixup->type) {
+ case m68k_fixup_memoffset:
+ *(u32 *)fixup->addr = m68k_memoffset;
+ break;
+ case m68k_fixup_vnode_shift:
+ *(u16 *)fixup->addr += m68k_virt_to_node_shift;
+ break;
+ }
+ }
+}
diff --git a/arch/m68k/kernel/module.lds b/arch/m68k/kernel/module.lds
new file mode 100644
index 00000000000..fda94fa3824
--- /dev/null
+++ b/arch/m68k/kernel/module.lds
@@ -0,0 +1,7 @@
+SECTIONS {
+ .m68k_fixup : {
+ __start_fixup = .;
+ *(.m68k_fixup)
+ __stop_fixup = .;
+ }
+}
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 61031935669..215c7bd4392 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -60,14 +60,12 @@ extern unsigned long availmem;
int m68k_num_memory;
int m68k_realnum_memory;
EXPORT_SYMBOL(m68k_realnum_memory);
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
unsigned long m68k_memoffset;
EXPORT_SYMBOL(m68k_memoffset);
-#endif
struct mem_info m68k_memory[NUM_MEMINFO];
EXPORT_SYMBOL(m68k_memory);
-static struct mem_info m68k_ramdisk;
+struct mem_info m68k_ramdisk;
static char m68k_command_line[CL_SIZE];
@@ -208,9 +206,6 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
void __init setup_arch(char **cmdline_p)
{
extern int _etext, _edata, _end;
-#ifndef CONFIG_SUN3
- unsigned long endmem, startmem;
-#endif
int i;
/* The bootinfo is located right after the kernel bss */
@@ -320,30 +315,16 @@ void __init setup_arch(char **cmdline_p)
panic("No configuration setup");
}
-#ifndef CONFIG_SUN3
- startmem= m68k_memory[0].addr;
- endmem = startmem + m68k_memory[0].size;
- high_memory = (void *)PAGE_OFFSET;
- for (i = 0; i < m68k_num_memory; i++) {
- m68k_memory[i].size &= MASK_256K;
- if (m68k_memory[i].addr < startmem)
- startmem = m68k_memory[i].addr;
- if (m68k_memory[i].addr+m68k_memory[i].size > endmem)
- endmem = m68k_memory[i].addr+m68k_memory[i].size;
- high_memory += m68k_memory[i].size;
- }
-
- availmem += init_bootmem_node(NODE_DATA(0), availmem >> PAGE_SHIFT,
- startmem >> PAGE_SHIFT, endmem >> PAGE_SHIFT);
-
- for (i = 0; i < m68k_num_memory; i++)
- free_bootmem(m68k_memory[i].addr, m68k_memory[i].size);
-
- reserve_bootmem(m68k_memory[0].addr, availmem - m68k_memory[0].addr);
+ paging_init();
+#ifndef CONFIG_SUN3
+ for (i = 1; i < m68k_num_memory; i++)
+ free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
+ m68k_memory[i].size);
#ifdef CONFIG_BLK_DEV_INITRD
if (m68k_ramdisk.size) {
- reserve_bootmem(m68k_ramdisk.addr, m68k_ramdisk.size);
+ reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
+ m68k_ramdisk.addr, m68k_ramdisk.size);
initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
initrd_end = initrd_start + m68k_ramdisk.size;
printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
@@ -362,8 +343,6 @@ void __init setup_arch(char **cmdline_p)
#endif /* !CONFIG_SUN3 */
- paging_init();
-
/* set ISA defs early as possible */
#if defined(CONFIG_ISA) && defined(MULTI_ISA)
#if defined(CONFIG_Q40)
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index 78f139226a1..40f02b128f2 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -60,6 +60,11 @@ SECTIONS
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ .m68k_fixup : {
+ __start_fixup = .;
+ *(.m68k_fixup)
+ __stop_fixup = .;
+ }
SECURITY_INIT
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(8192);
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index c8999b2db23..f06425b6d20 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -54,6 +54,11 @@ __init_begin = .;
__con_initcall_start = .;
.con_initcall.init : { *(.con_initcall.init) }
__con_initcall_end = .;
+ .m68k_fixup : {
+ __start_fixup = .;
+ *(.m68k_fixup)
+ __stop_fixup = .;
+ }
SECURITY_INIT
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(8192);
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
index 7a5bed5bdc5..e8a57138b4a 100644
--- a/arch/m68k/mac/debug.c
+++ b/arch/m68k/mac/debug.c
@@ -71,7 +71,7 @@ void mac_debugging_short(int pos, short num)
/* calculate current offset */
pengoffset = (unsigned char *)mac_videobase +
- (150+line*2) * mac_rowbytes) + 80 * peng;
+ (150+line*2) * mac_rowbytes + 80 * peng;
pptr = pengoffset;
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index ab90213e5c5..f1de19e1dde 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -7,6 +7,7 @@
* to motorola.c and sun3mmu.c
*/
+#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -31,6 +32,37 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+static bootmem_data_t __initdata bootmem_data[MAX_NUMNODES];
+
+pg_data_t pg_data_map[MAX_NUMNODES];
+EXPORT_SYMBOL(pg_data_map);
+
+int m68k_virt_to_node_shift;
+
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+pg_data_t *pg_data_table[65];
+EXPORT_SYMBOL(pg_data_table);
+#endif
+
+void m68k_setup_node(int node)
+{
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+ struct mem_info *info = m68k_memory + node;
+ int i, end;
+
+ i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
+ end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
+ for (; i <= end; i++) {
+ if (pg_data_table[i])
+ printk("overlap at %u for chunk %u\n", i, node);
+ pg_data_table[i] = pg_data_map + node;
+ }
+#endif
+ pg_data_map[node].bdata = bootmem_data + node;
+ node_set_online(node);
+}
+
+
/*
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
@@ -40,52 +72,51 @@ void *empty_zero_page;
void show_mem(void)
{
- unsigned long i;
- int free = 0, total = 0, reserved = 0, shared = 0;
- int cached = 0;
-
- printk("\nMem-info:\n");
- show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
- i = max_mapnr;
- while (i-- > 0) {
- total++;
- if (PageReserved(mem_map+i))
- reserved++;
- else if (PageSwapCache(mem_map+i))
- cached++;
- else if (!page_count(mem_map+i))
- free++;
- else
- shared += page_count(mem_map+i) - 1;
- }
- printk("%d pages of RAM\n",total);
- printk("%d free pages\n",free);
- printk("%d reserved pages\n",reserved);
- printk("%d pages shared\n",shared);
- printk("%d pages swap cached\n",cached);
+ pg_data_t *pgdat;
+ int free = 0, total = 0, reserved = 0, shared = 0;
+ int cached = 0;
+ int i;
+
+ printk("\nMem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ for_each_online_pgdat(pgdat) {
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page = pgdat->node_mem_map + i;
+ total++;
+ if (PageReserved(page))
+ reserved++;
+ else if (PageSwapCache(page))
+ cached++;
+ else if (!page_count(page))
+ free++;
+ else
+ shared += page_count(page) - 1;
+ }
+ }
+ printk("%d pages of RAM\n",total);
+ printk("%d free pages\n",free);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
}
extern void init_pointer_table(unsigned long ptable);
/* References to section boundaries */
-extern char _text, _etext, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
+extern char _text[], _etext[];
+extern char __init_begin[], __init_end[];
extern pmd_t *zero_pgtable;
void __init mem_init(void)
{
+ pg_data_t *pgdat;
int codepages = 0;
int datapages = 0;
int initpages = 0;
- unsigned long tmp;
-#ifndef CONFIG_SUN3
int i;
-#endif
-
- max_mapnr = num_physpages = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT);
#ifdef CONFIG_ATARI
if (MACH_IS_ATARI)
@@ -93,19 +124,25 @@ void __init mem_init(void)
#endif
/* this will put all memory onto the freelists */
- totalram_pages = free_all_bootmem();
-
- for (tmp = PAGE_OFFSET ; tmp < (unsigned long)high_memory; tmp += PAGE_SIZE) {
- if (PageReserved(virt_to_page(tmp))) {
- if (tmp >= (unsigned long)&_text
- && tmp < (unsigned long)&_etext)
+ totalram_pages = num_physpages = 0;
+ for_each_online_pgdat(pgdat) {
+ num_physpages += pgdat->node_present_pages;
+
+ totalram_pages += free_all_bootmem_node(pgdat);
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page = pgdat->node_mem_map + i;
+ char *addr = page_to_virt(page);
+
+ if (!PageReserved(page))
+ continue;
+ if (addr >= _text &&
+ addr < _etext)
codepages++;
- else if (tmp >= (unsigned long) &__init_begin
- && tmp < (unsigned long) &__init_end)
+ else if (addr >= __init_begin &&
+ addr < __init_end)
initpages++;
else
datapages++;
- continue;
}
}
@@ -124,7 +161,7 @@ void __init mem_init(void)
printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
(unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
- max_mapnr << (PAGE_SHIFT-10),
+ totalram_pages << (PAGE_SHIFT-10),
codepages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10));
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index 13c0b4ad01e..b7473525b43 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -127,67 +127,6 @@ int free_pointer_table (pmd_t *ptable)
return 0;
}
-#ifdef DEBUG_INVALID_PTOV
-int mm_inv_cnt = 5;
-#endif
-
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-/*
- * The following two routines map from a physical address to a kernel
- * virtual address and vice versa.
- */
-unsigned long mm_vtop(unsigned long vaddr)
-{
- int i=0;
- unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET;
-
- do {
- if (voff < m68k_memory[i].size) {
-#ifdef DEBUGPV
- printk ("VTOP(%p)=%lx\n", vaddr,
- m68k_memory[i].addr + voff);
-#endif
- return m68k_memory[i].addr + voff;
- }
- voff -= m68k_memory[i].size;
- } while (++i < m68k_num_memory);
-
- /* As a special case allow `__pa(high_memory)'. */
- if (voff == 0)
- return m68k_memory[i-1].addr + m68k_memory[i-1].size;
-
- return -1;
-}
-EXPORT_SYMBOL(mm_vtop);
-
-unsigned long mm_ptov (unsigned long paddr)
-{
- int i = 0;
- unsigned long poff, voff = PAGE_OFFSET;
-
- do {
- poff = paddr - m68k_memory[i].addr;
- if (poff < m68k_memory[i].size) {
-#ifdef DEBUGPV
- printk ("PTOV(%lx)=%lx\n", paddr, poff + voff);
-#endif
- return poff + voff;
- }
- voff += m68k_memory[i].size;
- } while (++i < m68k_num_memory);
-
-#ifdef DEBUG_INVALID_PTOV
- if (mm_inv_cnt > 0) {
- mm_inv_cnt--;
- printk("Invalid use of phys_to_virt(0x%lx) at 0x%p!\n",
- paddr, __builtin_return_address(0));
- }
-#endif
- return -1;
-}
-EXPORT_SYMBOL(mm_ptov);
-#endif
-
/* invalidate page in both caches */
static inline void clear040(unsigned long paddr)
{
@@ -354,15 +293,3 @@ void cache_push (unsigned long paddr, int len)
}
EXPORT_SYMBOL(cache_push);
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-int mm_end_of_chunk (unsigned long addr, int len)
-{
- int i;
-
- for (i = 0; i < m68k_num_memory; i++)
- if (m68k_memory[i].addr + m68k_memory[i].size == addr + len)
- return 1;
- return 0;
-}
-EXPORT_SYMBOL(mm_end_of_chunk);
-#endif
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index afcccdc6ad4..7d571a2b44d 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -43,6 +43,11 @@ unsigned long mm_cachebits;
EXPORT_SYMBOL(mm_cachebits);
#endif
+/* size of memory already mapped in head.S */
+#define INIT_MAPPED_SIZE (4UL<<20)
+
+extern unsigned long availmem;
+
static pte_t * __init kernel_page_table(void)
{
pte_t *ptablep;
@@ -98,19 +103,20 @@ static pmd_t * __init kernel_ptr_table(void)
return last_pgtable;
}
-static unsigned long __init
-map_chunk (unsigned long addr, long size)
+static void __init map_node(int node)
{
#define PTRTREESIZE (256*1024)
#define ROOTTREESIZE (32*1024*1024)
- static unsigned long virtaddr = PAGE_OFFSET;
- unsigned long physaddr;
+ unsigned long physaddr, virtaddr, size;
pgd_t *pgd_dir;
pmd_t *pmd_dir;
pte_t *pte_dir;
- physaddr = (addr | m68k_supervisor_cachemode |
- _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+ size = m68k_memory[node].size;
+ physaddr = m68k_memory[node].addr;
+ virtaddr = (unsigned long)phys_to_virt(physaddr);
+ physaddr |= m68k_supervisor_cachemode |
+ _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY;
if (CPU_IS_040_OR_060)
physaddr |= _PAGE_GLOBAL040;
@@ -190,8 +196,6 @@ map_chunk (unsigned long addr, long size)
#ifdef DEBUG
printk("\n");
#endif
-
- return virtaddr;
}
/*
@@ -200,15 +204,16 @@ map_chunk (unsigned long addr, long size)
*/
void __init paging_init(void)
{
- int chunk;
- unsigned long mem_avail = 0;
unsigned long zones_size[MAX_NR_ZONES] = { 0, };
+ unsigned long min_addr, max_addr;
+ unsigned long addr, size, end;
+ int i;
#ifdef DEBUG
{
extern unsigned long availmem;
- printk ("start of paging_init (%p, %lx, %lx, %lx)\n",
- kernel_pg_dir, availmem, start_mem, end_mem);
+ printk ("start of paging_init (%p, %lx)\n",
+ kernel_pg_dir, availmem);
}
#endif
@@ -222,24 +227,62 @@ void __init paging_init(void)
pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
}
+ min_addr = m68k_memory[0].addr;
+ max_addr = min_addr + m68k_memory[0].size;
+ for (i = 1; i < m68k_num_memory;) {
+ if (m68k_memory[i].addr < min_addr) {
+ printk("Ignoring memory chunk at 0x%lx:0x%lx before the first chunk\n",
+ m68k_memory[i].addr, m68k_memory[i].size);
+ printk("Fix your bootloader or use a memfile to make use of this area!\n");
+ m68k_num_memory--;
+ memmove(m68k_memory + i, m68k_memory + i + 1,
+ (m68k_num_memory - i) * sizeof(struct mem_info));
+ continue;
+ }
+ addr = m68k_memory[i].addr + m68k_memory[i].size;
+ if (addr > max_addr)
+ max_addr = addr;
+ i++;
+ }
+ m68k_memoffset = min_addr - PAGE_OFFSET;
+ m68k_virt_to_node_shift = fls(max_addr - min_addr - 1) - 6;
+
+ module_fixup(NULL, __start_fixup, __stop_fixup);
+ flush_icache();
+
+ high_memory = phys_to_virt(max_addr);
+
+ min_low_pfn = availmem >> PAGE_SHIFT;
+ max_low_pfn = max_addr >> PAGE_SHIFT;
+
+ for (i = 0; i < m68k_num_memory; i++) {
+ addr = m68k_memory[i].addr;
+ end = addr + m68k_memory[i].size;
+ m68k_setup_node(i);
+ availmem = PAGE_ALIGN(availmem);
+ availmem += init_bootmem_node(NODE_DATA(i),
+ availmem >> PAGE_SHIFT,
+ addr >> PAGE_SHIFT,
+ end >> PAGE_SHIFT);
+ }
+
/*
* Map the physical memory available into the kernel virtual
- * address space. It may allocate some memory for page
- * tables and thus modify availmem.
+ * address space. First initialize the bootmem allocator with
+ * the memory we already mapped, so map_node() has something
+ * to allocate.
*/
+ addr = m68k_memory[0].addr;
+ size = m68k_memory[0].size;
+ free_bootmem_node(NODE_DATA(0), availmem, min(INIT_MAPPED_SIZE, size) - (availmem - addr));
+ map_node(0);
+ if (size > INIT_MAPPED_SIZE)
+ free_bootmem_node(NODE_DATA(0), addr + INIT_MAPPED_SIZE, size - INIT_MAPPED_SIZE);
- for (chunk = 0; chunk < m68k_num_memory; chunk++) {
- mem_avail = map_chunk (m68k_memory[chunk].addr,
- m68k_memory[chunk].size);
-
- }
+ for (i = 1; i < m68k_num_memory; i++)
+ map_node(i);
flush_tlb_all();
-#ifdef DEBUG
- printk ("memory available is %ldKB\n", mem_avail >> 10);
- printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
- start_mem, end_mem);
-#endif
/*
* initialize the bad page table and bad page to point
@@ -256,14 +299,11 @@ void __init paging_init(void)
#ifdef DEBUG
printk ("before free_area_init\n");
#endif
- zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ?
- (mach_max_dma_address+1) : (unsigned long)high_memory);
- zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0];
-
- zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT;
- zones_size[ZONE_NORMAL] >>= PAGE_SHIFT;
-
- free_area_init(zones_size);
+ for (i = 0; i < m68k_num_memory; i++) {
+ zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
+ free_area_init_node(i, pg_data_map + i, zones_size,
+ m68k_memory[i].addr >> PAGE_SHIFT, NULL);
+ }
}
extern char __init_begin, __init_end;
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 4851b8437a8..c0fbd278fbb 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -21,6 +21,7 @@
#include <asm/contregs.h>
#include <asm/movs.h>
#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/sun3-head.h>
#include <asm/sun3mmu.h>
#include <asm/rtc.h>
@@ -127,6 +128,7 @@ void __init sun3_bootmem_alloc(unsigned long memory_start, unsigned long memory_
high_memory = (void *)memory_end;
availmem = memory_start;
+ m68k_setup_node(0);
availmem += init_bootmem_node(NODE_DATA(0), start_page, 0, num_pages);
availmem = (availmem + (PAGE_SIZE-1)) & PAGE_MASK;
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index 92e58070b01..fb66eadd589 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -62,10 +62,13 @@ void coldfire_tick(void)
/***************************************************************************/
+static int ticks_per_intr;
+
void coldfire_timer_init(irq_handler_t handler)
{
__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
- __raw_writetrr(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
+ ticks_per_intr = (MCF_BUSCLK / 16) / HZ;
+ __raw_writetrr(ticks_per_intr - 1, TA(MCFTIMER_TRR));
__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
@@ -81,11 +84,10 @@ void coldfire_timer_init(irq_handler_t handler)
unsigned long coldfire_timer_offset(void)
{
- unsigned long trr, tcn, offset;
+ unsigned long tcn, offset;
tcn = __raw_readw(TA(MCFTIMER_TCN));
- trr = __raw_readtrr(TA(MCFTIMER_TRR));
- offset = (tcn * (1000000 / HZ)) / trr;
+ offset = ((tcn + 1) * (1000000 / HZ)) / ticks_per_intr;
/* Check if we just wrapped the counters and maybe missed a tick */
if ((offset < (1000000 / HZ / 2)) && mcf_timerirqpending(1))
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 0f09412e1b7..5c863bcd561 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -15,6 +15,29 @@ choice
prompt "System type"
default SGI_IP22
+config LEMOTE_FULONG
+ bool "Lemote Fulong mini-PC"
+ select ARCH_SPARSEMEM_ENABLE
+ select SYS_HAS_CPU_LOONGSON2
+ select DMA_NONCOHERENT
+ select BOOT_ELF32
+ select BOARD_SCACHE
+ select HAVE_STD_PC_SERIAL_PORT
+ select HW_HAS_PCI
+ select I8259
+ select ISA
+ select IRQ_CPU
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
+ select SYS_HAS_EARLY_PRINTK
+ select GENERIC_HARDIRQS_NO__DO_IRQ
+ select CPU_HAS_WB
+ help
+ Lemote Fulong mini-PC board based on the Chinese Loongson-2E CPU and
+ an FPGA northbridge
+
config MACH_ALCHEMY
bool "Alchemy processor based machines"
@@ -63,7 +86,7 @@ config MACH_DECSTATION
bool "DECstations"
select BOOT_ELF32
select DMA_NONCOHERENT
- select SYS_HAS_EARLY_PRINTK
+ select NO_IOPORT
select IRQ_CPU
select SYS_HAS_CPU_R3000
select SYS_HAS_CPU_R4X00
@@ -88,33 +111,15 @@ config MACH_DECSTATION
otherwise choose R3000.
-config MIPS_EV64120
- bool "Galileo EV64120 Evaluation board (EXPERIMENTAL)"
- depends on EXPERIMENTAL
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select PCI_GT64XXX_PCI0
- select SYS_HAS_CPU_R5000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- select SYS_SUPPORTS_KGDB
- help
- This is an evaluation board based on the Galileo GT-64120
- single-chip system controller that contains a MIPS R5000 compatible
- core running at 75/100MHz. Their website is located at
- <http://www.marvell.com/>. Say Y here if you wish to build a
- kernel for this platform.
-
config MACH_JAZZ
bool "Jazz family of machines"
select ARC
select ARC32
select ARCH_MAY_HAVE_PC_FDC
select GENERIC_ISA_DMA
- select I8253
select I8259
select ISA
+ select PCSPEAKER
select SYS_HAS_CPU_R4X00
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
@@ -126,20 +131,6 @@ config MACH_JAZZ
Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
Olivetti M700-10 workstations.
-config LASAT
- bool "LASAT Networks platforms"
- select DMA_NONCOHERENT
- select SYS_HAS_EARLY_PRINTK
- select HW_HAS_PCI
- select PCI_GT64XXX_PCI0
- select MIPS_NILE4
- select R5000_CPU_SCACHE
- select SYS_HAS_CPU_R5000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
- select SYS_SUPPORTS_LITTLE_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
-
config MIPS_ATLAS
bool "MIPS Atlas board"
select BOOT_ELF32
@@ -173,7 +164,6 @@ config MIPS_MALTA
bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC
select BOOT_ELF32
- select HAVE_STD_PC_SERIAL_PORT
select DMA_NONCOHERENT
select GENERIC_ISA_DMA
select IRQ_CPU
@@ -246,11 +236,13 @@ config MIPS_SIM
select DMA_NONCOHERENT
select SYS_HAS_EARLY_PRINTK
select IRQ_CPU
+ select BOOT_RAW
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_MIPS32_R2
select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_MULTITHREADING
select SYS_SUPPORTS_LITTLE_ENDIAN
help
This option enables support for MIPS Technologies MIPSsim software
@@ -274,50 +266,13 @@ config MOMENCO_OCELOT
The Ocelot is a MIPS-based Single Board Computer (SBC) made by
Momentum Computer <http://www.momenco.com/>.
-config MOMENCO_OCELOT_3
- bool "Momentum Ocelot-3 board"
- select BOOT_ELF32
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select IRQ_CPU
- select IRQ_CPU_RM7K
- select IRQ_MV64340
- select PCI_MARVELL
- select RM7000_CPU_SCACHE
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_RM9000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- help
- The Ocelot-3 is based off Discovery III System Controller and
- PMC-Sierra Rm79000 core.
-
-config MOMENCO_OCELOT_C
- bool "Momentum Ocelot-C board"
- select DMA_NONCOHERENT
- select HW_HAS_PCI
- select IRQ_CPU
- select IRQ_MV64340
- select PCI_MARVELL
- select RM7000_CPU_SCACHE
- select SWAP_IO_SPACE
- select SYS_HAS_CPU_RM7000
- select SYS_SUPPORTS_32BIT_KERNEL
- select SYS_SUPPORTS_64BIT_KERNEL
- select SYS_SUPPORTS_BIG_ENDIAN
- select GENERIC_HARDIRQS_NO__DO_IRQ
- help
- The Ocelot is a MIPS-based Single Board Computer (SBC) made by
- Momentum Computer <http://www.momenco.com/>.
-
config PNX8550_JBS
bool "Philips PNX8550 based JBS board"
select PNX8550
select SYS_SUPPORTS_LITTLE_ENDIAN
config PNX8550_STB810
- bool "Support for Philips PNX8550 based STB810 board"
+ bool "Philips PNX8550 based STB810 board"
select PNX8550
select SYS_SUPPORTS_LITTLE_ENDIAN
@@ -346,6 +301,27 @@ config MACH_VR41XX
select SYS_HAS_CPU_VR41XX
select GENERIC_HARDIRQS_NO__DO_IRQ
+config PMC_MSP
+ bool "PMC-Sierra MSP chipsets"
+ depends on EXPERIMENTAL
+ select DMA_NONCOHERENT
+ select SWAP_IO_SPACE
+ select NO_EXCEPT_FILL
+ select BOOT_RAW
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_KGDB
+ select IRQ_CPU
+ select SERIAL_8250
+ select SERIAL_8250_CONSOLE
+ help
+ This adds support for the PMC-Sierra family of Multi-Service
+ Processor System-On-A-Chips. These parts include a number
+ of integrated peripherals, interfaces and DSPs in addition to
+ a variety of MIPS cores.
+
config PMC_YOSEMITE
bool "PMC-Sierra Yosemite eval board"
select DMA_COHERENT
@@ -371,9 +347,9 @@ config QEMU
select DMA_COHERENT
select GENERIC_ISA_DMA
select HAVE_STD_PC_SERIAL_PORT
- select I8253
select I8259
select ISA
+ select PCSPEAKER
select SWAP_IO_SPACE
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL
@@ -392,7 +368,7 @@ config QEMU
can be found at http://www.linux-mips.org/wiki/Qemu.
config MARKEINS
- bool "Support for NEC EMMA2RH Mark-eins"
+ bool "NEC EMMA2RH Mark-eins"
select DMA_NONCOHERENT
select HW_HAS_PCI
select IRQ_CPU
@@ -450,8 +426,7 @@ config SGI_IP27
here.
config SGI_IP32
- bool "SGI IP32 (O2) (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ bool "SGI IP32 (O2)"
select ARC
select ARC32
select BOOT_ELF32
@@ -587,9 +562,9 @@ config SNI_RM
select HW_HAS_EISA
select HW_HAS_PCI
select IRQ_CPU
- select I8253
select I8259
select ISA
+ select PCSPEAKER
select SWAP_IO_SPACE if CPU_BIG_ENDIAN
select SYS_HAS_CPU_R4X00
select SYS_HAS_CPU_R5000
@@ -652,6 +627,7 @@ config TOSHIBA_RBTX4938
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_KGDB
select GENERIC_HARDIRQS_NO__DO_IRQ
+ select GENERIC_GPIO
help
This Toshiba board is based on the TX4938 processor. Say Y here to
support this machine type
@@ -660,9 +636,7 @@ endchoice
source "arch/mips/au1000/Kconfig"
source "arch/mips/ddb5xxx/Kconfig"
-source "arch/mips/gt64120/ev64120/Kconfig"
source "arch/mips/jazz/Kconfig"
-source "arch/mips/lasat/Kconfig"
source "arch/mips/pmc-sierra/Kconfig"
source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig"
@@ -721,6 +695,9 @@ config ARC
config ARCH_MAY_HAVE_PC_FDC
bool
+config BOOT_RAW
+ bool
+
config DMA_COHERENT
bool
@@ -747,9 +724,9 @@ config EARLY_PRINTK
to print messages very early in the bootup process.
This is useful for kernel debugging when your machine crashes very
- early before the console code is initialized. For normal operation
- it is not recommended because it looks on some machines ugly and
- oesn't cooperate with an X server. You should normally N here,
+ early before the console code is initialized. For normal operation,
+ it is not recommended because it looks ugly on some machines and
+ doesn't cooperate with an X server. You should normally say N here,
unless you want to debug such a crash.
config SYS_HAS_EARLY_PRINTK
@@ -768,16 +745,19 @@ config MIPS_BONITO64
config MIPS_MSC
bool
-config MIPS_NILE4
- bool
-
config MIPS_DISABLE_OBSOLETE_IDE
bool
+config NO_IOPORT
+ def_bool n
+
config GENERIC_ISA_DMA_SUPPORT_BROKEN
bool
select ZONE_DMA
+config GENERIC_GPIO
+ bool
+
#
# Endianess selection. Sufficiently obscure so many users don't know what to
# answer,so we try hard to limit the available choices. Also the use of a
@@ -821,7 +801,10 @@ config IRQ_CPU_RM7K
config IRQ_CPU_RM9K
bool
-config IRQ_MV64340
+config IRQ_MSP_SLP
+ bool
+
+config IRQ_MSP_CIC
bool
config DDB5XXX_COMMON
@@ -834,6 +817,9 @@ config MIPS_BOARDS_GEN
config PCI_GT64XXX_PCI0
bool
+config NO_EXCEPT_FILL
+ bool
+
config MIPS_TX3927
bool
select HAS_TXX9_SERIAL
@@ -841,14 +827,6 @@ config MIPS_TX3927
config MIPS_RM9122
bool
select SERIAL_RM9000
- select GPI_RM9000
- select WDT_RM9000
-
-config PCI_MARVELL
- bool
-
-config SERIAL_RM9000
- bool
config PNX8550
bool
@@ -863,6 +841,7 @@ config SOC_PNX8550
select SYS_SUPPORTS_32BIT_KERNEL
select GENERIC_HARDIRQS_NO__DO_IRQ
select SYS_SUPPORTS_KGDB
+ select GENERIC_GPIO
config SWAP_IO_SPACE
bool
@@ -875,31 +854,17 @@ config EMMA2RH
config SERIAL_RM9000
bool
-config GPI_RM9000
- bool
-
-config WDT_RM9000
- bool
-
#
# Unfortunately not all GT64120 systems run the chip at the same clock.
# As the user for the clock rate and try to minimize the available options.
#
choice
prompt "Galileo Chip Clock"
- #default SYSCLK_83 if MIPS_EV64120
- depends on MIPS_EV64120 || MOMENCO_OCELOT
- default SYSCLK_83 if MIPS_EV64120
+ depends on MOMENCO_OCELOT
default SYSCLK_100 if MOMENCO_OCELOT
-config SYSCLK_75
- bool "75" if MIPS_EV64120
-
-config SYSCLK_83
- bool "83.3" if MIPS_EV64120
-
config SYSCLK_100
- bool "100" if MIPS_EV64120 || MOMENCO_OCELOT
+ bool "100" if MOMENCO_OCELOT
endchoice
@@ -911,8 +876,9 @@ config BOOT_ELF32
config MIPS_L1_CACHE_SHIFT
int
- default "4" if MACH_DECSTATION || SNI_RM
- default "7" if SGI_IP27
+ default "4" if MACH_DECSTATION
+ default "7" if SGI_IP27 || SNI_RM
+ default "4" if PMC_MSP4200_EVAL
default "5"
config HAVE_STD_PC_SERIAL_PORT
@@ -944,6 +910,16 @@ choice
prompt "CPU type"
default CPU_R4X00
+config CPU_LOONGSON2
+ bool "Loongson 2"
+ depends on SYS_HAS_CPU_LOONGSON2
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_64BIT_KERNEL
+ select CPU_SUPPORTS_HIGHMEM
+ help
+ The Loongson 2E processor implements the MIPS III instruction set
+ with many extensions.
+
config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
@@ -1154,6 +1130,9 @@ config CPU_SB1
endchoice
+config SYS_HAS_CPU_LOONGSON2
+ bool
+
config SYS_HAS_CPU_MIPS32_R1
bool
@@ -1392,6 +1371,7 @@ config MIPS_VPE_LOADER
depends on SYS_SUPPORTS_MULTITHREADING
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
+ select CPU_MIPSR2_SRS
select MIPS_MT
help
Includes a loader for loading an elf relocatable object
@@ -1424,6 +1404,19 @@ config MIPS_MT_SMTC_INSTANT_REPLAY
it off), but ensures that IPIs are handled promptly even under
heavy I/O interrupt load.
+config MIPS_MT_SMTC_IM_BACKSTOP
+ bool "Use per-TC register bits as backstop for inhibited IM bits"
+ depends on MIPS_MT_SMTC
+ default y
+ help
+ To support multiple TC microthreads acting as "CPUs" within
+ a VPE, VPE-wide interrupt mask bits must be specially manipulated
+ during interrupt handling. To support legacy drivers and interrupt
+ controller management code, SMTC has a "backstop" to track and
+ if necessary restore the interrupt mask. This has some performance
+ impact on interrupt service overhead. Disable it only if you know
+ what you are doing.
+
config MIPS_VPE_LOADER_TOM
bool "Load VPE program into memory hidden from linux"
depends on MIPS_VPE_LOADER
@@ -1487,6 +1480,15 @@ config CPU_HAS_SMARTMIPS
config CPU_HAS_WB
bool
+config 64BIT_CONTEXT
+ bool "Save 64bit integer registers"
+ depends on 32BIT && CPU_LOONGSON2
+ help
+ Loongson2 CPU is 64bit , when used in 32BIT mode, its integer
+ registers can still be accessed as 64bit, mainly for multimedia
+ instructions. We must have all 64bit save/restored to make sure
+ those instructions to get correct result.
+
#
# Vectored interrupt mode is an R2 feature
#
@@ -1862,7 +1864,7 @@ config MMU
bool
default y
-config I8253
+config PCSPEAKER
bool
source "drivers/pcmcia/Kconfig"
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug
index 72d5c198e79..3efe117721a 100644
--- a/arch/mips/Kconfig.debug
+++ b/arch/mips/Kconfig.debug
@@ -37,7 +37,7 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
-config CONFIG_SMTC_IDLE_HOOK_DEBUG
+config SMTC_IDLE_HOOK_DEBUG
bool "Enable additional debug checks before going into CPU idle loop"
depends on DEBUG_KERNEL && MIPS_MT_SMTC
help
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index f450066b624..20d19c9b776 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -118,6 +118,7 @@ cflags-$(CONFIG_CPU_R4300) += -march=r4300 -Wa,--trap
cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap
cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
+cflags-$(CONFIG_CPU_LOONGSON2) += -march=r4600 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32 -Wa,--trap
cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
@@ -283,14 +284,6 @@ load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000
CLEAN_FILES += drivers/tc/lk201-map.c
#
-# Galileo EV64120 Board
-#
-core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/ev64120/
-core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/common/
-cflags-$(CONFIG_MIPS_EV64120) += -Iinclude/asm-mips/mach-ev64120
-load-$(CONFIG_MIPS_EV64120) += 0xffffffff80100000
-
-#
# Wind River PPMC Board (4KC + GT64120)
#
core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/
@@ -298,6 +291,13 @@ cflags-$(CONFIG_WR_PPMC) += -Iinclude/asm-mips/mach-wrppmc
load-$(CONFIG_WR_PPMC) += 0xffffffff80100000
#
+# lemote fulong mini-PC board
+#
+core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/
+load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000
+cflags-$(CONFIG_LEMOTE_FULONG) += -Iinclude/asm-mips/mach-lemote
+
+#
# For all MIPS, Inc. eval boards
#
core-$(CONFIG_MIPS_BOARDS_GEN) += arch/mips/mips-boards/generic/
@@ -327,7 +327,7 @@ load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000
#
# MIPS SIM
#
-core-$(CONFIG_MIPS_SIM) += arch/mips/mips-boards/sim/
+core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/
cflags-$(CONFIG_MIPS_SIM) += -Iinclude/asm-mips/mach-sim
load-$(CONFIG_MIPS_SIM) += 0x80100000
@@ -343,12 +343,12 @@ cflags-$(CONFIG_MOMENCO_OCELOT) += -Iinclude/asm-mips/mach-ocelot
load-$(CONFIG_MOMENCO_OCELOT) += 0xffffffff80100000
#
-# Momentum Ocelot-C and -CS boards
+# PMC-Sierra MSP SOCs
#
-# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the
-# mips_io_port_base.
-core-$(CONFIG_MOMENCO_OCELOT_C) += arch/mips/momentum/ocelot_c/
-load-$(CONFIG_MOMENCO_OCELOT_C) += 0xffffffff80100000
+core-$(CONFIG_PMC_MSP) += arch/mips/pmc-sierra/msp71xx/
+cflags-$(CONFIG_PMC_MSP) += -Iinclude/asm-mips/pmc-sierra/msp71xx \
+ -mno-branch-likely
+load-$(CONFIG_PMC_MSP) += 0xffffffff80100000
#
# PMC-Sierra Yosemite
@@ -365,13 +365,6 @@ cflags-$(CONFIG_QEMU) += -Iinclude/asm-mips/mach-qemu
load-$(CONFIG_QEMU) += 0xffffffff80010000
#
-# Momentum Ocelot-3
-#
-core-$(CONFIG_MOMENCO_OCELOT_3) += arch/mips/momentum/ocelot_3/
-cflags-$(CONFIG_MOMENCO_OCELOT_3) += -Iinclude/asm-mips/mach-ocelot3
-load-$(CONFIG_MOMENCO_OCELOT_3) += 0xffffffff80100000
-
-#
# Basler eXcite
#
core-$(CONFIG_BASLER_EXCITE) += arch/mips/basler/excite/
@@ -389,10 +382,6 @@ core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/
core-$(CONFIG_DDB5477) += arch/mips/ddb5xxx/ddb5477/
load-$(CONFIG_DDB5477) += 0xffffffff80100000
-core-$(CONFIG_LASAT) += arch/mips/lasat/
-cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat
-load-$(CONFIG_LASAT) += 0xffffffff80000000
-
#
# Common VR41xx
#
@@ -580,6 +569,7 @@ load-$(CONFIG_TOSHIBA_JMR3927) += 0xffffffff80050000
#
core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/toshiba_rbtx4927/
core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/common/
+cflags-$(CONFIG_TOSHIBA_RBTX4927) += -Iinclude/asm-mips/mach-tx49xx
load-$(CONFIG_TOSHIBA_RBTX4927) += 0xffffffff80020000
#
@@ -587,6 +577,7 @@ load-$(CONFIG_TOSHIBA_RBTX4927) += 0xffffffff80020000
#
core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/toshiba_rbtx4938/
core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/tx4938/common/
+cflags-$(CONFIG_TOSHIBA_RBTX4938) += -Iinclude/asm-mips/mach-tx49xx
load-$(CONFIG_TOSHIBA_RBTX4938) += 0xffffffff80100000
cflags-y += -Iinclude/asm-mips/mach-generic
@@ -603,7 +594,8 @@ JIFFIES = jiffies_64
endif
AFLAGS += $(cflags-y)
-CFLAGS += $(cflags-y)
+CFLAGS += $(cflags-y) \
+ -D"VMLINUX_LOAD_ADDRESS=$(load-y)"
LDFLAGS += -m $(ld-emul)
@@ -633,18 +625,11 @@ CPPFLAGS_vmlinux.lds := \
head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
libs-y += arch/mips/lib/
-libs-$(CONFIG_32BIT) += arch/mips/lib-32/
-libs-$(CONFIG_64BIT) += arch/mips/lib-64/
core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/
drivers-$(CONFIG_OPROFILE) += arch/mips/oprofile/
-ifdef CONFIG_LASAT
-rom.bin rom.sw: vmlinux
- $(Q)$(MAKE) $(build)=arch/mips/lasat/image $@
-endif
-
#
# Some machines like the Indy need 32-bit ELF binaries for booting purposes.
# Other need ECOFF, so we build a 32-bit ELF binary for them which we then
@@ -702,32 +687,19 @@ vmlinux.srec: $(vmlinux-32)
CLEAN_FILES += vmlinux.ecoff \
vmlinux.srec
+archprepare:
+ifdef CONFIG_MIPS32_N32
+ @echo ' Checking missing-syscalls for N32'
+ $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32"
+endif
+ifdef CONFIG_MIPS32_O32
+ @echo ' Checking missing-syscalls for O32'
+ $(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32"
+endif
+
archclean:
@$(MAKE) $(clean)=arch/mips/boot
- @$(MAKE) $(clean)=arch/mips/lasat
CLEAN_FILES += vmlinux.32 \
vmlinux.64 \
vmlinux.ecoff
-
-quiet_cmd_syscalls_n32 = CALL-N32 $<
- cmd_syscalls_n32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=n32
-
-quiet_cmd_syscalls_o32 = CALL-O32 $<
- cmd_syscalls_o32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=32
-
-PHONY += missing-syscalls-n32 missing-syscalls-o32
-
-missing-syscalls-n32: scripts/checksyscalls.sh FORCE
- $(call cmd,syscalls_n32)
-
-missing-syscalls-o32: scripts/checksyscalls.sh FORCE
- $(call cmd,syscalls_o32)
-
-archprepare:
-ifdef CONFIG_MIPS32_N32
- $(Q)$(MAKE) $(build)=arch/mips missing-syscalls-n32
-endif
-ifdef CONFIG_MIPS32_O32
- $(Q)$(MAKE) $(build)=arch/mips missing-syscalls-o32
-endif
diff --git a/arch/mips/au1000/common/gpio.c b/arch/mips/au1000/common/gpio.c
index ce55297dcb8..7abe4209943 100644
--- a/arch/mips/au1000/common/gpio.c
+++ b/arch/mips/au1000/common/gpio.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ * Architecture specific GPIO support
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -18,101 +21,136 @@
* You 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.
+ *
+ * Notes :
+ * au1000 SoC have only one GPIO line : GPIO1
+ * others have a second one : GPIO2
*/
+
+#include <linux/autoconf.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
#include <linux/module.h>
-#include <au1000.h>
-#include <au1xxx_gpio.h>
+
+#include <asm/addrspace.h>
+
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/gpio.h>
#define gpio1 sys
#if !defined(CONFIG_SOC_AU1000)
-static AU1X00_GPIO2 * const gpio2 = (AU1X00_GPIO2 *)GPIO2_BASE;
-#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
+static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE;
+#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
-int au1xxx_gpio2_read(int signal)
+static int au1xxx_gpio2_read(unsigned gpio)
{
- signal -= 200;
-/* gpio2->dir &= ~(0x01 << signal); //Set GPIO to input */
- return ((gpio2->pinstate >> signal) & 0x01);
+ gpio -= AU1XXX_GPIO_BASE;
+ return ((gpio2->pinstate >> gpio) & 0x01);
}
-void au1xxx_gpio2_write(int signal, int value)
+static void au1xxx_gpio2_write(unsigned gpio, int value)
{
- signal -= 200;
+ gpio -= AU1XXX_GPIO_BASE;
- gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << signal) |
- (value << signal);
+ gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | (value << gpio);
}
-void au1xxx_gpio2_tristate(int signal)
+static int au1xxx_gpio2_direction_input(unsigned gpio)
{
- signal -= 200;
- gpio2->dir &= ~(0x01 << signal); /* Set GPIO to input */
+ gpio -= AU1XXX_GPIO_BASE;
+ gpio2->dir &= ~(0x01 << gpio);
+ return 0;
}
-#endif
-int au1xxx_gpio1_read(int signal)
+static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
+{
+ gpio -= AU1XXX_GPIO_BASE;
+ gpio2->dir = (0x01 << gpio) | (value << gpio);
+ return 0;
+}
+
+#endif /* !defined(CONFIG_SOC_AU1000) */
+
+static int au1xxx_gpio1_read(unsigned gpio)
{
-/* gpio1->trioutclr |= (0x01 << signal); */
- return ((gpio1->pinstaterd >> signal) & 0x01);
+ return ((gpio1->pinstaterd >> gpio) & 0x01);
}
-void au1xxx_gpio1_write(int signal, int value)
+static void au1xxx_gpio1_write(unsigned gpio, int value)
{
- if(value)
- gpio1->outputset = (0x01 << signal);
+ if (value)
+ gpio1->outputset = (0x01 << gpio);
else
- gpio1->outputclr = (0x01 << signal); /* Output a Zero */
+ /* Output a zero */
+ gpio1->outputclr = (0x01 << gpio);
}
-void au1xxx_gpio1_tristate(int signal)
+static int au1xxx_gpio1_direction_input(unsigned gpio)
{
- gpio1->trioutclr = (0x01 << signal); /* Tristate signal */
+ gpio1->pininputen = (0x01 << gpio);
+ return 0;
}
+static int au1xxx_gpio1_direction_output(unsigned gpio, int value)
+{
+ gpio1->trioutclr = (0x01 & gpio);
+ return 0;
+}
-int au1xxx_gpio_read(int signal)
+int au1xxx_gpio_get_value(unsigned gpio)
{
- if(signal >= 200)
+ if (gpio >= AU1XXX_GPIO_BASE)
#if defined(CONFIG_SOC_AU1000)
return 0;
#else
- return au1xxx_gpio2_read(signal);
+ return au1xxx_gpio2_read(gpio);
#endif
else
- return au1xxx_gpio1_read(signal);
+ return au1xxx_gpio1_read(gpio);
}
-void au1xxx_gpio_write(int signal, int value)
+EXPORT_SYMBOL(au1xxx_gpio_get_value);
+
+void au1xxx_gpio_set_value(unsigned gpio, int value)
{
- if(signal >= 200)
+ if (gpio >= AU1XXX_GPIO_BASE)
#if defined(CONFIG_SOC_AU1000)
;
#else
- au1xxx_gpio2_write(signal, value);
+ au1xxx_gpio2_write(gpio, value);
#endif
else
- au1xxx_gpio1_write(signal, value);
+ au1xxx_gpio1_write(gpio, value);
}
-void au1xxx_gpio_tristate(int signal)
+EXPORT_SYMBOL(au1xxx_gpio_set_value);
+
+int au1xxx_gpio_direction_input(unsigned gpio)
{
- if(signal >= 200)
+ if (gpio >= AU1XXX_GPIO_BASE)
#if defined(CONFIG_SOC_AU1000)
;
#else
- au1xxx_gpio2_tristate(signal);
+ return au1xxx_gpio2_direction_input(gpio);
#endif
else
- au1xxx_gpio1_tristate(signal);
+ return au1xxx_gpio1_direction_input(gpio);
}
-void au1xxx_gpio1_set_inputs(void)
+EXPORT_SYMBOL(au1xxx_gpio_direction_input);
+
+int au1xxx_gpio_direction_output(unsigned gpio, int value)
{
- gpio1->pininputen = 0;
+ if (gpio >= AU1XXX_GPIO_BASE)
+#if defined(CONFIG_SOC_AU1000)
+ ;
+#else
+ return au1xxx_gpio2_direction_output(gpio, value);
+#endif
+ else
+ return au1xxx_gpio1_direction_output(gpio, value);
}
-EXPORT_SYMBOL(au1xxx_gpio1_set_inputs);
-EXPORT_SYMBOL(au1xxx_gpio_tristate);
-EXPORT_SYMBOL(au1xxx_gpio_write);
-EXPORT_SYMBOL(au1xxx_gpio_read);
+EXPORT_SYMBOL(au1xxx_gpio_direction_output);
diff --git a/arch/mips/au1000/common/platform.c b/arch/mips/au1000/common/platform.c
index 8fd203d4a33..d51e18fb789 100644
--- a/arch/mips/au1000/common/platform.c
+++ b/arch/mips/au1000/common/platform.c
@@ -289,7 +289,7 @@ static struct platform_device *au1xxx_platform_devices[] __initdata = {
#endif
};
-int au1xxx_platform_init(void)
+int __init au1xxx_platform_init(void)
{
return platform_add_devices(au1xxx_platform_devices, ARRAY_SIZE(au1xxx_platform_devices));
}
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index 13fe187f35d..a95b3777319 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -100,18 +100,9 @@ void __init plat_mem_setup(void)
argptr = prom_getcmdline();
/* default panel */
/*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
-#ifdef CONFIG_MIPS_HYDROGEN3
- strcat(argptr, " video=au1100fb:panel:Hydrogen_3_NEC_panel_320x240,nohwcursor");
-#endif
}
#endif
-#ifdef CONFIG_FB_XPERT98
- if ((argptr = strstr(argptr, "video=")) == NULL) {
- argptr = prom_getcmdline();
- strcat(argptr, " video=atyfb:1024x768-8@70");
- }
-#endif
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
/* au1000 does not support vra, au1500 and au1100 do */
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index fa1c62f0551..8fc29982d70 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -203,11 +203,7 @@ wakeup_counter0_set(int ticks)
/* I haven't found anyone that doesn't use a 12 MHz source clock,
* but just in case.....
*/
-#ifdef CONFIG_AU1000_SRC_CLK
-#define AU1000_SRC_CLK CONFIG_AU1000_SRC_CLK
-#else
#define AU1000_SRC_CLK 12000000
-#endif
/*
* We read the real processor speed from the PLL. This is important
@@ -247,33 +243,8 @@ unsigned long cal_r4koff(void)
au_writel (0, SYS_TOYWRITE);
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
-#if defined(CONFIG_AU1000_USE32K)
- {
- unsigned long start, end, count;
-
- start = au_readl(SYS_RTCREAD);
- start += 2;
- /* wait for the beginning of a new tick
- */
- while (au_readl(SYS_RTCREAD) < start);
-
- /* Start r4k counter.
- */
- write_c0_count(0);
-
- /* Wait 0.5 seconds.
- */
- end = start + (32768 / trim_divide)/2;
-
- while (end > au_readl(SYS_RTCREAD));
-
- count = read_c0_count();
- cpu_speed = count * 2;
- }
-#else
cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) *
AU1000_SRC_CLK;
-#endif
}
else {
/* The 32KHz oscillator isn't running, so assume there
diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c
index 1fae39a608c..6131b56f41b 100644
--- a/arch/mips/au1000/pb1100/init.c
+++ b/arch/mips/au1000/pb1100/init.c
@@ -53,7 +53,7 @@ void __init prom_init(void)
prom_argc = fw_arg0;
prom_argv = (char **) fw_arg1;
- prom_envp = (int *) fw_arg3;
+ prom_envp = (char **) fw_arg3;
mips_machgroup = MACH_GROUP_ALCHEMY;
mips_machtype = MACH_PB1100;
diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c
index 043302b7fe5..eea2092bde8 100644
--- a/arch/mips/au1000/pb1200/board_setup.c
+++ b/arch/mips/au1000/pb1200/board_setup.c
@@ -131,14 +131,7 @@ void __init board_setup(void)
/* The Pb1200 development board uses external MUX for PSC0 to
support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
*/
-#if defined(CONFIG_AU1XXX_PSC_SPI) && defined(CONFIG_I2C_AU1550)
- #error I2C and SPI are mutually exclusive. Both are physically connected to PSC0.\
- Refer to Pb1200/Db1200 documentation.
-#elif defined( CONFIG_AU1XXX_PSC_SPI )
- bcsr->resets |= BCSR_RESETS_PCS0MUX;
- /*Hard Coding Value to enable Temp Sensors [bit 14] Value for SOC Au1200. Pls refer documentation*/
- bcsr->resets =0x900f;
-#elif defined( CONFIG_I2C_AU1550 )
+#ifdef CONFIG_I2C_AU1550
bcsr->resets &= (~BCSR_RESETS_PCS0MUX);
#endif
au_sync();
diff --git a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c
index 0ffdb4fd575..c9b655616fb 100644
--- a/arch/mips/au1000/pb1500/board_setup.c
+++ b/arch/mips/au1000/pb1500/board_setup.c
@@ -125,7 +125,7 @@ void __init board_setup(void)
au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
}
/* Put the clock in BCD mode */
- if (readl(0xac00002C) & 0x4) { /* reg B */
+ if (au_readl(0xac00002C) & 0x4) { /* reg B */
au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
au_sync();
}
diff --git a/arch/mips/cobalt/pci.c b/arch/mips/cobalt/pci.c
index d91027f43de..cfce7af1bca 100644
--- a/arch/mips/cobalt/pci.c
+++ b/arch/mips/cobalt/pci.c
@@ -35,6 +35,7 @@ static struct pci_controller cobalt_pci_controller = {
.mem_resource = &cobalt_mem_resource,
.io_resource = &cobalt_io_resource,
.io_offset = 0 - GT_DEF_PCI0_IO_BASE,
+ .io_map_base = CKSEG1ADDR(GT_DEF_PCI0_IO_BASE),
};
static int __init cobalt_pci_init(void)
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 39e251300c6..129e2c961fe 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
CONFIG_MIPS_ATLAS=y
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_MIPS_ATLAS=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index 4713a13211c..dc3e1bf4e42 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index 5e7ae56b1f3..4c7031222e6 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 631b2138ad6..c8c05785a86 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,44 +1,24 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc7
-# Wed Apr 18 14:25:45 2007
+# Linux kernel version: 2.6.22-rc2
+# Fri May 25 11:17:29 2007
#
CONFIG_MIPS=y
#
# Machine selection
#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
CONFIG_MIPS_COBALT=y
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_DDB5477 is not set
@@ -138,7 +118,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+CONFIG_ZONE_DMA_FLAG=0
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
@@ -178,6 +158,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
# CONFIG_BLK_DEV_INITRD is not set
@@ -193,14 +174,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -233,16 +219,13 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_MMU=y
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -268,7 +251,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -300,11 +282,11 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
#
@@ -345,13 +327,16 @@ CONFIG_NETWORK_SECMARK=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -370,10 +355,6 @@ CONFIG_FW_LOADER=y
#
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -418,7 +399,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -445,16 +425,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=0
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -479,87 +456,145 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
# CONFIG_BLK_DEV_RAM is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-CONFIG_SGI_IOC4=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=y
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_BLK_DEV_TC86C001=y
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
#
# SCSI device support
#
CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
+# CONFIG_SCSI_SRP is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+CONFIG_PATA_VIA=y
+# CONFIG_PATA_WINBOND is not set
+# CONFIG_PATA_PLATFORM is not set
#
# Multi-device support (RAID and LVM)
@@ -570,10 +605,14 @@ CONFIG_RAID_ATTRS=y
# Fusion MPT device support
#
# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -594,24 +633,7 @@ CONFIG_NETDEVICES=y
# ARCnet devices
#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
@@ -639,35 +661,8 @@ CONFIG_TULIP=y
# CONFIG_ULI526X is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
#
# Token Ring devices
@@ -675,18 +670,16 @@ CONFIG_NETXEN_NIC=y
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
@@ -711,10 +704,7 @@ CONFIG_INPUT=y
#
# Userland interfaces
#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_TSDEV is not set
# CONFIG_INPUT_EVDEV is not set
@@ -726,18 +716,23 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_COBALT_BTNS=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_UINPUT is not set
+CONFIG_INPUT_POLLDEV=y
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
@@ -754,7 +749,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
+# CONFIG_SERIAL_8250_PCI is not set
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
@@ -773,16 +768,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
CONFIG_COBALT_LCD=y
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_DRM is not set
@@ -792,10 +782,7 @@ CONFIG_COBALT_LCD=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -808,12 +795,7 @@ CONFIG_COBALT_LCD=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
# Multifunction device drivers
@@ -824,16 +806,19 @@ CONFIG_COBALT_LCD=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
#
@@ -868,10 +853,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -912,18 +893,30 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
#
-# RTC drivers
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
#
CONFIG_RTC_DRV_CMOS=y
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+
+#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
@@ -937,14 +930,6 @@ CONFIG_RTC_DRV_CMOS=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -952,8 +937,13 @@ CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
@@ -969,7 +959,7 @@ CONFIG_INOTIFY_USER=y
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
+# CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
#
@@ -1003,7 +993,6 @@ CONFIG_CONFIGFS_FS=y
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
@@ -1021,13 +1010,23 @@ CONFIG_CONFIGFS_FS=y
# Network File Systems
#
CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1051,10 +1050,7 @@ CONFIG_MSDOS_PARTITION=y
#
# Distributed Lock Manager
#
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
#
# Profiling support
@@ -1072,72 +1068,30 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
#
# Security options
#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 10f6af43753..ec60beb888b 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1000=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1000=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 4b086292774..f3c25f08bfa 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1100=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1100=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 820659e810d..6d400befbac 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1200=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1200=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 4050b9b91bc..82aea6e0882 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1500=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1500=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 7b3519058ab..82697714a9e 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_DB1550=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_DB1550=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 5b502a2013f..a42ab9ae7d4 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 4bbdab078ff..d6e3fffbc80 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
CONFIG_MACH_DECSTATION=y
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_MACH_DECSTATION=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index b5714a6a539..78f5004fb72 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
index 3044579f171..b29bff0f56c 100644
--- a/arch/mips/configs/emma2rh_defconfig
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
@@ -951,8 +947,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_RTC=m
-CONFIG_GEN_RTC=m
-CONFIG_GEN_RTC_X=y
+# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
deleted file mode 100644
index c10e4e06322..00000000000
--- a/arch/mips/configs/ev64120_defconfig
+++ /dev/null
@@ -1,985 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:30 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-CONFIG_MIPS_EV64120=y
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-# CONFIG_EVB_PCI1 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_MIPS_GT64120=y
-# CONFIG_SYSCLK_75 is not set
-# CONFIG_SYSCLK_83 is not set
-CONFIG_SYSCLK_100=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_KMOD is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=y
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-CONFIG_SLHC=y
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::"
-CONFIG_SYS_SUPPORTS_KGDB=y
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=m
-CONFIG_CRC_CCITT=y
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
index 460d7a26a8b..69810592aa6 100644
--- a/arch/mips/configs/excite_defconfig
+++ b/arch/mips/configs/excite_defconfig
@@ -26,9 +26,7 @@ CONFIG_BASLER_EXCITE=y
# CONFIG_BASLER_EXCITE_PROTOTYPE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_BASLER_EXCITE=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/fulong_defconfig b/arch/mips/configs/fulong_defconfig
new file mode 100644
index 00000000000..6ab94d8cf08
--- /dev/null
+++ b/arch/mips/configs/fulong_defconfig
@@ -0,0 +1,1765 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.22-rc4
+# Mon Jun 11 00:23:51 2007
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+CONFIG_LEMOTE_FULONG=y
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_MARKEINS is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_LOONGSON2=y
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_LOONGSON2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+# CONFIG_PAGE_SIZE_4KB is not set
+# CONFIG_PAGE_SIZE_8KB is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_BOARD_SCACHE=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_CPU_HAS_WB=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION="lm32"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_ISA=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_BUILD_ELF64 is not set
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_IEEE80211_SOFTMAC is not set
+# CONFIG_RFKILL is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_PARTITIONS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x1fc00000
+CONFIG_MTD_PHYSMAP_LEN=0x80000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+CONFIG_ATA_OVER_ETH=m
+
+#
+# Misc devices
+#
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_ATA is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=m
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_FIXED_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_DM9000 is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_TC35815 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_NET_FC=y
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_INPORT is not set
+# CONFIG_MOUSE_LOGIBM is not set
+# CONFIG_MOUSE_PC110PAD is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_ELEKTOR is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+# CONFIG_I2C_VIA is not set
+CONFIG_I2C_VIAPRO=m
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_SAA7134 is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_VIDEO_CX88 is not set
+# CONFIG_VIDEO_IVTV is not set
+# CONFIG_VIDEO_CAFE_CCIC is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_BACKLIGHT=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=y
+# CONFIG_FB_RADEON_I2C is not set
+CONFIG_FB_RADEON_BACKLIGHT=y
+# CONFIG_FB_RADEON_DEBUG is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_RTCTIMER=m
+CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_AC97_CODEC=m
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# PCI devices
+#
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+CONFIG_SND_VIA82XX=m
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
+
+#
+# ALSA MIPS devices
+#
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=y
+CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=936
+CONFIG_FAT_DEFAULT_IOCHARSET="utf8"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_BIND34 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp936"
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_WEAK_PW_HASH=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_DEBUG2=y
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+CONFIG_NLS_CODEPAGE_936=y
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 7ec618f3c8b..405c9f505a7 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 9ddc3eff479..a9dcbcf563c 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 8fc18809d5f..a040459bec1 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 9331cb0a19b..8a0b4ac5283 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
CONFIG_MACH_JAZZ=y
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_MACH_JAZZ=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
@@ -245,7 +241,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_ISA=y
CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
#
# PCCARD (PCMCIA/CardBus) support
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 1b364cf6914..9a25e770abd 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
deleted file mode 100644
index fd4272c1458..00000000000
--- a/arch/mips/configs/lasat200_defconfig
+++ /dev/null
@@ -1,1118 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:34 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-CONFIG_LASAT=y
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_PICVUE=y
-CONFIG_PICVUE_PROC=y
-CONFIG_DS1603=y
-CONFIG_LASAT_SYSCTL=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_MIPS_NILE4=y
-# CONFIG_CPU_BIG_ENDIAN is not set
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
-CONFIG_MIPS_GT64120=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-CONFIG_CPU_R5000=y
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_R5000_CPU_SCACHE=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-CONFIG_MTD_LASAT=y
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=m
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 1f64d7632a0..546cb243fd0 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
CONFIG_MIPS_MALTA=y
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_MIPS_MALTA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index a2db5c20121..6abad6f8831 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
CONFIG_MIPS_SIM=y
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
@@ -496,36 +492,23 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_MIPS_SIM_NET=y
+# CONFIG_DM9000 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index ad5c0bf87b2..4981ce425d8 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/msp71xx_defconfig
index 28547313ce1..adca5f7ba53 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:35 2007
+# Linux kernel version: 2.6.21-rc4
+# Thu Apr 26 18:11:29 2007
#
CONFIG_MIPS=y
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,14 +33,13 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-CONFIG_MOMENCO_OCELOT_3=y
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_DDB5477 is not set
# CONFIG_MACH_VR41XX is not set
+CONFIG_PMC_MSP=y
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_QEMU is not set
# CONFIG_MARKEINS is not set
@@ -62,6 +59,16 @@ CONFIG_MOMENCO_OCELOT_3=y
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_PMC_MSP4200_EVAL is not set
+# CONFIG_PMC_MSP4200_GW is not set
+# CONFIG_PMC_MSP7120_EVAL is not set
+CONFIG_PMC_MSP7120_GW=y
+# CONFIG_PMC_MSP7120_FPGA is not set
+
+#
+# Options for PMC-Sierra MSP chipsets
+#
+CONFIG_PMC_MSP_EMBEDDED_ROOTFS=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -71,24 +78,24 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
+CONFIG_BOOT_RAW=y
CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_NO_EXCEPT_FILL=y
CONFIG_CPU_BIG_ENDIAN=y
# CONFIG_CPU_LITTLE_ENDIAN is not set
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
+CONFIG_IRQ_MSP_CIC=y
+CONFIG_MSP_USB=y
CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
CONFIG_MIPS_L1_CACHE_SHIFT=5
#
# CPU selection
#
# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
+CONFIG_CPU_MIPS32_R2=y
# CONFIG_CPU_MIPS64_R1 is not set
# CONFIG_CPU_MIPS64_R2 is not set
# CONFIG_CPU_R3000 is not set
@@ -104,14 +111,14 @@ CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_R10000 is not set
# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_RM9000=y
+# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM9000=y
-CONFIG_WEAK_ORDERING=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR2=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
#
# Kernel type
@@ -122,13 +129,12 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PAGE_SIZE_16KB is not set
# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
# CONFIG_64BIT_PHYS_ADDR is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_SYNC=y
@@ -149,15 +155,16 @@ CONFIG_ZONE_DMA_FLAG=1
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
+CONFIG_HZ=250
+# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_BKL is not set
# CONFIG_KEXEC is not set
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
@@ -168,14 +175,15 @@ CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
#
-CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION="-pmc"
CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
+# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
CONFIG_SYSVIPC_SYSCTL=y
@@ -184,15 +192,16 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
+# CONFIG_IKCONFIG is not set
CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
@@ -201,11 +210,11 @@ CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-CONFIG_SHMEM=y
+# CONFIG_SHMEM is not set
CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
+CONFIG_TINY_SHMEM=y
CONFIG_BASE_SMALL=0
# CONFIG_SLOB is not set
@@ -232,8 +241,8 @@ CONFIG_BLOCK=y
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_DEADLINE is not set
# CONFIG_DEFAULT_CFQ is not set
@@ -245,6 +254,7 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+# CONFIG_PCI_DEBUG is not set
CONFIG_MMU=y
#
@@ -267,10 +277,7 @@ CONFIG_TRAD_SIGNALS=y
#
# Power management options
#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_PM is not set
#
# Networking
@@ -281,17 +288,16 @@ CONFIG_NET=y
# Networking options
#
# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
+# CONFIG_PACKET is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
@@ -300,122 +306,92 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not set
# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
+# CONFIG_TCP_MD5SIG is not set
#
# IP: Virtual Server Configuration
#
# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-CONFIG_IPV6_MIP6=y
+# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
#
# Core Netfilter Configuration
#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-CONFIG_NETFILTER_XT_MATCH_POLICY=m
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+CONFIG_NETFILTER_XTABLES=y
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
#
# IP: Netfilter Configuration
#
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_LOG is not set
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
# CONFIG_IP_NF_ARPTABLES is not set
#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
+# Bridge: Netfilter Configuration
#
-CONFIG_NF_CONNTRACK_IPV6=m
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
#
# DCCP Configuration (EXPERIMENTAL)
@@ -432,9 +408,10 @@ CONFIG_NF_CONNTRACK_IPV6=m
#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
+CONFIG_BRIDGE=y
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
+CONFIG_LLC=y
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
@@ -447,7 +424,6 @@ CONFIG_NF_CONNTRACK_IPV6=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -456,14 +432,8 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
+# CONFIG_IEEE80211 is not set
CONFIG_WIRELESS_EXT=y
-CONFIG_FIB_RULES=y
#
# Device Drivers
@@ -473,19 +443,101 @@ CONFIG_FIB_RULES=y
# Generic Driver Options
#
CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
+# CONFIG_CONNECTOR is not set
#
# Memory Technology Devices (MTD)
#
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PMC_MSP_EVM=y
+CONFIG_MSP_FLASH_MAP_LIMIT_32M=y
+CONFIG_MSP_FLASH_MAP_LIMIT=0x02000000
+CONFIG_MTD_PMC_MSP_RAMROOT=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
#
# Parallel port support
@@ -505,19 +557,21 @@ CONFIG_CONNECTOR=m
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_CDROM_PKTCDVD is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-CONFIG_SGI_IOC4=m
+# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
#
@@ -528,16 +582,16 @@ CONFIG_SGI_IOC4=m
#
# SCSI device support
#
-CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_SCSI_TGT=m
-CONFIG_SCSI_NETLINK=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
CONFIG_SCSI_PROC_FS=y
#
# SCSI support type (disk, tape, CD-ROM)
#
-# CONFIG_BLK_DEV_SD is not set
+CONFIG_BLK_DEV_SD=y
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
# CONFIG_BLK_DEV_SR is not set
@@ -550,22 +604,21 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_MULTI_LUN is not set
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
-CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
#
# SCSI Transports
#
# CONFIG_SCSI_SPI_ATTRS is not set
-CONFIG_SCSI_FC_ATTRS=m
-CONFIG_SCSI_ISCSI_ATTRS=m
-CONFIG_SCSI_SAS_ATTRS=m
-CONFIG_SCSI_SAS_LIBSAS=m
-# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
#
# SCSI low-level drivers
#
-CONFIG_ISCSI_TCP=m
+# CONFIG_ISCSI_TCP is not set
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
@@ -573,8 +626,7 @@ CONFIG_ISCSI_TCP=m
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_AIC94XX=m
-# CONFIG_AIC94XX_DEBUG is not set
+# CONFIG_SCSI_AIC94XX is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ARCMSR is not set
# CONFIG_MEGARAID_NEWGEN is not set
@@ -630,10 +682,10 @@ CONFIG_SCSI_AIC94XX=m
# Network device support
#
CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
+# CONFIG_TUN is not set
#
# ARCnet devices
@@ -643,26 +695,16 @@ CONFIG_TUN=m
#
# PHY device support
#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
+CONFIG_MSPETH=y
+CONFIG_MSPETH_NAPI=y
+# CONFIG_MSPETH_SKB_RECYCLE is not set
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
@@ -674,26 +716,7 @@ CONFIG_MII=y
#
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-CONFIG_E100=y
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_SC92031 is not set
+# CONFIG_NET_PCI is not set
#
# Ethernet (1000 Mbit)
@@ -709,22 +732,20 @@ CONFIG_E100=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
-CONFIG_MV643XX_ETH=y
-CONFIG_QLA3XXX=m
+# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
+# CONFIG_NETXEN_NIC is not set
#
# Token Ring devices
@@ -734,7 +755,29 @@ CONFIG_NETXEN_NIC=m
#
# Wireless LAN (non-hamradio)
#
-# CONFIG_NET_RADIO is not set
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
#
# Wan interfaces
@@ -742,17 +785,17 @@ CONFIG_NETXEN_NIC=m
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
-CONFIG_PPP=m
+CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
# CONFIG_SLIP is not set
-CONFIG_SLHC=m
+CONFIG_SLHC=y
# CONFIG_NET_FC is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
@@ -796,31 +839,24 @@ CONFIG_INPUT=y
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_PMCMSP_GPIO=y
#
# Serial drivers
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
# CONFIG_SERIAL_8250_EXTENDED is not set
#
@@ -830,8 +866,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_LEGACY_PTYS is not set
#
# IPMI
@@ -843,7 +878,8 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
@@ -858,7 +894,58 @@ CONFIG_RTC=y
#
# I2C support
#
-# CONFIG_I2C is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PASEMI is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_PMCMSP=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+CONFIG_PMCTWILED=y
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
#
# SPI support
@@ -874,8 +961,57 @@ CONFIG_RTC=y
#
# Hardware Monitoring support
#
-# CONFIG_HWMON is not set
+CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
@@ -886,62 +1022,13 @@ CONFIG_RTC=y
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB is not set
#
# Sound
@@ -960,13 +1047,134 @@ CONFIG_HID=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -1030,37 +1238,22 @@ CONFIG_USB_ARCH_HAS_EHCI=y
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
+# CONFIG_INOTIFY is not set
# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
#
# CD-ROM/DVD Filesystems
@@ -1071,22 +1264,25 @@ CONFIG_GENERIC_ACL=y
#
# DOS/FAT/NT Filesystems
#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
+# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -1097,8 +1293,21 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
-CONFIG_EFS_FS=y
-CONFIG_CRAMFS=y
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_SQUASHFS_VMALLOC=y
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -1108,26 +1317,9 @@ CONFIG_CRAMFS=y
#
# Network File Systems
#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
-# CONFIG_NFSD_V4 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -1143,9 +1335,9 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=m
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
@@ -1169,7 +1361,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
@@ -1187,10 +1379,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Distributed Lock Manager
#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
#
# Profiling support
@@ -1203,14 +1392,40 @@ CONFIG_DLM_TCP=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
# CONFIG_PRINTK_TIME is not set
CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_LIST is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="ip=any root=nfs"
+CONFIG_CMDLINE=""
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_KGDB is not set
+CONFIG_SYS_SUPPORTS_KGDB=y
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_MIPS_UNCACHED is not set
#
# Security options
@@ -1223,41 +1438,40 @@ CONFIG_CMDLINE="ip=any root=nfs"
#
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
+# CONFIG_CRYPTO_XCBC is not set
+CONFIG_CRYPTO_NULL=y
+# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_ECB is not set
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
@@ -1268,16 +1482,12 @@ CONFIG_CRYPTO_CAMELLIA=m
# Library routines
#
CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
+# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
+CONFIG_ZLIB_DEFLATE=y
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
deleted file mode 100644
index 82ff6fc0cd4..00000000000
--- a/arch/mips/configs/ocelot_c_defconfig
+++ /dev/null
@@ -1,982 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:36 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-CONFIG_MOMENCO_OCELOT_C=y
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM7000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-# CONFIG_32BIT is not set
-CONFIG_64BIT=y
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_KEXEC is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_BLK_DEV_IO_TRACE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-# CONFIG_BUILD_ELF64 is not set
-CONFIG_MIPS32_COMPAT=y
-CONFIG_COMPAT=y
-CONFIG_SYSVIPC_COMPAT=y
-CONFIG_MIPS32_O32=y
-CONFIG_MIPS32_N32=y
-CONFIG_BINFMT_ELF32=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=y
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-# CONFIG_MV643XX_ETH is not set
-CONFIG_QLA3XXX=y
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Distributed Lock Manager
-#
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index 15a027e00ee..e1db1fb80cd 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
CONFIG_MOMENCO_OCELOT=y
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 37d696c6454..0028aef0af9 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_PB1100=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_PB1100=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index b11f0e8b605..8a1d5888739 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_PB1500=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_PB1500=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 2927f38f490..5581ad2ca41 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -26,9 +26,7 @@ CONFIG_MIPS_PB1550=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -36,8 +34,6 @@ CONFIG_MIPS_PB1550=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index fae16c5ec52..821c1cee563 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
CONFIG_PNX8550_JBS=y
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig
index cd821e52181..0e8bd92b38c 100644
--- a/arch/mips/configs/pnx8550-stb810_defconfig
+++ b/arch/mips/configs/pnx8550-stb810_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 8e8d0315795..703de002e37 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
@@ -225,7 +221,7 @@ CONFIG_DEFAULT_IOSCHED="noop"
#
CONFIG_ISA=y
CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
#
# PCCARD (PCMCIA/CardBus) support
diff --git a/arch/mips/configs/rbhma4200_defconfig b/arch/mips/configs/rbhma4200_defconfig
index 35d64260917..20a38526d48 100644
--- a/arch/mips/configs/rbhma4200_defconfig
+++ b/arch/mips/configs/rbhma4200_defconfig
@@ -24,17 +24,13 @@ CONFIG_MIPS=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 41011f770a6..5dbb250f71c 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:39 2007
+# Linux kernel version: 2.6.22-rc5
+# Fri Jun 22 21:39:45 2007
#
CONFIG_MIPS=y
@@ -9,40 +9,23 @@ CONFIG_MIPS=y
# Machine selection
#
CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MACH_ALCHEMY is not set
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_WR_PPMC is not set
# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_DDB5477 is not set
# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_MSP is not set
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_QEMU is not set
# CONFIG_MARKEINS is not set
@@ -82,6 +65,8 @@ CONFIG_DMA_NONCOHERENT=y
CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_I8259=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
@@ -93,6 +78,7 @@ CONFIG_HAVE_STD_PC_SERIAL_PORT=y
#
# CPU selection
#
+# CONFIG_CPU_LOONGSON2 is not set
# CONFIG_CPU_MIPS32_R1 is not set
# CONFIG_CPU_MIPS32_R2 is not set
# CONFIG_CPU_MIPS64_R1 is not set
@@ -149,12 +135,12 @@ CONFIG_ZONE_DMA_FLAG=1
# CONFIG_HZ_48 is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
# CONFIG_HZ_1024 is not set
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
@@ -186,28 +172,35 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
+# CONFIG_HOTPLUG is not set
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -244,17 +237,12 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
#
CONFIG_HW_HAS_PCI=y
CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_MMU=y
#
# PCCARD (PCMCIA/CardBus) support
#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
#
# Executable file formats
@@ -266,10 +254,7 @@ CONFIG_TRAD_SIGNALS=y
#
# Power management options
#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_PM is not set
#
# Networking
@@ -279,14 +264,9 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
-CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -294,7 +274,7 @@ CONFIG_IP_MULTICAST=y
CONFIG_IP_FIB_HASH=y
CONFIG_IP_PNP=y
# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
@@ -305,130 +285,23 @@ CONFIG_IP_PNP_BOOTP=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-CONFIG_IPV6=m
-# CONFIG_IPV6_PRIVACY is not set
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-CONFIG_IPV6_MIP6=y
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
-CONFIG_IPV6_SIT=m
-# CONFIG_IPV6_TUNNEL is not set
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETWORK_SECMARK=y
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-CONFIG_NETFILTER_NETLINK=m
-CONFIG_NETFILTER_NETLINK_QUEUE=m
-CONFIG_NETFILTER_NETLINK_LOG=m
-CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
-CONFIG_NF_CONNTRACK=m
-CONFIG_NF_CT_ACCT=y
-CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CONNTRACK_SECMARK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CONNTRACK_AMANDA=m
-CONFIG_NF_CONNTRACK_FTP=m
-CONFIG_NF_CONNTRACK_H323=m
-CONFIG_NF_CONNTRACK_IRC=m
-# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
-CONFIG_NF_CONNTRACK_PPTP=m
-CONFIG_NF_CONNTRACK_SANE=m
-CONFIG_NF_CONNTRACK_SIP=m
-CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NF_CT_NETLINK=m
-CONFIG_NETFILTER_XTABLES=m
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
-CONFIG_NETFILTER_XT_TARGET_MARK=m
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NFLOG=m
-CONFIG_NETFILTER_XT_TARGET_SECMARK=m
-CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
-CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_COMMENT=m
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-CONFIG_NETFILTER_XT_MATCH_DCCP=m
-CONFIG_NETFILTER_XT_MATCH_DSCP=m
-CONFIG_NETFILTER_XT_MATCH_ESP=m
-CONFIG_NETFILTER_XT_MATCH_HELPER=m
-CONFIG_NETFILTER_XT_MATCH_LENGTH=m
-CONFIG_NETFILTER_XT_MATCH_LIMIT=m
-CONFIG_NETFILTER_XT_MATCH_MAC=m
-CONFIG_NETFILTER_XT_MATCH_MARK=m
-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
-CONFIG_NETFILTER_XT_MATCH_QUOTA=m
-CONFIG_NETFILTER_XT_MATCH_REALM=m
-CONFIG_NETFILTER_XT_MATCH_SCTP=m
-CONFIG_NETFILTER_XT_MATCH_STATE=m
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
-CONFIG_NETFILTER_XT_MATCH_STRING=m
-CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_CONNTRACK_PROC_COMPAT=y
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-
-#
-# IPv6: Netfilter Configuration (EXPERIMENTAL)
-#
-CONFIG_NF_CONNTRACK_IPV6=m
-# CONFIG_IP6_NF_QUEUE is not set
-# CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -446,7 +319,6 @@ CONFIG_NF_CONNTRACK_IPV6=m
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -455,15 +327,16 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_CRYPT_TKIP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-CONFIG_FIB_RULES=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -474,94 +347,13 @@ CONFIG_FIB_RULES=y
#
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_PMC551 is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
-# CONFIG_MTD_NAND is not set
-
-#
-# OneNAND Flash Device Drivers
-#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
#
# Parallel port support
@@ -583,93 +375,30 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_UB is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-CONFIG_SGI_IOC4=m
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_IDE_MAX_HWIFS=4
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_BLK_DEV_CMD64X is not set
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_JMICRON is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-CONFIG_BLK_DEV_IT8213=m
-# CONFIG_BLK_DEV_IT821X is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_BLK_DEV_SVWKS is not set
-# CONFIG_BLK_DEV_SIIMAGE is not set
-# CONFIG_BLK_DEV_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_TC86C001=m
-# CONFIG_IDE_ARM is not set
-CONFIG_BLK_DEV_IDEDMA=y
-# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLINK is not set
+# CONFIG_IDE is not set
#
# SCSI device support
#
-CONFIG_RAID_ATTRS=m
+# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -685,6 +414,7 @@ CONFIG_RAID_ATTRS=m
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -699,36 +429,15 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
+# CONFIG_TUN is not set
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
@@ -747,6 +456,7 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
+CONFIG_TC35815=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
@@ -761,91 +471,20 @@ CONFIG_NET_PCI=y
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=m
-# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-CONFIG_IPW2200=m
-# CONFIG_IPW2200_MONITOR is not set
-# CONFIG_IPW2200_QOS is not set
-# CONFIG_IPW2200_DEBUG is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_BCM43XX is not set
-# CONFIG_ZD1211RW is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-CONFIG_PPP_MULTILINK=y
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
+# CONFIG_PPP is not set
# CONFIG_SLIP is not set
-CONFIG_SLHC=m
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
@@ -864,57 +503,18 @@ CONFIG_SLHC=m
#
# Input device support
#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
#
# Character devices
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
# CONFIG_SERIAL_NONSTANDARD is not set
#
@@ -926,11 +526,12 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_TXX9=y
CONFIG_HAS_TXX9_SERIAL=y
CONFIG_SERIAL_TXX9_NR_UARTS=6
-# CONFIG_SERIAL_TXX9_CONSOLE is not set
-# CONFIG_SERIAL_TXX9_STDSERIAL is not set
+CONFIG_SERIAL_TXX9_CONSOLE=y
+CONFIG_SERIAL_TXX9_STDSERIAL=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
@@ -940,15 +541,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_DRM is not set
@@ -958,108 +554,61 @@ CONFIG_LEGACY_PTY_COUNT=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
#
-# I2C support
+# SPI Master Controller Drivers
#
-# CONFIG_I2C is not set
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_TXX9=y
#
-# SPI support
+# SPI Protocol Masters
#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
+CONFIG_SPI_AT25=y
+# CONFIG_SPI_SPIDEV is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_SENSORS_ABITUGURU is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
# Graphics support
#
-# CONFIG_FIRMWARE_EDID is not set
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-CONFIG_FB_ATY=y
-CONFIG_FB_ATY_CT=y
-# CONFIG_FB_ATY_GENERIC_LCD is not set
-# CONFIG_FB_ATY_GX is not set
-# CONFIG_FB_S3 is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_VGACON_SOFT_SCROLLBACK is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Sound
+# Display device support
#
-# CONFIG_SOUND is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
#
-# HID Devices
+# Sound
#
-CONFIG_HID=y
-# CONFIG_HID_DEBUG is not set
+# CONFIG_SOUND is not set
#
# USB support
@@ -1067,148 +616,80 @@ CONFIG_HID=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_EHCI_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_OHCI_HCD is not set
-# CONFIG_USB_UHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
+# CONFIG_USB is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
#
#
-# may also be needed; see USB_STORAGE Help for more information
-#
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-CONFIG_USB_YEALINK=m
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
-CONFIG_USB_MON=y
-
-#
-# USB port drivers
+# USB Gadget Support
#
+# CONFIG_USB_GADGET is not set
+# CONFIG_MMC is not set
#
-# USB Serial Converter support
+# LED devices
#
-# CONFIG_USB_SERIAL is not set
+# CONFIG_NEW_LEDS is not set
#
-# USB Miscellaneous drivers
+# LED drivers
#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_BERRY_CHARGE is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
#
-# USB DSL modem support
+# LED Triggers
#
#
-# USB Gadget Support
+# InfiniBand support
#
-# CONFIG_USB_GADGET is not set
+# CONFIG_INFINIBAND is not set
#
-# MMC/SD Card support
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
#
-# CONFIG_MMC is not set
#
-# LED devices
+# Real Time Clock
#
-# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
#
-# LED drivers
+# RTC interfaces
#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
#
-# LED Triggers
+# I2C RTC drivers
#
#
-# InfiniBand support
+# SPI RTC drivers
#
-# CONFIG_INFINIBAND is not set
+CONFIG_RTC_DRV_RS5C348=y
+# CONFIG_RTC_DRV_MAX6902 is not set
#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+# Platform RTC drivers
#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
#
-# Real Time Clock
+# on-CPU RTC drivers
#
-# CONFIG_RTC_CLASS is not set
#
# DMA Engine support
@@ -1224,38 +705,15 @@ CONFIG_USB_MON=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
# CONFIG_EXT4DEV_FS is not set
-CONFIG_JBD=m
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_XFS_RT is not set
+# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
@@ -1265,26 +723,21 @@ CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
# CONFIG_DNOTIFY is not set
# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=m
-CONFIG_FUSE_FS=m
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
CONFIG_GENERIC_ACL=y
#
# CD-ROM/DVD Filesystems
#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+# CONFIG_ISO9660_FS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
-CONFIG_FAT_FS=y
# CONFIG_MSDOS_FS is not set
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set
#
@@ -1298,7 +751,7 @@ CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=m
+# CONFIG_CONFIGFS_FS is not set
#
# Miscellaneous filesystems
@@ -1310,16 +763,7 @@ CONFIG_CONFIGFS_FS=m
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-CONFIG_CRAMFS=y
+# CONFIG_CRAMFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
@@ -1334,19 +778,16 @@ CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
@@ -1362,54 +803,12 @@ CONFIG_MSDOS_PARTITION=y
#
# Native Language Support
#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+# CONFIG_NLS is not set
#
# Distributed Lock Manager
#
-CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
#
# Profiling support
@@ -1427,7 +826,6 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_CROSSCOMPILE=y
CONFIG_CMDLINE=""
CONFIG_SYS_SUPPORTS_KGDB=y
@@ -1441,62 +839,17 @@ CONFIG_SYS_SUPPORTS_KGDB=y
#
# Cryptographic options
#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_GF128MUL=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
-CONFIG_CRC_CCITT=m
-CONFIG_CRC16=m
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_TEXTSEARCH=y
-CONFIG_TEXTSEARCH_KMP=m
-CONFIG_TEXTSEARCH_BM=m
-CONFIG_TEXTSEARCH_FSM=m
+# CONFIG_LIBCRC32C is not set
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 5593cde9f74..a5dc5cb97aa 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
@@ -255,7 +251,7 @@ CONFIG_PCI=y
CONFIG_ISA=y
# CONFIG_EISA is not set
CONFIG_MMU=y
-CONFIG_I8253=y
+CONFIG_PCSPEAKER=y
#
# PCCARD (PCMCIA/CardBus) support
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index 6c4f09a381e..98a91409225 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 988b9cdef01..69c08b24c82 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
CONFIG_MIPS_SEAD=y
@@ -35,8 +33,6 @@ CONFIG_MIPS_SEAD=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig
index 8b1675c07ec..5d4fc0e4f72 100644
--- a/arch/mips/configs/tb0219_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index b5be8b74d89..1b92b48de05 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 8bb6be4342b..5b77c7a5d83 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index 8f019ffcc71..94a4f94a8b2 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
index 52b48c0715d..e38bd9b0ead 100644
--- a/arch/mips/configs/wrppmc_defconfig
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_WR_PPMC=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index 6824606309e..f342d8c887b 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
@@ -596,8 +592,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_RTC is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index 23fd3b81fe1..4864b8a659c 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,8 @@
# Makefile for NEC DDB-Vrc5477 board
#
-obj-y += irq.o irq_5477.o setup.o lcd44780.o
+obj-y += ddb5477-platform.o irq.o irq_5477.o setup.o \
+ lcd44780.o
obj-$(CONFIG_RUNTIME_DEBUG) += debug.o
obj-$(CONFIG_KGDB) += kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c b/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c
new file mode 100644
index 00000000000..c16020ad54c
--- /dev/null
+++ b/arch/mips/ddb5xxx/ddb5477/ddb5477-platform.c
@@ -0,0 +1,49 @@
+/*
+ * 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) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ddb5xxx/ddb5477.h>
+
+#define DDB_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+#define DDB5477_PORT(base, int) \
+{ \
+ .mapbase = base, \
+ .irq = int, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_MEM, \
+ .flags = DDB_UART_FLAGS, \
+ .regshift = 3, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ DDB5477_PORT(0xbfa04200, VRC5477_IRQ_UART0),
+ DDB5477_PORT(0xbfa04240, VRC5477_IRQ_UART1),
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the NEC DDB5477");
diff --git a/arch/mips/dec/prom/console.c b/arch/mips/dec/prom/console.c
index 65419bf3244..078e1a12421 100644
--- a/arch/mips/dec/prom/console.c
+++ b/arch/mips/dec/prom/console.c
@@ -3,7 +3,7 @@
*
* DECstation PROM-based early console support.
*
- * Copyright (C) 2004 Maciej W. Rozycki
+ * Copyright (C) 2004, 2007 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -13,15 +13,35 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/string.h>
#include <asm/dec/prom.h>
-void prom_putchar(char c)
+static void __init prom_console_write(struct console *con, const char *s,
+ unsigned int c)
{
- char s[2];
+ char buf[81];
+ unsigned int chunk = sizeof(buf) - 1;
- s[0] = c;
- s[1] = '\0';
+ while (c > 0) {
+ if (chunk > c)
+ chunk = c;
+ memcpy(buf, s, chunk);
+ buf[chunk] = '\0';
+ prom_printf("%s", buf);
+ s += chunk;
+ c -= chunk;
+ }
+}
+
+static struct console promcons __initdata = {
+ .name = "prom",
+ .write = prom_console_write,
+ .flags = CON_BOOT | CON_PRINTBUFFER,
+ .index = -1,
+};
- prom_printf( s);
+void __init register_prom_console(void)
+{
+ register_console(&promcons);
}
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
index a217aafe59f..808c182fd3f 100644
--- a/arch/mips/dec/prom/init.c
+++ b/arch/mips/dec/prom/init.c
@@ -86,7 +86,7 @@ void __init which_prom(s32 magic, s32 *prom_vec)
void __init prom_init(void)
{
- extern void ATTRIB_NORET dec_machine_halt(void);
+ extern void dec_machine_halt(void);
static char cpu_msg[] __initdata =
"Sorry, this kernel is compiled for a wrong CPU type!\n";
s32 argc = fw_arg0;
@@ -103,6 +103,9 @@ void __init prom_init(void)
if (prom_is_rex(magic))
rex_clear_cache();
+ /* Register the early console. */
+ register_prom_console();
+
/* Were we compiled with the right CPU option? */
#if defined(CONFIG_CPU_R3000)
if ((current_cpu_data.cputype == CPU_R4000SC) ||
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
index 56397227adb..c15a879046e 100644
--- a/arch/mips/dec/reset.c
+++ b/arch/mips/dec/reset.c
@@ -9,26 +9,26 @@
#include <asm/addrspace.h>
-typedef void ATTRIB_NORET (* noret_func_t)(void);
+typedef void __noreturn (* noret_func_t)(void);
-static inline void ATTRIB_NORET back_to_prom(void)
+static inline void __noreturn back_to_prom(void)
{
noret_func_t func = (void *)CKSEG1ADDR(0x1fc00000);
func();
}
-void ATTRIB_NORET dec_machine_restart(char *command)
+void __noreturn dec_machine_restart(char *command)
{
back_to_prom();
}
-void ATTRIB_NORET dec_machine_halt(void)
+void __noreturn dec_machine_halt(void)
{
back_to_prom();
}
-void ATTRIB_NORET dec_machine_power_off(void)
+void __noreturn dec_machine_power_off(void)
{
/* DECstations don't have a software power switch */
back_to_prom();
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 41211f8b773..b3b6e58058f 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -25,9 +25,7 @@ CONFIG_ZONE_DMA=y
# CONFIG_BASLER_EXCITE is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_MALTA is not set
# CONFIG_MIPS_SEAD is not set
@@ -35,8 +33,6 @@ CONFIG_ZONE_DMA=y
# CONFIG_MIPS_SIM is not set
# CONFIG_MOMENCO_JAGUAR_ATX is not set
# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
# CONFIG_MOMENCO_OCELOT_G is not set
# CONFIG_MIPS_XXS1500 is not set
# CONFIG_PNX8550_JBS is not set
diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c
index b29a4473923..2f060e1ed36 100644
--- a/arch/mips/emma2rh/markeins/setup.c
+++ b/arch/mips/emma2rh/markeins/setup.c
@@ -115,30 +115,6 @@ extern void markeins_irq_setup(void);
static void inline __init markeins_sio_setup(void)
{
-#ifdef CONFIG_KGDB_8250
- struct uart_port emma_port;
-
- memset(&emma_port, 0, sizeof(emma_port));
-
- emma_port.flags =
- UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
- emma_port.iotype = UPIO_MEM;
- emma_port.regshift = 4; /* I/O addresses are every 8 bytes */
- emma_port.uartclk = 18544000; /* Clock rate of the chip */
-
- emma_port.line = 0;
- emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3);
- emma_port.membase = (u8*)emma_port.mapbase;
- early_serial_setup(&emma_port);
-
- emma_port.line = 1;
- emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3);
- emma_port.membase = (u8*)emma_port.mapbase;
- early_serial_setup(&emma_port);
-
- emma_port.irq = EMMA2RH_IRQ_PFUR1;
- kgdb8250_add_port(1, &emma_port);
-#endif
}
void __init plat_mem_setup(void)
diff --git a/arch/mips/gt64120/ev64120/Kconfig b/arch/mips/gt64120/ev64120/Kconfig
deleted file mode 100644
index d691762cb0f..00000000000
--- a/arch/mips/gt64120/ev64120/Kconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-config EVB_PCI1
- bool "Enable Second PCI (PCI1)"
- depends on MIPS_EV64120
diff --git a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile
deleted file mode 100644
index 323b2cebc69..00000000000
--- a/arch/mips/gt64120/ev64120/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Copyright 2000 RidgeRun, Inc.
-# Author: RidgeRun, Inc.
-# glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
-#
-# Makefile for the Galileo EV64120 board.
-#
-
-obj-y += irq.o promcon.o reset.o serialGT.o setup.o
diff --git a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c
deleted file mode 100644
index 64e4c80b613..00000000000
--- a/arch/mips/gt64120/ev64120/irq.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Code to handle irqs on GT64120A boards
- * Derived from mips/orion and Cort <cort@fsmlabs.com>
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/gt64120.h>
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-
- if (pending & STATUSF_IP4) /* int2 hardware line (timer) */
- do_IRQ(4);
- else if (pending & STATUSF_IP2) /* int0 hardware line */
- do_IRQ(GT_INTA);
- else if (pending & STATUSF_IP5) /* int3 hardware line */
- do_IRQ(GT_INTD);
- else if (pending & STATUSF_IP6) /* int4 hardware line */
- do_IRQ(6);
- else if (pending & STATUSF_IP7) /* compare int */
- do_IRQ(7);
- else
- spurious_interrupt();
-}
-
-static void disable_ev64120_irq(unsigned int irq_nr)
-{
- if (irq_nr >= 8) { // All PCI interrupts are on line 5 or 2
- clear_c0_status(9 << 10);
- } else {
- clear_c0_status(1 << (irq_nr + 8));
- }
-}
-
-static void enable_ev64120_irq(unsigned int irq_nr)
-{
- if (irq_nr >= 8) // All PCI interrupts are on line 5 or 2
- set_c0_status(9 << 10);
- else
- set_c0_status(1 << (irq_nr + 8));
-}
-
-static void end_ev64120_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_ev64120_irq(irq);
-}
-
-static struct irq_chip ev64120_irq_type = {
- .name = "EV64120",
- .ack = disable_ev64120_irq,
- .mask = disable_ev64120_irq,
- .mask_ack = disable_ev64120_irq,
- .unmask = enable_ev64120_irq,
- .end = end_ev64120_irq,
-};
-
-void gt64120_irq_setup(void)
-{
- /*
- * Clear all of the interrupts while we change the able around a bit.
- */
- clear_c0_status(ST0_IM);
-
- /*
- * Enable timer. Other interrupts will be enabled as they are
- * registered.
- */
- set_c0_status(IE_IRQ2);
-}
-
-void __init arch_init_irq(void)
-{
- gt64120_irq_setup();
-}
diff --git a/arch/mips/gt64120/ev64120/promcon.c b/arch/mips/gt64120/ev64120/promcon.c
deleted file mode 100644
index 6e0ecfed964..00000000000
--- a/arch/mips/gt64120/ev64120/promcon.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Wrap-around code for a console using the
- * SGI PROM io-routines.
- *
- * Copyright (c) 1999 Ulf Carlsson
- *
- * Derived from DECstation promcon.c
- * Copyright (c) 1998 Harald Koerfgen
- */
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-static void prom_console_write(struct console *co, const char *s,
- unsigned count)
-{
- extern int CONSOLE_CHANNEL; // The default serial port
- unsigned i;
-
- for (i = 0; i < count; i++) {
- if (*s == 10)
- serial_putc(CONSOLE_CHANNEL, 13);
- serial_putc(CONSOLE_CHANNEL, *s++);
- }
-}
-
-static struct console sercons = {
- .name = "ttyS",
- .write = prom_console_write,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-/*
- * Register console.
- */
-
-static int gal_serial_console_init(void)
-{
- // serial_init();
- //serial_set(115200);
-
- register_console(&sercons);
-
- return 0;
-}
-
-console_initcall(gal_serial_console_init);
diff --git a/arch/mips/gt64120/ev64120/reset.c b/arch/mips/gt64120/ev64120/reset.c
deleted file mode 100644
index 7b9f5e5bf21..00000000000
--- a/arch/mips/gt64120/ev64120/reset.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1997 Ralf Baechle
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void galileo_machine_restart(char *command)
-{
- *(volatile char *) 0xbc000000 = 0x0f;
- /*
- * Ouch, we're still alive ... This time we take the silver bullet ...
- * ... and find that we leave the hardware in a state in which the
- * kernel in the flush locks up somewhen during of after the PCI
- * detection stuff.
- */
- set_c0_status(ST0_BEV | ST0_ERL);
- change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
- flush_cache_all();
- write_c0_wired(0);
- __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-}
-
-void galileo_machine_halt(void)
-{
- printk(KERN_NOTICE "You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-
-}
-
-void galileo_machine_power_off(void)
-{
- galileo_machine_halt();
-}
diff --git a/arch/mips/gt64120/ev64120/serialGT.c b/arch/mips/gt64120/ev64120/serialGT.c
deleted file mode 100644
index 8f0d835491f..00000000000
--- a/arch/mips/gt64120/ev64120/serialGT.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * serialGT.c
- *
- * BRIEF MODULE DESCRIPTION
- * Low Level Serial Port control for use
- * with the Galileo EVB64120A MIPS eval board and
- * its on board two channel 16552 Uart.
- *
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-// Note:
-// Serial CHANNELS - 0 is the bottom connector of evb64120A.
-// (The one that maps to the "B" channel of the
-// board's uart)
-// 1 is the top connector of evb64120A.
-// (The one that maps to the "A" channel of the
-// board's uart)
-int DEBUG_CHANNEL = 0; // See Note Above
-int CONSOLE_CHANNEL = 1; // See Note Above
-
-#define DUART 0xBD000000 /* Base address of Uart. */
-#define CHANNELOFFSET 0x20 /* DUART+CHANNELOFFSET gets you to the ChanA
- register set of the 16552 Uart device.
- DUART+0 gets you to the ChanB register set.
- */
-#define DUART_DELTA 0x4
-#define FIFO_ENABLE 0x07
-#define INT_ENABLE 0x04 /* default interrupt mask */
-
-#define RBR 0x00
-#define THR 0x00
-#define DLL 0x00
-#define IER 0x01
-#define DLM 0x01
-#define IIR 0x02
-#define FCR 0x02
-#define LCR 0x03
-#define MCR 0x04
-#define LSR 0x05
-#define MSR 0x06
-#define SCR 0x07
-
-#define LCR_DLAB 0x80
-#define XTAL 1843200
-#define LSR_THRE 0x20
-#define LSR_BI 0x10
-#define LSR_DR 0x01
-#define MCR_LOOP 0x10
-#define ACCESS_DELAY 0x10000
-
-/******************************
- Routine:
- Description:
- ******************************/
-int inreg(int channel, int reg)
-{
- int val;
- val =
- *((volatile unsigned char *) DUART +
- (channel * CHANNELOFFSET) + (reg * DUART_DELTA));
- return val;
-}
-
-/******************************
- Routine:
- Description:
- ******************************/
-void outreg(int channel, int reg, unsigned char val)
-{
- *((volatile unsigned char *) DUART + (channel * CHANNELOFFSET)
- + (reg * DUART_DELTA)) = val;
-}
-
-/******************************
- Routine:
- Description:
- Initialize the device driver.
- ******************************/
-void serial_init(int channel)
-{
- /*
- * Configure active port, (CHANNELOFFSET already set.)
- *
- * Set 8 bits, 1 stop bit, no parity.
- *
- * LCR<7> 0 divisor latch access bit
- * LCR<6> 0 break control (1=send break)
- * LCR<5> 0 stick parity (0=space, 1=mark)
- * LCR<4> 0 parity even (0=odd, 1=even)
- * LCR<3> 0 parity enable (1=enabled)
- * LCR<2> 0 # stop bits (0=1, 1=1.5)
- * LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8)
- */
- outreg(channel, LCR, 0x3);
-
- outreg(channel, FCR, FIFO_ENABLE); /* Enable the FIFO */
-
- outreg(channel, IER, INT_ENABLE); /* Enable appropriate interrupts */
-}
-
-/******************************
- Routine:
- Description:
- Set the baud rate.
- ******************************/
-void serial_set(int channel, unsigned long baud)
-{
- unsigned char sav_lcr;
-
- /*
- * Enable access to the divisor latches by setting DLAB in LCR.
- *
- */
- sav_lcr = inreg(channel, LCR);
-
-#if 0
- /*
- * Set baud rate
- */
- outreg(channel, LCR, LCR_DLAB | sav_lcr);
- // outreg(DLL,(XTAL/(16*2*(baud))-2));
- outreg(channel, DLL, XTAL / (16 * baud));
- // outreg(DLM,(XTAL/(16*2*(baud))-2)>>8);
- outreg(channel, DLM, (XTAL / (16 * baud)) >> 8);
-#else
- /*
- * Note: Set baud rate, hardcoded here for rate of 115200
- * since became unsure of above "baud rate" algorithm (??).
- */
- outreg(channel, LCR, 0x83);
- outreg(channel, DLM, 0x00); // See note above
- outreg(channel, DLL, 0x02); // See note above.
- outreg(channel, LCR, 0x03);
-#endif
-
- /*
- * Restore line control register
- */
- outreg(channel, LCR, sav_lcr);
-}
-
-
-/******************************
- Routine:
- Description:
- Transmit a character.
- ******************************/
-void serial_putc(int channel, int c)
-{
- while ((inreg(channel, LSR) & LSR_THRE) == 0);
- outreg(channel, THR, c);
-}
-
-/******************************
- Routine:
- Description:
- Read a received character if one is
- available. Return -1 otherwise.
- ******************************/
-int serial_getc(int channel)
-{
- if (inreg(channel, LSR) & LSR_DR) {
- return inreg(channel, RBR);
- }
- return -1;
-}
-
-/******************************
- Routine:
- Description:
- Used by embedded gdb client. (example; gdb-stub.c)
- ******************************/
-char getDebugChar()
-{
- int val;
- while ((val = serial_getc(DEBUG_CHANNEL)) == -1); // loop until we get a character in.
- return (char) val;
-}
-
-/******************************
- Routine:
- Description:
- Used by embedded gdb target. (example; gdb-stub.c)
- ******************************/
-void putDebugChar(char c)
-{
- serial_putc(DEBUG_CHANNEL, (int) c);
-}
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
deleted file mode 100644
index 477848c22a2..00000000000
--- a/arch/mips/gt64120/ev64120/setup.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/pm.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/time.h>
-#include <asm/reboot.h>
-#include <asm/traps.h>
-#include <linux/bootmem.h>
-
-unsigned long gt64120_base = KSEG1ADDR(0x14000000);
-
-/* These functions are used for rebooting or halting the machine*/
-extern void galileo_machine_restart(char *command);
-extern void galileo_machine_halt(void);
-extern void galileo_machine_power_off(void);
-/*
- *This structure holds pointers to the pci configuration space accesses
- *and interrupts allocating routine for device over the PCI
- */
-extern struct pci_ops galileo_pci_ops;
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-/*
- * Initializes basic routines and structures pointers, memory size (as
- * given by the bios and saves the command line.
- */
-
-void __init plat_mem_setup(void)
-{
- _machine_restart = galileo_machine_restart;
- _machine_halt = galileo_machine_halt;
- pm_power_off = galileo_machine_power_off;
-
- set_io_port_base(KSEG1);
-}
-
-const char *get_system_type(void)
-{
- return "Galileo EV64120A";
-}
-
-/*
- * Kernel arguments passed by the firmware
- *
- * $a0 - nothing
- * $a1 - holds a pointer to the eprom parameters
- * $a2 - nothing
- */
-
-void __init prom_init(void)
-{
- mips_machgroup = MACH_GROUP_GALILEO;
- mips_machtype = MACH_EV64120A;
-
- add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/gt64120/momenco_ocelot/Makefile b/arch/mips/gt64120/momenco_ocelot/Makefile
index 9f9a33fc76b..1df5fe23c64 100644
--- a/arch/mips/gt64120/momenco_ocelot/Makefile
+++ b/arch/mips/gt64120/momenco_ocelot/Makefile
@@ -2,6 +2,6 @@
# Makefile for Momentum's Ocelot board.
#
-obj-y += irq.o prom.o reset.o setup.o
+obj-y += irq.o ocelot-platform.o prom.o reset.o setup.o
obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c b/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c
new file mode 100644
index 00000000000..81d9031a5a2
--- /dev/null
+++ b/arch/mips/gt64120/momenco_ocelot/ocelot-platform.c
@@ -0,0 +1,46 @@
+/*
+ * 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) 2007 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * A NS16552 DUART with a 20MHz crystal.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define OCELOT_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+ {
+ .mapbase = 0xe0001020,
+ .irq = 4,
+ .uartclk = 20000000,
+ .iotype = UPIO_MEM,
+ .flags = OCELOT_UART_FLAGS,
+ .regshift = 2,
+ },
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Momenco Ocelot");
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
index 121188d5ec4..ea965529e5e 100644
--- a/arch/mips/gt64120/wrppmc/setup.c
+++ b/arch/mips/gt64120/wrppmc/setup.c
@@ -158,8 +158,8 @@ const char *get_system_type(void)
*/
void __init prom_init(void)
{
- mips_machgroup = MACH_GROUP_GALILEO;
- mips_machtype = MACH_EV64120A;
+ mips_machgroup = MACH_GROUP_WINDRIVER;
+ mips_machtype = MACH_WRPPMC;
add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM);
add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA);
diff --git a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile
index dd9d99bfcf7..ae4c402b500 100644
--- a/arch/mips/jazz/Makefile
+++ b/arch/mips/jazz/Makefile
@@ -2,4 +2,4 @@
# Makefile for the Jazz family specific parts of the kernel
#
-obj-y := irq.o jazzdma.o reset.o setup.o
+obj-y := irq.o jazzdma.o jazz-platform.o reset.o setup.o
diff --git a/arch/mips/jazz/jazz-platform.c b/arch/mips/jazz/jazz-platform.c
new file mode 100644
index 00000000000..fd736703eef
--- /dev/null
+++ b/arch/mips/jazz/jazz-platform.c
@@ -0,0 +1,60 @@
+/*
+ * 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) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/serial_8250.h>
+
+#include <asm/jazz.h>
+
+/*
+ * Confusion ... It seems the original Microsoft Jazz machine used to have a
+ * 4.096MHz clock for its UART while the MIPS Magnum and Millenium systems
+ * had 8MHz. The Olivetti M700-10 and the Acer PICA have 1.8432MHz like PCs.
+ */
+#ifdef CONFIG_OLIVETTI_M700
+#define JAZZ_BASE_BAUD 1843200
+#else
+#define JAZZ_BASE_BAUD 8000000 /* 3072000 */
+#endif
+
+#define JAZZ_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+#define JAZZ_PORT(base, int) \
+{ \
+ .mapbase = base, \
+ .irq = int, \
+ .uartclk = JAZZ_BASE_BAUD, \
+ .iotype = UPIO_MEM, \
+ .flags = JAZZ_UART_FLAGS, \
+ .regshift = 0, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ JAZZ_PORT(JAZZ_SERIAL1_BASE, JAZZ_SERIAL1_IRQ),
+ JAZZ_PORT(JAZZ_SERIAL2_BASE, JAZZ_SERIAL2_IRQ),
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Jazz family");
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index d848f1a0778..81ec559a1c2 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -54,7 +54,7 @@ static struct resource jazz_io_resources[] = {
.start = 0x40,
.end = 0x5f,
.name = "timer",
- .end = IORESOURCE_BUSY
+ .flags = IORESOURCE_BUSY
}, {
.start = 0x80,
.end = 0x8f,
diff --git a/arch/mips/jmr3927/rbhma3100/kgdb_io.c b/arch/mips/jmr3927/rbhma3100/kgdb_io.c
index 2604f2c9a96..342579cfdc0 100644
--- a/arch/mips/jmr3927/rbhma3100/kgdb_io.c
+++ b/arch/mips/jmr3927/rbhma3100/kgdb_io.c
@@ -36,7 +36,7 @@
#define TIMEOUT 0xffffff
static int remoteDebugInitialized = 0;
-static void debugInit(int baud)
+static void debugInit(int baud);
int putDebugChar(unsigned char c)
{
diff --git a/arch/mips/kernel/8250-platform.c b/arch/mips/kernel/8250-platform.c
new file mode 100644
index 00000000000..cbf3fe20ad1
--- /dev/null
+++ b/arch/mips/kernel/8250-platform.c
@@ -0,0 +1,47 @@
+/*
+ * 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) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define PORT(base, int) \
+{ \
+ .iobase = base, \
+ .irq = int, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
+ .regshift = 0, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ PORT(0x3F8, 4),
+ PORT(0x2F8, 3),
+ PORT(0x3E8, 4),
+ PORT(0x2E8, 3),
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic 8250 UART probe driver");
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 49246264cc7..5c8085b6d7a 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -14,14 +14,15 @@ binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-$(CONFIG_MODULES) += mips_ksyms.o module.o
+obj-$(CONFIG_CPU_LOONGSON2) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
-obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R8000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o
@@ -29,13 +30,14 @@ obj-$(CONFIG_CPU_RM9000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_NEVADA) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_R10000) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o
-obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o
+obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o
+obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_MIPS_MT) += mips-mt.o
+obj-$(CONFIG_MIPS_MT_FPAFF) += mips-mt-fpaff.o
obj-$(CONFIG_MIPS_MT_SMTC) += smtc.o smtc-asm.o smtc-proc.o
obj-$(CONFIG_MIPS_MT_SMP) += smp-mt.o
@@ -47,7 +49,6 @@ obj-$(CONFIG_I8259) += i8259.o
obj-$(CONFIG_IRQ_CPU) += irq_cpu.o
obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o
obj-$(CONFIG_IRQ_CPU_RM9K) += irq-rm9000.o
-obj-$(CONFIG_IRQ_MV64340) += irq-mv6434x.o
obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.o
obj-$(CONFIG_32BIT) += scall32-o32.o
@@ -62,9 +63,11 @@ obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_64BIT) += cpu-bugs64.o
-obj-$(CONFIG_I8253) += i8253.o
+obj-$(CONFIG_PCSPEAKER) += pcspeaker.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
+
+obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 76fd3f22c76..6b5df8bfab8 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -22,7 +22,8 @@
*/
int __compute_return_epc(struct pt_regs *regs)
{
- unsigned int *addr, bit, fcr31, dspcontrol;
+ unsigned int __user *addr;
+ unsigned int bit, fcr31, dspcontrol;
long epc;
union mips_instruction insn;
@@ -33,7 +34,7 @@ int __compute_return_epc(struct pt_regs *regs)
/*
* Read the instruction
*/
- addr = (unsigned int *) epc;
+ addr = (unsigned int __user *) epc;
if (__get_user(insn.word, addr)) {
force_sig(SIGSEGV, current);
return -EFAULT;
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index ab755ea26c6..c6b8b074a81 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -137,14 +137,24 @@ static inline void check_wait(void)
case CPU_4KEC:
case CPU_4KSC:
case CPU_5KC:
-/* case CPU_20KC:*/
- case CPU_24K:
case CPU_25KF:
+ case CPU_PR4450:
+ cpu_wait = r4k_wait;
+ break;
+
+ case CPU_24K:
case CPU_34K:
+ cpu_wait = r4k_wait;
+ if (read_c0_config7() & MIPS_CONF7_WII)
+ cpu_wait = r4k_wait_irqoff;
+ break;
+
case CPU_74K:
- case CPU_PR4450:
cpu_wait = r4k_wait;
+ if ((c->processor_id & 0xff) >= PRID_REV_ENCODE_332(2, 1, 0))
+ cpu_wait = r4k_wait_irqoff;
break;
+
case CPU_TX49XX:
cpu_wait = r4k_wait_irqoff;
break;
@@ -156,6 +166,17 @@ static inline void check_wait(void)
if (allow_au1k_wait)
cpu_wait = au1k_wait;
break;
+ case CPU_20KC:
+ /*
+ * WAIT on Rev1.0 has E1, E2, E3 and E16.
+ * WAIT on Rev2.0 and Rev3.0 has E16.
+ * Rev3.1 WAIT is nop, why bother
+ */
+ if ((c->processor_id & 0xff) <= 0x64)
+ break;
+
+ cpu_wait = r4k_wait;
+ break;
case CPU_RM9000:
if ((c->processor_id & 0x00ff) >= 0x40)
cpu_wait = r4k_wait;
@@ -165,9 +186,29 @@ static inline void check_wait(void)
}
}
+static inline void check_errata(void)
+{
+ struct cpuinfo_mips *c = &current_cpu_data;
+
+ switch (c->cputype) {
+ case CPU_34K:
+ /*
+ * Erratum "RPS May Cause Incorrect Instruction Execution"
+ * This code only handles VPE0, any SMP/SMTC/RTOS code
+ * making use of VPE1 will be responsable for that VPE.
+ */
+ if ((c->processor_id & PRID_REV_MASK) <= PRID_REV_34K_V1_0_2)
+ write_c0_config7(read_c0_config7() | MIPS_CONF7_RPS);
+ break;
+ default:
+ break;
+ }
+}
+
void __init check_bugs32(void)
{
check_wait();
+ check_errata();
}
/*
@@ -464,6 +505,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c)
MIPS_CPU_LLSC;
c->tlbsize = 64;
break;
+ case PRID_IMP_LOONGSON2:
+ c->cputype = CPU_LOONGSON2;
+ c->isa_level = MIPS_CPU_ISA_III;
+ c->options = R4K_OPTS |
+ MIPS_CPU_FPU | MIPS_CPU_LLSC |
+ MIPS_CPU_32FPR;
+ c->tlbsize = 64;
+ break;
}
}
@@ -567,6 +616,8 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
c->options |= MIPS_CPU_VEIC;
if (config3 & MIPS_CONF3_MT)
c->ases |= MIPS_ASE_MIPSMT;
+ if (config3 & MIPS_CONF3_ULRI)
+ c->options |= MIPS_CPU_ULRI;
return config3 & MIPS_CONF_M;
}
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 686249c5c32..e29598ae939 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -84,6 +84,7 @@ FEXPORT(restore_all) # restore full frame
LONG_S sp, TI_REGS($28)
jal deferred_smtc_ipi
LONG_S s0, TI_REGS($28)
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
/* Re-arm any temporarily masked interrupts not explicitly "acked" */
mfc0 v0, CP0_TCSTATUS
ori v1, v0, TCSTATUS_IXMT
@@ -110,6 +111,7 @@ FEXPORT(restore_all) # restore full frame
_ehb
xor t0, t0, t3
mtc0 t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
#endif /* CONFIG_MIPS_MT_SMTC */
.set noat
RESTORE_TEMP
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 297bd56c234..c0f19d638b9 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -243,9 +243,11 @@ NESTED(except_vec_vi_handler, 0, sp)
*/
mfc0 t1, CP0_STATUS
and t0, a0, t1
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
mfc0 t2, CP0_TCCONTEXT
or t0, t0, t2
mtc0 t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC_IM_BACKSTOP */
xor t1, t1, t0
mtc0 t1, CP0_STATUS
_ehb
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 6f57ca44291..f78538eceef 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/threads.h>
+#include <asm/addrspace.h>
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/irqflags.h>
@@ -129,24 +130,25 @@
#endif
.endm
+#ifndef CONFIG_NO_EXCEPT_FILL
/*
* Reserved space for exception handlers.
* Necessary for machines which link their kernels at KSEG0.
*/
.fill 0x400
+#endif
EXPORT(stext) # used for profiling
EXPORT(_stext)
-#ifdef CONFIG_MIPS_SIM
+#ifdef CONFIG_BOOT_RAW
/*
* Give us a fighting chance of running if execution beings at the
* kernel load address. This is needed because this platform does
* not have a ELF loader yet.
*/
- j kernel_entry
-#endif
__INIT
+#endif
NESTED(kernel_entry, 16, sp) # kernel entry point
@@ -197,9 +199,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
j start_kernel
END(kernel_entry)
-#ifdef CONFIG_QEMU
__INIT
-#endif
#ifdef CONFIG_SMP
/*
diff --git a/arch/mips/kernel/irq-mv6434x.c b/arch/mips/kernel/irq-mv6434x.c
deleted file mode 100644
index 3dd561832e4..00000000000
--- a/arch/mips/kernel/irq-mv6434x.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.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.
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/mv643xx.h>
-#include <linux/sched.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/marvell.h>
-
-static unsigned int irq_base;
-
-static inline int ls1bit32(unsigned int x)
-{
- int b = 31, s;
-
- s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
- s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
- s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
- s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
- s = 1; if (x << 1 == 0) s = 0; b -= s;
-
- return b;
-}
-
-/* mask off an interrupt -- 1 is enable, 0 is disable */
-static inline void mask_mv64340_irq(unsigned int irq)
-{
- uint32_t value;
-
- if (irq < (irq_base + 32)) {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- value &= ~(1 << (irq - irq_base));
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
- } else {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- value &= ~(1 << (irq - irq_base - 32));
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
- }
-}
-
-/* unmask an interrupt -- 1 is enable, 0 is disable */
-static inline void unmask_mv64340_irq(unsigned int irq)
-{
- uint32_t value;
-
- if (irq < (irq_base + 32)) {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- value |= 1 << (irq - irq_base);
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value);
- } else {
- value = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- value |= 1 << (irq - irq_base - 32);
- MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value);
- }
-}
-
-/*
- * Interrupt handler for interrupts coming from the Marvell chip.
- * It could be built in ethernet ports etc...
- */
-void ll_mv64340_irq(void)
-{
- unsigned int irq_src_low, irq_src_high;
- unsigned int irq_mask_low, irq_mask_high;
-
- /* read the interrupt status registers */
- irq_mask_low = MV_READ(MV64340_INTERRUPT0_MASK_0_LOW);
- irq_mask_high = MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH);
- irq_src_low = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW);
- irq_src_high = MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH);
-
- /* mask for just the interrupts we want */
- irq_src_low &= irq_mask_low;
- irq_src_high &= irq_mask_high;
-
- if (irq_src_low)
- do_IRQ(ls1bit32(irq_src_low) + irq_base);
- else
- do_IRQ(ls1bit32(irq_src_high) + irq_base + 32);
-}
-
-struct irq_chip mv64340_irq_type = {
- .name = "MV-64340",
- .ack = mask_mv64340_irq,
- .mask = mask_mv64340_irq,
- .mask_ack = mask_mv64340_irq,
- .unmask = unmask_mv64340_irq,
-};
-
-void __init mv64340_irq_init(unsigned int base)
-{
- int i;
-
- for (i = base; i < base + 64; i++)
- set_irq_chip_and_handler(i, &mv64340_irq_type,
- handle_level_irq);
-
- irq_base = base;
-}
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 37849edd064..06e04da211d 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -556,6 +556,16 @@ asmlinkage long sys32_sync_file_range(int fd, int __pad,
flags);
}
+asmlinkage long sys32_fadvise64_64(int fd, int __pad,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ int flags)
+{
+ return sys_fadvise64_64(fd,
+ merge_64(a2, a3), merge_64(a4, a5),
+ flags);
+}
+
save_static_function(sys32_clone);
__attribute_used__ noinline static int
_sys32_clone(nabi_no_regargs struct pt_regs regs)
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
new file mode 100644
index 00000000000..ede5d73d652
--- /dev/null
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -0,0 +1,176 @@
+/*
+ * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/security.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+
+/*
+ * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
+ */
+cpumask_t mt_fpu_cpumask;
+
+static int fpaff_threshold = -1;
+unsigned long mt_fpemul_threshold = 0;
+
+/*
+ * Replacement functions for the sys_sched_setaffinity() and
+ * sys_sched_getaffinity() system calls, so that we can integrate
+ * FPU affinity with the user's requested processor affinity.
+ * This code is 98% identical with the sys_sched_setaffinity()
+ * and sys_sched_getaffinity() system calls, and should be
+ * updated when kernel/sched.c changes.
+ */
+
+/*
+ * find_process_by_pid - find a process with a matching PID value.
+ * used in sys_sched_set/getaffinity() in kernel/sched.c, so
+ * cloned here.
+ */
+static inline struct task_struct *find_process_by_pid(pid_t pid)
+{
+ return pid ? find_task_by_pid(pid) : current;
+}
+
+
+/*
+ * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+ unsigned long __user *user_mask_ptr)
+{
+ cpumask_t new_mask;
+ cpumask_t effective_mask;
+ int retval;
+ struct task_struct *p;
+
+ if (len < sizeof(new_mask))
+ return -EINVAL;
+
+ if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+ return -EFAULT;
+
+ lock_cpu_hotplug();
+ read_lock(&tasklist_lock);
+
+ p = find_process_by_pid(pid);
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ unlock_cpu_hotplug();
+ return -ESRCH;
+ }
+
+ /*
+ * It is not safe to call set_cpus_allowed with the
+ * tasklist_lock held. We will bump the task_struct's
+ * usage count and drop tasklist_lock before invoking
+ * set_cpus_allowed.
+ */
+ get_task_struct(p);
+
+ retval = -EPERM;
+ if ((current->euid != p->euid) && (current->euid != p->uid) &&
+ !capable(CAP_SYS_NICE)) {
+ read_unlock(&tasklist_lock);
+ goto out_unlock;
+ }
+
+ retval = security_task_setscheduler(p, 0, NULL);
+ if (retval)
+ goto out_unlock;
+
+ /* Record new user-specified CPU set for future reference */
+ p->thread.user_cpus_allowed = new_mask;
+
+ /* Unlock the task list */
+ read_unlock(&tasklist_lock);
+
+ /* Compute new global allowed CPU set if necessary */
+ if ((p->thread.mflags & MF_FPUBOUND)
+ && cpus_intersects(new_mask, mt_fpu_cpumask)) {
+ cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
+ retval = set_cpus_allowed(p, effective_mask);
+ } else {
+ p->thread.mflags &= ~MF_FPUBOUND;
+ retval = set_cpus_allowed(p, new_mask);
+ }
+
+
+out_unlock:
+ put_task_struct(p);
+ unlock_cpu_hotplug();
+ return retval;
+}
+
+/*
+ * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
+ unsigned long __user *user_mask_ptr)
+{
+ unsigned int real_len;
+ cpumask_t mask;
+ int retval;
+ struct task_struct *p;
+
+ real_len = sizeof(mask);
+ if (len < real_len)
+ return -EINVAL;
+
+ lock_cpu_hotplug();
+ read_lock(&tasklist_lock);
+
+ retval = -ESRCH;
+ p = find_process_by_pid(pid);
+ if (!p)
+ goto out_unlock;
+ retval = security_task_getscheduler(p);
+ if (retval)
+ goto out_unlock;
+
+ cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+
+out_unlock:
+ read_unlock(&tasklist_lock);
+ unlock_cpu_hotplug();
+ if (retval)
+ return retval;
+ if (copy_to_user(user_mask_ptr, &mask, real_len))
+ return -EFAULT;
+ return real_len;
+}
+
+
+static int __init fpaff_thresh(char *str)
+{
+ get_option(&str, &fpaff_threshold);
+ return 1;
+}
+__setup("fpaff=", fpaff_thresh);
+
+/*
+ * FPU Use Factor empirically derived from experiments on 34K
+ */
+#define FPUSEFACTOR 333
+
+static __init int mt_fp_affinity_init(void)
+{
+ if (fpaff_threshold >= 0) {
+ mt_fpemul_threshold = fpaff_threshold;
+ } else {
+ mt_fpemul_threshold =
+ (FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
+ }
+ printk(KERN_DEBUG "FPU Affinity set after %ld emulations\n",
+ mt_fpemul_threshold);
+
+ return 0;
+}
+arch_initcall(mt_fp_affinity_init);
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
index ba01800b601..1a7d8923129 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -6,7 +6,6 @@
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/sched.h>
-#include <linux/cpumask.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/security.h>
@@ -23,149 +22,6 @@
#include <asm/cacheflush.h>
/*
- * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
- */
-
-cpumask_t mt_fpu_cpumask;
-
-#ifdef CONFIG_MIPS_MT_FPAFF
-
-#include <linux/cpu.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-
-unsigned long mt_fpemul_threshold = 0;
-
-/*
- * Replacement functions for the sys_sched_setaffinity() and
- * sys_sched_getaffinity() system calls, so that we can integrate
- * FPU affinity with the user's requested processor affinity.
- * This code is 98% identical with the sys_sched_setaffinity()
- * and sys_sched_getaffinity() system calls, and should be
- * updated when kernel/sched.c changes.
- */
-
-/*
- * find_process_by_pid - find a process with a matching PID value.
- * used in sys_sched_set/getaffinity() in kernel/sched.c, so
- * cloned here.
- */
-static inline struct task_struct *find_process_by_pid(pid_t pid)
-{
- return pid ? find_task_by_pid(pid) : current;
-}
-
-
-/*
- * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
- */
-asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
- unsigned long __user *user_mask_ptr)
-{
- cpumask_t new_mask;
- cpumask_t effective_mask;
- int retval;
- struct task_struct *p;
-
- if (len < sizeof(new_mask))
- return -EINVAL;
-
- if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
- return -EFAULT;
-
- lock_cpu_hotplug();
- read_lock(&tasklist_lock);
-
- p = find_process_by_pid(pid);
- if (!p) {
- read_unlock(&tasklist_lock);
- unlock_cpu_hotplug();
- return -ESRCH;
- }
-
- /*
- * It is not safe to call set_cpus_allowed with the
- * tasklist_lock held. We will bump the task_struct's
- * usage count and drop tasklist_lock before invoking
- * set_cpus_allowed.
- */
- get_task_struct(p);
-
- retval = -EPERM;
- if ((current->euid != p->euid) && (current->euid != p->uid) &&
- !capable(CAP_SYS_NICE)) {
- read_unlock(&tasklist_lock);
- goto out_unlock;
- }
-
- retval = security_task_setscheduler(p, 0, NULL);
- if (retval)
- goto out_unlock;
-
- /* Record new user-specified CPU set for future reference */
- p->thread.user_cpus_allowed = new_mask;
-
- /* Unlock the task list */
- read_unlock(&tasklist_lock);
-
- /* Compute new global allowed CPU set if necessary */
- if( (p->thread.mflags & MF_FPUBOUND)
- && cpus_intersects(new_mask, mt_fpu_cpumask)) {
- cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
- retval = set_cpus_allowed(p, effective_mask);
- } else {
- p->thread.mflags &= ~MF_FPUBOUND;
- retval = set_cpus_allowed(p, new_mask);
- }
-
-
-out_unlock:
- put_task_struct(p);
- unlock_cpu_hotplug();
- return retval;
-}
-
-/*
- * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
- */
-asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
- unsigned long __user *user_mask_ptr)
-{
- unsigned int real_len;
- cpumask_t mask;
- int retval;
- struct task_struct *p;
-
- real_len = sizeof(mask);
- if (len < real_len)
- return -EINVAL;
-
- lock_cpu_hotplug();
- read_lock(&tasklist_lock);
-
- retval = -ESRCH;
- p = find_process_by_pid(pid);
- if (!p)
- goto out_unlock;
- retval = security_task_getscheduler(p);
- if (retval)
- goto out_unlock;
-
- cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
-
-out_unlock:
- read_unlock(&tasklist_lock);
- unlock_cpu_hotplug();
- if (retval)
- return retval;
- if (copy_to_user(user_mask_ptr, &mask, real_len))
- return -EFAULT;
- return real_len;
-}
-
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
-/*
* Dump new MIPS MT state for the core. Does not leave TCs halted.
* Takes an argument which taken to be a pre-call MVPControl value.
*/
@@ -195,27 +51,31 @@ void mips_mt_regdump(unsigned long mvpctl)
nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
printk("-- per-VPE State --\n");
- for(i = 0; i < nvpe; i++) {
- for(tc = 0; tc < ntc; tc++) {
+ for (i = 0; i < nvpe; i++) {
+ for (tc = 0; tc < ntc; tc++) {
settc(tc);
- if((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
- printk(" VPE %d\n", i);
- printk(" VPEControl : %08lx\n", read_vpe_c0_vpecontrol());
- printk(" VPEConf0 : %08lx\n", read_vpe_c0_vpeconf0());
- printk(" VPE%d.Status : %08lx\n",
- i, read_vpe_c0_status());
- printk(" VPE%d.EPC : %08lx\n", i, read_vpe_c0_epc());
- printk(" VPE%d.Cause : %08lx\n", i, read_vpe_c0_cause());
- printk(" VPE%d.Config7 : %08lx\n",
- i, read_vpe_c0_config7());
- break; /* Next VPE */
+ if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
+ printk(" VPE %d\n", i);
+ printk(" VPEControl : %08lx\n",
+ read_vpe_c0_vpecontrol());
+ printk(" VPEConf0 : %08lx\n",
+ read_vpe_c0_vpeconf0());
+ printk(" VPE%d.Status : %08lx\n",
+ i, read_vpe_c0_status());
+ printk(" VPE%d.EPC : %08lx\n",
+ i, read_vpe_c0_epc());
+ printk(" VPE%d.Cause : %08lx\n",
+ i, read_vpe_c0_cause());
+ printk(" VPE%d.Config7 : %08lx\n",
+ i, read_vpe_c0_config7());
+ break; /* Next VPE */
+ }
}
- }
}
printk("-- per-TC State --\n");
- for(tc = 0; tc < ntc; tc++) {
+ for (tc = 0; tc < ntc; tc++) {
settc(tc);
- if(read_tc_c0_tcbind() == read_c0_tcbind()) {
+ if (read_tc_c0_tcbind() == read_c0_tcbind()) {
/* Are we dumping ourself? */
haltval = 0; /* Then we're not halted, and mustn't be */
tcstatval = flags; /* And pre-dump TCStatus is flags */
@@ -310,17 +170,6 @@ static int __init ndflush(char *s)
return 1;
}
__setup("ndflush=", ndflush);
-#ifdef CONFIG_MIPS_MT_FPAFF
-static int fpaff_threshold = -1;
-
-static int __init fpaff_thresh(char *str)
-{
- get_option(&str, &fpaff_threshold);
- return 1;
-}
-
-__setup("fpaff=", fpaff_thresh);
-#endif /* CONFIG_MIPS_MT_FPAFF */
static unsigned int itc_base = 0;
@@ -376,20 +225,6 @@ void mips_mt_set_cpuoptions(void)
if (mt_n_dflushes != 1)
printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes);
-#ifdef CONFIG_MIPS_MT_FPAFF
- /* FPU Use Factor empirically derived from experiments on 34K */
-#define FPUSEFACTOR 333
-
- if (fpaff_threshold >= 0) {
- mt_fpemul_threshold = fpaff_threshold;
- } else {
- mt_fpemul_threshold =
- (FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
- }
- printk("FPU Affinity set after %ld emulations\n",
- mt_fpemul_threshold);
-#endif /* CONFIG_MIPS_MT_FPAFF */
-
if (itc_base != 0) {
/*
* Configure ITC mapping. This code is very
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/pcspeaker.c
index 475df690421..475df690421 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/pcspeaker.c
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 5ddc2e9deec..ec04f5a1a5e 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -14,7 +14,6 @@
#include <asm/cpu-features.h>
#include <asm/mipsregs.h>
#include <asm/processor.h>
-#include <asm/watch.h>
unsigned int vced_count, vcei_count;
@@ -84,6 +83,7 @@ static const char *cpu_name[] = {
[CPU_VR4181A] = "NEC VR4181A",
[CPU_SR71000] = "Sandcraft SR71000",
[CPU_PR4450] = "Philips PR4450",
+ [CPU_LOONGSON2] = "ICT Loongson-2",
};
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 6bdfb5a9fa1..8f4cf27c715 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -46,7 +46,7 @@
* power and have a low exit latency (ie sit in a loop waiting for somebody to
* say that they'd like to reschedule)
*/
-ATTRIB_NORET void cpu_idle(void)
+void __noreturn cpu_idle(void)
{
/* endless idle loop with no priority at all */
while (1) {
@@ -213,7 +213,7 @@ int dump_task_fpu (struct task_struct *t, elf_fpregset_t *fpr)
/*
* Create a kernel thread
*/
-static ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
+static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))
{
do_exit(fn(arg));
}
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index cc566cf1224..d9bfae53c43 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -85,12 +85,7 @@
move $28, a2
cpu_restore_nonscratch a1
-#if (_THREAD_SIZE - 32) < 0x10000
- PTR_ADDIU t0, $28, _THREAD_SIZE - 32
-#else
- PTR_LI t0, _THREAD_SIZE - 32
- PTR_ADDU t0, $28
-#endif
+ PTR_ADDU t0, $28, _THREAD_SIZE - 32
set_saved_sp t0, t1, t2
#ifdef CONFIG_MIPS_MT_SMTC
/* Read-modify-writes of Status must be atomic on a VPE */
@@ -174,7 +169,7 @@ LEAF(_init_fpu)
or t0, t1
mtc0 t0, CP0_STATUS
#endif /* CONFIG_MIPS_MT_SMTC */
- fpu_enable_hazard
+ enable_fpu_hazard
li t1, FPU_DEFAULT
ctc1 t1, fcr31
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 0c9a9ff8cd2..ae985d1fcca 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -657,7 +657,11 @@ einval: li v0, -EINVAL
sys sys_getcpu 3
sys sys_epoll_pwait 6
sys sys_ioprio_set 3
- sys sys_ioprio_get 2
+ sys sys_ioprio_get 2 /* 4315 */
+ sys sys_utimensat 4
+ sys sys_signalfd 3
+ sys sys_timerfd 4
+ sys sys_eventfd 1
.endm
/* We pre-compute the number of _instruction_ bytes needed to
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 23f3b118f71..7bcd5a1a85f 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -473,4 +473,8 @@ sys_call_table:
PTR sys_epoll_pwait
PTR sys_ioprio_set
PTR sys_ioprio_get
+ PTR sys_utimensat /* 5275 */
+ PTR sys_signalfd
+ PTR sys_timerfd
+ PTR sys_eventfd
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 6eac2833742..532a2f3b42f 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -299,7 +299,7 @@ EXPORT(sysn32_call_table)
PTR sys_ni_syscall /* res. for afs_syscall */
PTR sys_ni_syscall /* res. for security */
PTR sys_gettid
- PTR sys32_readahead
+ PTR sys_readahead
PTR sys_setxattr /* 6180 */
PTR sys_lsetxattr
PTR sys_fsetxattr
@@ -399,4 +399,8 @@ EXPORT(sysn32_call_table)
PTR compat_sys_epoll_pwait
PTR sys_ioprio_set
PTR sys_ioprio_get
+ PTR compat_sys_utimensat
+ PTR compat_sys_signalfd /* 5280 */
+ PTR compat_sys_timerfd
+ PTR sys_eventfd
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 7e74b412a78..6bbe0f4ed8b 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -459,7 +459,7 @@ sys_call_table:
PTR sys_remap_file_pages
PTR sys_set_tid_address
PTR sys_restart_syscall
- PTR sys_fadvise64_64
+ PTR sys32_fadvise64_64
PTR compat_sys_statfs64 /* 4255 */
PTR compat_sys_fstatfs64
PTR compat_sys_timer_create
@@ -521,4 +521,8 @@ sys_call_table:
PTR compat_sys_epoll_pwait
PTR sys_ioprio_set
PTR sys_ioprio_get /* 4315 */
+ PTR compat_sys_utimensat
+ PTR compat_sys_signalfd
+ PTR compat_sys_timerfd
+ PTR sys_eventfd
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 4975da0bfb6..316685fca05 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -20,6 +20,7 @@
#include <linux/highmem.h>
#include <linux/console.h>
#include <linux/pfn.h>
+#include <linux/debugfs.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
@@ -574,3 +575,18 @@ __setup("nodsp", dsp_disable);
unsigned long kernelsp[NR_CPUS];
unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *mips_debugfs_dir;
+static int __init debugfs_mips(void)
+{
+ struct dentry *d;
+
+ d = debugfs_create_dir("mips", NULL);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ mips_debugfs_dir = d;
+ return 0;
+}
+arch_initcall(debugfs_mips);
+#endif
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 003f8152b9e..486b8e5f52d 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -36,68 +36,6 @@
#include "signal-common.h"
-#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
-
-typedef struct compat_siginfo {
- int si_signo;
- int si_code;
- int si_errno;
-
- union {
- int _pad[SI_PAD_SIZE32];
-
- /* kill() */
- struct {
- compat_pid_t _pid; /* sender's pid */
- compat_uid_t _uid; /* sender's uid */
- } _kill;
-
- /* SIGCHLD */
- struct {
- compat_pid_t _pid; /* which child */
- compat_uid_t _uid; /* sender's uid */
- int _status; /* exit code */
- compat_clock_t _utime;
- compat_clock_t _stime;
- } _sigchld;
-
- /* IRIX SIGCHLD */
- struct {
- compat_pid_t _pid; /* which child */
- compat_clock_t _utime;
- int _status; /* exit code */
- compat_clock_t _stime;
- } _irix_sigchld;
-
- /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
- struct {
- s32 _addr; /* faulting insn/memory ref. */
- } _sigfault;
-
- /* SIGPOLL, SIGXFSZ (To do ...) */
- struct {
- int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
- int _fd;
- } _sigpoll;
-
- /* POSIX.1b timers */
- struct {
- timer_t _tid; /* timer id */
- int _overrun; /* overrun count */
- compat_sigval_t _sigval;/* same as below */
- int _sys_private; /* not to be passed to user */
- } _timer;
-
- /* POSIX.1b signals */
- struct {
- compat_pid_t _pid; /* sender's pid */
- compat_uid_t _uid; /* sender's uid */
- compat_sigval_t _sigval;
- } _rt;
-
- } _sifields;
-} compat_siginfo_t;
-
/*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 4cf9ff24d1f..eb7e05926eb 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -72,7 +72,7 @@ struct ucontextn32 {
struct rt_sigframe_n32 {
u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_code[2]; /* signal trampoline */
- struct siginfo rs_info;
+ struct compat_siginfo rs_info;
struct ucontextn32 rs_uc;
};
@@ -81,7 +81,7 @@ struct rt_sigframe_n32 {
struct rt_sigframe_n32 {
u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_pad[2];
- struct siginfo rs_info;
+ struct compat_siginfo rs_info;
struct ucontextn32 rs_uc;
u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
};
@@ -187,7 +187,7 @@ static int setup_rt_frame_n32(struct k_sigaction * ka,
install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
/* Create siginfo. */
- err |= copy_siginfo_to_user(&frame->rs_info, info);
+ err |= copy_siginfo_to_user32(&frame->rs_info, info);
/* Create the ucontext. */
err |= __put_user(0, &frame->rs_uc.uc_flags);
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 64b62bdfb4f..19b30d6f172 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -129,13 +129,13 @@ static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
static struct irqaction irq_resched = {
.handler = ipi_resched_interrupt,
- .flags = IRQF_DISABLED,
+ .flags = IRQF_DISABLED|IRQF_PERCPU,
.name = "IPI_resched"
};
static struct irqaction irq_call = {
.handler = ipi_call_interrupt,
- .flags = IRQF_DISABLED,
+ .flags = IRQF_DISABLED|IRQF_PERCPU,
.name = "IPI_call"
};
@@ -236,8 +236,6 @@ void __init plat_smp_setup(void)
dvpe();
dmt();
- mips_mt_set_cpuoptions();
-
/* Put MVPE's into 'configuration state' */
set_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -263,6 +261,8 @@ void __init plat_smp_setup(void)
void __init plat_prepare_cpus(unsigned int max_cpus)
{
+ mips_mt_set_cpuoptions();
+
/* set up ipi interrupts */
if (cpu_has_vint) {
set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
@@ -275,10 +275,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
setup_irq(cpu_ipi_resched_irq, &irq_resched);
setup_irq(cpu_ipi_call_irq, &irq_call);
- /* need to mark IPI's as IRQ_PER_CPU */
- irq_desc[cpu_ipi_resched_irq].status |= IRQ_PER_CPU;
set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq);
- irq_desc[cpu_ipi_call_irq].status |= IRQ_PER_CPU;
set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq);
}
@@ -326,8 +323,11 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
void prom_init_secondary(void)
{
+ /* Enable per-cpu interrupts */
+
+ /* This is Malta specific: IPI,performance and timer inetrrupts */
write_c0_status((read_c0_status() & ~ST0_IM ) |
- (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7));
+ (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7));
}
void prom_smp_finish(void)
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index c46e479c992..be7362bc2c9 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -51,24 +51,14 @@ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
EXPORT_SYMBOL(phys_cpu_present_map);
EXPORT_SYMBOL(cpu_online_map);
-/* This happens early in bootup, can't really do it better */
-static void smp_tune_scheduling (void)
-{
- struct cache_desc *cd = &current_cpu_data.scache;
- unsigned long cachesize = cd->linesz * cd->sets * cd->ways;
-
- if (cachesize > max_cache_size)
- max_cache_size = cachesize;
-}
-
extern void __init calibrate_delay(void);
-extern ATTRIB_NORET void cpu_idle(void);
+extern void cpu_idle(void);
/*
* First C code run on the secondary CPUs after being started up by
* the master.
*/
-asmlinkage void start_secondary(void)
+asmlinkage __cpuinit void start_secondary(void)
{
unsigned int cpu;
@@ -228,7 +218,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
{
init_new_context(current, &init_mm);
current_thread_info()->cpu = 0;
- smp_tune_scheduling();
plat_prepare_cpus(max_cpus);
#ifndef CONFIG_HOTPLUG_CPU
cpu_present_map = cpu_possible_map;
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
index 921207c4a83..20938a4cb52 100644
--- a/arch/mips/kernel/smtc-asm.S
+++ b/arch/mips/kernel/smtc-asm.S
@@ -121,10 +121,7 @@ LEAF(self_ipi)
subu t1,sp,PT_SIZE
sw ra,PT_EPC(t1)
sw a0,PT_PADSLOT4(t1)
- LONG_L s0, TI_REGS($28)
- LONG_S sp, TI_REGS($28)
la t2,ipi_decode
- LONG_S s0, TI_REGS($28)
sw t2,PT_PADSLOT5(t1)
/* Save pre-disable value of TCStatus */
sw t0,PT_TCSTATUS(t1)
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index b361edb83dc..342d873b2ec 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -13,9 +13,9 @@
#include <asm/system.h>
#include <asm/hardirq.h>
#include <asm/hazards.h>
+#include <asm/irq.h>
#include <asm/mmu_context.h>
#include <asm/smp.h>
-#include <asm/mips-boards/maltaint.h>
#include <asm/mipsregs.h>
#include <asm/cacheflush.h>
#include <asm/time.h>
@@ -611,12 +611,12 @@ void smtc_cpus_done(void)
int setup_irq_smtc(unsigned int irq, struct irqaction * new,
unsigned long hwmask)
{
+#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
unsigned int vpe = current_cpu_data.vpe_id;
- irq_hwmask[irq] = hwmask;
-#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
- vpemask[vpe][irq - MIPSCPU_INT_BASE] = 1;
+ vpemask[vpe][irq - MIPS_CPU_IRQ_BASE] = 1;
#endif
+ irq_hwmask[irq] = hwmask;
return setup_irq(irq, new);
}
@@ -822,7 +822,7 @@ void ipi_decode(struct smtc_ipi *pipi)
switch (type_copy) {
case SMTC_CLOCK_TICK:
irq_enter();
- kstat_this_cpu.irqs[MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR]++;
+ kstat_this_cpu.irqs[MIPS_CPU_IRQ_BASE + cp0_compare_irq]++;
/* Invoke Clock "Interrupt" */
ipi_timer_latch[dest_copy] = 0;
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
@@ -1104,7 +1104,7 @@ void smtc_idle_loop_hook(void)
mtflags = dmt();
pdb_msg = &id_ho_db_msg[0];
im = read_c0_status();
- vpe = cpu_data[smp_processor_id()].vpe_id;
+ vpe = current_cpu_data.vpe_id;
for (bit = 0; bit < 8; bit++) {
/*
* In current prototype, I/O interrupts
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 9dd5a2df8ea..b947c61c0cc 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -272,9 +272,8 @@ asmlinkage int sys_set_thread_area(unsigned long addr)
struct thread_info *ti = task_thread_info(current);
ti->tp_value = addr;
-
- /* If some future MIPS implementation has this register in hardware,
- * we will need to update it here (and in context switches). */
+ if (cpu_has_userlocal)
+ write_c0_userlocal(addr);
return 0;
}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 751b4a18b13..d48d1d5bea0 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -199,6 +199,35 @@ int (*perf_irq)(void) = null_perf_irq;
EXPORT_SYMBOL(null_perf_irq);
EXPORT_SYMBOL(perf_irq);
+/*
+ * Timer interrupt
+ */
+int cp0_compare_irq;
+
+/*
+ * Performance counter IRQ or -1 if shared with timer
+ */
+int cp0_perfcount_irq;
+EXPORT_SYMBOL_GPL(cp0_perfcount_irq);
+
+/*
+ * Possibly handle a performance counter interrupt.
+ * Return true if the timer interrupt should not be checked
+ */
+static inline int handle_perf_irq (int r2)
+{
+ /*
+ * The performance counter overflow interrupt may be shared with the
+ * timer interrupt (cp0_perfcount_irq < 0). If it is and a
+ * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
+ * and we can't reliably determine if a counter interrupt has also
+ * happened (!r2) then don't check for a timer interrupt.
+ */
+ return (cp0_perfcount_irq < 0) &&
+ perf_irq() == IRQ_HANDLED &&
+ !r2;
+}
+
asmlinkage void ll_timer_interrupt(int irq)
{
int r2 = cpu_has_mips_r2;
@@ -206,19 +235,13 @@ asmlinkage void ll_timer_interrupt(int irq)
irq_enter();
kstat_this_cpu.irqs[irq]++;
- /*
- * Suckage alert:
- * Before R2 of the architecture there was no way to see if a
- * performance counter interrupt was pending, so we have to run the
- * performance counter interrupt handler anyway.
- */
- if (!r2 || (read_c0_cause() & (1 << 26)))
- if (perf_irq())
- goto out;
+ if (handle_perf_irq(r2))
+ goto out;
- /* we keep interrupt disabled all the time */
- if (!r2 || (read_c0_cause() & (1 << 30)))
- timer_interrupt(irq, NULL);
+ if (r2 && ((read_c0_cause() & (1 << 30)) == 0))
+ goto out;
+
+ timer_interrupt(irq, NULL);
out:
irq_exit();
@@ -258,7 +281,7 @@ unsigned int mips_hpt_frequency;
static struct irqaction timer_irqaction = {
.handler = timer_interrupt,
- .flags = IRQF_DISABLED,
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
.name = "timer",
};
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 200de027f35..37c562c4c81 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -11,6 +11,7 @@
* Copyright (C) 2000, 01 MIPS Technologies, Inc.
* Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki
*/
+#include <linux/bug.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
@@ -38,7 +39,6 @@
#include <asm/traps.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
-#include <asm/watch.h>
#include <asm/types.h>
#include <asm/stacktrace.h>
@@ -69,6 +69,7 @@ extern asmlinkage void handle_reserved(void);
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx, int has_fpu);
+void (*board_watchpoint_handler)(struct pt_regs *regs);
void (*board_be_init)(void);
int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
void (*board_nmi_handler_setup)(void);
@@ -130,7 +131,7 @@ static void show_stacktrace(struct task_struct *task, struct pt_regs *regs)
const int field = 2 * sizeof(unsigned long);
long stackdata;
int i;
- unsigned long *sp = (unsigned long *)regs->regs[29];
+ unsigned long __user *sp = (unsigned long __user *)regs->regs[29];
printk("Stack :");
i = 0;
@@ -186,7 +187,7 @@ void dump_stack(void)
EXPORT_SYMBOL(dump_stack);
-void show_code(unsigned int *pc)
+static void show_code(unsigned int __user *pc)
{
long i;
@@ -304,13 +305,13 @@ void show_registers(struct pt_regs *regs)
printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
current->comm, current->pid, current_thread_info(), current);
show_stacktrace(current, regs);
- show_code((unsigned int *) regs->cp0_epc);
+ show_code((unsigned int __user *) regs->cp0_epc);
printk("\n");
}
static DEFINE_SPINLOCK(die_lock);
-NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
+void __noreturn die(const char * str, struct pt_regs * regs)
{
static int die_counter;
#ifdef CONFIG_MIPS_MT_SMTC
@@ -372,7 +373,7 @@ asmlinkage void do_be(struct pt_regs *regs)
action = MIPS_BE_FIXUP;
if (board_be_handler)
- action = board_be_handler(regs, fixup != 0);
+ action = board_be_handler(regs, fixup != NULL);
switch (action) {
case MIPS_BE_DISCARD:
@@ -752,6 +753,33 @@ asmlinkage void do_ri(struct pt_regs *regs)
force_sig(SIGILL, current);
}
+/*
+ * MIPS MT processors may have fewer FPU contexts than CPU threads. If we've
+ * emulated more than some threshold number of instructions, force migration to
+ * a "CPU" that has FP support.
+ */
+static void mt_ase_fp_affinity(void)
+{
+#ifdef CONFIG_MIPS_MT_FPAFF
+ if (mt_fpemul_threshold > 0 &&
+ ((current->thread.emulated_fp++ > mt_fpemul_threshold))) {
+ /*
+ * If there's no FPU present, or if the application has already
+ * restricted the allowed set to exclude any CPUs with FPUs,
+ * we'll skip the procedure.
+ */
+ if (cpus_intersects(current->cpus_allowed, mt_fpu_cpumask)) {
+ cpumask_t tmask;
+
+ cpus_and(tmask, current->thread.user_cpus_allowed,
+ mt_fpu_cpumask);
+ set_cpus_allowed(current, tmask);
+ current->thread.mflags |= MF_FPUBOUND;
+ }
+ }
+#endif /* CONFIG_MIPS_MT_FPAFF */
+}
+
asmlinkage void do_cpu(struct pt_regs *regs)
{
unsigned int cpid;
@@ -785,36 +813,8 @@ asmlinkage void do_cpu(struct pt_regs *regs)
&current->thread.fpu, 0);
if (sig)
force_sig(sig, current);
-#ifdef CONFIG_MIPS_MT_FPAFF
- else {
- /*
- * MIPS MT processors may have fewer FPU contexts
- * than CPU threads. If we've emulated more than
- * some threshold number of instructions, force
- * migration to a "CPU" that has FP support.
- */
- if(mt_fpemul_threshold > 0
- && ((current->thread.emulated_fp++
- > mt_fpemul_threshold))) {
- /*
- * If there's no FPU present, or if the
- * application has already restricted
- * the allowed set to exclude any CPUs
- * with FPUs, we'll skip the procedure.
- */
- if (cpus_intersects(current->cpus_allowed,
- mt_fpu_cpumask)) {
- cpumask_t tmask;
-
- cpus_and(tmask,
- current->thread.user_cpus_allowed,
- mt_fpu_cpumask);
- set_cpus_allowed(current, tmask);
- current->thread.mflags |= MF_FPUBOUND;
- }
- }
- }
-#endif /* CONFIG_MIPS_MT_FPAFF */
+ else
+ mt_ase_fp_affinity();
}
return;
@@ -834,6 +834,11 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
asmlinkage void do_watch(struct pt_regs *regs)
{
+ if (board_watchpoint_handler) {
+ (*board_watchpoint_handler)(regs);
+ return;
+ }
+
/*
* We use the watch exception where available to detect stack
* overflows.
@@ -860,7 +865,7 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
dump_tlb_all();
}
- show_code((unsigned int *) regs->cp0_epc);
+ show_code((unsigned int __user *) regs->cp0_epc);
/*
* Some chips may have other causes of machine check (e.g. SB1
@@ -927,12 +932,6 @@ asmlinkage void do_reserved(struct pt_regs *regs)
(regs->cp0_cause & 0x7f) >> 2);
}
-static asmlinkage void do_default_vi(void)
-{
- show_regs(get_irq_regs());
- panic("Caught unexpected vectored interrupt.");
-}
-
/*
* Some MIPS CPUs can enable/disable for cache parity detection, but do
* it different ways.
@@ -1128,6 +1127,12 @@ void mips_srs_free(int set)
clear_bit(set, &sr->sr_allocated);
}
+static asmlinkage void do_default_vi(void)
+{
+ show_regs(get_irq_regs());
+ panic("Caught unexpected vectored interrupt.");
+}
+
static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
{
unsigned long handler;
@@ -1190,8 +1195,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
memcpy (b, &except_vec_vi, handler_len);
#ifdef CONFIG_MIPS_MT_SMTC
- if (n > 7)
- printk("Vector index %d exceeds SMTC maximum\n", n);
+ BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
+
w = (u32 *)(b + mori_offset);
*w = (*w & 0xffff0000) | (0x100 << n);
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -1342,16 +1347,20 @@ void __init per_cpu_trap_init(void)
set_c0_status(ST0_MX);
#ifdef CONFIG_CPU_MIPSR2
- write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
+ if (cpu_has_mips_r2) {
+ unsigned int enable = 0x0000000f;
+
+ if (cpu_has_userlocal)
+ enable |= (1 << 29);
+
+ write_c0_hwrena(enable);
+ }
#endif
#ifdef CONFIG_MIPS_MT_SMTC
if (!secondaryTC) {
#endif /* CONFIG_MIPS_MT_SMTC */
- /*
- * Interrupt handling.
- */
if (cpu_has_veic || cpu_has_vint) {
write_c0_ebase (ebase);
/* Setting vector spacing enables EI/VI mode */
@@ -1365,6 +1374,23 @@ void __init per_cpu_trap_init(void)
} else
set_c0_cause(CAUSEF_IV);
}
+
+ /*
+ * Before R2 both interrupt numbers were fixed to 7, so on R2 only:
+ *
+ * o read IntCtl.IPTI to determine the timer interrupt
+ * o read IntCtl.IPPCI to determine the performance counter interrupt
+ */
+ if (cpu_has_mips_r2) {
+ cp0_compare_irq = (read_c0_intctl () >> 29) & 7;
+ cp0_perfcount_irq = (read_c0_intctl () >> 26) & 7;
+ if (cp0_perfcount_irq == cp0_compare_irq)
+ cp0_perfcount_irq = -1;
+ } else {
+ cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
+ cp0_perfcount_irq = -1;
+ }
+
#ifdef CONFIG_MIPS_MT_SMTC
}
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -1383,6 +1409,13 @@ void __init per_cpu_trap_init(void)
cpu_cache_init();
tlb_init();
#ifdef CONFIG_MIPS_MT_SMTC
+ } else if (!secondaryTC) {
+ /*
+ * First TC in non-boot VPE must do subset of tlb_init()
+ * for MMU countrol registers.
+ */
+ write_c0_pagemask(PM_DEFAULT_MASK);
+ write_c0_wired(0);
}
#endif /* CONFIG_MIPS_MT_SMTC */
}
@@ -1531,8 +1564,7 @@ void __init trap_init(void)
if (cpu_has_mipsmt)
set_except_vector(25, handle_mt);
- if (cpu_has_dsp)
- set_except_vector(26, handle_dsp);
+ set_except_vector(26, handle_dsp);
if (cpu_has_vce)
/* Special exception: R4[04]00 uses also the divec space. */
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 18c4a3c45a3..8b9c34ffae1 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -77,6 +77,7 @@
#include <linux/signal.h>
#include <linux/smp.h>
#include <linux/sched.h>
+#include <linux/debugfs.h>
#include <asm/asm.h>
#include <asm/branch.h>
#include <asm/byteorder.h>
@@ -87,9 +88,18 @@
#define STR(x) __STR(x)
#define __STR(x) #x
-#ifdef CONFIG_PROC_FS
-unsigned long unaligned_instructions;
+enum {
+ UNALIGNED_ACTION_QUIET,
+ UNALIGNED_ACTION_SIGNAL,
+ UNALIGNED_ACTION_SHOW,
+};
+#ifdef CONFIG_DEBUG_FS
+static u32 unaligned_instructions;
+static u32 unaligned_action;
+#else
+#define unaligned_action UNALIGNED_ACTION_QUIET
#endif
+extern void show_registers(struct pt_regs *regs);
static inline int emulate_load_store_insn(struct pt_regs *regs,
void __user *addr, unsigned int __user *pc,
@@ -459,7 +469,7 @@ static inline int emulate_load_store_insn(struct pt_regs *regs,
goto sigill;
}
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_DEBUG_FS
unaligned_instructions++;
#endif
@@ -516,6 +526,10 @@ asmlinkage void do_ade(struct pt_regs *regs)
pc = (unsigned int __user *) exception_epc(regs);
if (user_mode(regs) && (current->thread.mflags & MF_FIXADE) == 0)
goto sigbus;
+ if (unaligned_action == UNALIGNED_ACTION_SIGNAL)
+ goto sigbus;
+ else if (unaligned_action == UNALIGNED_ACTION_SHOW)
+ show_registers(regs);
/*
* Do branch emulation only if we didn't forward the exception.
@@ -546,3 +560,24 @@ sigbus:
* XXX On return from the signal handler we should advance the epc
*/
}
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_unaligned(void)
+{
+ struct dentry *d;
+
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+ d = debugfs_create_u32("unaligned_instructions", S_IRUGO,
+ mips_debugfs_dir, &unaligned_instructions);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ d = debugfs_create_u32("unaligned_action", S_IRUGO | S_IWUSR,
+ mips_debugfs_dir, &unaligned_action);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ return 0;
+}
+__initcall(debugfs_unaligned);
+#endif
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index c9ee9d2d585..9e66354dee8 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -1436,10 +1436,6 @@ static int __init vpe_module_init(void)
write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);
if (i != 0) {
- write_vpe_c0_status((read_c0_status() &
- ~(ST0_IM | ST0_IE | ST0_KSU))
- | ST0_CU0);
-
/*
* Set config to be the same as vpe0,
* particularly kseg0 coherency alg
diff --git a/arch/mips/lasat/Kconfig b/arch/mips/lasat/Kconfig
deleted file mode 100644
index 1d2ee8a9be1..00000000000
--- a/arch/mips/lasat/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config PICVUE
- tristate "PICVUE LCD display driver"
- depends on LASAT
-
-config PICVUE_PROC
- tristate "PICVUE LCD display driver /proc interface"
- depends on PICVUE
-
-config DS1603
- bool "DS1603 RTC driver"
- depends on LASAT
-
-config LASAT_SYSCTL
- bool "LASAT sysctl interface"
- depends on LASAT
diff --git a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile
deleted file mode 100644
index 99f5046fdf4..00000000000
--- a/arch/mips/lasat/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the LASAT specific kernel interface routines under Linux.
-#
-
-obj-y += reset.o setup.o prom.o lasat_board.o \
- at93c.o interrupt.o
-
-obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o
-obj-$(CONFIG_DS1603) += ds1603.o
-obj-$(CONFIG_PICVUE) += picvue.o
-obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o
-
-clean:
- make -C image clean
diff --git a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c
deleted file mode 100644
index ca26e554615..00000000000
--- a/arch/mips/lasat/at93c.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Atmel AT93C46 serial eeprom driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/lasat/lasat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "at93c.h"
-
-#define AT93C_ADDR_SHIFT 7
-#define AT93C_ADDR_MAX ((1 << AT93C_ADDR_SHIFT) - 1)
-#define AT93C_RCMD (0x6 << AT93C_ADDR_SHIFT)
-#define AT93C_WCMD (0x5 << AT93C_ADDR_SHIFT)
-#define AT93C_WENCMD 0x260
-#define AT93C_WDSCMD 0x200
-
-struct at93c_defs *at93c;
-
-static void at93c_reg_write(u32 val)
-{
- *at93c->reg = val;
-}
-
-static u32 at93c_reg_read(void)
-{
- u32 tmp = *at93c->reg;
- return tmp;
-}
-
-static u32 at93c_datareg_read(void)
-{
- u32 tmp = *at93c->rdata_reg;
- return tmp;
-}
-
-static void at93c_cycle_clk(u32 data)
-{
- at93c_reg_write(data | at93c->clk);
- lasat_ndelay(250);
- at93c_reg_write(data & ~at93c->clk);
- lasat_ndelay(250);
-}
-
-static void at93c_write_databit(u8 bit)
-{
- u32 data = at93c_reg_read();
- if (bit)
- data |= 1 << at93c->wdata_shift;
- else
- data &= ~(1 << at93c->wdata_shift);
-
- at93c_reg_write(data);
- lasat_ndelay(100);
- at93c_cycle_clk(data);
-}
-
-static unsigned int at93c_read_databit(void)
-{
- u32 data;
-
- at93c_cycle_clk(at93c_reg_read());
- data = (at93c_datareg_read() >> at93c->rdata_shift) & 1;
- return data;
-}
-
-static u8 at93c_read_byte(void)
-{
- int i;
- u8 data = 0;
-
- for (i = 0; i<=7; i++) {
- data <<= 1;
- data |= at93c_read_databit();
- }
- return data;
-}
-
-static void at93c_write_bits(u32 data, int size)
-{
- int i;
- int shift = size - 1;
- u32 mask = (1 << shift);
-
- for (i = 0; i < size; i++) {
- at93c_write_databit((data & mask) >> shift);
- data <<= 1;
- }
-}
-
-static void at93c_init_op(void)
-{
- at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift));
- lasat_ndelay(50);
-}
-
-static void at93c_end_op(void)
-{
- at93c_reg_write(at93c_reg_read() & ~at93c->cs);
- lasat_ndelay(250);
-}
-
-static void at93c_wait(void)
-{
- at93c_init_op();
- while (!at93c_read_databit())
- ;
- at93c_end_op();
-};
-
-static void at93c_disable_wp(void)
-{
- at93c_init_op();
- at93c_write_bits(AT93C_WENCMD, 10);
- at93c_end_op();
-}
-
-static void at93c_enable_wp(void)
-{
- at93c_init_op();
- at93c_write_bits(AT93C_WDSCMD, 10);
- at93c_end_op();
-}
-
-u8 at93c_read(u8 addr)
-{
- u8 byte;
- at93c_init_op();
- at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10);
- byte = at93c_read_byte();
- at93c_end_op();
- return byte;
-}
-
-void at93c_write(u8 addr, u8 data)
-{
- at93c_disable_wp();
- at93c_init_op();
- at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10);
- at93c_write_bits(data, 8);
- at93c_end_op();
- at93c_wait();
- at93c_enable_wp();
-}
diff --git a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h
deleted file mode 100644
index cfe2f99b1d4..00000000000
--- a/arch/mips/lasat/at93c.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Atmel AT93C46 serial eeprom driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-
-extern struct at93c_defs {
- volatile u32 *reg;
- volatile u32 *rdata_reg;
- int rdata_shift;
- int wdata_shift;
- u32 cs;
- u32 clk;
-} *at93c;
-
-u8 at93c_read(u8 addr);
-void at93c_write(u8 addr, u8 data);
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
deleted file mode 100644
index 7dced67c55e..00000000000
--- a/arch/mips/lasat/ds1603.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#include <linux/kernel.h>
-#include <asm/lasat/lasat.h>
-#include <linux/delay.h>
-#include <asm/lasat/ds1603.h>
-#include <asm/time.h>
-
-#include "ds1603.h"
-
-#define READ_TIME_CMD 0x81
-#define SET_TIME_CMD 0x80
-#define TRIMMER_SET_CMD 0xC0
-#define TRIMMER_VALUE_MASK 0x38
-#define TRIMMER_SHIFT 3
-
-struct ds_defs *ds1603 = NULL;
-
-/* HW specific register functions */
-static void rtc_reg_write(unsigned long val)
-{
- *ds1603->reg = val;
-}
-
-static unsigned long rtc_reg_read(void)
-{
- unsigned long tmp = *ds1603->reg;
- return tmp;
-}
-
-static unsigned long rtc_datareg_read(void)
-{
- unsigned long tmp = *ds1603->data_reg;
- return tmp;
-}
-
-static void rtc_nrst_high(void)
-{
- rtc_reg_write(rtc_reg_read() | ds1603->rst);
-}
-
-static void rtc_nrst_low(void)
-{
- rtc_reg_write(rtc_reg_read() & ~ds1603->rst);
-}
-
-static void rtc_cycle_clock(unsigned long data)
-{
- data |= ds1603->clk;
- rtc_reg_write(data);
- lasat_ndelay(250);
- if (ds1603->data_reversed)
- data &= ~ds1603->data;
- else
- data |= ds1603->data;
- data &= ~ds1603->clk;
- rtc_reg_write(data);
- lasat_ndelay(250 + ds1603->huge_delay);
-}
-
-static void rtc_write_databit(unsigned int bit)
-{
- unsigned long data = rtc_reg_read();
- if (ds1603->data_reversed)
- bit = !bit;
- if (bit)
- data |= ds1603->data;
- else
- data &= ~ds1603->data;
-
- rtc_reg_write(data);
- lasat_ndelay(50 + ds1603->huge_delay);
- rtc_cycle_clock(data);
-}
-
-static unsigned int rtc_read_databit(void)
-{
- unsigned int data;
-
- data = (rtc_datareg_read() & (1 << ds1603->data_read_shift))
- >> ds1603->data_read_shift;
- rtc_cycle_clock(rtc_reg_read());
- return data;
-}
-
-static void rtc_write_byte(unsigned int byte)
-{
- int i;
-
- for (i = 0; i<=7; i++) {
- rtc_write_databit(byte & 1L);
- byte >>= 1;
- }
-}
-
-static void rtc_write_word(unsigned long word)
-{
- int i;
-
- for (i = 0; i<=31; i++) {
- rtc_write_databit(word & 1L);
- word >>= 1;
- }
-}
-
-static unsigned long rtc_read_word(void)
-{
- int i;
- unsigned long word = 0;
- unsigned long shift = 0;
-
- for (i = 0; i<=31; i++) {
- word |= rtc_read_databit() << shift;
- shift++;
- }
- return word;
-}
-
-static void rtc_init_op(void)
-{
- rtc_nrst_high();
-
- rtc_reg_write(rtc_reg_read() & ~ds1603->clk);
-
- lasat_ndelay(50);
-}
-
-static void rtc_end_op(void)
-{
- rtc_nrst_low();
- lasat_ndelay(1000);
-}
-
-/* interface */
-unsigned long ds1603_read(void)
-{
- unsigned long word;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- rtc_init_op();
- rtc_write_byte(READ_TIME_CMD);
- word = rtc_read_word();
- rtc_end_op();
- spin_unlock_irqrestore(&rtc_lock, flags);
- return word;
-}
-
-int ds1603_set(unsigned long time)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- rtc_init_op();
- rtc_write_byte(SET_TIME_CMD);
- rtc_write_word(time);
- rtc_end_op();
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return 0;
-}
-
-void ds1603_set_trimmer(unsigned int trimval)
-{
- rtc_init_op();
- rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK)
- | (TRIMMER_SET_CMD));
- rtc_end_op();
-}
-
-void ds1603_disable(void)
-{
- ds1603_set_trimmer(TRIMMER_DISABLE_RTC);
-}
-
-void ds1603_enable(void)
-{
- ds1603_set_trimmer(TRIMMER_DEFAULT);
-}
diff --git a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h
deleted file mode 100644
index c2e5c76a379..00000000000
--- a/arch/mips/lasat/ds1603.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Dallas Semiconductors 1603 RTC driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#ifndef __DS1603_H
-#define __DS1603_H
-
-struct ds_defs {
- volatile u32 *reg;
- volatile u32 *data_reg;
- u32 rst;
- u32 clk;
- u32 data;
- u32 data_read_shift;
- char data_reversed;
- u32 huge_delay;
-};
-
-extern struct ds_defs *ds1603;
-
-unsigned long ds1603_read(void);
-int ds1603_set(unsigned long);
-void ds1603_set_trimmer(unsigned int);
-void ds1603_enable(void);
-void ds1603_disable(void);
-void ds1603_init(struct ds_defs *);
-
-#define TRIMMER_DEFAULT 3
-#define TRIMMER_DISABLE_RTC 0
-
-#endif
diff --git a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile
deleted file mode 100644
index 35ecd6483ef..00000000000
--- a/arch/mips/lasat/image/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER
-#
-# i-data Networks
-#
-# Author: Thomas Horsten <thh@i-data.com>
-#
-
-ifndef Version
- Version = "$(USER)-test"
-endif
-
-MKLASATIMG = mklasatimg
-MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200
-KERNEL_IMAGE = $(TOPDIR)/vmlinux
-KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ )
-KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ )
-
-LDSCRIPT= -L$(obj) -Tromscript.normal
-
-HEAD_DEFINES := -D_kernel_start=0x$(KERNEL_START) \
- -D_kernel_entry=0x$(KERNEL_ENTRY) \
- -D VERSION="\"$(Version)\"" \
- -D TIMESTAMP=$(shell date +%s)
-
-$(obj)/head.o: $(obj)/head.S $(KERNEL_IMAGE)
- $(CC) -fno-pic $(HEAD_DEFINES) -I$(TOPDIR)/include -c -o $@ $<
-
-OBJECTS = head.o kImage.o
-
-rom.sw: $(obj)/rom.sw
-
-$(obj)/rom.sw: $(obj)/rom.bin
- $(MKLASATIMG) -o $@ -k $^ -m $(MKLASATIMG_ARCH)
-
-$(obj)/rom.bin: $(obj)/rom
- $(OBJCOPY) -O binary -S $^ $@
-
-# Rule to make the bootloader
-$(obj)/rom: $(addprefix $(obj)/,$(OBJECTS))
- $(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^
-
-$(obj)/%.o: $(obj)/%.gz
- $(LD) -r -o $@ -b binary $<
-
-$(obj)/%.gz: $(obj)/%.bin
- gzip -cf -9 $< > $@
-
-$(obj)/kImage.bin: $(KERNEL_IMAGE)
- $(OBJCOPY) -O binary -S $^ $@
-
-clean:
- rm -f rom rom.bin rom.sw kImage.bin kImage.o
diff --git a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S
deleted file mode 100644
index efb95f2609c..00000000000
--- a/arch/mips/lasat/image/head.S
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <asm/lasat/head.h>
-
- .text
- .section .text.start, "ax"
- .set noreorder
- .set mips3
-
- /* Magic words identifying a software image */
- .word LASAT_K_MAGIC0_VAL
- .word LASAT_K_MAGIC1_VAL
-
- /* Image header version */
- .word 0x00000002
-
- /* image start and size */
- .word _image_start
- .word _image_size
-
- /* start of kernel and entrypoint in uncompressed image */
- .word _kernel_start
- .word _kernel_entry
-
- /* Here we have room for future flags */
-
- .org 0x40
-reldate:
- .word TIMESTAMP
-
- .org 0x50
-release:
- .string VERSION
diff --git a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal
deleted file mode 100644
index 988f8ad189c..00000000000
--- a/arch/mips/lasat/image/romscript.normal
+++ /dev/null
@@ -1,23 +0,0 @@
-OUTPUT_ARCH(mips)
-
-SECTIONS
-{
- .text :
- {
- *(.text.start)
- }
-
- /* Data in ROM */
-
- .data ALIGN(0x10) :
- {
- *(.data)
- }
- _image_start = ADDR(.data);
- _image_size = SIZEOF(.data);
-
- .other :
- {
- *(.*)
- }
-}
diff --git a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c
deleted file mode 100644
index 9a622b9a105..00000000000
--- a/arch/mips/lasat/interrupt.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
- *
- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You 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.
- *
- * Routines for generic manipulation of the interrupts found on the
- * Lasat boards.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/lasat/lasatint.h>
-#include <asm/time.h>
-#include <asm/gdb-stub.h>
-
-static volatile int *lasat_int_status = NULL;
-static volatile int *lasat_int_mask = NULL;
-static volatile int lasat_int_mask_shift;
-
-void disable_lasat_irq(unsigned int irq_nr)
-{
- *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
-}
-
-void enable_lasat_irq(unsigned int irq_nr)
-{
- *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
-}
-
-static struct irq_chip lasat_irq_type = {
- .name = "Lasat",
- .ack = disable_lasat_irq,
- .mask = disable_lasat_irq,
- .mask_ack = disable_lasat_irq,
- .unmask = enable_lasat_irq,
-};
-
-static inline int ls1bit32(unsigned int x)
-{
- int b = 31, s;
-
- s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
- s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
- s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
- s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
- s = 1; if (x << 1 == 0) s = 0; b -= s;
-
- return b;
-}
-
-static unsigned long (* get_int_status)(void);
-
-static unsigned long get_int_status_100(void)
-{
- return *lasat_int_status & *lasat_int_mask;
-}
-
-static unsigned long get_int_status_200(void)
-{
- unsigned long int_status;
-
- int_status = *lasat_int_status;
- int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff;
- return int_status;
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned long int_status;
- unsigned int cause = read_c0_cause();
- int irq;
-
- if (cause & CAUSEF_IP7) { /* R4000 count / compare IRQ */
- ll_timer_interrupt(7);
- return;
- }
-
- int_status = get_int_status();
-
- /* if int_status == 0, then the interrupt has already been cleared */
- if (int_status) {
- irq = ls1bit32(int_status);
-
- do_IRQ(irq);
- }
-}
-
-void __init arch_init_irq(void)
-{
- int i;
-
- switch (mips_machtype) {
- case MACH_LASAT_100:
- lasat_int_status = (void *)LASAT_INT_STATUS_REG_100;
- lasat_int_mask = (void *)LASAT_INT_MASK_REG_100;
- lasat_int_mask_shift = LASATINT_MASK_SHIFT_100;
- get_int_status = get_int_status_100;
- *lasat_int_mask = 0;
- break;
- case MACH_LASAT_200:
- lasat_int_status = (void *)LASAT_INT_STATUS_REG_200;
- lasat_int_mask = (void *)LASAT_INT_MASK_REG_200;
- lasat_int_mask_shift = LASATINT_MASK_SHIFT_200;
- get_int_status = get_int_status_200;
- *lasat_int_mask &= 0xffff;
- break;
- default:
- panic("arch_init_irq: mips_machtype incorrect");
- }
-
- for (i = 0; i <= LASATINT_END; i++)
- set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c
deleted file mode 100644
index fbe9a87bd0a..00000000000
--- a/arch/mips/lasat/lasat_board.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You 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.
- *
- * Routines specific to the LASAT boards
- */
-#include <linux/types.h>
-#include <linux/crc32.h>
-#include <asm/lasat/lasat.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <asm/bootinfo.h>
-#include <asm/addrspace.h>
-#include "at93c.h"
-/* New model description table */
-#include "lasat_models.h"
-
-#define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len))
-
-struct lasat_info lasat_board_info;
-
-void update_bcastaddr(void);
-
-int EEPROMRead(unsigned int pos, unsigned char *data, int len)
-{
- int i;
-
- for (i=0; i<len; i++)
- *data++ = at93c_read(pos++);
-
- return 0;
-}
-int EEPROMWrite(unsigned int pos, unsigned char *data, int len)
-{
- int i;
-
- for (i=0; i<len; i++)
- at93c_write(pos++, *data++);
-
- return 0;
-}
-
-static void init_flash_sizes(void)
-{
- int i;
- unsigned long *lb = lasat_board_info.li_flashpart_base;
- unsigned long *ls = lasat_board_info.li_flashpart_size;
-
- ls[LASAT_MTD_BOOTLOADER] = 0x40000;
- ls[LASAT_MTD_SERVICE] = 0xC0000;
- ls[LASAT_MTD_NORMAL] = 0x100000;
-
- if (mips_machtype == MACH_LASAT_100) {
- lasat_board_info.li_flash_base = 0x1e000000;
-
- lb[LASAT_MTD_BOOTLOADER] = 0x1e400000;
-
- if (lasat_board_info.li_flash_size > 0x200000) {
- ls[LASAT_MTD_CONFIG] = 0x100000;
- ls[LASAT_MTD_FS] = 0x500000;
- }
- } else {
- lasat_board_info.li_flash_base = 0x10000000;
-
- if (lasat_board_info.li_flash_size < 0x1000000) {
- lb[LASAT_MTD_BOOTLOADER] = 0x10000000;
- ls[LASAT_MTD_CONFIG] = 0x100000;
- if (lasat_board_info.li_flash_size >= 0x400000) {
- ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000;
- }
- }
- }
-
- for (i = 1; i < LASAT_MTD_LAST; i++)
- lb[i] = lb[i-1] + ls[i-1];
-}
-
-int lasat_init_board_info(void)
-{
- int c;
- unsigned long crc;
- unsigned long cfg0, cfg1;
- const product_info_t *ppi;
- int i_n_base_models = N_BASE_MODELS;
- const char * const * i_txt_base_models = txt_base_models;
- int i_n_prids = N_PRIDS;
-
- memset(&lasat_board_info, 0, sizeof(lasat_board_info));
-
- /* First read the EEPROM info */
- EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
- sizeof(struct lasat_eeprom_struct));
-
- /* Check the CRC */
- crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
- sizeof(struct lasat_eeprom_struct) - 4);
-
- if (crc != lasat_board_info.li_eeprom_info.crc32) {
- printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM CRC does "
- "not match calculated, attempting to soldier on...\n");
- }
-
- if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) {
- printk(KERN_WARNING "WARNING...\nWARNING...\nEEPROM version "
- "%d, wanted version %d, attempting to soldier on...\n",
- (unsigned int)lasat_board_info.li_eeprom_info.version,
- LASAT_EEPROM_VERSION);
- }
-
- cfg0 = lasat_board_info.li_eeprom_info.cfg[0];
- cfg1 = lasat_board_info.li_eeprom_info.cfg[1];
-
- if ( LASAT_W0_DSCTYPE(cfg0) != 1) {
- printk(KERN_WARNING "WARNING...\nWARNING...\n"
- "Invalid configuration read from EEPROM, attempting to "
- "soldier on...");
- }
- /* We have a valid configuration */
-
- switch (LASAT_W0_SDRAMBANKSZ(cfg0)) {
- case 0:
- lasat_board_info.li_memsize = 0x0800000;
- break;
- case 1:
- lasat_board_info.li_memsize = 0x1000000;
- break;
- case 2:
- lasat_board_info.li_memsize = 0x2000000;
- break;
- case 3:
- lasat_board_info.li_memsize = 0x4000000;
- break;
- case 4:
- lasat_board_info.li_memsize = 0x8000000;
- break;
- default:
- lasat_board_info.li_memsize = 0;
- }
-
- switch (LASAT_W0_SDRAMBANKS(cfg0)) {
- case 0:
- break;
- case 1:
- lasat_board_info.li_memsize *= 2;
- break;
- default:
- break;
- }
-
- switch (LASAT_W0_BUSSPEED(cfg0)) {
- case 0x0:
- lasat_board_info.li_bus_hz = 60000000;
- break;
- case 0x1:
- lasat_board_info.li_bus_hz = 66000000;
- break;
- case 0x2:
- lasat_board_info.li_bus_hz = 66666667;
- break;
- case 0x3:
- lasat_board_info.li_bus_hz = 80000000;
- break;
- case 0x4:
- lasat_board_info.li_bus_hz = 83333333;
- break;
- case 0x5:
- lasat_board_info.li_bus_hz = 100000000;
- break;
- }
-
- switch (LASAT_W0_CPUCLK(cfg0)) {
- case 0x0:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz;
- break;
- case 0x1:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz +
- (lasat_board_info.li_bus_hz >> 1);
- break;
- case 0x2:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz +
- lasat_board_info.li_bus_hz;
- break;
- case 0x3:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz +
- lasat_board_info.li_bus_hz +
- (lasat_board_info.li_bus_hz >> 1);
- break;
- case 0x4:
- lasat_board_info.li_cpu_hz =
- lasat_board_info.li_bus_hz +
- lasat_board_info.li_bus_hz +
- lasat_board_info.li_bus_hz;
- break;
- }
-
- /* Flash size */
- switch (LASAT_W1_FLASHSIZE(cfg1)) {
- case 0:
- lasat_board_info.li_flash_size = 0x200000;
- break;
- case 1:
- lasat_board_info.li_flash_size = 0x400000;
- break;
- case 2:
- lasat_board_info.li_flash_size = 0x800000;
- break;
- case 3:
- lasat_board_info.li_flash_size = 0x1000000;
- break;
- case 4:
- lasat_board_info.li_flash_size = 0x2000000;
- break;
- }
-
- init_flash_sizes();
-
- lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0);
- lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid;
- if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0)
- lasat_board_info.li_prid = lasat_board_info.li_bmid;
-
- /* Base model stuff */
- if (lasat_board_info.li_bmid > i_n_base_models)
- lasat_board_info.li_bmid = i_n_base_models;
- strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]);
-
- /* Product ID dependent values */
- c = lasat_board_info.li_prid;
- if (c >= i_n_prids) {
- strcpy(lasat_board_info.li_namestr, "Unknown Model");
- strcpy(lasat_board_info.li_typestr, "Unknown Type");
- } else {
- ppi = &vendor_info_table[0].vi_product_info[c];
- strcpy(lasat_board_info.li_namestr, ppi->pi_name);
- if (ppi->pi_type)
- strcpy(lasat_board_info.li_typestr, ppi->pi_type);
- else
- sprintf(lasat_board_info.li_typestr, "%d",10*c);
- }
-
-#if defined(CONFIG_INET) && defined(CONFIG_SYSCTL)
- update_bcastaddr();
-#endif
-
- return 0;
-}
-
-void lasat_write_eeprom_info(void)
-{
- unsigned long crc;
-
- /* Generate the CRC */
- crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info),
- sizeof(struct lasat_eeprom_struct) - 4);
- lasat_board_info.li_eeprom_info.crc32 = crc;
-
- /* Write the EEPROM info */
- EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info,
- sizeof(struct lasat_eeprom_struct));
-}
-
diff --git a/arch/mips/lasat/lasat_models.h b/arch/mips/lasat/lasat_models.h
deleted file mode 100644
index ae0c5d0bd40..00000000000
--- a/arch/mips/lasat/lasat_models.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Model description tables
- */
-
-typedef struct product_info_t {
- const char *pi_name;
- const char *pi_type;
-} product_info_t;
-
-typedef struct vendor_info_t {
- const char *vi_name;
- const product_info_t *vi_product_info;
-} vendor_info_t;
-
-/*
- * Base models
- */
-static const char * const txt_base_models[] = {
- "MQ 2", "MQ Pro", "SP 25", "SP 50", "SP 100", "SP 5000", "SP 7000", "SP 1000", "Unknown"
-};
-#define N_BASE_MODELS (sizeof(txt_base_models)/sizeof(char*)-1)
-
-/*
- * Eicon Networks
- */
-static const char txt_en_mq[] = "Masquerade";
-static const char txt_en_sp[] = "Safepipe";
-
-static const product_info_t product_info_eicon[] = {
- { txt_en_mq, "II" }, /* 0 */
- { txt_en_mq, "Pro" }, /* 1 */
- { txt_en_sp, "25" }, /* 2 */
- { txt_en_sp, "50" }, /* 3 */
- { txt_en_sp, "100" }, /* 4 */
- { txt_en_sp, "5000" }, /* 5 */
- { txt_en_sp, "7000" }, /* 6 */
- { txt_en_sp, "30" }, /* 7 */
- { txt_en_sp, "5100" }, /* 8 */
- { txt_en_sp, "7100" }, /* 9 */
- { txt_en_sp, "1110" }, /* 10 */
- { txt_en_sp, "3020" }, /* 11 */
- { txt_en_sp, "3030" }, /* 12 */
- { txt_en_sp, "5020" }, /* 13 */
- { txt_en_sp, "5030" }, /* 14 */
- { txt_en_sp, "1120" }, /* 15 */
- { txt_en_sp, "1130" }, /* 16 */
- { txt_en_sp, "6010" }, /* 17 */
- { txt_en_sp, "6110" }, /* 18 */
- { txt_en_sp, "6210" }, /* 19 */
- { txt_en_sp, "1020" }, /* 20 */
- { txt_en_sp, "1040" }, /* 21 */
- { txt_en_sp, "1050" }, /* 22 */
- { txt_en_sp, "1060" }, /* 23 */
-};
-#define N_PRIDS (sizeof(product_info_eicon)/sizeof(product_info_t))
-
-/*
- * The vendor table
- */
-static vendor_info_t const vendor_info_table[] = {
- { "Eicon Networks", product_info_eicon },
-};
-#define N_VENDORS (sizeof(vendor_info_table)/sizeof(vendor_info_t))
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c
deleted file mode 100644
index 9ae82c3ffb0..00000000000
--- a/arch/mips/lasat/picvue.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian@murphy.dk>
- *
- */
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <asm/bootinfo.h>
-#include <asm/lasat/lasat.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-
-#include "picvue.h"
-
-#define PVC_BUSY 0x80
-#define PVC_NLINES 2
-#define PVC_DISPMEM 80
-#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES
-
-struct pvc_defs *picvue = NULL;
-
-DECLARE_MUTEX(pvc_sem);
-
-static void pvc_reg_write(u32 val)
-{
- *picvue->reg = val;
-}
-
-static u32 pvc_reg_read(void)
-{
- u32 tmp = *picvue->reg;
- return tmp;
-}
-
-static void pvc_write_byte(u32 data, u8 byte)
-{
- data |= picvue->e;
- pvc_reg_write(data);
- data &= ~picvue->data_mask;
- data |= byte << picvue->data_shift;
- pvc_reg_write(data);
- ndelay(220);
- pvc_reg_write(data & ~picvue->e);
- ndelay(220);
-}
-
-static u8 pvc_read_byte(u32 data)
-{
- u8 byte;
-
- data |= picvue->e;
- pvc_reg_write(data);
- ndelay(220);
- byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift;
- data &= ~picvue->e;
- pvc_reg_write(data);
- ndelay(220);
- return byte;
-}
-
-static u8 pvc_read_data(void)
-{
- u32 data = pvc_reg_read();
- u8 byte;
- data |= picvue->rw;
- data &= ~picvue->rs;
- pvc_reg_write(data);
- ndelay(40);
- byte = pvc_read_byte(data);
- data |= picvue->rs;
- pvc_reg_write(data);
- return byte;
-}
-
-#define TIMEOUT 1000
-static int pvc_wait(void)
-{
- int i = TIMEOUT;
- int err = 0;
-
- while ((pvc_read_data() & PVC_BUSY) && i)
- i--;
- if (i == 0)
- err = -ETIME;
-
- return err;
-}
-
-#define MODE_INST 0
-#define MODE_DATA 1
-static void pvc_write(u8 byte, int mode)
-{
- u32 data = pvc_reg_read();
- data &= ~picvue->rw;
- if (mode == MODE_DATA)
- data |= picvue->rs;
- else
- data &= ~picvue->rs;
- pvc_reg_write(data);
- ndelay(40);
- pvc_write_byte(data, byte);
- if (mode == MODE_DATA)
- data &= ~picvue->rs;
- else
- data |= picvue->rs;
- pvc_reg_write(data);
- pvc_wait();
-}
-
-void pvc_write_string(const unsigned char *str, u8 addr, int line)
-{
- int i = 0;
-
- if (line > 0 && (PVC_NLINES > 1))
- addr += 0x40 * line;
- pvc_write(0x80 | addr, MODE_INST);
-
- while (*str != 0 && i < PVC_LINELEN) {
- pvc_write(*str++, MODE_DATA);
- i++;
- }
-}
-
-void pvc_write_string_centered(const unsigned char *str, int line)
-{
- int len = strlen(str);
- u8 addr;
-
- if (len > PVC_VISIBLE_CHARS)
- addr = 0;
- else
- addr = (PVC_VISIBLE_CHARS - strlen(str))/2;
-
- pvc_write_string(str, addr, line);
-}
-
-void pvc_dump_string(const unsigned char *str)
-{
- int len = strlen(str);
-
- pvc_write_string(str, 0, 0);
- if (len > PVC_VISIBLE_CHARS)
- pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1);
-}
-
-#define BM_SIZE 8
-#define MAX_PROGRAMMABLE_CHARS 8
-int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE])
-{
- int i;
- int addr;
-
- if (charnum > MAX_PROGRAMMABLE_CHARS)
- return -ENOENT;
-
- addr = charnum * 8;
- pvc_write(0x40 | addr, MODE_INST);
-
- for (i=0; i<BM_SIZE; i++)
- pvc_write(bitmap[i], MODE_DATA);
- return 0;
-}
-
-#define FUNC_SET_CMD 0x20
-#define EIGHT_BYTE (1 << 4)
-#define FOUR_BYTE 0
-#define TWO_LINES (1 << 3)
-#define ONE_LINE 0
-#define LARGE_FONT (1 << 2)
-#define SMALL_FONT 0
-static void pvc_funcset(u8 cmd)
-{
- pvc_write(FUNC_SET_CMD | (cmd & (EIGHT_BYTE|TWO_LINES|LARGE_FONT)), MODE_INST);
-}
-
-#define ENTRYMODE_CMD 0x4
-#define AUTO_INC (1 << 1)
-#define AUTO_DEC 0
-#define CURSOR_FOLLOWS_DISP (1 << 0)
-static void pvc_entrymode(u8 cmd)
-{
- pvc_write(ENTRYMODE_CMD | (cmd & (AUTO_INC|CURSOR_FOLLOWS_DISP)), MODE_INST);
-}
-
-#define DISP_CNT_CMD 0x08
-#define DISP_OFF 0
-#define DISP_ON (1 << 2)
-#define CUR_ON (1 << 1)
-#define CUR_BLINK (1 << 0)
-void pvc_dispcnt(u8 cmd)
-{
- pvc_write(DISP_CNT_CMD | (cmd & (DISP_ON|CUR_ON|CUR_BLINK)), MODE_INST);
-}
-
-#define MOVE_CMD 0x10
-#define DISPLAY (1 << 3)
-#define CURSOR 0
-#define RIGHT (1 << 2)
-#define LEFT 0
-void pvc_move(u8 cmd)
-{
- pvc_write(MOVE_CMD | (cmd & (DISPLAY|RIGHT)), MODE_INST);
-}
-
-#define CLEAR_CMD 0x1
-void pvc_clear(void)
-{
- pvc_write(CLEAR_CMD, MODE_INST);
-}
-
-#define HOME_CMD 0x2
-void pvc_home(void)
-{
- pvc_write(HOME_CMD, MODE_INST);
-}
-
-int pvc_init(void)
-{
- u8 cmd = EIGHT_BYTE;
-
- if (PVC_NLINES == 2)
- cmd |= (SMALL_FONT|TWO_LINES);
- else
- cmd |= (LARGE_FONT|ONE_LINE);
- pvc_funcset(cmd);
- pvc_dispcnt(DISP_ON);
- pvc_entrymode(AUTO_INC);
-
- pvc_clear();
- pvc_write_string_centered("Display", 0);
- pvc_write_string_centered("Initialized", 1);
-
- return 0;
-}
-
-module_init(pvc_init);
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/picvue.h b/arch/mips/lasat/picvue.h
deleted file mode 100644
index 2a96bf97189..00000000000
--- a/arch/mips/lasat/picvue.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <asm/semaphore.h>
-
-struct pvc_defs {
- volatile u32 *reg;
- u32 data_shift;
- u32 data_mask;
- u32 e;
- u32 rw;
- u32 rs;
-};
-
-extern struct pvc_defs *picvue;
-
-#define PVC_NLINES 2
-#define PVC_DISPMEM 80
-#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES
-#define PVC_VISIBLE_CHARS 16
-
-void pvc_write_string(const unsigned char *str, u8 addr, int line);
-void pvc_write_string_centered(const unsigned char *str, int line);
-void pvc_dump_string(const unsigned char *str);
-
-#define BM_SIZE 8
-#define MAX_PROGRAMMABLE_CHARS 8
-int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]);
-
-void pvc_dispcnt(u8 cmd);
-#define DISP_OFF 0
-#define DISP_ON (1 << 2)
-#define CUR_ON (1 << 1)
-#define CUR_BLINK (1 << 0)
-
-void pvc_move(u8 cmd);
-#define DISPLAY (1 << 3)
-#define CURSOR 0
-#define RIGHT (1 << 2)
-#define LEFT 0
-
-void pvc_clear(void);
-void pvc_home(void);
-
-extern struct semaphore pvc_sem;
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c
deleted file mode 100644
index cce7cddcdb0..00000000000
--- a/arch/mips/lasat/picvue_proc.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Picvue PVC160206 display driver
- *
- * Brian Murphy <brian.murphy@eicon.com>
- *
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-
-#include <linux/proc_fs.h>
-#include <linux/interrupt.h>
-
-#include <linux/timer.h>
-
-#include "picvue.h"
-
-static char pvc_lines[PVC_NLINES][PVC_LINELEN+1];
-static int pvc_linedata[PVC_NLINES];
-static struct proc_dir_entry *pvc_display_dir;
-static char *pvc_linename[PVC_NLINES] = {"line1", "line2"};
-#define DISPLAY_DIR_NAME "display"
-static int scroll_dir = 0, scroll_interval = 0;
-
-static struct timer_list timer;
-
-static void pvc_display(unsigned long data) {
- int i;
-
- pvc_clear();
- for (i=0; i<PVC_NLINES; i++)
- pvc_write_string(pvc_lines[i], 0, i);
-}
-
-static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
-
-static int pvc_proc_read_line(char *page, char **start,
- off_t off, int count,
- int *eof, void *data)
-{
- char *origpage = page;
- int lineno = *(int *)data;
-
- if (lineno < 0 || lineno > PVC_NLINES) {
- printk("proc_read_line: invalid lineno %d\n", lineno);
- return 0;
- }
-
- down(&pvc_sem);
- page += sprintf(page, "%s\n", pvc_lines[lineno]);
- up(&pvc_sem);
-
- return page - origpage;
-}
-
-static int pvc_proc_write_line(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- int origcount = count;
- int lineno = *(int *)data;
-
- if (lineno < 0 || lineno > PVC_NLINES) {
- printk("proc_write_line: invalid lineno %d\n", lineno);
- return origcount;
- }
-
- if (count > PVC_LINELEN)
- count = PVC_LINELEN;
-
- if (buffer[count-1] == '\n')
- count--;
-
- down(&pvc_sem);
- strncpy(pvc_lines[lineno], buffer, count);
- pvc_lines[lineno][count] = '\0';
- up(&pvc_sem);
-
- tasklet_schedule(&pvc_display_tasklet);
-
- return origcount;
-}
-
-static int pvc_proc_write_scroll(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- int origcount = count;
- int cmd = simple_strtol(buffer, NULL, 10);
-
- down(&pvc_sem);
- if (scroll_interval != 0)
- del_timer(&timer);
-
- if (cmd == 0) {
- scroll_dir = 0;
- scroll_interval = 0;
- } else {
- if (cmd < 0) {
- scroll_dir = -1;
- scroll_interval = -cmd;
- } else {
- scroll_dir = 1;
- scroll_interval = cmd;
- }
- add_timer(&timer);
- }
- up(&pvc_sem);
-
- return origcount;
-}
-
-static int pvc_proc_read_scroll(char *page, char **start,
- off_t off, int count,
- int *eof, void *data)
-{
- char *origpage = page;
-
- down(&pvc_sem);
- page += sprintf(page, "%d\n", scroll_dir * scroll_interval);
- up(&pvc_sem);
-
- return page - origpage;
-}
-
-
-void pvc_proc_timerfunc(unsigned long data)
-{
- if (scroll_dir < 0)
- pvc_move(DISPLAY|RIGHT);
- else if (scroll_dir > 0)
- pvc_move(DISPLAY|LEFT);
-
- timer.expires = jiffies + scroll_interval;
- add_timer(&timer);
-}
-
-static void pvc_proc_cleanup(void)
-{
- int i;
- for (i=0; i<PVC_NLINES; i++)
- remove_proc_entry(pvc_linename[i], pvc_display_dir);
- remove_proc_entry("scroll", pvc_display_dir);
- remove_proc_entry(DISPLAY_DIR_NAME, NULL);
-
- del_timer(&timer);
-}
-
-static int __init pvc_proc_init(void)
-{
- struct proc_dir_entry *proc_entry;
- int i;
-
- pvc_display_dir = proc_mkdir(DISPLAY_DIR_NAME, NULL);
- if (pvc_display_dir == NULL)
- goto error;
-
- for (i=0; i<PVC_NLINES; i++) {
- strcpy(pvc_lines[i], "");
- pvc_linedata[i] = i;
- }
- for (i=0; i<PVC_NLINES; i++) {
- proc_entry = create_proc_entry(pvc_linename[i], 0644, pvc_display_dir);
- if (proc_entry == NULL)
- goto error;
- proc_entry->read_proc = pvc_proc_read_line;
- proc_entry->write_proc = pvc_proc_write_line;
- proc_entry->data = &pvc_linedata[i];
- }
- proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir);
- if (proc_entry == NULL)
- goto error;
- proc_entry->write_proc = pvc_proc_write_scroll;
- proc_entry->read_proc = pvc_proc_read_scroll;
-
- init_timer(&timer);
- timer.function = pvc_proc_timerfunc;
-
- return 0;
-error:
- pvc_proc_cleanup();
- return -ENOMEM;
-}
-
-module_init(pvc_proc_init);
-module_exit(pvc_proc_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c
deleted file mode 100644
index 812c6ac366b..00000000000
--- a/arch/mips/lasat/prom.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * PROM interface routines.
- */
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/ioport.h>
-#include <asm/bootinfo.h>
-#include <asm/lasat/lasat.h>
-#include <asm/cpu.h>
-
-#include "at93c.h"
-#include <asm/lasat/eeprom.h>
-#include "prom.h"
-
-#define RESET_VECTOR 0xbfc00000
-#define PROM_JUMP_TABLE_ENTRY(n) (*((u32 *)(RESET_VECTOR + 0x20) + n))
-#define PROM_DISPLAY_ADDR PROM_JUMP_TABLE_ENTRY(0)
-#define PROM_PUTC_ADDR PROM_JUMP_TABLE_ENTRY(1)
-#define PROM_MONITOR_ADDR PROM_JUMP_TABLE_ENTRY(2)
-
-static void null_prom_display(const char *string, int pos, int clear)
-{
-}
-
-static void null_prom_monitor(void)
-{
-}
-
-static void null_prom_putc(char c)
-{
-}
-
-/* these are functions provided by the bootloader */
-static void (* __prom_putc)(char c) = null_prom_putc;
-
-void prom_putchar(char c)
-{
- __prom_putc(c);
-}
-
-void (* prom_display)(const char *string, int pos, int clear) =
- null_prom_display;
-void (* prom_monitor)(void) = null_prom_monitor;
-
-unsigned int lasat_ndelay_divider;
-
-static void setup_prom_vectors(void)
-{
- u32 version = *(u32 *)(RESET_VECTOR + 0x90);
-
- if (version >= 307) {
- prom_display = (void *)PROM_DISPLAY_ADDR;
- __prom_putc = (void *)PROM_PUTC_ADDR;
- prom_monitor = (void *)PROM_MONITOR_ADDR;
- }
- printk("prom vectors set up\n");
-}
-
-static struct at93c_defs at93c_defs[N_MACHTYPES] = {
- {(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100,
- AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100},
- {(void *)AT93C_REG_200, (void *)AT93C_RDATA_REG_200, AT93C_RDATA_SHIFT_200,
- AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200},
-};
-
-void __init prom_init(void)
-{
- int argc = fw_arg0;
- char **argv = (char **) fw_arg1;
-
- setup_prom_vectors();
-
- if (current_cpu_data.cputype == CPU_R5000) {
- printk("LASAT 200 board\n");
- mips_machtype = MACH_LASAT_200;
- lasat_ndelay_divider = LASAT_200_DIVIDER;
- } else {
- printk("LASAT 100 board\n");
- mips_machtype = MACH_LASAT_100;
- lasat_ndelay_divider = LASAT_100_DIVIDER;
- }
-
- at93c = &at93c_defs[mips_machtype];
-
- lasat_init_board_info(); /* Read info from EEPROM */
-
- mips_machgroup = MACH_GROUP_LASAT;
-
- /* Get the command line */
- if (argc > 0) {
- strncpy(arcs_cmdline, argv[0], CL_SIZE-1);
- arcs_cmdline[CL_SIZE-1] = '\0';
- }
-
- /* Set the I/O base address */
- set_io_port_base(KSEG1);
-
- /* Set memory regions */
- ioport_resource.start = 0;
- ioport_resource.end = 0xffffffff; /* Wrong, fixme. */
-
- add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM);
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-const char *get_system_type(void)
-{
- return lasat_board_info.li_bmstr;
-}
diff --git a/arch/mips/lasat/prom.h b/arch/mips/lasat/prom.h
deleted file mode 100644
index 019d45fbd26..00000000000
--- a/arch/mips/lasat/prom.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef PROM_H
-#define PROM_H
-extern void (* prom_display)(const char *string, int pos, int clear);
-extern void (* prom_monitor)(void);
-#endif
diff --git a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c
deleted file mode 100644
index 9e22acf0308..00000000000
--- a/arch/mips/lasat/reset.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You 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.
- *
- * Reset the LASAT board.
- */
-#include <linux/kernel.h>
-#include <linux/pm.h>
-
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/lasat/lasat.h>
-
-#include "picvue.h"
-#include "prom.h"
-
-static void lasat_machine_restart(char *command);
-static void lasat_machine_halt(void);
-
-/* Used to set machine to boot in service mode via /proc interface */
-int lasat_boot_to_service = 0;
-
-static void lasat_machine_restart(char *command)
-{
- local_irq_disable();
-
- if (lasat_boot_to_service) {
- printk("machine_restart: Rebooting to service mode\n");
- *(volatile unsigned int *)0xa0000024 = 0xdeadbeef;
- *(volatile unsigned int *)0xa00000fc = 0xfedeabba;
- }
- *lasat_misc->reset_reg = 0xbedead;
- for (;;) ;
-}
-
-#define MESSAGE "System halted"
-static void lasat_machine_halt(void)
-{
- local_irq_disable();
-
- /* Disable interrupts and loop forever */
- printk(KERN_NOTICE MESSAGE "\n");
-#ifdef CONFIG_PICVUE
- pvc_clear();
- pvc_write_string(MESSAGE, 0, 0);
-#endif
- prom_monitor();
- for (;;) ;
-}
-
-void lasat_reboot_setup(void)
-{
- _machine_restart = lasat_machine_restart;
- _machine_halt = lasat_machine_halt;
- pm_power_off = lasat_machine_halt;
-}
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
deleted file mode 100644
index 488007f1398..00000000000
--- a/arch/mips/lasat/setup.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved.
- *
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * Brian Murphy <brian@murphy.dk>
- *
- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You 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.
- *
- * Lasat specific setup.
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-
-#include <asm/time.h>
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/lasat/lasat.h>
-#include <asm/lasat/serial.h>
-
-#ifdef CONFIG_PICVUE
-#include <linux/notifier.h>
-#endif
-
-#include "ds1603.h"
-#include <asm/lasat/ds1603.h>
-#include <asm/lasat/picvue.h>
-#include <asm/lasat/eeprom.h>
-
-#include "prom.h"
-
-int lasat_command_line = 0;
-void lasatint_init(void);
-
-extern void lasat_reboot_setup(void);
-extern void pcisetup(void);
-extern void edhac_init(void *, void *, void *);
-extern void addrflt_init(void);
-
-struct lasat_misc lasat_misc_info[N_MACHTYPES] = {
- {(void *)KSEG1ADDR(0x1c840000), (void *)KSEG1ADDR(0x1c800000), 2},
- {(void *)KSEG1ADDR(0x11080000), (void *)KSEG1ADDR(0x11000000), 6}
-};
-
-struct lasat_misc *lasat_misc = NULL;
-
-#ifdef CONFIG_DS1603
-static struct ds_defs ds_defs[N_MACHTYPES] = {
- { (void *)DS1603_REG_100, (void *)DS1603_REG_100,
- DS1603_RST_100, DS1603_CLK_100, DS1603_DATA_100,
- DS1603_DATA_SHIFT_100, 0, 0 },
- { (void *)DS1603_REG_200, (void *)DS1603_DATA_REG_200,
- DS1603_RST_200, DS1603_CLK_200, DS1603_DATA_200,
- DS1603_DATA_READ_SHIFT_200, 1, 2000 }
-};
-#endif
-
-#ifdef CONFIG_PICVUE
-#include "picvue.h"
-static struct pvc_defs pvc_defs[N_MACHTYPES] = {
- { (void *)PVC_REG_100, PVC_DATA_SHIFT_100, PVC_DATA_M_100,
- PVC_E_100, PVC_RW_100, PVC_RS_100 },
- { (void *)PVC_REG_200, PVC_DATA_SHIFT_200, PVC_DATA_M_200,
- PVC_E_200, PVC_RW_200, PVC_RS_200 }
-};
-#endif
-
-static int lasat_panic_display(struct notifier_block *this,
- unsigned long event, void *ptr)
-{
-#ifdef CONFIG_PICVUE
- unsigned char *string = ptr;
- if (string == NULL)
- string = "Kernel Panic";
- pvc_dump_string(string);
-#endif
- return NOTIFY_DONE;
-}
-
-static int lasat_panic_prom_monitor(struct notifier_block *this,
- unsigned long event, void *ptr)
-{
- prom_monitor();
- return NOTIFY_DONE;
-}
-
-static struct notifier_block lasat_panic_block[] =
-{
- { lasat_panic_display, NULL, INT_MAX },
- { lasat_panic_prom_monitor, NULL, INT_MIN }
-};
-
-static void lasat_time_init(void)
-{
- mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5);
-}
-
-#define DYNAMIC_SERIAL_INIT
-#ifdef DYNAMIC_SERIAL_INIT
-void __init serial_init(void)
-{
-#ifdef CONFIG_SERIAL_8250
- struct uart_port s;
-
- memset(&s, 0, sizeof(s));
-
- s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
- s.iotype = UPIO_MEM;
-
- if (mips_machtype == MACH_LASAT_100) {
- s.uartclk = LASAT_BASE_BAUD_100 * 16;
- s.irq = LASATINT_UART_100;
- s.regshift = LASAT_UART_REGS_SHIFT_100;
- s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_100);
- } else {
- s.uartclk = LASAT_BASE_BAUD_200 * 16;
- s.irq = LASATINT_UART_200;
- s.regshift = LASAT_UART_REGS_SHIFT_200;
- s.membase = (char *)KSEG1ADDR(LASAT_UART_REGS_BASE_200);
- }
-
- if (early_serial_setup(&s) != 0)
- printk(KERN_ERR "Serial setup failed!\n");
-#endif
-}
-#endif
-
-void __init plat_mem_setup(void)
-{
- int i;
- lasat_misc = &lasat_misc_info[mips_machtype];
-#ifdef CONFIG_PICVUE
- picvue = &pvc_defs[mips_machtype];
-#endif
-
- /* Set up panic notifier */
- for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++)
- atomic_notifier_chain_register(&panic_notifier_list,
- &lasat_panic_block[i]);
-
- lasat_reboot_setup();
-
- board_time_init = lasat_time_init;
-
-#ifdef CONFIG_DS1603
- ds1603 = &ds_defs[mips_machtype];
- rtc_mips_get_time = ds1603_read;
- rtc_mips_set_time = ds1603_set;
-#endif
-
-#ifdef DYNAMIC_SERIAL_INIT
- serial_init();
-#endif
- /* Switch from prom exception handler to normal mode */
- change_c0_status(ST0_BEV,0);
-
- pr_info("Lasat specific initialization complete\n");
-}
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
deleted file mode 100644
index 699ab1886ce..00000000000
--- a/arch/mips/lasat/sysctl.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You 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.
- *
- * Routines specific to the LASAT boards
- */
-#include <linux/types.h>
-#include <asm/lasat/lasat.h>
-
-#include <linux/module.h>
-#include <linux/sysctl.h>
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/net.h>
-#include <linux/inet.h>
-#include <linux/mutex.h>
-#include <asm/uaccess.h>
-
-#include "sysctl.h"
-#include "ds1603.h"
-
-static DEFINE_MUTEX(lasat_info_mutex);
-
-/* Strategy function to write EEPROM after changing string entry */
-int sysctl_lasatstring(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = sysctl_string(table, name,
- nlen, oldval, oldlenp, newval, newlen);
- if (r < 0) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- if (newval && newlen) {
- lasat_write_eeprom_info();
- }
- mutex_unlock(&lasat_info_mutex);
- return 1;
-}
-
-
-/* And the same for proc */
-int proc_dolasatstring(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = proc_dostring(table, write, filp, buffer, lenp, ppos);
- if ( (!write) || r) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- lasat_write_eeprom_info();
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-
-/* proc function to write EEPROM after changing int entry */
-int proc_dolasatint(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
- if ( (!write) || r) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- lasat_write_eeprom_info();
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-
-static int rtctmp;
-
-#ifdef CONFIG_DS1603
-/* proc function to read/write RealTime Clock */
-int proc_dolasatrtc(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- if (!write) {
- rtctmp = ds1603_read();
- /* check for time < 0 and set to 0 */
- if (rtctmp < 0)
- rtctmp = 0;
- }
- r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
- if ( (!write) || r) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- ds1603_set(rtctmp);
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-#endif
-
-/* Sysctl for setting the IP addresses */
-int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
- if (r < 0) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- if (newval && newlen) {
- lasat_write_eeprom_info();
- }
- mutex_unlock(&lasat_info_mutex);
- return 1;
-}
-
-#ifdef CONFIG_DS1603
-/* Same for RTC */
-int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- rtctmp = ds1603_read();
- if (rtctmp < 0)
- rtctmp = 0;
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
- if (r < 0) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- if (newval && newlen) {
- ds1603_set(rtctmp);
- }
- mutex_unlock(&lasat_info_mutex);
- return 1;
-}
-#endif
-
-#ifdef CONFIG_INET
-static char lasat_bcastaddr[16];
-
-void update_bcastaddr(void)
-{
- unsigned int ip;
-
- ip = (lasat_board_info.li_eeprom_info.ipaddr &
- lasat_board_info.li_eeprom_info.netmask) |
- ~lasat_board_info.li_eeprom_info.netmask;
-
- sprintf(lasat_bcastaddr, "%d.%d.%d.%d",
- (ip ) & 0xff,
- (ip >> 8) & 0xff,
- (ip >> 16) & 0xff,
- (ip >> 24) & 0xff);
-}
-
-static char proc_lasat_ipbuf[32];
-/* Parsing of IP address */
-int proc_lasat_ip(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int len;
- unsigned int ip;
- char *p, c;
-
- if (!table->data || !table->maxlen || !*lenp ||
- (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
-
- mutex_lock(&lasat_info_mutex);
- if (write) {
- len = 0;
- p = buffer;
- while (len < *lenp) {
- if(get_user(c, p++)) {
- mutex_unlock(&lasat_info_mutex);
- return -EFAULT;
- }
- if (c == 0 || c == '\n')
- break;
- len++;
- }
- if (len >= sizeof(proc_lasat_ipbuf)-1)
- len = sizeof(proc_lasat_ipbuf) - 1;
- if (copy_from_user(proc_lasat_ipbuf, buffer, len))
- {
- mutex_unlock(&lasat_info_mutex);
- return -EFAULT;
- }
- proc_lasat_ipbuf[len] = 0;
- *ppos += *lenp;
- /* Now see if we can convert it to a valid IP */
- ip = in_aton(proc_lasat_ipbuf);
- *(unsigned int *)(table->data) = ip;
- lasat_write_eeprom_info();
- } else {
- ip = *(unsigned int *)(table->data);
- sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d",
- (ip ) & 0xff,
- (ip >> 8) & 0xff,
- (ip >> 16) & 0xff,
- (ip >> 24) & 0xff);
- len = strlen(proc_lasat_ipbuf);
- if (len > *lenp)
- len = *lenp;
- if (len)
- if(copy_to_user(buffer, proc_lasat_ipbuf, len)) {
- mutex_unlock(&lasat_info_mutex);
- return -EFAULT;
- }
- if (len < *lenp) {
- if(put_user('\n', ((char *) buffer) + len)) {
- mutex_unlock(&lasat_info_mutex);
- return -EFAULT;
- }
- len++;
- }
- *lenp = len;
- *ppos += len;
- }
- update_bcastaddr();
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-#endif /* defined(CONFIG_INET) */
-
-static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen)
-{
- int r;
-
- mutex_lock(&lasat_info_mutex);
- r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen);
- if (r < 0) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
-
- if (newval && newlen)
- {
- if (name && *name == LASAT_PRID)
- lasat_board_info.li_eeprom_info.prid = *(int*)newval;
-
- lasat_write_eeprom_info();
- lasat_init_board_info();
- }
- mutex_unlock(&lasat_info_mutex);
-
- return 0;
-}
-
-int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp,
- void *buffer, size_t *lenp, loff_t *ppos)
-{
- int r;
- mutex_lock(&lasat_info_mutex);
- r = proc_dointvec(table, write, filp, buffer, lenp, ppos);
- if ( (!write) || r) {
- mutex_unlock(&lasat_info_mutex);
- return r;
- }
- if (filp && filp->f_path.dentry)
- {
- if (!strcmp(filp->f_path.dentry->d_name.name, "prid"))
- lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid;
- if (!strcmp(filp->f_path.dentry->d_name.name, "debugaccess"))
- lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess;
- }
- lasat_write_eeprom_info();
- mutex_unlock(&lasat_info_mutex);
- return 0;
-}
-
-extern int lasat_boot_to_service;
-
-#ifdef CONFIG_SYSCTL
-
-static ctl_table lasat_table[] = {
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "cpu-hz",
- .data = &lasat_board_info.li_cpu_hz,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "bus-hz",
- .data = &lasat_board_info.li_bus_hz,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "bmid",
- .data = &lasat_board_info.li_bmid,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "prid",
- .data = &lasat_board_info.li_prid,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_lasat_eeprom_value,
- .strategy = &sysctl_lasat_eeprom_value
- },
-#ifdef CONFIG_INET
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "ipaddr",
- .data = &lasat_board_info.li_eeprom_info.ipaddr,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_lasat_ip,
- .strategy = &sysctl_lasat_intvec
- },
- {
- .ctl_name = LASAT_NETMASK,
- .procname = "netmask",
- .data = &lasat_board_info.li_eeprom_info.netmask,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_lasat_ip,
- .strategy = &sysctl_lasat_intvec
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "bcastaddr",
- .data = &lasat_bcastaddr,
- .maxlen = sizeof(lasat_bcastaddr),
- .mode = 0600,
- .proc_handler = &proc_dostring,
- .strategy = &sysctl_string
- },
-#endif
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "passwd_hash",
- .data = &lasat_board_info.li_eeprom_info.passwd_hash,
- .maxlen = sizeof(lasat_board_info.li_eeprom_info.passwd_hash),
- .mode = 0600,
- .proc_handler = &proc_dolasatstring,
- .strategy = &sysctl_lasatstring
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "boot-service",
- .data = &lasat_boot_to_service,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- .strategy = &sysctl_intvec
- },
-#ifdef CONFIG_DS1603
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "rtc",
- .data = &rtctmp,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dolasatrtc,
- .strategy = &sysctl_lasat_rtc
- },
-#endif
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "namestr",
- .data = &lasat_board_info.li_namestr,
- .maxlen = sizeof(lasat_board_info.li_namestr),
- .mode = 0444,
- .proc_handler = &proc_dostring,
- .strategy = &sysctl_string
- },
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "typestr",
- .data = &lasat_board_info.li_typestr,
- .maxlen = sizeof(lasat_board_info.li_typestr),
- .mode = 0444,
- .proc_handler = &proc_dostring,
- .strategy = &sysctl_string
- },
- {}
-};
-
-static ctl_table lasat_root_table[] = {
- {
- .ctl_name = CTL_UNNUMBERED,
- .procname = "lasat",
- .mode = 0555,
- .child = lasat_table
- },
- {}
-};
-
-static int __init lasat_register_sysctl(void)
-{
- struct ctl_table_header *lasat_table_header;
-
- lasat_table_header =
- register_sysctl_table(lasat_root_table);
-
- return 0;
-}
-
-__initcall(lasat_register_sysctl);
-#endif /* CONFIG_SYSCTL */
diff --git a/arch/mips/lasat/sysctl.h b/arch/mips/lasat/sysctl.h
deleted file mode 100644
index 4d139d2adbd..00000000000
--- a/arch/mips/lasat/sysctl.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * LASAT sysctl values
- */
-
-#ifndef _LASAT_SYSCTL_H
-#define _LASAT_SYSCTL_H
-
-/* /proc/sys/lasat */
-enum {
- LASAT_CPU_HZ=1,
- LASAT_BUS_HZ,
- LASAT_MODEL,
- LASAT_PRID,
- LASAT_IPADDR,
- LASAT_NETMASK,
- LASAT_BCAST,
- LASAT_PASSWORD,
- LASAT_SBOOT,
- LASAT_RTC,
- LASAT_NAMESTR,
- LASAT_TYPESTR,
-};
-
-#endif /* _LASAT_SYSCTL_H */
diff --git a/arch/mips/lemote/lm2e/Makefile b/arch/mips/lemote/lm2e/Makefile
new file mode 100644
index 00000000000..fb1b48c48cb
--- /dev/null
+++ b/arch/mips/lemote/lm2e/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Lemote Fulong mini-PC board.
+#
+
+obj-y += setup.o prom.o reset.o irq.o pci.o bonito-irq.o dbg_io.o mem.o
+EXTRA_AFLAGS := $(CFLAGS)
+
diff --git a/arch/mips/lemote/lm2e/bonito-irq.c b/arch/mips/lemote/lm2e/bonito-irq.c
new file mode 100644
index 00000000000..8fc3bce7075
--- /dev/null
+++ b/arch/mips/lemote/lm2e/bonito-irq.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+
+static inline void bonito_irq_enable(unsigned int irq)
+{
+ BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE));
+ mmiowb();
+}
+
+static inline void bonito_irq_disable(unsigned int irq)
+{
+ BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE));
+ mmiowb();
+}
+
+static struct irq_chip bonito_irq_type = {
+ .name = "bonito_irq",
+ .ack = bonito_irq_disable,
+ .mask = bonito_irq_disable,
+ .mask_ack = bonito_irq_disable,
+ .unmask = bonito_irq_enable,
+};
+
+static struct irqaction dma_timeout_irqaction = {
+ .handler = no_action,
+ .name = "dma_timeout",
+};
+
+void bonito_irq_init(void)
+{
+ u32 i;
+
+ for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++) {
+ set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
+ }
+
+ setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction);
+}
diff --git a/arch/mips/lemote/lm2e/dbg_io.c b/arch/mips/lemote/lm2e/dbg_io.c
new file mode 100644
index 00000000000..6c95da3ca76
--- /dev/null
+++ b/arch/mips/lemote/lm2e/dbg_io.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/types.h>
+
+#include <asm/serial.h>
+
+#define UART16550_BAUD_2400 2400
+#define UART16550_BAUD_4800 4800
+#define UART16550_BAUD_9600 9600
+#define UART16550_BAUD_19200 19200
+#define UART16550_BAUD_38400 38400
+#define UART16550_BAUD_57600 57600
+#define UART16550_BAUD_115200 115200
+
+#define UART16550_PARITY_NONE 0
+#define UART16550_PARITY_ODD 0x08
+#define UART16550_PARITY_EVEN 0x18
+#define UART16550_PARITY_MARK 0x28
+#define UART16550_PARITY_SPACE 0x38
+
+#define UART16550_DATA_5BIT 0x0
+#define UART16550_DATA_6BIT 0x1
+#define UART16550_DATA_7BIT 0x2
+#define UART16550_DATA_8BIT 0x3
+
+#define UART16550_STOP_1BIT 0x0
+#define UART16550_STOP_2BIT 0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+#ifdef CONFIG_64BIT
+#define BASE (0xffffffffbfd003f8)
+#else
+#define BASE (0xbfd003f8)
+#endif
+
+#define MAX_BAUD BASE_BAUD
+/* === END OF CONFIG === */
+
+#define REG_OFFSET 1
+
+/* register offset */
+#define OFS_RCV_BUFFER 0
+#define OFS_TRANS_HOLD 0
+#define OFS_SEND_BUFFER 0
+#define OFS_INTR_ENABLE (1*REG_OFFSET)
+#define OFS_INTR_ID (2*REG_OFFSET)
+#define OFS_DATA_FORMAT (3*REG_OFFSET)
+#define OFS_LINE_CONTROL (3*REG_OFFSET)
+#define OFS_MODEM_CONTROL (4*REG_OFFSET)
+#define OFS_RS232_OUTPUT (4*REG_OFFSET)
+#define OFS_LINE_STATUS (5*REG_OFFSET)
+#define OFS_MODEM_STATUS (6*REG_OFFSET)
+#define OFS_RS232_INPUT (6*REG_OFFSET)
+#define OFS_SCRATCH_PAD (7*REG_OFFSET)
+
+#define OFS_DIVISOR_LSB (0*REG_OFFSET)
+#define OFS_DIVISOR_MSB (1*REG_OFFSET)
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y) readb((char *)BASE + (y))
+#define UART16550_WRITE(y, z) writeb(z, (char *)BASE + (y))
+
+void debugInit(u32 baud, u8 data, u8 parity, u8 stop)
+{
+ u32 divisor;
+
+ /* disable interrupts */
+ UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+ /* set up buad rate */
+ /* set DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+ /* set divisor */
+ divisor = MAX_BAUD / baud;
+ UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+ UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+ /* clear DIAB bit */
+ UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+
+ /* set data format */
+ UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized;
+
+u8 getDebugChar(void)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ debugInit(UART16550_BAUD_115200,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0) ;
+ return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+int putDebugChar(u8 byte)
+{
+ if (!remoteDebugInitialized) {
+ remoteDebugInitialized = 1;
+ /*
+ debugInit(UART16550_BAUD_115200,
+ UART16550_DATA_8BIT,
+ UART16550_PARITY_NONE, UART16550_STOP_1BIT); */
+ }
+
+ while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0) ;
+ UART16550_WRITE(OFS_SEND_BUFFER, byte);
+ return 1;
+}
diff --git a/arch/mips/lemote/lm2e/irq.c b/arch/mips/lemote/lm2e/irq.c
new file mode 100644
index 00000000000..05693bceaea
--- /dev/null
+++ b/arch/mips/lemote/lm2e/irq.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/i8259.h>
+#include <asm/mipsregs.h>
+#include <asm/mips-boards/bonito64.h>
+
+
+/*
+ * the first level int-handler will jump here if it is a bonito irq
+ */
+static void bonito_irqdispatch(void)
+{
+ u32 int_status;
+ int i;
+
+ /* workaround the IO dma problem: let cpu looping to allow DMA finish */
+ int_status = BONITO_INTISR;
+ if (int_status & (1 << 10)) {
+ while (int_status & (1 << 10)) {
+ udelay(1);
+ int_status = BONITO_INTISR;
+ }
+ }
+
+ /* Get pending sources, masked by current enables */
+ int_status = BONITO_INTISR & BONITO_INTEN;
+
+ if (int_status != 0) {
+ i = __ffs(int_status);
+ int_status &= ~(1 << i);
+ do_IRQ(BONITO_IRQ_BASE + i);
+ }
+}
+
+static void i8259_irqdispatch(void)
+{
+ int irq;
+
+ irq = i8259_irq();
+ if (irq >= 0) {
+ do_IRQ(irq);
+ } else {
+ spurious_interrupt();
+ }
+
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP7) {
+ do_IRQ(MIPS_CPU_IRQ_BASE + 7);
+ } else if (pending & CAUSEF_IP5) {
+ i8259_irqdispatch();
+ } else if (pending & CAUSEF_IP2) {
+ bonito_irqdispatch();
+ } else {
+ spurious_interrupt();
+ }
+}
+
+static struct irqaction cascade_irqaction = {
+ .handler = no_action,
+ .mask = CPU_MASK_NONE,
+ .name = "cascade",
+};
+
+void __init arch_init_irq(void)
+{
+ extern void bonito_irq_init(void);
+
+ /*
+ * Clear all of the interrupts while we change the able around a bit.
+ * int-handler is not on bootstrap
+ */
+ clear_c0_status(ST0_IM | ST0_BEV);
+ local_irq_disable();
+
+ /* most bonito irq should be level triggered */
+ BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR |
+ BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES;
+ BONITO_INTSTEER = 0;
+
+ /*
+ * Mask out all interrupt by writing "1" to all bit position in
+ * the interrupt reset reg.
+ */
+ BONITO_INTENCLR = ~0;
+
+ /* init all controller
+ * 0-15 ------> i8259 interrupt
+ * 16-23 ------> mips cpu interrupt
+ * 32-63 ------> bonito irq
+ */
+
+ /* Sets the first-level interrupt dispatcher. */
+ mips_cpu_irq_init();
+ init_i8259_irqs();
+ bonito_irq_init();
+
+ /*
+ printk("GPIODATA=%x, GPIOIE=%x\n", BONITO_GPIODATA, BONITO_GPIOIE);
+ printk("INTEN=%x, INTSET=%x, INTCLR=%x, INTISR=%x\n",
+ BONITO_INTEN, BONITO_INTENSET,
+ BONITO_INTENCLR, BONITO_INTISR);
+ */
+
+ /* bonito irq at IP2 */
+ setup_irq(MIPS_CPU_IRQ_BASE + 2, &cascade_irqaction);
+ /* 8259 irq at IP5 */
+ setup_irq(MIPS_CPU_IRQ_BASE + 5, &cascade_irqaction);
+
+}
diff --git a/arch/mips/lemote/lm2e/mem.c b/arch/mips/lemote/lm2e/mem.c
new file mode 100644
index 00000000000..16cd21587d3
--- /dev/null
+++ b/arch/mips/lemote/lm2e/mem.c
@@ -0,0 +1,23 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/fs.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+
+/* override of arch/mips/mm/cache.c: __uncached_access */
+int __uncached_access(struct file *file, unsigned long addr)
+{
+ if (file->f_flags & O_SYNC)
+ return 1;
+
+ /*
+ * On the Lemote Loongson 2e system, the peripheral registers
+ * reside between 0x1000:0000 and 0x2000:0000.
+ */
+ return addr >= __pa(high_memory) ||
+ ((addr >= 0x10000000) && (addr < 0x20000000));
+}
diff --git a/arch/mips/lemote/lm2e/pci.c b/arch/mips/lemote/lm2e/pci.c
new file mode 100644
index 00000000000..1ade1cef389
--- /dev/null
+++ b/arch/mips/lemote/lm2e/pci.c
@@ -0,0 +1,93 @@
+/*
+ * pci.c
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/mips-boards/bonito64.h>
+
+extern struct pci_ops bonito64_pci_ops;
+
+static struct resource loongson2e_pci_mem_resource = {
+ .name = "LOONGSON2E PCI MEM",
+ .start = 0x14000000UL,
+ .end = 0x1fffffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource loongson2e_pci_io_resource = {
+ .name = "LOONGSON2E PCI IO MEM",
+ .start = 0x00004000UL,
+ .end = IO_SPACE_LIMIT,
+ .flags = IORESOURCE_IO,
+};
+
+static struct pci_controller loongson2e_pci_controller = {
+ .pci_ops = &bonito64_pci_ops,
+ .io_resource = &loongson2e_pci_io_resource,
+ .mem_resource = &loongson2e_pci_mem_resource,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static void __init ict_pcimap(void)
+{
+ /*
+ * local to PCI mapping: [256M,512M] -> [256M,512M]; differ from PMON
+ *
+ * CPU address space [256M,448M] is window for accessing pci space
+ * we set pcimap_lo[0,1,2] to map it to pci space [256M,448M]
+ * pcimap: bit18,pcimap_2; bit[17-12],lo2;bit[11-6],lo1;bit[5-0],lo0
+ */
+ /* 1,00 0110 ,0001 01,00 0000 */
+ BONITO_PCIMAP = 0x46140;
+
+ /* 1, 00 0010, 0000,01, 00 0000 */
+ /* BONITO_PCIMAP = 0x42040; */
+
+ /*
+ * PCI to local mapping: [2G,2G+256M] -> [0,256M]
+ */
+ BONITO_PCIBASE0 = 0x80000000;
+ BONITO_PCIBASE1 = 0x00800000;
+ BONITO_PCIBASE2 = 0x90000000;
+
+}
+
+static int __init pcibios_init(void)
+{
+ extern int pci_probe_only;
+ pci_probe_only = 0;
+
+ ict_pcimap();
+ register_pci_controller(&loongson2e_pci_controller);
+
+ return 0;
+}
+
+arch_initcall(pcibios_init);
diff --git a/arch/mips/lemote/lm2e/prom.c b/arch/mips/lemote/lm2e/prom.c
new file mode 100644
index 00000000000..67312d7acf2
--- /dev/null
+++ b/arch/mips/lemote/lm2e/prom.c
@@ -0,0 +1,104 @@
+/*
+ * Based on Ocelot Linux port, which is
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: jsun@mvista.com or jsun@junsun.net
+ *
+ * Copyright 2003 ICT CAS
+ * Author: Michael Guo <guoyi@ict.ac.cn>
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.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/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+extern unsigned long bus_clock;
+extern unsigned long cpu_clock;
+extern unsigned int memsize, highmemsize;
+extern int putDebugChar(unsigned char byte);
+
+static int argc;
+/* pmon passes arguments in 32bit pointers */
+static int *arg;
+static int *env;
+
+const char *get_system_type(void)
+{
+ return "lemote-fulong";
+}
+
+void __init prom_init_cmdline(void)
+{
+ int i;
+ long l;
+
+ /* arg[0] is "g", the rest is boot parameters */
+ arcs_cmdline[0] = '\0';
+ for (i = 1; i < argc; i++) {
+ l = (long)arg[i];
+ if (strlen(arcs_cmdline) + strlen(((char *)l) + 1)
+ >= sizeof(arcs_cmdline))
+ break;
+ strcat(arcs_cmdline, ((char *)l));
+ strcat(arcs_cmdline, " ");
+ }
+}
+
+void __init prom_init(void)
+{
+ long l;
+ argc = fw_arg0;
+ arg = (int *)fw_arg1;
+ env = (int *)fw_arg2;
+
+ mips_machgroup = MACH_GROUP_LEMOTE;
+ mips_machtype = MACH_LEMOTE_FULONG;
+
+ prom_init_cmdline();
+
+ if ((strstr(arcs_cmdline, "console=")) == NULL)
+ strcat(arcs_cmdline, " console=ttyS0,115200");
+ if ((strstr(arcs_cmdline, "root=")) == NULL)
+ strcat(arcs_cmdline, " root=/dev/hda1");
+
+#define parse_even_earlier(res, option, p) \
+do { \
+ if (strncmp(option, (char *)p, strlen(option)) == 0) \
+ res = simple_strtol((char *)p + strlen(option"="), \
+ NULL, 10); \
+} while (0)
+
+ l = (long)*env;
+ while (l != 0) {
+ parse_even_earlier(bus_clock, "busclock", l);
+ parse_even_earlier(cpu_clock, "cpuclock", l);
+ parse_even_earlier(memsize, "memsize", l);
+ parse_even_earlier(highmemsize, "highmemsize", l);
+ env++;
+ l = (long)*env;
+ }
+ if (memsize == 0)
+ memsize = 256;
+
+ pr_info("busclock=%ld, cpuclock=%ld,memsize=%d,highmemsize=%d\n",
+ bus_clock, cpu_clock, memsize, highmemsize);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+void prom_putchar(char c)
+{
+ putDebugChar(c);
+}
diff --git a/arch/mips/lemote/lm2e/reset.c b/arch/mips/lemote/lm2e/reset.c
new file mode 100644
index 00000000000..099387a3827
--- /dev/null
+++ b/arch/mips/lemote/lm2e/reset.c
@@ -0,0 +1,41 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ */
+#include <linux/pm.h>
+
+#include <asm/reboot.h>
+
+static void loongson2e_restart(char *command)
+{
+#ifdef CONFIG_32BIT
+ *(unsigned long *)0xbfe00104 &= ~(1 << 2);
+ *(unsigned long *)0xbfe00104 |= (1 << 2);
+#else
+ *(unsigned long *)0xffffffffbfe00104 &= ~(1 << 2);
+ *(unsigned long *)0xffffffffbfe00104 |= (1 << 2);
+#endif
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+static void loongson2e_halt(void)
+{
+ while (1) ;
+}
+
+static void loongson2e_power_off(void)
+{
+ loongson2e_halt();
+}
+
+void mips_reboot_setup(void)
+{
+ _machine_restart = loongson2e_restart;
+ _machine_halt = loongson2e_halt;
+ pm_power_off = loongson2e_power_off;
+}
diff --git a/arch/mips/lemote/lm2e/setup.c b/arch/mips/lemote/lm2e/setup.c
new file mode 100644
index 00000000000..0e4d1fa572b
--- /dev/null
+++ b/arch/mips/lemote/lm2e/setup.c
@@ -0,0 +1,134 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * setup.c - board dependent boot routines
+ *
+ * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mc146818-time.h>
+#include <asm/time.h>
+#include <asm/wbflush.h>
+
+#ifdef CONFIG_VT
+#include <linux/console.h>
+#include <linux/screen_info.h>
+#endif
+
+extern void mips_reboot_setup(void);
+
+#ifdef CONFIG_64BIT
+#define PTR_PAD(p) ((0xffffffff00000000)|((unsigned long long)(p)))
+#else
+#define PTR_PAD(p) (p)
+#endif
+
+unsigned long cpu_clock;
+unsigned long bus_clock;
+unsigned int memsize;
+unsigned int highmemsize = 0;
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+ setup_irq(MIPS_CPU_IRQ_BASE + 7, irq);
+}
+
+static void __init loongson2e_time_init(void)
+{
+ /* setup mips r4k timer */
+ mips_hpt_frequency = cpu_clock / 2;
+}
+
+static unsigned long __init mips_rtc_get_time(void)
+{
+ return mc146818_get_cmos_time();
+}
+
+void (*__wbflush)(void);
+EXPORT_SYMBOL(__wbflush);
+
+static void wbflush_loongson2e(void)
+{
+ asm(".set\tpush\n\t"
+ ".set\tnoreorder\n\t"
+ ".set mips3\n\t"
+ "sync\n\t"
+ "nop\n\t"
+ ".set\tpop\n\t"
+ ".set mips0\n\t");
+}
+
+void __init plat_mem_setup(void)
+{
+ set_io_port_base(PTR_PAD(0xbfd00000));
+
+ mips_reboot_setup();
+
+ board_time_init = loongson2e_time_init;
+ rtc_mips_get_time = mips_rtc_get_time;
+
+ __wbflush = wbflush_loongson2e;
+
+ add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
+#ifdef CONFIG_64BIT
+ if (highmemsize > 0) {
+ add_memory_region(0x20000000, highmemsize << 20, BOOT_MEM_RAM);
+ }
+#endif
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+
+ screen_info = (struct screen_info) {
+ 0, 25, /* orig-x, orig-y */
+ 0, /* unused */
+ 0, /* orig-video-page */
+ 0, /* orig-video-mode */
+ 80, /* orig-video-cols */
+ 0, 0, 0, /* ega_ax, ega_bx, ega_cx */
+ 25, /* orig-video-lines */
+ VIDEO_TYPE_VGAC, /* orig-video-isVGA */
+ 16 /* orig-video-points */
+ };
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
+#endif
+
+}
diff --git a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile
deleted file mode 100644
index 8b94d4cc5a3..00000000000
--- a/arch/mips/lib-32/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for MIPS-specific library files..
-#
-
-lib-y += watch.o
-
-obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
-obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
-obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
-obj-$(CONFIG_CPU_R10000) += dump_tlb.o
-obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
-obj-$(CONFIG_CPU_R4300) += dump_tlb.o
-obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
-obj-$(CONFIG_CPU_R5000) += dump_tlb.o
-obj-$(CONFIG_CPU_R5432) += dump_tlb.o
-obj-$(CONFIG_CPU_R6000) +=
-obj-$(CONFIG_CPU_R8000) +=
-obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
-obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
-obj-$(CONFIG_CPU_SB1) += dump_tlb.o
-obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
-obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
-obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
deleted file mode 100644
index 6a68deb51aa..00000000000
--- a/arch/mips/lib-32/dump_tlb.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Dump R4x00 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-static inline const char *msk2str(unsigned int mask)
-{
- switch (mask) {
- case PM_4K:
- return "4kb";
- case PM_16K:
- return "16kb";
- case PM_64K:
- return "64kb";
- case PM_256K:
- return "256kb";
-#ifndef CONFIG_CPU_VR41XX
- case PM_1M:
- return "1Mb";
- case PM_4M:
- return "4Mb";
- case PM_16M:
- return "16Mb";
- case PM_64M:
- return "64Mb";
- case PM_256M:
- return "256Mb";
-#endif
- }
-
- return "unknown";
-}
-
-#define BARRIER() \
- __asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- "nop;nop;nop;nop;nop;nop;nop\n\t" \
- ".set\treorder");
-
-void dump_tlb(int first, int last)
-{
- unsigned int pagemask, c0, c1, asid;
- unsigned long long entrylo0, entrylo1;
- unsigned long entryhi;
- int i;
-
- asid = read_c0_entryhi() & 0xff;
-
- printk("\n");
- for (i = first; i <= last; i++) {
- write_c0_index(i);
- BARRIER();
- tlb_read();
- BARRIER();
- pagemask = read_c0_pagemask();
- entryhi = read_c0_entryhi();
- entrylo0 = read_c0_entrylo0();
- entrylo1 = read_c0_entrylo1();
-
- /* Unused entries have a virtual address in KSEG0. */
- if ((entryhi & 0xf0000000) != 0x80000000
- && (entryhi & 0xff) == asid) {
- /*
- * Only print entries in use
- */
- printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
-
- c0 = (entrylo0 >> 3) & 7;
- c1 = (entrylo1 >> 3) & 7;
-
- printk("va=%08lx asid=%02lx\n",
- (entryhi & 0xffffe000), (entryhi & 0xff));
- printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
- (entrylo0 << 6) & PAGE_MASK, c0,
- (entrylo0 & 4) ? 1 : 0,
- (entrylo0 & 2) ? 1 : 0, (entrylo0 & 1));
- printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n",
- (entrylo1 << 6) & PAGE_MASK, c1,
- (entrylo1 & 4) ? 1 : 0,
- (entrylo1 & 2) ? 1 : 0, (entrylo1 & 1));
- printk("\n");
- }
- }
-
- write_c0_entryhi(asid);
-}
-
-void dump_tlb_all(void)
-{
- dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
- int wired;
-
- wired = read_c0_wired();
- printk("Wired: %d", wired);
- dump_tlb(0, read_c0_wired());
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
- unsigned int flags, oldpid;
- int index;
-
- local_irq_save(flags);
- oldpid = read_c0_entryhi() & 0xff;
- BARRIER();
- write_c0_entryhi((addr & PAGE_MASK) | oldpid);
- BARRIER();
- tlb_probe();
- BARRIER();
- index = read_c0_index();
- write_c0_entryhi(oldpid);
- local_irq_restore(flags);
-
- if (index < 0) {
- printk("No entry for address 0x%08lx in TLB\n", addr);
- return;
- }
-
- printk("Entry %d maps address 0x%08lx\n", index, addr);
- dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
- dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
- pgd_t *page_dir, *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte, page;
- unsigned long addr, val;
-
- addr = (unsigned long) address;
-
- printk("Addr == %08lx\n", addr);
- printk("task == %8p\n", t);
- printk("task->mm == %8p\n", t->mm);
- //printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
-
- if (addr > KSEG0) {
- page_dir = pgd_offset_k(0);
- pgd = pgd_offset_k(addr);
- } else if (t->mm) {
- page_dir = pgd_offset(t->mm, 0);
- pgd = pgd_offset(t->mm, addr);
- } else {
- printk("Current thread has no mm\n");
- return;
- }
- printk("page_dir == %08x\n", (unsigned int) page_dir);
- printk("pgd == %08x, ", (unsigned int) pgd);
- pud = pud_offset(pgd, addr);
- printk("pud == %08x, ", (unsigned int) pud);
-
- pmd = pmd_offset(pud, addr);
- printk("pmd == %08x, ", (unsigned int) pmd);
-
- pte = pte_offset(pmd, addr);
- printk("pte == %08x, ", (unsigned int) pte);
-
- page = *pte;
-#ifdef CONFIG_64BIT_PHYS_ADDR
- printk("page == %08Lx\n", pte_val(page));
-#else
- printk("page == %08lx\n", pte_val(page));
-#endif
-
- val = pte_val(page);
- if (val & _PAGE_PRESENT)
- printk("present ");
- if (val & _PAGE_READ)
- printk("read ");
- if (val & _PAGE_WRITE)
- printk("write ");
- if (val & _PAGE_ACCESSED)
- printk("accessed ");
- if (val & _PAGE_MODIFIED)
- printk("modified ");
- if (val & _PAGE_R4KBUG)
- printk("r4kbug ");
- if (val & _PAGE_GLOBAL)
- printk("global ");
- if (val & _PAGE_VALID)
- printk("valid ");
- printk("\n");
-}
-
-void dump_list_current(void *address)
-{
- dump_list_process(current, address);
-}
-
-unsigned int vtop(void *address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned int addr, paddr;
-
- addr = (unsigned long) address;
- pgd = pgd_offset(current->mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- pte = pte_offset(pmd, addr);
- paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
- paddr |= (addr & ~PAGE_MASK);
-
- return paddr;
-}
-
-void dump16(unsigned long *p)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- printk("*%08lx == %08lx, ", (unsigned long) p, *p);
- p++;
- printk("*%08lx == %08lx\n", (unsigned long) p, *p);
- p++;
- }
-}
diff --git a/arch/mips/lib-32/r3k_dump_tlb.c b/arch/mips/lib-32/r3k_dump_tlb.c
deleted file mode 100644
index 4f2cb74f076..00000000000
--- a/arch/mips/lib-32/r3k_dump_tlb.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Dump R3000 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- * Copyright (C) 1999 by Harald Koerfgen
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
-
-void dump_tlb(int first, int last)
-{
- int i;
- unsigned int asid;
- unsigned long entryhi, entrylo0;
-
- asid = read_c0_entryhi() & 0xfc0;
-
- for (i = first; i <= last; i++) {
- write_c0_index(i<<8);
- __asm__ __volatile__(
- ".set\tnoreorder\n\t"
- "tlbr\n\t"
- "nop\n\t"
- ".set\treorder");
- entryhi = read_c0_entryhi();
- entrylo0 = read_c0_entrylo0();
-
- /* Unused entries have a virtual address of KSEG0. */
- if ((entryhi & 0xffffe000) != 0x80000000
- && (entryhi & 0xfc0) == asid) {
- /*
- * Only print entries in use
- */
- printk("Index: %2d ", i);
-
- printk("va=%08lx asid=%08lx"
- " [pa=%06lx n=%d d=%d v=%d g=%d]",
- (entryhi & 0xffffe000),
- entryhi & 0xfc0,
- entrylo0 & PAGE_MASK,
- (entrylo0 & (1 << 11)) ? 1 : 0,
- (entrylo0 & (1 << 10)) ? 1 : 0,
- (entrylo0 & (1 << 9)) ? 1 : 0,
- (entrylo0 & (1 << 8)) ? 1 : 0);
- }
- }
- printk("\n");
-
- write_c0_entryhi(asid);
-}
-
-void dump_tlb_all(void)
-{
- dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
- int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
-
- printk("Wired: %d", wired);
- dump_tlb(0, wired - 1);
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
- unsigned long flags, oldpid;
- int index;
-
- local_irq_save(flags);
- oldpid = read_c0_entryhi() & 0xff;
- write_c0_entryhi((addr & PAGE_MASK) | oldpid);
- tlb_probe();
- index = read_c0_index();
- write_c0_entryhi(oldpid);
- local_irq_restore(flags);
-
- if (index < 0) {
- printk("No entry for address 0x%08lx in TLB\n", addr);
- return;
- }
-
- printk("Entry %d maps address 0x%08lx\n", index, addr);
- dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
- int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
- dump_tlb(wired, current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
- pgd_t *page_dir, *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte, page;
- unsigned int addr;
- unsigned long val;
-
- addr = (unsigned int) address;
-
- printk("Addr == %08x\n", addr);
- printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd);
-
- page_dir = pgd_offset(t->mm, 0);
- printk("page_dir == %08x\n", (unsigned int) page_dir);
-
- pgd = pgd_offset(t->mm, addr);
- printk("pgd == %08x, ", (unsigned int) pgd);
-
- pud = pud_offset(pgd, addr);
- printk("pud == %08x, ", (unsigned int) pud);
-
- pmd = pmd_offset(pud, addr);
- printk("pmd == %08x, ", (unsigned int) pmd);
-
- pte = pte_offset(pmd, addr);
- printk("pte == %08x, ", (unsigned int) pte);
-
- page = *pte;
- printk("page == %08x\n", (unsigned int) pte_val(page));
-
- val = pte_val(page);
- if (val & _PAGE_PRESENT) printk("present ");
- if (val & _PAGE_READ) printk("read ");
- if (val & _PAGE_WRITE) printk("write ");
- if (val & _PAGE_ACCESSED) printk("accessed ");
- if (val & _PAGE_MODIFIED) printk("modified ");
- if (val & _PAGE_GLOBAL) printk("global ");
- if (val & _PAGE_VALID) printk("valid ");
- printk("\n");
-}
-
-void dump_list_current(void *address)
-{
- dump_list_process(current, address);
-}
-
-unsigned int vtop(void *address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned int addr, paddr;
-
- addr = (unsigned long) address;
- pgd = pgd_offset(current->mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- pte = pte_offset(pmd, addr);
- paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
- paddr |= (addr & ~PAGE_MASK);
-
- return paddr;
-}
-
-void dump16(unsigned long *p)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- printk("*%08lx == %08lx, ", (unsigned long)p, *p);
- p++;
- printk("*%08lx == %08lx\n", (unsigned long)p, *p);
- p++;
- }
-}
diff --git a/arch/mips/lib-32/watch.S b/arch/mips/lib-32/watch.S
deleted file mode 100644
index 808b3af1a60..00000000000
--- a/arch/mips/lib-32/watch.S
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Kernel debug stuff to use the Watch registers.
- * Useful to find stack overflows, dangling pointers etc.
- *
- * Copyright (C) 1995, 1996, 1999 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-
- .set noreorder
-/*
- * Parameter: a0 - logic address to watch
- * Currently only KSEG0 addresses are allowed!
- * a1 - set bit #1 to trap on load references
- * bit #0 to trap on store references
- * Results : none
- */
- LEAF(__watch_set)
- li t0, 0x80000000
- subu a0, t0
- ori a0, 7
- xori a0, 7
- or a0, a1
- mtc0 a0, CP0_WATCHLO
- sw a0, watch_savelo
-
- jr ra
- mtc0 zero, CP0_WATCHHI
- END(__watch_set)
-
-/*
- * Parameter: none
- * Results : none
- */
- LEAF(__watch_clear)
- jr ra
- mtc0 zero, CP0_WATCHLO
- END(__watch_clear)
-
-/*
- * Parameter: none
- * Results : none
- */
- LEAF(__watch_reenable)
- lw t0, watch_savelo
- jr ra
- mtc0 t0, CP0_WATCHLO
- END(__watch_reenable)
-
-/*
- * Saved value of the c0_watchlo register for watch_reenable()
- */
- .data
-watch_savelo: .word 0
- .text
diff --git a/arch/mips/lib-64/Makefile b/arch/mips/lib-64/Makefile
deleted file mode 100644
index 8b94d4cc5a3..00000000000
--- a/arch/mips/lib-64/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile for MIPS-specific library files..
-#
-
-lib-y += watch.o
-
-obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
-obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
-obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
-obj-$(CONFIG_CPU_R10000) += dump_tlb.o
-obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
-obj-$(CONFIG_CPU_R4300) += dump_tlb.o
-obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
-obj-$(CONFIG_CPU_R5000) += dump_tlb.o
-obj-$(CONFIG_CPU_R5432) += dump_tlb.o
-obj-$(CONFIG_CPU_R6000) +=
-obj-$(CONFIG_CPU_R8000) +=
-obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
-obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
-obj-$(CONFIG_CPU_SB1) += dump_tlb.o
-obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
-obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
-obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
deleted file mode 100644
index 594df1a05ec..00000000000
--- a/arch/mips/lib-64/dump_tlb.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Dump R4x00 TLB for debugging purposes.
- *
- * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
- * Copyright (C) 1999 by Silicon Graphics, Inc.
- */
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-static inline const char *msk2str(unsigned int mask)
-{
- switch (mask) {
- case PM_4K: return "4kb";
- case PM_16K: return "16kb";
- case PM_64K: return "64kb";
- case PM_256K: return "256kb";
-#ifndef CONFIG_CPU_VR41XX
- case PM_1M: return "1Mb";
- case PM_4M: return "4Mb";
- case PM_16M: return "16Mb";
- case PM_64M: return "64Mb";
- case PM_256M: return "256Mb";
-#endif
- }
-
- return "unknown";
-}
-
-#define BARRIER() \
- __asm__ __volatile__( \
- ".set\tnoreorder\n\t" \
- "nop;nop;nop;nop;nop;nop;nop\n\t" \
- ".set\treorder");
-
-void dump_tlb(int first, int last)
-{
- unsigned long s_entryhi, entryhi, entrylo0, entrylo1, asid;
- unsigned int s_index, pagemask, c0, c1, i;
-
- s_entryhi = read_c0_entryhi();
- s_index = read_c0_index();
- asid = s_entryhi & 0xff;
-
- for (i = first; i <= last; i++) {
- write_c0_index(i);
- BARRIER();
- tlb_read();
- BARRIER();
- pagemask = read_c0_pagemask();
- entryhi = read_c0_entryhi();
- entrylo0 = read_c0_entrylo0();
- entrylo1 = read_c0_entrylo1();
-
- /* Unused entries have a virtual address of CKSEG0. */
- if ((entryhi & ~0x1ffffUL) != CKSEG0
- && (entryhi & 0xff) == asid) {
- /*
- * Only print entries in use
- */
- printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
-
- c0 = (entrylo0 >> 3) & 7;
- c1 = (entrylo1 >> 3) & 7;
-
- printk("va=%011lx asid=%02lx\n",
- (entryhi & ~0x1fffUL),
- entryhi & 0xff);
- printk("\t[pa=%011lx c=%d d=%d v=%d g=%ld] ",
- (entrylo0 << 6) & PAGE_MASK, c0,
- (entrylo0 & 4) ? 1 : 0,
- (entrylo0 & 2) ? 1 : 0,
- (entrylo0 & 1));
- printk("[pa=%011lx c=%d d=%d v=%d g=%ld]\n",
- (entrylo1 << 6) & PAGE_MASK, c1,
- (entrylo1 & 4) ? 1 : 0,
- (entrylo1 & 2) ? 1 : 0,
- (entrylo1 & 1));
- }
- }
- printk("\n");
-
- write_c0_entryhi(s_entryhi);
- write_c0_index(s_index);
-}
-
-void dump_tlb_all(void)
-{
- dump_tlb(0, current_cpu_data.tlbsize - 1);
-}
-
-void dump_tlb_wired(void)
-{
- int wired;
-
- wired = read_c0_wired();
- printk("Wired: %d", wired);
- dump_tlb(0, read_c0_wired());
-}
-
-void dump_tlb_addr(unsigned long addr)
-{
- unsigned int flags, oldpid;
- int index;
-
- local_irq_save(flags);
- oldpid = read_c0_entryhi() & 0xff;
- BARRIER();
- write_c0_entryhi((addr & PAGE_MASK) | oldpid);
- BARRIER();
- tlb_probe();
- BARRIER();
- index = read_c0_index();
- write_c0_entryhi(oldpid);
- local_irq_restore(flags);
-
- if (index < 0) {
- printk("No entry for address 0x%08lx in TLB\n", addr);
- return;
- }
-
- printk("Entry %d maps address 0x%08lx\n", index, addr);
- dump_tlb(index, index);
-}
-
-void dump_tlb_nonwired(void)
-{
- dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1);
-}
-
-void dump_list_process(struct task_struct *t, void *address)
-{
- pgd_t *page_dir, *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte, page;
- unsigned long addr, val;
-
- addr = (unsigned long) address;
-
- printk("Addr == %08lx\n", addr);
- printk("tasks->mm.pgd == %08lx\n", (unsigned long) t->mm->pgd);
-
- page_dir = pgd_offset(t->mm, 0UL);
- printk("page_dir == %016lx\n", (unsigned long) page_dir);
-
- pgd = pgd_offset(t->mm, addr);
- printk("pgd == %016lx\n", (unsigned long) pgd);
-
- pud = pud_offset(pgd, addr);
- printk("pud == %016lx\n", (unsigned long) pud);
-
- pmd = pmd_offset(pud, addr);
- printk("pmd == %016lx\n", (unsigned long) pmd);
-
- pte = pte_offset(pmd, addr);
- printk("pte == %016lx\n", (unsigned long) pte);
-
- page = *pte;
- printk("page == %08lx\n", pte_val(page));
-
- val = pte_val(page);
- if (val & _PAGE_PRESENT) printk("present ");
- if (val & _PAGE_READ) printk("read ");
- if (val & _PAGE_WRITE) printk("write ");
- if (val & _PAGE_ACCESSED) printk("accessed ");
- if (val & _PAGE_MODIFIED) printk("modified ");
- if (val & _PAGE_R4KBUG) printk("r4kbug ");
- if (val & _PAGE_GLOBAL) printk("global ");
- if (val & _PAGE_VALID) printk("valid ");
- printk("\n");
-}
-
-void dump_list_current(void *address)
-{
- dump_list_process(current, address);
-}
-
-unsigned long vtop(void *address)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long addr, paddr;
-
- addr = (unsigned long) address;
- pgd = pgd_offset(current->mm, addr);
- pud = pud_offset(pgd, addr);
- pmd = pmd_offset(pud, addr);
- pte = pte_offset(pmd, addr);
- paddr = (CKSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
- paddr |= (addr & ~PAGE_MASK);
-
- return paddr;
-}
-
-void dump16(unsigned long *p)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- printk("*%08lx == %08lx, ", (unsigned long)p, *p);
- p++;
- printk("*%08lx == %08lx\n", (unsigned long)p, *p);
- p++;
- }
-}
diff --git a/arch/mips/lib-64/watch.S b/arch/mips/lib-64/watch.S
deleted file mode 100644
index f9143401369..00000000000
--- a/arch/mips/lib-64/watch.S
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Kernel debug stuff to use the Watch registers.
- * Useful to find stack overflows, dangling pointers etc.
- *
- * Copyright (C) 1995, 1996, 1999, 2001 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-
- .set noreorder
-/*
- * Parameter: a0 - physical address to watch
- * a1 - set bit #1 to trap on load references
- * bit #0 to trap on store references
- * Results : none
- */
- LEAF(__watch_set)
- ori a0, 7
- xori a0, 7
- or a0, a1
- mtc0 a0, CP0_WATCHLO
- sd a0, watch_savelo
- dsrl32 a0, a0, 0
-
- jr ra
- mtc0 zero, CP0_WATCHHI
- END(__watch_set)
-
-/*
- * Parameter: none
- * Results : none
- */
- LEAF(__watch_clear)
- jr ra
- mtc0 zero, CP0_WATCHLO
- END(__watch_clear)
-
-/*
- * Parameter: none
- * Results : none
- */
- LEAF(__watch_reenable)
- ld t0, watch_savelo
- jr ra
- mtc0 t0, CP0_WATCHLO
- END(__watch_reenable)
-
-/*
- * Saved value of the c0_watchlo register for watch_reenable()
- */
- .local watch_savelo
- .comm watch_savelo, 8, 8
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 5dad13efba7..91ed1eb3310 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -8,5 +8,24 @@ lib-y += csum_partial.o memcpy.o memcpy-inatomic.o memset.o strlen_user.o \
obj-y += iomap.o
obj-$(CONFIG_PCI) += iomap-pci.o
+obj-$(CONFIG_CPU_LOONGSON2) += dump_tlb.o
+obj-$(CONFIG_CPU_MIPS32) += dump_tlb.o
+obj-$(CONFIG_CPU_MIPS64) += dump_tlb.o
+obj-$(CONFIG_CPU_NEVADA) += dump_tlb.o
+obj-$(CONFIG_CPU_R10000) += dump_tlb.o
+obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
+obj-$(CONFIG_CPU_R4300) += dump_tlb.o
+obj-$(CONFIG_CPU_R4X00) += dump_tlb.o
+obj-$(CONFIG_CPU_R5000) += dump_tlb.o
+obj-$(CONFIG_CPU_R5432) += dump_tlb.o
+obj-$(CONFIG_CPU_R6000) +=
+obj-$(CONFIG_CPU_R8000) +=
+obj-$(CONFIG_CPU_RM7000) += dump_tlb.o
+obj-$(CONFIG_CPU_RM9000) += dump_tlb.o
+obj-$(CONFIG_CPU_SB1) += dump_tlb.o
+obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
+obj-$(CONFIG_CPU_TX49XX) += dump_tlb.o
+obj-$(CONFIG_CPU_VR41XX) += dump_tlb.o
+
# libgcc-style stuff needed in the kernel
-lib-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
+obj-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
new file mode 100644
index 00000000000..465ff0ec85b
--- /dev/null
+++ b/arch/mips/lib/dump_tlb.c
@@ -0,0 +1,101 @@
+/*
+ * Dump R4x00 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbdebug.h>
+
+static inline const char *msk2str(unsigned int mask)
+{
+ switch (mask) {
+ case PM_4K: return "4kb";
+ case PM_16K: return "16kb";
+ case PM_64K: return "64kb";
+ case PM_256K: return "256kb";
+#ifndef CONFIG_CPU_VR41XX
+ case PM_1M: return "1Mb";
+ case PM_4M: return "4Mb";
+ case PM_16M: return "16Mb";
+ case PM_64M: return "64Mb";
+ case PM_256M: return "256Mb";
+#endif
+ }
+ return "";
+}
+
+#define BARRIER() \
+ __asm__ __volatile__( \
+ ".set\tnoreorder\n\t" \
+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
+ ".set\treorder");
+
+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;
+
+ s_entryhi = read_c0_entryhi();
+ s_index = read_c0_index();
+ asid = s_entryhi & 0xff;
+
+ for (i = first; i <= last; i++) {
+ write_c0_index(i);
+ BARRIER();
+ tlb_read();
+ BARRIER();
+ pagemask = read_c0_pagemask();
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+ entrylo1 = read_c0_entrylo1();
+
+ /* Unused entries have a virtual address of CKSEG0. */
+ if ((entryhi & ~0x1ffffUL) != CKSEG0
+ && (entryhi & 0xff) == asid) {
+#ifdef CONFIG_32BIT
+ int width = 8;
+#else
+ int width = 11;
+#endif
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d pgmask=%s ", i, msk2str(pagemask));
+
+ c0 = (entrylo0 >> 3) & 7;
+ c1 = (entrylo1 >> 3) & 7;
+
+ printk("va=%0*lx asid=%02lx\n",
+ width, (entryhi & ~0x1fffUL),
+ entryhi & 0xff);
+ printk("\t[pa=%0*llx c=%d d=%d v=%d g=%d] ",
+ width,
+ (entrylo0 << 6) & PAGE_MASK, c0,
+ (entrylo0 & 4) ? 1 : 0,
+ (entrylo0 & 2) ? 1 : 0,
+ (entrylo0 & 1) ? 1 : 0);
+ printk("[pa=%0*llx c=%d d=%d v=%d g=%d]\n",
+ width,
+ (entrylo1 << 6) & PAGE_MASK, c1,
+ (entrylo1 & 4) ? 1 : 0,
+ (entrylo1 & 2) ? 1 : 0,
+ (entrylo1 & 1) ? 1 : 0);
+ }
+ }
+ printk("\n");
+
+ write_c0_entryhi(s_entryhi);
+ write_c0_index(s_index);
+}
+
+void dump_tlb_all(void)
+{
+ dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c
new file mode 100644
index 00000000000..9cee907975a
--- /dev/null
+++ b/arch/mips/lib/r3k_dump_tlb.c
@@ -0,0 +1,63 @@
+/*
+ * Dump R3000 TLB for debugging purposes.
+ *
+ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 1999 by Harald Koerfgen
+ */
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbdebug.h>
+
+extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */
+
+static void dump_tlb(int first, int last)
+{
+ int i;
+ unsigned int asid;
+ unsigned long entryhi, entrylo0;
+
+ asid = read_c0_entryhi() & 0xfc0;
+
+ for (i = first; i <= last; i++) {
+ write_c0_index(i<<8);
+ __asm__ __volatile__(
+ ".set\tnoreorder\n\t"
+ "tlbr\n\t"
+ "nop\n\t"
+ ".set\treorder");
+ entryhi = read_c0_entryhi();
+ entrylo0 = read_c0_entrylo0();
+
+ /* Unused entries have a virtual address of KSEG0. */
+ if ((entryhi & 0xffffe000) != 0x80000000
+ && (entryhi & 0xfc0) == asid) {
+ /*
+ * Only print entries in use
+ */
+ printk("Index: %2d ", i);
+
+ printk("va=%08lx asid=%08lx"
+ " [pa=%06lx n=%d d=%d v=%d g=%d]",
+ (entryhi & 0xffffe000),
+ entryhi & 0xfc0,
+ entrylo0 & PAGE_MASK,
+ (entrylo0 & (1 << 11)) ? 1 : 0,
+ (entrylo0 & (1 << 10)) ? 1 : 0,
+ (entrylo0 & (1 << 9)) ? 1 : 0,
+ (entrylo0 & (1 << 8)) ? 1 : 0);
+ }
+ }
+ printk("\n");
+
+ write_c0_entryhi(asid);
+}
+
+void dump_tlb_all(void)
+{
+ dump_tlb(0, current_cpu_data.tlbsize - 1);
+}
diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c
index e9ff258ef02..e2ff6072b5a 100644
--- a/arch/mips/lib/ucmpdi2.c
+++ b/arch/mips/lib/ucmpdi2.c
@@ -2,7 +2,7 @@
#include "libgcc.h"
-word_type __ucmpdi2 (unsigned long a, unsigned long b)
+word_type __ucmpdi2 (unsigned long long a, unsigned long long b)
{
const DWunion au = {.ll = a};
const DWunion bu = {.ll = b};
diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c
index 2388f7f3ffd..58d14f4d934 100644
--- a/arch/mips/lib/uncached.c
+++ b/arch/mips/lib/uncached.c
@@ -12,6 +12,7 @@
#include <asm/addrspace.h>
#include <asm/bug.h>
+#include <asm/cacheflush.h>
#ifndef CKSEG2
#define CKSEG2 CKSSEG
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 80531b35cd6..17419e11eca 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -35,6 +35,7 @@
* better performance by compiling with -msoft-float!
*/
#include <linux/sched.h>
+#include <linux/debugfs.h>
#include <asm/inst.h>
#include <asm/bootinfo.h>
@@ -204,7 +205,7 @@ static int isBranchInstr(mips_instruction * i)
static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
{
mips_instruction ir;
- void * emulpc, *contpc;
+ unsigned long emulpc, contpc;
unsigned int cond;
if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
@@ -229,7 +230,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
* Linux MIPS branch emulator operates on context, updating the
* cp0_epc.
*/
- emulpc = (void *) (xcp->cp0_epc + 4); /* Snapshot emulation target */
+ emulpc = xcp->cp0_epc + 4; /* Snapshot emulation target */
if (__compute_return_epc(xcp)) {
#ifdef CP1DBG
@@ -243,12 +244,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
return SIGBUS;
}
/* __compute_return_epc() will have updated cp0_epc */
- contpc = (void *) xcp->cp0_epc;
+ contpc = xcp->cp0_epc;
/* In order not to confuse ptrace() et al, tweak context */
- xcp->cp0_epc = (unsigned long) emulpc - 4;
+ xcp->cp0_epc = emulpc - 4;
} else {
- emulpc = (void *) xcp->cp0_epc;
- contpc = (void *) (xcp->cp0_epc + 4);
+ emulpc = xcp->cp0_epc;
+ contpc = xcp->cp0_epc + 4;
}
emul:
@@ -426,8 +427,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
* instruction
*/
xcp->cp0_epc += 4;
- contpc = (void *)
- (xcp->cp0_epc +
+ contpc = (xcp->cp0_epc +
(MIPSInst_SIMM(ir) << 2));
if (get_user(ir,
@@ -461,7 +461,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
* Single step the non-cp1
* instruction in the dslot
*/
- return mips_dsemul(xcp, ir, (unsigned long) contpc);
+ return mips_dsemul(xcp, ir, contpc);
}
else {
/* branch not taken */
@@ -520,7 +520,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
}
/* we did it !! */
- xcp->cp0_epc = (unsigned long) contpc;
+ xcp->cp0_epc = contpc;
xcp->cp0_cause &= ~CAUSEF_BD;
return 0;
@@ -1277,3 +1277,36 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
return sig;
}
+
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *mips_debugfs_dir;
+static int __init debugfs_fpuemu(void)
+{
+ struct dentry *d, *dir;
+ int i;
+ static struct {
+ const char *name;
+ unsigned int *v;
+ } vars[] __initdata = {
+ { "emulated", &fpuemustats.emulated },
+ { "loads", &fpuemustats.loads },
+ { "stores", &fpuemustats.stores },
+ { "cp1ops", &fpuemustats.cp1ops },
+ { "cp1xops", &fpuemustats.cp1xops },
+ { "errors", &fpuemustats.errors },
+ };
+
+ if (!mips_debugfs_dir)
+ return -ENODEV;
+ dir = debugfs_create_dir("fpuemustats", mips_debugfs_dir);
+ if (IS_ERR(dir))
+ return PTR_ERR(dir);
+ for (i = 0; i < ARRAY_SIZE(vars); i++) {
+ d = debugfs_create_u32(vars[i].name, S_IRUGO, dir, vars[i].v);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ }
+ return 0;
+}
+__initcall(debugfs_fpuemu);
+#endif
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index ea6ba724848..653e325849e 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -54,8 +54,7 @@ struct emuframe {
int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
{
extern asmlinkage void handle_dsemulret(void);
- mips_instruction *dsemul_insns;
- struct emuframe *fr;
+ struct emuframe __user *fr;
int err;
if (ir == 0) { /* a nop is easy */
@@ -87,8 +86,8 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
*/
/* Ensure that the two instructions are in the same cache line */
- dsemul_insns = (mips_instruction *) ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
- fr = (struct emuframe *) dsemul_insns;
+ fr = (struct emuframe __user *)
+ ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
/* Verify that the stack pointer is not competely insane */
if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))
@@ -113,12 +112,13 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
int do_dsemulret(struct pt_regs *xcp)
{
- struct emuframe *fr;
+ struct emuframe __user *fr;
unsigned long epc;
u32 insn, cookie;
int err = 0;
- fr = (struct emuframe *) (xcp->cp0_epc - sizeof(mips_instruction));
+ fr = (struct emuframe __user *)
+ (xcp->cp0_epc - sizeof(mips_instruction));
/*
* If we can't even access the area, something is very wrong, but we'll
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
index dfa0acbd7fc..6c8f0255e85 100644
--- a/arch/mips/mips-boards/atlas/atlas_int.c
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -189,7 +189,7 @@ asmlinkage void plat_irq_dispatch(void)
if (irq == MIPSCPU_INT_ATLAS)
atlas_hw0_irqdispatch();
else if (irq >= 0)
- do_IRQ(MIPSCPU_INT_BASE + irq);
+ do_IRQ(MIPS_CPU_IRQ_BASE + irq);
else
spurious_interrupt();
}
@@ -248,25 +248,24 @@ void __init arch_init_irq(void)
case MIPS_REVISION_CORID_CORE_24K:
case MIPS_REVISION_CORID_CORE_EMUL_MSC:
if (cpu_has_veic)
- init_msc_irqs (MSC01E_INT_BASE,
+ init_msc_irqs (MSC01E_INT_BASE, MSC01E_INT_BASE,
msc_eicirqmap, msc_nr_eicirqs);
else
- init_msc_irqs (MSC01C_INT_BASE,
+ init_msc_irqs (MSC01E_INT_BASE, MSC01C_INT_BASE,
msc_irqmap, msc_nr_irqs);
}
-
if (cpu_has_veic) {
set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch);
setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq);
} else if (cpu_has_vint) {
set_vi_handler (MIPSCPU_INT_ATLAS, atlas_hw0_irqdispatch);
#ifdef CONFIG_MIPS_MT_SMTC
- setup_irq_smtc (MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS,
+ setup_irq_smtc (MIPS_CPU_IRQ_BASE + MIPSCPU_INT_ATLAS,
&atlasirq, (0x100 << MIPSCPU_INT_ATLAS));
#else /* Not SMTC */
- setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+ setup_irq(MIPS_CPU_IRQ_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
#endif /* CONFIG_MIPS_MT_SMTC */
} else
- setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+ setup_irq(MIPS_CPU_IRQ_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
}
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index 0c6b0ce1502..1cc6ebbedfd 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -48,6 +48,8 @@ const char *get_system_type(void)
return "MIPS Atlas";
}
+const char display_string[] = " LINUX ON ATLAS ";
+
void __init plat_mem_setup(void)
{
mips_pcibios_init();
diff --git a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c
index 548dbe5ce7c..5d600054090 100644
--- a/arch/mips/mips-boards/generic/display.c
+++ b/arch/mips/mips-boards/generic/display.c
@@ -19,9 +19,14 @@
*/
#include <linux/compiler.h>
+#include <linux/timer.h>
#include <asm/io.h>
#include <asm/mips-boards/generic.h>
+extern const char display_string[];
+static unsigned int display_count;
+static unsigned int max_display_count;
+
void mips_display_message(const char *str)
{
static unsigned int __iomem *display = NULL;
@@ -37,3 +42,22 @@ void mips_display_message(const char *str)
writel(' ', display + i);
}
}
+
+static void scroll_display_message(unsigned long data);
+static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0);
+
+static void scroll_display_message(unsigned long data)
+{
+ mips_display_message(&display_string[display_count++]);
+ if (display_count == max_display_count)
+ display_count = 0;
+
+ mod_timer(&mips_scroll_timer, jiffies + HZ);
+}
+
+void mips_scroll_message(void)
+{
+ del_timer_sync(&mips_scroll_timer);
+ max_display_count = strlen(display_string) + 1 - 8;
+ mod_timer(&mips_scroll_timer, jiffies + 1);
+}
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index 88e9c2a7a2f..4eabc1eadd2 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -57,7 +57,8 @@ int *_prom_argv, *_prom_envp;
int init_debug = 0;
-unsigned int mips_revision_corid;
+int mips_revision_corid;
+int mips_revision_sconid;
/* Bonito64 system controller register base. */
unsigned long _pcictrl_bonito;
@@ -275,13 +276,38 @@ void __init prom_init(void)
else
mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
}
- switch(mips_revision_corid) {
+
+ mips_revision_sconid = MIPS_REVISION_SCONID;
+ if (mips_revision_sconid == MIPS_REVISION_SCON_OTHER) {
+ switch (mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ mips_revision_sconid = MIPS_REVISION_SCON_GT64120;
+ break;
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ mips_revision_sconid = MIPS_REVISION_SCON_BONITO;
+ break;
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_FPGA3:
+ case MIPS_REVISION_CORID_CORE_24K:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ mips_revision_sconid = MIPS_REVISION_SCON_SOCIT;
+ break;
+ default:
+ mips_display_message("CC Error");
+ while (1); /* We die here... */
+ }
+ }
+
+ switch (mips_revision_sconid) {
u32 start, map, mask, data;
- case MIPS_REVISION_CORID_QED_RM5261:
- case MIPS_REVISION_CORID_CORE_LV:
- case MIPS_REVISION_CORID_CORE_FPGA:
- case MIPS_REVISION_CORID_CORE_FPGAR2:
+ case MIPS_REVISION_SCON_GT64120:
/*
* Setup the North bridge to do Master byte-lane swapping
* when running in bigendian.
@@ -305,9 +331,7 @@ void __init prom_init(void)
set_io_port_base(MALTA_GT_PORT_BASE);
break;
- case MIPS_REVISION_CORID_CORE_EMUL_BON:
- case MIPS_REVISION_CORID_BONITO64:
- case MIPS_REVISION_CORID_CORE_20K:
+ case MIPS_REVISION_SCON_BONITO:
_pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
/*
@@ -334,13 +358,10 @@ void __init prom_init(void)
set_io_port_base(MALTA_BONITO_PORT_BASE);
break;
- case MIPS_REVISION_CORID_CORE_MSC:
- case MIPS_REVISION_CORID_CORE_FPGA2:
- case MIPS_REVISION_CORID_CORE_FPGA3:
- case MIPS_REVISION_CORID_CORE_24K:
- case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ case MIPS_REVISION_SCON_SOCIT:
+ case MIPS_REVISION_SCON_ROCIT:
_pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
-
+ mips_pci_controller:
mb();
MSC_READ(MSC01_PCI_CFG, data);
MSC_WRITE(MSC01_PCI_CFG, data & ~MSC01_PCI_CFG_EN_BIT);
@@ -374,10 +395,15 @@ void __init prom_init(void)
set_io_port_base(MALTA_MSC_PORT_BASE);
break;
+ case MIPS_REVISION_SCON_SOCITSC:
+ case MIPS_REVISION_SCON_SOCITSCP:
+ _pcictrl_msc = (unsigned long)ioremap(MIPS_SOCITSC_PCI_REG_BASE, 0x2000);
+ goto mips_pci_controller;
+
default:
- /* Unknown Core card */
- mips_display_message("CC Error");
- while(1); /* We die here... */
+ /* Unknown system controller */
+ mips_display_message("SC Error");
+ while (1); /* We die here... */
}
#endif
board_nmi_handler_setup = mips_nmi_setup;
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
index f98d60f7865..c9852206890 100644
--- a/arch/mips/mips-boards/generic/pci.c
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -92,11 +92,8 @@ void __init mips_pcibios_init(void)
struct pci_controller *controller;
resource_size_t start, end, map, start1, end1, map1, map2, map3, mask;
- switch (mips_revision_corid) {
- case MIPS_REVISION_CORID_QED_RM5261:
- case MIPS_REVISION_CORID_CORE_LV:
- case MIPS_REVISION_CORID_CORE_FPGA:
- case MIPS_REVISION_CORID_CORE_FPGAR2:
+ switch (mips_revision_sconid) {
+ case MIPS_REVISION_SCON_GT64120:
/*
* Due to a bug in the Galileo system controller, we need
* to setup the PCI BAR for the Galileo internal registers.
@@ -161,9 +158,7 @@ void __init mips_pcibios_init(void)
controller = &gt64120_controller;
break;
- case MIPS_REVISION_CORID_BONITO64:
- case MIPS_REVISION_CORID_CORE_20K:
- case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ case MIPS_REVISION_SCON_BONITO:
/* Set up resource ranges from the controller's registers. */
map = BONITO_PCIMAP;
map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >>
@@ -195,11 +190,10 @@ void __init mips_pcibios_init(void)
controller = &bonito64_controller;
break;
- case MIPS_REVISION_CORID_CORE_MSC:
- case MIPS_REVISION_CORID_CORE_FPGA2:
- case MIPS_REVISION_CORID_CORE_FPGA3:
- case MIPS_REVISION_CORID_CORE_24K:
- case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ case MIPS_REVISION_SCON_SOCIT:
+ case MIPS_REVISION_SCON_ROCIT:
+ case MIPS_REVISION_SCON_SOCITSC:
+ case MIPS_REVISION_SCON_SOCITSCP:
/* Set up resource ranges from the controller's registers. */
MSC_READ(MSC01_PCI_SC2PMBASL, start);
MSC_READ(MSC01_PCI_SC2PMMSKL, mask);
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index df2a2bd3aa5..c45d556aa96 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -53,40 +53,18 @@
unsigned long cpu_khz;
-#if defined(CONFIG_MIPS_ATLAS)
-static char display_string[] = " LINUX ON ATLAS ";
-#endif
-#if defined(CONFIG_MIPS_MALTA)
-#if defined(CONFIG_MIPS_MT_SMTC)
-static char display_string[] = " SMTC LINUX ON MALTA ";
-#else
-static char display_string[] = " LINUX ON MALTA ";
-#endif /* CONFIG_MIPS_MT_SMTC */
-#endif
-#if defined(CONFIG_MIPS_SEAD)
-static char display_string[] = " LINUX ON SEAD ";
-#endif
-static unsigned int display_count;
-#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
-
-#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
-
-static unsigned int timer_tick_count;
static int mips_cpu_timer_irq;
+extern int cp0_perfcount_irq;
extern void smtc_timer_broadcast(int);
-static inline void scroll_display_message(void)
+static void mips_timer_dispatch(void)
{
- if ((timer_tick_count++ % HZ) == 0) {
- mips_display_message(&display_string[display_count++]);
- if (display_count == MAX_DISPLAY_COUNT)
- display_count = 0;
- }
+ do_IRQ(mips_cpu_timer_irq);
}
-static void mips_timer_dispatch(void)
+static void mips_perf_dispatch(void)
{
- do_IRQ(mips_cpu_timer_irq);
+ do_IRQ(cp0_perfcount_irq);
}
/*
@@ -96,6 +74,24 @@ extern int null_perf_irq(void);
extern int (*perf_irq)(void);
+/*
+ * Possibly handle a performance counter interrupt.
+ * Return true if the timer interrupt should not be checked
+ */
+static inline int handle_perf_irq (int r2)
+{
+ /*
+ * The performance counter overflow interrupt may be shared with the
+ * timer interrupt (cp0_perfcount_irq < 0). If it is and a
+ * performance counter has overflowed (perf_irq() == IRQ_HANDLED)
+ * and we can't reliably determine if a counter interrupt has also
+ * happened (!r2) then don't check for a timer interrupt.
+ */
+ return (cp0_perfcount_irq < 0) &&
+ perf_irq() == IRQ_HANDLED &&
+ !r2;
+}
+
irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
{
int cpu = smp_processor_id();
@@ -114,25 +110,13 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
* the general MIPS timer_interrupt routine.
*/
- int vpflags;
-
/*
* We could be here due to timer interrupt,
* perf counter overflow, or both.
*/
- if (read_c0_cause() & (1 << 26))
- perf_irq();
+ (void) handle_perf_irq(1);
if (read_c0_cause() & (1 << 30)) {
- /* If timer interrupt, make it de-assert */
- write_c0_compare (read_c0_count() - 1);
- /*
- * DVPE is necessary so long as cross-VPE interrupts
- * are done via read-modify-write of Cause register.
- */
- vpflags = dvpe();
- clear_c0_cause(CPUCTR_IMASKBIT);
- evpe(vpflags);
/*
* There are things we only want to do once per tick
* in an "MP" system. One TC of each VPE will take
@@ -141,34 +125,30 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
* the tick on VPE 0 to run the full timer_interrupt().
*/
if (cpu_data[cpu].vpe_id == 0) {
- timer_interrupt(irq, NULL);
- smtc_timer_broadcast(cpu_data[cpu].vpe_id);
- scroll_display_message();
+ timer_interrupt(irq, NULL);
} else {
write_c0_compare(read_c0_count() +
(mips_hpt_frequency/HZ));
local_timer_interrupt(irq, dev_id);
- smtc_timer_broadcast(cpu_data[cpu].vpe_id);
}
+ smtc_timer_broadcast(cpu_data[cpu].vpe_id);
}
#else /* CONFIG_MIPS_MT_SMTC */
int r2 = cpu_has_mips_r2;
+ if (handle_perf_irq(r2))
+ goto out;
+
+ if (r2 && ((read_c0_cause() & (1 << 30)) == 0))
+ goto out;
+
if (cpu == 0) {
/*
* CPU 0 handles the global timer interrupt job and process
* accounting resets count/compare registers to trigger next
* timer int.
*/
- if (!r2 || (read_c0_cause() & (1 << 26)))
- if (perf_irq())
- goto out;
-
- /* we keep interrupt disabled all the time */
- if (!r2 || (read_c0_cause() & (1 << 30)))
- timer_interrupt(irq, NULL);
-
- scroll_display_message();
+ timer_interrupt(irq, NULL);
} else {
/* Everyone else needs to reset the timer int here as
ll_local_timer_interrupt doesn't */
@@ -262,6 +242,44 @@ void __init mips_time_init(void)
(est_freq%1000000)*100/1000000);
cpu_khz = est_freq / 1000;
+
+ mips_scroll_message();
+}
+
+irqreturn_t mips_perf_interrupt(int irq, void *dev_id)
+{
+ return perf_irq();
+}
+
+static struct irqaction perf_irqaction = {
+ .handler = mips_perf_interrupt,
+ .flags = IRQF_DISABLED | IRQF_PERCPU,
+ .name = "performance",
+};
+
+void __init plat_perf_setup(struct irqaction *irq)
+{
+ cp0_perfcount_irq = -1;
+
+#ifdef MSC01E_INT_BASE
+ if (cpu_has_veic) {
+ set_vi_handler (MSC01E_INT_PERFCTR, mips_perf_dispatch);
+ cp0_perfcount_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
+ } else
+#endif
+ if (cp0_perfcount_irq >= 0) {
+ if (cpu_has_vint)
+ set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
+#ifdef CONFIG_MIPS_MT_SMTC
+ setup_irq_smtc(cp0_perfcount_irq, irq,
+ 0x100 << cp0_perfcount_irq);
+#else
+ setup_irq(cp0_perfcount_irq, irq);
+#endif /* CONFIG_MIPS_MT_SMTC */
+#ifdef CONFIG_SMP
+ set_irq_handler(cp0_perfcount_irq, handle_percpu_irq);
+#endif
+ }
}
void __init plat_timer_setup(struct irqaction *irq)
@@ -270,29 +288,25 @@ void __init plat_timer_setup(struct irqaction *irq)
if (cpu_has_veic) {
set_vi_handler (MSC01E_INT_CPUCTR, mips_timer_dispatch);
mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
- } else
+ }
+ else
#endif
{
if (cpu_has_vint)
- set_vi_handler (MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
- mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
+ set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
+ mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
}
-
/* we are using the cpu counter for timer interrupts */
irq->handler = mips_timer_interrupt; /* we use our own handler */
#ifdef CONFIG_MIPS_MT_SMTC
- setup_irq_smtc(mips_cpu_timer_irq, irq, CPUCTR_IMASKBIT);
+ setup_irq_smtc(mips_cpu_timer_irq, irq, 0x100 << cp0_compare_irq);
#else
setup_irq(mips_cpu_timer_irq, irq);
#endif /* CONFIG_MIPS_MT_SMTC */
-
#ifdef CONFIG_SMP
- /* irq_desc(riptor) is a global resource, when the interrupt overlaps
- on seperate cpu's the first one tries to handle the second interrupt.
- The effect is that the int remains disabled on the second cpu.
- Mark the interrupt with IRQ_PER_CPU to avoid any confusion */
- irq_desc[mips_cpu_timer_irq].status |= IRQ_PER_CPU;
set_irq_handler(mips_cpu_timer_irq, handle_percpu_irq);
#endif
+
+ plat_perf_setup(&perf_irqaction);
}
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
index 377d9e8f250..a242b0fc377 100644
--- a/arch/mips/mips-boards/malta/Makefile
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -19,6 +19,7 @@
# under Linux.
#
-obj-y := malta_int.o malta_setup.o
+obj-y := malta_int.o malta_platform.o malta_setup.o
+
obj-$(CONFIG_MTD) += malta_mtd.o
obj-$(CONFIG_MIPS_MT_SMTC) += malta_smtc.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index 1cd830e3d93..c78d4834960 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -53,25 +53,19 @@ static inline int mips_pcibios_iack(void)
* Determine highest priority pending interrupt by performing
* a PCI Interrupt Acknowledge cycle.
*/
- switch(mips_revision_corid) {
- case MIPS_REVISION_CORID_CORE_MSC:
- case MIPS_REVISION_CORID_CORE_FPGA2:
- case MIPS_REVISION_CORID_CORE_FPGA3:
- case MIPS_REVISION_CORID_CORE_24K:
- case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ switch (mips_revision_sconid) {
+ case MIPS_REVISION_SCON_SOCIT:
+ case MIPS_REVISION_SCON_ROCIT:
+ case MIPS_REVISION_SCON_SOCITSC:
+ case MIPS_REVISION_SCON_SOCITSCP:
MSC_READ(MSC01_PCI_IACK, irq);
irq &= 0xff;
break;
- case MIPS_REVISION_CORID_QED_RM5261:
- case MIPS_REVISION_CORID_CORE_LV:
- case MIPS_REVISION_CORID_CORE_FPGA:
- case MIPS_REVISION_CORID_CORE_FPGAR2:
+ case MIPS_REVISION_SCON_GT64120:
irq = GT_READ(GT_PCI0_IACK_OFS);
irq &= 0xff;
break;
- case MIPS_REVISION_CORID_BONITO64:
- case MIPS_REVISION_CORID_CORE_20K:
- case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ case MIPS_REVISION_SCON_BONITO:
/* The following will generate a PCI IACK cycle on the
* Bonito controller. It's a little bit kludgy, but it
* was the easiest way to implement it in hardware at
@@ -89,7 +83,7 @@ static inline int mips_pcibios_iack(void)
BONITO_PCIMAP_CFG = 0;
break;
default:
- printk("Unknown Core card, don't know the system controller.\n");
+ printk("Unknown system controller.\n");
return -1;
}
return irq;
@@ -144,27 +138,21 @@ static void corehi_irqdispatch(void)
Do it for the others too.
*/
- switch(mips_revision_corid) {
- case MIPS_REVISION_CORID_CORE_MSC:
- case MIPS_REVISION_CORID_CORE_FPGA2:
- case MIPS_REVISION_CORID_CORE_FPGA3:
- case MIPS_REVISION_CORID_CORE_24K:
- case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ switch (mips_revision_sconid) {
+ case MIPS_REVISION_SCON_SOCIT:
+ case MIPS_REVISION_SCON_ROCIT:
+ case MIPS_REVISION_SCON_SOCITSC:
+ case MIPS_REVISION_SCON_SOCITSCP:
ll_msc_irq();
break;
- case MIPS_REVISION_CORID_QED_RM5261:
- case MIPS_REVISION_CORID_CORE_LV:
- case MIPS_REVISION_CORID_CORE_FPGA:
- case MIPS_REVISION_CORID_CORE_FPGAR2:
+ case MIPS_REVISION_SCON_GT64120:
intrcause = GT_READ(GT_INTRCAUSE_OFS);
datalo = GT_READ(GT_CPUERR_ADDRLO_OFS);
datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
printk("GT_INTRCAUSE = %08x\n", intrcause);
printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo);
break;
- case MIPS_REVISION_CORID_BONITO64:
- case MIPS_REVISION_CORID_CORE_20K:
- case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ case MIPS_REVISION_SCON_BONITO:
pcibadaddr = BONITO_PCIBADADDR;
pcimstat = BONITO_PCIMSTAT;
intisr = BONITO_INTISR;
@@ -269,7 +257,7 @@ asmlinkage void plat_irq_dispatch(void)
if (irq == MIPSCPU_INT_I8259A)
malta_hw0_irqdispatch();
else if (irq > 0)
- do_IRQ(MIPSCPU_INT_BASE + irq);
+ do_IRQ(MIPS_CPU_IRQ_BASE + irq);
else
spurious_interrupt();
}
@@ -338,17 +326,17 @@ void __init arch_init_irq(void)
set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch);
#ifdef CONFIG_MIPS_MT_SMTC
- setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq,
+ setup_irq_smtc (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq,
(0x100 << MIPSCPU_INT_I8259A));
- setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI,
+ setup_irq_smtc (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI,
&corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
#else /* Not SMTC */
- setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
- setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+ setup_irq (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
+ setup_irq (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
#endif /* CONFIG_MIPS_MT_SMTC */
}
else {
- setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
- setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+ setup_irq (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq);
+ setup_irq (MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
}
}
diff --git a/arch/mips/mips-boards/malta/malta_platform.c b/arch/mips/mips-boards/malta/malta_platform.c
new file mode 100644
index 00000000000..83b9bab3cd3
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_platform.c
@@ -0,0 +1,65 @@
+/*
+ * 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) 2007 MIPS Technologies, Inc.
+ * written by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * Probe driver for the Malta's UART ports:
+ *
+ * o 2 ports in the SMC SuperIO
+ * o 1 port in the CBUS UART, a discrete 16550 which normally is only used
+ * for bringups.
+ *
+ * We don't use 8250_platform.c on Malta as it would result in the CBUS
+ * UART becoming ttyS0.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+
+#define SMC_PORT(base, int) \
+{ \
+ .iobase = base, \
+ .irq = int, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_PORT, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, \
+ .regshift = 0, \
+}
+
+#define CBUS_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
+
+static struct plat_serial8250_port uart8250_data[] = {
+ SMC_PORT(0x3F8, 4),
+ SMC_PORT(0x2F8, 3),
+ {
+ .mapbase = 0x1f000900, /* The CBUS UART */
+ .irq = MIPS_CPU_IRQ_BASE + 2,
+ .uartclk = 3686400, /* Twice the usual clk! */
+ .iotype = UPIO_MEM32,
+ .flags = CBUS_UART_FLAGS,
+ .regshift = 3,
+ },
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM2,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ return platform_device_register(&uart8250_device);
+}
+
+module_init(uart8250_init);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for the Malta CBUS UART");
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index 7873932532a..8f1b78dfd89 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -56,6 +56,12 @@ const char *get_system_type(void)
return "MIPS Malta";
}
+#if defined(CONFIG_MIPS_MT_SMTC)
+const char display_string[] = " SMTC LINUX ON MALTA ";
+#else
+const char display_string[] = " LINUX ON MALTA ";
+#endif /* CONFIG_MIPS_MT_SMTC */
+
#ifdef CONFIG_BLK_DEV_FD
void __init fd_activate(void)
{
@@ -97,9 +103,7 @@ void __init plat_mem_setup(void)
kgdb_config ();
#endif
- if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) ||
- (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) ||
- (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) {
+ if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) {
char *argptr;
argptr = prom_getcmdline();
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
index c4b9de3a7f2..9ca0f82f136 100644
--- a/arch/mips/mips-boards/sead/sead_int.c
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -106,7 +106,7 @@ asmlinkage void plat_irq_dispatch(void)
irq = irq_ffs(pending);
if (irq >= 0)
- do_IRQ(MIPSCPU_INT_BASE + irq);
+ do_IRQ(MIPS_CPU_IRQ_BASE + irq);
else
spurious_interrupt();
}
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
index a189dec7c7b..bb801409d39 100644
--- a/arch/mips/mips-boards/sead/sead_setup.c
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -43,6 +43,8 @@ const char *get_system_type(void)
return "MIPS SEAD";
}
+const char display_string[] = " LINUX ON SEAD ";
+
void __init plat_mem_setup(void)
{
ioport_resource.end = 0x7fffffff;
@@ -66,7 +68,7 @@ static void __init serial_init(void)
#else
s.iobase = SEAD_UART0_REGS_BASE+3;
#endif
- s.irq = MIPSCPU_INT_BASE + MIPSCPU_INT_UART0;
+ s.irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_UART0;
s.uartclk = SEAD_BASE_BAUD * 16;
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ;
s.iotype = UPIO_PORT;
diff --git a/arch/mips/mips-boards/sim/sim_int.c b/arch/mips/mips-boards/sim/sim_int.c
index 15ac0655c1f..766e0159ee5 100644
--- a/arch/mips/mips-boards/sim/sim_int.c
+++ b/arch/mips/mips-boards/sim/sim_int.c
@@ -77,7 +77,7 @@ asmlinkage void plat_irq_dispatch(void)
irq = irq_ffs(pending);
if (irq > 0)
- do_IRQ(MIPSCPU_INT_BASE + irq);
+ do_IRQ(MIPS_CPU_IRQ_BASE + irq);
else
spurious_interrupt();
}
diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mipssim/Makefile
index dc0bfda1142..dc0bfda1142 100644
--- a/arch/mips/mips-boards/sim/Makefile
+++ b/arch/mips/mipssim/Makefile
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c
index c63021a5dc6..c63021a5dc6 100644
--- a/arch/mips/mips-boards/sim/sim_cmdline.c
+++ b/arch/mips/mipssim/sim_cmdline.c
diff --git a/arch/mips/mips-boards/sim/sim_console.c b/arch/mips/mipssim/sim_console.c
index de595a9ccb2..a2f41672cd5 100644
--- a/arch/mips/mips-boards/sim/sim_console.c
+++ b/arch/mips/mipssim/sim_console.c
@@ -18,8 +18,8 @@
* written by Ralf Baechle
*/
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/serial_reg.h>
-#include <asm/io.h>
static inline unsigned int serial_in(int offset)
{
diff --git a/arch/mips/mipssim/sim_int.c b/arch/mips/mipssim/sim_int.c
new file mode 100644
index 00000000000..5cbc3509ab5
--- /dev/null
+++ b/arch/mips/mipssim/sim_int.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 1999, 2005 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <asm/mips-boards/simint.h>
+#include <asm/irq_cpu.h>
+
+static inline int clz(unsigned long x)
+{
+ __asm__ (
+ " .set push \n"
+ " .set mips32 \n"
+ " clz %0, %1 \n"
+ " .set pop \n"
+ : "=r" (x)
+ : "r" (x));
+
+ return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ return -clz(pending) + 31 - CAUSEB_IP;
+#else
+ unsigned int a0 = 7;
+ unsigned int t0;
+
+ t0 = s0 & 0xf000;
+ t0 = t0 < 1;
+ t0 = t0 << 2;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0xc000;
+ t0 = t0 < 1;
+ t0 = t0 << 1;
+ a0 = a0 - t0;
+ s0 = s0 << t0;
+
+ t0 = s0 & 0x8000;
+ t0 = t0 < 1;
+ /* t0 = t0 << 2; */
+ a0 = a0 - t0;
+ /* s0 = s0 << t0; */
+
+ return a0;
+#endif
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+ int irq;
+
+ irq = irq_ffs(pending);
+
+ if (irq > 0)
+ do_IRQ(MIPS_CPU_IRQ_BASE + irq);
+ else
+ spurious_interrupt();
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init();
+}
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mipssim/sim_mem.c
index e408ef0bcd6..2312483eb83 100644
--- a/arch/mips/mips-boards/sim/sim_mem.c
+++ b/arch/mips/mipssim/sim_mem.c
@@ -95,7 +95,7 @@ void __init prom_meminit(void)
size = p->size;
add_memory_region(base, size, type);
- p++;
+ p++;
}
}
diff --git a/arch/mips/mips-boards/sim/sim_platform.c b/arch/mips/mipssim/sim_platform.c
index 53210a8c5de..53210a8c5de 100644
--- a/arch/mips/mips-boards/sim/sim_platform.c
+++ b/arch/mips/mipssim/sim_platform.c
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
index b705f09e57c..60e66906be6 100644
--- a/arch/mips/mips-boards/sim/sim_setup.c
+++ b/arch/mips/mipssim/sim_setup.c
@@ -19,18 +19,18 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
#include <linux/ioport.h>
+#include <linux/serial.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <asm/cpu.h>
#include <asm/bootinfo.h>
-#include <asm/irq.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/prom.h>
-#include <asm/serial.h>
-#include <asm/io.h>
#include <asm/time.h>
#include <asm/mips-boards/sim.h>
#include <asm/mips-boards/simint.h>
@@ -62,7 +62,7 @@ void __init plat_mem_setup(void)
#endif
}
-void prom_init(void)
+void __init prom_init(void)
{
set_io_port_base(0xbfd00000);
@@ -84,7 +84,7 @@ static void __init serial_init(void)
/* hardware int 4 - the serial int, is CPU int 6
but poll for now */
s.irq = 0;
- s.uartclk = BASE_BAUD * 16;
+ s.uartclk = 1843200;
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
s.iotype = UPIO_PORT;
s.regshift = 0;
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mipssim/sim_smp.c
index cb47863ecf1..38fa807b99f 100644
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ b/arch/mips/mipssim/sim_smp.c
@@ -22,13 +22,13 @@
#include <linux/sched.h>
#include <linux/cpumask.h>
#include <linux/interrupt.h>
+#include <linux/smp.h>
+
#include <asm/atomic.h>
#include <asm/cpu.h>
#include <asm/processor.h>
#include <asm/system.h>
-#include <asm/hardirq.h>
#include <asm/mmu_context.h>
-#include <asm/smp.h>
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/smtc_ipi.h>
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -73,11 +73,19 @@ void prom_init_secondary(void)
#endif /* CONFIG_MIPS_MT_SMTC */
}
+void plat_smp_setup(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+ if (read_c0_config3() & (1 << 2))
+ mipsmt_build_cpu_map(0);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
/*
* Platform SMP pre-initialization
*/
-void prom_prepare_cpus(unsigned int max_cpus)
+void plat_prepare_cpus(unsigned int max_cpus)
{
#ifdef CONFIG_MIPS_MT_SMTC
/*
@@ -85,8 +93,8 @@ void prom_prepare_cpus(unsigned int max_cpus)
* but it may be multithreaded.
*/
- if (read_c0_config3() & (1<<2)) {
- mipsmt_prepare_cpus(max_cpus);
+ if (read_c0_config3() & (1 << 2)) {
+ mipsmt_prepare_cpus();
}
#endif /* CONFIG_MIPS_MT_SMTC */
}
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mipssim/sim_time.c
index d3a21c74151..a0f5a5dca1b 100644
--- a/arch/mips/mips-boards/sim/sim_time.c
+++ b/arch/mips/mipssim/sim_time.c
@@ -5,10 +5,9 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>
+#include <linux/smp.h>
#include <linux/timex.h>
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
#include <asm/hardirq.h>
#include <asm/div64.h>
#include <asm/cpu.h>
@@ -16,7 +15,6 @@
#include <asm/irq.h>
#include <asm/mc146818-time.h>
#include <asm/msc01_ic.h>
-#include <asm/smp.h>
#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/prom.h>
@@ -37,8 +35,7 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
#ifndef CONFIG_MIPS_MT_SMTC
if (cpu == 0) {
timer_interrupt(irq, dev_id);
- }
- else {
+ } else {
/* Everyone else needs to reset the timer int here as
ll_local_timer_interrupt doesn't */
/*
@@ -71,13 +68,15 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
int vpflags = dvpe();
write_c0_compare (read_c0_count() - 1);
- clear_c0_cause(0x100 << MIPSCPU_INT_CPUCTR);
- set_c0_status(0x100 << MIPSCPU_INT_CPUCTR);
+ clear_c0_cause(0x100 << cp0_compare_irq);
+ set_c0_status(0x100 << cp0_compare_irq);
irq_enable_hazard();
evpe(vpflags);
- if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id);
- else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+ if (cpu_data[cpu].vpe_id == 0)
+ timer_interrupt(irq, dev_id);
+ else
+ write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
smtc_timer_broadcast(cpu_data[cpu].vpe_id);
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -85,7 +84,8 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id)
/*
* every CPU should do profiling and process accounting
*/
- local_timer_interrupt (irq, dev_id);
+ local_timer_interrupt (irq, dev_id);
+
return IRQ_HANDLED;
#else
return timer_interrupt (irq, dev_id);
@@ -152,17 +152,15 @@ void __init sim_time_init(void)
local_irq_save(flags);
-
- /* Set Data mode - binary. */
+ /* Set Data mode - binary. */
CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
-
est_freq = estimate_cpu_frequency ();
- printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
- (est_freq%1000000)*100/1000000);
+ printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
+ (est_freq % 1000000) * 100 / 1000000);
- cpu_khz = est_freq / 1000;
+ cpu_khz = est_freq / 1000;
local_irq_restore(flags);
}
@@ -180,11 +178,10 @@ void __init plat_timer_setup(struct irqaction *irq)
if (cpu_has_veic) {
set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
- }
- else {
+ } else {
if (cpu_has_vint)
- set_vi_handler(MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
- mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
+ set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
+ mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
}
/* we are using the cpu counter for timer interrupts */
diff --git a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile
index 293697b1560..19a0e544c4e 100644
--- a/arch/mips/mm/Makefile
+++ b/arch/mips/mm/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_32BIT) += ioremap.o pgtable-32.o
obj-$(CONFIG_64BIT) += pgtable-64.o
obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_CPU_LOONGSON2) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index df04a315d83..be96231dccb 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -335,6 +335,10 @@ static void r4k_flush_cache_all(void)
static inline void local_r4k___flush_cache_all(void * args)
{
+#if defined(CONFIG_CPU_LOONGSON2)
+ r4k_blast_scache();
+ return;
+#endif
r4k_blast_dcache();
r4k_blast_icache();
@@ -848,6 +852,24 @@ static void __init probe_pcache(void)
c->options |= MIPS_CPU_PREFETCH;
break;
+ case CPU_LOONGSON2:
+ icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
+ c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
+ if (prid & 0x3)
+ c->icache.ways = 4;
+ else
+ c->icache.ways = 2;
+ c->icache.waybit = 0;
+
+ dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
+ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
+ if (prid & 0x3)
+ c->dcache.ways = 4;
+ else
+ c->dcache.ways = 2;
+ c->dcache.waybit = 0;
+ break;
+
default:
if (!(config & MIPS_CONF_M))
panic("Don't know how to probe P-caches on this cpu.");
@@ -963,6 +985,14 @@ static void __init probe_pcache(void)
break;
}
+#ifdef CONFIG_CPU_LOONGSON2
+ /*
+ * LOONGSON2 has 4 way icache, but when using indexed cache op,
+ * one op will act on all 4 ways
+ */
+ c->icache.ways = 1;
+#endif
+
printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
icache_size >> 10,
cpu_has_vtag_icache ? "virtually tagged" : "physically tagged",
@@ -1036,6 +1066,24 @@ static int __init probe_scache(void)
return 1;
}
+#if defined(CONFIG_CPU_LOONGSON2)
+static void __init loongson2_sc_init(void)
+{
+ struct cpuinfo_mips *c = &current_cpu_data;
+
+ scache_size = 512*1024;
+ c->scache.linesz = 32;
+ c->scache.ways = 4;
+ c->scache.waybit = 0;
+ c->scache.waysize = scache_size / (c->scache.ways);
+ c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
+ pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
+ scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
+
+ c->options |= MIPS_CPU_INCLUSIVE_CACHES;
+}
+#endif
+
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
extern int mips_sc_init(void);
@@ -1085,6 +1133,12 @@ static void __init setup_scache(void)
#endif
return;
+#if defined(CONFIG_CPU_LOONGSON2)
+ case CPU_LOONGSON2:
+ loongson2_sc_init();
+ return;
+#endif
+
default:
if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
c->isa_level == MIPS_CPU_ISA_M32R2 ||
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 9ea460b16bd..6f9bd7fbd48 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -476,7 +476,7 @@ static __init void probe_cache_sizes(void)
* memory management function pointers, as well as initialize
* the caches and tlbs
*/
-void sb1_cache_init(void)
+void __init sb1_cache_init(void)
{
extern char except_vec2_sb1;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index abf99b1eba1..81f925a9a73 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -6,6 +6,8 @@
* Copyright (C) 1994 - 2003, 07 by Ralf Baechle (ralf@linux-mips.org)
* Copyright (C) 2007 MIPS Technologies, Inc.
*/
+#include <linux/fs.h>
+#include <linux/fcntl.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -164,3 +166,11 @@ void __init cpu_cache_init(void)
panic(cache_panic);
}
+
+int __weak __uncached_access(struct file *file, unsigned long addr)
+{
+ if (file->f_flags & O_SYNC)
+ return 1;
+
+ return addr >= __pa(high_memory);
+}
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index f0eb29917d9..76903c72764 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -168,8 +168,9 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
addr = (unsigned long) page_address(sg->page);
if (!plat_device_is_coherent(dev) && addr)
__dma_sync(addr + sg->offset, sg->length, direction);
- sg->dma_address = plat_map_dma_mem_page(dev, sg->page) +
- sg->offset;
+ sg->dma_address = plat_map_dma_mem(dev,
+ (void *)(addr + sg->offset),
+ sg->length);
}
return nents;
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 65160d4984d..dcd6913dc1f 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -48,6 +48,22 @@ extern void build_tlb_refill_handler(void);
#endif /* CONFIG_MIPS_MT_SMTC */
+#if defined(CONFIG_CPU_LOONGSON2)
+/*
+ * LOONGSON2 has a 4 entry itlb which is a subset of dtlb,
+ * unfortrunately, itlb is not totally transparent to software.
+ */
+#define FLUSH_ITLB write_c0_diag(4);
+
+#define FLUSH_ITLB_VM(vma) { if ((vma)->vm_flags & VM_EXEC) write_c0_diag(4); }
+
+#else
+
+#define FLUSH_ITLB
+#define FLUSH_ITLB_VM(vma)
+
+#endif
+
void local_flush_tlb_all(void)
{
unsigned long flags;
@@ -73,6 +89,7 @@ void local_flush_tlb_all(void)
}
tlbw_use_hazard();
write_c0_entryhi(old_ctx);
+ FLUSH_ITLB;
EXIT_CRITICAL(flags);
}
@@ -136,6 +153,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
} else {
drop_mmu_context(mm, cpu);
}
+ FLUSH_ITLB;
EXIT_CRITICAL(flags);
}
}
@@ -178,6 +196,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
} else {
local_flush_tlb_all();
}
+ FLUSH_ITLB;
EXIT_CRITICAL(flags);
}
@@ -210,6 +229,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
finish:
write_c0_entryhi(oldpid);
+ FLUSH_ITLB_VM(vma);
EXIT_CRITICAL(flags);
}
}
@@ -241,7 +261,7 @@ void local_flush_tlb_one(unsigned long page)
tlbw_use_hazard();
}
write_c0_entryhi(oldpid);
-
+ FLUSH_ITLB;
EXIT_CRITICAL(flags);
}
@@ -293,6 +313,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
else
tlb_write_indexed();
tlbw_use_hazard();
+ FLUSH_ITLB_VM(vma);
EXIT_CRITICAL(flags);
}
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index e7149290d1c..4ec0964b839 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -893,6 +893,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l,
case CPU_4KSC:
case CPU_20KC:
case CPU_25KF:
+ case CPU_LOONGSON2:
tlbw(p);
break;
@@ -1276,7 +1277,8 @@ static void __init build_r4000_tlb_refill_handler(void)
* need three, with the second nop'ed and the third being
* unused.
*/
-#ifdef CONFIG_32BIT
+ /* Loongson2 ebase is different than r4k, we have more space */
+#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
if ((p - tlb_handler) > 64)
panic("TLB refill handler space exceeded");
#else
@@ -1289,7 +1291,7 @@ static void __init build_r4000_tlb_refill_handler(void)
/*
* Now fold the handler in the TLB refill handler space.
*/
-#ifdef CONFIG_32BIT
+#if defined(CONFIG_32BIT) || defined(CONFIG_CPU_LOONGSON2)
f = final_handler;
/* Simplest case, just copy the handler. */
copy_handler(relocs, labels, tlb_handler, p, f);
@@ -1336,7 +1338,7 @@ static void __init build_r4000_tlb_refill_handler(void)
final_len);
f = final_handler;
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2)
if (final_len > 32)
final_len = 64;
else
diff --git a/arch/mips/momentum/ocelot_3/Makefile b/arch/mips/momentum/ocelot_3/Makefile
deleted file mode 100644
index d5a090a85a1..00000000000
--- a/arch/mips/momentum/ocelot_3/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-3 board.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-obj-y += irq.o platform.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/irq.c b/arch/mips/momentum/ocelot_3/irq.c
deleted file mode 100644
index 3862d1d1add..00000000000
--- a/arch/mips/momentum/ocelot_3/irq.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-static struct irqaction cascade_mv64340 = {
- no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
-};
-
-void __init arch_init_irq(void)
-{
- /*
- * Clear all of the interrupts while we change the able around a bit.
- * int-handler is not on bootstrap
- */
- clear_c0_status(ST0_IM | ST0_BEV);
-
- rm7k_cpu_irq_init();
-
- /* set up the cascading interrupts */
- setup_irq(8, &cascade_mv64340); /* unmask intControl IM8, IRQ 9 */
- mv64340_irq_init(16);
-
- set_c0_status(ST0_IM); /* IE in the status register */
-
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_cause() & read_c0_status();
-
- if (pending & STATUSF_IP0)
- do_IRQ(0);
- else if (pending & STATUSF_IP1)
- do_IRQ(1);
- else if (pending & STATUSF_IP2)
- do_IRQ(2);
- else if (pending & STATUSF_IP3)
- do_IRQ(3);
- else if (pending & STATUSF_IP4)
- do_IRQ(4);
- else if (pending & STATUSF_IP5)
- do_IRQ(5);
- else if (pending & STATUSF_IP6)
- do_IRQ(6);
- else if (pending & STATUSF_IP7)
- do_IRQ(7);
- else {
- /*
- * Now look at the extended interrupts
- */
- pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
-
- if (pending & STATUSF_IP8)
- ll_mv64340_irq();
- else
- spurious_interrupt();
- }
-}
diff --git a/arch/mips/momentum/ocelot_3/platform.c b/arch/mips/momentum/ocelot_3/platform.c
deleted file mode 100644
index 44e4c3fc740..00000000000
--- a/arch/mips/momentum/ocelot_3/platform.c
+++ /dev/null
@@ -1,208 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "ocelot_3_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
- [0] = {
- .name = "ethernet shared base",
- .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
- .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
- MV643XX_ETH_SHARED_REGS_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
- .name = MV643XX_ETH_SHARED_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
- .resource = mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE 0xfe000000UL
-#define MV_SRAM_SIZE (256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-#define MV64x60_IRQ_ETH_2 50
-
-static struct resource mv64x60_eth0_resources[] = {
- [0] = {
- .name = "eth0 irq",
- .start = MV64x60_IRQ_ETH_0,
- .end = MV64x60_IRQ_ETH_0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
- .port_number = 0,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH0,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
- .name = MV643XX_ETH_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv64x60_eth0_resources),
- .resource = mv64x60_eth0_resources,
- .dev = {
- .platform_data = &eth0_pd,
- },
-};
-
-static struct resource mv64x60_eth1_resources[] = {
- [0] = {
- .name = "eth1 irq",
- .start = MV64x60_IRQ_ETH_1,
- .end = MV64x60_IRQ_ETH_1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
- .port_number = 1,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH1,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
- .name = MV643XX_ETH_NAME,
- .id = 1,
- .num_resources = ARRAY_SIZE(mv64x60_eth1_resources),
- .resource = mv64x60_eth1_resources,
- .dev = {
- .platform_data = &eth1_pd,
- },
-};
-
-static struct resource mv64x60_eth2_resources[] = {
- [0] = {
- .name = "eth2 irq",
- .start = MV64x60_IRQ_ETH_2,
- .end = MV64x60_IRQ_ETH_2,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth2_pd = {
- .port_number = 2,
-};
-
-static struct platform_device eth2_device = {
- .name = MV643XX_ETH_NAME,
- .id = 2,
- .num_resources = ARRAY_SIZE(mv64x60_eth2_resources),
- .resource = mv64x60_eth2_resources,
- .dev = {
- .platform_data = &eth2_pd,
- },
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
- &mv643xx_eth_shared_device,
- &eth0_device,
- &eth1_device,
- &eth2_device,
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
- /* place the data */
- OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock on */
- OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock off and read-strobe */
- OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
- /* return the data */
- return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
- u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int i,j;
-
- for (i = 0; i < 12; i++)
- exchange_bit(read_opcode[i], 1);
-
- for (j = 0; j < 6; j++) {
- dest[j] = 0;
- for (i = 0; i < 8; i++) {
- dest[j] <<= 1;
- dest[j] |= exchange_bit(0, 1);
- }
- }
-
- /* turn off CS */
- exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
- unsigned int add)
-{
- int i;
-
- BUG_ON(add >= 256);
-
- for (i = ETH_ALEN; i >= 0; i--) {
- dst[i] = src[i] + add;
- add = dst[i] < src[i]; /* compute carry */
- }
-
- WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
- unsigned char mac[ETH_ALEN];
- int ret;
-
- get_mac(mac);
- eth_mac_add(eth0_pd.mac_addr, mac, 0);
- eth_mac_add(eth1_pd.mac_addr, mac, 1);
- eth_mac_add(eth2_pd.mac_addr, mac, 2);
- ret = platform_add_devices(mv643xx_eth_pd_devs,
- ARRAY_SIZE(mv643xx_eth_pd_devs));
-
- return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/ocelot_3/prom.c b/arch/mips/momentum/ocelot_3/prom.c
deleted file mode 100644
index 8e02df63578..00000000000
--- a/arch/mips/momentum/ocelot_3/prom.c
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- */
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-#include "ocelot_3_fpga.h"
-
-struct callvectors* debug_vectors;
-extern unsigned long marvell_base;
-extern unsigned long cpu_clock;
-
-const char *get_system_type(void)
-{
- return "Momentum Ocelot-3";
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
- addr &= 0xffffffff;
- return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
- unsigned long ul;
- unsigned char *puc, uc;
-
- args += (arc * 4);
- ul = (unsigned long)signext(args);
- puc = (unsigned char *)ul;
- if (puc == 0)
- return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
- uc = *puc++;
- ul = (unsigned long)uc;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 24);
-#else /* CONFIG_CPU_LITTLE_ENDIAN */
- uc = *puc++;
- ul = ((unsigned long)uc) << 24;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= ((unsigned long)uc);
-#endif /* CONFIG_CPU_LITTLE_ENDIAN */
- ul = signext(ul);
- return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
- unsigned long args;
- char *p;
-
- args = signext(addrin);
- p = (char *)get_arg(args, arg_index);
-
- return p;
-}
-#endif /* CONFIG_64BIT */
-
-void __init prom_init(void)
-{
- int argc = fw_arg0;
- char **arg = (char **) fw_arg1;
- char **env = (char **) fw_arg2;
- struct callvectors *cv = (struct callvectors *) fw_arg3;
- int i;
-
-#ifdef CONFIG_64BIT
- char *ptr;
- printk("prom_init - MIPS64\n");
-
- /* save the PROM vectors for debugging use */
- debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
-
- for (i = 1; i < argc; i++) {
- ptr = (char *)arg64((unsigned long)arg, i);
- if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
- sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, ptr);
- strcat(arcs_cmdline, " ");
- }
- i = 0;
-
- while (1) {
- ptr = (char *)arg64((unsigned long)env, i);
- if (! ptr)
- break;
-
- if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(ptr + strlen("gtbase="),
- NULL, 16);
-
- if ((marvell_base & 0xffffffff00000000) == 0)
- marvell_base |= 0xffffffff00000000;
-
- printk("marvell_base set to 0x%016lx\n", marvell_base);
- }
- if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
- NULL, 10);
- printk("cpu_clock set to %d\n", cpu_clock);
- }
- i++;
- }
- printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else /* CONFIG_64BIT */
-
- /* save the PROM vectors for debugging use */
- debug_vectors = cv;
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
- for (i = 1; i < argc; i++) {
- if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
- >= sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, arg[i]);
- strcat(arcs_cmdline, " ");
- }
-
- while (*env) {
- if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(*env + strlen("gtbase="),
- NULL, 16);
- }
- if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(*env + strlen("cpuclock="),
- NULL, 10);
- }
- env++;
- }
-#endif /* CONFIG_64BIT */
-
- mips_machgroup = MACH_GROUP_MOMENCO;
- mips_machtype = MACH_MOMENCO_OCELOT_3;
-
-#ifndef CONFIG_64BIT
- debug_vectors->printf("Booting Linux kernel...\n");
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-}
diff --git a/arch/mips/momentum/ocelot_3/reset.c b/arch/mips/momentum/ocelot_3/reset.c
deleted file mode 100644
index 9d86d246837..00000000000
--- a/arch/mips/momentum/ocelot_3/reset.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 01, 05 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void momenco_ocelot_restart(char *command)
-{
- /* base address of timekeeper portion of part */
- void *nvram = (void *) 0xfc807000L;
-
- /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
- writeb(0x84, nvram + 0xff7);
-
- /* wait for the watchdog to go off */
- mdelay(100+(1000/16));
-
- /* if the watchdog fails for some reason, let people know */
- printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
- printk(KERN_NOTICE "\n** You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
- momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
deleted file mode 100644
index ff0829f8111..00000000000
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * setup.c
- *
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-3 board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 01, 05 - 06 Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- * mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mc146818rtc.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-#include <linux/pm.h>
-#include <linux/bcd.h>
-
-#include <asm/time.h>
-#include <asm/page.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/mc146818rtc.h>
-#include <asm/tlbflush.h>
-#include "ocelot_3_fpga.h"
-
-/* Marvell Discovery Register Base */
-unsigned long marvell_base = (signed)0xf4000000;
-
-/* CPU clock */
-unsigned long cpu_clock;
-
-/* RTC/NVRAM */
-unsigned char* rtc_base = (unsigned char*)(signed)0xfc800000;
-
-/* FPGA Base */
-unsigned long ocelot_fpga_base = (signed)0xfc000000;
-
-/* Serial base */
-unsigned long uart_base = (signed)0xfd000000;
-
-/*
- * Marvell Discovery SRAM. This is one place where Ethernet
- * Tx and Rx descriptors can be placed to improve performance
- */
-extern unsigned long mv64340_sram_base;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-void momenco_time_init(void);
-static char reset_reason;
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
- unsigned long entryhi, unsigned long pagemask);
-
-static inline unsigned long ENTRYLO(unsigned long paddr)
-{
- return ((paddr & PAGE_MASK) |
- (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
- _CACHE_UNCACHED)) >> 6;
-}
-
-void __init bus_error_init(void)
-{
- /* nothing */
-}
-
-/*
- * setup code for a handoff from a version 2 PMON 2000 PROM
- */
-void setup_wired_tlb_entries(void)
-{
- write_c0_wired(0);
- local_flush_tlb_all();
-
- /* marvell and extra space */
- add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), (signed)0xf4000000, PM_64K);
-
- /* fpga, rtc, and uart */
- add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M);
-}
-
-unsigned long m48t37y_get_time(void)
-{
- unsigned int year, month, day, hour, min, sec;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* stop the update */
- rtc_base[0x7ff8] = 0x40;
-
- year = BCD2BIN(rtc_base[0x7fff]);
- year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
- month = BCD2BIN(rtc_base[0x7ffe]);
-
- day = BCD2BIN(rtc_base[0x7ffd]);
-
- hour = BCD2BIN(rtc_base[0x7ffb]);
- min = BCD2BIN(rtc_base[0x7ffa]);
- sec = BCD2BIN(rtc_base[0x7ff9]);
-
- /* start the update */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
- struct rtc_time tm;
- unsigned long flags;
-
- /* convert to a more useful format -- note months count from 0 */
- to_tm(sec, &tm);
- tm.tm_mon += 1;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* enable writing */
- rtc_base[0x7ff8] = 0x80;
-
- /* year */
- rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
- rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
- /* month */
- rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
- /* day */
- rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
- /* hour/min/sec */
- rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
- rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
- rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
- /* day of week -- not really used, but let's keep it up-to-date */
- rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
- /* disable writing */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(7, irq); /* Timer interrupt, unmask status IM7 */
-}
-
-void momenco_time_init(void)
-{
- setup_wired_tlb_entries();
-
- /*
- * Ocelot-3 board has been built with both
- * the Rm7900 and the Rm7065C
- */
- mips_hpt_frequency = cpu_clock / 2;
-
- rtc_mips_get_time = m48t37y_get_time;
- rtc_mips_set_time = m48t37y_set_time;
-}
-
-/*
- * PCI Support for Ocelot-3
- */
-
-/* Bus #0 IO and MEM space */
-#define OCELOT_3_PCI_IO_0_START 0xe0000000
-#define OCELOT_3_PCI_IO_0_SIZE 0x08000000
-#define OCELOT_3_PCI_MEM_0_START 0xc0000000
-#define OCELOT_3_PCI_MEM_0_SIZE 0x10000000
-
-/* Bus #1 IO and MEM space */
-#define OCELOT_3_PCI_IO_1_START 0xe8000000
-#define OCELOT_3_PCI_IO_1_SIZE 0x08000000
-#define OCELOT_3_PCI_MEM_1_START 0xd0000000
-#define OCELOT_3_PCI_MEM_1_SIZE 0x10000000
-
-static struct resource mv_pci_io_mem0_resource = {
- .name = "MV64340 PCI0 IO MEM",
- .start = OCELOT_3_PCI_IO_0_START,
- .end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE - 1,
- .flags = IORESOURCE_IO,
-};
-
-static struct resource mv_pci_io_mem1_resource = {
- .name = "MV64340 PCI1 IO MEM",
- .start = OCELOT_3_PCI_IO_1_START,
- .end = OCELOT_3_PCI_IO_1_START + OCELOT_3_PCI_IO_1_SIZE - 1,
- .flags = IORESOURCE_IO,
-};
-
-static struct resource mv_pci_mem0_resource = {
- .name = "MV64340 PCI0 MEM",
- .start = OCELOT_3_PCI_MEM_0_START,
- .end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct resource mv_pci_mem1_resource = {
- .name = "MV64340 PCI1 MEM",
- .start = OCELOT_3_PCI_MEM_1_START,
- .end = OCELOT_3_PCI_MEM_1_START + OCELOT_3_PCI_MEM_1_SIZE - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem0_resource,
- .io_resource = &mv_pci_io_mem0_resource,
- },
- .config_addr = MV64340_PCI_0_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem1_resource,
- .io_resource = &mv_pci_io_mem1_resource,
- },
- .config_addr = MV64340_PCI_1_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init int __init ja_pci_init(void)
-{
- uint32_t enable;
- extern int pci_probe_only;
-
- /* PMON will assign PCI resources */
- pci_probe_only = 1;
-
- enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
- /*
- * We require at least one enabled I/O or PCI memory window or we
- * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
- */
- if (enable & (0x01 << 9) || enable & (0x01 << 10))
- register_pci_controller(&mv_bus0_controller.pcic);
-
- if (enable & (0x01 << 14) || enable & (0x01 << 15))
- register_pci_controller(&mv_bus1_controller.pcic);
-
- ioport_resource.end = OCELOT_3_PCI_IO_0_START + OCELOT_3_PCI_IO_0_SIZE +
- OCELOT_3_PCI_IO_1_SIZE - 1;
-
- iomem_resource.end = OCELOT_3_PCI_MEM_0_START + OCELOT_3_PCI_MEM_0_SIZE +
- OCELOT_3_PCI_MEM_1_SIZE - 1;
-
- set_io_port_base(OCELOT_3_PCI_IO_0_START); /* mips_io_port_base */
-
- return 0;
-}
-
-arch_initcall(ja_pci_init);
-
-void __init plat_mem_setup(void)
-{
- unsigned int tmpword;
-
- board_time_init = momenco_time_init;
-
- _machine_restart = momenco_ocelot_restart;
- _machine_halt = momenco_ocelot_halt;
- pm_power_off = momenco_ocelot_power_off;
-
- /* Wired TLB entries */
- setup_wired_tlb_entries();
-
- /* shut down ethernet ports, just to be sure our memory doesn't get
- * corrupted by random ethernet traffic.
- */
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
- do {}
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-
- /* Turn off the Bit-Error LED */
- OCELOT_FPGA_WRITE(0x80, CLR);
-
- tmpword = OCELOT_FPGA_READ(BOARDREV);
- if (tmpword < 26)
- printk("Momenco Ocelot-3: Board Assembly Rev. %c\n",
- 'A'+tmpword);
- else
- printk("Momenco Ocelot-3: Board Assembly Revision #0x%x\n",
- tmpword);
-
- tmpword = OCELOT_FPGA_READ(FPGA_REV);
- printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
- tmpword = OCELOT_FPGA_READ(RESET_STATUS);
- printk("Reset reason: 0x%x\n", tmpword);
- switch (tmpword) {
- case 0x1:
- printk(" - Power-up reset\n");
- break;
- case 0x2:
- printk(" - Push-button reset\n");
- break;
- case 0x4:
- printk(" - cPCI bus reset\n");
- break;
- case 0x8:
- printk(" - Watchdog reset\n");
- break;
- case 0x10:
- printk(" - Software reset\n");
- break;
- default:
- printk(" - Unknown reset cause\n");
- }
- reset_reason = tmpword;
- OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
-
- tmpword = OCELOT_FPGA_READ(CPCI_ID);
- printk("cPCI ID register: 0x%02x\n", tmpword);
- printk(" - Slot number: %d\n", tmpword & 0x1f);
- printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
- printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
-
- tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
- printk("Board Status register: 0x%02x\n", tmpword);
- printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
- printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
- printk(" - L3 cache size: %d MB\n", (1<<((tmpword&12) >> 2))&~1);
-
- /* Support for 128 MB memory */
- add_memory_region(0x0, 0x08000000, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile
deleted file mode 100644
index d69161aa167..00000000000
--- a/arch/mips/momentum/ocelot_c/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-C and -CS boards.
-#
-
-obj-y += cpci-irq.o irq.o platform.o prom.o reset.o \
- setup.o uart-irq.o
-
-obj-$(CONFIG_KGDB) += dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c
deleted file mode 100644
index 186a140fd2a..00000000000
--- a/arch/mips/momentum/ocelot_c/cpci-irq.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_c/cpci-irq.c
- * Interrupt routines for cpci. Interrupt numbers are assigned from
- * CPCI_IRQ_BASE to CPCI_IRQ_BASE+8 (8 interrupt sources).
- *
- * Note that the high-level software will need to be careful about using
- * these interrupts. If this board is asserting a cPCI interrupt, it will
- * also see the asserted interrupt. Care must be taken to avoid an
- * interrupt flood.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include "ocelot_c_fpga.h"
-
-#define CPCI_IRQ_BASE 8
-
-static inline int ls1bit8(unsigned int x)
-{
- int b = 7, s;
-
- s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s;
- s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s;
- s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s;
-
- return b;
-}
-
-/* mask off an interrupt -- 0 is enable, 1 is disable */
-static inline void mask_cpci_irq(unsigned int irq)
-{
- uint32_t value;
-
- value = OCELOT_FPGA_READ(INTMASK);
- value |= 1 << (irq - CPCI_IRQ_BASE);
- OCELOT_FPGA_WRITE(value, INTMASK);
-
- /* read the value back to assure that it's really been written */
- value = OCELOT_FPGA_READ(INTMASK);
-}
-
-/* unmask an interrupt -- 0 is enable, 1 is disable */
-static inline void unmask_cpci_irq(unsigned int irq)
-{
- uint32_t value;
-
- value = OCELOT_FPGA_READ(INTMASK);
- value &= ~(1 << (irq - CPCI_IRQ_BASE));
- OCELOT_FPGA_WRITE(value, INTMASK);
-
- /* read the value back to assure that it's really been written */
- value = OCELOT_FPGA_READ(INTMASK);
-}
-
-/*
- * Interrupt handler for interrupts coming from the FPGA chip.
- * It could be built in ethernet ports etc...
- */
-void ll_cpci_irq(void)
-{
- unsigned int irq_src, irq_mask;
-
- /* read the interrupt status registers */
- irq_src = OCELOT_FPGA_READ(INTSTAT);
- irq_mask = OCELOT_FPGA_READ(INTMASK);
-
- /* mask for just the interrupts we want */
- irq_src &= ~irq_mask;
-
- do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE);
-}
-
-struct irq_chip cpci_irq_type = {
- .name = "CPCI/FPGA",
- .ack = mask_cpci_irq,
- .mask = mask_cpci_irq,
- .mask_ack = mask_cpci_irq,
- .unmask = unmask_cpci_irq,
-};
-
-void cpci_irq_init(void)
-{
- int i;
-
- for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++)
- set_irq_chip_and_handler(i, &cpci_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c
deleted file mode 100644
index 32d6fb4ee67..00000000000
--- a/arch/mips/momentum/ocelot_c/dbg_io.c
+++ /dev/null
@@ -1,121 +0,0 @@
-
-#include <asm/serial.h> /* For the serial port location and base baud */
-
-/* --- CONFIG --- */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-/* --- END OF CONFIG --- */
-
-#define UART16550_BAUD_2400 2400
-#define UART16550_BAUD_4800 4800
-#define UART16550_BAUD_9600 9600
-#define UART16550_BAUD_19200 19200
-#define UART16550_BAUD_38400 38400
-#define UART16550_BAUD_57600 57600
-#define UART16550_BAUD_115200 115200
-
-#define UART16550_PARITY_NONE 0
-#define UART16550_PARITY_ODD 0x08
-#define UART16550_PARITY_EVEN 0x18
-#define UART16550_PARITY_MARK 0x28
-#define UART16550_PARITY_SPACE 0x38
-
-#define UART16550_DATA_5BIT 0x0
-#define UART16550_DATA_6BIT 0x1
-#define UART16550_DATA_7BIT 0x2
-#define UART16550_DATA_8BIT 0x3
-
-#define UART16550_STOP_1BIT 0x0
-#define UART16550_STOP_2BIT 0x4
-
-/* ----------------------------------------------------- */
-
-/* === CONFIG === */
-
-/* [jsun] we use the second serial port for kdb */
-#define BASE OCELOT_SERIAL1_BASE
-#define MAX_BAUD OCELOT_BASE_BAUD
-
-/* === END OF CONFIG === */
-
-#define REG_OFFSET 4
-
-/* register offset */
-#define OFS_RCV_BUFFER 0
-#define OFS_TRANS_HOLD 0
-#define OFS_SEND_BUFFER 0
-#define OFS_INTR_ENABLE (1*REG_OFFSET)
-#define OFS_INTR_ID (2*REG_OFFSET)
-#define OFS_DATA_FORMAT (3*REG_OFFSET)
-#define OFS_LINE_CONTROL (3*REG_OFFSET)
-#define OFS_MODEM_CONTROL (4*REG_OFFSET)
-#define OFS_RS232_OUTPUT (4*REG_OFFSET)
-#define OFS_LINE_STATUS (5*REG_OFFSET)
-#define OFS_MODEM_STATUS (6*REG_OFFSET)
-#define OFS_RS232_INPUT (6*REG_OFFSET)
-#define OFS_SCRATCH_PAD (7*REG_OFFSET)
-
-#define OFS_DIVISOR_LSB (0*REG_OFFSET)
-#define OFS_DIVISOR_MSB (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define UART16550_READ(y) (*((volatile uint8*)(BASE + y)))
-#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
- /* disable interrupts */
- UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
- /* set up baud rate */
- {
- uint32 divisor;
-
- /* set DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
- /* set divisor */
- divisor = MAX_BAUD / baud;
- UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
- UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
- /* clear DIAB bit */
- UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
- }
-
- /* set data format */
- UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-static int remoteDebugInitialized = 0;
-
-uint8 getDebugChar(void)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(UART16550_BAUD_38400,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
- return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
- if (!remoteDebugInitialized) {
- remoteDebugInitialized = 1;
- debugInit(UART16550_BAUD_38400,
- UART16550_DATA_8BIT,
- UART16550_PARITY_NONE, UART16550_STOP_1BIT);
- }
-
- while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
- UART16550_WRITE(OFS_SEND_BUFFER, byte);
- return 1;
-}
diff --git a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c
deleted file mode 100644
index 844d566c9de..00000000000
--- a/arch/mips/momentum/ocelot_c/irq.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <linux/mv643xx.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-extern void uart_irq_init(void);
-extern void cpci_irq_init(void);
-
-static struct irqaction cascade_fpga = {
- no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via FPGA", NULL, NULL
-};
-
-static struct irqaction cascade_mv64340 = {
- no_action, IRQF_DISABLED, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
-};
-
-extern void ll_uart_irq(void);
-extern void ll_cpci_irq(void);
-
-asmlinkage void plat_irq_dispatch(void)
-{
- unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-
- if (pending & STATUSF_IP0)
- do_IRQ(0);
- else if (pending & STATUSF_IP1)
- do_IRQ(1);
- else if (pending & STATUSF_IP2)
- do_IRQ(2);
- else if (pending & STATUSF_IP3)
- ll_uart_irq();
- else if (pending & STATUSF_IP4)
- do_IRQ(4);
- else if (pending & STATUSF_IP5)
- ll_cpci_irq();
- else if (pending & STATUSF_IP6)
- ll_mv64340_irq();
- else if (pending & STATUSF_IP7)
- do_IRQ(7);
- else
- spurious_interrupt();
-}
-
-void __init arch_init_irq(void)
-{
- /*
- * Clear all of the interrupts while we change the able around a bit.
- * int-handler is not on bootstrap
- */
- clear_c0_status(ST0_IM);
-
- mips_cpu_irq_init();
-
- /* set up the cascading interrupts */
- setup_irq(3, &cascade_fpga);
- setup_irq(5, &cascade_fpga);
- setup_irq(6, &cascade_mv64340);
-
- mv64340_irq_init(16);
- uart_irq_init();
- cpci_irq_init();
-}
diff --git a/arch/mips/momentum/ocelot_c/platform.c b/arch/mips/momentum/ocelot_c/platform.c
deleted file mode 100644
index 7780aa0c655..00000000000
--- a/arch/mips/momentum/ocelot_c/platform.c
+++ /dev/null
@@ -1,183 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "ocelot_c_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
- [0] = {
- .name = "ethernet shared base",
- .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
- .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
- MV643XX_ETH_SHARED_REGS_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
- .name = MV643XX_ETH_SHARED_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources),
- .resource = mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE 0xfe000000UL
-#define MV_SRAM_SIZE (256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE (MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE (MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0 MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1 (MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-
-static struct resource mv64x60_eth0_resources[] = {
- [0] = {
- .name = "eth0 irq",
- .start = MV64x60_IRQ_ETH_0,
- .end = MV64x60_IRQ_ETH_0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
- .port_number = 0,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH0,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
- .name = MV643XX_ETH_NAME,
- .id = 0,
- .num_resources = ARRAY_SIZE(mv64x60_eth0_resources),
- .resource = mv64x60_eth0_resources,
- .dev = {
- .platform_data = &eth0_pd,
- },
-};
-
-static struct resource mv64x60_eth1_resources[] = {
- [0] = {
- .name = "eth1 irq",
- .start = MV64x60_IRQ_ETH_1,
- .end = MV64x60_IRQ_ETH_1,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
- .port_number = 1,
-
- .tx_sram_addr = MV_SRAM_BASE_ETH1,
- .tx_sram_size = MV_SRAM_TXRING_SIZE,
- .tx_queue_size = MV_SRAM_TXRING_SIZE / 16,
-
- .rx_sram_addr = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
- .rx_sram_size = MV_SRAM_RXRING_SIZE,
- .rx_queue_size = MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
- .name = MV643XX_ETH_NAME,
- .id = 1,
- .num_resources = ARRAY_SIZE(mv64x60_eth1_resources),
- .resource = mv64x60_eth1_resources,
- .dev = {
- .platform_data = &eth1_pd,
- },
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
- &mv643xx_eth_shared_device,
- &eth0_device,
- &eth1_device,
- /* The third port is not wired up on the Ocelot C */
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
- /* place the data */
- OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock on */
- OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
- udelay(1);
-
- /* turn the clock off and read-strobe */
- OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
- /* return the data */
- return (OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
- u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int i,j;
-
- for (i = 0; i < 12; i++)
- exchange_bit(read_opcode[i], 1);
-
- for (j = 0; j < 6; j++) {
- dest[j] = 0;
- for (i = 0; i < 8; i++) {
- dest[j] <<= 1;
- dest[j] |= exchange_bit(0, 1);
- }
- }
-
- /* turn off CS */
- exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
- unsigned int add)
-{
- int i;
-
- BUG_ON(add >= 256);
-
- for (i = ETH_ALEN; i >= 0; i--) {
- dst[i] = src[i] + add;
- add = dst[i] < src[i]; /* compute carry */
- }
-
- WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
- unsigned char mac[ETH_ALEN];
- int ret;
-
- get_mac(mac);
- eth_mac_add(eth0_pd.mac_addr, mac, 0);
- eth_mac_add(eth1_pd.mac_addr, mac, 1);
- ret = platform_add_devices(mv643xx_eth_pd_devs,
- ARRAY_SIZE(mv643xx_eth_pd_devs));
-
- return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
deleted file mode 100644
index b689ceea8cf..00000000000
--- a/arch/mips/momentum/ocelot_c/prom.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-
-#include "ocelot_c_fpga.h"
-
-struct callvectors* debug_vectors;
-
-extern unsigned long marvell_base;
-extern unsigned int cpu_clock;
-
-const char *get_system_type(void)
-{
-#ifdef CONFIG_CPU_SR71000
- return "Momentum Ocelot-CS";
-#else
- return "Momentum Ocelot-C";
-#endif
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
- addr &= 0xffffffff;
- return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
- unsigned long ul;
- unsigned char *puc, uc;
-
- args += (arc * 4);
- ul = (unsigned long)signext(args);
- puc = (unsigned char *)ul;
- if (puc == 0)
- return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
- uc = *puc++;
- ul = (unsigned long)uc;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 24);
-#else /* CONFIG_CPU_LITTLE_ENDIAN */
- uc = *puc++;
- ul = ((unsigned long)uc) << 24;
- uc = *puc++;
- ul |= (((unsigned long)uc) << 16);
- uc = *puc++;
- ul |= (((unsigned long)uc) << 8);
- uc = *puc++;
- ul |= ((unsigned long)uc);
-#endif /* CONFIG_CPU_LITTLE_ENDIAN */
- ul = signext(ul);
- return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
- unsigned long args;
- char *p;
- args = signext(addrin);
- p = (char *)get_arg(args, arg_index);
- return p;
-}
-#endif /* CONFIG_64BIT */
-
-
-void __init prom_init(void)
-{
- int argc = fw_arg0;
- char **arg = (char **) fw_arg1;
- char **env = (char **) fw_arg2;
- struct callvectors *cv = (struct callvectors *) fw_arg3;
- int i;
-
-#ifdef CONFIG_64BIT
- char *ptr;
-
- printk("prom_init - MIPS64\n");
- /* save the PROM vectors for debugging use */
- debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
-
- for (i = 1; i < argc; i++) {
- ptr = (char *)arg64((unsigned long)arg, i);
- if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
- sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, ptr);
- strcat(arcs_cmdline, " ");
- }
- i = 0;
- while (1) {
- ptr = (char *)arg64((unsigned long)env, i);
- if (! ptr)
- break;
-
- if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(ptr + strlen("gtbase="),
- NULL, 16);
-
- if ((marvell_base & 0xffffffff00000000) == 0)
- marvell_base |= 0xffffffff00000000;
-
- printk("marvell_base set to 0x%016lx\n", marvell_base);
- }
- if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
- NULL, 10);
- printk("cpu_clock set to %d\n", cpu_clock);
- }
- i++;
- }
- printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else /* CONFIG_64BIT */
- /* save the PROM vectors for debugging use */
- debug_vectors = cv;
-
- /* arg[0] is "g", the rest is boot parameters */
- arcs_cmdline[0] = '\0';
- for (i = 1; i < argc; i++) {
- if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
- >= sizeof(arcs_cmdline))
- break;
- strcat(arcs_cmdline, arg[i]);
- strcat(arcs_cmdline, " ");
- }
-
- while (*env) {
- if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
- marvell_base = simple_strtol(*env + strlen("gtbase="),
- NULL, 16);
- }
- if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
- cpu_clock = simple_strtol(*env + strlen("cpuclock="),
- NULL, 10);
- }
- env++;
- }
-#endif /* CONFIG_64BIT */
-
- mips_machgroup = MACH_GROUP_MOMENCO;
- mips_machtype = MACH_MOMENCO_OCELOT_C;
-
-#ifndef CONFIG_64BIT
- debug_vectors->printf("Booting Linux kernel...\n");
-#endif
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
diff --git a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c
deleted file mode 100644
index 3fdcb64ff1e..00000000000
--- a/arch/mips/momentum/ocelot_c/reset.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-
-void momenco_ocelot_restart(char *command)
-{
- /* base address of timekeeper portion of part */
- void *nvram = (void *)
-#ifdef CONFIG_64BIT
- 0xfffffffffc807000;
-#else
- 0xfc807000;
-#endif
-
- /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
- writeb(0x84, nvram + 0xff7);
-
- /* wait for the watchdog to go off */
- mdelay(100+(1000/16));
-
- /* if the watchdog fails for some reason, let people know */
- printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
- printk(KERN_NOTICE "\n** You can safely turn off the power\n");
- while (1)
- __asm__(".set\tmips3\n\t"
- "wait\n\t"
- ".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
- momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
deleted file mode 100644
index 0b6b2338cfb..00000000000
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-C and -CS board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 2001 Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- * mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-#include <linux/timex.h>
-#include <linux/vmalloc.h>
-#include <linux/mv643xx.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/marvell.h>
-#include <linux/bootmem.h>
-#include <linux/blkdev.h>
-#include "ocelot_c_fpga.h"
-
-unsigned long marvell_base;
-unsigned int cpu_clock;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-void momenco_time_init(void);
-
-static char reset_reason;
-
-void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask);
-
-static unsigned long ENTRYLO(unsigned long paddr)
-{
- return ((paddr & PAGE_MASK) |
- (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
- _CACHE_UNCACHED)) >> 6;
-}
-
-/* setup code for a handoff from a version 2 PMON 2000 PROM */
-void PMON_v2_setup(void)
-{
- /* Some wired TLB entries for the MV64340 and perhiperals. The
- MV64340 is going to be hit on every IRQ anyway - there's
- absolutely no point in letting it be a random TLB entry, as
- it'll just cause needless churning of the TLB. And we use
- the other half for the serial port, which is just a PITA
- otherwise :)
-
- Device Physical Virtual
- MV64340 Internal Regs 0xf4000000 0xf4000000
- Ocelot-C[S] PLD (CS0) 0xfc000000 0xfc000000
- NVRAM (CS1) 0xfc800000 0xfc800000
- UARTs (CS2) 0xfd000000 0xfd000000
- Internal SRAM 0xfe000000 0xfe000000
- M-Systems DOC (CS3) 0xff000000 0xff000000
- */
- printk("PMON_v2_setup\n");
-
-#ifdef CONFIG_64BIT
- /* marvell and extra space */
- add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K);
- /* fpga, rtc, and uart */
- add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M);
- /* m-sys and internal SRAM */
- add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M);
-
- marvell_base = 0xfffffffff4000000;
-#else
- /* marvell and extra space */
- add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K);
- /* fpga, rtc, and uart */
- add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfc000000, PM_16M);
- /* m-sys and internal SRAM */
- add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M);
-
- marvell_base = 0xf4000000;
-#endif
-}
-
-unsigned long m48t37y_get_time(void)
-{
-#ifdef CONFIG_64BIT
- unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000;
-#else
- unsigned char* rtc_base = (unsigned char*)0xfc800000;
-#endif
- unsigned int year, month, day, hour, min, sec;
- unsigned long flags;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* stop the update */
- rtc_base[0x7ff8] = 0x40;
-
- year = BCD2BIN(rtc_base[0x7fff]);
- year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
- month = BCD2BIN(rtc_base[0x7ffe]);
-
- day = BCD2BIN(rtc_base[0x7ffd]);
-
- hour = BCD2BIN(rtc_base[0x7ffb]);
- min = BCD2BIN(rtc_base[0x7ffa]);
- sec = BCD2BIN(rtc_base[0x7ff9]);
-
- /* start the update */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
-#ifdef CONFIG_64BIT
- unsigned char* rtc_base = (unsigned char*)0xfffffffffc800000;
-#else
- unsigned char* rtc_base = (unsigned char*)0xfc800000;
-#endif
- struct rtc_time tm;
- unsigned long flags;
-
- /* convert to a more useful format -- note months count from 0 */
- to_tm(sec, &tm);
- tm.tm_mon += 1;
-
- spin_lock_irqsave(&rtc_lock, flags);
- /* enable writing */
- rtc_base[0x7ff8] = 0x80;
-
- /* year */
- rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
- rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
- /* month */
- rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
- /* day */
- rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
- /* hour/min/sec */
- rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
- rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
- rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
- /* day of week -- not really used, but let's keep it up-to-date */
- rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
- /* disable writing */
- rtc_base[0x7ff8] = 0x00;
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
- setup_irq(7, irq);
-}
-
-void momenco_time_init(void)
-{
-#ifdef CONFIG_CPU_SR71000
- mips_hpt_frequency = cpu_clock;
-#elif defined(CONFIG_CPU_RM7000)
- mips_hpt_frequency = cpu_clock / 2;
-#else
-#error Unknown CPU for this board
-#endif
- printk("momenco_time_init cpu_clock=%d\n", cpu_clock);
-
- rtc_mips_get_time = m48t37y_get_time;
- rtc_mips_set_time = m48t37y_set_time;
-}
-
-void __init plat_mem_setup(void)
-{
- unsigned int tmpword;
-
- board_time_init = momenco_time_init;
-
- _machine_restart = momenco_ocelot_restart;
- _machine_halt = momenco_ocelot_halt;
- pm_power_off = momenco_ocelot_power_off;
-
- /*
- * initrd_start = (unsigned long)ocelot_initrd_start;
- * initrd_end = (unsigned long)ocelot_initrd_start + (ulong)ocelot_initrd_size;
- * initrd_below_start_ok = 1;
- */
-
- /* do handoff reconfiguration */
- PMON_v2_setup();
-
- /* shut down ethernet ports, just to be sure our memory doesn't get
- * corrupted by random ethernet traffic.
- */
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
- MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
- do {}
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
- do {}
- while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
- MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
- MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-
- /* Turn off the Bit-Error LED */
- OCELOT_FPGA_WRITE(0x80, CLR);
-
- tmpword = OCELOT_FPGA_READ(BOARDREV);
-#ifdef CONFIG_CPU_SR71000
- if (tmpword < 26)
- printk("Momenco Ocelot-CS: Board Assembly Rev. %c\n",
- 'A'+tmpword);
- else
- printk("Momenco Ocelot-CS: Board Assembly Revision #0x%x\n",
- tmpword);
-#else
- if (tmpword < 26)
- printk("Momenco Ocelot-C: Board Assembly Rev. %c\n",
- 'A'+tmpword);
- else
- printk("Momenco Ocelot-C: Board Assembly Revision #0x%x\n",
- tmpword);
-#endif
-
- tmpword = OCELOT_FPGA_READ(FPGA_REV);
- printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
- tmpword = OCELOT_FPGA_READ(RESET_STATUS);
- printk("Reset reason: 0x%x\n", tmpword);
- switch (tmpword) {
- case 0x1:
- printk(" - Power-up reset\n");
- break;
- case 0x2:
- printk(" - Push-button reset\n");
- break;
- case 0x4:
- printk(" - cPCI bus reset\n");
- break;
- case 0x8:
- printk(" - Watchdog reset\n");
- break;
- case 0x10:
- printk(" - Software reset\n");
- break;
- default:
- printk(" - Unknown reset cause\n");
- }
- reset_reason = tmpword;
- OCELOT_FPGA_WRITE(0xff, RESET_STATUS);
-
- tmpword = OCELOT_FPGA_READ(CPCI_ID);
- printk("cPCI ID register: 0x%02x\n", tmpword);
- printk(" - Slot number: %d\n", tmpword & 0x1f);
- printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no");
- printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no");
-
- tmpword = OCELOT_FPGA_READ(BOARD_STATUS);
- printk("Board Status register: 0x%02x\n", tmpword);
- printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
- printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
- printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
- printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
-
- switch(tmpword &3) {
- case 3:
- /* 512MiB */
- add_memory_region(0x0, 0x200<<20, BOOT_MEM_RAM);
- break;
- case 2:
- /* 256MiB */
- add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
- break;
- case 1:
- /* 128MiB */
- add_memory_region(0x0, 0x80<<20, BOOT_MEM_RAM);
- break;
- case 0:
- /* 1GiB -- needs CONFIG_HIGHMEM */
- add_memory_region(0x0, 0x400<<20, BOOT_MEM_RAM);
- break;
- }
-}
-
-/*
- * This needs to be one of the first initcalls, because no I/O port access
- * can work before this
- */
-static int io_base_ioremap(void)
-{
- void __iomem * io_remap_range = ioremap(0xc0000000UL, 0x10000);
-
- if (!io_remap_range)
- panic("Could not ioremap I/O port range");
-
- set_io_port_base((unsigned long) io_remap_range);
-
- return 0;
-}
-
-module_init(io_base_ioremap);
diff --git a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c
deleted file mode 100644
index de1a31ee52f..00000000000
--- a/arch/mips/momentum/ocelot_c/uart-irq.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_c/uart-irq.c
- * Interrupt routines for UARTs. Interrupt numbers are assigned from
- * 80 to 81 (2 interrupt sources).
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "ocelot_c_fpga.h"
-
-static inline int ls1bit8(unsigned int x)
-{
- int b = 7, s;
-
- s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s;
- s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s;
- s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s;
-
- return b;
-}
-
-/* mask off an interrupt -- 0 is enable, 1 is disable */
-static inline void mask_uart_irq(unsigned int irq)
-{
- uint8_t value;
-
- value = OCELOT_FPGA_READ(UART_INTMASK);
- value |= 1 << (irq - 74);
- OCELOT_FPGA_WRITE(value, UART_INTMASK);
-
- /* read the value back to assure that it's really been written */
- value = OCELOT_FPGA_READ(UART_INTMASK);
-}
-
-/* unmask an interrupt -- 0 is enable, 1 is disable */
-static inline void unmask_uart_irq(unsigned int irq)
-{
- uint8_t value;
-
- value = OCELOT_FPGA_READ(UART_INTMASK);
- value &= ~(1 << (irq - 74));
- OCELOT_FPGA_WRITE(value, UART_INTMASK);
-
- /* read the value back to assure that it's really been written */
- value = OCELOT_FPGA_READ(UART_INTMASK);
-}
-
-/*
- * Interrupt handler for interrupts coming from the FPGA chip.
- */
-void ll_uart_irq(void)
-{
- unsigned int irq_src, irq_mask;
-
- /* read the interrupt status registers */
- irq_src = OCELOT_FPGA_READ(UART_INTSTAT);
- irq_mask = OCELOT_FPGA_READ(UART_INTMASK);
-
- /* mask for just the interrupts we want */
- irq_src &= ~irq_mask;
-
- do_IRQ(ls1bit8(irq_src) + 74);
-}
-
-struct irq_chip uart_irq_type = {
- .name = "UART/FPGA",
- .ack = mask_uart_irq,
- .mask = mask_uart_irq,
- .mask_ack = mask_uart_irq,
- .unmask = unmask_uart_irq,
-};
-
-void uart_irq_init(void)
-{
- set_irq_chip_and_handler(80, &uart_irq_type, handle_level_irq);
- set_irq_chip_and_handler(81, &uart_irq_type, handle_level_irq);
-}
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 4f94fa261aa..1ea5c9c1010 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -177,7 +177,10 @@ static int mipsxx_perfcount_handler(void)
unsigned int counters = op_model_mipsxx_ops.num_counters;
unsigned int control;
unsigned int counter;
- int handled = 0;
+ int handled = IRQ_NONE;
+
+ if (cpu_has_mips_r2 && !(read_c0_cause() & (1 << 26)))
+ return handled;
switch (counters) {
#define HANDLE_COUNTER(n) \
@@ -188,7 +191,7 @@ static int mipsxx_perfcount_handler(void)
(counter & M_COUNTER_OVERFLOW)) { \
oprofile_add_sample(get_irq_regs(), n); \
w_c0_perfcntr ## n(reg.counter[n]); \
- handled = 1; \
+ handled = IRQ_HANDLED; \
}
HANDLE_COUNTER(3)
HANDLE_COUNTER(2)
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index aba3dbf47ed..c58bd3d036f 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -2,16 +2,14 @@
# Makefile for the PCI specific kernel interface routines under Linux.
#
-obj-y += pci.o pci-dac.o
+obj-y += pci.o
#
# PCI bus host bridge specific code
#
obj-$(CONFIG_MIPS_BONITO64) += ops-bonito64.o
obj-$(CONFIG_PCI_GT64XXX_PCI0) += ops-gt64xxx_pci0.o
-obj-$(CONFIG_PCI_MARVELL) += ops-marvell.o
obj-$(CONFIG_MIPS_MSC) += ops-msc.o
-obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o
obj-$(CONFIG_MIPS_TX3927) += ops-tx3927.o
obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o
obj-$(CONFIG_NEC_CMBVR4133) += fixup-vr4133.o
@@ -22,17 +20,17 @@ obj-$(CONFIG_MARKEINS) += ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o
#
obj-$(CONFIG_BASLER_EXCITE) += ops-titan.o pci-excite.o fixup-excite.o
obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
-obj-$(CONFIG_LASAT) += pci-lasat.o
obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o
obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
-obj-$(CONFIG_MIPS_EV64120) += pci-ev64120.o
obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_AU1550) += fixup-au1000.o ops-au1000.o
obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o
+obj-$(CONFIG_LEMOTE_FULONG) += fixup-lm2e.o ops-bonito64.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o
obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o
-obj-$(CONFIG_MOMENCO_OCELOT_3) += fixup-ocelot3.o
-obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.o
+obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
+obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
+obj-$(CONFIG_PMC_MSP7120_FPGA) += fixup-pmcmsp.o ops-pmcmsp.o
obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \
pci-yosemite.o
obj-$(CONFIG_SGI_IP27) += ops-bridge.o pci-ip27.o
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
index c6cd6e9cdfb..45224fd2c7b 100644
--- a/arch/mips/pci/fixup-atlas.c
+++ b/arch/mips/pci/fixup-atlas.c
@@ -58,7 +58,7 @@ static char irq_tab[][5] __initdata = {
{0, 0, 0, 0, 0 } /* 21: Unused */
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab[slot][pin];
}
diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
index c2f8304fe55..ca0276c8070 100644
--- a/arch/mips/pci/fixup-au1000.c
+++ b/arch/mips/pci/fixup-au1000.c
@@ -35,7 +35,7 @@
extern char irq_tab_alchemy[][5];
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_alchemy[slot][pin];
}
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
index 1e530751936..1416bca6d1a 100644
--- a/arch/mips/pci/fixup-capcella.c
+++ b/arch/mips/pci/fixup-capcella.c
@@ -38,7 +38,7 @@ static char irq_tab_capcella[][5] __initdata = {
[14] = { -1, INTA, INTB, INTC, INTD }
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_capcella[slot][pin];
}
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index d57ffd7242c..76b4f0ffb1e 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -58,8 +58,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
static void qube_raq_galileo_fixup(struct pci_dev *dev)
{
- unsigned short galileo_id;
-
if (dev->devfn != PCI_DEVFN(0, 0))
return;
@@ -84,16 +82,14 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev)
* Therefore we must set the disconnect/retry cycle values to
* something sensible when using the new Galileo.
*/
- pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id);
- galileo_id &= 0xff; /* mask off class info */
- printk(KERN_INFO "Galileo: revision %u\n", galileo_id);
+ printk(KERN_INFO "Galileo: revision %u\n", dev->revision);
#if 0
- if (galileo_id >= 0x10) {
+ if (dev->revision >= 0x10) {
/* New Galileo, assumes PCI stop line to VIA is connected. */
GT_WRITE(GT_PCI0_TOR_OFS, 0x4020);
- } else if (galileo_id == 0x1 || galileo_id == 0x2)
+ } else if (dev->revision == 0x1 || dev->revision == 0x2)
#endif
{
signed int timeo;
@@ -161,7 +157,7 @@ static char irq_tab_raq2[] __initdata = {
[COBALT_PCICONF_ETH1] = COBALT_ETH1_IRQ
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (cobalt_board_id < COBALT_BRD_ID_QUBE2)
return irq_tab_qube1[slot];
diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c
index 7abcfd175d4..a2705895561 100644
--- a/arch/mips/pci/fixup-emma2rh.c
+++ b/arch/mips/pci/fixup-emma2rh.c
@@ -89,7 +89,7 @@ static void __devinit emma2rh_pci_host_fixup(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
emma2rh_pci_host_fixup);
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_map[slot][pin];
}
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
index 1da696d43f0..cd64d9f177c 100644
--- a/arch/mips/pci/fixup-excite.c
+++ b/arch/mips/pci/fixup-excite.c
@@ -21,7 +21,7 @@
#include <linux/pci.h>
#include <excite.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (pin == 0)
return -1;
diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c
index 3e66b0aa63c..190fffd08d3 100644
--- a/arch/mips/pci/fixup-ip32.c
+++ b/arch/mips/pci/fixup-ip32.c
@@ -39,7 +39,7 @@ static char irq_tab_mace[][5] __initdata = {
* irqs. I suppose a device without a pin A will thank us for doing it
* right if there exists such a broken piece of crap.
*/
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return irq_tab_mace[slot][pin];
}
diff --git a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c
index 73d18503517..e974394be7b 100644
--- a/arch/mips/pci/fixup-jmr3927.c
+++ b/arch/mips/pci/fixup-jmr3927.c
@@ -33,7 +33,7 @@
#include <asm/jmr3927/jmr3927.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char irq = pin;
diff --git a/arch/mips/pci/fixup-lm2e.c b/arch/mips/pci/fixup-lm2e.c
new file mode 100644
index 00000000000..e18ae4f574c
--- /dev/null
+++ b/arch/mips/pci/fixup-lm2e.c
@@ -0,0 +1,242 @@
+/*
+ * fixup-lm2e.c
+ *
+ * Copyright (C) 2004 ICT CAS
+ * Author: Li xiaoyu, ICT CAS
+ * lixy@ict.ac.cn
+ *
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/mips-boards/bonito64.h>
+
+/* South bridge slot number is set by the pci probe process */
+static u8 sb_slot = 5;
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq = 0;
+
+ if (slot == sb_slot) {
+ switch (PCI_FUNC(dev->devfn)) {
+ case 2:
+ irq = 10;
+ break;
+ case 3:
+ irq = 11;
+ break;
+ case 5:
+ irq = 9;
+ break;
+ }
+ } else {
+ irq = BONITO_IRQ_BASE + 25 + pin;
+ }
+ return irq;
+
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return 0;
+}
+
+static void __init loongson2e_nec_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+
+ /* Configues port 1, 2, 3, 4 to be validate*/
+ pci_read_config_dword(pdev, 0xe0, &val);
+ pci_write_config_dword(pdev, 0xe0, (val & ~7) | 0x4);
+
+ /* System clock is 48-MHz Oscillator. */
+ pci_write_config_dword(pdev, 0xe4, 1 << 5);
+}
+
+static void __init loongson2e_686b_func0_fixup(struct pci_dev *pdev)
+{
+ unsigned char c;
+
+ sb_slot = PCI_SLOT(pdev->devfn);
+
+ printk(KERN_INFO "via686b fix: ISA bridge\n");
+
+ /* Enable I/O Recovery time */
+ pci_write_config_byte(pdev, 0x40, 0x08);
+
+ /* Enable ISA refresh */
+ pci_write_config_byte(pdev, 0x41, 0x01);
+
+ /* disable ISA line buffer */
+ pci_write_config_byte(pdev, 0x45, 0x00);
+
+ /* Gate INTR, and flush line buffer */
+ pci_write_config_byte(pdev, 0x46, 0xe0);
+
+ /* Disable PCI Delay Transaction, Enable EISA ports 4D0/4D1. */
+ /* pci_write_config_byte(pdev, 0x47, 0x20); */
+
+ /*
+ * enable PCI Delay Transaction, Enable EISA ports 4D0/4D1.
+ * enable time-out timer
+ */
+ pci_write_config_byte(pdev, 0x47, 0xe6);
+
+ /*
+ * enable level trigger on pci irqs: 9,10,11,13
+ * important! without this PCI interrupts won't work
+ */
+ outb(0x2e, 0x4d1);
+
+ /* 512 K PCI Decode */
+ pci_write_config_byte(pdev, 0x48, 0x01);
+
+ /* Wait for PGNT before grant to ISA Master/DMA */
+ pci_write_config_byte(pdev, 0x4a, 0x84);
+
+ /*
+ * Plug'n'Play
+ *
+ * Parallel DRQ 3, Floppy DRQ 2 (default)
+ */
+ pci_write_config_byte(pdev, 0x50, 0x0e);
+
+ /*
+ * IRQ Routing for Floppy and Parallel port
+ *
+ * IRQ 6 for floppy, IRQ 7 for parallel port
+ */
+ pci_write_config_byte(pdev, 0x51, 0x76);
+
+ /* IRQ Routing for serial ports (take IRQ 3 and 4) */
+ pci_write_config_byte(pdev, 0x52, 0x34);
+
+ /* All IRQ's level triggered. */
+ pci_write_config_byte(pdev, 0x54, 0x00);
+
+ /* route PIRQA-D irq */
+ pci_write_config_byte(pdev, 0x55, 0x90); /* bit 7-4, PIRQA */
+ pci_write_config_byte(pdev, 0x56, 0xba); /* bit 7-4, PIRQC; */
+ /* 3-0, PIRQB */
+ pci_write_config_byte(pdev, 0x57, 0xd0); /* bit 7-4, PIRQD */
+
+ /* enable function 5/6, audio/modem */
+ pci_read_config_byte(pdev, 0x85, &c);
+ c &= ~(0x3 << 2);
+ pci_write_config_byte(pdev, 0x85, c);
+
+ printk(KERN_INFO"via686b fix: ISA bridge done\n");
+}
+
+static void __init loongson2e_686b_func1_fixup(struct pci_dev *pdev)
+{
+ printk(KERN_INFO"via686b fix: IDE\n");
+
+ /* Modify IDE controller setup */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 48);
+ pci_write_config_byte(pdev, PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+ pci_write_config_byte(pdev, 0x40, 0x0b);
+ /* legacy mode */
+ pci_write_config_byte(pdev, 0x42, 0x09);
+
+#if 1/* play safe, otherwise we may see notebook's usb keyboard lockup */
+ /* disable read prefetch/write post buffers */
+ pci_write_config_byte(pdev, 0x41, 0x02);
+
+ /* use 3/4 as fifo thresh hold */
+ pci_write_config_byte(pdev, 0x43, 0x0a);
+ pci_write_config_byte(pdev, 0x44, 0x00);
+
+ pci_write_config_byte(pdev, 0x45, 0x00);
+#else
+ pci_write_config_byte(pdev, 0x41, 0xc2);
+ pci_write_config_byte(pdev, 0x43, 0x35);
+ pci_write_config_byte(pdev, 0x44, 0x1c);
+
+ pci_write_config_byte(pdev, 0x45, 0x10);
+#endif
+
+ printk(KERN_INFO"via686b fix: IDE done\n");
+}
+
+static void __init loongson2e_686b_func2_fixup(struct pci_dev *pdev)
+{
+ /* irq routing */
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 10);
+}
+
+static void __init loongson2e_686b_func3_fixup(struct pci_dev *pdev)
+{
+ /* irq routing */
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 11);
+}
+
+static void __init loongson2e_686b_func5_fixup(struct pci_dev *pdev)
+{
+ unsigned int val;
+ unsigned char c;
+
+ /* enable IO */
+ pci_write_config_byte(pdev, PCI_COMMAND,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+ pci_read_config_dword(pdev, 0x4, &val);
+ pci_write_config_dword(pdev, 0x4, val | 1);
+
+ /* route ac97 IRQ */
+ pci_write_config_byte(pdev, 0x3c, 9);
+
+ pci_read_config_byte(pdev, 0x8, &c);
+
+ /* link control: enable link & SGD PCM output */
+ pci_write_config_byte(pdev, 0x41, 0xcc);
+
+ /* disable game port, FM, midi, sb, enable write to reg2c-2f */
+ pci_write_config_byte(pdev, 0x42, 0x20);
+
+ /* we are using Avance logic codec */
+ pci_write_config_word(pdev, 0x2c, 0x1005);
+ pci_write_config_word(pdev, 0x2e, 0x4710);
+ pci_read_config_dword(pdev, 0x2c, &val);
+
+ pci_write_config_byte(pdev, 0x42, 0x0);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686,
+ loongson2e_686b_func0_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+ loongson2e_686b_func1_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2,
+ loongson2e_686b_func2_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3,
+ loongson2e_686b_func3_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5,
+ loongson2e_686b_func5_fixup);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+ loongson2e_nec_fixup);
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index bf2c41d1e9c..0f48498bc23 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -36,7 +36,7 @@ static char irq_tab[][5] __initdata = {
{0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int virq;
virq = irq_tab[slot][pin];
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
index 3c9ae41f751..59115962572 100644
--- a/arch/mips/pci/fixup-mpc30x.c
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -34,7 +34,7 @@ static const int irq_tab_mpc30x[] __initdata = {
[29] = MQ200_IRQ,
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (slot == 30)
return internal_func_irqs[PCI_FUNC(dev->devfn)];
diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c
deleted file mode 100644
index d45494807a3..00000000000
--- a/arch/mips/pci/fixup-ocelot-c.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work for the Linux port to the Ocelot board, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/momentum/ocelot_g/pci.c
- * Board-specific PCI routines for mv64340 controller.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int bus = dev->bus->number;
-
- if (bus == 0 && slot == 1)
- return 2; /* PCI-X A */
- if (bus == 1 && slot == 1)
- return 12; /* PCI-X B */
- if (bus == 1 && slot == 2)
- return 4; /* PCI B */
-
-return 0;
- panic("Whooops in pcibios_map_irq");
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/fixup-ocelot3.c b/arch/mips/pci/fixup-ocelot3.c
deleted file mode 100644
index ececc03ec62..00000000000
--- a/arch/mips/pci/fixup-ocelot3.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 Montavista Software Inc.
- * Author: Manish Lachwani (mlachwani@mvista.com)
- *
- * Looking at the schematics for the Ocelot-3 board, there are
- * two PCI busses and each bus has two PCI slots.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/mipsregs.h>
-
-/*
- * Do platform specific device initialization at
- * pci_enable_device() time
- */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int bus = dev->bus->number;
-
- if (bus == 0 && slot == 1)
- return 2; /* PCI-X A */
- if (bus == 0 && slot == 2)
- return 3; /* PCI-X B */
- if (bus == 1 && slot == 1)
- return 4; /* PCI A */
- if (bus == 1 && slot == 2)
- return 5; /* PCI B */
-
-return 0;
- panic("Whooops in pcibios_map_irq");
-}
diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c
new file mode 100644
index 00000000000..00261211dbf
--- /dev/null
+++ b/arch/mips/pci/fixup-pmcmsp.c
@@ -0,0 +1,216 @@
+/*
+ * PMC-Sierra MSP board specific pci fixups.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2005-2007 PMC-Sierra, Inc
+ *
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+
+#include <msp_pci.h>
+#include <msp_cic_int.h>
+
+/* PCI interrupt pins */
+#define IRQ4 MSP_INT_EXT4
+#define IRQ5 MSP_INT_EXT5
+#define IRQ6 MSP_INT_EXT6
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+/* Garibaldi Board IRQ wiring to PCI slots */
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */
+ {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */
+ {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */
+ {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */
+ {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */
+ {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */
+ {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */
+ {0, 0, 0, 0, 0 }, /* 6 (AD[16]): Unused */
+ {0, 0, 0, 0, 0 }, /* 7 (AD[17]): Unused */
+ {0, 0, 0, 0, 0 }, /* 8 (AD[18]): Unused */
+ {0, 0, 0, 0, 0 }, /* 9 (AD[19]): Unused */
+ {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */
+ {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */
+ {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */
+ {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */
+ {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */
+ {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */
+ {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */
+ {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */
+ {0, IRQ4, IRQ4, 0, 0 }, /* 18 (AD[28]): slot 0 */
+ {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */
+ {0, IRQ5, IRQ5, 0, 0 }, /* 20 (AD[30]): slot 1 */
+ {0, IRQ6, IRQ6, 0, 0 } /* 21 (AD[31]): slot 2 */
+};
+
+#elif defined(CONFIG_PMC_MSP7120_EVAL)
+
+/* MSP7120 Eval Board IRQ wiring to PCI slots */
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */
+ {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */
+ {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */
+ {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */
+ {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */
+ {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */
+ {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */
+ {0, IRQ6, IRQ6, 0, 0 }, /* 6 (AD[16]): slot 3 (mini) */
+ {0, IRQ5, IRQ5, 0, 0 }, /* 7 (AD[17]): slot 2 (mini) */
+ {0, IRQ4, IRQ4, IRQ4, IRQ4}, /* 8 (AD[18]): slot 0 (PCI) */
+ {0, IRQ5, IRQ5, IRQ5, IRQ5}, /* 9 (AD[19]): slot 1 (PCI) */
+ {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */
+ {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */
+ {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */
+ {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */
+ {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */
+ {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */
+ {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */
+ {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */
+ {0, 0, 0, 0, 0 }, /* 18 (AD[28]): Unused */
+ {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */
+ {0, 0, 0, 0, 0 }, /* 20 (AD[30]): Unused */
+ {0, 0, 0, 0, 0 } /* 21 (AD[31]): Unused */
+};
+
+#else
+
+/* Unknown board -- don't assign any IRQs */
+static char irq_tab[][5] __initdata = {
+ /* INTA INTB INTC INTD */
+ {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */
+ {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */
+ {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */
+ {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */
+ {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */
+ {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */
+ {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */
+ {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */
+ {0, 0, 0, 0, 0 }, /* 6 (AD[16]): Unused */
+ {0, 0, 0, 0, 0 }, /* 7 (AD[17]): Unused */
+ {0, 0, 0, 0, 0 }, /* 8 (AD[18]): Unused */
+ {0, 0, 0, 0, 0 }, /* 9 (AD[19]): Unused */
+ {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */
+ {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */
+ {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */
+ {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */
+ {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */
+ {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */
+ {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */
+ {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */
+ {0, 0, 0, 0, 0 }, /* 18 (AD[28]): Unused */
+ {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */
+ {0, 0, 0, 0, 0 }, /* 20 (AD[30]): Unused */
+ {0, 0, 0, 0, 0 } /* 21 (AD[31]): Unused */
+};
+#endif
+
+/*****************************************************************************
+ *
+ * FUNCTION: pcibios_plat_dev_init
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Perform platform specific device initialization at
+ * pci_enable_device() time.
+ * None are needed for the MSP7120 PCI Controller.
+ *
+ * INPUTS: dev - structure describing the PCI device
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL
+ *
+ ****************************************************************************/
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: pcibios_map_irq
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Perform board supplied PCI IRQ mapping routine.
+ *
+ * INPUTS: dev - unused
+ * slot - PCI slot. Identified by which bit of the AD[] bus
+ * drives the IDSEL line. AD[10] is 0, AD[31] is
+ * slot 21.
+ * pin - numbered using the scheme of the PCI_INTERRUPT_PIN
+ * field of the config header.
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: IRQ number
+ *
+ ****************************************************************************/
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+#if !defined(CONFIG_PMC_MSP7120_GW) && !defined(CONFIG_PMC_MSP7120_EVAL)
+ printk(KERN_WARNING "PCI: unknown board, no PCI IRQs assigned.\n");
+#endif
+ printk(KERN_WARNING "PCI: irq_tab returned %d for slot=%d pin=%d\n",
+ irq_tab[slot][pin], slot, pin);
+
+ return irq_tab[slot][pin];
+}
+
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/pci/fixup-pnx8550.c b/arch/mips/pci/fixup-pnx8550.c
index 50546dab668..96857ac63bf 100644
--- a/arch/mips/pci/fixup-pnx8550.c
+++ b/arch/mips/pci/fixup-pnx8550.c
@@ -45,7 +45,7 @@ void __init pcibios_fixup(void)
/* nothing to do here */
}
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return pnx8550_irq_tab[slot][pin];
}
diff --git a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c
index ceeb1860895..3cdbecb8e71 100644
--- a/arch/mips/pci/fixup-rbtx4927.c
+++ b/arch/mips/pci/fixup-rbtx4927.c
@@ -119,7 +119,7 @@ int pci_get_irq(struct pci_dev *dev, int pin)
return irq;
}
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char irq;
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index 36e5fb1b378..a45bedd1723 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -120,7 +120,7 @@ static inline int is_rm300_revd(void)
return (csmsr & 0xa0) == 0x20;
}
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
switch (sni_brd_type) {
case SNI_BRD_PCI_TOWER:
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index 734f2b71e16..720a2b720c5 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -23,7 +23,7 @@
#include <asm/vr41xx/tb0219.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = -1;
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
index c9e7cb4361a..e3eedf4bf9b 100644
--- a/arch/mips/pci/fixup-tb0226.c
+++ b/arch/mips/pci/fixup-tb0226.c
@@ -23,7 +23,7 @@
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/tb0226.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq = -1;
diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c
index fbe6bcb2819..267ab3dc3d4 100644
--- a/arch/mips/pci/fixup-tb0287.c
+++ b/arch/mips/pci/fixup-tb0287.c
@@ -22,7 +22,7 @@
#include <asm/vr41xx/tb0287.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char bus;
int irq = -1;
diff --git a/arch/mips/pci/fixup-tx4938.c b/arch/mips/pci/fixup-tx4938.c
index f455520ada8..2485f47dfe6 100644
--- a/arch/mips/pci/fixup-tx4938.c
+++ b/arch/mips/pci/fixup-tx4938.c
@@ -69,7 +69,7 @@ int pci_get_irq(struct pci_dev *dev, int pin)
return irq;
}
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
unsigned char irq = 0;
diff --git a/arch/mips/pci/fixup-vr4133.c b/arch/mips/pci/fixup-vr4133.c
index a8d9d22b13d..de5e5f6bbf4 100644
--- a/arch/mips/pci/fixup-vr4133.c
+++ b/arch/mips/pci/fixup-vr4133.c
@@ -169,7 +169,7 @@ void i8259_init(void)
}
#endif
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
extern int pci_probe_only;
pci_probe_only = 1;
diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c
index 3357c1300bb..3d277549d5d 100644
--- a/arch/mips/pci/fixup-wrppmc.c
+++ b/arch/mips/pci/fixup-wrppmc.c
@@ -25,7 +25,7 @@ static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = {
[6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0},
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return pci_irq_tab[slot][pin];
}
diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c
index 81d77a587a5..fdafb13a793 100644
--- a/arch/mips/pci/fixup-yosemite.c
+++ b/arch/mips/pci/fixup-yosemite.c
@@ -26,7 +26,7 @@
#include <linux/init.h>
#include <linux/pci.h>
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (pin == 0)
return -1;
diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c
index dc35270b65a..f742c51acf0 100644
--- a/arch/mips/pci/ops-bonito64.c
+++ b/arch/mips/pci/ops-bonito64.c
@@ -29,83 +29,60 @@
#define PCI_ACCESS_READ 0
#define PCI_ACCESS_WRITE 1
-/*
- * PCI configuration cycle AD bus definition
- */
-/* Type 0 */
-#define PCI_CFG_TYPE0_REG_SHF 0
-#define PCI_CFG_TYPE0_FUNC_SHF 8
+#ifdef CONFIG_LEMOTE_FULONG
+#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(BONITO_PCICFG_BASE | (offset))
+#define ID_SEL_BEGIN 11
+#else
+#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset))
+#define ID_SEL_BEGIN 10
+#endif
+#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
-/* Type 1 */
-#define PCI_CFG_TYPE1_REG_SHF 0
-#define PCI_CFG_TYPE1_FUNC_SHF 8
-#define PCI_CFG_TYPE1_DEV_SHF 11
-#define PCI_CFG_TYPE1_BUS_SHF 16
static int bonito64_pcibios_config_access(unsigned char access_type,
struct pci_bus *bus,
unsigned int devfn, int where,
u32 * data)
{
- unsigned char busnum = bus->number;
+ u32 busnum = bus->number;
+ u32 addr, type;
u32 dummy;
- u64 pci_addr;
-
- /* Algorithmics Bonito64 system controller. */
+ void *addrp;
+ int device = PCI_SLOT(devfn);
+ int function = PCI_FUNC(devfn);
+ int reg = where & ~3;
- if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) {
- /* We number bus 0 devices from 0..21 */
- return -1;
- }
-
- /* Clear cause register bits */
- BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
- BONITO_PCICMD_MTABORT_CLR);
-
- /*
- * Setup pattern to be used as PCI "address" for
- * Type 0 cycle
- */
if (busnum == 0) {
- /* IDSEL */
- pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10);
- } else {
- /* Bus number */
- pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF;
-
- /* Device number */
- pci_addr |=
- PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF;
- }
-
- /* Function (same for Type 0/1) */
- pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF;
-
- /* Register number (same for Type 0/1) */
- pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF;
+ /* Type 0 configuration for onboard PCI bus */
+ if (device > MAX_DEV_NUM)
+ return -1;
- if (busnum == 0) {
- /* Type 0 */
- BONITO_PCIMAP_CFG = pci_addr >> 16;
+ addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
+ type = 0;
} else {
- /* Type 1 */
- BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000;
+ /* Type 1 configuration for offboard PCI bus */
+ addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+ type = 0x10000;
}
- pci_addr &= 0xffff;
+ /* Clear aborts */
+ BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR;
+
+ BONITO_PCIMAP_CFG = (addr >> 16) | type;
/* Flush Bonito register block */
dummy = BONITO_PCIMAP_CFG;
- iob(); /* sync */
+ mmiowb();
- /* Perform access */
+ addrp = CFG_SPACE_REG(addr & 0xffff);
if (access_type == PCI_ACCESS_WRITE) {
- *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data;
-
+ writel(cpu_to_le32(*data), addrp);
+#ifndef CONFIG_LEMOTE_FULONG
/* Wait till done */
while (BONITO_PCIMSTAT & 0xF);
+#endif
} else {
- *(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr);
+ *data = le32_to_cpu(readl(addrp));
}
/* Detect Master/Target abort */
@@ -121,6 +98,7 @@ static int bonito64_pcibios_config_access(unsigned char access_type,
}
return 0;
+
}
diff --git a/arch/mips/pci/ops-marvell.c b/arch/mips/pci/ops-marvell.c
deleted file mode 100644
index 1ac5c59199d..00000000000
--- a/arch/mips/pci/ops-marvell.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/marvell.h>
-
-static int mv_read_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 * val)
-{
- struct mv_pci_controller *mvbc = bus->sysdata;
- unsigned long address_reg, data_reg;
- u32 address;
-
- address_reg = mvbc->config_addr;
- data_reg = mvbc->config_vreg;
-
- /* Accessing device 31 crashes those Marvells. Since years.
- Will they ever make sane controllers ... */
- if (PCI_SLOT(devfn) == 31)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- address = (bus->number << 16) | (devfn << 8) |
- (where & 0xfc) | 0x80000000;
-
- /* start the configuration cycle */
- MV_WRITE(address_reg, address);
-
- switch (size) {
- case 1:
- *val = MV_READ_8(data_reg + (where & 0x3));
- break;
-
- case 2:
- *val = MV_READ_16(data_reg + (where & 0x3));
- break;
-
- case 4:
- *val = MV_READ(data_reg);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int mv_write_config(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- struct mv_pci_controller *mvbc = bus->sysdata;
- unsigned long address_reg, data_reg;
- u32 address;
-
- address_reg = mvbc->config_addr;
- data_reg = mvbc->config_vreg;
-
- /* Accessing device 31 crashes those Marvells. Since years.
- Will they ever make sane controllers ... */
- if (PCI_SLOT(devfn) == 31)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- address = (bus->number << 16) | (devfn << 8) |
- (where & 0xfc) | 0x80000000;
-
- /* start the configuration cycle */
- MV_WRITE(address_reg, address);
-
- switch (size) {
- case 1:
- MV_WRITE_8(data_reg + (where & 0x3), val);
- break;
-
- case 2:
- MV_WRITE_16(data_reg + (where & 0x3), val);
- break;
-
- case 4:
- MV_WRITE(data_reg, val);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops mv_pci_ops = {
- .read = mv_read_config,
- .write = mv_write_config
-};
diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c
deleted file mode 100644
index a8d38dc8c50..00000000000
--- a/arch/mips/pci/ops-nile4.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/bootinfo.h>
-
-#include <asm/lasat/lasat.h>
-#include <asm/gt64120.h>
-#include <asm/nile4.h>
-
-#define PCI_ACCESS_READ 0
-#define PCI_ACCESS_WRITE 1
-
-#define LO(reg) (reg / 4)
-#define HI(reg) (reg / 4 + 1)
-
-volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE;
-
-static DEFINE_SPINLOCK(nile4_pci_lock);
-
-static int nile4_pcibios_config_access(unsigned char access_type,
- struct pci_bus *bus, unsigned int devfn, int where, u32 * val)
-{
- unsigned char busnum = bus->number;
- u32 adr, mask, err;
-
- if ((busnum == 0) && (PCI_SLOT(devfn) > 8))
- /* The addressing scheme chosen leaves room for just
- * 8 devices on the first busnum (besides the PCI
- * controller itself) */
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) {
- /* Access controller registers directly */
- if (access_type == PCI_ACCESS_WRITE) {
- vrc_pciregs[(0x200 + where) >> 2] = *val;
- } else {
- *val = vrc_pciregs[(0x200 + where) >> 2];
- }
- return PCIBIOS_SUCCESSFUL;
- }
-
- /* Temporarily map PCI Window 1 to config space */
- mask = vrc_pciregs[LO(NILE4_PCIINIT1)];
- vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0);
-
- /* Clear PCI Error register. This also clears the Error Type
- * bits in the Control register */
- vrc_pciregs[LO(NILE4_PCIERR)] = 0;
- vrc_pciregs[HI(NILE4_PCIERR)] = 0;
-
- /* Setup address */
- if (busnum == 0)
- adr =
- KSEG1ADDR(PCI_WINDOW1) +
- ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8)
- | (where & ~3));
- else
- adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) |
- (where & ~3);
-
- if (access_type == PCI_ACCESS_WRITE)
- *(u32 *) adr = *val;
- else
- *val = *(u32 *) adr;
-
- /* Check for master or target abort */
- err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7;
-
- /* Restore PCI Window 1 */
- vrc_pciregs[LO(NILE4_PCIINIT1)] = mask;
-
- if (err)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 * val)
-{
- unsigned long flags;
- u32 data = 0;
- int err;
-
- if ((size == 2) && (where & 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
- else if ((size == 4) && (where & 3))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- spin_lock_irqsave(&nile4_pci_lock, flags);
- err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
- &data);
- spin_unlock_irqrestore(&nile4_pci_lock, flags);
-
- if (err)
- return err;
-
- if (size == 1)
- *val = (data >> ((where & 3) << 3)) & 0xff;
- else if (size == 2)
- *val = (data >> ((where & 3) << 3)) & 0xffff;
- else
- *val = data;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn,
- int where, int size, u32 val)
-{
- unsigned long flags;
- u32 data = 0;
- int err;
-
- if ((size == 2) && (where & 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
- else if ((size == 4) && (where & 3))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- spin_lock_irqsave(&nile4_pci_lock, flags);
- err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
- &data);
- spin_unlock_irqrestore(&nile4_pci_lock, flags);
-
- if (err)
- return err;
-
- if (size == 1)
- data = (data & ~(0xff << ((where & 3) << 3))) |
- (val << ((where & 3) << 3));
- else if (size == 2)
- data = (data & ~(0xffff << ((where & 3) << 3))) |
- (val << ((where & 3) << 3));
- else
- data = val;
-
- if (nile4_pcibios_config_access
- (PCI_ACCESS_WRITE, bus, devfn, where, &data))
- return -1;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops nile4_pci_ops = {
- .read = nile4_pcibios_read,
- .write = nile4_pcibios_write,
-};
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c
new file mode 100644
index 00000000000..09fa007c1d1
--- /dev/null
+++ b/arch/mips/pci/ops-pmcmsp.c
@@ -0,0 +1,994 @@
+/*
+ * PMC-Sierra MSP board specific pci_ops
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2005-2007 PMC-Sierra, Inc
+ *
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * Much of the code is derived from the original DDB5074 port by
+ * Geert Uytterhoeven <geert@sonycom.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#define PCI_COUNTERS 1
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+#include <asm/mipsmtregs.h>
+#endif
+
+#include <msp_prom.h>
+#include <msp_cic_int.h>
+#include <msp_pci.h>
+#include <msp_regs.h>
+#include <msp_regops.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+static char proc_init;
+extern struct proc_dir_entry *proc_bus_pci_dir;
+unsigned int pci_int_count[32];
+
+static void pci_proc_init(void);
+
+/*****************************************************************************
+ *
+ * FUNCTION: read_msp_pci_counts
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Prints the count of how many times each PCI
+ * interrupt has asserted. Can be invoked by the
+ * /proc filesystem.
+ *
+ * INPUTS: page - part of STDOUT calculation
+ * off - part of STDOUT calculation
+ * count - part of STDOUT calculation
+ * data - unused
+ *
+ * OUTPUTS: start - new start location
+ * eof - end of file pointer
+ *
+ * RETURNS: len - STDOUT length
+ *
+ ****************************************************************************/
+static int read_msp_pci_counts(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int i;
+ int len = 0;
+ unsigned int intcount, total = 0;
+
+ for (i = 0; i < 32; ++i) {
+ intcount = pci_int_count[i];
+ if (intcount != 0) {
+ len += sprintf(page + len, "[%d] = %u\n", i, intcount);
+ total += intcount;
+ }
+ }
+
+ len += sprintf(page + len, "total = %u\n", total);
+ if (len <= off+count)
+ *eof = 1;
+
+ *start = page + off;
+ len -= off;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: gen_pci_cfg_wr
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Generates a configuration write cycle for debug purposes.
+ * The IDSEL line asserted and location and data written are
+ * immaterial. Just want to be able to prove that a
+ * configuration write can be correctly generated on the
+ * PCI bus. Intent is that this function by invocable from
+ * the /proc filesystem.
+ *
+ * INPUTS: page - part of STDOUT calculation
+ * off - part of STDOUT calculation
+ * count - part of STDOUT calculation
+ * data - unused
+ *
+ * OUTPUTS: start - new start location
+ * eof - end of file pointer
+ *
+ * RETURNS: len - STDOUT length
+ *
+ ****************************************************************************/
+static int gen_pci_cfg_wr(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ unsigned char where = 0; /* Write to static Device/Vendor ID */
+ unsigned char bus_num = 0; /* Bus 0 */
+ unsigned char dev_fn = 0xF; /* Arbitrary device number */
+ u32 wr_data = 0xFF00AA00; /* Arbitrary data */
+ struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+ int len = 0;
+ unsigned long value;
+ int intr;
+
+ len += sprintf(page + len, "PMC MSP PCI: Beginning\n");
+
+ if (proc_init == 0) {
+ pci_proc_init();
+ proc_init = ~0;
+ }
+
+ len += sprintf(page + len, "PMC MSP PCI: Before Cfg Wr\n");
+
+ /*
+ * Generate PCI Configuration Write Cycle
+ */
+
+ /* Clear cause register bits */
+ preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+ /* Setup address that is to appear on PCI bus */
+ preg->config_addr = BPCI_CFGADDR_ENABLE |
+ (bus_num << BPCI_CFGADDR_BUSNUM_SHF) |
+ (dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |
+ (where & 0xFC);
+
+ value = cpu_to_le32(wr_data);
+
+ /* Launch the PCI configuration write cycle */
+ *PCI_CONFIG_SPACE_REG = value;
+
+ /*
+ * Check if the PCI configuration cycle (rd or wr) succeeded, by
+ * checking the status bits for errors like master or target abort.
+ */
+ intr = preg->if_status;
+
+ len += sprintf(page + len, "PMC MSP PCI: After Cfg Wr\n");
+
+ /* Handle STDOUT calculations */
+ if (len <= off+count)
+ *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len > count)
+ len = count;
+ if (len < 0)
+ len = 0;
+
+ return len;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: pci_proc_init
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Create entries in the /proc filesystem for debug access.
+ *
+ * INPUTS: none
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: none
+ *
+ ****************************************************************************/
+static void pci_proc_init(void)
+{
+ create_proc_read_entry("pmc_msp_pci_rd_cnt", 0, NULL,
+ read_msp_pci_counts, NULL);
+ create_proc_read_entry("pmc_msp_pci_cfg_wr", 0, NULL,
+ gen_pci_cfg_wr, NULL);
+}
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+spinlock_t bpci_lock = SPIN_LOCK_UNLOCKED;
+
+/*****************************************************************************
+ *
+ * STRUCT: pci_io_resource
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Defines the address range that pciauto() will use to
+ * assign to the I/O BARs of PCI devices.
+ *
+ * Use the start and end addresses of the MSP7120 PCI Host
+ * Controller I/O space, in the form that they appear on the
+ * PCI bus AFTER MSP7120 has performed address translation.
+ *
+ * For I/O accesses, MSP7120 ignores OATRAN and maps I/O
+ * accesses into the bottom 0xFFF region of address space,
+ * so that is the range to put into the pci_io_resource
+ * struct.
+ *
+ * In MSP4200, the start address was 0x04 instead of the
+ * expected 0x00. Will just assume there was a good reason
+ * for this!
+ *
+ * NOTES: Linux, by default, will assign I/O space to the lowest
+ * region of address space. Since MSP7120 and Linux,
+ * by default, have no offset in between how they map, the
+ * io_offset element of pci_controller struct should be set
+ * to zero.
+ * ELEMENTS:
+ * name - String used for a meaningful name.
+ *
+ * start - Start address of MSP7120's I/O space, as MSP7120 presents
+ * the address on the PCI bus.
+ *
+ * end - End address of MSP7120's I/O space, as MSP7120 presents
+ * the address on the PCI bus.
+ *
+ * flags - Attributes indicating the type of resource. In this case,
+ * indicate I/O space.
+ *
+ ****************************************************************************/
+static struct resource pci_io_resource = {
+ .name = "pci IO space",
+ .start = 0x04,
+ .end = 0x0FFF,
+ .flags = IORESOURCE_IO /* I/O space */
+};
+
+/*****************************************************************************
+ *
+ * STRUCT: pci_mem_resource
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Defines the address range that pciauto() will use to
+ * assign to the memory BARs of PCI devices.
+ *
+ * The .start and .end values are dependent upon how address
+ * translation is performed by the OATRAN regiser.
+ *
+ * The values to use for .start and .end are the values
+ * in the form they appear on the PCI bus AFTER MSP7120 has
+ * performed OATRAN address translation.
+ *
+ * ELEMENTS:
+ * name - String used for a meaningful name.
+ *
+ * start - Start address of MSP7120's memory space, as MSP7120 presents
+ * the address on the PCI bus.
+ *
+ * end - End address of MSP7120's memory space, as MSP7120 presents
+ * the address on the PCI bus.
+ *
+ * flags - Attributes indicating the type of resource. In this case,
+ * indicate memory space.
+ *
+ ****************************************************************************/
+static struct resource pci_mem_resource = {
+ .name = "pci memory space",
+ .start = MSP_PCI_SPACE_BASE,
+ .end = MSP_PCI_SPACE_END,
+ .flags = IORESOURCE_MEM /* memory space */
+};
+
+/*****************************************************************************
+ *
+ * FUNCTION: bpci_interrupt
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: PCI status interrupt handler. Updates the count of how
+ * many times each status bit has been set, then clears
+ * the status bits. If the appropriate macros are defined,
+ * these counts can be viewed via the /proc filesystem.
+ *
+ * INPUTS: irq - unused
+ * dev_id - unused
+ * pt_regs - unused
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ *
+ ****************************************************************************/
+static int bpci_interrupt(int irq, void *dev_id)
+{
+ struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+ unsigned int stat = preg->if_status;
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+ int i;
+ for (i = 0; i < 32; ++i) {
+ if ((1 << i) & stat)
+ ++pci_int_count[i];
+ }
+#endif /* PROC_FS && PCI_COUNTERS */
+
+ /* printk("PCI ISR: Status=%08X\n", stat); */
+
+ /* write to clear all asserted interrupts */
+ preg->if_status = stat;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_config_access
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Performs a PCI configuration access (rd or wr), then
+ * checks that the access succeeded by querying MSP7120's
+ * PCI status bits.
+ *
+ * INPUTS:
+ * access_type - kind of PCI configuration cycle to perform
+ * (read or write). Legal values are
+ * PCI_ACCESS_WRITE and PCI_ACCESS_READ.
+ *
+ * bus - pointer to the bus number of the device to
+ * be targetted for the configuration cycle.
+ * The only element of the pci_bus structure
+ * used is bus->number. This argument determines
+ * if the configuration access will be Type 0 or
+ * Type 1. Since MSP7120 assumes itself to be the
+ * PCI Host, any non-zero bus->number generates
+ * a Type 1 access.
+ *
+ * devfn - this is an 8-bit field. The lower three bits
+ * specify the function number of the device to
+ * be targetted for the configuration cycle, with
+ * all three-bit combinations being legal. The
+ * upper five bits specify the device number,
+ * with legal values being 10 to 31.
+ *
+ * where - address within the Configuration Header
+ * space to access.
+ *
+ * data - for write accesses, contains the data to
+ * write.
+ *
+ * OUTPUTS:
+ * data - for read accesses, contains the value read.
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - access failure
+ *
+ ****************************************************************************/
+int msp_pcibios_config_access(unsigned char access_type,
+ struct pci_bus *bus,
+ unsigned int devfn,
+ unsigned char where,
+ u32 *data)
+{
+ struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+ unsigned char bus_num = bus->number;
+ unsigned char dev_fn = (unsigned char)devfn;
+ unsigned long flags;
+ unsigned long intr;
+ unsigned long value;
+ static char pciirqflag;
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+ unsigned int vpe_status;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS)
+ if (proc_init == 0) {
+ pci_proc_init();
+ proc_init = ~0;
+ }
+#endif /* CONFIG_PROC_FS && PCI_COUNTERS */
+
+ /*
+ * Just the first time this function invokes, allocate
+ * an interrupt line for PCI host status interrupts. The
+ * allocation assigns an interrupt handler to the interrupt.
+ */
+ if (pciirqflag == 0) {
+ request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */
+ bpci_interrupt,
+ SA_SHIRQ | SA_INTERRUPT,
+ "PMC MSP PCI Host",
+ preg);
+ pciirqflag = ~0;
+ }
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+ local_irq_save(flags);
+ vpe_status = dvpe();
+#else
+ spin_lock_irqsave(&bpci_lock, flags);
+#endif
+
+ /*
+ * Clear PCI cause register bits.
+ *
+ * In Polo, the PCI Host had a dedicated DMA called the
+ * Block Copy (not to be confused with the general purpose Block
+ * Copy Engine block). There appear to have been special interrupts
+ * for this Block Copy, called Block Copy 0 Fault (BC0F) and
+ * Block Copy 1 Fault (BC1F). MSP4200 and MSP7120 don't have this
+ * dedicated Block Copy block, so these two interrupts are now
+ * marked reserved. In case the Block Copy is resurrected in a
+ * future design, maintain the code that treats these two interrupts
+ * specially.
+ *
+ * Write to clear all interrupts in the PCI status register, aside
+ * from BC0F and BC1F.
+ */
+ preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+ /* Setup address that is to appear on PCI bus */
+ preg->config_addr = BPCI_CFGADDR_ENABLE |
+ (bus_num << BPCI_CFGADDR_BUSNUM_SHF) |
+ (dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) |
+ (where & 0xFC);
+
+ /* IF access is a PCI configuration write */
+ if (access_type == PCI_ACCESS_WRITE) {
+ value = cpu_to_le32(*data);
+ *PCI_CONFIG_SPACE_REG = value;
+ } else {
+ /* ELSE access is a PCI configuration read */
+ value = le32_to_cpu(*PCI_CONFIG_SPACE_REG);
+ *data = value;
+ }
+
+ /*
+ * Check if the PCI configuration cycle (rd or wr) succeeded, by
+ * checking the status bits for errors like master or target abort.
+ */
+ intr = preg->if_status;
+
+ /* Clear config access */
+ preg->config_addr = 0;
+
+ /* IF error occurred */
+ if (intr & ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F)) {
+ /* Clear status bits */
+ preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+ evpe(vpe_status);
+ local_irq_restore(flags);
+#else
+ spin_unlock_irqrestore(&bpci_lock, flags);
+#endif
+
+ return -1;
+ }
+
+#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL)
+ evpe(vpe_status);
+ local_irq_restore(flags);
+#else
+ spin_unlock_irqrestore(&bpci_lock, flags);
+#endif
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_read_config_byte
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Read a byte from PCI configuration address spac
+ * Since the hardware can't address 8 bit chunks
+ * directly, read a 32-bit chunk, then mask off extraneous
+ * bits.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the read is destined for.
+ * devfn - device/function combination that the read is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ *
+ * OUTPUTS val - read data
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_byte(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u32 *val)
+{
+ u32 data = 0;
+
+ /*
+ * If the config access did not complete normally (e.g., underwent
+ * master abort) do the PCI compliant thing, which is to supply an
+ * all ones value.
+ */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data)) {
+ *val = 0xFFFFFFFF;
+ return -1;
+ }
+
+ *val = (data >> ((where & 3) << 3)) & 0x0ff;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_read_config_word
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Read a word (16 bits) from PCI configuration address space.
+ * Since the hardware can't address 16 bit chunks
+ * directly, read a 32-bit chunk, then mask off extraneous
+ * bits.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the read is destined for.
+ * devfn - device/function combination that the read is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ *
+ * OUTPUTS val - read data
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * PCIBIOS_BAD_REGISTER_NUMBER - bad register address
+ * -1 - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_word(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u32 *val)
+{
+ u32 data = 0;
+
+ /* if (where & 1) */ /* Commented out non-compliant code.
+ * Should allow word access to configuration
+ * registers, with only exception being when
+ * the word access would wrap around into
+ * the next dword.
+ */
+ if ((where & 3) == 3) {
+ *val = 0xFFFFFFFF;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ /*
+ * If the config access did not complete normally (e.g., underwent
+ * master abort) do the PCI compliant thing, which is to supply an
+ * all ones value.
+ */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data)) {
+ *val = 0xFFFFFFFF;
+ return -1;
+ }
+
+ *val = (data >> ((where & 3) << 3)) & 0x0ffff;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_read_config_dword
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Read a double word (32 bits) from PCI configuration
+ * address space.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the read is destined for.
+ * devfn - device/function combination that the read is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ *
+ * OUTPUTS val - read data
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * PCIBIOS_BAD_REGISTER_NUMBER - bad register address
+ * -1 - read access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_read_config_dword(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u32 *val)
+{
+ u32 data = 0;
+
+ /* Address must be dword aligned. */
+ if (where & 3) {
+ *val = 0xFFFFFFFF;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ /*
+ * If the config access did not complete normally (e.g., underwent
+ * master abort) do the PCI compliant thing, which is to supply an
+ * all ones value.
+ */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data)) {
+ *val = 0xFFFFFFFF;
+ return -1;
+ }
+
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_write_config_byte
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Write a byte to PCI configuration address space.
+ * Since the hardware can't address 8 bit chunks
+ * directly, a read-modify-write is performed.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * val - value to write
+ *
+ * OUTPUTS none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_byte(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u8 val)
+{
+ u32 data = 0;
+
+ /* read config space */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return -1;
+
+ /* modify the byte within the dword */
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ /* write back the full dword */
+ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+ where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_write_config_word
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Write a word (16-bits) to PCI configuration address space.
+ * Since the hardware can't address 16 bit chunks
+ * directly, a read-modify-write is performed.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * val - value to write
+ *
+ * OUTPUTS none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * PCIBIOS_BAD_REGISTER_NUMBER - bad register address
+ * -1 - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_word(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u16 val)
+{
+ u32 data = 0;
+
+ /* Fixed non-compliance: if (where & 1) */
+ if ((where & 3) == 3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ /* read config space */
+ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
+ where, &data))
+ return -1;
+
+ /* modify the word within the dword */
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+
+ /* write back the full dword */
+ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+ where, &data))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_write_config_dword
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Write a double word (32-bits) to PCI configuration address
+ * space.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * val - value to write
+ *
+ * OUTPUTS none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * PCIBIOS_BAD_REGISTER_NUMBER - bad register address
+ * -1 - write access failure
+ *
+ ****************************************************************************/
+static int
+msp_pcibios_write_config_dword(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ u32 val)
+{
+ /* check that address is dword aligned */
+ if (where & 3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ /* perform write */
+ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn,
+ where, &val))
+ return -1;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_read_config
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Interface the PCI configuration read request with
+ * the appropriate function, based on how many bytes
+ * the read request is.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * size - in units of bytes, should be 1, 2, or 4.
+ *
+ * OUTPUTS val - value read, with any extraneous bytes masked
+ * to zero.
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - failure
+ *
+ ****************************************************************************/
+int
+msp_pcibios_read_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ int size,
+ u32 *val)
+{
+ if (size == 1) {
+ if (msp_pcibios_read_config_byte(bus, devfn, where, val)) {
+ return -1;
+ }
+ } else if (size == 2) {
+ if (msp_pcibios_read_config_word(bus, devfn, where, val)) {
+ return -1;
+ }
+ } else if (size == 4) {
+ if (msp_pcibios_read_config_dword(bus, devfn, where, val)) {
+ return -1;
+ }
+ } else {
+ *val = 0xFFFFFFFF;
+ return -1;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pcibios_write_config
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Interface the PCI configuration write request with
+ * the appropriate function, based on how many bytes
+ * the read request is.
+ *
+ * INPUTS bus - structure containing attributes for the PCI bus
+ * that the write is destined for.
+ * devfn - device/function combination that the write is
+ * destined for.
+ * where - register within the Configuration Header space
+ * to access.
+ * size - in units of bytes, should be 1, 2, or 4.
+ * val - value to write
+ *
+ * OUTPUTS: none
+ *
+ * RETURNS: PCIBIOS_SUCCESSFUL - success
+ * -1 - failure
+ *
+ ****************************************************************************/
+int
+msp_pcibios_write_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where,
+ int size,
+ u32 val)
+{
+ if (size == 1) {
+ if (msp_pcibios_write_config_byte(bus, devfn,
+ where, (u8)(0xFF & val))) {
+ return -1;
+ }
+ } else if (size == 2) {
+ if (msp_pcibios_write_config_word(bus, devfn,
+ where, (u16)(0xFFFF & val))) {
+ return -1;
+ }
+ } else if (size == 4) {
+ if (msp_pcibios_write_config_dword(bus, devfn, where, val)) {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/*****************************************************************************
+ *
+ * STRUCTURE: msp_pci_ops
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: structure to abstract the hardware specific PCI
+ * configuration accesses.
+ *
+ * ELEMENTS:
+ * read - function for Linux to generate PCI Configuration reads.
+ * write - function for Linux to generate PCI Configuration writes.
+ *
+ ****************************************************************************/
+struct pci_ops msp_pci_ops = {
+ .read = msp_pcibios_read_config,
+ .write = msp_pcibios_write_config
+};
+
+/*****************************************************************************
+ *
+ * STRUCTURE: msp_pci_controller
+ * _________________________________________________________________________
+ *
+ * Describes the attributes of the MSP7120 PCI Host Controller
+ *
+ * ELEMENTS:
+ * pci_ops - abstracts the hardware specific PCI configuration
+ * accesses.
+ *
+ * mem_resource - address range pciauto() uses to assign to PCI device
+ * memory BARs.
+ *
+ * mem_offset - offset between how MSP7120 outbound PCI memory
+ * transaction addresses appear on the PCI bus and how Linux
+ * wants to configure memory BARs of the PCI devices.
+ * MSP7120 does nothing funky, so just set to zero.
+ *
+ * io_resource - address range pciauto() uses to assign to PCI device
+ * I/O BARs.
+ *
+ * io_offset - offset between how MSP7120 outbound PCI I/O
+ * transaction addresses appear on the PCI bus and how
+ * Linux defaults to configure I/O BARs of the PCI devices.
+ * MSP7120 maps outbound I/O accesses into the bottom
+ * bottom 4K of PCI address space (and ignores OATRAN).
+ * Since the Linux default is to configure I/O BARs to the
+ * bottom 4K, no special offset is needed. Just set to zero.
+ *
+ ****************************************************************************/
+static struct pci_controller msp_pci_controller = {
+ .pci_ops = &msp_pci_ops,
+ .mem_resource = &pci_mem_resource,
+ .mem_offset = 0,
+ .io_resource = &pci_io_resource,
+ .io_offset = 0
+};
+
+/*****************************************************************************
+ *
+ * FUNCTION: msp_pci_init
+ * _________________________________________________________________________
+ *
+ * DESCRIPTION: Initialize the PCI Host Controller and register it with
+ * Linux so Linux can seize control of the PCI bus.
+ *
+ ****************************************************************************/
+void __init msp_pci_init(void)
+{
+ struct msp_pci_regs *preg = (void *)PCI_BASE_REG;
+ u32 id;
+
+ /* Extract Device ID */
+ id = read_reg32(PCI_JTAG_DEVID_REG, 0xFFFF) >> 12;
+
+ /* Check if JTAG ID identifies MSP7120 */
+ if (!MSP_HAS_PCI(id)) {
+ printk(KERN_WARNING "PCI: No PCI; id reads as %x\n", id);
+ goto no_pci;
+ }
+
+ /*
+ * Enable flushing of the PCI-SDRAM queue upon a read
+ * of the SDRAM's Memory Configuration Register.
+ */
+ *(unsigned long *)QFLUSH_REG_1 = 3;
+
+ /* Configure PCI Host Controller. */
+ preg->if_status = ~0; /* Clear cause register bits */
+ preg->config_addr = 0; /* Clear config access */
+ preg->oatran = MSP_PCI_OATRAN; /* PCI outbound addr translation */
+ preg->if_mask = 0xF8BF87C0; /* Enable all PCI status interrupts */
+
+ /* configure so inb(), outb(), and family are functional */
+ set_io_port_base(MSP_PCI_IOSPACE_BASE);
+
+ /* Tell Linux the details of the MSP7120 PCI Host Controller */
+ register_pci_controller(&msp_pci_controller);
+
+ return;
+
+no_pci:
+ /* Disable PCI channel */
+ printk(KERN_WARNING "PCI: no host PCI bus detected\n");
+}
diff --git a/arch/mips/pci/ops-tx4938.c b/arch/mips/pci/ops-tx4938.c
index 44500708451..a450c406203 100644
--- a/arch/mips/pci/ops-tx4938.c
+++ b/arch/mips/pci/ops-tx4938.c
@@ -46,50 +46,63 @@ struct resource tx4938_pcic1_pci_mem_resource = {
.flags = IORESOURCE_MEM
};
-static int mkaddr(int bus, int dev_fn, int where, int *flagsp)
+static int mkaddr(int bus, int dev_fn, int where,
+ struct tx4938_pcic_reg *pcicptr)
{
if (bus > 0) {
/* Type 1 configuration */
- tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+ pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1;
} else {
if (dev_fn >= PCI_DEVFN(TX4938_PCIC_MAX_DEVNU, 0))
return -1;
/* Type 0 configuration */
- tx4938_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
+ pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) |
((dev_fn & 0xff) << 0x08) | (where & 0xfc);
}
/* clear M_ABORT and Disable M_ABORT Int. */
- tx4938_pcicptr->pcistatus =
- (tx4938_pcicptr->pcistatus & 0x0000ffff) |
+ pcicptr->pcistatus =
+ (pcicptr->pcistatus & 0x0000ffff) |
(PCI_STATUS_REC_MASTER_ABORT << 16);
- tx4938_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
+ pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT;
return 0;
}
-static int check_abort(int flags)
+static int check_abort(struct tx4938_pcic_reg *pcicptr)
{
int code = PCIBIOS_SUCCESSFUL;
/* wait write cycle completion before checking error status */
- while (tx4938_pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
+ while (pcicptr->pcicstatus & TX4938_PCIC_PCICSTATUS_IWB)
;
- if (tx4938_pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
- tx4938_pcicptr->pcistatus =
- (tx4938_pcicptr->
+ if (pcicptr->pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) {
+ pcicptr->pcistatus =
+ (pcicptr->
pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT
<< 16);
- tx4938_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
+ pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT;
code = PCIBIOS_DEVICE_NOT_FOUND;
}
return code;
}
+extern struct pci_controller tx4938_pci_controller[];
+extern struct tx4938_pcic_reg *get_tx4938_pcicptr(int ch);
+
+static struct tx4938_pcic_reg *pci_bus_to_pcicptr(struct pci_bus *bus)
+{
+ struct pci_controller *channel = bus->sysdata;
+ return get_tx4938_pcicptr(channel - &tx4938_pci_controller[0]);
+}
+
static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 * val)
{
- int flags, retval, dev, busno, func;
+ int retval, dev, busno, func;
+ struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
+ void __iomem *cfgdata =
+ (void __iomem *)(unsigned long)&pcicptr->g2pcfgdata;
dev = PCI_SLOT(devfn);
func = PCI_FUNC(devfn);
@@ -101,32 +114,32 @@ static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
busno = 0;
}
- if (mkaddr(busno, devfn, where, &flags))
+ if (mkaddr(busno, devfn, where, pcicptr))
return -1;
switch (size) {
case 1:
- *val = *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
#ifdef __BIG_ENDIAN
- ((where & 3) ^ 3));
+ cfgdata += (where & 3) ^ 3;
#else
- (where & 3));
+ cfgdata += where & 3;
#endif
+ *val = __raw_readb(cfgdata);
break;
case 2:
- *val = *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
#ifdef __BIG_ENDIAN
- ((where & 3) ^ 2));
+ cfgdata += (where & 2) ^ 2;
#else
- (where & 3));
+ cfgdata += where & 2;
#endif
+ *val = __raw_readw(cfgdata);
break;
case 4:
- *val = tx4938_pcicptr->g2pcfgdata;
+ *val = __raw_readl(cfgdata);
break;
}
- retval = check_abort(flags);
+ retval = check_abort(pcicptr);
if (retval == PCIBIOS_DEVICE_NOT_FOUND)
*val = 0xffffffff;
@@ -136,7 +149,10 @@ static int tx4938_pcibios_read_config(struct pci_bus *bus, unsigned int devfn,
static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
- int flags, dev, busno, func;
+ int dev, busno, func;
+ struct tx4938_pcic_reg *pcicptr = pci_bus_to_pcicptr(bus);
+ void __iomem *cfgdata =
+ (void __iomem *)(unsigned long)&pcicptr->g2pcfgdata;
busno = bus->number;
dev = PCI_SLOT(devfn);
@@ -149,32 +165,32 @@ static int tx4938_pcibios_write_config(struct pci_bus *bus, unsigned int devfn,
busno = 0;
}
- if (mkaddr(busno, devfn, where, &flags))
+ if (mkaddr(busno, devfn, where, pcicptr))
return -1;
switch (size) {
case 1:
- *(volatile u8 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
#ifdef __BIG_ENDIAN
- ((where & 3) ^ 3)) = val;
+ cfgdata += (where & 3) ^ 3;
#else
- (where & 3)) = val;
+ cfgdata += where & 3;
#endif
+ __raw_writeb(val, cfgdata);
break;
case 2:
- *(volatile u16 *) ((unsigned long) & tx4938_pcicptr->g2pcfgdata |
#ifdef __BIG_ENDIAN
- ((where & 0x3) ^ 0x2)) = val;
+ cfgdata += (where & 2) ^ 2;
#else
- (where & 3)) = val;
+ cfgdata += where & 2;
#endif
+ __raw_writew(val, cfgdata);
break;
case 4:
- tx4938_pcicptr->g2pcfgdata = val;
+ __raw_writel(val, cfgdata);
break;
}
- return check_abort(flags);
+ return check_abort(pcicptr);
}
struct pci_ops tx4938_pci_ops = {
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c
index d7b9e1349f6..2b4e30c7d10 100644
--- a/arch/mips/pci/pci-bcm1480.c
+++ b/arch/mips/pci/pci-bcm1480.c
@@ -74,8 +74,9 @@ static inline void WRITECFG32(u32 addr, u32 data)
*(u32 *)(cfg_space + (addr & ~3)) = data;
}
-int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
+ This is b0rked.
return dev->irq;
}
diff --git a/arch/mips/pci/pci-dac.c b/arch/mips/pci/pci-dac.c
deleted file mode 100644
index 0f0ea1b7d4d..00000000000
--- a/arch/mips/pci/pci-dac.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Ani Joshi <ajoshi@unixbox.com>
- * Copyright (C) 2000, 2001, 06 Ralf Baechle <ralf@linux-mips.org>
- * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
- */
-
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-#include <dma-coherence.h>
-
-#include <linux/pci.h>
-
-dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
- struct page *page, unsigned long offset, int direction)
-{
- struct device *dev = &pdev->dev;
-
- BUG_ON(direction == DMA_NONE);
-
- if (!plat_device_is_coherent(dev)) {
- unsigned long addr;
-
- addr = (unsigned long) page_address(page) + offset;
- dma_cache_wback_inv(addr, PAGE_SIZE);
- }
-
- return plat_map_dma_mem_page(dev, page) + offset;
-}
-
-EXPORT_SYMBOL(pci_dac_page_to_dma);
-
-struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
- dma64_addr_t dma_addr)
-{
- return pfn_to_page(plat_dma_addr_to_phys(dma_addr) >> PAGE_SHIFT);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_page);
-
-unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
- dma64_addr_t dma_addr)
-{
- return dma_addr & ~PAGE_MASK;
-}
-
-EXPORT_SYMBOL(pci_dac_dma_to_offset);
-
-void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-
- if (!plat_device_is_coherent(&pdev->dev))
- dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_cpu);
-
-void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-
- if (!plat_device_is_coherent(&pdev->dev))
- dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len);
-}
-
-EXPORT_SYMBOL(pci_dac_dma_sync_single_for_device);
diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c
index d071bc375b1..7363e187784 100644
--- a/arch/mips/pci/pci-ddb5477.c
+++ b/arch/mips/pci/pci-ddb5477.c
@@ -131,7 +131,7 @@ static unsigned char rockhopperII_irq_map[MAX_SLOT_NUM] = {
/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */
};
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int slot_num;
unsigned char *slot_irq_map;
diff --git a/arch/mips/pci/pci-ev64120.c b/arch/mips/pci/pci-ev64120.c
deleted file mode 100644
index a84f594b5a1..00000000000
--- a/arch/mips/pci/pci-ev64120.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <linux/pci.h>
-#include <asm/irq.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- int irq;
-
- if (!pin)
- return 0;
-
- irq = allocate_irqno();
- if (irq < 0)
- return 0;
-
- return irq;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 405ce015273..a322543ac34 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -134,7 +134,7 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid)
* A given PCI device, in general, should be able to intr any of the cpus
* on any one of the hubs connected to its xbow.
*/
-int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus);
int irq = bc->pci_int[slot];
diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c
deleted file mode 100644
index 985784a3e6f..00000000000
--- a/arch/mips/pci/pci-lasat.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000, 2001, 04 Keith M Wesolowski
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-
-extern struct pci_ops nile4_pci_ops;
-extern struct pci_ops gt64xxx_pci0_ops;
-static struct resource lasat_pci_mem_resource = {
- .name = "LASAT PCI MEM",
- .start = 0x18000000,
- .end = 0x19ffffff,
- .flags = IORESOURCE_MEM,
-};
-
-static struct resource lasat_pci_io_resource = {
- .name = "LASAT PCI IO",
- .start = 0x1a000000,
- .end = 0x1bffffff,
- .flags = IORESOURCE_IO,
-};
-
-static struct pci_controller lasat_pci_controller = {
- .mem_resource = &lasat_pci_mem_resource,
- .io_resource = &lasat_pci_io_resource,
-};
-
-static int __init lasat_pci_setup(void)
-{
- printk("PCI: starting\n");
-
- switch (mips_machtype) {
- case MACH_LASAT_100:
- lasat_pci_controller.pci_ops = &gt64xxx_pci0_ops;
- break;
- case MACH_LASAT_200:
- lasat_pci_controller.pci_ops = &nile4_pci_ops;
- break;
- default:
- panic("pcibios_init: mips_machtype incorrect");
- }
-
- register_pci_controller(&lasat_pci_controller);
-
- return 0;
-}
-
-arch_initcall(lasat_pci_setup);
-
-#define LASATINT_ETH1 0
-#define LASATINT_ETH0 1
-#define LASATINT_HDC 2
-#define LASATINT_COMP 3
-#define LASATINT_HDLC 4
-#define LASATINT_PCIA 5
-#define LASATINT_PCIB 6
-#define LASATINT_PCIC 7
-#define LASATINT_PCID 8
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
- switch (slot) {
- case 1:
- case 2:
- case 3:
- return LASATINT_PCIA + (((slot-1) + (pin-1)) % 4);
- case 4:
- return LASATINT_ETH1; /* Ethernet 1 (LAN 2) */
- case 5:
- return LASATINT_ETH0; /* Ethernet 0 (LAN 1) */
- case 6:
- return LASATINT_HDC; /* IDE controller */
- default:
- return 0xff; /* Illegal */
- }
-
- return -1;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
- return 0;
-}
diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c
deleted file mode 100644
index 027759f7c90..00000000000
--- a/arch/mips/pci/pci-ocelot-c.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004, 06 by Ralf Baechle (ralf@linux-mips.org)
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/mv643xx.h>
-
-#include <linux/init.h>
-
-#include <asm/marvell.h>
-
-/*
- * We assume the address ranges have already been setup appropriately by
- * the firmware. PMON in case of the Ocelot C does that.
- */
-static struct resource mv_pci_io_mem0_resource = {
- .name = "MV64340 PCI0 IO MEM",
- .flags = IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem0_resource = {
- .name = "MV64340 PCI0 MEM",
- .flags = IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem0_resource,
- .io_resource = &mv_pci_io_mem0_resource,
- },
- .config_addr = MV64340_PCI_0_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static uint32_t mv_io_base, mv_io_size;
-
-static void mv64340_pci0_init(void)
-{
- uint32_t mem0_base, mem0_size;
- uint32_t io_base, io_size;
-
- io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
- io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
- mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
- mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
-
- mv_pci_io_mem0_resource.start = 0;
- mv_pci_io_mem0_resource.end = io_size - 1;
- mv_pci_mem0_resource.start = mem0_base;
- mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
- mv_bus0_controller.pcic.mem_offset = mem0_base;
- mv_bus0_controller.pcic.io_offset = 0;
-
- ioport_resource.end = io_size - 1;
-
- register_pci_controller(&mv_bus0_controller.pcic);
-
- mv_io_base = io_base;
- mv_io_size = io_size;
-}
-
-static struct resource mv_pci_io_mem1_resource = {
- .name = "MV64340 PCI1 IO MEM",
- .flags = IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem1_resource = {
- .name = "MV64340 PCI1 MEM",
- .flags = IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
- .pcic = {
- .pci_ops = &mv_pci_ops,
- .mem_resource = &mv_pci_mem1_resource,
- .io_resource = &mv_pci_io_mem1_resource,
- },
- .config_addr = MV64340_PCI_1_CONFIG_ADDR,
- .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init void mv64340_pci1_init(void)
-{
- uint32_t mem0_base, mem0_size;
- uint32_t io_base, io_size;
-
- io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
- io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
- mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
- mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
-
- /*
- * Here we assume the I/O window of second bus to be contiguous with
- * the first. A gap is no problem but would waste address space for
- * remapping the port space.
- */
- mv_pci_io_mem1_resource.start = mv_io_size;
- mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
- mv_pci_mem1_resource.start = mem0_base;
- mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
- mv_bus1_controller.pcic.mem_offset = mem0_base;
- mv_bus1_controller.pcic.io_offset = 0;
-
- ioport_resource.end = io_base + io_size -mv_io_base - 1;
-
- register_pci_controller(&mv_bus1_controller.pcic);
-
- mv_io_size = io_base + io_size - mv_io_base;
-}
-
-static __init int __init ocelot_c_pci_init(void)
-{
- unsigned long io_v_base;
- uint32_t enable;
-
- enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
-
- /*
- * We require at least one enabled I/O or PCI memory window or we
- * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
- */
- if (enable & (0x01 << 9) || enable & (0x01 << 10))
- mv64340_pci0_init();
-
- if (enable & (0x01 << 14) || enable & (0x01 << 15))
- mv64340_pci1_init();
-
- if (mv_io_size) {
- io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
- if (!io_v_base)
- panic("Could not ioremap I/O port range");
-
- set_io_port_base(io_v_base);
- }
-
- return 0;
-}
-
-arch_initcall(ocelot_c_pci_init);
diff --git a/arch/mips/pci/pci-ocelot.c b/arch/mips/pci/pci-ocelot.c
index 7f94f26d35a..1421d34535e 100644
--- a/arch/mips/pci/pci-ocelot.c
+++ b/arch/mips/pci/pci-ocelot.c
@@ -71,19 +71,19 @@ static inline void pci0WriteConfigReg(unsigned int offset, unsigned int data)
}
static struct resource ocelot_mem_resource = {
- start = GT_PCI_MEM_BASE;
- end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
+ .start = GT_PCI_MEM_BASE,
+ .end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1,
};
static struct resource ocelot_io_resource = {
- start = GT_PCI_IO_BASE;
- end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+ .start = GT_PCI_IO_BASE,
+ .end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1,
};
static struct pci_controller ocelot_pci_controller = {
- .pci_ops = gt64xxx_pci0_ops;
- .mem_resource = &ocelot_mem_resource;
- .io_resource = &ocelot_io_resource;
+ .pci_ops = gt64xxx_pci0_ops,
+ .mem_resource = &ocelot_mem_resource,
+ .io_resource = &ocelot_io_resource,
};
static int __init ocelot_pcibios_init(void)
diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c
index 75c1246ced5..c1ac6493155 100644
--- a/arch/mips/pci/pci-sb1250.c
+++ b/arch/mips/pci/pci-sb1250.c
@@ -84,7 +84,7 @@ static inline void WRITECFG32(u32 addr, u32 data)
*(u32 *) (cfg_space + (addr & ~3)) = data;
}
-int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return dev->irq;
}
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 8108231f2e2..99d8f4fd3ff 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -269,7 +269,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
}
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
- struct pci_dev *dev = pci_dev_b(ln);
+ dev = pci_dev_b(ln);
if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
pcibios_fixup_device_resources(dev, bus);
diff --git a/arch/mips/philips/pnx8550/common/platform.c b/arch/mips/philips/pnx8550/common/platform.c
index d43f56e2cd7..c839436bd01 100644
--- a/arch/mips/philips/pnx8550/common/platform.c
+++ b/arch/mips/philips/pnx8550/common/platform.c
@@ -123,7 +123,7 @@ static struct platform_device *pnx8550_platform_devices[] __initdata = {
&pnx8550_uart_device,
};
-int pnx8550_platform_init(void)
+static int __init pnx8550_platform_init(void)
{
return platform_add_devices(pnx8550_platform_devices,
ARRAY_SIZE(pnx8550_platform_devices));
diff --git a/arch/mips/philips/pnx8550/common/proc.c b/arch/mips/philips/pnx8550/common/proc.c
index 3f097558ef1..92311e95b70 100644
--- a/arch/mips/philips/pnx8550/common/proc.c
+++ b/arch/mips/philips/pnx8550/common/proc.c
@@ -78,29 +78,33 @@ static int pnx8550_proc_init( void )
{
// Create /proc/pnx8550
- pnx8550_dir = create_proc_entry("pnx8550", S_IFDIR|S_IRUGO, NULL);
+ pnx8550_dir = proc_mkdir("pnx8550", NULL);
if (!pnx8550_dir) {
printk(KERN_ERR "Can't create pnx8550 proc dir\n");
return -1;
}
// Create /proc/pnx8550/timers
- pnx8550_timers = create_proc_entry("timers", S_IFREG|S_IRUGO, pnx8550_dir );
- if (pnx8550_timers){
- pnx8550_timers->read_proc = pnx8550_timers_read;
- }
- else {
+ pnx8550_timers = create_proc_read_entry(
+ "timers",
+ 0,
+ pnx8550_dir,
+ pnx8550_timers_read,
+ NULL);
+
+ if (!pnx8550_timers)
printk(KERN_ERR "Can't create pnx8550 timers proc file\n");
- }
// Create /proc/pnx8550/registers
- pnx8550_registers = create_proc_entry("registers", S_IFREG|S_IRUGO, pnx8550_dir );
- if (pnx8550_registers){
- pnx8550_registers->read_proc = pnx8550_registers_read;
- }
- else {
+ pnx8550_registers = create_proc_read_entry(
+ "registers",
+ 0,
+ pnx8550_dir,
+ pnx8550_registers_read,
+ NULL);
+
+ if (!pnx8550_registers)
printk(KERN_ERR "Can't create pnx8550 registers proc file\n");
- }
return 0;
}
diff --git a/arch/mips/pmc-sierra/Kconfig b/arch/mips/pmc-sierra/Kconfig
index 24d514c9dff..abbd0bbfabd 100644
--- a/arch/mips/pmc-sierra/Kconfig
+++ b/arch/mips/pmc-sierra/Kconfig
@@ -1,3 +1,49 @@
+choice
+ prompt "PMC-Sierra MSP SOC type"
+ depends on PMC_MSP
+
+config PMC_MSP4200_EVAL
+ bool "PMC-Sierra MSP4200 Eval Board"
+ select IRQ_MSP_SLP
+ select HW_HAS_PCI
+
+config PMC_MSP4200_GW
+ bool "PMC-Sierra MSP4200 VoIP Gateway"
+ select IRQ_MSP_SLP
+ select HW_HAS_PCI
+
+config PMC_MSP7120_EVAL
+ bool "PMC-Sierra MSP7120 Eval Board"
+ select SYS_SUPPORTS_MULTITHREADING
+ select IRQ_MSP_CIC
+ select HW_HAS_PCI
+
+config PMC_MSP7120_GW
+ bool "PMC-Sierra MSP7120 Residential Gateway"
+ select SYS_SUPPORTS_MULTITHREADING
+ select IRQ_MSP_CIC
+ select HW_HAS_PCI
+
+config PMC_MSP7120_FPGA
+ bool "PMC-Sierra MSP7120 FPGA"
+ select SYS_SUPPORTS_MULTITHREADING
+ select IRQ_MSP_CIC
+ select HW_HAS_PCI
+
+endchoice
+
+menu "Options for PMC-Sierra MSP chipsets"
+ depends on PMC_MSP
+
+config PMC_MSP_EMBEDDED_ROOTFS
+ bool "Root filesystem embedded in kernel image"
+ select MTD
+ select MTD_BLOCK
+ select MTD_PMC_MSP_RAMROOT
+ select MTD_RAM
+
+endmenu
+
config HYPERTRANSPORT
bool "Hypertransport Support for PMC-Sierra Yosemite"
depends on PMC_YOSEMITE
diff --git a/arch/mips/pmc-sierra/msp71xx/Makefile b/arch/mips/pmc-sierra/msp71xx/Makefile
new file mode 100644
index 00000000000..4bba79c1cc7
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the PMC-Sierra MSP SOCs
+#
+obj-y += msp_prom.o msp_setup.o msp_irq.o \
+ msp_time.o msp_serial.o msp_elb.o
+obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o
+obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o
+obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o
+obj-$(CONFIG_PCI) += msp_pci.o
+obj-$(CONFIG_MSPETH) += msp_eth.o
+obj-$(CONFIG_USB_MSP71XX) += msp_usb.o
diff --git a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/pmc-sierra/msp71xx/msp_elb.c
index f0f5581dcb5..3e964100721 100644
--- a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h
+++ b/arch/mips/pmc-sierra/msp71xx/msp_elb.c
@@ -1,7 +1,9 @@
/*
- * Ocelot-C Board Register Definitions
+ * Sets up the proper Chip Select configuration registers. It is assumed that
+ * PMON sets up the ADDR and MASK registers properly.
*
- * (C) 2002 Momentum Computer Inc.
+ * Copyright 2005-2006 PMC-Sierra, Inc.
+ * Author: Marc St-Jean, Marc_St-Jean@pmc-sierra.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
@@ -22,40 +24,23 @@
* You 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.
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
*/
-#ifndef __OCELOT_C_FPGA_H__
-#define __OCELOT_C_FPGA_H__
-
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <msp_regs.h>
-#ifdef CONFIG_64BIT
-#define OCELOT_C_CS0_ADDR (0xfffffffffc000000)
-#else
-#define OCELOT_C_CS0_ADDR (0xfc000000)
+static int __init msp_elb_setup(void)
+{
+#if defined(CONFIG_PMC_MSP7120_GW) \
+ || defined(CONFIG_PMC_MSP7120_EVAL)
+ /*
+ * Force all CNFG to be identical and equal to CS0,
+ * according to OPS doc
+ */
+ *CS1_CNFG_REG = *CS2_CNFG_REG = *CS3_CNFG_REG = *CS0_CNFG_REG;
#endif
+ return 0;
+}
-#define OCELOT_C_REG_BOARDREV 0x0
-#define OCELOT_C_REG_FPGA_REV 0x1
-#define OCELOT_C_REG_FPGA_TYPE 0x2
-#define OCELOT_C_REG_RESET_STATUS 0x3
-#define OCELOT_C_REG_BOARD_STATUS 0x4
-#define OCELOT_C_REG_CPCI_ID 0x5
-#define OCELOT_C_REG_SET 0x6
-#define OCELOT_C_REG_CLR 0x7
-#define OCELOT_C_REG_EEPROM_MODE 0x9
-#define OCELOT_C_REG_INTMASK 0xa
-#define OCELOT_C_REG_INTSTAT 0xb
-#define OCELOT_C_REG_UART_INTMASK 0xc
-#define OCELOT_C_REG_UART_INTSTAT 0xd
-#define OCELOT_C_REG_INTSET 0xe
-#define OCELOT_C_REG_INTCLR 0xf
-
-#define __FPGA_REG_TO_ADDR(reg) \
- ((void *) OCELOT_C_CS0_ADDR + OCELOT_C_REG_##reg)
-#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
-
-#endif
+subsys_initcall(msp_elb_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c
new file mode 100644
index 00000000000..6fa85728158
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_hwbutton.c
@@ -0,0 +1,179 @@
+/*
+ * Sets up interrupt handlers for various hardware switches which are
+ * connected to interrupt lines.
+ *
+ * Copyright 2005-2207 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <msp_int.h>
+#include <msp_regs.h>
+#include <msp_regops.h>
+#ifdef CONFIG_PMCTWILED
+#include <msp_led_macros.h>
+#endif
+
+/* For hwbutton_interrupt->initial_state */
+#define HWBUTTON_HI 0x1
+#define HWBUTTON_LO 0x2
+
+/*
+ * This struct describes a hardware button
+ */
+struct hwbutton_interrupt {
+ char *name; /* Name of button */
+ int irq; /* Actual LINUX IRQ */
+ int eirq; /* Extended IRQ number (0-7) */
+ int initial_state; /* The "normal" state of the switch */
+ void (*handle_hi)(void *); /* Handler: switch input has gone HI */
+ void (*handle_lo)(void *); /* Handler: switch input has gone LO */
+ void *data; /* Optional data to pass to handler */
+};
+
+#ifdef CONFIG_PMC_MSP7120_GW
+extern void msp_restart(char *);
+
+static void softreset_push(void *data)
+{
+ printk(KERN_WARNING "SOFTRESET switch was pushed\n");
+
+ /*
+ * In the future you could move this to the release handler,
+ * timing the difference between the 'push' and 'release', and only
+ * doing this ungraceful restart if the button has been down for
+ * a certain amount of time; otherwise doing a graceful restart.
+ */
+
+ msp_restart(NULL);
+}
+
+static void softreset_release(void *data)
+{
+ printk(KERN_WARNING "SOFTRESET switch was released\n");
+
+ /* Do nothing */
+}
+
+static void standby_on(void *data)
+{
+ printk(KERN_WARNING "STANDBY switch was set to ON (not implemented)\n");
+
+ /* TODO: Put board in standby mode */
+#ifdef CONFIG_PMCTWILED
+ msp_led_turn_off(MSP_LED_PWRSTANDBY_GREEN);
+ msp_led_turn_on(MSP_LED_PWRSTANDBY_RED);
+#endif
+}
+
+static void standby_off(void *data)
+{
+ printk(KERN_WARNING
+ "STANDBY switch was set to OFF (not implemented)\n");
+
+ /* TODO: Take out of standby mode */
+#ifdef CONFIG_PMCTWILED
+ msp_led_turn_on(MSP_LED_PWRSTANDBY_GREEN);
+ msp_led_turn_off(MSP_LED_PWRSTANDBY_RED);
+#endif
+}
+
+static struct hwbutton_interrupt softreset_sw = {
+ .name = "Softreset button",
+ .irq = MSP_INT_EXT0,
+ .eirq = 0,
+ .initial_state = HWBUTTON_HI,
+ .handle_hi = softreset_release,
+ .handle_lo = softreset_push,
+ .data = NULL,
+};
+
+static struct hwbutton_interrupt standby_sw = {
+ .name = "Standby switch",
+ .irq = MSP_INT_EXT1,
+ .eirq = 1,
+ .initial_state = HWBUTTON_HI,
+ .handle_hi = standby_off,
+ .handle_lo = standby_on,
+ .data = NULL,
+};
+#endif /* CONFIG_PMC_MSP7120_GW */
+
+static irqreturn_t hwbutton_handler(int irq, void *data)
+{
+ struct hwbutton_interrupt *hirq = data;
+ unsigned long cic_ext = *CIC_EXT_CFG_REG;
+
+ if (irq != hirq->irq)
+ return IRQ_NONE;
+
+ if (CIC_EXT_IS_ACTIVE_HI(cic_ext, hirq->eirq)) {
+ /* Interrupt: pin is now HI */
+ CIC_EXT_SET_ACTIVE_LO(cic_ext, hirq->eirq);
+ hirq->handle_hi(hirq->data);
+ } else {
+ /* Interrupt: pin is now LO */
+ CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq);
+ hirq->handle_lo(hirq->data);
+ }
+
+ /*
+ * Invert the POLARITY of this level interrupt to ack the interrupt
+ * Thus next state change will invoke the opposite message
+ */
+ *CIC_EXT_CFG_REG = cic_ext;
+
+ return IRQ_HANDLED;
+}
+
+static int msp_hwbutton_register(struct hwbutton_interrupt *hirq)
+{
+ unsigned long cic_ext;
+
+ if (hirq->handle_hi == NULL || hirq->handle_lo == NULL)
+ return -EINVAL;
+
+ cic_ext = *CIC_EXT_CFG_REG;
+ CIC_EXT_SET_TRIGGER_LEVEL(cic_ext, hirq->eirq);
+ if (hirq->initial_state == HWBUTTON_HI)
+ CIC_EXT_SET_ACTIVE_LO(cic_ext, hirq->eirq);
+ else
+ CIC_EXT_SET_ACTIVE_HI(cic_ext, hirq->eirq);
+ *CIC_EXT_CFG_REG = cic_ext;
+
+ return request_irq(hirq->irq, hwbutton_handler, SA_INTERRUPT,
+ hirq->name, (void *)hirq);
+}
+
+static int __init msp_hwbutton_setup(void)
+{
+#ifdef CONFIG_PMC_MSP7120_GW
+ msp_hwbutton_register(&softreset_sw);
+ msp_hwbutton_register(&standby_sw);
+#endif
+ return 0;
+}
+
+subsys_initcall(msp_hwbutton_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq.c b/arch/mips/pmc-sierra/msp71xx/msp_irq.c
new file mode 100644
index 00000000000..734d598a2e3
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq.c
@@ -0,0 +1,124 @@
+/*
+ * IRQ vector handles
+ *
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/time.h>
+
+#include <asm/irq_cpu.h>
+
+#include <msp_int.h>
+
+extern void msp_int_handle(void);
+
+/* SLP bases systems */
+extern void msp_slp_irq_init(void);
+extern void msp_slp_irq_dispatch(void);
+
+/* CIC based systems */
+extern void msp_cic_irq_init(void);
+extern void msp_cic_irq_dispatch(void);
+
+/*
+ * The PMC-Sierra MSP interrupts are arranged in a 3 level cascaded
+ * hierarchical system. The first level are the direct MIPS interrupts
+ * and are assigned the interrupt range 0-7. The second level is the SLM
+ * interrupt controller and is assigned the range 8-39. The third level
+ * comprises the Peripherial block, the PCI block, the PCI MSI block and
+ * the SLP. The PCI interrupts and the SLP errors are handled by the
+ * relevant subsystems so the core interrupt code needs only concern
+ * itself with the Peripheral block. These are assigned interrupts in
+ * the range 40-71.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+ u32 pending;
+
+ pending = read_c0_status() & read_c0_cause();
+
+ /*
+ * jump to the correct interrupt routine
+ * These are arranged in priority order and the timer
+ * comes first!
+ */
+
+#ifdef CONFIG_IRQ_MSP_CIC /* break out the CIC stuff for now */
+ if (pending & C_IRQ4) /* do the peripherals first, that's the timer */
+ msp_cic_irq_dispatch();
+
+ else if (pending & C_IRQ0)
+ do_IRQ(MSP_INT_MAC0);
+
+ else if (pending & C_IRQ1)
+ do_IRQ(MSP_INT_MAC1);
+
+ else if (pending & C_IRQ2)
+ do_IRQ(MSP_INT_USB);
+
+ else if (pending & C_IRQ3)
+ do_IRQ(MSP_INT_SAR);
+
+ else if (pending & C_IRQ5)
+ do_IRQ(MSP_INT_SEC);
+
+#else
+ if (pending & C_IRQ5)
+ do_IRQ(MSP_INT_TIMER);
+
+ else if (pending & C_IRQ0)
+ do_IRQ(MSP_INT_MAC0);
+
+ else if (pending & C_IRQ1)
+ do_IRQ(MSP_INT_MAC1);
+
+ else if (pending & C_IRQ3)
+ do_IRQ(MSP_INT_VE);
+
+ else if (pending & C_IRQ4)
+ msp_slp_irq_dispatch();
+#endif
+
+ else if (pending & C_SW0) /* do software after hardware */
+ do_IRQ(MSP_INT_SW0);
+
+ else if (pending & C_SW1)
+ do_IRQ(MSP_INT_SW1);
+}
+
+static struct irqaction cascade_msp = {
+ .handler = no_action,
+ .name = "MSP cascade"
+};
+
+
+void __init arch_init_irq(void)
+{
+ /* initialize the 1st-level CPU based interrupt controller */
+ mips_cpu_irq_init();
+
+#ifdef CONFIG_IRQ_MSP_CIC
+ msp_cic_irq_init();
+
+ /* setup the cascaded interrupts */
+ setup_irq(MSP_INT_CIC, &cascade_msp);
+ setup_irq(MSP_INT_PER, &cascade_msp);
+#else
+ /* setup the 2nd-level SLP register based interrupt controller */
+ msp_slp_irq_init();
+
+ /* setup the cascaded SLP/PER interrupts */
+ setup_irq(MSP_INT_SLP, &cascade_msp);
+ setup_irq(MSP_INT_PER, &cascade_msp);
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
new file mode 100644
index 00000000000..5175357d0a2
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
@@ -0,0 +1,134 @@
+/*
+ * This file define the irq handler for MSP SLM subsystem interrupts.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc, derived from irq_cpu.c
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.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/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+
+#include <msp_cic_int.h>
+#include <msp_regs.h>
+
+/*
+ * NOTE: We are only enabling support for VPE0 right now.
+ */
+
+static inline void unmask_msp_cic_irq(unsigned int irq)
+{
+
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *CIC_VPE0_MSK_REG |= (1 << (irq - MSP_CIC_INTBASE));
+ else
+ *PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+}
+
+static inline void mask_msp_cic_irq(unsigned int irq)
+{
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *CIC_VPE0_MSK_REG &= ~(1 << (irq - MSP_CIC_INTBASE));
+ else
+ *PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues. Same for msp_cic_irq_end.
+ */
+static inline void ack_msp_cic_irq(unsigned int irq)
+{
+ mask_msp_cic_irq(irq);
+
+ /*
+ * only really necessary for 18, 16-14 and sometimes 3:0 (since
+ * these can be edge sensitive) but it doesn't hurt for the others.
+ */
+
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *CIC_STS_REG = (1 << (irq - MSP_CIC_INTBASE));
+ else
+ *PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
+}
+
+static struct irq_chip msp_cic_irq_controller = {
+ .name = "MSP_CIC",
+ .ack = ack_msp_cic_irq,
+ .mask = ack_msp_cic_irq,
+ .mask_ack = ack_msp_cic_irq,
+ .unmask = unmask_msp_cic_irq,
+};
+
+
+void __init msp_cic_irq_init(void)
+{
+ int i;
+
+ /* Mask/clear interrupts. */
+ *CIC_VPE0_MSK_REG = 0x00000000;
+ *PER_INT_MSK_REG = 0x00000000;
+ *CIC_STS_REG = 0xFFFFFFFF;
+ *PER_INT_STS_REG = 0xFFFFFFFF;
+
+#if defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_EVAL)
+ /*
+ * The MSP7120 RG and EVBD boards use IRQ[6:4] for PCI.
+ * These inputs map to EXT_INT_POL[6:4] inside the CIC.
+ * They are to be active low, level sensitive.
+ */
+ *CIC_EXT_CFG_REG &= 0xFFFF8F8F;
+#endif
+
+ /* initialize all the IRQ descriptors */
+ for (i = MSP_CIC_INTBASE; i < MSP_PER_INTBASE + 32; i++)
+ set_irq_chip_and_handler(i, &msp_cic_irq_controller,
+ handle_level_irq);
+}
+
+void msp_cic_irq_dispatch(void)
+{
+ u32 pending;
+ int intbase;
+
+ intbase = MSP_CIC_INTBASE;
+ pending = *CIC_STS_REG & *CIC_VPE0_MSK_REG;
+
+ /* check for PER interrupt */
+ if (pending == (1 << (MSP_INT_PER - MSP_CIC_INTBASE))) {
+ intbase = MSP_PER_INTBASE;
+ pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
+ }
+
+ /* check for spurious interrupt */
+ if (pending == 0x00000000) {
+ printk(KERN_ERR
+ "Spurious %s interrupt? status %08x, mask %08x\n",
+ (intbase == MSP_CIC_INTBASE) ? "CIC" : "PER",
+ (intbase == MSP_CIC_INTBASE) ?
+ *CIC_STS_REG : *PER_INT_STS_REG,
+ (intbase == MSP_CIC_INTBASE) ?
+ *CIC_VPE0_MSK_REG : *PER_INT_MSK_REG);
+ return;
+ }
+
+ /* check for the timer and dispatch it first */
+ if ((intbase == MSP_CIC_INTBASE) &&
+ (pending & (1 << (MSP_INT_VPE0_TIMER - MSP_CIC_INTBASE))))
+ do_IRQ(MSP_INT_VPE0_TIMER);
+ else
+ do_IRQ(ffs(pending) + intbase - 1);
+}
+
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c b/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
new file mode 100644
index 00000000000..f5f1b8d2bb9
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
@@ -0,0 +1,109 @@
+/*
+ * This file define the irq handler for MSP SLM subsystem interrupts.
+ *
+ * Copyright 2005-2006 PMC-Sierra, Inc, derived from irq_cpu.c
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.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/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <msp_slp_int.h>
+#include <msp_regs.h>
+
+static inline void unmask_msp_slp_irq(unsigned int irq)
+{
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *SLP_INT_MSK_REG |= (1 << (irq - MSP_SLP_INTBASE));
+ else
+ *PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+}
+
+static inline void mask_msp_slp_irq(unsigned int irq)
+{
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *SLP_INT_MSK_REG &= ~(1 << (irq - MSP_SLP_INTBASE));
+ else
+ *PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+}
+
+/*
+ * While we ack the interrupt interrupts are disabled and thus we don't need
+ * to deal with concurrency issues. Same for msp_slp_irq_end.
+ */
+static inline void ack_msp_slp_irq(unsigned int irq)
+{
+ mask_slp_irq(irq);
+
+ /*
+ * only really necessary for 18, 16-14 and sometimes 3:0 (since
+ * these can be edge sensitive) but it doesn't hurt for the others.
+ */
+
+ /* check for PER interrupt range */
+ if (irq < MSP_PER_INTBASE)
+ *SLP_INT_STS_REG = (1 << (irq - MSP_SLP_INTBASE));
+ else
+ *PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
+}
+
+static struct irq_chip msp_slp_irq_controller = {
+ .name = "MSP_SLP",
+ .ack = ack_msp_slp_irq,
+ .mask = ack_msp_slp_irq,
+ .mask_ack = ack_msp_slp_irq,
+ .unmask = unmask_msp_slp_irq,
+};
+
+void __init msp_slp_irq_init(void)
+{
+ int i;
+
+ /* Mask/clear interrupts. */
+ *SLP_INT_MSK_REG = 0x00000000;
+ *PER_INT_MSK_REG = 0x00000000;
+ *SLP_INT_STS_REG = 0xFFFFFFFF;
+ *PER_INT_STS_REG = 0xFFFFFFFF;
+
+ /* initialize all the IRQ descriptors */
+ for (i = MSP_SLP_INTBASE; i < MSP_PER_INTBASE + 32; i++)
+ set_irq_chip_and_handler(i, &msp_slp_irq_controller
+ handle_level_irq);
+}
+
+void msp_slp_irq_dispatch(void)
+{
+ u32 pending;
+ int intbase;
+
+ intbase = MSP_SLP_INTBASE;
+ pending = *SLP_INT_STS_REG & *SLP_INT_MSK_REG;
+
+ /* check for PER interrupt */
+ if (pending == (1 << (MSP_INT_PER - MSP_SLP_INTBASE))) {
+ intbase = MSP_PER_INTBASE;
+ pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
+ }
+
+ /* check for spurious interrupt */
+ if (pending == 0x00000000) {
+ printk(KERN_ERR "Spurious %s interrupt?\n",
+ (intbase == MSP_SLP_INTBASE) ? "SLP" : "PER");
+ return;
+ }
+
+ /* dispatch the irq */
+ do_IRQ(ffs(pending) + intbase - 1);
+}
diff --git a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h b/arch/mips/pmc-sierra/msp71xx/msp_pci.c
index 5710a9029f1..f764fe7748d 100644
--- a/arch/mips/momentum/ocelot_3/ocelot_3_fpga.h
+++ b/arch/mips/pmc-sierra/msp71xx/msp_pci.c
@@ -1,7 +1,7 @@
/*
- * Ocelot-3 Board Register Definitions
+ * The setup file for PCI related hardware on PMC-Sierra MSP processors.
*
- * (C) 2002 Momentum Computer Inc.
+ * Copyright 2005-2006 PMC-Sierra, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -22,38 +22,29 @@
* You 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.
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com [MIPS64 modifications]
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
*/
-#ifndef __OCELOT_3_FPGA_H__
-#define __OCELOT_3_FPGA_H__
-
-#define OCELOT_3_REG_BOARDREV 0x0
-#define OCELOT_3_REG_FPGA_REV 0x1
-#define OCELOT_3_REG_FPGA_TYPE 0x2
-#define OCELOT_3_REG_RESET_STATUS 0x3
-#define OCELOT_3_REG_BOARD_STATUS 0x4
-#define OCELOT_3_REG_CPCI_ID 0x5
-#define OCELOT_3_REG_SET 0x6
-#define OCELOT_3_REG_CLR 0x7
-#define OCELOT_3_REG_EEPROM_MODE 0x9
-#define OCELOT_3_REG_INTMASK 0xa
-#define OCELOT_3_REG_INTSTAT 0xb
-#define OCELOT_3_REG_UART_INTMASK 0xc
-#define OCELOT_3_REG_UART_INTSTAT 0xd
-#define OCELOT_3_REG_INTSET 0xe
-#define OCELOT_3_REG_INTCLR 0xf
-
-extern unsigned long ocelot_fpga_base;
-
-#define __FPGA_REG_TO_ADDR(reg) \
- ((void *) ocelot_fpga_base + OCELOT_3_REG_##reg)
-#define OCELOT_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define OCELOT_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
+#include <linux/init.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+extern void msp_pci_init(void);
+static int __init msp_pci_setup(void)
+{
+#if 0 /* Linux 2.6 initialization code to be completed */
+ if (getdeviceid() & DEV_ID_SINGLE_PC) {
+ /* If single card mode */
+ slmRegs *sreg = (slmRegs *) SREG_BASE;
+
+ sreg->single_pc_enable = SINGLE_PCCARD;
+ }
#endif
+
+ msp_pci_init();
+
+ return 0;
+}
+
+subsys_initcall(msp_pci_setup);
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_prom.c b/arch/mips/pmc-sierra/msp71xx/msp_prom.c
new file mode 100644
index 00000000000..e5bd5481d8d
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_prom.c
@@ -0,0 +1,566 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * PROM library initialisation code, assuming a version of
+ * pmon is the boot code.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#ifdef CONFIG_CRAMFS
+#include <linux/cramfs_fs.h>
+#endif
+#ifdef CONFIG_SQUASHFS
+#include <linux/squashfs_fs.h>
+#endif
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm-generic/sections.h>
+#include <asm/page.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+/* global PROM environment variables and pointers */
+int prom_argc;
+char **prom_argv, **prom_envp;
+int *prom_vec;
+
+/* debug flag */
+int init_debug = 1;
+
+/* memory blocks */
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+/* default feature sets */
+static char msp_default_features[] =
+#if defined(CONFIG_PMC_MSP4200_EVAL) \
+ || defined(CONFIG_PMC_MSP4200_GW)
+ "ERER";
+#elif defined(CONFIG_PMC_MSP7120_EVAL) \
+ || defined(CONFIG_PMC_MSP7120_GW)
+ "EMEMSP";
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+ "EMEM";
+#endif
+
+/* conversion functions */
+static inline unsigned char str2hexnum(unsigned char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0; /* foo */
+}
+
+static inline int str2eaddr(unsigned char *ea, unsigned char *str)
+{
+ int index = 0;
+ unsigned char num = 0;
+
+ while (*str != '\0') {
+ if ((*str == '.') || (*str == ':')) {
+ ea[index++] = num;
+ num = 0;
+ str++;
+ } else {
+ num = num << 4;
+ num |= str2hexnum(*str++);
+ }
+ }
+
+ if (index == 5) {
+ ea[index++] = num;
+ return 0;
+ } else
+ return -1;
+}
+EXPORT_SYMBOL(str2eaddr);
+
+static inline unsigned long str2hex(unsigned char *str)
+{
+ int value = 0;
+
+ while (*str) {
+ value = value << 4;
+ value |= str2hexnum(*str++);
+ }
+
+ return value;
+}
+
+/* function to query the system information */
+const char *get_system_type(void)
+{
+#if defined(CONFIG_PMC_MSP4200_EVAL)
+ return "PMC-Sierra MSP4200 Eval Board";
+#elif defined(CONFIG_PMC_MSP4200_GW)
+ return "PMC-Sierra MSP4200 VoIP Gateway";
+#elif defined(CONFIG_PMC_MSP7120_EVAL)
+ return "PMC-Sierra MSP7120 Eval Board";
+#elif defined(CONFIG_PMC_MSP7120_GW)
+ return "PMC-Sierra MSP7120 Residential Gateway";
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+ return "PMC-Sierra MSP7120 FPGA";
+#else
+ #error "What is the type of *your* MSP?"
+#endif
+}
+
+int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr)
+{
+ char *ethaddr_str;
+
+ ethaddr_str = prom_getenv(ethaddr_name);
+ if (!ethaddr_str) {
+ printk(KERN_WARNING "%s not set in boot prom\n", ethaddr_name);
+ return -1;
+ }
+
+ if (str2eaddr(ethernet_addr, ethaddr_str) == -1) {
+ printk(KERN_WARNING "%s badly formatted-<%s>\n",
+ ethaddr_name, ethaddr_str);
+ return -1;
+ }
+
+ if (init_debug > 1) {
+ int i;
+ printk(KERN_DEBUG "get_ethernet_addr: for %s ", ethaddr_name);
+ for (i = 0; i < 5; i++)
+ printk(KERN_DEBUG "%02x:",
+ (unsigned char)*(ethernet_addr+i));
+ printk(KERN_DEBUG "%02x\n", *(ethernet_addr+i));
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(get_ethernet_addr);
+
+static char *get_features(void)
+{
+ char *feature = prom_getenv(FEATURES);
+
+ if (feature == NULL) {
+ /* default features based on MACHINE_TYPE */
+ feature = msp_default_features;
+ }
+
+ return feature;
+}
+
+static char test_feature(char c)
+{
+ char *feature = get_features();
+
+ while (*feature) {
+ if (*feature++ == c)
+ return *feature;
+ feature++;
+ }
+
+ return FEATURE_NOEXIST;
+}
+
+unsigned long get_deviceid(void)
+{
+ char *deviceid = prom_getenv(DEVICEID);
+
+ if (deviceid == NULL)
+ return *DEV_ID_REG;
+ else
+ return str2hex(deviceid);
+}
+
+char identify_pci(void)
+{
+ return test_feature(PCI_KEY);
+}
+EXPORT_SYMBOL(identify_pci);
+
+char identify_pcimux(void)
+{
+ return test_feature(PCIMUX_KEY);
+}
+
+char identify_sec(void)
+{
+ return test_feature(SEC_KEY);
+}
+EXPORT_SYMBOL(identify_sec);
+
+char identify_spad(void)
+{
+ return test_feature(SPAD_KEY);
+}
+EXPORT_SYMBOL(identify_spad);
+
+char identify_tdm(void)
+{
+ return test_feature(TDM_KEY);
+}
+EXPORT_SYMBOL(identify_tdm);
+
+char identify_zsp(void)
+{
+ return test_feature(ZSP_KEY);
+}
+EXPORT_SYMBOL(identify_zsp);
+
+static char identify_enetfeature(char key, unsigned long interface_num)
+{
+ char *feature = get_features();
+
+ while (*feature) {
+ if (*feature++ == key && interface_num-- == 0)
+ return *feature;
+ feature++;
+ }
+
+ return FEATURE_NOEXIST;
+}
+
+char identify_enet(unsigned long interface_num)
+{
+ return identify_enetfeature(ENET_KEY, interface_num);
+}
+EXPORT_SYMBOL(identify_enet);
+
+char identify_enetTxD(unsigned long interface_num)
+{
+ return identify_enetfeature(ENETTXD_KEY, interface_num);
+}
+EXPORT_SYMBOL(identify_enetTxD);
+
+unsigned long identify_family(void)
+{
+ unsigned long deviceid;
+
+ deviceid = get_deviceid();
+
+ return deviceid & CPU_DEVID_FAMILY;
+}
+EXPORT_SYMBOL(identify_family);
+
+unsigned long identify_revision(void)
+{
+ unsigned long deviceid;
+
+ deviceid = get_deviceid();
+
+ return deviceid & CPU_DEVID_REVISION;
+}
+EXPORT_SYMBOL(identify_revision);
+
+/* PROM environment functions */
+char *prom_getenv(char *env_name)
+{
+ /*
+ * Return a pointer to the given environment variable. prom_envp
+ * points to a null terminated array of pointers to variables.
+ * Environment variables are stored in the form of "memsize=64"
+ */
+
+ char **var = prom_envp;
+ int i = strlen(env_name);
+
+ while (*var) {
+ if (strncmp(env_name, *var, i) == 0) {
+ return (*var + strlen(env_name) + 1);
+ }
+ var++;
+ }
+
+ return NULL;
+}
+
+/* PROM commandline functions */
+char *prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+EXPORT_SYMBOL(prom_getcmdline);
+
+void __init prom_init_cmdline(void)
+{
+ char *cp;
+ int actr;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = &(arcs_cmdline[0]);
+ while (actr < prom_argc) {
+ strcpy(cp, prom_argv[actr]);
+ cp += strlen(prom_argv[actr]);
+ *cp++ = ' ';
+ actr++;
+ }
+ if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+}
+
+/* memory allocation functions */
+static int __init prom_memtype_classify(unsigned int type)
+{
+ switch (type) {
+ case yamon_free:
+ return BOOT_MEM_RAM;
+ case yamon_prom:
+ return BOOT_MEM_ROM_DATA;
+ default:
+ return BOOT_MEM_RESERVED;
+ }
+}
+
+void __init prom_meminit(void)
+{
+ struct prom_pmemblock *p;
+
+ p = prom_getmdesc();
+
+ while (p->size) {
+ long type;
+ unsigned long base, size;
+
+ type = prom_memtype_classify(p->type);
+ base = p->base;
+ size = p->size;
+
+ add_memory_region(base, size, type);
+ p++;
+ }
+}
+
+void __init prom_free_prom_memory(void)
+{
+ int argc;
+ char **argv;
+ char **envp;
+ char *ptr;
+ int len = 0;
+ int i;
+ unsigned long addr;
+
+ /*
+ * preserve environment variables and command line from pmon/bbload
+ * first preserve the command line
+ */
+ for (argc = 0; argc < prom_argc; argc++) {
+ len += sizeof(char *); /* length of pointer */
+ len += strlen(prom_argv[argc]) + 1; /* length of string */
+ }
+ len += sizeof(char *); /* plus length of null pointer */
+
+ argv = kmalloc(len, GFP_KERNEL);
+ ptr = (char *) &argv[prom_argc + 1]; /* strings follow array */
+
+ for (argc = 0; argc < prom_argc; argc++) {
+ argv[argc] = ptr;
+ strcpy(ptr, prom_argv[argc]);
+ ptr += strlen(prom_argv[argc]) + 1;
+ }
+ argv[prom_argc] = NULL; /* end array with null pointer */
+ prom_argv = argv;
+
+ /* next preserve the environment variables */
+ len = 0;
+ i = 0;
+ for (envp = prom_envp; *envp != NULL; envp++) {
+ i++; /* count number of environment variables */
+ len += sizeof(char *); /* length of pointer */
+ len += strlen(*envp) + 1; /* length of string */
+ }
+ len += sizeof(char *); /* plus length of null pointer */
+
+ envp = kmalloc(len, GFP_KERNEL);
+ ptr = (char *) &envp[i+1];
+
+ for (argc = 0; argc < i; argc++) {
+ envp[argc] = ptr;
+ strcpy(ptr, prom_envp[argc]);
+ ptr += strlen(prom_envp[argc]) + 1;
+ }
+ envp[i] = NULL; /* end array with null pointer */
+ prom_envp = envp;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+ continue;
+
+ addr = boot_mem_map.map[i].addr;
+ free_init_pages("prom memory",
+ addr, addr + boot_mem_map.map[i].size);
+ }
+}
+
+struct prom_pmemblock *__init prom_getmdesc(void)
+{
+ static char memsz_env[] __initdata = "memsize";
+ static char heaptop_env[] __initdata = "heaptop";
+ char *str;
+ unsigned int memsize;
+ unsigned int heaptop;
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+ void *ramroot_start;
+ unsigned long ramroot_size;
+#endif
+ int i;
+
+ str = prom_getenv(memsz_env);
+ if (!str) {
+ ppfinit("memsize not set in boot prom, "
+ "set to default (32Mb)\n");
+ memsize = 0x02000000;
+ } else {
+ memsize = simple_strtol(str, NULL, 0);
+
+ if (memsize == 0) {
+ /* if memsize is a bad size, use reasonable default */
+ memsize = 0x02000000;
+ }
+
+ /* convert to physical address (removing caching bits, etc) */
+ memsize = CPHYSADDR(memsize);
+ }
+
+ str = prom_getenv(heaptop_env);
+ if (!str) {
+ heaptop = CPHYSADDR((u32)&_text);
+ ppfinit("heaptop not set in boot prom, "
+ "set to default 0x%08x\n", heaptop);
+ } else {
+ heaptop = simple_strtol(str, NULL, 16);
+ if (heaptop == 0) {
+ /* heaptop conversion bad, might have 0xValue */
+ heaptop = simple_strtol(str, NULL, 0);
+
+ if (heaptop == 0) {
+ /* heaptop still bad, use reasonable default */
+ heaptop = CPHYSADDR((u32)&_text);
+ }
+ }
+
+ /* convert to physical address (removing caching bits, etc) */
+ heaptop = CPHYSADDR((u32)heaptop);
+ }
+
+ /* the base region */
+ i = 0;
+ mdesc[i].type = BOOT_MEM_RESERVED;
+ mdesc[i].base = 0x00000000;
+ mdesc[i].size = PAGE_ALIGN(0x300 + 0x80);
+ /* jtag interrupt vector + sizeof vector */
+
+ /* PMON data */
+ if (heaptop > mdesc[i].base + mdesc[i].size) {
+ i++; /* 1 */
+ mdesc[i].type = BOOT_MEM_ROM_DATA;
+ mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
+ mdesc[i].size = heaptop - mdesc[i].base;
+ }
+
+ /* end of PMON data to start of kernel -- probably zero .. */
+ if (heaptop != CPHYSADDR((u32)_text)) {
+ i++; /* 2 */
+ mdesc[i].type = BOOT_MEM_RAM;
+ mdesc[i].base = heaptop;
+ mdesc[i].size = CPHYSADDR((u32)_text) - mdesc[i].base;
+ }
+
+ /* kernel proper */
+ i++; /* 3 */
+ mdesc[i].type = BOOT_MEM_RESERVED;
+ mdesc[i].base = CPHYSADDR((u32)_text);
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+ if (get_ramroot(&ramroot_start, &ramroot_size)) {
+ /*
+ * Rootfs in RAM -- follows kernel
+ * Combine rootfs image with kernel block so a
+ * page (4k) isn't wasted between memory blocks
+ */
+ mdesc[i].size = CPHYSADDR(PAGE_ALIGN(
+ (u32)ramroot_start + ramroot_size)) - mdesc[i].base;
+ } else
+#endif
+ mdesc[i].size = CPHYSADDR(PAGE_ALIGN(
+ (u32)_end)) - mdesc[i].base;
+
+ /* Remainder of RAM -- under memsize */
+ i++; /* 5 */
+ mdesc[i].type = yamon_free;
+ mdesc[i].base = mdesc[i-1].base + mdesc[i-1].size;
+ mdesc[i].size = memsize - mdesc[i].base;
+
+ return &mdesc[0];
+}
+
+/* rootfs functions */
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+bool get_ramroot(void **start, unsigned long *size)
+{
+ extern char _end[];
+
+ /* Check for start following the end of the kernel */
+ void *check_start = (void *)_end;
+
+ /* Check for supported rootfs types */
+#ifdef CONFIG_CRAMFS
+ if (*(__u32 *)check_start == CRAMFS_MAGIC) {
+ /* Get CRAMFS size */
+ *start = check_start;
+ *size = PAGE_ALIGN(((struct cramfs_super *)
+ check_start)->size);
+
+ return true;
+ }
+#endif
+#ifdef CONFIG_SQUASHFS
+ if (*((unsigned int *)check_start) == SQUASHFS_MAGIC) {
+ /* Get SQUASHFS size */
+ *start = check_start;
+ *size = PAGE_ALIGN(((struct squashfs_super_block *)
+ check_start)->bytes_used);
+
+ return true;
+ }
+#endif
+
+ return false;
+}
+EXPORT_SYMBOL(get_ramroot);
+#endif
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
new file mode 100644
index 00000000000..8f69b789be9
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c
@@ -0,0 +1,256 @@
+/*
+ * The generic setup file for PMC-Sierra MSP processors
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc,
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bootinfo.h>
+#include <asm/cacheflush.h>
+#include <asm/r4kcache.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+
+#include <msp_prom.h>
+#include <msp_regs.h>
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+#include <msp_regops.h>
+#include <msp_gpio.h>
+#define MSP_BOARD_RESET_GPIO 9
+#endif
+
+extern void msp_timer_init(void);
+extern void msp_serial_setup(void);
+extern void pmctwiled_setup(void);
+
+#if defined(CONFIG_PMC_MSP7120_EVAL) || \
+ defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_FPGA)
+/*
+ * Performs the reset for MSP7120-based boards
+ */
+void msp7120_reset(void)
+{
+ void *start, *end, *iptr;
+ register int i;
+
+ /* Diasble all interrupts */
+ local_irq_disable();
+#ifdef CONFIG_SYS_SUPPORTS_MULTITHREADING
+ dvpe();
+#endif
+
+ /* Cache the reset code of this function */
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set mips3 \n"
+ " la %0,startpoint \n"
+ " la %1,endpoint \n"
+ " .set pop \n"
+ : "=r" (start), "=r" (end)
+ :
+ );
+
+ for (iptr = (void *)((unsigned int)start & ~(L1_CACHE_BYTES - 1));
+ iptr < end; iptr += L1_CACHE_BYTES)
+ cache_op(Fill, iptr);
+
+ __asm__ __volatile__ (
+ "startpoint: \n"
+ );
+
+ /* Put the DDRC into self-refresh mode */
+ DDRC_INDIRECT_WRITE(DDRC_CTL(10), 0xb, 1 << 16);
+
+ /*
+ * IMPORTANT!
+ * DO NOT do anything from here on out that might even
+ * think about fetching from RAM - i.e., don't call any
+ * non-inlined functions, and be VERY sure that any inline
+ * functions you do call do NOT access any sort of RAM
+ * anywhere!
+ */
+
+ /* Wait a bit for the DDRC to settle */
+ for (i = 0; i < 100000000; i++);
+
+#if defined(CONFIG_PMC_MSP7120_GW)
+ /*
+ * Set GPIO 9 HI, (tied to board reset logic)
+ * GPIO 9 is the 4th GPIO of register 3
+ *
+ * NOTE: We cannot use the higher-level msp_gpio_mode()/out()
+ * as GPIO char driver may not be enabled and it would look up
+ * data inRAM!
+ */
+ set_value_reg32(GPIO_CFG3_REG,
+ basic_mode_mask(MSP_BOARD_RESET_GPIO),
+ basic_mode(MSP_GPIO_OUTPUT, MSP_BOARD_RESET_GPIO));
+ set_reg32(GPIO_DATA3_REG,
+ basic_data_mask(MSP_BOARD_RESET_GPIO));
+
+ /*
+ * In case GPIO9 doesn't reset the board (jumper configurable!)
+ * fallback to device reset below.
+ */
+#endif
+ /* Set bit 1 of the MSP7120 reset register */
+ *RST_SET_REG = 0x00000001;
+
+ __asm__ __volatile__ (
+ "endpoint: \n"
+ );
+}
+#endif
+
+void msp_restart(char *command)
+{
+ printk(KERN_WARNING "Now rebooting .......\n");
+
+#if defined(CONFIG_PMC_MSP7120_EVAL) || \
+ defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_FPGA)
+ msp7120_reset();
+#else
+ /* No chip-specific reset code, just jump to the ROM reset vector */
+ set_c0_status(ST0_BEV | ST0_ERL);
+ change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+ flush_cache_all();
+ write_c0_wired(0);
+
+ __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+#endif
+}
+
+void msp_halt(void)
+{
+ printk(KERN_WARNING "\n** You can safely turn off the power\n");
+ while (1)
+ /* If possible call official function to get CPU WARs */
+ if (cpu_wait)
+ (*cpu_wait)();
+ else
+ __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0");
+}
+
+void msp_power_off(void)
+{
+ msp_halt();
+}
+
+void __init plat_mem_setup(void)
+{
+ _machine_restart = msp_restart;
+ _machine_halt = msp_halt;
+ pm_power_off = msp_power_off;
+
+ board_time_init = msp_timer_init;
+}
+
+void __init prom_init(void)
+{
+ unsigned long family;
+ unsigned long revision;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **)fw_arg1;
+ prom_envp = (char **)fw_arg2;
+
+ /*
+ * Someday we can use this with PMON2000 to get a
+ * platform call prom routines for output etc. without
+ * having to use grody hacks. For now it's unused.
+ *
+ * struct callvectors *cv = (struct callvectors *) fw_arg3;
+ */
+ family = identify_family();
+ revision = identify_revision();
+
+ switch (family) {
+ case FAMILY_FPGA:
+ if (FPGA_IS_MSP4200(revision)) {
+ /* Old-style revision ID */
+ mips_machgroup = MACH_GROUP_MSP;
+ mips_machtype = MACH_MSP4200_FPGA;
+ } else {
+ mips_machgroup = MACH_GROUP_MSP;
+ mips_machtype = MACH_MSP_OTHER;
+ }
+ break;
+
+ case FAMILY_MSP4200:
+ mips_machgroup = MACH_GROUP_MSP;
+#if defined(CONFIG_PMC_MSP4200_EVAL)
+ mips_machtype = MACH_MSP4200_EVAL;
+#elif defined(CONFIG_PMC_MSP4200_GW)
+ mips_machtype = MACH_MSP4200_GW;
+#else
+ mips_machtype = MACH_MSP_OTHER;
+#endif
+ break;
+
+ case FAMILY_MSP4200_FPGA:
+ mips_machgroup = MACH_GROUP_MSP;
+ mips_machtype = MACH_MSP4200_FPGA;
+ break;
+
+ case FAMILY_MSP7100:
+ mips_machgroup = MACH_GROUP_MSP;
+#if defined(CONFIG_PMC_MSP7120_EVAL)
+ mips_machtype = MACH_MSP7120_EVAL;
+#elif defined(CONFIG_PMC_MSP7120_GW)
+ mips_machtype = MACH_MSP7120_GW;
+#else
+ mips_machtype = MACH_MSP_OTHER;
+#endif
+ break;
+
+ case FAMILY_MSP7100_FPGA:
+ mips_machgroup = MACH_GROUP_MSP;
+ mips_machtype = MACH_MSP7120_FPGA;
+ break;
+
+ default:
+ /* we don't recognize the machine */
+ mips_machgroup = MACH_GROUP_UNKNOWN;
+ mips_machtype = MACH_UNKNOWN;
+ break;
+ }
+
+ /* make sure we have the right initialization routine - sanity */
+ if (mips_machgroup != MACH_GROUP_MSP) {
+ ppfinit("Unknown machine group in a "
+ "MSP initialization routine\n");
+ panic("***Bogosity factor five***, exiting\n");
+ }
+
+ prom_init_cmdline();
+
+ prom_meminit();
+
+ /*
+ * Sub-system setup follows.
+ * Setup functions can either be called here or using the
+ * subsys_initcall mechanism (i.e. see msp_pci_setup). The
+ * order in which they are called can be changed by using the
+ * link order in arch/mips/pmc-sierra/msp71xx/Makefile.
+ *
+ * NOTE: Please keep sub-system specific initialization code
+ * in separate specific files.
+ */
+ msp_serial_setup();
+
+#ifdef CONFIG_PMCTWILED
+ /*
+ * Setup LED states before the subsys_initcall loads other
+ * dependant drivers/modules.
+ */
+ pmctwiled_setup();
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c
new file mode 100644
index 00000000000..2a2beac5a4f
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c
@@ -0,0 +1,94 @@
+/*
+ * Setting up the clock on MSP SOCs. No RTC typically.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+
+#include <asm/mipsregs.h>
+#include <asm/time.h>
+
+#include <msp_prom.h>
+#include <msp_int.h>
+#include <msp_regs.h>
+
+void __init msp_timer_init(void)
+{
+ char *endp, *s;
+ unsigned long cpu_rate = 0;
+
+ if (cpu_rate == 0) {
+ s = prom_getenv("clkfreqhz");
+ cpu_rate = simple_strtoul(s, &endp, 10);
+ if (endp != NULL && *endp != 0) {
+ printk(KERN_ERR
+ "Clock rate in Hz parse error: %s\n", s);
+ cpu_rate = 0;
+ }
+ }
+
+ if (cpu_rate == 0) {
+ s = prom_getenv("clkfreq");
+ cpu_rate = 1000 * simple_strtoul(s, &endp, 10);
+ if (endp != NULL && *endp != 0) {
+ printk(KERN_ERR
+ "Clock rate in MHz parse error: %s\n", s);
+ cpu_rate = 0;
+ }
+ }
+
+ if (cpu_rate == 0) {
+#if defined(CONFIG_PMC_MSP7120_EVAL) \
+ || defined(CONFIG_PMC_MSP7120_GW)
+ cpu_rate = 400000000;
+#elif defined(CONFIG_PMC_MSP7120_FPGA)
+ cpu_rate = 25000000;
+#else
+ cpu_rate = 150000000;
+#endif
+ printk(KERN_ERR
+ "Failed to determine CPU clock rate, "
+ "assuming %ld hz ...\n", cpu_rate);
+ }
+
+ printk(KERN_WARNING "Clock rate set to %ld\n", cpu_rate);
+
+ /* timer frequency is 1/2 clock rate */
+ mips_hpt_frequency = cpu_rate/2;
+}
+
+
+void __init plat_timer_setup(struct irqaction *irq)
+{
+#ifdef CONFIG_IRQ_MSP_CIC
+ /* we are using the vpe0 counter for timer interrupts */
+ setup_irq(MSP_INT_VPE0_TIMER, irq);
+#else
+ /* we are using the mips counter for timer interrupts */
+ setup_irq(MSP_INT_TIMER, irq);
+#endif
+}
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_usb.c b/arch/mips/pmc-sierra/msp71xx/msp_usb.c
new file mode 100644
index 00000000000..21f9c70b692
--- /dev/null
+++ b/arch/mips/pmc-sierra/msp71xx/msp_usb.c
@@ -0,0 +1,150 @@
+/*
+ * The setup file for USB related hardware on PMC-Sierra MSP processors.
+ *
+ * Copyright 2006-2007 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/mipsregs.h>
+
+#include <msp_regs.h>
+#include <msp_int.h>
+#include <msp_prom.h>
+
+#if defined(CONFIG_USB_EHCI_HCD)
+static struct resource msp_usbhost_resources [] = {
+ [0] = {
+ .start = MSP_USB_BASE_START,
+ .end = MSP_USB_BASE_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MSP_INT_USB,
+ .end = MSP_INT_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 msp_usbhost_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device msp_usbhost_device = {
+ .name = "pmcmsp-ehci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &msp_usbhost_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ },
+ .num_resources = ARRAY_SIZE (msp_usbhost_resources),
+ .resource = msp_usbhost_resources,
+};
+#endif /* CONFIG_USB_EHCI_HCD */
+
+#if defined(CONFIG_USB_GADGET)
+static struct resource msp_usbdev_resources [] = {
+ [0] = {
+ .start = MSP_USB_BASE,
+ .end = MSP_USB_BASE_END,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = MSP_INT_USB,
+ .end = MSP_INT_USB,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 msp_usbdev_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device msp_usbdev_device = {
+ .name = "msp71xx_udc",
+ .id = 0,
+ .dev = {
+ .dma_mask = &msp_usbdev_dma_mask,
+ .coherent_dma_mask = DMA_32BIT_MASK,
+ },
+ .num_resources = ARRAY_SIZE (msp_usbdev_resources),
+ .resource = msp_usbdev_resources,
+};
+#endif /* CONFIG_USB_GADGET */
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
+static struct platform_device *msp_devs[1];
+#endif
+
+
+static int __init msp_usb_setup(void)
+{
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
+ char *strp;
+ char envstr[32];
+ unsigned int val = 0;
+ int result = 0;
+
+ /*
+ * construct environment name usbmode
+ * set usbmode <host/device> as pmon environment var
+ */
+ snprintf((char *)&envstr[0], sizeof(envstr), "usbmode");
+
+#if defined(CONFIG_USB_EHCI_HCD)
+ /* default to host mode */
+ val = 1;
+#endif
+
+ /* get environment string */
+ strp = prom_getenv((char *)&envstr[0]);
+ if (strp) {
+ if (!strcmp(strp, "device"))
+ val = 0;
+ }
+
+ if (val) {
+#if defined(CONFIG_USB_EHCI_HCD)
+ /* get host mode device */
+ msp_devs[0] = &msp_usbhost_device;
+ ppfinit("platform add USB HOST done %s.\n",
+ msp_devs[0]->name);
+
+ result = platform_add_devices(msp_devs, ARRAY_SIZE (msp_devs));
+#endif /* CONFIG_USB_EHCI_HCD */
+ }
+#if defined(CONFIG_USB_GADGET)
+ else {
+ /* get device mode structure */
+ msp_devs[0] = &msp_usbdev_device;
+ ppfinit("platform add USB DEVICE done %s.\n",
+ msp_devs[0]->name);
+
+ result = platform_add_devices(msp_devs, ARRAY_SIZE (msp_devs));
+ }
+#endif /* CONFIG_USB_GADGET */
+#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */
+
+ return result;
+}
+
+subsys_initcall(msp_usb_setup);
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 305491e74db..d83c4ada14f 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -77,7 +77,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
* stack so the first thing we do is throw away that stuff and load useful
* values into the registers ...
*/
-void prom_boot_secondary(int cpu, struct task_struct *idle)
+void __init prom_boot_secondary(int cpu, struct task_struct *idle)
{
unsigned long gp = (unsigned long) task_thread_info(idle);
unsigned long sp = __KSTK_TOS(idle);
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index f5ea2fe10f1..89891e984b3 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -7,8 +7,6 @@
#include <asm/system.h>
#include <asm/time.h>
-extern asmlinkage void qemu_handle_int(void);
-
asmlinkage void plat_irq_dispatch(void)
{
unsigned int pending = read_c0_status() & read_c0_cause();
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 66df5ac8f08..63afd7e4442 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -46,7 +46,7 @@ static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer;
static int machine_state;
-static void ATTRIB_NORET sgi_machine_power_off(void)
+static void __noreturn sgi_machine_power_off(void)
{
unsigned int tmp;
@@ -68,7 +68,7 @@ static void ATTRIB_NORET sgi_machine_power_off(void)
}
}
-static void ATTRIB_NORET sgi_machine_restart(char *command)
+static void __noreturn sgi_machine_restart(char *command)
{
if (machine_state & MACHINE_SHUTTING_DOWN)
sgi_machine_power_off();
@@ -76,7 +76,7 @@ static void ATTRIB_NORET sgi_machine_restart(char *command)
while (1);
}
-static void ATTRIB_NORET sgi_machine_halt(void)
+static void __noreturn sgi_machine_halt(void)
{
if (machine_state & MACHINE_SHUTTING_DOWN)
sgi_machine_power_off();
diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c
index ce907eda221..123141ab21a 100644
--- a/arch/mips/sgi-ip27/ip27-berr.c
+++ b/arch/mips/sgi-ip27/ip27-berr.c
@@ -21,7 +21,6 @@
#include <asm/traps.h>
#include <asm/uaccess.h>
-extern void dump_tlb_addr(unsigned long addr);
extern void dump_tlb_all(void);
static void dump_hub_information(unsigned long errst0, unsigned long errst1)
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index fe8a1066aec..e5e023f50a0 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -517,7 +517,7 @@ void __init paging_init(void)
pfn_t start_pfn = slot_getbasepfn(node, 0);
pfn_t end_pfn = node_getmaxclick(node) + 1;
- zones_size[ZONE_DMA] = end_pfn - start_pfn;
+ zones_size[ZONE_NORMAL] = end_pfn - start_pfn;
free_area_init_node(node, NODE_DATA(node),
zones_size, start_pfn, NULL);
diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c
index 120b15932ca..ba3697ee7ff 100644
--- a/arch/mips/sgi-ip32/ip32-platform.c
+++ b/arch/mips/sgi-ip32/ip32-platform.c
@@ -1,5 +1,53 @@
+/*
+ * 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) 2007 Ralf Baechle (ralf@linux-mips.org)
+ */
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <asm/ip32/mace.h>
+#include <asm/ip32/ip32_ints.h>
+
+/*
+ * .iobase isn't a constant (in the sense of C) so we fill it in at runtime.
+ */
+#define MACE_PORT(int) \
+{ \
+ .irq = int, \
+ .uartclk = 1843200, \
+ .iotype = UPIO_MEM, \
+ .flags = UPF_SKIP_TEST, \
+ .regshift = 8, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ MACE_PORT(MACEISA_SERIAL1_IRQ),
+ MACE_PORT(MACEISA_SERIAL2_IRQ),
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static int __init uart8250_init(void)
+{
+ uart8250_data[0].iobase = (unsigned long) &mace->isa.serial1;
+ uart8250_data[1].iobase = (unsigned long) &mace->isa.serial1;
+
+ return platform_device_register(&uart8250_device);
+}
+
+device_initcall(uart8250_init);
static __init int meth_devinit(void)
{
@@ -18,3 +66,7 @@ static __init int meth_devinit(void)
}
device_initcall(meth_devinit);
+
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("8250 UART probe driver for SGI IP32 aka O2");
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index 57708fe28bd..bbba066cb40 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -62,12 +62,6 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str)
}
#endif
-#ifdef CONFIG_SERIAL_8250
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#endif /* CONFIG_SERIAL_8250 */
-
/* An arbitrary time; this can be decreased if reliability looks good */
#define WAIT_MS 10
@@ -96,36 +90,6 @@ void __init plat_mem_setup(void)
board_time_init = ip32_time_init;
-#ifdef CONFIG_SERIAL_8250
- {
- static struct uart_port o2_serial[2];
-
- memset(o2_serial, 0, sizeof(o2_serial));
- o2_serial[0].type = PORT_16550A;
- o2_serial[0].line = 0;
- o2_serial[0].irq = MACEISA_SERIAL1_IRQ;
- o2_serial[0].flags = UPF_SKIP_TEST;
- o2_serial[0].uartclk = 1843200;
- o2_serial[0].iotype = UPIO_MEM;
- o2_serial[0].membase = (char *)&mace->isa.serial1;
- o2_serial[0].fifosize = 14;
- /* How much to shift register offset by. Each UART register
- * is replicated over 256 byte space */
- o2_serial[0].regshift = 8;
- o2_serial[1].type = PORT_16550A;
- o2_serial[1].line = 1;
- o2_serial[1].irq = MACEISA_SERIAL2_IRQ;
- o2_serial[1].flags = UPF_SKIP_TEST;
- o2_serial[1].uartclk = 1843200;
- o2_serial[1].iotype = UPIO_MEM;
- o2_serial[1].membase = (char *)&mace->isa.serial2;
- o2_serial[1].fifosize = 14;
- o2_serial[1].regshift = 8;
-
- early_serial_setup(&o2_serial[0]);
- early_serial_setup(&o2_serial[1]);
- }
-#endif
#ifdef CONFIG_SGI_O2MACE_ETH
{
char *mac = ArcGetEnvironmentVariable("eaddr");
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c
index ae4a92c3e52..51898dd1304 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/cfe/setup.c
@@ -62,7 +62,7 @@ extern unsigned long initrd_start, initrd_end;
extern int kgdb_port;
#endif
-static void ATTRIB_NORET cfe_linux_exit(void *arg)
+static void __noreturn cfe_linux_exit(void *arg)
{
int warm = *(int *)arg;
@@ -83,14 +83,14 @@ static void ATTRIB_NORET cfe_linux_exit(void *arg)
while (1);
}
-static void ATTRIB_NORET cfe_linux_restart(char *command)
+static void __noreturn cfe_linux_restart(char *command)
{
static const int zero;
cfe_linux_exit((void *)&zero);
}
-static void ATTRIB_NORET cfe_linux_halt(void)
+static void __noreturn cfe_linux_halt(void)
{
static const int one = 1;
diff --git a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c
deleted file mode 100644
index 97c73c793c3..00000000000
--- a/arch/mips/sibyte/swarm/time.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/*
- * Time routines for the swarm board. We pass all the hard stuff
- * through to the sb1250 handling code. Only thing we really keep
- * track of here is what time of day we think it is. And we don't
- * really even do a good job of that...
- */
-
-
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <asm/addrspace.h>
-#include <asm/io.h>
-
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_smbus.h>
-
-static unsigned long long sec_bias = 0;
-static unsigned int usec_bias = 0;
-
-/* Xicor 1241 definitions */
-
-/*
- * Register bits
- */
-
-#define X1241REG_SR_BAT 0x80 /* currently on battery power */
-#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
-#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
-#define X1241REG_SR_RTCF 0x01 /* clock failed */
-#define X1241REG_BL_BP2 0x80 /* block protect 2 */
-#define X1241REG_BL_BP1 0x40 /* block protect 1 */
-#define X1241REG_BL_BP0 0x20 /* block protect 0 */
-#define X1241REG_BL_WD1 0x10
-#define X1241REG_BL_WD0 0x08
-#define X1241REG_HR_MIL 0x80 /* military time format */
-
-/*
- * Register numbers
- */
-
-#define X1241REG_BL 0x10 /* block protect bits */
-#define X1241REG_INT 0x11 /* */
-#define X1241REG_SC 0x30 /* Seconds */
-#define X1241REG_MN 0x31 /* Minutes */
-#define X1241REG_HR 0x32 /* Hours */
-#define X1241REG_DT 0x33 /* Day of month */
-#define X1241REG_MO 0x34 /* Month */
-#define X1241REG_YR 0x35 /* Year */
-#define X1241REG_DW 0x36 /* Day of Week */
-#define X1241REG_Y2K 0x37 /* Year 2K */
-#define X1241REG_SR 0x3F /* Status register */
-
-#define X1241_CCR_ADDRESS 0x6F
-
-#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
-
-static int xicor_read(uint8_t addr)
-{
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- __raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
- __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA));
- __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
- SMB_CSR(R_SMB_START));
-
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
- SMB_CSR(R_SMB_START));
-
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
- /* Clear error bit by writing a 1 */
- __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
- return -1;
- }
-
- return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
-}
-
-static int xicor_write(uint8_t addr, int b)
-{
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- __raw_writeq(addr, SMB_CSR(R_SMB_CMD));
- __raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
- __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
- SMB_CSR(R_SMB_START));
-
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
- /* Clear error bit by writing a 1 */
- __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
- return -1;
- } else {
- return 0;
- }
-}
-
-/*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
- * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- * sets the minutes. Usually you'll only notice that after reboot!
- */
-int set_rtc_mmss(unsigned long nowtime)
-{
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
-
- cmos_minutes = xicor_read(X1241REG_MN);
- cmos_minutes = BCD2BIN(cmos_minutes);
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
- real_minutes += 30; /* correct for half hour time zone */
- real_minutes %= 60;
-
- /* unlock writes to the CCR */
- xicor_write(X1241REG_SR, X1241REG_SR_WEL);
- xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- real_seconds = BIN2BCD(real_seconds);
- real_minutes = BIN2BCD(real_minutes);
- xicor_write(X1241REG_SC, real_seconds);
- xicor_write(X1241REG_MN, real_minutes);
- } else {
- printk(KERN_WARNING
- "set_rtc_mmss: can't update from %d to %d\n",
- cmos_minutes, real_minutes);
- retval = -1;
- }
-
- xicor_write(X1241REG_SR, 0);
-
- printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds);
-
- return retval;
-}
-
-static unsigned long __init get_swarm_time(void)
-{
- unsigned int year, mon, day, hour, min, sec, y2k;
-
- sec = xicor_read(X1241REG_SC);
- min = xicor_read(X1241REG_MN);
- hour = xicor_read(X1241REG_HR);
-
- if (hour & X1241REG_HR_MIL) {
- hour &= 0x3f;
- } else {
- if (hour & 0x20)
- hour = (hour & 0xf) + 0x12;
- }
-
- sec = BCD2BIN(sec);
- min = BCD2BIN(min);
- hour = BCD2BIN(hour);
-
- day = xicor_read(X1241REG_DT);
- mon = xicor_read(X1241REG_MO);
- year = xicor_read(X1241REG_YR);
- y2k = xicor_read(X1241REG_Y2K);
-
- day = BCD2BIN(day);
- mon = BCD2BIN(mon);
- year = BCD2BIN(year);
- y2k = BCD2BIN(y2k);
-
- year += (y2k * 100);
-
- return mktime(year, mon, day, hour, min, sec);
-}
-
-/*
- * Bring up the timer at 100 Hz.
- */
-void __init swarm_time_init(void)
-{
- unsigned int flags;
- int status;
-
- /* Set up the scd general purpose timer 0 to cpu 0 */
- sb1250_time_init();
-
- /* Establish communication with the Xicor 1241 RTC */
- /* XXXKW how do I share the SMBus with the I2C subsystem? */
-
- __raw_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
- __raw_writeq(0, SMB_CSR(R_SMB_CONTROL));
-
- if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) {
- printk("x1241: couldn't detect on SWARM SMBus 1\n");
- } else {
- if (status & X1241REG_SR_RTCF)
- printk("x1241: battery failed -- time is probably wrong\n");
- write_seqlock_irqsave(&xtime_lock, flags);
- xtime.tv_sec = get_swarm_time();
- xtime.tv_nsec = 0;
- write_sequnlock_irqrestore(&xtime_lock, flags);
- }
-}
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index e5777b7e2bc..471418e4f44 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -2,5 +2,5 @@
# Makefile for the SNI specific part of the kernel
#
-obj-y += irq.o reset.o setup.o ds1216.o a20r.o rm200.o pcimt.o pcit.o time.o
+obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o
obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index 31ab80f1bef..acc9ba76c1a 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -15,7 +15,6 @@
#include <asm/sni.h>
#include <asm/time.h>
-#include <asm/ds1216.h>
#define PORT(_base,_irq) \
{ \
@@ -40,20 +39,34 @@ static struct platform_device a20r_serial8250_device = {
},
};
+static struct resource a20r_ds1216_rsrc[] = {
+ {
+ .start = 0x1c081ffc,
+ .end = 0x1c081fff,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct platform_device a20r_ds1216_device = {
+ .name = "rtc-ds1216",
+ .num_resources = ARRAY_SIZE(a20r_ds1216_rsrc),
+ .resource = a20r_ds1216_rsrc
+};
+
static struct resource snirm_82596_rsrc[] = {
{
- .start = 0xb8000000,
- .end = 0xb8000004,
+ .start = 0x18000000,
+ .end = 0x18000004,
.flags = IORESOURCE_MEM
},
{
- .start = 0xb8010000,
- .end = 0xb8010004,
+ .start = 0x18010000,
+ .end = 0x18010004,
.flags = IORESOURCE_MEM
},
{
- .start = 0xbff00000,
- .end = 0xbff00020,
+ .start = 0x1ff00000,
+ .end = 0x1ff00020,
.flags = IORESOURCE_MEM
},
{
@@ -74,8 +87,8 @@ static struct platform_device snirm_82596_pdev = {
static struct resource snirm_53c710_rsrc[] = {
{
- .start = 0xb9000000,
- .end = 0xb90fffff,
+ .start = 0x19000000,
+ .end = 0x190fffff,
.flags = IORESOURCE_MEM
},
{
@@ -93,8 +106,8 @@ static struct platform_device snirm_53c710_pdev = {
static struct resource sc26xx_rsrc[] = {
{
- .start = 0xbc070000,
- .end = 0xbc0700ff,
+ .start = 0x1c070000,
+ .end = 0x1c0700ff,
.flags = IORESOURCE_MEM
},
{
@@ -205,8 +218,7 @@ void __init sni_a20r_irq_init(void)
void sni_a20r_init(void)
{
- ds1216_base = (volatile unsigned char *) SNI_DS1216_A20R_BASE;
- rtc_mips_get_time = ds1216_get_cmos_time;
+ /* FIXME, remove if not needed */
}
static int __init snirm_a20r_setup_devinit(void)
@@ -218,6 +230,7 @@ static int __init snirm_a20r_setup_devinit(void)
platform_device_register(&snirm_53c710_pdev);
platform_device_register(&sc26xx_pdev);
platform_device_register(&a20r_serial8250_device);
+ platform_device_register(&a20r_ds1216_device);
break;
}
diff --git a/arch/mips/sni/ds1216.c b/arch/mips/sni/ds1216.c
deleted file mode 100644
index 1d92732c14f..00000000000
--- a/arch/mips/sni/ds1216.c
+++ /dev/null
@@ -1,81 +0,0 @@
-
-#include <linux/bcd.h>
-#include <linux/time.h>
-
-#include <asm/ds1216.h>
-
-volatile unsigned char *ds1216_base;
-
-/*
- * Read the 64 bit we'd like to have - It a series
- * of 64 bits showing up in the LSB of the base register.
- *
- */
-static unsigned char *ds1216_read(void)
-{
- static unsigned char rdbuf[8];
- unsigned char c;
- int i, j;
-
- for (i = 0; i < 8; i++) {
- c = 0x0;
- for (j = 0; j < 8; j++) {
- c |= (*ds1216_base & 0x1) << j;
- }
- rdbuf[i] = c;
- }
-
- return rdbuf;
-}
-
-static void ds1216_switch_ds_to_clock(void)
-{
- unsigned char magic[] = {
- 0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
- };
- int i,j,c;
-
- /* Reset magic pointer */
- c = *ds1216_base;
-
- /* Write 64 bit magic to DS1216 */
- for (i = 0; i < 8; i++) {
- c = magic[i];
- for (j = 0; j < 8; j++) {
- *ds1216_base = c;
- c = c >> 1;
- }
- }
-}
-
-unsigned long ds1216_get_cmos_time(void)
-{
- unsigned char *rdbuf;
- unsigned int year, month, date, hour, min, sec;
-
- ds1216_switch_ds_to_clock();
- rdbuf = ds1216_read();
-
- sec = BCD2BIN(DS1216_SEC(rdbuf));
- min = BCD2BIN(DS1216_MIN(rdbuf));
- hour = BCD2BIN(DS1216_HOUR(rdbuf));
- date = BCD2BIN(DS1216_DATE(rdbuf));
- month = BCD2BIN(DS1216_MONTH(rdbuf));
- year = BCD2BIN(DS1216_YEAR(rdbuf));
-
- if (DS1216_1224(rdbuf) && DS1216_AMPM(rdbuf))
- hour+=12;
-
- if (year < 70)
- year += 2000;
- else
- year += 1900;
-
- return mktime(year, month, date, hour, min, sec);
-}
-
-int ds1216_set_rtc_mmss(unsigned long nowtime)
-{
- printk("ds1216_set_rtc_mmss called but not implemented\n");
- return -1;
-}
diff --git a/arch/mips/sni/pcimt.c b/arch/mips/sni/pcimt.c
index 9ee208daa8b..44b1ae62aa4 100644
--- a/arch/mips/sni/pcimt.c
+++ b/arch/mips/sni/pcimt.c
@@ -6,7 +6,7 @@
* for more details.
*
* Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*/
#include <linux/init.h>
@@ -14,7 +14,6 @@
#include <linux/pci.h>
#include <linux/serial_8250.h>
-#include <asm/mc146818-time.h>
#include <asm/sni.h>
#include <asm/time.h>
#include <asm/i8259.h>
@@ -90,6 +89,26 @@ static struct platform_device pcimt_serial8250_device = {
},
};
+static struct resource pcimt_cmos_rsrc[] = {
+ {
+ .start = 0x70,
+ .end = 0x71,
+ .flags = IORESOURCE_IO
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device pcimt_cmos_device = {
+ .name = "rtc_cmos",
+ .num_resources = ARRAY_SIZE(pcimt_cmos_rsrc),
+ .resource = pcimt_cmos_rsrc
+};
+
+
static struct resource sni_io_resource = {
.start = 0x00000000UL,
.end = 0x03bfffffUL,
@@ -131,6 +150,19 @@ static struct resource pcimt_io_resources[] = {
}
};
+static struct resource pcimt_mem_resources[] = {
+ {
+ /*
+ * this region should only be 4 bytes long,
+ * but it's 16MB on all RM300C I've checked
+ */
+ .start = 0x1a000000,
+ .end = 0x1affffff,
+ .name = "PCI INT ACK",
+ .flags = IORESOURCE_BUSY
+ }
+};
+
static struct resource sni_mem_resource = {
.start = 0x18000000UL,
.end = 0x1fbfffffUL,
@@ -145,6 +177,9 @@ static void __init sni_pcimt_resource_init(void)
/* request I/O space for devices used on all i[345]86 PCs */
for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++)
request_resource(&sni_io_resource, pcimt_io_resources + i);
+ /* request MEM space for devices used on all i[345]86 PCs */
+ for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++)
+ request_resource(&sni_mem_resource, pcimt_mem_resources + i);
}
extern struct pci_ops sni_pcimt_ops;
@@ -274,12 +309,10 @@ void __init sni_pcimt_irq_init(void)
change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
}
-void sni_pcimt_init(void)
+void __init sni_pcimt_init(void)
{
sni_pcimt_detect();
sni_pcimt_sc_init();
- rtc_mips_get_time = mc146818_get_cmos_time;
- rtc_mips_set_time = mc146818_set_rtc_mmss;
board_time_init = sni_cpu_time_init;
ioport_resource.end = sni_io_resource.end;
#ifdef CONFIG_PCI
@@ -296,6 +329,7 @@ static int __init snirm_pcimt_setup_devinit(void)
case SNI_BRD_PCI_DESKTOP:
case SNI_BRD_PCI_MTOWER_CPLUS:
platform_device_register(&pcimt_serial8250_device);
+ platform_device_register(&pcimt_cmos_device);
break;
}
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c
index 00d151f4d12..2480c478dcb 100644
--- a/arch/mips/sni/pcit.c
+++ b/arch/mips/sni/pcit.c
@@ -13,7 +13,6 @@
#include <linux/pci.h>
#include <linux/serial_8250.h>
-#include <asm/mc146818-time.h>
#include <asm/sni.h>
#include <asm/time.h>
#include <asm/irq_cpu.h>
@@ -58,6 +57,25 @@ static struct platform_device pcit_cplus_serial8250_device = {
},
};
+static struct resource pcit_cmos_rsrc[] = {
+ {
+ .start = 0x70,
+ .end = 0x71,
+ .flags = IORESOURCE_IO
+ },
+ {
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device pcit_cmos_device = {
+ .name = "rtc_cmos",
+ .num_resources = ARRAY_SIZE(pcit_cmos_rsrc),
+ .resource = pcit_cmos_rsrc
+};
+
static struct resource sni_io_resource = {
.start = 0x00000000UL,
.end = 0x03bfffffUL,
@@ -243,10 +261,8 @@ void __init sni_pcit_cplus_irq_init(void)
setup_irq (MIPS_CPU_IRQ_BASE + 3, &sni_isa_irq);
}
-void sni_pcit_init(void)
+void __init sni_pcit_init(void)
{
- rtc_mips_get_time = mc146818_get_cmos_time;
- rtc_mips_set_time = mc146818_set_rtc_mmss;
board_time_init = sni_cpu_time_init;
ioport_resource.end = sni_io_resource.end;
#ifdef CONFIG_PCI
@@ -261,10 +277,12 @@ static int __init snirm_pcit_setup_devinit(void)
switch (sni_brd_type) {
case SNI_BRD_PCI_TOWER:
platform_device_register(&pcit_serial8250_device);
+ platform_device_register(&pcit_cmos_device);
break;
case SNI_BRD_PCI_TOWER_CPLUS:
platform_device_register(&pcit_cplus_serial8250_device);
+ platform_device_register(&pcit_cmos_device);
break;
}
return 0;
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index b82ff129f5e..28a11d8605c 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -15,7 +15,6 @@
#include <asm/sni.h>
#include <asm/time.h>
-#include <asm/ds1216.h>
#include <asm/irq_cpu.h>
#define PORT(_base,_irq) \
@@ -41,20 +40,34 @@ static struct platform_device rm200_serial8250_device = {
},
};
+static struct resource rm200_ds1216_rsrc[] = {
+ {
+ .start = 0x1cd41ffc,
+ .end = 0x1cd41fff,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct platform_device rm200_ds1216_device = {
+ .name = "rtc-ds1216",
+ .num_resources = ARRAY_SIZE(rm200_ds1216_rsrc),
+ .resource = rm200_ds1216_rsrc
+};
+
static struct resource snirm_82596_rm200_rsrc[] = {
{
- .start = 0xb8000000,
- .end = 0xb80fffff,
+ .start = 0x18000000,
+ .end = 0x180fffff,
.flags = IORESOURCE_MEM
},
{
- .start = 0xbb000000,
- .end = 0xbb000004,
+ .start = 0x1b000000,
+ .end = 0x1b000004,
.flags = IORESOURCE_MEM
},
{
- .start = 0xbff00000,
- .end = 0xbff00020,
+ .start = 0x1ff00000,
+ .end = 0x1ff00020,
.flags = IORESOURCE_MEM
},
{
@@ -75,8 +88,8 @@ static struct platform_device snirm_82596_rm200_pdev = {
static struct resource snirm_53c710_rm200_rsrc[] = {
{
- .start = 0xb9000000,
- .end = 0xb90fffff,
+ .start = 0x19000000,
+ .end = 0x190fffff,
.flags = IORESOURCE_MEM
},
{
@@ -96,6 +109,7 @@ static int __init snirm_setup_devinit(void)
{
if (sni_brd_type == SNI_BRD_RM200) {
platform_device_register(&rm200_serial8250_device);
+ platform_device_register(&rm200_ds1216_device);
platform_device_register(&snirm_82596_rm200_pdev);
platform_device_register(&snirm_53c710_rm200_pdev);
}
@@ -176,11 +190,9 @@ void __init sni_rm200_irq_init(void)
setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq);
}
-void sni_rm200_init(void)
+void __init sni_rm200_init(void)
{
set_io_port_base(SNI_PORT_BASE + 0x02000000);
ioport_resource.end += 0x02000000;
- ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE;
- rtc_mips_get_time = ds1216_get_cmos_time;
board_time_init = sni_cpu_time_init;
}
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 68d7cf609b4..4fedfbda0c7 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -6,7 +6,7 @@
* for more details.
*
* Copyright (C) 1996, 97, 98, 2000, 03, 04, 06 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
*/
#include <linux/eisa.h>
#include <linux/init.h>
@@ -92,3 +92,34 @@ void __init plat_mem_setup(void)
sni_display_setup();
}
+
+#if CONFIG_PCI
+
+#include <linux/pci.h>
+#include <video/vga.h>
+#include <video/cirrus.h>
+
+static void __devinit quirk_cirrus_ram_size(struct pci_dev *dev)
+{
+ u16 cmd;
+
+ /*
+ * firmware doesn't set the ram size correct, so we
+ * need to do it here, otherwise we get screen corruption
+ * on older Cirrus chips
+ */
+ pci_read_config_word (dev, PCI_COMMAND, &cmd);
+ if ((cmd & (PCI_COMMAND_IO|PCI_COMMAND_MEMORY))
+ == (PCI_COMMAND_IO|PCI_COMMAND_MEMORY)) {
+ vga_wseq (NULL, CL_SEQR6, 0x12); /* unlock all extension registers */
+ vga_wseq (NULL, CL_SEQRF, 0x18);
+ }
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5434_8,
+ quirk_cirrus_ram_size);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5436,
+ quirk_cirrus_ram_size);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446,
+ quirk_cirrus_ram_size);
+#endif
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
index 643366eb854..00a03a6e8f5 100644
--- a/arch/mips/sni/sniprom.c
+++ b/arch/mips/sni/sniprom.c
@@ -146,7 +146,10 @@ static void __init sni_console_setup(void)
}
if (baud)
strcpy(options, baud);
- add_preferred_console("ttyS", port, baud ? options : NULL);
+ if (strncmp (cdev, "tty552", 6) == 0)
+ add_preferred_console("ttyS", port, baud ? options : NULL);
+ else
+ add_preferred_console("ttySC", port, baud ? options : NULL);
}
}
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
index a0c11efeaee..40c7c3eeafa 100644
--- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
+++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c
@@ -138,7 +138,6 @@ extern void toshiba_rbtx4927_irq_setup(void);
char *prom_getcmdline(void);
#ifdef CONFIG_PCI
-#define CONFIG_TX4927BUG_WORKAROUND
#undef TX4927_SUPPORT_COMMAND_IO
#undef TX4927_SUPPORT_PCI_66
int tx4927_cpu_clock = 100000000; /* 100MHz */
@@ -669,15 +668,7 @@ void tx4927_pci_setup(void)
/* PCI->GB mappings (MEM 16MB) -not used */
tx4927_pcicptr->p2gm1plbase = 0xffffffff;
-#ifdef CONFIG_TX4927BUG_WORKAROUND
- /*
- * TX4927-PCIC-BUG: P2GM1PUBASE must be 0
- * if P2GM0PUBASE was 0.
- */
- tx4927_pcicptr->p2gm1pubase = 0;
-#else
tx4927_pcicptr->p2gm1pubase = 0xffffffff;
-#endif
tx4927_pcicptr->p2gmgbase[1] = 0;
/* PCI->GB mappings (MEM 1MB) -not used */
@@ -910,16 +901,6 @@ void __init toshiba_rbtx4927_setup(void)
if (tx4927_ccfg_toeon)
tx4927_ccfgptr->ccfg |= TX4927_CCFG_TOE;
- /* SDRAMC fixup */
-#ifdef CONFIG_TX4927BUG_WORKAROUND
- /*
- * TX4927-BUG: INF 01-01-18/ BUG 01-01-22
- * G-bus timeout error detection is incorrect
- */
- if (tx4927_ccfg_toeon)
- tx4927_sdramcptr->tr |= 0x02000000; /* RCD:3tck */
-#endif
-
tx4927_pci_setup();
if (tx4927_using_backplane == 1)
printk("backplane board IS installed\n");
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile
index 2033ae77f63..83cda518f20 100644
--- a/arch/mips/tx4938/common/Makefile
+++ b/arch/mips/tx4938/common/Makefile
@@ -6,6 +6,6 @@
# unless it's something special (ie not a .c file).
#
-obj-y += prom.o setup.o irq.o rtc_rx5c348.o
+obj-y += prom.o setup.o irq.o
obj-$(CONFIG_KGDB) += dbgio.o
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c
deleted file mode 100644
index 07f782fc072..00000000000
--- a/arch/mips/tx4938/common/rtc_rx5c348.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * RTC routines for RICOH Rx5C348 SPI chip.
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/rtc.h>
-#include <linux/time.h>
-#include <linux/bcd.h>
-#include <asm/time.h>
-#include <asm/tx4938/spi.h>
-
-#define EPOCH 2000
-
-/* registers */
-#define Rx5C348_REG_SECOND 0
-#define Rx5C348_REG_MINUTE 1
-#define Rx5C348_REG_HOUR 2
-#define Rx5C348_REG_WEEK 3
-#define Rx5C348_REG_DAY 4
-#define Rx5C348_REG_MONTH 5
-#define Rx5C348_REG_YEAR 6
-#define Rx5C348_REG_ADJUST 7
-#define Rx5C348_REG_ALARM_W_MIN 8
-#define Rx5C348_REG_ALARM_W_HOUR 9
-#define Rx5C348_REG_ALARM_W_WEEK 10
-#define Rx5C348_REG_ALARM_D_MIN 11
-#define Rx5C348_REG_ALARM_D_HOUR 12
-#define Rx5C348_REG_CTL1 14
-#define Rx5C348_REG_CTL2 15
-
-/* register bits */
-#define Rx5C348_BIT_PM 0x20 /* REG_HOUR */
-#define Rx5C348_BIT_Y2K 0x80 /* REG_MONTH */
-#define Rx5C348_BIT_24H 0x20 /* REG_CTL1 */
-#define Rx5C348_BIT_XSTP 0x10 /* REG_CTL2 */
-
-/* commands */
-#define Rx5C348_CMD_W(addr) (((addr) << 4) | 0x08) /* single write */
-#define Rx5C348_CMD_R(addr) (((addr) << 4) | 0x0c) /* single read */
-#define Rx5C348_CMD_MW(addr) (((addr) << 4) | 0x00) /* burst write */
-#define Rx5C348_CMD_MR(addr) (((addr) << 4) | 0x04) /* burst read */
-
-static struct spi_dev_desc srtc_dev_desc = {
- .baud = 1000000, /* 1.0Mbps @ Vdd 2.0V */
- .tcss = 31,
- .tcsh = 1,
- .tcsr = 62,
- /* 31us for Tcss (62us for Tcsr) is required for carry operation) */
- .byteorder = 1, /* MSB-First */
- .polarity = 0, /* High-Active */
- .phase = 1, /* Shift-Then-Sample */
-
-};
-static int srtc_chipid;
-static int srtc_24h;
-
-static inline int
-spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count)
-{
- unsigned char *inbufs[1], *outbufs[1];
- unsigned int incounts[2], outcounts[2];
- inbufs[0] = inbuf;
- incounts[0] = count;
- incounts[1] = 0;
- outbufs[0] = outbuf;
- outcounts[0] = count;
- outcounts[1] = 0;
- return txx9_spi_io(srtc_chipid, &srtc_dev_desc,
- inbufs, incounts, outbufs, outcounts, 0);
-}
-
-/* RTC-dependent code for time.c */
-
-static int
-rtc_rx5c348_set_time(unsigned long t)
-{
- unsigned char inbuf[8];
- struct rtc_time tm;
- u8 year, month, day, hour, minute, second, century;
-
- /* convert */
- to_tm(t, &tm);
-
- year = tm.tm_year % 100;
- month = tm.tm_mon+1; /* tm_mon starts from 0 to 11 */
- day = tm.tm_mday;
- hour = tm.tm_hour;
- minute = tm.tm_min;
- second = tm.tm_sec;
- century = tm.tm_year / 100;
-
- inbuf[0] = Rx5C348_CMD_MW(Rx5C348_REG_SECOND);
- BIN_TO_BCD(second);
- inbuf[1] = second;
- BIN_TO_BCD(minute);
- inbuf[2] = minute;
-
- if (srtc_24h) {
- BIN_TO_BCD(hour);
- inbuf[3] = hour;
- } else {
- /* hour 0 is AM12, noon is PM12 */
- inbuf[3] = 0;
- if (hour >= 12)
- inbuf[3] = Rx5C348_BIT_PM;
- hour = (hour + 11) % 12 + 1;
- BIN_TO_BCD(hour);
- inbuf[3] |= hour;
- }
- inbuf[4] = 0; /* ignore week */
- BIN_TO_BCD(day);
- inbuf[5] = day;
- BIN_TO_BCD(month);
- inbuf[6] = month;
- if (century >= 20)
- inbuf[6] |= Rx5C348_BIT_Y2K;
- BIN_TO_BCD(year);
- inbuf[7] = year;
- /* write in one transfer to avoid data inconsistency */
- return spi_rtc_io(inbuf, NULL, 8);
-}
-
-static unsigned long
-rtc_rx5c348_get_time(void)
-{
- unsigned char inbuf[8], outbuf[8];
- unsigned int year, month, day, hour, minute, second;
-
- inbuf[0] = Rx5C348_CMD_MR(Rx5C348_REG_SECOND);
- memset(inbuf + 1, 0, 7);
- /* read in one transfer to avoid data inconsistency */
- if (spi_rtc_io(inbuf, outbuf, 8))
- return 0;
- second = outbuf[1];
- BCD_TO_BIN(second);
- minute = outbuf[2];
- BCD_TO_BIN(minute);
- if (srtc_24h) {
- hour = outbuf[3];
- BCD_TO_BIN(hour);
- } else {
- hour = outbuf[3] & ~Rx5C348_BIT_PM;
- BCD_TO_BIN(hour);
- hour %= 12;
- if (outbuf[3] & Rx5C348_BIT_PM)
- hour += 12;
- }
- day = outbuf[5];
- BCD_TO_BIN(day);
- month = outbuf[6] & ~Rx5C348_BIT_Y2K;
- BCD_TO_BIN(month);
- year = outbuf[7];
- BCD_TO_BIN(year);
- year += EPOCH;
-
- return mktime(year, month, day, hour, minute, second);
-}
-
-void __init
-rtc_rx5c348_init(int chipid)
-{
- unsigned char inbuf[2], outbuf[2];
- srtc_chipid = chipid;
- /* turn on RTC if it is not on */
- inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL2);
- inbuf[1] = 0;
- spi_rtc_io(inbuf, outbuf, 2);
- if (outbuf[1] & Rx5C348_BIT_XSTP) {
- inbuf[0] = Rx5C348_CMD_W(Rx5C348_REG_CTL2);
- inbuf[1] = 0;
- spi_rtc_io(inbuf, NULL, 2);
- }
-
- inbuf[0] = Rx5C348_CMD_R(Rx5C348_REG_CTL1);
- inbuf[1] = 0;
- spi_rtc_io(inbuf, outbuf, 2);
- if (outbuf[1] & Rx5C348_BIT_24H)
- srtc_24h = 1;
-
- /* set the function pointers */
- rtc_mips_get_time = rtc_rx5c348_get_time;
- rtc_mips_set_time = rtc_rx5c348_set_time;
-}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/Makefile b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
index 226941279d7..10c94e62bf5 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/Makefile
+++ b/arch/mips/tx4938/toshiba_rbtx4938/Makefile
@@ -6,4 +6,4 @@
# unless it's something special (ie not a .c file).
#
-obj-y += prom.o setup.o irq.o spi_eeprom.o spi_txx9.o
+obj-y += prom.o setup.o irq.o spi_eeprom.o
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
index 2e96dbb248b..91aea7aff51 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c
@@ -165,8 +165,6 @@ toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
TX4938_RD08(TOSHIBA_RBTX4938_IOC_INTR_ENAB);
}
-extern void __init txx9_spi_irqinit(int irc_irq);
-
void __init arch_init_irq(void)
{
extern void tx4938_irq_init(void);
@@ -185,9 +183,5 @@ void __init arch_init_irq(void)
/* Onboard 10M Ether: High Active */
TX4938_WR(TX4938_MKA(TX4938_IRC_IRDM0), 0x00000040);
- if (tx4938_ccfgptr->pcfg & TX4938_PCFG_SPI_SEL) {
- txx9_spi_irqinit(RBTX4938_IRQ_IRC_SPI);
- }
-
wbflush();
}
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index f5d1ce739fc..6ed39a5aea7 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -14,13 +14,13 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/ioport.h>
-#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/console.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <asm/wbflush.h>
#include <asm/reboot.h>
@@ -35,6 +35,9 @@
#include <linux/serial.h>
#include <linux/serial_core.h>
#endif
+#include <linux/spi/spi.h>
+#include <asm/tx4938/spi.h>
+#include <asm/gpio.h>
extern void rbtx4938_time_init(void) __init;
extern char * __init prom_getcmdline(void);
@@ -349,7 +352,7 @@ static struct pci_dev *fake_pci_dev(struct pci_controller *hose,
static struct pci_dev dev;
static struct pci_bus bus;
- dev.sysdata = (void *)hose;
+ dev.sysdata = bus.sysdata = hose;
dev.devfn = devfn;
bus.number = busnr;
bus.ops = hose->pci_ops;
@@ -382,8 +385,10 @@ int txboard_pci66_check(struct pci_controller *hose, int top_bus, int current_bu
printk("PCI: Checking 66MHz capabilities...\n");
for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
- early_read_config_word(hose, top_bus, current_bus, pci_devfn,
- PCI_VENDOR_ID, &vid);
+ if (early_read_config_word(hose, top_bus, current_bus,
+ pci_devfn, PCI_VENDOR_ID,
+ &vid) != PCIBIOS_SUCCESSFUL)
+ continue;
if (vid == 0xffff) continue;
@@ -460,7 +465,6 @@ static int __init tx4938_pcibios_init(void)
int extarb = !(tx4938_ccfgptr->ccfg & TX4938_CCFG_PCIXARB);
PCIBIOS_MIN_IO = 0x00001000UL;
- PCIBIOS_MIN_MEM = 0x01000000UL;
mem_base[0] = txboard_request_phys_region_shrink(&mem_size[0]);
io_base[0] = txboard_request_phys_region_shrink(&io_size[0]);
@@ -574,82 +578,43 @@ arch_initcall(tx4938_pcibios_init);
#define SEEPROM3_CS 1 /* IOC */
#define SRTC_CS 2 /* IOC */
-static int rbtx4938_spi_cs_func(int chipid, int on)
-{
- unsigned char bit;
- switch (chipid) {
- case RBTX4938_SEEPROM1_CHIPID:
- if (on)
- tx4938_pioptr->dout &= ~(1 << SEEPROM1_CS);
- else
- tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
- return 0;
- break;
- case RBTX4938_SEEPROM2_CHIPID:
- bit = (1 << SEEPROM2_CS);
- break;
- case RBTX4938_SEEPROM3_CHIPID:
- bit = (1 << SEEPROM3_CS);
- break;
- case RBTX4938_SRTC_CHIPID:
- bit = (1 << SRTC_CS);
- break;
- default:
- return -ENODEV;
- }
- /* bit1,2,4 are low active, bit3 is high active */
- *rbtx4938_spics_ptr =
- (*rbtx4938_spics_ptr & ~bit) |
- ((on ? (bit ^ 0x0b) : ~(bit ^ 0x0b)) & bit);
- return 0;
-}
-
#ifdef CONFIG_PCI
-extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
-
-int rbtx4938_get_tx4938_ethaddr(struct pci_dev *dev, unsigned char *addr)
+static int __init rbtx4938_ethaddr_init(void)
{
- struct pci_controller *channel = (struct pci_controller *)dev->bus->sysdata;
- static unsigned char dat[17];
- static int read_dat = 0;
- int ch = 0;
+ unsigned char dat[17];
+ unsigned char sum;
+ int i;
- if (channel != &tx4938_pci_controller[1])
- return -ENODEV;
- /* TX4938 PCIC1 */
- switch (PCI_SLOT(dev->devfn)) {
- case TX4938_PCIC_IDSEL_AD_TO_SLOT(31):
- ch = 0;
- break;
- case TX4938_PCIC_IDSEL_AD_TO_SLOT(30):
- ch = 1;
- break;
- default:
+ /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
+ if (spi_eeprom_read(SEEPROM1_CS, 0, dat, sizeof(dat))) {
+ printk(KERN_ERR "seeprom: read error.\n");
return -ENODEV;
+ } else {
+ if (strcmp(dat, "MAC") != 0)
+ printk(KERN_WARNING "seeprom: bad signature.\n");
+ for (i = 0, sum = 0; i < sizeof(dat); i++)
+ sum += dat[i];
+ if (sum)
+ printk(KERN_WARNING "seeprom: bad checksum.\n");
}
- if (!read_dat) {
- unsigned char sum;
- int i;
- read_dat = 1;
- /* 0-3: "MAC\0", 4-9:eth0, 10-15:eth1, 16:sum */
- if (spi_eeprom_read(RBTX4938_SEEPROM1_CHIPID,
- 0, dat, sizeof(dat))) {
- printk(KERN_ERR "seeprom: read error.\n");
- } else {
- if (strcmp(dat, "MAC") != 0)
- printk(KERN_WARNING "seeprom: bad signature.\n");
- for (i = 0, sum = 0; i < sizeof(dat); i++)
- sum += dat[i];
- if (sum)
- printk(KERN_WARNING "seeprom: bad checksum.\n");
- }
+ for (i = 0; i < 2; i++) {
+ unsigned int slot = TX4938_PCIC_IDSEL_AD_TO_SLOT(31 - i);
+ unsigned int id = (1 << 8) | PCI_DEVFN(slot, 0); /* bus 1 */
+ struct platform_device *pdev;
+ if (!(tx4938_ccfgptr->pcfg &
+ (i ? TX4938_PCFG_ETH1_SEL : TX4938_PCFG_ETH0_SEL)))
+ continue;
+ pdev = platform_device_alloc("tc35815-mac", id);
+ if (!pdev ||
+ platform_device_add_data(pdev, &dat[4 + 6 * i], 6) ||
+ platform_device_add(pdev))
+ platform_device_put(pdev);
}
- memcpy(addr, &dat[4 + 6 * ch], 6);
return 0;
}
+device_initcall(rbtx4938_ethaddr_init);
#endif /* CONFIG_PCI */
-extern void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on));
static void __init rbtx4938_spi_setup(void)
{
/* set SPI_SEL */
@@ -657,7 +622,6 @@ static void __init rbtx4938_spi_setup(void)
/* chip selects for SPI devices */
tx4938_pioptr->dout |= (1 << SEEPROM1_CS);
tx4938_pioptr->dir |= (1 << SEEPROM1_CS);
- txx9_spi_init(TX4938_SPI_REG, rbtx4938_spi_cs_func);
}
static struct resource rbtx4938_fpga_resource;
@@ -896,10 +860,8 @@ void tx4938_report_pcic_status(void)
/* We use onchip r4k counter or TMR timer as our system wide timer
* interrupt running at 100HZ. */
-extern void __init rtc_rx5c348_init(int chipid);
void __init rbtx4938_time_init(void)
{
- rtc_rx5c348_init(RBTX4938_SRTC_CHIPID);
mips_hpt_frequency = txx9_cpu_clock / 2;
}
@@ -1016,29 +978,6 @@ void __init toshiba_rbtx4938_setup(void)
*rbtx4938_dipsw_ptr, *rbtx4938_bdipsw_ptr);
}
-#ifdef CONFIG_PROC_FS
-extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid);
-static int __init tx4938_spi_proc_setup(void)
-{
- struct proc_dir_entry *tx4938_spi_eeprom_dir;
-
- tx4938_spi_eeprom_dir = proc_mkdir("spi_eeprom", 0);
-
- if (!tx4938_spi_eeprom_dir)
- return -ENOMEM;
-
- /* don't allow user access to RBTX4938_SEEPROM1_CHIPID
- * as it contains eth0 and eth1 MAC addresses
- */
- spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM2_CHIPID);
- spi_eeprom_proc_create(tx4938_spi_eeprom_dir, RBTX4938_SEEPROM3_CHIPID);
-
- return 0;
-}
-
-__initcall(tx4938_spi_proc_setup);
-#endif
-
static int __init rbtx4938_ne_init(void)
{
struct resource res[] = {
@@ -1057,3 +996,176 @@ static int __init rbtx4938_ne_init(void)
return IS_ERR(dev) ? PTR_ERR(dev) : 0;
}
device_initcall(rbtx4938_ne_init);
+
+/* GPIO support */
+
+static DEFINE_SPINLOCK(rbtx4938_spi_gpio_lock);
+
+static void rbtx4938_spi_gpio_set(unsigned gpio, int value)
+{
+ u8 val;
+ unsigned long flags;
+ gpio -= 16;
+ spin_lock_irqsave(&rbtx4938_spi_gpio_lock, flags);
+ val = *rbtx4938_spics_ptr;
+ if (value)
+ val |= 1 << gpio;
+ else
+ val &= ~(1 << gpio);
+ *rbtx4938_spics_ptr = val;
+ mmiowb();
+ spin_unlock_irqrestore(&rbtx4938_spi_gpio_lock, flags);
+}
+
+static int rbtx4938_spi_gpio_dir_out(unsigned gpio, int value)
+{
+ rbtx4938_spi_gpio_set(gpio, value);
+ return 0;
+}
+
+static DEFINE_SPINLOCK(tx4938_gpio_lock);
+
+static int tx4938_gpio_get(unsigned gpio)
+{
+ return tx4938_pioptr->din & (1 << gpio);
+}
+
+static void tx4938_gpio_set_raw(unsigned gpio, int value)
+{
+ u32 val;
+ val = tx4938_pioptr->dout;
+ if (value)
+ val |= 1 << gpio;
+ else
+ val &= ~(1 << gpio);
+ tx4938_pioptr->dout = val;
+}
+
+static void tx4938_gpio_set(unsigned gpio, int value)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tx4938_gpio_lock, flags);
+ tx4938_gpio_set_raw(gpio, value);
+ mmiowb();
+ spin_unlock_irqrestore(&tx4938_gpio_lock, flags);
+}
+
+static int tx4938_gpio_dir_in(unsigned gpio)
+{
+ spin_lock_irq(&tx4938_gpio_lock);
+ tx4938_pioptr->dir &= ~(1 << gpio);
+ mmiowb();
+ spin_unlock_irq(&tx4938_gpio_lock);
+ return 0;
+}
+
+static int tx4938_gpio_dir_out(unsigned int gpio, int value)
+{
+ spin_lock_irq(&tx4938_gpio_lock);
+ tx4938_gpio_set_raw(gpio, value);
+ tx4938_pioptr->dir |= 1 << gpio;
+ mmiowb();
+ spin_unlock_irq(&tx4938_gpio_lock);
+ return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+ if (gpio < 16)
+ return tx4938_gpio_dir_in(gpio);
+ return -EINVAL;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+ if (gpio < 16)
+ return tx4938_gpio_dir_out(gpio, value);
+ if (gpio < 16 + 3)
+ return rbtx4938_spi_gpio_dir_out(gpio, value);
+ return -EINVAL;
+}
+
+int gpio_get_value(unsigned gpio)
+{
+ if (gpio < 16)
+ return tx4938_gpio_get(gpio);
+ return 0;
+}
+
+void gpio_set_value(unsigned gpio, int value)
+{
+ if (gpio < 16)
+ tx4938_gpio_set(gpio, value);
+ else
+ rbtx4938_spi_gpio_set(gpio, value);
+}
+
+/* SPI support */
+
+static void __init txx9_spi_init(unsigned long base, int irq)
+{
+ struct resource res[] = {
+ {
+ .start = base,
+ .end = base + 0x20 - 1,
+ .flags = IORESOURCE_MEM,
+ .parent = &tx4938_reg_resource,
+ }, {
+ .start = irq,
+ .flags = IORESOURCE_IRQ,
+ },
+ };
+ platform_device_register_simple("txx9spi", 0,
+ res, ARRAY_SIZE(res));
+}
+
+static int __init rbtx4938_spi_init(void)
+{
+ struct spi_board_info srtc_info = {
+ .modalias = "rs5c348",
+ .max_speed_hz = 1000000, /* 1.0Mbps @ Vdd 2.0V */
+ .bus_num = 0,
+ .chip_select = 16 + SRTC_CS,
+ /* Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS */
+ .mode = SPI_MODE_1 | SPI_CS_HIGH,
+ };
+ spi_register_board_info(&srtc_info, 1);
+ spi_eeprom_register(SEEPROM1_CS);
+ spi_eeprom_register(16 + SEEPROM2_CS);
+ spi_eeprom_register(16 + SEEPROM3_CS);
+ txx9_spi_init(TX4938_SPI_REG & 0xfffffffffULL, RBTX4938_IRQ_IRC_SPI);
+ return 0;
+}
+arch_initcall(rbtx4938_spi_init);
+
+/* Minimum CLK support */
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ if (!strcmp(id, "spi-baseclk"))
+ return (struct clk *)(txx9_gbus_clock / 2 / 4);
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return (unsigned long)clk;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
index 89596e62f90..4d6b4ade5e8 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c
@@ -10,209 +10,90 @@
* Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
*/
#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
#include <asm/tx4938/spi.h>
-#include <asm/tx4938/tx4938.h>
-/* ATMEL 250x0 instructions */
-#define ATMEL_WREN 0x06
-#define ATMEL_WRDI 0x04
-#define ATMEL_RDSR 0x05
-#define ATMEL_WRSR 0x01
-#define ATMEL_READ 0x03
-#define ATMEL_WRITE 0x02
+#define AT250X0_PAGE_SIZE 8
-#define ATMEL_SR_BSY 0x01
-#define ATMEL_SR_WEN 0x02
-#define ATMEL_SR_BP0 0x04
-#define ATMEL_SR_BP1 0x08
-
-DEFINE_SPINLOCK(spi_eeprom_lock);
-
-static struct spi_dev_desc seeprom_dev_desc = {
- .baud = 1500000, /* 1.5Mbps */
- .tcss = 1,
- .tcsh = 1,
- .tcsr = 1,
- .byteorder = 1, /* MSB-First */
- .polarity = 0, /* High-Active */
- .phase = 0, /* Sample-Then-Shift */
-
-};
-static inline int
-spi_eeprom_io(int chipid,
- unsigned char **inbufs, unsigned int *incounts,
- unsigned char **outbufs, unsigned int *outcounts)
-{
- return txx9_spi_io(chipid, &seeprom_dev_desc,
- inbufs, incounts, outbufs, outcounts, 0);
-}
-
-int spi_eeprom_write_enable(int chipid, int enable)
+/* register board information for at25 driver */
+int __init spi_eeprom_register(int chipid)
{
- unsigned char inbuf[1];
- unsigned char *inbufs[1];
- unsigned int incounts[2];
- unsigned long flags;
- int stat;
- inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;
- inbufs[0] = inbuf;
- incounts[0] = sizeof(inbuf);
- incounts[1] = 0;
- spin_lock_irqsave(&spi_eeprom_lock, flags);
- stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
- return stat;
-}
-
-static int spi_eeprom_read_status_nolock(int chipid)
-{
- unsigned char inbuf[2], outbuf[2];
- unsigned char *inbufs[1], *outbufs[1];
- unsigned int incounts[2], outcounts[2];
- int stat;
- inbuf[0] = ATMEL_RDSR;
- inbuf[1] = 0;
- inbufs[0] = inbuf;
- incounts[0] = sizeof(inbuf);
- incounts[1] = 0;
- outbufs[0] = outbuf;
- outcounts[0] = sizeof(outbuf);
- outcounts[1] = 0;
- stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
- if (stat < 0)
- return stat;
- return outbuf[1];
+ static struct spi_eeprom eeprom = {
+ .name = "at250x0",
+ .byte_len = 128,
+ .page_size = AT250X0_PAGE_SIZE,
+ .flags = EE_ADDR1,
+ };
+ struct spi_board_info info = {
+ .modalias = "at25",
+ .max_speed_hz = 1500000, /* 1.5Mbps */
+ .bus_num = 0,
+ .chip_select = chipid,
+ .platform_data = &eeprom,
+ /* Mode 0: High-Active, Sample-Then-Shift */
+ };
+
+ return spi_register_board_info(&info, 1);
}
-int spi_eeprom_read_status(int chipid)
-{
- unsigned long flags;
- int stat;
- spin_lock_irqsave(&spi_eeprom_lock, flags);
- stat = spi_eeprom_read_status_nolock(chipid);
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
- return stat;
-}
+/* simple temporary spi driver to provide early access to seeprom. */
-int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len)
-{
- unsigned char inbuf[2];
- unsigned char *inbufs[2], *outbufs[2];
- unsigned int incounts[2], outcounts[3];
- unsigned long flags;
- int stat;
- inbuf[0] = ATMEL_READ;
- inbuf[1] = address;
- inbufs[0] = inbuf;
- inbufs[1] = NULL;
- incounts[0] = sizeof(inbuf);
- incounts[1] = 0;
- outbufs[0] = NULL;
- outbufs[1] = buf;
- outcounts[0] = 2;
- outcounts[1] = len;
- outcounts[2] = 0;
- spin_lock_irqsave(&spi_eeprom_lock, flags);
- stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
- return stat;
-}
+static struct read_param {
+ int chipid;
+ int address;
+ unsigned char *buf;
+ int len;
+} *read_param;
-int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len)
+static int __init early_seeprom_probe(struct spi_device *spi)
{
- unsigned char inbuf[2];
- unsigned char *inbufs[2];
- unsigned int incounts[3];
- unsigned long flags;
- int i, stat;
-
- if (address / 8 != (address + len - 1) / 8)
- return -EINVAL;
- stat = spi_eeprom_write_enable(chipid, 1);
- if (stat < 0)
- return stat;
- stat = spi_eeprom_read_status(chipid);
- if (stat < 0)
- return stat;
- if (!(stat & ATMEL_SR_WEN))
- return -EPERM;
-
- inbuf[0] = ATMEL_WRITE;
- inbuf[1] = address;
- inbufs[0] = inbuf;
- inbufs[1] = buf;
- incounts[0] = sizeof(inbuf);
- incounts[1] = len;
- incounts[2] = 0;
- spin_lock_irqsave(&spi_eeprom_lock, flags);
- stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);
- if (stat < 0)
- goto unlock_return;
-
- /* write start. max 10ms */
- for (i = 10; i > 0; i--) {
- int stat = spi_eeprom_read_status_nolock(chipid);
- if (stat < 0)
- goto unlock_return;
- if (!(stat & ATMEL_SR_BSY))
- break;
- mdelay(1);
+ int stat = 0;
+ u8 cmd[2];
+ int len = read_param->len;
+ char *buf = read_param->buf;
+ int address = read_param->address;
+
+ dev_info(&spi->dev, "spiclk %u KHz.\n",
+ (spi->max_speed_hz + 500) / 1000);
+ if (read_param->chipid != spi->chip_select)
+ return -ENODEV;
+ while (len > 0) {
+ /* spi_write_then_read can only work with small chunk */
+ int c = len < AT250X0_PAGE_SIZE ? len : AT250X0_PAGE_SIZE;
+ cmd[0] = 0x03; /* AT25_READ */
+ cmd[1] = address;
+ stat = spi_write_then_read(spi, cmd, sizeof(cmd), buf, c);
+ buf += c;
+ len -= c;
+ address += c;
}
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
- if (i == 0)
- return -EIO;
- return len;
- unlock_return:
- spin_unlock_irqrestore(&spi_eeprom_lock, flags);
return stat;
}
-#ifdef CONFIG_PROC_FS
-#define MAX_SIZE 0x80 /* for ATMEL 25010 */
-static int spi_eeprom_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- unsigned int size = MAX_SIZE;
- if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)
- size = 0;
- return size;
-}
-
-static int spi_eeprom_write_proc(struct file *file, const char *buffer,
- unsigned long count, void *data)
-{
- unsigned int size = MAX_SIZE;
- int i;
- if (file->f_pos >= size)
- return -EIO;
- if (file->f_pos + count > size)
- count = size - file->f_pos;
- for (i = 0; i < count; i += 8) {
- int len = count - i < 8 ? count - i : 8;
- if (spi_eeprom_write((int)data, file->f_pos,
- (unsigned char *)buffer, len) < 0) {
- count = -EIO;
- break;
- }
- buffer += len;
- file->f_pos += len;
- }
- return count;
-}
+static struct spi_driver early_seeprom_driver __initdata = {
+ .driver = {
+ .name = "at25",
+ .owner = THIS_MODULE,
+ },
+ .probe = early_seeprom_probe,
+};
-__init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid)
+int __init spi_eeprom_read(int chipid, int address,
+ unsigned char *buf, int len)
{
- struct proc_dir_entry *entry;
- char name[128];
- sprintf(name, "seeprom-%d", chipid);
- entry = create_proc_entry(name, 0600, dir);
- if (entry) {
- entry->read_proc = spi_eeprom_read_proc;
- entry->write_proc = spi_eeprom_write_proc;
- entry->data = (void *)chipid;
- }
+ int ret;
+ struct read_param param = {
+ .chipid = chipid,
+ .address = address,
+ .buf = buf,
+ .len = len
+ };
+
+ read_param = &param;
+ ret = spi_register_driver(&early_seeprom_driver);
+ if (!ret)
+ spi_unregister_driver(&early_seeprom_driver);
+ return ret;
}
-#endif /* CONFIG_PROC_FS */
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c b/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
deleted file mode 100644
index 08b20cdfd7b..00000000000
--- a/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_txx9.c
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
- * terms of the GNU General Public License version 2. This program is
- * licensed "as is" without any warranty of any kind, whether express
- * or implied.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <asm/tx4938/spi.h>
-#include <asm/tx4938/tx4938.h>
-
-static int (*txx9_spi_cs_func)(int chipid, int on);
-static DEFINE_SPINLOCK(txx9_spi_lock);
-
-extern unsigned int txx9_gbus_clock;
-
-#define SPI_FIFO_SIZE 4
-
-void __init txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on))
-{
- txx9_spi_cs_func = cs_func;
- /* enter config mode */
- tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
-}
-
-static DECLARE_WAIT_QUEUE_HEAD(txx9_spi_wait);
-
-static irqreturn_t txx9_spi_interrupt(int irq, void *dev_id)
-{
- /* disable rx intr */
- tx4938_spiptr->cr0 &= ~TXx9_SPCR0_RBSIE;
- wake_up(&txx9_spi_wait);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction txx9_spi_action = {
- .handler = txx9_spi_interrupt,
- .name = "spi",
-};
-
-void __init txx9_spi_irqinit(int irc_irq)
-{
- setup_irq(irc_irq, &txx9_spi_action);
-}
-
-int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
- unsigned char **inbufs, unsigned int *incounts,
- unsigned char **outbufs, unsigned int *outcounts,
- int cansleep)
-{
- unsigned int incount, outcount;
- unsigned char *inp, *outp;
- int ret;
- unsigned long flags;
-
- spin_lock_irqsave(&txx9_spi_lock, flags);
- if ((tx4938_spiptr->mcr & TXx9_SPMCR_OPMODE) == TXx9_SPMCR_ACTIVE) {
- spin_unlock_irqrestore(&txx9_spi_lock, flags);
- return -EBUSY;
- }
- /* enter config mode */
- tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
- tx4938_spiptr->cr0 =
- (desc->byteorder ? TXx9_SPCR0_SBOS : 0) |
- (desc->polarity ? TXx9_SPCR0_SPOL : 0) |
- (desc->phase ? TXx9_SPCR0_SPHA : 0) |
- 0x08;
- tx4938_spiptr->cr1 =
- (((TXX9_IMCLK + desc->baud) / (2 * desc->baud) - 1) << 8) |
- 0x08 /* 8 bit only */;
- /* enter active mode */
- tx4938_spiptr->mcr = TXx9_SPMCR_ACTIVE;
- spin_unlock_irqrestore(&txx9_spi_lock, flags);
-
- /* CS ON */
- if ((ret = txx9_spi_cs_func(chipid, 1)) < 0) {
- spin_unlock_irqrestore(&txx9_spi_lock, flags);
- return ret;
- }
- udelay(desc->tcss);
-
- /* do scatter IO */
- inp = inbufs ? *inbufs : NULL;
- outp = outbufs ? *outbufs : NULL;
- incount = 0;
- outcount = 0;
- while (1) {
- unsigned char data;
- unsigned int count;
- int i;
- if (!incount) {
- incount = incounts ? *incounts++ : 0;
- inp = (incount && inbufs) ? *inbufs++ : NULL;
- }
- if (!outcount) {
- outcount = outcounts ? *outcounts++ : 0;
- outp = (outcount && outbufs) ? *outbufs++ : NULL;
- }
- if (!inp && !outp)
- break;
- count = SPI_FIFO_SIZE;
- if (incount)
- count = min(count, incount);
- if (outcount)
- count = min(count, outcount);
-
- /* now tx must be idle... */
- while (!(tx4938_spiptr->sr & TXx9_SPSR_SIDLE))
- ;
-
- tx4938_spiptr->cr0 =
- (tx4938_spiptr->cr0 & ~TXx9_SPCR0_RXIFL_MASK) |
- ((count - 1) << 12);
- if (cansleep) {
- /* enable rx intr */
- tx4938_spiptr->cr0 |= TXx9_SPCR0_RBSIE;
- }
- /* send */
- for (i = 0; i < count; i++)
- tx4938_spiptr->dr = inp ? *inp++ : 0;
- /* wait all rx data */
- if (cansleep) {
- wait_event(txx9_spi_wait,
- tx4938_spiptr->sr & TXx9_SPSR_SRRDY);
- } else {
- while (!(tx4938_spiptr->sr & TXx9_SPSR_RBSI))
- ;
- }
- /* receive */
- for (i = 0; i < count; i++) {
- data = tx4938_spiptr->dr;
- if (outp)
- *outp++ = data;
- }
- if (incount)
- incount -= count;
- if (outcount)
- outcount -= count;
- }
-
- /* CS OFF */
- udelay(desc->tcsh);
- txx9_spi_cs_func(chipid, 0);
- udelay(desc->tcsr);
-
- spin_lock_irqsave(&txx9_spi_lock, flags);
- /* enter config mode */
- tx4938_spiptr->mcr = TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR;
- spin_unlock_irqrestore(&txx9_spi_lock, flags);
-
- return 0;
-}
diff --git a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
index f842783acd8..d0d84ec8d63 100644
--- a/arch/mips/vr41xx/common/Makefile
+++ b/arch/mips/vr41xx/common/Makefile
@@ -2,4 +2,4 @@
# Makefile for common code of the NEC VR4100 series.
#
-obj-y += bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
+obj-y += bcu.o cmu.o giu.o icu.o init.o irq.o pmu.o rtc.o siu.o type.o
diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c
new file mode 100644
index 00000000000..d21f6f2d22a
--- /dev/null
+++ b/arch/mips/vr41xx/common/giu.c
@@ -0,0 +1,122 @@
+/*
+ * NEC VR4100 series GIU platform device.
+ *
+ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/irq.h>
+
+static struct resource giu_50pins_pullupdown_resource[] __initdata = {
+ {
+ .start = 0x0b000100,
+ .end = 0x0b00011f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x0b0002e0,
+ .end = 0x0b0002e3,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = GIUINT_IRQ,
+ .end = GIUINT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource giu_36pins_resource[] __initdata = {
+ {
+ .start = 0x0f000140,
+ .end = 0x0f00015f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = GIUINT_IRQ,
+ .end = GIUINT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource giu_48pins_resource[] __initdata = {
+ {
+ .start = 0x0f000140,
+ .end = 0x0f000167,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = GIUINT_IRQ,
+ .end = GIUINT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int __init vr41xx_giu_add(void)
+{
+ struct platform_device *pdev;
+ struct resource *res;
+ unsigned int num;
+ int retval;
+
+ pdev = platform_device_alloc("GIU", -1);
+ if (!pdev)
+ return -ENOMEM;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ pdev->id = GPIO_50PINS_PULLUPDOWN;
+ res = giu_50pins_pullupdown_resource;
+ num = ARRAY_SIZE(giu_50pins_pullupdown_resource);
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ pdev->id = GPIO_36PINS;
+ res = giu_36pins_resource;
+ num = ARRAY_SIZE(giu_36pins_resource);
+ break;
+ case CPU_VR4133:
+ pdev->id = GPIO_48PINS_EDGE_SELECT;
+ res = giu_48pins_resource;
+ num = ARRAY_SIZE(giu_48pins_resource);
+ break;
+ default:
+ retval = -ENODEV;
+ goto err_free_device;
+ }
+
+ retval = platform_device_add_resources(pdev, res, num);
+ if (retval)
+ goto err_free_device;
+
+ retval = platform_device_add(pdev);
+ if (retval)
+ goto err_free_device;
+
+ return 0;
+
+err_free_device:
+ platform_device_put(pdev);
+
+ return retval;
+}
+device_initcall(vr41xx_giu_add);
diff --git a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c
new file mode 100644
index 00000000000..cce605b3d68
--- /dev/null
+++ b/arch/mips/vr41xx/common/rtc.c
@@ -0,0 +1,117 @@
+/*
+ * NEC VR4100 series RTC platform device.
+ *
+ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/irq.h>
+
+static struct resource rtc_type1_resource[] __initdata = {
+ {
+ .start = 0x0b0000c0,
+ .end = 0x0b0000df,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x0b0001c0,
+ .end = 0x0b0001df,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = ELAPSEDTIME_IRQ,
+ .end = ELAPSEDTIME_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = RTCLONG1_IRQ,
+ .end = RTCLONG1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource rtc_type2_resource[] __initdata = {
+ {
+ .start = 0x0f000100,
+ .end = 0x0f00011f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x0f000120,
+ .end = 0x0f00013f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = ELAPSEDTIME_IRQ,
+ .end = ELAPSEDTIME_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = RTCLONG1_IRQ,
+ .end = RTCLONG1_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int __init vr41xx_rtc_add(void)
+{
+ struct platform_device *pdev;
+ struct resource *res;
+ unsigned int num;
+ int retval;
+
+ pdev = platform_device_alloc("RTC", -1);
+ if (!pdev)
+ return -ENOMEM;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ res = rtc_type1_resource;
+ num = ARRAY_SIZE(rtc_type1_resource);
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ res = rtc_type2_resource;
+ num = ARRAY_SIZE(rtc_type2_resource);
+ break;
+ default:
+ retval = -ENODEV;
+ goto err_free_device;
+ }
+
+ retval = platform_device_add_resources(pdev, res, num);
+ if (retval)
+ goto err_free_device;
+
+ retval = platform_device_add(pdev);
+ if (retval)
+ goto err_free_device;
+
+ return 0;
+
+err_free_device:
+ platform_device_put(pdev);
+
+ return retval;
+}
+device_initcall(vr41xx_rtc_add);
diff --git a/arch/mips/vr41xx/common/siu.c b/arch/mips/vr41xx/common/siu.c
new file mode 100644
index 00000000000..a1e77414216
--- /dev/null
+++ b/arch/mips/vr41xx/common/siu.c
@@ -0,0 +1,120 @@
+/*
+ * NEC VR4100 series SIU platform device.
+ *
+ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/vr41xx/siu.h>
+
+static unsigned int siu_type1_ports[SIU_PORTS_MAX] __initdata = {
+ PORT_VR41XX_SIU,
+ PORT_UNKNOWN,
+};
+
+static struct resource siu_type1_resource[] __initdata = {
+ {
+ .start = 0x0c000000,
+ .end = 0x0c00000a,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_IRQ,
+ .end = SIU_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static unsigned int siu_type2_ports[SIU_PORTS_MAX] __initdata = {
+ PORT_VR41XX_SIU,
+ PORT_VR41XX_DSIU,
+};
+
+static struct resource siu_type2_resource[] __initdata = {
+ {
+ .start = 0x0f000800,
+ .end = 0x0f00080a,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = 0x0f000820,
+ .end = 0x0f000829,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = SIU_IRQ,
+ .end = SIU_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = DSIU_IRQ,
+ .end = DSIU_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int __init vr41xx_siu_add(void)
+{
+ struct platform_device *pdev;
+ struct resource *res;
+ unsigned int num;
+ int retval;
+
+ pdev = platform_device_alloc("SIU", -1);
+ if (!pdev)
+ return -ENOMEM;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ pdev->dev.platform_data = siu_type1_ports;
+ res = siu_type1_resource;
+ num = ARRAY_SIZE(siu_type1_resource);
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ pdev->dev.platform_data = siu_type2_ports;
+ res = siu_type2_resource;
+ num = ARRAY_SIZE(siu_type2_resource);
+ break;
+ default:
+ retval = -ENODEV;
+ goto err_free_device;
+ }
+
+ retval = platform_device_add_resources(pdev, res, num);
+ if (retval)
+ goto err_free_device;
+
+ retval = platform_device_add(pdev);
+ if (retval)
+ goto err_free_device;
+
+ return 0;
+
+err_free_device:
+ platform_device_put(pdev);
+
+ return retval;
+}
+device_initcall(vr41xx_siu_add);
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
index d86e1577677..f2042e6466a 100644
--- a/arch/parisc/hpux/fs.c
+++ b/arch/parisc/hpux/fs.c
@@ -21,6 +21,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/file.h>
@@ -69,7 +70,6 @@ struct getdents_callback {
};
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
u64 ino, unsigned d_type)
@@ -77,7 +77,7 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
struct hpux_dirent __user * dirent;
struct getdents_callback * buf = (struct getdents_callback *) __buf;
ino_t d_ino;
- int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+ int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(long));
buf->error = -EINVAL; /* only used if we fail.. */
if (reclen > buf->count)
@@ -102,7 +102,6 @@ static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
}
#undef NAME_OFFSET
-#undef ROUND_UP
int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned int count)
{
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 8474f9e5ca1..42598abf457 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -954,21 +954,6 @@ intr_return:
/* NOTE: Need to enable interrupts incase we schedule. */
ssm PSW_SM_I, %r0
- /* Check for software interrupts */
-
- .import irq_stat,data
-
- load32 irq_stat,%r19
-#ifdef CONFIG_SMP
- mfctl %cr30,%r1
- ldw TI_CPU(%r1),%r1 /* get cpu # - int */
- /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
- ** irq_stat[] is defined using ____cacheline_aligned.
- */
- SHLREG %r1,L1_CACHE_SHIFT,%r20
- add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */
-#endif /* CONFIG_SMP */
-
intr_check_resched:
/* check for reschedule */
@@ -2034,10 +2019,9 @@ ENTRY(syscall_exit)
STREG %r28,TASK_PT_GR28(%r1)
#ifdef CONFIG_HPUX
-
/* <linux/personality.h> cannot be easily included */
#define PER_HPUX 0x10
- LDREG TASK_PERSONALITY(%r1),%r19
+ ldw TASK_PERSONALITY(%r1),%r19
/* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */
ldo -PER_HPUX(%r19), %r19
@@ -2055,24 +2039,6 @@ ENTRY(syscall_exit)
*/
loadgp
-syscall_check_bh:
-
- /* Check for software interrupts */
-
- .import irq_stat,data
-
- load32 irq_stat,%r19
-
-#ifdef CONFIG_SMP
- /* sched.h: int processor */
- /* %r26 is used as scratch register to index into irq_stat[] */
- ldw TI_CPU-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
-
- /* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
- SHLREG %r26,L1_CACHE_SHIFT,%r20
- add %r19,%r20,%r19 /* now have &irq_stat[smp_processor_id()] */
-#endif /* CONFIG_SMP */
-
syscall_check_resched:
/* check for reschedule */
@@ -2114,7 +2080,7 @@ syscall_restore:
/* Are we being ptraced? */
LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
- LDREG TASK_PTRACE(%r1), %r19
+ ldw TASK_PTRACE(%r1), %r19
bb,< %r19,31,syscall_restore_rfi
nop
@@ -2244,7 +2210,7 @@ syscall_do_resched:
#else
nop
#endif
- b syscall_check_bh /* if resched, we start over again */
+ b syscall_check_resched /* if resched, we start over again */
nop
ENDPROC(syscall_exit)
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 39dc835bf89..fd6552c4c08 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -634,7 +634,7 @@ EXPORT_SYMBOL(pdc_lan_station_id);
* pdc_stable_read - Read data from Stable Storage.
* @staddr: Stable Storage address to access.
* @memaddr: The memory address where Stable Storage data shall be copied.
- * @count: number of bytes to transfert. count is multiple of 4.
+ * @count: number of bytes to transfer. count is multiple of 4.
*
* This PDC call reads from the Stable Storage address supplied in staddr
* and copies count bytes to the memory address memaddr.
@@ -660,7 +660,7 @@ EXPORT_SYMBOL(pdc_stable_read);
* pdc_stable_write - Write data to Stable Storage.
* @staddr: Stable Storage address to access.
* @memaddr: The memory address where Stable Storage data shall be read from.
- * @count: number of bytes to transfert. count is multiple of 4.
+ * @count: number of bytes to transfer. count is multiple of 4.
*
* This PDC call reads count bytes from the supplied memaddr address,
* and copies count bytes to the Stable Storage address staddr.
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
index 18ba4cb9159..04848b2b381 100644
--- a/arch/parisc/kernel/hardware.c
+++ b/arch/parisc/kernel/hardware.c
@@ -38,7 +38,7 @@
* so don't reference this table after starting the init process
*/
-static struct hp_hardware hp_hardware_list[] __initdata = {
+static struct hp_hardware hp_hardware_list[] __devinitdata = {
{HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
{HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
{HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
@@ -1219,7 +1219,7 @@ static struct hp_cpu_type_mask {
unsigned short model;
unsigned short mask;
enum cpu_type cpu;
-} hp_cpu_type_mask_list[] __initdata = {
+} hp_cpu_type_mask_list[] __devinitdata = {
{ 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */
{ 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */
@@ -1296,10 +1296,11 @@ static struct hp_cpu_type_mask {
{ 0x05f0, 0x0ff0, pcxw2 }, /* 0x05f0 - 0x05ff */
{ 0x0600, 0x0fe0, pcxl }, /* 0x0600 - 0x061f */
{ 0x0880, 0x0ff0, mako }, /* 0x0880 - 0x088f */
+ { 0x0890, 0x0ff0, mako2 }, /* 0x0890 - 0x089f */
{ 0x0000, 0x0000, pcx } /* terminate table */
};
-char *cpu_name_version[][2] = {
+const char * const cpu_name_version[][2] = {
[pcx] = { "PA7000 (PCX)", "1.0" },
[pcxs] = { "PA7000 (PCX-S)", "1.1a" },
[pcxt] = { "PA7100 (PCX-T)", "1.1b" },
@@ -1311,10 +1312,11 @@ char *cpu_name_version[][2] = {
[pcxw] = { "PA8500 (PCX-W)", "2.0" },
[pcxw_] = { "PA8600 (PCX-W+)", "2.0" },
[pcxw2] = { "PA8700 (PCX-W2)", "2.0" },
- [mako] = { "PA8800 (Mako)", "2.0" }
+ [mako] = { "PA8800 (Mako)", "2.0" },
+ [mako2] = { "PA8900 (Shortfin)", "2.0" }
};
-const char * __init
+const char * __devinit
parisc_hardware_description(struct parisc_device_id *id)
{
struct hp_hardware *listptr;
@@ -1353,7 +1355,7 @@ parisc_hardware_description(struct parisc_device_id *id)
/* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */
-enum cpu_type __init
+enum cpu_type __cpuinit
parisc_get_cpu_type(unsigned long hversion)
{
struct hp_cpu_type_mask *ptr;
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
index d8baa158d8a..43b41df0b54 100644
--- a/arch/parisc/kernel/hpmc.S
+++ b/arch/parisc/kernel/hpmc.S
@@ -295,8 +295,5 @@ os_hpmc_6:
b .
nop
ENDPROC(os_hpmc)
-
- /* this label used to compute os_hpmc checksum */
-ENTRY(os_hpmc_end)
-
+ENTRY(os_hpmc_end) /* this label used to compute os_hpmc checksum */
nop
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index c5c9125dace..76ce5e3b005 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -46,14 +46,10 @@ extern irqreturn_t ipi_interrupt(int, void *);
static volatile unsigned long cpu_eiem = 0;
/*
-** ack bitmap ... habitually set to 1, but reset to zero
+** local ACK bitmap ... habitually set to 1, but reset to zero
** between ->ack() and ->end() of the interrupt to prevent
** re-interruption of a processing interrupt.
*/
-static volatile unsigned long global_ack_eiem = ~0UL;
-/*
-** Local bitmap, same as above but for per-cpu interrupts
-*/
static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL;
static void cpu_disable_irq(unsigned int irq)
@@ -94,13 +90,11 @@ void cpu_ack_irq(unsigned int irq)
int cpu = smp_processor_id();
/* Clear in EIEM so we can no longer process */
- if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
- per_cpu(local_ack_eiem, cpu) &= ~mask;
- else
- global_ack_eiem &= ~mask;
+ per_cpu(local_ack_eiem, cpu) &= ~mask;
/* disable the interrupt */
- set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+ set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
+
/* and now ack it */
mtctl(mask, 23);
}
@@ -111,13 +105,10 @@ void cpu_end_irq(unsigned int irq)
int cpu = smp_processor_id();
/* set it in the eiems---it's no longer in process */
- if (CHECK_IRQ_PER_CPU(irq_desc[irq].status))
- per_cpu(local_ack_eiem, cpu) |= mask;
- else
- global_ack_eiem |= mask;
+ per_cpu(local_ack_eiem, cpu) |= mask;
/* enable the interrupt */
- set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+ set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
}
#ifdef CONFIG_SMP
@@ -354,8 +345,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
local_irq_disable();
irq_enter();
- eirr_val = mfctl(23) & cpu_eiem & global_ack_eiem &
- per_cpu(local_ack_eiem, cpu);
+ eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu);
if (!eirr_val)
goto set_out;
irq = eirr_to_irq(eirr_val);
@@ -381,7 +371,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
return;
set_out:
- set_eiem(cpu_eiem & global_ack_eiem & per_cpu(local_ack_eiem, cpu));
+ set_eiem(cpu_eiem & per_cpu(local_ack_eiem, cpu));
goto out;
}
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index 0c3aecb85a5..23c1388df1f 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -21,6 +21,7 @@
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
@@ -34,7 +35,6 @@
#include <asm/tlbflush.h> /* for purge_tlb_*() macros */
static struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
-static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length);
static unsigned long pcxl_used_bytes __read_mostly = 0;
static unsigned long pcxl_used_pages __read_mostly = 0;
@@ -330,6 +330,54 @@ pcxl_free_range(unsigned long vaddr, size_t size)
dump_resmap();
}
+static int proc_pcxl_dma_show(struct seq_file *m, void *v)
+{
+#if 0
+ u_long i = 0;
+ unsigned long *res_ptr = (u_long *)pcxl_res_map;
+#endif
+ unsigned long total_pages = pcxl_res_size << 3; /* 8 bits per byte */
+
+ seq_printf(m, "\nDMA Mapping Area size : %d bytes (%ld pages)\n",
+ PCXL_DMA_MAP_SIZE, total_pages);
+
+ seq_printf(m, "Resource bitmap : %d bytes\n", pcxl_res_size);
+
+ seq_puts(m, " total: free: used: % used:\n");
+ seq_printf(m, "blocks %8d %8ld %8ld %8ld%%\n", pcxl_res_size,
+ pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes,
+ (pcxl_used_bytes * 100) / pcxl_res_size);
+
+ seq_printf(m, "pages %8ld %8ld %8ld %8ld%%\n", total_pages,
+ total_pages - pcxl_used_pages, pcxl_used_pages,
+ (pcxl_used_pages * 100 / total_pages));
+
+#if 0
+ seq_puts(m, "\nResource bitmap:");
+
+ for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
+ if ((i & 7) == 0)
+ seq_puts(m,"\n ");
+ seq_printf(m, "%s %08lx", buf, *res_ptr);
+ }
+#endif
+ seq_putc(m, '\n');
+ return 0;
+}
+
+static int proc_pcxl_dma_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_pcxl_dma_show, NULL);
+}
+
+static const struct file_operations proc_pcxl_dma_ops = {
+ .owner = THIS_MODULE,
+ .open = proc_pcxl_dma_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int __init
pcxl_dma_init(void)
{
@@ -348,9 +396,10 @@ pcxl_dma_init(void)
"pcxl_dma_init: Unable to create gsc /proc dir entry\n");
else {
struct proc_dir_entry* ent;
- ent = create_proc_info_entry("pcxl_dma", 0,
- proc_gsc_root, pcxl_proc_info);
- if (!ent)
+ ent = create_proc_entry("pcxl_dma", 0, proc_gsc_root);
+ if (ent)
+ ent->proc_fops = &proc_pcxl_dma_ops;
+ else
printk(KERN_WARNING
"pci-dma.c: Unable to create pcxl_dma /proc entry.\n");
}
@@ -551,40 +600,3 @@ struct hppa_dma_ops pcx_dma_ops = {
.dma_sync_sg_for_cpu = pa11_dma_sync_sg_for_cpu,
.dma_sync_sg_for_device = pa11_dma_sync_sg_for_device,
};
-
-
-static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
-{
-#if 0
- u_long i = 0;
- unsigned long *res_ptr = (u_long *)pcxl_res_map;
-#endif
- unsigned long total_pages = pcxl_res_size << 3; /* 8 bits per byte */
-
- sprintf(buf, "\nDMA Mapping Area size : %d bytes (%ld pages)\n",
- PCXL_DMA_MAP_SIZE, total_pages);
-
- sprintf(buf, "%sResource bitmap : %d bytes\n", buf, pcxl_res_size);
-
- strcat(buf, " total: free: used: % used:\n");
- sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size,
- pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes,
- (pcxl_used_bytes * 100) / pcxl_res_size);
-
- sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
- total_pages - pcxl_used_pages, pcxl_used_pages,
- (pcxl_used_pages * 100 / total_pages));
-
-#if 0
- strcat(buf, "\nResource bitmap:");
-
- for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) {
- if ((i & 7) == 0)
- strcat(buf,"\n ");
- sprintf(buf, "%s %08lx", buf, *res_ptr);
- }
-#endif
- strcat(buf, "\n");
- return strlen(buf);
-}
-
diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
index a46bc62b643..89d6d5ad44b 100644
--- a/arch/parisc/kernel/perf.c
+++ b/arch/parisc/kernel/perf.c
@@ -171,7 +171,7 @@ static const uint64_t perf_bitmasks[] = {
/*
* Write control bitmasks for Pa-8700 processor given
- * somethings have changed slightly.
+ * some things have changed slightly.
*/
static const uint64_t perf_bitmasks_piranha[] = {
0x0000000000000000ul, /* first dbl word must be zero */
@@ -511,10 +511,12 @@ static int __init perf_init(void)
} else if (boot_cpu_data.cpu_type == pcxw ||
boot_cpu_data.cpu_type == pcxw_ ||
boot_cpu_data.cpu_type == pcxw2 ||
- boot_cpu_data.cpu_type == mako) {
+ boot_cpu_data.cpu_type == mako ||
+ boot_cpu_data.cpu_type == mako2) {
perf_processor_interface = CUDA_INTF;
if (boot_cpu_data.cpu_type == pcxw2 ||
- boot_cpu_data.cpu_type == mako)
+ boot_cpu_data.cpu_type == mako ||
+ boot_cpu_data.cpu_type == mako2)
bitmask_array = perf_bitmasks_piranha;
} else {
perf_processor_interface = UNKNOWN_INTF;
@@ -574,27 +576,27 @@ static int perf_stop_counters(uint32_t *raddr)
if (!perf_rdr_read_ubuf(16, userbuf))
return -13;
- /* Counter0 is bits 1398 thru 1429 */
+ /* Counter0 is bits 1398 to 1429 */
tmp64 = (userbuf[21] << 22) & 0x00000000ffc00000;
tmp64 |= (userbuf[22] >> 42) & 0x00000000003fffff;
/* OR sticky0 (bit 1430) to counter0 bit 32 */
tmp64 |= (userbuf[22] >> 10) & 0x0000000080000000;
raddr[0] = (uint32_t)tmp64;
- /* Counter1 is bits 1431 thru 1462 */
+ /* Counter1 is bits 1431 to 1462 */
tmp64 = (userbuf[22] >> 9) & 0x00000000ffffffff;
/* OR sticky1 (bit 1463) to counter1 bit 32 */
tmp64 |= (userbuf[22] << 23) & 0x0000000080000000;
raddr[1] = (uint32_t)tmp64;
- /* Counter2 is bits 1464 thru 1495 */
+ /* Counter2 is bits 1464 to 1495 */
tmp64 = (userbuf[22] << 24) & 0x00000000ff000000;
tmp64 |= (userbuf[23] >> 40) & 0x0000000000ffffff;
/* OR sticky2 (bit 1496) to counter2 bit 32 */
tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000;
raddr[2] = (uint32_t)tmp64;
- /* Counter3 is bits 1497 thru 1528 */
+ /* Counter3 is bits 1497 to 1528 */
tmp64 = (userbuf[23] >> 7) & 0x00000000ffffffff;
/* OR sticky3 (bit 1529) to counter3 bit 32 */
tmp64 |= (userbuf[23] << 25) & 0x0000000080000000;
@@ -616,7 +618,7 @@ static int perf_stop_counters(uint32_t *raddr)
userbuf[23] = 0;
/*
- * Write back the zero'ed bytes + the image given
+ * Write back the zeroed bytes + the image given
* the read was destructive.
*/
perf_rdr_write(16, userbuf);
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 0dd3847f494..355664812b8 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -381,6 +381,10 @@ get_wchan(struct task_struct *p)
struct unwind_frame_info info;
unsigned long ip;
int count = 0;
+
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
/*
* These bracket the sleeping functions..
*/
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 566226d78bc..549f5484342 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -63,7 +63,7 @@ extern int update_cr16_clocksource(void); /* from time.c */
** will call register_parisc_driver(&cpu_driver) before calling do_inventory().
**
** The goal of consolidating CPU initialization into one place is
-** to make sure all CPU's get initialized the same way.
+** to make sure all CPUs get initialized the same way.
** The code path not shared is how PDC hands control of the CPU to the OS.
** The initialization of OS data structures is the same (done below).
*/
@@ -76,7 +76,7 @@ extern int update_cr16_clocksource(void); /* from time.c */
* (return 1). If so, initialize the chip and tell other partners in crime
* they have work to do.
*/
-static int __init processor_probe(struct parisc_device *dev)
+static int __cpuinit processor_probe(struct parisc_device *dev)
{
unsigned long txn_addr;
unsigned long cpuid;
@@ -166,7 +166,7 @@ static int __init processor_probe(struct parisc_device *dev)
#endif
/*
- ** CONFIG_SMP: init_smp_config() will attempt to get CPU's into
+ ** CONFIG_SMP: init_smp_config() will attempt to get CPUs into
** OS control. RENDEZVOUS is the default state - see mem_set above.
** p->state = STATE_RENDEZVOUS;
*/
@@ -334,7 +334,7 @@ int __init init_per_cpu(int cpunum)
}
/*
- * Display cpu info for all cpu's.
+ * Display CPU info for all CPUs.
*/
int
show_cpuinfo (struct seq_file *m, void *v)
@@ -381,19 +381,19 @@ show_cpuinfo (struct seq_file *m, void *v)
return 0;
}
-static struct parisc_device_id processor_tbl[] __read_mostly = {
+static const struct parisc_device_id processor_tbl[] = {
{ HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID },
{ 0, }
};
-static struct parisc_driver cpu_driver __read_mostly = {
+static struct parisc_driver cpu_driver = {
.name = "CPU",
.id_table = processor_tbl,
.probe = processor_probe
};
/**
- * processor_init - Processor initalization procedure.
+ * processor_init - Processor initialization procedure.
*
* Register this driver.
*/
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index 9818919571f..c44b8c51f5d 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -45,7 +45,7 @@
#include <asm/io.h>
#include <asm/setup.h>
-char __initdata command_line[COMMAND_LINE_SIZE];
+static char __initdata command_line[COMMAND_LINE_SIZE];
/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
struct proc_dir_entry * proc_runway_root __read_mostly = NULL;
@@ -162,7 +162,7 @@ void __init setup_arch(char **cmdline_p)
}
/*
- * Display cpu info for all cpu's.
+ * Display CPU info for all CPUs.
* for parisc this is in processor.c
*/
extern int show_cpuinfo (struct seq_file *m, void *v);
@@ -225,6 +225,7 @@ static void __init parisc_proc_mkdir(void)
}
break;
case mako:
+ case mako2:
if (NULL == proc_mckinley_root)
{
proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
index e39b38a67a8..c7800846422 100644
--- a/arch/parisc/kernel/signal32.h
+++ b/arch/parisc/kernel/signal32.h
@@ -113,7 +113,7 @@ int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);
/* In a deft move of uber-hackery, we decide to carry the top half of all
* 64-bit registers in a non-portable, non-ABI, hidden structure.
* Userspace can read the hidden structure if it *wants* but is never
- * guaranteed to be in the same place. Infact the uc_sigmask from the
+ * guaranteed to be in the same place. In fact the uc_sigmask from the
* ucontext_t structure may push the hidden register file downards
*/
struct compat_regfile {
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 6ba9257fdb7..04c7e1d36ce 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -8,7 +8,7 @@
** Lots of stuff stolen from arch/alpha/kernel/smp.c
** ...and then parisc stole from arch/ia64/kernel/smp.c. Thanks David! :^)
**
-** Thanks to John Curry and Ullas Ponnadi. I learned alot from their work.
+** Thanks to John Curry and Ullas Ponnadi. I learned a lot from their work.
** -grant (1/12/2001)
**
** This program is free software; you can redistribute it and/or modify
@@ -419,7 +419,7 @@ smp_cpu_init(int cpunum)
BUG();
enter_lazy_tlb(&init_mm, current);
- init_IRQ(); /* make sure no IRQ's are enabled or pending */
+ init_IRQ(); /* make sure no IRQs are enabled or pending */
start_cpu_itimer();
}
@@ -461,7 +461,7 @@ void __init smp_callin(void)
/*
* Bring one cpu online.
*/
-int __init smp_boot_one_cpu(int cpuid)
+int __cpuinit smp_boot_one_cpu(int cpuid)
{
struct task_struct *idle;
long timeout;
@@ -552,7 +552,7 @@ void __devinit smp_prepare_boot_cpu(void)
/*
** inventory.c:do_inventory() hasn't yet been run and thus we
-** don't 'discover' the additional CPU's until later.
+** don't 'discover' the additional CPUs until later.
*/
void __init smp_prepare_cpus(unsigned int max_cpus)
{
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index ce3245f87fd..bb23ff71c28 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -311,14 +311,13 @@ struct readdir32_callback {
int count;
};
-#define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
static int filldir32 (void *__buf, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type)
{
struct linux32_dirent __user * dirent;
struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
- int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
+ int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, 4);
u32 d_ino;
buf->error = -EINVAL; /* only used if we fail.. */
@@ -350,6 +349,10 @@ sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
struct getdents32_callback buf;
int error;
+ error = -EFAULT;
+ if (!access_ok(VERIFY_WRITE, dirent, count))
+ goto out;
+
error = -EBADF;
file = fget(fd);
if (!file)
@@ -366,8 +369,10 @@ sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
- put_user(file->f_pos, &lastdirent->d_off);
- error = count - buf.count;
+ if (put_user(file->f_pos, &lastdirent->d_off))
+ error = -EFAULT;
+ else
+ error = count - buf.count;
}
out_putf:
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 10859f53e94..56f6231cb86 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -181,7 +181,7 @@ linux_gateway_entry:
/* Are we being ptraced? */
mfctl %cr30, %r1
LDREG TI_TASK(%r1),%r1
- LDREG TASK_PTRACE(%r1), %r1
+ ldw TASK_PTRACE(%r1), %r1
bb,<,n %r1,31,.Ltracesys
/* Note! We cannot use the syscall table that is mapped
@@ -198,7 +198,7 @@ linux_gateway_entry:
ldil L%sys_call_table, %r1
ldo R%sys_call_table(%r1), %r19
#endif
- comiclr,>>= __NR_Linux_syscalls, %r20, %r0
+ comiclr,>> __NR_Linux_syscalls, %r20, %r0
b,n .Lsyscall_nosys
LDREGX %r20(%r19), %r19
@@ -501,7 +501,7 @@ lws_compare_and_swap:
shlw %r20, 4, %r20
add %r20, %r28, %r20
-# ifdef ENABLE_LWS_DEBUG
+# if ENABLE_LWS_DEBUG
/*
DEBUG, check for deadlock!
If the thread register values are the same
@@ -550,7 +550,7 @@ cas_wouldblock:
perspective
*/
cas_action:
-#if defined CONFIG_SMP && defined ENABLE_LWS_DEBUG
+#if defined CONFIG_SMP && ENABLE_LWS_DEBUG
/* DEBUG */
mfctl %cr27, %r1
stw %r1, 4(%sr2,%r20)
@@ -562,7 +562,7 @@ cas_action:
#ifdef CONFIG_SMP
/* Free lock */
stw %r20, 0(%sr2,%r20)
-# ifdef ENABLE_LWS_DEBUG
+# if ENABLE_LWS_DEBUG
/* Clear thread register indicator */
stw %r0, 4(%sr2,%r20)
# endif
@@ -576,7 +576,7 @@ cas_action:
#ifdef CONFIG_SMP
/* Free lock */
stw %r20, 0(%sr2,%r20)
-# ifdef ENABLE_LWS_DEBUG
+# if ENABLE_LWS_DEBUG
stw %r0, 4(%sr2,%r20)
# endif
#endif
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 8bf87e5d9c3..627f3c28ad8 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -30,11 +30,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#undef ENTRY_SAME
-#undef ENTRY_DIFF
-#undef ENTRY_UHOH
-#undef ENTRY_COMP
-#undef ENTRY_OURS
#if defined(CONFIG_64BIT) && !defined(SYSCALL_TABLE_64BIT)
/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
* narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
@@ -405,5 +400,16 @@
ENTRY_SAME(epoll_pwait)
ENTRY_COMP(statfs64)
ENTRY_COMP(fstatfs64)
+ ENTRY_COMP(kexec_load) /* 300 */
+ ENTRY_COMP(utimensat)
+ ENTRY_COMP(signalfd)
+ ENTRY_COMP(timerfd)
+ ENTRY_SAME(eventfd)
+
/* Nothing yet */
+#undef ENTRY_SAME
+#undef ENTRY_DIFF
+#undef ENTRY_UHOH
+#undef ENTRY_COMP
+#undef ENTRY_OURS
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 07a991aa9b0..8b3062a5c81 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -191,7 +191,7 @@ int update_cr16_clocksource(void)
{
int change = 0;
- /* since the cr16 cycle counters are not syncronized across CPUs,
+ /* since the cr16 cycle counters are not synchronized across CPUs,
we'll check if we should switch to a safe clocksource: */
if (clocksource_cr16.rating != 0 && num_online_cpus() > 1) {
clocksource_change_rating(&clocksource_cr16, 0);
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 745ff741490..c3ec9f1ec0f 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -615,7 +615,7 @@ void handle_interruption(int code, struct pt_regs *regs)
case 13:
/* Conditional Trap
- The condition succees in an instruction which traps
+ The condition succeeds in an instruction which traps
on condition */
if(user_mode(regs)){
si.si_signo = SIGFPE;
@@ -802,13 +802,14 @@ void handle_interruption(int code, struct pt_regs *regs)
int __init check_ivt(void *iva)
{
+ extern const u32 os_hpmc[];
+ extern const u32 os_hpmc_end[];
+
int i;
u32 check = 0;
u32 *ivap;
u32 *hpmcp;
u32 length;
- extern void os_hpmc(void);
- extern void os_hpmc_end(void);
if (strcmp((char *)iva, "cows can fly"))
return -1;
@@ -820,7 +821,7 @@ int __init check_ivt(void *iva)
/* Compute Checksum for HPMC handler */
- length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);
+ length = os_hpmc_end - os_hpmc;
ivap[7] = length;
hpmcp = (u32 *)os_hpmc;
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 89c03707ecc..322167737de 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -16,6 +16,8 @@
#include <asm/uaccess.h>
#include <asm/assembly.h>
+#include <asm/asm-offsets.h>
+#include <asm/ptrace.h>
#include <asm/unwind.h>
@@ -26,6 +28,8 @@
#define dbg(x...)
#endif
+#define KERNEL_START (KERNEL_BINARY_TEXT_START - 0x1000)
+
extern struct unwind_table_entry __start___unwind[];
extern struct unwind_table_entry __stop___unwind[];
@@ -197,6 +201,29 @@ static int unwind_init(void)
return 0;
}
+#ifdef CONFIG_64BIT
+#define get_func_addr(fptr) fptr[2]
+#else
+#define get_func_addr(fptr) fptr[0]
+#endif
+
+static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
+{
+ void handle_interruption(int, struct pt_regs *);
+ static unsigned long *hi = (unsigned long)&handle_interruption;
+
+ if (pc == get_func_addr(hi)) {
+ struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
+ dbg("Unwinding through handle_interruption()\n");
+ info->prev_sp = regs->gr[30];
+ info->prev_ip = regs->iaoq[0];
+
+ return 1;
+ }
+
+ return 0;
+}
+
static void unwind_frame_regs(struct unwind_frame_info *info)
{
const struct unwind_table_entry *e;
@@ -216,8 +243,10 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
/* Handle some frequent special cases.... */
{
char symname[KSYM_NAME_LEN+1];
+ char *modname;
- kallsyms_lookup(info->ip, NULL, NULL, NULL, symname);
+ kallsyms_lookup(info->ip, NULL, NULL, &modname,
+ symname);
dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname);
@@ -308,13 +337,15 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
}
}
- info->prev_sp = info->sp - frame_size;
- if (e->Millicode)
- info->rp = info->r31;
- else if (rpoffset)
- info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
- info->prev_ip = info->rp;
- info->rp = 0;
+ if (!unwind_special(info, e->region_start, frame_size)) {
+ info->prev_sp = info->sp - frame_size;
+ if (e->Millicode)
+ info->rp = info->r31;
+ else if (rpoffset)
+ info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
+ info->prev_ip = info->rp;
+ info->rp = 0;
+ }
dbg("analyzing func @ %lx, setting prev_sp=%lx "
"prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
diff --git a/arch/parisc/math-emu/dbl_float.h b/arch/parisc/math-emu/dbl_float.h
index 1570e2e0a32..0c2fa9a951b 100644
--- a/arch/parisc/math-emu/dbl_float.h
+++ b/arch/parisc/math-emu/dbl_float.h
@@ -22,7 +22,7 @@
PA header file -- do not include this header file for non-PA builds.
#endif
-/* 32-bit word grabing functions */
+/* 32-bit word grabbing functions */
#define Dbl_firstword(value) Dallp1(value)
#define Dbl_secondword(value) Dallp2(value)
#define Dbl_thirdword(value) dummy_location
@@ -37,7 +37,7 @@
#define Dbl_allp1(object) Dallp1(object)
#define Dbl_allp2(object) Dallp2(object)
-/* dbl_and_signs ands the sign bits of each argument and puts the result
+/* dbl_and_signs ANDs the sign bits of each argument and puts the result
* into the first argument. dbl_or_signs ors those same sign bits */
#define Dbl_and_signs( src1dst, src2) \
Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst)
diff --git a/arch/parisc/math-emu/dfsqrt.c b/arch/parisc/math-emu/dfsqrt.c
index b6ed1066f1e..9542c6d281a 100644
--- a/arch/parisc/math-emu/dfsqrt.c
+++ b/arch/parisc/math-emu/dfsqrt.c
@@ -76,7 +76,7 @@ dbl_fsqrt(
}
/*
* Return quiet NaN or positive infinity.
- * Fall thru to negative test if negative infinity.
+ * Fall through to negative test if negative infinity.
*/
if (Dbl_iszero_sign(srcp1) ||
Dbl_isnotzero_mantissa(srcp1,srcp2)) {
diff --git a/arch/parisc/math-emu/sfsqrt.c b/arch/parisc/math-emu/sfsqrt.c
index cd3f6db1f6f..4657a12c910 100644
--- a/arch/parisc/math-emu/sfsqrt.c
+++ b/arch/parisc/math-emu/sfsqrt.c
@@ -76,7 +76,7 @@ sgl_fsqrt(
}
/*
* Return quiet NaN or positive infinity.
- * Fall thru to negative test if negative infinity.
+ * Fall through to negative test if negative infinity.
*/
if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) {
*dstptr = src;
diff --git a/arch/parisc/math-emu/sgl_float.h b/arch/parisc/math-emu/sgl_float.h
index 82519a5c2ba..4ee4cc95e4b 100644
--- a/arch/parisc/math-emu/sgl_float.h
+++ b/arch/parisc/math-emu/sgl_float.h
@@ -23,7 +23,7 @@
PA header file -- do not include this header file for non-PA builds.
#endif
-/* 32-bit word grabing functions */
+/* 32-bit word grabbing functions */
#define Sgl_firstword(value) Sall(value)
#define Sgl_secondword(value) dummy_location
#define Sgl_thirdword(value) dummy_location
@@ -36,7 +36,7 @@
#define Sgl_exponentmantissa(object) Sexponentmantissa(object)
#define Sgl_all(object) Sall(object)
-/* sgl_and_signs ands the sign bits of each argument and puts the result
+/* sgl_and_signs ANDs the sign bits of each argument and puts the result
* into the first argument. sgl_or_signs ors those same sign bits */
#define Sgl_and_signs( src1dst, src2) \
Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst)
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 75ea9f2a8a4..e724b362c49 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -890,7 +890,7 @@ void __init paging_init(void)
#ifdef CONFIG_PA20
/*
- * Currently, all PA20 chips have 18 bit protection id's, which is the
+ * Currently, all PA20 chips have 18 bit protection IDs, which is the
* limiting factor (space ids are 32 bits).
*/
@@ -899,10 +899,10 @@ void __init paging_init(void)
#else
/*
- * Currently we have a one-to-one relationship between space id's and
- * protection id's. Older parisc chips (PCXS, PCXT, PCXL, PCXL2) only
- * support 15 bit protection id's, so that is the limiting factor.
- * PCXT' has 18 bit protection id's, but only 16 bit spaceids, so it's
+ * Currently we have a one-to-one relationship between space IDs and
+ * protection IDs. Older parisc chips (PCXS, PCXT, PCXL, PCXL2) only
+ * support 15 bit protection IDs, so that is the limiting factor.
+ * PCXT' has 18 bit protection IDs, but only 16 bit spaceids, so it's
* probably not worth the effort for a special case here.
*/
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 5eaeafd30bd..6beee32144c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -698,8 +698,10 @@ config PCI
infrastructure code to support PCI bus devices.
config PCI_DOMAINS
- bool
- default PCI
+ def_bool PCI
+
+config PCI_SYSCALL
+ def_bool PCI
config PCI_QSPAN
bool "QSpan PCI"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 6238b5875fd..fbafd965dcd 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -142,7 +142,6 @@ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
# Default to zImage, override when needed
defaultimage-y := zImage
-defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
defaultimage-$(CONFIG_DEFAULT_UIMAGE) := uImage
KBUILD_IMAGE := $(defaultimage-y)
all: $(KBUILD_IMAGE)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 83788986b93..ff2701949ee 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -11,20 +11,18 @@
# bootloader and increase compatibility with OpenFirmware.
#
# To this end we need to define BOOTCC, etc, as the tools
-# needed to build the 32 bit image. These are normally HOSTCC,
-# but may be a third compiler if, for example, you are cross
-# compiling from an intel box. Once the 64bit ppc gcc is
-# stable it will probably simply be a compiler switch to
-# compile for 32bit mode.
+# needed to build the 32 bit image. That's normally the same
+# compiler for the rest of the kernel, with the -m32 flag added.
# To make it easier to setup a cross compiler,
# CROSS32_COMPILE is setup as a prefix just like CROSS_COMPILE
# in the toplevel makefile.
all: $(obj)/zImage
-HOSTCC := gcc
-BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem \
- $(shell $(CROSS32CC) -print-file-name=include) -fPIC
+BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
+ -fno-strict-aliasing -Os -msoft-float -pipe \
+ -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
+ -isystem $(shell $(CROSS32CC) -print-file-name=include)
BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
ifeq ($(call cc-option-yn, -fstack-protector),y)
@@ -33,8 +31,8 @@ endif
BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj)
-$(obj)/44x.o: BOOTCFLAGS += -Wa,-mbooke
-$(obj)/ebony.o: BOOTCFLAGS += -Wa,-mbooke
+$(obj)/44x.o: BOOTCFLAGS += -mcpu=440
+$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
zlib := inffast.c inflate.c inftrees.c
zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
@@ -136,6 +134,7 @@ image-$(CONFIG_PPC_EFIKA) += zImage.chrp
image-$(CONFIG_PPC_PMAC) += zImage.pmac
image-$(CONFIG_PPC_HOLLY) += zImage.holly-elf
image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
+image-$(CONFIG_PPC_ISERIES) += zImage.iseries
image-$(CONFIG_DEFAULT_UIMAGE) += uImage
ifneq ($(CONFIG_DEVICE_TREE),"")
@@ -185,6 +184,9 @@ $(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
$(obj)/zImage.%: vmlinux $(wrapperbits)
$(call if_changed,wrap,$*)
+$(obj)/zImage.iseries: vmlinux
+ $(STRIP) -s -R .comment $< -o $@
+
$(obj)/zImage.ps3: vmlinux
$(STRIP) -s -R .comment $< -o $@
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S
index 5a4215c4b01..f1c4dfc635b 100644
--- a/arch/powerpc/boot/crt0.S
+++ b/arch/powerpc/boot/crt0.S
@@ -13,6 +13,7 @@
.text
/* a procedure descriptor used when booting this as a COFF file */
+ .globl _zimage_start_opd
_zimage_start_opd:
.long _zimage_start, 0, 0, 0
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 2ed8b8b3f0e..da77adc7307 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -129,7 +129,7 @@ case "$platform" in
pmac|pseries|chrp)
platformo=$object/of.o
;;
-pmaccoff)
+coff)
platformo=$object/of.o
lds=$object/zImage.coff.lds
;;
@@ -220,7 +220,7 @@ case "$platform" in
pseries|chrp)
$object/addnote "$ofile"
;;
-pmaccoff)
+coff)
${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
$object/hack-coff "$ofile"
;;
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 02c428affc8..74f83f4a4e5 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc6
-# Mon Apr 23 20:46:48 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:32:34 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -41,6 +41,7 @@ CONFIG_PPC_DCR=y
CONFIG_PPC_OF_PLATFORM_PCI=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
@@ -69,6 +70,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
CONFIG_CPUSETS=y
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
@@ -87,14 +89,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -163,9 +170,14 @@ CONFIG_SPU_FS=m
CONFIG_SPU_BASE=y
CONFIG_CBE_RAS=y
CONFIG_CBE_THERM=m
+CONFIG_CBE_CPUFREQ=m
+# CONFIG_PQ2ADS is not set
CONFIG_PPC_NATIVE=y
CONFIG_UDBG_RTAS_CONSOLE=y
CONFIG_PPC_UDBG_BEAT=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
# CONFIG_U3_DART is not set
CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
@@ -177,9 +189,23 @@ CONFIG_MMIO_NVRAM=y
# CONFIG_PPC_970_NAP is not set
CONFIG_PPC_INDIRECT_IO=y
CONFIG_GENERIC_IOMAP=y
-# CONFIG_CPU_FREQ_PMAC64 is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+
+#
+# CPU Frequency drivers
+#
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -224,12 +250,14 @@ CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_ARCH_MEMORY_PROBE=y
CONFIG_NODES_SPAN_OTHER_NODES=y
+CONFIG_PPC_HAS_HASH_64K=y
CONFIG_PPC_64K_PAGES=y
CONFIG_SCHED_SMT=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
@@ -237,22 +265,18 @@ CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCIEPORTBUS=y
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
CONFIG_KERNEL_START=0xc000000000000000
@@ -264,7 +288,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -300,14 +323,11 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
CONFIG_INET6_AH=m
CONFIG_INET6_ESP=m
CONFIG_INET6_IPCOMP=m
@@ -332,6 +352,7 @@ CONFIG_NETFILTER_NETLINK=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
@@ -389,20 +410,8 @@ CONFIG_IP_NF_ARP_MANGLE=m
#
# CONFIG_IP6_NF_QUEUE is not set
# CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -429,7 +438,16 @@ CONFIG_NET_CLS_ROUTE=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -449,10 +467,6 @@ CONFIG_FW_LOADER=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -489,12 +503,10 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -509,6 +521,7 @@ CONFIG_IDEDISK_MULTI_MODE=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -516,6 +529,7 @@ CONFIG_IDEDISK_MULTI_MODE=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
@@ -580,6 +594,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -626,10 +641,6 @@ CONFIG_SCSI_SAS_ATTRS=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
@@ -652,6 +663,7 @@ CONFIG_SATA_PROMISE=y
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -705,6 +717,7 @@ CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
# CONFIG_DM_MULTIPATH_EMC is not set
+# CONFIG_DM_DELAY is not set
#
# Fusion MPT device support
@@ -719,18 +732,14 @@ CONFIG_FUSION_MAX_SGE=128
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -740,15 +749,7 @@ CONFIG_NETDEVICES=y
CONFIG_BONDING=m
# CONFIG_EQUALIZER is not set
CONFIG_TUN=y
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -767,10 +768,7 @@ CONFIG_MII=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=m
@@ -784,15 +782,13 @@ CONFIG_E1000_NAPI=y
CONFIG_SKGE=m
CONFIG_SKY2=m
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
CONFIG_SPIDER_NET=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
@@ -800,20 +796,24 @@ CONFIG_SPIDER_NET=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_PASEMI_MAC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -840,6 +840,7 @@ CONFIG_SPIDER_NET=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -859,6 +860,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -933,10 +935,6 @@ CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_IPMI_WATCHDOG=m
CONFIG_IPMI_POWEROFF=m
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -959,7 +957,6 @@ CONFIG_WATCHDOG=y
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -971,11 +968,9 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_CHARDEV is not set
#
@@ -999,17 +994,17 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -1036,12 +1031,7 @@ CONFIG_I2C_ALGOBIT=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
# Multifunction device drivers
@@ -1052,17 +1042,19 @@ CONFIG_I2C_ALGOBIT=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -1084,6 +1076,17 @@ CONFIG_HID=m
# CONFIG_HID_DEBUG is not set
#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1096,6 +1099,7 @@ CONFIG_USB=m
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -1147,44 +1151,10 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -1228,10 +1198,6 @@ CONFIG_USB_MON=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1253,10 +1219,12 @@ CONFIG_USB_MON=y
CONFIG_INFINIBAND=m
CONFIG_INFINIBAND_USER_MAD=m
CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_MTHCA_DEBUG=y
# CONFIG_INFINIBAND_AMSO1100 is not set
+# CONFIG_MLX4_INFINIBAND is not set
CONFIG_INFINIBAND_IPOIB=m
# CONFIG_INFINIBAND_IPOIB_CM is not set
CONFIG_INFINIBAND_IPOIB_DEBUG=y
@@ -1287,14 +1255,6 @@ CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1389,6 +1349,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1418,6 +1379,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1468,7 +1430,6 @@ CONFIG_NLS_ISO8859_15=m
#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
#
# Library routines
@@ -1476,6 +1437,7 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
@@ -1487,6 +1449,7 @@ CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1506,7 +1469,6 @@ CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=15
# CONFIG_DETECT_SOFTLOCKUP is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1565,6 +1527,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=m
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig
index 91b657b339b..0dc9874b46e 100644
--- a/arch/powerpc/configs/celleb_defconfig
+++ b/arch/powerpc/configs/celleb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Tue May 8 12:32:16 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:33:17 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -40,6 +40,7 @@ CONFIG_PPC_FPU=y
CONFIG_PPC_OF_PLATFORM_PCI=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
@@ -68,6 +69,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
# CONFIG_CPUSETS is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
@@ -86,14 +88,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -148,6 +155,7 @@ CONFIG_PPC_CELL=y
# Cell Broadband Engine options
#
CONFIG_SPU_FS=y
+CONFIG_SPU_FS_64K_LS=y
CONFIG_SPU_BASE=y
# CONFIG_PQ2ADS is not set
CONFIG_PPC_UDBG_BEAT=y
@@ -206,6 +214,7 @@ CONFIG_RESOURCES_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_ARCH_MEMORY_PROBE=y
CONFIG_NODES_SPAN_OTHER_NODES=y
+CONFIG_PPC_HAS_HASH_64K=y
# CONFIG_PPC_64K_PAGES is not set
# CONFIG_SCHED_SMT is not set
CONFIG_PROC_DEVICETREE=y
@@ -224,16 +233,14 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
CONFIG_KERNEL_START=0xc000000000000000
@@ -277,10 +284,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
@@ -323,20 +326,8 @@ CONFIG_IP_NF_QUEUE=m
#
# CONFIG_IP6_NF_QUEUE is not set
# CONFIG_IP6_NF_IPTABLES is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -369,7 +360,9 @@ CONFIG_IP_NF_QUEUE=m
#
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -425,12 +418,10 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -445,6 +436,7 @@ CONFIG_BLK_DEV_IDECD=m
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -452,6 +444,7 @@ CONFIG_BLK_DEV_IDECD=m
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
@@ -516,6 +509,7 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -560,12 +554,7 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -588,6 +577,7 @@ CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
# CONFIG_DM_MULTIPATH_EMC is not set
+# CONFIG_DM_DELAY is not set
#
# Fusion MPT device support
@@ -600,6 +590,7 @@ CONFIG_DM_MULTIPATH=m
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -616,15 +607,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -643,10 +626,7 @@ CONFIG_MII=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -658,15 +638,13 @@ CONFIG_MII=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
CONFIG_SPIDER_NET=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
@@ -674,10 +652,7 @@ CONFIG_SPIDER_NET=y
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_PASEMI_MAC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
@@ -687,8 +662,14 @@ CONFIG_SPIDER_NET=y
# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -715,6 +696,7 @@ CONFIG_SPIDER_NET=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -734,6 +716,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -797,10 +780,6 @@ CONFIG_HVC_BEAT=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -822,7 +801,6 @@ CONFIG_WATCHDOG=y
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -834,11 +812,9 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_CHARDEV is not set
#
@@ -864,14 +840,15 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -898,12 +875,7 @@ CONFIG_I2C_ALGOBIT=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
# Multifunction device drivers
@@ -914,17 +886,19 @@ CONFIG_I2C_ALGOBIT=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -1015,37 +989,10 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -1089,10 +1036,6 @@ CONFIG_USB_MON=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1136,14 +1079,6 @@ CONFIG_USB_MON=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1246,6 +1181,7 @@ CONFIG_EXPORTFS=m
CONFIG_NFS_ACL_SUPPORT=m
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=m
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1275,6 +1211,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1325,7 +1262,6 @@ CONFIG_NLS_ISO8859_15=m
#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
#
# Library routines
@@ -1333,6 +1269,7 @@ CONFIG_NLS_ISO8859_15=m
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=m
@@ -1340,6 +1277,7 @@ CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1358,7 +1296,6 @@ CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=15
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1395,6 +1332,7 @@ CONFIG_PPC_EARLY_DEBUG=y
# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
CONFIG_PPC_EARLY_DEBUG_BEAT=y
+# CONFIG_PPC_EARLY_DEBUG_44x is not set
#
# Security options
@@ -1425,6 +1363,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=m
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
index 029c9a0e730..7a747c43853 100644
--- a/arch/powerpc/configs/chrp32_defconfig
+++ b/arch/powerpc/configs/chrp32_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:12:58 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:36:45 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_CLASSIC32=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_SMP=y
CONFIG_NR_CPUS=4
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -64,6 +65,7 @@ CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -71,9 +73,11 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=15
# CONFIG_CPUSETS is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -88,14 +92,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -137,13 +146,18 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
CONFIG_PPC_CHRP=y
# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_LITE5200 is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
CONFIG_PPC_NATIVE=y
# CONFIG_UDBG_RTAS_CONSOLE is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
CONFIG_RTAS_PROC=y
@@ -154,8 +168,7 @@ CONFIG_PPC_MPC106=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -186,33 +199,33 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
CONFIG_ISA=y
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -237,7 +250,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -266,10 +278,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
@@ -283,8 +291,6 @@ CONFIG_NETFILTER=y
#
# CONFIG_NETFILTER_NETLINK is not set
CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
CONFIG_NF_CONNTRACK=m
# CONFIG_NF_CT_ACCT is not set
# CONFIG_NF_CONNTRACK_MARK is not set
@@ -296,9 +302,37 @@ CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_IRC=m
# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
-# CONFIG_NETFILTER_XTABLES is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_MAC is not set
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+# CONFIG_NETFILTER_XT_MATCH_STATE is not set
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
#
# IP: Netfilter Configuration
@@ -306,20 +340,38 @@ CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
# CONFIG_IP_NF_QUEUE is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_TOS is not set
+# CONFIG_IP_NF_MATCH_RECENT is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_SAME is not set
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+CONFIG_NF_NAT_SIP=m
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -345,7 +397,16 @@ CONFIG_NF_CONNTRACK_PROC_COMPAT=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -358,16 +419,13 @@ CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -379,6 +437,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Plug and Play support
#
# CONFIG_PNP is not set
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -399,19 +458,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -426,6 +482,7 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -433,12 +490,12 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
@@ -453,6 +510,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -463,11 +521,11 @@ CONFIG_BLK_DEV_SL82C105=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
# CONFIG_IDE_ARM is not set
# CONFIG_IDE_CHIPSETS is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -497,6 +555,7 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -562,10 +621,6 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -589,18 +644,14 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -610,15 +661,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -677,10 +720,8 @@ CONFIG_8139TOO=y
CONFIG_VIA_RHINE=y
# CONFIG_VIA_RHINE_MMIO is not set
# CONFIG_VIA_RHINE_NAPI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -696,33 +737,33 @@ CONFIG_VIA_RHINE=y
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
CONFIG_MV643XX_ETH=y
-# CONFIG_MV643XX_ETH_0 is not set
-# CONFIG_MV643XX_ETH_1 is not set
-# CONFIG_MV643XX_ETH_2 is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -758,6 +799,7 @@ CONFIG_SLHC=m
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -783,15 +825,28 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_INPORT is not set
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_PCSPKR is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
CONFIG_INPUT_UINPUT=y
#
@@ -831,6 +886,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -841,10 +897,6 @@ CONFIG_BRIQ_PANEL=m
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
@@ -861,11 +913,9 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_CHARDEV is not set
#
@@ -893,10 +943,12 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
@@ -928,37 +980,56 @@ CONFIG_I2C_ALGOBIT=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+CONFIG_DISPLAY_SUPPORT=m
+
+#
+# Display hardware drivers
+#
+# CONFIG_VGASTATE is not set
CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
CONFIG_FB_MACMODES=y
-# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_BACKLIGHT=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -978,12 +1049,15 @@ CONFIG_FB_MATROX_G=y
# CONFIG_FB_MATROX_MULTIHEAD is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_RADEON_DEBUG is not set
# CONFIG_FB_ATY128 is not set
CONFIG_FB_ATY=y
CONFIG_FB_ATY_CT=y
# CONFIG_FB_ATY_GENERIC_LCD is not set
CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_BACKLIGHT=y
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
@@ -991,7 +1065,10 @@ CONFIG_FB_ATY_GX=y
CONFIG_FB_3DFX=y
# CONFIG_FB_3DFX_ACCEL is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
@@ -1007,15 +1084,10 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -1026,6 +1098,15 @@ CONFIG_LOGO_LINUX_CLUT224=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
#
# USB support
@@ -1040,9 +1121,8 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1052,9 +1132,12 @@ CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_SL811_HCD is not set
@@ -1088,40 +1171,10 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -1143,6 +1196,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1153,6 +1207,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1163,10 +1218,6 @@ CONFIG_USB_MON=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1210,10 +1261,6 @@ CONFIG_USB_MON=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1323,6 +1370,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1372,6 +1420,7 @@ CONFIG_NLS_ISO8859_1=m
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1379,17 +1428,21 @@ CONFIG_NLS_ISO8859_1=m
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=m
CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
#
# CONFIG_PROFILING is not set
+# CONFIG_KPROBES is not set
#
# Kernel hacking
@@ -1401,15 +1454,15 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1420,6 +1473,10 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
@@ -1454,8 +1511,11 @@ CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1469,6 +1529,7 @@ CONFIG_CRYPTO_ARC4=m
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
diff --git a/arch/powerpc/configs/ebony_defconfig b/arch/powerpc/configs/ebony_defconfig
index c3b96ef3c2d..5762cddfc14 100644
--- a/arch/powerpc/configs/ebony_defconfig
+++ b/arch/powerpc/configs/ebony_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Fri May 4 13:47:08 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:38:33 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_4xx=y
CONFIG_BOOKE=y
CONFIG_PTE_64BIT=y
CONFIG_PHYS_64BIT=y
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -70,6 +71,7 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -87,14 +89,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -193,16 +200,14 @@ CONFIG_PPC_INDIRECT_PCI=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -264,20 +269,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -310,7 +303,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -365,12 +360,10 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -379,10 +372,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -398,6 +387,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -414,35 +404,21 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
#
-# PHY device support
-#
-
-#
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
-CONFIG_IBM_NEW_EMAC=y
-CONFIG_IBM_NEW_EMAC_RXB=128
-CONFIG_IBM_NEW_EMAC_TXB=64
-CONFIG_IBM_NEW_EMAC_POLL_WEIGHT=32
-CONFIG_IBM_NEW_EMAC_RX_COPY_THRESHOLD=256
-CONFIG_IBM_NEW_EMAC_RX_SKB_HEADROOM=0
-# CONFIG_IBM_NEW_EMAC_DEBUG is not set
-CONFIG_IBM_NEW_EMAC_ZMII=y
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_IBM_EMAC=y
+CONFIG_IBM_EMAC_RXB=128
+CONFIG_IBM_EMAC_TXB=64
+CONFIG_IBM_EMAC_POLL_WEIGHT=32
+CONFIG_IBM_EMAC_RX_COPY_THRESHOLD=256
+CONFIG_IBM_EMAC_RX_SKB_HEADROOM=0
+# CONFIG_IBM_EMAC_DEBUG is not set
+CONFIG_IBM_EMAC_ZMII=y
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -454,24 +430,19 @@ CONFIG_IBM_NEW_EMAC_ZMII=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
@@ -479,10 +450,6 @@ CONFIG_IBM_NEW_EMAC_ZMII=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-
-#
-# Wan interfaces
-#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -550,15 +517,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -569,10 +531,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -585,12 +544,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
# Multifunction device drivers
@@ -601,16 +555,19 @@ CONFIG_LEGACY_PTY_COUNT=256
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -635,10 +592,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -682,14 +635,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -770,6 +715,7 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -795,7 +741,6 @@ CONFIG_MSDOS_PARTITION=y
#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
#
# Library routines
@@ -803,12 +748,14 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -826,7 +773,6 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -851,7 +797,6 @@ CONFIG_FORCED_INLINING=y
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
@@ -882,6 +827,7 @@ CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 3ccf19d8da3..a217f4ebcf7 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:15:04 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 12:38:34 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -27,6 +27,7 @@ CONFIG_GENERIC_TBSYNC=y
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC64_SWSUSP=y
#
# Processor support
@@ -39,6 +40,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_OF_PLATFORM_PCI is not set
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
@@ -59,6 +61,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -66,9 +69,11 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
# CONFIG_CPUSETS is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
@@ -83,14 +88,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -131,15 +141,21 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_PPC_PSERIES is not set
# CONFIG_PPC_ISERIES is not set
# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
CONFIG_PPC_PMAC=y
CONFIG_PPC_PMAC64=y
# CONFIG_PPC_MAPLE is not set
# CONFIG_PPC_PASEMI is not set
+# CONFIG_PPC_CELLEB is not set
+# CONFIG_PPC_PS3 is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_PPC_PS3 is not set
+# CONFIG_PQ2ADS is not set
CONFIG_PPC_NATIVE=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
CONFIG_U3_DART=y
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
@@ -160,9 +176,12 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPU Frequency drivers
+#
CONFIG_CPU_FREQ_PMAC64=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -199,34 +218,34 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_PPC_HAS_HASH_64K is not set
# CONFIG_PPC_64K_PAGES is not set
# CONFIG_SCHED_SMT is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
CONFIG_KERNEL_START=0xc000000000000000
@@ -238,14 +257,15 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -270,10 +290,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
@@ -287,8 +303,6 @@ CONFIG_NETFILTER=y
#
# CONFIG_NETFILTER_NETLINK is not set
CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
CONFIG_NF_CONNTRACK=m
# CONFIG_NF_CT_ACCT is not set
CONFIG_NF_CONNTRACK_MARK=y
@@ -300,6 +314,7 @@ CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_IRC=m
# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
# CONFIG_NF_CONNTRACK_SIP is not set
CONFIG_NF_CONNTRACK_TFTP=m
# CONFIG_NETFILTER_XTABLES is not set
@@ -310,20 +325,10 @@ CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -350,7 +355,16 @@ CONFIG_LLC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -363,16 +377,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -383,6 +394,7 @@ CONFIG_FW_LOADER=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -402,7 +414,6 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
CONFIG_CDROM_PKTCDVD=m
CONFIG_CDROM_PKTCDVD_BUFFERS=8
# CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -411,12 +422,10 @@ CONFIG_CDROM_PKTCDVD_BUFFERS=8
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -431,6 +440,7 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -438,12 +448,12 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
@@ -458,6 +468,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -468,13 +479,13 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -504,6 +515,7 @@ CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -550,11 +562,8 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
CONFIG_SATA_SVW=y
# CONFIG_ATA_PIIX is not set
@@ -570,10 +579,12 @@ CONFIG_SATA_SVW=y
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -585,6 +596,7 @@ CONFIG_SATA_SVW=y
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
@@ -624,6 +636,7 @@ CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
#
# Fusion MPT device support
@@ -636,28 +649,26 @@ CONFIG_DM_ZERO=m
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
CONFIG_IEEE1394=y
#
# Subsystem Options
#
# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-CONFIG_IEEE1394_OUI_DB=y
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
#
-# Device Drivers
+# Controllers
#
# CONFIG_IEEE1394_PCILYNX is not set
CONFIG_IEEE1394_OHCI1394=y
#
-# Protocol Drivers
+# Protocols
#
CONFIG_IEEE1394_VIDEO1394=m
CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
CONFIG_IEEE1394_ETH1394=m
CONFIG_IEEE1394_DV1394=m
CONFIG_IEEE1394_RAWIO=y
@@ -666,10 +677,7 @@ CONFIG_IEEE1394_RAWIO=y
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
+CONFIG_MACINTOSH_DRIVERS=y
CONFIG_ADB_PMU=y
# CONFIG_ADB_PMU_LED is not set
CONFIG_PMAC_SMU=y
@@ -689,15 +697,7 @@ CONFIG_DUMMY=m
CONFIG_BONDING=m
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -716,10 +716,7 @@ CONFIG_SUNGEM=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
CONFIG_ACENIC=y
CONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not set
@@ -734,35 +731,50 @@ CONFIG_E1000=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_PASEMI_MAC is not set
+# CONFIG_MLX4_CORE is not set
CONFIG_TR=y
CONFIG_IBMOL=y
# CONFIG_3C359 is not set
# CONFIG_TMS380TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET_MII is not set
+CONFIG_USB_USBNET=m
+# CONFIG_USB_NET_AX8817X is not set
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_GL620A is not set
+# CONFIG_USB_NET_NET1080 is not set
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+# CONFIG_USB_NET_ZAURUS is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -798,6 +810,7 @@ CONFIG_SLHC=m
#
CONFIG_INPUT=y
CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -824,8 +837,10 @@ CONFIG_INPUT_KEYBOARD=y
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -866,15 +881,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
CONFIG_AGP=m
@@ -888,11 +898,9 @@ CONFIG_MAX_RAW_DEVS=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -919,14 +927,15 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -953,37 +962,53 @@ CONFIG_I2C_POWERMAC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+CONFIG_VGASTATE=y
CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
CONFIG_FB_MACMODES=y
-# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_BACKLIGHT=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -994,20 +1019,27 @@ CONFIG_FB_OF=y
# CONFIG_FB_S1D13XXX is not set
CONFIG_FB_NVIDIA=y
CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
+CONFIG_FB_NVIDIA_BACKLIGHT=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_RADEON_DEBUG is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
@@ -1021,19 +1053,10 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
#
# Sound
@@ -1152,6 +1175,12 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m
#
CONFIG_SND_USB_AUDIO=m
# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
#
# Open Sound System
@@ -1162,6 +1191,20 @@ CONFIG_SND_USB_AUDIO=m
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_THRUSTMASTER_FF=y
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_HIDDEV=y
#
# USB support
@@ -1176,9 +1219,8 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1188,9 +1230,15 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
@@ -1224,53 +1272,10 @@ CONFIG_USB_STORAGE_JUMPSHOT=y
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-CONFIG_HID_FF=y
-CONFIG_HID_PID=y
-CONFIG_LOGITECH_FF=y
-CONFIG_THRUSTMASTER_FF=y
-# CONFIG_ZEROPLUS_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-# CONFIG_USB_USBNET_MII is not set
-CONFIG_USB_USBNET=m
-# CONFIG_USB_NET_AX8817X is not set
-CONFIG_USB_NET_CDCETHER=m
-# CONFIG_USB_NET_GL620A is not set
-# CONFIG_USB_NET_NET1080 is not set
-# CONFIG_USB_NET_PLUSB is not set
-# CONFIG_USB_NET_MCS7830 is not set
-# CONFIG_USB_NET_RNDIS_HOST is not set
-# CONFIG_USB_NET_CDC_SUBSET is not set
-# CONFIG_USB_NET_ZAURUS is not set
CONFIG_USB_MON=y
#
@@ -1343,6 +1348,7 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1353,6 +1359,7 @@ CONFIG_USB_APPLEDISPLAY=m
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1363,10 +1370,6 @@ CONFIG_USB_APPLEDISPLAY=m
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1410,10 +1413,6 @@ CONFIG_USB_APPLEDISPLAY=m
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1461,7 +1460,6 @@ CONFIG_AUTOFS_FS=m
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y
@@ -1527,6 +1525,7 @@ CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1561,6 +1560,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1610,6 +1610,7 @@ CONFIG_NLS_UTF8=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1617,12 +1618,15 @@ CONFIG_NLS_UTF8=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1641,15 +1645,15 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1659,8 +1663,10 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
CONFIG_IRQSTACKS=y
CONFIG_BOOTX_TEXT=y
@@ -1693,8 +1699,11 @@ CONFIG_CRYPTO_WP512=m
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1709,6 +1718,7 @@ CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_TEST=m
#
diff --git a/arch/powerpc/configs/holly_defconfig b/arch/powerpc/configs/holly_defconfig
index be633b9b57c..32781849ad4 100644
--- a/arch/powerpc/configs/holly_defconfig
+++ b/arch/powerpc/configs/holly_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Sat May 5 11:02:35 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:22:36 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -70,6 +71,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -87,14 +89,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -140,6 +147,7 @@ CONFIG_EMBEDDED6xx=y
# CONFIG_LINKSTATION is not set
# CONFIG_MPC7448HPC2 is not set
CONFIG_PPC_HOLLY=y
+# CONFIG_PPC_PRPMC2800 is not set
CONFIG_TSI108_BRIDGE=y
CONFIG_MPIC=y
CONFIG_MPIC_WEIRD=y
@@ -197,16 +205,14 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -271,20 +277,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -317,7 +311,9 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
#
# CONFIG_CFG80211 is not set
# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -372,12 +368,10 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -406,6 +400,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -453,12 +448,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
@@ -531,6 +521,7 @@ CONFIG_ATA=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -547,15 +538,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -589,10 +572,7 @@ CONFIG_VORTEX=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -604,25 +584,20 @@ CONFIG_VORTEX=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
CONFIG_TSI108_ETH=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
@@ -630,10 +605,6 @@ CONFIG_TSI108_ETH=y
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-
-#
-# Wan interfaces
-#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -660,6 +631,7 @@ CONFIG_TSI108_ETH=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -676,6 +648,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -721,16 +694,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -741,10 +709,7 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -757,16 +722,15 @@ CONFIG_GEN_RTC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
@@ -778,16 +742,19 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -818,10 +785,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -865,14 +828,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -957,6 +912,7 @@ CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -986,6 +942,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -997,7 +954,6 @@ CONFIG_MSDOS_PARTITION=y
#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
#
# Library routines
@@ -1005,11 +961,13 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1028,7 +986,6 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig
index af25118c8f2..8e336745242 100644
--- a/arch/powerpc/configs/iseries_defconfig
+++ b/arch/powerpc/configs/iseries_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22-rc1
-# Mon May 14 14:27:46 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:22:39 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -281,10 +281,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
@@ -387,25 +383,13 @@ CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
# CONFIG_SCTP_HMAC_NONE is not set
# CONFIG_SCTP_HMAC_SHA1 is not set
CONFIG_SCTP_HMAC_MD5=y
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -501,10 +485,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
# CONFIG_IDE is not set
#
@@ -581,7 +561,6 @@ CONFIG_SCSI_IBMVSCSI=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_ATA is not set
@@ -634,10 +613,6 @@ CONFIG_DUMMY=m
CONFIG_BONDING=m
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
# CONFIG_PHYLIB is not set
@@ -705,11 +680,6 @@ CONFIG_NETDEV_10000=y
# CONFIG_NETXEN_NIC is not set
# CONFIG_PASEMI_MAC is not set
# CONFIG_MLX4_CORE is not set
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
CONFIG_TR=y
CONFIG_IBMOL=y
# CONFIG_3C359 is not set
@@ -757,6 +727,7 @@ CONFIG_NET_POLL_CONTROLLER=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -1139,7 +1110,6 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_DLM=m
# CONFIG_DLM_DEBUG is not set
# CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
#
# Library routines
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index dde66a597a8..78fd07c5f47 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc6
-# Sun Jan 28 23:13:56 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:25:19 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -24,7 +24,7 @@ CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
-# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
@@ -34,9 +34,9 @@ CONFIG_CLASSIC32=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -63,6 +64,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -70,8 +72,10 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -86,14 +90,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -133,8 +142,20 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_EMBEDDED6xx=y
# CONFIG_APUS is not set
# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+CONFIG_LINKSTATION=y
+# CONFIG_MPC7448HPC2 is not set
+# CONFIG_PPC_HOLLY is not set
+# CONFIG_PPC_PRPMC2800 is not set
+CONFIG_MPC10X_BRIDGE=y
+CONFIG_MPC10X_OPENPIC=y
+# CONFIG_MPC10X_STORE_GATHERING is not set
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_PPC_MPC106 is not set
@@ -143,39 +164,7 @@ CONFIG_EMBEDDED6xx=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
-# CONFIG_KATANA is not set
-# CONFIG_WILLOW is not set
-# CONFIG_CPCI690 is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_CHESTNUT is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_HDPU is not set
-# CONFIG_EV64260 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-CONFIG_LINKSTATION=y
-# CONFIG_MPC7448HPC2 is not set
-# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBC82xx is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX8260 is not set
-# CONFIG_TQM8260 is not set
-# CONFIG_ADS8272 is not set
-# CONFIG_PQ2FADS is not set
-# CONFIG_EV64360 is not set
-CONFIG_PPC_GEN550=y
-CONFIG_MPC10X_BRIDGE=y
-CONFIG_MPC10X_OPENPIC=y
-# CONFIG_MPC10X_STORE_GATHERING is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -203,33 +192,33 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -254,13 +243,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -289,10 +278,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
@@ -306,8 +291,6 @@ CONFIG_NETFILTER=y
#
# CONFIG_NETFILTER_NETLINK is not set
CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
CONFIG_NF_CONNTRACK=m
# CONFIG_NF_CT_ACCT is not set
# CONFIG_NF_CONNTRACK_MARK is not set
@@ -320,16 +303,21 @@ CONFIG_NF_CONNTRACK_H323=m
CONFIG_NF_CONNTRACK_IRC=m
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
CONFIG_NF_CONNTRACK_PPTP=m
+# CONFIG_NF_CONNTRACK_SANE is not set
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NETFILTER_XTABLES=m
# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
# CONFIG_NETFILTER_XT_TARGET_MARK is not set
# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
@@ -370,7 +358,6 @@ CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
# CONFIG_IP_NF_TARGET_LOG is not set
# CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -390,24 +377,13 @@ CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -433,6 +409,14 @@ CONFIG_IP_NF_ARP_MANGLE=m
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+CONFIG_WIRELESS_EXT=y
+# CONFIG_MAC80211 is not set
CONFIG_IEEE80211=m
CONFIG_IEEE80211_DEBUG=y
CONFIG_IEEE80211_CRYPT_WEP=m
@@ -440,7 +424,7 @@ CONFIG_IEEE80211_CRYPT_CCMP=m
CONFIG_IEEE80211_CRYPT_TKIP=m
CONFIG_IEEE80211_SOFTMAC=m
CONFIG_IEEE80211_SOFTMAC_DEBUG=y
-CONFIG_WIRELESS_EXT=y
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -453,16 +437,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=m
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
CONFIG_MTD_CONCAT=y
@@ -511,7 +492,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -539,17 +519,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -559,6 +535,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=1
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -578,19 +555,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=2
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -619,6 +593,7 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -667,11 +642,8 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
@@ -687,10 +659,12 @@ CONFIG_ATA=y
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -702,6 +676,7 @@ CONFIG_ATA=y
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
CONFIG_PATA_IT821X=y
+# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
@@ -738,18 +713,14 @@ CONFIG_PATA_SIL680=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -759,15 +730,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -795,10 +758,7 @@ CONFIG_TULIP_MMIO=y
# CONFIG_ULI526X is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -811,58 +771,36 @@ CONFIG_R8169=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-# CONFIG_IPW2100 is not set
-# CONFIG_IPW2200 is not set
-# CONFIG_AIRO is not set
-# CONFIG_HERMES is not set
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+# Wireless LAN
#
-# CONFIG_PRISM54 is not set
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_HOSTAP is not set
-# CONFIG_BCM43XX is not set
-CONFIG_ZD1211RW=m
-# CONFIG_ZD1211RW_DEBUG is not set
-CONFIG_NET_WIRELESS=y
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -872,7 +810,6 @@ CONFIG_NET_WIRELESS=y
# CONFIG_SHAPER is not set
CONFIG_NETCONSOLE=y
CONFIG_NETPOLL=y
-# CONFIG_NETPOLL_RX is not set
# CONFIG_NETPOLL_TRAP is not set
CONFIG_NET_POLL_CONTROLLER=y
@@ -891,6 +828,7 @@ CONFIG_NET_POLL_CONTROLLER=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -910,8 +848,14 @@ CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
CONFIG_INPUT_UINPUT=m
#
@@ -950,6 +894,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -958,15 +903,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -977,11 +917,9 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -1008,14 +946,15 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -1043,16 +982,14 @@ CONFIG_SENSORS_EEPROM=m
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
@@ -1075,6 +1012,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
@@ -1094,20 +1032,27 @@ CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -1116,7 +1061,6 @@ CONFIG_FIRMWARE_EDID=y
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -1127,6 +1071,18 @@ CONFIG_DUMMY_CONSOLE=y
# HID Devices
#
CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
#
# USB support
@@ -1141,7 +1097,7 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -1152,9 +1108,15 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
@@ -1187,43 +1149,10 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -1283,6 +1212,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1293,6 +1223,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1303,10 +1234,6 @@ CONFIG_USB_SERIAL_FTDI_SIO=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1347,24 +1274,37 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
#
-# RTC drivers
+# I2C RTC drivers
#
-# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_DS1307 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+CONFIG_RTC_DRV_RS5C372=y
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
-CONFIG_RTC_DRV_RS5C372=y
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+
+#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
@@ -1378,10 +1318,6 @@ CONFIG_RTC_DRV_RS5C372=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1421,7 +1357,6 @@ CONFIG_DNOTIFY=y
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=m
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y
@@ -1489,6 +1424,7 @@ CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1557,6 +1493,7 @@ CONFIG_NLS_UTF8=m
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1564,6 +1501,7 @@ CONFIG_NLS_UTF8=m
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=m
@@ -1571,13 +1509,16 @@ CONFIG_ZLIB_DEFLATE=m
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
#
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
+# CONFIG_KPROBES is not set
#
# Kernel hacking
@@ -1589,15 +1530,15 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1607,10 +1548,13 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
@@ -1639,8 +1583,11 @@ CONFIG_CRYPTO_SHA1=m
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1655,6 +1602,7 @@ CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
diff --git a/arch/powerpc/configs/lite5200_defconfig b/arch/powerpc/configs/lite5200_defconfig
index 8cbd87ded6b..d12a981398b 100644
--- a/arch/powerpc/configs/lite5200_defconfig
+++ b/arch/powerpc/configs/lite5200_defconfig
@@ -1,9 +1,10 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:18:18 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:26:09 2007
#
# CONFIG_PPC64 is not set
+CONFIG_PPC_PM_NEEDS_RTC_LIB=y
CONFIG_PPC32=y
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
@@ -34,9 +35,9 @@ CONFIG_CLASSIC32=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
@@ -45,6 +46,7 @@ CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -63,14 +65,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -83,14 +88,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -131,11 +141,17 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
# CONFIG_PPC_CHRP is not set
CONFIG_PPC_MPC52xx=y
+CONFIG_PPC_MPC5200=y
+CONFIG_PPC_MPC5200_BUGFIX=y
# CONFIG_PPC_EFIKA is not set
CONFIG_PPC_LITE5200=y
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_PPC_MPC106 is not set
@@ -144,8 +160,7 @@ CONFIG_PPC_LITE5200=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-# CONFIG_MPIC is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -174,6 +189,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_PM=y
@@ -182,28 +198,27 @@ CONFIG_PM=y
# CONFIG_PM_SYSFS_DEPRECATED is not set
# CONFIG_SOFTWARE_SUSPEND is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -228,13 +243,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -268,20 +283,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -307,7 +310,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -320,16 +332,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -340,6 +349,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -358,19 +368,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -399,6 +406,7 @@ CONFIG_SCSI=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -447,11 +455,8 @@ CONFIG_SCSI=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
@@ -467,10 +472,12 @@ CONFIG_ATA=y
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -482,9 +489,11 @@ CONFIG_ATA=y
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
+CONFIG_PATA_MPC52xx=y
# CONFIG_PATA_MPIIX is not set
# CONFIG_PATA_OLDPIIX is not set
# CONFIG_PATA_NETCELL is not set
@@ -519,18 +528,14 @@ CONFIG_ATA=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -540,24 +545,13 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
#
-# PHY device support
-#
-
-#
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -569,33 +563,27 @@ CONFIG_NETDEVICES=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -657,15 +645,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -676,10 +659,7 @@ CONFIG_LEGACY_PTY_COUNT=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -692,30 +672,32 @@ CONFIG_LEGACY_PTY_COUNT=256
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -738,10 +720,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -769,6 +747,7 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
# Real Time Clock
#
+CONFIG_RTC_LIB=y
# CONFIG_RTC_CLASS is not set
#
@@ -785,10 +764,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -888,16 +863,20 @@ CONFIG_MSDOS_PARTITION=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
#
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
# CONFIG_CRC32 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -914,15 +893,15 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -932,10 +911,13 @@ CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 15366f0e489..eb3d9ad655e 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:19:02 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:27:35 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -39,6 +39,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_OF_PLATFORM_PCI is not set
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
@@ -59,6 +60,7 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -66,10 +68,11 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
# CONFIG_CPUSETS is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
@@ -83,14 +86,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -131,29 +139,34 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_PPC_PSERIES is not set
# CONFIG_PPC_ISERIES is not set
# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
# CONFIG_PPC_PMAC is not set
CONFIG_PPC_MAPLE=y
# CONFIG_PPC_PASEMI is not set
+# CONFIG_PPC_CELLEB is not set
+# CONFIG_PPC_PS3 is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_PPC_PS3 is not set
+# CONFIG_PQ2ADS is not set
CONFIG_PPC_NATIVE=y
CONFIG_UDBG_RTAS_CONSOLE=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
CONFIG_U3_DART=y
CONFIG_PPC_RTAS=y
# CONFIG_RTAS_ERROR_LOGGING is not set
CONFIG_RTAS_PROC=y
# CONFIG_RTAS_FLASH is not set
-# CONFIG_MMIO_NVRAM is not set
+CONFIG_MMIO_NVRAM=y
CONFIG_MPIC_U3_HT_IRQS=y
# CONFIG_PPC_MPC106 is not set
CONFIG_PPC_970_NAP=y
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -189,34 +202,34 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_PPC_HAS_HASH_64K is not set
# CONFIG_PPC_64K_PAGES is not set
# CONFIG_SCHED_SMT is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
CONFIG_KERNEL_START=0xc000000000000000
@@ -228,13 +241,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -268,20 +281,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -307,7 +308,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -320,16 +330,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -340,6 +347,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -358,19 +366,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -384,6 +389,7 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -391,12 +397,12 @@ CONFIG_IDE_TASK_IOCTL=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
@@ -411,6 +417,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -421,10 +428,10 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -433,10 +440,6 @@ CONFIG_IDEDMA_AUTO=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -452,18 +455,14 @@ CONFIG_IDEDMA_AUTO=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -473,15 +472,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -518,10 +509,8 @@ CONFIG_AMD8111_ETH=y
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
@@ -539,29 +528,33 @@ CONFIG_E1000=y
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_PASEMI_MAC is not set
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=y
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -587,6 +580,7 @@ CONFIG_TIGON3=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -606,6 +600,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1200
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -640,6 +635,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -650,15 +646,10 @@ CONFIG_HVC_RTAS=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -670,11 +661,9 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -700,14 +689,15 @@ CONFIG_I2C_AMD8111=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -734,28 +724,30 @@ CONFIG_I2C_AMD8111=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -764,7 +756,6 @@ CONFIG_FIRMWARE_EDID=y
#
# CONFIG_VGA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -775,6 +766,15 @@ CONFIG_DUMMY_CONSOLE=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
#
# USB support
@@ -789,9 +789,8 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -801,9 +800,12 @@ CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_SPLIT_ISO=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_SL811_HCD is not set
@@ -824,39 +826,9 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-CONFIG_USB_PEGASUS=y
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -929,6 +901,7 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -939,6 +912,7 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -949,10 +923,6 @@ CONFIG_USB_EZUSB=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -996,10 +966,6 @@ CONFIG_USB_EZUSB=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1090,6 +1056,7 @@ CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1119,6 +1086,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1168,6 +1136,7 @@ CONFIG_NLS_UTF8=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1175,11 +1144,14 @@ CONFIG_NLS_UTF8=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1197,16 +1169,16 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
CONFIG_DEBUG_SLAB=y
# CONFIG_DEBUG_SLAB_LEAK is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1216,8 +1188,10 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
@@ -1252,8 +1226,11 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1267,6 +1244,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
index fdf09eabe6e..174a290ee7a 100644
--- a/arch/powerpc/configs/mpc7448_hpc2_defconfig
+++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:20:53 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:54 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_CLASSIC32=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_ALTIVEC is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -63,14 +64,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -84,14 +88,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -126,8 +135,18 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
CONFIG_EMBEDDED6xx=y
# CONFIG_APUS is not set
# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_LINKSTATION is not set
+CONFIG_MPC7448HPC2=y
+# CONFIG_PPC_HOLLY is not set
+# CONFIG_PPC_PRPMC2800 is not set
+CONFIG_TSI108_BRIDGE=y
+CONFIG_MPIC=y
+CONFIG_MPIC_WEIRD=y
+# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_PPC_MPC106 is not set
@@ -136,36 +155,7 @@ CONFIG_EMBEDDED6xx=y
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
# CONFIG_TAU is not set
-# CONFIG_KATANA is not set
-# CONFIG_WILLOW is not set
-# CONFIG_CPCI690 is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_CHESTNUT is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_HDPU is not set
-# CONFIG_EV64260 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_LINKSTATION is not set
-CONFIG_MPC7448HPC2=y
-# CONFIG_RADSTONE_PPC7D is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-# CONFIG_EST8260 is not set
-# CONFIG_SBC82xx is not set
-# CONFIG_SBS8260 is not set
-# CONFIG_RPX8260 is not set
-# CONFIG_TQM8260 is not set
-# CONFIG_ADS8272 is not set
-# CONFIG_PQ2FADS is not set
-# CONFIG_EV64360 is not set
-CONFIG_TSI108_BRIDGE=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -193,31 +183,30 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-CONFIG_MPIC_WEIRD=y
-# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -242,13 +231,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -282,20 +271,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -321,7 +298,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -339,10 +325,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -353,6 +335,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -371,19 +354,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=131072
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -460,11 +440,8 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
@@ -480,10 +457,12 @@ CONFIG_SATA_MV=y
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -495,6 +474,7 @@ CONFIG_SATA_MV=y
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
@@ -532,18 +512,14 @@ CONFIG_SATA_MV=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -553,15 +529,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -615,10 +583,8 @@ CONFIG_8139TOO=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -635,29 +601,22 @@ CONFIG_8139TOO=y
# CONFIG_BNX2 is not set
CONFIG_TSI108_ETH=y
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -684,6 +643,7 @@ CONFIG_TSI108_ETH=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -700,6 +660,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -732,6 +693,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -740,16 +702,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -760,10 +717,7 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -776,35 +730,41 @@ CONFIG_GEN_RTC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -815,6 +775,7 @@ CONFIG_FIRMWARE_EDID=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -832,10 +793,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -879,10 +836,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -967,6 +920,7 @@ CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -996,6 +950,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1006,6 +961,7 @@ CONFIG_MSDOS_PARTITION=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1013,10 +969,13 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1033,7 +992,6 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
diff --git a/arch/powerpc/configs/mpc8272_ads_defconfig b/arch/powerpc/configs/mpc8272_ads_defconfig
index 2af45025082..4a429294e4d 100644
--- a/arch/powerpc/configs/mpc8272_ads_defconfig
+++ b/arch/powerpc/configs/mpc8272_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc5
-# Fri Jul 14 20:36:35 2006
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:55 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -21,25 +22,31 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
-# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
CONFIG_PPC_82xx=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# Code maturity level options
@@ -55,14 +62,21 @@ CONFIG_LOCALVERSION="powerpc8272"
CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_EXTRA_PASS=y
@@ -72,12 +86,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -87,6 +108,7 @@ CONFIG_BASE_SMALL=0
#
# Block layer
#
+CONFIG_BLOCK=y
# CONFIG_LBD is not set
# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_LSF is not set
@@ -103,17 +125,29 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PQ2ADS=y
-CONFIG_8260=y
-CONFIG_8272=y
-CONFIG_CPM2=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_EMBEDDEDBOOT=y
#
# Platform support
#
-CONFIG_ADS8272=y
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_MPC82xx_ADS=y
+CONFIG_PQ2ADS=y
+CONFIG_8260=y
+CONFIG_8272=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_CPM2=y
#
# Kernel options
@@ -121,6 +155,7 @@ CONFIG_ADS8272=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_PREEMPT_NONE=y
@@ -128,26 +163,30 @@ CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT is not set
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
-# CONFIG_PC_KEYBOARD is not set
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
-# CONFIG_SOFTWARE_SUSPEND is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
CONFIG_FSL_SOC=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -155,10 +194,6 @@ CONFIG_FSL_SOC=y
# CONFIG_PCCARD is not set
#
-# PCI Hotplug Support
-#
-
-#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
@@ -180,10 +215,11 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -201,15 +237,15 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_IP_VS is not set
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
@@ -219,7 +255,12 @@ CONFIG_IPV6=y
# CONFIG_INET6_IPCOMP is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+CONFIG_IPV6_SIT=y
# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
@@ -227,13 +268,16 @@ CONFIG_NETFILTER=y
# Core Netfilter Configuration
#
# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
# CONFIG_NETFILTER_XTABLES is not set
#
# IP: Netfilter Configuration
#
-# CONFIG_IP_NF_CONNTRACK is not set
# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
# CONFIG_BRIDGE is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
@@ -253,7 +297,14 @@ CONFIG_NETFILTER=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -266,15 +317,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -285,6 +334,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -295,14 +345,15 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
-# ATA/ATAPI/MFM/RLL support
+# Misc devices
#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
CONFIG_BLK_DEV_IDE=y
#
@@ -314,14 +365,15 @@ CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
#
# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
# CONFIG_IDE_ARM is not set
# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
#
@@ -329,29 +381,14 @@ CONFIG_BLK_DEV_IDEDISK=y
#
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -361,10 +398,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=y
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -375,6 +408,9 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -385,27 +421,14 @@ CONFIG_MII=y
CONFIG_FS_ENET=y
# CONFIG_FS_ENET_HAS_SCC is not set
CONFIG_FS_ENET_HAS_FCC=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
CONFIG_PPP=y
# CONFIG_PPP_FILTER is not set
@@ -414,6 +437,7 @@ CONFIG_PPP_SYNC_TTY=y
CONFIG_PPP_DEFLATE=y
# CONFIG_PPP_BSDCOMP is not set
# CONFIG_SLIP is not set
+CONFIG_SLHC=y
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
@@ -431,6 +455,8 @@ CONFIG_PPP_DEFLATE=y
# Input device support
#
CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -453,11 +479,19 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -485,6 +519,7 @@ CONFIG_SERIO_LIBPS2=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
@@ -503,29 +538,16 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_AGP is not set
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -538,32 +560,32 @@ CONFIG_LEGACY_PTY_COUNT=256
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
-# Misc devices
+# Multifunction device drivers
#
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-CONFIG_VIDEO_V4L2=y
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
+# CONFIG_FB_IBM_GXT4500 is not set
#
# Sound
@@ -571,6 +593,12 @@ CONFIG_VIDEO_V4L2=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
@@ -586,6 +614,7 @@ CONFIG_VIDEO_V4L2=y
#
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG_FILES is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
# CONFIG_USB_GADGET_NET2280 is not set
# CONFIG_USB_GADGET_PXA2XX is not set
# CONFIG_USB_GADGET_GOKU is not set
@@ -594,10 +623,6 @@ CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_AT91 is not set
# CONFIG_USB_GADGET_DUMMY_HCD is not set
# CONFIG_USB_GADGET_DUALSPEED is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -626,6 +651,19 @@ CONFIG_USB_GADGET=y
#
#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -645,9 +683,12 @@ CONFIG_XFS_FS=y
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_SECURITY is not set
# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
# CONFIG_QUOTA is not set
CONFIG_DNOTIFY=y
# CONFIG_AUTOFS_FS is not set
@@ -672,8 +713,10 @@ CONFIG_AUTOFS4_FS=y
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
@@ -694,6 +737,7 @@ CONFIG_CRAMFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
@@ -727,6 +771,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -771,37 +816,55 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=y
+# CONFIG_UCC_SLOW is not set
#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Kernel hacking
#
# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_FS is not set
# CONFIG_DEBUG_VM is not set
-# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_KGDB_CONSOLE is not set
CONFIG_BDI_SWITCH=y
@@ -818,6 +881,9 @@ CONFIG_BDI_SWITCH=y
# Cryptographic options
#
CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
# CONFIG_CRYPTO_HMAC is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_MD4 is not set
@@ -827,7 +893,12 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=y
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -841,7 +912,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
#
# Hardware crypto devices
diff --git a/arch/powerpc/configs/mpc8313_rdb_defconfig b/arch/powerpc/configs/mpc8313_rdb_defconfig
index f87523716c4..b7d3dffc981 100644
--- a/arch/powerpc/configs/mpc8313_rdb_defconfig
+++ b/arch/powerpc/configs/mpc8313_rdb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Wed Feb 7 22:08:04 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:55 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -63,14 +64,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -83,14 +87,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -122,19 +131,33 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
CONFIG_MPC8313_RDB=y
# CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
# CONFIG_MPC834x_ITX is not set
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
CONFIG_PPC_MPC831x=y
# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -162,33 +185,34 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -213,13 +237,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -253,20 +277,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -292,7 +304,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -305,16 +326,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -357,7 +375,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -387,17 +404,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -407,6 +420,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -426,19 +440,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -467,6 +478,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -514,10 +526,6 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -545,18 +553,14 @@ CONFIG_MD_RAID1=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -566,15 +570,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -624,10 +620,8 @@ CONFIG_E100=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -645,29 +639,32 @@ CONFIG_E100=y
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -694,6 +691,7 @@ CONFIG_GFAR_NAPI=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -710,6 +708,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -742,6 +741,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -750,10 +750,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -776,7 +772,6 @@ CONFIG_83xx_WDT=y
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -787,11 +782,9 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -818,14 +811,15 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -859,21 +853,21 @@ CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
@@ -897,6 +891,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
@@ -916,23 +911,30 @@ CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
-# Multimedia devices
+# Multifunction device drivers
#
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_MFD_SM501 is not set
#
-# Digital Video Broadcasting Devices
+# Multimedia devices
#
-# CONFIG_DVB is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -943,6 +945,18 @@ CONFIG_FIRMWARE_EDID=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
#
# USB support
@@ -957,7 +971,7 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -968,9 +982,15 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_SL811_HCD is not set
@@ -1002,43 +1022,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -1060,6 +1047,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1070,6 +1058,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1082,6 +1071,7 @@ CONFIG_USB_MON=y
CONFIG_USB_GADGET=y
# CONFIG_USB_GADGET_DEBUG_FILES is not set
CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_FSL_USB2 is not set
CONFIG_USB_GADGET_NET2280=y
CONFIG_USB_NET2280=y
# CONFIG_USB_GADGET_PXA2XX is not set
@@ -1098,10 +1088,6 @@ CONFIG_USB_ETH_RNDIS=y
# CONFIG_USB_FILE_STORAGE is not set
# CONFIG_USB_G_SERIAL is not set
# CONFIG_USB_MIDI_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1142,26 +1128,39 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
#
-# RTC drivers
+# I2C RTC drivers
#
-# CONFIG_RTC_DRV_X1205 is not set
CONFIG_RTC_DRV_DS1307=y
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
+
+#
+# SPI RTC drivers
+#
# CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+
+#
# DMA Engine support
#
CONFIG_DMA_ENGINE=y
@@ -1177,10 +1176,6 @@ CONFIG_NET_DMA=y
CONFIG_INTEL_IOATDMA=y
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1269,6 +1264,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1298,6 +1294,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1308,6 +1305,7 @@ CONFIG_MSDOS_PARTITION=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1315,10 +1313,13 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1335,15 +1336,15 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1353,12 +1354,13 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
@@ -1387,8 +1389,11 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_ECB is not set
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1402,6 +1407,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
diff --git a/arch/powerpc/configs/mpc832x_mds_defconfig b/arch/powerpc/configs/mpc832x_mds_defconfig
index 83192c0dc5b..75ce78139a1 100644
--- a/arch/powerpc/configs/mpc832x_mds_defconfig
+++ b/arch/powerpc/configs/mpc832x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc5
-# Mon Apr 9 16:09:16 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:55 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -70,6 +71,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -85,14 +87,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -124,12 +131,15 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_QUICC_ENGINE=y
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
# CONFIG_MPC8313_RDB is not set
CONFIG_MPC832x_MDS=y
# CONFIG_MPC832x_RDB is not set
@@ -138,6 +148,17 @@ CONFIG_MPC832x_MDS=y
# CONFIG_MPC836x_MDS is not set
CONFIG_PPC_MPC832x=y
# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -171,6 +192,8 @@ CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
@@ -178,22 +201,19 @@ CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -218,7 +238,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -259,20 +278,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -298,7 +305,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -316,10 +332,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -355,12 +367,10 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -389,6 +399,7 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -436,10 +447,6 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -458,18 +465,14 @@ CONFIG_SCSI_PROC_FS=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -479,15 +482,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -501,7 +496,6 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -520,10 +514,7 @@ CONFIG_MII=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -535,6 +526,7 @@ CONFIG_MII=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_GIANFAR is not set
@@ -542,33 +534,24 @@ CONFIG_UCC_GETH=y
# CONFIG_UGETH_NAPI is not set
# CONFIG_UGETH_MAGIC_PACKET is not set
# CONFIG_UGETH_FILTERING is not set
-# CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -595,6 +578,7 @@ CONFIG_UCC_GETH=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -611,6 +595,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -652,10 +637,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -674,7 +655,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -685,11 +665,9 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -714,9 +692,9 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -724,7 +702,6 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -752,13 +729,10 @@ CONFIG_I2C_MPC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -785,6 +759,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
@@ -812,16 +787,19 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -852,10 +830,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -899,14 +873,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -994,6 +960,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1019,6 +986,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1039,11 +1007,13 @@ CONFIG_UCC=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1060,7 +1030,6 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1093,6 +1062,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc832x_rdb_defconfig b/arch/powerpc/configs/mpc832x_rdb_defconfig
index 4a4da875fa4..6a83b66dd99 100644
--- a/arch/powerpc/configs/mpc832x_rdb_defconfig
+++ b/arch/powerpc/configs/mpc832x_rdb_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc5
-# Mon Apr 9 16:12:43 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:56 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -70,6 +71,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -85,14 +87,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -124,12 +131,15 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_QUICC_ENGINE=y
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
# CONFIG_MPC8313_RDB is not set
# CONFIG_MPC832x_MDS is not set
CONFIG_MPC832x_RDB=y
@@ -138,6 +148,17 @@ CONFIG_MPC832x_RDB=y
# CONFIG_MPC836x_MDS is not set
CONFIG_PPC_MPC832x=y
# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -171,6 +192,8 @@ CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
@@ -178,22 +201,19 @@ CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -218,7 +238,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -259,20 +278,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -298,7 +305,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -316,10 +332,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -356,12 +368,10 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -390,6 +400,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -437,10 +448,6 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -459,18 +466,14 @@ CONFIG_BLK_DEV_SD=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -480,15 +483,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -502,7 +497,6 @@ CONFIG_PHYLIB=y
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
-CONFIG_ICPLUS_PHY=y
# CONFIG_FIXED_PHY is not set
#
@@ -521,10 +515,7 @@ CONFIG_MII=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
@@ -538,6 +529,7 @@ CONFIG_E1000=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_GIANFAR is not set
@@ -545,33 +537,34 @@ CONFIG_UCC_GETH=y
CONFIG_UGETH_NAPI=y
# CONFIG_UGETH_MAGIC_PACKET is not set
# CONFIG_UGETH_FILTERING is not set
-# CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -598,6 +591,7 @@ CONFIG_UGETH_NAPI=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -614,6 +608,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -655,10 +650,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -682,7 +673,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -693,11 +683,9 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -722,17 +710,17 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -760,13 +748,10 @@ CONFIG_I2C_MPC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -793,6 +778,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
@@ -820,17 +806,20 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
# CONFIG_USB_DABUSB is not set
#
# Graphics support
#
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -846,6 +835,17 @@ CONFIG_HID=y
# CONFIG_HID_DEBUG is not set
#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -858,6 +858,7 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -908,44 +909,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
-
-#
-# USB HID Boot Protocol drivers
-#
-# CONFIG_USB_KBD is not set
-# CONFIG_USB_MOUSE is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-# CONFIG_USB_GTCO is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -989,10 +956,6 @@ CONFIG_USB_MON=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1036,14 +999,6 @@ CONFIG_USB_MON=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1134,6 +1089,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1164,6 +1120,7 @@ CONFIG_LDM_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1223,11 +1180,13 @@ CONFIG_UCC=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1244,7 +1203,6 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1277,6 +1235,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig
index 23d8964846e..85470b8cae0 100644
--- a/arch/powerpc/configs/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/mpc834x_itx_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Wed Feb 7 13:12:18 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:56 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -63,14 +64,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -83,14 +87,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -122,18 +131,33 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPC8313_RDB is not set
# CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
CONFIG_MPC834x_ITX=y
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
CONFIG_MPC834x=y
# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -161,32 +185,33 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -211,13 +236,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -251,20 +276,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -290,7 +303,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -308,10 +330,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -354,7 +372,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -384,17 +401,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -404,6 +417,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -423,19 +437,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_IDE_MAX_HWIFS=4
# CONFIG_BLK_DEV_IDE is not set
@@ -468,6 +479,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -516,10 +528,6 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
@@ -537,10 +545,12 @@ CONFIG_SATA_SIL=y
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -552,6 +562,7 @@ CONFIG_SATA_SIL=y
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
@@ -598,18 +609,14 @@ CONFIG_MD_RAID1=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -619,15 +626,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -647,10 +646,7 @@ CONFIG_CICADA_PHY=y
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -662,34 +658,38 @@ CONFIG_CICADA_PHY=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -745,6 +745,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -753,10 +754,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -779,7 +776,6 @@ CONFIG_83xx_WDT=y
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -790,11 +786,9 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -821,14 +815,15 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -861,36 +856,40 @@ CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -910,7 +909,7 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
@@ -921,6 +920,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
# CONFIG_USB_UHCI_HCD is not set
@@ -953,28 +953,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-
-#
-# USB HID Boot Protocol drivers
-#
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -996,6 +978,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1006,6 +989,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1016,10 +1000,6 @@ CONFIG_USB_MON=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1060,26 +1040,39 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
#
-# RTC drivers
+# I2C RTC drivers
#
-# CONFIG_RTC_DRV_X1205 is not set
CONFIG_RTC_DRV_DS1307=y
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
+
+#
+# SPI RTC drivers
+#
# CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+
+#
# DMA Engine support
#
CONFIG_DMA_ENGINE=y
@@ -1095,10 +1088,6 @@ CONFIG_NET_DMA=y
CONFIG_INTEL_IOATDMA=y
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1190,6 +1179,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1219,6 +1209,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1268,6 +1259,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1275,10 +1267,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1295,10 +1290,8 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
@@ -1327,8 +1320,11 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_ECB is not set
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1342,6 +1338,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
diff --git a/arch/powerpc/configs/mpc834x_itxgp_defconfig b/arch/powerpc/configs/mpc834x_itxgp_defconfig
index 4aa666c9cb9..704ee8b285b 100644
--- a/arch/powerpc/configs/mpc834x_itxgp_defconfig
+++ b/arch/powerpc/configs/mpc834x_itxgp_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Fri Feb 9 13:28:19 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:56 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -63,14 +64,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -83,14 +87,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -122,18 +131,33 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPC8313_RDB is not set
# CONFIG_MPC832x_MDS is not set
-# CONFIG_MPC834x_SYS is not set
+# CONFIG_MPC832x_RDB is not set
+# CONFIG_MPC834x_MDS is not set
CONFIG_MPC834x_ITX=y
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
CONFIG_MPC834x=y
# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -161,32 +185,33 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -211,13 +236,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -251,20 +276,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -290,7 +303,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -308,10 +330,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
@@ -354,7 +372,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -384,17 +401,13 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-
-#
-# NAND Flash Device Drivers
-#
# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_NAND_CAFE is not set
+# CONFIG_MTD_ONENAND is not set
#
-# OneNAND Flash Device Drivers
+# UBI - Unsorted block images
#
-# CONFIG_MTD_ONENAND is not set
+# CONFIG_MTD_UBI is not set
#
# Parallel port support
@@ -404,6 +417,7 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -422,19 +436,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -463,6 +474,7 @@ CONFIG_CHR_DEV_SG=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -510,10 +522,6 @@ CONFIG_SCSI_SPI_ATTRS=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -532,18 +540,14 @@ CONFIG_SCSI_SPI_ATTRS=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -553,15 +557,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -581,10 +577,7 @@ CONFIG_CICADA_PHY=y
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -596,34 +589,28 @@ CONFIG_CICADA_PHY=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -679,6 +666,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -687,10 +675,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -708,7 +692,6 @@ CONFIG_83xx_WDT=y
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -719,11 +702,9 @@ CONFIG_HW_RANDOM=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -750,6 +731,7 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -757,7 +739,6 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -790,35 +771,39 @@ CONFIG_SPI_MPC83xx=y
#
# SPI Protocol Masters
#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -841,10 +826,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -885,26 +866,39 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+# CONFIG_RTC_DRV_TEST is not set
#
-# RTC drivers
+# I2C RTC drivers
#
-# CONFIG_RTC_DRV_X1205 is not set
CONFIG_RTC_DRV_DS1307=y
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
# CONFIG_RTC_DRV_PCF8563 is not set
# CONFIG_RTC_DRV_PCF8583 is not set
+
+#
+# SPI RTC drivers
+#
# CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_MAX6902 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+
+#
# DMA Engine support
#
CONFIG_DMA_ENGINE=y
@@ -920,10 +914,6 @@ CONFIG_NET_DMA=y
CONFIG_INTEL_IOATDMA=y
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1015,6 +1005,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1044,6 +1035,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1093,6 +1085,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1100,10 +1093,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1120,10 +1116,8 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
@@ -1152,8 +1146,11 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_ECB is not set
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1167,6 +1164,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig
index 2e3f8efb6ab..c28b3ee3cb1 100644
--- a/arch/powerpc/configs/mpc834x_mds_defconfig
+++ b/arch/powerpc/configs/mpc834x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Thu Feb 8 01:00:48 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:57 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -63,14 +64,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -83,14 +87,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -122,19 +131,33 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_PPC_GEN550=y
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
# CONFIG_MPC8313_RDB is not set
# CONFIG_MPC832x_MDS is not set
+# CONFIG_MPC832x_RDB is not set
CONFIG_MPC834x_MDS=y
# CONFIG_MPC834x_ITX is not set
-# CONFIG_MPC8360E_PB is not set
+# CONFIG_MPC836x_MDS is not set
CONFIG_MPC834x=y
# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -162,32 +185,33 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -212,13 +236,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -252,20 +276,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -291,7 +303,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -309,10 +330,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -323,6 +340,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -341,19 +359,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -362,10 +377,6 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -381,18 +392,14 @@ CONFIG_BLK_DEV_INITRD=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -402,15 +409,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -460,10 +459,8 @@ CONFIG_E100=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -481,29 +478,22 @@ CONFIG_E100=y
CONFIG_GIANFAR=y
# CONFIG_GFAR_NAPI is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -529,6 +519,7 @@ CONFIG_GIANFAR=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -545,6 +536,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -577,6 +569,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -585,10 +578,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -607,7 +596,6 @@ CONFIG_83xx_WDT=y
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -618,11 +606,9 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -649,6 +635,7 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -656,7 +643,6 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -684,16 +670,14 @@ CONFIG_I2C_MPC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
@@ -716,6 +700,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
@@ -735,22 +720,29 @@ CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -761,6 +753,7 @@ CONFIG_FIRMWARE_EDID=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -778,10 +771,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -825,10 +814,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -916,6 +901,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -941,6 +927,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -951,6 +938,7 @@ CONFIG_PARTITION_ADVANCED=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -958,10 +946,13 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -978,10 +969,8 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
-# CONFIG_SERIAL_TEXT_DEBUG is not set
# CONFIG_PPC_EARLY_DEBUG is not set
#
@@ -1010,8 +999,11 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_SERPENT is not set
@@ -1025,6 +1017,7 @@ CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
diff --git a/arch/powerpc/configs/mpc836x_mds_defconfig b/arch/powerpc/configs/mpc836x_mds_defconfig
index 921a151dc77..bcbbc167f90 100644
--- a/arch/powerpc/configs/mpc836x_mds_defconfig
+++ b/arch/powerpc/configs/mpc836x_mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc5
-# Mon Apr 9 16:14:05 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:57 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -70,6 +71,7 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -85,14 +87,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -124,12 +131,15 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_QUICC_ENGINE=y
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
# CONFIG_MPC8313_RDB is not set
# CONFIG_MPC832x_MDS is not set
# CONFIG_MPC832x_RDB is not set
@@ -138,6 +148,17 @@ CONFIG_QUICC_ENGINE=y
CONFIG_MPC836x_MDS=y
CONFIG_PPC_MPC836x=y
# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_QUICC_ENGINE=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -170,6 +191,8 @@ CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
@@ -177,22 +200,19 @@ CONFIG_ISA_DMA_API=y
#
CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -217,7 +237,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -258,20 +277,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -297,7 +304,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -315,10 +331,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -354,12 +366,10 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -388,6 +398,7 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -435,10 +446,6 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -457,18 +464,14 @@ CONFIG_SCSI_PROC_FS=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -478,15 +481,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -500,7 +495,6 @@ CONFIG_MARVELL_PHY=y
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
# CONFIG_FIXED_PHY is not set
#
@@ -519,10 +513,7 @@ CONFIG_MII=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -534,6 +525,7 @@ CONFIG_MII=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
# CONFIG_GIANFAR is not set
@@ -541,33 +533,24 @@ CONFIG_UCC_GETH=y
# CONFIG_UGETH_NAPI is not set
# CONFIG_UGETH_MAGIC_PACKET is not set
# CONFIG_UGETH_FILTERING is not set
-# CONFIG_UGETH_TX_ON_DEMOND is not set
+# CONFIG_UGETH_TX_ON_DEMAND is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -594,6 +577,7 @@ CONFIG_UCC_GETH=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -610,6 +594,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -651,10 +636,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -673,7 +654,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -684,11 +664,9 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -713,9 +691,9 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PASEMI is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
@@ -723,7 +701,6 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -751,13 +728,10 @@ CONFIG_I2C_MPC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
@@ -784,6 +758,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SIS5595 is not set
@@ -811,16 +786,19 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -851,10 +829,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -898,14 +872,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -993,6 +959,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -1018,6 +985,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1038,11 +1006,13 @@ CONFIG_UCC=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1059,7 +1029,6 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
@@ -1092,6 +1061,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig
index 17120c47230..faedcf8d64a 100644
--- a/arch/powerpc/configs/mpc8540_ads_defconfig
+++ b/arch/powerpc/configs/mpc8540_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:25:24 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:58 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_83xx is not set
CONFIG_PPC_85xx=y
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_85xx=y
CONFIG_E500=y
@@ -46,6 +46,7 @@ CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -63,14 +64,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -85,14 +89,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -119,17 +128,33 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
CONFIG_MPC8540_ADS=y
# CONFIG_MPC8560_ADS is not set
# CONFIG_MPC85xx_CDS is not set
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC8544_DS is not set
CONFIG_MPC8540=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPC85xx=y
CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -158,21 +183,25 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_FSL_SOC=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -180,10 +209,6 @@ CONFIG_FSL_SOC=y
# CONFIG_PCCARD is not set
#
-# PCI Hotplug Support
-#
-
-#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
@@ -205,13 +230,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -245,20 +270,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -284,7 +297,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -297,16 +319,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -317,6 +336,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -330,18 +350,13 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -350,35 +365,13 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -388,10 +381,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -412,29 +401,16 @@ CONFIG_PHYLIB=y
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -458,6 +434,7 @@ CONFIG_GFAR_NAPI=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -474,6 +451,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -497,6 +475,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
#
# Non-8250 serial port support
@@ -504,6 +483,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -512,16 +492,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -529,10 +504,6 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -545,35 +516,41 @@ CONFIG_GEN_RTC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -584,6 +561,7 @@ CONFIG_FIRMWARE_EDID=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -600,10 +578,6 @@ CONFIG_HID=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -646,10 +620,6 @@ CONFIG_HID=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -734,6 +704,7 @@ CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -759,6 +730,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -769,6 +741,7 @@ CONFIG_PARTITION_ADVANCED=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -776,10 +749,13 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -796,15 +772,15 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -813,7 +789,10 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
diff --git a/arch/powerpc/configs/mpc8544_ds_defconfig b/arch/powerpc/configs/mpc8544_ds_defconfig
index b563513cc96..c40a25a79cb 100644
--- a/arch/powerpc/configs/mpc8544_ds_defconfig
+++ b/arch/powerpc/configs/mpc8544_ds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc3
-# Mon Mar 19 17:18:49 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:58 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -46,6 +46,7 @@ CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
# CONFIG_PHYS_64BIT is not set
# CONFIG_SPE is not set
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -73,6 +74,7 @@ CONFIG_AUDIT=y
# CONFIG_AUDITSYSCALL is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
@@ -90,14 +92,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -129,19 +136,32 @@ CONFIG_IOSCHED_CFQ=y
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
# CONFIG_MPC8540_ADS is not set
# CONFIG_MPC8560_ADS is not set
# CONFIG_MPC85xx_CDS is not set
# CONFIG_MPC85xx_MDS is not set
CONFIG_MPC8544_DS=y
CONFIG_MPC85xx=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -176,28 +196,26 @@ CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="root=/dev/sda3 rw console=ttyS0,115200"
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
CONFIG_ZONE_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_FSL_SOC=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
#
-# PCI Hotplug Support
-#
-
-#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
@@ -219,7 +237,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -270,25 +287,13 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
CONFIG_IP_SCTP=m
# CONFIG_SCTP_DBG_MSG is not set
# CONFIG_SCTP_DBG_OBJCNT is not set
# CONFIG_SCTP_HMAC_NONE is not set
# CONFIG_SCTP_HMAC_SHA1 is not set
CONFIG_SCTP_HMAC_MD5=y
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -314,10 +319,19 @@ CONFIG_SCTP_HMAC_MD5=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_AF_RXRPC is not set
CONFIG_FIB_RULES=y
#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+
+#
# Device Drivers
#
@@ -334,10 +348,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -368,10 +378,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
#
# Misc devices
#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -400,6 +407,7 @@ CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
CONFIG_SCSI_LOGGING=y
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -415,10 +423,6 @@ CONFIG_SCSI_LOGGING=y
#
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_PATA_PLATFORM is not set
@@ -427,25 +431,7 @@ CONFIG_ATA=y
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -455,10 +441,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -479,29 +461,16 @@ CONFIG_VITESSE_PHY=y
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -525,6 +494,7 @@ CONFIG_GFAR_NAPI=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -541,6 +511,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -571,6 +542,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
#
# Non-8250 serial port support
@@ -587,16 +559,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
CONFIG_GEN_RTC=y
CONFIG_GEN_RTC_X=y
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -604,10 +571,6 @@ CONFIG_GEN_RTC_X=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -620,12 +583,7 @@ CONFIG_GEN_RTC_X=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
#
# Multifunction device drivers
@@ -636,13 +594,9 @@ CONFIG_GEN_RTC_X=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-CONFIG_DVB=y
CONFIG_DVB_CORE=m
# CONFIG_DVB_CORE_ATTACH is not set
+CONFIG_DVB_CAPTURE_DRIVERS=y
#
# Supported DVB Frontends
@@ -676,11 +630,18 @@ CONFIG_DVB_CORE=m
#
# Miscellaneous devices
#
+CONFIG_DAB=y
#
# Graphics support
#
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -716,10 +677,6 @@ CONFIG_HID=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -759,17 +716,29 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
#
-# RTC drivers
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
#
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_TEST is not set
# CONFIG_RTC_DRV_V3020 is not set
#
+# on-CPU RTC drivers
+#
+
+#
# DMA Engine support
#
# CONFIG_DMA_ENGINE is not set
@@ -783,14 +752,6 @@ CONFIG_RTC_INTF_DEV=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -890,6 +851,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -919,6 +881,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -968,6 +931,7 @@ CONFIG_NLS_UTF8=m
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -975,12 +939,14 @@ CONFIG_NLS_UTF8=m
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -998,7 +964,6 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
@@ -1020,6 +985,7 @@ CONFIG_FORCED_INLINING=y
# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
@@ -1054,6 +1020,7 @@ CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc8560_ads_defconfig b/arch/powerpc/configs/mpc8560_ads_defconfig
index ecaa267a853..a30bc6f6211 100644
--- a/arch/powerpc/configs/mpc8560_ads_defconfig
+++ b/arch/powerpc/configs/mpc8560_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:25:53 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:58 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -20,7 +20,7 @@ CONFIG_GENERIC_NVRAM=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_PPC_OF=y
-# CONFIG_PPC_UDBG_16550 is not set
+CONFIG_PPC_UDBG_16550=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
@@ -34,9 +34,9 @@ CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_83xx is not set
CONFIG_PPC_85xx=y
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_85xx=y
CONFIG_E500=y
@@ -46,6 +46,7 @@ CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -63,14 +64,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -85,14 +89,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -119,18 +128,33 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CPM2=y
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
# CONFIG_MPC8540_ADS is not set
CONFIG_MPC8560_ADS=y
# CONFIG_MPC85xx_CDS is not set
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC8544_DS is not set
CONFIG_MPC8560=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPC85xx=y
CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_CPM2=y
#
# Kernel options
@@ -148,7 +172,6 @@ CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
# CONFIG_MATH_EMULATION is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
-# CONFIG_PC_KEYBOARD is not set
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_SELECT_MEMORY_MODEL=y
@@ -160,32 +183,33 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
CONFIG_PCI_DEBUG=y
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -210,13 +234,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -250,20 +274,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -289,7 +301,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -302,16 +323,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -322,6 +340,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -340,19 +359,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -361,10 +377,6 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -380,18 +392,14 @@ CONFIG_BLK_DEV_INITRD=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -401,15 +409,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -444,10 +444,7 @@ CONFIG_MII=y
CONFIG_FS_ENET=y
# CONFIG_FS_ENET_HAS_SCC is not set
CONFIG_FS_ENET_HAS_FCC=y
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
@@ -461,34 +458,28 @@ CONFIG_E1000_NAPI=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -514,6 +505,7 @@ CONFIG_GFAR_NAPI=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -530,6 +522,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -573,16 +566,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -593,10 +581,7 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -609,35 +594,41 @@ CONFIG_GEN_RTC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -648,6 +639,7 @@ CONFIG_FIRMWARE_EDID=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -665,10 +657,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -712,10 +700,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -800,6 +784,7 @@ CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -825,6 +810,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -835,6 +821,7 @@ CONFIG_PARTITION_ADVANCED=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -842,10 +829,13 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -862,15 +852,15 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -879,7 +869,10 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_KGDB_CONSOLE is not set
# CONFIG_BDI_SWITCH is not set
diff --git a/arch/powerpc/configs/mpc8568mds_defconfig b/arch/powerpc/configs/mpc8568mds_defconfig
index 7b3800674cb..6451d4dd28a 100644
--- a/arch/powerpc/configs/mpc8568mds_defconfig
+++ b/arch/powerpc/configs/mpc8568mds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Sat Feb 17 16:26:53 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:59 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -46,6 +46,7 @@ CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -70,8 +71,10 @@ CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -84,14 +87,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -123,18 +131,32 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
# CONFIG_MPC8540_ADS is not set
# CONFIG_MPC8560_ADS is not set
# CONFIG_MPC85xx_CDS is not set
CONFIG_MPC85xx_MDS=y
+# CONFIG_MPC8544_DS is not set
CONFIG_MPC85xx=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -168,18 +190,20 @@ CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
CONFIG_ZONE_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_FSL_SOC=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -187,10 +211,6 @@ CONFIG_FSL_SOC=y
# CONFIG_PCCARD is not set
#
-# PCI Hotplug Support
-#
-
-#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
@@ -212,7 +232,6 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
@@ -253,20 +272,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -292,7 +299,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -312,10 +328,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -326,6 +338,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -339,17 +352,13 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -378,6 +387,7 @@ CONFIG_SCSI_PROC_FS=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -393,35 +403,13 @@ CONFIG_SCSI_PROC_FS=y
#
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -431,10 +419,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -455,29 +439,16 @@ CONFIG_MARVELL_PHY=y
#
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -501,6 +472,7 @@ CONFIG_GFAR_NAPI=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -517,6 +489,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -540,6 +513,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
#
# Non-8250 serial port support
@@ -556,10 +530,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
CONFIG_WATCHDOG=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
@@ -572,7 +542,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
@@ -580,11 +549,8 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -600,8 +566,8 @@ CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MPC=y
# CONFIG_I2C_OCORES is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -629,16 +595,14 @@ CONFIG_I2C_MPC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
@@ -661,6 +625,7 @@ CONFIG_HWMON=y
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
@@ -677,22 +642,29 @@ CONFIG_HWMON=y
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -720,10 +692,6 @@ CONFIG_HID=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -766,14 +734,6 @@ CONFIG_HID=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -861,6 +821,7 @@ CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -886,6 +847,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -896,6 +858,7 @@ CONFIG_PARTITION_ADVANCED=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -903,11 +866,13 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -926,9 +891,9 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
@@ -943,8 +908,10 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_DEBUGGER=y
# CONFIG_XMON is not set
# CONFIG_BDI_SWITCH is not set
@@ -958,6 +925,7 @@ CONFIG_PPC_EARLY_DEBUG=y
# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
# CONFIG_PPC_EARLY_DEBUG_BEAT is not set
+# CONFIG_PPC_EARLY_DEBUG_44x is not set
#
# Security options
@@ -987,6 +955,7 @@ CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_BLOWFISH is not set
diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
index 1f61bce33e3..d9afe7009d9 100644
--- a/arch/powerpc/configs/mpc85xx_cds_defconfig
+++ b/arch/powerpc/configs/mpc85xx_cds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:26:46 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:56:59 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -34,9 +34,9 @@ CONFIG_DEFAULT_UIMAGE=y
# CONFIG_PPC_83xx is not set
CONFIG_PPC_85xx=y
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_85xx=y
CONFIG_E500=y
@@ -46,6 +46,7 @@ CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
@@ -63,14 +64,17 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -85,14 +89,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -119,17 +128,33 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
# CONFIG_MPC8540_ADS is not set
# CONFIG_MPC8560_ADS is not set
CONFIG_MPC85xx_CDS=y
+# CONFIG_MPC85xx_MDS is not set
+# CONFIG_MPC8544_DS is not set
CONFIG_MPC8540=y
-CONFIG_PPC_INDIRECT_PCI_BE=y
+CONFIG_MPC85xx=y
CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -158,32 +183,33 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
+CONFIG_WANT_DEVICE_TREE=y
+CONFIG_DEVICE_TREE=""
CONFIG_ISA_DMA_API=y
#
# Bus options
#
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_FSL_SOC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -208,13 +234,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -248,20 +274,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -287,7 +301,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -300,16 +323,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -320,6 +340,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -338,19 +359,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=32768
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_IDE_MAX_HWIFS=4
CONFIG_BLK_DEV_IDE=y
@@ -365,6 +383,7 @@ CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -372,12 +391,13 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
@@ -391,6 +411,7 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -401,10 +422,10 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_TC86C001 is not set
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
# CONFIG_BLK_DEV_HD is not set
#
@@ -413,10 +434,6 @@ CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -432,18 +449,14 @@ CONFIG_BLK_DEV_IDEDMA=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -453,15 +466,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -493,10 +498,7 @@ CONFIG_MII=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
@@ -510,34 +512,28 @@ CONFIG_E1000_NAPI=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
CONFIG_GFAR_NAPI=y
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -563,6 +559,7 @@ CONFIG_GFAR_NAPI=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -579,6 +576,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -603,6 +601,7 @@ CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
#
# Non-8250 serial port support
@@ -611,6 +610,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -619,16 +619,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -639,10 +634,7 @@ CONFIG_GEN_RTC=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
# CONFIG_I2C is not set
#
@@ -655,35 +647,41 @@ CONFIG_GEN_RTC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -694,6 +692,7 @@ CONFIG_FIRMWARE_EDID=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -711,10 +710,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -758,10 +753,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -846,6 +837,7 @@ CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -871,6 +863,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -881,6 +874,7 @@ CONFIG_PARTITION_ADVANCED=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -888,10 +882,13 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -908,15 +905,15 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -925,7 +922,10 @@ CONFIG_DEBUG_MUTEXES=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
index 53fcd6932f5..1ac94a605b0 100644
--- a/arch/powerpc/configs/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:27:14 2007
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:57:00 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -24,7 +24,7 @@ CONFIG_PPC_UDBG_16550=y
CONFIG_GENERIC_TBSYNC=y
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
-# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_DEFAULT_UIMAGE=y
#
# Processor support
@@ -34,9 +34,9 @@ CONFIG_GENERIC_BUG=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
CONFIG_PPC_86xx=y
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
@@ -45,6 +45,7 @@ CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -70,9 +71,11 @@ CONFIG_LOCALVERSION=""
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_CPUSETS is not set
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -87,14 +90,19 @@ CONFIG_BUG=y
# CONFIG_ELF_CORE is not set
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -121,15 +129,28 @@ CONFIG_DEFAULT_DEADLINE=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="deadline"
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_PPC_INDIRECT_PCI_BE=y
-CONFIG_MPIC=y
#
-# Platform Support
+# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
CONFIG_MPC8641_HPCN=y
CONFIG_MPC8641=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -159,33 +180,34 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_FSL_SOC=y
+CONFIG_FSL_PCIE=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -210,13 +232,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
@@ -234,7 +256,7 @@ CONFIG_IP_PNP_RARP=y
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
@@ -247,6 +269,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
@@ -262,20 +285,8 @@ CONFIG_IPV6_SIT=y
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -301,7 +312,16 @@ CONFIG_IPV6_SIT=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -314,16 +334,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -334,6 +351,7 @@ CONFIG_FW_LOADER=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -352,19 +370,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=131072
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -373,10 +388,6 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -392,18 +403,14 @@ CONFIG_BLK_DEV_INITRD=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -413,15 +420,7 @@ CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -453,10 +452,7 @@ CONFIG_MII=y
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -468,34 +464,28 @@ CONFIG_MII=y
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2 is not set
CONFIG_GIANFAR=y
# CONFIG_GFAR_NAPI is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -521,6 +511,7 @@ CONFIG_GIANFAR=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -537,6 +528,7 @@ CONFIG_INPUT=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -581,6 +573,7 @@ CONFIG_SERIAL_8250_RSA=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
@@ -588,15 +581,10 @@ CONFIG_UNIX98_PTYS=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -607,11 +595,9 @@ CONFIG_UNIX98_PTYS=y
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_CHARDEV is not set
#
@@ -638,13 +624,13 @@ CONFIG_I2C_MPC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -672,27 +658,30 @@ CONFIG_SENSORS_EEPROM=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
# CONFIG_FB_IBM_GXT4500 is not set
@@ -702,7 +691,6 @@ CONFIG_FIRMWARE_EDID=y
CONFIG_VGA_CONSOLE=y
# CONFIG_VGACON_SOFT_SCROLLBACK is not set
CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -713,6 +701,7 @@ CONFIG_DUMMY_CONSOLE=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
#
# USB support
@@ -730,10 +719,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -777,10 +762,6 @@ CONFIG_USB_ARCH_HAS_EHCI=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -869,6 +850,7 @@ CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -899,6 +881,7 @@ CONFIG_LDM_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -948,6 +931,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -955,10 +939,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -975,15 +962,15 @@ CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -993,7 +980,10 @@ CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
-# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_DEBUGGER is not set
# CONFIG_BDI_SWITCH is not set
# CONFIG_BOOTX_TEXT is not set
diff --git a/arch/powerpc/configs/mpc866_ads_defconfig b/arch/powerpc/configs/mpc866_ads_defconfig
index 539d9e3d366..e6b18ea8f64 100644
--- a/arch/powerpc/configs/mpc866_ads_defconfig
+++ b/arch/powerpc/configs/mpc866_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc6
-# Fri Nov 24 21:13:55 2006
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:57:00 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -28,7 +29,6 @@ CONFIG_AUDIT_ARCH=y
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
@@ -40,6 +40,7 @@ CONFIG_PPC_8xx=y
CONFIG_8xx=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -58,14 +59,17 @@ CONFIG_LOCALVERSION_AUTO=y
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -78,14 +82,19 @@ CONFIG_PRINTK=y
CONFIG_ELF_CORE=y
# CONFIG_BASE_FULL is not set
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -112,13 +121,14 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_EMBEDDEDBOOT=y
-# CONFIG_MPIC is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
CONFIG_CPM1=y
# CONFIG_MPC8XXFADS is not set
CONFIG_MPC86XADS=y
@@ -137,6 +147,18 @@ CONFIG_NO_UCODE_PATCH=y
# CONFIG_USB_SOF_UCODE_PATCH is not set
# CONFIG_I2C_SPI_UCODE_PATCH is not set
# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -144,6 +166,7 @@ CONFIG_NO_UCODE_PATCH=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_PREEMPT_NONE=y
@@ -164,31 +187,29 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
CONFIG_FSL_SOC=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_QSPAN is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
#
-# PCI Hotplug Support
-#
-
-#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
@@ -212,13 +233,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -246,25 +267,14 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -290,7 +300,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -307,10 +326,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -321,6 +336,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -331,18 +347,13 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -351,34 +362,13 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -388,10 +378,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -404,6 +390,7 @@ CONFIG_PHYLIB=y
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
CONFIG_FIXED_PHY=y
CONFIG_FIXED_MII_10_FDX=y
CONFIG_FIXED_MII_100_FDX=y
@@ -417,27 +404,14 @@ CONFIG_MII=y
CONFIG_FS_ENET=y
CONFIG_FS_ENET_HAS_SCC=y
CONFIG_FS_ENET_HAS_FEC=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -461,6 +435,7 @@ CONFIG_FS_ENET_HAS_FEC=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -486,9 +461,16 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -516,6 +498,7 @@ CONFIG_SERIO_LIBPS2=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
@@ -533,31 +516,18 @@ CONFIG_UNIX98_PTYS=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -570,33 +540,41 @@ CONFIG_GEN_RTC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
#
# Sound
@@ -604,6 +582,12 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
@@ -618,10 +602,6 @@ CONFIG_FIRMWARE_EDID=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -752,6 +732,7 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -781,6 +762,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -788,14 +770,25 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -809,11 +802,9 @@ CONFIG_PLIST=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
diff --git a/arch/powerpc/configs/mpc885_ads_defconfig b/arch/powerpc/configs/mpc885_ads_defconfig
index e2c17d8da4f..fc4f9b766aa 100644
--- a/arch/powerpc/configs/mpc885_ads_defconfig
+++ b/arch/powerpc/configs/mpc885_ads_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc4
-# Fri Nov 10 21:30:40 2006
+# Linux kernel version: 2.6.22-rc7
+# Sun Jul 1 23:57:01 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -10,6 +10,7 @@ CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_IRQ_PER_CPU=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
@@ -28,7 +29,6 @@ CONFIG_AUDIT_ARCH=y
# Processor support
#
# CONFIG_CLASSIC32 is not set
-# CONFIG_PPC_52xx is not set
# CONFIG_PPC_82xx is not set
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
@@ -38,6 +38,9 @@ CONFIG_PPC_8xx=y
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_8xx=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -56,14 +59,17 @@ CONFIG_LOCALVERSION_AUTO=y
# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
-CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_EMBEDDED=y
@@ -76,14 +82,19 @@ CONFIG_PRINTK=y
CONFIG_ELF_CORE=y
# CONFIG_BASE_FULL is not set
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
# CONFIG_EPOLL is not set
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=1
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -110,19 +121,27 @@ CONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="anticipatory"
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_EMBEDDEDBOOT=y
-# CONFIG_MPIC is not set
#
# Platform support
#
+# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
CONFIG_CPM1=y
# CONFIG_MPC8XXFADS is not set
# CONFIG_MPC86XADS is not set
CONFIG_MPC885ADS=y
#
+# Freescale Ethernet driver platform-specific options
+#
+CONFIG_MPC8xx_SECOND_ETH=y
+CONFIG_MPC8xx_SECOND_ETH_FEC2=y
+# CONFIG_MPC8xx_SECOND_ETH_SCC3 is not set
+
+#
# MPC8xx CPM Options
#
@@ -135,6 +154,18 @@ CONFIG_NO_UCODE_PATCH=y
# CONFIG_USB_SOF_UCODE_PATCH is not set
# CONFIG_I2C_SPI_UCODE_PATCH is not set
# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+# CONFIG_PQ2ADS is not set
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -142,6 +173,7 @@ CONFIG_NO_UCODE_PATCH=y
# CONFIG_HIGHMEM is not set
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
CONFIG_PREEMPT_NONE=y
@@ -162,31 +194,29 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
# CONFIG_PROC_DEVICETREE is not set
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
+CONFIG_ZONE_DMA=y
CONFIG_FSL_SOC=y
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_QSPAN is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
#
# PCCARD (PCMCIA/CardBus) support
#
#
-# PCI Hotplug Support
-#
-
-#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
@@ -210,13 +240,13 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
# CONFIG_XFRM_USER is not set
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
@@ -244,25 +274,14 @@ CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -288,7 +307,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -305,10 +333,6 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -319,6 +343,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -329,18 +354,13 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
-# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
# CONFIG_IDE is not set
#
@@ -349,34 +369,13 @@ CONFIG_BLK_DEV_LOOP=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Macintosh device drivers
-#
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -386,10 +385,6 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -402,6 +397,7 @@ CONFIG_DAVICOM_PHY=y
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
CONFIG_FIXED_PHY=y
CONFIG_FIXED_MII_10_FDX=y
# CONFIG_FIXED_MII_100_FDX is not set
@@ -415,27 +411,14 @@ CONFIG_MII=y
CONFIG_FS_ENET=y
CONFIG_FS_ENET_HAS_SCC=y
CONFIG_FS_ENET_HAS_FEC=y
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
-#
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -459,6 +442,7 @@ CONFIG_FS_ENET_HAS_FEC=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -484,9 +468,16 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -514,6 +505,7 @@ CONFIG_SERIO_LIBPS2=y
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
@@ -531,31 +523,18 @@ CONFIG_UNIX98_PTYS=y
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
CONFIG_HW_RANDOM=y
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
-
-#
-# Ftape, the floppy tape device driver
-#
# CONFIG_RAW_DRIVER is not set
#
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
# CONFIG_I2C is not set
#
@@ -568,33 +547,41 @@ CONFIG_GEN_RTC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
#
# Sound
@@ -602,6 +589,12 @@ CONFIG_FIRMWARE_EDID=y
# CONFIG_SOUND is not set
#
+# HID Devices
+#
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
# USB support
#
# CONFIG_USB_ARCH_HAS_HCD is not set
@@ -616,10 +609,6 @@ CONFIG_FIRMWARE_EDID=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -750,6 +739,7 @@ CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
@@ -779,6 +769,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -786,14 +777,25 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_NLS is not set
#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+
+#
# Library routines
#
+CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -807,11 +809,9 @@ CONFIG_PLIST=y
CONFIG_ENABLE_MUST_CHECK=y
# CONFIG_MAGIC_SYSRQ is not set
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
# CONFIG_BOOTX_TEXT is not set
# CONFIG_PPC_EARLY_DEBUG is not set
diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig
index 0507c8f7bfb..905998b925e 100644
--- a/arch/powerpc/configs/pasemi_defconfig
+++ b/arch/powerpc/configs/pasemi_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Mon May 14 12:55:04 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 13:51:39 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -295,20 +295,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -466,10 +454,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -571,7 +555,6 @@ CONFIG_SCSI_3W_9XXX=y
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
# CONFIG_SCSI_SRP is not set
#
@@ -580,10 +563,6 @@ CONFIG_SCSI_3W_9XXX=y
# CONFIG_PCMCIA_FDOMAIN is not set
# CONFIG_PCMCIA_QLOGIC is not set
# CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
@@ -694,15 +673,7 @@ CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -752,10 +723,7 @@ CONFIG_NET_PCI=y
# CONFIG_SUNDANCE is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
@@ -774,10 +742,7 @@ CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
@@ -786,11 +751,6 @@ CONFIG_TIGON3=y
# CONFIG_NETXEN_NIC is not set
CONFIG_PASEMI_MAC=y
# CONFIG_MLX4_CORE is not set
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
# CONFIG_TR is not set
#
@@ -808,15 +768,7 @@ CONFIG_MLX4_DEBUG=y
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET_MII is not set
# CONFIG_USB_USBNET is not set
-
-#
-# PCMCIA network device support
-#
# CONFIG_NET_PCMCIA is not set
-
-#
-# Wan interfaces
-#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -843,6 +795,7 @@ CONFIG_MLX4_DEBUG=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -1661,7 +1614,6 @@ CONFIG_NLS_ISO8859_1=y
#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
#
# Library routines
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index f611df480fd..0d8ba623e29 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1,9 +1,10 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:28:56 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:11:36 2007
#
# CONFIG_PPC64 is not set
+CONFIG_PPC_PM_NEEDS_RTC_LIB=y
CONFIG_PPC32=y
CONFIG_PPC_MERGE=y
CONFIG_MMU=y
@@ -24,6 +25,7 @@ CONFIG_PPC_OF=y
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
# CONFIG_DEFAULT_UIMAGE is not set
#
@@ -34,9 +36,9 @@ CONFIG_CLASSIC32=y
# CONFIG_PPC_83xx is not set
# CONFIG_PPC_85xx is not set
# CONFIG_PPC_86xx is not set
+# CONFIG_PPC_8xx is not set
# CONFIG_40x is not set
# CONFIG_44x is not set
-# CONFIG_8xx is not set
# CONFIG_E200 is not set
CONFIG_6xx=y
CONFIG_PPC_FPU=y
@@ -45,6 +47,7 @@ CONFIG_PPC_FPU=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
CONFIG_PPC_STD_MMU_32=y
+# CONFIG_PPC_MM_SLICES is not set
# CONFIG_SMP is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
@@ -63,6 +66,7 @@ CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
@@ -70,8 +74,10 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
@@ -86,14 +92,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -134,12 +145,17 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_APUS is not set
# CONFIG_PPC_CHRP is not set
# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
# CONFIG_PPC_EFIKA is not set
# CONFIG_PPC_LITE5200 is not set
CONFIG_PPC_PMAC=y
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
+# CONFIG_PQ2ADS is not set
CONFIG_PPC_NATIVE=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
CONFIG_PPC_MPC106=y
@@ -158,11 +174,14 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPU Frequency drivers
+#
CONFIG_CPU_FREQ_PMAC=y
CONFIG_PPC601_SYNC_FIX=y
# CONFIG_TAU is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -191,6 +210,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
CONFIG_PM=y
@@ -200,19 +220,23 @@ CONFIG_PM_DEBUG=y
CONFIG_PM_SYSFS_DEPRECATED=y
CONFIG_SOFTWARE_SUSPEND=y
CONFIG_PM_STD_PARTITION=""
+CONFIG_APM_EMULATION=y
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
CONFIG_PPC_INDIRECT_PCI=y
+# CONFIG_PPC_INDIRECT_PCI_BE is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
# CONFIG_PCI_DEBUG is not set
#
@@ -237,10 +261,6 @@ CONFIG_YENTA_TOSHIBA=y
# CONFIG_PD6729 is not set
# CONFIG_I82092 is not set
CONFIG_PCCARD_NONSTATIC=m
-
-#
-# PCI Hotplug Support
-#
# CONFIG_HOTPLUG_PCI is not set
#
@@ -265,14 +285,15 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -297,10 +318,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
@@ -314,8 +331,6 @@ CONFIG_NETFILTER=y
#
# CONFIG_NETFILTER_NETLINK is not set
CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
CONFIG_NF_CONNTRACK=m
# CONFIG_NF_CT_ACCT is not set
# CONFIG_NF_CONNTRACK_MARK is not set
@@ -327,16 +342,21 @@ CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_IRC=m
# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
# CONFIG_NF_CONNTRACK_SIP is not set
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
CONFIG_NETFILTER_XT_MATCH_DCCP=m
CONFIG_NETFILTER_XT_MATCH_DSCP=m
@@ -377,7 +397,6 @@ CONFIG_IP_NF_FILTER=m
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IP_NF_TARGET_LOG=m
CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
CONFIG_NF_NAT=m
CONFIG_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -396,14 +415,11 @@ CONFIG_IP_NF_MANGLE=m
CONFIG_IP_NF_TARGET_TOS=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
CONFIG_IP_NF_RAW=m
CONFIG_IP_NF_ARPTABLES=m
CONFIG_IP_NF_ARPFILTER=m
CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
CONFIG_IP_DCCP=m
CONFIG_INET_DCCP_DIAG=m
CONFIG_IP_DCCP_ACKVEC=y
@@ -422,15 +438,7 @@ CONFIG_IP_DCCP_CCID3_RTO=100
# DCCP Kernel Hacking
#
# CONFIG_IP_DCCP_DEBUG is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -448,6 +456,7 @@ CONFIG_IP_DCCP_CCID3_RTO=100
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+CONFIG_NET_SCH_FIFO=y
CONFIG_NET_CLS_ROUTE=y
#
@@ -485,6 +494,7 @@ CONFIG_IRTTY_SIR=m
# Dongle support
#
# CONFIG_DONGLE is not set
+# CONFIG_KINGSUN_DONGLE is not set
#
# Old SIR device drivers
@@ -532,13 +542,23 @@ CONFIG_BT_HCIBFUSB=m
# CONFIG_BT_HCIBLUECARD is not set
# CONFIG_BT_HCIBTUART is not set
# CONFIG_BT_HCIVHCI is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+CONFIG_CFG80211=m
+CONFIG_WIRELESS_EXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUG is not set
CONFIG_IEEE80211=m
# CONFIG_IEEE80211_DEBUG is not set
CONFIG_IEEE80211_CRYPT_WEP=m
CONFIG_IEEE80211_CRYPT_CCMP=m
CONFIG_IEEE80211_CRYPT_TKIP=m
# CONFIG_IEEE80211_SOFTMAC is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -551,6 +571,7 @@ CONFIG_WIRELESS_EXT=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
@@ -558,10 +579,6 @@ CONFIG_FW_LOADER=y
#
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -572,6 +589,7 @@ CONFIG_PROC_EVENTS=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -592,19 +610,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -615,11 +630,13 @@ CONFIG_BLK_DEV_IDE=y
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_DELKIN is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
CONFIG_BLK_DEV_IDEFLOPPY=y
CONFIG_BLK_DEV_IDESCSI=y
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -627,12 +644,12 @@ CONFIG_BLK_DEV_IDESCSI=y
# CONFIG_IDE_GENERIC is not set
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
@@ -647,6 +664,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -657,13 +675,13 @@ CONFIG_BLK_DEV_SL82C105=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -693,6 +711,7 @@ CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -762,10 +781,6 @@ CONFIG_SCSI_MAC53C94=y
# CONFIG_PCMCIA_NINJA_SCSI is not set
# CONFIG_PCMCIA_QLOGIC is not set
# CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -787,6 +802,7 @@ CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
#
# Fusion MPT device support
@@ -799,28 +815,26 @@ CONFIG_DM_ZERO=m
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
CONFIG_IEEE1394=m
#
# Subsystem Options
#
# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
#
-# Device Drivers
+# Controllers
#
# CONFIG_IEEE1394_PCILYNX is not set
CONFIG_IEEE1394_OHCI1394=m
#
-# Protocol Drivers
+# Protocols
#
CONFIG_IEEE1394_VIDEO1394=m
CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_ETH1394_ROM_ENTRY is not set
# CONFIG_IEEE1394_ETH1394 is not set
CONFIG_IEEE1394_DV1394=m
CONFIG_IEEE1394_RAWIO=m
@@ -829,10 +843,7 @@ CONFIG_IEEE1394_RAWIO=m
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
+CONFIG_MACINTOSH_DRIVERS=y
CONFIG_ADB=y
CONFIG_ADB_CUDA=y
CONFIG_ADB_PMU=y
@@ -858,15 +869,7 @@ CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -907,10 +910,8 @@ CONFIG_PCNET32=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
@@ -927,77 +928,62 @@ CONFIG_PCNET32=y
# CONFIG_BNX2 is not set
# CONFIG_MV643XX_ETH is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-# CONFIG_NET_WIRELESS_RTNETLINK is not set
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
+# Wireless LAN
#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
# CONFIG_PCMCIA_RAYCS is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
# CONFIG_IPW2100 is not set
# CONFIG_IPW2200 is not set
+# CONFIG_LIBERTAS is not set
# CONFIG_AIRO is not set
CONFIG_HERMES=m
CONFIG_APPLE_AIRPORT=m
# CONFIG_PLX_HERMES is not set
# CONFIG_TMD_HERMES is not set
# CONFIG_NORTEL_HERMES is not set
-# CONFIG_PCI_HERMES is not set
+CONFIG_PCI_HERMES=m
# CONFIG_ATMEL is not set
-
-#
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-# CONFIG_PCMCIA_HERMES is not set
+CONFIG_PCMCIA_HERMES=m
# CONFIG_PCMCIA_SPECTRUM is not set
# CONFIG_AIRO_CS is not set
# CONFIG_PCMCIA_WL3501 is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
CONFIG_PRISM54=m
# CONFIG_USB_ZD1201 is not set
# CONFIG_HOSTAP is not set
-CONFIG_NET_WIRELESS=y
#
-# PCMCIA network device support
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET_MII=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
# CONFIG_NET_PCMCIA is not set
-
-#
-# Wan interfaces
-#
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -1033,6 +1019,7 @@ CONFIG_SLHC=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -1059,8 +1046,10 @@ CONFIG_INPUT_KEYBOARD=y
CONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not set
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
@@ -1100,6 +1089,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_CORE=m
CONFIG_SERIAL_PMACZILOG=m
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -1108,16 +1098,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_NVRAM=y
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
CONFIG_AGP=m
@@ -1143,11 +1128,9 @@ CONFIG_DRM_RADEON=m
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=m
#
@@ -1175,14 +1158,15 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -1210,37 +1194,56 @@ CONFIG_I2C_POWERMAC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
#
-# Graphics support
+# Display device support
#
-# CONFIG_FIRMWARE_EDID is not set
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+CONFIG_VGASTATE=y
CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
CONFIG_FB_MACMODES=y
CONFIG_FB_BACKLIGHT=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -1255,6 +1258,7 @@ CONFIG_FB_IMSTT=y
# CONFIG_FB_S1D13XXX is not set
CONFIG_FB_NVIDIA=y
CONFIG_FB_NVIDIA_I2C=y
+# CONFIG_FB_NVIDIA_DEBUG is not set
CONFIG_FB_NVIDIA_BACKLIGHT=y
# CONFIG_FB_RIVA is not set
CONFIG_FB_MATROX=y
@@ -1274,6 +1278,7 @@ CONFIG_FB_ATY_CT=y
# CONFIG_FB_ATY_GENERIC_LCD is not set
CONFIG_FB_ATY_GX=y
CONFIG_FB_ATY_BACKLIGHT=y
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
@@ -1281,7 +1286,10 @@ CONFIG_FB_ATY_BACKLIGHT=y
CONFIG_FB_3DFX=y
# CONFIG_FB_3DFX_ACCEL is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
# CONFIG_FB_IBM_GXT4500 is not set
# CONFIG_FB_VIRTUAL is not set
@@ -1295,26 +1303,15 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
#
# Sound
#
CONFIG_SOUND=m
-CONFIG_DMASOUND_PMAC=m
-CONFIG_DMASOUND=m
#
# Advanced Linux Sound Architecture
@@ -1428,6 +1425,7 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m
#
CONFIG_SND_USB_AUDIO=m
# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
#
# PCMCIA devices
@@ -1436,6 +1434,11 @@ CONFIG_SND_USB_AUDIO=m
# CONFIG_SND_PDAUDIOCF is not set
#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
+
+#
# Open Sound System
#
# CONFIG_SOUND_PRIME is not set
@@ -1444,6 +1447,15 @@ CONFIG_SND_USB_AUDIO=m
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT_POWERBOOK=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
#
# USB support
@@ -1458,10 +1470,9 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
CONFIG_USB_DYNAMIC_MINORS=y
# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1471,9 +1482,12 @@ CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_SPLIT_ISO=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
@@ -1506,49 +1520,10 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT_POWERBOOK=y
-# CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-CONFIG_USB_APPLETOUCH=y
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-CONFIG_USB_USBNET_MII=m
-CONFIG_USB_USBNET=m
-CONFIG_USB_NET_AX8817X=m
-CONFIG_USB_NET_CDCETHER=m
-# CONFIG_USB_NET_GL620A is not set
-CONFIG_USB_NET_NET1080=m
-# CONFIG_USB_NET_PLUSB is not set
-# CONFIG_USB_NET_MCS7830 is not set
-# CONFIG_USB_NET_RNDIS_HOST is not set
-# CONFIG_USB_NET_CDC_SUBSET is not set
-CONFIG_USB_NET_ZAURUS=m
CONFIG_USB_MON=y
#
@@ -1620,6 +1595,7 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1630,6 +1606,7 @@ CONFIG_USB_APPLEDISPLAY=m
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1640,10 +1617,6 @@ CONFIG_USB_APPLEDISPLAY=m
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1676,6 +1649,7 @@ CONFIG_LEDS_TRIGGER_IDE_DISK=y
#
# Real Time Clock
#
+CONFIG_RTC_LIB=y
# CONFIG_RTC_CLASS is not set
#
@@ -1692,10 +1666,6 @@ CONFIG_LEDS_TRIGGER_IDE_DISK=y
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1731,7 +1701,6 @@ CONFIG_FUSE_FS=m
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y
@@ -1796,6 +1765,7 @@ CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
# CONFIG_RPCSEC_GSS_SPKM3 is not set
CONFIG_SMB_FS=m
@@ -1826,6 +1796,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1875,6 +1846,7 @@ CONFIG_NLS_UTF8=m
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1882,6 +1854,7 @@ CONFIG_NLS_UTF8=m
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=y
CONFIG_CRC16=y
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
@@ -1891,13 +1864,16 @@ CONFIG_TEXTSEARCH_KMP=m
CONFIG_TEXTSEARCH_BM=m
CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
#
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
+# CONFIG_KPROBES is not set
#
# Kernel hacking
@@ -1909,15 +1885,15 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_FS is not set
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1927,6 +1903,9 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_FORCED_INLINING is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
CONFIG_DEBUGGER=y
CONFIG_XMON=y
CONFIG_XMON_DEFAULT=y
@@ -1962,8 +1941,11 @@ CONFIG_CRYPTO_TGR192=m
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1978,6 +1960,7 @@ CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_TEST is not set
#
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 126b9f87df2..6e503d98dab 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:28:58 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:15:02 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -27,6 +27,7 @@ CONFIG_GENERIC_TBSYNC=y
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
# CONFIG_DEFAULT_UIMAGE is not set
+CONFIG_PPC64_SWSUSP=y
#
# Processor support
@@ -41,6 +42,7 @@ CONFIG_PPC_DCR=y
CONFIG_PPC_OF_PLATFORM_PCI=y
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
@@ -61,20 +63,23 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
+# CONFIG_TASK_XACCT is not set
# CONFIG_UTS_NS is not set
# CONFIG_AUDIT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
CONFIG_CPUSETS=y
CONFIG_SYSFS_DEPRECATED=y
CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-# CONFIG_TASK_XACCT is not set
CONFIG_SYSCTL=y
# CONFIG_EMBEDDED is not set
CONFIG_SYSCTL_SYSCALL=y
@@ -87,14 +92,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -133,24 +143,54 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
CONFIG_PPC_PSERIES=y
+CONFIG_PPC_SPLPAR=y
+CONFIG_EEH=y
+CONFIG_SCANLOG=m
+CONFIG_LPARCFG=y
CONFIG_PPC_ISERIES=y
+
+#
+# iSeries device drivers
+#
+CONFIG_VIODASD=y
+CONFIG_VIOCD=m
+CONFIG_VIOTAPE=m
+CONFIG_VIOPATH=y
# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
CONFIG_PPC_PMAC=y
CONFIG_PPC_PMAC64=y
CONFIG_PPC_MAPLE=y
# CONFIG_PPC_PASEMI is not set
+CONFIG_PPC_CELLEB=y
+# CONFIG_PPC_PS3 is not set
CONFIG_PPC_CELL=y
CONFIG_PPC_CELL_NATIVE=y
CONFIG_PPC_IBM_CELL_BLADE=y
-# CONFIG_PPC_PS3 is not set
+
+#
+# Cell Broadband Engine options
+#
+CONFIG_SPU_FS=m
+CONFIG_SPU_FS_64K_LS=y
+CONFIG_SPU_BASE=y
+CONFIG_CBE_RAS=y
+CONFIG_CBE_THERM=m
+CONFIG_CBE_CPUFREQ=m
+# CONFIG_PQ2ADS is not set
CONFIG_PPC_NATIVE=y
CONFIG_UDBG_RTAS_CONSOLE=y
+CONFIG_PPC_UDBG_BEAT=y
CONFIG_XICS=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
CONFIG_U3_DART=y
CONFIG_PPC_RTAS=y
CONFIG_RTAS_ERROR_LOGGING=y
CONFIG_RTAS_PROC=y
CONFIG_RTAS_FLASH=m
+CONFIG_PPC_PMI=m
CONFIG_MMIO_NVRAM=y
CONFIG_MPIC_U3_HT_IRQS=y
CONFIG_IBMVIO=y
@@ -171,18 +211,12 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
-CONFIG_CPU_FREQ_PMAC64=y
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
#
-# Cell Broadband Engine options
+# CPU Frequency drivers
#
-CONFIG_SPU_FS=m
-CONFIG_SPU_BASE=y
-CONFIG_CBE_RAS=y
-CONFIG_CBE_THERM=m
-CONFIG_CBE_CPUFREQ=m
+CONFIG_CPU_FREQ_PMAC64=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -205,10 +239,6 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_KEXEC=y
# CONFIG_CRASH_DUMP is not set
CONFIG_IRQ_ALL_CPUS=y
-CONFIG_PPC_SPLPAR=y
-CONFIG_EEH=y
-CONFIG_SCANLOG=m
-CONFIG_LPARCFG=y
# CONFIG_NUMA is not set
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_FLATMEM_ENABLE=y
@@ -227,35 +257,35 @@ CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_ARCH_MEMORY_PROBE=y
+CONFIG_PPC_HAS_HASH_64K=y
# CONFIG_PPC_64K_PAGES is not set
# CONFIG_SCHED_SMT is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
CONFIG_HOTPLUG_PCI=m
# CONFIG_HOTPLUG_PCI_FAKE is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
@@ -272,14 +302,15 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -304,10 +335,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
@@ -323,8 +350,6 @@ CONFIG_NETFILTER_NETLINK=y
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CT_ACCT=y
CONFIG_NF_CONNTRACK_MARK=y
@@ -337,10 +362,42 @@ CONFIG_NF_CONNTRACK_H323=m
CONFIG_NF_CONNTRACK_IRC=m
CONFIG_NF_CONNTRACK_NETBIOS_NS=m
CONFIG_NF_CONNTRACK_PPTP=m
+# CONFIG_NF_CONNTRACK_SANE is not set
CONFIG_NF_CONNTRACK_SIP=m
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
-# CONFIG_NETFILTER_XTABLES is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
#
# IP: Netfilter Configuration
@@ -348,20 +405,45 @@ CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -380,6 +462,7 @@ CONFIG_LLC=y
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -388,7 +471,16 @@ CONFIG_LLC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -401,16 +493,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -421,6 +510,7 @@ CONFIG_FW_LOADER=y
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -440,19 +530,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -467,6 +554,7 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -474,12 +562,12 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
@@ -494,6 +582,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -504,13 +593,14 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_CELLEB=y
CONFIG_BLK_DEV_IDE_PMAC=y
CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
CONFIG_BLK_DEV_IDEDMA_PMAC=y
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -540,6 +630,7 @@ CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -593,11 +684,8 @@ CONFIG_SCSI_LPFC=m
# CONFIG_SCSI_DC390T is not set
CONFIG_SCSI_DEBUG=m
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
+CONFIG_ATA_NONSTANDARD=y
# CONFIG_SATA_AHCI is not set
CONFIG_SATA_SVW=y
# CONFIG_ATA_PIIX is not set
@@ -613,10 +701,12 @@ CONFIG_SATA_SVW=y
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -628,6 +718,7 @@ CONFIG_SATA_SVW=y
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
@@ -647,6 +738,7 @@ CONFIG_SATA_SVW=y
# CONFIG_PATA_SIS is not set
# CONFIG_PATA_VIA is not set
CONFIG_PATA_WINBOND=y
+CONFIG_PATA_SCC=y
#
# Multi-device support (RAID and LVM)
@@ -669,6 +761,7 @@ CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_DELAY is not set
#
# Fusion MPT device support
@@ -681,28 +774,26 @@ CONFIG_DM_MULTIPATH_EMC=m
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
CONFIG_IEEE1394=y
#
# Subsystem Options
#
# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
-CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
-# CONFIG_IEEE1394_EXPORT_FULL_API is not set
#
-# Device Drivers
+# Controllers
#
# CONFIG_IEEE1394_PCILYNX is not set
CONFIG_IEEE1394_OHCI1394=y
#
-# Protocol Drivers
+# Protocols
#
CONFIG_IEEE1394_VIDEO1394=m
CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y
CONFIG_IEEE1394_ETH1394=m
CONFIG_IEEE1394_DV1394=m
CONFIG_IEEE1394_RAWIO=y
@@ -711,10 +802,7 @@ CONFIG_IEEE1394_RAWIO=y
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
+CONFIG_MACINTOSH_DRIVERS=y
CONFIG_ADB_PMU=y
# CONFIG_ADB_PMU_LED is not set
CONFIG_PMAC_SMU=y
@@ -734,16 +822,23 @@ CONFIG_DUMMY=m
CONFIG_BONDING=m
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=m
#
-# PHY device support
+# MII PHY device drivers
#
-# CONFIG_PHYLIB is not set
+CONFIG_MARVELL_PHY=m
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+CONFIG_BROADCOM_PHY=m
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
#
# Ethernet (10 or 100Mbit)
@@ -782,10 +877,8 @@ CONFIG_E100=y
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+# CONFIG_SC92031 is not set
+CONFIG_NETDEV_1000=y
CONFIG_ACENIC=y
CONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not set
@@ -805,33 +898,37 @@ CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
CONFIG_SPIDER_NET=m
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
CONFIG_IXGB=m
# CONFIG_IXGB_NAPI is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+CONFIG_PASEMI_MAC=m
+# CONFIG_MLX4_CORE is not set
CONFIG_TR=y
CONFIG_IBMOL=y
# CONFIG_3C359 is not set
# CONFIG_TMS380TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
CONFIG_ISERIES_VETH=m
# CONFIG_FDDI is not set
@@ -851,7 +948,6 @@ CONFIG_SLHC=m
# CONFIG_SHAPER is not set
CONFIG_NETCONSOLE=y
CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
CONFIG_NETPOLL_TRAP=y
CONFIG_NET_POLL_CONTROLLER=y
@@ -870,6 +966,7 @@ CONFIG_NET_POLL_CONTROLLER=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -895,12 +992,25 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
# CONFIG_INPUT_UINPUT is not set
#
@@ -940,7 +1050,12 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_PMACZILOG is not set
CONFIG_SERIAL_ICOM=m
+CONFIG_SERIAL_TXX9=y
+CONFIG_HAS_TXX9_SERIAL=y
+CONFIG_SERIAL_TXX9_NR_UARTS=6
+CONFIG_SERIAL_TXX9_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -948,21 +1063,17 @@ CONFIG_HVC_DRIVER=y
CONFIG_HVC_CONSOLE=y
CONFIG_HVC_ISERIES=y
CONFIG_HVC_RTAS=y
+CONFIG_HVC_BEAT=y
CONFIG_HVCS=m
#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -975,11 +1086,9 @@ CONFIG_MAX_RAW_DEVS=256
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
#
@@ -1006,14 +1115,15 @@ CONFIG_I2C_POWERMAC=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -1040,37 +1150,56 @@ CONFIG_I2C_POWERMAC=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+# CONFIG_VGASTATE is not set
CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
CONFIG_FB_MACMODES=y
-# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_BACKLIGHT=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -1090,16 +1219,21 @@ CONFIG_FB_MATROX_MAVEN=m
CONFIG_FB_MATROX_MULTIHEAD=y
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_RADEON_DEBUG is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
CONFIG_FB_IBM_GXT4500=y
# CONFIG_FB_VIRTUAL is not set
@@ -1113,19 +1247,10 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_LCD_DEVICE=y
#
# Sound
@@ -1242,6 +1367,12 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m
#
# CONFIG_SND_USB_AUDIO is not set
# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
+
+#
+# System on Chip audio support
+#
+# CONFIG_SND_SOC is not set
#
# Open Sound System
@@ -1252,6 +1383,15 @@ CONFIG_SND_AOA_SOUNDBUS_I2S=m
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
#
# USB support
@@ -1266,9 +1406,8 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1278,9 +1417,12 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
@@ -1314,40 +1456,10 @@ CONFIG_USB_STORAGE=m
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
# CONFIG_USB_MON is not set
#
@@ -1369,6 +1481,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1379,6 +1492,7 @@ CONFIG_USB_APPLEDISPLAY=m
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1389,10 +1503,6 @@ CONFIG_USB_APPLEDISPLAY=m
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1417,8 +1527,11 @@ CONFIG_INFINIBAND=m
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_IPATH is not set
# CONFIG_INFINIBAND_AMSO1100 is not set
+# CONFIG_MLX4_INFINIBAND is not set
CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
CONFIG_INFINIBAND_IPOIB_DEBUG=y
# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
# CONFIG_INFINIBAND_SRP is not set
@@ -1447,10 +1560,6 @@ CONFIG_INFINIBAND_ISER=m
#
#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1567,6 +1676,7 @@ CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_RPCSEC_GSS_SPKM3=m
# CONFIG_SMB_FS is not set
@@ -1602,6 +1712,7 @@ CONFIG_MSDOS_PARTITION=y
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
#
# Native Language Support
@@ -1651,15 +1762,7 @@ CONFIG_NLS_UTF8=m
# Distributed Lock Manager
#
# CONFIG_DLM is not set
-
-#
-# iSeries device drivers
-#
-# CONFIG_VIOCONS is not set
-CONFIG_VIODASD=y
-CONFIG_VIOCD=m
-CONFIG_VIOTAPE=m
-CONFIG_VIOPATH=y
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1667,14 +1770,19 @@ CONFIG_VIOPATH=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
CONFIG_TEXTSEARCH=y
CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1693,15 +1801,15 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1711,8 +1819,10 @@ CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_LIST is not set
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_HCALL_STATS is not set
CONFIG_DEBUGGER=y
CONFIG_XMON=y
@@ -1749,8 +1859,11 @@ CONFIG_CRYPTO_TGR192=m
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1765,6 +1878,7 @@ CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_TEST=m
#
diff --git a/arch/powerpc/configs/prpmc2800_defconfig b/arch/powerpc/configs/prpmc2800_defconfig
index c70a7308200..fb504a71462 100644
--- a/arch/powerpc/configs/prpmc2800_defconfig
+++ b/arch/powerpc/configs/prpmc2800_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Wed May 9 09:42:46 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:15:11 2007
#
# CONFIG_PPC64 is not set
CONFIG_PPC32=y
@@ -90,7 +90,11 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
@@ -274,20 +278,8 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_INET6_TUNNEL is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -383,7 +375,6 @@ CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
#
# Mapping drivers for chip access
@@ -454,10 +445,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -472,6 +459,7 @@ CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -479,6 +467,7 @@ CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
@@ -588,12 +577,7 @@ CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
@@ -665,6 +649,7 @@ CONFIG_SATA_MV=y
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
@@ -683,15 +668,7 @@ CONFIG_NETDEVICES=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
CONFIG_PHYLIB=y
#
@@ -746,10 +723,7 @@ CONFIG_8139TOO=y
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
CONFIG_E1000=y
@@ -769,20 +743,14 @@ CONFIG_E1000=y
CONFIG_MV643XX_ETH=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_IXGB is not set
# CONFIG_S2IO is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_MLX4_CORE is not set
# CONFIG_TR is not set
#
@@ -792,8 +760,14 @@ CONFIG_MV643XX_ETH=y
# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -820,6 +794,7 @@ CONFIG_MV643XX_ETH=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -880,16 +855,11 @@ CONFIG_LEGACY_PTY_COUNT=256
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
# CONFIG_NVRAM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -1023,12 +993,8 @@ CONFIG_HWMON=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
# Graphics support
@@ -1124,16 +1090,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -1261,14 +1217,6 @@ CONFIG_RTC_DRV_MAX6900=y
#
#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1396,7 +1344,6 @@ CONFIG_MSDOS_PARTITION=y
#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
#
# Library routines
@@ -1404,6 +1351,7 @@ CONFIG_MSDOS_PARTITION=y
CONFIG_BITREVERSE=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_PLIST=y
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig
index 477934558f0..956d1df61e0 100644
--- a/arch/powerpc/configs/ps3_defconfig
+++ b/arch/powerpc/configs/ps3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21
-# Fri May 11 10:16:27 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:15:19 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -87,7 +87,11 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLAB=y
@@ -301,20 +305,8 @@ CONFIG_IPV6_SIT=y
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -418,10 +410,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
# Misc devices
#
# CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
# CONFIG_IDE is not set
#
@@ -467,11 +455,6 @@ CONFIG_SCSI_WAIT_SCAN=m
#
# CONFIG_ISCSI_TCP is not set
# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_ESP_CORE is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
# CONFIG_ATA is not set
#
@@ -490,27 +473,12 @@ CONFIG_NETDEVICES=y
# CONFIG_TUN is not set
#
-# PHY device support
-#
-
-#
# Ethernet (10 or 100Mbit)
#
# CONFIG_NET_ETHERNET is not set
CONFIG_MII=m
-
-#
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
#
# Wireless LAN
@@ -536,10 +504,6 @@ CONFIG_USB_NET_MCS7830=m
# CONFIG_USB_NET_RNDIS_HOST is not set
# CONFIG_USB_NET_CDC_SUBSET is not set
# CONFIG_USB_NET_ZAURUS is not set
-
-#
-# Wan interfaces
-#
# CONFIG_WAN is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
@@ -563,6 +527,7 @@ CONFIG_USB_NET_MCS7830=m
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -652,12 +617,8 @@ CONFIG_GEN_RTC=y
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
# Graphics support
@@ -672,13 +633,13 @@ CONFIG_GEN_RTC=y
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+CONFIG_FB_SYS_FOPS=y
CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
@@ -751,9 +712,10 @@ CONFIG_SND_VERBOSE_PROCFS=y
#
# CONFIG_SND_USB_AUDIO is not set
# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND_USB_CAIAQ is not set
#
-# SoC audio support
+# System on Chip audio support
#
# CONFIG_SND_SOC is not set
@@ -1098,7 +1060,6 @@ CONFIG_NLS_ISO8859_1=y
#
# CONFIG_DLM is not set
# CONFIG_UCC_SLOW is not set
-# CONFIG_UCC_FAST is not set
#
# Library routines
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 6e96e50c362..0caf0dd5ea8 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc5
-# Mon Jan 22 22:31:27 2007
+# Linux kernel version: 2.6.22-rc6
+# Tue Jun 26 14:17:45 2007
#
CONFIG_PPC64=y
CONFIG_64BIT=y
@@ -40,6 +40,7 @@ CONFIG_PPC_FPU=y
# CONFIG_PPC_OF_PLATFORM_PCI is not set
CONFIG_ALTIVEC=y
CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_MM_SLICES=y
CONFIG_VIRT_CPU_ACCOUNTING=y
CONFIG_SMP=y
CONFIG_NR_CPUS=128
@@ -60,16 +61,23 @@ CONFIG_LOCALVERSION_AUTO=y
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
# CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
# CONFIG_UTS_NS is not set
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
CONFIG_CPUSETS=y
CONFIG_SYSFS_DEPRECATED=y
# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
@@ -84,14 +92,19 @@ CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-CONFIG_SLAB=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
CONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
#
# Loadable module support
@@ -130,18 +143,28 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_EMBEDDED6xx is not set
# CONFIG_APUS is not set
CONFIG_PPC_PSERIES=y
+CONFIG_PPC_SPLPAR=y
+CONFIG_EEH=y
+CONFIG_SCANLOG=m
+CONFIG_LPARCFG=y
# CONFIG_PPC_ISERIES is not set
# CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
# CONFIG_PPC_PMAC is not set
# CONFIG_PPC_MAPLE is not set
# CONFIG_PPC_PASEMI is not set
+# CONFIG_PPC_CELLEB is not set
+# CONFIG_PPC_PS3 is not set
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
# CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_PPC_PS3 is not set
+# CONFIG_PQ2ADS is not set
CONFIG_PPC_NATIVE=y
# CONFIG_UDBG_RTAS_CONSOLE is not set
CONFIG_XICS=y
+CONFIG_MPIC=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
# CONFIG_U3_DART is not set
CONFIG_PPC_RTAS=y
CONFIG_RTAS_ERROR_LOGGING=y
@@ -155,8 +178,7 @@ CONFIG_IBMEBUS=y
# CONFIG_PPC_INDIRECT_IO is not set
# CONFIG_GENERIC_IOMAP is not set
# CONFIG_CPU_FREQ is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-CONFIG_MPIC=y
+# CONFIG_CPM2 is not set
#
# Kernel options
@@ -179,10 +201,6 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_KEXEC=y
# CONFIG_CRASH_DUMP is not set
CONFIG_IRQ_ALL_CPUS=y
-CONFIG_PPC_SPLPAR=y
-CONFIG_EEH=y
-CONFIG_SCANLOG=m
-CONFIG_LPARCFG=y
CONFIG_NUMA=y
CONFIG_NODES_SHIFT=4
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
@@ -202,35 +220,35 @@ CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_NODES_SPAN_OTHER_NODES=y
+# CONFIG_PPC_HAS_HASH_64K is not set
# CONFIG_PPC_64K_PAGES is not set
CONFIG_SCHED_SMT=y
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
CONFIG_ISA_DMA_API=y
#
# Bus options
#
+CONFIG_ZONE_DMA=y
CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-CONFIG_PPC_I8259=y
# CONFIG_PPC_INDIRECT_PCI is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+CONFIG_PCI_MSI=y
# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
CONFIG_HOTPLUG_PCI=m
# CONFIG_HOTPLUG_PCI_FAKE is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
@@ -247,14 +265,15 @@ CONFIG_NET=y
#
# Networking options
#
-# CONFIG_NETDEBUG is not set
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=m
# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -279,10 +298,6 @@ CONFIG_INET_TCP_DIAG=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
-
-#
-# IP: Virtual Server Configuration
-#
# CONFIG_IP_VS is not set
# CONFIG_IPV6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
@@ -298,10 +313,8 @@ CONFIG_NETFILTER_NETLINK=y
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NF_CONNTRACK_ENABLED=m
-CONFIG_NF_CONNTRACK_SUPPORT=y
-# CONFIG_IP_NF_CONNTRACK_SUPPORT is not set
CONFIG_NF_CONNTRACK=m
-# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CT_ACCT=y
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
# CONFIG_NF_CT_PROTO_SCTP is not set
@@ -311,10 +324,39 @@ CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_IRC=m
# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
# CONFIG_NF_CONNTRACK_SIP is not set
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_CT_NETLINK=m
-# CONFIG_NETFILTER_XTABLES is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
#
# IP: Netfilter Configuration
@@ -322,20 +364,38 @@ CONFIG_NF_CT_NETLINK=m
CONFIG_NF_CONNTRACK_IPV4=m
CONFIG_NF_CONNTRACK_PROC_COMPAT=y
CONFIG_IP_NF_QUEUE=m
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
@@ -354,6 +414,7 @@ CONFIG_LLC=y
# QoS and/or fair queueing
#
# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
#
# Network testing
@@ -363,7 +424,16 @@ CONFIG_LLC=y
# CONFIG_HAMRADIO is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
#
# Device Drivers
@@ -376,16 +446,13 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
#
# Connector - unified userspace <-> kernelspace linker
#
# CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
# CONFIG_MTD is not set
#
@@ -403,6 +470,7 @@ CONFIG_PARPORT_PC=m
#
# Plug and Play support
#
+# CONFIG_PNPACPI is not set
#
# Block devices
@@ -423,19 +491,16 @@ CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
#
# Misc devices
#
+# CONFIG_PHANTOM is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
+# CONFIG_BLINK is not set
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
@@ -450,6 +515,7 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
#
# IDE chipset support/bugfixes
@@ -457,12 +523,12 @@ CONFIG_BLK_DEV_IDECD=y
CONFIG_IDE_GENERIC=y
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
@@ -477,6 +543,7 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_JMICRON is not set
# CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
# CONFIG_BLK_DEV_IT821X is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -487,10 +554,10 @@ CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
# CONFIG_IDE_ARM is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
@@ -520,6 +587,7 @@ CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
@@ -575,11 +643,8 @@ CONFIG_SCSI_LPFC=m
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_SATA_AHCI is not set
# CONFIG_SATA_SVW is not set
# CONFIG_ATA_PIIX is not set
@@ -595,10 +660,12 @@ CONFIG_ATA=y
# CONFIG_SATA_ULI is not set
# CONFIG_SATA_VIA is not set
# CONFIG_SATA_VITESSE is not set
+# CONFIG_SATA_INIC162X is not set
# CONFIG_PATA_ALI is not set
# CONFIG_PATA_AMD is not set
# CONFIG_PATA_ARTOP is not set
# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD640_PCI is not set
# CONFIG_PATA_CMD64X is not set
# CONFIG_PATA_CS5520 is not set
# CONFIG_PATA_CS5530 is not set
@@ -610,6 +677,7 @@ CONFIG_ATA=y
# CONFIG_PATA_HPT3X2N is not set
# CONFIG_PATA_HPT3X3 is not set
# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_IT8213 is not set
# CONFIG_PATA_JMICRON is not set
# CONFIG_PATA_TRIFLEX is not set
# CONFIG_PATA_MARVELL is not set
@@ -650,6 +718,7 @@ CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_EMC=m
+# CONFIG_DM_DELAY is not set
#
# Fusion MPT device support
@@ -662,18 +731,14 @@ CONFIG_DM_MULTIPATH_EMC=m
#
# IEEE 1394 (FireWire) support
#
+# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
#
# I2O device support
#
# CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
#
# Network device support
@@ -683,15 +748,7 @@ CONFIG_DUMMY=m
CONFIG_BONDING=m
# CONFIG_EQUALIZER is not set
CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
# CONFIG_PHYLIB is not set
#
@@ -731,11 +788,9 @@ CONFIG_E100=y
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
# CONFIG_NET_POCKET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
+CONFIG_NETDEV_1000=y
CONFIG_ACENIC=y
CONFIG_ACENIC_OMIT_TIGON_I=y
# CONFIG_DL2K is not set
@@ -754,11 +809,10 @@ CONFIG_E1000=y
CONFIG_TIGON3=y
# CONFIG_BNX2 is not set
# CONFIG_QLA3XXX is not set
-
-#
-# Ethernet (10000 Mbit)
-#
+# CONFIG_ATL1 is not set
+CONFIG_NETDEV_10000=y
# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
CONFIG_EHEA=m
CONFIG_IXGB=m
# CONFIG_IXGB_NAPI is not set
@@ -766,23 +820,28 @@ CONFIG_S2IO=m
# CONFIG_S2IO_NAPI is not set
# CONFIG_MYRI10GE is not set
# CONFIG_NETXEN_NIC is not set
-
-#
-# Token Ring devices
-#
+# CONFIG_PASEMI_MAC is not set
+# CONFIG_MLX4_CORE is not set
CONFIG_TR=y
CONFIG_IBMOL=y
# CONFIG_3C359 is not set
# CONFIG_TMS380TR is not set
#
-# Wireless LAN (non-hamradio)
+# Wireless LAN
#
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
#
-# Wan interfaces
+# USB Network Adapters
#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
# CONFIG_WAN is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
@@ -802,7 +861,6 @@ CONFIG_SLHC=m
# CONFIG_SHAPER is not set
CONFIG_NETCONSOLE=y
CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
CONFIG_NETPOLL_TRAP=y
CONFIG_NET_POLL_CONTROLLER=y
@@ -821,6 +879,7 @@ CONFIG_NET_POLL_CONTROLLER=y
#
CONFIG_INPUT=y
# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
#
# Userland interfaces
@@ -846,12 +905,25 @@ CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_STOWAWAY is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PCSPKR=m
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
# CONFIG_INPUT_UINPUT is not set
#
@@ -892,6 +964,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_ICOM=m
CONFIG_SERIAL_JSM=m
+# CONFIG_SERIAL_OF_PLATFORM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -907,15 +980,10 @@ CONFIG_HVCS=m
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
# CONFIG_WATCHDOG is not set
# CONFIG_HW_RANDOM is not set
CONFIG_GEN_RTC=y
# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_AGP is not set
@@ -928,11 +996,9 @@ CONFIG_MAX_RAW_DEVS=1024
# TPM devices
#
# CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_CHARDEV is not set
#
@@ -959,14 +1025,15 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
-# CONFIG_I2C_PCA_ISA is not set
#
# Miscellaneous I2C Chip support
@@ -993,37 +1060,56 @@ CONFIG_I2C_ALGOBIT=y
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
+# CONFIG_HWMON is not set
#
-# Hardware Monitoring support
+# Multifunction device drivers
#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_DAB is not set
#
-# Digital Video Broadcasting Devices
+# Graphics support
#
-# CONFIG_DVB is not set
-# CONFIG_USB_DABUSB is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
#
-# Graphics support
+# Display device support
#
-CONFIG_FIRMWARE_EDID=y
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+# CONFIG_VGASTATE is not set
CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
CONFIG_FB_DDC=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
CONFIG_FB_MACMODES=y
-# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_BACKLIGHT=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -1042,16 +1128,21 @@ CONFIG_FB_MATROX_G=y
CONFIG_FB_MATROX_MULTIHEAD=y
CONFIG_FB_RADEON=y
CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_BACKLIGHT=y
# CONFIG_FB_RADEON_DEBUG is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
# CONFIG_FB_SAVAGE is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_KYRO is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
CONFIG_FB_IBM_GXT4500=y
# CONFIG_FB_VIRTUAL is not set
@@ -1065,19 +1156,10 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
CONFIG_LOGO=y
CONFIG_LOGO_LINUX_MONO=y
CONFIG_LOGO_LINUX_VGA16=y
CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=m
-CONFIG_BACKLIGHT_DEVICE=y
-CONFIG_LCD_CLASS_DEVICE=m
-CONFIG_LCD_DEVICE=y
#
# Sound
@@ -1088,6 +1170,15 @@ CONFIG_LCD_DEVICE=y
# HID Devices
#
CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
#
# USB support
@@ -1102,9 +1193,8 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
# CONFIG_USB_OTG is not set
#
@@ -1114,9 +1204,12 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
# CONFIG_USB_ISP116X_HCD is not set
CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
@@ -1149,40 +1242,10 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_LIBUSUAL is not set
#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_ACECAD is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_TOUCHSCREEN is not set
-# CONFIG_USB_YEALINK is not set
-# CONFIG_USB_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
-# CONFIG_USB_ATI_REMOTE2 is not set
-# CONFIG_USB_KEYSPAN_REMOTE is not set
-# CONFIG_USB_APPLETOUCH is not set
-
-#
# USB Imaging devices
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-# CONFIG_USB_USBNET_MII is not set
-# CONFIG_USB_USBNET is not set
CONFIG_USB_MON=y
#
@@ -1205,6 +1268,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
@@ -1215,6 +1279,7 @@ CONFIG_USB_MON=y
# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
#
@@ -1225,10 +1290,6 @@ CONFIG_USB_MON=y
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
# CONFIG_MMC is not set
#
@@ -1250,13 +1311,16 @@ CONFIG_USB_MON=y
CONFIG_INFINIBAND=m
CONFIG_INFINIBAND_USER_MAD=m
CONFIG_INFINIBAND_USER_ACCESS=m
+CONFIG_INFINIBAND_USER_MEM=y
CONFIG_INFINIBAND_ADDR_TRANS=y
CONFIG_INFINIBAND_MTHCA=m
CONFIG_INFINIBAND_MTHCA_DEBUG=y
+# CONFIG_INFINIBAND_IPATH is not set
CONFIG_INFINIBAND_EHCA=m
-CONFIG_INFINIBAND_EHCA_SCALING=y
# CONFIG_INFINIBAND_AMSO1100 is not set
+# CONFIG_MLX4_INFINIBAND is not set
CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_CM is not set
CONFIG_INFINIBAND_IPOIB_DEBUG=y
# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
CONFIG_INFINIBAND_SRP=m
@@ -1285,8 +1349,9 @@ CONFIG_INFINIBAND_SRP=m
#
#
-# Virtualization
+# Auxiliary Display support
#
+# CONFIG_KS0108 is not set
#
# File systems
@@ -1341,7 +1406,6 @@ CONFIG_FUSE_FS=m
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
CONFIG_UDF_FS=m
CONFIG_UDF_NLS=y
@@ -1407,6 +1471,7 @@ CONFIG_NFS_ACL_SUPPORT=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_BIND34 is not set
CONFIG_RPCSEC_GSS_KRB5=y
CONFIG_RPCSEC_GSS_SPKM3=m
# CONFIG_SMB_FS is not set
@@ -1476,6 +1541,7 @@ CONFIG_NLS_ISO8859_1=y
# Distributed Lock Manager
#
# CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
#
# Library routines
@@ -1483,12 +1549,19 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_BITREVERSE=y
CONFIG_CRC_CCITT=m
# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
#
# Instrumentation Support
@@ -1507,15 +1580,15 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_RT_MUTEX_TESTER is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_RWSEMS is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_DEBUG_KOBJECT is not set
@@ -1526,8 +1599,10 @@ CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_FORCED_INLINING=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_LKDTM is not set
+# CONFIG_FAULT_INJECTION is not set
CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_HCALL_STATS=y
CONFIG_DEBUGGER=y
CONFIG_XMON=y
@@ -1564,8 +1639,11 @@ CONFIG_CRYPTO_TGR192=m
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_PCBC=m
# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1580,6 +1658,7 @@ CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_TEST=m
#
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 068377a2a8d..c2b84c64db2 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -412,6 +412,12 @@ struct irq_map_entry irq_map[NR_IRQS];
static unsigned int irq_virq_count = NR_IRQS;
static struct irq_host *irq_default_host;
+irq_hw_number_t virq_to_hw(unsigned int virq)
+{
+ return irq_map[virq].hwirq;
+}
+EXPORT_SYMBOL_GPL(virq_to_hw);
+
struct irq_host *irq_alloc_host(unsigned int revmap_type,
unsigned int revmap_arg,
struct irq_host_ops *ops,
@@ -489,7 +495,7 @@ struct irq_host *irq_alloc_host(unsigned int revmap_type,
case IRQ_HOST_MAP_LINEAR:
rmap = (unsigned int *)(host + 1);
for (i = 0; i < revmap_arg; i++)
- rmap[i] = IRQ_NONE;
+ rmap[i] = NO_IRQ;
host->revmap_data.linear.size = revmap_arg;
smp_wmb();
host->revmap_data.linear.revmap = rmap;
@@ -614,7 +620,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
* host->ops->map() to update the flags
*/
virq = irq_find_mapping(host, hwirq);
- if (virq != IRQ_NONE) {
+ if (virq != NO_IRQ) {
if (host->ops->remap)
host->ops->remap(host, virq, hwirq);
pr_debug("irq: -> existing mapping on virq %d\n", virq);
@@ -741,7 +747,7 @@ void irq_dispose_mapping(unsigned int virq)
switch(host->revmap_type) {
case IRQ_HOST_MAP_LINEAR:
if (hwirq < host->revmap_data.linear.size)
- host->revmap_data.linear.revmap[hwirq] = IRQ_NONE;
+ host->revmap_data.linear.revmap[hwirq] = NO_IRQ;
break;
case IRQ_HOST_MAP_TREE:
/* Check if radix tree allocated yet */
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index d501c23e515..d454f61c9c7 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -433,7 +433,7 @@ static int __devinit of_pci_phb_probe(struct of_device *dev,
* Note also that we don't do ISA, this will also be fixed with a
* more massive rework.
*/
- pci_setup_phb_io(phb, 0);
+ pci_setup_phb_io(phb, pci_io_base == 0);
/* Init pci_dn data structures */
pci_devs_phb_init_dynamic(phb);
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index e66064b5093..86982112b0d 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -1047,10 +1047,10 @@ void pcibios_make_OF_bus_map(void)
#endif /* CONFIG_PPC_OF */
/* Add sysfs properties */
-void pcibios_add_platform_entries(struct pci_dev *pdev)
+int pcibios_add_platform_entries(struct pci_dev *pdev)
{
#ifdef CONFIG_PPC_OF
- device_create_file(&pdev->dev, &dev_attr_devspec);
+ return device_create_file(&pdev->dev, &dev_attr_devspec);
#endif /* CONFIG_PPC_OF */
}
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 249cca27a9b..e3009a43ac5 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -367,8 +367,10 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
dev->class = get_int_prop(node, "class-code", 0);
+ dev->revision = get_int_prop(node, "revision-id", 0);
DBG(" class: 0x%x\n", dev->class);
+ DBG(" revision: 0x%x\n", dev->revision);
dev->current_state = 4; /* unknown power state */
dev->error_state = pci_channel_io_normal;
@@ -876,9 +878,9 @@ static ssize_t pci_show_devspec(struct device *dev,
}
static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-void pcibios_add_platform_entries(struct pci_dev *pdev)
+int pcibios_add_platform_entries(struct pci_dev *pdev)
{
- device_create_file(&pdev->dev, &dev_attr_devspec);
+ return device_create_file(&pdev->dev, &dev_attr_devspec);
}
#define ISA_SPACE_MASK 0x1
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 066a6a7a25b..af42ddab3ab 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1171,11 +1171,12 @@ EXPORT_SYMBOL(of_find_node_by_name);
/**
* of_find_node_by_type - Find a node by its "device_type" property
- * @from: The node to start searching from or NULL, the node
- * you pass will not be searched, only the next one
- * will; typically, you pass what the previous call
- * returned. of_node_put() will be called on it
- * @name: The type string to match against
+ * @from: The node to start searching from, or NULL to start searching
+ * the entire device tree. The node you pass will not be
+ * searched, only the next one will; typically, you pass
+ * what the previous call returned. of_node_put() will be
+ * called on from for you.
+ * @type: The type string to match against
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index f4f391cdd8f..bf76562167c 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -218,6 +218,7 @@ set_single_step(struct task_struct *task)
regs->msr |= MSR_SE;
#endif
}
+ set_tsk_thread_flag(task, TIF_SINGLESTEP);
}
static inline void
@@ -233,6 +234,7 @@ clear_single_step(struct task_struct *task)
regs->msr &= ~MSR_SE;
#endif
}
+ clear_tsk_thread_flag(task, TIF_SINGLESTEP);
}
#endif /* CONFIG_PPC32 */
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 1ce0ae3f6ff..b27e26852fd 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -176,6 +176,13 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
*/
discard_lazy_cpu_state();
+ /*
+ * Force reload of FP/VEC.
+ * This has to be done before copying stuff into current->thread.fpr/vr
+ * for the reasons explained in the previous comment.
+ */
+ regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
+
err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
#ifdef CONFIG_ALTIVEC
@@ -197,9 +204,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
current->thread.vrsave = 0;
#endif /* CONFIG_ALTIVEC */
- /* Force reload of FP/VEC */
- regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
-
return err;
}
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 047246ad4f6..b42cbf1e2d7 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -810,3 +810,12 @@ asmlinkage long compat_sys_request_key(const char __user *_type,
return sys_request_key(_type, _description, _callout_info, destringid);
}
+asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
+ unsigned offset_hi, unsigned offset_lo,
+ unsigned nbytes_hi, unsigned nbytes_lo)
+{
+ loff_t offset = ((loff_t)offset_hi << 32) | offset_lo;
+ loff_t nbytes = ((loff_t)nbytes_hi << 32) | nbytes_lo;
+
+ return sys_sync_file_range(fd, offset, nbytes, flags);
+}
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 87703df8750..cbca1df8bc6 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -151,12 +151,18 @@ static struct console udbg_console = {
static int early_console_initialized;
-/* called by setup_system */
+/*
+ * Called by setup_system after ppc_md->probe and ppc_md->early_init.
+ * Call it again after setting udbg_putc in ppc_md->setup_arch.
+ */
void register_early_udbg_console(void)
{
if (early_console_initialized)
return;
+ if (!udbg_putc)
+ return;
+
if (strstr(boot_command_line, "udbg-immortal")) {
printk(KERN_INFO "early console immortal !\n");
udbg_console.flags &= ~CON_BOOT;
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
index 05909f75430..72ca26df457 100644
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -32,6 +32,8 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday)
mr r11,r4 /* r11 saves tz */
bl __get_datapage@local /* get data page */
mr r9, r3 /* datapage ptr in r9 */
+ cmplwi r10,0 /* check if tv is NULL */
+ beq 3f
bl __do_get_xsec@local /* get xsec from tb & kernel */
bne- 2f /* out of line -> do syscall */
@@ -50,7 +52,7 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday)
mulhwu r5,r5,r6
stw r5,TVAL32_TV_USEC(r10)
- cmpli cr0,r11,0 /* check if tz is NULL */
+3: cmplwi r11,0 /* check if tz is NULL */
beq 1f
lwz r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */
lwz r5,CFG_TZ_DSTTIME(r9)
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
index 40ffd9b6cef..c6401f9e37f 100644
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -1,5 +1,4 @@
-
- /*
+/*
* Userland implementation of gettimeofday() for 64 bits processes in a
* ppc64 kernel for use in the vDSO
*
@@ -32,6 +31,8 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday)
mr r11,r3 /* r11 holds tv */
mr r10,r4 /* r10 holds tz */
bl V_LOCAL_FUNC(__get_datapage) /* get data page */
+ cmpldi r11,0 /* check if tv is NULL */
+ beq 2f
bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
ori r7,r7,16960
@@ -43,8 +44,8 @@ V_FUNCTION_BEGIN(__kernel_gettimeofday)
* XSEC_PER_SEC
*/
rldicl r0,r0,44,20
- cmpldi cr0,r10,0 /* check if tz is NULL */
std r0,TVAL64_TV_USEC(r11) /* store usec in tv */
+2: cmpldi r10,0 /* check if tz is NULL */
beq 1f
lwz r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
lwz r5,CFG_TZ_DSTTIME(r3)
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index 180ee2933ab..2f24ea0d723 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -437,27 +437,26 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch
struct list_head *l;
rh_block_t *blk;
rh_block_t *newblk;
- unsigned long start;
+ unsigned long start, sp_size;
/* Validate size, and alignment must be power of two */
if (size <= 0 || (alignment & (alignment - 1)) != 0)
return (unsigned long) -EINVAL;
- /* given alignment larger that default rheap alignment */
- if (alignment > info->alignment)
- size += alignment - 1;
-
/* Align to configured alignment */
size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
- if (assure_empty(info, 1) < 0)
+ if (assure_empty(info, 2) < 0)
return (unsigned long) -ENOMEM;
blk = NULL;
list_for_each(l, &info->free_list) {
blk = list_entry(l, rh_block_t, list);
- if (size <= blk->size)
- break;
+ if (size <= blk->size) {
+ start = (blk->start + alignment - 1) & ~(alignment - 1);
+ if (start + size <= blk->start + blk->size)
+ break;
+ }
blk = NULL;
}
@@ -470,25 +469,36 @@ unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const ch
list_del(&blk->list);
newblk = blk;
} else {
+ /* Fragment caused, split if needed */
+ /* Create block for fragment in the beginning */
+ sp_size = start - blk->start;
+ if (sp_size) {
+ rh_block_t *spblk;
+
+ spblk = get_slot(info);
+ spblk->start = blk->start;
+ spblk->size = sp_size;
+ /* add before the blk */
+ list_add(&spblk->list, blk->list.prev);
+ }
newblk = get_slot(info);
- newblk->start = blk->start;
+ newblk->start = start;
newblk->size = size;
- /* blk still in free list, with updated start, size */
- blk->start += size;
- blk->size -= size;
+ /* blk still in free list, with updated start and size
+ * for fragment in the end */
+ blk->start = start + size;
+ blk->size -= sp_size + size;
+ /* No fragment in the end, remove blk */
+ if (blk->size == 0) {
+ list_del(&blk->list);
+ release_slot(info, blk);
+ }
}
newblk->owner = owner;
- start = newblk->start;
attach_taken_block(info, newblk);
- /* for larger alignment return fixed up pointer */
- /* this is no problem with the deallocator since */
- /* we scan for pointers that lie in the blocks */
- if (alignment > info->alignment)
- start = (start + alignment - 1) & ~(alignment - 1);
-
return start;
}
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index bfe90135314..115b25f50bf 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -279,14 +279,13 @@ good_area:
#endif /* CONFIG_8xx */
if (is_exec) {
-#ifdef CONFIG_PPC64
+#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
/* protection fault */
if (error_code & DSISR_PROTFAULT)
goto bad_area;
if (!(vma->vm_flags & VM_EXEC))
goto bad_area;
-#endif
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#else
pte_t *ptep;
pmd_t *pmdp;
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index f9ac3fe3be9..ab511d5b65a 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -67,12 +67,14 @@ static u64 MIC_Slow_Next_Timer_table[] = {
0x00003FC000000000ull,
};
+static unsigned int pmi_frequency_limit = 0;
/*
* hardware specific functions
*/
static struct of_device *pmi_dev;
+#ifdef CONFIG_PPC_PMI
static int set_pmode_pmi(int cpu, unsigned int pmode)
{
int ret;
@@ -101,7 +103,7 @@ static int set_pmode_pmi(int cpu, unsigned int pmode)
#endif
return ret;
}
-
+#endif
static int get_pmode(int cpu)
{
@@ -156,15 +158,16 @@ static int set_pmode_reg(int cpu, unsigned int pmode)
}
static int set_pmode(int cpu, unsigned int slow_mode) {
+#ifdef CONFIG_PPC_PMI
if (pmi_dev)
return set_pmode_pmi(cpu, slow_mode);
else
+#endif
return set_pmode_reg(cpu, slow_mode);
}
static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
{
- struct cpufreq_policy policy;
u8 cpu;
u8 cbe_pmode_new;
@@ -173,15 +176,27 @@ static void cbe_cpufreq_handle_pmi(struct of_device *dev, pmi_message_t pmi_msg)
cpu = cbe_node_to_cpu(pmi_msg.data1);
cbe_pmode_new = pmi_msg.data2;
- cpufreq_get_policy(&policy, cpu);
+ pmi_frequency_limit = cbe_freqs[cbe_pmode_new].frequency;
- policy.max = min(policy.max, cbe_freqs[cbe_pmode_new].frequency);
- policy.min = min(policy.min, policy.max);
+ pr_debug("cbe_handle_pmi: max freq=%d\n", pmi_frequency_limit);
+}
+
+static int pmi_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct cpufreq_policy *policy = data;
- pr_debug("cbe_handle_pmi: new policy.min=%d policy.max=%d\n", policy.min, policy.max);
- cpufreq_set_policy(&policy);
+ if (event != CPUFREQ_INCOMPATIBLE)
+ return 0;
+
+ cpufreq_verify_within_limits(policy, 0, pmi_frequency_limit);
+ return 0;
}
+static struct notifier_block pmi_notifier_block = {
+ .notifier_call = pmi_notifier,
+};
+
static struct pmi_handler cbe_pmi_handler = {
.type = PMI_TYPE_FREQ_CHANGE,
.handle_pmi_message = cbe_cpufreq_handle_pmi,
@@ -238,12 +253,21 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
+ if (pmi_dev) {
+ /* frequency might get limited later, initialize limit with max_freq */
+ pmi_frequency_limit = max_freq;
+ cpufreq_register_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+ }
+
/* this ensures that policy->cpuinfo_min and policy->cpuinfo_max are set correctly */
return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
}
static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
{
+ if (pmi_dev)
+ cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
+
cpufreq_frequency_table_put_attr(policy->cpu);
return 0;
}
@@ -302,26 +326,28 @@ static struct cpufreq_driver cbe_cpufreq_driver = {
static int __init cbe_cpufreq_init(void)
{
+#ifdef CONFIG_PPC_PMI
struct device_node *np;
-
+#endif
if (!machine_is(cell))
return -ENODEV;
-
+#ifdef CONFIG_PPC_PMI
np = of_find_node_by_type(NULL, "ibm,pmi");
pmi_dev = of_find_device_by_node(np);
if (pmi_dev)
pmi_register_handler(pmi_dev, &cbe_pmi_handler);
-
+#endif
return cpufreq_register_driver(&cbe_cpufreq_driver);
}
static void __exit cbe_cpufreq_exit(void)
{
+#ifdef CONFIG_PPC_PMI
if (pmi_dev)
pmi_unregister_handler(pmi_dev, &cbe_pmi_handler);
-
+#endif
cpufreq_unregister_driver(&cbe_cpufreq_driver);
}
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 8654749e317..7c51cb54bca 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -39,7 +39,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
if (spu_init_csa(&ctx->csa))
goto out_free;
spin_lock_init(&ctx->mmio_lock);
- spin_lock_init(&ctx->mapping_lock);
+ mutex_init(&ctx->mapping_lock);
kref_init(&ctx->kref);
mutex_init(&ctx->state_mutex);
mutex_init(&ctx->run_mutex);
@@ -103,6 +103,7 @@ void spu_forget(struct spu_context *ctx)
void spu_unmap_mappings(struct spu_context *ctx)
{
+ mutex_lock(&ctx->mapping_lock);
if (ctx->local_store)
unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1);
if (ctx->mfc)
@@ -117,6 +118,7 @@ void spu_unmap_mappings(struct spu_context *ctx)
unmap_mapping_range(ctx->mss, 0, 0x1000, 1);
if (ctx->psmap)
unmap_mapping_range(ctx->psmap, 0, 0x20000, 1);
+ mutex_unlock(&ctx->mapping_lock);
}
/**
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 45614c73c78..b1e7e2f8a2e 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -45,11 +45,11 @@ spufs_mem_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
file->private_data = ctx;
if (!i->i_openers++)
ctx->local_store = inode->i_mapping;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return 0;
}
@@ -59,10 +59,10 @@ spufs_mem_release(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->local_store = NULL;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return 0;
}
@@ -217,6 +217,7 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr,
static const struct file_operations spufs_mem_fops = {
.open = spufs_mem_open,
+ .release = spufs_mem_release,
.read = spufs_mem_read,
.write = spufs_mem_write,
.llseek = generic_file_llseek,
@@ -309,11 +310,11 @@ static int spufs_cntl_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
file->private_data = ctx;
if (!i->i_openers++)
ctx->cntl = inode->i_mapping;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return simple_attr_open(inode, file, spufs_cntl_get,
spufs_cntl_set, "0x%08lx");
}
@@ -326,10 +327,10 @@ spufs_cntl_release(struct inode *inode, struct file *file)
simple_attr_close(inode, file);
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->cntl = NULL;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return 0;
}
@@ -812,11 +813,11 @@ static int spufs_signal1_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
file->private_data = ctx;
if (!i->i_openers++)
ctx->signal1 = inode->i_mapping;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
@@ -826,10 +827,10 @@ spufs_signal1_release(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->signal1 = NULL;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return 0;
}
@@ -936,11 +937,11 @@ static int spufs_signal2_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
file->private_data = ctx;
if (!i->i_openers++)
ctx->signal2 = inode->i_mapping;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
@@ -950,10 +951,10 @@ spufs_signal2_release(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->signal2 = NULL;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return 0;
}
@@ -1154,10 +1155,10 @@ static int spufs_mss_open(struct inode *inode, struct file *file)
file->private_data = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
if (!i->i_openers++)
ctx->mss = inode->i_mapping;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
@@ -1167,10 +1168,10 @@ spufs_mss_release(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->mss = NULL;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return 0;
}
@@ -1211,11 +1212,11 @@ static int spufs_psmap_open(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
file->private_data = i->i_ctx;
if (!i->i_openers++)
ctx->psmap = inode->i_mapping;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
@@ -1225,10 +1226,10 @@ spufs_psmap_release(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->psmap = NULL;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return 0;
}
@@ -1281,11 +1282,11 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
if (atomic_read(&inode->i_count) != 1)
return -EBUSY;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
file->private_data = ctx;
if (!i->i_openers++)
ctx->mfc = inode->i_mapping;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return nonseekable_open(inode, file);
}
@@ -1295,10 +1296,10 @@ spufs_mfc_release(struct inode *inode, struct file *file)
struct spufs_inode_info *i = SPUFS_I(inode);
struct spu_context *ctx = i->i_ctx;
- spin_lock(&ctx->mapping_lock);
+ mutex_lock(&ctx->mapping_lock);
if (!--i->i_openers)
ctx->mfc = NULL;
- spin_unlock(&ctx->mapping_lock);
+ mutex_unlock(&ctx->mapping_lock);
return 0;
}
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 7150730e2ff..9807206e021 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -177,7 +177,7 @@ static int spufs_rmdir(struct inode *parent, struct dentry *dir)
static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
int mode, struct spu_context *ctx)
{
- struct dentry *dentry;
+ struct dentry *dentry, *tmp;
int ret;
while (files->name && files->name[0]) {
@@ -193,7 +193,20 @@ static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files,
}
return 0;
out:
- spufs_prune_dir(dir);
+ /*
+ * remove all children from dir. dir->inode is not set so don't
+ * just simply use spufs_prune_dir() and panic afterwards :)
+ * dput() looks like it will do the right thing:
+ * - dec parent's ref counter
+ * - remove child from parent's child list
+ * - free child's inode if possible
+ * - free child
+ */
+ list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
+ dput(dentry);
+ }
+
+ shrink_dcache_parent(dir);
return ret;
}
@@ -274,6 +287,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags,
goto out;
out_free_ctx:
+ spu_forget(ctx);
put_spu_context(ctx);
out_iput:
iput(inode);
@@ -349,37 +363,6 @@ out:
return ret;
}
-static int spufs_rmgang(struct inode *root, struct dentry *dir)
-{
- /* FIXME: this fails if the dir is not empty,
- which causes a leak of gangs. */
- return simple_rmdir(root, dir);
-}
-
-static int spufs_gang_close(struct inode *inode, struct file *file)
-{
- struct inode *parent;
- struct dentry *dir;
- int ret;
-
- dir = file->f_path.dentry;
- parent = dir->d_parent->d_inode;
-
- ret = spufs_rmgang(parent, dir);
- WARN_ON(ret);
-
- return dcache_dir_close(inode, file);
-}
-
-const struct file_operations spufs_gang_fops = {
- .open = dcache_dir_open,
- .release = spufs_gang_close,
- .llseek = dcache_dir_lseek,
- .read = generic_read_dir,
- .readdir = dcache_readdir,
- .fsync = simple_sync_file,
-};
-
static int
spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
{
@@ -407,7 +390,6 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
inode->i_fop = &simple_dir_operations;
d_instantiate(dentry, inode);
- dget(dentry);
dir->i_nlink++;
dentry->d_inode->i_nlink++;
return ret;
@@ -437,7 +419,7 @@ static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
goto out;
}
- filp->f_op = &spufs_gang_fops;
+ filp->f_op = &simple_dir_operations;
fd_install(ret, filp);
out:
return ret;
@@ -458,8 +440,10 @@ static int spufs_create_gang(struct inode *inode,
* in error path of *_open().
*/
ret = spufs_gang_open(dget(dentry), mntget(mnt));
- if (ret < 0)
- WARN_ON(spufs_rmgang(inode, dentry));
+ if (ret < 0) {
+ int err = simple_rmdir(inode, dentry);
+ WARN_ON(err);
+ }
out:
mutex_unlock(&inode->i_mutex);
@@ -600,6 +584,10 @@ spufs_create_root(struct super_block *sb, void *data)
struct inode *inode;
int ret;
+ ret = -ENODEV;
+ if (!spu_management_ops)
+ goto out;
+
ret = -ENOMEM;
inode = spufs_new_inode(sb, S_IFDIR | 0775);
if (!inode)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index b6ecb30e7d5..3b831e07f1e 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -93,43 +93,6 @@ void spu_stop_tick(struct spu_context *ctx)
}
}
-void spu_sched_tick(struct work_struct *work)
-{
- struct spu_context *ctx =
- container_of(work, struct spu_context, sched_work.work);
- struct spu *spu;
- int preempted = 0;
-
- /*
- * If this context is being stopped avoid rescheduling from the
- * scheduler tick because we would block on the state_mutex.
- * The caller will yield the spu later on anyway.
- */
- if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
- return;
-
- mutex_lock(&ctx->state_mutex);
- spu = ctx->spu;
- if (spu) {
- int best = sched_find_first_bit(spu_prio->bitmap);
- if (best <= ctx->prio) {
- spu_deactivate(ctx);
- preempted = 1;
- }
- }
- mutex_unlock(&ctx->state_mutex);
-
- if (preempted) {
- /*
- * We need to break out of the wait loop in spu_run manually
- * to ensure this context gets put on the runqueue again
- * ASAP.
- */
- wake_up(&ctx->stop_wq);
- } else
- spu_start_tick(ctx);
-}
-
/**
* spu_add_to_active_list - add spu to active list
* @spu: spu to add to the active list
@@ -273,34 +236,6 @@ static void spu_prio_wait(struct spu_context *ctx)
remove_wait_queue(&ctx->stop_wq, &wait);
}
-/**
- * spu_reschedule - try to find a runnable context for a spu
- * @spu: spu available
- *
- * This function is called whenever a spu becomes idle. It looks for the
- * most suitable runnable spu context and schedules it for execution.
- */
-static void spu_reschedule(struct spu *spu)
-{
- int best;
-
- spu_free(spu);
-
- spin_lock(&spu_prio->runq_lock);
- best = sched_find_first_bit(spu_prio->bitmap);
- if (best < MAX_PRIO) {
- struct list_head *rq = &spu_prio->runq[best];
- struct spu_context *ctx;
-
- BUG_ON(list_empty(rq));
-
- ctx = list_entry(rq->next, struct spu_context, rq);
- __spu_del_from_rq(ctx);
- wake_up(&ctx->stop_wq);
- }
- spin_unlock(&spu_prio->runq_lock);
-}
-
static struct spu *spu_get_idle(struct spu_context *ctx)
{
struct spu *spu = NULL;
@@ -429,6 +364,51 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
}
/**
+ * grab_runnable_context - try to find a runnable context
+ *
+ * Remove the highest priority context on the runqueue and return it
+ * to the caller. Returns %NULL if no runnable context was found.
+ */
+static struct spu_context *grab_runnable_context(int prio)
+{
+ struct spu_context *ctx = NULL;
+ int best;
+
+ spin_lock(&spu_prio->runq_lock);
+ best = sched_find_first_bit(spu_prio->bitmap);
+ if (best < prio) {
+ struct list_head *rq = &spu_prio->runq[best];
+
+ BUG_ON(list_empty(rq));
+
+ ctx = list_entry(rq->next, struct spu_context, rq);
+ __spu_del_from_rq(ctx);
+ }
+ spin_unlock(&spu_prio->runq_lock);
+
+ return ctx;
+}
+
+static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
+{
+ struct spu *spu = ctx->spu;
+ struct spu_context *new = NULL;
+
+ if (spu) {
+ new = grab_runnable_context(max_prio);
+ if (new || force) {
+ spu_unbind_context(spu, ctx);
+ spu_free(spu);
+ if (new)
+ wake_up(&new->stop_wq);
+ }
+
+ }
+
+ return new != NULL;
+}
+
+/**
* spu_deactivate - unbind a context from it's physical spu
* @ctx: spu context to unbind
*
@@ -437,12 +417,7 @@ int spu_activate(struct spu_context *ctx, unsigned long flags)
*/
void spu_deactivate(struct spu_context *ctx)
{
- struct spu *spu = ctx->spu;
-
- if (spu) {
- spu_unbind_context(spu, ctx);
- spu_reschedule(spu);
- }
+ __spu_deactivate(ctx, 1, MAX_PRIO);
}
/**
@@ -455,21 +430,43 @@ void spu_deactivate(struct spu_context *ctx)
*/
void spu_yield(struct spu_context *ctx)
{
- struct spu *spu;
-
- if (mutex_trylock(&ctx->state_mutex)) {
- if ((spu = ctx->spu) != NULL) {
- int best = sched_find_first_bit(spu_prio->bitmap);
- if (best < MAX_PRIO) {
- pr_debug("%s: yielding SPU %d NODE %d\n",
- __FUNCTION__, spu->number, spu->node);
- spu_deactivate(ctx);
- }
- }
+ if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
+ mutex_lock(&ctx->state_mutex);
+ __spu_deactivate(ctx, 0, MAX_PRIO);
mutex_unlock(&ctx->state_mutex);
}
}
+void spu_sched_tick(struct work_struct *work)
+{
+ struct spu_context *ctx =
+ container_of(work, struct spu_context, sched_work.work);
+ int preempted;
+
+ /*
+ * If this context is being stopped avoid rescheduling from the
+ * scheduler tick because we would block on the state_mutex.
+ * The caller will yield the spu later on anyway.
+ */
+ if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags))
+ return;
+
+ mutex_lock(&ctx->state_mutex);
+ preempted = __spu_deactivate(ctx, 0, ctx->prio + 1);
+ mutex_unlock(&ctx->state_mutex);
+
+ if (preempted) {
+ /*
+ * We need to break out of the wait loop in spu_run manually
+ * to ensure this context gets put on the runqueue again
+ * ASAP.
+ */
+ wake_up(&ctx->stop_wq);
+ } else {
+ spu_start_tick(ctx);
+ }
+}
+
int __init spu_sched_init(void)
{
int i;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 0a947fd7de5..47617e8014a 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -55,7 +55,7 @@ struct spu_context {
struct address_space *signal2; /* 'signal2' area mappings. */
struct address_space *mss; /* 'mss' area mappings. */
struct address_space *psmap; /* 'psmap' area mappings. */
- spinlock_t mapping_lock;
+ struct mutex mapping_lock;
u64 object_id; /* user space pointer for oprofile */
enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state;
diff --git a/arch/powerpc/platforms/celleb/Makefile b/arch/powerpc/platforms/celleb/Makefile
index f4f82520dc4..5240046d867 100644
--- a/arch/powerpc/platforms/celleb/Makefile
+++ b/arch/powerpc/platforms/celleb/Makefile
@@ -4,5 +4,5 @@ obj-y += interrupt.o iommu.o setup.o \
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PPC_UDBG_BEAT) += udbg_beat.o
-obj-$(CONFIG_HAS_TXX9_SERIAL) += scc_sio.o
+obj-$(CONFIG_SERIAL_TXX9) += scc_sio.o
obj-$(CONFIG_SPU_BASE) += spu_priv1.o
diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c
index 03cd45d8fef..3c962d5757b 100644
--- a/arch/powerpc/platforms/pasemi/idle.c
+++ b/arch/powerpc/platforms/pasemi/idle.c
@@ -26,6 +26,7 @@
#include <asm/machdep.h>
#include <asm/reg.h>
+#include <asm/smp.h>
#include "pasemi.h"
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 95fa6a7d15e..f33b21b9f5d 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -31,8 +31,6 @@
#define IOBMAP_PAGE_SIZE (1 << IOBMAP_PAGE_SHIFT)
#define IOBMAP_PAGE_MASK (IOBMAP_PAGE_SIZE - 1)
-#define IOBMAP_PAGE_FACTOR (PAGE_SHIFT - IOBMAP_PAGE_SHIFT)
-
#define IOB_BASE 0xe0000000
#define IOB_SIZE 0x3000
/* Configuration registers */
@@ -97,9 +95,6 @@ static void iobmap_build(struct iommu_table *tbl, long index,
bus_addr = (tbl->it_offset + index) << PAGE_SHIFT;
- npages <<= IOBMAP_PAGE_FACTOR;
- index <<= IOBMAP_PAGE_FACTOR;
-
ip = ((u32 *)tbl->it_base) + index;
while (npages--) {
@@ -125,9 +120,6 @@ static void iobmap_free(struct iommu_table *tbl, long index,
bus_addr = (tbl->it_offset + index) << PAGE_SHIFT;
- npages <<= IOBMAP_PAGE_FACTOR;
- index <<= IOBMAP_PAGE_FACTOR;
-
ip = ((u32 *)tbl->it_base) + index;
while (npages--) {
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 07b1c4ec428..7ccb9236e8b 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -363,8 +363,19 @@ static void __init pmac_setup_arch(void)
smp_ops = &core99_smp_ops;
}
#ifdef CONFIG_PPC32
- else
+ else {
+ /*
+ * We have to set bits in cpu_possible_map here since the
+ * secondary CPU(s) aren't in the device tree, and
+ * setup_per_cpu_areas only allocates per-cpu data for
+ * CPUs in the cpu_possible_map.
+ */
+ int cpu;
+
+ for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu)
+ cpu_set(cpu, cpu_possible_map);
smp_ops = &psurge_smp_ops;
+ }
#endif
#endif /* CONFIG_SMP */
@@ -443,6 +454,9 @@ static int initializing = 1;
static int pmac_late_init(void)
{
+ if (!machine_is(powermac))
+ return -ENODEV;
+
initializing = 0;
/* this is udbg (which is __init) and we can later use it during
* cpu hotplug (in smp_core99_kick_cpu) */
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 686ed82bde7..cb2d894541c 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -317,7 +317,6 @@ static int __init smp_psurge_probe(void)
ncpus = NR_CPUS;
for (i = 1; i < ncpus ; ++i) {
cpu_set(i, cpu_present_map);
- cpu_set(i, cpu_possible_map);
set_hard_smp_processor_id(i, i);
}
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 9da82c266ba..ec9030dbb5f 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -25,6 +25,7 @@
#include <asm/machdep.h>
#include <asm/udbg.h>
#include <asm/lv1call.h>
+#include <asm/smp.h>
#include "platform.h"
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 470db6efaeb..a031d99becb 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -176,7 +176,7 @@ static void __init pseries_mpic_init_IRQ(void)
return;
cascade_irq = irq_of_parse_and_map(cascade, 0);
- if (cascade == NO_IRQ) {
+ if (cascade_irq == NO_IRQ) {
printk(KERN_ERR "mpic: failed to map cascade interrupt");
return;
}
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index b854e7f1001..f1df942072b 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -752,6 +752,7 @@ skip_gserver_check:
void xics_request_IPIs(void)
{
unsigned int ipi;
+ int rc;
ipi = irq_create_mapping(xics_host, XICS_IPI);
BUG_ON(ipi == NO_IRQ);
@@ -762,11 +763,12 @@ void xics_request_IPIs(void)
*/
set_irq_handler(ipi, handle_percpu_irq);
if (firmware_has_feature(FW_FEATURE_LPAR))
- request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
- "IPI", NULL);
+ rc = request_irq(ipi, xics_ipi_action_lpar, IRQF_DISABLED,
+ "IPI", NULL);
else
- request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
- "IPI", NULL);
+ rc = request_irq(ipi, xics_ipi_action_direct, IRQF_DISABLED,
+ "IPI", NULL);
+ BUG_ON(rc);
}
#endif /* CONFIG_SMP */
diff --git a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c
index 4c0a7d732f6..615b6583d9b 100644
--- a/arch/ppc/8260_io/enet.c
+++ b/arch/ppc/8260_io/enet.c
@@ -477,9 +477,9 @@ for (;;) {
}
else {
skb_put(skb,pkt_len-4); /* Make room */
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
(unsigned char *)__va(bdp->cbd_bufaddr),
- pkt_len-4, 0);
+ pkt_len-4);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index cab395da25d..6f3ed6a72e0 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -734,9 +734,9 @@ for (;;) {
}
else {
skb_put(skb,pkt_len); /* Make room */
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
(unsigned char *)__va(bdp->cbd_bufaddr),
- pkt_len, 0);
+ pkt_len);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index e58288e1436..703d47eee43 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -506,9 +506,9 @@ for (;;) {
}
else {
skb_put(skb,pkt_len-4); /* Make room */
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
cep->rx_vaddr[bdp - cep->rx_bd_base],
- pkt_len-4, 0);
+ pkt_len-4);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
diff --git a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c
index d38335d2d71..0288279be9a 100644
--- a/arch/ppc/8xx_io/fec.c
+++ b/arch/ppc/8xx_io/fec.c
@@ -725,7 +725,7 @@ while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) {
fep->stats.rx_dropped++;
} else {
skb_put(skb,pkt_len-4); /* Make room */
- eth_copy_and_sum(skb, data, pkt_len-4, 0);
+ skb_copy_to_linear_data(skb, data, pkt_len-4);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index ccce2a4a152..6bdeeb70b15 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -1237,8 +1237,10 @@ config PCI
infrastructure code to support PCI bus devices.
config PCI_DOMAINS
- bool
- default PCI
+ def_bool PCI
+
+config PCI_SYSCALL
+ def_bool PCI
config MPC83xx_PCI2
bool "Support for 2nd PCI host controller"
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 5e723c4c257..c2ec13bea00 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -633,12 +633,6 @@ void pcibios_make_OF_bus_map(void)
{
}
-/* Add sysfs properties */
-void pcibios_add_platform_entries(struct pci_dev *pdev)
-{
-}
-
-
static int __init
pcibios_init(void)
{
diff --git a/arch/ppc/syslib/ibm_ocp.c b/arch/ppc/syslib/ibm_ocp.c
index 3f6e55c7918..2ee176610e7 100644
--- a/arch/ppc/syslib/ibm_ocp.c
+++ b/arch/ppc/syslib/ibm_ocp.c
@@ -1,4 +1,5 @@
#include <linux/module.h>
+#include <asm/ibm4xx.h>
#include <asm/ocp.h>
struct ocp_sys_info_data ocp_sys_info = {
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
index 8485a68cd47..032f4b7f422 100644
--- a/arch/ppc/syslib/mv64x60.c
+++ b/arch/ppc/syslib/mv64x60.c
@@ -2415,7 +2415,6 @@ static struct bin_attribute mv64xxx_hs_reg_attr = { /* Hotswap register */
.attr = {
.name = "hs_reg",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = VAL_LEN_MAX,
.read = mv64xxx_hs_reg_read,
diff --git a/arch/ppc/syslib/qspan_pci.c b/arch/ppc/syslib/qspan_pci.c
index 85053b2816a..7a97c7440b3 100644
--- a/arch/ppc/syslib/qspan_pci.c
+++ b/arch/ppc/syslib/qspan_pci.c
@@ -365,13 +365,13 @@ int qspan_pcibios_find_class(unsigned int class_code, unsigned short index,
}
void __init
-m8xx_pcibios_fixup(void))
+m8xx_pcibios_fixup(void)
{
/* Lots to do here, all board and configuration specific. */
}
void __init
-m8xx_setup_pci_ptrs(void))
+m8xx_setup_pci_ptrs(void)
{
set_config_access_method(qspan);
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 68441e0e74b..143ed8e154a 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -19,7 +19,7 @@ CFLAGS += -m31
AFLAGS += -m31
UTS_MACHINE := s390
STACK_SIZE := 8192
-CHECKFLAGS += -D__s390__
+CHECKFLAGS += -D__s390__ -msize-long
else
LDFLAGS := -m elf64_s390
MODFLAGS += -fpic -D__PIC__
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 81a2b92ab0c..6ffbab77ae4 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -535,8 +535,7 @@ void appldata_unregister_ops(struct appldata_ops *ops)
/******************************* init / exit *********************************/
-static void
-appldata_online_cpu(int cpu)
+static void __cpuinit appldata_online_cpu(int cpu)
{
init_virt_timer(&per_cpu(appldata_timer, cpu));
per_cpu(appldata_timer, cpu).function = appldata_timer_function;
@@ -580,7 +579,7 @@ appldata_cpu_notify(struct notifier_block *self,
return NOTIFY_OK;
}
-static struct notifier_block appldata_nb = {
+static struct notifier_block __cpuinitdata appldata_nb = {
.notifier_call = appldata_cpu_notify,
};
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index 2775d261833..95f5160df27 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -24,7 +24,7 @@
#define CRYPT_S390_PRIORITY 300
#define CRYPT_S390_COMPOSITE_PRIORITY 400
-/* s930 cryptographic operations */
+/* s390 cryptographic operations */
enum crypt_s390_operations {
CRYPT_S390_KM = 0x0100,
CRYPT_S390_KMC = 0x0200,
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 2782cf9da5b..b9a1ce1f28e 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -481,9 +481,17 @@ out:
/* Diagnose 224 functions */
-static void diag224(void *ptr)
+static int diag224(void *ptr)
{
- asm volatile("diag %0,%1,0x224" : :"d" (0), "d"(ptr) : "memory");
+ int rc = -ENOTSUPP;
+
+ asm volatile(
+ " diag %1,%2,0x224\n"
+ "0: lhi %0,0x0\n"
+ "1:\n"
+ EX_TABLE(0b,1b)
+ : "+d" (rc) :"d" (0), "d" (ptr) : "memory");
+ return rc;
}
static int diag224_get_name_table(void)
@@ -492,7 +500,10 @@ static int diag224_get_name_table(void)
diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
if (!diag224_cpu_names)
return -ENOMEM;
- diag224(diag224_cpu_names);
+ if (diag224(diag224_cpu_names)) {
+ kfree(diag224_cpu_names);
+ return -ENOTSUPP;
+ }
EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
return 0;
}
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index dca6eaf82c8..1b2f5ce4532 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -163,7 +163,7 @@ unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
static debug_info_t *debug_area_first = NULL;
static debug_info_t *debug_area_last = NULL;
-static DECLARE_MUTEX(debug_lock);
+static DEFINE_MUTEX(debug_mutex);
static int initialized;
@@ -576,7 +576,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
int rc = 0;
file_private_info_t *p_info;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
p_info = ((file_private_info_t *) file->private_data);
if (p_info->view->input_proc)
rc = p_info->view->input_proc(p_info->debug_info_org,
@@ -584,7 +584,7 @@ debug_input(struct file *file, const char __user *user_buf, size_t length,
length, offset);
else
rc = -EPERM;
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc; /* number of input characters */
}
@@ -602,7 +602,7 @@ debug_open(struct inode *inode, struct file *file)
file_private_info_t *p_info;
debug_info_t *debug_info, *debug_info_snapshot;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_info = file->f_path.dentry->d_inode->i_private;
/* find debug view */
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
@@ -653,7 +653,7 @@ found:
file->private_data = p_info;
debug_info_get(debug_info);
out:
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
@@ -688,7 +688,7 @@ debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
if (!initialized)
BUG();
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
/* create new debug_info */
@@ -702,7 +702,7 @@ out:
if (!rc){
printk(KERN_ERR "debug: debug_register failed for %s\n",name);
}
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
@@ -716,9 +716,9 @@ debug_unregister(debug_info_t * id)
{
if (!id)
goto out;
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_info_put(id);
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
out:
return;
@@ -1054,11 +1054,11 @@ __init debug_init(void)
int rc = 0;
s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
- down(&debug_lock);
+ mutex_lock(&debug_mutex);
debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
printk(KERN_INFO "debug: Initialization complete\n");
initialized = 1;
- up(&debug_lock);
+ mutex_unlock(&debug_mutex);
return rc;
}
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 50538e54561..e6289ee74ec 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -171,37 +171,6 @@ static inline int memory_fast_detect(void)
}
#endif
-#define ADDR2G (1UL << 31)
-
-static noinline __init unsigned long sclp_memory_detect(void)
-{
- struct sclp_readinfo_sccb *sccb;
- unsigned long long memsize;
-
- sccb = &s390_readinfo_sccb;
-
- if (sccb->header.response_code != 0x10)
- return 0;
-
- if (sccb->rnsize)
- memsize = sccb->rnsize << 20;
- else
- memsize = sccb->rnsize2 << 20;
- if (sccb->rnmax)
- memsize *= sccb->rnmax;
- else
- memsize *= sccb->rnmax2;
-#ifndef CONFIG_64BIT
- /*
- * Can't deal with more than 2G in 31 bit addressing mode, so
- * limit the value in order to avoid strange side effects.
- */
- if (memsize > ADDR2G)
- memsize = ADDR2G;
-#endif
- return (unsigned long) memsize;
-}
-
static inline __init unsigned long __tprot(unsigned long addr)
{
int cc = -1;
@@ -218,6 +187,7 @@ static inline __init unsigned long __tprot(unsigned long addr)
/* Checking memory in 128KB increments. */
#define CHUNK_INCR (1UL << 17)
+#define ADDR2G (1UL << 31)
static noinline __init void find_memory_chunks(unsigned long memsize)
{
@@ -293,7 +263,7 @@ static noinline __init void setup_lowcore_early(void)
*/
void __init startup_init(void)
{
- unsigned long memsize;
+ unsigned long long memsize;
ipl_save_parameters();
clear_bss_section();
@@ -305,8 +275,17 @@ void __init startup_init(void)
sort_main_extable();
setup_lowcore_early();
sclp_readinfo_early();
+ sclp_facilities_detect();
memsize = sclp_memory_detect();
+#ifndef CONFIG_64BIT
+ /*
+ * Can't deal with more than 2G in 31 bit addressing mode, so
+ * limit the value in order to avoid strange side effects.
+ */
+ if (memsize > ADDR2G)
+ memsize = ADDR2G;
+#endif
if (memory_fast_detect() < 0)
- find_memory_chunks(memsize);
+ find_memory_chunks((unsigned long) memsize);
lockdep_on();
}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index c8a2212014e..bc7ff3658c3 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -107,6 +107,11 @@ STACK_SIZE = 1 << STACK_SHIFT
l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13
.endm
+ .macro SAVE_ALL_SVC psworg,savearea
+ la %r12,\psworg
+ l %r15,__LC_KERNEL_STACK # problem state -> load ksp
+ .endm
+
.macro SAVE_ALL_SYNC psworg,savearea
la %r12,\psworg
tm \psworg+1,0x01 # test problem state bit
@@ -218,7 +223,7 @@ system_call:
STORE_TIMER __LC_SYNC_ENTER_TIMER
sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
- SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+ SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
lh %r7,0x8a # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -769,10 +774,13 @@ mcck_return:
RESTORE_ALL __LC_RETURN_MCCK_PSW,0
-#ifdef CONFIG_SMP
/*
* Restart interruption handler, kick starter for additional CPUs
*/
+#ifdef CONFIG_SMP
+#ifndef CONFIG_HOTPLUG_CPU
+ .section .init.text,"ax"
+#endif
.globl restart_int_handler
restart_int_handler:
l %r15,__LC_SAVE_AREA+60 # load ksp
@@ -785,6 +793,9 @@ restart_int_handler:
br %r14 # branch to start_secondary
restart_addr:
.long start_secondary
+#ifndef CONFIG_HOTPLUG_CPU
+ .previous
+#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 93745fd8f55..2a7b1304418 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -99,6 +99,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \
larl %r13,system_call
.endm
+ .macro SAVE_ALL_SVC psworg,savearea
+ la %r12,\psworg
+ lg %r15,__LC_KERNEL_STACK # problem state -> load ksp
+ .endm
+
.macro SAVE_ALL_SYNC psworg,savearea
la %r12,\psworg
tm \psworg+1,0x01 # test problem state bit
@@ -207,7 +212,7 @@ system_call:
STORE_TIMER __LC_SYNC_ENTER_TIMER
sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
- SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
+ SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA
CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -745,10 +750,13 @@ mcck_return:
#endif
lpswe __LC_RETURN_MCCK_PSW # back to caller
-#ifdef CONFIG_SMP
/*
* Restart interruption handler, kick starter for additional CPUs
*/
+#ifdef CONFIG_SMP
+#ifndef CONFIG_HOTPLUG_CPU
+ .section .init.text,"ax"
+#endif
.globl restart_int_handler
restart_int_handler:
lg %r15,__LC_SAVE_AREA+120 # load ksp
@@ -759,6 +767,9 @@ restart_int_handler:
lmg %r6,%r15,__SF_GPRS(%r15) # load registers from clone
stosm __SF_EMPTY(%r15),0x04 # now we can turn dat on
jg start_secondary
+#ifndef CONFIG_HOTPLUG_CPU
+ .previous
+#endif
#else
/*
* If we do not run with SMP enabled, let the new CPU crash ...
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 367caf92ea7..8b8f136d9cc 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -25,10 +25,6 @@
#define IPL_PARM_BLOCK_VERSION 0
-#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
-#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
-#define SCCB_FLAG (s390_readinfo_sccb.flags)
-
#define IPL_UNKNOWN_STR "unknown"
#define IPL_CCW_STR "ccw"
#define IPL_FCP_STR "fcp"
@@ -146,6 +142,8 @@ static struct ipl_parameter_block *dump_block_ccw;
static enum shutdown_action on_panic_action = SHUTDOWN_STOP;
+static struct sclp_ipl_info sclp_ipl_info;
+
int diag308(unsigned long subcode, void *addr)
{
register unsigned long _addr asm("0") = (unsigned long) addr;
@@ -297,8 +295,8 @@ static ssize_t sys_ipl_device_show(struct kset *kset, char *page)
static struct subsys_attribute sys_ipl_device_attr =
__ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
-static ssize_t ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
{
unsigned int size = IPL_PARMBLOCK_SIZE;
@@ -314,14 +312,13 @@ static struct bin_attribute ipl_parameter_attr = {
.attr = {
.name = "binary_parameter",
.mode = S_IRUGO,
- .owner = THIS_MODULE,
},
.size = PAGE_SIZE,
.read = &ipl_parameter_read,
};
-static ssize_t ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
{
unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
@@ -338,10 +335,9 @@ static struct bin_attribute ipl_scp_data_attr = {
.attr = {
.name = "scp_data",
.mode = S_IRUGO,
- .owner = THIS_MODULE,
},
.size = PAGE_SIZE,
- .read = &ipl_scp_data_read,
+ .read = ipl_scp_data_read,
};
/* FCP ipl device attributes */
@@ -375,9 +371,9 @@ static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
{
char loadparm[LOADPARM_LEN + 1] = {};
- if (!SCCB_VALID)
+ if (!sclp_ipl_info.is_valid)
return sprintf(page, "#unknown#\n");
- memcpy(loadparm, SCCB_LOADPARM, LOADPARM_LEN);
+ memcpy(loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
EBCASC(loadparm, LOADPARM_LEN);
strstrip(loadparm);
return sprintf(page, "%s\n", loadparm);
@@ -910,9 +906,9 @@ static int __init reipl_ccw_init(void)
reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
/* check if read scp info worked and set loadparm */
- if (SCCB_VALID)
+ if (sclp_ipl_info.is_valid)
memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
- SCCB_LOADPARM, LOADPARM_LEN);
+ &sclp_ipl_info.loadparm, LOADPARM_LEN);
else
/* read scp info failed: set empty loadparm (EBCDIC blanks) */
memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
@@ -1007,7 +1003,7 @@ static int __init dump_fcp_init(void)
{
int rc;
- if(!(SCCB_FLAG & 0x2) || !SCCB_VALID)
+ if (!sclp_ipl_info.has_dump)
return 0; /* LDIPL DUMP is not installed */
if (!diag308_set_works)
return 0;
@@ -1088,6 +1084,7 @@ static int __init s390_ipl_init(void)
{
int rc;
+ sclp_get_ipl_info(&sclp_ipl_info);
reipl_probe();
rc = ipl_init();
if (rc)
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index eb43c3b3126..441975b796f 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -93,8 +93,8 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
/* disable monitor call class 0 */
__ctl_clear_bit(8, 15);
- atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE,
- (void *)(long) smp_processor_id());
+ atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
+ (void *)(long) smp_processor_id());
}
extern void s390_handle_mcck(void);
@@ -115,7 +115,7 @@ static void default_idle(void)
}
rc = atomic_notifier_call_chain(&idle_chain,
- CPU_IDLE, (void *)(long) cpu);
+ S390_CPU_IDLE, (void *)(long) cpu);
if (rc != NOTIFY_OK && rc != NOTIFY_DONE)
BUG();
if (rc != NOTIFY_OK) {
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 6bfb0889eb1..7e1bfb98406 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -102,7 +102,7 @@ static struct resource data_resource = {
/*
* cpu_init() initializes state that is per-CPU.
*/
-void __devinit cpu_init (void)
+void __cpuinit cpu_init(void)
{
int addr = hard_smp_processor_id();
@@ -300,6 +300,7 @@ static void __init setup_zfcpdump(unsigned int console_devno)
else
sprintf(str, "cio_ignore=all,!0.0.%04x",
ipl_info.data.fcp.dev_id.devno);
+ strcat(COMMAND_LINE, " ");
strcat(COMMAND_LINE, str);
console_loglevel = 2;
}
@@ -915,7 +916,7 @@ setup_arch(char **cmdline_p)
setup_zfcpdump(console_devno);
}
-void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+void __cpuinit print_cpu_info(struct cpuinfo_S390 *cpuinfo)
{
printk("cpu %d "
#ifdef CONFIG_SMP
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 09f028a3266..182c085ae4d 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -410,58 +410,40 @@ EXPORT_SYMBOL(smp_ctl_clear_bit);
unsigned int zfcpdump_prefix_array[NR_CPUS + 1] \
__attribute__((__section__(".data")));
-static void __init smp_get_save_areas(void)
+static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
{
- unsigned int cpu, cpu_num, rc;
- __u16 boot_cpu_addr;
-
if (ipl_info.type != IPL_TYPE_FCP_DUMP)
return;
- boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
- cpu_num = 1;
- for (cpu = 0; cpu <= 65535; cpu++) {
- if ((u16) cpu == boot_cpu_addr)
- continue;
- __cpu_logical_map[1] = (__u16) cpu;
- if (signal_processor(1, sigp_sense) == sigp_not_operational)
- continue;
- if (cpu_num >= NR_CPUS) {
- printk("WARNING: Registers for cpu %i are not "
- "saved, since dump kernel was compiled with"
- "NR_CPUS=%i!\n", cpu_num, NR_CPUS);
- continue;
- }
- zfcpdump_save_areas[cpu_num] =
- alloc_bootmem(sizeof(union save_area));
- while (1) {
- rc = signal_processor(1, sigp_stop_and_store_status);
- if (rc != sigp_busy)
- break;
- cpu_relax();
- }
- memcpy(zfcpdump_save_areas[cpu_num],
- (void *)(unsigned long) store_prefix() +
- SAVE_AREA_BASE, SAVE_AREA_SIZE);
-#ifdef __s390x__
- /* copy original prefix register */
- zfcpdump_save_areas[cpu_num]->s390x.pref_reg =
- zfcpdump_prefix_array[cpu_num];
-#endif
- cpu_num++;
+ if (cpu >= NR_CPUS) {
+ printk(KERN_WARNING "Registers for cpu %i not saved since dump "
+ "kernel was compiled with NR_CPUS=%i\n", cpu, NR_CPUS);
+ return;
}
+ zfcpdump_save_areas[cpu] = alloc_bootmem(sizeof(union save_area));
+ __cpu_logical_map[1] = (__u16) phy_cpu;
+ while (signal_processor(1, sigp_stop_and_store_status) == sigp_busy)
+ cpu_relax();
+ memcpy(zfcpdump_save_areas[cpu],
+ (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
+ SAVE_AREA_SIZE);
+#ifdef CONFIG_64BIT
+ /* copy original prefix register */
+ zfcpdump_save_areas[cpu]->s390x.pref_reg = zfcpdump_prefix_array[cpu];
+#endif
}
union save_area *zfcpdump_save_areas[NR_CPUS + 1];
EXPORT_SYMBOL_GPL(zfcpdump_save_areas);
#else
-#define smp_get_save_areas() do { } while (0)
-#endif
+
+static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
+
+#endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */
/*
* Lets check how many CPUs we have.
*/
-
static unsigned int __init smp_count_cpus(void)
{
unsigned int cpu, num_cpus;
@@ -470,7 +452,6 @@ static unsigned int __init smp_count_cpus(void)
/*
* cpu 0 is the boot cpu. See smp_prepare_boot_cpu.
*/
-
boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
current_thread_info()->cpu = 0;
num_cpus = 1;
@@ -480,19 +461,18 @@ static unsigned int __init smp_count_cpus(void)
__cpu_logical_map[1] = (__u16) cpu;
if (signal_processor(1, sigp_sense) == sigp_not_operational)
continue;
+ smp_get_save_area(num_cpus, cpu);
num_cpus++;
}
-
printk("Detected %d CPU's\n", (int) num_cpus);
printk("Boot cpu address %2X\n", boot_cpu_addr);
-
return num_cpus;
}
/*
* Activate a secondary processor.
*/
-int __devinit start_secondary(void *cpuvoid)
+int __cpuinit start_secondary(void *cpuvoid)
{
/* Setup the cpu */
cpu_init();
@@ -606,7 +586,6 @@ void __init smp_setup_cpu_possible_map(void)
{
unsigned int phy_cpus, pos_cpus, cpu;
- smp_get_save_areas();
phy_cpus = smp_count_cpus();
pos_cpus = min(phy_cpus + additional_cpus, (unsigned int) NR_CPUS);
@@ -741,7 +720,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
smp_create_idle(cpu);
}
-void __devinit smp_prepare_boot_cpu(void)
+void __init smp_prepare_boot_cpu(void)
{
BUG_ON(smp_processor_id() != 0);
@@ -750,7 +729,7 @@ void __devinit smp_prepare_boot_cpu(void)
current_set[0] = current;
}
-void smp_cpus_done(unsigned int max_cpus)
+void __init smp_cpus_done(unsigned int max_cpus)
{
cpu_present_map = cpu_possible_map;
}
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9c2872a7cca..48dae49bc1e 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -226,10 +226,10 @@ static int nohz_idle_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
switch (action) {
- case CPU_IDLE:
+ case S390_CPU_IDLE:
stop_hz_timer();
break;
- case CPU_NOT_IDLE:
+ case S390_CPU_NOT_IDLE:
start_hz_timer();
break;
}
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index cbfe73034c3..ee9186f8fb0 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -253,19 +253,22 @@ void die(const char * str, struct pt_regs * regs, long err)
{
static int die_counter;
+ oops_enter();
debug_stop_all();
console_verbose();
spin_lock_irq(&die_lock);
bust_spinlocks(1);
printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
- show_regs(regs);
+ print_modules();
+ show_regs(regs);
bust_spinlocks(0);
- spin_unlock_irq(&die_lock);
+ spin_unlock_irq(&die_lock);
if (in_interrupt())
panic("Fatal exception in interrupt");
if (panic_on_oops)
panic("Fatal exception: panic_on_oops");
- do_exit(SIGSEGV);
+ oops_exit();
+ do_exit(SIGSEGV);
}
static void inline
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 1e1a6ee2cac..b6ed143e859 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -545,10 +545,10 @@ static int vtimer_idle_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
switch (action) {
- case CPU_IDLE:
+ case S390_CPU_IDLE:
stop_cpu_timer();
break;
- case CPU_NOT_IDLE:
+ case S390_CPU_NOT_IDLE:
start_cpu_timer();
break;
}
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 59aea65ce99..52084436ab6 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,7 +4,7 @@
EXTRA_AFLAGS := -traditional
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o
-obj-$(CONFIG_32BIT) += div64.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+obj-$(CONFIG_32BIT) += div64.o qrnnd.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 7b112241705..883b03b040c 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -39,7 +39,7 @@ cflags-$(CONFIG_CPU_SH2A) := -m2a $(call cc-option,-m2a-nofpu,)
cflags-$(CONFIG_CPU_SH3) := -m3
cflags-$(CONFIG_CPU_SH4) := -m4 \
$(call cc-option,-mno-implicit-fp,-m4-nofpu)
-cflags-$(CONFIG_CPU_SH4A) := -m4a $(call cc-option,-m4a-nofpu,)
+cflags-$(CONFIG_CPU_SH4A) := $(call cc-option,-m4a,) $(call cc-option,-m4a-nofpu,)
cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml
diff --git a/arch/sh/boards/se/73180/setup.c b/arch/sh/boards/se/73180/setup.c
index 911ce1cdbd7..e143017c897 100644
--- a/arch/sh/boards/se/73180/setup.c
+++ b/arch/sh/boards/se/73180/setup.c
@@ -38,8 +38,8 @@ static struct platform_device *se73180_devices[] __initdata = {
static int __init se73180_devices_setup(void)
{
- return platform_add_devices(sh7343se_platform_devices,
- ARRAY_SIZE(sh7343se_platform_devices));
+ return platform_add_devices(se73180_devices,
+ ARRAY_SIZE(se73180_devices));
}
__initcall(se73180_devices_setup);
diff --git a/arch/sh/boards/superh/microdev/irq.c b/arch/sh/boards/superh/microdev/irq.c
index cc1cb04fa61..4d335077a3f 100644
--- a/arch/sh/boards/superh/microdev/irq.c
+++ b/arch/sh/boards/superh/microdev/irq.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/microdev.h>
diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c
index 70f12907647..d70e5c8461b 100644
--- a/arch/sh/cchips/voyagergx/irq.c
+++ b/arch/sh/cchips/voyagergx/irq.c
@@ -28,7 +28,7 @@ static void disable_voyagergx_irq(unsigned int irq)
unsigned long val;
unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
- pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+ pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
val = readl((void __iomem *)VOYAGER_INT_MASK);
val &= ~mask;
writel(val, (void __iomem *)VOYAGER_INT_MASK);
@@ -39,7 +39,7 @@ static void enable_voyagergx_irq(unsigned int irq)
unsigned long val;
unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE);
- pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask);
+ pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask);
val = readl((void __iomem *)VOYAGER_INT_MASK);
val |= mask;
writel(val, (void __iomem *)VOYAGER_INT_MASK);
@@ -125,11 +125,12 @@ int voyagergx_irq_demux(int irq)
i = 17;
else
printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val);
- pr_debug("voyagergx_irq_demux %d \n", i);
- if (i < VOYAGER_IRQ_NUM) {
+ pr_debug("voyagergx_irq_demux %ld \n", i);
+ if (i < VOYAGER_IRQ_NUM) {
irq = VOYAGER_IRQ_BASE + i;
- if (voyagergx_demux[i].func != 0)
- irq = voyagergx_demux[i].func(irq, voyagergx_demux[i].dev);
+ if (voyagergx_demux[i].func != 0)
+ irq = voyagergx_demux[i].func(irq,
+ voyagergx_demux[i].dev);
}
}
return irq;
diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c
index 8057a27a1bc..cf8e1199433 100644
--- a/arch/sh/drivers/dma/dma-api.c
+++ b/arch/sh/drivers/dma/dma-api.c
@@ -16,6 +16,7 @@
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/mm.h>
+#include <linux/sched.h>
#include <asm/dma.h>
DEFINE_SPINLOCK(dma_spin_lock);
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c
index 849a9e19139..ebc73b85094 100644
--- a/arch/sh/kernel/cf-enabler.c
+++ b/arch/sh/kernel/cf-enabler.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -149,6 +150,11 @@ static int __init cf_init_se(void)
ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
return 0;
}
+#else
+static int __init cf_init_se(void)
+{
+ return -1;
+}
#endif
int __init cf_init(void)
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 832c0b4a1e6..b0b59d4a33c 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -320,6 +320,9 @@ skip_restore:
.align 2
5: .long 0x00001000 ! DSP
+#ifdef CONFIG_KGDB_NMI
+6: .long in_nmi
+#endif
7: .long 0x30000000
! common exception handler
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index fcb2c41bc34..a33429463e9 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -111,7 +111,7 @@ static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
return 0;
}
-static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
+static int shoc_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id)
{
unsigned long frqcr3;
unsigned int tmp;
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 8cd04904c77..fab2eb07196 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -12,6 +12,7 @@
*/
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/smp.h>
#include <asm/processor.h>
#include <asm/cache.h>
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index b32c35a7c0a..e323e299878 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -268,7 +268,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
badframe:
force_sig(SIGSEGV, current);
return 0;
-}
+}
/*
* Set up a signal frame.
@@ -481,7 +481,7 @@ give_sigsegv:
static int
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *oldset, struct pt_regs *regs)
+ sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
{
int ret;
@@ -489,6 +489,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
if (regs->tra >= 0) {
/* If so, check system call restarting.. */
switch (regs->regs[0]) {
+ case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
regs->regs[0] = -EINTR;
break;
@@ -500,6 +501,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
}
/* fallthrough */
case -ERESTARTNOINTR:
+ regs->regs[0] = save_r0;
regs->pc -= instruction_size(
ctrl_inw(regs->pc - 4));
break;
@@ -583,7 +585,8 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
- if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+ if (handle_signal(signr, &ka, &info, oldset,
+ regs, save_r0) == 0) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index dbebaddcfe3..283e1425ced 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -10,6 +10,8 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
+
+#include <linux/err.h>
#include <linux/cache.h>
#include <linux/cpumask.h>
#include <linux/delay.h>
diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c
index a6bcc913d25..4e7e747d1b6 100644
--- a/arch/sh/kernel/timers/timer.c
+++ b/arch/sh/kernel/timers/timer.c
@@ -13,7 +13,7 @@
#include <linux/string.h>
#include <asm/timer.h>
-static struct sys_timer *sys_timers[] __initdata = {
+static struct sys_timer *sys_timers[] = {
#ifdef CONFIG_SH_TMU
&tmu_timer,
#endif
@@ -26,7 +26,7 @@ static struct sys_timer *sys_timers[] __initdata = {
NULL,
};
-static char timer_override[10] __initdata;
+static char timer_override[10];
static int __init timer_setup(char *str)
{
if (str)
@@ -53,4 +53,3 @@ struct sys_timer *get_sys_timer(void)
return NULL;
}
-
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index 5b75cb6f8f9..8f18930d5bf 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -83,6 +83,8 @@ void die(const char * str, struct pt_regs * regs, long err)
{
static int die_counter;
+ oops_enter();
+
console_verbose();
spin_lock_irq(&die_lock);
bust_spinlocks(1);
@@ -112,6 +114,7 @@ void die(const char * str, struct pt_regs * regs, long err)
if (panic_on_oops)
panic("Fatal exception");
+ oops_exit();
do_exit(SIGSEGV);
}
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
index e146bafcd14..2aa9438361b 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.c
+++ b/arch/sh/kernel/vsyscall/vsyscall.c
@@ -17,6 +17,7 @@
#include <linux/gfp.h>
#include <linux/module.h>
#include <linux/elf.h>
+#include <linux/sched.h>
/*
* Should the kernel map a VDSO page into processes and pass its
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index be03d74e99c..0c7b7e33abd 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -22,6 +22,7 @@
#include <asm/addrspace.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
+#include <asm/mmu.h>
/*
* Remap an arbitrary physical address space into the kernel virtual
diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
index fb51660847c..3334f99b583 100644
--- a/arch/sh64/kernel/pci_sh5.c
+++ b/arch/sh64/kernel/pci_sh5.c
@@ -521,10 +521,10 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
bus->resource[0]->start = PCIBIOS_MIN_IO;
bus->resource[1]->start = PCIBIOS_MIN_MEM;
#else
- bus->resource[0]->end = 0
- bus->resource[1]->end = 0
- bus->resource[0]->start =0
- bus->resource[1]->start = 0;
+ bus->resource[0]->end = 0;
+ bus->resource[1]->end = 0;
+ bus->resource[0]->start =0;
+ bus->resource[1]->start = 0;
#endif
/* Turn off downstream PF memory address range by default */
bus->resource[2]->start = 1024*1024;
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
index c8525ade056..0bb4a8f9427 100644
--- a/arch/sh64/kernel/signal.c
+++ b/arch/sh64/kernel/signal.c
@@ -640,6 +640,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
if (regs->syscall_nr >= 0) {
/* If so, check system call restarting.. */
switch (regs->regs[REG_RET]) {
+ case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
regs->regs[REG_RET] = -EINTR;
break;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index fbcc00c6c06..8567cc90194 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -210,6 +210,9 @@ config PCI
CP-1200, JavaEngine-1, Corona, Red October, and Serengeti SGSC.
All of these platforms are extremely obscure, so say N if unsure.
+config PCI_SYSCALL
+ def_bool PCI
+
source "drivers/pci/Kconfig"
endif
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 4d9ad59031b..4fea3ac7bff 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -68,16 +68,6 @@ void __cpuinit smp_store_cpu_info(int id)
cpu_data(id).prom_node = cpu_node;
cpu_data(id).mid = cpu_get_hwmid(cpu_node);
- /* this is required to tune the scheduler correctly */
- /* is it possible to have CPUs with different cache sizes? */
- if (id == boot_cpu_id) {
- int cache_line,cache_nlines;
- cache_line = 0x20;
- cache_line = prom_getintdefault(cpu_node, "ecache-line-size", cache_line);
- cache_nlines = 0x8000;
- cache_nlines = prom_getintdefault(cpu_node, "ecache-nlines", cache_nlines);
- max_cache_size = cache_line * cache_nlines;
- }
if (cpu_data(id).mid < 0)
panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
}
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index 617d29832e1..cbddeb38ffd 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -124,10 +124,10 @@ unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new)
unsigned long flags;
u32 prev;
- spin_lock_irqsave(ATOMIC_HASH(addr), flags);
+ spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
if ((prev = *ptr) == old)
*ptr = new;
- spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);
+ spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
return (unsigned long)prev;
}
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index bd00f89eed1..6566d13db04 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -320,8 +320,10 @@ config PCI
doesn't.
config PCI_DOMAINS
- bool
- default PCI
+ def_bool PCI
+
+config PCI_SYSCALL
+ def_bool PCI
source "drivers/pci/Kconfig"
@@ -396,6 +398,15 @@ config SCHED_SMT
when dealing with UltraSPARC cpus at a cost of slightly increased
overhead in some places. If unsure say N here.
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on SMP
+ default y
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
source "kernel/Kconfig.preempt"
config CMDLINE_BOOL
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index d8d19093d12..f964bf28d21 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.70 2002/02/09 19:49:30 davem Exp $
+#
# Makefile for the linux kernel.
#
@@ -8,7 +8,7 @@ EXTRA_CFLAGS := -Werror
extra-y := head.o init_task.o vmlinux.lds
obj-y := process.o setup.o cpu.o idprom.o \
- traps.o auxio.o una_asm.o \
+ traps.o auxio.o una_asm.o sysfs.o \
irq.o ptrace.o time.o sys_sparc.o signal.o \
unaligned.o central.o pci.o starfire.o semaphore.o \
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 8f10dda0f5c..8059531bf0a 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -2357,8 +2357,9 @@ sun4v_ldc_unmap:
nop
.size sun4v_ldc_unmap, .-sun4v_ldc_unmap
- /* %o0: cookie
- * %o1: mte_cookie
+ /* %o0: channel
+ * %o1: cookie
+ * %o2: mte_cookie
*
* returns %o0: status
*/
@@ -2498,3 +2499,97 @@ sun4v_vintr_set_target:
retl
nop
.size sun4v_vintr_set_target, .-sun4v_vintr_set_target
+
+ /* %o0: NCS sub-function
+ * %o1: sub-function arg real-address
+ * %o2: sub-function arg size
+ *
+ * returns %o0: status
+ */
+ .globl sun4v_ncs_request
+ .type sun4v_ncs_request,#function
+sun4v_ncs_request:
+ mov HV_FAST_NCS_REQUEST, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_ncs_request, .-sun4v_ncs_request
+
+ .globl sun4v_svc_send
+ .type sun4v_svc_send,#function
+sun4v_svc_send:
+ save %sp, -192, %sp
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ mov HV_FAST_SVC_SEND, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%i3]
+ ret
+ restore
+ .size sun4v_svc_send, .-sun4v_svc_send
+
+ .globl sun4v_svc_recv
+ .type sun4v_svc_recv,#function
+sun4v_svc_recv:
+ save %sp, -192, %sp
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ mov HV_FAST_SVC_RECV, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%i3]
+ ret
+ restore
+ .size sun4v_svc_recv, .-sun4v_svc_recv
+
+ .globl sun4v_svc_getstatus
+ .type sun4v_svc_getstatus,#function
+sun4v_svc_getstatus:
+ mov HV_FAST_SVC_GETSTATUS, %o5
+ mov %o1, %o4
+ ta HV_FAST_TRAP
+ stx %o1, [%o4]
+ retl
+ nop
+ .size sun4v_svc_getstatus, .-sun4v_svc_getstatus
+
+ .globl sun4v_svc_setstatus
+ .type sun4v_svc_setstatus,#function
+sun4v_svc_setstatus:
+ mov HV_FAST_SVC_SETSTATUS, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_svc_setstatus, .-sun4v_svc_setstatus
+
+ .globl sun4v_svc_clrstatus
+ .type sun4v_svc_clrstatus,#function
+sun4v_svc_clrstatus:
+ mov HV_FAST_SVC_CLRSTATUS, %o5
+ ta HV_FAST_TRAP
+ retl
+ nop
+ .size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus
+
+ .globl sun4v_mmustat_conf
+ .type sun4v_mmustat_conf,#function
+sun4v_mmustat_conf:
+ mov %o1, %o4
+ mov HV_FAST_MMUSTAT_CONF, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%o4]
+ retl
+ nop
+ .size sun4v_mmustat_conf, .-sun4v_mmustat_conf
+
+ .globl sun4v_mmustat_info
+ .type sun4v_mmustat_info,#function
+sun4v_mmustat_info:
+ mov %o0, %o4
+ mov HV_FAST_MMUSTAT_INFO, %o5
+ ta HV_FAST_TRAP
+ stx %o1, [%o4]
+ retl
+ nop
+ .size sun4v_mmustat_info, .-sun4v_mmustat_info
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index a36f8dd0c02..6b6165d36fd 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,7 +1,6 @@
-/* $Id: irq.c,v 1.114 2002/01/11 08:45:38 davem Exp $
- * irq.c: UltraSparc IRQ handling/init/registry.
+/* irq.c: UltraSparc IRQ handling/init/registry.
*
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 2007 David S. Miller (davem@davemloft.net)
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
@@ -43,6 +42,7 @@
#include <asm/cpudata.h>
#include <asm/auxio.h>
#include <asm/head.h>
+#include <asm/hypervisor.h>
/* UPA nodes send interrupt packet to UltraSparc with first data reg
* value low 5 (7 on Starfire) bits holding the IRQ identifier being
@@ -329,6 +329,10 @@ static void sun4v_irq_enable(unsigned int virt_irq)
if (err != HV_EOK)
printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
ino, cpuid, err);
+ err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
+ if (err != HV_EOK)
+ printk("sun4v_intr_setstate(%x): "
+ "err(%d)\n", ino, err);
err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
if (err != HV_EOK)
printk("sun4v_intr_setenabled(%x): err(%d)\n",
@@ -380,6 +384,82 @@ static void sun4v_irq_end(unsigned int virt_irq)
}
}
+static void sun4v_virq_enable(unsigned int virt_irq)
+{
+ struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+ unsigned int ino = bucket - &ivector_table[0];
+
+ if (likely(bucket)) {
+ unsigned long cpuid, dev_handle, dev_ino;
+ int err;
+
+ cpuid = irq_choose_cpu(virt_irq);
+
+ dev_handle = ino & IMAP_IGN;
+ dev_ino = ino & IMAP_INO;
+
+ err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
+ if (err != HV_EOK)
+ printk("sun4v_vintr_set_target(%lx,%lx,%lu): "
+ "err(%d)\n",
+ dev_handle, dev_ino, cpuid, err);
+ err = sun4v_vintr_set_state(dev_handle, dev_ino,
+ HV_INTR_STATE_IDLE);
+ if (err != HV_EOK)
+ printk("sun4v_vintr_set_state(%lx,%lx,"
+ "HV_INTR_STATE_IDLE): err(%d)\n",
+ dev_handle, dev_ino, err);
+ err = sun4v_vintr_set_valid(dev_handle, dev_ino,
+ HV_INTR_ENABLED);
+ if (err != HV_EOK)
+ printk("sun4v_vintr_set_state(%lx,%lx,"
+ "HV_INTR_ENABLED): err(%d)\n",
+ dev_handle, dev_ino, err);
+ }
+}
+
+static void sun4v_virq_disable(unsigned int virt_irq)
+{
+ struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+ unsigned int ino = bucket - &ivector_table[0];
+
+ if (likely(bucket)) {
+ unsigned long dev_handle, dev_ino;
+ int err;
+
+ dev_handle = ino & IMAP_IGN;
+ dev_ino = ino & IMAP_INO;
+
+ err = sun4v_vintr_set_valid(dev_handle, dev_ino,
+ HV_INTR_DISABLED);
+ if (err != HV_EOK)
+ printk("sun4v_vintr_set_state(%lx,%lx,"
+ "HV_INTR_DISABLED): err(%d)\n",
+ dev_handle, dev_ino, err);
+ }
+}
+
+static void sun4v_virq_end(unsigned int virt_irq)
+{
+ struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+ unsigned int ino = bucket - &ivector_table[0];
+
+ if (likely(bucket)) {
+ unsigned long dev_handle, dev_ino;
+ int err;
+
+ dev_handle = ino & IMAP_IGN;
+ dev_ino = ino & IMAP_INO;
+
+ err = sun4v_vintr_set_state(dev_handle, dev_ino,
+ HV_INTR_STATE_IDLE);
+ if (err != HV_EOK)
+ printk("sun4v_vintr_set_state(%lx,%lx,"
+ "HV_INTR_STATE_IDLE): err(%d)\n",
+ dev_handle, dev_ino, err);
+ }
+}
+
static void run_pre_handler(unsigned int virt_irq)
{
struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
@@ -434,6 +514,21 @@ static struct irq_chip sun4v_msi = {
};
#endif
+static struct irq_chip sun4v_virq = {
+ .typename = "vsun4v",
+ .enable = sun4v_virq_enable,
+ .disable = sun4v_virq_disable,
+ .end = sun4v_virq_end,
+};
+
+static struct irq_chip sun4v_virq_ack = {
+ .typename = "vsun4v+ack",
+ .enable = sun4v_virq_enable,
+ .disable = sun4v_virq_disable,
+ .ack = run_pre_handler,
+ .end = sun4v_virq_end,
+};
+
void irq_install_pre_handler(int virt_irq,
void (*func)(unsigned int, void *, void *),
void *arg1, void *arg2)
@@ -447,7 +542,8 @@ void irq_install_pre_handler(int virt_irq,
chip = get_irq_chip(virt_irq);
if (chip == &sun4u_irq_ack ||
- chip == &sun4v_irq_ack
+ chip == &sun4v_irq_ack ||
+ chip == &sun4v_virq_ack
#ifdef CONFIG_PCI_MSI
|| chip == &sun4v_msi
#endif
@@ -455,7 +551,9 @@ void irq_install_pre_handler(int virt_irq,
return;
chip = (chip == &sun4u_irq ?
- &sun4u_irq_ack : &sun4v_irq_ack);
+ &sun4u_irq_ack :
+ (chip == &sun4v_irq ?
+ &sun4v_irq_ack : &sun4v_virq_ack));
set_irq_chip(virt_irq, chip);
}
@@ -492,19 +590,18 @@ out:
return bucket->virt_irq;
}
-unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
+static unsigned int sun4v_build_common(unsigned long sysino,
+ struct irq_chip *chip)
{
struct ino_bucket *bucket;
struct irq_handler_data *data;
- unsigned long sysino;
BUG_ON(tlb_type != hypervisor);
- sysino = sun4v_devino_to_sysino(devhandle, devino);
bucket = &ivector_table[sysino];
if (!bucket->virt_irq) {
bucket->virt_irq = virt_irq_alloc(__irq(bucket));
- set_irq_chip(bucket->virt_irq, &sun4v_irq);
+ set_irq_chip(bucket->virt_irq, chip);
}
data = get_irq_chip_data(bucket->virt_irq);
@@ -529,6 +626,32 @@ out:
return bucket->virt_irq;
}
+unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
+{
+ unsigned long sysino = sun4v_devino_to_sysino(devhandle, devino);
+
+ return sun4v_build_common(sysino, &sun4v_irq);
+}
+
+unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
+{
+ unsigned long sysino, hv_err;
+
+ BUG_ON(devhandle & ~IMAP_IGN);
+ BUG_ON(devino & ~IMAP_INO);
+
+ sysino = devhandle | devino;
+
+ hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino);
+ if (hv_err) {
+ prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] "
+ "err=%lu\n", devhandle, devino, hv_err);
+ prom_halt();
+ }
+
+ return sun4v_build_common(sysino, &sun4v_virq);
+}
+
#ifdef CONFIG_PCI_MSI
unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
unsigned int msi_start, unsigned int msi_end)
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index 9246c2cf957..f0e16045fb1 100644
--- a/arch/sparc64/kernel/mdesc.c
+++ b/arch/sparc64/kernel/mdesc.c
@@ -473,6 +473,53 @@ static void __init set_core_ids(void)
}
}
+static void __init mark_proc_ids(struct mdesc_node *mp, int proc_id)
+{
+ int i;
+
+ for (i = 0; i < mp->num_arcs; i++) {
+ struct mdesc_node *t = mp->arcs[i].arc;
+ const u64 *id;
+
+ if (strcmp(mp->arcs[i].name, "back"))
+ continue;
+
+ if (strcmp(t->name, "cpu"))
+ continue;
+
+ id = md_get_property(t, "id", NULL);
+ if (*id < NR_CPUS)
+ cpu_data(*id).proc_id = proc_id;
+ }
+}
+
+static void __init __set_proc_ids(const char *exec_unit_name)
+{
+ struct mdesc_node *mp;
+ int idx;
+
+ idx = 0;
+ md_for_each_node_by_name(mp, exec_unit_name) {
+ const char *type;
+ int len;
+
+ type = md_get_property(mp, "type", &len);
+ if (!find_in_proplist(type, "int", len) &&
+ !find_in_proplist(type, "integer", len))
+ continue;
+
+ mark_proc_ids(mp, idx);
+
+ idx++;
+ }
+}
+
+static void __init set_proc_ids(void)
+{
+ __set_proc_ids("exec_unit");
+ __set_proc_ids("exec-unit");
+}
+
static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def)
{
u64 val;
@@ -574,9 +621,15 @@ static void __init mdesc_fill_in_cpu_data(void)
#endif
c->core_id = 0;
+ c->proc_id = -1;
}
+#ifdef CONFIG_SMP
+ sparc64_multi_core = 1;
+#endif
+
set_core_ids();
+ set_proc_ids();
smp_fill_in_sib_core_maps();
}
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 16cc46a7187..6676b93219d 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -343,6 +343,15 @@ static int of_bus_simba_match(struct device_node *np)
if (model && !strcmp(model, "SUNW,simba"))
return 1;
+
+ /* Treat PCI busses lacking ranges property just like
+ * simba.
+ */
+ if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
+ if (!of_find_property(np, "ranges", NULL))
+ return 1;
+ }
+
return 0;
}
@@ -549,8 +558,6 @@ static int __init build_one_resource(struct device_node *parent,
static int __init use_1to1_mapping(struct device_node *pp)
{
- const char *model;
-
/* If this is on the PMU bus, don't try to translate it even
* if a ranges property exists.
*/
@@ -567,9 +574,11 @@ static int __init use_1to1_mapping(struct device_node *pp)
if (!strcmp(pp->name, "dma"))
return 0;
- /* Similarly for Simba PCI bridges. */
- model = of_get_property(pp, "model", NULL);
- if (model && !strcmp(model, "SUNW,simba"))
+ /* Similarly for all PCI bridges, if we get this far
+ * it lacks a ranges property, and this will include
+ * cases like Simba.
+ */
+ if (!strcmp(pp->type, "pci") || !strcmp(pp->type, "pciex"))
return 0;
return 1;
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 38a32bc95d2..55ad1b899bb 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -448,6 +448,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
*/
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
dev->class = class >> 8;
+ dev->revision = class & 0xff;
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
@@ -522,6 +523,89 @@ static void pci_resource_adjust(struct resource *res,
res->end += root->start;
}
+/* For PCI bus devices which lack a 'ranges' property we interrogate
+ * the config space values to set the resources, just like the generic
+ * Linux PCI probing code does.
+ */
+static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
+ struct pci_bus *bus,
+ struct pci_pbm_info *pbm)
+{
+ struct resource *res;
+ u8 io_base_lo, io_limit_lo;
+ u16 mem_base_lo, mem_limit_lo;
+ unsigned long base, limit;
+
+ pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
+ pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
+ base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
+ limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
+
+ if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
+ u16 io_base_hi, io_limit_hi;
+
+ pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
+ pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
+ base |= (io_base_hi << 16);
+ limit |= (io_limit_hi << 16);
+ }
+
+ res = bus->resource[0];
+ if (base <= limit) {
+ res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
+ if (!res->start)
+ res->start = base;
+ if (!res->end)
+ res->end = limit + 0xfff;
+ pci_resource_adjust(res, &pbm->io_space);
+ }
+
+ pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
+ pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
+ base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
+ limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+
+ res = bus->resource[1];
+ if (base <= limit) {
+ res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
+ IORESOURCE_MEM);
+ res->start = base;
+ res->end = limit + 0xfffff;
+ pci_resource_adjust(res, &pbm->mem_space);
+ }
+
+ pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
+ pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
+ base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
+ limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
+
+ if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
+ u32 mem_base_hi, mem_limit_hi;
+
+ pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
+ pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
+
+ /*
+ * Some bridges set the base > limit by default, and some
+ * (broken) BIOSes do not initialize them. If we find
+ * this, just assume they are not being used.
+ */
+ if (mem_base_hi <= mem_limit_hi) {
+ base |= ((long) mem_base_hi) << 32;
+ limit |= ((long) mem_limit_hi) << 32;
+ }
+ }
+
+ res = bus->resource[2];
+ if (base <= limit) {
+ res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
+ IORESOURCE_MEM | IORESOURCE_PREFETCH);
+ res->start = base;
+ res->end = limit + 0xfffff;
+ pci_resource_adjust(res, &pbm->mem_space);
+ }
+}
+
/* Cook up fake bus resources for SUNW,simba PCI bridges which lack
* a proper 'ranges' property.
*/
@@ -581,13 +665,8 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
simba = 0;
if (ranges == NULL) {
const char *model = of_get_property(node, "model", NULL);
- if (model && !strcmp(model, "SUNW,simba")) {
+ if (model && !strcmp(model, "SUNW,simba"))
simba = 1;
- } else {
- printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
- node->full_name);
- return;
- }
}
bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
@@ -611,7 +690,10 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
}
if (simba) {
apb_fake_ranges(dev, bus, pbm);
- goto simba_cont;
+ goto after_ranges;
+ } else if (ranges == NULL) {
+ pci_cfg_fake_ranges(dev, bus, pbm);
+ goto after_ranges;
}
i = 1;
for (; len >= 32; len -= 32, ranges += 8) {
@@ -650,7 +732,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
*/
pci_resource_adjust(res, root);
}
-simba_cont:
+after_ranges:
sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
bus->number);
if (ofpci_verbose)
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index f974fefc3eb..4249214608a 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -291,8 +291,9 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
for (i = 0; i < num_pbm_ranges; i++) {
const struct linux_prom_pci_ranges *pr = &pbm_ranges[i];
- unsigned long a;
+ unsigned long a, size;
u32 parent_phys_hi, parent_phys_lo;
+ u32 size_hi, size_lo;
int type;
parent_phys_hi = pr->parent_phys_hi;
@@ -300,9 +301,14 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
if (tlb_type == hypervisor)
parent_phys_hi &= 0x0fffffff;
+ size_hi = pr->size_hi;
+ size_lo = pr->size_lo;
+
type = (pr->child_phys_hi >> 24) & 0x3;
a = (((unsigned long)parent_phys_hi << 32UL) |
((unsigned long)parent_phys_lo << 0UL));
+ size = (((unsigned long)size_hi << 32UL) |
+ ((unsigned long)size_lo << 0UL));
switch (type) {
case 0:
@@ -313,7 +319,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
case 1:
/* 16-bit IO space, 16MB */
pbm->io_space.start = a;
- pbm->io_space.end = a + ((16UL*1024UL*1024UL) - 1UL);
+ pbm->io_space.end = a + size - 1UL;
pbm->io_space.flags = IORESOURCE_IO;
saw_io = 1;
break;
@@ -321,7 +327,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm)
case 2:
/* 32-bit MEM space, 2GB */
pbm->mem_space.start = a;
- pbm->mem_space.end = a + (0x80000000UL - 1UL);
+ pbm->mem_space.end = a + size - 1UL;
pbm->mem_space.flags = IORESOURCE_MEM;
saw_mem = 1;
break;
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 323d6c27851..22e1be5c748 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -636,13 +636,18 @@ static void apb_init(struct pci_bus *sabre_bus)
static void sabre_scan_bus(struct pci_pbm_info *pbm)
{
static int once;
- struct pci_bus *pbus;
/* The APB bridge speaks to the Sabre host PCI bridge
* at 66Mhz, but the front side of APB runs at 33Mhz
* for both segments.
+ *
+ * Hummingbird systems do not use APB, so they run
+ * at 66MHZ.
*/
- pbm->is_66mhz_capable = 0;
+ if (hummingbird_p)
+ pbm->is_66mhz_capable = 1;
+ else
+ pbm->is_66mhz_capable = 0;
/* This driver has not been verified to handle
* multiple SABREs yet, so trap this.
@@ -656,13 +661,13 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm)
}
once++;
- pbus = pci_scan_one_pbm(pbm);
- if (!pbus)
+ pbm->pci_bus = pci_scan_one_pbm(pbm);
+ if (!pbm->pci_bus)
return;
- sabre_root_bus = pbus;
+ sabre_root_bus = pbm->pci_bus;
- apb_init(pbus);
+ apb_init(pbm->pci_bus);
sabre_register_error_handlers(pbm);
}
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index dad4b3ba705..61036b34666 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -933,29 +933,29 @@ static void __init fire_irq_trans_init(struct device_node *dp)
* This should conform to both Sunfire/Wildfire server and Fusion
* desktop designs.
*/
-#define SYSIO_IMAP_SLOT0 0x2c04UL
-#define SYSIO_IMAP_SLOT1 0x2c0cUL
-#define SYSIO_IMAP_SLOT2 0x2c14UL
-#define SYSIO_IMAP_SLOT3 0x2c1cUL
-#define SYSIO_IMAP_SCSI 0x3004UL
-#define SYSIO_IMAP_ETH 0x300cUL
-#define SYSIO_IMAP_BPP 0x3014UL
-#define SYSIO_IMAP_AUDIO 0x301cUL
-#define SYSIO_IMAP_PFAIL 0x3024UL
-#define SYSIO_IMAP_KMS 0x302cUL
-#define SYSIO_IMAP_FLPY 0x3034UL
-#define SYSIO_IMAP_SHW 0x303cUL
-#define SYSIO_IMAP_KBD 0x3044UL
-#define SYSIO_IMAP_MS 0x304cUL
-#define SYSIO_IMAP_SER 0x3054UL
-#define SYSIO_IMAP_TIM0 0x3064UL
-#define SYSIO_IMAP_TIM1 0x306cUL
-#define SYSIO_IMAP_UE 0x3074UL
-#define SYSIO_IMAP_CE 0x307cUL
-#define SYSIO_IMAP_SBERR 0x3084UL
-#define SYSIO_IMAP_PMGMT 0x308cUL
-#define SYSIO_IMAP_GFX 0x3094UL
-#define SYSIO_IMAP_EUPA 0x309cUL
+#define SYSIO_IMAP_SLOT0 0x2c00UL
+#define SYSIO_IMAP_SLOT1 0x2c08UL
+#define SYSIO_IMAP_SLOT2 0x2c10UL
+#define SYSIO_IMAP_SLOT3 0x2c18UL
+#define SYSIO_IMAP_SCSI 0x3000UL
+#define SYSIO_IMAP_ETH 0x3008UL
+#define SYSIO_IMAP_BPP 0x3010UL
+#define SYSIO_IMAP_AUDIO 0x3018UL
+#define SYSIO_IMAP_PFAIL 0x3020UL
+#define SYSIO_IMAP_KMS 0x3028UL
+#define SYSIO_IMAP_FLPY 0x3030UL
+#define SYSIO_IMAP_SHW 0x3038UL
+#define SYSIO_IMAP_KBD 0x3040UL
+#define SYSIO_IMAP_MS 0x3048UL
+#define SYSIO_IMAP_SER 0x3050UL
+#define SYSIO_IMAP_TIM0 0x3060UL
+#define SYSIO_IMAP_TIM1 0x3068UL
+#define SYSIO_IMAP_UE 0x3070UL
+#define SYSIO_IMAP_CE 0x3078UL
+#define SYSIO_IMAP_SBERR 0x3080UL
+#define SYSIO_IMAP_PMGMT 0x3088UL
+#define SYSIO_IMAP_GFX 0x3090UL
+#define SYSIO_IMAP_EUPA 0x3098UL
#define bogon ((unsigned long) -1)
static unsigned long sysio_irq_offsets[] = {
@@ -1006,10 +1006,10 @@ static unsigned long sysio_irq_offsets[] = {
* Interrupt Clear register pointer, SYSIO specific version.
*/
#define SYSIO_ICLR_UNUSED0 0x3400UL
-#define SYSIO_ICLR_SLOT0 0x340cUL
-#define SYSIO_ICLR_SLOT1 0x344cUL
-#define SYSIO_ICLR_SLOT2 0x348cUL
-#define SYSIO_ICLR_SLOT3 0x34ccUL
+#define SYSIO_ICLR_SLOT0 0x3408UL
+#define SYSIO_ICLR_SLOT1 0x3448UL
+#define SYSIO_ICLR_SLOT2 0x3488UL
+#define SYSIO_ICLR_SLOT3 0x34c8UL
static unsigned long sysio_imap_to_iclr(unsigned long imap)
{
unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
@@ -1781,6 +1781,10 @@ static void __init of_fill_in_cpu_data(void)
}
cpu_data(cpuid).core_id = portid + 1;
+ cpu_data(cpuid).proc_id = portid;
+#ifdef CONFIG_SMP
+ sparc64_multi_core = 1;
+#endif
} else {
cpu_data(cpuid).dcache_size =
of_getintprop_default(dp, "dcache-size", 16 * 1024);
@@ -1799,6 +1803,7 @@ static void __init of_fill_in_cpu_data(void)
of_getintprop_default(dp, "ecache-line-size", 64);
cpu_data(cpuid).core_id = 0;
+ cpu_data(cpuid).proc_id = -1;
}
#ifdef CONFIG_SMP
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 91f6e2a74ad..a1fd9bcc0b8 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -629,29 +629,29 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
* This should conform to both Sunfire/Wildfire server and Fusion
* desktop designs.
*/
-#define SYSIO_IMAP_SLOT0 0x2c04UL
-#define SYSIO_IMAP_SLOT1 0x2c0cUL
-#define SYSIO_IMAP_SLOT2 0x2c14UL
-#define SYSIO_IMAP_SLOT3 0x2c1cUL
-#define SYSIO_IMAP_SCSI 0x3004UL
-#define SYSIO_IMAP_ETH 0x300cUL
-#define SYSIO_IMAP_BPP 0x3014UL
-#define SYSIO_IMAP_AUDIO 0x301cUL
-#define SYSIO_IMAP_PFAIL 0x3024UL
-#define SYSIO_IMAP_KMS 0x302cUL
-#define SYSIO_IMAP_FLPY 0x3034UL
-#define SYSIO_IMAP_SHW 0x303cUL
-#define SYSIO_IMAP_KBD 0x3044UL
-#define SYSIO_IMAP_MS 0x304cUL
-#define SYSIO_IMAP_SER 0x3054UL
-#define SYSIO_IMAP_TIM0 0x3064UL
-#define SYSIO_IMAP_TIM1 0x306cUL
-#define SYSIO_IMAP_UE 0x3074UL
-#define SYSIO_IMAP_CE 0x307cUL
-#define SYSIO_IMAP_SBERR 0x3084UL
-#define SYSIO_IMAP_PMGMT 0x308cUL
-#define SYSIO_IMAP_GFX 0x3094UL
-#define SYSIO_IMAP_EUPA 0x309cUL
+#define SYSIO_IMAP_SLOT0 0x2c00UL
+#define SYSIO_IMAP_SLOT1 0x2c08UL
+#define SYSIO_IMAP_SLOT2 0x2c10UL
+#define SYSIO_IMAP_SLOT3 0x2c18UL
+#define SYSIO_IMAP_SCSI 0x3000UL
+#define SYSIO_IMAP_ETH 0x3008UL
+#define SYSIO_IMAP_BPP 0x3010UL
+#define SYSIO_IMAP_AUDIO 0x3018UL
+#define SYSIO_IMAP_PFAIL 0x3020UL
+#define SYSIO_IMAP_KMS 0x3028UL
+#define SYSIO_IMAP_FLPY 0x3030UL
+#define SYSIO_IMAP_SHW 0x3038UL
+#define SYSIO_IMAP_KBD 0x3040UL
+#define SYSIO_IMAP_MS 0x3048UL
+#define SYSIO_IMAP_SER 0x3050UL
+#define SYSIO_IMAP_TIM0 0x3060UL
+#define SYSIO_IMAP_TIM1 0x3068UL
+#define SYSIO_IMAP_UE 0x3070UL
+#define SYSIO_IMAP_CE 0x3078UL
+#define SYSIO_IMAP_SBERR 0x3080UL
+#define SYSIO_IMAP_PMGMT 0x3088UL
+#define SYSIO_IMAP_GFX 0x3090UL
+#define SYSIO_IMAP_EUPA 0x3098UL
#define bogon ((unsigned long) -1)
static unsigned long sysio_irq_offsets[] = {
@@ -700,10 +700,10 @@ static unsigned long sysio_irq_offsets[] = {
* Interrupt Clear register pointer, SYSIO specific version.
*/
#define SYSIO_ICLR_UNUSED0 0x3400UL
-#define SYSIO_ICLR_SLOT0 0x340cUL
-#define SYSIO_ICLR_SLOT1 0x344cUL
-#define SYSIO_ICLR_SLOT2 0x348cUL
-#define SYSIO_ICLR_SLOT3 0x34ccUL
+#define SYSIO_ICLR_SLOT0 0x3408UL
+#define SYSIO_ICLR_SLOT1 0x3448UL
+#define SYSIO_ICLR_SLOT2 0x3488UL
+#define SYSIO_ICLR_SLOT3 0x34c8UL
static unsigned long sysio_imap_to_iclr(unsigned long imap)
{
unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index de9b4c13f1c..7490cc670a5 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -513,22 +513,3 @@ void sun_do_break(void)
int serial_console = -1;
int stop_a_enabled = 1;
-
-static int __init topology_init(void)
-{
- int i, err;
-
- err = -ENOMEM;
-
- for_each_possible_cpu(i) {
- struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
- if (p) {
- register_cpu(p, i);
- err = 0;
- }
- }
-
- return err;
-}
-
-subsys_initcall(topology_init);
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index c550bba3490..40e40f968d6 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -44,6 +44,8 @@
extern void calibrate_delay(void);
+int sparc64_multi_core __read_mostly;
+
/* Please don't make this stuff initdata!!! --DaveM */
unsigned char boot_cpu_id;
@@ -51,6 +53,8 @@ cpumask_t cpu_online_map __read_mostly = CPU_MASK_NONE;
cpumask_t phys_cpu_present_map __read_mostly = CPU_MASK_NONE;
cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly =
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
+cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
+ { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
static cpumask_t smp_commenced_mask;
static cpumask_t cpu_callout_map;
@@ -1159,32 +1163,6 @@ int setup_profiling_timer(unsigned int multiplier)
return -EINVAL;
}
-static void __init smp_tune_scheduling(void)
-{
- unsigned int smallest = ~0U;
- int i;
-
- for (i = 0; i < NR_CPUS; i++) {
- unsigned int val = cpu_data(i).ecache_size;
-
- if (val && val < smallest)
- smallest = val;
- }
-
- /* Any value less than 256K is nonsense. */
- if (smallest < (256U * 1024U))
- smallest = 256 * 1024;
-
- max_cache_size = smallest;
-
- if (smallest < 1U * 1024U * 1024U)
- printk(KERN_INFO "Using max_cache_size of %uKB\n",
- smallest / 1024U);
- else
- printk(KERN_INFO "Using max_cache_size of %uMB\n",
- smallest / 1024U / 1024U);
-}
-
/* Constrain the number of cpus to max_cpus. */
void __init smp_prepare_cpus(unsigned int max_cpus)
{
@@ -1202,7 +1180,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
cpu_data(boot_cpu_id).udelay_val = loops_per_jiffy;
- smp_tune_scheduling();
}
void __devinit smp_prepare_boot_cpu(void)
@@ -1217,13 +1194,28 @@ void __devinit smp_fill_in_sib_core_maps(void)
unsigned int j;
if (cpu_data(i).core_id == 0) {
- cpu_set(i, cpu_sibling_map[i]);
+ cpu_set(i, cpu_core_map[i]);
continue;
}
for_each_possible_cpu(j) {
if (cpu_data(i).core_id ==
cpu_data(j).core_id)
+ cpu_set(j, cpu_core_map[i]);
+ }
+ }
+
+ for_each_possible_cpu(i) {
+ unsigned int j;
+
+ if (cpu_data(i).proc_id == -1) {
+ cpu_set(i, cpu_sibling_map[i]);
+ continue;
+ }
+
+ for_each_possible_cpu(j) {
+ if (cpu_data(i).proc_id ==
+ cpu_data(j).proc_id)
cpu_set(j, cpu_sibling_map[i]);
}
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index d00f51a5683..6fa76161289 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -24,6 +24,7 @@
#include <linux/syscalls.h>
#include <linux/percpu.h>
#include <linux/init.h>
+#include <linux/rwsem.h>
#include <net/compat.h>
#include <asm/oplib.h>
@@ -58,7 +59,6 @@
#include <asm/ns87303.h>
#include <asm/timer.h>
#include <asm/cpudata.h>
-#include <asm/rwsem.h>
struct poll {
int fd;
diff --git a/arch/sparc64/kernel/sysfs.c b/arch/sparc64/kernel/sysfs.c
new file mode 100644
index 00000000000..cdb1477af89
--- /dev/null
+++ b/arch/sparc64/kernel/sysfs.c
@@ -0,0 +1,297 @@
+/* sysfs.c: Toplogy sysfs support code for sparc64.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
+
+#include <asm/hypervisor.h>
+#include <asm/spitfire.h>
+
+static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64)));
+
+#define SHOW_MMUSTAT_ULONG(NAME) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+ struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \
+ return sprintf(buf, "%lu\n", p->NAME); \
+} \
+static SYSDEV_ATTR(NAME, 0444, show_##NAME, NULL)
+
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_8k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_64k_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_4mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte);
+SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte);
+
+static struct attribute *mmu_stat_attrs[] = {
+ &attr_immu_tsb_hits_ctx0_8k_tte.attr,
+ &attr_immu_tsb_ticks_ctx0_8k_tte.attr,
+ &attr_immu_tsb_hits_ctx0_64k_tte.attr,
+ &attr_immu_tsb_ticks_ctx0_64k_tte.attr,
+ &attr_immu_tsb_hits_ctx0_4mb_tte.attr,
+ &attr_immu_tsb_ticks_ctx0_4mb_tte.attr,
+ &attr_immu_tsb_hits_ctx0_256mb_tte.attr,
+ &attr_immu_tsb_ticks_ctx0_256mb_tte.attr,
+ &attr_immu_tsb_hits_ctxnon0_8k_tte.attr,
+ &attr_immu_tsb_ticks_ctxnon0_8k_tte.attr,
+ &attr_immu_tsb_hits_ctxnon0_64k_tte.attr,
+ &attr_immu_tsb_ticks_ctxnon0_64k_tte.attr,
+ &attr_immu_tsb_hits_ctxnon0_4mb_tte.attr,
+ &attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr,
+ &attr_immu_tsb_hits_ctxnon0_256mb_tte.attr,
+ &attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr,
+ &attr_dmmu_tsb_hits_ctx0_8k_tte.attr,
+ &attr_dmmu_tsb_ticks_ctx0_8k_tte.attr,
+ &attr_dmmu_tsb_hits_ctx0_64k_tte.attr,
+ &attr_dmmu_tsb_ticks_ctx0_64k_tte.attr,
+ &attr_dmmu_tsb_hits_ctx0_4mb_tte.attr,
+ &attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr,
+ &attr_dmmu_tsb_hits_ctx0_256mb_tte.attr,
+ &attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr,
+ &attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr,
+ &attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr,
+ &attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr,
+ &attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr,
+ &attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr,
+ &attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr,
+ &attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr,
+ &attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr,
+ NULL,
+};
+
+static struct attribute_group mmu_stat_group = {
+ .attrs = mmu_stat_attrs,
+ .name = "mmu_stats",
+};
+
+/* XXX convert to rusty's on_one_cpu */
+static unsigned long run_on_cpu(unsigned long cpu,
+ unsigned long (*func)(unsigned long),
+ unsigned long arg)
+{
+ cpumask_t old_affinity = current->cpus_allowed;
+ unsigned long ret;
+
+ /* should return -EINVAL to userspace */
+ if (set_cpus_allowed(current, cpumask_of_cpu(cpu)))
+ return 0;
+
+ ret = func(arg);
+
+ set_cpus_allowed(current, old_affinity);
+
+ return ret;
+}
+
+static unsigned long read_mmustat_enable(unsigned long junk)
+{
+ unsigned long ra = 0;
+
+ sun4v_mmustat_info(&ra);
+
+ return ra != 0;
+}
+
+static unsigned long write_mmustat_enable(unsigned long val)
+{
+ unsigned long ra, orig_ra;
+
+ if (val)
+ ra = __pa(&per_cpu(mmu_stats, smp_processor_id()));
+ else
+ ra = 0UL;
+
+ return sun4v_mmustat_conf(ra, &orig_ra);
+}
+
+static ssize_t show_mmustat_enable(struct sys_device *s, char *buf)
+{
+ unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0);
+ return sprintf(buf, "%lx\n", val);
+}
+
+static ssize_t store_mmustat_enable(struct sys_device *s, const char *buf, size_t count)
+{
+ unsigned long val, err;
+ int ret = sscanf(buf, "%ld", &val);
+
+ if (ret != 1)
+ return -EINVAL;
+
+ err = run_on_cpu(s->id, write_mmustat_enable, val);
+ if (err)
+ return -EIO;
+
+ return count;
+}
+
+static SYSDEV_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable);
+
+static int mmu_stats_supported;
+
+static int register_mmu_stats(struct sys_device *s)
+{
+ if (!mmu_stats_supported)
+ return 0;
+ sysdev_create_file(s, &attr_mmustat_enable);
+ return sysfs_create_group(&s->kobj, &mmu_stat_group);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void unregister_mmu_stats(struct sys_device *s)
+{
+ if (!mmu_stats_supported)
+ return;
+ sysfs_remove_group(&s->kobj, &mmu_stat_group);
+ sysdev_remove_file(s, &attr_mmustat_enable);
+}
+#endif
+
+#define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+ cpuinfo_sparc *c = &cpu_data(dev->id); \
+ return sprintf(buf, "%lu\n", c->MEMBER); \
+}
+
+#define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \
+static ssize_t show_##NAME(struct sys_device *dev, char *buf) \
+{ \
+ cpuinfo_sparc *c = &cpu_data(dev->id); \
+ return sprintf(buf, "%u\n", c->MEMBER); \
+}
+
+SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick);
+SHOW_CPUDATA_ULONG_NAME(udelay_val, udelay_val);
+SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size);
+SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size);
+SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size);
+SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size);
+SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size);
+SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size);
+
+static struct sysdev_attribute cpu_core_attrs[] = {
+ _SYSDEV_ATTR(clock_tick, 0444, show_clock_tick, NULL),
+ _SYSDEV_ATTR(udelay_val, 0444, show_udelay_val, NULL),
+ _SYSDEV_ATTR(l1_dcache_size, 0444, show_l1_dcache_size, NULL),
+ _SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
+ _SYSDEV_ATTR(l1_icache_size, 0444, show_l1_icache_size, NULL),
+ _SYSDEV_ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL),
+ _SYSDEV_ATTR(l2_cache_size, 0444, show_l2_cache_size, NULL),
+ _SYSDEV_ATTR(l2_cache_line_size, 0444, show_l2_cache_line_size, NULL),
+};
+
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+
+static void register_cpu_online(unsigned int cpu)
+{
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+ struct sys_device *s = &c->sysdev;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
+ sysdev_create_file(s, &cpu_core_attrs[i]);
+
+ register_mmu_stats(s);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void unregister_cpu_online(unsigned int cpu)
+{
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+ struct sys_device *s = &c->sysdev;
+ int i;
+
+ unregister_mmu_stats(s);
+ for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
+ sysdev_remove_file(s, &cpu_core_attrs[i]);
+}
+#endif
+
+static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned int)(long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ register_cpu_online(cpu);
+ break;
+#ifdef CONFIG_HOTPLUG_CPU
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ unregister_cpu_online(cpu);
+ break;
+#endif
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
+ .notifier_call = sysfs_cpu_notify,
+};
+
+static void __init check_mmu_stats(void)
+{
+ unsigned long dummy1, err;
+
+ if (tlb_type != hypervisor)
+ return;
+
+ err = sun4v_mmustat_info(&dummy1);
+ if (!err)
+ mmu_stats_supported = 1;
+}
+
+static int __init topology_init(void)
+{
+ int cpu;
+
+ check_mmu_stats();
+
+ register_cpu_notifier(&sysfs_cpu_nb);
+
+ for_each_possible_cpu(cpu) {
+ struct cpu *c = &per_cpu(cpu_devices, cpu);
+
+ register_cpu(c, cpu);
+ if (cpu_online(cpu))
+ register_cpu_online(cpu);
+ }
+
+ return 0;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
index fb648de18a8..3ad10f3027e 100644
--- a/arch/sparc64/kernel/vmlinux.lds.S
+++ b/arch/sparc64/kernel/vmlinux.lds.S
@@ -1,5 +1,6 @@
/* ld script to make UltraLinux kernel */
+#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>
OUTPUT_FORMAT("elf64-sparc", "elf64-sparc", "elf64-sparc")
@@ -23,7 +24,7 @@ SECTIONS
_etext = .;
PROVIDE (etext = .);
- RODATA
+ RO_DATA(PAGE_SIZE)
.data :
{
@@ -44,7 +45,7 @@ SECTIONS
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
- . = ALIGN(8192);
+ . = ALIGN(PAGE_SIZE);
__init_begin = .;
.init.text : {
_sinittext = .;
@@ -83,17 +84,17 @@ SECTIONS
__sun4v_2insn_patch_end = .;
#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(8192);
+ . = ALIGN(PAGE_SIZE);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
#endif
- . = ALIGN(8192);
+ . = ALIGN(PAGE_SIZE);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
- . = ALIGN(8192);
+ . = ALIGN(PAGE_SIZE);
__init_end = .;
__bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c504312219b..e6ff3026654 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -278,6 +278,7 @@ config HIGHMEM
config KERNEL_STACK_ORDER
int "Kernel stack size order"
default 1 if 64BIT
+ range 1 10 if 64BIT
default 0 if !64BIT
help
This option determines the size of UML kernel stacks. They will
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index ced99106f79..4bd40bb43ec 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -3,6 +3,7 @@
* Licensed under the GPL
*/
+#include "linux/kernel.h"
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/list.h"
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 91153929387..4739dd527b4 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -1,3 +1,4 @@
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/console.h>
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 70509ddaac0..2e09f162c42 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -20,6 +20,7 @@
#define MAJOR_NR UBD_MAJOR
#define UBD_SHIFT 4
+#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/blkdev.h"
#include "linux/hdreg.h"
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 541f4a8ca51..7376ee44e33 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -9,6 +9,7 @@ OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
OFFSET(HOST_TASK_PID, task_struct, pid);
DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
+DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index 8b7f2cdedf9..c716b5a6db1 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -1,8 +1,9 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
+#include "linux/kernel.h"
#include "linux/init.h"
#include "linux/ctype.h"
#include "linux/proc_fs.h"
@@ -24,11 +25,14 @@ static int read_proc_exitcode(char *page, char **start, off_t off,
val = uml_exitcode;
len = sprintf(page, "%d\n", val);
len -= off;
- if(len <= off+count) *eof = 1;
+ if(len <= off+count)
+ *eof = 1;
*start = page + off;
- if(len > count) len = count;
- if(len < 0) len = 0;
- return(len);
+ if(len > count)
+ len = count;
+ if(len < 0)
+ len = 0;
+ return len;
}
static int write_proc_exitcode(struct file *file, const char __user *buffer,
@@ -38,12 +42,14 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer,
int tmp;
if(copy_from_user(buf, buffer, count))
- return(-EFAULT);
+ return -EFAULT;
+
tmp = simple_strtol(buf, &end, 0);
if((*end != '\0') && !isspace(*end))
- return(-EINVAL);
+ return -EINVAL;
+
uml_exitcode = tmp;
- return(count);
+ return count;
}
static int make_proc_exitcode(void)
@@ -54,24 +60,13 @@ static int make_proc_exitcode(void)
if(ent == NULL){
printk(KERN_WARNING "make_proc_exitcode : Failed to register "
"/proc/exitcode\n");
- return(0);
+ return 0;
}
ent->read_proc = read_proc_exitcode;
ent->write_proc = write_proc_exitcode;
-
- return(0);
+
+ return 0;
}
__initcall(make_proc_exitcode);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index ea9a23696f3..fb510d40480 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -24,6 +24,7 @@
#include "uml-config.h"
#include "os.h"
#include "um_malloc.h"
+#include "kern_constants.h"
/* Set in main, unchanged thereafter */
char *linux_prog;
@@ -232,7 +233,8 @@ void *__wrap_malloc(int size)
if(!CAN_KMALLOC())
return __real_malloc(size);
- else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/
+ else if(size <= UM_KERN_PAGE_SIZE)
+ /* finding contiguous pages can be hard*/
ret = um_kmalloc(size);
else ret = um_vmalloc(size);
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 5c894632079..0f7df4eb903 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -25,6 +25,7 @@
#include "sysdep/ptrace.h"
#include "sysdep/stub.h"
#include "init.h"
+#include "kern_constants.h"
extern unsigned long batch_syscall_stub, __syscall_stub_start;
@@ -149,8 +150,8 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall,
*stack = 0;
multi_op_count++;
- if(!done && ((((unsigned long) stack) & ~PAGE_MASK) <
- PAGE_SIZE - 10 * sizeof(long))){
+ if(!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) <
+ UM_KERN_PAGE_SIZE - 10 * sizeof(long))){
*addr = stack;
return 0;
}
@@ -168,8 +169,8 @@ long syscall_stub_data(struct mm_id * mm_idp,
/* If *addr still is uninitialized, it *must* contain NULL.
* Thus in this case do_syscall_stub correctly won't be called.
*/
- if((((unsigned long) *addr) & ~PAGE_MASK) >=
- PAGE_SIZE - (10 + data_count) * sizeof(long)) {
+ if((((unsigned long) *addr) & ~UM_KERN_PAGE_MASK) >=
+ UM_KERN_PAGE_SIZE - (10 + data_count) * sizeof(long)) {
ret = do_syscall_stub(mm_idp, addr);
/* in case of error, don't overwrite data on stack */
if(ret)
@@ -183,8 +184,8 @@ long syscall_stub_data(struct mm_id * mm_idp,
memcpy(stack + 1, data, data_count * sizeof(long));
- *stub_addr = (void *)(((unsigned long)(stack + 1) & ~PAGE_MASK) +
- UML_CONFIG_STUB_DATA);
+ *stub_addr = (void *)(((unsigned long)(stack + 1) &
+ ~UM_KERN_PAGE_MASK) + UML_CONFIG_STUB_DATA);
return 0;
}
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index f9d2f8545af..46c00cc429b 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -252,11 +252,12 @@ int start_userspace(unsigned long stub_stack)
unsigned long sp;
int pid, status, n, flags;
- stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+ stack = mmap(NULL, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(stack == MAP_FAILED)
panic("start_userspace : mmap failed, errno = %d", errno);
- sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
+ sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
flags = CLONE_FILES | SIGCHLD;
if(proc_mm) flags |= CLONE_VM;
@@ -279,7 +280,7 @@ int start_userspace(unsigned long stub_stack)
panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n",
errno);
- if(munmap(stack, PAGE_SIZE) < 0)
+ if(munmap(stack, UM_KERN_PAGE_SIZE) < 0)
panic("start_userspace : munmap failed, errno = %d\n", errno);
return(pid);
@@ -365,7 +366,7 @@ static int __init init_thread_regs(void)
thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
(unsigned long) stub_clone_handler -
(unsigned long) &__syscall_stub_start;
- thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
+ thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE -
sizeof(void *);
#ifdef __SIGNAL_FRAMESIZE
thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
@@ -453,7 +454,7 @@ void map_stub_pages(int fd, unsigned long code,
.u =
{ .mmap =
{ .addr = code,
- .len = PAGE_SIZE,
+ .len = UM_KERN_PAGE_SIZE,
.prot = PROT_EXEC,
.flags = MAP_FIXED | MAP_PRIVATE,
.fd = code_fd,
@@ -476,7 +477,7 @@ void map_stub_pages(int fd, unsigned long code,
.u =
{ .mmap =
{ .addr = data,
- .len = PAGE_SIZE,
+ .len = UM_KERN_PAGE_SIZE,
.prot = PROT_READ | PROT_WRITE,
.flags = MAP_FIXED | MAP_SHARED,
.fd = map_fd,
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 3fc13fa8729..46f613975c1 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -107,11 +107,12 @@ static int start_ptraced_child(void **stack_out)
unsigned long sp;
int pid, n, status;
- stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+ stack = mmap(NULL, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(stack == MAP_FAILED)
fatal_perror("check_ptrace : mmap failed");
- sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
+ sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
if(pid < 0)
fatal_perror("start_ptraced_child : clone failed");
@@ -153,7 +154,7 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode,
ret = -1;
}
- if(munmap(stack, PAGE_SIZE) < 0)
+ if(munmap(stack, UM_KERN_PAGE_SIZE) < 0)
fatal_perror("check_ptrace : munmap failed");
return ret;
}
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 5ce94430c01..8bdd25ac154 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -427,6 +427,10 @@ config NR_CPUS
This is purely to save memory - each supported CPU requires
memory in the static kernel configuration.
+config PHYSICAL_ALIGN
+ hex
+ default "0x200000"
+
config HOTPLUG_CPU
bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)"
depends on SMP && HOTPLUG && EXPERIMENTAL
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index ee6f6505f95..67096389de1 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -1,135 +1,9 @@
#
# arch/x86_64/boot/Makefile
#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-# Copyright (C) 1994 by Linus Torvalds
-#
-
-# ROOT_DEV specifies the default root-device when making the image.
-# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
-# the default of FLOPPY is used by 'build'.
-
-ROOT_DEV := CURRENT
-
-# If you want to preset the SVGA mode, uncomment the next line and
-# set SVGA_MODE to whatever number you want.
-# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
-# The number is the same as you would ordinarily press at bootup.
-
-SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
-
-# If you want the RAM disk device, define this to be the size in blocks.
-
-#RAMDISK := -DRAMDISK=512
-
-targets := vmlinux.bin bootsect bootsect.o \
- setup setup.o bzImage mtools.conf
-
-EXTRA_CFLAGS := -m32
-
-hostprogs-y := tools/build
-HOST_EXTRACFLAGS += $(LINUXINCLUDE)
-subdir- := compressed/ #Let make clean descend in compressed/
-# ---------------------------------------------------------------------------
-
-$(obj)/bzImage: IMAGE_OFFSET := 0x100000
-$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
-$(obj)/bzImage: BUILDFLAGS := -b
-
-quiet_cmd_image = BUILD $@
-cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
- $(obj)/vmlinux.bin $(ROOT_DEV) > $@
-
-$(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
- $(obj)/vmlinux.bin $(obj)/tools/build FORCE
- $(call if_changed,image)
- @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
-
-$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
- $(call if_changed,objcopy)
-
-LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
-LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext
-
-$(obj)/setup $(obj)/bootsect: %: %.o FORCE
- $(call if_changed,ld)
-
-$(obj)/compressed/vmlinux: FORCE
- $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
-
-# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel
-FDARGS =
-# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel
-FDINITRD =
-
-image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,)
-
-$(obj)/mtools.conf: $(src)/mtools.conf.in
- sed -e 's|@OBJ@|$(obj)|g' < $< > $@
-
-# This requires write access to /dev/fd0
-zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
- MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync
- syslinux /dev/fd0 ; sync
- echo '$(image_cmdline)' | \
- MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg
- if [ -f '$(FDINITRD)' ] ; then \
- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \
- fi
- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync
-
-# These require being root or having syslinux 2.02 or higher installed
-fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
- dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
- MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync
- syslinux $(obj)/fdimage ; sync
- echo '$(image_cmdline)' | \
- MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
- if [ -f '$(FDINITRD)' ] ; then \
- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \
- fi
- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync
-
-fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
- dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
- MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync
- syslinux $(obj)/fdimage ; sync
- echo '$(image_cmdline)' | \
- MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
- if [ -f '$(FDINITRD)' ] ; then \
- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \
- fi
- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync
-
-isoimage: $(BOOTIMAGE)
- -rm -rf $(obj)/isoimage
- mkdir $(obj)/isoimage
- for i in lib lib64 share end ; do \
- if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
- cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
- break ; \
- fi ; \
- if [ $$i = end ] ; then exit 1 ; fi ; \
- done
- cp $(BOOTIMAGE) $(obj)/isoimage/linux
- echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
- if [ -f '$(FDINITRD)' ] ; then \
- cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \
- fi
- mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \
- -no-emul-boot -boot-load-size 4 -boot-info-table \
- $(obj)/isoimage
- rm -rf $(obj)/isoimage
-
-zlilo: $(BOOTIMAGE)
- if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
- if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
- cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
- cp System.map $(INSTALL_PATH)/
- if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+# The actual boot code is shared with i386 including the Makefile.
+# So tell kbuild that we fetch the code from i386 and include the
+# Makefile from i386 too.
-install:
- sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)"
+src := arch/i386/boot
+include $(src)/Makefile
diff --git a/arch/x86_64/boot/bootsect.S b/arch/x86_64/boot/bootsect.S
deleted file mode 100644
index 011b7a4993d..00000000000
--- a/arch/x86_64/boot/bootsect.S
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds
- *
- * modified by Drew Eckhardt
- * modified by Bruce Evans (bde)
- * modified by Chris Noe (May 1999) (as86 -> gas)
- * gutted by H. Peter Anvin (Jan 2003)
- *
- * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
- * addresses must be multiplied by 16 to obtain their respective linear
- * addresses. To avoid confusion, linear addresses are written using leading
- * hex while segment addresses are written as segment:offset.
- *
- */
-
-#include <asm/boot.h>
-
-SETUPSECTS = 4 /* default nr of setup-sectors */
-BOOTSEG = 0x07C0 /* original address of boot-sector */
-INITSEG = DEF_INITSEG /* we move boot here - out of the way */
-SETUPSEG = DEF_SETUPSEG /* setup starts here */
-SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */
-SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */
- /* to be loaded */
-ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */
-SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
-
-#ifndef SVGA_MODE
-#define SVGA_MODE ASK_VGA
-#endif
-
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif
-
-#ifndef ROOT_RDONLY
-#define ROOT_RDONLY 1
-#endif
-
-.code16
-.text
-
-.global _start
-_start:
-
- # Normalize the start address
- jmpl $BOOTSEG, $start2
-
-start2:
- movw %cs, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- movw $0x7c00, %sp
- sti
- cld
-
- movw $bugger_off_msg, %si
-
-msg_loop:
- lodsb
- andb %al, %al
- jz die
- movb $0xe, %ah
- movw $7, %bx
- int $0x10
- jmp msg_loop
-
-die:
- # Allow the user to press a key, then reboot
- xorw %ax, %ax
- int $0x16
- int $0x19
-
- # int 0x19 should never return. In case it does anyway,
- # invoke the BIOS reset code...
- ljmp $0xf000,$0xfff0
-
-
-bugger_off_msg:
- .ascii "Direct booting from floppy is no longer supported.\r\n"
- .ascii "Please use a boot loader program instead.\r\n"
- .ascii "\n"
- .ascii "Remove disk and press any key to reboot . . .\r\n"
- .byte 0
-
-
- # Kernel attributes; used by setup
-
- .org 497
-setup_sects: .byte SETUPSECTS
-root_flags: .word ROOT_RDONLY
-syssize: .word SYSSIZE
-swap_dev: .word SWAP_DEV
-ram_size: .word RAMDISK
-vid_mode: .word SVGA_MODE
-root_dev: .word ROOT_DEV
-boot_flag: .word 0xAA55
diff --git a/arch/x86_64/boot/compressed/Makefile b/arch/x86_64/boot/compressed/Makefile
index 705a3e33d7e..c9f2da7496c 100644
--- a/arch/x86_64/boot/compressed/Makefile
+++ b/arch/x86_64/boot/compressed/Makefile
@@ -7,11 +7,12 @@
#
targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-EXTRA_AFLAGS := -traditional
-# cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with
-# -m32
-CFLAGS := -m64 -D__KERNEL__ -Iinclude -O2 -fno-strict-aliasing -fPIC -mcmodel=small -fno-builtin
+CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \
+ -fno-strict-aliasing -fPIC -mcmodel=small \
+ $(call cc-option, -ffreestanding) \
+ $(call cc-option, -fno-stack-protector)
+AFLAGS := $(CFLAGS) -D__ASSEMBLY__
LDFLAGS := -m elf_x86_64
LDFLAGS_vmlinux := -T
diff --git a/arch/x86_64/boot/compressed/head.S b/arch/x86_64/boot/compressed/head.S
index f9d5692a010..1312bfaff30 100644
--- a/arch/x86_64/boot/compressed/head.S
+++ b/arch/x86_64/boot/compressed/head.S
@@ -46,10 +46,10 @@ startup_32:
* at and where we were actually loaded at. This can only be done
* with a short local call on x86. Nothing else will tell us what
* address we are running at. The reserved chunk of the real-mode
- * data at 0x34-0x3f are used as the stack for this calculation.
- * Only 4 bytes are needed.
+ * data at 0x1e4 (defined as a scratch field) are used as the stack
+ * for this calculation. Only 4 bytes are needed.
*/
- leal 0x40(%esi), %esp
+ leal (0x1e4+4)(%esi), %esp
call 1f
1: popl %ebp
subl $1b, %ebp
diff --git a/arch/x86_64/boot/install.sh b/arch/x86_64/boot/install.sh
deleted file mode 100644
index baaa2369bdb..00000000000
--- a/arch/x86_64/boot/install.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-. $srctree/arch/i386/boot/install.sh
diff --git a/arch/x86_64/boot/mtools.conf.in b/arch/x86_64/boot/mtools.conf.in
deleted file mode 100644
index efd6d2490c1..00000000000
--- a/arch/x86_64/boot/mtools.conf.in
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# mtools configuration file for "make (b)zdisk"
-#
-
-# Actual floppy drive
-drive a:
- file="/dev/fd0"
-
-# 1.44 MB floppy disk image
-drive v:
- file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
-
-# 2.88 MB floppy disk image (mostly for virtual uses)
-drive w:
- file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
-
-
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
deleted file mode 100644
index e9e33f94969..00000000000
--- a/arch/x86_64/boot/setup.S
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
- * setup.S Copyright (C) 1991, 1992 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- * Move PS/2 aux init code to psaux.c
- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *
- * some changes and additional features by Christoph Niemann,
- * March 1993/June 1994 (Christoph.Niemann@linux.org)
- *
- * add APM BIOS checking by Stephen Rothwell, May 1994
- * (sfr@canb.auug.org.au)
- *
- * High load stuff, initrd support and position independency
- * by Hans Lermen & Werner Almesberger, February 1996
- * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
- *
- * Video handling moved to video.S by Martin Mares, March 1996
- * <mj@k332.feld.cvut.cz>
- *
- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
- * parsons) to avoid loadlin confusion, July 1997
- *
- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
- * <stiker@northlink.com>
- *
- * Fix to work around buggy BIOSes which don't use carry bit correctly
- * and/or report extended memory in CX/DX for e801h memory size detection
- * call. As a result the kernel got wrong figures. The int15/e801h docs
- * from Ralf Brown interrupt list seem to indicate AX/BX should be used
- * anyway. So to avoid breaking many machines (presumably there was a reason
- * to orginally use CX/DX instead of AX/BX), we do a kludge to see
- * if CX/DX have been changed in the e801 call and if so use AX/BX .
- * Michael Miller, April 2001 <michaelm@mjmm.org>
- *
- * Added long mode checking and SSE force. March 2003, Andi Kleen.
- */
-
-#include <asm/segment.h>
-#include <linux/utsrelease.h>
-#include <linux/compile.h>
-#include <asm/boot.h>
-#include <asm/e820.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-
-/* Signature words to ensure LILO loaded us right */
-#define SIG1 0xAA55
-#define SIG2 0x5A5A
-
-INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way
-SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment
- # ... and the former contents of CS
-
-DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020
-
-.code16
-.globl begtext, begdata, begbss, endtext, enddata, endbss
-
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-start:
- jmp trampoline
-
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
- .ascii "HdrS" # header signature
- .word 0x0206 # header version number (>= 0x0105)
- # or else old loadlin-1.5 will fail)
-realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
-start_sys_seg: .word SYSSEG
- .word kernel_version # pointing to kernel version string
- # above section of header is compatible
- # with loadlin-1.5 (header v1.5). Don't
- # change it.
-
-type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin,
- # Bootlin, SYSLX, bootsect...)
- # See Documentation/i386/boot.txt for
- # assigned ids
-
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH = 1 # If set, the kernel is loaded high
-CAN_USE_HEAP = 0x80 # If set, the loader also has set
- # heap_end_ptr to tell how much
- # space behind setup.S can be used for
- # heap purposes.
- # Only the loader knows what is free
-#ifndef __BIG_KERNEL__
- .byte 0
-#else
- .byte LOADED_HIGH
-#endif
-
-setup_move_size: .word 0x8000 # size to move, when setup is not
- # loaded at 0x90000. We will move setup
- # to 0x90000 then just before jumping
- # into the kernel. However, only the
- # loader knows how much data behind
- # us also needs to be loaded.
-
-code32_start: # here loaders can put a different
- # start address for 32-bit code.
-#ifndef __BIG_KERNEL__
- .long 0x1000 # 0x1000 = default for zImage
-#else
- .long 0x100000 # 0x100000 = default for big kernel
-#endif
-
-ramdisk_image: .long 0 # address of loaded ramdisk image
- # Here the loader puts the 32-bit
- # address where it loaded the image.
- # This only will be read by the kernel.
-
-ramdisk_size: .long 0 # its size in bytes
-
-bootsect_kludge:
- .long 0 # obsolete
-
-heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later)
- # space from here (exclusive) down to
- # end of setup code can be used by setup
- # for local heap purposes.
-
-pad1: .word 0
-cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
- # If nonzero, a 32-bit pointer
- # to the kernel command line.
- # The command line should be
- # located between the start of
- # setup and the end of low
- # memory (0xa0000), or it may
- # get overwritten before it
- # gets read. If this field is
- # used, there is no longer
- # anything magical about the
- # 0x90000 segment; the setup
- # can be located anywhere in
- # low memory 0x10000 or higher.
-
-ramdisk_max: .long 0xffffffff
-kernel_alignment: .long 0x200000 # physical addr alignment required for
- # protected mode relocatable kernel
-#ifdef CONFIG_RELOCATABLE
-relocatable_kernel: .byte 1
-#else
-relocatable_kernel: .byte 0
-#endif
-pad2: .byte 0
-pad3: .word 0
-
-cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line,
- #added with boot protocol
- #version 2.06
-
-trampoline: call start_of_setup
- .align 16
- # The offset at this point is 0x240
- .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff)
-# End of setup header #####################################################
-
-start_of_setup:
-# Bootlin depends on this being done early
- movw $0x01500, %ax
- movb $0x81, %dl
- int $0x13
-
-#ifdef SAFE_RESET_DISK_CONTROLLER
-# Reset the disk controller.
- movw $0x0000, %ax
- movb $0x80, %dl
- int $0x13
-#endif
-
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
-# Check signature at end of setup
- cmpw $SIG1, setup_sig1
- jne bad_sig
-
- cmpw $SIG2, setup_sig2
- jne bad_sig
-
- jmp good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
- lodsb
- andb %al, %al
- jz fin
-
- call prtchr
- jmp prtstr
-
-fin: ret
-
-# Space printing
-prtsp2: call prtspc # Print double space
-prtspc: movb $0x20, %al # Print single space (note: fall-thru)
-
-prtchr:
- pushw %ax
- pushw %cx
- movw $0007,%bx
- movw $0x01, %cx
- movb $0x0e, %ah
- int $0x10
- popw %cx
- popw %ax
- ret
-
-beep: movb $0x07, %al
- jmp prtchr
-
-no_sig_mess: .string "No setup signature found ..."
-
-good_sig1:
- jmp good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
- movw %cs, %ax # SETUPSEG
- subw $DELTA_INITSEG, %ax # INITSEG
- movw %ax, %ds
- xorb %bh, %bh
- movb (497), %bl # get setup sect from bootsect
- subw $4, %bx # LILO loads 4 sectors of setup
- shlw $8, %bx # convert to words (1sect=2^8 words)
- movw %bx, %cx
- shrw $3, %bx # convert to segment
- addw $SYSSEG, %bx
- movw %bx, %cs:start_sys_seg
-# Move rest of setup code/data to here
- movw $2048, %di # four sectors loaded by LILO
- subw %si, %si
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %es
- movw $SYSSEG, %ax
- movw %ax, %ds
- rep
- movsw
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
- cmpw $SIG1, setup_sig1
- jne no_sig
-
- cmpw $SIG2, setup_sig2
- jne no_sig
-
- jmp good_sig
-
-no_sig:
- lea no_sig_mess, %si
- call prtstr
-
-no_sig_loop:
- jmp no_sig_loop
-
-good_sig:
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %ds
-# Check if an old loader tries to load a big-kernel
- testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel?
- jz loader_ok # No, no danger for old loaders.
-
- cmpb $0, %cs:type_of_loader # Do we have a loader that
- # can deal with us?
- jnz loader_ok # Yes, continue.
-
- pushw %cs # No, we have an old loader,
- popw %ds # die.
- lea loader_panic_mess, %si
- call prtstr
-
- jmp no_sig_loop
-
-loader_panic_mess: .string "Wrong loader, giving up..."
-
-loader_ok:
- /* check for long mode. */
- /* we have to do this before the VESA setup, otherwise the user
- can't see the error message. */
-
- pushw %ds
- movw %cs,%ax
- movw %ax,%ds
-
- call verify_cpu
- testl %eax,%eax
- jz sse_ok
-
-no_longmode:
- call beep
- lea long_mode_panic,%si
- call prtstr
-no_longmode_loop:
- jmp no_longmode_loop
-long_mode_panic:
- .string "Your CPU does not support long mode. Use a 32bit distribution."
- .byte 0
-
-#include "../kernel/verify_cpu.S"
-sse_ok:
- popw %ds
-
-# tell BIOS we want to go to long mode
- movl $0xec00,%eax # declare target operating mode
- movl $2,%ebx # long mode
- int $0x15
-
-# Get memory size (extended mem, kB)
-
- xorl %eax, %eax
- movl %eax, (0x1e0)
-#ifndef STANDARD_MEMORY_BIOS_CALL
- movb %al, (E820NR)
-# Try three different memory detection schemes. First, try
-# e820h, which lets us assemble a memory map, then try e801h,
-# which returns a 32-bit memory size, and finally 88h, which
-# returns 0-64m
-
-# method E820H:
-# the memory map from hell. e820h returns memory classified into
-# a whole bunch of different types, and allows memory holes and
-# everything. We scan through this memory map and build a list
-# of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
-
-#define SMAP 0x534d4150
-
-meme820:
- xorl %ebx, %ebx # continuation counter
- movw $E820MAP, %di # point into the whitelist
- # so we can have the bios
- # directly write into it.
-
-jmpe820:
- movl $0x0000e820, %eax # e820, upper word zeroed
- movl $SMAP, %edx # ascii 'SMAP'
- movl $20, %ecx # size of the e820rec
- pushw %ds # data record.
- popw %es
- int $0x15 # make the call
- jc bail820 # fall to e801 if it fails
-
- cmpl $SMAP, %eax # check the return is `SMAP'
- jne bail820 # fall to e801 if it fails
-
-# cmpl $1, 16(%di) # is this usable memory?
-# jne again820
-
- # If this is usable memory, we save it by simply advancing %di by
- # sizeof(e820rec).
- #
-good820:
- movb (E820NR), %al # up to 128 entries
- cmpb $E820MAX, %al
- jae bail820
-
- incb (E820NR)
- movw %di, %ax
- addw $20, %ax
- movw %ax, %di
-again820:
- cmpl $0, %ebx # check to see if
- jne jmpe820 # %ebx is set to EOF
-bail820:
-
-
-# method E801H:
-# memory size is in 1k chunksizes, to avoid confusing loadlin.
-# we store the 0xe801 memory size in a completely different place,
-# because it will most likely be longer than 16 bits.
-# (use 1e0 because that's what Larry Augustine uses in his
-# alternative new memory detection scheme, and it's sensible
-# to write everything into the same place.)
-
-meme801:
- stc # fix to work around buggy
- xorw %cx,%cx # BIOSes which don't clear/set
- xorw %dx,%dx # carry on pass/error of
- # e801h memory size call
- # or merely pass cx,dx though
- # without changing them.
- movw $0xe801, %ax
- int $0x15
- jc mem88
-
- cmpw $0x0, %cx # Kludge to handle BIOSes
- jne e801usecxdx # which report their extended
- cmpw $0x0, %dx # memory in AX/BX rather than
- jne e801usecxdx # CX/DX. The spec I have read
- movw %ax, %cx # seems to indicate AX/BX
- movw %bx, %dx # are more reasonable anyway...
-
-e801usecxdx:
- andl $0xffff, %edx # clear sign extend
- shll $6, %edx # and go from 64k to 1k chunks
- movl %edx, (0x1e0) # store extended memory size
- andl $0xffff, %ecx # clear sign extend
- addl %ecx, (0x1e0) # and add lower memory into
- # total size.
-
-# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
-# 64mb, depending on the bios) in ax.
-mem88:
-
-#endif
- movb $0x88, %ah
- int $0x15
- movw %ax, (2)
-
-# Set the keyboard repeat rate to the max
- movw $0x0305, %ax
- xorw %bx, %bx
- int $0x16
-
-# Check for video adapter and its parameters and allow the
-# user to browse video modes.
- call video # NOTE: we need %ds pointing
- # to bootsector
-
-# Get hd0 data...
- xorw %ax, %ax
- movw %ax, %ds
- ldsw (4 * 0x41), %si
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- pushw %ax
- movw %ax, %es
- movw $0x0080, %di
- movw $0x10, %cx
- pushw %cx
- cld
- rep
- movsb
-# Get hd1 data...
- xorw %ax, %ax
- movw %ax, %ds
- ldsw (4 * 0x46), %si
- popw %cx
- popw %es
- movw $0x0090, %di
- rep
- movsb
-# Check that there IS a hd1 :-)
- movw $0x01500, %ax
- movb $0x81, %dl
- int $0x13
- jc no_disk1
-
- cmpb $3, %ah
- je is_disk1
-
-no_disk1:
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %es
- movw $0x0090, %di
- movw $0x10, %cx
- xorw %ax, %ax
- cld
- rep
- stosb
-is_disk1:
-
-# Check for PS/2 pointing device
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %ds
- movb $0, (0x1ff) # default is no pointing device
- int $0x11 # int 0x11: equipment list
- testb $0x04, %al # check if mouse installed
- jz no_psmouse
-
- movb $0xAA, (0x1ff) # device present
-no_psmouse:
-
-#include "../../i386/boot/edd.S"
-
-# Now we want to move to protected mode ...
- cmpw $0, %cs:realmode_swtch
- jz rmodeswtch_normal
-
- lcall *%cs:realmode_swtch
-
- jmp rmodeswtch_end
-
-rmodeswtch_normal:
- pushw %cs
- call default_switch
-
-rmodeswtch_end:
-# we get the code32 start address and modify the below 'jmpi'
-# (loader may have changed it)
- movl %cs:code32_start, %eax
- movl %eax, %cs:code32
-
-# Now we move the system to its rightful place ... but we check if we have a
-# big-kernel. In that case we *must* not move it ...
- testb $LOADED_HIGH, %cs:loadflags
- jz do_move0 # .. then we have a normal low
- # loaded zImage
- # .. or else we have a high
- # loaded bzImage
- jmp end_move # ... and we skip moving
-
-do_move0:
- movw $0x100, %ax # start of destination segment
- movw %cs, %bp # aka SETUPSEG
- subw $DELTA_INITSEG, %bp # aka INITSEG
- movw %cs:start_sys_seg, %bx # start of source segment
- cld
-do_move:
- movw %ax, %es # destination segment
- incb %ah # instead of add ax,#0x100
- movw %bx, %ds # source segment
- addw $0x100, %bx
- subw %di, %di
- subw %si, %si
- movw $0x800, %cx
- rep
- movsw
- cmpw %bp, %bx # assume start_sys_seg > 0x200,
- # so we will perhaps read one
- # page more than needed, but
- # never overwrite INITSEG
- # because destination is a
- # minimum one page below source
- jb do_move
-
-end_move:
-# then we load the segment descriptors
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
-
-# Check whether we need to be downward compatible with version <=201
- cmpl $0, cmd_line_ptr
- jne end_move_self # loader uses version >=202 features
- cmpb $0x20, type_of_loader
- je end_move_self # bootsect loader, we know of it
-
-# Boot loader doesnt support boot protocol version 2.02.
-# If we have our code not at 0x90000, we need to move it there now.
-# We also then need to move the params behind it (commandline)
-# Because we would overwrite the code on the current IP, we move
-# it in two steps, jumping high after the first one.
- movw %cs, %ax
- cmpw $SETUPSEG, %ax
- je end_move_self
-
- cli # make sure we really have
- # interrupts disabled !
- # because after this the stack
- # should not be used
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ss, %dx
- cmpw %ax, %dx
- jb move_self_1
-
- addw $INITSEG, %dx
- subw %ax, %dx # this will go into %ss after
- # the move
-move_self_1:
- movw %ax, %ds
- movw $INITSEG, %ax # real INITSEG
- movw %ax, %es
- movw %cs:setup_move_size, %cx
- std # we have to move up, so we use
- # direction down because the
- # areas may overlap
- movw %cx, %di
- decw %di
- movw %di, %si
- subw $move_self_here+0x200, %cx
- rep
- movsb
- ljmp $SETUPSEG, $move_self_here
-
-move_self_here:
- movw $move_self_here+0x200, %cx
- rep
- movsb
- movw $SETUPSEG, %ax
- movw %ax, %ds
- movw %dx, %ss
-end_move_self: # now we are at the right place
- lidt idt_48 # load idt with 0,0
- xorl %eax, %eax # Compute gdt_base
- movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
- shll $4, %eax
- addl $gdt, %eax
- movl %eax, (gdt_48+2)
- lgdt gdt_48 # load gdt with whatever is
- # appropriate
-
-# that was painless, now we enable a20
- call empty_8042
-
- movb $0xD1, %al # command write
- outb %al, $0x64
- call empty_8042
-
- movb $0xDF, %al # A20 on
- outb %al, $0x60
- call empty_8042
-
-#
-# You must preserve the other bits here. Otherwise embarrasing things
-# like laptops powering off on boot happen. Corrected version by Kira
-# Brown from Linux 2.2
-#
- inb $0x92, %al #
- orb $02, %al # "fast A20" version
- outb %al, $0x92 # some chips have only this
-
-# wait until a20 really *is* enabled; it can take a fair amount of
-# time on certain systems; Toshiba Tecras are known to have this
-# problem. The memory location used here (0x200) is the int 0x80
-# vector, which should be safe to use.
-
- xorw %ax, %ax # segment 0x0000
- movw %ax, %fs
- decw %ax # segment 0xffff (HMA)
- movw %ax, %gs
-a20_wait:
- incw %ax # unused memory location <0xfff0
- movw %ax, %fs:(0x200) # we use the "int 0x80" vector
- cmpw %gs:(0x210), %ax # and its corresponding HMA addr
- je a20_wait # loop until no longer aliased
-
-# make sure any possible coprocessor is properly reset..
- xorw %ax, %ax
- outb %al, $0xf0
- call delay
-
- outb %al, $0xf1
- call delay
-
-# well, that went ok, I hope. Now we mask all interrupts - the rest
-# is done in init_IRQ().
- movb $0xFF, %al # mask all interrupts for now
- outb %al, $0xA1
- call delay
-
- movb $0xFB, %al # mask all irq's but irq2 which
- outb %al, $0x21 # is cascaded
-
-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-# need no steenking BIOS anyway (except for the initial loading :-).
-# The BIOS-routine wants lots of unnecessary data, and it's less
-# "interesting" anyway. This is how REAL programmers do it.
-#
-# Well, now's the time to actually move into protected mode. To make
-# things as simple as possible, we do no register set-up or anything,
-# we let the gnu-compiled 32-bit programs do that. We just jump to
-# absolute address 0x1000 (or the loader supplied one),
-# in 32-bit protected mode.
-#
-# Note that the short jump isn't strictly needed, although there are
-# reasons why it might be a good idea. It won't hurt in any case.
- movw $1, %ax # protected mode (PE) bit
- lmsw %ax # This is it!
- jmp flush_instr
-
-flush_instr:
- xorw %bx, %bx # Flag to indicate a boot
- xorl %esi, %esi # Pointer to real-mode code
- movw %cs, %si
- subw $DELTA_INITSEG, %si
- shll $4, %esi # Convert to 32-bit pointer
-# NOTE: For high loaded big kernels we need a
-# jmpi 0x100000,__KERNEL_CS
-#
-# but we yet haven't reloaded the CS register, so the default size
-# of the target offset still is 16 bit.
-# However, using an operand prefix (0x66), the CPU will properly
-# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
-# Manual, Mixing 16-bit and 32-bit code, page 16-6)
-
- .byte 0x66, 0xea # prefix + jmpi-opcode
-code32: .long 0x1000 # will be set to 0x100000
- # for big kernels
- .word __KERNEL_CS
-
-# Here's a bunch of information about your current kernel..
-kernel_version: .ascii UTS_RELEASE
- .ascii " ("
- .ascii LINUX_COMPILE_BY
- .ascii "@"
- .ascii LINUX_COMPILE_HOST
- .ascii ") "
- .ascii UTS_VERSION
- .byte 0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
- cli # no interrupts allowed !
- movb $0x80, %al # disable NMI for bootup
- # sequence
- outb %al, $0x70
- lret
-
-
-# This routine checks that the keyboard command queue is empty
-# (after emptying the output buffers)
-#
-# Some machines have delusions that the keyboard buffer is always full
-# with no keyboard attached...
-#
-# If there is no keyboard controller, we will usually get 0xff
-# to all the reads. With each IO taking a microsecond and
-# a timeout of 100,000 iterations, this can take about half a
-# second ("delay" == outb to port 0x80). That should be ok,
-# and should also be plenty of time for a real keyboard controller
-# to empty.
-#
-
-empty_8042:
- pushl %ecx
- movl $100000, %ecx
-
-empty_8042_loop:
- decl %ecx
- jz empty_8042_end_loop
-
- call delay
-
- inb $0x64, %al # 8042 status port
- testb $1, %al # output buffer?
- jz no_output
-
- call delay
- inb $0x60, %al # read it
- jmp empty_8042_loop
-
-no_output:
- testb $2, %al # is input buffer full?
- jnz empty_8042_loop # yes - loop
-empty_8042_end_loop:
- popl %ecx
- ret
-
-# Read the cmos clock. Return the seconds in al
-gettime:
- pushw %cx
- movb $0x02, %ah
- int $0x1a
- movb %dh, %al # %dh contains the seconds
- andb $0x0f, %al
- movb %dh, %ah
- movb $0x04, %cl
- shrb %cl, %ah
- aad
- popw %cx
- ret
-
-# Delay is needed after doing I/O
-delay:
- outb %al,$0x80
- ret
-
-# Descriptor tables
-gdt:
- .word 0, 0, 0, 0 # dummy
-
- .word 0, 0, 0, 0 # unused
-
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9A00 # code read/exec
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9200 # data read/write
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-gdt_end:
-idt_48:
- .word 0 # idt limit = 0
- .word 0, 0 # idt base = 0L
-gdt_48:
- .word gdt_end-gdt-1 # gdt limit
- .word 0, 0 # gdt base (filled in later)
-
-# Include video setup & detection code
-
-#include "../../i386/boot/video.S"
-
-# Setup signature -- must be last
-setup_sig1: .word SIG1
-setup_sig2: .word SIG2
-
-# After this point, there is some free space which is used by the video mode
-# handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/arch/x86_64/boot/tools/build.c b/arch/x86_64/boot/tools/build.c
deleted file mode 100644
index eae86691709..00000000000
--- a/arch/x86_64/boot/tools/build.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 1991, 1992 Linus Torvalds
- * Copyright (C) 1997 Martin Mares
- */
-
-/*
- * This file builds a disk-image from three different files:
- *
- * - bootsect: compatibility mbr which prints an error message if
- * someone tries to boot the kernel directly.
- * - setup: 8086 machine code, sets up system parm
- * - system: 80386 code for actual system
- *
- * It does some checking that all files are of the correct type, and
- * just writes the result to stdout, removing headers and padding to
- * the right amount. It also writes some system data to stderr.
- */
-
-/*
- * Changes by tytso to allow root device specification
- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
- * Cross compiling fixes by Gertjan van Wingerde, July 1996
- * Rewritten by Martin Mares, April 1997
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <asm/boot.h>
-
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long u32;
-
-#define DEFAULT_MAJOR_ROOT 0
-#define DEFAULT_MINOR_ROOT 0
-
-/* Minimal number of setup sectors (see also bootsect.S) */
-#define SETUP_SECTS 4
-
-byte buf[1024];
-int fd;
-int is_big_kernel;
-
-void die(const char * str, ...)
-{
- va_list args;
- va_start(args, str);
- vfprintf(stderr, str, args);
- fputc('\n', stderr);
- exit(1);
-}
-
-void file_open(const char *name)
-{
- if ((fd = open(name, O_RDONLY, 0)) < 0)
- die("Unable to open `%s': %m", name);
-}
-
-void usage(void)
-{
- die("Usage: build [-b] bootsect setup system [rootdev] [> image]");
-}
-
-int main(int argc, char ** argv)
-{
- unsigned int i, c, sz, setup_sectors;
- u32 sys_size;
- byte major_root, minor_root;
- struct stat sb;
-
- if (argc > 2 && !strcmp(argv[1], "-b"))
- {
- is_big_kernel = 1;
- argc--, argv++;
- }
- if ((argc < 4) || (argc > 5))
- usage();
- if (argc > 4) {
- if (!strcmp(argv[4], "CURRENT")) {
- if (stat("/", &sb)) {
- perror("/");
- die("Couldn't stat /");
- }
- major_root = major(sb.st_dev);
- minor_root = minor(sb.st_dev);
- } else if (strcmp(argv[4], "FLOPPY")) {
- if (stat(argv[4], &sb)) {
- perror(argv[4]);
- die("Couldn't stat root device.");
- }
- major_root = major(sb.st_rdev);
- minor_root = minor(sb.st_rdev);
- } else {
- major_root = 0;
- minor_root = 0;
- }
- } else {
- major_root = DEFAULT_MAJOR_ROOT;
- minor_root = DEFAULT_MINOR_ROOT;
- }
- fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root);
-
- file_open(argv[1]);
- i = read(fd, buf, sizeof(buf));
- fprintf(stderr,"Boot sector %d bytes.\n",i);
- if (i != 512)
- die("Boot block must be exactly 512 bytes");
- if (buf[510] != 0x55 || buf[511] != 0xaa)
- die("Boot block hasn't got boot flag (0xAA55)");
- buf[508] = minor_root;
- buf[509] = major_root;
- if (write(1, buf, 512) != 512)
- die("Write call failed");
- close (fd);
-
- file_open(argv[2]); /* Copy the setup code */
- for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c )
- if (write(1, buf, c) != c)
- die("Write call failed");
- if (c != 0)
- die("read-error on `setup'");
- close (fd);
-
- setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */
- /* for compatibility with ancient versions of LILO. */
- if (setup_sectors < SETUP_SECTS)
- setup_sectors = SETUP_SECTS;
- fprintf(stderr, "Setup is %d bytes.\n", i);
- memset(buf, 0, sizeof(buf));
- while (i < setup_sectors * 512) {
- c = setup_sectors * 512 - i;
- if (c > sizeof(buf))
- c = sizeof(buf);
- if (write(1, buf, c) != c)
- die("Write call failed");
- i += c;
- }
-
- file_open(argv[3]);
- if (fstat (fd, &sb))
- die("Unable to stat `%s': %m", argv[3]);
- sz = sb.st_size;
- fprintf (stderr, "System is %d kB\n", sz/1024);
- sys_size = (sz + 15) / 16;
- if (!is_big_kernel && sys_size > DEF_SYSSIZE)
- die("System is too big. Try using bzImage or modules.");
- while (sz > 0) {
- int l, n;
-
- l = (sz > sizeof(buf)) ? sizeof(buf) : sz;
- if ((n=read(fd, buf, l)) != l) {
- if (n < 0)
- die("Error reading %s: %m", argv[3]);
- else
- die("%s: Unexpected EOF", argv[3]);
- }
- if (write(1, buf, l) != l)
- die("Write failed");
- sz -= l;
- }
- close(fd);
-
- if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */
- die("Output: seek failed");
- buf[0] = setup_sectors;
- if (write(1, buf, 1) != 1)
- die("Write of setup sector count failed");
- if (lseek(1, 500, SEEK_SET) != 500)
- die("Output: seek failed");
- buf[0] = (sys_size & 0xff);
- buf[1] = ((sys_size >> 8) & 0xff);
- buf[2] = ((sys_size >> 16) & 0xff);
- buf[3] = ((sys_size >> 24) & 0xff);
- if (write(1, buf, 4) != 4)
- die("Write of image length failed");
-
- return 0; /* Everything is OK */
-}
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 21868f9bed7..47565c3345d 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -620,7 +620,7 @@ ia32_sys_call_table:
.quad quiet_ni_syscall /* tux */
.quad quiet_ni_syscall /* security */
.quad sys_gettid
- .quad sys_readahead /* 225 */
+ .quad sys32_readahead /* 225 */
.quad sys_setxattr
.quad sys_lsetxattr
.quad sys_fsetxattr
@@ -645,7 +645,7 @@ ia32_sys_call_table:
.quad compat_sys_io_getevents
.quad compat_sys_io_submit
.quad sys_io_cancel
- .quad sys_fadvise64 /* 250 */
+ .quad sys32_fadvise64 /* 250 */
.quad quiet_ni_syscall /* free_huge_pages */
.quad sys_exit_group
.quad sys32_lookup_dcookie
@@ -709,7 +709,7 @@ ia32_sys_call_table:
.quad compat_sys_set_robust_list
.quad compat_sys_get_robust_list
.quad sys_splice
- .quad sys_sync_file_range
+ .quad sys32_sync_file_range
.quad sys_tee /* 315 */
.quad compat_sys_vmsplice
.quad compat_sys_move_pages
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 200fdde18d9..99a78a3cce7 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -860,3 +860,22 @@ long sys32_lookup_dcookie(u32 addr_low, u32 addr_high,
return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
}
+asmlinkage ssize_t sys32_readahead(int fd, unsigned off_lo, unsigned off_hi, size_t count)
+{
+ return sys_readahead(fd, ((u64)off_hi << 32) | off_lo, count);
+}
+
+asmlinkage long sys32_sync_file_range(int fd, unsigned off_low, unsigned off_hi,
+ unsigned n_low, unsigned n_hi, int flags)
+{
+ return sys_sync_file_range(fd,
+ ((u64)off_hi << 32) | off_low,
+ ((u64)n_hi << 32) | n_low, flags);
+}
+
+asmlinkage long sys32_fadvise64(int fd, unsigned offset_lo, unsigned offset_hi, size_t len,
+ int advice)
+{
+ return sys_fadvise64_64(fd, ((u64)offset_hi << 32) | offset_lo,
+ len, advice);
+}
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index de1de8a2fd8..47f1dc30bf5 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_PCI) += early-quirks.o
obj-y += topology.o
obj-y += intel_cacheinfo.o
+obj-y += addon_cpuid_features.o
obj-y += pcspeaker.o
CFLAGS_vsyscall.o := $(PROFILING) -g0
@@ -55,6 +56,7 @@ cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o
topology-y += ../../i386/kernel/topology.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o
intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o
+addon_cpuid_features-y += ../../i386/kernel/cpu/addon_cpuid_features.o
quirks-y += ../../i386/kernel/quirks.o
i8237-y += ../../i386/kernel/i8237.o
msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o
diff --git a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig
index c0749d2479f..a3fd51926cb 100644
--- a/arch/x86_64/kernel/cpufreq/Kconfig
+++ b/arch/x86_64/kernel/cpufreq/Kconfig
@@ -48,10 +48,6 @@ config X86_SPEEDSTEP_CENTRINO
If in doubt, say N.
-config X86_SPEEDSTEP_CENTRINO_ACPI
- bool
- depends on X86_SPEEDSTEP_CENTRINO
-
config X86_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver"
select CPU_FREQ_TABLE
@@ -73,7 +69,7 @@ comment "shared options"
config X86_ACPI_CPUFREQ_PROC_INTF
bool "/proc/acpi/processor/../performance interface (deprecated)"
depends on PROC_FS
- depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K8_ACPI
+ depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K8_ACPI
help
This enables the deprecated /proc/acpi/processor/../performance
interface. While it is helpful for debugging, the generic,
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index fa984b53e7e..a67f87bf401 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -1163,3 +1163,10 @@ ENTRY(call_softirq)
ret
CFI_ENDPROC
ENDPROC(call_softirq)
+
+KPROBE_ENTRY(ignore_sysret)
+ CFI_STARTPROC
+ mov $-ENOSYS,%eax
+ sysret
+ CFI_ENDPROC
+ENDPROC(ignore_sysret)
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index d8bfe315471..1c6c6f72457 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -1492,6 +1492,7 @@ static void ack_lapic_irq (unsigned int irq)
static void end_lapic_irq (unsigned int i) { /* nothing */ }
static struct hw_interrupt_type lapic_irq_type __read_mostly = {
+ .name = "local-APIC",
.typename = "local-APIC-edge",
.startup = NULL, /* startup_irq() not used for IRQ0 */
.shutdown = NULL, /* shutdown_irq() not used for IRQ0 */
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 3eaceac3248..39cb3fa83eb 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -144,17 +144,43 @@ void fixup_irqs(cpumask_t map)
for (irq = 0; irq < NR_IRQS; irq++) {
cpumask_t mask;
+ int break_affinity = 0;
+ int set_affinity = 1;
+
if (irq == 2)
continue;
+ /* interrupt's are disabled at this point */
+ spin_lock(&irq_desc[irq].lock);
+
+ if (!irq_has_action(irq) ||
+ cpus_equal(irq_desc[irq].affinity, map)) {
+ spin_unlock(&irq_desc[irq].lock);
+ continue;
+ }
+
cpus_and(mask, irq_desc[irq].affinity, map);
- if (any_online_cpu(mask) == NR_CPUS) {
- printk("Breaking affinity for irq %i\n", irq);
+ if (cpus_empty(mask)) {
+ break_affinity = 1;
mask = map;
}
+
+ if (irq_desc[irq].chip->mask)
+ irq_desc[irq].chip->mask(irq);
+
if (irq_desc[irq].chip->set_affinity)
irq_desc[irq].chip->set_affinity(irq, mask);
- else if (irq_desc[irq].action && !(warned++))
+ else if (!(warned++))
+ set_affinity = 0;
+
+ if (irq_desc[irq].chip->unmask)
+ irq_desc[irq].chip->unmask(irq);
+
+ spin_unlock(&irq_desc[irq].lock);
+
+ if (break_affinity && set_affinity)
+ printk("Broke affinity for irq %i\n", irq);
+ else if (!set_affinity)
printk("Cannot set affinity for irq %i\n", irq);
}
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index a14375dd542..aa1d1599179 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -497,15 +497,17 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
for (i = 0; i < next; i++) {
unsigned long start = jiffies;
while (!mcelog.entry[i].finished) {
- if (!time_before(jiffies, start + 2)) {
+ if (time_after_eq(jiffies, start + 2)) {
memset(mcelog.entry + i,0, sizeof(struct mce));
- continue;
+ goto timeout;
}
cpu_relax();
}
smp_rmb();
err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce));
buf += sizeof(struct mce);
+ timeout:
+ ;
}
memset(mcelog.entry, 0, next * sizeof(struct mce));
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 651ccfb0669..90f6315d02d 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -22,8 +22,7 @@ EXPORT_SYMBOL(bad_dma_address);
int iommu_bio_merge __read_mostly = 0;
EXPORT_SYMBOL(iommu_bio_merge);
-int iommu_sac_force __read_mostly = 0;
-EXPORT_SYMBOL(iommu_sac_force);
+static int iommu_sac_force __read_mostly = 0;
int no_iommu __read_mostly;
#ifdef CONFIG_IOMMU_DEBUG
@@ -322,5 +321,17 @@ static int __init pci_iommu_init(void)
return 0;
}
+#ifdef CONFIG_PCI
+/* Many VIA bridges seem to corrupt data for DAC. Disable it here */
+
+static __devinit void via_no_dac(struct pci_dev *dev)
+{
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) {
+ printk(KERN_INFO "PCI: VIA PCI bridge detected. Disabling DAC.\n");
+ forbid_dac = 1;
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac);
+#endif
/* Must execute after PCI subsystem */
fs_initcall(pci_iommu_init);
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index eb6524f3ac2..33ef718f8cb 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -846,6 +846,8 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
c->x86_capability[2] = cpuid_edx(0x80860001);
}
+ init_scattered_cpuid_features(c);
+
c->apicid = phys_pkg_id(0);
/*
@@ -931,7 +933,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
"pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
- "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL,
+ "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
/* AMD-defined */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -947,10 +949,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* Other (Linux-defined) */
- "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
- "constant_tsc", NULL, NULL,
- "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+ NULL, NULL, NULL, NULL,
+ "constant_tsc", "up", NULL, "arch_perfmon",
+ "pebs", "bts", NULL, "sync_rdtsc",
+ "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* Intel-defined (#2) */
@@ -961,7 +964,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* VIA/Cyrix/Centaur-defined */
NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -972,6 +975,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"osvw", "ibs", NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ /* Auxiliary (Linux-defined) */
+ "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static char *x86_power_flags[] = {
"ts", /* temperature sensor */
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 64379a80d76..1200aaac403 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -150,6 +150,8 @@ void pda_init(int cpu)
char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]
__attribute__((section(".bss.page_aligned")));
+extern asmlinkage void ignore_sysret(void);
+
/* May not be marked __init: used by software suspend */
void syscall_init(void)
{
@@ -160,6 +162,7 @@ void syscall_init(void)
*/
wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32);
wrmsrl(MSR_LSTAR, system_call);
+ wrmsrl(MSR_CSTAR, ignore_sysret);
#ifdef CONFIG_IA32_EMULATION
syscall32_cpu_init ();
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index cb29fb96948..aac1c0be54c 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -465,13 +465,14 @@ static unsigned int die_nest_count;
unsigned __kprobes long oops_begin(void)
{
- int cpu = smp_processor_id();
+ int cpu;
unsigned long flags;
oops_enter();
/* racy, but better than risking deadlock. */
local_irq_save(flags);
+ cpu = smp_processor_id();
if (!spin_trylock(&die_lock)) {
if (cpu == die_owner)
/* nested oops. should stop eventually */;
diff --git a/arch/x86_64/kernel/verify_cpu.S b/arch/x86_64/kernel/verify_cpu.S
index e035f594819..45b6f8a975a 100644
--- a/arch/x86_64/kernel/verify_cpu.S
+++ b/arch/x86_64/kernel/verify_cpu.S
@@ -37,20 +37,6 @@ verify_cpu:
pushl $0 # Kill any dangerous flags
popfl
- /* minimum CPUID flags for x86-64 as defined by AMD */
-#define M(x) (1<<(x))
-#define M2(a,b) M(a)|M(b)
-#define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d)
-
-#define SSE_MASK \
- (M2(X86_FEATURE_XMM,X86_FEATURE_XMM2))
-#define REQUIRED_MASK1 \
- (M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\
- M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\
- M(X86_FEATURE_FXSR))
-#define REQUIRED_MASK2 \
- (M(X86_FEATURE_LM - 32))
-
pushfl # standard way to check for cpuid
popl %eax
movl %eax,%ebx
@@ -79,8 +65,8 @@ verify_cpu:
verify_cpu_noamd:
movl $0x1,%eax # Does the cpu have what it takes
cpuid
- andl $REQUIRED_MASK1,%edx
- xorl $REQUIRED_MASK1,%edx
+ andl $REQUIRED_MASK0,%edx
+ xorl $REQUIRED_MASK0,%edx
jnz verify_cpu_no_longmode
movl $0x80000000,%eax # See if extended cpuid is implemented
@@ -90,8 +76,8 @@ verify_cpu_noamd:
movl $0x80000001,%eax # Does the cpu have what it takes
cpuid
- andl $REQUIRED_MASK2,%edx
- xorl $REQUIRED_MASK2,%edx
+ andl $REQUIRED_MASK1,%edx
+ xorl $REQUIRED_MASK1,%edx
jnz verify_cpu_no_longmode
verify_cpu_sse_test:
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index bfb62a13d7e..635e58d443d 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -476,6 +476,12 @@ bad_area:
bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */
if (error_code & PF_USER) {
+
+ /*
+ * It's possible to have interrupts off here.
+ */
+ local_irq_enable();
+
if (is_prefetch(regs, address, error_code))
return;
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 1336da8bdee..9a0e98accf0 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -79,6 +79,8 @@ void show_mem(void)
if (unlikely(i % MAX_ORDER_NR_PAGES == 0)) {
touch_nmi_watchdog();
}
+ if (!pfn_valid(pgdat->node_start_pfn + i))
+ continue;
page = pfn_to_page(pgdat->node_start_pfn + i);
total++;
if (PageReserved(page))
@@ -603,6 +605,11 @@ void mark_rodata_ro(void)
if (num_possible_cpus() > 1)
start = (unsigned long)_etext;
#endif
+
+#ifdef CONFIG_KPROBES
+ start = (unsigned long)__start_rodata;
+#endif
+
end = (unsigned long)__end_rodata;
start = (start + PAGE_SIZE - 1) & PAGE_MASK;
end &= PAGE_MASK;
@@ -761,3 +768,9 @@ int in_gate_area_no_task(unsigned long addr)
{
return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
}
+
+void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+{
+ return __alloc_bootmem_core(pgdat->bdata, size,
+ SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0);
+}
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c
index d653d0bf3df..9148f4a4cec 100644
--- a/arch/x86_64/mm/pageattr.c
+++ b/arch/x86_64/mm/pageattr.c
@@ -74,10 +74,11 @@ static void flush_kernel_map(void *arg)
struct page *pg;
/* When clflush is available always use it because it is
- much cheaper than WBINVD */
- if (!cpu_has_clflush)
+ much cheaper than WBINVD. Disable clflush for now because
+ the high level code is not ready yet */
+ if (1 || !cpu_has_clflush)
asm volatile("wbinvd" ::: "memory");
- list_for_each_entry(pg, l, lru) {
+ else list_for_each_entry(pg, l, lru) {
void *adr = page_address(pg);
if (cpu_has_clflush)
cache_flush_page(adr);
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index 698079b3a33..d0323cd6a2e 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -39,6 +39,7 @@ int main(void)
DEFINE(PT_LEND, offsetof (struct pt_regs, lend));
DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount));
DEFINE(PT_SAR, offsetof (struct pt_regs, sar));
+ DEFINE(PT_ICOUNTLEVEL, offsetof (struct pt_regs, icountlevel));
DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall));
DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0]));
DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 9e271ba009b..8dc7a2c26ff 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -125,8 +125,9 @@ _user_exception:
movi a2, 0
rsr a3, SAR
- wsr a2, ICOUNTLEVEL
+ 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 */
@@ -276,8 +277,9 @@ _kernel_exception:
movi a2, 0
rsr a3, SAR
- wsr a2, ICOUNTLEVEL
+ 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 */
@@ -330,14 +332,16 @@ _kernel_exception:
common_exception:
- /* Save EXCVADDR, DEBUGCAUSE, and PC, and clear LCOUNT */
+ /* Save some registers, disable loops and clear the syscall flag. */
rsr a2, DEBUGCAUSE
rsr a3, EPC_1
s32i a2, a1, PT_DEBUGCAUSE
s32i a3, a1, PT_PC
+ movi a2, -1
rsr a3, EXCVADDR
+ s32i a2, a1, PT_SYSCALL
movi a2, 0
s32i a3, a1, PT_EXCVADDR
xsr a2, LCOUNT
@@ -450,27 +454,8 @@ common_exception_return:
/* Restore the state of the task and return from the exception. */
-
- /* If we are returning from a user exception, and the process
- * to run next has PT_SINGLESTEP set, we want to setup
- * ICOUNT and ICOUNTLEVEL to step one instruction.
- * PT_SINGLESTEP is set by sys_ptrace (ptrace.c)
- */
-
4: /* a2 holds GET_CURRENT(a2,a1) */
- l32i a3, a2, TI_TASK
- l32i a3, a3, TASK_PTRACE
- bbci.l a3, PT_SINGLESTEP_BIT, 1f # jump if single-step flag is not set
-
- movi a3, -2 # PT_SINGLESTEP flag is set,
- movi a4, 1 # icountlevel of 1 means it won't
- wsr a3, ICOUNT # start counting until after rfe
- wsr a4, ICOUNTLEVEL # so setup icount & icountlevel.
- isync
-
-1:
-
#if XCHAL_EXTRA_SA_SIZE
/* For user exceptions, restore the extra state from the user's TCB. */
@@ -665,6 +650,13 @@ common_exception_exit:
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
+
/* Check if it was double exception. */
l32i a0, a1, PT_DEPC
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index ea89910efa4..67e69139520 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -19,6 +19,8 @@
#include <asm/page.h>
#include <asm/cacheasm.h>
+#include <linux/linkage.h>
+
/*
* This module contains the entry code for kernel images. It performs the
* minimal setup needed to call the generic C routines.
@@ -227,13 +229,14 @@ _startup:
should_never_return:
j should_never_return
- /* Define some common data structures here. We define them
- * here in this assembly file due to their unusual alignment
- * requirements.
- */
- .comm swapper_pg_dir,PAGE_SIZE,PAGE_SIZE
- .comm empty_bad_page_table,PAGE_SIZE,PAGE_SIZE
- .comm empty_bad_page,PAGE_SIZE,PAGE_SIZE
- .comm empty_zero_page,PAGE_SIZE,PAGE_SIZE
+/*
+ * BSS section
+ */
+
+.section ".bss.page_aligned", "w"
+ENTRY(swapper_pg_dir)
+ .fill PAGE_SIZE, 1, 0
+ENTRY(empty_zero_page)
+ .fill PAGE_SIZE, 1, 0
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 45571ccb72d..77deae5290f 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -401,7 +401,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
* Also, think for a moment about likes of floppy.c that
* include architecture specific parts. They may want to redefine ins/outs.
*
- * We do not use horroble macroses here because we want to
+ * We do not use horrible macros here because we want to
* advance pointer by sizeof(size).
*/
void outsb(unsigned long addr, const void *src, unsigned long count) {
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
index 1ecf6716c32..2e8d398cf19 100644
--- a/arch/xtensa/kernel/setup.c
+++ b/arch/xtensa/kernel/setup.c
@@ -41,6 +41,7 @@
#include <asm/platform.h>
#include <asm/page.h>
#include <asm/setup.h>
+#include <asm/param.h>
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 58107672a61..033aae0336d 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -1,397 +1,239 @@
-// TODO coprocessor stuff
/*
- * linux/arch/xtensa/kernel/signal.c
+ * arch/xtensa/kernel/signal.c
*
- * Copyright (C) 1991, 1992 Linus Torvalds
- * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
- *
- * Joe Taylor <joe@tensilica.com>
- * Chris Zankel <chris@zankel.net>
+ * Default platform functions.
*
+ * 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, 2006 Tensilica Inc.
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
*
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com>
*/
-#include <asm/variant/core.h>
-#include <asm/coprocessor.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
-#include <linux/wait.h>
#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
#include <linux/personality.h>
+#include <linux/freezer.h>
+
#include <asm/ucontext.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.h>
#include <asm/cacheflush.h>
+#include <asm/coprocessor.h>
+#include <asm/unistd.h>
#define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options,
- struct rusage * ru);
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
extern struct task_struct *coproc_owners[];
+extern void release_all_cp (struct task_struct *);
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
+struct rt_sigframe
+{
+ struct siginfo info;
+ struct ucontext uc;
+ cp_state_t cpstate;
+ unsigned char retcode[6];
+ unsigned int window[4];
+};
+
+/*
+ * Flush register windows stored in pt_regs to stack.
+ * Returns 1 for errors.
+ *
+ * Note that windowbase, windowstart, and wmask are not updated!
*/
-int xtensa_sigsuspend(struct pt_regs *regs)
+int
+flush_window_regs_user(struct pt_regs *regs)
{
- old_sigset_t mask = (old_sigset_t) regs->areg[3];
- sigset_t saveset;
+ const unsigned long ws = regs->windowstart;
+ const unsigned long wb = regs->windowbase;
+ unsigned long sp = 0;
+ unsigned long wm;
+ int err = 1;
+ int base;
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ /* Return if no other frames. */
- regs->areg[2] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
+ if (regs->wmask == 1)
+ return 0;
-asmlinkage int
-xtensa_rt_sigsuspend(struct pt_regs *regs)
-{
- sigset_t *unewset = (sigset_t *) regs->areg[4];
- size_t sigsetsize = (size_t) regs->areg[3];
- sigset_t saveset, newset;
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
+ /* Rotate windowmask and skip empty frames. */
- if (copy_from_user(&newset, unewset, sizeof(newset)))
- return -EFAULT;
- sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ wm = (ws >> wb) | (ws << (XCHAL_NUM_AREGS / 4 - wb));
+ base = (XCHAL_NUM_AREGS / 4) - (regs->wmask >> 4);
+
+ /* For call8 or call12 frames, we need the previous stack pointer. */
- regs->areg[2] = -EINTR;
- while (1) {
- current->state = TASK_INTERRUPTIBLE;
- schedule();
- if (do_signal(regs, &saveset))
- return -EINTR;
- }
-}
+ if ((regs->wmask & 2) == 0)
+ if (__get_user(sp, (int*)(regs->areg[base * 4 + 1] - 12)))
+ goto errout;
-asmlinkage int
-xtensa_sigaction(int sig, const struct old_sigaction *act,
- struct old_sigaction *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
+ /* Spill frames to stack. */
- if (act) {
- old_sigset_t mask;
- if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
- return -EFAULT;
- __get_user(new_ka.sa.sa_flags, &act->sa_flags);
- __get_user(mask, &act->sa_mask);
- siginitset(&new_ka.sa.sa_mask, mask);
- }
+ while (base < XCHAL_NUM_AREGS / 4) {
- ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+ int m = (wm >> base);
+ int inc = 0;
- if (!ret && oact) {
- if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
- return -EFAULT;
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
- }
+ /* Save registers a4..a7 (call8) or a4...a11 (call12) */
- return ret;
-}
+ if (m & 2) { /* call4 */
+ inc = 1;
-asmlinkage int
-xtensa_sigaltstack(struct pt_regs *regs)
-{
- const stack_t *uss = (stack_t *) regs->areg[4];
- stack_t *uoss = (stack_t *) regs->areg[3];
+ } else if (m & 4) { /* call8 */
+ if (copy_to_user((void*)(sp - 32),
+ &regs->areg[(base + 1) * 4], 16))
+ goto errout;
+ inc = 2;
- if (regs->depc > 64)
- panic ("Double exception sys_sigreturn\n");
+ } else if (m & 8) { /* call12 */
+ if (copy_to_user((void*)(sp - 48),
+ &regs->areg[(base + 1) * 4], 32))
+ goto errout;
+ inc = 3;
+ }
+ /* Save current frame a0..a3 under next SP */
- return do_sigaltstack(uss, uoss, regs->areg[1]);
-}
+ sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS];
+ if (copy_to_user((void*)(sp - 16), &regs->areg[base * 4], 16))
+ goto errout;
+
+ /* Get current stack pointer for next loop iteration. */
+
+ sp = regs->areg[base * 4 + 1];
+ base += inc;
+ }
+
+ return 0;
+errout:
+ return err;
+}
/*
- * Do a signal return; undo the signal stack.
+ * Note: We don't copy double exception 'regs', we have to finish double exc.
+ * first before we return to signal handler! This dbl.exc.handler might cause
+ * another double exception, but I think we are fine as the situation is the
+ * same as if we had returned to the signal handerl and got an interrupt
+ * immediately...
*/
-struct sigframe
-{
- struct sigcontext sc;
- struct _cpstate cpstate;
- unsigned long extramask[_NSIG_WORDS-1];
- unsigned char retcode[6];
- unsigned int reserved[4]; /* Reserved area for chaining */
- unsigned int window[4]; /* Window of 4 registers for initial context */
-};
-
-struct rt_sigframe
+static int
+setup_sigcontext(struct sigcontext __user *sc, cp_state_t *cpstate,
+ struct pt_regs *regs, unsigned long mask)
{
- struct siginfo info;
- struct ucontext uc;
- struct _cpstate cpstate;
- unsigned char retcode[6];
- unsigned int reserved[4]; /* Reserved area for chaining */
- unsigned int window[4]; /* Window of 4 registers for initial context */
-};
+ int err = 0;
-extern void release_all_cp (struct task_struct *);
+#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
+ COPY(pc);
+ COPY(ps);
+ COPY(lbeg);
+ COPY(lend);
+ COPY(lcount);
+ COPY(sar);
+#undef COPY
+ err |= flush_window_regs_user(regs);
+ err |= __copy_to_user (sc->sc_a, regs->areg, 16 * 4);
-// FIXME restore_cpextra
-static inline int
-restore_cpextra (struct _cpstate *buf)
-{
-#if 0
- /* The signal handler may have used coprocessors in which
- * case they are still enabled. We disable them to force a
- * reloading of the original task's CP state by the lazy
- * context-switching mechanisms of CP exception handling.
- * Also, we essentially discard any coprocessor state that the
- * signal handler created. */
+ // err |= __copy_to_user (sc->sc_a, regs->areg, XCHAL_NUM_AREGS * 4)
- struct task_struct *tsk = current;
- release_all_cp(tsk);
- return __copy_from_user(tsk->thread.cpextra, buf, XTENSA_CP_EXTRA_SIZE);
+#if XCHAL_HAVE_CP
+# error Coprocessors unsupported
+ err |= save_cpextra(cpstate);
+ err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate);
#endif
- return 0;
-}
-
-/* Note: We don't copy double exception 'tregs', we have to finish double exc. first before we return to signal handler! This dbl.exc.handler might cause another double exception, but I think we are fine as the situation is the same as if we had returned to the signal handerl and got an interrupt immediately...
- */
+ /* non-iBCS2 extensions.. */
+ err |= __put_user(mask, &sc->oldmask);
+ return err;
+}
static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
{
- struct thread_struct *thread;
unsigned int err = 0;
unsigned long ps;
- struct _cpstate *buf;
#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
COPY(pc);
- COPY(depc);
- COPY(wmask);
COPY(lbeg);
COPY(lend);
COPY(lcount);
COPY(sar);
- COPY(windowbase);
- COPY(windowstart);
#undef COPY
+ /* All registers were flushed to stack. Start with a prestine frame. */
+
+ regs->wmask = 1;
+ regs->windowbase = 0;
+ regs->windowstart = 1;
+
/* For PS, restore only PS.CALLINC.
* Assume that all other bits are either the same as for the signal
* handler, or the user mode value doesn't matter (e.g. PS.OWB).
*/
err |= __get_user(ps, &sc->sc_ps);
- regs->ps = (regs->ps & ~PS_CALLINC_MASK)
- | (ps & PS_CALLINC_MASK);
+ regs->ps = (regs->ps & ~PS_CALLINC_MASK) | (ps & PS_CALLINC_MASK);
/* Additional corruption checks */
- if ((regs->windowbase >= (XCHAL_NUM_AREGS/4))
- || ((regs->windowstart & ~((1<<(XCHAL_NUM_AREGS/4)) - 1)) != 0) )
- err = 1;
if ((regs->lcount > 0)
- && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
+ && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
err = 1;
- /* Restore extended register state.
- * See struct thread_struct in processor.h.
- */
- thread = &current->thread;
-
- err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4);
- err |= __get_user(buf, &sc->sc_cpstate);
- if (buf) {
- if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
- goto badframe;
- err |= restore_cpextra(buf);
- }
-
- regs->syscall = -1; /* disable syscall checks */
- return err;
-
-badframe:
- return 1;
-}
-
-static inline void
-flush_my_cpstate(struct task_struct *tsk)
-{
- unsigned long flags;
- local_irq_save(flags);
-
-#if 0 // FIXME
- for (i = 0; i < XCHAL_CP_NUM; i++) {
- if (tsk == coproc_owners[i]) {
- xthal_validate_cp(i);
- xthal_save_cpregs(tsk->thread.cpregs_ptr[i], i);
+ err |= __copy_from_user(regs->areg, sc->sc_a, 16 * 4);
- /* Invalidate and "disown" the cp to allow
- * callers the chance to reset cp state in the
- * task_struct. */
+#if XCHAL_HAVE_CP
+# error Coprocessors unsupported
+ /* The signal handler may have used coprocessors in which
+ * case they are still enabled. We disable them to force a
+ * reloading of the original task's CP state by the lazy
+ * context-switching mechanisms of CP exception handling.
+ * Also, we essentially discard any coprocessor state that the
+ * signal handler created. */
- xthal_invalidate_cp(i);
- coproc_owners[i] = 0;
- }
+ if (!err) {
+ struct task_struct *tsk = current;
+ release_all_cp(tsk);
+ err |= __copy_from_user(tsk->thread.cpextra, sc->sc_cpstate,
+ XTENSA_CP_EXTRA_SIZE);
}
#endif
- local_irq_restore(flags);
-}
-
-/* Return codes:
- 0: nothing saved
- 1: stuff to save, successful
- -1: stuff to save, error happened
-*/
-static int
-save_cpextra (struct _cpstate *buf)
-{
-#if XCHAL_CP_NUM == 0
- return 0;
-#else
-
- /* FIXME: If a task has never used a coprocessor, there is
- * no need to save and restore anything. Tracking this
- * information would allow us to optimize this section.
- * Perhaps we can use current->used_math or (current->flags &
- * PF_USEDFPU) or define a new field in the thread
- * structure. */
-
- /* We flush any live, task-owned cp state to the task_struct,
- * then copy it all to the sigframe. Then we clear all
- * cp/extra state in the task_struct, effectively
- * clearing/resetting all cp/extra state for the signal
- * handler (cp-exception handling will load these new values
- * into the cp/extra registers.) This step is important for
- * things like a floating-point cp, where the OS must reset
- * the FCR to the default rounding mode. */
-
- int err = 0;
- struct task_struct *tsk = current;
-
- flush_my_cpstate(tsk);
- /* Note that we just copy everything: 'extra' and 'cp' state together.*/
- err |= __copy_to_user(buf, tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
- memset(tsk->thread.cp_save, 0, XTENSA_CP_EXTRA_SIZE);
-
-#if (XTENSA_CP_EXTRA_SIZE == 0)
-#error Sanity check on memset above, cpextra_size should not be zero.
-#endif
-
- return err ? -1 : 1;
-#endif
-}
-
-static int
-setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
- struct pt_regs *regs, unsigned long mask)
-{
- struct thread_struct *thread;
- int err = 0;
-
-//printk("setup_sigcontext\n");
-#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
- COPY(pc);
- COPY(ps);
- COPY(depc);
- COPY(wmask);
- COPY(lbeg);
- COPY(lend);
- COPY(lcount);
- COPY(sar);
- COPY(windowbase);
- COPY(windowstart);
-#undef COPY
-
- /* Save extended register state.
- * See struct thread_struct in processor.h.
- */
- thread = &current->thread;
- err |= __copy_to_user (sc->sc_areg, regs->areg, XCHAL_NUM_AREGS * 4);
- err |= save_cpextra(cpstate);
- err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate);
- /* non-iBCS2 extensions.. */
- err |= __put_user(mask, &sc->oldmask);
+ regs->syscall = -1; /* disable syscall checks */
return err;
}
-asmlinkage int xtensa_sigreturn(struct pt_regs *regs)
-{
- struct sigframe *frame = (struct sigframe *)regs->areg[1];
- sigset_t set;
- if (regs->depc > 64)
- panic ("Double exception sys_sigreturn\n");
-
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
-
- if (__get_user(set.sig[0], &frame->sc.oldmask)
- || (_NSIG_WORDS > 1
- && __copy_from_user(&set.sig[1], &frame->extramask,
- sizeof(frame->extramask))))
- goto badframe;
-
- sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- if (restore_sigcontext(regs, &frame->sc))
- goto badframe;
- return regs->areg[2];
-badframe:
- force_sig(SIGSEGV, current);
- return 0;
-}
+/*
+ * Do a signal return; undo the signal stack.
+ */
-asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs)
+asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
+ long a4, long a5, struct pt_regs *regs)
{
- struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
+ struct rt_sigframe __user *frame;
sigset_t set;
- stack_t st;
int ret;
+
if (regs->depc > 64)
- {
- printk("!!!!!!! DEPC !!!!!!!\n");
- return 0;
- }
+ panic("rt_sigreturn in double exception!\n");
+
+ frame = (struct rt_sigframe __user *) regs->areg[1];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
@@ -407,13 +249,11 @@ asmlinkage int xtensa_rt_sigreturn(struct pt_regs *regs)
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
+
ret = regs->areg[2];
- if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->areg[1]) == -EFAULT)
goto badframe;
- /* It is more difficult to avoid calling this function than to
- call it and ignore errors. */
- do_sigaltstack(&st, NULL, regs->areg[1]);
return ret;
@@ -422,77 +262,50 @@ badframe:
return 0;
}
-/*
- * Set up a signal frame.
- */
+
/*
- * Determine which stack to use..
+ * Set up a signal frame.
*/
-static inline void *
-get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
-{
- if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
- sp = current->sas_ss_sp + current->sas_ss_size;
-
- return (void *)((sp - frame_size) & -16ul);
-}
-
-#define USE_SIGRETURN 0
-#define USE_RT_SIGRETURN 1
static int
-gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
+gen_return_code(unsigned char *codemem)
{
- unsigned int retcall;
int err = 0;
-#if 0
- /* Ignoring SA_RESTORER for now; it's supposed to be obsolete,
- * and the xtensa glibc doesn't use it.
+ /*
+ * The 12-bit immediate is really split up within the 24-bit MOVI
+ * instruction. As long as the above system call numbers fit within
+ * 8-bits, the following code works fine. See the Xtensa ISA for
+ * details.
*/
- if (ka->sa.sa_flags & SA_RESTORER) {
- regs->pr = (unsigned long) ka->sa.sa_restorer;
- } else
-#endif /* 0 */
- {
-
-#if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255)
-
-/* The 12-bit immediate is really split up within the 24-bit MOVI
- * instruction. As long as the above system call numbers fit within
- * 8-bits, the following code works fine. See the Xtensa ISA for
- * details.
- */
-#error Generating the MOVI instruction below breaks!
+#if __NR_rt_sigreturn > 255
+# error Generating the MOVI instruction below breaks!
#endif
- retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn;
-
#ifdef __XTENSA_EB__ /* Big Endian version */
- /* Generate instruction: MOVI a2, retcall */
- err |= __put_user(0x22, &codemem[0]);
- err |= __put_user(0x0a, &codemem[1]);
- err |= __put_user(retcall, &codemem[2]);
- /* Generate instruction: SYSCALL */
- err |= __put_user(0x00, &codemem[3]);
- err |= __put_user(0x05, &codemem[4]);
- err |= __put_user(0x00, &codemem[5]);
+ /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
+ err |= __put_user(0x22, &codemem[0]);
+ err |= __put_user(0x0a, &codemem[1]);
+ err |= __put_user(__NR_rt_sigreturn, &codemem[2]);
+ /* Generate instruction: SYSCALL */
+ err |= __put_user(0x00, &codemem[3]);
+ err |= __put_user(0x05, &codemem[4]);
+ err |= __put_user(0x00, &codemem[5]);
#elif defined __XTENSA_EL__ /* Little Endian version */
- /* Generate instruction: MOVI a2, retcall */
- err |= __put_user(0x22, &codemem[0]);
- err |= __put_user(0xa0, &codemem[1]);
- err |= __put_user(retcall, &codemem[2]);
- /* Generate instruction: SYSCALL */
- err |= __put_user(0x00, &codemem[3]);
- err |= __put_user(0x50, &codemem[4]);
- err |= __put_user(0x00, &codemem[5]);
+ /* Generate instruction: MOVI a2, __NR_rt_sigreturn */
+ err |= __put_user(0x22, &codemem[0]);
+ err |= __put_user(0xa0, &codemem[1]);
+ err |= __put_user(__NR_rt_sigreturn, &codemem[2]);
+ /* Generate instruction: SYSCALL */
+ err |= __put_user(0x00, &codemem[3]);
+ err |= __put_user(0x50, &codemem[4]);
+ err |= __put_user(0x00, &codemem[5]);
#else
-#error Must use compiler for Xtensa processors.
+# error Must use compiler for Xtensa processors.
#endif
- }
/* Flush generated code out of the data cache */
@@ -504,97 +317,29 @@ gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
return err;
}
-static void
-set_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr,
- void *handler, unsigned long arg1, void *arg2, void *arg3)
-{
- /* Set up registers for signal handler */
- start_thread(regs, (unsigned long) handler, (unsigned long) stack);
-
- /* Set up a stack frame for a call4
- * Note: PS.CALLINC is set to one by start_thread
- */
- regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000;
- regs->areg[6] = arg1;
- regs->areg[7] = (unsigned long) arg2;
- regs->areg[8] = (unsigned long) arg3;
-}
-static void setup_frame(int sig, struct k_sigaction *ka,
+static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
- struct sigframe *frame;
+ struct rt_sigframe *frame;
int err = 0;
int signal;
+ unsigned long sp, ra;
- frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
- if (regs->depc > 64)
- {
- printk("!!!!!!! DEPC !!!!!!!\n");
- return;
- }
-
-
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
- goto give_sigsegv;
-
- signal = current_thread_info()->exec_domain
- && current_thread_info()->exec_domain->signal_invmap
- && sig < 32
- ? current_thread_info()->exec_domain->signal_invmap[sig]
- : sig;
-
- err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]);
+ sp = regs->areg[1];
- if (_NSIG_WORDS > 1) {
- err |= __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) {
+ sp = current->sas_ss_sp + current->sas_ss_size;
}
- /* Create sys_sigreturn syscall in stack frame */
- err |= gen_return_code(frame->retcode, USE_SIGRETURN);
-
- if (err)
- goto give_sigsegv;
-
- /* Create signal handler execution context.
- * Return context not modified until this point.
- */
- set_thread_state(regs, frame, frame->retcode,
- ka->sa.sa_handler, signal, &frame->sc, NULL);
-
- /* Set access mode to USER_DS. Nomenclature is outdated, but
- * functionality is used in uaccess.h
- */
- set_fs(USER_DS);
-
-
-#if DEBUG_SIG
- printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
- current->comm, current->pid, signal, frame, regs->pc);
-#endif
-
- return;
-
-give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
-}
-
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
-{
- struct rt_sigframe *frame;
- int err = 0;
- int signal;
+ frame = (void *)((sp - sizeof(*frame)) & -16ul);
- frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
if (regs->depc > 64)
panic ("Double exception sys_sigreturn\n");
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
goto give_sigsegv;
+ }
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
@@ -602,9 +347,12 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
- err |= copy_siginfo_to_user(&frame->info, info);
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+ err |= copy_siginfo_to_user(&frame->info, info);
+ }
+
+ /* Create the user context. */
- /* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
err |= __put_user(0, &frame->uc.uc_link);
err |= __put_user((void *)current->sas_ss_sp,
@@ -617,16 +365,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
/* Create sys_rt_sigreturn syscall in stack frame */
- err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN);
- if (err)
+ err |= gen_return_code(frame->retcode);
+
+ if (err) {
goto give_sigsegv;
+ }
+
- /* Create signal handler execution context.
+ /*
+ * Create signal handler execution context.
* Return context not modified until this point.
*/
- set_thread_state(regs, frame, frame->retcode,
- ka->sa.sa_handler, signal, &frame->info, &frame->uc);
+
+ /* Set up registers for signal handler */
+ start_thread(regs, (unsigned long) ka->sa.sa_handler,
+ (unsigned long) frame);
+
+ /* Set up a stack frame for a call4
+ * Note: PS.CALLINC is set to one by start_thread
+ */
+ ra = (unsigned long) frame->retcode;
+ regs->areg[4] = (((unsigned long) ra) & 0x3fffffff) | 0x40000000;
+ regs->areg[6] = (unsigned long) signal;
+ regs->areg[7] = (unsigned long) &frame->info;
+ regs->areg[8] = (unsigned long) &frame->uc;
/* Set access mode to USER_DS. Nomenclature is outdated, but
* functionality is used in uaccess.h
@@ -646,6 +409,48 @@ give_sigsegv:
force_sig(SIGSEGV, current);
}
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+
+asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset,
+ size_t sigsetsize,
+ long a2, long a3, long a4, long a5,
+ struct pt_regs *regs)
+{
+ sigset_t saveset, newset;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ regs->areg[2] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(regs, &saveset))
+ return -EINTR;
+ }
+}
+
+asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
+ stack_t __user *uoss,
+ long a2, long a3, long a4, long a5,
+ struct pt_regs *regs)
+{
+ return do_sigaltstack(uss, uoss, regs->areg[1]);
+}
+
/*
@@ -663,51 +468,89 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
int signr;
struct k_sigaction ka;
+ if (!user_mode(regs))
+ return 0;
+
+ if (try_to_freeze())
+ goto no_signal;
+
if (!oldset)
oldset = &current->blocked;
+ task_pt_regs(current)->icountlevel = 0;
+
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- /* Are we from a system call? */
- if (regs->syscall >= 0) {
- /* If so, check system call restarting.. */
- switch (regs->areg[2]) {
- case ERESTARTNOHAND:
- case ERESTART_RESTARTBLOCK:
- regs->areg[2] = -EINTR;
- break;
+ if (signr > 0) {
+
+ /* Are we from a system call? */
+
+ if ((signed)regs->syscall >= 0) {
- case ERESTARTSYS:
- if (!(ka.sa.sa_flags & SA_RESTART)) {
+ /* If so, check system call restarting.. */
+
+ switch (regs->areg[2]) {
+ case -ERESTARTNOHAND:
+ case -ERESTART_RESTARTBLOCK:
regs->areg[2] = -EINTR;
break;
- }
- /* fallthrough */
- case ERESTARTNOINTR:
- regs->areg[2] = regs->syscall;
- regs->pc -= 3;
+
+ case -ERESTARTSYS:
+ if (!(ka.sa.sa_flags & SA_RESTART)) {
+ regs->areg[2] = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ regs->areg[2] = regs->syscall;
+ regs->pc -= 3;
+ break;
+
+ default:
+ /* nothing to do */
+ if (regs->areg[2] != 0)
+ break;
+ }
}
- }
- if (signr == 0)
- return 0; /* no signals delivered */
+ /* Whee! Actually deliver the signal. */
+ /* Set up the stack frame */
+ setup_frame(signr, &ka, &info, oldset, regs);
- /* Whee! Actually deliver the signal. */
+ if (ka.sa.sa_flags & SA_ONESHOT)
+ ka.sa.sa_handler = SIG_DFL;
- /* Set up the stack frame */
- if (ka.sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(signr, &ka, &info, oldset, regs);
- else
- setup_frame(signr, &ka, oldset, regs);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+ if (!(ka.sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, signr);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ if (current->ptrace & PT_SINGLESTEP)
+ task_pt_regs(current)->icountlevel = 1;
- if (ka.sa.sa_flags & SA_ONESHOT)
- ka.sa.sa_handler = SIG_DFL;
+ return 1;
+ }
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
- if (!(ka.sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- return 1;
+no_signal:
+ /* Did we come from a system call? */
+ if ((signed) regs->syscall >= 0) {
+ /* Restart the system call - no handlers present */
+ switch (regs->areg[2]) {
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ regs->areg[2] = regs->syscall;
+ regs->pc -= 3;
+ break;
+ case -ERESTART_RESTARTBLOCK:
+ regs->areg[2] = __NR_restart_syscall;
+ regs->pc -= 3;
+ break;
+ }
+ }
+ if (current->ptrace & PT_SINGLESTEP)
+ task_pt_regs(current)->icountlevel = 1;
+ return 0;
}
+
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 4b7b4ff7997..b0582c3c5f8 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -84,9 +84,7 @@ SECTIONS
{
/* The .head.text section must be the first section! */
*(.head.text)
- *(.literal)
- TEXT_TEXT
- *(.srom.text)
+ *(.literal .text)
VMLINUX_SYMBOL(__sched_text_start) = .;
*(.sched.literal .sched.text)
VMLINUX_SYMBOL(__sched_text_end) = .;
@@ -96,6 +94,7 @@ SECTIONS
}
_etext = .;
+ PROVIDE (etext = .);
. = ALIGN(16);
@@ -103,32 +102,6 @@ SECTIONS
/* Relocation table */
- . = ALIGN(16);
- __boot_reloc_table_start = ABSOLUTE(.);
-
- __relocate : {
-
- RELOCATE_ENTRY(_WindowVectors_text,
- .WindowVectors.text);
-#if 0
- RELOCATE_ENTRY(_KernelExceptionVector_literal,
- .KernelExceptionVector.literal);
-#endif
- RELOCATE_ENTRY(_KernelExceptionVector_text,
- .KernelExceptionVector.text);
-#if 0
- RELOCATE_ENTRY(_UserExceptionVector_literal,
- .UserExceptionVector.literal);
-#endif
- RELOCATE_ENTRY(_UserExceptionVector_text,
- .UserExceptionVector.text);
- RELOCATE_ENTRY(_DoubleExceptionVector_literal,
- .DoubleExceptionVector.literal);
- RELOCATE_ENTRY(_DoubleExceptionVector_text,
- .DoubleExceptionVector.text);
- }
- __boot_reloc_table_end = ABSOLUTE(.) ;
-
.fixup : { *(.fixup) }
. = ALIGN(16);
@@ -145,8 +118,7 @@ SECTIONS
_fdata = .;
.data :
{
- DATA_DATA
- CONSTRUCTORS
+ *(.data) CONSTRUCTORS
. = ALIGN(XCHAL_ICACHE_LINESIZE);
*(.data.cacheline_aligned)
}
@@ -174,6 +146,22 @@ SECTIONS
__tagtable_begin = .;
*(.taglist)
__tagtable_end = .;
+
+ . = ALIGN(16);
+ __boot_reloc_table_start = ABSOLUTE(.);
+
+ RELOCATE_ENTRY(_WindowVectors_text,
+ .WindowVectors.text);
+ RELOCATE_ENTRY(_KernelExceptionVector_text,
+ .KernelExceptionVector.text);
+ RELOCATE_ENTRY(_UserExceptionVector_text,
+ .UserExceptionVector.text);
+ RELOCATE_ENTRY(_DoubleExceptionVector_literal,
+ .DoubleExceptionVector.literal);
+ RELOCATE_ENTRY(_DoubleExceptionVector_text,
+ .DoubleExceptionVector.text);
+
+ __boot_reloc_table_end = ABSOLUTE(.) ;
}
. = ALIGN(XCHAL_ICACHE_LINESIZE);
@@ -194,16 +182,6 @@ SECTIONS
SECURITY_INIT
- . = ALIGN(4);
-
- __start___ftr_fixup = .;
- __ftr_fixup : { *(__ftr_fixup) }
- __stop___ftr_fixup = .;
-
- . = ALIGN(4096);
- __per_cpu_start = .;
- .data.percpu : { *(.data.percpu) }
- __per_cpu_end = .;
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(4096);
@@ -212,6 +190,12 @@ SECTIONS
__initramfs_end = .;
#endif
+ . = ALIGN(4096);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+
+
/* We need this dummy segment here */
. = ALIGN(4);
@@ -273,9 +257,9 @@ SECTIONS
/* BSS section */
_bss_start = .;
- .sbss : { *(.sbss) *(.scommon) }
- .bss : { *(COMMON) *(.bss) }
+ .bss : { *(.bss.page_aligned) *(.bss) }
_bss_end = .;
+
_end = .;
/* only used by the boot loader */
@@ -293,16 +277,16 @@ SECTIONS
*(.ResetVector.text)
}
-
/* Sections to be discarded */
/DISCARD/ :
{
- *(.text.exit)
- *(.text.exit.literal)
- *(.data.exit)
+ *(.exit.literal .exit.text)
+ *(.exit.data)
*(.exitcall.exit)
}
+ .xt.lit : { *(.xt.lit) }
+ .xt.prop : { *(.xt.prop) }
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index cd7e6a02060..60dbdb43fb4 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -38,21 +38,10 @@
/*
* String functions
*/
-EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(kernel_thread);
/*
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S
index a834057bda6..b2655d94558 100644
--- a/arch/xtensa/lib/strncpy_user.S
+++ b/arch/xtensa/lib/strncpy_user.S
@@ -25,18 +25,18 @@
/*
* char *__strncpy_user(char *dst, const char *src, size_t len)
*/
-.text
-.begin literal
-.align 4
-.Lmask0:
- .byte 0xff, 0x00, 0x00, 0x00
-.Lmask1:
- .byte 0x00, 0xff, 0x00, 0x00
-.Lmask2:
- .byte 0x00, 0x00, 0xff, 0x00
-.Lmask3:
- .byte 0x00, 0x00, 0x00, 0xff
-.end literal
+
+#ifdef __XTENSA_EB__
+# define MASK0 0xff000000
+# define MASK1 0x00ff0000
+# define MASK2 0x0000ff00
+# define MASK3 0x000000ff
+#else
+# define MASK0 0x000000ff
+# define MASK1 0x0000ff00
+# define MASK2 0x00ff0000
+# define MASK3 0xff000000
+#endif
# Register use
# a0/ return address
@@ -53,6 +53,7 @@
# a11/ dst
# a12/ tmp
+.text
.align 4
.global __strncpy_user
.type __strncpy_user,@function
@@ -61,10 +62,10 @@ __strncpy_user:
# a2/ dst, a3/ src, a4/ len
mov a11, a2 # leave dst in return value register
beqz a4, .Lret # if len is zero
- l32r a5, .Lmask0 # mask for byte 0
- l32r a6, .Lmask1 # mask for byte 1
- l32r a7, .Lmask2 # mask for byte 2
- l32r a8, .Lmask3 # mask for byte 3
+ movi a5, MASK0 # mask for byte 0
+ movi a6, MASK1 # mask for byte 1
+ movi a7, MASK2 # mask for byte 2
+ movi a8, MASK3 # mask for byte 3
bbsi.l a3, 0, .Lsrc1mod2 # if only 8-bit aligned
bbsi.l a3, 1, .Lsrc2mod4 # if only 16-bit aligned
.Lsrcaligned: # return here when src is word-aligned
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S
index 5e9c1e709b2..ad3f616322c 100644
--- a/arch/xtensa/lib/strnlen_user.S
+++ b/arch/xtensa/lib/strnlen_user.S
@@ -24,18 +24,18 @@
/*
* size_t __strnlen_user(const char *s, size_t len)
*/
-.text
-.begin literal
-.align 4
-.Lmask0:
- .byte 0xff, 0x00, 0x00, 0x00
-.Lmask1:
- .byte 0x00, 0xff, 0x00, 0x00
-.Lmask2:
- .byte 0x00, 0x00, 0xff, 0x00
-.Lmask3:
- .byte 0x00, 0x00, 0x00, 0xff
-.end literal
+
+#ifdef __XTENSA_EB__
+# define MASK0 0xff000000
+# define MASK1 0x00ff0000
+# define MASK2 0x0000ff00
+# define MASK3 0x000000ff
+#else
+# define MASK0 0x000000ff
+# define MASK1 0x0000ff00
+# define MASK2 0x00ff0000
+# define MASK3 0xff000000
+#endif
# Register use:
# a2/ src
@@ -48,6 +48,7 @@
# a9/ tmp
# a10/ tmp
+.text
.align 4
.global __strnlen_user
.type __strnlen_user,@function
@@ -56,10 +57,10 @@ __strnlen_user:
# a2/ s, a3/ len
addi a4, a2, -4 # because we overincrement at the end;
# we compensate with load offsets of 4
- l32r a5, .Lmask0 # mask for byte 0
- l32r a6, .Lmask1 # mask for byte 1
- l32r a7, .Lmask2 # mask for byte 2
- l32r a8, .Lmask3 # mask for byte 3
+ movi a5, MASK0 # mask for byte 0
+ movi a6, MASK1 # mask for byte 1
+ movi a7, MASK2 # mask for byte 2
+ movi a8, MASK3 # mask for byte 3
bbsi.l a2, 0, .L1mod2 # if only 8-bit aligned
bbsi.l a2, 1, .L2mod4 # if only 16-bit aligned
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
index e1ec2d1e818..8415c76f11c 100644
--- a/arch/xtensa/mm/init.c
+++ b/arch/xtensa/mm/init.c
@@ -205,7 +205,7 @@ void __init init_mmu (void)
/* Writing zeros to the <t>TLBCFG special registers ensure
* that valid values exist in the register. For existing
* PGSZID<w> fields, zero selects the first element of the
- * page-size array. For nonexistant PGSZID<w> fields, zero is
+ * page-size array. For nonexistent PGSZID<w> fields, zero is
* the best value to write. Also, when changing PGSZID<w>
* fields, the corresponding TLB must be flushed.
*/
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
index 4bfe333be22..f09962fa98c 100644
--- a/arch/xtensa/platform-iss/network.c
+++ b/arch/xtensa/platform-iss/network.c
@@ -473,7 +473,7 @@ static int iss_net_open(struct net_device *dev)
netif_start_queue(dev);
/* clear buffer - it can happen that the host side of the interface
- * is full when we gethere. In this case, new data is never queued,
+ * is full when we get here. In this case, new data is never queued,
* SIGIOs never arrive, and the net never works.
*/
while ((err = iss_net_rx(dev)) > 0)
diff --git a/block/Kconfig b/block/Kconfig
index a50f4811164..285935134bc 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -1,7 +1,7 @@
#
# Block layer core configuration
#
-config BLOCK
+menuconfig BLOCK
bool "Enable the block layer" if EMBEDDED
default y
help
@@ -49,6 +49,6 @@ config LSF
If unsure, say Y.
-endif
+endif # BLOCK
source block/Kconfig.iosched
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index baef5fc7cff..e0aa4dad674 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -92,6 +92,8 @@ struct cfq_data {
struct cfq_queue *active_queue;
struct cfq_io_context *active_cic;
+ struct cfq_queue *async_cfqq[IOPRIO_BE_NR];
+
struct timer_list idle_class_timer;
sector_t last_position;
@@ -1351,8 +1353,8 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc)
}
static struct cfq_queue *
-cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
- gfp_t gfp_mask)
+cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
+ struct task_struct *tsk, gfp_t gfp_mask)
{
struct cfq_queue *cfqq, *new_cfqq = NULL;
struct cfq_io_context *cic;
@@ -1405,12 +1407,35 @@ retry:
if (new_cfqq)
kmem_cache_free(cfq_pool, new_cfqq);
- atomic_inc(&cfqq->ref);
out:
WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
return cfqq;
}
+static struct cfq_queue *
+cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct task_struct *tsk,
+ gfp_t gfp_mask)
+{
+ const int ioprio = task_ioprio(tsk);
+ struct cfq_queue *cfqq = NULL;
+
+ if (!is_sync)
+ cfqq = cfqd->async_cfqq[ioprio];
+ if (!cfqq)
+ cfqq = cfq_find_alloc_queue(cfqd, is_sync, tsk, gfp_mask);
+
+ /*
+ * pin the queue now that it's allocated, scheduler exit will prune it
+ */
+ if (!is_sync && !cfqd->async_cfqq[ioprio]) {
+ atomic_inc(&cfqq->ref);
+ cfqd->async_cfqq[ioprio] = cfqq;
+ }
+
+ atomic_inc(&cfqq->ref);
+ return cfqq;
+}
+
/*
* We drop cfq io contexts lazily, so we may find a dead one.
*/
@@ -2019,6 +2044,7 @@ static void cfq_exit_queue(elevator_t *e)
{
struct cfq_data *cfqd = e->elevator_data;
request_queue_t *q = cfqd->queue;
+ int i;
cfq_shutdown_timer_wq(cfqd);
@@ -2035,6 +2061,13 @@ static void cfq_exit_queue(elevator_t *e)
__cfq_exit_single_io_context(cfqd, cic);
}
+ /*
+ * Put the async queues
+ */
+ for (i = 0; i < IOPRIO_BE_NR; i++)
+ if (cfqd->async_cfqq[i])
+ cfq_put_queue(cfqd->async_cfqq[i]);
+
spin_unlock_irq(q->queue_lock);
cfq_shutdown_timer_wq(cfqd);
diff --git a/block/elevator.c b/block/elevator.c
index ce866eb75f6..4769a25d703 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -112,12 +112,8 @@ static inline int elv_try_merge(struct request *__rq, struct bio *bio)
static struct elevator_type *elevator_find(const char *name)
{
struct elevator_type *e;
- struct list_head *entry;
-
- list_for_each(entry, &elv_list) {
-
- e = list_entry(entry, struct elevator_type, list);
+ list_for_each_entry(e, &elv_list, list) {
if (!strcmp(e->elevator_name, name))
return e;
}
@@ -1116,14 +1112,11 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
{
elevator_t *e = q->elevator;
struct elevator_type *elv = e->elevator_type;
- struct list_head *entry;
+ struct elevator_type *__e;
int len = 0;
spin_lock(&elv_list_lock);
- list_for_each(entry, &elv_list) {
- struct elevator_type *__e;
-
- __e = list_entry(entry, struct elevator_type, list);
+ list_for_each_entry(__e, &elv_list, list) {
if (!strcmp(elv->elevator_name, __e->elevator_name))
len += sprintf(name+len, "[%s] ", elv->elevator_name);
else
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 6b5173ac813..ef42bb2b12b 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -340,6 +340,15 @@ unsigned blk_ordered_req_seq(struct request *rq)
if (rq == &q->post_flush_rq)
return QUEUE_ORDSEQ_POSTFLUSH;
+ /*
+ * !fs requests don't need to follow barrier ordering. Always
+ * put them at the front. This fixes the following deadlock.
+ *
+ * http://thread.gmane.org/gmane.linux.kernel/537473
+ */
+ if (!blk_fs_request(rq))
+ return QUEUE_ORDSEQ_DRAIN;
+
if ((rq->cmd_flags & REQ_ORDERED_COLOR) ==
(q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR))
return QUEUE_ORDSEQ_DRAIN;
@@ -518,8 +527,6 @@ int blk_do_ordered(request_queue_t *q, struct request **rqp)
static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
{
request_queue_t *q = bio->bi_private;
- struct bio_vec *bvec;
- int i;
/*
* This is dry run, restore bio_sector and size. We'll finish
@@ -531,13 +538,6 @@ static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
if (bio->bi_size)
return 1;
- /* Rewind bvec's */
- bio->bi_idx = 0;
- bio_for_each_segment(bvec, bio, i) {
- bvec->bv_len += bvec->bv_offset;
- bvec->bv_offset = 0;
- }
-
/* Reset bio */
set_bit(BIO_UPTODATE, &bio->bi_flags);
bio->bi_size = q->bi_size;
@@ -1295,9 +1295,9 @@ static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
if (unlikely(!bio_flagged(nxt, BIO_SEG_VALID)))
blk_recount_segments(q, nxt);
if (!BIOVEC_VIRT_MERGEABLE(__BVEC_END(bio), __BVEC_START(nxt)) ||
- BIOVEC_VIRT_OVERSIZE(bio->bi_hw_front_size + bio->bi_hw_back_size))
+ BIOVEC_VIRT_OVERSIZE(bio->bi_hw_back_size + nxt->bi_hw_front_size))
return 0;
- if (bio->bi_size + nxt->bi_size > q->max_segment_size)
+ if (bio->bi_hw_back_size + nxt->bi_hw_front_size > q->max_segment_size)
return 0;
return 1;
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 4ca0ab3448d..3d1a1e27944 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1,10 +1,18 @@
#
-# Cryptographic API Configuration
+# Generic algorithms support
#
+config XOR_BLOCKS
+ tristate
-menu "Cryptographic options"
+#
+# async_tx api: hardware offloaded memory transfer/transform support
+#
+source "crypto/async_tx/Kconfig"
-config CRYPTO
+#
+# Cryptographic API Configuration
+#
+menuconfig CRYPTO
bool "Cryptographic API"
help
This option provides the core Cryptographic API.
@@ -463,5 +471,3 @@ config CRYPTO_TEST
source "drivers/crypto/Kconfig"
endif # if CRYPTO
-
-endmenu
diff --git a/crypto/Makefile b/crypto/Makefile
index cce46a1c9dc..0cf17f1ea15 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -50,3 +50,9 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+
+#
+# generic algorithms and the async_tx api
+#
+obj-$(CONFIG_XOR_BLOCKS) += xor.o
+obj-$(CONFIG_ASYNC_CORE) += async_tx/
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index 9348ddd84a5..1c166b47b4c 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -19,16 +19,41 @@
#include <linux/module.h>
#include <linux/seq_file.h>
+static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, unsigned int keylen)
+{
+ struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm);
+ unsigned long alignmask = crypto_ablkcipher_alignmask(tfm);
+ int ret;
+ u8 *buffer, *alignbuffer;
+ unsigned long absize;
+
+ absize = keylen + alignmask;
+ buffer = kmalloc(absize, GFP_ATOMIC);
+ if (!buffer)
+ return -ENOMEM;
+
+ alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+ memcpy(alignbuffer, key, keylen);
+ ret = cipher->setkey(tfm, alignbuffer, keylen);
+ memset(alignbuffer, 0, absize);
+ kfree(buffer);
+ return ret;
+}
+
static int setkey(struct crypto_ablkcipher *tfm, const u8 *key,
unsigned int keylen)
{
struct ablkcipher_alg *cipher = crypto_ablkcipher_alg(tfm);
+ unsigned long alignmask = crypto_ablkcipher_alignmask(tfm);
if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL;
}
+ if ((unsigned long)key & alignmask)
+ return setkey_unaligned(tfm, key, keylen);
+
return cipher->setkey(tfm, key, keylen);
}
@@ -66,8 +91,10 @@ static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize);
seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize);
seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize);
- seq_printf(m, "qlen : %u\n", ablkcipher->queue->qlen);
- seq_printf(m, "max qlen : %u\n", ablkcipher->queue->max_qlen);
+ if (ablkcipher->queue) {
+ seq_printf(m, "qlen : %u\n", ablkcipher->queue->qlen);
+ seq_printf(m, "max qlen : %u\n", ablkcipher->queue->max_qlen);
+ }
}
const struct crypto_type crypto_ablkcipher_type = {
diff --git a/crypto/algapi.c b/crypto/algapi.c
index f137a432061..38aa9e99470 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -34,7 +34,7 @@ void crypto_larval_error(const char *name, u32 type, u32 mask)
if (alg) {
if (crypto_is_larval(alg)) {
struct crypto_larval *larval = (void *)alg;
- complete(&larval->completion);
+ complete_all(&larval->completion);
}
crypto_mod_put(alg);
}
@@ -164,7 +164,7 @@ static int __crypto_register_alg(struct crypto_alg *alg,
continue;
larval->adult = alg;
- complete(&larval->completion);
+ complete_all(&larval->completion);
continue;
}
diff --git a/crypto/api.c b/crypto/api.c
index 33734fd9198..4ccc5af6c26 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -144,7 +144,7 @@ static void crypto_larval_kill(struct crypto_alg *alg)
down_write(&crypto_alg_sem);
list_del(&alg->cra_list);
up_write(&crypto_alg_sem);
- complete(&larval->completion);
+ complete_all(&larval->completion);
crypto_alg_put(alg);
}
diff --git a/crypto/async_tx/Kconfig b/crypto/async_tx/Kconfig
new file mode 100644
index 00000000000..d8fb3914598
--- /dev/null
+++ b/crypto/async_tx/Kconfig
@@ -0,0 +1,16 @@
+config ASYNC_CORE
+ tristate
+
+config ASYNC_MEMCPY
+ tristate
+ select ASYNC_CORE
+
+config ASYNC_XOR
+ tristate
+ select ASYNC_CORE
+ select XOR_BLOCKS
+
+config ASYNC_MEMSET
+ tristate
+ select ASYNC_CORE
+
diff --git a/crypto/async_tx/Makefile b/crypto/async_tx/Makefile
new file mode 100644
index 00000000000..27baa7d52fb
--- /dev/null
+++ b/crypto/async_tx/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_ASYNC_CORE) += async_tx.o
+obj-$(CONFIG_ASYNC_MEMCPY) += async_memcpy.o
+obj-$(CONFIG_ASYNC_MEMSET) += async_memset.o
+obj-$(CONFIG_ASYNC_XOR) += async_xor.o
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
new file mode 100644
index 00000000000..a973f4ef897
--- /dev/null
+++ b/crypto/async_tx/async_memcpy.c
@@ -0,0 +1,131 @@
+/*
+ * copy offload engine support
+ *
+ * Copyright © 2006, Intel Corporation.
+ *
+ * Dan Williams <dan.j.williams@intel.com>
+ *
+ * with architecture considerations by:
+ * Neil Brown <neilb@suse.de>
+ * Jeff Garzik <jeff@garzik.org>
+ *
+ * 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/kernel.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/async_tx.h>
+
+/**
+ * async_memcpy - attempt to copy memory with a dma engine.
+ * @dest: destination page
+ * @src: src page
+ * @offset: offset in pages to start transaction
+ * @len: length in bytes
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK,
+ * ASYNC_TX_KMAP_SRC, ASYNC_TX_KMAP_DST
+ * @depend_tx: memcpy depends on the result of this transaction
+ * @cb_fn: function to call when the memcpy completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+ unsigned int src_offset, size_t len, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
+{
+ struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMCPY);
+ struct dma_device *device = chan ? chan->device : NULL;
+ int int_en = cb_fn ? 1 : 0;
+ struct dma_async_tx_descriptor *tx = device ?
+ device->device_prep_dma_memcpy(chan, len,
+ int_en) : NULL;
+
+ if (tx) { /* run the memcpy asynchronously */
+ dma_addr_t addr;
+ enum dma_data_direction dir;
+
+ pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+
+ dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+ DMA_NONE : DMA_FROM_DEVICE;
+
+ addr = dma_map_page(device->dev, dest, dest_offset, len, dir);
+ tx->tx_set_dest(addr, tx, 0);
+
+ dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+ DMA_NONE : DMA_TO_DEVICE;
+
+ addr = dma_map_page(device->dev, src, src_offset, len, dir);
+ tx->tx_set_src(addr, tx, 0);
+
+ async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+ } else { /* run the memcpy synchronously */
+ void *dest_buf, *src_buf;
+ pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+ /* wait for any prerequisite operations */
+ if (depend_tx) {
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+ BUG_ON(depend_tx->ack);
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+ __FUNCTION__);
+ }
+
+ if (flags & ASYNC_TX_KMAP_DST)
+ dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
+ else
+ dest_buf = page_address(dest) + dest_offset;
+
+ if (flags & ASYNC_TX_KMAP_SRC)
+ src_buf = kmap_atomic(src, KM_USER0) + src_offset;
+ else
+ src_buf = page_address(src) + src_offset;
+
+ memcpy(dest_buf, src_buf, len);
+
+ if (flags & ASYNC_TX_KMAP_DST)
+ kunmap_atomic(dest_buf, KM_USER0);
+
+ if (flags & ASYNC_TX_KMAP_SRC)
+ kunmap_atomic(src_buf, KM_USER0);
+
+ async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ }
+
+ return tx;
+}
+EXPORT_SYMBOL_GPL(async_memcpy);
+
+static int __init async_memcpy_init(void)
+{
+ return 0;
+}
+
+static void __exit async_memcpy_exit(void)
+{
+ do { } while (0);
+}
+
+module_init(async_memcpy_init);
+module_exit(async_memcpy_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous memcpy api");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c
new file mode 100644
index 00000000000..66ef6351202
--- /dev/null
+++ b/crypto/async_tx/async_memset.c
@@ -0,0 +1,109 @@
+/*
+ * memory fill offload engine support
+ *
+ * Copyright © 2006, Intel Corporation.
+ *
+ * Dan Williams <dan.j.williams@intel.com>
+ *
+ * with architecture considerations by:
+ * Neil Brown <neilb@suse.de>
+ * Jeff Garzik <jeff@garzik.org>
+ *
+ * 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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/async_tx.h>
+
+/**
+ * async_memset - attempt to fill memory with a dma engine.
+ * @dest: destination page
+ * @val: fill value
+ * @offset: offset in pages to start transaction
+ * @len: length in bytes
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: memset depends on the result of this transaction
+ * @cb_fn: function to call when the memcpy completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_memset(struct page *dest, int val, unsigned int offset,
+ size_t len, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
+{
+ struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_MEMSET);
+ struct dma_device *device = chan ? chan->device : NULL;
+ int int_en = cb_fn ? 1 : 0;
+ struct dma_async_tx_descriptor *tx = device ?
+ device->device_prep_dma_memset(chan, val, len,
+ int_en) : NULL;
+
+ if (tx) { /* run the memset asynchronously */
+ dma_addr_t dma_addr;
+ enum dma_data_direction dir;
+
+ pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+ dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+ DMA_NONE : DMA_FROM_DEVICE;
+
+ dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
+ tx->tx_set_dest(dma_addr, tx, 0);
+
+ async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+ } else { /* run the memset synchronously */
+ void *dest_buf;
+ pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+ dest_buf = (void *) (((char *) page_address(dest)) + offset);
+
+ /* wait for any prerequisite operations */
+ if (depend_tx) {
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+ BUG_ON(depend_tx->ack);
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+ __FUNCTION__);
+ }
+
+ memset(dest_buf, val, len);
+
+ async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ }
+
+ return tx;
+}
+EXPORT_SYMBOL_GPL(async_memset);
+
+static int __init async_memset_init(void)
+{
+ return 0;
+}
+
+static void __exit async_memset_exit(void)
+{
+ do { } while (0);
+}
+
+module_init(async_memset_init);
+module_exit(async_memset_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous memset api");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
new file mode 100644
index 00000000000..035007145e7
--- /dev/null
+++ b/crypto/async_tx/async_tx.c
@@ -0,0 +1,497 @@
+/*
+ * core routines for the asynchronous memory transfer/transform api
+ *
+ * Copyright © 2006, Intel Corporation.
+ *
+ * Dan Williams <dan.j.williams@intel.com>
+ *
+ * with architecture considerations by:
+ * Neil Brown <neilb@suse.de>
+ * Jeff Garzik <jeff@garzik.org>
+ *
+ * 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/kernel.h>
+#include <linux/async_tx.h>
+
+#ifdef CONFIG_DMA_ENGINE
+static enum dma_state_client
+dma_channel_add_remove(struct dma_client *client,
+ struct dma_chan *chan, enum dma_state state);
+
+static struct dma_client async_tx_dma = {
+ .event_callback = dma_channel_add_remove,
+ /* .cap_mask == 0 defaults to all channels */
+};
+
+/**
+ * dma_cap_mask_all - enable iteration over all operation types
+ */
+static dma_cap_mask_t dma_cap_mask_all;
+
+/**
+ * chan_ref_percpu - tracks channel allocations per core/opertion
+ */
+struct chan_ref_percpu {
+ struct dma_chan_ref *ref;
+};
+
+static int channel_table_initialized;
+static struct chan_ref_percpu *channel_table[DMA_TX_TYPE_END];
+
+/**
+ * async_tx_lock - protect modification of async_tx_master_list and serialize
+ * rebalance operations
+ */
+static spinlock_t async_tx_lock;
+
+static struct list_head
+async_tx_master_list = LIST_HEAD_INIT(async_tx_master_list);
+
+/* async_tx_issue_pending_all - start all transactions on all channels */
+void async_tx_issue_pending_all(void)
+{
+ struct dma_chan_ref *ref;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+ ref->chan->device->device_issue_pending(ref->chan);
+ rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(async_tx_issue_pending_all);
+
+/* dma_wait_for_async_tx - spin wait for a transcation to complete
+ * @tx: transaction to wait on
+ */
+enum dma_status
+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+{
+ enum dma_status status;
+ struct dma_async_tx_descriptor *iter;
+
+ if (!tx)
+ return DMA_SUCCESS;
+
+ /* poll through the dependency chain, return when tx is complete */
+ do {
+ iter = tx;
+ while (iter->cookie == -EBUSY)
+ iter = iter->parent;
+
+ status = dma_sync_wait(iter->chan, iter->cookie);
+ } while (status == DMA_IN_PROGRESS || (iter != tx));
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
+
+/* async_tx_run_dependencies - helper routine for dma drivers to process
+ * (start) dependent operations on their target channel
+ * @tx: transaction with dependencies
+ */
+void
+async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
+{
+ struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
+ struct dma_device *dev;
+ struct dma_chan *chan;
+
+ list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
+ depend_node) {
+ chan = dep_tx->chan;
+ dev = chan->device;
+ /* we can't depend on ourselves */
+ BUG_ON(chan == tx->chan);
+ list_del(&dep_tx->depend_node);
+ tx->tx_submit(dep_tx);
+
+ /* we need to poke the engine as client code does not
+ * know about dependency submission events
+ */
+ dev->device_issue_pending(chan);
+ }
+}
+EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
+
+static void
+free_dma_chan_ref(struct rcu_head *rcu)
+{
+ struct dma_chan_ref *ref;
+ ref = container_of(rcu, struct dma_chan_ref, rcu);
+ kfree(ref);
+}
+
+static void
+init_dma_chan_ref(struct dma_chan_ref *ref, struct dma_chan *chan)
+{
+ INIT_LIST_HEAD(&ref->node);
+ INIT_RCU_HEAD(&ref->rcu);
+ ref->chan = chan;
+ atomic_set(&ref->count, 0);
+}
+
+/**
+ * get_chan_ref_by_cap - returns the nth channel of the given capability
+ * defaults to returning the channel with the desired capability and the
+ * lowest reference count if the index can not be satisfied
+ * @cap: capability to match
+ * @index: nth channel desired, passing -1 has the effect of forcing the
+ * default return value
+ */
+static struct dma_chan_ref *
+get_chan_ref_by_cap(enum dma_transaction_type cap, int index)
+{
+ struct dma_chan_ref *ret_ref = NULL, *min_ref = NULL, *ref;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+ if (dma_has_cap(cap, ref->chan->device->cap_mask)) {
+ if (!min_ref)
+ min_ref = ref;
+ else if (atomic_read(&ref->count) <
+ atomic_read(&min_ref->count))
+ min_ref = ref;
+
+ if (index-- == 0) {
+ ret_ref = ref;
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+ if (!ret_ref)
+ ret_ref = min_ref;
+
+ if (ret_ref)
+ atomic_inc(&ret_ref->count);
+
+ return ret_ref;
+}
+
+/**
+ * async_tx_rebalance - redistribute the available channels, optimize
+ * for cpu isolation in the SMP case, and opertaion isolation in the
+ * uniprocessor case
+ */
+static void async_tx_rebalance(void)
+{
+ int cpu, cap, cpu_idx = 0;
+ unsigned long flags;
+
+ if (!channel_table_initialized)
+ return;
+
+ spin_lock_irqsave(&async_tx_lock, flags);
+
+ /* undo the last distribution */
+ for_each_dma_cap_mask(cap, dma_cap_mask_all)
+ for_each_possible_cpu(cpu) {
+ struct dma_chan_ref *ref =
+ per_cpu_ptr(channel_table[cap], cpu)->ref;
+ if (ref) {
+ atomic_set(&ref->count, 0);
+ per_cpu_ptr(channel_table[cap], cpu)->ref =
+ NULL;
+ }
+ }
+
+ for_each_dma_cap_mask(cap, dma_cap_mask_all)
+ for_each_online_cpu(cpu) {
+ struct dma_chan_ref *new;
+ if (NR_CPUS > 1)
+ new = get_chan_ref_by_cap(cap, cpu_idx++);
+ else
+ new = get_chan_ref_by_cap(cap, -1);
+
+ per_cpu_ptr(channel_table[cap], cpu)->ref = new;
+ }
+
+ spin_unlock_irqrestore(&async_tx_lock, flags);
+}
+
+static enum dma_state_client
+dma_channel_add_remove(struct dma_client *client,
+ struct dma_chan *chan, enum dma_state state)
+{
+ unsigned long found, flags;
+ struct dma_chan_ref *master_ref, *ref;
+ enum dma_state_client ack = DMA_DUP; /* default: take no action */
+
+ switch (state) {
+ case DMA_RESOURCE_AVAILABLE:
+ found = 0;
+ rcu_read_lock();
+ list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+ if (ref->chan == chan) {
+ found = 1;
+ break;
+ }
+ rcu_read_unlock();
+
+ pr_debug("async_tx: dma resource available [%s]\n",
+ found ? "old" : "new");
+
+ if (!found)
+ ack = DMA_ACK;
+ else
+ break;
+
+ /* add the channel to the generic management list */
+ master_ref = kmalloc(sizeof(*master_ref), GFP_KERNEL);
+ if (master_ref) {
+ /* keep a reference until async_tx is unloaded */
+ dma_chan_get(chan);
+ init_dma_chan_ref(master_ref, chan);
+ spin_lock_irqsave(&async_tx_lock, flags);
+ list_add_tail_rcu(&master_ref->node,
+ &async_tx_master_list);
+ spin_unlock_irqrestore(&async_tx_lock,
+ flags);
+ } else {
+ printk(KERN_WARNING "async_tx: unable to create"
+ " new master entry in response to"
+ " a DMA_RESOURCE_ADDED event"
+ " (-ENOMEM)\n");
+ return 0;
+ }
+
+ async_tx_rebalance();
+ break;
+ case DMA_RESOURCE_REMOVED:
+ found = 0;
+ spin_lock_irqsave(&async_tx_lock, flags);
+ list_for_each_entry_rcu(ref, &async_tx_master_list, node)
+ if (ref->chan == chan) {
+ /* permit backing devices to go away */
+ dma_chan_put(ref->chan);
+ list_del_rcu(&ref->node);
+ call_rcu(&ref->rcu, free_dma_chan_ref);
+ found = 1;
+ break;
+ }
+ spin_unlock_irqrestore(&async_tx_lock, flags);
+
+ pr_debug("async_tx: dma resource removed [%s]\n",
+ found ? "ours" : "not ours");
+
+ if (found)
+ ack = DMA_ACK;
+ else
+ break;
+
+ async_tx_rebalance();
+ break;
+ case DMA_RESOURCE_SUSPEND:
+ case DMA_RESOURCE_RESUME:
+ printk(KERN_WARNING "async_tx: does not support dma channel"
+ " suspend/resume\n");
+ break;
+ default:
+ BUG();
+ }
+
+ return ack;
+}
+
+static int __init
+async_tx_init(void)
+{
+ enum dma_transaction_type cap;
+
+ spin_lock_init(&async_tx_lock);
+ bitmap_fill(dma_cap_mask_all.bits, DMA_TX_TYPE_END);
+
+ /* an interrupt will never be an explicit operation type.
+ * clearing this bit prevents allocation to a slot in 'channel_table'
+ */
+ clear_bit(DMA_INTERRUPT, dma_cap_mask_all.bits);
+
+ for_each_dma_cap_mask(cap, dma_cap_mask_all) {
+ channel_table[cap] = alloc_percpu(struct chan_ref_percpu);
+ if (!channel_table[cap])
+ goto err;
+ }
+
+ channel_table_initialized = 1;
+ dma_async_client_register(&async_tx_dma);
+ dma_async_client_chan_request(&async_tx_dma);
+
+ printk(KERN_INFO "async_tx: api initialized (async)\n");
+
+ return 0;
+err:
+ printk(KERN_ERR "async_tx: initialization failure\n");
+
+ while (--cap >= 0)
+ free_percpu(channel_table[cap]);
+
+ return 1;
+}
+
+static void __exit async_tx_exit(void)
+{
+ enum dma_transaction_type cap;
+
+ channel_table_initialized = 0;
+
+ for_each_dma_cap_mask(cap, dma_cap_mask_all)
+ if (channel_table[cap])
+ free_percpu(channel_table[cap]);
+
+ dma_async_client_unregister(&async_tx_dma);
+}
+
+/**
+ * async_tx_find_channel - find a channel to carry out the operation or let
+ * the transaction execute synchronously
+ * @depend_tx: transaction dependency
+ * @tx_type: transaction type
+ */
+struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+ enum dma_transaction_type tx_type)
+{
+ /* see if we can keep the chain on one channel */
+ if (depend_tx &&
+ dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
+ return depend_tx->chan;
+ else if (likely(channel_table_initialized)) {
+ struct dma_chan_ref *ref;
+ int cpu = get_cpu();
+ ref = per_cpu_ptr(channel_table[tx_type], cpu)->ref;
+ put_cpu();
+ return ref ? ref->chan : NULL;
+ } else
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(async_tx_find_channel);
+#else
+static int __init async_tx_init(void)
+{
+ printk(KERN_INFO "async_tx: api initialized (sync-only)\n");
+ return 0;
+}
+
+static void __exit async_tx_exit(void)
+{
+ do { } while (0);
+}
+#endif
+
+void
+async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+ enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
+{
+ tx->callback = cb_fn;
+ tx->callback_param = cb_param;
+
+ /* set this new tx to run after depend_tx if:
+ * 1/ a dependency exists (depend_tx is !NULL)
+ * 2/ the tx can not be submitted to the current channel
+ */
+ if (depend_tx && depend_tx->chan != chan) {
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+ BUG_ON(depend_tx->ack);
+
+ tx->parent = depend_tx;
+ spin_lock_bh(&depend_tx->lock);
+ list_add_tail(&tx->depend_node, &depend_tx->depend_list);
+ if (depend_tx->cookie == 0) {
+ struct dma_chan *dep_chan = depend_tx->chan;
+ struct dma_device *dep_dev = dep_chan->device;
+ dep_dev->device_dependency_added(dep_chan);
+ }
+ spin_unlock_bh(&depend_tx->lock);
+
+ /* schedule an interrupt to trigger the channel switch */
+ async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
+ } else {
+ tx->parent = NULL;
+ tx->tx_submit(tx);
+ }
+
+ if (flags & ASYNC_TX_ACK)
+ async_tx_ack(tx);
+
+ if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
+ async_tx_ack(depend_tx);
+}
+EXPORT_SYMBOL_GPL(async_tx_submit);
+
+/**
+ * async_trigger_callback - schedules the callback function to be run after
+ * any dependent operations have been completed.
+ * @flags: ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: 'callback' requires the completion of this transaction
+ * @cb_fn: function to call after depend_tx completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_trigger_callback(enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
+{
+ struct dma_chan *chan;
+ struct dma_device *device;
+ struct dma_async_tx_descriptor *tx;
+
+ if (depend_tx) {
+ chan = depend_tx->chan;
+ device = chan->device;
+
+ /* see if we can schedule an interrupt
+ * otherwise poll for completion
+ */
+ if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
+ device = NULL;
+
+ tx = device ? device->device_prep_dma_interrupt(chan) : NULL;
+ } else
+ tx = NULL;
+
+ if (tx) {
+ pr_debug("%s: (async)\n", __FUNCTION__);
+
+ async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+ } else {
+ pr_debug("%s: (sync)\n", __FUNCTION__);
+
+ /* wait for any prerequisite operations */
+ if (depend_tx) {
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+ BUG_ON(depend_tx->ack);
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+ __FUNCTION__);
+ }
+
+ async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ }
+
+ return tx;
+}
+EXPORT_SYMBOL_GPL(async_trigger_callback);
+
+module_init(async_tx_init);
+module_exit(async_tx_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Asynchronous Bulk Memory Transactions API");
+MODULE_LICENSE("GPL");
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
new file mode 100644
index 00000000000..2575f674dcd
--- /dev/null
+++ b/crypto/async_tx/async_xor.c
@@ -0,0 +1,327 @@
+/*
+ * xor offload engine api
+ *
+ * Copyright © 2006, Intel Corporation.
+ *
+ * Dan Williams <dan.j.williams@intel.com>
+ *
+ * with architecture considerations by:
+ * Neil Brown <neilb@suse.de>
+ * Jeff Garzik <jeff@garzik.org>
+ *
+ * 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/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/raid/xor.h>
+#include <linux/async_tx.h>
+
+static void
+do_async_xor(struct dma_async_tx_descriptor *tx, struct dma_device *device,
+ struct dma_chan *chan, struct page *dest, struct page **src_list,
+ unsigned int offset, unsigned int src_cnt, size_t len,
+ enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
+{
+ dma_addr_t dma_addr;
+ enum dma_data_direction dir;
+ int i;
+
+ pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+
+ dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+ DMA_NONE : DMA_FROM_DEVICE;
+
+ dma_addr = dma_map_page(device->dev, dest, offset, len, dir);
+ tx->tx_set_dest(dma_addr, tx, 0);
+
+ dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+ DMA_NONE : DMA_TO_DEVICE;
+
+ for (i = 0; i < src_cnt; i++) {
+ dma_addr = dma_map_page(device->dev, src_list[i],
+ offset, len, dir);
+ tx->tx_set_src(dma_addr, tx, i);
+ }
+
+ async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+}
+
+static void
+do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
+ unsigned int src_cnt, size_t len, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
+{
+ void *_dest;
+ int i;
+
+ pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+
+ /* reuse the 'src_list' array to convert to buffer pointers */
+ for (i = 0; i < src_cnt; i++)
+ src_list[i] = (struct page *)
+ (page_address(src_list[i]) + offset);
+
+ /* set destination address */
+ _dest = page_address(dest) + offset;
+
+ if (flags & ASYNC_TX_XOR_ZERO_DST)
+ memset(_dest, 0, len);
+
+ xor_blocks(src_cnt, len, _dest,
+ (void **) src_list);
+
+ async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+}
+
+/**
+ * async_xor - attempt to xor a set of blocks with a dma engine.
+ * xor_blocks always uses the dest as a source so the ASYNC_TX_XOR_ZERO_DST
+ * flag must be set to not include dest data in the calculation. The
+ * assumption with dma eninges is that they only use the destination
+ * buffer as a source when it is explicity specified in the source list.
+ * @dest: destination page
+ * @src_list: array of source pages (if the dest is also a source it must be
+ * at index zero). The contents of this array may be overwritten.
+ * @offset: offset in pages to start transaction
+ * @src_cnt: number of source pages
+ * @len: length in bytes
+ * @flags: ASYNC_TX_XOR_ZERO_DST, ASYNC_TX_XOR_DROP_DEST,
+ * ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: xor depends on the result of this transaction.
+ * @cb_fn: function to call when the xor completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+ int src_cnt, size_t len, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
+{
+ struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_XOR);
+ struct dma_device *device = chan ? chan->device : NULL;
+ struct dma_async_tx_descriptor *tx = NULL;
+ dma_async_tx_callback _cb_fn;
+ void *_cb_param;
+ unsigned long local_flags;
+ int xor_src_cnt;
+ int i = 0, src_off = 0, int_en;
+
+ BUG_ON(src_cnt <= 1);
+
+ while (src_cnt) {
+ local_flags = flags;
+ if (device) { /* run the xor asynchronously */
+ xor_src_cnt = min(src_cnt, device->max_xor);
+ /* if we are submitting additional xors
+ * only set the callback on the last transaction
+ */
+ if (src_cnt > xor_src_cnt) {
+ local_flags &= ~ASYNC_TX_ACK;
+ _cb_fn = NULL;
+ _cb_param = NULL;
+ } else {
+ _cb_fn = cb_fn;
+ _cb_param = cb_param;
+ }
+
+ int_en = _cb_fn ? 1 : 0;
+
+ tx = device->device_prep_dma_xor(
+ chan, xor_src_cnt, len, int_en);
+
+ if (tx) {
+ do_async_xor(tx, device, chan, dest,
+ &src_list[src_off], offset, xor_src_cnt, len,
+ local_flags, depend_tx, _cb_fn,
+ _cb_param);
+ } else /* fall through */
+ goto xor_sync;
+ } else { /* run the xor synchronously */
+xor_sync:
+ /* in the sync case the dest is an implied source
+ * (assumes the dest is at the src_off index)
+ */
+ if (flags & ASYNC_TX_XOR_DROP_DST) {
+ src_cnt--;
+ src_off++;
+ }
+
+ /* process up to 'MAX_XOR_BLOCKS' sources */
+ xor_src_cnt = min(src_cnt, MAX_XOR_BLOCKS);
+
+ /* if we are submitting additional xors
+ * only set the callback on the last transaction
+ */
+ if (src_cnt > xor_src_cnt) {
+ local_flags &= ~ASYNC_TX_ACK;
+ _cb_fn = NULL;
+ _cb_param = NULL;
+ } else {
+ _cb_fn = cb_fn;
+ _cb_param = cb_param;
+ }
+
+ /* wait for any prerequisite operations */
+ if (depend_tx) {
+ /* if ack is already set then we cannot be sure
+ * we are referring to the correct operation
+ */
+ BUG_ON(depend_tx->ack);
+ if (dma_wait_for_async_tx(depend_tx) ==
+ DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for "
+ "depend_tx\n",
+ __FUNCTION__);
+ }
+
+ do_sync_xor(dest, &src_list[src_off], offset,
+ xor_src_cnt, len, local_flags, depend_tx,
+ _cb_fn, _cb_param);
+ }
+
+ /* the previous tx is hidden from the client,
+ * so ack it
+ */
+ if (i && depend_tx)
+ async_tx_ack(depend_tx);
+
+ depend_tx = tx;
+
+ if (src_cnt > xor_src_cnt) {
+ /* drop completed sources */
+ src_cnt -= xor_src_cnt;
+ src_off += xor_src_cnt;
+
+ /* unconditionally preserve the destination */
+ flags &= ~ASYNC_TX_XOR_ZERO_DST;
+
+ /* use the intermediate result a source, but remember
+ * it's dropped, because it's implied, in the sync case
+ */
+ src_list[--src_off] = dest;
+ src_cnt++;
+ flags |= ASYNC_TX_XOR_DROP_DST;
+ } else
+ src_cnt = 0;
+ i++;
+ }
+
+ return tx;
+}
+EXPORT_SYMBOL_GPL(async_xor);
+
+static int page_is_zero(struct page *p, unsigned int offset, size_t len)
+{
+ char *a = page_address(p) + offset;
+ return ((*(u32 *) a) == 0 &&
+ memcmp(a, a + 4, len - 4) == 0);
+}
+
+/**
+ * async_xor_zero_sum - attempt a xor parity check with a dma engine.
+ * @dest: destination page used if the xor is performed synchronously
+ * @src_list: array of source pages. The dest page must be listed as a source
+ * at index zero. The contents of this array may be overwritten.
+ * @offset: offset in pages to start transaction
+ * @src_cnt: number of source pages
+ * @len: length in bytes
+ * @result: 0 if sum == 0 else non-zero
+ * @flags: ASYNC_TX_ASSUME_COHERENT, ASYNC_TX_ACK, ASYNC_TX_DEP_ACK
+ * @depend_tx: xor depends on the result of this transaction.
+ * @cb_fn: function to call when the xor completes
+ * @cb_param: parameter to pass to the callback routine
+ */
+struct dma_async_tx_descriptor *
+async_xor_zero_sum(struct page *dest, struct page **src_list,
+ unsigned int offset, int src_cnt, size_t len,
+ u32 *result, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_param)
+{
+ struct dma_chan *chan = async_tx_find_channel(depend_tx, DMA_ZERO_SUM);
+ struct dma_device *device = chan ? chan->device : NULL;
+ int int_en = cb_fn ? 1 : 0;
+ struct dma_async_tx_descriptor *tx = device ?
+ device->device_prep_dma_zero_sum(chan, src_cnt, len, result,
+ int_en) : NULL;
+ int i;
+
+ BUG_ON(src_cnt <= 1);
+
+ if (tx) {
+ dma_addr_t dma_addr;
+ enum dma_data_direction dir;
+
+ pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+
+ dir = (flags & ASYNC_TX_ASSUME_COHERENT) ?
+ DMA_NONE : DMA_TO_DEVICE;
+
+ for (i = 0; i < src_cnt; i++) {
+ dma_addr = dma_map_page(device->dev, src_list[i],
+ offset, len, dir);
+ tx->tx_set_src(dma_addr, tx, i);
+ }
+
+ async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
+ } else {
+ unsigned long xor_flags = flags;
+
+ pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+
+ xor_flags |= ASYNC_TX_XOR_DROP_DST;
+ xor_flags &= ~ASYNC_TX_ACK;
+
+ tx = async_xor(dest, src_list, offset, src_cnt, len, xor_flags,
+ depend_tx, NULL, NULL);
+
+ if (tx) {
+ if (dma_wait_for_async_tx(tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for tx\n",
+ __FUNCTION__);
+ async_tx_ack(tx);
+ }
+
+ *result = page_is_zero(dest, offset, len) ? 0 : 1;
+
+ tx = NULL;
+
+ async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
+ }
+
+ return tx;
+}
+EXPORT_SYMBOL_GPL(async_xor_zero_sum);
+
+static int __init async_xor_init(void)
+{
+ return 0;
+}
+
+static void __exit async_xor_exit(void)
+{
+ do { } while (0);
+}
+
+module_init(async_xor_init);
+module_exit(async_xor_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("asynchronous xor/xor-zero-sum api");
+MODULE_LICENSE("GPL");
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 8edf40c835a..40a3dcff15b 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -336,16 +336,41 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
return blkcipher_walk_next(desc, walk);
}
+static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+ struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher;
+ unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+ int ret;
+ u8 *buffer, *alignbuffer;
+ unsigned long absize;
+
+ absize = keylen + alignmask;
+ buffer = kmalloc(absize, GFP_ATOMIC);
+ if (!buffer)
+ return -ENOMEM;
+
+ alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+ memcpy(alignbuffer, key, keylen);
+ ret = cipher->setkey(tfm, alignbuffer, keylen);
+ memset(alignbuffer, 0, absize);
+ kfree(buffer);
+ return ret;
+}
+
static int setkey(struct crypto_tfm *tfm, const u8 *key,
unsigned int keylen)
{
struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher;
+ unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
}
+ if ((unsigned long)key & alignmask)
+ return setkey_unaligned(tfm, key, keylen);
+
return cipher->setkey(tfm, key, keylen);
}
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 333aab2f027..0b2650c2014 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -20,16 +20,43 @@
#include <linux/string.h>
#include "internal.h"
+static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+ struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
+ unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+ int ret;
+ u8 *buffer, *alignbuffer;
+ unsigned long absize;
+
+ absize = keylen + alignmask;
+ buffer = kmalloc(absize, GFP_ATOMIC);
+ if (!buffer)
+ return -ENOMEM;
+
+ alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+ memcpy(alignbuffer, key, keylen);
+ ret = cia->cia_setkey(tfm, alignbuffer, keylen);
+ memset(alignbuffer, 0, absize);
+ kfree(buffer);
+ return ret;
+
+}
+
static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
{
struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher;
-
+ unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+
tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
return -EINVAL;
- } else
- return cia->cia_setkey(tfm, key, keylen);
+ }
+
+ if ((unsigned long)key & alignmask)
+ return setkey_unaligned(tfm, key, keylen);
+
+ return cia->cia_setkey(tfm, key, keylen);
}
static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 3ff4e1f0f03..ac6dce2e759 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -298,7 +298,7 @@ static inline int cryptd_create_thread(struct cryptd_state *state,
mutex_init(&state->mutex);
crypto_init_queue(&state->queue, CRYPTD_MAX_QLEN);
- state->task = kthread_create(fn, state, name);
+ state->task = kthread_run(fn, state, name);
if (IS_ERR(state->task))
return PTR_ERR(state->task);
@@ -316,6 +316,8 @@ static int cryptd_thread(void *data)
struct cryptd_state *state = data;
int stop;
+ current->flags |= PF_NOFREEZE;
+
do {
struct crypto_async_request *req, *backlog;
diff --git a/crypto/hash.c b/crypto/hash.c
index 4ccd22deef3..4d75ca7b57b 100644
--- a/crypto/hash.c
+++ b/crypto/hash.c
@@ -22,6 +22,42 @@ static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg, u32 type,
return alg->cra_ctxsize;
}
+static int hash_setkey_unaligned(struct crypto_hash *crt, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_tfm *tfm = crypto_hash_tfm(crt);
+ struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+ unsigned long alignmask = crypto_hash_alignmask(crt);
+ int ret;
+ u8 *buffer, *alignbuffer;
+ unsigned long absize;
+
+ absize = keylen + alignmask;
+ buffer = kmalloc(absize, GFP_ATOMIC);
+ if (!buffer)
+ return -ENOMEM;
+
+ alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+ memcpy(alignbuffer, key, keylen);
+ ret = alg->setkey(crt, alignbuffer, keylen);
+ memset(alignbuffer, 0, absize);
+ kfree(buffer);
+ return ret;
+}
+
+static int hash_setkey(struct crypto_hash *crt, const u8 *key,
+ unsigned int keylen)
+{
+ struct crypto_tfm *tfm = crypto_hash_tfm(crt);
+ struct hash_alg *alg = &tfm->__crt_alg->cra_hash;
+ unsigned long alignmask = crypto_hash_alignmask(crt);
+
+ if ((unsigned long)key & alignmask)
+ return hash_setkey_unaligned(crt, key, keylen);
+
+ return alg->setkey(crt, key, keylen);
+}
+
static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
struct hash_tfm *crt = &tfm->crt_hash;
@@ -34,7 +70,7 @@ static int crypto_init_hash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
crt->update = alg->update;
crt->final = alg->final;
crt->digest = alg->digest;
- crt->setkey = alg->setkey;
+ crt->setkey = hash_setkey;
crt->digestsize = alg->digestsize;
return 0;
diff --git a/drivers/md/xor.c b/crypto/xor.c
index 324897c4be4..b2e6db075e4 100644
--- a/drivers/md/xor.c
+++ b/crypto/xor.c
@@ -26,32 +26,32 @@
static struct xor_block_template *active_template;
void
-xor_block(unsigned int count, unsigned int bytes, void **ptr)
+xor_blocks(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
{
- unsigned long *p0, *p1, *p2, *p3, *p4;
+ unsigned long *p1, *p2, *p3, *p4;
- p0 = (unsigned long *) ptr[0];
- p1 = (unsigned long *) ptr[1];
- if (count == 2) {
- active_template->do_2(bytes, p0, p1);
+ p1 = (unsigned long *) srcs[0];
+ if (src_count == 1) {
+ active_template->do_2(bytes, dest, p1);
return;
}
- p2 = (unsigned long *) ptr[2];
- if (count == 3) {
- active_template->do_3(bytes, p0, p1, p2);
+ p2 = (unsigned long *) srcs[1];
+ if (src_count == 2) {
+ active_template->do_3(bytes, dest, p1, p2);
return;
}
- p3 = (unsigned long *) ptr[3];
- if (count == 4) {
- active_template->do_4(bytes, p0, p1, p2, p3);
+ p3 = (unsigned long *) srcs[2];
+ if (src_count == 3) {
+ active_template->do_4(bytes, dest, p1, p2, p3);
return;
}
- p4 = (unsigned long *) ptr[4];
- active_template->do_5(bytes, p0, p1, p2, p3, p4);
+ p4 = (unsigned long *) srcs[3];
+ active_template->do_5(bytes, dest, p1, p2, p3, p4);
}
+EXPORT_SYMBOL(xor_blocks);
/* Set of all registered templates. */
static struct xor_block_template *template_list;
@@ -78,7 +78,7 @@ do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
now = jiffies;
count = 0;
while (jiffies == now) {
- mb();
+ mb(); /* prevent loop optimzation */
tmpl->do_2(BENCH_SIZE, b1, b2);
mb();
count++;
@@ -91,26 +91,26 @@ do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
speed = max * (HZ * BENCH_SIZE / 1024);
tmpl->speed = speed;
- printk(" %-10s: %5d.%03d MB/sec\n", tmpl->name,
+ printk(KERN_INFO " %-10s: %5d.%03d MB/sec\n", tmpl->name,
speed / 1000, speed % 1000);
}
-static int
-calibrate_xor_block(void)
+static int __init
+calibrate_xor_blocks(void)
{
void *b1, *b2;
struct xor_block_template *f, *fastest;
b1 = (void *) __get_free_pages(GFP_KERNEL, 2);
- if (! b1) {
- printk("raid5: Yikes! No memory available.\n");
+ if (!b1) {
+ printk(KERN_WARNING "xor: Yikes! No memory available.\n");
return -ENOMEM;
}
b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE;
/*
- * If this arch/cpu has a short-circuited selection, don't loop through all
- * the possible functions, just test the best one
+ * If this arch/cpu has a short-circuited selection, don't loop through
+ * all the possible functions, just test the best one
*/
fastest = NULL;
@@ -122,11 +122,12 @@ calibrate_xor_block(void)
#define xor_speed(templ) do_xor_speed((templ), b1, b2)
if (fastest) {
- printk(KERN_INFO "raid5: automatically using best checksumming function: %s\n",
+ printk(KERN_INFO "xor: automatically using best "
+ "checksumming function: %s\n",
fastest->name);
xor_speed(fastest);
} else {
- printk(KERN_INFO "raid5: measuring checksumming speed\n");
+ printk(KERN_INFO "xor: measuring software checksum speed\n");
XOR_TRY_TEMPLATES;
fastest = template_list;
for (f = fastest; f; f = f->next)
@@ -134,7 +135,7 @@ calibrate_xor_block(void)
fastest = f;
}
- printk("raid5: using function: %s (%d.%03d MB/sec)\n",
+ printk(KERN_INFO "xor: using function: %s (%d.%03d MB/sec)\n",
fastest->name, fastest->speed / 1000, fastest->speed % 1000);
#undef xor_speed
@@ -147,8 +148,8 @@ calibrate_xor_block(void)
static __exit void xor_exit(void) { }
-EXPORT_SYMBOL(xor_block);
MODULE_LICENSE("GPL");
-module_init(calibrate_xor_block);
+/* when built-in xor.o must initialize before drivers/md/md.o */
+core_initcall(calibrate_xor_blocks);
module_exit(xor_exit);
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 050323fd79e..7916f4b86d2 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -24,8 +24,6 @@ source "drivers/scsi/Kconfig"
source "drivers/ata/Kconfig"
-source "drivers/cdrom/Kconfig"
-
source "drivers/md/Kconfig"
source "drivers/message/fusion/Kconfig"
@@ -54,6 +52,8 @@ source "drivers/spi/Kconfig"
source "drivers/w1/Kconfig"
+source "drivers/power/Kconfig"
+
source "drivers/hwmon/Kconfig"
source "drivers/mfd/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index adad2f3d438..503d8256944 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_RTC_LIB) += rtc/
obj-y += i2c/
obj-$(CONFIG_W1) += w1/
+obj-$(CONFIG_POWER_SUPPLY) += power/
obj-$(CONFIG_HWMON) += hwmon/
obj-$(CONFIG_PHONE) += telephony/
obj-$(CONFIG_MD) += md/
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index 674bf81c6e6..423ed08fb6f 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1246,7 +1246,7 @@ repeat:
del_timer(&motor_off_timer);
ReqCnt = 0;
- ReqCmd = CURRENT->cmd;
+ ReqCmd = rq_data_dir(CURRENT);
ReqBlock = CURRENT->sector;
ReqBuffer = CURRENT->buffer;
setup_req_params(drive);
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
index 689a4c3542b..d85520f78e6 100644
--- a/drivers/acorn/block/mfmhd.c
+++ b/drivers/acorn/block/mfmhd.c
@@ -439,7 +439,7 @@ static void mfm_rw_intr(void)
a choice of command end or some data which is ready to be collected */
/* I think we have to transfer data while the interrupt line is on and its
not any other type of interrupt */
- if (CURRENT->cmd == WRITE) {
+ if (rq_data_dir(CURRENT) == WRITE) {
extern void hdc63463_writedma(void);
if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
@@ -799,7 +799,7 @@ static void issue_request(unsigned int block, unsigned int nsect,
raw_cmd.head = start_head;
raw_cmd.cylinder = track / p->heads;
raw_cmd.cmdtype = CURRENT->cmd;
- raw_cmd.cmdcode = CURRENT->cmd == WRITE ? CMD_WD : CMD_RD;
+ raw_cmd.cmdcode = rq_data_dir(CURRENT) == WRITE ? CMD_WD : CMD_RD;
raw_cmd.cmddata[0] = dev + 1; /* DAG: +1 to get US */
raw_cmd.cmddata[1] = raw_cmd.head;
raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
@@ -830,7 +830,7 @@ static void issue_request(unsigned int block, unsigned int nsect,
hdc63463_dataleft = nsect * 256; /* Better way? */
DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
- raw_cmd.dev + 'a', (CURRENT->cmd == READ) ? "read" : "writ",
+ raw_cmd.dev + 'a', rq_data_dir(CURRENT) == READ ? "read" : "writ",
raw_cmd.cylinder,
raw_cmd.head,
raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
@@ -917,13 +917,6 @@ static void mfm_request(void)
DBG("mfm_request: block after offset=%d\n", block);
- if (CURRENT->cmd != READ && CURRENT->cmd != WRITE) {
- printk("unknown mfm-command %d\n", CURRENT->cmd);
- end_request(CURRENT, 0);
- Busy = 0;
- printk("mfm: continue 4\n");
- continue;
- }
issue_request(block, nsect, CURRENT);
break;
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index b770deab968..3cd79caad70 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -1357,7 +1357,7 @@ static struct backlight_ops asus_backlight_data = {
.update_status = set_brightness_status,
};
-static void __exit asus_acpi_exit(void)
+static void asus_acpi_exit(void)
{
if (asus_backlight_device)
backlight_device_unregister(asus_backlight_device);
@@ -1398,7 +1398,7 @@ static int __init asus_acpi_init(void)
if (!asus_hotk_found) {
acpi_bus_unregister_driver(&asus_hotk_driver);
remove_proc_entry(PROC_ASUS, acpi_root_dir);
- return result;
+ return -ENODEV;
}
asus_backlight_device = backlight_device_register("asus",NULL,NULL,
@@ -1407,6 +1407,7 @@ static int __init asus_acpi_init(void)
printk(KERN_ERR "Could not register asus backlight device\n");
asus_backlight_device = NULL;
asus_acpi_exit();
+ return -ENODEV;
}
asus_backlight_device->props.max_brightness = 15;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index a2efae8a4c4..0c9f15c54e8 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -59,7 +59,7 @@ int node_to_pxm(int node)
return node_to_pxm_map[node];
}
-int __cpuinit acpi_map_pxm_to_node(int pxm)
+int acpi_map_pxm_to_node(int pxm)
{
int node = pxm_to_node_map[pxm];
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index b998340e23d..2e7ba615d76 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -33,6 +33,7 @@
#include <linux/interrupt.h>
#include <linux/kmod.h>
#include <linux/delay.h>
+#include <linux/dmi.h>
#include <linux/workqueue.h>
#include <linux/nmi.h>
#include <linux/acpi.h>
@@ -73,6 +74,21 @@ static void *acpi_irq_context;
static struct workqueue_struct *kacpid_wq;
static struct workqueue_struct *kacpi_notify_wq;
+#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
+static char osi_additional_string[OSI_STRING_LENGTH_MAX];
+
+#define OSI_LINUX_ENABLED
+#ifdef OSI_LINUX_ENABLED
+int osi_linux = 1; /* enable _OSI(Linux) by default */
+#else
+int osi_linux; /* disable _OSI(Linux) by default */
+#endif
+
+
+#ifdef CONFIG_DMI
+static struct __initdata dmi_system_id acpi_osl_dmi_table[];
+#endif
+
static void __init acpi_request_region (struct acpi_generic_address *addr,
unsigned int length, char *desc)
{
@@ -121,8 +137,9 @@ static int __init acpi_reserve_resources(void)
}
device_initcall(acpi_reserve_resources);
-acpi_status acpi_os_initialize(void)
+acpi_status __init acpi_os_initialize(void)
{
+ dmi_check_system(acpi_osl_dmi_table);
return AE_OK;
}
@@ -960,20 +977,38 @@ static int __init acpi_os_name_setup(char *str)
__setup("acpi_os_name=", acpi_os_name_setup);
+static void enable_osi_linux(int enable) {
+
+ if (osi_linux != enable)
+ printk(KERN_INFO PREFIX "%sabled _OSI(Linux)\n",
+ enable ? "En": "Dis");
+
+ osi_linux = enable;
+ return;
+}
+
/*
- * _OSI control
+ * Modify the list of "OS Interfaces" reported to BIOS via _OSI
+ *
* empty string disables _OSI
- * TBD additional string adds to _OSI
+ * string starting with '!' disables that string
+ * otherwise string is added to list, augmenting built-in strings
*/
static int __init acpi_osi_setup(char *str)
{
if (str == NULL || *str == '\0') {
printk(KERN_INFO PREFIX "_OSI method disabled\n");
acpi_gbl_create_osi_method = FALSE;
- } else {
- /* TBD */
- printk(KERN_ERR PREFIX "_OSI additional string ignored -- %s\n",
- str);
+ } else if (!strcmp("!Linux", str)) {
+ enable_osi_linux(0);
+ } else if (*str == '!') {
+ if (acpi_osi_invalidate(++str) == AE_OK)
+ printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
+ } else if (!strcmp("Linux", str)) {
+ enable_osi_linux(1);
+ } else if (*osi_additional_string == '\0') {
+ strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
+ printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
}
return 1;
@@ -1143,11 +1178,28 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
acpi_status
acpi_os_validate_interface (char *interface)
{
-
- return AE_SUPPORT;
+ if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
+ return AE_OK;
+ if (!strcmp("Linux", interface)) {
+ printk(KERN_WARNING PREFIX
+ "System BIOS is requesting _OSI(Linux)\n");
+#ifdef OSI_LINUX_ENABLED
+ printk(KERN_WARNING PREFIX
+ "Please test with \"acpi_osi=!Linux\"\n"
+ "Please send dmidecode "
+ "to linux-acpi@vger.kernel.org\n");
+#else
+ printk(KERN_WARNING PREFIX
+ "If \"acpi_osi=Linux\" works better,\n"
+ "Please send dmidecode "
+ "to linux-acpi@vger.kernel.org\n");
+#endif
+ if(osi_linux)
+ return AE_OK;
+ }
+ return AE_SUPPORT;
}
-
/******************************************************************************
*
* FUNCTION: acpi_os_validate_address
@@ -1174,5 +1226,51 @@ acpi_os_validate_address (
return AE_OK;
}
+#ifdef CONFIG_DMI
+#ifdef OSI_LINUX_ENABLED
+static int dmi_osi_not_linux(struct dmi_system_id *d)
+{
+ printk(KERN_NOTICE "%s detected: requires not _OSI(Linux)\n", d->ident);
+ enable_osi_linux(0);
+ return 0;
+}
+#else
+static int dmi_osi_linux(struct dmi_system_id *d)
+{
+ printk(KERN_NOTICE "%s detected: requires _OSI(Linux)\n", d->ident);
+ enable_osi_linux(1);
+ return 0;
+}
+#endif
+
+static struct dmi_system_id acpi_osl_dmi_table[] __initdata = {
+#ifdef OSI_LINUX_ENABLED
+ /*
+ * Boxes that need NOT _OSI(Linux)
+ */
+ {
+ .callback = dmi_osi_not_linux,
+ .ident = "Toshiba Satellite P100",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_BOARD_NAME, "Satellite P100"),
+ },
+ },
+#else
+ /*
+ * Boxes that need _OSI(Linux)
+ */
+ {
+ .callback = dmi_osi_linux,
+ .ident = "Intel Napa CRB",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"),
+ },
+ },
+#endif
+ {}
+};
+#endif /* CONFIG_DMI */
#endif
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index f7de02a6f49..e1ca86dfdd6 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -115,7 +115,6 @@ struct acpi_processor_errata errata __read_mostly;
static int acpi_processor_errata_piix4(struct pci_dev *dev)
{
- u8 rev = 0;
u8 value1 = 0;
u8 value2 = 0;
@@ -127,9 +126,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
* Note that 'dev' references the PIIX4 ACPI Controller.
*/
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
- switch (rev) {
+ switch (dev->revision) {
case 0:
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found PIIX4 A-step\n"));
break;
@@ -147,7 +144,7 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
break;
}
- switch (rev) {
+ switch (dev->revision) {
case 0: /* PIIX4 A-step */
case 1: /* PIIX4 B-step */
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index ee5759bef94..80ffc782991 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -332,16 +332,18 @@ static void acpi_processor_idle(void)
int sleep_ticks = 0;
u32 t1, t2 = 0;
- pr = processors[smp_processor_id()];
- if (!pr)
- return;
-
/*
* Interrupts must be disabled during bus mastering calculations and
* for C2/C3 transitions.
*/
local_irq_disable();
+ pr = processors[smp_processor_id()];
+ if (!pr) {
+ local_irq_enable();
+ return;
+ }
+
/*
* Check whether we truly need to go idle, or should
* reschedule:
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 0e7b121a99c..3bc0c67a928 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -123,14 +123,14 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc,
}
}
- /* The table must be either an SSDT or a PSDT */
+ /* The table must be either an SSDT or a PSDT or an OEMx */
if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT))
&&
- (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)))
- {
+ (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
+ && (strncmp(table_desc->pointer->signature, "OEM", 3))) {
ACPI_ERROR((AE_INFO,
- "Table has invalid signature [%4.4s], must be SSDT or PSDT",
+ "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx",
table_desc->pointer->signature));
return_ACPI_STATUS(AE_BAD_SIGNATURE);
}
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 1ada017d01e..88a6fc7fd27 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -827,6 +827,9 @@ static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_thermal *tz = seq->private;
+ struct acpi_device *device;
+ acpi_status status;
+
int i = 0;
int j = 0;
@@ -849,9 +852,10 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
tz->trips.passive.tc1, tz->trips.passive.tc2,
tz->trips.passive.tsp);
for (j = 0; j < tz->trips.passive.devices.count; j++) {
-
- seq_printf(seq, "0x%p ",
- tz->trips.passive.devices.handles[j]);
+ status = acpi_bus_get_device(tz->trips.passive.devices.
+ handles[j], &device);
+ seq_printf(seq, "%4.4s ", status ? "" :
+ acpi_device_bid(device));
}
seq_puts(seq, "\n");
}
@@ -862,9 +866,13 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
seq_printf(seq, "active[%d]: %ld C: devices=",
i,
KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
- for (j = 0; j < tz->trips.active[i].devices.count; j++)
- seq_printf(seq, "0x%p ",
- tz->trips.active[i].devices.handles[j]);
+ for (j = 0; j < tz->trips.active[i].devices.count; j++){
+ status = acpi_bus_get_device(tz->trips.active[i].
+ devices.handles[j],
+ &device);
+ seq_printf(seq, "%4.4s ", status ? "" :
+ acpi_device_bid(device));
+ }
seq_puts(seq, "\n");
}
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 3906d47b978..13369b45563 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -524,7 +524,7 @@ static acpi_status __init add_device(void)
return AE_OK;
}
-static acpi_status __exit remove_device(void)
+static acpi_status remove_device(void)
{
ProcItem *item;
@@ -538,7 +538,7 @@ static struct backlight_ops toshiba_backlight_data = {
.update_status = set_lcd_status,
};
-static void __exit toshiba_acpi_exit(void)
+static void toshiba_acpi_exit(void)
{
if (toshiba_backlight_device)
backlight_device_unregister(toshiba_backlight_device);
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 4c1e00874df..879eaa10d3a 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -68,6 +68,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
union acpi_operand_object **return_obj);
static acpi_status
+acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
+ union acpi_operand_object **internal_object);
+
+static acpi_status
acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
union acpi_operand_object *dest_desc);
@@ -518,77 +522,73 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
return_ACPI_STATUS(AE_NO_MEMORY);
}
-#ifdef ACPI_FUTURE_IMPLEMENTATION
-/* Code to convert packages that are parameters to control methods */
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_epackage_to_ipackage
*
- * PARAMETERS: *internal_object - Pointer to the object we are returning
- * *Buffer - Where the object is returned
- * *space_used - Where the length of the object is returned
+ * PARAMETERS: external_object - The external object to be converted
+ * internal_object - Where the internal object is returned
*
* RETURN: Status
*
- * DESCRIPTION: This function is called to place a package object in a user
- * buffer. A package object by definition contains other objects.
- *
- * The buffer is assumed to have sufficient space for the object.
- * The caller must have verified the buffer length needed using the
- * acpi_ut_get_object_size function before calling this function.
+ * DESCRIPTION: Copy an external package object to an internal package.
+ * Handles nested packages.
*
******************************************************************************/
static acpi_status
-acpi_ut_copy_epackage_to_ipackage(union acpi_operand_object *internal_object,
- u8 * buffer, u32 * space_used)
+acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
+ union acpi_operand_object **internal_object)
{
- u8 *free_space;
- union acpi_object *external_object;
- u32 length = 0;
- u32 this_index;
- u32 object_space = 0;
- union acpi_operand_object *this_internal_obj;
- union acpi_object *this_external_obj;
+ acpi_status status = AE_OK;
+ union acpi_operand_object *package_object;
+ union acpi_operand_object **package_elements;
+ acpi_native_uint i;
ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
- /*
- * First package at head of the buffer
- */
- external_object = (union acpi_object *)buffer;
+ /* Create the package object */
- /*
- * Free space begins right after the first package
- */
- free_space = buffer + sizeof(union acpi_object);
+ package_object =
+ acpi_ut_create_package_object(external_object->package.count);
+ if (!package_object) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
+ }
- external_object->type = ACPI_GET_OBJECT_TYPE(internal_object);
- external_object->package.count = internal_object->package.count;
- external_object->package.elements = (union acpi_object *)free_space;
+ package_elements = package_object->package.elements;
/*
- * Build an array of ACPI_OBJECTS in the buffer
- * and move the free space past it
+ * Recursive implementation. Probably ok, since nested external packages
+ * as parameters should be very rare.
*/
- free_space +=
- external_object->package.count * sizeof(union acpi_object);
+ for (i = 0; i < external_object->package.count; i++) {
+ status =
+ acpi_ut_copy_eobject_to_iobject(&external_object->package.
+ elements[i],
+ &package_elements[i]);
+ if (ACPI_FAILURE(status)) {
- /* Call walk_package */
+ /* Truncate package and delete it */
-}
+ package_object->package.count = i;
+ package_elements[i] = NULL;
+ acpi_ut_remove_reference(package_object);
+ return_ACPI_STATUS(status);
+ }
+ }
-#endif /* Future implementation */
+ *internal_object = package_object;
+ return_ACPI_STATUS(status);
+}
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_eobject_to_iobject
*
- * PARAMETERS: *internal_object - The external object to be converted
- * *buffer_ptr - Where the internal object is returned
+ * PARAMETERS: external_object - The external object to be converted
+ * internal_object - Where the internal object is returned
*
- * RETURN: Status - the status of the call
+ * RETURN: Status - the status of the call
*
* DESCRIPTION: Converts an external object to an internal object.
*
@@ -603,16 +603,10 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
if (external_object->type == ACPI_TYPE_PACKAGE) {
- /*
- * Packages as external input to control methods are not supported,
- */
- ACPI_ERROR((AE_INFO,
- "Packages as parameters not implemented!"));
-
- return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
- }
-
- else {
+ status =
+ acpi_ut_copy_epackage_to_ipackage(external_object,
+ internal_object);
+ } else {
/*
* Build a simple object (no nested objects)
*/
@@ -803,33 +797,19 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type,
* Create and build the package object
*/
target_object =
- acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
+ acpi_ut_create_package_object(source_object->package.count);
if (!target_object) {
return (AE_NO_MEMORY);
}
- target_object->package.count = source_object->package.count;
target_object->common.flags = source_object->common.flags;
- /*
- * Create the object array
- */
- target_object->package.elements =
- ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.
- count + 1) * sizeof(void *));
- if (!target_object->package.elements) {
- status = AE_NO_MEMORY;
- goto error_exit;
- }
+ /* Pass the new package object back to the package walk routine */
- /*
- * Pass the new package object back to the package walk routine
- */
state->pkg.this_target_obj = target_object;
- /*
- * Store the object pointer in the parent package object
- */
+ /* Store the object pointer in the parent package object */
+
*this_target_ptr = target_object;
break;
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 13d5879cd98..8ec6f8e4813 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -59,10 +59,9 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
/*
* Strings supported by the _OSI predefined (internal) method.
*/
-static const char *acpi_interfaces_supported[] = {
+static char *acpi_interfaces_supported[] = {
/* Operating System Vendor Strings */
- "Linux",
"Windows 2000",
"Windows 2001",
"Windows 2001 SP0",
@@ -158,6 +157,31 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
/*******************************************************************************
*
+ * FUNCTION: acpi_osi_invalidate
+ *
+ * PARAMETERS: interface_string
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: invalidate string in pre-defiend _OSI string list
+ *
+ ******************************************************************************/
+
+acpi_status acpi_osi_invalidate(char *interface)
+{
+ int i;
+
+ for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
+ if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) {
+ *acpi_interfaces_supported[i] = '\0';
+ return AE_OK;
+ }
+ }
+ return AE_NOT_FOUND;
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ut_evaluate_object
*
* PARAMETERS: prefix_node - Starting node
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index 4696124759e..76ee766c84f 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -146,6 +146,48 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name,
/*******************************************************************************
*
+ * FUNCTION: acpi_ut_create_package_object
+ *
+ * PARAMETERS: Count - Number of package elements
+ *
+ * RETURN: Pointer to a new Package object, null on failure
+ *
+ * DESCRIPTION: Create a fully initialized package object
+ *
+ ******************************************************************************/
+
+union acpi_operand_object *acpi_ut_create_package_object(u32 count)
+{
+ union acpi_operand_object *package_desc;
+ union acpi_operand_object **package_elements;
+
+ ACPI_FUNCTION_TRACE_U32(ut_create_package_object, count);
+
+ /* Create a new Package object */
+
+ package_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
+ if (!package_desc) {
+ return_PTR(NULL);
+ }
+
+ /*
+ * Create the element array. Count+1 allows the array to be null
+ * terminated.
+ */
+ package_elements = ACPI_ALLOCATE_ZEROED((acpi_size)
+ (count + 1) * sizeof(void *));
+ if (!package_elements) {
+ acpi_ut_remove_reference(package_desc);
+ return_PTR(NULL);
+ }
+
+ package_desc->package.count = count;
+ package_desc->package.elements = package_elements;
+ return_PTR(package_desc);
+}
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ut_create_buffer_object
*
* PARAMETERS: buffer_size - Size of buffer to be created
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index e9a57806cd3..2d496918b3c 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -61,7 +61,7 @@ ACPI_MODULE_NAME("utxface")
* called, so any early initialization belongs here.
*
******************************************************************************/
-acpi_status acpi_initialize_subsystem(void)
+acpi_status __init acpi_initialize_subsystem(void)
{
acpi_status status;
@@ -108,8 +108,6 @@ acpi_status acpi_initialize_subsystem(void)
return_ACPI_STATUS(status);
}
-ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem)
-
/*******************************************************************************
*
* FUNCTION: acpi_enable_subsystem
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index b4a8d6030e4..d8046a113c3 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -16,6 +16,11 @@ menuconfig ATA
that "speaks" the ATA protocol, also called ATA controller),
because you will be asked for it.
+ NOTE: ATA enables basic SCSI support; *however*,
+ 'SCSI disk support', 'SCSI tape support', or
+ 'SCSI CDROM support' may also be needed,
+ depending on your hardware configuration.
+
if ATA
config ATA_NONSTANDARD
@@ -304,7 +309,7 @@ config PATA_HPT3X2N
If unsure, say N.
config PATA_HPT3X3
- tristate "HPT 343/363 PATA support (Experimental)"
+ tristate "HPT 343/363 PATA support"
depends on PCI
help
This option enables support for the HPT 343/363
@@ -312,6 +317,14 @@ config PATA_HPT3X3
If unsure, say N.
+config PATA_HPT3X3_DMA
+ bool "HPT 343/363 DMA support (Experimental)"
+ depends on PATA_HPT3X3
+ help
+ This option enables DMA support for the HPT343/363
+ controllers. Enable with care as there are still some
+ problems with DMA on this chipset.
+
config PATA_ISAPNP
tristate "ISA Plug and Play PATA support (Experimental)"
depends on EXPERIMENTAL && ISAPNP
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 7baeaffefe7..11e4eb9f304 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -46,7 +46,7 @@
#include <linux/libata.h>
#define DRV_NAME "ahci"
-#define DRV_VERSION "2.2"
+#define DRV_VERSION "2.3"
enum {
@@ -54,7 +54,7 @@ enum {
AHCI_MAX_PORTS = 32,
AHCI_MAX_SG = 168, /* hardware max is 64K */
AHCI_DMA_BOUNDARY = 0xffffffff,
- AHCI_USE_CLUSTERING = 0,
+ AHCI_USE_CLUSTERING = 1,
AHCI_MAX_CMDS = 32,
AHCI_CMD_SZ = 32,
AHCI_CMD_SLOT_SZ = AHCI_MAX_CMDS * AHCI_CMD_SZ,
@@ -81,6 +81,7 @@ enum {
board_ahci_vt8251 = 2,
board_ahci_ign_iferr = 3,
board_ahci_sb600 = 4,
+ board_ahci_mv = 5,
/* global controller registers */
HOST_CAP = 0x00, /* host capabilities */
@@ -171,6 +172,8 @@ enum {
AHCI_FLAG_HONOR_PI = (1 << 26), /* honor PORTS_IMPL */
AHCI_FLAG_IGN_SERR_INTERNAL = (1 << 27), /* ignore SERR_INTERNAL */
AHCI_FLAG_32BIT_ONLY = (1 << 28), /* force 32bit */
+ AHCI_FLAG_MV_PATA = (1 << 29), /* PATA port */
+ AHCI_FLAG_NO_MSI = (1 << 30), /* no PCI MSI */
AHCI_FLAG_COMMON = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
@@ -228,9 +231,12 @@ static void ahci_thaw(struct ata_port *ap);
static void ahci_error_handler(struct ata_port *ap);
static void ahci_vt8251_error_handler(struct ata_port *ap);
static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
+static int ahci_port_resume(struct ata_port *ap);
+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl);
+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+ u32 opts);
#ifdef CONFIG_PM
static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
-static int ahci_port_resume(struct ata_port *ap);
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
static int ahci_pci_device_resume(struct pci_dev *pdev);
#endif
@@ -327,14 +333,14 @@ static const struct ata_port_info ahci_port_info[] = {
{
.flags = AHCI_FLAG_COMMON,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_pi */
{
.flags = AHCI_FLAG_COMMON | AHCI_FLAG_HONOR_PI,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_vt8251 */
@@ -342,14 +348,14 @@ static const struct ata_port_info ahci_port_info[] = {
.flags = AHCI_FLAG_COMMON | ATA_FLAG_HRST_TO_RESUME |
AHCI_FLAG_NO_NCQ,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_vt8251_ops,
},
/* board_ahci_ign_iferr */
{
.flags = AHCI_FLAG_COMMON | AHCI_FLAG_IGN_IRQ_IF_ERR,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
/* board_ahci_sb600 */
@@ -358,7 +364,19 @@ static const struct ata_port_info ahci_port_info[] = {
AHCI_FLAG_IGN_SERR_INTERNAL |
AHCI_FLAG_32BIT_ONLY,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+ },
+ /* board_ahci_mv */
+ {
+ .sht = &ahci_sht,
+ .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+ ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_HONOR_PI |
+ AHCI_FLAG_NO_NCQ | AHCI_FLAG_NO_MSI |
+ AHCI_FLAG_MV_PATA,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &ahci_ops,
},
};
@@ -426,12 +444,39 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */
+ { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
+ { PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
/* SiS */
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
{ PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 966 */
{ PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */
+ /* Marvell */
+ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
+
/* Generic, PCI class code for AHCI */
{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -457,11 +502,17 @@ static inline int ahci_nr_ports(u32 cap)
return (cap & 0x1f) + 1;
}
-static inline void __iomem *ahci_port_base(struct ata_port *ap)
+static inline void __iomem *__ahci_port_base(struct ata_host *host,
+ unsigned int port_no)
{
- void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
+ void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+
+ return mmio + 0x100 + (port_no * 0x80);
+}
- return mmio + 0x100 + (ap->port_no * 0x80);
+static inline void __iomem *ahci_port_base(struct ata_port *ap)
+{
+ return __ahci_port_base(ap->host, ap->port_no);
}
/**
@@ -503,7 +554,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
/* fixup zero port_map */
if (!port_map) {
- port_map = (1 << ahci_nr_ports(hpriv->cap)) - 1;
+ port_map = (1 << ahci_nr_ports(cap)) - 1;
dev_printk(KERN_WARNING, &pdev->dev,
"PORTS_IMPL is zero, forcing 0x%x\n", port_map);
@@ -511,6 +562,20 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
hpriv->saved_port_map = port_map;
}
+ /*
+ * Temporary Marvell 6145 hack: PATA port presence
+ * is asserted through the standard AHCI port
+ * presence register, as bit 4 (counting from 0)
+ */
+ if (pi->flags & AHCI_FLAG_MV_PATA) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "MV_AHCI HACK: port_map %x -> %x\n",
+ hpriv->port_map,
+ hpriv->port_map & 0xf);
+
+ port_map &= 0xf;
+ }
+
/* cross check port_map and cap.n_ports */
if (pi->flags & AHCI_FLAG_HONOR_PI) {
u32 tmp_port_map = port_map;
@@ -716,7 +781,7 @@ static void ahci_power_down(struct ata_port *ap)
}
#endif
-static void ahci_init_port(struct ata_port *ap)
+static void ahci_start_port(struct ata_port *ap)
{
/* enable FIS reception */
ahci_start_fis_rx(ap);
@@ -790,39 +855,62 @@ static int ahci_reset_controller(struct ata_host *host)
return 0;
}
+static void ahci_port_init(struct pci_dev *pdev, struct ata_port *ap,
+ int port_no, void __iomem *mmio,
+ void __iomem *port_mmio)
+{
+ const char *emsg = NULL;
+ int rc;
+ u32 tmp;
+
+ /* make sure port is not active */
+ rc = ahci_deinit_port(ap, &emsg);
+ if (rc)
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "%s (%d)\n", emsg, rc);
+
+ /* clear SError */
+ tmp = readl(port_mmio + PORT_SCR_ERR);
+ VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
+ writel(tmp, port_mmio + PORT_SCR_ERR);
+
+ /* clear port IRQ */
+ tmp = readl(port_mmio + PORT_IRQ_STAT);
+ VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
+ if (tmp)
+ writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+ writel(1 << port_no, mmio + HOST_IRQ_STAT);
+}
+
static void ahci_init_controller(struct ata_host *host)
{
struct pci_dev *pdev = to_pci_dev(host->dev);
void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
- int i, rc;
+ int i;
+ void __iomem *port_mmio;
u32 tmp;
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- void __iomem *port_mmio = ahci_port_base(ap);
- const char *emsg = NULL;
-
- if (ata_port_is_dummy(ap))
- continue;
-
- /* make sure port is not active */
- rc = ahci_deinit_port(ap, &emsg);
- if (rc)
- dev_printk(KERN_WARNING, &pdev->dev,
- "%s (%d)\n", emsg, rc);
+ if (host->ports[0]->flags & AHCI_FLAG_MV_PATA) {
+ port_mmio = __ahci_port_base(host, 4);
- /* clear SError */
- tmp = readl(port_mmio + PORT_SCR_ERR);
- VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
- writel(tmp, port_mmio + PORT_SCR_ERR);
+ writel(0, port_mmio + PORT_IRQ_MASK);
/* clear port IRQ */
tmp = readl(port_mmio + PORT_IRQ_STAT);
VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
if (tmp)
writel(tmp, port_mmio + PORT_IRQ_STAT);
+ }
- writel(1 << i, mmio + HOST_IRQ_STAT);
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ port_mmio = ahci_port_base(ap);
+ if (ata_port_is_dummy(ap))
+ continue;
+
+ ahci_port_init(pdev, ap, i, mmio, port_mmio);
}
tmp = readl(mmio + HOST_CTL);
@@ -1208,7 +1296,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
ata_port_abort(ap);
}
-static void ahci_host_intr(struct ata_port *ap)
+static void ahci_port_intr(struct ata_port *ap)
{
void __iomem *port_mmio = ap->ioaddr.cmd_addr;
struct ata_eh_info *ehi = &ap->eh_info;
@@ -1334,7 +1422,7 @@ static irqreturn_t ahci_interrupt(int irq, void *dev_instance)
ap = host->ports[i];
if (ap) {
- ahci_host_intr(ap);
+ ahci_port_intr(ap);
VPRINTK("port %u\n", i);
} else {
VPRINTK("port %u (no irq)\n", i);
@@ -1442,7 +1530,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
ahci_power_down(ap);
else {
ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc);
- ahci_init_port(ap);
+ ahci_start_port(ap);
}
return rc;
@@ -1451,7 +1539,7 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
static int ahci_port_resume(struct ata_port *ap)
{
ahci_power_up(ap);
- ahci_init_port(ap);
+ ahci_start_port(ap);
return 0;
}
@@ -1549,13 +1637,8 @@ static int ahci_port_start(struct ata_port *ap)
ap->private_data = pp;
- /* power up port */
- ahci_power_up(ap);
-
- /* initialize port */
- ahci_init_port(ap);
-
- return 0;
+ /* engage engines, captain */
+ return ahci_port_resume(ap);
}
static void ahci_port_stop(struct ata_port *ap)
@@ -1700,7 +1783,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
return rc;
- if (pci_enable_msi(pdev))
+ if ((pi.flags & AHCI_FLAG_NO_MSI) || pci_enable_msi(pdev))
pci_intx(pdev, 1);
hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
@@ -1721,14 +1804,18 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
host->private_data = hpriv;
for (i = 0; i < host->n_ports; i++) {
- if (hpriv->port_map & (1 << i)) {
- struct ata_port *ap = host->ports[i];
- void __iomem *port_mmio = ahci_port_base(ap);
+ struct ata_port *ap = host->ports[i];
+ void __iomem *port_mmio = ahci_port_base(ap);
+ /* standard SATA port setup */
+ if (hpriv->port_map & (1 << i)) {
ap->ioaddr.cmd_addr = port_mmio;
ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
- } else
- host->ports[i]->ops = &ata_dummy_port_ops;
+ }
+
+ /* disabled/not-implemented port */
+ else
+ ap->ops = &ata_dummy_port_ops;
}
/* initialize adapter */
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 7565f022bd6..430fcf4f9ef 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -50,7 +50,7 @@ static int generic_set_mode(struct ata_port *ap, struct ata_device **unused)
/* Bits 5 and 6 indicate if DMA is active on master/slave */
if (ap->ioaddr.bmdma_addr)
- dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+ dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
@@ -143,10 +143,10 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
u16 command;
static const struct ata_port_info info = {
.sht = &generic_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &generic_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 9c07b88631b..d9fa329fd15 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -200,6 +200,8 @@ static const struct pci_device_id piix_pci_tbl[] = {
/* ICH7/7-R (i945, i975) UDMA 100*/
{ 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_133 },
{ 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
+ /* ICH8 Mobile PATA Controller */
+ { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
/* NOTE: The following PCI ids must be kept in sync with the
* list in drivers/pci/quirks.c.
@@ -412,7 +414,7 @@ static const struct piix_map_db ich6m_map_db = {
*/
.map = {
/* PM PS SM SS MAP */
- { P0, P2, RV, RV }, /* 00b */
+ { P0, P2, NA, NA }, /* 00b */
{ IDE, IDE, P1, P3 }, /* 01b */
{ P0, P2, IDE, IDE }, /* 10b */
{ RV, RV, RV, RV },
@@ -495,7 +497,7 @@ static struct ata_port_info piix_port_info[] = {
.flags = PIIX_SATA_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -505,7 +507,7 @@ static struct ata_port_info piix_port_info[] = {
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -516,7 +518,7 @@ static struct ata_port_info piix_port_info[] = {
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -527,7 +529,7 @@ static struct ata_port_info piix_port_info[] = {
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -538,7 +540,7 @@ static struct ata_port_info piix_port_info[] = {
PIIX_FLAG_AHCI,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
@@ -685,8 +687,14 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
if (adev->class == ATA_DEV_ATA)
control |= 4; /* PPE enable */
+ /* PIO configuration clears DTE unconditionally. It will be
+ * programmed in set_dmamode which is guaranteed to be called
+ * after set_piomode if any DMA mode is available.
+ */
pci_read_config_word(dev, master_port, &master_data);
if (is_slave) {
+ /* clear TIME1|IE1|PPE1|DTE1 */
+ master_data &= 0xff0f;
/* Enable SITRE (seperate slave timing register) */
master_data |= 0x4000;
/* enable PPE1, IE1 and TIME1 as needed */
@@ -694,12 +702,14 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
pci_read_config_byte(dev, slave_port, &slave_data);
slave_data &= (ap->port_no ? 0x0f : 0xf0);
/* Load the timing nibble for this slave */
- slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1])
+ << (ap->port_no ? 4 : 0);
} else {
- /* Master keeps the bits in a different format */
- master_data &= 0xccf8;
+ /* clear ISP|RCT|TIME0|IE0|PPE0|DTE0 */
+ master_data &= 0xccf0;
/* Enable PPE, IE and TIME as appropriate */
master_data |= control;
+ /* load ISP and RCT */
master_data |=
(timings[pio][0] << 12) |
(timings[pio][1] << 8);
@@ -816,7 +826,7 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i
master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */
master_data |= control << 4;
pci_read_config_byte(dev, 0x44, &slave_data);
- slave_data &= (0x0F + 0xE1 * ap->port_no);
+ slave_data &= (ap->port_no ? 0x0f : 0xf0);
/* Load the matching timing */
slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->port_no ? 4 : 0);
pci_write_config_byte(dev, 0x44, slave_data);
@@ -828,8 +838,11 @@ static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, i
(timings[pio][0] << 12) |
(timings[pio][1] << 8);
}
- udma_enable &= ~(1 << devid);
- pci_write_config_word(dev, master_port, master_data);
+
+ if (ap->udma_mask) {
+ udma_enable &= ~(1 << devid);
+ pci_write_config_word(dev, master_port, master_data);
+ }
}
/* Don't scribble on 0x48 if the controller does not support UDMA */
if (ap->udma_mask)
@@ -915,20 +928,18 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
{
struct pci_dev *pdev = NULL;
u16 cfg;
- u8 rev;
int no_piix_dma = 0;
while((pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev)) != NULL)
{
/* Look for 450NX PXB. Check for problem configurations
A PCI quirk checks bit 6 already */
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
pci_read_config_word(pdev, 0x41, &cfg);
/* Only on the original revision: IDE DMA can hang */
- if (rev == 0x00)
+ if (pdev->revision == 0x00)
no_piix_dma = 1;
/* On all revisions below 5 PXB bus lock must be disabled for IDE */
- else if (cfg & (1<<14) && rev < 5)
+ else if (cfg & (1<<14) && pdev->revision < 5)
no_piix_dma = 2;
}
if (no_piix_dma)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 02236739b40..c059f78ad94 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -24,15 +24,13 @@
#include <acpi/acmacros.h>
#include <acpi/actypes.h>
-#define SATA_ROOT_PORT(x) (((x) >> 16) & 0xffff)
-#define SATA_PORT_NUMBER(x) ((x) & 0xffff) /* or NO_PORT_MULT */
#define NO_PORT_MULT 0xffff
-#define SATA_ADR_RSVD 0xffffffff
+#define SATA_ADR(root,pmp) (((root) << 16) | (pmp))
#define REGS_PER_GTF 7
-struct taskfile_array {
- u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
-};
+struct ata_acpi_gtf {
+ u8 tf[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */
+} __packed;
/*
* Helper - belongs in the PCI layer somewhere eventually
@@ -42,237 +40,173 @@ static int is_pci_dev(struct device *dev)
return (dev->bus == &pci_bus_type);
}
+static void ata_acpi_associate_sata_port(struct ata_port *ap)
+{
+ acpi_integer adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
+
+ ap->device->acpi_handle = acpi_get_child(ap->host->acpi_handle, adr);
+}
+
+static void ata_acpi_associate_ide_port(struct ata_port *ap)
+{
+ int max_devices, i;
+
+ ap->acpi_handle = acpi_get_child(ap->host->acpi_handle, ap->port_no);
+ if (!ap->acpi_handle)
+ return;
+
+ max_devices = 1;
+ if (ap->flags & ATA_FLAG_SLAVE_POSS)
+ max_devices++;
+
+ for (i = 0; i < max_devices; i++) {
+ struct ata_device *dev = &ap->device[i];
+
+ dev->acpi_handle = acpi_get_child(ap->acpi_handle, i);
+ }
+}
+
/**
- * sata_get_dev_handle - finds acpi_handle and PCI device.function
- * @dev: device to locate
- * @handle: returned acpi_handle for @dev
- * @pcidevfn: return PCI device.func for @dev
+ * ata_acpi_associate - associate ATA host with ACPI objects
+ * @host: target ATA host
+ *
+ * Look up ACPI objects associated with @host and initialize
+ * acpi_handle fields of @host, its ports and devices accordingly.
*
- * This function is somewhat SATA-specific. Or at least the
- * PATA & SATA versions of this function are different,
- * so it's not entirely generic code.
+ * LOCKING:
+ * EH context.
*
- * Returns 0 on success, <0 on error.
+ * RETURNS:
+ * 0 on success, -errno on failure.
*/
-static int sata_get_dev_handle(struct device *dev, acpi_handle *handle,
- acpi_integer *pcidevfn)
+void ata_acpi_associate(struct ata_host *host)
{
- struct pci_dev *pci_dev;
- acpi_integer addr;
-
- if (!is_pci_dev(dev))
- return -ENODEV;
-
- pci_dev = to_pci_dev(dev); /* NOTE: PCI-specific */
- /* Please refer to the ACPI spec for the syntax of _ADR. */
- addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
- *pcidevfn = addr;
- *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
- if (!*handle)
- return -ENODEV;
- return 0;
+ int i;
+
+ if (!is_pci_dev(host->dev) || libata_noacpi)
+ return;
+
+ host->acpi_handle = DEVICE_ACPI_HANDLE(host->dev);
+ if (!host->acpi_handle)
+ return;
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ if (host->ports[0]->flags & ATA_FLAG_ACPI_SATA)
+ ata_acpi_associate_sata_port(ap);
+ else
+ ata_acpi_associate_ide_port(ap);
+ }
}
/**
- * pata_get_dev_handle - finds acpi_handle and PCI device.function
- * @dev: device to locate
- * @handle: returned acpi_handle for @dev
- * @pcidevfn: return PCI device.func for @dev
+ * ata_acpi_gtm - execute _GTM
+ * @ap: target ATA port
+ * @gtm: out parameter for _GTM result
+ *
+ * Evaluate _GTM and store the result in @gtm.
*
- * The PATA and SATA versions of this function are different.
+ * LOCKING:
+ * EH context.
*
- * Returns 0 on success, <0 on error.
+ * RETURNS:
+ * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
*/
-static int pata_get_dev_handle(struct device *dev, acpi_handle *handle,
- acpi_integer *pcidevfn)
+static int ata_acpi_gtm(const struct ata_port *ap, struct ata_acpi_gtm *gtm)
{
- unsigned int bus, devnum, func;
- acpi_integer addr;
- acpi_handle dev_handle, parent_handle;
- struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER,
- .pointer = NULL};
+ struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
+ union acpi_object *out_obj;
acpi_status status;
- struct acpi_device_info *dinfo = NULL;
- int ret = -ENODEV;
- struct pci_dev *pdev;
-
- if (!is_pci_dev(dev))
- return -ENODEV;
-
- pdev = to_pci_dev(dev);
-
- bus = pdev->bus->number;
- devnum = PCI_SLOT(pdev->devfn);
- func = PCI_FUNC(pdev->devfn);
-
- dev_handle = DEVICE_ACPI_HANDLE(dev);
- parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
-
- status = acpi_get_object_info(parent_handle, &buffer);
- if (ACPI_FAILURE(status))
- goto err;
-
- dinfo = buffer.pointer;
- if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
- dinfo->address == bus) {
- /* ACPI spec for _ADR for PCI bus: */
- addr = (acpi_integer)(devnum << 16 | func);
- *pcidevfn = addr;
- *handle = dev_handle;
- } else {
- goto err;
+ int rc = 0;
+
+ status = acpi_evaluate_object(ap->acpi_handle, "_GTM", NULL, &output);
+
+ rc = -ENOENT;
+ if (status == AE_NOT_FOUND)
+ goto out_free;
+
+ rc = -EINVAL;
+ if (ACPI_FAILURE(status)) {
+ ata_port_printk(ap, KERN_ERR,
+ "ACPI get timing mode failed (AE 0x%x)\n",
+ status);
+ goto out_free;
}
- if (!*handle)
- goto err;
- ret = 0;
-err:
- kfree(dinfo);
- return ret;
-}
+ out_obj = output.pointer;
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
+ ata_port_printk(ap, KERN_WARNING,
+ "_GTM returned unexpected object type 0x%x\n",
+ out_obj->type);
-struct walk_info { /* can be trimmed some */
- struct device *dev;
- struct acpi_device *adev;
- acpi_handle handle;
- acpi_integer pcidevfn;
- unsigned int drivenum;
- acpi_handle obj_handle;
- struct ata_port *ataport;
- struct ata_device *atadev;
- u32 sata_adr;
- int status;
- char basepath[ACPI_PATHNAME_MAX];
- int basepath_len;
-};
-
-static acpi_status get_devices(acpi_handle handle,
- u32 level, void *context, void **return_value)
-{
- acpi_status status;
- struct walk_info *winfo = context;
- struct acpi_buffer namebuf = {ACPI_ALLOCATE_BUFFER, NULL};
- char *pathname;
- struct acpi_buffer buffer;
- struct acpi_device_info *dinfo;
-
- status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &namebuf);
- if (status)
- goto ret;
- pathname = namebuf.pointer;
-
- buffer.length = ACPI_ALLOCATE_BUFFER;
- buffer.pointer = NULL;
- status = acpi_get_object_info(handle, &buffer);
- if (ACPI_FAILURE(status))
- goto out2;
-
- dinfo = buffer.pointer;
-
- /* find full device path name for pcidevfn */
- if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
- dinfo->address == winfo->pcidevfn) {
- if (ata_msg_probe(winfo->ataport))
- ata_dev_printk(winfo->atadev, KERN_DEBUG,
- ":%s: matches pcidevfn (0x%llx)\n",
- pathname, winfo->pcidevfn);
- strlcpy(winfo->basepath, pathname,
- sizeof(winfo->basepath));
- winfo->basepath_len = strlen(pathname);
- goto out;
+ goto out_free;
}
- /* if basepath is not yet known, ignore this object */
- if (!winfo->basepath_len)
- goto out;
-
- /* if this object is in scope of basepath, maybe use it */
- if (strncmp(pathname, winfo->basepath,
- winfo->basepath_len) == 0) {
- if (!(dinfo->valid & ACPI_VALID_ADR))
- goto out;
- if (ata_msg_probe(winfo->ataport))
- ata_dev_printk(winfo->atadev, KERN_DEBUG,
- "GOT ONE: (%s) root_port = 0x%llx,"
- " port_num = 0x%llx\n", pathname,
- SATA_ROOT_PORT(dinfo->address),
- SATA_PORT_NUMBER(dinfo->address));
- /* heuristics: */
- if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
- if (ata_msg_probe(winfo->ataport))
- ata_dev_printk(winfo->atadev,
- KERN_DEBUG, "warning: don't"
- " know how to handle SATA port"
- " multiplier\n");
- if (SATA_ROOT_PORT(dinfo->address) ==
- winfo->ataport->port_no &&
- SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
- if (ata_msg_probe(winfo->ataport))
- ata_dev_printk(winfo->atadev,
- KERN_DEBUG,
- "THIS ^^^^^ is the requested"
- " SATA drive (handle = 0x%p)\n",
- handle);
- winfo->sata_adr = dinfo->address;
- winfo->obj_handle = handle;
- }
+ if (out_obj->buffer.length != sizeof(struct ata_acpi_gtm)) {
+ ata_port_printk(ap, KERN_ERR,
+ "_GTM returned invalid length %d\n",
+ out_obj->buffer.length);
+ goto out_free;
}
-out:
- kfree(dinfo);
-out2:
- kfree(pathname);
-ret:
- return status;
+ memcpy(gtm, out_obj->buffer.pointer, sizeof(struct ata_acpi_gtm));
+ rc = 0;
+ out_free:
+ kfree(output.pointer);
+ return rc;
}
-/* Get the SATA drive _ADR object. */
-static int get_sata_adr(struct device *dev, acpi_handle handle,
- acpi_integer pcidevfn, unsigned int drive,
- struct ata_port *ap,
- struct ata_device *atadev, u32 *dev_adr)
+/**
+ * ata_acpi_stm - execute _STM
+ * @ap: target ATA port
+ * @stm: timing parameter to _STM
+ *
+ * Evaluate _STM with timing parameter @stm.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -ENOENT if _STM doesn't exist, -errno on failure.
+ */
+static int ata_acpi_stm(const struct ata_port *ap, struct ata_acpi_gtm *stm)
{
- acpi_status status;
- struct walk_info *winfo;
- int err = -ENOMEM;
-
- winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
- if (!winfo)
- goto out;
-
- winfo->dev = dev;
- winfo->atadev = atadev;
- winfo->ataport = ap;
- if (acpi_bus_get_device(handle, &winfo->adev) < 0)
- if (ata_msg_probe(ap))
- ata_dev_printk(winfo->atadev, KERN_DEBUG,
- "acpi_bus_get_device failed\n");
- winfo->handle = handle;
- winfo->pcidevfn = pcidevfn;
- winfo->drivenum = drive;
+ acpi_status status;
+ struct acpi_object_list input;
+ union acpi_object in_params[3];
- status = acpi_get_devices(NULL, get_devices, winfo, NULL);
+ in_params[0].type = ACPI_TYPE_BUFFER;
+ in_params[0].buffer.length = sizeof(struct ata_acpi_gtm);
+ in_params[0].buffer.pointer = (u8 *)stm;
+ /* Buffers for id may need byteswapping ? */
+ in_params[1].type = ACPI_TYPE_BUFFER;
+ in_params[1].buffer.length = 512;
+ in_params[1].buffer.pointer = (u8 *)ap->device[0].id;
+ in_params[2].type = ACPI_TYPE_BUFFER;
+ in_params[2].buffer.length = 512;
+ in_params[2].buffer.pointer = (u8 *)ap->device[1].id;
+
+ input.count = 3;
+ input.pointer = in_params;
+
+ status = acpi_evaluate_object(ap->acpi_handle, "_STM", &input, NULL);
+
+ if (status == AE_NOT_FOUND)
+ return -ENOENT;
if (ACPI_FAILURE(status)) {
- if (ata_msg_probe(ap))
- ata_dev_printk(winfo->atadev, KERN_DEBUG,
- "%s: acpi_get_devices failed\n",
- __FUNCTION__);
- err = -ENODEV;
- } else {
- *dev_adr = winfo->sata_adr;
- atadev->obj_handle = winfo->obj_handle;
- err = 0;
+ ata_port_printk(ap, KERN_ERR,
+ "ACPI set timing mode failed (status=0x%x)\n", status);
+ return -EINVAL;
}
- kfree(winfo);
-out:
- return err;
+ return 0;
}
/**
- * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * ata_dev_get_GTF - get the drive bootup default taskfile settings
* @dev: target ATA device
- * @gtf_length: number of bytes of _GTF data returned at @gtf_address
- * @gtf_address: buffer containing _GTF taskfile arrays
+ * @gtf: output parameter for buffer containing _GTF taskfile arrays
+ * @ptr_to_free: pointer which should be freed
*
* This applies to both PATA and SATA drives.
*
@@ -282,121 +216,41 @@ out:
* The <variable number> is not known in advance, so have ACPI-CA
* allocate the buffer as needed and return it, then free it later.
*
- * The returned @gtf_length and @gtf_address are only valid if the
- * function return value is 0.
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Number of taskfiles on success, 0 if _GTF doesn't exist or doesn't
+ * contain valid data. -errno on other errors.
*/
-static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
- unsigned long *gtf_address, unsigned long *obj_loc)
+static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf,
+ void **ptr_to_free)
{
struct ata_port *ap = dev->ap;
acpi_status status;
- acpi_handle dev_handle = NULL;
- acpi_handle chan_handle, drive_handle;
- acpi_integer pcidevfn = 0;
- u32 dev_adr;
struct acpi_buffer output;
union acpi_object *out_obj;
- struct device *gdev = ap->host->dev;
- int err = -ENODEV;
+ int rc = 0;
- *gtf_length = 0;
- *gtf_address = 0UL;
- *obj_loc = 0UL;
-
- if (libata_noacpi)
- return 0;
+ /* set up output buffer */
+ output.length = ACPI_ALLOCATE_BUFFER;
+ output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
__FUNCTION__, ap->port_no);
- if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED)) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: ERR: "
- "ata_dev_present: %d, PORT_DISABLED: %lu\n",
- __FUNCTION__, ata_dev_enabled(dev),
- ap->flags & ATA_FLAG_DISABLED);
- goto out;
- }
-
- /* Don't continue if device has no _ADR method.
- * _GTF is intended for known motherboard devices. */
- if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
- err = pata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
- if (err < 0) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: pata_get_dev_handle failed (%d)\n",
- __FUNCTION__, err);
- goto out;
- }
- } else {
- err = sata_get_dev_handle(gdev, &dev_handle, &pcidevfn);
- if (err < 0) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: sata_get_dev_handle failed (%d\n",
- __FUNCTION__, err);
- goto out;
- }
- }
-
- /* Get this drive's _ADR info. if not already known. */
- if (!dev->obj_handle) {
- if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
- /* get child objects of dev_handle == channel objects,
- * + _their_ children == drive objects */
- /* channel is ap->port_no */
- chan_handle = acpi_get_child(dev_handle,
- ap->port_no);
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: chan adr=%d: chan_handle=0x%p\n",
- __FUNCTION__, ap->port_no,
- chan_handle);
- if (!chan_handle) {
- err = -ENODEV;
- goto out;
- }
- /* TBD: could also check ACPI object VALID bits */
- drive_handle = acpi_get_child(chan_handle, dev->devno);
- if (!drive_handle) {
- err = -ENODEV;
- goto out;
- }
- dev_adr = dev->devno;
- dev->obj_handle = drive_handle;
- } else { /* for SATA mode */
- dev_adr = SATA_ADR_RSVD;
- err = get_sata_adr(gdev, dev_handle, pcidevfn, 0,
- ap, dev, &dev_adr);
- }
- if (err < 0 || dev_adr == SATA_ADR_RSVD ||
- !dev->obj_handle) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: get_sata/pata_adr failed: "
- "err=%d, dev_adr=%u, obj_handle=0x%p\n",
- __FUNCTION__, err, dev_adr,
- dev->obj_handle);
- goto out;
- }
- }
-
- /* Setting up output buffer */
- output.length = ACPI_ALLOCATE_BUFFER;
- output.pointer = NULL; /* ACPI-CA sets this; save/free it later */
-
/* _GTF has no input parameters */
- err = -EIO;
- status = acpi_evaluate_object(dev->obj_handle, "_GTF",
- NULL, &output);
+ status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
+
if (ACPI_FAILURE(status)) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: Run _GTF error: status = 0x%x\n",
- __FUNCTION__, status);
- goto out;
+ if (status != AE_NOT_FOUND) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "_GTF evaluation failed (AE 0x%x)\n",
+ status);
+ rc = -EIO;
+ }
+ goto out_free;
}
if (!output.length || !output.pointer) {
@@ -406,43 +260,39 @@ static int do_drive_get_GTF(struct ata_device *dev, unsigned int *gtf_length,
__FUNCTION__,
(unsigned long long)output.length,
output.pointer);
- kfree(output.pointer);
- goto out;
+ goto out_free;
}
out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
- kfree(output.pointer);
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
- "error: expected object type of "
- " ACPI_TYPE_BUFFER, got 0x%x\n",
- __FUNCTION__, out_obj->type);
- err = -ENOENT;
- goto out;
+ ata_dev_printk(dev, KERN_WARNING,
+ "_GTF unexpected object type 0x%x\n",
+ out_obj->type);
+ rc = -EINVAL;
+ goto out_free;
}
- if (!out_obj->buffer.length || !out_obj->buffer.pointer ||
- out_obj->buffer.length % REGS_PER_GTF) {
- if (ata_msg_drv(ap))
- ata_dev_printk(dev, KERN_ERR,
- "%s: unexpected GTF length (%d) or addr (0x%p)\n",
- __FUNCTION__, out_obj->buffer.length,
- out_obj->buffer.pointer);
- err = -ENOENT;
- goto out;
+ if (out_obj->buffer.length % REGS_PER_GTF) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "unexpected _GTF length (%d)\n",
+ out_obj->buffer.length);
+ rc = -EINVAL;
+ goto out_free;
}
- *gtf_length = out_obj->buffer.length;
- *gtf_address = (unsigned long)out_obj->buffer.pointer;
- *obj_loc = (unsigned long)out_obj;
+ *ptr_to_free = out_obj;
+ *gtf = (void *)out_obj->buffer.pointer;
+ rc = out_obj->buffer.length / REGS_PER_GTF;
+
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: returning "
- "gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n",
- __FUNCTION__, *gtf_length, *gtf_address, *obj_loc);
- err = 0;
-out:
- return err;
+ "gtf=%p, gtf_count=%d, ptr_to_free=%p\n",
+ __FUNCTION__, *gtf, rc, *ptr_to_free);
+ return rc;
+
+ out_free:
+ kfree(output.pointer);
+ return rc;
}
/**
@@ -461,154 +311,99 @@ out:
* function also waits for idle after writing control and before
* writing the remaining registers.
*
- * LOCKING: TBD:
- * Inherited from caller.
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
*/
-static void taskfile_load_raw(struct ata_device *dev,
- const struct taskfile_array *gtf)
+static int taskfile_load_raw(struct ata_device *dev,
+ const struct ata_acpi_gtf *gtf)
{
struct ata_port *ap = dev->ap;
- struct ata_taskfile tf;
- unsigned int err;
+ struct ata_taskfile tf, rtf;
+ unsigned int err_mask;
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: (0x1f1-1f7): hex: "
- "%02x %02x %02x %02x %02x %02x %02x\n",
- __FUNCTION__,
- gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
- gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
-
- if ((gtf->tfa[0] == 0) && (gtf->tfa[1] == 0) && (gtf->tfa[2] == 0)
- && (gtf->tfa[3] == 0) && (gtf->tfa[4] == 0) && (gtf->tfa[5] == 0)
- && (gtf->tfa[6] == 0))
- return;
+ if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0)
+ && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0)
+ && (gtf->tf[6] == 0))
+ return 0;
ata_tf_init(dev, &tf);
/* convert gtf to tf */
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
tf.protocol = ATA_PROT_NODATA;
- tf.feature = gtf->tfa[0]; /* 0x1f1 */
- tf.nsect = gtf->tfa[1]; /* 0x1f2 */
- tf.lbal = gtf->tfa[2]; /* 0x1f3 */
- tf.lbam = gtf->tfa[3]; /* 0x1f4 */
- tf.lbah = gtf->tfa[4]; /* 0x1f5 */
- tf.device = gtf->tfa[5]; /* 0x1f6 */
- tf.command = gtf->tfa[6]; /* 0x1f7 */
-
- err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
- if (err && ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_ERR,
- "%s: ata_exec_internal failed: %u\n",
- __FUNCTION__, err);
-}
-
-/**
- * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
- * @dev: target ATA device
- * @gtf_length: total number of bytes of _GTF taskfiles
- * @gtf_address: location of _GTF taskfile arrays
- *
- * This applies to both PATA and SATA drives.
- *
- * Write {gtf_address, length gtf_length} in groups of
- * REGS_PER_GTF bytes.
- */
-static int do_drive_set_taskfiles(struct ata_device *dev,
- unsigned int gtf_length,
- unsigned long gtf_address)
-{
- struct ata_port *ap = dev->ap;
- int err = -ENODEV;
- int gtf_count = gtf_length / REGS_PER_GTF;
- int ix;
- struct taskfile_array *gtf;
+ tf.feature = gtf->tf[0]; /* 0x1f1 */
+ tf.nsect = gtf->tf[1]; /* 0x1f2 */
+ tf.lbal = gtf->tf[2]; /* 0x1f3 */
+ tf.lbam = gtf->tf[3]; /* 0x1f4 */
+ tf.lbah = gtf->tf[4]; /* 0x1f5 */
+ tf.device = gtf->tf[5]; /* 0x1f6 */
+ tf.command = gtf->tf[6]; /* 0x1f7 */
if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
- __FUNCTION__, ap->port_no);
-
- if (libata_noacpi || !(ap->flags & ATA_FLAG_ACPI_SATA))
- return 0;
-
- if (!ata_dev_enabled(dev) || (ap->flags & ATA_FLAG_DISABLED))
- goto out;
- if (!gtf_count) /* shouldn't be here */
- goto out;
-
- if (gtf_length % REGS_PER_GTF) {
- if (ata_msg_drv(ap))
- ata_dev_printk(dev, KERN_ERR,
- "%s: unexpected GTF length (%d)\n",
- __FUNCTION__, gtf_length);
- goto out;
- }
-
- for (ix = 0; ix < gtf_count; ix++) {
- gtf = (struct taskfile_array *)
- (gtf_address + ix * REGS_PER_GTF);
-
- /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
- taskfile_load_raw(dev, gtf);
+ ata_dev_printk(dev, KERN_DEBUG, "executing ACPI cmd "
+ "%02x/%02x:%02x:%02x:%02x:%02x:%02x\n",
+ tf.command, tf.feature, tf.nsect,
+ tf.lbal, tf.lbam, tf.lbah, tf.device);
+
+ rtf = tf;
+ err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0);
+ if (err_mask) {
+ ata_dev_printk(dev, KERN_ERR,
+ "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed "
+ "(Emask=0x%x Stat=0x%02x Err=0x%02x)\n",
+ tf.command, tf.feature, tf.nsect, tf.lbal, tf.lbam,
+ tf.lbah, tf.device, err_mask, rtf.command, rtf.feature);
+ return -EIO;
}
- err = 0;
-out:
- return err;
+ return 0;
}
/**
* ata_acpi_exec_tfs - get then write drive taskfile settings
- * @ap: the ata_port for the drive
+ * @dev: target ATA device
*
- * This applies to both PATA and SATA drives.
+ * Evaluate _GTF and excute returned taskfiles.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Number of executed taskfiles on success, 0 if _GTF doesn't exist or
+ * doesn't contain valid data. -errno on other errors.
*/
-int ata_acpi_exec_tfs(struct ata_port *ap)
+static int ata_acpi_exec_tfs(struct ata_device *dev)
{
- int ix;
- int ret = 0;
- unsigned int gtf_length;
- unsigned long gtf_address;
- unsigned long obj_loc;
-
- if (libata_noacpi)
- return 0;
- /*
- * TBD - implement PATA support. For now,
- * we should not run GTF on PATA devices since some
- * PATA require execution of GTM/STM before GTF.
- */
- if (!(ap->flags & ATA_FLAG_ACPI_SATA))
- return 0;
-
- for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
- struct ata_device *dev = &ap->device[ix];
-
- if (!ata_dev_enabled(dev))
- continue;
-
- ret = do_drive_get_GTF(dev, &gtf_length, &gtf_address,
- &obj_loc);
- if (ret < 0) {
- if (ata_msg_probe(ap))
- ata_port_printk(ap, KERN_DEBUG,
- "%s: get_GTF error (%d)\n",
- __FUNCTION__, ret);
- break;
- }
-
- ret = do_drive_set_taskfiles(dev, gtf_length, gtf_address);
- kfree((void *)obj_loc);
- if (ret < 0) {
- if (ata_msg_probe(ap))
- ata_port_printk(ap, KERN_DEBUG,
- "%s: set_taskfiles error (%d)\n",
- __FUNCTION__, ret);
- break;
- }
+ struct ata_acpi_gtf *gtf = NULL;
+ void *ptr_to_free = NULL;
+ int gtf_count, i, rc;
+
+ /* get taskfiles */
+ rc = ata_dev_get_GTF(dev, &gtf, &ptr_to_free);
+ if (rc < 0)
+ return rc;
+ gtf_count = rc;
+
+ /* execute them */
+ for (i = 0, rc = 0; i < gtf_count; i++) {
+ int tmp;
+
+ /* ACPI errors are eventually ignored. Run till the
+ * end even after errors.
+ */
+ tmp = taskfile_load_raw(dev, gtf++);
+ if (!rc)
+ rc = tmp;
}
- return ret;
+ kfree(ptr_to_free);
+
+ if (rc == 0)
+ return gtf_count;
+ return rc;
}
/**
@@ -620,62 +415,25 @@ int ata_acpi_exec_tfs(struct ata_port *ap)
* ATM this function never returns a failure. It is an optional
* method and if it fails for whatever reason, we should still
* just keep going.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
*/
-int ata_acpi_push_id(struct ata_device *dev)
+static int ata_acpi_push_id(struct ata_device *dev)
{
struct ata_port *ap = dev->ap;
- acpi_handle handle;
- acpi_integer pcidevfn;
int err;
- struct device *gdev = ap->host->dev;
- u32 dev_adr;
acpi_status status;
struct acpi_object_list input;
union acpi_object in_params[1];
- if (libata_noacpi)
- return 0;
-
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
__FUNCTION__, dev->devno, ap->port_no);
- /* Don't continue if not a SATA device. */
- if (!(ap->flags & ATA_FLAG_ACPI_SATA)) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: Not a SATA device\n", __FUNCTION__);
- goto out;
- }
-
- /* Don't continue if device has no _ADR method.
- * _SDD is intended for known motherboard devices. */
- err = sata_get_dev_handle(gdev, &handle, &pcidevfn);
- if (err < 0) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: sata_get_dev_handle failed (%d\n",
- __FUNCTION__, err);
- goto out;
- }
-
- /* Get this drive's _ADR info, if not already known */
- if (!dev->obj_handle) {
- dev_adr = SATA_ADR_RSVD;
- err = get_sata_adr(gdev, handle, pcidevfn, dev->devno, ap, dev,
- &dev_adr);
- if (err < 0 || dev_adr == SATA_ADR_RSVD ||
- !dev->obj_handle) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s: get_sata_adr failed: "
- "err=%d, dev_adr=%u, obj_handle=0x%p\n",
- __FUNCTION__, err, dev_adr,
- dev->obj_handle);
- goto out;
- }
- }
-
/* Give the drive Identify data to the drive via the _SDD method */
/* _SDD: set up input parameters */
input.count = 1;
@@ -687,20 +445,150 @@ int ata_acpi_push_id(struct ata_device *dev)
/* It's OK for _SDD to be missing too. */
swap_buf_le16(dev->id, ATA_ID_WORDS);
- status = acpi_evaluate_object(dev->obj_handle, "_SDD", &input, NULL);
+ status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL);
swap_buf_le16(dev->id, ATA_ID_WORDS);
err = ACPI_FAILURE(status) ? -EIO : 0;
- if (err < 0) {
- if (ata_msg_probe(ap))
- ata_dev_printk(dev, KERN_DEBUG,
- "%s _SDD error: status = 0x%x\n",
- __FUNCTION__, status);
+ if (err < 0)
+ ata_dev_printk(dev, KERN_WARNING,
+ "ACPI _SDD failed (AE 0x%x)\n", status);
+
+ return err;
+}
+
+/**
+ * ata_acpi_on_suspend - ATA ACPI hook called on suspend
+ * @ap: target ATA port
+ *
+ * This function is called when @ap is about to be suspended. All
+ * devices are already put to sleep but the port_suspend() callback
+ * hasn't been executed yet. Error return from this function aborts
+ * suspend.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int ata_acpi_on_suspend(struct ata_port *ap)
+{
+ unsigned long flags;
+ int rc;
+
+ /* proceed iff per-port acpi_handle is valid */
+ if (!ap->acpi_handle)
+ return 0;
+ BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
+
+ /* store timing parameters */
+ rc = ata_acpi_gtm(ap, &ap->acpi_gtm);
+
+ spin_lock_irqsave(ap->lock, flags);
+ if (rc == 0)
+ ap->pflags |= ATA_PFLAG_GTM_VALID;
+ else
+ ap->pflags &= ~ATA_PFLAG_GTM_VALID;
+ spin_unlock_irqrestore(ap->lock, flags);
+
+ if (rc == -ENOENT)
+ rc = 0;
+ return rc;
+}
+
+/**
+ * ata_acpi_on_resume - ATA ACPI hook called on resume
+ * @ap: target ATA port
+ *
+ * This function is called when @ap is resumed - right after port
+ * itself is resumed but before any EH action is taken.
+ *
+ * LOCKING:
+ * EH context.
+ */
+void ata_acpi_on_resume(struct ata_port *ap)
+{
+ int i;
+
+ if (ap->acpi_handle && (ap->pflags & ATA_PFLAG_GTM_VALID)) {
+ BUG_ON(ap->flags & ATA_FLAG_ACPI_SATA);
+
+ /* restore timing parameters */
+ ata_acpi_stm(ap, &ap->acpi_gtm);
}
- /* always return success */
-out:
- return 0;
+ /* schedule _GTF */
+ for (i = 0; i < ATA_MAX_DEVICES; i++)
+ ap->device[i].flags |= ATA_DFLAG_ACPI_PENDING;
}
+/**
+ * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
+ * @dev: target ATA device
+ *
+ * This function is called when @dev is about to be configured.
+ * IDENTIFY data might have been modified after this hook is run.
+ *
+ * LOCKING:
+ * EH context.
+ *
+ * RETURNS:
+ * Positive number if IDENTIFY data needs to be refreshed, 0 if not,
+ * -errno on failure.
+ */
+int ata_acpi_on_devcfg(struct ata_device *dev)
+{
+ struct ata_port *ap = dev->ap;
+ struct ata_eh_context *ehc = &ap->eh_context;
+ int acpi_sata = ap->flags & ATA_FLAG_ACPI_SATA;
+ int rc;
+
+ if (!dev->acpi_handle)
+ return 0;
+
+ /* do we need to do _GTF? */
+ if (!(dev->flags & ATA_DFLAG_ACPI_PENDING) &&
+ !(acpi_sata && (ehc->i.flags & ATA_EHI_DID_HARDRESET)))
+ return 0;
+
+ /* do _SDD if SATA */
+ if (acpi_sata) {
+ rc = ata_acpi_push_id(dev);
+ if (rc)
+ goto acpi_err;
+ }
+
+ /* do _GTF */
+ rc = ata_acpi_exec_tfs(dev);
+ if (rc < 0)
+ goto acpi_err;
+
+ dev->flags &= ~ATA_DFLAG_ACPI_PENDING;
+
+ /* refresh IDENTIFY page if any _GTF command has been executed */
+ if (rc > 0) {
+ rc = ata_dev_reread_id(dev, 0);
+ if (rc < 0) {
+ ata_dev_printk(dev, KERN_ERR, "failed to IDENTIFY "
+ "after ACPI commands\n");
+ return rc;
+ }
+ }
+ return 0;
+
+ acpi_err:
+ /* let EH retry on the first failure, disable ACPI on the second */
+ if (dev->flags & ATA_DFLAG_ACPI_FAILED) {
+ ata_dev_printk(dev, KERN_WARNING, "ACPI on devcfg failed the "
+ "second time, disabling (errno=%d)\n", rc);
+
+ dev->acpi_handle = NULL;
+
+ /* if port is working, request IDENTIFY reload and continue */
+ if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ rc = 1;
+ }
+ dev->flags |= ATA_DFLAG_ACPI_FAILED;
+ return rc;
+}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 3ca9c610c11..88e2dd0983b 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -71,6 +71,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
u16 heads, u16 sectors);
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
static void ata_dev_xfermask(struct ata_device *dev);
+static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
unsigned int ata_print_id = 1;
static struct workqueue_struct *ata_wq;
@@ -600,8 +601,9 @@ static const char *sata_spd_string(unsigned int spd)
void ata_dev_disable(struct ata_device *dev)
{
- if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) {
- ata_dev_printk(dev, KERN_WARNING, "disabled\n");
+ if (ata_dev_enabled(dev)) {
+ if (ata_msg_drv(dev->ap))
+ ata_dev_printk(dev, KERN_WARNING, "disabled\n");
ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 |
ATA_DNXFER_QUIET);
dev->class++;
@@ -983,11 +985,6 @@ static u64 ata_hpa_resize(struct ata_device *dev)
else
hpa_sectors = ata_read_native_max_address(dev);
- /* if no hpa, both should be equal */
- ata_dev_printk(dev, KERN_INFO, "%s 1: sectors = %lld, "
- "hpa_sectors = %lld\n",
- __FUNCTION__, (long long)sectors, (long long)hpa_sectors);
-
if (hpa_sectors > sectors) {
ata_dev_printk(dev, KERN_INFO,
"Host Protected Area detected:\n"
@@ -1009,7 +1006,11 @@ static u64 ata_hpa_resize(struct ata_device *dev)
return hpa_sectors;
}
}
- }
+ } else if (hpa_sectors < sectors)
+ ata_dev_printk(dev, KERN_WARNING, "%s 1: hpa sectors (%lld) "
+ "is smaller than sectors (%lld)\n", __FUNCTION__,
+ (long long)hpa_sectors, (long long)sectors);
+
return sectors;
}
@@ -1283,18 +1284,11 @@ static unsigned int ata_id_xfermask(const u16 *id)
void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
unsigned long delay)
{
- int rc;
-
- if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
- return;
-
PREPARE_DELAYED_WORK(&ap->port_task, fn);
ap->port_task_data = data;
- rc = queue_delayed_work(ata_wq, &ap->port_task, delay);
-
- /* rc == 0 means that another user is using port task */
- WARN_ON(rc == 0);
+ /* may fail if ata_port_flush_task() in progress */
+ queue_delayed_work(ata_wq, &ap->port_task, delay);
}
/**
@@ -1309,32 +1303,9 @@ void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
*/
void ata_port_flush_task(struct ata_port *ap)
{
- unsigned long flags;
-
DPRINTK("ENTER\n");
- spin_lock_irqsave(ap->lock, flags);
- ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
- spin_unlock_irqrestore(ap->lock, flags);
-
- DPRINTK("flush #1\n");
- cancel_work_sync(&ap->port_task.work); /* akpm: seems unneeded */
-
- /*
- * At this point, if a task is running, it's guaranteed to see
- * the FLUSH flag; thus, it will never queue pio tasks again.
- * Cancel and flush.
- */
- if (!cancel_delayed_work(&ap->port_task)) {
- if (ata_msg_ctl(ap))
- ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
- __FUNCTION__);
- cancel_work_sync(&ap->port_task.work);
- }
-
- spin_lock_irqsave(ap->lock, flags);
- ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
- spin_unlock_irqrestore(ap->lock, flags);
+ cancel_rearming_delayed_work(&ap->port_task);
if (ata_msg_ctl(ap))
ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
@@ -1727,7 +1698,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
/* sanity check */
rc = -EINVAL;
- reason = "device reports illegal type";
+ reason = "device reports invalid type";
if (class == ATA_DEV_ATA) {
if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
@@ -1814,7 +1785,7 @@ static void ata_dev_config_ncq(struct ata_device *dev,
desc[0] = '\0';
return;
}
- if (ata_device_blacklisted(dev) & ATA_HORKAGE_NONCQ) {
+ if (dev->horkage & ATA_HORKAGE_NONCQ) {
snprintf(desc, desc_sz, "NCQ (not used)");
return;
}
@@ -1845,7 +1816,8 @@ static void ata_dev_config_ncq(struct ata_device *dev,
int ata_dev_configure(struct ata_device *dev)
{
struct ata_port *ap = dev->ap;
- int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO;
+ struct ata_eh_context *ehc = &ap->eh_context;
+ int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
const u16 *id = dev->id;
unsigned int xfer_mask;
char revbuf[7]; /* XYZ-99\0 */
@@ -1862,15 +1834,13 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
- /* set _SDD */
- rc = ata_acpi_push_id(dev);
- if (rc) {
- ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n",
- rc);
- }
+ /* set horkage */
+ dev->horkage |= ata_dev_blacklisted(dev);
- /* retrieve and execute the ATA task file of _GTF */
- ata_acpi_exec_tfs(ap);
+ /* let ACPI work its magic */
+ rc = ata_acpi_on_devcfg(dev);
+ if (rc)
+ return rc;
/* print device capabilities */
if (ata_msg_probe(ap))
@@ -1900,6 +1870,13 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_msg_probe(ap))
ata_dump_id(id);
+ /* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
+ ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
+ sizeof(fwrevbuf));
+
+ ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
+ sizeof(modelbuf));
+
/* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) {
if (ata_id_is_cfa(id)) {
@@ -1914,13 +1891,6 @@ int ata_dev_configure(struct ata_device *dev)
dev->n_sectors = ata_id_n_sectors(id);
- /* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
- ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
- sizeof(fwrevbuf));
-
- ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
- sizeof(modelbuf));
-
if (dev->id[59] & 0x100)
dev->multi_count = dev->id[59] & 0xff;
@@ -2009,7 +1979,9 @@ int ata_dev_configure(struct ata_device *dev)
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info)
- ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
+ ata_dev_printk(dev, KERN_INFO,
+ "ATAPI: %s, %s, max %s%s\n",
+ modelbuf, fwrevbuf,
ata_mode_string(xfer_mask),
cdb_intr_string);
}
@@ -2040,14 +2012,10 @@ int ata_dev_configure(struct ata_device *dev)
dev->max_sectors = ATA_MAX_SECTORS;
}
- if (ata_device_blacklisted(dev) & ATA_HORKAGE_MAX_SEC_128)
+ if (dev->horkage & ATA_HORKAGE_MAX_SEC_128)
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);
- /* limit ATAPI DMA to R/W commands only */
- if (ata_device_blacklisted(dev) & ATA_HORKAGE_DMA_RW_ONLY)
- dev->horkage |= ATA_HORKAGE_DMA_RW_ONLY;
-
if (ap->ops->dev_config)
ap->ops->dev_config(dev);
@@ -3059,22 +3027,28 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
}
}
- /* if device 1 was found in ata_devchk, wait for
- * register access, then wait for BSY to clear
+ /* if device 1 was found in ata_devchk, wait for register
+ * access briefly, then wait for BSY to clear.
*/
- while (dev1) {
- u8 nsect, lbal;
+ if (dev1) {
+ int i;
ap->ops->dev_select(ap, 1);
- nsect = ioread8(ioaddr->nsect_addr);
- lbal = ioread8(ioaddr->lbal_addr);
- if ((nsect == 1) && (lbal == 1))
- break;
- if (time_after(jiffies, deadline))
- return -EBUSY;
- msleep(50); /* give drive a breather */
- }
- if (dev1) {
+
+ /* Wait for register access. Some ATAPI devices fail
+ * to set nsect/lbal after reset, so don't waste too
+ * much time on it. We're gonna wait for !BSY anyway.
+ */
+ for (i = 0; i < 2; i++) {
+ u8 nsect, lbal;
+
+ nsect = ioread8(ioaddr->nsect_addr);
+ lbal = ioread8(ioaddr->lbal_addr);
+ if ((nsect == 1) && (lbal == 1))
+ break;
+ msleep(50); /* give drive a breather */
+ }
+
rc = ata_wait_ready(ap, deadline);
if (rc) {
if (rc != -ENODEV)
@@ -3190,9 +3164,6 @@ void ata_bus_reset(struct ata_port *ap)
if ((slave_possible) && (err != 0x81))
ap->device[1].class = ata_dev_try_classify(ap, 1, &err);
- /* re-enable interrupts */
- ap->ops->irq_on(ap);
-
/* is double-select really necessary? */
if (ap->device[1].class != ATA_DEV_NONE)
ap->ops->dev_select(ap, 1);
@@ -3355,7 +3326,7 @@ int ata_std_prereset(struct ata_port *ap, unsigned long deadline)
return 0;
/* if SATA, resume phy */
- if (ap->cbl == ATA_CBL_SATA) {
+ if (ap->flags & ATA_FLAG_SATA) {
rc = sata_phy_resume(ap, timing, deadline);
/* whine about phy resume failure but proceed */
if (rc && rc != -EOPNOTSUPP)
@@ -3577,10 +3548,6 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
sata_scr_write(ap, SCR_ERROR, serror);
- /* re-enable interrupts */
- if (!ap->ops->error_handler)
- ap->ops->irq_on(ap);
-
/* is double-select really necessary? */
if (classes[0] != ATA_DEV_NONE)
ap->ops->dev_select(ap, 1);
@@ -3651,7 +3618,7 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
/**
* ata_dev_reread_id - Re-read IDENTIFY data
- * @adev: target ATA device
+ * @dev: target ATA device
* @readid_flags: read ID flags
*
* Re-read IDENTIFY page and make sure @dev is still attached to
@@ -3769,10 +3736,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
+ { "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */
+ { "IOMEGA ZIP 250 ATAPI Floppy",
+ NULL, ATA_HORKAGE_NODMA },
/* Weird ATAPI devices */
- { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 |
- ATA_HORKAGE_DMA_RW_ONLY },
+ { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 },
/* Devices we expect to fail diagnostics */
@@ -3783,6 +3752,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ },
/* NCQ is broken */
{ "Maxtor 6L250S0", "BANC1G10", ATA_HORKAGE_NONCQ },
+ { "Maxtor 6B200M0", "BANC1BM0", ATA_HORKAGE_NONCQ },
+ { "Maxtor 6B200M0", "BANC1B10", ATA_HORKAGE_NONCQ },
+ { "HITACHI HDS7250SASUN500G 0621KTAWSD", "K2AOAJ0AHITACHI",
+ ATA_HORKAGE_NONCQ },
/* NCQ hard hangs device under heavier load, needs hard power cycle */
{ "Maxtor 6B250S0", "BANC1B70", ATA_HORKAGE_NONCQ },
/* Blacklist entries taken from Silicon Image 3124/3132
@@ -3790,6 +3763,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, },
+ /* Drives which do spurious command completion */
+ { "HTS541680J9SA00", "SB2IC7EP", ATA_HORKAGE_NONCQ, },
+ { "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, },
+ { "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, },
+ { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, },
+ { "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, },
/* Devices with NCQ limits */
@@ -3797,7 +3776,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ }
};
-unsigned long ata_device_blacklisted(const struct ata_device *dev)
+static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
{
unsigned char model_num[ATA_ID_PROD_LEN + 1];
unsigned char model_rev[ATA_ID_FW_REV_LEN + 1];
@@ -3827,7 +3806,7 @@ static int ata_dma_blacklisted(const struct ata_device *dev)
if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
(dev->flags & ATA_DFLAG_CDB_INTR))
return 1;
- return (ata_device_blacklisted(dev) & ATA_HORKAGE_NODMA) ? 1 : 0;
+ return (dev->horkage & ATA_HORKAGE_NODMA) ? 1 : 0;
}
/**
@@ -3932,10 +3911,13 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
/* set up set-features taskfile */
DPRINTK("set features - xfer mode\n");
+ /* Some controllers and ATAPI devices show flaky interrupt
+ * behavior after setting xfer mode. Use polling instead.
+ */
ata_tf_init(dev, &tf);
tf.command = ATA_CMD_SET_FEATURES;
tf.feature = SETFEATURES_XFER;
- tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+ tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_POLLING;
tf.protocol = ATA_PROT_NODATA;
tf.nsect = dev->xfer_mode;
@@ -4092,6 +4074,69 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
if (idx)
ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
}
+
+/**
+ * ata_fill_sg_dumb - Fill PCI IDE PRD table
+ * @qc: Metadata associated with taskfile to be transferred
+ *
+ * Fill PCI IDE PRD (scatter-gather) table with segments
+ * associated with the current disk command. Perform the fill
+ * so that we avoid writing any length 64K records for
+ * controllers that don't follow the spec.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ *
+ */
+static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ struct scatterlist *sg;
+ unsigned int idx;
+
+ WARN_ON(qc->__sg == NULL);
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+
+ idx = 0;
+ ata_for_each_sg(sg, qc) {
+ u32 addr, offset;
+ u32 sg_len, len, blen;
+
+ /* determine if physical DMA addr spans 64K boundary.
+ * Note h/w doesn't support 64-bit, so we unconditionally
+ * truncate dma_addr_t to u32.
+ */
+ addr = (u32) sg_dma_address(sg);
+ sg_len = sg_dma_len(sg);
+
+ while (sg_len) {
+ offset = addr & 0xffff;
+ len = sg_len;
+ if ((offset + sg_len) > 0x10000)
+ len = 0x10000 - offset;
+
+ blen = len & 0xffff;
+ ap->prd[idx].addr = cpu_to_le32(addr);
+ if (blen == 0) {
+ /* Some PATA chipsets like the CS5530 can't
+ cope with 0x0000 meaning 64K as the spec says */
+ ap->prd[idx].flags_len = cpu_to_le32(0x8000);
+ blen = 0x8000;
+ ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
+ }
+ ap->prd[idx].flags_len = cpu_to_le32(blen);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+
+ idx++;
+ sg_len -= len;
+ addr += len;
+ }
+ }
+
+ if (idx)
+ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+
/**
* ata_check_atapi_dma - Check whether ATAPI DMA can be supported
* @qc: Metadata associated with taskfile to check
@@ -4109,33 +4154,19 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
int ata_check_atapi_dma(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- int rc = 0; /* Assume ATAPI DMA is OK by default */
-
- /* some drives can only do ATAPI DMA on read/write */
- if (unlikely(qc->dev->horkage & ATA_HORKAGE_DMA_RW_ONLY)) {
- struct scsi_cmnd *cmd = qc->scsicmd;
- u8 *scsicmd = cmd->cmnd;
-
- switch (scsicmd[0]) {
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- case READ_6:
- case WRITE_6:
- /* atapi dma maybe ok */
- break;
- default:
- /* turn off atapi dma */
- return 1;
- }
- }
+
+ /* Don't allow DMA if it isn't multiple of 16 bytes. Quite a
+ * few ATAPI devices choke on such DMA requests.
+ */
+ if (unlikely(qc->nbytes & 15))
+ return 1;
if (ap->ops->check_atapi_dma)
- rc = ap->ops->check_atapi_dma(qc);
+ return ap->ops->check_atapi_dma(qc);
- return rc;
+ return 0;
}
+
/**
* ata_qc_prep - Prepare taskfile for submission
* @qc: Metadata associated with taskfile to be prepared
@@ -4153,6 +4184,23 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
ata_fill_sg(qc);
}
+/**
+ * ata_dumb_qc_prep - Prepare taskfile for submission
+ * @qc: Metadata associated with taskfile to be prepared
+ *
+ * Prepare ATA taskfile for submission.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host lock)
+ */
+void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
+{
+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+ return;
+
+ ata_fill_sg_dumb(qc);
+}
+
void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
/**
@@ -4782,8 +4830,6 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
} else
ata_qc_complete(qc);
}
-
- ata_altstatus(ap); /* flush */
}
/**
@@ -5413,14 +5459,6 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
}
}
- /* Some controllers show flaky interrupt behavior after
- * setting xfer mode. Use polling instead.
- */
- if (unlikely(qc->tf.command == ATA_CMD_SET_FEATURES &&
- qc->tf.feature == SETFEATURES_XFER) &&
- (ap->flags & ATA_FLAG_SETXFER_POLLING))
- qc->tf.flags |= ATA_TFLAG_POLLING;
-
/* select the device */
ata_dev_select(ap, qc->dev->devno, 1, 0);
@@ -5670,7 +5708,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance)
*/
int sata_scr_valid(struct ata_port *ap)
{
- return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
+ return (ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read;
}
/**
@@ -6303,6 +6341,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
if (rc)
return rc;
+ /* associate with ACPI nodes */
+ ata_acpi_associate(host);
+
/* set cable, sata_spd_limit and report */
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i];
@@ -6317,7 +6358,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
/* init sata_spd_limit to the current value */
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
int spd = (scontrol >> 4) & 0xf;
- ap->hw_sata_spd_limit &= (1 << spd) - 1;
+ if (spd)
+ ap->hw_sata_spd_limit &= (1 << spd) - 1;
}
ap->sata_spd_limit = ap->hw_sata_spd_limit;
@@ -6333,7 +6375,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
if (!ata_port_is_dummy(ap))
ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p "
"ctl 0x%p bmdma 0x%p irq %d\n",
- ap->cbl == ATA_CBL_SATA ? 'S' : 'P',
+ (ap->flags & ATA_FLAG_SATA) ? 'S' : 'P',
ata_mode_string(xfer_mask),
ap->ioaddr.cmd_addr,
ap->ioaddr.ctl_addr,
@@ -6432,6 +6474,9 @@ int ata_host_activate(struct ata_host *host, int irq,
if (rc)
return rc;
+ /* Used to print device info at probe */
+ host->irq = irq;
+
rc = ata_host_register(host, sht);
/* if failed, just free the IRQ and leave ports alone */
if (rc)
@@ -6485,13 +6530,7 @@ void ata_port_detach(struct ata_port *ap)
spin_unlock_irqrestore(ap->lock, flags);
ata_port_wait_eh(ap);
-
- /* Flush hotplug task. The sequence is similar to
- * ata_port_flush_task().
- */
- cancel_work_sync(&ap->hotplug_task.work); /* akpm: why? */
- cancel_delayed_work(&ap->hotplug_task);
- cancel_work_sync(&ap->hotplug_task.work);
+ cancel_rearming_delayed_work(&ap->hotplug_task);
skip_eh:
/* remove the associated SCSI host */
@@ -6822,11 +6861,13 @@ EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_altstatus);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
+EXPORT_SYMBOL_GPL(ata_sff_port_start);
EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_do_set_mode);
EXPORT_SYMBOL_GPL(ata_data_xfer);
EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
EXPORT_SYMBOL_GPL(ata_qc_prep);
+EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
EXPORT_SYMBOL_GPL(ata_bmdma_start);
@@ -6878,7 +6919,6 @@ EXPORT_SYMBOL_GPL(ata_host_resume);
EXPORT_SYMBOL_GPL(ata_id_string);
EXPORT_SYMBOL_GPL(ata_id_c_string);
EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
-EXPORT_SYMBOL_GPL(ata_device_blacklisted);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
@@ -6887,9 +6927,9 @@ EXPORT_SYMBOL_GPL(ata_timing_merge);
#ifdef CONFIG_PCI
EXPORT_SYMBOL_GPL(pci_test_config_bits);
-EXPORT_SYMBOL_GPL(ata_pci_init_native_host);
+EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
-EXPORT_SYMBOL_GPL(ata_pci_prepare_native_host);
+EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
EXPORT_SYMBOL_GPL(ata_pci_remove_one);
#ifdef CONFIG_PM
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index d8070989a39..9aa62a0754f 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -336,6 +336,7 @@ void ata_scsi_error(struct Scsi_Host *host)
}
ata_port_printk(ap, KERN_ERR, "EH pending after %d "
"tries, giving up\n", ATA_EH_MAX_REPEAT);
+ ap->pflags &= ~ATA_PFLAG_EH_PENDING;
}
/* this run is complete, make sure EH info is clear */
@@ -1616,7 +1617,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
unsigned long deadline;
unsigned int action;
ata_reset_fn_t reset;
- int i, did_followup_srst, rc;
+ int i, rc;
/* about to reset */
ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK);
@@ -1665,8 +1666,6 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
/* did prereset() screw up? if so, fix up to avoid oopsing */
if (!reset) {
- ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested "
- "invalid reset type\n");
if (softreset)
reset = softreset;
else
@@ -1689,11 +1688,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
rc = ata_do_reset(ap, reset, classes, deadline);
- did_followup_srst = 0;
if (reset == hardreset &&
ata_eh_followup_srst_needed(rc, classify, classes)) {
/* okay, let's do follow-up softreset */
- did_followup_srst = 1;
reset = softreset;
if (!reset) {
@@ -1900,6 +1897,57 @@ static int ata_eh_skip_recovery(struct ata_port *ap)
return 1;
}
+static void ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+{
+ struct ata_port *ap = dev->ap;
+ struct ata_eh_context *ehc = &ap->eh_context;
+
+ ehc->tries[dev->devno]--;
+
+ switch (err) {
+ case -ENODEV:
+ /* device missing or wrong IDENTIFY data, schedule probing */
+ ehc->i.probe_mask |= (1 << dev->devno);
+ case -EINVAL:
+ /* give it just one more chance */
+ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
+ case -EIO:
+ if (ehc->tries[dev->devno] == 1) {
+ /* This is the last chance, better to slow
+ * down than lose it.
+ */
+ sata_down_spd_limit(ap);
+ ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
+ }
+ }
+
+ if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
+ /* disable device if it has used up all its chances */
+ ata_dev_disable(dev);
+
+ /* detach if offline */
+ if (ata_port_offline(ap))
+ ata_eh_detach_dev(dev);
+
+ /* probe if requested */
+ if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+ !(ehc->did_probe_mask & (1 << dev->devno))) {
+ ata_eh_detach_dev(dev);
+ ata_dev_init(dev);
+
+ ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+ ehc->did_probe_mask |= (1 << dev->devno);
+ ehc->i.action |= ATA_EH_SOFTRESET;
+ }
+ } else {
+ /* soft didn't work? be haaaaard */
+ if (ehc->i.flags & ATA_EHI_DID_RESET)
+ ehc->i.action |= ATA_EH_HARDRESET;
+ else
+ ehc->i.action |= ATA_EH_SOFTRESET;
+ }
+}
+
/**
* ata_eh_recover - recover host port after error
* @ap: host port to recover
@@ -2000,50 +2048,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
goto out;
dev_fail:
- ehc->tries[dev->devno]--;
-
- switch (rc) {
- case -ENODEV:
- /* device missing or wrong IDENTIFY data, schedule probing */
- ehc->i.probe_mask |= (1 << dev->devno);
- case -EINVAL:
- /* give it just one more chance */
- ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
- case -EIO:
- if (ehc->tries[dev->devno] == 1) {
- /* This is the last chance, better to slow
- * down than lose it.
- */
- sata_down_spd_limit(ap);
- ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
- }
- }
-
- if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
- /* disable device if it has used up all its chances */
- ata_dev_disable(dev);
-
- /* detach if offline */
- if (ata_port_offline(ap))
- ata_eh_detach_dev(dev);
-
- /* probe if requested */
- if ((ehc->i.probe_mask & (1 << dev->devno)) &&
- !(ehc->did_probe_mask & (1 << dev->devno))) {
- ata_eh_detach_dev(dev);
- ata_dev_init(dev);
-
- ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
- ehc->did_probe_mask |= (1 << dev->devno);
- ehc->i.action |= ATA_EH_SOFTRESET;
- }
- } else {
- /* soft didn't work? be haaaaard */
- if (ehc->i.flags & ATA_EHI_DID_RESET)
- ehc->i.action |= ATA_EH_HARDRESET;
- else
- ehc->i.action |= ATA_EH_SOFTRESET;
- }
+ ata_eh_handle_dev_fail(dev, rc);
if (ata_port_nr_enabled(ap)) {
ata_port_printk(ap, KERN_WARNING, "failed to recover some "
@@ -2157,19 +2162,25 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
+ /* tell ACPI we're suspending */
+ rc = ata_acpi_on_suspend(ap);
+ if (rc)
+ goto out;
+
/* suspend */
ata_eh_freeze_port(ap);
if (ap->ops->port_suspend)
rc = ap->ops->port_suspend(ap, ap->pm_mesg);
+ out:
/* report result */
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~ATA_PFLAG_PM_PENDING;
if (rc == 0)
ap->pflags |= ATA_PFLAG_SUSPENDED;
- else
+ else if (ap->pflags & ATA_PFLAG_FROZEN)
ata_port_schedule_eh(ap);
if (ap->pm_result) {
@@ -2210,6 +2221,9 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
if (ap->ops->port_resume)
rc = ap->ops->port_resume(ap);
+ /* tell ACPI that we're resuming */
+ ata_acpi_on_resume(ap);
+
/* report result */
spin_lock_irqsave(ap->lock, flags);
ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b3900cfbd88..cfde22da07a 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1363,12 +1363,22 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
* cache
*/
- if (ap->ops->error_handler &&
- !need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
- ((qc->tf.feature == SETFEATURES_WC_ON) ||
- (qc->tf.feature == SETFEATURES_WC_OFF))) {
- ap->eh_info.action |= ATA_EH_REVALIDATE;
- ata_port_schedule_eh(ap);
+ if (ap->ops->error_handler && !need_sense) {
+ switch (qc->tf.command) {
+ case ATA_CMD_SET_FEATURES:
+ if ((qc->tf.feature == SETFEATURES_WC_ON) ||
+ (qc->tf.feature == SETFEATURES_WC_OFF)) {
+ ap->eh_info.action |= ATA_EH_REVALIDATE;
+ ata_port_schedule_eh(ap);
+ }
+ break;
+
+ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+ case ATA_CMD_SET_MULTI: /* multi_count changed */
+ ap->eh_info.action |= ATA_EH_REVALIDATE;
+ ata_port_schedule_eh(ap);
+ break;
+ }
}
/* For ATA pass thru (SAT) commands, generate a sense block if
@@ -2374,11 +2384,6 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
int using_pio = (dev->flags & ATA_DFLAG_PIO);
int nodata = (scmd->sc_data_direction == DMA_NONE);
- if (!using_pio)
- /* Check whether ATAPI DMA is safe */
- if (ata_check_atapi_dma(qc))
- using_pio = 1;
-
memset(qc->cdb, 0, dev->cdb_len);
memcpy(qc->cdb, scmd->cmnd, scmd->cmd_len);
@@ -2391,19 +2396,22 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
}
qc->tf.command = ATA_CMD_PACKET;
+ qc->nbytes = scmd->request_bufflen;
+
+ /* check whether ATAPI DMA is safe */
+ if (!using_pio && ata_check_atapi_dma(qc))
+ using_pio = 1;
- /* no data, or PIO data xfer */
if (using_pio || nodata) {
+ /* no data, or PIO data xfer */
if (nodata)
qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
else
qc->tf.protocol = ATA_PROT_ATAPI;
qc->tf.lbam = (8 * 1024) & 0xff;
qc->tf.lbah = (8 * 1024) >> 8;
- }
-
- /* DMA data xfer */
- else {
+ } else {
+ /* DMA data xfer */
qc->tf.protocol = ATA_PROT_ATAPI_DMA;
qc->tf.feature |= ATAPI_PKT_DMA;
@@ -2412,8 +2420,6 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
qc->tf.feature |= ATAPI_DMADIR;
}
- qc->nbytes = scmd->request_bufflen;
-
return 0;
}
@@ -2506,22 +2512,21 @@ ata_scsi_map_proto(u8 byte1)
return ATA_PROT_NODATA;
case 6: /* DMA */
+ case 10: /* UDMA Data-in */
+ case 11: /* UDMA Data-Out */
return ATA_PROT_DMA;
case 4: /* PIO Data-in */
case 5: /* PIO Data-out */
return ATA_PROT_PIO;
- case 10: /* Device Reset */
case 0: /* Hard Reset */
case 1: /* SRST */
- case 2: /* Bus Idle */
- case 7: /* Packet */
- case 8: /* DMA Queued */
- case 9: /* Device Diagnostic */
- case 11: /* UDMA Data-in */
- case 12: /* UDMA Data-Out */
- case 13: /* FPDMA */
+ case 8: /* Device Diagnostic */
+ case 9: /* Device Reset */
+ case 7: /* DMA Queued */
+ case 12: /* FPDMA */
+ case 15: /* Return Response Info */
default: /* Reserved */
break;
}
@@ -2552,10 +2557,6 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
goto invalid_fld;
- if (cdb[1] & 0xe0)
- /* PIO multi not supported yet */
- goto invalid_fld;
-
/*
* 12 and 16 byte CDBs use different offsets to
* provide the various register values.
@@ -2600,12 +2601,26 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->device = cdb[8];
tf->command = cdb[9];
}
- /*
- * If slave is possible, enforce correct master/slave bit
- */
- if (qc->ap->flags & ATA_FLAG_SLAVE_POSS)
- tf->device = qc->dev->devno ?
- tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
+
+ /* enforce correct master/slave bit */
+ tf->device = dev->devno ?
+ tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
+
+ /* sanity check for pio multi commands */
+ if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf))
+ goto invalid_fld;
+
+ if (is_multi_taskfile(tf)) {
+ unsigned int multi_count = 1 << (cdb[1] >> 5);
+
+ /* compare the passed through multi_count
+ * with the cached multi_count of libata
+ */
+ if (multi_count != dev->multi_count)
+ ata_dev_printk(dev, KERN_WARNING,
+ "invalid multi_count %u ignored\n",
+ multi_count);
+ }
/* READ/WRITE LONG use a non-standard sect_size */
qc->sect_size = ATA_SECT_SIZE;
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index e35d13466c6..ca7d2245d68 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -80,25 +80,25 @@ u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; }
u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
{
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
- u8 host_stat, post_stat, status;
+ u8 host_stat = 0, post_stat = 0, status;
status = ata_busy_wait(ap, bits, 1000);
if (status & bits)
if (ata_msg_err(ap))
printk(KERN_ERR "abnormal status 0x%X\n", status);
- /* get controller status; clear intr, err bits */
- host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
- iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
- ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
-
- post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ if (ap->ioaddr.bmdma_addr) {
+ /* get controller status; clear intr, err bits */
+ host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
+ ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ }
if (ata_msg_intr(ap))
printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
__FUNCTION__,
host_stat, post_stat, status);
-
return status;
}
@@ -516,6 +516,27 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
ata_bmdma_stop(qc);
}
+/**
+ * ata_sff_port_start - Set port up for dma.
+ * @ap: Port to initialize
+ *
+ * Called just after data structures for each port are
+ * initialized. Allocates space for PRD table if the device
+ * is DMA capable SFF.
+ *
+ * May be used as the port_start() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
+int ata_sff_port_start(struct ata_port *ap)
+{
+ if (ap->ioaddr.bmdma_addr)
+ return ata_port_start(ap);
+ return 0;
+}
+
#ifdef CONFIG_PCI
static int ata_resources_present(struct pci_dev *pdev, int port)
@@ -583,13 +604,17 @@ int ata_pci_init_bmdma(struct ata_host *host)
}
/**
- * ata_pci_init_native_host - acquire native ATA resources and init host
+ * ata_pci_init_sff_host - acquire native PCI ATA resources and init host
* @host: target ATA host
*
* Acquire native PCI ATA resources for @host and initialize the
* first two ports of @host accordingly. Ports marked dummy are
* skipped and allocation failure makes the port dummy.
*
+ * Note that native PCI resources are valid even for legacy hosts
+ * as we fix up pdev resources array early in boot, so this
+ * function can be used for both native and legacy SFF hosts.
+ *
* LOCKING:
* Inherited from calling layer (may sleep).
*
@@ -597,7 +622,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
* 0 if at least one port is initialized, -ENODEV if no port is
* available.
*/
-int ata_pci_init_native_host(struct ata_host *host)
+int ata_pci_init_sff_host(struct ata_host *host)
{
struct device *gdev = host->dev;
struct pci_dev *pdev = to_pci_dev(gdev);
@@ -652,7 +677,7 @@ int ata_pci_init_native_host(struct ata_host *host)
}
/**
- * ata_pci_prepare_native_host - helper to prepare native PCI ATA host
+ * ata_pci_prepare_sff_host - helper to prepare native PCI ATA host
* @pdev: target PCI device
* @ppi: array of port_info, must be enough for two ports
* @r_host: out argument for the initialized ATA host
@@ -666,9 +691,9 @@ int ata_pci_init_native_host(struct ata_host *host)
* RETURNS:
* 0 on success, -errno otherwise.
*/
-int ata_pci_prepare_native_host(struct pci_dev *pdev,
- const struct ata_port_info * const * ppi,
- struct ata_host **r_host)
+int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ const struct ata_port_info * const * ppi,
+ struct ata_host **r_host)
{
struct ata_host *host;
int rc;
@@ -684,7 +709,7 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev,
goto err_out;
}
- rc = ata_pci_init_native_host(host);
+ rc = ata_pci_init_sff_host(host);
if (rc)
goto err_out;
@@ -709,221 +734,6 @@ int ata_pci_prepare_native_host(struct pci_dev *pdev,
return rc;
}
-struct ata_legacy_devres {
- unsigned int mask;
- unsigned long cmd_port[2];
- void __iomem * cmd_addr[2];
- void __iomem * ctl_addr[2];
- unsigned int irq[2];
- void * irq_dev_id[2];
-};
-
-static void ata_legacy_free_irqs(struct ata_legacy_devres *legacy_dr)
-{
- int i;
-
- for (i = 0; i < 2; i++) {
- if (!legacy_dr->irq[i])
- continue;
-
- free_irq(legacy_dr->irq[i], legacy_dr->irq_dev_id[i]);
- legacy_dr->irq[i] = 0;
- legacy_dr->irq_dev_id[i] = NULL;
- }
-}
-
-static void ata_legacy_release(struct device *gdev, void *res)
-{
- struct ata_legacy_devres *this = res;
- int i;
-
- ata_legacy_free_irqs(this);
-
- for (i = 0; i < 2; i++) {
- if (this->cmd_addr[i])
- ioport_unmap(this->cmd_addr[i]);
- if (this->ctl_addr[i])
- ioport_unmap(this->ctl_addr[i]);
- if (this->cmd_port[i])
- release_region(this->cmd_port[i], 8);
- }
-}
-
-static int ata_init_legacy_port(struct ata_port *ap,
- struct ata_legacy_devres *legacy_dr)
-{
- struct ata_host *host = ap->host;
- int port_no = ap->port_no;
- unsigned long cmd_port, ctl_port;
-
- if (port_no == 0) {
- cmd_port = ATA_PRIMARY_CMD;
- ctl_port = ATA_PRIMARY_CTL;
- } else {
- cmd_port = ATA_SECONDARY_CMD;
- ctl_port = ATA_SECONDARY_CTL;
- }
-
- /* request cmd_port */
- if (request_region(cmd_port, 8, "libata"))
- legacy_dr->cmd_port[port_no] = cmd_port;
- else {
- dev_printk(KERN_WARNING, host->dev,
- "0x%0lX IDE port busy\n", cmd_port);
- return -EBUSY;
- }
-
- /* iomap cmd and ctl ports */
- legacy_dr->cmd_addr[port_no] = ioport_map(cmd_port, 8);
- legacy_dr->ctl_addr[port_no] = ioport_map(ctl_port, 1);
- if (!legacy_dr->cmd_addr[port_no] || !legacy_dr->ctl_addr[port_no]) {
- dev_printk(KERN_WARNING, host->dev,
- "failed to map cmd/ctl ports\n");
- return -ENOMEM;
- }
-
- /* init IO addresses */
- ap->ioaddr.cmd_addr = legacy_dr->cmd_addr[port_no];
- ap->ioaddr.altstatus_addr = legacy_dr->ctl_addr[port_no];
- ap->ioaddr.ctl_addr = legacy_dr->ctl_addr[port_no];
- ata_std_ports(&ap->ioaddr);
-
- return 0;
-}
-
-/**
- * ata_init_legacy_host - acquire legacy ATA resources and init ATA host
- * @host: target ATA host
- * @was_busy: out parameter, indicates whether any port was busy
- *
- * Acquire legacy ATA resources for the first two ports of @host
- * and initialize it accordingly. Ports marked dummy are skipped
- * and resource acquistion failure makes the port dummy.
- *
- * LOCKING:
- * Inherited from calling layer (may sleep).
- *
- * RETURNS:
- * 0 if at least one port is initialized, -ENODEV if no port is
- * available.
- */
-static int ata_init_legacy_host(struct ata_host *host, int *was_busy)
-{
- struct device *gdev = host->dev;
- struct ata_legacy_devres *legacy_dr;
- int i, rc;
-
- if (!devres_open_group(gdev, NULL, GFP_KERNEL))
- return -ENOMEM;
-
- rc = -ENOMEM;
- legacy_dr = devres_alloc(ata_legacy_release, sizeof(*legacy_dr),
- GFP_KERNEL);
- if (!legacy_dr)
- goto err_out;
- devres_add(gdev, legacy_dr);
-
- for (i = 0; i < 2; i++) {
- if (ata_port_is_dummy(host->ports[i]))
- continue;
-
- rc = ata_init_legacy_port(host->ports[i], legacy_dr);
- if (rc == 0)
- legacy_dr->mask |= 1 << i;
- else {
- if (rc == -EBUSY)
- (*was_busy)++;
- host->ports[i]->ops = &ata_dummy_port_ops;
- }
- }
-
- if (!legacy_dr->mask) {
- dev_printk(KERN_ERR, gdev, "no available legacy port\n");
- return -ENODEV;
- }
-
- devres_remove_group(gdev, NULL);
- return 0;
-
- err_out:
- devres_release_group(gdev, NULL);
- return rc;
-}
-
-/**
- * ata_request_legacy_irqs - request legacy ATA IRQs
- * @host: target ATA host
- * @handler: array of IRQ handlers
- * @irq_flags: array of IRQ flags
- * @dev_id: array of IRQ dev_ids
- *
- * Request legacy IRQs for non-dummy legacy ports in @host. All
- * IRQ parameters are passed as array to allow ports to have
- * separate IRQ handlers.
- *
- * LOCKING:
- * Inherited from calling layer (may sleep).
- *
- * RETURNS:
- * 0 on success, -errno otherwise.
- */
-static int ata_request_legacy_irqs(struct ata_host *host,
- irq_handler_t const *handler,
- const unsigned int *irq_flags,
- void * const *dev_id)
-{
- struct device *gdev = host->dev;
- struct ata_legacy_devres *legacy_dr;
- int i, rc;
-
- legacy_dr = devres_find(host->dev, ata_legacy_release, NULL, NULL);
- BUG_ON(!legacy_dr);
-
- for (i = 0; i < 2; i++) {
- unsigned int irq;
-
- /* FIXME: ATA_*_IRQ() should take generic device not pci_dev */
- if (i == 0)
- irq = ATA_PRIMARY_IRQ(to_pci_dev(gdev));
- else
- irq = ATA_SECONDARY_IRQ(to_pci_dev(gdev));
-
- if (!(legacy_dr->mask & (1 << i)))
- continue;
-
- if (!handler[i]) {
- dev_printk(KERN_ERR, gdev,
- "NULL handler specified for port %d\n", i);
- rc = -EINVAL;
- goto err_out;
- }
-
- rc = request_irq(irq, handler[i], irq_flags[i], DRV_NAME,
- dev_id[i]);
- if (rc) {
- dev_printk(KERN_ERR, gdev,
- "irq %u request failed (errno=%d)\n", irq, rc);
- goto err_out;
- }
-
- /* record irq allocation in legacy_dr */
- legacy_dr->irq[i] = irq;
- legacy_dr->irq_dev_id[i] = dev_id[i];
-
- /* only used to print info */
- if (i == 0)
- host->irq = irq;
- else
- host->irq2 = irq;
- }
-
- return 0;
-
- err_out:
- ata_legacy_free_irqs(legacy_dr);
- return rc;
-}
-
/**
* ata_pci_init_one - Initialize/register PCI IDE host controller
* @pdev: Controller to be initialized
@@ -1008,35 +818,11 @@ int ata_pci_init_one(struct pci_dev *pdev,
#endif
}
- /* alloc and init host */
- host = ata_host_alloc_pinfo(dev, ppi, 2);
- if (!host) {
- dev_printk(KERN_ERR, &pdev->dev,
- "failed to allocate ATA host\n");
- rc = -ENOMEM;
+ /* prepare host */
+ rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
+ if (rc)
goto err_out;
- }
- if (!legacy_mode) {
- rc = ata_pci_init_native_host(host);
- if (rc)
- goto err_out;
- } else {
- int was_busy = 0;
-
- rc = ata_init_legacy_host(host, &was_busy);
- if (was_busy)
- pcim_pin_device(pdev);
- if (rc)
- goto err_out;
-
- /* request respective PCI regions, may fail */
- rc = pci_request_region(pdev, 1, DRV_NAME);
- rc = pci_request_region(pdev, 3, DRV_NAME);
- }
-
- /* init BMDMA, may fail */
- ata_pci_init_bmdma(host);
pci_set_master(pdev);
/* start host and request IRQ */
@@ -1044,19 +830,31 @@ int ata_pci_init_one(struct pci_dev *pdev,
if (rc)
goto err_out;
- if (!legacy_mode)
+ if (!legacy_mode) {
rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
IRQF_SHARED, DRV_NAME, host);
- else {
- irq_handler_t handler[2] = { host->ops->irq_handler,
- host->ops->irq_handler };
- unsigned int irq_flags[2] = { IRQF_SHARED, IRQF_SHARED };
- void *dev_id[2] = { host, host };
+ if (rc)
+ goto err_out;
+ host->irq = pdev->irq;
+ } else {
+ if (!ata_port_is_dummy(host->ports[0])) {
+ host->irq = ATA_PRIMARY_IRQ(pdev);
+ rc = devm_request_irq(dev, host->irq,
+ pi->port_ops->irq_handler,
+ IRQF_SHARED, DRV_NAME, host);
+ if (rc)
+ goto err_out;
+ }
- rc = ata_request_legacy_irqs(host, handler, irq_flags, dev_id);
+ if (!ata_port_is_dummy(host->ports[1])) {
+ host->irq2 = ATA_SECONDARY_IRQ(pdev);
+ rc = devm_request_irq(dev, host->irq2,
+ pi->port_ops->irq_handler,
+ IRQF_SHARED, DRV_NAME, host);
+ if (rc)
+ goto err_out;
+ }
}
- if (rc)
- goto err_out;
/* register */
rc = ata_host_register(host, pi->sht);
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 5e246665842..ba17fc5f2e9 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -98,17 +98,15 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host);
/* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI
-extern int ata_acpi_exec_tfs(struct ata_port *ap);
-extern int ata_acpi_push_id(struct ata_device *dev);
+extern void ata_acpi_associate(struct ata_host *host);
+extern int ata_acpi_on_suspend(struct ata_port *ap);
+extern void ata_acpi_on_resume(struct ata_port *ap);
+extern int ata_acpi_on_devcfg(struct ata_device *adev);
#else
-static inline int ata_acpi_exec_tfs(struct ata_port *ap)
-{
- return 0;
-}
-static inline int ata_acpi_push_id(struct ata_device *dev)
-{
- return 0;
-}
+static inline void ata_acpi_associate(struct ata_host *host) { }
+static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
+static inline void ata_acpi_on_resume(struct ata_port *ap) { }
+static inline int ata_acpi_on_devcfg(struct ata_device *adev) { return 0; }
#endif
/* libata-scsi.c */
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index 3c55a5ff74c..010436795d2 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -455,23 +455,21 @@ static struct ata_port_operations ali_c5_port_ops = {
static void ali_init_chipset(struct pci_dev *pdev)
{
- u8 rev, tmp;
+ u8 tmp;
struct pci_dev *north, *isa_bridge;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
/*
* The chipset revision selects the driver operations and
* mode data.
*/
- if (rev >= 0x20 && rev < 0xC2) {
+ if (pdev->revision >= 0x20 && pdev->revision < 0xC2) {
/* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
pci_read_config_byte(pdev, 0x4B, &tmp);
/* Clear CD-ROM DMA write bit */
tmp &= 0x7F;
pci_write_config_byte(pdev, 0x4B, tmp);
- } else if (rev >= 0xC2) {
+ } else if (pdev->revision >= 0xC2) {
/* Enable cable detection logic */
pci_read_config_byte(pdev, 0x4B, &tmp);
pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
@@ -483,21 +481,21 @@ static void ali_init_chipset(struct pci_dev *pdev)
/* Configure the ALi bridge logic. For non ALi rely on BIOS.
Set the south bridge enable bit */
pci_read_config_byte(isa_bridge, 0x79, &tmp);
- if (rev == 0xC2)
+ if (pdev->revision == 0xC2)
pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
- else if (rev > 0xC2 && rev < 0xC5)
+ else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
}
- if (rev >= 0x20) {
+ if (pdev->revision >= 0x20) {
/*
* CD_ROM DMA on (0x53 bit 0). Enable this even if we want
* to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
* via 0x54/55.
*/
pci_read_config_byte(pdev, 0x53, &tmp);
- if (rev <= 0x20)
+ if (pdev->revision <= 0x20)
tmp &= ~0x02;
- if (rev >= 0xc7)
+ if (pdev->revision >= 0xc7)
tmp |= 0x03;
else
tmp |= 0x01; /* CD_ROM enable for DMA */
@@ -520,14 +518,14 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info_early = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &ali_early_port_ops
};
/* Revision 0x20 added DMA */
static const struct ata_port_info info_20 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &ali_20_port_ops
@@ -535,7 +533,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Revision 0x20 with support logic added UDMA */
static const struct ata_port_info info_20_udma = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07, /* UDMA33 */
@@ -544,60 +542,58 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Revision 0xC2 adds UDMA66 */
static const struct ata_port_info info_c2 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &ali_c2_port_ops
};
- /* Revision 0xC3 is UDMA100 */
+ /* Revision 0xC3 is UDMA66 for now */
static const struct ata_port_info info_c3 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &ali_c2_port_ops
};
- /* Revision 0xC4 is UDMA133 */
+ /* Revision 0xC4 is UDMA100 */
static const struct ata_port_info info_c4 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
+ .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &ali_c2_port_ops
};
/* Revision 0xC5 is UDMA133 with LBA48 DMA */
static const struct ata_port_info info_c5 = {
.sht = &ali_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &ali_c5_port_ops
};
const struct ata_port_info *ppi[] = { NULL, NULL };
- u8 rev, tmp;
+ u8 tmp;
struct pci_dev *isa_bridge;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
/*
* The chipset revision selects the driver operations and
* mode data.
*/
- if (rev < 0x20) {
+ if (pdev->revision < 0x20) {
ppi[0] = &info_early;
- } else if (rev < 0xC2) {
+ } else if (pdev->revision < 0xC2) {
ppi[0] = &info_20;
- } else if (rev == 0xC2) {
+ } else if (pdev->revision == 0xC2) {
ppi[0] = &info_c2;
- } else if (rev == 0xC3) {
+ } else if (pdev->revision == 0xC3) {
ppi[0] = &info_c3;
- } else if (rev == 0xC4) {
+ } else if (pdev->revision == 0xC4) {
ppi[0] = &info_c4;
} else
ppi[0] = &info_c5;
@@ -605,7 +601,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
ali_init_chipset(pdev);
isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
- if (isa_bridge && rev >= 0x20 && rev < 0xC2) {
+ if (isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
/* Are we paired with a UDMA capable chip */
pci_read_config_byte(isa_bridge, 0x5E, &tmp);
if ((tmp & 0x1E) == 0x12)
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index b439351f1fd..b09facad63e 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -541,7 +541,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info info[10] = {
{ /* 0: AMD 7401 */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07, /* No SWDMA */
.udma_mask = 0x07, /* UDMA 33 */
@@ -549,91 +549,89 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
},
{ /* 1: Early AMD7409 - no swdma */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f, /* UDMA 66 */
+ .udma_mask = ATA_UDMA4, /* UDMA 66 */
.port_ops = &amd66_port_ops
},
{ /* 2: AMD 7409, no swdma errata */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f, /* UDMA 66 */
+ .udma_mask = ATA_UDMA4, /* UDMA 66 */
.port_ops = &amd66_port_ops
},
{ /* 3: AMD 7411 */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA5, /* UDMA 100 */
.port_ops = &amd100_port_ops
},
{ /* 4: AMD 7441 */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA5, /* UDMA 100 */
.port_ops = &amd100_port_ops
},
{ /* 5: AMD 8111*/
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f, /* UDMA 133, no swdma */
+ .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */
.port_ops = &amd133_port_ops
},
{ /* 6: AMD 8111 UDMA 100 (Serenade) */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100, no swdma */
+ .udma_mask = ATA_UDMA5, /* UDMA 100, no swdma */
.port_ops = &amd133_port_ops
},
{ /* 7: Nvidia Nforce */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA5, /* UDMA 100 */
.port_ops = &nv100_port_ops
},
{ /* 8: Nvidia Nforce2 and later */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f, /* UDMA 133, no swdma */
+ .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */
.port_ops = &nv133_port_ops
},
{ /* 9: AMD CS5536 (Geode companion) */
.sht = &amd_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA5, /* UDMA 100 */
.port_ops = &amd100_port_ops
}
};
const struct ata_port_info *ppi[] = { NULL, NULL };
static int printed_version;
int type = id->driver_data;
- u8 rev;
u8 fifo;
if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
pci_read_config_byte(pdev, 0x41, &fifo);
/* Check for AMD7409 without swdma errata and if found adjust type */
- if (type == 1 && rev > 0x7)
+ if (type == 1 && pdev->revision > 0x7)
type = 2;
/* Check for AMD7411 */
@@ -693,6 +691,8 @@ static const struct pci_device_id amd[] = {
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 8 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 8 },
{ PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 8 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE), 8 },
+ { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE), 8 },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 9 },
{ },
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c
index 03b6ddd2abd..ce589d96ca4 100644
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -416,7 +416,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
static int printed_version;
static const struct ata_port_info info_6210 = {
.sht = &artop_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA2,
@@ -424,7 +424,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
};
static const struct ata_port_info info_626x = {
.sht = &artop_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA4,
@@ -432,7 +432,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
};
static const struct ata_port_info info_626x_fast = {
.sht = &artop_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = ATA_UDMA5,
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index 844914681a2..80509be49e7 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -270,7 +270,7 @@ static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &atiixp_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x06, /* No MWDMA0 support */
.udma_mask = 0x3F,
@@ -285,6 +285,7 @@ static const struct pci_device_id atiixp[] = {
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP300_IDE), },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), },
+ { PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), },
{ },
};
diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c
index 31cbf8daa29..0feb5ae8c48 100644
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -251,7 +251,7 @@ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &cmd640_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &cmd640_port_ops
};
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
index 320a5b10aa9..dc443e7dc37 100644
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -380,21 +380,21 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info cmd_info[6] = {
{ /* CMD 643 - no UDMA */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &cmd64x_port_ops
},
{ /* CMD 646 with broken UDMA */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &cmd64x_port_ops
},
{ /* CMD 646 with working UDMA */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA1,
@@ -402,14 +402,14 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
},
{ /* CMD 646 rev 1 */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &cmd646r1_port_ops
},
{ /* CMD 648 */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA2,
@@ -417,7 +417,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
},
{ /* CMD 649 */
.sht = &cmd64x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA3,
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
index 1aabe15ad9d..6bf037d82b5 100644
--- a/drivers/ata/pata_cs5520.c
+++ b/drivers/ata/pata_cs5520.c
@@ -146,7 +146,7 @@ static struct scsi_host_template cs5520_sht = {
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -178,7 +178,7 @@ static struct ata_port_operations cs5520_port_ops = {
.bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
+ .qc_prep = ata_dumb_qc_prep,
.qc_issue = ata_qc_issue_prot,
.data_xfer = ata_data_xfer,
@@ -284,6 +284,11 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
ata_interrupt, 0, DRV_NAME, host);
if (rc)
return rc;
+
+ if (i == 0)
+ host->irq = irq[0];
+ else
+ host->irq2 = irq[1];
}
return ata_host_register(host, &cs5520_sht);
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c
index 848f0309bf0..68f150a1e2f 100644
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -167,7 +167,7 @@ static struct scsi_host_template cs5530_sht = {
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -201,7 +201,7 @@ static struct ata_port_operations cs5530_port_ops = {
.post_internal_cmd = ata_bmdma_post_internal_cmd,
.cable_detect = ata_cable_40wire,
- .qc_prep = ata_qc_prep,
+ .qc_prep = ata_dumb_qc_prep,
.qc_issue = cs5530_qc_issue_prot,
.data_xfer = ata_data_xfer,
@@ -266,7 +266,7 @@ static int cs5530_init_chip(void)
}
pci_set_master(cs5530_0);
- pci_set_mwi(cs5530_0);
+ pci_try_set_mwi(cs5530_0);
/*
* Set PCI CacheLineSize to 16-bytes:
@@ -337,7 +337,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &cs5530_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
@@ -346,7 +346,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* The docking connector doesn't do UDMA, and it seems not MWDMA */
static const struct ata_port_info info_palmax_secondary = {
.sht = &cs5530_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &cs5530_port_ops
};
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c
index aa3256fb9f7..360b6f32e17 100644
--- a/drivers/ata/pata_cs5535.c
+++ b/drivers/ata/pata_cs5535.c
@@ -225,10 +225,10 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &cs5535_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &cs5535_port_ops
};
const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info };
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c
index d41a7691dd8..6cbc8778bf4 100644
--- a/drivers/ata/pata_cypress.c
+++ b/drivers/ata/pata_cypress.c
@@ -167,7 +167,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i
{
static const struct ata_port_info info = {
.sht = &cy82c693_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &cy82c693_port_ops
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
index 079248a9b46..c8ba59c5611 100644
--- a/drivers/ata/pata_efar.c
+++ b/drivers/ata/pata_efar.c
@@ -303,7 +303,7 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
static const struct ata_port_info info = {
.sht = &efar_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma1-2 */
.udma_mask = 0x0f, /* UDMA 66 */
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 0c9cb609071..6f7d34ad19e 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -393,10 +393,10 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info_hpt366 = {
.sht = &hpt36x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &hpt366_port_ops
};
struct ata_port_info info = info_hpt366;
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 6446735a46e..b0af65aadde 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -889,25 +889,25 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT370 - UDMA100 */
static const struct ata_port_info info_hpt370 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &hpt370_port_ops
};
/* HPT370A - UDMA100 */
static const struct ata_port_info info_hpt370a = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &hpt370a_port_ops
};
/* HPT370 - UDMA100 */
static const struct ata_port_info info_hpt370_33 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x0f,
@@ -916,7 +916,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT370A - UDMA100 */
static const struct ata_port_info info_hpt370a_33 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x0f,
@@ -925,19 +925,19 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT371, 372 and friends - UDMA133 */
static const struct ata_port_info info_hpt372 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &hpt372_port_ops
};
- /* HPT374 - UDMA133 */
+ /* HPT374 - UDMA100 */
static const struct ata_port_info info_hpt374 = {
.sht = &hpt37x_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &hpt374_port_ops
};
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index e947433cb37..aa29cde09f8 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -490,10 +490,10 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id)
/* HPT372N and friends - UDMA133 */
static const struct ata_port_info info = {
.sht = &hpt3x2n_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &hpt3x2n_port_ops
};
struct ata_port_info port = info;
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index 8ce5e23a5f7..be0f05efac6 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -23,7 +23,7 @@
#include <linux/libata.h>
#define DRV_NAME "pata_hpt3x3"
-#define DRV_VERSION "0.4.3"
+#define DRV_VERSION "0.5.3"
/**
* hpt3x3_set_piomode - PIO setup
@@ -52,6 +52,7 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev)
pci_write_config_dword(pdev, 0x48, r2);
}
+#if defined(CONFIG_PATA_HPT3X3_DMA)
/**
* hpt3x3_set_dmamode - DMA timing setup
* @ap: ATA interface
@@ -59,6 +60,9 @@ static void hpt3x3_set_piomode(struct ata_port *ap, struct ata_device *adev)
*
* Set up the channel for MWDMA or UDMA modes. Much the same as with
* PIO, load the mode number and then set MWDMA or UDMA flag.
+ *
+ * 0x44 : bit 0-2 master mode, 3-5 slave mode, etc
+ * 0x48 : bit 4/0 DMA/UDMA bit 5/1 for slave etc
*/
static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
@@ -76,13 +80,26 @@ static void hpt3x3_set_dmamode(struct ata_port *ap, struct ata_device *adev)
r2 &= ~(0x11 << dn); /* Clear MWDMA and UDMA bits */
if (adev->dma_mode >= XFER_UDMA_0)
- r2 |= 0x01 << dn; /* Ultra mode */
+ r2 |= (0x10 << dn); /* Ultra mode */
else
- r2 |= 0x10 << dn; /* MWDMA */
+ r2 |= (0x01 << dn); /* MWDMA */
pci_write_config_dword(pdev, 0x44, r1);
pci_write_config_dword(pdev, 0x48, r2);
}
+#endif /* CONFIG_PATA_HPT3X3_DMA */
+
+/**
+ * hpt3x3_atapi_dma - ATAPI DMA check
+ * @qc: Queued command
+ *
+ * Just say no - we don't do ATAPI DMA
+ */
+
+static int hpt3x3_atapi_dma(struct ata_queued_cmd *qc)
+{
+ return 1;
+}
static struct scsi_host_template hpt3x3_sht = {
.module = THIS_MODULE,
@@ -105,7 +122,9 @@ static struct scsi_host_template hpt3x3_sht = {
static struct ata_port_operations hpt3x3_port_ops = {
.port_disable = ata_port_disable,
.set_piomode = hpt3x3_set_piomode,
+#if defined(CONFIG_PATA_HPT3X3_DMA)
.set_dmamode = hpt3x3_set_dmamode,
+#endif
.mode_filter = ata_pci_default_filter,
.tf_load = ata_tf_load,
@@ -124,6 +143,7 @@ static struct ata_port_operations hpt3x3_port_ops = {
.bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
+ .check_atapi_dma= hpt3x3_atapi_dma,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
@@ -158,32 +178,79 @@ static void hpt3x3_init_chipset(struct pci_dev *dev)
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
}
-
/**
* hpt3x3_init_one - Initialise an HPT343/363
- * @dev: PCI device
+ * @pdev: PCI device
* @id: Entry in match table
*
- * Perform basic initialisation. The chip has a quirk that it won't
- * function unless it is at XX00. The old ATA driver touched this up
- * but we leave it for pci quirks to do properly.
+ * Perform basic initialisation. We set the device up so we access all
+ * ports via BAR4. This is neccessary to work around errata.
*/
-static int hpt3x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
+ static int printed_version;
static const struct ata_port_info info = {
.sht = &hpt3x3_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
+#if defined(CONFIG_PATA_HPT3X3_DMA)
+ /* Further debug needed */
.mwdma_mask = 0x07,
.udma_mask = 0x07,
+#endif
.port_ops = &hpt3x3_port_ops
};
+ /* Register offsets of taskfiles in BAR4 area */
+ static const u8 offset_cmd[2] = { 0x20, 0x28 };
+ static const u8 offset_ctl[2] = { 0x36, 0x3E };
const struct ata_port_info *ppi[] = { &info, NULL };
-
- hpt3x3_init_chipset(dev);
- /* Now kick off ATA set up */
- return ata_pci_init_one(dev, ppi);
+ struct ata_host *host;
+ int i, rc;
+ void __iomem *base;
+
+ hpt3x3_init_chipset(pdev);
+
+ if (!printed_version++)
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
+
+ host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
+ if (!host)
+ return -ENOMEM;
+ /* acquire resources and fill host */
+ rc = pcim_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ /* Everything is relative to BAR4 if we set up this way */
+ rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
+ if (rc == -EBUSY)
+ pcim_pin_device(pdev);
+ if (rc)
+ return rc;
+ host->iomap = pcim_iomap_table(pdev);
+ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+ if (rc)
+ return rc;
+ rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
+ if (rc)
+ return rc;
+
+ base = host->iomap[4]; /* Bus mastering base */
+
+ for (i = 0; i < host->n_ports; i++) {
+ struct ata_ioports *ioaddr = &host->ports[i]->ioaddr;
+
+ ioaddr->cmd_addr = base + offset_cmd[i];
+ ioaddr->altstatus_addr =
+ ioaddr->ctl_addr = base + offset_ctl[i];
+ ioaddr->scr_addr = NULL;
+ ata_std_ports(ioaddr);
+ ioaddr->bmdma_addr = base + 8 * i;
+ }
+ pci_set_master(pdev);
+ return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED,
+ &hpt3x3_sht);
}
#ifdef CONFIG_PM
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index c791a46df46..321d98b0bed 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -530,7 +530,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
ap->pio_mask = 0x1f;
ap->mwdma_mask = info->mwdma_mask;
- ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+ ap->flags |= ATA_FLAG_SLAVE_POSS;
ap->ops = &pata_icside_port_ops;
pata_icside_setup_ioaddr(&ap->ioaddr, info->base, info->port[i]);
diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c
index 1f647b64820..5525518204e 100644
--- a/drivers/ata/pata_isapnp.c
+++ b/drivers/ata/pata_isapnp.c
@@ -77,7 +77,6 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
struct ata_host *host;
struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr;
- int rc;
if (pnp_port_valid(idev, 0) == 0)
return -ENODEV;
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
index 95b0bb61788..b8af55e8915 100644
--- a/drivers/ata/pata_it8213.c
+++ b/drivers/ata/pata_it8213.c
@@ -313,10 +313,10 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en
static int printed_version;
static const struct ata_port_info info = {
.sht = &it8213_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x1f, /* UDMA 100 */
+ .udma_mask = ATA_UDMA4, /* FIXME: want UDMA 100? */
.port_ops = &it8213_ops,
};
/* Current IT8213 stuff is single port */
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index b3456d7a592..430673be1df 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -2,6 +2,7 @@
* pata_it821x.c - IT821x PATA for new ATA layer
* (C) 2005 Red Hat Inc
* Alan Cox <alan@redhat.com>
+ * (C) 2007 Bartlomiej Zolnierkiewicz
*
* based upon
*
@@ -79,7 +80,7 @@
#define DRV_NAME "pata_it821x"
-#define DRV_VERSION "0.3.6"
+#define DRV_VERSION "0.3.7"
struct it821x_dev
{
@@ -460,14 +461,8 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc)
static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused)
{
- int dma_enabled = 0;
int i;
- /* Bits 5 and 6 indicate if DMA is active on master/slave */
- /* It is possible that BMDMA isn't allocated */
- if (ap->ioaddr.bmdma_addr)
- dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
-
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->device[i];
if (ata_dev_enabled(dev)) {
@@ -476,7 +471,7 @@ static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused
dev->dma_mode = XFER_MW_DMA_0;
/* We do need the right mode information for DMA or PIO
and this comes from the current configuration flags */
- if (dma_enabled & (1 << (5 + i))) {
+ if (ata_id_has_dma(dev->id)) {
ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
dev->xfer_mode = XFER_MW_DMA_0;
dev->xfer_shift = ATA_SHIFT_MWDMA;
@@ -592,8 +587,7 @@ static int it821x_port_start(struct ata_port *ap)
itdev->want[1][1] = ATA_ANY;
itdev->last_device = -1;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &conf);
- if (conf == 0x10) {
+ if (pdev->revision == 0x11) {
itdev->timing10 = 1;
/* Need to disable ATAPI DMA for this case */
if (!itdev->smart)
@@ -695,7 +689,7 @@ static struct ata_port_operations it821x_passthru_port_ops = {
.port_start = it821x_port_start,
};
-static void __devinit it821x_disable_raid(struct pci_dev *pdev)
+static void it821x_disable_raid(struct pci_dev *pdev)
{
/* Reset local CPU, and set BIOS not ready */
pci_write_config_byte(pdev, 0x5E, 0x01);
@@ -719,17 +713,17 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
static const struct ata_port_info info_smart = {
.sht = &it821x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &it821x_smart_port_ops
};
static const struct ata_port_info info_passthru = {
.sht = &it821x_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &it821x_passthru_port_ops
};
@@ -799,7 +793,7 @@ MODULE_VERSION(DRV_VERSION);
module_param_named(noraid, it8212_noraid, int, S_IRUGO);
-MODULE_PARM_DESC(it8212_noraid, "Force card into bypass mode");
+MODULE_PARM_DESC(noraid, "Force card into bypass mode");
module_init(it821x_init);
module_exit(it821x_exit);
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index 8d2bc1e9e87..4ca7fd6118d 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -1,13 +1,14 @@
/*
* ixp4xx PATA/Compact Flash driver
- * Copyright (c) 2006 Tower Technologies
+ * Copyright (C) 2006-07 Tower Technologies
* Author: Alessandro Zummo <a.zummo@towertech.it>
*
* An ATA driver to handle a Compact Flash connected
* to the ixp4xx expansion bus in TrueIDE mode. The CF
* must have it chip selects connected to two CS lines
- * on the ixp4xx. The interrupt line is optional, if not
- * specified the driver will run in polling mode.
+ * on the ixp4xx. In the irq is not available, you might
+ * want to modify both this driver and libata to run in
+ * polling mode.
*
* 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
@@ -23,7 +24,7 @@
#include <scsi/scsi_host.h>
#define DRV_NAME "pata_ixp4xx_cf"
-#define DRV_VERSION "0.1.3"
+#define DRV_VERSION "0.2"
static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error)
{
@@ -42,13 +43,6 @@ static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device **error)
return 0;
}
-static void ixp4xx_phy_reset(struct ata_port *ap)
-{
- ap->cbl = ATA_CBL_PATA40;
- ata_port_probe(ap);
- ata_bus_reset(ap);
-}
-
static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data)
{
@@ -56,7 +50,7 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int words = buflen >> 1;
u16 *buf16 = (u16 *) buf;
struct ata_port *ap = adev->ap;
- void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+ void __iomem *mmio = ap->ioaddr.data_addr;
struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
/* set the expansion bus in 16bit mode and restore
@@ -92,10 +86,6 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
*data->cs0_cfg |= 0x01;
}
-static void ixp4xx_irq_clear(struct ata_port *ap)
-{
-}
-
static struct scsi_host_template ixp4xx_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
@@ -115,29 +105,32 @@ static struct scsi_host_template ixp4xx_sht = {
};
static struct ata_port_operations ixp4xx_port_ops = {
- .set_mode = ixp4xx_set_mode,
- .mode_filter = ata_pci_default_filter,
-
- .port_disable = ata_port_disable,
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = ata_exec_command,
- .dev_select = ata_std_dev_select,
-
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .eng_timeout = ata_eng_timeout,
- .data_xfer = ixp4xx_mmio_data_xfer,
- .cable_detect = ata_cable_40wire,
-
- .irq_clear = ixp4xx_irq_clear,
- .irq_on = ata_irq_on,
- .irq_ack = ata_irq_ack,
-
- .port_start = ata_port_start,
-
- .phy_reset = ixp4xx_phy_reset,
+ .set_mode = ixp4xx_set_mode,
+ .mode_filter = ata_pci_default_filter,
+
+ .port_disable = ata_port_disable,
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .exec_command = ata_exec_command,
+ .check_status = ata_check_status,
+ .dev_select = ata_std_dev_select,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ata_bmdma_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .data_xfer = ixp4xx_mmio_data_xfer,
+ .cable_detect = ata_cable_40wire,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+ .irq_on = ata_irq_on,
+ .irq_ack = ata_dummy_irq_ack,
+
+ .port_start = ata_port_start,
};
static void ixp4xx_setup_port(struct ata_ioports *ioaddr,
@@ -178,7 +171,6 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
struct ata_host *host;
struct ata_port *ap;
struct ixp4xx_pata_data *data = pdev->dev.platform_data;
- int rc;
cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -211,10 +203,6 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
ap->pio_mask = 0x1f; /* PIO4 */
ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
- /* run in polling mode if no irq has been assigned */
- if (!irq)
- ap->flags |= ATA_FLAG_PIO_POLLING;
-
ixp4xx_setup_port(&ap->ioaddr, data);
dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 2af7ff8256c..4d67f238eee 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -193,11 +193,11 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
{
static const struct ata_port_info info = {
.sht = &jmicron_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &jmicron_ops,
};
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index edbfe0dbbf7..87594c04d3a 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -163,22 +163,22 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i
{
static const struct ata_port_info info = {
.sht = &marvell_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &marvell_ops,
};
static const struct ata_port_info info_sata = {
.sht = &marvell_sht,
/* Slave possible as its magically mapped not real */
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &marvell_ops,
};
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 368fac7d168..182e83c9047 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -467,13 +467,27 @@ mpc52xx_ata_remove(struct of_device *op)
static int
mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
{
- return 0; /* FIXME : What to do here ? */
+ struct ata_host *host = dev_get_drvdata(&op->dev);
+
+ return ata_host_suspend(host, state);
}
static int
mpc52xx_ata_resume(struct of_device *op)
{
- return 0; /* FIXME : What to do here ? */
+ struct ata_host *host = dev_get_drvdata(&op->dev);
+ struct mpc52xx_ata_priv *priv = host->private_data;
+ int rv;
+
+ rv = mpc52xx_ata_hw_init(priv);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": Error during HW init\n");
+ return rv;
+ }
+
+ ata_host_resume(host);
+
+ return 0;
}
#endif
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c
index 81f56345866..40eb574828b 100644
--- a/drivers/ata/pata_netcell.c
+++ b/drivers/ata/pata_netcell.c
@@ -94,12 +94,12 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.sht = &netcell_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
/* Actually we don't really care about these as the
firmware deals with it */
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* UDMA 133 */
+ .udma_mask = ATA_UDMA5, /* UDMA 133 */
.port_ops = &netcell_ops,
};
const struct ata_port_info *port_info[] = { &info, NULL };
diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c
index ea70ec74487..2f5d714ebfc 100644
--- a/drivers/ata/pata_ns87410.c
+++ b/drivers/ata/pata_ns87410.c
@@ -193,7 +193,7 @@ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &ns87410_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x0F,
.port_ops = &ns87410_port_ops
};
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index 29c23ddd655..091a70a0ef1 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -291,7 +291,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.sht = &oldpiix_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma1-2 */
.port_ops = &oldpiix_pata_ops,
diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c
index 1c44653e1e0..458bf67f766 100644
--- a/drivers/ata/pata_opti.c
+++ b/drivers/ata/pata_opti.c
@@ -218,7 +218,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &opti_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &opti_port_ops
};
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c
index 3093b02286c..f89bdfde16d 100644
--- a/drivers/ata/pata_optidma.c
+++ b/drivers/ata/pata_optidma.c
@@ -484,14 +484,14 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info_82c700 = {
.sht = &optidma_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &optidma_port_ops
};
static const struct ata_port_info info_82c700_udma = {
.sht = &optidma_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 4d44c7555db..a56257c98fe 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -129,7 +129,7 @@ static struct ata_port_operations pcmcia_port_ops = {
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
- .port_start = ata_port_start,
+ .port_start = ata_sff_port_start,
};
#define CS_CHECK(fn, ret) \
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index 0d2cc49fde4..69a5aa4949f 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -689,10 +689,12 @@ static long pdc_detect_pll_input_clock(struct ata_host *host)
void __iomem *mmio_base = host->iomap[PDC_MMIO_BAR];
u32 scr;
long start_count, end_count;
- long pll_clock;
+ struct timeval start_time, end_time;
+ long pll_clock, usec_elapsed;
/* Read current counter value */
start_count = pdc_read_counter(host);
+ do_gettimeofday(&start_time);
/* Start the test mode */
scr = readl(mmio_base + PDC_SYS_CTL);
@@ -705,6 +707,7 @@ static long pdc_detect_pll_input_clock(struct ata_host *host)
/* Read the counter values again */
end_count = pdc_read_counter(host);
+ do_gettimeofday(&end_time);
/* Stop the test mode */
scr = readl(mmio_base + PDC_SYS_CTL);
@@ -713,7 +716,11 @@ static long pdc_detect_pll_input_clock(struct ata_host *host)
readl(mmio_base + PDC_SYS_CTL); /* flush */
/* calculate the input clock in Hz */
- pll_clock = (start_count - end_count) * 10;
+ usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
+ (end_time.tv_usec - start_time.tv_usec);
+
+ pll_clock = (start_count - end_count) / 100 *
+ (100000000 / usec_elapsed);
PDPRINTK("start[%ld] end[%ld] \n", start_count, end_count);
PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock);
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
index edbaf9d653b..92447bed5e7 100644
--- a/drivers/ata/pata_pdc202xx_old.c
+++ b/drivers/ata/pata_pdc202xx_old.c
@@ -31,8 +31,8 @@ static int pdc2026x_cable_detect(struct ata_port *ap)
pci_read_config_word(pdev, 0x50, &cis);
if (cis & (1 << (10 + ap->port_no)))
- return ATA_CBL_PATA80;
- return ATA_CBL_PATA40;
+ return ATA_CBL_PATA40;
+ return ATA_CBL_PATA80;
}
/**
@@ -320,7 +320,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
static const struct ata_port_info info[3] = {
{
.sht = &pdc202xx_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA2,
@@ -328,7 +328,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
},
{
.sht = &pdc202xx_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA4,
@@ -336,7 +336,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id
},
{
.sht = &pdc202xx_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA5,
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index cbb7866940d..79f841bca59 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -139,6 +139,7 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
struct resource *io_res, *ctl_res;
struct ata_host *host;
struct ata_port *ap;
+ struct pata_platform_info *pp_info;
unsigned int mmio;
/*
@@ -208,11 +209,12 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
- pata_platform_setup_port(&ap->ioaddr, pdev->dev.platform_data);
+ pp_info = (struct pata_platform_info *)(pdev->dev.platform_data);
+ pata_platform_setup_port(&ap->ioaddr, pp_info);
/* activate */
return ata_host_activate(host, platform_get_irq(pdev, 0), ata_interrupt,
- 0, &pata_platform_sht);
+ pp_info->irq_flags, &pata_platform_sht);
}
/**
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c
index ba96b54f5b8..7d1aabed422 100644
--- a/drivers/ata/pata_radisys.c
+++ b/drivers/ata/pata_radisys.c
@@ -257,7 +257,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e
static int printed_version;
static const struct ata_port_info info = {
.sht = &radisys_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma1-2 */
.udma_mask = 0x14, /* UDMA33/66 only */
diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c
index a3488b41ad2..7632fcb070c 100644
--- a/drivers/ata/pata_rz1000.c
+++ b/drivers/ata/pata_rz1000.c
@@ -133,7 +133,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en
static int printed_version;
static const struct ata_port_info info = {
.sht = &rz1000_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &rz1000_port_ops
};
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index 1233063ab9a..b8b2d11e418 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -185,7 +185,7 @@ static struct scsi_host_template sc1200_sht = {
.queuecommand = ata_scsi_queuecmd,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = LIBATA_DUMB_MAX_PRD,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
@@ -219,7 +219,7 @@ static struct ata_port_operations sc1200_port_ops = {
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
+ .qc_prep = ata_dumb_qc_prep,
.qc_issue = sc1200_qc_issue_prot,
.data_xfer = ata_data_xfer,
@@ -245,7 +245,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &sc1200_sht,
- .flags = ATA_FLAG_SLAVE_POSS|ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 61502bc7bf1..c55667e0eb6 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -238,6 +238,12 @@ static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev)
else
offset = 0; /* 100MHz */
+ /* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */
+ if (adev->class == ATA_DEV_ATAPI && speed > XFER_UDMA_4) {
+ printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
+ speed = XFER_UDMA_4;
+ }
+
if (speed >= XFER_UDMA_0)
idx = speed - XFER_UDMA_0;
else
@@ -724,22 +730,36 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc)
static u8 scc_bmdma_status (struct ata_port *ap)
{
- u8 host_stat;
void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
- host_stat = in_be32(mmio + SCC_DMA_STATUS);
-
- /* Workaround for PTERADD: emulate DMA_INTR when
- * - IDE_STATUS[ERR] = 1
- * - INT_STATUS[INTRQ] = 1
- * - DMA_STATUS[IORACTA] = 1
- */
- if (!(host_stat & ATA_DMA_INTR)) {
- u32 int_status = in_be32(mmio + SCC_DMA_INTST);
- if (ata_altstatus(ap) & ATA_ERR &&
- int_status & INTSTS_INTRQ &&
- host_stat & ATA_DMA_ACTIVE)
- host_stat |= ATA_DMA_INTR;
+ u8 host_stat = in_be32(mmio + SCC_DMA_STATUS);
+ u32 int_status = in_be32(mmio + SCC_DMA_INTST);
+ struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+ static int retry = 0;
+
+ /* return if IOS_SS is cleared */
+ if (!(in_be32(mmio + SCC_DMA_CMD) & ATA_DMA_START))
+ return host_stat;
+
+ /* errata A252,A308 workaround: Step4 */
+ if (ata_altstatus(ap) & ATA_ERR && int_status & INTSTS_INTRQ)
+ return (host_stat | ATA_DMA_INTR);
+
+ /* errata A308 workaround Step5 */
+ if (int_status & INTSTS_IOIRQS) {
+ host_stat |= ATA_DMA_INTR;
+
+ /* We don't check ATAPI DMA because it is limited to UDMA4 */
+ if ((qc->tf.protocol == ATA_PROT_DMA &&
+ qc->dev->xfer_mode > XFER_UDMA_4)) {
+ if (!(int_status & INTSTS_ACTEINT)) {
+ printk(KERN_WARNING "ata%u: data lost occurred. (ACTEINT==0, retry:%d)\n",
+ ap->print_id, retry);
+ host_stat |= ATA_DMA_ERR;
+ if (retry++)
+ ap->udma_mask >>= 1;
+ } else
+ retry = 0;
+ }
}
return host_stat;
@@ -892,10 +912,6 @@ static void scc_std_postreset (struct ata_port *ap, unsigned int *classes)
{
DPRINTK("ENTER\n");
- /* re-enable interrupts */
- if (!ap->ops->error_handler)
- ap->ops->irq_on(ap);
-
/* is double-select really necessary? */
if (classes[0] != ATA_DEV_NONE)
ap->ops->dev_select(ap, 1);
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
index 1e8f421963c..89691541fe5 100644
--- a/drivers/ata/pata_serverworks.c
+++ b/drivers/ata/pata_serverworks.c
@@ -410,11 +410,8 @@ static int serverworks_fixup_osb4(struct pci_dev *pdev)
static int serverworks_fixup_csb(struct pci_dev *pdev)
{
- u8 rev;
u8 btr;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-
/* Third Channel Test */
if (!(PCI_FUNC(pdev->devfn) & 1)) {
struct pci_dev * findev = NULL;
@@ -456,7 +453,7 @@ static int serverworks_fixup_csb(struct pci_dev *pdev)
if (!(PCI_FUNC(pdev->devfn) & 1))
btr |= 0x2;
else
- btr |= (rev >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
+ btr |= (pdev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
pci_write_config_byte(pdev, 0x5A, btr);
return btr;
@@ -478,31 +475,31 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id
static const struct ata_port_info info[4] = {
{ /* OSB4 */
.sht = &serverworks_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x07,
.port_ops = &serverworks_osb4_port_ops
}, { /* OSB4 no UDMA */
.sht = &serverworks_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x00,
.port_ops = &serverworks_osb4_port_ops
}, { /* CSB5 */
.sht = &serverworks_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &serverworks_csb_port_ops
}, { /* CSB5 - later revisions*/
.sht = &serverworks_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &serverworks_csb_port_ops
}
};
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 440e2cb6ee7..b0cd52d6e3f 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -35,6 +35,8 @@
#define DRV_NAME "pata_sil680"
#define DRV_VERSION "0.4.6"
+#define SIL680_MMIO_BAR 5
+
/**
* sil680_selreg - return register base
* @hwif: interface
@@ -293,8 +295,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev)
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
- printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
- tmpbyte & 1, tmpbyte & 0x30);
+ dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
+ tmpbyte & 1, tmpbyte & 0x30);
switch(tmpbyte & 0x30) {
case 0x00:
@@ -315,8 +317,8 @@ static u8 sil680_init_chip(struct pci_dev *pdev)
}
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
- printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
- tmpbyte & 1, tmpbyte & 0x30);
+ dev_dbg(&pdev->dev, "sil680: BA5_EN = %d clock = %02X\n",
+ tmpbyte & 1, tmpbyte & 0x30);
pci_write_config_byte(pdev, 0xA1, 0x72);
pci_write_config_word(pdev, 0xA2, 0x328A);
@@ -339,22 +341,23 @@ static u8 sil680_init_chip(struct pci_dev *pdev)
return tmpbyte & 0x30;
}
-static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+static int __devinit sil680_init_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &sil680_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &sil680_port_ops
};
static const struct ata_port_info info_slow = {
.sht = &sil680_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil680_port_ops
};
const struct ata_port_info *ppi[] = { &info, NULL };
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index ec3ae937501..9a829a7cbc6 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -149,6 +149,9 @@ static int sis_pre_reset(struct ata_port *ap, unsigned long deadline)
if (!pci_test_config_bits(pdev, &sis_enable_bits[ap->port_no]))
return -ENOENT;
+ /* Clear the FIFO settings. We can't enable the FIFO until
+ we know we are poking at a disk */
+ pci_write_config_byte(pdev, 0x4B, 0);
return ata_std_prereset(ap, deadline);
}
@@ -560,6 +563,40 @@ static const struct ata_port_operations sis_133_ops = {
.port_start = ata_port_start,
};
+static const struct ata_port_operations sis_133_for_sata_ops = {
+ .port_disable = ata_port_disable,
+ .set_piomode = sis_133_set_piomode,
+ .set_dmamode = sis_133_set_dmamode,
+ .mode_filter = ata_pci_default_filter,
+
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+
+ .freeze = ata_bmdma_freeze,
+ .thaw = ata_bmdma_thaw,
+ .error_handler = ata_bmdma_error_handler,
+ .post_internal_cmd = ata_bmdma_post_internal_cmd,
+ .cable_detect = sis_133_cable_detect,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .bmdma_stop = ata_bmdma_stop,
+ .bmdma_status = ata_bmdma_status,
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+ .data_xfer = ata_data_xfer,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+ .irq_on = ata_irq_on,
+ .irq_ack = ata_irq_ack,
+
+ .port_start = ata_port_start,
+};
+
static const struct ata_port_operations sis_133_early_ops = {
.port_disable = ata_port_disable,
.set_piomode = sis_100_set_piomode,
@@ -698,7 +735,7 @@ static const struct ata_port_operations sis_old_ops = {
static const struct ata_port_info sis_info = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07,
.udma_mask = 0,
@@ -706,7 +743,7 @@ static const struct ata_port_info sis_info = {
};
static const struct ata_port_info sis_info33 = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA2, /* UDMA 33 */
@@ -714,42 +751,49 @@ static const struct ata_port_info sis_info33 = {
};
static const struct ata_port_info sis_info66 = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA4, /* UDMA 66 */
.port_ops = &sis_66_ops,
};
static const struct ata_port_info sis_info100 = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA5,
.port_ops = &sis_100_ops,
};
static const struct ata_port_info sis_info100_early = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.udma_mask = ATA_UDMA5,
.pio_mask = 0x1f, /* pio0-4 */
.port_ops = &sis_66_ops,
};
-const struct ata_port_info sis_info133 = {
+static const struct ata_port_info sis_info133 = {
.sht = &sis_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
.port_ops = &sis_133_ops,
};
-static const struct ata_port_info sis_info133_early = {
+const struct ata_port_info sis_info133_for_sata = {
.sht = &sis_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f, /* pio0-4 */
.udma_mask = ATA_UDMA6,
+ .port_ops = &sis_133_for_sata_ops,
+};
+static const struct ata_port_info sis_info133_early = {
+ .sht = &sis_sht,
+ .flags = ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &sis_133_early_ops,
};
/* Privately shared with the SiS180 SATA driver, not for use elsewhere */
-EXPORT_SYMBOL_GPL(sis_info133);
+EXPORT_SYMBOL_GPL(sis_info133_for_sata);
static void sis_fixup(struct pci_dev *pdev, struct sis_chipset *sis)
{
@@ -887,9 +931,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (host != NULL) {
chipset = sets; /* Match found */
if (sets->device == 0x630) { /* SIS630 */
- u8 host_rev;
- pci_read_config_byte(host, PCI_REVISION_ID, &host_rev);
- if (host_rev >= 0x30) /* 630 ET */
+ if (host->revision >= 0x30) /* 630 ET */
chipset = &sis100_early;
}
break;
@@ -933,7 +975,6 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
u16 trueid;
u8 prefctl;
u8 idecfg;
- u8 sbrev;
/* Try the second unmasking technique */
pci_read_config_byte(pdev, 0x4a, &idecfg);
@@ -946,11 +987,10 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
lpc_bridge = pci_get_slot(pdev->bus, 0x10); /* Bus 0 Dev 2 Fn 0 */
if (lpc_bridge == NULL)
break;
- pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
pci_read_config_byte(pdev, 0x49, &prefctl);
pci_dev_put(lpc_bridge);
- if (sbrev == 0x10 && (prefctl & 0x80)) {
+ if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
chipset = &sis133_early;
break;
}
@@ -975,6 +1015,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static const struct pci_device_id sis_pci_tbl[] = {
{ PCI_VDEVICE(SI, 0x5513), }, /* SiS 5513 */
{ PCI_VDEVICE(SI, 0x5518), }, /* SiS 5518 */
+ { PCI_VDEVICE(SI, 0x1180), }, /* SiS 1180 */
{ }
};
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
index e5aaec43694..8c2813aa6cd 100644
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -270,7 +270,6 @@ static struct ata_port_operations sl82c105_port_ops = {
static int sl82c105_bridge_revision(struct pci_dev *pdev)
{
struct pci_dev *bridge;
- u8 rev;
/*
* The bridge should be part of the same device, but function 0.
@@ -292,10 +291,8 @@ static int sl82c105_bridge_revision(struct pci_dev *pdev)
/*
* We need to find function 0's revision, not function 1
*/
- pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
-
pci_dev_put(bridge);
- return rev;
+ return bridge->revision;
}
@@ -303,14 +300,14 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
{
static const struct ata_port_info info_dma = {
.sht = &sl82c105_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &sl82c105_port_ops
};
static const struct ata_port_info info_early = {
.sht = &sl82c105_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.port_ops = &sl82c105_port_ops
};
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c
index b1d3076dfe5..af21f443db6 100644
--- a/drivers/ata/pata_triflex.c
+++ b/drivers/ata/pata_triflex.c
@@ -235,7 +235,7 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static const struct ata_port_info info = {
.sht = &triflex_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &triflex_port_ops
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index a8462f1e890..f645fe22cd1 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -452,7 +452,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Early VIA without UDMA support */
static const struct ata_port_info via_mwdma_info = {
.sht = &via_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &via_port_ops
@@ -460,7 +460,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Ditto with IRQ masking required */
static const struct ata_port_info via_mwdma_info_borked = {
.sht = &via_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.port_ops = &via_port_ops_noirq,
@@ -468,37 +468,37 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* VIA UDMA 33 devices (and borked 66) */
static const struct ata_port_info via_udma33_info = {
.sht = &via_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7,
+ .udma_mask = ATA_UDMA2,
.port_ops = &via_port_ops
};
/* VIA UDMA 66 devices */
static const struct ata_port_info via_udma66_info = {
.sht = &via_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x1f,
+ .udma_mask = ATA_UDMA4,
.port_ops = &via_port_ops
};
/* VIA UDMA 100 devices */
static const struct ata_port_info via_udma100_info = {
.sht = &via_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x3f,
+ .udma_mask = ATA_UDMA5,
.port_ops = &via_port_ops
};
/* UDMA133 with bad AST (All current 133) */
static const struct ata_port_info via_udma133_info = {
.sht = &via_sht,
- .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SETXFER_POLLING,
+ .flags = ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f, /* FIXME: should check north bridge */
+ .udma_mask = ATA_UDMA6, /* FIXME: should check north bridge */
.port_ops = &via_port_ops
};
struct ata_port_info type;
@@ -506,7 +506,6 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
struct pci_dev *isa = NULL;
const struct via_isa_bridge *config;
static int printed_version;
- u8 t;
u8 enable;
u32 timing;
@@ -520,9 +519,8 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
!!(config->flags & VIA_BAD_ID),
config->id, NULL))) {
- pci_read_config_byte(isa, PCI_REVISION_ID, &t);
- if (t >= config->rev_min &&
- t <= config->rev_max)
+ if (isa->revision >= config->rev_min &&
+ isa->revision <= config->rev_max)
break;
pci_dev_put(isa);
}
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index f12c2b6ac08..bec1de594de 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -145,32 +145,32 @@ static struct scsi_host_template adma_ata_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
+ .slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
+ .bios_param = ata_std_bios_param,
+ .proc_name = DRV_NAME,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
+ .dma_boundary = ADMA_DMA_BOUNDARY,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
- .emulated = ATA_SHT_EMULATED,
.use_clustering = ENABLE_CLUSTERING,
- .proc_name = DRV_NAME,
- .dma_boundary = ADMA_DMA_BOUNDARY,
- .slave_configure = ata_scsi_slave_config,
- .slave_destroy = ata_scsi_slave_destroy,
- .bios_param = ata_std_bios_param,
+ .emulated = ATA_SHT_EMULATED,
};
static const struct ata_port_operations adma_ata_ops = {
.port_disable = ata_port_disable,
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .check_atapi_dma = adma_check_atapi_dma,
.exec_command = ata_exec_command,
+ .check_status = ata_check_status,
.dev_select = ata_std_dev_select,
.phy_reset = adma_phy_reset,
+ .check_atapi_dma = adma_check_atapi_dma,
+ .data_xfer = ata_data_xfer,
.qc_prep = adma_qc_prep,
.qc_issue = adma_qc_issue,
.eng_timeout = adma_eng_timeout,
- .data_xfer = ata_data_xfer,
.irq_clear = adma_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
@@ -188,7 +188,7 @@ static struct ata_port_info adma_port_info[] = {
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */
- .udma_mask = 0x1f, /* udma0-4 */
+ .udma_mask = ATA_UDMA4,
.port_ops = &adma_ata_ops,
},
};
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 2d80c9d95e9..3de183461c3 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -192,7 +192,7 @@ static void inic_reset_port(void __iomem *port_base)
static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg)
{
- void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+ void __iomem *scr_addr = ap->ioaddr.scr_addr;
void __iomem *addr;
u32 val;
@@ -210,7 +210,7 @@ static u32 inic_scr_read(struct ata_port *ap, unsigned sc_reg)
static void inic_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val)
{
- void __iomem *scr_addr = (void __iomem *)ap->ioaddr.scr_addr;
+ void __iomem *scr_addr = ap->ioaddr.scr_addr;
void __iomem *addr;
if (unlikely(sc_reg >= ARRAY_SIZE(scr_map)))
@@ -496,6 +496,13 @@ static void inic_dev_config(struct ata_device *dev)
/* inic can only handle upto LBA28 max sectors */
if (dev->max_sectors > ATA_MAX_SECTORS)
dev->max_sectors = ATA_MAX_SECTORS;
+
+ if (dev->n_sectors >= 1 << 28) {
+ ata_dev_printk(dev, KERN_ERR,
+ "ERROR: This driver doesn't support LBA48 yet and may cause\n"
+ " data corruption on such devices. Disabling.\n");
+ ata_dev_disable(dev);
+ }
}
static void init_port(struct ata_port *ap)
@@ -587,7 +594,7 @@ static struct ata_port_info inic_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &inic_port_ops
};
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index c957e6e54ba..5d576435fcc 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -29,11 +29,6 @@
I distinctly remember a couple workarounds (one related to PCI-X)
are still needed.
- 2) Convert to LibATA new EH. Required for hotplug, NCQ, and sane
- probing/error handling in general. MUST HAVE.
-
- 3) Add hotplug support (easy, once new-EH support appears)
-
4) Add NCQ support (easy to intermediate, once new-EH support appears)
5) Investigate problems with PCI Message Signalled Interrupts (MSI).
@@ -108,8 +103,6 @@ enum {
MV_SATAHC_ARBTR_REG_SZ = MV_MINOR_REG_AREA_SZ, /* arbiter */
MV_PORT_REG_SZ = MV_MINOR_REG_AREA_SZ,
- MV_USE_Q_DEPTH = ATA_DEF_QUEUE,
-
MV_MAX_Q_DEPTH = 32,
MV_MAX_Q_DEPTH_MASK = MV_MAX_Q_DEPTH - 1,
@@ -133,18 +126,22 @@ enum {
/* Host Flags */
MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
- MV_COMMON_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
- ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
+ MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+ ATA_FLAG_PIO_POLLING,
MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE,
CRQB_FLAG_READ = (1 << 0),
CRQB_TAG_SHIFT = 1,
+ CRQB_IOID_SHIFT = 6, /* CRQB Gen-II/IIE IO Id shift */
+ CRQB_HOSTQ_SHIFT = 17, /* CRQB Gen-II/IIE HostQueTag shift */
CRQB_CMD_ADDR_SHIFT = 8,
CRQB_CMD_CS = (0x2 << 11),
CRQB_CMD_LAST = (1 << 15),
CRPB_FLAG_STATUS_SHIFT = 8,
+ CRPB_IOID_SHIFT_6 = 5, /* CRPB Gen-II IO Id shift */
+ CRPB_IOID_SHIFT_7 = 7, /* CRPB Gen-IIE IO Id shift */
EPRD_FLAG_END_OF_TBL = (1 << 31),
@@ -236,8 +233,10 @@ enum {
EDMA_ERR_DEV_DCON = (1 << 3),
EDMA_ERR_DEV_CON = (1 << 4),
EDMA_ERR_SERR = (1 << 5),
- EDMA_ERR_SELF_DIS = (1 << 7),
+ EDMA_ERR_SELF_DIS = (1 << 7), /* Gen II/IIE self-disable */
+ EDMA_ERR_SELF_DIS_5 = (1 << 8), /* Gen I self-disable */
EDMA_ERR_BIST_ASYNC = (1 << 8),
+ EDMA_ERR_TRANS_IRQ_7 = (1 << 8), /* Gen IIE transprt layer irq */
EDMA_ERR_CRBQ_PAR = (1 << 9),
EDMA_ERR_CRPB_PAR = (1 << 10),
EDMA_ERR_INTRL_PAR = (1 << 11),
@@ -248,13 +247,33 @@ enum {
EDMA_ERR_LNK_CTRL_TX = (0x1f << 21),
EDMA_ERR_LNK_DATA_TX = (0x1f << 26),
EDMA_ERR_TRANS_PROTO = (1 << 31),
- EDMA_ERR_FATAL = (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
- EDMA_ERR_DEV_DCON | EDMA_ERR_CRBQ_PAR |
- EDMA_ERR_CRPB_PAR | EDMA_ERR_INTRL_PAR |
- EDMA_ERR_IORDY | EDMA_ERR_LNK_CTRL_RX_2 |
- EDMA_ERR_LNK_DATA_RX |
- EDMA_ERR_LNK_DATA_TX |
- EDMA_ERR_TRANS_PROTO),
+ EDMA_ERR_OVERRUN_5 = (1 << 5),
+ EDMA_ERR_UNDERRUN_5 = (1 << 6),
+ EDMA_EH_FREEZE = EDMA_ERR_D_PAR |
+ EDMA_ERR_PRD_PAR |
+ EDMA_ERR_DEV_DCON |
+ EDMA_ERR_DEV_CON |
+ EDMA_ERR_SERR |
+ EDMA_ERR_SELF_DIS |
+ EDMA_ERR_CRBQ_PAR |
+ EDMA_ERR_CRPB_PAR |
+ EDMA_ERR_INTRL_PAR |
+ EDMA_ERR_IORDY |
+ EDMA_ERR_LNK_CTRL_RX_2 |
+ EDMA_ERR_LNK_DATA_RX |
+ EDMA_ERR_LNK_DATA_TX |
+ EDMA_ERR_TRANS_PROTO,
+ EDMA_EH_FREEZE_5 = EDMA_ERR_D_PAR |
+ EDMA_ERR_PRD_PAR |
+ EDMA_ERR_DEV_DCON |
+ EDMA_ERR_DEV_CON |
+ EDMA_ERR_OVERRUN_5 |
+ EDMA_ERR_UNDERRUN_5 |
+ EDMA_ERR_SELF_DIS_5 |
+ EDMA_ERR_CRBQ_PAR |
+ EDMA_ERR_CRPB_PAR |
+ EDMA_ERR_INTRL_PAR |
+ EDMA_ERR_IORDY,
EDMA_REQ_Q_BASE_HI_OFS = 0x10,
EDMA_REQ_Q_IN_PTR_OFS = 0x14, /* also contains BASE_LO */
@@ -282,18 +301,18 @@ enum {
MV_HP_ERRATA_60X1B2 = (1 << 3),
MV_HP_ERRATA_60X1C0 = (1 << 4),
MV_HP_ERRATA_XX42A0 = (1 << 5),
- MV_HP_50XX = (1 << 6),
- MV_HP_GEN_IIE = (1 << 7),
+ MV_HP_GEN_I = (1 << 6),
+ MV_HP_GEN_II = (1 << 7),
+ MV_HP_GEN_IIE = (1 << 8),
/* Port private flags (pp_flags) */
MV_PP_FLAG_EDMA_EN = (1 << 0),
MV_PP_FLAG_EDMA_DS_ACT = (1 << 1),
+ MV_PP_FLAG_HAD_A_RESET = (1 << 2),
};
-#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
-#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
-#define IS_GEN_I(hpriv) IS_50XX(hpriv)
-#define IS_GEN_II(hpriv) IS_60XX(hpriv)
+#define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
+#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
enum {
@@ -352,6 +371,10 @@ struct mv_port_priv {
dma_addr_t crpb_dma;
struct mv_sg *sg_tbl;
dma_addr_t sg_tbl_dma;
+
+ unsigned int req_idx;
+ unsigned int resp_idx;
+
u32 pp_flags;
};
@@ -384,14 +407,15 @@ static u32 mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
static u32 mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in);
static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
-static void mv_phy_reset(struct ata_port *ap);
-static void __mv_phy_reset(struct ata_port *ap, int can_sleep);
static int mv_port_start(struct ata_port *ap);
static void mv_port_stop(struct ata_port *ap);
static void mv_qc_prep(struct ata_queued_cmd *qc);
static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
-static void mv_eng_timeout(struct ata_port *ap);
+static void mv_error_handler(struct ata_port *ap);
+static void mv_post_int_cmd(struct ata_queued_cmd *qc);
+static void mv_eh_freeze(struct ata_port *ap);
+static void mv_eh_thaw(struct ata_port *ap);
static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
@@ -415,14 +439,31 @@ static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
unsigned int port_no);
-static void mv_stop_and_reset(struct ata_port *ap);
-static struct scsi_host_template mv_sht = {
+static struct scsi_host_template mv5_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = MV_MAX_SG_CT,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = 1,
+ .proc_name = DRV_NAME,
+ .dma_boundary = MV_DMA_BOUNDARY,
+ .slave_configure = ata_scsi_slave_config,
+ .slave_destroy = ata_scsi_slave_destroy,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct scsi_host_template mv6_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
- .can_queue = MV_USE_Q_DEPTH,
+ .can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = MV_MAX_SG_CT,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
@@ -444,19 +485,21 @@ static const struct ata_port_operations mv5_ops = {
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
- .phy_reset = mv_phy_reset,
.cable_detect = ata_cable_sata,
.qc_prep = mv_qc_prep,
.qc_issue = mv_qc_issue,
.data_xfer = ata_data_xfer,
- .eng_timeout = mv_eng_timeout,
-
.irq_clear = mv_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
+ .error_handler = mv_error_handler,
+ .post_internal_cmd = mv_post_int_cmd,
+ .freeze = mv_eh_freeze,
+ .thaw = mv_eh_thaw,
+
.scr_read = mv5_scr_read,
.scr_write = mv5_scr_write,
@@ -473,19 +516,21 @@ static const struct ata_port_operations mv6_ops = {
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
- .phy_reset = mv_phy_reset,
.cable_detect = ata_cable_sata,
.qc_prep = mv_qc_prep,
.qc_issue = mv_qc_issue,
.data_xfer = ata_data_xfer,
- .eng_timeout = mv_eng_timeout,
-
.irq_clear = mv_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
+ .error_handler = mv_error_handler,
+ .post_internal_cmd = mv_post_int_cmd,
+ .freeze = mv_eh_freeze,
+ .thaw = mv_eh_thaw,
+
.scr_read = mv_scr_read,
.scr_write = mv_scr_write,
@@ -502,19 +547,21 @@ static const struct ata_port_operations mv_iie_ops = {
.exec_command = ata_exec_command,
.dev_select = ata_std_dev_select,
- .phy_reset = mv_phy_reset,
.cable_detect = ata_cable_sata,
.qc_prep = mv_qc_prep_iie,
.qc_issue = mv_qc_issue,
.data_xfer = ata_data_xfer,
- .eng_timeout = mv_eng_timeout,
-
.irq_clear = mv_irq_clear,
.irq_on = ata_irq_on,
.irq_ack = ata_irq_ack,
+ .error_handler = mv_error_handler,
+ .post_internal_cmd = mv_post_int_cmd,
+ .freeze = mv_eh_freeze,
+ .thaw = mv_eh_thaw,
+
.scr_read = mv_scr_read,
.scr_write = mv_scr_write,
@@ -526,44 +573,44 @@ static const struct ata_port_info mv_port_info[] = {
{ /* chip_504x */
.flags = MV_COMMON_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_508x */
- .flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+ .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_5080 */
- .flags = (MV_COMMON_FLAGS | MV_FLAG_DUAL_HC),
+ .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv5_ops,
},
{ /* chip_604x */
- .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv6_ops,
},
{ /* chip_608x */
- .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS |
- MV_FLAG_DUAL_HC),
+ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+ MV_FLAG_DUAL_HC,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv6_ops,
},
{ /* chip_6042 */
- .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv_iie_ops,
},
{ /* chip_7042 */
- .flags = (MV_COMMON_FLAGS | MV_6XXX_FLAGS),
+ .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &mv_iie_ops,
},
};
@@ -582,6 +629,9 @@ static const struct pci_device_id mv_pci_tbl[] = {
{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
+ /* Adaptec 1430SA */
+ { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
+
{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
/* add Marvell 7042 support */
@@ -706,6 +756,46 @@ static void mv_irq_clear(struct ata_port *ap)
{
}
+static void mv_set_edma_ptrs(void __iomem *port_mmio,
+ struct mv_host_priv *hpriv,
+ struct mv_port_priv *pp)
+{
+ u32 index;
+
+ /*
+ * initialize request queue
+ */
+ index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
+
+ WARN_ON(pp->crqb_dma & 0x3ff);
+ writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
+ writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
+ port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+
+ if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
+ writelfl((pp->crqb_dma & 0xffffffff) | index,
+ port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+ else
+ writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+
+ /*
+ * initialize response queue
+ */
+ index = (pp->resp_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_RSP_Q_PTR_SHIFT;
+
+ WARN_ON(pp->crpb_dma & 0xff);
+ writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
+
+ if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
+ writelfl((pp->crpb_dma & 0xffffffff) | index,
+ port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+ else
+ writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
+
+ writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
+ port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+}
+
/**
* mv_start_dma - Enable eDMA engine
* @base: port base address
@@ -717,9 +807,15 @@ static void mv_irq_clear(struct ata_port *ap)
* LOCKING:
* Inherited from caller.
*/
-static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
+static void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv,
+ struct mv_port_priv *pp)
{
- if (!(MV_PP_FLAG_EDMA_EN & pp->pp_flags)) {
+ if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
+ /* clear EDMA event indicators, if any */
+ writelfl(0, base + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ mv_set_edma_ptrs(base, hpriv, pp);
+
writelfl(EDMA_EN, base + EDMA_CMD_OFS);
pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
}
@@ -736,14 +832,14 @@ static void mv_start_dma(void __iomem *base, struct mv_port_priv *pp)
* LOCKING:
* Inherited from caller.
*/
-static void mv_stop_dma(struct ata_port *ap)
+static int mv_stop_dma(struct ata_port *ap)
{
void __iomem *port_mmio = mv_ap_base(ap);
struct mv_port_priv *pp = ap->private_data;
u32 reg;
- int i;
+ int i, err = 0;
- if (MV_PP_FLAG_EDMA_EN & pp->pp_flags) {
+ if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
/* Disable EDMA if active. The disable bit auto clears.
*/
writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS);
@@ -755,16 +851,18 @@ static void mv_stop_dma(struct ata_port *ap)
/* now properly wait for the eDMA to stop */
for (i = 1000; i > 0; i--) {
reg = readl(port_mmio + EDMA_CMD_OFS);
- if (!(EDMA_EN & reg)) {
+ if (!(reg & EDMA_EN))
break;
- }
+
udelay(100);
}
- if (EDMA_EN & reg) {
+ if (reg & EDMA_EN) {
ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
- /* FIXME: Consider doing a reset here to recover */
+ err = -EIO;
}
+
+ return err;
}
#ifdef ATA_DEBUG
@@ -881,12 +979,13 @@ static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
writelfl(val, mv_ap_base(ap) + ofs);
}
-static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
+static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
+ void __iomem *port_mmio)
{
u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
/* set up non-NCQ EDMA configuration */
- cfg &= ~(1 << 9); /* disable equeue */
+ cfg &= ~(1 << 9); /* disable eQue */
if (IS_GEN_I(hpriv)) {
cfg &= ~0x1f; /* clear queue depth */
@@ -906,7 +1005,7 @@ static void mv_edma_cfg(struct mv_host_priv *hpriv, void __iomem *port_mmio)
cfg |= (1 << 18); /* enab early completion */
cfg |= (1 << 17); /* enab cut-through (dis stor&forwrd) */
cfg &= ~(1 << 16); /* dis FIS-based switching (for now) */
- cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
+ cfg &= ~(EDMA_CFG_NCQ); /* clear NCQ */
}
writelfl(cfg, port_mmio + EDMA_CFG_OFS);
@@ -968,28 +1067,9 @@ static int mv_port_start(struct ata_port *ap)
pp->sg_tbl = mem;
pp->sg_tbl_dma = mem_dma;
- mv_edma_cfg(hpriv, port_mmio);
+ mv_edma_cfg(ap, hpriv, port_mmio);
- writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
- writelfl(pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK,
- port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-
- if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
- writelfl(pp->crqb_dma & 0xffffffff,
- port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
- else
- writelfl(0, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
-
- writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
-
- if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
- writelfl(pp->crpb_dma & 0xffffffff,
- port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
- else
- writelfl(0, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
-
- writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
- port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
+ mv_set_edma_ptrs(port_mmio, hpriv, pp);
/* Don't turn on EDMA here...do it before DMA commands only. Else
* we'll be unable to send non-data, PIO, etc due to restricted access
@@ -1052,11 +1132,6 @@ static unsigned int mv_fill_sg(struct ata_queued_cmd *qc)
return n_sg;
}
-static inline unsigned mv_inc_q_index(unsigned index)
-{
- return (index + 1) & MV_MAX_Q_DEPTH_MASK;
-}
-
static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
{
u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
@@ -1085,7 +1160,7 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
u16 flags = 0;
unsigned in_index;
- if (ATA_PROT_DMA != qc->tf.protocol)
+ if (qc->tf.protocol != ATA_PROT_DMA)
return;
/* Fill in command request block
@@ -1094,10 +1169,10 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
flags |= CRQB_FLAG_READ;
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT;
+ flags |= qc->tag << CRQB_IOID_SHIFT; /* 50xx appears to ignore this*/
- /* get current queue index from hardware */
- in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
- >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+ /* get current queue index from software */
+ in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
pp->crqb[in_index].sg_addr =
cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
@@ -1177,7 +1252,7 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
unsigned in_index;
u32 flags = 0;
- if (ATA_PROT_DMA != qc->tf.protocol)
+ if (qc->tf.protocol != ATA_PROT_DMA)
return;
/* Fill in Gen IIE command request block
@@ -1187,10 +1262,11 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
flags |= qc->tag << CRQB_TAG_SHIFT;
+ flags |= qc->tag << CRQB_IOID_SHIFT; /* "I/O Id" is -really-
+ what we use as our tag */
- /* get current queue index from hardware */
- in_index = (readl(mv_ap_base(ap) + EDMA_REQ_Q_IN_PTR_OFS)
- >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+ /* get current queue index from software */
+ in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
@@ -1238,83 +1314,41 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
*/
static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
{
- void __iomem *port_mmio = mv_ap_base(qc->ap);
- struct mv_port_priv *pp = qc->ap->private_data;
- unsigned in_index;
- u32 in_ptr;
+ struct ata_port *ap = qc->ap;
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct mv_port_priv *pp = ap->private_data;
+ struct mv_host_priv *hpriv = ap->host->private_data;
+ u32 in_index;
- if (ATA_PROT_DMA != qc->tf.protocol) {
+ if (qc->tf.protocol != ATA_PROT_DMA) {
/* We're about to send a non-EDMA capable command to the
* port. Turn off EDMA so there won't be problems accessing
* shadow block, etc registers.
*/
- mv_stop_dma(qc->ap);
+ mv_stop_dma(ap);
return ata_qc_issue_prot(qc);
}
- in_ptr = readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
- in_index = (in_ptr >> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+ mv_start_dma(port_mmio, hpriv, pp);
+
+ in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
/* until we do queuing, the queue should be empty at this point */
WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
- in_index = mv_inc_q_index(in_index); /* now incr producer index */
+ pp->req_idx++;
- mv_start_dma(port_mmio, pp);
+ in_index = (pp->req_idx & MV_MAX_Q_DEPTH_MASK) << EDMA_REQ_Q_PTR_SHIFT;
/* and write the request in pointer to kick the EDMA to life */
- in_ptr &= EDMA_REQ_Q_BASE_LO_MASK;
- in_ptr |= in_index << EDMA_REQ_Q_PTR_SHIFT;
- writelfl(in_ptr, port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
+ writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index,
+ port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
return 0;
}
/**
- * mv_get_crpb_status - get status from most recently completed cmd
- * @ap: ATA channel to manipulate
- *
- * This routine is for use when the port is in DMA mode, when it
- * will be using the CRPB (command response block) method of
- * returning command completion information. We check indices
- * are good, grab status, and bump the response consumer index to
- * prove that we're up to date.
- *
- * LOCKING:
- * Inherited from caller.
- */
-static u8 mv_get_crpb_status(struct ata_port *ap)
-{
- void __iomem *port_mmio = mv_ap_base(ap);
- struct mv_port_priv *pp = ap->private_data;
- unsigned out_index;
- u32 out_ptr;
- u8 ata_status;
-
- out_ptr = readl(port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
- out_index = (out_ptr >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
-
- ata_status = le16_to_cpu(pp->crpb[out_index].flags)
- >> CRPB_FLAG_STATUS_SHIFT;
-
- /* increment our consumer index... */
- out_index = mv_inc_q_index(out_index);
-
- /* and, until we do NCQ, there should only be 1 CRPB waiting */
- WARN_ON(out_index != ((readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
- >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
-
- /* write out our inc'd consumer index so EDMA knows we're caught up */
- out_ptr &= EDMA_RSP_Q_BASE_LO_MASK;
- out_ptr |= out_index << EDMA_RSP_Q_PTR_SHIFT;
- writelfl(out_ptr, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
-
- /* Return ATA status register for completed CRPB */
- return ata_status;
-}
-
-/**
* mv_err_intr - Handle error interrupts on the port
* @ap: ATA channel to manipulate
* @reset_allowed: bool: 0 == don't trigger from reset here
@@ -1328,30 +1362,191 @@ static u8 mv_get_crpb_status(struct ata_port *ap)
* LOCKING:
* Inherited from caller.
*/
-static void mv_err_intr(struct ata_port *ap, int reset_allowed)
+static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
{
void __iomem *port_mmio = mv_ap_base(ap);
- u32 edma_err_cause, serr = 0;
+ u32 edma_err_cause, eh_freeze_mask, serr = 0;
+ struct mv_port_priv *pp = ap->private_data;
+ struct mv_host_priv *hpriv = ap->host->private_data;
+ unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
+ unsigned int action = 0, err_mask = 0;
+ struct ata_eh_info *ehi = &ap->eh_info;
- edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+ ata_ehi_clear_desc(ehi);
- if (EDMA_ERR_SERR & edma_err_cause) {
+ if (!edma_enabled) {
+ /* just a guess: do we need to do this? should we
+ * expand this, and do it in all cases?
+ */
sata_scr_read(ap, SCR_ERROR, &serr);
sata_scr_write_flush(ap, SCR_ERROR, serr);
}
- if (EDMA_ERR_SELF_DIS & edma_err_cause) {
- struct mv_port_priv *pp = ap->private_data;
- pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+
+ edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ ata_ehi_push_desc(ehi, "edma_err 0x%08x", edma_err_cause);
+
+ /*
+ * all generations share these EDMA error cause bits
+ */
+
+ if (edma_err_cause & EDMA_ERR_DEV)
+ err_mask |= AC_ERR_DEV;
+ if (edma_err_cause & (EDMA_ERR_D_PAR | EDMA_ERR_PRD_PAR |
+ EDMA_ERR_CRBQ_PAR | EDMA_ERR_CRPB_PAR |
+ EDMA_ERR_INTRL_PAR)) {
+ err_mask |= AC_ERR_ATA_BUS;
+ action |= ATA_EH_HARDRESET;
+ ata_ehi_push_desc(ehi, ", parity error");
+ }
+ if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
+ ata_ehi_hotplugged(ehi);
+ ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
+ ", dev disconnect" : ", dev connect");
+ }
+
+ if (IS_GEN_I(hpriv)) {
+ eh_freeze_mask = EDMA_EH_FREEZE_5;
+
+ if (edma_err_cause & EDMA_ERR_SELF_DIS_5) {
+ struct mv_port_priv *pp = ap->private_data;
+ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ ata_ehi_push_desc(ehi, ", EDMA self-disable");
+ }
+ } else {
+ eh_freeze_mask = EDMA_EH_FREEZE;
+
+ if (edma_err_cause & EDMA_ERR_SELF_DIS) {
+ struct mv_port_priv *pp = ap->private_data;
+ pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ ata_ehi_push_desc(ehi, ", EDMA self-disable");
+ }
+
+ if (edma_err_cause & EDMA_ERR_SERR) {
+ sata_scr_read(ap, SCR_ERROR, &serr);
+ sata_scr_write_flush(ap, SCR_ERROR, serr);
+ err_mask = AC_ERR_ATA_BUS;
+ action |= ATA_EH_HARDRESET;
+ }
}
- DPRINTK(KERN_ERR "ata%u: port error; EDMA err cause: 0x%08x "
- "SERR: 0x%08x\n", ap->print_id, edma_err_cause, serr);
/* Clear EDMA now that SERR cleanup done */
writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
- /* check for fatal here and recover if needed */
- if (reset_allowed && (EDMA_ERR_FATAL & edma_err_cause))
- mv_stop_and_reset(ap);
+ if (!err_mask) {
+ err_mask = AC_ERR_OTHER;
+ action |= ATA_EH_HARDRESET;
+ }
+
+ ehi->serror |= serr;
+ ehi->action |= action;
+
+ if (qc)
+ qc->err_mask |= err_mask;
+ else
+ ehi->err_mask |= err_mask;
+
+ if (edma_err_cause & eh_freeze_mask)
+ ata_port_freeze(ap);
+ else
+ ata_port_abort(ap);
+}
+
+static void mv_intr_pio(struct ata_port *ap)
+{
+ struct ata_queued_cmd *qc;
+ u8 ata_status;
+
+ /* ignore spurious intr if drive still BUSY */
+ ata_status = readb(ap->ioaddr.status_addr);
+ if (unlikely(ata_status & ATA_BUSY))
+ return;
+
+ /* get active ATA command */
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (unlikely(!qc)) /* no active tag */
+ return;
+ if (qc->tf.flags & ATA_TFLAG_POLLING) /* polling; we don't own qc */
+ return;
+
+ /* and finally, complete the ATA command */
+ qc->err_mask |= ac_err_mask(ata_status);
+ ata_qc_complete(qc);
+}
+
+static void mv_intr_edma(struct ata_port *ap)
+{
+ void __iomem *port_mmio = mv_ap_base(ap);
+ struct mv_host_priv *hpriv = ap->host->private_data;
+ struct mv_port_priv *pp = ap->private_data;
+ struct ata_queued_cmd *qc;
+ u32 out_index, in_index;
+ bool work_done = false;
+
+ /* get h/w response queue pointer */
+ in_index = (readl(port_mmio + EDMA_RSP_Q_IN_PTR_OFS)
+ >> EDMA_RSP_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
+
+ while (1) {
+ u16 status;
+
+ /* get s/w response queue last-read pointer, and compare */
+ out_index = pp->resp_idx & MV_MAX_Q_DEPTH_MASK;
+ if (in_index == out_index)
+ break;
+
+
+ /* 50xx: get active ATA command */
+ if (IS_GEN_I(hpriv))
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+
+ /* 60xx: get active ATA command via tag, to enable support
+ * for queueing. this works transparently for queued and
+ * non-queued modes.
+ */
+ else {
+ unsigned int tag;
+
+ if (IS_GEN_II(hpriv))
+ tag = (le16_to_cpu(pp->crpb[out_index].id)
+ >> CRPB_IOID_SHIFT_6) & 0x3f;
+ else
+ tag = (le16_to_cpu(pp->crpb[out_index].id)
+ >> CRPB_IOID_SHIFT_7) & 0x3f;
+
+ qc = ata_qc_from_tag(ap, tag);
+ }
+
+ /* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
+ * bits (WARNING: might not necessarily be associated
+ * with this command), which -should- be clear
+ * if all is well
+ */
+ status = le16_to_cpu(pp->crpb[out_index].flags);
+ if (unlikely(status & 0xff)) {
+ mv_err_intr(ap, qc);
+ return;
+ }
+
+ /* and finally, complete the ATA command */
+ if (qc) {
+ qc->err_mask |=
+ ac_err_mask(status >> CRPB_FLAG_STATUS_SHIFT);
+ ata_qc_complete(qc);
+ }
+
+ /* advance software response queue pointer, to
+ * indicate (after the loop completes) to hardware
+ * that we have consumed a response queue entry.
+ */
+ work_done = true;
+ pp->resp_idx++;
+ }
+
+ if (work_done)
+ writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
+ (out_index << EDMA_RSP_Q_PTR_SHIFT),
+ port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
}
/**
@@ -1374,10 +1569,8 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
{
void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
void __iomem *hc_mmio = mv_hc_base(mmio, hc);
- struct ata_queued_cmd *qc;
u32 hc_irq_cause;
- int shift, port, port0, hard_port, handled;
- unsigned int err_mask;
+ int port, port0;
if (hc == 0)
port0 = 0;
@@ -1386,79 +1579,95 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc)
/* we'll need the HC success int register in most cases */
hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
- if (hc_irq_cause)
- writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+ if (!hc_irq_cause)
+ return;
+
+ writelfl(~hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n",
hc,relevant,hc_irq_cause);
for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) {
- u8 ata_status = 0;
struct ata_port *ap = host->ports[port];
struct mv_port_priv *pp = ap->private_data;
+ int have_err_bits, hard_port, shift;
+
+ if ((!ap) || (ap->flags & ATA_FLAG_DISABLED))
+ continue;
+
+ shift = port << 1; /* (port * 2) */
+ if (port >= MV_PORTS_PER_HC) {
+ shift++; /* skip bit 8 in the HC Main IRQ reg */
+ }
+ have_err_bits = ((PORT0_ERR << shift) & relevant);
+
+ if (unlikely(have_err_bits)) {
+ struct ata_queued_cmd *qc;
+
+ qc = ata_qc_from_tag(ap, ap->active_tag);
+ if (qc && (qc->tf.flags & ATA_TFLAG_POLLING))
+ continue;
+
+ mv_err_intr(ap, qc);
+ continue;
+ }
hard_port = mv_hardport_from_port(port); /* range 0..3 */
- handled = 0; /* ensure ata_status is set if handled++ */
- /* Note that DEV_IRQ might happen spuriously during EDMA,
- * and should be ignored in such cases.
- * The cause of this is still under investigation.
- */
if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
- /* EDMA: check for response queue interrupt */
- if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
- ata_status = mv_get_crpb_status(ap);
- handled = 1;
- }
+ if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause)
+ mv_intr_edma(ap);
} else {
- /* PIO: check for device (drive) interrupt */
- if ((DEV_IRQ << hard_port) & hc_irq_cause) {
- ata_status = readb(ap->ioaddr.status_addr);
- handled = 1;
- /* ignore spurious intr if drive still BUSY */
- if (ata_status & ATA_BUSY) {
- ata_status = 0;
- handled = 0;
- }
- }
+ if ((DEV_IRQ << hard_port) & hc_irq_cause)
+ mv_intr_pio(ap);
}
+ }
+ VPRINTK("EXIT\n");
+}
- if (ap && (ap->flags & ATA_FLAG_DISABLED))
- continue;
+static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
+{
+ struct ata_port *ap;
+ struct ata_queued_cmd *qc;
+ struct ata_eh_info *ehi;
+ unsigned int i, err_mask, printed = 0;
+ u32 err_cause;
- err_mask = ac_err_mask(ata_status);
+ err_cause = readl(mmio + PCI_IRQ_CAUSE_OFS);
- shift = port << 1; /* (port * 2) */
- if (port >= MV_PORTS_PER_HC) {
- shift++; /* skip bit 8 in the HC Main IRQ reg */
- }
- if ((PORT0_ERR << shift) & relevant) {
- mv_err_intr(ap, 1);
- err_mask |= AC_ERR_OTHER;
- handled = 1;
- }
+ dev_printk(KERN_ERR, host->dev, "PCI ERROR; PCI IRQ cause=0x%08x\n",
+ err_cause);
+
+ DPRINTK("All regs @ PCI error\n");
+ mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
- if (handled) {
+ writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
+
+ for (i = 0; i < host->n_ports; i++) {
+ ap = host->ports[i];
+ if (!ata_port_offline(ap)) {
+ ehi = &ap->eh_info;
+ ata_ehi_clear_desc(ehi);
+ if (!printed++)
+ ata_ehi_push_desc(ehi,
+ "PCI err cause 0x%08x", err_cause);
+ err_mask = AC_ERR_HOST_BUS;
+ ehi->action = ATA_EH_HARDRESET;
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (qc && (qc->flags & ATA_QCFLAG_ACTIVE)) {
- VPRINTK("port %u IRQ found for qc, "
- "ata_status 0x%x\n", port,ata_status);
- /* mark qc status appropriately */
- if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
- qc->err_mask |= err_mask;
- ata_qc_complete(qc);
- }
- }
+ if (qc)
+ qc->err_mask |= err_mask;
+ else
+ ehi->err_mask |= err_mask;
+
+ ata_port_freeze(ap);
}
}
- VPRINTK("EXIT\n");
}
/**
- * mv_interrupt -
+ * mv_interrupt - Main interrupt event handler
* @irq: unused
* @dev_instance: private data; in this case the host structure
- * @regs: unused
*
* Read the read only register to determine if any host
* controllers have pending interrupts. If so, call lower level
@@ -1474,7 +1683,6 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
struct ata_host *host = dev_instance;
unsigned int hc, handled = 0, n_hcs;
void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
- struct mv_host_priv *hpriv;
u32 irq_stat;
irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
@@ -1488,34 +1696,21 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
n_hcs = mv_get_hc_count(host->ports[0]->flags);
spin_lock(&host->lock);
+ if (unlikely(irq_stat & PCI_ERR)) {
+ mv_pci_error(host, mmio);
+ handled = 1;
+ goto out_unlock; /* skip all other HC irq handling */
+ }
+
for (hc = 0; hc < n_hcs; hc++) {
u32 relevant = irq_stat & (HC0_IRQ_PEND << (hc * HC_SHIFT));
if (relevant) {
mv_host_intr(host, relevant, hc);
- handled++;
- }
- }
-
- hpriv = host->private_data;
- if (IS_60XX(hpriv)) {
- /* deal with the interrupt coalescing bits */
- if (irq_stat & (TRAN_LO_DONE | TRAN_HI_DONE | PORTS_0_7_COAL_DONE)) {
- writelfl(0, mmio + MV_IRQ_COAL_CAUSE_LO);
- writelfl(0, mmio + MV_IRQ_COAL_CAUSE_HI);
- writelfl(0, mmio + MV_IRQ_COAL_CAUSE);
+ handled = 1;
}
}
- if (PCI_ERR & irq_stat) {
- printk(KERN_ERR DRV_NAME ": PCI ERROR; PCI IRQ cause=0x%08x\n",
- readl(mmio + PCI_IRQ_CAUSE_OFS));
-
- DPRINTK("All regs @ PCI error\n");
- mv_dump_all_regs(mmio, -1, to_pci_dev(host->dev));
-
- writelfl(0, mmio + PCI_IRQ_CAUSE_OFS);
- handled++;
- }
+out_unlock:
spin_unlock(&host->lock);
return IRQ_RETVAL(handled);
@@ -1570,12 +1765,9 @@ static void mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
{
- u8 rev_id;
int early_5080;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
- early_5080 = (pdev->device == 0x5080) && (rev_id == 0);
+ early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
if (!early_5080) {
u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
@@ -1904,7 +2096,7 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
- if (IS_60XX(hpriv)) {
+ if (IS_GEN_II(hpriv)) {
u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
ifctl |= (1 << 7); /* enable gen2i speed */
ifctl = (ifctl & 0xfff) | 0x9b1000; /* from chip spec */
@@ -1920,32 +2112,12 @@ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
hpriv->ops->phy_errata(hpriv, mmio, port_no);
- if (IS_50XX(hpriv))
+ if (IS_GEN_I(hpriv))
mdelay(1);
}
-static void mv_stop_and_reset(struct ata_port *ap)
-{
- struct mv_host_priv *hpriv = ap->host->private_data;
- void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
-
- mv_stop_dma(ap);
-
- mv_channel_reset(hpriv, mmio, ap->port_no);
-
- __mv_phy_reset(ap, 0);
-}
-
-static inline void __msleep(unsigned int msec, int can_sleep)
-{
- if (can_sleep)
- msleep(msec);
- else
- mdelay(msec);
-}
-
/**
- * __mv_phy_reset - Perform eDMA reset followed by COMRESET
+ * mv_phy_reset - Perform eDMA reset followed by COMRESET
* @ap: ATA channel to manipulate
*
* Part of this is taken from __sata_phy_reset and modified to
@@ -1955,14 +2127,12 @@ static inline void __msleep(unsigned int msec, int can_sleep)
* Inherited from caller. This is coded to safe to call at
* interrupt level, i.e. it does not sleep.
*/
-static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
+static void mv_phy_reset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
struct mv_port_priv *pp = ap->private_data;
struct mv_host_priv *hpriv = ap->host->private_data;
void __iomem *port_mmio = mv_ap_base(ap);
- struct ata_taskfile tf;
- struct ata_device *dev = &ap->device[0];
- unsigned long timeout;
int retry = 5;
u32 sstatus;
@@ -1975,22 +2145,21 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep)
/* Issue COMRESET via SControl */
comreset_retry:
sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
- __msleep(1, can_sleep);
+ msleep(1);
sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
- __msleep(20, can_sleep);
+ msleep(20);
- timeout = jiffies + msecs_to_jiffies(200);
do {
sata_scr_read(ap, SCR_STATUS, &sstatus);
if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0))
break;
- __msleep(1, can_sleep);
- } while (time_before(jiffies, timeout));
+ msleep(1);
+ } while (time_before(jiffies, deadline));
/* work around errata */
- if (IS_60XX(hpriv) &&
+ if (IS_GEN_II(hpriv) &&
(sstatus != 0x0) && (sstatus != 0x113) && (sstatus != 0x123) &&
(retry-- > 0))
goto comreset_retry;
@@ -1999,13 +2168,8 @@ comreset_retry:
"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
- if (ata_port_online(ap)) {
- ata_port_probe(ap);
- } else {
- sata_scr_read(ap, SCR_STATUS, &sstatus);
- ata_port_printk(ap, KERN_INFO,
- "no device found (phy stat %08x)\n", sstatus);
- ata_port_disable(ap);
+ if (ata_port_offline(ap)) {
+ *class = ATA_DEV_NONE;
return;
}
@@ -2019,68 +2183,152 @@ comreset_retry:
u8 drv_stat = ata_check_status(ap);
if ((drv_stat != 0x80) && (drv_stat != 0x7f))
break;
- __msleep(500, can_sleep);
+ msleep(500);
if (retry-- <= 0)
break;
+ if (time_after(jiffies, deadline))
+ break;
}
- tf.lbah = readb(ap->ioaddr.lbah_addr);
- tf.lbam = readb(ap->ioaddr.lbam_addr);
- tf.lbal = readb(ap->ioaddr.lbal_addr);
- tf.nsect = readb(ap->ioaddr.nsect_addr);
+ /* FIXME: if we passed the deadline, the following
+ * code probably produces an invalid result
+ */
- dev->class = ata_dev_classify(&tf);
- if (!ata_dev_enabled(dev)) {
- VPRINTK("Port disabled post-sig: No device present.\n");
- ata_port_disable(ap);
- }
+ /* finally, read device signature from TF registers */
+ *class = ata_dev_try_classify(ap, 0, NULL);
writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
- pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
+ WARN_ON(pp->pp_flags & MV_PP_FLAG_EDMA_EN);
VPRINTK("EXIT\n");
}
-static void mv_phy_reset(struct ata_port *ap)
+static int mv_prereset(struct ata_port *ap, unsigned long deadline)
{
- __mv_phy_reset(ap, 1);
+ struct mv_port_priv *pp = ap->private_data;
+ struct ata_eh_context *ehc = &ap->eh_context;
+ int rc;
+
+ rc = mv_stop_dma(ap);
+ if (rc)
+ ehc->i.action |= ATA_EH_HARDRESET;
+
+ if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) {
+ pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
+ ehc->i.action |= ATA_EH_HARDRESET;
+ }
+
+ /* if we're about to do hardreset, nothing more to do */
+ if (ehc->i.action & ATA_EH_HARDRESET)
+ return 0;
+
+ if (ata_port_online(ap))
+ rc = ata_wait_ready(ap, deadline);
+ else
+ rc = -ENODEV;
+
+ return rc;
}
-/**
- * mv_eng_timeout - Routine called by libata when SCSI times out I/O
- * @ap: ATA channel to manipulate
- *
- * Intent is to clear all pending error conditions, reset the
- * chip/bus, fail the command, and move on.
- *
- * LOCKING:
- * This routine holds the host lock while failing the command.
- */
-static void mv_eng_timeout(struct ata_port *ap)
+static int mv_hardreset(struct ata_port *ap, unsigned int *class,
+ unsigned long deadline)
{
+ struct mv_host_priv *hpriv = ap->host->private_data;
void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
- struct ata_queued_cmd *qc;
- unsigned long flags;
- ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
- DPRINTK("All regs @ start of eng_timeout\n");
- mv_dump_all_regs(mmio, ap->port_no, to_pci_dev(ap->host->dev));
+ mv_stop_dma(ap);
- qc = ata_qc_from_tag(ap, ap->active_tag);
- printk(KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n",
- mmio, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
+ mv_channel_reset(hpriv, mmio, ap->port_no);
- spin_lock_irqsave(&ap->host->lock, flags);
- mv_err_intr(ap, 0);
- mv_stop_and_reset(ap);
- spin_unlock_irqrestore(&ap->host->lock, flags);
+ mv_phy_reset(ap, class, deadline);
- WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
- if (qc->flags & ATA_QCFLAG_ACTIVE) {
- qc->err_mask |= AC_ERR_TIMEOUT;
- ata_eh_qc_complete(qc);
+ return 0;
+}
+
+static void mv_postreset(struct ata_port *ap, unsigned int *classes)
+{
+ u32 serr;
+
+ /* print link status */
+ sata_print_link_status(ap);
+
+ /* clear SError */
+ sata_scr_read(ap, SCR_ERROR, &serr);
+ sata_scr_write_flush(ap, SCR_ERROR, serr);
+
+ /* bail out if no device is present */
+ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
+ DPRINTK("EXIT, no device\n");
+ return;
}
+
+ /* set up device control */
+ iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
+}
+
+static void mv_error_handler(struct ata_port *ap)
+{
+ ata_do_eh(ap, mv_prereset, ata_std_softreset,
+ mv_hardreset, mv_postreset);
+}
+
+static void mv_post_int_cmd(struct ata_queued_cmd *qc)
+{
+ mv_stop_dma(qc->ap);
+}
+
+static void mv_eh_freeze(struct ata_port *ap)
+{
+ void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+ unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+ u32 tmp, mask;
+ unsigned int shift;
+
+ /* FIXME: handle coalescing completion events properly */
+
+ shift = ap->port_no * 2;
+ if (hc > 0)
+ shift++;
+
+ mask = 0x3 << shift;
+
+ /* disable assertion of portN err, done events */
+ tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
+ writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS);
+}
+
+static void mv_eh_thaw(struct ata_port *ap)
+{
+ void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+ unsigned int hc = (ap->port_no > 3) ? 1 : 0;
+ void __iomem *hc_mmio = mv_hc_base(mmio, hc);
+ void __iomem *port_mmio = mv_ap_base(ap);
+ u32 tmp, mask, hc_irq_cause;
+ unsigned int shift, hc_port_no = ap->port_no;
+
+ /* FIXME: handle coalescing completion events properly */
+
+ shift = ap->port_no * 2;
+ if (hc > 0) {
+ shift++;
+ hc_port_no -= 4;
+ }
+
+ mask = 0x3 << shift;
+
+ /* clear EDMA errors on this port */
+ writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+
+ /* clear pending irq events */
+ hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
+ hc_irq_cause &= ~(1 << hc_port_no); /* clear CRPB-done */
+ hc_irq_cause &= ~(1 << (hc_port_no + 8)); /* clear Device int */
+ writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
+
+ /* enable assertion of portN err, done events */
+ tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
+ writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS);
}
/**
@@ -2136,17 +2384,14 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
{
struct pci_dev *pdev = to_pci_dev(host->dev);
struct mv_host_priv *hpriv = host->private_data;
- u8 rev_id;
u32 hp_flags = hpriv->hp_flags;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
switch(board_idx) {
case chip_5080:
hpriv->ops = &mv5xxx_ops;
- hp_flags |= MV_HP_50XX;
+ hp_flags |= MV_HP_GEN_I;
- switch (rev_id) {
+ switch (pdev->revision) {
case 0x1:
hp_flags |= MV_HP_ERRATA_50XXB0;
break;
@@ -2164,9 +2409,9 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
case chip_504x:
case chip_508x:
hpriv->ops = &mv5xxx_ops;
- hp_flags |= MV_HP_50XX;
+ hp_flags |= MV_HP_GEN_I;
- switch (rev_id) {
+ switch (pdev->revision) {
case 0x0:
hp_flags |= MV_HP_ERRATA_50XXB0;
break;
@@ -2184,8 +2429,9 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
case chip_604x:
case chip_608x:
hpriv->ops = &mv6xxx_ops;
+ hp_flags |= MV_HP_GEN_II;
- switch (rev_id) {
+ switch (pdev->revision) {
case 0x7:
hp_flags |= MV_HP_ERRATA_60X1B2;
break;
@@ -2203,10 +2449,9 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
case chip_7042:
case chip_6042:
hpriv->ops = &mv6xxx_ops;
-
hp_flags |= MV_HP_GEN_IIE;
- switch (rev_id) {
+ switch (pdev->revision) {
case 0x0:
hp_flags |= MV_HP_ERRATA_XX42A0;
break;
@@ -2270,7 +2515,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
hpriv->ops->enable_leds(hpriv, mmio);
for (port = 0; port < host->n_ports; port++) {
- if (IS_60XX(hpriv)) {
+ if (IS_GEN_II(hpriv)) {
void __iomem *port_mmio = mv_port_base(mmio, port);
u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
@@ -2305,7 +2550,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
/* and unmask interrupt generation for host regs */
writelfl(PCI_UNMASK_ALL_IRQS, mmio + PCI_IRQ_MASK_OFS);
- if (IS_50XX(hpriv))
+ if (IS_GEN_I(hpriv))
writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS);
else
writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS);
@@ -2334,25 +2579,32 @@ static void mv_print_info(struct ata_host *host)
{
struct pci_dev *pdev = to_pci_dev(host->dev);
struct mv_host_priv *hpriv = host->private_data;
- u8 rev_id, scc;
- const char *scc_s;
+ u8 scc;
+ const char *scc_s, *gen;
/* Use this to determine the HW stepping of the chip so we know
* what errata to workaround
*/
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
-
pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &scc);
if (scc == 0)
scc_s = "SCSI";
else if (scc == 0x01)
scc_s = "RAID";
else
- scc_s = "unknown";
+ scc_s = "?";
+
+ if (IS_GEN_I(hpriv))
+ gen = "I";
+ else if (IS_GEN_II(hpriv))
+ gen = "II";
+ else if (IS_GEN_IIE(hpriv))
+ gen = "IIE";
+ else
+ gen = "?";
dev_printk(KERN_INFO, &pdev->dev,
- "%u slots %u ports %s mode IRQ via %s\n",
- (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
+ "Gen-%s %u slots %u ports %s mode IRQ via %s\n",
+ gen, (unsigned)MV_MAX_Q_DEPTH, host->n_ports,
scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
}
@@ -2414,8 +2666,9 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
mv_print_info(host);
pci_set_master(pdev);
+ pci_set_mwi(pdev);
return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
- &mv_sht);
+ IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
}
static int __init mv_init(void)
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index adfa693db53..db81e3efa5e 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -325,6 +325,7 @@ static struct scsi_host_template nv_adma_sht = {
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
+ .change_queue_depth = ata_scsi_change_queue_depth,
.can_queue = NV_ADMA_MAX_CPBS,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN,
@@ -1559,7 +1560,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
}
ppi[0] = &nv_port_info[type];
- rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+ rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
if (rc)
return rc;
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index 2b924a69b36..d2fcb9a6bec 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -45,8 +45,7 @@
#include "sata_promise.h"
#define DRV_NAME "sata_promise"
-#define DRV_VERSION "2.07"
-
+#define DRV_VERSION "2.09"
enum {
PDC_MAX_PORTS = 4,
@@ -94,7 +93,7 @@ enum {
board_20319 = 2, /* FastTrak S150 TX4 */
board_20619 = 3, /* FastTrak TX4000 */
board_2057x = 4, /* SATAII150 Tx2plus */
- board_2057x_pata = 5, /* SATAII150 Tx2plus */
+ board_2057x_pata = 5, /* SATAII150 Tx2plus PATA port */
board_40518 = 6, /* SATAII150 Tx4 */
PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */
@@ -124,7 +123,6 @@ enum {
PDC_FLAG_4_PORTS = (1 << 26), /* 4 ports */
};
-
struct pdc_port_priv {
u8 *pkt;
dma_addr_t pkt_dma;
@@ -252,7 +250,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_SATA_PATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_old_sata_ops,
},
@@ -261,7 +259,7 @@ static const struct ata_port_info pdc_port_info[] = {
.flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -271,7 +269,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_old_sata_ops,
},
@@ -281,7 +279,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -291,7 +289,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_sata_ops,
},
@@ -301,7 +299,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_GEN_II,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_pata_ops,
},
@@ -311,7 +309,7 @@ static const struct ata_port_info pdc_port_info[] = {
PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_sata_ops,
},
};
@@ -340,7 +338,6 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = {
{ } /* terminate list */
};
-
static struct pci_driver pdc_ata_pci_driver = {
.name = DRV_NAME,
.id_table = pdc_ata_pci_tbl,
@@ -348,7 +345,6 @@ static struct pci_driver pdc_ata_pci_driver = {
.remove = ata_pci_remove_one,
};
-
static int pdc_common_port_start(struct ata_port *ap)
{
struct device *dev = ap->host->dev;
@@ -382,7 +378,7 @@ static int pdc_sata_port_start(struct ata_port *ap)
/* fix up PHYMODE4 align timing */
if (ap->flags & PDC_FLAG_GEN_II) {
- void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr;
+ void __iomem *mmio = ap->ioaddr.scr_addr;
unsigned int tmp;
tmp = readl(mmio + 0x014);
@@ -418,7 +414,7 @@ static void pdc_reset_port(struct ata_port *ap)
static int pdc_pata_cable_detect(struct ata_port *ap)
{
u8 tmp;
- void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+ void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
tmp = readb(mmio);
if (tmp & 0x01)
@@ -438,7 +434,6 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
-
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
u32 val)
{
@@ -573,7 +568,7 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
static void pdc_freeze(struct ata_port *ap)
{
- void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+ void __iomem *mmio = ap->ioaddr.cmd_addr;
u32 tmp;
tmp = readl(mmio + PDC_CTLSTAT);
@@ -585,7 +580,7 @@ static void pdc_freeze(struct ata_port *ap)
static void pdc_thaw(struct ata_port *ap)
{
- void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+ void __iomem *mmio = ap->ioaddr.cmd_addr;
u32 tmp;
/* clear IRQ */
@@ -657,8 +652,8 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc,
ata_port_abort(ap);
}
-static inline unsigned int pdc_host_intr( struct ata_port *ap,
- struct ata_queued_cmd *qc)
+static inline unsigned int pdc_host_intr(struct ata_port *ap,
+ struct ata_queued_cmd *qc)
{
unsigned int handled = 0;
void __iomem *port_mmio = ap->ioaddr.cmd_addr;
@@ -685,10 +680,10 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
handled = 1;
break;
- default:
+ default:
ap->stats.idle_irq++;
break;
- }
+ }
return handled;
}
@@ -701,6 +696,18 @@ static void pdc_irq_clear(struct ata_port *ap)
readl(mmio + PDC_INT_SEQMASK);
}
+static inline int pdc_is_sataii_tx4(unsigned long flags)
+{
+ const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
+ return (flags & mask) == mask;
+}
+
+static inline unsigned int pdc_port_no_to_ata_no(unsigned int port_no, int is_sataii_tx4)
+{
+ static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+ return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
+}
+
static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
@@ -709,6 +716,9 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
unsigned int i, tmp;
unsigned int handled = 0;
void __iomem *mmio_base;
+ unsigned int hotplug_offset, ata_no;
+ u32 hotplug_status;
+ int is_sataii_tx4;
VPRINTK("ENTER\n");
@@ -719,10 +729,20 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
mmio_base = host->iomap[PDC_MMIO_BAR];
+ /* read and clear hotplug flags for all ports */
+ if (host->ports[0]->flags & PDC_FLAG_GEN_II)
+ hotplug_offset = PDC2_SATA_PLUG_CSR;
+ else
+ hotplug_offset = PDC_SATA_PLUG_CSR;
+ hotplug_status = readl(mmio_base + hotplug_offset);
+ if (hotplug_status & 0xff)
+ writel(hotplug_status | 0xff, mmio_base + hotplug_offset);
+ hotplug_status &= 0xff; /* clear uninteresting bits */
+
/* reading should also clear interrupts */
mask = readl(mmio_base + PDC_INT_SEQMASK);
- if (mask == 0xffffffff) {
+ if (mask == 0xffffffff && hotplug_status == 0) {
VPRINTK("QUICK EXIT 2\n");
return IRQ_NONE;
}
@@ -730,16 +750,34 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance)
spin_lock(&host->lock);
mask &= 0xffff; /* only 16 tags possible */
- if (!mask) {
+ if (mask == 0 && hotplug_status == 0) {
VPRINTK("QUICK EXIT 3\n");
goto done_irq;
}
writel(mask, mmio_base + PDC_INT_SEQMASK);
+ is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags);
+
for (i = 0; i < host->n_ports; i++) {
VPRINTK("port %u\n", i);
ap = host->ports[i];
+
+ /* check for a plug or unplug event */
+ ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
+ tmp = hotplug_status & (0x11 << ata_no);
+ if (tmp && ap &&
+ !(ap->flags & ATA_FLAG_DISABLED)) {
+ struct ata_eh_info *ehi = &ap->eh_info;
+ ata_ehi_clear_desc(ehi);
+ ata_ehi_hotplugged(ehi);
+ ata_ehi_push_desc(ehi, "hotplug_status %#x", tmp);
+ ata_port_freeze(ap);
+ ++handled;
+ continue;
+ }
+
+ /* check for a packet interrupt */
tmp = mask & (1 << (i + 1));
if (tmp && ap &&
!(ap->flags & ATA_FLAG_DISABLED)) {
@@ -784,9 +822,12 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
break;
/*FALLTHROUGH*/
+ case ATA_PROT_NODATA:
+ if (qc->tf.flags & ATA_TFLAG_POLLING)
+ break;
+ /*FALLTHROUGH*/
case ATA_PROT_ATAPI_DMA:
case ATA_PROT_DMA:
- case ATA_PROT_NODATA:
pdc_packet_start(qc);
return 0;
@@ -800,15 +841,14 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_tf_load(ap, tf);
}
-
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
WARN_ON (tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_NODATA);
+ tf->protocol == ATA_PROT_ATAPI_DMA);
ata_exec_command(ap, tf);
}
@@ -864,7 +904,6 @@ static void pdc_ata_setup_port(struct ata_port *ap,
ap->ioaddr.scr_addr = scr_addr;
}
-
static void pdc_host_init(struct ata_host *host)
{
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
@@ -894,9 +933,9 @@ static void pdc_host_init(struct ata_host *host)
tmp = readl(mmio + hotplug_offset);
writel(tmp | 0xff, mmio + hotplug_offset);
- /* mask plug/unplug ints */
+ /* unmask plug/unplug ints */
tmp = readl(mmio + hotplug_offset);
- writel(tmp | 0xff0000, mmio + hotplug_offset);
+ writel(tmp & ~0xff0000, mmio + hotplug_offset);
/* don't initialise TBG or SLEW on 2nd generation chips */
if (is_gen2)
@@ -952,10 +991,8 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
if (pi->flags & PDC_FLAG_SATA_PATA) {
u8 tmp = readb(base + PDC_FLASH_CTL+1);
- if (!(tmp & 0x80)) {
+ if (!(tmp & 0x80))
ppi[n_ports++] = pi + 1;
- dev_printk(KERN_INFO, &pdev->dev, "PATA port found\n");
- }
}
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
@@ -965,22 +1002,12 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
}
host->iomap = pcim_iomap_table(pdev);
- is_sataii_tx4 = 0;
- if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) {
- is_sataii_tx4 = 1;
- dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n");
- }
+ is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags);
for (i = 0; i < host->n_ports; i++) {
- static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
- int ata_nr;
-
- ata_nr = i;
- if (is_sataii_tx4)
- ata_nr = sataii_tx4_port_remap[i];
-
+ unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
pdc_ata_setup_port(host->ports[i],
- base + 0x200 + ata_nr * 0x80,
- base + 0x400 + ata_nr * 0x100);
+ base + 0x200 + ata_no * 0x80,
+ base + 0x400 + ata_no * 0x100);
}
/* initialize adapter */
@@ -999,19 +1026,16 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
&pdc_ata_sht);
}
-
static int __init pdc_ata_init(void)
{
return pci_register_driver(&pdc_ata_pci_driver);
}
-
static void __exit pdc_ata_exit(void)
{
pci_unregister_driver(&pdc_ata_pci_driver);
}
-
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index 6688ccb6632..9ab554da89b 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -176,7 +176,7 @@ static const struct ata_port_info qs_port_info[] = {
//FIXME ATA_FLAG_SRST |
ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x10, /* pio4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &qs_ata_ops,
},
};
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index a3b339bcf3c..2a86dc4598d 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -218,7 +218,7 @@ static const struct ata_port_info sil_port_info[] = {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
/* sil_3112_no_sata_irq */
@@ -227,7 +227,7 @@ static const struct ata_port_info sil_port_info[] = {
SIL_FLAG_NO_SATA_IRQ,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
/* sil_3512 */
@@ -235,7 +235,7 @@ static const struct ata_port_info sil_port_info[] = {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
/* sil_3114 */
@@ -243,7 +243,7 @@ static const struct ata_port_info sil_port_info[] = {
.flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5,
.port_ops = &sil_ops,
},
};
@@ -262,8 +262,9 @@ static const struct {
unsigned long sfis_cfg; /* SATA FIS reception config register */
} sil_port[] = {
/* port 0 ... */
- { 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
- { 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
+ /* tf ctl bmdma bmdma2 fifo scr sien mode sfis */
+ { 0x80, 0x8A, 0x0, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
+ { 0xC0, 0xCA, 0x8, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
{ 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
{ 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
/* ... port 3 */
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 0ddfae9911c..ac43a30ebe2 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -426,7 +426,7 @@ static const struct ata_port_info sil24_port_info[] = {
SIL24_FLAG_PCIX_IRQ_WOC,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
.port_ops = &sil24_ops,
},
/* sil_3132 */
@@ -434,7 +434,7 @@ static const struct ata_port_info sil24_port_info[] = {
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
.port_ops = &sil24_ops,
},
/* sil_3131/sil_3531 */
@@ -442,7 +442,7 @@ static const struct ata_port_info sil24_port_info[] = {
.flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x3f, /* udma0-5 */
+ .udma_mask = ATA_UDMA5, /* udma0-5 */
.port_ops = &sil24_ops,
},
};
@@ -888,7 +888,7 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance)
if (status & (1 << i)) {
struct ata_port *ap = host->ports[i];
if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
- sil24_host_intr(host->ports[i]);
+ sil24_host_intr(ap);
handled++;
} else
printk(KERN_ERR DRV_NAME
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 221099d1d08..33716b00c6b 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -72,8 +72,8 @@ static const struct pci_device_id sis_pci_tbl[] = {
{ PCI_VDEVICE(SI, 0x0181), sis_180 }, /* SiS 964/180 */
{ PCI_VDEVICE(SI, 0x0182), sis_180 }, /* SiS 965/965L */
{ PCI_VDEVICE(SI, 0x0183), sis_180 }, /* SiS 965/965L */
- { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/966L */
- { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L */
+ { PCI_VDEVICE(SI, 0x1182), sis_180 }, /* SiS 966/680 */
+ { PCI_VDEVICE(SI, 0x1183), sis_180 }, /* SiS 966/966L/968/680 */
{ } /* terminate list */
};
@@ -133,7 +133,7 @@ static const struct ata_port_info sis_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x7,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &sis_ops,
};
@@ -161,7 +161,6 @@ static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
case 0x0182:
case 0x0183:
case 0x1182:
- case 0x1183:
addr += SIS182_SATA1_OFS;
break;
}
@@ -183,8 +182,8 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
pci_read_config_dword(pdev, cfg_addr, &val);
- if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
- (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+ if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+ (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
pci_read_config_dword(pdev, cfg_addr+0x10, &val2);
return (val|val2) & 0xfffffffb; /* avoid problems with powerdowned ports */
@@ -203,8 +202,8 @@ static void sis_scr_cfg_write (struct ata_port *ap, unsigned int sc_reg, u32 val
pci_write_config_dword(pdev, cfg_addr, val);
- if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
- (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+ if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+ (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
pci_write_config_dword(pdev, cfg_addr+0x10, val);
}
@@ -224,8 +223,8 @@ static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
val = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
- if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
- (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+ if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+ (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
val2 = ioread32(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10);
return (val | val2) & 0xfffffffb;
@@ -245,8 +244,8 @@ static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
sis_scr_cfg_write(ap, sc_reg, val);
else {
iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
- if ((pdev->device == 0x0182) || (pdev->device == 0x0183) || (pdev->device == 0x1182) ||
- (pdev->device == 0x1183) || (pmr & SIS_PMR_COMBINED))
+ if ((pdev->device == 0x0182) || (pdev->device == 0x0183) ||
+ (pdev->device == 0x1182) || (pmr & SIS_PMR_COMBINED))
iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10);
}
}
@@ -293,11 +292,11 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
/* The PATA-handling is provided by pata_sis */
switch (pmr & 0x30) {
case 0x10:
- ppi[1] = &sis_info133;
+ ppi[1] = &sis_info133_for_sata;
break;
case 0x30:
- ppi[0] = &sis_info133;
+ ppi[0] = &sis_info133_for_sata;
break;
}
if ((pmr & SIS_PMR_COMBINED) == 0) {
@@ -324,18 +323,18 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
break;
case 0x1182:
+ dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/966/680 SATA controller\n");
+ pi.flags |= ATA_FLAG_SLAVE_POSS;
+ break;
+
case 0x1183:
- pci_read_config_dword(pdev, 0x64, &val);
- if (val & 0x10000000) {
- dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/1183/966L SATA controller\n");
- } else {
- dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1182/1183/966 SATA controller\n");
- pi.flags |= ATA_FLAG_SLAVE_POSS;
- }
+ dev_printk(KERN_INFO, &pdev->dev, "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
+ ppi[0] = &sis_info133_for_sata;
+ ppi[1] = &sis_info133_for_sata;
break;
}
- rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+ rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
if (rc)
return rc;
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index bcb2cd8b063..63fe99afd59 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -107,7 +107,7 @@ static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
{
if (sc_reg > SCR_CONTROL)
return 0xffffffffU;
- return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -116,7 +116,7 @@ static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
{
if (sc_reg > SCR_CONTROL)
return;
- writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4));
+ writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
}
@@ -197,7 +197,8 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;
unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
u8 dmactl;
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
+
/* load PRD table addr. */
mb(); /* make sure PRD table writes are visible to controller */
writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
@@ -225,7 +226,7 @@ static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+ void __iomem *mmio = ap->ioaddr.bmdma_addr;
u8 dmactl;
/* start host DMA transaction */
@@ -253,7 +254,7 @@ static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
static u8 k2_stat_check_status(struct ata_port *ap)
{
- return readl((void __iomem *) ap->ioaddr.status_addr);
+ return readl(ap->ioaddr.status_addr);
}
#ifdef CONFIG_PPC_OF
@@ -360,7 +361,7 @@ static const struct ata_port_info k2_port_info[] = {
ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
/* board_svw8 */
@@ -370,7 +371,7 @@ static const struct ata_port_info k2_port_info[] = {
K2_FLAG_SATA_8_PORTS,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
};
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 2d14f3d56d9..5193bd8647b 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -30,6 +30,54 @@
*
*/
+/*
+ Theory of operation
+ -------------------
+
+ The SX4 (PDC20621) chip features a single Host DMA (HDMA) copy
+ engine, DIMM memory, and four ATA engines (one per SATA port).
+ Data is copied to/from DIMM memory by the HDMA engine, before
+ handing off to one (or more) of the ATA engines. The ATA
+ engines operate solely on DIMM memory.
+
+ The SX4 behaves like a PATA chip, with no SATA controls or
+ knowledge whatsoever, leading to the presumption that
+ PATA<->SATA bridges exist on SX4 boards, external to the
+ PDC20621 chip itself.
+
+ The chip is quite capable, supporting an XOR engine and linked
+ hardware commands (permits a string to transactions to be
+ submitted and waited-on as a single unit), and an optional
+ microprocessor.
+
+ The limiting factor is largely software. This Linux driver was
+ written to multiplex the single HDMA engine to copy disk
+ transactions into a fixed DIMM memory space, from where an ATA
+ engine takes over. As a result, each WRITE looks like this:
+
+ submit HDMA packet to hardware
+ hardware copies data from system memory to DIMM
+ hardware raises interrupt
+
+ submit ATA packet to hardware
+ hardware executes ATA WRITE command, w/ data in DIMM
+ hardware raises interrupt
+
+ and each READ looks like this:
+
+ submit ATA packet to hardware
+ hardware executes ATA READ command, w/ data in DIMM
+ hardware raises interrupt
+
+ submit HDMA packet to hardware
+ hardware copies data from DIMM to system memory
+ hardware raises interrupt
+
+ This is a very slow, lock-step way of doing things that can
+ certainly be improved by motivated kernel hackers.
+
+ */
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -58,6 +106,8 @@ enum {
PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */
+ PDC_CTLSTAT = 0x60, /* IDEn control / status */
+
PDC_20621_SEQCTL = 0x400,
PDC_20621_SEQMASK = 0x480,
PDC_20621_GENERAL_CTL = 0x484,
@@ -87,48 +137,60 @@ enum {
board_20621 = 0, /* FastTrak S150 SX4 */
- PDC_RESET = (1 << 11), /* HDMA reset */
+ PDC_MASK_INT = (1 << 10), /* HDMA/ATA mask int */
+ PDC_RESET = (1 << 11), /* HDMA/ATA reset */
+ PDC_DMA_ENABLE = (1 << 7), /* DMA start/stop */
PDC_MAX_HDMA = 32,
PDC_HDMA_Q_MASK = (PDC_MAX_HDMA - 1),
- PDC_DIMM0_SPD_DEV_ADDRESS = 0x50,
- PDC_DIMM1_SPD_DEV_ADDRESS = 0x51,
- PDC_MAX_DIMM_MODULE = 0x02,
- PDC_I2C_CONTROL_OFFSET = 0x48,
- PDC_I2C_ADDR_DATA_OFFSET = 0x4C,
- PDC_DIMM0_CONTROL_OFFSET = 0x80,
- PDC_DIMM1_CONTROL_OFFSET = 0x84,
- PDC_SDRAM_CONTROL_OFFSET = 0x88,
- PDC_I2C_WRITE = 0x00000000,
- PDC_I2C_READ = 0x00000040,
- PDC_I2C_START = 0x00000080,
- PDC_I2C_MASK_INT = 0x00000020,
- PDC_I2C_COMPLETE = 0x00010000,
- PDC_I2C_NO_ACK = 0x00100000,
- PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
- PDC_DIMM_SPD_SUBADDRESS_END = 0x7F,
- PDC_DIMM_SPD_ROW_NUM = 3,
- PDC_DIMM_SPD_COLUMN_NUM = 4,
- PDC_DIMM_SPD_MODULE_ROW = 5,
- PDC_DIMM_SPD_TYPE = 11,
- PDC_DIMM_SPD_FRESH_RATE = 12,
- PDC_DIMM_SPD_BANK_NUM = 17,
- PDC_DIMM_SPD_CAS_LATENCY = 18,
- PDC_DIMM_SPD_ATTRIBUTE = 21,
- PDC_DIMM_SPD_ROW_PRE_CHARGE = 27,
- PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
- PDC_DIMM_SPD_RAS_CAS_DELAY = 29,
- PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
- PDC_DIMM_SPD_SYSTEM_FREQ = 126,
- PDC_CTL_STATUS = 0x08,
- PDC_DIMM_WINDOW_CTLR = 0x0C,
- PDC_TIME_CONTROL = 0x3C,
- PDC_TIME_PERIOD = 0x40,
- PDC_TIME_COUNTER = 0x44,
- PDC_GENERAL_CTLR = 0x484,
- PCI_PLL_INIT = 0x8A531824,
- PCI_X_TCOUNT = 0xEE1E5CFF
+ PDC_DIMM0_SPD_DEV_ADDRESS = 0x50,
+ PDC_DIMM1_SPD_DEV_ADDRESS = 0x51,
+ PDC_I2C_CONTROL = 0x48,
+ PDC_I2C_ADDR_DATA = 0x4C,
+ PDC_DIMM0_CONTROL = 0x80,
+ PDC_DIMM1_CONTROL = 0x84,
+ PDC_SDRAM_CONTROL = 0x88,
+ PDC_I2C_WRITE = 0, /* master -> slave */
+ PDC_I2C_READ = (1 << 6), /* master <- slave */
+ PDC_I2C_START = (1 << 7), /* start I2C proto */
+ PDC_I2C_MASK_INT = (1 << 5), /* mask I2C interrupt */
+ PDC_I2C_COMPLETE = (1 << 16), /* I2C normal compl. */
+ PDC_I2C_NO_ACK = (1 << 20), /* slave no-ack addr */
+ PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
+ PDC_DIMM_SPD_SUBADDRESS_END = 0x7F,
+ PDC_DIMM_SPD_ROW_NUM = 3,
+ PDC_DIMM_SPD_COLUMN_NUM = 4,
+ PDC_DIMM_SPD_MODULE_ROW = 5,
+ PDC_DIMM_SPD_TYPE = 11,
+ PDC_DIMM_SPD_FRESH_RATE = 12,
+ PDC_DIMM_SPD_BANK_NUM = 17,
+ PDC_DIMM_SPD_CAS_LATENCY = 18,
+ PDC_DIMM_SPD_ATTRIBUTE = 21,
+ PDC_DIMM_SPD_ROW_PRE_CHARGE = 27,
+ PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,
+ PDC_DIMM_SPD_RAS_CAS_DELAY = 29,
+ PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
+ PDC_DIMM_SPD_SYSTEM_FREQ = 126,
+ PDC_CTL_STATUS = 0x08,
+ PDC_DIMM_WINDOW_CTLR = 0x0C,
+ PDC_TIME_CONTROL = 0x3C,
+ PDC_TIME_PERIOD = 0x40,
+ PDC_TIME_COUNTER = 0x44,
+ PDC_GENERAL_CTLR = 0x484,
+ PCI_PLL_INIT = 0x8A531824,
+ PCI_X_TCOUNT = 0xEE1E5CFF,
+
+ /* PDC_TIME_CONTROL bits */
+ PDC_TIMER_BUZZER = (1 << 10),
+ PDC_TIMER_MODE_PERIODIC = 0, /* bits 9:8 == 00 */
+ PDC_TIMER_MODE_ONCE = (1 << 8), /* bits 9:8 == 01 */
+ PDC_TIMER_ENABLE = (1 << 7),
+ PDC_TIMER_MASK_INT = (1 << 5),
+ PDC_TIMER_SEQ_MASK = 0x1f, /* SEQ ID for timer */
+ PDC_TIMER_DEFAULT = PDC_TIMER_MODE_ONCE |
+ PDC_TIMER_ENABLE |
+ PDC_TIMER_MASK_INT,
};
@@ -217,7 +279,7 @@ static const struct ata_port_info pdc_port_info[] = {
ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .udma_mask = ATA_UDMA6,
.port_ops = &pdc_20621_ops,
},
@@ -999,17 +1061,17 @@ static unsigned int pdc20621_i2c_read(struct ata_host *host, u32 device,
i2creg |= subaddr << 16;
/* Set the device and subaddress */
- writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
- readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+ writel(i2creg, mmio + PDC_I2C_ADDR_DATA);
+ readl(mmio + PDC_I2C_ADDR_DATA);
/* Write Control to perform read operation, mask int */
writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT,
- mmio + PDC_I2C_CONTROL_OFFSET);
+ mmio + PDC_I2C_CONTROL);
for (count = 0; count <= 1000; count ++) {
- status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
+ status = readl(mmio + PDC_I2C_CONTROL);
if (status & PDC_I2C_COMPLETE) {
- status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+ status = readl(mmio + PDC_I2C_ADDR_DATA);
break;
} else if (count == 1000)
return 0;
@@ -1099,8 +1161,8 @@ static int pdc20621_prog_dimm0(struct ata_host *host)
data |= (((size / 16) - 1) << 16);
data |= (0 << 23);
data |= 8;
- writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET);
- readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
+ writel(data, mmio + PDC_DIMM0_CONTROL);
+ readl(mmio + PDC_DIMM0_CONTROL);
return size;
}
@@ -1122,27 +1184,27 @@ static unsigned int pdc20621_prog_dimm_global(struct ata_host *host)
*/
data = 0x022259F1;
- writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
- readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+ writel(data, mmio + PDC_SDRAM_CONTROL);
+ readl(mmio + PDC_SDRAM_CONTROL);
/* Turn on for ECC */
pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0);
if (spd0 == 0x02) {
data |= (0x01 << 16);
- writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
- readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+ writel(data, mmio + PDC_SDRAM_CONTROL);
+ readl(mmio + PDC_SDRAM_CONTROL);
printk(KERN_ERR "Local DIMM ECC Enabled\n");
}
/* DIMM Initialization Select/Enable (bit 18/19) */
data &= (~(1<<18));
data |= (1<<19);
- writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+ writel(data, mmio + PDC_SDRAM_CONTROL);
error = 1;
for (i = 1; i <= 10; i++) { /* polling ~5 secs */
- data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+ data = readl(mmio + PDC_SDRAM_CONTROL);
if (!(data & (1<<19))) {
error = 0;
break;
@@ -1176,7 +1238,7 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host)
VPRINTK("Time Period Register (0x40): 0x%x\n", time_period);
/* Enable timer */
- writel(0x00001a0, mmio + PDC_TIME_CONTROL);
+ writel(PDC_TIMER_DEFAULT, mmio + PDC_TIME_CONTROL);
readl(mmio + PDC_TIME_CONTROL);
/* Wait 3 seconds */
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index 6815de7cca7..b52f83ab056 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -129,7 +129,7 @@ static const struct ata_port_info uli_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_IGN_SIMPLEX,
.pio_mask = 0x1f, /* pio0-4 */
- .udma_mask = 0x7f, /* udma0-6 */
+ .udma_mask = ATA_UDMA6,
.port_ops = &uli_ops,
};
@@ -213,7 +213,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
host->private_data = hpriv;
/* the first two ports are standard SFF */
- rc = ata_pci_init_native_host(host);
+ rc = ata_pci_init_sff_host(host);
if (rc)
return rc;
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index e8b90e7b42d..c4124475f75 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -223,7 +223,7 @@ static const struct ata_port_info vt6420_port_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &vt6420_sata_ops,
};
@@ -231,7 +231,7 @@ static struct ata_port_info vt6421_sport_info = {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &vt6421_sata_ops,
};
@@ -239,7 +239,7 @@ static struct ata_port_info vt6421_pport_info = {
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &vt6421_pata_ops,
};
@@ -303,9 +303,7 @@ static int vt6420_prereset(struct ata_port *ap, unsigned long deadline)
if (!(ap->pflags & ATA_PFLAG_LOADING))
goto skip_scr;
- /* Resume phy. This is the old resume sequence from
- * __sata_phy_reset().
- */
+ /* Resume phy. This is the old SATA resume sequence */
svia_scr_write(ap, SCR_CONTROL, 0x300);
svia_scr_read(ap, SCR_CONTROL); /* flush */
@@ -414,7 +412,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host)
struct ata_host *host;
int rc;
- rc = ata_pci_prepare_native_host(pdev, ppi, &host);
+ rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
if (rc)
return rc;
*r_host = host;
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index 81330175fc8..1b5d81faa10 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -371,7 +371,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
ATA_FLAG_MMIO,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
- .udma_mask = 0x7f,
+ .udma_mask = ATA_UDMA6,
.port_ops = &vsc_sata_ops,
};
const struct ata_port_info *ppi[] = { &pi, NULL };
diff --git a/drivers/ata/sis.h b/drivers/ata/sis.h
index 0f2208d8d5e..f7f3eebe666 100644
--- a/drivers/ata/sis.h
+++ b/drivers/ata/sis.h
@@ -2,4 +2,4 @@
struct ata_port_info;
/* pata_sis.c */
-extern const struct ata_port_info sis_info133;
+extern const struct ata_port_info sis_info133_for_sata;
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index f5a47a48c3b..5b4fab24155 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -7,7 +7,7 @@ menuconfig ATM_DRIVERS
depends on NETDEVICES && ATM
default y
-if ATM_DRIVERS
+if ATM_DRIVERS && NETDEVICES && ATM
config ATM_DUMMY
tristate "Dummy ATM driver"
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 0d3a38b1cb0..77637e780d4 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1704,7 +1704,6 @@ static int __devinit eni_do_init(struct atm_dev *dev)
struct pci_dev *pci_dev;
unsigned long real_base;
void __iomem *base;
- unsigned char revision;
int error,i,last;
DPRINTK(">eni_init\n");
@@ -1715,12 +1714,6 @@ static int __devinit eni_do_init(struct atm_dev *dev)
pci_dev = eni_dev->pci_dev;
real_base = pci_resource_start(pci_dev, 0);
eni_dev->irq = pci_dev->irq;
- error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision);
- if (error) {
- printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",
- dev->number,error);
- return -EINVAL;
- }
if ((error = pci_write_config_word(pci_dev,PCI_COMMAND,
PCI_COMMAND_MEMORY |
(eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
@@ -1729,7 +1722,7 @@ static int __devinit eni_do_init(struct atm_dev *dev)
return -EIO;
}
printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
- dev->number,revision,real_base,eni_dev->irq);
+ dev->number,pci_dev->revision,real_base,eni_dev->irq);
if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) {
printk("\n");
printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 9c67df5ccfa..38b688f9f6a 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1475,6 +1475,7 @@ static void top_off_fp (struct fs_dev *dev, struct freepool *fp,
struct FS_BPENTRY *qe, *ne;
struct sk_buff *skb;
int n = 0;
+ u32 qe_tmp;
fs_dprintk (FS_DEBUG_QUEUE, "Topping off queue at %x (%d-%d/%d)\n",
fp->offset, read_fs (dev, FP_CNT (fp->offset)), fp->n,
@@ -1502,10 +1503,16 @@ static void top_off_fp (struct fs_dev *dev, struct freepool *fp,
ne->skb = skb;
ne->fp = fp;
- qe = (struct FS_BPENTRY *) (read_fs (dev, FP_EA(fp->offset)));
- fs_dprintk (FS_DEBUG_QUEUE, "link at %p\n", qe);
- if (qe) {
- qe = bus_to_virt ((long) qe);
+ /*
+ * FIXME: following code encodes and decodes
+ * machine pointers (could be 64-bit) into a
+ * 32-bit register.
+ */
+
+ qe_tmp = read_fs (dev, FP_EA(fp->offset));
+ fs_dprintk (FS_DEBUG_QUEUE, "link at %x\n", qe_tmp);
+ if (qe_tmp) {
+ qe = bus_to_virt ((long) qe_tmp);
qe->next = virt_to_bus(ne);
qe->flags &= ~FP_FLAGS_EPI;
} else
@@ -1647,7 +1654,7 @@ static void fs_poll (unsigned long data)
{
struct fs_dev *dev = (struct fs_dev *) data;
- fs_irq (0, dev, NULL);
+ fs_irq (0, dev);
dev->timer.expires = jiffies + FS_POLL_FREQ;
add_timer (&dev->timer);
}
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index 3800bc0cb2e..8f995ce8d73 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -3679,7 +3679,6 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
unsigned long membase, srambase;
struct idt77252_dev *card;
struct atm_dev *dev;
- ushort revision = 0;
int i, err;
@@ -3688,19 +3687,13 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
return err;
}
- if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) {
- printk("idt77252-%d: can't read PCI_REVISION_ID\n", index);
- err = -ENODEV;
- goto err_out_disable_pdev;
- }
-
card = kzalloc(sizeof(struct idt77252_dev), GFP_KERNEL);
if (!card) {
printk("idt77252-%d: can't allocate private data\n", index);
err = -ENOMEM;
goto err_out_disable_pdev;
}
- card->revision = revision;
+ card->revision = pcidev->revision;
card->index = index;
card->pcidev = pcidev;
sprintf(card->name, "idt77252-%d", card->index);
@@ -3762,8 +3755,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
}
printk("%s: ABR SAR (Rev %c): MEM %08lx SRAM %08lx [%u KB]\n",
- card->name, ((revision > 1) && (revision < 25)) ?
- 'A' + revision - 1 : '?', membase, srambase,
+ card->name, ((card->revision > 1) && (card->revision < 25)) ?
+ 'A' + card->revision - 1 : '?', membase, srambase,
card->sramsize / 1024);
if (init_card(dev)) {
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index bb7ef570514..a3b605a0ca1 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -2290,7 +2290,6 @@ static int __devinit ia_init(struct atm_dev *dev)
unsigned long real_base;
void __iomem *base;
unsigned short command;
- unsigned char revision;
int error, i;
/* The device has been identified and registered. Now we read
@@ -2305,16 +2304,14 @@ static int __devinit ia_init(struct atm_dev *dev)
real_base = pci_resource_start (iadev->pci, 0);
iadev->irq = iadev->pci->irq;
- if ((error = pci_read_config_word(iadev->pci, PCI_COMMAND,&command))
- || (error = pci_read_config_byte(iadev->pci,
- PCI_REVISION_ID,&revision)))
- {
+ error = pci_read_config_word(iadev->pci, PCI_COMMAND, &command);
+ if (error) {
printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%x\n",
dev->number,error);
return -EINVAL;
}
IF_INIT(printk(DEV_LABEL "(itf %d): rev.%d,realbase=0x%lx,irq=%d\n",
- dev->number, revision, real_base, iadev->irq);)
+ dev->number, iadev->pci->revision, real_base, iadev->irq);)
/* find mapping size of board */
@@ -2353,7 +2350,7 @@ static int __devinit ia_init(struct atm_dev *dev)
return error;
}
IF_INIT(printk(DEV_LABEL " (itf %d): rev.%d,base=%p,irq=%d\n",
- dev->number, revision, base, iadev->irq);)
+ dev->number, iadev->pci->revision, base, iadev->irq);)
/* filling the iphase dev structure */
iadev->mem = iadev->pci_map_size /2;
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 09f477d4237..0e2c1ae650e 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -246,8 +246,8 @@ struct lanai_vcc {
};
enum lanai_type {
- lanai2 = PCI_VENDOR_ID_EF_ATM_LANAI2,
- lanaihb = PCI_VENDOR_ID_EF_ATM_LANAIHB
+ lanai2 = PCI_DEVICE_ID_EF_ATM_LANAI2,
+ lanaihb = PCI_DEVICE_ID_EF_ATM_LANAIHB
};
struct lanai_dev_stats {
@@ -293,7 +293,6 @@ struct lanai_dev {
struct atm_vcc *cbrvcc;
int number;
int board_rev;
- u8 pci_revision;
/* TODO - look at race conditions with maintence of conf1/conf2 */
/* TODO - transmit locking: should we use _irq not _irqsave? */
/* TODO - organize above in some rational fashion (see <asm/cache.h>) */
@@ -1969,14 +1968,6 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai)
"(itf %d): No suitable DMA available.\n", lanai->number);
return -EBUSY;
}
- /* Get the pci revision byte */
- result = pci_read_config_byte(pci, PCI_REVISION_ID,
- &lanai->pci_revision);
- if (result != PCIBIOS_SUCCESSFUL) {
- printk(KERN_ERR DEV_LABEL "(itf %d): can't read "
- "PCI_REVISION_ID: %d\n", lanai->number, result);
- return -EINVAL;
- }
result = pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &w);
if (result != PCIBIOS_SUCCESSFUL) {
printk(KERN_ERR DEV_LABEL "(itf %d): can't read "
@@ -2254,7 +2245,7 @@ static int __devinit lanai_dev_open(struct atm_dev *atmdev)
lanai_timed_poll_start(lanai);
printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d, base=0x%lx, irq=%u "
"(%02X-%02X-%02X-%02X-%02X-%02X)\n", lanai->number,
- (int) lanai->pci_revision, (unsigned long) lanai->base,
+ (int) lanai->pci->revision, (unsigned long) lanai->base,
lanai->pci->irq,
atmdev->esi[0], atmdev->esi[1], atmdev->esi[2],
atmdev->esi[3], atmdev->esi[4], atmdev->esi[5]);
@@ -2491,7 +2482,7 @@ static int lanai_proc_read(struct atm_dev *atmdev, loff_t *pos, char *page)
(unsigned int) lanai->magicno, lanai->num_vci);
if (left-- == 0)
return sprintf(page, "revision: board=%d, pci_if=%d\n",
- lanai->board_rev, (int) lanai->pci_revision);
+ lanai->board_rev, (int) lanai->pci->revision);
if (left-- == 0)
return sprintf(page, "EEPROM ESI: "
"%02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -2631,14 +2622,8 @@ static int __devinit lanai_init_one(struct pci_dev *pci,
}
static struct pci_device_id lanai_pci_tbl[] = {
- {
- PCI_VENDOR_ID_EF, PCI_VENDOR_ID_EF_ATM_LANAI2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
- },
- {
- PCI_VENDOR_ID_EF, PCI_VENDOR_ID_EF_ATM_LANAIHB,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
- },
+ { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAI2) },
+ { PCI_VDEVICE(EF, PCI_DEVICE_ID_EF_ATM_LANAIHB) },
{ 0, } /* terminal entry */
};
MODULE_DEVICE_TABLE(pci, lanai_pci_tbl);
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 2ad2527cf5b..020a87a476c 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -1182,7 +1182,6 @@ static int __devinit zatm_init(struct atm_dev *dev)
struct zatm_dev *zatm_dev;
struct pci_dev *pci_dev;
unsigned short command;
- unsigned char revision;
int error,i,last;
unsigned long t0,t1,t2;
@@ -1192,8 +1191,7 @@ static int __devinit zatm_init(struct atm_dev *dev)
pci_dev = zatm_dev->pci_dev;
zatm_dev->base = pci_resource_start(pci_dev, 0);
zatm_dev->irq = pci_dev->irq;
- if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command)) ||
- (error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision))) {
+ if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command))) {
printk(KERN_ERR DEV_LABEL "(itf %d): init error 0x%02x\n",
dev->number,error);
return -EINVAL;
@@ -1206,7 +1204,7 @@ static int __devinit zatm_init(struct atm_dev *dev)
}
eprom_get_esi(dev);
printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%x,irq=%d,",
- dev->number,revision,zatm_dev->base,zatm_dev->irq);
+ dev->number,pci_dev->revision,zatm_dev->base,zatm_dev->irq);
/* reset uPD98401 */
zout(0,SWR);
while (!(zin(GSR) & uPD98401_INT_IND));
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index 2e18a63ead3..ea4fe3e48f3 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -68,6 +68,10 @@ config CFAG12864B
depends on X86
depends on FB
depends on KS0108
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
default n
---help---
If you have a Crystalfontz 128x64 2-color LCD, cfag12864b Series,
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c
index 66fafbb1d08..307c190699e 100644
--- a/drivers/auxdisplay/cfag12864bfb.c
+++ b/drivers/auxdisplay/cfag12864bfb.c
@@ -73,9 +73,11 @@ static int cfag12864bfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
static struct fb_ops cfag12864bfb_ops = {
.owner = THIS_MODULE,
- .fb_fillrect = cfb_fillrect,
- .fb_copyarea = cfb_copyarea,
- .fb_imageblit = cfb_imageblit,
+ .fb_read = fb_sys_read,
+ .fb_write = fb_sys_write,
+ .fb_fillrect = sys_fillrect,
+ .fb_copyarea = sys_copyarea,
+ .fb_imageblit = sys_imageblit,
.fb_mmap = cfag12864bfb_mmap,
};
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 1ec0654665c..7370d7cf598 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include "base.h"
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 5512d84452f..47eb02d9f1a 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -44,6 +44,6 @@ struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
extern char *make_class_name(const char *name, struct kobject *kobj);
-extern void devres_release_all(struct device *dev);
+extern int devres_release_all(struct device *dev);
extern struct kset devices_subsys;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index dca734819e5..61c67526a65 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -138,12 +138,24 @@ void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
}
}
-static struct kobj_type ktype_bus = {
+static struct kobj_type bus_ktype = {
.sysfs_ops = &bus_sysfs_ops,
+};
+
+static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
+{
+ struct kobj_type *ktype = get_ktype(kobj);
+ if (ktype == &bus_ktype)
+ return 1;
+ return 0;
+}
+
+static struct kset_uevent_ops bus_uevent_ops = {
+ .filter = bus_uevent_filter,
};
-static decl_subsys(bus, &ktype_bus, NULL);
+static decl_subsys(bus, &bus_ktype, &bus_uevent_ops);
#ifdef CONFIG_HOTPLUG
@@ -562,7 +574,6 @@ static int add_probe_files(struct bus_type *bus)
bus->drivers_probe_attr.attr.name = "drivers_probe";
bus->drivers_probe_attr.attr.mode = S_IWUSR;
- bus->drivers_probe_attr.attr.owner = bus->owner;
bus->drivers_probe_attr.store = store_drivers_probe;
retval = bus_create_file(bus, &bus->drivers_probe_attr);
if (retval)
@@ -570,7 +581,6 @@ static int add_probe_files(struct bus_type *bus)
bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
- bus->drivers_autoprobe_attr.attr.owner = bus->owner;
bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
@@ -610,7 +620,8 @@ int bus_add_driver(struct device_driver *drv)
if (error)
goto out_put_bus;
drv->kobj.kset = &bus->drivers;
- if ((error = kobject_register(&drv->kobj)))
+ error = kobject_register(&drv->kobj);
+ if (error)
goto out_put_bus;
if (drv->bus->drivers_autoprobe) {
@@ -760,7 +771,8 @@ static int bus_add_attrs(struct bus_type * bus)
if (bus->bus_attrs) {
for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
- if ((error = bus_create_file(bus,&bus->bus_attrs[i])))
+ error = bus_create_file(bus,&bus->bus_attrs[i]);
+ if (error)
goto Err;
}
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 20c4ea6eb50..4d2222618b7 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -312,9 +312,6 @@ static void class_dev_release(struct kobject * kobj)
pr_debug("device class '%s': release.\n", cd->class_id);
- kfree(cd->devt_attr);
- cd->devt_attr = NULL;
-
if (cd->release)
cd->release(cd);
else if (cls->release)
@@ -369,36 +366,6 @@ char *make_class_name(const char *name, struct kobject *kobj)
return class_name;
}
-static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index,
- char *buffer, int buffer_size,
- int *cur_len,
- struct class_device *class_dev)
-{
- struct device *dev = class_dev->dev;
- char *path;
-
- if (!dev)
- return 0;
-
- /* add device, backing this class device (deprecated) */
- path = kobject_get_path(&dev->kobj, GFP_KERNEL);
-
- add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size,
- cur_len, "PHYSDEVPATH=%s", path);
- kfree(path);
-
- if (dev->bus)
- add_uevent_var(envp, num_envp, cur_index,
- buffer, buffer_size, cur_len,
- "PHYSDEVBUS=%s", dev->bus->name);
-
- if (dev->driver)
- add_uevent_var(envp, num_envp, cur_index,
- buffer, buffer_size, cur_len,
- "PHYSDEVDRIVER=%s", dev->driver->name);
- return 0;
-}
-
static int make_deprecated_class_device_links(struct class_device *class_dev)
{
char *class_name;
@@ -430,11 +397,6 @@ static void remove_deprecated_class_device_links(struct class_device *class_dev)
kfree(class_name);
}
#else
-static inline int deprecated_class_uevent(char **envp, int num_envp,
- int *cur_index, char *buffer,
- int buffer_size, int *cur_len,
- struct class_device *class_dev)
-{ return 0; }
static inline int make_deprecated_class_device_links(struct class_device *cd)
{ return 0; }
static void remove_deprecated_class_device_links(struct class_device *cd)
@@ -445,15 +407,13 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
struct class_device *class_dev = to_class_dev(kobj);
+ struct device *dev = class_dev->dev;
int i = 0;
int length = 0;
int retval = 0;
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
- deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
- &length, class_dev);
-
if (MAJOR(class_dev->devt)) {
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
@@ -464,6 +424,26 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
"MINOR=%u", MINOR(class_dev->devt));
}
+ if (dev) {
+ const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+ if (path) {
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVPATH=%s", path);
+ kfree(path);
+ }
+
+ if (dev->bus)
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVBUS=%s", dev->bus->name);
+
+ if (dev->driver)
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVDRIVER=%s", dev->driver->name);
+ }
+
/* terminate, set to next free slot, shrink available space */
envp[i] = NULL;
envp = &envp[i];
@@ -564,6 +544,9 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
return print_dev_t(buf, class_dev->devt);
}
+static struct class_device_attribute class_devt_attr =
+ __ATTR(dev, S_IRUGO, show_dev, NULL);
+
static ssize_t store_uevent(struct class_device *class_dev,
const char *buf, size_t count)
{
@@ -571,6 +554,9 @@ static ssize_t store_uevent(struct class_device *class_dev,
return count;
}
+static struct class_device_attribute class_uevent_attr =
+ __ATTR(uevent, S_IWUSR, NULL, store_uevent);
+
void class_device_initialize(struct class_device *class_dev)
{
kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -620,32 +606,15 @@ int class_device_add(struct class_device *class_dev)
&parent_class->subsys.kobj, "subsystem");
if (error)
goto out3;
- class_dev->uevent_attr.attr.name = "uevent";
- class_dev->uevent_attr.attr.mode = S_IWUSR;
- class_dev->uevent_attr.attr.owner = parent_class->owner;
- class_dev->uevent_attr.store = store_uevent;
- error = class_device_create_file(class_dev, &class_dev->uevent_attr);
+
+ error = class_device_create_file(class_dev, &class_uevent_attr);
if (error)
goto out3;
if (MAJOR(class_dev->devt)) {
- struct class_device_attribute *attr;
- attr = kzalloc(sizeof(*attr), GFP_KERNEL);
- if (!attr) {
- error = -ENOMEM;
- goto out4;
- }
- attr->attr.name = "dev";
- attr->attr.mode = S_IRUGO;
- attr->attr.owner = parent_class->owner;
- attr->show = show_dev;
- error = class_device_create_file(class_dev, attr);
- if (error) {
- kfree(attr);
+ error = class_device_create_file(class_dev, &class_devt_attr);
+ if (error)
goto out4;
- }
-
- class_dev->devt_attr = attr;
}
error = class_device_add_attrs(class_dev);
@@ -688,10 +657,10 @@ int class_device_add(struct class_device *class_dev)
out6:
class_device_remove_attrs(class_dev);
out5:
- if (class_dev->devt_attr)
- class_device_remove_file(class_dev, class_dev->devt_attr);
+ if (MAJOR(class_dev->devt))
+ class_device_remove_file(class_dev, &class_devt_attr);
out4:
- class_device_remove_file(class_dev, &class_dev->uevent_attr);
+ class_device_remove_file(class_dev, &class_uevent_attr);
out3:
kobject_del(&class_dev->kobj);
out2:
@@ -791,9 +760,9 @@ void class_device_del(struct class_device *class_dev)
sysfs_remove_link(&class_dev->kobj, "device");
}
sysfs_remove_link(&class_dev->kobj, "subsystem");
- class_device_remove_file(class_dev, &class_dev->uevent_attr);
- if (class_dev->devt_attr)
- class_device_remove_file(class_dev, class_dev->devt_attr);
+ class_device_remove_file(class_dev, &class_uevent_attr);
+ if (MAJOR(class_dev->devt))
+ class_device_remove_file(class_dev, &class_devt_attr);
class_device_remove_attrs(class_dev);
class_device_remove_groups(class_dev);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index b78fc1e6826..0455aa78fa1 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -180,10 +180,12 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
const char *path;
path = kobject_get_path(&parent->kobj, GFP_KERNEL);
- add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PHYSDEVPATH=%s", path);
- kfree(path);
+ if (path) {
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "PHYSDEVPATH=%s", path);
+ kfree(path);
+ }
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
@@ -308,6 +310,9 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
return count;
}
+static struct device_attribute uevent_attr =
+ __ATTR(uevent, S_IRUGO | S_IWUSR, show_uevent, store_uevent);
+
static int device_add_attributes(struct device *dev,
struct device_attribute *attrs)
{
@@ -421,6 +426,9 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
return print_dev_t(buf, dev->devt);
}
+static struct device_attribute devt_attr =
+ __ATTR(dev, S_IRUGO, show_dev, NULL);
+
/*
* devices_subsys - structure to be registered with kobject core.
*/
@@ -679,35 +687,14 @@ int device_add(struct device *dev)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
- dev->uevent_attr.attr.name = "uevent";
- dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
- if (dev->driver)
- dev->uevent_attr.attr.owner = dev->driver->owner;
- dev->uevent_attr.store = store_uevent;
- dev->uevent_attr.show = show_uevent;
- error = device_create_file(dev, &dev->uevent_attr);
+ error = device_create_file(dev, &uevent_attr);
if (error)
goto attrError;
if (MAJOR(dev->devt)) {
- struct device_attribute *attr;
- attr = kzalloc(sizeof(*attr), GFP_KERNEL);
- if (!attr) {
- error = -ENOMEM;
- goto ueventattrError;
- }
- attr->attr.name = "dev";
- attr->attr.mode = S_IRUGO;
- if (dev->driver)
- attr->attr.owner = dev->driver->owner;
- attr->show = show_dev;
- error = device_create_file(dev, attr);
- if (error) {
- kfree(attr);
+ error = device_create_file(dev, &devt_attr);
+ if (error)
goto ueventattrError;
- }
-
- dev->devt_attr = attr;
}
if (dev->class) {
@@ -731,11 +718,14 @@ int device_add(struct device *dev)
}
}
- if ((error = device_add_attrs(dev)))
+ error = device_add_attrs(dev);
+ if (error)
goto AttrsError;
- if ((error = device_pm_add(dev)))
+ error = device_pm_add(dev);
+ if (error)
goto PMError;
- if ((error = bus_add_device(dev)))
+ error = bus_add_device(dev);
+ if (error)
goto BusError;
kobject_uevent(&dev->kobj, KOBJ_ADD);
bus_attach_device(dev);
@@ -765,10 +755,8 @@ int device_add(struct device *dev)
BUS_NOTIFY_DEL_DEVICE, dev);
device_remove_attrs(dev);
AttrsError:
- if (dev->devt_attr) {
- device_remove_file(dev, dev->devt_attr);
- kfree(dev->devt_attr);
- }
+ if (MAJOR(dev->devt))
+ device_remove_file(dev, &devt_attr);
if (dev->class) {
sysfs_remove_link(&dev->kobj, "subsystem");
@@ -790,7 +778,7 @@ int device_add(struct device *dev)
}
}
ueventattrError:
- device_remove_file(dev, &dev->uevent_attr);
+ device_remove_file(dev, &uevent_attr);
attrError:
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
@@ -867,10 +855,8 @@ void device_del(struct device * dev)
if (parent)
klist_del(&dev->knode_parent);
- if (dev->devt_attr) {
- device_remove_file(dev, dev->devt_attr);
- kfree(dev->devt_attr);
- }
+ if (MAJOR(dev->devt))
+ device_remove_file(dev, &devt_attr);
if (dev->class) {
sysfs_remove_link(&dev->kobj, "subsystem");
/* If this is not a "fake" compatible device, remove the
@@ -924,7 +910,7 @@ void device_del(struct device * dev)
up(&dev->class->sem);
}
}
- device_remove_file(dev, &dev->uevent_attr);
+ device_remove_file(dev, &uevent_attr);
device_remove_attrs(dev);
bus_remove_device(dev);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 92428e55b0c..7ac474db88c 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -207,19 +207,6 @@ static int __device_attach(struct device_driver * drv, void * data)
return driver_probe_device(drv, dev);
}
-static int device_probe_drivers(void *data)
-{
- struct device *dev = data;
- int ret = 0;
-
- if (dev->bus) {
- down(&dev->sem);
- ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
- up(&dev->sem);
- }
- return ret;
-}
-
/**
* device_attach - try to attach device to a driver.
* @dev: device.
@@ -294,24 +281,16 @@ int driver_attach(struct device_driver * drv)
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
-/**
- * device_release_driver - manually detach device from driver.
- * @dev: device.
- *
- * Manually detach device from driver.
- *
+/*
* __device_release_driver() must be called with @dev->sem held.
- * When called for a USB interface, @dev->parent->sem must be held
- * as well.
+ * When called for a USB interface, @dev->parent->sem must be held as well.
*/
-
static void __device_release_driver(struct device * dev)
{
struct device_driver * drv;
- drv = dev->driver;
+ drv = get_driver(dev->driver);
if (drv) {
- get_driver(drv);
driver_sysfs_remove(dev);
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
@@ -331,6 +310,13 @@ static void __device_release_driver(struct device * dev)
}
}
+/**
+ * device_release_driver - manually detach device from driver.
+ * @dev: device.
+ *
+ * Manually detach device from driver.
+ * When called for a USB interface, @dev->parent->sem must be held.
+ */
void device_release_driver(struct device * dev)
{
/*
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index e1c0730a3b9..e8beb8e5b62 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -10,6 +10,8 @@
#include <linux/device.h>
#include <linux/module.h>
+#include "base.h"
+
struct devres_node {
struct list_head entry;
dr_release_t release;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 97ab5bd1c4d..53f0ee6f301 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1,7 +1,7 @@
/*
* firmware_class.c - Multi purpose firmware loading support
*
- * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
+ * Copyright (c) 2003 Manuel Estrada Sainz
*
* Please see Documentation/firmware_class/ for more information.
*
@@ -23,7 +23,7 @@
#define to_dev(obj) container_of(obj, struct device, kobj)
-MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
+MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Multi purpose firmware loading support");
MODULE_LICENSE("GPL");
@@ -175,7 +175,7 @@ static ssize_t firmware_loading_store(struct device *dev,
static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
static ssize_t
-firmware_data_read(struct kobject *kobj,
+firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct device *dev = to_dev(kobj);
@@ -240,7 +240,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
* the driver as a firmware image.
**/
static ssize_t
-firmware_data_write(struct kobject *kobj,
+firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct device *dev = to_dev(kobj);
@@ -271,7 +271,7 @@ out:
}
static struct bin_attribute firmware_attr_data_tmpl = {
- .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
+ .attr = {.name = "data", .mode = 0644},
.size = 0,
.read = firmware_data_read,
.write = firmware_data_write,
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 05dc8764e76..eb9f38d0aa5 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -20,64 +20,44 @@
*/
#include <linux/device.h>
+#include <linux/mutex.h>
+
#include "power.h"
LIST_HEAD(dpm_active);
LIST_HEAD(dpm_off);
LIST_HEAD(dpm_off_irq);
-DECLARE_MUTEX(dpm_sem);
-DECLARE_MUTEX(dpm_list_sem);
+DEFINE_MUTEX(dpm_mtx);
+DEFINE_MUTEX(dpm_list_mtx);
int (*platform_enable_wakeup)(struct device *dev, int is_on);
-
-/**
- * device_pm_set_parent - Specify power dependency.
- * @dev: Device who needs power.
- * @parent: Device that supplies power.
- *
- * This function is used to manually describe a power-dependency
- * relationship. It may be used to specify a transversal relationship
- * (where the power supplier is not the physical (or electrical)
- * ancestor of a specific device.
- * The effect of this is that the supplier will not be powered down
- * before the power dependent.
- */
-
-void device_pm_set_parent(struct device * dev, struct device * parent)
-{
- put_device(dev->power.pm_parent);
- dev->power.pm_parent = get_device(parent);
-}
-EXPORT_SYMBOL_GPL(device_pm_set_parent);
-
-int device_pm_add(struct device * dev)
+int device_pm_add(struct device *dev)
{
int error;
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus",
kobject_name(&dev->kobj));
- down(&dpm_list_sem);
+ mutex_lock(&dpm_list_mtx);
list_add_tail(&dev->power.entry, &dpm_active);
- device_pm_set_parent(dev, dev->parent);
- if ((error = dpm_sysfs_add(dev)))
+ error = dpm_sysfs_add(dev);
+ if (error)
list_del(&dev->power.entry);
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
return error;
}
-void device_pm_remove(struct device * dev)
+void device_pm_remove(struct device *dev)
{
pr_debug("PM: Removing info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus",
kobject_name(&dev->kobj));
- down(&dpm_list_sem);
+ mutex_lock(&dpm_list_mtx);
dpm_sysfs_remove(dev);
- put_device(dev->power.pm_parent);
list_del_init(&dev->power.entry);
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
}
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index fb3d35a9e10..2760f25b3ac 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -14,12 +14,12 @@ extern void device_shutdown(void);
/*
* Used to synchronize global power management operations.
*/
-extern struct semaphore dpm_sem;
+extern struct mutex dpm_mtx;
/*
* Used to serialize changes to the dpm_* lists.
*/
-extern struct semaphore dpm_list_sem;
+extern struct mutex dpm_list_mtx;
/*
* The PM lists.
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index a2c64188d71..00fd84ae6e6 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -29,14 +29,6 @@ int resume_device(struct device * dev)
down(&dev->sem);
- if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state.event) {
- dev_err(dev, "PM: resume from %d, parent %s still %d\n",
- dev->power.power_state.event,
- dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state.event);
- }
-
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
error = dev->bus->resume(dev);
@@ -80,7 +72,7 @@ static int resume_device_early(struct device * dev)
*/
void dpm_resume(void)
{
- down(&dpm_list_sem);
+ mutex_lock(&dpm_list_mtx);
while(!list_empty(&dpm_off)) {
struct list_head * entry = dpm_off.next;
struct device * dev = to_device(entry);
@@ -88,13 +80,12 @@ void dpm_resume(void)
get_device(dev);
list_move_tail(entry, &dpm_active);
- up(&dpm_list_sem);
- if (!dev->power.prev_state.event)
- resume_device(dev);
- down(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
+ resume_device(dev);
+ mutex_lock(&dpm_list_mtx);
put_device(dev);
}
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
}
@@ -108,9 +99,9 @@ void dpm_resume(void)
void device_resume(void)
{
might_sleep();
- down(&dpm_sem);
+ mutex_lock(&dpm_mtx);
dpm_resume();
- up(&dpm_sem);
+ mutex_unlock(&dpm_mtx);
}
EXPORT_SYMBOL_GPL(device_resume);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 96370ec1d67..df6174d8586 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -32,9 +32,9 @@ static void runtime_resume(struct device * dev)
void dpm_runtime_resume(struct device * dev)
{
- down(&dpm_sem);
+ mutex_lock(&dpm_mtx);
runtime_resume(dev);
- up(&dpm_sem);
+ mutex_unlock(&dpm_mtx);
}
EXPORT_SYMBOL(dpm_runtime_resume);
@@ -49,7 +49,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
{
int error = 0;
- down(&dpm_sem);
+ mutex_lock(&dpm_mtx);
if (dev->power.power_state.event == state.event)
goto Done;
@@ -59,7 +59,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
if (!(error = suspend_device(dev, state)))
dev->power.power_state = state;
Done:
- up(&dpm_sem);
+ mutex_unlock(&dpm_mtx);
return error;
}
EXPORT_SYMBOL(dpm_runtime_suspend);
@@ -78,8 +78,8 @@ EXPORT_SYMBOL(dpm_runtime_suspend);
*/
void dpm_set_power_state(struct device * dev, pm_message_t state)
{
- down(&dpm_sem);
+ mutex_lock(&dpm_mtx);
dev->power.power_state = state;
- up(&dpm_sem);
+ mutex_unlock(&dpm_mtx);
}
#endif /* 0 */
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 42d2b86ba76..26df9b23173 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -40,6 +40,14 @@ static inline char *suspend_verb(u32 event)
}
+static void
+suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
+{
+ dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
+ ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
+ ", may wakeup" : "");
+}
+
/**
* suspend_device - Save state of one device.
* @dev: Device.
@@ -55,49 +63,21 @@ int suspend_device(struct device * dev, pm_message_t state)
dev_dbg(dev, "PM: suspend %d-->%d\n",
dev->power.power_state.event, state.event);
}
- if (dev->power.pm_parent
- && dev->power.pm_parent->power.power_state.event) {
- dev_err(dev,
- "PM: suspend %d->%d, parent %s already %d\n",
- dev->power.power_state.event, state.event,
- dev->power.pm_parent->bus_id,
- dev->power.pm_parent->power.power_state.event);
- }
-
- dev->power.prev_state = dev->power.power_state;
- if (dev->class && dev->class->suspend && !dev->power.power_state.event) {
- dev_dbg(dev, "class %s%s\n",
- suspend_verb(state.event),
- ((state.event == PM_EVENT_SUSPEND)
- && device_may_wakeup(dev))
- ? ", may wakeup"
- : ""
- );
+ if (dev->class && dev->class->suspend) {
+ suspend_device_dbg(dev, state, "class ");
error = dev->class->suspend(dev, state);
suspend_report_result(dev->class->suspend, error);
}
- if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) {
- dev_dbg(dev, "%s%s\n",
- suspend_verb(state.event),
- ((state.event == PM_EVENT_SUSPEND)
- && device_may_wakeup(dev))
- ? ", may wakeup"
- : ""
- );
+ if (!error && dev->type && dev->type->suspend) {
+ suspend_device_dbg(dev, state, "type ");
error = dev->type->suspend(dev, state);
suspend_report_result(dev->type->suspend, error);
}
- if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
- dev_dbg(dev, "%s%s\n",
- suspend_verb(state.event),
- ((state.event == PM_EVENT_SUSPEND)
- && device_may_wakeup(dev))
- ? ", may wakeup"
- : ""
- );
+ if (!error && dev->bus && dev->bus->suspend) {
+ suspend_device_dbg(dev, state, "");
error = dev->bus->suspend(dev, state);
suspend_report_result(dev->bus->suspend, error);
}
@@ -108,21 +88,15 @@ int suspend_device(struct device * dev, pm_message_t state)
/*
* This is called with interrupts off, only a single CPU
- * running. We can't do down() on a semaphore (and we don't
+ * running. We can't acquire a mutex or semaphore (and we don't
* need the protection)
*/
static int suspend_device_late(struct device *dev, pm_message_t state)
{
int error = 0;
- if (dev->bus && dev->bus->suspend_late && !dev->power.power_state.event) {
- dev_dbg(dev, "LATE %s%s\n",
- suspend_verb(state.event),
- ((state.event == PM_EVENT_SUSPEND)
- && device_may_wakeup(dev))
- ? ", may wakeup"
- : ""
- );
+ if (dev->bus && dev->bus->suspend_late) {
+ suspend_device_dbg(dev, state, "LATE ");
error = dev->bus->suspend_late(dev, state);
suspend_report_result(dev->bus->suspend_late, error);
}
@@ -153,18 +127,18 @@ int device_suspend(pm_message_t state)
int error = 0;
might_sleep();
- down(&dpm_sem);
- down(&dpm_list_sem);
+ mutex_lock(&dpm_mtx);
+ mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_active) && error == 0) {
struct list_head * entry = dpm_active.prev;
struct device * dev = to_device(entry);
get_device(dev);
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
error = suspend_device(dev, state);
- down(&dpm_list_sem);
+ mutex_lock(&dpm_list_mtx);
/* Check if the device got removed */
if (!list_empty(&dev->power.entry)) {
@@ -179,11 +153,11 @@ int device_suspend(pm_message_t state)
error == -EAGAIN ? " (please convert to suspend_late)" : "");
put_device(dev);
}
- up(&dpm_list_sem);
+ mutex_unlock(&dpm_list_mtx);
if (error)
dpm_resume();
- up(&dpm_sem);
+ mutex_unlock(&dpm_mtx);
return error;
}
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 29f1291966c..18febe26caa 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -21,7 +21,7 @@
#include <linux/string.h>
#include <linux/pm.h>
#include <linux/device.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
#include "base.h"
@@ -155,7 +155,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregister);
static LIST_HEAD(sysdev_drivers);
-static DECLARE_MUTEX(sysdev_drivers_lock);
+static DEFINE_MUTEX(sysdev_drivers_lock);
/**
* sysdev_driver_register - Register auxillary driver
@@ -172,7 +172,7 @@ static DECLARE_MUTEX(sysdev_drivers_lock);
int sysdev_driver_register(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
- down(&sysdev_drivers_lock);
+ mutex_lock(&sysdev_drivers_lock);
if (cls && kset_get(&cls->kset)) {
list_add_tail(&drv->entry, &cls->drivers);
@@ -184,7 +184,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
}
} else
list_add_tail(&drv->entry, &sysdev_drivers);
- up(&sysdev_drivers_lock);
+ mutex_unlock(&sysdev_drivers_lock);
return 0;
}
@@ -197,7 +197,7 @@ int sysdev_driver_register(struct sysdev_class * cls,
void sysdev_driver_unregister(struct sysdev_class * cls,
struct sysdev_driver * drv)
{
- down(&sysdev_drivers_lock);
+ mutex_lock(&sysdev_drivers_lock);
list_del_init(&drv->entry);
if (cls) {
if (drv->remove) {
@@ -207,7 +207,7 @@ void sysdev_driver_unregister(struct sysdev_class * cls,
}
kset_put(&cls->kset);
}
- up(&sysdev_drivers_lock);
+ mutex_unlock(&sysdev_drivers_lock);
}
EXPORT_SYMBOL_GPL(sysdev_driver_register);
@@ -246,7 +246,7 @@ int sysdev_register(struct sys_device * sysdev)
if (!error) {
struct sysdev_driver * drv;
- down(&sysdev_drivers_lock);
+ mutex_lock(&sysdev_drivers_lock);
/* Generic notification is implicit, because it's that
* code that should have called us.
*/
@@ -262,7 +262,7 @@ int sysdev_register(struct sys_device * sysdev)
if (drv->add)
drv->add(sysdev);
}
- up(&sysdev_drivers_lock);
+ mutex_unlock(&sysdev_drivers_lock);
}
return error;
}
@@ -271,7 +271,7 @@ void sysdev_unregister(struct sys_device * sysdev)
{
struct sysdev_driver * drv;
- down(&sysdev_drivers_lock);
+ mutex_lock(&sysdev_drivers_lock);
list_for_each_entry(drv, &sysdev_drivers, entry) {
if (drv->remove)
drv->remove(sysdev);
@@ -281,7 +281,7 @@ void sysdev_unregister(struct sys_device * sysdev)
if (drv->remove)
drv->remove(sysdev);
}
- up(&sysdev_drivers_lock);
+ mutex_unlock(&sysdev_drivers_lock);
kobject_unregister(&sysdev->kobj);
}
@@ -308,7 +308,7 @@ void sysdev_shutdown(void)
pr_debug("Shutting Down System Devices\n");
- down(&sysdev_drivers_lock);
+ mutex_lock(&sysdev_drivers_lock);
list_for_each_entry_reverse(cls, &system_subsys.list,
kset.kobj.entry) {
struct sys_device * sysdev;
@@ -337,7 +337,7 @@ void sysdev_shutdown(void)
cls->shutdown(sysdev);
}
}
- up(&sysdev_drivers_lock);
+ mutex_unlock(&sysdev_drivers_lock);
}
static void __sysdev_resume(struct sys_device *dev)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b4c8319138b..6e23af1ecbd 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -2,9 +2,12 @@
# Block device driver configuration
#
-if BLOCK
+menuconfig BLK_DEV
+ bool "Block devices"
+ depends on BLOCK
+ default y
-menu "Block devices"
+if BLK_DEV
config BLK_DEV_FD
tristate "Normal floppy disk support"
@@ -56,40 +59,9 @@ config AMIGA_Z2RAM
To compile this driver as a module, choose M here: the
module will be called z2ram.
-config ATARI_ACSI
- tristate "Atari ACSI support"
- depends on ATARI && BROKEN
- ---help---
- This enables support for the Atari ACSI interface. The driver
- supports hard disks and CD-ROMs, which have 512-byte sectors, or can
- be switched to that mode. Due to the ACSI command format, only disks
- up to 1 GB are supported. Special support for certain ACSI to SCSI
- adapters, which could relax that, isn't included yet. The ACSI
- driver is also the basis for certain other drivers for devices
- attached to the ACSI bus: Atari SLM laser printer, BioNet-100
- Ethernet, and PAMsNet Ethernet. If you want to use one of these
- devices, you need ACSI support, too.
-
- To compile this driver as a module, choose M here: the
- module will be called acsi.
-
-comment "Some devices (e.g. CD jukebox) support multiple LUNs"
- depends on ATARI && ATARI_ACSI
-
-config ACSI_MULTI_LUN
- bool "Probe all LUNs on each ACSI device"
- depends on ATARI_ACSI
- help
- If you have a ACSI device that supports more than one LUN (Logical
- Unit Number), e.g. a CD jukebox, you should say Y here so that all
- will be found by the ACSI driver. An ACSI device with multiple LUNs
- acts logically like multiple ACSI devices. The vast majority of ACSI
- devices have only one LUN, and so most people can say N here and
- should in fact do so, because it is safer.
-
config ATARI_SLM
tristate "Atari SLM laser printer support"
- depends on ATARI && ATARI_ACSI!=n
+ depends on ATARI
help
If you have an Atari SLM laser printer, say Y to include support for
it in the kernel. Otherwise, say N. This driver is also available as
@@ -453,6 +425,4 @@ config ATA_OVER_ETH
source "drivers/s390/block/Kconfig"
-endmenu
-
-endif
+endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index dd88e33c1eb..e5f98acc5d5 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o
obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
-obj-$(CONFIG_ATARI_ACSI) += acsi.o
obj-$(CONFIG_ATARI_SLM) += acsi_slm.o
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
obj-$(CONFIG_BLK_DEV_RAM) += rd.o
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
deleted file mode 100644
index e3d9152e231..00000000000
--- a/drivers/block/acsi.c
+++ /dev/null
@@ -1,1825 +0,0 @@
-/*
- * acsi.c -- Device driver for Atari ACSI hard disks
- *
- * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *
- * Some parts are based on hd.c by Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive for
- * more details.
- *
- */
-
-/*
- * Still to in this file:
- * - If a command ends with an error status (!= 0), the following
- * REQUEST SENSE commands (4 to fill the ST-DMA FIFO) are done by
- * polling the _IRQ signal (not interrupt-driven). This should be
- * avoided in future because it takes up a non-neglectible time in
- * the interrupt service routine while interrupts are disabled.
- * Maybe a timer interrupt will get lost :-(
- */
-
-/*
- * General notes:
- *
- * - All ACSI devices (disks, CD-ROMs, ...) use major number 28.
- * Minors are organized like it is with SCSI: The upper 4 bits
- * identify the device, the lower 4 bits the partition.
- * The device numbers (the upper 4 bits) are given in the same
- * order as the devices are found on the bus.
- * - Up to 8 LUNs are supported for each target (if CONFIG_ACSI_MULTI_LUN
- * is defined), but only a total of 16 devices (due to minor
- * numbers...). Note that Atari allows only a maximum of 4 targets
- * (i.e. controllers, not devices) on the ACSI bus!
- * - A optimizing scheme similar to SCSI scatter-gather is implemented.
- * - Removable media are supported. After a medium change to device
- * is reinitialized (partition check etc.). Also, if the device
- * knows the PREVENT/ALLOW MEDIUM REMOVAL command, the door should
- * be locked and unlocked when mounting the first or unmounting the
- * last filesystem on the device. The code is untested, because I
- * don't have a removable hard disk.
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/genhd.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */
-#include <scsi/scsi_ioctl.h>
-#include <linux/hdreg.h> /* for HDIO_GETGEO */
-#include <linux/blkpg.h>
-#include <linux/buffer_head.h>
-#include <linux/blkdev.h>
-
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/atarihw.h>
-#include <asm/atariints.h>
-#include <asm/atari_acsi.h>
-#include <asm/atari_stdma.h>
-#include <asm/atari_stram.h>
-
-static void (*do_acsi)(void) = NULL;
-static struct request_queue *acsi_queue;
-#define QUEUE (acsi_queue)
-#define CURRENT elv_next_request(acsi_queue)
-
-#define DEBUG
-#undef DEBUG_DETECT
-#undef NO_WRITE
-
-#define MAX_ERRORS 8 /* Max read/write errors/sector */
-#define MAX_LUN 8 /* Max LUNs per target */
-#define MAX_DEV 16
-
-#define ACSI_BUFFER_SIZE (16*1024) /* "normal" ACSI buffer size */
-#define ACSI_BUFFER_MINSIZE (2048) /* min. buf size if ext. DMA */
-#define ACSI_BUFFER_SIZE_ORDER 2 /* order size for above */
-#define ACSI_BUFFER_MINSIZE_ORDER 0 /* order size for above */
-#define ACSI_BUFFER_SECTORS (ACSI_BUFFER_SIZE/512)
-
-#define ACSI_BUFFER_ORDER \
- (ATARIHW_PRESENT(EXTD_DMA) ? \
- ACSI_BUFFER_MINSIZE_ORDER : \
- ACSI_BUFFER_SIZE_ORDER)
-
-#define ACSI_TIMEOUT (4*HZ)
-
-/* minimum delay between two commands */
-
-#define COMMAND_DELAY 500
-
-typedef enum {
- NONE, HARDDISK, CDROM
-} ACSI_TYPE;
-
-struct acsi_info_struct {
- ACSI_TYPE type; /* type of device */
- unsigned target; /* target number */
- unsigned lun; /* LUN in target controller */
- unsigned removable : 1; /* Flag for removable media */
- unsigned read_only : 1; /* Flag for read only devices */
- unsigned old_atari_disk : 1; /* Is an old Atari disk */
- unsigned changed : 1; /* Medium has been changed */
- unsigned long size; /* #blocks */
- int access_count;
-} acsi_info[MAX_DEV];
-
-/*
- * SENSE KEYS
- */
-
-#define NO_SENSE 0x00
-#define RECOVERED_ERROR 0x01
-#define NOT_READY 0x02
-#define MEDIUM_ERROR 0x03
-#define HARDWARE_ERROR 0x04
-#define ILLEGAL_REQUEST 0x05
-#define UNIT_ATTENTION 0x06
-#define DATA_PROTECT 0x07
-#define BLANK_CHECK 0x08
-#define COPY_ABORTED 0x0a
-#define ABORTED_COMMAND 0x0b
-#define VOLUME_OVERFLOW 0x0d
-#define MISCOMPARE 0x0e
-
-
-/*
- * DEVICE TYPES
- */
-
-#define TYPE_DISK 0x00
-#define TYPE_TAPE 0x01
-#define TYPE_WORM 0x04
-#define TYPE_ROM 0x05
-#define TYPE_MOD 0x07
-#define TYPE_NO_LUN 0x7f
-
-/* The data returned by MODE SENSE differ between the old Atari
- * hard disks and SCSI disks connected to ACSI. In the following, both
- * formats are defined and some macros to operate on them potably.
- */
-
-typedef struct {
- unsigned long dummy[2];
- unsigned long sector_size;
- unsigned char format_code;
-#define ATARI_SENSE_FORMAT_FIX 1
-#define ATARI_SENSE_FORMAT_CHNG 2
- unsigned char cylinders_h;
- unsigned char cylinders_l;
- unsigned char heads;
- unsigned char reduced_h;
- unsigned char reduced_l;
- unsigned char precomp_h;
- unsigned char precomp_l;
- unsigned char landing_zone;
- unsigned char steprate;
- unsigned char type;
-#define ATARI_SENSE_TYPE_FIXCHNG_MASK 4
-#define ATARI_SENSE_TYPE_SOFTHARD_MASK 8
-#define ATARI_SENSE_TYPE_FIX 4
-#define ATARI_SENSE_TYPE_CHNG 0
-#define ATARI_SENSE_TYPE_SOFT 0
-#define ATARI_SENSE_TYPE_HARD 8
- unsigned char sectors;
-} ATARI_SENSE_DATA;
-
-#define ATARI_CAPACITY(sd) \
- (((int)((sd).cylinders_h<<8)|(sd).cylinders_l) * \
- (sd).heads * (sd).sectors)
-
-
-typedef struct {
- unsigned char dummy1;
- unsigned char medium_type;
- unsigned char dummy2;
- unsigned char descriptor_size;
- unsigned long block_count;
- unsigned long sector_size;
- /* Page 0 data */
- unsigned char page_code;
- unsigned char page_size;
- unsigned char page_flags;
- unsigned char qualifier;
-} SCSI_SENSE_DATA;
-
-#define SCSI_CAPACITY(sd) ((sd).block_count & 0xffffff)
-
-
-typedef union {
- ATARI_SENSE_DATA atari;
- SCSI_SENSE_DATA scsi;
-} SENSE_DATA;
-
-#define SENSE_TYPE_UNKNOWN 0
-#define SENSE_TYPE_ATARI 1
-#define SENSE_TYPE_SCSI 2
-
-#define SENSE_TYPE(sd) \
- (((sd).atari.dummy[0] == 8 && \
- ((sd).atari.format_code == 1 || \
- (sd).atari.format_code == 2)) ? SENSE_TYPE_ATARI : \
- ((sd).scsi.dummy1 >= 11) ? SENSE_TYPE_SCSI : \
- SENSE_TYPE_UNKNOWN)
-
-#define CAPACITY(sd) \
- (SENSE_TYPE(sd) == SENSE_TYPE_ATARI ? \
- ATARI_CAPACITY((sd).atari) : \
- SCSI_CAPACITY((sd).scsi))
-
-#define SECTOR_SIZE(sd) \
- (SENSE_TYPE(sd) == SENSE_TYPE_ATARI ? \
- (sd).atari.sector_size : \
- (sd).scsi.sector_size & 0xffffff)
-
-/* Default size if capacity cannot be determined (1 GByte) */
-#define DEFAULT_SIZE 0x1fffff
-
-#define CARTRCH_STAT(aip,buf) \
- (aip->old_atari_disk ? \
- (((buf)[0] & 0x7f) == 0x28) : \
- ((((buf)[0] & 0x70) == 0x70) ? \
- (((buf)[2] & 0x0f) == 0x06) : \
- (((buf)[0] & 0x0f) == 0x06))) \
-
-/* These two are also exported to other drivers that work on the ACSI bus and
- * need an ST-RAM buffer. */
-char *acsi_buffer;
-unsigned long phys_acsi_buffer;
-
-static int NDevices;
-
-static int CurrentNReq;
-static int CurrentNSect;
-static char *CurrentBuffer;
-
-static DEFINE_SPINLOCK(acsi_lock);
-
-
-#define SET_TIMER() mod_timer(&acsi_timer, jiffies + ACSI_TIMEOUT)
-#define CLEAR_TIMER() del_timer(&acsi_timer)
-
-static unsigned long STramMask;
-#define STRAM_ADDR(a) (((a) & STramMask) == 0)
-
-
-
-/* ACSI commands */
-
-static char tur_cmd[6] = { 0x00, 0, 0, 0, 0, 0 };
-static char modesense_cmd[6] = { 0x1a, 0, 0, 0, 24, 0 };
-static char modeselect_cmd[6] = { 0x15, 0, 0, 0, 12, 0 };
-static char inquiry_cmd[6] = { 0x12, 0, 0, 0,255, 0 };
-static char reqsense_cmd[6] = { 0x03, 0, 0, 0, 4, 0 };
-static char read_cmd[6] = { 0x08, 0, 0, 0, 0, 0 };
-static char write_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 };
-static char pa_med_rem_cmd[6] = { 0x1e, 0, 0, 0, 0, 0 };
-
-#define CMDSET_TARG_LUN(cmd,targ,lun) \
- do { \
- cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5; \
- cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \
- } while(0)
-
-#define CMDSET_BLOCK(cmd,blk) \
- do { \
- unsigned long __blk = (blk); \
- cmd[3] = __blk; __blk >>= 8; \
- cmd[2] = __blk; __blk >>= 8; \
- cmd[1] = (cmd[1] & 0xe0) | (__blk & 0x1f); \
- } while(0)
-
-#define CMDSET_LEN(cmd,len) \
- do { \
- cmd[4] = (len); \
- } while(0)
-
-/* ACSI errors (from REQUEST SENSE); There are two tables, one for the
- * old Atari disks and one for SCSI on ACSI disks.
- */
-
-struct acsi_error {
- unsigned char code;
- const char *text;
-} atari_acsi_errors[] = {
- { 0x00, "No error (??)" },
- { 0x01, "No index pulses" },
- { 0x02, "Seek not complete" },
- { 0x03, "Write fault" },
- { 0x04, "Drive not ready" },
- { 0x06, "No Track 00 signal" },
- { 0x10, "ECC error in ID field" },
- { 0x11, "Uncorrectable data error" },
- { 0x12, "ID field address mark not found" },
- { 0x13, "Data field address mark not found" },
- { 0x14, "Record not found" },
- { 0x15, "Seek error" },
- { 0x18, "Data check in no retry mode" },
- { 0x19, "ECC error during verify" },
- { 0x1a, "Access to bad block" },
- { 0x1c, "Unformatted or bad format" },
- { 0x20, "Invalid command" },
- { 0x21, "Invalid block address" },
- { 0x23, "Volume overflow" },
- { 0x24, "Invalid argument" },
- { 0x25, "Invalid drive number" },
- { 0x26, "Byte zero parity check" },
- { 0x28, "Cartride changed" },
- { 0x2c, "Error count overflow" },
- { 0x30, "Controller selftest failed" }
-},
-
- scsi_acsi_errors[] = {
- { 0x00, "No error (??)" },
- { 0x01, "Recovered error" },
- { 0x02, "Drive not ready" },
- { 0x03, "Uncorrectable medium error" },
- { 0x04, "Hardware error" },
- { 0x05, "Illegal request" },
- { 0x06, "Unit attention (Reset or cartridge changed)" },
- { 0x07, "Data protection" },
- { 0x08, "Blank check" },
- { 0x0b, "Aborted Command" },
- { 0x0d, "Volume overflow" }
-};
-
-
-
-/***************************** Prototypes *****************************/
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
- rwflag, int enable);
-static int acsi_reqsense( char *buffer, int targ, int lun);
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip);
-static irqreturn_t acsi_interrupt (int irq, void *data);
-static void unexpected_acsi_interrupt( void );
-static void bad_rw_intr( void );
-static void read_intr( void );
-static void write_intr( void);
-static void acsi_times_out( unsigned long dummy );
-static void copy_to_acsibuffer( void );
-static void copy_from_acsibuffer( void );
-static void do_end_requests( void );
-static void do_acsi_request( request_queue_t * );
-static void redo_acsi_request( void );
-static int acsi_ioctl( struct inode *inode, struct file *file, unsigned int
- cmd, unsigned long arg );
-static int acsi_open( struct inode * inode, struct file * filp );
-static int acsi_release( struct inode * inode, struct file * file );
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag );
-static int acsi_change_blk_size( int target, int lun);
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
-static int acsi_revalidate (struct gendisk *disk);
-
-/************************* End of Prototypes **************************/
-
-
-DEFINE_TIMER(acsi_timer, acsi_times_out, 0, 0);
-
-
-#ifdef CONFIG_ATARI_SLM
-
-extern int attach_slm( int target, int lun );
-extern int slm_init( void );
-
-#endif
-
-
-
-/***********************************************************************
- *
- * ACSI primitives
- *
- **********************************************************************/
-
-
-/*
- * The following two functions wait for _IRQ to become Low or High,
- * resp., with a timeout. The 'timeout' parameter is in jiffies
- * (10ms).
- * If the functions are called with timer interrupts on (int level <
- * 6), the timeout is based on the 'jiffies' variable to provide exact
- * timeouts for device probing etc.
- * If interrupts are disabled, the number of tries is based on the
- * 'loops_per_jiffy' variable. A rough estimation is sufficient here...
- */
-
-#define INT_LEVEL \
- ({ unsigned __sr; \
- __asm__ __volatile__ ( "movew %/sr,%0" : "=dm" (__sr) ); \
- (__sr >> 8) & 7; \
- })
-
-int acsi_wait_for_IRQ( unsigned timeout )
-
-{
- if (INT_LEVEL < 6) {
- unsigned long maxjif = jiffies + timeout;
- while (time_before(jiffies, maxjif))
- if (!(mfp.par_dt_reg & 0x20)) return( 1 );
- }
- else {
- long tries = loops_per_jiffy / 8 * timeout;
- while( --tries >= 0 )
- if (!(mfp.par_dt_reg & 0x20)) return( 1 );
- }
- return( 0 ); /* timeout! */
-}
-
-
-int acsi_wait_for_noIRQ( unsigned timeout )
-
-{
- if (INT_LEVEL < 6) {
- unsigned long maxjif = jiffies + timeout;
- while (time_before(jiffies, maxjif))
- if (mfp.par_dt_reg & 0x20) return( 1 );
- }
- else {
- long tries = loops_per_jiffy * timeout / 8;
- while( tries-- >= 0 )
- if (mfp.par_dt_reg & 0x20) return( 1 );
- }
- return( 0 ); /* timeout! */
-}
-
-static struct timeval start_time;
-
-void
-acsi_delay_start(void)
-{
- do_gettimeofday(&start_time);
-}
-
-/* wait from acsi_delay_start to now usec (<1E6) usec */
-
-void
-acsi_delay_end(long usec)
-{
- struct timeval end_time;
- long deltau,deltas;
- do_gettimeofday(&end_time);
- deltau=end_time.tv_usec - start_time.tv_usec;
- deltas=end_time.tv_sec - start_time.tv_sec;
- if (deltas > 1 || deltas < 0)
- return;
- if (deltas > 0)
- deltau += 1000*1000;
- if (deltau >= usec)
- return;
- udelay(usec-deltau);
-}
-
-/* acsicmd_dma() sends an ACSI command and sets up the DMA to transfer
- * 'blocks' blocks of 512 bytes from/to 'buffer'.
- * Because the _IRQ signal is used for handshaking the command bytes,
- * the ACSI interrupt has to be disabled in this function. If the end
- * of the operation should be signalled by a real interrupt, it has to be
- * reenabled afterwards.
- */
-
-static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, int enable)
-
-{ unsigned long flags, paddr;
- int i;
-
-#ifdef NO_WRITE
- if (rwflag || *cmd == 0x0a) {
- printk( "ACSI: Write commands disabled!\n" );
- return( 0 );
- }
-#endif
-
- rwflag = rwflag ? 0x100 : 0;
- paddr = virt_to_phys( buffer );
-
- acsi_delay_end(COMMAND_DELAY);
- DISABLE_IRQ();
-
- local_irq_save(flags);
- /* Low on A1 */
- dma_wd.dma_mode_status = 0x88 | rwflag;
- MFPDELAY();
-
- /* set DMA address */
- dma_wd.dma_lo = (unsigned char)paddr;
- paddr >>= 8;
- MFPDELAY();
- dma_wd.dma_md = (unsigned char)paddr;
- paddr >>= 8;
- MFPDELAY();
- if (ATARIHW_PRESENT(EXTD_DMA))
- st_dma_ext_dmahi = (unsigned short)paddr;
- else
- dma_wd.dma_hi = (unsigned char)paddr;
- MFPDELAY();
- local_irq_restore(flags);
-
- /* send the command bytes except the last */
- for( i = 0; i < 5; ++i ) {
- DMA_LONG_WRITE( *cmd++, 0x8a | rwflag );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
-
- /* Clear FIFO and switch DMA to correct direction */
- dma_wd.dma_mode_status = 0x92 | (rwflag ^ 0x100);
- MFPDELAY();
- dma_wd.dma_mode_status = 0x92 | rwflag;
- MFPDELAY();
-
- /* How many sectors for DMA */
- dma_wd.fdc_acces_seccount = blocks;
- MFPDELAY();
-
- /* send last command byte */
- dma_wd.dma_mode_status = 0x8a | rwflag;
- MFPDELAY();
- DMA_LONG_WRITE( *cmd++, 0x0a | rwflag );
- if (enable)
- ENABLE_IRQ();
- udelay(80);
-
- return( 1 );
-}
-
-
-/*
- * acsicmd_nodma() sends an ACSI command that requires no DMA.
- */
-
-int acsicmd_nodma( const char *cmd, int enable)
-
-{ int i;
-
- acsi_delay_end(COMMAND_DELAY);
- DISABLE_IRQ();
-
- /* send first command byte */
- dma_wd.dma_mode_status = 0x88;
- MFPDELAY();
- DMA_LONG_WRITE( *cmd++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
-
- /* send the intermediate command bytes */
- for( i = 0; i < 4; ++i ) {
- DMA_LONG_WRITE( *cmd++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
-
- /* send last command byte */
- DMA_LONG_WRITE( *cmd++, 0x0a );
- if (enable)
- ENABLE_IRQ();
- udelay(80);
-
- return( 1 );
- /* Note that the ACSI interrupt is still disabled after this
- * function. If you want to get the IRQ delivered, enable it manually!
- */
-}
-
-
-static int acsi_reqsense( char *buffer, int targ, int lun)
-
-{
- CMDSET_TARG_LUN( reqsense_cmd, targ, lun);
- if (!acsicmd_dma( reqsense_cmd, buffer, 1, 0, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
- if (!acsi_wait_for_IRQ( 10 )) return( 0 );
- acsi_getstatus();
- dma_cache_maintenance( virt_to_phys(buffer), 16, 0 );
-
- return( 1 );
-}
-
-
-/*
- * ACSI status phase: get the status byte from the bus
- *
- * I've seen several times that a 0xff status is read, propably due to
- * a timing error. In this case, the procedure is repeated after the
- * next _IRQ edge.
- */
-
-int acsi_getstatus( void )
-
-{ int status;
-
- DISABLE_IRQ();
- for(;;) {
- if (!acsi_wait_for_IRQ( 100 )) {
- acsi_delay_start();
- return( -1 );
- }
- dma_wd.dma_mode_status = 0x8a;
- MFPDELAY();
- status = dma_wd.fdc_acces_seccount;
- if (status != 0xff) break;
-#ifdef DEBUG
- printk("ACSI: skipping 0xff status byte\n" );
-#endif
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
- }
- dma_wd.dma_mode_status = 0x80;
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
-
- acsi_delay_start();
- return( status & 0x1f ); /* mask of the device# */
-}
-
-
-#if (defined(CONFIG_ATARI_SLM) || defined(CONFIG_ATARI_SLM_MODULE))
-
-/* Receive data in an extended status phase. Needed by SLM printer. */
-
-int acsi_extstatus( char *buffer, int cnt )
-
-{ int status;
-
- DISABLE_IRQ();
- udelay(80);
- while( cnt-- > 0 ) {
- if (!acsi_wait_for_IRQ( 40 )) return( 0 );
- dma_wd.dma_mode_status = 0x8a;
- MFPDELAY();
- status = dma_wd.fdc_acces_seccount;
- MFPDELAY();
- *buffer++ = status & 0xff;
- udelay(40);
- }
- return( 1 );
-}
-
-
-/* Finish an extended status phase */
-
-void acsi_end_extstatus( void )
-
-{
- dma_wd.dma_mode_status = 0x80;
- udelay(40);
- acsi_wait_for_noIRQ( 20 );
- acsi_delay_start();
-}
-
-
-/* Send data in an extended command phase */
-
-int acsi_extcmd( unsigned char *buffer, int cnt )
-
-{
- while( cnt-- > 0 ) {
- DMA_LONG_WRITE( *buffer++, 0x8a );
- udelay(20);
- if (!acsi_wait_for_IRQ( HZ/2 )) return( 0 ); /* timeout */
- }
- return( 1 );
-}
-
-#endif
-
-
-static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip)
-
-{ int atari_err, i, errcode;
- struct acsi_error *arr;
-
- atari_err = aip->old_atari_disk;
- if (atari_err)
- errcode = errblk[0] & 0x7f;
- else
- if ((errblk[0] & 0x70) == 0x70)
- errcode = errblk[2] & 0x0f;
- else
- errcode = errblk[0] & 0x0f;
-
- printk( KERN_ERR "ACSI error 0x%02x", errcode );
-
- if (errblk[0] & 0x80)
- printk( " for sector %d",
- ((errblk[1] & 0x1f) << 16) |
- (errblk[2] << 8) | errblk[0] );
-
- arr = atari_err ? atari_acsi_errors : scsi_acsi_errors;
- i = atari_err ? sizeof(atari_acsi_errors)/sizeof(*atari_acsi_errors) :
- sizeof(scsi_acsi_errors)/sizeof(*scsi_acsi_errors);
-
- for( --i; i >= 0; --i )
- if (arr[i].code == errcode) break;
- if (i >= 0)
- printk( ": %s\n", arr[i].text );
-}
-
-/*******************************************************************
- *
- * ACSI interrupt routine
- * Test, if this is a ACSI interrupt and call the irq handler
- * Otherwise ignore this interrupt.
- *
- *******************************************************************/
-
-static irqreturn_t acsi_interrupt(int irq, void *data )
-
-{ void (*acsi_irq_handler)(void) = do_acsi;
-
- do_acsi = NULL;
- CLEAR_TIMER();
-
- if (!acsi_irq_handler)
- acsi_irq_handler = unexpected_acsi_interrupt;
- acsi_irq_handler();
- return IRQ_HANDLED;
-}
-
-
-/******************************************************************
- *
- * The Interrupt handlers
- *
- *******************************************************************/
-
-
-static void unexpected_acsi_interrupt( void )
-
-{
- printk( KERN_WARNING "Unexpected ACSI interrupt\n" );
-}
-
-
-/* This function is called in case of errors. Because we cannot reset
- * the ACSI bus or a single device, there is no other choice than
- * retrying several times :-(
- */
-
-static void bad_rw_intr( void )
-
-{
- if (!CURRENT)
- return;
-
- if (++CURRENT->errors >= MAX_ERRORS)
- end_request(CURRENT, 0);
- /* Otherwise just retry */
-}
-
-
-static void read_intr( void )
-
-{ int status;
-
- status = acsi_getstatus();
- if (status != 0) {
- struct gendisk *disk = CURRENT->rq_disk;
- struct acsi_info_struct *aip = disk->private_data;
- printk(KERN_ERR "%s: ", disk->disk_name);
- if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun))
- printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
- else {
- acsi_print_error(acsi_buffer, aip);
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- ENABLE_IRQ();
- bad_rw_intr();
- redo_acsi_request();
- return;
- }
-
- dma_cache_maintenance( virt_to_phys(CurrentBuffer), CurrentNSect*512, 0 );
- if (CurrentBuffer == acsi_buffer)
- copy_from_acsibuffer();
-
- do_end_requests();
- redo_acsi_request();
-}
-
-
-static void write_intr(void)
-
-{ int status;
-
- status = acsi_getstatus();
- if (status != 0) {
- struct gendisk *disk = CURRENT->rq_disk;
- struct acsi_info_struct *aip = disk->private_data;
- printk( KERN_ERR "%s: ", disk->disk_name);
- if (!acsi_reqsense( acsi_buffer, aip->target, aip->lun))
- printk( "ACSI error and REQUEST SENSE failed (status=0x%02x)\n", status );
- else {
- acsi_print_error(acsi_buffer, aip);
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- bad_rw_intr();
- redo_acsi_request();
- return;
- }
-
- do_end_requests();
- redo_acsi_request();
-}
-
-
-static void acsi_times_out( unsigned long dummy )
-
-{
- DISABLE_IRQ();
- if (!do_acsi) return;
-
- do_acsi = NULL;
- printk( KERN_ERR "ACSI timeout\n" );
- if (!CURRENT)
- return;
- if (++CURRENT->errors >= MAX_ERRORS) {
-#ifdef DEBUG
- printk( KERN_ERR "ACSI: too many errors.\n" );
-#endif
- end_request(CURRENT, 0);
- }
-
- redo_acsi_request();
-}
-
-
-
-/***********************************************************************
- *
- * Scatter-gather utility functions
- *
- ***********************************************************************/
-
-
-static void copy_to_acsibuffer( void )
-
-{ int i;
- char *src, *dst;
- struct buffer_head *bh;
-
- src = CURRENT->buffer;
- dst = acsi_buffer;
- bh = CURRENT->bh;
-
- if (!bh)
- memcpy( dst, src, CurrentNSect*512 );
- else
- for( i = 0; i < CurrentNReq; ++i ) {
- memcpy( dst, src, bh->b_size );
- dst += bh->b_size;
- if ((bh = bh->b_reqnext))
- src = bh->b_data;
- }
-}
-
-
-static void copy_from_acsibuffer( void )
-
-{ int i;
- char *src, *dst;
- struct buffer_head *bh;
-
- dst = CURRENT->buffer;
- src = acsi_buffer;
- bh = CURRENT->bh;
-
- if (!bh)
- memcpy( dst, src, CurrentNSect*512 );
- else
- for( i = 0; i < CurrentNReq; ++i ) {
- memcpy( dst, src, bh->b_size );
- src += bh->b_size;
- if ((bh = bh->b_reqnext))
- dst = bh->b_data;
- }
-}
-
-
-static void do_end_requests( void )
-
-{ int i, n;
-
- if (!CURRENT->bh) {
- CURRENT->nr_sectors -= CurrentNSect;
- CURRENT->current_nr_sectors -= CurrentNSect;
- CURRENT->sector += CurrentNSect;
- if (CURRENT->nr_sectors == 0)
- end_request(CURRENT, 1);
- }
- else {
- for( i = 0; i < CurrentNReq; ++i ) {
- n = CURRENT->bh->b_size >> 9;
- CURRENT->nr_sectors -= n;
- CURRENT->current_nr_sectors -= n;
- CURRENT->sector += n;
- end_request(CURRENT, 1);
- }
- }
-}
-
-
-
-
-/***********************************************************************
- *
- * do_acsi_request and friends
- *
- ***********************************************************************/
-
-static void do_acsi_request( request_queue_t * q )
-
-{
- stdma_lock( acsi_interrupt, NULL );
- redo_acsi_request();
-}
-
-
-static void redo_acsi_request( void )
-{
- unsigned block, target, lun, nsect;
- char *buffer;
- unsigned long pbuffer;
- struct buffer_head *bh;
- struct gendisk *disk;
- struct acsi_info_struct *aip;
-
- repeat:
- CLEAR_TIMER();
-
- if (do_acsi)
- return;
-
- if (!CURRENT) {
- do_acsi = NULL;
- ENABLE_IRQ();
- stdma_release();
- return;
- }
-
- disk = CURRENT->rq_disk;
- aip = disk->private_data;
- if (CURRENT->bh) {
- if (!CURRENT->bh && !buffer_locked(CURRENT->bh))
- panic("ACSI: block not locked");
- }
-
- block = CURRENT->sector;
- if (block+CURRENT->nr_sectors >= get_capacity(disk)) {
-#ifdef DEBUG
- printk( "%s: attempted access for blocks %d...%ld past end of device at block %ld.\n",
- disk->disk_name,
- block, block + CURRENT->nr_sectors - 1,
- get_capacity(disk));
-#endif
- end_request(CURRENT, 0);
- goto repeat;
- }
- if (aip->changed) {
- printk( KERN_NOTICE "%s: request denied because cartridge has "
- "been changed.\n", disk->disk_name);
- end_request(CURRENT, 0);
- goto repeat;
- }
-
- target = aip->target;
- lun = aip->lun;
-
- /* Find out how many sectors should be transferred from/to
- * consecutive buffers and thus can be done with a single command.
- */
- buffer = CURRENT->buffer;
- pbuffer = virt_to_phys(buffer);
- nsect = CURRENT->current_nr_sectors;
- CurrentNReq = 1;
-
- if ((bh = CURRENT->bh) && bh != CURRENT->bhtail) {
- if (!STRAM_ADDR(pbuffer)) {
- /* If transfer is done via the ACSI buffer anyway, we can
- * assemble as much bh's as fit in the buffer.
- */
- while( (bh = bh->b_reqnext) ) {
- if (nsect + (bh->b_size>>9) > ACSI_BUFFER_SECTORS) break;
- nsect += bh->b_size >> 9;
- ++CurrentNReq;
- if (bh == CURRENT->bhtail) break;
- }
- buffer = acsi_buffer;
- pbuffer = phys_acsi_buffer;
- }
- else {
- unsigned long pendadr, pnewadr;
- pendadr = pbuffer + nsect*512;
- while( (bh = bh->b_reqnext) ) {
- pnewadr = virt_to_phys(bh->b_data);
- if (!STRAM_ADDR(pnewadr) || pendadr != pnewadr) break;
- nsect += bh->b_size >> 9;
- pendadr = pnewadr + bh->b_size;
- ++CurrentNReq;
- if (bh == CURRENT->bhtail) break;
- }
- }
- }
- else {
- if (!STRAM_ADDR(pbuffer)) {
- buffer = acsi_buffer;
- pbuffer = phys_acsi_buffer;
- if (nsect > ACSI_BUFFER_SECTORS)
- nsect = ACSI_BUFFER_SECTORS;
- }
- }
- CurrentBuffer = buffer;
- CurrentNSect = nsect;
-
- if (rq_data_dir(CURRENT) == WRITE) {
- CMDSET_TARG_LUN( write_cmd, target, lun );
- CMDSET_BLOCK( write_cmd, block );
- CMDSET_LEN( write_cmd, nsect );
- if (buffer == acsi_buffer)
- copy_to_acsibuffer();
- dma_cache_maintenance( pbuffer, nsect*512, 1 );
- do_acsi = write_intr;
- if (!acsicmd_dma( write_cmd, buffer, nsect, 1, 1)) {
- do_acsi = NULL;
- printk( KERN_ERR "ACSI (write): Timeout in command block\n" );
- bad_rw_intr();
- goto repeat;
- }
- SET_TIMER();
- return;
- }
- if (rq_data_dir(CURRENT) == READ) {
- CMDSET_TARG_LUN( read_cmd, target, lun );
- CMDSET_BLOCK( read_cmd, block );
- CMDSET_LEN( read_cmd, nsect );
- do_acsi = read_intr;
- if (!acsicmd_dma( read_cmd, buffer, nsect, 0, 1)) {
- do_acsi = NULL;
- printk( KERN_ERR "ACSI (read): Timeout in command block\n" );
- bad_rw_intr();
- goto repeat;
- }
- SET_TIMER();
- return;
- }
- panic("unknown ACSI command");
-}
-
-
-
-/***********************************************************************
- *
- * Misc functions: ioctl, open, release, check_change, ...
- *
- ***********************************************************************/
-
-static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- struct acsi_info_struct *aip = bdev->bd_disk->private_data;
-
- /*
- * Just fake some geometry here, it's nonsense anyway
- * To make it easy, use Adaptec's usual 64/32 mapping
- */
- geo->heads = 64;
- geo->sectors = 32;
- geo->cylinders = aip->size >> 11;
- return 0;
-}
-
-static int acsi_ioctl( struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
- switch (cmd) {
- case SCSI_IOCTL_GET_IDLUN:
- /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */
- put_user( aip->target | (aip->lun << 8),
- &((Scsi_Idlun *) arg)->dev_id );
- put_user( 0, &((Scsi_Idlun *) arg)->host_unique_id );
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-
-/*
- * Open a device, check for read-only and lock the medium if it is
- * removable.
- *
- * Changes by Martin Rogge, 9th Aug 1995:
- * Check whether check_disk_change (and therefore revalidate_acsidisk)
- * was successful. They fail when there is no medium in the drive.
- *
- * The problem of media being changed during an operation can be
- * ignored because of the prevent_removal code.
- *
- * Added check for the validity of the device number.
- *
- */
-
-static int acsi_open( struct inode * inode, struct file * filp )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
-
- if (aip->access_count == 0 && aip->removable) {
-#if 0
- aip->changed = 1; /* safety first */
-#endif
- check_disk_change( inode->i_bdev );
- if (aip->changed) /* revalidate was not successful (no medium) */
- return -ENXIO;
- acsi_prevent_removal(aip, 1);
- }
- aip->access_count++;
-
- if (filp && filp->f_mode) {
- check_disk_change( inode->i_bdev );
- if (filp->f_mode & 2) {
- if (aip->read_only) {
- acsi_release( inode, filp );
- return -EROFS;
- }
- }
- }
-
- return 0;
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-
-static int acsi_release( struct inode * inode, struct file * file )
-{
- struct gendisk *disk = inode->i_bdev->bd_disk;
- struct acsi_info_struct *aip = disk->private_data;
- if (--aip->access_count == 0 && aip->removable)
- acsi_prevent_removal(aip, 0);
- return( 0 );
-}
-
-/*
- * Prevent or allow a media change for removable devices.
- */
-
-static void acsi_prevent_removal(struct acsi_info_struct *aip, int flag)
-{
- stdma_lock( NULL, NULL );
-
- CMDSET_TARG_LUN(pa_med_rem_cmd, aip->target, aip->lun);
- CMDSET_LEN( pa_med_rem_cmd, flag );
-
- if (acsicmd_nodma(pa_med_rem_cmd, 0) && acsi_wait_for_IRQ(3*HZ))
- acsi_getstatus();
- /* Do not report errors -- some devices may not know this command. */
-
- ENABLE_IRQ();
- stdma_release();
-}
-
-static int acsi_media_change(struct gendisk *disk)
-{
- struct acsi_info_struct *aip = disk->private_data;
-
- if (!aip->removable)
- return 0;
-
- if (aip->changed)
- /* We can be sure that the medium has been changed -- REQUEST
- * SENSE has reported this earlier.
- */
- return 1;
-
- /* If the flag isn't set, make a test by reading block 0.
- * If errors happen, it seems to be better to say "changed"...
- */
- stdma_lock( NULL, NULL );
- CMDSET_TARG_LUN(read_cmd, aip->target, aip->lun);
- CMDSET_BLOCK( read_cmd, 0 );
- CMDSET_LEN( read_cmd, 1 );
- if (acsicmd_dma(read_cmd, acsi_buffer, 1, 0, 0) &&
- acsi_wait_for_IRQ(3*HZ)) {
- if (acsi_getstatus()) {
- if (acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
- if (CARTRCH_STAT(aip, acsi_buffer))
- aip->changed = 1;
- }
- else {
- printk( KERN_ERR "%s: REQUEST SENSE failed in test for "
- "medium change; assuming a change\n", disk->disk_name );
- aip->changed = 1;
- }
- }
- }
- else {
- printk( KERN_ERR "%s: Test for medium changed timed out; "
- "assuming a change\n", disk->disk_name);
- aip->changed = 1;
- }
- ENABLE_IRQ();
- stdma_release();
-
- /* Now, after reading a block, the changed status is surely valid. */
- return aip->changed;
-}
-
-
-static int acsi_change_blk_size( int target, int lun)
-
-{ int i;
-
- for (i=0; i<12; i++)
- acsi_buffer[i] = 0;
-
- acsi_buffer[3] = 8;
- acsi_buffer[10] = 2;
- CMDSET_TARG_LUN( modeselect_cmd, target, lun);
-
- if (!acsicmd_dma( modeselect_cmd, acsi_buffer, 1,1,0) ||
- !acsi_wait_for_IRQ( 3*HZ ) ||
- acsi_getstatus() != 0 ) {
- return(0);
- }
- return(1);
-}
-
-
-static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd )
-
-{
- int page;
-
- CMDSET_TARG_LUN( modesense_cmd, target, lun );
- for (page=0; page<4; page++) {
- modesense_cmd[2] = page;
- if (!acsicmd_dma( modesense_cmd, acsi_buffer, 1, 0, 0 ) ||
- !acsi_wait_for_IRQ( 3*HZ ) ||
- acsi_getstatus())
- continue;
-
- /* read twice to jump over the second 16-byte border! */
- udelay(300);
- if (acsi_wait_for_noIRQ( 20 ) &&
- acsicmd_nodma( modesense_cmd, 0 ) &&
- acsi_wait_for_IRQ( 3*HZ ) &&
- acsi_getstatus() == 0)
- break;
- }
- if (page == 4) {
- return(0);
- }
-
- dma_cache_maintenance( phys_acsi_buffer, sizeof(SENSE_DATA), 0 );
- *sd = *(SENSE_DATA *)acsi_buffer;
-
- /* Validity check, depending on type of data */
-
- switch( SENSE_TYPE(*sd) ) {
-
- case SENSE_TYPE_ATARI:
- if (CAPACITY(*sd) == 0)
- goto invalid_sense;
- break;
-
- case SENSE_TYPE_SCSI:
- if (sd->scsi.descriptor_size != 8)
- goto invalid_sense;
- break;
-
- case SENSE_TYPE_UNKNOWN:
-
- printk( KERN_ERR "ACSI target %d, lun %d: Cannot interpret "
- "sense data\n", target, lun );
-
- invalid_sense:
-
-#ifdef DEBUG
- { int i;
- printk( "Mode sense data for ACSI target %d, lun %d seem not valid:",
- target, lun );
- for( i = 0; i < sizeof(SENSE_DATA); ++i )
- printk( "%02x ", (unsigned char)acsi_buffer[i] );
- printk( "\n" );
- }
-#endif
- return( 0 );
- }
-
- return( 1 );
-}
-
-
-
-/*******************************************************************
- *
- * Initialization
- *
- ********************************************************************/
-
-
-extern struct block_device_operations acsi_fops;
-
-static struct gendisk *acsi_gendisk[MAX_DEV];
-
-#define MAX_SCSI_DEVICE_CODE 10
-
-static const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
-{
- "Direct-Access ",
- "Sequential-Access",
- "Printer ",
- "Processor ",
- "WORM ",
- "CD-ROM ",
- "Scanner ",
- "Optical Device ",
- "Medium Changer ",
- "Communications "
-};
-
-static void print_inquiry(unsigned char *data)
-{
- int i;
-
- printk(KERN_INFO " Vendor: ");
- for (i = 8; i < 16; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk(" Model: ");
- for (i = 16; i < 32; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk(" Rev: ");
- for (i = 32; i < 36; i++)
- {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk("\n");
-
- i = data[0] & 0x1f;
-
- printk(KERN_INFO " Type: %s ", (i < MAX_SCSI_DEVICE_CODE
- ? scsi_device_types[i]
- : "Unknown "));
- printk(" ANSI SCSI revision: %02x", data[2] & 0x07);
- if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
- printk(" CCS\n");
- else
- printk("\n");
-}
-
-
-/*
- * Changes by Martin Rogge, 9th Aug 1995:
- * acsi_devinit has been taken out of acsi_geninit, because it needs
- * to be called from revalidate_acsidisk. The result of request sense
- * is now checked for DRIVE NOT READY.
- *
- * The structure *aip is only valid when acsi_devinit returns
- * DEV_SUPPORTED.
- *
- */
-
-#define DEV_NONE 0
-#define DEV_UNKNOWN 1
-#define DEV_SUPPORTED 2
-#define DEV_SLM 3
-
-static int acsi_devinit(struct acsi_info_struct *aip)
-{
- int status, got_inquiry;
- SENSE_DATA sense;
- unsigned char reqsense, extsense;
-
- /*****************************************************************/
- /* Do a TEST UNIT READY command to test the presence of a device */
- /*****************************************************************/
-
- CMDSET_TARG_LUN(tur_cmd, aip->target, aip->lun);
- if (!acsicmd_nodma(tur_cmd, 0)) {
- /* timed out -> no device here */
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: timeout\n", aip->target, aip->lun);
-#endif
- return DEV_NONE;
- }
-
- /*************************/
- /* Read the ACSI status. */
- /*************************/
-
- status = acsi_getstatus();
- if (status) {
- if (status == 0x12) {
- /* The SLM printer should be the only device that
- * responds with the error code in the status byte. In
- * correct status bytes, bit 4 is never set.
- */
- printk( KERN_INFO "Detected SLM printer at id %d lun %d\n",
- aip->target, aip->lun);
- return DEV_SLM;
- }
- /* ignore CHECK CONDITION, since some devices send a
- UNIT ATTENTION */
- if ((status & 0x1e) != 0x2) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: status %d\n",
- aip->target, aip->lun, status);
-#endif
- return DEV_UNKNOWN;
- }
- }
-
- /*******************************/
- /* Do a REQUEST SENSE command. */
- /*******************************/
-
- if (!acsi_reqsense(acsi_buffer, aip->target, aip->lun)) {
- printk( KERN_WARNING "acsi_reqsense failed\n");
- acsi_buffer[0] = 0;
- acsi_buffer[2] = UNIT_ATTENTION;
- }
- reqsense = acsi_buffer[0];
- extsense = acsi_buffer[2] & 0xf;
- if (status) {
- if ((reqsense & 0x70) == 0x70) { /* extended sense */
- if (extsense != UNIT_ATTENTION &&
- extsense != NOT_READY) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: extended sense %d\n",
- aip->target, aip->lun, extsense);
-#endif
- return DEV_UNKNOWN;
- }
- }
- else {
- if (reqsense & 0x7f) {
-#ifdef DEBUG_DETECT
- printk("target %d lun %d: sense %d\n",
- aip->target, aip->lun, reqsense);
-#endif
- return DEV_UNKNOWN;
- }
- }
- }
- else
- if (reqsense == 0x4) { /* SH204 Bug workaround */
-#ifdef DEBUG_DETECT
- printk("target %d lun %d status=0 sense=4\n",
- aip->target, aip->lun);
-#endif
- return DEV_UNKNOWN;
- }
-
- /***********************************************************/
- /* Do an INQUIRY command to get more infos on this device. */
- /***********************************************************/
-
- /* Assume default values */
- aip->removable = 1;
- aip->read_only = 0;
- aip->old_atari_disk = 0;
- aip->changed = (extsense == NOT_READY); /* medium inserted? */
- aip->size = DEFAULT_SIZE;
- got_inquiry = 0;
- /* Fake inquiry result for old atari disks */
- memcpy(acsi_buffer, "\000\000\001\000 Adaptec 40xx"
- " ", 40);
- CMDSET_TARG_LUN(inquiry_cmd, aip->target, aip->lun);
- if (acsicmd_dma(inquiry_cmd, acsi_buffer, 1, 0, 0) &&
- acsi_getstatus() == 0) {
- acsicmd_nodma(inquiry_cmd, 0);
- acsi_getstatus();
- dma_cache_maintenance( phys_acsi_buffer, 256, 0 );
- got_inquiry = 1;
- aip->removable = !!(acsi_buffer[1] & 0x80);
- }
- if (aip->type == NONE) /* only at boot time */
- print_inquiry(acsi_buffer);
- switch(acsi_buffer[0]) {
- case TYPE_DISK:
- aip->type = HARDDISK;
- break;
- case TYPE_ROM:
- aip->type = CDROM;
- aip->read_only = 1;
- break;
- default:
- return DEV_UNKNOWN;
- }
- /****************************/
- /* Do a MODE SENSE command. */
- /****************************/
-
- if (!acsi_mode_sense(aip->target, aip->lun, &sense)) {
- printk( KERN_WARNING "No mode sense data.\n" );
- return DEV_UNKNOWN;
- }
- if ((SECTOR_SIZE(sense) != 512) &&
- ((aip->type != CDROM) ||
- !acsi_change_blk_size(aip->target, aip->lun) ||
- !acsi_mode_sense(aip->target, aip->lun, &sense) ||
- (SECTOR_SIZE(sense) != 512))) {
- printk( KERN_WARNING "Sector size != 512 not supported.\n" );
- return DEV_UNKNOWN;
- }
- /* There are disks out there that claim to have 0 sectors... */
- if (CAPACITY(sense))
- aip->size = CAPACITY(sense); /* else keep DEFAULT_SIZE */
- if (!got_inquiry && SENSE_TYPE(sense) == SENSE_TYPE_ATARI) {
- /* If INQUIRY failed and the sense data suggest an old
- * Atari disk (SH20x, Megafile), the disk is not removable
- */
- aip->removable = 0;
- aip->old_atari_disk = 1;
- }
-
- /******************/
- /* We've done it. */
- /******************/
-
- return DEV_SUPPORTED;
-}
-
-EXPORT_SYMBOL(acsi_delay_start);
-EXPORT_SYMBOL(acsi_delay_end);
-EXPORT_SYMBOL(acsi_wait_for_IRQ);
-EXPORT_SYMBOL(acsi_wait_for_noIRQ);
-EXPORT_SYMBOL(acsicmd_nodma);
-EXPORT_SYMBOL(acsi_getstatus);
-EXPORT_SYMBOL(acsi_buffer);
-EXPORT_SYMBOL(phys_acsi_buffer);
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-
-EXPORT_SYMBOL(acsi_extstatus);
-EXPORT_SYMBOL(acsi_end_extstatus);
-EXPORT_SYMBOL(acsi_extcmd);
-EXPORT_SYMBOL(acsi_attach_SLMs);
-
-/* to remember IDs of SLM devices, SLM module is loaded later
- * (index is target#, contents is lun#, -1 means "no SLM") */
-int SLM_devices[8];
-#endif
-
-static struct block_device_operations acsi_fops = {
- .owner = THIS_MODULE,
- .open = acsi_open,
- .release = acsi_release,
- .ioctl = acsi_ioctl,
- .getgeo = acsi_getgeo,
- .media_changed = acsi_media_change,
- .revalidate_disk= acsi_revalidate,
-};
-
-#ifdef CONFIG_ATARI_SLM_MODULE
-/* call attach_slm() for each device that is a printer; needed for init of SLM
- * driver as a module, since it's not yet present if acsi.c is inited and thus
- * the bus gets scanned. */
-void acsi_attach_SLMs( int (*attach_func)( int, int ) )
-{
- int i, n = 0;
-
- for( i = 0; i < 8; ++i )
- if (SLM_devices[i] >= 0)
- n += (*attach_func)( i, SLM_devices[i] );
- printk( KERN_INFO "Found %d SLM printer(s) total.\n", n );
-}
-#endif /* CONFIG_ATARI_SLM_MODULE */
-
-
-int acsi_init( void )
-{
- int err = 0;
- int i, target, lun;
- struct acsi_info_struct *aip;
-#ifdef CONFIG_ATARI_SLM
- int n_slm = 0;
-#endif
- if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
- return 0;
- if (register_blkdev(ACSI_MAJOR, "ad")) {
- err = -EBUSY;
- goto out1;
- }
- if (!(acsi_buffer =
- (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) {
- err = -ENOMEM;
- printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );
- goto out2;
- }
- phys_acsi_buffer = virt_to_phys( acsi_buffer );
- STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
-
- acsi_queue = blk_init_queue(do_acsi_request, &acsi_lock);
- if (!acsi_queue) {
- err = -ENOMEM;
- goto out2a;
- }
-#ifdef CONFIG_ATARI_SLM
- err = slm_init();
-#endif
- if (err)
- goto out3;
-
- printk( KERN_INFO "Probing ACSI devices:\n" );
- NDevices = 0;
-#ifdef CONFIG_ATARI_SLM_MODULE
- for( i = 0; i < 8; ++i )
- SLM_devices[i] = -1;
-#endif
- stdma_lock(NULL, NULL);
-
- for (target = 0; target < 8 && NDevices < MAX_DEV; ++target) {
- lun = 0;
- do {
- aip = &acsi_info[NDevices];
- aip->type = NONE;
- aip->target = target;
- aip->lun = lun;
- i = acsi_devinit(aip);
- switch (i) {
- case DEV_SUPPORTED:
- printk( KERN_INFO "Detected ");
- switch (aip->type) {
- case HARDDISK:
- printk("disk");
- break;
- case CDROM:
- printk("cdrom");
- break;
- default:
- }
- printk(" ad%c at id %d lun %d ",
- 'a' + NDevices, target, lun);
- if (aip->removable)
- printk("(removable) ");
- if (aip->read_only)
- printk("(read-only) ");
- if (aip->size == DEFAULT_SIZE)
- printk(" unkown size, using default ");
- printk("%ld MByte\n",
- (aip->size*512+1024*1024/2)/(1024*1024));
- NDevices++;
- break;
- case DEV_SLM:
-#ifdef CONFIG_ATARI_SLM
- n_slm += attach_slm( target, lun );
- break;
-#endif
-#ifdef CONFIG_ATARI_SLM_MODULE
- SLM_devices[target] = lun;
- break;
-#endif
- /* neither of the above: fall through to unknown device */
- case DEV_UNKNOWN:
- printk( KERN_INFO "Detected unsupported device at "
- "id %d lun %d\n", target, lun);
- break;
- }
- }
-#ifdef CONFIG_ACSI_MULTI_LUN
- while (i != DEV_NONE && ++lun < MAX_LUN);
-#else
- while (0);
-#endif
- }
-
- /* reenable interrupt */
- ENABLE_IRQ();
- stdma_release();
-
-#ifndef CONFIG_ATARI_SLM
- printk( KERN_INFO "Found %d ACSI device(s) total.\n", NDevices );
-#else
- printk( KERN_INFO "Found %d ACSI device(s) and %d SLM printer(s) total.\n",
- NDevices, n_slm );
-#endif
- err = -ENOMEM;
- for( i = 0; i < NDevices; ++i ) {
- acsi_gendisk[i] = alloc_disk(16);
- if (!acsi_gendisk[i])
- goto out4;
- }
-
- for( i = 0; i < NDevices; ++i ) {
- struct gendisk *disk = acsi_gendisk[i];
- sprintf(disk->disk_name, "ad%c", 'a'+i);
- aip = &acsi_info[NDevices];
- disk->major = ACSI_MAJOR;
- disk->first_minor = i << 4;
- if (acsi_info[i].type != HARDDISK)
- disk->minors = 1;
- disk->fops = &acsi_fops;
- disk->private_data = &acsi_info[i];
- set_capacity(disk, acsi_info[i].size);
- disk->queue = acsi_queue;
- add_disk(disk);
- }
- return 0;
-out4:
- while (i--)
- put_disk(acsi_gendisk[i]);
-out3:
- blk_cleanup_queue(acsi_queue);
-out2a:
- atari_stram_free( acsi_buffer );
-out2:
- unregister_blkdev( ACSI_MAJOR, "ad" );
-out1:
- return err;
-}
-
-
-#ifdef MODULE
-
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
- int err;
-
- if ((err = acsi_init()))
- return( err );
- printk( KERN_INFO "ACSI driver loaded as module.\n");
- return( 0 );
-}
-
-void cleanup_module(void)
-{
- int i;
- del_timer( &acsi_timer );
- blk_cleanup_queue(acsi_queue);
- atari_stram_free( acsi_buffer );
-
- if (unregister_blkdev( ACSI_MAJOR, "ad" ) != 0)
- printk( KERN_ERR "acsi: cleanup_module failed\n");
-
- for (i = 0; i < NDevices; i++) {
- del_gendisk(acsi_gendisk[i]);
- put_disk(acsi_gendisk[i]);
- }
-}
-#endif
-
-/*
- * This routine is called to flush all partitions and partition tables
- * for a changed scsi disk, and then re-read the new partition table.
- * If we are revalidating a disk because of a media change, then we
- * enter with usage == 0. If we are using an ioctl, we automatically have
- * usage == 1 (we need an open channel to use an ioctl :-), so this
- * is our limit.
- *
- * Changes by Martin Rogge, 9th Aug 1995:
- * got cd-roms to work by calling acsi_devinit. There are only two problems:
- * First, if there is no medium inserted, the status will remain "changed".
- * That is no problem at all, but our design of three-valued logic (medium
- * changed, medium not changed, no medium inserted).
- * Secondly the check could fail completely and the drive could deliver
- * nonsensical data, which could mess up the acsi_info[] structure. In
- * that case we try to make the entry safe.
- *
- */
-
-static int acsi_revalidate(struct gendisk *disk)
-{
- struct acsi_info_struct *aip = disk->private_data;
- stdma_lock( NULL, NULL );
- if (acsi_devinit(aip) != DEV_SUPPORTED) {
- printk( KERN_ERR "ACSI: revalidate failed for target %d lun %d\n",
- aip->target, aip->lun);
- aip->size = 0;
- aip->read_only = 1;
- aip->removable = 1;
- aip->changed = 1; /* next acsi_open will try again... */
- }
-
- ENABLE_IRQ();
- stdma_release();
- set_capacity(disk, aip->size);
- return 0;
-}
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 27a139025ce..6ce8b897e26 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1363,7 +1363,7 @@ static void redo_fd_request(void)
#ifdef DEBUG
printk("fd: sector %ld + %d requested for %s\n",
CURRENT->sector,cnt,
- (CURRENT->cmd==READ)?"read":"write");
+ (rq_data_dir(CURRENT) == READ) ? "read" : "write");
#endif
block = CURRENT->sector + cnt;
if ((int)block > floppy->blocks) {
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5acc6c44aea..0fcad430474 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -87,6 +87,7 @@ static const struct pci_device_id cciss_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D},
{PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
{0,}
@@ -119,6 +120,7 @@ static struct board_type products[] = {
{0x3214103C, "Smart Array E200i", &SA5_access, 120},
{0x3215103C, "Smart Array E200i", &SA5_access, 120},
{0x3237103C, "Smart Array E500", &SA5_access, 512},
+ {0x323D103C, "Smart Array P700m", &SA5_access, 512},
{0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
};
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 5526eadb659..4503290da40 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -74,6 +74,7 @@
#include <linux/highmem.h>
#include <linux/gfp.h>
#include <linux/kthread.h>
+#include <linux/splice.h>
#include <asm/uaccess.h>
@@ -401,50 +402,73 @@ struct lo_read_data {
};
static int
-lo_read_actor(read_descriptor_t *desc, struct page *page,
- unsigned long offset, unsigned long size)
+lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
{
- unsigned long count = desc->count;
- struct lo_read_data *p = desc->arg.data;
+ struct lo_read_data *p = sd->u.data;
struct loop_device *lo = p->lo;
+ struct page *page = buf->page;
sector_t IV;
+ size_t size;
+ int ret;
- IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
+ ret = buf->ops->confirm(pipe, buf);
+ if (unlikely(ret))
+ return ret;
- if (size > count)
- size = count;
+ IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9)) +
+ (buf->offset >> 9);
+ size = sd->len;
+ if (size > p->bsize)
+ size = p->bsize;
- if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) {
- size = 0;
+ if (lo_do_transfer(lo, READ, page, buf->offset, p->page, p->offset, size, IV)) {
printk(KERN_ERR "loop: transfer error block %ld\n",
page->index);
- desc->error = -EINVAL;
+ size = -EINVAL;
}
flush_dcache_page(p->page);
- desc->count = count - size;
- desc->written += size;
- p->offset += size;
+ if (size > 0)
+ p->offset += size;
+
return size;
}
static int
+lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd)
+{
+ return __splice_from_pipe(pipe, sd, lo_splice_actor);
+}
+
+static int
do_lo_receive(struct loop_device *lo,
struct bio_vec *bvec, int bsize, loff_t pos)
{
struct lo_read_data cookie;
+ struct splice_desc sd;
struct file *file;
- int retval;
+ long retval;
cookie.lo = lo;
cookie.page = bvec->bv_page;
cookie.offset = bvec->bv_offset;
cookie.bsize = bsize;
+
+ sd.len = 0;
+ sd.total_len = bvec->bv_len;
+ sd.flags = 0;
+ sd.pos = pos;
+ sd.u.data = &cookie;
+
file = lo->lo_backing_file;
- retval = file->f_op->sendfile(file, &pos, bvec->bv_len,
- lo_read_actor, &cookie);
- return (retval < 0)? retval: 0;
+ retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor);
+
+ if (retval < 0)
+ return retval;
+
+ return 0;
}
static int
@@ -679,8 +703,8 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file,
if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
goto out_putf;
- /* new backing store needs to support loop (eg sendfile) */
- if (!inode->i_fop->sendfile)
+ /* new backing store needs to support loop (eg splice_read) */
+ if (!inode->i_fop->splice_read)
goto out_putf;
/* size of the new backing store needs to be the same */
@@ -760,7 +784,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
* If we can't read - sorry. If we only can't write - well,
* it's going to be read-only.
*/
- if (!file->f_op->sendfile)
+ if (!file->f_op->splice_read)
goto out_putf;
if (aops->prepare_write && aops->commit_write)
lo_flags |= LO_FLAGS_USE_AOPS;
@@ -1354,7 +1378,7 @@ static struct block_device_operations lo_fops = {
*/
static int max_loop;
module_param(max_loop, int, 0);
-MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand");
+MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
@@ -1394,16 +1418,11 @@ int loop_unregister_transfer(int number)
EXPORT_SYMBOL(loop_register_transfer);
EXPORT_SYMBOL(loop_unregister_transfer);
-static struct loop_device *loop_init_one(int i)
+static struct loop_device *loop_alloc(int i)
{
struct loop_device *lo;
struct gendisk *disk;
- list_for_each_entry(lo, &loop_devices, lo_list) {
- if (lo->lo_number == i)
- return lo;
- }
-
lo = kzalloc(sizeof(*lo), GFP_KERNEL);
if (!lo)
goto out;
@@ -1427,8 +1446,6 @@ static struct loop_device *loop_init_one(int i)
disk->private_data = lo;
disk->queue = lo->lo_queue;
sprintf(disk->disk_name, "loop%d", i);
- add_disk(disk);
- list_add_tail(&lo->lo_list, &loop_devices);
return lo;
out_free_queue:
@@ -1439,15 +1456,37 @@ out:
return NULL;
}
-static void loop_del_one(struct loop_device *lo)
+static void loop_free(struct loop_device *lo)
{
- del_gendisk(lo->lo_disk);
blk_cleanup_queue(lo->lo_queue);
put_disk(lo->lo_disk);
list_del(&lo->lo_list);
kfree(lo);
}
+static struct loop_device *loop_init_one(int i)
+{
+ struct loop_device *lo;
+
+ list_for_each_entry(lo, &loop_devices, lo_list) {
+ if (lo->lo_number == i)
+ return lo;
+ }
+
+ lo = loop_alloc(i);
+ if (lo) {
+ add_disk(lo->lo_disk);
+ list_add_tail(&lo->lo_list, &loop_devices);
+ }
+ return lo;
+}
+
+static void loop_del_one(struct loop_device *lo)
+{
+ del_gendisk(lo->lo_disk);
+ loop_free(lo);
+}
+
static struct kobject *loop_probe(dev_t dev, int *part, void *data)
{
struct loop_device *lo;
@@ -1464,28 +1503,77 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
static int __init loop_init(void)
{
- if (register_blkdev(LOOP_MAJOR, "loop"))
- return -EIO;
- blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS,
- THIS_MODULE, loop_probe, NULL, NULL);
+ int i, nr;
+ unsigned long range;
+ struct loop_device *lo, *next;
+
+ /*
+ * loop module now has a feature to instantiate underlying device
+ * structure on-demand, provided that there is an access dev node.
+ * However, this will not work well with user space tool that doesn't
+ * know about such "feature". In order to not break any existing
+ * tool, we do the following:
+ *
+ * (1) if max_loop is specified, create that many upfront, and this
+ * also becomes a hard limit.
+ * (2) if max_loop is not specified, create 8 loop device on module
+ * load, user can further extend loop device by create dev node
+ * themselves and have kernel automatically instantiate actual
+ * device on-demand.
+ */
+ if (max_loop > 1UL << MINORBITS)
+ return -EINVAL;
if (max_loop) {
- printk(KERN_INFO "loop: the max_loop option is obsolete "
- "and will be removed in March 2008\n");
+ nr = max_loop;
+ range = max_loop;
+ } else {
+ nr = 8;
+ range = 1UL << MINORBITS;
+ }
+
+ if (register_blkdev(LOOP_MAJOR, "loop"))
+ return -EIO;
+ for (i = 0; i < nr; i++) {
+ lo = loop_alloc(i);
+ if (!lo)
+ goto Enomem;
+ list_add_tail(&lo->lo_list, &loop_devices);
}
+
+ /* point of no return */
+
+ list_for_each_entry(lo, &loop_devices, lo_list)
+ add_disk(lo->lo_disk);
+
+ blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
+ THIS_MODULE, loop_probe, NULL, NULL);
+
printk(KERN_INFO "loop: module loaded\n");
return 0;
+
+Enomem:
+ printk(KERN_INFO "loop: out of memory\n");
+
+ list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
+ loop_free(lo);
+
+ unregister_blkdev(LOOP_MAJOR, "loop");
+ return -ENOMEM;
}
static void __exit loop_exit(void)
{
+ unsigned long range;
struct loop_device *lo, *next;
+ range = max_loop ? max_loop : 1UL << MINORBITS;
+
list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
loop_del_one(lo);
- blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS);
+ blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
if (unregister_blkdev(LOOP_MAJOR, "loop"))
printk(KERN_WARNING "loop: cannot unregister blkdev\n");
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 069ae39a9cd..c575fb1d585 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -416,7 +416,7 @@ static void nbd_clear_que(struct nbd_device *lo)
/*
* We always wait for result of write, for now. It would be nice to make it optional
* in future
- * if ((req->cmd == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
+ * if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_WRITE_NOCHK))
* { printk( "Warning: Ignoring result!\n"); nbd_end_request( req ); }
*/
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index f1b9dd7d47d..ce64e86d6ff 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -146,8 +146,7 @@ static void pkt_kobj_release(struct kobject *kobj)
**********************************************************/
#define DEF_ATTR(_obj,_name,_mode) \
- static struct attribute _obj = { \
- .name = _name, .owner = THIS_MODULE, .mode = _mode }
+ static struct attribute _obj = { .name = _name, .mode = _mode }
/**********************************************************
/sys/class/pktcdvd/pktcdvd[0-7]/
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 746a118a9b5..18c8b6c0db2 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1547,10 +1547,8 @@ static void ub_reset_enter(struct ub_dev *sc, int try)
#endif
#if 0 /* We let them stop themselves. */
- struct list_head *p;
struct ub_lun *lun;
- list_for_each(p, &sc->luns) {
- lun = list_entry(p, struct ub_lun, link);
+ list_for_each_entry(lun, &sc->luns, link) {
blk_stop_queue(lun->disk->queue);
}
#endif
@@ -1562,7 +1560,6 @@ static void ub_reset_task(struct work_struct *work)
{
struct ub_dev *sc = container_of(work, struct ub_dev, reset_work);
unsigned long flags;
- struct list_head *p;
struct ub_lun *lun;
int lkr, rc;
@@ -1608,8 +1605,7 @@ static void ub_reset_task(struct work_struct *work)
spin_lock_irqsave(sc->lock, flags);
sc->reset = 0;
tasklet_schedule(&sc->tasklet);
- list_for_each(p, &sc->luns) {
- lun = list_entry(p, struct ub_lun, link);
+ list_for_each_entry(lun, &sc->luns, link) {
blk_start_queue(lun->disk->queue);
}
wake_up(&sc->reset_wait);
@@ -2348,7 +2344,6 @@ err_alloc:
static void ub_disconnect(struct usb_interface *intf)
{
struct ub_dev *sc = usb_get_intfdata(intf);
- struct list_head *p;
struct ub_lun *lun;
unsigned long flags;
@@ -2403,8 +2398,7 @@ static void ub_disconnect(struct usb_interface *intf)
/*
* Unregister the upper layer.
*/
- list_for_each (p, &sc->luns) {
- lun = list_entry(p, struct ub_lun, link);
+ list_for_each_entry(lun, &sc->luns, link) {
del_gendisk(lun->disk);
/*
* I wish I could do:
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 7e04dd69f60..59b054810ed 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -199,7 +199,6 @@ static void hci_usb_tx_complete(struct urb *urb);
#define __pending_q(husb, type) (&husb->pending_q[type-1])
#define __completed_q(husb, type) (&husb->completed_q[type-1])
#define __transmit_q(husb, type) (&husb->transmit_q[type-1])
-#define __reassembly(husb, type) (husb->reassembly[type-1])
static inline struct _urb *__get_completed(struct hci_usb *husb, int type)
{
@@ -429,12 +428,6 @@ static void hci_usb_unlink_urbs(struct hci_usb *husb)
kfree(urb->transfer_buffer);
_urb_free(_urb);
}
-
- /* Release reassembly buffers */
- if (husb->reassembly[i]) {
- kfree_skb(husb->reassembly[i]);
- husb->reassembly[i] = NULL;
- }
}
}
@@ -671,83 +664,6 @@ static int hci_usb_send_frame(struct sk_buff *skb)
return 0;
}
-static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int count)
-{
- BT_DBG("%s type %d data %p count %d", husb->hdev->name, type, data, count);
-
- husb->hdev->stat.byte_rx += count;
-
- while (count) {
- struct sk_buff *skb = __reassembly(husb, type);
- struct { int expect; } *scb;
- int len = 0;
-
- if (!skb) {
- /* Start of the frame */
-
- switch (type) {
- case HCI_EVENT_PKT:
- if (count >= HCI_EVENT_HDR_SIZE) {
- struct hci_event_hdr *h = data;
- len = HCI_EVENT_HDR_SIZE + h->plen;
- } else
- return -EILSEQ;
- break;
-
- case HCI_ACLDATA_PKT:
- if (count >= HCI_ACL_HDR_SIZE) {
- struct hci_acl_hdr *h = data;
- len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
- } else
- return -EILSEQ;
- break;
-#ifdef CONFIG_BT_HCIUSB_SCO
- case HCI_SCODATA_PKT:
- if (count >= HCI_SCO_HDR_SIZE) {
- struct hci_sco_hdr *h = data;
- len = HCI_SCO_HDR_SIZE + h->dlen;
- } else
- return -EILSEQ;
- break;
-#endif
- }
- BT_DBG("new packet len %d", len);
-
- skb = bt_skb_alloc(len, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("%s no memory for the packet", husb->hdev->name);
- return -ENOMEM;
- }
- skb->dev = (void *) husb->hdev;
- bt_cb(skb)->pkt_type = type;
-
- __reassembly(husb, type) = skb;
-
- scb = (void *) skb->cb;
- scb->expect = len;
- } else {
- /* Continuation */
- scb = (void *) skb->cb;
- len = scb->expect;
- }
-
- len = min(len, count);
-
- memcpy(skb_put(skb, len), data, len);
-
- scb->expect -= len;
- if (!scb->expect) {
- /* Complete frame */
- __reassembly(husb, type) = NULL;
- bt_cb(skb)->pkt_type = type;
- hci_recv_frame(skb);
- }
-
- count -= len; data += len;
- }
- return 0;
-}
-
static void hci_usb_rx_complete(struct urb *urb)
{
struct _urb *_urb = container_of(urb, struct _urb, urb);
@@ -776,7 +692,7 @@ static void hci_usb_rx_complete(struct urb *urb)
urb->iso_frame_desc[i].actual_length);
if (!urb->iso_frame_desc[i].status)
- __recv_frame(husb, _urb->type,
+ hci_recv_fragment(husb->hdev, _urb->type,
urb->transfer_buffer + urb->iso_frame_desc[i].offset,
urb->iso_frame_desc[i].actual_length);
}
@@ -784,7 +700,7 @@ static void hci_usb_rx_complete(struct urb *urb)
;
#endif
} else {
- err = __recv_frame(husb, _urb->type, urb->transfer_buffer, count);
+ err = hci_recv_fragment(husb->hdev, _urb->type, urb->transfer_buffer, count);
if (err < 0) {
BT_ERR("%s corrupted packet: type %d count %d",
husb->hdev->name, _urb->type, count);
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
index 963fc55cdc8..56cd3a92cec 100644
--- a/drivers/bluetooth/hci_usb.h
+++ b/drivers/bluetooth/hci_usb.h
@@ -102,9 +102,9 @@ struct hci_usb {
struct hci_dev *hdev;
unsigned long state;
-
+
struct usb_device *udev;
-
+
struct usb_host_endpoint *bulk_in_ep;
struct usb_host_endpoint *bulk_out_ep;
struct usb_host_endpoint *intr_in_ep;
@@ -116,7 +116,6 @@ struct hci_usb {
__u8 ctrl_req;
struct sk_buff_head transmit_q[4];
- struct sk_buff *reassembly[4]; /* Reassembly buffers */
rwlock_t completion_lock;
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index b71a5ccc587..0638730a4a1 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -180,11 +180,6 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
return total;
}
-static loff_t vhci_llseek(struct file *file, loff_t offset, int origin)
-{
- return -ESPIPE;
-}
-
static ssize_t vhci_read(struct file *file,
char __user *buf, size_t count, loff_t *pos)
{
@@ -334,7 +329,6 @@ static int vhci_fasync(int fd, struct file *file, int on)
static const struct file_operations vhci_fops = {
.owner = THIS_MODULE,
- .llseek = vhci_llseek,
.read = vhci_read,
.write = vhci_write,
.poll = vhci_poll,
diff --git a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig
deleted file mode 100644
index 4b12e9031fb..00000000000
--- a/drivers/cdrom/Kconfig
+++ /dev/null
@@ -1,213 +0,0 @@
-#
-# CDROM driver configuration
-#
-
-menu "Old CD-ROM drivers (not SCSI, not IDE)"
- depends on ISA && BLOCK
-
-config CD_NO_IDESCSI
- bool "Support non-SCSI/IDE/ATAPI CDROM drives"
- ---help---
- If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y
- here, otherwise N. Read the CD-ROM-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- Note that the answer to this question doesn't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about these CD-ROM drives. If you are unsure what you
- have, say Y and find out whether you have one of the following
- drives.
-
- For each of these drivers, a <file:Documentation/cdrom/{driver_name}>
- exists. Especially in cases where you do not know exactly which kind
- of drive you have you should read there. Most of these drivers use a
- file drivers/cdrom/{driver_name}.h where you can define your
- interface parameters and switch some internal goodies.
-
- To compile these CD-ROM drivers as a module, choose M instead of Y.
-
- If you want to use any of these CD-ROM drivers, you also have to
- answer Y or M to "ISO 9660 CD-ROM file system support" below (this
- answer will get "defaulted" for you if you enable any of the Linux
- CD-ROM drivers).
-
-config AZTCD
- tristate "Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is your driver if you have an Aztech CDA268-01A, Orchid
- CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or
- CR540 CD-ROM drive. This driver -- just like all these CD-ROM
- drivers -- is NOT for CD-ROM drives with IDE/ATAPI interfaces, such
- as Aztech CDA269-031SE. Please read the file
- <file:Documentation/cdrom/aztcd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called aztcd.
-
-config GSCD
- tristate "Goldstar R420 CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- If this is your CD-ROM drive, say Y here. As described in the file
- <file:Documentation/cdrom/gscd>, you might have to change a setting
- in the file <file:drivers/cdrom/gscd.h> before compiling the
- kernel. Please read the file <file:Documentation/cdrom/gscd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called gscd.
-
-config SBPCD
- tristate "Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- This driver supports most of the drives which use the Panasonic or
- Sound Blaster interface. Please read the file
- <file:Documentation/cdrom/sbpcd>.
-
- The Matsushita CR-521, CR-522, CR-523, CR-562, CR-563 drives
- (sometimes labeled "Creative"), the Creative Labs CD200, the
- Longshine LCS-7260, the "IBM External ISA CD-ROM" (in fact a CR-56x
- model), the TEAC CD-55A fall under this category. Some other
- "electrically compatible" drives (Vertos, Genoa, some Funai models)
- are currently not supported; for the Sanyo H94A drive currently a
- separate driver (asked later) is responsible. Most drives have a
- uniquely shaped faceplate, with a caddyless motorized drawer, but
- without external brand markings. The older CR-52x drives have a
- caddy and manual loading/eject, but still no external markings. The
- driver is able to do an extended auto-probing for interface
- addresses and drive types; this can help to find facts in cases you
- are not sure, but can consume some time during the boot process if
- none of the supported drives gets found. Once your drive got found,
- you should enter the reported parameters into
- <file:drivers/cdrom/sbpcd.h> and set "DISTRIBUTION 0" there.
-
- This driver can support up to four CD-ROM controller cards, and each
- card can support up to four CD-ROM drives; if you say Y here, you
- will be asked how many controller cards you have. If compiled as a
- module, only one controller card (but with up to four drives) is
- usable.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sbpcd.
-
-config MCDX
- tristate "Mitsumi CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- Use this driver if you want to be able to use your Mitsumi LU-005,
- FX-001 or FX-001D CD-ROM drive.
-
- Please read the file <file:Documentation/cdrom/mcdx>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called mcdx.
-
-config OPTCD
- tristate "Optics Storage DOLPHIN 8000AT CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is the driver for the 'DOLPHIN' drive with a 34-pin Sony
- compatible interface. It also works with the Lasermate CR328A. If
- you have one of those, say Y. This driver does not work for the
- Optics Storage 8001 drive; use the IDE-ATAPI CD-ROM driver for that
- one. Please read the file <file:Documentation/cdrom/optcd>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called optcd.
-
-config CM206
- tristate "Philips/LMS CM206 CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- If you have a Philips/LMS CD-ROM drive cm206 in combination with a
- cm260 host adapter card, say Y here. Please also read the file
- <file:Documentation/cdrom/cm206>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called cm206.
-
-config SJCD
- tristate "Sanyo CDR-H94A CDROM support"
- depends on CD_NO_IDESCSI
- help
- If this is your CD-ROM drive, say Y here and read the file
- <file:Documentation/cdrom/sjcd>. You should then also say Y or M to
- "ISO 9660 CD-ROM file system support" below, because that's the
- file system used on CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sjcd.
-
-config ISP16_CDI
- tristate "ISP16/MAD16/Mozart soft configurable cdrom interface support"
- depends on CD_NO_IDESCSI
- ---help---
- These are sound cards with built-in cdrom interfaces using the OPTi
- 82C928 or 82C929 chips. Say Y here to have them detected and
- possibly configured at boot time. In addition, You'll have to say Y
- to a driver for the particular cdrom drive you have attached to the
- card. Read <file:Documentation/cdrom/isp16> for details.
-
- To compile this driver as a module, choose M here: the
- module will be called isp16.
-
-config CDU31A
- tristate "Sony CDU31A/CDU33A CDROM support"
- depends on CD_NO_IDESCSI && BROKEN_ON_SMP
- ---help---
- These CD-ROM drives have a spring-pop-out caddyless drawer, and a
- rectangular green LED centered beneath it. NOTE: these CD-ROM
- drives will not be auto detected by the kernel at boot time; you
- have to provide the interface address as an option to the kernel at
- boot time as described in <file:Documentation/cdrom/cdu31a> or fill
- in your parameters into <file:drivers/cdrom/cdu31a.c>. Try "man
- bootparam" or see the documentation of your boot loader (lilo or
- loadlin) about how to pass options to the kernel.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called cdu31a.
-
-config CDU535
- tristate "Sony CDU535 CDROM support"
- depends on CD_NO_IDESCSI
- ---help---
- This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM
- drives. Please read the file <file:Documentation/cdrom/sonycd535>.
-
- If you say Y here, you should also say Y or M to "ISO 9660 CD-ROM
- file system support" below, because that's the file system used on
- CD-ROMs.
-
- To compile this driver as a module, choose M here: the
- module will be called sonycd535.
-
-endmenu
diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
index d1d1e5a4be7..774c180a4e1 100644
--- a/drivers/cdrom/Makefile
+++ b/drivers/cdrom/Makefile
@@ -10,14 +10,4 @@ obj-$(CONFIG_BLK_DEV_SR) += cdrom.o
obj-$(CONFIG_PARIDE_PCD) += cdrom.o
obj-$(CONFIG_CDROM_PKTCDVD) += cdrom.o
-obj-$(CONFIG_AZTCD) += aztcd.o
-obj-$(CONFIG_CDU31A) += cdu31a.o cdrom.o
-obj-$(CONFIG_CM206) += cm206.o cdrom.o
-obj-$(CONFIG_GSCD) += gscd.o
-obj-$(CONFIG_ISP16_CDI) += isp16.o
-obj-$(CONFIG_MCDX) += mcdx.o cdrom.o
-obj-$(CONFIG_OPTCD) += optcd.o
-obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o
-obj-$(CONFIG_SJCD) += sjcd.o
-obj-$(CONFIG_CDU535) += sonycd535.o
obj-$(CONFIG_VIOCD) += viocd.o cdrom.o
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
deleted file mode 100644
index 1f9fb7a9670..00000000000
--- a/drivers/cdrom/aztcd.c
+++ /dev/null
@@ -1,2492 +0,0 @@
-#define AZT_VERSION "2.60"
-
-/* $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $
- linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver
-
- Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
-
- based on Mitsumi CDROM driver by Martin Hariss and preworks by
- Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby
- Schirmer.
-
- This program is free software; you can redistribute 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.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You 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.
-
- HISTORY
- V0.0 Adaption to Aztech CD268-01A Version 1.3
- Version is PRE_ALPHA, unresolved points:
- 1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW
- thus driver causes CPU overhead and is very slow
- 2. could not find a way to stop the drive, when it is
- in data read mode, therefore I had to set
- msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one
- frame can be read in sequence, this is also the reason for
- 3. getting 'timeout in state 4' messages, but nevertheless
- it works
- W.Zimmermann, Oct. 31, 1994
- V0.1 Version is ALPHA, problems #2 and #3 resolved.
- W.Zimmermann, Nov. 3, 1994
- V0.2 Modification to some comments, debugging aids for partial test
- with Borland C under DOS eliminated. Timer interrupt wait
- STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented;
- use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_
- SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy
- waiting seems better to me than interrupt rescheduling.
- Besides that, when used in the wrong place, STEN_LOW_WAIT causes
- kernel panic.
- In function aztPlay command ACMD_PLAY_AUDIO added, should make
- audio functions work. The Aztech drive needs different commands
- to read data tracks and play audio tracks.
- W.Zimmermann, Nov. 8, 1994
- V0.3 Recognition of missing drive during boot up improved (speeded up).
- W.Zimmermann, Nov. 13, 1994
- V0.35 Rewrote the control mechanism in azt_poll (formerly mcd_poll)
- including removal of all 'goto' commands. :-);
- J. Nardone, Nov. 14, 1994
- V0.4 Renamed variables and constants to 'azt' instead of 'mcd'; had
- to make some "compatibility" defines in azt.h; please note,
- that the source file was renamed to azt.c, the include file to
- azt.h
- Speeded up drive recognition during init (will be a little bit
- slower than before if no drive is installed!); suggested by
- Robby Schirmer.
- read_count declared volatile and set to AZT_BUF_SIZ to make
- drive faster (now 300kB/sec, was 60kB/sec before, measured
- by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096';
- different AZT_BUF_SIZes were test, above 16 no further im-
- provement seems to be possible; suggested by E.Moenkeberg.
- W.Zimmermann, Nov. 18, 1994
- V0.42 Included getAztStatus command in GetQChannelInfo() to allow
- reading Q-channel info on audio disks, if drive is stopped,
- and some other bug fixes in the audio stuff, suggested by
- Robby Schirmer.
- Added more ioctls (reading data in mode 1 and mode 2).
- Completely removed the old azt_poll() routine.
- Detection of ORCHID CDS-3110 in aztcd_init implemented.
- Additional debugging aids (see the readme file).
- W.Zimmermann, Dec. 9, 1994
- V0.50 Autodetection of drives implemented.
- W.Zimmermann, Dec. 12, 1994
- V0.52 Prepared for including in the standard kernel, renamed most
- variables to contain 'azt', included autoconf.h
- W.Zimmermann, Dec. 16, 1994
- V0.6 Version for being included in the standard Linux kernel.
- Renamed source and header file to aztcd.c and aztcd.h
- W.Zimmermann, Dec. 24, 1994
- V0.7 Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case
- CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl,
- which causes kernel crashes when playing audio, changed
- include-files (config.h instead of autoconf.h, removed
- delay.h)
- W.Zimmermann, Jan. 8, 1995
- V0.72 Some more modifications for adaption to the standard kernel.
- W.Zimmermann, Jan. 16, 1995
- V0.80 aztcd is now part of the standard kernel since version 1.1.83.
- Modified the SET_TIMER and CLEAR_TIMER macros to comply with
- the new timer scheme.
- W.Zimmermann, Jan. 21, 1995
- V0.90 Included CDROMVOLCTRL, but with my Aztech drive I can only turn
- the channels on and off. If it works better with your drive,
- please mail me. Also implemented ACMD_CLOSE for CDROMSTART.
- W.Zimmermann, Jan. 24, 1995
- V1.00 Implemented close and lock tray commands. Patches supplied by
- Frank Racis
- Added support for loadable MODULEs, so aztcd can now also be
- loaded by insmod and removed by rmmod during run time
- Werner Zimmermann, Mar. 24, 95
- V1.10 Implemented soundcard configuration for Orchid CDS-3110 drives
- connected to Soundwave32 cards. Release for LST 2.1.
- (still experimental)
- Werner Zimmermann, May 8, 95
- V1.20 Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but
- sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver-
- sion needs an update of Dosemu0.60's cdrom.c, which will come with the
- next revision of Dosemu.
- Also Soundwave32 support now works.
- Werner Zimmermann, May 22, 95
- V1.30 Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
- Werner Zimmermann, July 4, 95
- V1.40 Started multisession support. Implementation copied from mcdx.c
- by Heiko Schlittermann. Not tested yet.
- Werner Zimmermann, July 15, 95
- V1.50 Implementation of ioctl CDROMRESET, continued multisession, began
- XA, but still untested. Heavy modifications to drive status de-
- tection.
- Werner Zimmermann, July 25, 95
- V1.60 XA support now should work. Speeded up drive recognition in cases,
- where no drive is installed.
- Werner Zimmermann, August 8, 1995
- V1.70 Multisession support now is completed, but there is still not
- enough testing done. If you can test it, please contact me. For
- details please read Documentation/cdrom/aztcd
- Werner Zimmermann, August 19, 1995
- V1.80 Modification to suit the new kernel boot procedure introduced
- with kernel 1.3.33. Will definitely not work with older kernels.
- Programming done by Linus himself.
- Werner Zimmermann, October 11, 1995
- V1.90 Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza.
- Werner Zimmermann, October 21, 1995
- V2.00 Changed #include "blk.h" to <linux/blk.h> as the directory
- structure was changed. README.aztcd is now /usr/src/docu-
- mentation/cdrom/aztcd
- Werner Zimmermann, November 10, 95
- V2.10 Started to modify azt_poll to prevent reading beyond end of
- tracks.
- Werner Zimmermann, December 3, 95
- V2.20 Changed some comments
- Werner Zimmermann, April 1, 96
- V2.30 Implemented support for CyCDROM CR520, CR940, Code for CR520
- delivered by H.Berger with preworks by E.Moenkeberg.
- Werner Zimmermann, April 29, 96
- V2.40 Reorganized the placement of functions in the source code file
- to reflect the layered approach; did not actually change code
- Werner Zimmermann, May 1, 96
- V2.50 Heiko Eissfeldt suggested to remove some VERIFY_READs in
- aztcd_ioctl; check_aztcd_media_change modified
- Werner Zimmermann, May 16, 96
- V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
- Adaption to linux kernel > 2.1.0
- Werner Zimmermann, Nov 29, 97
-
- November 1999 -- Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-*/
-
-#include <linux/blkdev.h>
-#include "aztcd.h"
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/uaccess.h>
-
-/*###########################################################################
- Defines
- ###########################################################################
-*/
-
-#define MAJOR_NR AZTECH_CDROM_MAJOR
-#define QUEUE (azt_queue)
-#define CURRENT elv_next_request(azt_queue)
-#define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \
- delay_timer.function = (void *) (func); \
- add_timer(&delay_timer);
-
-#define CLEAR_TIMER del_timer(&delay_timer);
-
-#define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
- return value;}
-#define RETURN(message) {printk("aztcd: Warning: %s failed\n",message);\
- return;}
-
-/* Macros to switch the IDE-interface to the slave device and back to the master*/
-#define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \
- outb_p(0x10,azt_port+6); \
- outb_p(0x00,azt_port+7); \
- outb_p(0x10,azt_port+6);
-#define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
-
-
-#if 0
-#define AZT_TEST
-#define AZT_TEST1 /* <int-..> */
-#define AZT_TEST2 /* do_aztcd_request */
-#define AZT_TEST3 /* AZT_S_state */
-#define AZT_TEST4 /* QUICK_LOOP-counter */
-#define AZT_TEST5 /* port(1) state */
-#define AZT_DEBUG
-#define AZT_DEBUG_MULTISESSION
-#endif
-
-static struct request_queue *azt_queue;
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
-#define AZT_BUF_SIZ 16
-
-#define READ_TIMEOUT 3000
-
-#define azt_port aztcd /*needed for the modutils */
-
-/*##########################################################################
- Type Definitions
- ##########################################################################
-*/
-enum azt_state_e { AZT_S_IDLE, /* 0 */
- AZT_S_START, /* 1 */
- AZT_S_MODE, /* 2 */
- AZT_S_READ, /* 3 */
- AZT_S_DATA, /* 4 */
- AZT_S_STOP, /* 5 */
- AZT_S_STOPPING /* 6 */
-};
-enum azt_read_modes { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware */
- AZT_MODE_1, /*read mode for normal CD-ROMs */
- AZT_MODE_2 /*read mode for XA CD-ROMs */
-};
-
-/*##########################################################################
- Global Variables
- ##########################################################################
-*/
-static int aztPresent = 0;
-
-static volatile int azt_transfer_is_active = 0;
-
-static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ]; /*buffer for block size conversion */
-#if AZT_PRIVATE_IOCTLS
-static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls */
-#endif
-
-static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
-static volatile int azt_buf_in, azt_buf_out = -1;
-static volatile int azt_error = 0;
-static int azt_open_count = 0;
-static volatile enum azt_state_e azt_state = AZT_S_IDLE;
-#ifdef AZT_TEST3
-static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
-static volatile int azt_st_old = 0;
-#endif
-static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
-
-static int azt_mode = -1;
-static volatile int azt_read_count = 1;
-
-static int azt_port = AZT_BASE_ADDR;
-
-module_param(azt_port, int, 0);
-
-static int azt_port_auto[16] = AZT_BASE_AUTO;
-
-static char azt_cont = 0;
-static char azt_init_end = 0;
-static char azt_auto_eject = AZT_AUTO_EJECT;
-
-static int AztTimeout, AztTries;
-static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
-static DEFINE_TIMER(delay_timer, NULL, 0, 0);
-
-static struct azt_DiskInfo DiskInfo;
-static struct azt_Toc Toc[MAX_TRACKS];
-static struct azt_Play_msf azt_Play;
-
-static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
-static char aztDiskChanged = 1;
-static char aztTocUpToDate = 0;
-
-static unsigned char aztIndatum;
-static unsigned long aztTimeOutCount;
-static int aztCmd = 0;
-
-static DEFINE_SPINLOCK(aztSpin);
-
-/*###########################################################################
- Function Prototypes
- ###########################################################################
-*/
-/* CDROM Drive Low Level I/O Functions */
-static void aztStatTimer(void);
-
-/* CDROM Drive Command Functions */
-static int aztGetDiskInfo(void);
-#if AZT_MULTISESSION
-static int aztGetMultiDiskInfo(void);
-#endif
-static int aztGetToc(int multi);
-
-/* Kernel Interface Functions */
-static int check_aztcd_media_change(struct gendisk *disk);
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg);
-static int aztcd_open(struct inode *ip, struct file *fp);
-static int aztcd_release(struct inode *inode, struct file *file);
-
-static struct block_device_operations azt_fops = {
- .owner = THIS_MODULE,
- .open = aztcd_open,
- .release = aztcd_release,
- .ioctl = aztcd_ioctl,
- .media_changed = check_aztcd_media_change,
-};
-
-/* Aztcd State Machine: Controls Drive Operating State */
-static void azt_poll(void);
-
-/* Miscellaneous support functions */
-static void azt_hsg2msf(long hsg, struct msf *msf);
-static long azt_msf2hsg(struct msf *mp);
-static void azt_bin2bcd(unsigned char *p);
-static int azt_bcd2bin(unsigned char bcd);
-
-/*##########################################################################
- CDROM Drive Low Level I/O Functions
- ##########################################################################
-*/
-/* Macros for the drive hardware interface handshake, these macros use
- busy waiting */
-/* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
-# define OP_OK op_ok()
-static void op_ok(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(DATA_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait OP_OK\n");
- break;
- }
- } while (aztIndatum != AFL_OP_OK);
-}
-
-/* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
-#if 0
-# define PA_OK pa_ok()
-static void pa_ok(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(DATA_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait PA_OK\n");
- break;
- }
- } while (aztIndatum != AFL_PA_OK);
-}
-#endif
-
-/* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
-# define STEN_LOW sten_low()
-static void sten_low(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- if (azt_init_end)
- printk
- ("aztcd: Error Wait STEN_LOW commands:%x\n",
- aztCmd);
- break;
- }
- } while (aztIndatum & AFL_STATUS);
-}
-
-/* Wait for DTEN=Low = handshake signal 'Data available'*/
-# define DTEN_LOW dten_low()
-static void dten_low(void)
-{
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: Error Wait DTEN_OK\n");
- break;
- }
- } while (aztIndatum & AFL_DATA);
-}
-
-/*
- * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
- * may cause kernel panic when used in the wrong place
-*/
-#define STEN_LOW_WAIT statusAzt()
-static void statusAzt(void)
-{
- AztTimeout = AZT_STATUS_DELAY;
- SET_TIMER(aztStatTimer, HZ / 100);
- sleep_on(&azt_waitq);
- if (AztTimeout <= 0)
- printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",
- aztCmd);
- return;
-}
-
-static void aztStatTimer(void)
-{
- if (!(inb(STATUS_PORT) & AFL_STATUS)) {
- wake_up(&azt_waitq);
- return;
- }
- AztTimeout--;
- if (AztTimeout <= 0) {
- wake_up(&azt_waitq);
- printk("aztcd: Error aztStatTimer: Timeout\n");
- return;
- }
- SET_TIMER(aztStatTimer, HZ / 100);
-}
-
-/*##########################################################################
- CDROM Drive Command Functions
- ##########################################################################
-*/
-/*
- * Send a single command, return -1 on error, else 0
-*/
-static int aztSendCmd(int cmd)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: Executing command %x\n", cmd);
-#endif
-
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */
-
- aztCmd = cmd;
- outb(POLLED, MODE_PORT);
- do {
- if (inb(STATUS_PORT) & AFL_STATUS)
- break;
- inb(DATA_PORT); /* if status left from last command, read and */
- } while (1); /* discard it */
- do {
- if (inb(STATUS_PORT) & AFL_DATA)
- break;
- inb(DATA_PORT); /* if data left from last command, read and */
- } while (1); /* discard it */
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- outb((unsigned char) cmd, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_OP_OK) {
- return 0;
- } /*OP_OK? */
- if (data == AFL_OP_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: aztSendCmd %x Error Code %x\n",
- cmd, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSendCmd %x \n", cmd);
- azt_error = 0xA5;
- }
- RETURNM("aztSendCmd", -1);
-}
-
-/*
- * Send a play or read command to the drive, return -1 on error, else 0
-*/
-static int sendAztCmd(int cmd, struct azt_Play_msf *params)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n",
- params->start.min, params->start.sec, params->start.frame,
- params->end.min, params->end.sec, params->end.frame);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(cmd);
- outb(params->start.min, CMD_PORT);
- outb(params->start.sec, CMD_PORT);
- outb(params->start.frame, CMD_PORT);
- outb(params->end.min, CMD_PORT);
- outb(params->end.sec, CMD_PORT);
- outb(params->end.frame, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) {
- return 0;
- } /*PA_OK ? */
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: sendAztCmd %x Error Code %x\n",
- cmd, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd);
- azt_error = 0xA5;
- }
- RETURNM("sendAztCmd", -1);
-}
-
-/*
- * Send a seek command to the drive, return -1 on error, else 0
-*/
-static int aztSeek(struct azt_Play_msf *params)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: aztSeek %02x:%02x:%02x\n",
- params->start.min, params->start.sec, params->start.frame);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(ACMD_SEEK);
- outb(params->start.min, CMD_PORT);
- outb(params->start.sec, CMD_PORT);
- outb(params->start.frame, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) {
- return 0;
- } /*PA_OK ? */
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk("### Error 1 aztcd: aztSeek\n");
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSeek\n ");
- azt_error = 0xA5;
- }
- RETURNM("aztSeek", -1);
-}
-
-/* Send a Set Disk Type command
- does not seem to work with Aztech drives, behavior is completely indepen-
- dent on which mode is set ???
-*/
-static int aztSetDiskType(int type)
-{
- unsigned char data;
- int retry;
-
-#ifdef AZT_DEBUG
- printk("aztcd: set disk type command: type= %i\n", type);
-#endif
- for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
- aztSendCmd(ACMD_SET_DISK_TYPE);
- outb(type, CMD_PORT);
- STEN_LOW;
- data = inb(DATA_PORT);
- if (data == AFL_PA_OK) { /*PA_OK ? */
- azt_read_mode = type;
- return 0;
- }
- if (data == AFL_PA_ERR) {
- STEN_LOW;
- data = inb(DATA_PORT);
- printk
- ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",
- type, data);
- }
- }
- if (retry >= AZT_RETRY_ATTEMPTS) {
- printk("### Error 2 aztcd: aztSetDiskType %x\n ", type);
- azt_error = 0xA5;
- }
- RETURNM("aztSetDiskType", -1);
-}
-
-
-/* used in azt_poll to poll the status, expects another program to issue a
- * ACMD_GET_STATUS directly before
- */
-static int aztStatus(void)
-{
- int st;
-/* int i;
-
- i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ???
- if (!i)
-*/ STEN_LOW;
- if (aztTimeOutCount < AZT_TIMEOUT) {
- st = inb(DATA_PORT) & 0xFF;
- return st;
- } else
- RETURNM("aztStatus", -1);
-}
-
-/*
- * Get the drive status
- */
-static int getAztStatus(void)
-{
- int st;
-
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURNM("getAztStatus 1", -1);
- STEN_LOW;
- st = inb(DATA_PORT) & 0xFF;
-#ifdef AZT_DEBUG
- printk("aztcd: Status = %x\n", st);
-#endif
- if ((st == 0xFF) || (st & AST_CMD_CHECK)) {
- printk
- ("aztcd: AST_CMD_CHECK error or no status available\n");
- return -1;
- }
-
- if (((st & AST_MODE_BITS) != AST_BUSY)
- && (aztAudioStatus == CDROM_AUDIO_PLAY))
- /* XXX might be an error? look at q-channel? */
- aztAudioStatus = CDROM_AUDIO_COMPLETED;
-
- if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- }
- return st;
-}
-
-
-/*
- * Send a 'Play' command and get the status. Use only from the top half.
- */
-static int aztPlay(struct azt_Play_msf *arg)
-{
- if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0)
- RETURNM("aztPlay", -1);
- return 0;
-}
-
-/*
- * Subroutines to automatically close the door (tray) and
- * lock it closed when the cd is mounted. Leave the tray
- * locking as an option
- */
-static void aztCloseDoor(void)
-{
- aztSendCmd(ACMD_CLOSE);
- STEN_LOW;
- return;
-}
-
-static void aztLockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
- aztSendCmd(ACMD_LOCK);
- STEN_LOW;
-#endif
- return;
-}
-
-static void aztUnlockDoor(void)
-{
-#if AZT_ALLOW_TRAY_LOCK
- aztSendCmd(ACMD_UNLOCK);
- STEN_LOW;
-#endif
- return;
-}
-
-/*
- * Read a value from the drive. Should return quickly, so a busy wait
- * is used to avoid excessive rescheduling. The read command itself must
- * be issued with aztSendCmd() directly before
- */
-static int aztGetValue(unsigned char *result)
-{
- int s;
-
- STEN_LOW;
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk("aztcd: aztGetValue timeout\n");
- return -1;
- }
- s = inb(DATA_PORT) & 0xFF;
- *result = (unsigned char) s;
- return 0;
-}
-
-/*
- * Read the current Q-channel info. Also used for reading the
- * table of contents.
- */
-static int aztGetQChannelInfo(struct azt_Toc *qp)
-{
- unsigned char notUsed;
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetQChannelInfo Time:%li\n", jiffies);
-#endif
- if ((st = getAztStatus()) == -1)
- RETURNM("aztGetQChannelInfo 1", -1);
- if (aztSendCmd(ACMD_GET_Q_CHANNEL))
- RETURNM("aztGetQChannelInfo 2", -1);
- /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */
- if (aztGetValue(&notUsed))
- RETURNM("aztGetQChannelInfo 3", -1); /*??? Nullbyte einlesen */
- if ((st & AST_MODE_BITS) == AST_INITIAL) {
- qp->ctrl_addr = 0; /* when audio stop ACMD_GET_Q_CHANNEL returns */
- qp->track = 0; /* only one byte with Aztech drives */
- qp->pointIndex = 0;
- qp->trackTime.min = 0;
- qp->trackTime.sec = 0;
- qp->trackTime.frame = 0;
- qp->diskTime.min = 0;
- qp->diskTime.sec = 0;
- qp->diskTime.frame = 0;
- return 0;
- } else {
- if (aztGetValue(&qp->ctrl_addr) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->track) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->pointIndex) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.min) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.sec) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->trackTime.frame) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&notUsed) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.min) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.sec) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- if (aztGetValue(&qp->diskTime.frame) < 0)
- RETURNM("aztGetQChannelInfo 4", -1);
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetQChannelInfo Time:%li\n", jiffies);
-#endif
- return 0;
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary
- */
-static int aztUpdateToc(void)
-{
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztUpdateToc Time:%li\n", jiffies);
-#endif
- if (aztTocUpToDate)
- return 0;
-
- if (aztGetDiskInfo() < 0)
- return -EIO;
-
- if (aztGetToc(0) < 0)
- return -EIO;
-
- /*audio disk detection
- with my Aztech drive there is no audio status bit, so I use the copy
- protection bit of the first track. If this track is copy protected
- (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */
- if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
- DiskInfo.audio = 1;
- else
- DiskInfo.audio = 0;
-
- /* XA detection */
- if (!DiskInfo.audio) {
- azt_Play.start.min = 0; /*XA detection only seems to work */
- azt_Play.start.sec = 2; /*when we play a track */
- azt_Play.start.frame = 0;
- azt_Play.end.min = 0;
- azt_Play.end.sec = 0;
- azt_Play.end.frame = 1;
- if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
- return -1;
- DTEN_LOW;
- for (st = 0; st < CD_FRAMESIZE; st++)
- inb(DATA_PORT);
- }
- DiskInfo.xa = getAztStatus() & AST_MODE;
- if (DiskInfo.xa) {
- printk
- ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
- }
-
- /*multisession detection
- support for multisession CDs is done automatically with Aztech drives,
- we don't have to take care about TOC redirection; if we want the isofs
- to take care about redirection, we have to set AZT_MULTISESSION to 1 */
- DiskInfo.multi = 0;
-#if AZT_MULTISESSION
- if (DiskInfo.xa) {
- aztGetMultiDiskInfo(); /*here Disk.Info.multi is set */
- }
-#endif
- if (DiskInfo.multi) {
- DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
- DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
- DiskInfo.lastSession.frame =
- Toc[DiskInfo.next].diskTime.frame;
- printk("aztcd: Multisession support experimental\n");
- } else {
- DiskInfo.lastSession.min =
- Toc[DiskInfo.first].diskTime.min;
- DiskInfo.lastSession.sec =
- Toc[DiskInfo.first].diskTime.sec;
- DiskInfo.lastSession.frame =
- Toc[DiskInfo.first].diskTime.frame;
- }
-
- aztTocUpToDate = 1;
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztUpdateToc Time:%li\n", jiffies);
-#endif
- return 0;
-}
-
-
-/* Read the table of contents header, i.e. no. of tracks and start of first
- * track
- */
-static int aztGetDiskInfo(void)
-{
- int limit;
- unsigned char test;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetDiskInfo Time:%li\n", jiffies);
-#endif
- if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
- RETURNM("aztGetDiskInfo 1", -1);
- STEN_LOW_WAIT;
- test = 0;
- for (limit = 300; limit > 0; limit--) {
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetDiskInfo 2", -1);
- if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */
- DiskInfo.first = qInfo.diskTime.min;
- DiskInfo.first = azt_bcd2bin(DiskInfo.first);
- test = test | 0x01;
- }
- if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
- DiskInfo.last = qInfo.diskTime.min;
- DiskInfo.last = azt_bcd2bin(DiskInfo.last);
- test = test | 0x02;
- }
- if (qInfo.pointIndex == 0xA2) { /*DiskLength */
- DiskInfo.diskLength.min = qInfo.diskTime.min;
- DiskInfo.diskLength.sec = qInfo.diskTime.sec;
- DiskInfo.diskLength.frame = qInfo.diskTime.frame;
- test = test | 0x04;
- }
- if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) { /*StartTime of First Track */
- DiskInfo.firstTrack.min = qInfo.diskTime.min;
- DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
- DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
- test = test | 0x08;
- }
- if (test == 0x0F)
- break;
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetDiskInfo Time:%li\n", jiffies);
- printk
- ("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n",
- DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
- DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
- DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
- DiskInfo.firstTrack.frame);
-#endif
- if (test != 0x0F)
- return -1;
- return 0;
-}
-
-#if AZT_MULTISESSION
-/*
- * Get Multisession Disk Info
- */
-static int aztGetMultiDiskInfo(void)
-{
- int limit, k = 5;
- unsigned char test;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetMultiDiskInfo\n");
-#endif
-
- do {
- azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min;
- azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec;
- azt_Play.start.frame =
- Toc[DiskInfo.last + 1].diskTime.frame;
- test = 0;
-
- for (limit = 30; limit > 0; limit--) { /*Seek for LeadIn of next session */
- if (aztSeek(&azt_Play))
- RETURNM("aztGetMultiDiskInfo 1", -1);
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetMultiDiskInfo 2", -1);
- if ((qInfo.track == 0) && (qInfo.pointIndex))
- break; /*LeadIn found */
- if ((azt_Play.start.sec += 10) > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- }
- if (!limit)
- break; /*Check, if a leadin track was found, if not we're
- at the end of the disk */
-#ifdef AZT_DEBUG_MULTISESSION
- printk("leadin found track %d pointIndex %x limit %d\n",
- qInfo.track, qInfo.pointIndex, limit);
-#endif
- for (limit = 300; limit > 0; limit--) {
- if (++azt_Play.start.frame > 74) {
- azt_Play.start.frame = 0;
- if (azt_Play.start.sec > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- }
- if (aztSeek(&azt_Play))
- RETURNM("aztGetMultiDiskInfo 3", -1);
- if (aztGetQChannelInfo(&qInfo) < 0)
- RETURNM("aztGetMultiDiskInfo 4", -1);
- if (qInfo.pointIndex == 0xA0) { /*Number of NextTrack */
- DiskInfo.next = qInfo.diskTime.min;
- DiskInfo.next = azt_bcd2bin(DiskInfo.next);
- test = test | 0x01;
- }
- if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
- DiskInfo.last = qInfo.diskTime.min;
- DiskInfo.last = azt_bcd2bin(DiskInfo.last);
- test = test | 0x02;
- }
- if (qInfo.pointIndex == 0xA2) { /*DiskLength */
- DiskInfo.diskLength.min =
- qInfo.diskTime.min;
- DiskInfo.diskLength.sec =
- qInfo.diskTime.sec;
- DiskInfo.diskLength.frame =
- qInfo.diskTime.frame;
- test = test | 0x04;
- }
- if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) { /*StartTime of Next Track */
- DiskInfo.nextSession.min =
- qInfo.diskTime.min;
- DiskInfo.nextSession.sec =
- qInfo.diskTime.sec;
- DiskInfo.nextSession.frame =
- qInfo.diskTime.frame;
- test = test | 0x08;
- }
- if (test == 0x0F)
- break;
- }
-#ifdef AZT_DEBUG_MULTISESSION
- printk
- ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n",
- DiskInfo.first, DiskInfo.next, DiskInfo.last,
- DiskInfo.diskLength.min, DiskInfo.diskLength.sec,
- DiskInfo.diskLength.frame, DiskInfo.firstTrack.min,
- DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame,
- DiskInfo.nextSession.min, DiskInfo.nextSession.sec,
- DiskInfo.nextSession.frame);
-#endif
- if (test != 0x0F)
- break;
- else
- DiskInfo.multi = 1; /*found TOC of more than one session */
- aztGetToc(1);
- } while (--k);
-
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztGetMultiDiskInfo Time:%li\n", jiffies);
-#endif
- return 0;
-}
-#endif
-
-/*
- * Read the table of contents (TOC)
- */
-static int aztGetToc(int multi)
-{
- int i, px;
- int limit;
- struct azt_Toc qInfo;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztGetToc Time:%li\n", jiffies);
-#endif
- if (!multi) {
- for (i = 0; i < MAX_TRACKS; i++)
- Toc[i].pointIndex = 0;
- i = DiskInfo.last + 3;
- } else {
- for (i = DiskInfo.next; i < MAX_TRACKS; i++)
- Toc[i].pointIndex = 0;
- i = DiskInfo.last + 4 - DiskInfo.next;
- }
-
-/*Is there a good reason to stop motor before TOC read?
- if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
- STEN_LOW_WAIT;
-*/
-
- if (!multi) {
- azt_mode = 0x05;
- if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
- RETURNM("aztGetToc 2", -1);
- STEN_LOW_WAIT;
- }
- for (limit = 300; limit > 0; limit--) {
- if (multi) {
- if (++azt_Play.start.sec > 59) {
- azt_Play.start.sec = 0;
- azt_Play.start.min++;
- }
- if (aztSeek(&azt_Play))
- RETURNM("aztGetToc 3", -1);
- }
- if (aztGetQChannelInfo(&qInfo) < 0)
- break;
-
- px = azt_bcd2bin(qInfo.pointIndex);
-
- if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
- if (Toc[px].pointIndex == 0) {
- Toc[px] = qInfo;
- i--;
- }
-
- if (i <= 0)
- break;
- }
-
- Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
- Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
-
-#ifdef AZT_DEBUG_MULTISESSION
- printk("aztcd: exiting aztGetToc\n");
- for (i = 1; i <= DiskInfo.last + 1; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
- for (i = 100; i < 103; i++)
- printk
- ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
- i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
- Toc[i].trackTime.min, Toc[i].trackTime.sec,
- Toc[i].trackTime.frame, Toc[i].diskTime.min,
- Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-#endif
-
- return limit > 0 ? 0 : -1;
-}
-
-
-/*##########################################################################
- Kernel Interface Functions
- ##########################################################################
-*/
-
-#ifndef MODULE
-static int __init aztcd_setup(char *str)
-{
- int ints[4];
-
- (void) get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0)
- azt_port = ints[1];
- if (ints[1] > 1)
- azt_cont = ints[2];
- return 1;
-}
-
-__setup("aztcd=", aztcd_setup);
-
-#endif /* !MODULE */
-
-/*
- * Checking if the media has been changed
-*/
-static int check_aztcd_media_change(struct gendisk *disk)
-{
- if (aztDiskChanged) { /* disk changed */
- aztDiskChanged = 0;
- return 1;
- } else
- return 0; /* no change */
-}
-
-/*
- * Kernel IO-controls
-*/
-static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- int i;
- struct azt_Toc qInfo;
- struct cdrom_ti ti;
- struct cdrom_tochdr tocHdr;
- struct cdrom_msf msf;
- struct cdrom_tocentry entry;
- struct azt_Toc *tocPtr;
- struct cdrom_subchnl subchnl;
- struct cdrom_volctrl volctrl;
- void __user *argp = (void __user *)arg;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n",
- cmd, jiffies);
- printk("aztcd Status %x\n", getAztStatus());
-#endif
- if (!ip)
- RETURNM("aztcd_ioctl 1", -EINVAL);
- if (getAztStatus() < 0)
- RETURNM("aztcd_ioctl 2", -EIO);
- if ((!aztTocUpToDate) || (aztDiskChanged)) {
- if ((i = aztUpdateToc()) < 0)
- RETURNM("aztcd_ioctl 3", i); /* error reading TOC */
- }
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive. Don't know, what to do,
- at least close the tray */
-#if AZT_PRIVATE_IOCTLS
- if (aztSendCmd(ACMD_CLOSE))
- RETURNM("aztcd_ioctl 4", -1);
- STEN_LOW_WAIT;
-#endif
- break;
- case CDROMSTOP: /* Spin down the drive */
- if (aztSendCmd(ACMD_STOP))
- RETURNM("aztcd_ioctl 5", -1);
- STEN_LOW_WAIT;
- /* should we do anything if it fails? */
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMPAUSE: /* Pause the drive */
- if (aztAudioStatus != CDROM_AUDIO_PLAY)
- return -EINVAL;
-
- if (aztGetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- RETURNM("aztcd_ioctl 7", 0);
- }
- azt_Play.start = qInfo.diskTime; /* remember restart point */
-
- if (aztSendCmd(ACMD_PAUSE))
- RETURNM("aztcd_ioctl 8", -1);
- STEN_LOW_WAIT;
- aztAudioStatus = CDROM_AUDIO_PAUSED;
- break;
- case CDROMRESUME: /* Play it again, Sam */
- if (aztAudioStatus != CDROM_AUDIO_PAUSED)
- return -EINVAL;
- /* restart the drive at the saved position. */
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
- case CDROMMULTISESSION: /*multisession support -- experimental */
- {
- struct cdrom_multisession ms;
-#ifdef AZT_DEBUG
- printk("aztcd ioctl MULTISESSION\n");
-#endif
- if (copy_from_user(&ms, argp,
- sizeof(struct cdrom_multisession)))
- return -EFAULT;
- if (ms.addr_format == CDROM_MSF) {
- ms.addr.msf.minute =
- azt_bcd2bin(DiskInfo.lastSession.min);
- ms.addr.msf.second =
- azt_bcd2bin(DiskInfo.lastSession.sec);
- ms.addr.msf.frame =
- azt_bcd2bin(DiskInfo.lastSession.
- frame);
- } else if (ms.addr_format == CDROM_LBA)
- ms.addr.lba =
- azt_msf2hsg(&DiskInfo.lastSession);
- else
- return -EINVAL;
- ms.xa_flag = DiskInfo.xa;
- if (copy_to_user(argp, &ms,
- sizeof(struct cdrom_multisession)))
- return -EFAULT;
-#ifdef AZT_DEBUG
- if (ms.addr_format == CDROM_MSF)
- printk
- ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
- ms.xa_flag, ms.addr.msf.minute,
- ms.addr.msf.second, ms.addr.msf.frame,
- DiskInfo.lastSession.min,
- DiskInfo.lastSession.sec,
- DiskInfo.lastSession.frame);
- else
- printk
- ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
- ms.xa_flag, ms.addr.lba,
- DiskInfo.lastSession.min,
- DiskInfo.lastSession.sec,
- DiskInfo.lastSession.frame);
-#endif
- return 0;
- }
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- if (copy_from_user(&ti, argp, sizeof ti))
- return -EFAULT;
- if (ti.cdti_trk0 < DiskInfo.first
- || ti.cdti_trk0 > DiskInfo.last
- || ti.cdti_trk1 < ti.cdti_trk0) {
- return -EINVAL;
- }
- if (ti.cdti_trk1 > DiskInfo.last)
- ti.cdti_trk1 = DiskInfo.last;
- azt_Play.start = Toc[ti.cdti_trk0].diskTime;
- azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
-#ifdef AZT_DEBUG
- printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- azt_Play.start.min, azt_Play.start.sec,
- azt_Play.start.frame, azt_Play.end.min,
- azt_Play.end.sec, azt_Play.end.frame);
-#endif
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
-/* if (aztAudioStatus == CDROM_AUDIO_PLAY)
- { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
- STEN_LOW;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- }
-*/
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- azt_bin2bcd(&msf.cdmsf_min1);
- azt_bin2bcd(&msf.cdmsf_sec1);
- azt_bin2bcd(&msf.cdmsf_frame1);
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- azt_Play.end.min = msf.cdmsf_min1;
- azt_Play.end.sec = msf.cdmsf_sec1;
- azt_Play.end.frame = msf.cdmsf_frame1;
-#ifdef AZT_DEBUG
- printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
- azt_Play.start.min, azt_Play.start.sec,
- azt_Play.start.frame, azt_Play.end.min,
- azt_Play.end.sec, azt_Play.end.frame);
-#endif
- i = aztPlay(&azt_Play);
- if (i < 0) {
- aztAudioStatus = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- aztAudioStatus = CDROM_AUDIO_PLAY;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- tocHdr.cdth_trk0 = DiskInfo.first;
- tocHdr.cdth_trk1 = DiskInfo.last;
- if (copy_to_user(argp, &tocHdr, sizeof tocHdr))
- return -EFAULT;
- break;
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- if (copy_from_user(&entry, argp, sizeof entry))
- return -EFAULT;
- if ((!aztTocUpToDate) || aztDiskChanged)
- aztUpdateToc();
- if (entry.cdte_track == CDROM_LEADOUT)
- tocPtr = &Toc[DiskInfo.last + 1];
- else if (entry.cdte_track > DiskInfo.last
- || entry.cdte_track < DiskInfo.first) {
- return -EINVAL;
- } else
- tocPtr = &Toc[entry.cdte_track];
- entry.cdte_adr = tocPtr->ctrl_addr;
- entry.cdte_ctrl = tocPtr->ctrl_addr >> 4;
- if (entry.cdte_format == CDROM_LBA)
- entry.cdte_addr.lba =
- azt_msf2hsg(&tocPtr->diskTime);
- else if (entry.cdte_format == CDROM_MSF) {
- entry.cdte_addr.msf.minute =
- azt_bcd2bin(tocPtr->diskTime.min);
- entry.cdte_addr.msf.second =
- azt_bcd2bin(tocPtr->diskTime.sec);
- entry.cdte_addr.msf.frame =
- azt_bcd2bin(tocPtr->diskTime.frame);
- } else {
- return -EINVAL;
- }
- if (copy_to_user(argp, &entry, sizeof entry))
- return -EFAULT;
- break;
- case CDROMSUBCHNL: /* Get subchannel info */
- if (copy_from_user
- (&subchnl, argp, sizeof(struct cdrom_subchnl)))
- return -EFAULT;
- if (aztGetQChannelInfo(&qInfo) < 0) {
-#ifdef AZT_DEBUG
- printk
- ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",
- cmd);
-#endif
- return -EIO;
- }
- subchnl.cdsc_audiostatus = aztAudioStatus;
- subchnl.cdsc_adr = qInfo.ctrl_addr;
- subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
- subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
- subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
- if (subchnl.cdsc_format == CDROM_LBA) {
- subchnl.cdsc_absaddr.lba =
- azt_msf2hsg(&qInfo.diskTime);
- subchnl.cdsc_reladdr.lba =
- azt_msf2hsg(&qInfo.trackTime);
- } else { /*default */
- subchnl.cdsc_format = CDROM_MSF;
- subchnl.cdsc_absaddr.msf.minute =
- azt_bcd2bin(qInfo.diskTime.min);
- subchnl.cdsc_absaddr.msf.second =
- azt_bcd2bin(qInfo.diskTime.sec);
- subchnl.cdsc_absaddr.msf.frame =
- azt_bcd2bin(qInfo.diskTime.frame);
- subchnl.cdsc_reladdr.msf.minute =
- azt_bcd2bin(qInfo.trackTime.min);
- subchnl.cdsc_reladdr.msf.second =
- azt_bcd2bin(qInfo.trackTime.sec);
- subchnl.cdsc_reladdr.msf.frame =
- azt_bcd2bin(qInfo.trackTime.frame);
- }
- if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl)))
- return -EFAULT;
- break;
- case CDROMVOLCTRL: /* Volume control
- * With my Aztech CD268-01A volume control does not work, I can only
- turn the channels on (any value !=0) or off (value==0). Maybe it
- works better with your drive */
- if (copy_from_user(&volctrl, argp, sizeof(volctrl)))
- return -EFAULT;
- azt_Play.start.min = 0x21;
- azt_Play.start.sec = 0x84;
- azt_Play.start.frame = volctrl.channel0;
- azt_Play.end.min = volctrl.channel1;
- azt_Play.end.sec = volctrl.channel2;
- azt_Play.end.frame = volctrl.channel3;
- sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
- STEN_LOW_WAIT;
- break;
- case CDROMEJECT:
- aztUnlockDoor(); /* Assume user knows what they're doing */
- /* all drives can at least stop! */
- if (aztAudioStatus == CDROM_AUDIO_PLAY) {
- if (aztSendCmd(ACMD_STOP))
- RETURNM("azt_ioctl 10", -1);
- STEN_LOW_WAIT;
- }
- if (aztSendCmd(ACMD_EJECT))
- RETURNM("azt_ioctl 11", -1);
- STEN_LOW_WAIT;
- aztAudioStatus = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMEJECT_SW:
- azt_auto_eject = (char) arg;
- break;
- case CDROMRESET:
- outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
- STEN_LOW;
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
- printk
- ("aztcd: AZTECH CD-ROM drive does not respond\n");
- }
- break;
-/*Take care, the following code is not compatible with other CD-ROM drivers,
- use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
- if you do not want to use it!
-*/
-#if AZT_PRIVATE_IOCTLS
- case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes) */
- case CDROMREADRAW: /*read data in mode 2 (2336 Bytes) */
- {
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- msf.cdmsf_min1 = 0;
- msf.cdmsf_sec1 = 0;
- msf.cdmsf_frame1 = 1; /*read only one frame */
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- azt_Play.end.min = msf.cdmsf_min1;
- azt_Play.end.sec = msf.cdmsf_sec1;
- azt_Play.end.frame = msf.cdmsf_frame1;
- if (cmd == CDROMREADRAW) {
- if (DiskInfo.xa) {
- return -1; /*XA Disks can't be read raw */
- } else {
- if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play))
- return -1;
- DTEN_LOW;
- insb(DATA_PORT, buf, CD_FRAMESIZE_RAW);
- if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW))
- return -EFAULT;
- }
- } else
- /*CDROMREADCOOKED*/ {
- if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
- return -1;
- DTEN_LOW;
- insb(DATA_PORT, buf, CD_FRAMESIZE);
- if (copy_to_user(argp, &buf, CD_FRAMESIZE))
- return -EFAULT;
- }
- }
- break;
- case CDROMSEEK: /*seek msf address */
- if (copy_from_user(&msf, argp, sizeof msf))
- return -EFAULT;
- /* convert to bcd */
- azt_bin2bcd(&msf.cdmsf_min0);
- azt_bin2bcd(&msf.cdmsf_sec0);
- azt_bin2bcd(&msf.cdmsf_frame0);
- azt_Play.start.min = msf.cdmsf_min0;
- azt_Play.start.sec = msf.cdmsf_sec0;
- azt_Play.start.frame = msf.cdmsf_frame0;
- if (aztSeek(&azt_Play))
- return -1;
- break;
-#endif /*end of incompatible code */
- case CDROMREADMODE1: /*set read data in mode 1 */
- return aztSetDiskType(AZT_MODE_1);
- case CDROMREADMODE2: /*set read data in mode 2 */
- return aztSetDiskType(AZT_MODE_2);
- default:
- return -EINVAL;
- }
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n", cmd,
- jiffies);
-#endif
- return 0;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-static void azt_transfer(void)
-{
-#ifdef AZT_TEST
- printk("aztcd: executing azt_transfer Time:%li\n", jiffies);
-#endif
- if (!current_valid())
- return;
-
- while (CURRENT->nr_sectors) {
- int bn = CURRENT->sector / 4;
- int i;
- for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i);
- if (i < AZT_BUF_SIZ) {
- int offs = (i * 4 + (CURRENT->sector & 3)) * 512;
- int nr_sectors = 4 - (CURRENT->sector & 3);
- if (azt_buf_out != i) {
- azt_buf_out = i;
- if (azt_buf_bn[i] != bn) {
- azt_buf_out = -1;
- continue;
- }
- }
- if (nr_sectors > CURRENT->nr_sectors)
- nr_sectors = CURRENT->nr_sectors;
- memcpy(CURRENT->buffer, azt_buf + offs,
- nr_sectors * 512);
- CURRENT->nr_sectors -= nr_sectors;
- CURRENT->sector += nr_sectors;
- CURRENT->buffer += nr_sectors * 512;
- } else {
- azt_buf_out = -1;
- break;
- }
- }
-}
-
-static void do_aztcd_request(request_queue_t * q)
-{
-#ifdef AZT_TEST
- printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector,
- CURRENT->nr_sectors, jiffies);
-#endif
- if (DiskInfo.audio) {
- printk("aztcd: Error, tried to mount an Audio CD\n");
- end_request(CURRENT, 0);
- return;
- }
- azt_transfer_is_active = 1;
- while (current_valid()) {
- azt_transfer();
- if (CURRENT->nr_sectors == 0) {
- end_request(CURRENT, 1);
- } else {
- azt_buf_out = -1; /* Want to read a block not in buffer */
- if (azt_state == AZT_S_IDLE) {
- if ((!aztTocUpToDate) || aztDiskChanged) {
- if (aztUpdateToc() < 0) {
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- }
- azt_state = AZT_S_START;
- AztTries = 5;
- SET_TIMER(azt_poll, HZ / 100);
- }
- break;
- }
- }
- azt_transfer_is_active = 0;
-#ifdef AZT_TEST2
- printk
- ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
- azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
- printk(" do_aztcd_request ends Time:%li\n", jiffies);
-#endif
-}
-
-
-static void azt_invalidate_buffers(void)
-{
- int i;
-
-#ifdef AZT_DEBUG
- printk("aztcd: executing azt_invalidate_buffers\n");
-#endif
- for (i = 0; i < AZT_BUF_SIZ; ++i)
- azt_buf_bn[i] = -1;
- azt_buf_out = -1;
-}
-
-/*
- * Open the device special file. Check that a disk is in.
- */
-static int aztcd_open(struct inode *ip, struct file *fp)
-{
- int st;
-
-#ifdef AZT_DEBUG
- printk("aztcd: starting aztcd_open\n");
-#endif
-
- if (aztPresent == 0)
- return -ENXIO; /* no hardware */
-
- if (!azt_open_count && azt_state == AZT_S_IDLE) {
- azt_invalidate_buffers();
-
- st = getAztStatus(); /* check drive status */
- if (st == -1)
- goto err_out; /* drive doesn't respond */
-
- if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */
- printk("aztcd: Door Open?\n");
- aztCloseDoor();
- st = getAztStatus();
- }
-
- if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) { /*no disk in drive or changed */
- printk
- ("aztcd: Disk Changed or No Disk in Drive?\n");
- aztTocUpToDate = 0;
- }
- if (aztUpdateToc())
- goto err_out;
-
- }
- ++azt_open_count;
- aztLockDoor();
-
-#ifdef AZT_DEBUG
- printk("aztcd: exiting aztcd_open\n");
-#endif
- return 0;
-
- err_out:
- return -EIO;
-}
-
-
-/*
- * On close, we flush all azt blocks from the buffer cache.
- */
-static int aztcd_release(struct inode *inode, struct file *file)
-{
-#ifdef AZT_DEBUG
- printk("aztcd: executing aztcd_release\n");
- printk("inode: %p, device: %s file: %p\n", inode,
- inode->i_bdev->bd_disk->disk_name, file);
-#endif
- if (!--azt_open_count) {
- azt_invalidate_buffers();
- aztUnlockDoor();
- if (azt_auto_eject)
- aztSendCmd(ACMD_EJECT);
- CLEAR_TIMER;
- }
- return 0;
-}
-
-static struct gendisk *azt_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- */
-
-static int __init aztcd_init(void)
-{
- long int count, max_count;
- unsigned char result[50];
- int st;
- void* status = NULL;
- int i = 0;
- int ret = 0;
-
- if (azt_port == 0) {
- printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization");
- return -EIO;
- }
-
- printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM "
- "CD-ROM Driver\n");
- printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n");
- if (azt_port == -1) {
- printk
- ("aztcd: DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",
- AZT_VERSION);
- } else
- printk
- ("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",
- AZT_VERSION, azt_port);
- printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/"
- "Documentation/cdrom/aztcd\n");
-
-
-#ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */
- if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) {
- printk
- ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
- AZT_SW32_BASE_ADDR, AZT_SW32_INIT,
- AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG);
- return -EIO;
- } else {
- printk(KERN_INFO
- "aztcd: Soundwave32 card detected at %x Version %x\n",
- AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
- outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG);
- for (count = 0; count < 10000; count++); /*delay a bit */
- }
-#endif
-
- /* check for presence of drive */
-
- if (azt_port == -1) { /* autoprobing for proprietary interface */
- for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) {
- azt_port = azt_port_auto[i];
- printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x"
- "\n", azt_port);
- /*proprietary interfaces need 4 bytes */
- if (!request_region(azt_port, 4, "aztcd")) {
- continue;
- }
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */
-
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
- if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */
- break;
- }
- else { /* Drive not found on this port - try next one */
- release_region(azt_port, 4);
- }
- }
- if ((i == 16) || (azt_port_auto[i] == 0)) {
- printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
- return -EIO;
- }
- } else { /* no autoprobing */
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- status = request_region(azt_port, 8, "aztcd"); /*IDE-interfaces need 8 bytes */
- else
- status = request_region(azt_port, 4, "aztcd"); /*proprietary interfaces need 4 bytes */
- if (!status) {
- printk(KERN_WARNING "aztcd: conflict, I/O port (%X) "
- "already used\n", azt_port);
- return -EIO;
- }
-
- if ((azt_port == 0x1f0) || (azt_port == 0x170))
- SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */
-
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */
-
- aztTimeOutCount = 0;
- do {
- aztIndatum = inb(STATUS_PORT);
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
-
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */
-#ifndef MODULE
- if (azt_cont != 0x79) {
- printk(KERN_WARNING "aztcd: no AZTECH CD-ROM "
- "drive found-Try boot parameter aztcd="
- "<BaseAddress>,0x79\n");
- ret = -EIO;
- goto err_out;
- }
-#else
- if (0) {
- }
-#endif
- else {
- printk(KERN_INFO "aztcd: drive reset - "
- "please wait\n");
- for (count = 0; count < 50; count++) {
- inb(STATUS_PORT); /*removing all data from earlier tries */
- inb(DATA_PORT);
- }
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- getAztStatus(); /*trap errors */
- outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
- STEN_LOW;
- if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
- printk(KERN_WARNING "aztcd: no AZTECH "
- "CD-ROM drive found\n");
- ret = -EIO;
- goto err_out;
- }
-
- for (count = 0; count < AZT_TIMEOUT;
- count++)
- barrier(); /* Stop gcc 2.96 being smart */
- /* use udelay(), damnit -- AV */
-
- if ((st = getAztStatus()) == -1) {
- printk(KERN_WARNING "aztcd: Drive Status"
- " Error Status=%x\n", st);
- ret = -EIO;
- goto err_out;
- }
-#ifdef AZT_DEBUG
- printk(KERN_DEBUG "aztcd: Status = %x\n", st);
-#endif
- outb(POLLED, MODE_PORT);
- inb(CMD_PORT);
- inb(CMD_PORT);
- outb(ACMD_GET_VERSION, CMD_PORT); /*GetVersion */
- STEN_LOW;
- OP_OK;
- }
- }
- }
-
- azt_init_end = 1;
- STEN_LOW;
- result[0] = inb(DATA_PORT); /*reading in a null byte??? */
- for (count = 1; count < 50; count++) { /*Reading version string */
- aztTimeOutCount = 0; /*here we must implement STEN_LOW differently */
- do {
- aztIndatum = inb(STATUS_PORT); /*because we want to exit by timeout */
- aztTimeOutCount++;
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break;
- } while (aztIndatum & AFL_STATUS);
- if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
- break; /*all chars read? */
- result[count] = inb(DATA_PORT);
- }
- if (count > 30)
- max_count = 30; /*print max.30 chars of the version string */
- else
- max_count = count;
- printk(KERN_INFO "aztcd: FirmwareVersion=");
- for (count = 1; count < max_count; count++)
- printk("%c", result[count]);
- printk("<<>> ");
-
- if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) {
- printk("AZTECH drive detected\n");
- /*AZTECH*/}
- else if ((result[2] == 'C') && (result[3] == 'D')
- && (result[4] == 'D')) {
- printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES */
- } else if ((result[1] == 0x03) && (result[2] == '5')) {
- printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM */
- } else { /*OTHERS or none */
- printk("\nunknown drive or firmware version detected\n");
- printk
- ("aztcd may not run stable, if you want to try anyhow,\n");
- printk("boot with: aztcd=<BaseAddress>,0x79\n");
- if ((azt_cont != 0x79)) {
- printk("aztcd: FirmwareVersion=");
- for (count = 1; count < 5; count++)
- printk("%c", result[count]);
- printk("<<>> ");
- printk("Aborted\n");
- ret = -EIO;
- goto err_out;
- }
- }
- azt_disk = alloc_disk(1);
- if (!azt_disk)
- goto err_out;
-
- if (register_blkdev(MAJOR_NR, "aztcd")) {
- ret = -EIO;
- goto err_out2;
- }
-
- azt_queue = blk_init_queue(do_aztcd_request, &aztSpin);
- if (!azt_queue) {
- ret = -ENOMEM;
- goto err_out3;
- }
-
- blk_queue_hardsect_size(azt_queue, 2048);
- azt_disk->major = MAJOR_NR;
- azt_disk->first_minor = 0;
- azt_disk->fops = &azt_fops;
- sprintf(azt_disk->disk_name, "aztcd");
- azt_disk->queue = azt_queue;
- add_disk(azt_disk);
- azt_invalidate_buffers();
- aztPresent = 1;
- aztCloseDoor();
- return 0;
-err_out3:
- unregister_blkdev(MAJOR_NR, "aztcd");
-err_out2:
- put_disk(azt_disk);
-err_out:
- if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
- SWITCH_IDE_MASTER;
- release_region(azt_port, 8); /*IDE-interface */
- } else
- release_region(azt_port, 4); /*proprietary interface */
- return ret;
-
-}
-
-static void __exit aztcd_exit(void)
-{
- del_gendisk(azt_disk);
- put_disk(azt_disk);
- if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
- printk("What's that: can't unregister aztcd\n");
- return;
- }
- blk_cleanup_queue(azt_queue);
- if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
- SWITCH_IDE_MASTER;
- release_region(azt_port, 8); /*IDE-interface */
- } else
- release_region(azt_port, 4); /*proprietary interface */
- printk(KERN_INFO "aztcd module released.\n");
-}
-
-module_init(aztcd_init);
-module_exit(aztcd_exit);
-
-/*##########################################################################
- Aztcd State Machine: Controls Drive Operating State
- ##########################################################################
-*/
-static void azt_poll(void)
-{
- int st = 0;
- int loop_ctl = 1;
- int skip = 0;
-
- if (azt_error) {
- if (aztSendCmd(ACMD_GET_ERROR))
- RETURN("azt_poll 1");
- STEN_LOW;
- azt_error = inb(DATA_PORT) & 0xFF;
- printk("aztcd: I/O error 0x%02x\n", azt_error);
- azt_invalidate_buffers();
-#ifdef WARN_IF_READ_FAILURE
- if (AztTries == 5)
- printk
- ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n",
- azt_next_bn);
-#endif
- if (!AztTries--) {
- printk
- ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n",
- azt_next_bn);
- if (azt_transfer_is_active) {
- AztTries = 0;
- loop_ctl = 0;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- AztTries = 5;
- }
- azt_error = 0;
- azt_state = AZT_S_STOP;
- }
-
- while (loop_ctl) {
- loop_ctl = 0; /* each case must flip this back to 1 if we want
- to come back up here */
- switch (azt_state) {
-
- case AZT_S_IDLE:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_IDLE\n");
- }
-#endif
- return;
-
- case AZT_S_START:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_START\n");
- }
-#endif
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 2"); /*result will be checked by aztStatus() */
- azt_state =
- azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
- AztTimeout = 3000;
- break;
-
- case AZT_S_MODE:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_MODE\n");
- }
-#endif
- if (!skip) {
- if ((st = aztStatus()) != -1) {
- if ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- end_request(CURRENT, 0);
- printk
- ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
- }
- } else
- break;
- }
- skip = 0;
-
- if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- printk
- ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- printk((st & AST_DOOR_OPEN) ?
- "aztcd: door open\n" :
- "aztcd: disk removed\n");
- if (azt_transfer_is_active) {
- azt_state = AZT_S_START;
- loop_ctl = 1; /* goto immediately */
- break;
- }
- azt_state = AZT_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
-
-/* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
- outb(0x01, DATA_PORT);
- PA_OK;
- STEN_LOW;
-*/
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 4");
- STEN_LOW;
- azt_mode = 1;
- azt_state = AZT_S_READ;
- AztTimeout = 3000;
-
- break;
-
-
- case AZT_S_READ:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_READ\n");
- }
-#endif
- if (!skip) {
- if ((st = aztStatus()) != -1) {
- if ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- printk
- ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- }
- } else
- break;
- }
-
- skip = 0;
- if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- printk((st & AST_DOOR_OPEN) ?
- "aztcd: door open\n" :
- "aztcd: disk removed\n");
- if (azt_transfer_is_active) {
- azt_state = AZT_S_START;
- loop_ctl = 1;
- break;
- }
- azt_state = AZT_S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
-
- if (current_valid()) {
- struct azt_Play_msf msf;
- int i;
- azt_next_bn = CURRENT->sector / 4;
- azt_hsg2msf(azt_next_bn, &msf.start);
- i = 0;
- /* find out in which track we are */
- while (azt_msf2hsg(&msf.start) >
- azt_msf2hsg(&Toc[++i].trackTime)) {
- };
- if (azt_msf2hsg(&msf.start) <
- azt_msf2hsg(&Toc[i].trackTime) -
- AZT_BUF_SIZ) {
- azt_read_count = AZT_BUF_SIZ; /*fast, because we read ahead */
- /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead */
- } else /* don't read beyond end of track */
-#if AZT_MULTISESSION
- {
- azt_read_count =
- (azt_msf2hsg(&Toc[i].trackTime)
- / 4) * 4 -
- azt_msf2hsg(&msf.start);
- if (azt_read_count < 0)
- azt_read_count = 0;
- if (azt_read_count > AZT_BUF_SIZ)
- azt_read_count =
- AZT_BUF_SIZ;
- printk
- ("aztcd: warning - trying to read beyond end of track\n");
-/* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
-*/ }
-#else
- {
- azt_read_count = AZT_BUF_SIZ;
- }
-#endif
- msf.end.min = 0;
- msf.end.sec = 0;
- msf.end.frame = azt_read_count; /*Mitsumi here reads 0xffffff sectors */
-#ifdef AZT_TEST3
- printk
- ("---reading msf-address %x:%x:%x %x:%x:%x\n",
- msf.start.min, msf.start.sec,
- msf.start.frame, msf.end.min,
- msf.end.sec, msf.end.frame);
- printk
- ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
- azt_next_bn, azt_buf_in, azt_buf_out,
- azt_buf_bn[azt_buf_in]);
-#endif
- if (azt_read_mode == AZT_MODE_2) {
- sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode */
- } else {
- sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode */
- }
- azt_state = AZT_S_DATA;
- AztTimeout = READ_TIMEOUT;
- } else {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
-
- break;
-
-
- case AZT_S_DATA:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_DATA\n");
- }
-#endif
-
- st = inb(STATUS_PORT) & AFL_STATUSorDATA;
-
- switch (st) {
-
- case AFL_DATA:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk("---AFL_DATA st:%x\n", st);
- }
-#endif
- if (!AztTries--) {
- printk
- ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n",
- azt_next_bn);
- if (azt_transfer_is_active) {
- AztTries = 0;
- break;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- AztTries = 5;
- }
- azt_state = AZT_S_START;
- AztTimeout = READ_TIMEOUT;
- loop_ctl = 1;
- break;
-
- case AFL_STATUSorDATA:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk
- ("---AFL_STATUSorDATA st:%x\n",
- st);
- }
-#endif
- break;
-
- default:
-#ifdef AZT_TEST3
- if (st != azt_st_old) {
- azt_st_old = st;
- printk("---default: st:%x\n", st);
- }
-#endif
- AztTries = 5;
- if (!current_valid() && azt_buf_in == azt_buf_out) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- if (azt_read_count <= 0)
- printk
- ("aztcd: warning - try to read 0 frames\n");
- while (azt_read_count) { /*??? fast read ahead loop */
- azt_buf_bn[azt_buf_in] = -1;
- DTEN_LOW; /*??? unsolved problem, very
- seldom we get timeouts
- here, don't now the real
- reason. With my drive this
- sometimes also happens with
- Aztech's original driver under
- DOS. Is it a hardware bug?
- I tried to recover from such
- situations here. Zimmermann */
- if (aztTimeOutCount >= AZT_TIMEOUT) {
- printk
- ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n",
- azt_read_count,
- CURRENT->nr_sectors,
- azt_buf_in);
- printk
- ("azt_transfer_is_active:%x\n",
- azt_transfer_is_active);
- azt_read_count = 0;
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- end_request(CURRENT, 1); /*should we have here (1) or (0)? */
- } else {
- if (azt_read_mode ==
- AZT_MODE_2) {
- insb(DATA_PORT,
- azt_buf +
- CD_FRAMESIZE_RAW
- * azt_buf_in,
- CD_FRAMESIZE_RAW);
- } else {
- insb(DATA_PORT,
- azt_buf +
- CD_FRAMESIZE *
- azt_buf_in,
- CD_FRAMESIZE);
- }
- azt_read_count--;
-#ifdef AZT_TEST3
- printk
- ("AZT_S_DATA; ---I've read data- read_count: %d\n",
- azt_read_count);
- printk
- ("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n",
- azt_next_bn,
- azt_buf_in,
- azt_buf_out,
- azt_buf_bn
- [azt_buf_in]);
-#endif
- azt_buf_bn[azt_buf_in] =
- azt_next_bn++;
- if (azt_buf_out == -1)
- azt_buf_out =
- azt_buf_in;
- azt_buf_in =
- azt_buf_in + 1 ==
- AZT_BUF_SIZ ? 0 :
- azt_buf_in + 1;
- }
- }
- if (!azt_transfer_is_active) {
- while (current_valid()) {
- azt_transfer();
- if (CURRENT->nr_sectors ==
- 0)
- end_request(CURRENT, 1);
- else
- break;
- }
- }
-
- if (current_valid()
- && (CURRENT->sector / 4 < azt_next_bn
- || CURRENT->sector / 4 >
- azt_next_bn + AZT_BUF_SIZ)) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- AztTimeout = READ_TIMEOUT;
- if (azt_read_count == 0) {
- azt_state = AZT_S_STOP;
- loop_ctl = 1;
- break;
- }
- break;
- }
- break;
-
-
- case AZT_S_STOP:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_STOP\n");
- }
-#endif
- if (azt_read_count != 0)
- printk("aztcd: discard data=%x frames\n",
- azt_read_count);
- while (azt_read_count != 0) {
- int i;
- if (!(inb(STATUS_PORT) & AFL_DATA)) {
- if (azt_read_mode == AZT_MODE_2)
- for (i = 0;
- i < CD_FRAMESIZE_RAW;
- i++)
- inb(DATA_PORT);
- else
- for (i = 0;
- i < CD_FRAMESIZE; i++)
- inb(DATA_PORT);
- }
- azt_read_count--;
- }
- if (aztSendCmd(ACMD_GET_STATUS))
- RETURN("azt_poll 5");
- azt_state = AZT_S_STOPPING;
- AztTimeout = 1000;
- break;
-
- case AZT_S_STOPPING:
-#ifdef AZT_TEST3
- if (azt_state != azt_state_old) {
- azt_state_old = azt_state;
- printk("AZT_S_STOPPING\n");
- }
-#endif
-
- if ((st = aztStatus()) == -1 && AztTimeout)
- break;
-
- if ((st != -1)
- && ((st & AST_DSK_CHG)
- || (st & AST_NOT_READY))) {
- aztDiskChanged = 1;
- aztTocUpToDate = 0;
- azt_invalidate_buffers();
- printk
- ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
- end_request(CURRENT, 0);
- }
-
-#ifdef AZT_TEST3
- printk("CURRENT_VALID %d azt_mode %d\n",
- current_valid(), azt_mode);
-#endif
-
- if (current_valid()) {
- if (st != -1) {
- if (azt_mode == 1) {
- azt_state = AZT_S_READ;
- loop_ctl = 1;
- skip = 1;
- break;
- } else {
- azt_state = AZT_S_MODE;
- loop_ctl = 1;
- skip = 1;
- break;
- }
- } else {
- azt_state = AZT_S_START;
- AztTimeout = 1;
- }
- } else {
- azt_state = AZT_S_IDLE;
- return;
- }
- break;
-
- default:
- printk("aztcd: invalid state %d\n", azt_state);
- return;
- } /* case */
- } /* while */
-
-
- if (!AztTimeout--) {
- printk("aztcd: timeout in state %d\n", azt_state);
- azt_state = AZT_S_STOP;
- if (aztSendCmd(ACMD_STOP))
- RETURN("azt_poll 6");
- STEN_LOW_WAIT;
- };
-
- SET_TIMER(azt_poll, HZ / 100);
-}
-
-
-/*###########################################################################
- * Miscellaneous support functions
- ###########################################################################
-*/
-static void azt_hsg2msf(long hsg, struct msf *msf)
-{
- hsg += 150;
- msf->min = hsg / 4500;
- hsg %= 4500;
- msf->sec = hsg / 75;
- msf->frame = hsg % 75;
-#ifdef AZT_DEBUG
- if (msf->min >= 70)
- printk("aztcd: Error hsg2msf address Minutes\n");
- if (msf->sec >= 60)
- printk("aztcd: Error hsg2msf address Seconds\n");
- if (msf->frame >= 75)
- printk("aztcd: Error hsg2msf address Frames\n");
-#endif
- azt_bin2bcd(&msf->min); /* convert to BCD */
- azt_bin2bcd(&msf->sec);
- azt_bin2bcd(&msf->frame);
-}
-
-static long azt_msf2hsg(struct msf *mp)
-{
- return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75
- + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET;
-}
-
-static void azt_bin2bcd(unsigned char *p)
-{
- int u, t;
-
- u = *p % 10;
- t = *p / 10;
- *p = u | (t << 4);
-}
-
-static int azt_bcd2bin(unsigned char bcd)
-{
- return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR);
diff --git a/drivers/cdrom/aztcd.h b/drivers/cdrom/aztcd.h
deleted file mode 100644
index 057501e3162..00000000000
--- a/drivers/cdrom/aztcd.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/* $Id: aztcd.h,v 2.60 1997/11/29 09:51:22 root Exp root $
- *
- * Definitions for a AztechCD268 CD-ROM interface
- * Copyright (C) 1994-98 Werner Zimmermann
- *
- * based on Mitsumi CDROM driver by Martin Harriss
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * History: W.Zimmermann adaption to Aztech CD268-01A Version 1.3
- * October 1994 Email: Werner.Zimmermann@fht-esslingen.de
- */
-
-/* *** change this to set the I/O port address of your CD-ROM drive,
- set to '-1', if you want autoprobing */
-#define AZT_BASE_ADDR -1
-
-/* list of autoprobing addresses (not more than 15), last value must be 0x000
- Note: Autoprobing is only enabled, if AZT_BASE_ADDR is set to '-1' ! */
-#define AZT_BASE_AUTO { 0x320, 0x300, 0x310, 0x330, 0x000 }
-
-/* Uncomment this, if your CDROM is connected to a Soundwave32-soundcard
- and configure AZT_BASE_ADDR and AZT_SW32_BASE_ADDR */
-/*#define AZT_SW32 1
-*/
-
-#ifdef AZT_SW32
-#define AZT_SW32_BASE_ADDR 0x220 /*I/O port base address of your soundcard*/
-#endif
-
-/* Set this to 1, if you want your tray to be locked, set to 0 to prevent tray
- from locking */
-#define AZT_ALLOW_TRAY_LOCK 1
-
-/*Set this to 1 to allow auto-eject when unmounting a disk, set to 0, if you
- don't want the auto-eject feature*/
-#define AZT_AUTO_EJECT 0
-
-/*Set this to 1, if you want to use incompatible ioctls for reading in raw and
- cooked mode */
-#define AZT_PRIVATE_IOCTLS 1
-
-/*Set this to 1, if you want multisession support by the ISO fs. Even if you set
- this value to '0' you can use multisession CDs. In that case the drive's firm-
- ware will do the appropriate redirection automatically. The CD will then look
- like a single session CD (but nevertheless all data may be read). Please read
- chapter '5.1 Multisession support' in README.aztcd for details. Normally it's
- uncritical to leave this setting untouched */
-#define AZT_MULTISESSION 1
-
-/*Uncomment this, if you are using a linux kernel version prior to 2.1.0 */
-/*#define AZT_KERNEL_PRIOR_2_1 */
-
-/*---------------------------------------------------------------------------*/
-/*-----nothing to be configured for normal applications below this line------*/
-
-
-/* Increase this if you get lots of timeouts; if you get kernel panic, replace
- STEN_LOW_WAIT by STEN_LOW in the source code */
-#define AZT_STATUS_DELAY 400 /*for timer wait, STEN_LOW_WAIT*/
-#define AZT_TIMEOUT 8000000 /*for busy wait STEN_LOW, DTEN_LOW*/
-#define AZT_FAST_TIMEOUT 10000 /*for reading the version string*/
-
-/* number of times to retry a command before giving up */
-#define AZT_RETRY_ATTEMPTS 3
-
-/* port access macros */
-#define CMD_PORT azt_port
-#define DATA_PORT azt_port
-#define STATUS_PORT azt_port+1
-#define MODE_PORT azt_port+2
-#ifdef AZT_SW32
- #define AZT_SW32_INIT (unsigned int) (0xFF00 & (AZT_BASE_ADDR*16))
- #define AZT_SW32_CONFIG_REG AZT_SW32_BASE_ADDR+0x16 /*Soundwave32 Config. Register*/
- #define AZT_SW32_ID_REG AZT_SW32_BASE_ADDR+0x04 /*Soundwave32 ID Version Register*/
-#endif
-
-/* status bits */
-#define AST_CMD_CHECK 0x80 /* 1 = command error */
-#define AST_DOOR_OPEN 0x40 /* 1 = door is open */
-#define AST_NOT_READY 0x20 /* 1 = no disk in the drive */
-#define AST_DSK_CHG 0x02 /* 1 = disk removed or changed */
-#define AST_MODE 0x01 /* 0=MODE1, 1=MODE2 */
-#define AST_MODE_BITS 0x1C /* Mode Bits */
-#define AST_INITIAL 0x0C /* initial, only valid ... */
-#define AST_BUSY 0x04 /* now playing, only valid
- in combination with mode
- bits */
-/* flag bits */
-#define AFL_DATA 0x02 /* data available if low */
-#define AFL_STATUS 0x04 /* status available if low */
-#define AFL_OP_OK 0x01 /* OP_OK command correct*/
-#define AFL_PA_OK 0x02 /* PA_OK parameter correct*/
-#define AFL_OP_ERR 0x05 /* error in command*/
-#define AFL_PA_ERR 0x06 /* error in parameters*/
-#define POLLED 0x04 /* polled mode */
-
-/* commands */
-#define ACMD_SOFT_RESET 0x10 /* reset drive */
-#define ACMD_PLAY_READ 0x20 /* read data track in cooked mode */
-#define ACMD_PLAY_READ_RAW 0x21 /* reading in raw mode*/
-#define ACMD_SEEK 0x30 /* seek msf address*/
-#define ACMD_SEEK_TO_LEADIN 0x31 /* seek to leadin track*/
-#define ACMD_GET_ERROR 0x40 /* get error code */
-#define ACMD_GET_STATUS 0x41 /* get status */
-#define ACMD_GET_Q_CHANNEL 0x50 /* read info from q channel */
-#define ACMD_EJECT 0x60 /* eject/open tray */
-#define ACMD_CLOSE 0x61 /* close tray */
-#define ACMD_LOCK 0x71 /* lock tray closed */
-#define ACMD_UNLOCK 0x72 /* unlock tray */
-#define ACMD_PAUSE 0x80 /* pause */
-#define ACMD_STOP 0x81 /* stop play */
-#define ACMD_PLAY_AUDIO 0x90 /* play audio track */
-#define ACMD_SET_VOLUME 0x93 /* set audio level */
-#define ACMD_GET_VERSION 0xA0 /* get firmware version */
-#define ACMD_SET_DISK_TYPE 0xA1 /* set disk data mode */
-
-#define MAX_TRACKS 104
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct azt_Play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct azt_DiskInfo {
- unsigned char first;
- unsigned char next;
- unsigned char last;
- struct msf diskLength;
- struct msf firstTrack;
- unsigned char multi;
- struct msf nextSession;
- struct msf lastSession;
- unsigned char xa;
- unsigned char audio;
-};
-
-struct azt_Toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char pointIndex;
- struct msf trackTime;
- struct msf diskTime;
-};
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 3625a05bc3d..aa5468f487b 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -302,7 +302,7 @@ module_param(lockdoor, bool, 0);
module_param(check_media_type, bool, 0);
module_param(mrw_format_restart, bool, 0);
-static DEFINE_SPINLOCK(cdrom_lock);
+static DEFINE_MUTEX(cdrom_mutex);
static const char *mrw_format_status[] = {
"not mrw",
@@ -438,10 +438,10 @@ int register_cdrom(struct cdrom_device_info *cdi)
cdo->generic_packet = cdrom_dummy_generic_packet;
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
- spin_lock(&cdrom_lock);
+ mutex_lock(&cdrom_mutex);
cdi->next = topCdromPtr;
topCdromPtr = cdi;
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
return 0;
}
#undef ENSURE
@@ -452,7 +452,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
cdinfo(CD_OPEN, "entering unregister_cdrom\n");
prev = NULL;
- spin_lock(&cdrom_lock);
+ mutex_lock(&cdrom_mutex);
cdi = topCdromPtr;
while (cdi && cdi != unreg) {
prev = cdi;
@@ -460,7 +460,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
}
if (cdi == NULL) {
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
return -2;
}
if (prev)
@@ -468,7 +468,7 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
else
topCdromPtr = cdi->next;
- spin_unlock(&cdrom_lock);
+ mutex_unlock(&cdrom_mutex);
if (cdi->exit)
cdi->exit(cdi);
@@ -3289,103 +3289,137 @@ static struct cdrom_sysctl_settings {
int check; /* check media type */
} cdrom_sysctl_settings;
+enum cdrom_print_option {
+ CTL_NAME,
+ CTL_SPEED,
+ CTL_SLOTS,
+ CTL_CAPABILITY
+};
+
+static int cdrom_print_info(const char *header, int val, char *info,
+ int *pos, enum cdrom_print_option option)
+{
+ const int max_size = sizeof(cdrom_sysctl_settings.info);
+ struct cdrom_device_info *cdi;
+ int ret;
+
+ ret = scnprintf(info + *pos, max_size - *pos, header);
+ if (!ret)
+ return 1;
+
+ *pos += ret;
+
+ for (cdi = topCdromPtr; cdi; cdi = cdi->next) {
+ switch (option) {
+ case CTL_NAME:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%s", cdi->name);
+ break;
+ case CTL_SPEED:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", cdi->speed);
+ break;
+ case CTL_SLOTS:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", cdi->capacity);
+ break;
+ case CTL_CAPABILITY:
+ ret = scnprintf(info + *pos, max_size - *pos,
+ "\t%d", CDROM_CAN(val) != 0);
+ break;
+ default:
+ printk(KERN_INFO "cdrom: invalid option%d\n", option);
+ return 1;
+ }
+ if (!ret)
+ return 1;
+ *pos += ret;
+ }
+
+ return 0;
+}
+
static int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- int pos;
- struct cdrom_device_info *cdi;
+ int pos;
char *info = cdrom_sysctl_settings.info;
+ const int max_size = sizeof(cdrom_sysctl_settings.info);
if (!*lenp || (*ppos && !write)) {
*lenp = 0;
return 0;
}
+ mutex_lock(&cdrom_mutex);
+
pos = sprintf(info, "CD-ROM information, " VERSION "\n");
- pos += sprintf(info+pos, "\ndrive name:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%s", cdi->name);
-
- pos += sprintf(info+pos, "\ndrive speed:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", cdi->speed);
-
- pos += sprintf(info+pos, "\ndrive # of slots:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", cdi->capacity);
-
- pos += sprintf(info+pos, "\nCan close tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CLOSE_TRAY) != 0);
-
- pos += sprintf(info+pos, "\nCan open tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_OPEN_TRAY) != 0);
-
- pos += sprintf(info+pos, "\nCan lock tray:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_LOCK) != 0);
-
- pos += sprintf(info+pos, "\nCan change speed:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_SPEED) != 0);
-
- pos += sprintf(info+pos, "\nCan select disk:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_SELECT_DISC) != 0);
-
- pos += sprintf(info+pos, "\nCan read multisession:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MULTI_SESSION) != 0);
-
- pos += sprintf(info+pos, "\nCan read MCN:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MCN) != 0);
-
- pos += sprintf(info+pos, "\nReports media changed:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MEDIA_CHANGED) != 0);
-
- pos += sprintf(info+pos, "\nCan play audio:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_PLAY_AUDIO) != 0);
-
- pos += sprintf(info+pos, "\nCan write CD-R:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_R) != 0);
-
- pos += sprintf(info+pos, "\nCan write CD-RW:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_CD_RW) != 0);
-
- pos += sprintf(info+pos, "\nCan read DVD:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD) != 0);
-
- pos += sprintf(info+pos, "\nCan write DVD-R:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_R) != 0);
-
- pos += sprintf(info+pos, "\nCan write DVD-RAM:");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
-
- pos += sprintf(info+pos, "\nCan read MRW:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0);
-
- pos += sprintf(info+pos, "\nCan write MRW:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0);
-
- pos += sprintf(info+pos, "\nCan write RAM:\t");
- for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
- pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
-
- strcpy(info+pos,"\n\n");
-
- return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+ if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
+ goto done;
+ if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
+ goto done;
+ if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
+ goto done;
+ if (cdrom_print_info("\nCan close tray:\t",
+ CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan open tray:\t",
+ CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan lock tray:\t",
+ CDC_LOCK, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan change speed:",
+ CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan select disk:",
+ CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read multisession:",
+ CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read MCN:\t",
+ CDC_MCN, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nReports media changed:",
+ CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan play audio:\t",
+ CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write CD-R:\t",
+ CDC_CD_R, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write CD-RW:",
+ CDC_CD_RW, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read DVD:\t",
+ CDC_DVD, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write DVD-R:",
+ CDC_DVD_R, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write DVD-RAM:",
+ CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan read MRW:\t",
+ CDC_MRW, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write MRW:\t",
+ CDC_MRW_W, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (cdrom_print_info("\nCan write RAM:\t",
+ CDC_RAM, info, &pos, CTL_CAPABILITY))
+ goto done;
+ if (!scnprintf(info + pos, max_size - pos, "\n\n"))
+ goto done;
+doit:
+ mutex_unlock(&cdrom_mutex);
+ return proc_dostring(ctl, write, filp, buffer, lenp, ppos);
+done:
+ printk(KERN_INFO "cdrom: info buffer too small\n");
+ goto doit;
}
/* Unfortunately, per device settings are not implemented through
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
deleted file mode 100644
index 2157c58755e..00000000000
--- a/drivers/cdrom/cdu31a.c
+++ /dev/null
@@ -1,3251 +0,0 @@
-/*
-* Sony CDU-31A CDROM interface device driver.
-*
-* Corey Minyard (minyard@wf-rch.cirr.com)
-*
-* Colossians 3:17
-*
-* See Documentation/cdrom/cdu31a for additional details about this driver.
-*
-* The Sony interface device driver handles Sony interface CDROM
-* drives and provides a complete block-level interface as well as an
-* ioctl() interface compatible with the Sun (as specified in
-* include/linux/cdrom.h). With this interface, CDROMs can be
-* accessed and standard audio CDs can be played back normally.
-*
-* WARNING - All autoprobes have been removed from the driver.
-* You MUST configure the CDU31A via a LILO config
-* at boot time or in lilo.conf. I have the
-* following in my lilo.conf:
-*
-* append="cdu31a=0x1f88,0,PAS"
-*
-* The first number is the I/O base address of the
-* card. The second is the interrupt (0 means none).
- * The third should be "PAS" if on a Pro-Audio
- * spectrum, or nothing if on something else.
- *
- * This interface is (unfortunately) a polled interface. This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables. Some (like mine) do not even have the capability to
- * handle interrupts or DMA. For this reason you will see a lot of
- * the following:
- *
- * retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
- * while (time_before(jiffies, retry_count) && (! <some condition to wait for))
- * {
- * while (handle_sony_cd_attention())
- * ;
- *
- * sony_sleep();
- * }
- * if (the condition not met)
- * {
- * return an error;
- * }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try. it also handles attentions, which are
- * asynchronous events from the drive informing the driver that a disk
- * has been inserted, removed, etc.
- *
- * NEWS FLASH - The driver now supports interrupts but they are
- * turned off by default. Use of interrupts is highly encouraged, it
- * cuts CPU usage down to a reasonable level. I had DMA in for a while
- * but PC DMA is just too slow. Better to just insb() it.
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk. The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal. A lot of conversion goes on.
- *
- * DRIVER SPECIAL FEATURES
- * -----------------------
- *
- * This section describes features beyond the normal audio and CD-ROM
- * functions of the drive.
- *
- * XA compatibility
- *
- * The driver should support XA disks for both the CDU31A and CDU33A.
- * It does this transparently, the using program doesn't need to set it.
- *
- * Multi-Session
- *
- * A multi-session disk looks just like a normal disk to the user.
- * Just mount one normally, and all the data should be there.
- * A special thanks to Koen for help with this!
- *
- * Raw sector I/O
- *
- * Using the CDROMREADAUDIO it is possible to read raw audio and data
- * tracks. Both operations return 2352 bytes per sector. On the data
- * tracks, the first 12 bytes is not returned by the drive and the value
- * of that data is indeterminate.
- *
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * TODO:
- * CDs with form1 and form2 sectors cause problems
- * with current read-ahead strategy.
- *
- * Credits:
- * Heiko Eissfeldt <heiko@colossus.escape.de>
- * For finding abug in the return of the track numbers.
- * TOC processing redone for proper multisession support.
- *
- *
- * It probably a little late to be adding a history, but I guess I
- * will start.
- *
- * 10/24/95 - Added support for disabling the eject button when the
- * drive is open. Note that there is a small problem
- * still here, if the eject button is pushed while the
- * drive light is flashing, the drive will return a bad
- * status and be reset. It recovers, though.
- *
- * 03/07/97 - Fixed a problem with timers.
- *
- *
- * 18 Spetember 1997 -- Ported to Uniform CD-ROM driver by
- * Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- * changes by Erik Andersen <andersee@debian.org>
- *
- * 24 January 1998 -- Removed the scd_disc_status() function, which was now
- * just dead code left over from the port.
- * Erik Andersen <andersee@debian.org>
- *
- * 16 July 1998 -- Drive donated to Erik Andersen by John Kodis
- * <kodis@jagunet.com>. Work begun on fixing driver to
- * work under 2.1.X. Added temporary extra printks
- * which seem to slow it down enough to work.
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 22 October 2004 -- Make the driver work in 2.6.X
- * Added workaround to fix hard lockups on eject
- * Fixed door locking problem after mounting empty drive
- * Set double-speed drives to double speed by default
- * Removed all readahead things - not needed anymore
- * Ondrej Zary <rainbow@rainbow-software.org>
-*/
-
-#define DEBUG 1
-
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/cdrom.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/dma.h>
-
-#include "cdu31a.h"
-
-#define MAJOR_NR CDU31A_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define CDU31A_MAX_CONSECUTIVE_ATTENTIONS 10
-
-#define PFX "CDU31A: "
-
-/*
-** Edit the following data to change interrupts, DMA channels, etc.
-** Default is polled and no DMA. DMA is not recommended for double-speed
-** drives.
-*/
-static struct {
- unsigned short base; /* I/O Base Address */
- short int_num; /* Interrupt Number (-1 means scan for it,
- 0 means don't use) */
-} cdu31a_addresses[] __initdata = {
- {0}
-};
-
-static int handle_sony_cd_attention(void);
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int scd_spinup(void);
-/*static int scd_open(struct inode *inode, struct file *filp);*/
-static int scd_open(struct cdrom_device_info *, int);
-static void do_sony_cd_cmd(unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer,
- unsigned int *result_size);
-static void size_to_buf(unsigned int size, unsigned char *buf);
-
-/* Parameters for the read-ahead. */
-static unsigned int sony_next_block; /* Next 512 byte block offset */
-static unsigned int sony_blocks_left = 0; /* Number of 512 byte blocks left
- in the current read command. */
-
-
-/* The base I/O address of the Sony Interface. This is a variable (not a
- #define) so it can be easily changed via some future ioctl() */
-static unsigned int cdu31a_port = 0;
-module_param(cdu31a_port, uint, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive. The
- * comment for the base address also applies here.
- */
-static volatile unsigned short sony_cd_cmd_reg;
-static volatile unsigned short sony_cd_param_reg;
-static volatile unsigned short sony_cd_write_reg;
-static volatile unsigned short sony_cd_control_reg;
-static volatile unsigned short sony_cd_status_reg;
-static volatile unsigned short sony_cd_result_reg;
-static volatile unsigned short sony_cd_read_reg;
-static volatile unsigned short sony_cd_fifost_reg;
-
-static struct request_queue *cdu31a_queue;
-static DEFINE_SPINLOCK(cdu31a_lock); /* queue lock */
-
-static int sony_spun_up = 0; /* Has the drive been spun up? */
-
-static int sony_speed = 0; /* Last wanted speed */
-
-static int sony_xa_mode = 0; /* Is an XA disk in the drive
- and the drive a CDU31A? */
-
-static int sony_raw_data_mode = 1; /* 1 if data tracks, 0 if audio.
- For raw data reads. */
-
-static unsigned int sony_usage = 0; /* How many processes have the
- drive open. */
-
-static int sony_pas_init = 0; /* Initialize the Pro-Audio
- Spectrum card? */
-
-static struct s_sony_session_toc single_toc; /* Holds the
- table of
- contents. */
-
-static struct s_all_sessions_toc sony_toc; /* entries gathered from all
- sessions */
-
-static int sony_toc_read = 0; /* Has the TOC been read for
- the drive? */
-
-static struct s_sony_subcode last_sony_subcode; /* Points to the last
- subcode address read */
-
-static DECLARE_MUTEX(sony_sem); /* Semaphore for drive hardware access */
-
-static int is_double_speed = 0; /* does the drive support double speed ? */
-
-static int is_auto_eject = 1; /* Door has been locked? 1=No/0=Yes */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static volatile int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play. The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over. This holds the
- * position during a pause so a resume can restart it. It uses the
- * audio status variable above to tell if it is paused.
- */
-static unsigned volatile char cur_pos_msf[3] = { 0, 0, 0 };
-static unsigned volatile char final_pos_msf[3] = { 0, 0, 0 };
-
-/* What IRQ is the drive using? 0 if none. */
-static int cdu31a_irq = 0;
-module_param(cdu31a_irq, int, 0);
-
-/* The interrupt handler will wake this queue up when it gets an
- interrupts. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
-static int irq_flag = 0;
-
-static int curr_control_reg = 0; /* Current value of the control register */
-
-/* A disk changed variable. When a disk change is detected, it will
- all be set to TRUE. As the upper layers ask for disk_changed status
- it will be cleared. */
-static char disk_changed;
-
-/* This was readahead_buffer once... Now it's used only for audio reads */
-static char audio_buffer[CD_FRAMESIZE_RAW];
-
-/* Used to time a short period to abort an operation after the
- drive has been idle for a while. This keeps the light on
- the drive from flashing for very long. */
-static struct timer_list cdu31a_abort_timer;
-
-/* Marks if the timeout has started an abort read. This is used
- on entry to the drive to tell the code to read out the status
- from the abort read. */
-static int abort_read_started = 0;
-
-/*
- * Uniform cdrom interface function
- * report back, if disc has changed from time of last request.
- */
-static int scd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- int retval;
-
- retval = disk_changed;
- disk_changed = 0;
-
- return retval;
-}
-
-/*
- * Uniform cdrom interface function
- * report back, if drive is ready
- */
-static int scd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- if (CDSL_CURRENT != slot_nr)
- /* we have no changer support */
- return -EINVAL;
- if (sony_spun_up)
- return CDS_DISC_OK;
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (scd_spinup() == 0)
- sony_spun_up = 1;
- up(&sony_sem);
- return sony_spun_up ? CDS_DISC_OK : CDS_DRIVE_NOT_READY;
-}
-
-static inline void enable_interrupts(void)
-{
- curr_control_reg |= (SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-}
-
-static inline void disable_interrupts(void)
-{
- curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-}
-
-/*
- * Wait a little while (used for polling the drive). If in initialization,
- * setting a timeout doesn't work, so just loop for a while.
- */
-static inline void sony_sleep(void)
-{
- if (cdu31a_irq <= 0) {
- yield();
- } else { /* Interrupt driven */
- DEFINE_WAIT(w);
- int first = 1;
-
- while (1) {
- prepare_to_wait(&cdu31a_irq_wait, &w,
- TASK_INTERRUPTIBLE);
- if (first) {
- enable_interrupts();
- first = 0;
- }
-
- if (irq_flag != 0)
- break;
- if (!signal_pending(current)) {
- schedule();
- continue;
- } else
- disable_interrupts();
- break;
- }
- finish_wait(&cdu31a_irq_wait, &w);
- irq_flag = 0;
- }
-}
-
-
-/*
- * The following are convenience routine to read various status and set
- * various conditions in the drive.
- */
-static inline int is_attention(void)
-{
- return (inb(sony_cd_status_reg) & SONY_ATTN_BIT) != 0;
-}
-
-static inline int is_busy(void)
-{
- return (inb(sony_cd_status_reg) & SONY_BUSY_BIT) != 0;
-}
-
-static inline int is_data_ready(void)
-{
- return (inb(sony_cd_status_reg) & SONY_DATA_RDY_BIT) != 0;
-}
-
-static inline int is_data_requested(void)
-{
- return (inb(sony_cd_status_reg) & SONY_DATA_REQUEST_BIT) != 0;
-}
-
-static inline int is_result_ready(void)
-{
- return (inb(sony_cd_status_reg) & SONY_RES_RDY_BIT) != 0;
-}
-
-static inline int is_param_write_rdy(void)
-{
- return (inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0;
-}
-
-static inline int is_result_reg_not_empty(void)
-{
- return (inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0;
-}
-
-static inline void reset_drive(void)
-{
- curr_control_reg = 0;
- sony_toc_read = 0;
- outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);
-}
-
-/*
- * Uniform cdrom interface function
- * reset drive and return when it is ready
- */
-static int scd_reset(struct cdrom_device_info *cdi)
-{
- unsigned long retry_count;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- reset_drive();
-
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count) && (!is_attention())) {
- sony_sleep();
- }
-
- up(&sony_sem);
- return 0;
-}
-
-static inline void clear_attention(void)
-{
- outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_result_ready(void)
-{
- outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline void clear_data_ready(void)
-{
- outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT,
- sony_cd_control_reg);
-}
-
-static inline void clear_param_reg(void)
-{
- outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg);
-}
-
-static inline unsigned char read_status_register(void)
-{
- return inb(sony_cd_status_reg);
-}
-
-static inline unsigned char read_result_register(void)
-{
- return inb(sony_cd_result_reg);
-}
-
-static inline unsigned char read_data_register(void)
-{
- return inb(sony_cd_read_reg);
-}
-
-static inline void write_param(unsigned char param)
-{
- outb(param, sony_cd_param_reg);
-}
-
-static inline void write_cmd(unsigned char cmd)
-{
- outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT,
- sony_cd_control_reg);
- outb(cmd, sony_cd_cmd_reg);
-}
-
-static irqreturn_t cdu31a_interrupt(int irq, void *dev_id)
-{
- unsigned char val;
-
- if (abort_read_started) {
- /* We might be waiting for an abort to finish. Don't
- disable interrupts yet, though, because we handle
- this one here. */
- /* Clear out the result registers. */
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
-
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
- abort_read_started = 0;
-
- /* If something was waiting, wake it up now. */
- if (waitqueue_active(&cdu31a_irq_wait)) {
- disable_interrupts();
- irq_flag = 1;
- wake_up_interruptible(&cdu31a_irq_wait);
- }
- } else if (waitqueue_active(&cdu31a_irq_wait)) {
- disable_interrupts();
- irq_flag = 1;
- wake_up_interruptible(&cdu31a_irq_wait);
- } else {
- disable_interrupts();
- printk(KERN_NOTICE PFX
- "Got an interrupt but nothing was waiting\n");
- }
- return IRQ_HANDLED;
-}
-
-/*
- * give more verbose error messages
- */
-static unsigned char *translate_error(unsigned char err_code)
-{
- static unsigned char errbuf[80];
-
- switch (err_code) {
- case 0x10: return "illegal command ";
- case 0x11: return "illegal parameter ";
-
- case 0x20: return "not loaded ";
- case 0x21: return "no disc ";
- case 0x22: return "not spinning ";
- case 0x23: return "spinning ";
- case 0x25: return "spindle servo ";
- case 0x26: return "focus servo ";
- case 0x29: return "eject mechanism ";
- case 0x2a: return "audio playing ";
- case 0x2c: return "emergency eject ";
-
- case 0x30: return "focus ";
- case 0x31: return "frame sync ";
- case 0x32: return "subcode address ";
- case 0x33: return "block sync ";
- case 0x34: return "header address ";
-
- case 0x40: return "illegal track read ";
- case 0x41: return "mode 0 read ";
- case 0x42: return "illegal mode read ";
- case 0x43: return "illegal block size read ";
- case 0x44: return "mode read ";
- case 0x45: return "form read ";
- case 0x46: return "leadout read ";
- case 0x47: return "buffer overrun ";
-
- case 0x53: return "unrecoverable CIRC ";
- case 0x57: return "unrecoverable LECC ";
-
- case 0x60: return "no TOC ";
- case 0x61: return "invalid subcode data ";
- case 0x63: return "focus on TOC read ";
- case 0x64: return "frame sync on TOC read ";
- case 0x65: return "TOC data ";
-
- case 0x70: return "hardware failure ";
- case 0x91: return "leadin ";
- case 0x92: return "leadout ";
- case 0x93: return "data track ";
- }
- sprintf(errbuf, "unknown 0x%02x ", err_code);
- return errbuf;
-}
-
-/*
- * Set the drive parameters so the drive will auto-spin-up when a
- * disk is inserted.
- */
-static void set_drive_params(int want_doublespeed)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[3];
-
-
- params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME;
- params[1] = 0x00; /* Never spin down the drive. */
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX
- "Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);
- }
-
- params[0] = SONY_SD_MECH_CONTROL;
- params[1] = SONY_AUTO_SPIN_UP_BIT; /* Set auto spin up */
-
- if (is_auto_eject)
- params[1] |= SONY_AUTO_EJECT_BIT;
-
- if (is_double_speed && want_doublespeed) {
- params[1] |= SONY_DOUBLE_SPEED_BIT; /* Set the drive to double speed if
- possible */
- }
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX "Unable to set mechanical "
- "parameters: 0x%2.2x\n", res_reg[1]);
- }
-}
-
-/*
- * Uniform cdrom interface function
- * select reading speed for data access
- */
-static int scd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- if (speed == 0)
- sony_speed = 1;
- else
- sony_speed = speed - 1;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- set_drive_params(sony_speed);
- up(&sony_sem);
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * lock or unlock eject button
- */
-static int scd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- if (lock == 0) {
- is_auto_eject = 1;
- } else {
- is_auto_eject = 0;
- }
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- set_drive_params(sony_speed);
- up(&sony_sem);
- return 0;
-}
-
-/*
- * This code will reset the drive and attempt to restore sane parameters.
- */
-static void restart_on_error(void)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned long retry_count;
-
-
- printk(KERN_NOTICE PFX "Resetting drive on error\n");
- reset_drive();
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count) && (!is_attention())) {
- sony_sleep();
- }
- set_drive_params(sony_speed);
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_NOTICE PFX "Unable to spin up drive: 0x%2.2x\n",
- res_reg[1]);
- }
-
- msleep(2000);
-
- sony_get_toc();
-}
-
-/*
- * This routine writes data to the parameter register. Since this should
- * happen fairly fast, it is polled with no OS waits between.
- */
-static int write_params(unsigned char *params, int num_params)
-{
- unsigned int retry_count;
-
-
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0) && (!is_param_write_rdy())) {
- retry_count--;
- }
- if (!is_param_write_rdy()) {
- return -EIO;
- }
-
- while (num_params > 0) {
- write_param(*params);
- params++;
- num_params--;
- }
-
- return 0;
-}
-
-
-/*
- * The following reads data from the command result register. It is a
- * fairly complex routine, all status info flows back through this
- * interface. The algorithm is stolen directly from the flowcharts in
- * the drive manual.
- */
-static void
-get_result(unsigned char *result_buffer, unsigned int *result_size)
-{
- unsigned char a, b;
- int i;
- unsigned long retry_count;
-
-
- while (handle_sony_cd_attention());
- /* Wait for the result data to be ready */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && (is_busy() || (!(is_result_ready())))) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
- if (is_busy() || (!(is_result_ready()))) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] = SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
-
- /*
- * Get the first two bytes. This determines what else needs
- * to be done.
- */
- clear_result_ready();
- a = read_result_register();
- *result_buffer = a;
- result_buffer++;
-
- /* Check for block error status result. */
- if ((a & 0xf0) == 0x50) {
- *result_size = 1;
- return;
- }
-
- b = read_result_register();
- *result_buffer = b;
- result_buffer++;
- *result_size = 2;
-
- /*
- * 0x20 means an error occurred. Byte 2 will have the error code.
- * Otherwise, the command succeeded, byte 2 will have the count of
- * how many more status bytes are coming.
- *
- * The result register can be read 10 bytes at a time, a wait for
- * result ready to be asserted must be done between every 10 bytes.
- */
- if ((a & 0xf0) != 0x20) {
- if (b > 8) {
- for (i = 0; i < 8; i++) {
- *result_buffer = read_result_register();
- result_buffer++;
- (*result_size)++;
- }
- b = b - 8;
-
- while (b > 10) {
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0)
- && (!is_result_ready())) {
- retry_count--;
- }
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n",
- __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] =
- SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
-
- clear_result_ready();
-
- for (i = 0; i < 10; i++) {
- *result_buffer =
- read_result_register();
- result_buffer++;
- (*result_size)++;
- }
- b = b - 10;
- }
-
- if (b > 0) {
- retry_count = SONY_READY_RETRIES;
- while ((retry_count > 0)
- && (!is_result_ready())) {
- retry_count--;
- }
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n",
- __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] =
- SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- return;
- }
- }
- }
-
- while (b > 0) {
- *result_buffer = read_result_register();
- result_buffer++;
- (*result_size)++;
- b--;
- }
- }
-}
-
-/*
- * Do a command that does not involve data transfer. This routine must
- * be re-entrant from the same task to support being called from the
- * data operation code when an error occurs.
- */
-static void
-do_sony_cd_cmd(unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer, unsigned int *result_size)
-{
- unsigned long retry_count;
- int num_retries = 0;
-
-retry_cd_operation:
-
- while (handle_sony_cd_attention());
-
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && (is_busy())) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
- if (is_busy()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- result_buffer[0] = 0x20;
- result_buffer[1] = SONY_TIMEOUT_OP_ERR;
- *result_size = 2;
- } else {
- clear_result_ready();
- clear_param_reg();
-
- write_params(params, num_params);
- write_cmd(cmd);
-
- get_result(result_buffer, result_size);
- }
-
- if (((result_buffer[0] & 0xf0) == 0x20)
- && (num_retries < MAX_CDU31A_RETRIES)) {
- num_retries++;
- msleep(100);
- goto retry_cd_operation;
- }
-}
-
-
-/*
- * Handle an attention from the drive. This will return 1 if it found one
- * or 0 if not (if one is found, the caller might want to call again).
- *
- * This routine counts the number of consecutive times it is called
- * (since this is always called from a while loop until it returns
- * a 0), and returns a 0 if it happens too many times. This will help
- * prevent a lockup.
- */
-static int handle_sony_cd_attention(void)
-{
- unsigned char atten_code;
- static int num_consecutive_attentions = 0;
- volatile int val;
-
-
-#if 0
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-#endif
- if (is_attention()) {
- if (num_consecutive_attentions >
- CDU31A_MAX_CONSECUTIVE_ATTENTIONS) {
- printk(KERN_NOTICE PFX "Too many consecutive "
- "attentions: %d\n", num_consecutive_attentions);
- num_consecutive_attentions = 0;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__,
- __LINE__);
- return 0;
- }
-
- clear_attention();
- atten_code = read_result_register();
-
- switch (atten_code) {
- /* Someone changed the CD. Mark it as changed */
- case SONY_MECH_LOADED_ATTN:
- disk_changed = 1;
- sony_toc_read = 0;
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- sony_blocks_left = 0;
- break;
-
- case SONY_SPIN_DOWN_COMPLETE_ATTN:
- /* Mark the disk as spun down. */
- sony_spun_up = 0;
- break;
-
- case SONY_AUDIO_PLAY_DONE_ATTN:
- sony_audio_status = CDROM_AUDIO_COMPLETED;
- read_subcode();
- break;
-
- case SONY_EJECT_PUSHED_ATTN:
- if (is_auto_eject) {
- sony_audio_status = CDROM_AUDIO_INVALID;
- }
- break;
-
- case SONY_LEAD_IN_ERR_ATTN:
- case SONY_LEAD_OUT_ERR_ATTN:
- case SONY_DATA_TRACK_ERR_ATTN:
- case SONY_AUDIO_PLAYBACK_ERR_ATTN:
- sony_audio_status = CDROM_AUDIO_ERROR;
- break;
- }
-
- num_consecutive_attentions++;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- } else if (abort_read_started) {
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
- abort_read_started = 0;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- }
-
- num_consecutive_attentions = 0;
-#if 0
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-#endif
- return 0;
-}
-
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int int_to_bcd(unsigned int val)
-{
- int retval;
-
-
- retval = (val / 10) << 4;
- retval = retval | val % 10;
- return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int bcd_to_int(unsigned int bcd)
-{
- return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void log_to_msf(unsigned int log, unsigned char *msf)
-{
- log = log + LOG_START_OFFSET;
- msf[0] = int_to_bcd(log / 4500);
- log = log % 4500;
- msf[1] = int_to_bcd(log / 75);
- msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int msf_to_log(unsigned char *msf)
-{
- unsigned int log;
-
-
- log = msf[2];
- log += msf[1] * 75;
- log += msf[0] * 4500;
- log = log - LOG_START_OFFSET;
-
- return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void size_to_buf(unsigned int size, unsigned char *buf)
-{
- buf[0] = size / 65536;
- size = size % 65536;
- buf[1] = size / 256;
- buf[2] = size % 256;
-}
-
-/* Starts a read operation. Returns 0 on success and 1 on failure.
- The read operation used here allows multiple sequential sectors
- to be read and status returned for each sector. The driver will
- read the output one at a time as the requests come and abort the
- operation if the requested sector is not the next one from the
- drive. */
-static int
-start_request(unsigned int sector, unsigned int nsect)
-{
- unsigned char params[6];
- unsigned long retry_count;
-
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
- log_to_msf(sector, params);
- size_to_buf(nsect, &params[3]);
-
- /*
- * Clear any outstanding attentions and wait for the drive to
- * complete any pending operations.
- */
- while (handle_sony_cd_attention());
-
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && (is_busy())) {
- sony_sleep();
-
- while (handle_sony_cd_attention());
- }
-
- if (is_busy()) {
- printk(KERN_NOTICE PFX "Timeout while waiting "
- "to issue command\n");
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 1;
- } else {
- /* Issue the command */
- clear_result_ready();
- clear_param_reg();
-
- write_params(params, 6);
- write_cmd(SONY_READ_BLKERR_STAT_CMD);
-
- sony_blocks_left = nsect * 4;
- sony_next_block = sector * 4;
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
- return 0;
- }
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-/* Abort a pending read operation. Clear all the drive status variables. */
-static void abort_read(void)
-{
- unsigned char result_reg[2];
- int result_size;
- volatile int val;
-
-
- do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);
- if ((result_reg[0] & 0xf0) == 0x20) {
- printk(KERN_ERR PFX "Aborting read, %s error\n",
- translate_error(result_reg[1]));
- }
-
- while (is_result_reg_not_empty()) {
- val = read_result_register();
- }
- clear_data_ready();
- clear_result_ready();
- /* Clear out the data */
- while (is_data_requested()) {
- val = read_data_register();
- }
-
- sony_blocks_left = 0;
-}
-
-/* Called when the timer times out. This will abort the
- pending read operation. */
-static void handle_abort_timeout(unsigned long data)
-{
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
- /* If it is in use, ignore it. */
- if (down_trylock(&sony_sem) == 0) {
- /* We can't use abort_read(), because it will sleep
- or schedule in the timer interrupt. Just start
- the operation, finish it on the next access to
- the drive. */
- clear_result_ready();
- clear_param_reg();
- write_cmd(SONY_ABORT_CMD);
-
- sony_blocks_left = 0;
- abort_read_started = 1;
- up(&sony_sem);
- }
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* Actually get one sector of data from the drive. */
-static void
-input_data_sector(char *buffer)
-{
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- /* If an XA disk on a CDU31A, skip the first 12 bytes of data from
- the disk. The real data is after that. We can use audio_buffer. */
- if (sony_xa_mode)
- insb(sony_cd_read_reg, audio_buffer, CD_XA_HEAD);
-
- clear_data_ready();
-
- insb(sony_cd_read_reg, buffer, 2048);
-
- /* If an XA disk, we have to clear out the rest of the unused
- error correction data. We can use audio_buffer for that. */
- if (sony_xa_mode)
- insb(sony_cd_read_reg, audio_buffer, CD_XA_TAIL);
-
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-/* read data from the drive. Note the nsect must be <= 4. */
-static void
-read_data_block(char *buffer,
- unsigned int block,
- unsigned int nblocks,
- unsigned char res_reg[], int *res_size)
-{
- unsigned long retry_count;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- res_reg[0] = 0;
- res_reg[1] = 0;
- *res_size = 0;
-
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count) && !(is_data_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
- if (!(is_data_ready())) {
- if (is_result_ready()) {
- get_result(res_reg, res_size);
- if ((res_reg[0] & 0xf0) != 0x20) {
- printk(KERN_NOTICE PFX "Got result that should"
- " have been error: %d\n", res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- abort_read();
- } else {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- }
- } else {
- input_data_sector(buffer);
- sony_blocks_left -= nblocks;
- sony_next_block += nblocks;
-
- /* Wait for the status from the drive. */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && !(is_result_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
-
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- } else {
- get_result(res_reg, res_size);
-
- /* If we got a buffer status, handle that. */
- if ((res_reg[0] & 0xf0) == 0x50) {
-
- if ((res_reg[0] ==
- SONY_NO_CIRC_ERR_BLK_STAT)
- || (res_reg[0] ==
- SONY_NO_LECC_ERR_BLK_STAT)
- || (res_reg[0] ==
- SONY_RECOV_LECC_ERR_BLK_STAT)) {
- /* nothing here */
- } else {
- printk(KERN_ERR PFX "Data block "
- "error: 0x%x\n", res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
-
- /* Final transfer is done for read command, get final result. */
- if (sony_blocks_left == 0) {
- get_result(res_reg, res_size);
- }
- } else if ((res_reg[0] & 0xf0) != 0x20) {
- /* The drive gave me bad status, I don't know what to do.
- Reset the driver and return an error. */
- printk(KERN_ERR PFX "Invalid block "
- "status: 0x%x\n", res_reg[0]);
- restart_on_error();
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- }
- }
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail. Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations. This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void do_cdu31a_request(request_queue_t * q)
-{
- struct request *req;
- int block, nblock, num_retries;
- unsigned char res_reg[12];
- unsigned int res_size;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- spin_unlock_irq(q->queue_lock);
- if (down_interruptible(&sony_sem)) {
- spin_lock_irq(q->queue_lock);
- return;
- }
-
- /* Get drive status before doing anything. */
- while (handle_sony_cd_attention());
-
- /* Make sure we have a valid TOC. */
- sony_get_toc();
-
-
- /* Make sure the timer is cancelled. */
- del_timer(&cdu31a_abort_timer);
-
- while (1) {
- /*
- * The beginning here is stolen from the hard disk driver. I hope
- * it's right.
- */
- req = elv_next_request(q);
- if (!req)
- goto end_do_cdu31a_request;
-
- if (!sony_spun_up)
- scd_spinup();
-
- block = req->sector;
- nblock = req->nr_sectors;
- pr_debug(PFX "request at block %d, length %d blocks\n",
- block, nblock);
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
-
- /* WTF??? */
- if (!blk_fs_request(req)) {
- end_request(req, 0);
- continue;
- }
- if (rq_data_dir(req) == WRITE) {
- end_request(req, 0);
- continue;
- }
-
- /*
- * If the block address is invalid or the request goes beyond the end of
- * the media, return an error.
- */
- if (((block + nblock) / 4) >= sony_toc.lead_out_start_lba) {
- printk(KERN_NOTICE PFX "Request past end of media\n");
- end_request(req, 0);
- continue;
- }
-
- if (nblock > 4)
- nblock = 4;
- num_retries = 0;
-
- try_read_again:
- while (handle_sony_cd_attention());
-
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
-
- /* If no data is left to be read from the drive, start the
- next request. */
- if (sony_blocks_left == 0) {
- if (start_request(block / 4, nblock / 4)) {
- end_request(req, 0);
- continue;
- }
- }
- /* If the requested block is not the next one waiting in
- the driver, abort the current operation and start a
- new one. */
- else if (block != sony_next_block) {
- pr_debug(PFX "Read for block %d, expected %d\n",
- block, sony_next_block);
- abort_read();
- if (!sony_toc_read) {
- printk(KERN_NOTICE PFX "TOC not read\n");
- end_request(req, 0);
- continue;
- }
- if (start_request(block / 4, nblock / 4)) {
- printk(KERN_NOTICE PFX "start request failed\n");
- end_request(req, 0);
- continue;
- }
- }
-
- read_data_block(req->buffer, block, nblock, res_reg, &res_size);
-
- if (res_reg[0] != 0x20) {
- if (!end_that_request_first(req, 1, nblock)) {
- spin_lock_irq(q->queue_lock);
- blkdev_dequeue_request(req);
- end_that_request_last(req, 1);
- spin_unlock_irq(q->queue_lock);
- }
- continue;
- }
-
- if (num_retries > MAX_CDU31A_RETRIES) {
- end_request(req, 0);
- continue;
- }
-
- num_retries++;
- if (res_reg[1] == SONY_NOT_SPIN_ERR) {
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
- } else {
- printk(KERN_NOTICE PFX "%s error for block %d, nblock %d\n",
- translate_error(res_reg[1]), block, nblock);
- }
- goto try_read_again;
- }
- end_do_cdu31a_request:
-#if 0
- /* After finished, cancel any pending operations. */
- abort_read();
-#else
- /* Start a timer to time out after a while to disable
- the read. */
- cdu31a_abort_timer.expires = jiffies + 2 * HZ; /* Wait 2 seconds */
- add_timer(&cdu31a_abort_timer);
-#endif
-
- up(&sony_sem);
- spin_lock_irq(q->queue_lock);
- pr_debug(PFX "Leaving %s at %d\n", __FUNCTION__, __LINE__);
-}
-
-
-/*
- * Read the table of contents from the drive and set up TOC if
- * successful.
- */
-static void sony_get_toc(void)
-{
- unsigned char res_reg[2];
- unsigned int res_size;
- unsigned char parms[1];
- int session;
- int num_spin_ups;
- int totaltracks = 0;
- int mint = 99;
- int maxt = 0;
-
- pr_debug(PFX "Entering %s\n", __FUNCTION__);
-
- num_spin_ups = 0;
- if (!sony_toc_read) {
- respinup_on_gettoc:
- /* Ignore the result, since it might error if spinning already. */
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2)
- || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- /* If the drive is already playing, it's ok. */
- if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
- || (res_reg[1] == 0)) {
- goto gettoc_drive_spinning;
- }
-
- /* If the drive says it is not spun up (even though we just did it!)
- then retry the operation at least a few times. */
- if ((res_reg[1] == SONY_NOT_SPIN_ERR)
- && (num_spin_ups < MAX_CDU31A_RETRIES)) {
- num_spin_ups++;
- goto respinup_on_gettoc;
- }
-
- printk("cdu31a: Error reading TOC: %x %s\n",
- res_reg[0], translate_error(res_reg[1]));
- return;
- }
-
- gettoc_drive_spinning:
-
- /* The idea here is we keep asking for sessions until the command
- fails. Then we know what the last valid session on the disk is.
- No need to check session 0, since session 0 is the same as session
- 1; the command returns different information if you give it 0.
- */
-#if DEBUG
- memset(&sony_toc, 0x0e, sizeof(sony_toc));
- memset(&single_toc, 0x0f, sizeof(single_toc));
-#endif
- session = 1;
- while (1) {
-/* This seems to slow things down enough to make it work. This
- * appears to be a problem in do_sony_cd_cmd. This printk seems
- * to address the symptoms... -Erik */
- pr_debug(PFX "Trying session %d\n", session);
- parms[0] = session;
- do_sony_cd_cmd(SONY_READ_TOC_SPEC_CMD,
- parms, 1, res_reg, &res_size);
-
- pr_debug(PFX "%2.2x %2.2x\n", res_reg[0], res_reg[1]);
-
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- /* An error reading the TOC, this must be past the last session. */
- if (session == 1)
- printk
- ("Yikes! Couldn't read any sessions!");
- break;
- }
- pr_debug(PFX "Reading session %d\n", session);
-
- parms[0] = session;
- do_sony_cd_cmd(SONY_REQ_TOC_DATA_SPEC_CMD,
- parms,
- 1,
- (unsigned char *) &single_toc,
- &res_size);
- if ((res_size < 2)
- || ((single_toc.exec_status[0] & 0xf0) ==
- 0x20)) {
- printk(KERN_ERR PFX "Error reading "
- "session %d: %x %s\n",
- session, single_toc.exec_status[0],
- translate_error(single_toc.
- exec_status[1]));
- /* An error reading the TOC. Return without sony_toc_read
- set. */
- return;
- }
- pr_debug(PFX "add0 %01x, con0 %01x, poi0 %02x, "
- "1st trk %d, dsktyp %x, dum0 %x\n",
- single_toc.address0, single_toc.control0,
- single_toc.point0,
- bcd_to_int(single_toc.first_track_num),
- single_toc.disk_type, single_toc.dummy0);
- pr_debug(PFX "add1 %01x, con1 %01x, poi1 %02x, "
- "lst trk %d, dummy1 %x, dum2 %x\n",
- single_toc.address1, single_toc.control1,
- single_toc.point1,
- bcd_to_int(single_toc.last_track_num),
- single_toc.dummy1, single_toc.dummy2);
- pr_debug(PFX "add2 %01x, con2 %01x, poi2 %02x "
- "leadout start min %d, sec %d, frame %d\n",
- single_toc.address2, single_toc.control2,
- single_toc.point2,
- bcd_to_int(single_toc.lead_out_start_msf[0]),
- bcd_to_int(single_toc.lead_out_start_msf[1]),
- bcd_to_int(single_toc.lead_out_start_msf[2]));
- if (res_size > 18 && single_toc.pointb0 > 0xaf)
- pr_debug(PFX "addb0 %01x, conb0 %01x, poib0 %02x, nextsession min %d, sec %d, frame %d\n"
- "#mode5_ptrs %02d, max_start_outer_leadout_msf min %d, sec %d, frame %d\n",
- single_toc.addressb0,
- single_toc.controlb0,
- single_toc.pointb0,
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [0]),
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [1]),
- bcd_to_int(single_toc.
- next_poss_prog_area_msf
- [2]),
- single_toc.num_mode_5_pointers,
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [0]),
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [1]),
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [2]));
- if (res_size > 27 && single_toc.pointb1 > 0xaf)
- pr_debug(PFX "addb1 %01x, conb1 %01x, poib1 %02x, %x %x %x %x #skipint_ptrs %d, #skiptrkassign %d %x\n",
- single_toc.addressb1,
- single_toc.controlb1,
- single_toc.pointb1,
- single_toc.dummyb0_1[0],
- single_toc.dummyb0_1[1],
- single_toc.dummyb0_1[2],
- single_toc.dummyb0_1[3],
- single_toc.num_skip_interval_pointers,
- single_toc.num_skip_track_assignments,
- single_toc.dummyb0_2);
- if (res_size > 36 && single_toc.pointb2 > 0xaf)
- pr_debug(PFX "addb2 %01x, conb2 %01x, poib2 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb2,
- single_toc.controlb2,
- single_toc.pointb2,
- single_toc.tracksb2[0],
- single_toc.tracksb2[1],
- single_toc.tracksb2[2],
- single_toc.tracksb2[3],
- single_toc.tracksb2[4],
- single_toc.tracksb2[5],
- single_toc.tracksb2[6]);
- if (res_size > 45 && single_toc.pointb3 > 0xaf)
- pr_debug(PFX "addb3 %01x, conb3 %01x, poib3 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb3,
- single_toc.controlb3,
- single_toc.pointb3,
- single_toc.tracksb3[0],
- single_toc.tracksb3[1],
- single_toc.tracksb3[2],
- single_toc.tracksb3[3],
- single_toc.tracksb3[4],
- single_toc.tracksb3[5],
- single_toc.tracksb3[6]);
- if (res_size > 54 && single_toc.pointb4 > 0xaf)
- pr_debug(PFX "addb4 %01x, conb4 %01x, poib4 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressb4,
- single_toc.controlb4,
- single_toc.pointb4,
- single_toc.tracksb4[0],
- single_toc.tracksb4[1],
- single_toc.tracksb4[2],
- single_toc.tracksb4[3],
- single_toc.tracksb4[4],
- single_toc.tracksb4[5],
- single_toc.tracksb4[6]);
- if (res_size > 63 && single_toc.pointc0 > 0xaf)
- pr_debug(PFX "addc0 %01x, conc0 %01x, poic0 %02x, %02x %02x %02x %02x %02x %02x %02x\n",
- single_toc.addressc0,
- single_toc.controlc0,
- single_toc.pointc0,
- single_toc.dummyc0[0],
- single_toc.dummyc0[1],
- single_toc.dummyc0[2],
- single_toc.dummyc0[3],
- single_toc.dummyc0[4],
- single_toc.dummyc0[5],
- single_toc.dummyc0[6]);
-#undef DEBUG
-#define DEBUG 0
-
- sony_toc.lead_out_start_msf[0] =
- bcd_to_int(single_toc.lead_out_start_msf[0]);
- sony_toc.lead_out_start_msf[1] =
- bcd_to_int(single_toc.lead_out_start_msf[1]);
- sony_toc.lead_out_start_msf[2] =
- bcd_to_int(single_toc.lead_out_start_msf[2]);
- sony_toc.lead_out_start_lba =
- single_toc.lead_out_start_lba =
- msf_to_log(sony_toc.lead_out_start_msf);
-
- /* For points that do not exist, move the data over them
- to the right location. */
- if (single_toc.pointb0 != 0xb0) {
- memmove(((char *) &single_toc) + 27,
- ((char *) &single_toc) + 18,
- res_size - 18);
- res_size += 9;
- } else if (res_size > 18) {
- sony_toc.lead_out_start_msf[0] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [0]);
- sony_toc.lead_out_start_msf[1] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [1]);
- sony_toc.lead_out_start_msf[2] =
- bcd_to_int(single_toc.
- max_start_outer_leadout_msf
- [2]);
- sony_toc.lead_out_start_lba =
- msf_to_log(sony_toc.
- lead_out_start_msf);
- }
- if (single_toc.pointb1 != 0xb1) {
- memmove(((char *) &single_toc) + 36,
- ((char *) &single_toc) + 27,
- res_size - 27);
- res_size += 9;
- }
- if (single_toc.pointb2 != 0xb2) {
- memmove(((char *) &single_toc) + 45,
- ((char *) &single_toc) + 36,
- res_size - 36);
- res_size += 9;
- }
- if (single_toc.pointb3 != 0xb3) {
- memmove(((char *) &single_toc) + 54,
- ((char *) &single_toc) + 45,
- res_size - 45);
- res_size += 9;
- }
- if (single_toc.pointb4 != 0xb4) {
- memmove(((char *) &single_toc) + 63,
- ((char *) &single_toc) + 54,
- res_size - 54);
- res_size += 9;
- }
- if (single_toc.pointc0 != 0xc0) {
- memmove(((char *) &single_toc) + 72,
- ((char *) &single_toc) + 63,
- res_size - 63);
- res_size += 9;
- }
-#if DEBUG
- printk(PRINT_INFO PFX "start track lba %u, "
- "leadout start lba %u\n",
- single_toc.start_track_lba,
- single_toc.lead_out_start_lba);
- {
- int i;
- for (i = 0;
- i <
- 1 +
- bcd_to_int(single_toc.last_track_num)
- -
- bcd_to_int(single_toc.
- first_track_num); i++) {
- printk(KERN_INFO PFX "trk %02d: add 0x%01x, con 0x%01x, track %02d, start min %02d, sec %02d, frame %02d\n",
- i,
- single_toc.tracks[i].address,
- single_toc.tracks[i].control,
- bcd_to_int(single_toc.
- tracks[i].track),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [0]),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [1]),
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf
- [2]));
- if (mint >
- bcd_to_int(single_toc.
- tracks[i].track))
- mint =
- bcd_to_int(single_toc.
- tracks[i].
- track);
- if (maxt <
- bcd_to_int(single_toc.
- tracks[i].track))
- maxt =
- bcd_to_int(single_toc.
- tracks[i].
- track);
- }
- printk(KERN_INFO PFX "min track number %d, "
- "max track number %d\n",
- mint, maxt);
- }
-#endif
-
- /* prepare a special table of contents for a CD-I disc. They don't have one. */
- if (single_toc.disk_type == 0x10 &&
- single_toc.first_track_num == 2 &&
- single_toc.last_track_num == 2 /* CD-I */ ) {
- sony_toc.tracks[totaltracks].address = 1;
- sony_toc.tracks[totaltracks].control = 4; /* force data tracks */
- sony_toc.tracks[totaltracks].track = 1;
- sony_toc.tracks[totaltracks].
- track_start_msf[0] = 0;
- sony_toc.tracks[totaltracks].
- track_start_msf[1] = 2;
- sony_toc.tracks[totaltracks].
- track_start_msf[2] = 0;
- mint = maxt = 1;
- totaltracks++;
- } else
- /* gather track entries from this session */
- {
- int i;
- for (i = 0;
- i <
- 1 +
- bcd_to_int(single_toc.last_track_num)
- -
- bcd_to_int(single_toc.
- first_track_num);
- i++, totaltracks++) {
- sony_toc.tracks[totaltracks].
- address =
- single_toc.tracks[i].address;
- sony_toc.tracks[totaltracks].
- control =
- single_toc.tracks[i].control;
- sony_toc.tracks[totaltracks].
- track =
- bcd_to_int(single_toc.
- tracks[i].track);
- sony_toc.tracks[totaltracks].
- track_start_msf[0] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[0]);
- sony_toc.tracks[totaltracks].
- track_start_msf[1] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[1]);
- sony_toc.tracks[totaltracks].
- track_start_msf[2] =
- bcd_to_int(single_toc.
- tracks[i].
- track_start_msf[2]);
- if (i == 0)
- single_toc.
- start_track_lba =
- msf_to_log(sony_toc.
- tracks
- [totaltracks].
- track_start_msf);
- if (mint >
- sony_toc.tracks[totaltracks].
- track)
- mint =
- sony_toc.
- tracks[totaltracks].
- track;
- if (maxt <
- sony_toc.tracks[totaltracks].
- track)
- maxt =
- sony_toc.
- tracks[totaltracks].
- track;
- }
- }
- sony_toc.first_track_num = mint;
- sony_toc.last_track_num = maxt;
- /* Disk type of last session wins. For example:
- CD-Extra has disk type 0 for the first session, so
- a dumb HiFi CD player thinks it is a plain audio CD.
- We are interested in the disk type of the last session,
- which is 0x20 (XA) for CD-Extra, so we can access the
- data track ... */
- sony_toc.disk_type = single_toc.disk_type;
- sony_toc.sessions = session;
-
- /* don't believe everything :-) */
- if (session == 1)
- single_toc.start_track_lba = 0;
- sony_toc.start_track_lba =
- single_toc.start_track_lba;
-
- if (session > 1 && single_toc.pointb0 == 0xb0 &&
- sony_toc.lead_out_start_lba ==
- single_toc.lead_out_start_lba) {
- break;
- }
-
- /* Let's not get carried away... */
- if (session > 40) {
- printk(KERN_NOTICE PFX "too many sessions: "
- "%d\n", session);
- break;
- }
- session++;
- }
- sony_toc.track_entries = totaltracks;
- /* add one entry for the LAST track with track number CDROM_LEADOUT */
- sony_toc.tracks[totaltracks].address = single_toc.address2;
- sony_toc.tracks[totaltracks].control = single_toc.control2;
- sony_toc.tracks[totaltracks].track = CDROM_LEADOUT;
- sony_toc.tracks[totaltracks].track_start_msf[0] =
- sony_toc.lead_out_start_msf[0];
- sony_toc.tracks[totaltracks].track_start_msf[1] =
- sony_toc.lead_out_start_msf[1];
- sony_toc.tracks[totaltracks].track_start_msf[2] =
- sony_toc.lead_out_start_msf[2];
-
- sony_toc_read = 1;
-
- pr_debug(PFX "Disk session %d, start track: %d, "
- "stop track: %d\n",
- session, single_toc.start_track_lba,
- single_toc.lead_out_start_lba);
- }
- pr_debug(PFX "Leaving %s\n", __FUNCTION__);
-}
-
-
-/*
- * Uniform cdrom interface function
- * return multisession offset and sector information
- */
-static int scd_get_last_session(struct cdrom_device_info *cdi,
- struct cdrom_multisession *ms_info)
-{
- if (ms_info == NULL)
- return 1;
-
- if (!sony_toc_read) {
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- sony_get_toc();
- up(&sony_sem);
- }
-
- ms_info->addr_format = CDROM_LBA;
- ms_info->addr.lba = sony_toc.start_track_lba;
- ms_info->xa_flag = sony_toc.disk_type == SONY_XA_DISK_TYPE ||
- sony_toc.disk_type == 0x10 /* CDI */ ;
-
- return 0;
-}
-
-/*
- * Search for a specific track in the table of contents.
- */
-static int find_track(int track)
-{
- int i;
-
- for (i = 0; i <= sony_toc.track_entries; i++) {
- if (sony_toc.tracks[i].track == track) {
- return i;
- }
- }
-
- return -1;
-}
-
-
-/*
- * Read the subcode and put it in last_sony_subcode for future use.
- */
-static int read_subcode(void)
-{
- unsigned int res_size;
-
-
- do_sony_cd_cmd(SONY_REQ_SUBCODE_ADDRESS_CMD,
- NULL,
- 0, (unsigned char *) &last_sony_subcode, &res_size);
- if ((res_size < 2)
- || ((last_sony_subcode.exec_status[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Sony CDROM error %s (read_subcode)\n",
- translate_error(last_sony_subcode.exec_status[1]));
- return -EIO;
- }
-
- last_sony_subcode.track_num =
- bcd_to_int(last_sony_subcode.track_num);
- last_sony_subcode.index_num =
- bcd_to_int(last_sony_subcode.index_num);
- last_sony_subcode.abs_msf[0] =
- bcd_to_int(last_sony_subcode.abs_msf[0]);
- last_sony_subcode.abs_msf[1] =
- bcd_to_int(last_sony_subcode.abs_msf[1]);
- last_sony_subcode.abs_msf[2] =
- bcd_to_int(last_sony_subcode.abs_msf[2]);
-
- last_sony_subcode.rel_msf[0] =
- bcd_to_int(last_sony_subcode.rel_msf[0]);
- last_sony_subcode.rel_msf[1] =
- bcd_to_int(last_sony_subcode.rel_msf[1]);
- last_sony_subcode.rel_msf[2] =
- bcd_to_int(last_sony_subcode.rel_msf[2]);
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * return the media catalog number found on some older audio cds
- */
-static int
-scd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- unsigned char resbuffer[2 + 14];
- unsigned char *mcnp = mcn->medium_catalog_number;
- unsigned char *resp = resbuffer + 3;
- unsigned int res_size;
-
- memset(mcn->medium_catalog_number, 0, 14);
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- do_sony_cd_cmd(SONY_REQ_UPC_EAN_CMD,
- NULL, 0, resbuffer, &res_size);
- up(&sony_sem);
- if ((res_size < 2) || ((resbuffer[0] & 0xf0) == 0x20));
- else {
- /* packed bcd to single ASCII digits */
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- }
- *mcnp = '\0';
- return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing). If the drive is paused or completed, the subcode information has
- * already been stored, just use that. The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int sony_get_subchnl_info(struct cdrom_subchnl *schi)
-{
- /* Get attention stuff */
- while (handle_sony_cd_attention());
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
-
- switch (sony_audio_status) {
- case CDROM_AUDIO_NO_STATUS:
- case CDROM_AUDIO_PLAY:
- if (read_subcode() < 0) {
- return -EIO;
- }
- break;
-
- case CDROM_AUDIO_PAUSED:
- case CDROM_AUDIO_COMPLETED:
- break;
-
-#if 0
- case CDROM_AUDIO_NO_STATUS:
- schi->cdsc_audiostatus = sony_audio_status;
- return 0;
- break;
-#endif
- case CDROM_AUDIO_INVALID:
- case CDROM_AUDIO_ERROR:
- default:
- return -EIO;
- }
-
- schi->cdsc_audiostatus = sony_audio_status;
- schi->cdsc_adr = last_sony_subcode.address;
- schi->cdsc_ctrl = last_sony_subcode.control;
- schi->cdsc_trk = last_sony_subcode.track_num;
- schi->cdsc_ind = last_sony_subcode.index_num;
- if (schi->cdsc_format == CDROM_MSF) {
- schi->cdsc_absaddr.msf.minute =
- last_sony_subcode.abs_msf[0];
- schi->cdsc_absaddr.msf.second =
- last_sony_subcode.abs_msf[1];
- schi->cdsc_absaddr.msf.frame =
- last_sony_subcode.abs_msf[2];
-
- schi->cdsc_reladdr.msf.minute =
- last_sony_subcode.rel_msf[0];
- schi->cdsc_reladdr.msf.second =
- last_sony_subcode.rel_msf[1];
- schi->cdsc_reladdr.msf.frame =
- last_sony_subcode.rel_msf[2];
- } else if (schi->cdsc_format == CDROM_LBA) {
- schi->cdsc_absaddr.lba =
- msf_to_log(last_sony_subcode.abs_msf);
- schi->cdsc_reladdr.lba =
- msf_to_log(last_sony_subcode.rel_msf);
- }
-
- return 0;
-}
-
-/* Get audio data from the drive. This is fairly complex because I
- am looking for status and data at the same time, but if I get status
- then I just look for data. I need to get the status immediately so
- the switch from audio to data tracks will happen quickly. */
-static void
-read_audio_data(char *buffer, unsigned char res_reg[], int *res_size)
-{
- unsigned long retry_count;
- int result_read;
-
-
- res_reg[0] = 0;
- res_reg[1] = 0;
- *res_size = 0;
- result_read = 0;
-
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- continue_read_audio_wait:
- while (time_before(jiffies, retry_count) && !(is_data_ready())
- && !(is_result_ready() || result_read)) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
- if (!(is_data_ready())) {
- if (is_result_ready() && !result_read) {
- get_result(res_reg, res_size);
-
- /* Read block status and continue waiting for data. */
- if ((res_reg[0] & 0xf0) == 0x50) {
- result_read = 1;
- goto continue_read_audio_wait;
- }
- /* Invalid data from the drive. Shut down the operation. */
- else if ((res_reg[0] & 0xf0) != 0x20) {
- printk(KERN_WARNING PFX "Got result that "
- "should have been error: %d\n",
- res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- abort_read();
- } else {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- }
- } else {
- clear_data_ready();
-
- /* If data block, then get 2340 bytes offset by 12. */
- if (sony_raw_data_mode) {
- insb(sony_cd_read_reg, buffer + CD_XA_HEAD,
- CD_FRAMESIZE_RAW1);
- } else {
- /* Audio gets the whole 2352 bytes. */
- insb(sony_cd_read_reg, buffer, CD_FRAMESIZE_RAW);
- }
-
- /* If I haven't already gotten the result, get it now. */
- if (!result_read) {
- /* Wait for the drive to tell us we have something */
- retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && !(is_result_ready())) {
- while (handle_sony_cd_attention());
-
- sony_sleep();
- }
-
- if (!is_result_ready()) {
- pr_debug(PFX "timeout out %d\n", __LINE__);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_TIMEOUT_OP_ERR;
- *res_size = 2;
- abort_read();
- return;
- } else {
- get_result(res_reg, res_size);
- }
- }
-
- if ((res_reg[0] & 0xf0) == 0x50) {
- if ((res_reg[0] == SONY_NO_CIRC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_NO_LECC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_RECOV_LECC_ERR_BLK_STAT)
- || (res_reg[0] == SONY_NO_ERR_DETECTION_STAT)) {
- /* Ok, nothing to do. */
- } else {
- printk(KERN_ERR PFX "Data block error: 0x%x\n",
- res_reg[0]);
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- } else if ((res_reg[0] & 0xf0) != 0x20) {
- /* The drive gave me bad status, I don't know what to do.
- Reset the driver and return an error. */
- printk(KERN_NOTICE PFX "Invalid block status: 0x%x\n",
- res_reg[0]);
- restart_on_error();
- res_reg[0] = 0x20;
- res_reg[1] = SONY_BAD_DATA_ERR;
- *res_size = 2;
- }
- }
-}
-
-/* Perform a raw data read. This will automatically detect the
- track type and read the proper data (audio or data). */
-static int read_audio(struct cdrom_read_audio *ra)
-{
- int retval;
- unsigned char params[2];
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned int cframe;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (!sony_spun_up)
- scd_spinup();
-
- /* Set the drive to do raw operations. */
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x06 | sony_raw_data_mode;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to set decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- goto out_up;
- }
-
- /* From here down, we have to goto exit_read_audio instead of returning
- because the drive parameters have to be set back to data before
- return. */
-
- retval = 0;
- if (start_request(ra->addr.lba, ra->nframes)) {
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* For every requested frame. */
- cframe = 0;
- while (cframe < ra->nframes) {
- read_audio_data(audio_buffer, res_reg, &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- if (res_reg[1] == SONY_BAD_DATA_ERR) {
- printk(KERN_ERR PFX "Data error on audio "
- "sector %d\n",
- ra->addr.lba + cframe);
- } else if (res_reg[1] == SONY_ILL_TRACK_R_ERR) {
- /* Illegal track type, change track types and start over. */
- sony_raw_data_mode =
- (sony_raw_data_mode) ? 0 : 1;
-
- /* Set the drive mode. */
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x06 | sony_raw_data_mode;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params,
- 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to set "
- "decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* Restart the request on the current frame. */
- if (start_request
- (ra->addr.lba + cframe,
- ra->nframes - cframe)) {
- retval = -EIO;
- goto exit_read_audio;
- }
-
- /* Don't go back to the top because don't want to get into
- and infinite loop. A lot of code gets duplicated, but
- that's no big deal, I don't guess. */
- read_audio_data(audio_buffer, res_reg,
- &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- if (res_reg[1] ==
- SONY_BAD_DATA_ERR) {
- printk(KERN_ERR PFX "Data error"
- " on audio sector %d\n",
- ra->addr.lba +
- cframe);
- } else {
- printk(KERN_ERR PFX "Error reading audio data on sector %d: %s\n",
- ra->addr.lba + cframe,
- translate_error
- (res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
- } else if (copy_to_user(ra->buf +
- (CD_FRAMESIZE_RAW
- * cframe),
- audio_buffer,
- CD_FRAMESIZE_RAW)) {
- retval = -EFAULT;
- goto exit_read_audio;
- }
- } else {
- printk(KERN_ERR PFX "Error reading audio "
- "data on sector %d: %s\n",
- ra->addr.lba + cframe,
- translate_error(res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
- } else if (copy_to_user(ra->buf + (CD_FRAMESIZE_RAW * cframe),
- (char *)audio_buffer,
- CD_FRAMESIZE_RAW)) {
- retval = -EFAULT;
- goto exit_read_audio;
- }
-
- cframe++;
- }
-
- get_result(res_reg, &res_size);
- if ((res_reg[0] & 0xf0) == 0x20) {
- printk(KERN_ERR PFX "Error return from audio read: %s\n",
- translate_error(res_reg[1]));
- retval = -EIO;
- goto exit_read_audio;
- }
-
- exit_read_audio:
-
- /* Set the drive mode back to the proper one for the disk. */
- params[0] = SONY_SD_DECODE_PARAM;
- if (!sony_xa_mode) {
- params[1] = 0x0f;
- } else {
- params[1] = 0x07;
- }
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Unable to reset decode params: 0x%2.2x\n",
- res_reg[1]);
- retval = -EIO;
- }
-
- out_up:
- up(&sony_sem);
-
- return retval;
-}
-
-static int
-do_sony_cd_cmd_chk(const char *name,
- unsigned char cmd,
- unsigned char *params,
- unsigned int num_params,
- unsigned char *result_buffer, unsigned int *result_size)
-{
- do_sony_cd_cmd(cmd, params, num_params, result_buffer,
- result_size);
- if ((*result_size < 2) || ((result_buffer[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX "Error %s (CDROM%s)\n",
- translate_error(result_buffer[1]), name);
- return -EIO;
- }
- return 0;
-}
-
-/*
- * Uniform cdrom interface function
- * open the tray
- */
-static int scd_tray_move(struct cdrom_device_info *cdi, int position)
-{
- int retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- if (position == 1 /* open tray */ ) {
- unsigned char res_reg[12];
- unsigned int res_size;
-
- do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size);
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
-
- sony_audio_status = CDROM_AUDIO_INVALID;
- retval = do_sony_cd_cmd_chk("EJECT", SONY_EJECT_CMD, NULL, 0,
- res_reg, &res_size);
- } else {
- if (0 == scd_spinup())
- sony_spun_up = 1;
- retval = 0;
- }
- up(&sony_sem);
- return retval;
-}
-
-/*
- * The big ugly ioctl handler.
- */
-static int scd_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[7];
- int i, retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- retval = do_sony_cd_cmd_chk("START", SONY_SPIN_UP_CMD, NULL,
- 0, res_reg, &res_size);
- break;
-
- case CDROMSTOP: /* Spin down the drive */
- do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /*
- * Spin the drive down, ignoring the error if the disk was
- * already not spinning.
- */
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- retval = do_sony_cd_cmd_chk("STOP", SONY_SPIN_DOWN_CMD, NULL,
- 0, res_reg, &res_size);
- break;
-
- case CDROMPAUSE: /* Pause the drive */
- if (do_sony_cd_cmd_chk
- ("PAUSE", SONY_AUDIO_STOP_CMD, NULL, 0, res_reg,
- &res_size)) {
- retval = -EIO;
- break;
- }
- /* Get the current position and save it for resuming */
- if (read_subcode() < 0) {
- retval = -EIO;
- break;
- }
- cur_pos_msf[0] = last_sony_subcode.abs_msf[0];
- cur_pos_msf[1] = last_sony_subcode.abs_msf[1];
- cur_pos_msf[2] = last_sony_subcode.abs_msf[2];
- sony_audio_status = CDROM_AUDIO_PAUSED;
- retval = 0;
- break;
-
- case CDROMRESUME: /* Start the drive after being paused */
- if (sony_audio_status != CDROM_AUDIO_PAUSED) {
- retval = -EINVAL;
- break;
- }
-
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* Start the drive at the saved position. */
- params[1] = int_to_bcd(cur_pos_msf[0]);
- params[2] = int_to_bcd(cur_pos_msf[1]);
- params[3] = int_to_bcd(cur_pos_msf[2]);
- params[4] = int_to_bcd(final_pos_msf[0]);
- params[5] = int_to_bcd(final_pos_msf[1]);
- params[6] = int_to_bcd(final_pos_msf[2]);
- params[0] = 0x03;
- if (do_sony_cd_cmd_chk
- ("RESUME", SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg,
- &res_size) < 0) {
- retval = -EIO;
- break;
- }
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
-
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- /* The parameters are given in int, must be converted */
- for (i = 1; i < 7; i++) {
- params[i] =
- int_to_bcd(((unsigned char *) arg)[i - 1]);
- }
- params[0] = 0x03;
- if (do_sony_cd_cmd_chk
- ("PLAYMSF", SONY_AUDIO_PLAYBACK_CMD, params, 7,
- res_reg, &res_size) < 0) {
- retval = -EIO;
- break;
- }
-
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = bcd_to_int(params[4]);
- final_pos_msf[1] = bcd_to_int(params[5]);
- final_pos_msf[2] = bcd_to_int(params[6]);
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- {
- struct cdrom_tochdr *hdr;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- hdr = (struct cdrom_tochdr *) arg;
- hdr->cdth_trk0 = sony_toc.first_track_num;
- hdr->cdth_trk1 = sony_toc.last_track_num;
- }
- retval = 0;
- break;
-
- case CDROMREADTOCENTRY: /* Read a given table of contents entry */
- {
- struct cdrom_tocentry *entry;
- int track_idx;
- unsigned char *msf_val = NULL;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- entry = (struct cdrom_tocentry *) arg;
-
- track_idx = find_track(entry->cdte_track);
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
-
- entry->cdte_adr =
- sony_toc.tracks[track_idx].address;
- entry->cdte_ctrl =
- sony_toc.tracks[track_idx].control;
- msf_val =
- sony_toc.tracks[track_idx].track_start_msf;
-
- /* Logical buffer address or MSF format requested? */
- if (entry->cdte_format == CDROM_LBA) {
- entry->cdte_addr.lba = msf_to_log(msf_val);
- } else if (entry->cdte_format == CDROM_MSF) {
- entry->cdte_addr.msf.minute = *msf_val;
- entry->cdte_addr.msf.second =
- *(msf_val + 1);
- entry->cdte_addr.msf.frame =
- *(msf_val + 2);
- }
- }
- retval = 0;
- break;
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- {
- struct cdrom_ti *ti = (struct cdrom_ti *) arg;
- int track_idx;
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- if ((ti->cdti_trk0 < sony_toc.first_track_num)
- || (ti->cdti_trk0 > sony_toc.last_track_num)
- || (ti->cdti_trk1 < ti->cdti_trk0)) {
- retval = -EINVAL;
- break;
- }
-
- track_idx = find_track(ti->cdti_trk0);
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
- params[1] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[0]);
- params[2] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[1]);
- params[3] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[2]);
-
- /*
- * If we want to stop after the last track, use the lead-out
- * MSF to do that.
- */
- if (ti->cdti_trk1 >= sony_toc.last_track_num) {
- track_idx = find_track(CDROM_LEADOUT);
- } else {
- track_idx = find_track(ti->cdti_trk1 + 1);
- }
- if (track_idx < 0) {
- retval = -EINVAL;
- break;
- }
- params[4] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[0]);
- params[5] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[1]);
- params[6] =
- int_to_bcd(sony_toc.tracks[track_idx].
- track_start_msf[2]);
- params[0] = 0x03;
-
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg,
- &res_size);
-
- do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7,
- res_reg, &res_size);
-
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_ERR PFX
- "Params: %x %x %x %x %x %x %x\n",
- params[0], params[1], params[2],
- params[3], params[4], params[5],
- params[6]);
- printk(KERN_ERR PFX
- "Error %s (CDROMPLAYTRKIND)\n",
- translate_error(res_reg[1]));
- retval = -EIO;
- break;
- }
-
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = bcd_to_int(params[4]);
- final_pos_msf[1] = bcd_to_int(params[5]);
- final_pos_msf[2] = bcd_to_int(params[6]);
- sony_audio_status = CDROM_AUDIO_PLAY;
- retval = 0;
- break;
- }
-
- case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
- {
- struct cdrom_volctrl *volctrl =
- (struct cdrom_volctrl *) arg;
-
- params[0] = SONY_SD_AUDIO_VOLUME;
- params[1] = volctrl->channel0;
- params[2] = volctrl->channel1;
- retval = do_sony_cd_cmd_chk("VOLCTRL",
- SONY_SET_DRIVE_PARAM_CMD,
- params, 3, res_reg,
- &res_size);
- break;
- }
- case CDROMSUBCHNL: /* Get subchannel info */
- retval = sony_get_subchnl_info((struct cdrom_subchnl *) arg);
- break;
-
- default:
- retval = -EINVAL;
- break;
- }
- up(&sony_sem);
- return retval;
-}
-
-static int scd_read_audio(struct cdrom_device_info *cdi,
- unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int retval;
-
- if (down_interruptible(&sony_sem))
- return -ERESTARTSYS;
- switch (cmd) {
- case CDROMREADAUDIO: /* Read 2352 byte audio tracks and 2340 byte
- raw data tracks. */
- {
- struct cdrom_read_audio ra;
-
-
- sony_get_toc();
- if (!sony_toc_read) {
- retval = -EIO;
- break;
- }
-
- if (copy_from_user(&ra, argp, sizeof(ra))) {
- retval = -EFAULT;
- break;
- }
-
- if (ra.nframes == 0) {
- retval = 0;
- break;
- }
-
- if (!access_ok(VERIFY_WRITE, ra.buf,
- CD_FRAMESIZE_RAW * ra.nframes))
- return -EFAULT;
-
- if (ra.addr_format == CDROM_LBA) {
- if ((ra.addr.lba >=
- sony_toc.lead_out_start_lba)
- || (ra.addr.lba + ra.nframes >=
- sony_toc.lead_out_start_lba)) {
- retval = -EINVAL;
- break;
- }
- } else if (ra.addr_format == CDROM_MSF) {
- if ((ra.addr.msf.minute >= 75)
- || (ra.addr.msf.second >= 60)
- || (ra.addr.msf.frame >= 75)) {
- retval = -EINVAL;
- break;
- }
-
- ra.addr.lba = ((ra.addr.msf.minute * 4500)
- + (ra.addr.msf.second * 75)
- + ra.addr.msf.frame);
- if ((ra.addr.lba >=
- sony_toc.lead_out_start_lba)
- || (ra.addr.lba + ra.nframes >=
- sony_toc.lead_out_start_lba)) {
- retval = -EINVAL;
- break;
- }
-
- /* I know, this can go negative on an unsigned. However,
- the first thing done to the data is to add this value,
- so this should compensate and allow direct msf access. */
- ra.addr.lba -= LOG_START_OFFSET;
- } else {
- retval = -EINVAL;
- break;
- }
-
- retval = read_audio(&ra);
- break;
- }
- retval = 0;
- break;
-
- default:
- retval = -EINVAL;
- }
- up(&sony_sem);
- return retval;
-}
-
-static int scd_spinup(void)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- int num_spin_ups;
-
- num_spin_ups = 0;
-
- respinup_on_open:
- do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- printk(KERN_ERR PFX "%s error (scd_open, spin up)\n",
- translate_error(res_reg[1]));
- return 1;
- }
-
- do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
-
- /* The drive sometimes returns error 0. I don't know why, but ignore
- it. It seems to mean the drive has already done the operation. */
- if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0))) {
- /* If the drive is already playing, it's ok. */
- if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR)
- || (res_reg[1] == 0)) {
- return 0;
- }
-
- /* If the drive says it is not spun up (even though we just did it!)
- then retry the operation at least a few times. */
- if ((res_reg[1] == SONY_NOT_SPIN_ERR)
- && (num_spin_ups < MAX_CDU31A_RETRIES)) {
- num_spin_ups++;
- goto respinup_on_open;
- }
-
- printk(KERN_ERR PFX "Error %s (scd_open, read toc)\n",
- translate_error(res_reg[1]));
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
- return 1;
- }
- return 0;
-}
-
-/*
- * Open the drive for operations. Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int scd_open(struct cdrom_device_info *cdi, int purpose)
-{
- unsigned char res_reg[12];
- unsigned int res_size;
- unsigned char params[2];
-
- if (purpose == 1) {
- /* Open for IOCTLs only - no media check */
- sony_usage++;
- return 0;
- }
-
- if (sony_usage == 0) {
- if (scd_spinup() != 0)
- return -EIO;
- sony_get_toc();
- if (!sony_toc_read) {
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0,
- res_reg, &res_size);
- return -EIO;
- }
-
- /* For XA on the CDU31A only, we have to do special reads.
- The CDU33A handles XA automagically. */
- /* if ( (sony_toc.disk_type == SONY_XA_DISK_TYPE) */
- if ((sony_toc.disk_type != 0x00)
- && (!is_double_speed)) {
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x07;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_WARNING PFX "Unable to set "
- "XA params: 0x%2.2x\n", res_reg[1]);
- }
- sony_xa_mode = 1;
- }
- /* A non-XA disk. Set the parms back if necessary. */
- else if (sony_xa_mode) {
- params[0] = SONY_SD_DECODE_PARAM;
- params[1] = 0x0f;
- do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,
- params, 2, res_reg, &res_size);
- if ((res_size < 2)
- || ((res_reg[0] & 0xf0) == 0x20)) {
- printk(KERN_WARNING PFX "Unable to reset "
- "XA params: 0x%2.2x\n", res_reg[1]);
- }
- sony_xa_mode = 0;
- }
-
- sony_spun_up = 1;
- }
-
- sony_usage++;
-
- return 0;
-}
-
-
-/*
- * Close the drive. Spin it down if no task is using it. The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static void scd_release(struct cdrom_device_info *cdi)
-{
- if (sony_usage == 1) {
- unsigned char res_reg[12];
- unsigned int res_size;
-
- do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg,
- &res_size);
-
- sony_spun_up = 0;
- }
- sony_usage--;
-}
-
-static struct cdrom_device_ops scd_dops = {
- .open = scd_open,
- .release = scd_release,
- .drive_status = scd_drive_status,
- .media_changed = scd_media_changed,
- .tray_move = scd_tray_move,
- .lock_door = scd_lock_door,
- .select_speed = scd_select_speed,
- .get_last_session = scd_get_last_session,
- .get_mcn = scd_get_mcn,
- .reset = scd_reset,
- .audio_ioctl = scd_audio_ioctl,
- .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
- CDC_SELECT_SPEED | CDC_MULTI_SESSION |
- CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
- CDC_RESET | CDC_DRIVE_STATUS,
- .n_minors = 1,
-};
-
-static struct cdrom_device_info scd_info = {
- .ops = &scd_dops,
- .speed = 2,
- .capacity = 1,
- .name = "cdu31a"
-};
-
-static int scd_block_open(struct inode *inode, struct file *file)
-{
- return cdrom_open(&scd_info, inode, file);
-}
-
-static int scd_block_release(struct inode *inode, struct file *file)
-{
- return cdrom_release(&scd_info, file);
-}
-
-static int scd_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- int retval;
-
- /* The eject and close commands should be handled by Uniform CD-ROM
- * driver - but I always got hard lockup instead of eject
- * until I put this here.
- */
- switch (cmd) {
- case CDROMEJECT:
- scd_lock_door(&scd_info, 0);
- retval = scd_tray_move(&scd_info, 1);
- break;
- case CDROMCLOSETRAY:
- retval = scd_tray_move(&scd_info, 0);
- break;
- case CDROMREADAUDIO:
- retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg);
- break;
- default:
- retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
- }
- return retval;
-}
-
-static int scd_block_media_changed(struct gendisk *disk)
-{
- return cdrom_media_changed(&scd_info);
-}
-
-static struct block_device_operations scd_bdops =
-{
- .owner = THIS_MODULE,
- .open = scd_block_open,
- .release = scd_block_release,
- .ioctl = scd_block_ioctl,
- .media_changed = scd_block_media_changed,
-};
-
-static struct gendisk *scd_gendisk;
-
-/* The different types of disc loading mechanisms supported */
-static char *load_mech[] __initdata =
- { "caddy", "tray", "pop-up", "unknown" };
-
-static int __init
-get_drive_configuration(unsigned short base_io,
- unsigned char res_reg[], unsigned int *res_size)
-{
- unsigned long retry_count;
-
-
- if (!request_region(base_io, 4, "cdu31a"))
- return 0;
-
- /* Set the base address */
- cdu31a_port = base_io;
-
- /* Set up all the register locations */
- sony_cd_cmd_reg = cdu31a_port + SONY_CMD_REG_OFFSET;
- sony_cd_param_reg = cdu31a_port + SONY_PARAM_REG_OFFSET;
- sony_cd_write_reg = cdu31a_port + SONY_WRITE_REG_OFFSET;
- sony_cd_control_reg = cdu31a_port + SONY_CONTROL_REG_OFFSET;
- sony_cd_status_reg = cdu31a_port + SONY_STATUS_REG_OFFSET;
- sony_cd_result_reg = cdu31a_port + SONY_RESULT_REG_OFFSET;
- sony_cd_read_reg = cdu31a_port + SONY_READ_REG_OFFSET;
- sony_cd_fifost_reg = cdu31a_port + SONY_FIFOST_REG_OFFSET;
-
- /*
- * Check to see if anything exists at the status register location.
- * I don't know if this is a good way to check, but it seems to work
- * ok for me.
- */
- if (read_status_register() != 0xff) {
- /*
- * Reset the drive and wait for attention from it (to say it's reset).
- * If you don't wait, the next operation will probably fail.
- */
- reset_drive();
- retry_count = jiffies + SONY_RESET_TIMEOUT;
- while (time_before(jiffies, retry_count)
- && (!is_attention())) {
- sony_sleep();
- }
-
-#if 0
- /* If attention is never seen probably not a CDU31a present */
- if (!is_attention()) {
- res_reg[0] = 0x20;
- goto out_err;
- }
-#endif
-
- /*
- * Get the drive configuration.
- */
- do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,
- NULL,
- 0, (unsigned char *) res_reg, res_size);
- if (*res_size <= 2 || (res_reg[0] & 0xf0) != 0)
- goto out_err;
- return 1;
- }
-
- /* Return an error */
- res_reg[0] = 0x20;
-out_err:
- release_region(cdu31a_port, 4);
- cdu31a_port = 0;
- return 0;
-}
-
-#ifndef MODULE
-/*
- * Set up base I/O and interrupts, called from main.c.
- */
-
-static int __init cdu31a_setup(char *strings)
-{
- int ints[4];
-
- (void) get_options(strings, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0) {
- cdu31a_port = ints[1];
- }
- if (ints[0] > 1) {
- cdu31a_irq = ints[2];
- }
- if ((strings != NULL) && (*strings != '\0')) {
- if (strcmp(strings, "PAS") == 0) {
- sony_pas_init = 1;
- } else {
- printk(KERN_NOTICE PFX "Unknown interface type: %s\n",
- strings);
- }
- }
-
- return 1;
-}
-
-__setup("cdu31a=", cdu31a_setup);
-
-#endif
-
-/*
- * Initialize the driver.
- */
-int __init cdu31a_init(void)
-{
- struct s_sony_drive_config drive_config;
- struct gendisk *disk;
- int deficiency = 0;
- unsigned int res_size;
- char msg[255];
- char buf[40];
- int i;
- int tmp_irq;
-
- /*
- * According to Alex Freed (freed@europa.orion.adobe.com), this is
- * required for the Fusion CD-16 package. If the sound driver is
- * loaded, it should work fine, but just in case...
- *
- * The following turn on the CD-ROM interface for a Fusion CD-16.
- */
- if (sony_pas_init) {
- outb(0xbc, 0x9a01);
- outb(0xe2, 0x9a01);
- }
-
- /* Setting the base I/O address to 0xffff will disable it. */
- if (cdu31a_port == 0xffff)
- goto errout3;
-
- if (cdu31a_port != 0) {
- /* Need IRQ 0 because we can't sleep here. */
- tmp_irq = cdu31a_irq;
- cdu31a_irq = 0;
- if (!get_drive_configuration(cdu31a_port,
- drive_config.exec_status,
- &res_size))
- goto errout3;
- cdu31a_irq = tmp_irq;
- } else {
- cdu31a_irq = 0;
- for (i = 0; cdu31a_addresses[i].base; i++) {
- if (get_drive_configuration(cdu31a_addresses[i].base,
- drive_config.exec_status,
- &res_size)) {
- cdu31a_irq = cdu31a_addresses[i].int_num;
- break;
- }
- }
- if (!cdu31a_port)
- goto errout3;
- }
-
- if (register_blkdev(MAJOR_NR, "cdu31a"))
- goto errout2;
-
- disk = alloc_disk(1);
- if (!disk)
- goto errout1;
- disk->major = MAJOR_NR;
- disk->first_minor = 0;
- sprintf(disk->disk_name, "cdu31a");
- disk->fops = &scd_bdops;
- disk->flags = GENHD_FL_CD;
-
- if (SONY_HWC_DOUBLE_SPEED(drive_config))
- is_double_speed = 1;
-
- tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */
- cdu31a_irq = 0;
-
- sony_speed = is_double_speed; /* Set 2X drives to 2X by default */
- set_drive_params(sony_speed);
-
- cdu31a_irq = tmp_irq;
-
- if (cdu31a_irq > 0) {
- if (request_irq
- (cdu31a_irq, cdu31a_interrupt, IRQF_DISABLED,
- "cdu31a", NULL)) {
- printk(KERN_WARNING PFX "Unable to grab IRQ%d for "
- "the CDU31A driver\n", cdu31a_irq);
- cdu31a_irq = 0;
- }
- }
-
- sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
- drive_config.vendor_id,
- drive_config.product_id,
- drive_config.product_rev_level);
- sprintf(buf, " Capabilities: %s",
- load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
- strcat(msg, buf);
- if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
- strcat(msg, ", audio");
- else
- deficiency |= CDC_PLAY_AUDIO;
- if (SONY_HWC_EJECT(drive_config))
- strcat(msg, ", eject");
- else
- deficiency |= CDC_OPEN_TRAY;
- if (SONY_HWC_LED_SUPPORT(drive_config))
- strcat(msg, ", LED");
- if (SONY_HWC_ELECTRIC_VOLUME(drive_config))
- strcat(msg, ", elec. Vol");
- if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config))
- strcat(msg, ", sep. Vol");
- if (is_double_speed)
- strcat(msg, ", double speed");
- else
- deficiency |= CDC_SELECT_SPEED;
- if (cdu31a_irq > 0) {
- sprintf(buf, ", irq %d", cdu31a_irq);
- strcat(msg, buf);
- }
- strcat(msg, "\n");
- printk(KERN_INFO PFX "%s",msg);
-
- cdu31a_queue = blk_init_queue(do_cdu31a_request, &cdu31a_lock);
- if (!cdu31a_queue)
- goto errout0;
- blk_queue_hardsect_size(cdu31a_queue, 2048);
-
- init_timer(&cdu31a_abort_timer);
- cdu31a_abort_timer.function = handle_abort_timeout;
-
- scd_info.mask = deficiency;
- scd_gendisk = disk;
- if (register_cdrom(&scd_info))
- goto err;
- disk->queue = cdu31a_queue;
- add_disk(disk);
-
- disk_changed = 1;
- return 0;
-
-err:
- blk_cleanup_queue(cdu31a_queue);
-errout0:
- if (cdu31a_irq)
- free_irq(cdu31a_irq, NULL);
- printk(KERN_ERR PFX "Unable to register with Uniform cdrom driver\n");
- put_disk(disk);
-errout1:
- if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
- printk(KERN_WARNING PFX "Can't unregister block device\n");
- }
-errout2:
- release_region(cdu31a_port, 4);
-errout3:
- return -EIO;
-}
-
-
-static void __exit cdu31a_exit(void)
-{
- del_gendisk(scd_gendisk);
- put_disk(scd_gendisk);
- if (unregister_cdrom(&scd_info)) {
- printk(KERN_WARNING PFX "Can't unregister from Uniform "
- "cdrom driver\n");
- return;
- }
- if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
- printk(KERN_WARNING PFX "Can't unregister\n");
- return;
- }
-
- blk_cleanup_queue(cdu31a_queue);
-
- if (cdu31a_irq > 0)
- free_irq(cdu31a_irq, NULL);
-
- release_region(cdu31a_port, 4);
- printk(KERN_INFO PFX "module released.\n");
-}
-
-#ifdef MODULE
-module_init(cdu31a_init);
-#endif
-module_exit(cdu31a_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU31A_CDROM_MAJOR);
diff --git a/drivers/cdrom/cdu31a.h b/drivers/cdrom/cdu31a.h
deleted file mode 100644
index 61d4768c412..00000000000
--- a/drivers/cdrom/cdu31a.h
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Definitions for a Sony interface CDROM drive.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com)
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- */
-
-/*
- * General defines.
- */
-#define SONY_XA_DISK_TYPE 0x20
-
-/*
- * Offsets (from the base address) and bits for the various write registers
- * of the drive.
- */
-#define SONY_CMD_REG_OFFSET 0
-#define SONY_PARAM_REG_OFFSET 1
-#define SONY_WRITE_REG_OFFSET 2
-#define SONY_CONTROL_REG_OFFSET 3
-# define SONY_ATTN_CLR_BIT 0x01
-# define SONY_RES_RDY_CLR_BIT 0x02
-# define SONY_DATA_RDY_CLR_BIT 0x04
-# define SONY_ATTN_INT_EN_BIT 0x08
-# define SONY_RES_RDY_INT_EN_BIT 0x10
-# define SONY_DATA_RDY_INT_EN_BIT 0x20
-# define SONY_PARAM_CLR_BIT 0x40
-# define SONY_DRIVE_RESET_BIT 0x80
-
-/*
- * Offsets (from the base address) and bits for the various read registers
- * of the drive.
- */
-#define SONY_STATUS_REG_OFFSET 0
-# define SONY_ATTN_BIT 0x01
-# define SONY_RES_RDY_BIT 0x02
-# define SONY_DATA_RDY_BIT 0x04
-# define SONY_ATTN_INT_ST_BIT 0x08
-# define SONY_RES_RDY_INT_ST_BIT 0x10
-# define SONY_DATA_RDY_INT_ST_BIT 0x20
-# define SONY_DATA_REQUEST_BIT 0x40
-# define SONY_BUSY_BIT 0x80
-#define SONY_RESULT_REG_OFFSET 1
-#define SONY_READ_REG_OFFSET 2
-#define SONY_FIFOST_REG_OFFSET 3
-# define SONY_PARAM_WRITE_RDY_BIT 0x01
-# define SONY_PARAM_REG_EMPTY_BIT 0x02
-# define SONY_RES_REG_NOT_EMP_BIT 0x04
-# define SONY_RES_REG_FULL_BIT 0x08
-
-#define LOG_START_OFFSET 150 /* Offset of first logical sector */
-
-#define SONY_DETECT_TIMEOUT (8*HZ/10) /* Maximum amount of time
- that drive detection code
- will wait for response
- from drive (in 1/100th's
- of seconds). */
-
-#define SONY_JIFFIES_TIMEOUT (10*HZ) /* Maximum number of times the
- drive will wait/try for an
- operation */
-#define SONY_RESET_TIMEOUT HZ /* Maximum number of times the
- drive will wait/try a reset
- operation */
-#define SONY_READY_RETRIES 20000 /* How many times to retry a
- spin waiting for a register
- to come ready */
-
-#define MAX_CDU31A_RETRIES 3 /* How many times to retry an
- operation */
-
-/* Commands to request or set drive control parameters and disc information */
-#define SONY_REQ_DRIVE_CONFIG_CMD 0x00 /* Returns s_sony_drive_config */
-#define SONY_REQ_DRIVE_MODE_CMD 0x01
-#define SONY_REQ_DRIVE_PARAM_CMD 0x02
-#define SONY_REQ_MECH_STATUS_CMD 0x03
-#define SONY_REQ_AUDIO_STATUS_CMD 0x04
-#define SONY_SET_DRIVE_PARAM_CMD 0x10
-#define SONY_REQ_TOC_DATA_CMD 0x20 /* Returns s_sony_toc */
-#define SONY_REQ_SUBCODE_ADDRESS_CMD 0x21 /* Returns s_sony_subcode */
-#define SONY_REQ_UPC_EAN_CMD 0x22
-#define SONY_REQ_ISRC_CMD 0x23
-#define SONY_REQ_TOC_DATA_SPEC_CMD 0x24 /* Returns s_sony_session_toc */
-
-/* Commands to request information from the drive */
-#define SONY_READ_TOC_CMD 0x30 /* let the drive firmware grab the TOC */
-#define SONY_SEEK_CMD 0x31
-#define SONY_READ_CMD 0x32
-#define SONY_READ_BLKERR_STAT_CMD 0x34
-#define SONY_ABORT_CMD 0x35
-#define SONY_READ_TOC_SPEC_CMD 0x36
-
-/* Commands to control audio */
-#define SONY_AUDIO_PLAYBACK_CMD 0x40
-#define SONY_AUDIO_STOP_CMD 0x41
-#define SONY_AUDIO_SCAN_CMD 0x42
-
-/* Miscellaneous control commands */
-#define SONY_EJECT_CMD 0x50
-#define SONY_SPIN_UP_CMD 0x51
-#define SONY_SPIN_DOWN_CMD 0x52
-
-/* Diagnostic commands */
-#define SONY_WRITE_BUFFER_CMD 0x60
-#define SONY_READ_BUFFER_CMD 0x61
-#define SONY_DIAGNOSTICS_CMD 0x62
-
-
-/*
- * The following are command parameters for the set drive parameter command
- */
-#define SONY_SD_DECODE_PARAM 0x00
-#define SONY_SD_INTERFACE_PARAM 0x01
-#define SONY_SD_BUFFERING_PARAM 0x02
-#define SONY_SD_AUDIO_PARAM 0x03
-#define SONY_SD_AUDIO_VOLUME 0x04
-#define SONY_SD_MECH_CONTROL 0x05
-#define SONY_SD_AUTO_SPIN_DOWN_TIME 0x06
-
-/*
- * The following are parameter bits for the mechanical control command
- */
-#define SONY_AUTO_SPIN_UP_BIT 0x01
-#define SONY_AUTO_EJECT_BIT 0x02
-#define SONY_DOUBLE_SPEED_BIT 0x04
-
-/*
- * The following extract information from the drive configuration about
- * the drive itself.
- */
-#define SONY_HWC_GET_LOAD_MECH(c) (c.hw_config[0] & 0x03)
-#define SONY_HWC_EJECT(c) (c.hw_config[0] & 0x04)
-#define SONY_HWC_LED_SUPPORT(c) (c.hw_config[0] & 0x08)
-#define SONY_HWC_DOUBLE_SPEED(c) (c.hw_config[0] & 0x10)
-#define SONY_HWC_GET_BUF_MEM_SIZE(c) ((c.hw_config[0] & 0xc0) >> 6)
-#define SONY_HWC_AUDIO_PLAYBACK(c) (c.hw_config[1] & 0x01)
-#define SONY_HWC_ELECTRIC_VOLUME(c) (c.hw_config[1] & 0x02)
-#define SONY_HWC_ELECTRIC_VOLUME_CTL(c) (c.hw_config[1] & 0x04)
-
-#define SONY_HWC_CADDY_LOAD_MECH 0x00
-#define SONY_HWC_TRAY_LOAD_MECH 0x01
-#define SONY_HWC_POPUP_LOAD_MECH 0x02
-#define SONY_HWC_UNKWN_LOAD_MECH 0x03
-
-#define SONY_HWC_8KB_BUFFER 0x00
-#define SONY_HWC_32KB_BUFFER 0x01
-#define SONY_HWC_64KB_BUFFER 0x02
-#define SONY_HWC_UNKWN_BUFFER 0x03
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s_sony_drive_config
-{
- unsigned char exec_status[2];
- char vendor_id[8];
- char product_id[16];
- char product_rev_level[8];
- unsigned char hw_config[2];
-};
-
-/* The following is returned from the request subcode address command */
-struct s_sony_subcode
-{
- unsigned char exec_status[2];
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track_num;
- unsigned char index_num;
- unsigned char rel_msf[3];
- unsigned char reserved1;
- unsigned char abs_msf[3];
-};
-
-#define MAX_TRACKS 100 /* The maximum tracks a disk may have. */
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s_sony_toc
-{
- unsigned char exec_status[2];
- unsigned char address0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char disk_type;
- unsigned char dummy0;
- unsigned char address1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char address2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int lead_out_start_lba;
-};
-
-struct s_sony_session_toc
-{
- unsigned char exec_status[2];
- unsigned char session_number;
- unsigned char address0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char disk_type;
- unsigned char dummy0;
- unsigned char address1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char address2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- unsigned char addressb0 :4;
- unsigned char controlb0 :4;
- unsigned char pointb0;
- unsigned char next_poss_prog_area_msf[3];
- unsigned char num_mode_5_pointers;
- unsigned char max_start_outer_leadout_msf[3];
- unsigned char addressb1 :4;
- unsigned char controlb1 :4;
- unsigned char pointb1;
- unsigned char dummyb0_1[4];
- unsigned char num_skip_interval_pointers;
- unsigned char num_skip_track_assignments;
- unsigned char dummyb0_2;
- unsigned char addressb2 :4;
- unsigned char controlb2 :4;
- unsigned char pointb2;
- unsigned char tracksb2[7];
- unsigned char addressb3 :4;
- unsigned char controlb3 :4;
- unsigned char pointb3;
- unsigned char tracksb3[7];
- unsigned char addressb4 :4;
- unsigned char controlb4 :4;
- unsigned char pointb4;
- unsigned char tracksb4[7];
- unsigned char addressc0 :4;
- unsigned char controlc0 :4;
- unsigned char pointc0;
- unsigned char dummyc0[7];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int start_track_lba;
- unsigned int lead_out_start_lba;
- unsigned int mint;
- unsigned int maxt;
-};
-
-struct s_all_sessions_toc
-{
- unsigned char sessions;
- unsigned int track_entries;
- unsigned char first_track_num;
- unsigned char last_track_num;
- unsigned char disk_type;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[MAX_TRACKS];
-
- unsigned int start_track_lba;
- unsigned int lead_out_start_lba;
-};
-
-
-/*
- * The following are errors returned from the drive.
- */
-
-/* Command error group */
-#define SONY_ILL_CMD_ERR 0x10
-#define SONY_ILL_PARAM_ERR 0x11
-
-/* Mechanism group */
-#define SONY_NOT_LOAD_ERR 0x20
-#define SONY_NO_DISK_ERR 0x21
-#define SONY_NOT_SPIN_ERR 0x22
-#define SONY_SPIN_ERR 0x23
-#define SONY_SPINDLE_SERVO_ERR 0x25
-#define SONY_FOCUS_SERVO_ERR 0x26
-#define SONY_EJECT_MECH_ERR 0x29
-#define SONY_AUDIO_PLAYING_ERR 0x2a
-#define SONY_EMERGENCY_EJECT_ERR 0x2c
-
-/* Seek error group */
-#define SONY_FOCUS_ERR 0x30
-#define SONY_FRAME_SYNC_ERR 0x31
-#define SONY_SUBCODE_ADDR_ERR 0x32
-#define SONY_BLOCK_SYNC_ERR 0x33
-#define SONY_HEADER_ADDR_ERR 0x34
-
-/* Read error group */
-#define SONY_ILL_TRACK_R_ERR 0x40
-#define SONY_MODE_0_R_ERR 0x41
-#define SONY_ILL_MODE_R_ERR 0x42
-#define SONY_ILL_BLOCK_SIZE_R_ERR 0x43
-#define SONY_MODE_R_ERR 0x44
-#define SONY_FORM_R_ERR 0x45
-#define SONY_LEAD_OUT_R_ERR 0x46
-#define SONY_BUFFER_OVERRUN_R_ERR 0x47
-
-/* Data error group */
-#define SONY_UNREC_CIRC_ERR 0x53
-#define SONY_UNREC_LECC_ERR 0x57
-
-/* Subcode error group */
-#define SONY_NO_TOC_ERR 0x60
-#define SONY_SUBCODE_DATA_NVAL_ERR 0x61
-#define SONY_FOCUS_ON_TOC_READ_ERR 0x63
-#define SONY_FRAME_SYNC_ON_TOC_READ_ERR 0x64
-#define SONY_TOC_DATA_ERR 0x65
-
-/* Hardware failure group */
-#define SONY_HW_FAILURE_ERR 0x70
-#define SONY_LEAD_IN_A_ERR 0x91
-#define SONY_LEAD_OUT_A_ERR 0x92
-#define SONY_DATA_TRACK_A_ERR 0x93
-
-/*
- * The following are returned from the Read With Block Error Status command.
- * They are not errors but information (Errors from the 0x5x group above may
- * also be returned
- */
-#define SONY_NO_CIRC_ERR_BLK_STAT 0x50
-#define SONY_NO_LECC_ERR_BLK_STAT 0x54
-#define SONY_RECOV_LECC_ERR_BLK_STAT 0x55
-#define SONY_NO_ERR_DETECTION_STAT 0x59
-
-/*
- * The following is not an error returned by the drive, but by the code
- * that talks to the drive. It is returned because of a timeout.
- */
-#define SONY_TIMEOUT_OP_ERR 0x01
-#define SONY_SIGNAL_OP_ERR 0x02
-#define SONY_BAD_DATA_ERR 0x03
-
-
-/*
- * The following are attention code for asynchronous events from the drive.
- */
-
-/* Standard attention group */
-#define SONY_EMER_EJECT_ATTN 0x2c
-#define SONY_HW_FAILURE_ATTN 0x70
-#define SONY_MECH_LOADED_ATTN 0x80
-#define SONY_EJECT_PUSHED_ATTN 0x81
-
-/* Audio attention group */
-#define SONY_AUDIO_PLAY_DONE_ATTN 0x90
-#define SONY_LEAD_IN_ERR_ATTN 0x91
-#define SONY_LEAD_OUT_ERR_ATTN 0x92
-#define SONY_DATA_TRACK_ERR_ATTN 0x93
-#define SONY_AUDIO_PLAYBACK_ERR_ATTN 0x94
-
-/* Auto spin up group */
-#define SONY_SPIN_UP_COMPLETE_ATTN 0x24
-#define SONY_SPINDLE_SERVO_ERR_ATTN 0x25
-#define SONY_FOCUS_SERVO_ERR_ATTN 0x26
-#define SONY_TOC_READ_DONE_ATTN 0x62
-#define SONY_FOCUS_ON_TOC_READ_ERR_ATTN 0x63
-#define SONY_SYNC_ON_TOC_READ_ERR_ATTN 0x65
-
-/* Auto eject group */
-#define SONY_SPIN_DOWN_COMPLETE_ATTN 0x27
-#define SONY_EJECT_COMPLETE_ATTN 0x28
-#define SONY_EJECT_MECH_ERR_ATTN 0x29
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
deleted file mode 100644
index 23013116324..00000000000
--- a/drivers/cdrom/cm206.c
+++ /dev/null
@@ -1,1594 +0,0 @@
-/* cm206.c. A linux-driver for the cm206 cdrom player with cm260 adapter card.
- Copyright (c) 1995--1997 David A. van Leeuwen.
- $Id: cm206.c,v 1.5 1997/12/26 11:02:51 david Exp $
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the 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.
-
-History:
- Started 25 jan 1994. Waiting for documentation...
- 22 feb 1995: 0.1a first reasonably safe polling driver.
- Two major bugs, one in read_sector and one in
- do_cm206_request, happened to cancel!
- 25 feb 1995: 0.2a first reasonable interrupt driven version of above.
- uart writes are still done in polling mode.
- 25 feb 1995: 0.21a writes also in interrupt mode, still some
- small bugs to be found... Larger buffer.
- 2 mrt 1995: 0.22 Bug found (cd-> nowhere, interrupt was called in
- initialization), read_ahead of 16. Timeouts implemented.
- unclear if they do something...
- 7 mrt 1995: 0.23 Start of background read-ahead.
- 18 mrt 1995: 0.24 Working background read-ahead. (still problems)
- 26 mrt 1995: 0.25 Multi-session ioctl added (kernel v1.2).
- Statistics implemented, though separate stats206.h.
- Accessible through ioctl 0x1000 (just a number).
- Hard to choose between v1.2 development and 1.1.75.
- Bottom-half doesn't work with 1.2...
- 0.25a: fixed... typo. Still problems...
- 1 apr 1995: 0.26 Module support added. Most bugs found. Use kernel 1.2.n.
- 5 apr 1995: 0.27 Auto-probe for the adapter card base address.
- Auto-probe for the adaptor card irq line.
- 7 apr 1995: 0.28 Added lilo setup support for base address and irq.
- Use major number 32 (not in this source), officially
- assigned to this driver.
- 9 apr 1995: 0.29 Added very limited audio support. Toc_header, stop, pause,
- resume, eject. Play_track ignores track info, because we can't
- read a table-of-contents entry. Toc_entry is implemented
- as a `placebo' function: always returns start of disc.
- 3 may 1995: 0.30 Audio support completed. The get_toc_entry function
- is implemented as a binary search.
- 15 may 1995: 0.31 More work on audio stuff. Workman is not easy to
- satisfy; changed binary search into linear search.
- Auto-probe for base address somewhat relaxed.
- 1 jun 1995: 0.32 Removed probe_irq_on/off for module version.
- 10 jun 1995: 0.33 Workman still behaves funny, but you should be
- able to eject and substitute another disc.
-
- An adaptation of 0.33 is included in linux-1.3.7 by Eberhard Moenkeberg
-
- 18 jul 1995: 0.34 Patch by Heiko Eissfeldt included, mainly considering
- verify_area's in the ioctls. Some bugs introduced by
- EM considering the base port and irq fixed.
-
- 18 dec 1995: 0.35 Add some code for error checking... no luck...
-
- We jump to reach our goal: version 1.0 in the next stable linux kernel.
-
- 19 mar 1996: 0.95 Different implementation of CDROM_GET_UPC, on
- request of Thomas Quinot.
- 25 mar 1996: 0.96 Interpretation of opening with O_WRONLY or O_RDWR:
- open only for ioctl operation, e.g., for operation of
- tray etc.
- 4 apr 1996: 0.97 First implementation of layer between VFS and cdrom
- driver, a generic interface. Much of the functionality
- of cm206_open() and cm206_ioctl() is transferred to a
- new file cdrom.c and its header ucdrom.h.
-
- Upgrade to Linux kernel 1.3.78.
-
- 11 apr 1996 0.98 Upgrade to Linux kernel 1.3.85
- More code moved to cdrom.c
-
- 0.99 Some more small changes to decrease number
- of oopses at module load;
-
- 27 jul 1996 0.100 Many hours of debugging, kernel change from 1.2.13
- to 2.0.7 seems to have introduced some weird behavior
- in (interruptible_)sleep_on(&cd->data): the process
- seems to be woken without any explicit wake_up in my own
- code. Patch to try 100x in case such untriggered wake_up's
- occur.
-
- 28 jul 1996 0.101 Rewriting of the code that receives the command echo,
- using a fifo to store echoed bytes.
-
- Branch from 0.99:
-
- 0.99.1.0 Update to kernel release 2.0.10 dev_t -> kdev_t
- (emoenke) various typos found by others. extra
- module-load oops protection.
-
- 0.99.1.1 Initialization constant cdrom_dops.speed
- changed from float (2.0) to int (2); Cli()-sti() pair
- around cm260_reset() in module initialization code.
-
- 0.99.1.2 Changes literally as proposed by Scott Snyder
- <snyder@d0sgif.fnal.gov> for the 2.1 kernel line, which
- have to do mainly with the poor minor support i had. The
- major new concept is to change a cdrom driver's
- operations struct from the capabilities struct. This
- reflects the fact that there is one major for a driver,
- whilst there can be many minors whith completely
- different capabilities.
-
- 0.99.1.3 More changes for operations/info separation.
-
- 0.99.1.4 Added speed selection (someone had to do this
- first).
-
- 23 jan 1997 0.99.1.5 MODULE_PARMS call added.
-
- 23 jan 1997 0.100.1.2--0.100.1.5 following similar lines as
- 0.99.1.1--0.99.1.5. I get too many complaints about the
- drive making read errors. What't wrong with the 2.0+
- kernel line? Why get i (and othe cm206 owners) weird
- results? Why were things good in the good old 1.1--1.2
- era? Why don't i throw away the drive?
-
- 2 feb 1997 0.102 Added `volatile' to values in cm206_struct. Seems to
- reduce many of the problems. Rewrote polling routines
- to use fixed delays between polls.
- 0.103 Changed printk behavior.
- 0.104 Added a 0.100 -> 0.100.1.1 change
-
-11 feb 1997 0.105 Allow auto_probe during module load, disable
- with module option "auto_probe=0". Moved some debugging
- statements to lower priority. Implemented select_speed()
- function.
-
-13 feb 1997 1.0 Final version for 2.0 kernel line.
-
- All following changes will be for the 2.1 kernel line.
-
-15 feb 1997 1.1 Keep up with kernel 2.1.26, merge in changes from
- cdrom.c 0.100.1.1--1.0. Add some more MODULE_PARMS.
-
-14 sep 1997 1.2 Upgrade to Linux 2.1.55. Added blksize_size[], patch
- sent by James Bottomley <James.Bottomley@columbiasc.ncr.com>.
-
-21 dec 1997 1.4 Upgrade to Linux 2.1.72.
-
-24 jan 1998 Removed the cm206_disc_status() function, as it was now dead
- code. The Uniform CDROM driver now provides this functionality.
-
-9 Nov. 1999 Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
- *
- * Parts of the code are based upon lmscd.c written by Kai Petzke,
- * sbpcd.c written by Eberhard Moenkeberg, and mcd.c by Martin
- * Harriss, but any off-the-shelf dynamic programming algorithm won't
- * be able to find them.
- *
- * The cm206 drive interface and the cm260 adapter card seem to be
- * sufficiently different from their cm205/cm250 counterparts
- * in order to write a complete new driver.
- *
- * I call all routines connected to the Linux kernel something
- * with `cm206' in it, as this stuff is too series-dependent.
- *
- * Currently, my limited knowledge is based on:
- * - The Linux Kernel Hacker's guide, v. 0.5, by Michael K. Johnson
- * - Linux Kernel Programmierung, by Michael Beck and others
- * - Philips/LMS cm206 and cm226 product specification
- * - Philips/LMS cm260 product specification
- *
- * David van Leeuwen, david@tm.tno.nl. */
-#define REVISION "$Revision: 1.5 $"
-
-#include <linux/module.h>
-
-#include <linux/errno.h> /* These include what we really need */
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-/* #include <linux/ucdrom.h> */
-
-#include <asm/io.h>
-
-#define MAJOR_NR CM206_CDROM_MAJOR
-
-#include <linux/blkdev.h>
-
-#undef DEBUG
-#define STATISTICS /* record times and frequencies of events */
-#define AUTO_PROBE_MODULE
-#define USE_INSW
-
-#include "cm206.h"
-
-/* This variable defines whether or not to probe for adapter base port
- address and interrupt request. It can be overridden by the boot
- parameter `auto'.
-*/
-static int auto_probe = 1; /* Yes, why not? */
-
-static int cm206_base = CM206_BASE;
-static int cm206_irq = CM206_IRQ;
-#ifdef MODULE
-static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */
-module_param_array(cm206, int, NULL, 0); /* base,irq or irq,base */
-#endif
-
-module_param(cm206_base, int, 0); /* base */
-module_param(cm206_irq, int, 0); /* irq */
-module_param(auto_probe, bool, 0); /* auto probe base and irq */
-MODULE_LICENSE("GPL");
-
-#define POLLOOP 100 /* milliseconds */
-#define READ_AHEAD 1 /* defines private buffer, waste! */
-#define BACK_AHEAD 1 /* defines adapter-read ahead */
-#define DATA_TIMEOUT (3*HZ) /* measured in jiffies (10 ms) */
-#define UART_TIMEOUT (5*HZ/100)
-#define DSB_TIMEOUT (7*HZ) /* time for the slowest command to finish */
-#define UR_SIZE 4 /* uart receive buffer fifo size */
-
-#define LINUX_BLOCK_SIZE 512 /* WHERE is this defined? */
-#define RAW_SECTOR_SIZE 2352 /* ok, is also defined in cdrom.h */
-#define ISO_SECTOR_SIZE 2048
-#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE) /* 4 */
-#define CD_SYNC_HEAD 16 /* CD_SYNC + CD_HEAD */
-
-#ifdef STATISTICS /* keep track of errors in counters */
-#define stats(i) { ++cd->stats[st_ ## i]; \
- cd->last_stat[st_ ## i] = cd->stat_counter++; \
- }
-#else
-#define stats(i) (void) 0;
-#endif
-
-#define Debug(a) {printk (KERN_DEBUG); printk a;}
-#ifdef DEBUG
-#define debug(a) Debug(a)
-#else
-#define debug(a) (void) 0;
-#endif
-
-typedef unsigned char uch; /* 8-bits */
-typedef unsigned short ush; /* 16-bits */
-
-struct toc_struct { /* private copy of Table of Contents */
- uch track, fsm[3], q0;
-};
-
-struct cm206_struct {
- volatile ush intr_ds; /* data status read on last interrupt */
- volatile ush intr_ls; /* uart line status read on last interrupt */
- volatile uch ur[UR_SIZE]; /* uart receive buffer fifo */
- volatile uch ur_w, ur_r; /* write/read buffer index */
- volatile uch dsb, cc; /* drive status byte and condition (error) code */
- int command; /* command to be written to the uart */
- int openfiles;
- ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2]; /* buffered cd-sector */
- int sector_first, sector_last; /* range of these sectors */
- wait_queue_head_t uart; /* wait queues for interrupt */
- wait_queue_head_t data;
- struct timer_list timer; /* time-out */
- char timed_out;
- signed char max_sectors; /* number of sectors that fit in adapter mem */
- char wait_back; /* we're waiting for a background-read */
- char background; /* is a read going on in the background? */
- int adapter_first; /* if so, that's the starting sector */
- int adapter_last;
- char fifo_overflowed;
- uch disc_status[7]; /* result of get_disc_status command */
-#ifdef STATISTICS
- int stats[NR_STATS];
- int last_stat[NR_STATS]; /* `time' at which stat was stat */
- int stat_counter;
-#endif
- struct toc_struct toc[101]; /* The whole table of contents + lead-out */
- uch q[10]; /* Last read q-channel info */
- uch audio_status[5]; /* last read position on pause */
- uch media_changed; /* record if media changed */
-};
-
-#define DISC_STATUS cd->disc_status[0]
-#define FIRST_TRACK cd->disc_status[1]
-#define LAST_TRACK cd->disc_status[2]
-#define PAUSED cd->audio_status[0] /* misuse this memory byte! */
-#define PLAY_TO cd->toc[0] /* toc[0] records end-time in play */
-
-static struct cm206_struct *cd; /* the main memory structure */
-static struct request_queue *cm206_queue;
-static DEFINE_SPINLOCK(cm206_lock);
-
-/* First, we define some polling functions. These are actually
- only being used in the initialization. */
-
-static void send_command_polled(int command)
-{
- int loop = POLLOOP;
- while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
- && loop > 0) {
- mdelay(1); /* one millisec delay */
- --loop;
- }
- outw(command, r_uart_transmit);
-}
-
-static uch receive_echo_polled(void)
-{
- int loop = POLLOOP;
- while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
- mdelay(1);
- --loop;
- }
- return ((uch) inw(r_uart_receive));
-}
-
-static uch send_receive_polled(int command)
-{
- send_command_polled(command);
- return receive_echo_polled();
-}
-
-static inline void clear_ur(void)
-{
- if (cd->ur_r != cd->ur_w) {
- debug(("Deleting bytes from fifo:"));
- for (; cd->ur_r != cd->ur_w;
- cd->ur_r++, cd->ur_r %= UR_SIZE)
- debug((" 0x%x", cd->ur[cd->ur_r]));
- debug(("\n"));
- }
-}
-
-static struct tasklet_struct cm206_tasklet;
-
-/* The interrupt handler. When the cm260 generates an interrupt, very
- much care has to be taken in reading out the registers in the right
- order; in case of a receive_buffer_full interrupt, first the
- uart_receive must be read, and then the line status again to
- de-assert the interrupt line. It took me a couple of hours to find
- this out:-(
-
- The function reset_cm206 appears to cause an interrupt, because
- pulling up the INIT line clears both the uart-write-buffer /and/
- the uart-write-buffer-empty mask. We call this a `lost interrupt,'
- as there seems so reason for this to happen.
-*/
-
-static irqreturn_t cm206_interrupt(int sig, void *dev_id)
-{
- volatile ush fool;
- cd->intr_ds = inw(r_data_status); /* resets data_ready, data_error,
- crc_error, sync_error, toc_ready
- interrupts */
- cd->intr_ls = inw(r_line_status); /* resets overrun bit */
- debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
- cd->background));
- if (cd->intr_ls & ls_attention)
- stats(attention);
- /* receive buffer full? */
- if (cd->intr_ls & ls_receive_buffer_full) {
- cd->ur[cd->ur_w] = inb(r_uart_receive); /* get order right! */
- cd->intr_ls = inw(r_line_status); /* resets rbf interrupt */
- debug(("receiving #%d: 0x%x\n", cd->ur_w,
- cd->ur[cd->ur_w]));
- cd->ur_w++;
- cd->ur_w %= UR_SIZE;
- if (cd->ur_w == cd->ur_r)
- debug(("cd->ur overflow!\n"));
- if (waitqueue_active(&cd->uart) && cd->background < 2) {
- del_timer(&cd->timer);
- wake_up_interruptible(&cd->uart);
- }
- }
- /* data ready in fifo? */
- else if (cd->intr_ds & ds_data_ready) {
- if (cd->background)
- ++cd->adapter_last;
- if (waitqueue_active(&cd->data)
- && (cd->wait_back || !cd->background)) {
- del_timer(&cd->timer);
- wake_up_interruptible(&cd->data);
- }
- stats(data_ready);
- }
- /* ready to issue a write command? */
- else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
- outw(dc_normal | (inw(r_data_status) & 0x7f),
- r_data_control);
- outw(cd->command, r_uart_transmit);
- cd->command = 0;
- if (!cd->background)
- wake_up_interruptible(&cd->uart);
- }
- /* now treat errors (at least, identify them for debugging) */
- else if (cd->intr_ds & ds_fifo_overflow) {
- debug(("Fifo overflow at sectors 0x%x\n",
- cd->sector_first));
- fool = inw(r_fifo_output_buffer); /* de-assert the interrupt */
- cd->fifo_overflowed = 1; /* signal one word less should be read */
- stats(fifo_overflow);
- } else if (cd->intr_ds & ds_data_error) {
- debug(("Data error at sector 0x%x\n", cd->sector_first));
- stats(data_error);
- } else if (cd->intr_ds & ds_crc_error) {
- debug(("CRC error at sector 0x%x\n", cd->sector_first));
- stats(crc_error);
- } else if (cd->intr_ds & ds_sync_error) {
- debug(("Sync at sector 0x%x\n", cd->sector_first));
- stats(sync_error);
- } else if (cd->intr_ds & ds_toc_ready) {
- /* do something appropriate */
- }
- /* couldn't see why this interrupt, maybe due to init */
- else {
- outw(dc_normal | READ_AHEAD, r_data_control);
- stats(lost_intr);
- }
- if (cd->background
- && (cd->adapter_last - cd->adapter_first == cd->max_sectors
- || cd->fifo_overflowed))
- tasklet_schedule(&cm206_tasklet); /* issue a stop read command */
- stats(interrupt);
- return IRQ_HANDLED;
-}
-
-/* we have put the address of the wait queue in who */
-static void cm206_timeout(unsigned long who)
-{
- cd->timed_out = 1;
- debug(("Timing out\n"));
- wake_up_interruptible((wait_queue_head_t *) who);
-}
-
-/* This function returns 1 if a timeout occurred, 0 if an interrupt
- happened */
-static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
-{
- cd->timed_out = 0;
- init_timer(&cd->timer);
- cd->timer.data = (unsigned long) wait;
- cd->timer.expires = jiffies + timeout;
- add_timer(&cd->timer);
- debug(("going to sleep\n"));
- interruptible_sleep_on(wait);
- del_timer(&cd->timer);
- if (cd->timed_out) {
- cd->timed_out = 0;
- return 1;
- } else
- return 0;
-}
-
-static void send_command(int command)
-{
- debug(("Sending 0x%x\n", command));
- if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
- cd->command = command;
- cli(); /* don't interrupt before sleep */
- outw(dc_mask_sync_error | dc_no_stop_on_error |
- (inw(r_data_status) & 0x7f), r_data_control);
- /* interrupt routine sends command */
- if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
- debug(("Time out on write-buffer\n"));
- stats(write_timeout);
- outw(command, r_uart_transmit);
- }
- debug(("Write commmand delayed\n"));
- } else
- outw(command, r_uart_transmit);
-}
-
-static uch receive_byte(int timeout)
-{
- uch ret;
- cli();
- debug(("cli\n"));
- ret = cd->ur[cd->ur_r];
- if (cd->ur_r != cd->ur_w) {
- sti();
- debug(("returning #%d: 0x%x\n", cd->ur_r,
- cd->ur[cd->ur_r]));
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- return ret;
- } else if (sleep_or_timeout(&cd->uart, timeout)) { /* does sti() */
- debug(("Time out on receive-buffer\n"));
-#ifdef STATISTICS
- if (timeout == UART_TIMEOUT)
- stats(receive_timeout) /* no `;'! */
- else
- stats(dsb_timeout);
-#endif
- return 0xda;
- }
- ret = cd->ur[cd->ur_r];
- debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
- cd->ur[cd->ur_r]));
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- return ret;
-}
-
-static inline uch receive_echo(void)
-{
- return receive_byte(UART_TIMEOUT);
-}
-
-static inline uch send_receive(int command)
-{
- send_command(command);
- return receive_echo();
-}
-
-static inline uch wait_dsb(void)
-{
- return receive_byte(DSB_TIMEOUT);
-}
-
-static int type_0_command(int command, int expect_dsb)
-{
- int e;
- clear_ur();
- if (command != (e = send_receive(command))) {
- debug(("command 0x%x echoed as 0x%x\n", command, e));
- stats(echo);
- return -1;
- }
- if (expect_dsb) {
- cd->dsb = wait_dsb(); /* wait for command to finish */
- }
- return 0;
-}
-
-static int type_1_command(int command, int bytes, uch * status)
-{ /* returns info */
- int i;
- if (type_0_command(command, 0))
- return -1;
- for (i = 0; i < bytes; i++)
- status[i] = send_receive(c_gimme);
- return 0;
-}
-
-/* This function resets the adapter card. We'd better not do this too
- * often, because it tends to generate `lost interrupts.' */
-static void reset_cm260(void)
-{
- outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
- udelay(10); /* 3.3 mu sec minimum */
- outw(dc_normal | READ_AHEAD, r_data_control);
-}
-
-/* fsm: frame-sec-min from linear address; one of many */
-static void fsm(int lba, uch * fsm)
-{
- fsm[0] = lba % 75;
- lba /= 75;
- lba += 2;
- fsm[1] = lba % 60;
- fsm[2] = lba / 60;
-}
-
-static inline int fsm2lba(uch * fsm)
-{
- return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
-}
-
-static inline int f_s_m2lba(uch f, uch s, uch m)
-{
- return f + 75 * (s - 2 + 60 * m);
-}
-
-static int start_read(int start)
-{
- uch read_sector[4] = { c_read_data, };
- int i, e;
-
- fsm(start, &read_sector[1]);
- clear_ur();
- for (i = 0; i < 4; i++)
- if (read_sector[i] != (e = send_receive(read_sector[i]))) {
- debug(("read_sector: %x echoes %x\n",
- read_sector[i], e));
- stats(echo);
- if (e == 0xff) { /* this seems to happen often */
- e = receive_echo();
- debug(("Second try %x\n", e));
- if (e != read_sector[i])
- return -1;
- }
- }
- return 0;
-}
-
-static int stop_read(void)
-{
- int e;
- type_0_command(c_stop, 0);
- if ((e = receive_echo()) != 0xff) {
- debug(("c_stop didn't send 0xff, but 0x%x\n", e));
- stats(stop_0xff);
- return -1;
- }
- return 0;
-}
-
-/* This function starts to read sectors in adapter memory, the
- interrupt routine should stop the read. In fact, the bottom_half
- routine takes care of this. Set a flag `background' in the cd
- struct to indicate the process. */
-
-static int read_background(int start, int reading)
-{
- if (cd->background)
- return -1; /* can't do twice */
- outw(dc_normal | BACK_AHEAD, r_data_control);
- if (!reading && start_read(start))
- return -2;
- cd->adapter_first = cd->adapter_last = start;
- cd->background = 1; /* flag a read is going on */
- return 0;
-}
-
-#ifdef USE_INSW
-#define transport_data insw
-#else
-/* this routine implements insw(,,). There was a time i had the
- impression that there would be any difference in error-behaviour. */
-void transport_data(int port, ush * dest, int count)
-{
- int i;
- ush *d;
- for (i = 0, d = dest; i < count; i++, d++)
- *d = inw(port);
-}
-#endif
-
-
-#define MAX_TRIES 100
-static int read_sector(int start)
-{
- int tries = 0;
- if (cd->background) {
- cd->background = 0;
- cd->adapter_last = -1; /* invalidate adapter memory */
- stop_read();
- }
- cd->fifo_overflowed = 0;
- reset_cm260(); /* empty fifo etc. */
- if (start_read(start))
- return -1;
- do {
- if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
- debug(("Read timed out sector 0x%x\n", start));
- stats(read_timeout);
- stop_read();
- return -3;
- }
- tries++;
- } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
- if (tries > 1)
- debug(("Took me some tries\n"))
- else
- if (tries == MAX_TRIES)
- debug(("MAX_TRIES tries for read sector\n"));
- transport_data(r_fifo_output_buffer, cd->sector,
- READ_AHEAD * RAW_SECTOR_SIZE / 2);
- if (read_background(start + READ_AHEAD, 1))
- stats(read_background);
- cd->sector_first = start;
- cd->sector_last = start + READ_AHEAD;
- stats(read_restarted);
- return 0;
-}
-
-/* The function of bottom-half is to send a stop command to the drive
- This isn't easy because the routine is not `owned' by any process;
- we can't go to sleep! The variable cd->background gives the status:
- 0 no read pending
- 1 a read is pending
- 2 c_stop waits for write_buffer_empty
- 3 c_stop waits for receive_buffer_full: echo
- 4 c_stop waits for receive_buffer_full: 0xff
-*/
-
-static void cm206_tasklet_func(unsigned long ignore)
-{
- debug(("bh: %d\n", cd->background));
- switch (cd->background) {
- case 1:
- stats(bh);
- if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
- cd->command = c_stop;
- outw(dc_mask_sync_error | dc_no_stop_on_error |
- (inw(r_data_status) & 0x7f), r_data_control);
- cd->background = 2;
- break; /* we'd better not time-out here! */
- } else
- outw(c_stop, r_uart_transmit);
- /* fall into case 2: */
- case 2:
- /* the write has been satisfied by interrupt routine */
- cd->background = 3;
- break;
- case 3:
- if (cd->ur_r != cd->ur_w) {
- if (cd->ur[cd->ur_r] != c_stop) {
- debug(("cm206_bh: c_stop echoed 0x%x\n",
- cd->ur[cd->ur_r]));
- stats(echo);
- }
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- }
- cd->background++;
- break;
- case 4:
- if (cd->ur_r != cd->ur_w) {
- if (cd->ur[cd->ur_r] != 0xff) {
- debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
- stats(stop_0xff);
- }
- cd->ur_r++;
- cd->ur_r %= UR_SIZE;
- }
- cd->background = 0;
- }
-}
-
-static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
-
-/* This command clears the dsb_possible_media_change flag, so we must
- * retain it.
- */
-static void get_drive_status(void)
-{
- uch status[2];
- type_1_command(c_drive_status, 2, status); /* this might be done faster */
- cd->dsb = status[0];
- cd->cc = status[1];
- cd->media_changed |=
- !!(cd->dsb & (dsb_possible_media_change |
- dsb_drive_not_ready | dsb_tray_not_closed));
-}
-
-static void get_disc_status(void)
-{
- if (type_1_command(c_disc_status, 7, cd->disc_status)) {
- debug(("get_disc_status: error\n"));
- }
-}
-
-/* The new open. The real opening strategy is defined in cdrom.c. */
-
-static int cm206_open(struct cdrom_device_info *cdi, int purpose)
-{
- if (!cd->openfiles) { /* reset only first time */
- cd->background = 0;
- reset_cm260();
- cd->adapter_last = -1; /* invalidate adapter memory */
- cd->sector_last = -1;
- }
- ++cd->openfiles;
- stats(open);
- return 0;
-}
-
-static void cm206_release(struct cdrom_device_info *cdi)
-{
- if (cd->openfiles == 1) {
- if (cd->background) {
- cd->background = 0;
- stop_read();
- }
- cd->sector_last = -1; /* Make our internal buffer invalid */
- FIRST_TRACK = 0; /* No valid disc status */
- }
- --cd->openfiles;
-}
-
-/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
- * and then reads a sector in kernel memory. */
-static void empty_buffer(int sectors)
-{
- while (sectors >= 0) {
- transport_data(r_fifo_output_buffer,
- cd->sector + cd->fifo_overflowed,
- RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
- --sectors;
- ++cd->adapter_first; /* update the current adapter sector */
- cd->fifo_overflowed = 0; /* reset overflow bit */
- stats(sector_transferred);
- }
- cd->sector_first = cd->adapter_first - 1;
- cd->sector_last = cd->adapter_first; /* update the buffer sector */
-}
-
-/* try_adapter. This function determines if the requested sector is
- in adapter memory, or will appear there soon. Returns 0 upon
- success */
-static int try_adapter(int sector)
-{
- if (cd->adapter_first <= sector && sector < cd->adapter_last) {
- /* sector is in adapter memory */
- empty_buffer(sector - cd->adapter_first);
- return 0;
- } else if (cd->background == 1 && cd->adapter_first <= sector
- && sector < cd->adapter_first + cd->max_sectors) {
- /* a read is going on, we can wait for it */
- cd->wait_back = 1;
- while (sector >= cd->adapter_last) {
- if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
- debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
- stats(back_read_timeout);
- cd->wait_back = 0;
- return -1;
- }
- }
- cd->wait_back = 0;
- empty_buffer(sector - cd->adapter_first);
- return 0;
- } else
- return -2;
-}
-
-/* This is not a very smart implementation. We could optimize for
- consecutive block numbers. I'm not convinced this would really
- bring down the processor load. */
-static void do_cm206_request(request_queue_t * q)
-{
- long int i, cd_sec_no;
- int quarter, error;
- uch *source, *dest;
- struct request *req;
-
- while (1) { /* repeat until all requests have been satisfied */
- req = elv_next_request(q);
- if (!req)
- return;
-
- if (req->cmd != READ) {
- debug(("Non-read command %d on cdrom\n", req->cmd));
- end_request(req, 0);
- continue;
- }
- spin_unlock_irq(q->queue_lock);
- error = 0;
- for (i = 0; i < req->nr_sectors; i++) {
- int e1, e2;
- cd_sec_no = (req->sector + i) / BLOCKS_ISO; /* 4 times 512 bytes */
- quarter = (req->sector + i) % BLOCKS_ISO;
- dest = req->buffer + i * LINUX_BLOCK_SIZE;
- /* is already in buffer memory? */
- if (cd->sector_first <= cd_sec_no
- && cd_sec_no < cd->sector_last) {
- source =
- ((uch *) cd->sector) + 16 +
- quarter * LINUX_BLOCK_SIZE +
- (cd_sec_no -
- cd->sector_first) * RAW_SECTOR_SIZE;
- memcpy(dest, source, LINUX_BLOCK_SIZE);
- } else if (!(e1 = try_adapter(cd_sec_no)) ||
- !(e2 = read_sector(cd_sec_no))) {
- source =
- ((uch *) cd->sector) + 16 +
- quarter * LINUX_BLOCK_SIZE;
- memcpy(dest, source, LINUX_BLOCK_SIZE);
- } else {
- error = 1;
- debug(("cm206_request: %d %d\n", e1, e2));
- }
- }
- spin_lock_irq(q->queue_lock);
- end_request(req, !error);
- }
-}
-
-/* Audio support. I've tried very hard, but the cm206 drive doesn't
- seem to have a get_toc (table-of-contents) function, while i'm
- pretty sure it must read the toc upon disc insertion. Therefore
- this function has been implemented through a binary search
- strategy. All track starts that happen to be found are stored in
- cd->toc[], for future use.
-
- I've spent a whole day on a bug that only shows under Workman---
- I don't get it. Tried everything, nothing works. If workman asks
- for track# 0xaa, it'll get the wrong time back. Any other program
- receives the correct value. I'm stymied.
-*/
-
-/* seek seeks to address lba. It does wait to arrive there. */
-static void seek(int lba)
-{
- int i;
- uch seek_command[4] = { c_seek, };
-
- fsm(lba, &seek_command[1]);
- for (i = 0; i < 4; i++)
- type_0_command(seek_command[i], 0);
- cd->dsb = wait_dsb();
-}
-
-static uch bcdbin(unsigned char bcd)
-{ /* stolen from mcd.c! */
- return (bcd >> 4) * 10 + (bcd & 0xf);
-}
-
-static inline uch normalize_track(uch track)
-{
- if (track < 1)
- return 1;
- if (track > LAST_TRACK)
- return LAST_TRACK + 1;
- return track;
-}
-
-/* This function does a binary search for track start. It records all
- * tracks seen in the process. Input $track$ must be between 1 and
- * #-of-tracks+1. Note that the start of the disc must be in toc[1].fsm.
- */
-static int get_toc_lba(uch track)
-{
- int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
- int i, lba, l, old_lba = 0;
- uch *q = cd->q;
- uch ct; /* current track */
- int binary = 0;
- const int skip = 3 * 60 * 75; /* 3 minutes */
-
- for (i = track; i > 0; i--)
- if (cd->toc[i].track) {
- min = fsm2lba(cd->toc[i].fsm);
- break;
- }
- lba = min + skip;
- do {
- seek(lba);
- type_1_command(c_read_current_q, 10, q);
- ct = normalize_track(q[1]);
- if (!cd->toc[ct].track) {
- l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
- bcdbin(q[4]) - 2 +
- 60 * (q[7] -
- bcdbin(q
- [3])));
- cd->toc[ct].track = q[1]; /* lead out still 0xaa */
- fsm(l, cd->toc[ct].fsm);
- cd->toc[ct].q0 = q[0]; /* contains adr and ctrl info */
- if (ct == track)
- return l;
- }
- old_lba = lba;
- if (binary) {
- if (ct < track)
- min = lba;
- else
- max = lba;
- lba = (min + max) / 2;
- } else {
- if (ct < track)
- lba += skip;
- else {
- binary = 1;
- max = lba;
- min = lba - skip;
- lba = (min + max) / 2;
- }
- }
- } while (lba != old_lba);
- return lba;
-}
-
-static void update_toc_entry(uch track)
-{
- track = normalize_track(track);
- if (!cd->toc[track].track)
- get_toc_lba(track);
-}
-
-/* return 0 upon success */
-static int read_toc_header(struct cdrom_tochdr *hp)
-{
- if (!FIRST_TRACK)
- get_disc_status();
- if (hp) {
- int i;
- hp->cdth_trk0 = FIRST_TRACK;
- hp->cdth_trk1 = LAST_TRACK;
- /* fill in first track position */
- for (i = 0; i < 3; i++)
- cd->toc[1].fsm[i] = cd->disc_status[3 + i];
- update_toc_entry(LAST_TRACK + 1); /* find most entries */
- return 0;
- }
- return -1;
-}
-
-static void play_from_to_msf(struct cdrom_msf *msfp)
-{
- uch play_command[] = { c_play,
- msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
- msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
- 2
- };
- int i;
- for (i = 0; i < 9; i++)
- type_0_command(play_command[i], 0);
- for (i = 0; i < 3; i++)
- PLAY_TO.fsm[i] = play_command[i + 4];
- PLAY_TO.track = 0; /* say no track end */
- cd->dsb = wait_dsb();
-}
-
-static void play_from_to_track(int from, int to)
-{
- uch play_command[8] = { c_play, };
- int i;
-
- if (from == 0) { /* continue paused play */
- for (i = 0; i < 3; i++) {
- play_command[i + 1] = cd->audio_status[i + 2];
- play_command[i + 4] = PLAY_TO.fsm[i];
- }
- } else {
- update_toc_entry(from);
- update_toc_entry(to + 1);
- for (i = 0; i < 3; i++) {
- play_command[i + 1] = cd->toc[from].fsm[i];
- PLAY_TO.fsm[i] = play_command[i + 4] =
- cd->toc[to + 1].fsm[i];
- }
- PLAY_TO.track = to;
- }
- for (i = 0; i < 7; i++)
- type_0_command(play_command[i], 0);
- for (i = 0; i < 2; i++)
- type_0_command(0x2, 0); /* volume */
- cd->dsb = wait_dsb();
-}
-
-static int get_current_q(struct cdrom_subchnl *qp)
-{
- int i;
- uch *q = cd->q;
- if (type_1_command(c_read_current_q, 10, q))
- return 0;
-/* q[0] = bcdbin(q[0]); Don't think so! */
- for (i = 2; i < 6; i++)
- q[i] = bcdbin(q[i]);
- qp->cdsc_adr = q[0] & 0xf;
- qp->cdsc_ctrl = q[0] >> 4; /* from mcd.c */
- qp->cdsc_trk = q[1];
- qp->cdsc_ind = q[2];
- if (qp->cdsc_format == CDROM_MSF) {
- qp->cdsc_reladdr.msf.minute = q[3];
- qp->cdsc_reladdr.msf.second = q[4];
- qp->cdsc_reladdr.msf.frame = q[5];
- qp->cdsc_absaddr.msf.minute = q[7];
- qp->cdsc_absaddr.msf.second = q[8];
- qp->cdsc_absaddr.msf.frame = q[9];
- } else {
- qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
- qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
- }
- get_drive_status();
- if (cd->dsb & dsb_play_in_progress)
- qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
- else if (PAUSED)
- qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
- else
- qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
- return 0;
-}
-
-static void invalidate_toc(void)
-{
- memset(cd->toc, 0, sizeof(cd->toc));
- memset(cd->disc_status, 0, sizeof(cd->disc_status));
-}
-
-/* cdrom.c guarantees that cdte_format == CDROM_MSF */
-static void get_toc_entry(struct cdrom_tocentry *ep)
-{
- uch track = normalize_track(ep->cdte_track);
- update_toc_entry(track);
- ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
- ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
- ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
- ep->cdte_adr = cd->toc[track].q0 & 0xf;
- ep->cdte_ctrl = cd->toc[track].q0 >> 4;
- ep->cdte_datamode = 0;
-}
-
-/* Audio ioctl. Ioctl commands connected to audio are in such an
- * idiosyncratic i/o format, that we leave these untouched. Return 0
- * upon success. Memory checking has been done by cdrom_ioctl(), the
- * calling function, as well as LBA/MSF sanitization.
-*/
-static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg)
-{
- switch (cmd) {
- case CDROMREADTOCHDR:
- return read_toc_header((struct cdrom_tochdr *) arg);
- case CDROMREADTOCENTRY:
- get_toc_entry((struct cdrom_tocentry *) arg);
- return 0;
- case CDROMPLAYMSF:
- play_from_to_msf((struct cdrom_msf *) arg);
- return 0;
- case CDROMPLAYTRKIND: /* admittedly, not particularly beautiful */
- play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
- ((struct cdrom_ti *) arg)->cdti_trk1);
- return 0;
- case CDROMSTOP:
- PAUSED = 0;
- if (cd->dsb & dsb_play_in_progress)
- return type_0_command(c_stop, 1);
- else
- return 0;
- case CDROMPAUSE:
- get_drive_status();
- if (cd->dsb & dsb_play_in_progress) {
- type_0_command(c_stop, 1);
- type_1_command(c_audio_status, 5,
- cd->audio_status);
- PAUSED = 1; /* say we're paused */
- }
- return 0;
- case CDROMRESUME:
- if (PAUSED)
- play_from_to_track(0, 0);
- PAUSED = 0;
- return 0;
- case CDROMSTART:
- case CDROMVOLCTRL:
- return 0;
- case CDROMSUBCHNL:
- return get_current_q((struct cdrom_subchnl *) arg);
- default:
- return -EINVAL;
- }
-}
-
-static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- if (cd != NULL) {
- int r;
- get_drive_status(); /* ensure cd->media_changed OK */
- r = cd->media_changed;
- cd->media_changed = 0; /* clear bit */
- return r;
- } else
- return -EIO;
-}
-
-/* The new generic cdrom support. Routines should be concise, most of
- the logic should be in cdrom.c */
-
-
-/* controls tray movement */
-static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
-{
- if (position) { /* 1: eject */
- type_0_command(c_open_tray, 1);
- invalidate_toc();
- } else
- type_0_command(c_close_tray, 1); /* 0: close */
- return 0;
-}
-
-/* gives current state of the drive */
-static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- get_drive_status();
- if (cd->dsb & dsb_tray_not_closed)
- return CDS_TRAY_OPEN;
- if (!(cd->dsb & dsb_disc_present))
- return CDS_NO_DISC;
- if (cd->dsb & dsb_drive_not_ready)
- return CDS_DRIVE_NOT_READY;
- return CDS_DISC_OK;
-}
-
-/* locks or unlocks door lock==1: lock; return 0 upon success */
-static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- uch command = (lock) ? c_lock_tray : c_unlock_tray;
- type_0_command(command, 1); /* wait and get dsb */
- /* the logic calculates the success, 0 means successful */
- return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
-}
-
-/* Although a session start should be in LBA format, we return it in
- MSF format because it is slightly easier, and the new generic ioctl
- will take care of the necessary conversion. */
-static int cm206_get_last_session(struct cdrom_device_info *cdi,
- struct cdrom_multisession *mssp)
-{
- if (!FIRST_TRACK)
- get_disc_status();
- if (mssp != NULL) {
- if (DISC_STATUS & cds_multi_session) { /* multi-session */
- mssp->addr.msf.frame = cd->disc_status[3];
- mssp->addr.msf.second = cd->disc_status[4];
- mssp->addr.msf.minute = cd->disc_status[5];
- mssp->addr_format = CDROM_MSF;
- mssp->xa_flag = 1;
- } else {
- mssp->xa_flag = 0;
- }
- return 1;
- }
- return 0;
-}
-
-static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- uch upc[10];
- char *ret = mcn->medium_catalog_number;
- int i;
-
- if (type_1_command(c_read_upc, 10, upc))
- return -EIO;
- for (i = 0; i < 13; i++) {
- int w = i / 2 + 1, r = i % 2;
- if (r)
- ret[i] = 0x30 | (upc[w] & 0x0f);
- else
- ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
- }
- ret[13] = '\0';
- return 0;
-}
-
-static int cm206_reset(struct cdrom_device_info *cdi)
-{
- stop_read();
- reset_cm260();
- outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
- mdelay(1); /* 750 musec minimum */
- outw(dc_normal | READ_AHEAD, r_data_control);
- cd->sector_last = -1; /* flag no data buffered */
- cd->adapter_last = -1;
- invalidate_toc();
- return 0;
-}
-
-static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- int r;
- switch (speed) {
- case 0:
- r = type_0_command(c_auto_mode, 1);
- break;
- case 1:
- r = type_0_command(c_force_1x, 1);
- break;
- case 2:
- r = type_0_command(c_force_2x, 1);
- break;
- default:
- return -1;
- }
- if (r < 0)
- return r;
- else
- return 1;
-}
-
-static struct cdrom_device_ops cm206_dops = {
- .open = cm206_open,
- .release = cm206_release,
- .drive_status = cm206_drive_status,
- .media_changed = cm206_media_changed,
- .tray_move = cm206_tray_move,
- .lock_door = cm206_lock_door,
- .select_speed = cm206_select_speed,
- .get_last_session = cm206_get_last_session,
- .get_mcn = cm206_get_upc,
- .reset = cm206_reset,
- .audio_ioctl = cm206_audio_ioctl,
- .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
- CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
- CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
- CDC_DRIVE_STATUS,
- .n_minors = 1,
-};
-
-
-static struct cdrom_device_info cm206_info = {
- .ops = &cm206_dops,
- .speed = 2,
- .capacity = 1,
- .name = "cm206",
-};
-
-static int cm206_block_open(struct inode *inode, struct file *file)
-{
- return cdrom_open(&cm206_info, inode, file);
-}
-
-static int cm206_block_release(struct inode *inode, struct file *file)
-{
- return cdrom_release(&cm206_info, file);
-}
-
-static int cm206_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- switch (cmd) {
-#ifdef STATISTICS
- case CM206CTL_GET_STAT:
- if (arg >= NR_STATS)
- return -EINVAL;
- return cd->stats[arg];
- case CM206CTL_GET_LAST_STAT:
- if (arg >= NR_STATS)
- return -EINVAL;
- return cd->last_stat[arg];
-#endif
- default:
- break;
- }
-
- return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
-}
-
-static int cm206_block_media_changed(struct gendisk *disk)
-{
- return cdrom_media_changed(&cm206_info);
-}
-
-static struct block_device_operations cm206_bdops =
-{
- .owner = THIS_MODULE,
- .open = cm206_block_open,
- .release = cm206_block_release,
- .ioctl = cm206_block_ioctl,
- .media_changed = cm206_block_media_changed,
-};
-
-static struct gendisk *cm206_gendisk;
-
-/* This function probes for the adapter card. It returns the base
- address if it has found the adapter card. One can specify a base
- port to probe specifically, or 0 which means span all possible
- bases.
-
- Linus says it is too dangerous to use writes for probing, so we
- stick with pure reads for a while. Hope that 8 possible ranges,
- request_region, 15 bits of one port and 6 of another make things
- likely enough to accept the region on the first hit...
- */
-static int __init probe_base_port(int base)
-{
- int b = 0x300, e = 0x370; /* this is the range of start addresses */
- volatile int fool, i;
-
- if (base)
- b = e = base;
- for (base = b; base <= e; base += 0x10) {
- if (!request_region(base, 0x10,"cm206"))
- continue;
- for (i = 0; i < 3; i++)
- fool = inw(base + 2); /* empty possibly uart_receive_buffer */
- if ((inw(base + 6) & 0xffef) != 0x0001 || /* line_status */
- (inw(base) & 0xad00) != 0) { /* data status */
- release_region(base,0x10);
- continue;
- }
- return (base);
- }
- return 0;
-}
-
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
-/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-static int __init probe_irq(int nr)
-{
- int irqs, irq;
- outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */
- sti();
- irqs = probe_irq_on();
- reset_cm260(); /* causes interrupt */
- udelay(100); /* wait for it */
- irq = probe_irq_off(irqs);
- outw(dc_normal | READ_AHEAD, r_data_control); /* services interrupt */
- if (nr && irq != nr && irq > 0)
- return 0; /* wrong interrupt happened */
- else
- return irq;
-}
-#endif
-
-int __init cm206_init(void)
-{
- uch e = 0;
- long int size = sizeof(struct cm206_struct);
- struct gendisk *disk;
-
- printk(KERN_INFO "cm206 cdrom driver " REVISION);
- cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
- if (!cm206_base) {
- printk(" can't find adapter!\n");
- return -EIO;
- }
- printk(" adapter at 0x%x", cm206_base);
- cd = kmalloc(size, GFP_KERNEL);
- if (!cd)
- goto out_base;
- /* Now we have found the adaptor card, try to reset it. As we have
- * found out earlier, this process generates an interrupt as well,
- * so we might just exploit that fact for irq probing! */
-#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
- cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
- if (cm206_irq <= 0) {
- printk("can't find IRQ!\n");
- goto out_probe;
- } else
- printk(" IRQ %d found\n", cm206_irq);
-#else
- cli();
- reset_cm260();
- /* Now, the problem here is that reset_cm260 can generate an
- interrupt. It seems that this can cause a kernel oops some time
- later. So we wait a while and `service' this interrupt. */
- mdelay(1);
- outw(dc_normal | READ_AHEAD, r_data_control);
- sti();
- printk(" using IRQ %d\n", cm206_irq);
-#endif
- if (send_receive_polled(c_drive_configuration) !=
- c_drive_configuration) {
- printk(KERN_INFO " drive not there\n");
- goto out_probe;
- }
- e = send_receive_polled(c_gimme);
- printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
- if (e & dcf_transfer_rate)
- printk(" double");
- else
- printk(" single");
- printk(" speed drive");
- if (e & dcf_motorized_tray)
- printk(", motorized tray");
- if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
- printk("\nUnable to reserve IRQ---aborted\n");
- goto out_probe;
- }
- printk(".\n");
-
- if (register_blkdev(MAJOR_NR, "cm206"))
- goto out_blkdev;
-
- disk = alloc_disk(1);
- if (!disk)
- goto out_disk;
- disk->major = MAJOR_NR;
- disk->first_minor = 0;
- sprintf(disk->disk_name, "cm206cd");
- disk->fops = &cm206_bdops;
- disk->flags = GENHD_FL_CD;
- cm206_gendisk = disk;
- if (register_cdrom(&cm206_info) != 0) {
- printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
- goto out_cdrom;
- }
- cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock);
- if (!cm206_queue)
- goto out_queue;
-
- blk_queue_hardsect_size(cm206_queue, 2048);
- disk->queue = cm206_queue;
- add_disk(disk);
-
- memset(cd, 0, sizeof(*cd)); /* give'm some reasonable value */
- cd->sector_last = -1; /* flag no data buffered */
- cd->adapter_last = -1;
- init_timer(&cd->timer);
- cd->timer.function = cm206_timeout;
- cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
- printk(KERN_INFO "%d kB adapter memory available, "
- " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
- size);
- return 0;
-
-out_queue:
- unregister_cdrom(&cm206_info);
-out_cdrom:
- put_disk(disk);
-out_disk:
- unregister_blkdev(MAJOR_NR, "cm206");
-out_blkdev:
- free_irq(cm206_irq, NULL);
-out_probe:
- kfree(cd);
-out_base:
- release_region(cm206_base, 16);
- return -EIO;
-}
-
-#ifdef MODULE
-
-
-static void __init parse_options(void)
-{
- int i;
- for (i = 0; i < 2; i++) {
- if (0x300 <= cm206[i] && i <= 0x370
- && cm206[i] % 0x10 == 0) {
- cm206_base = cm206[i];
- auto_probe = 0;
- } else if (3 <= cm206[i] && cm206[i] <= 15) {
- cm206_irq = cm206[i];
- auto_probe = 0;
- }
- }
-}
-
-static int __init __cm206_init(void)
-{
- parse_options();
-#if !defined(AUTO_PROBE_MODULE)
- auto_probe = 0;
-#endif
- return cm206_init();
-}
-
-static void __exit cm206_exit(void)
-{
- del_gendisk(cm206_gendisk);
- put_disk(cm206_gendisk);
- if (unregister_cdrom(&cm206_info)) {
- printk("Can't unregister cdrom cm206\n");
- return;
- }
- if (unregister_blkdev(MAJOR_NR, "cm206")) {
- printk("Can't unregister major cm206\n");
- return;
- }
- blk_cleanup_queue(cm206_queue);
- free_irq(cm206_irq, NULL);
- kfree(cd);
- release_region(cm206_base, 16);
- printk(KERN_INFO "cm206 removed\n");
-}
-
-module_init(__cm206_init);
-module_exit(cm206_exit);
-
-#else /* !MODULE */
-
-/* This setup function accepts either `auto' or numbers in the range
- * 3--11 (for irq) or 0x300--0x370 (for base port) or both. */
-
-static int __init cm206_setup(char *s)
-{
- int i, p[4];
-
- (void) get_options(s, ARRAY_SIZE(p), p);
-
- if (!strcmp(s, "auto"))
- auto_probe = 1;
- for (i = 1; i <= p[0]; i++) {
- if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
- cm206_base = p[i];
- auto_probe = 0;
- } else if (3 <= p[i] && p[i] <= 15) {
- cm206_irq = p[i];
- auto_probe = 0;
- }
- }
- return 1;
-}
-
-__setup("cm206=", cm206_setup);
-
-#endif /* !MODULE */
-MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR);
-
diff --git a/drivers/cdrom/cm206.h b/drivers/cdrom/cm206.h
deleted file mode 100644
index 0ae51c1a0da..00000000000
--- a/drivers/cdrom/cm206.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* cm206.h Header file for cm206.c.
- Copyright (c) 1995 David van Leeuwen
-*/
-
-#ifndef LINUX_CM206_H
-#define LINUX_CM206_H
-
-#include <linux/ioctl.h>
-
-/* First, the cm260 stuff */
-/* The ports and irq used. Although CM206_BASE and CM206_IRQ are defined
- below, the values are not used unless autoprobing is turned off and
- no LILO boot options or module command line options are given. Change
- these values to your own as last resort if autoprobing and options
- don't work. */
-
-#define CM206_BASE 0x340
-#define CM206_IRQ 11
-
-#define r_data_status (cm206_base)
-#define r_uart_receive (cm206_base+0x2)
-#define r_fifo_output_buffer (cm206_base+0x4)
-#define r_line_status (cm206_base+0x6)
-#define r_data_control (cm206_base+0x8)
-#define r_uart_transmit (cm206_base+0xa)
-#define r_test_clock (cm206_base+0xc)
-#define r_test_control (cm206_base+0xe)
-
-/* the data_status flags */
-#define ds_ram_size 0x4000
-#define ds_toc_ready 0x2000
-#define ds_fifo_empty 0x1000
-#define ds_sync_error 0x800
-#define ds_crc_error 0x400
-#define ds_data_error 0x200
-#define ds_fifo_overflow 0x100
-#define ds_data_ready 0x80
-
-/* the line_status flags */
-#define ls_attention 0x10
-#define ls_parity_error 0x8
-#define ls_overrun 0x4
-#define ls_receive_buffer_full 0x2
-#define ls_transmitter_buffer_empty 0x1
-
-/* the data control register flags */
-#define dc_read_q_channel 0x4000
-#define dc_mask_sync_error 0x2000
-#define dc_toc_enable 0x1000
-#define dc_no_stop_on_error 0x800
-#define dc_break 0x400
-#define dc_initialize 0x200
-#define dc_mask_transmit_ready 0x100
-#define dc_flag_enable 0x80
-
-/* Define the default data control register flags here */
-#define dc_normal (dc_mask_sync_error | dc_no_stop_on_error | \
- dc_mask_transmit_ready)
-
-/* now some constants related to the cm206 */
-/* another drive status byte, echoed by the cm206 on most commands */
-
-#define dsb_error_condition 0x1
-#define dsb_play_in_progress 0x4
-#define dsb_possible_media_change 0x8
-#define dsb_disc_present 0x10
-#define dsb_drive_not_ready 0x20
-#define dsb_tray_locked 0x40
-#define dsb_tray_not_closed 0x80
-
-#define dsb_not_useful (dsb_drive_not_ready | dsb_tray_not_closed)
-
-/* the cm206 command set */
-
-#define c_close_tray 0
-#define c_lock_tray 0x01
-#define c_unlock_tray 0x04
-#define c_open_tray 0x05
-#define c_seek 0x10
-#define c_read_data 0x20
-#define c_force_1x 0x21
-#define c_force_2x 0x22
-#define c_auto_mode 0x23
-#define c_play 0x30
-#define c_set_audio_mode 0x31
-#define c_read_current_q 0x41
-#define c_stream_q 0x42
-#define c_drive_status 0x50
-#define c_disc_status 0x51
-#define c_audio_status 0x52
-#define c_drive_configuration 0x53
-#define c_read_upc 0x60
-#define c_stop 0x70
-#define c_calc_checksum 0xe5
-
-#define c_gimme 0xf8
-
-/* finally, the (error) condition that the drive can be in *
- * OK, this is not always an error, but let's prefix it with e_ */
-
-#define e_none 0
-#define e_illegal_command 0x01
-#define e_sync 0x02
-#define e_seek 0x03
-#define e_parity 0x04
-#define e_focus 0x05
-#define e_header_sync 0x06
-#define e_code_incompatibility 0x07
-#define e_reset_done 0x08
-#define e_bad_parameter 0x09
-#define e_radial 0x0a
-#define e_sub_code 0x0b
-#define e_no_data_track 0x0c
-#define e_scan 0x0d
-#define e_tray_open 0x0f
-#define e_no_disc 0x10
-#define e_tray stalled 0x11
-
-/* drive configuration masks */
-
-#define dcf_revision_code 0x7
-#define dcf_transfer_rate 0x60
-#define dcf_motorized_tray 0x80
-
-/* disc status byte */
-
-#define cds_multi_session 0x2
-#define cds_all_audio 0x8
-#define cds_xa_mode 0xf0
-
-/* finally some ioctls for the driver */
-
-#define CM206CTL_GET_STAT _IO( 0x20, 0 )
-#define CM206CTL_GET_LAST_STAT _IO( 0x20, 1 )
-
-#ifdef STATISTICS
-
-/* This is an ugly way to guarantee that the names of the statistics
- * are the same in the code and in the diagnostics program. */
-
-#ifdef __KERNEL__
-#define x(a) st_ ## a
-#define y enum
-#else
-#define x(a) #a
-#define y char * stats_name[] =
-#endif
-
-y {x(interrupt), x(data_ready), x(fifo_overflow), x(data_error),
- x(crc_error), x(sync_error), x(lost_intr), x(echo),
- x(write_timeout), x(receive_timeout), x(read_timeout),
- x(dsb_timeout), x(stop_0xff), x(back_read_timeout),
- x(sector_transferred), x(read_restarted), x(read_background),
- x(bh), x(open), x(ioctl_multisession), x(attention)
-#ifdef __KERNEL__
- , x(last_entry)
-#endif
- };
-
-#ifdef __KERNEL__
-#define NR_STATS st_last_entry
-#else
-#define NR_STATS (sizeof(stats_name)/sizeof(char*))
-#endif
-
-#undef y
-#undef x
-
-#endif /* STATISTICS */
-
-#endif /* LINUX_CM206_H */
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
deleted file mode 100644
index b3ab6e9b8df..00000000000
--- a/drivers/cdrom/gscd.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-#define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
-
-/*
- linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
-
- Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- based upon pre-works by Eberhard Moenkeberg <emoenke@gwdg.de>
-
-
- For all kind of other information about the GoldStar CDROM
- and this Linux device driver I installed a WWW-URL:
- http://linux.rz.fh-hannover.de/~raupach
-
-
- If you are the editor of a Linux CD, you should
- enable gscd.c within your boot floppy kernel and
- send me one of your CDs for free.
-
-
- --------------------------------------------------------------------
- This program is free software; you can redistribute 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.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You 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.
-
- --------------------------------------------------------------------
-
- 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-
-*/
-
-/* These settings are for various debug-level. Leave they untouched ... */
-#define NO_GSCD_DEBUG
-#define NO_IOCTL_DEBUG
-#define NO_MODULE_DEBUG
-#define NO_FUTURE_WORK
-/*------------------------*/
-
-#include <linux/module.h>
-
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#define MAJOR_NR GOLDSTAR_CDROM_MAJOR
-#include <linux/blkdev.h>
-#include "gscd.h"
-
-static int gscdPresent = 0;
-
-static unsigned char gscd_buf[2048]; /* buffer for block size conversion */
-static int gscd_bn = -1;
-static short gscd_port = GSCD_BASE_ADDR;
-module_param_named(gscd, gscd_port, short, 0);
-
-/* Kommt spaeter vielleicht noch mal dran ...
- * static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
- */
-
-static void gscd_read_cmd(struct request *req);
-static void gscd_hsg2msf(long hsg, struct msf *msf);
-static void gscd_bin2bcd(unsigned char *p);
-
-/* Schnittstellen zum Kern/FS */
-
-static void __do_gscd_request(unsigned long dummy);
-static int gscd_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
-static int gscd_open(struct inode *, struct file *);
-static int gscd_release(struct inode *, struct file *);
-static int check_gscd_med_chg(struct gendisk *disk);
-
-/* GoldStar Funktionen */
-
-static void cmd_out(int, char *, char *, int);
-static void cmd_status(void);
-static void init_cd_drive(int);
-
-static int get_status(void);
-static void clear_Audio(void);
-static void cc_invalidate(void);
-
-/* some things for the next version */
-#ifdef FUTURE_WORK
-static void update_state(void);
-static long gscd_msf2hsg(struct msf *mp);
-static int gscd_bcd2bin(unsigned char bcd);
-#endif
-
-
-/* lo-level cmd-Funktionen */
-
-static void cmd_info_in(char *, int);
-static void cmd_end(void);
-static void cmd_read_b(char *, int, int);
-static void cmd_read_w(char *, int, int);
-static int cmd_unit_alive(void);
-static void cmd_write_cmd(char *);
-
-
-/* GoldStar Variablen */
-
-static int curr_drv_state;
-static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-static int drv_mode;
-static int disk_state;
-static int speed;
-static int ndrives;
-
-static unsigned char drv_num_read;
-static unsigned char f_dsk_valid;
-static unsigned char current_drive;
-static unsigned char f_drv_ok;
-
-
-static char f_AudioPlay;
-static char f_AudioPause;
-static int AudioStart_m;
-static int AudioStart_f;
-static int AudioEnd_m;
-static int AudioEnd_f;
-
-static DEFINE_TIMER(gscd_timer, NULL, 0, 0);
-static DEFINE_SPINLOCK(gscd_lock);
-static struct request_queue *gscd_queue;
-
-static struct block_device_operations gscd_fops = {
- .owner = THIS_MODULE,
- .open = gscd_open,
- .release = gscd_release,
- .ioctl = gscd_ioctl,
- .media_changed = check_gscd_med_chg,
-};
-
-/*
- * Checking if the media has been changed
- * (not yet implemented)
- */
-static int check_gscd_med_chg(struct gendisk *disk)
-{
-#ifdef GSCD_DEBUG
- printk("gscd: check_med_change\n");
-#endif
- return 0;
-}
-
-
-#ifndef MODULE
-/* Using new interface for kernel-parameters */
-
-static int __init gscd_setup(char *str)
-{
- int ints[2];
- (void) get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0) {
- gscd_port = ints[1];
- }
- return 1;
-}
-
-__setup("gscd=", gscd_setup);
-
-#endif
-
-static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
- unsigned long arg)
-{
- unsigned char to_do[10];
- unsigned char dummy;
-
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- /* Don't think we can do this. Even if we could,
- * I think the drive times out and stops after a while
- * anyway. For now, ignore it.
- */
- return 0;
-
- case CDROMRESUME: /* keine Ahnung was das ist */
- return 0;
-
-
- case CDROMEJECT:
- cmd_status();
- to_do[0] = CMD_TRAY_CTL;
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
- return 0;
-
- default:
- return -EINVAL;
- }
-
-}
-
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static void gscd_transfer(struct request *req)
-{
- while (req->nr_sectors > 0 && gscd_bn == req->sector / 4) {
- long offs = (req->sector & 3) * 512;
- memcpy(req->buffer, gscd_buf + offs, 512);
- req->nr_sectors--;
- req->sector++;
- req->buffer += 512;
- }
-}
-
-
-/*
- * I/O request routine called from Linux kernel.
- */
-
-static void do_gscd_request(request_queue_t * q)
-{
- __do_gscd_request(0);
-}
-
-static void __do_gscd_request(unsigned long dummy)
-{
- struct request *req;
- unsigned int block;
- unsigned int nsect;
-
-repeat:
- req = elv_next_request(gscd_queue);
- if (!req)
- return;
-
- block = req->sector;
- nsect = req->nr_sectors;
-
- if (req->sector == -1)
- goto out;
-
- if (req->cmd != READ) {
- printk("GSCD: bad cmd %u\n", rq_data_dir(req));
- end_request(req, 0);
- goto repeat;
- }
-
- gscd_transfer(req);
-
- /* if we satisfied the request from the buffer, we're done. */
-
- if (req->nr_sectors == 0) {
- end_request(req, 1);
- goto repeat;
- }
-#ifdef GSCD_DEBUG
- printk("GSCD: block %d, nsect %d\n", block, nsect);
-#endif
- gscd_read_cmd(req);
-out:
- return;
-}
-
-
-
-/*
- * Check the result of the set-mode command. On success, send the
- * read-data command.
- */
-
-static void gscd_read_cmd(struct request *req)
-{
- long block;
- struct gscd_Play_msf gscdcmd;
- char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 }; /* cmd mode M-S-F secth sectl */
-
- cmd_status();
- if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
- printk("GSCD: no disk or door open\n");
- end_request(req, 0);
- } else {
- if (disk_state & ST_INVALID) {
- printk("GSCD: disk invalid\n");
- end_request(req, 0);
- } else {
- gscd_bn = -1; /* purge our buffer */
- block = req->sector / 4;
- gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */
-
- cmd[2] = gscdcmd.start.min;
- cmd[3] = gscdcmd.start.sec;
- cmd[4] = gscdcmd.start.frame;
-
-#ifdef GSCD_DEBUG
- printk("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3],
- cmd[4]);
-#endif
- cmd_out(TYPE_DATA, (char *) &cmd,
- (char *) &gscd_buf[0], 1);
-
- gscd_bn = req->sector / 4;
- gscd_transfer(req);
- end_request(req, 1);
- }
- }
- SET_TIMER(__do_gscd_request, 1);
-}
-
-
-/*
- * Open the device special file. Check that a disk is in.
- */
-
-static int gscd_open(struct inode *ip, struct file *fp)
-{
- int st;
-
-#ifdef GSCD_DEBUG
- printk("GSCD: open\n");
-#endif
-
- if (gscdPresent == 0)
- return -ENXIO; /* no hardware */
-
- get_status();
- st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
- if (st) {
- printk("GSCD: no disk or door open\n");
- return -ENXIO;
- }
-
-/* if (updateToc() < 0)
- return -EIO;
-*/
-
- return 0;
-}
-
-
-/*
- * On close, we flush all gscd blocks from the buffer cache.
- */
-
-static int gscd_release(struct inode *inode, struct file *file)
-{
-
-#ifdef GSCD_DEBUG
- printk("GSCD: release\n");
-#endif
-
- gscd_bn = -1;
-
- return 0;
-}
-
-
-static int get_status(void)
-{
- int status;
-
- cmd_status();
- status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
-
- if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) {
- cc_invalidate();
- return 1;
- } else {
- return 0;
- }
-}
-
-
-static void cc_invalidate(void)
-{
- drv_num_read = 0xFF;
- f_dsk_valid = 0xFF;
- current_drive = 0xFF;
- f_drv_ok = 0xFF;
-
- clear_Audio();
-
-}
-
-static void clear_Audio(void)
-{
-
- f_AudioPlay = 0;
- f_AudioPause = 0;
- AudioStart_m = 0;
- AudioStart_f = 0;
- AudioEnd_m = 0;
- AudioEnd_f = 0;
-
-}
-
-/*
- * waiting ?
- */
-
-static int wait_drv_ready(void)
-{
- int found, read;
-
- do {
- found = inb(GSCDPORT(0));
- found &= 0x0f;
- read = inb(GSCDPORT(0));
- read &= 0x0f;
- } while (read != found);
-
-#ifdef GSCD_DEBUG
- printk("Wait for: %d\n", read);
-#endif
-
- return read;
-}
-
-static void cc_Ident(char *respons)
-{
- char to_do[] = { CMD_IDENT, 0, 0 };
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E);
-
-}
-
-static void cc_SetSpeed(void)
-{
- char to_do[] = { CMD_SETSPEED, 0, 0 };
- char dummy;
-
- if (speed > 0) {
- to_do[1] = speed & 0x0F;
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
- }
-}
-
-static void cc_Reset(void)
-{
- char to_do[] = { CMD_RESET, 0 };
- char dummy;
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-}
-
-static void cmd_status(void)
-{
- char to_do[] = { CMD_STATUS, 0 };
- char dummy;
-
- cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
-
-#ifdef GSCD_DEBUG
- printk("GSCD: Status: %d\n", disk_state);
-#endif
-
-}
-
-static void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
-{
- int result;
-
-
- result = wait_drv_ready();
- if (result != drv_mode) {
- unsigned long test_loops = 0xFFFF;
- int i, dummy;
-
- outb(curr_drv_state, GSCDPORT(0));
-
- /* LOCLOOP_170 */
- do {
- result = wait_drv_ready();
- test_loops--;
- } while ((result != drv_mode) && (test_loops > 0));
-
- if (result != drv_mode) {
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
-
- /* ...and waiting */
- for (i = 1, dummy = 1; i < 0xFFFF; i++) {
- dummy *= i;
- }
- }
-
- /* LOC_172 */
- /* check the unit */
- /* and wake it up */
- if (cmd_unit_alive() != 0x08) {
- /* LOC_174 */
- /* game over for this unit */
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
-
- /* LOC_176 */
-#ifdef GSCD_DEBUG
- printk("LOC_176 ");
-#endif
- if (drv_mode == 0x09) {
- /* magic... */
- printk("GSCD: magic ...\n");
- outb(result, GSCDPORT(2));
- }
-
- /* write the command to the drive */
- cmd_write_cmd(cmd);
-
- /* LOC_178 */
- for (;;) {
- result = wait_drv_ready();
- if (result != drv_mode) {
- /* LOC_179 */
- if (result == 0x04) { /* Mode 4 */
- /* LOC_205 */
-#ifdef GSCD_DEBUG
- printk("LOC_205 ");
-#endif
- disk_state = inb(GSCDPORT(2));
-
- do {
- result = wait_drv_ready();
- } while (result != drv_mode);
- return;
-
- } else {
- if (result == 0x06) { /* Mode 6 */
- /* LOC_181 */
-#ifdef GSCD_DEBUG
- printk("LOC_181 ");
-#endif
-
- if (cmd_type == TYPE_DATA) {
- /* read data */
- /* LOC_184 */
- if (drv_mode == 9) {
- /* read the data to the buffer (word) */
-
- /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
- cmd_read_w
- (respo_buf,
- respo_count,
- CD_FRAMESIZE /
- 2);
- return;
- } else {
- /* read the data to the buffer (byte) */
-
- /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */
- cmd_read_b
- (respo_buf,
- respo_count,
- CD_FRAMESIZE);
- return;
- }
- } else {
- /* read the info to the buffer */
- cmd_info_in(respo_buf,
- respo_count);
- return;
- }
-
- return;
- }
- }
-
- } else {
- disk_state = ST_x08 | ST_x04 | ST_INVALID;
- return;
- }
- } /* for (;;) */
-
-
-#ifdef GSCD_DEBUG
- printk("\n");
-#endif
-}
-
-
-static void cmd_write_cmd(char *pstr)
-{
- int i, j;
-
- /* LOC_177 */
-#ifdef GSCD_DEBUG
- printk("LOC_177 ");
-#endif
-
- /* calculate the number of parameter */
- j = *pstr & 0x0F;
-
- /* shift it out */
- for (i = 0; i < j; i++) {
- outb(*pstr, GSCDPORT(2));
- pstr++;
- }
-}
-
-
-static int cmd_unit_alive(void)
-{
- int result;
- unsigned long max_test_loops;
-
-
- /* LOC_172 */
-#ifdef GSCD_DEBUG
- printk("LOC_172 ");
-#endif
-
- outb(curr_drv_state, GSCDPORT(0));
- max_test_loops = 0xFFFF;
-
- do {
- result = wait_drv_ready();
- max_test_loops--;
- } while ((result != 0x08) && (max_test_loops > 0));
-
- return result;
-}
-
-
-static void cmd_info_in(char *pb, int count)
-{
- int result;
- char read;
-
-
- /* read info */
- /* LOC_182 */
-#ifdef GSCD_DEBUG
- printk("LOC_182 ");
-#endif
-
- do {
- read = inb(GSCDPORT(2));
- if (count > 0) {
- *pb = read;
- pb++;
- count--;
- }
-
- /* LOC_183 */
- do {
- result = wait_drv_ready();
- } while (result == 0x0E);
- } while (result == 6);
-
- cmd_end();
- return;
-}
-
-
-static void cmd_read_b(char *pb, int count, int size)
-{
- int result;
- int i;
-
-
- /* LOC_188 */
- /* LOC_189 */
-#ifdef GSCD_DEBUG
- printk("LOC_189 ");
-#endif
-
- do {
- do {
- result = wait_drv_ready();
- } while (result != 6 || result == 0x0E);
-
- if (result != 6) {
- cmd_end();
- return;
- }
-#ifdef GSCD_DEBUG
- printk("LOC_191 ");
-#endif
-
- for (i = 0; i < size; i++) {
- *pb = inb(GSCDPORT(2));
- pb++;
- }
- count--;
- } while (count > 0);
-
- cmd_end();
- return;
-}
-
-
-static void cmd_end(void)
-{
- int result;
-
-
- /* LOC_204 */
-#ifdef GSCD_DEBUG
- printk("LOC_204 ");
-#endif
-
- do {
- result = wait_drv_ready();
- if (result == drv_mode) {
- return;
- }
- } while (result != 4);
-
- /* LOC_205 */
-#ifdef GSCD_DEBUG
- printk("LOC_205 ");
-#endif
-
- disk_state = inb(GSCDPORT(2));
-
- do {
- result = wait_drv_ready();
- } while (result != drv_mode);
- return;
-
-}
-
-
-static void cmd_read_w(char *pb, int count, int size)
-{
- int result;
- int i;
-
-
-#ifdef GSCD_DEBUG
- printk("LOC_185 ");
-#endif
-
- do {
- /* LOC_185 */
- do {
- result = wait_drv_ready();
- } while (result != 6 || result == 0x0E);
-
- if (result != 6) {
- cmd_end();
- return;
- }
-
- for (i = 0; i < size; i++) {
- /* na, hier muss ich noch mal drueber nachdenken */
- *pb = inw(GSCDPORT(2));
- pb++;
- }
- count--;
- } while (count > 0);
-
- cmd_end();
- return;
-}
-
-static int __init find_drives(void)
-{
- int *pdrv;
- int drvnum;
- int subdrv;
- int i;
-
- speed = 0;
- pdrv = (int *) &drv_states;
- curr_drv_state = 0xFE;
- subdrv = 0;
- drvnum = 0;
-
- for (i = 0; i < 8; i++) {
- subdrv++;
- cmd_status();
- disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
- if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
- /* LOC_240 */
- *pdrv = curr_drv_state;
- init_cd_drive(drvnum);
- pdrv++;
- drvnum++;
- } else {
- if (subdrv < 2) {
- continue;
- } else {
- subdrv = 0;
- }
- }
-
-/* curr_drv_state<<1; <-- das geht irgendwie nicht */
-/* muss heissen: curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
- curr_drv_state *= 2;
- curr_drv_state |= 1;
-#ifdef GSCD_DEBUG
- printk("DriveState: %d\n", curr_drv_state);
-#endif
- }
-
- ndrives = drvnum;
- return drvnum;
-}
-
-static void __init init_cd_drive(int num)
-{
- char resp[50];
- int i;
-
- printk("GSCD: init unit %d\n", num);
- cc_Ident((char *) &resp);
-
- printk("GSCD: identification: ");
- for (i = 0; i < 0x1E; i++) {
- printk("%c", resp[i]);
- }
- printk("\n");
-
- cc_SetSpeed();
-
-}
-
-#ifdef FUTURE_WORK
-/* return_done */
-static void update_state(void)
-{
- unsigned int AX;
-
-
- if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
- if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
- AX = ST_INVALID;
- }
-
- if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
- == 0) {
- invalidate();
- f_drv_ok = 0;
- }
-
- AX |= 0x8000;
- }
-
- if (disk_state & ST_PLAYING) {
- AX |= 0x200;
- }
-
- AX |= 0x100;
- /* pkt_esbx = AX; */
-
- disk_state = 0;
-
-}
-#endif
-
-static struct gendisk *gscd_disk;
-
-static void __exit gscd_exit(void)
-{
- CLEAR_TIMER;
-
- del_gendisk(gscd_disk);
- put_disk(gscd_disk);
- if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
- printk("What's that: can't unregister GoldStar-module\n");
- return;
- }
- blk_cleanup_queue(gscd_queue);
- release_region(gscd_port, GSCD_IO_EXTENT);
- printk(KERN_INFO "GoldStar-module released.\n");
-}
-
-/* This is the common initialisation for the GoldStar drive. */
-/* It is called at boot time AND for module init. */
-static int __init gscd_init(void)
-{
- int i;
- int result;
- int ret=0;
-
- printk(KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
- printk(KERN_INFO
- "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n",
- gscd_port);
-
- if (!request_region(gscd_port, GSCD_IO_EXTENT, "gscd")) {
- printk(KERN_WARNING "GSCD: Init failed, I/O port (%X) already"
- " in use.\n", gscd_port);
- return -EIO;
- }
-
-
- /* check for card */
- result = wait_drv_ready();
- if (result == 0x09) {
- printk(KERN_WARNING "GSCD: DMA kann ich noch nicht!\n");
- ret = -EIO;
- goto err_out1;
- }
-
- if (result == 0x0b) {
- drv_mode = result;
- i = find_drives();
- if (i == 0) {
- printk(KERN_WARNING "GSCD: GoldStar CD-ROM Drive is"
- " not found.\n");
- ret = -EIO;
- goto err_out1;
- }
- }
-
- if ((result != 0x0b) && (result != 0x09)) {
- printk(KERN_WARNING "GSCD: GoldStar Interface Adapter does not "
- "exist or H/W error\n");
- ret = -EIO;
- goto err_out1;
- }
-
- /* reset all drives */
- i = 0;
- while (drv_states[i] != 0) {
- curr_drv_state = drv_states[i];
- printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
- cc_Reset();
- printk("done\n");
- i++;
- }
-
- gscd_disk = alloc_disk(1);
- if (!gscd_disk)
- goto err_out1;
- gscd_disk->major = MAJOR_NR;
- gscd_disk->first_minor = 0;
- gscd_disk->fops = &gscd_fops;
- sprintf(gscd_disk->disk_name, "gscd");
-
- if (register_blkdev(MAJOR_NR, "gscd")) {
- ret = -EIO;
- goto err_out2;
- }
-
- gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock);
- if (!gscd_queue) {
- ret = -ENOMEM;
- goto err_out3;
- }
-
- disk_state = 0;
- gscdPresent = 1;
-
- gscd_disk->queue = gscd_queue;
- add_disk(gscd_disk);
-
- printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
- return 0;
-
-err_out3:
- unregister_blkdev(MAJOR_NR, "gscd");
-err_out2:
- put_disk(gscd_disk);
-err_out1:
- release_region(gscd_port, GSCD_IO_EXTENT);
- return ret;
-}
-
-static void gscd_hsg2msf(long hsg, struct msf *msf)
-{
- hsg += CD_MSF_OFFSET;
- msf->min = hsg / (CD_FRAMES * CD_SECS);
- hsg %= CD_FRAMES * CD_SECS;
- msf->sec = hsg / CD_FRAMES;
- msf->frame = hsg % CD_FRAMES;
-
- gscd_bin2bcd(&msf->min); /* convert to BCD */
- gscd_bin2bcd(&msf->sec);
- gscd_bin2bcd(&msf->frame);
-}
-
-
-static void gscd_bin2bcd(unsigned char *p)
-{
- int u, t;
-
- u = *p % 10;
- t = *p / 10;
- *p = u | (t << 4);
-}
-
-
-#ifdef FUTURE_WORK
-static long gscd_msf2hsg(struct msf *mp)
-{
- return gscd_bcd2bin(mp->frame)
- + gscd_bcd2bin(mp->sec) * CD_FRAMES
- + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
-}
-
-static int gscd_bcd2bin(unsigned char bcd)
-{
- return (bcd >> 4) * 10 + (bcd & 0xF);
-}
-#endif
-
-MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
-MODULE_LICENSE("GPL");
-module_init(gscd_init);
-module_exit(gscd_exit);
-MODULE_ALIAS_BLOCKDEV_MAJOR(GOLDSTAR_CDROM_MAJOR);
diff --git a/drivers/cdrom/gscd.h b/drivers/cdrom/gscd.h
deleted file mode 100644
index a41e64bfc06..00000000000
--- a/drivers/cdrom/gscd.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Definitions for a GoldStar R420 CD-ROM interface
- *
- * Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
- * Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- * Published under the GPL.
- *
- */
-
-
-/* The Interface Card default address is 0x340. This will work for most
- applications. Address selection is accomplished by jumpers PN801-1 to
- PN801-4 on the GoldStar Interface Card.
- Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360
- 0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0 */
-
-/* insert here the I/O port address and extent */
-#define GSCD_BASE_ADDR 0x340
-#define GSCD_IO_EXTENT 4
-
-
-/************** nothing to set up below here *********************/
-
-/* port access macro */
-#define GSCDPORT(x) (gscd_port + (x))
-
-/*
- * commands
- * the lower nibble holds the command length
- */
-#define CMD_STATUS 0x01
-#define CMD_READSUBQ 0x02 /* 1: ?, 2: UPC, 5: ? */
-#define CMD_SEEK 0x05 /* read_mode M-S-F */
-#define CMD_READ 0x07 /* read_mode M-S-F nsec_h nsec_l */
-#define CMD_RESET 0x11
-#define CMD_SETMODE 0x15
-#define CMD_PLAY 0x17 /* M-S-F M-S-F */
-#define CMD_LOCK_CTL 0x22 /* 0: unlock, 1: lock */
-#define CMD_IDENT 0x31
-#define CMD_SETSPEED 0x32 /* 0: auto */ /* ??? */
-#define CMD_GETMODE 0x41
-#define CMD_PAUSE 0x51
-#define CMD_READTOC 0x61
-#define CMD_DISKINFO 0x71
-#define CMD_TRAY_CTL 0x81
-
-/*
- * disk_state:
- */
-#define ST_PLAYING 0x80
-#define ST_UNLOCKED 0x40
-#define ST_NO_DISK 0x20
-#define ST_DOOR_OPEN 0x10
-#define ST_x08 0x08
-#define ST_x04 0x04
-#define ST_INVALID 0x02
-#define ST_x01 0x01
-
-/*
- * cmd_type:
- */
-#define TYPE_INFO 0x01
-#define TYPE_DATA 0x02
-
-/*
- * read_mode:
- */
-#define MOD_POLLED 0x80
-#define MOD_x08 0x08
-#define MOD_RAW 0x04
-
-#define READ_DATA(port, buf, nr) insb(port, buf, nr)
-
-#define SET_TIMER(func, jifs) \
- ((mod_timer(&gscd_timer, jiffies + jifs)), \
- (gscd_timer.function = func))
-
-#define CLEAR_TIMER del_timer_sync(&gscd_timer)
-
-#define MAX_TRACKS 104
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct gscd_Play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct gscd_DiskInfo {
- unsigned char first;
- unsigned char last;
- struct msf diskLength;
- struct msf firstTrack;
-};
-
-struct gscd_Toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char pointIndex;
- struct msf trackTime;
- struct msf diskTime;
-};
-
diff --git a/drivers/cdrom/isp16.c b/drivers/cdrom/isp16.c
deleted file mode 100644
index db0fd9a240e..00000000000
--- a/drivers/cdrom/isp16.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* -- ISP16 cdrom detection and configuration
- *
- * Copyright (c) 1995,1996 Eric van der Maarel <H.T.M.v.d.Maarel@marin.nl>
- *
- * Version 0.6
- *
- * History:
- * 0.5 First release.
- * Was included in the sjcd and optcd cdrom drivers.
- * 0.6 First "stand-alone" version.
- * Removed sound configuration.
- * Added "module" support.
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 19 June 2004 -- check_region() converted to request_region()
- * and return statement cleanups.
- * - Jesper Juhl
- *
- * Detect cdrom interface on ISP16 sound card.
- * Configure cdrom interface.
- *
- * Algorithm for the card with OPTi 82C928 taken
- * from the CDSETUP.SYS driver for MSDOS,
- * by OPTi Computers, version 2.03.
- * Algorithm for the card with OPTi 82C929 as communicated
- * to me by Vadim Model and Leo Spiekman.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 ISP16_VERSION_MAJOR 0
-#define ISP16_VERSION_MINOR 6
-
-#include <linux/module.h>
-
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include "isp16.h"
-
-static short isp16_detect(void);
-static short isp16_c928__detect(void);
-static short isp16_c929__detect(void);
-static short isp16_cdi_config(int base, u_char drive_type, int irq,
- int dma);
-static short isp16_type; /* dependent on type of interface card */
-static u_char isp16_ctrl;
-static u_short isp16_enable_port;
-
-static int isp16_cdrom_base = ISP16_CDROM_IO_BASE;
-static int isp16_cdrom_irq = ISP16_CDROM_IRQ;
-static int isp16_cdrom_dma = ISP16_CDROM_DMA;
-static char *isp16_cdrom_type = ISP16_CDROM_TYPE;
-
-module_param(isp16_cdrom_base, int, 0);
-module_param(isp16_cdrom_irq, int, 0);
-module_param(isp16_cdrom_dma, int, 0);
-module_param(isp16_cdrom_type, charp, 0);
-
-#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
-#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
-
-#ifndef MODULE
-
-static int
-__init isp16_setup(char *str)
-{
- int ints[4];
-
- (void) get_options(str, ARRAY_SIZE(ints), ints);
- if (ints[0] > 0)
- isp16_cdrom_base = ints[1];
- if (ints[0] > 1)
- isp16_cdrom_irq = ints[2];
- if (ints[0] > 2)
- isp16_cdrom_dma = ints[3];
- if (str)
- isp16_cdrom_type = str;
-
- return 1;
-}
-
-__setup("isp16=", isp16_setup);
-
-#endif /* MODULE */
-
-/*
- * ISP16 initialisation.
- *
- */
-static int __init isp16_init(void)
-{
- u_char expected_drive;
-
- printk(KERN_INFO
- "ISP16: configuration cdrom interface, version %d.%d.\n",
- ISP16_VERSION_MAJOR, ISP16_VERSION_MINOR);
-
- if (!strcmp(isp16_cdrom_type, "noisp16")) {
- printk("ISP16: no cdrom interface configured.\n");
- return 0;
- }
-
- if (!request_region(ISP16_IO_BASE, ISP16_IO_SIZE, "isp16")) {
- printk("ISP16: i/o ports already in use.\n");
- goto out;
- }
-
- if ((isp16_type = isp16_detect()) < 0) {
- printk("ISP16: no cdrom interface found.\n");
- goto cleanup_out;
- }
-
- printk(KERN_INFO
- "ISP16: cdrom interface (with OPTi 82C92%d chip) detected.\n",
- (isp16_type == 2) ? 9 : 8);
-
- if (!strcmp(isp16_cdrom_type, "Sanyo"))
- expected_drive =
- (isp16_type ? ISP16_SANYO1 : ISP16_SANYO0);
- else if (!strcmp(isp16_cdrom_type, "Sony"))
- expected_drive = ISP16_SONY;
- else if (!strcmp(isp16_cdrom_type, "Panasonic"))
- expected_drive =
- (isp16_type ? ISP16_PANASONIC1 : ISP16_PANASONIC0);
- else if (!strcmp(isp16_cdrom_type, "Mitsumi"))
- expected_drive = ISP16_MITSUMI;
- else {
- printk("ISP16: %s not supported by cdrom interface.\n",
- isp16_cdrom_type);
- goto cleanup_out;
- }
-
- if (isp16_cdi_config(isp16_cdrom_base, expected_drive,
- isp16_cdrom_irq, isp16_cdrom_dma) < 0) {
- printk
- ("ISP16: cdrom interface has not been properly configured.\n");
- goto cleanup_out;
- }
- printk(KERN_INFO
- "ISP16: cdrom interface set up with io base 0x%03X, irq %d, dma %d,"
- " type %s.\n", isp16_cdrom_base, isp16_cdrom_irq,
- isp16_cdrom_dma, isp16_cdrom_type);
- return 0;
-
-cleanup_out:
- release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
-out:
- return -EIO;
-}
-
-static short __init isp16_detect(void)
-{
-
- if (isp16_c929__detect() >= 0)
- return 2;
- else
- return (isp16_c928__detect());
-}
-
-static short __init isp16_c928__detect(void)
-{
- u_char ctrl;
- u_char enable_cdrom;
- u_char io;
- short i = -1;
-
- isp16_ctrl = ISP16_C928__CTRL;
- isp16_enable_port = ISP16_C928__ENABLE_PORT;
-
- /* read' and write' are a special read and write, respectively */
-
- /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
- ctrl = ISP16_IN(ISP16_CTRL_PORT) & 0xFC;
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- /* read' 3,4 and 5-bit from the cdrom enable port */
- enable_cdrom = ISP16_IN(ISP16_C928__ENABLE_PORT) & 0x38;
-
- if (!(enable_cdrom & 0x20)) { /* 5-bit not set */
- /* read' last 2 bits of ISP16_IO_SET_PORT */
- io = ISP16_IN(ISP16_IO_SET_PORT) & 0x03;
- if (((io & 0x01) << 1) == (io & 0x02)) { /* bits are the same */
- if (io == 0) { /* ...the same and 0 */
- i = 0;
- enable_cdrom |= 0x20;
- } else { /* ...the same and 1 *//* my card, first time 'round */
- i = 1;
- enable_cdrom |= 0x28;
- }
- ISP16_OUT(ISP16_C928__ENABLE_PORT, enable_cdrom);
- } else { /* bits are not the same */
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
- return i; /* -> not detected: possibly incorrect conclusion */
- }
- } else if (enable_cdrom == 0x20)
- i = 0;
- else if (enable_cdrom == 0x28) /* my card, already initialised */
- i = 1;
-
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- return i;
-}
-
-static short __init isp16_c929__detect(void)
-{
- u_char ctrl;
- u_char tmp;
-
- isp16_ctrl = ISP16_C929__CTRL;
- isp16_enable_port = ISP16_C929__ENABLE_PORT;
-
- /* read' and write' are a special read and write, respectively */
-
- /* read' ISP16_CTRL_PORT and save */
- ctrl = ISP16_IN(ISP16_CTRL_PORT);
-
- /* write' zero to the ctrl port and get response */
- ISP16_OUT(ISP16_CTRL_PORT, 0);
- tmp = ISP16_IN(ISP16_CTRL_PORT);
-
- if (tmp != 2) /* isp16 with 82C929 not detected */
- return -1;
-
- /* restore ctrl port value */
- ISP16_OUT(ISP16_CTRL_PORT, ctrl);
-
- return 2;
-}
-
-static short __init
-isp16_cdi_config(int base, u_char drive_type, int irq, int dma)
-{
- u_char base_code;
- u_char irq_code;
- u_char dma_code;
- u_char i;
-
- if ((drive_type == ISP16_MITSUMI) && (dma != 0))
- printk("ISP16: Mitsumi cdrom drive has no dma support.\n");
-
- switch (base) {
- case 0x340:
- base_code = ISP16_BASE_340;
- break;
- case 0x330:
- base_code = ISP16_BASE_330;
- break;
- case 0x360:
- base_code = ISP16_BASE_360;
- break;
- case 0x320:
- base_code = ISP16_BASE_320;
- break;
- default:
- printk
- ("ISP16: base address 0x%03X not supported by cdrom interface.\n",
- base);
- return -1;
- }
- switch (irq) {
- case 0:
- irq_code = ISP16_IRQ_X;
- break; /* disable irq */
- case 5:
- irq_code = ISP16_IRQ_5;
- printk("ISP16: irq 5 shouldn't be used by cdrom interface,"
- " due to possible conflicts with the sound card.\n");
- break;
- case 7:
- irq_code = ISP16_IRQ_7;
- printk("ISP16: irq 7 shouldn't be used by cdrom interface,"
- " due to possible conflicts with the sound card.\n");
- break;
- case 3:
- irq_code = ISP16_IRQ_3;
- break;
- case 9:
- irq_code = ISP16_IRQ_9;
- break;
- case 10:
- irq_code = ISP16_IRQ_10;
- break;
- case 11:
- irq_code = ISP16_IRQ_11;
- break;
- default:
- printk("ISP16: irq %d not supported by cdrom interface.\n",
- irq);
- return -1;
- }
- switch (dma) {
- case 0:
- dma_code = ISP16_DMA_X;
- break; /* disable dma */
- case 1:
- printk("ISP16: dma 1 cannot be used by cdrom interface,"
- " due to conflict with the sound card.\n");
- return -1;
- break;
- case 3:
- dma_code = ISP16_DMA_3;
- break;
- case 5:
- dma_code = ISP16_DMA_5;
- break;
- case 6:
- dma_code = ISP16_DMA_6;
- break;
- case 7:
- dma_code = ISP16_DMA_7;
- break;
- default:
- printk("ISP16: dma %d not supported by cdrom interface.\n",
- dma);
- return -1;
- }
-
- if (drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
- drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
- drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
- drive_type != ISP16_DRIVE_X) {
- printk
- ("ISP16: drive type (code 0x%02X) not supported by cdrom"
- " interface.\n", drive_type);
- return -1;
- }
-
- /* set type of interface */
- i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK; /* clear some bits */
- ISP16_OUT(ISP16_DRIVE_SET_PORT, i | drive_type);
-
- /* enable cdrom on interface with 82C929 chip */
- if (isp16_type > 1)
- ISP16_OUT(isp16_enable_port, ISP16_ENABLE_CDROM);
-
- /* set base address, irq and dma */
- i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK; /* keep some bits */
- ISP16_OUT(ISP16_IO_SET_PORT, i | base_code | irq_code | dma_code);
-
- return 0;
-}
-
-static void __exit isp16_exit(void)
-{
- release_region(ISP16_IO_BASE, ISP16_IO_SIZE);
- printk(KERN_INFO "ISP16: module released.\n");
-}
-
-module_init(isp16_init);
-module_exit(isp16_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/cdrom/isp16.h b/drivers/cdrom/isp16.h
deleted file mode 100644
index 5bd22c8f7a9..00000000000
--- a/drivers/cdrom/isp16.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -- isp16.h
- *
- * Header for detection and initialisation of cdrom interface (only) on
- * ISP16 (MAD16, Mozart) sound card.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- */
-
-/* These are the default values */
-#define ISP16_CDROM_TYPE "Sanyo"
-#define ISP16_CDROM_IO_BASE 0x340
-#define ISP16_CDROM_IRQ 0
-#define ISP16_CDROM_DMA 0
-
-/* Some (Media)Magic */
-/* define types of drive the interface on an ISP16 card may be looking at */
-#define ISP16_DRIVE_X 0x00
-#define ISP16_SONY 0x02
-#define ISP16_PANASONIC0 0x02
-#define ISP16_SANYO0 0x02
-#define ISP16_MITSUMI 0x04
-#define ISP16_PANASONIC1 0x06
-#define ISP16_SANYO1 0x06
-#define ISP16_DRIVE_NOT_USED 0x08 /* not used */
-#define ISP16_DRIVE_SET_MASK 0xF1 /* don't change 0-bit or 4-7-bits*/
-/* ...for port */
-#define ISP16_DRIVE_SET_PORT 0xF8D
-/* set io parameters */
-#define ISP16_BASE_340 0x00
-#define ISP16_BASE_330 0x40
-#define ISP16_BASE_360 0x80
-#define ISP16_BASE_320 0xC0
-#define ISP16_IRQ_X 0x00
-#define ISP16_IRQ_5 0x04 /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_7 0x08 /* shouldn't be used to avoid sound card conflicts */
-#define ISP16_IRQ_3 0x0C
-#define ISP16_IRQ_9 0x10
-#define ISP16_IRQ_10 0x14
-#define ISP16_IRQ_11 0x18
-#define ISP16_DMA_X 0x03
-#define ISP16_DMA_3 0x00
-#define ISP16_DMA_5 0x00
-#define ISP16_DMA_6 0x01
-#define ISP16_DMA_7 0x02
-#define ISP16_IO_SET_MASK 0x20 /* don't change 5-bit */
-/* ...for port */
-#define ISP16_IO_SET_PORT 0xF8E
-/* enable the card */
-#define ISP16_C928__ENABLE_PORT 0xF90 /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__ENABLE_PORT 0xF91 /* ISP16 with OPTi 82C929 chip */
-#define ISP16_ENABLE_CDROM 0x80 /* seven bit */
-
-/* the magic stuff */
-#define ISP16_CTRL_PORT 0xF8F
-#define ISP16_C928__CTRL 0xE2 /* ISP16 with OPTi 82C928 chip */
-#define ISP16_C929__CTRL 0xE3 /* ISP16 with OPTi 82C929 chip */
-
-#define ISP16_IO_BASE 0xF8D
-#define ISP16_IO_SIZE 5 /* ports used from 0xF8D up to 0xF91 */
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
deleted file mode 100644
index f574962f428..00000000000
--- a/drivers/cdrom/mcdx.c
+++ /dev/null
@@ -1,1943 +0,0 @@
-/*
- * The Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.14(hs)
- *
- * ... anyway, I'm back again, thanks to Marcin, he adopted
- * large portions of my code (at least the parts containing
- * my main thoughts ...)
- *
- ****************** H E L P *********************************
- * If you ever plan to update your CD ROM drive and perhaps
- * want to sell or simply give away your Mitsumi FX-001[DS]
- * -- Please --
- * mail me (heiko@lotte.sax.de). When my last drive goes
- * ballistic no more driver support will be available from me!
- *************************************************************
- *
- * This program is free software; you can redistribute 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- * The Linux Community at all and ...
- * Martin Harriss (he wrote the first Mitsumi Driver)
- * Eberhard Moenkeberg (he gave me much support and the initial kick)
- * Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
- * improved the original driver)
- * Jon Tombs, Bjorn Ekwall (module support)
- * Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- * Gerd Knorr (he lent me his PhotoCD)
- * Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- * Andreas Kies (testing the mysterious hang-ups)
- * Heiko Eissfeldt (VERIFY_READ/WRITE)
- * Marcin Dalecki (improved performance, shortened code)
- * ... somebody forgotten?
- *
- * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- */
-
-
-#ifdef RCS
-static const char *mcdx_c_version
- = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $";
-#endif
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-
-#include <linux/major.h>
-#define MAJOR_NR MITSUMI_X_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#include "mcdx.h"
-
-#ifndef HZ
-#error HZ not defined
-#endif
-
-#define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args)
-
-#if !MCDX_QUIET
-#define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args)
-#else
-#define xinfo(fmt, args...) { ; }
-#endif
-
-#if MCDX_DEBUG
-#define xtrace(lvl, fmt, args...) \
- { if (lvl > 0) \
- { printk(KERN_DEBUG MCDX ":: " fmt, ## args); } }
-#define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args)
-#else
-#define xtrace(lvl, fmt, args...) { ; }
-#define xdebug(fmt, args...) { ; }
-#endif
-
-/* CONSTANTS *******************************************************/
-
-/* Following are the number of sectors we _request_ from the drive
- every time an access outside the already requested range is done.
- The _direct_ size is the number of sectors we're allowed to skip
- directly (performing a read instead of requesting the new sector
- needed */
-static const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */
-static const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */
-
-enum drivemodes { TOC, DATA, RAW, COOKED };
-enum datamodes { MODE0, MODE1, MODE2 };
-enum resetmodes { SOFT, HARD };
-
-static const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */
-static const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */
-static const int DOOR = 0x04; /* door locking capability */
-static const int MULTI = 0x08; /* multi session capability */
-
-static const unsigned char READ1X = 0xc0;
-static const unsigned char READ2X = 0xc1;
-
-
-/* DECLARATIONS ****************************************************/
-struct s_subqcode {
- unsigned char control;
- unsigned char tno;
- unsigned char index;
- struct cdrom_msf0 tt;
- struct cdrom_msf0 dt;
-};
-
-struct s_diskinfo {
- unsigned int n_first;
- unsigned int n_last;
- struct cdrom_msf0 msf_leadout;
- struct cdrom_msf0 msf_first;
-};
-
-struct s_multi {
- unsigned char multi;
- struct cdrom_msf0 msf_last;
-};
-
-struct s_version {
- unsigned char code;
- unsigned char ver;
-};
-
-/* Per drive/controller stuff **************************************/
-
-struct s_drive_stuff {
- /* waitqueues */
- wait_queue_head_t busyq;
- wait_queue_head_t lockq;
- wait_queue_head_t sleepq;
-
- /* flags */
- volatile int introk; /* status of last irq operation */
- volatile int busy; /* drive performs an operation */
- volatile int lock; /* exclusive usage */
-
- /* cd infos */
- struct s_diskinfo di;
- struct s_multi multi;
- struct s_subqcode *toc; /* first entry of the toc array */
- struct s_subqcode start;
- struct s_subqcode stop;
- int xa; /* 1 if xa disk */
- int audio; /* 1 if audio disk */
- int audiostatus;
-
- /* `buffer' control */
- volatile int valid; /* pending, ..., values are valid */
- volatile int pending; /* next sector to be read */
- volatile int low_border; /* first sector not to be skipped direct */
- volatile int high_border; /* first sector `out of area' */
-#ifdef AK2
- volatile int int_err;
-#endif /* AK2 */
-
- /* adds and odds */
- unsigned wreg_data; /* w data */
- unsigned wreg_reset; /* w hardware reset */
- unsigned wreg_hcon; /* w hardware conf */
- unsigned wreg_chn; /* w channel */
- unsigned rreg_data; /* r data */
- unsigned rreg_status; /* r status */
-
- int irq; /* irq used by this drive */
- int present; /* drive present and its capabilities */
- unsigned char readcmd; /* read cmd depends on single/double speed */
- unsigned char playcmd; /* play should always be single speed */
- unsigned int xxx; /* set if changed, reset while open */
- unsigned int yyy; /* set if changed, reset by media_changed */
- int users; /* keeps track of open/close */
- int lastsector; /* last block accessible */
- int status; /* last operation's error / status */
- int readerrs; /* # of blocks read w/o error */
- struct cdrom_device_info info;
- struct gendisk *disk;
-};
-
-
-/* Prototypes ******************************************************/
-
-/* The following prototypes are already declared elsewhere. They are
- repeated here to show what's going on. And to sense, if they're
- changed elsewhere. */
-
-static int mcdx_init(void);
-
-static int mcdx_block_open(struct inode *inode, struct file *file)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_open(&p->info, inode, file);
-}
-
-static int mcdx_block_release(struct inode *inode, struct file *file)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_release(&p->info, file);
-}
-
-static int mcdx_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_ioctl(file, &p->info, inode, cmd, arg);
-}
-
-static int mcdx_block_media_changed(struct gendisk *disk)
-{
- struct s_drive_stuff *p = disk->private_data;
- return cdrom_media_changed(&p->info);
-}
-
-static struct block_device_operations mcdx_bdops =
-{
- .owner = THIS_MODULE,
- .open = mcdx_block_open,
- .release = mcdx_block_release,
- .ioctl = mcdx_block_ioctl,
- .media_changed = mcdx_block_media_changed,
-};
-
-
-/* Indirect exported functions. These functions are exported by their
- addresses, such as mcdx_open and mcdx_close in the
- structure mcdx_dops. */
-
-/* exported by file_ops */
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose);
-static void mcdx_close(struct cdrom_device_info *cdi);
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr);
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position);
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock);
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg);
-
-/* misc internal support functions */
-static void log2msf(unsigned int, struct cdrom_msf0 *);
-static unsigned int msf2log(const struct cdrom_msf0 *);
-static unsigned int uint2bcd(unsigned int);
-static unsigned int bcd2uint(unsigned char);
-static unsigned port(int *);
-static int irq(int *);
-static void mcdx_delay(struct s_drive_stuff *, long jifs);
-static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
- int nr_sectors);
-static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector,
- int nr_sectors);
-
-static int mcdx_config(struct s_drive_stuff *, int);
-static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *,
- int);
-static int mcdx_stop(struct s_drive_stuff *, int);
-static int mcdx_hold(struct s_drive_stuff *, int);
-static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int);
-static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int);
-static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int);
-static int mcdx_requestsubqcode(struct s_drive_stuff *,
- struct s_subqcode *, int);
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *,
- struct s_multi *, int);
-static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *,
- int);
-static int mcdx_getstatus(struct s_drive_stuff *, int);
-static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *);
-static int mcdx_talk(struct s_drive_stuff *,
- const unsigned char *cmd, size_t,
- void *buffer, size_t size, unsigned int timeout, int);
-static int mcdx_readtoc(struct s_drive_stuff *);
-static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *);
-static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *);
-static int mcdx_setattentuator(struct s_drive_stuff *,
- struct cdrom_volctrl *, int);
-
-/* static variables ************************************************/
-
-static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
-static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
-static DEFINE_SPINLOCK(mcdx_lock);
-static struct request_queue *mcdx_queue;
-
-/* You can only set the first two pairs, from old MODULE_PARM code. */
-static int mcdx_set(const char *val, struct kernel_param *kp)
-{
- get_options((char *)val, 4, (int *)mcdx_drive_map);
- return 0;
-}
-module_param_call(mcdx, mcdx_set, NULL, NULL, 0);
-
-static struct cdrom_device_ops mcdx_dops = {
- .open = mcdx_open,
- .release = mcdx_close,
- .media_changed = mcdx_media_changed,
- .tray_move = mcdx_tray_move,
- .lock_door = mcdx_lockdoor,
- .audio_ioctl = mcdx_audio_ioctl,
- .capability = CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED |
- CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
-};
-
-/* KERNEL INTERFACE FUNCTIONS **************************************/
-
-
-static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
- unsigned int cmd, void *arg)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
-
- if (!stuffp->present)
- return -ENXIO;
-
- if (stuffp->xxx) {
- if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
- stuffp->lastsector = -1;
- } else {
- stuffp->lastsector = (CD_FRAMESIZE / 512)
- * msf2log(&stuffp->di.msf_leadout) - 1;
- }
-
- if (stuffp->toc) {
- kfree(stuffp->toc);
- stuffp->toc = NULL;
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
- }
-
- stuffp->xxx = 0;
- }
-
- switch (cmd) {
- case CDROMSTART:{
- xtrace(IOCTL, "ioctl() START\n");
- /* Spin up the drive. Don't think we can do this.
- * For now, ignore it.
- */
- return 0;
- }
-
- case CDROMSTOP:{
- xtrace(IOCTL, "ioctl() STOP\n");
- stuffp->audiostatus = CDROM_AUDIO_INVALID;
- if (-1 == mcdx_stop(stuffp, 1))
- return -EIO;
- return 0;
- }
-
- case CDROMPLAYTRKIND:{
- struct cdrom_ti *ti = (struct cdrom_ti *) arg;
-
- xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
- if ((ti->cdti_trk0 < stuffp->di.n_first)
- || (ti->cdti_trk0 > stuffp->di.n_last)
- || (ti->cdti_trk1 < stuffp->di.n_first))
- return -EINVAL;
- if (ti->cdti_trk1 > stuffp->di.n_last)
- ti->cdti_trk1 = stuffp->di.n_last;
- xtrace(PLAYTRK, "ioctl() track %d to %d\n",
- ti->cdti_trk0, ti->cdti_trk1);
- return mcdx_playtrk(stuffp, ti);
- }
-
- case CDROMPLAYMSF:{
- struct cdrom_msf *msf = (struct cdrom_msf *) arg;
-
- xtrace(IOCTL, "ioctl() PLAYMSF\n");
-
- if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
- && (-1 == mcdx_hold(stuffp, 1)))
- return -EIO;
-
- msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
- msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
- msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
-
- msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
- msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
- msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
-
- stuffp->stop.dt.minute = msf->cdmsf_min1;
- stuffp->stop.dt.second = msf->cdmsf_sec1;
- stuffp->stop.dt.frame = msf->cdmsf_frame1;
-
- return mcdx_playmsf(stuffp, msf);
- }
-
- case CDROMRESUME:{
- xtrace(IOCTL, "ioctl() RESUME\n");
- return mcdx_playtrk(stuffp, NULL);
- }
-
- case CDROMREADTOCENTRY:{
- struct cdrom_tocentry *entry =
- (struct cdrom_tocentry *) arg;
- struct s_subqcode *tp = NULL;
- xtrace(IOCTL, "ioctl() READTOCENTRY\n");
-
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
- if (entry->cdte_track == CDROM_LEADOUT)
- tp = &stuffp->toc[stuffp->di.n_last -
- stuffp->di.n_first + 1];
- else if (entry->cdte_track > stuffp->di.n_last
- || entry->cdte_track < stuffp->di.n_first)
- return -EINVAL;
- else
- tp = &stuffp->toc[entry->cdte_track -
- stuffp->di.n_first];
-
- if (NULL == tp)
- return -EIO;
- entry->cdte_adr = tp->control;
- entry->cdte_ctrl = tp->control >> 4;
- /* Always return stuff in MSF, and let the Uniform cdrom driver
- worry about what the user actually wants */
- entry->cdte_addr.msf.minute =
- bcd2uint(tp->dt.minute);
- entry->cdte_addr.msf.second =
- bcd2uint(tp->dt.second);
- entry->cdte_addr.msf.frame =
- bcd2uint(tp->dt.frame);
- return 0;
- }
-
- case CDROMSUBCHNL:{
- struct cdrom_subchnl *sub =
- (struct cdrom_subchnl *) arg;
- struct s_subqcode q;
-
- xtrace(IOCTL, "ioctl() SUBCHNL\n");
-
- if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
- return -EIO;
-
- xtrace(SUBCHNL, "audiostatus: %x\n",
- stuffp->audiostatus);
- sub->cdsc_audiostatus = stuffp->audiostatus;
- sub->cdsc_adr = q.control;
- sub->cdsc_ctrl = q.control >> 4;
- sub->cdsc_trk = bcd2uint(q.tno);
- sub->cdsc_ind = bcd2uint(q.index);
-
- xtrace(SUBCHNL, "trk %d, ind %d\n",
- sub->cdsc_trk, sub->cdsc_ind);
- /* Always return stuff in MSF, and let the Uniform cdrom driver
- worry about what the user actually wants */
- sub->cdsc_absaddr.msf.minute =
- bcd2uint(q.dt.minute);
- sub->cdsc_absaddr.msf.second =
- bcd2uint(q.dt.second);
- sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
- sub->cdsc_reladdr.msf.minute =
- bcd2uint(q.tt.minute);
- sub->cdsc_reladdr.msf.second =
- bcd2uint(q.tt.second);
- sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
- xtrace(SUBCHNL,
- "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
- sub->cdsc_absaddr.msf.minute,
- sub->cdsc_absaddr.msf.second,
- sub->cdsc_absaddr.msf.frame,
- sub->cdsc_reladdr.msf.minute,
- sub->cdsc_reladdr.msf.second,
- sub->cdsc_reladdr.msf.frame);
-
- return 0;
- }
-
- case CDROMREADTOCHDR:{
- struct cdrom_tochdr *toc =
- (struct cdrom_tochdr *) arg;
-
- xtrace(IOCTL, "ioctl() READTOCHDR\n");
- toc->cdth_trk0 = stuffp->di.n_first;
- toc->cdth_trk1 = stuffp->di.n_last;
- xtrace(TOCHDR,
- "ioctl() track0 = %d, track1 = %d\n",
- stuffp->di.n_first, stuffp->di.n_last);
- return 0;
- }
-
- case CDROMPAUSE:{
- xtrace(IOCTL, "ioctl() PAUSE\n");
- if (stuffp->audiostatus != CDROM_AUDIO_PLAY)
- return -EINVAL;
- if (-1 == mcdx_stop(stuffp, 1))
- return -EIO;
- stuffp->audiostatus = CDROM_AUDIO_PAUSED;
- if (-1 ==
- mcdx_requestsubqcode(stuffp, &stuffp->start,
- 1))
- return -EIO;
- return 0;
- }
-
- case CDROMMULTISESSION:{
- struct cdrom_multisession *ms =
- (struct cdrom_multisession *) arg;
- xtrace(IOCTL, "ioctl() MULTISESSION\n");
- /* Always return stuff in LBA, and let the Uniform cdrom driver
- worry about what the user actually wants */
- ms->addr.lba = msf2log(&stuffp->multi.msf_last);
- ms->xa_flag = !!stuffp->multi.multi;
- xtrace(MS,
- "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
- ms->xa_flag, ms->addr.lba,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
-
- return 0;
- }
-
- case CDROMEJECT:{
- xtrace(IOCTL, "ioctl() EJECT\n");
- if (stuffp->users > 1)
- return -EBUSY;
- return (mcdx_tray_move(cdi, 1));
- }
-
- case CDROMCLOSETRAY:{
- xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
- return (mcdx_tray_move(cdi, 0));
- }
-
- case CDROMVOLCTRL:{
- struct cdrom_volctrl *volctrl =
- (struct cdrom_volctrl *) arg;
- xtrace(IOCTL, "ioctl() VOLCTRL\n");
-
-#if 0 /* not tested! */
- /* adjust for the weirdness of workman (md) */
- /* can't test it (hs) */
- volctrl.channel2 = volctrl.channel1;
- volctrl.channel1 = volctrl.channel3 = 0x00;
-#endif
- return mcdx_setattentuator(stuffp, volctrl, 2);
- }
-
- default:
- return -EINVAL;
- }
-}
-
-static void do_mcdx_request(request_queue_t * q)
-{
- struct s_drive_stuff *stuffp;
- struct request *req;
-
- again:
-
- req = elv_next_request(q);
- if (!req)
- return;
-
- stuffp = req->rq_disk->private_data;
-
- if (!stuffp->present) {
- xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name);
- xtrace(REQUEST, "end_request(0): bad device\n");
- end_request(req, 0);
- return;
- }
-
- if (stuffp->audio) {
- xwarn("do_request() attempt to read from audio cd\n");
- xtrace(REQUEST, "end_request(0): read from audio\n");
- end_request(req, 0);
- return;
- }
-
- xtrace(REQUEST, "do_request() (%lu + %lu)\n",
- req->sector, req->nr_sectors);
-
- if (req->cmd != READ) {
- xwarn("do_request(): non-read command to cd!!\n");
- xtrace(REQUEST, "end_request(0): write\n");
- end_request(req, 0);
- return;
- }
- else {
- stuffp->status = 0;
- while (req->nr_sectors) {
- int i;
-
- i = mcdx_transfer(stuffp,
- req->buffer,
- req->sector,
- req->nr_sectors);
-
- if (i == -1) {
- end_request(req, 0);
- goto again;
- }
- req->sector += i;
- req->nr_sectors -= i;
- req->buffer += (i * 512);
- }
- end_request(req, 1);
- goto again;
-
- xtrace(REQUEST, "end_request(1)\n");
- end_request(req, 1);
- }
-
- goto again;
-}
-
-static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
-{
- struct s_drive_stuff *stuffp;
- xtrace(OPENCLOSE, "open()\n");
- stuffp = cdi->handle;
- if (!stuffp->present)
- return -ENXIO;
-
- /* Make the modules looking used ... (thanx bjorn).
- * But we shouldn't forget to decrement the module counter
- * on error return */
-
- /* this is only done to test if the drive talks with us */
- if (-1 == mcdx_getstatus(stuffp, 1))
- return -EIO;
-
- if (stuffp->xxx) {
-
- xtrace(OPENCLOSE, "open() media changed\n");
- stuffp->audiostatus = CDROM_AUDIO_INVALID;
- stuffp->readcmd = 0;
- xtrace(OPENCLOSE, "open() Request multisession info\n");
- if (-1 ==
- mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6))
- xinfo("No multidiskinfo\n");
- } else {
- /* multisession ? */
- if (!stuffp->multi.multi)
- stuffp->multi.msf_last.second = 2;
-
- xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
- stuffp->multi.multi,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
-
- {;
- } /* got multisession information */
- /* request the disks table of contents (aka diskinfo) */
- if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-
- stuffp->lastsector = -1;
-
- } else {
-
- stuffp->lastsector = (CD_FRAMESIZE / 512)
- * msf2log(&stuffp->di.msf_leadout) - 1;
-
- xtrace(OPENCLOSE,
- "open() start %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_first,
- stuffp->di.msf_first.minute,
- stuffp->di.msf_first.second,
- stuffp->di.msf_first.frame,
- msf2log(&stuffp->di.msf_first));
- xtrace(OPENCLOSE,
- "open() last %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_last,
- stuffp->di.msf_leadout.minute,
- stuffp->di.msf_leadout.second,
- stuffp->di.msf_leadout.frame,
- msf2log(&stuffp->di.msf_leadout));
- }
-
- if (stuffp->toc) {
- xtrace(MALLOC, "open() free old toc @ %p\n",
- stuffp->toc);
- kfree(stuffp->toc);
-
- stuffp->toc = NULL;
- }
-
- xtrace(OPENCLOSE, "open() init irq generation\n");
- if (-1 == mcdx_config(stuffp, 1))
- return -EIO;
-#ifdef FALLBACK
- /* Set the read speed */
- xwarn("AAA %x AAA\n", stuffp->readcmd);
- if (stuffp->readerrs)
- stuffp->readcmd = READ1X;
- else
- stuffp->readcmd =
- stuffp->present | SINGLE ? READ1X : READ2X;
- xwarn("XXX %x XXX\n", stuffp->readcmd);
-#else
- stuffp->readcmd =
- stuffp->present | SINGLE ? READ1X : READ2X;
-#endif
-
- /* try to get the first sector, iff any ... */
- if (stuffp->lastsector >= 0) {
- char buf[512];
- int ans;
- int tries;
-
- stuffp->xa = 0;
- stuffp->audio = 0;
-
- for (tries = 6; tries; tries--) {
-
- stuffp->introk = 1;
-
- xtrace(OPENCLOSE, "open() try as %s\n",
- stuffp->xa ? "XA" : "normal");
- /* set data mode */
- if (-1 == (ans = mcdx_setdatamode(stuffp,
- stuffp->
- xa ?
- MODE2 :
- MODE1,
- 1))) {
- /* return -EIO; */
- stuffp->xa = 0;
- break;
- }
-
- if ((stuffp->audio = e_audio(ans)))
- break;
-
- while (0 ==
- (ans =
- mcdx_transfer(stuffp, buf, 0, 1)));
-
- if (ans == 1)
- break;
- stuffp->xa = !stuffp->xa;
- }
- }
- /* xa disks will be read in raw mode, others not */
- if (-1 == mcdx_setdrivemode(stuffp,
- stuffp->xa ? RAW : COOKED,
- 1))
- return -EIO;
- if (stuffp->audio) {
- xinfo("open() audio disk found\n");
- } else if (stuffp->lastsector >= 0) {
- xinfo("open() %s%s disk found\n",
- stuffp->xa ? "XA / " : "",
- stuffp->multi.
- multi ? "Multi Session" : "Single Session");
- }
- }
- stuffp->xxx = 0;
- stuffp->users++;
- return 0;
-}
-
-static void mcdx_close(struct cdrom_device_info *cdi)
-{
- struct s_drive_stuff *stuffp;
-
- xtrace(OPENCLOSE, "close()\n");
-
- stuffp = cdi->handle;
-
- --stuffp->users;
-}
-
-static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-/* Return: 1 if media changed since last call to this function
- 0 otherwise */
-{
- struct s_drive_stuff *stuffp;
-
- xinfo("mcdx_media_changed called for device %s\n", cdi->name);
-
- stuffp = cdi->handle;
- mcdx_getstatus(stuffp, 1);
-
- if (stuffp->yyy == 0)
- return 0;
-
- stuffp->yyy = 0;
- return 1;
-}
-
-#ifndef MODULE
-static int __init mcdx_setup(char *str)
-{
- int pi[4];
- (void) get_options(str, ARRAY_SIZE(pi), pi);
-
- if (pi[0] > 0)
- mcdx_drive_map[0][0] = pi[1];
- if (pi[0] > 1)
- mcdx_drive_map[0][1] = pi[2];
- return 1;
-}
-
-__setup("mcdx=", mcdx_setup);
-
-#endif
-
-/* DIRTY PART ******************************************************/
-
-static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
-/* This routine is used for sleeping.
- * A jifs value <0 means NO sleeping,
- * =0 means minimal sleeping (let the kernel
- * run for other processes)
- * >0 means at least sleep for that amount.
- * May be we could use a simple count loop w/ jumps to itself, but
- * I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
-{
- if (jifs < 0)
- return;
-
- xtrace(SLEEP, "*** delay: sleepq\n");
- interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
- xtrace(SLEEP, "delay awoken\n");
- if (signal_pending(current)) {
- xtrace(SLEEP, "got signal\n");
- }
-}
-
-static irqreturn_t mcdx_intr(int irq, void *dev_id)
-{
- struct s_drive_stuff *stuffp = dev_id;
- unsigned char b;
-
-#ifdef AK2
- if (!stuffp->busy && stuffp->pending)
- stuffp->int_err = 1;
-
-#endif /* AK2 */
- /* get the interrupt status */
- b = inb(stuffp->rreg_status);
- stuffp->introk = ~b & MCDX_RBIT_DTEN;
-
- /* NOTE: We only should get interrupts if the data we
- * requested are ready to transfer.
- * But the drive seems to generate ``asynchronous'' interrupts
- * on several error conditions too. (Despite the err int enable
- * setting during initialisation) */
-
- /* if not ok, read the next byte as the drives status */
- if (!stuffp->introk) {
- xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
- if (~b & MCDX_RBIT_STEN) {
- xinfo("intr() irq %d status 0x%02x\n",
- irq, inb(stuffp->rreg_data));
- } else {
- xinfo("intr() irq %d ambiguous hw status\n", irq);
- }
- } else {
- xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);
- }
-
- stuffp->busy = 0;
- wake_up_interruptible(&stuffp->busyq);
- return IRQ_HANDLED;
-}
-
-
-static int mcdx_talk(struct s_drive_stuff *stuffp,
- const unsigned char *cmd, size_t cmdlen,
- void *buffer, size_t size, unsigned int timeout, int tries)
-/* Send a command to the drive, wait for the result.
- * returns -1 on timeout, drive status otherwise
- * If buffer is not zero, the result (length size) is stored there.
- * If buffer is zero the size should be the number of bytes to read
- * from the drive. These bytes are discarded.
- */
-{
- int st;
- char c;
- int discard;
-
- /* Somebody wants the data read? */
- if ((discard = (buffer == NULL)))
- buffer = &c;
-
- while (stuffp->lock) {
- xtrace(SLEEP, "*** talk: lockq\n");
- interruptible_sleep_on(&stuffp->lockq);
- xtrace(SLEEP, "talk: awoken\n");
- }
-
- stuffp->lock = 1;
-
- /* An operation other then reading data destroys the
- * data already requested and remembered in stuffp->request, ... */
- stuffp->valid = 0;
-
-#if MCDX_DEBUG & TALK
- {
- unsigned char i;
- xtrace(TALK,
- "talk() %d / %d tries, res.size %d, command 0x%02x",
- tries, timeout, size, (unsigned char) cmd[0]);
- for (i = 1; i < cmdlen; i++)
- xtrace(TALK, " 0x%02x", cmd[i]);
- xtrace(TALK, "\n");
- }
-#endif
-
- /* give up if all tries are done (bad) or if the status
- * st != -1 (good) */
- for (st = -1; st == -1 && tries; tries--) {
-
- char *bp = (char *) buffer;
- size_t sz = size;
-
- outsb(stuffp->wreg_data, cmd, cmdlen);
- xtrace(TALK, "talk() command sent\n");
-
- /* get the status byte */
- if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
- xinfo("talk() %02x timed out (status), %d tr%s left\n",
- cmd[0], tries - 1, tries == 2 ? "y" : "ies");
- continue;
- }
- st = *bp;
- sz--;
- if (!discard)
- bp++;
-
- xtrace(TALK, "talk() got status 0x%02x\n", st);
-
- /* command error? */
- if (e_cmderr(st)) {
- xwarn("command error cmd = %02x %s \n",
- cmd[0], cmdlen > 1 ? "..." : "");
- st = -1;
- continue;
- }
-
- /* audio status? */
- if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
- stuffp->audiostatus =
- e_audiobusy(st) ? CDROM_AUDIO_PLAY :
- CDROM_AUDIO_NO_STATUS;
- else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
- && e_audiobusy(st) == 0)
- stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
-
- /* media change? */
- if (e_changed(st)) {
- xinfo("talk() media changed\n");
- stuffp->xxx = stuffp->yyy = 1;
- }
-
- /* now actually get the data */
- while (sz--) {
- if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
- xinfo("talk() %02x timed out (data), %d tr%s left\n",
- cmd[0], tries - 1,
- tries == 2 ? "y" : "ies");
- st = -1;
- break;
- }
- if (!discard)
- bp++;
- xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));
- }
- }
-
-#if !MCDX_QUIET
- if (!tries && st == -1)
- xinfo("talk() giving up\n");
-#endif
-
- stuffp->lock = 0;
- wake_up_interruptible(&stuffp->lockq);
-
- xtrace(TALK, "talk() done with 0x%02x\n", st);
- return st;
-}
-
-/* MODULE STUFF ***********************************************************/
-
-static int __init __mcdx_init(void)
-{
- int i;
- int drives = 0;
-
- mcdx_init();
- for (i = 0; i < MCDX_NDRIVES; i++) {
- if (mcdx_stuffp[i]) {
- xtrace(INIT, "init_module() drive %d stuff @ %p\n",
- i, mcdx_stuffp[i]);
- drives++;
- }
- }
-
- if (!drives)
- return -EIO;
-
- return 0;
-}
-
-static void __exit mcdx_exit(void)
-{
- int i;
-
- xinfo("cleanup_module called\n");
-
- for (i = 0; i < MCDX_NDRIVES; i++) {
- struct s_drive_stuff *stuffp = mcdx_stuffp[i];
- if (!stuffp)
- continue;
- del_gendisk(stuffp->disk);
- if (unregister_cdrom(&stuffp->info)) {
- printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
- continue;
- }
- put_disk(stuffp->disk);
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- free_irq(stuffp->irq, NULL);
- if (stuffp->toc) {
- xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
- stuffp->toc);
- kfree(stuffp->toc);
- }
- xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",
- stuffp);
- mcdx_stuffp[i] = NULL;
- kfree(stuffp);
- }
-
- if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
- xwarn("cleanup() unregister_blkdev() failed\n");
- }
- blk_cleanup_queue(mcdx_queue);
-#if !MCDX_QUIET
- else
- xinfo("cleanup() succeeded\n");
-#endif
-}
-
-#ifdef MODULE
-module_init(__mcdx_init);
-#endif
-module_exit(mcdx_exit);
-
-
-/* Support functions ************************************************/
-
-static int __init mcdx_init_drive(int drive)
-{
- struct s_version version;
- struct gendisk *disk;
- struct s_drive_stuff *stuffp;
- int size = sizeof(*stuffp);
- char msg[80];
-
- xtrace(INIT, "init() try drive %d\n", drive);
-
- xtrace(INIT, "kmalloc space for stuffpt's\n");
- xtrace(MALLOC, "init() malloc %d bytes\n", size);
- if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
- xwarn("init() malloc failed\n");
- return 1;
- }
-
- disk = alloc_disk(1);
- if (!disk) {
- xwarn("init() malloc failed\n");
- kfree(stuffp);
- return 1;
- }
-
- xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
- sizeof(*stuffp), stuffp);
-
- /* set default values */
- stuffp->present = 0; /* this should be 0 already */
- stuffp->toc = NULL; /* this should be NULL already */
-
- /* setup our irq and i/o addresses */
- stuffp->irq = irq(mcdx_drive_map[drive]);
- stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
- stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
- stuffp->wreg_hcon = stuffp->wreg_reset + 1;
- stuffp->wreg_chn = stuffp->wreg_hcon + 1;
-
- init_waitqueue_head(&stuffp->busyq);
- init_waitqueue_head(&stuffp->lockq);
- init_waitqueue_head(&stuffp->sleepq);
-
- /* check if i/o addresses are available */
- if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
- xwarn("0x%03x,%d: Init failed. "
- "I/O ports (0x%03x..0x%03x) already in use.\n",
- stuffp->wreg_data, stuffp->irq,
- stuffp->wreg_data,
- stuffp->wreg_data + MCDX_IO_SIZE - 1);
- xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
- kfree(stuffp);
- put_disk(disk);
- xtrace(INIT, "init() continue at next drive\n");
- return 0; /* next drive */
- }
-
- xtrace(INIT, "init() i/o port is available at 0x%03x\n"
- stuffp->wreg_data);
- xtrace(INIT, "init() hardware reset\n");
- mcdx_reset(stuffp, HARD, 1);
-
- xtrace(INIT, "init() get version\n");
- if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
- /* failed, next drive */
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
- MCDX, stuffp->wreg_data, stuffp->irq);
- xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
- kfree(stuffp);
- put_disk(disk);
- xtrace(INIT, "init() continue at next drive\n");
- return 0;
- }
-
- switch (version.code) {
- case 'D':
- stuffp->readcmd = READ2X;
- stuffp->present = DOUBLE | DOOR | MULTI;
- break;
- case 'F':
- stuffp->readcmd = READ1X;
- stuffp->present = SINGLE | DOOR | MULTI;
- break;
- case 'M':
- stuffp->readcmd = READ1X;
- stuffp->present = SINGLE;
- break;
- default:
- stuffp->present = 0;
- break;
- }
-
- stuffp->playcmd = READ1X;
-
- if (!stuffp->present) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
- MCDX, stuffp->wreg_data, stuffp->irq);
- kfree(stuffp);
- put_disk(disk);
- return 0; /* next drive */
- }
-
- xtrace(INIT, "init() register blkdev\n");
- if (register_blkdev(MAJOR_NR, "mcdx")) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- return 1;
- }
-
- mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
- if (!mcdx_queue) {
- unregister_blkdev(MAJOR_NR, "mcdx");
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- return 1;
- }
-
- xtrace(INIT, "init() subscribe irq and i/o\n");
- if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) {
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
- MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
- stuffp->irq = 0;
- blk_cleanup_queue(mcdx_queue);
- kfree(stuffp);
- put_disk(disk);
- return 0;
- }
-
- xtrace(INIT, "init() get garbage\n");
- {
- int i;
- mcdx_delay(stuffp, HZ / 2);
- for (i = 100; i; i--)
- (void) inb(stuffp->rreg_status);
- }
-
-
-#ifdef WE_KNOW_WHY
- /* irq 11 -> channel register */
- outb(0x50, stuffp->wreg_chn);
-#endif
-
- xtrace(INIT, "init() set non dma but irq mode\n");
- mcdx_config(stuffp, 1);
-
- stuffp->info.ops = &mcdx_dops;
- stuffp->info.speed = 2;
- stuffp->info.capacity = 1;
- stuffp->info.handle = stuffp;
- sprintf(stuffp->info.name, "mcdx%d", drive);
- disk->major = MAJOR_NR;
- disk->first_minor = drive;
- strcpy(disk->disk_name, stuffp->info.name);
- disk->fops = &mcdx_bdops;
- disk->flags = GENHD_FL_CD;
- stuffp->disk = disk;
-
- sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
- " (Firmware version %c %x)\n",
- stuffp->wreg_data, stuffp->irq, version.code, version.ver);
- mcdx_stuffp[drive] = stuffp;
- xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
- if (register_cdrom(&stuffp->info) != 0) {
- printk("Cannot register Mitsumi CD-ROM!\n");
- free_irq(stuffp->irq, NULL);
- release_region(stuffp->wreg_data, MCDX_IO_SIZE);
- kfree(stuffp);
- put_disk(disk);
- if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
- xwarn("cleanup() unregister_blkdev() failed\n");
- blk_cleanup_queue(mcdx_queue);
- return 2;
- }
- disk->private_data = stuffp;
- disk->queue = mcdx_queue;
- add_disk(disk);
- printk(msg);
- return 0;
-}
-
-static int __init mcdx_init(void)
-{
- int drive;
- xwarn("Version 2.14(hs) \n");
-
- xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
-
- /* zero the pointer array */
- for (drive = 0; drive < MCDX_NDRIVES; drive++)
- mcdx_stuffp[drive] = NULL;
-
- /* do the initialisation */
- for (drive = 0; drive < MCDX_NDRIVES; drive++) {
- switch (mcdx_init_drive(drive)) {
- case 2:
- return -EIO;
- case 1:
- break;
- }
- }
- return 0;
-}
-
-static int mcdx_transfer(struct s_drive_stuff *stuffp,
- char *p, int sector, int nr_sectors)
-/* This seems to do the actually transfer. But it does more. It
- keeps track of errors occurred and will (if possible) fall back
- to single speed on error.
- Return: -1 on timeout or other error
- else status byte (as in stuff->st) */
-{
- int ans;
-
- ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
- return ans;
-#ifdef FALLBACK
- if (-1 == ans)
- stuffp->readerrs++;
- else
- return ans;
-
- if (stuffp->readerrs && stuffp->readcmd == READ1X) {
- xwarn("XXX Already reading 1x -- no chance\n");
- return -1;
- }
-
- xwarn("XXX Fallback to 1x\n");
-
- stuffp->readcmd = READ1X;
- return mcdx_transfer(stuffp, p, sector, nr_sectors);
-#endif
-
-}
-
-
-static int mcdx_xfer(struct s_drive_stuff *stuffp,
- char *p, int sector, int nr_sectors)
-/* This does actually the transfer from the drive.
- Return: -1 on timeout or other error
- else status byte (as in stuff->st) */
-{
- int border;
- int done = 0;
- long timeout;
-
- if (stuffp->audio) {
- xwarn("Attempt to read from audio CD.\n");
- return -1;
- }
-
- if (!stuffp->readcmd) {
- xinfo("Can't transfer from missing disk.\n");
- return -1;
- }
-
- while (stuffp->lock) {
- interruptible_sleep_on(&stuffp->lockq);
- }
-
- if (stuffp->valid && (sector >= stuffp->pending)
- && (sector < stuffp->low_border)) {
-
- /* All (or at least a part of the sectors requested) seems
- * to be already requested, so we don't need to bother the
- * drive with new requests ...
- * Wait for the drive become idle, but first
- * check for possible occurred errors --- the drive
- * seems to report them asynchronously */
-
-
- border = stuffp->high_border < (border =
- sector + nr_sectors)
- ? stuffp->high_border : border;
-
- stuffp->lock = current->pid;
-
- do {
-
- while (stuffp->busy) {
-
- timeout =
- interruptible_sleep_on_timeout
- (&stuffp->busyq, 5 * HZ);
-
- if (!stuffp->introk) {
- xtrace(XFER,
- "error via interrupt\n");
- } else if (!timeout) {
- xtrace(XFER, "timeout\n");
- } else if (signal_pending(current)) {
- xtrace(XFER, "signal\n");
- } else
- continue;
-
- stuffp->lock = 0;
- stuffp->busy = 0;
- stuffp->valid = 0;
-
- wake_up_interruptible(&stuffp->lockq);
- xtrace(XFER, "transfer() done (-1)\n");
- return -1;
- }
-
- /* check if we need to set the busy flag (as we
- * expect an interrupt */
- stuffp->busy = (3 == (stuffp->pending & 3));
-
- /* Test if it's the first sector of a block,
- * there we have to skip some bytes as we read raw data */
- if (stuffp->xa && (0 == (stuffp->pending & 3))) {
- const int HEAD =
- CD_FRAMESIZE_RAW - CD_XA_TAIL -
- CD_FRAMESIZE;
- insb(stuffp->rreg_data, p, HEAD);
- }
-
- /* now actually read the data */
- insb(stuffp->rreg_data, p, 512);
-
- /* test if it's the last sector of a block,
- * if so, we have to handle XA special */
- if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
- char dummy[CD_XA_TAIL];
- insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL);
- }
-
- if (stuffp->pending == sector) {
- p += 512;
- done++;
- sector++;
- }
- } while (++(stuffp->pending) < border);
-
- stuffp->lock = 0;
- wake_up_interruptible(&stuffp->lockq);
-
- } else {
-
- /* The requested sector(s) is/are out of the
- * already requested range, so we have to bother the drive
- * with a new request. */
-
- static unsigned char cmd[] = {
- 0,
- 0, 0, 0,
- 0, 0, 0
- };
-
- cmd[0] = stuffp->readcmd;
-
- /* The numbers held in ->pending, ..., should be valid */
- stuffp->valid = 1;
- stuffp->pending = sector & ~3;
-
- /* do some sanity checks */
- if (stuffp->pending > stuffp->lastsector) {
- xwarn
- ("transfer() sector %d from nirvana requested.\n",
- stuffp->pending);
- stuffp->status = MCDX_ST_EOM;
- stuffp->valid = 0;
- xtrace(XFER, "transfer() done (-1)\n");
- return -1;
- }
-
- if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
- > stuffp->lastsector + 1) {
- xtrace(XFER, "cut low_border\n");
- stuffp->low_border = stuffp->lastsector + 1;
- }
- if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
- > stuffp->lastsector + 1) {
- xtrace(XFER, "cut high_border\n");
- stuffp->high_border = stuffp->lastsector + 1;
- }
-
- { /* Convert the sector to be requested to MSF format */
- struct cdrom_msf0 pending;
- log2msf(stuffp->pending / 4, &pending);
- cmd[1] = pending.minute;
- cmd[2] = pending.second;
- cmd[3] = pending.frame;
- }
-
- cmd[6] =
- (unsigned
- char) ((stuffp->high_border - stuffp->pending) / 4);
- xtrace(XFER, "[%2d]\n", cmd[6]);
-
- stuffp->busy = 1;
- /* Now really issue the request command */
- outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
- }
-#ifdef AK2
- if (stuffp->int_err) {
- stuffp->valid = 0;
- stuffp->int_err = 0;
- return -1;
- }
-#endif /* AK2 */
-
- stuffp->low_border = (stuffp->low_border +=
- done) <
- stuffp->high_border ? stuffp->low_border : stuffp->high_border;
-
- return done;
-}
-
-
-/* Access to elements of the mcdx_drive_map members */
-
-static unsigned port(int *ip)
-{
- return ip[0];
-}
-static int irq(int *ip)
-{
- return ip[1];
-}
-
-/* Misc number converters */
-
-static unsigned int bcd2uint(unsigned char c)
-{
- return (c >> 4) * 10 + (c & 0x0f);
-}
-
-static unsigned int uint2bcd(unsigned int ival)
-{
- return ((ival / 10) << 4) | (ival % 10);
-}
-
-static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
-{
- l += CD_MSF_OFFSET;
- pmsf->minute = uint2bcd(l / 4500), l %= 4500;
- pmsf->second = uint2bcd(l / 75);
- pmsf->frame = uint2bcd(l % 75);
-}
-
-static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
-{
- return bcd2uint(pmsf->frame)
- + bcd2uint(pmsf->second) * 75
- + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
-}
-
-int mcdx_readtoc(struct s_drive_stuff *stuffp)
-/* Read the toc entries from the CD,
- * Return: -1 on failure, else 0 */
-{
-
- if (stuffp->toc) {
- xtrace(READTOC, "ioctl() toc already read\n");
- return 0;
- }
-
- xtrace(READTOC, "ioctl() readtoc for %d tracks\n",
- stuffp->di.n_last - stuffp->di.n_first + 1);
-
- if (-1 == mcdx_hold(stuffp, 1))
- return -1;
-
- xtrace(READTOC, "ioctl() tocmode\n");
- if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
- return -EIO;
-
- /* all seems to be ok so far ... malloc */
- {
- int size;
- size =
- sizeof(struct s_subqcode) * (stuffp->di.n_last -
- stuffp->di.n_first + 2);
-
- xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);
- stuffp->toc = kmalloc(size, GFP_KERNEL);
- if (!stuffp->toc) {
- xwarn("Cannot malloc %d bytes for toc\n", size);
- mcdx_setdrivemode(stuffp, DATA, 1);
- return -EIO;
- }
- }
-
- /* now read actually the index */
- {
- int trk;
- int retries;
-
- for (trk = 0;
- trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
- trk++)
- stuffp->toc[trk].index = 0;
-
- for (retries = 300; retries; retries--) { /* why 300? */
- struct s_subqcode q;
- unsigned int idx;
-
- if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
- mcdx_setdrivemode(stuffp, DATA, 1);
- return -EIO;
- }
-
- idx = bcd2uint(q.index);
-
- if ((idx > 0)
- && (idx <= stuffp->di.n_last)
- && (q.tno == 0)
- && (stuffp->toc[idx - stuffp->di.n_first].
- index == 0)) {
- stuffp->toc[idx - stuffp->di.n_first] = q;
- xtrace(READTOC,
- "ioctl() toc idx %d (trk %d)\n",
- idx, trk);
- trk--;
- }
- if (trk == 0)
- break;
- }
- memset(&stuffp->
- toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
- sizeof(stuffp->toc[0]));
- stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
- 1].dt = stuffp->di.msf_leadout;
- }
-
- /* unset toc mode */
- xtrace(READTOC, "ioctl() undo toc mode\n");
- if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
- return -EIO;
-
-#if MCDX_DEBUG && READTOC
- {
- int trk;
- for (trk = 0;
- trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
- trk++)
- xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
- " %02x:%02x.%02x %02x:%02x.%02x\n",
- trk + stuffp->di.n_first,
- stuffp->toc[trk].control,
- stuffp->toc[trk].tno,
- stuffp->toc[trk].index,
- stuffp->toc[trk].tt.minute,
- stuffp->toc[trk].tt.second,
- stuffp->toc[trk].tt.frame,
- stuffp->toc[trk].dt.minute,
- stuffp->toc[trk].dt.second,
- stuffp->toc[trk].dt.frame);
- }
-#endif
-
- return 0;
-}
-
-static int
-mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
-{
- unsigned char cmd[7] = {
- 0, 0, 0, 0, 0, 0, 0
- };
-
- if (!stuffp->readcmd) {
- xinfo("Can't play from missing disk.\n");
- return -1;
- }
-
- cmd[0] = stuffp->playcmd;
-
- cmd[1] = msf->cdmsf_min0;
- cmd[2] = msf->cdmsf_sec0;
- cmd[3] = msf->cdmsf_frame0;
- cmd[4] = msf->cdmsf_min1;
- cmd[5] = msf->cdmsf_sec1;
- cmd[6] = msf->cdmsf_frame1;
-
- xtrace(PLAYMSF, "ioctl(): play %x "
- "%02x:%02x:%02x -- %02x:%02x:%02x\n",
- cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
-
- outsb(stuffp->wreg_data, cmd, sizeof cmd);
-
- if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
- xwarn("playmsf() timeout\n");
- return -1;
- }
-
- stuffp->audiostatus = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-static int
-mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
-{
- struct s_subqcode *p;
- struct cdrom_msf msf;
-
- if (-1 == mcdx_readtoc(stuffp))
- return -1;
-
- if (ti)
- p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
- else
- p = &stuffp->start;
-
- msf.cdmsf_min0 = p->dt.minute;
- msf.cdmsf_sec0 = p->dt.second;
- msf.cdmsf_frame0 = p->dt.frame;
-
- if (ti) {
- p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
- stuffp->stop = *p;
- } else
- p = &stuffp->stop;
-
- msf.cdmsf_min1 = p->dt.minute;
- msf.cdmsf_sec1 = p->dt.second;
- msf.cdmsf_frame1 = p->dt.frame;
-
- return mcdx_playmsf(stuffp, &msf);
-}
-
-
-/* Drive functions ************************************************/
-
-static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
-
- if (!stuffp->present)
- return -ENXIO;
- if (!(stuffp->present & DOOR))
- return -ENOSYS;
-
- if (position) /* 1: eject */
- return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
- else /* 0: close */
- return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
- return 1;
-}
-
-static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries);
-}
-
-static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
- struct s_subqcode *sub, int tries)
-{
- char buf[11];
- int ans;
-
- if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf),
- 2 * HZ, tries)))
- return -1;
- sub->control = buf[1];
- sub->tno = buf[2];
- sub->index = buf[3];
- sub->tt.minute = buf[4];
- sub->tt.second = buf[5];
- sub->tt.frame = buf[6];
- sub->dt.minute = buf[8];
- sub->dt.second = buf[9];
- sub->dt.frame = buf[10];
-
- return ans;
-}
-
-static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
- struct s_multi *multi, int tries)
-{
- char buf[5];
- int ans;
-
- if (stuffp->present & MULTI) {
- ans =
- mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ,
- tries);
- multi->multi = buf[1];
- multi->msf_last.minute = buf[2];
- multi->msf_last.second = buf[3];
- multi->msf_last.frame = buf[4];
- return ans;
- } else {
- multi->multi = 0;
- return 0;
- }
-}
-
-static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
- int tries)
-{
- char buf[9];
- int ans;
- ans =
- mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);
- if (ans == -1) {
- info->n_first = 0;
- info->n_last = 0;
- } else {
- info->n_first = bcd2uint(buf[1]);
- info->n_last = bcd2uint(buf[2]);
- info->msf_leadout.minute = buf[3];
- info->msf_leadout.second = buf[4];
- info->msf_leadout.frame = buf[5];
- info->msf_first.minute = buf[6];
- info->msf_first.second = buf[7];
- info->msf_first.frame = buf[8];
- }
- return ans;
-}
-
-static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
- int tries)
-{
- char cmd[2];
- int ans;
-
- xtrace(HW, "setdrivemode() %d\n", mode);
-
- if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
- return -1;
-
- switch (mode) {
- case TOC:
- cmd[1] |= 0x04;
- break;
- case DATA:
- cmd[1] &= ~0x04;
- break;
- case RAW:
- cmd[1] |= 0x40;
- break;
- case COOKED:
- cmd[1] &= ~0x40;
- break;
- default:
- break;
- }
- cmd[0] = 0x50;
- return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
- int tries)
-{
- unsigned char cmd[2] = { 0xa0 };
- xtrace(HW, "setdatamode() %d\n", mode);
- switch (mode) {
- case MODE0:
- cmd[1] = 0x00;
- break;
- case MODE1:
- cmd[1] = 0x01;
- break;
- case MODE2:
- cmd[1] = 0x02;
- break;
- default:
- return -EINVAL;
- }
- return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
-{
- char cmd[4];
-
- xtrace(HW, "config()\n");
-
- cmd[0] = 0x90;
-
- cmd[1] = 0x10; /* irq enable */
- cmd[2] = 0x05; /* pre, err irq enable */
-
- if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
- return -1;
-
- cmd[1] = 0x02; /* dma select */
- cmd[2] = 0x00; /* no dma */
-
- return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
-}
-
-static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
- int tries)
-{
- char buf[3];
- int ans;
-
- if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
- 1, buf, sizeof(buf), 2 * HZ, tries)))
- return ans;
-
- ver->code = buf[1];
- ver->ver = buf[2];
-
- return ans;
-}
-
-static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
-{
- if (mode == HARD) {
- outb(0, stuffp->wreg_chn); /* no dma, no irq -> hardware */
- outb(0, stuffp->wreg_reset); /* hw reset */
- return 0;
- } else
- return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
-{
- struct s_drive_stuff *stuffp = cdi->handle;
- char cmd[2] = { 0xfe };
-
- if (!(stuffp->present & DOOR))
- return -ENOSYS;
- if (stuffp->present & DOOR) {
- cmd[1] = lock ? 0x01 : 0x00;
- return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
- } else
- return 0;
-}
-
-static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
-{
- return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries);
-}
-
-static int
-mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
-{
- unsigned long timeout = to + jiffies;
- char c;
-
- if (!buf)
- buf = &c;
-
- while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) {
- if (time_after(jiffies, timeout))
- return -1;
- mcdx_delay(stuffp, delay);
- }
-
- *buf = (unsigned char) inb(stuffp->rreg_data) & 0xff;
-
- return 0;
-}
-
-static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
- struct cdrom_volctrl *vol, int tries)
-{
- char cmd[5];
- cmd[0] = 0xae;
- cmd[1] = vol->channel0;
- cmd[2] = 0;
- cmd[3] = vol->channel1;
- cmd[4] = 0;
-
- return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR);
diff --git a/drivers/cdrom/mcdx.h b/drivers/cdrom/mcdx.h
deleted file mode 100644
index 83c364a74dc..00000000000
--- a/drivers/cdrom/mcdx.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Definitions for the Mitsumi CDROM interface
- * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: @VERSION@
- *
- * This program is free software; you can redistribute 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- * The Linux Community at all and ...
- * Martin Harris (he wrote the first Mitsumi Driver)
- * Eberhard Moenkeberg (he gave me much support and the initial kick)
- * Bernd Huebner, Ruediger Helsch (Unifix-Software Gmbh, they
- * improved the original driver)
- * Jon Tombs, Bjorn Ekwall (module support)
- * Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- * Gerd Knorr (he lent me his PhotoCD)
- * Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- * Andreas Kies (testing the mysterious hang up's)
- * ... somebody forgotten?
- * Marcin Dalecki
- *
- */
-
-/*
- * The following lines are for user configuration
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * {0|1} -- 1 if you want the driver detect your drive, may crash and
- * needs a long time to seek. The higher the address the longer the
- * seek.
- *
- * WARNING: AUTOPROBE doesn't work.
- */
-#define MCDX_AUTOPROBE 0
-
-/*
- * Drive specific settings according to the jumpers on the controller
- * board(s).
- * o MCDX_NDRIVES : number of used entries of the following table
- * o MCDX_DRIVEMAP : table of {i/o base, irq} per controller
- *
- * NOTE: I didn't get a drive at irq 9(2) working. Not even alone.
- */
-#if MCDX_AUTOPROBE == 0
- #define MCDX_NDRIVES 1
- #define MCDX_DRIVEMAP { \
- {0x300, 11}, \
- {0x304, 05}, \
- {0x000, 00}, \
- {0x000, 00}, \
- {0x000, 00}, \
- }
-#else
- #error Autoprobing is not implemented yet.
-#endif
-
-#ifndef MCDX_QUIET
-#define MCDX_QUIET 1
-#endif
-
-#ifndef MCDX_DEBUG
-#define MCDX_DEBUG 0
-#endif
-
-/* *** make the following line uncommented, if you're sure,
- * *** all configuration is done */
-/* #define I_WAS_HERE */
-
-/* The name of the device */
-#define MCDX "mcdx"
-
-/* Flags for DEBUGGING */
-#define INIT 0
-#define MALLOC 0
-#define IOCTL 0
-#define PLAYTRK 0
-#define SUBCHNL 0
-#define TOCHDR 0
-#define MS 0
-#define PLAYMSF 0
-#define READTOC 0
-#define OPENCLOSE 0
-#define HW 0
-#define TALK 0
-#define IRQ 0
-#define XFER 0
-#define REQUEST 0
-#define SLEEP 0
-
-/* The following addresses are taken from the Mitsumi Reference
- * and describe the possible i/o range for the controller.
- */
-#define MCDX_IO_BEGIN ((char*) 0x300) /* first base of i/o addr */
-#define MCDX_IO_END ((char*) 0x3fc) /* last base of i/o addr */
-
-/* Per controller 4 bytes i/o are needed. */
-#define MCDX_IO_SIZE 4
-
-/*
- * Bits
- */
-
-/* The status byte, returned from every command, set if
- * the description is true */
-#define MCDX_RBIT_OPEN 0x80 /* door is open */
-#define MCDX_RBIT_DISKSET 0x40 /* disk set (recognised) */
-#define MCDX_RBIT_CHANGED 0x20 /* disk was changed */
-#define MCDX_RBIT_CHECK 0x10 /* disk rotates, servo is on */
-#define MCDX_RBIT_AUDIOTR 0x08 /* current track is audio */
-#define MCDX_RBIT_RDERR 0x04 /* read error, refer SENSE KEY */
-#define MCDX_RBIT_AUDIOBS 0x02 /* currently playing audio */
-#define MCDX_RBIT_CMDERR 0x01 /* command, param or format error */
-
-/* The I/O Register holding the h/w status of the drive,
- * can be read at i/o base + 1 */
-#define MCDX_RBIT_DOOR 0x10 /* door is open */
-#define MCDX_RBIT_STEN 0x04 /* if 0, i/o base contains drive status */
-#define MCDX_RBIT_DTEN 0x02 /* if 0, i/o base contains data */
-
-/*
- * The commands.
- */
-
-#define OPCODE 1 /* offset of opcode */
-#define MCDX_CMD_REQUEST_TOC 1, 0x10
-#define MCDX_CMD_REQUEST_STATUS 1, 0x40
-#define MCDX_CMD_RESET 1, 0x60
-#define MCDX_CMD_REQUEST_DRIVE_MODE 1, 0xc2
-#define MCDX_CMD_SET_INTERLEAVE 2, 0xc8, 0
-#define MCDX_CMD_DATAMODE_SET 2, 0xa0, 0
- #define MCDX_DATAMODE1 0x01
- #define MCDX_DATAMODE2 0x02
-#define MCDX_CMD_LOCK_DOOR 2, 0xfe, 0
-
-#define READ_AHEAD 4 /* 8 Sectors (4K) */
-
-/* Useful macros */
-#define e_door(x) ((x) & MCDX_RBIT_OPEN)
-#define e_check(x) (~(x) & MCDX_RBIT_CHECK)
-#define e_notset(x) (~(x) & MCDX_RBIT_DISKSET)
-#define e_changed(x) ((x) & MCDX_RBIT_CHANGED)
-#define e_audio(x) ((x) & MCDX_RBIT_AUDIOTR)
-#define e_audiobusy(x) ((x) & MCDX_RBIT_AUDIOBS)
-#define e_cmderr(x) ((x) & MCDX_RBIT_CMDERR)
-#define e_readerr(x) ((x) & MCDX_RBIT_RDERR)
-
-/** no drive specific */
-#define MCDX_CDBLK 2048 /* 2048 cooked data each blk */
-
-#define MCDX_DATA_TIMEOUT (HZ/10) /* 0.1 second */
-
-/*
- * Access to the msf array
- */
-#define MSF_MIN 0 /* minute */
-#define MSF_SEC 1 /* second */
-#define MSF_FRM 2 /* frame */
-
-/*
- * Errors
- */
-#define MCDX_E 1 /* unspec error */
-#define MCDX_ST_EOM 0x0100 /* end of media */
-#define MCDX_ST_DRV 0x00ff /* mask to query the drive status */
-
-#ifndef I_WAS_HERE
-#ifndef MODULE
-#warning You have not edited mcdx.h
-#warning Perhaps irq and i/o settings are wrong.
-#endif
-#endif
-
-/* ex:set ts=4 sw=4: */
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
deleted file mode 100644
index 3541690a77d..00000000000
--- a/drivers/cdrom/optcd.c
+++ /dev/null
@@ -1,2105 +0,0 @@
-/* linux/drivers/cdrom/optcd.c - Optics Storage 8000 AT CDROM driver
- $Id: optcd.c,v 1.11 1997/01/26 07:13:00 davem Exp $
-
- Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
- Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
- by Eberhard Moenkeberg (emoenke@gwdg.de).
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, 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.
-*/
-
-/* Revision history
-
-
- 14-5-95 v0.0 Plays sound tracks. No reading of data CDs yet.
- Detection of disk change doesn't work.
- 21-5-95 v0.1 First ALPHA version. CD can be mounted. The
- device major nr is borrowed from the Aztech
- driver. Speed is around 240 kb/s, as measured
- with "time dd if=/dev/cdrom of=/dev/null \
- bs=2048 count=4096".
- 24-6-95 v0.2 Reworked the #defines for the command codes
- and the like, as well as the structure of
- the hardware communication protocol, to
- reflect the "official" documentation, kindly
- supplied by C.K. Tan, Optics Storage Pte. Ltd.
- Also tidied up the state machine somewhat.
- 28-6-95 v0.3 Removed the ISP-16 interface code, as this
- should go into its own driver. The driver now
- has its own major nr.
- Disk change detection now seems to work, too.
- This version became part of the standard
- kernel as of version 1.3.7
- 24-9-95 v0.4 Re-inserted ISP-16 interface code which I
- copied from sjcd.c, with a few changes.
- Updated README.optcd. Submitted for
- inclusion in 1.3.21
- 29-9-95 v0.4a Fixed bug that prevented compilation as module
- 25-10-95 v0.5 Started multisession code. Implementation
- copied from Werner Zimmermann, who copied it
- from Heiko Schlittermann's mcdx.
- 17-1-96 v0.6 Multisession works; some cleanup too.
- 18-4-96 v0.7 Increased some timing constants;
- thanks to Luke McFarlane. Also tidied up some
- printk behaviour. ISP16 initialization
- is now handled by a separate driver.
-
- 09-11-99 Make kernel-parameter implementation work with 2.3.x
- Removed init_module & cleanup_module in favor of
- module_init & module_exit.
- Torben Mathiasen <tmm@image.dk>
-*/
-
-/* Includes */
-
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <linux/blkdev.h>
-
-#include <linux/cdrom.h>
-#include "optcd.h"
-
-#include <asm/uaccess.h>
-
-#define MAJOR_NR OPTICS_CDROM_MAJOR
-#define QUEUE (opt_queue)
-#define CURRENT elv_next_request(opt_queue)
-
-
-/* Debug support */
-
-
-/* Don't forget to add new debug flags here. */
-#if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
- DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
-#define DEBUG(x) debug x
-static void debug(int debug_this, const char* fmt, ...)
-{
- char s[1024];
- va_list args;
-
- if (!debug_this)
- return;
-
- va_start(args, fmt);
- vsnprintf(s, sizeof(s), fmt, args);
- printk(KERN_DEBUG "optcd: %s\n", s);
- va_end(args);
-}
-#else
-#define DEBUG(x)
-#endif
-
-
-/* Drive hardware/firmware characteristics
- Identifiers in accordance with Optics Storage documentation */
-
-
-#define optcd_port optcd /* Needed for the modutils. */
-static short optcd_port = OPTCD_PORTBASE; /* I/O base of drive. */
-module_param(optcd_port, short, 0);
-/* Drive registers, read */
-#define DATA_PORT optcd_port /* Read data/status */
-#define STATUS_PORT optcd_port+1 /* Indicate data/status availability */
-
-/* Drive registers, write */
-#define COMIN_PORT optcd_port /* For passing command/parameter */
-#define RESET_PORT optcd_port+1 /* Write anything and wait 0.5 sec */
-#define HCON_PORT optcd_port+2 /* Host Xfer Configuration */
-
-
-/* Command completion/status read from DATA register */
-#define ST_DRVERR 0x80
-#define ST_DOOR_OPEN 0x40
-#define ST_MIXEDMODE_DISK 0x20
-#define ST_MODE_BITS 0x1c
-#define ST_M_STOP 0x00
-#define ST_M_READ 0x04
-#define ST_M_AUDIO 0x04
-#define ST_M_PAUSE 0x08
-#define ST_M_INITIAL 0x0c
-#define ST_M_ERROR 0x10
-#define ST_M_OTHERS 0x14
-#define ST_MODE2TRACK 0x02
-#define ST_DSK_CHG 0x01
-#define ST_L_LOCK 0x01
-#define ST_CMD_OK 0x00
-#define ST_OP_OK 0x01
-#define ST_PA_OK 0x02
-#define ST_OP_ERROR 0x05
-#define ST_PA_ERROR 0x06
-
-
-/* Error codes (appear as command completion code from DATA register) */
-/* Player related errors */
-#define ERR_ILLCMD 0x11 /* Illegal command to player module */
-#define ERR_ILLPARM 0x12 /* Illegal parameter to player module */
-#define ERR_SLEDGE 0x13
-#define ERR_FOCUS 0x14
-#define ERR_MOTOR 0x15
-#define ERR_RADIAL 0x16
-#define ERR_PLL 0x17 /* PLL lock error */
-#define ERR_SUB_TIM 0x18 /* Subcode timeout error */
-#define ERR_SUB_NF 0x19 /* Subcode not found error */
-#define ERR_TRAY 0x1a
-#define ERR_TOC 0x1b /* Table of Contents read error */
-#define ERR_JUMP 0x1c
-/* Data errors */
-#define ERR_MODE 0x21
-#define ERR_FORM 0x22
-#define ERR_HEADADDR 0x23 /* Header Address not found */
-#define ERR_CRC 0x24
-#define ERR_ECC 0x25 /* Uncorrectable ECC error */
-#define ERR_CRC_UNC 0x26 /* CRC error and uncorrectable error */
-#define ERR_ILLBSYNC 0x27 /* Illegal block sync error */
-#define ERR_VDST 0x28 /* VDST not found */
-/* Timeout errors */
-#define ERR_READ_TIM 0x31 /* Read timeout error */
-#define ERR_DEC_STP 0x32 /* Decoder stopped */
-#define ERR_DEC_TIM 0x33 /* Decoder interrupt timeout error */
-/* Function abort codes */
-#define ERR_KEY 0x41 /* Key -Detected abort */
-#define ERR_READ_FINISH 0x42 /* Read Finish */
-/* Second Byte diagnostic codes */
-#define ERR_NOBSYNC 0x01 /* No block sync */
-#define ERR_SHORTB 0x02 /* Short block */
-#define ERR_LONGB 0x03 /* Long block */
-#define ERR_SHORTDSP 0x04 /* Short DSP word */
-#define ERR_LONGDSP 0x05 /* Long DSP word */
-
-
-/* Status availability flags read from STATUS register */
-#define FL_EJECT 0x20
-#define FL_WAIT 0x10 /* active low */
-#define FL_EOP 0x08 /* active low */
-#define FL_STEN 0x04 /* Status available when low */
-#define FL_DTEN 0x02 /* Data available when low */
-#define FL_DRQ 0x01 /* active low */
-#define FL_RESET 0xde /* These bits are high after a reset */
-#define FL_STDT (FL_STEN|FL_DTEN)
-
-
-/* Transfer mode, written to HCON register */
-#define HCON_DTS 0x08
-#define HCON_SDRQB 0x04
-#define HCON_LOHI 0x02
-#define HCON_DMA16 0x01
-
-
-/* Drive command set, written to COMIN register */
-/* Quick response commands */
-#define COMDRVST 0x20 /* Drive Status Read */
-#define COMERRST 0x21 /* Error Status Read */
-#define COMIOCTLISTAT 0x22 /* Status Read; reset disk changed bit */
-#define COMINITSINGLE 0x28 /* Initialize Single Speed */
-#define COMINITDOUBLE 0x29 /* Initialize Double Speed */
-#define COMUNLOCK 0x30 /* Unlock */
-#define COMLOCK 0x31 /* Lock */
-#define COMLOCKST 0x32 /* Lock/Unlock Status */
-#define COMVERSION 0x40 /* Get Firmware Revision */
-#define COMVOIDREADMODE 0x50 /* Void Data Read Mode */
-/* Read commands */
-#define COMFETCH 0x60 /* Prefetch Data */
-#define COMREAD 0x61 /* Read */
-#define COMREADRAW 0x62 /* Read Raw Data */
-#define COMREADALL 0x63 /* Read All 2646 Bytes */
-/* Player control commands */
-#define COMLEADIN 0x70 /* Seek To Lead-in */
-#define COMSEEK 0x71 /* Seek */
-#define COMPAUSEON 0x80 /* Pause On */
-#define COMPAUSEOFF 0x81 /* Pause Off */
-#define COMSTOP 0x82 /* Stop */
-#define COMOPEN 0x90 /* Open Tray Door */
-#define COMCLOSE 0x91 /* Close Tray Door */
-#define COMPLAY 0xa0 /* Audio Play */
-#define COMPLAY_TNO 0xa2 /* Audio Play By Track Number */
-#define COMSUBQ 0xb0 /* Read Sub-q Code */
-#define COMLOCATION 0xb1 /* Read Head Position */
-/* Audio control commands */
-#define COMCHCTRL 0xc0 /* Audio Channel Control */
-/* Miscellaneous (test) commands */
-#define COMDRVTEST 0xd0 /* Write Test Bytes */
-#define COMTEST 0xd1 /* Diagnostic Test */
-
-/* Low level drive interface. Only here we do actual I/O
- Waiting for status / data available */
-
-
-/* Busy wait until FLAG goes low. Return 0 on timeout. */
-static inline int flag_low(int flag, unsigned long timeout)
-{
- int flag_high;
- unsigned long count = 0;
-
- while ((flag_high = (inb(STATUS_PORT) & flag)))
- if (++count >= timeout)
- break;
-
- DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
- flag, count, flag_high ? " timeout" : ""));
- return !flag_high;
-}
-
-
-/* Timed waiting for status or data */
-static int sleep_timeout; /* max # of ticks to sleep */
-static DECLARE_WAIT_QUEUE_HEAD(waitq);
-static void sleep_timer(unsigned long data);
-static DEFINE_TIMER(delay_timer, sleep_timer, 0, 0);
-static DEFINE_SPINLOCK(optcd_lock);
-static struct request_queue *opt_queue;
-
-/* Timer routine: wake up when desired flag goes low,
- or when timeout expires. */
-static void sleep_timer(unsigned long data)
-{
- int flags = inb(STATUS_PORT) & FL_STDT;
-
- if (flags == FL_STDT && --sleep_timeout > 0) {
- mod_timer(&delay_timer, jiffies + HZ/100); /* multi-statement macro */
- } else
- wake_up(&waitq);
-}
-
-
-/* Sleep until FLAG goes low. Return 0 on timeout or wrong flag low. */
-static int sleep_flag_low(int flag, unsigned long timeout)
-{
- int flag_high;
-
- DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
-
- sleep_timeout = timeout;
- flag_high = inb(STATUS_PORT) & flag;
- if (flag_high && sleep_timeout > 0) {
- mod_timer(&delay_timer, jiffies + HZ/100);
- sleep_on(&waitq);
- flag_high = inb(STATUS_PORT) & flag;
- }
-
- DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
- flag, timeout, flag_high ? " timeout" : ""));
- return !flag_high;
-}
-
-/* Low level drive interface. Only here we do actual I/O
- Sending commands and parameters */
-
-
-/* Errors in the command protocol */
-#define ERR_IF_CMD_TIMEOUT 0x100
-#define ERR_IF_ERR_TIMEOUT 0x101
-#define ERR_IF_RESP_TIMEOUT 0x102
-#define ERR_IF_DATA_TIMEOUT 0x103
-#define ERR_IF_NOSTAT 0x104
-
-
-/* Send command code. Return <0 indicates error */
-static int send_cmd(int cmd)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
-
- outb(HCON_DTS, HCON_PORT); /* Enable Suspend Data Transfer */
- outb(cmd, COMIN_PORT); /* Send command code */
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */
- return ack==ST_OP_OK ? 0 : -ack;
-}
-
-
-/* Send command parameters. Return <0 indicates error */
-static int send_params(struct cdrom_msf *params)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending parameters"
- " %02x:%02x:%02x"
- " %02x:%02x:%02x",
- params->cdmsf_min0,
- params->cdmsf_sec0,
- params->cdmsf_frame0,
- params->cdmsf_min1,
- params->cdmsf_sec1,
- params->cdmsf_frame1));
-
- outb(params->cdmsf_min0, COMIN_PORT);
- outb(params->cdmsf_sec0, COMIN_PORT);
- outb(params->cdmsf_frame0, COMIN_PORT);
- outb(params->cdmsf_min1, COMIN_PORT);
- outb(params->cdmsf_sec1, COMIN_PORT);
- outb(params->cdmsf_frame1, COMIN_PORT);
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Send parameters for SEEK command. Return <0 indicates error */
-static int send_seek_params(struct cdrom_msf *params)
-{
- unsigned char ack;
-
- DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
- " %02x:%02x:%02x",
- params->cdmsf_min0,
- params->cdmsf_sec0,
- params->cdmsf_frame0));
-
- outb(params->cdmsf_min0, COMIN_PORT);
- outb(params->cdmsf_sec0, COMIN_PORT);
- outb(params->cdmsf_frame0, COMIN_PORT);
- if (!flag_low(FL_STEN, BUSY_TIMEOUT)) /* Wait for status */
- return -ERR_IF_CMD_TIMEOUT;
- ack = inb(DATA_PORT); /* read command acknowledge */
- return ack==ST_PA_OK ? 0 : -ack;
-}
-
-
-/* Wait for command execution status. Choice between busy waiting
- and sleeping. Return value <0 indicates timeout. */
-static inline int get_exec_status(int busy_waiting)
-{
- unsigned char exec_status;
-
- if (busy_waiting
- ? !flag_low(FL_STEN, BUSY_TIMEOUT)
- : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
- return -ERR_IF_CMD_TIMEOUT;
-
- exec_status = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
- return exec_status;
-}
-
-
-/* Wait busy for extra byte of data that a command returns.
- Return value <0 indicates timeout. */
-static inline int get_data(int short_timeout)
-{
- unsigned char data;
-
- if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
- return -ERR_IF_DATA_TIMEOUT;
-
- data = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
- return data;
-}
-
-
-/* Returns 0 if failed */
-static int reset_drive(void)
-{
- unsigned long count = 0;
- int flags;
-
- DEBUG((DEBUG_DRIVE_IF, "reset drive"));
-
- outb(0, RESET_PORT);
- while (++count < RESET_WAIT)
- inb(DATA_PORT);
-
- count = 0;
- while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
- if (++count >= BUSY_TIMEOUT)
- break;
-
- DEBUG((DEBUG_DRIVE_IF, "reset %s",
- flags == FL_RESET ? "succeeded" : "failed"));
-
- if (flags != FL_RESET)
- return 0; /* Reset failed */
- outb(HCON_SDRQB, HCON_PORT); /* Disable Suspend Data Transfer */
- return 1; /* Reset succeeded */
-}
-
-
-/* Facilities for asynchronous operation */
-
-/* Read status/data availability flags FL_STEN and FL_DTEN */
-static inline int stdt_flags(void)
-{
- return inb(STATUS_PORT) & FL_STDT;
-}
-
-
-/* Fetch status that has previously been waited for. <0 means not available */
-static inline int fetch_status(void)
-{
- unsigned char status;
-
- if (inb(STATUS_PORT) & FL_STEN)
- return -ERR_IF_NOSTAT;
-
- status = inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
- return status;
-}
-
-
-/* Fetch data that has previously been waited for. */
-static inline void fetch_data(char *buf, int n)
-{
- insb(DATA_PORT, buf, n);
- DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
-}
-
-
-/* Flush status and data fifos */
-static inline void flush_data(void)
-{
- while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
- inb(DATA_PORT);
- DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
-}
-
-/* Command protocol */
-
-
-/* Send a simple command and wait for response. Command codes < COMFETCH
- are quick response commands */
-static inline int exec_cmd(int cmd)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- return get_exec_status(cmd < COMFETCH);
-}
-
-
-/* Send a command with parameters. Don't wait for the response,
- * which consists of data blocks read from the CD. */
-static inline int exec_read_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- return send_params(params);
-}
-
-
-/* Send a seek command with parameters and wait for response */
-static inline int exec_seek_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = send_cmd(cmd);
- if (ack < 0)
- return ack;
- ack = send_seek_params(params);
- if (ack < 0)
- return ack;
- return 0;
-}
-
-
-/* Send a command with parameters and wait for response */
-static inline int exec_long_cmd(int cmd, struct cdrom_msf *params)
-{
- int ack = exec_read_cmd(cmd, params);
- if (ack < 0)
- return ack;
- return get_exec_status(0);
-}
-
-/* Address conversion routines */
-
-
-/* Binary to BCD (2 digits) */
-static inline void single_bin2bcd(u_char *p)
-{
- DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
- *p = (*p % 10) | ((*p / 10) << 4);
-}
-
-
-/* Convert entire msf struct */
-static void bin2bcd(struct cdrom_msf *msf)
-{
- single_bin2bcd(&msf->cdmsf_min0);
- single_bin2bcd(&msf->cdmsf_sec0);
- single_bin2bcd(&msf->cdmsf_frame0);
- single_bin2bcd(&msf->cdmsf_min1);
- single_bin2bcd(&msf->cdmsf_sec1);
- single_bin2bcd(&msf->cdmsf_frame1);
-}
-
-
-/* Linear block address to minute, second, frame form */
-#define CD_FPM (CD_SECS * CD_FRAMES) /* frames per minute */
-
-static void lba2msf(int lba, struct cdrom_msf *msf)
-{
- DEBUG((DEBUG_CONV, "lba2msf %d", lba));
- lba += CD_MSF_OFFSET;
- msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM;
- msf->cdmsf_sec0 = lba / CD_FRAMES;
- msf->cdmsf_frame0 = lba % CD_FRAMES;
- msf->cdmsf_min1 = 0;
- msf->cdmsf_sec1 = 0;
- msf->cdmsf_frame1 = 0;
- bin2bcd(msf);
-}
-
-
-/* Two BCD digits to binary */
-static inline u_char bcd2bin(u_char bcd)
-{
- DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
- return (bcd >> 4) * 10 + (bcd & 0x0f);
-}
-
-
-static void msf2lba(union cdrom_addr *addr)
-{
- addr->lba = addr->msf.minute * CD_FPM
- + addr->msf.second * CD_FRAMES
- + addr->msf.frame - CD_MSF_OFFSET;
-}
-
-
-/* Minute, second, frame address BCD to binary or to linear address,
- depending on MODE */
-static void msf_bcd2bin(union cdrom_addr *addr)
-{
- addr->msf.minute = bcd2bin(addr->msf.minute);
- addr->msf.second = bcd2bin(addr->msf.second);
- addr->msf.frame = bcd2bin(addr->msf.frame);
-}
-
-/* High level drive commands */
-
-
-static int audio_status = CDROM_AUDIO_NO_STATUS;
-static char toc_uptodate = 0;
-static char disk_changed = 1;
-
-/* Get drive status, flagging completion of audio play and disk changes. */
-static int drive_status(void)
-{
- int status;
-
- status = exec_cmd(COMIOCTLISTAT);
- DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
- if (status < 0)
- return status;
- if (status == 0xff) /* No status available */
- return -ERR_IF_NOSTAT;
-
- if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
- (audio_status == CDROM_AUDIO_PLAY)) {
- audio_status = CDROM_AUDIO_COMPLETED;
- }
-
- if (status & ST_DSK_CHG) {
- toc_uptodate = 0;
- disk_changed = 1;
- audio_status = CDROM_AUDIO_NO_STATUS;
- }
-
- return status;
-}
-
-
-/* Read the current Q-channel info. Also used for reading the
- table of contents. qp->cdsc_format must be set on entry to
- indicate the desired address format */
-static int get_q_channel(struct cdrom_subchnl *qp)
-{
- int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
-
- status = drive_status();
- if (status < 0)
- return status;
- qp->cdsc_audiostatus = audio_status;
-
- status = exec_cmd(COMSUBQ);
- if (status < 0)
- return status;
-
- d1 = get_data(0);
- if (d1 < 0)
- return d1;
- qp->cdsc_adr = d1;
- qp->cdsc_ctrl = d1 >> 4;
-
- d2 = get_data(0);
- if (d2 < 0)
- return d2;
- qp->cdsc_trk = bcd2bin(d2);
-
- d3 = get_data(0);
- if (d3 < 0)
- return d3;
- qp->cdsc_ind = bcd2bin(d3);
-
- d4 = get_data(0);
- if (d4 < 0)
- return d4;
- qp->cdsc_reladdr.msf.minute = d4;
-
- d5 = get_data(0);
- if (d5 < 0)
- return d5;
- qp->cdsc_reladdr.msf.second = d5;
-
- d6 = get_data(0);
- if (d6 < 0)
- return d6;
- qp->cdsc_reladdr.msf.frame = d6;
-
- d7 = get_data(0);
- if (d7 < 0)
- return d7;
- /* byte not used */
-
- d8 = get_data(0);
- if (d8 < 0)
- return d8;
- qp->cdsc_absaddr.msf.minute = d8;
-
- d9 = get_data(0);
- if (d9 < 0)
- return d9;
- qp->cdsc_absaddr.msf.second = d9;
-
- d10 = get_data(0);
- if (d10 < 0)
- return d10;
- qp->cdsc_absaddr.msf.frame = d10;
-
- DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
- d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
-
- msf_bcd2bin(&qp->cdsc_absaddr);
- msf_bcd2bin(&qp->cdsc_reladdr);
- if (qp->cdsc_format == CDROM_LBA) {
- msf2lba(&qp->cdsc_absaddr);
- msf2lba(&qp->cdsc_reladdr);
- }
-
- return 0;
-}
-
-/* Table of contents handling */
-
-
-/* Errors in table of contents */
-#define ERR_TOC_MISSINGINFO 0x120
-#define ERR_TOC_MISSINGENTRY 0x121
-
-
-struct cdrom_disk_info {
- unsigned char first;
- unsigned char last;
- struct cdrom_msf0 disk_length;
- struct cdrom_msf0 first_track;
- /* Multisession info: */
- unsigned char next;
- struct cdrom_msf0 next_session;
- struct cdrom_msf0 last_session;
- unsigned char multi;
- unsigned char xa;
- unsigned char audio;
-};
-static struct cdrom_disk_info disk_info;
-
-#define MAX_TRACKS 111
-static struct cdrom_subchnl toc[MAX_TRACKS];
-
-#define QINFO_FIRSTTRACK 100 /* bcd2bin(0xa0) */
-#define QINFO_LASTTRACK 101 /* bcd2bin(0xa1) */
-#define QINFO_DISKLENGTH 102 /* bcd2bin(0xa2) */
-#define QINFO_NEXTSESSION 110 /* bcd2bin(0xb0) */
-
-#define I_FIRSTTRACK 0x01
-#define I_LASTTRACK 0x02
-#define I_DISKLENGTH 0x04
-#define I_NEXTSESSION 0x08
-#define I_ALL (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
-
-
-#if DEBUG_TOC
-static void toc_debug_info(int i)
-{
- printk(KERN_DEBUG "#%3d ctl %1x, adr %1x, track %2d index %3d"
- " %2d:%02d.%02d %2d:%02d.%02d\n",
- i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
- toc[i].cdsc_trk, toc[i].cdsc_ind,
- toc[i].cdsc_reladdr.msf.minute,
- toc[i].cdsc_reladdr.msf.second,
- toc[i].cdsc_reladdr.msf.frame,
- toc[i].cdsc_absaddr.msf.minute,
- toc[i].cdsc_absaddr.msf.second,
- toc[i].cdsc_absaddr.msf.frame);
-}
-#endif
-
-
-static int read_toc(void)
-{
- int status, limit, count;
- unsigned char got_info = 0;
- struct cdrom_subchnl q_info;
-#if DEBUG_TOC
- int i;
-#endif
-
- DEBUG((DEBUG_TOC, "starting read_toc"));
-
- count = 0;
- for (limit = 60; limit > 0; limit--) {
- int index;
-
- q_info.cdsc_format = CDROM_MSF;
- status = get_q_channel(&q_info);
- if (status < 0)
- return status;
-
- index = q_info.cdsc_ind;
- if (index > 0 && index < MAX_TRACKS
- && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
- toc[index] = q_info;
- DEBUG((DEBUG_TOC, "got %d", index));
- if (index < 100)
- count++;
-
- switch (q_info.cdsc_ind) {
- case QINFO_FIRSTTRACK:
- got_info |= I_FIRSTTRACK;
- break;
- case QINFO_LASTTRACK:
- got_info |= I_LASTTRACK;
- break;
- case QINFO_DISKLENGTH:
- got_info |= I_DISKLENGTH;
- break;
- case QINFO_NEXTSESSION:
- got_info |= I_NEXTSESSION;
- break;
- }
- }
-
- if ((got_info & I_ALL) == I_ALL
- && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
- >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
- break;
- }
-
- /* Construct disk_info from TOC */
- if (disk_info.first == 0) {
- disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
- disk_info.first_track.minute =
- toc[disk_info.first].cdsc_absaddr.msf.minute;
- disk_info.first_track.second =
- toc[disk_info.first].cdsc_absaddr.msf.second;
- disk_info.first_track.frame =
- toc[disk_info.first].cdsc_absaddr.msf.frame;
- }
- disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
- disk_info.disk_length.minute =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
- disk_info.disk_length.second =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
- disk_info.disk_length.frame =
- toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
- disk_info.next_session.minute =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
- disk_info.next_session.second =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
- disk_info.next_session.frame =
- toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
- disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
- disk_info.last_session.minute =
- toc[disk_info.next].cdsc_absaddr.msf.minute;
- disk_info.last_session.second =
- toc[disk_info.next].cdsc_absaddr.msf.second;
- disk_info.last_session.frame =
- toc[disk_info.next].cdsc_absaddr.msf.frame;
- toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
- disk_info.disk_length.minute;
- toc[disk_info.last + 1].cdsc_absaddr.msf.second =
- disk_info.disk_length.second;
- toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
- disk_info.disk_length.frame;
-#if DEBUG_TOC
- for (i = 1; i <= disk_info.last + 1; i++)
- toc_debug_info(i);
- toc_debug_info(QINFO_FIRSTTRACK);
- toc_debug_info(QINFO_LASTTRACK);
- toc_debug_info(QINFO_DISKLENGTH);
- toc_debug_info(QINFO_NEXTSESSION);
-#endif
-
- DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
- got_info, count));
- if ((got_info & I_ALL) != I_ALL
- || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
- < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
- return -ERR_TOC_MISSINGINFO;
- return 0;
-}
-
-
-#ifdef MULTISESSION
-static int get_multi_disk_info(void)
-{
- int sessions, status;
- struct cdrom_msf multi_index;
-
-
- for (sessions = 2; sessions < 10 /* %%for now */; sessions++) {
- int count;
-
- for (count = 100; count < MAX_TRACKS; count++)
- toc[count].cdsc_ind = 0;
-
- multi_index.cdmsf_min0 = disk_info.next_session.minute;
- multi_index.cdmsf_sec0 = disk_info.next_session.second;
- multi_index.cdmsf_frame0 = disk_info.next_session.frame;
- if (multi_index.cdmsf_sec0 >= 20)
- multi_index.cdmsf_sec0 -= 20;
- else {
- multi_index.cdmsf_sec0 += 40;
- multi_index.cdmsf_min0--;
- }
- DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
- multi_index.cdmsf_min0,
- multi_index.cdmsf_sec0,
- multi_index.cdmsf_frame0));
- bin2bcd(&multi_index);
- multi_index.cdmsf_min1 = 0;
- multi_index.cdmsf_sec1 = 0;
- multi_index.cdmsf_frame1 = 1;
-
- status = exec_read_cmd(COMREAD, &multi_index);
- if (status < 0) {
- DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
- -status));
- break;
- }
- status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
- 0 : -ERR_TOC_MISSINGINFO;
- flush_data();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
- break;
- }
-
- status = read_toc();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
- break;
- }
-
- disk_info.multi = 1;
- }
-
- exec_cmd(COMSTOP);
-
- if (status < 0)
- return -EIO;
- return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int update_toc(void)
-{
- int status, count;
-
- if (toc_uptodate)
- return 0;
-
- DEBUG((DEBUG_TOC, "starting update_toc"));
-
- disk_info.first = 0;
- for (count = 0; count < MAX_TRACKS; count++)
- toc[count].cdsc_ind = 0;
-
- status = exec_cmd(COMLEADIN);
- if (status < 0)
- return -EIO;
-
- status = read_toc();
- if (status < 0) {
- DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
- return -EIO;
- }
-
- /* Audio disk detection. Look at first track. */
- disk_info.audio =
- (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
-
- /* XA detection */
- disk_info.xa = drive_status() & ST_MODE2TRACK;
-
- /* Multisession detection: if we want this, define MULTISESSION */
- disk_info.multi = 0;
-#ifdef MULTISESSION
- if (disk_info.xa)
- get_multi_disk_info(); /* Here disk_info.multi is set */
-#endif /* MULTISESSION */
- if (disk_info.multi)
- printk(KERN_WARNING "optcd: Multisession support experimental, "
- "see Documentation/cdrom/optcd\n");
-
- DEBUG((DEBUG_TOC, "exiting update_toc"));
-
- toc_uptodate = 1;
- return 0;
-}
-
-/* Request handling */
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-/* Buffers for block size conversion. */
-#define NOBUF -1
-
-static char buf[CD_FRAMESIZE * N_BUFS];
-static volatile int buf_bn[N_BUFS], next_bn;
-static volatile int buf_in = 0, buf_out = NOBUF;
-
-static inline void opt_invalidate_buffers(void)
-{
- int i;
-
- DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
-
- for (i = 0; i < N_BUFS; i++)
- buf_bn[i] = NOBUF;
- buf_out = NOBUF;
-}
-
-
-/* Take care of the different block sizes between cdrom and Linux.
- When Linux gets variable block sizes this will probably go away. */
-static void transfer(void)
-{
-#if DEBUG_BUFFERS | DEBUG_REQUEST
- printk(KERN_DEBUG "optcd: executing transfer\n");
-#endif
-
- if (!current_valid())
- return;
- while (CURRENT -> nr_sectors) {
- int bn = CURRENT -> sector / 4;
- int i, offs, nr_sectors;
- for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
-
- DEBUG((DEBUG_REQUEST, "found %d", i));
-
- if (i >= N_BUFS) {
- buf_out = NOBUF;
- break;
- }
-
- offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
- nr_sectors = 4 - (CURRENT -> sector & 3);
-
- if (buf_out != i) {
- buf_out = i;
- if (buf_bn[i] != bn) {
- buf_out = NOBUF;
- continue;
- }
- }
-
- if (nr_sectors > CURRENT -> nr_sectors)
- nr_sectors = CURRENT -> nr_sectors;
- memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
- CURRENT -> nr_sectors -= nr_sectors;
- CURRENT -> sector += nr_sectors;
- CURRENT -> buffer += nr_sectors * 512;
- }
-}
-
-
-/* State machine for reading disk blocks */
-
-enum state_e {
- S_IDLE, /* 0 */
- S_START, /* 1 */
- S_READ, /* 2 */
- S_DATA, /* 3 */
- S_STOP, /* 4 */
- S_STOPPING /* 5 */
-};
-
-static volatile enum state_e state = S_IDLE;
-#if DEBUG_STATE
-static volatile enum state_e state_old = S_STOP;
-static volatile int flags_old = 0;
-static volatile long state_n = 0;
-#endif
-
-
-/* Used as mutex to keep do_optcd_request (and other processes calling
- ioctl) out while some process is inside a VFS call.
- Reverse is accomplished by checking if state = S_IDLE upon entry
- of opt_ioctl and opt_media_change. */
-static int in_vfs = 0;
-
-
-static volatile int transfer_is_active = 0;
-static volatile int error = 0; /* %% do something with this?? */
-static int tries; /* ibid?? */
-static int timeout = 0;
-
-static void poll(unsigned long data);
-static struct timer_list req_timer = {.function = poll};
-
-
-static void poll(unsigned long data)
-{
- static volatile int read_count = 1;
- int flags;
- int loop_again = 1;
- int status = 0;
- int skip = 0;
-
- if (error) {
- printk(KERN_ERR "optcd: I/O error 0x%02x\n", error);
- opt_invalidate_buffers();
- if (!tries--) {
- printk(KERN_ERR "optcd: read block %d failed;"
- " Giving up\n", next_bn);
- if (transfer_is_active)
- loop_again = 0;
- if (current_valid())
- end_request(CURRENT, 0);
- tries = 5;
- }
- error = 0;
- state = S_STOP;
- }
-
- while (loop_again)
- {
- loop_again = 0; /* each case must flip this back to 1 if we want
- to come back up here */
-
-#if DEBUG_STATE
- if (state == state_old)
- state_n++;
- else {
- state_old = state;
- if (++state_n > 1)
- printk(KERN_DEBUG "optcd: %ld times "
- "in previous state\n", state_n);
- printk(KERN_DEBUG "optcd: state %d\n", state);
- state_n = 0;
- }
-#endif
-
- switch (state) {
- case S_IDLE:
- return;
- case S_START:
- if (in_vfs)
- break;
- if (send_cmd(COMDRVST)) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- state = S_READ;
- timeout = READ_TIMEOUT;
- break;
- case S_READ: {
- struct cdrom_msf msf;
- if (!skip) {
- status = fetch_status();
- if (status < 0)
- break;
- if (status & ST_DSK_CHG) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- }
- }
- skip = 0;
- if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- printk(KERN_WARNING "optcd: %s\n",
- (status & ST_DOOR_OPEN)
- ? "door open"
- : "disk removed");
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- if (!current_valid()) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- next_bn = CURRENT -> sector / 4;
- lba2msf(next_bn, &msf);
- read_count = N_BUFS;
- msf.cdmsf_frame1 = read_count; /* Not BCD! */
-
- DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
- msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0,
- msf.cdmsf_min1,
- msf.cdmsf_sec1,
- msf.cdmsf_frame1));
- DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
- " buf_out:%d buf_bn:%d",
- next_bn,
- buf_in,
- buf_out,
- buf_bn[buf_in]));
-
- exec_read_cmd(COMREAD, &msf);
- state = S_DATA;
- timeout = READ_TIMEOUT;
- break;
- }
- case S_DATA:
- flags = stdt_flags() & (FL_STEN|FL_DTEN);
-
-#if DEBUG_STATE
- if (flags != flags_old) {
- flags_old = flags;
- printk(KERN_DEBUG "optcd: flags:%x\n", flags);
- }
- if (flags == FL_STEN)
- printk(KERN_DEBUG "timeout cnt: %d\n", timeout);
-#endif
-
- switch (flags) {
- case FL_DTEN: /* only STEN low */
- if (!tries--) {
- printk(KERN_ERR
- "optcd: read block %d failed; "
- "Giving up\n", next_bn);
- if (transfer_is_active) {
- tries = 0;
- break;
- }
- if (current_valid())
- end_request(CURRENT, 0);
- tries = 5;
- }
- state = S_START;
- timeout = READ_TIMEOUT;
- loop_again = 1;
- case (FL_STEN|FL_DTEN): /* both high */
- break;
- default: /* DTEN low */
- tries = 5;
- if (!current_valid() && buf_in == buf_out) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- if (read_count<=0)
- printk(KERN_WARNING
- "optcd: warning - try to read"
- " 0 frames\n");
- while (read_count) {
- buf_bn[buf_in] = NOBUF;
- if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
- /* should be no waiting here!?? */
- printk(KERN_ERR
- "read_count:%d "
- "CURRENT->nr_sectors:%ld "
- "buf_in:%d\n",
- read_count,
- CURRENT->nr_sectors,
- buf_in);
- printk(KERN_ERR
- "transfer active: %x\n",
- transfer_is_active);
- read_count = 0;
- state = S_STOP;
- loop_again = 1;
- end_request(CURRENT, 0);
- break;
- }
- fetch_data(buf+
- CD_FRAMESIZE*buf_in,
- CD_FRAMESIZE);
- read_count--;
-
- DEBUG((DEBUG_REQUEST,
- "S_DATA; ---I've read data- "
- "read_count: %d",
- read_count));
- DEBUG((DEBUG_REQUEST,
- "next_bn:%d buf_in:%d "
- "buf_out:%d buf_bn:%d",
- next_bn,
- buf_in,
- buf_out,
- buf_bn[buf_in]));
-
- buf_bn[buf_in] = next_bn++;
- if (buf_out == NOBUF)
- buf_out = buf_in;
- buf_in = buf_in + 1 ==
- N_BUFS ? 0 : buf_in + 1;
- }
- if (!transfer_is_active) {
- while (current_valid()) {
- transfer();
- if (CURRENT -> nr_sectors == 0)
- end_request(CURRENT, 1);
- else
- break;
- }
- }
-
- if (current_valid()
- && (CURRENT -> sector / 4 < next_bn ||
- CURRENT -> sector / 4 >
- next_bn + N_BUFS)) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- timeout = READ_TIMEOUT;
- if (read_count == 0) {
- state = S_STOP;
- loop_again = 1;
- break;
- }
- }
- break;
- case S_STOP:
- if (read_count != 0)
- printk(KERN_ERR
- "optcd: discard data=%x frames\n",
- read_count);
- flush_data();
- if (send_cmd(COMDRVST)) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- state = S_STOPPING;
- timeout = STOP_TIMEOUT;
- break;
- case S_STOPPING:
- status = fetch_status();
- if (status < 0 && timeout)
- break;
- if ((status >= 0) && (status & ST_DSK_CHG)) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- }
- if (current_valid()) {
- if (status >= 0) {
- state = S_READ;
- loop_again = 1;
- skip = 1;
- break;
- } else {
- state = S_START;
- timeout = 1;
- }
- } else {
- state = S_IDLE;
- return;
- }
- break;
- default:
- printk(KERN_ERR "optcd: invalid state %d\n", state);
- return;
- } /* case */
- } /* while */
-
- if (!timeout--) {
- printk(KERN_ERR "optcd: timeout in state %d\n", state);
- state = S_STOP;
- if (exec_cmd(COMSTOP) < 0) {
- state = S_IDLE;
- while (current_valid())
- end_request(CURRENT, 0);
- return;
- }
- }
-
- mod_timer(&req_timer, jiffies + HZ/100);
-}
-
-
-static void do_optcd_request(request_queue_t * q)
-{
- DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
- CURRENT -> sector, CURRENT -> nr_sectors));
-
- if (disk_info.audio) {
- printk(KERN_WARNING "optcd: tried to mount an Audio CD\n");
- end_request(CURRENT, 0);
- return;
- }
-
- transfer_is_active = 1;
- while (current_valid()) {
- transfer(); /* First try to transfer block from buffers */
- if (CURRENT -> nr_sectors == 0) {
- end_request(CURRENT, 1);
- } else { /* Want to read a block not in buffer */
- buf_out = NOBUF;
- if (state == S_IDLE) {
- /* %% Should this block the request queue?? */
- if (update_toc() < 0) {
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- /* Start state machine */
- state = S_START;
- timeout = READ_TIMEOUT;
- tries = 5;
- /* %% why not start right away?? */
- mod_timer(&req_timer, jiffies + HZ/100);
- }
- break;
- }
- }
- transfer_is_active = 0;
-
- DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d buf_out:%d buf_bn:%d",
- next_bn, buf_in, buf_out, buf_bn[buf_in]));
- DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
-}
-
-/* IOCTLs */
-
-
-static char auto_eject = 0;
-
-static int cdrompause(void)
-{
- int status;
-
- if (audio_status != CDROM_AUDIO_PLAY)
- return -EINVAL;
-
- status = exec_cmd(COMPAUSEON);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
- return -EIO;
- }
- audio_status = CDROM_AUDIO_PAUSED;
- return 0;
-}
-
-
-static int cdromresume(void)
-{
- int status;
-
- if (audio_status != CDROM_AUDIO_PAUSED)
- return -EINVAL;
-
- status = exec_cmd(COMPAUSEOFF);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromplaymsf(void __user *arg)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- status = exec_long_cmd(COMPLAY, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromplaytrkind(void __user *arg)
-{
- int status;
- struct cdrom_ti ti;
- struct cdrom_msf msf;
-
- if (copy_from_user(&ti, arg, sizeof ti))
- return -EFAULT;
-
- if (ti.cdti_trk0 < disk_info.first
- || ti.cdti_trk0 > disk_info.last
- || ti.cdti_trk1 < ti.cdti_trk0)
- return -EINVAL;
- if (ti.cdti_trk1 > disk_info.last)
- ti.cdti_trk1 = disk_info.last;
-
- msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
- msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
- msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
- msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
- msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
- msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
-
- DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
- msf.cdmsf_min0,
- msf.cdmsf_sec0,
- msf.cdmsf_frame0,
- msf.cdmsf_min1,
- msf.cdmsf_sec1,
- msf.cdmsf_frame1));
-
- bin2bcd(&msf);
- status = exec_long_cmd(COMPLAY, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
- audio_status = CDROM_AUDIO_ERROR;
- return -EIO;
- }
-
- audio_status = CDROM_AUDIO_PLAY;
- return 0;
-}
-
-
-static int cdromreadtochdr(void __user *arg)
-{
- struct cdrom_tochdr tochdr;
-
- tochdr.cdth_trk0 = disk_info.first;
- tochdr.cdth_trk1 = disk_info.last;
-
- return copy_to_user(arg, &tochdr, sizeof tochdr) ? -EFAULT : 0;
-}
-
-
-static int cdromreadtocentry(void __user *arg)
-{
- struct cdrom_tocentry entry;
- struct cdrom_subchnl *tocptr;
-
- if (copy_from_user(&entry, arg, sizeof entry))
- return -EFAULT;
-
- if (entry.cdte_track == CDROM_LEADOUT)
- tocptr = &toc[disk_info.last + 1];
- else if (entry.cdte_track > disk_info.last
- || entry.cdte_track < disk_info.first)
- return -EINVAL;
- else
- tocptr = &toc[entry.cdte_track];
-
- entry.cdte_adr = tocptr->cdsc_adr;
- entry.cdte_ctrl = tocptr->cdsc_ctrl;
- entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
- entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
- entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
- /* %% What should go into entry.cdte_datamode? */
-
- if (entry.cdte_format == CDROM_LBA)
- msf2lba(&entry.cdte_addr);
- else if (entry.cdte_format != CDROM_MSF)
- return -EINVAL;
-
- return copy_to_user(arg, &entry, sizeof entry) ? -EFAULT : 0;
-}
-
-
-static int cdromvolctrl(void __user *arg)
-{
- int status;
- struct cdrom_volctrl volctrl;
- struct cdrom_msf msf;
-
- if (copy_from_user(&volctrl, arg, sizeof volctrl))
- return -EFAULT;
-
- msf.cdmsf_min0 = 0x10;
- msf.cdmsf_sec0 = 0x32;
- msf.cdmsf_frame0 = volctrl.channel0;
- msf.cdmsf_min1 = volctrl.channel1;
- msf.cdmsf_sec1 = volctrl.channel2;
- msf.cdmsf_frame1 = volctrl.channel3;
-
- status = exec_long_cmd(COMCHCTRL, &msf);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
- return -EIO;
- }
- return 0;
-}
-
-
-static int cdromsubchnl(void __user *arg)
-{
- int status;
- struct cdrom_subchnl subchnl;
-
- if (copy_from_user(&subchnl, arg, sizeof subchnl))
- return -EFAULT;
-
- if (subchnl.cdsc_format != CDROM_LBA
- && subchnl.cdsc_format != CDROM_MSF)
- return -EINVAL;
-
- status = get_q_channel(&subchnl);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
- return -EIO;
- }
-
- if (copy_to_user(arg, &subchnl, sizeof subchnl))
- return -EFAULT;
- return 0;
-}
-
-
-static struct gendisk *optcd_disk;
-
-
-static int cdromread(void __user *arg, int blocksize, int cmd)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- msf.cdmsf_min1 = 0;
- msf.cdmsf_sec1 = 0;
- msf.cdmsf_frame1 = 1; /* read only one frame */
- status = exec_read_cmd(cmd, &msf);
-
- DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
-
- if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
- return -EIO;
-
- fetch_data(optcd_disk->private_data, blocksize);
-
- if (copy_to_user(arg, optcd_disk->private_data, blocksize))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int cdromseek(void __user *arg)
-{
- int status;
- struct cdrom_msf msf;
-
- if (copy_from_user(&msf, arg, sizeof msf))
- return -EFAULT;
-
- bin2bcd(&msf);
- status = exec_seek_cmd(COMSEEK, &msf);
-
- DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
-
- if (status < 0)
- return -EIO;
- return 0;
-}
-
-
-#ifdef MULTISESSION
-static int cdrommultisession(void __user *arg)
-{
- struct cdrom_multisession ms;
-
- if (copy_from_user(&ms, arg, sizeof ms))
- return -EFAULT;
-
- ms.addr.msf.minute = disk_info.last_session.minute;
- ms.addr.msf.second = disk_info.last_session.second;
- ms.addr.msf.frame = disk_info.last_session.frame;
-
- if (ms.addr_format != CDROM_LBA
- && ms.addr_format != CDROM_MSF)
- return -EINVAL;
- if (ms.addr_format == CDROM_LBA)
- msf2lba(&ms.addr);
-
- ms.xa_flag = disk_info.xa;
-
- if (copy_to_user(arg, &ms, sizeof(struct cdrom_multisession)))
- return -EFAULT;
-
-#if DEBUG_MULTIS
- if (ms.addr_format == CDROM_MSF)
- printk(KERN_DEBUG
- "optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
- ms.xa_flag,
- ms.addr.msf.minute,
- ms.addr.msf.second,
- ms.addr.msf.frame);
- else
- printk(KERN_DEBUG
- "optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
- ms.xa_flag,
- ms.addr.lba,
- disk_info.last_session.minute,
- disk_info.last_session.second,
- disk_info.last_session.frame);
-#endif /* DEBUG_MULTIS */
-
- return 0;
-}
-#endif /* MULTISESSION */
-
-
-static int cdromreset(void)
-{
- if (state != S_IDLE) {
- error = 1;
- tries = 0;
- }
-
- toc_uptodate = 0;
- disk_changed = 1;
- opt_invalidate_buffers();
- audio_status = CDROM_AUDIO_NO_STATUS;
-
- if (!reset_drive())
- return -EIO;
- return 0;
-}
-
-/* VFS calls */
-
-
-static int opt_ioctl(struct inode *ip, struct file *fp,
- unsigned int cmd, unsigned long arg)
-{
- int status, err, retval = 0;
- void __user *argp = (void __user *)arg;
-
- DEBUG((DEBUG_VFS, "starting opt_ioctl"));
-
- if (!ip)
- return -EINVAL;
-
- if (cmd == CDROMRESET)
- return cdromreset();
-
- /* is do_optcd_request or another ioctl busy? */
- if (state != S_IDLE || in_vfs)
- return -EBUSY;
-
- in_vfs = 1;
-
- status = drive_status();
- if (status < 0) {
- DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
- in_vfs = 0;
- return -EIO;
- }
-
- if (status & ST_DOOR_OPEN)
- switch (cmd) { /* Actions that can be taken with door open */
- case CDROMCLOSETRAY:
- /* We do this before trying to read the toc. */
- err = exec_cmd(COMCLOSE);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMCLOSE: %02x", -err));
- in_vfs = 0;
- return -EIO;
- }
- break;
- default: in_vfs = 0;
- return -EBUSY;
- }
-
- err = update_toc();
- if (err < 0) {
- DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
- in_vfs = 0;
- return -EIO;
- }
-
- DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
-
- switch (cmd) {
- case CDROMPAUSE: retval = cdrompause(); break;
- case CDROMRESUME: retval = cdromresume(); break;
- case CDROMPLAYMSF: retval = cdromplaymsf(argp); break;
- case CDROMPLAYTRKIND: retval = cdromplaytrkind(argp); break;
- case CDROMREADTOCHDR: retval = cdromreadtochdr(argp); break;
- case CDROMREADTOCENTRY: retval = cdromreadtocentry(argp); break;
-
- case CDROMSTOP: err = exec_cmd(COMSTOP);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMSTOP: %02x",
- -err));
- retval = -EIO;
- } else
- audio_status = CDROM_AUDIO_NO_STATUS;
- break;
- case CDROMSTART: break; /* This is a no-op */
- case CDROMEJECT: err = exec_cmd(COMUNLOCK);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMUNLOCK: %02x",
- -err));
- retval = -EIO;
- break;
- }
- err = exec_cmd(COMOPEN);
- if (err < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMOPEN: %02x",
- -err));
- retval = -EIO;
- }
- break;
-
- case CDROMVOLCTRL: retval = cdromvolctrl(argp); break;
- case CDROMSUBCHNL: retval = cdromsubchnl(argp); break;
-
- /* The drive detects the mode and automatically delivers the
- correct 2048 bytes, so we don't need these IOCTLs */
- case CDROMREADMODE2: retval = -EINVAL; break;
- case CDROMREADMODE1: retval = -EINVAL; break;
-
- /* Drive doesn't support reading audio */
- case CDROMREADAUDIO: retval = -EINVAL; break;
-
- case CDROMEJECT_SW: auto_eject = (char) arg;
- break;
-
-#ifdef MULTISESSION
- case CDROMMULTISESSION: retval = cdrommultisession(argp); break;
-#endif
-
- case CDROM_GET_MCN: retval = -EINVAL; break; /* not implemented */
- case CDROMVOLREAD: retval = -EINVAL; break; /* not implemented */
-
- case CDROMREADRAW:
- /* this drive delivers 2340 bytes in raw mode */
- retval = cdromread(argp, CD_FRAMESIZE_RAW1, COMREADRAW);
- break;
- case CDROMREADCOOKED:
- retval = cdromread(argp, CD_FRAMESIZE, COMREAD);
- break;
- case CDROMREADALL:
- retval = cdromread(argp, CD_FRAMESIZE_RAWER, COMREADALL);
- break;
-
- case CDROMSEEK: retval = cdromseek(argp); break;
- case CDROMPLAYBLK: retval = -EINVAL; break; /* not implemented */
- case CDROMCLOSETRAY: break; /* The action was taken earlier */
- default: retval = -EINVAL;
- }
- in_vfs = 0;
- return retval;
-}
-
-
-static int open_count = 0;
-
-/* Open device special file; check that a disk is in. */
-static int opt_open(struct inode *ip, struct file *fp)
-{
- DEBUG((DEBUG_VFS, "starting opt_open"));
-
- if (!open_count && state == S_IDLE) {
- int status;
- char *buf;
-
- buf = kmalloc(CD_FRAMESIZE_RAWER, GFP_KERNEL);
- if (!buf) {
- printk(KERN_INFO "optcd: cannot allocate read buffer\n");
- return -ENOMEM;
- }
- optcd_disk->private_data = buf; /* save read buffer */
-
- toc_uptodate = 0;
- opt_invalidate_buffers();
-
- status = exec_cmd(COMCLOSE); /* close door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status));
- }
-
- status = drive_status();
- if (status < 0) {
- DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
- goto err_out;
- }
- DEBUG((DEBUG_VFS, "status: %02x", status));
- if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
- printk(KERN_INFO "optcd: no disk or door open\n");
- goto err_out;
- }
- status = exec_cmd(COMLOCK); /* Lock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
- }
- status = update_toc(); /* Read table of contents */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
- status = exec_cmd(COMUNLOCK); /* Unlock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS,
- "exec_cmd COMUNLOCK: %02x", -status));
- }
- goto err_out;
- }
- open_count++;
- }
-
- DEBUG((DEBUG_VFS, "exiting opt_open"));
-
- return 0;
-
-err_out:
- return -EIO;
-}
-
-
-/* Release device special file; flush all blocks from the buffer cache */
-static int opt_release(struct inode *ip, struct file *fp)
-{
- int status;
-
- DEBUG((DEBUG_VFS, "executing opt_release"));
- DEBUG((DEBUG_VFS, "inode: %p, device: %s, file: %p\n",
- ip, ip->i_bdev->bd_disk->disk_name, fp));
-
- if (!--open_count) {
- toc_uptodate = 0;
- opt_invalidate_buffers();
- status = exec_cmd(COMUNLOCK); /* Unlock door */
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
- }
- if (auto_eject) {
- status = exec_cmd(COMOPEN);
- DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
- }
- kfree(optcd_disk->private_data);
- del_timer(&delay_timer);
- del_timer(&req_timer);
- }
- return 0;
-}
-
-
-/* Check if disk has been changed */
-static int opt_media_change(struct gendisk *disk)
-{
- DEBUG((DEBUG_VFS, "executing opt_media_change"));
- DEBUG((DEBUG_VFS, "dev: %s; disk_changed = %d\n",
- disk->disk_name, disk_changed));
-
- if (disk_changed) {
- disk_changed = 0;
- return 1;
- }
- return 0;
-}
-
-/* Driver initialisation */
-
-
-/* Returns 1 if a drive is detected with a version string
- starting with "DOLPHIN". Otherwise 0. */
-static int __init version_ok(void)
-{
- char devname[100];
- int count, i, ch, status;
-
- status = exec_cmd(COMVERSION);
- if (status < 0) {
- DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
- return 0;
- }
- if ((count = get_data(1)) < 0) {
- DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
- return 0;
- }
- for (i = 0, ch = -1; count > 0; count--) {
- if ((ch = get_data(1)) < 0) {
- DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
- break;
- }
- if (i < 99)
- devname[i++] = ch;
- }
- devname[i] = '\0';
- if (ch < 0)
- return 0;
-
- printk(KERN_INFO "optcd: Device %s detected\n", devname);
- return ((devname[0] == 'D')
- && (devname[1] == 'O')
- && (devname[2] == 'L')
- && (devname[3] == 'P')
- && (devname[4] == 'H')
- && (devname[5] == 'I')
- && (devname[6] == 'N'));
-}
-
-
-static struct block_device_operations opt_fops = {
- .owner = THIS_MODULE,
- .open = opt_open,
- .release = opt_release,
- .ioctl = opt_ioctl,
- .media_changed = opt_media_change,
-};
-
-#ifndef MODULE
-/* Get kernel parameter when used as a kernel driver */
-static int optcd_setup(char *str)
-{
- int ints[4];
- (void)get_options(str, ARRAY_SIZE(ints), ints);
-
- if (ints[0] > 0)
- optcd_port = ints[1];
-
- return 1;
-}
-
-__setup("optcd=", optcd_setup);
-
-#endif /* MODULE */
-
-/* Test for presence of drive and initialize it. Called at boot time
- or during module initialisation. */
-static int __init optcd_init(void)
-{
- int status;
-
- if (optcd_port <= 0) {
- printk(KERN_INFO
- "optcd: no Optics Storage CDROM Initialization\n");
- return -EIO;
- }
- optcd_disk = alloc_disk(1);
- if (!optcd_disk) {
- printk(KERN_ERR "optcd: can't allocate disk\n");
- return -ENOMEM;
- }
- optcd_disk->major = MAJOR_NR;
- optcd_disk->first_minor = 0;
- optcd_disk->fops = &opt_fops;
- sprintf(optcd_disk->disk_name, "optcd");
-
- if (!request_region(optcd_port, 4, "optcd")) {
- printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n",
- optcd_port);
- put_disk(optcd_disk);
- return -EIO;
- }
-
- if (!reset_drive()) {
- printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port);
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
- if (!version_ok()) {
- printk(KERN_ERR "optcd: unknown drive detected; aborting\n");
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
- status = exec_cmd(COMINITDOUBLE);
- if (status < 0) {
- printk(KERN_ERR "optcd: cannot init double speed mode\n");
- release_region(optcd_port, 4);
- DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
- put_disk(optcd_disk);
- return -EIO;
- }
- if (register_blkdev(MAJOR_NR, "optcd")) {
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -EIO;
- }
-
-
- opt_queue = blk_init_queue(do_optcd_request, &optcd_lock);
- if (!opt_queue) {
- unregister_blkdev(MAJOR_NR, "optcd");
- release_region(optcd_port, 4);
- put_disk(optcd_disk);
- return -ENOMEM;
- }
-
- blk_queue_hardsect_size(opt_queue, 2048);
- optcd_disk->queue = opt_queue;
- add_disk(optcd_disk);
-
- printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
- return 0;
-}
-
-
-static void __exit optcd_exit(void)
-{
- del_gendisk(optcd_disk);
- put_disk(optcd_disk);
- if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
- printk(KERN_ERR "optcd: what's that: can't unregister\n");
- return;
- }
- blk_cleanup_queue(opt_queue);
- release_region(optcd_port, 4);
- printk(KERN_INFO "optcd: module released.\n");
-}
-
-module_init(optcd_init);
-module_exit(optcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(OPTICS_CDROM_MAJOR);
diff --git a/drivers/cdrom/optcd.h b/drivers/cdrom/optcd.h
deleted file mode 100644
index 1911bb92ee2..00000000000
--- a/drivers/cdrom/optcd.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* linux/include/linux/optcd.h - Optics Storage 8000 AT CDROM driver
- $Id: optcd.h,v 1.2 1996/01/15 18:43:44 root Exp root $
-
- Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
-
-
- Configuration file for linux/drivers/cdrom/optcd.c
-*/
-
-#ifndef _LINUX_OPTCD_H
-#define _LINUX_OPTCD_H
-
-
-/* I/O base of drive. Drive uses base to base+2.
- This setting can be overridden with the kernel or insmod command
- line option 'optcd=<portbase>'. Use address of 0 to disable driver. */
-#define OPTCD_PORTBASE 0x340
-
-
-/* enable / disable parts of driver by define / undef */
-#define MULTISESSION /* multisession support (ALPHA) */
-
-
-/* Change 0 to 1 to debug various parts of the driver */
-#define DEBUG_DRIVE_IF 0 /* Low level drive interface */
-#define DEBUG_CONV 0 /* Address conversions */
-#define DEBUG_BUFFERS 0 /* Buffering and block size conversion */
-#define DEBUG_REQUEST 0 /* Request mechanism */
-#define DEBUG_STATE 0 /* State machine */
-#define DEBUG_TOC 0 /* Q-channel and Table of Contents */
-#define DEBUG_MULTIS 0 /* Multisession code */
-#define DEBUG_VFS 0 /* VFS interface */
-
-
-/* Don't touch these unless you know what you're doing. */
-
-/* Various timeout loop repetition counts. */
-#define BUSY_TIMEOUT 10000000 /* for busy wait */
-#define FAST_TIMEOUT 100000 /* ibid. for probing */
-#define SLEEP_TIMEOUT 6000 /* for timer wait */
-#define MULTI_SEEK_TIMEOUT 1000 /* for timer wait */
-#define READ_TIMEOUT 6000 /* for poll wait */
-#define STOP_TIMEOUT 2000 /* for poll wait */
-#define RESET_WAIT 5000 /* busy wait at drive reset */
-
-/* # of buffers for block size conversion. 6 is optimal for my setup (P75),
- giving 280 kb/s, with 0.4% CPU usage. Experiment to find your optimal
- setting */
-#define N_BUFS 6
-
-
-#endif /* _LINUX_OPTCD_H */
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
deleted file mode 100644
index a1283b1ef98..00000000000
--- a/drivers/cdrom/sbpcd.c
+++ /dev/null
@@ -1,5966 +0,0 @@
-/*
- * sbpcd.c CD-ROM device driver for the whole family of traditional,
- * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives.
- * Works with SoundBlaster compatible cards and with "no-sound"
- * interface cards like Lasermate, Panasonic CI-101P, Teac, ...
- * Also for the Longshine LCS-7260 drive.
- * Also for the IBM "External ISA CD-Rom" drive.
- * Also for the CreativeLabs CD200 drive.
- * Also for the TEAC CD-55A drive.
- * Also for the ECS-AT "Vertos 100" drive.
- * Not for Sanyo drives (but for the H94A, sjcd is there...).
- * Not for any other Funai drives than the CD200 types (sometimes
- * labelled E2550UA or MK4015 or 2800F).
- */
-
-#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000"
-
-/* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, 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.
- *
- * If you change this software, you should mail a .diff file with some
- * description lines to emoenke@gwdg.de. I want to know about it.
- *
- * If you are the editor of a Linux CD, you should enable sbpcd.c within
- * your boot floppy kernel and send me one of your CDs for free.
- *
- * If you would like to port the driver to an other operating system (f.e.
- * FreeBSD or NetBSD) or use it as an information source, you shall not be
- * restricted by the GPL under the following conditions:
- * a) the source code of your work is freely available
- * b) my part of the work gets mentioned at all places where your
- * authorship gets mentioned
- * c) I receive a copy of your code together with a full installation
- * package of your operating system for free.
- *
- *
- * VERSION HISTORY
- *
- * 0.1 initial release, April/May 93, after mcd.c (Martin Harriss)
- *
- * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for
- * end-of-request_queue (resulting in kernel panic).
- * Flow control seems stable, but throughput is not better.
- *
- * 0.3 interrupt locking totally eliminated (maybe "inb" and "outb"
- * are still locking) - 0.2 made keyboard-type-ahead losses.
- * check_sbpcd_media_change added (to use by isofs/inode.c)
- * - but it detects almost nothing.
- *
- * 0.4 use MAJOR 25 definitely.
- * Almost total re-design to support double-speed drives and
- * "naked" (no sound) interface cards ("LaserMate" interface type).
- * Flow control should be exact now.
- * Don't occupy the SbPro IRQ line (not needed either); will
- * live together with Hannu Savolainen's sndkit now.
- * Speeded up data transfer to 150 kB/sec, with help from Kai
- * Makisara, the "provider" of the "mt" tape utility.
- * Give "SpinUp" command if necessary.
- * First steps to support up to 4 drives (but currently only one).
- * Implemented audio capabilities - workman should work, xcdplayer
- * gives some problems.
- * This version is still consuming too much CPU time, and
- * sleeping still has to be worked on.
- * During "long" implied seeks, it seems possible that a
- * ReadStatus command gets ignored. That gives the message
- * "ResponseStatus timed out" (happens about 6 times here during
- * a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is
- * handled without data error, but it should get done better.
- *
- * 0.5 Free CPU during waits (again with help from Kai Makisara).
- * Made it work together with the LILO/kernel setup standard.
- * Included auto-probing code, as suggested by YGGDRASIL.
- * Formal redesign to add DDI debugging.
- * There are still flaws in IOCTL (workman with double speed drive).
- *
- * 1.0 Added support for all drive IDs (0...3, no longer only 0)
- * and up to 4 drives on one controller.
- * Added "#define MANY_SESSION" for "old" multi session CDs.
- *
- * 1.1 Do SpinUp for new drives, too.
- * Revised for clean compile under "old" kernels (0.99pl9).
- *
- * 1.2 Found the "workman with double-speed drive" bug: use the driver's
- * audio_state, not what the drive is reporting with ReadSubQ.
- *
- * 1.3 Minor cleanups.
- * Refinements regarding Workman.
- *
- * 1.4 Read XA disks (PhotoCDs) with "old" drives, too (but only the first
- * session - no chance to fully access a "multi-session" CD).
- * This currently still is too slow (50 kB/sec) - but possibly
- * the old drives won't do it faster.
- * Implemented "door (un)lock" for new drives (still does not work
- * as wanted - no lock possible after an unlock).
- * Added some debugging printout for the UPC/EAN code - but my drives
- * return only zeroes. Is there no UPC/EAN code written?
- *
- * 1.5 Laborate with UPC/EAN code (not better yet).
- * Adapt to kernel 1.1.8 change (have to explicitly include
- * <linux/string.h> now).
- *
- * 1.6 Trying to read audio frames as data. Impossible with the current
- * drive firmware levels, as it seems. Awaiting any hint. ;-)
- * Changed "door unlock": repeat it until success.
- * Changed CDROMSTOP routine (stop somewhat "softer" so that Workman
- * won't get confused).
- * Added a third interface type: Sequoia S-1000, as used with the SPEA
- * Media FX sound card. This interface (usable for Sony and Mitsumi
- * drives, too) needs a special configuration setup and behaves like a
- * LaserMate type after that. Still experimental - I do not have such
- * an interface.
- * Use the "variable BLOCK_SIZE" feature (2048). But it does only work
- * if you give the mount option "block=2048".
- * The media_check routine is currently disabled; now that it gets
- * called as it should I fear it must get synchronized for not to
- * disturb the normal driver's activity.
- *
- * 2.0 Version number bumped - two reasons:
- * - reading audio tracks as data works now with CR-562 and CR-563. We
- * currently do it by an IOCTL (yet has to get standardized), one frame
- * at a time; that is pretty slow. But it works.
- * - we are maintaining now up to 4 interfaces (each up to 4 drives):
- * did it the easy way - a different MAJOR (25, 26, ...) and a different
- * copy of the driver (sbpcd.c, sbpcd2.c, sbpcd3.c, sbpcd4.c - only
- * distinguished by the value of SBPCD_ISSUE and the driver's name),
- * and a common sbpcd.h file.
- * Bettered the "ReadCapacity error" problem with old CR-52x drives (the
- * drives sometimes need a manual "eject/insert" before work): just
- * reset the drive and do again. Needs lots of resets here and sometimes
- * that does not cure, so this can't be the solution.
- *
- * 2.1 Found bug with multisession CDs (accessing frame 16).
- * "read audio" works now with address type CDROM_MSF, too.
- * Bigger audio frame buffer: allows reading max. 4 frames at time; this
- * gives a significant speedup, but reading more than one frame at once
- * gives missing chunks at each single frame boundary.
- *
- * 2.2 Kernel interface cleanups: timers, init, setup, media check.
- *
- * 2.3 Let "door lock" and "eject" live together.
- * Implemented "close tray" (done automatically during open).
- *
- * 2.4 Use different names for device registering.
- *
- * 2.5 Added "#if EJECT" code (default: enabled) to automatically eject
- * the tray during last call to "sbpcd_release".
- * Added "#if JUKEBOX" code (default: disabled) to automatically eject
- * the tray during call to "sbpcd_open" if no disk is in.
- * Turn on the CD volume of "compatible" sound cards, too; just define
- * SOUND_BASE (in sbpcd.h) accordingly (default: disabled).
- *
- * 2.6 Nothing new.
- *
- * 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly:
- * 0 disables, 1 enables auto-ejecting. Useful to keep the tray in
- * during shutdown.
- *
- * 2.8 Added first support (still BETA, I need feedback or a drive) for
- * the Longshine LCS-7260 drives. They appear as double-speed drives
- * using the "old" command scheme, extended by tray control and door
- * lock functions.
- * Found (and fixed preliminary) a flaw with some multisession CDs: we
- * have to re-direct not only the accesses to frame 16 (the isofs
- * routines drive it up to max. 100), but also those to the continuation
- * (repetition) frames (as far as they exist - currently set fix as
- * 16..20).
- * Changed default of the "JUKEBOX" define. If you use this default,
- * your tray will eject if you try to mount without a disk in. Next
- * mount command will insert the tray - so, just fill in a disk. ;-)
- *
- * 2.9 Fulfilled the Longshine LCS-7260 support; with great help and
- * experiments by Serge Robyns.
- * First attempts to support the TEAC CD-55A drives; but still not
- * usable yet.
- * Implemented the CDROMMULTISESSION ioctl; this is an attempt to handle
- * multi session CDs more "transparent" (redirection handling has to be
- * done within the isofs routines, and only for the special purpose of
- * obtaining the "right" volume descriptor; accesses to the raw device
- * should not get redirected).
- *
- * 3.0 Just a "normal" increment, with some provisions to do it better. ;-)
- * Introduced "#define READ_AUDIO" to specify the maximum number of
- * audio frames to grab with one request. This defines a buffer size
- * within kernel space; a value of 0 will reserve no such space and
- * disable the CDROMREADAUDIO ioctl. A value of 75 enables the reading
- * of a whole second with one command, but will use a buffer of more
- * than 172 kB.
- * Started CD200 support. Drive detection should work, but nothing
- * more.
- *
- * 3.1 Working to support the CD200 and the Teac CD-55A drives.
- * AT-BUS style device numbering no longer used: use SCSI style now.
- * So, the first "found" device has MINOR 0, regardless of the
- * jumpered drive ID. This implies modifications to the /dev/sbpcd*
- * entries for some people, but will help the DAU (german TLA, english:
- * "newbie", maybe ;-) to install his "first" system from a CD.
- *
- * 3.2 Still testing with CD200 and CD-55A drives.
- *
- * 3.3 Working with CD200 support.
- *
- * 3.4 Auto-probing stops if an address of 0 is seen (to be entered with
- * the kernel command line).
- * Made the driver "loadable". If used as a module, "audio copy" is
- * disabled, and the internal read ahead data buffer has a reduced size
- * of 4 kB; so, throughput may be reduced a little bit with slow CPUs.
- *
- * 3.5 Provisions to handle weird photoCDs which have an interrupted
- * "formatting" immediately after the last frames of some files: simply
- * never "read ahead" with MultiSession CDs. By this, CPU usage may be
- * increased with those CDs, and there may be a loss in speed.
- * Re-structured the messaging system.
- * The "loadable" version no longer has a limited READ_AUDIO buffer
- * size.
- * Removed "MANY_SESSION" handling for "old" multi session CDs.
- * Added "private" IOCTLs CDROMRESET and CDROMVOLREAD.
- * Started again to support the TEAC CD-55A drives, now that I found
- * the money for "my own" drive. ;-)
- * The TEAC CD-55A support is fairly working now.
- * I have measured that the drive "delivers" at 600 kB/sec (even with
- * bigger requests than the drive's 64 kB buffer can satisfy), but
- * the "real" rate does not exceed 520 kB/sec at the moment.
- * Caused by the various changes to build in TEAC support, the timed
- * loops are de-optimized at the moment (less throughput with CR-52x
- * drives, and the TEAC will give speed only with SBP_BUFFER_FRAMES 64).
- *
- * 3.6 Fixed TEAC data read problems with SbPro interfaces.
- * Initial size of the READ_AUDIO buffer is 0. Can get set to any size
- * during runtime.
- *
- * 3.7 Introduced MAX_DRIVES for some poor interface cards (seen with TEAC
- * drives) which allow only one drive (ID 0); this avoids repetitive
- * detection under IDs 1..3.
- * Elongated cmd_out_T response waiting; necessary for photo CDs with
- * a lot of sessions.
- * Bettered the sbpcd_open() behavior with TEAC drives.
- *
- * 3.8 Elongated max_latency for CR-56x drives.
- *
- * 3.9 Finally fixed the long-known SoundScape/SPEA/Sequoia S-1000 interface
- * configuration bug.
- * Now Corey, Heiko, Ken, Leo, Vadim/Eric & Werner are invited to copy
- * the config_spea() routine into their drivers. ;-)
- *
- * 4.0 No "big step" - normal version increment.
- * Adapted the benefits from 1.3.33.
- * Fiddled with CDROMREADAUDIO flaws.
- * Avoid ReadCapacity command with CD200 drives (the MKE 1.01 version
- * seems not to support it).
- * Fulfilled "read audio" for CD200 drives, with help of Pete Heist
- * (heistp@rpi.edu).
- *
- * 4.1 Use loglevel KERN_INFO with printk().
- * Added support for "Vertos 100" drive ("ECS-AT") - it is very similar
- * to the Longshine LCS-7260. Give feedback if you can - I never saw
- * such a drive, and I have no specs.
- *
- * 4.2 Support for Teac 16-bit interface cards. Can't get auto-detected,
- * so you have to jumper your card to 0x2C0. Still not 100% - come
- * in contact if you can give qualified feedback.
- * Use loglevel KERN_NOTICE with printk(). If you get annoyed by a
- * flood of unwanted messages and the accompanied delay, try to read
- * my documentation. Especially the Linux CDROM drivers have to do an
- * important job for the newcomers, so the "distributed" version has
- * to fit some special needs. Since generations, the flood of messages
- * is user-configurable (even at runtime), but to get aware of this, one
- * needs a special mental quality: the ability to read.
- *
- * 4.3 CD200F does not like to receive a command while the drive is
- * reading the ToC; still trying to solve it.
- * Removed some redundant verify_area calls (yes, Heiko Eissfeldt
- * is visiting all the Linux CDROM drivers ;-).
- *
- * 4.4 Adapted one idea from tiensivu@pilot.msu.edu's "stripping-down"
- * experiments: "KLOGD_PAUSE".
- * Inhibited "play audio" attempts with data CDs. Provisions for a
- * "data-safe" handling of "mixed" (data plus audio) Cds.
- *
- * 4.5 Meanwhile Gonzalo Tornaria <tornaria@cmat.edu.uy> (GTL) built a
- * special end_request routine: we seem to have to take care for not
- * to have two processes working at the request list. My understanding
- * was and is that ll_rw_blk should not call do_sbpcd_request as long
- * as there is still one call active (the first call will care for all
- * outstanding I/Os, and if a second call happens, that is a bug in
- * ll_rw_blk.c).
- * "Check media change" without touching any drive.
- *
- * 4.6 Use a semaphore to synchronize multi-activity; elaborated by Rob
- * Riggs <rriggs@tesser.com>. At the moment, we simply block "read"
- * against "ioctl" and vice versa. This could be refined further, but
- * I guess with almost no performance increase.
- * Experiments to speed up the CD-55A; again with help of Rob Riggs
- * (to be true, he gave both, idea & code. ;-)
- *
- * 4.61 Ported to Uniform CD-ROM driver by
- * Heiko Eissfeldt <heiko@colossus.escape.de> with additional
- * changes by Erik Andersen <andersee@debian.org>
- *
- * 4.62 Fix a bug where playing audio left the drive in an unusable state.
- * Heiko Eissfeldt <heiko@colossus.escape.de>
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer.
- * Annoying things fixed:
- * TOC reread on automated disk changes
- * TOC reread on manual cd changes
- * Play IOCTL tries to play CD before it's actually ready... sometimes.
- * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play.
- * Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000
- *
- * 4.64 Fix module parameters - were being completely ignored.
- * Can also specify max_drives=N as a setup int to get rid of
- * "ghost" drives on crap hardware (aren't they all?) Paul Gortmaker
- *
- * TODO
- * implement "read all subchannel data" (96 bytes per frame)
- * remove alot of the virtual status bits and deal with hardware status
- * move the change of cd for audio to a better place
- * add debug levels to insmod parameters (trivial)
- *
- * special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
- * elaborated speed-up experiments (and the fabulous results!), for
- * the "push" towards load-free wait loops, and for the extensive mail
- * thread which brought additional hints and bug fixes.
- *
- */
-
-/*
- * Trying to merge requests breaks this driver horribly (as in it goes
- * boom and apparently has done so since 2.3.41). As it is a legacy
- * driver for a horribly slow double speed CD on a hideous interface
- * designed for polled operation, I won't lose any sleep in simply
- * disallowing merging. Paul G. 02/2001
- *
- * Thu May 30 14:14:47 CEST 2002:
- *
- * I have presumably found the reson for the above - there was a bogous
- * end_request substitute, which was manipulating the request queues
- * incorrectly. If someone has access to the actual hardware, and it's
- * still operations - well please free to test it.
- *
- * Marcin Dalecki
- */
-
-/*
- * Add bio/kdev_t changes for 2.5.x required to make it work again.
- * Still room for improvement in the request handling here if anyone
- * actually cares. Bring your own chainsaw. Paul G. 02/2002
- */
-
-
-#include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <stdarg.h>
-#include "sbpcd.h"
-
-#define MAJOR_NR MATSUSHITA_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-/*==========================================================================*/
-#if SBPCD_DIS_IRQ
-# define SBPCD_CLI cli()
-# define SBPCD_STI sti()
-#else
-# define SBPCD_CLI
-# define SBPCD_STI
-#endif
-
-/*==========================================================================*/
-/*
- * auto-probing address list
- * inspired by Adam J. Richter from Yggdrasil
- *
- * still not good enough - can cause a hang.
- * example: a NE 2000 ethernet card at 300 will cause a hang probing 310.
- * if that happens, reboot and use the LILO (kernel) command line.
- * The possibly conflicting ethernet card addresses get NOT probed
- * by default - to minimize the hang possibilities.
- *
- * The SB Pro addresses get "mirrored" at 0x6xx and some more locations - to
- * avoid a type error, the 0x2xx-addresses must get checked before 0x6xx.
- *
- * send mail to emoenke@gwdg.de if your interface card is not FULLY
- * represented here.
- */
-static int sbpcd[] =
-{
- CDROM_PORT, SBPRO, /* probe with user's setup first */
-#if DISTRIBUTION
- 0x230, 1, /* Soundblaster Pro and 16 (default) */
-#if 0
- 0x300, 0, /* CI-101P (default), WDH-7001C (default),
- Galaxy (default), Reveal (one default) */
- 0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */
- 0x2C0, 3, /* Teac 16-bit cards */
- 0x260, 1, /* OmniCD */
- 0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default),
- Longshine LCS-6853 (default) */
- 0x338, 0, /* Reveal Sound Wave 32 card model #SC600 */
- 0x340, 0, /* Mozart sound card (default), Lasermate, CI-101P */
- 0x360, 0, /* Lasermate, CI-101P */
- 0x270, 1, /* Soundblaster 16 */
- 0x670, 0, /* "sound card #9" */
- 0x690, 0, /* "sound card #9" */
- 0x338, 2, /* SPEA Media FX, Ensonic SoundScape (default) */
- 0x328, 2, /* SPEA Media FX */
- 0x348, 2, /* SPEA Media FX */
- 0x634, 0, /* some newer sound cards */
- 0x638, 0, /* some newer sound cards */
- 0x230, 1, /* some newer sound cards */
- /* due to incomplete address decoding of the SbPro card, these must be last */
- 0x630, 0, /* "sound card #9" (default) */
- 0x650, 0, /* "sound card #9" */
-#ifdef MODULE
- /*
- * some "hazardous" locations (no harm with the loadable version)
- * (will stop the bus if a NE2000 ethernet card resides at offset -0x10)
- */
- 0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
- 0x350, 0, /* Lasermate, CI-101P */
- 0x358, 2, /* SPEA Media FX */
- 0x370, 0, /* Lasermate, CI-101P */
- 0x290, 1, /* Soundblaster 16 */
- 0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
-#endif /* MODULE */
-#endif
-#endif /* DISTRIBUTION */
-};
-
-/*
- * Protects access to global structures etc.
- */
-static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock);
-static struct request_queue *sbpcd_queue;
-
-/* You can only set the first pair, from old MODULE_PARM code. */
-static int sbpcd_set(const char *val, struct kernel_param *kp)
-{
- get_options((char *)val, 2, (int *)sbpcd);
- return 0;
-}
-module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0);
-
-#define NUM_PROBE (sizeof(sbpcd) / sizeof(int))
-
-/*==========================================================================*/
-
-#define INLINE inline
-
-/*==========================================================================*/
-/*
- * the forward references:
- */
-static void sbp_sleep(u_int);
-static void mark_timeout_delay(u_long);
-static void mark_timeout_data(u_long);
-#if 0
-static void mark_timeout_audio(u_long);
-#endif
-static void sbp_read_cmd(struct request *req);
-static int sbp_data(struct request *req);
-static int cmd_out(void);
-static int DiskInfo(void);
-
-/*==========================================================================*/
-
-/*
- * pattern for printk selection:
- *
- * (1<<DBG_INF) necessary information
- * (1<<DBG_BSZ) BLOCK_SIZE trace
- * (1<<DBG_REA) "read" status trace
- * (1<<DBG_CHK) "media check" trace
- * (1<<DBG_TIM) datarate timer test
- * (1<<DBG_INI) initialization trace
- * (1<<DBG_TOC) tell TocEntry values
- * (1<<DBG_IOC) ioctl trace
- * (1<<DBG_STA) "ResponseStatus" trace
- * (1<<DBG_ERR) "cc_ReadError" trace
- * (1<<DBG_CMD) "cmd_out" trace
- * (1<<DBG_WRN) give explanation before auto-probing
- * (1<<DBG_MUL) multi session code test
- * (1<<DBG_IDX) "drive_id != 0" test code
- * (1<<DBG_IOX) some special information
- * (1<<DBG_DID) drive ID test
- * (1<<DBG_RES) drive reset info
- * (1<<DBG_SPI) SpinUp test info
- * (1<<DBG_IOS) ioctl trace: "subchannel"
- * (1<<DBG_IO2) ioctl trace: general
- * (1<<DBG_UPC) show UPC info
- * (1<<DBG_XA1) XA mode debugging
- * (1<<DBG_LCK) door (un)lock info
- * (1<<DBG_SQ1) dump SubQ frame
- * (1<<DBG_AUD) "read audio" debugging
- * (1<<DBG_SEQ) Sequoia interface configuration trace
- * (1<<DBG_LCS) Longshine LCS-7260 debugging trace
- * (1<<DBG_CD2) MKE/Funai CD200 debugging trace
- * (1<<DBG_TEA) TEAC CD-55A debugging trace
- * (1<<DBG_ECS) ECS-AT (Vertos-100) debugging trace
- * (1<<DBG_000) unnecessary information
- */
-#if DISTRIBUTION
-static int sbpcd_debug = (1<<DBG_INF);
-#else
-static int sbpcd_debug = 0 & ((1<<DBG_INF) |
- (1<<DBG_TOC) |
- (1<<DBG_MUL) |
- (1<<DBG_UPC));
-#endif /* DISTRIBUTION */
-
-static int sbpcd_ioaddr = CDROM_PORT; /* default I/O base address */
-static int sbpro_type = SBPRO;
-static unsigned char f_16bit;
-static unsigned char do_16bit;
-static int CDo_command, CDo_reset;
-static int CDo_sel_i_d, CDo_enable;
-static int CDi_info, CDi_status, CDi_data;
-static struct cdrom_msf msf;
-static struct cdrom_ti ti;
-static struct cdrom_tochdr tochdr;
-static struct cdrom_tocentry tocentry;
-static struct cdrom_subchnl SC;
-static struct cdrom_volctrl volctrl;
-static struct cdrom_read_audio read_audio;
-
-static unsigned char msgnum;
-static char msgbuf[80];
-
-static int max_drives = MAX_DRIVES;
-module_param(max_drives, int, 0);
-#ifndef MODULE
-static unsigned char setup_done;
-static const char *str_sb_l = "soundblaster";
-static const char *str_sp_l = "spea";
-static const char *str_ss_l = "soundscape";
-static const char *str_t16_l = "teac16bit";
-static const char *str_ss = "SoundScape";
-#endif
-static const char *str_sb = "SoundBlaster";
-static const char *str_lm = "LaserMate";
-static const char *str_sp = "SPEA";
-static const char *str_t16 = "Teac16bit";
-static const char *type;
-static const char *major_name="sbpcd";
-
-/*==========================================================================*/
-
-#ifdef FUTURE
-static DECLARE_WAIT_QUEUE_HEAD(sbp_waitq);
-#endif /* FUTURE */
-
-static int teac=SBP_TEAC_SPEED;
-static int buffers=SBP_BUFFER_FRAMES;
-
-static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */
-static u_char family1[]="CR-56"; /* MKE CR-562, CR-563 */
-static u_char family2[]="CD200"; /* MKE CD200, Funai CD200F */
-static u_char familyL[]="LCS-7260"; /* Longshine LCS-7260 */
-static u_char familyT[]="CD-55"; /* TEAC CD-55A */
-static u_char familyV[]="ECS-AT"; /* ECS Vertos 100 */
-
-static u_int recursion; /* internal testing only */
-static u_int fatal_err; /* internal testing only */
-static u_int response_count;
-static u_int flags_cmd_out;
-static u_char cmd_type;
-static u_char drvcmd[10];
-static u_char infobuf[20];
-static u_char xa_head_buf[CD_XA_HEAD];
-static u_char xa_tail_buf[CD_XA_TAIL];
-
-#if OLD_BUSY
-static volatile u_char busy_data;
-static volatile u_char busy_audio; /* true semaphores would be safer */
-#endif /* OLD_BUSY */
-static DECLARE_MUTEX(ioctl_read_sem);
-static u_long timeout;
-static volatile u_char timed_out_delay;
-static volatile u_char timed_out_data;
-#if 0
-static volatile u_char timed_out_audio;
-#endif
-static u_int datarate= 1000000;
-static u_int maxtim16=16000000;
-static u_int maxtim04= 4000000;
-static u_int maxtim02= 2000000;
-static u_int maxtim_8= 30000;
-#if LONG_TIMING
-static u_int maxtim_data= 9000;
-#else
-static u_int maxtim_data= 3000;
-#endif /* LONG_TIMING */
-#if DISTRIBUTION
-static int n_retries=6;
-#else
-static int n_retries=6;
-#endif
-/*==========================================================================*/
-
-static int ndrives;
-static u_char drv_pattern[NR_SBPCD]={speed_auto,speed_auto,speed_auto,speed_auto};
-
-/*==========================================================================*/
-/*
- * drive space begins here (needed separate for each unit)
- */
-static struct sbpcd_drive {
- char drv_id; /* "jumpered" drive ID or -1 */
- char drv_sel; /* drive select lines bits */
-
- char drive_model[9];
- u_char firmware_version[4];
- char f_eject; /* auto-eject flag: 0 or 1 */
- u_char *sbp_buf; /* Pointer to internal data buffer,
- space allocated during sbpcd_init() */
- u_int sbp_bufsiz; /* size of sbp_buf (# of frames) */
- int sbp_first_frame; /* First frame in buffer */
- int sbp_last_frame; /* Last frame in buffer */
- int sbp_read_frames; /* Number of frames being read to buffer */
- int sbp_current; /* Frame being currently read */
-
- u_char mode; /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */
- u_char *aud_buf; /* Pointer to audio data buffer,
- space allocated during sbpcd_init() */
- u_int sbp_audsiz; /* size of aud_buf (# of raw frames) */
- u_int drv_type;
- u_char drv_options;
- int status_bits;
- u_char diskstate_flags;
- u_char sense_byte;
-
- u_char CD_changed;
- char open_count;
- u_char error_byte;
-
- u_char f_multisession;
- u_int lba_multi;
- int first_session;
- int last_session;
- int track_of_last_session;
-
- u_char audio_state;
- u_int pos_audio_start;
- u_int pos_audio_end;
- char vol_chan0;
- u_char vol_ctrl0;
- char vol_chan1;
- u_char vol_ctrl1;
-#if 000 /* no supported drive has it */
- char vol_chan2;
- u_char vol_ctrl2;
- char vol_chan3;
- u_char vol_ctrl3;
-#endif /*000 */
- u_char volume_control; /* TEAC on/off bits */
-
- u_char SubQ_ctl_adr;
- u_char SubQ_trk;
- u_char SubQ_pnt_idx;
- u_int SubQ_run_tot;
- u_int SubQ_run_trk;
- u_char SubQ_whatisthis;
-
- u_char UPC_ctl_adr;
- u_char UPC_buf[7];
-
- int frame_size;
- int CDsize_frm;
-
- u_char xa_byte; /* 0x20: XA capabilities */
- u_char n_first_track; /* binary */
- u_char n_last_track; /* binary (not bcd), 0x01...0x63 */
- u_int size_msf; /* time of whole CD, position of LeadOut track */
- u_int size_blk;
-
- u_char TocEnt_nixbyte; /* em */
- u_char TocEnt_ctl_adr;
- u_char TocEnt_number;
- u_char TocEnt_format; /* em */
- u_int TocEnt_address;
-#ifdef SAFE_MIXED
- char has_data;
-#endif /* SAFE_MIXED */
- u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */
-
- struct {
- u_char nixbyte; /* em */
- u_char ctl_adr; /* 0x4x: data, 0x0x: audio */
- u_char number;
- u_char format; /* em */ /* 0x00: lba, 0x01: msf */
- u_int address;
- } TocBuffer[MAX_TRACKS+1]; /* last entry faked */
-
- int in_SpinUp; /* CR-52x test flag */
- int n_bytes; /* TEAC awaited response count */
- u_char error_state, b3, b4; /* TEAC command error state */
- u_char f_drv_error; /* TEAC command error flag */
- u_char speed_byte;
- int frmsiz;
- u_char f_XA; /* 1: XA */
- u_char type_byte; /* 0, 1, 3 */
- u_char mode_xb_6;
- u_char mode_yb_7;
- u_char mode_xb_8;
- u_char delay;
- struct cdrom_device_info *sbpcd_infop;
- struct gendisk *disk;
-} D_S[NR_SBPCD];
-
-static struct sbpcd_drive *current_drive = D_S;
-
-/*
- * drive space ends here (needed separate for each unit)
- */
-/*==========================================================================*/
-#if 0
-unsigned long cli_sti; /* for saving the processor flags */
-#endif
-/*==========================================================================*/
-static DEFINE_TIMER(delay_timer, mark_timeout_delay, 0, 0);
-static DEFINE_TIMER(data_timer, mark_timeout_data, 0, 0);
-#if 0
-static DEFINE_TIMER(audio_timer, mark_timeout_audio, 0, 0);
-#endif
-/*==========================================================================*/
-/*
- * DDI interface
- */
-static void msg(int level, const char *fmt, ...)
-{
-#if DISTRIBUTION
-#define MSG_LEVEL KERN_NOTICE
-#else
-#define MSG_LEVEL KERN_INFO
-#endif /* DISTRIBUTION */
-
- char buf[256];
- va_list args;
-
- if (!(sbpcd_debug&(1<<level))) return;
-
- msgnum++;
- if (msgnum>99) msgnum=0;
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- printk(MSG_LEVEL "%s-%d [%02d]: %s", major_name, current_drive - D_S, msgnum, buf);
-#if KLOGD_PAUSE
- sbp_sleep(KLOGD_PAUSE); /* else messages get lost */
-#endif /* KLOGD_PAUSE */
- return;
-}
-/*==========================================================================*/
-/*
- * DDI interface: runtime trace bit pattern maintenance
- */
-static int sbpcd_dbg_ioctl(unsigned long arg, int level)
-{
- switch(arg)
- {
- case 0: /* OFF */
- sbpcd_debug = DBG_INF;
- break;
-
- default:
- if (arg>=128) sbpcd_debug &= ~(1<<(arg-128));
- else sbpcd_debug |= (1<<arg);
- }
- return (arg);
-}
-/*==========================================================================*/
-static void mark_timeout_delay(u_long i)
-{
- timed_out_delay=1;
-#if 0
- msg(DBG_TIM,"delay timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-static void mark_timeout_data(u_long i)
-{
- timed_out_data=1;
-#if 0
- msg(DBG_TIM,"data timer expired.\n");
-#endif
-}
-/*==========================================================================*/
-#if 0
-static void mark_timeout_audio(u_long i)
-{
- timed_out_audio=1;
-#if 0
- msg(DBG_TIM,"audio timer expired.\n");
-#endif
-}
-#endif
-/*==========================================================================*/
-/*
- * Wait a little while (used for polling the drive).
- */
-static void sbp_sleep(u_int time)
-{
- sti();
- schedule_timeout_interruptible(time);
- sti();
-}
-/*==========================================================================*/
-#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);}
-/*==========================================================================*/
-/*
- * convert logical_block_address to m-s-f_number (3 bytes only)
- */
-static INLINE void lba2msf(int lba, u_char *msf)
-{
- lba += CD_MSF_OFFSET;
- msf[0] = lba / (CD_SECS*CD_FRAMES);
- lba %= CD_SECS*CD_FRAMES;
- msf[1] = lba / CD_FRAMES;
- msf[2] = lba % CD_FRAMES;
-}
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * convert msf-bin to msf-bcd
- */
-static INLINE void bin2bcdx(u_char *p) /* must work only up to 75 or 99 */
-{
- *p=((*p/10)<<4)|(*p%10);
-}
-/*==========================================================================*/
-static INLINE u_int blk2msf(u_int blk)
-{
- MSF msf;
- u_int mm;
-
- msf.c[3] = 0;
- msf.c[2] = (blk + CD_MSF_OFFSET) / (CD_SECS * CD_FRAMES);
- mm = (blk + CD_MSF_OFFSET) % (CD_SECS * CD_FRAMES);
- msf.c[1] = mm / CD_FRAMES;
- msf.c[0] = mm % CD_FRAMES;
- return (msf.n);
-}
-/*==========================================================================*/
-static INLINE u_int make16(u_char rh, u_char rl)
-{
- return ((rh<<8)|rl);
-}
-/*==========================================================================*/
-static INLINE u_int make32(u_int rh, u_int rl)
-{
- return ((rh<<16)|rl);
-}
-/*==========================================================================*/
-static INLINE u_char swap_nibbles(u_char i)
-{
- return ((i<<4)|(i>>4));
-}
-/*==========================================================================*/
-static INLINE u_char byt2bcd(u_char i)
-{
- return (((i/10)<<4)+i%10);
-}
-/*==========================================================================*/
-static INLINE u_char bcd2bin(u_char bcd)
-{
- return ((bcd>>4)*10+(bcd&0x0F));
-}
-/*==========================================================================*/
-static INLINE int msf2blk(int msfx)
-{
- MSF msf;
- int i;
-
- msf.n=msfx;
- i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_MSF_OFFSET;
- if (i<0) return (0);
- return (i);
-}
-/*==========================================================================*/
-/*
- * convert m-s-f_number (3 bytes only) to logical_block_address
- */
-static INLINE int msf2lba(u_char *msf)
-{
- int i;
-
- i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_MSF_OFFSET;
- if (i<0) return (0);
- return (i);
-}
-/*==========================================================================*/
-/* evaluate cc_ReadError code */
-static int sta2err(int sta)
-{
- if (famT_drive)
- {
- if (sta==0x00) return (0);
- if (sta==0x01) return (-604); /* CRC error */
- if (sta==0x02) return (-602); /* drive not ready */
- if (sta==0x03) return (-607); /* unknown media */
- if (sta==0x04) return (-612); /* general failure */
- if (sta==0x05) return (0);
- if (sta==0x06) return (-ERR_DISKCHANGE); /* disk change */
- if (sta==0x0b) return (-612); /* general failure */
- if (sta==0xff) return (-612); /* general failure */
- return (0);
- }
- else
- {
- if (sta<=2) return (sta);
- if (sta==0x05) return (-604); /* CRC error */
- if (sta==0x06) return (-606); /* seek error */
- if (sta==0x0d) return (-606); /* seek error */
- if (sta==0x0e) return (-603); /* unknown command */
- if (sta==0x14) return (-603); /* unknown command */
- if (sta==0x0c) return (-611); /* read fault */
- if (sta==0x0f) return (-611); /* read fault */
- if (sta==0x10) return (-611); /* read fault */
- if (sta>=0x16) return (-612); /* general failure */
- if (sta==0x11) return (-ERR_DISKCHANGE); /* disk change (LCS: removed) */
- if (famL_drive)
- if (sta==0x12) return (-ERR_DISKCHANGE); /* disk change (inserted) */
- return (-602); /* drive not ready */
- }
-}
-/*==========================================================================*/
-static INLINE void clr_cmdbuf(void)
-{
- int i;
-
- for (i=0;i<10;i++) drvcmd[i]=0;
- cmd_type=0;
-}
-/*==========================================================================*/
-static void flush_status(void)
-{
- int i;
-
- sbp_sleep(15*HZ/10);
- for (i=maxtim_data;i!=0;i--) inb(CDi_status);
-}
-/*====================================================================*/
-/*
- * CDi status loop for Teac CD-55A (Rob Riggs)
- *
- * This is needed because for some strange reason
- * the CD-55A can take a real long time to give a
- * status response. This seems to happen after we
- * issue a READ command where a long seek is involved.
- *
- * I tried to ensure that we get max throughput with
- * minimal busy waiting. We busy wait at first, then
- * "switch gears" and start sleeping. We sleep for
- * longer periods of time the longer we wait.
- *
- */
-static int CDi_stat_loop_T(void)
-{
- int i, gear=1;
- u_long timeout_1, timeout_2, timeout_3, timeout_4;
-
- timeout_1 = jiffies + HZ / 50; /* sbp_sleep(0) for a short period */
- timeout_2 = jiffies + HZ / 5; /* nap for no more than 200ms */
- timeout_3 = jiffies + 5 * HZ; /* sleep for up to 5s */
- timeout_4 = jiffies + 45 * HZ; /* long sleep for up to 45s. */
- do
- {
- i = inb(CDi_status);
- if (!(i&s_not_data_ready)) return (i);
- if (!(i&s_not_result_ready)) return (i);
- switch(gear)
- {
- case 4:
- sbp_sleep(HZ);
- if (time_after(jiffies, timeout_4)) gear++;
- msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
- break;
- case 3:
- sbp_sleep(HZ/10);
- if (time_after(jiffies, timeout_3)) gear++;
- break;
- case 2:
- sbp_sleep(HZ/100);
- if (time_after(jiffies, timeout_2)) gear++;
- break;
- case 1:
- sbp_sleep(0);
- if (time_after(jiffies, timeout_1)) gear++;
- }
- } while (gear < 5);
- return -1;
-}
-/*==========================================================================*/
-static int CDi_stat_loop(void)
-{
- int i,j;
-
- for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) return (j);
- if (!(j&s_not_result_ready)) return (j);
- if (fam0L_drive) if (j&s_attention) return (j);
- }
- sbp_sleep(1);
- i = 1;
- }
- msg(DBG_LCS,"CDi_stat_loop failed in line %d\n", __LINE__);
- return (-1);
-}
-/*==========================================================================*/
-#if 00000
-/*==========================================================================*/
-static int tst_DataReady(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_not_data_ready) return (0);
- return (1);
-}
-/*==========================================================================*/
-static int tst_ResultReady(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_not_result_ready) return (0);
- return (1);
-}
-/*==========================================================================*/
-static int tst_Attention(void)
-{
- int i;
-
- i=inb(CDi_status);
- if (i&s_attention) return (1);
- return (0);
-}
-/*==========================================================================*/
-#endif
-/*==========================================================================*/
-static int ResponseInfo(void)
-{
- int i,j,st=0;
- u_long timeout;
-
- for (i=0,timeout=jiffies+HZ;i<response_count;i++)
- {
- for (j=maxtim_data; ; )
- {
- for ( ;j!=0;j-- )
- {
- st=inb(CDi_status);
- if (!(st&s_not_result_ready)) break;
- }
- if ((j!=0)||time_after_eq(jiffies, timeout)) break;
- sbp_sleep(1);
- j = 1;
- }
- if (time_after_eq(jiffies, timeout)) break;
- infobuf[i]=inb(CDi_info);
- }
-#if 000
- while (!(inb(CDi_status)&s_not_result_ready))
- {
- infobuf[i++]=inb(CDi_info);
- }
- j=i-response_count;
- if (j>0) msg(DBG_INF,"ResponseInfo: got %d trailing bytes.\n",j);
-#endif /* 000 */
- for (j=0;j<i;j++)
- sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"ResponseInfo:%s (%d,%d)\n",msgbuf,response_count,i);
- j=response_count-i;
- if (j>0) return (-j);
- else return (i);
-}
-/*==========================================================================*/
-static void EvaluateStatus(int st)
-{
- current_drive->status_bits=0;
- if (fam1_drive) current_drive->status_bits=st|p_success;
- else if (fam0_drive)
- {
- if (st&p_caddin_old) current_drive->status_bits |= p_door_closed|p_caddy_in;
- if (st&p_spinning) current_drive->status_bits |= p_spinning;
- if (st&p_check) current_drive->status_bits |= p_check;
- if (st&p_success_old) current_drive->status_bits |= p_success;
- if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
- if (st&p_disk_ok) current_drive->status_bits |= p_disk_ok;
- }
- else if (famLV_drive)
- {
- current_drive->status_bits |= p_success;
- if (st&p_caddin_old) current_drive->status_bits |= p_disk_ok|p_caddy_in;
- if (st&p_spinning) current_drive->status_bits |= p_spinning;
- if (st&p_check) current_drive->status_bits |= p_check;
- if (st&p_busy_old) current_drive->status_bits |= p_busy_new;
- if (st&p_lcs_door_closed) current_drive->status_bits |= p_door_closed;
- if (st&p_lcs_door_locked) current_drive->status_bits |= p_door_locked;
- }
- else if (fam2_drive)
- {
- current_drive->status_bits |= p_success;
- if (st&p2_check) current_drive->status_bits |= p1_check;
- if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
- if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
- if (st&p2_busy1) current_drive->status_bits |= p1_busy;
- if (st&p2_busy2) current_drive->status_bits |= p1_busy;
- if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
- if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
- if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
- }
- else if (famT_drive)
- {
- return; /* still needs to get coded */
- current_drive->status_bits |= p_success;
- if (st&p2_check) current_drive->status_bits |= p1_check;
- if (st&p2_door_closed) current_drive->status_bits |= p1_door_closed;
- if (st&p2_disk_in) current_drive->status_bits |= p1_disk_in;
- if (st&p2_busy1) current_drive->status_bits |= p1_busy;
- if (st&p2_busy2) current_drive->status_bits |= p1_busy;
- if (st&p2_spinning) current_drive->status_bits |= p1_spinning;
- if (st&p2_door_locked) current_drive->status_bits |= p1_door_locked;
- if (st&p2_disk_ok) current_drive->status_bits |= p1_disk_ok;
- }
- return;
-}
-/*==========================================================================*/
-static int cmd_out_T(void);
-
-static int get_state_T(void)
-{
- int i;
-
- clr_cmdbuf();
- current_drive->n_bytes=1;
- drvcmd[0]=CMDT_STATUS;
- i=cmd_out_T();
- if (i>=0) i=infobuf[0];
- else
- {
- msg(DBG_TEA,"get_state_T error %d\n", i);
- return (i);
- }
- if (i>=0)
- /* 2: closed, disk in */
- current_drive->status_bits=p1_door_closed|p1_disk_in|p1_spinning|p1_disk_ok;
- else if (current_drive->error_state==6)
- {
- /* 3: closed, disk in, changed ("06 xx xx") */
- current_drive->status_bits=p1_door_closed|p1_disk_in;
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~toc_bit;
- }
- else if ((current_drive->error_state!=2)||(current_drive->b3!=0x3A)||(current_drive->b4==0x00))
- {
- /* 1: closed, no disk ("xx yy zz"or "02 3A 00") */
- current_drive->status_bits=p1_door_closed;
- current_drive->open_count=0;
- }
- else if (current_drive->b4==0x01)
- {
- /* 0: open ("02 3A 01") */
- current_drive->status_bits=0;
- current_drive->open_count=0;
- }
- else
- {
- /* 1: closed, no disk ("02 3A xx") */
- current_drive->status_bits=p1_door_closed;
- current_drive->open_count=0;
- }
- return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static int ResponseStatus(void)
-{
- int i,j;
- u_long timeout;
-
- msg(DBG_STA,"doing ResponseStatus...\n");
- if (famT_drive) return (get_state_T());
- if (flags_cmd_out & f_respo3) timeout = jiffies;
- else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ;
- else timeout = jiffies + 4*HZ;
- j=maxtim_8;
- do
- {
- for ( ;j!=0;j--)
- {
- i=inb(CDi_status);
- if (!(i&s_not_result_ready)) break;
- }
- if ((j!=0)||time_after(jiffies, timeout)) break;
- sbp_sleep(1);
- j = 1;
- }
- while (1);
- if (j==0)
- {
- if ((flags_cmd_out & f_respo3) == 0)
- msg(DBG_STA,"ResponseStatus: timeout.\n");
- current_drive->status_bits=0;
- return (-401);
- }
- i=inb(CDi_info);
- msg(DBG_STA,"ResponseStatus: response %02X.\n", i);
- EvaluateStatus(i);
- msg(DBG_STA,"status_bits=%02X, i=%02X\n",current_drive->status_bits,i);
- return (current_drive->status_bits);
-}
-/*==========================================================================*/
-static void cc_ReadStatus(void)
-{
- int i;
-
- msg(DBG_STA,"giving cc_ReadStatus command\n");
- if (famT_drive) return;
- SBPCD_CLI;
- if (fam0LV_drive) OUT(CDo_command,CMD0_STATUS);
- else if (fam1_drive) OUT(CDo_command,CMD1_STATUS);
- else if (fam2_drive) OUT(CDo_command,CMD2_STATUS);
- if (!fam0LV_drive) for (i=0;i<6;i++) OUT(CDo_command,0);
- SBPCD_STI;
-}
-/*==========================================================================*/
-static int cc_ReadError(void)
-{
- int i;
-
- clr_cmdbuf();
- msg(DBG_ERR,"giving cc_ReadError command.\n");
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_ERR;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READ_ERR;
- response_count=6;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ_ERR;
- response_count=6;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- response_count=5;
- drvcmd[0]=CMDT_READ_ERR;
- }
- i=cmd_out();
- current_drive->error_byte=0;
- msg(DBG_ERR,"cc_ReadError: cmd_out(CMDx_READ_ERR) returns %d (%02X)\n",i,i);
- if (i<0) return (i);
- if (fam0V_drive) i=1;
- else i=2;
- current_drive->error_byte=infobuf[i];
- msg(DBG_ERR,"cc_ReadError: infobuf[%d] is %d (%02X)\n",i,current_drive->error_byte,current_drive->error_byte);
- i=sta2err(infobuf[i]);
- if (i==-ERR_DISKCHANGE)
- {
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~toc_bit;
- }
- return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void);
-
-static int cmd_out_T(void)
-{
-#undef CMDT_TRIES
-#define CMDT_TRIES 1000
-#define TEST_FALSE_FF 1
-
- int i, j, l=0, m, ntries;
- unsigned long flags;
-
- current_drive->error_state=0;
- current_drive->b3=0;
- current_drive->b4=0;
- current_drive->f_drv_error=0;
- for (i=0;i<10;i++) sprintf(&msgbuf[i*3]," %02X",drvcmd[i]);
- msgbuf[i*3]=0;
- msg(DBG_CMD,"cmd_out_T:%s\n",msgbuf);
-
- OUT(CDo_sel_i_d,0);
- OUT(CDo_enable,current_drive->drv_sel);
- i=inb(CDi_status);
- do_16bit=0;
- if ((f_16bit)&&(!(i&0x80)))
- {
- do_16bit=1;
- msg(DBG_TEA,"cmd_out_T: do_16bit set.\n");
- }
- if (!(i&s_not_result_ready))
- do
- {
- j=inb(CDi_info);
- i=inb(CDi_status);
- sbp_sleep(0);
- msg(DBG_TEA,"cmd_out_T: spurious !s_not_result_ready. (%02X)\n", j);
- }
- while (!(i&s_not_result_ready));
- save_flags(flags); cli();
- for (i=0;i<10;i++) OUT(CDo_command,drvcmd[i]);
- restore_flags(flags);
- for (ntries=CMDT_TRIES;ntries>0;ntries--)
- {
- if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */
-#if 01
- OUT(CDo_sel_i_d,1);
-#endif /* 01 */
- if (teac==2)
- {
- if ((i=CDi_stat_loop_T()) == -1) break;
- }
- else
- {
-#if 0
- OUT(CDo_sel_i_d,1);
-#endif /* 0 */
- i=inb(CDi_status);
- }
- if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */
- {
- OUT(CDo_sel_i_d,1);
- if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
- if (drvcmd[0]==CMDT_DISKINFO)
- {
- l=0;
- do
- {
- if (do_16bit)
- {
- i=inw(CDi_data);
- infobuf[l++]=i&0x0ff;
- infobuf[l++]=i>>8;
-#if TEST_FALSE_FF
- if ((l==2)&&(infobuf[0]==0x0ff))
- {
- infobuf[0]=infobuf[1];
- l=1;
- msg(DBG_TEA,"cmd_out_T: do_16bit: false first byte!\n");
- }
-#endif /* TEST_FALSE_FF */
- }
- else infobuf[l++]=inb(CDi_data);
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- for (j=0;j<l;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"cmd_out_T data response:%s\n", msgbuf);
- }
- else
- {
- msg(DBG_TEA,"cmd_out_T: data response with cmd_%02X!\n",
- drvcmd[0]);
- j=0;
- do
- {
- if (do_16bit) i=inw(CDi_data);
- else i=inb(CDi_data);
- j++;
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- msg(DBG_TEA,"cmd_out_T: data response: discarded %d bytes/words.\n", j);
- fatal_err++;
- }
- }
- i=inb(CDi_status);
- if (!(i&s_not_result_ready))
- {
- OUT(CDo_sel_i_d,0);
- if (drvcmd[0]==CMDT_DISKINFO) m=l;
- else m=0;
- do
- {
- infobuf[m++]=inb(CDi_info);
- i=inb(CDi_status);
- }
- while (!(i&s_not_result_ready));
- for (j=0;j<m;j++) sprintf(&msgbuf[j*3]," %02X",infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_CMD,"cmd_out_T info response:%s\n", msgbuf);
- if (drvcmd[0]==CMDT_DISKINFO)
- {
- infobuf[0]=infobuf[l];
- if (infobuf[0]!=0x02) return (l); /* data length */
- }
- else if (infobuf[0]!=0x02) return (m); /* info length */
- do
- {
- ++recursion;
- if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (%02X): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", drvcmd[0], recursion);
- clr_cmdbuf();
- drvcmd[0]=CMDT_READ_ERR;
- j=cmd_out_T(); /* !!! recursive here !!! */
- --recursion;
- sbp_sleep(1);
- }
- while (j<0);
- current_drive->error_state=infobuf[2];
- current_drive->b3=infobuf[3];
- current_drive->b4=infobuf[4];
- if (current_drive->f_drv_error)
- {
- current_drive->f_drv_error=0;
- cc_DriveReset();
- current_drive->error_state=2;
- }
- return (-current_drive->error_state-400);
- }
- if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
- if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10);
- else sbp_sleep(HZ/100);
- if (ntries>(CMDT_TRIES-50)) continue;
- msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
- }
- current_drive->f_drv_error=1;
- cc_DriveReset();
- current_drive->error_state=2;
- return (-99);
-}
-/*==========================================================================*/
-static int cmd_out(void)
-{
- int i=0;
-
- if (famT_drive) return(cmd_out_T());
-
- if (flags_cmd_out&f_putcmd)
- {
- unsigned long flags;
- for (i=0;i<7;i++)
- sprintf(&msgbuf[i*3], " %02X", drvcmd[i]);
- msgbuf[i*3]=0;
- msg(DBG_CMD,"cmd_out:%s\n", msgbuf);
- save_flags(flags); cli();
- for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
- restore_flags(flags);
- }
- if (response_count!=0)
- {
- if (cmd_type!=0)
- {
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- msg(DBG_INF,"misleaded to try ResponseData.\n");
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- return (-22);
- }
- else i=ResponseInfo();
- if (i<0) return (i);
- }
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to CDi_stat_loop.\n");
- if (flags_cmd_out&f_lopsta)
- {
- i=CDi_stat_loop();
- if ((i<0)||!(i&s_attention)) return (-8);
- }
- if (!(flags_cmd_out&f_getsta)) goto LOC_229;
-
- LOC_228:
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadStatus.\n");
- cc_ReadStatus();
-
- LOC_229:
- if (flags_cmd_out&f_ResponseStatus)
- {
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to ResponseStatus.\n");
- i=ResponseStatus();
- /* builds status_bits, returns orig. status or p_busy_new */
- if (i<0) return (i);
- if (flags_cmd_out&(f_bit1|f_wait_if_busy))
- {
- if (!st_check)
- {
- if ((flags_cmd_out&f_bit1)&&(i&p_success)) goto LOC_232;
- if ((!(flags_cmd_out&f_wait_if_busy))||(!st_busy)) goto LOC_228;
- }
- }
- }
- LOC_232:
- if (!(flags_cmd_out&f_obey_p_check)) return (0);
- if (!st_check) return (0);
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cc_ReadError.\n");
- i=cc_ReadError();
- if (current_drive->in_SpinUp) msg(DBG_SPI,"in_SpinUp: to cmd_out OK.\n");
- msg(DBG_000,"cmd_out: cc_ReadError=%d\n", i);
- return (i);
-}
-/*==========================================================================*/
-static int cc_Seek(u_int pos, char f_blk_msf)
-{
- int i;
-
- clr_cmdbuf();
- if (f_blk_msf>1) return (-3);
- if (fam0V_drive)
- {
- drvcmd[0]=CMD0_SEEK;
- if (f_blk_msf==1) pos=msf2blk(pos);
- drvcmd[2]=(pos>>16)&0x00FF;
- drvcmd[3]=(pos>>8)&0x00FF;
- drvcmd[4]=pos&0x00FF;
- if (fam0_drive)
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_bit1;
- else
- flags_cmd_out = f_putcmd;
- }
- else if (fam1L_drive)
- {
- drvcmd[0]=CMD1_SEEK; /* same as CMD1_ and CMDL_ */
- if (f_blk_msf==0) pos=blk2msf(pos);
- drvcmd[1]=(pos>>16)&0x00FF;
- drvcmd[2]=(pos>>8)&0x00FF;
- drvcmd[3]=pos&0x00FF;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_SEEK;
- if (f_blk_msf==0) pos=blk2msf(pos);
- drvcmd[2]=(pos>>24)&0x00FF;
- drvcmd[3]=(pos>>16)&0x00FF;
- drvcmd[4]=(pos>>8)&0x00FF;
- drvcmd[5]=pos&0x00FF;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_SEEK;
- if (f_blk_msf==1) pos=msf2blk(pos);
- drvcmd[2]=(pos>>24)&0x00FF;
- drvcmd[3]=(pos>>16)&0x00FF;
- drvcmd[4]=(pos>>8)&0x00FF;
- drvcmd[5]=pos&0x00FF;
- current_drive->n_bytes=1;
- }
- response_count=0;
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_SpinUp(void)
-{
- int i;
-
- msg(DBG_SPI,"SpinUp.\n");
- current_drive->in_SpinUp = 1;
- clr_cmdbuf();
- if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_SPINUP;
- if (fam0L_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
- f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_SPINUP;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[4]=0x01; /* "spinup" */
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x03; /* "insert", it hopefully spins the drive up */
- }
- response_count=0;
- i=cmd_out();
- current_drive->in_SpinUp = 0;
- return (i);
-}
-/*==========================================================================*/
-static int cc_SpinDown(void)
-{
- int i;
-
- if (fam0_drive) return (0);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SPINDOWN;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[4]=0x02; /* "eject" */
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famL_drive)
- {
- drvcmd[0]=CMDL_SPINDOWN;
- drvcmd[1]=1;
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (famV_drive)
- {
- drvcmd[0]=CMDV_SPINDOWN;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x02; /* "eject" */
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_get_mode_T(void)
-{
- int i;
-
- clr_cmdbuf();
- response_count=10;
- drvcmd[0]=CMDT_GETMODE;
- drvcmd[4]=response_count;
- i=cmd_out_T();
- return (i);
-}
-/*==========================================================================*/
-static int cc_set_mode_T(void)
-{
- int i;
-
- clr_cmdbuf();
- response_count=1;
- drvcmd[0]=CMDT_SETMODE;
- drvcmd[1]=current_drive->speed_byte;
- drvcmd[2]=current_drive->frmsiz>>8;
- drvcmd[3]=current_drive->frmsiz&0x0FF;
- drvcmd[4]=current_drive->f_XA; /* 1: XA */
- drvcmd[5]=current_drive->type_byte; /* 0, 1, 3 */
- drvcmd[6]=current_drive->mode_xb_6;
- drvcmd[7]=current_drive->mode_yb_7|current_drive->volume_control;
- drvcmd[8]=current_drive->mode_xb_8;
- drvcmd[9]=current_drive->delay;
- i=cmd_out_T();
- return (i);
-}
-/*==========================================================================*/
-static int cc_prep_mode_T(void)
-{
- int i, j;
-
- i=cc_get_mode_T();
- if (i<0) return (i);
- for (i=0;i<10;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
- current_drive->speed_byte=0x02; /* 0x02: auto quad, 0x82: quad, 0x81: double, 0x80: single */
- current_drive->frmsiz=make16(infobuf[2],infobuf[3]);
- current_drive->f_XA=infobuf[4];
- if (current_drive->f_XA==0) current_drive->type_byte=0;
- else current_drive->type_byte=1;
- current_drive->mode_xb_6=infobuf[6];
- current_drive->mode_yb_7=1;
- current_drive->mode_xb_8=infobuf[8];
- current_drive->delay=0; /* 0, 1, 2, 3 */
- j=cc_set_mode_T();
- i=cc_get_mode_T();
- for (i=0;i<10;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"CMDT_GETMODE:%s\n", msgbuf);
- return (j);
-}
-/*==========================================================================*/
-static int cc_SetSpeed(u_char speed, u_char x1, u_char x2)
-{
- int i;
-
- if (fam0LV_drive) return (0);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x03;
- drvcmd[2]=speed;
- drvcmd[3]=x1;
- drvcmd[4]=x2;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_SETSPEED;
- if (speed&speed_auto)
- {
- drvcmd[2]=0xFF;
- drvcmd[3]=0xFF;
- }
- else
- {
- drvcmd[2]=0;
- drvcmd[3]=150;
- }
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- return (0);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_SetVolume(void)
-{
- int i;
- u_char channel0,channel1,volume0,volume1;
- u_char control0,value0,control1,value1;
-
- current_drive->diskstate_flags &= ~volume_bit;
- clr_cmdbuf();
- channel0=current_drive->vol_chan0;
- volume0=current_drive->vol_ctrl0;
- channel1=control1=current_drive->vol_chan1;
- volume1=value1=current_drive->vol_ctrl1;
- control0=value0=0;
-
- if (famV_drive) return (0);
-
- if (((current_drive->drv_options&audio_mono)!=0)&&(current_drive->drv_type>=drv_211))
- {
- if ((volume0!=0)&&(volume1==0))
- {
- volume1=volume0;
- channel1=channel0;
- }
- else if ((volume0==0)&&(volume1!=0))
- {
- volume0=volume1;
- channel0=channel1;
- }
- }
- if (channel0>1)
- {
- channel0=0;
- volume0=0;
- }
- if (channel1>1)
- {
- channel1=1;
- volume1=0;
- }
-
- if (fam1_drive)
- {
- control0=channel0+1;
- control1=channel1+1;
- value0=(volume0>volume1)?volume0:volume1;
- value1=value0;
- if (volume0==0) control0=0;
- if (volume1==0) control1=0;
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x05;
- drvcmd[3]=control0;
- drvcmd[4]=value0;
- drvcmd[5]=control1;
- drvcmd[6]=value1;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- control0=channel0+1;
- control1=channel1+1;
- value0=(volume0>volume1)?volume0:volume1;
- value1=value0;
- if (volume0==0) control0=0;
- if (volume1==0) control1=0;
- drvcmd[0]=CMD2_SETMODE;
- drvcmd[1]=0x0E;
- drvcmd[3]=control0;
- drvcmd[4]=value0;
- drvcmd[5]=control1;
- drvcmd[6]=value1;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famL_drive)
- {
- if ((volume0==0)||(channel0!=0)) control0 |= 0x80;
- if ((volume1==0)||(channel1!=1)) control0 |= 0x40;
- if (volume0|volume1) value0=0x80;
- drvcmd[0]=CMDL_SETMODE;
- drvcmd[1]=0x03;
- drvcmd[4]=control0;
- drvcmd[5]=value0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam0_drive) /* different firmware levels */
- {
- if (current_drive->drv_type>=drv_300)
- {
- control0=volume0&0xFC;
- value0=volume1&0xFC;
- if ((volume0!=0)&&(volume0<4)) control0 |= 0x04;
- if ((volume1!=0)&&(volume1<4)) value0 |= 0x04;
- if (channel0!=0) control0 |= 0x01;
- if (channel1==1) value0 |= 0x01;
- }
- else
- {
- value0=(volume0>volume1)?volume0:volume1;
- if (current_drive->drv_type<drv_211)
- {
- if (channel0!=0)
- {
- i=channel1;
- channel1=channel0;
- channel0=i;
- i=volume1;
- volume1=volume0;
- volume0=i;
- }
- if (channel0==channel1)
- {
- if (channel0==0)
- {
- channel1=1;
- volume1=0;
- volume0=value0;
- }
- else
- {
- channel0=0;
- volume0=0;
- volume1=value0;
- }
- }
- }
-
- if ((volume0!=0)&&(volume1!=0))
- {
- if (volume0==0xFF) volume1=0xFF;
- else if (volume1==0xFF) volume0=0xFF;
- }
- else if (current_drive->drv_type<drv_201) volume0=volume1=value0;
-
- if (current_drive->drv_type>=drv_201)
- {
- if (volume0==0) control0 |= 0x80;
- if (volume1==0) control0 |= 0x40;
- }
- if (current_drive->drv_type>=drv_211)
- {
- if (channel0!=0) control0 |= 0x20;
- if (channel1!=1) control0 |= 0x10;
- }
- }
- drvcmd[0]=CMD0_SETMODE;
- drvcmd[1]=0x83;
- drvcmd[4]=control0;
- drvcmd[5]=value0;
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- current_drive->volume_control=0;
- if (!volume0) current_drive->volume_control|=0x10;
- if (!volume1) current_drive->volume_control|=0x20;
- i=cc_prep_mode_T();
- if (i<0) return (i);
- }
- if (!famT_drive)
- {
- response_count=0;
- i=cmd_out();
- if (i<0) return (i);
- }
- current_drive->diskstate_flags |= volume_bit;
- return (0);
-}
-/*==========================================================================*/
-static int GetStatus(void)
-{
- int i;
-
- if (famT_drive) return (0);
- flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check;
- response_count=0;
- cmd_type=0;
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_DriveReset(void)
-{
- int i;
-
- msg(DBG_RES,"cc_DriveReset called.\n");
- clr_cmdbuf();
- response_count=0;
- if (fam0LV_drive) OUT(CDo_reset,0x00);
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_RESET;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_RESET;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- OUT(CDo_reset,0x00);
- }
- else if (famT_drive)
- {
- OUT(CDo_sel_i_d,0);
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_command,CMDT_RESET);
- for (i=1;i<10;i++) OUT(CDo_command,0);
- }
- if (fam0LV_drive) sbp_sleep(5*HZ); /* wait 5 seconds */
- else sbp_sleep(1*HZ); /* wait a second */
-#if 1
- if (famT_drive)
- {
- msg(DBG_TEA, "================CMDT_RESET given=================.\n");
- sbp_sleep(3*HZ);
- }
-#endif /* 1 */
- flush_status();
- i=GetStatus();
- if (i<0) return i;
- if (!famT_drive)
- if (current_drive->error_byte!=aud_12) return -501;
- return (0);
-}
-
-/*==========================================================================*/
-static int SetSpeed(void)
-{
- int i, speed;
-
- if (!(current_drive->drv_options&(speed_auto|speed_300|speed_150))) return (0);
- speed=speed_auto;
- if (!(current_drive->drv_options&speed_auto))
- {
- speed |= speed_300;
- if (!(current_drive->drv_options&speed_300)) speed=0;
- }
- i=cc_SetSpeed(speed,0,0);
- return (i);
-}
-
-static void switch_drive(struct sbpcd_drive *);
-
-static int sbpcd_select_speed(struct cdrom_device_info *cdi, int speed)
-{
- struct sbpcd_drive *p = cdi->handle;
- if (p != current_drive)
- switch_drive(p);
-
- return cc_SetSpeed(speed == 2 ? speed_300 : speed_150, 0, 0);
-}
-
-/*==========================================================================*/
-static int DriveReset(void)
-{
- int i;
-
- i=cc_DriveReset();
- if (i<0) return (-22);
- do
- {
- i=GetStatus();
- if ((i<0)&&(i!=-ERR_DISKCHANGE)) {
- return (-2); /* from sta2err */
- }
- if (!st_caddy_in) break;
- sbp_sleep(1);
- }
- while (!st_diskok);
-#if 000
- current_drive->CD_changed=1;
-#endif
- if ((st_door_closed) && (st_caddy_in))
- {
- i=DiskInfo();
- if (i<0) return (-23);
- }
- return (0);
-}
-
-static int sbpcd_reset(struct cdrom_device_info *cdi)
-{
- struct sbpcd_drive *p = cdi->handle;
- if (p != current_drive)
- switch_drive(p);
- return DriveReset();
-}
-
-/*==========================================================================*/
-static int cc_PlayAudio(int pos_audio_start,int pos_audio_end)
-{
- int i, j, n;
-
- if (current_drive->audio_state==audio_playing) return (-EINVAL);
- clr_cmdbuf();
- response_count=0;
- if (famLV_drive)
- {
- drvcmd[0]=CMDL_PLAY;
- i=msf2blk(pos_audio_start);
- n=msf2blk(pos_audio_end)+1-i;
- drvcmd[1]=(i>>16)&0x00FF;
- drvcmd[2]=(i>>8)&0x00FF;
- drvcmd[3]=i&0x00FF;
- drvcmd[4]=(n>>16)&0x00FF;
- drvcmd[5]=(n>>8)&0x00FF;
- drvcmd[6]=n&0x00FF;
- if (famL_drive)
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
- else
- flags_cmd_out = f_putcmd;
- }
- else
- {
- j=1;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
- f_obey_p_check | f_wait_if_busy;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_ResponseStatus | f_obey_p_check;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_PLAY_MSF;
- j=3;
- response_count=1;
- }
- else if (fam0_drive)
- {
- drvcmd[0]=CMD0_PLAY_MSF;
- flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
- f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
- }
- drvcmd[j]=(pos_audio_start>>16)&0x00FF;
- drvcmd[j+1]=(pos_audio_start>>8)&0x00FF;
- drvcmd[j+2]=pos_audio_start&0x00FF;
- drvcmd[j+3]=(pos_audio_end>>16)&0x00FF;
- drvcmd[j+4]=(pos_audio_end>>8)&0x00FF;
- drvcmd[j+5]=pos_audio_end&0x00FF;
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_Pause_Resume(int pau_res)
-{
- int i;
-
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_PAU_RES;
- if (pau_res!=1) drvcmd[1]=0x80;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_PAU_RES;
- if (pau_res!=1) drvcmd[2]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_PAU_RES;
- if (pau_res!=1) drvcmd[1]=0x80;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
- f_obey_p_check|f_bit1;
- else if (famV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|
- f_obey_p_check;
- }
- else if (famT_drive)
- {
- if (pau_res==3) return (cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end));
- else if (pau_res==1) drvcmd[0]=CMDT_PAUSE;
- else return (-56);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int cc_LockDoor(char lock)
-{
- int i;
-
- if (fam0_drive) return (0);
- msg(DBG_LCK,"cc_LockDoor: %d (drive %d)\n", lock, current_drive - D_S);
- msg(DBG_LCS,"p_door_locked bit %d before\n", st_door_locked);
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_LOCK_CTL;
- if (lock==1) drvcmd[1]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_LOCK_CTL;
- if (lock==1) drvcmd[4]=0x01;
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_LOCK_CTL;
- if (lock==1) drvcmd[1]=0x01;
- if (famL_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_LOCK_CTL;
- if (lock==1) drvcmd[4]=0x01;
- }
- i=cmd_out();
- msg(DBG_LCS,"p_door_locked bit %d after\n", st_door_locked);
- return (i);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int UnLockDoor(void)
-{
- int i,j;
-
- j=20;
- do
- {
- i=cc_LockDoor(0);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- if (i<0)
- {
- cc_DriveReset();
- return -84;
- }
- return (0);
-}
-/*==========================================================================*/
-static int LockDoor(void)
-{
- int i,j;
-
- j=20;
- do
- {
- i=cc_LockDoor(1);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- if (j==0)
- {
- cc_DriveReset();
- j=20;
- do
- {
- i=cc_LockDoor(1);
- --j;
- sbp_sleep(1);
- }
- while ((i<0)&&(j));
- }
- return (i);
-}
-
-static int sbpcd_lock_door(struct cdrom_device_info *cdi, int lock)
-{
- return lock ? LockDoor() : UnLockDoor();
-}
-
-/*==========================================================================*/
-static int cc_CloseTray(void)
-{
- int i;
-
- if (fam0_drive) return (0);
- msg(DBG_LCK,"cc_CloseTray (drive %d)\n", current_drive - D_S);
- msg(DBG_LCS,"p_door_closed bit %d before\n", st_door_closed);
-
- clr_cmdbuf();
- response_count=0;
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_TRAY_CTL;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_TRAY_CTL;
- drvcmd[1]=0x01;
- drvcmd[4]=0x03; /* "insert" */
- flags_cmd_out=f_putcmd|f_ResponseStatus;
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_TRAY_CTL;
- if (famLV_drive)
- flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|
- f_ResponseStatus|f_obey_p_check|f_bit1;
- else
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_TRAY_CTL;
- drvcmd[4]=0x03; /* "insert" */
- }
- i=cmd_out();
- msg(DBG_LCS,"p_door_closed bit %d after\n", st_door_closed);
-
- i=cc_ReadError();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus(); /* command: give 1-byte status */
- i=ResponseStatus();
- if (famT_drive&&(i<0))
- {
- cc_DriveReset();
- i=ResponseStatus();
-#if 0
- sbp_sleep(HZ);
-#endif /* 0 */
- i=ResponseStatus();
- }
- if (i<0)
- {
- msg(DBG_INF,"sbpcd cc_CloseTray: ResponseStatus timed out (%d).\n",i);
- }
- if (!(famT_drive))
- {
- if (!st_spinning)
- {
- cc_SpinUp();
- if (st_check) i=cc_ReadError();
- flags_cmd_out |= f_respo2;
- cc_ReadStatus();
- i=ResponseStatus();
- } else {
- }
- }
- i=DiskInfo();
- return (i);
-}
-
-static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
-{
- int retval=0;
- switch_drive(cdi->handle);
- /* DUH! --AJK */
- if(current_drive->CD_changed != 0xFF) {
- current_drive->CD_changed=0xFF;
- current_drive->diskstate_flags &= ~cd_size_bit;
- }
- if (position == 1) {
- cc_SpinDown();
- } else {
- retval=cc_CloseTray();
- }
- return retval;
-}
-
-/*==========================================================================*/
-static int cc_ReadSubQ(void)
-{
- int i,j;
-
- current_drive->diskstate_flags &= ~subq_bit;
- for (j=255;j>0;j--)
- {
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READSUBQ;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- response_count=11;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READSUBQ;
- drvcmd[1]=0x02;
- drvcmd[3]=0x01;
- flags_cmd_out=f_putcmd;
- response_count=10;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READSUBQ;
- drvcmd[1]=0x02;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- response_count=13;
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_READSUBQ;
- drvcmd[1]=0x02;
- drvcmd[2]=0x40;
- drvcmd[3]=0x01;
- drvcmd[8]=response_count;
- }
- i=cmd_out();
- if (i<0) return (i);
- for (i=0;i<response_count;i++)
- {
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_SQ1,"cc_ReadSubQ:%s\n", msgbuf);
- }
- if (famT_drive) break;
- if (infobuf[0]!=0) break;
- if ((!st_spinning) || (j==1))
- {
- current_drive->SubQ_ctl_adr=current_drive->SubQ_trk=current_drive->SubQ_pnt_idx=current_drive->SubQ_whatisthis=0;
- current_drive->SubQ_run_tot=current_drive->SubQ_run_trk=0;
- return (0);
- }
- }
- if (famT_drive) current_drive->SubQ_ctl_adr=infobuf[1];
- else current_drive->SubQ_ctl_adr=swap_nibbles(infobuf[1]);
- current_drive->SubQ_trk=byt2bcd(infobuf[2]);
- current_drive->SubQ_pnt_idx=byt2bcd(infobuf[3]);
- if (fam0LV_drive) i=5;
- else if (fam12_drive) i=4;
- else if (famT_drive) i=8;
- current_drive->SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
- i=7;
- if (fam0LV_drive) i=9;
- else if (fam12_drive) i=7;
- else if (famT_drive) i=4;
- current_drive->SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
- current_drive->SubQ_whatisthis=infobuf[i+3];
- current_drive->diskstate_flags |= subq_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ModeSense(void)
-{
- int i;
-
- if (fam2_drive) return (0);
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~frame_size_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- response_count=5;
- drvcmd[0]=CMD1_GETMODE;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- response_count=2;
- drvcmd[0]=CMD0_GETMODE;
- if (famL_drive) flags_cmd_out=f_putcmd;
- else flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- response_count=10;
- drvcmd[0]=CMDT_GETMODE;
- drvcmd[4]=response_count;
- }
- i=cmd_out();
- if (i<0) return (i);
- i=0;
- current_drive->sense_byte=0;
- if (fam1_drive) current_drive->sense_byte=infobuf[i++];
- else if (famT_drive)
- {
- if (infobuf[4]==0x01) current_drive->xa_byte=0x20;
- else current_drive->xa_byte=0;
- i=2;
- }
- current_drive->frame_size=make16(infobuf[i],infobuf[i+1]);
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_XA1,"cc_ModeSense:%s\n", msgbuf);
-
- current_drive->diskstate_flags |= frame_size_bit;
- return (0);
-}
-/*==========================================================================*/
-/*==========================================================================*/
-static int cc_ModeSelect(int framesize)
-{
- int i;
-
- if (fam2_drive) return (0);
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~frame_size_bit;
- clr_cmdbuf();
- current_drive->frame_size=framesize;
- if (framesize==CD_FRAMESIZE_RAW) current_drive->sense_byte=0x82;
- else current_drive->sense_byte=0x00;
-
- msg(DBG_XA1,"cc_ModeSelect: %02X %04X\n",
- current_drive->sense_byte, current_drive->frame_size);
-
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_SETMODE;
- drvcmd[1]=0x00;
- drvcmd[2]=current_drive->sense_byte;
- drvcmd[3]=(current_drive->frame_size>>8)&0xFF;
- drvcmd[4]=current_drive->frame_size&0xFF;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_SETMODE;
- drvcmd[1]=0x00;
- drvcmd[2]=(current_drive->frame_size>>8)&0xFF;
- drvcmd[3]=current_drive->frame_size&0xFF;
- drvcmd[4]=0x00;
- if(famL_drive)
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- return (-1);
- }
- response_count=0;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->diskstate_flags |= frame_size_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_GetVolume(void)
-{
- int i;
- u_char switches;
- u_char chan0=0;
- u_char vol0=0;
- u_char chan1=1;
- u_char vol1=0;
-
- if (famV_drive) return (0);
- current_drive->diskstate_flags &= ~volume_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_GETMODE;
- drvcmd[1]=0x05;
- response_count=5;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_GETMODE;
- drvcmd[1]=0x0E;
- response_count=5;
- flags_cmd_out=f_putcmd;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_GETMODE;
- drvcmd[1]=0x03;
- response_count=2;
- if(famL_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- i=cc_get_mode_T();
- if (i<0) return (i);
- }
- if (!famT_drive)
- {
- i=cmd_out();
- if (i<0) return (i);
- }
- if (fam1_drive)
- {
- chan0=infobuf[1]&0x0F;
- vol0=infobuf[2];
- chan1=infobuf[3]&0x0F;
- vol1=infobuf[4];
- if (chan0==0)
- {
- chan0=1;
- vol0=0;
- }
- if (chan1==0)
- {
- chan1=2;
- vol1=0;
- }
- chan0 >>= 1;
- chan1 >>= 1;
- }
- else if (fam2_drive)
- {
- chan0=infobuf[1];
- vol0=infobuf[2];
- chan1=infobuf[3];
- vol1=infobuf[4];
- }
- else if (famL_drive)
- {
- chan0=0;
- chan1=1;
- vol0=vol1=infobuf[1];
- switches=infobuf[0];
- if ((switches&0x80)!=0) chan0=1;
- if ((switches&0x40)!=0) chan1=0;
- }
- else if (fam0_drive) /* different firmware levels */
- {
- chan0=0;
- chan1=1;
- vol0=vol1=infobuf[1];
- if (current_drive->drv_type>=drv_201)
- {
- if (current_drive->drv_type<drv_300)
- {
- switches=infobuf[0];
- if ((switches&0x80)!=0) vol0=0;
- if ((switches&0x40)!=0) vol1=0;
- if (current_drive->drv_type>=drv_211)
- {
- if ((switches&0x20)!=0) chan0=1;
- if ((switches&0x10)!=0) chan1=0;
- }
- }
- else
- {
- vol0=infobuf[0];
- if ((vol0&0x01)!=0) chan0=1;
- if ((vol1&0x01)==0) chan1=0;
- vol0 &= 0xFC;
- vol1 &= 0xFC;
- if (vol0!=0) vol0 += 3;
- if (vol1!=0) vol1 += 3;
- }
- }
- }
- else if (famT_drive)
- {
- current_drive->volume_control=infobuf[7];
- chan0=0;
- chan1=1;
- if (current_drive->volume_control&0x10) vol0=0;
- else vol0=0xff;
- if (current_drive->volume_control&0x20) vol1=0;
- else vol1=0xff;
- }
- current_drive->vol_chan0=chan0;
- current_drive->vol_ctrl0=vol0;
- current_drive->vol_chan1=chan1;
- current_drive->vol_ctrl1=vol1;
-#if 000
- current_drive->vol_chan2=2;
- current_drive->vol_ctrl2=0xFF;
- current_drive->vol_chan3=3;
- current_drive->vol_ctrl3=0xFF;
-#endif /* 000 */
- current_drive->diskstate_flags |= volume_bit;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadCapacity(void)
-{
- int i, j;
-
- if (fam2_drive) return (0); /* some firmware lacks this command */
- if (famLV_drive) return (0); /* some firmware lacks this command */
- if (famT_drive) return (0); /* done with cc_ReadTocDescr() */
- current_drive->diskstate_flags &= ~cd_size_bit;
- for (j=3;j>0;j--)
- {
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_CAPACITY;
- response_count=5;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
-#if 00
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_CAPACITY;
- response_count=8;
- flags_cmd_out=f_putcmd;
- }
-#endif
- else if (fam0_drive)
- {
- drvcmd[0]=CMD0_CAPACITY;
- response_count=5;
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- i=cmd_out();
- if (i>=0) break;
- msg(DBG_000,"cc_ReadCapacity: cmd_out: err %d\n", i);
- cc_ReadError();
- }
- if (j==0) return (i);
- if (fam1_drive) current_drive->CDsize_frm=msf2blk(make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2])))+CD_MSF_OFFSET;
- else if (fam0_drive) current_drive->CDsize_frm=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
-#if 00
- else if (fam2_drive) current_drive->CDsize_frm=make32(make16(infobuf[0],infobuf[1]),make16(infobuf[2],infobuf[3]));
-#endif
- current_drive->diskstate_flags |= cd_size_bit;
- msg(DBG_000,"cc_ReadCapacity: %d frames.\n", current_drive->CDsize_frm);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocDescr(void)
-{
- int i;
-
- current_drive->diskstate_flags &= ~toc_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_DISKINFO;
- response_count=6;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_DISKINFO;
- response_count=6;
- if(famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- /* possibly longer timeout periods necessary */
- current_drive->f_multisession=0;
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAB;
- drvcmd[3]=0xFF; /* session */
- response_count=8;
- flags_cmd_out=f_putcmd;
- }
- else if (famT_drive)
- {
- current_drive->f_multisession=0;
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=CDROM_LEADOUT;
- drvcmd[8]=response_count;
- drvcmd[9]=0x00;
- }
- i=cmd_out();
- if (i<0) return (i);
- if ((famT_drive)&&(i<response_count)) return (-100-i);
- if ((fam1_drive)||(fam2_drive)||(fam0LV_drive))
- current_drive->xa_byte=infobuf[0];
- if (fam2_drive)
- {
- current_drive->first_session=infobuf[1];
- current_drive->last_session=infobuf[2];
- current_drive->n_first_track=infobuf[3];
- current_drive->n_last_track=infobuf[4];
- if (current_drive->first_session!=current_drive->last_session)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7])));
- }
-#if 0
- if (current_drive->first_session!=current_drive->last_session)
- {
- if (current_drive->last_session<=20)
- zwanzig=current_drive->last_session+1;
- else zwanzig=20;
- for (count=current_drive->first_session;count<zwanzig;count++)
- {
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAB;
- drvcmd[3]=count;
- response_count=8;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->msf_multi_n[count]=make32(make16(0,infobuf[5]),make16(infobuf[6],infobuf[7]));
- }
- current_drive->diskstate_flags |= multisession_bit;
- }
-#endif
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=0xAA;
- drvcmd[3]=0xFF;
- response_count=5;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->size_msf=make32(make16(0,infobuf[2]),make16(infobuf[3],infobuf[4]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- current_drive->CDsize_frm=current_drive->size_blk+1;
- }
- else if (famT_drive)
- {
- current_drive->size_msf=make32(make16(infobuf[8],infobuf[9]),make16(infobuf[10],infobuf[11]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- current_drive->CDsize_frm=current_drive->size_blk+1;
- current_drive->n_first_track=infobuf[2];
- current_drive->n_last_track=infobuf[3];
- }
- else
- {
- current_drive->n_first_track=infobuf[1];
- current_drive->n_last_track=infobuf[2];
- current_drive->size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
- current_drive->size_blk=msf2blk(current_drive->size_msf);
- if (famLV_drive) current_drive->CDsize_frm=current_drive->size_blk+1;
- }
- current_drive->diskstate_flags |= toc_bit;
- msg(DBG_TOC,"TocDesc: xa %02X firstt %02X lastt %02X size %08X firstses %02X lastsess %02X\n",
- current_drive->xa_byte,
- current_drive->n_first_track,
- current_drive->n_last_track,
- current_drive->size_msf,
- current_drive->first_session,
- current_drive->last_session);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadTocEntry(int num)
-{
- int i;
-
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READTOC;
- drvcmd[2]=num;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam2_drive)
- {
- /* possibly longer timeout periods necessary */
- drvcmd[0]=CMD2_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[2]=num;
- response_count=5;
- flags_cmd_out=f_putcmd;
- }
- else if (fam0LV_drive)
- {
- drvcmd[0]=CMD0_READTOC;
- drvcmd[1]=0x02;
- drvcmd[2]=num;
- response_count=8;
- if (famLV_drive)
- flags_cmd_out=f_putcmd;
- else
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=num;
- drvcmd[8]=response_count;
- drvcmd[9]=0x00;
- }
- i=cmd_out();
- if (i<0) return (i);
- if ((famT_drive)&&(i<response_count)) return (-100-i);
- if ((fam1_drive)||(fam0LV_drive))
- {
- current_drive->TocEnt_nixbyte=infobuf[0];
- i=1;
- }
- else if (fam2_drive) i=0;
- else if (famT_drive) i=5;
- current_drive->TocEnt_ctl_adr=swap_nibbles(infobuf[i++]);
- if ((fam1_drive)||(fam0L_drive))
- {
- current_drive->TocEnt_number=infobuf[i++];
- current_drive->TocEnt_format=infobuf[i];
- }
- else
- {
- current_drive->TocEnt_number=num;
- current_drive->TocEnt_format=0;
- }
- if (fam1_drive) i=4;
- else if (fam0LV_drive) i=5;
- else if (fam2_drive) i=2;
- else if (famT_drive) i=9;
- current_drive->TocEnt_address=make32(make16(0,infobuf[i]),
- make16(infobuf[i+1],infobuf[i+2]));
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"TocEntry:%s\n", msgbuf);
- msg(DBG_TOC,"TocEntry: %02X %02X %02X %02X %08X\n",
- current_drive->TocEnt_nixbyte, current_drive->TocEnt_ctl_adr,
- current_drive->TocEnt_number, current_drive->TocEnt_format,
- current_drive->TocEnt_address);
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadPacket(void)
-{
- int i;
-
- clr_cmdbuf();
- drvcmd[0]=CMD0_PACKET;
- drvcmd[1]=response_count;
- if(famL_drive) flags_cmd_out=f_putcmd;
- else if (fam01_drive)
- flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
- else if (fam2_drive) return (-1); /* not implemented yet */
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- return (i);
-}
-/*==========================================================================*/
-static int convert_UPC(u_char *p)
-{
- int i;
-
- p++;
- if (fam0L_drive) p[13]=0;
- for (i=0;i<7;i++)
- {
- if (fam1_drive) current_drive->UPC_buf[i]=swap_nibbles(*p++);
- else if (fam0L_drive)
- {
- current_drive->UPC_buf[i]=((*p++)<<4)&0xFF;
- current_drive->UPC_buf[i] |= *p++;
- }
- else if (famT_drive)
- {
- return (-1);
- }
- else /* CD200 */
- {
- return (-1);
- }
- }
- current_drive->UPC_buf[6] &= 0xF0;
- return (0);
-}
-/*==========================================================================*/
-static int cc_ReadUPC(void)
-{
- int i;
-#if TEST_UPC
- int block, checksum;
-#endif /* TEST_UPC */
-
- if (fam2_drive) return (0); /* not implemented yet */
- if (famT_drive) return (0); /* not implemented yet */
- if (famV_drive) return (0); /* not implemented yet */
-#if 1
- if (fam0_drive) return (0); /* but it should work */
-#endif
-
- current_drive->diskstate_flags &= ~upc_bit;
-#if TEST_UPC
- for (block=CD_MSF_OFFSET+1;block<CD_MSF_OFFSET+200;block++)
- {
-#endif /* TEST_UPC */
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_UPC;
-#if TEST_UPC
- drvcmd[1]=(block>>16)&0xFF;
- drvcmd[2]=(block>>8)&0xFF;
- drvcmd[3]=block&0xFF;
-#endif /* TEST_UPC */
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_READ_UPC;
-#if TEST_UPC
- drvcmd[2]=(block>>16)&0xFF;
- drvcmd[3]=(block>>8)&0xFF;
- drvcmd[4]=block&0xFF;
-#endif /* TEST_UPC */
- response_count=0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam2_drive)
- {
- return (-1);
- }
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
- return (i);
- }
- if (fam0L_drive)
- {
- response_count=16;
- if (famL_drive) flags_cmd_out=f_putcmd;
- i=cc_ReadPacket();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
- return (i);
- }
- }
-#if TEST_UPC
- checksum=0;
-#endif /* TEST_UPC */
- for (i=0;i<(fam1_drive?8:16);i++)
- {
-#if TEST_UPC
- checksum |= infobuf[i];
-#endif /* TEST_UPC */
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- }
- msgbuf[i*3]=0;
- msg(DBG_UPC,"UPC info:%s\n", msgbuf);
-#if TEST_UPC
- if ((checksum&0x7F)!=0) break;
- }
-#endif /* TEST_UPC */
- current_drive->UPC_ctl_adr=0;
- if (fam1_drive) i=0;
- else i=2;
- if ((infobuf[i]&0x80)!=0)
- {
- convert_UPC(&infobuf[i]);
- current_drive->UPC_ctl_adr = (current_drive->TocEnt_ctl_adr & 0xF0) | 0x02;
- }
- for (i=0;i<7;i++)
- sprintf(&msgbuf[i*3], " %02X", current_drive->UPC_buf[i]);
- sprintf(&msgbuf[i*3], " (%02X)", current_drive->UPC_ctl_adr);
- msgbuf[i*3+5]=0;
- msg(DBG_UPC,"UPC code:%s\n", msgbuf);
- current_drive->diskstate_flags |= upc_bit;
- return (0);
-}
-
-static int sbpcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
-{
- int i;
- unsigned char *mcnp = mcn->medium_catalog_number;
- unsigned char *resp;
-
- current_drive->diskstate_flags &= ~upc_bit;
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ_UPC;
- response_count=8;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- }
- else if (fam0L_drive)
- {
- drvcmd[0]=CMD0_READ_UPC;
- response_count=0;
- flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
- }
- else if (fam2_drive)
- {
- return (-1);
- }
- else if (famT_drive)
- {
- return (-1);
- }
- i=cmd_out();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC cmd_out: err %d\n", i);
- return (i);
- }
- if (fam0L_drive)
- {
- response_count=16;
- if (famL_drive) flags_cmd_out=f_putcmd;
- i=cc_ReadPacket();
- if (i<0)
- {
- msg(DBG_000,"cc_ReadUPC ReadPacket: err %d\n", i);
- return (i);
- }
- }
- current_drive->UPC_ctl_adr=0;
- if (fam1_drive) i=0;
- else i=2;
-
- resp = infobuf + i;
- if (*resp++ == 0x80) {
- /* packed bcd to single ASCII digits */
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- *mcnp++ = (*resp++ & 0x0f) + '0';
- *mcnp++ = (*resp >> 4) + '0';
- }
- *mcnp = '\0';
-
- current_drive->diskstate_flags |= upc_bit;
- return (0);
-}
-
-/*==========================================================================*/
-static int cc_CheckMultiSession(void)
-{
- int i;
-
- if (fam2_drive) return (0);
- current_drive->f_multisession=0;
- current_drive->lba_multi=0;
- if (fam0_drive) return (0);
- clr_cmdbuf();
- if (fam1_drive)
- {
- drvcmd[0]=CMD1_MULTISESS;
- response_count=6;
- flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
- i=cmd_out();
- if (i<0) return (i);
- if ((infobuf[0]&0x80)!=0)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[1]),
- make16(infobuf[2],infobuf[3])));
- }
- }
- else if (famLV_drive)
- {
- drvcmd[0]=CMDL_MULTISESS;
- drvcmd[1]=3;
- drvcmd[2]=1;
- response_count=8;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) return (i);
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[5]),
- make16(infobuf[6],infobuf[7])));
- }
- else if (famT_drive)
- {
- response_count=12;
- drvcmd[0]=CMDT_DISKINFO;
- drvcmd[1]=0x02;
- drvcmd[6]=0;
- drvcmd[8]=response_count;
- drvcmd[9]=0x40;
- i=cmd_out();
- if (i<0) return (i);
- if (i<response_count) return (-100-i);
- current_drive->first_session=infobuf[2];
- current_drive->last_session=infobuf[3];
- current_drive->track_of_last_session=infobuf[6];
- if (current_drive->first_session!=current_drive->last_session)
- {
- current_drive->f_multisession=1;
- current_drive->lba_multi=msf2blk(make32(make16(0,infobuf[9]),make16(infobuf[10],infobuf[11])));
- }
- }
- for (i=0;i<response_count;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_MUL,"MultiSession Info:%s (%d)\n", msgbuf, current_drive->lba_multi);
- if (current_drive->lba_multi>200)
- {
- current_drive->f_multisession=1;
- msg(DBG_MUL,"MultiSession base: %06X\n", current_drive->lba_multi);
- }
- return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-static int cc_SubChanInfo(int frame, int count, u_char *buffer)
- /* "frame" is a RED BOOK (msf-bin) address */
-{
- int i;
-
- if (fam0LV_drive) return (-ENOSYS); /* drive firmware lacks it */
- if (famT_drive)
- {
- return (-1);
- }
-#if 0
- if (current_drive->audio_state!=audio_playing) return (-ENODATA);
-#endif
- clr_cmdbuf();
- drvcmd[0]=CMD1_SUBCHANINF;
- drvcmd[1]=(frame>>16)&0xFF;
- drvcmd[2]=(frame>>8)&0xFF;
- drvcmd[3]=frame&0xFF;
- drvcmd[5]=(count>>8)&0xFF;
- drvcmd[6]=count&0xFF;
- flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
- cmd_type=READ_SC;
- current_drive->frame_size=CD_FRAMESIZE_SUB;
- i=cmd_out(); /* which buffer to use? */
- return (i);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-static void __init check_datarate(void)
-{
- int i=0;
-
- msg(DBG_IOX,"check_datarate entered.\n");
- datarate=0;
-#if TEST_STI
- for (i=0;i<=1000;i++) printk(".");
-#endif
- /* set a timer to make (timed_out_delay!=0) after 1.1 seconds */
-#if 1
- del_timer(&delay_timer);
-#endif
- delay_timer.expires=jiffies+11*HZ/10;
- timed_out_delay=0;
- add_timer(&delay_timer);
-#if 0
- msg(DBG_TIM,"delay timer started (11*HZ/10).\n");
-#endif
- do
- {
- i=inb(CDi_status);
- datarate++;
-#if 1
- if (datarate>0x6FFFFFFF) break;
-#endif
- }
- while (!timed_out_delay);
- del_timer(&delay_timer);
-#if 0
- msg(DBG_TIM,"datarate: %04X\n", datarate);
-#endif
- if (datarate<65536) datarate=65536;
- maxtim16=datarate*16;
- maxtim04=datarate*4;
- maxtim02=datarate*2;
- maxtim_8=datarate/32;
-#if LONG_TIMING
- maxtim_data=datarate/100;
-#else
- maxtim_data=datarate/300;
-#endif /* LONG_TIMING */
-#if 0
- msg(DBG_TIM,"maxtim_8 %d, maxtim_data %d.\n", maxtim_8, maxtim_data);
-#endif
-}
-/*==========================================================================*/
-#if 0
-static int c2_ReadError(int fam)
-{
- int i;
-
- clr_cmdbuf();
- response_count=9;
- clr_respo_buf(9);
- if (fam==1)
- {
- drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
- i=do_cmd(f_putcmd|f_lopsta|f_getsta|f_ResponseStatus);
- }
- else if (fam==2)
- {
- drvcmd[0]=CMD2_READ_ERR;
- i=do_cmd(f_putcmd);
- }
- else return (-1);
- return (i);
-}
-#endif
-/*==========================================================================*/
-static void __init ask_mail(void)
-{
- int i;
-
- msg(DBG_INF, "please mail the following lines to emoenke@gwdg.de\n");
- msg(DBG_INF, "(don't mail if you are not using the actual kernel):\n");
- msg(DBG_INF, "%s\n", VERSION);
- msg(DBG_INF, "address %03X, type %s, drive %s (ID %d)\n",
- CDo_command, type, current_drive->drive_model, current_drive->drv_id);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_INF,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_INF,"infobuf =%s\n", msgbuf);
-}
-/*==========================================================================*/
-static int __init check_version(void)
-{
- int i, j, l;
- int teac_possible=0;
-
- msg(DBG_INI,"check_version: id=%d, d=%d.\n", current_drive->drv_id, current_drive - D_S);
- current_drive->drv_type=0;
-
- /* check for CR-52x, CR-56x, LCS-7260 and ECS-AT */
- /* clear any pending error state */
- clr_cmdbuf();
- drvcmd[0]=CMD0_READ_ERR; /* same as CMD1_ and CMDL_ */
- response_count=9;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD0_READ_ERR returns %d (ok anyway).\n",i);
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- drvcmd[0]=CMD0_READ_VER; /* same as CMD1_ and CMDL_ */
- response_count=12; /* fam1: only 11 */
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<-1) msg(DBG_INI,"CMD0_READ_VER returns %d\n",i);
- if (i==-11) teac_possible++;
- j=0;
- for (i=0;i<12;i++) j+=infobuf[i];
- if (j)
- {
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_ECS,"infobuf =%s\n", msgbuf);
- }
- for (i=0;i<4;i++) if (infobuf[i]!=family1[i]) break;
- if (i==4)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='R';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]=infobuf[i++];
- current_drive->drive_model[5]=infobuf[i++];
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_fam1;
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<8;i++) if (infobuf[i]!=family0[i]) break;
- if (i==8)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='R';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]='2';
- current_drive->drive_model[5]='x';
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_fam0;
- }
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<8;i++) if (infobuf[i]!=familyL[i]) break;
- if (i==8)
- {
- for (j=0;j<8;j++)
- current_drive->drive_model[j]=infobuf[j];
- current_drive->drive_model[8]=0;
- current_drive->drv_type=drv_famL;
- }
- }
- if (!current_drive->drv_type)
- {
- for (i=0;i<6;i++) if (infobuf[i]!=familyV[i]) break;
- if (i==6)
- {
- for (j=0;j<6;j++)
- current_drive->drive_model[j]=infobuf[j];
- current_drive->drive_model[6]=0;
- current_drive->drv_type=drv_famV;
- i+=2; /* 2 blanks before version */
- }
- }
- if (!current_drive->drv_type)
- {
- /* check for CD200 */
- clr_cmdbuf();
- drvcmd[0]=CMD2_READ_ERR;
- response_count=9;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD2_READERR returns %d (ok anyway).\n",i);
- if (i<0) msg(DBG_000,"CMD2_READERR returns %d (ok anyway).\n",i);
- /* read drive version */
- clr_cmdbuf();
- for (i=0;i<12;i++) infobuf[i]=0;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
-#if 0
- OUT(CDo_reset,0);
- sbp_sleep(6*HZ);
- OUT(CDo_enable,current_drive->drv_sel);
-#endif
- drvcmd[0]=CMD2_READ_VER;
- response_count=12;
- flags_cmd_out=f_putcmd;
- i=cmd_out();
- if (i<0) msg(DBG_INI,"CMD2_READ_VER returns %d\n",i);
- if (i==-7) teac_possible++;
- j=0;
- for (i=0;i<12;i++) j+=infobuf[i];
- if (j)
- {
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %02X", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_IDX,"infobuf =%s\n", msgbuf);
- for (i=0;i<12;i++)
- sprintf(&msgbuf[i*3], " %c ", infobuf[i]);
- msgbuf[i*3]=0;
- msg(DBG_IDX,"infobuf =%s\n", msgbuf);
- }
- if (i>=0)
- {
- for (i=0;i<5;i++) if (infobuf[i]!=family2[i]) break;
- if (i==5)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='D';
- current_drive->drive_model[2]='2';
- current_drive->drive_model[3]='0';
- current_drive->drive_model[4]='0';
- current_drive->drive_model[5]=infobuf[i++];
- current_drive->drive_model[6]=infobuf[i++];
- current_drive->drive_model[7]=0;
- current_drive->drv_type=drv_fam2;
- }
- }
- }
- if (!current_drive->drv_type)
- {
- /* check for TEAC CD-55A */
- msg(DBG_TEA,"teac_possible: %d\n",teac_possible);
- for (j=1;j<=((current_drive->drv_id==0)?3:1);j++)
- {
- for (l=1;l<=((current_drive->drv_id==0)?10:1);l++)
- {
- msg(DBG_TEA,"TEAC reset #%d-%d.\n", j, l);
- if (sbpro_type==1) OUT(CDo_reset,0);
- else
- {
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_sel_i_d,0);
- OUT(CDo_command,CMDT_RESET);
- for (i=0;i<9;i++) OUT(CDo_command,0);
- }
- sbp_sleep(5*HZ/10);
- OUT(CDo_enable,current_drive->drv_sel);
- OUT(CDo_sel_i_d,0);
- i=inb(CDi_status);
- msg(DBG_TEA,"TEAC CDi_status: %02X.\n",i);
-#if 0
- if (i&s_not_result_ready) continue; /* drive not present or ready */
-#endif
- i=inb(CDi_info);
- msg(DBG_TEA,"TEAC CDi_info: %02X.\n",i);
- if (i==0x55) break; /* drive found */
- }
- if (i==0x55) break; /* drive found */
- }
- if (i==0x55) /* drive found */
- {
- msg(DBG_TEA,"TEAC drive found.\n");
- clr_cmdbuf();
- flags_cmd_out=f_putcmd;
- response_count=12;
- drvcmd[0]=CMDT_READ_VER;
- drvcmd[4]=response_count;
- for (i=0;i<12;i++) infobuf[i]=0;
- i=cmd_out_T();
- if (i!=0) msg(DBG_TEA,"cmd_out_T(CMDT_READ_VER) returns %d.\n",i);
- for (i=1;i<6;i++) if (infobuf[i]!=familyT[i-1]) break;
- if (i==6)
- {
- current_drive->drive_model[0]='C';
- current_drive->drive_model[1]='D';
- current_drive->drive_model[2]='-';
- current_drive->drive_model[3]='5';
- current_drive->drive_model[4]='5';
- current_drive->drive_model[5]=0;
- current_drive->drv_type=drv_famT;
- }
- }
- }
- if (!current_drive->drv_type)
- {
- msg(DBG_TEA,"no drive found at address %03X under ID %d.\n",CDo_command,current_drive->drv_id);
- return (-522);
- }
- for (j=0;j<4;j++) current_drive->firmware_version[j]=infobuf[i+j];
- if (famL_drive)
- {
- u_char lcs_firm_e1[]="A E1";
- u_char lcs_firm_f4[]="A4F4";
-
- for (j=0;j<4;j++)
- if (current_drive->firmware_version[j]!=lcs_firm_e1[j]) break;
- if (j==4) current_drive->drv_type=drv_e1;
-
- for (j=0;j<4;j++)
- if (current_drive->firmware_version[j]!=lcs_firm_f4[j]) break;
- if (j==4) current_drive->drv_type=drv_f4;
-
- if (current_drive->drv_type==drv_famL) ask_mail();
- }
- else if (famT_drive)
- {
- j=infobuf[4]; /* one-byte version??? - here: 0x15 */
- if (j=='5')
- {
- current_drive->firmware_version[0]=infobuf[7];
- current_drive->firmware_version[1]=infobuf[8];
- current_drive->firmware_version[2]=infobuf[10];
- current_drive->firmware_version[3]=infobuf[11];
- }
- else
- {
- if (j!=0x15) ask_mail();
- current_drive->firmware_version[0]='0';
- current_drive->firmware_version[1]='.';
- current_drive->firmware_version[2]='0'+(j>>4);
- current_drive->firmware_version[3]='0'+(j&0x0f);
- }
- }
- else /* CR-52x, CR-56x, CD200, ECS-AT */
- {
- j = (current_drive->firmware_version[0] & 0x0F) * 100 +
- (current_drive->firmware_version[2] & 0x0F) *10 +
- (current_drive->firmware_version[3] & 0x0F);
- if (fam0_drive)
- {
- if (j<200) current_drive->drv_type=drv_199;
- else if (j<201) current_drive->drv_type=drv_200;
- else if (j<210) current_drive->drv_type=drv_201;
- else if (j<211) current_drive->drv_type=drv_210;
- else if (j<300) current_drive->drv_type=drv_211;
- else if (j>=300) current_drive->drv_type=drv_300;
- }
- else if (fam1_drive)
- {
- if (j<100) current_drive->drv_type=drv_099;
- else
- {
- current_drive->drv_type=drv_100;
- if ((j!=500)&&(j!=102)) ask_mail();
- }
- }
- else if (fam2_drive)
- {
- if (current_drive->drive_model[5]=='F')
- {
- if ((j!=1)&&(j!=35)&&(j!=200)&&(j!=210))
- ask_mail(); /* unknown version at time */
- }
- else
- {
- msg(DBG_INF,"this CD200 drive is not fully supported yet - only audio will work.\n");
- if ((j!=101)&&(j!=35))
- ask_mail(); /* unknown version at time */
- }
- }
- else if (famV_drive)
- {
- if ((j==100)||(j==150)) current_drive->drv_type=drv_at;
- ask_mail(); /* hopefully we get some feedback by this */
- }
- }
- msg(DBG_LCS,"drive type %02X\n",current_drive->drv_type);
- msg(DBG_INI,"check_version done.\n");
- return (0);
-}
-/*==========================================================================*/
-static void switch_drive(struct sbpcd_drive *p)
-{
- current_drive = p;
- OUT(CDo_enable,current_drive->drv_sel);
- msg(DBG_DID,"drive %d (ID=%d) activated.\n",
- current_drive - D_S, current_drive->drv_id);
- return;
-}
-/*==========================================================================*/
-#ifdef PATH_CHECK
-/*
- * probe for the presence of an interface card
- */
-static int __init check_card(int port)
-{
-#undef N_RESPO
-#define N_RESPO 20
- int i, j, k;
- u_char response[N_RESPO];
- u_char save_port0;
- u_char save_port3;
-
- msg(DBG_INI,"check_card entered.\n");
- save_port0=inb(port+0);
- save_port3=inb(port+3);
-
- for (j=0;j<NR_SBPCD;j++)
- {
- OUT(port+3,j) ; /* enable drive #j */
- OUT(port+0,CMD0_PATH_CHECK);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=10000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
- OUT(port+0,CMD0_PATH_CHECK);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0xFF;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=10000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 00 (%d): %s\n", j, msgbuf);
-
- if (response[0]==0xAA)
- if (response[1]==0x55)
- return (0);
- }
- for (j=0;j<NR_SBPCD;j++)
- {
- OUT(port+3,j) ; /* enable drive #j */
- OUT(port+0,CMD2_READ_VER);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=1000000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
- OUT(port+0,CMD2_READ_VER);
- for (i=10;i>0;i--) OUT(port+0,0);
- for (k=0;k<N_RESPO;k++) response[k]=0xFF;
- for (k=0;k<N_RESPO;k++)
- {
- for (i=1000000;i>0;i--)
- {
- if (inb(port+1)&s_not_result_ready) continue;
- response[k]=inb(port+0);
- break;
- }
- }
- for (i=0;i<N_RESPO;i++)
- sprintf(&msgbuf[i*3], " %02X", response[i]);
- msgbuf[i*3]=0;
- msg(DBG_TEA,"path check 12 (%d): %s\n", j, msgbuf);
-
- if (response[0]==0xAA)
- if (response[1]==0x55)
- return (0);
- }
- OUT(port+0,save_port0);
- OUT(port+3,save_port3);
- return (0); /* in any case - no real "function" at time */
-}
-#endif /* PATH_CHECK */
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * probe for the presence of drives on the selected controller
- */
-static int __init check_drives(void)
-{
- int i, j;
-
- msg(DBG_INI,"check_drives entered.\n");
- ndrives=0;
- for (j=0;j<max_drives;j++)
- {
- struct sbpcd_drive *p = D_S + ndrives;
- p->drv_id=j;
- if (sbpro_type==1) p->drv_sel=(j&0x01)<<1|(j&0x02)>>1;
- else p->drv_sel=j;
- switch_drive(p);
- msg(DBG_INI,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
- msg(DBG_000,"check_drives: drive %d (ID=%d) activated.\n",ndrives,j);
- i=check_version();
- if (i<0) msg(DBG_INI,"check_version returns %d.\n",i);
- else
- {
- current_drive->drv_options=drv_pattern[j];
- if (fam0L_drive) current_drive->drv_options&=~(speed_auto|speed_300|speed_150);
- msg(DBG_INF, "Drive %d (ID=%d): %.9s (%.4s) at 0x%03X (type %d)\n",
- current_drive - D_S,
- current_drive->drv_id,
- current_drive->drive_model,
- current_drive->firmware_version,
- CDo_command,
- sbpro_type);
- ndrives++;
- }
- }
- for (j=ndrives;j<NR_SBPCD;j++) D_S[j].drv_id=-1;
- if (ndrives==0) return (-1);
- return (0);
-}
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- * obtain if requested service disturbs current audio state
- */
-static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc)
-{
- switch (audio_state) /* audio status from controller */
- {
- case aud_11: /* "audio play in progress" */
- case audx11:
- switch (func) /* DOS command code */
- {
- case cmd_07: /* input flush */
- case cmd_0d: /* open device */
- case cmd_0e: /* close device */
- case cmd_0c: /* ioctl output */
- return (1);
- case cmd_03: /* ioctl input */
- switch (subfunc)
- /* DOS ioctl input subfunction */
- {
- case cxi_00:
- case cxi_06:
- case cxi_09:
- return (1);
- default:
- return (ERROR15);
- }
- return (1);
- default:
- return (ERROR15);
- }
- return (1);
- case aud_12: /* "audio play paused" */
- case audx12:
- return (1);
- default:
- return (2);
- }
-}
-/*==========================================================================*/
-/* allowed is only
- * ioctl_o, flush_input, open_device, close_device,
- * tell_address, tell_volume, tell_capabiliti,
- * tell_framesize, tell_CD_changed, tell_audio_posi
- */
-static int check_allowed1(u_char func1, u_char func2)
-{
-#if 000
- if (func1==ioctl_o) return (0);
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1==audio_pause) return (-1);
- if (func1==audio_resume) return (-1);
- if (func1!=ioctl_i) return (0);
- if (func2==tell_SubQ_run_tot) return (-1);
- if (func2==tell_cdsize) return (-1);
- if (func2==tell_TocDescrip) return (-1);
- if (func2==tell_TocEntry) return (-1);
- if (func2==tell_subQ_info) return (-1);
- if (fam1_drive) if (func2==tell_SubChanInfo) return (-1);
- if (func2==tell_UPC) return (-1);
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed2(u_char func1, u_char func2)
-{
-#if 000
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1!=ioctl_o) return (0);
- if (fam1_drive)
- {
- if (func2==EjectDisk) return (-1);
- if (func2==CloseTray) return (-1);
- }
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int check_allowed3(u_char func1, u_char func2)
-{
-#if 000
- if (func1==ioctl_i)
- {
- if (func2==tell_address) return (0);
- if (func2==tell_capabiliti) return (0);
- if (func2==tell_CD_changed) return (0);
- if (fam0L_drive) if (func2==tell_SubChanInfo) return (0);
- return (-1);
- }
- if (func1==ioctl_o)
- {
- if (func2==DriveReset) return (0);
- if (fam0L_drive)
- {
- if (func2==EjectDisk) return (0);
- if (func2==LockDoor) return (0);
- if (func2==CloseTray) return (0);
- }
- return (-1);
- }
- if (func1==flush_input) return (-1);
- if (func1==read_long) return (-1);
- if (func1==read_long_prefetch) return (-1);
- if (func1==seek) return (-1);
- if (func1==audio_play) return (-1);
- if (func1==audio_pause) return (-1);
- if (func1==audio_resume) return (-1);
-#else
- return (0);
-#endif
-}
-/*==========================================================================*/
-static int seek_pos_audio_end(void)
-{
- int i;
-
- i=msf2blk(current_drive->pos_audio_end)-1;
- if (i<0) return (-1);
- i=cc_Seek(i,0);
- return (i);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-static int ReadToC(void)
-{
- int i, j;
- current_drive->diskstate_flags &= ~toc_bit;
- current_drive->ored_ctl_adr=0;
- /* special handling of CD-I HE */
- if ((current_drive->n_first_track == 2 && current_drive->n_last_track == 2) ||
- current_drive->xa_byte == 0x10)
- {
- current_drive->TocBuffer[1].nixbyte=0;
- current_drive->TocBuffer[1].ctl_adr=0x40;
- current_drive->TocBuffer[1].number=1;
- current_drive->TocBuffer[1].format=0;
- current_drive->TocBuffer[1].address=blk2msf(0);
- current_drive->ored_ctl_adr |= 0x40;
- current_drive->n_first_track = 1;
- current_drive->n_last_track = 1;
- current_drive->xa_byte = 0x10;
- j = 2;
- } else
- for (j=current_drive->n_first_track;j<=current_drive->n_last_track;j++)
- {
- i=cc_ReadTocEntry(j);
- if (i<0)
- {
- msg(DBG_INF,"cc_ReadTocEntry(%d) returns %d.\n",j,i);
- return (i);
- }
- current_drive->TocBuffer[j].nixbyte=current_drive->TocEnt_nixbyte;
- current_drive->TocBuffer[j].ctl_adr=current_drive->TocEnt_ctl_adr;
- current_drive->TocBuffer[j].number=current_drive->TocEnt_number;
- current_drive->TocBuffer[j].format=current_drive->TocEnt_format;
- current_drive->TocBuffer[j].address=current_drive->TocEnt_address;
- current_drive->ored_ctl_adr |= current_drive->TocEnt_ctl_adr;
- }
- /* fake entry for LeadOut Track */
- current_drive->TocBuffer[j].nixbyte=0;
- current_drive->TocBuffer[j].ctl_adr=0;
- current_drive->TocBuffer[j].number=CDROM_LEADOUT;
- current_drive->TocBuffer[j].format=0;
- current_drive->TocBuffer[j].address=current_drive->size_msf;
-
- current_drive->diskstate_flags |= toc_bit;
- return (0);
-}
-/*==========================================================================*/
-static int DiskInfo(void)
-{
- int i, j;
-
- current_drive->mode=READ_M1;
-
-#undef LOOP_COUNT
-#define LOOP_COUNT 10 /* needed for some "old" drives */
-
- msg(DBG_000,"DiskInfo entered.\n");
- for (j=1;j<LOOP_COUNT;j++)
- {
-#if 0
- i=SetSpeed();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: SetSpeed returns %d\n", i);
- continue;
- }
- i=cc_ModeSense();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_ModeSense returns %d\n", i);
- continue;
- }
-#endif
- i=cc_ReadCapacity();
- if (i>=0) break;
- msg(DBG_INF,"DiskInfo: ReadCapacity #%d returns %d\n", j, i);
-#if 0
- i=cc_DriveReset();
-#endif
- if (!fam0_drive && j == 2) break;
- }
- if (j==LOOP_COUNT) return (-33); /* give up */
-
- i=cc_ReadTocDescr();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: ReadTocDescr returns %d\n", i);
- return (i);
- }
- i=ReadToC();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: ReadToC returns %d\n", i);
- return (i);
- }
- i=cc_CheckMultiSession();
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_CheckMultiSession returns %d\n", i);
- return (i);
- }
- if (current_drive->f_multisession) current_drive->sbp_bufsiz=1; /* possibly a weird PhotoCD */
- else current_drive->sbp_bufsiz=buffers;
- i=cc_ReadTocEntry(current_drive->n_first_track);
- if (i<0)
- {
- msg(DBG_INF,"DiskInfo: cc_ReadTocEntry(1) returns %d\n", i);
- return (i);
- }
- i=cc_ReadUPC();
- if (i<0) msg(DBG_INF,"DiskInfo: cc_ReadUPC returns %d\n", i);
- if ((fam0L_drive) && (current_drive->xa_byte==0x20 || current_drive->xa_byte == 0x10))
- {
- /* XA disk with old drive */
- cc_ModeSelect(CD_FRAMESIZE_RAW1);
- cc_ModeSense();
- }
- if (famT_drive) cc_prep_mode_T();
- msg(DBG_000,"DiskInfo done.\n");
- return (0);
-}
-
-static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
-{
- struct sbpcd_drive *p = cdi->handle;
- int st;
-
- if (CDSL_CURRENT != slot_nr) {
- /* we have no changer support */
- return -EINVAL;
- }
-
- cc_ReadStatus();
- st=ResponseStatus();
- if (st<0)
- {
- msg(DBG_INF,"sbpcd_drive_status: timeout.\n");
- return (0);
- }
- msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
- msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
- msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
- msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
- msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
- msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
-
-#if 0
- if (!(p->status_bits & p_door_closed)) return CDS_TRAY_OPEN;
- if (p->status_bits & p_disk_ok) return CDS_DISC_OK;
- if (p->status_bits & p_disk_in) return CDS_DRIVE_NOT_READY;
-
- return CDS_NO_DISC;
-#else
- if (p->status_bits & p_spinning) return CDS_DISC_OK;
-/* return CDS_TRAY_OPEN; */
- return CDS_NO_DISC;
-
-#endif
-
-}
-
-
-/*==========================================================================*/
-#ifdef FUTURE
-/*
- * called always if driver gets entered
- * returns 0 or ERROR2 or ERROR15
- */
-static int prepare(u_char func, u_char subfunc)
-{
- int i;
-
- if (fam0L_drive)
- {
- i=inb(CDi_status);
- if (i&s_attention) GetStatus();
- }
- else if (fam1_drive) GetStatus();
- else if (fam2_drive) GetStatus();
- else if (famT_drive) GetStatus();
- if (current_drive->CD_changed==0xFF)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- if (!st_diskok)
- {
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- else
- {
- i=check_allowed3(func,subfunc);
- if (i<0)
- {
- current_drive->CD_changed=1;
- return (-15);
- }
- }
- }
- else
- {
- if (!st_diskok)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- else
- {
- if (st_busy)
- {
- if (current_drive->audio_state!=audio_pausing)
- {
- i=check_allowed2(func,subfunc);
- if (i<0) return (-2);
- }
- }
- else
- {
- if (current_drive->audio_state==audio_playing) seek_pos_audio_end();
- current_drive->audio_state=0;
- }
- if (!frame_size_valid)
- {
- i=DiskInfo();
- if (i<0)
- {
- current_drive->diskstate_flags=0;
- current_drive->audio_state=0;
- i=check_allowed1(func,subfunc);
- if (i<0) return (-2);
- }
- }
- }
- }
- return (0);
-}
-#endif /* FUTURE */
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * Check the results of the "get status" command.
- */
-static int sbp_status(void)
-{
- int st;
-
- st=ResponseStatus();
- if (st<0)
- {
- msg(DBG_INF,"sbp_status: timeout.\n");
- return (0);
- }
-
- if (!st_spinning) msg(DBG_SPI,"motor got off - ignoring.\n");
-
- if (st_check)
- {
- msg(DBG_INF,"st_check detected - retrying.\n");
- return (0);
- }
- if (!st_door_closed)
- {
- msg(DBG_INF,"door is open - retrying.\n");
- return (0);
- }
- if (!st_caddy_in)
- {
- msg(DBG_INF,"disk removed - retrying.\n");
- return (0);
- }
- if (!st_diskok)
- {
- msg(DBG_INF,"!st_diskok detected - retrying.\n");
- return (0);
- }
- if (st_busy)
- {
- msg(DBG_INF,"st_busy detected - retrying.\n");
- return (0);
- }
- return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_multisession *ms_infp)
-{
- struct sbpcd_drive *p = cdi->handle;
- ms_infp->addr_format = CDROM_LBA;
- ms_infp->addr.lba = p->lba_multi;
- if (p->f_multisession)
- ms_infp->xa_flag=1; /* valid redirection address */
- else
- ms_infp->xa_flag=0; /* invalid redirection address */
-
- return 0;
-}
-
-static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
- void * arg)
-{
- struct sbpcd_drive *p = cdi->handle;
- int i, st, j;
-
- msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
- if (p->drv_id==-1) {
- msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
- return (-ENXIO); /* no such drive */
- }
- down(&ioctl_read_sem);
- if (p != current_drive)
- switch_drive(p);
-
- msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
- switch (cmd) /* Sun-compatible */
- {
-
- case CDROMPAUSE: /* Pause the drive */
- msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
- /* pause the drive unit when it is currently in PLAY mode, */
- /* or reset the starting and ending locations when in PAUSED mode. */
- /* If applicable, at the next stopping point it reaches */
- /* the drive will discontinue playing. */
- switch (current_drive->audio_state)
- {
- case audio_playing:
- if (famL_drive) i=cc_ReadSubQ();
- else i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- if (famL_drive) i=cc_Pause_Resume(1);
- else i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- current_drive->pos_audio_start=current_drive->SubQ_run_tot;
- current_drive->audio_state=audio_pausing;
- RETURN_UP(0);
- case audio_pausing:
- i=cc_Seek(current_drive->pos_audio_start,1);
- if (i<0) RETURN_UP(-EIO);
- RETURN_UP(0);
- default:
- RETURN_UP(-EINVAL);
- }
-
- case CDROMRESUME: /* resume paused audio play */
- msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n");
- /* resume playing audio tracks when a previous PLAY AUDIO call has */
- /* been paused with a PAUSE command. */
- /* It will resume playing from the location saved in SubQ_run_tot. */
- if (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
- if (famL_drive)
- i=cc_PlayAudio(current_drive->pos_audio_start,
- current_drive->pos_audio_end);
- else i=cc_Pause_Resume(3);
- if (i<0) RETURN_UP(-EIO);
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYMSF:
- msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->audio_state==audio_playing)
- {
- i=cc_Pause_Resume(1);
- if (i<0) RETURN_UP(-EIO);
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- current_drive->pos_audio_start=current_drive->SubQ_run_tot;
- i=cc_Seek(current_drive->pos_audio_start,1);
- }
- memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
- /* values come as msf-bin */
- current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
- (msf.cdmsf_sec0<<8) |
- msf.cdmsf_frame0;
- current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
- (msf.cdmsf_sec1<<8) |
- msf.cdmsf_frame1;
- msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
- current_drive->pos_audio_start,current_drive->pos_audio_end);
- i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
- DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(-EIO);
- }
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->audio_state==audio_playing)
- {
- msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
-#if 1
- RETURN_UP(0); /* just let us play on */
-#else
- RETURN_UP(-EINVAL); /* play on, but say "error" */
-#endif
- }
- memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
- msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
- ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
- if (ti.cdti_trk0<current_drive->n_first_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
- if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
- if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
- current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
- current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
- i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
- if (i<0)
- {
- msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
- DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(-EIO);
- }
- current_drive->audio_state=audio_playing;
- RETURN_UP(0);
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
- tochdr.cdth_trk0=current_drive->n_first_track;
- tochdr.cdth_trk1=current_drive->n_last_track;
- memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
- RETURN_UP(0);
-
- case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
- msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
- memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
- i=tocentry.cdte_track;
- if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
- else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
- RETURN_UP(-EINVAL);
- tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
- tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
- tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
- if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
- {
- tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
- tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
- tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
- }
- else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
- tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
- else RETURN_UP(-EINVAL);
- memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
- RETURN_UP(0);
-
- case CDROMSTOP: /* Spin down the drive */
- msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- i=cc_Pause_Resume(1);
- current_drive->audio_state=0;
-#if 0
- cc_DriveReset();
-#endif
- RETURN_UP(i);
-
- case CDROMSTART: /* Spin up the drive */
- msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
- cc_SpinUp();
- current_drive->audio_state=0;
- RETURN_UP(0);
-
- case CDROMVOLCTRL: /* Volume control */
- msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
- memcpy(&volctrl,(char *) arg,sizeof(volctrl));
- current_drive->vol_chan0=0;
- current_drive->vol_ctrl0=volctrl.channel0;
- current_drive->vol_chan1=1;
- current_drive->vol_ctrl1=volctrl.channel1;
- i=cc_SetVolume();
- RETURN_UP(0);
-
- case CDROMVOLREAD: /* read Volume settings from drive */
- msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
- st=cc_GetVolume();
- if (st<0) RETURN_UP(st);
- volctrl.channel0=current_drive->vol_ctrl0;
- volctrl.channel1=current_drive->vol_ctrl1;
- volctrl.channel2=0;
- volctrl.channel2=0;
- memcpy((void *)arg,&volctrl,sizeof(volctrl));
- RETURN_UP(0);
-
- case CDROMSUBCHNL: /* Get subchannel info */
- msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
- /* Bogus, I can do better than this! --AJK
- if ((st_spinning)||(!subq_valid)) {
- i=cc_ReadSubQ();
- if (i<0) RETURN_UP(-EIO);
- }
- */
- i=cc_ReadSubQ();
- if (i<0) {
- j=cc_ReadError(); /* clear out error status from drive */
- current_drive->audio_state=CDROM_AUDIO_NO_STATUS;
- /* get and set the disk state here,
- probably not the right place, but who cares!
- It makes it work properly! --AJK */
- if (current_drive->CD_changed==0xFF) {
- msg(DBG_000,"Disk changed detect\n");
- current_drive->diskstate_flags &= ~cd_size_bit;
- }
- RETURN_UP(-EIO);
- }
- if (current_drive->CD_changed==0xFF) {
- /* reread the TOC because the disk has changed! --AJK */
- msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
- i=DiskInfo();
- if(i==0) {
- current_drive->CD_changed=0x00; /* cd has changed, procede, */
- RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
- } else {
- RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
- }
- }
- memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
- /*
- This virtual crap is very bogus!
- It doesn't detect when the cd is done playing audio!
- Lets do this right with proper hardware register reading!
- */
- cc_ReadStatus();
- i=ResponseStatus();
- msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
- msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
- msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
- msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
- msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
- msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
- /* st_busy indicates if it's _ACTUALLY_ playing audio */
- switch (current_drive->audio_state)
- {
- case audio_playing:
- if(st_busy==0) {
- /* CD has stopped playing audio --AJK */
- current_drive->audio_state=audio_completed;
- SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
- } else {
- SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
- }
- break;
- case audio_pausing:
- SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
- break;
- case audio_completed:
- SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
- break;
- default:
- SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
- break;
- }
- SC.cdsc_adr=current_drive->SubQ_ctl_adr;
- SC.cdsc_ctrl=current_drive->SubQ_ctl_adr>>4;
- SC.cdsc_trk=bcd2bin(current_drive->SubQ_trk);
- SC.cdsc_ind=bcd2bin(current_drive->SubQ_pnt_idx);
- if (SC.cdsc_format==CDROM_LBA)
- {
- SC.cdsc_absaddr.lba=msf2blk(current_drive->SubQ_run_tot);
- SC.cdsc_reladdr.lba=msf2blk(current_drive->SubQ_run_trk);
- }
- else /* not only if (SC.cdsc_format==CDROM_MSF) */
- {
- SC.cdsc_absaddr.msf.minute=(current_drive->SubQ_run_tot>>16)&0x00FF;
- SC.cdsc_absaddr.msf.second=(current_drive->SubQ_run_tot>>8)&0x00FF;
- SC.cdsc_absaddr.msf.frame=current_drive->SubQ_run_tot&0x00FF;
- SC.cdsc_reladdr.msf.minute=(current_drive->SubQ_run_trk>>16)&0x00FF;
- SC.cdsc_reladdr.msf.second=(current_drive->SubQ_run_trk>>8)&0x00FF;
- SC.cdsc_reladdr.msf.frame=current_drive->SubQ_run_trk&0x00FF;
- }
- memcpy((void *) arg, &SC, sizeof(struct cdrom_subchnl));
- msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
- SC.cdsc_format,SC.cdsc_audiostatus,
- SC.cdsc_adr,SC.cdsc_ctrl,
- SC.cdsc_trk,SC.cdsc_ind,
- SC.cdsc_absaddr,SC.cdsc_reladdr);
- RETURN_UP(0);
-
- default:
- msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
- RETURN_UP(-EINVAL);
- } /* end switch(cmd) */
-}
-/*==========================================================================*/
-/*
- * Take care of the different block sizes between cdrom and Linux.
- */
-static void sbp_transfer(struct request *req)
-{
- long offs;
-
- while ( (req->nr_sectors > 0) &&
- (req->sector/4 >= current_drive->sbp_first_frame) &&
- (req->sector/4 <= current_drive->sbp_last_frame) )
- {
- offs = (req->sector - current_drive->sbp_first_frame * 4) * 512;
- memcpy(req->buffer, current_drive->sbp_buf + offs, 512);
- req->nr_sectors--;
- req->sector++;
- req->buffer += 512;
- }
-}
-/*==========================================================================*/
-/*
- * special end_request for sbpcd to solve CURRENT==NULL bug. (GTL)
- * GTL = Gonzalo Tornaria <tornaria@cmat.edu.uy>
- *
- * This is a kludge so we don't need to modify end_request.
- * We put the req we take out after INIT_REQUEST in the requests list,
- * so that end_request will discard it.
- *
- * The bug could be present in other block devices, perhaps we
- * should modify INIT_REQUEST and end_request instead, and
- * change every block device..
- *
- * Could be a race here?? Could e.g. a timer interrupt schedule() us?
- * If so, we should copy end_request here, and do it right.. (or
- * modify end_request and the block devices).
- *
- * In any case, the race here would be much small than it was, and
- * I couldn't reproduce..
- *
- * The race could be: suppose CURRENT==NULL. We put our req in the list,
- * and we are scheduled. Other process takes over, and gets into
- * do_sbpcd_request. It sees CURRENT!=NULL (it is == to our req), so
- * proceeds. It ends, so CURRENT is now NULL.. Now we awake somewhere in
- * end_request, but now CURRENT==NULL... oops!
- *
- */
-#undef DEBUG_GTL
-
-/*==========================================================================*/
-/*
- * I/O request routine, called from Linux kernel.
- */
-static void do_sbpcd_request(request_queue_t * q)
-{
- u_int block;
- u_int nsect;
- int status_tries, data_tries;
- struct request *req;
- struct sbpcd_drive *p;
-#ifdef DEBUG_GTL
- static int xx_nr=0;
- int xnr;
-#endif
-
- request_loop:
-#ifdef DEBUG_GTL
- xnr=++xx_nr;
-
- req = elv_next_request(q);
-
- if (!req)
- {
- printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
- xnr, current->pid, jiffies);
- printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n",
- xnr, jiffies);
- return;
- }
-
- printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
-#endif
-
- req = elv_next_request(q); /* take out our request so no other */
- if (!req)
- return;
-
- if (req -> sector == -1)
- end_request(req, 0);
- spin_unlock_irq(q->queue_lock);
-
- down(&ioctl_read_sem);
- if (rq_data_dir(elv_next_request(q)) != READ)
- {
- msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
- goto err_done;
- }
- p = req->rq_disk->private_data;
-#if OLD_BUSY
- while (busy_audio) sbp_sleep(HZ); /* wait a bit */
- busy_data=1;
-#endif /* OLD_BUSY */
-
- if (p->audio_state==audio_playing) goto err_done;
- if (p != current_drive)
- switch_drive(p);
-
- block = req->sector; /* always numbered as 512-byte-pieces */
- nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
-
- msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect);
-#if 0
- msg(DBG_MUL,"read LBA %d\n", block/4);
-#endif
-
- sbp_transfer(req);
- /* if we satisfied the request from the buffer, we're done. */
- if (req->nr_sectors == 0)
- {
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- spin_lock_irq(q->queue_lock);
- end_request(req, 1);
- goto request_loop;
- }
-
-#ifdef FUTURE
- i=prepare(0,0); /* at moment not really a hassle check, but ... */
- if (i!=0)
- msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
-#endif /* FUTURE */
-
- if (!st_spinning) cc_SpinUp();
-
- for (data_tries=n_retries; data_tries > 0; data_tries--)
- {
- for (status_tries=3; status_tries > 0; status_tries--)
- {
- flags_cmd_out |= f_respo3;
- cc_ReadStatus();
- if (sbp_status() != 0) break;
- if (st_check) cc_ReadError();
- sbp_sleep(1); /* wait a bit, try again */
- }
- if (status_tries == 0)
- {
- msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
- break;
- }
-
- sbp_read_cmd(req);
- sbp_sleep(0);
- if (sbp_data(req) != 0)
- {
-#ifdef SAFE_MIXED
- current_drive->has_data=2; /* is really a data disk */
-#endif /* SAFE_MIXED */
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- spin_lock_irq(q->queue_lock);
- end_request(req, 1);
- goto request_loop;
- }
- }
-
- err_done:
-#if OLD_BUSY
- busy_data=0;
-#endif /* OLD_BUSY */
-#ifdef DEBUG_GTL
- printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
- xnr, req, req->sector, req->nr_sectors, jiffies);
-#endif
- up(&ioctl_read_sem);
- sbp_sleep(0); /* wait a bit, try again */
- spin_lock_irq(q->queue_lock);
- end_request(req, 0);
- goto request_loop;
-}
-/*==========================================================================*/
-/*
- * build and send the READ command.
- */
-static void sbp_read_cmd(struct request *req)
-{
-#undef OLD
-
- int i;
- int block;
-
- current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
- current_drive->sbp_current = 0;
- block=req->sector/4;
- if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
- current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
- else
- {
- current_drive->sbp_read_frames=current_drive->CDsize_frm-block;
- /* avoid reading past end of data */
- if (current_drive->sbp_read_frames < 1)
- {
- msg(DBG_INF,"requested frame %d, CD size %d ???\n",
- block, current_drive->CDsize_frm);
- current_drive->sbp_read_frames=1;
- }
- }
-
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
- clr_cmdbuf();
- if (famV_drive)
- {
- drvcmd[0]=CMDV_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
- bin2bcdx(&drvcmd[1]);
- bin2bcdx(&drvcmd[2]);
- bin2bcdx(&drvcmd[3]);
- drvcmd[4]=current_drive->sbp_read_frames>>8;
- drvcmd[5]=current_drive->sbp_read_frames&0xff;
- drvcmd[6]=0x02; /* flag "msf-bcd" */
- }
- else if (fam0L_drive)
- {
- flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
- if (current_drive->xa_byte==0x20)
- {
- cmd_type=READ_M2;
- drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
- drvcmd[1]=(block>>16)&0x0ff;
- drvcmd[2]=(block>>8)&0x0ff;
- drvcmd[3]=block&0x0ff;
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- }
- else
- {
- drvcmd[0]=CMD0_READ; /* "read frames", old drives */
- if (current_drive->drv_type>=drv_201)
- {
- lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
- bin2bcdx(&drvcmd[1]);
- bin2bcdx(&drvcmd[2]);
- bin2bcdx(&drvcmd[3]);
- }
- else
- {
- drvcmd[1]=(block>>16)&0x0ff;
- drvcmd[2]=(block>>8)&0x0ff;
- drvcmd[3]=block&0x0ff;
- }
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
- }
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
- drvcmd[6]=0x02;
- }
- else if (famT_drive)
- {
- drvcmd[0]=CMDT_READ;
- drvcmd[2]=(block>>24)&0x0ff;
- drvcmd[3]=(block>>16)&0x0ff;
- drvcmd[4]=(block>>8)&0x0ff;
- drvcmd[5]=block&0x0ff;
- drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
- drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
- }
- flags_cmd_out=f_putcmd;
- response_count=0;
- i=cmd_out();
- if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i);
- return;
-}
-/*==========================================================================*/
-/*
- * Check the completion of the read-data command. On success, read
- * the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
- */
-static int sbp_data(struct request *req)
-{
- int i=0, j=0, l, frame;
- u_int try=0;
- u_long timeout;
- u_char *p;
- u_int data_tries = 0;
- u_int data_waits = 0;
- u_int data_retrying = 0;
- int error_flag;
- int xa_count;
- int max_latency;
- int success;
- int wait;
- int duration;
-
- error_flag=0;
- success=0;
-#if LONG_TIMING
- max_latency=9*HZ;
-#else
- if (current_drive->f_multisession) max_latency=15*HZ;
- else max_latency=5*HZ;
-#endif
- duration=jiffies;
- for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
- {
- SBPCD_CLI;
-
- del_timer(&data_timer);
- data_timer.expires=jiffies+max_latency;
- timed_out_data=0;
- add_timer(&data_timer);
- while (!timed_out_data)
- {
- if (current_drive->f_multisession) try=maxtim_data*4;
- else try=maxtim_data;
- msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
- for ( ; try!=0;try--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (fam0LV_drive) if (j&s_attention) break;
- }
- if (!(j&s_not_data_ready)) goto data_ready;
- if (try==0)
- {
- if (data_retrying == 0) data_waits++;
- data_retrying = 1;
- msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n");
- sbp_sleep(1);
- try = 1;
- }
- }
- msg(DBG_INF,"sbp_data: CDi_status loop expired.\n");
- data_ready:
- del_timer(&data_timer);
-
- if (timed_out_data)
- {
- msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j);
- error_flag++;
- }
- if (try==0)
- {
- msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j);
- error_flag++;
- }
- if (!(j&s_not_result_ready))
- {
- msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j);
- response_count=20;
- j=ResponseInfo();
- j=inb(CDi_status);
- }
- if (j&s_not_data_ready)
- {
- if ((current_drive->ored_ctl_adr&0x40)==0)
- msg(DBG_INF, "CD contains no data tracks.\n");
- else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j);
- error_flag++;
- }
- SBPCD_STI;
- if (error_flag) break;
-
- msg(DBG_000, "sbp_data: beginning to read.\n");
- p = current_drive->sbp_buf + frame * CD_FRAMESIZE;
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (cmd_type==READ_M2) {
- if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
- else insb(CDi_data, xa_head_buf, CD_XA_HEAD);
- }
- if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1);
- else insb(CDi_data, p, CD_FRAMESIZE);
- if (cmd_type==READ_M2) {
- if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
- else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
- }
- current_drive->sbp_current++;
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- if (cmd_type==READ_M2)
- {
- for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++)
- sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]);
- msgbuf[xa_count*3]=0;
- msg(DBG_XA1,"xa head:%s\n", msgbuf);
- }
- data_retrying = 0;
- data_tries++;
- if (data_tries >= 1000)
- {
- msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries);
- data_waits = data_tries = 0;
- }
- }
- duration=jiffies-duration;
- msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
- if (famT_drive)
- {
- wait=8;
- do
- {
- if (teac==2)
- {
- if ((i=CDi_stat_loop_T()) == -1) break;
- }
- else
- {
- sbp_sleep(1);
- OUT(CDo_sel_i_d,0);
- i=inb(CDi_status);
- }
- if (!(i&s_not_data_ready))
- {
- OUT(CDo_sel_i_d,1);
- j=0;
- do
- {
- if (do_16bit) i=inw(CDi_data);
- else i=inb(CDi_data);
- j++;
- i=inb(CDi_status);
- }
- while (!(i&s_not_data_ready));
- msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j);
- }
- if (!(i&s_not_result_ready))
- {
- OUT(CDo_sel_i_d,0);
- l=0;
- do
- {
- infobuf[l++]=inb(CDi_info);
- i=inb(CDi_status);
- }
- while (!(i&s_not_result_ready));
- if (infobuf[0]==0x00) success=1;
-#if 1
- for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
- msgbuf[j*3]=0;
- msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf);
-#endif
- if (infobuf[0]==0x02)
- {
- error_flag++;
- do
- {
- ++recursion;
- if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion);
- else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n");
- clr_cmdbuf();
- drvcmd[0]=CMDT_READ_ERR;
- j=cmd_out_T(); /* !!! recursive here !!! */
- --recursion;
- sbp_sleep(1);
- }
- while (j<0);
- current_drive->error_state=infobuf[2];
- current_drive->b3=infobuf[3];
- current_drive->b4=infobuf[4];
- }
- break;
- }
- else
- {
-#if 0
- msg(DBG_TEA, "============= waiting for result=================.\n");
- sbp_sleep(1);
-#endif
- }
- }
- while (wait--);
- }
-
- if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
- {
- msg(DBG_TEA, "================error flag: %d=================.\n", error_flag);
- msg(DBG_INF,"sbp_data: read aborted by drive.\n");
-#if 1
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
- i=cc_ReadError();
-#endif
- return (0);
- }
-
- if (fam0LV_drive)
- {
- SBPCD_CLI;
- i=maxtim_data;
- for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (j&s_attention) break;
- }
- if (i != 0 || time_after_eq(jiffies, timeout)) break;
- sbp_sleep(0);
- i = 1;
- }
- if (i==0) msg(DBG_INF,"status timeout after READ.\n");
- if (!(j&s_attention))
- {
- msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- SBPCD_STI;
- return (0);
- }
- SBPCD_STI;
- }
-
-#if 0
- if (!success)
-#endif
- do
- {
- if (fam0LV_drive) cc_ReadStatus();
-#if 1
- if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
-#endif
- i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
-#if 1
- if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
-#endif
- if (i<0)
- {
- msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
- return (0);
- }
- }
- while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i);
- return (0);
- }
- if (fatal_err)
- {
- fatal_err=0;
- current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
- current_drive->sbp_current = 0;
- msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
- return (0);
- }
-
- current_drive->sbp_first_frame = req -> sector / 4;
- current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
- sbp_transfer(req);
- return (1);
-}
-/*==========================================================================*/
-
-static int sbpcd_block_open(struct inode *inode, struct file *file)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_open(p->sbpcd_infop, inode, file);
-}
-
-static int sbpcd_block_release(struct inode *inode, struct file *file)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- return cdrom_release(p->sbpcd_infop, file);
-}
-
-static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
- unsigned cmd, unsigned long arg)
-{
- struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
- struct cdrom_device_info *cdi = p->sbpcd_infop;
- int ret, i;
-
- ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg);
- if (ret != -ENOSYS)
- return ret;
-
- msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg);
- if (p->drv_id==-1) {
- msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
- return (-ENXIO); /* no such drive */
- }
- down(&ioctl_read_sem);
- if (p != current_drive)
- switch_drive(p);
-
- msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
- switch (cmd) /* Sun-compatible */
- {
- case DDIOCSDBG: /* DDI Debug */
- if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
- i=sbpcd_dbg_ioctl(arg,1);
- RETURN_UP(i);
- case CDROMRESET: /* hard reset the drive */
- msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
- i=DriveReset();
- current_drive->audio_state=0;
- RETURN_UP(i);
-
- case CDROMREADMODE1:
- msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- cc_ModeSelect(CD_FRAMESIZE);
- cc_ModeSense();
- current_drive->mode=READ_M1;
- RETURN_UP(0);
-
- case CDROMREADMODE2: /* not usable at the moment */
- msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- cc_ModeSelect(CD_FRAMESIZE_RAW1);
- cc_ModeSense();
- current_drive->mode=READ_M2;
- RETURN_UP(0);
-
- case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
- msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
- if (current_drive->sbp_audsiz>0)
- vfree(current_drive->aud_buf);
- current_drive->aud_buf=NULL;
- current_drive->sbp_audsiz=arg;
-
- if (current_drive->sbp_audsiz>16)
- {
- current_drive->sbp_audsiz = 0;
- RETURN_UP(current_drive->sbp_audsiz);
- }
-
- if (current_drive->sbp_audsiz>0)
- {
- current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
- if (current_drive->aud_buf==NULL)
- {
- msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
- current_drive->sbp_audsiz=0;
- }
- else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
- }
- RETURN_UP(current_drive->sbp_audsiz);
-
- case CDROMREADAUDIO:
- { /* start of CDROMREADAUDIO */
- int i=0, j=0, frame, block=0;
- u_int try=0;
- u_long timeout;
- u_char *p;
- u_int data_tries = 0;
- u_int data_waits = 0;
- u_int data_retrying = 0;
- int status_tries;
- int error_flag;
-
- msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
- if (fam0_drive) RETURN_UP(-EINVAL);
- if (famL_drive) RETURN_UP(-EINVAL);
- if (famV_drive) RETURN_UP(-EINVAL);
- if (famT_drive) RETURN_UP(-EINVAL);
-#ifdef SAFE_MIXED
- if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
- if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL);
- if (copy_from_user(&read_audio, (void __user *)arg,
- sizeof(struct cdrom_read_audio)))
- RETURN_UP(-EFAULT);
- if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
- if (!access_ok(VERIFY_WRITE, read_audio.buf,
- read_audio.nframes*CD_FRAMESIZE_RAW))
- RETURN_UP(-EFAULT);
-
- if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
- block=msf2lba(&read_audio.addr.msf.minute);
- else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
- block=read_audio.addr.lba;
- else RETURN_UP(-EINVAL);
-#if 000
- i=cc_SetSpeed(speed_150,0,0);
- if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
-#endif
- msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
- block, blk2msf(block));
- msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
-#if OLD_BUSY
- while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
- busy_audio=1;
-#endif /* OLD_BUSY */
- error_flag=0;
- for (data_tries=5; data_tries>0; data_tries--)
- {
- msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
- current_drive->mode=READ_AU;
- cc_ModeSelect(CD_FRAMESIZE_RAW);
- cc_ModeSense();
- for (status_tries=3; status_tries > 0; status_tries--)
- {
- flags_cmd_out |= f_respo3;
- cc_ReadStatus();
- if (sbp_status() != 0) break;
- if (st_check) cc_ReadError();
- sbp_sleep(1); /* wait a bit, try again */
- }
- if (status_tries == 0)
- {
- msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
- continue;
- }
- msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
-
- flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
- if (fam0L_drive)
- {
- flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
- cmd_type=READ_M2;
- drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
- drvcmd[1]=(block>>16)&0x000000ff;
- drvcmd[2]=(block>>8)&0x000000ff;
- drvcmd[3]=block&0x000000ff;
- drvcmd[4]=0;
- drvcmd[5]=read_audio.nframes; /* # of frames */
- drvcmd[6]=0;
- }
- else if (fam1_drive)
- {
- drvcmd[0]=CMD1_READ; /* "read frames", new drives */
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=0;
- drvcmd[5]=0;
- drvcmd[6]=read_audio.nframes; /* # of frames */
- }
- else if (fam2_drive)
- {
- drvcmd[0]=CMD2_READ_XA2;
- lba2msf(block,&drvcmd[1]); /* msf-bin format required */
- drvcmd[4]=0;
- drvcmd[5]=read_audio.nframes; /* # of frames */
- drvcmd[6]=0x11; /* raw mode */
- }
- else if (famT_drive) /* CD-55A: not tested yet */
- {
- }
- msg(DBG_AUD,"read_audio: before giving \"read\" command.\n");
- flags_cmd_out=f_putcmd;
- response_count=0;
- i=cmd_out();
- if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i);
- sbp_sleep(0);
- msg(DBG_AUD,"read_audio: after giving \"read\" command.\n");
- for (frame=1;frame<2 && !error_flag; frame++)
- {
- try=maxtim_data;
- for (timeout=jiffies+9*HZ; ; )
- {
- for ( ; try!=0;try--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (fam0L_drive) if (j&s_attention) break;
- }
- if (try != 0 || time_after_eq(jiffies, timeout)) break;
- if (data_retrying == 0) data_waits++;
- data_retrying = 1;
- sbp_sleep(1);
- try = 1;
- }
- if (try==0)
- {
- msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n");
- error_flag++;
- break;
- }
- msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n");
- if (j&s_not_data_ready)
- {
- msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n");
- error_flag++;
- break;
- }
- msg(DBG_AUD,"read_audio: before reading data.\n");
- error_flag=0;
- p = current_drive->aud_buf;
- if (sbpro_type==1) OUT(CDo_sel_i_d,1);
- if (do_16bit)
- {
- u_short *p2 = (u_short *) p;
-
- for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
- {
- if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
- /* get one sample */
- *p2++ = inw_p(CDi_data);
- *p2++ = inw_p(CDi_data);
- }
- } else {
- for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
- {
- if ((inb_p(CDi_status)&s_not_data_ready)) continue;
-
- /* get one sample */
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- *p++ = inb_p(CDi_data);
- }
- }
- if (sbpro_type==1) OUT(CDo_sel_i_d,0);
- data_retrying = 0;
- }
- msg(DBG_AUD,"read_audio: after reading data.\n");
- if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
- {
- msg(DBG_AUD,"read_audio: read aborted by drive\n");
-#if 0000
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
-#else
- i=cc_ReadError();
-#endif
- continue;
- }
- if (fam0L_drive)
- {
- i=maxtim_data;
- for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
- {
- for ( ;i!=0;i--)
- {
- j=inb(CDi_status);
- if (!(j&s_not_data_ready)) break;
- if (!(j&s_not_result_ready)) break;
- if (j&s_attention) break;
- }
- if (i != 0 || time_after_eq(jiffies, timeout)) break;
- sbp_sleep(0);
- i = 1;
- }
- if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
- if (!(j&s_attention))
- {
- msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n");
- i=cc_DriveReset(); /* ugly fix to prevent a hang */
- continue;
- }
- }
- do
- {
- if (fam0L_drive) cc_ReadStatus();
- i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
- if (i<0) { msg(DBG_AUD,
- "read_audio: cc_ReadStatus error after read: %02X\n",
- current_drive->status_bits);
- continue; /* FIXME */
- }
- }
- while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
- continue;
- }
- if (copy_to_user(read_audio.buf,
- current_drive->aud_buf,
- read_audio.nframes * CD_FRAMESIZE_RAW))
- RETURN_UP(-EFAULT);
- msg(DBG_AUD,"read_audio: copy_to_user done.\n");
- break;
- }
- cc_ModeSelect(CD_FRAMESIZE);
- cc_ModeSense();
- current_drive->mode=READ_M1;
-#if OLD_BUSY
- busy_audio=0;
-#endif /* OLD_BUSY */
- if (data_tries == 0)
- {
- msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
- RETURN_UP(-EIO);
- }
- msg(DBG_AUD,"read_audio: successful return.\n");
- RETURN_UP(0);
- } /* end of CDROMREADAUDIO */
-
- default:
- msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
- RETURN_UP(-EINVAL);
- } /* end switch(cmd) */
-}
-
-static int sbpcd_block_media_changed(struct gendisk *disk)
-{
- struct sbpcd_drive *p = disk->private_data;
- return cdrom_media_changed(p->sbpcd_infop);
-}
-
-static struct block_device_operations sbpcd_bdops =
-{
- .owner = THIS_MODULE,
- .open = sbpcd_block_open,
- .release = sbpcd_block_release,
- .ioctl = sbpcd_block_ioctl,
- .media_changed = sbpcd_block_media_changed,
-};
-/*==========================================================================*/
-/*
- * Open the device special file. Check that a disk is in. Read TOC.
- */
-static int sbpcd_open(struct cdrom_device_info *cdi, int purpose)
-{
- struct sbpcd_drive *p = cdi->handle;
-
- down(&ioctl_read_sem);
- switch_drive(p);
-
- /*
- * try to keep an "open" counter here and lock the door if 0->1.
- */
- msg(DBG_LCK,"open_count: %d -> %d\n",
- current_drive->open_count,current_drive->open_count+1);
- if (++current_drive->open_count<=1)
- {
- int i;
- i=LockDoor();
- current_drive->open_count=1;
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: before i=DiskInfo();.\n");
- i=DiskInfo();
- if (famT_drive) msg(DBG_TEA,"sbpcd_open: after i=DiskInfo();.\n");
- if ((current_drive->ored_ctl_adr&0x40)==0)
- {
- msg(DBG_INF,"CD contains no data tracks.\n");
-#ifdef SAFE_MIXED
- current_drive->has_data=0;
-#endif /* SAFE_MIXED */
- }
-#ifdef SAFE_MIXED
- else if (current_drive->has_data<1) current_drive->has_data=1;
-#endif /* SAFE_MIXED */
- }
- if (!st_spinning) cc_SpinUp();
- RETURN_UP(0);
-}
-/*==========================================================================*/
-/*
- * On close, we flush all sbp blocks from the buffer cache.
- */
-static void sbpcd_release(struct cdrom_device_info * cdi)
-{
- struct sbpcd_drive *p = cdi->handle;
-
- if (p->drv_id==-1) {
- msg(DBG_INF, "release: bad device: %s\n", cdi->name);
- return;
- }
- down(&ioctl_read_sem);
- switch_drive(p);
- /*
- * try to keep an "open" counter here and unlock the door if 1->0.
- */
- msg(DBG_LCK,"open_count: %d -> %d\n",
- p->open_count,p->open_count-1);
- if (p->open_count>-2) /* CDROMEJECT may have been done */
- {
- if (--p->open_count<=0)
- {
- p->sbp_first_frame=p->sbp_last_frame=-1;
- if (p->audio_state!=audio_playing)
- if (p->f_eject) cc_SpinDown();
- p->diskstate_flags &= ~cd_size_bit;
- p->open_count=0;
-#ifdef SAFE_MIXED
- p->has_data=0;
-#endif /* SAFE_MIXED */
- }
- }
- up(&ioctl_read_sem);
- return ;
-}
-/*==========================================================================*/
-/*
- *
- */
-static int sbpcd_media_changed( struct cdrom_device_info *cdi, int disc_nr);
-static struct cdrom_device_ops sbpcd_dops = {
- .open = sbpcd_open,
- .release = sbpcd_release,
- .drive_status = sbpcd_drive_status,
- .media_changed = sbpcd_media_changed,
- .tray_move = sbpcd_tray_move,
- .lock_door = sbpcd_lock_door,
- .select_speed = sbpcd_select_speed,
- .get_last_session = sbpcd_get_last_session,
- .get_mcn = sbpcd_get_mcn,
- .reset = sbpcd_reset,
- .audio_ioctl = sbpcd_audio_ioctl,
- .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
- CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
- CDC_MCN | CDC_PLAY_AUDIO,
- .n_minors = 1,
-};
-
-/*==========================================================================*/
-/*
- * accept "kernel command line" parameters
- * (suggested by Peter MacDonald with SLS 1.03)
- *
- * This is only implemented for the first controller. Should be enough to
- * allow installing with a "strange" distribution kernel.
- *
- * use: tell LILO:
- * sbpcd=0x230,SoundBlaster
- * or
- * sbpcd=0x300,LaserMate
- * or
- * sbpcd=0x338,SoundScape
- * or
- * sbpcd=0x2C0,Teac16bit
- *
- * (upper/lower case sensitive here - but all-lowercase is ok!!!).
- *
- * the address value has to be the CDROM PORT ADDRESS -
- * not the soundcard base address.
- * For the SPEA/SoundScape setup, DO NOT specify the "configuration port"
- * address, but the address which is really used for the CDROM (usually 8
- * bytes above).
- *
- */
-
-int sbpcd_setup(char *s)
-{
-#ifndef MODULE
- int p[4];
- (void)get_options(s, ARRAY_SIZE(p), p);
- setup_done++;
- msg(DBG_INI,"sbpcd_setup called with %04X,%s\n",p[1], s);
- sbpro_type=0; /* default: "LaserMate" */
- if (p[0]>1) sbpro_type=p[2];
- else if (!strcmp(s,str_sb)) sbpro_type=1;
- else if (!strcmp(s,str_sb_l)) sbpro_type=1;
- else if (!strcmp(s,str_sp)) sbpro_type=2;
- else if (!strcmp(s,str_sp_l)) sbpro_type=2;
- else if (!strcmp(s,str_ss)) sbpro_type=2;
- else if (!strcmp(s,str_ss_l)) sbpro_type=2;
- else if (!strcmp(s,str_t16)) sbpro_type=3;
- else if (!strcmp(s,str_t16_l)) sbpro_type=3;
- if (p[0]>0) sbpcd_ioaddr=p[1];
- if (p[0]>2) max_drives=p[3];
-#else
- sbpcd_ioaddr = sbpcd[0];
- sbpro_type = sbpcd[1];
-#endif
-
- CDo_command=sbpcd_ioaddr;
- CDi_info=sbpcd_ioaddr;
- CDi_status=sbpcd_ioaddr+1;
- CDo_sel_i_d=sbpcd_ioaddr+1;
- CDo_reset=sbpcd_ioaddr+2;
- CDo_enable=sbpcd_ioaddr+3;
- f_16bit=0;
- if ((sbpro_type==1)||(sbpro_type==3))
- {
- CDi_data=sbpcd_ioaddr;
- if (sbpro_type==3)
- {
- f_16bit=1;
- sbpro_type=1;
- }
- }
- else CDi_data=sbpcd_ioaddr+2;
-
- return 1;
-}
-
-__setup("sbpcd=", sbpcd_setup);
-
-
-/*==========================================================================*/
-/*
- * Sequoia S-1000 CD-ROM Interface Configuration
- * as used within SPEA Media FX, Ensonic SoundScape and some Reveal cards
- * The soundcard has to get jumpered for the interface type "Panasonic"
- * (not Sony or Mitsumi) and to get soft-configured for
- * -> configuration port address
- * -> CDROM port offset (num_ports): has to be 8 here. Possibly this
- * offset value determines the interface type (none, Panasonic,
- * Mitsumi, Sony).
- * The interface uses a configuration port (0x320, 0x330, 0x340, 0x350)
- * some bytes below the real CDROM address.
- *
- * For the Panasonic style (LaserMate) interface and the configuration
- * port 0x330, we have to use an offset of 8; so, the real CDROM port
- * address is 0x338.
- */
-static int __init config_spea(void)
-{
- /*
- * base address offset between configuration port and CDROM port,
- * this probably defines the interface type
- * 2 (type=??): 0x00
- * 8 (type=LaserMate):0x10
- * 16 (type=??):0x20
- * 32 (type=??):0x30
- */
- int n_ports=0x10;
-
- int irq_number=0; /* off:0x00, 2/9:0x01, 7:0x03, 12:0x05, 15:0x07 */
- int dma_channel=0; /* off: 0x00, 0:0x08, 1:0x18, 3:0x38, 5:0x58, 6:0x68 */
- int dack_polarity=0; /* L:0x00, H:0x80 */
- int drq_polarity=0x40; /* L:0x00, H:0x40 */
- int i;
-
-#define SPEA_REG_1 sbpcd_ioaddr-0x08+4
-#define SPEA_REG_2 sbpcd_ioaddr-0x08+5
-
- OUT(SPEA_REG_1,0xFF);
- i=inb(SPEA_REG_1);
- if (i!=0x0F)
- {
- msg(DBG_SEQ,"no SPEA interface at %04X present.\n", sbpcd_ioaddr);
- return (-1); /* no interface found */
- }
- OUT(SPEA_REG_1,0x04);
- OUT(SPEA_REG_2,0xC0);
-
- OUT(SPEA_REG_1,0x05);
- OUT(SPEA_REG_2,0x10|drq_polarity|dack_polarity);
-
-#if 1
-#define SPEA_PATTERN 0x80
-#else
-#define SPEA_PATTERN 0x00
-#endif
- OUT(SPEA_REG_1,0x06);
- OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
- OUT(SPEA_REG_2,dma_channel|irq_number|SPEA_PATTERN);
-
- OUT(SPEA_REG_1,0x09);
- i=(inb(SPEA_REG_2)&0xCF)|n_ports;
- OUT(SPEA_REG_2,i);
-
- sbpro_type = 0; /* acts like a LaserMate interface now */
- msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr);
- return (0);
-}
-
-/*==========================================================================*/
-/*
- * Test for presence of drive and initialize it.
- * Called once at boot or load time.
- */
-
-/* FIXME: cleanups after failed allocations are too ugly for words */
-#ifdef MODULE
-int __init __sbpcd_init(void)
-#else
-int __init sbpcd_init(void)
-#endif
-{
- int i=0, j=0;
- int addr[2]={1, CDROM_PORT};
- int port_index;
-
- sti();
-
- msg(DBG_INF,"sbpcd.c %s\n", VERSION);
-#ifndef MODULE
-#if DISTRIBUTION
- if (!setup_done)
- {
- msg(DBG_INF,"Looking for Matsushita/Panasonic, CreativeLabs, Longshine, TEAC CD-ROM drives\n");
- msg(DBG_INF,"= = = = = = = = = = W A R N I N G = = = = = = = = = =\n");
- msg(DBG_INF,"Auto-Probing can cause a hang (f.e. touching an NE2000 card).\n");
- msg(DBG_INF,"If that happens, you have to reboot and use the\n");
- msg(DBG_INF,"LILO (kernel) command line feature like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x230,SoundBlaster\n");
- msg(DBG_INF,"or like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x300,LaserMate\n");
- msg(DBG_INF,"or like:\n");
- msg(DBG_INF," LILO boot: ... sbpcd=0x338,SoundScape\n");
- msg(DBG_INF,"with your REAL address.\n");
- msg(DBG_INF,"= = = = = = = = = = END of WARNING = = = = = == = = =\n");
- }
-#endif /* DISTRIBUTION */
- sbpcd[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
- sbpcd[1]=sbpro_type; /* possibly changed by kernel command line */
-#endif /* MODULE */
-
- for (port_index=0;port_index<NUM_PROBE;port_index+=2)
- {
- addr[1]=sbpcd[port_index];
- if (addr[1]==0) break;
- if (check_region(addr[1],4))
- {
- msg(DBG_INF,"check_region: %03X is not free.\n",addr[1]);
- continue;
- }
- if (sbpcd[port_index+1]==2) type=str_sp;
- else if (sbpcd[port_index+1]==1) type=str_sb;
- else if (sbpcd[port_index+1]==3) type=str_t16;
- else type=str_lm;
- sbpcd_setup((char *)type);
-#if DISTRIBUTION
- msg(DBG_INF,"Scanning 0x%X (%s)...\n", CDo_command, type);
-#endif /* DISTRIBUTION */
- if (sbpcd[port_index+1]==2)
- {
- i=config_spea();
- if (i<0) continue;
- }
-#ifdef PATH_CHECK
- if (check_card(addr[1])) continue;
-#endif /* PATH_CHECK */
- i=check_drives();
- msg(DBG_INI,"check_drives done.\n");
- if (i>=0) break; /* drive found */
- } /* end of cycling through the set of possible I/O port addresses */
-
- if (ndrives==0)
- {
- msg(DBG_INF, "No drive found.\n");
-#ifdef MODULE
- return -EIO;
-#else
- goto init_done;
-#endif /* MODULE */
- }
-
- if (port_index>0)
- {
- msg(DBG_INF, "You should read Documentation/cdrom/sbpcd\n");
- msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n");
- }
- check_datarate();
- msg(DBG_INI,"check_datarate done.\n");
-
- for (j=0;j<NR_SBPCD;j++)
- {
- struct sbpcd_drive *p = D_S + j;
- if (p->drv_id==-1)
- continue;
- switch_drive(p);
-#if 1
- if (!famL_drive) cc_DriveReset();
-#endif
- if (!st_spinning) cc_SpinUp();
- p->sbp_first_frame = -1; /* First frame in buffer */
- p->sbp_last_frame = -1; /* Last frame in buffer */
- p->sbp_read_frames = 0; /* Number of frames being read to buffer */
- p->sbp_current = 0; /* Frame being currently read */
- p->CD_changed=1;
- p->frame_size=CD_FRAMESIZE;
- p->f_eject=0;
-#if EJECT
- if (!fam0_drive) p->f_eject=1;
-#endif /* EJECT */
- cc_ReadStatus();
- i=ResponseStatus(); /* returns orig. status or p_busy_new */
- if (famT_drive) i=ResponseStatus(); /* returns orig. status or p_busy_new */
- if (i<0)
- {
- if (i!=-402)
- msg(DBG_INF,"init: ResponseStatus returns %d.\n",i);
- }
- else
- {
- if (st_check)
- {
- i=cc_ReadError();
- msg(DBG_INI,"init: cc_ReadError returns %d\n",i);
- }
- }
- msg(DBG_INI,"init: first GetStatus: %d\n",i);
- msg(DBG_LCS,"init: first GetStatus: error_byte=%d\n",
- p->error_byte);
- if (p->error_byte==aud_12)
- {
- timeout=jiffies+2*HZ;
- do
- {
- i=GetStatus();
- msg(DBG_INI,"init: second GetStatus: %02X\n",i);
- msg(DBG_LCS,
- "init: second GetStatus: error_byte=%d\n",
- p->error_byte);
- if (i<0) break;
- if (!st_caddy_in) break;
- }
- while ((!st_diskok)||time_after(jiffies, timeout));
- }
- i=SetSpeed();
- if (i>=0) p->CD_changed=1;
- }
-
- if (!request_region(CDo_command,4,major_name))
- {
- printk(KERN_WARNING "sbpcd: Unable to request region 0x%x\n", CDo_command);
- return -EIO;
- }
-
- /*
- * Turn on the CD audio channels.
- * The addresses are obtained from SOUND_BASE (see sbpcd.h).
- */
-#if SOUND_BASE
- OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */
- OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
-#endif /* SOUND_BASE */
-
- if (register_blkdev(MAJOR_NR, major_name)) {
-#ifdef MODULE
- return -EIO;
-#else
- goto init_done;
-#endif /* MODULE */
- }
-
- /*
- * init error handling is broken beyond belief in this driver...
- */
- sbpcd_queue = blk_init_queue(do_sbpcd_request, &sbpcd_lock);
- if (!sbpcd_queue) {
- release_region(CDo_command,4);
- unregister_blkdev(MAJOR_NR, major_name);
- return -ENOMEM;
- }
-
- for (j=0;j<NR_SBPCD;j++)
- {
- struct cdrom_device_info * sbpcd_infop;
- struct gendisk *disk;
- struct sbpcd_drive *p = D_S + j;
-
- if (p->drv_id==-1) continue;
- switch_drive(p);
-#ifdef SAFE_MIXED
- p->has_data=0;
-#endif /* SAFE_MIXED */
- /*
- * allocate memory for the frame buffers
- */
- p->aud_buf=NULL;
- p->sbp_audsiz=0;
- p->sbp_bufsiz=buffers;
- if (p->drv_type&drv_fam1)
- if (READ_AUDIO>0)
- p->sbp_audsiz = READ_AUDIO;
- p->sbp_buf=(u_char *) vmalloc(buffers*CD_FRAMESIZE);
- if (!p->sbp_buf) {
- msg(DBG_INF,"data buffer (%d frames) not available.\n",
- buffers);
- if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- printk("Can't unregister %s\n", major_name);
- }
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- return -EIO;
- }
-#ifdef MODULE
- msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
-#endif /* MODULE */
- if (p->sbp_audsiz>0)
- {
- p->aud_buf=(u_char *) vmalloc(p->sbp_audsiz*CD_FRAMESIZE_RAW);
- if (p->aud_buf==NULL) msg(DBG_INF,"audio buffer (%d frames) not available.\n",p->sbp_audsiz);
- else msg(DBG_INF,"audio buffer size: %d frames.\n",p->sbp_audsiz);
- }
- sbpcd_infop = vmalloc(sizeof (struct cdrom_device_info));
- if (sbpcd_infop == NULL)
- {
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- return -ENOMEM;
- }
- memset(sbpcd_infop, 0, sizeof(struct cdrom_device_info));
- sbpcd_infop->ops = &sbpcd_dops;
- sbpcd_infop->speed = 2;
- sbpcd_infop->capacity = 1;
- sprintf(sbpcd_infop->name, "sbpcd%d", j);
- sbpcd_infop->handle = p;
- p->sbpcd_infop = sbpcd_infop;
- disk = alloc_disk(1);
- disk->major = MAJOR_NR;
- disk->first_minor = j;
- disk->fops = &sbpcd_bdops;
- strcpy(disk->disk_name, sbpcd_infop->name);
- disk->flags = GENHD_FL_CD;
- p->disk = disk;
- if (register_cdrom(sbpcd_infop))
- {
- printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
- }
- disk->private_data = p;
- disk->queue = sbpcd_queue;
- add_disk(disk);
- }
- blk_queue_hardsect_size(sbpcd_queue, CD_FRAMESIZE);
-
-#ifndef MODULE
- init_done:
-#endif
- return 0;
-}
-/*==========================================================================*/
-#ifdef MODULE
-static void sbpcd_exit(void)
-{
- int j;
-
- if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
- return;
- }
- release_region(CDo_command,4);
- blk_cleanup_queue(sbpcd_queue);
- for (j=0;j<NR_SBPCD;j++)
- {
- if (D_S[j].drv_id==-1) continue;
- del_gendisk(D_S[j].disk);
- put_disk(D_S[j].disk);
- vfree(D_S[j].sbp_buf);
- if (D_S[j].sbp_audsiz>0)
- vfree(D_S[j].aud_buf);
- if ((unregister_cdrom(D_S[j].sbpcd_infop) == -EINVAL))
- {
- msg(DBG_INF, "What's that: can't unregister info %s.\n", major_name);
- return;
- }
- vfree(D_S[j].sbpcd_infop);
- }
- msg(DBG_INF, "%s module released.\n", major_name);
-}
-
-
-module_init(__sbpcd_init) /*HACK!*/;
-module_exit(sbpcd_exit);
-
-
-#endif /* MODULE */
-static int sbpcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
-{
- struct sbpcd_drive *p = cdi->handle;
- msg(DBG_CHK,"media_check (%s) called\n", cdi->name);
-
- if (p->CD_changed==0xFF)
- {
- p->CD_changed=0;
- msg(DBG_CHK,"medium changed (drive %s)\n", cdi->name);
- current_drive->diskstate_flags &= ~toc_bit;
- /* we *don't* need invalidate here, it's done by caller */
- current_drive->diskstate_flags &= ~cd_size_bit;
-#ifdef SAFE_MIXED
- current_drive->has_data=0;
-#endif /* SAFE_MIXED */
-
- return (1);
- }
- else
- return (0);
-}
-
-MODULE_LICENSE("GPL");
-/* FIXME: Old modules.conf claims MATSUSHITA_CDROM2_MAJOR and CDROM3, but
- AFAICT this doesn't support those majors, so why? --RR 30 Jul 2003 */
-MODULE_ALIAS_BLOCKDEV_MAJOR(MATSUSHITA_CDROM_MAJOR);
-
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
-
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
deleted file mode 100644
index 2f2225f13c6..00000000000
--- a/drivers/cdrom/sbpcd.h
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * sbpcd.h Specify interface address and interface type here.
- */
-
-/*
- * Attention! This file contains user-serviceable parts!
- * I recommend to make use of it...
- * If you feel helpless, look into Documentation/cdrom/sbpcd
- * (good idea anyway, at least before mailing me).
- *
- * The definitions for the first controller can get overridden by
- * the kernel command line ("lilo boot option").
- * Examples:
- * sbpcd=0x300,LaserMate
- * or
- * sbpcd=0x230,SoundBlaster
- * or
- * sbpcd=0x338,SoundScape
- * or
- * sbpcd=0x2C0,Teac16bit
- *
- * If sbpcd gets used as a module, you can load it with
- * insmod sbpcd.o sbpcd=0x300,0
- * or
- * insmod sbpcd.o sbpcd=0x230,1
- * or
- * insmod sbpcd.o sbpcd=0x338,2
- * or
- * insmod sbpcd.o sbpcd=0x2C0,3
- * respective to override the configured address and type.
- */
-
-/*
- * define your CDROM port base address as CDROM_PORT
- * and specify the type of your interface card as SBPRO.
- *
- * address:
- * ========
- * SBPRO type addresses typically are 0x0230 (=0x220+0x10), 0x0250, ...
- * LASERMATE type (CI-101P, WDH-7001C) addresses typically are 0x0300, ...
- * SOUNDSCAPE addresses are from the LASERMATE type and range. You have to
- * specify the REAL address here, not the configuration port address. Look
- * at the CDROM driver's invoking line within your DOS CONFIG.SYS, or let
- * sbpcd auto-probe, if you are not firm with the address.
- * There are some soundcards on the market with 0x0630, 0x0650, ...; their
- * type is not obvious (both types are possible).
- *
- * example: if your SBPRO audio address is 0x220, specify 0x230 and SBPRO 1.
- * if your soundcard has its CDROM port above 0x300, specify
- * that address and try SBPRO 0 first.
- * if your SoundScape configuration port is at 0x330, specify
- * 0x338 and SBPRO 2.
- *
- * interface type:
- * ===============
- * set SBPRO to 1 for "true" SoundBlaster card
- * set SBPRO to 0 for "compatible" soundcards and
- * for "poor" (no sound) interface cards.
- * set SBPRO to 2 for Ensonic SoundScape or SPEA Media FX cards
- * set SBPRO to 3 for Teac 16bit interface cards
- *
- * Almost all "compatible" sound boards need to set SBPRO to 0.
- * If SBPRO is set wrong, the drives will get found - but any
- * data access will give errors (audio access will work).
- * The "OmniCD" no-sound interface card from CreativeLabs and most Teac
- * interface cards need SBPRO 1.
- *
- * sound base:
- * ===========
- * The SOUND_BASE definition tells if we should try to turn the CD sound
- * channels on. It will only be of use regarding soundcards with a SbPro
- * compatible mixer.
- *
- * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels
- * #define SOUND_BASE 0 leaves the soundcard untouched
- */
-#define CDROM_PORT 0x340 /* <-----------<< port address */
-#define SBPRO 0 /* <-----------<< interface type */
-#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */
-#define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0 */
-
-/*
- * some more or less user dependent definitions - service them!
- */
-
-/* Set this to 0 once you have configured your interface definitions right. */
-#define DISTRIBUTION 1
-
-/*
- * Time to wait after giving a message.
- * This gets important if you enable non-standard DBG_xxx flags.
- * You will see what happens if you omit the pause or make it
- * too short. Be warned!
- */
-#define KLOGD_PAUSE 1
-
-/* tray control: eject tray if no disk is in */
-#if DISTRIBUTION
-#define JUKEBOX 0
-#else
-#define JUKEBOX 1
-#endif /* DISTRIBUTION */
-
-/* tray control: eject tray after last use */
-#if DISTRIBUTION
-#define EJECT 0
-#else
-#define EJECT 1
-#endif /* DISTRIBUTION */
-
-/* max. number of audio frames to read with one */
-/* request (allocates n* 2352 bytes kernel memory!) */
-/* may be freely adjusted, f.e. 75 (= 1 sec.), at */
-/* runtime by use of the CDROMAUDIOBUFSIZ ioctl. */
-#define READ_AUDIO 0
-
-/* Optimizations for the Teac CD-55A drive read performance.
- * SBP_TEAC_SPEED can be changed here, or one can set the
- * variable "teac" when loading as a module.
- * Valid settings are:
- * 0 - very slow - the recommended "DISTRIBUTION 1" setup.
- * 1 - 2x performance with little overhead. No busy waiting.
- * 2 - 4x performance with 5ms overhead per read. Busy wait.
- *
- * Setting SBP_TEAC_SPEED or the variable 'teac' to anything
- * other than 0 may cause problems. If you run into them, first
- * change SBP_TEAC_SPEED back to 0 and see if your drive responds
- * normally. If yes, you are "allowed" to report your case - to help
- * me with the driver, not to solve your hassle. Don´t mail if you
- * simply are stuck into your own "tuning" experiments, you know?
- */
-#define SBP_TEAC_SPEED 1
-
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * nothing to change below here if you are not fully aware what you're doing
- */
-#ifndef _LINUX_SBPCD_H
-
-#define _LINUX_SBPCD_H
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * driver's own read_ahead, data mode
- */
-#define SBP_BUFFER_FRAMES 8
-
-#define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
-#undef FUTURE
-#undef SAFE_MIXED
-
-#define TEST_UPC 0
-#define SPEA_TEST 0
-#define TEST_STI 0
-#define OLD_BUSY 0
-#undef PATH_CHECK
-#ifndef SOUND_BASE
-#define SOUND_BASE 0
-#endif
-#if DISTRIBUTION
-#undef SBP_TEAC_SPEED
-#define SBP_TEAC_SPEED 0
-#endif
-/*==========================================================================*/
-/*
- * DDI interface definitions
- * "invented" by Fred N. van Kempen..
- */
-#define DDIOCSDBG 0x9000
-
-/*==========================================================================*/
-/*
- * "private" IOCTL functions
- */
-#define CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */
-
-/*==========================================================================*/
-/*
- * Debug output levels
- */
-#define DBG_INF 1 /* necessary information */
-#define DBG_BSZ 2 /* BLOCK_SIZE trace */
-#define DBG_REA 3 /* READ status trace */
-#define DBG_CHK 4 /* MEDIA CHECK trace */
-#define DBG_TIM 5 /* datarate timer test */
-#define DBG_INI 6 /* initialization trace */
-#define DBG_TOC 7 /* tell TocEntry values */
-#define DBG_IOC 8 /* ioctl trace */
-#define DBG_STA 9 /* ResponseStatus() trace */
-#define DBG_ERR 10 /* cc_ReadError() trace */
-#define DBG_CMD 11 /* cmd_out() trace */
-#define DBG_WRN 12 /* give explanation before auto-probing */
-#define DBG_MUL 13 /* multi session code test */
-#define DBG_IDX 14 /* test code for drive_id !=0 */
-#define DBG_IOX 15 /* some special information */
-#define DBG_DID 16 /* drive ID test */
-#define DBG_RES 17 /* drive reset info */
-#define DBG_SPI 18 /* SpinUp test */
-#define DBG_IOS 19 /* ioctl trace: subchannel functions */
-#define DBG_IO2 20 /* ioctl trace: general */
-#define DBG_UPC 21 /* show UPC information */
-#define DBG_XA1 22 /* XA mode debugging */
-#define DBG_LCK 23 /* door (un)lock info */
-#define DBG_SQ1 24 /* dump SubQ frame */
-#define DBG_AUD 25 /* READ AUDIO debugging */
-#define DBG_SEQ 26 /* Sequoia interface configuration trace */
-#define DBG_LCS 27 /* Longshine LCS-7260 debugging trace */
-#define DBG_CD2 28 /* MKE/Funai CD200 debugging trace */
-#define DBG_TEA 29 /* TEAC CD-55A debugging trace */
-#define DBG_ECS 30 /* ECS-AT (Vertos 100) debugging trace */
-#define DBG_000 31 /* unnecessary information */
-
-/*==========================================================================*/
-/*==========================================================================*/
-
-/*
- * bits of flags_cmd_out:
- */
-#define f_respo3 0x100
-#define f_putcmd 0x80
-#define f_respo2 0x40
-#define f_lopsta 0x20
-#define f_getsta 0x10
-#define f_ResponseStatus 0x08
-#define f_obey_p_check 0x04
-#define f_bit1 0x02
-#define f_wait_if_busy 0x01
-
-/*
- * diskstate_flags:
- */
-#define x80_bit 0x80
-#define upc_bit 0x40
-#define volume_bit 0x20
-#define toc_bit 0x10
-#define multisession_bit 0x08
-#define cd_size_bit 0x04
-#define subq_bit 0x02
-#define frame_size_bit 0x01
-
-/*
- * disk states (bits of diskstate_flags):
- */
-#define upc_valid (current_drive->diskstate_flags&upc_bit)
-#define volume_valid (current_drive->diskstate_flags&volume_bit)
-#define toc_valid (current_drive->diskstate_flags&toc_bit)
-#define cd_size_valid (current_drive->diskstate_flags&cd_size_bit)
-#define subq_valid (current_drive->diskstate_flags&subq_bit)
-#define frame_size_valid (current_drive->diskstate_flags&frame_size_bit)
-
-/*
- * the status_bits variable
- */
-#define p_success 0x100
-#define p_door_closed 0x80
-#define p_caddy_in 0x40
-#define p_spinning 0x20
-#define p_check 0x10
-#define p_busy_new 0x08
-#define p_door_locked 0x04
-#define p_disk_ok 0x01
-
-/*
- * LCS-7260 special status result bits:
- */
-#define p_lcs_door_locked 0x02
-#define p_lcs_door_closed 0x01 /* probably disk_in */
-
-/*
- * CR-52x special status result bits:
- */
-#define p_caddin_old 0x40
-#define p_success_old 0x08
-#define p_busy_old 0x04
-#define p_bit_1 0x02 /* hopefully unused now */
-
-/*
- * "generation specific" defs of the status result bits:
- */
-#define p0_door_closed 0x80
-#define p0_caddy_in 0x40
-#define p0_spinning 0x20
-#define p0_check 0x10
-#define p0_success 0x08 /* unused */
-#define p0_busy 0x04
-#define p0_bit_1 0x02 /* unused */
-#define p0_disk_ok 0x01
-
-#define pL_disk_in 0x40
-#define pL_spinning 0x20
-#define pL_check 0x10
-#define pL_success 0x08 /* unused ?? */
-#define pL_busy 0x04
-#define pL_door_locked 0x02
-#define pL_door_closed 0x01
-
-#define pV_door_closed 0x40
-#define pV_spinning 0x20
-#define pV_check 0x10
-#define pV_success 0x08
-#define pV_busy 0x04
-#define pV_door_locked 0x02
-#define pV_disk_ok 0x01
-
-#define p1_door_closed 0x80
-#define p1_disk_in 0x40
-#define p1_spinning 0x20
-#define p1_check 0x10
-#define p1_busy 0x08
-#define p1_door_locked 0x04
-#define p1_bit_1 0x02 /* unused */
-#define p1_disk_ok 0x01
-
-#define p2_disk_ok 0x80
-#define p2_door_locked 0x40
-#define p2_spinning 0x20
-#define p2_busy2 0x10
-#define p2_busy1 0x08
-#define p2_door_closed 0x04
-#define p2_disk_in 0x02
-#define p2_check 0x01
-
-/*
- * used drive states:
- */
-#define st_door_closed (current_drive->status_bits&p_door_closed)
-#define st_caddy_in (current_drive->status_bits&p_caddy_in)
-#define st_spinning (current_drive->status_bits&p_spinning)
-#define st_check (current_drive->status_bits&p_check)
-#define st_busy (current_drive->status_bits&p_busy_new)
-#define st_door_locked (current_drive->status_bits&p_door_locked)
-#define st_diskok (current_drive->status_bits&p_disk_ok)
-
-/*
- * bits of the CDi_status register:
- */
-#define s_not_result_ready 0x04 /* 0: "result ready" */
-#define s_not_data_ready 0x02 /* 0: "data ready" */
-#define s_attention 0x01 /* 1: "attention required" */
-/*
- * usable as:
- */
-#define DRV_ATTN ((inb(CDi_status)&s_attention)!=0)
-#define DATA_READY ((inb(CDi_status)&s_not_data_ready)==0)
-#define RESULT_READY ((inb(CDi_status)&s_not_result_ready)==0)
-
-/*
- * drive families and types (firmware versions):
- */
-#define drv_fam0 0x0100 /* CR-52x family */
-#define drv_199 (drv_fam0+0x01) /* <200 */
-#define drv_200 (drv_fam0+0x02) /* <201 */
-#define drv_201 (drv_fam0+0x03) /* <210 */
-#define drv_210 (drv_fam0+0x04) /* <211 */
-#define drv_211 (drv_fam0+0x05) /* <300 */
-#define drv_300 (drv_fam0+0x06) /* >=300 */
-
-#define drv_fam1 0x0200 /* CR-56x family */
-#define drv_099 (drv_fam1+0x01) /* <100 */
-#define drv_100 (drv_fam1+0x02) /* >=100, only 1.02 and 5.00 known */
-
-#define drv_fam2 0x0400 /* CD200 family */
-
-#define drv_famT 0x0800 /* TEAC CD-55A */
-
-#define drv_famL 0x1000 /* Longshine family */
-#define drv_260 (drv_famL+0x01) /* LCS-7260 */
-#define drv_e1 (drv_famL+0x01) /* LCS-7260, firmware "A E1" */
-#define drv_f4 (drv_famL+0x02) /* LCS-7260, firmware "A4F4" */
-
-#define drv_famV 0x2000 /* ECS-AT (vertos-100) family */
-#define drv_at (drv_famV+0x01) /* ECS-AT, firmware "1.00" */
-
-#define fam0_drive (current_drive->drv_type&drv_fam0)
-#define famL_drive (current_drive->drv_type&drv_famL)
-#define famV_drive (current_drive->drv_type&drv_famV)
-#define fam1_drive (current_drive->drv_type&drv_fam1)
-#define fam2_drive (current_drive->drv_type&drv_fam2)
-#define famT_drive (current_drive->drv_type&drv_famT)
-#define fam0L_drive (current_drive->drv_type&(drv_fam0|drv_famL))
-#define fam0V_drive (current_drive->drv_type&(drv_fam0|drv_famV))
-#define famLV_drive (current_drive->drv_type&(drv_famL|drv_famV))
-#define fam0LV_drive (current_drive->drv_type&(drv_fam0|drv_famL|drv_famV))
-#define fam1L_drive (current_drive->drv_type&(drv_fam1|drv_famL))
-#define fam1V_drive (current_drive->drv_type&(drv_fam1|drv_famV))
-#define fam1LV_drive (current_drive->drv_type&(drv_fam1|drv_famL|drv_famV))
-#define fam01_drive (current_drive->drv_type&(drv_fam0|drv_fam1))
-#define fam12_drive (current_drive->drv_type&(drv_fam1|drv_fam2))
-#define fam2T_drive (current_drive->drv_type&(drv_fam2|drv_famT))
-
-/*
- * audio states:
- */
-#define audio_completed 3 /* Forgot this one! --AJK */
-#define audio_playing 2
-#define audio_pausing 1
-
-/*
- * drv_pattern, drv_options:
- */
-#define speed_auto 0x80
-#define speed_300 0x40
-#define speed_150 0x20
-#define audio_mono 0x04
-
-/*
- * values of cmd_type (0 else):
- */
-#define READ_M1 0x01 /* "data mode 1": 2048 bytes per frame */
-#define READ_M2 0x02 /* "data mode 2": 12+2048+280 bytes per frame */
-#define READ_SC 0x04 /* "subchannel info": 96 bytes per frame */
-#define READ_AU 0x08 /* "audio frame": 2352 bytes per frame */
-
-/*
- * sense_byte:
- *
- * values: 00
- * 01
- * 81
- * 82 "raw audio" mode
- * xx from infobuf[0] after 85 00 00 00 00 00 00
- */
-
-/* audio status (bin) */
-#define aud_00 0x00 /* Audio status byte not supported or not valid */
-#define audx11 0x0b /* Audio play operation in progress */
-#define audx12 0x0c /* Audio play operation paused */
-#define audx13 0x0d /* Audio play operation successfully completed */
-#define audx14 0x0e /* Audio play operation stopped due to error */
-#define audx15 0x0f /* No current audio status to return */
-/* audio status (bcd) */
-#define aud_11 0x11 /* Audio play operation in progress */
-#define aud_12 0x12 /* Audio play operation paused */
-#define aud_13 0x13 /* Audio play operation successfully completed */
-#define aud_14 0x14 /* Audio play operation stopped due to error */
-#define aud_15 0x15 /* No current audio status to return */
-
-/*
- * highest allowed drive number (MINOR+1)
- */
-#define NR_SBPCD 4
-
-/*
- * we try to never disable interrupts - seems to work
- */
-#define SBPCD_DIS_IRQ 0
-
-/*
- * "write byte to port"
- */
-#define OUT(x,y) outb(y,x)
-
-/*==========================================================================*/
-
-#define MIXER_addr SOUND_BASE+4 /* sound card's address register */
-#define MIXER_data SOUND_BASE+5 /* sound card's data register */
-#define MIXER_CD_Volume 0x28 /* internal SB Pro register address */
-
-/*==========================================================================*/
-
-#define MAX_TRACKS 99
-
-#define ERR_DISKCHANGE 615
-
-/*==========================================================================*/
-/*
- * To make conversions easier (machine dependent!)
- */
-typedef union _msf
-{
- u_int n;
- u_char c[4];
-} MSF;
-
-typedef union _blk
-{
- u_int n;
- u_char c[4];
-} BLK;
-
-/*==========================================================================*/
-
-/*============================================================================
-==============================================================================
-
-COMMAND SET of "old" drives like CR-521, CR-522
- (the CR-562 family is different):
-
-No. Command Code
---------------------------------------------
-
-Drive Commands:
- 1 Seek 01
- 2 Read Data 02
- 3 Read XA-Data 03
- 4 Read Header 04
- 5 Spin Up 05
- 6 Spin Down 06
- 7 Diagnostic 07
- 8 Read UPC 08
- 9 Read ISRC 09
-10 Play Audio 0A
-11 Play Audio MSF 0B
-12 Play Audio Track/Index 0C
-
-Status Commands:
-13 Read Status 81
-14 Read Error 82
-15 Read Drive Version 83
-16 Mode Select 84
-17 Mode Sense 85
-18 Set XA Parameter 86
-19 Read XA Parameter 87
-20 Read Capacity 88
-21 Read SUB_Q 89
-22 Read Disc Code 8A
-23 Read Disc Information 8B
-24 Read TOC 8C
-25 Pause/Resume 8D
-26 Read Packet 8E
-27 Read Path Check 00
-
-
-all numbers (lba, msf-bin, msf-bcd, counts) to transfer high byte first
-
-mnemo 7-byte command #bytes response (r0...rn)
-________ ____________________ ____
-
-Read Status:
-status: 81. (1) one-byte command, gives the main
- status byte
-Read Error:
-check1: 82 00 00 00 00 00 00. (6) r1: audio status
-
-Read Packet:
-check2: 8e xx 00 00 00 00 00. (xx) gets xx bytes response, relating
- to commands 01 04 05 07 08 09
-
-Play Audio:
-play: 0a ll-bb-aa nn-nn-nn. (0) play audio, ll-bb-aa: starting block (lba),
- nn-nn-nn: #blocks
-Play Audio MSF:
- 0b mm-ss-ff mm-ss-ff (0) play audio from/to
-
-Play Audio Track/Index:
- 0c ...
-
-Pause/Resume:
-pause: 8d pr 00 00 00 00 00. (0) pause (pr=00)
- resume (pr=80) audio playing
-
-Mode Select:
- 84 00 nn-nn ??.?? 00 (0) nn-nn: 2048 or 2340
- possibly defines transfer size
-
-set_vol: 84 83 00 00 sw le 00. (0) sw(itch): lrxxxxxx (off=1)
- le(vel): min=0, max=FF, else half
- (firmware 2.11)
-
-Mode Sense:
-get_vol: 85 03 00 00 00 00 00. (2) tell current audio volume setting
-
-Read Disc Information:
-tocdesc: 8b 00 00 00 00 00 00. (6) read the toc descriptor ("msf-bin"-format)
-
-Read TOC:
-tocent: 8c fl nn 00 00 00 00. (8) read toc entry #nn
- (fl=0:"lba"-, =2:"msf-bin"-format)
-
-Read Capacity:
-capacit: 88 00 00 00 00 00 00. (5) "read CD-ROM capacity"
-
-
-Read Path Check:
-ping: 00 00 00 00 00 00 00. (2) r0=AA, r1=55
- ("ping" if the drive is connected)
-
-Read Drive Version:
-ident: 83 00 00 00 00 00 00. (12) gives "MATSHITAn.nn"
- (n.nn = 2.01, 2.11., 3.00, ...)
-
-Seek:
-seek: 01 00 ll-bb-aa 00 00. (0)
-seek: 01 02 mm-ss-ff 00 00. (0)
-
-Read Data:
-read: 02 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2048 bytes,
- starting at block xx-xx-xx
- fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read XA-Data:
-read: 03 xx-xx-xx nn-nn fl. (?) read nn-nn blocks of 2340 bytes,
- starting at block xx-xx-xx
- fl=0: "lba"-, =2:"msf-bcd"-coded xx-xx-xx
-
-Read SUB_Q:
- 89 fl 00 00 00 00 00. (13) r0: audio status, r4-r7: lba/msf,
- fl=0: "lba", fl=2: "msf"
-
-Read Disc Code:
- 8a 00 00 00 00 00 00. (14) possibly extended "check condition"-info
-
-Read Header:
- 04 00 ll-bb-aa 00 00. (0) 4 bytes response with "check2"
- 04 02 mm-ss-ff 00 00. (0) 4 bytes response with "check2"
-
-Spin Up:
- 05 00 ll-bb-aa 00 00. (0) possibly implies a "seek"
-
-Spin Down:
- 06 ...
-
-Diagnostic:
- 07 00 ll-bb-aa 00 00. (2) 2 bytes response with "check2"
- 07 02 mm-ss-ff 00 00. (2) 2 bytes response with "check2"
-
-Read UPC:
- 08 00 ll-bb-aa 00 00. (16)
- 08 02 mm-ss-ff 00 00. (16)
-
-Read ISRC:
- 09 00 ll-bb-aa 00 00. (15) 15 bytes response with "check2"
- 09 02 mm-ss-ff 00 00. (15) 15 bytes response with "check2"
-
-Set XA Parameter:
- 86 ...
-
-Read XA Parameter:
- 87 ...
-
-==============================================================================
-============================================================================*/
-
-/*
- * commands
- *
- * CR-52x: CMD0_
- * CR-56x: CMD1_
- * CD200: CMD2_
- * LCS-7260: CMDL_
- * TEAC CD-55A: CMDT_
- * ECS-AT: CMDV_
- */
-#define CMD1_RESET 0x0a
-#define CMD2_RESET 0x01
-#define CMDT_RESET 0xc0
-
-#define CMD1_LOCK_CTL 0x0c
-#define CMD2_LOCK_CTL 0x1e
-#define CMDT_LOCK_CTL CMD2_LOCK_CTL
-#define CMDL_LOCK_CTL 0x0e
-#define CMDV_LOCK_CTL CMDL_LOCK_CTL
-
-#define CMD1_TRAY_CTL 0x07
-#define CMD2_TRAY_CTL 0x1b
-#define CMDT_TRAY_CTL CMD2_TRAY_CTL
-#define CMDL_TRAY_CTL 0x0d
-#define CMDV_TRAY_CTL CMDL_TRAY_CTL
-
-#define CMD1_MULTISESS 0x8d
-#define CMDL_MULTISESS 0x8c
-#define CMDV_MULTISESS CMDL_MULTISESS
-
-#define CMD1_SUBCHANINF 0x11
-#define CMD2_SUBCHANINF 0x??
-
-#define CMD1_ABORT 0x08
-#define CMD2_ABORT 0x08
-#define CMDT_ABORT 0x08
-
-#define CMD2_x02 0x02
-
-#define CMD2_SETSPEED 0xda
-
-#define CMD0_PATH_CHECK 0x00
-#define CMD1_PATH_CHECK 0x???
-#define CMD2_PATH_CHECK 0x???
-#define CMDT_PATH_CHECK 0x???
-#define CMDL_PATH_CHECK CMD0_PATH_CHECK
-#define CMDV_PATH_CHECK CMD0_PATH_CHECK
-
-#define CMD0_SEEK 0x01
-#define CMD1_SEEK CMD0_SEEK
-#define CMD2_SEEK 0x2b
-#define CMDT_SEEK CMD2_SEEK
-#define CMDL_SEEK CMD0_SEEK
-#define CMDV_SEEK CMD0_SEEK
-
-#define CMD0_READ 0x02
-#define CMD1_READ 0x10
-#define CMD2_READ 0x28
-#define CMDT_READ CMD2_READ
-#define CMDL_READ CMD0_READ
-#define CMDV_READ CMD0_READ
-
-#define CMD0_READ_XA 0x03
-#define CMD2_READ_XA 0xd4
-#define CMD2_READ_XA2 0xd5
-#define CMDL_READ_XA CMD0_READ_XA /* really ?? */
-#define CMDV_READ_XA CMD0_READ_XA
-
-#define CMD0_READ_HEAD 0x04
-
-#define CMD0_SPINUP 0x05
-#define CMD1_SPINUP 0x02
-#define CMD2_SPINUP CMD2_TRAY_CTL
-#define CMDL_SPINUP CMD0_SPINUP
-#define CMDV_SPINUP CMD0_SPINUP
-
-#define CMD0_SPINDOWN 0x06 /* really??? */
-#define CMD1_SPINDOWN 0x06
-#define CMD2_SPINDOWN CMD2_TRAY_CTL
-#define CMDL_SPINDOWN 0x0d
-#define CMDV_SPINDOWN CMD0_SPINDOWN
-
-#define CMD0_DIAG 0x07
-
-#define CMD0_READ_UPC 0x08
-#define CMD1_READ_UPC 0x88
-#define CMD2_READ_UPC 0x???
-#define CMDL_READ_UPC CMD0_READ_UPC
-#define CMDV_READ_UPC 0x8f
-
-#define CMD0_READ_ISRC 0x09
-
-#define CMD0_PLAY 0x0a
-#define CMD1_PLAY 0x???
-#define CMD2_PLAY 0x???
-#define CMDL_PLAY CMD0_PLAY
-#define CMDV_PLAY CMD0_PLAY
-
-#define CMD0_PLAY_MSF 0x0b
-#define CMD1_PLAY_MSF 0x0e
-#define CMD2_PLAY_MSF 0x47
-#define CMDT_PLAY_MSF CMD2_PLAY_MSF
-#define CMDL_PLAY_MSF 0x???
-
-#define CMD0_PLAY_TI 0x0c
-#define CMD1_PLAY_TI 0x0f
-
-#define CMD0_STATUS 0x81
-#define CMD1_STATUS 0x05
-#define CMD2_STATUS 0x00
-#define CMDT_STATUS CMD2_STATUS
-#define CMDL_STATUS CMD0_STATUS
-#define CMDV_STATUS CMD0_STATUS
-#define CMD2_SEEK_LEADIN 0x00
-
-#define CMD0_READ_ERR 0x82
-#define CMD1_READ_ERR CMD0_READ_ERR
-#define CMD2_READ_ERR 0x03
-#define CMDT_READ_ERR CMD2_READ_ERR /* get audio status */
-#define CMDL_READ_ERR CMD0_READ_ERR
-#define CMDV_READ_ERR CMD0_READ_ERR
-
-#define CMD0_READ_VER 0x83
-#define CMD1_READ_VER CMD0_READ_VER
-#define CMD2_READ_VER 0x12
-#define CMDT_READ_VER CMD2_READ_VER /* really ?? */
-#define CMDL_READ_VER CMD0_READ_VER
-#define CMDV_READ_VER CMD0_READ_VER
-
-#define CMD0_SETMODE 0x84
-#define CMD1_SETMODE 0x09
-#define CMD2_SETMODE 0x55
-#define CMDT_SETMODE CMD2_SETMODE
-#define CMDL_SETMODE CMD0_SETMODE
-
-#define CMD0_GETMODE 0x85
-#define CMD1_GETMODE 0x84
-#define CMD2_GETMODE 0x5a
-#define CMDT_GETMODE CMD2_GETMODE
-#define CMDL_GETMODE CMD0_GETMODE
-
-#define CMD0_SET_XA 0x86
-
-#define CMD0_GET_XA 0x87
-
-#define CMD0_CAPACITY 0x88
-#define CMD1_CAPACITY 0x85
-#define CMD2_CAPACITY 0x25
-#define CMDL_CAPACITY CMD0_CAPACITY /* missing in some firmware versions */
-
-#define CMD0_READSUBQ 0x89
-#define CMD1_READSUBQ 0x87
-#define CMD2_READSUBQ 0x42
-#define CMDT_READSUBQ CMD2_READSUBQ
-#define CMDL_READSUBQ CMD0_READSUBQ
-#define CMDV_READSUBQ CMD0_READSUBQ
-
-#define CMD0_DISKCODE 0x8a
-
-#define CMD0_DISKINFO 0x8b
-#define CMD1_DISKINFO CMD0_DISKINFO
-#define CMD2_DISKINFO 0x43
-#define CMDT_DISKINFO CMD2_DISKINFO
-#define CMDL_DISKINFO CMD0_DISKINFO
-#define CMDV_DISKINFO CMD0_DISKINFO
-
-#define CMD0_READTOC 0x8c
-#define CMD1_READTOC CMD0_READTOC
-#define CMD2_READTOC 0x???
-#define CMDL_READTOC CMD0_READTOC
-#define CMDV_READTOC CMD0_READTOC
-
-#define CMD0_PAU_RES 0x8d
-#define CMD1_PAU_RES 0x0d
-#define CMD2_PAU_RES 0x4b
-#define CMDT_PAUSE CMD2_PAU_RES
-#define CMDL_PAU_RES CMD0_PAU_RES
-#define CMDV_PAUSE CMD0_PAU_RES
-
-#define CMD0_PACKET 0x8e
-#define CMD1_PACKET CMD0_PACKET
-#define CMD2_PACKET 0x???
-#define CMDL_PACKET CMD0_PACKET
-#define CMDV_PACKET 0x???
-
-/*==========================================================================*/
-/*==========================================================================*/
-#endif /* _LINUX_SBPCD_H */
-/*==========================================================================*/
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
deleted file mode 100644
index 5409fca5bbf..00000000000
--- a/drivers/cdrom/sjcd.c
+++ /dev/null
@@ -1,1815 +0,0 @@
-/* -- sjcd.c
- *
- * Sanyo CD-ROM device driver implementation, Version 1.6
- * Copyright (C) 1995 Vadim V. Model
- *
- * model@cecmow.enet.dec.com
- * vadim@rbrf.ru
- * vadim@ipsun.ras.ru
- *
- *
- * This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
- * it was developed under use of mcd.c from Martin Harriss, with help of
- * Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl).
- *
- * It is planned to include these routines into sbpcd.c later - to make
- * a "mixed use" on one cable possible for all kinds of drives which use
- * the SoundBlaster/Panasonic style CDROM interface. But today, the
- * ability to install directly from CDROM is more important than flexibility.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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.
- *
- * History:
- * 1.1 First public release with kernel version 1.3.7.
- * Written by Vadim Model.
- * 1.2 Added detection and configuration of cdrom interface
- * on ISP16 soundcard.
- * Allow for command line options: sjcd=<io_base>,<irq>,<dma>
- * 1.3 Some minor changes to README.sjcd.
- * 1.4 MSS Sound support!! Listen to a CD through the speakers.
- * 1.5 Module support and bugfixes.
- * Tray locking.
- * 1.6 Removed ISP16 code from this driver.
- * Allow only to set io base address on command line: sjcd=<io_base>
- * Changes to Documentation/cdrom/sjcd
- * Added cleanup after any error in the initialisation.
- * 1.7 Added code to set the sector size tables to prevent the bug present in
- * the previous version of this driver. Coded added by Anthony Barbachan
- * from bugfix tip originally suggested by Alan Cox.
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- */
-
-#define SJCD_VERSION_MAJOR 1
-#define SJCD_VERSION_MINOR 7
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/major.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/blkdev.h>
-#include "sjcd.h"
-
-static int sjcd_present = 0;
-static struct request_queue *sjcd_queue;
-
-#define MAJOR_NR SANYO_CDROM_MAJOR
-#define QUEUE (sjcd_queue)
-#define CURRENT elv_next_request(sjcd_queue)
-
-#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
-
-/*
- * buffer for block size conversion
- */
-static char sjcd_buf[2048 * SJCD_BUF_SIZ];
-static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn;
-static volatile int sjcd_buf_in, sjcd_buf_out = -1;
-
-/*
- * Status.
- */
-static unsigned short sjcd_status_valid = 0;
-static unsigned short sjcd_door_closed;
-static unsigned short sjcd_door_was_open;
-static unsigned short sjcd_media_is_available;
-static unsigned short sjcd_media_is_changed;
-static unsigned short sjcd_toc_uptodate = 0;
-static unsigned short sjcd_command_failed;
-static volatile unsigned char sjcd_completion_status = 0;
-static volatile unsigned char sjcd_completion_error = 0;
-static unsigned short sjcd_command_is_in_progress = 0;
-static unsigned short sjcd_error_reported = 0;
-static DEFINE_SPINLOCK(sjcd_lock);
-
-static int sjcd_open_count;
-
-static int sjcd_audio_status;
-static struct sjcd_play_msf sjcd_playing;
-
-static int sjcd_base = SJCD_BASE_ADDR;
-
-module_param(sjcd_base, int, 0);
-
-static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
-
-/*
- * Data transfer.
- */
-static volatile unsigned short sjcd_transfer_is_active = 0;
-
-enum sjcd_transfer_state {
- SJCD_S_IDLE = 0,
- SJCD_S_START = 1,
- SJCD_S_MODE = 2,
- SJCD_S_READ = 3,
- SJCD_S_DATA = 4,
- SJCD_S_STOP = 5,
- SJCD_S_STOPPING = 6
-};
-static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
-static long sjcd_transfer_timeout = 0;
-static int sjcd_read_count = 0;
-static unsigned char sjcd_mode = 0;
-
-#define SJCD_READ_TIMEOUT 5000
-
-#if defined( SJCD_GATHER_STAT )
-/*
- * Statistic.
- */
-static struct sjcd_stat statistic;
-#endif
-
-/*
- * Timer.
- */
-static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0);
-
-#define SJCD_SET_TIMER( func, tmout ) \
- ( sjcd_delay_timer.expires = jiffies+tmout, \
- sjcd_delay_timer.function = ( void * )func, \
- add_timer( &sjcd_delay_timer ) )
-
-#define CLEAR_TIMER del_timer( &sjcd_delay_timer )
-
-/*
- * Set up device, i.e., use command line data to set
- * base address.
- */
-#ifndef MODULE
-static int __init sjcd_setup(char *str)
-{
- int ints[2];
- (void) get_options(str, ARRAY_SIZE(ints), ints);
- if (ints[0] > 0)
- sjcd_base = ints[1];
-
- return 1;
-}
-
-__setup("sjcd=", sjcd_setup);
-
-#endif
-
-/*
- * Special converters.
- */
-static unsigned char bin2bcd(int bin)
-{
- int u, v;
-
- u = bin % 10;
- v = bin / 10;
- return (u | (v << 4));
-}
-
-static int bcd2bin(unsigned char bcd)
-{
- return ((bcd >> 4) * 10 + (bcd & 0x0F));
-}
-
-static long msf2hsg(struct msf *mp)
-{
- return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75
- + bcd2bin(mp->min) * 4500 - 150);
-}
-
-static void hsg2msf(long hsg, struct msf *msf)
-{
- hsg += 150;
- msf->min = hsg / 4500;
- hsg %= 4500;
- msf->sec = hsg / 75;
- msf->frame = hsg % 75;
- msf->min = bin2bcd(msf->min); /* convert to BCD */
- msf->sec = bin2bcd(msf->sec);
- msf->frame = bin2bcd(msf->frame);
-}
-
-/*
- * Send a command to cdrom. Invalidate status.
- */
-static void sjcd_send_cmd(unsigned char cmd)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with one arg to cdrom. Invalidate status.
- */
-static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(a, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a command with four args to cdrom. Invalidate status.
- */
-static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a,
- unsigned char b, unsigned char c,
- unsigned char d)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_4_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(a, SJCDPORT(0));
- outb(b, SJCDPORT(0));
- outb(c, SJCDPORT(0));
- outb(d, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Send a play or read command to cdrom. Invalidate Status.
- */
-static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: send_long_cmd( 0x%x )\n", cmd);
-#endif
- outb(cmd, SJCDPORT(0));
- outb(pms->start.min, SJCDPORT(0));
- outb(pms->start.sec, SJCDPORT(0));
- outb(pms->start.frame, SJCDPORT(0));
- outb(pms->end.min, SJCDPORT(0));
- outb(pms->end.sec, SJCDPORT(0));
- outb(pms->end.frame, SJCDPORT(0));
- sjcd_command_is_in_progress = 1;
- sjcd_status_valid = 0;
- sjcd_command_failed = 0;
-}
-
-/*
- * Get a value from the data port. Should not block, so we use a little
- * wait for a while. Returns 0 if OK.
- */
-static int sjcd_load_response(void *buf, int len)
-{
- unsigned char *resp = (unsigned char *) buf;
-
- for (; len; --len) {
- int i;
- for (i = 200;
- i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))););
- if (i > 0)
- *resp++ = (unsigned char) inb(SJCDPORT(0));
- else
- break;
- }
- return (len);
-}
-
-/*
- * Load and parse command completion status (drive info byte and maybe error).
- * Sorry, no error classification yet.
- */
-static void sjcd_load_status(void)
-{
- sjcd_media_is_changed = 0;
- sjcd_completion_error = 0;
- sjcd_completion_status = inb(SJCDPORT(0));
- if (sjcd_completion_status & SST_DOOR_OPENED) {
- sjcd_door_closed = sjcd_media_is_available = 0;
- } else {
- sjcd_door_closed = 1;
- if (sjcd_completion_status & SST_MEDIA_CHANGED)
- sjcd_media_is_available = sjcd_media_is_changed =
- 1;
- else if (sjcd_completion_status & 0x0F) {
- /*
- * OK, we seem to catch an error ...
- */
- while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))));
- sjcd_completion_error = inb(SJCDPORT(0));
- if ((sjcd_completion_status & 0x08) &&
- (sjcd_completion_error & 0x40))
- sjcd_media_is_available = 0;
- else
- sjcd_command_failed = 1;
- } else
- sjcd_media_is_available = 1;
- }
- /*
- * Ok, status loaded successfully.
- */
- sjcd_status_valid = 1, sjcd_error_reported = 0;
- sjcd_command_is_in_progress = 0;
-
- /*
- * If the disk is changed, the TOC is not valid.
- */
- if (sjcd_media_is_changed)
- sjcd_toc_uptodate = 0;
-#if defined( SJCD_TRACE )
- printk("SJCD: status %02x.%02x loaded.\n",
- (int) sjcd_completion_status, (int) sjcd_completion_error);
-#endif
-}
-
-/*
- * Read status from cdrom. Check to see if the status is available.
- */
-static int sjcd_check_status(void)
-{
- /*
- * Try to load the response from cdrom into buffer.
- */
- if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) {
- sjcd_load_status();
- return (1);
- } else {
- /*
- * No status is available.
- */
- return (0);
- }
-}
-
-/*
- * This is just timeout counter, and nothing more. Surprised ? :-)
- */
-static volatile long sjcd_status_timeout;
-
-/*
- * We need about 10 seconds to wait. The longest command takes about 5 seconds
- * to probe the disk (usually after tray closed or drive reset). Other values
- * should be thought of for other commands.
- */
-#define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
-
-static void sjcd_status_timer(void)
-{
- if (sjcd_check_status()) {
- /*
- * The command completed and status is loaded, stop waiting.
- */
- wake_up(&sjcd_waitq);
- } else if (--sjcd_status_timeout <= 0) {
- /*
- * We are timed out.
- */
- wake_up(&sjcd_waitq);
- } else {
- /*
- * We have still some time to wait. Try again.
- */
- SJCD_SET_TIMER(sjcd_status_timer, 1);
- }
-}
-
-/*
- * Wait for status for 10 sec approx. Returns non-positive when timed out.
- * Should not be used while reading data CDs.
- */
-static int sjcd_wait_for_status(void)
-{
- sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
- SJCD_SET_TIMER(sjcd_status_timer, 1);
- sleep_on(&sjcd_waitq);
-#if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
- if (sjcd_status_timeout <= 0)
- printk("SJCD: Error Wait For Status.\n");
-#endif
- return (sjcd_status_timeout);
-}
-
-static int sjcd_receive_status(void)
-{
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD: receive_status\n");
-#endif
- /*
- * Wait a bit for status available.
- */
- for (i = 200; i-- && (sjcd_check_status() == 0););
- if (i < 0) {
-#if defined( SJCD_TRACE )
- printk("SJCD: long wait for status\n");
-#endif
- if (sjcd_wait_for_status() <= 0)
- printk("SJCD: Timeout when read status.\n");
- else
- i = 0;
- }
- return (i);
-}
-
-/*
- * Load the status. Issue get status command and wait for status available.
- */
-static void sjcd_get_status(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: get_status\n");
-#endif
- sjcd_send_cmd(SCMD_GET_STATUS);
- sjcd_receive_status();
-}
-
-/*
- * Check the drive if the disk is changed. Should be revised.
- */
-static int sjcd_disk_change(struct gendisk *disk)
-{
-#if 0
- printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name);
-#endif
- if (!sjcd_command_is_in_progress)
- sjcd_get_status();
- return (sjcd_status_valid ? sjcd_media_is_changed : 0);
-}
-
-/*
- * Read the table of contents (TOC) and TOC header if necessary.
- * We assume that the drive contains no more than 99 toc entries.
- */
-static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS];
-static unsigned char sjcd_first_track_no, sjcd_last_track_no;
-#define sjcd_disk_length sjcd_table_of_contents[0].un.track_msf
-
-static int sjcd_update_toc(void)
-{
- struct sjcd_hw_disk_info info;
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD: update toc:\n");
-#endif
- /*
- * check to see if we need to do anything
- */
- if (sjcd_toc_uptodate)
- return (0);
-
- /*
- * Get the TOC start information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about TOC start.\n");
- return (-1);
- }
- sjcd_first_track_no = bcd2bin(info.un.track_no);
- } else {
- printk("SJCD: get first failed\n");
- return (-1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no);
-#endif
- /*
- * Get the TOC finish information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about TOC finish.\n");
- return (-1);
- }
- sjcd_last_track_no = bcd2bin(info.un.track_no);
- } else {
- printk("SJCD: get last failed\n");
- return (-1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no);
-#endif
- for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) {
- /*
- * Get the first track information.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i));
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&sjcd_table_of_contents[i],
- sizeof(struct
- sjcd_hw_disk_info))
- != 0) {
- printk
- ("SJCD: cannot load info for %d track\n",
- i);
- return (-1);
- }
- } else {
- printk("SJCD: get info %d failed\n", i);
- return (-1);
- }
- }
-
- /*
- * Get the disk length info.
- */
- sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE);
- sjcd_receive_status();
-
- if (!sjcd_status_valid) {
- printk("SJCD: cannot load status.\n");
- return (-1);
- }
-
- if (!sjcd_media_is_available) {
- printk("SJCD: no disk in drive\n");
- return (-1);
- }
-
- if (!sjcd_command_failed) {
- if (sjcd_load_response(&info, sizeof(info)) != 0) {
- printk
- ("SJCD: cannot load response about disk size.\n");
- return (-1);
- }
- sjcd_disk_length.min = info.un.track_msf.min;
- sjcd_disk_length.sec = info.un.track_msf.sec;
- sjcd_disk_length.frame = info.un.track_msf.frame;
- } else {
- printk("SJCD: get size failed\n");
- return (1);
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min,
- sjcd_disk_length.sec, sjcd_disk_length.frame);
-#endif
- return (0);
-}
-
-/*
- * Load subchannel information.
- */
-static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp)
-{
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: load sub q\n");
-#endif
- sjcd_send_cmd(SCMD_GET_QINFO);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {
- sjcd_send_cmd(0xF2);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
- return (-1);
- sjcd_send_cmd(SCMD_GET_QINFO);
- s = sjcd_receive_status();
- if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
- return (-1);
- }
- if (sjcd_media_is_available)
- if (sjcd_load_response(qp, sizeof(*qp)) == 0)
- return (0);
- return (-1);
-}
-
-/*
- * Start playing from the specified position.
- */
-static int sjcd_play(struct sjcd_play_msf *mp)
-{
- struct sjcd_play_msf msf;
-
- /*
- * Turn the device to play mode.
- */
- sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);
- if (sjcd_receive_status() < 0)
- return (-1);
-
- /*
- * Seek to the starting point.
- */
- msf.start = mp->start;
- msf.end.min = msf.end.sec = msf.end.frame = 0x00;
- sjcd_send_6_cmd(SCMD_SEEK, &msf);
- if (sjcd_receive_status() < 0)
- return (-1);
-
- /*
- * Start playing.
- */
- sjcd_send_6_cmd(SCMD_PLAY, mp);
- return (sjcd_receive_status());
-}
-
-/*
- * Tray control functions.
- */
-static int sjcd_tray_close(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_close\n");
-#endif
- sjcd_send_cmd(SCMD_CLOSE_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_lock(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_lock\n");
-#endif
- sjcd_send_cmd(SCMD_LOCK_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_unlock(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_unlock\n");
-#endif
- sjcd_send_cmd(SCMD_UNLOCK_TRAY);
- return (sjcd_receive_status());
-}
-
-static int sjcd_tray_open(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: tray_open\n");
-#endif
- sjcd_send_cmd(SCMD_EJECT_TRAY);
- return (sjcd_receive_status());
-}
-
-/*
- * Do some user commands.
- */
-static int sjcd_ioctl(struct inode *ip, struct file *fp,
- unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
-#if defined( SJCD_TRACE )
- printk("SJCD:ioctl\n");
-#endif
-
- sjcd_get_status();
- if (!sjcd_status_valid)
- return (-EIO);
- if (sjcd_update_toc() < 0)
- return (-EIO);
-
- switch (cmd) {
- case CDROMSTART:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: start\n");
-#endif
- return (0);
- }
-
- case CDROMSTOP:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: stop\n");
-#endif
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
- return (0);
- }
-
- case CDROMPAUSE:{
- struct sjcd_hw_qinfo q_info;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: pause\n");
-#endif
- if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- if (sjcd_get_q_info(&q_info) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_NO_STATUS;
- } else {
- sjcd_audio_status =
- CDROM_AUDIO_PAUSED;
- sjcd_playing.start = q_info.abs;
- }
- return (0);
- } else
- return (-EINVAL);
- }
-
- case CDROMRESUME:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: resume\n");
-#endif
- if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {
- /*
- * continue play starting at saved location
- */
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else {
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- return (0);
- }
- } else
- return (-EINVAL);
- }
-
- case CDROMPLAYTRKIND:{
- struct cdrom_ti ti;
- int s = -EFAULT;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: playtrkind\n");
-#endif
- if (!copy_from_user(&ti, argp, sizeof(ti))) {
- s = 0;
- if (ti.cdti_trk0 < sjcd_first_track_no)
- return (-EINVAL);
- if (ti.cdti_trk1 > sjcd_last_track_no)
- ti.cdti_trk1 = sjcd_last_track_no;
- if (ti.cdti_trk0 > ti.cdti_trk1)
- return (-EINVAL);
-
- sjcd_playing.start =
- sjcd_table_of_contents[ti.cdti_trk0].
- un.track_msf;
- sjcd_playing.end =
- (ti.cdti_trk1 <
- sjcd_last_track_no) ?
- sjcd_table_of_contents[ti.cdti_trk1 +
- 1].un.
- track_msf : sjcd_table_of_contents[0].
- un.track_msf;
-
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- }
- return (s);
- }
-
- case CDROMPLAYMSF:{
- struct cdrom_msf sjcd_msf;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: playmsf\n");
-#endif
- if ((s =
- access_ok(VERIFY_READ, argp, sizeof(sjcd_msf))
- ? 0 : -EFAULT) == 0) {
- if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
- sjcd_send_cmd(SCMD_PAUSE);
- (void) sjcd_receive_status();
- sjcd_audio_status =
- CDROM_AUDIO_NO_STATUS;
- }
-
- if (copy_from_user(&sjcd_msf, argp,
- sizeof(sjcd_msf)))
- return (-EFAULT);
-
- sjcd_playing.start.min =
- bin2bcd(sjcd_msf.cdmsf_min0);
- sjcd_playing.start.sec =
- bin2bcd(sjcd_msf.cdmsf_sec0);
- sjcd_playing.start.frame =
- bin2bcd(sjcd_msf.cdmsf_frame0);
- sjcd_playing.end.min =
- bin2bcd(sjcd_msf.cdmsf_min1);
- sjcd_playing.end.sec =
- bin2bcd(sjcd_msf.cdmsf_sec1);
- sjcd_playing.end.frame =
- bin2bcd(sjcd_msf.cdmsf_frame1);
-
- if (sjcd_play(&sjcd_playing) < 0) {
- sjcd_audio_status =
- CDROM_AUDIO_ERROR;
- return (-EIO);
- } else
- sjcd_audio_status =
- CDROM_AUDIO_PLAY;
- }
- return (s);
- }
-
- case CDROMREADTOCHDR:{
- struct cdrom_tochdr toc_header;
-#if defined (SJCD_TRACE )
- printk("SJCD: ioctl: readtocheader\n");
-#endif
- toc_header.cdth_trk0 = sjcd_first_track_no;
- toc_header.cdth_trk1 = sjcd_last_track_no;
- if (copy_to_user(argp, &toc_header,
- sizeof(toc_header)))
- return -EFAULT;
- return 0;
- }
-
- case CDROMREADTOCENTRY:{
- struct cdrom_tocentry toc_entry;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: readtocentry\n");
-#endif
- if ((s =
- access_ok(VERIFY_WRITE, argp, sizeof(toc_entry))
- ? 0 : -EFAULT) == 0) {
- struct sjcd_hw_disk_info *tp;
-
- if (copy_from_user(&toc_entry, argp,
- sizeof(toc_entry)))
- return (-EFAULT);
- if (toc_entry.cdte_track == CDROM_LEADOUT)
- tp = &sjcd_table_of_contents[0];
- else if (toc_entry.cdte_track <
- sjcd_first_track_no)
- return (-EINVAL);
- else if (toc_entry.cdte_track >
- sjcd_last_track_no)
- return (-EINVAL);
- else
- tp = &sjcd_table_of_contents
- [toc_entry.cdte_track];
-
- toc_entry.cdte_adr =
- tp->track_control & 0x0F;
- toc_entry.cdte_ctrl =
- tp->track_control >> 4;
-
- switch (toc_entry.cdte_format) {
- case CDROM_LBA:
- toc_entry.cdte_addr.lba =
- msf2hsg(&(tp->un.track_msf));
- break;
- case CDROM_MSF:
- toc_entry.cdte_addr.msf.minute =
- bcd2bin(tp->un.track_msf.min);
- toc_entry.cdte_addr.msf.second =
- bcd2bin(tp->un.track_msf.sec);
- toc_entry.cdte_addr.msf.frame =
- bcd2bin(tp->un.track_msf.
- frame);
- break;
- default:
- return (-EINVAL);
- }
- if (copy_to_user(argp, &toc_entry,
- sizeof(toc_entry)))
- s = -EFAULT;
- }
- return (s);
- }
-
- case CDROMSUBCHNL:{
- struct cdrom_subchnl subchnl;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: subchnl\n");
-#endif
- if ((s =
- access_ok(VERIFY_WRITE, argp, sizeof(subchnl))
- ? 0 : -EFAULT) == 0) {
- struct sjcd_hw_qinfo q_info;
-
- if (copy_from_user(&subchnl, argp,
- sizeof(subchnl)))
- return (-EFAULT);
-
- if (sjcd_get_q_info(&q_info) < 0)
- return (-EIO);
-
- subchnl.cdsc_audiostatus =
- sjcd_audio_status;
- subchnl.cdsc_adr =
- q_info.track_control & 0x0F;
- subchnl.cdsc_ctrl =
- q_info.track_control >> 4;
- subchnl.cdsc_trk =
- bcd2bin(q_info.track_no);
- subchnl.cdsc_ind = bcd2bin(q_info.x);
-
- switch (subchnl.cdsc_format) {
- case CDROM_LBA:
- subchnl.cdsc_absaddr.lba =
- msf2hsg(&(q_info.abs));
- subchnl.cdsc_reladdr.lba =
- msf2hsg(&(q_info.rel));
- break;
- case CDROM_MSF:
- subchnl.cdsc_absaddr.msf.minute =
- bcd2bin(q_info.abs.min);
- subchnl.cdsc_absaddr.msf.second =
- bcd2bin(q_info.abs.sec);
- subchnl.cdsc_absaddr.msf.frame =
- bcd2bin(q_info.abs.frame);
- subchnl.cdsc_reladdr.msf.minute =
- bcd2bin(q_info.rel.min);
- subchnl.cdsc_reladdr.msf.second =
- bcd2bin(q_info.rel.sec);
- subchnl.cdsc_reladdr.msf.frame =
- bcd2bin(q_info.rel.frame);
- break;
- default:
- return (-EINVAL);
- }
- if (copy_to_user(argp, &subchnl,
- sizeof(subchnl)))
- s = -EFAULT;
- }
- return (s);
- }
-
- case CDROMVOLCTRL:{
- struct cdrom_volctrl vol_ctrl;
- int s;
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: volctrl\n");
-#endif
- if ((s =
- access_ok(VERIFY_READ, argp, sizeof(vol_ctrl))
- ? 0 : -EFAULT) == 0) {
- unsigned char dummy[4];
-
- if (copy_from_user(&vol_ctrl, argp,
- sizeof(vol_ctrl)))
- return (-EFAULT);
- sjcd_send_4_cmd(SCMD_SET_VOLUME,
- vol_ctrl.channel0, 0xFF,
- vol_ctrl.channel1, 0xFF);
- if (sjcd_receive_status() < 0)
- return (-EIO);
- (void) sjcd_load_response(dummy, 4);
- }
- return (s);
- }
-
- case CDROMEJECT:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: eject\n");
-#endif
- if (!sjcd_command_is_in_progress) {
- sjcd_tray_unlock();
- sjcd_send_cmd(SCMD_EJECT_TRAY);
- (void) sjcd_receive_status();
- }
- return (0);
- }
-
-#if defined( SJCD_GATHER_STAT )
- case 0xABCD:{
-#if defined( SJCD_TRACE )
- printk("SJCD: ioctl: statistic\n");
-#endif
- if (copy_to_user(argp, &statistic, sizeof(statistic)))
- return -EFAULT;
- return 0;
- }
-#endif
-
- default:
- return (-EINVAL);
- }
-}
-
-/*
- * Invalidate internal buffers of the driver.
- */
-static void sjcd_invalidate_buffers(void)
-{
- int i;
- for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);
- sjcd_buf_out = -1;
-}
-
-/*
- * Take care of the different block sizes between cdrom and Linux.
- * When Linux gets variable block sizes this will probably go away.
- */
-
-static int current_valid(void)
-{
- return CURRENT &&
- CURRENT->cmd == READ &&
- CURRENT->sector != -1;
-}
-
-static void sjcd_transfer(void)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: transfer:\n");
-#endif
- if (current_valid()) {
- while (CURRENT->nr_sectors) {
- int i, bn = CURRENT->sector / 4;
- for (i = 0;
- i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;
- i++);
- if (i < SJCD_BUF_SIZ) {
- int offs =
- (i * 4 + (CURRENT->sector & 3)) * 512;
- int nr_sectors = 4 - (CURRENT->sector & 3);
- if (sjcd_buf_out != i) {
- sjcd_buf_out = i;
- if (sjcd_buf_bn[i] != bn) {
- sjcd_buf_out = -1;
- continue;
- }
- }
- if (nr_sectors > CURRENT->nr_sectors)
- nr_sectors = CURRENT->nr_sectors;
-#if defined( SJCD_TRACE )
- printk("SJCD: copy out\n");
-#endif
- memcpy(CURRENT->buffer, sjcd_buf + offs,
- nr_sectors * 512);
- CURRENT->nr_sectors -= nr_sectors;
- CURRENT->sector += nr_sectors;
- CURRENT->buffer += nr_sectors * 512;
- } else {
- sjcd_buf_out = -1;
- break;
- }
- }
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: transfer: done\n");
-#endif
-}
-
-static void sjcd_poll(void)
-{
-#if defined( SJCD_GATHER_STAT )
- /*
- * Update total number of ticks.
- */
- statistic.ticks++;
- statistic.tticks[sjcd_transfer_state]++;
-#endif
-
- ReSwitch:switch (sjcd_transfer_state) {
-
- case SJCD_S_IDLE:{
-#if defined( SJCD_GATHER_STAT )
- statistic.idle_ticks++;
-#endif
-#if defined( SJCD_TRACE )
- printk("SJCD_S_IDLE\n");
-#endif
- return;
- }
-
- case SJCD_S_START:{
-#if defined( SJCD_GATHER_STAT )
- statistic.start_ticks++;
-#endif
- sjcd_send_cmd(SCMD_GET_STATUS);
- sjcd_transfer_state =
- sjcd_mode ==
- SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
- printk("SJCD_S_START: goto SJCD_S_%s mode\n",
- sjcd_transfer_state ==
- SJCD_S_READ ? "READ" : "MODE");
-#endif
- break;
- }
-
- case SJCD_S_MODE:{
- if (sjcd_check_status()) {
- /*
- * Previous command is completed.
- */
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- sjcd_mode = 0; /* unknown mode; should not be valid when failed */
- sjcd_send_1_cmd(SCMD_SET_MODE,
- SCMD_MODE_COOKED);
- sjcd_transfer_state = SJCD_S_READ;
- sjcd_transfer_timeout = 1000;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_MODE: goto SJCD_S_READ mode\n");
-#endif
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.mode_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_READ:{
- if (sjcd_status_valid ? 1 : sjcd_check_status()) {
- /*
- * Previous command is completed.
- */
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- if (!sjcd_media_is_available) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- if (sjcd_mode != SCMD_MODE_COOKED) {
- /*
- * We seem to come from set mode. So discard one byte of result.
- */
- if (sjcd_load_response
- (&sjcd_mode, 1) != 0) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- if (sjcd_mode != SCMD_MODE_COOKED) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- }
-
- if (current_valid()) {
- struct sjcd_play_msf msf;
-
- sjcd_next_bn = CURRENT->sector / 4;
- hsg2msf(sjcd_next_bn, &msf.start);
- msf.end.min = 0;
- msf.end.sec = 0;
- msf.end.frame = sjcd_read_count =
- SJCD_BUF_SIZ;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n",
- msf.start.min, msf.start.sec,
- msf.start.frame, msf.end.min,
- msf.end.sec, msf.end.frame);
- printk
- ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n",
- sjcd_next_bn, sjcd_buf_in,
- sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
-#endif
- sjcd_send_6_cmd(SCMD_DATA_READ,
- &msf);
- sjcd_transfer_state = SJCD_S_DATA;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: go to SJCD_S_DATA mode\n");
-#endif
- } else {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.read_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_DATA:{
- unsigned char stat;
-
- sjcd_s_data:stat =
- inb(SJCDPORT
- (1));
-#if defined( SJCD_TRACE )
- printk("SJCD_S_DATA: status = 0x%02x\n", stat);
-#endif
- if (SJCD_STATUS_AVAILABLE(stat)) {
- /*
- * No data is waiting for us in the drive buffer. Status of operation
- * completion is available. Read and parse it.
- */
- sjcd_load_status();
-
- if (!sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: read block %d failed, maybe audio disk? Giving up\n",
- sjcd_next_bn);
-#endif
- if (current_valid())
- end_request(CURRENT, 0);
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- if (!sjcd_media_is_available) {
- printk
- ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n");
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- sjcd_transfer_state = SJCD_S_READ;
- goto ReSwitch;
- } else if (SJCD_DATA_AVAILABLE(stat)) {
- /*
- * One frame is read into device buffer. We must copy it to our memory.
- * Otherwise cdrom hangs up. Check to see if we have something to copy
- * to.
- */
- if (!current_valid()
- && sjcd_buf_in == sjcd_buf_out) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n");
- printk
- (" ... all the date would be discarded\n");
-#endif
- sjcd_transfer_state = SJCD_S_STOP;
- goto ReSwitch;
- }
-
- /*
- * Everything seems to be OK. Just read the frame and recalculate
- * indices.
- */
- sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */
- insb(SJCDPORT(2),
- sjcd_buf + 2048 * sjcd_buf_in, 2048);
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n",
- sjcd_next_bn, sjcd_buf_in,
- sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
-#endif
- sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;
- if (sjcd_buf_out == -1)
- sjcd_buf_out = sjcd_buf_in;
- if (++sjcd_buf_in == SJCD_BUF_SIZ)
- sjcd_buf_in = 0;
-
- /*
- * Only one frame is ready at time. So we should turn over to wait for
- * another frame. If we need that, of course.
- */
- if (--sjcd_read_count == 0) {
- /*
- * OK, request seems to be precessed. Continue transferring...
- */
- if (!sjcd_transfer_is_active) {
- while (current_valid()) {
- /*
- * Continue transferring.
- */
- sjcd_transfer();
- if (CURRENT->
- nr_sectors ==
- 0)
- end_request
- (CURRENT, 1);
- else
- break;
- }
- }
- if (current_valid() &&
- (CURRENT->sector / 4 <
- sjcd_next_bn
- || CURRENT->sector / 4 >
- sjcd_next_bn +
- SJCD_BUF_SIZ)) {
-#if defined( SJCD_TRACE )
- printk
- ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n");
-#endif
- sjcd_transfer_state =
- SJCD_S_STOP;
- goto ReSwitch;
- }
- }
- /*
- * Now we should turn around rather than wait for while.
- */
- goto sjcd_s_data;
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.data_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_STOP:{
- sjcd_read_count = 0;
- sjcd_send_cmd(SCMD_STOP);
- sjcd_transfer_state = SJCD_S_STOPPING;
- sjcd_transfer_timeout = 500;
-#if defined( SJCD_GATHER_STAT )
- statistic.stop_ticks++;
-#endif
- break;
- }
-
- case SJCD_S_STOPPING:{
- unsigned char stat;
-
- stat = inb(SJCDPORT(1));
-#if defined( SJCD_TRACE )
- printk("SJCD_S_STOP: status = 0x%02x\n", stat);
-#endif
- if (SJCD_DATA_AVAILABLE(stat)) {
- int i;
-#if defined( SJCD_TRACE )
- printk("SJCD_S_STOP: discard data\n");
-#endif
- /*
- * Discard all the data from the pipe. Foolish method.
- */
- for (i = 2048; i--;
- (void) inb(SJCDPORT(2)));
- sjcd_transfer_timeout = 500;
- } else if (SJCD_STATUS_AVAILABLE(stat)) {
- sjcd_load_status();
- if (sjcd_status_valid
- && sjcd_media_is_changed) {
- sjcd_toc_uptodate = 0;
- sjcd_invalidate_buffers();
- }
- if (current_valid()) {
- if (sjcd_status_valid)
- sjcd_transfer_state =
- SJCD_S_READ;
- else
- sjcd_transfer_state =
- SJCD_S_START;
- } else
- sjcd_transfer_state = SJCD_S_IDLE;
- goto ReSwitch;
- }
-#if defined( SJCD_GATHER_STAT )
- else
- statistic.stopping_ticks++;
-#endif
- break;
- }
-
- default:
- printk("SJCD: poll: invalid state %d\n",
- sjcd_transfer_state);
- return;
- }
-
- if (--sjcd_transfer_timeout == 0) {
- printk("SJCD: timeout in state %d\n", sjcd_transfer_state);
- while (current_valid())
- end_request(CURRENT, 0);
- sjcd_send_cmd(SCMD_STOP);
- sjcd_transfer_state = SJCD_S_IDLE;
- goto ReSwitch;
- }
-
- /*
- * Get back in some time. 1 should be replaced with count variable to
- * avoid unnecessary testings.
- */
- SJCD_SET_TIMER(sjcd_poll, 1);
-}
-
-static void do_sjcd_request(request_queue_t * q)
-{
-#if defined( SJCD_TRACE )
- printk("SJCD: do_sjcd_request(%ld+%ld)\n",
- CURRENT->sector, CURRENT->nr_sectors);
-#endif
- sjcd_transfer_is_active = 1;
- while (current_valid()) {
- sjcd_transfer();
- if (CURRENT->nr_sectors == 0)
- end_request(CURRENT, 1);
- else {
- sjcd_buf_out = -1; /* Want to read a block not in buffer */
- if (sjcd_transfer_state == SJCD_S_IDLE) {
- if (!sjcd_toc_uptodate) {
- if (sjcd_update_toc() < 0) {
- printk
- ("SJCD: transfer: discard\n");
- while (current_valid())
- end_request(CURRENT, 0);
- break;
- }
- }
- sjcd_transfer_state = SJCD_S_START;
- SJCD_SET_TIMER(sjcd_poll, HZ / 100);
- }
- break;
- }
- }
- sjcd_transfer_is_active = 0;
-#if defined( SJCD_TRACE )
- printk
- ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n",
- sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
- sjcd_buf_bn[sjcd_buf_in]);
- printk("do_sjcd_request ends\n");
-#endif
-}
-
-/*
- * Open the device special file. Check disk is in.
- */
-static int sjcd_open(struct inode *ip, struct file *fp)
-{
- /*
- * Check the presence of device.
- */
- if (!sjcd_present)
- return (-ENXIO);
-
- /*
- * Only read operations are allowed. Really? (:-)
- */
- if (fp->f_mode & 2)
- return (-EROFS);
-
- if (sjcd_open_count == 0) {
- int s, sjcd_open_tries;
-/* We don't know that, do we? */
-/*
- sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
-*/
- sjcd_mode = 0;
- sjcd_door_was_open = 0;
- sjcd_transfer_state = SJCD_S_IDLE;
- sjcd_invalidate_buffers();
- sjcd_status_valid = 0;
-
- /*
- * Strict status checking.
- */
- for (sjcd_open_tries = 4; --sjcd_open_tries;) {
- if (!sjcd_status_valid)
- sjcd_get_status();
- if (!sjcd_status_valid) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: open: timed out when check status.\n");
-#endif
- goto err_out;
- } else if (!sjcd_media_is_available) {
-#if defined( SJCD_DIAGNOSTIC )
- printk("SJCD: open: no disk in drive\n");
-#endif
- if (!sjcd_door_closed) {
- sjcd_door_was_open = 1;
-#if defined( SJCD_TRACE )
- printk
- ("SJCD: open: close the tray\n");
-#endif
- s = sjcd_tray_close();
- if (s < 0 || !sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: open: tray close attempt failed\n");
-#endif
- goto err_out;
- }
- continue;
- } else
- goto err_out;
- }
- break;
- }
- s = sjcd_tray_lock();
- if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk("SJCD: open: tray lock attempt failed\n");
-#endif
- goto err_out;
- }
-#if defined( SJCD_TRACE )
- printk("SJCD: open: done\n");
-#endif
- }
-
- ++sjcd_open_count;
- return (0);
-
- err_out:
- return (-EIO);
-}
-
-/*
- * On close, we flush all sjcd blocks from the buffer cache.
- */
-static int sjcd_release(struct inode *inode, struct file *file)
-{
- int s;
-
-#if defined( SJCD_TRACE )
- printk("SJCD: release\n");
-#endif
- if (--sjcd_open_count == 0) {
- sjcd_invalidate_buffers();
- s = sjcd_tray_unlock();
- if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: release: tray unlock attempt failed.\n");
-#endif
- }
- if (sjcd_door_was_open) {
- s = sjcd_tray_open();
- if (s < 0 || !sjcd_status_valid
- || sjcd_command_failed) {
-#if defined( SJCD_DIAGNOSTIC )
- printk
- ("SJCD: release: tray unload attempt failed.\n");
-#endif
- }
- }
- }
- return 0;
-}
-
-/*
- * A list of file operations allowed for this cdrom.
- */
-static struct block_device_operations sjcd_fops = {
- .owner = THIS_MODULE,
- .open = sjcd_open,
- .release = sjcd_release,
- .ioctl = sjcd_ioctl,
- .media_changed = sjcd_disk_change,
-};
-
-/*
- * Following stuff is intended for initialization of the cdrom. It
- * first looks for presence of device. If the device is present, it
- * will be reset. Then read the version of the drive and load status.
- * The version is two BCD-coded bytes.
- */
-static struct {
- unsigned char major, minor;
-} sjcd_version;
-
-static struct gendisk *sjcd_disk;
-
-/*
- * Test for presence of drive and initialize it. Called at boot time.
- * Probe cdrom, find out version and status.
- */
-static int __init sjcd_init(void)
-{
- int i;
-
- printk(KERN_INFO
- "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n",
- SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);
-
-#if defined( SJCD_TRACE )
- printk("SJCD: sjcd=0x%x: ", sjcd_base);
-#endif
-
- if (register_blkdev(MAJOR_NR, "sjcd"))
- return -EIO;
-
- sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock);
- if (!sjcd_queue)
- goto out0;
-
- blk_queue_hardsect_size(sjcd_queue, 2048);
-
- sjcd_disk = alloc_disk(1);
- if (!sjcd_disk) {
- printk(KERN_ERR "SJCD: can't allocate disk");
- goto out1;
- }
- sjcd_disk->major = MAJOR_NR,
- sjcd_disk->first_minor = 0,
- sjcd_disk->fops = &sjcd_fops,
- sprintf(sjcd_disk->disk_name, "sjcd");
-
- if (!request_region(sjcd_base, 4,"sjcd")) {
- printk
- ("SJCD: Init failed, I/O port (%X) is already in use\n",
- sjcd_base);
- goto out2;
- }
-
- /*
- * Check for card. Since we are booting now, we can't use standard
- * wait algorithm.
- */
- printk(KERN_INFO "SJCD: Resetting: ");
- sjcd_send_cmd(SCMD_RESET);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies; time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" reset failed, no drive found.\n");
- goto out3;
- } else
- printk("\n");
-
- /*
- * Get and print out cdrom version.
- */
- printk(KERN_INFO "SJCD: Getting version: ");
- sjcd_send_cmd(SCMD_GET_VERSION);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies; time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" get version failed, no drive found.\n");
- goto out3;
- }
-
- if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
- printk(" %1x.%02x\n", (int) sjcd_version.major,
- (int) sjcd_version.minor);
- } else {
- printk(" read version failed, no drive found.\n");
- goto out3;
- }
-
- /*
- * Check and print out the tray state. (if it is needed?).
- */
- if (!sjcd_status_valid) {
- printk(KERN_INFO "SJCD: Getting status: ");
- sjcd_send_cmd(SCMD_GET_STATUS);
- for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
- unsigned long timer;
-
- /*
- * Wait 10ms approx.
- */
- for (timer = jiffies;
- time_before_eq(jiffies, timer););
- if ((i % 100) == 0)
- printk(".");
- (void) sjcd_check_status();
- }
- if (i == 0 || sjcd_command_failed) {
- printk(" get status failed, no drive found.\n");
- goto out3;
- } else
- printk("\n");
- }
-
- printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
- sjcd_disk->queue = sjcd_queue;
- add_disk(sjcd_disk);
-
- sjcd_present++;
- return (0);
-out3:
- release_region(sjcd_base, 4);
-out2:
- put_disk(sjcd_disk);
-out1:
- blk_cleanup_queue(sjcd_queue);
-out0:
- if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
- printk("SJCD: cannot unregister device.\n");
- return (-EIO);
-}
-
-static void __exit sjcd_exit(void)
-{
- del_gendisk(sjcd_disk);
- put_disk(sjcd_disk);
- release_region(sjcd_base, 4);
- blk_cleanup_queue(sjcd_queue);
- if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
- printk("SJCD: cannot unregister device.\n");
- printk(KERN_INFO "SJCD: module: removed.\n");
-}
-
-module_init(sjcd_init);
-module_exit(sjcd_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR);
diff --git a/drivers/cdrom/sjcd.h b/drivers/cdrom/sjcd.h
deleted file mode 100644
index 0aa5e714659..00000000000
--- a/drivers/cdrom/sjcd.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Definitions for a Sanyo CD-ROM interface.
- *
- * Copyright (C) 1995 Vadim V. Model
- * model@cecmow.enet.dec.com
- * vadim@rbrf.msk.su
- * vadim@ipsun.ras.ru
- * Eric van der Maarel
- * H.T.M.v.d.Maarel@marin.nl
- *
- * This information is based on mcd.c from M. Harriss and sjcd102.lst from
- * E. Moenkeberg.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __SJCD_H__
-#define __SJCD_H__
-
-/*
- * Change this to set the I/O port address as default. More flexibility
- * come with setup implementation.
- */
-#define SJCD_BASE_ADDR 0x340
-
-/*
- * Change this to set the irq as default. Really SANYO do not use interrupts
- * at all.
- */
-#define SJCD_INTR_NR 0
-
-/*
- * Change this to set the dma as default value. really SANYO does not use
- * direct memory access at all.
- */
-#define SJCD_DMA_NR 0
-
-/*
- * Macros which allow us to find out the status of the drive.
- */
-#define SJCD_STATUS_AVAILABLE( x ) (((x)&0x02)==0)
-#define SJCD_DATA_AVAILABLE( x ) (((x)&0x01)==0)
-
-/*
- * Port access macro. Three ports are available: S-data port (command port),
- * status port (read only) and D-data port (read only).
- */
-#define SJCDPORT( x ) ( sjcd_base + ( x ) )
-#define SJCD_STATUS_PORT SJCDPORT( 1 )
-#define SJCD_S_DATA_PORT SJCDPORT( 0 )
-#define SJCD_COMMAND_PORT SJCDPORT( 0 )
-#define SJCD_D_DATA_PORT SJCDPORT( 2 )
-
-/*
- * Drive info bits. Drive info available as first (mandatory) byte of
- * command completion status.
- */
-#define SST_NOT_READY 0x10 /* no disk in the drive (???) */
-#define SST_MEDIA_CHANGED 0x20 /* disk is changed */
-#define SST_DOOR_OPENED 0x40 /* door is open */
-
-/* commands */
-
-#define SCMD_EJECT_TRAY 0xD0 /* eject tray if not locked */
-#define SCMD_LOCK_TRAY 0xD2 /* lock tray when in */
-#define SCMD_UNLOCK_TRAY 0xD4 /* unlock tray when in */
-#define SCMD_CLOSE_TRAY 0xD6 /* load tray in */
-
-#define SCMD_RESET 0xFA /* soft reset */
-#define SCMD_GET_STATUS 0x80
-#define SCMD_GET_VERSION 0xCC
-
-#define SCMD_DATA_READ 0xA0 /* are the same, depend on mode&args */
-#define SCMD_SEEK 0xA0
-#define SCMD_PLAY 0xA0
-
-#define SCMD_GET_QINFO 0xA8
-
-#define SCMD_SET_MODE 0xC4
-#define SCMD_MODE_PLAY 0xE0
-#define SCMD_MODE_COOKED (0xF8 & ~0x20)
-#define SCMD_MODE_RAW 0xF9
-#define SCMD_MODE_x20_BIT 0x20 /* What is it for ? */
-
-#define SCMD_SET_VOLUME 0xAE
-#define SCMD_PAUSE 0xE0
-#define SCMD_STOP 0xE0
-
-#define SCMD_GET_DISK_INFO 0xAA
-
-/*
- * Some standard arguments for SCMD_GET_DISK_INFO.
- */
-#define SCMD_GET_1_TRACK 0xA0 /* get the first track information */
-#define SCMD_GET_L_TRACK 0xA1 /* get the last track information */
-#define SCMD_GET_D_SIZE 0xA2 /* get the whole disk information */
-
-/*
- * Borrowed from hd.c. Allows to optimize multiple port read commands.
- */
-#define S_READ_DATA( port, buf, nr ) insb( port, buf, nr )
-
-/*
- * We assume that there are no audio disks with TOC length more than this
- * number (I personally have never seen disks with more than 20 fragments).
- */
-#define SJCD_MAX_TRACKS 100
-
-struct msf {
- unsigned char min;
- unsigned char sec;
- unsigned char frame;
-};
-
-struct sjcd_hw_disk_info {
- unsigned char track_control;
- unsigned char track_no;
- unsigned char x, y, z;
- union {
- unsigned char track_no;
- struct msf track_msf;
- } un;
-};
-
-struct sjcd_hw_qinfo {
- unsigned char track_control;
- unsigned char track_no;
- unsigned char x;
- struct msf rel;
- struct msf abs;
-};
-
-struct sjcd_play_msf {
- struct msf start;
- struct msf end;
-};
-
-struct sjcd_disk_info {
- unsigned char first;
- unsigned char last;
- struct msf disk_length;
- struct msf first_track;
-};
-
-struct sjcd_toc {
- unsigned char ctrl_addr;
- unsigned char track;
- unsigned char point_index;
- struct msf track_time;
- struct msf disk_time;
-};
-
-#if defined( SJCD_GATHER_STAT )
-
-struct sjcd_stat {
- int ticks;
- int tticks[ 8 ];
- int idle_ticks;
- int start_ticks;
- int mode_ticks;
- int read_ticks;
- int data_ticks;
- int stop_ticks;
- int stopping_ticks;
-};
-
-#endif
-
-#endif
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
deleted file mode 100644
index f77ada933ea..00000000000
--- a/drivers/cdrom/sonycd535.c
+++ /dev/null
@@ -1,1689 +0,0 @@
-/*
- * Sony CDU-535 interface device driver
- *
- * This is a modified version of the CDU-31A device driver (see below).
- * Changes were made using documentation for the CDU-531 (which Sony
- * assures me is very similar to the 535) and partial disassembly of the
- * DOS driver. I used Minyard's driver and replaced the CDU-31A
- * commands with the CDU-531 commands. This was complicated by a different
- * interface protocol with the drive. The driver is still polled.
- *
- * Data transfer rate is about 110 Kb/sec, theoretical maximum is 150 Kb/sec.
- * I tried polling without the sony_sleep during the data transfers but
- * it did not speed things up any.
- *
- * 1993-05-23 (rgj) changed the major number to 21 to get rid of conflict
- * with CDU-31A driver. This is the also the number from the Linux
- * Device Driver Registry for the Sony Drive. Hope nobody else is using it.
- *
- * 1993-08-29 (rgj) remove the configuring of the interface board address
- * from the top level configuration, you have to modify it in this file.
- *
- * 1995-01-26 Made module-capable (Joel Katz <Stimpson@Panix.COM>)
- *
- * 1995-05-20
- * Modified to support CDU-510/515 series
- * (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- * Fixed to report verify_area() failures
- * (Heiko Eissfeldt <heiko@colossus.escape.de>)
- *
- * 1995-06-01
- * More changes to support CDU-510/515 series
- * (Claudio Porfiri<C.Porfiri@nisms.tei.ericsson.se>)
- *
- * November 1999 -- Make kernel-parameter implementation work with 2.3.x
- * Removed init_module & cleanup_module in favor of
- * module_init & module_exit.
- * Torben Mathiasen <tmm@image.dk>
- *
- * September 2003 - Fix SMP support by removing cli/sti calls.
- * Using spinlocks with a wait_queue instead.
- * Felipe Damasio <felipewd@terra.com.br>
- *
- * Things to do:
- * - handle errors and status better, put everything into a single word
- * - use interrupts (code mostly there, but a big hole still missing)
- * - handle multi-session CDs?
- * - use DMA?
- *
- * Known Bugs:
- * -
- *
- * Ken Pizzini (ken@halcyon.com)
- *
- * Original by:
- * Ron Jeppesen (ronj.an@site007.saic.com)
- *
- *
- *------------------------------------------------------------------------
- * Sony CDROM interface device driver.
- *
- * Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to Ken above)
- *
- * Colossians 3:17
- *
- * The Sony interface device driver handles Sony interface CDROM
- * drives and provides a complete block-level interface as well as an
- * ioctl() interface compatible with the Sun (as specified in
- * include/linux/cdrom.h). With this interface, CDROMs can be
- * accessed and standard audio CDs can be played back normally.
- *
- * This interface is (unfortunately) a polled interface. This is
- * because most Sony interfaces are set up with DMA and interrupts
- * disables. Some (like mine) do not even have the capability to
- * handle interrupts or DMA. For this reason you will see a bit of
- * the following:
- *
- * snap = jiffies;
- * while (jiffies-snap < SONY_JIFFIES_TIMEOUT)
- * {
- * if (some_condition())
- * break;
- * sony_sleep();
- * }
- * if (some_condition not met)
- * {
- * return an_error;
- * }
- *
- * This ugly hack waits for something to happen, sleeping a little
- * between every try. (The conditional is written so that jiffies
- * wrap-around is handled properly.)
- *
- * One thing about these drives: They talk in MSF (Minute Second Frame) format.
- * There are 75 frames a second, 60 seconds a minute, and up to 75 minutes on a
- * disk. The funny thing is that these are sent to the drive in BCD, but the
- * interface wants to see them in decimal. A lot of conversion goes on.
- *
- * Copyright (C) 1993 Corey Minyard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-
-# include <linux/module.h>
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/genhd.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#define REALLY_SLOW_IO
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/cdrom.h>
-
-#define MAJOR_NR CDU535_CDROM_MAJOR
-#include <linux/blkdev.h>
-
-#define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */
-#include "sonycd535.h"
-
-/*
- * this is the base address of the interface card for the Sony CDU-535
- * CDROM drive. If your jumpers are set for an address other than
- * this one (the default), change the following line to the
- * proper address.
- */
-#ifndef CDU535_ADDRESS
-# define CDU535_ADDRESS 0x340
-#endif
-#ifndef CDU535_INTERRUPT
-# define CDU535_INTERRUPT 0
-#endif
-#ifndef CDU535_HANDLE
-# define CDU535_HANDLE "cdu535"
-#endif
-#ifndef CDU535_MESSAGE_NAME
-# define CDU535_MESSAGE_NAME "Sony CDU-535"
-#endif
-
-#define CDU535_BLOCK_SIZE 2048
-
-#ifndef MAX_SPINUP_RETRY
-# define MAX_SPINUP_RETRY 3 /* 1 is sufficient for most drives... */
-#endif
-#ifndef RETRY_FOR_BAD_STATUS
-# define RETRY_FOR_BAD_STATUS 100 /* in 10th of second */
-#endif
-
-#ifndef DEBUG
-# define DEBUG 1
-#endif
-
-/*
- * SONY535_BUFFER_SIZE determines the size of internal buffer used
- * by the drive. It must be at least 2K and the larger the buffer
- * the better the transfer rate. It does however take system memory.
- * On my system I get the following transfer rates using dd to read
- * 10 Mb off /dev/cdrom.
- *
- * 8K buffer 43 Kb/sec
- * 16K buffer 66 Kb/sec
- * 32K buffer 91 Kb/sec
- * 64K buffer 111 Kb/sec
- * 128K buffer 123 Kb/sec
- * 512K buffer 123 Kb/sec
- */
-#define SONY535_BUFFER_SIZE (64*1024)
-
-/*
- * if LOCK_DOORS is defined then the eject button is disabled while
- * the device is open.
- */
-#ifndef NO_LOCK_DOORS
-# define LOCK_DOORS
-#endif
-
-static int read_subcode(void);
-static void sony_get_toc(void);
-static int cdu_open(struct inode *inode, struct file *filp);
-static inline unsigned int int_to_bcd(unsigned int val);
-static unsigned int bcd_to_int(unsigned int bcd);
-static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
- Byte * response, int n_response, int ignoreStatusBit7);
-
-/* The base I/O address of the Sony Interface. This is a variable (not a
- #define) so it can be easily changed via some future ioctl() */
-static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
-module_param(sony535_cd_base_io, int, 0);
-
-/*
- * The following are I/O addresses of the various registers for the drive. The
- * comment for the base address also applies here.
- */
-static unsigned short select_unit_reg;
-static unsigned short result_reg;
-static unsigned short command_reg;
-static unsigned short read_status_reg;
-static unsigned short data_reg;
-
-static DEFINE_SPINLOCK(sonycd535_lock); /* queue lock */
-static struct request_queue *sonycd535_queue;
-
-static int initialized; /* Has the drive been initialized? */
-static int sony_disc_changed = 1; /* Has the disk been changed
- since the last check? */
-static int sony_toc_read; /* Has the table of contents been
- read? */
-static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead
- buffer. */
-static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of
- the read-ahead buffer. */
-static unsigned int sony_usage; /* How many processes have the
- drive open. */
-
-static int sony_first_block = -1; /* First OS block (512 byte) in
- the read-ahead buffer */
-static int sony_last_block = -1; /* Last OS block (512 byte) in
- the read-ahead buffer */
-
-static struct s535_sony_toc *sony_toc; /* Points to the table of
- contents. */
-
-static struct s535_sony_subcode *last_sony_subcode; /* Points to the last
- subcode address read */
-static Byte **sony_buffer; /* Points to the pointers
- to the sector buffers */
-
-static int sony_inuse; /* is the drive in use? Only one
- open at a time allowed */
-
-/*
- * The audio status uses the values from read subchannel data as specified
- * in include/linux/cdrom.h.
- */
-static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
-
-/*
- * The following are a hack for pausing and resuming audio play. The drive
- * does not work as I would expect it, if you stop it then start it again,
- * the drive seeks back to the beginning and starts over. This holds the
- * position during a pause so a resume can restart it. It uses the
- * audio status variable above to tell if it is paused.
- * I just kept the CDU-31A driver behavior rather than using the PAUSE
- * command on the CDU-535.
- */
-static Byte cur_pos_msf[3];
-static Byte final_pos_msf[3];
-
-/* What IRQ is the drive using? 0 if none. */
-static int sony535_irq_used = CDU535_INTERRUPT;
-
-/* The interrupt handler will wake this queue up when it gets an interrupt. */
-static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
-
-
-/*
- * This routine returns 1 if the disk has been changed since the last
- * check or 0 if it hasn't. Setting flag to 0 resets the changed flag.
- */
-static int
-cdu535_check_media_change(struct gendisk *disk)
-{
- /* if driver is not initialized, always return 0 */
- int retval = initialized ? sony_disc_changed : 0;
- sony_disc_changed = 0;
- return retval;
-}
-
-static inline void
-enable_interrupts(void)
-{
-#ifdef USE_IRQ
- /*
- * This code was taken from cdu31a.c; it will not
- * directly work for the cdu535 as written...
- */
- curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static inline void
-disable_interrupts(void)
-{
-#ifdef USE_IRQ
- /*
- * This code was taken from cdu31a.c; it will not
- * directly work for the cdu535 as written...
- */
- curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
- | SONY_RES_RDY_INT_EN_BIT
- | SONY_DATA_RDY_INT_EN_BIT);
- outb(curr_control_reg, sony_cd_control_reg);
-#endif
-}
-
-static irqreturn_t
-cdu535_interrupt(int irq, void *dev_id)
-{
- disable_interrupts();
- if (waitqueue_active(&cdu535_irq_wait)) {
- wake_up(&cdu535_irq_wait);
- return IRQ_HANDLED;
- }
- printk(CDU535_MESSAGE_NAME
- ": Got an interrupt but nothing was waiting\n");
- return IRQ_NONE;
-}
-
-
-/*
- * Wait a little while.
- */
-static inline void
-sony_sleep(void)
-{
- if (sony535_irq_used <= 0) { /* poll */
- yield();
- } else { /* Interrupt driven */
- DEFINE_WAIT(wait);
-
- spin_lock_irq(&sonycd535_lock);
- enable_interrupts();
- prepare_to_wait(&cdu535_irq_wait, &wait, TASK_INTERRUPTIBLE);
- spin_unlock_irq(&sonycd535_lock);
- schedule();
- finish_wait(&cdu535_irq_wait, &wait);
- }
-}
-
-/*------------------start of SONY CDU535 very specific ---------------------*/
-
-/****************************************************************************
- * void select_unit( int unit_no )
- *
- * Select the specified unit (0-3) so that subsequent commands reference it
- ****************************************************************************/
-static void
-select_unit(int unit_no)
-{
- unsigned int select_mask = ~(1 << unit_no);
- outb(select_mask, select_unit_reg);
-}
-
-/***************************************************************************
- * int read_result_reg( Byte *data_ptr )
- *
- * Read a result byte from the Sony CDU controller, store in location pointed
- * to by data_ptr. Return zero on success, TIME_OUT if we did not receive
- * data.
- ***************************************************************************/
-static int
-read_result_reg(Byte *data_ptr)
-{
- unsigned long snap;
- int read_status;
-
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- read_status = inb(read_status_reg);
- if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME
- ": read_result_reg(): readStatReg = 0x%x\n", read_status);
-#endif
- *data_ptr = inb(result_reg);
- return 0;
- } else {
- sony_sleep();
- }
- }
- printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
- return TIME_OUT;
-}
-
-/****************************************************************************
- * int read_exec_status( Byte status[2] )
- *
- * Read the execution status of the last command and put into status.
- * Handles reading second status word if available. Returns 0 on success,
- * TIME_OUT on failure.
- ****************************************************************************/
-static int
-read_exec_status(Byte status[2])
-{
- status[1] = 0;
- if (read_result_reg(&(status[0])) != 0)
- return TIME_OUT;
- if ((status[0] & 0x80) != 0) { /* byte two follows */
- if (read_result_reg(&(status[1])) != 0)
- return TIME_OUT;
- }
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
- status[0], status[1]);
-#endif
- return 0;
-}
-
-/****************************************************************************
- * int check_drive_status( void )
- *
- * Check the current drive status. Using this before executing a command
- * takes care of the problem of unsolicited drive status-2 messages.
- * Add a check of the audio status if we think the disk is playing.
- ****************************************************************************/
-static int
-check_drive_status(void)
-{
- Byte status, e_status[2];
- int CDD, ATN;
- Byte cmd;
-
- select_unit(0);
- if (sony_audio_status == CDROM_AUDIO_PLAY) { /* check status */
- outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
- if (read_result_reg(&status) == 0) {
- switch (status) {
- case 0x0:
- break; /* play in progress */
- case 0x1:
- break; /* paused */
- case 0x3: /* audio play completed */
- case 0x5: /* play not requested */
- sony_audio_status = CDROM_AUDIO_COMPLETED;
- read_subcode();
- break;
- case 0x4: /* error during play */
- sony_audio_status = CDROM_AUDIO_ERROR;
- break;
- }
- }
- }
- /* now check drive status */
- outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
- if (read_result_reg(&status) != 0)
- return TIME_OUT;
-
-#if DEBUG > 1
- printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
-#endif
-
- if (status == 0)
- return 0;
-
- ATN = status & 0xf;
- CDD = (status >> 4) & 0xf;
-
- switch (ATN) {
- case 0x0:
- break; /* go on to CDD stuff */
- case SONY535_ATN_BUSY:
- if (initialized)
- printk(CDU535_MESSAGE_NAME " error: drive busy\n");
- return CD_BUSY;
- case SONY535_ATN_EJECT_IN_PROGRESS:
- printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
- sony_audio_status = CDROM_AUDIO_INVALID;
- return CD_BUSY;
- case SONY535_ATN_RESET_OCCURRED:
- case SONY535_ATN_DISC_CHANGED:
- case SONY535_ATN_RESET_AND_DISC_CHANGED:
-#if DEBUG > 0
- printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
-#endif
- sony_disc_changed = 1;
- sony_toc_read = 0;
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- sony_first_block = -1;
- sony_last_block = -1;
- if (initialized) {
- cmd = SONY535_SPIN_UP;
- do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
- sony_get_toc();
- }
- return 0;
- default:
- printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
- return CD_BUSY;
- }
- switch (CDD) { /* the 531 docs are not helpful in decoding this */
- case 0x0: /* just use the values from the DOS driver */
- case 0x2:
- case 0xa:
- break; /* no error */
- case 0xc:
- printk(CDU535_MESSAGE_NAME
- ": check_drive_status(): CDD = 0xc! Not properly handled!\n");
- return CD_BUSY; /* ? */
- default:
- return CD_BUSY;
- }
- return 0;
-} /* check_drive_status() */
-
-/*****************************************************************************
- * int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
- * Byte *response, int n_response, int ignore_status_bit7 )
- *
- * Generic routine for executing commands. The command and its parameters
- * should be placed in the cmd[] array, number of bytes in the command is
- * stored in nCmd. The response from the command will be stored in the
- * response array. The number of bytes you expect back (excluding status)
- * should be passed in n_response. Finally, some
- * commands set bit 7 of the return status even when there is no second
- * status byte, on these commands set ignoreStatusBit7 TRUE.
- * If the command was sent and data received back, then we return 0,
- * else we return TIME_OUT. You still have to check the status yourself.
- * You should call check_drive_status() before calling this routine
- * so that you do not lose notifications of disk changes, etc.
- ****************************************************************************/
-static int
-do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
- Byte * response, int n_response, int ignore_status_bit7)
-{
- int i;
-
- /* write out the command */
- for (i = 0; i < n_cmd; i++)
- outb(cmd[i], command_reg);
-
- /* read back the status */
- if (read_result_reg(status) != 0)
- return TIME_OUT;
- if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
- /* get second status byte */
- if (read_result_reg(status + 1) != 0)
- return TIME_OUT;
- } else {
- status[1] = 0;
- }
-#if DEBUG > 2
- printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
- *cmd, status[0], status[1]);
-#endif
-
- /* do not know about when I should read set of data and when not to */
- if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
- return 0;
-
- /* else, read in rest of data */
- for (i = 0; 0 < n_response; n_response--, i++)
- if (read_result_reg(response + i) != 0)
- return TIME_OUT;
- return 0;
-} /* do_sony_cmd() */
-
-/**************************************************************************
- * int set_drive_mode( int mode, Byte status[2] )
- *
- * Set the drive mode to the specified value (mode=0 is audio, mode=e0
- * is mode-1 CDROM
- **************************************************************************/
-static int
-set_drive_mode(int mode, Byte status[2])
-{
- Byte cmd_buff[2];
- Byte ret_buff[1];
-
- cmd_buff[0] = SONY535_SET_DRIVE_MODE;
- cmd_buff[1] = mode;
- return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
-}
-
-/***************************************************************************
- * int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
- * Byte *data_buff, int buff_size )
- *
- * Read n_blocks of data from the CDROM starting at position params[0:2],
- * number of blocks in stored in params[3:5] -- both these are already
- * int bcd format.
- * Transfer the data into the buffer pointed at by data_buff. buff_size
- * gives the number of bytes available in the buffer.
- * The routine returns number of bytes read in if successful, otherwise
- * it returns one of the standard error returns.
- ***************************************************************************/
-static int
-seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
- Byte **buff, int buf_size)
-{
- Byte cmd_buff[7];
- int i;
- int read_status;
- unsigned long snap;
- Byte *data_buff;
- int sector_count = 0;
-
- if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
- return NO_ROOM;
-
- set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
-
- /* send command to read the data */
- cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
- for (i = 0; i < 6; i++)
- cmd_buff[i + 1] = params[i];
- for (i = 0; i < 7; i++)
- outb(cmd_buff[i], command_reg);
-
- /* read back the data one block at a time */
- while (0 < n_blocks--) {
- /* wait for data to be ready */
- int data_valid = 0;
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- read_status = inb(read_status_reg);
- if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
- read_exec_status(status);
- return BAD_STATUS;
- }
- if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
- /* data is ready, read it */
- data_buff = buff[sector_count++];
- for (i = 0; i < CDU535_BLOCK_SIZE; i++)
- *data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */
- data_valid = 1;
- break; /* exit the timeout loop */
- }
- sony_sleep(); /* data not ready, sleep a while */
- }
- if (!data_valid)
- return TIME_OUT; /* if we reach this stage */
- }
-
- /* read all the data, now read the status */
- if ((i = read_exec_status(status)) != 0)
- return i;
- return CDU535_BLOCK_SIZE * sector_count;
-} /* seek_and_read_N_blocks() */
-
-/****************************************************************************
- * int request_toc_data( Byte status[2], struct s535_sony_toc *toc )
- *
- * Read in the table of contents data. Converts all the bcd data
- * into integers in the toc structure.
- ****************************************************************************/
-static int
-request_toc_data(Byte status[2], struct s535_sony_toc *toc)
-{
- int to_status;
- int i, j, n_tracks, track_no;
- int first_track_num, last_track_num;
- Byte cmd_no = 0xb2;
- Byte track_address_buffer[5];
-
- /* read the fixed portion of the table of contents */
- if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
- return to_status;
-
- /* convert the data into integers so we can use them */
- first_track_num = bcd_to_int(toc->first_track_num);
- last_track_num = bcd_to_int(toc->last_track_num);
- n_tracks = last_track_num - first_track_num + 1;
-
- /* read each of the track address descriptors */
- for (i = 0; i < n_tracks; i++) {
- /* read the descriptor into a temporary buffer */
- for (j = 0; j < 5; j++) {
- if (read_result_reg(track_address_buffer + j) != 0)
- return TIME_OUT;
- if (j == 1) /* need to convert from bcd */
- track_no = bcd_to_int(track_address_buffer[j]);
- }
- /* copy the descriptor to proper location - sonycd.c just fills */
- memcpy(toc->tracks + i, track_address_buffer, 5);
- }
- return 0;
-} /* request_toc_data() */
-
-/***************************************************************************
- * int spin_up_drive( Byte status[2] )
- *
- * Spin up the drive (unless it is already spinning).
- ***************************************************************************/
-static int
-spin_up_drive(Byte status[2])
-{
- Byte cmd;
-
- /* first see if the drive is already spinning */
- cmd = SONY535_REQUEST_DRIVE_STATUS_1;
- if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
- return TIME_OUT;
- if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
- return 0; /* it's already spinning */
-
- /* otherwise, give the spin-up command */
- cmd = SONY535_SPIN_UP;
- return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
-}
-
-/*--------------------end of SONY CDU535 very specific ---------------------*/
-
-/* Convert from an integer 0-99 to BCD */
-static inline unsigned int
-int_to_bcd(unsigned int val)
-{
- int retval;
-
- retval = (val / 10) << 4;
- retval = retval | val % 10;
- return retval;
-}
-
-
-/* Convert from BCD to an integer from 0-99 */
-static unsigned int
-bcd_to_int(unsigned int bcd)
-{
- return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
-}
-
-
-/*
- * Convert a logical sector value (like the OS would want to use for
- * a block device) to an MSF format.
- */
-static void
-log_to_msf(unsigned int log, Byte *msf)
-{
- log = log + LOG_START_OFFSET;
- msf[0] = int_to_bcd(log / 4500);
- log = log % 4500;
- msf[1] = int_to_bcd(log / 75);
- msf[2] = int_to_bcd(log % 75);
-}
-
-
-/*
- * Convert an MSF format to a logical sector.
- */
-static unsigned int
-msf_to_log(Byte *msf)
-{
- unsigned int log;
-
-
- log = bcd_to_int(msf[2]);
- log += bcd_to_int(msf[1]) * 75;
- log += bcd_to_int(msf[0]) * 4500;
- log = log - LOG_START_OFFSET;
-
- return log;
-}
-
-
-/*
- * Take in integer size value and put it into a buffer like
- * the drive would want to see a number-of-sector value.
- */
-static void
-size_to_buf(unsigned int size, Byte *buf)
-{
- buf[0] = size / 65536;
- size = size % 65536;
- buf[1] = size / 256;
- buf[2] = size % 256;
-}
-
-
-/*
- * The OS calls this to perform a read or write operation to the drive.
- * Write obviously fail. Reads to a read ahead of sony_buffer_size
- * bytes to help speed operations. This especially helps since the OS
- * may use 1024 byte blocks and the drive uses 2048 byte blocks. Since most
- * data access on a CD is done sequentially, this saves a lot of operations.
- */
-static void
-do_cdu535_request(request_queue_t * q)
-{
- struct request *req;
- unsigned int read_size;
- int block;
- int nsect;
- int copyoff;
- int spin_up_retry;
- Byte params[10];
- Byte status[2];
- Byte cmd[2];
-
- while (1) {
- req = elv_next_request(q);
- if (!req)
- return;
-
- block = req->sector;
- nsect = req->nr_sectors;
- if (!blk_fs_request(req)) {
- end_request(req, 0);
- continue;
- }
- if (rq_data_dir(req) == WRITE) {
- end_request(req, 0);
- continue;
- }
- /*
- * If the block address is invalid or the request goes beyond
- * the end of the media, return an error.
- */
- if (sony_toc->lead_out_start_lba <= (block/4)) {
- end_request(req, 0);
- return;
- }
- if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
- end_request(req, 0);
- return;
- }
- while (0 < nsect) {
- /*
- * If the requested sector is not currently in
- * the read-ahead buffer, it must be read in.
- */
- if ((block < sony_first_block) || (sony_last_block < block)) {
- sony_first_block = (block / 4) * 4;
- log_to_msf(block / 4, params);
-
- /*
- * If the full read-ahead would go beyond the end of the media, trim
- * it back to read just till the end of the media.
- */
- if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
- sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
- read_size = sony_toc->lead_out_start_lba - (block / 4);
- } else {
- sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
- read_size = sony_buffer_sectors;
- }
- size_to_buf(read_size, &params[3]);
-
- /*
- * Read the data. If the drive was not spinning,
- * spin it up and try some more.
- */
- for (spin_up_retry=0 ;; ++spin_up_retry) {
- /* This loop has been modified to support the Sony
- * CDU-510/515 series, thanks to Claudio Porfiri
- * <C.Porfiri@nisms.tei.ericsson.se>.
- */
- /*
- * This part is to deal with very slow hardware. We
- * try at most MAX_SPINUP_RETRY times to read the same
- * block. A check for seek_and_read_N_blocks' result is
- * performed; if the result is wrong, the CDROM's engine
- * is restarted and the operation is tried again.
- */
- /*
- * 1995-06-01: The system got problems when downloading
- * from Slackware CDROM, the problem seems to be:
- * seek_and_read_N_blocks returns BAD_STATUS and we
- * should wait for a while before retrying, so a new
- * part was added to discriminate the return value from
- * seek_and_read_N_blocks for the various cases.
- */
- int readStatus = seek_and_read_N_blocks(params, read_size,
- status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
- if (0 <= readStatus) /* Good data; common case, placed first */
- break;
- if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
- /* give up */
- if (readStatus == NO_ROOM)
- printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
- else
- printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
- status[0]);
- sony_first_block = -1;
- sony_last_block = -1;
- end_request(req, 0);
- return;
- }
- if (readStatus == BAD_STATUS) {
- /* Sleep for a while, then retry */
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_irq(&sonycd535_lock);
- schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10);
- spin_lock_irq(&sonycd535_lock);
- }
-#if DEBUG > 0
- printk(CDU535_MESSAGE_NAME
- " debug: calling spin up when reading data!\n");
-#endif
- cmd[0] = SONY535_SPIN_UP;
- do_sony_cmd(cmd, 1, status, NULL, 0, 0);
- }
- }
- /*
- * The data is in memory now, copy it to the buffer and advance to the
- * next block to read.
- */
- copyoff = block - sony_first_block;
- memcpy(req->buffer,
- sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
-
- block += 1;
- nsect -= 1;
- req->buffer += 512;
- }
-
- end_request(req, 1);
- }
-}
-
-/*
- * Read the table of contents from the drive and set sony_toc_read if
- * successful.
- */
-static void
-sony_get_toc(void)
-{
- Byte status[2];
- if (!sony_toc_read) {
- /* do not call check_drive_status() from here since it can call this routine */
- if (request_toc_data(status, sony_toc) < 0)
- return;
- sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
- sony_toc_read = 1;
- }
-}
-
-
-/*
- * Search for a specific track in the table of contents. track is
- * passed in bcd format
- */
-static int
-find_track(int track)
-{
- int i;
- int num_tracks;
-
-
- num_tracks = bcd_to_int(sony_toc->last_track_num) -
- bcd_to_int(sony_toc->first_track_num) + 1;
- for (i = 0; i < num_tracks; i++) {
- if (sony_toc->tracks[i].track == track) {
- return i;
- }
- }
-
- return -1;
-}
-
-/*
- * Read the subcode and put it int last_sony_subcode for future use.
- */
-static int
-read_subcode(void)
-{
- Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
- Byte status[2];
- int dsc_status;
-
- if (check_drive_status() != 0)
- return -EIO;
-
- if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
- sizeof(struct s535_sony_subcode), 1)) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
- status[0], dsc_status);
- return -EIO;
- }
- return 0;
-}
-
-
-/*
- * Get the subchannel info like the CDROMSUBCHNL command wants to see it. If
- * the drive is playing, the subchannel needs to be read (since it would be
- * changing). If the drive is paused or completed, the subcode information has
- * already been stored, just use that. The ioctl call wants things in decimal
- * (not BCD), so all the conversions are done.
- */
-static int
-sony_get_subchnl_info(void __user *arg)
-{
- struct cdrom_subchnl schi;
-
- /* Get attention stuff */
- if (check_drive_status() != 0)
- return -EIO;
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
- if (copy_from_user(&schi, arg, sizeof schi))
- return -EFAULT;
-
- switch (sony_audio_status) {
- case CDROM_AUDIO_PLAY:
- if (read_subcode() < 0) {
- return -EIO;
- }
- break;
-
- case CDROM_AUDIO_PAUSED:
- case CDROM_AUDIO_COMPLETED:
- break;
-
- case CDROM_AUDIO_NO_STATUS:
- schi.cdsc_audiostatus = sony_audio_status;
- if (copy_to_user(arg, &schi, sizeof schi))
- return -EFAULT;
- return 0;
- break;
-
- case CDROM_AUDIO_INVALID:
- case CDROM_AUDIO_ERROR:
- default:
- return -EIO;
- }
-
- schi.cdsc_audiostatus = sony_audio_status;
- schi.cdsc_adr = last_sony_subcode->address;
- schi.cdsc_ctrl = last_sony_subcode->control;
- schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
- schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
- if (schi.cdsc_format == CDROM_MSF) {
- schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
- schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
- schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
-
- schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
- schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
- schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
- } else if (schi.cdsc_format == CDROM_LBA) {
- schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
- schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
- }
- return copy_to_user(arg, &schi, sizeof schi) ? -EFAULT : 0;
-}
-
-
-/*
- * The big ugly ioctl handler.
- */
-static int
-cdu_ioctl(struct inode *inode,
- struct file *file,
- unsigned int cmd,
- unsigned long arg)
-{
- Byte status[2];
- Byte cmd_buff[10], params[10];
- int i;
- int dsc_status;
- void __user *argp = (void __user *)arg;
-
- if (check_drive_status() != 0)
- return -EIO;
-
- switch (cmd) {
- case CDROMSTART: /* Spin up the drive */
- if (spin_up_drive(status) < 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- case CDROMSTOP: /* Spin down the drive */
- cmd_buff[0] = SONY535_HOLD;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
- /*
- * Spin the drive down, ignoring the error if the disk was
- * already not spinning.
- */
- sony_audio_status = CDROM_AUDIO_NO_STATUS;
- cmd_buff[0] = SONY535_SPIN_DOWN;
- dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
- ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- case CDROMPAUSE: /* Pause the drive */
- cmd_buff[0] = SONY535_HOLD; /* CDU-31 driver uses AUDIO_STOP, not pause */
- if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
- status[0]);
- return -EIO;
- }
- /* Get the current position and save it for resuming */
- if (read_subcode() < 0) {
- return -EIO;
- }
- cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
- cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
- cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
- sony_audio_status = CDROM_AUDIO_PAUSED;
- return 0;
- break;
-
- case CDROMRESUME: /* Start the drive after being paused */
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- if (sony_audio_status != CDROM_AUDIO_PAUSED) {
- return -EINVAL;
- }
- spin_up_drive(status);
-
- /* Start the drive at the saved position. */
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- cmd_buff[2] = cur_pos_msf[0];
- cmd_buff[3] = cur_pos_msf[1];
- cmd_buff[4] = cur_pos_msf[2];
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- cmd_buff[7] = final_pos_msf[0];
- cmd_buff[8] = final_pos_msf[1];
- cmd_buff[9] = final_pos_msf[2];
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
- status[0]);
- return -EIO;
- }
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- break;
-
- case CDROMPLAYMSF: /* Play starting at the given MSF address. */
- if (copy_from_user(params, argp, 6))
- return -EFAULT;
- spin_up_drive(status);
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- /* The parameters are given in int, must be converted */
- for (i = 0; i < 3; i++) {
- cmd_buff[2 + i] = int_to_bcd(params[i]);
- cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
- }
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- /* cmd_buff[2-4] are filled in for loop above */
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- /* cmd_buff[7-9] are filled in for loop above */
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
- status[0]);
- return -EIO;
- }
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = cmd_buff[7];
- final_pos_msf[1] = cmd_buff[8];
- final_pos_msf[2] = cmd_buff[9];
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- break;
-
- case CDROMREADTOCHDR: /* Read the table of contents header */
- {
- struct cdrom_tochdr __user *hdr = argp;
- struct cdrom_tochdr loc_hdr;
-
- sony_get_toc();
- if (!sony_toc_read)
- return -EIO;
- loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
- loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
- if (copy_to_user(hdr, &loc_hdr, sizeof *hdr))
- return -EFAULT;
- }
- return 0;
- break;
-
- case CDROMREADTOCENTRY: /* Read a given table of contents entry */
- {
- struct cdrom_tocentry __user *entry = argp;
- struct cdrom_tocentry loc_entry;
- int track_idx;
- Byte *msf_val = NULL;
-
- sony_get_toc();
- if (!sony_toc_read) {
- return -EIO;
- }
-
- if (copy_from_user(&loc_entry, entry, sizeof loc_entry))
- return -EFAULT;
-
- /* Lead out is handled separately since it is special. */
- if (loc_entry.cdte_track == CDROM_LEADOUT) {
- loc_entry.cdte_adr = 0 /*sony_toc->address2 */ ;
- loc_entry.cdte_ctrl = sony_toc->control2;
- msf_val = sony_toc->lead_out_start_msf;
- } else {
- track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
- if (track_idx < 0)
- return -EINVAL;
- loc_entry.cdte_adr = 0 /*sony_toc->tracks[track_idx].address */ ;
- loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
- msf_val = sony_toc->tracks[track_idx].track_start_msf;
- }
-
- /* Logical buffer address or MSF format requested? */
- if (loc_entry.cdte_format == CDROM_LBA) {
- loc_entry.cdte_addr.lba = msf_to_log(msf_val);
- } else if (loc_entry.cdte_format == CDROM_MSF) {
- loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
- loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
- loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
- }
- if (copy_to_user(entry, &loc_entry, sizeof *entry))
- return -EFAULT;
- }
- return 0;
- break;
-
- case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
- {
- struct cdrom_ti ti;
- int track_idx;
-
- sony_get_toc();
- if (!sony_toc_read)
- return -EIO;
-
- if (copy_from_user(&ti, argp, sizeof ti))
- return -EFAULT;
- if ((ti.cdti_trk0 < sony_toc->first_track_num)
- || (sony_toc->last_track_num < ti.cdti_trk0)
- || (ti.cdti_trk1 < ti.cdti_trk0)) {
- return -EINVAL;
- }
- track_idx = find_track(int_to_bcd(ti.cdti_trk0));
- if (track_idx < 0)
- return -EINVAL;
- params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
- params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
- params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
- /*
- * If we want to stop after the last track, use the lead-out
- * MSF to do that.
- */
- if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
- log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
- &(params[4]));
- } else {
- track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
- if (track_idx < 0)
- return -EINVAL;
- log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
- &(params[4]));
- }
- params[0] = 0x03;
-
- spin_up_drive(status);
-
- set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-
- /* Start the drive at the saved position. */
- cmd_buff[0] = SONY535_PLAY_AUDIO;
- cmd_buff[1] = 0; /* play back starting at this address */
- cmd_buff[2] = params[1];
- cmd_buff[3] = params[2];
- cmd_buff[4] = params[3];
- cmd_buff[5] = SONY535_PLAY_AUDIO;
- cmd_buff[6] = 2; /* set ending address */
- cmd_buff[7] = params[4];
- cmd_buff[8] = params[5];
- cmd_buff[9] = params[6];
- if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
- (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
- status[0]);
- printk("... Params: %x %x %x %x %x %x %x\n",
- params[0], params[1], params[2],
- params[3], params[4], params[5], params[6]);
- return -EIO;
- }
- /* Save the final position for pauses and resumes */
- final_pos_msf[0] = params[4];
- final_pos_msf[1] = params[5];
- final_pos_msf[2] = params[6];
- sony_audio_status = CDROM_AUDIO_PLAY;
- return 0;
- }
-
- case CDROMSUBCHNL: /* Get subchannel info */
- return sony_get_subchnl_info(argp);
-
- case CDROMVOLCTRL: /* Volume control. What volume does this change, anyway? */
- {
- struct cdrom_volctrl volctrl;
-
- if (copy_from_user(&volctrl, argp, sizeof volctrl))
- return -EFAULT;
- cmd_buff[0] = SONY535_SET_VOLUME;
- cmd_buff[1] = volctrl.channel0;
- cmd_buff[2] = volctrl.channel1;
- if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
- status[0]);
- return -EIO;
- }
- }
- return 0;
-
- case CDROMEJECT: /* Eject the drive */
- cmd_buff[0] = SONY535_STOP;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- cmd_buff[0] = SONY535_SPIN_DOWN;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-
- sony_audio_status = CDROM_AUDIO_INVALID;
- cmd_buff[0] = SONY535_EJECT_CADDY;
- if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
- status[0]);
- return -EIO;
- }
- return 0;
- break;
-
- default:
- return -EINVAL;
- }
-}
-
-
-/*
- * Open the drive for operations. Spin the drive up and read the table of
- * contents if these have not already been done.
- */
-static int
-cdu_open(struct inode *inode,
- struct file *filp)
-{
- Byte status[2], cmd_buff[2];
-
- if (sony_inuse)
- return -EBUSY;
- if (check_drive_status() != 0)
- return -EIO;
- sony_inuse = 1;
-
- if (spin_up_drive(status) != 0) {
- printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
- status[0]);
- sony_inuse = 0;
- return -EIO;
- }
- sony_get_toc();
- if (!sony_toc_read) {
- cmd_buff[0] = SONY535_SPIN_DOWN;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
- sony_inuse = 0;
- return -EIO;
- }
- check_disk_change(inode->i_bdev);
- sony_usage++;
-
-#ifdef LOCK_DOORS
- /* disable the eject button while mounted */
- cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
- do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
-#endif
-
- return 0;
-}
-
-
-/*
- * Close the drive. Spin it down if no task is using it. The spin
- * down will fail if playing audio, so audio play is OK.
- */
-static int
-cdu_release(struct inode *inode,
- struct file *filp)
-{
- Byte status[2], cmd_no;
-
- sony_inuse = 0;
-
- if (0 < sony_usage) {
- sony_usage--;
- }
- if (sony_usage == 0) {
- check_drive_status();
-
- if (sony_audio_status != CDROM_AUDIO_PLAY) {
- cmd_no = SONY535_SPIN_DOWN;
- do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
- }
-#ifdef LOCK_DOORS
- /* enable the eject button after umount */
- cmd_no = SONY535_ENABLE_EJECT_BUTTON;
- do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
-#endif
- }
- return 0;
-}
-
-static struct block_device_operations cdu_fops =
-{
- .owner = THIS_MODULE,
- .open = cdu_open,
- .release = cdu_release,
- .ioctl = cdu_ioctl,
- .media_changed = cdu535_check_media_change,
-};
-
-static struct gendisk *cdu_disk;
-
-/*
- * Initialize the driver.
- */
-static int __init sony535_init(void)
-{
- struct s535_sony_drive_config drive_config;
- Byte cmd_buff[3];
- Byte ret_buff[2];
- Byte status[2];
- unsigned long snap;
- int got_result = 0;
- int tmp_irq;
- int i;
- int err;
-
- /* Setting the base I/O address to 0 will disable it. */
- if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
- return 0;
-
- /* Set up all the register locations */
- result_reg = sony535_cd_base_io;
- command_reg = sony535_cd_base_io;
- data_reg = sony535_cd_base_io + 1;
- read_status_reg = sony535_cd_base_io + 2;
- select_unit_reg = sony535_cd_base_io + 3;
-
-#ifndef USE_IRQ
- sony535_irq_used = 0; /* polling only until this is ready... */
-#endif
- /* we need to poll until things get initialized */
- tmp_irq = sony535_irq_used;
- sony535_irq_used = 0;
-
-#if DEBUG > 0
- printk(KERN_INFO CDU535_MESSAGE_NAME ": probing base address %03X\n",
- sony535_cd_base_io);
-#endif
- /* look for the CD-ROM, follows the procedure in the DOS driver */
- inb(select_unit_reg);
- /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
- schedule_timeout_interruptible((HZ+17)*40/18);
- inb(result_reg);
-
- outb(0, read_status_reg); /* does a reset? */
- snap = jiffies;
- while (jiffies-snap < SONY_JIFFIES_TIMEOUT) {
- select_unit(0);
- if (inb(result_reg) != 0xff) {
- got_result = 1;
- break;
- }
- sony_sleep();
- }
-
- if (!got_result || check_drive_status() == TIME_OUT)
- goto Enodev;
-
- /* CD-ROM drive responded -- get the drive configuration */
- cmd_buff[0] = SONY535_INQUIRY;
- if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0)
- goto Enodev;
-
- /* was able to get the configuration,
- * set drive mode as rest of init
- */
-#if DEBUG > 0
- /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
- if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
- printk(CDU535_MESSAGE_NAME
- "Inquiry command returned status = 0x%x\n", status[0]);
-#endif
- /* now ready to use interrupts, if available */
- sony535_irq_used = tmp_irq;
-
- /* A negative sony535_irq_used will attempt an autoirq. */
- if (sony535_irq_used < 0) {
- unsigned long irq_mask, delay;
-
- irq_mask = probe_irq_on();
- enable_interrupts();
- outb(0, read_status_reg); /* does a reset? */
- delay = jiffies + HZ/10;
- while (time_before(jiffies, delay)) ;
-
- sony535_irq_used = probe_irq_off(irq_mask);
- disable_interrupts();
- }
- if (sony535_irq_used > 0) {
- if (request_irq(sony535_irq_used, cdu535_interrupt,
- IRQF_DISABLED, CDU535_HANDLE, NULL)) {
- printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
- " driver; polling instead.\n", sony535_irq_used);
- sony535_irq_used = 0;
- }
- }
- cmd_buff[0] = SONY535_SET_DRIVE_MODE;
- cmd_buff[1] = 0x0; /* default audio */
- if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0)
- goto Enodev_irq;
-
- /* set the drive mode successful, we are set! */
- sony_buffer_size = SONY535_BUFFER_SIZE;
- sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
-
- printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
- drive_config.vendor_id,
- drive_config.product_id,
- drive_config.product_rev_level);
- printk(" base address %03X, ", sony535_cd_base_io);
- if (tmp_irq > 0)
- printk("IRQ%d, ", tmp_irq);
- printk("using %d byte buffer\n", sony_buffer_size);
-
- if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) {
- err = -EIO;
- goto out1;
- }
- sonycd535_queue = blk_init_queue(do_cdu535_request, &sonycd535_lock);
- if (!sonycd535_queue) {
- err = -ENOMEM;
- goto out1a;
- }
-
- blk_queue_hardsect_size(sonycd535_queue, CDU535_BLOCK_SIZE);
- sony_toc = kmalloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
- err = -ENOMEM;
- if (!sony_toc)
- goto out2;
- last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL);
- if (!last_sony_subcode)
- goto out3;
- sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL);
- if (!sony_buffer)
- goto out4;
- for (i = 0; i < sony_buffer_sectors; i++) {
- sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
- if (!sony_buffer[i]) {
- while (--i>=0)
- kfree(sony_buffer[i]);
- goto out5;
- }
- }
- initialized = 1;
-
- cdu_disk = alloc_disk(1);
- if (!cdu_disk)
- goto out6;
- cdu_disk->major = MAJOR_NR;
- cdu_disk->first_minor = 0;
- cdu_disk->fops = &cdu_fops;
- sprintf(cdu_disk->disk_name, "cdu");
-
- if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) {
- printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n",
- sony535_cd_base_io);
- goto out7;
- }
- cdu_disk->queue = sonycd535_queue;
- add_disk(cdu_disk);
- return 0;
-
-out7:
- put_disk(cdu_disk);
-out6:
- for (i = 0; i < sony_buffer_sectors; i++)
- kfree(sony_buffer[i]);
-out5:
- kfree(sony_buffer);
-out4:
- kfree(last_sony_subcode);
-out3:
- kfree(sony_toc);
-out2:
- blk_cleanup_queue(sonycd535_queue);
-out1a:
- unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
-out1:
- if (sony535_irq_used)
- free_irq(sony535_irq_used, NULL);
- return err;
-Enodev_irq:
- if (sony535_irq_used)
- free_irq(sony535_irq_used, NULL);
-Enodev:
- printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
- return -EIO;
-}
-
-#ifndef MODULE
-
-/*
- * accept "kernel command line" parameters
- * (added by emoenke@gwdg.de)
- *
- * use: tell LILO:
- * sonycd535=0x320
- *
- * the address value has to be the existing CDROM port address.
- */
-static int __init
-sonycd535_setup(char *strings)
-{
- int ints[3];
- (void)get_options(strings, ARRAY_SIZE(ints), ints);
- /* if IRQ change and default io base desired,
- * then call with io base of 0
- */
- if (ints[0] > 0)
- if (ints[1] != 0)
- sony535_cd_base_io = ints[1];
- if (ints[0] > 1)
- sony535_irq_used = ints[2];
- if ((strings != NULL) && (*strings != '\0'))
- printk(CDU535_MESSAGE_NAME
- ": Warning: Unknown interface type: %s\n", strings);
-
- return 1;
-}
-
-__setup("sonycd535=", sonycd535_setup);
-
-#endif /* MODULE */
-
-static void __exit
-sony535_exit(void)
-{
- int i;
-
- release_region(sony535_cd_base_io, 4);
- for (i = 0; i < sony_buffer_sectors; i++)
- kfree(sony_buffer[i]);
- kfree(sony_buffer);
- kfree(last_sony_subcode);
- kfree(sony_toc);
- del_gendisk(cdu_disk);
- put_disk(cdu_disk);
- blk_cleanup_queue(sonycd535_queue);
- if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
- printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
- else
- printk(KERN_INFO CDU535_HANDLE " module released\n");
-}
-
-module_init(sony535_init);
-module_exit(sony535_exit);
-
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_BLOCKDEV_MAJOR(CDU535_CDROM_MAJOR);
diff --git a/drivers/cdrom/sonycd535.h b/drivers/cdrom/sonycd535.h
deleted file mode 100644
index 5dea1ef168d..00000000000
--- a/drivers/cdrom/sonycd535.h
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef SONYCD535_H
-#define SONYCD535_H
-
-/*
- * define all the commands recognized by the CDU-531/5
- */
-#define SONY535_REQUEST_DRIVE_STATUS_1 (0x80)
-#define SONY535_REQUEST_SENSE (0x82)
-#define SONY535_REQUEST_DRIVE_STATUS_2 (0x84)
-#define SONY535_REQUEST_ERROR_STATUS (0x86)
-#define SONY535_REQUEST_AUDIO_STATUS (0x88)
-#define SONY535_INQUIRY (0x8a)
-
-#define SONY535_SET_INACTIVITY_TIME (0x90)
-
-#define SONY535_SEEK_AND_READ_N_BLOCKS_1 (0xa0)
-#define SONY535_SEEK_AND_READ_N_BLOCKS_2 (0xa4)
-#define SONY535_PLAY_AUDIO (0xa6)
-
-#define SONY535_REQUEST_DISC_CAPACITY (0xb0)
-#define SONY535_REQUEST_TOC_DATA (0xb2)
-#define SONY535_REQUEST_SUB_Q_DATA (0xb4)
-#define SONY535_REQUEST_ISRC (0xb6)
-#define SONY535_REQUEST_UPC_EAN (0xb8)
-
-#define SONY535_SET_DRIVE_MODE (0xc0)
-#define SONY535_REQUEST_DRIVE_MODE (0xc2)
-#define SONY535_SET_RETRY_COUNT (0xc4)
-
-#define SONY535_DIAGNOSTIC_1 (0xc6)
-#define SONY535_DIAGNOSTIC_4 (0xcc)
-#define SONY535_DIAGNOSTIC_5 (0xce)
-
-#define SONY535_EJECT_CADDY (0xd0)
-#define SONY535_DISABLE_EJECT_BUTTON (0xd2)
-#define SONY535_ENABLE_EJECT_BUTTON (0xd4)
-
-#define SONY535_HOLD (0xe0)
-#define SONY535_AUDIO_PAUSE_ON_OFF (0xe2)
-#define SONY535_SET_VOLUME (0xe8)
-
-#define SONY535_STOP (0xf0)
-#define SONY535_SPIN_UP (0xf2)
-#define SONY535_SPIN_DOWN (0xf4)
-
-#define SONY535_CLEAR_PARAMETERS (0xf6)
-#define SONY535_CLEAR_ENDING_ADDRESS (0xf8)
-
-/*
- * define some masks
- */
-#define SONY535_DATA_NOT_READY_BIT (0x1)
-#define SONY535_RESULT_NOT_READY_BIT (0x2)
-
-/*
- * drive status 1
- */
-#define SONY535_STATUS1_COMMAND_ERROR (0x1)
-#define SONY535_STATUS1_DATA_ERROR (0x2)
-#define SONY535_STATUS1_SEEK_ERROR (0x4)
-#define SONY535_STATUS1_DISC_TYPE_ERROR (0x8)
-#define SONY535_STATUS1_NOT_SPINNING (0x10)
-#define SONY535_STATUS1_EJECT_BUTTON_PRESSED (0x20)
-#define SONY535_STATUS1_CADDY_NOT_INSERTED (0x40)
-#define SONY535_STATUS1_BYTE_TWO_FOLLOWS (0x80)
-
-/*
- * drive status 2
- */
-#define SONY535_CDD_LOADING_ERROR (0x7)
-#define SONY535_CDD_NO_DISC (0x8)
-#define SONY535_CDD_UNLOADING_ERROR (0x9)
-#define SONY535_CDD_CADDY_NOT_INSERTED (0xd)
-#define SONY535_ATN_RESET_OCCURRED (0x2)
-#define SONY535_ATN_DISC_CHANGED (0x4)
-#define SONY535_ATN_RESET_AND_DISC_CHANGED (0x6)
-#define SONY535_ATN_EJECT_IN_PROGRESS (0xe)
-#define SONY535_ATN_BUSY (0xf)
-
-/*
- * define some parameters
- */
-#define SONY535_AUDIO_DRIVE_MODE (0)
-#define SONY535_CDROM_DRIVE_MODE (0xe0)
-
-#define SONY535_PLAY_OP_PLAYBACK (0)
-#define SONY535_PLAY_OP_ENTER_HOLD (1)
-#define SONY535_PLAY_OP_SET_AUDIO_ENDING_ADDR (2)
-#define SONY535_PLAY_OP_SCAN_FORWARD (3)
-#define SONY535_PLAY_OP_SCAN_BACKWARD (4)
-
-/*
- * convert from msf format to block number
- */
-#define SONY_BLOCK_NUMBER(m,s,f) (((m)*60L+(s))*75L+(f))
-#define SONY_BLOCK_NUMBER_MSF(x) (((x)[0]*60L+(x)[1])*75L+(x)[2])
-
-/*
- * error return values from the doSonyCmd() routines
- */
-#define TIME_OUT (-1)
-#define NO_CDROM (-2)
-#define BAD_STATUS (-3)
-#define CD_BUSY (-4)
-#define NOT_DATA_CD (-5)
-#define NO_ROOM (-6)
-
-#define LOG_START_OFFSET 150 /* Offset of first logical sector */
-
-#define SONY_JIFFIES_TIMEOUT (5*HZ) /* Maximum time
- the drive will wait/try for an
- operation */
-#define SONY_READY_RETRIES (50000) /* How many times to retry a
- spin waiting for a register
- to come ready */
-#define SONY535_FAST_POLLS (10000) /* how many times recheck
- status waiting for a data
- to become ready */
-
-typedef unsigned char Byte;
-
-/*
- * This is the complete status returned from the drive configuration request
- * command.
- */
-struct s535_sony_drive_config
-{
- char vendor_id[8];
- char product_id[16];
- char product_rev_level[4];
-};
-
-/* The following is returned from the request sub-q data command */
-struct s535_sony_subcode
-{
- unsigned char address :4;
- unsigned char control :4;
- unsigned char track_num;
- unsigned char index_num;
- unsigned char rel_msf[3];
- unsigned char abs_msf[3];
-};
-
-struct s535_sony_disc_capacity
-{
- Byte mFirstTrack, sFirstTrack, fFirstTrack;
- Byte mLeadOut, sLeadOut, fLeadOut;
-};
-
-/*
- * The following is returned from the request TOC (Table Of Contents) command.
- * (last_track_num-first_track_num+1) values are valid in tracks.
- */
-struct s535_sony_toc
-{
- unsigned char reserved0 :4;
- unsigned char control0 :4;
- unsigned char point0;
- unsigned char first_track_num;
- unsigned char reserved0a;
- unsigned char reserved0b;
- unsigned char reserved1 :4;
- unsigned char control1 :4;
- unsigned char point1;
- unsigned char last_track_num;
- unsigned char dummy1;
- unsigned char dummy2;
- unsigned char reserved2 :4;
- unsigned char control2 :4;
- unsigned char point2;
- unsigned char lead_out_start_msf[3];
- struct
- {
- unsigned char reserved :4;
- unsigned char control :4;
- unsigned char track;
- unsigned char track_start_msf[3];
- } tracks[100];
-
- unsigned int lead_out_start_lba;
-};
-
-#endif /* SONYCD535_H */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index ef683ebd367..f6648682b43 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -374,20 +374,6 @@ config ISTALLION
To compile this driver as a module, choose M here: the
module will be called istallion.
-config AU1000_UART
- bool "Enable Au1000 UART Support"
- depends on SERIAL_NONSTANDARD && MIPS
- help
- If you have an Alchemy AU1000 processor (MIPS based) and you want
- to use serial ports, say Y. Otherwise, say N.
-
-config AU1000_SERIAL_CONSOLE
- bool "Enable Au1000 serial console"
- depends on AU1000_UART
- help
- If you have an Alchemy AU1000 processor (MIPS based) and you want
- to use a console on a serial port, say Y. Otherwise, say N.
-
config SERIAL_DEC
bool "DECstation serial support"
depends on MACH_DECSTATION
@@ -815,7 +801,7 @@ config SGI_IP27_RTC
config GEN_RTC
tristate "Generic /dev/rtc emulation"
- depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390 && !SUPERH
+ depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index fdbca25a394..35ab1a9f8e8 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -176,7 +176,7 @@ struct agp_bridge_data {
#define I830_GMCH_MEM_MASK 0x1
#define I830_GMCH_MEM_64M 0x1
#define I830_GMCH_MEM_128M 0
-#define I830_GMCH_GMS_MASK 0x70
+#define I830_GMCH_GMS_MASK 0xF0
#define I830_GMCH_GMS_DISABLED 0x00
#define I830_GMCH_GMS_LOCAL 0x10
#define I830_GMCH_GMS_STOLEN_512 0x20
@@ -231,6 +231,10 @@ struct agp_bridge_data {
#define I965_PGETBL_SIZE_512KB (0 << 1)
#define I965_PGETBL_SIZE_256KB (1 << 1)
#define I965_PGETBL_SIZE_128KB (2 << 1)
+#define G33_PGETBL_SIZE_MASK (3 << 8)
+#define G33_PGETBL_SIZE_1M (1 << 8)
+#define G33_PGETBL_SIZE_2M (2 << 8)
+
#define I810_DRAM_CTL 0x3000
#define I810_DRAM_ROW_0 0x00000001
#define I810_DRAM_ROW_0_SDRAM 0x00000001
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index e6c534e6284..df0ddf14b85 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -462,9 +462,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
* erratum 46: Setup violation on AGP SBA pins - Disable side band addressing.
* With this lot disabled, we should prevent lockups. */
if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) {
- u8 revision=0;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
- if (revision == 0x10 || revision == 0x11) {
+ if (pdev->revision == 0x10 || pdev->revision == 0x11) {
agp_bridge->flags = AGP_ERRATA_FASTWRITES;
agp_bridge->flags |= AGP_ERRATA_SBA;
agp_bridge->flags |= AGP_ERRATA_1X;
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 801abdd2906..d95662e9632 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -367,10 +367,8 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge)
{
char *revstring;
- u8 rev_id;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
- switch (rev_id) {
+ switch (pdev->revision) {
case 0x01: revstring="A0"; break;
case 0x02: revstring="A1"; break;
case 0x11: revstring="B0"; break;
@@ -386,7 +384,7 @@ static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data
* Work around errata.
* Chips before B2 stepping incorrectly reporting v3.5
*/
- if (rev_id < 0x13) {
+ if (pdev->revision < 0x13) {
printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n");
bridge->major_version = 3;
bridge->minor_version = 0;
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index ebdd6dd66ed..1b47c89a1b9 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -321,7 +321,7 @@ EXPORT_SYMBOL(agp_try_unsupported_boot);
static int __init agp_init(void)
{
if (!agp_off)
- printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n",
+ printk(KERN_INFO "Linux agpgart interface v%d.%d\n",
AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR);
return 0;
}
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 9c69f2e761f..a1240603912 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -20,6 +20,14 @@
#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2
#define PCI_DEVICE_ID_INTEL_82965GM_HB 0x2A00
#define PCI_DEVICE_ID_INTEL_82965GM_IG 0x2A02
+#define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12
+#define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE
+#define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0
+#define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2
+#define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0
+#define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2
+#define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0
+#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2
#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
@@ -27,6 +35,9 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB)
+#define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB)
extern int agp_memory_reserved;
@@ -53,6 +64,8 @@ extern int agp_memory_reserved;
#define I915_PTEADDR 0x1C
#define I915_GMCH_GMS_STOLEN_48M (0x6 << 4)
#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
+#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
+#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
/* Intel 965G registers */
#define I965_MSAC 0x62
@@ -86,11 +99,18 @@ static struct gatt_mask intel_i810_masks[] =
.type = INTEL_AGP_CACHED_MEMORY}
};
-static struct _intel_i810_private {
- struct pci_dev *i810_dev; /* device one */
- volatile u8 __iomem *registers;
+static struct _intel_private {
+ struct pci_dev *pcidev; /* device one */
+ u8 __iomem *registers;
+ u32 __iomem *gtt; /* I915G */
int num_dcache_entries;
-} intel_i810_private;
+ /* gtt_entries is the number of gtt entries that are already mapped
+ * to stolen memory. Stolen memory is larger than the memory mapped
+ * through gtt_entries, as it includes some reserved space for the BIOS
+ * popup and for the GTT.
+ */
+ int gtt_entries; /* i830+ */
+} intel_private;
static int intel_i810_fetch_size(void)
{
@@ -127,32 +147,32 @@ static int intel_i810_configure(void)
current_size = A_SIZE_FIX(agp_bridge->current_size);
- if (!intel_i810_private.registers) {
- pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
+ if (!intel_private.registers) {
+ pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
temp &= 0xfff80000;
- intel_i810_private.registers = ioremap(temp, 128 * 4096);
- if (!intel_i810_private.registers) {
+ intel_private.registers = ioremap(temp, 128 * 4096);
+ if (!intel_private.registers) {
printk(KERN_ERR PFX "Unable to remap memory.\n");
return -ENOMEM;
}
}
- if ((readl(intel_i810_private.registers+I810_DRAM_CTL)
+ if ((readl(intel_private.registers+I810_DRAM_CTL)
& I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) {
/* This will need to be dynamically assigned */
printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n");
- intel_i810_private.num_dcache_entries = 1024;
+ intel_private.num_dcache_entries = 1024;
}
- pci_read_config_dword(intel_i810_private.i810_dev, I810_GMADDR, &temp);
+ pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
- writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_i810_private.registers+I810_PGETBL_CTL);
- readl(intel_i810_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+ writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+ readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
if (agp_bridge->driver->needs_scratch_page) {
for (i = 0; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */
+ writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+ readl(intel_private.registers+I810_PTE_BASE+(i*4)); /* PCI posting. */
}
}
global_cache_flush();
@@ -161,9 +181,9 @@ static int intel_i810_configure(void)
static void intel_i810_cleanup(void)
{
- writel(0, intel_i810_private.registers+I810_PGETBL_CTL);
- readl(intel_i810_private.registers); /* PCI Posting. */
- iounmap(intel_i810_private.registers);
+ writel(0, intel_private.registers+I810_PGETBL_CTL);
+ readl(intel_private.registers); /* PCI Posting. */
+ iounmap(intel_private.registers);
}
static void intel_i810_tlbflush(struct agp_memory *mem)
@@ -261,9 +281,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
global_cache_flush();
for (i = pg_start; i < (pg_start + mem->page_count); i++) {
writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID,
- intel_i810_private.registers+I810_PTE_BASE+(i*4));
+ intel_private.registers+I810_PTE_BASE+(i*4));
}
- readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
break;
case AGP_PHYS_MEMORY:
case AGP_NORMAL_MEMORY:
@@ -273,9 +293,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i],
mask_type),
- intel_i810_private.registers+I810_PTE_BASE+(j*4));
+ intel_private.registers+I810_PTE_BASE+(j*4));
}
- readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
break;
default:
goto out_err;
@@ -298,9 +318,9 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
return 0;
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
+ writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
}
- readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
agp_bridge->driver->tlb_flush(mem);
return 0;
@@ -354,7 +374,7 @@ static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
struct agp_memory *new;
if (type == AGP_DCACHE_MEMORY) {
- if (pg_count != intel_i810_private.num_dcache_entries)
+ if (pg_count != intel_private.num_dcache_entries)
return NULL;
new = agp_create_memory(1);
@@ -404,18 +424,6 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
{512, 131072, 7},
};
-static struct _intel_i830_private {
- struct pci_dev *i830_dev; /* device one */
- volatile u8 __iomem *registers;
- volatile u32 __iomem *gtt; /* I915G */
- /* gtt_entries is the number of gtt entries that are already mapped
- * to stolen memory. Stolen memory is larger than the memory mapped
- * through gtt_entries, as it includes some reserved space for the BIOS
- * popup and for the GTT.
- */
- int gtt_entries;
-} intel_i830_private;
-
static void intel_i830_init_gtt_entries(void)
{
u16 gmch_ctrl;
@@ -429,7 +437,7 @@ static void intel_i830_init_gtt_entries(void)
if (IS_I965) {
u32 pgetbl_ctl;
- pgetbl_ctl = readl(intel_i830_private.registers+I810_PGETBL_CTL);
+ pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL);
/* The 965 has a field telling us the size of the GTT,
* which may be larger than what is necessary to map the
@@ -451,6 +459,22 @@ static void intel_i830_init_gtt_entries(void)
size = 512;
}
size += 4; /* add in BIOS popup space */
+ } else if (IS_G33) {
+ /* G33's GTT size defined in gmch_ctrl */
+ switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) {
+ case G33_PGETBL_SIZE_1M:
+ size = 1024;
+ break;
+ case G33_PGETBL_SIZE_2M:
+ size = 2048;
+ break;
+ default:
+ printk(KERN_INFO PFX "Unknown page table size 0x%x, "
+ "assuming 512KB\n",
+ (gmch_ctrl & G33_PGETBL_SIZE_MASK));
+ size = 512;
+ }
+ size += 4;
} else {
/* On previous hardware, the GTT size was just what was
* required to map the aperture.
@@ -471,7 +495,7 @@ static void intel_i830_init_gtt_entries(void)
gtt_entries = MB(8) - KB(size);
break;
case I830_GMCH_GMS_LOCAL:
- rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
+ rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
MB(ddt[I830_RDRAM_DDT(rdct)]);
local = 1;
@@ -502,7 +526,8 @@ static void intel_i830_init_gtt_entries(void)
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 )
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
+ IS_I965 || IS_G33)
gtt_entries = MB(48) - KB(size);
else
gtt_entries = 0;
@@ -512,10 +537,24 @@ static void intel_i830_init_gtt_entries(void)
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
+ IS_I965 || IS_G33)
gtt_entries = MB(64) - KB(size);
else
gtt_entries = 0;
+ break;
+ case G33_GMCH_GMS_STOLEN_128M:
+ if (IS_G33)
+ gtt_entries = MB(128) - KB(size);
+ else
+ gtt_entries = 0;
+ break;
+ case G33_GMCH_GMS_STOLEN_256M:
+ if (IS_G33)
+ gtt_entries = MB(256) - KB(size);
+ else
+ gtt_entries = 0;
+ break;
default:
gtt_entries = 0;
break;
@@ -529,7 +568,7 @@ static void intel_i830_init_gtt_entries(void)
"No pre-allocated video memory detected.\n");
gtt_entries /= KB(4);
- intel_i830_private.gtt_entries = gtt_entries;
+ intel_private.gtt_entries = gtt_entries;
}
/* The intel i830 automatically initializes the agp aperture during POST.
@@ -547,14 +586,14 @@ static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
num_entries = size->num_entries;
agp_bridge->gatt_table_real = NULL;
- pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
+ pci_read_config_dword(intel_private.pcidev,I810_MMADDR,&temp);
temp &= 0xfff80000;
- intel_i830_private.registers = ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
+ intel_private.registers = ioremap(temp,128 * 4096);
+ if (!intel_private.registers)
return -ENOMEM;
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+ temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ?? */
/* we have to call this as early as possible after the MMIO base address is known */
@@ -614,20 +653,20 @@ static int intel_i830_configure(void)
current_size = A_SIZE_FIX(agp_bridge->current_size);
- pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
+ pci_read_config_dword(intel_private.pcidev,I810_GMADDR,&temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
gmch_ctrl |= I830_GMCH_ENABLED;
pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
- readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+ writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+ readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
if (agp_bridge->driver->needs_scratch_page) {
- for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
- readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
+ for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
+ writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
+ readl(intel_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
}
@@ -637,7 +676,7 @@ static int intel_i830_configure(void)
static void intel_i830_cleanup(void)
{
- iounmap(intel_i830_private.registers);
+ iounmap(intel_private.registers);
}
static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type)
@@ -653,9 +692,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
- pg_start,intel_i830_private.gtt_entries);
+ if (pg_start < intel_private.gtt_entries) {
+ printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
+ pg_start,intel_private.gtt_entries);
printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
goto out_err;
@@ -683,9 +722,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mask_type),
- intel_i830_private.registers+I810_PTE_BASE+(j*4));
+ intel_private.registers+I810_PTE_BASE+(j*4));
}
- readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
agp_bridge->driver->tlb_flush(mem);
out:
@@ -703,15 +742,15 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
if (mem->page_count == 0)
return 0;
- if (pg_start < intel_i830_private.gtt_entries) {
+ if (pg_start < intel_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
return -EINVAL;
}
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
+ writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4));
}
- readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
+ readl(intel_private.registers+I810_PTE_BASE+((i-1)*4));
agp_bridge->driver->tlb_flush(mem);
return 0;
@@ -734,7 +773,7 @@ static int intel_i915_configure(void)
current_size = A_SIZE_FIX(agp_bridge->current_size);
- pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp);
+ pci_read_config_dword(intel_private.pcidev, I915_GMADDR, &temp);
agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
@@ -742,13 +781,13 @@ static int intel_i915_configure(void)
gmch_ctrl |= I830_GMCH_ENABLED;
pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
- writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
- readl(intel_i830_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
+ writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+ readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */
if (agp_bridge->driver->needs_scratch_page) {
- for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
- readl(intel_i830_private.gtt+i); /* PCI Posting. */
+ for (i = intel_private.gtt_entries; i < current_size->num_entries; i++) {
+ writel(agp_bridge->scratch_page, intel_private.gtt+i);
+ readl(intel_private.gtt+i); /* PCI Posting. */
}
}
@@ -758,8 +797,8 @@ static int intel_i915_configure(void)
static void intel_i915_cleanup(void)
{
- iounmap(intel_i830_private.gtt);
- iounmap(intel_i830_private.registers);
+ iounmap(intel_private.gtt);
+ iounmap(intel_private.registers);
}
static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -776,9 +815,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;
- if (pg_start < intel_i830_private.gtt_entries) {
- printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
- pg_start,intel_i830_private.gtt_entries);
+ if (pg_start < intel_private.gtt_entries) {
+ printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
+ pg_start,intel_private.gtt_entries);
printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
goto out_err;
@@ -805,10 +844,10 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
- mem->memory[i], mask_type), intel_i830_private.gtt+j);
+ mem->memory[i], mask_type), intel_private.gtt+j);
}
- readl(intel_i830_private.gtt+j-1);
+ readl(intel_private.gtt+j-1);
agp_bridge->driver->tlb_flush(mem);
out:
@@ -826,15 +865,15 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
if (mem->page_count == 0)
return 0;
- if (pg_start < intel_i830_private.gtt_entries) {
+ if (pg_start < intel_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
return -EINVAL;
}
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
+ writel(agp_bridge->scratch_page, intel_private.gtt+i);
}
- readl(intel_i830_private.gtt+i-1);
+ readl(intel_private.gtt+i-1);
agp_bridge->driver->tlb_flush(mem);
return 0;
@@ -850,7 +889,7 @@ static int intel_i9xx_fetch_size(void)
int aper_size; /* size in megabytes */
int i;
- aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1);
+ aper_size = pci_resource_len(intel_private.pcidev, 2) / MB(1);
for (i = 0; i < num_sizes; i++) {
if (aper_size == intel_i830_sizes[i].size) {
@@ -878,20 +917,20 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
num_entries = size->num_entries;
agp_bridge->gatt_table_real = NULL;
- pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
- pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
+ pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
+ pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2);
- intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
- if (!intel_i830_private.gtt)
+ intel_private.gtt = ioremap(temp2, 256 * 1024);
+ if (!intel_private.gtt)
return -ENOMEM;
temp &= 0xfff80000;
- intel_i830_private.registers = ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
+ intel_private.registers = ioremap(temp,128 * 4096);
+ if (!intel_private.registers)
return -ENOMEM;
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+ temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ? */
/* we have to call this as early as possible after the MMIO base address is known */
@@ -938,20 +977,20 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
num_entries = size->num_entries;
agp_bridge->gatt_table_real = NULL;
- pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
+ pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
temp &= 0xfff00000;
- intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
+ intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
- if (!intel_i830_private.gtt)
+ if (!intel_private.gtt)
return -ENOMEM;
- intel_i830_private.registers = ioremap(temp,128 * 4096);
- if (!intel_i830_private.registers)
+ intel_private.registers = ioremap(temp,128 * 4096);
+ if (!intel_private.registers)
return -ENOMEM;
- temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
+ temp = readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000;
global_cache_flush(); /* FIXME: ? */
/* we have to call this as early as possible after the MMIO base address is known */
@@ -1722,41 +1761,127 @@ static const struct agp_bridge_driver intel_7505_driver = {
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
};
-static int find_i810(u16 device)
-{
- struct pci_dev *i810_dev;
-
- i810_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
- if (!i810_dev)
- return 0;
- intel_i810_private.i810_dev = i810_dev;
- return 1;
-}
+static const struct agp_bridge_driver intel_g33_driver = {
+ .owner = THIS_MODULE,
+ .aperture_sizes = intel_i830_sizes,
+ .size_type = FIXED_APER_SIZE,
+ .num_aperture_sizes = 4,
+ .needs_scratch_page = TRUE,
+ .configure = intel_i915_configure,
+ .fetch_size = intel_i9xx_fetch_size,
+ .cleanup = intel_i915_cleanup,
+ .tlb_flush = intel_i810_tlbflush,
+ .mask_memory = intel_i965_mask_memory,
+ .masks = intel_i810_masks,
+ .agp_enable = intel_i810_agp_enable,
+ .cache_flush = global_cache_flush,
+ .create_gatt_table = intel_i915_create_gatt_table,
+ .free_gatt_table = intel_i830_free_gatt_table,
+ .insert_memory = intel_i915_insert_entries,
+ .remove_memory = intel_i915_remove_entries,
+ .alloc_by_type = intel_i830_alloc_by_type,
+ .free_by_type = intel_i810_free_by_type,
+ .agp_alloc_page = agp_generic_alloc_page,
+ .agp_destroy_page = agp_generic_destroy_page,
+ .agp_type_to_mask_type = intel_i830_type_to_mask_type,
+};
-static int find_i830(u16 device)
+static int find_gmch(u16 device)
{
- struct pci_dev *i830_dev;
+ struct pci_dev *gmch_device;
- i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
- if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
- i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
- device, i830_dev);
+ gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
+ if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
+ gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
+ device, gmch_device);
}
- if (!i830_dev)
+ if (!gmch_device)
return 0;
- intel_i830_private.i830_dev = i830_dev;
+ intel_private.pcidev = gmch_device;
return 1;
}
+/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
+ * driver and gmch_driver must be non-null, and find_gmch will determine
+ * which one should be used if a gmch_chip_id is present.
+ */
+static const struct intel_driver_description {
+ unsigned int chip_id;
+ unsigned int gmch_chip_id;
+ unsigned int multi_gmch_chip; /* if we have more gfx chip type on this HB. */
+ char *name;
+ const struct agp_bridge_driver *driver;
+ const struct agp_bridge_driver *gmch_driver;
+} intel_agp_chipsets[] = {
+ { PCI_DEVICE_ID_INTEL_82443LX_0, 0, 0, "440LX", &intel_generic_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82443BX_0, 0, 0, "440BX", &intel_generic_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82443GX_0, 0, 0, "440GX", &intel_generic_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82810_MC1, PCI_DEVICE_ID_INTEL_82810_IG1, 0, "i810",
+ NULL, &intel_810_driver },
+ { PCI_DEVICE_ID_INTEL_82810_MC3, PCI_DEVICE_ID_INTEL_82810_IG3, 0, "i810",
+ NULL, &intel_810_driver },
+ { PCI_DEVICE_ID_INTEL_82810E_MC, PCI_DEVICE_ID_INTEL_82810E_IG, 0, "i810",
+ NULL, &intel_810_driver },
+ { PCI_DEVICE_ID_INTEL_82815_MC, PCI_DEVICE_ID_INTEL_82815_CGC, 0, "i815",
+ &intel_815_driver, &intel_810_driver },
+ { PCI_DEVICE_ID_INTEL_82820_HB, 0, 0, "i820", &intel_820_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82820_UP_HB, 0, 0, "i820", &intel_820_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82830_HB, PCI_DEVICE_ID_INTEL_82830_CGC, 0, "830M",
+ &intel_830mp_driver, &intel_830_driver },
+ { PCI_DEVICE_ID_INTEL_82840_HB, 0, 0, "i840", &intel_840_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82845_HB, 0, 0, "845G", &intel_845_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M",
+ &intel_845_driver, &intel_830_driver },
+ { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM",
+ &intel_845_driver, &intel_830_driver },
+ { PCI_DEVICE_ID_INTEL_82860_HB, 0, 0, "i860", &intel_860_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82865_HB, PCI_DEVICE_ID_INTEL_82865_IG, 0, "865",
+ &intel_845_driver, &intel_830_driver },
+ { PCI_DEVICE_ID_INTEL_82875_HB, 0, 0, "i875", &intel_845_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_82915G_HB, PCI_DEVICE_ID_INTEL_82915G_IG, 0, "915G",
+ NULL, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82915GM_HB, PCI_DEVICE_ID_INTEL_82915GM_IG, 0, "915GM",
+ NULL, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82945G_HB, PCI_DEVICE_ID_INTEL_82945G_IG, 0, "945G",
+ NULL, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GM_IG, 1, "945GM",
+ NULL, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82945GM_HB, PCI_DEVICE_ID_INTEL_82945GME_IG, 0, "945GME",
+ NULL, &intel_915_driver },
+ { PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
+ NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965G_1_HB, PCI_DEVICE_ID_INTEL_82965G_1_IG, 0, "965G",
+ NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, 0, "965Q",
+ NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965G_HB, PCI_DEVICE_ID_INTEL_82965G_IG, 0, "965G",
+ NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GM_IG, 1, "965GM",
+ NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_82965GM_HB, PCI_DEVICE_ID_INTEL_82965GME_IG, 0, "965GME/GLE",
+ NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_7505_0, 0, 0, "E7505", &intel_7505_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_7205_0, 0, 0, "E7205", &intel_7505_driver, NULL },
+ { PCI_DEVICE_ID_INTEL_G33_HB, PCI_DEVICE_ID_INTEL_G33_IG, 0, "G33",
+ NULL, &intel_g33_driver },
+ { PCI_DEVICE_ID_INTEL_Q35_HB, PCI_DEVICE_ID_INTEL_Q35_IG, 0, "Q35",
+ NULL, &intel_g33_driver },
+ { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
+ NULL, &intel_g33_driver },
+ { 0, 0, 0, NULL, NULL, NULL }
+};
+
static int __devinit agp_intel_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct agp_bridge_data *bridge;
- char *name = "(unknown)";
u8 cap_ptr = 0;
struct resource *r;
+ int i;
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
@@ -1764,195 +1889,49 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
if (!bridge)
return -ENOMEM;
- switch (pdev->device) {
- case PCI_DEVICE_ID_INTEL_82443LX_0:
- bridge->driver = &intel_generic_driver;
- name = "440LX";
- break;
- case PCI_DEVICE_ID_INTEL_82443BX_0:
- bridge->driver = &intel_generic_driver;
- name = "440BX";
- break;
- case PCI_DEVICE_ID_INTEL_82443GX_0:
- bridge->driver = &intel_generic_driver;
- name = "440GX";
- break;
- case PCI_DEVICE_ID_INTEL_82810_MC1:
- name = "i810";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82810_MC3:
- name = "i810 DC100";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82810E_MC:
- name = "i810 E";
- if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG))
- goto fail;
- bridge->driver = &intel_810_driver;
- break;
- case PCI_DEVICE_ID_INTEL_82815_MC:
- /*
- * The i815 can operate either as an i810 style
- * integrated device, or as an AGP4X motherboard.
- */
- if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC))
- bridge->driver = &intel_810_driver;
- else
- bridge->driver = &intel_815_driver;
- name = "i815";
- break;
- case PCI_DEVICE_ID_INTEL_82820_HB:
- case PCI_DEVICE_ID_INTEL_82820_UP_HB:
- bridge->driver = &intel_820_driver;
- name = "i820";
- break;
- case PCI_DEVICE_ID_INTEL_82830_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC))
- bridge->driver = &intel_830_driver;
- else
- bridge->driver = &intel_830mp_driver;
- name = "830M";
- break;
- case PCI_DEVICE_ID_INTEL_82840_HB:
- bridge->driver = &intel_840_driver;
- name = "i840";
- break;
- case PCI_DEVICE_ID_INTEL_82845_HB:
- bridge->driver = &intel_845_driver;
- name = "i845";
- break;
- case PCI_DEVICE_ID_INTEL_82845G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG))
- bridge->driver = &intel_830_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "845G";
- break;
- case PCI_DEVICE_ID_INTEL_82850_HB:
- bridge->driver = &intel_850_driver;
- name = "i850";
- break;
- case PCI_DEVICE_ID_INTEL_82855PM_HB:
- bridge->driver = &intel_845_driver;
- name = "855PM";
- break;
- case PCI_DEVICE_ID_INTEL_82855GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) {
- bridge->driver = &intel_830_driver;
- name = "855";
- } else {
- bridge->driver = &intel_845_driver;
- name = "855GM";
+ for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
+ /* In case that multiple models of gfx chip may
+ stand on same host bridge type, this can be
+ sure we detect the right IGD. */
+ if (pdev->device == intel_agp_chipsets[i].chip_id) {
+ if ((intel_agp_chipsets[i].gmch_chip_id != 0) &&
+ find_gmch(intel_agp_chipsets[i].gmch_chip_id)) {
+ bridge->driver =
+ intel_agp_chipsets[i].gmch_driver;
+ break;
+ } else if (intel_agp_chipsets[i].multi_gmch_chip) {
+ continue;
+ } else {
+ bridge->driver = intel_agp_chipsets[i].driver;
+ break;
+ }
}
- break;
- case PCI_DEVICE_ID_INTEL_82860_HB:
- bridge->driver = &intel_860_driver;
- name = "i860";
- break;
- case PCI_DEVICE_ID_INTEL_82865_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG))
- bridge->driver = &intel_830_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "865";
- break;
- case PCI_DEVICE_ID_INTEL_82875_HB:
- bridge->driver = &intel_845_driver;
- name = "i875";
- break;
- case PCI_DEVICE_ID_INTEL_82915G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915G_IG))
- bridge->driver = &intel_915_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "915G";
- break;
- case PCI_DEVICE_ID_INTEL_82915GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82915GM_IG))
- bridge->driver = &intel_915_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "915GM";
- break;
- case PCI_DEVICE_ID_INTEL_82945G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG))
- bridge->driver = &intel_915_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "945G";
- break;
- case PCI_DEVICE_ID_INTEL_82945GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82945GM_IG))
- bridge->driver = &intel_915_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "945GM";
- break;
- case PCI_DEVICE_ID_INTEL_82946GZ_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "946GZ";
- break;
- case PCI_DEVICE_ID_INTEL_82965G_1_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "965G";
- break;
- case PCI_DEVICE_ID_INTEL_82965Q_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "965Q";
- break;
- case PCI_DEVICE_ID_INTEL_82965G_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "965G";
- break;
- case PCI_DEVICE_ID_INTEL_82965GM_HB:
- if (find_i830(PCI_DEVICE_ID_INTEL_82965GM_IG))
- bridge->driver = &intel_i965_driver;
- else
- bridge->driver = &intel_845_driver;
- name = "965GM";
- break;
- case PCI_DEVICE_ID_INTEL_7505_0:
- bridge->driver = &intel_7505_driver;
- name = "E7505";
- break;
- case PCI_DEVICE_ID_INTEL_7205_0:
- bridge->driver = &intel_7505_driver;
- name = "E7205";
- break;
- default:
+ }
+
+ if (intel_agp_chipsets[i].name == NULL) {
if (cap_ptr)
- printk(KERN_WARNING PFX "Unsupported Intel chipset (device id: %04x)\n",
- pdev->device);
+ printk(KERN_WARNING PFX "Unsupported Intel chipset"
+ "(device id: %04x)\n", pdev->device);
agp_put_bridge(bridge);
return -ENODEV;
- };
+ }
+
+ if (bridge->driver == NULL) {
+ /* bridge has no AGP and no IGD detected */
+ if (cap_ptr)
+ printk(KERN_WARNING PFX "Failed to find bridge device "
+ "(chip_id: %04x)\n",
+ intel_agp_chipsets[i].gmch_chip_id);
+ agp_put_bridge(bridge);
+ return -ENODEV;
+ }
bridge->dev = pdev;
bridge->capndx = cap_ptr;
+ bridge->dev_private_data = &intel_private;
- if (bridge->driver == &intel_810_driver)
- bridge->dev_private_data = &intel_i810_private;
- else if (bridge->driver == &intel_830_driver)
- bridge->dev_private_data = &intel_i830_private;
-
- printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
+ printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n",
+ intel_agp_chipsets[i].name);
/*
* The following fixes the case where the BIOS has "forgotten" to
@@ -1988,12 +1967,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
-
-fail:
- printk(KERN_ERR PFX "Detected an Intel %s chipset, "
- "but could not find the secondary device.\n", name);
- agp_put_bridge(bridge);
- return -ENODEV;
}
static void __devexit agp_intel_remove(struct pci_dev *pdev)
@@ -2002,10 +1975,8 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
agp_remove_bridge(bridge);
- if (intel_i810_private.i810_dev)
- pci_dev_put(intel_i810_private.i810_dev);
- if (intel_i830_private.i830_dev)
- pci_dev_put(intel_i830_private.i830_dev);
+ if (intel_private.pcidev)
+ pci_dev_put(intel_private.pcidev);
agp_put_bridge(bridge);
}
@@ -2021,10 +1992,8 @@ static int agp_intel_resume(struct pci_dev *pdev)
* as host bridge (00:00) resumes before graphics device (02:00),
* then our access to its pci space can work right.
*/
- if (intel_i810_private.i810_dev)
- pci_restore_state(intel_i810_private.i810_dev);
- if (intel_i830_private.i830_dev)
- pci_restore_state(intel_i830_private.i830_dev);
+ if (intel_private.pcidev)
+ pci_restore_state(intel_private.pcidev);
if (bridge->driver == &intel_generic_driver)
intel_configure();
@@ -2087,6 +2056,9 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
ID(PCI_DEVICE_ID_INTEL_82965G_HB),
ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
+ ID(PCI_DEVICE_ID_INTEL_G33_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q35_HB),
+ ID(PCI_DEVICE_ID_INTEL_Q33_HB),
{ }
};
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c
index de37d5f7456..b33313be254 100644
--- a/drivers/char/drm/drm_drawable.c
+++ b/drivers/char/drm/drm_drawable.c
@@ -172,38 +172,49 @@ int drm_rmdraw(DRM_IOCTL_ARGS)
bitfield_length = idx + 1;
- if (idx != id / (8 * sizeof(*bitfield)))
- bitfield = drm_alloc(bitfield_length *
- sizeof(*bitfield), DRM_MEM_BUFS);
+ bitfield = NULL;
- if (!bitfield && bitfield_length) {
- bitfield = dev->drw_bitfield;
- bitfield_length = dev->drw_bitfield_length;
+ if (bitfield_length) {
+ if (bitfield_length != dev->drw_bitfield_length)
+ bitfield = drm_alloc(bitfield_length *
+ sizeof(*bitfield),
+ DRM_MEM_BUFS);
+
+ if (!bitfield) {
+ bitfield = dev->drw_bitfield;
+ bitfield_length = dev->drw_bitfield_length;
+ }
}
}
if (bitfield != dev->drw_bitfield) {
info_length = 8 * sizeof(*bitfield) * bitfield_length;
- info = drm_alloc(info_length * sizeof(*info), DRM_MEM_BUFS);
+ if (info_length) {
+ info = drm_alloc(info_length * sizeof(*info),
+ DRM_MEM_BUFS);
- if (!info && info_length) {
- info = dev->drw_info;
- info_length = dev->drw_info_length;
- }
+ if (!info) {
+ info = dev->drw_info;
+ info_length = dev->drw_info_length;
+ }
+ } else
+ info = NULL;
spin_lock_irqsave(&dev->drw_lock, irqflags);
- memcpy(bitfield, dev->drw_bitfield, bitfield_length *
- sizeof(*bitfield));
+ if (bitfield)
+ memcpy(bitfield, dev->drw_bitfield, bitfield_length *
+ sizeof(*bitfield));
drm_free(dev->drw_bitfield, sizeof(*bitfield) *
dev->drw_bitfield_length, DRM_MEM_BUFS);
dev->drw_bitfield = bitfield;
dev->drw_bitfield_length = bitfield_length;
if (info != dev->drw_info) {
- memcpy(info, dev->drw_info, info_length *
- sizeof(*info));
+ if (info)
+ memcpy(info, dev->drw_info, info_length *
+ sizeof(*info));
drm_free(dev->drw_info, sizeof(*info) *
dev->drw_info_length, DRM_MEM_BUFS);
dev->drw_info = info;
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 31cdde83713..30b200b0131 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -102,13 +102,20 @@
{0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \
{0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \
+ {0x1002, 0x5954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
{0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+ {0x1002, 0x5974, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+ {0x1002, 0x5975, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
{0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
+ {0x1002, 0x5a41, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+ {0x1002, 0x5a42, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+ {0x1002, 0x5a61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
+ {0x1002, 0x5a62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \
{0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
{0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
{0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \
@@ -212,6 +219,8 @@
{0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
{0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x18CA, 0x0040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
+ {0x18CA, 0x0042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \
{0, 0, 0}
#define tdfx_PCI_IDS \
@@ -293,10 +302,15 @@
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x27ae, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x29b2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x29c2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x29d2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2a02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x2a12, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 1ba15d9a171..ea52740af4f 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -35,7 +35,12 @@
dev->pci_device == 0x2982 || \
dev->pci_device == 0x2992 || \
dev->pci_device == 0x29A2 || \
- dev->pci_device == 0x2A02)
+ dev->pci_device == 0x2A02 || \
+ dev->pci_device == 0x2A12)
+
+#define IS_G33(dev) (dev->pci_device == 0x29b2 || \
+ dev->pci_device == 0x29c2 || \
+ dev->pci_device == 0x29d2)
/* Really want an OS-independent resettable timer. Would like to have
* this loop run for (eg) 3 sec, but have the timer reset every time
@@ -106,6 +111,12 @@ static int i915_dma_cleanup(drm_device_t * dev)
I915_WRITE(0x02080, 0x1ffff000);
}
+ if (dev_priv->status_gfx_addr) {
+ dev_priv->status_gfx_addr = 0;
+ drm_core_ioremapfree(&dev_priv->hws_map, dev);
+ I915_WRITE(0x2080, 0x1ffff000);
+ }
+
drm_free(dev->dev_private, sizeof(drm_i915_private_t),
DRM_MEM_DRIVER);
@@ -179,26 +190,24 @@ static int i915_initialize(drm_device_t * dev,
dev_priv->allow_batchbuffer = 1;
/* Program Hardware Status Page */
- dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE,
- 0xffffffff);
+ if (!IS_G33(dev)) {
+ dev_priv->status_page_dmah =
+ drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff);
+
+ if (!dev_priv->status_page_dmah) {
+ dev->dev_private = (void *)dev_priv;
+ i915_dma_cleanup(dev);
+ DRM_ERROR("Can not allocate hardware status page\n");
+ return DRM_ERR(ENOMEM);
+ }
+ dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
+ dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
- if (!dev_priv->status_page_dmah) {
- dev->dev_private = (void *)dev_priv;
- i915_dma_cleanup(dev);
- DRM_ERROR("Can not allocate hardware status page\n");
- return DRM_ERR(ENOMEM);
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ I915_WRITE(0x02080, dev_priv->dma_status_page);
}
- dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr;
- dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
-
- memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
- I915_WRITE(0x02080, dev_priv->dma_status_page);
DRM_DEBUG("Enabled hardware status page\n");
-
dev->dev_private = (void *)dev_priv;
-
return 0;
}
@@ -231,7 +240,10 @@ static int i915_dma_resume(drm_device_t * dev)
}
DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
- I915_WRITE(0x02080, dev_priv->dma_status_page);
+ if (dev_priv->status_gfx_addr != 0)
+ I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+ else
+ I915_WRITE(0x02080, dev_priv->dma_status_page);
DRM_DEBUG("Enabled hardware status page\n");
return 0;
@@ -739,6 +751,47 @@ static int i915_setparam(DRM_IOCTL_ARGS)
return 0;
}
+static int i915_set_status_page(DRM_IOCTL_ARGS)
+{
+ DRM_DEVICE;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ drm_i915_hws_addr_t hws;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+ DRM_COPY_FROM_USER_IOCTL(hws, (drm_i915_hws_addr_t __user *) data,
+ sizeof(hws));
+ printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws.addr);
+
+ dev_priv->status_gfx_addr = hws.addr & (0x1ffff<<12);
+
+ dev_priv->hws_map.offset = dev->agp->agp_info.aper_base + hws.addr;
+ dev_priv->hws_map.size = 4*1024;
+ dev_priv->hws_map.type = 0;
+ dev_priv->hws_map.flags = 0;
+ dev_priv->hws_map.mtrr = 0;
+
+ drm_core_ioremap(&dev_priv->hws_map, dev);
+ if (dev_priv->hws_map.handle == NULL) {
+ dev->dev_private = (void *)dev_priv;
+ i915_dma_cleanup(dev);
+ dev_priv->status_gfx_addr = 0;
+ DRM_ERROR("can not ioremap virtual address for"
+ " G33 hw status page\n");
+ return DRM_ERR(ENOMEM);
+ }
+ dev_priv->hw_status_page = dev_priv->hws_map.handle;
+
+ memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
+ I915_WRITE(0x02080, dev_priv->status_gfx_addr);
+ DRM_DEBUG("load hws 0x2080 with gfx mem 0x%x\n",
+ dev_priv->status_gfx_addr);
+ DRM_DEBUG("load hws at %p\n", dev_priv->hw_status_page);
+ return 0;
+}
+
int i915_driver_load(drm_device_t *dev, unsigned long flags)
{
/* i915 has 4 more counters */
@@ -785,6 +838,7 @@ drm_ioctl_desc_t i915_ioctls[] = {
[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
[DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH},
+ [DRM_IOCTL_NR(DRM_I915_HWS_ADDR)] = {i915_set_status_page, DRM_AUTH},
};
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 96a468886a7..7b7b68b96f3 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -142,6 +142,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_SET_VBLANK_PIPE 0x0d
#define DRM_I915_GET_VBLANK_PIPE 0x0e
#define DRM_I915_VBLANK_SWAP 0x0f
+#define DRM_I915_HWS_ADDR 0x11
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -262,4 +263,8 @@ typedef struct drm_i915_vblank_swap {
unsigned int sequence;
} drm_i915_vblank_swap_t;
+typedef struct drm_i915_hws_addr {
+ uint64_t addr;
+} drm_i915_hws_addr_t;
+
#endif /* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 93cdcfe6aa8..85e323acb95 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -91,6 +91,8 @@ typedef struct drm_i915_private {
void *hw_status_page;
dma_addr_t dma_status_page;
unsigned long counter;
+ unsigned int status_gfx_addr;
+ drm_local_map_t hws_map;
unsigned int cpp;
int back_offset;
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 78c1ae28f17..b92062a239f 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -582,7 +582,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&dev_priv->swaps_lock);
INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
dev_priv->swaps_pending = 0;
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
index 1f1f9cc055a..56decda2a71 100644
--- a/drivers/char/drm/radeon_ioc32.c
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -349,6 +349,36 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request);
}
+/* The two 64-bit arches where alignof(u64)==4 in 32-bit code */
+#if defined (CONFIG_X86_64) || defined(CONFIG_IA64)
+typedef struct drm_radeon_setparam32 {
+ int param;
+ u64 value;
+} __attribute__((packed)) drm_radeon_setparam32_t;
+
+static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_setparam32_t req32;
+ drm_radeon_setparam_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.param, &request->param)
+ || __put_user((void __user *)(unsigned long)req32.value,
+ &request->value))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request);
+}
+#else
+#define compat_radeon_cp_setparam NULL
+#endif /* X86_64 || IA64 */
+
drm_ioctl_compat_t *radeon_compat_ioctls[] = {
[DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
[DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
@@ -357,6 +387,7 @@ drm_ioctl_compat_t *radeon_compat_ioctls[] = {
[DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
[DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
[DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
+ [DRM_RADEON_SETPARAM] = compat_radeon_cp_setparam,
[DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
[DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
};
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index 2b8d6f6ed7c..70d4ede75fe 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -33,11 +33,11 @@
#define DRIVER_AUTHOR "SIS, Tungsten Graphics"
#define DRIVER_NAME "sis"
-#define DRIVER_DESC "SIS 300/630/540"
-#define DRIVER_DATE "20060704"
+#define DRIVER_DESC "SIS 300/630/540 and XGI V3XE/V5/V8"
+#define DRIVER_DATE "20070626"
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 2
-#define DRIVER_PATCHLEVEL 1
+#define DRIVER_MINOR 3
+#define DRIVER_PATCHLEVEL 0
enum sis_family {
SIS_OTHER = 0,
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 8e222f2b80c..b5df7e61aeb 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2171,52 +2171,42 @@ static int create_files(struct bmc_device *bmc)
int err;
bmc->device_id_attr.attr.name = "device_id";
- bmc->device_id_attr.attr.owner = THIS_MODULE;
bmc->device_id_attr.attr.mode = S_IRUGO;
bmc->device_id_attr.show = device_id_show;
bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs";
- bmc->provides_dev_sdrs_attr.attr.owner = THIS_MODULE;
bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO;
bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show;
bmc->revision_attr.attr.name = "revision";
- bmc->revision_attr.attr.owner = THIS_MODULE;
bmc->revision_attr.attr.mode = S_IRUGO;
bmc->revision_attr.show = revision_show;
bmc->firmware_rev_attr.attr.name = "firmware_revision";
- bmc->firmware_rev_attr.attr.owner = THIS_MODULE;
bmc->firmware_rev_attr.attr.mode = S_IRUGO;
bmc->firmware_rev_attr.show = firmware_rev_show;
bmc->version_attr.attr.name = "ipmi_version";
- bmc->version_attr.attr.owner = THIS_MODULE;
bmc->version_attr.attr.mode = S_IRUGO;
bmc->version_attr.show = ipmi_version_show;
bmc->add_dev_support_attr.attr.name = "additional_device_support";
- bmc->add_dev_support_attr.attr.owner = THIS_MODULE;
bmc->add_dev_support_attr.attr.mode = S_IRUGO;
bmc->add_dev_support_attr.show = add_dev_support_show;
bmc->manufacturer_id_attr.attr.name = "manufacturer_id";
- bmc->manufacturer_id_attr.attr.owner = THIS_MODULE;
bmc->manufacturer_id_attr.attr.mode = S_IRUGO;
bmc->manufacturer_id_attr.show = manufacturer_id_show;
bmc->product_id_attr.attr.name = "product_id";
- bmc->product_id_attr.attr.owner = THIS_MODULE;
bmc->product_id_attr.attr.mode = S_IRUGO;
bmc->product_id_attr.show = product_id_show;
bmc->guid_attr.attr.name = "guid";
- bmc->guid_attr.attr.owner = THIS_MODULE;
bmc->guid_attr.attr.mode = S_IRUGO;
bmc->guid_attr.show = guid_show;
bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision";
- bmc->aux_firmware_rev_attr.attr.owner = THIS_MODULE;
bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO;
bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show;
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 1b094509b1d..90965b4def5 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -1005,8 +1005,8 @@ static const unsigned short x86_keycodes[256] =
284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339,
367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349,
360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355,
- 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361,
- 291,108,381,281,290,272,292,305,280, 99,112,257,258,359,113,114,
+ 103,104,105,275,287,279,258,106,274,107,294,364,358,363,362,361,
+ 291,108,381,281,290,272,292,305,280, 99,112,257,306,359,113,114,
264,117,271,374,379,265,266, 93, 94, 95, 85,259,375,260, 90,116,
377,109,111,277,278,282,283,295,296,297,299,300,301,293,303,307,
308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index cc9a9d0df97..bbee97ff355 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -24,7 +24,7 @@
#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
#include <linux/bootmem.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
#include <linux/pfn.h>
#include <asm/uaccess.h>
@@ -75,6 +75,13 @@ static inline int uncached_access(struct file *file, unsigned long addr)
* On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
*/
return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
+#elif defined(CONFIG_MIPS)
+ {
+ extern int __uncached_access(struct file *file,
+ unsigned long addr);
+
+ return __uncached_access(file, addr);
+ }
#else
/*
* Accessing memory above the top the kernel knows about or through a file pointer
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index b3d4ccc33a4..154f42203b0 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1191,6 +1191,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
is_current_pgrp_orphaned())
return -EIO;
kill_pgrp(task_pgrp(current), SIGTTIN, 1);
+ set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}
}
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0474cac4a84..7f5271272f9 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -794,7 +794,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
buf[0] ^= buf[3];
buf[1] ^= buf[4];
- buf[0] ^= rol32(buf[3], 16);
+ buf[2] ^= rol32(buf[2], 16);
memcpy(out, buf, EXTRACT_SIZE);
memset(buf, 0, sizeof(buf));
}
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index e45113a7a47..8c73ccb8830 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -2172,11 +2172,12 @@ static int __devinit stl_initech(struct stlbrd *brdp)
}
status = inb(ioaddr + ECH_PNLSTATUS);
if ((status & ECH_PNLIDMASK) != nxtid)
- goto err_fr;
+ break;
panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
if (!panelp) {
printk("STALLION: failed to allocate memory "
"(size=%Zd)\n", sizeof(struct stlpanel));
+ retval = -ENOMEM;
goto err_fr;
}
panelp->magic = STL_PANELMAGIC;
@@ -2223,8 +2224,10 @@ static int __devinit stl_initech(struct stlbrd *brdp)
brdp->nrports += panelp->nrports;
brdp->panels[panelnr++] = panelp;
if ((brdp->brdtype != BRD_ECHPCI) &&
- (ioaddr >= (brdp->ioaddr2 + brdp->iosize2)))
+ (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
+ retval = -EINVAL;
goto err_fr;
+ }
}
brdp->nrpanels = panelnr;
@@ -2371,6 +2374,7 @@ static int __devinit stl_pciprobe(struct pci_dev *pdev,
dev_err(&pdev->dev, "too many boards found, "
"maximum supported %d\n", STL_MAXBRDS);
mutex_unlock(&stl_brdslock);
+ retval = -ENODEV;
goto err_fr;
}
brdp->brdnr = (unsigned int)brdnr;
@@ -4710,6 +4714,29 @@ static int __init stallion_module_init(void)
spin_lock_init(&stallion_lock);
spin_lock_init(&brd_lock);
+ stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+ if (!stl_serial) {
+ retval = -ENOMEM;
+ goto err;
+ }
+
+ stl_serial->owner = THIS_MODULE;
+ stl_serial->driver_name = stl_drvname;
+ stl_serial->name = "ttyE";
+ stl_serial->major = STL_SERIALMAJOR;
+ stl_serial->minor_start = 0;
+ stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
+ stl_serial->subtype = SERIAL_TYPE_NORMAL;
+ stl_serial->init_termios = stl_deftermios;
+ stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ tty_set_operations(stl_serial, &stl_ops);
+
+ retval = tty_register_driver(stl_serial);
+ if (retval) {
+ printk("STALLION: failed to register serial driver\n");
+ goto err_frtty;
+ }
+
/*
* Find any dynamically supported boards. That is via module load
* line options.
@@ -4726,26 +4753,23 @@ static int __init stallion_module_init(void)
brdp->ioaddr2 = conf.ioaddr2;
brdp->irq = conf.irq;
brdp->irqtype = conf.irqtype;
- if (stl_brdinit(brdp))
+ stl_brds[brdp->brdnr] = brdp;
+ if (stl_brdinit(brdp)) {
+ stl_brds[brdp->brdnr] = NULL;
kfree(brdp);
- else {
+ } else {
for (j = 0; j < brdp->nrports; j++)
tty_register_device(stl_serial,
brdp->brdnr * STL_MAXPORTS + j, NULL);
- stl_brds[brdp->brdnr] = brdp;
stl_nrbrds = i + 1;
}
}
/* this has to be _after_ isa finding because of locking */
retval = pci_register_driver(&stl_pcidriver);
- if (retval && stl_nrbrds == 0)
- goto err;
-
- stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
- if (!stl_serial) {
- retval = -ENOMEM;
- goto err_pcidr;
+ if (retval && stl_nrbrds == 0) {
+ printk(KERN_ERR "STALLION: can't register pci driver\n");
+ goto err_unrtty;
}
/*
@@ -4756,43 +4780,18 @@ static int __init stallion_module_init(void)
printk("STALLION: failed to register serial board device\n");
stallion_class = class_create(THIS_MODULE, "staliomem");
- if (IS_ERR(stallion_class)) {
- retval = PTR_ERR(stallion_class);
- goto err_reg;
- }
+ if (IS_ERR(stallion_class))
+ printk("STALLION: failed to create class\n");
for (i = 0; i < 4; i++)
class_device_create(stallion_class, NULL,
MKDEV(STL_SIOMEMMAJOR, i), NULL,
"staliomem%d", i);
- stl_serial->owner = THIS_MODULE;
- stl_serial->driver_name = stl_drvname;
- stl_serial->name = "ttyE";
- stl_serial->major = STL_SERIALMAJOR;
- stl_serial->minor_start = 0;
- stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
- stl_serial->subtype = SERIAL_TYPE_NORMAL;
- stl_serial->init_termios = stl_deftermios;
- stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- tty_set_operations(stl_serial, &stl_ops);
-
- retval = tty_register_driver(stl_serial);
- if (retval) {
- printk("STALLION: failed to register serial driver\n");
- goto err_clsdev;
- }
-
return 0;
-err_clsdev:
- for (i = 0; i < 4; i++)
- class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
- class_destroy(stallion_class);
-err_reg:
- unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+err_unrtty:
+ tty_unregister_driver(stl_serial);
+err_frtty:
put_tty_driver(stl_serial);
-err_pcidr:
- pci_unregister_driver(&stl_pcidriver);
- stl_free_isabrds();
err:
return retval;
}
@@ -4821,8 +4820,6 @@ static void __exit stallion_module_exit(void)
tty_unregister_device(stl_serial,
brdp->brdnr * STL_MAXPORTS + j);
}
- tty_unregister_driver(stl_serial);
- put_tty_driver(stl_serial);
for (i = 0; i < 4; i++)
class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
@@ -4834,6 +4831,9 @@ static void __exit stallion_module_exit(void)
pci_unregister_driver(&stl_pcidriver);
stl_free_isabrds();
+
+ tty_unregister_driver(stl_serial);
+ put_tty_driver(stl_serial);
}
module_init(stallion_module_init);
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 1da92a689ae..85a23283dff 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2721,9 +2721,9 @@ static void __devexit sx_pci_remove(struct pci_dev *pdev)
its because the standard requires it. So check for SUBVENDOR_ID. */
static struct pci_device_id sx_pci_tbl[] = {
{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
- .subvendor = 0x0200,.subdevice = PCI_ANY_ID },
+ .subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
- .subvendor = 0x0300,.subdevice = PCI_ANY_ID },
+ .subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
{ 0 }
};
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 75d2a46e106..a96f26a63fa 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1148,7 +1148,8 @@ int tty_check_change(struct tty_struct * tty)
return 0;
if (is_current_pgrp_orphaned())
return -EIO;
- (void) kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+ kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+ set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}
@@ -1172,8 +1173,14 @@ static unsigned int hung_up_tty_poll(struct file * filp, poll_table * wait)
return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
}
-static long hung_up_tty_ioctl(struct file * file,
- unsigned int cmd, unsigned long arg)
+static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
+}
+
+static long hung_up_tty_compat_ioctl(struct file * file,
+ unsigned int cmd, unsigned long arg)
{
return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
}
@@ -1221,8 +1228,8 @@ static const struct file_operations hung_up_tty_fops = {
.read = hung_up_tty_read,
.write = hung_up_tty_write,
.poll = hung_up_tty_poll,
- .unlocked_ioctl = hung_up_tty_ioctl,
- .compat_ioctl = hung_up_tty_ioctl,
+ .ioctl = hung_up_tty_ioctl,
+ .compat_ioctl = hung_up_tty_compat_ioctl,
.release = tty_release,
};
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
index 0cea8d4907d..e5ed09192be 100644
--- a/drivers/char/vr41xx_giu.c
+++ b/drivers/char/vr41xx_giu.c
@@ -19,18 +19,17 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
-#include <linux/irq.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/types.h>
-#include <asm/cpu.h>
#include <asm/io.h>
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/irq.h>
@@ -44,18 +43,6 @@ static int major; /* default is dynamic major device number */
module_param(major, int, 0);
MODULE_PARM_DESC(major, "Major device number");
-#define GIU_TYPE1_START 0x0b000100UL
-#define GIU_TYPE1_SIZE 0x20UL
-
-#define GIU_TYPE2_START 0x0f000140UL
-#define GIU_TYPE2_SIZE 0x20UL
-
-#define GIU_TYPE3_START 0x0f000140UL
-#define GIU_TYPE3_SIZE 0x28UL
-
-#define GIU_PULLUPDOWN_START 0x0b0002e0UL
-#define GIU_PULLUPDOWN_SIZE 0x04UL
-
#define GIUIOSELL 0x00
#define GIUIOSELH 0x02
#define GIUPIODL 0x04
@@ -89,8 +76,6 @@ MODULE_PARM_DESC(major, "Major device number");
#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
static spinlock_t giu_lock;
-static struct resource *giu_resource1;
-static struct resource *giu_resource2;
static unsigned long giu_flags;
static unsigned int giu_nr_pins;
@@ -234,7 +219,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
giu_set(GIUINTHTSELL, mask);
else
giu_clear(GIUINTHTSELL, mask);
- if (current_cpu_data.cputype == CPU_VR4133) {
+ if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
switch (trigger) {
case IRQ_TRIGGER_EDGE_FALLING:
giu_set(GIUFEDGEINHL, mask);
@@ -269,7 +254,7 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
giu_set(GIUINTHTSELH, mask);
else
giu_clear(GIUINTHTSELH, mask);
- if (current_cpu_data.cputype == CPU_VR4133) {
+ if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
switch (trigger) {
case IRQ_TRIGGER_EDGE_FALLING:
giu_set(GIUFEDGEINHH, mask);
@@ -298,7 +283,6 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
giu_write(GIUINTSTATH, mask);
}
}
-
EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
@@ -321,7 +305,6 @@ void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
giu_write(GIUINTSTATH, mask);
}
}
-
EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
@@ -350,7 +333,6 @@ gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
return GPIO_DATA_LOW;
}
-
EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
@@ -388,7 +370,6 @@ int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
return 0;
}
-
EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
@@ -438,7 +419,6 @@ int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
return 0;
}
-
EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
@@ -477,7 +457,6 @@ int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
return 0;
}
-
EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
@@ -596,61 +575,40 @@ static const struct file_operations gpio_fops = {
static int __devinit giu_probe(struct platform_device *dev)
{
- unsigned long start, size, flags = 0;
- unsigned int nr_pins = 0, trigger, i, pin;
- struct resource *res1, *res2 = NULL;
- void *base;
+ struct resource *res;
+ unsigned int trigger, i, pin;
struct irq_chip *chip;
- int retval;
-
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- start = GIU_TYPE1_START;
- size = GIU_TYPE1_SIZE;
- flags = GPIO_HAS_PULLUPDOWN_IO;
- nr_pins = 50;
+ int irq, retval;
+
+ switch (dev->id) {
+ case GPIO_50PINS_PULLUPDOWN:
+ giu_flags = GPIO_HAS_PULLUPDOWN_IO;
+ giu_nr_pins = 50;
break;
- case CPU_VR4122:
- case CPU_VR4131:
- start = GIU_TYPE2_START;
- size = GIU_TYPE2_SIZE;
- nr_pins = 36;
+ case GPIO_36PINS:
+ giu_nr_pins = 36;
break;
- case CPU_VR4133:
- start = GIU_TYPE3_START;
- size = GIU_TYPE3_SIZE;
- flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
- nr_pins = 48;
+ case GPIO_48PINS_EDGE_SELECT:
+ giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+ giu_nr_pins = 48;
break;
default:
+ printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
return -ENODEV;
}
- res1 = request_mem_region(start, size, "GIU");
- if (res1 == NULL)
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res)
return -EBUSY;
- base = ioremap(start, size);
- if (base == NULL) {
- release_resource(res1);
+ giu_base = ioremap(res->start, res->end - res->start + 1);
+ if (!giu_base)
return -ENOMEM;
- }
-
- if (flags & GPIO_HAS_PULLUPDOWN_IO) {
- res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
- if (res2 == NULL) {
- iounmap(base);
- release_resource(res1);
- return -EBUSY;
- }
- }
retval = register_chrdev(major, "GIU", &gpio_fops);
if (retval < 0) {
- iounmap(base);
- release_resource(res1);
- release_resource(res2);
+ iounmap(giu_base);
+ giu_base = NULL;
return retval;
}
@@ -660,11 +618,6 @@ static int __devinit giu_probe(struct platform_device *dev)
}
spin_lock_init(&giu_lock);
- giu_base = base;
- giu_resource1 = res1;
- giu_resource2 = res2;
- giu_flags = flags;
- giu_nr_pins = nr_pins;
giu_write(GIUINTENL, 0);
giu_write(GIUINTENH, 0);
@@ -685,22 +638,23 @@ static int __devinit giu_probe(struct platform_device *dev)
}
- return cascade_irq(GIUINT_IRQ, giu_get_irq);
+ irq = platform_get_irq(dev, 0);
+ if (irq < 0 || irq >= NR_IRQS)
+ return -EBUSY;
+
+ return cascade_irq(irq, giu_get_irq);
}
static int __devexit giu_remove(struct platform_device *dev)
{
- iounmap(giu_base);
-
- release_resource(giu_resource1);
- if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
- release_resource(giu_resource2);
+ if (giu_base) {
+ iounmap(giu_base);
+ giu_base = NULL;
+ }
return 0;
}
-static struct platform_device *giu_platform_device;
-
static struct platform_driver giu_device_driver = {
.probe = giu_probe,
.remove = __devexit_p(giu_remove),
@@ -712,30 +666,12 @@ static struct platform_driver giu_device_driver = {
static int __init vr41xx_giu_init(void)
{
- int retval;
-
- giu_platform_device = platform_device_alloc("GIU", -1);
- if (!giu_platform_device)
- return -ENOMEM;
-
- retval = platform_device_add(giu_platform_device);
- if (retval < 0) {
- platform_device_put(giu_platform_device);
- return retval;
- }
-
- retval = platform_driver_register(&giu_device_driver);
- if (retval < 0)
- platform_device_unregister(giu_platform_device);
-
- return retval;
+ return platform_driver_register(&giu_device_driver);
}
static void __exit vr41xx_giu_exit(void)
{
platform_driver_unregister(&giu_device_driver);
-
- platform_device_unregister(giu_platform_device);
}
module_init(vr41xx_giu_init);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index bbd9fc41287..6650ae1c088 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -1956,7 +1956,7 @@ char con_buf[CON_BUF_SIZE];
DEFINE_MUTEX(con_buf_mtx);
/* is_double_width() is based on the wcwidth() implementation by
- * Markus Kuhn -- 2003-05-20 (Unicode 4.0)
+ * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
*/
struct interval {
@@ -1988,8 +1988,8 @@ static int is_double_width(uint32_t ucs)
static const struct interval double_width[] = {
{ 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E },
{ 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF },
- { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, { 0xFFE0, 0xFFE6 },
- { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
+ { 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 },
+ { 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
};
return bisearch(ucs, double_width,
sizeof(double_width) / sizeof(*double_width) - 1);
@@ -2187,9 +2187,12 @@ rescan_last_byte:
continue; /* nothing to display */
}
/* Glyph not found */
- if (!(vc->vc_utf && !vc->vc_disp_ctrl) && !(c & ~charmask)) {
+ if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) {
/* In legacy mode use the glyph we get by a 1:1 mapping.
- This would make absolutely no sense with Unicode in mind. */
+ This would make absolutely no sense with Unicode in mind,
+ but do this for ASCII characters since a font may lack
+ Unicode mapping info and we don't want to end up with
+ having question marks only. */
tc = c;
} else {
/* Display U+FFFD. If it's not found, display an inverse question mark. */
@@ -2213,6 +2216,7 @@ rescan_last_byte:
} else {
vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
}
+ FLUSH
}
while (1) {
@@ -2246,6 +2250,10 @@ rescan_last_byte:
if (tc < 0) tc = ' ';
}
+ if (inverse) {
+ FLUSH
+ }
+
if (rescan) {
rescan = 0;
inverse = 0;
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 1cad32c62ed..53f5538c0c0 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -115,6 +115,13 @@ config IXP4XX_WATCHDOG
Say N if you are unsure.
+config KS8695_WATCHDOG
+ tristate "KS8695 watchdog"
+ depends on ARCH_KS8695
+ help
+ Watchdog timer embedded into KS8695 processor. This will reboot your
+ system when the timeout is reached.
+
config S3C2410_WATCHDOG
tristate "S3C2410 Watchdog"
depends on ARCH_S3C2410
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 8bfc00cc7c2..d90f649038c 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
obj-$(CONFIG_977_WATCHDOG) += wdt977.o
obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
+obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index fd955dbd588..dc7548dcaf3 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -205,7 +205,7 @@ static void __exit ixp2000_wdt_exit(void)
module_init(ixp2000_wdt_init);
module_exit(ixp2000_wdt_exit);
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net">);
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
MODULE_DESCRIPTION("IXP2000 Network Processor Watchdog");
module_param(heartbeat, int, 0);
diff --git a/drivers/char/watchdog/ks8695_wdt.c b/drivers/char/watchdog/ks8695_wdt.c
new file mode 100644
index 00000000000..7150fb945ea
--- /dev/null
+++ b/drivers/char/watchdog/ks8695_wdt.c
@@ -0,0 +1,308 @@
+/*
+ * Watchdog driver for Kendin/Micrel KS8695.
+ *
+ * (C) 2007 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/arch/regs-timer.h>
+
+
+#define WDT_DEFAULT_TIME 5 /* seconds */
+#define WDT_MAX_TIME 171 /* seconds */
+
+static int wdt_time = WDT_DEFAULT_TIME;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(wdt_time, int, 0);
+MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")");
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+#endif
+
+
+static unsigned long ks8695wdt_busy;
+
+/* ......................................................................... */
+
+/*
+ * Disable the watchdog.
+ */
+static void inline ks8695_wdt_stop(void)
+{
+ unsigned long tmcon;
+
+ /* disable timer0 */
+ tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
+ __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+}
+
+/*
+ * Enable and reset the watchdog.
+ */
+static void inline ks8695_wdt_start(void)
+{
+ unsigned long tmcon;
+ unsigned long tval = wdt_time * CLOCK_TICK_RATE;
+
+ /* disable timer0 */
+ tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
+ __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+
+ /* program timer0 */
+ __raw_writel(tval | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC);
+
+ /* re-enable timer0 */
+ tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
+ __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+}
+
+/*
+ * Reload the watchdog timer. (ie, pat the watchdog)
+ */
+static void inline ks8695_wdt_reload(void)
+{
+ unsigned long tmcon;
+
+ /* disable, then re-enable timer0 */
+ tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
+ __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+ __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+}
+
+/*
+ * Change the watchdog time interval.
+ */
+static int ks8695_wdt_settimeout(int new_time)
+{
+ /*
+ * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+ *
+ * Since WDV is a 16-bit counter, the maximum period is
+ * 65536 / 0.256 = 256 seconds.
+ */
+ if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
+ return -EINVAL;
+
+ /* Set new watchdog time. It will be used when ks8695_wdt_start() is called. */
+ wdt_time = new_time;
+ return 0;
+}
+
+/* ......................................................................... */
+
+/*
+ * Watchdog device is opened, and watchdog starts running.
+ */
+static int ks8695_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, &ks8695wdt_busy))
+ return -EBUSY;
+
+ ks8695_wdt_start();
+ return nonseekable_open(inode, file);
+}
+
+/*
+ * Close the watchdog device.
+ * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also
+ * disabled.
+ */
+static int ks8695_wdt_close(struct inode *inode, struct file *file)
+{
+ if (!nowayout)
+ ks8695_wdt_stop(); /* Disable the watchdog when file is closed */
+
+ clear_bit(0, &ks8695wdt_busy);
+ return 0;
+}
+
+static struct watchdog_info ks8695_wdt_info = {
+ .identity = "ks8695 watchdog",
+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+};
+
+/*
+ * Handle commands from user-space.
+ */
+static int ks8695_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int new_value;
+
+ switch(cmd) {
+ case WDIOC_KEEPALIVE:
+ ks8695_wdt_reload(); /* pat the watchdog */
+ return 0;
+
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ks8695_wdt_info, sizeof(ks8695_wdt_info)) ? -EFAULT : 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_value, p))
+ return -EFAULT;
+
+ if (ks8695_wdt_settimeout(new_value))
+ return -EINVAL;
+
+ /* Enable new time value */
+ ks8695_wdt_start();
+
+ /* Return current value */
+ return put_user(wdt_time, p);
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(wdt_time, p);
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_SETOPTIONS:
+ if (get_user(new_value, p))
+ return -EFAULT;
+
+ if (new_value & WDIOS_DISABLECARD)
+ ks8695_wdt_stop();
+ if (new_value & WDIOS_ENABLECARD)
+ ks8695_wdt_start();
+ return 0;
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+/*
+ * Pat the watchdog whenever device is written to.
+ */
+static ssize_t ks8695_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+ ks8695_wdt_reload(); /* pat the watchdog */
+ return len;
+}
+
+/* ......................................................................... */
+
+static const struct file_operations ks8695wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .ioctl = ks8695_wdt_ioctl,
+ .open = ks8695_wdt_open,
+ .release = ks8695_wdt_close,
+ .write = ks8695_wdt_write,
+};
+
+static struct miscdevice ks8695wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &ks8695wdt_fops,
+};
+
+static int __init ks8695wdt_probe(struct platform_device *pdev)
+{
+ int res;
+
+ if (ks8695wdt_miscdev.parent)
+ return -EBUSY;
+ ks8695wdt_miscdev.parent = &pdev->dev;
+
+ res = misc_register(&ks8695wdt_miscdev);
+ if (res)
+ return res;
+
+ printk("KS8695 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : "");
+ return 0;
+}
+
+static int __exit ks8695wdt_remove(struct platform_device *pdev)
+{
+ int res;
+
+ res = misc_deregister(&ks8695wdt_miscdev);
+ if (!res)
+ ks8695wdt_miscdev.parent = NULL;
+
+ return res;
+}
+
+static void ks8695wdt_shutdown(struct platform_device *pdev)
+{
+ ks8695_wdt_stop();
+}
+
+#ifdef CONFIG_PM
+
+static int ks8695wdt_suspend(struct platform_device *pdev, pm_message_t message)
+{
+ ks8695_wdt_stop();
+ return 0;
+}
+
+static int ks8695wdt_resume(struct platform_device *pdev)
+{
+ if (ks8695wdt_busy)
+ ks8695_wdt_start();
+ return 0;
+}
+
+#else
+#define ks8695wdt_suspend NULL
+#define ks8695wdt_resume NULL
+#endif
+
+static struct platform_driver ks8695wdt_driver = {
+ .probe = ks8695wdt_probe,
+ .remove = __exit_p(ks8695wdt_remove),
+ .shutdown = ks8695wdt_shutdown,
+ .suspend = ks8695wdt_suspend,
+ .resume = ks8695wdt_resume,
+ .driver = {
+ .name = "ks8695_wdt",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ks8695_wdt_init(void)
+{
+ /* Check that the heartbeat value is within range; if not reset to the default */
+ if (ks8695_wdt_settimeout(wdt_time)) {
+ ks8695_wdt_settimeout(WDT_DEFAULT_TIME);
+ pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i, using %d\n", wdt_time, WDT_MAX_TIME);
+ }
+
+ return platform_driver_register(&ks8695wdt_driver);
+}
+
+static void __exit ks8695_wdt_exit(void)
+{
+ platform_driver_unregister(&ks8695wdt_driver);
+}
+
+module_init(ks8695_wdt_init);
+module_exit(ks8695_wdt_exit);
+
+MODULE_AUTHOR("Andrew Victor");
+MODULE_DESCRIPTION("Watchdog driver for KS8695");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 5cfcff53254..e783dbf0f16 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -105,14 +105,11 @@ static inline void acpi_pm_need_workaround(void)
*/
static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev)
{
- u8 rev;
-
if (acpi_pm_good)
return;
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
/* the bug has been fixed in PIIX4M */
- if (rev < 3) {
+ if (dev->revision < 3) {
printk(KERN_WARNING "* Found PM-Timer Bug on the chipset."
" Due to workarounds for a bug,\n"
"* this clock source is slow. Consider trying"
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index eb37fba9b7e..2f6a73c01b7 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -39,6 +39,10 @@
*/
static struct cpufreq_driver *cpufreq_driver;
static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS];
+#ifdef CONFIG_HOTPLUG_CPU
+/* This one keeps track of the previously set governor of a removed CPU */
+static struct cpufreq_governor *cpufreq_cpu_governor[NR_CPUS];
+#endif
static DEFINE_SPINLOCK(cpufreq_driver_lock);
/*
@@ -770,9 +774,17 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
}
policy->user_policy.min = policy->cpuinfo.min_freq;
policy->user_policy.max = policy->cpuinfo.max_freq;
- policy->user_policy.governor = policy->governor;
#ifdef CONFIG_SMP
+
+#ifdef CONFIG_HOTPLUG_CPU
+ if (cpufreq_cpu_governor[cpu]){
+ policy->governor = cpufreq_cpu_governor[cpu];
+ dprintk("Restoring governor %s for cpu %d\n",
+ policy->governor->name, cpu);
+ }
+#endif
+
for_each_cpu_mask(j, policy->cpus) {
if (cpu == j)
continue;
@@ -826,13 +838,21 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
/* set up files for this cpu device */
drv_attr = cpufreq_driver->attr;
while ((drv_attr) && (*drv_attr)) {
- sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+ ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
+ if (ret)
+ goto err_out_driver_exit;
drv_attr++;
}
- if (cpufreq_driver->get)
- sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
- if (cpufreq_driver->target)
- sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+ if (cpufreq_driver->get){
+ ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
+ if (ret)
+ goto err_out_driver_exit;
+ }
+ if (cpufreq_driver->target){
+ ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
+ if (ret)
+ goto err_out_driver_exit;
+ }
spin_lock_irqsave(&cpufreq_driver_lock, flags);
for_each_cpu_mask(j, policy->cpus) {
@@ -865,6 +885,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
/* set default policy */
ret = __cpufreq_set_policy(policy, &new_policy);
policy->user_policy.policy = policy->policy;
+ policy->user_policy.governor = policy->governor;
unlock_policy_rwsem_write(cpu);
@@ -961,6 +982,11 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
}
#ifdef CONFIG_SMP
+
+#ifdef CONFIG_HOTPLUG_CPU
+ cpufreq_cpu_governor[cpu] = data->governor;
+#endif
+
/* if we have other CPUs still registered, we need to unlink them,
* or else wait_for_completion below will lock up. Clean the
* cpufreq_cpu_data[] while holding the lock, and remove the sysfs
@@ -981,6 +1007,9 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
if (j == cpu)
continue;
dprintk("removing link for cpu %u\n", j);
+#ifdef CONFIG_HOTPLUG_CPU
+ cpufreq_cpu_governor[j] = data->governor;
+#endif
cpu_sys_dev = get_cpu_sysdev(j);
sysfs_remove_link(&cpu_sys_dev->kobj, "cpufreq");
cpufreq_cpu_put(data);
@@ -1679,7 +1708,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
{
unsigned int cpu = (unsigned long)hcpu;
struct sys_device *sys_dev;
- struct cpufreq_policy *policy;
sys_dev = get_cpu_sysdev(cpu);
if (sys_dev) {
@@ -1693,11 +1721,6 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb,
if (unlikely(lock_policy_rwsem_write(cpu)))
BUG();
- policy = cpufreq_cpu_data[cpu];
- if (policy) {
- __cpufreq_driver_target(policy, policy->min,
- CPUFREQ_RELATION_H);
- }
__cpufreq_remove_dev(sys_dev);
break;
case CPU_DOWN_FAILED:
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 8532bb79e5f..e794527e492 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -96,15 +96,25 @@ static struct dbs_tuners {
static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
{
- cputime64_t retval;
+ cputime64_t idle_time;
+ cputime64_t cur_jiffies;
+ cputime64_t busy_time;
- retval = cputime64_add(kstat_cpu(cpu).cpustat.idle,
- kstat_cpu(cpu).cpustat.iowait);
+ cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
+ busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user,
+ kstat_cpu(cpu).cpustat.system);
- if (dbs_tuners_ins.ignore_nice)
- retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice);
+ busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.irq);
+ busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.softirq);
+ busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.steal);
- return retval;
+ if (!dbs_tuners_ins.ignore_nice) {
+ busy_time = cputime64_add(busy_time,
+ kstat_cpu(cpu).cpustat.nice);
+ }
+
+ idle_time = cputime64_sub(cur_jiffies, busy_time);
+ return idle_time;
}
/*
@@ -325,7 +335,7 @@ static struct attribute_group dbs_attr_group = {
static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
{
unsigned int idle_ticks, total_ticks;
- unsigned int load;
+ unsigned int load = 0;
cputime64_t cur_jiffies;
struct cpufreq_policy *policy;
@@ -339,7 +349,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
total_ticks = (unsigned int) cputime64_sub(cur_jiffies,
this_dbs_info->prev_cpu_wall);
- this_dbs_info->prev_cpu_wall = cur_jiffies;
+ this_dbs_info->prev_cpu_wall = get_jiffies_64();
+
if (!total_ticks)
return;
/*
@@ -370,7 +381,8 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
if (tmp_idle_ticks < idle_ticks)
idle_ticks = tmp_idle_ticks;
}
- load = (100 * (total_ticks - idle_ticks)) / total_ticks;
+ if (likely(total_ticks > idle_ticks))
+ load = (100 * (total_ticks - idle_ticks)) / total_ticks;
/* Check for frequency increase */
if (load > dbs_tuners_ins.up_threshold) {
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index d2f0cbd8b8f..917b9bab9cc 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -25,8 +25,7 @@ static spinlock_t cpufreq_stats_lock;
#define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \
static struct freq_attr _attr_##_name = {\
- .attr = {.name = __stringify(_name), .owner = THIS_MODULE, \
- .mode = _mode, }, \
+ .attr = {.name = __stringify(_name), .mode = _mode, }, \
.show = _show,\
};
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 860345c7799..51bedab6c80 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -37,6 +37,7 @@ static unsigned int cpu_set_freq[NR_CPUS]; /* CPU freq desired by userspace */
static unsigned int cpu_is_managed[NR_CPUS];
static DEFINE_MUTEX (userspace_mutex);
+static int cpus_using_userspace_governor;
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
@@ -47,7 +48,11 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
{
struct cpufreq_freqs *freq = data;
- dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n", freq->cpu, freq->new);
+ if (!cpu_is_managed[freq->cpu])
+ return 0;
+
+ dprintk("saving cpu_cur_freq of cpu %u to be %u kHz\n",
+ freq->cpu, freq->new);
cpu_cur_freq[freq->cpu] = freq->new;
return 0;
@@ -120,7 +125,7 @@ store_speed (struct cpufreq_policy *policy, const char *buf, size_t count)
static struct freq_attr freq_attr_scaling_setspeed =
{
- .attr = { .name = "scaling_setspeed", .mode = 0644, .owner = THIS_MODULE },
+ .attr = { .name = "scaling_setspeed", .mode = 0644 },
.show = show_speed,
.store = store_speed,
};
@@ -142,6 +147,13 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
if (rc)
goto start_out;
+ if (cpus_using_userspace_governor == 0) {
+ cpufreq_register_notifier(
+ &userspace_cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ }
+ cpus_using_userspace_governor++;
+
cpu_is_managed[cpu] = 1;
cpu_min_freq[cpu] = policy->min;
cpu_max_freq[cpu] = policy->max;
@@ -153,6 +165,13 @@ start_out:
break;
case CPUFREQ_GOV_STOP:
mutex_lock(&userspace_mutex);
+ cpus_using_userspace_governor--;
+ if (cpus_using_userspace_governor == 0) {
+ cpufreq_unregister_notifier(
+ &userspace_cpufreq_notifier_block,
+ CPUFREQ_TRANSITION_NOTIFIER);
+ }
+
cpu_is_managed[cpu] = 0;
cpu_min_freq[cpu] = 0;
cpu_max_freq[cpu] = 0;
@@ -198,7 +217,6 @@ EXPORT_SYMBOL(cpufreq_gov_userspace);
static int __init cpufreq_gov_userspace_init(void)
{
- cpufreq_register_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
return cpufreq_register_governor(&cpufreq_gov_userspace);
}
@@ -206,7 +224,6 @@ static int __init cpufreq_gov_userspace_init(void)
static void __exit cpufreq_gov_userspace_exit(void)
{
cpufreq_unregister_governor(&cpufreq_gov_userspace);
- cpufreq_unregister_notifier(&userspace_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
}
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index e7490925fdc..5409f3afb3f 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -199,7 +199,6 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
.attr = { .name = "scaling_available_frequencies",
.mode = 0444,
- .owner=THIS_MODULE
},
.show = show_available_freqs,
};
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 72be6c63edf..b31756d5997 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -8,8 +8,8 @@ menu "DMA Engine support"
config DMA_ENGINE
bool "Support for DMA engines"
---help---
- DMA engines offload copy operations from the CPU to dedicated
- hardware, allowing the copies to happen asynchronously.
+ DMA engines offload bulk memory operations from the CPU to dedicated
+ hardware, allowing the operations to happen asynchronously.
comment "DMA Clients"
@@ -32,4 +32,12 @@ config INTEL_IOATDMA
---help---
Enable support for the Intel(R) I/OAT DMA engine.
+config INTEL_IOP_ADMA
+ tristate "Intel IOP ADMA support"
+ depends on DMA_ENGINE && (ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX)
+ select ASYNC_CORE
+ default m
+ ---help---
+ Enable support for the Intel(R) IOP Series RAID engines.
+
endmenu
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index bdcfdbdb1ae..b3839b687ae 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
obj-$(CONFIG_NET_DMA) += iovlock.o
obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
+obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 322ee2984e3..82489923af0 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -37,11 +37,11 @@
* Each device has a channels list, which runs unlocked but is never modified
* once the device is registered, it's just setup by the driver.
*
- * Each client has a channels list, it's only modified under the client->lock
- * and in an RCU callback, so it's safe to read under rcu_read_lock().
+ * Each client is responsible for keeping track of the channels it uses. See
+ * the definition of dma_event_callback in dmaengine.h.
*
* Each device has a kref, which is initialized to 1 when the device is
- * registered. A kref_put is done for each class_device registered. When the
+ * registered. A kref_get is done for each class_device registered. When the
* class_device is released, the coresponding kref_put is done in the release
* method. Every time one of the device's channels is allocated to a client,
* a kref_get occurs. When the channel is freed, the coresponding kref_put
@@ -51,14 +51,17 @@
* references to finish.
*
* Each channel has an open-coded implementation of Rusty Russell's "bigref,"
- * with a kref and a per_cpu local_t. A single reference is set when on an
- * ADDED event, and removed with a REMOVE event. Net DMA client takes an
- * extra reference per outstanding transaction. The relase function does a
- * kref_put on the device. -ChrisL
+ * with a kref and a per_cpu local_t. A dma_chan_get is called when a client
+ * signals that it wants to use a channel, and dma_chan_put is called when
+ * a channel is removed or a client using it is unregesitered. A client can
+ * take extra references per outstanding transaction, as is the case with
+ * the NET DMA client. The release function does a kref_put on the device.
+ * -ChrisL, DanW
*/
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/mm.h>
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/hardirq.h>
@@ -66,6 +69,7 @@
#include <linux/percpu.h>
#include <linux/rcupdate.h>
#include <linux/mutex.h>
+#include <linux/jiffies.h>
static DEFINE_MUTEX(dma_list_mutex);
static LIST_HEAD(dma_device_list);
@@ -100,8 +104,19 @@ static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
static ssize_t show_in_use(struct class_device *cd, char *buf)
{
struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+ int in_use = 0;
+
+ if (unlikely(chan->slow_ref) &&
+ atomic_read(&chan->refcount.refcount) > 1)
+ in_use = 1;
+ else {
+ if (local_read(&(per_cpu_ptr(chan->local,
+ get_cpu())->refcount)) > 0)
+ in_use = 1;
+ put_cpu();
+ }
- return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
+ return sprintf(buf, "%d\n", in_use);
}
static struct class_device_attribute dma_class_attrs[] = {
@@ -127,43 +142,72 @@ static struct class dma_devclass = {
/* --- client and device registration --- */
+#define dma_chan_satisfies_mask(chan, mask) \
+ __dma_chan_satisfies_mask((chan), &(mask))
+static int
+__dma_chan_satisfies_mask(struct dma_chan *chan, dma_cap_mask_t *want)
+{
+ dma_cap_mask_t has;
+
+ bitmap_and(has.bits, want->bits, chan->device->cap_mask.bits,
+ DMA_TX_TYPE_END);
+ return bitmap_equal(want->bits, has.bits, DMA_TX_TYPE_END);
+}
+
/**
- * dma_client_chan_alloc - try to allocate a channel to a client
+ * dma_client_chan_alloc - try to allocate channels to a client
* @client: &dma_client
*
* Called with dma_list_mutex held.
*/
-static struct dma_chan *dma_client_chan_alloc(struct dma_client *client)
+static void dma_client_chan_alloc(struct dma_client *client)
{
struct dma_device *device;
struct dma_chan *chan;
- unsigned long flags;
int desc; /* allocated descriptor count */
+ enum dma_state_client ack;
- /* Find a channel, any DMA engine will do */
- list_for_each_entry(device, &dma_device_list, global_node) {
+ /* Find a channel */
+ list_for_each_entry(device, &dma_device_list, global_node)
list_for_each_entry(chan, &device->channels, device_node) {
- if (chan->client)
+ if (!dma_chan_satisfies_mask(chan, client->cap_mask))
continue;
desc = chan->device->device_alloc_chan_resources(chan);
if (desc >= 0) {
- kref_get(&device->refcount);
- kref_init(&chan->refcount);
- chan->slow_ref = 0;
- INIT_RCU_HEAD(&chan->rcu);
- chan->client = client;
- spin_lock_irqsave(&client->lock, flags);
- list_add_tail_rcu(&chan->client_node,
- &client->channels);
- spin_unlock_irqrestore(&client->lock, flags);
- return chan;
+ ack = client->event_callback(client,
+ chan,
+ DMA_RESOURCE_AVAILABLE);
+
+ /* we are done once this client rejects
+ * an available resource
+ */
+ if (ack == DMA_ACK) {
+ dma_chan_get(chan);
+ kref_get(&device->refcount);
+ } else if (ack == DMA_NAK)
+ return;
}
}
- }
+}
+
+enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie)
+{
+ enum dma_status status;
+ unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000);
+
+ dma_async_issue_pending(chan);
+ do {
+ status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
+ if (time_after_eq(jiffies, dma_sync_wait_timeout)) {
+ printk(KERN_ERR "dma_sync_wait_timeout!\n");
+ return DMA_ERROR;
+ }
+ } while (status == DMA_IN_PROGRESS);
- return NULL;
+ return status;
}
+EXPORT_SYMBOL(dma_sync_wait);
/**
* dma_chan_cleanup - release a DMA channel's resources
@@ -173,7 +217,6 @@ void dma_chan_cleanup(struct kref *kref)
{
struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
chan->device->device_free_chan_resources(chan);
- chan->client = NULL;
kref_put(&chan->device->refcount, dma_async_device_cleanup);
}
EXPORT_SYMBOL(dma_chan_cleanup);
@@ -189,7 +232,7 @@ static void dma_chan_free_rcu(struct rcu_head *rcu)
kref_put(&chan->refcount, dma_chan_cleanup);
}
-static void dma_client_chan_free(struct dma_chan *chan)
+static void dma_chan_release(struct dma_chan *chan)
{
atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
chan->slow_ref = 1;
@@ -197,70 +240,57 @@ static void dma_client_chan_free(struct dma_chan *chan)
}
/**
- * dma_chans_rebalance - reallocate channels to clients
- *
- * When the number of DMA channel in the system changes,
- * channels need to be rebalanced among clients.
+ * dma_chans_notify_available - broadcast available channels to the clients
*/
-static void dma_chans_rebalance(void)
+static void dma_clients_notify_available(void)
{
struct dma_client *client;
- struct dma_chan *chan;
- unsigned long flags;
mutex_lock(&dma_list_mutex);
- list_for_each_entry(client, &dma_client_list, global_node) {
- while (client->chans_desired > client->chan_count) {
- chan = dma_client_chan_alloc(client);
- if (!chan)
- break;
- client->chan_count++;
- client->event_callback(client,
- chan,
- DMA_RESOURCE_ADDED);
- }
- while (client->chans_desired < client->chan_count) {
- spin_lock_irqsave(&client->lock, flags);
- chan = list_entry(client->channels.next,
- struct dma_chan,
- client_node);
- list_del_rcu(&chan->client_node);
- spin_unlock_irqrestore(&client->lock, flags);
- client->chan_count--;
- client->event_callback(client,
- chan,
- DMA_RESOURCE_REMOVED);
- dma_client_chan_free(chan);
- }
- }
+ list_for_each_entry(client, &dma_client_list, global_node)
+ dma_client_chan_alloc(client);
mutex_unlock(&dma_list_mutex);
}
/**
- * dma_async_client_register - allocate and register a &dma_client
- * @event_callback: callback for notification of channel addition/removal
+ * dma_chans_notify_available - tell the clients that a channel is going away
+ * @chan: channel on its way out
*/
-struct dma_client *dma_async_client_register(dma_event_callback event_callback)
+static void dma_clients_notify_removed(struct dma_chan *chan)
{
struct dma_client *client;
+ enum dma_state_client ack;
- client = kzalloc(sizeof(*client), GFP_KERNEL);
- if (!client)
- return NULL;
+ mutex_lock(&dma_list_mutex);
- INIT_LIST_HEAD(&client->channels);
- spin_lock_init(&client->lock);
- client->chans_desired = 0;
- client->chan_count = 0;
- client->event_callback = event_callback;
+ list_for_each_entry(client, &dma_client_list, global_node) {
+ ack = client->event_callback(client, chan,
+ DMA_RESOURCE_REMOVED);
+
+ /* client was holding resources for this channel so
+ * free it
+ */
+ if (ack == DMA_ACK) {
+ dma_chan_put(chan);
+ kref_put(&chan->device->refcount,
+ dma_async_device_cleanup);
+ }
+ }
+ mutex_unlock(&dma_list_mutex);
+}
+
+/**
+ * dma_async_client_register - register a &dma_client
+ * @client: ptr to a client structure with valid 'event_callback' and 'cap_mask'
+ */
+void dma_async_client_register(struct dma_client *client)
+{
mutex_lock(&dma_list_mutex);
list_add_tail(&client->global_node, &dma_client_list);
mutex_unlock(&dma_list_mutex);
-
- return client;
}
EXPORT_SYMBOL(dma_async_client_register);
@@ -272,40 +302,42 @@ EXPORT_SYMBOL(dma_async_client_register);
*/
void dma_async_client_unregister(struct dma_client *client)
{
+ struct dma_device *device;
struct dma_chan *chan;
+ enum dma_state_client ack;
if (!client)
return;
- rcu_read_lock();
- list_for_each_entry_rcu(chan, &client->channels, client_node)
- dma_client_chan_free(chan);
- rcu_read_unlock();
-
mutex_lock(&dma_list_mutex);
+ /* free all channels the client is holding */
+ list_for_each_entry(device, &dma_device_list, global_node)
+ list_for_each_entry(chan, &device->channels, device_node) {
+ ack = client->event_callback(client, chan,
+ DMA_RESOURCE_REMOVED);
+
+ if (ack == DMA_ACK) {
+ dma_chan_put(chan);
+ kref_put(&chan->device->refcount,
+ dma_async_device_cleanup);
+ }
+ }
+
list_del(&client->global_node);
mutex_unlock(&dma_list_mutex);
-
- kfree(client);
- dma_chans_rebalance();
}
EXPORT_SYMBOL(dma_async_client_unregister);
/**
- * dma_async_client_chan_request - request DMA channels
- * @client: &dma_client
- * @number: count of DMA channels requested
- *
- * Clients call dma_async_client_chan_request() to specify how many
- * DMA channels they need, 0 to free all currently allocated.
- * The resulting allocations/frees are indicated to the client via the
- * event callback.
+ * dma_async_client_chan_request - send all available channels to the
+ * client that satisfy the capability mask
+ * @client - requester
*/
-void dma_async_client_chan_request(struct dma_client *client,
- unsigned int number)
+void dma_async_client_chan_request(struct dma_client *client)
{
- client->chans_desired = number;
- dma_chans_rebalance();
+ mutex_lock(&dma_list_mutex);
+ dma_client_chan_alloc(client);
+ mutex_unlock(&dma_list_mutex);
}
EXPORT_SYMBOL(dma_async_client_chan_request);
@@ -316,12 +348,31 @@ EXPORT_SYMBOL(dma_async_client_chan_request);
int dma_async_device_register(struct dma_device *device)
{
static int id;
- int chancnt = 0;
+ int chancnt = 0, rc;
struct dma_chan* chan;
if (!device)
return -ENODEV;
+ /* validate device routines */
+ BUG_ON(dma_has_cap(DMA_MEMCPY, device->cap_mask) &&
+ !device->device_prep_dma_memcpy);
+ BUG_ON(dma_has_cap(DMA_XOR, device->cap_mask) &&
+ !device->device_prep_dma_xor);
+ BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
+ !device->device_prep_dma_zero_sum);
+ BUG_ON(dma_has_cap(DMA_MEMSET, device->cap_mask) &&
+ !device->device_prep_dma_memset);
+ BUG_ON(dma_has_cap(DMA_ZERO_SUM, device->cap_mask) &&
+ !device->device_prep_dma_interrupt);
+
+ BUG_ON(!device->device_alloc_chan_resources);
+ BUG_ON(!device->device_free_chan_resources);
+ BUG_ON(!device->device_dependency_added);
+ BUG_ON(!device->device_is_tx_complete);
+ BUG_ON(!device->device_issue_pending);
+ BUG_ON(!device->dev);
+
init_completion(&device->done);
kref_init(&device->refcount);
device->dev_id = id++;
@@ -338,17 +389,38 @@ int dma_async_device_register(struct dma_device *device)
snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d",
device->dev_id, chan->chan_id);
+ rc = class_device_register(&chan->class_dev);
+ if (rc) {
+ chancnt--;
+ free_percpu(chan->local);
+ chan->local = NULL;
+ goto err_out;
+ }
+
kref_get(&device->refcount);
- class_device_register(&chan->class_dev);
+ kref_init(&chan->refcount);
+ chan->slow_ref = 0;
+ INIT_RCU_HEAD(&chan->rcu);
}
mutex_lock(&dma_list_mutex);
list_add_tail(&device->global_node, &dma_device_list);
mutex_unlock(&dma_list_mutex);
- dma_chans_rebalance();
+ dma_clients_notify_available();
return 0;
+
+err_out:
+ list_for_each_entry(chan, &device->channels, device_node) {
+ if (chan->local == NULL)
+ continue;
+ kref_put(&device->refcount, dma_async_device_cleanup);
+ class_device_unregister(&chan->class_dev);
+ chancnt--;
+ free_percpu(chan->local);
+ }
+ return rc;
}
EXPORT_SYMBOL(dma_async_device_register);
@@ -371,32 +443,165 @@ static void dma_async_device_cleanup(struct kref *kref)
void dma_async_device_unregister(struct dma_device *device)
{
struct dma_chan *chan;
- unsigned long flags;
mutex_lock(&dma_list_mutex);
list_del(&device->global_node);
mutex_unlock(&dma_list_mutex);
list_for_each_entry(chan, &device->channels, device_node) {
- if (chan->client) {
- spin_lock_irqsave(&chan->client->lock, flags);
- list_del(&chan->client_node);
- chan->client->chan_count--;
- spin_unlock_irqrestore(&chan->client->lock, flags);
- chan->client->event_callback(chan->client,
- chan,
- DMA_RESOURCE_REMOVED);
- dma_client_chan_free(chan);
- }
+ dma_clients_notify_removed(chan);
class_device_unregister(&chan->class_dev);
+ dma_chan_release(chan);
}
- dma_chans_rebalance();
kref_put(&device->refcount, dma_async_device_cleanup);
wait_for_completion(&device->done);
}
EXPORT_SYMBOL(dma_async_device_unregister);
+/**
+ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
+ * @chan: DMA channel to offload copy to
+ * @dest: destination address (virtual)
+ * @src: source address (virtual)
+ * @len: length
+ *
+ * Both @dest and @src must be mappable to a bus address according to the
+ * DMA mapping API rules for streaming mappings.
+ * Both @dest and @src must stay memory resident (kernel memory or locked
+ * user space pages).
+ */
+dma_cookie_t
+dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+ void *src, size_t len)
+{
+ struct dma_device *dev = chan->device;
+ struct dma_async_tx_descriptor *tx;
+ dma_addr_t addr;
+ dma_cookie_t cookie;
+ int cpu;
+
+ tx = dev->device_prep_dma_memcpy(chan, len, 0);
+ if (!tx)
+ return -ENOMEM;
+
+ tx->ack = 1;
+ tx->callback = NULL;
+ addr = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
+ tx->tx_set_src(addr, tx, 0);
+ addr = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
+ tx->tx_set_dest(addr, tx, 0);
+ cookie = tx->tx_submit(tx);
+
+ cpu = get_cpu();
+ per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+ per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+ put_cpu();
+
+ return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
+ * @chan: DMA channel to offload copy to
+ * @page: destination page
+ * @offset: offset in page to copy to
+ * @kdata: source address (virtual)
+ * @len: length
+ *
+ * Both @page/@offset and @kdata must be mappable to a bus address according
+ * to the DMA mapping API rules for streaming mappings.
+ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
+ * locked user space pages)
+ */
+dma_cookie_t
+dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+ unsigned int offset, void *kdata, size_t len)
+{
+ struct dma_device *dev = chan->device;
+ struct dma_async_tx_descriptor *tx;
+ dma_addr_t addr;
+ dma_cookie_t cookie;
+ int cpu;
+
+ tx = dev->device_prep_dma_memcpy(chan, len, 0);
+ if (!tx)
+ return -ENOMEM;
+
+ tx->ack = 1;
+ tx->callback = NULL;
+ addr = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
+ tx->tx_set_src(addr, tx, 0);
+ addr = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
+ tx->tx_set_dest(addr, tx, 0);
+ cookie = tx->tx_submit(tx);
+
+ cpu = get_cpu();
+ per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+ per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+ put_cpu();
+
+ return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+
+/**
+ * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
+ * @chan: DMA channel to offload copy to
+ * @dest_pg: destination page
+ * @dest_off: offset in page to copy to
+ * @src_pg: source page
+ * @src_off: offset in page to copy from
+ * @len: length
+ *
+ * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
+ * address according to the DMA mapping API rules for streaming mappings.
+ * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
+ * (kernel memory or locked user space pages).
+ */
+dma_cookie_t
+dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
+ unsigned int dest_off, struct page *src_pg, unsigned int src_off,
+ size_t len)
+{
+ struct dma_device *dev = chan->device;
+ struct dma_async_tx_descriptor *tx;
+ dma_addr_t addr;
+ dma_cookie_t cookie;
+ int cpu;
+
+ tx = dev->device_prep_dma_memcpy(chan, len, 0);
+ if (!tx)
+ return -ENOMEM;
+
+ tx->ack = 1;
+ tx->callback = NULL;
+ addr = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
+ tx->tx_set_src(addr, tx, 0);
+ addr = dma_map_page(dev->dev, dest_pg, dest_off, len, DMA_FROM_DEVICE);
+ tx->tx_set_dest(addr, tx, 0);
+ cookie = tx->tx_submit(tx);
+
+ cpu = get_cpu();
+ per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+ per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+ put_cpu();
+
+ return cookie;
+}
+EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
+
+void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+ struct dma_chan *chan)
+{
+ tx->chan = chan;
+ spin_lock_init(&tx->lock);
+ INIT_LIST_HEAD(&tx->depend_node);
+ INIT_LIST_HEAD(&tx->depend_list);
+}
+EXPORT_SYMBOL(dma_async_tx_descriptor_init);
+
static int __init dma_bus_init(void)
{
mutex_init(&dma_list_mutex);
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c
index 8e872610461..5fbe56b5cea 100644
--- a/drivers/dma/ioatdma.c
+++ b/drivers/dma/ioatdma.c
@@ -32,16 +32,17 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include "ioatdma.h"
-#include "ioatdma_io.h"
#include "ioatdma_registers.h"
#include "ioatdma_hw.h"
#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
#define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
+#define tx_to_ioat_desc(tx) container_of(tx, struct ioat_desc_sw, async_tx)
/* internal functions */
static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void ioat_shutdown(struct pci_dev *pdev);
static void __devexit ioat_remove(struct pci_dev *pdev);
static int enumerate_dma_channels(struct ioat_device *device)
@@ -51,8 +52,8 @@ static int enumerate_dma_channels(struct ioat_device *device)
int i;
struct ioat_dma_chan *ioat_chan;
- device->common.chancnt = ioatdma_read8(device, IOAT_CHANCNT_OFFSET);
- xfercap_scale = ioatdma_read8(device, IOAT_XFERCAP_OFFSET);
+ device->common.chancnt = readb(device->reg_base + IOAT_CHANCNT_OFFSET);
+ xfercap_scale = readb(device->reg_base + IOAT_XFERCAP_OFFSET);
xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
for (i = 0; i < device->common.chancnt; i++) {
@@ -71,13 +72,79 @@ static int enumerate_dma_channels(struct ioat_device *device)
INIT_LIST_HEAD(&ioat_chan->used_desc);
/* This should be made common somewhere in dmaengine.c */
ioat_chan->common.device = &device->common;
- ioat_chan->common.client = NULL;
list_add_tail(&ioat_chan->common.device_node,
&device->common.channels);
}
return device->common.chancnt;
}
+static void
+ioat_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
+{
+ struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+
+ pci_unmap_addr_set(desc, src, addr);
+
+ list_for_each_entry(iter, &desc->async_tx.tx_list, node) {
+ iter->hw->src_addr = addr;
+ addr += ioat_chan->xfercap;
+ }
+
+}
+
+static void
+ioat_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, int index)
+{
+ struct ioat_desc_sw *iter, *desc = tx_to_ioat_desc(tx);
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+
+ pci_unmap_addr_set(desc, dst, addr);
+
+ list_for_each_entry(iter, &desc->async_tx.tx_list, node) {
+ iter->hw->dst_addr = addr;
+ addr += ioat_chan->xfercap;
+ }
+}
+
+static dma_cookie_t
+ioat_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(tx->chan);
+ struct ioat_desc_sw *desc = tx_to_ioat_desc(tx);
+ int append = 0;
+ dma_cookie_t cookie;
+ struct ioat_desc_sw *group_start;
+
+ group_start = list_entry(desc->async_tx.tx_list.next,
+ struct ioat_desc_sw, node);
+ spin_lock_bh(&ioat_chan->desc_lock);
+ /* cookie incr and addition to used_list must be atomic */
+ cookie = ioat_chan->common.cookie;
+ cookie++;
+ if (cookie < 0)
+ cookie = 1;
+ ioat_chan->common.cookie = desc->async_tx.cookie = cookie;
+
+ /* write address into NextDescriptor field of last desc in chain */
+ to_ioat_desc(ioat_chan->used_desc.prev)->hw->next =
+ group_start->async_tx.phys;
+ list_splice_init(&desc->async_tx.tx_list, ioat_chan->used_desc.prev);
+
+ ioat_chan->pending += desc->tx_cnt;
+ if (ioat_chan->pending >= 4) {
+ append = 1;
+ ioat_chan->pending = 0;
+ }
+ spin_unlock_bh(&ioat_chan->desc_lock);
+
+ if (append)
+ writeb(IOAT_CHANCMD_APPEND,
+ ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
+
+ return cookie;
+}
+
static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
struct ioat_dma_chan *ioat_chan,
gfp_t flags)
@@ -99,8 +166,13 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
}
memset(desc, 0, sizeof(*desc));
+ dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common);
+ desc_sw->async_tx.tx_set_src = ioat_set_src;
+ desc_sw->async_tx.tx_set_dest = ioat_set_dest;
+ desc_sw->async_tx.tx_submit = ioat_tx_submit;
+ INIT_LIST_HEAD(&desc_sw->async_tx.tx_list);
desc_sw->hw = desc;
- desc_sw->phys = phys;
+ desc_sw->async_tx.phys = phys;
return desc_sw;
}
@@ -123,7 +195,7 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
* In-use bit automatically set by reading chanctrl
* If 0, we got it, if 1, someone else did
*/
- chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+ chanctrl = readw(ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
if (chanctrl & IOAT_CHANCTRL_CHANNEL_IN_USE)
return -EBUSY;
@@ -132,12 +204,12 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
IOAT_CHANCTRL_ERR_INT_EN |
IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
IOAT_CHANCTRL_ERR_COMPLETION_EN;
- ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+ writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
- chanerr = ioatdma_chan_read32(ioat_chan, IOAT_CHANERR_OFFSET);
+ chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
if (chanerr) {
printk("IOAT: CHANERR = %x, clearing\n", chanerr);
- ioatdma_chan_write32(ioat_chan, IOAT_CHANERR_OFFSET, chanerr);
+ writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
}
/* Allocate descriptors */
@@ -161,10 +233,10 @@ static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
&ioat_chan->completion_addr);
memset(ioat_chan->completion_virt, 0,
sizeof(*ioat_chan->completion_virt));
- ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_LOW,
- ((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF);
- ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_HIGH,
- ((u64) ioat_chan->completion_addr) >> 32);
+ writel(((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);
+ writel(((u64) ioat_chan->completion_addr) >> 32,
+ ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
ioat_start_null_desc(ioat_chan);
return i;
@@ -182,18 +254,20 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
ioat_dma_memcpy_cleanup(ioat_chan);
- ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
+ writeb(IOAT_CHANCMD_RESET, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
spin_lock_bh(&ioat_chan->desc_lock);
list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
in_use_descs++;
list_del(&desc->node);
- pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+ pci_pool_free(ioat_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
kfree(desc);
}
list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
list_del(&desc->node);
- pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+ pci_pool_free(ioat_device->dma_pool, desc->hw,
+ desc->async_tx.phys);
kfree(desc);
}
spin_unlock_bh(&ioat_chan->desc_lock);
@@ -210,50 +284,30 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
ioat_chan->last_completion = ioat_chan->completion_addr = 0;
/* Tell hw the chan is free */
- chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+ chanctrl = readw(ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
chanctrl &= ~IOAT_CHANCTRL_CHANNEL_IN_USE;
- ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+ writew(chanctrl, ioat_chan->reg_base + IOAT_CHANCTRL_OFFSET);
}
-/**
- * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction
- * @ioat_chan: IOAT DMA channel handle
- * @dest: DMA destination address
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
- dma_addr_t dest,
- dma_addr_t src,
- size_t len)
+static struct dma_async_tx_descriptor *
+ioat_dma_prep_memcpy(struct dma_chan *chan, size_t len, int int_en)
{
- struct ioat_desc_sw *first;
- struct ioat_desc_sw *prev;
- struct ioat_desc_sw *new;
- dma_cookie_t cookie;
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ struct ioat_desc_sw *first, *prev, *new;
LIST_HEAD(new_chain);
u32 copy;
size_t orig_len;
- dma_addr_t orig_src, orig_dst;
- unsigned int desc_count = 0;
- unsigned int append = 0;
-
- if (!ioat_chan || !dest || !src)
- return -EFAULT;
+ int desc_count = 0;
if (!len)
- return ioat_chan->common.cookie;
+ return NULL;
orig_len = len;
- orig_src = src;
- orig_dst = dest;
first = NULL;
prev = NULL;
spin_lock_bh(&ioat_chan->desc_lock);
-
while (len) {
if (!list_empty(&ioat_chan->free_desc)) {
new = to_ioat_desc(ioat_chan->free_desc.next);
@@ -270,141 +324,36 @@ static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
new->hw->size = copy;
new->hw->ctl = 0;
- new->hw->src_addr = src;
- new->hw->dst_addr = dest;
- new->cookie = 0;
+ new->async_tx.cookie = 0;
+ new->async_tx.ack = 1;
/* chain together the physical address list for the HW */
if (!first)
first = new;
else
- prev->hw->next = (u64) new->phys;
+ prev->hw->next = (u64) new->async_tx.phys;
prev = new;
-
len -= copy;
- dest += copy;
- src += copy;
-
list_add_tail(&new->node, &new_chain);
desc_count++;
}
- new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
- new->hw->next = 0;
- /* cookie incr and addition to used_list must be atomic */
+ list_splice(&new_chain, &new->async_tx.tx_list);
- cookie = ioat_chan->common.cookie;
- cookie++;
- if (cookie < 0)
- cookie = 1;
- ioat_chan->common.cookie = new->cookie = cookie;
+ new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+ new->hw->next = 0;
+ new->tx_cnt = desc_count;
+ new->async_tx.ack = 0; /* client is in control of this ack */
+ new->async_tx.cookie = -EBUSY;
- pci_unmap_addr_set(new, src, orig_src);
- pci_unmap_addr_set(new, dst, orig_dst);
pci_unmap_len_set(new, src_len, orig_len);
pci_unmap_len_set(new, dst_len, orig_len);
-
- /* write address into NextDescriptor field of last desc in chain */
- to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys;
- list_splice_init(&new_chain, ioat_chan->used_desc.prev);
-
- ioat_chan->pending += desc_count;
- if (ioat_chan->pending >= 20) {
- append = 1;
- ioat_chan->pending = 0;
- }
-
spin_unlock_bh(&ioat_chan->desc_lock);
- if (append)
- ioatdma_chan_write8(ioat_chan,
- IOAT_CHANCMD_OFFSET,
- IOAT_CHANCMD_APPEND);
- return cookie;
-}
-
-/**
- * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs
- * @chan: IOAT DMA channel handle
- * @dest: DMA destination address
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan,
- void *dest,
- void *src,
- size_t len)
-{
- dma_addr_t dest_addr;
- dma_addr_t src_addr;
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
- dest_addr = pci_map_single(ioat_chan->device->pdev,
- dest, len, PCI_DMA_FROMDEVICE);
- src_addr = pci_map_single(ioat_chan->device->pdev,
- src, len, PCI_DMA_TODEVICE);
-
- return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+ return new ? &new->async_tx : NULL;
}
-/**
- * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page
- * @chan: IOAT DMA channel handle
- * @page: pointer to the page to copy to
- * @offset: offset into that page
- * @src: DMA source address
- * @len: transaction length in bytes
- */
-
-static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan,
- struct page *page,
- unsigned int offset,
- void *src,
- size_t len)
-{
- dma_addr_t dest_addr;
- dma_addr_t src_addr;
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
- dest_addr = pci_map_page(ioat_chan->device->pdev,
- page, offset, len, PCI_DMA_FROMDEVICE);
- src_addr = pci_map_single(ioat_chan->device->pdev,
- src, len, PCI_DMA_TODEVICE);
-
- return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
-}
-
-/**
- * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages
- * @chan: IOAT DMA channel handle
- * @dest_pg: pointer to the page to copy to
- * @dest_off: offset into that page
- * @src_pg: pointer to the page to copy from
- * @src_off: offset into that page
- * @len: transaction length in bytes. This is guaranteed not to make a copy
- * across a page boundary.
- */
-
-static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan,
- struct page *dest_pg,
- unsigned int dest_off,
- struct page *src_pg,
- unsigned int src_off,
- size_t len)
-{
- dma_addr_t dest_addr;
- dma_addr_t src_addr;
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
- dest_addr = pci_map_page(ioat_chan->device->pdev,
- dest_pg, dest_off, len, PCI_DMA_FROMDEVICE);
- src_addr = pci_map_page(ioat_chan->device->pdev,
- src_pg, src_off, len, PCI_DMA_TODEVICE);
-
- return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
-}
/**
* ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw
@@ -417,9 +366,8 @@ static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan)
if (ioat_chan->pending != 0) {
ioat_chan->pending = 0;
- ioatdma_chan_write8(ioat_chan,
- IOAT_CHANCMD_OFFSET,
- IOAT_CHANCMD_APPEND);
+ writeb(IOAT_CHANCMD_APPEND,
+ ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
}
}
@@ -449,7 +397,7 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==
IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {
printk("IOAT: Channel halted, chanerr = %x\n",
- ioatdma_chan_read32(chan, IOAT_CHANERR_OFFSET));
+ readl(chan->reg_base + IOAT_CHANERR_OFFSET));
/* TODO do something to salvage the situation */
}
@@ -467,8 +415,8 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
* exceeding xfercap, perhaps. If so, only the last one will
* have a cookie, and require unmapping.
*/
- if (desc->cookie) {
- cookie = desc->cookie;
+ if (desc->async_tx.cookie) {
+ cookie = desc->async_tx.cookie;
/* yes we are unmapping both _page and _single alloc'd
regions with unmap_page. Is this *really* that bad?
@@ -483,14 +431,19 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
PCI_DMA_TODEVICE);
}
- if (desc->phys != phys_complete) {
- /* a completed entry, but not the last, so cleanup */
- list_del(&desc->node);
- list_add_tail(&desc->node, &chan->free_desc);
+ if (desc->async_tx.phys != phys_complete) {
+ /* a completed entry, but not the last, so cleanup
+ * if the client is done with the descriptor
+ */
+ if (desc->async_tx.ack) {
+ list_del(&desc->node);
+ list_add_tail(&desc->node, &chan->free_desc);
+ } else
+ desc->async_tx.cookie = 0;
} else {
/* last used desc. Do not remove, so we can append from
it, but don't look at it next time, either */
- desc->cookie = 0;
+ desc->async_tx.cookie = 0;
/* TODO check status bits? */
break;
@@ -506,6 +459,17 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
spin_unlock(&chan->cleanup_lock);
}
+static void ioat_dma_dependency_added(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+ spin_lock_bh(&ioat_chan->desc_lock);
+ if (ioat_chan->pending == 0) {
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ ioat_dma_memcpy_cleanup(ioat_chan);
+ } else
+ spin_unlock_bh(&ioat_chan->desc_lock);
+}
+
/**
* ioat_dma_is_complete - poll the status of a IOAT DMA transaction
* @chan: IOAT DMA channel handle
@@ -553,13 +517,16 @@ static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
static struct pci_device_id ioat_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
+ { PCI_DEVICE(PCI_VENDOR_ID_UNISYS,
+ PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR) },
{ 0, }
};
-static struct pci_driver ioat_pci_drv = {
+static struct pci_driver ioat_pci_driver = {
.name = "ioatdma",
.id_table = ioat_pci_tbl,
.probe = ioat_probe,
+ .shutdown = ioat_shutdown,
.remove = __devexit_p(ioat_remove),
};
@@ -569,21 +536,21 @@ static irqreturn_t ioat_do_interrupt(int irq, void *data)
unsigned long attnstatus;
u8 intrctrl;
- intrctrl = ioatdma_read8(instance, IOAT_INTRCTRL_OFFSET);
+ intrctrl = readb(instance->reg_base + IOAT_INTRCTRL_OFFSET);
if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))
return IRQ_NONE;
if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {
- ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+ writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
return IRQ_NONE;
}
- attnstatus = ioatdma_read32(instance, IOAT_ATTNSTATUS_OFFSET);
+ attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus);
- ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+ writeb(intrctrl, instance->reg_base + IOAT_INTRCTRL_OFFSET);
return IRQ_HANDLED;
}
@@ -607,19 +574,17 @@ static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan)
desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
desc->hw->next = 0;
+ desc->async_tx.ack = 1;
list_add_tail(&desc->node, &ioat_chan->used_desc);
spin_unlock_bh(&ioat_chan->desc_lock);
-#if (BITS_PER_LONG == 64)
- ioatdma_chan_write64(ioat_chan, IOAT_CHAINADDR_OFFSET, desc->phys);
-#else
- ioatdma_chan_write32(ioat_chan,
- IOAT_CHAINADDR_OFFSET_LOW,
- (u32) desc->phys);
- ioatdma_chan_write32(ioat_chan, IOAT_CHAINADDR_OFFSET_HIGH, 0);
-#endif
- ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_START);
+ writel(((u64) desc->async_tx.phys) & 0x00000000FFFFFFFF,
+ ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_LOW);
+ writel(((u64) desc->async_tx.phys) >> 32,
+ ioat_chan->reg_base + IOAT_CHAINADDR_OFFSET_HIGH);
+
+ writeb(IOAT_CHANCMD_START, ioat_chan->reg_base + IOAT_CHANCMD_OFFSET);
}
/*
@@ -633,6 +598,8 @@ static int ioat_self_test(struct ioat_device *device)
u8 *src;
u8 *dest;
struct dma_chan *dma_chan;
+ struct dma_async_tx_descriptor *tx;
+ dma_addr_t addr;
dma_cookie_t cookie;
int err = 0;
@@ -658,7 +625,15 @@ static int ioat_self_test(struct ioat_device *device)
goto out;
}
- cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE);
+ tx = ioat_dma_prep_memcpy(dma_chan, IOAT_TEST_SIZE, 0);
+ async_tx_ack(tx);
+ addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE,
+ DMA_TO_DEVICE);
+ ioat_set_src(addr, tx, 0);
+ addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE,
+ DMA_FROM_DEVICE);
+ ioat_set_dest(addr, tx, 0);
+ cookie = ioat_tx_submit(tx);
ioat_dma_memcpy_issue_pending(dma_chan);
msleep(1);
@@ -699,7 +674,7 @@ static int __devinit ioat_probe(struct pci_dev *pdev,
if (err)
goto err_set_dma_mask;
- err = pci_request_regions(pdev, ioat_pci_drv.name);
+ err = pci_request_regions(pdev, ioat_pci_driver.name);
if (err)
goto err_request_regions;
@@ -748,19 +723,20 @@ static int __devinit ioat_probe(struct pci_dev *pdev,
device->reg_base = reg_base;
- ioatdma_write8(device, IOAT_INTRCTRL_OFFSET, IOAT_INTRCTRL_MASTER_INT_EN);
+ writeb(IOAT_INTRCTRL_MASTER_INT_EN, device->reg_base + IOAT_INTRCTRL_OFFSET);
pci_set_master(pdev);
INIT_LIST_HEAD(&device->common.channels);
enumerate_dma_channels(device);
+ dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
- device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf;
- device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg;
- device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg;
- device->common.device_memcpy_complete = ioat_dma_is_complete;
- device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending;
+ device->common.device_prep_dma_memcpy = ioat_dma_prep_memcpy;
+ device->common.device_is_tx_complete = ioat_dma_is_complete;
+ device->common.device_issue_pending = ioat_dma_memcpy_issue_pending;
+ device->common.device_dependency_added = ioat_dma_dependency_added;
+ device->common.dev = &pdev->dev;
printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
device->common.chancnt);
@@ -787,9 +763,20 @@ err_request_regions:
err_set_dma_mask:
pci_disable_device(pdev);
err_enable_device:
+
+ printk(KERN_ERR "Intel(R) I/OAT DMA Engine initialization failed\n");
+
return err;
}
+static void ioat_shutdown(struct pci_dev *pdev)
+{
+ struct ioat_device *device;
+ device = pci_get_drvdata(pdev);
+
+ dma_async_device_unregister(&device->common);
+}
+
static void __devexit ioat_remove(struct pci_dev *pdev)
{
struct ioat_device *device;
@@ -818,7 +805,7 @@ static void __devexit ioat_remove(struct pci_dev *pdev)
}
/* MODULE API */
-MODULE_VERSION("1.7");
+MODULE_VERSION("1.9");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Intel Corporation");
@@ -828,14 +815,14 @@ static int __init ioat_init_module(void)
/* if forced, worst case is that rmmod hangs */
__unsafe(THIS_MODULE);
- return pci_register_driver(&ioat_pci_drv);
+ return pci_register_driver(&ioat_pci_driver);
}
module_init(ioat_init_module);
static void __exit ioat_exit_module(void)
{
- pci_unregister_driver(&ioat_pci_drv);
+ pci_unregister_driver(&ioat_pci_driver);
}
module_exit(ioat_exit_module);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index 62b26a9be4c..d3726478031 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -30,9 +30,6 @@
#define IOAT_LOW_COMPLETION_MASK 0xffffffc0
-extern struct list_head dma_device_list;
-extern struct list_head dma_client_list;
-
/**
* struct ioat_device - internal representation of a IOAT device
* @pdev: PCI-Express device
@@ -105,21 +102,20 @@ struct ioat_dma_chan {
/**
* struct ioat_desc_sw - wrapper around hardware descriptor
* @hw: hardware DMA descriptor
- * @node:
- * @cookie:
- * @phys:
+ * @node: this descriptor will either be on the free list,
+ * or attached to a transaction list (async_tx.tx_list)
+ * @tx_cnt: number of descriptors required to complete the transaction
+ * @async_tx: the generic software descriptor for all engines
*/
-
struct ioat_desc_sw {
struct ioat_dma_descriptor *hw;
struct list_head node;
- dma_cookie_t cookie;
- dma_addr_t phys;
+ int tx_cnt;
DECLARE_PCI_UNMAP_ADDR(src)
DECLARE_PCI_UNMAP_LEN(src_len)
DECLARE_PCI_UNMAP_ADDR(dst)
DECLARE_PCI_UNMAP_LEN(dst_len)
+ struct dma_async_tx_descriptor async_tx;
};
#endif /* IOATDMA_H */
-
diff --git a/drivers/dma/ioatdma_io.h b/drivers/dma/ioatdma_io.h
deleted file mode 100644
index c0b4bf66c92..00000000000
--- a/drivers/dma/ioatdma_io.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The full GNU General Public License is included in this distribution in the
- * file called COPYING.
- */
-#ifndef IOATDMA_IO_H
-#define IOATDMA_IO_H
-
-#include <asm/io.h>
-
-/*
- * device and per-channel MMIO register read and write functions
- * this is a lot of anoying inline functions, but it's typesafe
- */
-
-static inline u8 ioatdma_read8(struct ioat_device *device,
- unsigned int offset)
-{
- return readb(device->reg_base + offset);
-}
-
-static inline u16 ioatdma_read16(struct ioat_device *device,
- unsigned int offset)
-{
- return readw(device->reg_base + offset);
-}
-
-static inline u32 ioatdma_read32(struct ioat_device *device,
- unsigned int offset)
-{
- return readl(device->reg_base + offset);
-}
-
-static inline void ioatdma_write8(struct ioat_device *device,
- unsigned int offset, u8 value)
-{
- writeb(value, device->reg_base + offset);
-}
-
-static inline void ioatdma_write16(struct ioat_device *device,
- unsigned int offset, u16 value)
-{
- writew(value, device->reg_base + offset);
-}
-
-static inline void ioatdma_write32(struct ioat_device *device,
- unsigned int offset, u32 value)
-{
- writel(value, device->reg_base + offset);
-}
-
-static inline u8 ioatdma_chan_read8(struct ioat_dma_chan *chan,
- unsigned int offset)
-{
- return readb(chan->reg_base + offset);
-}
-
-static inline u16 ioatdma_chan_read16(struct ioat_dma_chan *chan,
- unsigned int offset)
-{
- return readw(chan->reg_base + offset);
-}
-
-static inline u32 ioatdma_chan_read32(struct ioat_dma_chan *chan,
- unsigned int offset)
-{
- return readl(chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write8(struct ioat_dma_chan *chan,
- unsigned int offset, u8 value)
-{
- writeb(value, chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write16(struct ioat_dma_chan *chan,
- unsigned int offset, u16 value)
-{
- writew(value, chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write32(struct ioat_dma_chan *chan,
- unsigned int offset, u32 value)
-{
- writel(value, chan->reg_base + offset);
-}
-
-#if (BITS_PER_LONG == 64)
-static inline u64 ioatdma_chan_read64(struct ioat_dma_chan *chan,
- unsigned int offset)
-{
- return readq(chan->reg_base + offset);
-}
-
-static inline void ioatdma_chan_write64(struct ioat_dma_chan *chan,
- unsigned int offset, u64 value)
-{
- writeq(value, chan->reg_base + offset);
-}
-#endif
-
-#endif /* IOATDMA_IO_H */
-
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
new file mode 100644
index 00000000000..5a1d426744d
--- /dev/null
+++ b/drivers/dma/iop-adma.c
@@ -0,0 +1,1467 @@
+/*
+ * offload engine driver for the Intel Xscale series of i/o processors
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * 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.
+ *
+ */
+
+/*
+ * This driver supports the asynchrounous DMA copy and RAID engines available
+ * on the Intel Xscale(R) family of I/O Processors (IOP 32x, 33x, 134x)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/async_tx.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/memory.h>
+#include <linux/ioport.h>
+
+#include <asm/arch/adma.h>
+
+#define to_iop_adma_chan(chan) container_of(chan, struct iop_adma_chan, common)
+#define to_iop_adma_device(dev) \
+ container_of(dev, struct iop_adma_device, common)
+#define tx_to_iop_adma_slot(tx) \
+ container_of(tx, struct iop_adma_desc_slot, async_tx)
+
+/**
+ * iop_adma_free_slots - flags descriptor slots for reuse
+ * @slot: Slot to free
+ * Caller must hold &iop_chan->lock while calling this function
+ */
+static void iop_adma_free_slots(struct iop_adma_desc_slot *slot)
+{
+ int stride = slot->slots_per_op;
+
+ while (stride--) {
+ slot->slots_per_op = 0;
+ slot = list_entry(slot->slot_node.next,
+ struct iop_adma_desc_slot,
+ slot_node);
+ }
+}
+
+static dma_cookie_t
+iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
+{
+ BUG_ON(desc->async_tx.cookie < 0);
+ spin_lock_bh(&desc->async_tx.lock);
+ if (desc->async_tx.cookie > 0) {
+ cookie = desc->async_tx.cookie;
+ desc->async_tx.cookie = 0;
+
+ /* call the callback (must not sleep or submit new
+ * operations to this channel)
+ */
+ if (desc->async_tx.callback)
+ desc->async_tx.callback(
+ desc->async_tx.callback_param);
+
+ /* unmap dma addresses
+ * (unmap_single vs unmap_page?)
+ */
+ if (desc->group_head && desc->unmap_len) {
+ struct iop_adma_desc_slot *unmap = desc->group_head;
+ struct device *dev =
+ &iop_chan->device->pdev->dev;
+ u32 len = unmap->unmap_len;
+ u32 src_cnt = unmap->unmap_src_cnt;
+ dma_addr_t addr = iop_desc_get_dest_addr(unmap,
+ iop_chan);
+
+ dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+ while (src_cnt--) {
+ addr = iop_desc_get_src_addr(unmap,
+ iop_chan,
+ src_cnt);
+ dma_unmap_page(dev, addr, len,
+ DMA_TO_DEVICE);
+ }
+ desc->group_head = NULL;
+ }
+ }
+
+ /* run dependent operations */
+ async_tx_run_dependencies(&desc->async_tx);
+ spin_unlock_bh(&desc->async_tx.lock);
+
+ return cookie;
+}
+
+static int
+iop_adma_clean_slot(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *iop_chan)
+{
+ /* the client is allowed to attach dependent operations
+ * until 'ack' is set
+ */
+ if (!desc->async_tx.ack)
+ return 0;
+
+ /* leave the last descriptor in the chain
+ * so we can append to it
+ */
+ if (desc->chain_node.next == &iop_chan->chain)
+ return 1;
+
+ dev_dbg(iop_chan->device->common.dev,
+ "\tfree slot: %d slots_per_op: %d\n",
+ desc->idx, desc->slots_per_op);
+
+ list_del(&desc->chain_node);
+ iop_adma_free_slots(desc);
+
+ return 0;
+}
+
+static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+{
+ struct iop_adma_desc_slot *iter, *_iter, *grp_start = NULL;
+ dma_cookie_t cookie = 0;
+ u32 current_desc = iop_chan_get_current_descriptor(iop_chan);
+ int busy = iop_chan_is_busy(iop_chan);
+ int seen_current = 0, slot_cnt = 0, slots_per_op = 0;
+
+ dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+ /* free completed slots from the chain starting with
+ * the oldest descriptor
+ */
+ list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
+ chain_node) {
+ pr_debug("\tcookie: %d slot: %d busy: %d "
+ "this_desc: %#x next_desc: %#x ack: %d\n",
+ iter->async_tx.cookie, iter->idx, busy,
+ iter->async_tx.phys, iop_desc_get_next_desc(iter),
+ iter->async_tx.ack);
+ prefetch(_iter);
+ prefetch(&_iter->async_tx);
+
+ /* do not advance past the current descriptor loaded into the
+ * hardware channel, subsequent descriptors are either in
+ * process or have not been submitted
+ */
+ if (seen_current)
+ break;
+
+ /* stop the search if we reach the current descriptor and the
+ * channel is busy, or if it appears that the current descriptor
+ * needs to be re-read (i.e. has been appended to)
+ */
+ if (iter->async_tx.phys == current_desc) {
+ BUG_ON(seen_current++);
+ if (busy || iop_desc_get_next_desc(iter))
+ break;
+ }
+
+ /* detect the start of a group transaction */
+ if (!slot_cnt && !slots_per_op) {
+ slot_cnt = iter->slot_cnt;
+ slots_per_op = iter->slots_per_op;
+ if (slot_cnt <= slots_per_op) {
+ slot_cnt = 0;
+ slots_per_op = 0;
+ }
+ }
+
+ if (slot_cnt) {
+ pr_debug("\tgroup++\n");
+ if (!grp_start)
+ grp_start = iter;
+ slot_cnt -= slots_per_op;
+ }
+
+ /* all the members of a group are complete */
+ if (slots_per_op != 0 && slot_cnt == 0) {
+ struct iop_adma_desc_slot *grp_iter, *_grp_iter;
+ int end_of_chain = 0;
+ pr_debug("\tgroup end\n");
+
+ /* collect the total results */
+ if (grp_start->xor_check_result) {
+ u32 zero_sum_result = 0;
+ slot_cnt = grp_start->slot_cnt;
+ grp_iter = grp_start;
+
+ list_for_each_entry_from(grp_iter,
+ &iop_chan->chain, chain_node) {
+ zero_sum_result |=
+ iop_desc_get_zero_result(grp_iter);
+ pr_debug("\titer%d result: %d\n",
+ grp_iter->idx, zero_sum_result);
+ slot_cnt -= slots_per_op;
+ if (slot_cnt == 0)
+ break;
+ }
+ pr_debug("\tgrp_start->xor_check_result: %p\n",
+ grp_start->xor_check_result);
+ *grp_start->xor_check_result = zero_sum_result;
+ }
+
+ /* clean up the group */
+ slot_cnt = grp_start->slot_cnt;
+ grp_iter = grp_start;
+ list_for_each_entry_safe_from(grp_iter, _grp_iter,
+ &iop_chan->chain, chain_node) {
+ cookie = iop_adma_run_tx_complete_actions(
+ grp_iter, iop_chan, cookie);
+
+ slot_cnt -= slots_per_op;
+ end_of_chain = iop_adma_clean_slot(grp_iter,
+ iop_chan);
+
+ if (slot_cnt == 0 || end_of_chain)
+ break;
+ }
+
+ /* the group should be complete at this point */
+ BUG_ON(slot_cnt);
+
+ slots_per_op = 0;
+ grp_start = NULL;
+ if (end_of_chain)
+ break;
+ else
+ continue;
+ } else if (slots_per_op) /* wait for group completion */
+ continue;
+
+ /* write back zero sum results (single descriptor case) */
+ if (iter->xor_check_result && iter->async_tx.cookie)
+ *iter->xor_check_result =
+ iop_desc_get_zero_result(iter);
+
+ cookie = iop_adma_run_tx_complete_actions(
+ iter, iop_chan, cookie);
+
+ if (iop_adma_clean_slot(iter, iop_chan))
+ break;
+ }
+
+ BUG_ON(!seen_current);
+
+ iop_chan_idle(busy, iop_chan);
+
+ if (cookie > 0) {
+ iop_chan->completed_cookie = cookie;
+ pr_debug("\tcompleted cookie %d\n", cookie);
+ }
+}
+
+static void
+iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
+{
+ spin_lock_bh(&iop_chan->lock);
+ __iop_adma_slot_cleanup(iop_chan);
+ spin_unlock_bh(&iop_chan->lock);
+}
+
+static void iop_adma_tasklet(unsigned long data)
+{
+ struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
+ __iop_adma_slot_cleanup(chan);
+}
+
+static struct iop_adma_desc_slot *
+iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots,
+ int slots_per_op)
+{
+ struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL;
+ struct list_head chain = LIST_HEAD_INIT(chain);
+ int slots_found, retry = 0;
+
+ /* start search from the last allocated descrtiptor
+ * if a contiguous allocation can not be found start searching
+ * from the beginning of the list
+ */
+retry:
+ slots_found = 0;
+ if (retry == 0)
+ iter = iop_chan->last_used;
+ else
+ iter = list_entry(&iop_chan->all_slots,
+ struct iop_adma_desc_slot,
+ slot_node);
+
+ list_for_each_entry_safe_continue(
+ iter, _iter, &iop_chan->all_slots, slot_node) {
+ prefetch(_iter);
+ prefetch(&_iter->async_tx);
+ if (iter->slots_per_op) {
+ /* give up after finding the first busy slot
+ * on the second pass through the list
+ */
+ if (retry)
+ break;
+
+ slots_found = 0;
+ continue;
+ }
+
+ /* start the allocation if the slot is correctly aligned */
+ if (!slots_found++) {
+ if (iop_desc_is_aligned(iter, slots_per_op))
+ alloc_start = iter;
+ else {
+ slots_found = 0;
+ continue;
+ }
+ }
+
+ if (slots_found == num_slots) {
+ struct iop_adma_desc_slot *alloc_tail = NULL;
+ struct iop_adma_desc_slot *last_used = NULL;
+ iter = alloc_start;
+ while (num_slots) {
+ int i;
+ dev_dbg(iop_chan->device->common.dev,
+ "allocated slot: %d "
+ "(desc %p phys: %#x) slots_per_op %d\n",
+ iter->idx, iter->hw_desc,
+ iter->async_tx.phys, slots_per_op);
+
+ /* pre-ack all but the last descriptor */
+ if (num_slots != slots_per_op)
+ iter->async_tx.ack = 1;
+ else
+ iter->async_tx.ack = 0;
+
+ list_add_tail(&iter->chain_node, &chain);
+ alloc_tail = iter;
+ iter->async_tx.cookie = 0;
+ iter->slot_cnt = num_slots;
+ iter->xor_check_result = NULL;
+ for (i = 0; i < slots_per_op; i++) {
+ iter->slots_per_op = slots_per_op - i;
+ last_used = iter;
+ iter = list_entry(iter->slot_node.next,
+ struct iop_adma_desc_slot,
+ slot_node);
+ }
+ num_slots -= slots_per_op;
+ }
+ alloc_tail->group_head = alloc_start;
+ alloc_tail->async_tx.cookie = -EBUSY;
+ list_splice(&chain, &alloc_tail->async_tx.tx_list);
+ iop_chan->last_used = last_used;
+ iop_desc_clear_next_desc(alloc_start);
+ iop_desc_clear_next_desc(alloc_tail);
+ return alloc_tail;
+ }
+ }
+ if (!retry++)
+ goto retry;
+
+ /* try to free some slots if the allocation fails */
+ tasklet_schedule(&iop_chan->irq_tasklet);
+
+ return NULL;
+}
+
+static dma_cookie_t
+iop_desc_assign_cookie(struct iop_adma_chan *iop_chan,
+ struct iop_adma_desc_slot *desc)
+{
+ dma_cookie_t cookie = iop_chan->common.cookie;
+ cookie++;
+ if (cookie < 0)
+ cookie = 1;
+ iop_chan->common.cookie = desc->async_tx.cookie = cookie;
+ return cookie;
+}
+
+static void iop_adma_check_threshold(struct iop_adma_chan *iop_chan)
+{
+ dev_dbg(iop_chan->device->common.dev, "pending: %d\n",
+ iop_chan->pending);
+
+ if (iop_chan->pending >= IOP_ADMA_THRESHOLD) {
+ iop_chan->pending = 0;
+ iop_chan_append(iop_chan);
+ }
+}
+
+static dma_cookie_t
+iop_adma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
+ struct iop_adma_desc_slot *grp_start, *old_chain_tail;
+ int slot_cnt;
+ int slots_per_op;
+ dma_cookie_t cookie;
+
+ grp_start = sw_desc->group_head;
+ slot_cnt = grp_start->slot_cnt;
+ slots_per_op = grp_start->slots_per_op;
+
+ spin_lock_bh(&iop_chan->lock);
+ cookie = iop_desc_assign_cookie(iop_chan, sw_desc);
+
+ old_chain_tail = list_entry(iop_chan->chain.prev,
+ struct iop_adma_desc_slot, chain_node);
+ list_splice_init(&sw_desc->async_tx.tx_list,
+ &old_chain_tail->chain_node);
+
+ /* fix up the hardware chain */
+ iop_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys);
+
+ /* 1/ don't add pre-chained descriptors
+ * 2/ dummy read to flush next_desc write
+ */
+ BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+ /* increment the pending count by the number of slots
+ * memcpy operations have a 1:1 (slot:operation) relation
+ * other operations are heavier and will pop the threshold
+ * more often.
+ */
+ iop_chan->pending += slot_cnt;
+ iop_adma_check_threshold(iop_chan);
+ spin_unlock_bh(&iop_chan->lock);
+
+ dev_dbg(iop_chan->device->common.dev, "%s cookie: %d slot: %d\n",
+ __FUNCTION__, sw_desc->async_tx.cookie, sw_desc->idx);
+
+ return cookie;
+}
+
+static void
+iop_adma_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+ int index)
+{
+ struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan);
+
+ /* to do: support transfers lengths > IOP_ADMA_MAX_BYTE_COUNT */
+ iop_desc_set_dest_addr(sw_desc->group_head, iop_chan, addr);
+}
+
+static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan);
+static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan);
+
+/* returns the number of allocated descriptors */
+static int iop_adma_alloc_chan_resources(struct dma_chan *chan)
+{
+ char *hw_desc;
+ int idx;
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *slot = NULL;
+ int init = iop_chan->slots_allocated ? 0 : 1;
+ struct iop_adma_platform_data *plat_data =
+ iop_chan->device->pdev->dev.platform_data;
+ int num_descs_in_pool = plat_data->pool_size/IOP_ADMA_SLOT_SIZE;
+
+ /* Allocate descriptor slots */
+ do {
+ idx = iop_chan->slots_allocated;
+ if (idx == num_descs_in_pool)
+ break;
+
+ slot = kzalloc(sizeof(*slot), GFP_KERNEL);
+ if (!slot) {
+ printk(KERN_INFO "IOP ADMA Channel only initialized"
+ " %d descriptor slots", idx);
+ break;
+ }
+ hw_desc = (char *) iop_chan->device->dma_desc_pool_virt;
+ slot->hw_desc = (void *) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
+
+ dma_async_tx_descriptor_init(&slot->async_tx, chan);
+ slot->async_tx.tx_submit = iop_adma_tx_submit;
+ slot->async_tx.tx_set_dest = iop_adma_set_dest;
+ INIT_LIST_HEAD(&slot->chain_node);
+ INIT_LIST_HEAD(&slot->slot_node);
+ INIT_LIST_HEAD(&slot->async_tx.tx_list);
+ hw_desc = (char *) iop_chan->device->dma_desc_pool;
+ slot->async_tx.phys =
+ (dma_addr_t) &hw_desc[idx * IOP_ADMA_SLOT_SIZE];
+ slot->idx = idx;
+
+ spin_lock_bh(&iop_chan->lock);
+ iop_chan->slots_allocated++;
+ list_add_tail(&slot->slot_node, &iop_chan->all_slots);
+ spin_unlock_bh(&iop_chan->lock);
+ } while (iop_chan->slots_allocated < num_descs_in_pool);
+
+ if (idx && !iop_chan->last_used)
+ iop_chan->last_used = list_entry(iop_chan->all_slots.next,
+ struct iop_adma_desc_slot,
+ slot_node);
+
+ dev_dbg(iop_chan->device->common.dev,
+ "allocated %d descriptor slots last_used: %p\n",
+ iop_chan->slots_allocated, iop_chan->last_used);
+
+ /* initialize the channel and the chain with a null operation */
+ if (init) {
+ if (dma_has_cap(DMA_MEMCPY,
+ iop_chan->device->common.cap_mask))
+ iop_chan_start_null_memcpy(iop_chan);
+ else if (dma_has_cap(DMA_XOR,
+ iop_chan->device->common.cap_mask))
+ iop_chan_start_null_xor(iop_chan);
+ else
+ BUG();
+ }
+
+ return (idx > 0) ? idx : -ENOMEM;
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_interrupt(struct dma_chan *chan)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+ int slot_cnt, slots_per_op;
+
+ dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_interrupt_slot_count(&slots_per_op, iop_chan);
+ sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+ iop_desc_init_interrupt(grp_start, iop_chan);
+ grp_start->unmap_len = 0;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_memcpy_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+ int index)
+{
+ struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+ struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+ iop_desc_set_memcpy_src_addr(grp_start, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+ int slot_cnt, slots_per_op;
+
+ if (unlikely(!len))
+ return NULL;
+ BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+
+ dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+ __FUNCTION__, len);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_memcpy_slot_count(len, &slots_per_op);
+ sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+ iop_desc_init_memcpy(grp_start, int_en);
+ iop_desc_set_byte_count(grp_start, iop_chan, len);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
+ sw_desc->async_tx.tx_set_src = iop_adma_memcpy_set_src;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len,
+ int int_en)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+ int slot_cnt, slots_per_op;
+
+ if (unlikely(!len))
+ return NULL;
+ BUG_ON(unlikely(len > IOP_ADMA_MAX_BYTE_COUNT));
+
+ dev_dbg(iop_chan->device->common.dev, "%s len: %u\n",
+ __FUNCTION__, len);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_memset_slot_count(len, &slots_per_op);
+ sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+ iop_desc_init_memset(grp_start, int_en);
+ iop_desc_set_byte_count(grp_start, iop_chan, len);
+ iop_desc_set_block_fill_val(grp_start, value);
+ sw_desc->unmap_src_cnt = 1;
+ sw_desc->unmap_len = len;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_xor_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx,
+ int index)
+{
+ struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+ struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+ iop_desc_set_xor_src_addr(grp_start, index, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_xor(struct dma_chan *chan, unsigned int src_cnt, size_t len,
+ int int_en)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+ int slot_cnt, slots_per_op;
+
+ if (unlikely(!len))
+ return NULL;
+ BUG_ON(unlikely(len > IOP_ADMA_XOR_MAX_BYTE_COUNT));
+
+ dev_dbg(iop_chan->device->common.dev,
+ "%s src_cnt: %d len: %u int_en: %d\n",
+ __FUNCTION__, src_cnt, len, int_en);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op);
+ sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+ iop_desc_init_xor(grp_start, src_cnt, int_en);
+ iop_desc_set_byte_count(grp_start, iop_chan, len);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
+ sw_desc->async_tx.tx_set_src = iop_adma_xor_set_src;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void
+iop_adma_xor_zero_sum_set_src(dma_addr_t addr,
+ struct dma_async_tx_descriptor *tx,
+ int index)
+{
+ struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx);
+ struct iop_adma_desc_slot *grp_start = sw_desc->group_head;
+
+ iop_desc_set_zero_sum_src_addr(grp_start, index, addr);
+}
+
+static struct dma_async_tx_descriptor *
+iop_adma_prep_dma_zero_sum(struct dma_chan *chan, unsigned int src_cnt,
+ size_t len, u32 *result, int int_en)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+ int slot_cnt, slots_per_op;
+
+ if (unlikely(!len))
+ return NULL;
+
+ dev_dbg(iop_chan->device->common.dev, "%s src_cnt: %d len: %u\n",
+ __FUNCTION__, src_cnt, len);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_zero_sum_slot_count(len, src_cnt, &slots_per_op);
+ sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+ iop_desc_init_zero_sum(grp_start, src_cnt, int_en);
+ iop_desc_set_zero_sum_byte_count(grp_start, len);
+ grp_start->xor_check_result = result;
+ pr_debug("\t%s: grp_start->xor_check_result: %p\n",
+ __FUNCTION__, grp_start->xor_check_result);
+ sw_desc->unmap_src_cnt = src_cnt;
+ sw_desc->unmap_len = len;
+ sw_desc->async_tx.tx_set_src = iop_adma_xor_zero_sum_set_src;
+ }
+ spin_unlock_bh(&iop_chan->lock);
+
+ return sw_desc ? &sw_desc->async_tx : NULL;
+}
+
+static void iop_adma_dependency_added(struct dma_chan *chan)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ tasklet_schedule(&iop_chan->irq_tasklet);
+}
+
+static void iop_adma_free_chan_resources(struct dma_chan *chan)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ struct iop_adma_desc_slot *iter, *_iter;
+ int in_use_descs = 0;
+
+ iop_adma_slot_cleanup(iop_chan);
+
+ spin_lock_bh(&iop_chan->lock);
+ list_for_each_entry_safe(iter, _iter, &iop_chan->chain,
+ chain_node) {
+ in_use_descs++;
+ list_del(&iter->chain_node);
+ }
+ list_for_each_entry_safe_reverse(
+ iter, _iter, &iop_chan->all_slots, slot_node) {
+ list_del(&iter->slot_node);
+ kfree(iter);
+ iop_chan->slots_allocated--;
+ }
+ iop_chan->last_used = NULL;
+
+ dev_dbg(iop_chan->device->common.dev, "%s slots_allocated %d\n",
+ __FUNCTION__, iop_chan->slots_allocated);
+ spin_unlock_bh(&iop_chan->lock);
+
+ /* one is ok since we left it on there on purpose */
+ if (in_use_descs > 1)
+ printk(KERN_ERR "IOP: Freeing %d in use descriptors!\n",
+ in_use_descs - 1);
+}
+
+/**
+ * iop_adma_is_complete - poll the status of an ADMA transaction
+ * @chan: ADMA channel handle
+ * @cookie: ADMA transaction identifier
+ */
+static enum dma_status iop_adma_is_complete(struct dma_chan *chan,
+ dma_cookie_t cookie,
+ dma_cookie_t *done,
+ dma_cookie_t *used)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+ dma_cookie_t last_used;
+ dma_cookie_t last_complete;
+ enum dma_status ret;
+
+ last_used = chan->cookie;
+ last_complete = iop_chan->completed_cookie;
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ ret = dma_async_is_complete(cookie, last_complete, last_used);
+ if (ret == DMA_SUCCESS)
+ return ret;
+
+ iop_adma_slot_cleanup(iop_chan);
+
+ last_used = chan->cookie;
+ last_complete = iop_chan->completed_cookie;
+
+ if (done)
+ *done = last_complete;
+ if (used)
+ *used = last_used;
+
+ return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+static irqreturn_t iop_adma_eot_handler(int irq, void *data)
+{
+ struct iop_adma_chan *chan = data;
+
+ dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
+
+ tasklet_schedule(&chan->irq_tasklet);
+
+ iop_adma_device_clear_eot_status(chan);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t iop_adma_eoc_handler(int irq, void *data)
+{
+ struct iop_adma_chan *chan = data;
+
+ dev_dbg(chan->device->common.dev, "%s\n", __FUNCTION__);
+
+ tasklet_schedule(&chan->irq_tasklet);
+
+ iop_adma_device_clear_eoc_status(chan);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t iop_adma_err_handler(int irq, void *data)
+{
+ struct iop_adma_chan *chan = data;
+ unsigned long status = iop_chan_get_status(chan);
+
+ dev_printk(KERN_ERR, chan->device->common.dev,
+ "error ( %s%s%s%s%s%s%s)\n",
+ iop_is_err_int_parity(status, chan) ? "int_parity " : "",
+ iop_is_err_mcu_abort(status, chan) ? "mcu_abort " : "",
+ iop_is_err_int_tabort(status, chan) ? "int_tabort " : "",
+ iop_is_err_int_mabort(status, chan) ? "int_mabort " : "",
+ iop_is_err_pci_tabort(status, chan) ? "pci_tabort " : "",
+ iop_is_err_pci_mabort(status, chan) ? "pci_mabort " : "",
+ iop_is_err_split_tx(status, chan) ? "split_tx " : "");
+
+ iop_adma_device_clear_err_status(chan);
+
+ BUG();
+
+ return IRQ_HANDLED;
+}
+
+static void iop_adma_issue_pending(struct dma_chan *chan)
+{
+ struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
+
+ if (iop_chan->pending) {
+ iop_chan->pending = 0;
+ iop_chan_append(iop_chan);
+ }
+}
+
+/*
+ * Perform a transaction to verify the HW works.
+ */
+#define IOP_ADMA_TEST_SIZE 2000
+
+static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
+{
+ int i;
+ void *src, *dest;
+ dma_addr_t src_dma, dest_dma;
+ struct dma_chan *dma_chan;
+ dma_cookie_t cookie;
+ struct dma_async_tx_descriptor *tx;
+ int err = 0;
+ struct iop_adma_chan *iop_chan;
+
+ dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
+
+ src = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+ if (!src)
+ return -ENOMEM;
+ dest = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
+ if (!dest) {
+ kfree(src);
+ return -ENOMEM;
+ }
+
+ /* Fill in src buffer */
+ for (i = 0; i < IOP_ADMA_TEST_SIZE; i++)
+ ((u8 *) src)[i] = (u8)i;
+
+ memset(dest, 0, IOP_ADMA_TEST_SIZE);
+
+ /* Start copy, using first DMA channel */
+ dma_chan = container_of(device->common.channels.next,
+ struct dma_chan,
+ device_node);
+ if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ tx = iop_adma_prep_dma_memcpy(dma_chan, IOP_ADMA_TEST_SIZE, 1);
+ dest_dma = dma_map_single(dma_chan->device->dev, dest,
+ IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
+ iop_adma_set_dest(dest_dma, tx, 0);
+ src_dma = dma_map_single(dma_chan->device->dev, src,
+ IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE);
+ iop_adma_memcpy_set_src(src_dma, tx, 0);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(1);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+ DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test copy timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ iop_chan = to_iop_adma_chan(dma_chan);
+ dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
+ IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE);
+ if (memcmp(src, dest, IOP_ADMA_TEST_SIZE)) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test copy failed compare, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+free_resources:
+ iop_adma_free_chan_resources(dma_chan);
+out:
+ kfree(src);
+ kfree(dest);
+ return err;
+}
+
+#define IOP_ADMA_NUM_SRC_TEST 4 /* must be <= 15 */
+static int __devinit
+iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device)
+{
+ int i, src_idx;
+ struct page *dest;
+ struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST];
+ struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1];
+ dma_addr_t dma_addr, dest_dma;
+ struct dma_async_tx_descriptor *tx;
+ struct dma_chan *dma_chan;
+ dma_cookie_t cookie;
+ u8 cmp_byte = 0;
+ u32 cmp_word;
+ u32 zero_sum_result;
+ int err = 0;
+ struct iop_adma_chan *iop_chan;
+
+ dev_dbg(device->common.dev, "%s\n", __FUNCTION__);
+
+ for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+ xor_srcs[src_idx] = alloc_page(GFP_KERNEL);
+ if (!xor_srcs[src_idx])
+ while (src_idx--) {
+ __free_page(xor_srcs[src_idx]);
+ return -ENOMEM;
+ }
+ }
+
+ dest = alloc_page(GFP_KERNEL);
+ if (!dest)
+ while (src_idx--) {
+ __free_page(xor_srcs[src_idx]);
+ return -ENOMEM;
+ }
+
+ /* Fill in src buffers */
+ for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) {
+ u8 *ptr = page_address(xor_srcs[src_idx]);
+ for (i = 0; i < PAGE_SIZE; i++)
+ ptr[i] = (1 << src_idx);
+ }
+
+ for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++)
+ cmp_byte ^= (u8) (1 << src_idx);
+
+ cmp_word = (cmp_byte << 24) | (cmp_byte << 16) |
+ (cmp_byte << 8) | cmp_byte;
+
+ memset(page_address(dest), 0, PAGE_SIZE);
+
+ dma_chan = container_of(device->common.channels.next,
+ struct dma_chan,
+ device_node);
+ if (iop_adma_alloc_chan_resources(dma_chan) < 1) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ /* test xor */
+ tx = iop_adma_prep_dma_xor(dma_chan, IOP_ADMA_NUM_SRC_TEST,
+ PAGE_SIZE, 1);
+ dest_dma = dma_map_page(dma_chan->device->dev, dest, 0,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ iop_adma_set_dest(dest_dma, tx, 0);
+
+ for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) {
+ dma_addr = dma_map_page(dma_chan->device->dev, xor_srcs[i], 0,
+ PAGE_SIZE, DMA_TO_DEVICE);
+ iop_adma_xor_set_src(dma_addr, tx, i);
+ }
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) !=
+ DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test xor timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ iop_chan = to_iop_adma_chan(dma_chan);
+ dma_sync_single_for_cpu(&iop_chan->device->pdev->dev, dest_dma,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
+ u32 *ptr = page_address(dest);
+ if (ptr[i] != cmp_word) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test xor failed compare, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+ }
+ dma_sync_single_for_device(&iop_chan->device->pdev->dev, dest_dma,
+ PAGE_SIZE, DMA_TO_DEVICE);
+
+ /* skip zero sum if the capability is not present */
+ if (!dma_has_cap(DMA_ZERO_SUM, dma_chan->device->cap_mask))
+ goto free_resources;
+
+ /* zero sum the sources with the destintation page */
+ for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++)
+ zero_sum_srcs[i] = xor_srcs[i];
+ zero_sum_srcs[i] = dest;
+
+ zero_sum_result = 1;
+
+ tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
+ PAGE_SIZE, &zero_sum_result, 1);
+ for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
+ dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
+ 0, PAGE_SIZE, DMA_TO_DEVICE);
+ iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
+ }
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test zero sum timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ if (zero_sum_result != 0) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test zero sum failed compare, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ /* test memset */
+ tx = iop_adma_prep_dma_memset(dma_chan, 0, PAGE_SIZE, 1);
+ dma_addr = dma_map_page(dma_chan->device->dev, dest, 0,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ iop_adma_set_dest(dma_addr, tx, 0);
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test memset timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ for (i = 0; i < PAGE_SIZE/sizeof(u32); i++) {
+ u32 *ptr = page_address(dest);
+ if (ptr[i]) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test memset failed compare, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+ }
+
+ /* test for non-zero parity sum */
+ zero_sum_result = 0;
+ tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1,
+ PAGE_SIZE, &zero_sum_result, 1);
+ for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) {
+ dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i],
+ 0, PAGE_SIZE, DMA_TO_DEVICE);
+ iop_adma_xor_zero_sum_set_src(dma_addr, tx, i);
+ }
+
+ cookie = iop_adma_tx_submit(tx);
+ iop_adma_issue_pending(dma_chan);
+ async_tx_ack(tx);
+ msleep(8);
+
+ if (iop_adma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test non-zero sum timed out, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+ if (zero_sum_result != 1) {
+ dev_printk(KERN_ERR, dma_chan->device->dev,
+ "Self-test non-zero sum failed compare, disabling\n");
+ err = -ENODEV;
+ goto free_resources;
+ }
+
+free_resources:
+ iop_adma_free_chan_resources(dma_chan);
+out:
+ src_idx = IOP_ADMA_NUM_SRC_TEST;
+ while (src_idx--)
+ __free_page(xor_srcs[src_idx]);
+ __free_page(dest);
+ return err;
+}
+
+static int __devexit iop_adma_remove(struct platform_device *dev)
+{
+ struct iop_adma_device *device = platform_get_drvdata(dev);
+ struct dma_chan *chan, *_chan;
+ struct iop_adma_chan *iop_chan;
+ int i;
+ struct iop_adma_platform_data *plat_data = dev->dev.platform_data;
+
+ dma_async_device_unregister(&device->common);
+
+ for (i = 0; i < 3; i++) {
+ unsigned int irq;
+ irq = platform_get_irq(dev, i);
+ free_irq(irq, device);
+ }
+
+ dma_free_coherent(&dev->dev, plat_data->pool_size,
+ device->dma_desc_pool_virt, device->dma_desc_pool);
+
+ do {
+ struct resource *res;
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start);
+ } while (0);
+
+ list_for_each_entry_safe(chan, _chan, &device->common.channels,
+ device_node) {
+ iop_chan = to_iop_adma_chan(chan);
+ list_del(&chan->device_node);
+ kfree(iop_chan);
+ }
+ kfree(device);
+
+ return 0;
+}
+
+static int __devinit iop_adma_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int ret = 0, i;
+ struct iop_adma_device *adev;
+ struct iop_adma_chan *iop_chan;
+ struct dma_device *dma_dev;
+ struct iop_adma_platform_data *plat_data = pdev->dev.platform_data;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ res->end - res->start, pdev->name))
+ return -EBUSY;
+
+ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
+ if (!adev)
+ return -ENOMEM;
+ dma_dev = &adev->common;
+
+ /* allocate coherent memory for hardware descriptors
+ * note: writecombine gives slightly better performance, but
+ * requires that we explicitly flush the writes
+ */
+ if ((adev->dma_desc_pool_virt = dma_alloc_writecombine(&pdev->dev,
+ plat_data->pool_size,
+ &adev->dma_desc_pool,
+ GFP_KERNEL)) == NULL) {
+ ret = -ENOMEM;
+ goto err_free_adev;
+ }
+
+ dev_dbg(&pdev->dev, "%s: allocted descriptor pool virt %p phys %p\n",
+ __FUNCTION__, adev->dma_desc_pool_virt,
+ (void *) adev->dma_desc_pool);
+
+ adev->id = plat_data->hw_id;
+
+ /* discover transaction capabilites from the platform data */
+ dma_dev->cap_mask = plat_data->cap_mask;
+
+ adev->pdev = pdev;
+ platform_set_drvdata(pdev, adev);
+
+ INIT_LIST_HEAD(&dma_dev->channels);
+
+ /* set base routines */
+ dma_dev->device_alloc_chan_resources = iop_adma_alloc_chan_resources;
+ dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
+ dma_dev->device_is_tx_complete = iop_adma_is_complete;
+ dma_dev->device_issue_pending = iop_adma_issue_pending;
+ dma_dev->device_dependency_added = iop_adma_dependency_added;
+ dma_dev->dev = &pdev->dev;
+
+ /* set prep routines based on capability */
+ if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
+ dma_dev->device_prep_dma_memcpy = iop_adma_prep_dma_memcpy;
+ if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
+ dma_dev->device_prep_dma_memset = iop_adma_prep_dma_memset;
+ if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
+ dma_dev->max_xor = iop_adma_get_max_xor();
+ dma_dev->device_prep_dma_xor = iop_adma_prep_dma_xor;
+ }
+ if (dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask))
+ dma_dev->device_prep_dma_zero_sum =
+ iop_adma_prep_dma_zero_sum;
+ if (dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask))
+ dma_dev->device_prep_dma_interrupt =
+ iop_adma_prep_dma_interrupt;
+
+ iop_chan = kzalloc(sizeof(*iop_chan), GFP_KERNEL);
+ if (!iop_chan) {
+ ret = -ENOMEM;
+ goto err_free_dma;
+ }
+ iop_chan->device = adev;
+
+ iop_chan->mmr_base = devm_ioremap(&pdev->dev, res->start,
+ res->end - res->start);
+ if (!iop_chan->mmr_base) {
+ ret = -ENOMEM;
+ goto err_free_iop_chan;
+ }
+ tasklet_init(&iop_chan->irq_tasklet, iop_adma_tasklet, (unsigned long)
+ iop_chan);
+
+ /* clear errors before enabling interrupts */
+ iop_adma_device_clear_err_status(iop_chan);
+
+ for (i = 0; i < 3; i++) {
+ irq_handler_t handler[] = { iop_adma_eot_handler,
+ iop_adma_eoc_handler,
+ iop_adma_err_handler };
+ int irq = platform_get_irq(pdev, i);
+ if (irq < 0) {
+ ret = -ENXIO;
+ goto err_free_iop_chan;
+ } else {
+ ret = devm_request_irq(&pdev->dev, irq,
+ handler[i], 0, pdev->name, iop_chan);
+ if (ret)
+ goto err_free_iop_chan;
+ }
+ }
+
+ spin_lock_init(&iop_chan->lock);
+ init_timer(&iop_chan->cleanup_watchdog);
+ iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
+ iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
+ INIT_LIST_HEAD(&iop_chan->chain);
+ INIT_LIST_HEAD(&iop_chan->all_slots);
+ INIT_RCU_HEAD(&iop_chan->common.rcu);
+ iop_chan->common.device = dma_dev;
+ list_add_tail(&iop_chan->common.device_node, &dma_dev->channels);
+
+ if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
+ ret = iop_adma_memcpy_self_test(adev);
+ dev_dbg(&pdev->dev, "memcpy self test returned %d\n", ret);
+ if (ret)
+ goto err_free_iop_chan;
+ }
+
+ if (dma_has_cap(DMA_XOR, dma_dev->cap_mask) ||
+ dma_has_cap(DMA_MEMSET, dma_dev->cap_mask)) {
+ ret = iop_adma_xor_zero_sum_self_test(adev);
+ dev_dbg(&pdev->dev, "xor self test returned %d\n", ret);
+ if (ret)
+ goto err_free_iop_chan;
+ }
+
+ dev_printk(KERN_INFO, &pdev->dev, "Intel(R) IOP: "
+ "( %s%s%s%s%s%s%s%s%s%s)\n",
+ dma_has_cap(DMA_PQ_XOR, dma_dev->cap_mask) ? "pq_xor " : "",
+ dma_has_cap(DMA_PQ_UPDATE, dma_dev->cap_mask) ? "pq_update " : "",
+ dma_has_cap(DMA_PQ_ZERO_SUM, dma_dev->cap_mask) ? "pq_zero_sum " : "",
+ dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
+ dma_has_cap(DMA_DUAL_XOR, dma_dev->cap_mask) ? "dual_xor " : "",
+ dma_has_cap(DMA_ZERO_SUM, dma_dev->cap_mask) ? "xor_zero_sum " : "",
+ dma_has_cap(DMA_MEMSET, dma_dev->cap_mask) ? "fill " : "",
+ dma_has_cap(DMA_MEMCPY_CRC32C, dma_dev->cap_mask) ? "cpy+crc " : "",
+ dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+ dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
+
+ dma_async_device_register(dma_dev);
+ goto out;
+
+ err_free_iop_chan:
+ kfree(iop_chan);
+ err_free_dma:
+ dma_free_coherent(&adev->pdev->dev, plat_data->pool_size,
+ adev->dma_desc_pool_virt, adev->dma_desc_pool);
+ err_free_adev:
+ kfree(adev);
+ out:
+ return ret;
+}
+
+static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan)
+{
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+ dma_cookie_t cookie;
+ int slot_cnt, slots_per_op;
+
+ dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_memcpy_slot_count(0, &slots_per_op);
+ sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+
+ list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+ sw_desc->async_tx.ack = 1;
+ iop_desc_init_memcpy(grp_start, 0);
+ iop_desc_set_byte_count(grp_start, iop_chan, 0);
+ iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+ iop_desc_set_memcpy_src_addr(grp_start, 0);
+
+ cookie = iop_chan->common.cookie;
+ cookie++;
+ if (cookie <= 1)
+ cookie = 2;
+
+ /* initialize the completed cookie to be less than
+ * the most recently used cookie
+ */
+ iop_chan->completed_cookie = cookie - 1;
+ iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+
+ /* channel should not be busy */
+ BUG_ON(iop_chan_is_busy(iop_chan));
+
+ /* clear any prior error-status bits */
+ iop_adma_device_clear_err_status(iop_chan);
+
+ /* disable operation */
+ iop_chan_disable(iop_chan);
+
+ /* set the descriptor address */
+ iop_chan_set_next_descriptor(iop_chan, sw_desc->async_tx.phys);
+
+ /* 1/ don't add pre-chained descriptors
+ * 2/ dummy read to flush next_desc write
+ */
+ BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+ /* run the descriptor */
+ iop_chan_enable(iop_chan);
+ } else
+ dev_printk(KERN_ERR, iop_chan->device->common.dev,
+ "failed to allocate null descriptor\n");
+ spin_unlock_bh(&iop_chan->lock);
+}
+
+static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan)
+{
+ struct iop_adma_desc_slot *sw_desc, *grp_start;
+ dma_cookie_t cookie;
+ int slot_cnt, slots_per_op;
+
+ dev_dbg(iop_chan->device->common.dev, "%s\n", __FUNCTION__);
+
+ spin_lock_bh(&iop_chan->lock);
+ slot_cnt = iop_chan_xor_slot_count(0, 2, &slots_per_op);
+ sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op);
+ if (sw_desc) {
+ grp_start = sw_desc->group_head;
+ list_splice_init(&sw_desc->async_tx.tx_list, &iop_chan->chain);
+ sw_desc->async_tx.ack = 1;
+ iop_desc_init_null_xor(grp_start, 2, 0);
+ iop_desc_set_byte_count(grp_start, iop_chan, 0);
+ iop_desc_set_dest_addr(grp_start, iop_chan, 0);
+ iop_desc_set_xor_src_addr(grp_start, 0, 0);
+ iop_desc_set_xor_src_addr(grp_start, 1, 0);
+
+ cookie = iop_chan->common.cookie;
+ cookie++;
+ if (cookie <= 1)
+ cookie = 2;
+
+ /* initialize the completed cookie to be less than
+ * the most recently used cookie
+ */
+ iop_chan->completed_cookie = cookie - 1;
+ iop_chan->common.cookie = sw_desc->async_tx.cookie = cookie;
+
+ /* channel should not be busy */
+ BUG_ON(iop_chan_is_busy(iop_chan));
+
+ /* clear any prior error-status bits */
+ iop_adma_device_clear_err_status(iop_chan);
+
+ /* disable operation */
+ iop_chan_disable(iop_chan);
+
+ /* set the descriptor address */
+ iop_chan_set_next_descriptor(iop_chan, sw_desc->async_tx.phys);
+
+ /* 1/ don't add pre-chained descriptors
+ * 2/ dummy read to flush next_desc write
+ */
+ BUG_ON(iop_desc_get_next_desc(sw_desc));
+
+ /* run the descriptor */
+ iop_chan_enable(iop_chan);
+ } else
+ dev_printk(KERN_ERR, iop_chan->device->common.dev,
+ "failed to allocate null descriptor\n");
+ spin_unlock_bh(&iop_chan->lock);
+}
+
+static struct platform_driver iop_adma_driver = {
+ .probe = iop_adma_probe,
+ .remove = iop_adma_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "iop-adma",
+ },
+};
+
+static int __init iop_adma_init (void)
+{
+ /* it's currently unsafe to unload this module */
+ /* if forced, worst case is that rmmod hangs */
+ __unsafe(THIS_MODULE);
+
+ return platform_driver_register(&iop_adma_driver);
+}
+
+static void __exit iop_adma_exit (void)
+{
+ platform_driver_unregister(&iop_adma_driver);
+ return;
+}
+
+module_init(iop_adma_init);
+module_exit(iop_adma_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("IOP ADMA Engine Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index 396dade731f..d011a76f8e7 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -4,27 +4,44 @@ comment "An alternative FireWire stack is available with EXPERIMENTAL=y"
depends on EXPERIMENTAL=n
config FIREWIRE
- tristate "IEEE 1394 (FireWire) support (JUJU alternative stack, experimental)"
+ tristate "IEEE 1394 (FireWire) support - alternative stack, EXPERIMENTAL"
depends on EXPERIMENTAL
select CRC_ITU_T
help
- IEEE 1394 describes a high performance serial bus, which is also
- known as FireWire(tm) or i.Link(tm) and is used for connecting all
- sorts of devices (most notably digital video cameras) to your
- computer.
-
- If you have FireWire hardware and want to use it, say Y here. This
- is the core support only, you will also need to select a driver for
- your IEEE 1394 adapter.
-
- To compile this driver as a module, say M here: the module will be
- called firewire-core.
-
- This is the "JUJU" FireWire stack, an alternative implementation
+ This is the "Juju" FireWire stack, a new alternative implementation
designed for robustness and simplicity. You can build either this
stack, or the classic stack (the ieee1394 driver, ohci1394 etc.)
or both.
+ To compile this driver as a module, say M here: the module will be
+ called firewire-core. It functionally replaces ieee1394, raw1394,
+ and video1394.
+
+ NOTE:
+
+ You should only build ONE of the stacks, unless you REALLY know what
+ you are doing. If you install both, you should configure them only as
+ modules rather than link them statically, and you should blacklist one
+ of the concurrent low-level drivers in /etc/modprobe.conf. Add either
+
+ blacklist firewire-ohci
+ or
+ blacklist ohci1394
+
+ there depending on which driver you DON'T want to have auto-loaded.
+ You can optionally do the same with the other IEEE 1394/ FireWire
+ drivers.
+
+ If you have an old modprobe which doesn't implement the blacklist
+ directive, use either
+
+ install firewire-ohci /bin/true
+ or
+ install ohci1394 /bin/true
+
+ and so on, depending on which modules you DON't want to have
+ auto-loaded.
+
config FIREWIRE_OHCI
tristate "Support for OHCI FireWire host controllers"
depends on PCI && FIREWIRE
@@ -34,11 +51,13 @@ config FIREWIRE_OHCI
is the only chipset in use, so say Y here.
To compile this driver as a module, say M here: The module will be
- called firewire-ohci.
+ called firewire-ohci. It replaces ohci1394 of the classic IEEE 1394
+ stack.
+
+ NOTE:
- If you also build ohci1394 of the classic IEEE 1394 driver stack,
- blacklist either ohci1394 or firewire-ohci to let hotplug load the
- desired driver.
+ If you also build ohci1394 of the classic stack, blacklist either
+ ohci1394 or firewire-ohci to let hotplug load only the desired driver.
config FIREWIRE_SBP2
tristate "Support for storage devices (SBP-2 protocol driver)"
@@ -50,12 +69,14 @@ config FIREWIRE_SBP2
like scanners.
To compile this driver as a module, say M here: The module will be
- called firewire-sbp2.
+ called firewire-sbp2. It replaces sbp2 of the classic IEEE 1394
+ stack.
You should also enable support for disks, CD-ROMs, etc. in the SCSI
configuration section.
- If you also build sbp2 of the classic IEEE 1394 driver stack,
- blacklist either sbp2 or firewire-sbp2 to let hotplug load the
- desired driver.
+ NOTE:
+
+ If you also build sbp2 of the classic stack, blacklist either sbp2
+ or firewire-sbp2 to let hotplug load only the desired driver.
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
index 636151a64ad..0aeab3218bb 100644
--- a/drivers/firewire/fw-card.c
+++ b/drivers/firewire/fw-card.c
@@ -336,8 +336,11 @@ fw_card_bm_work(struct work_struct *work)
}
pick_me:
- /* Now figure out what gap count to set. */
- if (card->topology_type == FW_TOPOLOGY_A &&
+ /*
+ * Pick a gap count from 1394a table E-1. The table doesn't cover
+ * the typically much larger 1394b beta repeater delays though.
+ */
+ if (!card->beta_repeaters_present &&
card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
gap_count = gap_count_table[card->root_node->max_hops];
else
@@ -407,11 +410,6 @@ fw_card_add(struct fw_card *card,
card->link_speed = link_speed;
card->guid = guid;
- /* Activate link_on bit and contender bit in our self ID packets.*/
- if (card->driver->update_phy_reg(card, 4, 0,
- PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
- return -EIO;
-
/*
* The subsystem grabs a reference when the card is added and
* drops it when the driver calls fw_core_remove_card.
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index 3ab3585d360..75388641a7d 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -397,7 +397,7 @@ static int ioctl_send_request(struct client *client, void *buffer)
request->tcode & 0x1f,
device->node->node_id,
request->generation,
- device->node->max_speed,
+ device->max_speed,
request->offset,
response->response.data, request->length,
complete_transaction, response);
@@ -640,6 +640,7 @@ iso_callback(struct fw_iso_context *context, u32 cycle,
static int ioctl_create_iso_context(struct client *client, void *buffer)
{
struct fw_cdev_create_iso_context *request = buffer;
+ struct fw_iso_context *context;
if (request->channel > 63)
return -EINVAL;
@@ -661,15 +662,17 @@ static int ioctl_create_iso_context(struct client *client, void *buffer)
return -EINVAL;
}
+ context = fw_iso_context_create(client->device->card,
+ request->type,
+ request->channel,
+ request->speed,
+ request->header_size,
+ iso_callback, client);
+ if (IS_ERR(context))
+ return PTR_ERR(context);
+
client->iso_closure = request->closure;
- client->iso_context = fw_iso_context_create(client->device->card,
- request->type,
- request->channel,
- request->speed,
- request->header_size,
- iso_callback, client);
- if (IS_ERR(client->iso_context))
- return PTR_ERR(client->iso_context);
+ client->iso_context = context;
/* We only support one context at this time. */
request->handle = 0;
@@ -677,12 +680,21 @@ static int ioctl_create_iso_context(struct client *client, void *buffer)
return 0;
}
+/* Macros for decoding the iso packet control header. */
+#define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff)
+#define GET_INTERRUPT(v) (((v) >> 16) & 0x01)
+#define GET_SKIP(v) (((v) >> 17) & 0x01)
+#define GET_TAG(v) (((v) >> 18) & 0x02)
+#define GET_SY(v) (((v) >> 20) & 0x04)
+#define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff)
+
static int ioctl_queue_iso(struct client *client, void *buffer)
{
struct fw_cdev_queue_iso *request = buffer;
struct fw_cdev_iso_packet __user *p, *end, *next;
struct fw_iso_context *ctx = client->iso_context;
unsigned long payload, buffer_end, header_length;
+ u32 control;
int count;
struct {
struct fw_iso_packet packet;
@@ -717,8 +729,14 @@ static int ioctl_queue_iso(struct client *client, void *buffer)
end = (void __user *)p + request->size;
count = 0;
while (p < end) {
- if (__copy_from_user(&u.packet, p, sizeof(*p)))
+ if (get_user(control, &p->control))
return -EFAULT;
+ u.packet.payload_length = GET_PAYLOAD_LENGTH(control);
+ u.packet.interrupt = GET_INTERRUPT(control);
+ u.packet.skip = GET_SKIP(control);
+ u.packet.tag = GET_TAG(control);
+ u.packet.sy = GET_SY(control);
+ u.packet.header_length = GET_HEADER_LENGTH(control);
if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {
header_length = u.packet.header_length;
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index c1ce465d971..2b658634163 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -401,8 +401,7 @@ static int read_rom(struct fw_device *device, int index, u32 * data)
offset = 0xfffff0000400ULL + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
- device->node_id,
- device->generation, SCODE_100,
+ device->node_id, device->generation, device->max_speed,
offset, NULL, 4, complete_transaction, &callback_data);
wait_for_completion(&callback_data.done);
@@ -418,6 +417,8 @@ static int read_bus_info_block(struct fw_device *device)
u32 stack[16], sp, key;
int i, end, length;
+ device->max_speed = SCODE_100;
+
/* First read the bus info block. */
for (i = 0; i < 5; i++) {
if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
@@ -434,6 +435,33 @@ static int read_bus_info_block(struct fw_device *device)
return -1;
}
+ device->max_speed = device->node->max_speed;
+
+ /*
+ * Determine the speed of
+ * - devices with link speed less than PHY speed,
+ * - devices with 1394b PHY (unless only connected to 1394a PHYs),
+ * - all devices if there are 1394b repeaters.
+ * Note, we cannot use the bus info block's link_spd as starting point
+ * because some buggy firmwares set it lower than necessary and because
+ * 1394-1995 nodes do not have the field.
+ */
+ if ((rom[2] & 0x7) < device->max_speed ||
+ device->max_speed == SCODE_BETA ||
+ device->card->beta_repeaters_present) {
+ u32 dummy;
+
+ /* for S1600 and S3200 */
+ if (device->max_speed == SCODE_BETA)
+ device->max_speed = device->card->link_speed;
+
+ while (device->max_speed > SCODE_100) {
+ if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
+ break;
+ device->max_speed--;
+ }
+ }
+
/*
* Now parse the config rom. The config rom is a recursive
* directory structure so we parse it using a stack of
@@ -680,8 +708,10 @@ static void fw_device_init(struct work_struct *work)
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
fw_device_shutdown(&device->work.work);
else
- fw_notify("created new fw device %s (%d config rom retries)\n",
- device->device.bus_id, device->config_rom_retries);
+ fw_notify("created new fw device %s "
+ "(%d config rom retries, S%d00)\n",
+ device->device.bus_id, device->config_rom_retries,
+ 1 << device->max_speed);
/*
* Reschedule the IRM work if we just finished reading the
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index 0ba9d64ccf4..d13e6a69707 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -40,6 +40,7 @@ struct fw_device {
struct fw_node *node;
int node_id;
int generation;
+ unsigned max_speed;
struct fw_card *card;
struct device device;
struct list_head link;
@@ -99,6 +100,7 @@ fw_unit(struct device *dev)
#define CSR_DEPENDENT_INFO 0x14
#define CSR_MODEL 0x17
#define CSR_INSTANCE 0x18
+#define CSR_DIRECTORY_ID 0x20
#define SBP2_COMMAND_SET_SPECIFIER 0x38
#define SBP2_COMMAND_SET 0x39
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 2e4cfa57126..41476abc069 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -373,8 +373,8 @@ static void ar_context_tasklet(unsigned long data)
offset = offsetof(struct ar_buffer, data);
dma_unmap_single(ohci->card.device,
- ab->descriptor.data_address - offset,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
+ le32_to_cpu(ab->descriptor.data_address) - offset,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
buffer = ab;
ab = ab->next;
@@ -417,12 +417,21 @@ ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs)
ctx->current_buffer = ab.next;
ctx->pointer = ctx->current_buffer->data;
- reg_write(ctx->ohci, COMMAND_PTR(ctx->regs),
- le32_to_cpu(ab.descriptor.branch_address));
+ return 0;
+}
+
+static void ar_context_run(struct ar_context *ctx)
+{
+ struct ar_buffer *ab = ctx->current_buffer;
+ dma_addr_t ab_bus;
+ size_t offset;
+
+ offset = offsetof(struct ar_buffer, data);
+ ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+
+ reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab_bus | 1);
reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
flush_writes(ctx->ohci);
-
- return 0;
}
static void context_tasklet(unsigned long data)
@@ -992,7 +1001,7 @@ static irqreturn_t irq_handler(int irq, void *data)
event = reg_read(ohci, OHCI1394_IntEventClear);
- if (!event)
+ if (!event || !~event)
return IRQ_NONE;
reg_write(ohci, OHCI1394_IntEventClear, event);
@@ -1039,11 +1048,78 @@ static irqreturn_t irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
+static int software_reset(struct fw_ohci *ohci)
+{
+ int i;
+
+ reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
+
+ for (i = 0; i < OHCI_LOOP_COUNT; i++) {
+ if ((reg_read(ohci, OHCI1394_HCControlSet) &
+ OHCI1394_HCControl_softReset) == 0)
+ return 0;
+ msleep(1);
+ }
+
+ return -EBUSY;
+}
+
static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
{
struct fw_ohci *ohci = fw_ohci(card);
struct pci_dev *dev = to_pci_dev(card->device);
+ if (software_reset(ohci)) {
+ fw_error("Failed to reset ohci card.\n");
+ return -EBUSY;
+ }
+
+ /*
+ * Now enable LPS, which we need in order to start accessing
+ * most of the registers. In fact, on some cards (ALI M5251),
+ * accessing registers in the SClk domain without LPS enabled
+ * will lock up the machine. Wait 50msec to make sure we have
+ * full link enabled.
+ */
+ reg_write(ohci, OHCI1394_HCControlSet,
+ OHCI1394_HCControl_LPS |
+ OHCI1394_HCControl_postedWriteEnable);
+ flush_writes(ohci);
+ msleep(50);
+
+ reg_write(ohci, OHCI1394_HCControlClear,
+ OHCI1394_HCControl_noByteSwapData);
+
+ reg_write(ohci, OHCI1394_LinkControlSet,
+ OHCI1394_LinkControl_rcvSelfID |
+ OHCI1394_LinkControl_cycleTimerEnable |
+ OHCI1394_LinkControl_cycleMaster);
+
+ reg_write(ohci, OHCI1394_ATRetries,
+ OHCI1394_MAX_AT_REQ_RETRIES |
+ (OHCI1394_MAX_AT_RESP_RETRIES << 4) |
+ (OHCI1394_MAX_PHYS_RESP_RETRIES << 8));
+
+ ar_context_run(&ohci->ar_request_ctx);
+ ar_context_run(&ohci->ar_response_ctx);
+
+ reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
+ reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
+ reg_write(ohci, OHCI1394_IntEventClear, ~0);
+ reg_write(ohci, OHCI1394_IntMaskClear, ~0);
+ reg_write(ohci, OHCI1394_IntMaskSet,
+ OHCI1394_selfIDComplete |
+ OHCI1394_RQPkt | OHCI1394_RSPkt |
+ OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
+ OHCI1394_isochRx | OHCI1394_isochTx |
+ OHCI1394_masterIntEnable |
+ OHCI1394_cycle64Seconds);
+
+ /* Activate link_on bit and contender bit in our self ID packets.*/
+ if (ohci_update_phy_reg(card, 4, 0,
+ PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
+ return -EIO;
+
/*
* When the link is not yet enabled, the atomic config rom
* update mechanism described below in ohci_set_config_rom()
@@ -1701,22 +1777,6 @@ static const struct fw_card_driver ohci_driver = {
.stop_iso = ohci_stop_iso,
};
-static int software_reset(struct fw_ohci *ohci)
-{
- int i;
-
- reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
-
- for (i = 0; i < OHCI_LOOP_COUNT; i++) {
- if ((reg_read(ohci, OHCI1394_HCControlSet) &
- OHCI1394_HCControl_softReset) == 0)
- return 0;
- msleep(1);
- }
-
- return -EBUSY;
-}
-
static int __devinit
pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
@@ -1762,33 +1822,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
goto fail_iomem;
}
- if (software_reset(ohci)) {
- fw_error("Failed to reset ohci card.\n");
- err = -EBUSY;
- goto fail_registers;
- }
-
- /*
- * Now enable LPS, which we need in order to start accessing
- * most of the registers. In fact, on some cards (ALI M5251),
- * accessing registers in the SClk domain without LPS enabled
- * will lock up the machine. Wait 50msec to make sure we have
- * full link enabled.
- */
- reg_write(ohci, OHCI1394_HCControlSet,
- OHCI1394_HCControl_LPS |
- OHCI1394_HCControl_postedWriteEnable);
- flush_writes(ohci);
- msleep(50);
-
- reg_write(ohci, OHCI1394_HCControlClear,
- OHCI1394_HCControl_noByteSwapData);
-
- reg_write(ohci, OHCI1394_LinkControlSet,
- OHCI1394_LinkControl_rcvSelfID |
- OHCI1394_LinkControl_cycleTimerEnable |
- OHCI1394_LinkControl_cycleMaster);
-
ar_context_init(&ohci->ar_request_ctx, ohci,
OHCI1394_AsReqRcvContextControlSet);
@@ -1801,11 +1834,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE,
OHCI1394_AsRspTrContextControlSet, handle_at_packet);
- reg_write(ohci, OHCI1394_ATRetries,
- OHCI1394_MAX_AT_REQ_RETRIES |
- (OHCI1394_MAX_AT_RESP_RETRIES << 4) |
- (OHCI1394_MAX_PHYS_RESP_RETRIES << 8));
-
reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
@@ -1835,18 +1863,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
goto fail_registers;
}
- reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
- reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
- reg_write(ohci, OHCI1394_IntEventClear, ~0);
- reg_write(ohci, OHCI1394_IntMaskClear, ~0);
- reg_write(ohci, OHCI1394_IntMaskSet,
- OHCI1394_selfIDComplete |
- OHCI1394_RQPkt | OHCI1394_RSPkt |
- OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
- OHCI1394_isochRx | OHCI1394_isochTx |
- OHCI1394_masterIntEnable |
- OHCI1394_cycle64Seconds);
-
bus_options = reg_read(ohci, OHCI1394_BusOptions);
max_receive = (bus_options >> 12) & 0xf;
link_speed = bus_options & 0x7;
@@ -1908,6 +1924,45 @@ static void pci_remove(struct pci_dev *dev)
fw_notify("Removed fw-ohci device.\n");
}
+#ifdef CONFIG_PM
+static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct fw_ohci *ohci = pci_get_drvdata(pdev);
+ int err;
+
+ software_reset(ohci);
+ free_irq(pdev->irq, ohci);
+ err = pci_save_state(pdev);
+ if (err) {
+ fw_error("pci_save_state failed\n");
+ return err;
+ }
+ err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (err) {
+ fw_error("pci_set_power_state failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int pci_resume(struct pci_dev *pdev)
+{
+ struct fw_ohci *ohci = pci_get_drvdata(pdev);
+ int err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ err = pci_enable_device(pdev);
+ if (err) {
+ fw_error("pci_enable_device failed\n");
+ return err;
+ }
+
+ return ohci_enable(&ohci->card, ohci->config_rom, CONFIG_ROM_SIZE);
+}
+#endif
+
static struct pci_device_id pci_table[] = {
{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) },
{ }
@@ -1920,6 +1975,10 @@ static struct pci_driver fw_ohci_pci_driver = {
.id_table = pci_table,
.probe = pci_probe,
.remove = pci_remove,
+#ifdef CONFIG_PM
+ .resume = pci_resume,
+ .suspend = pci_suspend,
+#endif
};
MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 68300414e5f..7c53be0387f 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -30,10 +30,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/mod_devicetable.h>
#include <linux/device.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
+#include <linux/string.h>
#include <linux/timer.h>
#include <scsi/scsi.h>
@@ -46,6 +49,18 @@
#include "fw-topology.h"
#include "fw-device.h"
+/*
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
+ *
+ * Concurrent logins are useful together with cluster filesystems.
+ */
+static int sbp2_param_exclusive_login = 1;
+module_param_named(exclusive_login, sbp2_param_exclusive_login, bool, 0644);
+MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
+ "(default = Y, use N for concurrent initiators)");
+
/* I don't know why the SCSI stack doesn't define something like this... */
typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
@@ -154,7 +169,7 @@ struct sbp2_orb {
#define MANAGEMENT_ORB_LUN(v) ((v))
#define MANAGEMENT_ORB_FUNCTION(v) ((v) << 16)
#define MANAGEMENT_ORB_RECONNECT(v) ((v) << 20)
-#define MANAGEMENT_ORB_EXCLUSIVE ((1) << 28)
+#define MANAGEMENT_ORB_EXCLUSIVE(v) ((v) ? 1 << 28 : 0)
#define MANAGEMENT_ORB_REQUEST_FORMAT(v) ((v) << 29)
#define MANAGEMENT_ORB_NOTIFY ((1) << 31)
@@ -205,9 +220,8 @@ struct sbp2_command_orb {
scsi_done_fn_t done;
struct fw_unit *unit;
- struct sbp2_pointer page_table[SG_ALL];
+ struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
dma_addr_t page_table_bus;
- dma_addr_t request_buffer_bus;
};
/*
@@ -347,8 +361,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
spin_unlock_irqrestore(&device->card->lock, flags);
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
- node_id, generation,
- device->node->max_speed, offset,
+ node_id, generation, device->max_speed, offset,
&orb->pointer, sizeof(orb->pointer),
complete_transaction, orb);
}
@@ -383,7 +396,7 @@ static void
complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{
struct sbp2_management_orb *orb =
- (struct sbp2_management_orb *)base_orb;
+ container_of(base_orb, struct sbp2_management_orb, base);
if (status)
memcpy(&orb->status, status, sizeof(*status));
@@ -403,21 +416,11 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
if (orb == NULL)
return -ENOMEM;
- /*
- * The sbp2 device is going to send a block read request to
- * read out the request from host memory, so map it for dma.
- */
- orb->base.request_bus =
- dma_map_single(device->card->device, &orb->request,
- sizeof(orb->request), DMA_TO_DEVICE);
- if (dma_mapping_error(orb->base.request_bus))
- goto out;
-
orb->response_bus =
dma_map_single(device->card->device, &orb->response,
sizeof(orb->response), DMA_FROM_DEVICE);
if (dma_mapping_error(orb->response_bus))
- goto out;
+ goto fail_mapping_response;
orb->request.response.high = 0;
orb->request.response.low = orb->response_bus;
@@ -432,14 +435,9 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
orb->request.status_fifo.high = sd->address_handler.offset >> 32;
orb->request.status_fifo.low = sd->address_handler.offset;
- /*
- * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive
- * login and 1 second reconnect time. The reconnect setting
- * is probably fine, but the exclusive login should be an option.
- */
if (function == SBP2_LOGIN_REQUEST) {
orb->request.misc |=
- MANAGEMENT_ORB_EXCLUSIVE |
+ MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
MANAGEMENT_ORB_RECONNECT(0);
}
@@ -448,6 +446,12 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
init_completion(&orb->done);
orb->base.callback = complete_management_orb;
+ orb->base.request_bus =
+ dma_map_single(device->card->device, &orb->request,
+ sizeof(orb->request), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->base.request_bus))
+ goto fail_mapping_request;
+
sbp2_send_orb(&orb->base, unit,
node_id, generation, sd->management_agent_address);
@@ -479,9 +483,10 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
out:
dma_unmap_single(device->card->device, orb->base.request_bus,
sizeof(orb->request), DMA_TO_DEVICE);
+ fail_mapping_request:
dma_unmap_single(device->card->device, orb->response_bus,
sizeof(orb->response), DMA_FROM_DEVICE);
-
+ fail_mapping_response:
if (response)
fw_memcpy_from_be32(response,
orb->response, sizeof(orb->response));
@@ -511,7 +516,7 @@ static int sbp2_agent_reset(struct fw_unit *unit)
return -ENOMEM;
fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
- sd->node_id, sd->generation, SCODE_400,
+ sd->node_id, sd->generation, device->max_speed,
sd->command_block_agent_address + SBP2_AGENT_RESET,
&zero, sizeof(zero), complete_agent_reset_write, t);
@@ -521,17 +526,15 @@ static int sbp2_agent_reset(struct fw_unit *unit)
static void sbp2_reconnect(struct work_struct *work);
static struct scsi_host_template scsi_driver_template;
-static void
-release_sbp2_device(struct kref *kref)
+static void release_sbp2_device(struct kref *kref)
{
struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
struct Scsi_Host *host =
container_of((void *)sd, struct Scsi_Host, hostdata[0]);
+ scsi_remove_host(host);
sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
-
- scsi_remove_host(host);
fw_core_remove_address_handler(&sd->address_handler);
fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
put_device(&sd->unit->device);
@@ -833,7 +836,8 @@ sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
static void
complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{
- struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb;
+ struct sbp2_command_orb *orb =
+ container_of(base_orb, struct sbp2_command_orb, base);
struct fw_unit *unit = orb->unit;
struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg;
@@ -880,12 +884,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
if (orb->page_table_bus != 0)
dma_unmap_single(device->card->device, orb->page_table_bus,
- sizeof(orb->page_table_bus), DMA_TO_DEVICE);
-
- if (orb->request_buffer_bus != 0)
- dma_unmap_single(device->card->device, orb->request_buffer_bus,
- sizeof(orb->request_buffer_bus),
- DMA_FROM_DEVICE);
+ sizeof(orb->page_table), DMA_TO_DEVICE);
orb->cmd->result = result;
orb->done(orb->cmd);
@@ -900,7 +899,6 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
struct fw_device *device = fw_device(unit->device.parent);
struct scatterlist *sg;
int sg_len, l, i, j, count;
- size_t size;
dma_addr_t sg_addr;
sg = (struct scatterlist *)orb->cmd->request_buffer;
@@ -935,6 +933,11 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
sg_len = sg_dma_len(sg + i);
sg_addr = sg_dma_address(sg + i);
while (sg_len) {
+ /* FIXME: This won't get us out of the pinch. */
+ if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
+ fw_error("page table overflow\n");
+ goto fail_page_table;
+ }
l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
orb->page_table[j].low = sg_addr;
orb->page_table[j].high = (l << 16);
@@ -944,7 +947,13 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
}
}
- size = sizeof(orb->page_table[0]) * j;
+ fw_memcpy_to_be32(orb->page_table, orb->page_table,
+ sizeof(orb->page_table[0]) * j);
+ orb->page_table_bus =
+ dma_map_single(device->card->device, orb->page_table,
+ sizeof(orb->page_table), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->page_table_bus))
+ goto fail_page_table;
/*
* The data_descriptor pointer is the one case where we need
@@ -953,20 +962,12 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
* initiator (i.e. us), but data_descriptor can refer to data
* on other nodes so we need to put our ID in descriptor.high.
*/
-
- orb->page_table_bus =
- dma_map_single(device->card->device, orb->page_table,
- size, DMA_TO_DEVICE);
- if (dma_mapping_error(orb->page_table_bus))
- goto fail_page_table;
orb->request.data_descriptor.high = sd->address_high;
orb->request.data_descriptor.low = orb->page_table_bus;
orb->request.misc |=
COMMAND_ORB_PAGE_TABLE_PRESENT |
COMMAND_ORB_DATA_SIZE(j);
- fw_memcpy_to_be32(orb->page_table, orb->page_table, size);
-
return 0;
fail_page_table:
@@ -991,7 +992,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
* transfer direction not handled.
*/
if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
- fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+ fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
cmd->result = DID_ERROR << 16;
done(cmd);
return 0;
@@ -1005,11 +1006,6 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
/* Initialize rcode to something not RCODE_COMPLETE. */
orb->base.rcode = -1;
- orb->base.request_bus =
- dma_map_single(device->card->device, &orb->request,
- sizeof(orb->request), DMA_TO_DEVICE);
- if (dma_mapping_error(orb->base.request_bus))
- goto fail_mapping;
orb->unit = unit;
orb->done = done;
@@ -1024,8 +1020,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
* if we set this to max_speed + 7, we get the right value.
*/
orb->request.misc =
- COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) |
- COMMAND_ORB_SPEED(device->node->max_speed) |
+ COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
+ COMMAND_ORB_SPEED(device->max_speed) |
COMMAND_ORB_NOTIFY;
if (cmd->sc_data_direction == DMA_FROM_DEVICE)
@@ -1036,7 +1032,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
- goto fail_map_payload;
+ goto fail_mapping;
fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
@@ -1045,15 +1041,17 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
orb->base.callback = complete_command_orb;
+ orb->base.request_bus =
+ dma_map_single(device->card->device, &orb->request,
+ sizeof(orb->request), DMA_TO_DEVICE);
+ if (dma_mapping_error(orb->base.request_bus))
+ goto fail_mapping;
sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
sd->command_block_agent_address + SBP2_ORB_POINTER);
return 0;
- fail_map_payload:
- dma_unmap_single(device->card->device, orb->base.request_bus,
- sizeof(orb->request), DMA_TO_DEVICE);
fail_mapping:
kfree(orb);
fail_alloc:
@@ -1087,7 +1085,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
sdev->fix_capacity = 1;
}
-
+ if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+ blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
return 0;
}
@@ -1108,6 +1107,58 @@ static int sbp2_scsi_abort(struct scsi_cmnd *cmd)
return SUCCESS;
}
+/*
+ * Format of /sys/bus/scsi/devices/.../ieee1394_id:
+ * u64 EUI-64 : u24 directory_ID : u16 LUN (all printed in hexadecimal)
+ *
+ * This is the concatenation of target port identifier and logical unit
+ * identifier as per SAM-2...SAM-4 annex A.
+ */
+static ssize_t
+sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct sbp2_device *sd;
+ struct fw_unit *unit;
+ struct fw_device *device;
+ u32 directory_id;
+ struct fw_csr_iterator ci;
+ int key, value, lun;
+
+ if (!sdev)
+ return 0;
+ sd = (struct sbp2_device *)sdev->host->hostdata;
+ unit = sd->unit;
+ device = fw_device(unit->device.parent);
+
+ /* implicit directory ID */
+ directory_id = ((unit->directory - device->config_rom) * 4
+ + CSR_CONFIG_ROM) & 0xffffff;
+
+ /* explicit directory ID, overrides implicit ID if present */
+ fw_csr_iterator_init(&ci, unit->directory);
+ while (fw_csr_iterator_next(&ci, &key, &value))
+ if (key == CSR_DIRECTORY_ID) {
+ directory_id = value;
+ break;
+ }
+
+ /* FIXME: Make this work for multi-lun devices. */
+ lun = 0;
+
+ return sprintf(buf, "%08x%08x:%06x:%04x\n",
+ device->config_rom[3], device->config_rom[4],
+ directory_id, lun);
+}
+
+static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
+
+static struct device_attribute *sbp2_scsi_sysfs_attrs[] = {
+ &dev_attr_ieee1394_id,
+ NULL
+};
+
static struct scsi_host_template scsi_driver_template = {
.module = THIS_MODULE,
.name = "SBP-2 IEEE-1394",
@@ -1121,6 +1172,7 @@ static struct scsi_host_template scsi_driver_template = {
.use_clustering = ENABLE_CLUSTERING,
.cmd_per_lun = 1,
.can_queue = 1,
+ .sdev_attrs = sbp2_scsi_sysfs_attrs,
};
MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index 7aebb8ae0ef..39e5cd12aa5 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -135,17 +135,17 @@ static void update_hop_count(struct fw_node *node)
int i;
for (i = 0; i < node->port_count; i++) {
- if (node->ports[i].node == NULL)
+ if (node->ports[i] == NULL)
continue;
- if (node->ports[i].node->max_hops > max_child_hops)
- max_child_hops = node->ports[i].node->max_hops;
+ if (node->ports[i]->max_hops > max_child_hops)
+ max_child_hops = node->ports[i]->max_hops;
- if (node->ports[i].node->max_depth > depths[0]) {
+ if (node->ports[i]->max_depth > depths[0]) {
depths[1] = depths[0];
- depths[0] = node->ports[i].node->max_depth;
- } else if (node->ports[i].node->max_depth > depths[1])
- depths[1] = node->ports[i].node->max_depth;
+ depths[0] = node->ports[i]->max_depth;
+ } else if (node->ports[i]->max_depth > depths[1])
+ depths[1] = node->ports[i]->max_depth;
}
node->max_depth = depths[0] + 1;
@@ -172,7 +172,8 @@ static struct fw_node *build_tree(struct fw_card *card,
struct list_head stack, *h;
u32 *next_sid, *end, q;
int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
- int gap_count, topology_type;
+ int gap_count;
+ bool beta_repeaters_present;
local_node = NULL;
node = NULL;
@@ -182,7 +183,7 @@ static struct fw_node *build_tree(struct fw_card *card,
phy_id = 0;
irm_node = NULL;
gap_count = SELF_ID_GAP_COUNT(*sid);
- topology_type = 0;
+ beta_repeaters_present = false;
while (sid < end) {
next_sid = count_ports(sid, &port_count, &child_port_count);
@@ -214,7 +215,7 @@ static struct fw_node *build_tree(struct fw_card *card,
node = fw_node_create(q, port_count, card->color);
if (node == NULL) {
- fw_error("Out of memory while building topology.");
+ fw_error("Out of memory while building topology.\n");
return NULL;
}
@@ -224,11 +225,6 @@ static struct fw_node *build_tree(struct fw_card *card,
if (SELF_ID_CONTENDER(q))
irm_node = node;
- if (node->phy_speed == SCODE_BETA)
- topology_type |= FW_TOPOLOGY_B;
- else
- topology_type |= FW_TOPOLOGY_A;
-
parent_count = 0;
for (i = 0; i < port_count; i++) {
@@ -249,12 +245,12 @@ static struct fw_node *build_tree(struct fw_card *card,
break;
case SELFID_PORT_CHILD:
- node->ports[i].node = child;
+ node->ports[i] = child;
/*
* Fix up parent reference for this
* child node.
*/
- child->ports[child->color].node = node;
+ child->ports[child->color] = node;
child->color = card->color;
child = fw_node(child->link.next);
break;
@@ -278,6 +274,10 @@ static struct fw_node *build_tree(struct fw_card *card,
list_add_tail(&node->link, &stack);
stack_depth += 1 - child_port_count;
+ if (node->phy_speed == SCODE_BETA &&
+ parent_count + child_port_count > 1)
+ beta_repeaters_present = true;
+
/*
* If all PHYs does not report the same gap count
* setting, we fall back to 63 which will force a gap
@@ -295,7 +295,7 @@ static struct fw_node *build_tree(struct fw_card *card,
card->root_node = node;
card->irm_node = irm_node;
card->gap_count = gap_count;
- card->topology_type = topology_type;
+ card->beta_repeaters_present = beta_repeaters_present;
return local_node;
}
@@ -321,7 +321,7 @@ for_each_fw_node(struct fw_card *card, struct fw_node *root,
node->color = card->color;
for (i = 0; i < node->port_count; i++) {
- child = node->ports[i].node;
+ child = node->ports[i];
if (!child)
continue;
if (child->color == card->color)
@@ -382,11 +382,11 @@ static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
struct fw_node *tree;
int i;
- tree = node1->ports[port].node;
- node0->ports[port].node = tree;
+ tree = node1->ports[port];
+ node0->ports[port] = tree;
for (i = 0; i < tree->port_count; i++) {
- if (tree->ports[i].node == node1) {
- tree->ports[i].node = node0;
+ if (tree->ports[i] == node1) {
+ tree->ports[i] = node0;
break;
}
}
@@ -437,19 +437,17 @@ update_tree(struct fw_card *card, struct fw_node *root)
card->irm_node = node0;
for (i = 0; i < node0->port_count; i++) {
- if (node0->ports[i].node && node1->ports[i].node) {
+ if (node0->ports[i] && node1->ports[i]) {
/*
* This port didn't change, queue the
* connected node for further
* investigation.
*/
- if (node0->ports[i].node->color == card->color)
+ if (node0->ports[i]->color == card->color)
continue;
- list_add_tail(&node0->ports[i].node->link,
- &list0);
- list_add_tail(&node1->ports[i].node->link,
- &list1);
- } else if (node0->ports[i].node) {
+ list_add_tail(&node0->ports[i]->link, &list0);
+ list_add_tail(&node1->ports[i]->link, &list1);
+ } else if (node0->ports[i]) {
/*
* The nodes connected here were
* unplugged; unref the lost nodes and
@@ -457,10 +455,10 @@ update_tree(struct fw_card *card, struct fw_node *root)
* them.
*/
- for_each_fw_node(card, node0->ports[i].node,
+ for_each_fw_node(card, node0->ports[i],
report_lost_node);
- node0->ports[i].node = NULL;
- } else if (node1->ports[i].node) {
+ node0->ports[i] = NULL;
+ } else if (node1->ports[i]) {
/*
* One or more node were connected to
* this port. Move the new nodes into
@@ -468,7 +466,7 @@ update_tree(struct fw_card *card, struct fw_node *root)
* callbacks for them.
*/
move_tree(node0, node1, i);
- for_each_fw_node(card, node0->ports[i].node,
+ for_each_fw_node(card, node0->ports[i],
report_found_node);
}
}
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
index 363b6cbcd0b..1b56b4ac7fb 100644
--- a/drivers/firewire/fw-topology.h
+++ b/drivers/firewire/fw-topology.h
@@ -20,12 +20,6 @@
#define __fw_topology_h
enum {
- FW_TOPOLOGY_A = 0x01,
- FW_TOPOLOGY_B = 0x02,
- FW_TOPOLOGY_MIXED = 0x03,
-};
-
-enum {
FW_NODE_CREATED = 0x00,
FW_NODE_UPDATED = 0x01,
FW_NODE_DESTROYED = 0x02,
@@ -33,21 +27,16 @@ enum {
FW_NODE_LINK_OFF = 0x04,
};
-struct fw_port {
- struct fw_node *node;
- unsigned speed : 3; /* S100, S200, ... S3200 */
-};
-
struct fw_node {
u16 node_id;
u8 color;
u8 port_count;
- unsigned link_on : 1;
- unsigned initiated_reset : 1;
- unsigned b_path : 1;
- u8 phy_speed : 3; /* As in the self ID packet. */
- u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on
- * the path from the local node to this node. */
+ u8 link_on : 1;
+ u8 initiated_reset : 1;
+ u8 b_path : 1;
+ u8 phy_speed : 2; /* As in the self ID packet. */
+ u8 max_speed : 2; /* Minimum of all phy-speeds on the path from the
+ * local node to this node. */
u8 max_depth : 4; /* Maximum depth to any leaf node */
u8 max_hops : 4; /* Max hops in this sub tree */
atomic_t ref_count;
@@ -58,7 +47,7 @@ struct fw_node {
/* Upper layer specific data. */
void *data;
- struct fw_port ports[0];
+ struct fw_node *ports[0];
};
static inline struct fw_node *
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index acdc3be38c6..5abed193f4a 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -81,7 +81,6 @@
#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
static inline void
fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
@@ -246,7 +245,7 @@ struct fw_card {
struct fw_node *irm_node;
int color;
int gap_count;
- int topology_type;
+ bool beta_repeaters_present;
int index;
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 88f462122a3..05f02a326f1 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -84,4 +84,13 @@ config DCDBAS
Say Y or M here to enable the driver for use by Dell systems
management software such as Dell OpenManage.
+config DMIID
+ bool "Export DMI identification via sysfs to userspace"
+ depends on DMI
+ default y
+ help
+ Say Y here if you want to query SMBIOS/DMI system identification
+ information from userspace through /sys/class/dmi/id/ or if you want
+ DMI-based module auto-loading.
+
endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 98e395f4bb2..8d4ebc805a5 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_PCDP) += pcdp.o
obj-$(CONFIG_DELL_RBU) += dell_rbu.o
obj-$(CONFIG_DCDBAS) += dcdbas.o
+obj-$(CONFIG_DMIID) += dmi-id.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 1865b56fb14..18cdcb3ae1c 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -149,8 +149,9 @@ static ssize_t smi_data_buf_size_store(struct device *dev,
return count;
}
-static ssize_t smi_data_read(struct kobject *kobj, char *buf, loff_t pos,
- size_t count)
+static ssize_t smi_data_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t count)
{
size_t max_read;
ssize_t ret;
@@ -170,8 +171,9 @@ out:
return ret;
}
-static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos,
- size_t count)
+static ssize_t smi_data_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t count)
{
ssize_t ret;
diff --git a/drivers/firmware/dcdbas.h b/drivers/firmware/dcdbas.h
index 58a85182b3e..dcdba0f1b32 100644
--- a/drivers/firmware/dcdbas.h
+++ b/drivers/firmware/dcdbas.h
@@ -67,8 +67,7 @@
#define DCDBAS_BIN_ATTR_RW(_name) \
struct bin_attribute bin_attr_##_name = { \
.attr = { .name = __stringify(_name), \
- .mode = 0600, \
- .owner = THIS_MODULE }, \
+ .mode = 0600 }, \
.read = _name##_read, \
.write = _name##_write, \
}
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index fc702e40bd4..477a3d0e3ca 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -543,8 +543,9 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
return ret_count;
}
-static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
- loff_t pos, size_t count)
+static ssize_t read_rbu_data(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t count)
{
ssize_t ret_count = 0;
@@ -591,8 +592,9 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
spin_unlock(&rbu_data.lock);
}
-static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
- loff_t pos, size_t count)
+static ssize_t read_rbu_image_type(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t count)
{
int size = 0;
if (!pos)
@@ -600,8 +602,9 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
return size;
}
-static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
- loff_t pos, size_t count)
+static ssize_t write_rbu_image_type(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t count)
{
int rc = count;
int req_firm_rc = 0;
@@ -660,8 +663,9 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
return rc;
}
-static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
- loff_t pos, size_t count)
+static ssize_t read_rbu_packet_size(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t count)
{
int size = 0;
if (!pos) {
@@ -672,8 +676,9 @@ static ssize_t read_rbu_packet_size(struct kobject *kobj, char *buffer,
return size;
}
-static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
- loff_t pos, size_t count)
+static ssize_t write_rbu_packet_size(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t count)
{
unsigned long temp;
spin_lock(&rbu_data.lock);
@@ -687,18 +692,18 @@ static ssize_t write_rbu_packet_size(struct kobject *kobj, char *buffer,
}
static struct bin_attribute rbu_data_attr = {
- .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
+ .attr = {.name = "data", .mode = 0444},
.read = read_rbu_data,
};
static struct bin_attribute rbu_image_type_attr = {
- .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
+ .attr = {.name = "image_type", .mode = 0644},
.read = read_rbu_image_type,
.write = write_rbu_image_type,
};
static struct bin_attribute rbu_packet_size_attr = {
- .attr = {.name = "packet_size",.owner = THIS_MODULE,.mode = 0644},
+ .attr = {.name = "packet_size", .mode = 0644},
.read = read_rbu_packet_size,
.write = write_rbu_packet_size,
};
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
new file mode 100644
index 00000000000..59c3b5aa89f
--- /dev/null
+++ b/drivers/firmware/dmi-id.c
@@ -0,0 +1,222 @@
+/*
+ * Export SMBIOS/DMI info via sysfs to userspace
+ *
+ * Copyright 2007, Lennart Poettering
+ *
+ * Licensed under GPLv2
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/device.h>
+#include <linux/autoconf.h>
+
+#define DEFINE_DMI_ATTR(_name, _mode, _show) \
+static struct device_attribute sys_dmi_##_name##_attr = \
+ __ATTR(_name, _mode, _show, NULL);
+
+#define DEFINE_DMI_ATTR_WITH_SHOW(_name, _mode, _field) \
+static ssize_t sys_dmi_##_name##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *page) \
+{ \
+ ssize_t len; \
+ len = scnprintf(page, PAGE_SIZE, "%s\n", dmi_get_system_info(_field)); \
+ page[len-1] = '\n'; \
+ return len; \
+} \
+DEFINE_DMI_ATTR(_name, _mode, sys_dmi_##_name##_show);
+
+DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor, 0444, DMI_BIOS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_version, 0444, DMI_BIOS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_date, 0444, DMI_BIOS_DATE);
+DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor, 0444, DMI_SYS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(product_name, 0444, DMI_PRODUCT_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID);
+DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME);
+DEFINE_DMI_ATTR_WITH_SHOW(board_version, 0444, DMI_BOARD_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(board_serial, 0400, DMI_BOARD_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(board_asset_tag, 0444, DMI_BOARD_ASSET_TAG);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_vendor, 0444, DMI_CHASSIS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_type, 0444, DMI_CHASSIS_TYPE);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_version, 0444, DMI_CHASSIS_VERSION);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_serial, 0400, DMI_CHASSIS_SERIAL);
+DEFINE_DMI_ATTR_WITH_SHOW(chassis_asset_tag, 0444, DMI_CHASSIS_ASSET_TAG);
+
+static void ascii_filter(char *d, const char *s)
+{
+ /* Filter out characters we don't want to see in the modalias string */
+ for (; *s; s++)
+ if (*s > ' ' && *s < 127 && *s != ':')
+ *(d++) = *s;
+
+ *d = 0;
+}
+
+static ssize_t get_modalias(char *buffer, size_t buffer_size)
+{
+ static const struct mafield {
+ const char *prefix;
+ int field;
+ } fields[] = {
+ { "bvn", DMI_BIOS_VENDOR },
+ { "bvr", DMI_BIOS_VERSION },
+ { "bd", DMI_BIOS_DATE },
+ { "svn", DMI_SYS_VENDOR },
+ { "pn", DMI_PRODUCT_NAME },
+ { "pvr", DMI_PRODUCT_VERSION },
+ { "rvn", DMI_BOARD_VENDOR },
+ { "rn", DMI_BOARD_NAME },
+ { "rvr", DMI_BOARD_VERSION },
+ { "cvn", DMI_CHASSIS_VENDOR },
+ { "ct", DMI_CHASSIS_TYPE },
+ { "cvr", DMI_CHASSIS_VERSION },
+ { NULL, DMI_NONE }
+ };
+
+ ssize_t l, left;
+ char *p;
+ const struct mafield *f;
+
+ strcpy(buffer, "dmi");
+ p = buffer + 3; left = buffer_size - 4;
+
+ for (f = fields; f->prefix && left > 0; f++) {
+ const char *c;
+ char *t;
+
+ c = dmi_get_system_info(f->field);
+ if (!c)
+ continue;
+
+ t = kmalloc(strlen(c) + 1, GFP_KERNEL);
+ if (!t)
+ break;
+ ascii_filter(t, c);
+ l = scnprintf(p, left, ":%s%s", f->prefix, t);
+ kfree(t);
+
+ p += l;
+ left -= l;
+ }
+
+ p[0] = ':';
+ p[1] = 0;
+
+ return p - buffer + 1;
+}
+
+static ssize_t sys_dmi_modalias_show(struct device *dev,
+ struct device_attribute *attr, char *page)
+{
+ ssize_t r;
+ r = get_modalias(page, PAGE_SIZE-1);
+ page[r] = '\n';
+ page[r+1] = 0;
+ return r+1;
+}
+
+DEFINE_DMI_ATTR(modalias, 0444, sys_dmi_modalias_show);
+
+static struct attribute *sys_dmi_attributes[DMI_STRING_MAX+2];
+
+static struct attribute_group sys_dmi_attribute_group = {
+ .attrs = sys_dmi_attributes,
+};
+
+static struct attribute_group* sys_dmi_attribute_groups[] = {
+ &sys_dmi_attribute_group,
+ NULL
+};
+
+static int dmi_dev_uevent(struct device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size)
+{
+ strcpy(buffer, "MODALIAS=");
+ get_modalias(buffer+9, buffer_size-9);
+ envp[0] = buffer;
+ envp[1] = NULL;
+
+ return 0;
+}
+
+static struct class dmi_class = {
+ .name = "dmi",
+ .dev_release = (void(*)(struct device *)) kfree,
+ .dev_uevent = dmi_dev_uevent,
+};
+
+static struct device *dmi_dev;
+
+/* Initialization */
+
+#define ADD_DMI_ATTR(_name, _field) \
+ if (dmi_get_system_info(_field)) \
+ sys_dmi_attributes[i++] = & sys_dmi_##_name##_attr.attr;
+
+extern int dmi_available;
+
+static int __init dmi_id_init(void)
+{
+ int ret, i;
+
+ if (!dmi_available)
+ return -ENODEV;
+
+ /* Not necessarily all DMI fields are available on all
+ * systems, hence let's built an attribute table of just
+ * what's available */
+ i = 0;
+ ADD_DMI_ATTR(bios_vendor, DMI_BIOS_VENDOR);
+ ADD_DMI_ATTR(bios_version, DMI_BIOS_VERSION);
+ ADD_DMI_ATTR(bios_date, DMI_BIOS_DATE);
+ ADD_DMI_ATTR(sys_vendor, DMI_SYS_VENDOR);
+ ADD_DMI_ATTR(product_name, DMI_PRODUCT_NAME);
+ ADD_DMI_ATTR(product_version, DMI_PRODUCT_VERSION);
+ ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL);
+ ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID);
+ ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR);
+ ADD_DMI_ATTR(board_name, DMI_BOARD_NAME);
+ ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION);
+ ADD_DMI_ATTR(board_serial, DMI_BOARD_SERIAL);
+ ADD_DMI_ATTR(board_asset_tag, DMI_BOARD_ASSET_TAG);
+ ADD_DMI_ATTR(chassis_vendor, DMI_CHASSIS_VENDOR);
+ ADD_DMI_ATTR(chassis_type, DMI_CHASSIS_TYPE);
+ ADD_DMI_ATTR(chassis_version, DMI_CHASSIS_VERSION);
+ ADD_DMI_ATTR(chassis_serial, DMI_CHASSIS_SERIAL);
+ ADD_DMI_ATTR(chassis_asset_tag, DMI_CHASSIS_ASSET_TAG);
+ sys_dmi_attributes[i++] = &sys_dmi_modalias_attr.attr;
+
+ ret = class_register(&dmi_class);
+ if (ret)
+ return ret;
+
+ dmi_dev = kzalloc(sizeof(*dmi_dev), GFP_KERNEL);
+ if (!dmi_dev) {
+ ret = -ENOMEM;
+ goto fail_class_unregister;
+ }
+
+ dmi_dev->class = &dmi_class;
+ strcpy(dmi_dev->bus_id, "id");
+ dmi_dev->groups = sys_dmi_attribute_groups;
+
+ ret = device_register(dmi_dev);
+ if (ret)
+ goto fail_class_unregister;
+
+ return 0;
+
+fail_class_unregister:
+
+ class_unregister(&dmi_class);
+
+ return ret;
+}
+
+arch_initcall(dmi_id_init);
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 37deee6c0c1..f7318b3b51f 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -84,6 +84,7 @@ static int __init dmi_checksum(u8 *buf)
static char *dmi_ident[DMI_STRING_MAX];
static LIST_HEAD(dmi_devices);
+int dmi_available;
/*
* Save a DMI string
@@ -102,6 +103,51 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
dmi_ident[slot] = p;
}
+static void __init dmi_save_uuid(struct dmi_header *dm, int slot, int index)
+{
+ u8 *d = (u8*) dm + index;
+ char *s;
+ int is_ff = 1, is_00 = 1, i;
+
+ if (dmi_ident[slot])
+ return;
+
+ for (i = 0; i < 16 && (is_ff || is_00); i++) {
+ if(d[i] != 0x00) is_ff = 0;
+ if(d[i] != 0xFF) is_00 = 0;
+ }
+
+ if (is_ff || is_00)
+ return;
+
+ s = dmi_alloc(16*2+4+1);
+ if (!s)
+ return;
+
+ sprintf(s,
+ "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+ d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+
+ dmi_ident[slot] = s;
+}
+
+static void __init dmi_save_type(struct dmi_header *dm, int slot, int index)
+{
+ u8 *d = (u8*) dm + index;
+ char *s;
+
+ if (dmi_ident[slot])
+ return;
+
+ s = dmi_alloc(4);
+ if (!s)
+ return;
+
+ sprintf(s, "%u", *d & 0x7F);
+ dmi_ident[slot] = s;
+}
+
static void __init dmi_save_devices(struct dmi_header *dm)
{
int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
@@ -192,11 +238,21 @@ static void __init dmi_decode(struct dmi_header *dm)
dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
+ dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
break;
case 2: /* Base Board Information */
dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
dmi_save_ident(dm, DMI_BOARD_NAME, 5);
dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
+ dmi_save_ident(dm, DMI_BOARD_SERIAL, 7);
+ dmi_save_ident(dm, DMI_BOARD_ASSET_TAG, 8);
+ break;
+ case 3: /* Chassis Information */
+ dmi_save_ident(dm, DMI_CHASSIS_VENDOR, 4);
+ dmi_save_type(dm, DMI_CHASSIS_TYPE, 5);
+ dmi_save_ident(dm, DMI_CHASSIS_VERSION, 6);
+ dmi_save_ident(dm, DMI_CHASSIS_SERIAL, 7);
+ dmi_save_ident(dm, DMI_CHASSIS_ASSET_TAG, 8);
break;
case 10: /* Onboard Devices Information */
dmi_save_devices(dm);
@@ -243,18 +299,20 @@ void __init dmi_scan_machine(void)
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
goto out;
- /* This is called as a core_initcall() because it isn't
- * needed during early boot. This also means we can
- * iounmap the space when we're done with it.
- */
+ /* This is called as a core_initcall() because it isn't
+ * needed during early boot. This also means we can
+ * iounmap the space when we're done with it.
+ */
p = dmi_ioremap(efi.smbios, 32);
if (p == NULL)
goto out;
rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
dmi_iounmap(p, 32);
- if (!rc)
+ if (!rc) {
+ dmi_available = 1;
return;
+ }
}
else {
/*
@@ -268,8 +326,10 @@ void __init dmi_scan_machine(void)
for (q = p; q < p + 0x10000; q += 16) {
rc = dmi_present(q);
- if (!rc)
+ if (!rc) {
+ dmi_available = 1;
return;
+ }
}
}
out: printk(KERN_INFO "DMI not present or invalid.\n");
@@ -404,3 +464,4 @@ int dmi_get_year(int field)
return year;
}
+
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index d8806e4f182..15232271d84 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -74,7 +74,7 @@ static struct edd_device *edd_devices[EDD_MBR_SIG_MAX];
#define EDD_DEVICE_ATTR(_name,_mode,_show,_test) \
struct edd_attribute edd_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.test = _test, \
};
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 1324984a4c3..bfd2d67df68 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -131,21 +131,21 @@ struct efivar_attribute {
#define EFI_ATTR(_name, _mode, _show, _store) \
struct subsys_attribute efi_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+ .attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};
#define EFIVAR_ATTR(_name, _mode, _show, _store) \
struct efivar_attribute efivar_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+ .attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};
#define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
struct subsys_attribute var_subsys_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+ .attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 8fbe9fdac12..3b63b0b7812 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1,8 +1,12 @@
#
# HID driver configuration
#
-menu "HID Devices"
+menuconfig HID_SUPPORT
+ bool "HID Devices"
depends on INPUT
+ default y
+
+if HID_SUPPORT
config HID
tristate "Generic HID support"
@@ -24,6 +28,7 @@ config HID
config HID_DEBUG
bool "HID debugging support"
+ default y if !EMBEDDED
depends on HID
---help---
This option lets the HID layer output diagnostics about its internal
@@ -38,5 +43,4 @@ config HID_DEBUG
source "drivers/hid/usbhid/Kconfig"
-endmenu
-
+endif # HID_SUPPORT
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6ec04e79f68..317cf8a7b63 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -40,6 +40,13 @@
#define DRIVER_DESC "HID core driver"
#define DRIVER_LICENSE "GPL"
+#ifdef CONFIG_HID_DEBUG
+int hid_debug = 0;
+module_param_named(debug, hid_debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Turn HID debugging mode on and off");
+EXPORT_SYMBOL_GPL(hid_debug);
+#endif
+
/*
* Register a new report for a device.
*/
@@ -78,7 +85,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
struct hid_field *field;
if (report->maxfield == HID_MAX_FIELDS) {
- dbg("too many fields in report");
+ dbg_hid("too many fields in report\n");
return NULL;
}
@@ -106,7 +113,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
usage = parser->local.usage[0];
if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
- dbg("collection stack overflow");
+ dbg_hid("collection stack overflow\n");
return -1;
}
@@ -114,7 +121,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
collection = kmalloc(sizeof(struct hid_collection) *
parser->device->collection_size * 2, GFP_KERNEL);
if (collection == NULL) {
- dbg("failed to reallocate collection array");
+ dbg_hid("failed to reallocate collection array\n");
return -1;
}
memcpy(collection, parser->device->collection,
@@ -150,7 +157,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
static int close_collection(struct hid_parser *parser)
{
if (!parser->collection_stack_ptr) {
- dbg("collection stack underflow");
+ dbg_hid("collection stack underflow\n");
return -1;
}
parser->collection_stack_ptr--;
@@ -178,7 +185,7 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type)
static int hid_add_usage(struct hid_parser *parser, unsigned usage)
{
if (parser->local.usage_index >= HID_MAX_USAGES) {
- dbg("usage index exceeded");
+ dbg_hid("usage index exceeded\n");
return -1;
}
parser->local.usage[parser->local.usage_index] = usage;
@@ -202,12 +209,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
int i;
if (!(report = hid_register_report(parser->device, report_type, parser->global.report_id))) {
- dbg("hid_register_report failed");
+ dbg_hid("hid_register_report failed\n");
return -1;
}
if (parser->global.logical_maximum < parser->global.logical_minimum) {
- dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
+ dbg_hid("logical range invalid %d %d\n", parser->global.logical_minimum, parser->global.logical_maximum);
return -1;
}
@@ -287,7 +294,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_PUSH:
if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
- dbg("global enviroment stack overflow");
+ dbg_hid("global enviroment stack overflow\n");
return -1;
}
@@ -298,7 +305,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_POP:
if (!parser->global_stack_ptr) {
- dbg("global enviroment stack underflow");
+ dbg_hid("global enviroment stack underflow\n");
return -1;
}
@@ -342,27 +349,27 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
if ((parser->global.report_size = item_udata(item)) > 32) {
- dbg("invalid report_size %d", parser->global.report_size);
+ dbg_hid("invalid report_size %d\n", parser->global.report_size);
return -1;
}
return 0;
case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
- dbg("invalid report_count %d", parser->global.report_count);
+ dbg_hid("invalid report_count %d\n", parser->global.report_count);
return -1;
}
return 0;
case HID_GLOBAL_ITEM_TAG_REPORT_ID:
if ((parser->global.report_id = item_udata(item)) == 0) {
- dbg("report_id 0 is invalid");
+ dbg_hid("report_id 0 is invalid\n");
return -1;
}
return 0;
default:
- dbg("unknown global tag 0x%x", item->tag);
+ dbg_hid("unknown global tag 0x%x\n", item->tag);
return -1;
}
}
@@ -377,7 +384,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
unsigned n;
if (item->size == 0) {
- dbg("item data expected for local item");
+ dbg_hid("item data expected for local item\n");
return -1;
}
@@ -395,14 +402,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
* items and the first delimiter set.
*/
if (parser->local.delimiter_depth != 0) {
- dbg("nested delimiters");
+ dbg_hid("nested delimiters\n");
return -1;
}
parser->local.delimiter_depth++;
parser->local.delimiter_branch++;
} else {
if (parser->local.delimiter_depth < 1) {
- dbg("bogus close delimiter");
+ dbg_hid("bogus close delimiter\n");
return -1;
}
parser->local.delimiter_depth--;
@@ -412,7 +419,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -424,7 +431,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -437,7 +444,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
if (parser->local.delimiter_branch > 1) {
- dbg("alternative usage ignored");
+ dbg_hid("alternative usage ignored\n");
return 0;
}
@@ -446,14 +453,14 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
for (n = parser->local.usage_minimum; n <= data; n++)
if (hid_add_usage(parser, n)) {
- dbg("hid_add_usage failed\n");
+ dbg_hid("hid_add_usage failed\n");
return -1;
}
return 0;
default:
- dbg("unknown local item tag 0x%x", item->tag);
+ dbg_hid("unknown local item tag 0x%x\n", item->tag);
return 0;
}
return 0;
@@ -487,7 +494,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
ret = hid_add_field(parser, HID_FEATURE_REPORT, data);
break;
default:
- dbg("unknown main item tag 0x%x", item->tag);
+ dbg_hid("unknown main item tag 0x%x\n", item->tag);
ret = 0;
}
@@ -502,7 +509,7 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item)
static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
{
- dbg("reserved item type, tag 0x%x", item->tag);
+ dbg_hid("reserved item type, tag 0x%x\n", item->tag);
return 0;
}
@@ -667,14 +674,14 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
while ((start = fetch_item(start, end, &item)) != NULL) {
if (item.format != HID_ITEM_FORMAT_SHORT) {
- dbg("unexpected long global item");
+ dbg_hid("unexpected long global item\n");
hid_free_device(device);
vfree(parser);
return NULL;
}
if (dispatch_type[item.type](parser, &item)) {
- dbg("item %u %u %u %u parsing failed\n",
+ dbg_hid("item %u %u %u %u parsing failed\n",
item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
hid_free_device(device);
vfree(parser);
@@ -683,13 +690,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
if (start == end) {
if (parser->collection_stack_ptr) {
- dbg("unbalanced collection at end of report description");
+ dbg_hid("unbalanced collection at end of report description\n");
hid_free_device(device);
vfree(parser);
return NULL;
}
if (parser->local.delimiter_depth) {
- dbg("unbalanced delimiter at end of report description");
+ dbg_hid("unbalanced delimiter at end of report description\n");
hid_free_device(device);
vfree(parser);
return NULL;
@@ -699,7 +706,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size)
}
}
- dbg("item fetching failed at offset %d\n", (int)(end - start));
+ dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
hid_free_device(device);
vfree(parser);
return NULL;
@@ -915,13 +922,13 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
hid_dump_input(field->usage + offset, value);
if (offset >= field->report_count) {
- dbg("offset (%d) exceeds report_count (%d)", offset, field->report_count);
+ dbg_hid("offset (%d) exceeds report_count (%d)\n", offset, field->report_count);
hid_dump_field(field, 8);
return -1;
}
if (field->logical_minimum < 0) {
if (value != snto32(s32ton(value, size), size)) {
- dbg("value %d is out of range", value);
+ dbg_hid("value %d is out of range\n", value);
return -1;
}
}
@@ -934,19 +941,17 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
{
struct hid_report_enum *report_enum = hid->report_enum + type;
struct hid_report *report;
- int n, rsize;
+ int n, rsize, i;
if (!hid)
return -ENODEV;
if (!size) {
- dbg("empty report");
+ dbg_hid("empty report\n");
return -1;
}
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
-#endif
+ dbg_hid("report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
n = 0; /* Normally report number is 0 */
if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
@@ -954,25 +959,21 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
size--;
}
-#ifdef CONFIG_HID_DEBUG
- {
- int i;
- printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
- for (i = 0; i < size; i++)
- printk(" %02x", data[i]);
- printk("\n");
- }
-#endif
+ /* dump the report descriptor */
+ dbg_hid("report %d (size %u) = ", n, size);
+ for (i = 0; i < size; i++)
+ dbg_hid_line(" %02x", data[i]);
+ dbg_hid_line("\n");
if (!(report = report_enum->report_id_hash[n])) {
- dbg("undefined report_id %d received", n);
+ dbg_hid("undefined report_id %d received\n", n);
return -1;
}
rsize = ((report->size - 1) >> 3) + 1;
if (size < rsize) {
- dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
+ dbg_hid("report %d is too short, (%d < %d)\n", report->id, size, rsize);
memset(data + size, 0, rsize - size);
}
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 83c4126b37c..a13757b7898 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -347,6 +347,9 @@ static void resolv_usage_page(unsigned page) {
void hid_resolv_usage(unsigned usage) {
const struct hid_usage_entry *p;
+ if (!hid_debug)
+ return;
+
resolv_usage_page(usage >> 16);
printk(".");
for (p = hid_usage_table; p->description; p++)
@@ -369,6 +372,9 @@ __inline__ static void tab(int n) {
void hid_dump_field(struct hid_field *field, int n) {
int j;
+ if (!hid_debug)
+ return;
+
if (field->physical) {
tab(n);
printk("Physical(");
@@ -466,6 +472,9 @@ void hid_dump_device(struct hid_device *device) {
unsigned i,k;
static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
+ if (!hid_debug)
+ return;
+
for (i = 0; i < HID_REPORT_TYPES; i++) {
report_enum = device->report_enum + i;
list = report_enum->report_list.next;
@@ -489,6 +498,9 @@ void hid_dump_device(struct hid_device *device) {
EXPORT_SYMBOL_GPL(hid_dump_device);
void hid_dump_input(struct hid_usage *usage, __s32 value) {
+ if (!hid_debug)
+ return;
+
printk("hid-debug: input ");
hid_resolv_usage(usage->hid);
printk(" = %d\n", value);
@@ -758,6 +770,9 @@ static char **names[EV_MAX + 1] = {
void hid_resolv_event(__u8 type, __u16 code) {
+ if (!hid_debug)
+ return;
+
printk("%s.%s", events[type] ? events[type] : "?",
names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
}
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7f817897b17..8edbd30cf79 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -60,6 +60,19 @@ static const unsigned char hid_keyboard[256] = {
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};
+/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
+#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
+static int logitech_expanded_keymap[LOGITECH_EXPANDED_KEYMAP_SIZE] = {
+ 0,216, 0,213,175,156, 0, 0, 0, 0,
+ 144, 0, 0, 0, 0, 0, 0, 0, 0,212,
+ 174,167,152,161,112, 0, 0, 0,154, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,183,184,185,186,187,
+ 188,189,190,191,192,193,194, 0, 0, 0
+};
+
static const struct {
__s32 x;
__s32 y;
@@ -308,9 +321,7 @@ static int hidinput_setkeycode(struct input_dev *dev, int scancode,
clear_bit(old_keycode, dev->keybit);
set_bit(usage->code, dev->keybit);
-#ifdef CONFIG_HID_DEBUG
- printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
-#endif
+ dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
/* Set the keybit for the old keycode if the old keycode is used
* by another key */
if (hidinput_find_key (hid, 0, old_keycode))
@@ -333,11 +344,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
field->hidinput = hidinput;
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG "Mapping: ");
+ dbg_hid("Mapping: ");
hid_resolv_usage(usage->hid);
- printk(" ---> ");
-#endif
+ dbg_hid_line(" ---> ");
if (field->flags & HID_MAIN_ITEM_CONSTANT)
goto ignore;
@@ -378,6 +387,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
}
+ /* Special handling for Logitech Cordless Desktop */
+ if (field->application != HID_GD_MOUSE) {
+ if (device->quirks & HID_QUIRK_LOGITECH_EXPANDED_KEYMAP) {
+ int hid = usage->hid & HID_USAGE;
+ if (hid < LOGITECH_EXPANDED_KEYMAP_SIZE && logitech_expanded_keymap[hid] != 0)
+ code = logitech_expanded_keymap[hid];
+ }
+ } else {
+ if (device->quirks & HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL) {
+ int hid = usage->hid & HID_USAGE;
+ if (hid == 7 || hid == 8)
+ goto ignore;
+ }
+ }
+
map_key(code);
break;
@@ -566,6 +590,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
case 0x0e9: map_key_clear(KEY_VOLUMEUP); break;
case 0x0ea: map_key_clear(KEY_VOLUMEDOWN); break;
+
+ /* reserved in HUT 1.12. Reported on Petalynx remote */
+ case 0x0f6: map_key_clear(KEY_NEXT); break;
+ case 0x0fa: map_key_clear(KEY_BACK); break;
+
case 0x183: map_key_clear(KEY_CONFIG); break;
case 0x184: map_key_clear(KEY_WORDPROCESSOR); break;
case 0x185: map_key_clear(KEY_EDITOR); break;
@@ -598,7 +627,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x21b: map_key_clear(KEY_COPY); break;
case 0x21c: map_key_clear(KEY_CUT); break;
case 0x21d: map_key_clear(KEY_PASTE); break;
- case 0x221: map_key_clear(KEY_FIND); break;
+ case 0x21f: map_key_clear(KEY_FIND); break;
+ case 0x221: map_key_clear(KEY_SEARCH); break;
+ case 0x222: map_key_clear(KEY_GOTO); break;
case 0x223: map_key_clear(KEY_HOMEPAGE); break;
case 0x224: map_key_clear(KEY_BACK); break;
case 0x225: map_key_clear(KEY_FORWARD); break;
@@ -688,7 +719,28 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break;
case HID_UP_MSVENDOR:
- goto ignore;
+
+ /* special case - Chicony Chicony KU-0418 tactical pad */
+ if (device->vendor == 0x04f2 && device->product == 0x0418) {
+ set_bit(EV_REP, input->evbit);
+ switch(usage->hid & HID_USAGE) {
+ case 0xff01: map_key_clear(BTN_1); break;
+ case 0xff02: map_key_clear(BTN_2); break;
+ case 0xff03: map_key_clear(BTN_3); break;
+ case 0xff04: map_key_clear(BTN_4); break;
+ case 0xff05: map_key_clear(BTN_5); break;
+ case 0xff06: map_key_clear(BTN_6); break;
+ case 0xff07: map_key_clear(BTN_7); break;
+ case 0xff08: map_key_clear(BTN_8); break;
+ case 0xff09: map_key_clear(BTN_9); break;
+ case 0xff0a: map_key_clear(BTN_A); break;
+ case 0xff0b: map_key_clear(BTN_B); break;
+ default: goto ignore;
+ }
+ } else {
+ goto ignore;
+ }
+ break;
case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
@@ -704,10 +756,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
break;
- case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media Remote */
-
+ case HID_UP_LOGIVENDOR:
set_bit(EV_REP, input->evbit);
switch(usage->hid & HID_USAGE) {
+ /* Reported on Logitech Ultra X Media Remote */
case 0x004: map_key_clear(KEY_AGAIN); break;
case 0x00d: map_key_clear(KEY_HOME); break;
case 0x024: map_key_clear(KEY_SHUFFLE); break;
@@ -725,6 +777,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x04d: map_key_clear(KEY_SUBTITLE); break;
case 0x051: map_key_clear(KEY_RED); break;
case 0x052: map_key_clear(KEY_CLOSE); break;
+
+ /* Reported on Petalynx Maxter remote */
+ case 0x05a: map_key_clear(KEY_TEXT); break;
+ case 0x05b: map_key_clear(KEY_RED); break;
+ case 0x05c: map_key_clear(KEY_GREEN); break;
+ case 0x05d: map_key_clear(KEY_YELLOW); break;
+ case 0x05e: map_key_clear(KEY_BLUE); break;
+
default: goto ignore;
}
break;
@@ -818,16 +878,24 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
field->dpad = usage->code;
}
+ /* for those devices which produce Consumer volume usage as relative,
+ * we emulate pressing volumeup/volumedown appropriate number of times
+ * in hidinput_hid_event()
+ */
+ if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+ (usage->code == ABS_VOLUME)) {
+ set_bit(KEY_VOLUMEUP, input->keybit);
+ set_bit(KEY_VOLUMEDOWN, input->keybit);
+ }
+
hid_resolv_event(usage->type, usage->code);
-#ifdef CONFIG_HID_DEBUG
- printk("\n");
-#endif
+
+ dbg_hid_line("\n");
+
return;
ignore:
-#ifdef CONFIG_HID_DEBUG
- printk("IGNORED\n");
-#endif
+ dbg_hid_line("IGNORED\n");
return;
}
@@ -896,18 +964,33 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
}
if (usage->hid == (HID_UP_PID | 0x83UL)) { /* Simultaneous Effects Max */
- dbg("Maximum Effects - %d",value);
+ dbg_hid("Maximum Effects - %d\n",value);
return;
}
if (usage->hid == (HID_UP_PID | 0x7fUL)) {
- dbg("PID Pool Report\n");
+ dbg_hid("PID Pool Report\n");
return;
}
if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
return;
+ if ((usage->type == EV_ABS) && (field->flags & HID_MAIN_ITEM_RELATIVE) &&
+ (usage->code == ABS_VOLUME)) {
+ int count = abs(value);
+ int direction = value > 0 ? KEY_VOLUMEUP : KEY_VOLUMEDOWN;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ input_event(input, EV_KEY, direction, 1);
+ input_sync(input);
+ input_event(input, EV_KEY, direction, 0);
+ input_sync(input);
+ }
+ return;
+ }
+
input_event(input, usage->type, usage->code, value);
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
@@ -976,7 +1059,7 @@ int hidinput_connect(struct hid_device *hid)
if (IS_INPUT_APPLICATION(hid->collection[i].usage))
break;
- if (i == hid->maxcollection)
+ if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDINPUT) == 0)
return -1;
if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
@@ -994,7 +1077,7 @@ int hidinput_connect(struct hid_device *hid)
if (!hidinput || !input_dev) {
kfree(hidinput);
input_free_device(input_dev);
- err("Out of memory during hid input probe");
+ err_hid("Out of memory during hid input probe");
return -1;
}
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index d91b9dac6df..b2baeaeba9b 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -60,6 +60,12 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
" quirks=vendorID:productID:quirks"
" where vendorID, productID, and quirks are all in"
" 0x-prefixed hex");
+static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
+module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
+MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
+ " rdesc_quirks=vendorID:productID:rdesc_quirks"
+ " where vendorID, productID, and rdesc_quirks are all in"
+ " 0x-prefixed hex");
/*
* Input submission and I/O error handler.
*/
@@ -127,7 +133,7 @@ static void hid_reset(struct work_struct *work)
hid_io_error(hid);
break;
default:
- err("can't reset device, %s-%s/input%d, status %d",
+ err_hid("can't reset device, %s-%s/input%d, status %d",
hid_to_usb_dev(hid)->bus->bus_name,
hid_to_usb_dev(hid)->devpath,
usbhid->ifnum, rc);
@@ -220,7 +226,7 @@ static void hid_irq_in(struct urb *urb)
if (status) {
clear_bit(HID_IN_RUNNING, &usbhid->iofl);
if (status != -EPERM) {
- err("can't resubmit intr, %s-%s/input%d, status %d",
+ err_hid("can't resubmit intr, %s-%s/input%d, status %d",
hid_to_usb_dev(hid)->bus->bus_name,
hid_to_usb_dev(hid)->devpath,
usbhid->ifnum, status);
@@ -240,10 +246,10 @@ static int hid_submit_out(struct hid_device *hid)
usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
usbhid->urbout->dev = hid_to_usb_dev(hid);
- dbg("submitting out urb");
+ dbg_hid("submitting out urb\n");
if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
- err("usb_submit_urb(out) failed");
+ err_hid("usb_submit_urb(out) failed");
return -1;
}
@@ -287,12 +293,12 @@ static int hid_submit_ctrl(struct hid_device *hid)
usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
usbhid->cr->wLength = cpu_to_le16(len);
- dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
+ dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n",
usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
- err("usb_submit_urb(ctrl) failed");
+ err_hid("usb_submit_urb(ctrl) failed");
return -1;
}
@@ -474,7 +480,7 @@ int usbhid_wait_io(struct hid_device *hid)
if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
10*HZ)) {
- dbg("timeout waiting for ctrl or out queue to clear");
+ dbg_hid("timeout waiting for ctrl or out queue to clear\n");
return -1;
}
@@ -633,20 +639,6 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
}
/*
- * Cherry Cymotion keyboard have an invalid HID report descriptor,
- * that needs fixing before we can parse it.
- */
-
-static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize)
-{
- if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
- info("Fixing up Cherry Cymotion report descriptor");
- rdesc[11] = rdesc[16] = 0xff;
- rdesc[12] = rdesc[17] = 0x03;
- }
-}
-
-/*
* Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
* to "operational". Without this, the ps3 controller will not report any
* events.
@@ -667,51 +659,11 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
USB_CTRL_GET_TIMEOUT);
if (result < 0)
- err("%s failed: %d\n", __func__, result);
+ err_hid("%s failed: %d\n", __func__, result);
kfree(buf);
}
-/*
- * Certain Logitech keyboards send in report #3 keys which are far
- * above the logical maximum described in descriptor. This extends
- * the original value of 0x28c of logical maximum to 0x104d
- */
-static void hid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
-{
- if (rsize >= 90 && rdesc[83] == 0x26
- && rdesc[84] == 0x8c
- && rdesc[85] == 0x02) {
- info("Fixing up Logitech keyboard report descriptor");
- rdesc[84] = rdesc[89] = 0x4d;
- rdesc[85] = rdesc[90] = 0x10;
- }
-}
-
-/*
- * Some USB barcode readers from cypress have usage min and usage max in
- * the wrong order
- */
-static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
-{
- short fixed = 0;
- int i;
-
- for (i = 0; i < rsize - 4; i++) {
- if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
- unsigned char tmp;
-
- rdesc[i] = 0x19; rdesc[i+2] = 0x29;
- tmp = rdesc[i+3];
- rdesc[i+3] = rdesc[i+1];
- rdesc[i+1] = tmp;
- }
- }
-
- if (fixed)
- info("Fixing up Cypress report descriptor");
-}
-
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
struct usb_host_interface *interface = intf->cur_altsetting;
@@ -746,7 +698,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
(!interface->desc.bNumEndpoints ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
- dbg("class descriptor not present\n");
+ dbg_hid("class descriptor not present\n");
return NULL;
}
@@ -755,41 +707,34 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
- dbg("weird size of report descriptor (%u)", rsize);
+ dbg_hid("weird size of report descriptor (%u)\n", rsize);
return NULL;
}
if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
- dbg("couldn't allocate rdesc memory");
+ dbg_hid("couldn't allocate rdesc memory\n");
return NULL;
}
hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);
if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
- dbg("reading report descriptor failed");
+ dbg_hid("reading report descriptor failed\n");
kfree(rdesc);
return NULL;
}
- if ((quirks & HID_QUIRK_CYMOTION))
- hid_fixup_cymotion_descriptor(rdesc, rsize);
-
- if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
- hid_fixup_logitech_descriptor(rdesc, rsize);
+ usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct), rdesc,
+ rsize, rdesc_quirks_param);
- if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
- hid_fixup_cypress_descriptor(rdesc, rsize);
-
-#ifdef CONFIG_HID_DEBUG
- printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
+ dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
- printk(" %02x", (unsigned char) rdesc[n]);
- printk("\n");
-#endif
+ dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
+ dbg_hid_line("\n");
if (!(hid = hid_parse_report(rdesc, n))) {
- dbg("parsing report descriptor failed");
+ dbg_hid("parsing report descriptor failed\n");
kfree(rdesc);
return NULL;
}
@@ -861,7 +806,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
}
if (!usbhid->urbin) {
- err("couldn't find an input interrupt endpoint");
+ err_hid("couldn't find an input interrupt endpoint");
goto fail;
}
@@ -956,7 +901,7 @@ static void hid_disconnect(struct usb_interface *intf)
usb_kill_urb(usbhid->urbctrl);
del_timer_sync(&usbhid->io_retry);
- flush_scheduled_work();
+ cancel_work_sync(&usbhid->reset_work);
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(hid);
@@ -978,7 +923,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
int i;
char *c;
- dbg("HID probe called for ifnum %d",
+ dbg_hid("HID probe called for ifnum %d\n",
intf->altsetting->desc.bInterfaceNumber);
if (!(hid = usb_hid_configure(intf)))
@@ -1064,20 +1009,22 @@ static int hid_resume(struct usb_interface *intf)
}
/* Treat USB reset pretty much the same as suspend/resume */
-static void hid_pre_reset(struct usb_interface *intf)
+static int hid_pre_reset(struct usb_interface *intf)
{
/* FIXME: What if the interface is already suspended? */
hid_suspend(intf, PMSG_ON);
+ return 0;
}
-static void hid_post_reset(struct usb_interface *intf)
+/* Same routine used for post_reset and reset_resume */
+static int hid_post_reset(struct usb_interface *intf)
{
struct usb_device *dev = interface_to_usbdev (intf);
hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
/* FIXME: Any more reinitialization needed? */
- hid_resume(intf);
+ return hid_resume(intf);
}
static struct usb_device_id hid_usb_ids [] = {
@@ -1094,6 +1041,7 @@ static struct usb_driver hid_driver = {
.disconnect = hid_disconnect,
.suspend = hid_suspend,
.resume = hid_resume,
+ .reset_resume = hid_post_reset,
.pre_reset = hid_pre_reset,
.post_reset = hid_post_reset,
.id_table = hid_usb_ids,
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c
index c5cd4107d6a..4b7ab6a46d9 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/usbhid/hid-lgff.c
@@ -78,7 +78,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[1] = 0x08;
report->field[0]->value[2] = x;
report->field[0]->value[3] = y;
- dbg("(x, y)=(%04x, %04x)", x, y);
+ dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
@@ -93,7 +93,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
report->field[0]->value[1] = 0x00;
report->field[0]->value[2] = left;
report->field[0]->value[3] = right;
- dbg("(left, right)=(%04x, %04x)", left, right);
+ dbg_hid("(left, right)=(%04x, %04x)\n", left, right);
usbhid_submit_report(hid, report, USB_DIR_OUT);
break;
}
@@ -113,20 +113,20 @@ int hid_lgff_init(struct hid_device* hid)
/* Find the report to use */
if (list_empty(report_list)) {
- err("No output report found");
+ err_hid("No output report found");
return -1;
}
/* Check that the report looks ok */
report = list_entry(report_list->next, struct hid_report, list);
if (!report) {
- err("NULL output report");
+ err_hid("NULL output report");
return -1;
}
field = report->field[0];
if (!field) {
- err("NULL field");
+ err_hid("NULL field");
return -1;
}
diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index f5a90e950e6..011326178c0 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -738,6 +738,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = 0;
pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = 0;
pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
+ pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
pidff->set_effect[PID_START_DELAY].value[0] = 0;
usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index f6c4145dc20..775b9f3b8ce 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -105,6 +105,9 @@
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+#define USB_VENDOR_ID_GAMERON 0x0810
+#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
+
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
@@ -196,8 +199,10 @@
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
+#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
+#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
@@ -209,6 +214,13 @@
#define USB_DEVICE_ID_MGE_UPS 0xffff
#define USB_DEVICE_ID_MGE_UPS1 0x0001
+#define USB_VENDOR_ID_MICROSOFT 0x045e
+#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
+
+#define USB_VENDOR_ID_NCR 0x0404
+#define USB_DEVICE_ID_NCR_FIRST 0x0300
+#define USB_DEVICE_ID_NCR_LAST 0x03ff
+
#define USB_VENDOR_ID_NEC 0x073e
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
@@ -220,6 +232,9 @@
#define USB_VENDOR_ID_PANTHERLORD 0x0810
#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
+#define USB_VENDOR_ID_PETALYNX 0x18b1
+#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
+
#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
@@ -278,6 +293,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
+ { USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
@@ -285,11 +301,10 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
- { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
-
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE, HID_QUIRK_DUPLICATE_USAGES },
{ USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM, HID_QUIRK_HIDDEV },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
@@ -409,9 +424,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_LOGITECH_DESCRIPTOR },
- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_LOGITECH_DESCRIPTOR },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
@@ -426,6 +439,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -448,9 +462,28 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
- { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
+ { 0, 0 }
+};
+
+/* Quirks for devices which require report descriptor fixup go here */
+static const struct hid_rdesc_blacklist {
+ __u16 idVendor;
+ __u16 idProduct;
+ __u32 quirks;
+} hid_rdesc_blacklist[] = {
+
+ { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_RDESC_CYMOTION },
+
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
+
+ { USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
+
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+ { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
{ 0, 0 }
};
@@ -493,7 +526,7 @@ static struct hid_blacklist *usbhid_exists_dquirk(const u16 idVendor,
}
if (bl_entry != NULL)
- dbg("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+ dbg_hid("Found dynamic quirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
bl_entry->quirks, bl_entry->idVendor,
bl_entry->idProduct);
@@ -521,13 +554,13 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
int list_edited = 0;
if (!idVendor) {
- dbg("Cannot add a quirk with idVendor = 0");
+ dbg_hid("Cannot add a quirk with idVendor = 0\n");
return -EINVAL;
}
q_new = kmalloc(sizeof(struct quirks_list_struct), GFP_KERNEL);
if (!q_new) {
- dbg("Could not allocate quirks_list_struct");
+ dbg_hid("Could not allocate quirks_list_struct\n");
return -ENOMEM;
}
@@ -559,7 +592,6 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
return 0;
}
-
/**
* usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
*
@@ -643,7 +675,7 @@ static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor,
bl_entry = &hid_blacklist[n];
if (bl_entry != NULL)
- dbg("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
+ dbg_hid("Found squirk 0x%x for USB HID vendor 0x%hx prod 0x%hx\n",
bl_entry->quirks, bl_entry->idVendor,
bl_entry->idProduct);
return bl_entry;
@@ -675,6 +707,12 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
idProduct <= USB_DEVICE_ID_CODEMERCS_IOW_LAST)
return HID_QUIRK_IGNORE;
+ /* NCR devices must not be queried for reports */
+ if (idVendor == USB_VENDOR_ID_NCR &&
+ idProduct >= USB_DEVICE_ID_NCR_FIRST &&
+ idProduct <= USB_DEVICE_ID_NCR_LAST)
+ return HID_QUIRK_NOGET;
+
down_read(&dquirks_rwsem);
bl_entry = usbhid_exists_dquirk(idVendor, idProduct);
if (!bl_entry)
@@ -686,3 +724,126 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
return quirks;
}
+/*
+ * Cherry Cymotion keyboard have an invalid HID report descriptor,
+ * that needs fixing before we can parse it.
+ */
+static void usbhid_fixup_cymotion_descriptor(char *rdesc, int rsize)
+{
+ if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
+ printk(KERN_INFO "Fixing up Cherry Cymotion report descriptor\n");
+ rdesc[11] = rdesc[16] = 0xff;
+ rdesc[12] = rdesc[17] = 0x03;
+ }
+}
+
+
+/*
+ * Certain Logitech keyboards send in report #3 keys which are far
+ * above the logical maximum described in descriptor. This extends
+ * the original value of 0x28c of logical maximum to 0x104d
+ */
+static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
+{
+ if (rsize >= 90 && rdesc[83] == 0x26
+ && rdesc[84] == 0x8c
+ && rdesc[85] == 0x02) {
+ printk(KERN_INFO "Fixing up Logitech keyboard report descriptor\n");
+ rdesc[84] = rdesc[89] = 0x4d;
+ rdesc[85] = rdesc[90] = 0x10;
+ }
+}
+
+/* Petalynx Maxter Remote has maximum for consumer page set too low */
+static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
+{
+ if (rsize >= 60 && rdesc[39] == 0x2a
+ && rdesc[40] == 0xf5
+ && rdesc[41] == 0x00
+ && rdesc[59] == 0x26
+ && rdesc[60] == 0xf9
+ && rdesc[61] == 0x00) {
+ printk(KERN_INFO "Fixing up Petalynx Maxter Remote report descriptor\n");
+ rdesc[60] = 0xfa;
+ rdesc[40] = 0xfa;
+ }
+}
+
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void usbhid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
+{
+ short fixed = 0;
+ int i;
+
+ for (i = 0; i < rsize - 4; i++) {
+ if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
+ unsigned char tmp;
+
+ rdesc[i] = 0x19; rdesc[i+2] = 0x29;
+ tmp = rdesc[i+3];
+ rdesc[i+3] = rdesc[i+1];
+ rdesc[i+1] = tmp;
+ }
+ }
+
+ if (fixed)
+ printk(KERN_INFO "Fixing up Cypress report descriptor\n");
+}
+
+
+static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+{
+ if ((quirks & HID_QUIRK_RDESC_CYMOTION))
+ usbhid_fixup_cymotion_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_LOGITECH)
+ usbhid_fixup_logitech_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_SWAPPED_MIN_MAX)
+ usbhid_fixup_cypress_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_PETALYNX)
+ usbhid_fixup_petalynx_descriptor(rdesc, rsize);
+}
+
+/**
+ * usbhid_fixup_report_descriptor: check if report descriptor needs fixup
+ *
+ * Description:
+ * Walks the hid_rdesc_blacklist[] array and checks whether the device
+ * is known to have broken report descriptor that needs to be fixed up
+ * prior to entering the HID parser
+ *
+ * Returns: nothing
+ */
+void usbhid_fixup_report_descriptor(const u16 idVendor, const u16 idProduct,
+ char *rdesc, unsigned rsize, char **quirks_param)
+{
+ int n, m;
+ u16 paramVendor, paramProduct;
+ u32 quirks;
+
+ /* static rdesc quirk entries */
+ for (n = 0; hid_rdesc_blacklist[n].idVendor; n++)
+ if (hid_rdesc_blacklist[n].idVendor == idVendor &&
+ hid_rdesc_blacklist[n].idProduct == idProduct)
+ __usbhid_fixup_report_descriptor(hid_rdesc_blacklist[n].quirks,
+ rdesc, rsize);
+
+ /* runtime rdesc quirk entries handling */
+ for (n = 0; quirks_param[n] && n < MAX_USBHID_BOOT_QUIRKS; n++) {
+ m = sscanf(quirks_param[n], "0x%hx:0x%hx:0x%x",
+ &paramVendor, &paramProduct, &quirks);
+
+ if (m != 3)
+ printk(KERN_WARNING
+ "Could not parse HID quirk module param %s\n",
+ quirks_param[n]);
+ else if (paramVendor == idVendor && paramProduct == idProduct)
+ __usbhid_fixup_report_descriptor(quirks, rdesc, rsize);
+ }
+
+}
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
index ab5ba6ef891..555bb48b429 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/usbhid/hid-tmff.c
@@ -70,7 +70,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
tmff->rumble->value[0] = left;
tmff->rumble->value[1] = right;
- dbg("(left,right)=(%08x, %08x)", left, right);
+ dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
return 0;
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c
index a7fbffcdaf3..5a688274f6a 100644
--- a/drivers/hid/usbhid/hid-zpff.c
+++ b/drivers/hid/usbhid/hid-zpff.c
@@ -21,10 +21,6 @@
*/
-/* #define DEBUG */
-
-#define debug(format, arg...) pr_debug("hid-zpff: " format "\n" , ## arg)
-
#include <linux/input.h>
#include <linux/usb.h>
#include <linux/hid.h>
@@ -49,14 +45,14 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
left = effect->u.rumble.strong_magnitude;
right = effect->u.rumble.weak_magnitude;
- debug("called with 0x%04x 0x%04x", left, right);
+ dbg_hid("called with 0x%04x 0x%04x\n", left, right);
left = left * 0x7f / 0xffff;
right = right * 0x7f / 0xffff;
zpff->report->field[2]->value[0] = left;
zpff->report->field[3]->value[0] = right;
- debug("running with 0x%02x 0x%02x", left, right);
+ dbg_hid("running with 0x%02x 0x%02x\n", left, right);
usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
return 0;
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 488d61bdbf2..e793127f971 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -779,7 +779,7 @@ int hiddev_connect(struct hid_device *hid)
retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) {
- err("Not able to get a minor for this device.");
+ err_hid("Not able to get a minor for this device.");
kfree(hiddev);
return -1;
}
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 13097878071..b76b02f7b52 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -125,7 +125,7 @@ static void usb_kbd_irq(struct urb *urb)
resubmit:
i = usb_submit_urb (urb, GFP_ATOMIC);
if (i)
- err ("can't resubmit intr, %s-%s/input0, status %d",
+ err_hid ("can't resubmit intr, %s-%s/input0, status %d",
kbd->usbdev->bus->bus_name,
kbd->usbdev->devpath, i);
}
@@ -151,7 +151,7 @@ static int usb_kbd_event(struct input_dev *dev, unsigned int type,
*(kbd->leds) = kbd->newleds;
kbd->led->dev = kbd->usbdev;
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
- err("usb_submit_urb(leds) failed");
+ err_hid("usb_submit_urb(leds) failed");
return 0;
}
@@ -169,7 +169,7 @@ static void usb_kbd_led(struct urb *urb)
*(kbd->leds) = kbd->newleds;
kbd->led->dev = kbd->usbdev;
if (usb_submit_urb(kbd->led, GFP_ATOMIC))
- err("usb_submit_urb(leds) failed");
+ err_hid("usb_submit_urb(leds) failed");
}
static int usb_kbd_open(struct input_dev *dev)
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 0328382df8f..6d54c8caed7 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -185,6 +185,7 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
/* check for microcode update */
rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx);
if (edx < 0x39) {
+ err = -ENODEV;
dev_err(&pdev->dev,
"Errata AE18 not fixed, update BIOS or "
"microcode of the CPU!\n");
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index 58899078810..014dfa575be 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -34,10 +34,6 @@ config I2C_ALGOPCA
This support is also available as a module. If so, the module
will be called i2c-algo-pca.
-config I2C_ALGO8XX
- tristate "MPC8xx CPM I2C interface"
- depends on 8xx
-
config I2C_ALGO_SGI
tristate "I2C SGI interfaces"
depends on SGI_IP22 || SGI_IP32 || X86_VISWS
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 838dc1c19d6..1c77e14480d 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -207,6 +207,7 @@ config I2C_PIIX4
ATI IXP300
ATI IXP400
ATI SB600
+ ATI SB700
Serverworks OSB4
Serverworks CSB5
Serverworks CSB6
@@ -390,11 +391,6 @@ config I2C_PROSAVAGE
This support is also available as a module. If so, the module
will be called i2c-prosavage.
-config I2C_RPXLITE
- tristate "Embedded Planet RPX Lite/Classic support"
- depends on RPXLITE || RPXCLASSIC
- select I2C_ALGO8XX
-
config I2C_S3C2410
tristate "S3C2410 I2C Driver"
depends on ARCH_S3C2410
@@ -512,6 +508,22 @@ config I2C_SIS96X
This driver can also be built as a module. If so, the module
will be called i2c-sis96x.
+config I2C_TAOS_EVM
+ tristate "TAOS evaluation module"
+ depends on EXPERIMENTAL
+ select SERIO
+ select SERIO_SERPORT
+ default n
+ help
+ This supports TAOS evaluation modules on serial port. In order to
+ use this driver, you will need the inputattach tool, which is part
+ of the input-utils package.
+
+ If unsure, say N.
+
+ This support is also available as a module. If so, the module
+ will be called i2c-taos-evm.
+
config I2C_STUB
tristate "I2C/SMBus Test Stub"
depends on EXPERIMENTAL && m
@@ -548,7 +560,7 @@ config I2C_VERSATILE
will be called i2c-versatile.
config I2C_ACORN
- bool "Acorn IOC/IOMD I2C bus support"
+ tristate "Acorn IOC/IOMD I2C bus support"
depends on ARCH_ACORN
default y
select I2C_ALGOBIT
@@ -635,4 +647,13 @@ config I2C_PNX
This driver can also be built as a module. If so, the module
will be called i2c-pnx.
+config I2C_PMCMSP
+ tristate "PMC MSP I2C TWI Controller"
+ depends on PMC_MSP
+ help
+ This driver supports the PMC TWI controller on MSP devices.
+
+ This driver can also be built as module. If so, the module
+ will be called i2c-pmcmsp.
+
endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 14d1432f698..a6db4e38bda 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -32,10 +32,10 @@ obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
+obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
-obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
@@ -44,6 +44,7 @@ obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
+obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o
obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 09bd7f40b90..7c2be3558a2 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -94,4 +94,4 @@ static int __init i2c_ioc_init(void)
return i2c_bit_add_bus(&ioc_ops);
}
-__initcall(i2c_ioc_init);
+module_init(i2c_ioc_init);
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index a7dd54654a9..025f19423fa 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -63,14 +63,14 @@ static void i2c_gpio_setscl_val(void *data, int state)
gpio_set_value(pdata->scl_pin, state);
}
-int i2c_gpio_getsda(void *data)
+static int i2c_gpio_getsda(void *data)
{
struct i2c_gpio_platform_data *pdata = data;
return gpio_get_value(pdata->sda_pin);
}
-int i2c_gpio_getscl(void *data)
+static int i2c_gpio_getscl(void *data)
{
struct i2c_gpio_platform_data *pdata = data;
@@ -142,7 +142,13 @@ static int __init i2c_gpio_probe(struct platform_device *pdev)
adap->algo_data = bit_data;
adap->dev.parent = &pdev->dev;
- ret = i2c_bit_add_bus(adap);
+ /*
+ * If "dev->id" is negative we consider it as zero.
+ * The reason to do so is to avoid sysfs names that only make
+ * sense when there are multiple adapters.
+ */
+ adap->nr = pdev->id >= 0 ? pdev->id : 0;
+ ret = i2c_bit_add_numbered_bus(adap);
if (ret)
goto err_add_bus;
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 611b57192c9..8f5c686123b 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -22,12 +22,12 @@
/*
SUPPORTED DEVICES PCI ID
- 82801AA 2413
- 82801AB 2423
- 82801BA 2443
- 82801CA/CAM 2483
- 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported)
- 82801EB 24D3 (HW PEC supported, 32 byte buffer not supported)
+ 82801AA 2413
+ 82801AB 2423
+ 82801BA 2443
+ 82801CA/CAM 2483
+ 82801DB 24C3 (HW PEC supported)
+ 82801EB 24D3 (HW PEC supported)
6300ESB 25A4
ICH6 266A
ICH7 27DA
@@ -74,6 +74,13 @@
#define SMBHSTCFG_SMB_SMI_EN 2
#define SMBHSTCFG_I2C_EN 4
+/* Auxillary control register bits, ICH4+ only */
+#define SMBAUXCTL_CRC 1
+#define SMBAUXCTL_E32B 2
+
+/* kill bit for SMBHSTCNT */
+#define SMBHSTCNT_KILL 2
+
/* Other settings */
#define MAX_TIMEOUT 100
#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */
@@ -91,10 +98,15 @@
#define I801_START 0x40
#define I801_PEC_EN 0x80 /* ICH4 only */
-
-static int i801_transaction(void);
-static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
- int command, int hwpec);
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE 0x80
+#define SMBHSTSTS_INUSE_STS 0x40
+#define SMBHSTSTS_SMBALERT_STS 0x20
+#define SMBHSTSTS_FAILED 0x10
+#define SMBHSTSTS_BUS_ERR 0x08
+#define SMBHSTSTS_DEV_ERR 0x04
+#define SMBHSTSTS_INTR 0x02
+#define SMBHSTSTS_HOST_BUSY 0x01
static unsigned long i801_smba;
static unsigned char i801_original_hstcfg;
@@ -102,7 +114,7 @@ static struct pci_driver i801_driver;
static struct pci_dev *I801_dev;
static int isich4;
-static int i801_transaction(void)
+static int i801_transaction(int xact)
{
int temp;
int result = 0;
@@ -127,33 +139,40 @@ static int i801_transaction(void)
}
}
- outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+ /* the current contents of SMBHSTCNT can be overwritten, since PEC,
+ * INTREN, SMBSCMD are passed in xact */
+ outb_p(xact | I801_START, SMBHSTCNT);
/* We will always wait for a fraction of a second! */
do {
msleep(1);
temp = inb_p(SMBHSTSTS);
- } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+ } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) {
dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
result = -1;
+ /* try to stop the current command */
+ dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
+ outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
+ msleep(1);
+ outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
}
- if (temp & 0x10) {
+ if (temp & SMBHSTSTS_FAILED) {
result = -1;
dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
}
- if (temp & 0x08) {
+ if (temp & SMBHSTSTS_BUS_ERR) {
result = -1;
dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
"until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */
}
- if (temp & 0x04) {
+ if (temp & SMBHSTSTS_DEV_ERR) {
result = -1;
dev_dbg(&I801_dev->dev, "Error: no response!\n");
}
@@ -172,44 +191,70 @@ static int i801_transaction(void)
return result;
}
-/* All-inclusive block transaction function */
-static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
- int command, int hwpec)
+/* wait for INTR bit as advised by Intel */
+static void i801_wait_hwpec(void)
+{
+ int timeout = 0;
+ int temp;
+
+ do {
+ msleep(1);
+ temp = inb_p(SMBHSTSTS);
+ } while ((!(temp & SMBHSTSTS_INTR))
+ && (timeout++ < MAX_TIMEOUT));
+
+ if (timeout >= MAX_TIMEOUT) {
+ dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
+ }
+ outb_p(temp, SMBHSTSTS);
+}
+
+static int i801_block_transaction_by_block(union i2c_smbus_data *data,
+ char read_write, int hwpec)
+{
+ int i, len;
+
+ inb_p(SMBHSTCNT); /* reset the data buffer index */
+
+ /* Use 32-byte buffer to process this transaction */
+ if (read_write == I2C_SMBUS_WRITE) {
+ len = data->block[0];
+ outb_p(len, SMBHSTDAT0);
+ for (i = 0; i < len; i++)
+ outb_p(data->block[i+1], SMBBLKDAT);
+ }
+
+ if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
+ I801_PEC_EN * hwpec))
+ return -1;
+
+ if (read_write == I2C_SMBUS_READ) {
+ len = inb_p(SMBHSTDAT0);
+ if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+ return -1;
+
+ data->block[0] = len;
+ for (i = 0; i < len; i++)
+ data->block[i + 1] = inb_p(SMBBLKDAT);
+ }
+ return 0;
+}
+
+static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
+ char read_write, int hwpec)
{
int i, len;
int smbcmd;
int temp;
int result = 0;
int timeout;
- unsigned char hostc, errmask;
+ unsigned char errmask;
- if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
- if (read_write == I2C_SMBUS_WRITE) {
- /* set I2C_EN bit in configuration register */
- pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
- pci_write_config_byte(I801_dev, SMBHSTCFG,
- hostc | SMBHSTCFG_I2C_EN);
- } else {
- dev_err(&I801_dev->dev,
- "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
- return -1;
- }
- }
+ len = data->block[0];
if (read_write == I2C_SMBUS_WRITE) {
- len = data->block[0];
- if (len < 1)
- len = 1;
- if (len > 32)
- len = 32;
outb_p(len, SMBHSTDAT0);
outb_p(data->block[1], SMBBLKDAT);
- } else {
- len = 32; /* max for reads */
- }
-
- if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
- /* set 32 byte buffer */
}
for (i = 1; i <= len; i++) {
@@ -227,13 +272,13 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
/* Make sure the SMBus host is ready to start transmitting */
temp = inb_p(SMBHSTSTS);
if (i == 1) {
- /* Erronenous conditions before transaction:
+ /* Erronenous conditions before transaction:
* Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
- errmask=0x9f;
+ errmask = 0x9f;
} else {
- /* Erronenous conditions during transaction:
+ /* Erronenous conditions during transaction:
* Failed, Bus_Err, Dev_Err, Intr */
- errmask=0x1e;
+ errmask = 0x1e;
}
if (temp & errmask) {
dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
@@ -242,14 +287,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
dev_err(&I801_dev->dev,
"Reset failed! (%02x)\n", temp);
- result = -1;
- goto END;
+ return -1;
}
- if (i != 1) {
+ if (i != 1)
/* if die in middle of block transaction, fail */
- result = -1;
- goto END;
- }
+ return -1;
}
if (i == 1)
@@ -261,33 +303,38 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
msleep(1);
temp = inb_p(SMBHSTSTS);
}
- while ((!(temp & 0x80))
- && (timeout++ < MAX_TIMEOUT));
+ while ((!(temp & SMBHSTSTS_BYTE_DONE))
+ && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
if (timeout >= MAX_TIMEOUT) {
+ /* try to stop the current command */
+ dev_dbg(&I801_dev->dev, "Terminating the current "
+ "operation\n");
+ outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
+ msleep(1);
+ outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
+ SMBHSTCNT);
result = -1;
dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
}
- if (temp & 0x10) {
+ if (temp & SMBHSTSTS_FAILED) {
result = -1;
dev_dbg(&I801_dev->dev,
"Error: Failed bus transaction\n");
- } else if (temp & 0x08) {
+ } else if (temp & SMBHSTSTS_BUS_ERR) {
result = -1;
dev_err(&I801_dev->dev, "Bus collision!\n");
- } else if (temp & 0x04) {
+ } else if (temp & SMBHSTSTS_DEV_ERR) {
result = -1;
dev_dbg(&I801_dev->dev, "Error: no response!\n");
}
if (i == 1 && read_write == I2C_SMBUS_READ) {
len = inb_p(SMBHSTDAT0);
- if (len < 1)
- len = 1;
- if (len > 32)
- len = 32;
+ if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+ return -1;
data->block[0] = len;
}
@@ -310,25 +357,58 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
if (result < 0)
- goto END;
+ return result;
}
+ return result;
+}
- if (hwpec) {
- /* wait for INTR bit as advised by Intel */
- timeout = 0;
- do {
- msleep(1);
- temp = inb_p(SMBHSTSTS);
- } while ((!(temp & 0x02))
- && (timeout++ < MAX_TIMEOUT));
+static int i801_set_block_buffer_mode(void)
+{
+ outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
+ if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
+ return -1;
+ return 0;
+}
- if (timeout >= MAX_TIMEOUT) {
- dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
+/* Block transaction function */
+static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
+ int command, int hwpec)
+{
+ int result = 0;
+ unsigned char hostc;
+
+ if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+ if (read_write == I2C_SMBUS_WRITE) {
+ /* set I2C_EN bit in configuration register */
+ pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
+ pci_write_config_byte(I801_dev, SMBHSTCFG,
+ hostc | SMBHSTCFG_I2C_EN);
+ } else {
+ dev_err(&I801_dev->dev,
+ "I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
+ return -1;
}
- outb_p(temp, SMBHSTSTS);
}
- result = 0;
-END:
+
+ if (read_write == I2C_SMBUS_WRITE) {
+ if (data->block[0] < 1)
+ data->block[0] = 1;
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ data->block[0] = I2C_SMBUS_BLOCK_MAX;
+ } else {
+ data->block[0] = 32; /* max for reads */
+ }
+
+ if (isich4 && i801_set_block_buffer_mode() == 0 )
+ result = i801_block_transaction_by_block(data, read_write,
+ hwpec);
+ else
+ result = i801_block_transaction_byte_by_byte(data, read_write,
+ hwpec);
+
+ if (result == 0 && hwpec)
+ i801_wait_hwpec();
+
if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
/* restore saved configuration register value */
pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
@@ -393,19 +473,22 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
return -1;
}
- outb_p(hwpec, SMBAUXCTL); /* enable/disable hardware PEC */
+ if (hwpec) /* enable/disable hardware PEC */
+ outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL);
+ else
+ outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL);
if(block)
ret = i801_block_transaction(data, read_write, size, hwpec);
- else {
- outb_p(xact | ENABLE_INT9, SMBHSTCNT);
- ret = i801_transaction();
- }
+ else
+ ret = i801_transaction(xact | ENABLE_INT9);
/* Some BIOSes don't like it when PEC is enabled at reboot or resume
- time, so we forcibly disable it after every transaction. */
+ time, so we forcibly disable it after every transaction. Turn off
+ E32B for the same reason. */
if (hwpec)
- outb_p(0, SMBAUXCTL);
+ outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
+ SMBAUXCTL);
if(block)
return ret;
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 90e2d9350c1..440342bc62e 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -491,6 +491,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
new_adapter->id = I2C_HW_IOP3XX;
new_adapter->owner = THIS_MODULE;
new_adapter->dev.parent = &pdev->dev;
+ new_adapter->nr = pdev->id;
/*
* Default values...should these come in from board code?
@@ -508,7 +509,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, new_adapter);
new_adapter->algo_data = adapter_data;
- i2c_add_adapter(new_adapter);
+ i2c_add_numbered_adapter(new_adapter);
return 0;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index c6b6898592b..851c3ed513d 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -74,6 +74,25 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
+/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
+ * the bus, because it wants to send ACK.
+ * Following sequence of enabling/disabling and sending start/stop generates
+ * the pulse, so it's all OK.
+ */
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+ writeccr(i2c, 0);
+ udelay(30);
+ writeccr(i2c, CCR_MEN);
+ udelay(30);
+ writeccr(i2c, CCR_MSTA | CCR_MTX);
+ udelay(30);
+ writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+ udelay(30);
+ writeccr(i2c, CCR_MEN);
+ udelay(30);
+}
+
static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
{
unsigned long orig_jiffies = jiffies;
@@ -153,6 +172,7 @@ static void mpc_i2c_start(struct mpc_i2c *i2c)
static void mpc_i2c_stop(struct mpc_i2c *i2c)
{
writeccr(i2c, CCR_MEN);
+ writeccr(i2c, 0);
}
static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +265,9 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
}
if (time_after(jiffies, orig_jiffies + HZ)) {
pr_debug("I2C: timeout\n");
+ if (readb(i2c->base + MPC_I2C_SR) ==
+ (CSR_MCF | CSR_MBB | CSR_RXAK))
+ mpc_i2c_fixup(i2c);
return -EIO;
}
schedule();
@@ -327,9 +350,10 @@ static int fsl_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, i2c);
i2c->adap = mpc_ops;
+ i2c->adap.nr = pdev->id;
i2c_set_adapdata(&i2c->adap, i2c);
i2c->adap.dev.parent = &pdev->dev;
- if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
+ if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) {
printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
goto fail_add;
}
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index a55b3335d1b..251154ae5d9 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -527,6 +527,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
drv_data->adapter.class = I2C_CLASS_HWMON;
drv_data->adapter.timeout = pdata->timeout;
drv_data->adapter.retries = pdata->retries;
+ drv_data->adapter.nr = pd->id;
platform_set_drvdata(pd, drv_data);
i2c_set_adapdata(&drv_data->adapter, drv_data);
@@ -539,7 +540,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
drv_data->irq);
rc = -EINVAL;
goto exit_unmap_regs;
- } else if ((rc = i2c_add_adapter(&drv_data->adapter)) != 0) {
+ } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) {
dev_err(&drv_data->adapter.dev,
"mv64xxx: Can't add i2c adapter, rc: %d\n", -rc);
goto exit_free_irq;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 3cd0d63e7b5..c48140f782d 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -61,6 +61,7 @@ struct nforce2_smbus {
struct i2c_adapter adapter;
int base;
int size;
+ int blockops;
};
@@ -80,6 +81,8 @@ struct nforce2_smbus {
#define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */
#define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */
#define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */
+#define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data
+ bytes */
#define NVIDIA_SMB_STS_DONE 0x80
#define NVIDIA_SMB_STS_ALRM 0x40
@@ -92,6 +95,7 @@ struct nforce2_smbus {
#define NVIDIA_SMB_PRTCL_BYTE 0x04
#define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06
#define NVIDIA_SMB_PRTCL_WORD_DATA 0x08
+#define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a
#define NVIDIA_SMB_PRTCL_PEC 0x80
static struct pci_driver nforce2_driver;
@@ -103,6 +107,8 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
{
struct nforce2_smbus *smbus = adap->algo_data;
unsigned char protocol, pec, temp;
+ u8 len;
+ int i;
protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
NVIDIA_SMB_PRTCL_WRITE;
@@ -137,6 +143,25 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;
break;
+ case I2C_SMBUS_BLOCK_DATA:
+ outb_p(command, NVIDIA_SMB_CMD);
+ if (read_write == I2C_SMBUS_WRITE) {
+ len = data->block[0];
+ if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
+ dev_err(&adap->dev,
+ "Transaction failed "
+ "(requested block size: %d)\n",
+ len);
+ return -1;
+ }
+ outb_p(len, NVIDIA_SMB_BCNT);
+ for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
+ outb_p(data->block[i + 1],
+ NVIDIA_SMB_DATA+i);
+ }
+ protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;
+ break;
+
default:
dev_err(&adap->dev, "Unsupported transaction %d\n", size);
return -1;
@@ -174,6 +199,14 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
case I2C_SMBUS_WORD_DATA:
data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8);
break;
+
+ case I2C_SMBUS_BLOCK_DATA:
+ len = inb_p(NVIDIA_SMB_BCNT);
+ len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
+ for (i = 0; i < len; i++)
+ data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
+ data->block[0] = len;
+ break;
}
return 0;
@@ -184,7 +217,9 @@ static u32 nforce2_func(struct i2c_adapter *adapter)
{
/* other functionality might be possible, but is not tested */
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ (((struct nforce2_smbus*)adapter->algo_data)->blockops ?
+ I2C_FUNC_SMBUS_BLOCK_DATA : 0);
}
static struct i2c_algorithm smbus_algorithm = {
@@ -268,6 +303,13 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
return -ENOMEM;
pci_set_drvdata(dev, smbuses);
+ switch(dev->device) {
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS:
+ case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS:
+ smbuses[0].blockops = 1;
+ smbuses[1].blockops = 1;
+ }
+
/* SMBus adapter 1 */
res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
if (res1 < 0) {
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 5a52bf5e3fb..debc76cd216 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -23,7 +23,7 @@
Supports:
Intel PIIX4, 440MX
Serverworks OSB4, CSB5, CSB6, HT-1000
- ATI IXP200, IXP300, IXP400, SB600
+ ATI IXP200, IXP300, IXP400, SB600, SB700
SMSC Victory66
Note: we assume there can only be one device, with one SMBus interface.
@@ -399,6 +399,8 @@ static struct pci_device_id piix4_ids[] = {
.driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SMBUS),
.driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SMBUS),
+ .driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
.driver_data = 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
new file mode 100644
index 00000000000..03188d277af
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -0,0 +1,653 @@
+/*
+ * Specific bus support for PMC-TWI compliant implementation on MSP71xx.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#define DRV_NAME "pmcmsptwi"
+
+#define MSP_TWI_SF_CLK_REG_OFFSET 0x00
+#define MSP_TWI_HS_CLK_REG_OFFSET 0x04
+#define MSP_TWI_CFG_REG_OFFSET 0x08
+#define MSP_TWI_CMD_REG_OFFSET 0x0c
+#define MSP_TWI_ADD_REG_OFFSET 0x10
+#define MSP_TWI_DAT_0_REG_OFFSET 0x14
+#define MSP_TWI_DAT_1_REG_OFFSET 0x18
+#define MSP_TWI_INT_STS_REG_OFFSET 0x1c
+#define MSP_TWI_INT_MSK_REG_OFFSET 0x20
+#define MSP_TWI_BUSY_REG_OFFSET 0x24
+
+#define MSP_TWI_INT_STS_DONE (1 << 0)
+#define MSP_TWI_INT_STS_LOST_ARBITRATION (1 << 1)
+#define MSP_TWI_INT_STS_NO_RESPONSE (1 << 2)
+#define MSP_TWI_INT_STS_DATA_COLLISION (1 << 3)
+#define MSP_TWI_INT_STS_BUSY (1 << 4)
+#define MSP_TWI_INT_STS_ALL 0x1f
+
+#define MSP_MAX_BYTES_PER_RW 8
+#define MSP_MAX_POLL 5
+#define MSP_POLL_DELAY 10
+#define MSP_IRQ_TIMEOUT (MSP_MAX_POLL * MSP_POLL_DELAY)
+
+/* IO Operation macros */
+#define pmcmsptwi_readl __raw_readl
+#define pmcmsptwi_writel __raw_writel
+
+/* TWI command type */
+enum pmcmsptwi_cmd_type {
+ MSP_TWI_CMD_WRITE = 0, /* Write only */
+ MSP_TWI_CMD_READ = 1, /* Read only */
+ MSP_TWI_CMD_WRITE_READ = 2, /* Write then Read */
+};
+
+/* The possible results of the xferCmd */
+enum pmcmsptwi_xfer_result {
+ MSP_TWI_XFER_OK = 0,
+ MSP_TWI_XFER_TIMEOUT,
+ MSP_TWI_XFER_BUSY,
+ MSP_TWI_XFER_DATA_COLLISION,
+ MSP_TWI_XFER_NO_RESPONSE,
+ MSP_TWI_XFER_LOST_ARBITRATION,
+};
+
+/* Corresponds to a PMCTWI clock configuration register */
+struct pmcmsptwi_clock {
+ u8 filter; /* Bits 15:12, default = 0x03 */
+ u16 clock; /* Bits 9:0, default = 0x001f */
+};
+
+struct pmcmsptwi_clockcfg {
+ struct pmcmsptwi_clock standard; /* The standard/fast clock config */
+ struct pmcmsptwi_clock highspeed; /* The highspeed clock config */
+};
+
+/* Corresponds to the main TWI configuration register */
+struct pmcmsptwi_cfg {
+ u8 arbf; /* Bits 15:12, default=0x03 */
+ u8 nak; /* Bits 11:8, default=0x03 */
+ u8 add10; /* Bit 7, default=0x00 */
+ u8 mst_code; /* Bits 6:4, default=0x00 */
+ u8 arb; /* Bit 1, default=0x01 */
+ u8 highspeed; /* Bit 0, default=0x00 */
+};
+
+/* A single pmctwi command to issue */
+struct pmcmsptwi_cmd {
+ u16 addr; /* The slave address (7 or 10 bits) */
+ enum pmcmsptwi_cmd_type type; /* The command type */
+ u8 write_len; /* Number of bytes in the write buffer */
+ u8 read_len; /* Number of bytes in the read buffer */
+ u8 *write_data; /* Buffer of characters to send */
+ u8 *read_data; /* Buffer to fill with incoming data */
+};
+
+/* The private data */
+struct pmcmsptwi_data {
+ void __iomem *iobase; /* iomapped base for IO */
+ int irq; /* IRQ to use (0 disables) */
+ struct completion wait; /* Completion for xfer */
+ struct mutex lock; /* Used for threadsafeness */
+ enum pmcmsptwi_xfer_result last_result; /* result of last xfer */
+};
+
+/* The default settings */
+const static struct pmcmsptwi_clockcfg pmcmsptwi_defclockcfg = {
+ .standard = {
+ .filter = 0x3,
+ .clock = 0x1f,
+ },
+ .highspeed = {
+ .filter = 0x3,
+ .clock = 0x1f,
+ },
+};
+
+const static struct pmcmsptwi_cfg pmcmsptwi_defcfg = {
+ .arbf = 0x03,
+ .nak = 0x03,
+ .add10 = 0x00,
+ .mst_code = 0x00,
+ .arb = 0x01,
+ .highspeed = 0x00,
+};
+
+static struct pmcmsptwi_data pmcmsptwi_data;
+
+static struct i2c_adapter pmcmsptwi_adapter;
+
+/* inline helper functions */
+static inline u32 pmcmsptwi_clock_to_reg(
+ const struct pmcmsptwi_clock *clock)
+{
+ return ((clock->filter & 0xf) << 12) | (clock->clock & 0x03ff);
+}
+
+static inline void pmcmsptwi_reg_to_clock(
+ u32 reg, struct pmcmsptwi_clock *clock)
+{
+ clock->filter = (reg >> 12) & 0xf;
+ clock->clock = reg & 0x03ff;
+}
+
+static inline u32 pmcmsptwi_cfg_to_reg(const struct pmcmsptwi_cfg *cfg)
+{
+ return ((cfg->arbf & 0xf) << 12) |
+ ((cfg->nak & 0xf) << 8) |
+ ((cfg->add10 & 0x1) << 7) |
+ ((cfg->mst_code & 0x7) << 4) |
+ ((cfg->arb & 0x1) << 1) |
+ (cfg->highspeed & 0x1);
+}
+
+static inline void pmcmsptwi_reg_to_cfg(u32 reg, struct pmcmsptwi_cfg *cfg)
+{
+ cfg->arbf = (reg >> 12) & 0xf;
+ cfg->nak = (reg >> 8) & 0xf;
+ cfg->add10 = (reg >> 7) & 0x1;
+ cfg->mst_code = (reg >> 4) & 0x7;
+ cfg->arb = (reg >> 1) & 0x1;
+ cfg->highspeed = reg & 0x1;
+}
+
+/*
+ * Sets the current clock configuration
+ */
+static void pmcmsptwi_set_clock_config(const struct pmcmsptwi_clockcfg *cfg,
+ struct pmcmsptwi_data *data)
+{
+ mutex_lock(&data->lock);
+ pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->standard),
+ data->iobase + MSP_TWI_SF_CLK_REG_OFFSET);
+ pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->highspeed),
+ data->iobase + MSP_TWI_HS_CLK_REG_OFFSET);
+ mutex_unlock(&data->lock);
+}
+
+/*
+ * Gets the current TWI bus configuration
+ */
+static void pmcmsptwi_get_twi_config(struct pmcmsptwi_cfg *cfg,
+ struct pmcmsptwi_data *data)
+{
+ mutex_lock(&data->lock);
+ pmcmsptwi_reg_to_cfg(pmcmsptwi_readl(
+ data->iobase + MSP_TWI_CFG_REG_OFFSET), cfg);
+ mutex_unlock(&data->lock);
+}
+
+/*
+ * Sets the current TWI bus configuration
+ */
+static void pmcmsptwi_set_twi_config(const struct pmcmsptwi_cfg *cfg,
+ struct pmcmsptwi_data *data)
+{
+ mutex_lock(&data->lock);
+ pmcmsptwi_writel(pmcmsptwi_cfg_to_reg(cfg),
+ data->iobase + MSP_TWI_CFG_REG_OFFSET);
+ mutex_unlock(&data->lock);
+}
+
+/*
+ * Parses the 'int_sts' register and returns a well-defined error code
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_get_result(u32 reg)
+{
+ if (reg & MSP_TWI_INT_STS_LOST_ARBITRATION) {
+ dev_dbg(&pmcmsptwi_adapter.dev,
+ "Result: Lost arbitration\n");
+ return MSP_TWI_XFER_LOST_ARBITRATION;
+ } else if (reg & MSP_TWI_INT_STS_NO_RESPONSE) {
+ dev_dbg(&pmcmsptwi_adapter.dev,
+ "Result: No response\n");
+ return MSP_TWI_XFER_NO_RESPONSE;
+ } else if (reg & MSP_TWI_INT_STS_DATA_COLLISION) {
+ dev_dbg(&pmcmsptwi_adapter.dev,
+ "Result: Data collision\n");
+ return MSP_TWI_XFER_DATA_COLLISION;
+ } else if (reg & MSP_TWI_INT_STS_BUSY) {
+ dev_dbg(&pmcmsptwi_adapter.dev,
+ "Result: Bus busy\n");
+ return MSP_TWI_XFER_BUSY;
+ }
+
+ dev_dbg(&pmcmsptwi_adapter.dev, "Result: Operation succeeded\n");
+ return MSP_TWI_XFER_OK;
+}
+
+/*
+ * In interrupt mode, handle the interrupt.
+ * NOTE: Assumes data->lock is held.
+ */
+static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr)
+{
+ struct pmcmsptwi_data *data = ptr;
+
+ u32 reason = pmcmsptwi_readl(data->iobase +
+ MSP_TWI_INT_STS_REG_OFFSET);
+ pmcmsptwi_writel(reason, data->iobase + MSP_TWI_INT_STS_REG_OFFSET);
+
+ dev_dbg(&pmcmsptwi_adapter.dev, "Got interrupt 0x%08x\n", reason);
+ if (!(reason & MSP_TWI_INT_STS_DONE))
+ return IRQ_NONE;
+
+ data->last_result = pmcmsptwi_get_result(reason);
+ complete(&data->wait);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Probe for and register the device and return 0 if there is one.
+ */
+static int __devinit pmcmsptwi_probe(struct platform_device *pldev)
+{
+ struct resource *res;
+ int rc = -ENODEV;
+
+ /* get the static platform resources */
+ res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pldev->dev, "IOMEM resource not found\n");
+ goto ret_err;
+ }
+
+ /* reserve the memory region */
+ if (!request_mem_region(res->start, res->end - res->start + 1,
+ pldev->name)) {
+ dev_err(&pldev->dev,
+ "Unable to get memory/io address region 0x%08x\n",
+ res->start);
+ rc = -EBUSY;
+ goto ret_err;
+ }
+
+ /* remap the memory */
+ pmcmsptwi_data.iobase = ioremap_nocache(res->start,
+ res->end - res->start + 1);
+ if (!pmcmsptwi_data.iobase) {
+ dev_err(&pldev->dev,
+ "Unable to ioremap address 0x%08x\n", res->start);
+ rc = -EIO;
+ goto ret_unreserve;
+ }
+
+ /* request the irq */
+ pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
+ if (pmcmsptwi_data.irq) {
+ rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
+ IRQF_SHARED | IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
+ pldev->name, &pmcmsptwi_data);
+ if (rc == 0) {
+ /*
+ * Enable 'DONE' interrupt only.
+ *
+ * If you enable all interrupts, you will get one on
+ * error and another when the operation completes.
+ * This way you only have to handle one interrupt,
+ * but you can still check all result flags.
+ */
+ pmcmsptwi_writel(MSP_TWI_INT_STS_DONE,
+ pmcmsptwi_data.iobase +
+ MSP_TWI_INT_MSK_REG_OFFSET);
+ } else {
+ dev_warn(&pldev->dev,
+ "Could not assign TWI IRQ handler "
+ "to irq %d (continuing with poll)\n",
+ pmcmsptwi_data.irq);
+ pmcmsptwi_data.irq = 0;
+ }
+ }
+
+ init_completion(&pmcmsptwi_data.wait);
+ mutex_init(&pmcmsptwi_data.lock);
+
+ pmcmsptwi_set_clock_config(&pmcmsptwi_defclockcfg, &pmcmsptwi_data);
+ pmcmsptwi_set_twi_config(&pmcmsptwi_defcfg, &pmcmsptwi_data);
+
+ printk(KERN_INFO DRV_NAME ": Registering MSP71xx I2C adapter\n");
+
+ pmcmsptwi_adapter.dev.parent = &pldev->dev;
+ platform_set_drvdata(pldev, &pmcmsptwi_adapter);
+ i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data);
+
+ rc = i2c_add_adapter(&pmcmsptwi_adapter);
+ if (rc) {
+ dev_err(&pldev->dev, "Unable to register I2C adapter\n");
+ goto ret_unmap;
+ }
+
+ return 0;
+
+ret_unmap:
+ platform_set_drvdata(pldev, NULL);
+ if (pmcmsptwi_data.irq) {
+ pmcmsptwi_writel(0,
+ pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
+ free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
+ }
+
+ iounmap(pmcmsptwi_data.iobase);
+
+ret_unreserve:
+ release_mem_region(res->start, res->end - res->start + 1);
+
+ret_err:
+ return rc;
+}
+
+/*
+ * Release the device and return 0 if there is one.
+ */
+static int __devexit pmcmsptwi_remove(struct platform_device *pldev)
+{
+ struct resource *res;
+
+ i2c_del_adapter(&pmcmsptwi_adapter);
+
+ platform_set_drvdata(pldev, NULL);
+ if (pmcmsptwi_data.irq) {
+ pmcmsptwi_writel(0,
+ pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET);
+ free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data);
+ }
+
+ iounmap(pmcmsptwi_data.iobase);
+
+ res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, res->end - res->start + 1);
+
+ return 0;
+}
+
+/*
+ * Polls the 'busy' register until the command is complete.
+ * NOTE: Assumes data->lock is held.
+ */
+static void pmcmsptwi_poll_complete(struct pmcmsptwi_data *data)
+{
+ int i;
+
+ for (i = 0; i < MSP_MAX_POLL; i++) {
+ u32 val = pmcmsptwi_readl(data->iobase +
+ MSP_TWI_BUSY_REG_OFFSET);
+ if (val == 0) {
+ u32 reason = pmcmsptwi_readl(data->iobase +
+ MSP_TWI_INT_STS_REG_OFFSET);
+ pmcmsptwi_writel(reason, data->iobase +
+ MSP_TWI_INT_STS_REG_OFFSET);
+ data->last_result = pmcmsptwi_get_result(reason);
+ return;
+ }
+ udelay(MSP_POLL_DELAY);
+ }
+
+ dev_dbg(&pmcmsptwi_adapter.dev, "Result: Poll timeout\n");
+ data->last_result = MSP_TWI_XFER_TIMEOUT;
+}
+
+/*
+ * Do the transfer (low level):
+ * May use interrupt-driven or polling, depending on if an IRQ is
+ * presently registered.
+ * NOTE: Assumes data->lock is held.
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_do_xfer(
+ u32 reg, struct pmcmsptwi_data *data)
+{
+ dev_dbg(&pmcmsptwi_adapter.dev, "Writing cmd reg 0x%08x\n", reg);
+ pmcmsptwi_writel(reg, data->iobase + MSP_TWI_CMD_REG_OFFSET);
+ if (data->irq) {
+ unsigned long timeleft = wait_for_completion_timeout(
+ &data->wait, MSP_IRQ_TIMEOUT);
+ if (timeleft == 0) {
+ dev_dbg(&pmcmsptwi_adapter.dev,
+ "Result: IRQ timeout\n");
+ complete(&data->wait);
+ data->last_result = MSP_TWI_XFER_TIMEOUT;
+ }
+ } else
+ pmcmsptwi_poll_complete(data);
+
+ return data->last_result;
+}
+
+/*
+ * Helper routine, converts 'pmctwi_cmd' struct to register format
+ */
+static inline u32 pmcmsptwi_cmd_to_reg(const struct pmcmsptwi_cmd *cmd)
+{
+ return ((cmd->type & 0x3) << 8) |
+ (((cmd->write_len - 1) & 0x7) << 4) |
+ ((cmd->read_len - 1) & 0x7);
+}
+
+/*
+ * Do the transfer (high level)
+ */
+static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
+ struct pmcmsptwi_cmd *cmd,
+ struct pmcmsptwi_data *data)
+{
+ enum pmcmsptwi_xfer_result retval;
+
+ if ((cmd->type == MSP_TWI_CMD_WRITE && cmd->write_len == 0) ||
+ (cmd->type == MSP_TWI_CMD_READ && cmd->read_len == 0) ||
+ (cmd->type == MSP_TWI_CMD_WRITE_READ &&
+ (cmd->read_len == 0 || cmd->write_len == 0))) {
+ dev_err(&pmcmsptwi_adapter.dev,
+ "%s: Cannot transfer less than 1 byte\n",
+ __FUNCTION__);
+ return -EINVAL;
+ }
+
+ if (cmd->read_len > MSP_MAX_BYTES_PER_RW ||
+ cmd->write_len > MSP_MAX_BYTES_PER_RW) {
+ dev_err(&pmcmsptwi_adapter.dev,
+ "%s: Cannot transfer more than %d bytes\n",
+ __FUNCTION__, MSP_MAX_BYTES_PER_RW);
+ return -EINVAL;
+ }
+
+ mutex_lock(&data->lock);
+ dev_dbg(&pmcmsptwi_adapter.dev,
+ "Setting address to 0x%04x\n", cmd->addr);
+ pmcmsptwi_writel(cmd->addr, data->iobase + MSP_TWI_ADD_REG_OFFSET);
+
+ if (cmd->type == MSP_TWI_CMD_WRITE ||
+ cmd->type == MSP_TWI_CMD_WRITE_READ) {
+ __be64 tmp = cpu_to_be64p((u64 *)cmd->write_data);
+ tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8;
+ dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp);
+ pmcmsptwi_writel(tmp & 0x00000000ffffffffLL,
+ data->iobase + MSP_TWI_DAT_0_REG_OFFSET);
+ if (cmd->write_len > 4)
+ pmcmsptwi_writel(tmp >> 32,
+ data->iobase + MSP_TWI_DAT_1_REG_OFFSET);
+ }
+
+ retval = pmcmsptwi_do_xfer(pmcmsptwi_cmd_to_reg(cmd), data);
+ if (retval != MSP_TWI_XFER_OK)
+ goto xfer_err;
+
+ if (cmd->type == MSP_TWI_CMD_READ ||
+ cmd->type == MSP_TWI_CMD_WRITE_READ) {
+ int i;
+ u64 rmsk = ~(0xffffffffffffffffLL << (cmd->read_len * 8));
+ u64 tmp = (u64)pmcmsptwi_readl(data->iobase +
+ MSP_TWI_DAT_0_REG_OFFSET);
+ if (cmd->read_len > 4)
+ tmp |= (u64)pmcmsptwi_readl(data->iobase +
+ MSP_TWI_DAT_1_REG_OFFSET) << 32;
+ tmp &= rmsk;
+ dev_dbg(&pmcmsptwi_adapter.dev, "Read 0x%016llx\n", tmp);
+
+ for (i = 0; i < cmd->read_len; i++)
+ cmd->read_data[i] = tmp >> i;
+ }
+
+xfer_err:
+ mutex_unlock(&data->lock);
+
+ return retval;
+}
+
+/* -- Algorithm functions -- */
+
+/*
+ * Sends an i2c command out on the adapter
+ */
+static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msg, int num)
+{
+ struct pmcmsptwi_data *data = i2c_get_adapdata(adap);
+ struct pmcmsptwi_cmd cmd;
+ struct pmcmsptwi_cfg oldcfg, newcfg;
+ int ret;
+
+ if (num > 2) {
+ dev_dbg(&adap->dev, "%d messages unsupported\n", num);
+ return -EINVAL;
+ } else if (num == 2) {
+ /* Check for a dual write-then-read command */
+ struct i2c_msg *nextmsg = msg + 1;
+ if (!(msg->flags & I2C_M_RD) &&
+ (nextmsg->flags & I2C_M_RD) &&
+ msg->addr == nextmsg->addr) {
+ cmd.type = MSP_TWI_CMD_WRITE_READ;
+ cmd.write_len = msg->len;
+ cmd.write_data = msg->buf;
+ cmd.read_len = nextmsg->len;
+ cmd.read_data = nextmsg->buf;
+ } else {
+ dev_dbg(&adap->dev,
+ "Non write-read dual messages unsupported\n");
+ return -EINVAL;
+ }
+ } else if (msg->flags & I2C_M_RD) {
+ cmd.type = MSP_TWI_CMD_READ;
+ cmd.read_len = msg->len;
+ cmd.read_data = msg->buf;
+ cmd.write_len = 0;
+ cmd.write_data = NULL;
+ } else {
+ cmd.type = MSP_TWI_CMD_WRITE;
+ cmd.read_len = 0;
+ cmd.read_data = NULL;
+ cmd.write_len = msg->len;
+ cmd.write_data = msg->buf;
+ }
+
+ if (msg->len == 0) {
+ dev_err(&adap->dev, "Zero-byte messages unsupported\n");
+ return -EINVAL;
+ }
+
+ cmd.addr = msg->addr;
+
+ if (msg->flags & I2C_M_TEN) {
+ pmcmsptwi_get_twi_config(&newcfg, data);
+ memcpy(&oldcfg, &newcfg, sizeof(oldcfg));
+
+ /* Set the special 10-bit address flag */
+ newcfg.add10 = 1;
+
+ pmcmsptwi_set_twi_config(&newcfg, data);
+ }
+
+ /* Execute the command */
+ ret = pmcmsptwi_xfer_cmd(&cmd, data);
+
+ if (msg->flags & I2C_M_TEN)
+ pmcmsptwi_set_twi_config(&oldcfg, data);
+
+ dev_dbg(&adap->dev, "I2C %s of %d bytes ",
+ (msg->flags & I2C_M_RD) ? "read" : "write", msg->len);
+ if (ret != MSP_TWI_XFER_OK) {
+ /*
+ * TODO: We could potentially loop and retry in the case
+ * of MSP_TWI_XFER_TIMEOUT.
+ */
+ dev_dbg(&adap->dev, "failed\n");
+ return -1;
+ }
+
+ dev_dbg(&adap->dev, "succeeded\n");
+ return 0;
+}
+
+static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
+ I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL;
+}
+
+/* -- Initialization -- */
+
+static struct i2c_algorithm pmcmsptwi_algo = {
+ .master_xfer = pmcmsptwi_master_xfer,
+ .functionality = pmcmsptwi_i2c_func,
+};
+
+static struct i2c_adapter pmcmsptwi_adapter = {
+ .owner = THIS_MODULE,
+ .class = I2C_CLASS_HWMON,
+ .algo = &pmcmsptwi_algo,
+ .name = DRV_NAME,
+};
+
+static struct platform_driver pmcmsptwi_driver = {
+ .probe = pmcmsptwi_probe,
+ .remove = __devexit_p(pmcmsptwi_remove),
+ .driver {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pmcmsptwi_init(void)
+{
+ return platform_driver_register(&pmcmsptwi_driver);
+}
+
+static void __exit pmcmsptwi_exit(void)
+{
+ platform_driver_unregister(&pmcmsptwi_driver);
+}
+
+MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver");
+MODULE_LICENSE("GPL");
+
+module_init(pmcmsptwi_init);
+module_exit(pmcmsptwi_exit);
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 1425d2245c8..0ab4f2627c2 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -121,8 +121,7 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap,
if (rc)
goto bail;
rc = pmac_i2c_xfer(bus, addrdir, 1, command,
- read ? data->block : &data->block[1],
- data->block[0]);
+ &data->block[1], data->block[0]);
break;
default:
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 28e7b91a455..9d6b790d432 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -921,7 +921,14 @@ static int i2c_pxa_probe(struct platform_device *dev)
i2c->adap.class = plat->class;
}
- ret = i2c_add_adapter(&i2c->adap);
+ /*
+ * If "dev->id" is negative we consider it as zero.
+ * The reason to do so is to avoid sysfs names that only make
+ * sense when there are multiple adapters.
+ */
+ i2c->adap.nr = dev->id >= 0 ? dev->id : 0;
+
+ ret = i2c_add_numbered_adapter(&i2c->adap);
if (ret < 0) {
printk(KERN_INFO "I2C: Failed to add bus\n");
goto eadapt;
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c
deleted file mode 100644
index 8764df06f51..00000000000
--- a/drivers/i2c/busses/i2c-rpx.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Embedded Planet RPX Lite MPC8xx CPM I2C interface.
- * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
- *
- * moved into proper i2c interface;
- * Brad Parker (brad@heeltoe.com)
- *
- * RPX lite specific parts of the i2c interface
- * Update: There actually isn't anything RPXLite-specific about this module.
- * This should work for most any 8xx board. The console messages have been
- * changed to eliminate RPXLite references.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/stddef.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-8xx.h>
-#include <asm/mpc8xx.h>
-#include <asm/commproc.h>
-
-
-static void
-rpx_iic_init(struct i2c_algo_8xx_data *data)
-{
- volatile cpm8xx_t *cp;
- volatile immap_t *immap;
-
- cp = cpmp; /* Get pointer to Communication Processor */
- immap = (immap_t *)IMAP_ADDR; /* and to internal registers */
-
- data->iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
-
- /* Check for and use a microcode relocation patch.
- */
- if ((data->reloc = data->iip->iic_rpbase))
- data->iip = (iic_t *)&cp->cp_dpmem[data->iip->iic_rpbase];
-
- data->i2c = (i2c8xx_t *)&(immap->im_i2c);
- data->cp = cp;
-
- /* Initialize Port B IIC pins.
- */
- cp->cp_pbpar |= 0x00000030;
- cp->cp_pbdir |= 0x00000030;
- cp->cp_pbodr |= 0x00000030;
-
- /* Allocate space for two transmit and two receive buffer
- * descriptors in the DP ram.
- */
- data->dp_addr = cpm_dpalloc(sizeof(cbd_t) * 4, 8);
-
- /* ptr to i2c area */
- data->i2c = (i2c8xx_t *)&(((immap_t *)IMAP_ADDR)->im_i2c);
-}
-
-static int rpx_install_isr(int irq, void (*func)(void *), void *data)
-{
- /* install interrupt handler */
- cpm_install_handler(irq, func, data);
-
- return 0;
-}
-
-static struct i2c_algo_8xx_data rpx_data = {
- .setisr = rpx_install_isr
-};
-
-static struct i2c_adapter rpx_ops = {
- .owner = THIS_MODULE,
- .name = "m8xx",
- .id = I2C_HW_MPC8XX_EPON,
- .algo_data = &rpx_data,
-};
-
-int __init i2c_rpx_init(void)
-{
- printk(KERN_INFO "i2c-rpx: i2c MPC8xx driver\n");
-
- /* reset hardware to sane state */
- rpx_iic_init(&rpx_data);
-
- if (i2c_8xx_add_bus(&rpx_ops) < 0) {
- printk(KERN_ERR "i2c-rpx: Unable to register with I2C\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-void __exit i2c_rpx_exit(void)
-{
- i2c_8xx_del_bus(&rpx_ops);
-}
-
-MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
-MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
-
-module_init(i2c_rpx_init);
-module_exit(i2c_rpx_exit);
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index b7fb65c3011..8adf4abaa03 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -25,8 +25,6 @@
/* This interfaces to the I2C bus of the Savage4 to gain access to
the BT869 and possibly other I2C devices. The DDC bus is not
yet supported because its register is not memory-mapped.
- However we leave the DDC code here, commented out, to make
- it easier to add later.
*/
#include <linux/kernel.h>
@@ -37,36 +35,19 @@
#include <linux/i2c-algo-bit.h>
#include <asm/io.h>
-/* 3DFX defines */
-#define PCI_CHIP_SAVAGE3D 0x8A20
-#define PCI_CHIP_SAVAGE3D_MV 0x8A21
+/* device IDs */
#define PCI_CHIP_SAVAGE4 0x8A22
#define PCI_CHIP_SAVAGE2000 0x9102
-#define PCI_CHIP_PROSAVAGE_PM 0x8A25
-#define PCI_CHIP_PROSAVAGE_KM 0x8A26
-#define PCI_CHIP_SAVAGE_MX_MV 0x8c10
-#define PCI_CHIP_SAVAGE_MX 0x8c11
-#define PCI_CHIP_SAVAGE_IX_MV 0x8c12
-#define PCI_CHIP_SAVAGE_IX 0x8c13
#define REG 0xff20 /* Serial Port 1 Register */
/* bit locations in the register */
-#define DDC_ENAB 0x00040000
-#define DDC_SCL_OUT 0x00080000
-#define DDC_SDA_OUT 0x00100000
-#define DDC_SCL_IN 0x00200000
-#define DDC_SDA_IN 0x00400000
#define I2C_ENAB 0x00000020
#define I2C_SCL_OUT 0x00000001
#define I2C_SDA_OUT 0x00000002
#define I2C_SCL_IN 0x00000008
#define I2C_SDA_IN 0x00000010
-/* initialization states */
-#define INIT2 0x20
-#define INIT3 0x04
-
/* delays */
#define CYCLE_DELAY 10
#define TIMEOUT (HZ / 2)
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index a6feed449db..283769cecee 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -129,6 +129,7 @@ MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller"
static struct pci_driver sis5595_driver;
static unsigned short sis5595_base;
+static struct pci_dev *sis5595_pdev;
static u8 sis5595_read(u8 reg)
{
@@ -379,6 +380,8 @@ MODULE_DEVICE_TABLE (pci, sis5595_ids);
static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
+ int err;
+
if (sis5595_setup(dev)) {
dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n");
return -ENODEV;
@@ -389,20 +392,24 @@ static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_
sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x",
sis5595_base + SMB_INDEX);
- return i2c_add_adapter(&sis5595_adapter);
-}
+ err = i2c_add_adapter(&sis5595_adapter);
+ if (err) {
+ release_region(sis5595_base + SMB_INDEX, 2);
+ return err;
+ }
-static void __devexit sis5595_remove(struct pci_dev *dev)
-{
- i2c_del_adapter(&sis5595_adapter);
- release_region(sis5595_base + SMB_INDEX, 2);
+ /* Always return failure here. This is to allow other drivers to bind
+ * to this pci device. We don't really want to have control over the
+ * pci device, we only wanted to read as few register values from it.
+ */
+ sis5595_pdev = pci_dev_get(dev);
+ return -ENODEV;
}
static struct pci_driver sis5595_driver = {
.name = "sis5595_smbus",
.id_table = sis5595_ids,
.probe = sis5595_probe,
- .remove = __devexit_p(sis5595_remove),
};
static int __init i2c_sis5595_init(void)
@@ -413,6 +420,12 @@ static int __init i2c_sis5595_init(void)
static void __exit i2c_sis5595_exit(void)
{
pci_unregister_driver(&sis5595_driver);
+ if (sis5595_pdev) {
+ i2c_del_adapter(&sis5595_adapter);
+ release_region(sis5595_base + SMB_INDEX, 2);
+ pci_dev_put(sis5595_pdev);
+ sis5595_pdev = NULL;
+ }
}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c
new file mode 100644
index 00000000000..1b0cfd5472f
--- /dev/null
+++ b/drivers/i2c/busses/i2c-taos-evm.c
@@ -0,0 +1,330 @@
+/*
+ * Driver for the TAOS evaluation modules
+ * These devices include an I2C master which can be controlled over the
+ * serial port.
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#define TAOS_BUFFER_SIZE 63
+
+#define TAOS_STATE_INIT 0
+#define TAOS_STATE_IDLE 1
+#define TAOS_STATE_SEND 2
+#define TAOS_STATE_RECV 3
+
+#define TAOS_CMD_RESET 0x12
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+struct taos_data {
+ struct i2c_adapter adapter;
+ struct i2c_client *client;
+ int state;
+ u8 addr; /* last used address */
+ unsigned char buffer[TAOS_BUFFER_SIZE];
+ unsigned int pos; /* position inside the buffer */
+};
+
+/* TAOS TSL2550 EVM */
+static struct i2c_board_info tsl2550_info = {
+ I2C_BOARD_INFO("tsl2550", 0x39),
+ .type = "tsl2550",
+};
+
+/* Instantiate i2c devices based on the adapter name */
+static struct i2c_client *taos_instantiate_device(struct i2c_adapter *adapter)
+{
+ if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) {
+ dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n",
+ tsl2550_info.driver_name, tsl2550_info.addr);
+ return i2c_new_device(adapter, &tsl2550_info);
+ }
+
+ return NULL;
+}
+
+static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data)
+{
+ struct serio *serio = adapter->algo_data;
+ struct taos_data *taos = serio_get_drvdata(serio);
+ char *p;
+
+ /* Encode our transaction. "@" is for the device address, "$" for the
+ SMBus command and "#" for the data. */
+ p = taos->buffer;
+
+ /* The device remembers the last used address, no need to send it
+ again if it's the same */
+ if (addr != taos->addr)
+ p += sprintf(p, "@%02X", addr);
+
+ switch (size) {
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_WRITE)
+ sprintf(p, "$#%02X", command);
+ else
+ sprintf(p, "$");
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ if (read_write == I2C_SMBUS_WRITE)
+ sprintf(p, "$%02X#%02X", command, data->byte);
+ else
+ sprintf(p, "$%02X", command);
+ break;
+ default:
+ dev_dbg(&adapter->dev, "Unsupported transaction size %d\n",
+ size);
+ return -EINVAL;
+ }
+
+ /* Send the transaction to the TAOS EVM */
+ dev_dbg(&adapter->dev, "Command buffer: %s\n", taos->buffer);
+ taos->pos = 0;
+ taos->state = TAOS_STATE_SEND;
+ serio_write(serio, taos->buffer[0]);
+ wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+ msecs_to_jiffies(250));
+ if (taos->state != TAOS_STATE_IDLE) {
+ dev_err(&adapter->dev, "Transaction failed "
+ "(state=%d, pos=%d)\n", taos->state, taos->pos);
+ taos->addr = 0;
+ return -EIO;
+ }
+ taos->addr = addr;
+
+ /* Start the transaction and read the answer */
+ taos->pos = 0;
+ taos->state = TAOS_STATE_RECV;
+ serio_write(serio, read_write == I2C_SMBUS_WRITE ? '>' : '<');
+ wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+ msecs_to_jiffies(150));
+ if (taos->state != TAOS_STATE_IDLE
+ || taos->pos != 6) {
+ dev_err(&adapter->dev, "Transaction timeout (pos=%d)\n",
+ taos->pos);
+ return -EIO;
+ }
+ dev_dbg(&adapter->dev, "Answer buffer: %s\n", taos->buffer);
+
+ /* Interpret the returned string */
+ p = taos->buffer + 2;
+ p[3] = '\0';
+ if (!strcmp(p, "NAK"))
+ return -ENODEV;
+
+ if (read_write == I2C_SMBUS_WRITE) {
+ if (!strcmp(p, "ACK"))
+ return 0;
+ } else {
+ if (p[0] == 'x') {
+ data->byte = simple_strtol(p + 1, NULL, 16);
+ return 0;
+ }
+ }
+
+ return -EIO;
+}
+
+static u32 taos_smbus_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static const struct i2c_algorithm taos_algorithm = {
+ .smbus_xfer = taos_smbus_xfer,
+ .functionality = taos_smbus_func,
+};
+
+static irqreturn_t taos_interrupt(struct serio *serio, unsigned char data,
+ unsigned int flags)
+{
+ struct taos_data *taos = serio_get_drvdata(serio);
+
+ switch (taos->state) {
+ case TAOS_STATE_INIT:
+ taos->buffer[taos->pos++] = data;
+ if (data == ':'
+ || taos->pos == TAOS_BUFFER_SIZE - 1) {
+ taos->buffer[taos->pos] = '\0';
+ taos->state = TAOS_STATE_IDLE;
+ wake_up_interruptible(&wq);
+ }
+ break;
+ case TAOS_STATE_SEND:
+ if (taos->buffer[++taos->pos])
+ serio_write(serio, taos->buffer[taos->pos]);
+ else {
+ taos->state = TAOS_STATE_IDLE;
+ wake_up_interruptible(&wq);
+ }
+ break;
+ case TAOS_STATE_RECV:
+ taos->buffer[taos->pos++] = data;
+ if (data == ']') {
+ taos->buffer[taos->pos] = '\0';
+ taos->state = TAOS_STATE_IDLE;
+ wake_up_interruptible(&wq);
+ }
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* Extract the adapter name from the buffer received after reset.
+ The buffer is modified and a pointer inside the buffer is returned. */
+static char *taos_adapter_name(char *buffer)
+{
+ char *start, *end;
+
+ start = strstr(buffer, "TAOS ");
+ if (!start)
+ return NULL;
+
+ end = strchr(start, '\r');
+ if (!end)
+ return NULL;
+ *end = '\0';
+
+ return start;
+}
+
+static int taos_connect(struct serio *serio, struct serio_driver *drv)
+{
+ struct taos_data *taos;
+ struct i2c_adapter *adapter;
+ char *name;
+ int err;
+
+ taos = kzalloc(sizeof(struct taos_data), GFP_KERNEL);
+ if (!taos) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ taos->state = TAOS_STATE_INIT;
+ serio_set_drvdata(serio, taos);
+
+ err = serio_open(serio, drv);
+ if (err)
+ goto exit_kfree;
+
+ adapter = &taos->adapter;
+ adapter->owner = THIS_MODULE;
+ adapter->algo = &taos_algorithm;
+ adapter->algo_data = serio;
+ adapter->dev.parent = &serio->dev;
+
+ /* Reset the TAOS evaluation module to identify it */
+ serio_write(serio, TAOS_CMD_RESET);
+ wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE,
+ msecs_to_jiffies(2000));
+
+ if (taos->state != TAOS_STATE_IDLE) {
+ err = -ENODEV;
+ dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, "
+ "pos=%d)\n", taos->state, taos->pos);
+ goto exit_close;
+ }
+
+ name = taos_adapter_name(taos->buffer);
+ if (!name) {
+ err = -ENODEV;
+ dev_err(&serio->dev, "TAOS EVM identification failed\n");
+ goto exit_close;
+ }
+ strlcpy(adapter->name, name, sizeof(adapter->name));
+
+ err = i2c_add_adapter(adapter);
+ if (err)
+ goto exit_close;
+ dev_dbg(&serio->dev, "Connected to TAOS EVM\n");
+
+ taos->client = taos_instantiate_device(adapter);
+ return 0;
+
+ exit_close:
+ serio_close(serio);
+ exit_kfree:
+ serio_set_drvdata(serio, NULL);
+ kfree(taos);
+ exit:
+ return err;
+}
+
+static void taos_disconnect(struct serio *serio)
+{
+ struct taos_data *taos = serio_get_drvdata(serio);
+
+ if (taos->client)
+ i2c_unregister_device(taos->client);
+ i2c_del_adapter(&taos->adapter);
+ serio_close(serio);
+ serio_set_drvdata(serio, NULL);
+ kfree(taos);
+
+ dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n");
+}
+
+static struct serio_device_id taos_serio_ids[] = {
+ {
+ .type = SERIO_RS232,
+ .proto = SERIO_TAOSEVM,
+ .id = SERIO_ANY,
+ .extra = SERIO_ANY,
+ },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(serio, taos_serio_ids);
+
+static struct serio_driver taos_drv = {
+ .driver = {
+ .name = "taos-evm",
+ },
+ .description = "TAOS evaluation module driver",
+ .id_table = taos_serio_ids,
+ .connect = taos_connect,
+ .disconnect = taos_disconnect,
+ .interrupt = taos_interrupt,
+};
+
+static int __init taos_init(void)
+{
+ return serio_register_driver(&taos_drv);
+}
+
+static void __exit taos_exit(void)
+{
+ serio_unregister_driver(&taos_drv);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("TAOS evaluation module driver");
+MODULE_LICENSE("GPL");
+
+module_init(taos_init);
+module_exit(taos_exit);
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 7a2bc06304f..edc275002f8 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -235,7 +235,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
if (!(vt596_features & FEATURE_I2CBLOCK))
goto exit_unsupported;
if (read_write == I2C_SMBUS_READ)
- outb_p(I2C_SMBUS_BLOCK_MAX, SMBHSTDAT0);
+ outb_p(data->block[0], SMBHSTDAT0);
/* Fall through */
case I2C_SMBUS_BLOCK_DATA:
outb_p(command, SMBHSTCMD);
@@ -397,8 +397,7 @@ found:
case PCI_DEVICE_ID_VIA_82C686_4:
/* The VT82C686B (rev 0x40) does support I2C block
transactions, but the VT82C686A (rev 0x30) doesn't */
- if (!pci_read_config_byte(pdev, PCI_REVISION_ID, &temp)
- && temp >= 0x40)
+ if (pdev->revision >= 0x40)
vt596_features |= FEATURE_I2CBLOCK;
break;
}
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 0d6bd4f7b7f..e6c4a2b762e 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -310,8 +310,6 @@ static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter,
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
- if (rw == I2C_SMBUS_READ)
- data->block[0] = I2C_SMBUS_BLOCK_MAX; /* For now */
len = data->block[0];
if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
return -EINVAL;
@@ -388,7 +386,7 @@ static const struct i2c_algorithm scx200_acb_algorithm = {
};
static struct scx200_acb_iface *scx200_acb_list;
-static DECLARE_MUTEX(scx200_acb_list_mutex);
+static DEFINE_MUTEX(scx200_acb_list_mutex);
static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
{
@@ -472,10 +470,10 @@ static int __init scx200_acb_create(struct scx200_acb_iface *iface)
return -ENODEV;
}
- down(&scx200_acb_list_mutex);
+ mutex_lock(&scx200_acb_list_mutex);
iface->next = scx200_acb_list;
scx200_acb_list = iface;
- up(&scx200_acb_list_mutex);
+ mutex_unlock(&scx200_acb_list_mutex);
return 0;
}
@@ -633,10 +631,10 @@ static void __exit scx200_acb_cleanup(void)
{
struct scx200_acb_iface *iface;
- down(&scx200_acb_list_mutex);
+ mutex_lock(&scx200_acb_list_mutex);
while ((iface = scx200_acb_list) != NULL) {
scx200_acb_list = iface->next;
- up(&scx200_acb_list_mutex);
+ mutex_unlock(&scx200_acb_list_mutex);
i2c_del_adapter(&iface->adapter);
@@ -648,9 +646,9 @@ static void __exit scx200_acb_cleanup(void)
release_region(iface->base, 8);
kfree(iface);
- down(&scx200_acb_list_mutex);
+ mutex_lock(&scx200_acb_list_mutex);
}
- up(&scx200_acb_list_mutex);
+ mutex_unlock(&scx200_acb_list_mutex);
}
module_init(scx200_acb_init);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index ea085a006ea..3944e889cb2 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -5,7 +5,7 @@
menu "Miscellaneous I2C Chip support"
config SENSORS_DS1337
- tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
+ tristate "Dallas DS1337 and DS1339 Real Time Clock (DEPRECATED)"
depends on EXPERIMENTAL
help
If you say yes here you get support for Dallas Semiconductor
@@ -14,8 +14,11 @@ config SENSORS_DS1337
This driver can also be built as a module. If so, the module
will be called ds1337.
+ This driver is deprecated and will be dropped soon. Use
+ rtc-ds1307 instead.
+
config SENSORS_DS1374
- tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
+ tristate "Dallas DS1374 Real Time Clock (DEPRECATED)"
depends on EXPERIMENTAL
help
If you say yes here you get support for Dallas Semiconductor
@@ -24,6 +27,19 @@ config SENSORS_DS1374
This driver can also be built as a module. If so, the module
will be called ds1374.
+ This driver is deprecated and will be dropped soon. Use
+ rtc-ds1374 instead.
+
+config DS1682
+ tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
+ depends on EXPERIMENTAL
+ help
+ If you say yes here you get support for Dallas Semiconductor
+ DS1682 Total Elapsed Time Recorder.
+
+ This driver can also be built as a module. If so, the module
+ will be called ds1682.
+
config SENSORS_EEPROM
tristate "EEPROM reader"
depends on EXPERIMENTAL
@@ -101,7 +117,7 @@ config TPS65010
will be called tps65010.
config SENSORS_M41T00
- tristate "ST M41T00 RTC chip"
+ tristate "ST M41T00 RTC chip (DEPRECATED)"
depends on PPC32
help
If you say yes here you get support for the ST M41T00 RTC chip.
@@ -109,6 +125,9 @@ config SENSORS_M41T00
This driver can also be built as a module. If so, the module
will be called m41t00.
+ This driver is deprecated and will be dropped soon. Use
+ rtc-ds1307 or rtc-m41t80 instead.
+
config SENSORS_MAX6875
tristate "Maxim MAX6875 Power supply supervisor"
depends on EXPERIMENTAL
@@ -124,4 +143,14 @@ config SENSORS_MAX6875
This driver can also be built as a module. If so, the module
will be called max6875.
+config SENSORS_TSL2550
+ tristate "Taos TSL2550 ambient light sensor"
+ depends on EXPERIMENTAL
+ help
+ If you say yes here you get support for the Taos TSL2550
+ ambient light sensor.
+
+ This driver can also be built as a module. If so, the module
+ will be called tsl2550.
+
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 779868ef2e2..d8cbeb3f4b6 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_SENSORS_DS1337) += ds1337.o
obj-$(CONFIG_SENSORS_DS1374) += ds1374.o
+obj-$(CONFIG_DS1682) += ds1682.o
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
@@ -12,6 +13,7 @@ obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TPS65010) += tps65010.o
+obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/ds1682.c b/drivers/i2c/chips/ds1682.c
new file mode 100644
index 00000000000..5879f0f2549
--- /dev/null
+++ b/drivers/i2c/chips/ds1682.c
@@ -0,0 +1,259 @@
+/*
+ * Dallas Semiconductor DS1682 Elapsed Time Recorder device driver
+ *
+ * Written by: Grant Likely <grant.likely@secretlab.ca>
+ *
+ * Copyright (C) 2007 Secret Lab Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * The DS1682 elapsed timer recorder is a simple device that implements
+ * one elapsed time counter, one event counter, an alarm signal and 10
+ * bytes of general purpose EEPROM.
+ *
+ * This driver provides access to the DS1682 counters and user data via
+ * the sysfs. The following attributes are added to the device node:
+ * elapsed_time (u32): Total elapsed event time in ms resolution
+ * alarm_time (u32): When elapsed time exceeds the value in alarm_time,
+ * then the alarm pin is asserted.
+ * event_count (u16): number of times the event pin has gone low.
+ * eeprom (u8[10]): general purpose EEPROM
+ *
+ * Counter registers and user data are both read/write unless the device
+ * has been write protected. This driver does not support turning off write
+ * protection. Once write protection is turned on, it is impossible to
+ * turn it off again, so I have left the feature out of this driver to avoid
+ * accidental enabling, but it is trivial to add write protect support.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/sysfs.h>
+#include <linux/ctype.h>
+#include <linux/hwmon-sysfs.h>
+
+/* Device registers */
+#define DS1682_REG_CONFIG 0x00
+#define DS1682_REG_ALARM 0x01
+#define DS1682_REG_ELAPSED 0x05
+#define DS1682_REG_EVT_CNTR 0x09
+#define DS1682_REG_EEPROM 0x0b
+#define DS1682_REG_RESET 0x1d
+#define DS1682_REG_WRITE_DISABLE 0x1e
+#define DS1682_REG_WRITE_MEM_DISABLE 0x1f
+
+#define DS1682_EEPROM_SIZE 10
+
+/*
+ * Generic counter attributes
+ */
+static ssize_t ds1682_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ __le32 val = 0;
+ int rc;
+
+ dev_dbg(dev, "ds1682_show() called on %s\n", attr->attr.name);
+
+ /* Read the register */
+ rc = i2c_smbus_read_i2c_block_data(client, sattr->index, sattr->nr,
+ (u8 *) & val);
+ if (rc < 0)
+ return -EIO;
+
+ /* Special case: the 32 bit regs are time values with 1/4s
+ * resolution, scale them up to milliseconds */
+ if (sattr->nr == 4)
+ return sprintf(buf, "%llu\n", ((u64) le32_to_cpu(val)) * 250);
+
+ /* Format the output string and return # of bytes */
+ return sprintf(buf, "%li\n", (long)le32_to_cpu(val));
+}
+
+static ssize_t ds1682_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ char *endp;
+ u64 val;
+ __le32 val_le;
+ int rc;
+
+ dev_dbg(dev, "ds1682_store() called on %s\n", attr->attr.name);
+
+ /* Decode input */
+ val = simple_strtoull(buf, &endp, 0);
+ if (buf == endp) {
+ dev_dbg(dev, "input string not a number\n");
+ return -EINVAL;
+ }
+
+ /* Special case: the 32 bit regs are time values with 1/4s
+ * resolution, scale input down to quarter-seconds */
+ if (sattr->nr == 4)
+ do_div(val, 250);
+
+ /* write out the value */
+ val_le = cpu_to_le32(val);
+ rc = i2c_smbus_write_i2c_block_data(client, sattr->index, sattr->nr,
+ (u8 *) & val_le);
+ if (rc < 0) {
+ dev_err(dev, "register write failed; reg=0x%x, size=%i\n",
+ sattr->index, sattr->nr);
+ return -EIO;
+ }
+
+ return count;
+}
+
+/*
+ * Simple register attributes
+ */
+static SENSOR_DEVICE_ATTR_2(elapsed_time, S_IRUGO | S_IWUSR, ds1682_show,
+ ds1682_store, 4, DS1682_REG_ELAPSED);
+static SENSOR_DEVICE_ATTR_2(alarm_time, S_IRUGO | S_IWUSR, ds1682_show,
+ ds1682_store, 4, DS1682_REG_ALARM);
+static SENSOR_DEVICE_ATTR_2(event_count, S_IRUGO | S_IWUSR, ds1682_show,
+ ds1682_store, 2, DS1682_REG_EVT_CNTR);
+
+static const struct attribute_group ds1682_group = {
+ .attrs = (struct attribute *[]) {
+ &sensor_dev_attr_elapsed_time.dev_attr.attr,
+ &sensor_dev_attr_alarm_time.dev_attr.attr,
+ &sensor_dev_attr_event_count.dev_attr.attr,
+ NULL,
+ },
+};
+
+/*
+ * User data attribute
+ */
+static ssize_t ds1682_eeprom_read(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
+ int rc;
+
+ dev_dbg(&client->dev, "ds1682_eeprom_read(p=%p, off=%lli, c=%zi)\n",
+ buf, off, count);
+
+ if (off >= DS1682_EEPROM_SIZE)
+ return 0;
+
+ if (off + count > DS1682_EEPROM_SIZE)
+ count = DS1682_EEPROM_SIZE - off;
+
+ rc = i2c_smbus_read_i2c_block_data(client, DS1682_REG_EEPROM + off,
+ count, buf);
+ if (rc < 0)
+ return -EIO;
+
+ return count;
+}
+
+static ssize_t ds1682_eeprom_write(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct i2c_client *client = kobj_to_i2c_client(kobj);
+
+ dev_dbg(&client->dev, "ds1682_eeprom_write(p=%p, off=%lli, c=%zi)\n",
+ buf, off, count);
+
+ if (off >= DS1682_EEPROM_SIZE)
+ return -ENOSPC;
+
+ if (off + count > DS1682_EEPROM_SIZE)
+ count = DS1682_EEPROM_SIZE - off;
+
+ /* Write out to the device */
+ if (i2c_smbus_write_i2c_block_data(client, DS1682_REG_EEPROM + off,
+ count, buf) < 0)
+ return -EIO;
+
+ return count;
+}
+
+static struct bin_attribute ds1682_eeprom_attr = {
+ .attr = {
+ .name = "eeprom",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = DS1682_EEPROM_SIZE,
+ .read = ds1682_eeprom_read,
+ .write = ds1682_eeprom_write,
+};
+
+/*
+ * Called when a ds1682 device is matched with this driver
+ */
+static int ds1682_probe(struct i2c_client *client)
+{
+ int rc;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ dev_err(&client->dev, "i2c bus does not support the ds1682\n");
+ rc = -ENODEV;
+ goto exit;
+ }
+
+ rc = sysfs_create_group(&client->dev.kobj, &ds1682_group);
+ if (rc)
+ goto exit;
+
+ rc = sysfs_create_bin_file(&client->dev.kobj, &ds1682_eeprom_attr);
+ if (rc)
+ goto exit_bin_attr;
+
+ return 0;
+
+ exit_bin_attr:
+ sysfs_remove_group(&client->dev.kobj, &ds1682_group);
+ exit:
+ return rc;
+}
+
+static int ds1682_remove(struct i2c_client *client)
+{
+ sysfs_remove_bin_file(&client->dev.kobj, &ds1682_eeprom_attr);
+ sysfs_remove_group(&client->dev.kobj, &ds1682_group);
+ return 0;
+}
+
+static struct i2c_driver ds1682_driver = {
+ .driver = {
+ .name = "ds1682",
+ },
+ .probe = ds1682_probe,
+ .remove = ds1682_remove,
+};
+
+static int __init ds1682_init(void)
+{
+ return i2c_add_driver(&ds1682_driver);
+}
+
+static void __exit ds1682_exit(void)
+{
+ i2c_del_driver(&ds1682_driver);
+}
+
+MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
+MODULE_DESCRIPTION("DS1682 Elapsed Time Indicator driver");
+MODULE_LICENSE("GPL");
+
+module_init(ds1682_init);
+module_exit(ds1682_exit);
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index bfce13c8f1f..d3da1fb05b9 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -88,8 +88,10 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
- for (i = slice << 5; i < (slice + 1) << 5; i += I2C_SMBUS_BLOCK_MAX)
- if (i2c_smbus_read_i2c_block_data(client, i, data->data + i) != I2C_SMBUS_BLOCK_MAX)
+ for (i = slice << 5; i < (slice + 1) << 5; i += 32)
+ if (i2c_smbus_read_i2c_block_data(client, i,
+ 32, data->data + i)
+ != 32)
goto exit;
} else {
if (i2c_smbus_write_byte(client, slice << 5)) {
@@ -110,7 +112,8 @@ exit:
mutex_unlock(&data->update_lock);
}
-static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
struct eeprom_data *data = i2c_get_clientdata(client);
@@ -143,7 +146,6 @@ static struct bin_attribute eeprom_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO,
- .owner = THIS_MODULE,
},
.size = EEPROM_SIZE,
.read = eeprom_read,
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
index 76645c14297..64692f66637 100644
--- a/drivers/i2c/chips/max6875.c
+++ b/drivers/i2c/chips/max6875.c
@@ -106,6 +106,7 @@ static void max6875_update_slice(struct i2c_client *client, int slice)
I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
if (i2c_smbus_read_i2c_block_data(client,
MAX6875_CMD_BLK_READ,
+ SLICE_SIZE,
buf) != SLICE_SIZE) {
goto exit_up;
}
@@ -125,8 +126,9 @@ exit_up:
mutex_unlock(&data->update_lock);
}
-static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t max6875_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct i2c_client *client = kobj_to_i2c_client(kobj);
struct max6875_data *data = i2c_get_clientdata(client);
@@ -152,7 +154,6 @@ static struct bin_attribute user_eeprom_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO,
- .owner = THIS_MODULE,
},
.size = USER_EEPROM_SIZE,
.read = max6875_read,
diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
new file mode 100644
index 00000000000..3de4b19ba08
--- /dev/null
+++ b/drivers/i2c/chips/tsl2550.c
@@ -0,0 +1,460 @@
+/*
+ * tsl2550.c - Linux kernel modules for ambient light sensor
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#define TSL2550_DRV_NAME "tsl2550"
+#define DRIVER_VERSION "1.1.1"
+
+/*
+ * Defines
+ */
+
+#define TSL2550_POWER_DOWN 0x00
+#define TSL2550_POWER_UP 0x03
+#define TSL2550_STANDARD_RANGE 0x18
+#define TSL2550_EXTENDED_RANGE 0x1d
+#define TSL2550_READ_ADC0 0x43
+#define TSL2550_READ_ADC1 0x83
+
+/*
+ * Structs
+ */
+
+struct tsl2550_data {
+ struct i2c_client *client;
+ struct mutex update_lock;
+
+ unsigned int power_state : 1;
+ unsigned int operating_mode : 1;
+};
+
+/*
+ * Global data
+ */
+
+static const u8 TSL2550_MODE_RANGE[2] = {
+ TSL2550_STANDARD_RANGE, TSL2550_EXTENDED_RANGE,
+};
+
+/*
+ * Management functions
+ */
+
+static int tsl2550_set_operating_mode(struct i2c_client *client, int mode)
+{
+ struct tsl2550_data *data = i2c_get_clientdata(client);
+
+ int ret = i2c_smbus_write_byte(client, TSL2550_MODE_RANGE[mode]);
+
+ data->operating_mode = mode;
+
+ return ret;
+}
+
+static int tsl2550_set_power_state(struct i2c_client *client, int state)
+{
+ struct tsl2550_data *data = i2c_get_clientdata(client);
+ int ret;
+
+ if (state == 0)
+ ret = i2c_smbus_write_byte(client, TSL2550_POWER_DOWN);
+ else {
+ ret = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
+
+ /* On power up we should reset operating mode also... */
+ tsl2550_set_operating_mode(client, data->operating_mode);
+ }
+
+ data->power_state = state;
+
+ return ret;
+}
+
+static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd)
+{
+ unsigned long end;
+ int loop = 0, ret = 0;
+
+ /*
+ * Read ADC channel waiting at most 400ms (see data sheet for further
+ * info).
+ * To avoid long busy wait we spin for few milliseconds then
+ * start sleeping.
+ */
+ end = jiffies + msecs_to_jiffies(400);
+ while (time_before(jiffies, end)) {
+ i2c_smbus_write_byte(client, cmd);
+
+ if (loop++ < 5)
+ mdelay(1);
+ else
+ msleep(1);
+
+ ret = i2c_smbus_read_byte(client);
+ if (ret < 0)
+ return ret;
+ else if (ret & 0x0080)
+ break;
+ }
+ if (!(ret & 0x80))
+ return -EIO;
+ return ret & 0x7f; /* remove the "valid" bit */
+}
+
+/*
+ * LUX calculation
+ */
+
+#define TSL2550_MAX_LUX 1846
+
+static const u8 ratio_lut[] = {
+ 100, 100, 100, 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100, 100, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 98, 98, 98, 98, 98,
+ 98, 98, 97, 97, 97, 97, 97, 96,
+ 96, 96, 96, 95, 95, 95, 94, 94,
+ 93, 93, 93, 92, 92, 91, 91, 90,
+ 89, 89, 88, 87, 87, 86, 85, 84,
+ 83, 82, 81, 80, 79, 78, 77, 75,
+ 74, 73, 71, 69, 68, 66, 64, 62,
+ 60, 58, 56, 54, 52, 49, 47, 44,
+ 42, 41, 40, 40, 39, 39, 38, 38,
+ 37, 37, 37, 36, 36, 36, 35, 35,
+ 35, 35, 34, 34, 34, 34, 33, 33,
+ 33, 33, 32, 32, 32, 32, 32, 31,
+ 31, 31, 31, 31, 30, 30, 30, 30,
+ 30,
+};
+
+static const u16 count_lut[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46,
+ 49, 53, 57, 61, 65, 69, 73, 77,
+ 81, 85, 89, 93, 97, 101, 105, 109,
+ 115, 123, 131, 139, 147, 155, 163, 171,
+ 179, 187, 195, 203, 211, 219, 227, 235,
+ 247, 263, 279, 295, 311, 327, 343, 359,
+ 375, 391, 407, 423, 439, 455, 471, 487,
+ 511, 543, 575, 607, 639, 671, 703, 735,
+ 767, 799, 831, 863, 895, 927, 959, 991,
+ 1039, 1103, 1167, 1231, 1295, 1359, 1423, 1487,
+ 1551, 1615, 1679, 1743, 1807, 1871, 1935, 1999,
+ 2095, 2223, 2351, 2479, 2607, 2735, 2863, 2991,
+ 3119, 3247, 3375, 3503, 3631, 3759, 3887, 4015,
+};
+
+/*
+ * This function is described into Taos TSL2550 Designer's Notebook
+ * pages 2, 3.
+ */
+static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
+{
+ unsigned int lux;
+
+ /* Look up count from channel values */
+ u16 c0 = count_lut[ch0];
+ u16 c1 = count_lut[ch1];
+
+ /*
+ * Calculate ratio.
+ * Note: the "128" is a scaling factor
+ */
+ u8 r = 128;
+
+ /* Avoid division by 0 and count 1 cannot be greater than count 0 */
+ if (c0 && (c1 <= c0))
+ r = c1 * 128 / c0;
+ else
+ return -1;
+
+ /* Calculate LUX */
+ lux = ((c0 - c1) * ratio_lut[r]) / 256;
+
+ /* LUX range check */
+ return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
+}
+
+/*
+ * SysFS support
+ */
+
+static ssize_t tsl2550_show_power_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
+
+ return sprintf(buf, "%u\n", data->power_state);
+}
+
+static ssize_t tsl2550_store_power_state(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsl2550_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ int ret;
+
+ if (val < 0 || val > 1)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ ret = tsl2550_set_power_state(client, val);
+ mutex_unlock(&data->update_lock);
+
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO,
+ tsl2550_show_power_state, tsl2550_store_power_state);
+
+static ssize_t tsl2550_show_operating_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tsl2550_data *data = i2c_get_clientdata(to_i2c_client(dev));
+
+ return sprintf(buf, "%u\n", data->operating_mode);
+}
+
+static ssize_t tsl2550_store_operating_mode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsl2550_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ int ret;
+
+ if (val < 0 || val > 1)
+ return -EINVAL;
+
+ if (data->power_state == 0)
+ return -EBUSY;
+
+ mutex_lock(&data->update_lock);
+ ret = tsl2550_set_operating_mode(client, val);
+ mutex_unlock(&data->update_lock);
+
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(operating_mode, S_IWUSR | S_IRUGO,
+ tsl2550_show_operating_mode, tsl2550_store_operating_mode);
+
+static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf)
+{
+ u8 ch0, ch1;
+ int ret;
+
+ ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC0);
+ if (ret < 0)
+ return ret;
+ ch0 = ret;
+
+ mdelay(1);
+
+ ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1);
+ if (ret < 0)
+ return ret;
+ ch1 = ret;
+
+ /* Do the job */
+ ret = tsl2550_calculate_lux(ch0, ch1);
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t tsl2550_show_lux1_input(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct tsl2550_data *data = i2c_get_clientdata(client);
+ int ret;
+
+ /* No LUX data if not operational */
+ if (!data->power_state)
+ return -EBUSY;
+
+ mutex_lock(&data->update_lock);
+ ret = __tsl2550_show_lux(client, buf);
+ mutex_unlock(&data->update_lock);
+
+ return ret;
+}
+
+static DEVICE_ATTR(lux1_input, S_IRUGO,
+ tsl2550_show_lux1_input, NULL);
+
+static struct attribute *tsl2550_attributes[] = {
+ &dev_attr_power_state.attr,
+ &dev_attr_operating_mode.attr,
+ &dev_attr_lux1_input.attr,
+ NULL
+};
+
+static const struct attribute_group tsl2550_attr_group = {
+ .attrs = tsl2550_attributes,
+};
+
+/*
+ * Initialization function
+ */
+
+static int tsl2550_init_client(struct i2c_client *client)
+{
+ struct tsl2550_data *data = i2c_get_clientdata(client);
+ int err;
+
+ /*
+ * Probe the chip. To do so we try to power up the device and then to
+ * read back the 0x03 code
+ */
+ err = i2c_smbus_write_byte(client, TSL2550_POWER_UP);
+ if (err < 0)
+ return err;
+ mdelay(1);
+ if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP)
+ return -ENODEV;
+ data->power_state = 1;
+
+ /* Set the default operating mode */
+ err = i2c_smbus_write_byte(client,
+ TSL2550_MODE_RANGE[data->operating_mode]);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+
+static struct i2c_driver tsl2550_driver;
+static int __devinit tsl2550_probe(struct i2c_client *client)
+{
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct tsl2550_data *data;
+ int *opmode, err = 0;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
+ err = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct tsl2550_data), GFP_KERNEL);
+ if (!data) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ data->client = client;
+ i2c_set_clientdata(client, data);
+
+ /* Check platform data */
+ opmode = client->dev.platform_data;
+ if (opmode) {
+ if (*opmode < 0 || *opmode > 1) {
+ dev_err(&client->dev, "invalid operating_mode (%d)\n",
+ *opmode);
+ err = -EINVAL;
+ goto exit_kfree;
+ }
+ data->operating_mode = *opmode;
+ } else
+ data->operating_mode = 0; /* default mode is standard */
+ dev_info(&client->dev, "%s operating mode\n",
+ data->operating_mode ? "extended" : "standard");
+
+ mutex_init(&data->update_lock);
+
+ /* Initialize the TSL2550 chip */
+ err = tsl2550_init_client(client);
+ if (err)
+ goto exit_kfree;
+
+ /* Register sysfs hooks */
+ err = sysfs_create_group(&client->dev.kobj, &tsl2550_attr_group);
+ if (err)
+ goto exit_kfree;
+
+ dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+
+ return 0;
+
+exit_kfree:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int __devexit tsl2550_remove(struct i2c_client *client)
+{
+ sysfs_remove_group(&client->dev.kobj, &tsl2550_attr_group);
+
+ /* Power down the device */
+ tsl2550_set_power_state(client, 0);
+
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+static struct i2c_driver tsl2550_driver = {
+ .driver = {
+ .name = TSL2550_DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = tsl2550_probe,
+ .remove = __devexit_p(tsl2550_remove),
+};
+
+static int __init tsl2550_init(void)
+{
+ return i2c_add_driver(&tsl2550_driver);
+}
+
+static void __exit tsl2550_exit(void)
+{
+ i2c_del_driver(&tsl2550_driver);
+}
+
+MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
+MODULE_DESCRIPTION("TSL2550 ambient light sensor driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+module_init(tsl2550_init);
+module_exit(tsl2550_exit);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 435925eba43..6971a62397d 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -207,6 +207,7 @@ EXPORT_SYMBOL_GPL(i2c_bus_type);
* i2c_new_device - instantiate an i2c device for use with a new style driver
* @adap: the adapter managing the device
* @info: describes one I2C device; bus_num is ignored
+ * Context: can sleep
*
* Create a device to work with a new style i2c driver, where binding is
* handled through driver model probe()/remove() methods. This call is not
@@ -255,6 +256,7 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
/**
* i2c_unregister_device - reverse effect of i2c_new_device()
* @client: value returned from i2c_new_device()
+ * Context: can sleep
*/
void i2c_unregister_device(struct i2c_client *client)
{
@@ -379,6 +381,7 @@ out_list:
/**
* i2c_add_adapter - declare i2c adapter, use dynamic bus number
* @adapter: the adapter to add
+ * Context: can sleep
*
* This routine is used to declare an I2C adapter when its bus number
* doesn't matter. Examples: for I2C adapters dynamically added by
@@ -416,6 +419,7 @@ EXPORT_SYMBOL(i2c_add_adapter);
/**
* i2c_add_numbered_adapter - declare i2c adapter, use static bus number
* @adap: the adapter to register (with adap->nr initialized)
+ * Context: can sleep
*
* This routine is used to declare an I2C adapter when its bus number
* matters. Example: for I2C adapters from system-on-chip CPUs, or
@@ -463,6 +467,14 @@ retry:
}
EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
+/**
+ * i2c_del_adapter - unregister I2C adapter
+ * @adap: the adapter being unregistered
+ * Context: can sleep
+ *
+ * This unregisters an I2C adapter which was previously registered
+ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+ */
int i2c_del_adapter(struct i2c_adapter *adap)
{
struct list_head *item, *_n;
@@ -598,6 +610,7 @@ EXPORT_SYMBOL(i2c_register_driver);
/**
* i2c_del_driver - unregister I2C driver
* @driver: the driver being unregistered
+ * Context: can sleep
*/
void i2c_del_driver(struct i2c_driver *driver)
{
@@ -1331,10 +1344,14 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
EXPORT_SYMBOL(i2c_smbus_write_block_data);
/* Returns the number of read bytes */
-s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
+s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
+ u8 length, u8 *values)
{
union i2c_smbus_data data;
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ length = I2C_SMBUS_BLOCK_MAX;
+ data.block[0] = length;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
I2C_SMBUS_READ,command,
I2C_SMBUS_I2C_BLOCK_DATA,&data))
@@ -1455,7 +1472,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) {
- msg[1].len = I2C_SMBUS_BLOCK_MAX;
+ msg[1].len = data->block[0];
} else {
msg[0].len = data->block[0] + 1;
if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
@@ -1511,9 +1528,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
data->word = msgbuf1[0] | (msgbuf1[1] << 8);
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
- /* fixed at 32 for now */
- data->block[0] = I2C_SMBUS_BLOCK_MAX;
- for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
+ for (i = 0; i < data->block[0]; i++)
data->block[i+1] = msgbuf1[i];
break;
case I2C_SMBUS_BLOCK_DATA:
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index e7a70971059..64eee9551b2 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -283,6 +283,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
(data_arg.size != I2C_SMBUS_WORD_DATA) &&
(data_arg.size != I2C_SMBUS_PROC_CALL) &&
(data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
+ (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
(data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
dev_dbg(&client->adapter->dev,
@@ -329,10 +330,18 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
+ (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
(data_arg.read_write == I2C_SMBUS_WRITE)) {
if (copy_from_user(&temp, data_arg.data, datasize))
return -EFAULT;
}
+ if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
+ /* Convert old I2C block commands to the new
+ convention. This preserves binary compatibility. */
+ data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
+ if (data_arg.read_write == I2C_SMBUS_READ)
+ temp.block[0] = I2C_SMBUS_BLOCK_MAX;
+ }
res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
data_arg.read_write,
data_arg.command,data_arg.size,&temp);
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 66f826252ae..c89b5f4b2d0 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -18,10 +18,10 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/scatterlist.h>
+#include <linux/io.h>
#include <asm/dma.h>
#include <asm/ecard.h>
-#include <asm/io.h>
#define ICS_IDENT_OFFSET 0x2280
@@ -448,23 +448,21 @@ static int icside_dma_test_irq(ide_drive_t *drive)
ICS_ARCIN_V6_INTRSTAT_1)) & 1;
}
-static int icside_dma_timeout(ide_drive_t *drive)
+static void icside_dma_timeout(ide_drive_t *drive)
{
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
if (icside_dma_test_irq(drive))
- return 0;
+ return;
- ide_dump_status(drive, "DMA timeout",
- HWIF(drive)->INB(IDE_STATUS_REG));
+ ide_dump_status(drive, "DMA timeout", HWIF(drive)->INB(IDE_STATUS_REG));
- return icside_dma_end(drive);
+ icside_dma_end(drive);
}
-static int icside_dma_lostirq(ide_drive_t *drive)
+static void icside_dma_lost_irq(ide_drive_t *drive)
{
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
- return 1;
}
static void icside_dma_init(ide_hwif_t *hwif)
@@ -490,8 +488,8 @@ static void icside_dma_init(ide_hwif_t *hwif)
hwif->dma_start = icside_dma_start;
hwif->ide_dma_end = icside_dma_end;
hwif->ide_dma_test_irq = icside_dma_test_irq;
- hwif->ide_dma_timeout = icside_dma_timeout;
- hwif->ide_dma_lostirq = icside_dma_lostirq;
+ hwif->dma_timeout = icside_dma_timeout;
+ hwif->dma_lost_irq = icside_dma_lost_irq;
hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index ca0341c05e5..886091bc7db 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -819,7 +819,7 @@ init_e100_ide (void)
hwif->dma_host_off = &cris_dma_off;
hwif->dma_host_on = &cris_dma_on;
hwif->dma_off_quietly = &cris_dma_off;
- hwif->udma_four = 0;
+ hwif->cbl = ATA_CBL_PATA40;
hwif->ultra_mask = cris_ultra_mask;
hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
hwif->autodma = 1;
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 252ab8295ed..1486eb212cc 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -481,7 +481,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
else
printk(" Unknown Error Type: ");
- if (sense->sense_key < ARY_LEN(sense_key_texts))
+ if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
s = sense_key_texts[sense->sense_key];
printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
@@ -491,7 +491,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
sense->ascq);
s = buf;
} else {
- int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
+ int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
unsigned long key = (sense->sense_key << 16);
key |= (sense->asc << 8);
if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
@@ -524,7 +524,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
if (failed_command != NULL) {
- int lo=0, mid, hi= ARY_LEN (packet_command_texts);
+ int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
s = NULL;
while (hi > lo) {
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index ad1f2ed14a3..228b29c5d2e 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -498,8 +498,6 @@ struct cdrom_info {
* Descriptions of ATAPI error codes.
*/
-#define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
-
/* This stuff should be in cdrom.h, since it is now generic... */
/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7fff773f2df..b1304a7f3e0 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1037,6 +1037,17 @@ static void ide_disk_release(struct kref *kref)
static int ide_disk_probe(ide_drive_t *drive);
+/*
+ * On HPA drives the capacity needs to be
+ * reinitilized on resume otherwise the disk
+ * can not be used and a hard reset is required
+ */
+static void ide_disk_resume(ide_drive_t *drive)
+{
+ if (idedisk_supports_hpa(drive->id))
+ init_idedisk_capacity(drive);
+}
+
static void ide_device_shutdown(ide_drive_t *drive)
{
#ifdef CONFIG_ALPHA
@@ -1071,6 +1082,7 @@ static ide_driver_t idedisk_driver = {
},
.probe = ide_disk_probe,
.remove = ide_disk_remove,
+ .resume = ide_disk_resume,
.shutdown = ide_device_shutdown,
.version = IDEDISK_VERSION,
.media = ide_disk,
@@ -1178,11 +1190,11 @@ static int idedisk_ioctl(struct inode *inode, struct file *file,
return generic_ide_ioctl(drive, file, bdev, cmd, arg);
read_val:
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
err = *val;
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
set_val:
@@ -1192,9 +1204,9 @@ set_val:
if (!capable(CAP_SYS_ADMIN))
err = -EACCES;
else {
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
err = setfunc(drive, arg);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
}
return err;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index ead141e2db9..5fe1d72ab45 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -91,45 +91,45 @@
static const struct drive_list_entry drive_whitelist [] = {
- { "Micropolis 2112A" , "ALL" },
- { "CONNER CTMA 4000" , "ALL" },
- { "CONNER CTT8000-A" , "ALL" },
- { "ST34342A" , "ALL" },
+ { "Micropolis 2112A" , NULL },
+ { "CONNER CTMA 4000" , NULL },
+ { "CONNER CTT8000-A" , NULL },
+ { "ST34342A" , NULL },
{ NULL , NULL }
};
static const struct drive_list_entry drive_blacklist [] = {
- { "WDC AC11000H" , "ALL" },
- { "WDC AC22100H" , "ALL" },
- { "WDC AC32500H" , "ALL" },
- { "WDC AC33100H" , "ALL" },
- { "WDC AC31600H" , "ALL" },
+ { "WDC AC11000H" , NULL },
+ { "WDC AC22100H" , NULL },
+ { "WDC AC32500H" , NULL },
+ { "WDC AC33100H" , NULL },
+ { "WDC AC31600H" , NULL },
{ "WDC AC32100H" , "24.09P07" },
{ "WDC AC23200L" , "21.10N21" },
- { "Compaq CRD-8241B" , "ALL" },
- { "CRD-8400B" , "ALL" },
- { "CRD-8480B", "ALL" },
- { "CRD-8482B", "ALL" },
- { "CRD-84" , "ALL" },
- { "SanDisk SDP3B" , "ALL" },
- { "SanDisk SDP3B-64" , "ALL" },
- { "SANYO CD-ROM CRD" , "ALL" },
- { "HITACHI CDR-8" , "ALL" },
- { "HITACHI CDR-8335" , "ALL" },
- { "HITACHI CDR-8435" , "ALL" },
- { "Toshiba CD-ROM XM-6202B" , "ALL" },
- { "TOSHIBA CD-ROM XM-1702BC", "ALL" },
- { "CD-532E-A" , "ALL" },
- { "E-IDE CD-ROM CR-840", "ALL" },
- { "CD-ROM Drive/F5A", "ALL" },
- { "WPI CDD-820", "ALL" },
- { "SAMSUNG CD-ROM SC-148C", "ALL" },
- { "SAMSUNG CD-ROM SC", "ALL" },
- { "ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL" },
- { "_NEC DV5800A", "ALL" },
+ { "Compaq CRD-8241B" , NULL },
+ { "CRD-8400B" , NULL },
+ { "CRD-8480B", NULL },
+ { "CRD-8482B", NULL },
+ { "CRD-84" , NULL },
+ { "SanDisk SDP3B" , NULL },
+ { "SanDisk SDP3B-64" , NULL },
+ { "SANYO CD-ROM CRD" , NULL },
+ { "HITACHI CDR-8" , NULL },
+ { "HITACHI CDR-8335" , NULL },
+ { "HITACHI CDR-8435" , NULL },
+ { "Toshiba CD-ROM XM-6202B" , NULL },
+ { "TOSHIBA CD-ROM XM-1702BC", NULL },
+ { "CD-532E-A" , NULL },
+ { "E-IDE CD-ROM CR-840", NULL },
+ { "CD-ROM Drive/F5A", NULL },
+ { "WPI CDD-820", NULL },
+ { "SAMSUNG CD-ROM SC-148C", NULL },
+ { "SAMSUNG CD-ROM SC", NULL },
+ { "ATAPI CD-ROM DRIVE 40X MAXIMUM", NULL },
+ { "_NEC DV5800A", NULL },
{ "SAMSUNG CD-ROM SN-124", "N001" },
- { "Seagate STT20000A", "ALL" },
+ { "Seagate STT20000A", NULL },
{ NULL , NULL }
};
@@ -147,8 +147,8 @@ int ide_in_drive_list(struct hd_driveid *id, const struct drive_list_entry *driv
{
for ( ; drive_table->id_model ; drive_table++)
if ((!strcmp(drive_table->id_model, id->model)) &&
- ((strstr(id->fw_rev, drive_table->id_firmware)) ||
- (!strcmp(drive_table->id_firmware, "ALL"))))
+ (!drive_table->id_firmware ||
+ strstr(id->fw_rev, drive_table->id_firmware)))
return 1;
return 0;
}
@@ -702,8 +702,22 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
mask = id->dma_mword & hwif->mwdma_mask;
break;
case XFER_SW_DMA_0:
- if (id->field_valid & 2)
+ if (id->field_valid & 2) {
mask = id->dma_1word & hwif->swdma_mask;
+ } else if (id->tDMA) {
+ /*
+ * ide_fix_driveid() doesn't convert ->tDMA to the
+ * CPU endianness so we need to do it here
+ */
+ u8 mode = le16_to_cpu(id->tDMA);
+
+ /*
+ * if the mode is valid convert it to the mask
+ * (the maximum allowed mode is XFER_SW_DMA_2)
+ */
+ if (mode <= 2)
+ mask = ((2 << mode) - 1) & hwif->swdma_mask;
+ }
break;
default:
BUG();
@@ -847,27 +861,27 @@ int ide_set_dma(ide_drive_t *drive)
return rc;
}
-EXPORT_SYMBOL_GPL(ide_set_dma);
-
#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-int __ide_dma_lostirq (ide_drive_t *drive)
+void ide_dma_lost_irq (ide_drive_t *drive)
{
printk("%s: DMA interrupt recovery\n", drive->name);
- return 1;
}
-EXPORT_SYMBOL(__ide_dma_lostirq);
+EXPORT_SYMBOL(ide_dma_lost_irq);
-int __ide_dma_timeout (ide_drive_t *drive)
+void ide_dma_timeout (ide_drive_t *drive)
{
+ ide_hwif_t *hwif = HWIF(drive);
+
printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
- if (HWIF(drive)->ide_dma_test_irq(drive))
- return 0;
- return HWIF(drive)->ide_dma_end(drive);
+ if (hwif->ide_dma_test_irq(drive))
+ return;
+
+ hwif->ide_dma_end(drive);
}
-EXPORT_SYMBOL(__ide_dma_timeout);
+EXPORT_SYMBOL(ide_dma_timeout);
/*
* Needed for allowing full modular support of ide-driver
@@ -1018,10 +1032,10 @@ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_p
hwif->ide_dma_end = &__ide_dma_end;
if (!hwif->ide_dma_test_irq)
hwif->ide_dma_test_irq = &__ide_dma_test_irq;
- if (!hwif->ide_dma_timeout)
- hwif->ide_dma_timeout = &__ide_dma_timeout;
- if (!hwif->ide_dma_lostirq)
- hwif->ide_dma_lostirq = &__ide_dma_lostirq;
+ if (!hwif->dma_timeout)
+ hwif->dma_timeout = &ide_dma_timeout;
+ if (!hwif->dma_lost_irq)
+ hwif->dma_lost_irq = &ide_dma_lost_irq;
if (hwif->chipset != ide_trm290) {
u8 dma_stat = hwif->INB(hwif->dma_status);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index bfe8f1b712b..c5b5011da56 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -1350,7 +1350,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
hwif->INB(IDE_STATUS_REG));
} else {
printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
- (void) hwif->ide_dma_timeout(drive);
+ hwif->dma_timeout(drive);
}
/*
@@ -1466,7 +1466,7 @@ void ide_timer_expiry (unsigned long data)
startstop = handler(drive);
} else if (drive_is_ready(drive)) {
if (drive->waiting_for_dma)
- (void) hwgroup->hwif->ide_dma_lostirq(drive);
+ hwgroup->hwif->dma_lost_irq(drive);
(void)ide_ack_intr(hwif);
printk(KERN_WARNING "%s: lost interrupt\n", drive->name);
startstop = handler(drive);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index f0be5f665a0..92578b6832e 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -574,7 +574,10 @@ u8 eighty_ninty_three (ide_drive_t *drive)
ide_hwif_t *hwif = drive->hwif;
struct hd_driveid *id = drive->id;
- if (hwif->udma_four == 0)
+ if (hwif->cbl == ATA_CBL_PATA40_SHORT)
+ return 1;
+
+ if (hwif->cbl != ATA_CBL_PATA80)
goto no_80w;
/* Check for SATA but only if we are ATA5 or higher */
@@ -600,7 +603,8 @@ no_80w:
printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
"limiting max speed to UDMA33\n",
- drive->name, hwif->udma_four ? "drive" : "host");
+ drive->name,
+ hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
drive->udma33_warned = 1;
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 3cebed77f55..cc580139946 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -144,7 +144,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
local_irq_enable();
ide_fix_driveid(id);
-#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
+#if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
/*
* EATA SCSI controllers do a hardware ATA emulation:
* Ignore them if there is a driver for them available.
@@ -154,7 +154,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
printk("%s: EATA SCSI HBA %.10s\n", drive->name, id->model);
goto err_misc;
}
-#endif /* CONFIG_SCSI_EATA_DMA || CONFIG_SCSI_EATA_PIO */
+#endif /* CONFIG_SCSI_EATA || CONFIG_SCSI_EATA_PIO */
/*
* WIN_IDENTIFY returns little-endian info,
@@ -574,11 +574,11 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
/* look for ATAPI device */
(void) do_probe(drive, WIN_PIDENTIFY);
}
- if (strstr(drive->id->model, "E X A B Y T E N E S T"))
- enable_nest(drive);
if (!drive->present)
/* drive not found */
return 0;
+ if (strstr(drive->id->model, "E X A B Y T E N E S T"))
+ enable_nest(drive);
/* identification failed? */
if (!drive->id_read) {
@@ -717,7 +717,7 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave);
* This routine only knows how to look for drive units 0 and 1
* on an interface, so any setting of MAX_DRIVES > 2 won't work here.
*/
-static void probe_hwif(ide_hwif_t *hwif)
+static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
{
unsigned int unit;
unsigned long flags;
@@ -820,6 +820,9 @@ static void probe_hwif(ide_hwif_t *hwif)
return;
}
+ if (fixup)
+ fixup(hwif);
+
for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit];
@@ -874,10 +877,7 @@ static int hwif_init(ide_hwif_t *hwif);
int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
{
- probe_hwif(hwif);
-
- if (fixup)
- fixup(hwif);
+ probe_hwif(hwif, fixup);
if (!hwif_init(hwif)) {
printk(KERN_INFO "%s: failed to initialize IDE interface\n",
@@ -1025,7 +1025,7 @@ static int init_irq (ide_hwif_t *hwif)
BUG_ON(irqs_disabled());
BUG_ON(hwif == NULL);
- down(&ide_cfg_sem);
+ mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL;
#if MAX_HWIFS > 1
/*
@@ -1154,7 +1154,7 @@ static int init_irq (ide_hwif_t *hwif)
printk(" (%sed with %s)",
hwif->sharing_irq ? "shar" : "serializ", match->name);
printk("\n");
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
return 0;
out_unlink:
spin_lock_irq(&ide_lock);
@@ -1177,7 +1177,7 @@ out_unlink:
}
spin_unlock_irq(&ide_lock);
out_up:
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
return 1;
}
@@ -1404,7 +1404,7 @@ int ideprobe_init (void)
for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index])
- probe_hwif(&ide_hwifs[index]);
+ probe_hwif(&ide_hwifs[index], NULL);
for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index])
hwif_init(&ide_hwifs[index]);
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index ea94c9aa122..fc1d8ae6a80 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -156,7 +156,7 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int d
{
ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
while ((*p) && strcmp((*p)->name, name) < 0)
p = &((*p)->next);
if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
@@ -177,10 +177,10 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int d
if (auto_remove)
setting->auto_remove = 1;
*p = setting;
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return 0;
abort:
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
kfree(setting);
return -1;
}
@@ -224,7 +224,7 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name)
*
* Automatically remove all the driver specific settings for this
* drive. This function may not be called from IRQ context. The
- * caller must hold ide_setting_sem.
+ * caller must hold ide_setting_mtx.
*/
static void auto_remove_settings (ide_drive_t *drive)
@@ -269,7 +269,7 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
* @setting: drive setting
*
* Read a drive setting and return the value. The caller
- * must hold the ide_setting_sem when making this call.
+ * must hold the ide_setting_mtx when making this call.
*
* BUGS: the data return and error are the same return value
* so an error -EINVAL and true return of the same value cannot
@@ -306,7 +306,7 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
* @val: value
*
* Write a drive setting if it is possible. The caller
- * must hold the ide_setting_sem when making this call.
+ * must hold the ide_setting_mtx when making this call.
*
* BUGS: the data return and error are the same return value
* so an error -EINVAL and true return of the same value cannot
@@ -367,7 +367,7 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
* @drive: drive being configured
*
* Add the generic parts of the system settings to the /proc files.
- * The caller must not be holding the ide_setting_sem.
+ * The caller must not be holding the ide_setting_mtx.
*/
void ide_add_generic_settings (ide_drive_t *drive)
@@ -408,7 +408,7 @@ static int proc_ide_read_settings
proc_ide_settings_warn();
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
while(setting) {
@@ -428,7 +428,7 @@ static int proc_ide_read_settings
setting = setting->next;
}
len = out - page;
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
@@ -508,16 +508,16 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
++p;
}
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
setting = ide_find_setting_by_name(drive, name);
if (!setting)
{
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
goto parse_error;
}
if (for_real)
ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
} while (!for_real++);
free_page((unsigned long)buf);
@@ -705,7 +705,7 @@ EXPORT_SYMBOL(ide_proc_register_driver);
* Clean up the driver specific /proc files and IDE settings
* for a given drive.
*
- * Takes ide_setting_sem and ide_lock.
+ * Takes ide_setting_mtx and ide_lock.
* Caller must hold none of the locks.
*/
@@ -715,10 +715,10 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
ide_remove_proc_entries(drive->proc, driver->proc);
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
/*
- * ide_setting_sem protects the settings list
+ * ide_setting_mtx protects the settings list
* ide_lock protects the use of settings
*
* so we need to hold both, ide_settings_sem because we want to
@@ -726,11 +726,11 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
* a setting out that is being used.
*
* OTOH both ide_{read,write}_setting are only ever used under
- * ide_setting_sem.
+ * ide_setting_mtx.
*/
auto_remove_settings(drive);
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
EXPORT_SYMBOL(ide_proc_unregister_driver);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 30175c7688e..aa06dafb74a 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -238,7 +238,7 @@ EXPORT_SYMBOL(task_no_data_intr);
static u8 wait_drive_not_busy(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
- int retries = 100;
+ int retries;
u8 stat;
/*
@@ -246,10 +246,14 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
* This can take up to 10 usec, but we will wait max 1 ms
* (drive_cmd_intr() waits that long).
*/
- while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
- udelay(10);
+ for (retries = 0; retries < 100; retries++) {
+ if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT)
+ udelay(10);
+ else
+ break;
+ }
- if (!retries)
+ if (stat & BUSY_STAT)
printk(KERN_ERR "%s: drive still BUSY!\n", drive->name);
return stat;
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index c0864b1e922..e6cb8593b5b 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -102,66 +102,16 @@ static struct ide_timing ide_timing[] = {
#define EZ(v,unit) ((v)?ENOUGH(v,unit):0)
#define XFER_MODE 0xf0
-#define XFER_UDMA_133 0x48
-#define XFER_UDMA_100 0x44
-#define XFER_UDMA_66 0x42
-#define XFER_UDMA 0x40
#define XFER_MWDMA 0x20
-#define XFER_SWDMA 0x10
#define XFER_EPIO 0x01
#define XFER_PIO 0x00
-static short ide_find_best_mode(ide_drive_t *drive, int map)
+static short ide_find_best_pio_mode(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
short best = 0;
- if (!id)
- return XFER_PIO_SLOW;
-
- if ((map & XFER_UDMA) && (id->field_valid & 4)) { /* Want UDMA and UDMA bitmap valid */
-
- if ((map & XFER_UDMA_133) == XFER_UDMA_133)
- if ((best = (id->dma_ultra & 0x0040) ? XFER_UDMA_6 : 0)) return best;
-
- if ((map & XFER_UDMA_100) == XFER_UDMA_100)
- if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
-
- if ((map & XFER_UDMA_66) == XFER_UDMA_66)
- if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 :
- (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
-
- if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
- (id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
- (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : 0)) return best;
- }
-
- if ((map & XFER_MWDMA) && (id->field_valid & 2)) { /* Want MWDMA and drive has EIDE fields */
-
- if ((best = (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
- (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
- (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : 0)) return best;
- }
-
- if (map & XFER_SWDMA) { /* Want SWDMA */
-
- if (id->field_valid & 2) { /* EIDE SWDMA */
-
- if ((best = (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
- (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
- (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0)) return best;
- }
-
- if (id->capability & 1) { /* Pre-EIDE style SWDMA */
-
- if ((best = (id->tDMA == 2) ? XFER_SW_DMA_2 :
- (id->tDMA == 1) ? XFER_SW_DMA_1 :
- (id->tDMA == 0) ? XFER_SW_DMA_0 : 0)) return best;
- }
- }
-
-
- if ((map & XFER_EPIO) && (id->field_valid & 2)) { /* EIDE PIO modes */
+ if (id->field_valid & 2) { /* EIDE PIO modes */
if ((best = (drive->id->eide_pio_modes & 4) ? XFER_PIO_5 :
(drive->id->eide_pio_modes & 2) ? XFER_PIO_4 :
@@ -262,7 +212,7 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
*/
if ((speed & XFER_MODE) != XFER_PIO) {
- ide_timing_compute(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO), &p, T, UT);
+ ide_timing_compute(drive, ide_find_best_pio_mode(drive), &p, T, UT);
ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 6002713a20a..c948a5c17a5 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -169,7 +169,7 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
static int idebus_parameter; /* holds the "idebus=" parameter */
static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
-DECLARE_MUTEX(ide_cfg_sem);
+DEFINE_MUTEX(ide_cfg_mtx);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
@@ -460,6 +460,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->mwdma_mask = tmp_hwif->mwdma_mask;
hwif->swdma_mask = tmp_hwif->swdma_mask;
+ hwif->cbl = tmp_hwif->cbl;
+
hwif->chipset = tmp_hwif->chipset;
hwif->hold = tmp_hwif->hold;
@@ -496,8 +498,8 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->ide_dma_clear_irq = tmp_hwif->ide_dma_clear_irq;
hwif->dma_host_on = tmp_hwif->dma_host_on;
hwif->dma_host_off = tmp_hwif->dma_host_off;
- hwif->ide_dma_lostirq = tmp_hwif->ide_dma_lostirq;
- hwif->ide_dma_timeout = tmp_hwif->ide_dma_timeout;
+ hwif->dma_lost_irq = tmp_hwif->dma_lost_irq;
+ hwif->dma_timeout = tmp_hwif->dma_timeout;
hwif->OUTB = tmp_hwif->OUTB;
hwif->OUTBSYNC = tmp_hwif->OUTBSYNC;
@@ -533,7 +535,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
hwif->extra_base = tmp_hwif->extra_base;
hwif->extra_ports = tmp_hwif->extra_ports;
hwif->autodma = tmp_hwif->autodma;
- hwif->udma_four = tmp_hwif->udma_four;
hwif->hwif_data = tmp_hwif->hwif_data;
}
@@ -564,7 +565,7 @@ void ide_unregister(unsigned int index)
{
ide_drive_t *drive;
ide_hwif_t *hwif, *g;
- static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
+ static ide_hwif_t tmp_hwif; /* protected by ide_cfg_mtx */
ide_hwgroup_t *hwgroup;
int irq_count = 0, unit;
@@ -572,7 +573,7 @@ void ide_unregister(unsigned int index)
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
- down(&ide_cfg_sem);
+ mutex_lock(&ide_cfg_mtx);
spin_lock_irq(&ide_lock);
hwif = &ide_hwifs[index];
if (!hwif->present)
@@ -679,7 +680,7 @@ void ide_unregister(unsigned int index)
abort:
spin_unlock_irq(&ide_lock);
- up(&ide_cfg_sem);
+ mutex_unlock(&ide_cfg_mtx);
}
EXPORT_SYMBOL(ide_unregister);
@@ -817,9 +818,9 @@ EXPORT_SYMBOL(ide_register_hw);
* Locks for IDE setting functionality
*/
-DECLARE_MUTEX(ide_setting_sem);
+DEFINE_MUTEX(ide_setting_mtx);
-EXPORT_SYMBOL_GPL(ide_setting_sem);
+EXPORT_SYMBOL_GPL(ide_setting_mtx);
/**
* ide_spin_wait_hwgroup - wait for group
@@ -1013,6 +1014,7 @@ static int generic_ide_resume(struct device *dev)
struct request rq;
struct request_pm_state rqpm;
ide_task_t args;
+ int err;
/* Call ACPI _STM only once */
if (!(drive->dn % 2))
@@ -1029,7 +1031,16 @@ static int generic_ide_resume(struct device *dev)
rqpm.pm_step = ide_pm_state_start_resume;
rqpm.pm_state = PM_EVENT_ON;
- return ide_do_drive_cmd(drive, &rq, ide_head_wait);
+ err = ide_do_drive_cmd(drive, &rq, ide_head_wait);
+
+ if (err == 0 && dev->driver) {
+ ide_driver_t *drv = to_ide_driver(dev->driver);
+
+ if (drv->resume)
+ drv->resume(drive);
+ }
+
+ return err;
}
int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
@@ -1182,11 +1193,11 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
}
read_val:
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
err = *val;
spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
set_val:
@@ -1196,9 +1207,9 @@ set_val:
if (!capable(CAP_SYS_ADMIN))
err = -EACCES;
else {
- down(&ide_setting_sem);
+ mutex_lock(&ide_setting_mtx);
err = setfunc(drive, arg);
- up(&ide_setting_sem);
+ mutex_unlock(&ide_setting_mtx);
}
}
return err;
@@ -1538,7 +1549,11 @@ static int __init ide_setup(char *s)
goto bad_option;
case -7: /* ata66 */
#ifdef CONFIG_BLK_DEV_IDEPCI
- hwif->udma_four = 1;
+ /*
+ * Use ATA_CBL_PATA40_SHORT so drive side
+ * cable detection is also overriden.
+ */
+ hwif->cbl = ATA_CBL_PATA40_SHORT;
goto obsolete_option;
#else
goto bad_hwif;
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index 45ed03591cd..8f2db8dd35f 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -130,7 +130,7 @@ struct hd_i_struct {
#ifdef HD_TYPE
static struct hd_i_struct hd_info[] = { HD_TYPE };
-static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct)));
+static int NR_HD = ARRAY_SIZE(hd_info);
#else
static struct hd_i_struct hd_info[MAX_HD];
static int NR_HD;
@@ -623,7 +623,8 @@ repeat:
cyl = track / disk->head;
#ifdef DEBUG
printk("%s: %sing: CHS=%d/%d/%d, sectors=%d, buffer=%p\n",
- req->rq_disk->disk_name, (req->cmd == READ)?"read":"writ",
+ req->rq_disk->disk_name,
+ req_data_dir(req) == READ ? "read" : "writ",
cyl, head, sec, nsect, req->buffer);
#endif
if (blk_fs_request(req)) {
@@ -718,74 +719,25 @@ static int __init hd_init(void)
device_timer.function = hd_times_out;
blk_queue_hardsect_size(hd_queue, 512);
-#ifdef __i386__
if (!NR_HD) {
- extern struct drive_info drive_info;
- unsigned char *BIOS = (unsigned char *) &drive_info;
- unsigned long flags;
- int cmos_disks;
-
- for (drive=0 ; drive<2 ; drive++) {
- hd_info[drive].cyl = *(unsigned short *) BIOS;
- hd_info[drive].head = *(2+BIOS);
- hd_info[drive].wpcom = *(unsigned short *) (5+BIOS);
- hd_info[drive].ctl = *(8+BIOS);
- hd_info[drive].lzone = *(unsigned short *) (12+BIOS);
- hd_info[drive].sect = *(14+BIOS);
-#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp
- if (hd_info[drive].cyl && NR_HD == drive)
- NR_HD++;
-#endif
- BIOS += 16;
- }
-
- /*
- We query CMOS about hard disks : it could be that
- we have a SCSI/ESDI/etc controller that is BIOS
- compatible with ST-506, and thus showing up in our
- BIOS table, but not register compatible, and therefore
- not present in CMOS.
-
- Furthermore, we will assume that our ST-506 drives
- <if any> are the primary drives in the system, and
- the ones reflected as drive 1 or 2.
-
- The first drive is stored in the high nibble of CMOS
- byte 0x12, the second in the low nibble. This will be
- either a 4 bit drive type or 0xf indicating use byte 0x19
- for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.
-
- Needless to say, a non-zero value means we have
- an AT controller hard disk for that drive.
-
- Currently the rtc_lock is a bit academic since this
- driver is non-modular, but someday... ? Paul G.
- */
-
- spin_lock_irqsave(&rtc_lock, flags);
- cmos_disks = CMOS_READ(0x12);
- spin_unlock_irqrestore(&rtc_lock, flags);
-
- if (cmos_disks & 0xf0) {
- if (cmos_disks & 0x0f)
- NR_HD = 2;
- else
- NR_HD = 1;
- }
- }
-#endif /* __i386__ */
-#ifdef __arm__
- if (!NR_HD) {
- /* We don't know anything about the drive. This means
+ /*
+ * We don't know anything about the drive. This means
* that you *MUST* specify the drive parameters to the
* kernel yourself.
+ *
+ * If we were on an i386, we used to read this info from
+ * the BIOS or CMOS. This doesn't work all that well,
+ * since this assumes that this is a primary or secondary
+ * drive, and if we're using this legacy driver, it's
+ * probably an auxilliary controller added to recover
+ * legacy data off an ST-506 drive. Either way, it's
+ * definitely safest to have the user explicitly specify
+ * the information.
*/
printk("hd: no drives specified - use hd=cyl,head,sectors"
" on kernel command line\n");
- }
-#endif
- if (!NR_HD)
goto out;
+ }
for (drive=0 ; drive < NR_HD ; drive++) {
struct gendisk *disk = alloc_disk(64);
diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
index c211fc78345..b557c45a5a9 100644
--- a/drivers/ide/legacy/macide.c
+++ b/drivers/ide/legacy/macide.c
@@ -77,15 +77,6 @@ int macide_ack_intr(ide_hwif_t* hwif)
return 0;
}
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
-static void macide_mediabay_interrupt(int irq, void *dev_id)
-{
- int state = baboon->mb_status & 0x04;
-
- printk(KERN_INFO "macide: media bay %s detected\n", state? "removal":"insertion");
-}
-#endif
-
/*
* Probe for a Macintosh IDE interface
*/
@@ -128,11 +119,6 @@ void macide_init(void)
ide_drive_t *drive = &ide_hwifs[index].drives[0];
drive->capacity64 = drive->cyl*drive->head*drive->sect;
-#ifdef CONFIG_BLK_DEV_MAC_MEDIABAY
- request_irq(IRQ_BABOON_2, macide_mediabay_interrupt,
- IRQ_FLG_FAST, "mediabay",
- macide_mediabay_interrupt);
-#endif
}
break;
diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
index d1414a75b52..7783745dd16 100644
--- a/drivers/ide/legacy/qd65xx.c
+++ b/drivers/ide/legacy/qd65xx.c
@@ -258,8 +258,7 @@ static void qd6580_tune_drive (ide_drive_t *drive, u8 pio)
int recovery_time = 415; /* worst case values from the dos driver */
if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
- pio = ide_get_best_pio_mode(drive, pio, 255, &d);
- pio = min_t(u8, pio, 4);
+ pio = ide_get_best_pio_mode(drive, pio, 4, &d);
switch (pio) {
case 0: break;
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index ca95e990862..2e7013a2a7f 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -381,9 +381,7 @@ static int auide_dma_setup(ide_drive_t *drive)
static int auide_dma_check(ide_drive_t *drive)
{
- u8 speed;
-
-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+ u8 speed = ide_max_dma_mode(drive);
if( dbdma_init_done == 0 ){
auide_hwif.white_list = ide_in_drive_list(drive->id,
@@ -394,7 +392,6 @@ static int auide_dma_check(ide_drive_t *drive)
auide_ddma_init(&auide_hwif);
dbdma_init_done = 1;
}
-#endif
/* Is the drive in our DMA black list? */
@@ -409,8 +406,6 @@ static int auide_dma_check(ide_drive_t *drive)
else
drive->using_dma = 1;
- speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA);
-
if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
return 0;
@@ -456,10 +451,9 @@ static void auide_dma_off_quietly(ide_drive_t *drive)
drive->using_dma = 0;
}
-static int auide_dma_lostirq(ide_drive_t *drive)
+static void auide_dma_lost_irq(ide_drive_t *drive)
{
printk(KERN_ERR "%s: IRQ lost\n", drive->name);
- return 0;
}
static void auide_ddma_tx_callback(int irq, void *param)
@@ -489,16 +483,16 @@ static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 de
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA)
-static int auide_dma_timeout(ide_drive_t *drive)
+static void auide_dma_timeout(ide_drive_t *drive)
{
-// printk("%s\n", __FUNCTION__);
+ ide_hwif_t *hwif = HWIF(drive);
printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
- if (HWIF(drive)->ide_dma_test_irq(drive))
- return 0;
+ if (hwif->ide_dma_test_irq(drive))
+ return;
- return HWIF(drive)->ide_dma_end(drive);
+ hwif->ide_dma_end(drive);
}
@@ -721,7 +715,7 @@ static int au_ide_probe(struct device *dev)
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
hwif->dma_off_quietly = &auide_dma_off_quietly;
- hwif->ide_dma_timeout = &auide_dma_timeout;
+ hwif->dma_timeout = &auide_dma_timeout;
hwif->ide_dma_check = &auide_dma_check;
hwif->dma_exec_cmd = &auide_dma_exec_cmd;
@@ -731,7 +725,7 @@ static int au_ide_probe(struct device *dev)
hwif->ide_dma_test_irq = &auide_dma_test_irq;
hwif->dma_host_off = &auide_dma_host_off;
hwif->dma_host_on = &auide_dma_host_on;
- hwif->ide_dma_lostirq = &auide_dma_lostirq;
+ hwif->dma_lost_irq = &auide_dma_lost_irq;
hwif->ide_dma_on = &auide_dma_on;
hwif->autodma = 1;
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index b173bc66ce1..e5d09367627 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/aec62xx.c Version 0.21 Apr 21, 2007
+ * linux/drivers/ide/pci/aec62xx.c Version 0.24 May 24, 2007
*
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
@@ -140,25 +140,10 @@ static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed)
return(ide_config_drive_speed(drive, speed));
}
-static int aec62xx_tune_chipset (ide_drive_t *drive, u8 speed)
-{
- switch (HWIF(drive)->pci_dev->device) {
- case PCI_DEVICE_ID_ARTOP_ATP865:
- case PCI_DEVICE_ID_ARTOP_ATP865R:
- case PCI_DEVICE_ID_ARTOP_ATP860:
- case PCI_DEVICE_ID_ARTOP_ATP860R:
- return ((int) aec6260_tune_chipset(drive, speed));
- case PCI_DEVICE_ID_ARTOP_ATP850UF:
- return ((int) aec6210_tune_chipset(drive, speed));
- default:
- return -1;
- }
-}
-
static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio)
{
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
- (void) aec62xx_tune_chipset(drive, pio + XFER_PIO_0);
+ (void) HWIF(drive)->speedproc(drive, pio + XFER_PIO_0);
}
static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
@@ -172,12 +157,9 @@ static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
return -1;
}
-static int aec62xx_irq_timeout (ide_drive_t *drive)
+static void aec62xx_dma_lost_irq (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
-
- switch(dev->device) {
+ switch (HWIF(drive)->pci_dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP860:
case PCI_DEVICE_ID_ARTOP_ATP860R:
case PCI_DEVICE_ID_ARTOP_ATP865:
@@ -186,7 +168,6 @@ static int aec62xx_irq_timeout (ide_drive_t *drive)
default:
break;
}
- return 0;
}
static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const char *name)
@@ -224,64 +205,46 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch
static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *dev = hwif->pci_dev;
+ u8 reg54 = 0, mask = hwif->channel ? 0xf0 : 0x0f;
+ unsigned long flags;
- hwif->autodma = 0;
hwif->tuneproc = &aec62xx_tune_drive;
- hwif->speedproc = &aec62xx_tune_chipset;
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
- hwif->serialized = hwif->channel;
-
- if (hwif->mate)
- hwif->mate->serialized = hwif->serialized;
+ if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+ if(hwif->mate)
+ hwif->mate->serialized = hwif->serialized = 1;
+ hwif->speedproc = &aec6210_tune_chipset;
+ } else
+ hwif->speedproc = &aec6260_tune_chipset;
if (!hwif->dma_base) {
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
+ hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
return;
}
hwif->ultra_mask = hwif->cds->udma_mask;
-
- /* atp865 and atp865r */
- if (hwif->ultra_mask == 0x3f) {
- /* check bit 0x10 of DMA status register */
- if (inb(pci_resource_start(dev, 4) + 2) & 0x10)
- hwif->ultra_mask = 0x7f; /* udma0-6 */
- }
-
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate;
- hwif->ide_dma_lostirq = &aec62xx_irq_timeout;
-
- if (!noautodma)
- hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
-}
-
-static void __devinit init_dma_aec62xx(ide_hwif_t *hwif, unsigned long dmabase)
-{
- struct pci_dev *dev = hwif->pci_dev;
+ hwif->dma_lost_irq = &aec62xx_dma_lost_irq;
if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
- u8 reg54h = 0;
- unsigned long flags;
-
spin_lock_irqsave(&ide_lock, flags);
- pci_read_config_byte(dev, 0x54, &reg54h);
- pci_write_config_byte(dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
+ pci_read_config_byte (dev, 0x54, &reg54);
+ pci_write_config_byte(dev, 0x54, (reg54 & ~mask));
spin_unlock_irqrestore(&ide_lock, flags);
- } else {
- u8 ata66 = 0;
+ } else if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+ u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
+
pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
- if (!(hwif->udma_four))
- hwif->udma_four = (ata66&(hwif->channel?0x02:0x01))?0:1;
+
+ hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
- ide_setup_dma(hwif, dmabase, 8);
+ if (!noautodma)
+ hwif->autodma = 1;
+ hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d)
@@ -291,16 +254,12 @@ static int __devinit init_setup_aec62xx(struct pci_dev *dev, ide_pci_device_t *d
static int __devinit init_setup_aec6x80(struct pci_dev *dev, ide_pci_device_t *d)
{
- unsigned long bar4reg = pci_resource_start(dev, 4);
-
- if (inb(bar4reg+2) & 0x10) {
- strcpy(d->name, "AEC6880");
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
- strcpy(d->name, "AEC6880R");
- } else {
- strcpy(d->name, "AEC6280");
- if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)
- strcpy(d->name, "AEC6280R");
+ unsigned long dma_base = pci_resource_start(dev, 4);
+
+ if (inb(dma_base + 2) & 0x10) {
+ d->name = (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) ?
+ "AEC6880R" : "AEC6880";
+ d->udma_mask = 0x7f; /* udma0-6 */
}
return ide_setup_pci_device(dev, d);
@@ -312,7 +271,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -323,7 +281,6 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = NOAUTODMA,
.bootable = OFF_BOARD,
@@ -333,28 +290,25 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
.init_setup = init_setup_aec62xx,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
.bootable = NEVER_BOARD,
.udma_mask = 0x1f, /* udma0-4 */
},{ /* 3 */
- .name = "AEC6X80",
+ .name = "AEC6280",
.init_setup = init_setup_aec6x80,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.bootable = OFF_BOARD,
.udma_mask = 0x3f, /* udma0-5 */
},{ /* 4 */
- .name = "AEC6X80R",
+ .name = "AEC6280R",
.init_setup = init_setup_aec6x80,
.init_chipset = init_chipset_aec62xx,
.init_hwif = init_hwif_aec62xx,
- .init_dma = init_dma_aec62xx,
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
@@ -370,13 +324,16 @@ static ide_pci_device_t aec62xx_chipsets[] __devinitdata = {
*
* Called when the PCI registration layer (or the IDE initialization)
* finds a device matching our IDE device tables.
+ *
+ * NOTE: since we're going to modify the 'name' field for AEC-6[26]80[R]
+ * chips, pass a local copy of 'struct pci_device_id' down the call chain.
*/
static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
- ide_pci_device_t *d = &aec62xx_chipsets[id->driver_data];
+ ide_pci_device_t d = aec62xx_chipsets[id->driver_data];
- return d->init_setup(dev, d);
+ return d.init_setup(dev, &d);
}
static struct pci_device_id aec62xx_pci_tbl[] = {
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 27525ec2e19..ba0fb92b041 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/alim15x3.c Version 0.21 2007/02/03
+ * linux/drivers/ide/pci/alim15x3.c Version 0.25 Jun 9 2007
*
* Copyright (C) 1998-2000 Michel Aubry, Maintainer
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
@@ -10,6 +10,7 @@
* Copyright (C) 2002 Alan Cox <alan@redhat.com>
* ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
*
* (U)DMA capable version of ali 1533/1543(C), 1535(D)
*
@@ -36,6 +37,7 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
+#include <linux/dmi.h>
#include <asm/io.h>
@@ -506,7 +508,7 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
u8 tmpbyte;
struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0));
- pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
+ m5229_revision = dev->revision;
isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
@@ -583,6 +585,35 @@ out:
return 0;
}
+/*
+ * Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+ {
+ .ident = "HP Pavilion N5430",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"),
+ },
+ },
+ { }
+};
+
+static int ali_cable_override(struct pci_dev *pdev)
+{
+ /* Fujitsu P2000 */
+ if (pdev->subsystem_vendor == 0x10CF &&
+ pdev->subsystem_device == 0x10AF)
+ return 1;
+
+ /* Systems by DMI */
+ if (dmi_check_system(cable_dmi_table))
+ return 1;
+
+ return 0;
+}
+
/**
* ata66_ali15x3 - check for UDMA 66 support
* @hwif: IDE interface
@@ -594,37 +625,31 @@ out:
* FIXME: frobs bits that are not defined on newer ALi devicea
*/
-static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
+static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- unsigned int ata66 = 0;
- u8 cable_80_pin[2] = { 0, 0 };
-
unsigned long flags;
- u8 tmpbyte;
+ u8 cbl = ATA_CBL_PATA40, tmpbyte;
local_irq_save(flags);
if (m5229_revision >= 0xC2) {
/*
- * Ultra66 cable detection (from Host View)
- * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
- */
- pci_read_config_byte(dev, 0x4a, &tmpbyte);
- /*
- * 0x4a, bit0 is 0 => primary channel
- * has 80-pin (from host view)
- */
- if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1;
- /*
- * 0x4a, bit1 is 0 => secondary channel
- * has 80-pin (from host view)
- */
- if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1;
- /*
- * Allow ata66 if cable of current channel has 80 pins
+ * m5229 80-pin cable detection (from Host View)
+ *
+ * 0x4a bit0 is 0 => primary channel has 80-pin
+ * 0x4a bit1 is 0 => secondary channel has 80-pin
+ *
+ * Certain laptops use short but suitable cables
+ * and don't implement the detect logic.
*/
- ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
+ if (ali_cable_override(dev))
+ cbl = ATA_CBL_PATA40_SHORT;
+ else {
+ pci_read_config_byte(dev, 0x4a, &tmpbyte);
+ if ((tmpbyte & (1 << hwif->channel)) == 0)
+ cbl = ATA_CBL_PATA80;
+ }
} else {
/*
* check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
@@ -657,7 +682,7 @@ static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
local_irq_restore(flags);
- return(ata66);
+ return cbl;
}
/**
@@ -708,8 +733,9 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
hwif->dma_setup = &ali15x3_dma_setup;
if (!noautodma)
hwif->autodma = 1;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_ali15x3(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_ali15x3(hwif);
}
hwif->drives[0].autodma = hwif->autodma;
hwif->drives[1].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index becb1a5648b..8d30b99a54d 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -1,10 +1,11 @@
/*
- * Version 2.13
+ * Version 2.20
*
* AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
* IDE driver for Linux.
*
* Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
*
* Based on the work of:
* Andre Hedrick
@@ -37,11 +38,6 @@
#define AMD_ADDRESS_SETUP (0x0c + amd_config->base)
#define AMD_UDMA_TIMING (0x10 + amd_config->base)
-#define AMD_UDMA 0x07
-#define AMD_UDMA_33 0x01
-#define AMD_UDMA_66 0x02
-#define AMD_UDMA_100 0x03
-#define AMD_UDMA_133 0x04
#define AMD_CHECK_SWDMA 0x08
#define AMD_BAD_SWDMA 0x10
#define AMD_BAD_FIFO 0x20
@@ -53,30 +49,33 @@
static struct amd_ide_chip {
unsigned short id;
- unsigned long base;
- unsigned char flags;
+ u8 base;
+ u8 udma_mask;
+ u8 flags;
} amd_ide_chips[] = {
- { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, AMD_UDMA_33 | AMD_BAD_SWDMA },
- { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, AMD_UDMA_66 | AMD_CHECK_SWDMA },
- { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, AMD_UDMA_100 | AMD_BAD_FIFO },
- { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, AMD_UDMA_100 },
- { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, AMD_UDMA_133 | AMD_CHECK_SERENADE },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, AMD_UDMA_100 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, AMD_UDMA_133 },
- { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 },
+ { PCI_DEVICE_ID_AMD_COBRA_7401, 0x40, ATA_UDMA2, AMD_BAD_SWDMA },
+ { PCI_DEVICE_ID_AMD_VIPER_7409, 0x40, ATA_UDMA4, AMD_CHECK_SWDMA },
+ { PCI_DEVICE_ID_AMD_VIPER_7411, 0x40, ATA_UDMA5, AMD_BAD_FIFO },
+ { PCI_DEVICE_ID_AMD_OPUS_7441, 0x40, ATA_UDMA5, },
+ { PCI_DEVICE_ID_AMD_8111_IDE, 0x40, ATA_UDMA6, AMD_CHECK_SERENADE },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_IDE, 0x50, ATA_UDMA5, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, },
+ { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, ATA_UDMA5, },
{ 0 }
};
@@ -85,7 +84,7 @@ static ide_pci_device_t *amd_chipset;
static unsigned int amd_80w;
static unsigned int amd_clock;
-static char *amd_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
/*
@@ -124,9 +123,8 @@ static int amd74xx_get_info(char *buffer, char **addr, off_t offset, int count)
amd_print("Driver Version: 2.13");
amd_print("South Bridge: %s", pci_name(bmide_dev));
- pci_read_config_byte(dev, PCI_REVISION_ID, &t);
- amd_print("Revision: IDE %#x", t);
- amd_print("Highest DMA rate: %s", amd_dma[amd_config->flags & AMD_UDMA]);
+ amd_print("Revision: IDE %#x", dev->revision);
+ amd_print("Highest DMA rate: UDMA%s", amd_dma[fls(amd_config->udma_mask) - 1]);
amd_print("BM-DMA base: %#lx", amd_base);
amd_print("PCI clock: %d.%dMHz", amd_clock / 1000, amd_clock / 100 % 10);
@@ -219,12 +217,12 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
- switch (amd_config->flags & AMD_UDMA) {
- case AMD_UDMA_33: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
- case AMD_UDMA_66: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
- case AMD_UDMA_100: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
- case AMD_UDMA_133: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
- default: return;
+ switch (amd_config->udma_mask) {
+ case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+ case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
+ case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
+ case ATA_UDMA6: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 15)]) : 0x03; break;
+ default: return;
}
pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
@@ -242,13 +240,11 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed)
struct ide_timing t, p;
int T, UT;
- if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
- if (ide_config_drive_speed(drive, speed))
- printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n",
- drive->dn >> 1, drive->dn & 1);
+ if (speed != XFER_PIO_SLOW)
+ ide_config_drive_speed(drive, speed);
T = 1000000000 / amd_clock;
- UT = T / min_t(int, max_t(int, amd_config->flags & AMD_UDMA, 1), 2);
+ UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
ide_timing_compute(drive, speed, &t, T, UT);
@@ -277,29 +273,19 @@ static int amd_set_drive(ide_drive_t *drive, u8 speed)
static void amd74xx_tune_drive(ide_drive_t *drive, u8 pio)
{
if (pio == 255) {
- amd_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+ amd_set_drive(drive, ide_find_best_pio_mode(drive));
return;
}
amd_set_drive(drive, XFER_PIO_0 + min_t(byte, pio, 5));
}
-/*
- * amd74xx_dmaproc() is a callback from upper layers that can do
- * a lot, but we use it for DMA/PIO tuning only, delegating everything
- * else to the default ide_dmaproc().
- */
-
static int amd74xx_ide_dma_check(ide_drive_t *drive)
{
- int w80 = HWIF(drive)->udma_four;
+ u8 speed = ide_max_dma_mode(drive);
- u8 speed = ide_find_best_mode(drive,
- XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA |
- ((amd_config->flags & AMD_BAD_SWDMA) ? 0 : XFER_SWDMA) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_66 ? XFER_UDMA_66 : 0) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_100 ? XFER_UDMA_100 : 0) |
- (w80 && (amd_config->flags & AMD_UDMA) >= AMD_UDMA_133 ? XFER_UDMA_133 : 0));
+ if (speed == 0)
+ speed = ide_find_best_pio_mode(drive);
amd_set_drive(drive, speed);
@@ -325,8 +311,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
*/
if (amd_config->flags & AMD_CHECK_SWDMA) {
- pci_read_config_byte(dev, PCI_REVISION_ID, &t);
- if (t <= 7)
+ if (dev->revision <= 7)
amd_config->flags |= AMD_BAD_SWDMA;
}
@@ -334,10 +319,10 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
* Check 80-wire cable presence.
*/
- switch (amd_config->flags & AMD_UDMA) {
+ switch (amd_config->udma_mask) {
- case AMD_UDMA_133:
- case AMD_UDMA_100:
+ case ATA_UDMA6:
+ case ATA_UDMA5:
pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
@@ -349,7 +334,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
}
break;
- case AMD_UDMA_66:
+ case ATA_UDMA4:
/* no host side cable detection */
amd_80w = 0x03;
break;
@@ -370,7 +355,7 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
if ((amd_config->flags & AMD_CHECK_SERENADE) &&
dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
- amd_config->flags = AMD_UDMA_100;
+ amd_config->udma_mask = ATA_UDMA5;
/*
* Determine the system bus clock.
@@ -395,8 +380,9 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
*/
pci_read_config_byte(dev, PCI_REVISION_ID, &t);
- printk(KERN_INFO "%s: %s (rev %02x) %s controller\n",
- amd_chipset->name, pci_name(dev), t, amd_dma[amd_config->flags & AMD_UDMA]);
+ printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
+ amd_chipset->name, pci_name(dev), dev->revision,
+ amd_dma[fls(amd_config->udma_mask) - 1]);
/*
* Register /proc/ide/amd74xx entry
@@ -437,12 +423,19 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
return;
hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
- hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
- if (!hwif->udma_four)
- hwif->udma_four = (amd_80w >> hwif->channel) & 1;
+ hwif->ultra_mask = amd_config->udma_mask;
+ hwif->mwdma_mask = 0x07;
+ if ((amd_config->flags & AMD_BAD_SWDMA) == 0)
+ hwif->swdma_mask = 0x07;
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+ if ((amd_80w >> hwif->channel) & 1)
+ hwif->cbl = ATA_CBL_PATA80;
+ else
+ hwif->cbl = ATA_CBL_PATA40;
+ }
+
hwif->ide_dma_check = &amd74xx_ide_dma_check;
if (!noautodma)
hwif->autodma = 1;
@@ -494,7 +487,9 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"),
- /* 20 */ DECLARE_AMD_DEV("AMD5536"),
+ /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"),
+ /* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"),
+ /* 22 */ DECLARE_AMD_DEV("AMD5536"),
};
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -534,7 +529,9 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 },
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 8ab33faf6f7..2761510309b 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -264,10 +264,11 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+
if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
- hwif->udma_four = 1;
+ hwif->cbl = ATA_CBL_PATA80;
else
- hwif->udma_four = 0;
+ hwif->cbl = ATA_CBL_PATA40;
hwif->dma_host_on = &atiixp_dma_host_on;
hwif->dma_host_off = &atiixp_dma_host_off;
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 7c57dc696f5..1e89dd6e5bb 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/cmd64x.c Version 1.47 Mar 19, 2007
+ * linux/drivers/ide/pci/cmd64x.c Version 1.50 May 10, 2007
*
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported
@@ -52,9 +52,6 @@
#define ARTTIM23_DIS_RA2 0x04
#define ARTTIM23_DIS_RA3 0x08
#define ARTTIM23_INTR_CH1 0x10
-#define ARTTIM2 0x57
-#define ARTTIM3 0x57
-#define DRWTIM23 0x58
#define DRWTIM2 0x58
#define BRST 0x59
#define DRWTIM3 0x5b
@@ -91,7 +88,6 @@ static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
u8 reg72 = 0, reg73 = 0; /* primary */
u8 reg7a = 0, reg7b = 0; /* secondary */
u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0; /* extra */
- u8 rev = 0;
p += sprintf(p, "\nController: %d\n", index);
p += sprintf(p, "PCI-%x Chipset.\n", dev->device);
@@ -106,9 +102,8 @@ static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
(void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
/* PCI0643/6 originally didn't have the primary channel enable bit */
- (void) pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
if ((dev->device == PCI_DEVICE_ID_CMD_643) ||
- (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 3))
+ (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 3))
reg51 |= CNTRL_ENA_1ST;
p += sprintf(p, "---------------- Primary Channel "
@@ -469,71 +464,43 @@ static int cmd646_1_ide_dma_end (ide_drive_t *drive)
static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const char *name)
{
- u32 class_rev = 0;
u8 mrdmode = 0;
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
+ if (dev->device == PCI_DEVICE_ID_CMD_646) {
+ u8 rev = 0;
- switch(dev->device) {
- case PCI_DEVICE_ID_CMD_643:
- break;
- case PCI_DEVICE_ID_CMD_646:
- printk(KERN_INFO "%s: chipset revision 0x%02X, ", name, class_rev);
- switch(class_rev) {
- case 0x07:
- case 0x05:
- printk("UltraDMA Capable");
- break;
- case 0x03:
- printk("MultiWord DMA Force Limited");
- break;
- case 0x01:
- default:
- printk("MultiWord DMA Limited, IRQ workaround enabled");
- break;
- }
- printk("\n");
- break;
- case PCI_DEVICE_ID_CMD_648:
- case PCI_DEVICE_ID_CMD_649:
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+
+ switch (rev) {
+ case 0x07:
+ case 0x05:
+ printk("%s: UltraDMA capable", name);
break;
+ case 0x03:
default:
+ printk("%s: MultiWord DMA force limited", name);
+ break;
+ case 0x01:
+ printk("%s: MultiWord DMA limited, "
+ "IRQ workaround enabled\n", name);
break;
+ }
}
/* Set a good latency timer and cache line size value. */
(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
/* FIXME: pci_set_master() to ensure a good latency timer value */
- /* Setup interrupts. */
- (void) pci_read_config_byte(dev, MRDMODE, &mrdmode);
- mrdmode &= ~(0x30);
- (void) pci_write_config_byte(dev, MRDMODE, mrdmode);
-
- /* Use MEMORY READ LINE for reads.
- * NOTE: Although not mentioned in the PCI0646U specs,
- * these bits are write only and won't be read
- * back as set or not. The PCI0646U2 specs clarify
- * this point.
+ /*
+ * Enable interrupts, select MEMORY READ LINE for reads.
+ *
+ * NOTE: although not mentioned in the PCI0646U specs,
+ * bits 0-1 are write only and won't be read back as
+ * set or not -- PCI0646U2 specs clarify this point.
*/
- (void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02);
-
- /* Set reasonable active/recovery/address-setup values. */
- (void) pci_write_config_byte(dev, ARTTIM0, 0x40);
- (void) pci_write_config_byte(dev, DRWTIM0, 0x3f);
- (void) pci_write_config_byte(dev, ARTTIM1, 0x40);
- (void) pci_write_config_byte(dev, DRWTIM1, 0x3f);
-#ifdef __i386__
- (void) pci_write_config_byte(dev, ARTTIM23, 0x1c);
-#else
- (void) pci_write_config_byte(dev, ARTTIM23, 0x5c);
-#endif
- (void) pci_write_config_byte(dev, DRWTIM23, 0x3f);
- (void) pci_write_config_byte(dev, DRWTIM3, 0x3f);
-#ifdef CONFIG_PPC
- (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);
-#endif /* CONFIG_PPC */
+ (void) pci_read_config_byte (dev, MRDMODE, &mrdmode);
+ mrdmode &= ~0x30;
+ (void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
@@ -548,29 +515,27 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
return 0;
}
-static unsigned int __devinit ata66_cmd64x(ide_hwif_t *hwif)
+static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
{
- u8 ata66 = 0, mask = (hwif->channel) ? 0x02 : 0x01;
+ struct pci_dev *dev = hwif->pci_dev;
+ u8 bmidecsr = 0, mask = hwif->channel ? 0x02 : 0x01;
- switch(hwif->pci_dev->device) {
- case PCI_DEVICE_ID_CMD_643:
- case PCI_DEVICE_ID_CMD_646:
- return ata66;
- default:
- break;
+ switch (dev->device) {
+ case PCI_DEVICE_ID_CMD_648:
+ case PCI_DEVICE_ID_CMD_649:
+ pci_read_config_byte(dev, BMIDECSR, &bmidecsr);
+ return (bmidecsr & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ default:
+ return ATA_CBL_PATA40;
}
- pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);
- return (ata66 & mask) ? 1 : 0;
}
static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
- unsigned int class_rev;
+ u8 rev = 0;
- hwif->autodma = 0;
- pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
- class_rev &= 0xff;
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
hwif->tuneproc = &cmd64x_tune_drive;
hwif->speedproc = &cmd64x_tune_chipset;
@@ -580,8 +545,8 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
if (!hwif->dma_base)
return;
- hwif->atapi_dma = 1;
-
+ hwif->atapi_dma = 1;
+ hwif->mwdma_mask = 0x07;
hwif->ultra_mask = hwif->cds->udma_mask;
/*
@@ -596,16 +561,15 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
*
* So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
*/
- if (dev->device == PCI_DEVICE_ID_CMD_646 && class_rev < 5)
+ if (dev->device == PCI_DEVICE_ID_CMD_646 && rev < 5)
hwif->ultra_mask = 0x00;
- hwif->mwdma_mask = 0x07;
-
hwif->ide_dma_check = &cmd64x_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_cmd64x(hwif);
- switch(dev->device) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_cmd64x(hwif);
+
+ switch (dev->device) {
case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_649:
alt_irq_bits:
@@ -614,10 +578,10 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
break;
case PCI_DEVICE_ID_CMD_646:
hwif->chipset = ide_cmd646;
- if (class_rev == 0x01) {
+ if (rev == 0x01) {
hwif->ide_dma_end = &cmd646_1_ide_dma_end;
break;
- } else if (class_rev >= 0x03)
+ } else if (rev >= 0x03)
goto alt_irq_bits;
/* fall thru */
default:
@@ -626,11 +590,9 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
break;
}
-
if (!noautodma)
hwif->autodma = 1;
- hwif->drives[0].autodma = hwif->autodma;
- hwif->drives[1].autodma = hwif->autodma;
+ hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma;
}
static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
@@ -640,14 +602,11 @@ static int __devinit init_setup_cmd64x(struct pci_dev *dev, ide_pci_device_t *d)
static int __devinit init_setup_cmd646(struct pci_dev *dev, ide_pci_device_t *d)
{
- u8 rev = 0;
-
/*
* The original PCI0646 didn't have the primary channel enable bit,
* it appeared starting with PCI0646U (i.e. revision ID 3).
*/
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
- if (rev < 3)
+ if (dev->revision < 3)
d->enablebits[0].reg = 0;
return ide_setup_pci_device(dev, d);
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index 1eec1f308d1..b5c00d15a70 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -236,7 +236,7 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
*/
pci_set_master(cs5530_0);
- pci_set_mwi(cs5530_0);
+ pci_try_set_mwi(cs5530_0);
/*
* Set PCI CacheLineSize to 16-bytes:
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 41925c47ef0..10f61f38243 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -187,7 +187,8 @@ static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
/* if a 80 wire cable was detected */
pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
- return (bit & 1);
+
+ return (bit & 1) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/****
@@ -212,8 +213,7 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
hwif->ultra_mask = 0x1F;
hwif->mwdma_mask = 0x07;
-
- hwif->udma_four = cs5535_cable_detect(hwif->pci_dev);
+ hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index f2c5a141ca1..0d51a11e81d 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -198,32 +198,41 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
ide_pci_device_t *d = &generic_chipsets[id->driver_data];
- u16 command;
int ret = -ENODEV;
/* Don't use the generic entry unless instructed to do so */
if (id->driver_data == 0 && ide_generic_all == 0)
goto out;
- if (dev->vendor == PCI_VENDOR_ID_UMC &&
- dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
- (!(PCI_FUNC(dev->devfn) & 1)))
- goto out; /* UM8886A/BF pair */
-
- if (dev->vendor == PCI_VENDOR_ID_OPTI &&
- dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
- (!(PCI_FUNC(dev->devfn) & 1)))
- goto out;
-
- if (dev->vendor == PCI_VENDOR_ID_JMICRON) {
- if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && PCI_FUNC(dev->devfn) != 1)
+ switch (dev->vendor) {
+ case PCI_VENDOR_ID_UMC:
+ if (dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
+ !(PCI_FUNC(dev->devfn) & 1))
+ goto out; /* UM8886A/BF pair */
+ break;
+ case PCI_VENDOR_ID_OPTI:
+ if (dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
+ !(PCI_FUNC(dev->devfn) & 1))
+ goto out;
+ break;
+ case PCI_VENDOR_ID_JMICRON:
+ if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 &&
+ PCI_FUNC(dev->devfn) != 1)
+ goto out;
+ break;
+ case PCI_VENDOR_ID_NS:
+ if (dev->device == PCI_DEVICE_ID_NS_87410 &&
+ (dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
goto out;
+ break;
}
if (dev->vendor != PCI_VENDOR_ID_JMICRON) {
+ u16 command;
pci_read_config_word(dev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_IO)) {
- printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name);
+ printk(KERN_INFO "Skipping disabled %s IDE "
+ "controller.\n", d->name);
goto out;
}
}
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index fcbc5605b38..e9b07a97c34 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/hpt366.c Version 1.03 May 4, 2007
+ * linux/drivers/ide/pci/hpt366.c Version 1.10 Jun 29, 2007
*
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
@@ -77,7 +77,7 @@
* since they may tamper with its fields
* - prefix the driver startup messages with the real chip name
* - claim the extra 240 bytes of I/O space for all chips
- * - optimize the rate masking/filtering and the drive list lookup code
+ * - optimize the UltraDMA filtering and the drive list lookup code
* - use pci_get_slot() to get to the function 1 of HPT36x/374
* - cache offset of the channel's misc. control registers (MCRs) being used
* throughout the driver
@@ -99,18 +99,20 @@
* stop duplicating it for each channel by storing the pointer in the pci_dev
* structure: first, at the init_setup stage, point it to a static "template"
* with only the chip type and its specific base DPLL frequency, the highest
- * supported DMA mode, and the chip settings table pointer filled, then, at
- * the init_chipset stage, allocate per-chip instance and fill it with the
- * rest of the necessary information
+ * UltraDMA mode, and the chip settings table pointer filled, then, at the
+ * init_chipset stage, allocate per-chip instance and fill it with the rest
+ * of the necessary information
* - get rid of the constant thresholds in the HPT37x PCI clock detection code,
* switch to calculating PCI clock frequency based on the chip's base DPLL
* frequency
* - switch to using the DPLL clock and enable UltraATA/133 mode by default on
- * anything newer than HPT370/A
+ * anything newer than HPT370/A (except HPT374 that is not capable of this
+ * mode according to the manual)
* - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
* also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
* unify HPT36x/37x timing setup code and the speedproc handlers by joining
* the register setting lists into the table indexed by the clock selected
+ * - set the correct hwif->ultra_mask for each individual chip
* Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
*/
@@ -181,6 +183,7 @@ static const char *bad_ata66_4[] = {
"IC35L040AVER07-0",
"IC35L060AVER07-0",
"WDC AC310200R",
+ "MAXTOR STM3320620A",
NULL
};
@@ -365,7 +368,6 @@ static u32 sixty_six_base_hpt37x[] = {
};
#define HPT366_DEBUG_DRIVE_INFO 0
-#define HPT374_ALLOW_ATA133_6 1
#define HPT371_ALLOW_ATA133_6 1
#define HPT302_ALLOW_ATA133_6 1
#define HPT372_ALLOW_ATA133_6 1
@@ -390,7 +392,7 @@ enum ata_clock {
struct hpt_info {
u8 chip_type; /* Chip type */
- u8 max_mode; /* Speeds allowed */
+ u8 max_ultra; /* Max. UltraDMA mode allowed */
u8 dpll_clk; /* DPLL clock in MHz */
u8 pci_clk; /* PCI clock in MHz */
u32 **settings; /* Chipset settings table */
@@ -429,77 +431,77 @@ static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
static struct hpt_info hpt36x __devinitdata = {
.chip_type = HPT36x,
- .max_mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1,
+ .max_ultra = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? 4 : 3) : 2,
.dpll_clk = 0, /* no DPLL */
.settings = hpt36x_settings
};
static struct hpt_info hpt370 __devinitdata = {
.chip_type = HPT370,
- .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2,
+ .max_ultra = HPT370_ALLOW_ATA100_5 ? 5 : 4,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt370a __devinitdata = {
.chip_type = HPT370A,
- .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2,
+ .max_ultra = HPT370_ALLOW_ATA100_5 ? 5 : 4,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt374 __devinitdata = {
.chip_type = HPT374,
- .max_mode = HPT374_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = 5,
.dpll_clk = 48,
.settings = hpt37x_settings
};
static struct hpt_info hpt372 __devinitdata = {
.chip_type = HPT372,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 55,
.settings = hpt37x_settings
};
static struct hpt_info hpt372a __devinitdata = {
.chip_type = HPT372A,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt302 __devinitdata = {
.chip_type = HPT302,
- .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt371 __devinitdata = {
.chip_type = HPT371,
- .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT371_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 66,
.settings = hpt37x_settings
};
static struct hpt_info hpt372n __devinitdata = {
.chip_type = HPT372N,
- .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT372_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
static struct hpt_info hpt302n __devinitdata = {
.chip_type = HPT302N,
- .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT302_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
static struct hpt_info hpt371n __devinitdata = {
.chip_type = HPT371N,
- .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3,
+ .max_ultra = HPT371_ALLOW_ATA133_6 ? 6 : 5,
.dpll_clk = 77,
.settings = hpt37x_settings
};
@@ -522,53 +524,38 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list)
static u8 hpt3xx_udma_filter(ide_drive_t *drive)
{
struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev);
- u8 chip_type = info->chip_type;
- u8 mode = info->max_mode;
u8 mask;
- switch (mode) {
- case 0x04:
- mask = 0x7f;
- break;
- case 0x03:
+ switch (info->chip_type) {
+ case HPT370A:
+ if (!HPT370_ALLOW_ATA100_5 ||
+ check_in_drive_list(drive, bad_ata100_5))
+ return 0x1f;
+ else
+ return 0x3f;
+ case HPT370:
+ if (!HPT370_ALLOW_ATA100_5 ||
+ check_in_drive_list(drive, bad_ata100_5))
+ mask = 0x1f;
+ else
mask = 0x3f;
- if (chip_type >= HPT374)
- break;
- if (!check_in_drive_list(drive, bad_ata100_5))
- goto check_bad_ata33;
- /* fall thru */
- case 0x02:
+ break;
+ case HPT36x:
+ if (!HPT366_ALLOW_ATA66_4 ||
+ check_in_drive_list(drive, bad_ata66_4))
+ mask = 0x0f;
+ else
mask = 0x1f;
- /*
- * CHECK ME, Does this need to be changed to HPT374 ??
- */
- if (chip_type >= HPT370)
- goto check_bad_ata33;
- if (HPT366_ALLOW_ATA66_4 &&
- !check_in_drive_list(drive, bad_ata66_4))
- goto check_bad_ata33;
-
- mask = 0x0f;
- if (HPT366_ALLOW_ATA66_3 &&
- !check_in_drive_list(drive, bad_ata66_3))
- goto check_bad_ata33;
- /* fall thru */
- case 0x01:
+ if (!HPT366_ALLOW_ATA66_3 ||
+ check_in_drive_list(drive, bad_ata66_3))
mask = 0x07;
-
- check_bad_ata33:
- if (chip_type >= HPT370A)
- break;
- if (!check_in_drive_list(drive, bad_ata33))
- break;
- /* fall thru */
- case 0x00:
- default:
- mask = 0x00;
- break;
+ break;
+ default:
+ return 0x7f;
}
- return mask;
+
+ return check_in_drive_list(drive, bad_ata33) ? 0x00 : mask;
}
static u32 get_speed_setting(u8 speed, struct hpt_info *info)
@@ -736,7 +723,7 @@ static int hpt366_config_drive_xfer_rate(ide_drive_t *drive)
* This is specific to the HPT366 UDMA chipset
* by HighPoint|Triones Technologies, Inc.
*/
-static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
+static void hpt366_dma_lost_irq(ide_drive_t *drive)
{
struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
@@ -748,7 +735,7 @@ static int hpt366_ide_dma_lostirq(ide_drive_t *drive)
drive->name, __FUNCTION__, mcr1, mcr3, scr1);
if (scr1 & 0x10)
pci_write_config_byte(dev, 0x5a, scr1 & ~0x10);
- return __ide_dma_lostirq(drive);
+ ide_dma_lost_irq(drive);
}
static void hpt370_clear_engine(ide_drive_t *drive)
@@ -798,10 +785,10 @@ static int hpt370_ide_dma_end(ide_drive_t *drive)
return __ide_dma_end(drive);
}
-static int hpt370_ide_dma_timeout(ide_drive_t *drive)
+static void hpt370_dma_timeout(ide_drive_t *drive)
{
hpt370_irq_timeout(drive);
- return __ide_dma_timeout(drive);
+ ide_dma_timeout(drive);
}
/* returns 1 if DMA IRQ issued, 0 otherwise */
@@ -1149,7 +1136,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
* Select 66 MHz DPLL clock only if UltraATA/133 mode is
* supported/enabled, use 50 MHz DPLL clock otherwise...
*/
- if (info->max_mode == 0x04) {
+ if (info->max_ultra == 6) {
dpll_clk = 66;
clock = ATA_CLOCK_66MHZ;
} else if (dpll_clk) { /* HPT36x chips don't have DPLL */
@@ -1242,7 +1229,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
struct pci_dev *dev = hwif->pci_dev;
struct hpt_info *info = pci_get_drvdata(dev);
int serialize = HPT_SERIALIZE_IO;
- u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02;
+ u8 scr1 = 0, ata66 = hwif->channel ? 0x01 : 0x02;
u8 chip_type = info->chip_type;
u8 new_mcr, old_mcr = 0;
@@ -1255,7 +1242,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
hwif->intrproc = &hpt3xx_intrproc;
hwif->maskproc = &hpt3xx_maskproc;
hwif->busproc = &hpt3xx_busproc;
- hwif->udma_filter = &hpt3xx_udma_filter;
+
+ if (chip_type <= HPT370A)
+ hwif->udma_filter = &hpt3xx_udma_filter;
/*
* HPT3xxN chips have some complications:
@@ -1304,7 +1293,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
return;
}
- hwif->ultra_mask = 0x7f;
+ hwif->ultra_mask = hwif->cds->udma_mask;
hwif->mwdma_mask = 0x07;
/*
@@ -1341,8 +1330,8 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
} else
pci_read_config_byte (dev, 0x5a, &scr1);
- if (!hwif->udma_four)
- hwif->udma_four = (scr1 & ata66) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
@@ -1352,9 +1341,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
} else if (chip_type >= HPT370) {
hwif->dma_start = &hpt370_ide_dma_start;
hwif->ide_dma_end = &hpt370_ide_dma_end;
- hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
+ hwif->dma_timeout = &hpt370_dma_timeout;
} else
- hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
+ hwif->dma_lost_irq = &hpt366_dma_lost_irq;
if (!noautodma)
hwif->autodma = 1;
@@ -1424,11 +1413,9 @@ static int __devinit init_setup_hpt372n(struct pci_dev *dev, ide_pci_device_t *d
static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
{
struct hpt_info *info;
- u8 rev = 0, mcr1 = 0;
-
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+ u8 mcr1 = 0;
- if (rev > 1) {
+ if (dev->revision > 1) {
d->name = "HPT371N";
info = &hpt371n;
@@ -1453,11 +1440,8 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d)
{
struct hpt_info *info;
- u8 rev = 0;
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-
- if (rev > 1) {
+ if (dev->revision > 1) {
d->name = "HPT372N";
info = &hpt372n;
@@ -1471,11 +1455,8 @@ static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d
static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d)
{
struct hpt_info *info;
- u8 rev = 0;
-
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
- if (rev > 1) {
+ if (dev->revision > 1) {
d->name = "HPT302N";
info = &hpt302n;
@@ -1489,7 +1470,7 @@ static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d)
static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
{
struct pci_dev *dev2;
- u8 rev = 0;
+ u8 rev = dev->revision;
static char *chipset_names[] = { "HPT366", "HPT366", "HPT368",
"HPT370", "HPT370A", "HPT372",
"HPT372N" };
@@ -1500,11 +1481,35 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
if (PCI_FUNC(dev->devfn) & 1)
return -ENODEV;
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+ switch (rev) {
+ case 0:
+ case 1:
+ case 2:
+ /*
+ * HPT36x chips have one channel per function and have
+ * both channel enable bits located differently and visible
+ * to both functions -- really stupid design decision... :-(
+ * Bit 4 is for the primary channel, bit 5 for the secondary.
+ */
+ d->channels = 1;
+ d->enablebits[0].mask = d->enablebits[0].val = 0x10;
- if (rev > 6)
+ d->udma_mask = HPT366_ALLOW_ATA66_3 ?
+ (HPT366_ALLOW_ATA66_4 ? 0x1f : 0x0f) : 0x07;
+ break;
+ case 3:
+ case 4:
+ d->udma_mask = HPT370_ALLOW_ATA100_5 ? 0x3f : 0x1f;
+ break;
+ default:
rev = 6;
-
+ /* fall thru */
+ case 5:
+ case 6:
+ d->udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f;
+ break;
+ }
+
d->name = chipset_names[rev];
pci_set_drvdata(dev, info[rev]);
@@ -1512,19 +1517,20 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
if (rev > 2)
goto init_single;
- /*
- * HPT36x chips are single channel and
- * do not seem to have the channel enable bit...
- */
- d->channels = 1;
- d->enablebits[0].reg = 0;
-
if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) {
- u8 pin1 = 0, pin2 = 0;
+ u8 mcr1 = 0, pin1 = 0, pin2 = 0;
int ret;
pci_set_drvdata(dev2, info[rev]);
+ /*
+ * Now we'll have to force both channels enabled if
+ * at least one of them has been enabled by BIOS...
+ */
+ pci_read_config_byte(dev, 0x50, &mcr1);
+ if (mcr1 & 0x30)
+ pci_write_config_byte(dev, 0x50, mcr1 | 0x30);
+
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
if (pin1 != pin2 && dev->irq == dev2->irq) {
@@ -1562,6 +1568,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 2 */
@@ -1573,6 +1580,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT302_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 3 */
@@ -1584,6 +1592,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2,
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT371_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 4 */
@@ -1595,6 +1604,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2, /* 4 */
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = 0x3f,
.bootable = OFF_BOARD,
.extra = 240
},{ /* 5 */
@@ -1606,6 +1616,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
.channels = 2, /* 4 */
.autodma = AUTODMA,
.enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ .udma_mask = HPT372_ALLOW_ATA133_6 ? 0x7f : 0x3f,
.bootable = OFF_BOARD,
.extra = 240
}
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index c04a02687b9..ff48c23e571 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -231,7 +231,7 @@ static int it8213_config_drive_for_dma (ide_drive_t *drive)
static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
{
- u8 reg42h = 0, ata66 = 0;
+ u8 reg42h = 0;
hwif->speedproc = &it8213_tune_chipset;
hwif->tuneproc = &it8213_tuneproc;
@@ -250,11 +250,11 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
- ata66 = (reg42h & 0x02) ? 0 : 1;
hwif->ide_dma_check = &it8213_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66;
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
/*
* The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 5faaff87d58..8197b653ba1 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -1,6 +1,6 @@
/*
- * linux/drivers/ide/pci/it821x.c Version 0.10 Mar 10 2007
+ * linux/drivers/ide/pci/it821x.c Version 0.16 Jul 3 2007
*
* Copyright (C) 2004 Red Hat <alan@redhat.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
@@ -262,7 +262,7 @@ static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
}
if (itdev->smart)
- goto set_drive_speed;
+ return 0;
/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
itdev->want[unit][1] = pio_want[set_pio];
@@ -271,7 +271,6 @@ static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
it821x_clock_strategy(drive);
it821x_program(drive, itdev->pio[unit]);
-set_drive_speed:
return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
}
@@ -455,12 +454,12 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
default:
return 1;
}
+
+ return ide_config_drive_speed(drive, speed);
}
- /*
- * In smart mode the clocking is done by the host controller
- * snooping the mode we picked. The rest of it is not our problem
- */
- return ide_config_drive_speed(drive, speed);
+
+ /* don't touch anything in the smart mode */
+ return 0;
}
/**
@@ -492,10 +491,10 @@ static int it821x_config_drive_for_dma (ide_drive_t *drive)
* the needed logic onboard.
*/
-static unsigned int __devinit ata66_it821x(ide_hwif_t *hwif)
+static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
{
/* The reference driver also only does disk side */
- return 1;
+ return ATA_CBL_PATA80;
}
/**
@@ -559,17 +558,10 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
if(idbits[129] != 1)
printk("(%dK stripe)", idbits[146]);
printk(".\n");
- /* Now the core code will have wrongly decided no DMA
- so we need to fix this */
- hwif->dma_off_quietly(drive);
-#ifdef CONFIG_IDEDMA_ONLYDISK
- if (drive->media == ide_disk)
-#endif
- ide_set_dma(drive);
} else {
/* Non RAID volume. Fixups to stop the core code
doing unsupported things */
- id->field_valid &= 1;
+ id->field_valid &= 3;
id->queue_depth = 0;
id->command_set_1 = 0;
id->command_set_2 &= 0xC400;
@@ -584,6 +576,16 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
printk(KERN_INFO "%s: Performing identify fixups.\n",
drive->name);
}
+
+ /*
+ * Set MWDMA0 mode as enabled/support - just to tell
+ * IDE core that DMA is supported (it821x hardware
+ * takes care of DMA mode programming).
+ */
+ if (id->capability & 1) {
+ id->dma_mword |= 0x0101;
+ drive->current_speed = XFER_MW_DMA_0;
+ }
}
}
@@ -658,11 +660,11 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
hwif->ultra_mask = 0x7f;
hwif->mwdma_mask = 0x07;
- hwif->swdma_mask = 0x07;
hwif->ide_dma_check = &it821x_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_it821x(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_it821x(hwif);
/*
* The BIOS often doesn't set up DMA on this controller
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index 76ed2514722..a6008f63e71 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -25,10 +25,10 @@ typedef enum {
* ata66_jmicron - Cable check
* @hwif: IDE port
*
- * Return 1 if the cable is 80pin
+ * Returns the cable type.
*/
-static int __devinit ata66_jmicron(ide_hwif_t *hwif)
+static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
{
struct pci_dev *pdev = hwif->pci_dev;
@@ -70,16 +70,17 @@ static int __devinit ata66_jmicron(ide_hwif_t *hwif)
{
case PORT_PATA0:
if (control & (1 << 3)) /* 40/80 pin primary */
- return 0;
- return 1;
+ return ATA_CBL_PATA40;
+ return ATA_CBL_PATA80;
case PORT_PATA1:
if (control5 & (1 << 19)) /* 40/80 pin secondary */
- return 0;
- return 1;
+ return ATA_CBL_PATA40;
+ return ATA_CBL_PATA80;
case PORT_SATA:
break;
}
- return 1; /* Avoid bogus "control reaches end of non-void function" */
+ /* Avoid bogus "control reaches end of non-void function" */
+ return ATA_CBL_PATA80;
}
static void jmicron_tuneproc (ide_drive_t *drive, byte mode_wanted)
@@ -159,8 +160,9 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &jmicron_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_jmicron(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_jmicron(hwif);
hwif->autodma = 1;
hwif->drives[0].autodma = hwif->autodma;
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index cc0bfdcf1f1..ee5020df005 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -225,7 +225,10 @@ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio)
static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
{
- return get_indexed_reg(hwif, 0x0b) & 0x04;
+ if (get_indexed_reg(hwif, 0x0b) & 0x04)
+ return ATA_CBL_PATA40;
+ else
+ return ATA_CBL_PATA80;
}
static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
@@ -306,11 +309,13 @@ static long __devinit read_counter(u32 dma_base)
*/
static long __devinit detect_pll_input_clock(unsigned long dma_base)
{
+ struct timeval start_time, end_time;
long start_count, end_count;
- long pll_input;
+ long pll_input, usec_elapsed;
u8 scr1;
start_count = read_counter(dma_base);
+ do_gettimeofday(&start_time);
/* Start the test mode */
outb(0x01, dma_base + 0x01);
@@ -322,6 +327,7 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base)
mdelay(10);
end_count = read_counter(dma_base);
+ do_gettimeofday(&end_time);
/* Stop the test mode */
outb(0x01, dma_base + 0x01);
@@ -333,7 +339,10 @@ static long __devinit detect_pll_input_clock(unsigned long dma_base)
* Calculate the input clock in Hz
* (the clock counter is 30 bit wide and counts down)
*/
- pll_input = ((start_count - end_count) & 0x3ffffff) * 100;
+ usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
+ (end_time.tv_usec - start_time.tv_usec);
+ pll_input = ((start_count - end_count) & 0x3ffffff) / 10 *
+ (10000000 / usec_elapsed);
DBG("start[%ld] end[%ld]\n", start_count, end_count);
@@ -503,8 +512,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
- if (!hwif->udma_four)
- hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = pdcnew_cable_detect(hwif);
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 23844687dee..41ac4a94959 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -152,8 +152,10 @@ static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
{
u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
+
pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
- return (CIS & mask) ? 1 : 0;
+
+ return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
/*
@@ -267,18 +269,24 @@ somebody_else:
return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
}
-static int pdc202xx_ide_dma_lostirq(ide_drive_t *drive)
+static void pdc202xx_dma_lost_irq(ide_drive_t *drive)
{
- if (HWIF(drive)->resetproc != NULL)
- HWIF(drive)->resetproc(drive);
- return __ide_dma_lostirq(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+
+ if (hwif->resetproc != NULL)
+ hwif->resetproc(drive);
+
+ ide_dma_lost_irq(drive);
}
-static int pdc202xx_ide_dma_timeout(ide_drive_t *drive)
+static void pdc202xx_dma_timeout(ide_drive_t *drive)
{
- if (HWIF(drive)->resetproc != NULL)
- HWIF(drive)->resetproc(drive);
- return __ide_dma_timeout(drive);
+ ide_hwif_t *hwif = HWIF(drive);
+
+ if (hwif->resetproc != NULL)
+ hwif->resetproc(drive);
+
+ ide_dma_timeout(drive);
}
static void pdc202xx_reset_host (ide_hwif_t *hwif)
@@ -347,12 +355,13 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
hwif->err_stops_fifo = 1;
hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate;
- hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq;
- hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout;
+ hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
+ hwif->dma_timeout = &pdc202xx_dma_timeout;
if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
- if (!(hwif->udma_four))
- hwif->udma_four = (pdc202xx_old_cable_detect(hwif)) ? 0 : 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = pdc202xx_old_cable_detect(hwif);
+
hwif->dma_start = &pdc202xx_old_ide_dma_start;
hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
}
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 8b219dd6302..1372c35be03 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/piix.c Version 0.47 February 8, 2007
+ * linux/drivers/ide/pci/piix.c Version 0.50 Jun 10, 2007
*
* Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
@@ -394,14 +394,45 @@ static void piix_dma_clear_irq(ide_drive_t *drive)
hwif->OUTB(dma_stat, hwif->dma_status);
}
-static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+struct ich_laptop {
+ u16 device;
+ u16 subvendor;
+ u16 subdevice;
+};
+
+/*
+ * List of laptops that use short cables rather than 80 wire
+ */
+
+static const struct ich_laptop ich_laptop[] = {
+ /* devid, subvendor, subdev */
+ { 0x27DF, 0x0005, 0x0280 }, /* ICH7 on Acer 5602WLMi */
+ { 0x27DF, 0x1025, 0x0110 }, /* ICH7 on Acer 3682WLMi */
+ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
+ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
+ /* end marker */
+ { 0, }
+};
+
+static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
{
- struct pci_dev *dev = hwif->pci_dev;
+ struct pci_dev *pdev = hwif->pci_dev;
+ const struct ich_laptop *lap = &ich_laptop[0];
u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
- pci_read_config_byte(dev, 0x54, &reg54h);
+ /* check for specials */
+ while (lap->device) {
+ if (lap->device == pdev->device &&
+ lap->subvendor == pdev->subsystem_vendor &&
+ lap->subdevice == pdev->subsystem_device) {
+ return ATA_CBL_PATA40_SHORT;
+ }
+ lap++;
+ }
+
+ pci_read_config_byte(pdev, 0x54, &reg54h);
- return (reg54h & mask) ? 1 : 0;
+ return (reg54h & mask) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/**
@@ -444,8 +475,8 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
hwif->swdma_mask = 0x04;
if (hwif->ultra_mask & 0x78) {
- if (!hwif->udma_four)
- hwif->udma_four = piix_cable_detect(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = piix_cable_detect(hwif);
}
if (no_piix_dma)
@@ -541,18 +572,16 @@ static void __devinit piix_check_450nx(void)
{
struct pci_dev *pdev = NULL;
u16 cfg;
- u8 rev;
while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
{
/* Look for 450NX PXB. Check for problem configurations
A PCI quirk checks bit 6 already */
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
pci_read_config_word(pdev, 0x41, &cfg);
/* Only on the original revision: IDE DMA can hang */
- if(rev == 0x00)
+ if (pdev->revision == 0x00)
no_piix_dma = 1;
/* On all revisions below 5 PXB bus lock must be disabled for IDE */
- else if(cfg & (1<<14) && rev < 5)
+ else if (cfg & (1<<14) && pdev->revision < 5)
no_piix_dma = 2;
}
if(no_piix_dma)
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 55bc0a32e34..7b87488e3da 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -716,7 +716,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
hwif->atapi_dma = 1;
/* we support 80c cable only. */
- hwif->udma_four = 1;
+ hwif->cbl = ATA_CBL_PATA80;
hwif->autodma = 0;
if (!noautodma)
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 47bcd91c9b5..ed04e0c8dd4 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/serverworks.c Version 0.9 Mar 4 2007
+ * linux/drivers/ide/pci/serverworks.c Version 0.20 Jun 3 2007
*
* Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz
@@ -55,7 +55,6 @@ static const char *svwks_bad_ata100[] = {
NULL
};
-static u8 svwks_revision = 0;
static struct pci_dev *isa_dev;
static int check_in_drive_lists (ide_drive_t *drive, const char **list)
@@ -71,9 +70,6 @@ static u8 svwks_udma_filter(ide_drive_t *drive)
struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 mask = 0;
- if (!svwks_revision)
- pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
-
if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
return 0x1f;
if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
@@ -88,9 +84,9 @@ static u8 svwks_udma_filter(ide_drive_t *drive)
return 0;
/* Check the OSB4 DMA33 enable bit */
return ((reg & 0x00004000) == 0x00004000) ? 0x07 : 0;
- } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) {
+ } else if (dev->revision < SVWKS_CSB5_REVISION_NEW) {
return 0x07;
- } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) {
+ } else if (dev->revision >= SVWKS_CSB5_REVISION_NEW) {
u8 btr = 0, mode;
pci_read_config_byte(dev, 0x5A, &btr);
mode = btr & 0x3;
@@ -151,71 +147,11 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 &&
drive->media == ide_disk && speed >= XFER_UDMA_0)
BUG();
-
- pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing);
- pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing);
+
pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
pci_read_config_word(dev, 0x4A, &csb5_pio);
pci_read_config_byte(dev, 0x54, &ultra_enable);
- /* If we are in RAID mode (eg AMI MegaIDE) then we can't it
- turns out trust the firmware configuration */
-
- if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
- goto oem_setup_failed;
-
- /* Per Specified Design by OEM, and ASIC Architect */
- if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
- (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) {
- if (!drive->init_speed) {
- u8 dma_stat = inb(hwif->dma_status);
-
-dma_pio:
- if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
- ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
- drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
- return 0;
- } else if ((dma_timing) &&
- ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
- u8 dmaspeed = dma_timing;
-
- dma_timing &= ~0xFFU;
- if ((dmaspeed & 0x20) == 0x20)
- dmaspeed = XFER_MW_DMA_2;
- else if ((dmaspeed & 0x21) == 0x21)
- dmaspeed = XFER_MW_DMA_1;
- else if ((dmaspeed & 0x77) == 0x77)
- dmaspeed = XFER_MW_DMA_0;
- else
- goto dma_pio;
- drive->current_speed = drive->init_speed = dmaspeed;
- return 0;
- } else if (pio_timing) {
- u8 piospeed = pio_timing;
-
- pio_timing &= ~0xFFU;
- if ((piospeed & 0x20) == 0x20)
- piospeed = XFER_PIO_4;
- else if ((piospeed & 0x22) == 0x22)
- piospeed = XFER_PIO_3;
- else if ((piospeed & 0x34) == 0x34)
- piospeed = XFER_PIO_2;
- else if ((piospeed & 0x47) == 0x47)
- piospeed = XFER_PIO_1;
- else if ((piospeed & 0x5d) == 0x5d)
- piospeed = XFER_PIO_0;
- else
- goto oem_setup_failed;
- drive->current_speed = drive->init_speed = piospeed;
- return 0;
- }
- }
- }
-
-oem_setup_failed:
-
- pio_timing &= ~0xFFU;
- dma_timing &= ~0xFFU;
ultra_timing &= ~(0x0F << (4*unit));
ultra_enable &= ~(0x01 << drive->dn);
csb5_pio &= ~(0x0F << (4*drive->dn));
@@ -294,9 +230,6 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
unsigned int reg;
u8 btr;
- /* save revision id to determine DMA capability */
- pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
-
/* force Master Latency Timer value to 64 PCICLKs */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
@@ -375,7 +308,7 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
if (!(PCI_FUNC(dev->devfn) & 1))
btr |= 0x2;
else
- btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
+ btr |= (dev->revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2;
pci_write_config_byte(dev, 0x5A, btr);
}
/* Setup HT1000 SouthBridge Controller - Single Channel Only */
@@ -389,9 +322,9 @@ static unsigned int __devinit init_chipset_svwks (struct pci_dev *dev, const cha
return dev->irq;
}
-static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
{
- return 1;
+ return ATA_CBL_PATA80;
}
/* On Dell PowerEdge servers with a CSB5/CSB6, the top two bits
@@ -401,7 +334,7 @@ static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
* Bit 14 clear = primary IDE channel does not have 80-pin cable.
* Bit 14 set = primary IDE channel has 80-pin cable.
*/
-static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
@@ -409,8 +342,8 @@ static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE))
return ((1 << (hwif->channel + 14)) &
- dev->subsystem_device) ? 1 : 0;
- return 0;
+ dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ return ATA_CBL_PATA40;
}
/* Sun Cobalt Alpine hardware avoids the 80-pin cable
@@ -419,18 +352,18 @@ static unsigned int __devinit ata66_svwks_dell (ide_hwif_t *hwif)
*
* WARNING: this only works on Alpine hardware!
*/
-static unsigned int __devinit ata66_svwks_cobalt (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
dev->vendor == PCI_VENDOR_ID_SERVERWORKS &&
dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
return ((1 << (hwif->channel + 14)) &
- dev->subsystem_device) ? 1 : 0;
- return 0;
+ dev->subsystem_device) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+ return ATA_CBL_PATA40;
}
-static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
+static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
{
struct pci_dev *dev = hwif->pci_dev;
@@ -449,9 +382,9 @@ static unsigned int __devinit ata66_svwks (ide_hwif_t *hwif)
/* Per Specified Design by OEM, and ASIC Architect */
if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
- return 1;
+ return ATA_CBL_PATA80;
- return 0;
+ return ATA_CBL_PATA40;
}
static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
@@ -482,8 +415,8 @@ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
hwif->ide_dma_check = &svwks_config_drive_xfer_rate;
if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
- if (!hwif->udma_four)
- hwif->udma_four = ata66_svwks(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_svwks(hwif);
}
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index d3185e29a38..d396b2929ed 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -316,14 +316,6 @@ static void sgiioc4_dma_host_off(ide_drive_t * drive)
sgiioc4_clearirq(drive);
}
-static int
-sgiioc4_ide_dma_lostirq(ide_drive_t * drive)
-{
- HWIF(drive)->resetproc(drive);
-
- return __ide_dma_lostirq(drive);
-}
-
static void
sgiioc4_resetproc(ide_drive_t * drive)
{
@@ -331,6 +323,14 @@ sgiioc4_resetproc(ide_drive_t * drive)
sgiioc4_clearirq(drive);
}
+static void
+sgiioc4_dma_lost_irq(ide_drive_t * drive)
+{
+ sgiioc4_resetproc(drive);
+
+ ide_dma_lost_irq(drive);
+}
+
static u8
sgiioc4_INB(unsigned long port)
{
@@ -607,8 +607,8 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
hwif->dma_host_on = &sgiioc4_dma_host_on;
hwif->dma_host_off = &sgiioc4_dma_host_off;
- hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
- hwif->ide_dma_timeout = &__ide_dma_timeout;
+ hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
+ hwif->dma_timeout = &ide_dma_timeout;
hwif->INB = &sgiioc4_INB;
}
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 1a4444e7226..1c3e3548789 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -933,16 +933,17 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
* interface.
*/
-static unsigned int __devinit ata66_siimage(ide_hwif_t *hwif)
+static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
{
unsigned long addr = siimage_selreg(hwif, 0);
- if (pci_get_drvdata(hwif->pci_dev) == NULL) {
- u8 ata66 = 0;
+ u8 ata66 = 0;
+
+ if (pci_get_drvdata(hwif->pci_dev) == NULL)
pci_read_config_byte(hwif->pci_dev, addr, &ata66);
- return (ata66 & 0x01) ? 1 : 0;
- }
+ else
+ ata66 = hwif->INB(addr);
- return (hwif->INB(addr) & 0x01) ? 1 : 0;
+ return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
/**
@@ -988,8 +989,9 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
hwif->atapi_dma = 1;
hwif->ide_dma_check = &siimage_config_drive_for_dma;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_siimage(hwif);
+
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_siimage(hwif);
if (hwif->mmio) {
hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index bb6cc4aedd6..756a9b6eb46 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/ide/pci/sis5513.c Version 0.20 Mar 4, 2007
+ * linux/drivers/ide/pci/sis5513.c Version 0.25 Jun 10, 2007
*
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
@@ -659,9 +659,7 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
/* Special case for SiS630 : 630S/ET is ATA_100a */
if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) {
- u8 hostrev;
- pci_read_config_byte(host, PCI_REVISION_ID, &hostrev);
- if (hostrev >= 0x30)
+ if (host->revision >= 0x30)
chipset_family = ATA_100a;
}
pci_dev_put(host);
@@ -702,7 +700,6 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
u16 trueid;
u8 prefctl;
u8 idecfg;
- u8 sbrev;
pci_read_config_byte(dev, 0x4a, &idecfg);
pci_write_config_byte(dev, 0x4a, idecfg | 0x10);
@@ -712,11 +709,10 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
if (trueid == 0x5517) { /* SiS 961/961B */
lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */
- pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev);
pci_read_config_byte(dev, 0x49, &prefctl);
pci_dev_put(lpc_bridge);
- if (sbrev == 0x10 && (prefctl & 0x80)) {
+ if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) {
printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n");
chipset_family = ATA_133a;
} else {
@@ -796,10 +792,33 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c
return 0;
}
-static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
+struct sis_laptop {
+ u16 device;
+ u16 subvendor;
+ u16 subdevice;
+};
+
+static const struct sis_laptop sis_laptop[] = {
+ /* devid, subvendor, subdev */
+ { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */
+ /* end marker */
+ { 0, }
+};
+
+static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
{
+ struct pci_dev *pdev = hwif->pci_dev;
+ const struct sis_laptop *lap = &sis_laptop[0];
u8 ata66 = 0;
+ while (lap->device) {
+ if (lap->device == pdev->device &&
+ lap->subvendor == pdev->subsystem_vendor &&
+ lap->subdevice == pdev->subsystem_device)
+ return ATA_CBL_PATA40_SHORT;
+ lap++;
+ }
+
if (chipset_family >= ATA_133) {
u16 regw = 0;
u16 reg_addr = hwif->channel ? 0x52: 0x50;
@@ -811,7 +830,8 @@ static unsigned int __devinit ata66_sis5513 (ide_hwif_t *hwif)
pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
ata66 = (reg48h & mask) ? 0 : 1;
}
- return ata66;
+
+ return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
}
static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
@@ -841,8 +861,8 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
if (!chipset_family)
return;
- if (!(hwif->udma_four))
- hwif->udma_four = ata66_sis5513(hwif);
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = ata66_sis5513(hwif);
if (chipset_family > ATA_16) {
hwif->ide_dma_check = &sis5513_config_xfer_rate;
@@ -872,6 +892,7 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi
static struct pci_device_id sis5513_pci_tbl[] = {
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_1180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ 0, },
};
MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 7c383d9cc47..a7323d278c4 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -195,7 +195,7 @@ static inline void sl82c105_reset_host(struct pci_dev *dev)
* This function is called when the IDE timer expires, the drive
* indicates that it is READY, and we were waiting for DMA to complete.
*/
-static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
+static void sl82c105_dma_lost_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
@@ -222,9 +222,6 @@ static int sl82c105_ide_dma_lostirq(ide_drive_t *drive)
}
sl82c105_reset_host(dev);
-
- /* __ide_dma_lostirq would return 1, so we do as well */
- return 1;
}
/*
@@ -244,15 +241,12 @@ static void sl82c105_dma_start(ide_drive_t *drive)
ide_dma_start(drive);
}
-static int sl82c105_ide_dma_timeout(ide_drive_t *drive)
+static void sl82c105_dma_timeout(ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct pci_dev *dev = hwif->pci_dev;
+ DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
- DBG(("sl82c105_ide_dma_timeout(drive:%s)\n", drive->name));
-
- sl82c105_reset_host(dev);
- return __ide_dma_timeout(drive);
+ sl82c105_reset_host(HWIF(drive)->pci_dev);
+ ide_dma_timeout(drive);
}
static int sl82c105_ide_dma_on(ide_drive_t *drive)
@@ -344,7 +338,6 @@ static void sl82c105_tune_drive(ide_drive_t *drive, u8 pio)
static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
{
struct pci_dev *bridge;
- u8 rev;
/*
* The bridge should be part of the same device, but function 0.
@@ -366,10 +359,9 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
/*
* We need to find function 0's revision, not function 1
*/
- pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
pci_dev_put(bridge);
- return rev;
+ return bridge->revision;
}
/*
@@ -441,9 +433,9 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
hwif->ide_dma_check = &sl82c105_ide_dma_check;
hwif->ide_dma_on = &sl82c105_ide_dma_on;
hwif->dma_off_quietly = &sl82c105_dma_off_quietly;
- hwif->ide_dma_lostirq = &sl82c105_ide_dma_lostirq;
+ hwif->dma_lost_irq = &sl82c105_dma_lost_irq;
hwif->dma_start = &sl82c105_dma_start;
- hwif->ide_dma_timeout = &sl82c105_ide_dma_timeout;
+ hwif->dma_timeout = &sl82c105_dma_timeout;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index c40f291f91e..575dbbd8b48 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -199,10 +199,9 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
hwif->mwdma_mask = 0x06;
hwif->swdma_mask = 0x04;
- if (!hwif->udma_four) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
/* bit[0(1)]: 0:80, 1:40 */
- hwif->udma_four = (reg47 & mask) ? 0 : 1;
- }
+ hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate;
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index cee619bb2ea..8de1f8e2249 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -220,13 +220,13 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate;
hwif->dma_start = &tc86c001_dma_start;
- if (!hwif->udma_four) {
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
/*
* System Control 1 Register bit 13 (PDIAGN):
* 0=80-pin cable, 1=40-pin cable
*/
scr1 = hwif->INW(sc_base + 0x00);
- hwif->udma_four = (scr1 & 0x2000) ? 0 : 1;
+ hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
}
if (!noautodma)
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index a508550c409..27e92fb9f95 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -1,6 +1,6 @@
/*
*
- * Version 3.38
+ * Version 3.45
*
* VIA IDE driver for Linux. Supported southbridges:
*
@@ -9,6 +9,7 @@
* vt8235, vt8237, vt8237a
*
* Copyright (c) 2000-2002 Vojtech Pavlik
+ * Copyright (c) 2007 Bartlomiej Zolnierkiewicz
*
* Based on the work of:
* Michel Aubry
@@ -33,6 +34,8 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/dmi.h>
+
#include <asm/io.h>
#ifdef CONFIG_PPC_CHRP
@@ -41,8 +44,6 @@
#include "ide-timing.h"
-#define DISPLAY_VIA_TIMINGS
-
#define VIA_IDE_ENABLE 0x40
#define VIA_IDE_CONFIG 0x41
#define VIA_FIFO_CONFIG 0x43
@@ -54,18 +55,12 @@
#define VIA_ADDRESS_SETUP 0x4c
#define VIA_UDMA_TIMING 0x50
-#define VIA_UDMA 0x007
-#define VIA_UDMA_NONE 0x000
-#define VIA_UDMA_33 0x001
-#define VIA_UDMA_66 0x002
-#define VIA_UDMA_100 0x003
-#define VIA_UDMA_133 0x004
-#define VIA_BAD_PREQ 0x010 /* Crashes if PREQ# till DDACK# set */
-#define VIA_BAD_CLK66 0x020 /* 66 MHz clock doesn't work correctly */
-#define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */
-#define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */
-#define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */
-#define VIA_BAD_AST 0x200 /* Don't touch Address Setup Timing */
+#define VIA_BAD_PREQ 0x01 /* Crashes if PREQ# till DDACK# set */
+#define VIA_BAD_CLK66 0x02 /* 66 MHz clock doesn't work correctly */
+#define VIA_SET_FIFO 0x04 /* Needs to have FIFO split set */
+#define VIA_NO_UNMASK 0x08 /* Doesn't work with IRQ unmasking on */
+#define VIA_BAD_ID 0x10 /* Has wrong vendor ID (0x1107) */
+#define VIA_BAD_AST 0x20 /* Don't touch Address Setup Timing */
/*
* VIA SouthBridge chips.
@@ -76,36 +71,37 @@ static struct via_isa_bridge {
u16 id;
u8 rev_min;
u8 rev_max;
- u16 flags;
+ u8 udma_mask;
+ u8 flags;
} via_isa_bridges[] = {
- { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
- { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 },
- { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 },
- { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 },
- { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
- { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, VIA_UDMA_66 },
- { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ },
- { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },
- { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
- { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK },
- { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, VIA_UDMA_NONE | VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
+ { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, ATA_UDMA6, VIA_BAD_AST },
+ { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, ATA_UDMA5, },
+ { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, ATA_UDMA5, },
+ { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, ATA_UDMA4, },
+ { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+ { "vt82c596b", PCI_DEVICE_ID_VIA_82C596, 0x10, 0x2f, ATA_UDMA4, },
+ { "vt82c596a", PCI_DEVICE_ID_VIA_82C596, 0x00, 0x0f, ATA_UDMA2, VIA_BAD_CLK66 },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x47, 0x4f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x46, ATA_UDMA2, VIA_SET_FIFO | VIA_BAD_PREQ },
+ { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586a", PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, ATA_UDMA2, VIA_SET_FIFO },
+ { "vt82c586", PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, 0x00, VIA_SET_FIFO },
+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK },
+ { "vt82c576", PCI_DEVICE_ID_VIA_82C576, 0x00, 0x2f, 0x00, VIA_SET_FIFO | VIA_NO_UNMASK | VIA_BAD_ID },
{ NULL }
};
static unsigned int via_clock;
-static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
+static char *via_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
struct via82cxxx_dev
{
@@ -140,12 +136,12 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
- case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
- case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
- case VIA_UDMA_133: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
- default: return;
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA2: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+ case ATA_UDMA4: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
+ case ATA_UDMA5: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+ case ATA_UDMA6: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+ default: return;
}
pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
@@ -173,12 +169,12 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
T = 1000000000 / via_clock;
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_33: UT = T; break;
- case VIA_UDMA_66: UT = T/2; break;
- case VIA_UDMA_100: UT = T/3; break;
- case VIA_UDMA_133: UT = T/4; break;
- default: UT = T;
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA2: UT = T; break;
+ case ATA_UDMA4: UT = T/2; break;
+ case ATA_UDMA5: UT = T/3; break;
+ case ATA_UDMA6: UT = T/4; break;
+ default: UT = T;
}
ide_timing_compute(drive, speed, &t, T, UT);
@@ -208,8 +204,7 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
{
if (pio == 255) {
- via_set_drive(drive,
- ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
+ via_set_drive(drive, ide_find_best_pio_mode(drive));
return;
}
@@ -226,16 +221,10 @@ static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
static int via82cxxx_ide_dma_check (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
- u16 w80 = hwif->udma_four;
+ u8 speed = ide_max_dma_mode(drive);
- u16 speed = ide_find_best_mode(drive,
- XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
- (vdev->via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
- (w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
+ if (speed == 0)
+ speed = ide_find_best_pio_mode(drive);
via_set_drive(drive, speed);
@@ -248,16 +237,14 @@ static int via82cxxx_ide_dma_check (ide_drive_t *drive)
static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
{
struct via_isa_bridge *via_config;
- u8 t;
for (via_config = via_isa_bridges; via_config->id; via_config++)
if ((*isa = pci_get_device(PCI_VENDOR_ID_VIA +
!!(via_config->flags & VIA_BAD_ID),
via_config->id, NULL))) {
- pci_read_config_byte(*isa, PCI_REVISION_ID, &t);
- if (t >= via_config->rev_min &&
- t <= via_config->rev_max)
+ if ((*isa)->revision >= via_config->rev_min &&
+ (*isa)->revision <= via_config->rev_max)
break;
pci_dev_put(*isa);
}
@@ -272,8 +259,8 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
{
int i;
- switch (vdev->via_config->flags & VIA_UDMA) {
- case VIA_UDMA_66:
+ switch (vdev->via_config->udma_mask) {
+ case ATA_UDMA4:
for (i = 24; i >= 0; i -= 8)
if (((u >> (i & 16)) & 8) &&
((u >> i) & 0x20) &&
@@ -286,7 +273,7 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
}
break;
- case VIA_UDMA_100:
+ case ATA_UDMA5:
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
@@ -298,7 +285,7 @@ static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u)
}
break;
- case VIA_UDMA_133:
+ case ATA_UDMA6:
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
@@ -353,7 +340,7 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
via_cable_detect(vdev, u);
- if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) {
+ if (via_config->udma_mask == ATA_UDMA4) {
/* Enable Clk66 */
pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
} else if (via_config->flags & VIA_BAD_CLK66) {
@@ -415,17 +402,54 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
* Print the boot message.
*/
- pci_read_config_byte(isa, PCI_REVISION_ID, &t);
- printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s "
+ printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %sDMA%s "
"controller on pci%s\n",
- via_config->name, t,
- via_dma[via_config->flags & VIA_UDMA],
+ via_config->name, isa->revision,
+ via_config->udma_mask ? "U" : "MW",
+ via_dma[via_config->udma_mask ?
+ (fls(via_config->udma_mask) - 1) : 0],
pci_name(dev));
pci_dev_put(isa);
return 0;
}
+/*
+ * Cable special cases
+ */
+
+static struct dmi_system_id cable_dmi_table[] = {
+ {
+ .ident = "Acer Ferrari 3400",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Acer,Inc."),
+ DMI_MATCH(DMI_BOARD_NAME, "Ferrari 3400"),
+ },
+ },
+ { }
+};
+
+static int via_cable_override(void)
+{
+ /* Systems by DMI */
+ if (dmi_check_system(cable_dmi_table))
+ return 1;
+ return 0;
+}
+
+static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
+{
+ struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
+
+ if (via_cable_override())
+ return ATA_CBL_PATA40_SHORT;
+
+ if ((vdev->via_80w >> hwif->channel) & 1)
+ return ATA_CBL_PATA80;
+ else
+ return ATA_CBL_PATA40;
+}
+
static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
{
struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
@@ -454,12 +478,14 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
return;
hwif->atapi_dma = 1;
- hwif->ultra_mask = 0x7f;
+
+ hwif->ultra_mask = vdev->via_config->udma_mask;
hwif->mwdma_mask = 0x07;
hwif->swdma_mask = 0x07;
- if (!hwif->udma_four)
- hwif->udma_four = (vdev->via_80w >> hwif->channel) & 1;
+ if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+ hwif->cbl = via82cxxx_cable_detect(hwif);
+
hwif->ide_dma_check = &via82cxxx_ide_dma_check;
if (!noautodma)
hwif->autodma = 1;
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 45fc36f0f21..e46f4720654 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -942,8 +942,8 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
return 1;
case XFER_UDMA_4:
case XFER_UDMA_3:
- if (HWIF(drive)->udma_four == 0)
- return 1;
+ if (drive->hwif->cbl != ATA_CBL_PATA80)
+ return 1;
case XFER_UDMA_2:
case XFER_UDMA_1:
case XFER_UDMA_0:
@@ -1244,7 +1244,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->chipset = ide_pmac;
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
hwif->hold = pmif->mediabay;
- hwif->udma_four = pmif->cable_80;
+ hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
hwif->drives[0].unmask = 1;
hwif->drives[1].unmask = 1;
hwif->tuneproc = pmac_ide_tuneproc;
@@ -1821,28 +1821,11 @@ pmac_ide_dma_check(ide_drive_t *drive)
enable = 0;
if (enable) {
- short mode;
-
- map = XFER_MWDMA;
- if (pmif->kind == controller_kl_ata4
- || pmif->kind == controller_un_ata6
- || pmif->kind == controller_k2_ata6
- || pmif->kind == controller_sh_ata6) {
- map |= XFER_UDMA;
- if (pmif->cable_80) {
- map |= XFER_UDMA_66;
- if (pmif->kind == controller_un_ata6 ||
- pmif->kind == controller_k2_ata6 ||
- pmif->kind == controller_sh_ata6)
- map |= XFER_UDMA_100;
- if (pmif->kind == controller_sh_ata6)
- map |= XFER_UDMA_133;
- }
- }
- mode = ide_find_best_mode(drive, map);
- if (mode & XFER_UDMA)
+ u8 mode = ide_max_dma_mode(drive);
+
+ if (mode >= XFER_UDMA_0)
drive->using_dma = pmac_ide_udma_enable(drive, mode);
- else if (mode & XFER_MWDMA)
+ else if (mode >= XFER_MW_DMA_0)
drive->using_dma = pmac_ide_mdma_enable(drive, mode);
hwif->OUTB(0, IDE_CONTROL_REG);
/* Apply settings to controller */
@@ -2004,20 +1987,19 @@ static void pmac_ide_dma_host_on(ide_drive_t *drive)
{
}
-static int
-pmac_ide_dma_lostirq (ide_drive_t *drive)
+static void
+pmac_ide_dma_lost_irq (ide_drive_t *drive)
{
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
volatile struct dbdma_regs __iomem *dma;
unsigned long status;
if (pmif == NULL)
- return 0;
+ return;
dma = pmif->dma_regs;
status = readl(&dma->status);
printk(KERN_ERR "ide-pmac lost interrupt, dma status: %lx\n", status);
- return 0;
}
/*
@@ -2057,8 +2039,8 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
hwif->dma_host_off = &pmac_ide_dma_host_off;
hwif->dma_host_on = &pmac_ide_dma_host_on;
- hwif->ide_dma_timeout = &__ide_dma_timeout;
- hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
+ hwif->dma_timeout = &ide_dma_timeout;
+ hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
hwif->atapi_dma = 1;
switch(pmif->kind) {
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 67035ba4bf5..c88d33225cf 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -872,11 +872,15 @@ void __init ide_scan_pcibus (int scan_direction)
* are post init.
*/
- list_for_each_safe(l, n, &ide_pci_drivers)
- {
+ list_for_each_safe(l, n, &ide_pci_drivers) {
list_del(l);
d = list_entry(l, struct pci_driver, node);
- __pci_register_driver(d, d->driver.owner, d->driver.mod_name);
+ if (__pci_register_driver(d, d->driver.owner,
+ d->driver.mod_name)) {
+ printk(KERN_ERR "%s: failed to register driver "
+ "for %s\n", __FUNCTION__,
+ d->driver.mod_name);
+ }
}
}
#endif
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 20814137761..65722117ab6 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2280,7 +2280,7 @@ static void dv1394_remove_host(struct hpsb_host *host)
} while (video);
if (found_ohci_card)
- class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+ device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
}
@@ -2295,9 +2295,9 @@ static void dv1394_add_host(struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
- NULL, "dv1394-%d", id);
+ device_create(hpsb_protocol_class, NULL, MKDEV(
+ IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
+ "dv1394-%d", id);
dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 5f026b5d785..93362eed94e 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -599,9 +599,7 @@ static void ether1394_add_host(struct hpsb_host *host)
}
SET_MODULE_OWNER(dev);
-
- /* This used to be &host->device in Linux 2.6.20 and before. */
- SET_NETDEV_DEV(dev, host->device.parent);
+ SET_NETDEV_DEV(dev, &host->device);
priv = netdev_priv(dev);
INIT_LIST_HEAD(&priv->ip_node_list);
@@ -1565,7 +1563,7 @@ static void ether1394_complete_cb(void *__ptask)
/* Transmit a packet (called by kernel) */
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct eth1394hdr *eth;
+ struct eth1394hdr hdr_buf;
struct eth1394_priv *priv = netdev_priv(dev);
__be16 proto;
unsigned long flags;
@@ -1595,16 +1593,17 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
if (!skb)
goto fail;
- /* Get rid of the fake eth1394 header, but save a pointer */
- eth = (struct eth1394hdr *)skb->data;
+ /* Get rid of the fake eth1394 header, but first make a copy.
+ * We might need to rebuild the header on tx failure. */
+ memcpy(&hdr_buf, skb->data, sizeof(hdr_buf));
skb_pull(skb, ETH1394_HLEN);
- proto = eth->h_proto;
+ proto = hdr_buf.h_proto;
dg_size = skb->len;
/* Set the transmission type for the packet. ARP packets and IP
* broadcast packets are sent via GASP. */
- if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
+ if (memcmp(hdr_buf.h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
proto == htons(ETH_P_ARP) ||
(proto == htons(ETH_P_IP) &&
IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
@@ -1616,7 +1615,7 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
priv->bc_dgl++;
} else {
- __be64 guid = get_unaligned((u64 *)eth->h_dest);
+ __be64 guid = get_unaligned((u64 *)hdr_buf.h_dest);
node = eth1394_find_node_guid(&priv->ip_node_list,
be64_to_cpu(guid));
@@ -1673,6 +1672,14 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
if (dest_node == (LOCAL_BUS | ALL_NODES))
goto fail;
+ /* At this point we want to restore the packet. When we return
+ * here with NETDEV_TX_BUSY we will get another entrance in this
+ * routine with the same skb and we need it to look the same.
+ * So we pull 4 more bytes, then build the header again. */
+ skb_pull(skb, 4);
+ ether1394_header(skb, dev, ntohs(hdr_buf.h_proto),
+ hdr_buf.h_dest, NULL, 0);
+
/* Most failures of ether1394_send_packet are recoverable. */
netif_stop_queue(dev);
priv->wake_node = dest_node;
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 83a49331275..b6425469b6e 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -483,37 +483,6 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval;
}
-/**
- * hpsb_listen_channel - enable receving a certain isochronous channel
- *
- * Reception is handled through the @hl's iso_receive op.
- */
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel)
-{
- if (channel > 63) {
- HPSB_ERR("%s called with invalid channel", __FUNCTION__);
- return -EINVAL;
- }
- if (host->iso_listen_count[channel]++ == 0)
- return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
- return 0;
-}
-
-/**
- * hpsb_unlisten_channel - disable receving a certain isochronous channel
- */
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel)
-{
- if (channel > 63) {
- HPSB_ERR("%s called with invalid channel", __FUNCTION__);
- return;
- }
- if (--host->iso_listen_count[channel] == 0)
- host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
-}
-
static void init_hpsb_highlevel(struct hpsb_host *host)
{
INIT_LIST_HEAD(&dummy_zero_addr.host_list);
@@ -570,20 +539,6 @@ void highlevel_host_reset(struct hpsb_host *host)
read_unlock_irqrestore(&hl_irqs_lock, flags);
}
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
-{
- unsigned long flags;
- struct hpsb_highlevel *hl;
- int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
-
- read_lock_irqsave(&hl_irqs_lock, flags);
- list_for_each_entry(hl, &hl_irqs, irq_list) {
- if (hl->iso_receive)
- hl->iso_receive(host, channel, data, length);
- }
- read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length)
{
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
index 63474f7ee69..eb9fe321e09 100644
--- a/drivers/ieee1394/highlevel.h
+++ b/drivers/ieee1394/highlevel.h
@@ -26,9 +26,7 @@ struct hpsb_address_serve {
struct hpsb_highlevel {
const char *name;
- /* Any of the following pointers can legally be NULL, except for
- * iso_receive which can only be NULL when you don't request
- * channels. */
+ /* Any of the following pointers can legally be NULL. */
/* New host initialized. Will also be called during
* hpsb_register_highlevel for all hosts already installed. */
@@ -43,13 +41,6 @@ struct hpsb_highlevel {
* You can not expect to be able to do stock hpsb_reads. */
void (*host_reset)(struct hpsb_host *host);
- /* An isochronous packet was received. Channel contains the channel
- * number for your convenience, it is also contained in the included
- * packet header (first quadlet, CRCs are missing). You may get called
- * for channel/host combinations you did not request. */
- void (*iso_receive)(struct hpsb_host *host, int channel,
- quadlet_t *data, size_t length);
-
/* A write request was received on either the FCP_COMMAND (direction =
* 0) or the FCP_RESPONSE (direction = 1) register. The cts arg
* contains the cts field (first byte of data). */
@@ -109,7 +100,6 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags);
-void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length);
@@ -125,10 +115,6 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start);
-int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel);
-void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
- unsigned int channel);
void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index bd0755c789c..8dd09d85041 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -154,15 +154,16 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
h->device.parent = dev;
+ set_dev_node(&h->device, dev_to_node(dev));
snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
- h->class_dev.dev = &h->device;
- h->class_dev.class = &hpsb_host_class;
- snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id);
+ h->host_dev.parent = &h->device;
+ h->host_dev.class = &hpsb_host_class;
+ snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id);
if (device_register(&h->device))
goto fail;
- if (class_device_register(&h->class_dev)) {
+ if (device_register(&h->host_dev)) {
device_unregister(&h->device);
goto fail;
}
@@ -202,7 +203,7 @@ void hpsb_remove_host(struct hpsb_host *host)
host->driver = &dummy_driver;
highlevel_remove_host(host);
- class_device_unregister(&host->class_dev);
+ device_unregister(&host->host_dev);
device_unregister(&host->device);
}
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index feb55d03229..e4e8aeb4d77 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -28,8 +28,6 @@ struct hpsb_host {
struct timer_list timeout;
unsigned long timeout_interval;
- unsigned char iso_listen_count[64];
-
int node_count; /* number of identified nodes on this bus */
int selfid_count; /* total number of SelfIDs received */
int nodes_active; /* number of nodes with active link layer */
@@ -57,7 +55,7 @@ struct hpsb_host {
struct hpsb_host_driver *driver;
struct pci_dev *pdev;
struct device device;
- struct class_device class_dev;
+ struct device host_dev;
struct delayed_work delayed_reset;
unsigned config_roms:31;
@@ -99,12 +97,6 @@ enum devctl_cmd {
/* Cancel all outstanding async requests without resetting the bus.
* Return void. */
CANCEL_REQUESTS,
-
- /* Start or stop receiving isochronous channel in arg. Return void.
- * This acts as an optimization hint, hosts are not required not to
- * listen on unrequested channels. */
- ISO_LISTEN_CHANNEL,
- ISO_UNLISTEN_CHANNEL
};
enum isoctl_cmd {
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 8f71b6a06aa..0fc8c6e559e 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -1028,11 +1028,6 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
handle_incoming_packet(host, tcode, data, size, write_acked);
break;
-
- case TCODE_ISO_DATA:
- highlevel_iso_receive(host, data, size);
- break;
-
case TCODE_CYCLE_START:
/* simply ignore this packet if it is passed on */
break;
@@ -1316,7 +1311,6 @@ EXPORT_SYMBOL(hpsb_make_streampacket);
EXPORT_SYMBOL(hpsb_make_lockpacket);
EXPORT_SYMBOL(hpsb_make_lock64packet);
EXPORT_SYMBOL(hpsb_make_phypacket);
-EXPORT_SYMBOL(hpsb_make_isopacket);
EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_packet_success);
@@ -1327,8 +1321,6 @@ EXPORT_SYMBOL(hpsb_unregister_highlevel);
EXPORT_SYMBOL(hpsb_register_addrspace);
EXPORT_SYMBOL(hpsb_unregister_addrspace);
EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
-EXPORT_SYMBOL(hpsb_listen_channel);
-EXPORT_SYMBOL(hpsb_unlisten_channel);
EXPORT_SYMBOL(hpsb_get_hostinfo);
EXPORT_SYMBOL(hpsb_create_hostinfo);
EXPORT_SYMBOL(hpsb_destroy_hostinfo);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index ad526523d0e..21d50f73a21 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -24,9 +24,8 @@ struct hpsb_packet {
nodeid_t node_id;
- /* Async and Iso types should be clear, raw means send-as-is, do not
- * CRC! Byte swapping shall still be done in this case. */
- enum { hpsb_async, hpsb_iso, hpsb_raw } __attribute__((packed)) type;
+ /* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
+ enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
/* Okay, this is core internal and a no care for hosts.
* queued = queued for sending
@@ -37,7 +36,7 @@ struct hpsb_packet {
hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
} __attribute__((packed)) state;
- /* These are core internal. */
+ /* These are core-internal. */
signed char tlabel;
signed char ack_code;
unsigned char tcode;
@@ -62,11 +61,15 @@ struct hpsb_packet {
/* Store jiffies for implementing bus timeouts. */
unsigned long sendtime;
- /* Sizes are in bytes. *data can be DMA-mapped. */
+ /* Core-internal. */
size_t allocated_data_size; /* as allocated */
+
+ /* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
size_t data_size; /* as filled in */
size_t header_size; /* as filled in, not counting the CRC */
- quadlet_t *data;
+
+ /* Buffers */
+ quadlet_t *data; /* can be DMA-mapped */
quadlet_t header[5];
quadlet_t embedded_data[0]; /* keep as last member */
};
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 40078ce930c..c39c70a8aa9 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -89,18 +89,6 @@ static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
packet->expect_response = 1;
}
-static void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
- int tag, int sync)
-{
- packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
- | (TCODE_ISO_DATA << 4) | sync;
-
- packet->header_size = 4;
- packet->data_size = length;
- packet->type = hpsb_iso;
- packet->tcode = TCODE_ISO_DATA;
-}
-
static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
{
packet->header[0] = data;
@@ -491,24 +479,6 @@ struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
return p;
}
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
- int length, int channel,
- int tag, int sync)
-{
- struct hpsb_packet *p;
-
- p = hpsb_alloc_packet(length);
- if (!p)
- return NULL;
-
- p->host = host;
- fill_iso_packet(p, length, channel, tag, sync);
-
- p->generation = get_hpsb_generation(host);
-
- return p;
-}
-
/*
* FIXME - these functions should probably read from / write to user space to
* avoid in kernel buffers for user space callers
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 86b8ee692ea..d2d5bc3546d 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -19,8 +19,6 @@ struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
nodeid_t node, u64 addr, int extcode,
octlet_t *data, octlet_t arg);
struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
-struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length,
- int channel, int tag, int sync);
struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
nodeid_t node, u64 addr,
quadlet_t *buffer, size_t length);
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 835937e3852..51a12062ed3 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,6 +19,7 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <asm/atomic.h>
+#include <asm/semaphore.h>
#include "csr.h"
#include "highlevel.h"
@@ -145,8 +146,6 @@ static struct csr1212_bus_ops nodemgr_csr_ops = {
* but now we are much simpler because of the LDM.
*/
-static DEFINE_MUTEX(nodemgr_serialize);
-
struct host_info {
struct hpsb_host *host;
struct list_head list;
@@ -154,7 +153,7 @@ struct host_info {
};
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size);
static void nodemgr_resume_ne(struct node_entry *ne);
static void nodemgr_remove_ne(struct node_entry *ne);
@@ -165,37 +164,38 @@ struct bus_type ieee1394_bus_type = {
.match = nodemgr_bus_match,
};
-static void host_cls_release(struct class_device *class_dev)
+static void host_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device);
+ put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
}
struct class hpsb_host_class = {
.name = "ieee1394_host",
- .release = host_cls_release,
+ .dev_release = host_cls_release,
};
-static void ne_cls_release(struct class_device *class_dev)
+static void ne_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
+ put_device(&container_of((dev), struct node_entry, node_dev)->device);
}
static struct class nodemgr_ne_class = {
.name = "ieee1394_node",
- .release = ne_cls_release,
+ .dev_release = ne_cls_release,
};
-static void ud_cls_release(struct class_device *class_dev)
+static void ud_cls_release(struct device *dev)
{
- put_device(&container_of((class_dev), struct unit_directory, class_dev)->device);
+ put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
}
/* The name here is only so that unit directory hotplug works with old
- * style hotplug, which only ever did unit directories anyway. */
+ * style hotplug, which only ever did unit directories anyway.
+ */
static struct class nodemgr_ud_class = {
.name = "ieee1394",
- .release = ud_cls_release,
- .uevent = nodemgr_uevent,
+ .dev_release = ud_cls_release,
+ .dev_uevent = nodemgr_uevent,
};
static struct hpsb_highlevel nodemgr_highlevel;
@@ -283,7 +283,7 @@ static ssize_t fw_show_##class##_##td_kv (struct device *dev, struct device_attr
memcpy(buf, \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(class->td_kv), \
len); \
- while ((buf + len - 1) == '\0') \
+ while (buf[len - 1] == '\0') \
len--; \
buf[len++] = '\n'; \
buf[len] = '\0'; \
@@ -730,11 +730,11 @@ static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
static void nodemgr_remove_uds(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *tmp, *ud;
- /* Iteration over nodemgr_ud_class.children has to be protected by
- * nodemgr_ud_class.sem, but class_device_unregister() will eventually
+ /* Iteration over nodemgr_ud_class.devices has to be protected by
+ * nodemgr_ud_class.sem, but device_unregister() will eventually
* take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
* release the semaphore, and then unregister the ud. Since this code
* may be called from other contexts besides the knodemgrds, protect the
@@ -744,9 +744,9 @@ static void nodemgr_remove_uds(struct node_entry *ne)
for (;;) {
ud = NULL;
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- tmp = container_of(cdev, struct unit_directory,
- class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ tmp = container_of(dev, struct unit_directory,
+ unit_dev);
if (tmp->ne == ne) {
ud = tmp;
break;
@@ -755,7 +755,7 @@ static void nodemgr_remove_uds(struct node_entry *ne)
up(&nodemgr_ud_class.sem);
if (ud == NULL)
break;
- class_device_unregister(&ud->class_dev);
+ device_unregister(&ud->unit_dev);
device_unregister(&ud->device);
}
mutex_unlock(&nodemgr_serialize_remove_uds);
@@ -772,10 +772,9 @@ static void nodemgr_remove_ne(struct node_entry *ne)
HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-
nodemgr_remove_uds(ne);
- class_device_unregister(&ne->class_dev);
+ device_unregister(&ne->node_dev);
device_unregister(dev);
put_device(dev);
@@ -783,7 +782,9 @@ static void nodemgr_remove_ne(struct node_entry *ne)
static int __nodemgr_remove_host_dev(struct device *dev, void *data)
{
- nodemgr_remove_ne(container_of(dev, struct node_entry, device));
+ if (dev->bus == &ieee1394_bus_type)
+ nodemgr_remove_ne(container_of(dev, struct node_entry,
+ device));
return 0;
}
@@ -850,14 +851,14 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr
snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx",
(unsigned long long)(ne->guid));
- ne->class_dev.dev = &ne->device;
- ne->class_dev.class = &nodemgr_ne_class;
- snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx",
- (unsigned long long)(ne->guid));
+ ne->node_dev.parent = &ne->device;
+ ne->node_dev.class = &nodemgr_ne_class;
+ snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx",
+ (unsigned long long)(ne->guid));
if (device_register(&ne->device))
goto fail_devreg;
- if (class_device_register(&ne->class_dev))
+ if (device_register(&ne->node_dev))
goto fail_classdevreg;
get_device(&ne->device);
@@ -885,12 +886,12 @@ fail_alloc:
static struct node_entry *find_entry_by_guid(u64 guid)
{
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne, *ret_ne = NULL;
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->guid == guid) {
ret_ne = ne;
@@ -906,12 +907,12 @@ static struct node_entry *find_entry_by_guid(u64 guid)
static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
nodeid_t nodeid)
{
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne, *ret_ne = NULL;
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->host == host && ne->nodeid == nodeid) {
ret_ne = ne;
@@ -935,14 +936,14 @@ static void nodemgr_register_device(struct node_entry *ne,
snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id);
- ud->class_dev.dev = &ud->device;
- ud->class_dev.class = &nodemgr_ud_class;
- snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
+ ud->unit_dev.parent = &ud->device;
+ ud->unit_dev.class = &nodemgr_ud_class;
+ snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u",
ne->device.bus_id, ud->id);
if (device_register(&ud->device))
goto fail_devreg;
- if (class_device_register(&ud->class_dev))
+ if (device_register(&ud->unit_dev))
goto fail_classdevreg;
get_device(&ud->device);
@@ -976,7 +977,8 @@ static struct unit_directory *nodemgr_process_unit_directory
ud->ne = ne;
ud->ignore_driver = ignore_drivers;
- ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE;
+ ud->address = ud_kv->offset + CSR1212_REGISTER_SPACE_BASE;
+ ud->directory_id = ud->address & 0xffffff;
ud->ud_kv = ud_kv;
ud->id = (*id)++;
@@ -1085,6 +1087,10 @@ static struct unit_directory *nodemgr_process_unit_directory
break;
+ case CSR1212_KV_ID_DIRECTORY_ID:
+ ud->directory_id = kv->value.immediate;
+ break;
+
default:
break;
}
@@ -1154,7 +1160,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
#ifdef CONFIG_HOTPLUG
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct unit_directory *ud;
@@ -1164,10 +1170,10 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
/* ieee1394:venNmoNspNverN */
char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
- if (!cdev)
+ if (!dev)
return -ENODEV;
- ud = container_of(cdev, struct unit_directory, class_dev);
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne->in_limbo || ud->ignore_driver)
return -ENODEV;
@@ -1202,7 +1208,7 @@ do { \
#else
-static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
+static int nodemgr_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
return -ENODEV;
@@ -1373,8 +1379,10 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
static void nodemgr_suspend_ne(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
+ int error;
HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]",
NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
@@ -1383,15 +1391,24 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver &&
- (!ud->device.driver->suspend ||
- ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ error = 1; /* release if suspend is not implemented */
+ if (drv->suspend) {
+ down(&ud->device.sem);
+ error = drv->suspend(&ud->device, PMSG_SUSPEND);
+ up(&ud->device.sem);
+ }
+ if (error)
device_release_driver(&ud->device);
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
}
@@ -1399,20 +1416,29 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
static void nodemgr_resume_ne(struct node_entry *ne)
{
- struct class_device *cdev;
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
ne->in_limbo = 0;
device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver && ud->device.driver->resume)
- ud->device.driver->resume(&ud->device);
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ if (drv->resume) {
+ down(&ud->device.sem);
+ drv->resume(&ud->device);
+ up(&ud->device.sem);
+ }
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
@@ -1423,23 +1449,32 @@ static void nodemgr_resume_ne(struct node_entry *ne)
static void nodemgr_update_pdrv(struct node_entry *ne)
{
+ struct device *dev;
struct unit_directory *ud;
+ struct device_driver *drv;
struct hpsb_protocol_driver *pdrv;
- struct class_device *cdev;
+ int error;
down(&nodemgr_ud_class.sem);
- list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {
- ud = container_of(cdev, struct unit_directory, class_dev);
+ list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+ ud = container_of(dev, struct unit_directory, unit_dev);
if (ud->ne != ne)
continue;
- if (ud->device.driver) {
- pdrv = container_of(ud->device.driver,
- struct hpsb_protocol_driver,
- driver);
- if (pdrv->update && pdrv->update(ud))
- device_release_driver(&ud->device);
+ drv = get_driver(ud->device.driver);
+ if (!drv)
+ continue;
+
+ error = 0;
+ pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
+ if (pdrv->update) {
+ down(&ud->device.sem);
+ error = pdrv->update(ud);
+ up(&ud->device.sem);
}
+ if (error)
+ device_release_driver(&ud->device);
+ put_driver(drv);
}
up(&nodemgr_ud_class.sem);
}
@@ -1504,7 +1539,7 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
static void nodemgr_node_probe(struct host_info *hi, int generation)
{
struct hpsb_host *host = hi->host;
- struct class_device *cdev;
+ struct device *dev;
struct node_entry *ne;
/* Do some processing of the nodes we've probed. This pulls them
@@ -1517,13 +1552,13 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
* improvement...) */
down(&nodemgr_ne_class.sem);
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (!ne->needs_probe)
nodemgr_probe_ne(hi, ne, generation);
}
- list_for_each_entry(cdev, &nodemgr_ne_class.children, node) {
- ne = container_of(cdev, struct node_entry, class_dev);
+ list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+ ne = container_of(dev, struct node_entry, node_dev);
if (ne->needs_probe)
nodemgr_probe_ne(hi, ne, generation);
}
@@ -1681,18 +1716,12 @@ static int nodemgr_host_thread(void *__hi)
if (kthread_should_stop())
goto exit;
- if (mutex_lock_interruptible(&nodemgr_serialize)) {
- if (try_to_freeze())
- continue;
- goto exit;
- }
-
/* Pause for 1/4 second in 1/16 second intervals,
* to make sure things settle down. */
g = get_hpsb_generation(host);
for (i = 0; i < 4 ; i++) {
if (msleep_interruptible(63) || kthread_should_stop())
- goto unlock_exit;
+ goto exit;
/* Now get the generation in which the node ID's we collect
* are valid. During the bus scan we will use this generation
@@ -1710,7 +1739,6 @@ static int nodemgr_host_thread(void *__hi)
if (!nodemgr_check_irm_capability(host, reset_cycles) ||
!nodemgr_do_irm_duties(host, reset_cycles)) {
reset_cycles++;
- mutex_unlock(&nodemgr_serialize);
continue;
}
reset_cycles = 0;
@@ -1727,11 +1755,7 @@ static int nodemgr_host_thread(void *__hi)
/* Update some of our sysfs symlinks */
nodemgr_update_host_dev_links(host);
-
- mutex_unlock(&nodemgr_serialize);
}
-unlock_exit:
- mutex_unlock(&nodemgr_serialize);
exit:
HPSB_VERBOSE("NodeMgr: Exiting thread");
return 0;
@@ -1751,13 +1775,13 @@ exit:
*/
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
{
- struct class_device *cdev;
+ struct device *dev;
struct hpsb_host *host;
int error = 0;
down(&hpsb_host_class.sem);
- list_for_each_entry(cdev, &hpsb_host_class.children, node) {
- host = container_of(cdev, struct hpsb_host, class_dev);
+ list_for_each_entry(dev, &hpsb_host_class.devices, node) {
+ host = container_of(dev, struct hpsb_host, host_dev);
if ((error = cb(host, data)))
break;
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
index e7ac683c72c..919e92e2a95 100644
--- a/drivers/ieee1394/nodemgr.h
+++ b/drivers/ieee1394/nodemgr.h
@@ -75,6 +75,7 @@ struct unit_directory {
struct csr1212_keyval *model_name_kv;
quadlet_t specifier_id;
quadlet_t version;
+ quadlet_t directory_id;
unsigned int id;
@@ -83,7 +84,7 @@ struct unit_directory {
int length; /* Number of quadlets */
struct device device;
- struct class_device class_dev;
+ struct device unit_dev;
struct csr1212_keyval *ud_kv;
u32 lun; /* logical unit number immediate value */
@@ -106,7 +107,7 @@ struct node_entry {
u32 capabilities;
struct device device;
- struct class_device class_dev;
+ struct device node_dev;
/* Means this node is not attached anymore */
int in_limbo;
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 5dadfd296f7..5667c8102ef 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -138,19 +138,6 @@ printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->
#define DBGMSG(fmt, args...) do {} while (0)
#endif
-#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG
-#define OHCI_DMA_ALLOC(fmt, args...) \
- HPSB_ERR("%s(%s)alloc(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
- ++global_outstanding_dmas, ## args)
-#define OHCI_DMA_FREE(fmt, args...) \
- HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \
- --global_outstanding_dmas, ## args)
-static int global_outstanding_dmas = 0;
-#else
-#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0)
-#define OHCI_DMA_FREE(fmt, args...) do {} while (0)
-#endif
-
/* print general (card independent) information */
#define PRINT_G(level, fmt, args...) \
printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
@@ -170,7 +157,6 @@ static void dma_trm_reset(struct dma_trm_ctx *d);
static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
enum context_type type, int ctx, int num_desc,
int buf_size, int split_buf_size, int context_base);
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
@@ -533,9 +519,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
initialize_dma_trm_ctx(&ohci->at_req_context);
initialize_dma_trm_ctx(&ohci->at_resp_context);
- /* Initialize IR Legacy DMA channel mask */
- ohci->ir_legacy_channels = 0;
-
/* Accept AR requests from all nodes */
reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
@@ -733,7 +716,6 @@ static void insert_packet(struct ti_ohci *ohci,
pci_map_single(ohci->dev, packet->data,
packet->data_size,
PCI_DMA_TODEVICE));
- OHCI_DMA_ALLOC("single, block transmit packet");
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
@@ -783,7 +765,6 @@ static void insert_packet(struct ti_ohci *ohci,
d->prg_cpu[idx]->end.address = cpu_to_le32(
pci_map_single(ohci->dev, packet->data,
packet->data_size, PCI_DMA_TODEVICE));
- OHCI_DMA_ALLOC("single, iso transmit packet");
d->prg_cpu[idx]->end.branchAddress = 0;
d->prg_cpu[idx]->end.status = 0;
@@ -884,36 +865,9 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
return -EOVERFLOW;
}
- /* Decide whether we have an iso, a request, or a response packet */
if (packet->type == hpsb_raw)
d = &ohci->at_req_context;
- else if ((packet->tcode == TCODE_ISO_DATA) && (packet->type == hpsb_iso)) {
- /* The legacy IT DMA context is initialized on first
- * use. However, the alloc cannot be run from
- * interrupt context, so we bail out if that is the
- * case. I don't see anyone sending ISO packets from
- * interrupt context anyway... */
-
- if (ohci->it_legacy_context.ohci == NULL) {
- if (in_interrupt()) {
- PRINT(KERN_ERR,
- "legacy IT context cannot be initialized during interrupt");
- return -EINVAL;
- }
-
- if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context,
- DMA_CTX_ISO, 0, IT_NUM_DESC,
- OHCI1394_IsoXmitContextBase) < 0) {
- PRINT(KERN_ERR,
- "error initializing legacy IT context");
- return -ENOMEM;
- }
-
- initialize_dma_trm_ctx(&ohci->it_legacy_context);
- }
-
- d = &ohci->it_legacy_context;
- } else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
+ else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
d = &ohci->at_resp_context;
else
d = &ohci->at_req_context;
@@ -932,9 +886,7 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
{
struct ti_ohci *ohci = host->hostdata;
- int retval = 0;
- unsigned long flags;
- int phy_reg;
+ int retval = 0, phy_reg;
switch (cmd) {
case RESET_BUS:
@@ -1027,117 +979,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
dma_trm_reset(&ohci->at_resp_context);
break;
- case ISO_LISTEN_CHANNEL:
- {
- u64 mask;
- struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
- int ir_legacy_active;
-
- if (arg<0 || arg>63) {
- PRINT(KERN_ERR,
- "%s: IS0 listen channel %d is out of range",
- __FUNCTION__, arg);
- return -EFAULT;
- }
-
- mask = (u64)0x1<<arg;
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (ohci->ISO_channel_usage & mask) {
- PRINT(KERN_ERR,
- "%s: IS0 listen channel %d is already used",
- __FUNCTION__, arg);
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- return -EFAULT;
- }
-
- ir_legacy_active = ohci->ir_legacy_channels;
-
- ohci->ISO_channel_usage |= mask;
- ohci->ir_legacy_channels |= mask;
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
-
- if (!ir_legacy_active) {
- if (ohci1394_register_iso_tasklet(ohci,
- &ohci->ir_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, "No IR DMA context available");
- return -EBUSY;
- }
-
- /* the IR context can be assigned to any DMA context
- * by ohci1394_register_iso_tasklet */
- d->ctx = ohci->ir_legacy_tasklet.context;
- d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
- 32*d->ctx;
- d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
- 32*d->ctx;
- d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
- d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
-
- initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
- if (printk_ratelimit())
- DBGMSG("IR legacy activated");
- }
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (arg>31)
- reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
- 1<<(arg-32));
- else
- reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
- 1<<arg);
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- DBGMSG("Listening enabled on channel %d", arg);
- break;
- }
- case ISO_UNLISTEN_CHANNEL:
- {
- u64 mask;
-
- if (arg<0 || arg>63) {
- PRINT(KERN_ERR,
- "%s: IS0 unlisten channel %d is out of range",
- __FUNCTION__, arg);
- return -EFAULT;
- }
-
- mask = (u64)0x1<<arg;
-
- spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-
- if (!(ohci->ISO_channel_usage & mask)) {
- PRINT(KERN_ERR,
- "%s: IS0 unlisten channel %d is not used",
- __FUNCTION__, arg);
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- return -EFAULT;
- }
-
- ohci->ISO_channel_usage &= ~mask;
- ohci->ir_legacy_channels &= ~mask;
-
- if (arg>31)
- reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear,
- 1<<(arg-32));
- else
- reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear,
- 1<<arg);
-
- spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
- DBGMSG("Listening disabled on channel %d", arg);
-
- if (ohci->ir_legacy_channels == 0) {
- stop_dma_rcv_ctx(&ohci->ir_legacy_context);
- DBGMSG("ISO legacy receive context stopped");
- }
-
- break;
- }
default:
PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
cmd);
@@ -2869,12 +2710,10 @@ static void dma_trm_tasklet (unsigned long data)
list_del_init(&packet->driver_list);
hpsb_packet_sent(ohci->host, packet, ack);
- if (datasize) {
+ if (datasize)
pci_unmap_single(ohci->dev,
cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
datasize, PCI_DMA_TODEVICE);
- OHCI_DMA_FREE("single Xmit data packet");
- }
d->sent_ind = (d->sent_ind+1)%d->num_desc;
d->free_prgs++;
@@ -2885,22 +2724,6 @@ static void dma_trm_tasklet (unsigned long data)
spin_unlock_irqrestore(&d->lock, flags);
}
-static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d)
-{
- if (d->ctrlClear) {
- ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
-
- if (d->type == DMA_CTX_ISO) {
- /* disable interrupts */
- reg_write(d->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << d->ctx);
- ohci1394_unregister_iso_tasklet(d->ohci, &d->ohci->ir_legacy_tasklet);
- } else {
- tasklet_kill(&d->task);
- }
- }
-}
-
-
static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
{
int i;
@@ -2913,23 +2736,19 @@ static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
if (d->buf_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->buf_cpu[i] && d->buf_bus[i]) {
+ if (d->buf_cpu[i] && d->buf_bus[i])
pci_free_consistent(
ohci->dev, d->buf_size,
d->buf_cpu[i], d->buf_bus[i]);
- OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i);
- }
kfree(d->buf_cpu);
kfree(d->buf_bus);
}
if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->prg_cpu[i] && d->prg_bus[i]) {
- pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
- OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i);
- }
+ if (d->prg_cpu[i] && d->prg_bus[i])
+ pci_pool_free(d->prg_pool, d->prg_cpu[i],
+ d->prg_bus[i]);
pci_pool_destroy(d->prg_pool);
- OHCI_DMA_FREE("dma_rcv prg pool");
kfree(d->prg_cpu);
kfree(d->prg_bus);
}
@@ -2998,13 +2817,10 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
}
num_allocs++;
- OHCI_DMA_ALLOC("dma_rcv prg pool");
-
for (i=0; i<d->num_desc; i++) {
d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
d->buf_size,
d->buf_bus+i);
- OHCI_DMA_ALLOC("consistent dma_rcv buf[%d]", i);
if (d->buf_cpu[i] != NULL) {
memset(d->buf_cpu[i], 0, d->buf_size);
@@ -3016,7 +2832,6 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
}
d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
- OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i);
if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
@@ -3030,18 +2845,11 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
spin_lock_init(&d->lock);
- if (type == DMA_CTX_ISO) {
- ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
- OHCI_ISO_MULTICHANNEL_RECEIVE,
- dma_rcv_tasklet, (unsigned long) d);
- } else {
- d->ctrlSet = context_base + OHCI1394_ContextControlSet;
- d->ctrlClear = context_base + OHCI1394_ContextControlClear;
- d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-
- tasklet_init (&d->task, dma_rcv_tasklet, (unsigned long) d);
- }
+ d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+ d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+ d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+ tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
return 0;
}
@@ -3057,12 +2865,10 @@ static void free_dma_trm_ctx(struct dma_trm_ctx *d)
if (d->prg_cpu) {
for (i=0; i<d->num_desc; i++)
- if (d->prg_cpu[i] && d->prg_bus[i]) {
- pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
- OHCI_DMA_FREE("pool dma_trm prg[%d]", i);
- }
+ if (d->prg_cpu[i] && d->prg_bus[i])
+ pci_pool_free(d->prg_pool, d->prg_cpu[i],
+ d->prg_bus[i]);
pci_pool_destroy(d->prg_pool);
- OHCI_DMA_FREE("dma_trm prg pool");
kfree(d->prg_cpu);
kfree(d->prg_bus);
}
@@ -3108,11 +2914,8 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
}
num_allocs++;
- OHCI_DMA_ALLOC("dma_rcv prg pool");
-
for (i = 0; i < d->num_desc; i++) {
d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
- OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i);
if (d->prg_cpu[i] != NULL) {
memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
@@ -3127,28 +2930,10 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
spin_lock_init(&d->lock);
/* initialize tasklet */
- if (type == DMA_CTX_ISO) {
- ohci1394_init_iso_tasklet(&ohci->it_legacy_tasklet, OHCI_ISO_TRANSMIT,
- dma_trm_tasklet, (unsigned long) d);
- if (ohci1394_register_iso_tasklet(ohci,
- &ohci->it_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, "No IT DMA context available");
- free_dma_trm_ctx(d);
- return -EBUSY;
- }
-
- /* IT can be assigned to any context by register_iso_tasklet */
- d->ctx = ohci->it_legacy_tasklet.context;
- d->ctrlSet = OHCI1394_IsoXmitContextControlSet + 16 * d->ctx;
- d->ctrlClear = OHCI1394_IsoXmitContextControlClear + 16 * d->ctx;
- d->cmdPtr = OHCI1394_IsoXmitCommandPtr + 16 * d->ctx;
- } else {
- d->ctrlSet = context_base + OHCI1394_ContextControlSet;
- d->ctrlClear = context_base + OHCI1394_ContextControlClear;
- d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
- tasklet_init (&d->task, dma_trm_tasklet, (unsigned long)d);
- }
-
+ d->ctrlSet = context_base + OHCI1394_ContextControlSet;
+ d->ctrlClear = context_base + OHCI1394_ContextControlClear;
+ d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
+ tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
return 0;
}
@@ -3294,7 +3079,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->csr_config_rom_cpu =
pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
&ohci->csr_config_rom_bus);
- OHCI_DMA_ALLOC("consistent csr_config_rom");
if (ohci->csr_config_rom_cpu == NULL)
FAIL(-ENOMEM, "Failed to allocate buffer config rom");
ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
@@ -3303,8 +3087,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->selfid_buf_cpu =
pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
&ohci->selfid_buf_bus);
- OHCI_DMA_ALLOC("consistent selfid_buf");
-
if (ohci->selfid_buf_cpu == NULL)
FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets");
ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
@@ -3377,20 +3159,6 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
ohci->ISO_channel_usage = 0;
spin_lock_init(&ohci->IR_channel_lock);
- /* Allocate the IR DMA context right here so we don't have
- * to do it in interrupt path - note that this doesn't
- * waste much memory and avoids the jugglery required to
- * allocate it in IRQ path. */
- if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
- DMA_CTX_ISO, 0, IR_NUM_DESC,
- IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
- OHCI1394_IsoRcvContextBase) < 0) {
- FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
- }
-
- /* We hopefully don't have to pre-allocate IT DMA like we did
- * for IR DMA above. Allocate it on-demand and mark inactive. */
- ohci->it_legacy_context.ohci = NULL;
spin_lock_init(&ohci->event_lock);
/*
@@ -3483,20 +3251,16 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
free_dma_rcv_ctx(&ohci->ar_resp_context);
free_dma_trm_ctx(&ohci->at_req_context);
free_dma_trm_ctx(&ohci->at_resp_context);
- free_dma_rcv_ctx(&ohci->ir_legacy_context);
- free_dma_trm_ctx(&ohci->it_legacy_context);
case OHCI_INIT_HAVE_SELFID_BUFFER:
pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
ohci->selfid_buf_cpu,
ohci->selfid_buf_bus);
- OHCI_DMA_FREE("consistent selfid_buf");
case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
ohci->csr_config_rom_cpu,
ohci->csr_config_rom_bus);
- OHCI_DMA_FREE("consistent csr_config_rom");
case OHCI_INIT_HAVE_IOMAPPING:
iounmap(ohci->registers);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index f1ad539e7c1..4320bf01049 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -190,23 +190,10 @@ struct ti_ohci {
unsigned long ir_multichannel_used; /* ditto */
spinlock_t IR_channel_lock;
- /* iso receive (legacy API) */
- u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
- it only accounts for channels listened to
- by the legacy API, so that we can know when
- it is safe to free the legacy API context */
-
- struct dma_rcv_ctx ir_legacy_context;
- struct ohci1394_iso_tasklet ir_legacy_tasklet;
-
/* iso transmit */
int nb_iso_xmit_ctx;
unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
- /* iso transmit (legacy API) */
- struct dma_trm_ctx it_legacy_context;
- struct ohci1394_iso_tasklet it_legacy_tasklet;
-
u64 ISO_channel_usage;
/* IEEE-1394 part follows */
@@ -221,7 +208,6 @@ struct ti_ohci {
/* Tasklets for iso receive and transmit, used by video1394
* and dv1394 */
-
struct list_head iso_tasklet_list;
spinlock_t iso_tasklet_list_lock;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 0742befe922..d1a5bcdb5e0 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -477,7 +477,11 @@ static void send_next(struct ti_lynx *lynx, int what)
struct lynx_send_data *d;
struct hpsb_packet *packet;
+#if 0 /* has been removed from ieee1394 core */
d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
+#else
+ d = &lynx->async;
+#endif
if (!list_empty(&d->pcl_queue)) {
PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
BUG();
@@ -511,9 +515,11 @@ static void send_next(struct ti_lynx *lynx, int what)
case hpsb_async:
pcl.buffer[0].control |= PCL_CMD_XMT;
break;
+#if 0 /* has been removed from ieee1394 core */
case hpsb_iso:
pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
break;
+#endif
case hpsb_raw:
pcl.buffer[0].control |= PCL_CMD_UNFXMT;
break;
@@ -542,9 +548,11 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
case hpsb_raw:
d = &lynx->async;
break;
+#if 0 /* has been removed from ieee1394 core */
case hpsb_iso:
d = &lynx->iso_send;
break;
+#endif
default:
PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
packet->type);
@@ -797,7 +805,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
}
break;
-
+#if 0 /* has been removed from ieee1394 core */
case ISO_LISTEN_CHANNEL:
spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
@@ -819,7 +827,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
break;
-
+#endif
default:
PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
retval = -1;
@@ -1009,11 +1017,11 @@ static irqreturn_t lynx_irq_handler(int irq, void *dev_id)
pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
packet->data_size, PCI_DMA_TODEVICE);
}
-
+#if 0 /* has been removed from ieee1394 core */
if (!list_empty(&lynx->iso_send.queue)) {
send_next(lynx, hpsb_iso);
}
-
+#endif
spin_unlock(&lynx->iso_send.queue_lock);
if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
index 50daabf6e5f..a06aaad5b44 100644
--- a/drivers/ieee1394/raw1394-private.h
+++ b/drivers/ieee1394/raw1394-private.h
@@ -36,11 +36,6 @@ struct file_info {
u8 __user *fcp_buffer;
- /* old ISO API */
- u64 listen_channels;
- quadlet_t __user *iso_buffer;
- size_t iso_buffer_length;
-
u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
/* new rawiso API */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index f1d05eeb9f5..336e5ff4cfc 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -98,21 +98,6 @@ static struct hpsb_address_ops arm_ops = {
static void queue_complete_cb(struct pending_request *req);
-#include <asm/current.h>
-static void print_old_iso_deprecation(void)
-{
- static pid_t p;
-
- if (p == current->pid)
- return;
- p = current->pid;
- printk(KERN_WARNING "raw1394: WARNING - Program \"%s\" uses unsupported"
- " isochronous request types which will be removed in a next"
- " kernel release\n", current->comm);
- printk(KERN_WARNING "raw1394: Update your software to use libraw1394's"
- " newer interface\n");
-}
-
static struct pending_request *__alloc_pending_request(gfp_t flags)
{
struct pending_request *req;
@@ -297,67 +282,6 @@ static void host_reset(struct hpsb_host *host)
spin_unlock_irqrestore(&host_info_lock, flags);
}
-static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
- size_t length)
-{
- unsigned long flags;
- struct host_info *hi;
- struct file_info *fi;
- struct pending_request *req, *req_next;
- struct iso_block_store *ibs = NULL;
- LIST_HEAD(reqs);
-
- if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
- HPSB_INFO("dropped iso packet");
- return;
- }
-
- spin_lock_irqsave(&host_info_lock, flags);
- hi = find_host_info(host);
-
- if (hi != NULL) {
- list_for_each_entry(fi, &hi->file_info_list, list) {
- if (!(fi->listen_channels & (1ULL << channel)))
- continue;
-
- req = __alloc_pending_request(GFP_ATOMIC);
- if (!req)
- break;
-
- if (!ibs) {
- ibs = kmalloc(sizeof(*ibs) + length,
- GFP_ATOMIC);
- if (!ibs) {
- kfree(req);
- break;
- }
-
- atomic_add(length, &iso_buffer_size);
- atomic_set(&ibs->refcount, 0);
- ibs->data_size = length;
- memcpy(ibs->data, data, length);
- }
-
- atomic_inc(&ibs->refcount);
-
- req->file_info = fi;
- req->ibs = ibs;
- req->data = ibs->data;
- req->req.type = RAW1394_REQ_ISO_RECEIVE;
- req->req.generation = get_hpsb_generation(host);
- req->req.misc = 0;
- req->req.recvb = ptr2int(fi->iso_buffer);
- req->req.length = min(length, fi->iso_buffer_length);
-
- list_add_tail(&req->list, &reqs);
- }
- }
- spin_unlock_irqrestore(&host_info_lock, flags);
-
- list_for_each_entry_safe(req, req_next, &reqs, list)
- queue_complete_req(req);
-}
-
static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
int cts, u8 * data, size_t length)
{
@@ -434,7 +358,11 @@ struct compat_raw1394_req {
__u64 sendb;
__u64 recvb;
-} __attribute__((packed));
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
static const char __user *raw1394_compat_write(const char __user *buf)
{
@@ -459,7 +387,7 @@ static const char __user *raw1394_compat_write(const char __user *buf)
static int
raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
{
- struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+ struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
P(type) ||
P(error) ||
@@ -587,7 +515,7 @@ static int state_opened(struct file_info *fi, struct pending_request *req)
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
static int state_initialized(struct file_info *fi, struct pending_request *req)
@@ -601,7 +529,7 @@ static int state_initialized(struct file_info *fi, struct pending_request *req)
req->req.generation = atomic_read(&internal_generation);
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
switch (req->req.type) {
@@ -673,44 +601,7 @@ out_set_card:
}
queue_complete_req(req);
- return sizeof(struct raw1394_request);
-}
-
-static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
-{
- int channel = req->req.misc;
-
- if ((channel > 63) || (channel < -64)) {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- } else if (channel >= 0) {
- /* allocate channel req.misc */
- if (fi->listen_channels & (1ULL << channel)) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- if (hpsb_listen_channel
- (&raw1394_highlevel, fi->host, channel)) {
- req->req.error = RAW1394_ERROR_ALREADY;
- } else {
- fi->listen_channels |= 1ULL << channel;
- fi->iso_buffer = int2ptr(req->req.recvb);
- fi->iso_buffer_length = req->req.length;
- }
- }
- } else {
- /* deallocate channel (one's complement neg) req.misc */
- channel = ~channel;
-
- if (fi->listen_channels & (1ULL << channel)) {
- hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
- channel);
- fi->listen_channels &= ~(1ULL << channel);
- } else {
- req->req.error = RAW1394_ERROR_INVALID_ARG;
- }
- }
-
- req->req.length = 0;
- queue_complete_req(req);
+ return 0;
}
static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
@@ -865,7 +756,7 @@ static int handle_async_request(struct file_info *fi,
if (req->req.error) {
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
hpsb_set_packet_complete_task(packet,
@@ -883,51 +774,7 @@ static int handle_async_request(struct file_info *fi,
hpsb_free_tlabel(packet);
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
-}
-
-static int handle_iso_send(struct file_info *fi, struct pending_request *req,
- int channel)
-{
- unsigned long flags;
- struct hpsb_packet *packet;
-
- packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
- (req->req.misc >> 16) & 0x3,
- req->req.misc & 0xf);
- if (!packet)
- return -ENOMEM;
-
- packet->speed_code = req->req.address & 0x3;
-
- req->packet = packet;
-
- if (copy_from_user(packet->data, int2ptr(req->req.sendb),
- req->req.length)) {
- req->req.error = RAW1394_ERROR_MEMFAULT;
- req->req.length = 0;
- queue_complete_req(req);
- return sizeof(struct raw1394_request);
- }
-
- req->req.length = 0;
- hpsb_set_packet_complete_task(packet,
- (void (*)(void *))queue_complete_req,
- req);
-
- spin_lock_irqsave(&fi->reqlists_lock, flags);
- list_add_tail(&req->list, &fi->req_pending);
- spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
- /* Update the generation of the packet just before sending. */
- packet->generation = req->req.generation;
-
- if (hpsb_send_packet(packet) < 0) {
- req->req.error = RAW1394_ERROR_SEND_ERROR;
- queue_complete_req(req);
- }
-
- return sizeof(struct raw1394_request);
+ return 0;
}
static int handle_async_send(struct file_info *fi, struct pending_request *req)
@@ -943,7 +790,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_INVALID_ARG;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
data_size = req->req.length - header_length;
@@ -957,7 +804,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
if (copy_from_user
@@ -966,7 +813,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
req->req.error = RAW1394_ERROR_MEMFAULT;
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
packet->type = hpsb_async;
@@ -994,7 +841,7 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
+ return 0;
}
static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
@@ -1869,7 +1716,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
spin_lock_irqsave(&host_info_lock, flags);
list_add_tail(&addr->addr_list, &fi->addr_list);
spin_unlock_irqrestore(&host_info_lock, flags);
- return sizeof(struct raw1394_request);
+ return 0;
}
retval =
hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
@@ -1887,7 +1734,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
return (-EALREADY);
}
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
static int arm_unregister(struct file_info *fi, struct pending_request *req)
@@ -1955,7 +1802,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
vfree(addr->addr_space_buffer);
kfree(addr);
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
retval =
hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
@@ -1971,7 +1818,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
vfree(addr->addr_space_buffer);
kfree(addr);
free_pending_request(req); /* immediate success or fail */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* Copy data from ARM buffer(s) to user buffer. */
@@ -2013,7 +1860,7 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req)
* queue no response, and therefore nobody
* will free it. */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
DBGMSG("arm_get_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2065,7 +1912,7 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req)
* queue no response, and therefore nobody
* will free it. */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
DBGMSG("arm_set_buf request exceeded mapping");
spin_unlock_irqrestore(&host_info_lock, flags);
@@ -2086,7 +1933,7 @@ static int reset_notification(struct file_info *fi, struct pending_request *req)
(req->req.misc == RAW1394_NOTIFY_ON)) {
fi->notification = (u8) req->req.misc;
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* error EINVAL (22) invalid argument */
return (-EINVAL);
@@ -2119,12 +1966,12 @@ static int write_phypacket(struct file_info *fi, struct pending_request *req)
req->req.length = 0;
queue_complete_req(req);
}
- return sizeof(struct raw1394_request);
+ return 0;
}
static int get_config_rom(struct file_info *fi, struct pending_request *req)
{
- int ret = sizeof(struct raw1394_request);
+ int ret = 0;
quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
int status;
@@ -2154,7 +2001,7 @@ static int get_config_rom(struct file_info *fi, struct pending_request *req)
static int update_config_rom(struct file_info *fi, struct pending_request *req)
{
- int ret = sizeof(struct raw1394_request);
+ int ret = 0;
quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -2221,7 +2068,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
hpsb_update_config_rom_image(fi->host);
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
}
@@ -2286,7 +2133,7 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req)
/* we have to free the request, because we queue no response,
* and therefore nobody will free it */
free_pending_request(req);
- return sizeof(struct raw1394_request);
+ return 0;
} else {
for (dentry =
fi->csr1212_dirs[dr]->value.directory.dentries_head;
@@ -2311,11 +2158,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_ECHO:
queue_complete_req(req);
- return sizeof(struct raw1394_request);
-
- case RAW1394_REQ_ISO_SEND:
- print_old_iso_deprecation();
- return handle_iso_send(fi, req, node);
+ return 0;
case RAW1394_REQ_ARM_REGISTER:
return arm_register(fi, req);
@@ -2332,27 +2175,30 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
case RAW1394_REQ_RESET_NOTIFY:
return reset_notification(fi, req);
+ case RAW1394_REQ_ISO_SEND:
case RAW1394_REQ_ISO_LISTEN:
- print_old_iso_deprecation();
- handle_iso_listen(fi, req);
- return sizeof(struct raw1394_request);
+ printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
+ req->req.error = RAW1394_ERROR_COMPAT;
+ req->req.misc = RAW1394_KERNELAPI_VERSION;
+ queue_complete_req(req);
+ return 0;
case RAW1394_REQ_FCP_LISTEN:
handle_fcp_listen(fi, req);
- return sizeof(struct raw1394_request);
+ return 0;
case RAW1394_REQ_RESET_BUS:
if (req->req.misc == RAW1394_LONG_RESET) {
DBGMSG("busreset called (type: LONG)");
hpsb_reset_bus(fi->host, LONG_RESET);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
if (req->req.misc == RAW1394_SHORT_RESET) {
DBGMSG("busreset called (type: SHORT)");
hpsb_reset_bus(fi->host, SHORT_RESET);
free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
- return sizeof(struct raw1394_request);
+ return 0;
}
/* error EINVAL (22) invalid argument */
return (-EINVAL);
@@ -2371,7 +2217,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
req->req.generation = get_hpsb_generation(fi->host);
req->req.length = 0;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
switch (req->req.type) {
@@ -2384,7 +2230,7 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
if (req->req.length == 0) {
req->req.error = RAW1394_ERROR_INVALID_ARG;
queue_complete_req(req);
- return sizeof(struct raw1394_request);
+ return 0;
}
return handle_async_request(fi, req, node);
@@ -2395,7 +2241,7 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
{
struct file_info *fi = (struct file_info *)file->private_data;
struct pending_request *req;
- ssize_t retval = 0;
+ ssize_t retval = -EBADFD;
#ifdef CONFIG_COMPAT
if (count == sizeof(struct compat_raw1394_req) &&
@@ -2437,6 +2283,9 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer,
if (retval < 0) {
free_pending_request(req);
+ } else {
+ BUG_ON(retval);
+ retval = count;
}
return retval;
@@ -2802,6 +2651,103 @@ static int raw1394_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
}
+#ifdef CONFIG_COMPAT
+struct raw1394_iso_packets32 {
+ __u32 n_packets;
+ compat_uptr_t infos;
+} __attribute__((packed));
+
+struct raw1394_cycle_timer32 {
+ __u32 cycle_timer;
+ __u64 local_time;
+}
+#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
+__attribute__((packed))
+#endif
+;
+
+#define RAW1394_IOC_ISO_RECV_PACKETS32 \
+ _IOW ('#', 0x25, struct raw1394_iso_packets32)
+#define RAW1394_IOC_ISO_XMIT_PACKETS32 \
+ _IOW ('#', 0x27, struct raw1394_iso_packets32)
+#define RAW1394_IOC_GET_CYCLE_TIMER32 \
+ _IOR ('#', 0x30, struct raw1394_cycle_timer32)
+
+static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
+ struct raw1394_iso_packets32 __user *arg)
+{
+ compat_uptr_t infos32;
+ void *infos;
+ long err = -EFAULT;
+ struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
+
+ if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
+ !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
+ infos = compat_ptr(infos32);
+ if (!copy_to_user(&dst->infos, &infos, sizeof infos))
+ err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst);
+ }
+ return err;
+}
+
+static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
+{
+ struct raw1394_cycle_timer32 ct;
+ int err;
+
+ err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
+ if (!err)
+ if (copy_to_user(uaddr, &ct, sizeof(ct)))
+ err = -EFAULT;
+ return err;
+}
+
+static long raw1394_compat_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct file_info *fi = file->private_data;
+ void __user *argp = (void __user *)arg;
+ long err;
+
+ lock_kernel();
+ switch (cmd) {
+ /* These requests have same format as long as 'int' has same size. */
+ case RAW1394_IOC_ISO_RECV_INIT:
+ case RAW1394_IOC_ISO_RECV_START:
+ case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
+ case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
+ case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
+ case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
+ case RAW1394_IOC_ISO_RECV_FLUSH:
+ case RAW1394_IOC_ISO_XMIT_RECV_STOP:
+ case RAW1394_IOC_ISO_XMIT_INIT:
+ case RAW1394_IOC_ISO_XMIT_START:
+ case RAW1394_IOC_ISO_XMIT_SYNC:
+ case RAW1394_IOC_ISO_GET_STATUS:
+ case RAW1394_IOC_ISO_SHUTDOWN:
+ case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
+ err = raw1394_ioctl(NULL, file, cmd, arg);
+ break;
+ /* These request have different format. */
+ case RAW1394_IOC_ISO_RECV_PACKETS32:
+ err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
+ break;
+ case RAW1394_IOC_ISO_XMIT_PACKETS32:
+ err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
+ break;
+ case RAW1394_IOC_GET_CYCLE_TIMER32:
+ err = raw1394_read_cycle_timer32(fi, argp);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+
+ return err;
+}
+#endif
+
static unsigned int raw1394_poll(struct file *file, poll_table * pt)
{
struct file_info *fi = file->private_data;
@@ -2861,14 +2807,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
if (fi->iso_state != RAW1394_ISO_INACTIVE)
raw1394_iso_shutdown(fi);
- for (i = 0; i < 64; i++) {
- if (fi->listen_channels & (1ULL << i)) {
- hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
- }
- }
-
spin_lock_irqsave(&host_info_lock, flags);
- fi->listen_channels = 0;
fail = 0;
/* set address-entries invalid */
@@ -3030,7 +2969,6 @@ static struct hpsb_highlevel raw1394_highlevel = {
.add_host = add_host,
.remove_host = remove_host,
.host_reset = host_reset,
- .iso_receive = iso_receive,
.fcp_request = fcp_request,
};
@@ -3041,7 +2979,9 @@ static const struct file_operations raw1394_fops = {
.write = raw1394_write,
.mmap = raw1394_mmap,
.ioctl = raw1394_ioctl,
- // .compat_ioctl = ... someone needs to do this
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = raw1394_compat_ioctl,
+#endif
.poll = raw1394_poll,
.open = raw1394_open,
.release = raw1394_release,
@@ -3054,9 +2994,9 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
if (IS_ERR
- (class_device_create
- (hpsb_protocol_class, NULL,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+ (device_create(
+ hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
@@ -3083,9 +3023,9 @@ static int __init init_raw1394(void)
goto out;
out_dev:
- class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
out_unreg:
hpsb_unregister_highlevel(&raw1394_highlevel);
out:
@@ -3094,9 +3034,9 @@ static int __init init_raw1394(void)
static void __exit cleanup_raw1394(void)
{
- class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
hpsb_unregister_highlevel(&raw1394_highlevel);
hpsb_unregister_protocol(&raw1394_driver);
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index 7bd22ee1afb..963ac20373d 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -17,11 +17,11 @@
#define RAW1394_REQ_ASYNC_WRITE 101
#define RAW1394_REQ_LOCK 102
#define RAW1394_REQ_LOCK64 103
-#define RAW1394_REQ_ISO_SEND 104
+#define RAW1394_REQ_ISO_SEND 104 /* removed ABI, now a no-op */
#define RAW1394_REQ_ASYNC_SEND 105
#define RAW1394_REQ_ASYNC_STREAM 106
-#define RAW1394_REQ_ISO_LISTEN 200
+#define RAW1394_REQ_ISO_LISTEN 200 /* removed ABI, now a no-op */
#define RAW1394_REQ_FCP_LISTEN 201
#define RAW1394_REQ_RESET_BUS 202
#define RAW1394_REQ_GET_ROM 203
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index ce86ff226a2..e882cb951b4 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -118,14 +118,13 @@ MODULE_PARM_DESC(max_speed, "Force max speed "
"(3 = 800Mb/s, 2 = 400Mb/s, 1 = 200Mb/s, 0 = 100Mb/s)");
/*
- * Set serialize_io to 1 if you'd like only one scsi command sent
- * down to us at a time (debugging). This might be necessary for very
- * badly behaved sbp2 devices.
+ * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
+ * This is and always has been buggy in multiple subtle ways. See above TODOs.
*/
static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, int, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers "
- "(default = 1, faster = 0)");
+module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
+MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
+ "(default = Y, faster but buggy = N)");
/*
* Bump up max_sectors if you'd like to support very large sized
@@ -154,9 +153,9 @@ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
* are possible on OXFW911 and newer Oxsemi bridges.
*/
static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, int, 0644);
+module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
- "(default = 1)");
+ "(default = Y, use N for concurrent initiators)");
/*
* If any of the following workarounds is required for your device to work,
@@ -194,6 +193,27 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
", or a combination)");
+/*
+ * This influences the format of the sysfs attribute
+ * /sys/bus/scsi/devices/.../ieee1394_id.
+ *
+ * The default format is like in older kernels: %016Lx:%d:%d
+ * It contains the target's EUI-64, a number given to the logical unit by
+ * the ieee1394 driver's nodemgr (starting at 0), and the LUN.
+ *
+ * The long format is: %016Lx:%06x:%04x
+ * It contains the target's EUI-64, the unit directory's directory_ID as per
+ * IEEE 1212 clause 7.7.19, and the LUN. This format comes closest to the
+ * format of SBP(-3) target port and logical unit identifier as per SAM (SCSI
+ * Architecture Model) rev.2 to 4 annex A. Therefore and because it is
+ * independent of the implementation of the ieee1394 nodemgr, the longer format
+ * is recommended for future use.
+ */
+static int sbp2_long_sysfs_ieee1394_id;
+module_param_named(long_ieee1394_id, sbp2_long_sysfs_ieee1394_id, bool, 0644);
+MODULE_PARM_DESC(long_ieee1394_id, "8+3+2 bytes format of ieee1394_id in sysfs "
+ "(default = backwards-compatible = N, SAM-conforming = Y)");
+
#define SBP2_INFO(fmt, args...) HPSB_INFO("sbp2: "fmt, ## args)
#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
@@ -2033,8 +2053,14 @@ static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0]))
return 0;
- return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)lu->ne->guid,
- lu->ud->id, ORB_SET_LUN(lu->lun));
+ if (sbp2_long_sysfs_ieee1394_id)
+ return sprintf(buf, "%016Lx:%06x:%04x\n",
+ (unsigned long long)lu->ne->guid,
+ lu->ud->directory_id, ORB_SET_LUN(lu->lun));
+ else
+ return sprintf(buf, "%016Lx:%d:%d\n",
+ (unsigned long long)lu->ne->guid,
+ lu->ud->id, ORB_SET_LUN(lu->lun));
}
MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index 44402b9d82a..333a4bb7674 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -67,7 +67,7 @@ struct sbp2_command_orb {
#define ORB_SET_LUN(v) ((v) & 0xffff)
#define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16)
#define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(v) (((v) & 0x1) << 28)
+#define ORB_SET_EXCLUSIVE(v) ((v) ? 1 << 28 : 0)
#define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff)
#define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16)
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 87ebd0846c3..bd28adfd7af 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1340,9 +1340,9 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
- class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, minor),
- NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
+ device_create(hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, minor),
+ "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
@@ -1351,8 +1351,8 @@ static void video1394_remove_host (struct hpsb_host *host)
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
if (ohci)
- class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
- IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
+ device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
return;
}
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 994decc7bcf..a193dfbf99d 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -1,14 +1,14 @@
-menu "InfiniBand support"
- depends on HAS_IOMEM
-
-config INFINIBAND
- depends on PCI || BROKEN
+menuconfig INFINIBAND
tristate "InfiniBand support"
+ depends on PCI || BROKEN
+ depends on HAS_IOMEM
---help---
Core support for InfiniBand (IB). Make sure to also select
any protocols you wish to use as well as drivers for your
InfiniBand hardware.
+if INFINIBAND
+
config INFINIBAND_USER_MAD
tristate "InfiniBand userspace MAD support"
depends on INFINIBAND
@@ -20,7 +20,6 @@ config INFINIBAND_USER_MAD
config INFINIBAND_USER_ACCESS
tristate "InfiniBand userspace access (verbs and CM)"
- depends on INFINIBAND
---help---
Userspace InfiniBand access support. This enables the
kernel side of userspace verbs and the userspace
@@ -37,7 +36,7 @@ config INFINIBAND_USER_MEM
config INFINIBAND_ADDR_TRANS
bool
- depends on INFINIBAND && INET
+ depends on INET
default y
source "drivers/infiniband/hw/mthca/Kconfig"
@@ -54,4 +53,4 @@ source "drivers/infiniband/ulp/srp/Kconfig"
source "drivers/infiniband/ulp/iser/Kconfig"
-endmenu
+endif # INFINIBAND
diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
index ecd1a3057c6..db2633e4aae 100644
--- a/drivers/infiniband/core/agent.c
+++ b/drivers/infiniband/core/agent.c
@@ -3,7 +3,7 @@
* Copyright (c) 2004, 2005 Infinicon Corporation. All rights reserved.
* Copyright (c) 2004, 2005 Intel Corporation. All rights reserved.
* Copyright (c) 2004, 2005 Topspin Corporation. All rights reserved.
- * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved.
+ * Copyright (c) 2004-2007 Voltaire Corporation. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -34,7 +34,6 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
- * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $
*/
#include <linux/slab.h>
@@ -42,6 +41,7 @@
#include "agent.h"
#include "smi.h"
+#include "mad_priv.h"
#define SPFX "ib_agent: "
@@ -87,8 +87,13 @@ int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
struct ib_mad_send_buf *send_buf;
struct ib_ah *ah;
int ret;
+ struct ib_mad_send_wr_private *mad_send_wr;
+
+ if (device->node_type == RDMA_NODE_IB_SWITCH)
+ port_priv = ib_get_agent_port(device, 0);
+ else
+ port_priv = ib_get_agent_port(device, port_num);
- port_priv = ib_get_agent_port(device, port_num);
if (!port_priv) {
printk(KERN_ERR SPFX "Unable to find port agent\n");
return -ENODEV;
@@ -113,6 +118,14 @@ int agent_send_response(struct ib_mad *mad, struct ib_grh *grh,
memcpy(send_buf->mad, mad, sizeof *mad);
send_buf->ah = ah;
+
+ if (device->node_type == RDMA_NODE_IB_SWITCH) {
+ mad_send_wr = container_of(send_buf,
+ struct ib_mad_send_wr_private,
+ send_buf);
+ mad_send_wr->send_wr.wr.ud.port_num = port_num;
+ }
+
if ((ret = ib_post_send_mad(send_buf, NULL))) {
printk(KERN_ERR SPFX "ib_post_send_mad error:%d\n", ret);
goto err2;
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 40c004a2697..9820c67ba47 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -87,6 +87,7 @@ struct cm_port {
struct cm_device {
struct list_head list;
struct ib_device *device;
+ u8 ack_delay;
struct cm_port port[0];
};
@@ -95,7 +96,7 @@ struct cm_av {
union ib_gid dgid;
struct ib_ah_attr ah_attr;
u16 pkey_index;
- u8 packet_life_time;
+ u8 timeout;
};
struct cm_work {
@@ -154,6 +155,7 @@ struct cm_id_private {
u8 retry_count;
u8 rnr_retry_count;
u8 service_timeout;
+ u8 target_ack_delay;
struct list_head work_list;
atomic_t work_count;
@@ -293,7 +295,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
av->port = port;
ib_init_ah_from_path(cm_dev->device, port->port_num, path,
&av->ah_attr);
- av->packet_life_time = path->packet_life_time;
+ av->timeout = path->packet_life_time + 1;
return 0;
}
@@ -318,12 +320,10 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
static void cm_free_id(__be32 local_id)
{
- unsigned long flags;
-
- spin_lock_irqsave(&cm.lock, flags);
+ spin_lock_irq(&cm.lock);
idr_remove(&cm.local_id_table,
(__force int) (local_id ^ cm.random_id_operand));
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
}
static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
@@ -345,11 +345,10 @@ static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id)
static struct cm_id_private * cm_acquire_id(__be32 local_id, __be32 remote_id)
{
struct cm_id_private *cm_id_priv;
- unsigned long flags;
- spin_lock_irqsave(&cm.lock, flags);
+ spin_lock_irq(&cm.lock);
cm_id_priv = cm_get_id(local_id, remote_id);
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
return cm_id_priv;
}
@@ -646,6 +645,25 @@ static inline int cm_convert_to_ms(int iba_time)
return 1 << max(iba_time - 8, 0);
}
+/*
+ * calculate: 4.096x2^ack_timeout = 4.096x2^ack_delay + 2x4.096x2^life_time
+ * Because of how ack_timeout is stored, adding one doubles the timeout.
+ * To avoid large timeouts, select the max(ack_delay, life_time + 1), and
+ * increment it (round up) only if the other is within 50%.
+ */
+static u8 cm_ack_timeout(u8 ca_ack_delay, u8 packet_life_time)
+{
+ int ack_timeout = packet_life_time + 1;
+
+ if (ack_timeout >= ca_ack_delay)
+ ack_timeout += (ca_ack_delay >= (ack_timeout - 1));
+ else
+ ack_timeout = ca_ack_delay +
+ (ack_timeout >= (ca_ack_delay - 1));
+
+ return min(31, ack_timeout);
+}
+
static void cm_cleanup_timewait(struct cm_timewait_info *timewait_info)
{
if (timewait_info->inserted_remote_id) {
@@ -689,7 +707,7 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv)
* timewait before notifying the user that we've exited timewait.
*/
cm_id_priv->id.state = IB_CM_TIMEWAIT;
- wait_time = cm_convert_to_ms(cm_id_priv->av.packet_life_time + 1);
+ wait_time = cm_convert_to_ms(cm_id_priv->av.timeout);
queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work,
msecs_to_jiffies(wait_time));
cm_id_priv->timewait_info = NULL;
@@ -713,31 +731,30 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
{
struct cm_id_private *cm_id_priv;
struct cm_work *work;
- unsigned long flags;
cm_id_priv = container_of(cm_id, struct cm_id_private, id);
retest:
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
switch (cm_id->state) {
case IB_CM_LISTEN:
cm_id->state = IB_CM_IDLE;
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- spin_lock_irqsave(&cm.lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
+ spin_lock_irq(&cm.lock);
rb_erase(&cm_id_priv->service_node, &cm.listen_service_table);
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
break;
case IB_CM_SIDR_REQ_SENT:
cm_id->state = IB_CM_IDLE;
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
break;
case IB_CM_SIDR_REQ_RCVD:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
break;
case IB_CM_REQ_SENT:
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT,
&cm_id_priv->id.device->node_guid,
sizeof cm_id_priv->id.device->node_guid,
@@ -747,9 +764,9 @@ retest:
if (err == -ENOMEM) {
/* Do not reject to allow future retries. */
cm_reset_to_idle(cm_id_priv);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
} else {
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
NULL, 0, NULL, 0);
}
@@ -762,25 +779,25 @@ retest:
case IB_CM_MRA_REQ_SENT:
case IB_CM_REP_RCVD:
case IB_CM_MRA_REP_SENT:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED,
NULL, 0, NULL, 0);
break;
case IB_CM_ESTABLISHED:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ib_send_cm_dreq(cm_id, NULL, 0);
goto retest;
case IB_CM_DREQ_SENT:
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
cm_enter_timewait(cm_id_priv);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
break;
case IB_CM_DREQ_RCVD:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ib_send_cm_drep(cm_id, NULL, 0);
break;
default:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
break;
}
@@ -912,7 +929,8 @@ static void cm_format_req(struct cm_req_msg *req_msg,
cm_req_set_primary_sl(req_msg, param->primary_path->sl);
cm_req_set_primary_subnet_local(req_msg, 1); /* local only... */
cm_req_set_primary_local_ack_timeout(req_msg,
- min(31, param->primary_path->packet_life_time + 1));
+ cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+ param->primary_path->packet_life_time));
if (param->alternate_path) {
req_msg->alt_local_lid = param->alternate_path->slid;
@@ -927,7 +945,8 @@ static void cm_format_req(struct cm_req_msg *req_msg,
cm_req_set_alt_sl(req_msg, param->alternate_path->sl);
cm_req_set_alt_subnet_local(req_msg, 1); /* local only... */
cm_req_set_alt_local_ack_timeout(req_msg,
- min(31, param->alternate_path->packet_life_time + 1));
+ cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+ param->alternate_path->packet_life_time));
}
if (param->private_data && param->private_data_len)
@@ -1169,7 +1188,6 @@ static void cm_format_req_event(struct cm_work *work,
static void cm_process_work(struct cm_id_private *cm_id_priv,
struct cm_work *work)
{
- unsigned long flags;
int ret;
/* We will typically only have the current event to report. */
@@ -1177,9 +1195,9 @@ static void cm_process_work(struct cm_id_private *cm_id_priv,
cm_free_work(work);
while (!ret && !atomic_add_negative(-1, &cm_id_priv->work_count)) {
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
work = cm_dequeue_work(cm_id_priv);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
BUG_ON(!work);
ret = cm_id_priv->id.cm_handler(&cm_id_priv->id,
&work->cm_event);
@@ -1250,7 +1268,6 @@ static void cm_dup_req_handler(struct cm_work *work,
struct cm_id_private *cm_id_priv)
{
struct ib_mad_send_buf *msg = NULL;
- unsigned long flags;
int ret;
/* Quick state check to discard duplicate REQs. */
@@ -1261,7 +1278,7 @@ static void cm_dup_req_handler(struct cm_work *work,
if (ret)
return;
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
switch (cm_id_priv->id.state) {
case IB_CM_MRA_REQ_SENT:
cm_format_mra((struct cm_mra_msg *) msg->mad, cm_id_priv,
@@ -1276,14 +1293,14 @@ static void cm_dup_req_handler(struct cm_work *work,
default:
goto unlock;
}
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ret = ib_post_send_mad(msg, NULL);
if (ret)
goto free;
return;
-unlock: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock: spin_unlock_irq(&cm_id_priv->lock);
free: cm_free_msg(msg);
}
@@ -1293,17 +1310,16 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv;
struct cm_timewait_info *timewait_info;
struct cm_req_msg *req_msg;
- unsigned long flags;
req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
/* Check for possible duplicate REQ. */
- spin_lock_irqsave(&cm.lock, flags);
+ spin_lock_irq(&cm.lock);
timewait_info = cm_insert_remote_id(cm_id_priv->timewait_info);
if (timewait_info) {
cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
timewait_info->work.remote_id);
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
if (cur_cm_id_priv) {
cm_dup_req_handler(work, cur_cm_id_priv);
cm_deref_id(cur_cm_id_priv);
@@ -1315,7 +1331,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
if (timewait_info) {
cm_cleanup_timewait(cm_id_priv->timewait_info);
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
cm_issue_rej(work->port, work->mad_recv_wc,
IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
NULL, 0);
@@ -1328,7 +1344,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
req_msg->private_data);
if (!listen_cm_id_priv) {
cm_cleanup_timewait(cm_id_priv->timewait_info);
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
cm_issue_rej(work->port, work->mad_recv_wc,
IB_CM_REJ_INVALID_SERVICE_ID, CM_MSG_RESPONSE_REQ,
NULL, 0);
@@ -1338,7 +1354,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
atomic_inc(&cm_id_priv->refcount);
cm_id_priv->id.state = IB_CM_REQ_RCVD;
atomic_inc(&cm_id_priv->work_count);
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
out:
return listen_cm_id_priv;
}
@@ -1440,7 +1456,8 @@ static void cm_format_rep(struct cm_rep_msg *rep_msg,
cm_rep_set_starting_psn(rep_msg, cpu_to_be32(param->starting_psn));
rep_msg->resp_resources = param->responder_resources;
rep_msg->initiator_depth = param->initiator_depth;
- cm_rep_set_target_ack_delay(rep_msg, param->target_ack_delay);
+ cm_rep_set_target_ack_delay(rep_msg,
+ cm_id_priv->av.port->cm_dev->ack_delay);
cm_rep_set_failover(rep_msg, param->failover_accepted);
cm_rep_set_flow_ctrl(rep_msg, param->flow_control);
cm_rep_set_rnr_retry_count(rep_msg, param->rnr_retry_count);
@@ -1591,7 +1608,6 @@ static void cm_dup_rep_handler(struct cm_work *work)
struct cm_id_private *cm_id_priv;
struct cm_rep_msg *rep_msg;
struct ib_mad_send_buf *msg = NULL;
- unsigned long flags;
int ret;
rep_msg = (struct cm_rep_msg *) work->mad_recv_wc->recv_buf.mad;
@@ -1604,7 +1620,7 @@ static void cm_dup_rep_handler(struct cm_work *work)
if (ret)
goto deref;
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
if (cm_id_priv->id.state == IB_CM_ESTABLISHED)
cm_format_rtu((struct cm_rtu_msg *) msg->mad, cm_id_priv,
cm_id_priv->private_data,
@@ -1616,14 +1632,14 @@ static void cm_dup_rep_handler(struct cm_work *work)
cm_id_priv->private_data_len);
else
goto unlock;
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ret = ib_post_send_mad(msg, NULL);
if (ret)
goto free;
goto deref;
-unlock: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock: spin_unlock_irq(&cm_id_priv->lock);
free: cm_free_msg(msg);
deref: cm_deref_id(cm_id_priv);
}
@@ -1632,7 +1648,6 @@ static int cm_rep_handler(struct cm_work *work)
{
struct cm_id_private *cm_id_priv;
struct cm_rep_msg *rep_msg;
- unsigned long flags;
int ret;
rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1644,13 +1659,13 @@ static int cm_rep_handler(struct cm_work *work)
cm_format_rep_event(work);
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
switch (cm_id_priv->id.state) {
case IB_CM_REQ_SENT:
case IB_CM_MRA_REQ_RCVD:
break;
default:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ret = -EINVAL;
goto error;
}
@@ -1663,7 +1678,7 @@ static int cm_rep_handler(struct cm_work *work)
/* Check for duplicate REP. */
if (cm_insert_remote_id(cm_id_priv->timewait_info)) {
spin_unlock(&cm.lock);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ret = -EINVAL;
goto error;
}
@@ -1673,7 +1688,7 @@ static int cm_rep_handler(struct cm_work *work)
&cm.remote_id_table);
cm_id_priv->timewait_info->inserted_remote_id = 0;
spin_unlock(&cm.lock);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
cm_issue_rej(work->port, work->mad_recv_wc,
IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP,
NULL, 0);
@@ -1689,6 +1704,13 @@ static int cm_rep_handler(struct cm_work *work)
cm_id_priv->responder_resources = rep_msg->initiator_depth;
cm_id_priv->sq_psn = cm_rep_get_starting_psn(rep_msg);
cm_id_priv->rnr_retry_count = cm_rep_get_rnr_retry_count(rep_msg);
+ cm_id_priv->target_ack_delay = cm_rep_get_target_ack_delay(rep_msg);
+ cm_id_priv->av.timeout =
+ cm_ack_timeout(cm_id_priv->target_ack_delay,
+ cm_id_priv->av.timeout - 1);
+ cm_id_priv->alt_av.timeout =
+ cm_ack_timeout(cm_id_priv->target_ack_delay,
+ cm_id_priv->alt_av.timeout - 1);
/* todo: handle peer_to_peer */
@@ -1696,7 +1718,7 @@ static int cm_rep_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -1712,7 +1734,6 @@ error:
static int cm_establish_handler(struct cm_work *work)
{
struct cm_id_private *cm_id_priv;
- unsigned long flags;
int ret;
/* See comment in cm_establish about lookup. */
@@ -1720,9 +1741,9 @@ static int cm_establish_handler(struct cm_work *work)
if (!cm_id_priv)
return -EINVAL;
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
if (cm_id_priv->id.state != IB_CM_ESTABLISHED) {
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
goto out;
}
@@ -1730,7 +1751,7 @@ static int cm_establish_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -1746,7 +1767,6 @@ static int cm_rtu_handler(struct cm_work *work)
{
struct cm_id_private *cm_id_priv;
struct cm_rtu_msg *rtu_msg;
- unsigned long flags;
int ret;
rtu_msg = (struct cm_rtu_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1757,10 +1777,10 @@ static int cm_rtu_handler(struct cm_work *work)
work->cm_event.private_data = &rtu_msg->private_data;
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
if (cm_id_priv->id.state != IB_CM_REP_SENT &&
cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
goto out;
}
cm_id_priv->id.state = IB_CM_ESTABLISHED;
@@ -1769,7 +1789,7 @@ static int cm_rtu_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -1932,7 +1952,6 @@ static int cm_dreq_handler(struct cm_work *work)
struct cm_id_private *cm_id_priv;
struct cm_dreq_msg *dreq_msg;
struct ib_mad_send_buf *msg = NULL;
- unsigned long flags;
int ret;
dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -1945,7 +1964,7 @@ static int cm_dreq_handler(struct cm_work *work)
work->cm_event.private_data = &dreq_msg->private_data;
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
if (cm_id_priv->local_qpn != cm_dreq_get_remote_qpn(dreq_msg))
goto unlock;
@@ -1964,7 +1983,7 @@ static int cm_dreq_handler(struct cm_work *work)
cm_format_drep((struct cm_drep_msg *) msg->mad, cm_id_priv,
cm_id_priv->private_data,
cm_id_priv->private_data_len);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ib_post_send_mad(msg, NULL))
cm_free_msg(msg);
@@ -1977,7 +1996,7 @@ static int cm_dreq_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -1985,7 +2004,7 @@ static int cm_dreq_handler(struct cm_work *work)
cm_deref_id(cm_id_priv);
return 0;
-unlock: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock: spin_unlock_irq(&cm_id_priv->lock);
deref: cm_deref_id(cm_id_priv);
return -EINVAL;
}
@@ -1994,7 +2013,6 @@ static int cm_drep_handler(struct cm_work *work)
{
struct cm_id_private *cm_id_priv;
struct cm_drep_msg *drep_msg;
- unsigned long flags;
int ret;
drep_msg = (struct cm_drep_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2005,10 +2023,10 @@ static int cm_drep_handler(struct cm_work *work)
work->cm_event.private_data = &drep_msg->private_data;
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
if (cm_id_priv->id.state != IB_CM_DREQ_SENT &&
cm_id_priv->id.state != IB_CM_DREQ_RCVD) {
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
goto out;
}
cm_enter_timewait(cm_id_priv);
@@ -2017,7 +2035,7 @@ static int cm_drep_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -2107,17 +2125,16 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
{
struct cm_timewait_info *timewait_info;
struct cm_id_private *cm_id_priv;
- unsigned long flags;
__be32 remote_id;
remote_id = rej_msg->local_comm_id;
if (__be16_to_cpu(rej_msg->reason) == IB_CM_REJ_TIMEOUT) {
- spin_lock_irqsave(&cm.lock, flags);
+ spin_lock_irq(&cm.lock);
timewait_info = cm_find_remote_id( *((__be64 *) rej_msg->ari),
remote_id);
if (!timewait_info) {
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
return NULL;
}
cm_id_priv = idr_find(&cm.local_id_table, (__force int)
@@ -2129,7 +2146,7 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg)
else
cm_id_priv = NULL;
}
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
} else if (cm_rej_get_msg_rejected(rej_msg) == CM_MSG_RESPONSE_REQ)
cm_id_priv = cm_acquire_id(rej_msg->remote_comm_id, 0);
else
@@ -2142,7 +2159,6 @@ static int cm_rej_handler(struct cm_work *work)
{
struct cm_id_private *cm_id_priv;
struct cm_rej_msg *rej_msg;
- unsigned long flags;
int ret;
rej_msg = (struct cm_rej_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2152,7 +2168,7 @@ static int cm_rej_handler(struct cm_work *work)
cm_format_rej_event(work);
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
switch (cm_id_priv->id.state) {
case IB_CM_REQ_SENT:
case IB_CM_MRA_REQ_RCVD:
@@ -2176,7 +2192,7 @@ static int cm_rej_handler(struct cm_work *work)
cm_enter_timewait(cm_id_priv);
break;
default:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
ret = -EINVAL;
goto out;
}
@@ -2184,7 +2200,7 @@ static int cm_rej_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -2295,7 +2311,6 @@ static int cm_mra_handler(struct cm_work *work)
{
struct cm_id_private *cm_id_priv;
struct cm_mra_msg *mra_msg;
- unsigned long flags;
int timeout, ret;
mra_msg = (struct cm_mra_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2307,9 +2322,9 @@ static int cm_mra_handler(struct cm_work *work)
work->cm_event.param.mra_rcvd.service_timeout =
cm_mra_get_service_timeout(mra_msg);
timeout = cm_convert_to_ms(cm_mra_get_service_timeout(mra_msg)) +
- cm_convert_to_ms(cm_id_priv->av.packet_life_time);
+ cm_convert_to_ms(cm_id_priv->av.timeout);
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
switch (cm_id_priv->id.state) {
case IB_CM_REQ_SENT:
if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_REQ ||
@@ -2342,7 +2357,7 @@ static int cm_mra_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -2350,7 +2365,7 @@ static int cm_mra_handler(struct cm_work *work)
cm_deref_id(cm_id_priv);
return 0;
out:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
cm_deref_id(cm_id_priv);
return -EINVAL;
}
@@ -2379,7 +2394,8 @@ static void cm_format_lap(struct cm_lap_msg *lap_msg,
cm_lap_set_sl(lap_msg, alternate_path->sl);
cm_lap_set_subnet_local(lap_msg, 1); /* local only... */
cm_lap_set_local_ack_timeout(lap_msg,
- min(31, alternate_path->packet_life_time + 1));
+ cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+ alternate_path->packet_life_time));
if (private_data && private_data_len)
memcpy(lap_msg->private_data, private_data, private_data_len);
@@ -2410,6 +2426,9 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id,
ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av);
if (ret)
goto out;
+ cm_id_priv->alt_av.timeout =
+ cm_ack_timeout(cm_id_priv->target_ack_delay,
+ cm_id_priv->alt_av.timeout - 1);
ret = cm_alloc_msg(cm_id_priv, &msg);
if (ret)
@@ -2465,7 +2484,6 @@ static int cm_lap_handler(struct cm_work *work)
struct cm_lap_msg *lap_msg;
struct ib_cm_lap_event_param *param;
struct ib_mad_send_buf *msg = NULL;
- unsigned long flags;
int ret;
/* todo: verify LAP request and send reject APR if invalid. */
@@ -2480,7 +2498,7 @@ static int cm_lap_handler(struct cm_work *work)
cm_format_path_from_lap(cm_id_priv, param->alternate_path, lap_msg);
work->cm_event.private_data = &lap_msg->private_data;
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
if (cm_id_priv->id.state != IB_CM_ESTABLISHED)
goto unlock;
@@ -2497,7 +2515,7 @@ static int cm_lap_handler(struct cm_work *work)
cm_id_priv->service_timeout,
cm_id_priv->private_data,
cm_id_priv->private_data_len);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ib_post_send_mad(msg, NULL))
cm_free_msg(msg);
@@ -2515,7 +2533,7 @@ static int cm_lap_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -2523,7 +2541,7 @@ static int cm_lap_handler(struct cm_work *work)
cm_deref_id(cm_id_priv);
return 0;
-unlock: spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+unlock: spin_unlock_irq(&cm_id_priv->lock);
deref: cm_deref_id(cm_id_priv);
return -EINVAL;
}
@@ -2598,7 +2616,6 @@ static int cm_apr_handler(struct cm_work *work)
{
struct cm_id_private *cm_id_priv;
struct cm_apr_msg *apr_msg;
- unsigned long flags;
int ret;
apr_msg = (struct cm_apr_msg *)work->mad_recv_wc->recv_buf.mad;
@@ -2612,11 +2629,11 @@ static int cm_apr_handler(struct cm_work *work)
work->cm_event.param.apr_rcvd.info_len = apr_msg->info_length;
work->cm_event.private_data = &apr_msg->private_data;
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
if (cm_id_priv->id.state != IB_CM_ESTABLISHED ||
(cm_id_priv->id.lap_state != IB_CM_LAP_SENT &&
cm_id_priv->id.lap_state != IB_CM_MRA_LAP_RCVD)) {
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
goto out;
}
cm_id_priv->id.lap_state = IB_CM_LAP_IDLE;
@@ -2626,7 +2643,7 @@ static int cm_apr_handler(struct cm_work *work)
ret = atomic_inc_and_test(&cm_id_priv->work_count);
if (!ret)
list_add_tail(&work->list, &cm_id_priv->work_list);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
if (ret)
cm_process_work(cm_id_priv, work);
@@ -2761,7 +2778,6 @@ static int cm_sidr_req_handler(struct cm_work *work)
struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
struct cm_sidr_req_msg *sidr_req_msg;
struct ib_wc *wc;
- unsigned long flags;
cm_id = ib_create_cm_id(work->port->cm_dev->device, NULL, NULL);
if (IS_ERR(cm_id))
@@ -2778,27 +2794,26 @@ static int cm_sidr_req_handler(struct cm_work *work)
work->mad_recv_wc->recv_buf.grh,
&cm_id_priv->av);
cm_id_priv->id.remote_id = sidr_req_msg->request_id;
- cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
cm_id_priv->tid = sidr_req_msg->hdr.tid;
atomic_inc(&cm_id_priv->work_count);
- spin_lock_irqsave(&cm.lock, flags);
+ spin_lock_irq(&cm.lock);
cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
if (cur_cm_id_priv) {
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
goto out; /* Duplicate message. */
}
+ cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
cur_cm_id_priv = cm_find_listen(cm_id->device,
sidr_req_msg->service_id,
sidr_req_msg->private_data);
if (!cur_cm_id_priv) {
- rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
- spin_unlock_irqrestore(&cm.lock, flags);
- /* todo: reply with no match */
+ spin_unlock_irq(&cm.lock);
+ cm_reject_sidr_req(cm_id_priv, IB_SIDR_UNSUPPORTED);
goto out; /* No match. */
}
atomic_inc(&cur_cm_id_priv->refcount);
- spin_unlock_irqrestore(&cm.lock, flags);
+ spin_unlock_irq(&cm.lock);
cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
cm_id_priv->id.context = cur_cm_id_priv->id.context;
@@ -2899,7 +2914,6 @@ static int cm_sidr_rep_handler(struct cm_work *work)
{
struct cm_sidr_rep_msg *sidr_rep_msg;
struct cm_id_private *cm_id_priv;
- unsigned long flags;
sidr_rep_msg = (struct cm_sidr_rep_msg *)
work->mad_recv_wc->recv_buf.mad;
@@ -2907,14 +2921,14 @@ static int cm_sidr_rep_handler(struct cm_work *work)
if (!cm_id_priv)
return -EINVAL; /* Unmatched reply. */
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
if (cm_id_priv->id.state != IB_CM_SIDR_REQ_SENT) {
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
goto out;
}
cm_id_priv->id.state = IB_CM_IDLE;
ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
cm_format_sidr_rep_event(work);
cm_process_work(cm_id_priv, work);
@@ -2930,14 +2944,13 @@ static void cm_process_send_error(struct ib_mad_send_buf *msg,
struct cm_id_private *cm_id_priv;
struct ib_cm_event cm_event;
enum ib_cm_state state;
- unsigned long flags;
int ret;
memset(&cm_event, 0, sizeof cm_event);
cm_id_priv = msg->context[0];
/* Discard old sends or ones without a response. */
- spin_lock_irqsave(&cm_id_priv->lock, flags);
+ spin_lock_irq(&cm_id_priv->lock);
state = (enum ib_cm_state) (unsigned long) msg->context[1];
if (msg != cm_id_priv->msg || state != cm_id_priv->id.state)
goto discard;
@@ -2964,7 +2977,7 @@ static void cm_process_send_error(struct ib_mad_send_buf *msg,
default:
goto discard;
}
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
cm_event.param.send_status = wc_status;
/* No other events can occur on the cm_id at this point. */
@@ -2974,7 +2987,7 @@ static void cm_process_send_error(struct ib_mad_send_buf *msg,
ib_destroy_cm_id(&cm_id_priv->id);
return;
discard:
- spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+ spin_unlock_irq(&cm_id_priv->lock);
cm_free_msg(msg);
}
@@ -3269,8 +3282,7 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv,
*qp_attr_mask |= IB_QP_ALT_PATH;
qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
- qp_attr->alt_timeout =
- cm_id_priv->alt_av.packet_life_time + 1;
+ qp_attr->alt_timeout = cm_id_priv->alt_av.timeout;
qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
}
ret = 0;
@@ -3308,8 +3320,7 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
*qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT |
IB_QP_RNR_RETRY |
IB_QP_MAX_QP_RD_ATOMIC;
- qp_attr->timeout =
- cm_id_priv->av.packet_life_time + 1;
+ qp_attr->timeout = cm_id_priv->av.timeout;
qp_attr->retry_cnt = cm_id_priv->retry_count;
qp_attr->rnr_retry = cm_id_priv->rnr_retry_count;
qp_attr->max_rd_atomic =
@@ -3323,8 +3334,7 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
*qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE;
qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num;
qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index;
- qp_attr->alt_timeout =
- cm_id_priv->alt_av.packet_life_time + 1;
+ qp_attr->alt_timeout = cm_id_priv->alt_av.timeout;
qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr;
qp_attr->path_mig_state = IB_MIG_REARM;
}
@@ -3364,6 +3374,16 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id,
}
EXPORT_SYMBOL(ib_cm_init_qp_attr);
+void cm_get_ack_delay(struct cm_device *cm_dev)
+{
+ struct ib_device_attr attr;
+
+ if (ib_query_device(cm_dev->device, &attr))
+ cm_dev->ack_delay = 0; /* acks will rely on packet life time */
+ else
+ cm_dev->ack_delay = attr.local_ca_ack_delay;
+}
+
static void cm_add_one(struct ib_device *device)
{
struct cm_device *cm_dev;
@@ -3388,6 +3408,7 @@ static void cm_add_one(struct ib_device *device)
return;
cm_dev->device = device;
+ cm_get_ack_delay(cm_dev);
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
for (i = 1; i <= device->phys_port_cnt; i++) {
diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h
index 4d3aee90c24..aec9c7af825 100644
--- a/drivers/infiniband/core/cm_msgs.h
+++ b/drivers/infiniband/core/cm_msgs.h
@@ -35,6 +35,7 @@
#define CM_MSGS_H
#include <rdma/ib_mad.h>
+#include <rdma/ib_cm.h>
/*
* Parameters to routines below should be in network-byte order, and values
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 2eb52b7a71d..23af7a032a0 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -2326,7 +2326,6 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
rep.private_data_len = conn_param->private_data_len;
rep.responder_resources = conn_param->responder_resources;
rep.initiator_depth = conn_param->initiator_depth;
- rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT;
rep.failover_accepted = 0;
rep.flow_control = conn_param->flow_control;
rep.rnr_retry_count = conn_param->rnr_retry_count;
@@ -2773,8 +2772,8 @@ static int cma_init(void)
int ret;
get_random_bytes(&next_port, sizeof next_port);
- next_port = (next_port % (sysctl_local_port_range[1] -
- sysctl_local_port_range[0])) +
+ next_port = ((unsigned int) next_port %
+ (sysctl_local_port_range[1] - sysctl_local_port_range[0])) +
sysctl_local_port_range[0];
cma_wq = create_singlethread_workqueue("rdma_cm");
if (!cma_wq)
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 85ccf13b804..6b8faca02f8 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -675,10 +675,16 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
struct ib_mad_port_private *port_priv;
struct ib_mad_agent_private *recv_mad_agent = NULL;
struct ib_device *device = mad_agent_priv->agent.device;
- u8 port_num = mad_agent_priv->agent.port_num;
+ u8 port_num;
struct ib_wc mad_wc;
struct ib_send_wr *send_wr = &mad_send_wr->send_wr;
+ if (device->node_type == RDMA_NODE_IB_SWITCH &&
+ smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+ port_num = send_wr->wr.ud.port_num;
+ else
+ port_num = mad_agent_priv->agent.port_num;
+
/*
* Directed route handling starts if the initial LID routed part of
* a request or the ending LID routed part of a response is empty.
@@ -1839,6 +1845,7 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
struct ib_mad_private *recv, *response;
struct ib_mad_list_head *mad_list;
struct ib_mad_agent_private *mad_agent;
+ int port_num;
response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL);
if (!response)
@@ -1872,25 +1879,50 @@ static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
if (!validate_mad(&recv->mad.mad, qp_info->qp->qp_num))
goto out;
+ if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH)
+ port_num = wc->port_num;
+ else
+ port_num = port_priv->port_num;
+
if (recv->mad.mad.mad_hdr.mgmt_class ==
IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
+ enum smi_forward_action retsmi;
+
if (smi_handle_dr_smp_recv(&recv->mad.smp,
port_priv->device->node_type,
- port_priv->port_num,
+ port_num,
port_priv->device->phys_port_cnt) ==
IB_SMI_DISCARD)
goto out;
- if (smi_check_forward_dr_smp(&recv->mad.smp) == IB_SMI_LOCAL)
+ retsmi = smi_check_forward_dr_smp(&recv->mad.smp);
+ if (retsmi == IB_SMI_LOCAL)
goto local;
- if (smi_handle_dr_smp_send(&recv->mad.smp,
- port_priv->device->node_type,
- port_priv->port_num) == IB_SMI_DISCARD)
- goto out;
+ if (retsmi == IB_SMI_SEND) { /* don't forward */
+ if (smi_handle_dr_smp_send(&recv->mad.smp,
+ port_priv->device->node_type,
+ port_num) == IB_SMI_DISCARD)
+ goto out;
+
+ if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD)
+ goto out;
+ } else if (port_priv->device->node_type == RDMA_NODE_IB_SWITCH) {
+ /* forward case for switches */
+ memcpy(response, recv, sizeof(*response));
+ response->header.recv_wc.wc = &response->header.wc;
+ response->header.recv_wc.recv_buf.mad = &response->mad.mad;
+ response->header.recv_wc.recv_buf.grh = &response->grh;
+
+ if (!agent_send_response(&response->mad.mad,
+ &response->grh, wc,
+ port_priv->device,
+ smi_get_fwd_port(&recv->mad.smp),
+ qp_info->qp->qp_num))
+ response = NULL;
- if (smi_check_local_smp(&recv->mad.smp, port_priv->device) == IB_SMI_DISCARD)
goto out;
+ }
}
local:
@@ -1919,7 +1951,7 @@ local:
agent_send_response(&response->mad.mad,
&recv->grh, wc,
port_priv->device,
- port_priv->port_num,
+ port_num,
qp_info->qp->qp_num);
goto out;
}
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index 1e13ab42b70..15b4c4d3606 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2006 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/core/sa.h b/drivers/infiniband/core/sa.h
index 24c93fd320f..b1d4bbf4ce5 100644
--- a/drivers/infiniband/core/sa.h
+++ b/drivers/infiniband/core/sa.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
* Copyright (c) 2006 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 6469406ea9d..20ab6b3e484 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Voltaire, Inc.  All rights reserved.
+ * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
* Copyright (c) 2006 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -56,6 +56,7 @@ MODULE_LICENSE("Dual BSD/GPL");
struct ib_sa_sm_ah {
struct ib_ah *ah;
struct kref ref;
+ u16 pkey_index;
u8 src_path_mask;
};
@@ -382,6 +383,13 @@ static void update_sm_ah(struct work_struct *work)
kref_init(&new_ah->ref);
new_ah->src_path_mask = (1 << port_attr.lmc) - 1;
+ new_ah->pkey_index = 0;
+ if (ib_find_pkey(port->agent->device, port->port_num,
+ IB_DEFAULT_PKEY_FULL, &new_ah->pkey_index) &&
+ ib_find_pkey(port->agent->device, port->port_num,
+ IB_DEFAULT_PKEY_PARTIAL, &new_ah->pkey_index))
+ printk(KERN_ERR "Couldn't find index for default PKey\n");
+
memset(&ah_attr, 0, sizeof ah_attr);
ah_attr.dlid = port_attr.sm_lid;
ah_attr.sl = port_attr.sm_sl;
@@ -512,6 +520,35 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
}
EXPORT_SYMBOL(ib_init_ah_from_path);
+static int alloc_mad(struct ib_sa_query *query, gfp_t gfp_mask)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&query->port->ah_lock, flags);
+ kref_get(&query->port->sm_ah->ref);
+ query->sm_ah = query->port->sm_ah;
+ spin_unlock_irqrestore(&query->port->ah_lock, flags);
+
+ query->mad_buf = ib_create_send_mad(query->port->agent, 1,
+ query->sm_ah->pkey_index,
+ 0, IB_MGMT_SA_HDR, IB_MGMT_SA_DATA,
+ gfp_mask);
+ if (!query->mad_buf) {
+ kref_put(&query->sm_ah->ref, free_sm_ah);
+ return -ENOMEM;
+ }
+
+ query->mad_buf->ah = query->sm_ah->ah;
+
+ return 0;
+}
+
+static void free_mad(struct ib_sa_query *query)
+{
+ ib_free_send_mad(query->mad_buf);
+ kref_put(&query->sm_ah->ref, free_sm_ah);
+}
+
static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
{
unsigned long flags;
@@ -548,20 +585,11 @@ retry:
query->mad_buf->context[0] = query;
query->id = id;
- spin_lock_irqsave(&query->port->ah_lock, flags);
- kref_get(&query->port->sm_ah->ref);
- query->sm_ah = query->port->sm_ah;
- spin_unlock_irqrestore(&query->port->ah_lock, flags);
-
- query->mad_buf->ah = query->sm_ah->ah;
-
ret = ib_post_send_mad(query->mad_buf, NULL);
if (ret) {
spin_lock_irqsave(&idr_lock, flags);
idr_remove(&query_idr, id);
spin_unlock_irqrestore(&idr_lock, flags);
-
- kref_put(&query->sm_ah->ref, free_sm_ah);
}
/*
@@ -647,13 +675,10 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
if (!query)
return -ENOMEM;
- query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
- 0, IB_MGMT_SA_HDR,
- IB_MGMT_SA_DATA, gfp_mask);
- if (!query->sa_query.mad_buf) {
- ret = -ENOMEM;
+ query->sa_query.port = port;
+ ret = alloc_mad(&query->sa_query, gfp_mask);
+ if (ret)
goto err1;
- }
ib_sa_client_get(client);
query->sa_query.client = client;
@@ -665,7 +690,6 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
query->sa_query.release = ib_sa_path_rec_release;
- query->sa_query.port = port;
mad->mad_hdr.method = IB_MGMT_METHOD_GET;
mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_PATH_REC);
mad->sa_hdr.comp_mask = comp_mask;
@@ -683,7 +707,7 @@ int ib_sa_path_rec_get(struct ib_sa_client *client,
err2:
*sa_query = NULL;
ib_sa_client_put(query->sa_query.client);
- ib_free_send_mad(query->sa_query.mad_buf);
+ free_mad(&query->sa_query);
err1:
kfree(query);
@@ -773,13 +797,10 @@ int ib_sa_service_rec_query(struct ib_sa_client *client,
if (!query)
return -ENOMEM;
- query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
- 0, IB_MGMT_SA_HDR,
- IB_MGMT_SA_DATA, gfp_mask);
- if (!query->sa_query.mad_buf) {
- ret = -ENOMEM;
+ query->sa_query.port = port;
+ ret = alloc_mad(&query->sa_query, gfp_mask);
+ if (ret)
goto err1;
- }
ib_sa_client_get(client);
query->sa_query.client = client;
@@ -791,7 +812,6 @@ int ib_sa_service_rec_query(struct ib_sa_client *client,
query->sa_query.callback = callback ? ib_sa_service_rec_callback : NULL;
query->sa_query.release = ib_sa_service_rec_release;
- query->sa_query.port = port;
mad->mad_hdr.method = method;
mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_SERVICE_REC);
mad->sa_hdr.comp_mask = comp_mask;
@@ -810,7 +830,7 @@ int ib_sa_service_rec_query(struct ib_sa_client *client,
err2:
*sa_query = NULL;
ib_sa_client_put(query->sa_query.client);
- ib_free_send_mad(query->sa_query.mad_buf);
+ free_mad(&query->sa_query);
err1:
kfree(query);
@@ -869,13 +889,10 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
if (!query)
return -ENOMEM;
- query->sa_query.mad_buf = ib_create_send_mad(agent, 1, 0,
- 0, IB_MGMT_SA_HDR,
- IB_MGMT_SA_DATA, gfp_mask);
- if (!query->sa_query.mad_buf) {
- ret = -ENOMEM;
+ query->sa_query.port = port;
+ ret = alloc_mad(&query->sa_query, gfp_mask);
+ if (ret)
goto err1;
- }
ib_sa_client_get(client);
query->sa_query.client = client;
@@ -887,7 +904,6 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
query->sa_query.release = ib_sa_mcmember_rec_release;
- query->sa_query.port = port;
mad->mad_hdr.method = method;
mad->mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
mad->sa_hdr.comp_mask = comp_mask;
@@ -906,7 +922,7 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client,
err2:
*sa_query = NULL;
ib_sa_client_put(query->sa_query.client);
- ib_free_send_mad(query->sa_query.mad_buf);
+ free_mad(&query->sa_query);
err1:
kfree(query);
@@ -939,8 +955,7 @@ static void send_handler(struct ib_mad_agent *agent,
idr_remove(&query_idr, query->id);
spin_unlock_irqrestore(&idr_lock, flags);
- ib_free_send_mad(mad_send_wc->send_buf);
- kref_put(&query->sm_ah->ref, free_sm_ah);
+ free_mad(query);
ib_sa_client_put(query->client);
query->release(query);
}
diff --git a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c
index 2bca753eb62..87236753bce 100644
--- a/drivers/infiniband/core/smi.c
+++ b/drivers/infiniband/core/smi.c
@@ -192,7 +192,7 @@ enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
}
/* smp->hop_ptr updated when sending */
return (node_type == RDMA_NODE_IB_SWITCH ?
- IB_SMI_HANDLE: IB_SMI_DISCARD);
+ IB_SMI_HANDLE : IB_SMI_DISCARD);
}
/* C14-13:4 -- hop_ptr = 0 -> give to SM */
@@ -211,7 +211,7 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
if (!ib_get_smp_direction(smp)) {
/* C14-9:2 -- intermediate hop */
if (hop_ptr && hop_ptr < hop_cnt)
- return IB_SMI_SEND;
+ return IB_SMI_FORWARD;
/* C14-9:3 -- at the end of the DR segment of path */
if (hop_ptr == hop_cnt)
@@ -224,7 +224,7 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
} else {
/* C14-13:2 -- intermediate hop */
if (2 <= hop_ptr && hop_ptr <= hop_cnt)
- return IB_SMI_SEND;
+ return IB_SMI_FORWARD;
/* C14-13:3 -- at the end of the DR segment of path */
if (hop_ptr == 1)
@@ -233,3 +233,13 @@ enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp)
}
return IB_SMI_LOCAL;
}
+
+/*
+ * Return the forwarding port number from initial_path for outgoing SMP and
+ * from return_path for returning SMP
+ */
+int smi_get_fwd_port(struct ib_smp *smp)
+{
+ return (!ib_get_smp_direction(smp) ? smp->initial_path[smp->hop_ptr+1] :
+ smp->return_path[smp->hop_ptr-1]);
+}
diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h
index 9a4b349efc3..1cfc2984434 100644
--- a/drivers/infiniband/core/smi.h
+++ b/drivers/infiniband/core/smi.h
@@ -48,10 +48,12 @@ enum smi_action {
enum smi_forward_action {
IB_SMI_LOCAL, /* SMP should be completed up the stack */
IB_SMI_SEND, /* received DR SMP should be forwarded to the send queue */
+ IB_SMI_FORWARD /* SMP should be forwarded (for switches only) */
};
enum smi_action smi_handle_dr_smp_recv(struct ib_smp *smp, u8 node_type,
int port_num, int phys_port_cnt);
+int smi_get_fwd_port(struct ib_smp *smp);
extern enum smi_forward_action smi_check_forward_dr_smp(struct ib_smp *smp);
extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
u8 node_type, int port_num);
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 08c299ebf4a..70b77ae6742 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -311,7 +311,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
return sprintf(buf, "N/A (no PMA)\n");
in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
- out_mad = kmalloc(sizeof *in_mad, GFP_KERNEL);
+ out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
if (!in_mad || !out_mad) {
ret = -ENOMEM;
goto out;
@@ -479,7 +479,6 @@ alloc_group_attrs(ssize_t (*show)(struct ib_port *,
element->attr.attr.name = element->name;
element->attr.attr.mode = S_IRUGO;
- element->attr.attr.owner = THIS_MODULE;
element->attr.show = show;
element->index = i;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 2586a3ee8eb..424983f5b1e 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -823,7 +823,6 @@ static ssize_t ib_ucm_send_rep(struct ib_ucm_file *file,
param.private_data_len = cmd.len;
param.responder_resources = cmd.responder_resources;
param.initiator_depth = cmd.initiator_depth;
- param.target_ack_delay = cmd.target_ack_delay;
param.failover_accepted = cmd.failover_accepted;
param.flow_control = cmd.flow_control;
param.rnr_retry_count = cmd.rnr_retry_count;
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index b4aec5103c9..26d0470eef6 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -121,6 +121,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
cur_base = addr & PAGE_MASK;
+ ret = 0;
while (npages) {
ret = get_user_pages(current, current->mm, cur_base,
min_t(int, npages,
@@ -225,13 +226,15 @@ void ib_umem_release(struct ib_umem *umem)
* up here and not be able to take the mmap_sem. In that case
* we defer the vm_locked accounting to the system workqueue.
*/
- if (context->closing && !down_write_trylock(&mm->mmap_sem)) {
- INIT_WORK(&umem->work, ib_umem_account);
- umem->mm = mm;
- umem->diff = diff;
-
- schedule_work(&umem->work);
- return;
+ if (context->closing) {
+ if (!down_write_trylock(&mm->mmap_sem)) {
+ INIT_WORK(&umem->work, ib_umem_account);
+ umem->mm = mm;
+ umem->diff = diff;
+
+ schedule_work(&umem->work);
+ return;
+ }
} else
down_write(&mm->mmap_sem);
diff --git a/drivers/infiniband/hw/amso1100/Kconfig b/drivers/infiniband/hw/amso1100/Kconfig
index 809cb14ac6d..e6ce5f209e4 100644
--- a/drivers/infiniband/hw/amso1100/Kconfig
+++ b/drivers/infiniband/hw/amso1100/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_AMSO1100
tristate "Ammasso 1100 HCA support"
- depends on PCI && INET && INFINIBAND
+ depends on PCI && INET
---help---
This is a low-level driver for the Ammasso 1100 host
channel adapter (HCA).
diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c
index 58bc272bd40..0aecea67f3e 100644
--- a/drivers/infiniband/hw/amso1100/c2.c
+++ b/drivers/infiniband/hw/amso1100/c2.c
@@ -672,7 +672,7 @@ static int c2_up(struct net_device *netdev)
* rdma interface.
*/
in_dev = in_dev_get(netdev);
- in_dev->cnf.arp_ignore = 1;
+ IN_DEV_CONF_SET(in_dev, ARP_IGNORE, 1);
in_dev_put(in_dev);
return 0;
diff --git a/drivers/infiniband/hw/cxgb3/Kconfig b/drivers/infiniband/hw/cxgb3/Kconfig
index 77977f55dca..2acec3fadf6 100644
--- a/drivers/infiniband/hw/cxgb3/Kconfig
+++ b/drivers/infiniband/hw/cxgb3/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_CXGB3
tristate "Chelsio RDMA Driver"
- depends on CHELSIO_T3 && INFINIBAND && INET
+ depends on CHELSIO_T3 && INET
select GENERIC_ALLOCATOR
---help---
This is an iWARP/RDMA driver for the Chelsio T3 1GbE and
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 76049afc765..1518b41482a 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -144,7 +144,7 @@ static int cxio_hal_clear_qp_ctx(struct cxio_rdev *rdev_p, u32 qpid)
}
wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
memset(wqe, 0, sizeof(*wqe));
- build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 3, 1, qpid, 7);
+ build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 3, 0, qpid, 7);
wqe->flags = cpu_to_be32(MODQP_WRITE_EC);
sge_cmd = qpid << 8 | 3;
wqe->sge_cmd = cpu_to_be64(sge_cmd);
@@ -548,7 +548,7 @@ static int cxio_hal_init_ctrl_qp(struct cxio_rdev *rdev_p)
V_EC_UP_TOKEN(T3_CTL_QP_TID) | F_EC_VALID)) << 32;
wqe = (struct t3_modify_qp_wr *) skb_put(skb, sizeof(*wqe));
memset(wqe, 0, sizeof(*wqe));
- build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 0, 1,
+ build_fw_riwrh((struct fw_riwrh *) wqe, T3_WR_QP_MOD, 0, 0,
T3_CTL_QP_TID, 7);
wqe->flags = cpu_to_be32(MODQP_WRITE_EC);
sge_cmd = (3ULL << 56) | FW_RI_SGEEC_START << 8 | 3;
@@ -833,7 +833,7 @@ int cxio_rdma_init(struct cxio_rdev *rdev_p, struct t3_rdma_init_attr *attr)
wqe->ird = cpu_to_be32(attr->ird);
wqe->qp_dma_addr = cpu_to_be64(attr->qp_dma_addr);
wqe->qp_dma_size = cpu_to_be32(attr->qp_dma_size);
- wqe->rsvd = 0;
+ wqe->irs = cpu_to_be32(attr->irs);
skb->priority = 0; /* 0=>ToeQ; 1=>CtrlQ */
return (cxgb3_ofld_send(rdev_p->t3cdev_p, skb));
}
diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
index ff7290eacef..c84d4ac4935 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
+++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
@@ -294,6 +294,7 @@ struct t3_rdma_init_attr {
u64 qp_dma_addr;
u32 qp_dma_size;
u32 flags;
+ u32 irs;
};
struct t3_rdma_init_wr {
@@ -314,7 +315,7 @@ struct t3_rdma_init_wr {
__be32 ird;
__be64 qp_dma_addr; /* 7 */
__be32 qp_dma_size; /* 8 */
- u32 rsvd;
+ u32 irs;
};
struct t3_genbit {
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index b2faff5abce..3b41dc0c39d 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -254,8 +254,6 @@ static void release_ep_resources(struct iwch_ep *ep)
cxgb3_remove_tid(ep->com.tdev, (void *)ep, ep->hwtid);
dst_release(ep->dst);
l2t_release(L2DATA(ep->com.tdev), ep->l2t);
- if (ep->com.tdev->type == T3B)
- release_tid(ep->com.tdev, ep->hwtid, NULL);
put_ep(&ep->com);
}
@@ -515,7 +513,7 @@ static void send_mpa_req(struct iwch_ep *ep, struct sk_buff *skb)
req->len = htonl(len);
req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
V_TX_SNDBUF(snd_win>>15));
- req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+ req->flags = htonl(F_TX_INIT);
req->sndseq = htonl(ep->snd_seq);
BUG_ON(ep->mpa_skb);
ep->mpa_skb = skb;
@@ -566,7 +564,7 @@ static int send_mpa_reject(struct iwch_ep *ep, const void *pdata, u8 plen)
req->len = htonl(mpalen);
req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
V_TX_SNDBUF(snd_win>>15));
- req->flags = htonl(F_TX_IMM_ACK|F_TX_INIT);
+ req->flags = htonl(F_TX_INIT);
req->sndseq = htonl(ep->snd_seq);
BUG_ON(ep->mpa_skb);
ep->mpa_skb = skb;
@@ -618,7 +616,7 @@ static int send_mpa_reply(struct iwch_ep *ep, const void *pdata, u8 plen)
req->len = htonl(len);
req->param = htonl(V_TX_PORT(ep->l2t->smt_idx) |
V_TX_SNDBUF(snd_win>>15));
- req->flags = htonl(F_TX_MORE | F_TX_IMM_ACK | F_TX_INIT);
+ req->flags = htonl(F_TX_INIT);
req->sndseq = htonl(ep->snd_seq);
ep->mpa_skb = skb;
state_set(&ep->com, MPA_REP_SENT);
@@ -641,6 +639,7 @@ static int act_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
cxgb3_insert_tid(ep->com.tdev, &t3c_client, ep, tid);
ep->snd_seq = ntohl(req->snd_isn);
+ ep->rcv_seq = ntohl(req->rcv_isn);
set_emss(ep, ntohs(req->tcp_opt));
@@ -1023,6 +1022,9 @@ static int rx_data(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
skb_pull(skb, sizeof(*hdr));
skb_trim(skb, dlen);
+ ep->rcv_seq += dlen;
+ BUG_ON(ep->rcv_seq != (ntohl(hdr->seq) + dlen));
+
switch (state_read(&ep->com)) {
case MPA_REQ_SENT:
process_mpa_reply(ep, skb);
@@ -1060,7 +1062,6 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
struct iwch_ep *ep = ctx;
struct cpl_wr_ack *hdr = cplhdr(skb);
unsigned int credits = ntohs(hdr->credits);
- enum iwch_qp_attr_mask mask;
PDBG("%s ep %p credits %u\n", __FUNCTION__, ep, credits);
@@ -1072,30 +1073,6 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
ep->mpa_skb = NULL;
dst_confirm(ep->dst);
if (state_read(&ep->com) == MPA_REP_SENT) {
- struct iwch_qp_attributes attrs;
-
- /* bind QP to EP and move to RTS */
- attrs.mpa_attr = ep->mpa_attr;
- attrs.max_ird = ep->ord;
- attrs.max_ord = ep->ord;
- attrs.llp_stream_handle = ep;
- attrs.next_state = IWCH_QP_STATE_RTS;
-
- /* bind QP and TID with INIT_WR */
- mask = IWCH_QP_ATTR_NEXT_STATE |
- IWCH_QP_ATTR_LLP_STREAM_HANDLE |
- IWCH_QP_ATTR_MPA_ATTR |
- IWCH_QP_ATTR_MAX_IRD |
- IWCH_QP_ATTR_MAX_ORD;
-
- ep->com.rpl_err = iwch_modify_qp(ep->com.qp->rhp,
- ep->com.qp, mask, &attrs, 1);
-
- if (!ep->com.rpl_err) {
- state_set(&ep->com, FPDU_MODE);
- established_upcall(ep);
- }
-
ep->com.rpl_done = 1;
PDBG("waking up ep %p\n", ep);
wake_up(&ep->com.waitq);
@@ -1124,6 +1101,15 @@ static int abort_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
return CPL_RET_BUF_DONE;
}
+/*
+ * Return whether a failed active open has allocated a TID
+ */
+static inline int act_open_has_tid(int status)
+{
+ return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST &&
+ status != CPL_ERR_ARP_MISS;
+}
+
static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
{
struct iwch_ep *ep = ctx;
@@ -1133,7 +1119,7 @@ static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
status2errno(rpl->status));
connect_reply_upcall(ep, status2errno(rpl->status));
state_set(&ep->com, DEAD);
- if (ep->com.tdev->type == T3B)
+ if (ep->com.tdev->type == T3B && act_open_has_tid(rpl->status))
release_tid(ep->com.tdev, GET_TID(rpl), NULL);
cxgb3_free_atid(ep->com.tdev, ep->atid);
dst_release(ep->dst);
@@ -1378,6 +1364,7 @@ static int pass_establish(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
PDBG("%s ep %p\n", __FUNCTION__, ep);
ep->snd_seq = ntohl(req->snd_isn);
+ ep->rcv_seq = ntohl(req->rcv_isn);
set_emss(ep, ntohs(req->tcp_opt));
@@ -1485,6 +1472,13 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
int ret;
int state;
+ if (is_neg_adv_abort(req->status)) {
+ PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
+ ep->hwtid);
+ t3_l2t_send_event(ep->com.tdev, ep->l2t);
+ return CPL_RET_BUF_DONE;
+ }
+
/*
* We get 2 peer aborts from the HW. The first one must
* be ignored except for scribbling that we need one more.
@@ -1494,13 +1488,6 @@ static int peer_abort(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
return CPL_RET_BUF_DONE;
}
- if (is_neg_adv_abort(req->status)) {
- PDBG("%s neg_adv_abort ep %p tid %d\n", __FUNCTION__, ep,
- ep->hwtid);
- t3_l2t_send_event(ep->com.tdev, ep->l2t);
- return CPL_RET_BUF_DONE;
- }
-
state = state_read(&ep->com);
PDBG("%s ep %p state %u\n", __FUNCTION__, ep, state);
switch (state) {
@@ -1732,10 +1719,8 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct iwch_qp *qp = get_qhp(h, conn_param->qpn);
PDBG("%s ep %p tid %u\n", __FUNCTION__, ep, ep->hwtid);
- if (state_read(&ep->com) == DEAD) {
- put_ep(&ep->com);
+ if (state_read(&ep->com) == DEAD)
return -ECONNRESET;
- }
BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
BUG_ON(!qp);
@@ -1755,17 +1740,8 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->ird = conn_param->ird;
ep->ord = conn_param->ord;
PDBG("%s %d ird %d ord %d\n", __FUNCTION__, __LINE__, ep->ird, ep->ord);
+
get_ep(&ep->com);
- err = send_mpa_reply(ep, conn_param->private_data,
- conn_param->private_data_len);
- if (err) {
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
- cm_id->rem_ref(cm_id);
- abort_connection(ep, NULL, GFP_KERNEL);
- put_ep(&ep->com);
- return err;
- }
/* bind QP to EP and move to RTS */
attrs.mpa_attr = ep->mpa_attr;
@@ -1783,16 +1759,28 @@ int iwch_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
err = iwch_modify_qp(ep->com.qp->rhp,
ep->com.qp, mask, &attrs, 1);
+ if (err)
+ goto err;
- if (err) {
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
- cm_id->rem_ref(cm_id);
- abort_connection(ep, NULL, GFP_KERNEL);
- } else {
- state_set(&ep->com, FPDU_MODE);
- established_upcall(ep);
- }
+ err = send_mpa_reply(ep, conn_param->private_data,
+ conn_param->private_data_len);
+ if (err)
+ goto err;
+
+ /* wait for wr_ack */
+ wait_event(ep->com.waitq, ep->com.rpl_done);
+ err = ep->com.rpl_err;
+ if (err)
+ goto err;
+
+ state_set(&ep->com, FPDU_MODE);
+ established_upcall(ep);
+ put_ep(&ep->com);
+ return 0;
+err:
+ ep->com.cm_id = NULL;
+ ep->com.qp = NULL;
+ cm_id->rem_ref(cm_id);
put_ep(&ep->com);
return err;
}
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.h b/drivers/infiniband/hw/cxgb3/iwch_cm.h
index 21a388c313c..6107e7cd9b5 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.h
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.h
@@ -175,6 +175,7 @@ struct iwch_ep {
unsigned int atid;
u32 hwtid;
u32 snd_seq;
+ u32 rcv_seq;
struct l2t_entry *l2t;
struct dst_entry *dst;
struct sk_buff *mpa_skb;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index e7c2c394803..f0c77758937 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1163,9 +1163,10 @@ int iwch_register_device(struct iwch_dev *dev)
dev->ibdev.post_recv = iwch_post_receive;
- dev->ibdev.iwcm =
- (struct iw_cm_verbs *) kmalloc(sizeof(struct iw_cm_verbs),
- GFP_KERNEL);
+ dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
+ if (!dev->ibdev.iwcm)
+ return -ENOMEM;
+
dev->ibdev.iwcm->connect = iwch_connect;
dev->ibdev.iwcm->accept = iwch_accept_cr;
dev->ibdev.iwcm->reject = iwch_reject_cr;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
index 714dddbc9a9..dd89b6b91f9 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
@@ -628,9 +628,9 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
/* immediate data starts here. */
term = (struct terminate_message *)wqe->send.sgl;
build_term_codes(rsp_msg, &term->layer_etype, &term->ecode);
- build_fw_riwrh((void *)wqe, T3_WR_SEND,
- T3_COMPLETION_FLAG | T3_NOTIFY_FLAG, 1,
- qhp->ep->hwtid, 5);
+ wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_SEND) |
+ V_FW_RIWR_FLAGS(T3_COMPLETION_FLAG | T3_NOTIFY_FLAG));
+ wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid));
skb->priority = CPL_PRIORITY_DATA;
return cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
}
@@ -732,6 +732,7 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
init_attr.qp_dma_addr = qhp->wq.dma_addr;
init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
+ init_attr.irs = qhp->ep->rcv_seq;
PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
"flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
init_attr.rq_addr, init_attr.rq_size,
diff --git a/drivers/infiniband/hw/ehca/Kconfig b/drivers/infiniband/hw/ehca/Kconfig
index 1a854598e0e..59f807d8d58 100644
--- a/drivers/infiniband/hw/ehca/Kconfig
+++ b/drivers/infiniband/hw/ehca/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_EHCA
tristate "eHCA support"
- depends on IBMEBUS && INFINIBAND
+ depends on IBMEBUS
---help---
This driver supports the IBM pSeries eHCA InfiniBand adapter.
diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
index 0d6e2c4bb24..3cd6bf3402d 100644
--- a/drivers/infiniband/hw/ehca/ehca_av.c
+++ b/drivers/infiniband/hw/ehca/ehca_av.c
@@ -118,7 +118,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
}
memcpy(&av->av.grh.word_1, &gid, sizeof(gid));
}
- av->av.pmtu = EHCA_MAX_MTU;
+ av->av.pmtu = shca->max_mtu;
/* dgid comes in grh.word_3 */
memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid,
@@ -137,6 +137,8 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
struct ehca_av *av;
struct ehca_ud_av new_ehca_av;
struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca = container_of(ah->pd->device, struct ehca_shca,
+ ib_device);
u32 cur_pid = current->tgid;
if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
@@ -192,7 +194,7 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr)
memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid));
}
- new_ehca_av.pmtu = EHCA_MAX_MTU;
+ new_ehca_av.pmtu = shca->max_mtu;
memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid,
sizeof(ah_attr->grh.dgid));
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
index 1d286d3cc2d..daf823ea1ac 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
@@ -5,6 +5,7 @@
*
* Authors: Heiko J Schick <schickhj@de.ibm.com>
* Christoph Raisch <raisch@de.ibm.com>
+ * Joachim Fenkes <fenkes@de.ibm.com>
*
* Copyright (c) 2005 IBM Corporation
*
@@ -86,11 +87,17 @@ struct ehca_eq {
struct ehca_eqe_cache_entry eqe_cache[EHCA_EQE_CACHE_SIZE];
};
+struct ehca_sma_attr {
+ u16 lid, lmc, sm_sl, sm_lid;
+ u16 pkey_tbl_len, pkeys[16];
+};
+
struct ehca_sport {
struct ib_cq *ibcq_aqp1;
struct ib_qp *ibqp_aqp1;
enum ib_rate rate;
enum ib_port_state port_state;
+ struct ehca_sma_attr saved_attr;
};
struct ehca_shca {
@@ -107,6 +114,8 @@ struct ehca_shca {
struct ehca_pd *pd;
struct h_galpas galpas;
struct mutex modify_mutex;
+ u64 hca_cap;
+ int max_mtu;
};
struct ehca_pd {
@@ -115,9 +124,20 @@ struct ehca_pd {
u32 ownpid;
};
+enum ehca_ext_qp_type {
+ EQPT_NORMAL = 0,
+ EQPT_LLQP = 1,
+ EQPT_SRQBASE = 2,
+ EQPT_SRQ = 3,
+};
+
struct ehca_qp {
- struct ib_qp ib_qp;
+ union {
+ struct ib_qp ib_qp;
+ struct ib_srq ib_srq;
+ };
u32 qp_type;
+ enum ehca_ext_qp_type ext_type;
struct ipz_queue ipz_squeue;
struct ipz_queue ipz_rqueue;
struct h_galpas galpas;
@@ -140,6 +160,10 @@ struct ehca_qp {
u32 mm_count_galpa;
};
+#define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
+#define HAS_SQ(qp) (qp->ext_type != EQPT_SRQ)
+#define HAS_RQ(qp) (qp->ext_type != EQPT_SRQBASE)
+
/* must be power of 2 */
#define QP_HASHTAB_LEN 8
@@ -156,8 +180,8 @@ struct ehca_cq {
spinlock_t cb_lock;
struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
struct list_head entry;
- u32 nr_callbacks; /* #events assigned to cpu by scaling code */
- u32 nr_events; /* #events seen */
+ u32 nr_callbacks; /* #events assigned to cpu by scaling code */
+ atomic_t nr_events; /* #events seen */
wait_queue_head_t wait_completion;
spinlock_t task_lock;
u32 ownpid;
@@ -275,9 +299,8 @@ void ehca_cleanup_av_cache(void);
int ehca_init_mrmw_cache(void);
void ehca_cleanup_mrmw_cache(void);
-extern spinlock_t ehca_qp_idr_lock;
-extern spinlock_t ehca_cq_idr_lock;
-extern spinlock_t hcall_lock;
+extern rwlock_t ehca_qp_idr_lock;
+extern rwlock_t ehca_cq_idr_lock;
extern struct idr ehca_qp_idr;
extern struct idr ehca_cq_idr;
@@ -305,6 +328,7 @@ struct ehca_create_qp_resp {
u32 qp_num;
u32 token;
u32 qp_type;
+ u32 ext_type;
u32 qkey;
/* qp_num assigned by ehca: sqp0/1 may have got different numbers */
u32 real_qp_num;
@@ -320,14 +344,42 @@ struct ehca_alloc_cq_parms {
struct ipz_eq_handle eq_handle;
};
+enum ehca_service_type {
+ ST_RC = 0,
+ ST_UC = 1,
+ ST_RD = 2,
+ ST_UD = 3,
+};
+
+enum ehca_ll_comp_flags {
+ LLQP_SEND_COMP = 0x20,
+ LLQP_RECV_COMP = 0x40,
+ LLQP_COMP_MASK = 0x60,
+};
+
struct ehca_alloc_qp_parms {
- int servicetype;
+/* input parameters */
+ enum ehca_service_type servicetype;
int sigtype;
- int daqp_ctrl;
- int max_send_sge;
- int max_recv_sge;
+ enum ehca_ext_qp_type ext_type;
+ enum ehca_ll_comp_flags ll_comp_flags;
+
+ int max_send_wr, max_recv_wr;
+ int max_send_sge, max_recv_sge;
int ud_av_l_key_ctl;
+ u32 token;
+ struct ipz_eq_handle eq_handle;
+ struct ipz_pd pd;
+ struct ipz_cq_handle send_cq_handle, recv_cq_handle;
+
+ u32 srq_qpn, srq_token, srq_limit;
+
+/* output parameters */
+ u32 real_qp_num;
+ struct ipz_qp_handle qp_handle;
+ struct h_galpas galpas;
+
u16 act_nr_send_wqes;
u16 act_nr_recv_wqes;
u8 act_nr_recv_sges;
@@ -335,9 +387,6 @@ struct ehca_alloc_qp_parms {
u32 nr_rq_pages;
u32 nr_sq_pages;
-
- struct ipz_eq_handle ipz_eq_handle;
- struct ipz_pd pd;
};
int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp);
diff --git a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
index 5665f213b81..fb3df5c271e 100644
--- a/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
+++ b/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h
@@ -228,8 +228,8 @@ struct hcp_modify_qp_control_block {
#define MQPCB_QP_NUMBER EHCA_BMASK_IBM(8,31)
#define MQPCB_MASK_QP_ENABLE EHCA_BMASK_IBM(48,48)
#define MQPCB_QP_ENABLE EHCA_BMASK_IBM(31,31)
-#define MQPCB_MASK_CURR_SQR_LIMIT EHCA_BMASK_IBM(49,49)
-#define MQPCB_CURR_SQR_LIMIT EHCA_BMASK_IBM(15,31)
+#define MQPCB_MASK_CURR_SRQ_LIMIT EHCA_BMASK_IBM(49,49)
+#define MQPCB_CURR_SRQ_LIMIT EHCA_BMASK_IBM(16,31)
#define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG EHCA_BMASK_IBM(50,50)
#define MQPCB_MASK_SHARED_RQ_HNDL EHCA_BMASK_IBM(51,51)
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index 67f0670fe3b..01d4a148bd7 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -56,11 +56,11 @@ int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp)
{
unsigned int qp_num = qp->real_qp_num;
unsigned int key = qp_num & (QP_HASHTAB_LEN-1);
- unsigned long spl_flags;
+ unsigned long flags;
- spin_lock_irqsave(&cq->spinlock, spl_flags);
+ spin_lock_irqsave(&cq->spinlock, flags);
hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]);
- spin_unlock_irqrestore(&cq->spinlock, spl_flags);
+ spin_unlock_irqrestore(&cq->spinlock, flags);
ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x",
cq->cq_number, qp_num);
@@ -74,9 +74,9 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1);
struct hlist_node *iter;
struct ehca_qp *qp;
- unsigned long spl_flags;
+ unsigned long flags;
- spin_lock_irqsave(&cq->spinlock, spl_flags);
+ spin_lock_irqsave(&cq->spinlock, flags);
hlist_for_each(iter, &cq->qp_hashtab[key]) {
qp = hlist_entry(iter, struct ehca_qp, list_entries);
if (qp->real_qp_num == real_qp_num) {
@@ -88,7 +88,7 @@ int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num)
break;
}
}
- spin_unlock_irqrestore(&cq->spinlock, spl_flags);
+ spin_unlock_irqrestore(&cq->spinlock, flags);
if (ret)
ehca_err(cq->ib_cq.device,
"qp not found cq_num=%x real_qp_num=%x",
@@ -146,6 +146,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
spin_lock_init(&my_cq->spinlock);
spin_lock_init(&my_cq->cb_lock);
spin_lock_init(&my_cq->task_lock);
+ atomic_set(&my_cq->nr_events, 0);
init_waitqueue_head(&my_cq->wait_completion);
my_cq->ownpid = current->tgid;
@@ -162,9 +163,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
goto create_cq_exit1;
}
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ write_lock_irqsave(&ehca_cq_idr_lock, flags);
ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token);
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
} while (ret == -EAGAIN);
@@ -293,9 +294,9 @@ create_cq_exit3:
"cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret);
create_cq_exit2:
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ write_lock_irqsave(&ehca_cq_idr_lock, flags);
idr_remove(&ehca_cq_idr, my_cq->token);
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
create_cq_exit1:
kmem_cache_free(cq_cache, my_cq);
@@ -303,16 +304,6 @@ create_cq_exit1:
return cq;
}
-static int get_cq_nr_events(struct ehca_cq *my_cq)
-{
- int ret;
- unsigned long flags;
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
- ret = my_cq->nr_events;
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
- return ret;
-}
-
int ehca_destroy_cq(struct ib_cq *cq)
{
u64 h_ret;
@@ -339,17 +330,18 @@ int ehca_destroy_cq(struct ib_cq *cq)
}
}
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
- while (my_cq->nr_events) {
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
- wait_event(my_cq->wait_completion, !get_cq_nr_events(my_cq));
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
- /* recheck nr_events to assure no cqe has just arrived */
- }
-
+ /*
+ * remove the CQ from the idr first to make sure
+ * no more interrupt tasklets will touch this CQ
+ */
+ write_lock_irqsave(&ehca_cq_idr_lock, flags);
idr_remove(&ehca_cq_idr, my_cq->token);
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ write_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+
+ /* now wait until all pending events have completed */
+ wait_event(my_cq->wait_completion, !atomic_read(&my_cq->nr_events));
+ /* nobody's using our CQ any longer -- we can destroy it */
h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
if (h_ret == H_R_STATE) {
/* cq in err: read err data and destroy it forcibly */
diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c
index 32b55a4f0e5..bbd3c6a5822 100644
--- a/drivers/infiniband/hw/ehca/ehca_hca.c
+++ b/drivers/infiniband/hw/ehca/ehca_hca.c
@@ -45,11 +45,25 @@
int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
{
- int ret = 0;
+ int i, ret = 0;
struct ehca_shca *shca = container_of(ibdev, struct ehca_shca,
ib_device);
struct hipz_query_hca *rblock;
+ static const u32 cap_mapping[] = {
+ IB_DEVICE_RESIZE_MAX_WR, HCA_CAP_WQE_RESIZE,
+ IB_DEVICE_BAD_PKEY_CNTR, HCA_CAP_BAD_P_KEY_CTR,
+ IB_DEVICE_BAD_QKEY_CNTR, HCA_CAP_Q_KEY_VIOL_CTR,
+ IB_DEVICE_RAW_MULTI, HCA_CAP_RAW_PACKET_MCAST,
+ IB_DEVICE_AUTO_PATH_MIG, HCA_CAP_AUTO_PATH_MIG,
+ IB_DEVICE_CHANGE_PHY_PORT, HCA_CAP_SQD_RTS_PORT_CHANGE,
+ IB_DEVICE_UD_AV_PORT_ENFORCE, HCA_CAP_AH_PORT_NR_CHECK,
+ IB_DEVICE_CURR_QP_STATE_MOD, HCA_CAP_CUR_QP_STATE_MOD,
+ IB_DEVICE_SHUTDOWN_PORT, HCA_CAP_SHUTDOWN_PORT,
+ IB_DEVICE_INIT_TYPE, HCA_CAP_INIT_TYPE,
+ IB_DEVICE_PORT_ACTIVE_EVENT, HCA_CAP_PORT_ACTIVE_EVENT,
+ };
+
rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
@@ -96,6 +110,13 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
props->max_total_mcast_qp_attach
= min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX);
+ /* translate device capabilities */
+ props->device_cap_flags = IB_DEVICE_SYS_IMAGE_GUID |
+ IB_DEVICE_RC_RNR_NAK_GEN | IB_DEVICE_N_NOTIFY_CQ;
+ for (i = 0; i < ARRAY_SIZE(cap_mapping); i += 2)
+ if (rblock->hca_cap_indicators & cap_mapping[i + 1])
+ props->device_cap_flags |= cap_mapping[i];
+
query_device1:
ehca_free_fw_ctrlblock(rblock);
@@ -172,6 +193,40 @@ query_port1:
return ret;
}
+int ehca_query_sma_attr(struct ehca_shca *shca,
+ u8 port, struct ehca_sma_attr *attr)
+{
+ int ret = 0;
+ struct hipz_query_port *rblock;
+
+ rblock = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+ if (!rblock) {
+ ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
+ return -ENOMEM;
+ }
+
+ if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) {
+ ehca_err(&shca->ib_device, "Can't query port properties");
+ ret = -EINVAL;
+ goto query_sma_attr1;
+ }
+
+ memset(attr, 0, sizeof(struct ehca_sma_attr));
+
+ attr->lid = rblock->lid;
+ attr->lmc = rblock->lmc;
+ attr->sm_sl = rblock->sm_sl;
+ attr->sm_lid = rblock->sm_lid;
+
+ attr->pkey_tbl_len = rblock->pkey_tbl_len;
+ memcpy(attr->pkeys, rblock->pkey_entries, sizeof(attr->pkeys));
+
+query_sma_attr1:
+ ehca_free_fw_ctrlblock(rblock);
+
+ return ret;
+}
+
int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
{
int ret = 0;
@@ -261,7 +316,7 @@ int ehca_modify_port(struct ib_device *ibdev,
}
if (mutex_lock_interruptible(&shca->modify_mutex))
- return -ERESTARTSYS;
+ return -ERESTARTSYS;
rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
@@ -290,7 +345,7 @@ modify_port2:
ehca_free_fw_ctrlblock(rblock);
modify_port1:
- mutex_unlock(&shca->modify_mutex);
+ mutex_unlock(&shca->modify_mutex);
return ret;
}
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 100329ba334..96eba383075 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -5,6 +5,8 @@
*
* Authors: Heiko J Schick <schickhj@de.ibm.com>
* Khadija Souissi <souissi@de.ibm.com>
+ * Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ * Joachim Fenkes <fenkes@de.ibm.com>
*
* Copyright (c) 2005 IBM Corporation
*
@@ -59,6 +61,7 @@
#define NEQE_EVENT_CODE EHCA_BMASK_IBM(2,7)
#define NEQE_PORT_NUMBER EHCA_BMASK_IBM(8,15)
#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16)
+#define NEQE_DISRUPTIVE EHCA_BMASK_IBM(16,16)
#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52,63)
#define ERROR_DATA_TYPE EHCA_BMASK_IBM(0,7)
@@ -178,12 +181,11 @@ static void qp_event_callback(struct ehca_shca *shca,
{
struct ib_event event;
struct ehca_qp *qp;
- unsigned long flags;
u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe);
- spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+ read_lock(&ehca_qp_idr_lock);
qp = idr_find(&ehca_qp_idr, token);
- spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+ read_unlock(&ehca_qp_idr_lock);
if (!qp)
@@ -207,18 +209,22 @@ static void cq_event_callback(struct ehca_shca *shca,
u64 eqe)
{
struct ehca_cq *cq;
- unsigned long flags;
u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe);
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ read_lock(&ehca_cq_idr_lock);
cq = idr_find(&ehca_cq_idr, token);
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ if (cq)
+ atomic_inc(&cq->nr_events);
+ read_unlock(&ehca_cq_idr_lock);
if (!cq)
return;
ehca_error_data(shca, cq, cq->ipz_cq_handle.handle);
+ if (atomic_dec_and_test(&cq->nr_events))
+ wake_up(&cq->wait_completion);
+
return;
}
@@ -281,30 +287,61 @@ static void parse_identifier(struct ehca_shca *shca, u64 eqe)
return;
}
-static void parse_ec(struct ehca_shca *shca, u64 eqe)
+static void dispatch_port_event(struct ehca_shca *shca, int port_num,
+ enum ib_event_type type, const char *msg)
{
struct ib_event event;
+
+ ehca_info(&shca->ib_device, "port %d %s.", port_num, msg);
+ event.device = &shca->ib_device;
+ event.event = type;
+ event.element.port_num = port_num;
+ ib_dispatch_event(&event);
+}
+
+static void notify_port_conf_change(struct ehca_shca *shca, int port_num)
+{
+ struct ehca_sma_attr new_attr;
+ struct ehca_sma_attr *old_attr = &shca->sport[port_num - 1].saved_attr;
+
+ ehca_query_sma_attr(shca, port_num, &new_attr);
+
+ if (new_attr.sm_sl != old_attr->sm_sl ||
+ new_attr.sm_lid != old_attr->sm_lid)
+ dispatch_port_event(shca, port_num, IB_EVENT_SM_CHANGE,
+ "SM changed");
+
+ if (new_attr.lid != old_attr->lid ||
+ new_attr.lmc != old_attr->lmc)
+ dispatch_port_event(shca, port_num, IB_EVENT_LID_CHANGE,
+ "LID changed");
+
+ if (new_attr.pkey_tbl_len != old_attr->pkey_tbl_len ||
+ memcmp(new_attr.pkeys, old_attr->pkeys,
+ sizeof(u16) * new_attr.pkey_tbl_len))
+ dispatch_port_event(shca, port_num, IB_EVENT_PKEY_CHANGE,
+ "P_Key changed");
+
+ *old_attr = new_attr;
+}
+
+static void parse_ec(struct ehca_shca *shca, u64 eqe)
+{
u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
switch (ec) {
case 0x30: /* port availability change */
if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
- ehca_info(&shca->ib_device,
- "port %x is active.", port);
- event.device = &shca->ib_device;
- event.event = IB_EVENT_PORT_ACTIVE;
- event.element.port_num = port;
shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
- ib_dispatch_event(&event);
+ dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+ "is active");
+ ehca_query_sma_attr(shca, port,
+ &shca->sport[port - 1].saved_attr);
} else {
- ehca_info(&shca->ib_device,
- "port %x is inactive.", port);
- event.device = &shca->ib_device;
- event.event = IB_EVENT_PORT_ERR;
- event.element.port_num = port;
shca->sport[port - 1].port_state = IB_PORT_DOWN;
- ib_dispatch_event(&event);
+ dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+ "is inactive");
}
break;
case 0x31:
@@ -312,24 +349,19 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
* disruptive change is caused by
* LID, PKEY or SM change
*/
- ehca_warn(&shca->ib_device,
- "disruptive port %x configuration change", port);
-
- ehca_info(&shca->ib_device,
- "port %x is inactive.", port);
- event.device = &shca->ib_device;
- event.event = IB_EVENT_PORT_ERR;
- event.element.port_num = port;
- shca->sport[port - 1].port_state = IB_PORT_DOWN;
- ib_dispatch_event(&event);
-
- ehca_info(&shca->ib_device,
- "port %x is active.", port);
- event.device = &shca->ib_device;
- event.event = IB_EVENT_PORT_ACTIVE;
- event.element.port_num = port;
- shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
- ib_dispatch_event(&event);
+ if (EHCA_BMASK_GET(NEQE_DISRUPTIVE, eqe)) {
+ ehca_warn(&shca->ib_device, "disruptive port "
+ "%d configuration change", port);
+
+ shca->sport[port - 1].port_state = IB_PORT_DOWN;
+ dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+ "is inactive");
+
+ shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
+ dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+ "is active");
+ } else
+ notify_port_conf_change(shca, port);
break;
case 0x32: /* adapter malfunction */
ehca_err(&shca->ib_device, "Adapter malfunction.");
@@ -404,7 +436,6 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
{
u64 eqe_value;
u32 token;
- unsigned long flags;
struct ehca_cq *cq;
eqe_value = eqe->entry;
@@ -412,27 +443,24 @@ static inline void process_eqe(struct ehca_shca *shca, struct ehca_eqe *eqe)
if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
ehca_dbg(&shca->ib_device, "Got completion event");
token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ read_lock(&ehca_cq_idr_lock);
cq = idr_find(&ehca_cq_idr, token);
+ if (cq)
+ atomic_inc(&cq->nr_events);
+ read_unlock(&ehca_cq_idr_lock);
if (cq == NULL) {
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
ehca_err(&shca->ib_device,
"Invalid eqe for non-existing cq token=%x",
token);
return;
}
reset_eq_pending(cq);
- cq->nr_events++;
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
if (ehca_scaling_code)
queue_comp_task(cq);
else {
comp_event_callback(cq);
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
- cq->nr_events--;
- if (!cq->nr_events)
+ if (atomic_dec_and_test(&cq->nr_events))
wake_up(&cq->wait_completion);
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
}
} else {
ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -476,17 +504,17 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
eqe_value = eqe_cache[eqe_cnt].eqe->entry;
if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, eqe_value)) {
token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe_value);
- spin_lock(&ehca_cq_idr_lock);
+ read_lock(&ehca_cq_idr_lock);
eqe_cache[eqe_cnt].cq = idr_find(&ehca_cq_idr, token);
+ if (eqe_cache[eqe_cnt].cq)
+ atomic_inc(&eqe_cache[eqe_cnt].cq->nr_events);
+ read_unlock(&ehca_cq_idr_lock);
if (!eqe_cache[eqe_cnt].cq) {
- spin_unlock(&ehca_cq_idr_lock);
ehca_err(&shca->ib_device,
"Invalid eqe for non-existing cq "
"token=%x", token);
continue;
}
- eqe_cache[eqe_cnt].cq->nr_events++;
- spin_unlock(&ehca_cq_idr_lock);
} else
eqe_cache[eqe_cnt].cq = NULL;
eqe_cnt++;
@@ -517,11 +545,8 @@ void ehca_process_eq(struct ehca_shca *shca, int is_irq)
else {
struct ehca_cq *cq = eq->eqe_cache[i].cq;
comp_event_callback(cq);
- spin_lock(&ehca_cq_idr_lock);
- cq->nr_events--;
- if (!cq->nr_events)
+ if (atomic_dec_and_test(&cq->nr_events))
wake_up(&cq->wait_completion);
- spin_unlock(&ehca_cq_idr_lock);
}
} else {
ehca_dbg(&shca->ib_device, "Got non completion event");
@@ -621,13 +646,10 @@ static void run_comp_task(struct ehca_cpu_comp_task* cct)
while (!list_empty(&cct->cq_list)) {
cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
spin_unlock_irqrestore(&cct->task_lock, flags);
- comp_event_callback(cq);
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
- cq->nr_events--;
- if (!cq->nr_events)
+ comp_event_callback(cq);
+ if (atomic_dec_and_test(&cq->nr_events))
wake_up(&cq->wait_completion);
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
spin_lock_irqsave(&cct->task_lock, flags);
spin_lock(&cq->task_lock);
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index 6ed06ee033e..3346cb06cea 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -47,7 +47,6 @@ struct ehca_shca;
#include <linux/interrupt.h>
#include <linux/types.h>
-#include <asm/atomic.h>
int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource);
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
index 37e7fe0908c..77aeca6a2c2 100644
--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
@@ -49,6 +49,9 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props);
int ehca_query_port(struct ib_device *ibdev, u8 port,
struct ib_port_attr *props);
+int ehca_query_sma_attr(struct ehca_shca *shca, u8 port,
+ struct ehca_sma_attr *attr);
+
int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey);
int ehca_query_gid(struct ib_device *ibdev, u8 port, int index,
@@ -154,6 +157,21 @@ int ehca_post_send(struct ib_qp *qp, struct ib_send_wr *send_wr,
int ehca_post_recv(struct ib_qp *qp, struct ib_recv_wr *recv_wr,
struct ib_recv_wr **bad_recv_wr);
+int ehca_post_srq_recv(struct ib_srq *srq,
+ struct ib_recv_wr *recv_wr,
+ struct ib_recv_wr **bad_recv_wr);
+
+struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+ struct ib_srq_init_attr *init_attr,
+ struct ib_udata *udata);
+
+int ehca_modify_srq(struct ib_srq *srq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
+
+int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
+
+int ehca_destroy_srq(struct ib_srq *srq);
+
u64 ehca_define_sqp(struct ehca_shca *shca, struct ehca_qp *ibqp,
struct ib_qp_init_attr *qp_init_attr);
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index c3f99f33b49..28ba2dd2421 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -94,17 +94,15 @@ MODULE_PARM_DESC(poll_all_eqs,
MODULE_PARM_DESC(static_rate,
"set permanent static rate (default: disabled)");
MODULE_PARM_DESC(scaling_code,
- "set scaling code (0: disabled, 1: enabled/default)");
+ "set scaling code (0: disabled/default, 1: enabled)");
-spinlock_t ehca_qp_idr_lock;
-spinlock_t ehca_cq_idr_lock;
-spinlock_t hcall_lock;
+DEFINE_RWLOCK(ehca_qp_idr_lock);
+DEFINE_RWLOCK(ehca_cq_idr_lock);
DEFINE_IDR(ehca_qp_idr);
DEFINE_IDR(ehca_cq_idr);
-
-static struct list_head shca_list; /* list of all registered ehcas */
-static spinlock_t shca_list_lock;
+static LIST_HEAD(shca_list); /* list of all registered ehcas */
+static DEFINE_SPINLOCK(shca_list_lock);
static struct timer_list poll_eqs_timer;
@@ -205,11 +203,35 @@ static void ehca_destroy_slab_caches(void)
#define EHCA_HCAAVER EHCA_BMASK_IBM(32,39)
#define EHCA_REVID EHCA_BMASK_IBM(40,63)
+static struct cap_descr {
+ u64 mask;
+ char *descr;
+} hca_cap_descr[] = {
+ { HCA_CAP_AH_PORT_NR_CHECK, "HCA_CAP_AH_PORT_NR_CHECK" },
+ { HCA_CAP_ATOMIC, "HCA_CAP_ATOMIC" },
+ { HCA_CAP_AUTO_PATH_MIG, "HCA_CAP_AUTO_PATH_MIG" },
+ { HCA_CAP_BAD_P_KEY_CTR, "HCA_CAP_BAD_P_KEY_CTR" },
+ { HCA_CAP_SQD_RTS_PORT_CHANGE, "HCA_CAP_SQD_RTS_PORT_CHANGE" },
+ { HCA_CAP_CUR_QP_STATE_MOD, "HCA_CAP_CUR_QP_STATE_MOD" },
+ { HCA_CAP_INIT_TYPE, "HCA_CAP_INIT_TYPE" },
+ { HCA_CAP_PORT_ACTIVE_EVENT, "HCA_CAP_PORT_ACTIVE_EVENT" },
+ { HCA_CAP_Q_KEY_VIOL_CTR, "HCA_CAP_Q_KEY_VIOL_CTR" },
+ { HCA_CAP_WQE_RESIZE, "HCA_CAP_WQE_RESIZE" },
+ { HCA_CAP_RAW_PACKET_MCAST, "HCA_CAP_RAW_PACKET_MCAST" },
+ { HCA_CAP_SHUTDOWN_PORT, "HCA_CAP_SHUTDOWN_PORT" },
+ { HCA_CAP_RC_LL_QP, "HCA_CAP_RC_LL_QP" },
+ { HCA_CAP_SRQ, "HCA_CAP_SRQ" },
+ { HCA_CAP_UD_LL_QP, "HCA_CAP_UD_LL_QP" },
+ { HCA_CAP_RESIZE_MR, "HCA_CAP_RESIZE_MR" },
+ { HCA_CAP_MINI_QP, "HCA_CAP_MINI_QP" },
+};
+
int ehca_sense_attributes(struct ehca_shca *shca)
{
- int ret = 0;
+ int i, ret = 0;
u64 h_ret;
struct hipz_query_hca *rblock;
+ struct hipz_query_port *port;
rblock = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
if (!rblock) {
@@ -222,7 +244,7 @@ int ehca_sense_attributes(struct ehca_shca *shca)
ehca_gen_err("Cannot query device properties. h_ret=%lx",
h_ret);
ret = -EPERM;
- goto num_ports1;
+ goto sense_attributes1;
}
if (ehca_nr_ports == 1)
@@ -242,18 +264,44 @@ int ehca_sense_attributes(struct ehca_shca *shca)
ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid);
if ((hcaaver == 1) && (revid == 0))
- shca->hw_level = 0;
+ shca->hw_level = 0x11;
else if ((hcaaver == 1) && (revid == 1))
- shca->hw_level = 1;
+ shca->hw_level = 0x12;
else if ((hcaaver == 1) && (revid == 2))
- shca->hw_level = 2;
+ shca->hw_level = 0x13;
+ else if ((hcaaver == 2) && (revid == 0))
+ shca->hw_level = 0x21;
+ else if ((hcaaver == 2) && (revid == 0x10))
+ shca->hw_level = 0x22;
+ else {
+ ehca_gen_warn("unknown hardware version"
+ " - assuming default level");
+ shca->hw_level = 0x22;
+ }
}
ehca_gen_dbg(" ... hardware level=%x", shca->hw_level);
shca->sport[0].rate = IB_RATE_30_GBPS;
shca->sport[1].rate = IB_RATE_30_GBPS;
-num_ports1:
+ shca->hca_cap = rblock->hca_cap_indicators;
+ ehca_gen_dbg(" ... HCA capabilities:");
+ for (i = 0; i < ARRAY_SIZE(hca_cap_descr); i++)
+ if (EHCA_BMASK_GET(hca_cap_descr[i].mask, shca->hca_cap))
+ ehca_gen_dbg(" %s", hca_cap_descr[i].descr);
+
+ port = (struct hipz_query_port *) rblock;
+ h_ret = hipz_h_query_port(shca->ipz_hca_handle, 1, port);
+ if (h_ret != H_SUCCESS) {
+ ehca_gen_err("Cannot query port properties. h_ret=%lx",
+ h_ret);
+ ret = -EPERM;
+ goto sense_attributes1;
+ }
+
+ shca->max_mtu = port->max_mtu;
+
+sense_attributes1:
ehca_free_fw_ctrlblock(rblock);
return ret;
}
@@ -293,7 +341,7 @@ int ehca_init_device(struct ehca_shca *shca)
strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
shca->ib_device.owner = THIS_MODULE;
- shca->ib_device.uverbs_abi_ver = 6;
+ shca->ib_device.uverbs_abi_ver = 7;
shca->ib_device.uverbs_cmd_mask =
(1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
@@ -361,6 +409,20 @@ int ehca_init_device(struct ehca_shca *shca)
/* shca->ib_device.process_mad = ehca_process_mad; */
shca->ib_device.mmap = ehca_mmap;
+ if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+ shca->ib_device.uverbs_cmd_mask |=
+ (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
+
+ shca->ib_device.create_srq = ehca_create_srq;
+ shca->ib_device.modify_srq = ehca_modify_srq;
+ shca->ib_device.query_srq = ehca_query_srq;
+ shca->ib_device.destroy_srq = ehca_destroy_srq;
+ shca->ib_device.post_srq_recv = ehca_post_srq_recv;
+ }
+
return ret;
}
@@ -800,14 +862,6 @@ int __init ehca_module_init(void)
printk(KERN_INFO "eHCA Infiniband Device Driver "
"(Rel.: SVNEHCA_0023)\n");
- idr_init(&ehca_qp_idr);
- idr_init(&ehca_cq_idr);
- spin_lock_init(&ehca_qp_idr_lock);
- spin_lock_init(&ehca_cq_idr_lock);
- spin_lock_init(&hcall_lock);
-
- INIT_LIST_HEAD(&shca_list);
- spin_lock_init(&shca_list_lock);
if ((ret = ehca_create_comp_pool())) {
ehca_gen_err("Cannot create comp pool.");
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index b5bc787c77b..74671250303 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -3,7 +3,9 @@
*
* QP functions
*
- * Authors: Waleri Fomin <fomin@de.ibm.com>
+ * Authors: Joachim Fenkes <fenkes@de.ibm.com>
+ * Stefan Roscher <stefan.roscher@de.ibm.com>
+ * Waleri Fomin <fomin@de.ibm.com>
* Hoang-Nam Nguyen <hnguyen@de.ibm.com>
* Reinhard Ernst <rernst@de.ibm.com>
* Heiko J Schick <schickhj@de.ibm.com>
@@ -234,13 +236,6 @@ static inline enum ib_qp_statetrans get_modqp_statetrans(int ib_fromstate,
return index;
}
-enum ehca_service_type {
- ST_RC = 0,
- ST_UC = 1,
- ST_RD = 2,
- ST_UD = 3
-};
-
/*
* ibqptype2servicetype returns hcp service type corresponding to given
* ib qp type used by create_qp()
@@ -268,15 +263,34 @@ static inline int ibqptype2servicetype(enum ib_qp_type ibqptype)
}
/*
- * init_qp_queues initializes/constructs r/squeue and registers queue pages.
+ * init userspace queue info from ipz_queue data
*/
-static inline int init_qp_queues(struct ehca_shca *shca,
- struct ehca_qp *my_qp,
- int nr_sq_pages,
- int nr_rq_pages,
- int swqe_size,
- int rwqe_size,
- int nr_send_sges, int nr_receive_sges)
+static inline void queue2resp(struct ipzu_queue_resp *resp,
+ struct ipz_queue *queue)
+{
+ resp->qe_size = queue->qe_size;
+ resp->act_nr_of_sg = queue->act_nr_of_sg;
+ resp->queue_length = queue->queue_length;
+ resp->pagesize = queue->pagesize;
+ resp->toggle_state = queue->toggle_state;
+}
+
+static inline int ll_qp_msg_size(int nr_sge)
+{
+ return 128 << nr_sge;
+}
+
+/*
+ * init_qp_queue initializes/constructs r/squeue and registers queue pages.
+ */
+static inline int init_qp_queue(struct ehca_shca *shca,
+ struct ehca_qp *my_qp,
+ struct ipz_queue *queue,
+ int q_type,
+ u64 expected_hret,
+ int nr_q_pages,
+ int wqe_size,
+ int nr_sges)
{
int ret, cnt, ipz_rc;
void *vpage;
@@ -284,127 +298,93 @@ static inline int init_qp_queues(struct ehca_shca *shca,
struct ib_device *ib_dev = &shca->ib_device;
struct ipz_adapter_handle ipz_hca_handle = shca->ipz_hca_handle;
- ipz_rc = ipz_queue_ctor(&my_qp->ipz_squeue,
- nr_sq_pages,
- EHCA_PAGESIZE, swqe_size, nr_send_sges);
+ if (!nr_q_pages)
+ return 0;
+
+ ipz_rc = ipz_queue_ctor(queue, nr_q_pages, EHCA_PAGESIZE,
+ wqe_size, nr_sges);
if (!ipz_rc) {
- ehca_err(ib_dev,"Cannot allocate page for squeue. ipz_rc=%x",
+ ehca_err(ib_dev, "Cannot allocate page for queue. ipz_rc=%x",
ipz_rc);
return -EBUSY;
}
- ipz_rc = ipz_queue_ctor(&my_qp->ipz_rqueue,
- nr_rq_pages,
- EHCA_PAGESIZE, rwqe_size, nr_receive_sges);
- if (!ipz_rc) {
- ehca_err(ib_dev, "Cannot allocate page for rqueue. ipz_rc=%x",
- ipz_rc);
- ret = -EBUSY;
- goto init_qp_queues0;
- }
- /* register SQ pages */
- for (cnt = 0; cnt < nr_sq_pages; cnt++) {
- vpage = ipz_qpageit_get_inc(&my_qp->ipz_squeue);
+ /* register queue pages */
+ for (cnt = 0; cnt < nr_q_pages; cnt++) {
+ vpage = ipz_qpageit_get_inc(queue);
if (!vpage) {
- ehca_err(ib_dev, "SQ ipz_qpageit_get_inc() "
+ ehca_err(ib_dev, "ipz_qpageit_get_inc() "
"failed p_vpage= %p", vpage);
ret = -EINVAL;
- goto init_qp_queues1;
+ goto init_qp_queue1;
}
rpage = virt_to_abs(vpage);
h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
my_qp->ipz_qp_handle,
- &my_qp->pf, 0, 0,
+ NULL, 0, q_type,
rpage, 1,
my_qp->galpas.kernel);
- if (h_ret < H_SUCCESS) {
- ehca_err(ib_dev, "SQ hipz_qp_register_rpage()"
- " failed rc=%lx", h_ret);
- ret = ehca2ib_return_code(h_ret);
- goto init_qp_queues1;
- }
- }
-
- ipz_qeit_reset(&my_qp->ipz_squeue);
-
- /* register RQ pages */
- for (cnt = 0; cnt < nr_rq_pages; cnt++) {
- vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue);
- if (!vpage) {
- ehca_err(ib_dev, "RQ ipz_qpageit_get_inc() "
- "failed p_vpage = %p", vpage);
- ret = -EINVAL;
- goto init_qp_queues1;
- }
-
- rpage = virt_to_abs(vpage);
-
- h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
- my_qp->ipz_qp_handle,
- &my_qp->pf, 0, 1,
- rpage, 1,my_qp->galpas.kernel);
- if (h_ret < H_SUCCESS) {
- ehca_err(ib_dev, "RQ hipz_qp_register_rpage() failed "
- "rc=%lx", h_ret);
- ret = ehca2ib_return_code(h_ret);
- goto init_qp_queues1;
- }
- if (cnt == (nr_rq_pages - 1)) { /* last page! */
- if (h_ret != H_SUCCESS) {
- ehca_err(ib_dev, "RQ hipz_qp_register_rpage() "
+ if (cnt == (nr_q_pages - 1)) { /* last page! */
+ if (h_ret != expected_hret) {
+ ehca_err(ib_dev, "hipz_qp_register_rpage() "
"h_ret= %lx ", h_ret);
ret = ehca2ib_return_code(h_ret);
- goto init_qp_queues1;
+ goto init_qp_queue1;
}
vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue);
if (vpage) {
ehca_err(ib_dev, "ipz_qpageit_get_inc() "
"should not succeed vpage=%p", vpage);
ret = -EINVAL;
- goto init_qp_queues1;
+ goto init_qp_queue1;
}
} else {
if (h_ret != H_PAGE_REGISTERED) {
- ehca_err(ib_dev, "RQ hipz_qp_register_rpage() "
+ ehca_err(ib_dev, "hipz_qp_register_rpage() "
"h_ret= %lx ", h_ret);
ret = ehca2ib_return_code(h_ret);
- goto init_qp_queues1;
+ goto init_qp_queue1;
}
}
}
- ipz_qeit_reset(&my_qp->ipz_rqueue);
+ ipz_qeit_reset(queue);
return 0;
-init_qp_queues1:
- ipz_queue_dtor(&my_qp->ipz_rqueue);
-init_qp_queues0:
- ipz_queue_dtor(&my_qp->ipz_squeue);
+init_qp_queue1:
+ ipz_queue_dtor(queue);
return ret;
}
-struct ib_qp *ehca_create_qp(struct ib_pd *pd,
- struct ib_qp_init_attr *init_attr,
- struct ib_udata *udata)
+/*
+ * Create an ib_qp struct that is either a QP or an SRQ, depending on
+ * the value of the is_srq parameter. If init_attr and srq_init_attr share
+ * fields, the field out of init_attr is used.
+ */
+struct ehca_qp *internal_create_qp(struct ib_pd *pd,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_srq_init_attr *srq_init_attr,
+ struct ib_udata *udata, int is_srq)
{
- static int da_rc_msg_size[]={ 128, 256, 512, 1024, 2048, 4096 };
- static int da_ud_sq_msg_size[]={ 128, 384, 896, 1920, 3968 };
struct ehca_qp *my_qp;
struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd);
struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
ib_device);
struct ib_ucontext *context = NULL;
u64 h_ret;
- int max_send_sge, max_recv_sge, ret;
+ int is_llqp = 0, has_srq = 0;
+ int qp_type, max_send_sge, max_recv_sge, ret;
/* h_call's out parameters */
struct ehca_alloc_qp_parms parms;
- u32 swqe_size = 0, rwqe_size = 0;
- u8 daqp_completion, isdaqp;
+ u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
unsigned long flags;
+ memset(&parms, 0, sizeof(parms));
+ qp_type = init_attr->qp_type;
+
if (init_attr->sq_sig_type != IB_SIGNAL_REQ_WR &&
init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) {
ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed",
@@ -412,41 +392,98 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
return ERR_PTR(-EINVAL);
}
- /* save daqp completion bits */
- daqp_completion = init_attr->qp_type & 0x60;
- /* save daqp bit */
- isdaqp = (init_attr->qp_type & 0x80) ? 1 : 0;
- init_attr->qp_type = init_attr->qp_type & 0x1F;
+ /* save LLQP info */
+ if (qp_type & 0x80) {
+ is_llqp = 1;
+ parms.ext_type = EQPT_LLQP;
+ parms.ll_comp_flags = qp_type & LLQP_COMP_MASK;
+ }
+ qp_type &= 0x1F;
+ init_attr->qp_type &= 0x1F;
- if (init_attr->qp_type != IB_QPT_UD &&
- init_attr->qp_type != IB_QPT_SMI &&
- init_attr->qp_type != IB_QPT_GSI &&
- init_attr->qp_type != IB_QPT_UC &&
- init_attr->qp_type != IB_QPT_RC) {
- ehca_err(pd->device, "wrong QP Type=%x", init_attr->qp_type);
- return ERR_PTR(-EINVAL);
+ /* handle SRQ base QPs */
+ if (init_attr->srq) {
+ struct ehca_qp *my_srq =
+ container_of(init_attr->srq, struct ehca_qp, ib_srq);
+
+ has_srq = 1;
+ parms.ext_type = EQPT_SRQBASE;
+ parms.srq_qpn = my_srq->real_qp_num;
+ parms.srq_token = my_srq->token;
}
- if ((init_attr->qp_type != IB_QPT_RC && init_attr->qp_type != IB_QPT_UD)
- && isdaqp) {
- ehca_err(pd->device, "unsupported LL QP Type=%x",
- init_attr->qp_type);
+
+ if (is_llqp && has_srq) {
+ ehca_err(pd->device, "LLQPs can't have an SRQ");
return ERR_PTR(-EINVAL);
- } else if (init_attr->qp_type == IB_QPT_RC && isdaqp &&
- (init_attr->cap.max_send_wr > 255 ||
- init_attr->cap.max_recv_wr > 255 )) {
- ehca_err(pd->device, "Invalid Number of max_sq_wr =%x "
- "or max_rq_wr=%x for QP Type=%x",
- init_attr->cap.max_send_wr,
- init_attr->cap.max_recv_wr,init_attr->qp_type);
- return ERR_PTR(-EINVAL);
- } else if (init_attr->qp_type == IB_QPT_UD && isdaqp &&
- init_attr->cap.max_send_wr > 255) {
- ehca_err(pd->device,
- "Invalid Number of max_send_wr=%x for UD QP_TYPE=%x",
- init_attr->cap.max_send_wr, init_attr->qp_type);
+ }
+
+ /* handle SRQs */
+ if (is_srq) {
+ parms.ext_type = EQPT_SRQ;
+ parms.srq_limit = srq_init_attr->attr.srq_limit;
+ if (init_attr->cap.max_recv_sge > 3) {
+ ehca_err(pd->device, "no more than three SGEs "
+ "supported for SRQ pd=%p max_sge=%x",
+ pd, init_attr->cap.max_recv_sge);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
+ /* check QP type */
+ if (qp_type != IB_QPT_UD &&
+ qp_type != IB_QPT_UC &&
+ qp_type != IB_QPT_RC &&
+ qp_type != IB_QPT_SMI &&
+ qp_type != IB_QPT_GSI) {
+ ehca_err(pd->device, "wrong QP Type=%x", qp_type);
return ERR_PTR(-EINVAL);
}
+ if (is_llqp) {
+ switch (qp_type) {
+ case IB_QPT_RC:
+ if ((init_attr->cap.max_send_wr > 255) ||
+ (init_attr->cap.max_recv_wr > 255)) {
+ ehca_err(pd->device,
+ "Invalid Number of max_sq_wr=%x "
+ "or max_rq_wr=%x for RC LLQP",
+ init_attr->cap.max_send_wr,
+ init_attr->cap.max_recv_wr);
+ return ERR_PTR(-EINVAL);
+ }
+ break;
+ case IB_QPT_UD:
+ if (!EHCA_BMASK_GET(HCA_CAP_UD_LL_QP, shca->hca_cap)) {
+ ehca_err(pd->device, "UD LLQP not supported "
+ "by this adapter");
+ return ERR_PTR(-ENOSYS);
+ }
+ if (!(init_attr->cap.max_send_sge <= 5
+ && init_attr->cap.max_send_sge >= 1
+ && init_attr->cap.max_recv_sge <= 5
+ && init_attr->cap.max_recv_sge >= 1)) {
+ ehca_err(pd->device,
+ "Invalid Number of max_send_sge=%x "
+ "or max_recv_sge=%x for UD LLQP",
+ init_attr->cap.max_send_sge,
+ init_attr->cap.max_recv_sge);
+ return ERR_PTR(-EINVAL);
+ } else if (init_attr->cap.max_send_wr > 255) {
+ ehca_err(pd->device,
+ "Invalid Number of "
+ "ax_send_wr=%x for UD QP_TYPE=%x",
+ init_attr->cap.max_send_wr, qp_type);
+ return ERR_PTR(-EINVAL);
+ }
+ break;
+ default:
+ ehca_err(pd->device, "unsupported LL QP Type=%x",
+ qp_type);
+ return ERR_PTR(-EINVAL);
+ break;
+ }
+ }
+
if (pd->uobject && udata)
context = pd->uobject->context;
@@ -456,16 +493,17 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
return ERR_PTR(-ENOMEM);
}
- memset (&parms, 0, sizeof(struct ehca_alloc_qp_parms));
spin_lock_init(&my_qp->spinlock_s);
spin_lock_init(&my_qp->spinlock_r);
+ my_qp->qp_type = qp_type;
+ my_qp->ext_type = parms.ext_type;
- my_qp->recv_cq =
- container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);
- my_qp->send_cq =
- container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
-
- my_qp->init_attr = *init_attr;
+ if (init_attr->recv_cq)
+ my_qp->recv_cq =
+ container_of(init_attr->recv_cq, struct ehca_cq, ib_cq);
+ if (init_attr->send_cq)
+ my_qp->send_cq =
+ container_of(init_attr->send_cq, struct ehca_cq, ib_cq);
do {
if (!idr_pre_get(&ehca_qp_idr, GFP_KERNEL)) {
@@ -474,9 +512,9 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
goto create_qp_exit0;
}
- spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+ write_lock_irqsave(&ehca_qp_idr_lock, flags);
ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token);
- spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+ write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
} while (ret == -EAGAIN);
@@ -486,10 +524,10 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
goto create_qp_exit0;
}
- parms.servicetype = ibqptype2servicetype(init_attr->qp_type);
+ parms.servicetype = ibqptype2servicetype(qp_type);
if (parms.servicetype < 0) {
ret = -EINVAL;
- ehca_err(pd->device, "Invalid qp_type=%x", init_attr->qp_type);
+ ehca_err(pd->device, "Invalid qp_type=%x", qp_type);
goto create_qp_exit0;
}
@@ -501,21 +539,25 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
/* UD_AV CIRCUMVENTION */
max_send_sge = init_attr->cap.max_send_sge;
max_recv_sge = init_attr->cap.max_recv_sge;
- if (IB_QPT_UD == init_attr->qp_type ||
- IB_QPT_GSI == init_attr->qp_type ||
- IB_QPT_SMI == init_attr->qp_type) {
+ if (parms.servicetype == ST_UD && !is_llqp) {
max_send_sge += 2;
max_recv_sge += 2;
}
- parms.ipz_eq_handle = shca->eq.ipz_eq_handle;
- parms.daqp_ctrl = isdaqp | daqp_completion;
+ parms.token = my_qp->token;
+ parms.eq_handle = shca->eq.ipz_eq_handle;
parms.pd = my_pd->fw_pd;
- parms.max_recv_sge = max_recv_sge;
- parms.max_send_sge = max_send_sge;
+ if (my_qp->send_cq)
+ parms.send_cq_handle = my_qp->send_cq->ipz_cq_handle;
+ if (my_qp->recv_cq)
+ parms.recv_cq_handle = my_qp->recv_cq->ipz_cq_handle;
- h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, my_qp, &parms);
+ parms.max_send_wr = init_attr->cap.max_send_wr;
+ parms.max_recv_wr = init_attr->cap.max_recv_wr;
+ parms.max_send_sge = max_send_sge;
+ parms.max_recv_sge = max_recv_sge;
+ h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, &parms);
if (h_ret != H_SUCCESS) {
ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lx",
h_ret);
@@ -523,18 +565,20 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
goto create_qp_exit1;
}
- my_qp->ib_qp.qp_num = my_qp->real_qp_num;
+ ib_qp_num = my_qp->real_qp_num = parms.real_qp_num;
+ my_qp->ipz_qp_handle = parms.qp_handle;
+ my_qp->galpas = parms.galpas;
- switch (init_attr->qp_type) {
+ switch (qp_type) {
case IB_QPT_RC:
- if (isdaqp == 0) {
+ if (!is_llqp) {
swqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[
(parms.act_nr_send_sges)]);
rwqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[
(parms.act_nr_recv_sges)]);
- } else { /* for daqp we need to use msg size, not wqe size */
- swqe_size = da_rc_msg_size[max_send_sge];
- rwqe_size = da_rc_msg_size[max_recv_sge];
+ } else { /* for LLQP we need to use msg size, not wqe size */
+ swqe_size = ll_qp_msg_size(max_send_sge);
+ rwqe_size = ll_qp_msg_size(max_recv_sge);
parms.act_nr_send_sges = 1;
parms.act_nr_recv_sges = 1;
}
@@ -549,29 +593,27 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
case IB_QPT_UD:
case IB_QPT_GSI:
case IB_QPT_SMI:
- /* UD circumvention */
- parms.act_nr_recv_sges -= 2;
- parms.act_nr_send_sges -= 2;
- if (isdaqp) {
- swqe_size = da_ud_sq_msg_size[max_send_sge];
- rwqe_size = da_rc_msg_size[max_recv_sge];
+ if (is_llqp) {
+ swqe_size = ll_qp_msg_size(parms.act_nr_send_sges);
+ rwqe_size = ll_qp_msg_size(parms.act_nr_recv_sges);
parms.act_nr_send_sges = 1;
parms.act_nr_recv_sges = 1;
} else {
+ /* UD circumvention */
+ parms.act_nr_send_sges -= 2;
+ parms.act_nr_recv_sges -= 2;
swqe_size = offsetof(struct ehca_wqe,
u.ud_av.sg_list[parms.act_nr_send_sges]);
rwqe_size = offsetof(struct ehca_wqe,
u.ud_av.sg_list[parms.act_nr_recv_sges]);
}
- if (IB_QPT_GSI == init_attr->qp_type ||
- IB_QPT_SMI == init_attr->qp_type) {
+ if (IB_QPT_GSI == qp_type || IB_QPT_SMI == qp_type) {
parms.act_nr_send_wqes = init_attr->cap.max_send_wr;
parms.act_nr_recv_wqes = init_attr->cap.max_recv_wr;
parms.act_nr_send_sges = init_attr->cap.max_send_sge;
parms.act_nr_recv_sges = init_attr->cap.max_recv_sge;
- my_qp->ib_qp.qp_num =
- (init_attr->qp_type == IB_QPT_SMI) ? 0 : 1;
+ ib_qp_num = (qp_type == IB_QPT_SMI) ? 0 : 1;
}
break;
@@ -580,108 +622,234 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
break;
}
- /* initializes r/squeue and registers queue pages */
- ret = init_qp_queues(shca, my_qp,
- parms.nr_sq_pages, parms.nr_rq_pages,
- swqe_size, rwqe_size,
- parms.act_nr_send_sges, parms.act_nr_recv_sges);
- if (ret) {
- ehca_err(pd->device,
- "Couldn't initialize r/squeue and pages ret=%x", ret);
- goto create_qp_exit2;
+ /* initialize r/squeue and register queue pages */
+ if (HAS_SQ(my_qp)) {
+ ret = init_qp_queue(
+ shca, my_qp, &my_qp->ipz_squeue, 0,
+ HAS_RQ(my_qp) ? H_PAGE_REGISTERED : H_SUCCESS,
+ parms.nr_sq_pages, swqe_size,
+ parms.act_nr_send_sges);
+ if (ret) {
+ ehca_err(pd->device, "Couldn't initialize squeue "
+ "and pages ret=%x", ret);
+ goto create_qp_exit2;
+ }
}
- my_qp->ib_qp.pd = &my_pd->ib_pd;
- my_qp->ib_qp.device = my_pd->ib_pd.device;
+ if (HAS_RQ(my_qp)) {
+ ret = init_qp_queue(
+ shca, my_qp, &my_qp->ipz_rqueue, 1,
+ H_SUCCESS, parms.nr_rq_pages, rwqe_size,
+ parms.act_nr_recv_sges);
+ if (ret) {
+ ehca_err(pd->device, "Couldn't initialize rqueue "
+ "and pages ret=%x", ret);
+ goto create_qp_exit3;
+ }
+ }
- my_qp->ib_qp.recv_cq = init_attr->recv_cq;
- my_qp->ib_qp.send_cq = init_attr->send_cq;
+ if (is_srq) {
+ my_qp->ib_srq.pd = &my_pd->ib_pd;
+ my_qp->ib_srq.device = my_pd->ib_pd.device;
- my_qp->ib_qp.qp_type = init_attr->qp_type;
+ my_qp->ib_srq.srq_context = init_attr->qp_context;
+ my_qp->ib_srq.event_handler = init_attr->event_handler;
+ } else {
+ my_qp->ib_qp.qp_num = ib_qp_num;
+ my_qp->ib_qp.pd = &my_pd->ib_pd;
+ my_qp->ib_qp.device = my_pd->ib_pd.device;
+
+ my_qp->ib_qp.recv_cq = init_attr->recv_cq;
+ my_qp->ib_qp.send_cq = init_attr->send_cq;
- my_qp->qp_type = init_attr->qp_type;
- my_qp->ib_qp.srq = init_attr->srq;
+ my_qp->ib_qp.qp_type = qp_type;
+ my_qp->ib_qp.srq = init_attr->srq;
- my_qp->ib_qp.qp_context = init_attr->qp_context;
- my_qp->ib_qp.event_handler = init_attr->event_handler;
+ my_qp->ib_qp.qp_context = init_attr->qp_context;
+ my_qp->ib_qp.event_handler = init_attr->event_handler;
+ }
init_attr->cap.max_inline_data = 0; /* not supported yet */
init_attr->cap.max_recv_sge = parms.act_nr_recv_sges;
init_attr->cap.max_recv_wr = parms.act_nr_recv_wqes;
init_attr->cap.max_send_sge = parms.act_nr_send_sges;
init_attr->cap.max_send_wr = parms.act_nr_send_wqes;
+ my_qp->init_attr = *init_attr;
/* NOTE: define_apq0() not supported yet */
- if (init_attr->qp_type == IB_QPT_GSI) {
+ if (qp_type == IB_QPT_GSI) {
h_ret = ehca_define_sqp(shca, my_qp, init_attr);
if (h_ret != H_SUCCESS) {
ehca_err(pd->device, "ehca_define_sqp() failed rc=%lx",
h_ret);
ret = ehca2ib_return_code(h_ret);
- goto create_qp_exit3;
+ goto create_qp_exit4;
}
}
- if (init_attr->send_cq) {
- struct ehca_cq *cq = container_of(init_attr->send_cq,
- struct ehca_cq, ib_cq);
- ret = ehca_cq_assign_qp(cq, my_qp);
+
+ if (my_qp->send_cq) {
+ ret = ehca_cq_assign_qp(my_qp->send_cq, my_qp);
if (ret) {
ehca_err(pd->device, "Couldn't assign qp to send_cq ret=%x",
ret);
- goto create_qp_exit3;
+ goto create_qp_exit4;
}
- my_qp->send_cq = cq;
}
+
/* copy queues, galpa data to user space */
if (context && udata) {
- struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue;
- struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue;
struct ehca_create_qp_resp resp;
memset(&resp, 0, sizeof(resp));
resp.qp_num = my_qp->real_qp_num;
resp.token = my_qp->token;
resp.qp_type = my_qp->qp_type;
+ resp.ext_type = my_qp->ext_type;
resp.qkey = my_qp->qkey;
resp.real_qp_num = my_qp->real_qp_num;
- /* rqueue properties */
- resp.ipz_rqueue.qe_size = ipz_rqueue->qe_size;
- resp.ipz_rqueue.act_nr_of_sg = ipz_rqueue->act_nr_of_sg;
- resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length;
- resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize;
- resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state;
- /* squeue properties */
- resp.ipz_squeue.qe_size = ipz_squeue->qe_size;
- resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg;
- resp.ipz_squeue.queue_length = ipz_squeue->queue_length;
- resp.ipz_squeue.pagesize = ipz_squeue->pagesize;
- resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state;
+ if (HAS_SQ(my_qp))
+ queue2resp(&resp.ipz_squeue, &my_qp->ipz_squeue);
+ if (HAS_RQ(my_qp))
+ queue2resp(&resp.ipz_rqueue, &my_qp->ipz_rqueue);
+
if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
ehca_err(pd->device, "Copy to udata failed");
ret = -EINVAL;
- goto create_qp_exit3;
+ goto create_qp_exit4;
}
}
- return &my_qp->ib_qp;
+ return my_qp;
+
+create_qp_exit4:
+ if (HAS_RQ(my_qp))
+ ipz_queue_dtor(&my_qp->ipz_rqueue);
create_qp_exit3:
- ipz_queue_dtor(&my_qp->ipz_rqueue);
- ipz_queue_dtor(&my_qp->ipz_squeue);
+ if (HAS_SQ(my_qp))
+ ipz_queue_dtor(&my_qp->ipz_squeue);
create_qp_exit2:
hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
create_qp_exit1:
- spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+ write_lock_irqsave(&ehca_qp_idr_lock, flags);
idr_remove(&ehca_qp_idr, my_qp->token);
- spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+ write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
create_qp_exit0:
kmem_cache_free(qp_cache, my_qp);
return ERR_PTR(ret);
}
+struct ib_qp *ehca_create_qp(struct ib_pd *pd,
+ struct ib_qp_init_attr *qp_init_attr,
+ struct ib_udata *udata)
+{
+ struct ehca_qp *ret;
+
+ ret = internal_create_qp(pd, qp_init_attr, NULL, udata, 0);
+ return IS_ERR(ret) ? (struct ib_qp *) ret : &ret->ib_qp;
+}
+
+int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ struct ib_uobject *uobject);
+
+struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+ struct ib_srq_init_attr *srq_init_attr,
+ struct ib_udata *udata)
+{
+ struct ib_qp_init_attr qp_init_attr;
+ struct ehca_qp *my_qp;
+ struct ib_srq *ret;
+ struct ehca_shca *shca = container_of(pd->device, struct ehca_shca,
+ ib_device);
+ struct hcp_modify_qp_control_block *mqpcb;
+ u64 hret, update_mask;
+
+ /* For common attributes, internal_create_qp() takes its info
+ * out of qp_init_attr, so copy all common attrs there.
+ */
+ memset(&qp_init_attr, 0, sizeof(qp_init_attr));
+ qp_init_attr.event_handler = srq_init_attr->event_handler;
+ qp_init_attr.qp_context = srq_init_attr->srq_context;
+ qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
+ qp_init_attr.qp_type = IB_QPT_RC;
+ qp_init_attr.cap.max_recv_wr = srq_init_attr->attr.max_wr;
+ qp_init_attr.cap.max_recv_sge = srq_init_attr->attr.max_sge;
+
+ my_qp = internal_create_qp(pd, &qp_init_attr, srq_init_attr, udata, 1);
+ if (IS_ERR(my_qp))
+ return (struct ib_srq *) my_qp;
+
+ /* copy back return values */
+ srq_init_attr->attr.max_wr = qp_init_attr.cap.max_recv_wr;
+ srq_init_attr->attr.max_sge = qp_init_attr.cap.max_recv_sge;
+
+ /* drive SRQ into RTR state */
+ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!mqpcb) {
+ ehca_err(pd->device, "Could not get zeroed page for mqpcb "
+ "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
+ ret = ERR_PTR(-ENOMEM);
+ goto create_srq1;
+ }
+
+ mqpcb->qp_state = EHCA_QPS_INIT;
+ mqpcb->prim_phys_port = 1;
+ update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+ hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+ my_qp->ipz_qp_handle,
+ &my_qp->pf,
+ update_mask,
+ mqpcb, my_qp->galpas.kernel);
+ if (hret != H_SUCCESS) {
+ ehca_err(pd->device, "Could not modify SRQ to INIT"
+ "ehca_qp=%p qp_num=%x hret=%lx",
+ my_qp, my_qp->real_qp_num, hret);
+ goto create_srq2;
+ }
+
+ mqpcb->qp_enable = 1;
+ update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1);
+ hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+ my_qp->ipz_qp_handle,
+ &my_qp->pf,
+ update_mask,
+ mqpcb, my_qp->galpas.kernel);
+ if (hret != H_SUCCESS) {
+ ehca_err(pd->device, "Could not enable SRQ"
+ "ehca_qp=%p qp_num=%x hret=%lx",
+ my_qp, my_qp->real_qp_num, hret);
+ goto create_srq2;
+ }
+
+ mqpcb->qp_state = EHCA_QPS_RTR;
+ update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1);
+ hret = hipz_h_modify_qp(shca->ipz_hca_handle,
+ my_qp->ipz_qp_handle,
+ &my_qp->pf,
+ update_mask,
+ mqpcb, my_qp->galpas.kernel);
+ if (hret != H_SUCCESS) {
+ ehca_err(pd->device, "Could not modify SRQ to RTR"
+ "ehca_qp=%p qp_num=%x hret=%lx",
+ my_qp, my_qp->real_qp_num, hret);
+ goto create_srq2;
+ }
+
+ return &my_qp->ib_srq;
+
+create_srq2:
+ ret = ERR_PTR(ehca2ib_return_code(hret));
+ ehca_free_fw_ctrlblock(mqpcb);
+
+create_srq1:
+ internal_destroy_qp(pd->device, my_qp, my_qp->ib_srq.uobject);
+
+ return ret;
+}
+
/*
* prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts
* set purge bit of bad wqe and subsequent wqes to avoid reentering sqe
@@ -765,7 +933,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
u64 h_ret;
int bad_wqe_cnt = 0;
int squeue_locked = 0;
- unsigned long spl_flags = 0;
+ unsigned long flags = 0;
/* do query_qp to obtain current attr values */
mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
@@ -886,6 +1054,17 @@ static int internal_modify_qp(struct ib_qp *ibqp,
"ehca_qp=%p qp_num=%x <VALID STATE CHANGE> qp_state_xsit=%x",
my_qp, ibqp->qp_num, statetrans);
+ /* eHCA2 rev2 and higher require the SEND_GRH_FLAG to be set
+ * in non-LL UD QPs.
+ */
+ if ((my_qp->qp_type == IB_QPT_UD) &&
+ (my_qp->ext_type != EQPT_LLQP) &&
+ (statetrans == IB_QPST_INIT2RTR) &&
+ (shca->hw_level >= 0x22)) {
+ update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1);
+ mqpcb->send_grh_flag = 1;
+ }
+
/* sqe -> rts: set purge bit of bad wqe before actual trans */
if ((my_qp->qp_type == IB_QPT_UD ||
my_qp->qp_type == IB_QPT_GSI ||
@@ -895,7 +1074,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
if (!ibqp->uobject) {
struct ehca_wqe *wqe;
/* lock send queue */
- spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
+ spin_lock_irqsave(&my_qp->spinlock_s, flags);
squeue_locked = 1;
/* mark next free wqe */
wqe = (struct ehca_wqe*)
@@ -1181,7 +1360,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
modify_qp_exit2:
if (squeue_locked) { /* this means: sqe -> rts */
- spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags);
+ spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
my_qp->sqerr_purgeflag = 1;
}
@@ -1312,6 +1491,9 @@ int ehca_query_qp(struct ib_qp *qp,
qp_attr->alt_port_num = qpcb->alt_phys_port;
qp_attr->alt_timeout = qpcb->timeout_al;
+ qp_attr->max_dest_rd_atomic = qpcb->rdma_nr_atomic_resp_res;
+ qp_attr->max_rd_atomic = qpcb->rdma_atomic_outst_dest_qp;
+
/* primary av */
qp_attr->ah_attr.sl = qpcb->service_level;
@@ -1367,53 +1549,170 @@ query_qp_exit1:
return ret;
}
-int ehca_destroy_qp(struct ib_qp *ibqp)
+int ehca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask attr_mask, struct ib_udata *udata)
{
- struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
- struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
+ struct ehca_qp *my_qp =
+ container_of(ibsrq, struct ehca_qp, ib_srq);
+ struct ehca_pd *my_pd =
+ container_of(ibsrq->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca =
+ container_of(ibsrq->pd->device, struct ehca_shca, ib_device);
+ struct hcp_modify_qp_control_block *mqpcb;
+ u64 update_mask;
+ u64 h_ret;
+ int ret = 0;
+
+ u32 cur_pid = current->tgid;
+ if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+ my_pd->ownpid != cur_pid) {
+ ehca_err(ibsrq->pd->device, "Invalid caller pid=%x ownpid=%x",
+ cur_pid, my_pd->ownpid);
+ return -EINVAL;
+ }
+
+ mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!mqpcb) {
+ ehca_err(ibsrq->device, "Could not get zeroed page for mqpcb "
+ "ehca_qp=%p qp_num=%x ", my_qp, my_qp->real_qp_num);
+ return -ENOMEM;
+ }
+
+ update_mask = 0;
+ if (attr_mask & IB_SRQ_LIMIT) {
+ attr_mask &= ~IB_SRQ_LIMIT;
+ update_mask |=
+ EHCA_BMASK_SET(MQPCB_MASK_CURR_SRQ_LIMIT, 1)
+ | EHCA_BMASK_SET(MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG, 1);
+ mqpcb->curr_srq_limit =
+ EHCA_BMASK_SET(MQPCB_CURR_SRQ_LIMIT, attr->srq_limit);
+ mqpcb->qp_aff_asyn_ev_log_reg =
+ EHCA_BMASK_SET(QPX_AAELOG_RESET_SRQ_LIMIT, 1);
+ }
+
+ /* by now, all bits in attr_mask should have been cleared */
+ if (attr_mask) {
+ ehca_err(ibsrq->device, "invalid attribute mask bits set "
+ "attr_mask=%x", attr_mask);
+ ret = -EINVAL;
+ goto modify_srq_exit0;
+ }
+
+ if (ehca_debug_level)
+ ehca_dmp(mqpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+ h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, my_qp->ipz_qp_handle,
+ NULL, update_mask, mqpcb,
+ my_qp->galpas.kernel);
+
+ if (h_ret != H_SUCCESS) {
+ ret = ehca2ib_return_code(h_ret);
+ ehca_err(ibsrq->device, "hipz_h_modify_qp() failed rc=%lx "
+ "ehca_qp=%p qp_num=%x",
+ h_ret, my_qp, my_qp->real_qp_num);
+ }
+
+modify_srq_exit0:
+ ehca_free_fw_ctrlblock(mqpcb);
+
+ return ret;
+}
+
+int ehca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr)
+{
+ struct ehca_qp *my_qp = container_of(srq, struct ehca_qp, ib_srq);
+ struct ehca_pd *my_pd = container_of(srq->pd, struct ehca_pd, ib_pd);
+ struct ehca_shca *shca = container_of(srq->device, struct ehca_shca,
ib_device);
+ struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle;
+ struct hcp_modify_qp_control_block *qpcb;
+ u32 cur_pid = current->tgid;
+ int ret = 0;
+ u64 h_ret;
+
+ if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
+ my_pd->ownpid != cur_pid) {
+ ehca_err(srq->device, "Invalid caller pid=%x ownpid=%x",
+ cur_pid, my_pd->ownpid);
+ return -EINVAL;
+ }
+
+ qpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
+ if (!qpcb) {
+ ehca_err(srq->device, "Out of memory for qpcb "
+ "ehca_qp=%p qp_num=%x", my_qp, my_qp->real_qp_num);
+ return -ENOMEM;
+ }
+
+ h_ret = hipz_h_query_qp(adapter_handle, my_qp->ipz_qp_handle,
+ NULL, qpcb, my_qp->galpas.kernel);
+
+ if (h_ret != H_SUCCESS) {
+ ret = ehca2ib_return_code(h_ret);
+ ehca_err(srq->device, "hipz_h_query_qp() failed "
+ "ehca_qp=%p qp_num=%x h_ret=%lx",
+ my_qp, my_qp->real_qp_num, h_ret);
+ goto query_srq_exit1;
+ }
+
+ srq_attr->max_wr = qpcb->max_nr_outst_recv_wr - 1;
+ srq_attr->srq_limit = EHCA_BMASK_GET(
+ MQPCB_CURR_SRQ_LIMIT, qpcb->curr_srq_limit);
+
+ if (ehca_debug_level)
+ ehca_dmp(qpcb, 4*70, "qp_num=%x", my_qp->real_qp_num);
+
+query_srq_exit1:
+ ehca_free_fw_ctrlblock(qpcb);
+
+ return ret;
+}
+
+int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ struct ib_uobject *uobject)
+{
+ struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device);
struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
ib_pd);
u32 cur_pid = current->tgid;
- u32 qp_num = ibqp->qp_num;
+ u32 qp_num = my_qp->real_qp_num;
int ret;
u64 h_ret;
u8 port_num;
enum ib_qp_type qp_type;
unsigned long flags;
- if (ibqp->uobject) {
+ if (uobject) {
if (my_qp->mm_count_galpa ||
my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
- ehca_err(ibqp->device, "Resources still referenced in "
- "user space qp_num=%x", ibqp->qp_num);
+ ehca_err(dev, "Resources still referenced in "
+ "user space qp_num=%x", qp_num);
return -EINVAL;
}
if (my_pd->ownpid != cur_pid) {
- ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x",
+ ehca_err(dev, "Invalid caller pid=%x ownpid=%x",
cur_pid, my_pd->ownpid);
return -EINVAL;
}
}
if (my_qp->send_cq) {
- ret = ehca_cq_unassign_qp(my_qp->send_cq,
- my_qp->real_qp_num);
+ ret = ehca_cq_unassign_qp(my_qp->send_cq, qp_num);
if (ret) {
- ehca_err(ibqp->device, "Couldn't unassign qp from "
+ ehca_err(dev, "Couldn't unassign qp from "
"send_cq ret=%x qp_num=%x cq_num=%x", ret,
- my_qp->ib_qp.qp_num, my_qp->send_cq->cq_number);
+ qp_num, my_qp->send_cq->cq_number);
return ret;
}
}
- spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+ write_lock_irqsave(&ehca_qp_idr_lock, flags);
idr_remove(&ehca_qp_idr, my_qp->token);
- spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+ write_unlock_irqrestore(&ehca_qp_idr_lock, flags);
h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
if (h_ret != H_SUCCESS) {
- ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx "
+ ehca_err(dev, "hipz_h_destroy_qp() failed rc=%lx "
"ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num);
return ehca2ib_return_code(h_ret);
}
@@ -1424,7 +1723,7 @@ int ehca_destroy_qp(struct ib_qp *ibqp)
/* no support for IB_QPT_SMI yet */
if (qp_type == IB_QPT_GSI) {
struct ib_event event;
- ehca_info(ibqp->device, "device %s: port %x is inactive.",
+ ehca_info(dev, "device %s: port %x is inactive.",
shca->ib_device.name, port_num);
event.device = &shca->ib_device;
event.event = IB_EVENT_PORT_ERR;
@@ -1433,12 +1732,28 @@ int ehca_destroy_qp(struct ib_qp *ibqp)
ib_dispatch_event(&event);
}
- ipz_queue_dtor(&my_qp->ipz_rqueue);
- ipz_queue_dtor(&my_qp->ipz_squeue);
+ if (HAS_RQ(my_qp))
+ ipz_queue_dtor(&my_qp->ipz_rqueue);
+ if (HAS_SQ(my_qp))
+ ipz_queue_dtor(&my_qp->ipz_squeue);
kmem_cache_free(qp_cache, my_qp);
return 0;
}
+int ehca_destroy_qp(struct ib_qp *qp)
+{
+ return internal_destroy_qp(qp->device,
+ container_of(qp, struct ehca_qp, ib_qp),
+ qp->uobject);
+}
+
+int ehca_destroy_srq(struct ib_srq *srq)
+{
+ return internal_destroy_qp(srq->device,
+ container_of(srq, struct ehca_qp, ib_srq),
+ srq->uobject);
+}
+
int ehca_init_qp_cache(void)
{
qp_cache = kmem_cache_create("ehca_cache_qp",
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index caec9dee09e..61da65e6e5e 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -3,8 +3,9 @@
*
* post_send/recv, poll_cq, req_notify
*
- * Authors: Waleri Fomin <fomin@de.ibm.com>
- * Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ * Authors: Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ * Waleri Fomin <fomin@de.ibm.com>
+ * Joachim Fenkes <fenkes@de.ibm.com>
* Reinhard Ernst <rernst@de.ibm.com>
*
* Copyright (c) 2005 IBM Corporation
@@ -362,10 +363,10 @@ int ehca_post_send(struct ib_qp *qp,
struct ehca_wqe *wqe_p;
int wqe_cnt = 0;
int ret = 0;
- unsigned long spl_flags;
+ unsigned long flags;
/* LOCK the QUEUE */
- spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
+ spin_lock_irqsave(&my_qp->spinlock_s, flags);
/* loop processes list of send reqs */
for (cur_send_wr = send_wr; cur_send_wr != NULL;
@@ -406,26 +407,31 @@ int ehca_post_send(struct ib_qp *qp,
} /* eof for cur_send_wr */
post_send_exit0:
- /* UNLOCK the QUEUE */
- spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags);
iosync(); /* serialize GAL register access */
hipz_update_sqa(my_qp, wqe_cnt);
+ spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
return ret;
}
-int ehca_post_recv(struct ib_qp *qp,
- struct ib_recv_wr *recv_wr,
- struct ib_recv_wr **bad_recv_wr)
+static int internal_post_recv(struct ehca_qp *my_qp,
+ struct ib_device *dev,
+ struct ib_recv_wr *recv_wr,
+ struct ib_recv_wr **bad_recv_wr)
{
- struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
struct ib_recv_wr *cur_recv_wr;
struct ehca_wqe *wqe_p;
int wqe_cnt = 0;
int ret = 0;
- unsigned long spl_flags;
+ unsigned long flags;
+
+ if (unlikely(!HAS_RQ(my_qp))) {
+ ehca_err(dev, "QP has no RQ ehca_qp=%p qp_num=%x ext_type=%d",
+ my_qp, my_qp->real_qp_num, my_qp->ext_type);
+ return -ENODEV;
+ }
/* LOCK the QUEUE */
- spin_lock_irqsave(&my_qp->spinlock_r, spl_flags);
+ spin_lock_irqsave(&my_qp->spinlock_r, flags);
/* loop processes list of send reqs */
for (cur_recv_wr = recv_wr; cur_recv_wr != NULL;
@@ -439,8 +445,8 @@ int ehca_post_recv(struct ib_qp *qp,
*bad_recv_wr = cur_recv_wr;
if (wqe_cnt == 0) {
ret = -ENOMEM;
- ehca_err(qp->device, "Too many posted WQEs "
- "qp_num=%x", qp->qp_num);
+ ehca_err(dev, "Too many posted WQEs "
+ "qp_num=%x", my_qp->real_qp_num);
}
goto post_recv_exit0;
}
@@ -455,23 +461,39 @@ int ehca_post_recv(struct ib_qp *qp,
*bad_recv_wr = cur_recv_wr;
if (wqe_cnt == 0) {
ret = -EINVAL;
- ehca_err(qp->device, "Could not write WQE "
- "qp_num=%x", qp->qp_num);
+ ehca_err(dev, "Could not write WQE "
+ "qp_num=%x", my_qp->real_qp_num);
}
goto post_recv_exit0;
}
wqe_cnt++;
- ehca_gen_dbg("ehca_qp=%p qp_num=%x wqe_cnt=%d",
- my_qp, qp->qp_num, wqe_cnt);
+ ehca_dbg(dev, "ehca_qp=%p qp_num=%x wqe_cnt=%d",
+ my_qp, my_qp->real_qp_num, wqe_cnt);
} /* eof for cur_recv_wr */
post_recv_exit0:
- spin_unlock_irqrestore(&my_qp->spinlock_r, spl_flags);
iosync(); /* serialize GAL register access */
hipz_update_rqa(my_qp, wqe_cnt);
+ spin_unlock_irqrestore(&my_qp->spinlock_r, flags);
return ret;
}
+int ehca_post_recv(struct ib_qp *qp,
+ struct ib_recv_wr *recv_wr,
+ struct ib_recv_wr **bad_recv_wr)
+{
+ return internal_post_recv(container_of(qp, struct ehca_qp, ib_qp),
+ qp->device, recv_wr, bad_recv_wr);
+}
+
+int ehca_post_srq_recv(struct ib_srq *srq,
+ struct ib_recv_wr *recv_wr,
+ struct ib_recv_wr **bad_recv_wr)
+{
+ return internal_post_recv(container_of(srq, struct ehca_qp, ib_srq),
+ srq->device, recv_wr, bad_recv_wr);
+}
+
/*
* ib_wc_opcode table converts ehca wc opcode to ib
* Since we use zero to indicate invalid opcode, the actual ib opcode must
@@ -494,6 +516,7 @@ static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc)
int ret = 0;
struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
struct ehca_cqe *cqe;
+ struct ehca_qp *my_qp;
int cqe_count = 0;
poll_cq_one_read_cqe:
@@ -513,7 +536,7 @@ poll_cq_one_read_cqe:
if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) {
struct ehca_qp *qp=ehca_cq_get_qp(my_cq, cqe->local_qp_number);
int purgeflag;
- unsigned long spl_flags;
+ unsigned long flags;
if (!qp) {
ehca_err(cq->device, "cq_num=%x qp_num=%x "
"could not find qp -> ignore cqe",
@@ -523,9 +546,9 @@ poll_cq_one_read_cqe:
/* ignore this purged cqe */
goto poll_cq_one_read_cqe;
}
- spin_lock_irqsave(&qp->spinlock_s, spl_flags);
+ spin_lock_irqsave(&qp->spinlock_s, flags);
purgeflag = qp->sqerr_purgeflag;
- spin_unlock_irqrestore(&qp->spinlock_s, spl_flags);
+ spin_unlock_irqrestore(&qp->spinlock_s, flags);
if (purgeflag) {
ehca_dbg(cq->device, "Got CQE with purged bit qp_num=%x "
@@ -545,7 +568,7 @@ poll_cq_one_read_cqe:
}
/* tracing cqe */
- if (ehca_debug_level) {
+ if (unlikely(ehca_debug_level)) {
ehca_dbg(cq->device,
"Received COMPLETION ehca_cq=%p cq_num=%x -----",
my_cq, my_cq->cq_number);
@@ -579,7 +602,11 @@ poll_cq_one_read_cqe:
} else
wc->status = IB_WC_SUCCESS;
- wc->qp = NULL;
+ read_lock(&ehca_qp_idr_lock);
+ my_qp = idr_find(&ehca_qp_idr, cqe->qp_token);
+ wc->qp = &my_qp->ib_qp;
+ read_unlock(&ehca_qp_idr_lock);
+
wc->byte_len = cqe->nr_bytes_transferred;
wc->pkey_index = cqe->pkey_index;
wc->slid = cqe->rlid;
@@ -589,7 +616,7 @@ poll_cq_one_read_cqe:
wc->imm_data = cpu_to_be32(cqe->immediate_data);
wc->sl = cqe->service_level;
- if (wc->status != IB_WC_SUCCESS)
+ if (unlikely(wc->status != IB_WC_SUCCESS))
ehca_dbg(cq->device,
"ehca_cq=%p cq_num=%x WARNING unsuccessful cqe "
"OPType=%x status=%x qp_num=%x src_qp=%x wr_id=%lx "
@@ -610,7 +637,7 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
int nr;
struct ib_wc *current_wc = wc;
int ret = 0;
- unsigned long spl_flags;
+ unsigned long flags;
if (num_entries < 1) {
ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p "
@@ -619,14 +646,14 @@ int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc)
goto poll_cq_exit0;
}
- spin_lock_irqsave(&my_cq->spinlock, spl_flags);
+ spin_lock_irqsave(&my_cq->spinlock, flags);
for (nr = 0; nr < num_entries; nr++) {
ret = ehca_poll_cq_one(cq, current_wc);
if (ret)
break;
current_wc++;
} /* eof for nr */
- spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
+ spin_unlock_irqrestore(&my_cq->spinlock, flags);
if (ret == -EAGAIN || !ret)
ret = nr;
@@ -637,7 +664,6 @@ poll_cq_exit0:
int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags)
{
struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
- unsigned long spl_flags;
int ret = 0;
switch (notify_flags & IB_CQ_SOLICITED_MASK) {
@@ -652,6 +678,7 @@ int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags notify_flags)
}
if (notify_flags & IB_CQ_REPORT_MISSED_EVENTS) {
+ unsigned long spl_flags;
spin_lock_irqsave(&my_cq->spinlock, spl_flags);
ret = ipz_qeit_is_valid(&my_cq->ipz_queue);
spin_unlock_irqrestore(&my_cq->spinlock, spl_flags);
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index 973c4b59154..03b185f873d 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -59,6 +59,7 @@
#include <linux/cpu.h>
#include <linux/device.h>
+#include <asm/atomic.h>
#include <asm/abs_addr.h>
#include <asm/ibmebus.h>
#include <asm/io.h>
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index 73db920b694..3031b3bb56f 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -253,16 +253,16 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
u32 cur_pid = current->tgid;
u32 ret;
- unsigned long flags;
struct ehca_cq *cq;
struct ehca_qp *qp;
struct ehca_pd *pd;
+ struct ib_uobject *uobject;
switch (q_type) {
case 1: /* CQ */
- spin_lock_irqsave(&ehca_cq_idr_lock, flags);
+ read_lock(&ehca_cq_idr_lock);
cq = idr_find(&ehca_cq_idr, idr_handle);
- spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+ read_unlock(&ehca_cq_idr_lock);
/* make sure this mmap really belongs to the authorized user */
if (!cq)
@@ -288,9 +288,9 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
break;
case 2: /* QP */
- spin_lock_irqsave(&ehca_qp_idr_lock, flags);
+ read_lock(&ehca_qp_idr_lock);
qp = idr_find(&ehca_qp_idr, idr_handle);
- spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+ read_unlock(&ehca_qp_idr_lock);
/* make sure this mmap really belongs to the authorized user */
if (!qp)
@@ -304,7 +304,8 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
return -ENOMEM;
}
- if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context)
+ uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
+ if (!uobject || uobject->context != context)
return -EINVAL;
ret = ehca_mmap_qp(vma, qp, rsrc_type);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index 5766ae3a202..4776a8b0fee 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -5,6 +5,7 @@
*
* Authors: Christoph Raisch <raisch@de.ibm.com>
* Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+ * Joachim Fenkes <fenkes@de.ibm.com>
* Gerd Bayer <gerd.bayer@de.ibm.com>
* Waleri Fomin <fomin@de.ibm.com>
*
@@ -62,6 +63,12 @@
#define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39)
#define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47)
+#define H_ALL_RES_QP_UD_AV_LKEY EHCA_BMASK_IBM(32, 63)
+#define H_ALL_RES_QP_SRQ_QP_TOKEN EHCA_BMASK_IBM(0, 31)
+#define H_ALL_RES_QP_SRQ_QP_HANDLE EHCA_BMASK_IBM(0, 64)
+#define H_ALL_RES_QP_SRQ_LIMIT EHCA_BMASK_IBM(48, 63)
+#define H_ALL_RES_QP_SRQ_QPN EHCA_BMASK_IBM(40, 63)
+
#define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31)
#define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63)
#define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15)
@@ -74,10 +81,7 @@
#define H_MP_SHUTDOWN EHCA_BMASK_IBM(48, 48)
#define H_MP_RESET_QKEY_CTR EHCA_BMASK_IBM(49, 49)
-/* direct access qp controls */
-#define DAQP_CTRL_ENABLE 0x01
-#define DAQP_CTRL_SEND_COMP 0x20
-#define DAQP_CTRL_RECV_COMP 0x40
+static DEFINE_SPINLOCK(hcall_lock);
static u32 get_longbusy_msecs(int longbusy_rc)
{
@@ -155,7 +159,7 @@ static long ehca_plpar_hcall9(unsigned long opcode,
{
long ret;
int i, sleep_msecs, lock_is_set = 0;
- unsigned long flags;
+ unsigned long flags = 0;
ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx "
"arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx",
@@ -284,53 +288,53 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
}
u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
- struct ehca_qp *qp,
struct ehca_alloc_qp_parms *parms)
{
u64 ret;
- u64 allocate_controls;
- u64 max_r10_reg;
+ u64 allocate_controls, max_r10_reg, r11, r12;
u64 outs[PLPAR_HCALL9_BUFSIZE];
- u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1;
- u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1;
- int daqp_ctrl = parms->daqp_ctrl;
allocate_controls =
- EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS,
- (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0)
+ EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, parms->ext_type)
| EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0)
| EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype)
| EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype)
| EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING,
- (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0)
+ !!(parms->ll_comp_flags & LLQP_RECV_COMP))
| EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING,
- (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0)
+ !!(parms->ll_comp_flags & LLQP_SEND_COMP))
| EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL,
parms->ud_av_l_key_ctl)
| EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1);
max_r10_reg =
EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR,
- max_nr_send_wqes)
+ parms->max_send_wr + 1)
| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR,
- max_nr_receive_wqes)
+ parms->max_recv_wr + 1)
| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE,
parms->max_send_sge)
| EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE,
parms->max_recv_sge);
+ r11 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QP_TOKEN, parms->srq_token);
+
+ if (parms->ext_type == EQPT_SRQ)
+ r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_LIMIT, parms->srq_limit);
+ else
+ r12 = EHCA_BMASK_SET(H_ALL_RES_QP_SRQ_QPN, parms->srq_qpn);
+
ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs,
adapter_handle.handle, /* r4 */
allocate_controls, /* r5 */
- qp->send_cq->ipz_cq_handle.handle,
- qp->recv_cq->ipz_cq_handle.handle,
- parms->ipz_eq_handle.handle,
- ((u64)qp->token << 32) | parms->pd.value,
- max_r10_reg, /* r10 */
- parms->ud_av_l_key_ctl, /* r11 */
- 0);
- qp->ipz_qp_handle.handle = outs[0];
- qp->real_qp_num = (u32)outs[1];
+ parms->send_cq_handle.handle,
+ parms->recv_cq_handle.handle,
+ parms->eq_handle.handle,
+ ((u64)parms->token << 32) | parms->pd.value,
+ max_r10_reg, r11, r12);
+
+ parms->qp_handle.handle = outs[0];
+ parms->real_qp_num = (u32)outs[1];
parms->act_nr_send_wqes =
(u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]);
parms->act_nr_recv_wqes =
@@ -345,7 +349,7 @@ u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
(u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]);
if (ret == H_SUCCESS)
- hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]);
+ hcp_galpas_ctor(&parms->galpas, outs[6], outs[6]);
if (ret == H_NOT_ENOUGH_RESOURCES)
ehca_gen_err("Not enough resources. ret=%lx", ret);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.h b/drivers/infiniband/hw/ehca/hcp_if.h
index 2869f7dd619..60ce02b7066 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.h
+++ b/drivers/infiniband/hw/ehca/hcp_if.h
@@ -78,7 +78,6 @@ u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle,
* initialize resources, create empty QPPTs (2 rings).
*/
u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle,
- struct ehca_qp *qp,
struct ehca_alloc_qp_parms *parms);
u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h
index fad91368dc5..dad6dea5636 100644
--- a/drivers/infiniband/hw/ehca/hipz_hw.h
+++ b/drivers/infiniband/hw/ehca/hipz_hw.h
@@ -163,6 +163,7 @@ struct hipz_qptemm {
#define QPX_SQADDER EHCA_BMASK_IBM(48,63)
#define QPX_RQADDER EHCA_BMASK_IBM(48,63)
+#define QPX_AAELOG_RESET_SRQ_LIMIT EHCA_BMASK_IBM(3,3)
#define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm,x)
@@ -360,6 +361,24 @@ struct hipz_query_hca {
u32 max_neq;
} __attribute__ ((packed));
+#define HCA_CAP_AH_PORT_NR_CHECK EHCA_BMASK_IBM( 0, 0)
+#define HCA_CAP_ATOMIC EHCA_BMASK_IBM( 1, 1)
+#define HCA_CAP_AUTO_PATH_MIG EHCA_BMASK_IBM( 2, 2)
+#define HCA_CAP_BAD_P_KEY_CTR EHCA_BMASK_IBM( 3, 3)
+#define HCA_CAP_SQD_RTS_PORT_CHANGE EHCA_BMASK_IBM( 4, 4)
+#define HCA_CAP_CUR_QP_STATE_MOD EHCA_BMASK_IBM( 5, 5)
+#define HCA_CAP_INIT_TYPE EHCA_BMASK_IBM( 6, 6)
+#define HCA_CAP_PORT_ACTIVE_EVENT EHCA_BMASK_IBM( 7, 7)
+#define HCA_CAP_Q_KEY_VIOL_CTR EHCA_BMASK_IBM( 8, 8)
+#define HCA_CAP_WQE_RESIZE EHCA_BMASK_IBM( 9, 9)
+#define HCA_CAP_RAW_PACKET_MCAST EHCA_BMASK_IBM(10, 10)
+#define HCA_CAP_SHUTDOWN_PORT EHCA_BMASK_IBM(11, 11)
+#define HCA_CAP_RC_LL_QP EHCA_BMASK_IBM(12, 12)
+#define HCA_CAP_SRQ EHCA_BMASK_IBM(13, 13)
+#define HCA_CAP_UD_LL_QP EHCA_BMASK_IBM(16, 16)
+#define HCA_CAP_RESIZE_MR EHCA_BMASK_IBM(17, 17)
+#define HCA_CAP_MINI_QP EHCA_BMASK_IBM(18, 18)
+
/* query port response block */
struct hipz_query_port {
u32 state;
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
index 57f141a36bc..007f0882fd4 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.h
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.h
@@ -105,7 +105,6 @@ void *ipz_qpageit_get_inc(struct ipz_queue *queue);
* step in struct ipz_queue, will wrap in ringbuffer
* returns address (kv) of Queue Entry BEFORE increment
* warning don't use in parallel with ipz_qpageit_get_inc()
- * warning unpredictable results may occur if steps>act_nr_of_queue_entries
*/
static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
{
@@ -121,31 +120,24 @@ static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
}
/*
+ * return a bool indicating whether current Queue Entry is valid
+ */
+static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
+{
+ struct ehca_cqe *cqe = ipz_qeit_get(queue);
+ return ((cqe->cqe_flags >> 7) == (queue->toggle_state & 1));
+}
+
+/*
* return current Queue Entry, increment Queue Entry iterator by one
* step in struct ipz_queue, will wrap in ringbuffer
* returns address (kv) of Queue Entry BEFORE increment
* returns 0 and does not increment, if wrong valid state
* warning don't use in parallel with ipz_qpageit_get_inc()
- * warning unpredictable results may occur if steps>act_nr_of_queue_entries
*/
static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
{
- struct ehca_cqe *cqe = ipz_qeit_get(queue);
- u32 cqe_flags = cqe->cqe_flags;
-
- if ((cqe_flags >> 7) != (queue->toggle_state & 1))
- return NULL;
-
- ipz_qeit_get_inc(queue);
- return cqe;
-}
-
-static inline int ipz_qeit_is_valid(struct ipz_queue *queue)
-{
- struct ehca_cqe *cqe = ipz_qeit_get(queue);
- u32 cqe_flags = cqe->cqe_flags;
-
- return cqe_flags >> 7 == (queue->toggle_state & 1);
+ return ipz_qeit_is_valid(queue) ? ipz_qeit_get_inc(queue) : NULL;
}
/*
diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig
index 90c14543677..044da5828a7 100644
--- a/drivers/infiniband/hw/ipath/Kconfig
+++ b/drivers/infiniband/hw/ipath/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_IPATH
tristate "QLogic InfiniPath Driver"
- depends on (PCI_MSI || HT_IRQ) && 64BIT && INFINIBAND && NET
+ depends on (PCI_MSI || HT_IRQ) && 64BIT && NET
---help---
This is a driver for QLogic InfiniPath host channel adapters,
including InfiniBand verbs support. This driver allows these
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
index 10c008f22ba..b4b786d0dfc 100644
--- a/drivers/infiniband/hw/ipath/ipath_common.h
+++ b/drivers/infiniband/hw/ipath/ipath_common.h
@@ -189,8 +189,7 @@ typedef enum _ipath_ureg {
#define IPATH_RUNTIME_FORCE_WC_ORDER 0x4
#define IPATH_RUNTIME_RCVHDR_COPY 0x8
#define IPATH_RUNTIME_MASTER 0x10
-#define IPATH_RUNTIME_PBC_REWRITE 0x20
-#define IPATH_RUNTIME_LOOSE_DMA_ALIGN 0x40
+/* 0x20 and 0x40 are no longer used, but are reserved for ABI compatibility */
/*
* This structure is returned by ipath_userinit() immediately after
@@ -432,8 +431,15 @@ struct ipath_user_info {
#define IPATH_CMD_UNUSED_1 25
#define IPATH_CMD_UNUSED_2 26
#define IPATH_CMD_PIOAVAILUPD 27 /* force an update of PIOAvail reg */
+#define IPATH_CMD_POLL_TYPE 28 /* set the kind of polling we want */
-#define IPATH_CMD_MAX 27
+#define IPATH_CMD_MAX 28
+
+/*
+ * Poll types
+ */
+#define IPATH_POLL_TYPE_URGENT 0x01
+#define IPATH_POLL_TYPE_OVERFLOW 0x02
struct ipath_port_info {
__u32 num_active; /* number of active units */
@@ -474,6 +480,8 @@ struct ipath_cmd {
__u16 part_key;
/* user address of __u32 bitmask of active slaves */
__u64 slave_mask_addr;
+ /* type of polling we want */
+ __u16 poll_type;
} cmd;
};
@@ -502,13 +510,30 @@ struct __ipath_sendpkt {
struct ipath_iovec sps_iov[4];
};
-/* Passed into diag data special file's ->write method. */
+/*
+ * diagnostics can send a packet by "writing" one of the following
+ * two structs to diag data special file
+ * The first is the legacy version for backward compatibility
+ */
struct ipath_diag_pkt {
__u32 unit;
__u64 data;
__u32 len;
};
+/* The second diag_pkt struct is the expanded version that allows
+ * more control over the packet, specifically, by allowing a custom
+ * pbc (+ extra) qword, so that special modes and deliberate
+ * changes to CRCs can be used. The elements were also re-ordered
+ * for better alignment and to avoid padding issues.
+ */
+struct ipath_diag_xpkt {
+ __u64 data;
+ __u64 pbc_wd;
+ __u32 unit;
+ __u32 len;
+};
+
/*
* Data layout in I2C flash (for GUID, etc.)
* All fields are little-endian binary unless otherwise stated
diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
index 3e9241badba..a6f04d27ec5 100644
--- a/drivers/infiniband/hw/ipath/ipath_cq.c
+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -90,6 +90,8 @@ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited)
wc->queue[head].sl = entry->sl;
wc->queue[head].dlid_path_bits = entry->dlid_path_bits;
wc->queue[head].port_num = entry->port_num;
+ /* Make sure queue entry is written before the head index. */
+ smp_wmb();
wc->head = next;
if (cq->notify == IB_CQ_NEXT_COMP ||
@@ -139,7 +141,8 @@ int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
if (tail == wc->head)
break;
-
+ /* Make sure entry is read after head index is read. */
+ smp_rmb();
qp = ipath_lookup_qpn(&to_idev(cq->ibcq.device)->qp_table,
wc->queue[tail].qp_num);
entry->qp = &qp->ibqp;
diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
index 42bfbdb0d3e..19c56e6491e 100644
--- a/drivers/infiniband/hw/ipath/ipath_debug.h
+++ b/drivers/infiniband/hw/ipath/ipath_debug.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c
index 63e8368b0e9..a698f1949d1 100644
--- a/drivers/infiniband/hw/ipath/ipath_diag.c
+++ b/drivers/infiniband/hw/ipath/ipath_diag.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -323,13 +323,14 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
{
u32 __iomem *piobuf;
u32 plen, clen, pbufn;
- struct ipath_diag_pkt dp;
+ struct ipath_diag_pkt odp;
+ struct ipath_diag_xpkt dp;
u32 *tmpbuf = NULL;
struct ipath_devdata *dd;
ssize_t ret = 0;
u64 val;
- if (count < sizeof(dp)) {
+ if (count != sizeof(dp)) {
ret = -EINVAL;
goto bail;
}
@@ -339,6 +340,29 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
goto bail;
}
+ /*
+ * Due to padding/alignment issues (lessened with new struct)
+ * the old and new structs are the same length. We need to
+ * disambiguate them, which we can do because odp.len has never
+ * been less than the total of LRH+BTH+DETH so far, while
+ * dp.unit (same offset) unit is unlikely to get that high.
+ * Similarly, dp.data, the pointer to user at the same offset
+ * as odp.unit, is almost certainly at least one (512byte)page
+ * "above" NULL. The if-block below can be omitted if compatibility
+ * between a new driver and older diagnostic code is unimportant.
+ * compatibility the other direction (new diags, old driver) is
+ * handled in the diagnostic code, with a warning.
+ */
+ if (dp.unit >= 20 && dp.data < 512) {
+ /* very probable version mismatch. Fix it up */
+ memcpy(&odp, &dp, sizeof(odp));
+ /* We got a legacy dp, copy elements to dp */
+ dp.unit = odp.unit;
+ dp.data = odp.data;
+ dp.len = odp.len;
+ dp.pbc_wd = 0; /* Indicate we need to compute PBC wd */
+ }
+
/* send count must be an exact number of dwords */
if (dp.len & 3) {
ret = -EINVAL;
@@ -371,9 +395,10 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
ret = -ENODEV;
goto bail;
}
+ /* Check link state, but not if we have custom PBC */
val = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
- if (val != IPATH_IBSTATE_INIT && val != IPATH_IBSTATE_ARM &&
- val != IPATH_IBSTATE_ACTIVE) {
+ if (!dp.pbc_wd && val != IPATH_IBSTATE_INIT &&
+ val != IPATH_IBSTATE_ARM && val != IPATH_IBSTATE_ACTIVE) {
ipath_cdbg(VERBOSE, "unit %u not ready (state %llx)\n",
dd->ipath_unit, (unsigned long long) val);
ret = -EINVAL;
@@ -419,9 +444,13 @@ static ssize_t ipath_diagpkt_write(struct file *fp,
ipath_cdbg(VERBOSE, "unit %u 0x%x+1w pio%d\n",
dd->ipath_unit, plen - 1, pbufn);
+ if (dp.pbc_wd == 0)
+ /* Legacy operation, use computed pbc_wd */
+ dp.pbc_wd = plen;
+
/* we have to flush after the PBC for correctness on some cpus
* or WC buffer can be written out of order */
- writeq(plen, piobuf);
+ writeq(dp.pbc_wd, piobuf);
ipath_flush_wc();
/* copy all by the trigger word, then flush, so it's written
* to chip before trigger word, then write trigger word, then
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index e3a22320971..9361f5ab8bd 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -104,6 +104,9 @@ static int __devinit ipath_init_one(struct pci_dev *,
#define PCI_DEVICE_ID_INFINIPATH_HT 0xd
#define PCI_DEVICE_ID_INFINIPATH_PE800 0x10
+/* Number of seconds before our card status check... */
+#define STATUS_TIMEOUT 60
+
static const struct pci_device_id ipath_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) },
{ PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) },
@@ -119,6 +122,18 @@ static struct pci_driver ipath_driver = {
.id_table = ipath_pci_tbl,
};
+static void ipath_check_status(struct work_struct *work)
+{
+ struct ipath_devdata *dd = container_of(work, struct ipath_devdata,
+ status_work.work);
+
+ /*
+ * If we don't have any interrupts, let the user know and
+ * don't bother checking again.
+ */
+ if (dd->ipath_int_counter == 0)
+ dev_err(&dd->pcidev->dev, "No interrupts detected.\n");
+}
static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
u32 *bar0, u32 *bar1)
@@ -187,6 +202,8 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
dd->pcidev = pdev;
pci_set_drvdata(pdev, dd);
+ INIT_DELAYED_WORK(&dd->status_work, ipath_check_status);
+
list_add(&dd->ipath_list, &ipath_dev_list);
bail_unlock:
@@ -270,7 +287,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
struct ipath_devdata *dd;
unsigned long long addr;
u32 bar0 = 0, bar1 = 0;
- u8 rev;
dd = ipath_alloc_devdata(pdev);
if (IS_ERR(dd)) {
@@ -432,13 +448,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
dd->ipath_deviceid = ent->device; /* save for later use */
dd->ipath_vendorid = ent->vendor;
- ret = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
- if (ret) {
- ipath_dev_err(dd, "Failed to read PCI revision ID unit "
- "%u: err %d\n", dd->ipath_unit, -ret);
- goto bail_regions; /* shouldn't ever happen */
- }
- dd->ipath_pcirev = rev;
+ dd->ipath_pcirev = pdev->revision;
#if defined(__powerpc__)
/* There isn't a generic way to specify writethrough mappings */
@@ -511,6 +521,9 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
ipath_diag_add(dd);
ipath_register_ib_device(dd);
+ /* Check that card status in STATUS_TIMEOUT seconds. */
+ schedule_delayed_work(&dd->status_work, HZ * STATUS_TIMEOUT);
+
goto bail;
bail_irqsetup:
@@ -638,6 +651,9 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev)
*/
ipath_shutdown_device(dd);
+ cancel_delayed_work(&dd->status_work);
+ flush_scheduled_work();
+
if (dd->verbs_dev)
ipath_unregister_ib_device(dd->verbs_dev);
@@ -706,9 +722,9 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
u64 sendctrl, sendorig;
ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
- sendorig = dd->ipath_sendctrl | INFINIPATH_S_DISARM;
+ sendorig = dd->ipath_sendctrl;
for (i = first; i < last; i++) {
- sendctrl = sendorig |
+ sendctrl = sendorig | INFINIPATH_S_DISARM |
(i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
sendctrl);
@@ -719,12 +735,12 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
* while we were looping; no critical bits that would require
* locking.
*
- * Write a 0, and then the original value, reading scratch in
+ * disable PIOAVAILUPD, then re-enable, reading scratch in
* between. This seems to avoid a chip timing race that causes
* pioavail updates to memory to stop.
*/
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- 0);
+ sendorig & ~IPATH_S_PIOBUFAVAILUPD);
sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl);
@@ -1021,14 +1037,10 @@ void ipath_kreceive(struct ipath_devdata *dd)
goto bail;
}
- /* There is already a thread processing this queue. */
- if (test_and_set_bit(0, &dd->ipath_rcv_pending))
- goto bail;
-
l = dd->ipath_port0head;
hdrqtail = (u32) le64_to_cpu(*dd->ipath_hdrqtailptr);
if (l == hdrqtail)
- goto done;
+ goto bail;
reloop:
for (i = 0; l != hdrqtail; i++) {
@@ -1163,10 +1175,6 @@ reloop:
ipath_stats.sps_avgpkts_call =
ipath_stats.sps_port0pkts / ++totcalls;
-done:
- clear_bit(0, &dd->ipath_rcv_pending);
- smp_mb__after_clear_bit();
-
bail:;
}
@@ -1596,6 +1604,35 @@ int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
return ret;
}
+
+/*
+ * Flush all sends that might be in the ready to send state, as well as any
+ * that are in the process of being sent. Used whenever we need to be
+ * sure the send side is idle. Cleans up all buffer state by canceling
+ * all pio buffers, and issuing an abort, which cleans up anything in the
+ * launch fifo. The cancel is superfluous on some chip versions, but
+ * it's safer to always do it.
+ * PIOAvail bits are updated by the chip as if normal send had happened.
+ */
+void ipath_cancel_sends(struct ipath_devdata *dd)
+{
+ ipath_dbg("Cancelling all in-progress send buffers\n");
+ dd->ipath_lastcancel = jiffies+HZ/2; /* skip armlaunch errs a bit */
+ /*
+ * the abort bit is auto-clearing. We read scratch to be sure
+ * that cancels and the abort have taken effect in the chip.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ INFINIPATH_S_ABORT);
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ ipath_disarm_piobufs(dd, 0,
+ (unsigned)(dd->ipath_piobcnt2k + dd->ipath_piobcnt4k));
+
+ /* and again, be sure all have hit the chip */
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+}
+
+
static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
{
static const char *what[4] = {
@@ -1617,14 +1654,8 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]);
/* flush all queued sends when going to DOWN or INIT, to be sure that
* they don't block MAD packets */
- if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) {
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- INFINIPATH_S_ABORT);
- ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
- (unsigned)(dd->ipath_piobcnt2k +
- dd->ipath_piobcnt4k) -
- dd->ipath_lastport_piobuf);
- }
+ if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT)
+ ipath_cancel_sends(dd);
ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
dd->ipath_ibcctrl | which);
@@ -1846,6 +1877,87 @@ void ipath_write_kreg_port(const struct ipath_devdata *dd, ipath_kreg regno,
ipath_write_kreg(dd, where, value);
}
+/*
+ * Following deal with the "obviously simple" task of overriding the state
+ * of the LEDS, which normally indicate link physical and logical status.
+ * The complications arise in dealing with different hardware mappings
+ * and the board-dependent routine being called from interrupts.
+ * and then there's the requirement to _flash_ them.
+ */
+#define LED_OVER_FREQ_SHIFT 8
+#define LED_OVER_FREQ_MASK (0xFF<<LED_OVER_FREQ_SHIFT)
+/* Below is "non-zero" to force override, but both actual LEDs are off */
+#define LED_OVER_BOTH_OFF (8)
+
+void ipath_run_led_override(unsigned long opaque)
+{
+ struct ipath_devdata *dd = (struct ipath_devdata *)opaque;
+ int timeoff;
+ int pidx;
+ u64 lstate, ltstate, val;
+
+ if (!(dd->ipath_flags & IPATH_INITTED))
+ return;
+
+ pidx = dd->ipath_led_override_phase++ & 1;
+ dd->ipath_led_override = dd->ipath_led_override_vals[pidx];
+ timeoff = dd->ipath_led_override_timeoff;
+
+ /*
+ * below potentially restores the LED values per current status,
+ * should also possibly setup the traffic-blink register,
+ * but leave that to per-chip functions.
+ */
+ val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_ibcstatus);
+ ltstate = (val >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKTRAININGSTATE_MASK;
+ lstate = (val >> INFINIPATH_IBCS_LINKSTATE_SHIFT) &
+ INFINIPATH_IBCS_LINKSTATE_MASK;
+
+ dd->ipath_f_setextled(dd, lstate, ltstate);
+ mod_timer(&dd->ipath_led_override_timer, jiffies + timeoff);
+}
+
+void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
+{
+ int timeoff, freq;
+
+ if (!(dd->ipath_flags & IPATH_INITTED))
+ return;
+
+ /* First check if we are blinking. If not, use 1HZ polling */
+ timeoff = HZ;
+ freq = (val & LED_OVER_FREQ_MASK) >> LED_OVER_FREQ_SHIFT;
+
+ if (freq) {
+ /* For blink, set each phase from one nybble of val */
+ dd->ipath_led_override_vals[0] = val & 0xF;
+ dd->ipath_led_override_vals[1] = (val >> 4) & 0xF;
+ timeoff = (HZ << 4)/freq;
+ } else {
+ /* Non-blink set both phases the same. */
+ dd->ipath_led_override_vals[0] = val & 0xF;
+ dd->ipath_led_override_vals[1] = val & 0xF;
+ }
+ dd->ipath_led_override_timeoff = timeoff;
+
+ /*
+ * If the timer has not already been started, do so. Use a "quick"
+ * timeout so the function will be called soon, to look at our request.
+ */
+ if (atomic_inc_return(&dd->ipath_led_override_timer_active) == 1) {
+ /* Need to start timer */
+ init_timer(&dd->ipath_led_override_timer);
+ dd->ipath_led_override_timer.function =
+ ipath_run_led_override;
+ dd->ipath_led_override_timer.data = (unsigned long) dd;
+ dd->ipath_led_override_timer.expires = jiffies + 1;
+ add_timer(&dd->ipath_led_override_timer);
+ } else {
+ atomic_dec(&dd->ipath_led_override_timer_active);
+ }
+}
+
/**
* ipath_shutdown_device - shut down a device
* @dd: the infinipath device
@@ -1886,17 +1998,9 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
*/
udelay(5);
- /*
- * abort any armed or launched PIO buffers that didn't go. (self
- * clearing). Will cause any packet currently being transmitted to
- * go out with an EBP, and may also cause a short packet error on
- * the receiver.
- */
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- INFINIPATH_S_ABORT);
-
ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
INFINIPATH_IBCC_LINKINITCMD_SHIFT);
+ ipath_cancel_sends(dd);
/* disable IBC */
dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
@@ -1909,7 +2013,6 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
* Turn the LEDs off explictly for the same reason.
*/
dd->ipath_f_quiet_serdes(dd);
- dd->ipath_f_setextled(dd, 0, 0);
if (dd->ipath_stats_timer_active) {
del_timer_sync(&dd->ipath_stats_timer);
@@ -1925,6 +2028,9 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
~0ULL & ~INFINIPATH_HWE_MEMBISTFAILED);
ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, -1LL);
ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, -1LL);
+
+ ipath_cdbg(VERBOSE, "Flush time and errors to EEPROM\n");
+ ipath_update_eeprom_log(dd);
}
/**
@@ -2085,6 +2191,16 @@ int ipath_reset_device(int unit)
goto bail;
}
+ if (atomic_read(&dd->ipath_led_override_timer_active)) {
+ /* Need to stop LED timer, _then_ shut off LEDs */
+ del_timer_sync(&dd->ipath_led_override_timer);
+ atomic_set(&dd->ipath_led_override_timer_active, 0);
+ }
+
+ /* Shut off LEDs after we are sure timer is not running */
+ dd->ipath_led_override = LED_OVER_BOTH_OFF;
+ dd->ipath_f_setextled(dd, 0, 0);
+
dev_info(&dd->pcidev->dev, "Reset on unit %u requested\n", unit);
if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_PRESENT)) {
diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
index 030185f90ee..6b9147964a4 100644
--- a/drivers/infiniband/hw/ipath/ipath_eeprom.c
+++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -95,39 +95,37 @@ static int i2c_gpio_set(struct ipath_devdata *dd,
enum i2c_type line,
enum i2c_state new_line_state)
{
- u64 read_val, write_val, mask, *gpioval;
+ u64 out_mask, dir_mask, *gpioval;
+ unsigned long flags = 0;
gpioval = &dd->ipath_gpio_out;
- read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
- if (line == i2c_line_scl)
- mask = dd->ipath_gpio_scl;
- else
- mask = dd->ipath_gpio_sda;
- if (new_line_state == i2c_line_high)
+ if (line == i2c_line_scl) {
+ dir_mask = dd->ipath_gpio_scl;
+ out_mask = (1UL << dd->ipath_gpio_scl_num);
+ } else {
+ dir_mask = dd->ipath_gpio_sda;
+ out_mask = (1UL << dd->ipath_gpio_sda_num);
+ }
+
+ spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+ if (new_line_state == i2c_line_high) {
/* tri-state the output rather than force high */
- write_val = read_val & ~mask;
- else
+ dd->ipath_extctrl &= ~dir_mask;
+ } else {
/* config line to be an output */
- write_val = read_val | mask;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+ dd->ipath_extctrl |= dir_mask;
+ }
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl);
- /* set high and verify */
+ /* set output as well (no real verify) */
if (new_line_state == i2c_line_high)
- write_val = 0x1UL;
+ *gpioval |= out_mask;
else
- write_val = 0x0UL;
+ *gpioval &= ~out_mask;
- if (line == i2c_line_scl) {
- write_val <<= dd->ipath_gpio_scl_num;
- *gpioval = *gpioval & ~(1UL << dd->ipath_gpio_scl_num);
- *gpioval |= write_val;
- } else {
- write_val <<= dd->ipath_gpio_sda_num;
- *gpioval = *gpioval & ~(1UL << dd->ipath_gpio_sda_num);
- *gpioval |= write_val;
- }
ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_out, *gpioval);
+ spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
return 0;
}
@@ -145,8 +143,9 @@ static int i2c_gpio_get(struct ipath_devdata *dd,
enum i2c_type line,
enum i2c_state *curr_statep)
{
- u64 read_val, write_val, mask;
+ u64 read_val, mask;
int ret;
+ unsigned long flags = 0;
/* check args */
if (curr_statep == NULL) {
@@ -154,15 +153,21 @@ static int i2c_gpio_get(struct ipath_devdata *dd,
goto bail;
}
- read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
/* config line to be an input */
if (line == i2c_line_scl)
mask = dd->ipath_gpio_scl;
else
mask = dd->ipath_gpio_sda;
- write_val = read_val & ~mask;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, write_val);
+
+ spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+ dd->ipath_extctrl &= ~mask;
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, dd->ipath_extctrl);
+ /*
+ * Below is very unlikely to reflect true input state if Output
+ * Enable actually changed.
+ */
read_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
+ spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
if (read_val & mask)
*curr_statep = i2c_line_high;
@@ -192,6 +197,7 @@ static void i2c_wait_for_writes(struct ipath_devdata *dd)
static void scl_out(struct ipath_devdata *dd, u8 bit)
{
+ udelay(1);
i2c_gpio_set(dd, i2c_line_scl, bit ? i2c_line_high : i2c_line_low);
i2c_wait_for_writes(dd);
@@ -314,12 +320,18 @@ static int eeprom_reset(struct ipath_devdata *dd)
int clock_cycles_left = 9;
u64 *gpioval = &dd->ipath_gpio_out;
int ret;
+ unsigned long flags;
- eeprom_init = 1;
+ spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
+ /* Make sure shadows are consistent */
+ dd->ipath_extctrl = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extctrl);
*gpioval = ipath_read_kreg64(dd, dd->ipath_kregs->kr_gpio_out);
+ spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
+
ipath_cdbg(VERBOSE, "Resetting i2c eeprom; initial gpioout reg "
"is %llx\n", (unsigned long long) *gpioval);
+ eeprom_init = 1;
/*
* This is to get the i2c into a known state, by first going low,
* then tristate sda (and then tristate scl as first thing
@@ -355,8 +367,8 @@ bail:
* @len: number of bytes to receive
*/
-int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
- void *buffer, int len)
+static int ipath_eeprom_internal_read(struct ipath_devdata *dd,
+ u8 eeprom_offset, void *buffer, int len)
{
/* compiler complains unless initialized */
u8 single_byte = 0;
@@ -406,6 +418,7 @@ bail:
return ret;
}
+
/**
* ipath_eeprom_write - writes data to the eeprom via I2C
* @dd: the infinipath device
@@ -413,8 +426,8 @@ bail:
* @buffer: data to write
* @len: number of bytes to write
*/
-int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
- const void *buffer, int len)
+int ipath_eeprom_internal_write(struct ipath_devdata *dd, u8 eeprom_offset,
+ const void *buffer, int len)
{
u8 single_byte;
int sub_len;
@@ -488,6 +501,38 @@ bail:
return ret;
}
+/*
+ * The public entry-points ipath_eeprom_read() and ipath_eeprom_write()
+ * are now just wrappers around the internal functions.
+ */
+int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
+ void *buff, int len)
+{
+ int ret;
+
+ ret = down_interruptible(&dd->ipath_eep_sem);
+ if (!ret) {
+ ret = ipath_eeprom_internal_read(dd, eeprom_offset, buff, len);
+ up(&dd->ipath_eep_sem);
+ }
+
+ return ret;
+}
+
+int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
+ const void *buff, int len)
+{
+ int ret;
+
+ ret = down_interruptible(&dd->ipath_eep_sem);
+ if (!ret) {
+ ret = ipath_eeprom_internal_write(dd, eeprom_offset, buff, len);
+ up(&dd->ipath_eep_sem);
+ }
+
+ return ret;
+}
+
static u8 flash_csum(struct ipath_flash *ifp, int adjust)
{
u8 *ip = (u8 *) ifp;
@@ -515,7 +560,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
void *buf;
struct ipath_flash *ifp;
__be64 guid;
- int len;
+ int len, eep_stat;
u8 csum, *bguid;
int t = dd->ipath_unit;
struct ipath_devdata *dd0 = ipath_lookup(0);
@@ -559,7 +604,11 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
goto bail;
}
- if (ipath_eeprom_read(dd, 0, buf, len)) {
+ down(&dd->ipath_eep_sem);
+ eep_stat = ipath_eeprom_internal_read(dd, 0, buf, len);
+ up(&dd->ipath_eep_sem);
+
+ if (eep_stat) {
ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
goto done;
}
@@ -634,8 +683,192 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
ipath_cdbg(VERBOSE, "Initted GUID to %llx from eeprom\n",
(unsigned long long) be64_to_cpu(dd->ipath_guid));
+ memcpy(&dd->ipath_eep_st_errs, &ifp->if_errcntp, IPATH_EEP_LOG_CNT);
+ /*
+ * Power-on (actually "active") hours are kept as little-endian value
+ * in EEPROM, but as seconds in a (possibly as small as 24-bit)
+ * atomic_t while running.
+ */
+ atomic_set(&dd->ipath_active_time, 0);
+ dd->ipath_eep_hrs = ifp->if_powerhour[0] | (ifp->if_powerhour[1] << 8);
+
done:
vfree(buf);
bail:;
}
+
+/**
+ * ipath_update_eeprom_log - copy active-time and error counters to eeprom
+ * @dd: the infinipath device
+ *
+ * Although the time is kept as seconds in the ipath_devdata struct, it is
+ * rounded to hours for re-write, as we have only 16 bits in EEPROM.
+ * First-cut code reads whole (expected) struct ipath_flash, modifies,
+ * re-writes. Future direction: read/write only what we need, assuming
+ * that the EEPROM had to have been "good enough" for driver init, and
+ * if not, we aren't making it worse.
+ *
+ */
+
+int ipath_update_eeprom_log(struct ipath_devdata *dd)
+{
+ void *buf;
+ struct ipath_flash *ifp;
+ int len, hi_water;
+ uint32_t new_time, new_hrs;
+ u8 csum;
+ int ret, idx;
+ unsigned long flags;
+
+ /* first, check if we actually need to do anything. */
+ ret = 0;
+ for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+ if (dd->ipath_eep_st_new_errs[idx]) {
+ ret = 1;
+ break;
+ }
+ }
+ new_time = atomic_read(&dd->ipath_active_time);
+
+ if (ret == 0 && new_time < 3600)
+ return 0;
+
+ /*
+ * The quick-check above determined that there is something worthy
+ * of logging, so get current contents and do a more detailed idea.
+ */
+ len = offsetof(struct ipath_flash, if_future);
+ buf = vmalloc(len);
+ ret = 1;
+ if (!buf) {
+ ipath_dev_err(dd, "Couldn't allocate memory to read %u "
+ "bytes from eeprom for logging\n", len);
+ goto bail;
+ }
+
+ /* Grab semaphore and read current EEPROM. If we get an
+ * error, let go, but if not, keep it until we finish write.
+ */
+ ret = down_interruptible(&dd->ipath_eep_sem);
+ if (ret) {
+ ipath_dev_err(dd, "Unable to acquire EEPROM for logging\n");
+ goto free_bail;
+ }
+ ret = ipath_eeprom_internal_read(dd, 0, buf, len);
+ if (ret) {
+ up(&dd->ipath_eep_sem);
+ ipath_dev_err(dd, "Unable read EEPROM for logging\n");
+ goto free_bail;
+ }
+ ifp = (struct ipath_flash *)buf;
+
+ csum = flash_csum(ifp, 0);
+ if (csum != ifp->if_csum) {
+ up(&dd->ipath_eep_sem);
+ ipath_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
+ csum, ifp->if_csum);
+ ret = 1;
+ goto free_bail;
+ }
+ hi_water = 0;
+ spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+ for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+ int new_val = dd->ipath_eep_st_new_errs[idx];
+ if (new_val) {
+ /*
+ * If we have seen any errors, add to EEPROM values
+ * We need to saturate at 0xFF (255) and we also
+ * would need to adjust the checksum if we were
+ * trying to minimize EEPROM traffic
+ * Note that we add to actual current count in EEPROM,
+ * in case it was altered while we were running.
+ */
+ new_val += ifp->if_errcntp[idx];
+ if (new_val > 0xFF)
+ new_val = 0xFF;
+ if (ifp->if_errcntp[idx] != new_val) {
+ ifp->if_errcntp[idx] = new_val;
+ hi_water = offsetof(struct ipath_flash,
+ if_errcntp) + idx;
+ }
+ /*
+ * update our shadow (used to minimize EEPROM
+ * traffic), to match what we are about to write.
+ */
+ dd->ipath_eep_st_errs[idx] = new_val;
+ dd->ipath_eep_st_new_errs[idx] = 0;
+ }
+ }
+ /*
+ * now update active-time. We would like to round to the nearest hour
+ * but unless atomic_t are sure to be proper signed ints we cannot,
+ * because we need to account for what we "transfer" to EEPROM and
+ * if we log an hour at 31 minutes, then we would need to set
+ * active_time to -29 to accurately count the _next_ hour.
+ */
+ if (new_time > 3600) {
+ new_hrs = new_time / 3600;
+ atomic_sub((new_hrs * 3600), &dd->ipath_active_time);
+ new_hrs += dd->ipath_eep_hrs;
+ if (new_hrs > 0xFFFF)
+ new_hrs = 0xFFFF;
+ dd->ipath_eep_hrs = new_hrs;
+ if ((new_hrs & 0xFF) != ifp->if_powerhour[0]) {
+ ifp->if_powerhour[0] = new_hrs & 0xFF;
+ hi_water = offsetof(struct ipath_flash, if_powerhour);
+ }
+ if ((new_hrs >> 8) != ifp->if_powerhour[1]) {
+ ifp->if_powerhour[1] = new_hrs >> 8;
+ hi_water = offsetof(struct ipath_flash, if_powerhour)
+ + 1;
+ }
+ }
+ /*
+ * There is a tiny possibility that we could somehow fail to write
+ * the EEPROM after updating our shadows, but problems from holding
+ * the spinlock too long are a much bigger issue.
+ */
+ spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+ if (hi_water) {
+ /* we made some change to the data, uopdate cksum and write */
+ csum = flash_csum(ifp, 1);
+ ret = ipath_eeprom_internal_write(dd, 0, buf, hi_water + 1);
+ }
+ up(&dd->ipath_eep_sem);
+ if (ret)
+ ipath_dev_err(dd, "Failed updating EEPROM\n");
+
+free_bail:
+ vfree(buf);
+bail:
+ return ret;
+
+}
+
+/**
+ * ipath_inc_eeprom_err - increment one of the four error counters
+ * that are logged to EEPROM.
+ * @dd: the infinipath device
+ * @eidx: 0..3, the counter to increment
+ * @incr: how much to add
+ *
+ * Each counter is 8-bits, and saturates at 255 (0xFF). They
+ * are copied to the EEPROM (aka flash) whenever ipath_update_eeprom_log()
+ * is called, but it can only be called in a context that allows sleep.
+ * This function can be called even at interrupt level.
+ */
+
+void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr)
+{
+ uint new_val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+ new_val = dd->ipath_eep_st_new_errs[eidx] + incr;
+ if (new_val > 255)
+ new_val = 255;
+ dd->ipath_eep_st_new_errs[eidx] = new_val;
+ spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+ return;
+}
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 1272aaf2a78..33ab0d6b80f 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -396,7 +396,8 @@ static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp,
"TID %u, vaddr %lx, physaddr %llx pgp %p\n",
tid, vaddr, (unsigned long long) physaddr,
pagep[i]);
- dd->ipath_f_put_tid(dd, &tidbase[tid], 1, physaddr);
+ dd->ipath_f_put_tid(dd, &tidbase[tid], RCVHQ_RCV_TYPE_EXPECTED,
+ physaddr);
/*
* don't check this tid in ipath_portshadow, since we
* just filled it in; start with the next one.
@@ -422,7 +423,8 @@ static int ipath_tid_update(struct ipath_portdata *pd, struct file *fp,
if (dd->ipath_pageshadow[porttid + tid]) {
ipath_cdbg(VERBOSE, "Freeing TID %u\n",
tid);
- dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+ dd->ipath_f_put_tid(dd, &tidbase[tid],
+ RCVHQ_RCV_TYPE_EXPECTED,
dd->ipath_tidinvalid);
pci_unmap_page(dd->pcidev,
dd->ipath_physshadow[porttid + tid],
@@ -538,7 +540,8 @@ static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport,
if (dd->ipath_pageshadow[porttid + tid]) {
ipath_cdbg(VERBOSE, "PID %u freeing TID %u\n",
pd->port_pid, tid);
- dd->ipath_f_put_tid(dd, &tidbase[tid], 1,
+ dd->ipath_f_put_tid(dd, &tidbase[tid],
+ RCVHQ_RCV_TYPE_EXPECTED,
dd->ipath_tidinvalid);
pci_unmap_page(dd->pcidev,
dd->ipath_physshadow[porttid + tid],
@@ -921,7 +924,8 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
(u64 __iomem *)
((char __iomem *)
dd->ipath_kregbase +
- dd->ipath_rcvegrbase), 0, pa);
+ dd->ipath_rcvegrbase),
+ RCVHQ_RCV_TYPE_EAGER, pa);
pa += egrsize;
}
cond_resched(); /* don't hog the cpu */
@@ -1337,68 +1341,133 @@ bail:
return ret;
}
-static unsigned int ipath_poll(struct file *fp,
- struct poll_table_struct *pt)
+static unsigned int ipath_poll_urgent(struct ipath_portdata *pd,
+ struct file *fp,
+ struct poll_table_struct *pt)
{
- struct ipath_portdata *pd;
- u32 head, tail;
- int bit;
unsigned pollflag = 0;
struct ipath_devdata *dd;
- pd = port_fp(fp);
- if (!pd)
- goto bail;
dd = pd->port_dd;
- bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT;
- set_bit(bit, &dd->ipath_rcvctrl);
+ if (test_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag)) {
+ pollflag |= POLLERR;
+ clear_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag);
+ }
- /*
- * Before blocking, make sure that head is still == tail,
- * reading from the chip, so we can be sure the interrupt
- * enable has made it to the chip. If not equal, disable
- * interrupt again and return immediately. This avoids races,
- * and the overhead of the chip read doesn't matter much at
- * this point, since we are waiting for something anyway.
- */
+ if (test_bit(IPATH_PORT_WAITING_URG, &pd->int_flag)) {
+ pollflag |= POLLIN | POLLRDNORM;
+ clear_bit(IPATH_PORT_WAITING_URG, &pd->int_flag);
+ }
- ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
- dd->ipath_rcvctrl);
+ if (!pollflag) {
+ set_bit(IPATH_PORT_WAITING_URG, &pd->port_flag);
+ if (pd->poll_type & IPATH_POLL_TYPE_OVERFLOW)
+ set_bit(IPATH_PORT_WAITING_OVERFLOW,
+ &pd->port_flag);
+
+ poll_wait(fp, &pd->port_wait, pt);
+ }
+
+ return pollflag;
+}
+
+static unsigned int ipath_poll_next(struct ipath_portdata *pd,
+ struct file *fp,
+ struct poll_table_struct *pt)
+{
+ u32 head, tail;
+ unsigned pollflag = 0;
+ struct ipath_devdata *dd;
+
+ dd = pd->port_dd;
head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
- tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
+ tail = *(volatile u64 *)pd->port_rcvhdrtail_kvaddr;
- if (tail == head) {
+ if (test_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag)) {
+ pollflag |= POLLERR;
+ clear_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag);
+ }
+
+ if (tail != head ||
+ test_bit(IPATH_PORT_WAITING_RCV, &pd->int_flag)) {
+ pollflag |= POLLIN | POLLRDNORM;
+ clear_bit(IPATH_PORT_WAITING_RCV, &pd->int_flag);
+ }
+
+ if (!pollflag) {
set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
+ if (pd->poll_type & IPATH_POLL_TYPE_OVERFLOW)
+ set_bit(IPATH_PORT_WAITING_OVERFLOW,
+ &pd->port_flag);
+
+ set_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
+ &dd->ipath_rcvctrl);
+
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ dd->ipath_rcvctrl);
+
if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */
- (void)ipath_write_ureg(dd, ur_rcvhdrhead,
- dd->ipath_rhdrhead_intr_off
- | head, pd->port_port);
- poll_wait(fp, &pd->port_wait, pt);
+ ipath_write_ureg(dd, ur_rcvhdrhead,
+ dd->ipath_rhdrhead_intr_off | head,
+ pd->port_port);
- if (test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) {
- /* timed out, no packets received */
- clear_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag);
- pd->port_rcvwait_to++;
- }
- else
- pollflag = POLLIN | POLLRDNORM;
- }
- else {
- /* it's already happened; don't do wait_event overhead */
- pollflag = POLLIN | POLLRDNORM;
- pd->port_rcvnowait++;
+ poll_wait(fp, &pd->port_wait, pt);
}
- clear_bit(bit, &dd->ipath_rcvctrl);
- ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
- dd->ipath_rcvctrl);
+ return pollflag;
+}
+
+static unsigned int ipath_poll(struct file *fp,
+ struct poll_table_struct *pt)
+{
+ struct ipath_portdata *pd;
+ unsigned pollflag;
+
+ pd = port_fp(fp);
+ if (!pd)
+ pollflag = 0;
+ else if (pd->poll_type & IPATH_POLL_TYPE_URGENT)
+ pollflag = ipath_poll_urgent(pd, fp, pt);
+ else
+ pollflag = ipath_poll_next(pd, fp, pt);
-bail:
return pollflag;
}
+static int ipath_supports_subports(int user_swmajor, int user_swminor)
+{
+ /* no subport implementation prior to software version 1.3 */
+ return (user_swmajor > 1) || (user_swminor >= 3);
+}
+
+static int ipath_compatible_subports(int user_swmajor, int user_swminor)
+{
+ /* this code is written long-hand for clarity */
+ if (IPATH_USER_SWMAJOR != user_swmajor) {
+ /* no promise of compatibility if major mismatch */
+ return 0;
+ }
+ if (IPATH_USER_SWMAJOR == 1) {
+ switch (IPATH_USER_SWMINOR) {
+ case 0:
+ case 1:
+ case 2:
+ /* no subport implementation so cannot be compatible */
+ return 0;
+ case 3:
+ /* 3 is only compatible with itself */
+ return user_swminor == 3;
+ default:
+ /* >= 4 are compatible (or are expected to be) */
+ return user_swminor >= 4;
+ }
+ }
+ /* make no promises yet for future major versions */
+ return 0;
+}
+
static int init_subports(struct ipath_devdata *dd,
struct ipath_portdata *pd,
const struct ipath_user_info *uinfo)
@@ -1408,20 +1477,32 @@ static int init_subports(struct ipath_devdata *dd,
size_t size;
/*
- * If the user is requesting zero or one port,
+ * If the user is requesting zero subports,
* skip the subport allocation.
*/
- if (uinfo->spu_subport_cnt <= 1)
+ if (uinfo->spu_subport_cnt <= 0)
+ goto bail;
+
+ /* Self-consistency check for ipath_compatible_subports() */
+ if (ipath_supports_subports(IPATH_USER_SWMAJOR, IPATH_USER_SWMINOR) &&
+ !ipath_compatible_subports(IPATH_USER_SWMAJOR,
+ IPATH_USER_SWMINOR)) {
+ dev_info(&dd->pcidev->dev,
+ "Inconsistent ipath_compatible_subports()\n");
goto bail;
+ }
- /* Old user binaries don't know about new subport implementation */
- if ((uinfo->spu_userversion & 0xffff) != IPATH_USER_SWMINOR) {
+ /* Check for subport compatibility */
+ if (!ipath_compatible_subports(uinfo->spu_userversion >> 16,
+ uinfo->spu_userversion & 0xffff)) {
dev_info(&dd->pcidev->dev,
- "Mismatched user minor version (%d) and driver "
- "minor version (%d) while port sharing. Ensure "
+ "Mismatched user version (%d.%d) and driver "
+ "version (%d.%d) while port sharing. Ensure "
"that driver and library are from the same "
"release.\n",
+ (int) (uinfo->spu_userversion >> 16),
(int) (uinfo->spu_userversion & 0xffff),
+ IPATH_USER_SWMAJOR,
IPATH_USER_SWMINOR);
goto bail;
}
@@ -1725,14 +1806,13 @@ static int ipath_open(struct inode *in, struct file *fp)
return fp->private_data ? 0 : -ENOMEM;
}
-
/* Get port early, so can set affinity prior to memory allocation */
static int ipath_assign_port(struct file *fp,
const struct ipath_user_info *uinfo)
{
int ret;
int i_minor;
- unsigned swminor;
+ unsigned swmajor, swminor;
/* Check to be sure we haven't already initialized this file */
if (port_fp(fp)) {
@@ -1741,7 +1821,8 @@ static int ipath_assign_port(struct file *fp,
}
/* for now, if major version is different, bail */
- if ((uinfo->spu_userversion >> 16) != IPATH_USER_SWMAJOR) {
+ swmajor = uinfo->spu_userversion >> 16;
+ if (swmajor != IPATH_USER_SWMAJOR) {
ipath_dbg("User major version %d not same as driver "
"major %d\n", uinfo->spu_userversion >> 16,
IPATH_USER_SWMAJOR);
@@ -1756,7 +1837,8 @@ static int ipath_assign_port(struct file *fp,
mutex_lock(&ipath_mutex);
- if (swminor == IPATH_USER_SWMINOR && uinfo->spu_subport_cnt &&
+ if (ipath_compatible_subports(swmajor, swminor) &&
+ uinfo->spu_subport_cnt &&
(ret = find_shared_port(fp, uinfo))) {
mutex_unlock(&ipath_mutex);
if (ret > 0)
@@ -2020,7 +2102,8 @@ static int ipath_port_info(struct ipath_portdata *pd, u16 subport,
info.port = pd->port_port;
info.subport = subport;
/* Don't return new fields if old library opened the port. */
- if ((pd->userversion & 0xffff) == IPATH_USER_SWMINOR) {
+ if (ipath_supports_subports(pd->userversion >> 16,
+ pd->userversion & 0xffff)) {
/* Number of user ports available for this device. */
info.num_ports = pd->port_dd->ipath_cfgports - 1;
info.num_subports = pd->port_subport_cnt;
@@ -2123,6 +2206,11 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
src = NULL;
dest = NULL;
break;
+ case IPATH_CMD_POLL_TYPE:
+ copy = sizeof(cmd.cmd.poll_type);
+ dest = &cmd.cmd.poll_type;
+ src = &ucmd->cmd.poll_type;
+ break;
default:
ret = -EINVAL;
goto bail;
@@ -2195,6 +2283,9 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
case IPATH_CMD_PIOAVAILUPD:
ret = ipath_force_pio_avail_update(pd->port_dd);
break;
+ case IPATH_CMD_POLL_TYPE:
+ pd->poll_type = cmd.cmd.poll_type;
+ break;
}
if (ret >= 0)
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index ebd5c7bd2cd..2e689b974e1 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -257,9 +257,14 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
/* Notimpl InitType (actually, an SMA decision) */
/* VLHighLimit is 0 (only one VL) */
; /* VLArbitrationHighCap is 0 (only one VL) */
+ /*
+ * Note: the chips support a maximum MTU of 4096, but the driver
+ * hasn't implemented this feature yet, so set the maximum
+ * to 2048.
+ */
portinfo[10] = /* VLArbitrationLowCap is 0 (only one VL) */
/* InitTypeReply is SMA decision */
- (5 << 16) /* MTUCap 4096 */
+ (4 << 16) /* MTUCap 2048 */
| (7 << 13) /* VLStallCount */
| (0x1f << 8) /* HOQLife */
| (1 << 4)
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
index 4171198fc20..650745d83fa 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -36,6 +36,7 @@
* HT chip.
*/
+#include <linux/vmalloc.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/htirq.h>
@@ -439,6 +440,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
u32 bits, ctrl;
int isfatal = 0;
char bitsmsg[64];
+ int log_idx;
hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
@@ -467,6 +469,11 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
hwerrs &= dd->ipath_hwerrmask;
+ /* We log some errors to EEPROM, check if we have any of those. */
+ for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)
+ if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)
+ ipath_inc_eeprom_err(dd, log_idx, 1);
+
/*
* make sure we get this much out, unless told to be quiet,
* it's a parity error we may recover from,
@@ -502,9 +509,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg,
if (!hwerrs) {
ipath_dbg("Clearing freezemode on ignored or "
"recovered hardware error\n");
- ctrl &= ~INFINIPATH_C_FREEZEMODE;
- ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
- ctrl);
+ ipath_clear_freeze(dd);
}
}
@@ -672,10 +677,16 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
if (n)
snprintf(name, namelen, "%s", n);
+ if (dd->ipath_boardrev != 6 && dd->ipath_boardrev != 7 &&
+ dd->ipath_boardrev != 11) {
+ ipath_dev_err(dd, "Unsupported InfiniPath board %s!\n", name);
+ ret = 1;
+ goto bail;
+ }
if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 ||
- dd->ipath_minrev > 3)) {
+ dd->ipath_minrev > 4)) {
/*
- * This version of the driver only supports Rev 3.2 and 3.3
+ * This version of the driver only supports Rev 3.2 - 3.4
*/
ipath_dev_err(dd,
"Unsupported InfiniPath hardware revision %u.%u!\n",
@@ -689,36 +700,11 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
* copies
*/
dd->ipath_flags |= IPATH_32BITCOUNTERS;
+ dd->ipath_flags |= IPATH_GPIO_INTR;
if (dd->ipath_htspeed != 800)
ipath_dev_err(dd,
"Incorrectly configured for HT @ %uMHz\n",
dd->ipath_htspeed);
- if (dd->ipath_boardrev == 7 || dd->ipath_boardrev == 11 ||
- dd->ipath_boardrev == 6)
- dd->ipath_flags |= IPATH_GPIO_INTR;
- else
- dd->ipath_flags |= IPATH_POLL_RX_INTR;
- if (dd->ipath_boardrev == 8) { /* LS/X-1 */
- u64 val;
- val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_extstatus);
- if (val & INFINIPATH_EXTS_SERDESSEL) {
- /*
- * hardware disabled
- *
- * This means that the chip is hardware disabled,
- * and will not be able to bring up the link,
- * in any case. We special case this and abort
- * early, to avoid later messages. We also set
- * the DISABLED status bit
- */
- ipath_dbg("Unit %u is hardware-disabled\n",
- dd->ipath_unit);
- *dd->ipath_statusp |= IPATH_STATUS_DISABLED;
- /* this value is handled differently */
- ret = 2;
- goto bail;
- }
- }
ret = 0;
bail:
@@ -1058,12 +1044,24 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
u64 lst, u64 ltst)
{
u64 extctl;
+ unsigned long flags = 0;
/* the diags use the LED to indicate diag info, so we leave
* the external LED alone when the diags are running */
if (ipath_diag_inuse)
return;
+ /* Allow override of LED display for, e.g. Locating system in rack */
+ if (dd->ipath_led_override) {
+ ltst = (dd->ipath_led_override & IPATH_LED_PHYS)
+ ? INFINIPATH_IBCS_LT_STATE_LINKUP
+ : INFINIPATH_IBCS_LT_STATE_DISABLED;
+ lst = (dd->ipath_led_override & IPATH_LED_LOG)
+ ? INFINIPATH_IBCS_L_STATE_ACTIVE
+ : INFINIPATH_IBCS_L_STATE_DOWN;
+ }
+
+ spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
/*
* start by setting both LED control bits to off, then turn
* on the appropriate bit(s).
@@ -1092,6 +1090,7 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
}
dd->ipath_extctrl = extctl;
ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+ spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
}
static void ipath_init_ht_variables(struct ipath_devdata *dd)
@@ -1157,6 +1156,22 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+
+ /*
+ * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
+ * 2 is Some Misc, 3 is reserved for future.
+ */
+ dd->ipath_eep_st_masks[0].hwerrs_to_log =
+ INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;
+
+ dd->ipath_eep_st_masks[1].hwerrs_to_log =
+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
+
+ dd->ipath_eep_st_masks[2].errs_to_log =
+ INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+
}
/**
@@ -1372,7 +1387,7 @@ static void ipath_ht_quiet_serdes(struct ipath_devdata *dd)
* ipath_pe_put_tid - write a TID in chip
* @dd: the infinipath device
* @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
* @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
*
* This exists as a separate routine to allow for special locking etc.
@@ -1393,7 +1408,7 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd,
"40 bits, using only 40!!!\n", pa);
pa &= INFINIPATH_RT_ADDR_MASK;
}
- if (type == 0)
+ if (type == RCVHQ_RCV_TYPE_EAGER)
pa |= dd->ipath_tidtemplate;
else {
/* in words (fixed, full page). */
@@ -1433,7 +1448,8 @@ static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port)
port * dd->ipath_rcvtidcnt *
sizeof(*tidbase));
for (i = 0; i < dd->ipath_rcvtidcnt; i++)
- ipath_ht_put_tid(dd, &tidbase[i], 1, dd->ipath_tidinvalid);
+ ipath_ht_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
+ dd->ipath_tidinvalid);
tidbase = (u64 __iomem *) ((char __iomem *)(dd->ipath_kregbase) +
dd->ipath_rcvegrbase +
@@ -1441,7 +1457,8 @@ static void ipath_ht_clear_tids(struct ipath_devdata *dd, unsigned port)
sizeof(*tidbase));
for (i = 0; i < dd->ipath_rcvegrcnt; i++)
- ipath_ht_put_tid(dd, &tidbase[i], 0, dd->ipath_tidinvalid);
+ ipath_ht_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER,
+ dd->ipath_tidinvalid);
}
/**
@@ -1528,11 +1545,6 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
writel(16, piobuf);
piobuf += pioincr;
}
- /*
- * self-clearing
- */
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- INFINIPATH_S_ABORT);
ipath_get_eeprom_info(dd);
if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' &&
@@ -1543,8 +1555,10 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
* with 128, rather than 112.
*/
dd->ipath_flags |= IPATH_GPIO_INTR;
- dd->ipath_flags &= ~IPATH_POLL_RX_INTR;
- }
+ } else
+ ipath_dev_err(dd, "Unsupported InfiniPath serial "
+ "number %.16s!\n", dd->ipath_serial);
+
return 0;
}
@@ -1561,7 +1575,6 @@ static int ipath_ht_txe_recover(struct ipath_devdata *dd)
}
dev_info(&dd->pcidev->dev,
"Recovering from TXE PIO parity error\n");
- ipath_disarm_senderrbufs(dd, 1);
return 1;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
index 4e2e3dfeb2c..9868ccda5f2 100644
--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -296,13 +296,6 @@ static const struct ipath_cregs ipath_pe_cregs = {
#define IPATH_GPIO_SCL (1ULL << \
(_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
-/*
- * Rev2 silicon allows suppressing check for ArmLaunch errors.
- * this can speed up short packet sends on systems that do
- * not guaranteee write-order.
- */
-#define INFINIPATH_XGXS_SUPPRESS_ARMLAUNCH_ERR (1ULL<<63)
-
/* 6120 specific hardware errors... */
static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
@@ -347,6 +340,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
u32 bits, ctrl;
int isfatal = 0;
char bitsmsg[64];
+ int log_idx;
hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
if (!hwerrs) {
@@ -374,6 +368,11 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
hwerrs &= dd->ipath_hwerrmask;
+ /* We log some errors to EEPROM, check if we have any of those. */
+ for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx)
+ if (hwerrs & dd->ipath_eep_st_masks[log_idx].hwerrs_to_log)
+ ipath_inc_eeprom_err(dd, log_idx, 1);
+
/*
* make sure we get this much out, unless told to be quiet,
* or it's occurred within the last 5 seconds
@@ -431,10 +430,12 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
dd->ipath_flags &= ~IPATH_INITTED;
} else {
- ipath_dbg("Clearing freezemode on ignored hardware "
- "error\n");
- ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
- dd->ipath_control);
+ static u32 freeze_cnt;
+
+ freeze_cnt++;
+ ipath_dbg("Clearing freezemode on ignored or recovered "
+ "hardware error (%u)\n", freeze_cnt);
+ ipath_clear_freeze(dd);
}
}
@@ -680,17 +681,6 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
val |= dd->ipath_rx_pol_inv <<
INFINIPATH_XGXS_RX_POL_SHIFT;
}
- if (dd->ipath_minrev >= 2) {
- /* Rev 2. can tolerate multiple writes to PBC, and
- * allowing them can provide lower latency on some
- * CPUs, but this feature is off by default, only
- * turned on by setting D63 of XGXSconfig reg.
- * May want to make this conditional more
- * fine-grained in future. This is not exactly
- * related to XGXS, but where the bit ended up.
- */
- val |= INFINIPATH_XGXS_SUPPRESS_ARMLAUNCH_ERR;
- }
if (val != prev_val)
ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
@@ -791,12 +781,24 @@ static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
u64 ltst)
{
u64 extctl;
+ unsigned long flags = 0;
/* the diags use the LED to indicate diag info, so we leave
* the external LED alone when the diags are running */
if (ipath_diag_inuse)
return;
+ /* Allow override of LED display for, e.g. Locating system in rack */
+ if (dd->ipath_led_override) {
+ ltst = (dd->ipath_led_override & IPATH_LED_PHYS)
+ ? INFINIPATH_IBCS_LT_STATE_LINKUP
+ : INFINIPATH_IBCS_LT_STATE_DISABLED;
+ lst = (dd->ipath_led_override & IPATH_LED_LOG)
+ ? INFINIPATH_IBCS_L_STATE_ACTIVE
+ : INFINIPATH_IBCS_L_STATE_DOWN;
+ }
+
+ spin_lock_irqsave(&dd->ipath_gpio_lock, flags);
extctl = dd->ipath_extctrl & ~(INFINIPATH_EXTC_LED1PRIPORT_ON |
INFINIPATH_EXTC_LED2PRIPORT_ON);
@@ -806,6 +808,7 @@ static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst,
extctl |= INFINIPATH_EXTC_LED1PRIPORT_ON;
dd->ipath_extctrl = extctl;
ipath_write_kreg(dd, dd->ipath_kregs->kr_extctrl, extctl);
+ spin_unlock_irqrestore(&dd->ipath_gpio_lock, flags);
}
/**
@@ -955,6 +958,27 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
+
+ /*
+ * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
+ * 2 is Some Misc, 3 is reserved for future.
+ */
+ dd->ipath_eep_st_masks[0].hwerrs_to_log =
+ INFINIPATH_HWE_TXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT;
+
+ /* Ignore errors in PIO/PBC on systems with unordered write-combining */
+ if (ipath_unordered_wc())
+ dd->ipath_eep_st_masks[0].hwerrs_to_log &= ~TXE_PIO_PARITY;
+
+ dd->ipath_eep_st_masks[1].hwerrs_to_log =
+ INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
+
+ dd->ipath_eep_st_masks[2].errs_to_log =
+ INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
+
+
}
/* setup the MSI stuff again after a reset. I'd like to just call
@@ -1082,7 +1106,7 @@ bail:
* ipath_pe_put_tid - write a TID in chip
* @dd: the infinipath device
* @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
* @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
*
* This exists as a separate routine to allow for special locking etc.
@@ -1108,7 +1132,7 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
"BUG: Physical page address 0x%lx "
"has bits set in 31-29\n", pa);
- if (type == 0)
+ if (type == RCVHQ_RCV_TYPE_EAGER)
pa |= dd->ipath_tidtemplate;
else /* for now, always full 4KB page */
pa |= 2 << 29;
@@ -1132,7 +1156,7 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr,
* ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher
* @dd: the infinipath device
* @tidptr: pointer to the expected TID (in chip) to udpate
- * @tidtype: 0 for eager, 1 for expected
+ * @tidtype: RCVHQ_RCV_TYPE_EAGER (1) for eager, RCVHQ_RCV_TYPE_EXPECTED (0) for expected
* @pa: physical address of in memory buffer; ipath_tidinvalid if freeing
*
* This exists as a separate routine to allow for selection of the
@@ -1157,7 +1181,7 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr,
"BUG: Physical page address 0x%lx "
"has bits set in 31-29\n", pa);
- if (type == 0)
+ if (type == RCVHQ_RCV_TYPE_EAGER)
pa |= dd->ipath_tidtemplate;
else /* for now, always full 4KB page */
pa |= 2 << 29;
@@ -1196,7 +1220,8 @@ static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port)
port * dd->ipath_rcvtidcnt * sizeof(*tidbase));
for (i = 0; i < dd->ipath_rcvtidcnt; i++)
- ipath_pe_put_tid(dd, &tidbase[i], 0, tidinv);
+ ipath_pe_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EXPECTED,
+ tidinv);
tidbase = (u64 __iomem *)
((char __iomem *)(dd->ipath_kregbase) +
@@ -1204,7 +1229,8 @@ static void ipath_pe_clear_tids(struct ipath_devdata *dd, unsigned port)
port * dd->ipath_rcvegrcnt * sizeof(*tidbase));
for (i = 0; i < dd->ipath_rcvegrcnt; i++)
- ipath_pe_put_tid(dd, &tidbase[i], 1, tidinv);
+ ipath_pe_put_tid(dd, &tidbase[i], RCVHQ_RCV_TYPE_EAGER,
+ tidinv);
}
/**
@@ -1311,13 +1337,6 @@ static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase)
dd = pd->port_dd;
- if (dd != NULL && dd->ipath_minrev >= 2) {
- ipath_cdbg(PROC, "IBA6120 Rev2, allow multiple PBC write\n");
- kinfo->spi_runtime_flags |= IPATH_RUNTIME_PBC_REWRITE;
- ipath_cdbg(PROC, "IBA6120 Rev2, allow loose DMA alignment\n");
- kinfo->spi_runtime_flags |= IPATH_RUNTIME_LOOSE_DMA_ALIGN;
- }
-
done:
kinfo->spi_runtime_flags |= IPATH_RUNTIME_PCIE;
return 0;
@@ -1354,7 +1373,6 @@ static int ipath_pe_txe_recover(struct ipath_devdata *dd)
dev_info(&dd->pcidev->dev,
"Recovering from TXE PIO parity error\n");
}
- ipath_disarm_senderrbufs(dd, 1);
return 1;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 7045ba68949..49951d58380 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -133,7 +133,8 @@ static int create_port0_egr(struct ipath_devdata *dd)
dd->ipath_ibmaxlen, PCI_DMA_FROMDEVICE);
dd->ipath_f_put_tid(dd, e + (u64 __iomem *)
((char __iomem *) dd->ipath_kregbase +
- dd->ipath_rcvegrbase), 0,
+ dd->ipath_rcvegrbase),
+ RCVHQ_RCV_TYPE_EAGER,
dd->ipath_port0_skbinfo[e].phys);
}
@@ -310,7 +311,12 @@ static int init_chip_first(struct ipath_devdata *dd,
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiosize);
dd->ipath_piosize2k = val & ~0U;
dd->ipath_piosize4k = val >> 32;
- dd->ipath_ibmtu = 4096; /* default to largest legal MTU */
+ /*
+ * Note: the chips support a maximum MTU of 4096, but the driver
+ * hasn't implemented this feature yet, so set the initial value
+ * to 2048.
+ */
+ dd->ipath_ibmtu = 2048;
val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_sendpiobufcnt);
dd->ipath_piobcnt2k = val & ~0U;
dd->ipath_piobcnt4k = val >> 32;
@@ -340,6 +346,10 @@ static int init_chip_first(struct ipath_devdata *dd,
spin_lock_init(&dd->ipath_tid_lock);
+ spin_lock_init(&dd->ipath_gpio_lock);
+ spin_lock_init(&dd->ipath_eep_st_lock);
+ sema_init(&dd->ipath_eep_sem, 1);
+
done:
*pdp = pd;
return ret;
@@ -646,7 +656,7 @@ static int init_housekeeping(struct ipath_devdata *dd,
ret = dd->ipath_f_get_boardname(dd, boardn, sizeof boardn);
snprintf(dd->ipath_boardversion, sizeof(dd->ipath_boardversion),
- "Driver %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
+ "ChipABI %u.%u, %s, InfiniPath%u %u.%u, PCI %u, "
"SW Compat %u\n",
IPATH_CHIP_VERS_MAJ, IPATH_CHIP_VERS_MIN, boardn,
(unsigned)(dd->ipath_revision >> INFINIPATH_R_ARCH_SHIFT) &
@@ -727,7 +737,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
uports = dd->ipath_cfgports ? dd->ipath_cfgports - 1 : 0;
if (ipath_kpiobufs == 0) {
/* not set by user (this is default) */
- if (piobufs >= (uports * IPATH_MIN_USER_PORT_BUFCNT) + 32)
+ if (piobufs > 144)
kpiobufs = 32;
else
kpiobufs = 16;
@@ -767,6 +777,12 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
piobufs, dd->ipath_pbufsport, uports);
dd->ipath_f_early_init(dd);
+ /*
+ * cancel any possible active sends from early driver load.
+ * Follows early_init because some chips have to initialize
+ * PIO buffers in early_init to avoid false parity errors.
+ */
+ ipath_cancel_sends(dd);
/* early_init sets rcvhdrentsize and rcvhdrsize, so this must be
* done after early_init */
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index a90d3b5699c..47aa43428fb 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -93,7 +93,8 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) {
int i;
- if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG)) {
+ if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG) &&
+ dd->ipath_lastcancel > jiffies) {
__IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG,
"SendbufErrs %lx %lx", sbuf[0],
sbuf[1]);
@@ -108,7 +109,8 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
ipath_clrpiobuf(dd, i);
ipath_disarm_piobufs(dd, i, 1);
}
- dd->ipath_lastcancel = jiffies+3; /* no armlaunch for a bit */
+ /* ignore armlaunch errs for a bit */
+ dd->ipath_lastcancel = jiffies+3;
}
}
@@ -131,6 +133,17 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite)
INFINIPATH_E_INVALIDADDR)
/*
+ * this is similar to E_SUM_ERRS, but can't ignore armlaunch, don't ignore
+ * errors not related to freeze and cancelling buffers. Can't ignore
+ * armlaunch because could get more while still cleaning up, and need
+ * to cancel those as they happen.
+ */
+#define E_SPKT_ERRS_IGNORE \
+ (INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_SDROPPEDSMPPKT | \
+ INFINIPATH_E_SMAXPKTLEN | INFINIPATH_E_SMINPKTLEN | \
+ INFINIPATH_E_SPKTLEN)
+
+/*
* these are errors that can occur when the link changes state while
* a packet is being sent or received. This doesn't cover things
* like EBP or VCRC that can be the result of a sending having the
@@ -290,12 +303,7 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
* Flush all queued sends when link went to DOWN or INIT,
* to be sure that they don't block SMA and other MAD packets
*/
- ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- INFINIPATH_S_ABORT);
- ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf,
- (unsigned)(dd->ipath_piobcnt2k +
- dd->ipath_piobcnt4k) -
- dd->ipath_lastport_piobuf);
+ ipath_cancel_sends(dd);
}
else if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM ||
lstate == IPATH_IBSTATE_ACTIVE) {
@@ -505,6 +513,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
int i, iserr = 0;
int chkerrpkts = 0, noprint = 0;
unsigned supp_msgs;
+ int log_idx;
supp_msgs = handle_frequent_errors(dd, errs, msg, &noprint);
@@ -518,6 +527,13 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
if (errs & INFINIPATH_E_HARDWARE) {
/* reuse same msg buf */
dd->ipath_f_handle_hwerrors(dd, msg, sizeof msg);
+ } else {
+ u64 mask;
+ for (log_idx = 0; log_idx < IPATH_EEP_LOG_CNT; ++log_idx) {
+ mask = dd->ipath_eep_st_masks[log_idx].errs_to_log;
+ if (errs & mask)
+ ipath_inc_eeprom_err(dd, log_idx, 1);
+ }
}
if (!noprint && (errs & ~dd->ipath_e_bitsextant))
@@ -675,6 +691,17 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
chkerrpkts = 1;
dd->ipath_lastrcvhdrqtails[i] = tl;
pd->port_hdrqfull++;
+ if (test_bit(IPATH_PORT_WAITING_OVERFLOW,
+ &pd->port_flag)) {
+ clear_bit(
+ IPATH_PORT_WAITING_OVERFLOW,
+ &pd->port_flag);
+ set_bit(
+ IPATH_PORT_WAITING_OVERFLOW,
+ &pd->int_flag);
+ wake_up_interruptible(
+ &pd->port_wait);
+ }
}
}
}
@@ -744,6 +771,72 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
return chkerrpkts;
}
+
+/*
+ * try to cleanup as much as possible for anything that might have gone
+ * wrong while in freeze mode, such as pio buffers being written by user
+ * processes (causing armlaunch), send errors due to going into freeze mode,
+ * etc., and try to avoid causing extra interrupts while doing so.
+ * Forcibly update the in-memory pioavail register copies after cleanup
+ * because the chip won't do it for anything changing while in freeze mode
+ * (we don't want to wait for the next pio buffer state change).
+ * Make sure that we don't lose any important interrupts by using the chip
+ * feature that says that writing 0 to a bit in *clear that is set in
+ * *status will cause an interrupt to be generated again (if allowed by
+ * the *mask value).
+ */
+void ipath_clear_freeze(struct ipath_devdata *dd)
+{
+ int i, im;
+ __le64 val;
+
+ /* disable error interrupts, to avoid confusion */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
+
+ /*
+ * clear all sends, because they have may been
+ * completed by usercode while in freeze mode, and
+ * therefore would not be sent, and eventually
+ * might cause the process to run out of bufs
+ */
+ ipath_cancel_sends(dd);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+ dd->ipath_control);
+
+ /* ensure pio avail updates continue */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl & ~IPATH_S_PIOBUFAVAILUPD);
+ ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ dd->ipath_sendctrl);
+
+ /*
+ * We just enabled pioavailupdate, so dma copy is almost certainly
+ * not yet right, so read the registers directly. Similar to init
+ */
+ for (i = 0; i < dd->ipath_pioavregs; i++) {
+ /* deal with 6110 chip bug */
+ im = i > 3 ? ((i&1) ? i-1 : i+1) : i;
+ val = ipath_read_kreg64(dd, 0x1000+(im*sizeof(u64)));
+ dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
+ = le64_to_cpu(val);
+ }
+
+ /*
+ * force new interrupt if any hwerr, error or interrupt bits are
+ * still set, and clear "safe" send packet errors related to freeze
+ * and cancelling sends. Re-enable error interrupts before possible
+ * force of re-interrupt on pending interrupts.
+ */
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
+ E_SPKT_ERRS_IGNORE);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
+ ~dd->ipath_maskederrs);
+ ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
+}
+
+
/* this is separate to allow for better optimization of ipath_intr() */
static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
@@ -872,14 +965,25 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
dd->ipath_i_rcvurg_mask);
for (i = 1; i < dd->ipath_cfgports; i++) {
struct ipath_portdata *pd = dd->ipath_pd[i];
- if (portr & (1 << i) && pd && pd->port_cnt &&
- test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) {
- clear_bit(IPATH_PORT_WAITING_RCV,
- &pd->port_flag);
- clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
- &dd->ipath_rcvctrl);
- wake_up_interruptible(&pd->port_wait);
- rcvdint = 1;
+ if (portr & (1 << i) && pd && pd->port_cnt) {
+ if (test_bit(IPATH_PORT_WAITING_RCV,
+ &pd->port_flag)) {
+ clear_bit(IPATH_PORT_WAITING_RCV,
+ &pd->port_flag);
+ set_bit(IPATH_PORT_WAITING_RCV,
+ &pd->int_flag);
+ clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
+ &dd->ipath_rcvctrl);
+ wake_up_interruptible(&pd->port_wait);
+ rcvdint = 1;
+ } else if (test_bit(IPATH_PORT_WAITING_URG,
+ &pd->port_flag)) {
+ clear_bit(IPATH_PORT_WAITING_URG,
+ &pd->port_flag);
+ set_bit(IPATH_PORT_WAITING_URG,
+ &pd->int_flag);
+ wake_up_interruptible(&pd->port_wait);
+ }
}
}
if (rcvdint) {
@@ -905,6 +1009,9 @@ irqreturn_t ipath_intr(int irq, void *data)
ipath_stats.sps_ints++;
+ if (dd->ipath_int_counter != (u32) -1)
+ dd->ipath_int_counter++;
+
if (!(dd->ipath_flags & IPATH_PRESENT)) {
/*
* This return value is not great, but we do not want the
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 12194f3dd8c..3105005fc9d 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -1,7 +1,7 @@
#ifndef _IPATH_KERNEL_H
#define _IPATH_KERNEL_H
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -57,6 +57,24 @@
extern struct infinipath_stats ipath_stats;
#define IPATH_CHIP_SWVERSION IPATH_CHIP_VERS_MAJ
+/*
+ * First-cut critierion for "device is active" is
+ * two thousand dwords combined Tx, Rx traffic per
+ * 5-second interval. SMA packets are 64 dwords,
+ * and occur "a few per second", presumably each way.
+ */
+#define IPATH_TRAFFIC_ACTIVE_THRESHOLD (2000)
+/*
+ * Struct used to indicate which errors are logged in each of the
+ * error-counters that are logged to EEPROM. A counter is incremented
+ * _once_ (saturating at 255) for each event with any bits set in
+ * the error or hwerror register masks below.
+ */
+#define IPATH_EEP_LOG_CNT (4)
+struct ipath_eep_log_mask {
+ u64 errs_to_log;
+ u64 hwerrs_to_log;
+};
struct ipath_portdata {
void **port_rcvegrbuf;
@@ -109,6 +127,8 @@ struct ipath_portdata {
u32 port_tidcursor;
/* next expected TID to check */
unsigned long port_flag;
+ /* what happened */
+ unsigned long int_flag;
/* WAIT_RCV that timed out, no interrupt */
u32 port_rcvwait_to;
/* WAIT_PIO that timed out, no interrupt */
@@ -137,6 +157,8 @@ struct ipath_portdata {
u32 userversion;
/* Bitmask of active slaves */
u32 active_slaves;
+ /* Type of packets or conditions we want to poll for */
+ u16 poll_type;
};
struct sk_buff;
@@ -275,6 +297,8 @@ struct ipath_devdata {
u32 ipath_lastport_piobuf;
/* is a stats timer active */
u32 ipath_stats_timer_active;
+ /* number of interrupts for this device -- saturates... */
+ u32 ipath_int_counter;
/* dwords sent read from counter */
u32 ipath_lastsword;
/* dwords received read from counter */
@@ -369,9 +393,6 @@ struct ipath_devdata {
struct class_device *diag_class_dev;
/* timer used to prevent stats overflow, error throttling, etc. */
struct timer_list ipath_stats_timer;
- /* check for stale messages in rcv queue */
- /* only allow one intr at a time. */
- unsigned long ipath_rcv_pending;
void *ipath_dummy_hdrq; /* used after port close */
dma_addr_t ipath_dummy_hdrq_phys;
@@ -399,6 +420,8 @@ struct ipath_devdata {
u64 ipath_gpio_out;
/* shadow the gpio mask register */
u64 ipath_gpio_mask;
+ /* shadow the gpio output enable, etc... */
+ u64 ipath_extctrl;
/* kr_revision shadow */
u64 ipath_revision;
/*
@@ -473,8 +496,6 @@ struct ipath_devdata {
u32 ipath_cregbase;
/* shadow the control register contents */
u32 ipath_control;
- /* shadow the gpio output contents */
- u32 ipath_extctrl;
/* PCI revision register (HTC rev on FPGA) */
u32 ipath_pcirev;
@@ -552,6 +573,9 @@ struct ipath_devdata {
u32 ipath_overrun_thresh_errs;
u32 ipath_lli_errs;
+ /* status check work */
+ struct delayed_work status_work;
+
/*
* Not all devices managed by a driver instance are the same
* type, so these fields must be per-device.
@@ -575,6 +599,37 @@ struct ipath_devdata {
u16 ipath_gpio_scl_num;
u64 ipath_gpio_sda;
u64 ipath_gpio_scl;
+
+ /* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
+ spinlock_t ipath_gpio_lock;
+
+ /* used to override LED behavior */
+ u8 ipath_led_override; /* Substituted for normal value, if non-zero */
+ u16 ipath_led_override_timeoff; /* delta to next timer event */
+ u8 ipath_led_override_vals[2]; /* Alternates per blink-frame */
+ u8 ipath_led_override_phase; /* Just counts, LSB picks from vals[] */
+ atomic_t ipath_led_override_timer_active;
+ /* Used to flash LEDs in override mode */
+ struct timer_list ipath_led_override_timer;
+
+ /* Support (including locks) for EEPROM logging of errors and time */
+ /* control access to actual counters, timer */
+ spinlock_t ipath_eep_st_lock;
+ /* control high-level access to EEPROM */
+ struct semaphore ipath_eep_sem;
+ /* Below inc'd by ipath_snap_cntrs(), locked by ipath_eep_st_lock */
+ uint64_t ipath_traffic_wds;
+ /* active time is kept in seconds, but logged in hours */
+ atomic_t ipath_active_time;
+ /* Below are nominal shadow of EEPROM, new since last EEPROM update */
+ uint8_t ipath_eep_st_errs[IPATH_EEP_LOG_CNT];
+ uint8_t ipath_eep_st_new_errs[IPATH_EEP_LOG_CNT];
+ uint16_t ipath_eep_hrs;
+ /*
+ * masks for which bits of errs, hwerrs that cause
+ * each of the counters to increment.
+ */
+ struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT];
};
/* Private data for file operations */
@@ -592,6 +647,7 @@ int ipath_enable_wc(struct ipath_devdata *dd);
void ipath_disable_wc(struct ipath_devdata *dd);
int ipath_count_units(int *npresentp, int *nupp, u32 *maxportsp);
void ipath_shutdown_device(struct ipath_devdata *);
+void ipath_clear_freeze(struct ipath_devdata *);
struct file_operations;
int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
@@ -627,6 +683,7 @@ int ipath_unordered_wc(void);
void ipath_disarm_piobufs(struct ipath_devdata *, unsigned first,
unsigned cnt);
+void ipath_cancel_sends(struct ipath_devdata *);
int ipath_create_rcvhdrq(struct ipath_devdata *, struct ipath_portdata *);
void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *);
@@ -685,7 +742,6 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
* are 64bit */
#define IPATH_32BITCOUNTERS 0x20000
/* can miss port0 rx interrupts */
-#define IPATH_POLL_RX_INTR 0x40000
#define IPATH_DISABLED 0x80000 /* administratively disabled */
/* Use GPIO interrupts for new counters */
#define IPATH_GPIO_ERRINTRS 0x100000
@@ -704,6 +760,10 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
#define IPATH_PORT_WAITING_PIO 3
/* master has not finished initializing */
#define IPATH_PORT_MASTER_UNINIT 4
+ /* waiting for an urgent packet to arrive */
+#define IPATH_PORT_WAITING_URG 5
+ /* waiting for a header overflow */
+#define IPATH_PORT_WAITING_OVERFLOW 6
/* free up any allocated data at closes */
void ipath_free_data(struct ipath_portdata *dd);
@@ -713,10 +773,21 @@ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
void ipath_init_iba6120_funcs(struct ipath_devdata *);
void ipath_init_iba6110_funcs(struct ipath_devdata *);
void ipath_get_eeprom_info(struct ipath_devdata *);
+int ipath_update_eeprom_log(struct ipath_devdata *dd);
+void ipath_inc_eeprom_err(struct ipath_devdata *dd, u32 eidx, u32 incr);
u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg);
void ipath_disarm_senderrbufs(struct ipath_devdata *, int);
/*
+ * Set LED override, only the two LSBs have "public" meaning, but
+ * any non-zero value substitutes them for the Link and LinkTrain
+ * LED states.
+ */
+#define IPATH_LED_PHYS 1 /* Physical (linktraining) GREEN LED */
+#define IPATH_LED_LOG 2 /* Logical (link) YELLOW LED */
+void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
+
+/*
* number of words used for protocol header if not set by ipath_userinit();
*/
#define IPATH_DFLT_RCVHDRSIZE 9
diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
index dd487c100f5..85a4aefc6c0 100644
--- a/drivers/infiniband/hw/ipath/ipath_keys.c
+++ b/drivers/infiniband/hw/ipath/ipath_keys.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c
index 05a1d2b01d9..82616b779e2 100644
--- a/drivers/infiniband/hw/ipath/ipath_layer.c
+++ b/drivers/infiniband/hw/ipath/ipath_layer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_layer.h b/drivers/infiniband/hw/ipath/ipath_layer.h
index 3854a4eae68..415709c4d85 100644
--- a/drivers/infiniband/hw/ipath/ipath_layer.h
+++ b/drivers/infiniband/hw/ipath/ipath_layer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index 25908b02fbe..d61c0304454 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -103,7 +103,7 @@ static int recv_subn_get_nodeinfo(struct ib_smp *smp,
/* This is already in network order */
nip->sys_guid = to_idev(ibdev)->sys_image_guid;
nip->node_guid = dd->ipath_guid;
- nip->port_guid = nip->sys_guid;
+ nip->port_guid = dd->ipath_guid;
nip->partition_cap = cpu_to_be16(ipath_get_npkeys(dd));
nip->device_id = cpu_to_be16(dd->ipath_deviceid);
majrev = dd->ipath_majrev;
@@ -292,7 +292,12 @@ static int recv_subn_get_portinfo(struct ib_smp *smp,
/* pip->vl_arb_high_cap; // only one VL */
/* pip->vl_arb_low_cap; // only one VL */
/* InitTypeReply = 0 */
- pip->inittypereply_mtucap = IB_MTU_4096;
+ /*
+ * Note: the chips support a maximum MTU of 4096, but the driver
+ * hasn't implemented this feature yet, so set the maximum value
+ * to 2048.
+ */
+ pip->inittypereply_mtucap = IB_MTU_2048;
// HCAs ignore VLStallCount and HOQLife
/* pip->vlstallcnt_hoqlife; */
pip->operationalvl_pei_peo_fpi_fpo = 0x10; /* OVLs = 1 */
diff --git a/drivers/infiniband/hw/ipath/ipath_mmap.c b/drivers/infiniband/hw/ipath/ipath_mmap.c
index 937bc3396b5..fa830e22002 100644
--- a/drivers/infiniband/hw/ipath/ipath_mmap.c
+++ b/drivers/infiniband/hw/ipath/ipath_mmap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c
index bdeef8d4f27..e442470a237 100644
--- a/drivers/infiniband/hw/ipath/ipath_mr.c
+++ b/drivers/infiniband/hw/ipath/ipath_mr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
index bfef08ecd34..1324b35ff1f 100644
--- a/drivers/infiniband/hw/ipath/ipath_qp.c
+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -336,7 +336,7 @@ static void ipath_reset_qp(struct ipath_qp *qp)
qp->qkey = 0;
qp->qp_access_flags = 0;
qp->s_busy = 0;
- qp->s_flags &= ~IPATH_S_SIGNAL_REQ_WR;
+ qp->s_flags &= IPATH_S_SIGNAL_REQ_WR;
qp->s_hdrwords = 0;
qp->s_psn = 0;
qp->r_psn = 0;
@@ -507,16 +507,13 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
attr->port_num > ibqp->device->phys_port_cnt)
goto inval;
+ /*
+ * Note: the chips support a maximum MTU of 4096, but the driver
+ * hasn't implemented this feature yet, so don't allow Path MTU
+ * values greater than 2048.
+ */
if (attr_mask & IB_QP_PATH_MTU)
- if (attr->path_mtu > IB_MTU_4096)
- goto inval;
-
- if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
- if (attr->max_dest_rd_atomic > 1)
- goto inval;
-
- if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC)
- if (attr->max_rd_atomic > 1)
+ if (attr->path_mtu > IB_MTU_2048)
goto inval;
if (attr_mask & IB_QP_PATH_MIG_STATE)
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
index 1915771fd03..46744ea2bab 100644
--- a/drivers/infiniband/hw/ipath/ipath_rc.c
+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -125,8 +125,10 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
if (len > pmtu) {
len = pmtu;
qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
- } else
+ } else {
qp->s_ack_state = OP(RDMA_READ_RESPONSE_ONLY);
+ e->sent = 1;
+ }
ohdr->u.aeth = ipath_compute_aeth(qp);
hwords++;
qp->s_ack_rdma_psn = e->psn;
@@ -143,6 +145,7 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
cpu_to_be32(e->atomic_data);
hwords += sizeof(ohdr->u.at) / sizeof(u32);
bth2 = e->psn;
+ e->sent = 1;
}
bth0 = qp->s_ack_state << 24;
break;
@@ -158,6 +161,7 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
ohdr->u.aeth = ipath_compute_aeth(qp);
hwords++;
qp->s_ack_state = OP(RDMA_READ_RESPONSE_LAST);
+ qp->s_ack_queue[qp->s_tail_ack_queue].sent = 1;
}
bth0 = qp->s_ack_state << 24;
bth2 = qp->s_ack_rdma_psn++ & IPATH_PSN_MASK;
@@ -188,7 +192,7 @@ static int ipath_make_rc_ack(struct ipath_qp *qp,
}
qp->s_hdrwords = hwords;
qp->s_cur_size = len;
- *bth0p = bth0;
+ *bth0p = bth0 | (1 << 22); /* Set M bit */
*bth2p = bth2;
return 1;
@@ -240,7 +244,7 @@ int ipath_make_rc_req(struct ipath_qp *qp,
/* header size in 32-bit words LRH+BTH = (8+12)/4. */
hwords = 5;
- bth0 = 0;
+ bth0 = 1 << 22; /* Set M bit */
/* Send a request. */
wqe = get_swqe_ptr(qp, qp->s_cur);
@@ -604,7 +608,7 @@ static void send_rc_ack(struct ipath_qp *qp)
}
/* read pkey_index w/o lock (its atomic) */
bth0 = ipath_get_pkey(dev->dd, qp->s_pkey_index) |
- OP(ACKNOWLEDGE) << 24;
+ (OP(ACKNOWLEDGE) << 24) | (1 << 22);
if (qp->r_nak_state)
ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) |
(qp->r_nak_state <<
@@ -806,13 +810,15 @@ static inline void update_last_psn(struct ipath_qp *qp, u32 psn)
* Called at interrupt level with the QP s_lock held and interrupts disabled.
* Returns 1 if OK, 0 if current operation should be aborted (NAK).
*/
-static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
+static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode,
+ u64 val)
{
struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
struct ib_wc wc;
struct ipath_swqe *wqe;
int ret = 0;
u32 ack_psn;
+ int diff;
/*
* Remove the QP from the timeout queue (or RNR timeout queue).
@@ -840,7 +846,19 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
* The MSN might be for a later WQE than the PSN indicates so
* only complete WQEs that the PSN finishes.
*/
- while (ipath_cmp24(ack_psn, wqe->lpsn) >= 0) {
+ while ((diff = ipath_cmp24(ack_psn, wqe->lpsn)) >= 0) {
+ /*
+ * RDMA_READ_RESPONSE_ONLY is a special case since
+ * we want to generate completion events for everything
+ * before the RDMA read, copy the data, then generate
+ * the completion for the read.
+ */
+ if (wqe->wr.opcode == IB_WR_RDMA_READ &&
+ opcode == OP(RDMA_READ_RESPONSE_ONLY) &&
+ diff == 0) {
+ ret = 1;
+ goto bail;
+ }
/*
* If this request is a RDMA read or atomic, and the ACK is
* for a later operation, this ACK NAKs the RDMA read or
@@ -851,12 +869,10 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
* is sent but before the response is received.
*/
if ((wqe->wr.opcode == IB_WR_RDMA_READ &&
- (opcode != OP(RDMA_READ_RESPONSE_LAST) ||
- ipath_cmp24(ack_psn, wqe->lpsn) != 0)) ||
+ (opcode != OP(RDMA_READ_RESPONSE_LAST) || diff != 0)) ||
((wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD) &&
- (opcode != OP(ATOMIC_ACKNOWLEDGE) ||
- ipath_cmp24(wqe->psn, psn) != 0))) {
+ (opcode != OP(ATOMIC_ACKNOWLEDGE) || diff != 0))) {
/*
* The last valid PSN seen is the previous
* request's.
@@ -870,6 +886,9 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
*/
goto bail;
}
+ if (wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
+ wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
+ *(u64 *) wqe->sg_list[0].vaddr = val;
if (qp->s_num_rd_atomic &&
(wqe->wr.opcode == IB_WR_RDMA_READ ||
wqe->wr.opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
@@ -1079,6 +1098,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
int diff;
u32 pad;
u32 aeth;
+ u64 val;
spin_lock_irqsave(&qp->s_lock, flags);
@@ -1118,8 +1138,6 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
data += sizeof(__be32);
}
if (opcode == OP(ATOMIC_ACKNOWLEDGE)) {
- u64 val;
-
if (!header_in_data) {
__be32 *p = ohdr->u.at.atomic_ack_eth;
@@ -1127,12 +1145,13 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
be32_to_cpu(p[1]);
} else
val = be64_to_cpu(((__be64 *) data)[0]);
- *(u64 *) wqe->sg_list[0].vaddr = val;
- }
- if (!do_rc_ack(qp, aeth, psn, opcode) ||
+ } else
+ val = 0;
+ if (!do_rc_ack(qp, aeth, psn, opcode, val) ||
opcode != OP(RDMA_READ_RESPONSE_FIRST))
goto ack_done;
hdrsize += 4;
+ wqe = get_swqe_ptr(qp, qp->s_last);
if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
goto ack_op_err;
/*
@@ -1176,13 +1195,12 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
goto bail;
case OP(RDMA_READ_RESPONSE_ONLY):
- if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) {
- dev->n_rdma_seq++;
- ipath_restart_rc(qp, qp->s_last_psn + 1, &wc);
+ if (!header_in_data)
+ aeth = be32_to_cpu(ohdr->u.aeth);
+ else
+ aeth = be32_to_cpu(((__be32 *) data)[0]);
+ if (!do_rc_ack(qp, aeth, psn, opcode, 0))
goto ack_done;
- }
- if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ))
- goto ack_op_err;
/* Get the number of bytes the message was padded by. */
pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
/*
@@ -1197,6 +1215,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
* have to be careful to copy the data to the right
* location.
*/
+ wqe = get_swqe_ptr(qp, qp->s_last);
qp->s_rdma_read_len = restart_sge(&qp->s_rdma_read_sge,
wqe, psn, pmtu);
goto read_last;
@@ -1230,7 +1249,8 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev,
data += sizeof(__be32);
}
ipath_copy_sge(&qp->s_rdma_read_sge, data, tlen);
- (void) do_rc_ack(qp, aeth, psn, OP(RDMA_READ_RESPONSE_LAST));
+ (void) do_rc_ack(qp, aeth, psn,
+ OP(RDMA_READ_RESPONSE_LAST), 0);
goto ack_done;
}
@@ -1344,8 +1364,11 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev,
e = NULL;
break;
}
- if (ipath_cmp24(psn, e->psn) >= 0)
+ if (ipath_cmp24(psn, e->psn) >= 0) {
+ if (prev == qp->s_tail_ack_queue)
+ old_req = 0;
break;
+ }
}
switch (opcode) {
case OP(RDMA_READ_REQUEST): {
@@ -1460,6 +1483,22 @@ static void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err)
spin_unlock_irqrestore(&qp->s_lock, flags);
}
+static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n)
+{
+ unsigned long flags;
+ unsigned next;
+
+ next = n + 1;
+ if (next > IPATH_MAX_RDMA_ATOMIC)
+ next = 0;
+ spin_lock_irqsave(&qp->s_lock, flags);
+ if (n == qp->s_tail_ack_queue) {
+ qp->s_tail_ack_queue = next;
+ qp->s_ack_state = OP(ACKNOWLEDGE);
+ }
+ spin_unlock_irqrestore(&qp->s_lock, flags);
+}
+
/**
* ipath_rc_rcv - process an incoming RC packet
* @dev: the device this packet came in on
@@ -1672,6 +1711,9 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
case OP(RDMA_WRITE_FIRST):
case OP(RDMA_WRITE_ONLY):
case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_WRITE)))
+ goto nack_inv;
/* consume RWQE */
/* RETH comes after BTH */
if (!header_in_data)
@@ -1701,9 +1743,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
qp->r_sge.sge.length = 0;
qp->r_sge.sge.sge_length = 0;
}
- if (unlikely(!(qp->qp_access_flags &
- IB_ACCESS_REMOTE_WRITE)))
- goto nack_acc;
if (opcode == OP(RDMA_WRITE_FIRST))
goto send_middle;
else if (opcode == OP(RDMA_WRITE_ONLY))
@@ -1717,13 +1756,17 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
u32 len;
u8 next;
- if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ)))
- goto nack_acc;
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_READ)))
+ goto nack_inv;
next = qp->r_head_ack_queue + 1;
if (next > IPATH_MAX_RDMA_ATOMIC)
next = 0;
- if (unlikely(next == qp->s_tail_ack_queue))
- goto nack_inv;
+ if (unlikely(next == qp->s_tail_ack_queue)) {
+ if (!qp->s_ack_queue[next].sent)
+ goto nack_inv;
+ ipath_update_ack_queue(qp, next);
+ }
e = &qp->s_ack_queue[qp->r_head_ack_queue];
/* RETH comes after BTH */
if (!header_in_data)
@@ -1758,6 +1801,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
e->rdma_sge.sge.sge_length = 0;
}
e->opcode = opcode;
+ e->sent = 0;
e->psn = psn;
/*
* We need to increment the MSN here instead of when we
@@ -1789,12 +1833,15 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
if (unlikely(!(qp->qp_access_flags &
IB_ACCESS_REMOTE_ATOMIC)))
- goto nack_acc;
+ goto nack_inv;
next = qp->r_head_ack_queue + 1;
if (next > IPATH_MAX_RDMA_ATOMIC)
next = 0;
- if (unlikely(next == qp->s_tail_ack_queue))
- goto nack_inv;
+ if (unlikely(next == qp->s_tail_ack_queue)) {
+ if (!qp->s_ack_queue[next].sent)
+ goto nack_inv;
+ ipath_update_ack_queue(qp, next);
+ }
if (!header_in_data)
ateth = &ohdr->u.atomic_eth;
else
@@ -1819,6 +1866,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
be64_to_cpu(ateth->compare_data),
sdata);
e->opcode = opcode;
+ e->sent = 0;
e->psn = psn & IPATH_PSN_MASK;
qp->r_msn++;
qp->r_psn++;
diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
index c182bcd6209..708eba3165d 100644
--- a/drivers/infiniband/hw/ipath/ipath_registers.h
+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
index d9c2a9b15d8..85256747d8a 100644
--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -194,6 +194,8 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only)
ret = 0;
goto bail;
}
+ /* Make sure entry is read after head index is read. */
+ smp_rmb();
wqe = get_rwqe_ptr(rq, tail);
if (++tail >= rq->size)
tail = 0;
@@ -267,7 +269,7 @@ again:
spin_lock_irqsave(&sqp->s_lock, flags);
if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_SEND_OK) ||
- qp->s_rnr_timeout) {
+ sqp->s_rnr_timeout) {
spin_unlock_irqrestore(&sqp->s_lock, flags);
goto done;
}
@@ -319,12 +321,22 @@ again:
break;
case IB_WR_RDMA_WRITE_WITH_IMM:
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_WRITE))) {
+ wc.status = IB_WC_REM_INV_REQ_ERR;
+ goto err;
+ }
wc.wc_flags = IB_WC_WITH_IMM;
wc.imm_data = wqe->wr.imm_data;
if (!ipath_get_rwqe(qp, 1))
goto rnr_nak;
/* FALLTHROUGH */
case IB_WR_RDMA_WRITE:
+ if (unlikely(!(qp->qp_access_flags &
+ IB_ACCESS_REMOTE_WRITE))) {
+ wc.status = IB_WC_REM_INV_REQ_ERR;
+ goto err;
+ }
if (wqe->length == 0)
break;
if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length,
@@ -354,8 +366,10 @@ again:
case IB_WR_RDMA_READ:
if (unlikely(!(qp->qp_access_flags &
- IB_ACCESS_REMOTE_READ)))
- goto acc_err;
+ IB_ACCESS_REMOTE_READ))) {
+ wc.status = IB_WC_REM_INV_REQ_ERR;
+ goto err;
+ }
if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length,
wqe->wr.wr.rdma.remote_addr,
wqe->wr.wr.rdma.rkey,
@@ -369,8 +383,10 @@ again:
case IB_WR_ATOMIC_CMP_AND_SWP:
case IB_WR_ATOMIC_FETCH_AND_ADD:
if (unlikely(!(qp->qp_access_flags &
- IB_ACCESS_REMOTE_ATOMIC)))
- goto acc_err;
+ IB_ACCESS_REMOTE_ATOMIC))) {
+ wc.status = IB_WC_REM_INV_REQ_ERR;
+ goto err;
+ }
if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64),
wqe->wr.wr.atomic.remote_addr,
wqe->wr.wr.atomic.rkey,
@@ -396,6 +412,8 @@ again:
if (len > sge->length)
len = sge->length;
+ if (len > sge->sge_length)
+ len = sge->sge_length;
BUG_ON(len == 0);
ipath_copy_sge(&qp->r_sge, sge->vaddr, len);
sge->vaddr += len;
@@ -503,11 +521,9 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev)
* could be called. If we are still in the tasklet function,
* tasklet_hi_schedule() will not call us until the next time
* tasklet_hi_schedule() is called.
- * We clear the tasklet flag now since we are committing to return
- * from the tasklet function.
+ * We leave the busy flag set so that another post send doesn't
+ * try to put the same QP on the piowait list again.
*/
- clear_bit(IPATH_S_BUSY, &qp->s_busy);
- tasklet_unlock(&qp->s_task);
want_buffer(dev->dd);
dev->n_piowait++;
}
diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
index 03acae66ba8..40c36ec1901 100644
--- a/drivers/infiniband/hw/ipath/ipath_srq.c
+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -80,6 +80,8 @@ int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
wqe->num_sge = wr->num_sge;
for (i = 0; i < wr->num_sge; i++)
wqe->sg_list[i] = wr->sg_list[i];
+ /* Make sure queue entry is written before the head index. */
+ smp_wmb();
wq->head = next;
spin_unlock_irqrestore(&srq->rq.lock, flags);
}
diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
index d8b5e4cefe2..73ed17d0318 100644
--- a/drivers/infiniband/hw/ipath/ipath_stats.c
+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -55,6 +55,7 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
u64 val64;
unsigned long t0, t1;
u64 ret;
+ unsigned long flags;
t0 = jiffies;
/* If fast increment counters are only 32 bits, snapshot them,
@@ -91,12 +92,18 @@ u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
if (creg == dd->ipath_cregs->cr_wordsendcnt) {
if (val != dd->ipath_lastsword) {
dd->ipath_sword += val - dd->ipath_lastsword;
+ spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+ dd->ipath_traffic_wds += val - dd->ipath_lastsword;
+ spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
dd->ipath_lastsword = val;
}
val64 = dd->ipath_sword;
} else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
if (val != dd->ipath_lastrword) {
dd->ipath_rword += val - dd->ipath_lastrword;
+ spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+ dd->ipath_traffic_wds += val - dd->ipath_lastrword;
+ spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
dd->ipath_lastrword = val;
}
val64 = dd->ipath_rword;
@@ -200,6 +207,7 @@ void ipath_get_faststats(unsigned long opaque)
struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
u32 val;
static unsigned cnt;
+ unsigned long flags;
/*
* don't access the chip while running diags, or memory diags can
@@ -210,9 +218,20 @@ void ipath_get_faststats(unsigned long opaque)
/* but re-arm the timer, for diags case; won't hurt other */
goto done;
+ /*
+ * We now try to maintain a "active timer", based on traffic
+ * exceeding a threshold, so we need to check the word-counts
+ * even if they are 64-bit.
+ */
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
+ ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
+ spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
+ if (dd->ipath_traffic_wds >= IPATH_TRAFFIC_ACTIVE_THRESHOLD)
+ atomic_add(5, &dd->ipath_active_time); /* S/B #define */
+ dd->ipath_traffic_wds = 0;
+ spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
+
if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
- ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt);
- ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
}
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
index 4dc398d5e01..16238cd3a03 100644
--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -596,6 +596,43 @@ bail:
return ret;
}
+static ssize_t store_led_override(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int ret;
+ u16 val;
+
+ ret = ipath_parse_ushort(buf, &val);
+ if (ret > 0)
+ ipath_set_led_override(dd, val);
+ else
+ ipath_dev_err(dd, "attempt to set invalid LED override\n");
+ return ret;
+}
+
+static ssize_t show_logged_errs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ipath_devdata *dd = dev_get_drvdata(dev);
+ int idx, count;
+
+ /* force consistency with actual EEPROM */
+ if (ipath_update_eeprom_log(dd) != 0)
+ return -ENXIO;
+
+ count = 0;
+ for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
+ count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
+ dd->ipath_eep_st_errs[idx],
+ idx == (IPATH_EEP_LOG_CNT - 1) ? '\n' : ' ');
+ }
+
+ return count;
+}
static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
@@ -625,6 +662,8 @@ static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL);
static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
+static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
+static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
static struct attribute *dev_attributes[] = {
&dev_attr_guid.attr,
@@ -641,6 +680,8 @@ static struct attribute *dev_attributes[] = {
&dev_attr_unit.attr,
&dev_attr_enabled.attr,
&dev_attr_rx_pol_inv.attr,
+ &dev_attr_led_override.attr,
+ &dev_attr_logged_errors.attr,
NULL
};
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c
index 1c2b03c2ef5..8380fbc50d2 100644
--- a/drivers/infiniband/hw/ipath/ipath_uc.c
+++ b/drivers/infiniband/hw/ipath/ipath_uc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -58,7 +58,6 @@ static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe,
wc->port_num = 0;
ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 0);
}
- wqe = get_swqe_ptr(qp, qp->s_last);
}
/**
@@ -87,7 +86,7 @@ int ipath_make_uc_req(struct ipath_qp *qp,
/* header size in 32-bit words LRH+BTH = (8+12)/4. */
hwords = 5;
- bth0 = 0;
+ bth0 = 1 << 22; /* Set M bit */
/* Get the next send request. */
wqe = get_swqe_ptr(qp, qp->s_last);
@@ -97,8 +96,10 @@ int ipath_make_uc_req(struct ipath_qp *qp,
* Signal the completion of the last send
* (if there is one).
*/
- if (qp->s_last != qp->s_tail)
+ if (qp->s_last != qp->s_tail) {
complete_last_send(qp, wqe, &wc);
+ wqe = get_swqe_ptr(qp, qp->s_last);
+ }
/* Check if send work queue is empty. */
if (qp->s_tail == qp->s_head)
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
index a518f7c8fa8..f9a3338a5fb 100644
--- a/drivers/infiniband/hw/ipath/ipath_ud.c
+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -176,6 +176,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp,
dev->n_pkt_drops++;
goto bail_sge;
}
+ /* Make sure entry is read after head index is read. */
+ smp_rmb();
wqe = get_rwqe_ptr(rq, tail);
if (++tail >= rq->size)
tail = 0;
@@ -231,6 +233,8 @@ static void ipath_ud_loopback(struct ipath_qp *sqp,
if (len > length)
len = length;
+ if (len > sge->sge_length)
+ len = sge->sge_length;
BUG_ON(len == 0);
ipath_copy_sge(&rsge, sge->vaddr, len);
sge->vaddr += len;
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
index 8536aeb96af..27034d38b3d 100644
--- a/drivers/infiniband/hw/ipath/ipath_user_pages.c
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
index bb70845279b..65f7181e9cf 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -164,9 +164,11 @@ void ipath_copy_sge(struct ipath_sge_state *ss, void *data, u32 length)
while (length) {
u32 len = sge->length;
- BUG_ON(len == 0);
if (len > length)
len = length;
+ if (len > sge->sge_length)
+ len = sge->sge_length;
+ BUG_ON(len == 0);
memcpy(sge->vaddr, data, len);
sge->vaddr += len;
sge->length -= len;
@@ -202,9 +204,11 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length)
while (length) {
u32 len = sge->length;
- BUG_ON(len == 0);
if (len > length)
len = length;
+ if (len > sge->sge_length)
+ len = sge->sge_length;
+ BUG_ON(len == 0);
sge->vaddr += len;
sge->length -= len;
sge->sge_length -= len;
@@ -323,6 +327,8 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
wqe->num_sge = wr->num_sge;
for (i = 0; i < wr->num_sge; i++)
wqe->sg_list[i] = wr->sg_list[i];
+ /* Make sure queue entry is written before the head index. */
+ smp_wmb();
wq->head = next;
spin_unlock_irqrestore(&qp->r_rq.lock, flags);
}
@@ -948,6 +954,7 @@ int ipath_ib_piobufavail(struct ipath_ibdev *dev)
qp = list_entry(dev->piowait.next, struct ipath_qp,
piowait);
list_del_init(&qp->piowait);
+ clear_bit(IPATH_S_BUSY, &qp->s_busy);
tasklet_hi_schedule(&qp->s_task);
}
spin_unlock_irqrestore(&dev->pending_lock, flags);
@@ -981,6 +988,8 @@ static int ipath_query_device(struct ib_device *ibdev,
props->max_ah = ib_ipath_max_ahs;
props->max_cqe = ib_ipath_max_cqes;
props->max_mr = dev->lk_table.max;
+ props->max_fmr = dev->lk_table.max;
+ props->max_map_per_fmr = 32767;
props->max_pd = ib_ipath_max_pds;
props->max_qp_rd_atom = IPATH_MAX_RDMA_ATOMIC;
props->max_qp_init_rd_atom = 255;
@@ -1051,7 +1060,12 @@ static int ipath_query_port(struct ib_device *ibdev,
props->max_vl_num = 1; /* VLCap = VL0 */
props->init_type_reply = 0;
- props->max_mtu = IB_MTU_4096;
+ /*
+ * Note: the chips support a maximum MTU of 4096, but the driver
+ * hasn't implemented this feature yet, so set the maximum value
+ * to 2048.
+ */
+ props->max_mtu = IB_MTU_2048;
switch (dev->dd->ipath_ibmtu) {
case 4096:
mtu = IB_MTU_4096;
@@ -1361,13 +1375,6 @@ static void __verbs_timer(unsigned long arg)
{
struct ipath_devdata *dd = (struct ipath_devdata *) arg;
- /*
- * If port 0 receive packet interrupts are not available, or
- * can be missed, poll the receive queue
- */
- if (dd->ipath_flags & IPATH_POLL_RX_INTR)
- ipath_kreceive(dd);
-
/* Handle verbs layer timeouts. */
ipath_ib_timer(dd->verbs_dev);
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
index 088b837ebea..f3d1f2cee6f 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -321,6 +321,7 @@ struct ipath_sge_state {
*/
struct ipath_ack_entry {
u8 opcode;
+ u8 sent;
u32 psn;
union {
struct ipath_sge_state rdma_sge;
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
index dd691cfa507..9e5abf9c309 100644
--- a/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
+++ b/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c b/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c
index 0095bb70f34..1d7bd82a1fb 100644
--- a/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c
+++ b/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
index 04696e62da8..3428acb0868 100644
--- a/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
+++ b/drivers/infiniband/hw/ipath/ipath_wc_x86_64.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 QLogic, Inc. All rights reserved.
+ * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -63,12 +63,29 @@ int ipath_enable_wc(struct ipath_devdata *dd)
* of 2 address matching the length (which has to be a power of 2).
* For rev1, that means the base address, for rev2, it will be just
* the PIO buffers themselves.
+ * For chips with two sets of buffers, the calculations are
+ * somewhat more complicated; we need to sum, and the piobufbase
+ * register has both offsets, 2K in low 32 bits, 4K in high 32 bits.
+ * The buffers are still packed, so a single range covers both.
*/
- pioaddr = addr + dd->ipath_piobufbase;
- piolen = (dd->ipath_piobcnt2k +
- dd->ipath_piobcnt4k) *
- ALIGN(dd->ipath_piobcnt2k +
- dd->ipath_piobcnt4k, dd->ipath_palign);
+ if (dd->ipath_piobcnt2k && dd->ipath_piobcnt4k) { /* 2 sizes */
+ unsigned long pio2kbase, pio4kbase;
+ pio2kbase = dd->ipath_piobufbase & 0xffffffffUL;
+ pio4kbase = (dd->ipath_piobufbase >> 32) & 0xffffffffUL;
+ if (pio2kbase < pio4kbase) { /* all, for now */
+ pioaddr = addr + pio2kbase;
+ piolen = pio4kbase - pio2kbase +
+ dd->ipath_piobcnt4k * dd->ipath_4kalign;
+ } else {
+ pioaddr = addr + pio4kbase;
+ piolen = pio2kbase - pio4kbase +
+ dd->ipath_piobcnt2k * dd->ipath_palign;
+ }
+ } else { /* single buffer size (2K, currently) */
+ pioaddr = addr + dd->ipath_piobufbase;
+ piolen = dd->ipath_piobcnt2k * dd->ipath_palign +
+ dd->ipath_piobcnt4k * dd->ipath_4kalign;
+ }
for (bits = 0; !(piolen & (1ULL << bits)); bits++)
/* do nothing */ ;
diff --git a/drivers/infiniband/hw/mlx4/Kconfig b/drivers/infiniband/hw/mlx4/Kconfig
index b8912cdb966..4175a4bd0c7 100644
--- a/drivers/infiniband/hw/mlx4/Kconfig
+++ b/drivers/infiniband/hw/mlx4/Kconfig
@@ -1,6 +1,5 @@
config MLX4_INFINIBAND
tristate "Mellanox ConnectX HCA support"
- depends on INFINIBAND
select MLX4_CORE
---help---
This driver provides low-level InfiniBand support for
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index b2a290c6703..660b27aecae 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -354,8 +354,8 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
if (is_send) {
wq = &(*cur_qp)->sq;
wqe_ctr = be16_to_cpu(cqe->wqe_index);
- wq->tail += wqe_ctr - (u16) wq->tail;
- wc->wr_id = wq->wrid[wq->tail & (wq->max - 1)];
+ wq->tail += (u16) (wqe_ctr - (u16) wq->tail);
+ wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
++wq->tail;
} else if ((*cur_qp)->ibqp.srq) {
srq = to_msrq((*cur_qp)->ibqp.srq);
@@ -364,7 +364,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
mlx4_ib_free_srq_wqe(srq, wqe_ctr);
} else {
wq = &(*cur_qp)->rq;
- wc->wr_id = wq->wrid[wq->tail & (wq->max - 1)];
+ wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
++wq->tail;
}
@@ -478,7 +478,8 @@ void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq)
{
u32 prod_index;
int nfreed = 0;
- struct mlx4_cqe *cqe;
+ struct mlx4_cqe *cqe, *dest;
+ u8 owner_bit;
/*
* First we need to find the current producer index, so we
@@ -501,9 +502,13 @@ void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq)
if (srq && !(cqe->owner_sr_opcode & MLX4_CQE_IS_SEND_MASK))
mlx4_ib_free_srq_wqe(srq, be16_to_cpu(cqe->wqe_index));
++nfreed;
- } else if (nfreed)
- memcpy(get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe),
- cqe, sizeof *cqe);
+ } else if (nfreed) {
+ dest = get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe);
+ owner_bit = dest->owner_sr_opcode & MLX4_CQE_OWNER_MASK;
+ memcpy(dest, cqe, sizeof *cqe);
+ dest->owner_sr_opcode = owner_bit |
+ (dest->owner_sr_opcode & ~MLX4_CQE_OWNER_MASK);
+ }
}
if (nfreed) {
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 402f3a20ec0..dde8fe9af47 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -120,12 +120,12 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma;
props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs;
- props->max_srq_wr = dev->dev->caps.max_srq_wqes;
+ props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1;
props->max_srq_sge = dev->dev->caps.max_srq_sge;
props->local_ca_ack_delay = dev->dev->caps.local_ca_ack_delay;
props->atomic_cap = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ?
IB_ATOMIC_HCA : IB_ATOMIC_NONE;
- props->max_pkeys = dev->dev->caps.pkey_table_len;
+ props->max_pkeys = dev->dev->caps.pkey_table_len[1];
props->max_mcast_grp = dev->dev->caps.num_mgms + dev->dev->caps.num_amgms;
props->max_mcast_qp_attach = dev->dev->caps.num_qp_per_mgm;
props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
@@ -168,9 +168,9 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
props->state = out_mad->data[32] & 0xf;
props->phys_state = out_mad->data[33] >> 4;
props->port_cap_flags = be32_to_cpup((__be32 *) (out_mad->data + 20));
- props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len;
- props->max_msg_sz = 0x80000000;
- props->pkey_tbl_len = to_mdev(ibdev)->dev->caps.pkey_table_len;
+ props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len[port];
+ props->max_msg_sz = to_mdev(ibdev)->dev->caps.max_msg_sz;
+ props->pkey_tbl_len = to_mdev(ibdev)->dev->caps.pkey_table_len[port];
props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46));
props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48));
props->active_width = out_mad->data[31] & 0xf;
@@ -280,8 +280,14 @@ static int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols,
return PTR_ERR(mailbox);
memset(mailbox->buf, 0, 256);
- *(u8 *) mailbox->buf = !!reset_qkey_viols << 6;
- ((__be32 *) mailbox->buf)[2] = cpu_to_be32(cap_mask);
+
+ if (dev->dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
+ *(u8 *) mailbox->buf = !!reset_qkey_viols << 6;
+ ((__be32 *) mailbox->buf)[2] = cpu_to_be32(cap_mask);
+ } else {
+ ((u8 *) mailbox->buf)[3] = !!reset_qkey_viols;
+ ((__be32 *) mailbox->buf)[1] = cpu_to_be32(cap_mask);
+ }
err = mlx4_cmd(dev->dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
MLX4_CMD_TIME_CLASS_B);
@@ -517,11 +523,13 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
(1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
(1ull << IB_USER_VERBS_CMD_CREATE_QP) |
(1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
(1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
(1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
(1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
(1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
(1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
+ (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
(1ull << IB_USER_VERBS_CMD_DESTROY_SRQ);
ibdev->ib_dev.query_device = mlx4_ib_query_device;
@@ -540,10 +548,12 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.destroy_ah = mlx4_ib_destroy_ah;
ibdev->ib_dev.create_srq = mlx4_ib_create_srq;
ibdev->ib_dev.modify_srq = mlx4_ib_modify_srq;
+ ibdev->ib_dev.query_srq = mlx4_ib_query_srq;
ibdev->ib_dev.destroy_srq = mlx4_ib_destroy_srq;
ibdev->ib_dev.post_srq_recv = mlx4_ib_post_srq_recv;
ibdev->ib_dev.create_qp = mlx4_ib_create_qp;
ibdev->ib_dev.modify_qp = mlx4_ib_modify_qp;
+ ibdev->ib_dev.query_qp = mlx4_ib_query_qp;
ibdev->ib_dev.destroy_qp = mlx4_ib_destroy_qp;
ibdev->ib_dev.post_send = mlx4_ib_post_send;
ibdev->ib_dev.post_recv = mlx4_ib_post_recv;
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 93dac71f323..705ff2fa237 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -35,6 +35,7 @@
#include <linux/compiler.h>
#include <linux/list.h>
+#include <linux/mutex.h>
#include <rdma/ib_verbs.h>
#include <rdma/ib_umem.h>
@@ -95,7 +96,8 @@ struct mlx4_ib_mr {
struct mlx4_ib_wq {
u64 *wrid;
spinlock_t lock;
- int max;
+ int wqe_cnt;
+ int max_post;
int max_gs;
int offset;
int wqe_shift;
@@ -113,6 +115,7 @@ struct mlx4_ib_qp {
u32 doorbell_qpn;
__be32 sq_signal_bits;
+ int sq_spare_wqes;
struct mlx4_ib_wq sq;
struct ib_umem *umem;
@@ -123,6 +126,7 @@ struct mlx4_ib_qp {
u8 alt_port;
u8 atomic_rd_en;
u8 resp_depth;
+ u8 sq_no_prefetch;
u8 state;
};
@@ -252,6 +256,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
struct ib_udata *udata);
int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
enum ib_srq_attr_mask attr_mask, struct ib_udata *udata);
+int mlx4_ib_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr);
int mlx4_ib_destroy_srq(struct ib_srq *srq);
void mlx4_ib_free_srq_wqe(struct mlx4_ib_srq *srq, int wqe_index);
int mlx4_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
@@ -263,6 +268,8 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
int mlx4_ib_destroy_qp(struct ib_qp *qp);
int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
+int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
+ struct ib_qp_init_attr *qp_init_attr);
int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
struct ib_send_wr **bad_wr);
int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index dc137dec230..40042184ad5 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -109,6 +109,20 @@ static void *get_send_wqe(struct mlx4_ib_qp *qp, int n)
return get_wqe(qp, qp->sq.offset + (n << qp->sq.wqe_shift));
}
+/*
+ * Stamp a SQ WQE so that it is invalid if prefetched by marking the
+ * first four bytes of every 64 byte chunk with 0xffffffff, except for
+ * the very first chunk of the WQE.
+ */
+static void stamp_send_wqe(struct mlx4_ib_qp *qp, int n)
+{
+ u32 *wqe = get_send_wqe(qp, n);
+ int i;
+
+ for (i = 16; i < 1 << (qp->sq.wqe_shift - 2); i += 16)
+ wqe[i] = 0xffffffff;
+}
+
static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type)
{
struct ib_event event;
@@ -178,6 +192,8 @@ static int send_wqe_overhead(enum ib_qp_type type)
case IB_QPT_GSI:
return sizeof (struct mlx4_wqe_ctrl_seg) +
ALIGN(MLX4_IB_UD_HEADER_SIZE +
+ DIV_ROUND_UP(MLX4_IB_UD_HEADER_SIZE,
+ MLX4_INLINE_ALIGN) *
sizeof (struct mlx4_wqe_inline_seg),
sizeof (struct mlx4_wqe_data_seg)) +
ALIGN(4 +
@@ -189,20 +205,30 @@ static int send_wqe_overhead(enum ib_qp_type type)
}
static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
- struct mlx4_ib_qp *qp)
+ int is_user, int has_srq, struct mlx4_ib_qp *qp)
{
/* Sanity check RQ size before proceeding */
if (cap->max_recv_wr > dev->dev->caps.max_wqes ||
cap->max_recv_sge > dev->dev->caps.max_rq_sg)
return -EINVAL;
- qp->rq.max = cap->max_recv_wr ? roundup_pow_of_two(cap->max_recv_wr) : 0;
+ if (has_srq) {
+ /* QPs attached to an SRQ should have no RQ */
+ if (cap->max_recv_wr)
+ return -EINVAL;
+
+ qp->rq.wqe_cnt = qp->rq.max_gs = 0;
+ } else {
+ /* HW requires >= 1 RQ entry with >= 1 gather entry */
+ if (is_user && (!cap->max_recv_wr || !cap->max_recv_sge))
+ return -EINVAL;
- qp->rq.wqe_shift = ilog2(roundup_pow_of_two(cap->max_recv_sge *
- sizeof (struct mlx4_wqe_data_seg)));
- qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof (struct mlx4_wqe_data_seg);
+ qp->rq.wqe_cnt = roundup_pow_of_two(max(1U, cap->max_recv_wr));
+ qp->rq.max_gs = roundup_pow_of_two(max(1U, cap->max_recv_sge));
+ qp->rq.wqe_shift = ilog2(qp->rq.max_gs * sizeof (struct mlx4_wqe_data_seg));
+ }
- cap->max_recv_wr = qp->rq.max;
+ cap->max_recv_wr = qp->rq.max_post = qp->rq.wqe_cnt;
cap->max_recv_sge = qp->rq.max_gs;
return 0;
@@ -226,8 +252,6 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
cap->max_send_sge + 2 > dev->dev->caps.max_sq_sg)
return -EINVAL;
- qp->sq.max = cap->max_send_wr ? roundup_pow_of_two(cap->max_send_wr) : 1;
-
qp->sq.wqe_shift = ilog2(roundup_pow_of_two(max(cap->max_send_sge *
sizeof (struct mlx4_wqe_data_seg),
cap->max_inline_data +
@@ -236,20 +260,27 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
qp->sq.max_gs = ((1 << qp->sq.wqe_shift) - send_wqe_overhead(type)) /
sizeof (struct mlx4_wqe_data_seg);
- qp->buf_size = (qp->rq.max << qp->rq.wqe_shift) +
- (qp->sq.max << qp->sq.wqe_shift);
+ /*
+ * We need to leave 2 KB + 1 WQE of headroom in the SQ to
+ * allow HW to prefetch.
+ */
+ qp->sq_spare_wqes = (2048 >> qp->sq.wqe_shift) + 1;
+ qp->sq.wqe_cnt = roundup_pow_of_two(cap->max_send_wr + qp->sq_spare_wqes);
+
+ qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
+ (qp->sq.wqe_cnt << qp->sq.wqe_shift);
if (qp->rq.wqe_shift > qp->sq.wqe_shift) {
qp->rq.offset = 0;
- qp->sq.offset = qp->rq.max << qp->rq.wqe_shift;
+ qp->sq.offset = qp->rq.wqe_cnt << qp->rq.wqe_shift;
} else {
- qp->rq.offset = qp->sq.max << qp->sq.wqe_shift;
+ qp->rq.offset = qp->sq.wqe_cnt << qp->sq.wqe_shift;
qp->sq.offset = 0;
}
- cap->max_send_wr = qp->sq.max;
- cap->max_send_sge = qp->sq.max_gs;
- cap->max_inline_data = (1 << qp->sq.wqe_shift) - send_wqe_overhead(type) -
- sizeof (struct mlx4_wqe_inline_seg);
+ cap->max_send_wr = qp->sq.max_post = qp->sq.wqe_cnt - qp->sq_spare_wqes;
+ cap->max_send_sge = qp->sq.max_gs;
+ /* We don't support inline sends for kernel QPs (yet) */
+ cap->max_inline_data = 0;
return 0;
}
@@ -257,11 +288,11 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
static int set_user_sq_size(struct mlx4_ib_qp *qp,
struct mlx4_ib_create_qp *ucmd)
{
- qp->sq.max = 1 << ucmd->log_sq_bb_count;
+ qp->sq.wqe_cnt = 1 << ucmd->log_sq_bb_count;
qp->sq.wqe_shift = ucmd->log_sq_stride;
- qp->buf_size = (qp->rq.max << qp->rq.wqe_shift) +
- (qp->sq.max << qp->sq.wqe_shift);
+ qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
+ (qp->sq.wqe_cnt << qp->sq.wqe_shift);
return 0;
}
@@ -285,7 +316,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
qp->sq.head = 0;
qp->sq.tail = 0;
- err = set_rq_size(dev, &init_attr->cap, qp);
+ err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
if (err)
goto err;
@@ -297,6 +328,8 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
goto err;
}
+ qp->sq_no_prefetch = ucmd.sq_no_prefetch;
+
err = set_user_sq_size(qp, &ucmd);
if (err)
goto err;
@@ -324,6 +357,8 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
goto err_mtt;
}
} else {
+ qp->sq_no_prefetch = 0;
+
err = set_kernel_sq_size(dev, &init_attr->cap, init_attr->qp_type, qp);
if (err)
goto err;
@@ -350,16 +385,13 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err_mtt;
- qp->sq.wrid = kmalloc(qp->sq.max * sizeof (u64), GFP_KERNEL);
- qp->rq.wrid = kmalloc(qp->rq.max * sizeof (u64), GFP_KERNEL);
+ qp->sq.wrid = kmalloc(qp->sq.wqe_cnt * sizeof (u64), GFP_KERNEL);
+ qp->rq.wrid = kmalloc(qp->rq.wqe_cnt * sizeof (u64), GFP_KERNEL);
if (!qp->sq.wrid || !qp->rq.wrid) {
err = -ENOMEM;
goto err_wrid;
}
-
- /* We don't support inline sends for kernel QPs (yet) */
- init_attr->cap.max_inline_data = 0;
}
err = mlx4_qp_alloc(dev->dev, sqpn, &qp->mqp);
@@ -573,24 +605,6 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
return 0;
}
-static void init_port(struct mlx4_ib_dev *dev, int port)
-{
- struct mlx4_init_port_param param;
- int err;
-
- memset(&param, 0, sizeof param);
-
- param.port_width_cap = dev->dev->caps.port_width_cap;
- param.vl_cap = dev->dev->caps.vl_cap;
- param.mtu = ib_mtu_enum_to_int(dev->dev->caps.mtu_cap);
- param.max_gid = dev->dev->caps.gid_table_len;
- param.max_pkey = dev->dev->caps.pkey_table_len;
-
- err = mlx4_INIT_PORT(dev->dev, &param, port);
- if (err)
- printk(KERN_WARNING "INIT_PORT failed, return code %d.\n", err);
-}
-
static int to_mlx4_st(enum ib_qp_type type)
{
switch (type) {
@@ -664,9 +678,9 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
path->counter_index = 0xff;
if (ah->ah_flags & IB_AH_GRH) {
- if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len) {
+ if (ah->grh.sgid_index >= dev->dev->caps.gid_table_len[port]) {
printk(KERN_ERR "sgid_index (%u) too large. max is %d\n",
- ah->grh.sgid_index, dev->dev->caps.gid_table_len - 1);
+ ah->grh.sgid_index, dev->dev->caps.gid_table_len[port] - 1);
return -1;
}
@@ -733,14 +747,17 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->mtu_msgmax = (attr->path_mtu << 5) | 31;
}
- if (qp->rq.max)
- context->rq_size_stride = ilog2(qp->rq.max) << 3;
+ if (qp->rq.wqe_cnt)
+ context->rq_size_stride = ilog2(qp->rq.wqe_cnt) << 3;
context->rq_size_stride |= qp->rq.wqe_shift - 4;
- if (qp->sq.max)
- context->sq_size_stride = ilog2(qp->sq.max) << 3;
+ if (qp->sq.wqe_cnt)
+ context->sq_size_stride = ilog2(qp->sq.wqe_cnt) << 3;
context->sq_size_stride |= qp->sq.wqe_shift - 4;
+ if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
+ context->sq_size_stride |= !!qp->sq_no_prefetch << 7;
+
if (qp->ibqp.uobject)
context->usr_page = cpu_to_be32(to_mucontext(ibqp->uobject->context)->uar.index);
else
@@ -762,11 +779,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
optpar |= MLX4_QP_OPTPAR_PKEY_INDEX;
}
- if (attr_mask & IB_QP_RNR_RETRY) {
- context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
- optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
- }
-
if (attr_mask & IB_QP_AV) {
if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path,
attr_mask & IB_QP_PORT ? attr->port_num : qp->port)) {
@@ -784,13 +796,14 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
}
if (attr_mask & IB_QP_ALT_PATH) {
- if (attr->alt_pkey_index >= dev->dev->caps.pkey_table_len)
- return -EINVAL;
-
if (attr->alt_port_num == 0 ||
attr->alt_port_num > dev->dev->caps.num_ports)
return -EINVAL;
+ if (attr->alt_pkey_index >=
+ dev->dev->caps.pkey_table_len[attr->alt_port_num])
+ return -EINVAL;
+
if (mlx4_set_path(dev, &attr->alt_ah_attr, &context->alt_path,
attr->alt_port_num))
return -EINVAL;
@@ -802,6 +815,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
+
+ if (attr_mask & IB_QP_RNR_RETRY) {
+ context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
+ optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
+ }
+
if (attr_mask & IB_QP_RETRY_CNT) {
context->params1 |= cpu_to_be32(attr->retry_cnt << 16);
optpar |= MLX4_QP_OPTPAR_RETRY_COUNT;
@@ -873,16 +892,19 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
/*
* Before passing a kernel QP to the HW, make sure that the
- * ownership bits of the send queue are set so that the
- * hardware doesn't start processing stale work requests.
+ * ownership bits of the send queue are set and the SQ
+ * headroom is stamped so that the hardware doesn't start
+ * processing stale work requests.
*/
if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
struct mlx4_wqe_ctrl_seg *ctrl;
int i;
- for (i = 0; i < qp->sq.max; ++i) {
+ for (i = 0; i < qp->sq.wqe_cnt; ++i) {
ctrl = get_send_wqe(qp, i);
ctrl->owner_opcode = cpu_to_be32(1 << 31);
+
+ stamp_send_wqe(qp, i);
}
}
@@ -912,7 +934,9 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
*/
if (is_qp0(dev, qp)) {
if (cur_state != IB_QPS_RTR && new_state == IB_QPS_RTR)
- init_port(dev, qp->port);
+ if (mlx4_INIT_PORT(dev->dev, qp->port))
+ printk(KERN_WARNING "INIT_PORT failed for port %d\n",
+ qp->port);
if (cur_state != IB_QPS_RESET && cur_state != IB_QPS_ERR &&
(new_state == IB_QPS_RESET || new_state == IB_QPS_ERR))
@@ -975,16 +999,17 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, attr_mask))
goto out;
- if ((attr_mask & IB_QP_PKEY_INDEX) &&
- attr->pkey_index >= dev->dev->caps.pkey_table_len) {
- goto out;
- }
-
if ((attr_mask & IB_QP_PORT) &&
(attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) {
goto out;
}
+ if (attr_mask & IB_QP_PKEY_INDEX) {
+ int p = attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
+ if (attr->pkey_index >= dev->dev->caps.pkey_table_len[p])
+ goto out;
+ }
+
if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
attr->max_rd_atomic > dev->dev->caps.max_qp_init_rdma) {
goto out;
@@ -1026,6 +1051,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
u16 pkey;
int send_size;
int header_size;
+ int spc;
int i;
send_size = 0;
@@ -1101,10 +1127,43 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
printk("\n");
}
- inl->byte_count = cpu_to_be32(1 << 31 | header_size);
- memcpy(inl + 1, sqp->header_buf, header_size);
+ /*
+ * Inline data segments may not cross a 64 byte boundary. If
+ * our UD header is bigger than the space available up to the
+ * next 64 byte boundary in the WQE, use two inline data
+ * segments to hold the UD header.
+ */
+ spc = MLX4_INLINE_ALIGN -
+ ((unsigned long) (inl + 1) & (MLX4_INLINE_ALIGN - 1));
+ if (header_size <= spc) {
+ inl->byte_count = cpu_to_be32(1 << 31 | header_size);
+ memcpy(inl + 1, sqp->header_buf, header_size);
+ i = 1;
+ } else {
+ inl->byte_count = cpu_to_be32(1 << 31 | spc);
+ memcpy(inl + 1, sqp->header_buf, spc);
- return ALIGN(sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
+ inl = (void *) (inl + 1) + spc;
+ memcpy(inl + 1, sqp->header_buf + spc, header_size - spc);
+ /*
+ * Need a barrier here to make sure all the data is
+ * visible before the byte_count field is set.
+ * Otherwise the HCA prefetcher could grab the 64-byte
+ * chunk with this inline segment and get a valid (!=
+ * 0xffffffff) byte count but stale data, and end up
+ * generating a packet with bad headers.
+ *
+ * The first inline segment's byte_count field doesn't
+ * need a barrier, because it comes after a
+ * control/MLX segment and therefore is at an offset
+ * of 16 mod 64.
+ */
+ wmb();
+ inl->byte_count = cpu_to_be32(1 << 31 | (header_size - spc));
+ i = 2;
+ }
+
+ return ALIGN(i * sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
}
static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq)
@@ -1113,7 +1172,7 @@ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq
struct mlx4_ib_cq *cq;
cur = wq->head - wq->tail;
- if (likely(cur + nreq < wq->max))
+ if (likely(cur + nreq < wq->max_post))
return 0;
cq = to_mcq(ib_cq);
@@ -1121,7 +1180,7 @@ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq
cur = wq->head - wq->tail;
spin_unlock(&cq->lock);
- return cur + nreq >= wq->max;
+ return cur + nreq >= wq->max_post;
}
int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
@@ -1154,8 +1213,8 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
goto out;
}
- ctrl = wqe = get_send_wqe(qp, ind & (qp->sq.max - 1));
- qp->sq.wrid[ind & (qp->sq.max - 1)] = wr->wr_id;
+ ctrl = wqe = get_send_wqe(qp, ind & (qp->sq.wqe_cnt - 1));
+ qp->sq.wrid[ind & (qp->sq.wqe_cnt - 1)] = wr->wr_id;
ctrl->srcrb_flags =
(wr->send_flags & IB_SEND_SIGNALED ?
@@ -1290,7 +1349,16 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
}
ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] |
- (ind & qp->sq.max ? cpu_to_be32(1 << 31) : 0);
+ (ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0);
+
+ /*
+ * We can improve latency by not stamping the last
+ * send queue WQE until after ringing the doorbell, so
+ * only stamp here if there are still more WQEs to post.
+ */
+ if (wr->next)
+ stamp_send_wqe(qp, (ind + qp->sq_spare_wqes) &
+ (qp->sq.wqe_cnt - 1));
++ind;
}
@@ -1313,6 +1381,9 @@ out:
* and reach the HCA out of order.
*/
mmiowb();
+
+ stamp_send_wqe(qp, (ind + qp->sq_spare_wqes - 1) &
+ (qp->sq.wqe_cnt - 1));
}
spin_unlock_irqrestore(&qp->rq.lock, flags);
@@ -1333,7 +1404,7 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
spin_lock_irqsave(&qp->rq.lock, flags);
- ind = qp->rq.head & (qp->rq.max - 1);
+ ind = qp->rq.head & (qp->rq.wqe_cnt - 1);
for (nreq = 0; wr; ++nreq, wr = wr->next) {
if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.send_cq)) {
@@ -1364,7 +1435,7 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
qp->rq.wrid[ind] = wr->wr_id;
- ind = (ind + 1) & (qp->rq.max - 1);
+ ind = (ind + 1) & (qp->rq.wqe_cnt - 1);
}
out:
@@ -1384,3 +1455,140 @@ out:
return err;
}
+
+static inline enum ib_qp_state to_ib_qp_state(enum mlx4_qp_state mlx4_state)
+{
+ switch (mlx4_state) {
+ case MLX4_QP_STATE_RST: return IB_QPS_RESET;
+ case MLX4_QP_STATE_INIT: return IB_QPS_INIT;
+ case MLX4_QP_STATE_RTR: return IB_QPS_RTR;
+ case MLX4_QP_STATE_RTS: return IB_QPS_RTS;
+ case MLX4_QP_STATE_SQ_DRAINING:
+ case MLX4_QP_STATE_SQD: return IB_QPS_SQD;
+ case MLX4_QP_STATE_SQER: return IB_QPS_SQE;
+ case MLX4_QP_STATE_ERR: return IB_QPS_ERR;
+ default: return -1;
+ }
+}
+
+static inline enum ib_mig_state to_ib_mig_state(int mlx4_mig_state)
+{
+ switch (mlx4_mig_state) {
+ case MLX4_QP_PM_ARMED: return IB_MIG_ARMED;
+ case MLX4_QP_PM_REARM: return IB_MIG_REARM;
+ case MLX4_QP_PM_MIGRATED: return IB_MIG_MIGRATED;
+ default: return -1;
+ }
+}
+
+static int to_ib_qp_access_flags(int mlx4_flags)
+{
+ int ib_flags = 0;
+
+ if (mlx4_flags & MLX4_QP_BIT_RRE)
+ ib_flags |= IB_ACCESS_REMOTE_READ;
+ if (mlx4_flags & MLX4_QP_BIT_RWE)
+ ib_flags |= IB_ACCESS_REMOTE_WRITE;
+ if (mlx4_flags & MLX4_QP_BIT_RAE)
+ ib_flags |= IB_ACCESS_REMOTE_ATOMIC;
+
+ return ib_flags;
+}
+
+static void to_ib_ah_attr(struct mlx4_dev *dev, struct ib_ah_attr *ib_ah_attr,
+ struct mlx4_qp_path *path)
+{
+ memset(ib_ah_attr, 0, sizeof *path);
+ ib_ah_attr->port_num = path->sched_queue & 0x40 ? 2 : 1;
+
+ if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->caps.num_ports)
+ return;
+
+ ib_ah_attr->dlid = be16_to_cpu(path->rlid);
+ ib_ah_attr->sl = (path->sched_queue >> 2) & 0xf;
+ ib_ah_attr->src_path_bits = path->grh_mylmc & 0x7f;
+ ib_ah_attr->static_rate = path->static_rate ? path->static_rate - 5 : 0;
+ ib_ah_attr->ah_flags = (path->grh_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
+ if (ib_ah_attr->ah_flags) {
+ ib_ah_attr->grh.sgid_index = path->mgid_index;
+ ib_ah_attr->grh.hop_limit = path->hop_limit;
+ ib_ah_attr->grh.traffic_class =
+ (be32_to_cpu(path->tclass_flowlabel) >> 20) & 0xff;
+ ib_ah_attr->grh.flow_label =
+ be32_to_cpu(path->tclass_flowlabel) & 0xffffff;
+ memcpy(ib_ah_attr->grh.dgid.raw,
+ path->rgid, sizeof ib_ah_attr->grh.dgid.raw);
+ }
+}
+
+int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
+ struct ib_qp_init_attr *qp_init_attr)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibqp->device);
+ struct mlx4_ib_qp *qp = to_mqp(ibqp);
+ struct mlx4_qp_context context;
+ int mlx4_state;
+ int err;
+
+ if (qp->state == IB_QPS_RESET) {
+ qp_attr->qp_state = IB_QPS_RESET;
+ goto done;
+ }
+
+ err = mlx4_qp_query(dev->dev, &qp->mqp, &context);
+ if (err)
+ return -EINVAL;
+
+ mlx4_state = be32_to_cpu(context.flags) >> 28;
+
+ qp_attr->qp_state = to_ib_qp_state(mlx4_state);
+ qp_attr->path_mtu = context.mtu_msgmax >> 5;
+ qp_attr->path_mig_state =
+ to_ib_mig_state((be32_to_cpu(context.flags) >> 11) & 0x3);
+ qp_attr->qkey = be32_to_cpu(context.qkey);
+ qp_attr->rq_psn = be32_to_cpu(context.rnr_nextrecvpsn) & 0xffffff;
+ qp_attr->sq_psn = be32_to_cpu(context.next_send_psn) & 0xffffff;
+ qp_attr->dest_qp_num = be32_to_cpu(context.remote_qpn) & 0xffffff;
+ qp_attr->qp_access_flags =
+ to_ib_qp_access_flags(be32_to_cpu(context.params2));
+
+ if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
+ to_ib_ah_attr(dev->dev, &qp_attr->ah_attr, &context.pri_path);
+ to_ib_ah_attr(dev->dev, &qp_attr->alt_ah_attr, &context.alt_path);
+ qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f;
+ qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num;
+ }
+
+ qp_attr->pkey_index = context.pri_path.pkey_index & 0x7f;
+ qp_attr->port_num = context.pri_path.sched_queue & 0x40 ? 2 : 1;
+
+ /* qp_attr->en_sqd_async_notify is only applicable in modify qp */
+ qp_attr->sq_draining = mlx4_state == MLX4_QP_STATE_SQ_DRAINING;
+
+ qp_attr->max_rd_atomic = 1 << ((be32_to_cpu(context.params1) >> 21) & 0x7);
+
+ qp_attr->max_dest_rd_atomic =
+ 1 << ((be32_to_cpu(context.params2) >> 21) & 0x7);
+ qp_attr->min_rnr_timer =
+ (be32_to_cpu(context.rnr_nextrecvpsn) >> 24) & 0x1f;
+ qp_attr->timeout = context.pri_path.ackto >> 3;
+ qp_attr->retry_cnt = (be32_to_cpu(context.params1) >> 16) & 0x7;
+ qp_attr->rnr_retry = (be32_to_cpu(context.params1) >> 13) & 0x7;
+ qp_attr->alt_timeout = context.alt_path.ackto >> 3;
+
+done:
+ qp_attr->cur_qp_state = qp_attr->qp_state;
+ if (!ibqp->uobject) {
+ qp_attr->cap.max_send_wr = qp->sq.wqe_cnt;
+ qp_attr->cap.max_recv_wr = qp->rq.wqe_cnt;
+ qp_attr->cap.max_send_sge = qp->sq.max_gs;
+ qp_attr->cap.max_recv_sge = qp->rq.max_gs;
+ qp_attr->cap.max_inline_data = (1 << qp->sq.wqe_shift) -
+ send_wqe_overhead(qp->ibqp.qp_type) -
+ sizeof (struct mlx4_wqe_inline_seg);
+ qp_init_attr->cap = qp_attr->cap;
+ }
+
+ return 0;
+}
+
diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c
index 12fac1c8989..408748fb528 100644
--- a/drivers/infiniband/hw/mlx4/srq.c
+++ b/drivers/infiniband/hw/mlx4/srq.c
@@ -240,6 +240,24 @@ int mlx4_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
return 0;
}
+int mlx4_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibsrq->device);
+ struct mlx4_ib_srq *srq = to_msrq(ibsrq);
+ int ret;
+ int limit_watermark;
+
+ ret = mlx4_srq_query(dev->dev, &srq->msrq, &limit_watermark);
+ if (ret)
+ return ret;
+
+ srq_attr->srq_limit = be16_to_cpu(limit_watermark);
+ srq_attr->max_wr = srq->msrq.max - 1;
+ srq_attr->max_sge = srq->msrq.max_gs;
+
+ return 0;
+}
+
int mlx4_ib_destroy_srq(struct ib_srq *srq)
{
struct mlx4_ib_dev *dev = to_mdev(srq->device);
diff --git a/drivers/infiniband/hw/mlx4/user.h b/drivers/infiniband/hw/mlx4/user.h
index 88c72d56368..e2d11be4525 100644
--- a/drivers/infiniband/hw/mlx4/user.h
+++ b/drivers/infiniband/hw/mlx4/user.h
@@ -39,7 +39,7 @@
* Increment this value if any changes that break userspace ABI
* compatibility are made.
*/
-#define MLX4_IB_UVERBS_ABI_VERSION 2
+#define MLX4_IB_UVERBS_ABI_VERSION 3
/*
* Make sure that all structs defined in this file remain laid out so
@@ -87,9 +87,10 @@ struct mlx4_ib_create_srq_resp {
struct mlx4_ib_create_qp {
__u64 buf_addr;
__u64 db_addr;
- __u8 log_sq_bb_count;
- __u8 log_sq_stride;
- __u8 reserved[6];
+ __u8 log_sq_bb_count;
+ __u8 log_sq_stride;
+ __u8 sq_no_prefetch;
+ __u8 reserved[5];
};
#endif /* MLX4_IB_USER_H */
diff --git a/drivers/infiniband/hw/mthca/Kconfig b/drivers/infiniband/hw/mthca/Kconfig
index 9aa5a4468a7..03efc074967 100644
--- a/drivers/infiniband/hw/mthca/Kconfig
+++ b/drivers/infiniband/hw/mthca/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_MTHCA
tristate "Mellanox HCA support"
- depends on PCI && INFINIBAND
+ depends on PCI
---help---
This is a low-level driver for Mellanox InfiniHost host
channel adapters (HCAs), including the MT23108 PCI-X HCA
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index f930e55b58f..a7630670961 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -255,7 +255,7 @@ int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
dma_list[i] = t;
pci_unmap_addr_set(&buf->page_list[i], mapping, t);
- memset(buf->page_list[i].buf, 0, PAGE_SIZE);
+ clear_page(buf->page_list[i].buf);
}
}
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 38102520ffb..f40558d7647 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -772,7 +772,7 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
MTHCA_GET(dev->fw_ver, outbox, QUERY_FW_VER_OFFSET);
/*
- * FW subminor version is at more signifant bits than minor
+ * FW subminor version is at more significant bits than minor
* version, so swap here.
*/
dev->fw_ver = (dev->fw_ver & 0xffff00000000ull) |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 8ec9fa1ff9e..8592b26dc4e 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -522,7 +522,7 @@ static int mthca_create_eq(struct mthca_dev *dev,
dma_list[i] = t;
pci_unmap_addr_set(&eq->page_list[i], mapping, t);
- memset(eq->page_list[i].buf, 0, PAGE_SIZE);
+ clear_page(eq->page_list[i].buf);
}
for (i = 0; i < eq->nent; ++i)
diff --git a/drivers/infiniband/ulp/ipoib/Kconfig b/drivers/infiniband/ulp/ipoib/Kconfig
index af78ccc4ce7..1f76bad020f 100644
--- a/drivers/infiniband/ulp/ipoib/Kconfig
+++ b/drivers/infiniband/ulp/ipoib/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_IPOIB
tristate "IP-over-InfiniBand"
- depends on INFINIBAND && NETDEVICES && INET && (IPV6 || IPV6=n)
+ depends on NETDEVICES && INET && (IPV6 || IPV6=n)
---help---
Support for the IP-over-InfiniBand protocol (IPoIB). This
transports IP packets over InfiniBand so you can use your IB
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 076a0bbb63d..08b4676a382 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -56,13 +56,6 @@ MODULE_PARM_DESC(cm_data_debug_level,
#define IPOIB_CM_RX_DELAY (3 * 256 * HZ)
#define IPOIB_CM_RX_UPDATE_MASK (0x3)
-struct ipoib_cm_id {
- struct ib_cm_id *id;
- int flags;
- u32 remote_qpn;
- u32 remote_mtu;
-};
-
static struct ib_qp_attr ipoib_cm_err_attr = {
.qp_state = IB_QPS_ERR
};
@@ -155,8 +148,8 @@ partial_error:
ib_dma_unmap_single(priv->ca, mapping[0], IPOIB_CM_HEAD_SIZE, DMA_FROM_DEVICE);
- for (; i >= 0; --i)
- ib_dma_unmap_single(priv->ca, mapping[i + 1], PAGE_SIZE, DMA_FROM_DEVICE);
+ for (; i > 0; --i)
+ ib_dma_unmap_single(priv->ca, mapping[i], PAGE_SIZE, DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
return NULL;
@@ -288,7 +281,6 @@ static int ipoib_cm_send_rep(struct net_device *dev, struct ib_cm_id *cm_id,
rep.private_data_len = sizeof data;
rep.flow_control = 0;
rep.rnr_retry_count = req->rnr_retry_count;
- rep.target_ack_delay = 20; /* FIXME */
rep.srq = 1;
rep.qp_num = qp->qp_num;
rep.starting_psn = psn;
@@ -309,6 +301,11 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
return -ENOMEM;
p->dev = dev;
p->id = cm_id;
+ cm_id->context = p;
+ p->state = IPOIB_CM_RX_LIVE;
+ p->jiffies = jiffies;
+ INIT_LIST_HEAD(&p->list);
+
p->qp = ipoib_cm_create_rx_qp(dev, p);
if (IS_ERR(p->qp)) {
ret = PTR_ERR(p->qp);
@@ -320,24 +317,24 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
if (ret)
goto err_modify;
+ spin_lock_irq(&priv->lock);
+ queue_delayed_work(ipoib_workqueue,
+ &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
+ /* Add this entry to passive ids list head, but do not re-add it
+ * if IB_EVENT_QP_LAST_WQE_REACHED has moved it to flush list. */
+ p->jiffies = jiffies;
+ if (p->state == IPOIB_CM_RX_LIVE)
+ list_move(&p->list, &priv->cm.passive_ids);
+ spin_unlock_irq(&priv->lock);
+
ret = ipoib_cm_send_rep(dev, cm_id, p->qp, &event->param.req_rcvd, psn);
if (ret) {
ipoib_warn(priv, "failed to send REP: %d\n", ret);
- goto err_rep;
+ if (ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE))
+ ipoib_warn(priv, "unable to move qp to error state\n");
}
-
- cm_id->context = p;
- p->jiffies = jiffies;
- p->state = IPOIB_CM_RX_LIVE;
- spin_lock_irq(&priv->lock);
- if (list_empty(&priv->cm.passive_ids))
- queue_delayed_work(ipoib_workqueue,
- &priv->cm.stale_task, IPOIB_CM_RX_DELAY);
- list_add(&p->list, &priv->cm.passive_ids);
- spin_unlock_irq(&priv->lock);
return 0;
-err_rep:
err_modify:
ib_destroy_qp(p->qp);
err_qp:
@@ -754,9 +751,9 @@ static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
p->mtu = be32_to_cpu(data->mtu);
- if (p->mtu < priv->dev->mtu + IPOIB_ENCAP_LEN) {
- ipoib_warn(priv, "Rejecting connection: mtu %d < device mtu %d + 4\n",
- p->mtu, priv->dev->mtu);
+ if (p->mtu <= IPOIB_ENCAP_LEN) {
+ ipoib_warn(priv, "Rejecting connection: mtu %d <= %d\n",
+ p->mtu, IPOIB_ENCAP_LEN);
return -EINVAL;
}
@@ -1150,7 +1147,6 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
{
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
cm.skb_task);
- struct net_device *dev = priv->dev;
struct sk_buff *skb;
unsigned mtu = priv->mcast_mtu;
@@ -1164,7 +1160,7 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6))
- icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev);
#endif
dev_kfree_skb_any(skb);
spin_lock_irq(&priv->tx_lock);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 8404f05b2b6..10944888cff 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -197,6 +197,13 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
}
/*
+ * Drop packets that this interface sent, ie multicast packets
+ * that the HCA has replicated.
+ */
+ if (wc->slid == priv->local_lid && wc->src_qp == priv->qp->qp_num)
+ goto repost;
+
+ /*
* If we can't allocate a new RX buffer, dump
* this packet and reuse the old buffer.
*/
@@ -213,24 +220,18 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
skb_put(skb, wc->byte_len);
skb_pull(skb, IB_GRH_BYTES);
- if (wc->slid != priv->local_lid ||
- wc->src_qp != priv->qp->qp_num) {
- skb->protocol = ((struct ipoib_header *) skb->data)->proto;
- skb_reset_mac_header(skb);
- skb_pull(skb, IPOIB_ENCAP_LEN);
+ skb->protocol = ((struct ipoib_header *) skb->data)->proto;
+ skb_reset_mac_header(skb);
+ skb_pull(skb, IPOIB_ENCAP_LEN);
- dev->last_rx = jiffies;
- ++priv->stats.rx_packets;
- priv->stats.rx_bytes += skb->len;
+ dev->last_rx = jiffies;
+ ++priv->stats.rx_packets;
+ priv->stats.rx_bytes += skb->len;
- skb->dev = dev;
- /* XXX get correct PACKET_ type here */
- skb->pkt_type = PACKET_HOST;
- netif_receive_skb(skb);
- } else {
- ipoib_dbg_data(priv, "dropping loopback packet\n");
- dev_kfree_skb_any(skb);
- }
+ skb->dev = dev;
+ /* XXX get correct PACKET_ type here */
+ skb->pkt_type = PACKET_HOST;
+ netif_receive_skb(skb);
repost:
if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
diff --git a/drivers/infiniband/ulp/iser/Kconfig b/drivers/infiniband/ulp/iser/Kconfig
index aecbb9083f0..fe604c8d299 100644
--- a/drivers/infiniband/ulp/iser/Kconfig
+++ b/drivers/infiniband/ulp/iser/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_ISER
tristate "iSCSI Extensions for RDMA (iSER)"
- depends on INFINIBAND && SCSI && INET
+ depends on SCSI && INET
select SCSI_ISCSI_ATTRS
---help---
Support for the iSCSI Extensions for RDMA (iSER) Protocol
diff --git a/drivers/infiniband/ulp/srp/Kconfig b/drivers/infiniband/ulp/srp/Kconfig
index 8fe3be4e991..3432dce2952 100644
--- a/drivers/infiniband/ulp/srp/Kconfig
+++ b/drivers/infiniband/ulp/srp/Kconfig
@@ -1,6 +1,6 @@
config INFINIBAND_SRP
tristate "InfiniBand SCSI RDMA Protocol"
- depends on INFINIBAND && SCSI
+ depends on SCSI
---help---
Support for the SCSI RDMA Protocol over InfiniBand. This
allows you to access storage devices that speak SRP over
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index f814fb3a469..2d87357e2b2 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -39,6 +39,19 @@ config INPUT_FF_MEMLESS
To compile this driver as a module, choose M here: the
module will be called ff-memless.
+config INPUT_POLLDEV
+ tristate "Polled input device skeleton"
+ help
+ Say Y here if you are using a driver for an input
+ device that periodically polls hardware state. This
+ option is only useful for out-of-tree drivers since
+ in-tree drivers select it automatically.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called input-polldev.
+
comment "Userland interfaces"
config INPUT_MOUSEDEV
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 8a2dd987546..15eb752697b 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_INPUT) += input-core.o
input-core-objs := input.o ff-core.o
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
+obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b234729706b..ab4b2d9b532 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -30,6 +30,7 @@ struct evdev {
wait_queue_head_t wait;
struct evdev_client *grab;
struct list_head client_list;
+ struct device dev;
};
struct evdev_client {
@@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id)
return input_flush_device(&evdev->handle, file);
}
-static void evdev_free(struct evdev *evdev)
+static void evdev_free(struct device *dev)
{
+ struct evdev *evdev = container_of(dev, struct evdev, dev);
+
evdev_table[evdev->minor] = NULL;
kfree(evdev);
}
@@ -114,12 +117,10 @@ static int evdev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--evdev->open) {
- if (evdev->exist)
- input_close_device(&evdev->handle);
- else
- evdev_free(evdev);
- }
+ if (!--evdev->open && evdev->exist)
+ input_close_device(&evdev->handle);
+
+ put_device(&evdev->dev);
return 0;
}
@@ -139,24 +140,32 @@ static int evdev_open(struct inode *inode, struct file *file)
if (!evdev || !evdev->exist)
return -ENODEV;
+ get_device(&evdev->dev);
+
client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_evdev;
+ }
client->evdev = evdev;
list_add_tail(&client->node, &evdev->client_list);
if (!evdev->open++ && evdev->exist) {
error = input_open_device(&evdev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_evdev:
+ put_device(&evdev->dev);
+ return error;
}
#ifdef CONFIG_COMPAT
@@ -625,8 +634,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct evdev *evdev;
- struct class_device *cdev;
- dev_t devt;
int minor;
int error;
@@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
evdev->handle.name = evdev->name;
evdev->handle.handler = handler;
evdev->handle.private = evdev;
- sprintf(evdev->name, "event%d", minor);
+ snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
- evdev_table[minor] = evdev;
-
- devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+ snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
+ "event%d", minor);
+ evdev->dev.class = &input_class;
+ evdev->dev.parent = &dev->dev;
+ evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
+ evdev->dev.release = evdev_free;
+ device_initialize(&evdev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, evdev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_evdev;
- }
+ evdev_table[minor] = evdev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, evdev->name);
+ error = device_add(&evdev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_evdev;
error = input_register_handle(&evdev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_evdev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_evdev:
+ device_del(&evdev->dev);
err_free_evdev:
- kfree(evdev);
- evdev_table[minor] = NULL;
+ put_device(&evdev->dev);
return error;
}
@@ -690,20 +691,19 @@ static void evdev_disconnect(struct input_handle *handle)
struct evdev_client *client;
input_unregister_handle(handle);
+ device_del(&evdev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
evdev->exist = 0;
if (evdev->open) {
input_flush_device(handle, NULL);
input_close_device(handle);
- wake_up_interruptible(&evdev->wait);
list_for_each_entry(client, &evdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- } else
- evdev_free(evdev);
+ wake_up_interruptible(&evdev->wait);
+ }
+
+ put_device(&evdev->dev);
}
static const struct input_device_id evdev_ids[] = {
diff --git a/drivers/input/misc/input-polldev.c b/drivers/input/input-polldev.c
index b773d4c756a..b773d4c756a 100644
--- a/drivers/input/misc/input-polldev.c
+++ b/drivers/input/input-polldev.c
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccd8abafcb7..75b4d2a83dd 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -442,7 +442,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
printk(KERN_ERR
"input: failed to attach handler %s to device %s, "
"error: %d\n",
- handler->name, kobject_name(&dev->cdev.kobj), error);
+ handler->name, kobject_name(&dev->dev.kobj), error);
return error;
}
@@ -527,7 +527,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
static int input_devices_seq_show(struct seq_file *seq, void *v)
{
struct input_dev *dev = container_of(v, struct input_dev, node);
- const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
struct input_handle *handle;
seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
@@ -682,15 +682,17 @@ static inline int input_proc_init(void) { return 0; }
static inline void input_proc_exit(void) { }
#endif
-#define INPUT_DEV_STRING_ATTR_SHOW(name) \
-static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- \
- return scnprintf(buf, PAGE_SIZE, "%s\n", \
- input_dev->name ? input_dev->name : ""); \
-} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
+#define INPUT_DEV_STRING_ATTR_SHOW(name) \
+static ssize_t input_dev_show_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ \
+ return scnprintf(buf, PAGE_SIZE, "%s\n", \
+ input_dev->name ? input_dev->name : ""); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys);
@@ -744,7 +746,9 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
return len;
}
-static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
+static ssize_t input_dev_show_modalias(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct input_dev *id = to_input_dev(dev);
ssize_t len;
@@ -753,13 +757,13 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
return min_t(int, len, PAGE_SIZE);
}
-static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
+static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
static struct attribute *input_dev_attrs[] = {
- &class_device_attr_name.attr,
- &class_device_attr_phys.attr,
- &class_device_attr_uniq.attr,
- &class_device_attr_modalias.attr,
+ &dev_attr_name.attr,
+ &dev_attr_phys.attr,
+ &dev_attr_uniq.attr,
+ &dev_attr_modalias.attr,
NULL
};
@@ -767,13 +771,15 @@ static struct attribute_group input_dev_attr_group = {
.attrs = input_dev_attrs,
};
-#define INPUT_DEV_ID_ATTR(name) \
-static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
-} \
-static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
+#define INPUT_DEV_ID_ATTR(name) \
+static ssize_t input_dev_show_id_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
INPUT_DEV_ID_ATTR(bustype);
INPUT_DEV_ID_ATTR(vendor);
@@ -781,10 +787,10 @@ INPUT_DEV_ID_ATTR(product);
INPUT_DEV_ID_ATTR(version);
static struct attribute *input_dev_id_attrs[] = {
- &class_device_attr_bustype.attr,
- &class_device_attr_vendor.attr,
- &class_device_attr_product.attr,
- &class_device_attr_version.attr,
+ &dev_attr_bustype.attr,
+ &dev_attr_vendor.attr,
+ &dev_attr_product.attr,
+ &dev_attr_version.attr,
NULL
};
@@ -813,15 +819,17 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
return len;
}
-#define INPUT_DEV_CAP_ATTR(ev, bm) \
-static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \
-{ \
- struct input_dev *input_dev = to_input_dev(dev); \
- int len = input_print_bitmap(buf, PAGE_SIZE, \
- input_dev->bm##bit, ev##_MAX, 1); \
- return min_t(int, len, PAGE_SIZE); \
-} \
-static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
+#define INPUT_DEV_CAP_ATTR(ev, bm) \
+static ssize_t input_dev_show_cap_##bm(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct input_dev *input_dev = to_input_dev(dev); \
+ int len = input_print_bitmap(buf, PAGE_SIZE, \
+ input_dev->bm##bit, ev##_MAX, 1); \
+ return min_t(int, len, PAGE_SIZE); \
+} \
+static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
INPUT_DEV_CAP_ATTR(EV, ev);
INPUT_DEV_CAP_ATTR(KEY, key);
@@ -834,15 +842,15 @@ INPUT_DEV_CAP_ATTR(FF, ff);
INPUT_DEV_CAP_ATTR(SW, sw);
static struct attribute *input_dev_caps_attrs[] = {
- &class_device_attr_ev.attr,
- &class_device_attr_key.attr,
- &class_device_attr_rel.attr,
- &class_device_attr_abs.attr,
- &class_device_attr_msc.attr,
- &class_device_attr_led.attr,
- &class_device_attr_snd.attr,
- &class_device_attr_ff.attr,
- &class_device_attr_sw.attr,
+ &dev_attr_ev.attr,
+ &dev_attr_key.attr,
+ &dev_attr_rel.attr,
+ &dev_attr_abs.attr,
+ &dev_attr_msc.attr,
+ &dev_attr_led.attr,
+ &dev_attr_snd.attr,
+ &dev_attr_ff.attr,
+ &dev_attr_sw.attr,
NULL
};
@@ -858,9 +866,9 @@ static struct attribute_group *input_dev_attr_groups[] = {
NULL
};
-static void input_dev_release(struct class_device *class_dev)
+static void input_dev_release(struct device *device)
{
- struct input_dev *dev = to_input_dev(class_dev);
+ struct input_dev *dev = to_input_dev(device);
input_ff_destroy(dev);
kfree(dev);
@@ -947,10 +955,10 @@ static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_ind
return err; \
} while (0)
-static int input_dev_uevent(struct class_device *cdev, char **envp,
+static int input_dev_uevent(struct device *device, char **envp,
int num_envp, char *buffer, int buffer_size)
{
- struct input_dev *dev = to_input_dev(cdev);
+ struct input_dev *dev = to_input_dev(device);
int i = 0;
int len = 0;
@@ -988,10 +996,14 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
return 0;
}
+static struct device_type input_dev_type = {
+ .groups = input_dev_attr_groups,
+ .release = input_dev_release,
+ .uevent = input_dev_uevent,
+};
+
struct class input_class = {
- .name = "input",
- .release = input_dev_release,
- .uevent = input_dev_uevent,
+ .name = "input",
};
EXPORT_SYMBOL_GPL(input_class);
@@ -1010,9 +1022,9 @@ struct input_dev *input_allocate_device(void)
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) {
- dev->cdev.class = &input_class;
- dev->cdev.groups = input_dev_attr_groups;
- class_device_initialize(&dev->cdev);
+ dev->dev.type = &input_dev_type;
+ dev->dev.class = &input_class;
+ device_initialize(&dev->dev);
mutex_init(&dev->mutex);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
@@ -1131,17 +1143,17 @@ int input_register_device(struct input_dev *dev)
list_add_tail(&dev->node, &input_dev_list);
- snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+ snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
- if (!dev->cdev.dev)
- dev->cdev.dev = dev->dev.parent;
+ if (dev->cdev.dev)
+ dev->dev.parent = dev->cdev.dev;
- error = class_device_add(&dev->cdev);
+ error = device_add(&dev->dev);
if (error)
return error;
- path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
+ path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s as %s\n",
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
kfree(path);
@@ -1173,7 +1185,7 @@ void input_unregister_device(struct input_dev *dev)
list_del_init(&dev->node);
- class_device_unregister(&dev->cdev);
+ device_unregister(&dev->dev);
input_wakeup_procfs_readers();
}
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 06f0541b24d..a9a0180bfd4 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,6 +43,8 @@ struct joydev {
struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
+ struct device dev;
+
struct js_corr corr[ABS_MAX + 1];
struct JS_DATA_SAVE_TYPE glue;
int nabs;
@@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
return retval < 0 ? retval : 0;
}
-static void joydev_free(struct joydev *joydev)
+static void joydev_free(struct device *dev)
{
+ struct joydev *joydev = container_of(dev, struct joydev, dev);
+
joydev_table[joydev->minor] = NULL;
kfree(joydev);
}
@@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--joydev->open) {
- if (joydev->exist)
- input_close_device(&joydev->handle);
- else
- joydev_free(joydev);
- }
+ if (!--joydev->open && joydev->exist)
+ input_close_device(&joydev->handle);
+
+ put_device(&joydev->dev);
return 0;
}
@@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file)
if (!joydev || !joydev->exist)
return -ENODEV;
+ get_device(&joydev->dev);
+
client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_joydev;
+ }
client->joydev = joydev;
list_add_tail(&client->node, &joydev->client_list);
if (!joydev->open++ && joydev->exist) {
error = input_open_device(&joydev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_joydev:
+ put_device(&joydev->dev);
+ return error;
}
static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct joydev *joydev;
- struct class_device *cdev;
- dev_t devt;
int i, j, t, minor;
int error;
@@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->handle.name = joydev->name;
joydev->handle.handler = handler;
joydev->handle.private = joydev;
- sprintf(joydev->name, "js%d", minor);
+ snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
for (i = 0; i < ABS_MAX + 1; i++)
if (test_bit(i, dev->absbit)) {
@@ -547,36 +555,30 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
}
- joydev_table[minor] = joydev;
-
- devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+ snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
+ "js%d", minor);
+ joydev->dev.class = &input_class;
+ joydev->dev.parent = &dev->dev;
+ joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
+ joydev->dev.release = joydev_free;
+ device_initialize(&joydev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, joydev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_joydev;
- }
+ joydev_table[minor] = joydev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, joydev->name);
+ error = device_add(&joydev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_joydev;
error = input_register_handle(&joydev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_joydev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_joydev:
+ device_del(&joydev->dev);
err_free_joydev:
- joydev_table[minor] = NULL;
- kfree(joydev);
+ put_device(&joydev->dev);
return error;
}
@@ -587,18 +589,18 @@ static void joydev_disconnect(struct input_handle *handle)
struct joydev_client *client;
input_unregister_handle(handle);
+ device_del(&joydev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
- class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
joydev->exist = 0;
if (joydev->open) {
input_close_device(handle);
- wake_up_interruptible(&joydev->wait);
list_for_each_entry(client, &joydev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- } else
- joydev_free(joydev);
+ wake_up_interruptible(&joydev->wait);
+ }
+
+ put_device(&joydev->dev);
}
static const struct input_device_id joydev_blacklist[] = {
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index b0023452ec9..12db72d83ea 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -268,4 +268,11 @@ config JOYSTICK_XPAD
To compile this driver as a module, choose M here: the
module will be called xpad.
+config JOYSTICK_XPAD_FF
+ bool "X-Box gamepad rumble support"
+ depends on JOYSTICK_XPAD && INPUT
+ select INPUT_FF_MEMLESS
+ ---help---
+ Say Y here if you want to take advantage of xbox 360 rumble features.
+
endif
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index 86ad1027e12..b069ee18e35 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -54,7 +54,7 @@ static struct db9_config db9_cfg[DB9_MAX_PORTS] __initdata;
module_param_array_named(dev, db9_cfg[0].args, int, &db9_cfg[0].nargs, 0);
MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
-module_param_array_named(dev2, db9_cfg[1].args, int, &db9_cfg[0].nargs, 0);
+module_param_array_named(dev2, db9_cfg[1].args, int, &db9_cfg[1].nargs, 0);
MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
module_param_array_named(dev3, db9_cfg[2].args, int, &db9_cfg[2].nargs, 0);
MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 555319e6378..4ed3a3eadf1 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -320,10 +320,10 @@ static int multiport_io(struct gameport* gameport, int sendflags, int sendcode,
static int dig_mode_start(struct gameport *gameport, u32 *packet)
{
- int i, seq_len = sizeof(init_seq)/sizeof(int);
+ int i;
int flags, tries = 0, bads = 0;
- for (i = 0; i < seq_len; i++) { /* Send magic sequence */
+ for (i = 0; i < ARRAY_SIZE(init_seq); i++) { /* Send magic sequence */
if (init_seq[i])
gameport_trigger(gameport);
udelay(GRIP_INIT_DELAY);
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 8c8cd95a698..244089c5265 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -8,6 +8,7 @@
* Ivan Hawkes <blackhawk@ivanhawkes.com>
* 2005 Dominic Cerquetti <binary1230@yahoo.com>
* 2006 Adam Buchbinder <adam.buchbinder@gmail.com>
+ * 2007 Jan Kratochvil <honza@jikos.cz>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -28,6 +29,7 @@
* - information from http://euc.jp/periphs/xbox-controller.ja.html
* - the iForce driver drivers/char/joystick/iforce.c
* - the skeleton-driver drivers/usb/usb-skeleton.c
+ * - Xbox 360 information http://www.free60.org/wiki/Gamepad
*
* Thanks to:
* - ITO Takayuki for providing essential xpad information on his website
@@ -88,6 +90,9 @@
#define MAP_DPAD_TO_AXES 1
#define MAP_DPAD_UNKNOWN -1
+#define XTYPE_XBOX 0
+#define XTYPE_XBOX360 1
+
static int dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
@@ -97,40 +102,42 @@ static const struct xpad_device {
u16 idProduct;
char *name;
u8 dpad_mapping;
+ u8 xtype;
} xpad_device[] = {
- { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES },
- { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS },
- { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES },
- { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES },
- { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES },
- { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES },
- { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES },
- { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS },
- { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS },
- { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES },
- { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES },
- { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES},
- { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES },
- { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES },
- { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES },
- { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES },
- { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES },
- { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS },
- { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS },
- { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES },
- { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN }
+ { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
+ { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
+ { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
+ { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_XBOX }
};
static const signed short xpad_btn[] = {
@@ -146,6 +153,12 @@ static const signed short xpad_btn_pad[] = {
-1 /* terminating entry */
};
+static const signed short xpad360_btn[] = { /* buttons for x360 controller */
+ BTN_TL, BTN_TR, /* Button LB/RB */
+ BTN_MODE, /* The big X button */
+ -1
+};
+
static const signed short xpad_abs[] = {
ABS_X, ABS_Y, /* left stick */
ABS_RX, ABS_RY, /* right stick */
@@ -159,8 +172,12 @@ static const signed short xpad_abs_pad[] = {
-1 /* terminating entry */
};
+/* Xbox 360 has a vendor-specific (sub)class, so we cannot match it with only
+ * USB_INTERFACE_INFO, more to that this device has 4 InterfaceProtocols,
+ * but we need only one of them. */
static struct usb_device_id xpad_table [] = {
{ USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */
+ { USB_DEVICE_INTERFACE_PROTOCOL(0x045e, 0x028e, 1) }, /* X-Box 360 controller */
{ }
};
@@ -174,9 +191,16 @@ struct usb_xpad {
unsigned char *idata; /* input data */
dma_addr_t idata_dma;
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+ struct urb *irq_out; /* urb for interrupt out report */
+ unsigned char *odata; /* output data */
+ dma_addr_t odata_dma;
+#endif
+
char phys[65]; /* physical device path */
int dpad_mapping; /* map d-pad to buttons or to axes */
+ int xtype; /* type of xbox device */
};
/*
@@ -212,8 +236,8 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
- input_report_key(dev, BTN_0, data[2] & 0x01); // up
- input_report_key(dev, BTN_1, data[2] & 0x02); // down
+ input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
+ input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
}
/* start/back buttons and stick press left/right */
@@ -235,6 +259,64 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
input_sync(dev);
}
+/*
+ * xpad360_process_packet
+ *
+ * Completes a request by converting the data into events for the
+ * input subsystem. It is version for xbox 360 controller
+ *
+ * The used report descriptor was taken from:
+ * http://www.free60.org/wiki/Gamepad
+ */
+
+static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
+{
+ struct input_dev *dev = xpad->dev;
+
+ /* digital pad */
+ if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
+ input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
+ input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
+ } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
+ /* dpad as buttons (right, left, down, up) */
+ input_report_key(dev, BTN_LEFT, data[2] & 0x04);
+ input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
+ input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
+ input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
+ }
+
+ /* start/back buttons */
+ input_report_key(dev, BTN_START, data[2] & 0x10);
+ input_report_key(dev, BTN_BACK, data[2] & 0x20);
+
+ /* stick press left/right */
+ input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
+ input_report_key(dev, BTN_THUMBR, data[2] & 0x80);
+
+ /* buttons A,B,X,Y,TL,TR and MODE */
+ input_report_key(dev, BTN_A, data[3] & 0x10);
+ input_report_key(dev, BTN_B, data[3] & 0x20);
+ input_report_key(dev, BTN_X, data[3] & 0x40);
+ input_report_key(dev, BTN_Y, data[3] & 0x80);
+ input_report_key(dev, BTN_TL, data[3] & 0x01);
+ input_report_key(dev, BTN_TR, data[3] & 0x02);
+ input_report_key(dev, BTN_MODE, data[3] & 0x04);
+
+ /* left stick */
+ input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6]));
+ input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8]));
+
+ /* right stick */
+ input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10]));
+ input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12]));
+
+ /* triggers left/right */
+ input_report_abs(dev, ABS_Z, data[4]);
+ input_report_abs(dev, ABS_RZ, data[5]);
+
+ input_sync(dev);
+}
+
static void xpad_irq_in(struct urb *urb)
{
struct usb_xpad *xpad = urb->context;
@@ -255,7 +337,10 @@ static void xpad_irq_in(struct urb *urb)
goto exit;
}
- xpad_process_packet(xpad, 0, xpad->idata);
+ if (xpad->xtype == XTYPE_XBOX360)
+ xpad360_process_packet(xpad, 0, xpad->idata);
+ else
+ xpad_process_packet(xpad, 0, xpad->idata);
exit:
retval = usb_submit_urb (urb, GFP_ATOMIC);
@@ -264,7 +349,114 @@ exit:
__FUNCTION__, retval);
}
-static int xpad_open (struct input_dev *dev)
+#ifdef CONFIG_JOYSTICK_XPAD_FF
+static void xpad_irq_out(struct urb *urb)
+{
+ int retval;
+
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ goto exit;
+ }
+
+exit:
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ err("%s - usb_submit_urb failed with result %d",
+ __FUNCTION__, retval);
+}
+
+static int xpad_play_effect(struct input_dev *dev, void *data,
+ struct ff_effect *effect)
+{
+ struct usb_xpad *xpad = input_get_drvdata(dev);
+
+ if (effect->type == FF_RUMBLE) {
+ __u16 strong = effect->u.rumble.strong_magnitude;
+ __u16 weak = effect->u.rumble.weak_magnitude;
+ xpad->odata[0] = 0x00;
+ xpad->odata[1] = 0x08;
+ xpad->odata[2] = 0x00;
+ xpad->odata[3] = strong / 256;
+ xpad->odata[4] = weak / 256;
+ xpad->odata[5] = 0x00;
+ xpad->odata[6] = 0x00;
+ xpad->odata[7] = 0x00;
+ usb_submit_urb(xpad->irq_out, GFP_KERNEL);
+ }
+
+ return 0;
+}
+
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad)
+{
+ struct usb_endpoint_descriptor *ep_irq_out;
+ int error = -ENOMEM;
+
+ if (xpad->xtype != XTYPE_XBOX360)
+ return 0;
+
+ xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
+ GFP_ATOMIC, &xpad->odata_dma );
+ if (!xpad->odata)
+ goto fail1;
+
+ xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
+ if (!xpad->irq_out)
+ goto fail2;
+
+ ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
+ usb_fill_int_urb(xpad->irq_out, xpad->udev,
+ usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
+ xpad->odata, XPAD_PKT_LEN,
+ xpad_irq_out, xpad, ep_irq_out->bInterval);
+ xpad->irq_out->transfer_dma = xpad->odata_dma;
+ xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
+
+ error = input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
+ if (error)
+ goto fail2;
+
+ return 0;
+
+ fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
+ fail1: return error;
+}
+
+static void xpad_stop_ff(struct usb_xpad *xpad)
+{
+ if (xpad->xtype == XTYPE_XBOX360)
+ usb_kill_urb(xpad->irq_out);
+}
+
+static void xpad_deinit_ff(struct usb_xpad *xpad)
+{
+ if (xpad->xtype == XTYPE_XBOX360) {
+ usb_free_urb(xpad->irq_out);
+ usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
+ xpad->odata, xpad->odata_dma);
+ }
+}
+
+#else
+static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
+static void xpad_stop_ff(struct usb_xpad *xpad) { }
+static void xpad_deinit_ff(struct usb_xpad *xpad) { }
+#endif
+
+static int xpad_open(struct input_dev *dev)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
@@ -275,11 +467,12 @@ static int xpad_open (struct input_dev *dev)
return 0;
}
-static void xpad_close (struct input_dev *dev)
+static void xpad_close(struct input_dev *dev)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
usb_kill_urb(xpad->irq_in);
+ xpad_stop_ff(xpad);
}
static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
@@ -335,6 +528,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->udev = udev;
xpad->dpad_mapping = xpad_device[i].dpad_mapping;
+ xpad->xtype = xpad_device[i].xtype;
if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
xpad->dpad_mapping = dpad_to_buttons;
xpad->dev = input_dev;
@@ -356,6 +550,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
/* set up buttons */
for (i = 0; xpad_btn[i] >= 0; i++)
set_bit(xpad_btn[i], input_dev->keybit);
+ if (xpad->xtype == XTYPE_XBOX360)
+ for (i = 0; xpad360_btn[i] >= 0; i++)
+ set_bit(xpad360_btn[i], input_dev->keybit);
if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
for (i = 0; xpad_btn_pad[i] >= 0; i++)
set_bit(xpad_btn_pad[i], input_dev->keybit);
@@ -367,6 +564,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
for (i = 0; xpad_abs_pad[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
+ error = xpad_init_ff(intf, xpad);
+ if (error)
+ goto fail2;
+
ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
usb_fill_int_urb(xpad->irq_in, udev,
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
@@ -396,10 +597,10 @@ static void xpad_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
if (xpad) {
- usb_kill_urb(xpad->irq_in);
input_unregister_device(xpad->dev);
+ xpad_deinit_ff(xpad);
usb_free_urb(xpad->irq_in);
- usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN,
+ usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
xpad->idata, xpad->idata_dma);
kfree(xpad);
}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index bd707b86c11..c97d5eb0075 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -164,6 +164,9 @@ config KEYBOARD_AMIGA
To compile this driver as a module, choose M here: the
module will be called amikbd.
+config ATARI_KBD_CORE
+ bool
+
config KEYBOARD_ATARI
tristate "Atari keyboard"
depends on ATARI
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index be1fe46cd30..41fc3d03b6e 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -89,7 +89,7 @@ static unsigned char atkbd_set2_keycode[512] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
- 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
+ 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142,
157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
@@ -111,7 +111,7 @@ static unsigned char atkbd_set3_keycode[512] = {
82, 83, 80, 76, 77, 72, 69, 98, 0, 96, 81, 0, 78, 73, 55,183,
184,185,186,187, 74, 94, 92, 93, 0, 0, 0,125,126,127,112, 0,
- 0,139,150,163,165,115,152,150,166,140,160,154,113,114,167,168,
+ 0,139,172,163,165,115,152,172,166,140,160,154,113,114,167,168,
148,149,147,140
};
@@ -219,7 +219,8 @@ struct atkbd {
unsigned long time;
unsigned long err_count;
- struct work_struct event_work;
+ struct delayed_work event_work;
+ unsigned long event_jiffies;
struct mutex event_mutex;
unsigned long event_mask;
};
@@ -408,9 +409,10 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
goto out;
case ATKBD_RET_ACK:
case ATKBD_RET_NAK:
- printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
- "Some program might be trying access hardware directly.\n",
- data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
+ if (printk_ratelimit())
+ printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
+ "Some program might be trying access hardware directly.\n",
+ data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
goto out;
case ATKBD_RET_HANGEUL:
case ATKBD_RET_HANJA:
@@ -565,7 +567,7 @@ static int atkbd_set_leds(struct atkbd *atkbd)
static void atkbd_event_work(struct work_struct *work)
{
- struct atkbd *atkbd = container_of(work, struct atkbd, event_work);
+ struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
mutex_lock(&atkbd->event_mutex);
@@ -579,12 +581,30 @@ static void atkbd_event_work(struct work_struct *work)
}
/*
+ * Schedule switch for execution. We need to throttle requests,
+ * otherwise keyboard may become unresponsive.
+ */
+static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)
+{
+ unsigned long delay = msecs_to_jiffies(50);
+
+ if (time_after(jiffies, atkbd->event_jiffies + delay))
+ delay = 0;
+
+ atkbd->event_jiffies = jiffies;
+ set_bit(event_bit, &atkbd->event_mask);
+ wmb();
+ schedule_delayed_work(&atkbd->event_work, delay);
+}
+
+/*
* Event callback from the input module. Events that change the state of
* the hardware are processed here. If action can not be performed in
* interrupt context it is offloaded to atkbd_event_work.
*/
-static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int atkbd_event(struct input_dev *dev,
+ unsigned int type, unsigned int code, int value)
{
struct atkbd *atkbd = input_get_drvdata(dev);
@@ -594,19 +614,12 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
switch (type) {
case EV_LED:
- set_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask);
- wmb();
- schedule_work(&atkbd->event_work);
+ atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
return 0;
case EV_REP:
-
- if (!atkbd->softrepeat) {
- set_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask);
- wmb();
- schedule_work(&atkbd->event_work);
- }
-
+ if (!atkbd->softrepeat)
+ atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
return 0;
}
@@ -940,7 +953,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
- INIT_WORK(&atkbd->event_work, atkbd_event_work);
+ INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
mutex_init(&atkbd->event_mutex);
switch (serio->id.type) {
diff --git a/drivers/input/keyboard/pxa27x_keyboard.c b/drivers/input/keyboard/pxa27x_keyboard.c
index 06eaf766d9d..ebe5eacf299 100644
--- a/drivers/input/keyboard/pxa27x_keyboard.c
+++ b/drivers/input/keyboard/pxa27x_keyboard.c
@@ -104,7 +104,7 @@ static int pxakbd_open(struct input_dev *dev)
KPREC = 0x7F;
/* Enable unit clock */
- pxa_set_cken(CKEN19_KEYPAD, 1);
+ pxa_set_cken(CKEN_KEYPAD, 1);
return 0;
}
@@ -112,7 +112,7 @@ static int pxakbd_open(struct input_dev *dev)
static void pxakbd_close(struct input_dev *dev)
{
/* Disable clock unit */
- pxa_set_cken(CKEN19_KEYPAD, 0);
+ pxa_set_cken(CKEN_KEYPAD, 0);
}
#ifdef CONFIG_PM
@@ -140,7 +140,7 @@ static int pxakbd_resume(struct platform_device *pdev)
KPREC = pdata->reg_kprec;
/* Enable unit clock */
- pxa_set_cken(CKEN19_KEYPAD, 1);
+ pxa_set_cken(CKEN_KEYPAD, 1);
}
mutex_unlock(&input_dev->mutex);
@@ -185,7 +185,7 @@ static int __devinit pxakbd_probe(struct platform_device *pdev)
DRIVER_NAME, pdev);
if (error) {
printk(KERN_ERR "Cannot request keypad IRQ\n");
- pxa_set_cken(CKEN19_KEYPAD, 0);
+ pxa_set_cken(CKEN_KEYPAD, 0);
goto err_free_dev;
}
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 842a7b4d16f..9b26574f146 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -65,9 +65,13 @@ config INPUT_COBALT_BTNS
config INPUT_WISTRON_BTNS
tristate "x86 Wistron laptop button interface"
depends on X86 && !X86_64
+ select INPUT_POLLDEV
+ select NEW_LEDS
+ select LEDS_CLASS
help
Say Y here for support of Winstron laptop button interface, used on
- laptops of various brands, including Acer and Fujitsu-Siemens.
+ laptops of various brands, including Acer and Fujitsu-Siemens. If
+ available, mail and wifi leds will be controlable via /sys/class/leds.
To compile this driver as a module, choose M here: the module will
be called wistron_btns.
@@ -170,17 +174,6 @@ config INPUT_UINPUT
To compile this driver as a module, choose M here: the
module will be called uinput.
-config INPUT_POLLDEV
- tristate "Polled input device skeleton"
- help
- Say Y here if you are using a driver for an input
- device that periodically polls hardware state. This
- option is only useful for out-of-tree drivers since
- in-tree drivers select it automatically.
-
- To compile this driver as a module, choose M here: the
- module will be called input-polldev.
-
config HP_SDC_RTC
tristate "HP SDC Real Time Clock"
depends on GSC || HP300
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 8b2f7799e25..3585b503841 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -4,7 +4,6 @@
# Each configuration option enables a list of files.
-obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 961aad7a047..60121f10f8d 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -20,37 +20,31 @@
#include <linux/io.h>
#include <linux/dmi.h>
#include <linux/init.h>
-#include <linux/input.h>
+#include <linux/input-polldev.h>
#include <linux/interrupt.h>
+#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#include <linux/module.h>
#include <linux/preempt.h>
#include <linux/string.h>
-#include <linux/timer.h>
#include <linux/types.h>
#include <linux/platform_device.h>
+#include <linux/leds.h>
-/*
- * Number of attempts to read data from queue per poll;
- * the queue can hold up to 31 entries
- */
-#define MAX_POLL_ITERATIONS 64
-
-#define POLL_FREQUENCY 10 /* Number of polls per second */
-
-#if POLL_FREQUENCY > HZ
-#error "POLL_FREQUENCY too high"
-#endif
+/* How often we poll keys - msecs */
+#define POLL_INTERVAL_DEFAULT 500 /* when idle */
+#define POLL_INTERVAL_BURST 100 /* when a key was recently pressed */
/* BIOS subsystem IDs */
#define WIFI 0x35
#define BLUETOOTH 0x34
+#define MAIL_LED 0x31
MODULE_AUTHOR("Miloslav Trmac <mitr@volny.cz>");
MODULE_DESCRIPTION("Wistron laptop button driver");
MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.2");
+MODULE_VERSION("0.3");
static int force; /* = 0; */
module_param(force, bool, 0);
@@ -248,9 +242,10 @@ enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
#define FE_WIFI_LED 0x02
#define FE_UNTESTED 0x80
-static const struct key_entry *keymap; /* = NULL; Current key map */
+static struct key_entry *keymap; /* = NULL; Current key map */
static int have_wifi;
static int have_bluetooth;
+static int have_leds;
static int __init dmi_matched(struct dmi_system_id *dmi)
{
@@ -263,6 +258,8 @@ static int __init dmi_matched(struct dmi_system_id *dmi)
else if (key->type == KE_BLUETOOTH)
have_bluetooth = 1;
}
+ have_leds = key->code & (FE_MAIL_LED | FE_WIFI_LED);
+
return 1;
}
@@ -966,118 +963,163 @@ static int __init select_keymap(void)
/* Input layer interface */
-static struct input_dev *input_dev;
+static struct input_polled_dev *wistron_idev;
+static unsigned long jiffies_last_press;
+static int wifi_enabled;
+static int bluetooth_enabled;
-static int __devinit setup_input_dev(void)
+static void report_key(struct input_dev *dev, unsigned int keycode)
{
- const struct key_entry *key;
- int error;
+ input_report_key(dev, keycode, 1);
+ input_sync(dev);
+ input_report_key(dev, keycode, 0);
+ input_sync(dev);
+}
- input_dev = input_allocate_device();
- if (!input_dev)
- return -ENOMEM;
+static void report_switch(struct input_dev *dev, unsigned int code, int value)
+{
+ input_report_switch(dev, code, value);
+ input_sync(dev);
+}
- input_dev->name = "Wistron laptop buttons";
- input_dev->phys = "wistron/input0";
- input_dev->id.bustype = BUS_HOST;
- input_dev->cdev.dev = &wistron_device->dev;
- for (key = keymap; key->type != KE_END; key++) {
- switch (key->type) {
- case KE_KEY:
- set_bit(EV_KEY, input_dev->evbit);
- set_bit(key->keycode, input_dev->keybit);
- break;
+ /* led management */
+static void wistron_mail_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ bios_set_state(MAIL_LED, (value != LED_OFF) ? 1 : 0);
+}
- case KE_SW:
- set_bit(EV_SW, input_dev->evbit);
- set_bit(key->sw.code, input_dev->swbit);
- break;
+/* same as setting up wifi card, but for laptops on which the led is managed */
+static void wistron_wifi_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ bios_set_state(WIFI, (value != LED_OFF) ? 1 : 0);
+}
- default:
- ;
- }
- }
+static struct led_classdev wistron_mail_led = {
+ .name = "mail:green",
+ .brightness_set = wistron_mail_led_set,
+};
- /* reads information flags on KE_END */
- if (key->code & FE_UNTESTED)
- printk(KERN_WARNING "Untested laptop multimedia keys, "
- "please report success or failure to eric.piel"
- "@tremplin-utc.net\n");
+static struct led_classdev wistron_wifi_led = {
+ .name = "wifi:red",
+ .brightness_set = wistron_wifi_led_set,
+};
- error = input_register_device(input_dev);
- if (error) {
- input_free_device(input_dev);
- return error;
+static void __devinit wistron_led_init(struct device *parent)
+{
+ if (have_leds & FE_WIFI_LED) {
+ u16 wifi = bios_get_default_setting(WIFI);
+ if (wifi & 1) {
+ wistron_wifi_led.brightness = (wifi & 2) ? LED_FULL : LED_OFF;
+ if (led_classdev_register(parent, &wistron_wifi_led))
+ have_leds &= ~FE_WIFI_LED;
+ else
+ bios_set_state(WIFI, wistron_wifi_led.brightness);
+
+ } else
+ have_leds &= ~FE_WIFI_LED;
}
- return 0;
+ if (have_leds & FE_MAIL_LED) {
+ /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */
+ wistron_mail_led.brightness = LED_OFF;
+ if (led_classdev_register(parent, &wistron_mail_led))
+ have_leds &= ~FE_MAIL_LED;
+ else
+ bios_set_state(MAIL_LED, wistron_mail_led.brightness);
+ }
}
-static void report_key(unsigned keycode)
+static void __devexit wistron_led_remove(void)
{
- input_report_key(input_dev, keycode, 1);
- input_sync(input_dev);
- input_report_key(input_dev, keycode, 0);
- input_sync(input_dev);
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_unregister(&wistron_mail_led);
+
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_unregister(&wistron_wifi_led);
}
-static void report_switch(unsigned code, int value)
+static inline void wistron_led_suspend(void)
{
- input_report_switch(input_dev, code, value);
- input_sync(input_dev);
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_suspend(&wistron_mail_led);
+
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_suspend(&wistron_wifi_led);
}
- /* Driver core */
+static inline void wistron_led_resume(void)
+{
+ if (have_leds & FE_MAIL_LED)
+ led_classdev_resume(&wistron_mail_led);
-static int wifi_enabled;
-static int bluetooth_enabled;
+ if (have_leds & FE_WIFI_LED)
+ led_classdev_resume(&wistron_wifi_led);
+}
+
+static struct key_entry *wistron_get_entry_by_scancode(int code)
+{
+ struct key_entry *key;
-static void poll_bios(unsigned long);
+ for (key = keymap; key->type != KE_END; key++)
+ if (code == key->code)
+ return key;
-static struct timer_list poll_timer = TIMER_INITIALIZER(poll_bios, 0, 0);
+ return NULL;
+}
-static void handle_key(u8 code)
+static struct key_entry *wistron_get_entry_by_keycode(int keycode)
{
- const struct key_entry *key;
+ struct key_entry *key;
- for (key = keymap; key->type != KE_END; key++) {
- if (code == key->code) {
- switch (key->type) {
- case KE_KEY:
- report_key(key->keycode);
- break;
+ for (key = keymap; key->type != KE_END; key++)
+ if (key->type == KE_KEY && keycode == key->keycode)
+ return key;
- case KE_SW:
- report_switch(key->sw.code, key->sw.value);
- break;
+ return NULL;
+}
- case KE_WIFI:
- if (have_wifi) {
- wifi_enabled = !wifi_enabled;
- bios_set_state(WIFI, wifi_enabled);
- }
- break;
+static void handle_key(u8 code)
+{
+ const struct key_entry *key = wistron_get_entry_by_scancode(code);
- case KE_BLUETOOTH:
- if (have_bluetooth) {
- bluetooth_enabled = !bluetooth_enabled;
- bios_set_state(BLUETOOTH, bluetooth_enabled);
- }
- break;
+ if (key) {
+ switch (key->type) {
+ case KE_KEY:
+ report_key(wistron_idev->input, key->keycode);
+ break;
- case KE_END:
- break;
- default:
- BUG();
+ case KE_SW:
+ report_switch(wistron_idev->input,
+ key->sw.code, key->sw.value);
+ break;
+
+ case KE_WIFI:
+ if (have_wifi) {
+ wifi_enabled = !wifi_enabled;
+ bios_set_state(WIFI, wifi_enabled);
+ }
+ break;
+
+ case KE_BLUETOOTH:
+ if (have_bluetooth) {
+ bluetooth_enabled = !bluetooth_enabled;
+ bios_set_state(BLUETOOTH, bluetooth_enabled);
}
- return;
+ break;
+
+ default:
+ BUG();
}
- }
- printk(KERN_NOTICE "wistron_btns: Unknown key code %02X\n", code);
+ jiffies_last_press = jiffies;
+ } else
+ printk(KERN_NOTICE
+ "wistron_btns: Unknown key code %02X\n", code);
}
-static void poll_bios(unsigned long discard)
+static void poll_bios(bool discard)
{
u8 qlen;
u16 val;
@@ -1090,15 +1132,118 @@ static void poll_bios(unsigned long discard)
if (val != 0 && !discard)
handle_key((u8)val);
}
+}
+
+static void wistron_flush(struct input_polled_dev *dev)
+{
+ /* Flush stale event queue */
+ poll_bios(true);
+}
+
+static void wistron_poll(struct input_polled_dev *dev)
+{
+ poll_bios(false);
+
+ /* Increase poll frequency if user is currently pressing keys (< 2s ago) */
+ if (time_before(jiffies, jiffies_last_press + 2 * HZ))
+ dev->poll_interval = POLL_INTERVAL_BURST;
+ else
+ dev->poll_interval = POLL_INTERVAL_DEFAULT;
+}
+
+static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+{
+ const struct key_entry *key = wistron_get_entry_by_scancode(scancode);
+
+ if (key && key->type == KE_KEY) {
+ *keycode = key->keycode;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
+{
+ struct key_entry *key;
+ int old_keycode;
+
+ if (keycode < 0 || keycode > KEY_MAX)
+ return -EINVAL;
+
+ key = wistron_get_entry_by_scancode(scancode);
+ if (key && key->type == KE_KEY) {
+ old_keycode = key->keycode;
+ key->keycode = keycode;
+ set_bit(keycode, dev->keybit);
+ if (!wistron_get_entry_by_keycode(old_keycode))
+ clear_bit(old_keycode, dev->keybit);
+ return 0;
+ }
- mod_timer(&poll_timer, jiffies + HZ / POLL_FREQUENCY);
+ return -EINVAL;
}
+static int __devinit setup_input_dev(void)
+{
+ const struct key_entry *key;
+ struct input_dev *input_dev;
+ int error;
+
+ wistron_idev = input_allocate_polled_device();
+ if (!wistron_idev)
+ return -ENOMEM;
+
+ wistron_idev->flush = wistron_flush;
+ wistron_idev->poll = wistron_poll;
+ wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT;
+
+ input_dev = wistron_idev->input;
+ input_dev->name = "Wistron laptop buttons";
+ input_dev->phys = "wistron/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->dev.parent = &wistron_device->dev;
+
+ input_dev->getkeycode = wistron_getkeycode;
+ input_dev->setkeycode = wistron_setkeycode;
+
+ for (key = keymap; key->type != KE_END; key++) {
+ switch (key->type) {
+ case KE_KEY:
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(key->keycode, input_dev->keybit);
+ break;
+
+ case KE_SW:
+ set_bit(EV_SW, input_dev->evbit);
+ set_bit(key->sw.code, input_dev->swbit);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* reads information flags on KE_END */
+ if (key->code & FE_UNTESTED)
+ printk(KERN_WARNING "Untested laptop multimedia keys, "
+ "please report success or failure to eric.piel"
+ "@tremplin-utc.net\n");
+
+ error = input_register_polled_device(wistron_idev);
+ if (error) {
+ input_free_polled_device(wistron_idev);
+ return error;
+ }
+
+ return 0;
+}
+
+/* Driver core */
+
static int __devinit wistron_probe(struct platform_device *dev)
{
- int err = setup_input_dev();
- if (err)
- return err;
+ int err;
bios_attach();
cmos_address = bios_get_cmos_address();
@@ -1125,15 +1270,21 @@ static int __devinit wistron_probe(struct platform_device *dev)
bios_set_state(BLUETOOTH, bluetooth_enabled);
}
- poll_bios(1); /* Flush stale event queue and arm timer */
+ wistron_led_init(&dev->dev);
+ err = setup_input_dev();
+ if (err) {
+ bios_detach();
+ return err;
+ }
return 0;
}
static int __devexit wistron_remove(struct platform_device *dev)
{
- del_timer_sync(&poll_timer);
- input_unregister_device(input_dev);
+ wistron_led_remove();
+ input_unregister_polled_device(wistron_idev);
+ input_free_polled_device(wistron_idev);
bios_detach();
return 0;
@@ -1142,14 +1293,13 @@ static int __devexit wistron_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int wistron_suspend(struct platform_device *dev, pm_message_t state)
{
- del_timer_sync(&poll_timer);
-
if (have_wifi)
bios_set_state(WIFI, 0);
if (have_bluetooth)
bios_set_state(BLUETOOTH, 0);
+ wistron_led_suspend();
return 0;
}
@@ -1161,7 +1311,8 @@ static int wistron_resume(struct platform_device *dev)
if (have_bluetooth)
bios_set_state(BLUETOOTH, bluetooth_enabled);
- poll_bios(1);
+ wistron_led_resume();
+ poll_bios(true);
return 0;
}
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index eb0167e9f0c..7bbea097cda 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -48,7 +48,7 @@ config MOUSE_PS2_ALPS
If unsure, say Y.
config MOUSE_PS2_LOGIPS2PP
- bool "Logictech PS/2++ mouse protocol extension" if EMBEDDED
+ bool "Logitech PS/2++ mouse protocol extension" if EMBEDDED
default y
depends on MOUSE_PS2
help
@@ -216,4 +216,20 @@ config MOUSE_HIL
help
Say Y here to support HIL pointers.
+config MOUSE_GPIO
+ tristate "GPIO mouse"
+ depends on GENERIC_GPIO
+ select INPUT_POLLDEV
+ help
+ This driver simulates a mouse on GPIO lines of various CPUs (and some
+ other chips).
+
+ Say Y here if your device has buttons or a simple joystick connected
+ directly to GPIO lines. Your board-specific setup logic must also
+ provide a platform device and platform data saying which GPIOs are
+ used.
+
+ To compile this driver as a module, choose M here: the
+ module will be called gpio_mouse.
+
endif
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index aa4ba878533..9e6e3633082 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
+obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
psmouse-objs := psmouse-base.o synaptics.o
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
new file mode 100644
index 00000000000..0936d6ba015
--- /dev/null
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -0,0 +1,196 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/gpio_mouse.h>
+
+#include <asm/gpio.h>
+
+/*
+ * Timer function which is run every scan_ms ms when the device is opened.
+ * The dev input varaible is set to the the input_dev pointer.
+ */
+static void gpio_mouse_scan(struct input_polled_dev *dev)
+{
+ struct gpio_mouse_platform_data *gpio = dev->private;
+ struct input_dev *input = dev->input;
+ int x, y;
+
+ if (gpio->bleft >= 0)
+ input_report_key(input, BTN_LEFT,
+ gpio_get_value(gpio->bleft) ^ gpio->polarity);
+ if (gpio->bmiddle >= 0)
+ input_report_key(input, BTN_MIDDLE,
+ gpio_get_value(gpio->bmiddle) ^ gpio->polarity);
+ if (gpio->bright >= 0)
+ input_report_key(input, BTN_RIGHT,
+ gpio_get_value(gpio->bright) ^ gpio->polarity);
+
+ x = (gpio_get_value(gpio->right) ^ gpio->polarity)
+ - (gpio_get_value(gpio->left) ^ gpio->polarity);
+ y = (gpio_get_value(gpio->down) ^ gpio->polarity)
+ - (gpio_get_value(gpio->up) ^ gpio->polarity);
+
+ input_report_rel(input, REL_X, x);
+ input_report_rel(input, REL_Y, y);
+ input_sync(input);
+}
+
+static int __init gpio_mouse_probe(struct platform_device *pdev)
+{
+ struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
+ struct input_polled_dev *input_poll;
+ struct input_dev *input;
+ int pin, i;
+ int error;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data\n");
+ error = -ENXIO;
+ goto out;
+ }
+
+ if (pdata->scan_ms < 0) {
+ dev_err(&pdev->dev, "invalid scan time\n");
+ error = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+ pin = pdata->pins[i];
+
+ if (pin < 0) {
+
+ if (i <= GPIO_MOUSE_PIN_RIGHT) {
+ /* Mouse direction is required. */
+ dev_err(&pdev->dev,
+ "missing GPIO for directions\n");
+ error = -EINVAL;
+ goto out_free_gpios;
+ }
+
+ if (i == GPIO_MOUSE_PIN_BLEFT)
+ dev_dbg(&pdev->dev, "no left button defined\n");
+
+ } else {
+ error = gpio_request(pin, "gpio_mouse");
+ if (error) {
+ dev_err(&pdev->dev, "fail %d pin (%d idx)\n",
+ pin, i);
+ goto out_free_gpios;
+ }
+
+ gpio_direction_input(pin);
+ }
+ }
+
+ input_poll = input_allocate_polled_device();
+ if (!input_poll) {
+ dev_err(&pdev->dev, "not enough memory for input device\n");
+ error = -ENOMEM;
+ goto out_free_gpios;
+ }
+
+ platform_set_drvdata(pdev, input_poll);
+
+ /* set input-polldev handlers */
+ input_poll->private = pdata;
+ input_poll->poll = gpio_mouse_scan;
+ input_poll->poll_interval = pdata->scan_ms;
+
+ input = input_poll->input;
+ input->name = pdev->name;
+ input->id.bustype = BUS_HOST;
+ input->dev.parent = &pdev->dev;
+
+ input_set_capability(input, EV_REL, REL_X);
+ input_set_capability(input, EV_REL, REL_Y);
+ if (pdata->bleft >= 0)
+ input_set_capability(input, EV_KEY, BTN_LEFT);
+ if (pdata->bmiddle >= 0)
+ input_set_capability(input, EV_KEY, BTN_MIDDLE);
+ if (pdata->bright >= 0)
+ input_set_capability(input, EV_KEY, BTN_RIGHT);
+
+ error = input_register_polled_device(input_poll);
+ if (error) {
+ dev_err(&pdev->dev, "could not register input device\n");
+ goto out_free_polldev;
+ }
+
+ dev_dbg(&pdev->dev, "%d ms scan time, buttons: %s%s%s\n",
+ pdata->scan_ms,
+ pdata->bleft < 0 ? "" : "left ",
+ pdata->bmiddle < 0 ? "" : "middle ",
+ pdata->bright < 0 ? "" : "right");
+
+ return 0;
+
+ out_free_polldev:
+ input_free_polled_device(input_poll);
+ platform_set_drvdata(pdev, NULL);
+
+ out_free_gpios:
+ while (--i >= 0) {
+ pin = pdata->pins[i];
+ if (pin)
+ gpio_free(pin);
+ }
+ out:
+ return error;
+}
+
+static int __devexit gpio_mouse_remove(struct platform_device *pdev)
+{
+ struct input_polled_dev *input = platform_get_drvdata(pdev);
+ struct gpio_mouse_platform_data *pdata = input->private;
+ int pin, i;
+
+ input_unregister_polled_device(input);
+ input_free_polled_device(input);
+
+ for (i = 0; i < GPIO_MOUSE_PIN_MAX; i++) {
+ pin = pdata->pins[i];
+ if (pin >= 0)
+ gpio_free(pin);
+ }
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+struct platform_driver gpio_mouse_device_driver = {
+ .remove = __devexit_p(gpio_mouse_remove),
+ .driver = {
+ .name = "gpio_mouse",
+ }
+};
+
+static int __init gpio_mouse_init(void)
+{
+ return platform_driver_probe(&gpio_mouse_device_driver,
+ gpio_mouse_probe);
+}
+module_init(gpio_mouse_init);
+
+static void __exit gpio_mouse_exit(void)
+{
+ platform_driver_unregister(&gpio_mouse_device_driver);
+}
+module_exit(gpio_mouse_exit);
+
+MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_DESCRIPTION("GPIO mouse driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index f15f695777f..b9f0fb2530e 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -178,6 +178,15 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
}
/*
+ * Cortron PS2 Trackball reports SIDE button on the 4th bit of the first
+ * byte.
+ */
+ if (psmouse->type == PSMOUSE_CORTRON) {
+ input_report_key(dev, BTN_SIDE, (packet[0] >> 3) & 1);
+ packet[0] |= 0x08;
+ }
+
+/*
* Generic PS/2 Mouse
*/
@@ -539,6 +548,20 @@ static int ps2bare_detect(struct psmouse *psmouse, int set_properties)
return 0;
}
+/*
+ * Cortron PS/2 protocol detection. There's no special way to detect it, so it
+ * must be forced by sysfs protocol writing.
+ */
+static int cortron_detect(struct psmouse *psmouse, int set_properties)
+{
+ if (set_properties) {
+ psmouse->vendor = "Cortron";
+ psmouse->name = "PS/2 Trackball";
+ set_bit(BTN_SIDE, psmouse->dev->keybit);
+ }
+
+ return 0;
+}
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
@@ -740,6 +763,12 @@ static const struct psmouse_protocol psmouse_protocols[] = {
},
#endif
{
+ .type = PSMOUSE_CORTRON,
+ .name = "CortronPS/2",
+ .alias = "cortps",
+ .detect = cortron_detect,
+ },
+ {
.type = PSMOUSE_AUTO,
.name = "auto",
.alias = "any",
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 3964e8acbc5..1317bdd8cc7 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -88,6 +88,7 @@ enum psmouse_type {
PSMOUSE_LIFEBOOK,
PSMOUSE_TRACKPOINT,
PSMOUSE_TOUCHKIT_PS2,
+ PSMOUSE_CORTRON,
PSMOUSE_AUTO /* This one should always be last */
};
@@ -118,7 +119,6 @@ static struct psmouse_attribute psmouse_attr_##_name = { \
.attr = { \
.name = __stringify(_name), \
.mode = _mode, \
- .owner = THIS_MODULE, \
}, \
.show = psmouse_attr_show_helper, \
.store = psmouse_attr_set_helper, \
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 8675f950939..9173916b8be 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -64,6 +64,7 @@ struct mousedev {
wait_queue_head_t wait;
struct list_head client_list;
struct input_handle handle;
+ struct device dev;
struct list_head mixdev_node;
int mixdev_open;
@@ -112,7 +113,7 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
static struct input_handler mousedev_handler;
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
-static struct mousedev mousedev_mix;
+static struct mousedev *mousedev_mix;
static LIST_HEAD(mousedev_mix_list);
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
@@ -218,10 +219,10 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
if (value) {
set_bit(index, &mousedev->packet.buttons);
- set_bit(index, &mousedev_mix.packet.buttons);
+ set_bit(index, &mousedev_mix->packet.buttons);
} else {
clear_bit(index, &mousedev->packet.buttons);
- clear_bit(index, &mousedev_mix.packet.buttons);
+ clear_bit(index, &mousedev_mix->packet.buttons);
}
}
@@ -287,11 +288,11 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
* motion packet so we won't mess current position.
*/
set_bit(0, &mousedev->packet.buttons);
- set_bit(0, &mousedev_mix.packet.buttons);
- mousedev_notify_readers(mousedev, &mousedev_mix.packet);
- mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
+ set_bit(0, &mousedev_mix->packet.buttons);
+ mousedev_notify_readers(mousedev, &mousedev_mix->packet);
+ mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
clear_bit(0, &mousedev->packet.buttons);
- clear_bit(0, &mousedev_mix.packet.buttons);
+ clear_bit(0, &mousedev_mix->packet.buttons);
}
mousedev->touch = mousedev->pkt_count = 0;
mousedev->frac_dx = 0;
@@ -343,7 +344,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
}
mousedev_notify_readers(mousedev, &mousedev->packet);
- mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
+ mousedev_notify_readers(mousedev_mix, &mousedev->packet);
mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
mousedev->packet.abs_event = 0;
@@ -362,8 +363,10 @@ static int mousedev_fasync(int fd, struct file *file, int on)
return retval < 0 ? retval : 0;
}
-static void mousedev_free(struct mousedev *mousedev)
+static void mousedev_free(struct device *dev)
{
+ struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
+
mousedev_table[mousedev->minor] = NULL;
kfree(mousedev);
}
@@ -372,15 +375,16 @@ static int mixdev_add_device(struct mousedev *mousedev)
{
int error;
- if (mousedev_mix.open) {
+ if (mousedev_mix->open) {
error = input_open_device(&mousedev->handle);
if (error)
return error;
mousedev->open++;
- mousedev->mixdev_open++;
+ mousedev->mixdev_open = 1;
}
+ get_device(&mousedev->dev);
list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
return 0;
@@ -395,36 +399,40 @@ static void mixdev_remove_device(struct mousedev *mousedev)
}
list_del_init(&mousedev->mixdev_node);
+ put_device(&mousedev->dev);
}
static void mixdev_open_devices(void)
{
struct mousedev *mousedev;
+ if (mousedev_mix->open++)
+ return;
+
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
- if (mousedev->exist && !mousedev->open) {
- if (input_open_device(&mousedev->handle))
- continue;
+ if (!mousedev->mixdev_open) {
+ if (!mousedev->open && mousedev->exist)
+ if (input_open_device(&mousedev->handle))
+ continue;
mousedev->open++;
- mousedev->mixdev_open++;
+ mousedev->mixdev_open = 1;
}
}
}
static void mixdev_close_devices(void)
{
- struct mousedev *mousedev, *next;
+ struct mousedev *mousedev;
- list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
+ if (--mousedev_mix->open)
+ return;
+
+ list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
if (mousedev->mixdev_open) {
mousedev->mixdev_open = 0;
- if (!--mousedev->open) {
- if (mousedev->exist)
- input_close_device(&mousedev->handle);
- else
- mousedev_free(mousedev);
- }
+ if (!--mousedev->open && mousedev->exist)
+ input_close_device(&mousedev->handle);
}
}
}
@@ -439,14 +447,12 @@ static int mousedev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--mousedev->open) {
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_close_devices();
- else if (mousedev->exist)
- input_close_device(&mousedev->handle);
- else
- mousedev_free(mousedev);
- }
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_close_devices();
+ else if (!--mousedev->open && mousedev->exist)
+ input_close_device(&mousedev->handle);
+
+ put_device(&mousedev->dev);
return 0;
}
@@ -473,9 +479,13 @@ static int mousedev_open(struct inode *inode, struct file *file)
if (!mousedev)
return -ENODEV;
+ get_device(&mousedev->dev);
+
client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_mousedev;
+ }
spin_lock_init(&client->packet_lock);
client->pos_x = xres / 2;
@@ -483,21 +493,23 @@ static int mousedev_open(struct inode *inode, struct file *file)
client->mousedev = mousedev;
list_add_tail(&client->node, &mousedev->client_list);
- if (!mousedev->open++) {
- if (mousedev->minor == MOUSEDEV_MIX)
- mixdev_open_devices();
- else if (mousedev->exist) {
- error = input_open_device(&mousedev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
- }
+ if (mousedev->minor == MOUSEDEV_MIX)
+ mixdev_open_devices();
+ else if (!mousedev->open++ && mousedev->exist) {
+ error = input_open_device(&mousedev->handle);
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_mousedev:
+ put_device(&mousedev->dev);
+ return error;
}
static inline int mousedev_limit_delta(int delta, int limit)
@@ -680,57 +692,96 @@ static const struct file_operations mousedev_fops = {
.fasync = mousedev_fasync,
};
-static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
- const struct input_device_id *id)
+static struct mousedev *mousedev_create(struct input_dev *dev,
+ struct input_handler *handler,
+ int minor)
{
struct mousedev *mousedev;
- struct class_device *cdev;
- dev_t devt;
- int minor;
int error;
- for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
- if (minor == MOUSEDEV_MINORS) {
- printk(KERN_ERR "mousedev: no more free mousedev devices\n");
- return -ENFILE;
- }
-
mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
- if (!mousedev)
- return -ENOMEM;
+ if (!mousedev) {
+ error = -ENOMEM;
+ goto err_out;
+ }
INIT_LIST_HEAD(&mousedev->client_list);
INIT_LIST_HEAD(&mousedev->mixdev_node);
init_waitqueue_head(&mousedev->wait);
+ if (minor == MOUSEDEV_MIX)
+ strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
+ else
+ snprintf(mousedev->name, sizeof(mousedev->name),
+ "mouse%d", minor);
+
mousedev->minor = minor;
mousedev->exist = 1;
mousedev->handle.dev = dev;
mousedev->handle.name = mousedev->name;
mousedev->handle.handler = handler;
mousedev->handle.private = mousedev;
- sprintf(mousedev->name, "mouse%d", minor);
- mousedev_table[minor] = mousedev;
+ strlcpy(mousedev->dev.bus_id, mousedev->name,
+ sizeof(mousedev->dev.bus_id));
+ mousedev->dev.class = &input_class;
+ if (dev)
+ mousedev->dev.parent = &dev->dev;
+ mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
+ mousedev->dev.release = mousedev_free;
+ device_initialize(&mousedev->dev);
- devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+ mousedev_table[minor] = mousedev;
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, mousedev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
+ error = device_add(&mousedev->dev);
+ if (error)
goto err_free_mousedev;
+
+ return mousedev;
+
+ err_free_mousedev:
+ put_device(&mousedev->dev);
+ err_out:
+ return ERR_PTR(error);
+}
+
+static void mousedev_destroy(struct mousedev *mousedev)
+{
+ struct mousedev_client *client;
+
+ device_del(&mousedev->dev);
+ mousedev->exist = 0;
+
+ if (mousedev->open) {
+ input_close_device(&mousedev->handle);
+ list_for_each_entry(client, &mousedev->client_list, node)
+ kill_fasync(&client->fasync, SIGIO, POLL_HUP);
+ wake_up_interruptible(&mousedev->wait);
}
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, mousedev->name);
- if (error)
- goto err_cdev_destroy;
+ put_device(&mousedev->dev);
+}
+
+static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct mousedev *mousedev;
+ int minor;
+ int error;
+
+ for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
+ if (minor == MOUSEDEV_MINORS) {
+ printk(KERN_ERR "mousedev: no more free mousedev devices\n");
+ return -ENFILE;
+ }
+
+ mousedev = mousedev_create(dev, handler, minor);
+ if (IS_ERR(mousedev))
+ return PTR_ERR(mousedev);
error = input_register_handle(&mousedev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_mousedev;
error = mixdev_add_device(mousedev);
if (error)
@@ -740,37 +791,18 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
err_unregister_handle:
input_unregister_handle(&mousedev->handle);
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
- err_free_mousedev:
- mousedev_table[minor] = NULL;
- kfree(mousedev);
+ err_delete_mousedev:
+ device_unregister(&mousedev->dev);
return error;
}
static void mousedev_disconnect(struct input_handle *handle)
{
struct mousedev *mousedev = handle->private;
- struct mousedev_client *client;
-
- input_unregister_handle(handle);
-
- sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
- mousedev->exist = 0;
mixdev_remove_device(mousedev);
-
- if (mousedev->open) {
- input_close_device(handle);
- wake_up_interruptible(&mousedev->wait);
- list_for_each_entry(client, &mousedev->client_list, node)
- kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- } else
- mousedev_free(mousedev);
+ input_unregister_handle(handle);
+ mousedev_destroy(mousedev);
}
static const struct input_device_id mousedev_ids[] = {
@@ -822,25 +854,16 @@ static int psaux_registered;
static int __init mousedev_init(void)
{
- struct class_device *cdev;
int error;
+ mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
+ if (IS_ERR(mousedev_mix))
+ return PTR_ERR(mousedev_mix);
+
error = input_register_handler(&mousedev_handler);
- if (error)
+ if (error) {
+ mousedev_destroy(mousedev_mix);
return error;
-
- memset(&mousedev_mix, 0, sizeof(struct mousedev));
- INIT_LIST_HEAD(&mousedev_mix.client_list);
- init_waitqueue_head(&mousedev_mix.wait);
- mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
- mousedev_mix.exist = 1;
- mousedev_mix.minor = MOUSEDEV_MIX;
-
- cdev = class_device_create(&input_class, NULL,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
- if (IS_ERR(cdev)) {
- input_unregister_handler(&mousedev_handler);
- return PTR_ERR(cdev);
}
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
@@ -863,9 +886,8 @@ static void __exit mousedev_exit(void)
if (psaux_registered)
misc_deregister(&psaux_mouse);
#endif
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
input_unregister_handler(&mousedev_handler);
+ mousedev_destroy(mousedev_mix);
}
module_init(mousedev_init);
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 6858bc58f0f..4fca1e7f267 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -69,6 +69,15 @@ static inline void i8042_write_command(int val)
static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
{
+ /* AUX LOOP command does not raise AUX IRQ */
+ .ident = "ASUS P65UP5",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"),
+ DMI_MATCH(DMI_BOARD_VERSION, "REV 2.X"),
+ },
+ },
+ {
.ident = "Compaq Proliant 8500",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
@@ -92,6 +101,15 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
},
},
+ {
+ /* AUX LOOP does not work properly */
+ .ident = "ULI EV4873",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ULI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+ },
+ },
{ }
};
@@ -182,6 +200,17 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
},
},
{
+ /*
+ * Like DV4017EA does not raise AUXERR for errors on MUX ports.
+ */
+ .ident = "HP Pavilion ZT1000",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
+ },
+ },
+ {
.ident = "Toshiba P10",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 5895202b972..a8f3bc1dff2 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -769,8 +769,10 @@ static int serio_driver_remove(struct device *dev)
static void serio_cleanup(struct serio *serio)
{
+ mutex_lock(&serio->drv_mutex);
if (serio->drv && serio->drv->cleanup)
serio->drv->cleanup(serio);
+ mutex_unlock(&serio->drv_mutex);
}
static void serio_shutdown(struct device *dev)
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 887357666c6..0403622ae26 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -160,7 +160,7 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, size_t cou
{
struct serio_raw_list *list = file->private_data;
struct serio_raw *serio_raw = list->serio_raw;
- char c;
+ char uninitialized_var(c);
ssize_t retval = 0;
if (!serio_raw->serio)
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c
index cc0a498763d..94683f58c9e 100644
--- a/drivers/input/tablet/aiptek.c
+++ b/drivers/input/tablet/aiptek.c
@@ -82,8 +82,8 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.5 (May-15-2004)"
-#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio"
+#define DRIVER_VERSION "v2.3 (May 2, 2007)"
+#define DRIVER_AUTHOR "Bryan W. Headley/Chris Atenasio/Cedric Brun/Rene van Paassen"
#define DRIVER_DESC "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)"
/*
@@ -112,7 +112,7 @@
* (returned as Report 3 - absolute coordinates from the mouse)
*
* bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
- * byte0 0 0 0 0 0 0 1 0
+ * byte0 0 0 0 0 0 0 1 1
* byte1 X7 X6 X5 X4 X3 X2 X1 X0
* byte2 X15 X14 X13 X12 X11 X10 X9 X8
* byte3 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
@@ -134,7 +134,7 @@
* (returned as Report 5 - macrokeys from the mouse)
*
* bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
- * byte0 0 0 0 0 0 1 0 0
+ * byte0 0 0 0 0 0 1 0 1
* byte1 0 0 0 BS2 BS Tip IR DV
* byte2 0 0 0 0 0 0 1 0
* byte3 0 0 0 K4 K3 K2 K1 K0
@@ -218,15 +218,9 @@
#define AIPTEK_WHEEL_DISABLE (-10101)
/* ToolCode values, which BTW are 0x140 .. 0x14f
- * We have things set up such that if TOOL_BUTTON_FIRED_BIT is
- * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx.
- *
- * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will
- * get reset.
+ * We have things set up such that if the tool button has changed,
+ * the tools get reset.
*/
-#define TOOL_BUTTON(x) ((x) & 0x14f)
-#define TOOL_BUTTON_FIRED(x) ((x) & 0x200)
-#define TOOL_BUTTON_FIRED_BIT 0x200
/* toolMode codes
*/
#define AIPTEK_TOOL_BUTTON_PEN_MODE BTN_TOOL_PEN
@@ -264,9 +258,9 @@
/* Mouse button programming
*/
-#define AIPTEK_MOUSE_LEFT_BUTTON 0x01
-#define AIPTEK_MOUSE_RIGHT_BUTTON 0x02
-#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x04
+#define AIPTEK_MOUSE_LEFT_BUTTON 0x04
+#define AIPTEK_MOUSE_RIGHT_BUTTON 0x08
+#define AIPTEK_MOUSE_MIDDLE_BUTTON 0x10
/* Stylus button programming
*/
@@ -294,7 +288,6 @@ struct aiptek_features {
int modelCode; /* Tablet model code (not unique) */
int firmwareCode; /* prom/eeprom version */
char usbPath[64 + 1]; /* device's physical usb path */
- char inputPath[64 + 1]; /* input device path */
};
struct aiptek_settings {
@@ -327,9 +320,32 @@ struct aiptek {
int inDelay; /* jitter: in jitter delay? */
unsigned long endDelay; /* jitter: time when delay ends */
int previousJitterable; /* jitterable prev value */
+
+ int lastMacro; /* macro key to reset */
+ int previousToolMode; /* pen, pencil, brush, etc. tool */
unsigned char *data; /* incoming packet data */
};
+static const int eventTypes[] = {
+ EV_KEY, EV_ABS, EV_REL, EV_MSC,
+};
+
+static const int absEvents[] = {
+ ABS_X, ABS_Y, ABS_PRESSURE, ABS_TILT_X, ABS_TILT_Y,
+ ABS_WHEEL, ABS_MISC,
+};
+
+static const int relEvents[] = {
+ REL_X, REL_Y, REL_WHEEL,
+};
+
+static const int buttonEvents[] = {
+ BTN_LEFT, BTN_RIGHT, BTN_MIDDLE,
+ BTN_TOOL_PEN, BTN_TOOL_RUBBER, BTN_TOOL_PENCIL, BTN_TOOL_AIRBRUSH,
+ BTN_TOOL_BRUSH, BTN_TOOL_MOUSE, BTN_TOOL_LENS, BTN_TOUCH,
+ BTN_STYLUS, BTN_STYLUS2,
+};
+
/*
* Permit easy lookup of keyboard events to send, versus
* the bitmap which comes from the tablet. This hides the
@@ -345,23 +361,39 @@ static const int macroKeyEvents[] = {
};
/***********************************************************************
- * Relative reports deliver values in 2's complement format to
- * deal with negative offsets.
+ * Map values to strings and back. Every map shoudl have the following
+ * as its last element: { NULL, AIPTEK_INVALID_VALUE }.
*/
-static int aiptek_convert_from_2s_complement(unsigned char c)
+#define AIPTEK_INVALID_VALUE -1
+
+struct aiptek_map {
+ const char *string;
+ int value;
+};
+
+static int map_str_to_val(const struct aiptek_map *map, const char *str, size_t count)
{
- int ret;
- unsigned char b = c;
- int negate = 0;
+ const struct aiptek_map *p;
- if ((b & 0x80) != 0) {
- b = ~b;
- b--;
- negate = 1;
- }
- ret = b;
- ret = (negate == 1) ? -ret : ret;
- return ret;
+ if (str[count - 1] == '\n')
+ count--;
+
+ for (p = map; p->string; p++)
+ if (!strncmp(str, p->string, count))
+ return p->value;
+
+ return AIPTEK_INVALID_VALUE;
+}
+
+static const char *map_val_to_str(const struct aiptek_map *map, int val)
+{
+ const struct aiptek_map *p;
+
+ for (p = map; p->value != AIPTEK_INVALID_VALUE; p++)
+ if (val == p->value)
+ return p->string;
+
+ return "unknown";
}
/***********************************************************************
@@ -385,6 +417,9 @@ static int aiptek_convert_from_2s_complement(unsigned char c)
* Proximity. Why two events? I thought it interesting to know if the
* Proximity event occurred while the tablet was in absolute or relative
* mode.
+ * Update: REL_MISC proved not to be such a good idea. With REL_MISC you
+ * get an event transmitted each time. ABS_MISC works better, since it
+ * can be set and re-set. Thus, only using ABS_MISC from now on.
*
* Other tablets use the notion of a certain minimum stylus pressure
* to infer proximity. While that could have been done, that is yet
@@ -441,8 +476,8 @@ static void aiptek_irq(struct urb *urb)
aiptek->diagnostic =
AIPTEK_DIAGNOSTIC_SENDING_RELATIVE_IN_ABSOLUTE;
} else {
- x = aiptek_convert_from_2s_complement(data[2]);
- y = aiptek_convert_from_2s_complement(data[3]);
+ x = (signed char) data[2];
+ y = (signed char) data[3];
/* jitterable keeps track of whether any button has been pressed.
* We're also using it to remap the physical mouse button mask
@@ -451,18 +486,20 @@ static void aiptek_irq(struct urb *urb)
* that a non-zero value indicates that one or more
* mouse button was pressed.)
*/
- jitterable = data[5] & 0x07;
+ jitterable = data[1] & 0x07;
- left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
- right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
- middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
+ left = (data[1] & aiptek->curSetting.mouseButtonLeft >> 2) != 0 ? 1 : 0;
+ right = (data[1] & aiptek->curSetting.mouseButtonRight >> 2) != 0 ? 1 : 0;
+ middle = (data[1] & aiptek->curSetting.mouseButtonMiddle >> 2) != 0 ? 1 : 0;
input_report_key(inputdev, BTN_LEFT, left);
input_report_key(inputdev, BTN_MIDDLE, middle);
input_report_key(inputdev, BTN_RIGHT, right);
+
+ input_report_abs(inputdev, ABS_MISC,
+ 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
input_report_rel(inputdev, REL_X, x);
input_report_rel(inputdev, REL_Y, y);
- input_report_rel(inputdev, REL_MISC, 1 | AIPTEK_REPORT_TOOL_UNKNOWN);
/* Wheel support is in the form of a single-event
* firing.
@@ -472,6 +509,11 @@ static void aiptek_irq(struct urb *urb)
aiptek->curSetting.wheel);
aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
}
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -489,8 +531,8 @@ static void aiptek_irq(struct urb *urb)
y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
- p = (data[5] & 0x01) != 0 ? 1 : 0;
- dv = (data[5] & 0x02) != 0 ? 1 : 0;
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
tip = (data[5] & 0x04) != 0 ? 1 : 0;
/* Use jitterable to re-arrange button masks
@@ -505,16 +547,18 @@ static void aiptek_irq(struct urb *urb)
* all 'bad' reports...
*/
if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED
- (aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
if (p != 0) {
@@ -550,6 +594,11 @@ static void aiptek_irq(struct urb *urb)
}
}
input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS);
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -568,23 +617,25 @@ static void aiptek_irq(struct urb *urb)
jitterable = data[5] & 0x1c;
- p = (data[5] & 0x01) != 0 ? 1 : 0;
- dv = (data[5] & 0x02) != 0 ? 1 : 0;
+ dv = (data[5] & 0x01) != 0 ? 1 : 0;
+ p = (data[5] & 0x02) != 0 ? 1 : 0;
left = (data[5] & aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
right = (data[5] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED
- (aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
if (p != 0) {
@@ -605,7 +656,12 @@ static void aiptek_irq(struct urb *urb)
aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
}
}
- input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+ input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+ if (aiptek->lastMacro != -1) {
+ input_report_key(inputdev,
+ macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
input_sync(inputdev);
}
}
@@ -615,98 +671,83 @@ static void aiptek_irq(struct urb *urb)
else if (data[0] == 4) {
jitterable = data[1] & 0x18;
- p = (data[1] & 0x01) != 0 ? 1 : 0;
- dv = (data[1] & 0x02) != 0 ? 1 : 0;
+ dv = (data[1] & 0x01) != 0 ? 1 : 0;
+ p = (data[1] & 0x02) != 0 ? 1 : 0;
tip = (data[1] & 0x04) != 0 ? 1 : 0;
bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0;
pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
- macro = data[3];
+ macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
- if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ if (dv) {
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
+ aiptek->curSetting.toolMode,
1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
+ }
- if (p != 0) {
- input_report_key(inputdev, BTN_TOUCH, tip);
- input_report_key(inputdev, BTN_STYLUS, bs);
- input_report_key(inputdev, BTN_STYLUS2, pck);
- input_report_abs(inputdev, ABS_PRESSURE, z);
- }
+ if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+ input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
- /* For safety, we're sending key 'break' codes for the
- * neighboring macro keys.
- */
- if (macro > 0) {
- input_report_key(inputdev,
- macroKeyEvents[macro - 1], 0);
- }
- if (macro < 25) {
- input_report_key(inputdev,
- macroKeyEvents[macro + 1], 0);
- }
- input_report_key(inputdev, macroKeyEvents[macro], p);
- input_report_abs(inputdev, ABS_MISC,
- p | AIPTEK_REPORT_TOOL_STYLUS);
- input_sync(inputdev);
+ if (macro != -1 && macro != aiptek->lastMacro) {
+ input_report_key(inputdev, macroKeyEvents[macro], 1);
+ aiptek->lastMacro = macro;
}
+ input_report_abs(inputdev, ABS_MISC,
+ p | AIPTEK_REPORT_TOOL_STYLUS);
+ input_sync(inputdev);
}
/* Report 5s come from the macro keys when pressed by mouse
*/
else if (data[0] == 5) {
jitterable = data[1] & 0x1c;
- p = (data[1] & 0x01) != 0 ? 1 : 0;
- dv = (data[1] & 0x02) != 0 ? 1 : 0;
+ dv = (data[1] & 0x01) != 0 ? 1 : 0;
+ p = (data[1] & 0x02) != 0 ? 1 : 0;
left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
- macro = data[3];
+ macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0;
- if (dv != 0) {
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
+ if (dv) {
+ /* If the selected tool changed, reset the old
+ * tool key, and set the new one.
*/
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
- input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.toolMode),
- 1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
- }
-
- if (p != 0) {
- input_report_key(inputdev, BTN_LEFT, left);
- input_report_key(inputdev, BTN_MIDDLE, middle);
- input_report_key(inputdev, BTN_RIGHT, right);
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
+ input_report_key(inputdev,
+ aiptek->curSetting.toolMode, 1);
+ aiptek->previousToolMode = aiptek->curSetting.toolMode;
}
+ }
- /* For safety, we're sending key 'break' codes for the
- * neighboring macro keys.
- */
- if (macro > 0) {
- input_report_key(inputdev,
- macroKeyEvents[macro - 1], 0);
- }
- if (macro < 25) {
- input_report_key(inputdev,
- macroKeyEvents[macro + 1], 0);
- }
+ if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+ input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+ aiptek->lastMacro = -1;
+ }
+ if (macro != -1 && macro != aiptek->lastMacro) {
input_report_key(inputdev, macroKeyEvents[macro], 1);
- input_report_rel(inputdev, ABS_MISC,
- p | AIPTEK_REPORT_TOOL_MOUSE);
- input_sync(inputdev);
+ aiptek->lastMacro = macro;
}
+
+ input_report_abs(inputdev, ABS_MISC,
+ p | AIPTEK_REPORT_TOOL_MOUSE);
+ input_sync(inputdev);
}
/* We have no idea which tool can generate a report 6. Theoretically,
* neither need to, having been given reports 4 & 5 for such use.
@@ -725,15 +766,18 @@ static void aiptek_irq(struct urb *urb)
0);
}
- /* If we've not already sent a tool_button_?? code, do
- * so now. Then set FIRED_BIT so it won't be resent unless
- * the user forces FIRED_BIT off.
- */
- if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+ /* If the selected tool changed, reset the old
+ tool key, and set the new one.
+ */
+ if (aiptek->previousToolMode !=
+ aiptek->curSetting.toolMode) {
+ input_report_key(inputdev,
+ aiptek->previousToolMode, 0);
input_report_key(inputdev,
- TOOL_BUTTON(aiptek->curSetting.
- toolMode), 1);
- aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+ aiptek->curSetting.toolMode,
+ 1);
+ aiptek->previousToolMode =
+ aiptek->curSetting.toolMode;
}
input_report_key(inputdev, macroKeyEvents[macro], 1);
@@ -1007,9 +1051,6 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%dx%d\n",
aiptek->inputdev->absmax[ABS_X] + 1,
aiptek->inputdev->absmax[ABS_Y] + 1);
@@ -1024,117 +1065,35 @@ static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr
static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL);
/***********************************************************************
- * support routines for the 'product_id' file
- */
-static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "0x%04x\n",
- aiptek->inputdev->id.product);
-}
-
-static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor_id' file
- */
-static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->inputdev->id.vendor);
-}
-
-static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
-
-/***********************************************************************
- * support routines for the 'vendor' file
- */
-static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
- int retval;
-
- if (aiptek == NULL)
- return 0;
-
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer);
- return retval;
-}
-
-static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL);
-
-/***********************************************************************
- * support routines for the 'product' file
- */
-static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
- int retval;
-
- if (aiptek == NULL)
- return 0;
-
- retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product);
- return retval;
-}
-
-static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL);
-
-/***********************************************************************
* support routines for the 'pointer_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+static struct aiptek_map pointer_mode_map[] = {
+ { "stylus", AIPTEK_POINTER_ONLY_STYLUS_MODE },
+ { "mouse", AIPTEK_POINTER_ONLY_MOUSE_MODE },
+ { "either", AIPTEK_POINTER_EITHER_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.pointerMode) {
- case AIPTEK_POINTER_ONLY_STYLUS_MODE:
- s = "stylus";
- break;
-
- case AIPTEK_POINTER_ONLY_MOUSE_MODE:
- s = "mouse";
- break;
-
- case AIPTEK_POINTER_EITHER_MODE:
- s = "either";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(pointer_mode_map,
+ aiptek->curSetting.pointerMode));
}
static ssize_t
store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(pointer_mode_map, buf, count);
- if (strcmp(buf, "stylus") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_POINTER_ONLY_STYLUS_MODE;
- } else if (strcmp(buf, "mouse") == 0) {
- aiptek->newSetting.pointerMode = AIPTEK_POINTER_ONLY_MOUSE_MODE;
- } else if (strcmp(buf, "either") == 0) {
- aiptek->newSetting.pointerMode = AIPTEK_POINTER_EITHER_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+
+ aiptek->newSetting.pointerMode = new_mode;
return count;
}
@@ -1146,44 +1105,32 @@ static DEVICE_ATTR(pointer_mode,
* support routines for the 'coordinate_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+
+static struct aiptek_map coordinate_mode_map[] = {
+ { "absolute", AIPTEK_COORDINATE_ABSOLUTE_MODE },
+ { "relative", AIPTEK_COORDINATE_RELATIVE_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.coordinateMode) {
- case AIPTEK_COORDINATE_ABSOLUTE_MODE:
- s = "absolute";
- break;
-
- case AIPTEK_COORDINATE_RELATIVE_MODE:
- s = "relative";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(coordinate_mode_map,
+ aiptek->curSetting.coordinateMode));
}
static ssize_t
store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(coordinate_mode_map, buf, count);
- if (strcmp(buf, "absolute") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_COORDINATE_ABSOLUTE_MODE;
- } else if (strcmp(buf, "relative") == 0) {
- aiptek->newSetting.pointerMode =
- AIPTEK_COORDINATE_RELATIVE_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+
+ aiptek->newSetting.coordinateMode = new_mode;
return count;
}
@@ -1195,73 +1142,37 @@ static DEVICE_ATTR(coordinate_mode,
* support routines for the 'tool_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
+
+static struct aiptek_map tool_mode_map[] = {
+ { "mouse", AIPTEK_TOOL_BUTTON_MOUSE_MODE },
+ { "eraser", AIPTEK_TOOL_BUTTON_ERASER_MODE },
+ { "pencil", AIPTEK_TOOL_BUTTON_PENCIL_MODE },
+ { "pen", AIPTEK_TOOL_BUTTON_PEN_MODE },
+ { "brush", AIPTEK_TOOL_BUTTON_BRUSH_MODE },
+ { "airbrush", AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE },
+ { "lens", AIPTEK_TOOL_BUTTON_LENS_MODE },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (TOOL_BUTTON(aiptek->curSetting.toolMode)) {
- case AIPTEK_TOOL_BUTTON_MOUSE_MODE:
- s = "mouse";
- break;
-
- case AIPTEK_TOOL_BUTTON_ERASER_MODE:
- s = "eraser";
- break;
-
- case AIPTEK_TOOL_BUTTON_PENCIL_MODE:
- s = "pencil";
- break;
-
- case AIPTEK_TOOL_BUTTON_PEN_MODE:
- s = "pen";
- break;
-
- case AIPTEK_TOOL_BUTTON_BRUSH_MODE:
- s = "brush";
- break;
-
- case AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE:
- s = "airbrush";
- break;
-
- case AIPTEK_TOOL_BUTTON_LENS_MODE:
- s = "lens";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(tool_mode_map,
+ aiptek->curSetting.toolMode));
}
static ssize_t
store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
+ int new_mode = map_str_to_val(tool_mode_map, buf, count);
- if (strcmp(buf, "mouse") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_MOUSE_MODE;
- } else if (strcmp(buf, "eraser") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_ERASER_MODE;
- } else if (strcmp(buf, "pencil") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PENCIL_MODE;
- } else if (strcmp(buf, "pen") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_PEN_MODE;
- } else if (strcmp(buf, "brush") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_BRUSH_MODE;
- } else if (strcmp(buf, "airbrush") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_AIRBRUSH_MODE;
- } else if (strcmp(buf, "lens") == 0) {
- aiptek->newSetting.toolMode = AIPTEK_TOOL_BUTTON_LENS_MODE;
- }
+ if (new_mode == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
+ aiptek->newSetting.toolMode = new_mode;
return count;
}
@@ -1277,9 +1188,6 @@ static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.xTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1294,9 +1202,6 @@ store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char
struct aiptek *aiptek = dev_get_drvdata(dev);
int x;
- if (aiptek == NULL)
- return 0;
-
if (strcmp(buf, "disable") == 0) {
aiptek->newSetting.xTilt = AIPTEK_TILT_DISABLE;
} else {
@@ -1319,9 +1224,6 @@ static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.yTilt == AIPTEK_TILT_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1336,9 +1238,6 @@ store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char
struct aiptek *aiptek = dev_get_drvdata(dev);
int y;
- if (aiptek == NULL)
- return 0;
-
if (strcmp(buf, "disable") == 0) {
aiptek->newSetting.yTilt = AIPTEK_TILT_DISABLE;
} else {
@@ -1361,9 +1260,6 @@ static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribut
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%d\n", aiptek->curSetting.jitterDelay);
}
@@ -1372,9 +1268,6 @@ store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.jitterDelay = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1391,9 +1284,6 @@ static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_at
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%d\n",
aiptek->curSetting.programmableDelay);
}
@@ -1403,9 +1293,6 @@ store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr,
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.programmableDelay = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1415,23 +1302,6 @@ static DEVICE_ATTR(delay,
show_tabletProgrammableDelay, store_tabletProgrammableDelay);
/***********************************************************************
- * support routines for the 'input_path' file. Note that this file
- * only displays current setting.
- */
-static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
- return snprintf(buf, PAGE_SIZE, "/dev/input/%s\n",
- aiptek->features.inputPath);
-}
-
-static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL);
-
-/***********************************************************************
* support routines for the 'event_count' file. Note that this file
* only displays current setting.
*/
@@ -1439,9 +1309,6 @@ static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attri
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%ld\n", aiptek->eventCount);
}
@@ -1456,9 +1323,6 @@ static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_at
struct aiptek *aiptek = dev_get_drvdata(dev);
char *retMsg;
- if (aiptek == NULL)
- return 0;
-
switch (aiptek->diagnostic) {
case AIPTEK_DIAGNOSTIC_NA:
retMsg = "no errors\n";
@@ -1493,45 +1357,32 @@ static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL);
* support routines for the 'stylus_upper' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
+static struct aiptek_map stylus_button_map[] = {
+ { "upper", AIPTEK_STYLUS_UPPER_BUTTON },
+ { "lower", AIPTEK_STYLUS_LOWER_BUTTON },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.stylusButtonUpper) {
- case AIPTEK_STYLUS_UPPER_BUTTON:
- s = "upper";
- break;
-
- case AIPTEK_STYLUS_LOWER_BUTTON:
- s = "lower";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(stylus_button_map,
+ aiptek->curSetting.stylusButtonUpper));
}
static ssize_t
store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(stylus_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "upper") == 0) {
- aiptek->newSetting.stylusButtonUpper =
- AIPTEK_STYLUS_UPPER_BUTTON;
- } else if (strcmp(buf, "lower") == 0) {
- aiptek->newSetting.stylusButtonUpper =
- AIPTEK_STYLUS_LOWER_BUTTON;
- }
+ aiptek->newSetting.stylusButtonUpper = new_button;
return count;
}
@@ -1543,45 +1394,26 @@ static DEVICE_ATTR(stylus_upper,
* support routines for the 'stylus_lower' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.stylusButtonLower) {
- case AIPTEK_STYLUS_UPPER_BUTTON:
- s = "upper";
- break;
-
- case AIPTEK_STYLUS_LOWER_BUTTON:
- s = "lower";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(stylus_button_map,
+ aiptek->curSetting.stylusButtonLower));
}
static ssize_t
store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(stylus_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "upper") == 0) {
- aiptek->newSetting.stylusButtonLower =
- AIPTEK_STYLUS_UPPER_BUTTON;
- } else if (strcmp(buf, "lower") == 0) {
- aiptek->newSetting.stylusButtonLower =
- AIPTEK_STYLUS_LOWER_BUTTON;
- }
+ aiptek->newSetting.stylusButtonLower = new_button;
return count;
}
@@ -1593,49 +1425,33 @@ static DEVICE_ATTR(stylus_lower,
* support routines for the 'mouse_left' file. Note that this file
* both displays current setting and allows for setting changing.
*/
+
+static struct aiptek_map mouse_button_map[] = {
+ { "left", AIPTEK_MOUSE_LEFT_BUTTON },
+ { "middle", AIPTEK_MOUSE_MIDDLE_BUTTON },
+ { "right", AIPTEK_MOUSE_RIGHT_BUTTON },
+ { NULL, AIPTEK_INVALID_VALUE }
+};
+
static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonLeft) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
-
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonLeft));
}
static ssize_t
store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonLeft = AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonLeft = new_button;
return count;
}
@@ -1650,48 +1466,22 @@ static DEVICE_ATTR(mouse_left,
static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonMiddle) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
-
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonMiddle));
}
static ssize_t
store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonMiddle = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonMiddle =
- AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonMiddle =
- AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonMiddle = new_button;
return count;
}
@@ -1706,47 +1496,22 @@ static DEVICE_ATTR(mouse_middle,
static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- char *s;
-
- if (aiptek == NULL)
- return 0;
-
- switch (aiptek->curSetting.mouseButtonRight) {
- case AIPTEK_MOUSE_LEFT_BUTTON:
- s = "left";
- break;
-
- case AIPTEK_MOUSE_MIDDLE_BUTTON:
- s = "middle";
- break;
- case AIPTEK_MOUSE_RIGHT_BUTTON:
- s = "right";
- break;
-
- default:
- s = "unknown";
- break;
- }
- return snprintf(buf, PAGE_SIZE, "%s\n", s);
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ map_val_to_str(mouse_button_map,
+ aiptek->curSetting.mouseButtonRight));
}
static ssize_t
store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
+ int new_button = map_str_to_val(mouse_button_map, buf, count);
- if (aiptek == NULL)
- return 0;
+ if (new_button == AIPTEK_INVALID_VALUE)
+ return -EINVAL;
- if (strcmp(buf, "left") == 0) {
- aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_LEFT_BUTTON;
- } else if (strcmp(buf, "middle") == 0) {
- aiptek->newSetting.mouseButtonRight =
- AIPTEK_MOUSE_MIDDLE_BUTTON;
- } else if (strcmp(buf, "right") == 0) {
- aiptek->newSetting.mouseButtonRight = AIPTEK_MOUSE_RIGHT_BUTTON;
- }
+ aiptek->newSetting.mouseButtonRight = new_button;
return count;
}
@@ -1762,9 +1527,6 @@ static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *att
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
if (aiptek->curSetting.wheel == AIPTEK_WHEEL_DISABLE) {
return snprintf(buf, PAGE_SIZE, "disable\n");
} else {
@@ -1778,9 +1540,6 @@ store_tabletWheel(struct device *dev, struct device_attribute *attr, const char
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
aiptek->newSetting.wheel = (int)simple_strtol(buf, NULL, 10);
return count;
}
@@ -1794,11 +1553,6 @@ static DEVICE_ATTR(wheel,
*/
static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct aiptek *aiptek = dev_get_drvdata(dev);
-
- if (aiptek == NULL)
- return 0;
-
/* There is nothing useful to display, so a one-line manual
* is in order...
*/
@@ -1811,9 +1565,6 @@ store_tabletExecute(struct device *dev, struct device_attribute *attr, const cha
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
/* We do not care what you write to this file. Merely the action
* of writing to this file triggers a tablet reprogramming.
*/
@@ -1837,9 +1588,6 @@ static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *a
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.odmCode);
}
@@ -1853,9 +1601,6 @@ static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "0x%04x\n", aiptek->features.modelCode);
}
@@ -1869,86 +1614,39 @@ static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *at
{
struct aiptek *aiptek = dev_get_drvdata(dev);
- if (aiptek == NULL)
- return 0;
-
return snprintf(buf, PAGE_SIZE, "%04x\n",
aiptek->features.firmwareCode);
}
static DEVICE_ATTR(firmware_code, S_IRUGO, show_firmwareCode, NULL);
-/***********************************************************************
- * This routine removes all existing sysfs files managed by this device
- * driver.
- */
-static void aiptek_delete_files(struct device *dev)
-{
- device_remove_file(dev, &dev_attr_size);
- device_remove_file(dev, &dev_attr_product_id);
- device_remove_file(dev, &dev_attr_vendor_id);
- device_remove_file(dev, &dev_attr_vendor);
- device_remove_file(dev, &dev_attr_product);
- device_remove_file(dev, &dev_attr_pointer_mode);
- device_remove_file(dev, &dev_attr_coordinate_mode);
- device_remove_file(dev, &dev_attr_tool_mode);
- device_remove_file(dev, &dev_attr_xtilt);
- device_remove_file(dev, &dev_attr_ytilt);
- device_remove_file(dev, &dev_attr_jitter);
- device_remove_file(dev, &dev_attr_delay);
- device_remove_file(dev, &dev_attr_input_path);
- device_remove_file(dev, &dev_attr_event_count);
- device_remove_file(dev, &dev_attr_diagnostic);
- device_remove_file(dev, &dev_attr_odm_code);
- device_remove_file(dev, &dev_attr_model_code);
- device_remove_file(dev, &dev_attr_firmware_code);
- device_remove_file(dev, &dev_attr_stylus_lower);
- device_remove_file(dev, &dev_attr_stylus_upper);
- device_remove_file(dev, &dev_attr_mouse_left);
- device_remove_file(dev, &dev_attr_mouse_middle);
- device_remove_file(dev, &dev_attr_mouse_right);
- device_remove_file(dev, &dev_attr_wheel);
- device_remove_file(dev, &dev_attr_execute);
-}
-
-/***********************************************************************
- * This routine creates the sysfs files managed by this device
- * driver.
- */
-static int aiptek_add_files(struct device *dev)
-{
- int ret;
+static struct attribute *aiptek_attributes[] = {
+ &dev_attr_size.attr,
+ &dev_attr_pointer_mode.attr,
+ &dev_attr_coordinate_mode.attr,
+ &dev_attr_tool_mode.attr,
+ &dev_attr_xtilt.attr,
+ &dev_attr_ytilt.attr,
+ &dev_attr_jitter.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_event_count.attr,
+ &dev_attr_diagnostic.attr,
+ &dev_attr_odm_code.attr,
+ &dev_attr_model_code.attr,
+ &dev_attr_firmware_code.attr,
+ &dev_attr_stylus_lower.attr,
+ &dev_attr_stylus_upper.attr,
+ &dev_attr_mouse_left.attr,
+ &dev_attr_mouse_middle.attr,
+ &dev_attr_mouse_right.attr,
+ &dev_attr_wheel.attr,
+ &dev_attr_execute.attr,
+ NULL
+};
- if ((ret = device_create_file(dev, &dev_attr_size)) ||
- (ret = device_create_file(dev, &dev_attr_product_id)) ||
- (ret = device_create_file(dev, &dev_attr_vendor_id)) ||
- (ret = device_create_file(dev, &dev_attr_vendor)) ||
- (ret = device_create_file(dev, &dev_attr_product)) ||
- (ret = device_create_file(dev, &dev_attr_pointer_mode)) ||
- (ret = device_create_file(dev, &dev_attr_coordinate_mode)) ||
- (ret = device_create_file(dev, &dev_attr_tool_mode)) ||
- (ret = device_create_file(dev, &dev_attr_xtilt)) ||
- (ret = device_create_file(dev, &dev_attr_ytilt)) ||
- (ret = device_create_file(dev, &dev_attr_jitter)) ||
- (ret = device_create_file(dev, &dev_attr_delay)) ||
- (ret = device_create_file(dev, &dev_attr_input_path)) ||
- (ret = device_create_file(dev, &dev_attr_event_count)) ||
- (ret = device_create_file(dev, &dev_attr_diagnostic)) ||
- (ret = device_create_file(dev, &dev_attr_odm_code)) ||
- (ret = device_create_file(dev, &dev_attr_model_code)) ||
- (ret = device_create_file(dev, &dev_attr_firmware_code)) ||
- (ret = device_create_file(dev, &dev_attr_stylus_lower)) ||
- (ret = device_create_file(dev, &dev_attr_stylus_upper)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_left)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_middle)) ||
- (ret = device_create_file(dev, &dev_attr_mouse_right)) ||
- (ret = device_create_file(dev, &dev_attr_wheel)) ||
- (ret = device_create_file(dev, &dev_attr_execute))) {
- err("aiptek: killing own sysfs device files\n");
- aiptek_delete_files(dev);
- }
- return ret;
-}
+static struct attribute_group aiptek_attribute_group = {
+ .attrs = aiptek_attributes,
+};
/***********************************************************************
* This routine is called when a tablet has been identified. It basically
@@ -1961,8 +1659,6 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_endpoint_descriptor *endpoint;
struct aiptek *aiptek;
struct input_dev *inputdev;
- struct input_handle *inputhandle;
- struct list_head *node, *next;
int i;
int speeds[] = { 0,
AIPTEK_PROGRAMMABLE_DELAY_50,
@@ -1984,17 +1680,23 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL);
inputdev = input_allocate_device();
- if (!aiptek || !inputdev)
+ if (!aiptek || !inputdev) {
+ warn("aiptek: cannot allocate memory or input device");
goto fail1;
+ }
aiptek->data = usb_buffer_alloc(usbdev, AIPTEK_PACKET_LENGTH,
GFP_ATOMIC, &aiptek->data_dma);
- if (!aiptek->data)
+ if (!aiptek->data) {
+ warn("aiptek: cannot allocate usb buffer");
goto fail1;
+ }
aiptek->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!aiptek->urb)
+ if (!aiptek->urb) {
+ warn("aiptek: cannot allocate urb");
goto fail2;
+ }
aiptek->inputdev = inputdev;
aiptek->usbdev = usbdev;
@@ -2002,6 +1704,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek->inDelay = 0;
aiptek->endDelay = 0;
aiptek->previousJitterable = 0;
+ aiptek->lastMacro = -1;
/* Set up the curSettings struct. Said struct contains the current
* programmable parameters. The newSetting struct contains changes
@@ -2054,36 +1757,23 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Now program the capacities of the tablet, in terms of being
* an input device.
*/
- inputdev->evbit[0] |= BIT(EV_KEY)
- | BIT(EV_ABS)
- | BIT(EV_REL)
- | BIT(EV_MSC);
-
- inputdev->absbit[0] |= BIT(ABS_MISC);
+ for (i = 0; i < ARRAY_SIZE(eventTypes); ++i)
+ __set_bit(eventTypes[i], inputdev->evbit);
- inputdev->relbit[0] |=
- (BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_MISC));
+ for (i = 0; i < ARRAY_SIZE(absEvents); ++i)
+ __set_bit(absEvents[i], inputdev->absbit);
- inputdev->keybit[LONG(BTN_LEFT)] |=
- (BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE));
+ for (i = 0; i < ARRAY_SIZE(relEvents); ++i)
+ __set_bit(relEvents[i], inputdev->relbit);
- inputdev->keybit[LONG(BTN_DIGI)] |=
- (BIT(BTN_TOOL_PEN) |
- BIT(BTN_TOOL_RUBBER) |
- BIT(BTN_TOOL_PENCIL) |
- BIT(BTN_TOOL_AIRBRUSH) |
- BIT(BTN_TOOL_BRUSH) |
- BIT(BTN_TOOL_MOUSE) |
- BIT(BTN_TOOL_LENS) |
- BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2));
+ __set_bit(MSC_SERIAL, inputdev->mscbit);
- inputdev->mscbit[0] = BIT(MSC_SERIAL);
+ /* Set up key and button codes */
+ for (i = 0; i < ARRAY_SIZE(buttonEvents); ++i)
+ __set_bit(buttonEvents[i], inputdev->keybit);
- /* Programming the tablet macro keys needs to be done with a for loop
- * as the keycodes are discontiguous.
- */
for (i = 0; i < ARRAY_SIZE(macroKeyEvents); ++i)
- set_bit(macroKeyEvents[i], inputdev->keybit);
+ __set_bit(macroKeyEvents[i], inputdev->keybit);
/*
* Program the input device coordinate capacities. We do not yet
@@ -2134,25 +1824,11 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
}
- /* Register the tablet as an Input Device
- */
- err = input_register_device(aiptek->inputdev);
- if (err)
+ /* Murphy says that some day someone will have a tablet that fails the
+ above test. That's you, Frederic Rodrigo */
+ if (i == ARRAY_SIZE(speeds)) {
+ info("input: Aiptek tried all speeds, no sane response");
goto fail2;
-
- /* We now will look for the evdev device which is mapped to
- * the tablet. The partial name is kept in the link list of
- * input_handles associated with this input device.
- * What identifies an evdev input_handler is that it begins
- * with 'event', continues with a digit, and that in turn
- * is mapped to input/eventN.
- */
- list_for_each_safe(node, next, &inputdev->h_list) {
- inputhandle = to_handle(node);
- if (strncmp(inputhandle->name, "event", 5) == 0) {
- strcpy(aiptek->features.inputPath, inputhandle->name);
- break;
- }
}
/* Associate this driver's struct with the usb interface.
@@ -2161,18 +1837,27 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
/* Set up the sysfs files
*/
- aiptek_add_files(&intf->dev);
+ err = sysfs_create_group(&intf->dev.kobj, &aiptek_attribute_group);
+ if (err) {
+ warn("aiptek: cannot create sysfs group err: %d", err);
+ goto fail3;
+ }
- /* Make sure the evdev module is loaded. Assuming evdev IS a module :-)
+ /* Register the tablet as an Input Device
*/
- if (request_module("evdev") != 0)
- info("aiptek: error loading 'evdev' module");
-
+ err = input_register_device(aiptek->inputdev);
+ if (err) {
+ warn("aiptek: input_register_device returned err: %d", err);
+ goto fail4;
+ }
return 0;
+ fail4: sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
+ fail3: usb_free_urb(aiptek->urb);
fail2: usb_buffer_free(usbdev, AIPTEK_PACKET_LENGTH, aiptek->data,
aiptek->data_dma);
- fail1: input_free_device(inputdev);
+ fail1: usb_set_intfdata(intf, NULL);
+ input_free_device(inputdev);
kfree(aiptek);
return err;
}
@@ -2192,7 +1877,7 @@ static void aiptek_disconnect(struct usb_interface *intf)
*/
usb_kill_urb(aiptek->urb);
input_unregister_device(aiptek->inputdev);
- aiptek_delete_files(&intf->dev);
+ sysfs_remove_group(&intf->dev.kobj, &aiptek_attribute_group);
usb_free_urb(aiptek->urb);
usb_buffer_free(interface_to_usbdev(intf),
AIPTEK_PACKET_LENGTH,
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index ef01a807ec0..6542edb6f76 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -11,7 +11,7 @@
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
- * Copyright (c) 2002-2006 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2007 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
@@ -62,8 +62,9 @@
* - Minor data report fix
* v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
* - where wacom_sys.c deals with system specific code,
- * - and wacom_wac.c deals with Wacom specific code
+ * - and wacom_wac.c deals with Wacom specific code
* - Support Intuos3 4x6
+ * v1.47 (pc) - Added support for Bamboo
*/
/*
@@ -84,7 +85,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.46"
+#define DRIVER_VERSION "v1.47"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
@@ -123,6 +124,7 @@ extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wa
extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
extern __u16 wacom_le16_to_cpu(unsigned char *data);
extern __u16 wacom_be16_to_cpu(unsigned char *data);
extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 83bddef6606..064e123c9b7 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -138,6 +138,12 @@ static void wacom_close(struct input_dev *dev)
usb_kill_urb(wacom->irq);
}
+void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+ input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_1) | BIT(BTN_5);
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+}
+
void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
input_dev->evbit[0] |= BIT(EV_MSC);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 7661f03a2db..fc03ba256f4 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -178,7 +178,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
case 2: /* Mouse with wheel */
wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
- if (wacom->features->type == WACOM_G4) {
+ if (wacom->features->type == WACOM_G4 ||
+ wacom->features->type == WACOM_MO) {
rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
wacom_report_rel(wcombo, REL_WHEEL, -rw);
} else
@@ -190,7 +191,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
id = CURSOR_DEVICE_ID;
wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
- if (wacom->features->type == WACOM_G4)
+ if (wacom->features->type == WACOM_G4 ||
+ wacom->features->type == WACOM_MO)
wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
else
wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
@@ -226,7 +228,8 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
}
/* send pad data */
- if (wacom->features->type == WACOM_G4) {
+ switch (wacom->features->type) {
+ case WACOM_G4:
if (data[7] & 0xf8) {
wacom_input_sync(wcombo); /* sync last event */
wacom->id[1] = 1;
@@ -247,6 +250,33 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
wacom_report_abs(wcombo, ABS_MISC, 0);
wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
}
+ break;
+ case WACOM_MO:
+ if ((data[7] & 0xf8) || (data[8] & 0x80)) {
+ wacom_input_sync(wcombo); /* sync last event */
+ wacom->id[1] = 1;
+ wacom->serial[1] = (data[7] & 0xf8);
+ wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+ wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+ wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+ wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+ wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+ wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+ wacom_report_abs(wcombo, ABS_MISC, PAD_DEVICE_ID);
+ wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+ } else if (wacom->id[1]) {
+ wacom_input_sync(wcombo); /* sync last event */
+ wacom->id[1] = 0;
+ wacom_report_key(wcombo, BTN_0, (data[7] & 0x08));
+ wacom_report_key(wcombo, BTN_1, (data[7] & 0x20));
+ wacom_report_key(wcombo, BTN_4, (data[7] & 0x10));
+ wacom_report_key(wcombo, BTN_5, (data[7] & 0x40));
+ wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f));
+ wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+ wacom_report_abs(wcombo, ABS_MISC, 0);
+ wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+ }
+ break;
}
return 1;
}
@@ -331,7 +361,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_EXTRA, 0);
wacom_report_abs(wcombo, ABS_THROTTLE, 0);
wacom_report_abs(wcombo, ABS_RZ, 0);
- } else {
+ } else {
wacom_report_abs(wcombo, ABS_PRESSURE, 0);
wacom_report_abs(wcombo, ABS_TILT_X, 0);
wacom_report_abs(wcombo, ABS_TILT_Y, 0);
@@ -423,9 +453,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
return result-1;
/* Only large I3 and I1 & I2 support Lense Cursor */
- if((wacom->tool[idx] == BTN_TOOL_LENS)
+ if ((wacom->tool[idx] == BTN_TOOL_LENS)
&& ((wacom->features->type == INTUOS3)
- || (wacom->features->type == INTUOS3S)))
+ || (wacom->features->type == INTUOS3S)))
return 0;
/* Cintiq doesn't send data when RDY bit isn't set */
@@ -517,6 +547,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
break;
case WACOM_G4:
case GRAPHIRE:
+ case WACOM_MO:
return (wacom_graphire_irq(wacom_wac, wcombo));
break;
case PTU:
@@ -538,6 +569,8 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
switch (wacom_wac->features->type) {
+ case WACOM_MO:
+ input_dev_mo(input_dev, wacom_wac);
case WACOM_G4:
input_dev_g4(input_dev, wacom_wac);
/* fall through */
@@ -579,6 +612,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE },
{ "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE },
{ "Wacom PenPartner2", 8, 3250, 2320, 255, 63, GRAPHIRE },
+ { "Wacom Bamboo", 9, 14760, 9225, 511, 63, WACOM_MO },
{ "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS },
{ "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
{ "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS },
@@ -627,6 +661,7 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+ { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index a5e12e8756d..a302e229bb8 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -25,6 +25,7 @@ enum {
INTUOS3,
INTUOS3L,
CINTIQ,
+ WACOM_MO,
MAX_TYPE
};
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index e5cca9bd040..69371779806 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -177,6 +177,7 @@ config TOUCHSCREEN_USB_COMPOSITE
- some other eTurboTouch
- Gunze AHL61
- DMC TSC-10/25
+ - IRTOUCHSYSTEMS/UNITOP
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
@@ -219,4 +220,9 @@ config TOUCHSCREEN_USB_DMC_TSC10
bool "DMC TSC-10/25 device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
+config TOUCHSCREEN_USB_IRTOUCH
+ default y
+ bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
+ depends on TOUCHSCREEN_USB_COMPOSITE
+
endif
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index 8e18e6c6477..b407028ffc5 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -9,6 +9,7 @@
* - eTurboTouch
* - Gunze AHL61
* - DMC TSC-10/25
+ * - IRTOUCHSYSTEMS/UNITOP
*
* Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -91,7 +92,7 @@ struct usbtouch_usb {
};
-#if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO)
+#if defined(CONFIG_TOUCHSCREEN_USB_EGALAX) || defined(CONFIG_TOUCHSCREEN_USB_ETURBO)
#define MULTI_PACKET
#endif
@@ -110,10 +111,11 @@ enum {
DEVTYPE_ETURBO,
DEVTYPE_GUNZE,
DEVTYPE_DMC_TSC10,
+ DEVTYPE_IRTOUCH,
};
static struct usb_device_id usbtouch_devices[] = {
-#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
{USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
{USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
@@ -123,33 +125,38 @@ static struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
{USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT},
{USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT},
{USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT},
{USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_3M
+#ifdef CONFIG_TOUCHSCREEN_USB_3M
{USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+#ifdef CONFIG_TOUCHSCREEN_USB_ITM
{USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
{USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
#endif
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+ {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+ {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
+#endif
+
{}
};
@@ -158,7 +165,7 @@ static struct usb_device_id usbtouch_devices[] = {
* eGalax part
*/
-#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
#define EGALAX_PKT_TYPE_MASK 0xFE
#define EGALAX_PKT_TYPE_REPT 0x80
@@ -197,7 +204,7 @@ static int egalax_get_pkt_len(unsigned char *buf, int len)
/*****************************************************************************
* PanJit Part
*/
-#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1];
@@ -212,7 +219,7 @@ static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
/*****************************************************************************
* 3M/Microtouch Part
*/
-#ifdef CONFIG_USB_TOUCHSCREEN_3M
+#ifdef CONFIG_TOUCHSCREEN_USB_3M
#define MTOUCHUSB_ASYNC_REPORT 1
#define MTOUCHUSB_RESET 7
@@ -262,7 +269,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
/*****************************************************************************
* ITM Part
*/
-#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+#ifdef CONFIG_TOUCHSCREEN_USB_ITM
static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
int touch;
@@ -296,7 +303,7 @@ static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
/*****************************************************************************
* eTurboTouch part
*/
-#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
static int eturbo_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
unsigned int shift;
@@ -327,7 +334,7 @@ static int eturbo_get_pkt_len(unsigned char *buf, int len)
/*****************************************************************************
* Gunze part
*/
-#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
{
if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
@@ -348,7 +355,7 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
* http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf
* http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf
*/
-#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
/* supported data rates. currently using 130 */
#define TSC10_RATE_POINT 0x50
@@ -416,10 +423,25 @@ static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
/*****************************************************************************
+ * IRTOUCH Part
+ */
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
+{
+ dev->x = (pkt[3] << 8) | pkt[2];
+ dev->y = (pkt[5] << 8) | pkt[4];
+ dev->touch = (pkt[1] & 0x03) ? 1 : 0;
+
+ return 1;
+}
+#endif
+
+
+/*****************************************************************************
* the different device descriptors
*/
static struct usbtouch_device_info usbtouch_dev_info[] = {
-#ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
+#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
[DEVTYPE_EGALAX] = {
.min_xc = 0x0,
.max_xc = 0x07ff,
@@ -433,7 +455,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
+#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT
[DEVTYPE_PANJIT] = {
.min_xc = 0x0,
.max_xc = 0x0fff,
@@ -444,7 +466,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_3M
+#ifdef CONFIG_TOUCHSCREEN_USB_3M
[DEVTYPE_3M] = {
.min_xc = 0x0,
.max_xc = 0x4000,
@@ -456,7 +478,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_ITM
+#ifdef CONFIG_TOUCHSCREEN_USB_ITM
[DEVTYPE_ITM] = {
.min_xc = 0x0,
.max_xc = 0x0fff,
@@ -468,7 +490,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO
[DEVTYPE_ETURBO] = {
.min_xc = 0x0,
.max_xc = 0x07ff,
@@ -482,7 +504,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE
[DEVTYPE_GUNZE] = {
.min_xc = 0x0,
.max_xc = 0x0fff,
@@ -493,7 +515,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
},
#endif
-#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
+#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10
[DEVTYPE_DMC_TSC10] = {
.min_xc = 0x0,
.max_xc = 0x03ff,
@@ -504,6 +526,17 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.read_data = dmc_tsc10_read_data,
},
#endif
+
+#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+ [DEVTYPE_IRTOUCH] = {
+ .min_xc = 0x0,
+ .max_xc = 0x0fff,
+ .min_yc = 0x0,
+ .max_yc = 0x0fff,
+ .rept_size = 8,
+ .read_data = irtouch_read_data,
+ },
+#endif
};
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 8238b13874c..d2f882e98e5 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -109,9 +109,11 @@ struct tsdev {
int open;
int minor;
char name[8];
+ struct input_handle handle;
wait_queue_head_t wait;
struct list_head client_list;
- struct input_handle handle;
+ struct device dev;
+
int x, y, pressure;
struct ts_calibration cal;
};
@@ -163,9 +165,13 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (!tsdev || !tsdev->exist)
return -ENODEV;
+ get_device(&tsdev->dev);
+
client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
- if (!client)
- return -ENOMEM;
+ if (!client) {
+ error = -ENOMEM;
+ goto err_put_tsdev;
+ }
client->tsdev = tsdev;
client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
@@ -173,19 +179,25 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (!tsdev->open++ && tsdev->exist) {
error = input_open_device(&tsdev->handle);
- if (error) {
- list_del(&client->node);
- kfree(client);
- return error;
- }
+ if (error)
+ goto err_free_client;
}
file->private_data = client;
return 0;
+
+ err_free_client:
+ list_del(&client->node);
+ kfree(client);
+ err_put_tsdev:
+ put_device(&tsdev->dev);
+ return error;
}
-static void tsdev_free(struct tsdev *tsdev)
+static void tsdev_free(struct device *dev)
{
+ struct tsdev *tsdev = container_of(dev, struct tsdev, dev);
+
tsdev_table[tsdev->minor] = NULL;
kfree(tsdev);
}
@@ -200,12 +212,10 @@ static int tsdev_release(struct inode *inode, struct file *file)
list_del(&client->node);
kfree(client);
- if (!--tsdev->open) {
- if (tsdev->exist)
- input_close_device(&tsdev->handle);
- else
- tsdev_free(tsdev);
- }
+ if (!--tsdev->open && tsdev->exist)
+ input_close_device(&tsdev->handle);
+
+ put_device(&tsdev->dev);
return 0;
}
@@ -361,7 +371,7 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
int x, y, tmp;
do_gettimeofday(&time);
- client->event[client->head].millisecs = time.tv_usec / 100;
+ client->event[client->head].millisecs = time.tv_usec / 1000;
client->event[client->head].pressure = tsdev->pressure;
x = tsdev->x;
@@ -388,8 +398,6 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct tsdev *tsdev;
- struct class_device *cdev;
- dev_t devt;
int minor, delta;
int error;
@@ -407,14 +415,13 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
INIT_LIST_HEAD(&tsdev->client_list);
init_waitqueue_head(&tsdev->wait);
- sprintf(tsdev->name, "ts%d", minor);
-
tsdev->exist = 1;
tsdev->minor = minor;
tsdev->handle.dev = dev;
tsdev->handle.name = tsdev->name;
tsdev->handle.handler = handler;
tsdev->handle.private = tsdev;
+ snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
/* Precompute the rough calibration matrix */
delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
@@ -429,36 +436,30 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
tsdev->cal.yscale = (yres << 8) / delta;
tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
- tsdev_table[minor] = tsdev;
-
- devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+ snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
+ "ts%d", minor);
+ tsdev->dev.class = &input_class;
+ tsdev->dev.parent = &dev->dev;
+ tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor);
+ tsdev->dev.release = tsdev_free;
+ device_initialize(&tsdev->dev);
- cdev = class_device_create(&input_class, &dev->cdev, devt,
- dev->cdev.dev, tsdev->name);
- if (IS_ERR(cdev)) {
- error = PTR_ERR(cdev);
- goto err_free_tsdev;
- }
+ tsdev_table[minor] = tsdev;
- /* temporary symlink to keep userspace happy */
- error = sysfs_create_link(&input_class.subsys.kobj,
- &cdev->kobj, tsdev->name);
+ error = device_add(&tsdev->dev);
if (error)
- goto err_cdev_destroy;
+ goto err_free_tsdev;
error = input_register_handle(&tsdev->handle);
if (error)
- goto err_remove_link;
+ goto err_delete_tsdev;
return 0;
- err_remove_link:
- sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- err_cdev_destroy:
- class_device_destroy(&input_class, devt);
+ err_delete_tsdev:
+ device_del(&tsdev->dev);
err_free_tsdev:
- tsdev_table[minor] = NULL;
- kfree(tsdev);
+ put_device(&tsdev->dev);
return error;
}
@@ -468,19 +469,18 @@ static void tsdev_disconnect(struct input_handle *handle)
struct tsdev_client *client;
input_unregister_handle(handle);
+ device_del(&tsdev->dev);
- sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
- class_device_destroy(&input_class,
- MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
tsdev->exist = 0;
if (tsdev->open) {
input_close_device(handle);
- wake_up_interruptible(&tsdev->wait);
list_for_each_entry(client, &tsdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
- } else
- tsdev_free(tsdev);
+ wake_up_interruptible(&tsdev->wait);
+ }
+
+ put_device(&tsdev->dev);
}
static const struct input_device_id tsdev_ids[] = {
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index d42fe89cddf..3e088c42b22 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -26,9 +26,9 @@ menu "Old ISDN4Linux"
depends on NET && ISDN
config ISDN_I4L
- tristate "Old ISDN4Linux (obsolete)"
+ tristate "Old ISDN4Linux (deprecated)"
---help---
- This driver allows you to use an ISDN-card for networking
+ This driver allows you to use an ISDN adapter for networking
connections and as dialin/out device. The isdn-tty's have a built
in AT-compatible modem emulator. Network devices support autodial,
channel-bundling, callback and caller-authentication without having
@@ -39,8 +39,9 @@ config ISDN_I4L
ISDN support in the linux kernel is moving towards a new API,
called CAPI (Common ISDN Application Programming Interface).
- Therefore the old ISDN4Linux layer is becoming obsolete. It is
- still usable, though, if you select this option.
+ Therefore the old ISDN4Linux layer will eventually become obsolete.
+ It is still available, though, for use with adapters that are not
+ supported by the new CAPI subsystem yet.
if ISDN_I4L
source "drivers/isdn/i4l/Kconfig"
diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
index 14298b8c835..d755d904e62 100644
--- a/drivers/isdn/hardware/eicon/diva_didd.c
+++ b/drivers/isdn/hardware/eicon/diva_didd.c
@@ -99,7 +99,7 @@ static int DIVA_INIT_FUNCTION create_proc(void)
return (0);
}
-static void DIVA_EXIT_FUNCTION remove_proc(void)
+static void remove_proc(void)
{
remove_proc_entry(DRIVERLNAME, proc_net_eicon);
remove_proc_entry("net/eicon", NULL);
diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
index df61e510a28..d36a4c09e25 100644
--- a/drivers/isdn/hardware/eicon/divasfunc.c
+++ b/drivers/isdn/hardware/eicon/divasfunc.c
@@ -195,7 +195,7 @@ static int DIVA_INIT_FUNCTION connect_didd(void)
/*
* disconnect from didd
*/
-static void DIVA_EXIT_FUNCTION disconnect_didd(void)
+static void disconnect_didd(void)
{
IDI_SYNC_REQ req;
@@ -231,7 +231,7 @@ int DIVA_INIT_FUNCTION divasfunc_init(int dbgmask)
/*
* exit
*/
-void DIVA_EXIT_FUNCTION divasfunc_exit(void)
+void divasfunc_exit(void)
{
divasa_xdi_driver_unload();
disconnect_didd();
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index 34031064534..6339bb443f6 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -287,7 +287,6 @@ setup_sct_quadro(struct IsdnCard *card)
#ifdef CONFIG_PCI
struct IsdnCardState *cs = card->cs;
char tmp[64];
- u_char pci_rev_id;
u_int found = 0;
u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5;
@@ -335,8 +334,7 @@ setup_sct_quadro(struct IsdnCard *card)
}
#ifdef ATTEMPT_PCI_REMAPPING
/* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
- pci_read_config_byte(dev_a8, PCI_REVISION_ID, &pci_rev_id);
- if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) {
+ if ((pci_ioaddr1 & 0x80) && (dev_a8->revision == 1)) {
printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
CardType[card->typ],
sct_quadro_subtypes[cs->subtyp]);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index ea5f30d4a5a..4e5f87c1e71 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -2693,8 +2693,9 @@ isdn_tty_getdial(char *p, char *q,int cnt)
int limit = ISDN_MSNLEN - 1; /* MUST match the size of interface var to avoid
buffer overflow */
- while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
+ while (strchr(" 0123456789,#.*WPTSR-", *p) && *p && --cnt>0) {
if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
+ ((*p == 'R') && first) ||
(*p == '*') || (*p == '#')) {
*q++ = *p;
limit--;
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index 1c040d80c64..152312c1faf 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -304,6 +304,7 @@ struct kvm_vcpu {
char *host_fx_image;
char *guest_fx_image;
int fpu_active;
+ int guest_fpu_loaded;
int mmio_needed;
int mmio_read_completed;
@@ -508,6 +509,8 @@ void fx_init(struct kvm_vcpu *vcpu);
void load_msrs(struct vmx_msr_entry *e, int n);
void save_msrs(struct vmx_msr_entry *e, int n);
void kvm_resched(struct kvm_vcpu *vcpu);
+void kvm_load_guest_fpu(struct kvm_vcpu *vcpu);
+void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
int kvm_read_guest(struct kvm_vcpu *vcpu,
gva_t addr,
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index da985b31b17..8f1f07adb04 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -253,6 +253,28 @@ int kvm_write_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long size,
}
EXPORT_SYMBOL_GPL(kvm_write_guest);
+void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
+{
+ if (!vcpu->fpu_active || vcpu->guest_fpu_loaded)
+ return;
+
+ vcpu->guest_fpu_loaded = 1;
+ fx_save(vcpu->host_fx_image);
+ fx_restore(vcpu->guest_fx_image);
+}
+EXPORT_SYMBOL_GPL(kvm_load_guest_fpu);
+
+void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
+{
+ if (!vcpu->guest_fpu_loaded)
+ return;
+
+ vcpu->guest_fpu_loaded = 0;
+ fx_save(vcpu->guest_fx_image);
+ fx_restore(vcpu->host_fx_image);
+}
+EXPORT_SYMBOL_GPL(kvm_put_guest_fpu);
+
/*
* Switches to specified vcpu, until a matching vcpu_put()
*/
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index e6e4d240b2a..c1ac106ace8 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -280,6 +280,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu)
static void vmx_vcpu_put(struct kvm_vcpu *vcpu)
{
+ kvm_put_guest_fpu(vcpu);
put_cpu();
}
@@ -639,7 +640,7 @@ static void free_vmcs(struct vmcs *vmcs)
free_pages((unsigned long)vmcs, vmcs_descriptor.order);
}
-static __exit void free_kvm_area(void)
+static void free_kvm_area(void)
{
int cpu;
@@ -1847,10 +1848,8 @@ again:
if (vcpu->guest_debug.enabled)
kvm_guest_debug_pre(vcpu);
- if (vcpu->fpu_active) {
- fx_save(vcpu->host_fx_image);
- fx_restore(vcpu->guest_fx_image);
- }
+ kvm_load_guest_fpu(vcpu);
+
/*
* Loading guest fpu may have cleared host cr0.ts
*/
@@ -2012,11 +2011,6 @@ again:
}
#endif
- if (vcpu->fpu_active) {
- fx_save(vcpu->guest_fx_image);
- fx_restore(vcpu->host_fx_image);
- }
-
vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0;
asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index f44c94abd88..dbe96268866 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -2,7 +2,7 @@
menuconfig MACINTOSH_DRIVERS
bool "Macintosh device drivers"
depends on PPC || MAC || X86
- default y
+ default y if (PPC_PMAC || MAC)
if MACINTOSH_DRIVERS
@@ -114,7 +114,7 @@ config PMAC_SMU
config PMAC_APM_EMU
tristate "APM emulation"
select APM_EMULATION
- depends on ADB_PMU && PM
+ depends on ADB_PMU && PM && PPC32
config PMAC_MEDIABAY
bool "Support PowerBook hotswap media bay"
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 11ced17f438..4fcb245ba18 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -212,7 +212,6 @@ int wf_register_control(struct wf_control *new_ct)
list_add(&new_ct->link, &wf_controls);
new_ct->attr.attr.name = new_ct->name;
- new_ct->attr.attr.owner = THIS_MODULE;
new_ct->attr.attr.mode = 0644;
new_ct->attr.show = wf_show_control;
new_ct->attr.store = wf_store_control;
@@ -325,7 +324,6 @@ int wf_register_sensor(struct wf_sensor *new_sr)
list_add(&new_sr->link, &wf_sensors);
new_sr->attr.attr.name = new_sr->name;
- new_sr->attr.attr.owner = THIS_MODULE;
new_sr->attr.attr.mode = 0444;
new_sr->attr.show = wf_show_sensor;
new_sr->attr.store = NULL;
diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c
index 1043b39aa12..351982bcec1 100644
--- a/drivers/macintosh/windfarm_smu_sat.c
+++ b/drivers/macintosh/windfarm_smu_sat.c
@@ -67,26 +67,6 @@ static struct i2c_driver wf_sat_driver = {
.detach_client = wf_sat_detach,
};
-/*
- * XXX i2c_smbus_read_i2c_block_data doesn't pass the requested
- * length down to the low-level driver, so we use this, which
- * works well enough with the SMU i2c driver code...
- */
-static int sat_read_block(struct i2c_client *client, u8 command,
- u8 *values, int len)
-{
- union i2c_smbus_data data;
- int err;
-
- data.block[0] = len;
- err = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
- I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA,
- &data);
- if (!err)
- memcpy(values, data.block, len);
- return err;
-}
-
struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
unsigned int *size)
{
@@ -124,8 +104,8 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
return NULL;
for (i = 0; i < len; i += 4) {
- err = sat_read_block(&sat->i2c, 0xa, data, 4);
- if (err) {
+ err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data);
+ if (err < 0) {
printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n",
err);
goto fail;
@@ -157,8 +137,8 @@ static int wf_sat_read_cache(struct wf_sat *sat)
{
int err;
- err = sat_read_block(&sat->i2c, 0x3f, sat->cache, 16);
- if (err)
+ err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache);
+ if (err < 0)
return err;
sat->last_read = jiffies;
#ifdef LOTSA_DEBUG
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 7df934d6913..64bf3a81db9 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -109,6 +109,8 @@ config MD_RAID10
config MD_RAID456
tristate "RAID-4/RAID-5/RAID-6 mode"
depends on BLK_DEV_MD
+ select ASYNC_MEMCPY
+ select ASYNC_XOR
---help---
A RAID-5 set of N drives with a capacity of C MB per drive provides
the capacity of C * (N - 1) MB, and protects against a failure
@@ -262,6 +264,12 @@ config DM_MULTIPATH_EMC
---help---
Multipath support for EMC CX/AX series hardware.
+config DM_MULTIPATH_RDAC
+ tristate "LSI/Engenio RDAC multipath support (EXPERIMENTAL)"
+ depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+ ---help---
+ Multipath support for LSI/Engenio RDAC.
+
config DM_DELAY
tristate "I/O delaying target (EXPERIMENTAL)"
depends on BLK_DEV_DM && EXPERIMENTAL
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 38754084eac..c49366cdc05 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -7,6 +7,7 @@ dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
dm-snapshot-objs := dm-snap.o dm-exception-store.o
dm-mirror-objs := dm-log.o dm-raid1.o
+dm-rdac-objs := dm-mpath-rdac.o
md-mod-objs := md.o bitmap.o
raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \
raid6int1.o raid6int2.o raid6int4.o \
@@ -17,7 +18,7 @@ raid456-objs := raid5.o raid6algos.o raid6recov.o raid6tables.o \
hostprogs-y := mktables
# Note: link order is important. All raid personalities
-# and xor.o must come before md.o, as they each initialise
+# and must come before md.o, as they each initialise
# themselves, and md.o may use the personalities when it
# auto-initialised.
@@ -25,7 +26,7 @@ obj-$(CONFIG_MD_LINEAR) += linear.o
obj-$(CONFIG_MD_RAID0) += raid0.o
obj-$(CONFIG_MD_RAID1) += raid1.o
obj-$(CONFIG_MD_RAID10) += raid10.o
-obj-$(CONFIG_MD_RAID456) += raid456.o xor.o
+obj-$(CONFIG_MD_RAID456) += raid456.o
obj-$(CONFIG_MD_MULTIPATH) += multipath.o
obj-$(CONFIG_MD_FAULTY) += faulty.o
obj-$(CONFIG_BLK_DEV_MD) += md-mod.o
@@ -34,6 +35,7 @@ obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
obj-$(CONFIG_DM_DELAY) += dm-delay.o
obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
obj-$(CONFIG_DM_MULTIPATH_EMC) += dm-emc.o
+obj-$(CONFIG_DM_MULTIPATH_RDAC) += dm-rdac.o
obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
obj-$(CONFIG_DM_MIRROR) += dm-mirror.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
diff --git a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h
index c6be88826fa..16ee3b018b3 100644
--- a/drivers/md/dm-bio-list.h
+++ b/drivers/md/dm-bio-list.h
@@ -8,7 +8,6 @@
#define DM_BIO_LIST_H
#include <linux/bio.h>
-#include <linux/prefetch.h>
struct bio_list {
struct bio *head;
@@ -31,8 +30,7 @@ static inline void bio_list_init(struct bio_list *bl)
}
#define bio_list_for_each(bio, bl) \
- for (bio = (bl)->head; bio && ({ prefetch(bio->bi_next); 1; }); \
- bio = bio->bi_next)
+ for (bio = (bl)->head; bio; bio = bio->bi_next)
static inline unsigned bio_list_size(const struct bio_list *bl)
{
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 7b0fcfc9eaa..ba952a03259 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -30,7 +30,7 @@
/*
* per bio private data
*/
-struct crypt_io {
+struct dm_crypt_io {
struct dm_target *target;
struct bio *base_bio;
struct work_struct work;
@@ -106,7 +106,7 @@ struct crypt_config {
static struct kmem_cache *_crypt_io_pool;
-static void clone_init(struct crypt_io *, struct bio *);
+static void clone_init(struct dm_crypt_io *, struct bio *);
/*
* Different IV generation algorithms:
@@ -382,7 +382,7 @@ static int crypt_convert(struct crypt_config *cc,
static void dm_crypt_bio_destructor(struct bio *bio)
{
- struct crypt_io *io = bio->bi_private;
+ struct dm_crypt_io *io = bio->bi_private;
struct crypt_config *cc = io->target->private;
bio_free(bio, cc->bs);
@@ -393,7 +393,7 @@ static int crypt_convert(struct crypt_config *cc,
* This should never violate the device limitations
* May return a smaller bio when running out of pages
*/
-static struct bio *crypt_alloc_buffer(struct crypt_io *io, unsigned int size)
+static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size)
{
struct crypt_config *cc = io->target->private;
struct bio *clone;
@@ -479,7 +479,7 @@ static void crypt_free_buffer_pages(struct crypt_config *cc,
* One of the bios was finished. Check for completion of
* the whole request and correctly clean up the buffer.
*/
-static void dec_pending(struct crypt_io *io, int error)
+static void dec_pending(struct dm_crypt_io *io, int error)
{
struct crypt_config *cc = (struct crypt_config *) io->target->private;
@@ -503,7 +503,7 @@ static void dec_pending(struct crypt_io *io, int error)
static struct workqueue_struct *_kcryptd_workqueue;
static void kcryptd_do_work(struct work_struct *work);
-static void kcryptd_queue_io(struct crypt_io *io)
+static void kcryptd_queue_io(struct dm_crypt_io *io)
{
INIT_WORK(&io->work, kcryptd_do_work);
queue_work(_kcryptd_workqueue, &io->work);
@@ -511,7 +511,7 @@ static void kcryptd_queue_io(struct crypt_io *io)
static int crypt_endio(struct bio *clone, unsigned int done, int error)
{
- struct crypt_io *io = clone->bi_private;
+ struct dm_crypt_io *io = clone->bi_private;
struct crypt_config *cc = io->target->private;
unsigned read_io = bio_data_dir(clone) == READ;
@@ -545,7 +545,7 @@ out:
return error;
}
-static void clone_init(struct crypt_io *io, struct bio *clone)
+static void clone_init(struct dm_crypt_io *io, struct bio *clone)
{
struct crypt_config *cc = io->target->private;
@@ -556,7 +556,7 @@ static void clone_init(struct crypt_io *io, struct bio *clone)
clone->bi_destructor = dm_crypt_bio_destructor;
}
-static void process_read(struct crypt_io *io)
+static void process_read(struct dm_crypt_io *io)
{
struct crypt_config *cc = io->target->private;
struct bio *base_bio = io->base_bio;
@@ -587,7 +587,7 @@ static void process_read(struct crypt_io *io)
generic_make_request(clone);
}
-static void process_write(struct crypt_io *io)
+static void process_write(struct dm_crypt_io *io)
{
struct crypt_config *cc = io->target->private;
struct bio *base_bio = io->base_bio;
@@ -644,7 +644,7 @@ static void process_write(struct crypt_io *io)
}
}
-static void process_read_endio(struct crypt_io *io)
+static void process_read_endio(struct dm_crypt_io *io)
{
struct crypt_config *cc = io->target->private;
struct convert_context ctx;
@@ -657,7 +657,7 @@ static void process_read_endio(struct crypt_io *io)
static void kcryptd_do_work(struct work_struct *work)
{
- struct crypt_io *io = container_of(work, struct crypt_io, work);
+ struct dm_crypt_io *io = container_of(work, struct dm_crypt_io, work);
if (io->post_process)
process_read_endio(io);
@@ -939,10 +939,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio,
union map_info *map_context)
{
struct crypt_config *cc = ti->private;
- struct crypt_io *io;
-
- if (bio_barrier(bio))
- return -EOPNOTSUPP;
+ struct dm_crypt_io *io;
io = mempool_alloc(cc->io_pool, GFP_NOIO);
io->target = ti;
@@ -1062,9 +1059,7 @@ static int __init dm_crypt_init(void)
{
int r;
- _crypt_io_pool = kmem_cache_create("dm-crypt_io",
- sizeof(struct crypt_io),
- 0, 0, NULL, NULL);
+ _crypt_io_pool = KMEM_CACHE(dm_crypt_io, 0);
if (!_crypt_io_pool)
return -ENOMEM;
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 52c7cf9e580..6928c136d3c 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -20,7 +20,7 @@
struct delay_c {
struct timer_list delay_timer;
- struct semaphore timer_lock;
+ struct mutex timer_lock;
struct work_struct flush_expired_bios;
struct list_head delayed_bios;
atomic_t may_delay;
@@ -37,7 +37,7 @@ struct delay_c {
unsigned writes;
};
-struct delay_info {
+struct dm_delay_info {
struct delay_c *context;
struct list_head list;
struct bio *bio;
@@ -58,12 +58,12 @@ static void handle_delayed_timer(unsigned long data)
static void queue_timeout(struct delay_c *dc, unsigned long expires)
{
- down(&dc->timer_lock);
+ mutex_lock(&dc->timer_lock);
if (!timer_pending(&dc->delay_timer) || expires < dc->delay_timer.expires)
mod_timer(&dc->delay_timer, expires);
- up(&dc->timer_lock);
+ mutex_unlock(&dc->timer_lock);
}
static void flush_bios(struct bio *bio)
@@ -80,7 +80,7 @@ static void flush_bios(struct bio *bio)
static struct bio *flush_delayed_bios(struct delay_c *dc, int flush_all)
{
- struct delay_info *delayed, *next;
+ struct dm_delay_info *delayed, *next;
unsigned long next_expires = 0;
int start_timer = 0;
BIO_LIST(flush_bios);
@@ -193,13 +193,11 @@ out:
goto bad;
}
- init_timer(&dc->delay_timer);
- dc->delay_timer.function = handle_delayed_timer;
- dc->delay_timer.data = (unsigned long)dc;
+ setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc);
INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
INIT_LIST_HEAD(&dc->delayed_bios);
- init_MUTEX(&dc->timer_lock);
+ mutex_init(&dc->timer_lock);
atomic_set(&dc->may_delay, 1);
ti->private = dc;
@@ -227,7 +225,7 @@ static void delay_dtr(struct dm_target *ti)
static int delay_bio(struct delay_c *dc, int delay, struct bio *bio)
{
- struct delay_info *delayed;
+ struct dm_delay_info *delayed;
unsigned long expires = 0;
if (!delay || !atomic_read(&dc->may_delay))
@@ -338,10 +336,7 @@ static int __init dm_delay_init(void)
goto bad_queue;
}
- delayed_cache = kmem_cache_create("dm-delay",
- sizeof(struct delay_info),
- __alignof__(struct delay_info),
- 0, NULL, NULL);
+ delayed_cache = KMEM_CACHE(dm_delay_info, 0);
if (!delayed_cache) {
DMERR("Couldn't create delayed bio cache.");
goto bad_memcache;
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 07e0a0c84f6..3d65917a1bb 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -125,9 +125,11 @@ struct pstore {
uint32_t callback_count;
struct commit_callback *callbacks;
struct dm_io_client *io_client;
+
+ struct workqueue_struct *metadata_wq;
};
-static inline unsigned int sectors_to_pages(unsigned int sectors)
+static unsigned sectors_to_pages(unsigned sectors)
{
return sectors / (PAGE_SIZE >> 9);
}
@@ -156,10 +158,24 @@ static void free_area(struct pstore *ps)
ps->area = NULL;
}
+struct mdata_req {
+ struct io_region *where;
+ struct dm_io_request *io_req;
+ struct work_struct work;
+ int result;
+};
+
+static void do_metadata(struct work_struct *work)
+{
+ struct mdata_req *req = container_of(work, struct mdata_req, work);
+
+ req->result = dm_io(req->io_req, 1, req->where, NULL);
+}
+
/*
* Read or write a chunk aligned and sized block of data from a device.
*/
-static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
+static int chunk_io(struct pstore *ps, uint32_t chunk, int rw, int metadata)
{
struct io_region where = {
.bdev = ps->snap->cow->bdev,
@@ -173,8 +189,23 @@ static int chunk_io(struct pstore *ps, uint32_t chunk, int rw)
.client = ps->io_client,
.notify.fn = NULL,
};
+ struct mdata_req req;
+
+ if (!metadata)
+ return dm_io(&io_req, 1, &where, NULL);
+
+ req.where = &where;
+ req.io_req = &io_req;
- return dm_io(&io_req, 1, &where, NULL);
+ /*
+ * Issue the synchronous I/O from a different thread
+ * to avoid generic_make_request recursion.
+ */
+ INIT_WORK(&req.work, do_metadata);
+ queue_work(ps->metadata_wq, &req.work);
+ flush_workqueue(ps->metadata_wq);
+
+ return req.result;
}
/*
@@ -189,7 +220,7 @@ static int area_io(struct pstore *ps, uint32_t area, int rw)
/* convert a metadata area index to a chunk index */
chunk = 1 + ((ps->exceptions_per_area + 1) * area);
- r = chunk_io(ps, chunk, rw);
+ r = chunk_io(ps, chunk, rw, 0);
if (r)
return r;
@@ -230,7 +261,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
if (r)
return r;
- r = chunk_io(ps, 0, READ);
+ r = chunk_io(ps, 0, READ, 1);
if (r)
goto bad;
@@ -292,7 +323,7 @@ static int write_header(struct pstore *ps)
dh->version = cpu_to_le32(ps->version);
dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
- return chunk_io(ps, 0, WRITE);
+ return chunk_io(ps, 0, WRITE, 1);
}
/*
@@ -393,7 +424,7 @@ static int read_exceptions(struct pstore *ps)
return 0;
}
-static inline struct pstore *get_info(struct exception_store *store)
+static struct pstore *get_info(struct exception_store *store)
{
return (struct pstore *) store->context;
}
@@ -409,6 +440,7 @@ static void persistent_destroy(struct exception_store *store)
{
struct pstore *ps = get_info(store);
+ destroy_workqueue(ps->metadata_wq);
dm_io_client_destroy(ps->io_client);
vfree(ps->callbacks);
free_area(ps);
@@ -457,11 +489,6 @@ static int persistent_read_metadata(struct exception_store *store)
/*
* Sanity checks.
*/
- if (!ps->valid) {
- DMWARN("snapshot is marked invalid");
- return -EINVAL;
- }
-
if (ps->version != SNAPSHOT_DISK_VERSION) {
DMWARN("unable to handle snapshot disk version %d",
ps->version);
@@ -469,6 +496,12 @@ static int persistent_read_metadata(struct exception_store *store)
}
/*
+ * Metadata are valid, but snapshot is invalidated
+ */
+ if (!ps->valid)
+ return 1;
+
+ /*
* Read the metadata.
*/
r = read_exceptions(ps);
@@ -480,7 +513,7 @@ static int persistent_read_metadata(struct exception_store *store)
}
static int persistent_prepare(struct exception_store *store,
- struct exception *e)
+ struct dm_snap_exception *e)
{
struct pstore *ps = get_info(store);
uint32_t stride;
@@ -505,7 +538,7 @@ static int persistent_prepare(struct exception_store *store,
}
static void persistent_commit(struct exception_store *store,
- struct exception *e,
+ struct dm_snap_exception *e,
void (*callback) (void *, int success),
void *callback_context)
{
@@ -588,6 +621,12 @@ int dm_create_persistent(struct exception_store *store)
atomic_set(&ps->pending_count, 0);
ps->callbacks = NULL;
+ ps->metadata_wq = create_singlethread_workqueue("ksnaphd");
+ if (!ps->metadata_wq) {
+ DMERR("couldn't start header metadata update thread");
+ return -ENOMEM;
+ }
+
store->destroy = persistent_destroy;
store->read_metadata = persistent_read_metadata;
store->prepare_exception = persistent_prepare;
@@ -616,7 +655,8 @@ static int transient_read_metadata(struct exception_store *store)
return 0;
}
-static int transient_prepare(struct exception_store *store, struct exception *e)
+static int transient_prepare(struct exception_store *store,
+ struct dm_snap_exception *e)
{
struct transient_c *tc = (struct transient_c *) store->context;
sector_t size = get_dev_size(store->snap->cow->bdev);
@@ -631,9 +671,9 @@ static int transient_prepare(struct exception_store *store, struct exception *e)
}
static void transient_commit(struct exception_store *store,
- struct exception *e,
- void (*callback) (void *, int success),
- void *callback_context)
+ struct dm_snap_exception *e,
+ void (*callback) (void *, int success),
+ void *callback_context)
{
/* Just succeed */
callback(callback_context, 1);
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index 352c6fbeac5..f3a77248643 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -293,7 +293,10 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
* bvec for bio_get/set_region() and decrement bi_max_vecs
* to hide it from bio_add_page().
*/
- num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2;
+ num_bvecs = dm_sector_div_up(remaining,
+ (PAGE_SIZE >> SECTOR_SHIFT));
+ num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev),
+ num_bvecs);
bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios);
bio->bi_sector = where->sector + (where->count - remaining);
bio->bi_bdev = where->bdev;
diff --git a/drivers/md/dm-mpath-rdac.c b/drivers/md/dm-mpath-rdac.c
new file mode 100644
index 00000000000..8b776b8cb7f
--- /dev/null
+++ b/drivers/md/dm-mpath-rdac.c
@@ -0,0 +1,700 @@
+/*
+ * Engenio/LSI RDAC DM HW handler
+ *
+ * Copyright (C) 2005 Mike Christie. All rights reserved.
+ * Copyright (C) Chandra Seetharaman, IBM Corp. 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+
+#define DM_MSG_PREFIX "multipath rdac"
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+#define RDAC_DM_HWH_NAME "rdac"
+#define RDAC_DM_HWH_VER "0.4"
+
+/*
+ * LSI mode page stuff
+ *
+ * These struct definitions and the forming of the
+ * mode page were taken from the LSI RDAC 2.4 GPL'd
+ * driver, and then converted to Linux conventions.
+ */
+#define RDAC_QUIESCENCE_TIME 20;
+/*
+ * Page Codes
+ */
+#define RDAC_PAGE_CODE_REDUNDANT_CONTROLLER 0x2c
+
+/*
+ * Controller modes definitions
+ */
+#define RDAC_MODE_TRANSFER_ALL_LUNS 0x01
+#define RDAC_MODE_TRANSFER_SPECIFIED_LUNS 0x02
+
+/*
+ * RDAC Options field
+ */
+#define RDAC_FORCED_QUIESENCE 0x02
+
+#define RDAC_FAILOVER_TIMEOUT (60 * HZ)
+
+struct rdac_mode_6_hdr {
+ u8 data_len;
+ u8 medium_type;
+ u8 device_params;
+ u8 block_desc_len;
+};
+
+struct rdac_mode_10_hdr {
+ u16 data_len;
+ u8 medium_type;
+ u8 device_params;
+ u16 reserved;
+ u16 block_desc_len;
+};
+
+struct rdac_mode_common {
+ u8 controller_serial[16];
+ u8 alt_controller_serial[16];
+ u8 rdac_mode[2];
+ u8 alt_rdac_mode[2];
+ u8 quiescence_timeout;
+ u8 rdac_options;
+};
+
+struct rdac_pg_legacy {
+ struct rdac_mode_6_hdr hdr;
+ u8 page_code;
+ u8 page_len;
+ struct rdac_mode_common common;
+#define MODE6_MAX_LUN 32
+ u8 lun_table[MODE6_MAX_LUN];
+ u8 reserved2[32];
+ u8 reserved3;
+ u8 reserved4;
+};
+
+struct rdac_pg_expanded {
+ struct rdac_mode_10_hdr hdr;
+ u8 page_code;
+ u8 subpage_code;
+ u8 page_len[2];
+ struct rdac_mode_common common;
+ u8 lun_table[256];
+ u8 reserved3;
+ u8 reserved4;
+};
+
+struct c9_inquiry {
+ u8 peripheral_info;
+ u8 page_code; /* 0xC9 */
+ u8 reserved1;
+ u8 page_len;
+ u8 page_id[4]; /* "vace" */
+ u8 avte_cvp;
+ u8 path_prio;
+ u8 reserved2[38];
+};
+
+#define SUBSYS_ID_LEN 16
+#define SLOT_ID_LEN 2
+
+struct c4_inquiry {
+ u8 peripheral_info;
+ u8 page_code; /* 0xC4 */
+ u8 reserved1;
+ u8 page_len;
+ u8 page_id[4]; /* "subs" */
+ u8 subsys_id[SUBSYS_ID_LEN];
+ u8 revision[4];
+ u8 slot_id[SLOT_ID_LEN];
+ u8 reserved[2];
+};
+
+struct rdac_controller {
+ u8 subsys_id[SUBSYS_ID_LEN];
+ u8 slot_id[SLOT_ID_LEN];
+ int use_10_ms;
+ struct kref kref;
+ struct list_head node; /* list of all controllers */
+ spinlock_t lock;
+ int submitted;
+ struct list_head cmd_list; /* list of commands to be submitted */
+ union {
+ struct rdac_pg_legacy legacy;
+ struct rdac_pg_expanded expanded;
+ } mode_select;
+};
+struct c8_inquiry {
+ u8 peripheral_info;
+ u8 page_code; /* 0xC8 */
+ u8 reserved1;
+ u8 page_len;
+ u8 page_id[4]; /* "edid" */
+ u8 reserved2[3];
+ u8 vol_uniq_id_len;
+ u8 vol_uniq_id[16];
+ u8 vol_user_label_len;
+ u8 vol_user_label[60];
+ u8 array_uniq_id_len;
+ u8 array_unique_id[16];
+ u8 array_user_label_len;
+ u8 array_user_label[60];
+ u8 lun[8];
+};
+
+struct c2_inquiry {
+ u8 peripheral_info;
+ u8 page_code; /* 0xC2 */
+ u8 reserved1;
+ u8 page_len;
+ u8 page_id[4]; /* "swr4" */
+ u8 sw_version[3];
+ u8 sw_date[3];
+ u8 features_enabled;
+ u8 max_lun_supported;
+ u8 partitions[239]; /* Total allocation length should be 0xFF */
+};
+
+struct rdac_handler {
+ struct list_head entry; /* list waiting to submit MODE SELECT */
+ unsigned timeout;
+ struct rdac_controller *ctlr;
+#define UNINITIALIZED_LUN (1 << 8)
+ unsigned lun;
+ unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+ struct dm_path *path;
+ struct work_struct work;
+#define SEND_C2_INQUIRY 1
+#define SEND_C4_INQUIRY 2
+#define SEND_C8_INQUIRY 3
+#define SEND_C9_INQUIRY 4
+#define SEND_MODE_SELECT 5
+ int cmd_to_send;
+ union {
+ struct c2_inquiry c2;
+ struct c4_inquiry c4;
+ struct c8_inquiry c8;
+ struct c9_inquiry c9;
+ } inq;
+};
+
+static LIST_HEAD(ctlr_list);
+static DEFINE_SPINLOCK(list_lock);
+static struct workqueue_struct *rdac_wkqd;
+
+static inline int had_failures(struct request *req, int error)
+{
+ return (error || host_byte(req->errors) != DID_OK ||
+ msg_byte(req->errors) != COMMAND_COMPLETE);
+}
+
+static void rdac_resubmit_all(struct rdac_handler *h)
+{
+ struct rdac_controller *ctlr = h->ctlr;
+ struct rdac_handler *tmp, *h1;
+
+ spin_lock(&ctlr->lock);
+ list_for_each_entry_safe(h1, tmp, &ctlr->cmd_list, entry) {
+ h1->cmd_to_send = SEND_C9_INQUIRY;
+ queue_work(rdac_wkqd, &h1->work);
+ list_del(&h1->entry);
+ }
+ ctlr->submitted = 0;
+ spin_unlock(&ctlr->lock);
+}
+
+static void mode_select_endio(struct request *req, int error)
+{
+ struct rdac_handler *h = req->end_io_data;
+ struct scsi_sense_hdr sense_hdr;
+ int sense = 0, fail = 0;
+
+ if (had_failures(req, error)) {
+ fail = 1;
+ goto failed;
+ }
+
+ if (status_byte(req->errors) == CHECK_CONDITION) {
+ scsi_normalize_sense(req->sense, SCSI_SENSE_BUFFERSIZE,
+ &sense_hdr);
+ sense = (sense_hdr.sense_key << 16) | (sense_hdr.asc << 8) |
+ sense_hdr.ascq;
+ /* If it is retryable failure, submit the c9 inquiry again */
+ if (sense == 0x59136 || sense == 0x68b02 || sense == 0xb8b02 ||
+ sense == 0x62900) {
+ /* 0x59136 - Command lock contention
+ * 0x[6b]8b02 - Quiesense in progress or achieved
+ * 0x62900 - Power On, Reset, or Bus Device Reset
+ */
+ h->cmd_to_send = SEND_C9_INQUIRY;
+ queue_work(rdac_wkqd, &h->work);
+ goto done;
+ }
+ if (sense)
+ DMINFO("MODE_SELECT failed on %s with sense 0x%x",
+ h->path->dev->name, sense);
+ }
+failed:
+ if (fail || sense)
+ dm_pg_init_complete(h->path, MP_FAIL_PATH);
+ else
+ dm_pg_init_complete(h->path, 0);
+
+done:
+ rdac_resubmit_all(h);
+ __blk_put_request(req->q, req);
+}
+
+static struct request *get_rdac_req(struct rdac_handler *h,
+ void *buffer, unsigned buflen, int rw)
+{
+ struct request *rq;
+ struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+ rq = blk_get_request(q, rw, GFP_KERNEL);
+
+ if (!rq) {
+ DMINFO("get_rdac_req: blk_get_request failed");
+ return NULL;
+ }
+
+ if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_KERNEL)) {
+ blk_put_request(rq);
+ DMINFO("get_rdac_req: blk_rq_map_kern failed");
+ return NULL;
+ }
+
+ memset(&rq->cmd, 0, BLK_MAX_CDB);
+ rq->sense = h->sense;
+ memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+ rq->sense_len = 0;
+
+ rq->end_io_data = h;
+ rq->timeout = h->timeout;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ rq->cmd_flags = REQ_FAILFAST | REQ_NOMERGE;
+ return rq;
+}
+
+static struct request *rdac_failover_get(struct rdac_handler *h)
+{
+ struct request *rq;
+ struct rdac_mode_common *common;
+ unsigned data_size;
+
+ if (h->ctlr->use_10_ms) {
+ struct rdac_pg_expanded *rdac_pg;
+
+ data_size = sizeof(struct rdac_pg_expanded);
+ rdac_pg = &h->ctlr->mode_select.expanded;
+ memset(rdac_pg, 0, data_size);
+ common = &rdac_pg->common;
+ rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40;
+ rdac_pg->subpage_code = 0x1;
+ rdac_pg->page_len[0] = 0x01;
+ rdac_pg->page_len[1] = 0x28;
+ rdac_pg->lun_table[h->lun] = 0x81;
+ } else {
+ struct rdac_pg_legacy *rdac_pg;
+
+ data_size = sizeof(struct rdac_pg_legacy);
+ rdac_pg = &h->ctlr->mode_select.legacy;
+ memset(rdac_pg, 0, data_size);
+ common = &rdac_pg->common;
+ rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
+ rdac_pg->page_len = 0x68;
+ rdac_pg->lun_table[h->lun] = 0x81;
+ }
+ common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;
+ common->quiescence_timeout = RDAC_QUIESCENCE_TIME;
+ common->rdac_options = RDAC_FORCED_QUIESENCE;
+
+ /* get request for block layer packet command */
+ rq = get_rdac_req(h, &h->ctlr->mode_select, data_size, WRITE);
+ if (!rq) {
+ DMERR("rdac_failover_get: no rq");
+ return NULL;
+ }
+
+ /* Prepare the command. */
+ if (h->ctlr->use_10_ms) {
+ rq->cmd[0] = MODE_SELECT_10;
+ rq->cmd[7] = data_size >> 8;
+ rq->cmd[8] = data_size & 0xff;
+ } else {
+ rq->cmd[0] = MODE_SELECT;
+ rq->cmd[4] = data_size;
+ }
+ rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+
+ return rq;
+}
+
+/* Acquires h->ctlr->lock */
+static void submit_mode_select(struct rdac_handler *h)
+{
+ struct request *rq;
+ struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+ spin_lock(&h->ctlr->lock);
+ if (h->ctlr->submitted) {
+ list_add(&h->entry, &h->ctlr->cmd_list);
+ goto drop_lock;
+ }
+
+ if (!q) {
+ DMINFO("submit_mode_select: no queue");
+ goto fail_path;
+ }
+
+ rq = rdac_failover_get(h);
+ if (!rq) {
+ DMERR("submit_mode_select: no rq");
+ goto fail_path;
+ }
+
+ DMINFO("queueing MODE_SELECT command on %s", h->path->dev->name);
+
+ blk_execute_rq_nowait(q, NULL, rq, 1, mode_select_endio);
+ h->ctlr->submitted = 1;
+ goto drop_lock;
+fail_path:
+ dm_pg_init_complete(h->path, MP_FAIL_PATH);
+drop_lock:
+ spin_unlock(&h->ctlr->lock);
+}
+
+static void release_ctlr(struct kref *kref)
+{
+ struct rdac_controller *ctlr;
+ ctlr = container_of(kref, struct rdac_controller, kref);
+
+ spin_lock(&list_lock);
+ list_del(&ctlr->node);
+ spin_unlock(&list_lock);
+ kfree(ctlr);
+}
+
+static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id)
+{
+ struct rdac_controller *ctlr, *tmp;
+
+ spin_lock(&list_lock);
+
+ list_for_each_entry(tmp, &ctlr_list, node) {
+ if ((memcmp(tmp->subsys_id, subsys_id, SUBSYS_ID_LEN) == 0) &&
+ (memcmp(tmp->slot_id, slot_id, SLOT_ID_LEN) == 0)) {
+ kref_get(&tmp->kref);
+ spin_unlock(&list_lock);
+ return tmp;
+ }
+ }
+ ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC);
+ if (!ctlr)
+ goto done;
+
+ /* initialize fields of controller */
+ memcpy(ctlr->subsys_id, subsys_id, SUBSYS_ID_LEN);
+ memcpy(ctlr->slot_id, slot_id, SLOT_ID_LEN);
+ kref_init(&ctlr->kref);
+ spin_lock_init(&ctlr->lock);
+ ctlr->submitted = 0;
+ ctlr->use_10_ms = -1;
+ INIT_LIST_HEAD(&ctlr->cmd_list);
+ list_add(&ctlr->node, &ctlr_list);
+done:
+ spin_unlock(&list_lock);
+ return ctlr;
+}
+
+static void c4_endio(struct request *req, int error)
+{
+ struct rdac_handler *h = req->end_io_data;
+ struct c4_inquiry *sp;
+
+ if (had_failures(req, error)) {
+ dm_pg_init_complete(h->path, MP_FAIL_PATH);
+ goto done;
+ }
+
+ sp = &h->inq.c4;
+
+ h->ctlr = get_controller(sp->subsys_id, sp->slot_id);
+
+ if (h->ctlr) {
+ h->cmd_to_send = SEND_C9_INQUIRY;
+ queue_work(rdac_wkqd, &h->work);
+ } else
+ dm_pg_init_complete(h->path, MP_FAIL_PATH);
+done:
+ __blk_put_request(req->q, req);
+}
+
+static void c2_endio(struct request *req, int error)
+{
+ struct rdac_handler *h = req->end_io_data;
+ struct c2_inquiry *sp;
+
+ if (had_failures(req, error)) {
+ dm_pg_init_complete(h->path, MP_FAIL_PATH);
+ goto done;
+ }
+
+ sp = &h->inq.c2;
+
+ /* If more than MODE6_MAX_LUN luns are supported, use mode select 10 */
+ if (sp->max_lun_supported >= MODE6_MAX_LUN)
+ h->ctlr->use_10_ms = 1;
+ else
+ h->ctlr->use_10_ms = 0;
+
+ h->cmd_to_send = SEND_MODE_SELECT;
+ queue_work(rdac_wkqd, &h->work);
+done:
+ __blk_put_request(req->q, req);
+}
+
+static void c9_endio(struct request *req, int error)
+{
+ struct rdac_handler *h = req->end_io_data;
+ struct c9_inquiry *sp;
+
+ if (had_failures(req, error)) {
+ dm_pg_init_complete(h->path, MP_FAIL_PATH);
+ goto done;
+ }
+
+ /* We need to look at the sense keys here to take clear action.
+ * For now simple logic: If the host is in AVT mode or if controller
+ * owns the lun, return dm_pg_init_complete(), otherwise submit
+ * MODE SELECT.
+ */
+ sp = &h->inq.c9;
+
+ /* If in AVT mode, return success */
+ if ((sp->avte_cvp >> 7) == 0x1) {
+ dm_pg_init_complete(h->path, 0);
+ goto done;
+ }
+
+ /* If the controller on this path owns the LUN, return success */
+ if (sp->avte_cvp & 0x1) {
+ dm_pg_init_complete(h->path, 0);
+ goto done;
+ }
+
+ if (h->ctlr) {
+ if (h->ctlr->use_10_ms == -1)
+ h->cmd_to_send = SEND_C2_INQUIRY;
+ else
+ h->cmd_to_send = SEND_MODE_SELECT;
+ } else
+ h->cmd_to_send = SEND_C4_INQUIRY;
+ queue_work(rdac_wkqd, &h->work);
+done:
+ __blk_put_request(req->q, req);
+}
+
+static void c8_endio(struct request *req, int error)
+{
+ struct rdac_handler *h = req->end_io_data;
+ struct c8_inquiry *sp;
+
+ if (had_failures(req, error)) {
+ dm_pg_init_complete(h->path, MP_FAIL_PATH);
+ goto done;
+ }
+
+ /* We need to look at the sense keys here to take clear action.
+ * For now simple logic: Get the lun from the inquiry page.
+ */
+ sp = &h->inq.c8;
+ h->lun = sp->lun[7]; /* currently it uses only one byte */
+ h->cmd_to_send = SEND_C9_INQUIRY;
+ queue_work(rdac_wkqd, &h->work);
+done:
+ __blk_put_request(req->q, req);
+}
+
+static void submit_inquiry(struct rdac_handler *h, int page_code,
+ unsigned int len, rq_end_io_fn endio)
+{
+ struct request *rq;
+ struct request_queue *q = bdev_get_queue(h->path->dev->bdev);
+
+ if (!q)
+ goto fail_path;
+
+ rq = get_rdac_req(h, &h->inq, len, READ);
+ if (!rq)
+ goto fail_path;
+
+ /* Prepare the command. */
+ rq->cmd[0] = INQUIRY;
+ rq->cmd[1] = 1;
+ rq->cmd[2] = page_code;
+ rq->cmd[4] = len;
+ rq->cmd_len = COMMAND_SIZE(INQUIRY);
+ blk_execute_rq_nowait(q, NULL, rq, 1, endio);
+ return;
+
+fail_path:
+ dm_pg_init_complete(h->path, MP_FAIL_PATH);
+}
+
+static void service_wkq(struct work_struct *work)
+{
+ struct rdac_handler *h = container_of(work, struct rdac_handler, work);
+
+ switch (h->cmd_to_send) {
+ case SEND_C2_INQUIRY:
+ submit_inquiry(h, 0xC2, sizeof(struct c2_inquiry), c2_endio);
+ break;
+ case SEND_C4_INQUIRY:
+ submit_inquiry(h, 0xC4, sizeof(struct c4_inquiry), c4_endio);
+ break;
+ case SEND_C8_INQUIRY:
+ submit_inquiry(h, 0xC8, sizeof(struct c8_inquiry), c8_endio);
+ break;
+ case SEND_C9_INQUIRY:
+ submit_inquiry(h, 0xC9, sizeof(struct c9_inquiry), c9_endio);
+ break;
+ case SEND_MODE_SELECT:
+ submit_mode_select(h);
+ break;
+ default:
+ BUG();
+ }
+}
+/*
+ * only support subpage2c until we confirm that this is just a matter of
+ * of updating firmware or not, and RDAC (basic AVT works already) for now
+ * but we can add these in in when we get time and testers
+ */
+static int rdac_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+ struct rdac_handler *h;
+ unsigned timeout;
+
+ if (argc == 0) {
+ /* No arguments: use defaults */
+ timeout = RDAC_FAILOVER_TIMEOUT;
+ } else if (argc != 1) {
+ DMWARN("incorrect number of arguments");
+ return -EINVAL;
+ } else {
+ if (sscanf(argv[1], "%u", &timeout) != 1) {
+ DMWARN("invalid timeout value");
+ return -EINVAL;
+ }
+ }
+
+ h = kzalloc(sizeof(*h), GFP_KERNEL);
+ if (!h)
+ return -ENOMEM;
+
+ hwh->context = h;
+ h->timeout = timeout;
+ h->lun = UNINITIALIZED_LUN;
+ INIT_WORK(&h->work, service_wkq);
+ DMWARN("using RDAC command with timeout %u", h->timeout);
+
+ return 0;
+}
+
+static void rdac_destroy(struct hw_handler *hwh)
+{
+ struct rdac_handler *h = hwh->context;
+
+ if (h->ctlr)
+ kref_put(&h->ctlr->kref, release_ctlr);
+ kfree(h);
+ hwh->context = NULL;
+}
+
+static unsigned rdac_error(struct hw_handler *hwh, struct bio *bio)
+{
+ /* Try default handler */
+ return dm_scsi_err_handler(hwh, bio);
+}
+
+static void rdac_pg_init(struct hw_handler *hwh, unsigned bypassed,
+ struct dm_path *path)
+{
+ struct rdac_handler *h = hwh->context;
+
+ h->path = path;
+ switch (h->lun) {
+ case UNINITIALIZED_LUN:
+ submit_inquiry(h, 0xC8, sizeof(struct c8_inquiry), c8_endio);
+ break;
+ default:
+ submit_inquiry(h, 0xC9, sizeof(struct c9_inquiry), c9_endio);
+ }
+}
+
+static struct hw_handler_type rdac_handler = {
+ .name = RDAC_DM_HWH_NAME,
+ .module = THIS_MODULE,
+ .create = rdac_create,
+ .destroy = rdac_destroy,
+ .pg_init = rdac_pg_init,
+ .error = rdac_error,
+};
+
+static int __init rdac_init(void)
+{
+ int r = dm_register_hw_handler(&rdac_handler);
+
+ if (r < 0) {
+ DMERR("%s: register failed %d", RDAC_DM_HWH_NAME, r);
+ return r;
+ }
+
+ rdac_wkqd = create_singlethread_workqueue("rdac_wkqd");
+ if (!rdac_wkqd) {
+ DMERR("Failed to create workqueue rdac_wkqd.");
+ dm_unregister_hw_handler(&rdac_handler);
+ return -ENOMEM;
+ }
+
+ DMINFO("%s: version %s loaded", RDAC_DM_HWH_NAME, RDAC_DM_HWH_VER);
+ return 0;
+}
+
+static void __exit rdac_exit(void)
+{
+ int r = dm_unregister_hw_handler(&rdac_handler);
+
+ destroy_workqueue(rdac_wkqd);
+ if (r < 0)
+ DMERR("%s: unregister failed %d", RDAC_DM_HWH_NAME, r);
+}
+
+module_init(rdac_init);
+module_exit(rdac_exit);
+
+MODULE_DESCRIPTION("DM Multipath LSI/Engenio RDAC support");
+MODULE_AUTHOR("Mike Christie, Chandra Seetharaman");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RDAC_DM_HWH_VER);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index de54b39e6ff..d6ca9d0a6fd 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -83,7 +83,7 @@ struct multipath {
struct work_struct trigger_event;
/*
- * We must use a mempool of mpath_io structs so that we
+ * We must use a mempool of dm_mpath_io structs so that we
* can resubmit bios on error.
*/
mempool_t *mpio_pool;
@@ -92,7 +92,7 @@ struct multipath {
/*
* Context information attached to each bio we process.
*/
-struct mpath_io {
+struct dm_mpath_io {
struct pgpath *pgpath;
struct dm_bio_details details;
};
@@ -122,7 +122,7 @@ static struct pgpath *alloc_pgpath(void)
return pgpath;
}
-static inline void free_pgpath(struct pgpath *pgpath)
+static void free_pgpath(struct pgpath *pgpath)
{
kfree(pgpath);
}
@@ -299,8 +299,8 @@ static int __must_push_back(struct multipath *m)
dm_noflush_suspending(m->ti));
}
-static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
- unsigned was_queued)
+static int map_io(struct multipath *m, struct bio *bio,
+ struct dm_mpath_io *mpio, unsigned was_queued)
{
int r = DM_MAPIO_REMAPPED;
unsigned long flags;
@@ -374,7 +374,7 @@ static void dispatch_queued_ios(struct multipath *m)
int r;
unsigned long flags;
struct bio *bio = NULL, *next;
- struct mpath_io *mpio;
+ struct dm_mpath_io *mpio;
union map_info *info;
spin_lock_irqsave(&m->lock, flags);
@@ -795,12 +795,9 @@ static int multipath_map(struct dm_target *ti, struct bio *bio,
union map_info *map_context)
{
int r;
- struct mpath_io *mpio;
+ struct dm_mpath_io *mpio;
struct multipath *m = (struct multipath *) ti->private;
- if (bio_barrier(bio))
- return -EOPNOTSUPP;
-
mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
dm_bio_record(&mpio->details, bio);
@@ -1014,7 +1011,7 @@ void dm_pg_init_complete(struct dm_path *path, unsigned err_flags)
* end_io handling
*/
static int do_end_io(struct multipath *m, struct bio *bio,
- int error, struct mpath_io *mpio)
+ int error, struct dm_mpath_io *mpio)
{
struct hw_handler *hwh = &m->hw_handler;
unsigned err_flags = MP_FAIL_PATH; /* Default behavior */
@@ -1075,8 +1072,8 @@ static int do_end_io(struct multipath *m, struct bio *bio,
static int multipath_end_io(struct dm_target *ti, struct bio *bio,
int error, union map_info *map_context)
{
- struct multipath *m = (struct multipath *) ti->private;
- struct mpath_io *mpio = (struct mpath_io *) map_context->ptr;
+ struct multipath *m = ti->private;
+ struct dm_mpath_io *mpio = map_context->ptr;
struct pgpath *pgpath = mpio->pgpath;
struct path_selector *ps;
int r;
@@ -1346,22 +1343,20 @@ static int __init dm_multipath_init(void)
int r;
/* allocate a slab for the dm_ios */
- _mpio_cache = kmem_cache_create("dm_mpath", sizeof(struct mpath_io),
- 0, 0, NULL, NULL);
+ _mpio_cache = KMEM_CACHE(dm_mpath_io, 0);
if (!_mpio_cache)
return -ENOMEM;
r = dm_register_target(&multipath_target);
if (r < 0) {
- DMERR("%s: register failed %d", multipath_target.name, r);
+ DMERR("register failed %d", r);
kmem_cache_destroy(_mpio_cache);
return -EINVAL;
}
kmultipathd = create_workqueue("kmpathd");
if (!kmultipathd) {
- DMERR("%s: failed to create workqueue kmpathd",
- multipath_target.name);
+ DMERR("failed to create workqueue kmpathd");
dm_unregister_target(&multipath_target);
kmem_cache_destroy(_mpio_cache);
return -ENOMEM;
@@ -1382,8 +1377,7 @@ static void __exit dm_multipath_exit(void)
r = dm_unregister_target(&multipath_target);
if (r < 0)
- DMERR("%s: target unregister failed %d",
- multipath_target.name, r);
+ DMERR("target unregister failed %d", r);
kmem_cache_destroy(_mpio_cache);
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index ef124b71ccc..1a876f9965e 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -24,6 +24,7 @@
#define DM_IO_PAGES 64
#define DM_RAID1_HANDLE_ERRORS 0x01
+#define errors_handled(p) ((p)->features & DM_RAID1_HANDLE_ERRORS)
static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped);
@@ -85,6 +86,7 @@ struct region_hash {
struct list_head clean_regions;
struct list_head quiesced_regions;
struct list_head recovered_regions;
+ struct list_head failed_recovered_regions;
};
enum {
@@ -132,6 +134,7 @@ struct mirror_set {
/* recovery */
region_t nr_regions;
int in_sync;
+ int log_failure;
struct mirror *default_mirror; /* Default mirror */
@@ -204,6 +207,7 @@ static int rh_init(struct region_hash *rh, struct mirror_set *ms,
INIT_LIST_HEAD(&rh->clean_regions);
INIT_LIST_HEAD(&rh->quiesced_regions);
INIT_LIST_HEAD(&rh->recovered_regions);
+ INIT_LIST_HEAD(&rh->failed_recovered_regions);
rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS,
sizeof(struct region));
@@ -368,6 +372,7 @@ static void rh_update_states(struct region_hash *rh)
LIST_HEAD(clean);
LIST_HEAD(recovered);
+ LIST_HEAD(failed_recovered);
/*
* Quickly grab the lists.
@@ -378,10 +383,8 @@ static void rh_update_states(struct region_hash *rh)
list_splice(&rh->clean_regions, &clean);
INIT_LIST_HEAD(&rh->clean_regions);
- list_for_each_entry (reg, &clean, list) {
- rh->log->type->clear_region(rh->log, reg->key);
+ list_for_each_entry(reg, &clean, list)
list_del(&reg->hash_list);
- }
}
if (!list_empty(&rh->recovered_regions)) {
@@ -391,6 +394,15 @@ static void rh_update_states(struct region_hash *rh)
list_for_each_entry (reg, &recovered, list)
list_del(&reg->hash_list);
}
+
+ if (!list_empty(&rh->failed_recovered_regions)) {
+ list_splice(&rh->failed_recovered_regions, &failed_recovered);
+ INIT_LIST_HEAD(&rh->failed_recovered_regions);
+
+ list_for_each_entry(reg, &failed_recovered, list)
+ list_del(&reg->hash_list);
+ }
+
spin_unlock(&rh->region_lock);
write_unlock_irq(&rh->hash_lock);
@@ -405,10 +417,17 @@ static void rh_update_states(struct region_hash *rh)
mempool_free(reg, rh->region_pool);
}
- rh->log->type->flush(rh->log);
+ list_for_each_entry_safe(reg, next, &failed_recovered, list) {
+ complete_resync_work(reg, errors_handled(rh->ms) ? 0 : 1);
+ mempool_free(reg, rh->region_pool);
+ }
- list_for_each_entry_safe (reg, next, &clean, list)
+ list_for_each_entry_safe(reg, next, &clean, list) {
+ rh->log->type->clear_region(rh->log, reg->key);
mempool_free(reg, rh->region_pool);
+ }
+
+ rh->log->type->flush(rh->log);
}
static void rh_inc(struct region_hash *rh, region_t region)
@@ -555,21 +574,25 @@ static struct region *rh_recovery_start(struct region_hash *rh)
return reg;
}
-/* FIXME: success ignored for now */
static void rh_recovery_end(struct region *reg, int success)
{
struct region_hash *rh = reg->rh;
spin_lock_irq(&rh->region_lock);
- list_add(&reg->list, &reg->rh->recovered_regions);
+ if (success)
+ list_add(&reg->list, &reg->rh->recovered_regions);
+ else {
+ reg->state = RH_NOSYNC;
+ list_add(&reg->list, &reg->rh->failed_recovered_regions);
+ }
spin_unlock_irq(&rh->region_lock);
wake(rh->ms);
}
-static void rh_flush(struct region_hash *rh)
+static int rh_flush(struct region_hash *rh)
{
- rh->log->type->flush(rh->log);
+ return rh->log->type->flush(rh->log);
}
static void rh_delay(struct region_hash *rh, struct bio *bio)
@@ -633,7 +656,14 @@ static void recovery_complete(int read_err, unsigned int write_err,
{
struct region *reg = (struct region *) context;
- /* FIXME: better error handling */
+ if (read_err)
+ /* Read error means the failure of default mirror. */
+ DMERR_LIMIT("Unable to read primary mirror during recovery");
+
+ if (write_err)
+ DMERR_LIMIT("Write error during recovery (error = 0x%x)",
+ write_err);
+
rh_recovery_end(reg, !(read_err || write_err));
}
@@ -863,12 +893,15 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
*/
rh_inc_pending(&ms->rh, &sync);
rh_inc_pending(&ms->rh, &nosync);
- rh_flush(&ms->rh);
+ ms->log_failure = rh_flush(&ms->rh) ? 1 : 0;
/*
* Dispatch io.
*/
- while ((bio = bio_list_pop(&sync)))
+ if (unlikely(ms->log_failure))
+ while ((bio = bio_list_pop(&sync)))
+ bio_endio(bio, bio->bi_size, -EIO);
+ else while ((bio = bio_list_pop(&sync)))
do_write(ms, bio);
while ((bio = bio_list_pop(&recover)))
@@ -1145,6 +1178,15 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
argv += args_used;
argc -= args_used;
+ /*
+ * Any read-balancing addition depends on the
+ * DM_RAID1_HANDLE_ERRORS flag being present.
+ * This is because the decision to balance depends
+ * on the sync state of a region. If the above
+ * flag is not present, we ignore errors; and
+ * the sync state may be inaccurate.
+ */
+
if (argc) {
ti->error = "Too many mirror arguments";
free_context(ms, ti, ms->nr_mirrors);
@@ -1288,12 +1330,12 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
for (m = 0; m < ms->nr_mirrors; m++)
DMEMIT("%s ", ms->mirror[m].dev->name);
- DMEMIT("%llu/%llu",
+ DMEMIT("%llu/%llu 0 ",
(unsigned long long)ms->rh.log->type->
get_sync_count(ms->rh.log),
(unsigned long long)ms->nr_regions);
- sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
+ sz += ms->rh.log->type->status(ms->rh.log, type, result+sz, maxlen-sz);
break;
@@ -1335,8 +1377,7 @@ static int __init dm_mirror_init(void)
r = dm_register_target(&mirror_target);
if (r < 0) {
- DMERR("%s: Failed to register mirror target",
- mirror_target.name);
+ DMERR("Failed to register mirror target");
dm_dirty_log_exit();
}
@@ -1349,7 +1390,7 @@ static void __exit dm_mirror_exit(void)
r = dm_unregister_target(&mirror_target);
if (r < 0)
- DMERR("%s: unregister failed %d", mirror_target.name, r);
+ DMERR("unregister failed %d", r);
dm_dirty_log_exit();
}
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
index a348a97b65a..391dfa2ad43 100644
--- a/drivers/md/dm-round-robin.c
+++ b/drivers/md/dm-round-robin.c
@@ -205,7 +205,7 @@ static void __exit dm_rr_exit(void)
int r = dm_unregister_path_selector(&rr_ps);
if (r < 0)
- DMERR("round-robin: unregister failed %d", r);
+ DMERR("unregister failed %d", r);
}
module_init(dm_rr_init);
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 0821a2b68a7..83ddbfe6b8a 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -42,8 +42,8 @@
static struct workqueue_struct *ksnapd;
static void flush_queued_bios(struct work_struct *work);
-struct pending_exception {
- struct exception e;
+struct dm_snap_pending_exception {
+ struct dm_snap_exception e;
/*
* Origin buffers waiting for this to complete are held
@@ -63,7 +63,7 @@ struct pending_exception {
* group of pending_exceptions. It is always last to get freed.
* These fields get set up when writing to the origin.
*/
- struct pending_exception *primary_pe;
+ struct dm_snap_pending_exception *primary_pe;
/*
* Number of pending_exceptions processing this chunk.
@@ -137,7 +137,7 @@ static void exit_origin_hash(void)
kfree(_origins);
}
-static inline unsigned int origin_hash(struct block_device *bdev)
+static unsigned origin_hash(struct block_device *bdev)
{
return bdev->bd_dev & ORIGIN_MASK;
}
@@ -231,7 +231,7 @@ static int init_exception_table(struct exception_table *et, uint32_t size)
static void exit_exception_table(struct exception_table *et, struct kmem_cache *mem)
{
struct list_head *slot;
- struct exception *ex, *next;
+ struct dm_snap_exception *ex, *next;
int i, size;
size = et->hash_mask + 1;
@@ -245,18 +245,19 @@ static void exit_exception_table(struct exception_table *et, struct kmem_cache *
vfree(et->table);
}
-static inline uint32_t exception_hash(struct exception_table *et, chunk_t chunk)
+static uint32_t exception_hash(struct exception_table *et, chunk_t chunk)
{
return chunk & et->hash_mask;
}
-static void insert_exception(struct exception_table *eh, struct exception *e)
+static void insert_exception(struct exception_table *eh,
+ struct dm_snap_exception *e)
{
struct list_head *l = &eh->table[exception_hash(eh, e->old_chunk)];
list_add(&e->hash_list, l);
}
-static inline void remove_exception(struct exception *e)
+static void remove_exception(struct dm_snap_exception *e)
{
list_del(&e->hash_list);
}
@@ -265,11 +266,11 @@ static inline void remove_exception(struct exception *e)
* Return the exception data for a sector, or NULL if not
* remapped.
*/
-static struct exception *lookup_exception(struct exception_table *et,
- chunk_t chunk)
+static struct dm_snap_exception *lookup_exception(struct exception_table *et,
+ chunk_t chunk)
{
struct list_head *slot;
- struct exception *e;
+ struct dm_snap_exception *e;
slot = &et->table[exception_hash(et, chunk)];
list_for_each_entry (e, slot, hash_list)
@@ -279,9 +280,9 @@ static struct exception *lookup_exception(struct exception_table *et,
return NULL;
}
-static inline struct exception *alloc_exception(void)
+static struct dm_snap_exception *alloc_exception(void)
{
- struct exception *e;
+ struct dm_snap_exception *e;
e = kmem_cache_alloc(exception_cache, GFP_NOIO);
if (!e)
@@ -290,24 +291,24 @@ static inline struct exception *alloc_exception(void)
return e;
}
-static inline void free_exception(struct exception *e)
+static void free_exception(struct dm_snap_exception *e)
{
kmem_cache_free(exception_cache, e);
}
-static inline struct pending_exception *alloc_pending_exception(void)
+static struct dm_snap_pending_exception *alloc_pending_exception(void)
{
return mempool_alloc(pending_pool, GFP_NOIO);
}
-static inline void free_pending_exception(struct pending_exception *pe)
+static void free_pending_exception(struct dm_snap_pending_exception *pe)
{
mempool_free(pe, pending_pool);
}
int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new)
{
- struct exception *e;
+ struct dm_snap_exception *e;
e = alloc_exception();
if (!e)
@@ -334,7 +335,7 @@ static int calc_max_buckets(void)
/*
* Rounds a number down to a power of 2.
*/
-static inline uint32_t round_down(uint32_t n)
+static uint32_t round_down(uint32_t n)
{
while (n & (n - 1))
n &= (n - 1);
@@ -384,7 +385,7 @@ static int init_hash_tables(struct dm_snapshot *s)
* Round a number up to the nearest 'size' boundary. size must
* be a power of 2.
*/
-static inline ulong round_up(ulong n, ulong size)
+static ulong round_up(ulong n, ulong size)
{
size--;
return (n + size) & ~size;
@@ -522,9 +523,12 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
/* Metadata must only be loaded into one table at once */
r = s->store.read_metadata(&s->store);
- if (r) {
+ if (r < 0) {
ti->error = "Failed to read snapshot metadata";
goto bad6;
+ } else if (r > 0) {
+ s->valid = 0;
+ DMWARN("Snapshot is marked invalid.");
}
bio_list_init(&s->queued_bios);
@@ -577,7 +581,7 @@ static void __free_exceptions(struct dm_snapshot *s)
static void snapshot_dtr(struct dm_target *ti)
{
- struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+ struct dm_snapshot *s = ti->private;
flush_workqueue(ksnapd);
@@ -655,14 +659,14 @@ static void __invalidate_snapshot(struct dm_snapshot *s, int err)
dm_table_event(s->table);
}
-static void get_pending_exception(struct pending_exception *pe)
+static void get_pending_exception(struct dm_snap_pending_exception *pe)
{
atomic_inc(&pe->ref_count);
}
-static struct bio *put_pending_exception(struct pending_exception *pe)
+static struct bio *put_pending_exception(struct dm_snap_pending_exception *pe)
{
- struct pending_exception *primary_pe;
+ struct dm_snap_pending_exception *primary_pe;
struct bio *origin_bios = NULL;
primary_pe = pe->primary_pe;
@@ -692,9 +696,9 @@ static struct bio *put_pending_exception(struct pending_exception *pe)
return origin_bios;
}
-static void pending_complete(struct pending_exception *pe, int success)
+static void pending_complete(struct dm_snap_pending_exception *pe, int success)
{
- struct exception *e;
+ struct dm_snap_exception *e;
struct dm_snapshot *s = pe->snap;
struct bio *origin_bios = NULL;
struct bio *snapshot_bios = NULL;
@@ -748,7 +752,8 @@ static void pending_complete(struct pending_exception *pe, int success)
static void commit_callback(void *context, int success)
{
- struct pending_exception *pe = (struct pending_exception *) context;
+ struct dm_snap_pending_exception *pe = context;
+
pending_complete(pe, success);
}
@@ -758,7 +763,7 @@ static void commit_callback(void *context, int success)
*/
static void copy_callback(int read_err, unsigned int write_err, void *context)
{
- struct pending_exception *pe = (struct pending_exception *) context;
+ struct dm_snap_pending_exception *pe = context;
struct dm_snapshot *s = pe->snap;
if (read_err || write_err)
@@ -773,7 +778,7 @@ static void copy_callback(int read_err, unsigned int write_err, void *context)
/*
* Dispatches the copy operation to kcopyd.
*/
-static void start_copy(struct pending_exception *pe)
+static void start_copy(struct dm_snap_pending_exception *pe)
{
struct dm_snapshot *s = pe->snap;
struct io_region src, dest;
@@ -803,11 +808,11 @@ static void start_copy(struct pending_exception *pe)
* NOTE: a write lock must be held on snap->lock before calling
* this.
*/
-static struct pending_exception *
+static struct dm_snap_pending_exception *
__find_pending_exception(struct dm_snapshot *s, struct bio *bio)
{
- struct exception *e;
- struct pending_exception *pe;
+ struct dm_snap_exception *e;
+ struct dm_snap_pending_exception *pe;
chunk_t chunk = sector_to_chunk(s, bio->bi_sector);
/*
@@ -816,7 +821,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
e = lookup_exception(&s->pending, chunk);
if (e) {
/* cast the exception to a pending exception */
- pe = container_of(e, struct pending_exception, e);
+ pe = container_of(e, struct dm_snap_pending_exception, e);
goto out;
}
@@ -836,7 +841,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
e = lookup_exception(&s->pending, chunk);
if (e) {
free_pending_exception(pe);
- pe = container_of(e, struct pending_exception, e);
+ pe = container_of(e, struct dm_snap_pending_exception, e);
goto out;
}
@@ -860,8 +865,8 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
return pe;
}
-static inline void remap_exception(struct dm_snapshot *s, struct exception *e,
- struct bio *bio)
+static void remap_exception(struct dm_snapshot *s, struct dm_snap_exception *e,
+ struct bio *bio)
{
bio->bi_bdev = s->cow->bdev;
bio->bi_sector = chunk_to_sector(s, e->new_chunk) +
@@ -871,11 +876,11 @@ static inline void remap_exception(struct dm_snapshot *s, struct exception *e,
static int snapshot_map(struct dm_target *ti, struct bio *bio,
union map_info *map_context)
{
- struct exception *e;
- struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+ struct dm_snap_exception *e;
+ struct dm_snapshot *s = ti->private;
int r = DM_MAPIO_REMAPPED;
chunk_t chunk;
- struct pending_exception *pe = NULL;
+ struct dm_snap_pending_exception *pe = NULL;
chunk = sector_to_chunk(s, bio->bi_sector);
@@ -884,9 +889,6 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
if (!s->valid)
return -EIO;
- if (unlikely(bio_barrier(bio)))
- return -EOPNOTSUPP;
-
/* FIXME: should only take write lock if we need
* to copy an exception */
down_write(&s->lock);
@@ -945,7 +947,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
static void snapshot_resume(struct dm_target *ti)
{
- struct dm_snapshot *s = (struct dm_snapshot *) ti->private;
+ struct dm_snapshot *s = ti->private;
down_write(&s->lock);
s->active = 1;
@@ -955,7 +957,7 @@ static void snapshot_resume(struct dm_target *ti)
static int snapshot_status(struct dm_target *ti, status_type_t type,
char *result, unsigned int maxlen)
{
- struct dm_snapshot *snap = (struct dm_snapshot *) ti->private;
+ struct dm_snapshot *snap = ti->private;
switch (type) {
case STATUSTYPE_INFO:
@@ -999,8 +1001,8 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
{
int r = DM_MAPIO_REMAPPED, first = 0;
struct dm_snapshot *snap;
- struct exception *e;
- struct pending_exception *pe, *next_pe, *primary_pe = NULL;
+ struct dm_snap_exception *e;
+ struct dm_snap_pending_exception *pe, *next_pe, *primary_pe = NULL;
chunk_t chunk;
LIST_HEAD(pe_queue);
@@ -1147,19 +1149,16 @@ static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
static void origin_dtr(struct dm_target *ti)
{
- struct dm_dev *dev = (struct dm_dev *) ti->private;
+ struct dm_dev *dev = ti->private;
dm_put_device(ti, dev);
}
static int origin_map(struct dm_target *ti, struct bio *bio,
union map_info *map_context)
{
- struct dm_dev *dev = (struct dm_dev *) ti->private;
+ struct dm_dev *dev = ti->private;
bio->bi_bdev = dev->bdev;
- if (unlikely(bio_barrier(bio)))
- return -EOPNOTSUPP;
-
/* Only tell snapshots if this is a write */
return (bio_rw(bio) == WRITE) ? do_origin(dev, bio) : DM_MAPIO_REMAPPED;
}
@@ -1172,7 +1171,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio,
*/
static void origin_resume(struct dm_target *ti)
{
- struct dm_dev *dev = (struct dm_dev *) ti->private;
+ struct dm_dev *dev = ti->private;
struct dm_snapshot *snap;
struct origin *o;
chunk_t chunk_size = 0;
@@ -1190,7 +1189,7 @@ static void origin_resume(struct dm_target *ti)
static int origin_status(struct dm_target *ti, status_type_t type, char *result,
unsigned int maxlen)
{
- struct dm_dev *dev = (struct dm_dev *) ti->private;
+ struct dm_dev *dev = ti->private;
switch (type) {
case STATUSTYPE_INFO:
@@ -1249,21 +1248,14 @@ static int __init dm_snapshot_init(void)
goto bad2;
}
- exception_cache = kmem_cache_create("dm-snapshot-ex",
- sizeof(struct exception),
- __alignof__(struct exception),
- 0, NULL, NULL);
+ exception_cache = KMEM_CACHE(dm_snap_exception, 0);
if (!exception_cache) {
DMERR("Couldn't create exception cache.");
r = -ENOMEM;
goto bad3;
}
- pending_cache =
- kmem_cache_create("dm-snapshot-in",
- sizeof(struct pending_exception),
- __alignof__(struct pending_exception),
- 0, NULL, NULL);
+ pending_cache = KMEM_CACHE(dm_snap_pending_exception, 0);
if (!pending_cache) {
DMERR("Couldn't create pending cache.");
r = -ENOMEM;
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h
index 15fa2ae6cdc..650e0f1f51d 100644
--- a/drivers/md/dm-snap.h
+++ b/drivers/md/dm-snap.h
@@ -30,7 +30,7 @@ typedef sector_t chunk_t;
* An exception is used where an old chunk of data has been
* replaced by a new one.
*/
-struct exception {
+struct dm_snap_exception {
struct list_head hash_list;
chunk_t old_chunk;
@@ -58,13 +58,13 @@ struct exception_store {
* Find somewhere to store the next exception.
*/
int (*prepare_exception) (struct exception_store *store,
- struct exception *e);
+ struct dm_snap_exception *e);
/*
* Update the metadata with this exception.
*/
void (*commit_exception) (struct exception_store *store,
- struct exception *e,
+ struct dm_snap_exception *e,
void (*callback) (void *, int success),
void *callback_context);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 2717a355dc5..f4f7d35561a 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -45,7 +45,7 @@ struct dm_io {
* One of these is allocated per target within a bio. Hopefully
* this will be simplified out one day.
*/
-struct target_io {
+struct dm_target_io {
struct dm_io *io;
struct dm_target *ti;
union map_info info;
@@ -54,7 +54,7 @@ struct target_io {
union map_info *dm_get_mapinfo(struct bio *bio)
{
if (bio && bio->bi_private)
- return &((struct target_io *)bio->bi_private)->info;
+ return &((struct dm_target_io *)bio->bi_private)->info;
return NULL;
}
@@ -132,14 +132,12 @@ static int __init local_init(void)
int r;
/* allocate a slab for the dm_ios */
- _io_cache = kmem_cache_create("dm_io",
- sizeof(struct dm_io), 0, 0, NULL, NULL);
+ _io_cache = KMEM_CACHE(dm_io, 0);
if (!_io_cache)
return -ENOMEM;
/* allocate a slab for the target ios */
- _tio_cache = kmem_cache_create("dm_tio", sizeof(struct target_io),
- 0, 0, NULL, NULL);
+ _tio_cache = KMEM_CACHE(dm_target_io, 0);
if (!_tio_cache) {
kmem_cache_destroy(_io_cache);
return -ENOMEM;
@@ -325,22 +323,22 @@ out:
return r;
}
-static inline struct dm_io *alloc_io(struct mapped_device *md)
+static struct dm_io *alloc_io(struct mapped_device *md)
{
return mempool_alloc(md->io_pool, GFP_NOIO);
}
-static inline void free_io(struct mapped_device *md, struct dm_io *io)
+static void free_io(struct mapped_device *md, struct dm_io *io)
{
mempool_free(io, md->io_pool);
}
-static inline struct target_io *alloc_tio(struct mapped_device *md)
+static struct dm_target_io *alloc_tio(struct mapped_device *md)
{
return mempool_alloc(md->tio_pool, GFP_NOIO);
}
-static inline void free_tio(struct mapped_device *md, struct target_io *tio)
+static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
{
mempool_free(tio, md->tio_pool);
}
@@ -498,7 +496,7 @@ static void dec_pending(struct dm_io *io, int error)
static int clone_endio(struct bio *bio, unsigned int done, int error)
{
int r = 0;
- struct target_io *tio = bio->bi_private;
+ struct dm_target_io *tio = bio->bi_private;
struct mapped_device *md = tio->io->md;
dm_endio_fn endio = tio->ti->type->end_io;
@@ -558,7 +556,7 @@ static sector_t max_io_len(struct mapped_device *md,
}
static void __map_bio(struct dm_target *ti, struct bio *clone,
- struct target_io *tio)
+ struct dm_target_io *tio)
{
int r;
sector_t sector;
@@ -672,7 +670,7 @@ static void __clone_and_map(struct clone_info *ci)
struct bio *clone, *bio = ci->bio;
struct dm_target *ti = dm_table_find_target(ci->map, ci->sector);
sector_t len = 0, max = max_io_len(ci->md, ci->sector, ti);
- struct target_io *tio;
+ struct dm_target_io *tio;
/*
* Allocate a target io object.
@@ -802,6 +800,15 @@ static int dm_request(request_queue_t *q, struct bio *bio)
int rw = bio_data_dir(bio);
struct mapped_device *md = q->queuedata;
+ /*
+ * There is no use in forwarding any barrier request since we can't
+ * guarantee it is (or can be) handled by the targets correctly.
+ */
+ if (unlikely(bio_barrier(bio))) {
+ bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+ return 0;
+ }
+
down_read(&md->io_lock);
disk_stat_inc(dm_disk(md), ios[rw]);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 2f796b1436b..462ee652a89 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -18,13 +18,45 @@
#define DM_NAME "device-mapper"
-#define DMERR(f, arg...) printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
-#define DMWARN(f, arg...) printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
-#define DMINFO(f, arg...) printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMERR(f, arg...) \
+ printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMERR_LIMIT(f, arg...) \
+ do { \
+ if (printk_ratelimit()) \
+ printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " \
+ f "\n", ## arg); \
+ } while (0)
+
+#define DMWARN(f, arg...) \
+ printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMWARN_LIMIT(f, arg...) \
+ do { \
+ if (printk_ratelimit()) \
+ printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " \
+ f "\n", ## arg); \
+ } while (0)
+
+#define DMINFO(f, arg...) \
+ printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMINFO_LIMIT(f, arg...) \
+ do { \
+ if (printk_ratelimit()) \
+ printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f \
+ "\n", ## arg); \
+ } while (0)
+
#ifdef CONFIG_DM_DEBUG
-# define DMDEBUG(f, arg...) printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
+# define DMDEBUG(f, arg...) \
+ printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX " DEBUG: " f "\n", ## arg)
+# define DMDEBUG_LIMIT(f, arg...) \
+ do { \
+ if (printk_ratelimit()) \
+ printk(KERN_DEBUG DM_NAME ": " DM_MSG_PREFIX ": " f \
+ "\n", ## arg); \
+ } while (0)
#else
# define DMDEBUG(f, arg...) do {} while (0)
+# define DMDEBUG_LIMIT(f, arg...) do {} while (0)
#endif
#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index dbc234e3c69..7e052378c47 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -29,7 +29,7 @@
static struct workqueue_struct *_kcopyd_wq;
static struct work_struct _kcopyd_work;
-static inline void wake(void)
+static void wake(void)
{
queue_work(_kcopyd_wq, &_kcopyd_work);
}
@@ -226,10 +226,7 @@ static LIST_HEAD(_pages_jobs);
static int jobs_init(void)
{
- _job_cache = kmem_cache_create("kcopyd-jobs",
- sizeof(struct kcopyd_job),
- __alignof__(struct kcopyd_job),
- 0, NULL, NULL);
+ _job_cache = KMEM_CACHE(kcopyd_job, 0);
if (!_job_cache)
return -ENOMEM;
@@ -258,7 +255,7 @@ static void jobs_exit(void)
* Functions to push and pop a job onto the head of a given job
* list.
*/
-static inline struct kcopyd_job *pop(struct list_head *jobs)
+static struct kcopyd_job *pop(struct list_head *jobs)
{
struct kcopyd_job *job = NULL;
unsigned long flags;
@@ -274,7 +271,7 @@ static inline struct kcopyd_job *pop(struct list_head *jobs)
return job;
}
-static inline void push(struct list_head *jobs, struct kcopyd_job *job)
+static void push(struct list_head *jobs, struct kcopyd_job *job)
{
unsigned long flags;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 1c54f3c1cca..33beaa7da08 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5814,7 +5814,7 @@ static __exit void md_exit(void)
}
}
-module_init(md_init)
+subsys_initcall(md_init);
module_exit(md_exit)
static int get_ro(char *buffer, struct kernel_param *kp)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 3a95cc5e029..46677d7d998 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1240,17 +1240,24 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
}
r1_bio->read_disk = primary;
for (i=0; i<mddev->raid_disks; i++)
- if (r1_bio->bios[i]->bi_end_io == end_sync_read &&
- test_bit(BIO_UPTODATE, &r1_bio->bios[i]->bi_flags)) {
+ if (r1_bio->bios[i]->bi_end_io == end_sync_read) {
int j;
int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9);
struct bio *pbio = r1_bio->bios[primary];
struct bio *sbio = r1_bio->bios[i];
- for (j = vcnt; j-- ; )
- if (memcmp(page_address(pbio->bi_io_vec[j].bv_page),
- page_address(sbio->bi_io_vec[j].bv_page),
- PAGE_SIZE))
- break;
+
+ if (test_bit(BIO_UPTODATE, &sbio->bi_flags)) {
+ for (j = vcnt; j-- ; ) {
+ struct page *p, *s;
+ p = pbio->bi_io_vec[j].bv_page;
+ s = sbio->bi_io_vec[j].bv_page;
+ if (memcmp(page_address(p),
+ page_address(s),
+ PAGE_SIZE))
+ break;
+ }
+ } else
+ j = 0;
if (j >= 0)
mddev->resync_mismatches += r1_bio->sectors;
if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 82249a69014..9eb66c1b523 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1867,6 +1867,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
int d = r10_bio->devs[i].devnum;
bio = r10_bio->devs[i].bio;
bio->bi_end_io = NULL;
+ clear_bit(BIO_UPTODATE, &bio->bi_flags);
if (conf->mirrors[d].rdev == NULL ||
test_bit(Faulty, &conf->mirrors[d].rdev->flags))
continue;
@@ -2037,6 +2038,11 @@ static int run(mddev_t *mddev)
/* 'size' is now the number of chunks in the array */
/* calculate "used chunks per device" in 'stride' */
stride = size * conf->copies;
+
+ /* We need to round up when dividing by raid_disks to
+ * get the stride size.
+ */
+ stride += conf->raid_disks - 1;
sector_div(stride, conf->raid_disks);
mddev->size = stride << (conf->chunk_shift-1);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 061375ee659..0b66afef2d8 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -52,6 +52,7 @@
#include "raid6.h"
#include <linux/raid/bitmap.h>
+#include <linux/async_tx.h>
/*
* Stripe cache
@@ -80,7 +81,6 @@
/*
* The following can be used to debug the driver
*/
-#define RAID5_DEBUG 0
#define RAID5_PARANOIA 1
#if RAID5_PARANOIA && defined(CONFIG_SMP)
# define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
@@ -88,8 +88,7 @@
# define CHECK_DEVLOCK()
#endif
-#define PRINTK(x...) ((void)(RAID5_DEBUG && printk(x)))
-#if RAID5_DEBUG
+#ifdef DEBUG
#define inline
#define __inline__
#endif
@@ -104,6 +103,23 @@ static inline int raid6_next_disk(int disk, int raid_disks)
disk++;
return (disk < raid_disks) ? disk : 0;
}
+
+static void return_io(struct bio *return_bi)
+{
+ struct bio *bi = return_bi;
+ while (bi) {
+ int bytes = bi->bi_size;
+
+ return_bi = bi->bi_next;
+ bi->bi_next = NULL;
+ bi->bi_size = 0;
+ bi->bi_end_io(bi, bytes,
+ test_bit(BIO_UPTODATE, &bi->bi_flags)
+ ? 0 : -EIO);
+ bi = return_bi;
+ }
+}
+
static void print_raid5_conf (raid5_conf_t *conf);
static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
@@ -125,6 +141,7 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
}
md_wakeup_thread(conf->mddev->thread);
} else {
+ BUG_ON(sh->ops.pending);
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
atomic_dec(&conf->preread_active_stripes);
if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
@@ -152,7 +169,8 @@ static void release_stripe(struct stripe_head *sh)
static inline void remove_hash(struct stripe_head *sh)
{
- PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
+ pr_debug("remove_hash(), stripe %llu\n",
+ (unsigned long long)sh->sector);
hlist_del_init(&sh->hash);
}
@@ -161,7 +179,8 @@ static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
{
struct hlist_head *hp = stripe_hash(conf, sh->sector);
- PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
+ pr_debug("insert_hash(), stripe %llu\n",
+ (unsigned long long)sh->sector);
CHECK_DEVLOCK();
hlist_add_head(&sh->hash, hp);
@@ -224,9 +243,10 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int
BUG_ON(atomic_read(&sh->count) != 0);
BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
-
+ BUG_ON(sh->ops.pending || sh->ops.ack || sh->ops.complete);
+
CHECK_DEVLOCK();
- PRINTK("init_stripe called, stripe %llu\n",
+ pr_debug("init_stripe called, stripe %llu\n",
(unsigned long long)sh->sector);
remove_hash(sh);
@@ -240,11 +260,11 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int
for (i = sh->disks; i--; ) {
struct r5dev *dev = &sh->dev[i];
- if (dev->toread || dev->towrite || dev->written ||
+ if (dev->toread || dev->read || dev->towrite || dev->written ||
test_bit(R5_LOCKED, &dev->flags)) {
- printk("sector=%llx i=%d %p %p %p %d\n",
+ printk(KERN_ERR "sector=%llx i=%d %p %p %p %p %d\n",
(unsigned long long)sh->sector, i, dev->toread,
- dev->towrite, dev->written,
+ dev->read, dev->towrite, dev->written,
test_bit(R5_LOCKED, &dev->flags));
BUG();
}
@@ -260,11 +280,11 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, in
struct hlist_node *hn;
CHECK_DEVLOCK();
- PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
+ pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector);
hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
if (sh->sector == sector && sh->disks == disks)
return sh;
- PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
+ pr_debug("__stripe %llu not in cache\n", (unsigned long long)sector);
return NULL;
}
@@ -276,7 +296,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
{
struct stripe_head *sh;
- PRINTK("get_stripe, sector %llu\n", (unsigned long long)sector);
+ pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector);
spin_lock_irq(&conf->device_lock);
@@ -324,6 +344,579 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector
return sh;
}
+/* test_and_ack_op() ensures that we only dequeue an operation once */
+#define test_and_ack_op(op, pend) \
+do { \
+ if (test_bit(op, &sh->ops.pending) && \
+ !test_bit(op, &sh->ops.complete)) { \
+ if (test_and_set_bit(op, &sh->ops.ack)) \
+ clear_bit(op, &pend); \
+ else \
+ ack++; \
+ } else \
+ clear_bit(op, &pend); \
+} while (0)
+
+/* find new work to run, do not resubmit work that is already
+ * in flight
+ */
+static unsigned long get_stripe_work(struct stripe_head *sh)
+{
+ unsigned long pending;
+ int ack = 0;
+
+ pending = sh->ops.pending;
+
+ test_and_ack_op(STRIPE_OP_BIOFILL, pending);
+ test_and_ack_op(STRIPE_OP_COMPUTE_BLK, pending);
+ test_and_ack_op(STRIPE_OP_PREXOR, pending);
+ test_and_ack_op(STRIPE_OP_BIODRAIN, pending);
+ test_and_ack_op(STRIPE_OP_POSTXOR, pending);
+ test_and_ack_op(STRIPE_OP_CHECK, pending);
+ if (test_and_clear_bit(STRIPE_OP_IO, &sh->ops.pending))
+ ack++;
+
+ sh->ops.count -= ack;
+ BUG_ON(sh->ops.count < 0);
+
+ return pending;
+}
+
+static int
+raid5_end_read_request(struct bio *bi, unsigned int bytes_done, int error);
+static int
+raid5_end_write_request (struct bio *bi, unsigned int bytes_done, int error);
+
+static void ops_run_io(struct stripe_head *sh)
+{
+ raid5_conf_t *conf = sh->raid_conf;
+ int i, disks = sh->disks;
+
+ might_sleep();
+
+ for (i = disks; i--; ) {
+ int rw;
+ struct bio *bi;
+ mdk_rdev_t *rdev;
+ if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
+ rw = WRITE;
+ else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
+ rw = READ;
+ else
+ continue;
+
+ bi = &sh->dev[i].req;
+
+ bi->bi_rw = rw;
+ if (rw == WRITE)
+ bi->bi_end_io = raid5_end_write_request;
+ else
+ bi->bi_end_io = raid5_end_read_request;
+
+ rcu_read_lock();
+ rdev = rcu_dereference(conf->disks[i].rdev);
+ if (rdev && test_bit(Faulty, &rdev->flags))
+ rdev = NULL;
+ if (rdev)
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+
+ if (rdev) {
+ if (test_bit(STRIPE_SYNCING, &sh->state) ||
+ test_bit(STRIPE_EXPAND_SOURCE, &sh->state) ||
+ test_bit(STRIPE_EXPAND_READY, &sh->state))
+ md_sync_acct(rdev->bdev, STRIPE_SECTORS);
+
+ bi->bi_bdev = rdev->bdev;
+ pr_debug("%s: for %llu schedule op %ld on disc %d\n",
+ __FUNCTION__, (unsigned long long)sh->sector,
+ bi->bi_rw, i);
+ atomic_inc(&sh->count);
+ bi->bi_sector = sh->sector + rdev->data_offset;
+ bi->bi_flags = 1 << BIO_UPTODATE;
+ bi->bi_vcnt = 1;
+ bi->bi_max_vecs = 1;
+ bi->bi_idx = 0;
+ bi->bi_io_vec = &sh->dev[i].vec;
+ bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
+ bi->bi_io_vec[0].bv_offset = 0;
+ bi->bi_size = STRIPE_SIZE;
+ bi->bi_next = NULL;
+ if (rw == WRITE &&
+ test_bit(R5_ReWrite, &sh->dev[i].flags))
+ atomic_add(STRIPE_SECTORS,
+ &rdev->corrected_errors);
+ generic_make_request(bi);
+ } else {
+ if (rw == WRITE)
+ set_bit(STRIPE_DEGRADED, &sh->state);
+ pr_debug("skip op %ld on disc %d for sector %llu\n",
+ bi->bi_rw, i, (unsigned long long)sh->sector);
+ clear_bit(R5_LOCKED, &sh->dev[i].flags);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ }
+ }
+}
+
+static struct dma_async_tx_descriptor *
+async_copy_data(int frombio, struct bio *bio, struct page *page,
+ sector_t sector, struct dma_async_tx_descriptor *tx)
+{
+ struct bio_vec *bvl;
+ struct page *bio_page;
+ int i;
+ int page_offset;
+
+ if (bio->bi_sector >= sector)
+ page_offset = (signed)(bio->bi_sector - sector) * 512;
+ else
+ page_offset = (signed)(sector - bio->bi_sector) * -512;
+ bio_for_each_segment(bvl, bio, i) {
+ int len = bio_iovec_idx(bio, i)->bv_len;
+ int clen;
+ int b_offset = 0;
+
+ if (page_offset < 0) {
+ b_offset = -page_offset;
+ page_offset += b_offset;
+ len -= b_offset;
+ }
+
+ if (len > 0 && page_offset + len > STRIPE_SIZE)
+ clen = STRIPE_SIZE - page_offset;
+ else
+ clen = len;
+
+ if (clen > 0) {
+ b_offset += bio_iovec_idx(bio, i)->bv_offset;
+ bio_page = bio_iovec_idx(bio, i)->bv_page;
+ if (frombio)
+ tx = async_memcpy(page, bio_page, page_offset,
+ b_offset, clen,
+ ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_SRC,
+ tx, NULL, NULL);
+ else
+ tx = async_memcpy(bio_page, page, b_offset,
+ page_offset, clen,
+ ASYNC_TX_DEP_ACK | ASYNC_TX_KMAP_DST,
+ tx, NULL, NULL);
+ }
+ if (clen < len) /* hit end of page */
+ break;
+ page_offset += len;
+ }
+
+ return tx;
+}
+
+static void ops_complete_biofill(void *stripe_head_ref)
+{
+ struct stripe_head *sh = stripe_head_ref;
+ struct bio *return_bi = NULL;
+ raid5_conf_t *conf = sh->raid_conf;
+ int i, more_to_read = 0;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ /* clear completed biofills */
+ for (i = sh->disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ /* check if this stripe has new incoming reads */
+ if (dev->toread)
+ more_to_read++;
+
+ /* acknowledge completion of a biofill operation */
+ /* and check if we need to reply to a read request
+ */
+ if (test_bit(R5_Wantfill, &dev->flags) && !dev->toread) {
+ struct bio *rbi, *rbi2;
+ clear_bit(R5_Wantfill, &dev->flags);
+
+ /* The access to dev->read is outside of the
+ * spin_lock_irq(&conf->device_lock), but is protected
+ * by the STRIPE_OP_BIOFILL pending bit
+ */
+ BUG_ON(!dev->read);
+ rbi = dev->read;
+ dev->read = NULL;
+ while (rbi && rbi->bi_sector <
+ dev->sector + STRIPE_SECTORS) {
+ rbi2 = r5_next_bio(rbi, dev->sector);
+ spin_lock_irq(&conf->device_lock);
+ if (--rbi->bi_phys_segments == 0) {
+ rbi->bi_next = return_bi;
+ return_bi = rbi;
+ }
+ spin_unlock_irq(&conf->device_lock);
+ rbi = rbi2;
+ }
+ }
+ }
+ clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
+ clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
+
+ return_io(return_bi);
+
+ if (more_to_read)
+ set_bit(STRIPE_HANDLE, &sh->state);
+ release_stripe(sh);
+}
+
+static void ops_run_biofill(struct stripe_head *sh)
+{
+ struct dma_async_tx_descriptor *tx = NULL;
+ raid5_conf_t *conf = sh->raid_conf;
+ int i;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ for (i = sh->disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (test_bit(R5_Wantfill, &dev->flags)) {
+ struct bio *rbi;
+ spin_lock_irq(&conf->device_lock);
+ dev->read = rbi = dev->toread;
+ dev->toread = NULL;
+ spin_unlock_irq(&conf->device_lock);
+ while (rbi && rbi->bi_sector <
+ dev->sector + STRIPE_SECTORS) {
+ tx = async_copy_data(0, rbi, dev->page,
+ dev->sector, tx);
+ rbi = r5_next_bio(rbi, dev->sector);
+ }
+ }
+ }
+
+ atomic_inc(&sh->count);
+ async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
+ ops_complete_biofill, sh);
+}
+
+static void ops_complete_compute5(void *stripe_head_ref)
+{
+ struct stripe_head *sh = stripe_head_ref;
+ int target = sh->ops.target;
+ struct r5dev *tgt = &sh->dev[target];
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ set_bit(R5_UPTODATE, &tgt->flags);
+ BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
+ clear_bit(R5_Wantcompute, &tgt->flags);
+ set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ release_stripe(sh);
+}
+
+static struct dma_async_tx_descriptor *
+ops_run_compute5(struct stripe_head *sh, unsigned long pending)
+{
+ /* kernel stack size limits the total number of disks */
+ int disks = sh->disks;
+ struct page *xor_srcs[disks];
+ int target = sh->ops.target;
+ struct r5dev *tgt = &sh->dev[target];
+ struct page *xor_dest = tgt->page;
+ int count = 0;
+ struct dma_async_tx_descriptor *tx;
+ int i;
+
+ pr_debug("%s: stripe %llu block: %d\n",
+ __FUNCTION__, (unsigned long long)sh->sector, target);
+ BUG_ON(!test_bit(R5_Wantcompute, &tgt->flags));
+
+ for (i = disks; i--; )
+ if (i != target)
+ xor_srcs[count++] = sh->dev[i].page;
+
+ atomic_inc(&sh->count);
+
+ if (unlikely(count == 1))
+ tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
+ 0, NULL, ops_complete_compute5, sh);
+ else
+ tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+ ASYNC_TX_XOR_ZERO_DST, NULL,
+ ops_complete_compute5, sh);
+
+ /* ack now if postxor is not set to be run */
+ if (tx && !test_bit(STRIPE_OP_POSTXOR, &pending))
+ async_tx_ack(tx);
+
+ return tx;
+}
+
+static void ops_complete_prexor(void *stripe_head_ref)
+{
+ struct stripe_head *sh = stripe_head_ref;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ set_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+}
+
+static struct dma_async_tx_descriptor *
+ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+{
+ /* kernel stack size limits the total number of disks */
+ int disks = sh->disks;
+ struct page *xor_srcs[disks];
+ int count = 0, pd_idx = sh->pd_idx, i;
+
+ /* existing parity data subtracted */
+ struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ /* Only process blocks that are known to be uptodate */
+ if (dev->towrite && test_bit(R5_Wantprexor, &dev->flags))
+ xor_srcs[count++] = dev->page;
+ }
+
+ tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+ ASYNC_TX_DEP_ACK | ASYNC_TX_XOR_DROP_DST, tx,
+ ops_complete_prexor, sh);
+
+ return tx;
+}
+
+static struct dma_async_tx_descriptor *
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+{
+ int disks = sh->disks;
+ int pd_idx = sh->pd_idx, i;
+
+ /* check if prexor is active which means only process blocks
+ * that are part of a read-modify-write (Wantprexor)
+ */
+ int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ struct bio *chosen;
+ int towrite;
+
+ towrite = 0;
+ if (prexor) { /* rmw */
+ if (dev->towrite &&
+ test_bit(R5_Wantprexor, &dev->flags))
+ towrite = 1;
+ } else { /* rcw */
+ if (i != pd_idx && dev->towrite &&
+ test_bit(R5_LOCKED, &dev->flags))
+ towrite = 1;
+ }
+
+ if (towrite) {
+ struct bio *wbi;
+
+ spin_lock(&sh->lock);
+ chosen = dev->towrite;
+ dev->towrite = NULL;
+ BUG_ON(dev->written);
+ wbi = dev->written = chosen;
+ spin_unlock(&sh->lock);
+
+ while (wbi && wbi->bi_sector <
+ dev->sector + STRIPE_SECTORS) {
+ tx = async_copy_data(1, wbi, dev->page,
+ dev->sector, tx);
+ wbi = r5_next_bio(wbi, dev->sector);
+ }
+ }
+ }
+
+ return tx;
+}
+
+static void ops_complete_postxor(void *stripe_head_ref)
+{
+ struct stripe_head *sh = stripe_head_ref;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ release_stripe(sh);
+}
+
+static void ops_complete_write(void *stripe_head_ref)
+{
+ struct stripe_head *sh = stripe_head_ref;
+ int disks = sh->disks, i, pd_idx = sh->pd_idx;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (dev->written || i == pd_idx)
+ set_bit(R5_UPTODATE, &dev->flags);
+ }
+
+ set_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
+ set_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+
+ set_bit(STRIPE_HANDLE, &sh->state);
+ release_stripe(sh);
+}
+
+static void
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+{
+ /* kernel stack size limits the total number of disks */
+ int disks = sh->disks;
+ struct page *xor_srcs[disks];
+
+ int count = 0, pd_idx = sh->pd_idx, i;
+ struct page *xor_dest;
+ int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+ unsigned long flags;
+ dma_async_tx_callback callback;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ /* check if prexor is active which means only process blocks
+ * that are part of a read-modify-write (written)
+ */
+ if (prexor) {
+ xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (dev->written)
+ xor_srcs[count++] = dev->page;
+ }
+ } else {
+ xor_dest = sh->dev[pd_idx].page;
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (i != pd_idx)
+ xor_srcs[count++] = dev->page;
+ }
+ }
+
+ /* check whether this postxor is part of a write */
+ callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
+ ops_complete_write : ops_complete_postxor;
+
+ /* 1/ if we prexor'd then the dest is reused as a source
+ * 2/ if we did not prexor then we are redoing the parity
+ * set ASYNC_TX_XOR_DROP_DST and ASYNC_TX_XOR_ZERO_DST
+ * for the synchronous xor case
+ */
+ flags = ASYNC_TX_DEP_ACK | ASYNC_TX_ACK |
+ (prexor ? ASYNC_TX_XOR_DROP_DST : ASYNC_TX_XOR_ZERO_DST);
+
+ atomic_inc(&sh->count);
+
+ if (unlikely(count == 1)) {
+ flags &= ~(ASYNC_TX_XOR_DROP_DST | ASYNC_TX_XOR_ZERO_DST);
+ tx = async_memcpy(xor_dest, xor_srcs[0], 0, 0, STRIPE_SIZE,
+ flags, tx, callback, sh);
+ } else
+ tx = async_xor(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+ flags, tx, callback, sh);
+}
+
+static void ops_complete_check(void *stripe_head_ref)
+{
+ struct stripe_head *sh = stripe_head_ref;
+ int pd_idx = sh->pd_idx;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ if (test_and_clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending) &&
+ sh->ops.zero_sum_result == 0)
+ set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+
+ set_bit(STRIPE_OP_CHECK, &sh->ops.complete);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ release_stripe(sh);
+}
+
+static void ops_run_check(struct stripe_head *sh)
+{
+ /* kernel stack size limits the total number of disks */
+ int disks = sh->disks;
+ struct page *xor_srcs[disks];
+ struct dma_async_tx_descriptor *tx;
+
+ int count = 0, pd_idx = sh->pd_idx, i;
+ struct page *xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
+
+ pr_debug("%s: stripe %llu\n", __FUNCTION__,
+ (unsigned long long)sh->sector);
+
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (i != pd_idx)
+ xor_srcs[count++] = dev->page;
+ }
+
+ tx = async_xor_zero_sum(xor_dest, xor_srcs, 0, count, STRIPE_SIZE,
+ &sh->ops.zero_sum_result, 0, NULL, NULL, NULL);
+
+ if (tx)
+ set_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
+ else
+ clear_bit(STRIPE_OP_MOD_DMA_CHECK, &sh->ops.pending);
+
+ atomic_inc(&sh->count);
+ tx = async_trigger_callback(ASYNC_TX_DEP_ACK | ASYNC_TX_ACK, tx,
+ ops_complete_check, sh);
+}
+
+static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
+{
+ int overlap_clear = 0, i, disks = sh->disks;
+ struct dma_async_tx_descriptor *tx = NULL;
+
+ if (test_bit(STRIPE_OP_BIOFILL, &pending)) {
+ ops_run_biofill(sh);
+ overlap_clear++;
+ }
+
+ if (test_bit(STRIPE_OP_COMPUTE_BLK, &pending))
+ tx = ops_run_compute5(sh, pending);
+
+ if (test_bit(STRIPE_OP_PREXOR, &pending))
+ tx = ops_run_prexor(sh, tx);
+
+ if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
+ tx = ops_run_biodrain(sh, tx);
+ overlap_clear++;
+ }
+
+ if (test_bit(STRIPE_OP_POSTXOR, &pending))
+ ops_run_postxor(sh, tx);
+
+ if (test_bit(STRIPE_OP_CHECK, &pending))
+ ops_run_check(sh);
+
+ if (test_bit(STRIPE_OP_IO, &pending))
+ ops_run_io(sh);
+
+ if (overlap_clear)
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (test_and_clear_bit(R5_Overlap, &dev->flags))
+ wake_up(&sh->raid_conf->wait_for_overlap);
+ }
+}
+
static int grow_one_stripe(raid5_conf_t *conf)
{
struct stripe_head *sh;
@@ -537,8 +1130,8 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done,
if (bi == &sh->dev[i].req)
break;
- PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n",
- (unsigned long long)sh->sector, i, atomic_read(&sh->count),
+ pr_debug("end_read_request %llu/%d, count: %d, uptodate %d.\n",
+ (unsigned long long)sh->sector, i, atomic_read(&sh->count),
uptodate);
if (i == disks) {
BUG();
@@ -613,7 +1206,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done,
if (bi == &sh->dev[i].req)
break;
- PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n",
+ pr_debug("end_write_request %llu/%d, count %d, uptodate: %d.\n",
(unsigned long long)sh->sector, i, atomic_read(&sh->count),
uptodate);
if (i == disks) {
@@ -658,7 +1251,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
{
char b[BDEVNAME_SIZE];
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
- PRINTK("raid5: error called\n");
+ pr_debug("raid5: error called\n");
if (!test_bit(Faulty, &rdev->flags)) {
set_bit(MD_CHANGE_DEVS, &mddev->flags);
@@ -916,137 +1509,13 @@ static void copy_data(int frombio, struct bio *bio,
}
}
-#define check_xor() do { \
- if (count == MAX_XOR_BLOCKS) { \
- xor_block(count, STRIPE_SIZE, ptr); \
- count = 1; \
- } \
+#define check_xor() do { \
+ if (count == MAX_XOR_BLOCKS) { \
+ xor_blocks(count, STRIPE_SIZE, dest, ptr);\
+ count = 0; \
+ } \
} while(0)
-
-static void compute_block(struct stripe_head *sh, int dd_idx)
-{
- int i, count, disks = sh->disks;
- void *ptr[MAX_XOR_BLOCKS], *p;
-
- PRINTK("compute_block, stripe %llu, idx %d\n",
- (unsigned long long)sh->sector, dd_idx);
-
- ptr[0] = page_address(sh->dev[dd_idx].page);
- memset(ptr[0], 0, STRIPE_SIZE);
- count = 1;
- for (i = disks ; i--; ) {
- if (i == dd_idx)
- continue;
- p = page_address(sh->dev[i].page);
- if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
- ptr[count++] = p;
- else
- printk(KERN_ERR "compute_block() %d, stripe %llu, %d"
- " not present\n", dd_idx,
- (unsigned long long)sh->sector, i);
-
- check_xor();
- }
- if (count != 1)
- xor_block(count, STRIPE_SIZE, ptr);
- set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
-}
-
-static void compute_parity5(struct stripe_head *sh, int method)
-{
- raid5_conf_t *conf = sh->raid_conf;
- int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
- void *ptr[MAX_XOR_BLOCKS];
- struct bio *chosen;
-
- PRINTK("compute_parity5, stripe %llu, method %d\n",
- (unsigned long long)sh->sector, method);
-
- count = 1;
- ptr[0] = page_address(sh->dev[pd_idx].page);
- switch(method) {
- case READ_MODIFY_WRITE:
- BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
- for (i=disks ; i-- ;) {
- if (i==pd_idx)
- continue;
- if (sh->dev[i].towrite &&
- test_bit(R5_UPTODATE, &sh->dev[i].flags)) {
- ptr[count++] = page_address(sh->dev[i].page);
- chosen = sh->dev[i].towrite;
- sh->dev[i].towrite = NULL;
-
- if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
- wake_up(&conf->wait_for_overlap);
-
- BUG_ON(sh->dev[i].written);
- sh->dev[i].written = chosen;
- check_xor();
- }
- }
- break;
- case RECONSTRUCT_WRITE:
- memset(ptr[0], 0, STRIPE_SIZE);
- for (i= disks; i-- ;)
- if (i!=pd_idx && sh->dev[i].towrite) {
- chosen = sh->dev[i].towrite;
- sh->dev[i].towrite = NULL;
-
- if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
- wake_up(&conf->wait_for_overlap);
-
- BUG_ON(sh->dev[i].written);
- sh->dev[i].written = chosen;
- }
- break;
- case CHECK_PARITY:
- break;
- }
- if (count>1) {
- xor_block(count, STRIPE_SIZE, ptr);
- count = 1;
- }
-
- for (i = disks; i--;)
- if (sh->dev[i].written) {
- sector_t sector = sh->dev[i].sector;
- struct bio *wbi = sh->dev[i].written;
- while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
- copy_data(1, wbi, sh->dev[i].page, sector);
- wbi = r5_next_bio(wbi, sector);
- }
-
- set_bit(R5_LOCKED, &sh->dev[i].flags);
- set_bit(R5_UPTODATE, &sh->dev[i].flags);
- }
-
- switch(method) {
- case RECONSTRUCT_WRITE:
- case CHECK_PARITY:
- for (i=disks; i--;)
- if (i != pd_idx) {
- ptr[count++] = page_address(sh->dev[i].page);
- check_xor();
- }
- break;
- case READ_MODIFY_WRITE:
- for (i = disks; i--;)
- if (sh->dev[i].written) {
- ptr[count++] = page_address(sh->dev[i].page);
- check_xor();
- }
- }
- if (count != 1)
- xor_block(count, STRIPE_SIZE, ptr);
-
- if (method != CHECK_PARITY) {
- set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
- set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);
- } else
- clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-}
-
static void compute_parity6(struct stripe_head *sh, int method)
{
raid6_conf_t *conf = sh->raid_conf;
@@ -1058,7 +1527,7 @@ static void compute_parity6(struct stripe_head *sh, int method)
qd_idx = raid6_next_disk(pd_idx, disks);
d0_idx = raid6_next_disk(qd_idx, disks);
- PRINTK("compute_parity, stripe %llu, method %d\n",
+ pr_debug("compute_parity, stripe %llu, method %d\n",
(unsigned long long)sh->sector, method);
switch(method) {
@@ -1132,20 +1601,20 @@ static void compute_parity6(struct stripe_head *sh, int method)
static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
{
int i, count, disks = sh->disks;
- void *ptr[MAX_XOR_BLOCKS], *p;
+ void *ptr[MAX_XOR_BLOCKS], *dest, *p;
int pd_idx = sh->pd_idx;
int qd_idx = raid6_next_disk(pd_idx, disks);
- PRINTK("compute_block_1, stripe %llu, idx %d\n",
+ pr_debug("compute_block_1, stripe %llu, idx %d\n",
(unsigned long long)sh->sector, dd_idx);
if ( dd_idx == qd_idx ) {
/* We're actually computing the Q drive */
compute_parity6(sh, UPDATE_PARITY);
} else {
- ptr[0] = page_address(sh->dev[dd_idx].page);
- if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
- count = 1;
+ dest = page_address(sh->dev[dd_idx].page);
+ if (!nozero) memset(dest, 0, STRIPE_SIZE);
+ count = 0;
for (i = disks ; i--; ) {
if (i == dd_idx || i == qd_idx)
continue;
@@ -1159,8 +1628,8 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
check_xor();
}
- if (count != 1)
- xor_block(count, STRIPE_SIZE, ptr);
+ if (count)
+ xor_blocks(count, STRIPE_SIZE, dest, ptr);
if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
}
@@ -1183,7 +1652,7 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
BUG_ON(faila == failb);
if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }
- PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
+ pr_debug("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
(unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb);
if ( failb == disks-1 ) {
@@ -1229,7 +1698,79 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
}
}
+static int
+handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
+{
+ int i, pd_idx = sh->pd_idx, disks = sh->disks;
+ int locked = 0;
+ if (rcw) {
+ /* if we are not expanding this is a proper write request, and
+ * there will be bios with new data to be drained into the
+ * stripe cache
+ */
+ if (!expand) {
+ set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+ sh->ops.count++;
+ }
+
+ set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+ sh->ops.count++;
+
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+
+ if (dev->towrite) {
+ set_bit(R5_LOCKED, &dev->flags);
+ if (!expand)
+ clear_bit(R5_UPTODATE, &dev->flags);
+ locked++;
+ }
+ }
+ } else {
+ BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
+ test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
+
+ set_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+ set_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+ set_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+
+ sh->ops.count += 3;
+
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (i == pd_idx)
+ continue;
+
+ /* For a read-modify write there may be blocks that are
+ * locked for reading while others are ready to be
+ * written so we distinguish these blocks by the
+ * R5_Wantprexor bit
+ */
+ if (dev->towrite &&
+ (test_bit(R5_UPTODATE, &dev->flags) ||
+ test_bit(R5_Wantcompute, &dev->flags))) {
+ set_bit(R5_Wantprexor, &dev->flags);
+ set_bit(R5_LOCKED, &dev->flags);
+ clear_bit(R5_UPTODATE, &dev->flags);
+ locked++;
+ }
+ }
+ }
+
+ /* keep the parity disk locked while asynchronous operations
+ * are in flight
+ */
+ set_bit(R5_LOCKED, &sh->dev[pd_idx].flags);
+ clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+ locked++;
+
+ pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
+ __FUNCTION__, (unsigned long long)sh->sector,
+ locked, sh->ops.pending);
+
+ return locked;
+}
/*
* Each stripe/dev can have one or more bion attached.
@@ -1242,7 +1783,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
raid5_conf_t *conf = sh->raid_conf;
int firstwrite=0;
- PRINTK("adding bh b#%llu to stripe s#%llu\n",
+ pr_debug("adding bh b#%llu to stripe s#%llu\n",
(unsigned long long)bi->bi_sector,
(unsigned long long)sh->sector);
@@ -1271,7 +1812,7 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
spin_unlock_irq(&conf->device_lock);
spin_unlock(&sh->lock);
- PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n",
+ pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
(unsigned long long)bi->bi_sector,
(unsigned long long)sh->sector, dd_idx);
@@ -1326,6 +1867,729 @@ static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
return pd_idx;
}
+static void
+handle_requests_to_failed_array(raid5_conf_t *conf, struct stripe_head *sh,
+ struct stripe_head_state *s, int disks,
+ struct bio **return_bi)
+{
+ int i;
+ for (i = disks; i--; ) {
+ struct bio *bi;
+ int bitmap_end = 0;
+
+ if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+ mdk_rdev_t *rdev;
+ rcu_read_lock();
+ rdev = rcu_dereference(conf->disks[i].rdev);
+ if (rdev && test_bit(In_sync, &rdev->flags))
+ /* multiple read failures in one stripe */
+ md_error(conf->mddev, rdev);
+ rcu_read_unlock();
+ }
+ spin_lock_irq(&conf->device_lock);
+ /* fail all writes first */
+ bi = sh->dev[i].towrite;
+ sh->dev[i].towrite = NULL;
+ if (bi) {
+ s->to_write--;
+ bitmap_end = 1;
+ }
+
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
+
+ while (bi && bi->bi_sector <
+ sh->dev[i].sector + STRIPE_SECTORS) {
+ struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
+ clear_bit(BIO_UPTODATE, &bi->bi_flags);
+ if (--bi->bi_phys_segments == 0) {
+ md_write_end(conf->mddev);
+ bi->bi_next = *return_bi;
+ *return_bi = bi;
+ }
+ bi = nextbi;
+ }
+ /* and fail all 'written' */
+ bi = sh->dev[i].written;
+ sh->dev[i].written = NULL;
+ if (bi) bitmap_end = 1;
+ while (bi && bi->bi_sector <
+ sh->dev[i].sector + STRIPE_SECTORS) {
+ struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
+ clear_bit(BIO_UPTODATE, &bi->bi_flags);
+ if (--bi->bi_phys_segments == 0) {
+ md_write_end(conf->mddev);
+ bi->bi_next = *return_bi;
+ *return_bi = bi;
+ }
+ bi = bi2;
+ }
+
+ /* fail any reads if this device is non-operational and
+ * the data has not reached the cache yet.
+ */
+ if (!test_bit(R5_Wantfill, &sh->dev[i].flags) &&
+ (!test_bit(R5_Insync, &sh->dev[i].flags) ||
+ test_bit(R5_ReadError, &sh->dev[i].flags))) {
+ bi = sh->dev[i].toread;
+ sh->dev[i].toread = NULL;
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
+ if (bi) s->to_read--;
+ while (bi && bi->bi_sector <
+ sh->dev[i].sector + STRIPE_SECTORS) {
+ struct bio *nextbi =
+ r5_next_bio(bi, sh->dev[i].sector);
+ clear_bit(BIO_UPTODATE, &bi->bi_flags);
+ if (--bi->bi_phys_segments == 0) {
+ bi->bi_next = *return_bi;
+ *return_bi = bi;
+ }
+ bi = nextbi;
+ }
+ }
+ spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0, 0);
+ }
+
+}
+
+/* __handle_issuing_new_read_requests5 - returns 0 if there are no more disks
+ * to process
+ */
+static int __handle_issuing_new_read_requests5(struct stripe_head *sh,
+ struct stripe_head_state *s, int disk_idx, int disks)
+{
+ struct r5dev *dev = &sh->dev[disk_idx];
+ struct r5dev *failed_dev = &sh->dev[s->failed_num];
+
+ /* don't schedule compute operations or reads on the parity block while
+ * a check is in flight
+ */
+ if ((disk_idx == sh->pd_idx) &&
+ test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
+ return ~0;
+
+ /* is the data in this block needed, and can we get it? */
+ if (!test_bit(R5_LOCKED, &dev->flags) &&
+ !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread ||
+ (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
+ s->syncing || s->expanding || (s->failed &&
+ (failed_dev->toread || (failed_dev->towrite &&
+ !test_bit(R5_OVERWRITE, &failed_dev->flags)
+ ))))) {
+ /* 1/ We would like to get this block, possibly by computing it,
+ * but we might not be able to.
+ *
+ * 2/ Since parity check operations potentially make the parity
+ * block !uptodate it will need to be refreshed before any
+ * compute operations on data disks are scheduled.
+ *
+ * 3/ We hold off parity block re-reads until check operations
+ * have quiesced.
+ */
+ if ((s->uptodate == disks - 1) &&
+ !test_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
+ set_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+ set_bit(R5_Wantcompute, &dev->flags);
+ sh->ops.target = disk_idx;
+ s->req_compute = 1;
+ sh->ops.count++;
+ /* Careful: from this point on 'uptodate' is in the eye
+ * of raid5_run_ops which services 'compute' operations
+ * before writes. R5_Wantcompute flags a block that will
+ * be R5_UPTODATE by the time it is needed for a
+ * subsequent operation.
+ */
+ s->uptodate++;
+ return 0; /* uptodate + compute == disks */
+ } else if ((s->uptodate < disks - 1) &&
+ test_bit(R5_Insync, &dev->flags)) {
+ /* Note: we hold off compute operations while checks are
+ * in flight, but we still prefer 'compute' over 'read'
+ * hence we only read if (uptodate < * disks-1)
+ */
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantread, &dev->flags);
+ if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
+ s->locked++;
+ pr_debug("Reading block %d (sync=%d)\n", disk_idx,
+ s->syncing);
+ }
+ }
+
+ return ~0;
+}
+
+static void handle_issuing_new_read_requests5(struct stripe_head *sh,
+ struct stripe_head_state *s, int disks)
+{
+ int i;
+
+ /* Clear completed compute operations. Parity recovery
+ * (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled
+ * later on in this routine
+ */
+ if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
+ !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+ clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+ clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
+ clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+ }
+
+ /* look for blocks to read/compute, skip this if a compute
+ * is already in flight, or if the stripe contents are in the
+ * midst of changing due to a write
+ */
+ if (!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
+ !test_bit(STRIPE_OP_PREXOR, &sh->ops.pending) &&
+ !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+ for (i = disks; i--; )
+ if (__handle_issuing_new_read_requests5(
+ sh, s, i, disks) == 0)
+ break;
+ }
+ set_bit(STRIPE_HANDLE, &sh->state);
+}
+
+static void handle_issuing_new_read_requests6(struct stripe_head *sh,
+ struct stripe_head_state *s, struct r6_state *r6s,
+ int disks)
+{
+ int i;
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (!test_bit(R5_LOCKED, &dev->flags) &&
+ !test_bit(R5_UPTODATE, &dev->flags) &&
+ (dev->toread || (dev->towrite &&
+ !test_bit(R5_OVERWRITE, &dev->flags)) ||
+ s->syncing || s->expanding ||
+ (s->failed >= 1 &&
+ (sh->dev[r6s->failed_num[0]].toread ||
+ s->to_write)) ||
+ (s->failed >= 2 &&
+ (sh->dev[r6s->failed_num[1]].toread ||
+ s->to_write)))) {
+ /* we would like to get this block, possibly
+ * by computing it, but we might not be able to
+ */
+ if (s->uptodate == disks-1) {
+ pr_debug("Computing stripe %llu block %d\n",
+ (unsigned long long)sh->sector, i);
+ compute_block_1(sh, i, 0);
+ s->uptodate++;
+ } else if ( s->uptodate == disks-2 && s->failed >= 2 ) {
+ /* Computing 2-failure is *very* expensive; only
+ * do it if failed >= 2
+ */
+ int other;
+ for (other = disks; other--; ) {
+ if (other == i)
+ continue;
+ if (!test_bit(R5_UPTODATE,
+ &sh->dev[other].flags))
+ break;
+ }
+ BUG_ON(other < 0);
+ pr_debug("Computing stripe %llu blocks %d,%d\n",
+ (unsigned long long)sh->sector,
+ i, other);
+ compute_block_2(sh, i, other);
+ s->uptodate += 2;
+ } else if (test_bit(R5_Insync, &dev->flags)) {
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantread, &dev->flags);
+ s->locked++;
+ pr_debug("Reading block %d (sync=%d)\n",
+ i, s->syncing);
+ }
+ }
+ }
+ set_bit(STRIPE_HANDLE, &sh->state);
+}
+
+
+/* handle_completed_write_requests
+ * any written block on an uptodate or failed drive can be returned.
+ * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
+ * never LOCKED, so we don't need to test 'failed' directly.
+ */
+static void handle_completed_write_requests(raid5_conf_t *conf,
+ struct stripe_head *sh, int disks, struct bio **return_bi)
+{
+ int i;
+ struct r5dev *dev;
+
+ for (i = disks; i--; )
+ if (sh->dev[i].written) {
+ dev = &sh->dev[i];
+ if (!test_bit(R5_LOCKED, &dev->flags) &&
+ test_bit(R5_UPTODATE, &dev->flags)) {
+ /* We can return any write requests */
+ struct bio *wbi, *wbi2;
+ int bitmap_end = 0;
+ pr_debug("Return write for disc %d\n", i);
+ spin_lock_irq(&conf->device_lock);
+ wbi = dev->written;
+ dev->written = NULL;
+ while (wbi && wbi->bi_sector <
+ dev->sector + STRIPE_SECTORS) {
+ wbi2 = r5_next_bio(wbi, dev->sector);
+ if (--wbi->bi_phys_segments == 0) {
+ md_write_end(conf->mddev);
+ wbi->bi_next = *return_bi;
+ *return_bi = wbi;
+ }
+ wbi = wbi2;
+ }
+ if (dev->towrite == NULL)
+ bitmap_end = 1;
+ spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap,
+ sh->sector,
+ STRIPE_SECTORS,
+ !test_bit(STRIPE_DEGRADED, &sh->state),
+ 0);
+ }
+ }
+}
+
+static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
+ struct stripe_head *sh, struct stripe_head_state *s, int disks)
+{
+ int rmw = 0, rcw = 0, i;
+ for (i = disks; i--; ) {
+ /* would I have to read this buffer for read_modify_write */
+ struct r5dev *dev = &sh->dev[i];
+ if ((dev->towrite || i == sh->pd_idx) &&
+ !test_bit(R5_LOCKED, &dev->flags) &&
+ !(test_bit(R5_UPTODATE, &dev->flags) ||
+ test_bit(R5_Wantcompute, &dev->flags))) {
+ if (test_bit(R5_Insync, &dev->flags))
+ rmw++;
+ else
+ rmw += 2*disks; /* cannot read it */
+ }
+ /* Would I have to read this buffer for reconstruct_write */
+ if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
+ !test_bit(R5_LOCKED, &dev->flags) &&
+ !(test_bit(R5_UPTODATE, &dev->flags) ||
+ test_bit(R5_Wantcompute, &dev->flags))) {
+ if (test_bit(R5_Insync, &dev->flags)) rcw++;
+ else
+ rcw += 2*disks;
+ }
+ }
+ pr_debug("for sector %llu, rmw=%d rcw=%d\n",
+ (unsigned long long)sh->sector, rmw, rcw);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ if (rmw < rcw && rmw > 0)
+ /* prefer read-modify-write, but need to get some data */
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if ((dev->towrite || i == sh->pd_idx) &&
+ !test_bit(R5_LOCKED, &dev->flags) &&
+ !(test_bit(R5_UPTODATE, &dev->flags) ||
+ test_bit(R5_Wantcompute, &dev->flags)) &&
+ test_bit(R5_Insync, &dev->flags)) {
+ if (
+ test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+ pr_debug("Read_old block "
+ "%d for r-m-w\n", i);
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantread, &dev->flags);
+ if (!test_and_set_bit(
+ STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
+ s->locked++;
+ } else {
+ set_bit(STRIPE_DELAYED, &sh->state);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ }
+ }
+ }
+ if (rcw <= rmw && rcw > 0)
+ /* want reconstruct write, but need to get some data */
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (!test_bit(R5_OVERWRITE, &dev->flags) &&
+ i != sh->pd_idx &&
+ !test_bit(R5_LOCKED, &dev->flags) &&
+ !(test_bit(R5_UPTODATE, &dev->flags) ||
+ test_bit(R5_Wantcompute, &dev->flags)) &&
+ test_bit(R5_Insync, &dev->flags)) {
+ if (
+ test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+ pr_debug("Read_old block "
+ "%d for Reconstruct\n", i);
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantread, &dev->flags);
+ if (!test_and_set_bit(
+ STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
+ s->locked++;
+ } else {
+ set_bit(STRIPE_DELAYED, &sh->state);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ }
+ }
+ }
+ /* now if nothing is locked, and if we have enough data,
+ * we can start a write request
+ */
+ /* since handle_stripe can be called at any time we need to handle the
+ * case where a compute block operation has been submitted and then a
+ * subsequent call wants to start a write request. raid5_run_ops only
+ * handles the case where compute block and postxor are requested
+ * simultaneously. If this is not the case then new writes need to be
+ * held off until the compute completes.
+ */
+ if ((s->req_compute ||
+ !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) &&
+ (s->locked == 0 && (rcw == 0 || rmw == 0) &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)))
+ s->locked += handle_write_operations5(sh, rcw == 0, 0);
+}
+
+static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
+ struct stripe_head *sh, struct stripe_head_state *s,
+ struct r6_state *r6s, int disks)
+{
+ int rcw = 0, must_compute = 0, pd_idx = sh->pd_idx, i;
+ int qd_idx = r6s->qd_idx;
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ /* Would I have to read this buffer for reconstruct_write */
+ if (!test_bit(R5_OVERWRITE, &dev->flags)
+ && i != pd_idx && i != qd_idx
+ && (!test_bit(R5_LOCKED, &dev->flags)
+ ) &&
+ !test_bit(R5_UPTODATE, &dev->flags)) {
+ if (test_bit(R5_Insync, &dev->flags)) rcw++;
+ else {
+ pr_debug("raid6: must_compute: "
+ "disk %d flags=%#lx\n", i, dev->flags);
+ must_compute++;
+ }
+ }
+ }
+ pr_debug("for sector %llu, rcw=%d, must_compute=%d\n",
+ (unsigned long long)sh->sector, rcw, must_compute);
+ set_bit(STRIPE_HANDLE, &sh->state);
+
+ if (rcw > 0)
+ /* want reconstruct write, but need to get some data */
+ for (i = disks; i--; ) {
+ struct r5dev *dev = &sh->dev[i];
+ if (!test_bit(R5_OVERWRITE, &dev->flags)
+ && !(s->failed == 0 && (i == pd_idx || i == qd_idx))
+ && !test_bit(R5_LOCKED, &dev->flags) &&
+ !test_bit(R5_UPTODATE, &dev->flags) &&
+ test_bit(R5_Insync, &dev->flags)) {
+ if (
+ test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+ pr_debug("Read_old stripe %llu "
+ "block %d for Reconstruct\n",
+ (unsigned long long)sh->sector, i);
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantread, &dev->flags);
+ s->locked++;
+ } else {
+ pr_debug("Request delayed stripe %llu "
+ "block %d for Reconstruct\n",
+ (unsigned long long)sh->sector, i);
+ set_bit(STRIPE_DELAYED, &sh->state);
+ set_bit(STRIPE_HANDLE, &sh->state);
+ }
+ }
+ }
+ /* now if nothing is locked, and if we have enough data, we can start a
+ * write request
+ */
+ if (s->locked == 0 && rcw == 0 &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
+ if (must_compute > 0) {
+ /* We have failed blocks and need to compute them */
+ switch (s->failed) {
+ case 0:
+ BUG();
+ case 1:
+ compute_block_1(sh, r6s->failed_num[0], 0);
+ break;
+ case 2:
+ compute_block_2(sh, r6s->failed_num[0],
+ r6s->failed_num[1]);
+ break;
+ default: /* This request should have been failed? */
+ BUG();
+ }
+ }
+
+ pr_debug("Computing parity for stripe %llu\n",
+ (unsigned long long)sh->sector);
+ compute_parity6(sh, RECONSTRUCT_WRITE);
+ /* now every locked buffer is ready to be written */
+ for (i = disks; i--; )
+ if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
+ pr_debug("Writing stripe %llu block %d\n",
+ (unsigned long long)sh->sector, i);
+ s->locked++;
+ set_bit(R5_Wantwrite, &sh->dev[i].flags);
+ }
+ /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
+ set_bit(STRIPE_INSYNC, &sh->state);
+
+ if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+ atomic_dec(&conf->preread_active_stripes);
+ if (atomic_read(&conf->preread_active_stripes) <
+ IO_THRESHOLD)
+ md_wakeup_thread(conf->mddev->thread);
+ }
+ }
+}
+
+static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
+ struct stripe_head_state *s, int disks)
+{
+ set_bit(STRIPE_HANDLE, &sh->state);
+ /* Take one of the following actions:
+ * 1/ start a check parity operation if (uptodate == disks)
+ * 2/ finish a check parity operation and act on the result
+ * 3/ skip to the writeback section if we previously
+ * initiated a recovery operation
+ */
+ if (s->failed == 0 &&
+ !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+ if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
+ BUG_ON(s->uptodate != disks);
+ clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
+ sh->ops.count++;
+ s->uptodate--;
+ } else if (
+ test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) {
+ clear_bit(STRIPE_OP_CHECK, &sh->ops.ack);
+ clear_bit(STRIPE_OP_CHECK, &sh->ops.pending);
+
+ if (sh->ops.zero_sum_result == 0)
+ /* parity is correct (on disc,
+ * not in buffer any more)
+ */
+ set_bit(STRIPE_INSYNC, &sh->state);
+ else {
+ conf->mddev->resync_mismatches +=
+ STRIPE_SECTORS;
+ if (test_bit(
+ MD_RECOVERY_CHECK, &conf->mddev->recovery))
+ /* don't try to repair!! */
+ set_bit(STRIPE_INSYNC, &sh->state);
+ else {
+ set_bit(STRIPE_OP_COMPUTE_BLK,
+ &sh->ops.pending);
+ set_bit(STRIPE_OP_MOD_REPAIR_PD,
+ &sh->ops.pending);
+ set_bit(R5_Wantcompute,
+ &sh->dev[sh->pd_idx].flags);
+ sh->ops.target = sh->pd_idx;
+ sh->ops.count++;
+ s->uptodate++;
+ }
+ }
+ }
+ }
+
+ /* check if we can clear a parity disk reconstruct */
+ if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
+ test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
+
+ clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending);
+ clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
+ clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
+ clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
+ }
+
+ /* Wait for check parity and compute block operations to complete
+ * before write-back
+ */
+ if (!test_bit(STRIPE_INSYNC, &sh->state) &&
+ !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) &&
+ !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) {
+ struct r5dev *dev;
+ /* either failed parity check, or recovery is happening */
+ if (s->failed == 0)
+ s->failed_num = sh->pd_idx;
+ dev = &sh->dev[s->failed_num];
+ BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
+ BUG_ON(s->uptodate != disks);
+
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
+
+ clear_bit(STRIPE_DEGRADED, &sh->state);
+ s->locked++;
+ set_bit(STRIPE_INSYNC, &sh->state);
+ }
+}
+
+
+static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh,
+ struct stripe_head_state *s,
+ struct r6_state *r6s, struct page *tmp_page,
+ int disks)
+{
+ int update_p = 0, update_q = 0;
+ struct r5dev *dev;
+ int pd_idx = sh->pd_idx;
+ int qd_idx = r6s->qd_idx;
+
+ set_bit(STRIPE_HANDLE, &sh->state);
+
+ BUG_ON(s->failed > 2);
+ BUG_ON(s->uptodate < disks);
+ /* Want to check and possibly repair P and Q.
+ * However there could be one 'failed' device, in which
+ * case we can only check one of them, possibly using the
+ * other to generate missing data
+ */
+
+ /* If !tmp_page, we cannot do the calculations,
+ * but as we have set STRIPE_HANDLE, we will soon be called
+ * by stripe_handle with a tmp_page - just wait until then.
+ */
+ if (tmp_page) {
+ if (s->failed == r6s->q_failed) {
+ /* The only possible failed device holds 'Q', so it
+ * makes sense to check P (If anything else were failed,
+ * we would have used P to recreate it).
+ */
+ compute_block_1(sh, pd_idx, 1);
+ if (!page_is_zero(sh->dev[pd_idx].page)) {
+ compute_block_1(sh, pd_idx, 0);
+ update_p = 1;
+ }
+ }
+ if (!r6s->q_failed && s->failed < 2) {
+ /* q is not failed, and we didn't use it to generate
+ * anything, so it makes sense to check it
+ */
+ memcpy(page_address(tmp_page),
+ page_address(sh->dev[qd_idx].page),
+ STRIPE_SIZE);
+ compute_parity6(sh, UPDATE_PARITY);
+ if (memcmp(page_address(tmp_page),
+ page_address(sh->dev[qd_idx].page),
+ STRIPE_SIZE) != 0) {
+ clear_bit(STRIPE_INSYNC, &sh->state);
+ update_q = 1;
+ }
+ }
+ if (update_p || update_q) {
+ conf->mddev->resync_mismatches += STRIPE_SECTORS;
+ if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+ /* don't try to repair!! */
+ update_p = update_q = 0;
+ }
+
+ /* now write out any block on a failed drive,
+ * or P or Q if they need it
+ */
+
+ if (s->failed == 2) {
+ dev = &sh->dev[r6s->failed_num[1]];
+ s->locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
+ if (s->failed >= 1) {
+ dev = &sh->dev[r6s->failed_num[0]];
+ s->locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
+
+ if (update_p) {
+ dev = &sh->dev[pd_idx];
+ s->locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
+ if (update_q) {
+ dev = &sh->dev[qd_idx];
+ s->locked++;
+ set_bit(R5_LOCKED, &dev->flags);
+ set_bit(R5_Wantwrite, &dev->flags);
+ }
+ clear_bit(STRIPE_DEGRADED, &sh->state);
+
+ set_bit(STRIPE_INSYNC, &sh->state);
+ }
+}
+
+static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
+ struct r6_state *r6s)
+{
+ int i;
+
+ /* We have read all the blocks in this stripe and now we need to
+ * copy some of them into a target stripe for expand.
+ */
+ struct dma_async_tx_descriptor *tx = NULL;
+ clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ for (i = 0; i < sh->disks; i++)
+ if (i != sh->pd_idx && (r6s && i != r6s->qd_idx)) {
+ int dd_idx, pd_idx, j;
+ struct stripe_head *sh2;
+
+ sector_t bn = compute_blocknr(sh, i);
+ sector_t s = raid5_compute_sector(bn, conf->raid_disks,
+ conf->raid_disks -
+ conf->max_degraded, &dd_idx,
+ &pd_idx, conf);
+ sh2 = get_active_stripe(conf, s, conf->raid_disks,
+ pd_idx, 1);
+ if (sh2 == NULL)
+ /* so far only the early blocks of this stripe
+ * have been requested. When later blocks
+ * get requested, we will try again
+ */
+ continue;
+ if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
+ test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
+ /* must have already done this block */
+ release_stripe(sh2);
+ continue;
+ }
+
+ /* place all the copies on one channel */
+ tx = async_memcpy(sh2->dev[dd_idx].page,
+ sh->dev[i].page, 0, 0, STRIPE_SIZE,
+ ASYNC_TX_DEP_ACK, tx, NULL, NULL);
+
+ set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
+ set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
+ for (j = 0; j < conf->raid_disks; j++)
+ if (j != sh2->pd_idx &&
+ (r6s && j != r6s->qd_idx) &&
+ !test_bit(R5_Expanded, &sh2->dev[j].flags))
+ break;
+ if (j == conf->raid_disks) {
+ set_bit(STRIPE_EXPAND_READY, &sh2->state);
+ set_bit(STRIPE_HANDLE, &sh2->state);
+ }
+ release_stripe(sh2);
+
+ /* done submitting copies, wait for them to complete */
+ if (i + 1 >= sh->disks) {
+ async_tx_ack(tx);
+ dma_wait_for_async_tx(tx);
+ }
+ }
+}
/*
* handle_stripe - do things to a stripe.
@@ -1339,81 +2603,70 @@ static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
* schedule a write of some buffers
* return confirmation of parity correctness
*
- * Parity calculations are done inside the stripe lock
* buffers are taken off read_list or write_list, and bh_cache buffers
* get BH_Lock set before the stripe lock is released.
*
*/
-
+
static void handle_stripe5(struct stripe_head *sh)
{
raid5_conf_t *conf = sh->raid_conf;
- int disks = sh->disks;
- struct bio *return_bi= NULL;
- struct bio *bi;
- int i;
- int syncing, expanding, expanded;
- int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
- int non_overwrite = 0;
- int failed_num=0;
+ int disks = sh->disks, i;
+ struct bio *return_bi = NULL;
+ struct stripe_head_state s;
struct r5dev *dev;
+ unsigned long pending = 0;
- PRINTK("handling stripe %llu, cnt=%d, pd_idx=%d\n",
- (unsigned long long)sh->sector, atomic_read(&sh->count),
- sh->pd_idx);
+ memset(&s, 0, sizeof(s));
+ pr_debug("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d "
+ "ops=%lx:%lx:%lx\n", (unsigned long long)sh->sector, sh->state,
+ atomic_read(&sh->count), sh->pd_idx,
+ sh->ops.pending, sh->ops.ack, sh->ops.complete);
spin_lock(&sh->lock);
clear_bit(STRIPE_HANDLE, &sh->state);
clear_bit(STRIPE_DELAYED, &sh->state);
- syncing = test_bit(STRIPE_SYNCING, &sh->state);
- expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
- expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+ s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
+ s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
/* Now to look around and see what can be done */
rcu_read_lock();
for (i=disks; i--; ) {
mdk_rdev_t *rdev;
- dev = &sh->dev[i];
+ struct r5dev *dev = &sh->dev[i];
clear_bit(R5_Insync, &dev->flags);
- PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
- i, dev->flags, dev->toread, dev->towrite, dev->written);
- /* maybe we can reply to a read */
- if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
- struct bio *rbi, *rbi2;
- PRINTK("Return read for disc %d\n", i);
- spin_lock_irq(&conf->device_lock);
- rbi = dev->toread;
- dev->toread = NULL;
- if (test_and_clear_bit(R5_Overlap, &dev->flags))
- wake_up(&conf->wait_for_overlap);
- spin_unlock_irq(&conf->device_lock);
- while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
- copy_data(0, rbi, dev->page, dev->sector);
- rbi2 = r5_next_bio(rbi, dev->sector);
- spin_lock_irq(&conf->device_lock);
- if (--rbi->bi_phys_segments == 0) {
- rbi->bi_next = return_bi;
- return_bi = rbi;
- }
- spin_unlock_irq(&conf->device_lock);
- rbi = rbi2;
- }
- }
+ pr_debug("check %d: state 0x%lx toread %p read %p write %p "
+ "written %p\n", i, dev->flags, dev->toread, dev->read,
+ dev->towrite, dev->written);
- /* now count some things */
- if (test_bit(R5_LOCKED, &dev->flags)) locked++;
- if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
+ /* maybe we can request a biofill operation
+ *
+ * new wantfill requests are only permitted while
+ * STRIPE_OP_BIOFILL is clear
+ */
+ if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread &&
+ !test_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+ set_bit(R5_Wantfill, &dev->flags);
-
- if (dev->toread) to_read++;
+ /* now count some things */
+ if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
+ if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
+ if (test_bit(R5_Wantcompute, &dev->flags)) s.compute++;
+
+ if (test_bit(R5_Wantfill, &dev->flags))
+ s.to_fill++;
+ else if (dev->toread)
+ s.to_read++;
if (dev->towrite) {
- to_write++;
+ s.to_write++;
if (!test_bit(R5_OVERWRITE, &dev->flags))
- non_overwrite++;
+ s.non_overwrite++;
}
- if (dev->written) written++;
+ if (dev->written)
+ s.written++;
rdev = rcu_dereference(conf->disks[i].rdev);
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
/* The ReadError flag will just be confusing now */
@@ -1422,306 +2675,131 @@ static void handle_stripe5(struct stripe_head *sh)
}
if (!rdev || !test_bit(In_sync, &rdev->flags)
|| test_bit(R5_ReadError, &dev->flags)) {
- failed++;
- failed_num = i;
+ s.failed++;
+ s.failed_num = i;
} else
set_bit(R5_Insync, &dev->flags);
}
rcu_read_unlock();
- PRINTK("locked=%d uptodate=%d to_read=%d"
+
+ if (s.to_fill && !test_and_set_bit(STRIPE_OP_BIOFILL, &sh->ops.pending))
+ sh->ops.count++;
+
+ pr_debug("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d\n",
- locked, uptodate, to_read, to_write, failed, failed_num);
+ s.locked, s.uptodate, s.to_read, s.to_write,
+ s.failed, s.failed_num);
/* check if the array has lost two devices and, if so, some requests might
* need to be failed
*/
- if (failed > 1 && to_read+to_write+written) {
- for (i=disks; i--; ) {
- int bitmap_end = 0;
-
- if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
- mdk_rdev_t *rdev;
- rcu_read_lock();
- rdev = rcu_dereference(conf->disks[i].rdev);
- if (rdev && test_bit(In_sync, &rdev->flags))
- /* multiple read failures in one stripe */
- md_error(conf->mddev, rdev);
- rcu_read_unlock();
- }
-
- spin_lock_irq(&conf->device_lock);
- /* fail all writes first */
- bi = sh->dev[i].towrite;
- sh->dev[i].towrite = NULL;
- if (bi) { to_write--; bitmap_end = 1; }
-
- if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
- wake_up(&conf->wait_for_overlap);
-
- while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
- struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
- clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
- md_write_end(conf->mddev);
- bi->bi_next = return_bi;
- return_bi = bi;
- }
- bi = nextbi;
- }
- /* and fail all 'written' */
- bi = sh->dev[i].written;
- sh->dev[i].written = NULL;
- if (bi) bitmap_end = 1;
- while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
- struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
- clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
- md_write_end(conf->mddev);
- bi->bi_next = return_bi;
- return_bi = bi;
- }
- bi = bi2;
- }
-
- /* fail any reads if this device is non-operational */
- if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
- test_bit(R5_ReadError, &sh->dev[i].flags)) {
- bi = sh->dev[i].toread;
- sh->dev[i].toread = NULL;
- if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
- wake_up(&conf->wait_for_overlap);
- if (bi) to_read--;
- while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
- struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
- clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
- bi->bi_next = return_bi;
- return_bi = bi;
- }
- bi = nextbi;
- }
- }
- spin_unlock_irq(&conf->device_lock);
- if (bitmap_end)
- bitmap_endwrite(conf->mddev->bitmap, sh->sector,
- STRIPE_SECTORS, 0, 0);
- }
- }
- if (failed > 1 && syncing) {
+ if (s.failed > 1 && s.to_read+s.to_write+s.written)
+ handle_requests_to_failed_array(conf, sh, &s, disks,
+ &return_bi);
+ if (s.failed > 1 && s.syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
clear_bit(STRIPE_SYNCING, &sh->state);
- syncing = 0;
+ s.syncing = 0;
}
/* might be able to return some write requests if the parity block
* is safe, or on a failed drive
*/
dev = &sh->dev[sh->pd_idx];
- if ( written &&
- ( (test_bit(R5_Insync, &dev->flags) && !test_bit(R5_LOCKED, &dev->flags) &&
- test_bit(R5_UPTODATE, &dev->flags))
- || (failed == 1 && failed_num == sh->pd_idx))
- ) {
- /* any written block on an uptodate or failed drive can be returned.
- * Note that if we 'wrote' to a failed drive, it will be UPTODATE, but
- * never LOCKED, so we don't need to test 'failed' directly.
- */
- for (i=disks; i--; )
- if (sh->dev[i].written) {
- dev = &sh->dev[i];
- if (!test_bit(R5_LOCKED, &dev->flags) &&
- test_bit(R5_UPTODATE, &dev->flags) ) {
- /* We can return any write requests */
- struct bio *wbi, *wbi2;
- int bitmap_end = 0;
- PRINTK("Return write for disc %d\n", i);
- spin_lock_irq(&conf->device_lock);
- wbi = dev->written;
- dev->written = NULL;
- while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
- wbi2 = r5_next_bio(wbi, dev->sector);
- if (--wbi->bi_phys_segments == 0) {
- md_write_end(conf->mddev);
- wbi->bi_next = return_bi;
- return_bi = wbi;
- }
- wbi = wbi2;
- }
- if (dev->towrite == NULL)
- bitmap_end = 1;
- spin_unlock_irq(&conf->device_lock);
- if (bitmap_end)
- bitmap_endwrite(conf->mddev->bitmap, sh->sector,
- STRIPE_SECTORS,
- !test_bit(STRIPE_DEGRADED, &sh->state), 0);
- }
- }
- }
+ if ( s.written &&
+ ((test_bit(R5_Insync, &dev->flags) &&
+ !test_bit(R5_LOCKED, &dev->flags) &&
+ test_bit(R5_UPTODATE, &dev->flags)) ||
+ (s.failed == 1 && s.failed_num == sh->pd_idx)))
+ handle_completed_write_requests(conf, sh, disks, &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 (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) {
- for (i=disks; i--;) {
- dev = &sh->dev[i];
- if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
- (dev->toread ||
- (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
- syncing ||
- expanding ||
- (failed && (sh->dev[failed_num].toread ||
- (sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags))))
- )
- ) {
- /* we would like to get this block, possibly
- * by computing it, but we might not be able to
- */
- if (uptodate == disks-1) {
- PRINTK("Computing block %d\n", i);
- compute_block(sh, i);
- uptodate++;
- } else if (test_bit(R5_Insync, &dev->flags)) {
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantread, &dev->flags);
- locked++;
- PRINTK("Reading block %d (sync=%d)\n",
- i, syncing);
- }
- }
- }
- set_bit(STRIPE_HANDLE, &sh->state);
+ if (s.to_read || s.non_overwrite ||
+ (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding ||
+ test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+ handle_issuing_new_read_requests5(sh, &s, disks);
+
+ /* Now we check to see if any write operations have recently
+ * completed
+ */
+
+ /* leave prexor set until postxor is done, allows us to distinguish
+ * a rmw from a rcw during biodrain
+ */
+ if (test_bit(STRIPE_OP_PREXOR, &sh->ops.complete) &&
+ test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+
+ clear_bit(STRIPE_OP_PREXOR, &sh->ops.complete);
+ clear_bit(STRIPE_OP_PREXOR, &sh->ops.ack);
+ clear_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+
+ for (i = disks; i--; )
+ clear_bit(R5_Wantprexor, &sh->dev[i].flags);
}
- /* now to consider writing and what else, if anything should be read */
- if (to_write) {
- int rmw=0, rcw=0;
- for (i=disks ; i--;) {
- /* would I have to read this buffer for read_modify_write */
+ /* if only POSTXOR is set then this is an 'expand' postxor */
+ if (test_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete) &&
+ test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete)) {
+
+ clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.complete);
+ clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.ack);
+ clear_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending);
+
+ clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+ clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
+ clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+
+ /* All the 'written' buffers and the parity block are ready to
+ * be written back to disk
+ */
+ BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
+ for (i = disks; i--; ) {
dev = &sh->dev[i];
- if ((dev->towrite || i == sh->pd_idx) &&
- (!test_bit(R5_LOCKED, &dev->flags)
- ) &&
- !test_bit(R5_UPTODATE, &dev->flags)) {
- if (test_bit(R5_Insync, &dev->flags)
-/* && !(!mddev->insync && i == sh->pd_idx) */
- )
- rmw++;
- else rmw += 2*disks; /* cannot read it */
- }
- /* Would I have to read this buffer for reconstruct_write */
- if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
- (!test_bit(R5_LOCKED, &dev->flags)
- ) &&
- !test_bit(R5_UPTODATE, &dev->flags)) {
- if (test_bit(R5_Insync, &dev->flags)) rcw++;
- else rcw += 2*disks;
+ if (test_bit(R5_LOCKED, &dev->flags) &&
+ (i == sh->pd_idx || dev->written)) {
+ pr_debug("Writing block %d\n", i);
+ set_bit(R5_Wantwrite, &dev->flags);
+ if (!test_and_set_bit(
+ STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
+ if (!test_bit(R5_Insync, &dev->flags) ||
+ (i == sh->pd_idx && s.failed == 0))
+ set_bit(STRIPE_INSYNC, &sh->state);
}
}
- PRINTK("for sector %llu, rmw=%d rcw=%d\n",
- (unsigned long long)sh->sector, rmw, rcw);
- set_bit(STRIPE_HANDLE, &sh->state);
- if (rmw < rcw && rmw > 0)
- /* prefer read-modify-write, but need to get some data */
- for (i=disks; i--;) {
- dev = &sh->dev[i];
- if ((dev->towrite || i == sh->pd_idx) &&
- !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
- test_bit(R5_Insync, &dev->flags)) {
- if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
- {
- PRINTK("Read_old block %d for r-m-w\n", i);
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantread, &dev->flags);
- locked++;
- } else {
- set_bit(STRIPE_DELAYED, &sh->state);
- set_bit(STRIPE_HANDLE, &sh->state);
- }
- }
- }
- if (rcw <= rmw && rcw > 0)
- /* want reconstruct write, but need to get some data */
- for (i=disks; i--;) {
- dev = &sh->dev[i];
- if (!test_bit(R5_OVERWRITE, &dev->flags) && i != sh->pd_idx &&
- !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
- test_bit(R5_Insync, &dev->flags)) {
- if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
- {
- PRINTK("Read_old block %d for Reconstruct\n", i);
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantread, &dev->flags);
- locked++;
- } else {
- set_bit(STRIPE_DELAYED, &sh->state);
- set_bit(STRIPE_HANDLE, &sh->state);
- }
- }
- }
- /* now if nothing is locked, and if we have enough data, we can start a write request */
- if (locked == 0 && (rcw == 0 ||rmw == 0) &&
- !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
- PRINTK("Computing parity...\n");
- compute_parity5(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
- /* now every locked buffer is ready to be written */
- for (i=disks; i--;)
- if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
- PRINTK("Writing block %d\n", i);
- locked++;
- set_bit(R5_Wantwrite, &sh->dev[i].flags);
- if (!test_bit(R5_Insync, &sh->dev[i].flags)
- || (i==sh->pd_idx && failed == 0))
- set_bit(STRIPE_INSYNC, &sh->state);
- }
- if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
- atomic_dec(&conf->preread_active_stripes);
- if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
- md_wakeup_thread(conf->mddev->thread);
- }
+ if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+ atomic_dec(&conf->preread_active_stripes);
+ if (atomic_read(&conf->preread_active_stripes) <
+ IO_THRESHOLD)
+ md_wakeup_thread(conf->mddev->thread);
}
}
- /* maybe we need to check and possibly fix the parity for this stripe
- * Any reads will already have been scheduled, so we just see if enough data
- * is available
+ /* 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.
+ * 2/ A 'check' operation is in flight, as it may clobber the parity
+ * block.
*/
- if (syncing && locked == 0 &&
- !test_bit(STRIPE_INSYNC, &sh->state)) {
- set_bit(STRIPE_HANDLE, &sh->state);
- if (failed == 0) {
- BUG_ON(uptodate != disks);
- compute_parity5(sh, CHECK_PARITY);
- uptodate--;
- if (page_is_zero(sh->dev[sh->pd_idx].page)) {
- /* parity is correct (on disc, not in buffer any more) */
- set_bit(STRIPE_INSYNC, &sh->state);
- } else {
- conf->mddev->resync_mismatches += STRIPE_SECTORS;
- if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
- /* don't try to repair!! */
- set_bit(STRIPE_INSYNC, &sh->state);
- else {
- compute_block(sh, sh->pd_idx);
- uptodate++;
- }
- }
- }
- if (!test_bit(STRIPE_INSYNC, &sh->state)) {
- /* either failed parity check, or recovery is happening */
- if (failed==0)
- failed_num = sh->pd_idx;
- dev = &sh->dev[failed_num];
- BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
- BUG_ON(uptodate != disks);
+ if (s.to_write && !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending) &&
+ !test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
+ handle_issuing_new_write_requests5(conf, sh, &s, disks);
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantwrite, &dev->flags);
- clear_bit(STRIPE_DEGRADED, &sh->state);
- locked++;
- set_bit(STRIPE_INSYNC, &sh->state);
- }
- }
- if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+ /* maybe we need to check and possibly fix the parity for this stripe
+ * Any reads will already have been scheduled, so we just see if enough
+ * data is available. The parity check is held off while parity
+ * dependent operations are in flight.
+ */
+ if ((s.syncing && s.locked == 0 &&
+ !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
+ !test_bit(STRIPE_INSYNC, &sh->state)) ||
+ test_bit(STRIPE_OP_CHECK, &sh->ops.pending) ||
+ test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending))
+ handle_parity_checks5(conf, sh, &s, disks);
+
+ if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
md_done_sync(conf->mddev, STRIPE_SECTORS,1);
clear_bit(STRIPE_SYNCING, &sh->state);
}
@@ -1729,186 +2807,102 @@ static void handle_stripe5(struct stripe_head *sh)
/* If the failed drive is just a ReadError, then we might need to progress
* the repair/check process
*/
- if (failed == 1 && ! conf->mddev->ro &&
- test_bit(R5_ReadError, &sh->dev[failed_num].flags)
- && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags)
- && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)
+ if (s.failed == 1 && !conf->mddev->ro &&
+ test_bit(R5_ReadError, &sh->dev[s.failed_num].flags)
+ && !test_bit(R5_LOCKED, &sh->dev[s.failed_num].flags)
+ && test_bit(R5_UPTODATE, &sh->dev[s.failed_num].flags)
) {
- dev = &sh->dev[failed_num];
+ dev = &sh->dev[s.failed_num];
if (!test_bit(R5_ReWrite, &dev->flags)) {
set_bit(R5_Wantwrite, &dev->flags);
+ if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
set_bit(R5_ReWrite, &dev->flags);
set_bit(R5_LOCKED, &dev->flags);
- locked++;
+ s.locked++;
} else {
/* let's read it back */
set_bit(R5_Wantread, &dev->flags);
+ if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
set_bit(R5_LOCKED, &dev->flags);
- locked++;
+ s.locked++;
}
}
- if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
- /* Need to write out all blocks after computing parity */
- sh->disks = conf->raid_disks;
- sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks);
- compute_parity5(sh, RECONSTRUCT_WRITE);
- for (i= conf->raid_disks; i--;) {
- set_bit(R5_LOCKED, &sh->dev[i].flags);
- locked++;
+ /* Finish postxor operations initiated by the expansion
+ * process
+ */
+ if (test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete) &&
+ !test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending)) {
+
+ clear_bit(STRIPE_EXPANDING, &sh->state);
+
+ clear_bit(STRIPE_OP_POSTXOR, &sh->ops.pending);
+ clear_bit(STRIPE_OP_POSTXOR, &sh->ops.ack);
+ clear_bit(STRIPE_OP_POSTXOR, &sh->ops.complete);
+
+ for (i = conf->raid_disks; i--; ) {
set_bit(R5_Wantwrite, &sh->dev[i].flags);
+ if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
}
- clear_bit(STRIPE_EXPANDING, &sh->state);
- } else if (expanded) {
+ }
+
+ if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state) &&
+ !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
+ /* Need to write out all blocks after computing parity */
+ sh->disks = conf->raid_disks;
+ sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
+ conf->raid_disks);
+ s.locked += handle_write_operations5(sh, 0, 1);
+ } else if (s.expanded &&
+ !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
clear_bit(STRIPE_EXPAND_READY, &sh->state);
atomic_dec(&conf->reshape_stripes);
wake_up(&conf->wait_for_overlap);
md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
}
- if (expanding && locked == 0) {
- /* We have read all the blocks in this stripe and now we need to
- * copy some of them into a target stripe for expand.
- */
- clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
- for (i=0; i< sh->disks; i++)
- if (i != sh->pd_idx) {
- int dd_idx, pd_idx, j;
- struct stripe_head *sh2;
-
- sector_t bn = compute_blocknr(sh, i);
- sector_t s = raid5_compute_sector(bn, conf->raid_disks,
- conf->raid_disks-1,
- &dd_idx, &pd_idx, conf);
- sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1);
- if (sh2 == NULL)
- /* so far only the early blocks of this stripe
- * have been requested. When later blocks
- * get requested, we will try again
- */
- continue;
- if(!test_bit(STRIPE_EXPANDING, &sh2->state) ||
- test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) {
- /* must have already done this block */
- release_stripe(sh2);
- continue;
- }
- memcpy(page_address(sh2->dev[dd_idx].page),
- page_address(sh->dev[i].page),
- STRIPE_SIZE);
- set_bit(R5_Expanded, &sh2->dev[dd_idx].flags);
- set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags);
- for (j=0; j<conf->raid_disks; j++)
- if (j != sh2->pd_idx &&
- !test_bit(R5_Expanded, &sh2->dev[j].flags))
- break;
- if (j == conf->raid_disks) {
- set_bit(STRIPE_EXPAND_READY, &sh2->state);
- set_bit(STRIPE_HANDLE, &sh2->state);
- }
- release_stripe(sh2);
- }
- }
+ if (s.expanding && s.locked == 0)
+ handle_stripe_expansion(conf, sh, NULL);
+
+ if (sh->ops.count)
+ pending = get_stripe_work(sh);
spin_unlock(&sh->lock);
- while ((bi=return_bi)) {
- int bytes = bi->bi_size;
+ if (pending)
+ raid5_run_ops(sh, pending);
- return_bi = bi->bi_next;
- bi->bi_next = NULL;
- bi->bi_size = 0;
- bi->bi_end_io(bi, bytes,
- test_bit(BIO_UPTODATE, &bi->bi_flags)
- ? 0 : -EIO);
- }
- for (i=disks; i-- ;) {
- int rw;
- struct bio *bi;
- mdk_rdev_t *rdev;
- if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
- rw = WRITE;
- else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
- rw = READ;
- else
- continue;
-
- bi = &sh->dev[i].req;
-
- bi->bi_rw = rw;
- if (rw == WRITE)
- bi->bi_end_io = raid5_end_write_request;
- else
- bi->bi_end_io = raid5_end_read_request;
-
- rcu_read_lock();
- rdev = rcu_dereference(conf->disks[i].rdev);
- if (rdev && test_bit(Faulty, &rdev->flags))
- rdev = NULL;
- if (rdev)
- atomic_inc(&rdev->nr_pending);
- rcu_read_unlock();
-
- if (rdev) {
- if (syncing || expanding || expanded)
- md_sync_acct(rdev->bdev, STRIPE_SECTORS);
+ return_io(return_bi);
- bi->bi_bdev = rdev->bdev;
- PRINTK("for %llu schedule op %ld on disc %d\n",
- (unsigned long long)sh->sector, bi->bi_rw, i);
- atomic_inc(&sh->count);
- bi->bi_sector = sh->sector + rdev->data_offset;
- bi->bi_flags = 1 << BIO_UPTODATE;
- bi->bi_vcnt = 1;
- bi->bi_max_vecs = 1;
- bi->bi_idx = 0;
- bi->bi_io_vec = &sh->dev[i].vec;
- bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
- bi->bi_io_vec[0].bv_offset = 0;
- bi->bi_size = STRIPE_SIZE;
- bi->bi_next = NULL;
- if (rw == WRITE &&
- test_bit(R5_ReWrite, &sh->dev[i].flags))
- atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
- generic_make_request(bi);
- } else {
- if (rw == WRITE)
- set_bit(STRIPE_DEGRADED, &sh->state);
- PRINTK("skip op %ld on disc %d for sector %llu\n",
- bi->bi_rw, i, (unsigned long long)sh->sector);
- clear_bit(R5_LOCKED, &sh->dev[i].flags);
- set_bit(STRIPE_HANDLE, &sh->state);
- }
- }
}
static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
{
raid6_conf_t *conf = sh->raid_conf;
int disks = sh->disks;
- struct bio *return_bi= NULL;
- struct bio *bi;
- int i;
- int syncing, expanding, expanded;
- int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
- int non_overwrite = 0;
- int failed_num[2] = {0, 0};
+ struct bio *return_bi = NULL;
+ int i, pd_idx = sh->pd_idx;
+ struct stripe_head_state s;
+ struct r6_state r6s;
struct r5dev *dev, *pdev, *qdev;
- int pd_idx = sh->pd_idx;
- int qd_idx = raid6_next_disk(pd_idx, disks);
- int p_failed, q_failed;
- PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n",
- (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count),
- pd_idx, qd_idx);
+ r6s.qd_idx = raid6_next_disk(pd_idx, disks);
+ pr_debug("handling stripe %llu, state=%#lx cnt=%d, "
+ "pd_idx=%d, qd_idx=%d\n",
+ (unsigned long long)sh->sector, sh->state,
+ atomic_read(&sh->count), pd_idx, r6s.qd_idx);
+ memset(&s, 0, sizeof(s));
spin_lock(&sh->lock);
clear_bit(STRIPE_HANDLE, &sh->state);
clear_bit(STRIPE_DELAYED, &sh->state);
- syncing = test_bit(STRIPE_SYNCING, &sh->state);
- expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
- expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
+ s.syncing = test_bit(STRIPE_SYNCING, &sh->state);
+ s.expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+ s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
/* Now to look around and see what can be done */
rcu_read_lock();
@@ -1917,12 +2911,12 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
dev = &sh->dev[i];
clear_bit(R5_Insync, &dev->flags);
- PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
+ pr_debug("check %d: state 0x%lx read %p write %p written %p\n",
i, dev->flags, dev->toread, dev->towrite, dev->written);
/* maybe we can reply to a read */
if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
struct bio *rbi, *rbi2;
- PRINTK("Return read for disc %d\n", i);
+ pr_debug("Return read for disc %d\n", i);
spin_lock_irq(&conf->device_lock);
rbi = dev->toread;
dev->toread = NULL;
@@ -1943,17 +2937,19 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
}
/* now count some things */
- if (test_bit(R5_LOCKED, &dev->flags)) locked++;
- if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
+ if (test_bit(R5_LOCKED, &dev->flags)) s.locked++;
+ if (test_bit(R5_UPTODATE, &dev->flags)) s.uptodate++;
- if (dev->toread) to_read++;
+ if (dev->toread)
+ s.to_read++;
if (dev->towrite) {
- to_write++;
+ s.to_write++;
if (!test_bit(R5_OVERWRITE, &dev->flags))
- non_overwrite++;
+ s.non_overwrite++;
}
- if (dev->written) written++;
+ if (dev->written)
+ s.written++;
rdev = rcu_dereference(conf->disks[i].rdev);
if (!rdev || !test_bit(In_sync, &rdev->flags)) {
/* The ReadError flag will just be confusing now */
@@ -1962,96 +2958,27 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
}
if (!rdev || !test_bit(In_sync, &rdev->flags)
|| test_bit(R5_ReadError, &dev->flags)) {
- if ( failed < 2 )
- failed_num[failed] = i;
- failed++;
+ if (s.failed < 2)
+ r6s.failed_num[s.failed] = i;
+ s.failed++;
} else
set_bit(R5_Insync, &dev->flags);
}
rcu_read_unlock();
- PRINTK("locked=%d uptodate=%d to_read=%d"
+ pr_debug("locked=%d uptodate=%d to_read=%d"
" to_write=%d failed=%d failed_num=%d,%d\n",
- locked, uptodate, to_read, to_write, failed,
- failed_num[0], failed_num[1]);
- /* check if the array has lost >2 devices and, if so, some requests might
- * need to be failed
+ s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
+ r6s.failed_num[0], r6s.failed_num[1]);
+ /* check if the array has lost >2 devices and, if so, some requests
+ * might need to be failed
*/
- if (failed > 2 && to_read+to_write+written) {
- for (i=disks; i--; ) {
- int bitmap_end = 0;
-
- if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
- mdk_rdev_t *rdev;
- rcu_read_lock();
- rdev = rcu_dereference(conf->disks[i].rdev);
- if (rdev && test_bit(In_sync, &rdev->flags))
- /* multiple read failures in one stripe */
- md_error(conf->mddev, rdev);
- rcu_read_unlock();
- }
-
- spin_lock_irq(&conf->device_lock);
- /* fail all writes first */
- bi = sh->dev[i].towrite;
- sh->dev[i].towrite = NULL;
- if (bi) { to_write--; bitmap_end = 1; }
-
- if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
- wake_up(&conf->wait_for_overlap);
-
- while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
- struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
- clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
- md_write_end(conf->mddev);
- bi->bi_next = return_bi;
- return_bi = bi;
- }
- bi = nextbi;
- }
- /* and fail all 'written' */
- bi = sh->dev[i].written;
- sh->dev[i].written = NULL;
- if (bi) bitmap_end = 1;
- while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
- struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
- clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
- md_write_end(conf->mddev);
- bi->bi_next = return_bi;
- return_bi = bi;
- }
- bi = bi2;
- }
-
- /* fail any reads if this device is non-operational */
- if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
- test_bit(R5_ReadError, &sh->dev[i].flags)) {
- bi = sh->dev[i].toread;
- sh->dev[i].toread = NULL;
- if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
- wake_up(&conf->wait_for_overlap);
- if (bi) to_read--;
- while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
- struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
- clear_bit(BIO_UPTODATE, &bi->bi_flags);
- if (--bi->bi_phys_segments == 0) {
- bi->bi_next = return_bi;
- return_bi = bi;
- }
- bi = nextbi;
- }
- }
- spin_unlock_irq(&conf->device_lock);
- if (bitmap_end)
- bitmap_endwrite(conf->mddev->bitmap, sh->sector,
- STRIPE_SECTORS, 0, 0);
- }
- }
- if (failed > 2 && syncing) {
+ if (s.failed > 2 && s.to_read+s.to_write+s.written)
+ handle_requests_to_failed_array(conf, sh, &s, disks,
+ &return_bi);
+ if (s.failed > 2 && s.syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
clear_bit(STRIPE_SYNCING, &sh->state);
- syncing = 0;
+ s.syncing = 0;
}
/*
@@ -2059,279 +2986,41 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
* are safe, or on a failed drive
*/
pdev = &sh->dev[pd_idx];
- p_failed = (failed >= 1 && failed_num[0] == pd_idx)
- || (failed >= 2 && failed_num[1] == pd_idx);
- qdev = &sh->dev[qd_idx];
- q_failed = (failed >= 1 && failed_num[0] == qd_idx)
- || (failed >= 2 && failed_num[1] == qd_idx);
-
- if ( written &&
- ( p_failed || ((test_bit(R5_Insync, &pdev->flags)
+ r6s.p_failed = (s.failed >= 1 && r6s.failed_num[0] == pd_idx)
+ || (s.failed >= 2 && r6s.failed_num[1] == pd_idx);
+ qdev = &sh->dev[r6s.qd_idx];
+ r6s.q_failed = (s.failed >= 1 && r6s.failed_num[0] == r6s.qd_idx)
+ || (s.failed >= 2 && r6s.failed_num[1] == r6s.qd_idx);
+
+ if ( s.written &&
+ ( r6s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
&& !test_bit(R5_LOCKED, &pdev->flags)
- && test_bit(R5_UPTODATE, &pdev->flags))) ) &&
- ( q_failed || ((test_bit(R5_Insync, &qdev->flags)
+ && test_bit(R5_UPTODATE, &pdev->flags)))) &&
+ ( r6s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
&& !test_bit(R5_LOCKED, &qdev->flags)
- && test_bit(R5_UPTODATE, &qdev->flags))) ) ) {
- /* any written block on an uptodate or failed drive can be
- * returned. Note that if we 'wrote' to a failed drive,
- * it will be UPTODATE, but never LOCKED, so we don't need
- * to test 'failed' directly.
- */
- for (i=disks; i--; )
- if (sh->dev[i].written) {
- dev = &sh->dev[i];
- if (!test_bit(R5_LOCKED, &dev->flags) &&
- test_bit(R5_UPTODATE, &dev->flags) ) {
- /* We can return any write requests */
- int bitmap_end = 0;
- struct bio *wbi, *wbi2;
- PRINTK("Return write for stripe %llu disc %d\n",
- (unsigned long long)sh->sector, i);
- spin_lock_irq(&conf->device_lock);
- wbi = dev->written;
- dev->written = NULL;
- while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
- wbi2 = r5_next_bio(wbi, dev->sector);
- if (--wbi->bi_phys_segments == 0) {
- md_write_end(conf->mddev);
- wbi->bi_next = return_bi;
- return_bi = wbi;
- }
- wbi = wbi2;
- }
- if (dev->towrite == NULL)
- bitmap_end = 1;
- spin_unlock_irq(&conf->device_lock);
- if (bitmap_end)
- bitmap_endwrite(conf->mddev->bitmap, sh->sector,
- STRIPE_SECTORS,
- !test_bit(STRIPE_DEGRADED, &sh->state), 0);
- }
- }
- }
+ && test_bit(R5_UPTODATE, &qdev->flags)))))
+ handle_completed_write_requests(conf, sh, disks, &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 (to_read || non_overwrite || (to_write && failed) ||
- (syncing && (uptodate < disks)) || expanding) {
- for (i=disks; i--;) {
- dev = &sh->dev[i];
- if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
- (dev->toread ||
- (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
- syncing ||
- expanding ||
- (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
- (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
- )
- ) {
- /* we would like to get this block, possibly
- * by computing it, but we might not be able to
- */
- if (uptodate == disks-1) {
- PRINTK("Computing stripe %llu block %d\n",
- (unsigned long long)sh->sector, i);
- compute_block_1(sh, i, 0);
- uptodate++;
- } else if ( uptodate == disks-2 && failed >= 2 ) {
- /* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
- int other;
- for (other=disks; other--;) {
- if ( other == i )
- continue;
- if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) )
- break;
- }
- BUG_ON(other < 0);
- PRINTK("Computing stripe %llu blocks %d,%d\n",
- (unsigned long long)sh->sector, i, other);
- compute_block_2(sh, i, other);
- uptodate += 2;
- } else if (test_bit(R5_Insync, &dev->flags)) {
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantread, &dev->flags);
- locked++;
- PRINTK("Reading block %d (sync=%d)\n",
- i, syncing);
- }
- }
- }
- set_bit(STRIPE_HANDLE, &sh->state);
- }
+ if (s.to_read || s.non_overwrite || (s.to_write && s.failed) ||
+ (s.syncing && (s.uptodate < disks)) || s.expanding)
+ handle_issuing_new_read_requests6(sh, &s, &r6s, disks);
/* now to consider writing and what else, if anything should be read */
- if (to_write) {
- int rcw=0, must_compute=0;
- for (i=disks ; i--;) {
- dev = &sh->dev[i];
- /* Would I have to read this buffer for reconstruct_write */
- if (!test_bit(R5_OVERWRITE, &dev->flags)
- && i != pd_idx && i != qd_idx
- && (!test_bit(R5_LOCKED, &dev->flags)
- ) &&
- !test_bit(R5_UPTODATE, &dev->flags)) {
- if (test_bit(R5_Insync, &dev->flags)) rcw++;
- else {
- PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags);
- must_compute++;
- }
- }
- }
- PRINTK("for sector %llu, rcw=%d, must_compute=%d\n",
- (unsigned long long)sh->sector, rcw, must_compute);
- set_bit(STRIPE_HANDLE, &sh->state);
-
- if (rcw > 0)
- /* want reconstruct write, but need to get some data */
- for (i=disks; i--;) {
- dev = &sh->dev[i];
- if (!test_bit(R5_OVERWRITE, &dev->flags)
- && !(failed == 0 && (i == pd_idx || i == qd_idx))
- && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
- test_bit(R5_Insync, &dev->flags)) {
- if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
- {
- PRINTK("Read_old stripe %llu block %d for Reconstruct\n",
- (unsigned long long)sh->sector, i);
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantread, &dev->flags);
- locked++;
- } else {
- PRINTK("Request delayed stripe %llu block %d for Reconstruct\n",
- (unsigned long long)sh->sector, i);
- set_bit(STRIPE_DELAYED, &sh->state);
- set_bit(STRIPE_HANDLE, &sh->state);
- }
- }
- }
- /* now if nothing is locked, and if we have enough data, we can start a write request */
- if (locked == 0 && rcw == 0 &&
- !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
- if ( must_compute > 0 ) {
- /* We have failed blocks and need to compute them */
- switch ( failed ) {
- case 0: BUG();
- case 1: compute_block_1(sh, failed_num[0], 0); break;
- case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
- default: BUG(); /* This request should have been failed? */
- }
- }
-
- PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector);
- compute_parity6(sh, RECONSTRUCT_WRITE);
- /* now every locked buffer is ready to be written */
- for (i=disks; i--;)
- if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
- PRINTK("Writing stripe %llu block %d\n",
- (unsigned long long)sh->sector, i);
- locked++;
- set_bit(R5_Wantwrite, &sh->dev[i].flags);
- }
- /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
- set_bit(STRIPE_INSYNC, &sh->state);
-
- if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
- atomic_dec(&conf->preread_active_stripes);
- if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
- md_wakeup_thread(conf->mddev->thread);
- }
- }
- }
+ if (s.to_write)
+ handle_issuing_new_write_requests6(conf, sh, &s, &r6s, disks);
/* maybe we need to check and possibly fix the parity for this stripe
- * Any reads will already have been scheduled, so we just see if enough data
- * is available
+ * Any reads will already have been scheduled, so we just see if enough
+ * data is available
*/
- if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
- int update_p = 0, update_q = 0;
- struct r5dev *dev;
-
- set_bit(STRIPE_HANDLE, &sh->state);
-
- BUG_ON(failed>2);
- BUG_ON(uptodate < disks);
- /* Want to check and possibly repair P and Q.
- * However there could be one 'failed' device, in which
- * case we can only check one of them, possibly using the
- * other to generate missing data
- */
-
- /* If !tmp_page, we cannot do the calculations,
- * but as we have set STRIPE_HANDLE, we will soon be called
- * by stripe_handle with a tmp_page - just wait until then.
- */
- if (tmp_page) {
- if (failed == q_failed) {
- /* The only possible failed device holds 'Q', so it makes
- * sense to check P (If anything else were failed, we would
- * have used P to recreate it).
- */
- compute_block_1(sh, pd_idx, 1);
- if (!page_is_zero(sh->dev[pd_idx].page)) {
- compute_block_1(sh,pd_idx,0);
- update_p = 1;
- }
- }
- if (!q_failed && failed < 2) {
- /* q is not failed, and we didn't use it to generate
- * anything, so it makes sense to check it
- */
- memcpy(page_address(tmp_page),
- page_address(sh->dev[qd_idx].page),
- STRIPE_SIZE);
- compute_parity6(sh, UPDATE_PARITY);
- if (memcmp(page_address(tmp_page),
- page_address(sh->dev[qd_idx].page),
- STRIPE_SIZE)!= 0) {
- clear_bit(STRIPE_INSYNC, &sh->state);
- update_q = 1;
- }
- }
- if (update_p || update_q) {
- conf->mddev->resync_mismatches += STRIPE_SECTORS;
- if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
- /* don't try to repair!! */
- update_p = update_q = 0;
- }
-
- /* now write out any block on a failed drive,
- * or P or Q if they need it
- */
+ if (s.syncing && s.locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state))
+ handle_parity_checks6(conf, sh, &s, &r6s, tmp_page, disks);
- if (failed == 2) {
- dev = &sh->dev[failed_num[1]];
- locked++;
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantwrite, &dev->flags);
- }
- if (failed >= 1) {
- dev = &sh->dev[failed_num[0]];
- locked++;
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantwrite, &dev->flags);
- }
-
- if (update_p) {
- dev = &sh->dev[pd_idx];
- locked ++;
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantwrite, &dev->flags);
- }
- if (update_q) {
- dev = &sh->dev[qd_idx];
- locked++;
- set_bit(R5_LOCKED, &dev->flags);
- set_bit(R5_Wantwrite, &dev->flags);
- }
- clear_bit(STRIPE_DEGRADED, &sh->state);
-
- set_bit(STRIPE_INSYNC, &sh->state);
- }
- }
-
- if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+ if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
md_done_sync(conf->mddev, STRIPE_SECTORS,1);
clear_bit(STRIPE_SYNCING, &sh->state);
}
@@ -2339,9 +3028,9 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
/* If the failed drives are just a ReadError, then we might need
* to progress the repair/check process
*/
- if (failed <= 2 && ! conf->mddev->ro)
- for (i=0; i<failed;i++) {
- dev = &sh->dev[failed_num[i]];
+ if (s.failed <= 2 && !conf->mddev->ro)
+ for (i = 0; i < s.failed; i++) {
+ dev = &sh->dev[r6s.failed_num[i]];
if (test_bit(R5_ReadError, &dev->flags)
&& !test_bit(R5_LOCKED, &dev->flags)
&& test_bit(R5_UPTODATE, &dev->flags)
@@ -2358,7 +3047,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
}
}
- if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
+ if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) {
/* Need to write out all blocks after computing P&Q */
sh->disks = conf->raid_disks;
sh->pd_idx = stripe_to_pdidx(sh->sector, conf,
@@ -2366,82 +3055,24 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
compute_parity6(sh, RECONSTRUCT_WRITE);
for (i = conf->raid_disks ; i-- ; ) {
set_bit(R5_LOCKED, &sh->dev[i].flags);
- locked++;
+ s.locked++;
set_bit(R5_Wantwrite, &sh->dev[i].flags);
}
clear_bit(STRIPE_EXPANDING, &sh->state);
- } else if (expanded) {
+ } else if (s.expanded) {
clear_bit(STRIPE_EXPAND_READY, &sh->state);
atomic_dec(&conf->reshape_stripes);
wake_up(&conf->wait_for_overlap);
md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
}
- if (expanding && locked == 0) {
- /* We have read all the blocks in this stripe and now we need to
- * copy some of them into a target stripe for expand.
- */
- clear_bit(STRIPE_EXPAND_SOURCE, &sh->state);
- for (i = 0; i < sh->disks ; i++)
- if (i != pd_idx && i != qd_idx) {
- int dd_idx2, pd_idx2, j;
- struct stripe_head *sh2;
-
- sector_t bn = compute_blocknr(sh, i);
- sector_t s = raid5_compute_sector(
- bn, conf->raid_disks,
- conf->raid_disks - conf->max_degraded,
- &dd_idx2, &pd_idx2, conf);
- sh2 = get_active_stripe(conf, s,
- conf->raid_disks,
- pd_idx2, 1);
- if (sh2 == NULL)
- /* so for only the early blocks of
- * this stripe have been requests.
- * When later blocks get requests, we
- * will try again
- */
- continue;
- if (!test_bit(STRIPE_EXPANDING, &sh2->state) ||
- test_bit(R5_Expanded,
- &sh2->dev[dd_idx2].flags)) {
- /* must have already done this block */
- release_stripe(sh2);
- continue;
- }
- memcpy(page_address(sh2->dev[dd_idx2].page),
- page_address(sh->dev[i].page),
- STRIPE_SIZE);
- set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags);
- set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags);
- for (j = 0 ; j < conf->raid_disks ; j++)
- if (j != sh2->pd_idx &&
- j != raid6_next_disk(sh2->pd_idx,
- sh2->disks) &&
- !test_bit(R5_Expanded,
- &sh2->dev[j].flags))
- break;
- if (j == conf->raid_disks) {
- set_bit(STRIPE_EXPAND_READY,
- &sh2->state);
- set_bit(STRIPE_HANDLE, &sh2->state);
- }
- release_stripe(sh2);
- }
- }
+ if (s.expanding && s.locked == 0)
+ handle_stripe_expansion(conf, sh, &r6s);
spin_unlock(&sh->lock);
- while ((bi=return_bi)) {
- int bytes = bi->bi_size;
+ return_io(return_bi);
- return_bi = bi->bi_next;
- bi->bi_next = NULL;
- bi->bi_size = 0;
- bi->bi_end_io(bi, bytes,
- test_bit(BIO_UPTODATE, &bi->bi_flags)
- ? 0 : -EIO);
- }
for (i=disks; i-- ;) {
int rw;
struct bio *bi;
@@ -2470,11 +3101,11 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
rcu_read_unlock();
if (rdev) {
- if (syncing || expanding || expanded)
+ if (s.syncing || s.expanding || s.expanded)
md_sync_acct(rdev->bdev, STRIPE_SECTORS);
bi->bi_bdev = rdev->bdev;
- PRINTK("for %llu schedule op %ld on disc %d\n",
+ pr_debug("for %llu schedule op %ld on disc %d\n",
(unsigned long long)sh->sector, bi->bi_rw, i);
atomic_inc(&sh->count);
bi->bi_sector = sh->sector + rdev->data_offset;
@@ -2494,7 +3125,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
} else {
if (rw == WRITE)
set_bit(STRIPE_DEGRADED, &sh->state);
- PRINTK("skip op %ld on disc %d for sector %llu\n",
+ pr_debug("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
set_bit(STRIPE_HANDLE, &sh->state);
@@ -2738,7 +3369,7 @@ static int raid5_align_endio(struct bio *bi, unsigned int bytes, int error)
}
- PRINTK("raid5_align_endio : io error...handing IO for a retry\n");
+ pr_debug("raid5_align_endio : io error...handing IO for a retry\n");
add_bio_to_retry(raid_bi, conf);
return 0;
@@ -2776,7 +3407,7 @@ static int chunk_aligned_read(request_queue_t *q, struct bio * raid_bio)
mdk_rdev_t *rdev;
if (!in_chunk_boundary(mddev, raid_bio)) {
- PRINTK("chunk_aligned_read : non aligned\n");
+ pr_debug("chunk_aligned_read : non aligned\n");
return 0;
}
/*
@@ -2900,7 +3531,7 @@ static int make_request(request_queue_t *q, struct bio * bi)
new_sector = raid5_compute_sector(logical_sector, disks, data_disks,
&dd_idx, &pd_idx, conf);
- PRINTK("raid5: make_request, sector %llu logical %llu\n",
+ pr_debug("raid5: make_request, sector %llu logical %llu\n",
(unsigned long long)new_sector,
(unsigned long long)logical_sector);
@@ -3273,7 +3904,7 @@ static void raid5d (mddev_t *mddev)
raid5_conf_t *conf = mddev_to_conf(mddev);
int handled;
- PRINTK("+++ raid5d active\n");
+ pr_debug("+++ raid5d active\n");
md_check_recovery(mddev);
@@ -3308,8 +3939,10 @@ static void raid5d (mddev_t *mddev)
handled++;
}
- if (list_empty(&conf->handle_list))
+ if (list_empty(&conf->handle_list)) {
+ async_tx_issue_pending_all();
break;
+ }
first = conf->handle_list.next;
sh = list_entry(first, struct stripe_head, lru);
@@ -3325,13 +3958,13 @@ static void raid5d (mddev_t *mddev)
spin_lock_irq(&conf->device_lock);
}
- PRINTK("%d stripes handled\n", handled);
+ pr_debug("%d stripes handled\n", handled);
spin_unlock_irq(&conf->device_lock);
unplug_slaves(mddev);
- PRINTK("--- raid5d inactive\n");
+ pr_debug("--- raid5d inactive\n");
}
static ssize_t
@@ -3507,7 +4140,7 @@ static int run(mddev_t *mddev)
atomic_set(&conf->preread_active_stripes, 0);
atomic_set(&conf->active_aligned_reads, 0);
- PRINTK("raid5: run(%s) called.\n", mdname(mddev));
+ pr_debug("raid5: run(%s) called.\n", mdname(mddev));
ITERATE_RDEV(mddev,rdev,tmp) {
raid_disk = rdev->raid_disk;
@@ -3690,7 +4323,7 @@ static int stop(mddev_t *mddev)
return 0;
}
-#if RAID5_DEBUG
+#ifdef DEBUG
static void print_sh (struct seq_file *seq, struct stripe_head *sh)
{
int i;
@@ -3737,7 +4370,7 @@ static void status (struct seq_file *seq, mddev_t *mddev)
conf->disks[i].rdev &&
test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
seq_printf (seq, "]");
-#if RAID5_DEBUG
+#ifdef DEBUG
seq_printf (seq, "\n");
printall(seq, conf);
#endif
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index c120114c241..5c63c8e24ee 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -4,5 +4,6 @@ config VIDEO_SAA7146
config VIDEO_SAA7146_VV
tristate
+ depends on VIDEO_DEV
select VIDEO_BUF
select VIDEO_SAA7146
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index efd2b746815..03ef88acd9b 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -11,7 +11,7 @@ menuconfig DVB_CAPTURE_DRIVERS
---help---
Say Y to select Digital TV adapters
-if DVB_CAPTURE_DRIVERS
+if DVB_CAPTURE_DRIVERS && DVB_CORE
comment "Supported SAA7146 based PCI Adapters"
depends on DVB_CORE && PCI && I2C
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index 1a1c3bca55f..bff00b58bf6 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -1,8 +1,11 @@
b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
- flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o \
- flexcop-dma.o
+ flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
+b2c2-flexcop-objs += flexcop-dma.o
+endif
+
b2c2-flexcop-pci-objs = flexcop-pci.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 34d7abc900d..b40af48a2ed 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -118,6 +118,7 @@ struct cinergyt2 {
struct dvb_demux demux;
struct usb_device *udev;
struct mutex sem;
+ struct mutex wq_sem;
struct dvb_adapter adapter;
struct dvb_device *fedev;
struct dmxdev dmxdev;
@@ -482,14 +483,14 @@ static int cinergyt2_open (struct inode *inode, struct file *file)
struct cinergyt2 *cinergyt2 = dvbdev->priv;
int err = -ERESTARTSYS;
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
+ if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
+ goto out;
- if ((err = dvb_generic_open(inode, file))) {
- mutex_unlock(&cinergyt2->sem);
- return err;
- }
+ if (mutex_lock_interruptible(&cinergyt2->sem))
+ goto out_unlock1;
+ if ((err = dvb_generic_open(inode, file)))
+ goto out_unlock2;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
cinergyt2_sleep(cinergyt2, 0);
@@ -498,8 +499,12 @@ static int cinergyt2_open (struct inode *inode, struct file *file)
atomic_inc(&cinergyt2->inuse);
+out_unlock2:
mutex_unlock(&cinergyt2->sem);
- return 0;
+out_unlock1:
+ mutex_unlock(&cinergyt2->wq_sem);
+out:
+ return err;
}
static void cinergyt2_unregister(struct cinergyt2 *cinergyt2)
@@ -519,16 +524,17 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv;
- if (mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
+ mutex_lock(&cinergyt2->wq_sem);
if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
- cancel_delayed_work(&cinergyt2->query_work);
- flush_scheduled_work();
+ cancel_rearming_delayed_work(&cinergyt2->query_work);
+
+ mutex_lock(&cinergyt2->sem);
cinergyt2_sleep(cinergyt2, 1);
+ mutex_unlock(&cinergyt2->sem);
}
- mutex_unlock(&cinergyt2->sem);
+ mutex_unlock(&cinergyt2->wq_sem);
if (atomic_dec_and_test(&cinergyt2->inuse) && cinergyt2->disconnect_pending) {
warn("delayed unregister in release");
@@ -839,13 +845,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
static void cinergyt2_unregister_rc(struct cinergyt2 *cinergyt2)
{
- cancel_delayed_work(&cinergyt2->rc_query_work);
+ cancel_rearming_delayed_work(&cinergyt2->rc_query_work);
input_unregister_device(cinergyt2->rc_input_dev);
}
static inline void cinergyt2_suspend_rc(struct cinergyt2 *cinergyt2)
{
- cancel_delayed_work(&cinergyt2->rc_query_work);
+ cancel_rearming_delayed_work(&cinergyt2->rc_query_work);
}
static inline void cinergyt2_resume_rc(struct cinergyt2 *cinergyt2)
@@ -908,6 +914,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
usb_set_intfdata (intf, (void *) cinergyt2);
mutex_init(&cinergyt2->sem);
+ mutex_init(&cinergyt2->wq_sem);
init_waitqueue_head (&cinergyt2->poll_wq);
INIT_DELAYED_WORK(&cinergyt2->query_work, cinergyt2_query);
@@ -975,11 +982,8 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- flush_scheduled_work();
-
cinergyt2_unregister_rc(cinergyt2);
-
- cancel_delayed_work(&cinergyt2->query_work);
+ cancel_rearming_delayed_work(&cinergyt2->query_work);
wake_up_interruptible(&cinergyt2->poll_wq);
cinergyt2->demux.dmx.close(&cinergyt2->demux.dmx);
@@ -993,21 +997,21 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
+ if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
return -ERESTARTSYS;
if (1) {
- struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
-
cinergyt2_suspend_rc(cinergyt2);
- cancel_delayed_work(&cinergyt2->query_work);
+ cancel_rearming_delayed_work(&cinergyt2->query_work);
+
+ mutex_lock(&cinergyt2->sem);
if (cinergyt2->streaming)
cinergyt2_stop_stream_xfer(cinergyt2);
- flush_scheduled_work();
cinergyt2_sleep(cinergyt2, 1);
+ mutex_unlock(&cinergyt2->sem);
}
- mutex_unlock(&cinergyt2->sem);
+ mutex_unlock(&cinergyt2->wq_sem);
return 0;
}
@@ -1015,9 +1019,15 @@ static int cinergyt2_resume (struct usb_interface *intf)
{
struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
struct dvbt_set_parameters_msg *param = &cinergyt2->param;
+ int err = -ERESTARTSYS;
- if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
- return -ERESTARTSYS;
+ if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->wq_sem))
+ goto out;
+
+ if (mutex_lock_interruptible(&cinergyt2->sem))
+ goto out_unlock1;
+
+ err = 0;
if (!cinergyt2->sleeping) {
cinergyt2_sleep(cinergyt2, 0);
@@ -1030,7 +1040,10 @@ static int cinergyt2_resume (struct usb_interface *intf)
cinergyt2_resume_rc(cinergyt2);
mutex_unlock(&cinergyt2->sem);
- return 0;
+out_unlock1:
+ mutex_unlock(&cinergyt2->wq_sem);
+out:
+ return err;
}
static const struct usb_device_id cinergyt2_table [] __devinitdata = {
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
index ccc429cbbad..0f2d4b41556 100644
--- a/drivers/media/dvb/frontends/tda10086.c
+++ b/drivers/media/dvb/frontends/tda10086.c
@@ -41,6 +41,7 @@ struct tda10086_state {
/* private demod data */
u32 frequency;
u32 symbol_rate;
+ bool has_lock;
};
static int debug = 0;
@@ -116,7 +117,7 @@ static int tda10086_init(struct dvb_frontend* fe)
// misc setup
tda10086_write_byte(state, 0x01, 0x94);
tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
- tda10086_write_byte(state, 0x03, 0x64);
+ tda10086_write_byte(state, 0x03, 0xe4);
tda10086_write_byte(state, 0x04, 0x43);
tda10086_write_byte(state, 0x0c, 0x0c);
tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
@@ -146,7 +147,7 @@ static int tda10086_init(struct dvb_frontend* fe)
// setup AGC
tda10086_write_byte(state, 0x05, 0x0B);
tda10086_write_byte(state, 0x37, 0x63);
- tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it
+ tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
tda10086_write_byte(state, 0x40, 0x64);
tda10086_write_byte(state, 0x41, 0x4f);
tda10086_write_byte(state, 0x42, 0x43);
@@ -398,6 +399,10 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
dprintk ("%s\n", __FUNCTION__);
+ // modify parameters for tuning
+ tda10086_write_byte(state, 0x02, 0x35);
+ state->has_lock = false;
+
// set params
if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, fe_params);
@@ -542,8 +547,14 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
*fe_status |= FE_HAS_VITERBI;
if (val & 0x08)
*fe_status |= FE_HAS_SYNC;
- if (val & 0x10)
+ if (val & 0x10) {
*fe_status |= FE_HAS_LOCK;
+ if (!state->has_lock) {
+ state->has_lock = true;
+ // modify parameters for stable reception
+ tda10086_write_byte(state, 0x02, 0x00);
+ }
+ }
return 0;
}
@@ -555,7 +566,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
dprintk ("%s\n", __FUNCTION__);
- _str = tda10086_read_byte(state, 0x43);
+ _str = 0xff - tda10086_read_byte(state, 0x43);
*signal = (_str << 8) | _str;
return 0;
@@ -568,7 +579,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
dprintk ("%s\n", __FUNCTION__);
- _snr = tda10086_read_byte(state, 0x1c);
+ _snr = 0xff - tda10086_read_byte(state, 0x1c);
*snr = (_snr << 8) | _snr;
return 0;
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
index 79f971dc52b..bd3ebc28483 100644
--- a/drivers/media/dvb/frontends/tda826x.c
+++ b/drivers/media/dvb/frontends/tda826x.c
@@ -89,8 +89,8 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
buf[3] = div >> 7;
buf[4] = div << 1;
- buf[5] = 0xff; // basedband filter to max
- buf[6] = 0xfe; // gains at max + no RF attenuation
+ buf[5] = 0x77; // baseband cut-off 19 MHz
+ buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
buf[7] = 0x83; // charge pumps at high, tests off
buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 2557ac9620d..b611f2b1f8b 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -529,7 +529,7 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
if (bi->type != BUDGET_FS_ACTIVY)
saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
- if (budget_register(budget) == 0)
+ if ((ret = budget_register(budget)) == 0)
return 0; /* Everything OK */
/* An error occurred, cleanup resources */
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index a6ac82a609d..194b102140e 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -9,7 +9,7 @@ menuconfig RADIO_ADAPTERS
---help---
Say Y here to enable selecting AM/FM radio adapters.
-if RADIO_ADAPTERS
+if RADIO_ADAPTERS && VIDEO_DEV
config RADIO_CADET
tristate "ADS Cadet AM/FM Tuner"
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index fdf5d6e46ea..5e6f17df204 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -94,7 +94,6 @@ struct gemtek_pci_card {
u32 iobase;
u32 length;
- u8 chiprev;
u16 model;
u32 current_frequency;
@@ -415,7 +414,6 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
goto err_pci;
}
- pci_read_config_byte( pci_dev, PCI_REVISION_ID, &card->chiprev );
pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model );
pci_set_drvdata( pci_dev, card );
@@ -436,7 +434,7 @@ static int __devinit gemtek_pci_probe( struct pci_dev *pci_dev, const struct pci
gemtek_pci_mute( card );
printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
- card->chiprev, card->iobase, card->iobase + card->length - 1 );
+ pci_dev->revision, card->iobase, card->iobase + card->length - 1 );
return 0;
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 5cb3f54b548..4d45a40016d 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -11,7 +11,7 @@ menuconfig VIDEO_CAPTURE_DRIVERS
webcams, analog TV, and hybrid analog/digital TV.
Some of those devices also supports FM radio.
-if VIDEO_CAPTURE_DRIVERS
+if VIDEO_CAPTURE_DRIVERS && VIDEO_DEV
config VIDEO_ADV_DEBUG
bool "Enable advanced debug functionality"
@@ -691,7 +691,7 @@ menuconfig V4L_USB_DRIVERS
depends on USB
default y
-if V4L_USB_DRIVERS
+if V4L_USB_DRIVERS && USB
source "drivers/media/video/pvrusb2/Kconfig"
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
index 1c38723d316..b1fedb0f643 100644
--- a/drivers/media/video/bt8xx/bttv-driver.c
+++ b/drivers/media/video/bt8xx/bttv-driver.c
@@ -1331,7 +1331,7 @@ set_tvnorm(struct bttv *btv, unsigned int norm)
/* Call with btv->lock down. */
static void
-set_input(struct bttv *btv, unsigned int input)
+set_input(struct bttv *btv, unsigned int input, unsigned int norm)
{
unsigned long flags;
@@ -1350,7 +1350,7 @@ set_input(struct bttv *btv, unsigned int input)
}
audio_input(btv,(input == bttv_tvcards[btv->c.type].tuner ?
TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN));
- set_tvnorm(btv,btv->tvnorm);
+ set_tvnorm(btv, norm);
i2c_vidiocschan(btv);
}
@@ -1441,7 +1441,7 @@ static void bttv_reinit_bt848(struct bttv *btv)
init_bt848(btv);
btv->pll.pll_current = -1;
- set_input(btv,btv->input);
+ set_input(btv, btv->input, btv->tvnorm);
}
static int get_control(struct bttv *btv, struct v4l2_control *c)
@@ -2011,8 +2011,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
return 0;
}
- btv->tvnorm = v->norm;
- set_input(btv,v->channel);
+ set_input(btv, v->channel, v->norm);
mutex_unlock(&btv->lock);
return 0;
}
@@ -2148,7 +2147,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg)
if (*i > bttv_tvcards[btv->c.type].video_inputs)
return -EINVAL;
mutex_lock(&btv->lock);
- set_input(btv,*i);
+ set_input(btv, *i, btv->tvnorm);
mutex_unlock(&btv->lock);
return 0;
}
@@ -4780,7 +4779,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
bt848_hue(btv,32768);
bt848_sat(btv,32768);
audio_mute(btv, 1);
- set_input(btv,0);
+ set_input(btv, 0, btv->tvnorm);
bttv_crop_reset(&btv->crop[0], btv->tvnorm);
btv->crop[1] = btv->crop[0]; /* current = default */
disclaim_vbi_lines(btv);
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index b0466b88f52..a80b1cb1abe 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1034,6 +1034,8 @@ static int vidioc_g_tuner (struct file *file, void *priv,
if (unlikely(UNSET == core->tuner_type))
return -EINVAL;
+ if (0 != t->index)
+ return -EINVAL;
strcpy(t->name, "Television");
t->type = V4L2_TUNER_ANALOG_TV;
diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h
index 15012f88b80..91e9e90c14a 100644
--- a/drivers/media/video/ivtv/ivtv-cards.h
+++ b/drivers/media/video/ivtv/ivtv-cards.h
@@ -86,7 +86,7 @@
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
V4L2_CAP_SLICED_VBI_CAPTURE)
#define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \
- V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_POS)
+ V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
struct ivtv_card_video_input {
u8 video_type; /* video input type */
diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c
index e29f949adf5..efc66355339 100644
--- a/drivers/media/video/ivtv/ivtv-driver.c
+++ b/drivers/media/video/ivtv/ivtv-driver.c
@@ -652,6 +652,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
itv->dma_timer.data = (unsigned long)itv;
itv->cur_dma_stream = -1;
+ itv->cur_pio_stream = -1;
itv->audio_stereo_mode = AUDIO_STEREO;
itv->audio_bilingual_mode = AUDIO_MONO_LEFT;
diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h
index 552f04511ea..e6e56f175f3 100644
--- a/drivers/media/video/ivtv/ivtv-driver.h
+++ b/drivers/media/video/ivtv/ivtv-driver.h
@@ -237,6 +237,7 @@ extern const u32 yuv_offset[4];
#define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29)
#define IVTV_IRQ_ENC_VIM_RST (0x1 << 28)
#define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27)
+#define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25)
#define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24)
#define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22)
#define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20)
@@ -247,7 +248,8 @@ extern const u32 yuv_offset[4];
#define IVTV_IRQ_DEC_VSYNC (0x1 << 10)
/* IRQ Masks */
-#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|IVTV_IRQ_DMA_READ)
+#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\
+ IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE)
#define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS)
#define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG)
@@ -374,6 +376,9 @@ struct ivtv_mailbox_data {
#define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */
#define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */
+#define IVTV_F_S_PIO_PENDING 9 /* this stream has pending PIO */
+#define IVTV_F_S_PIO_HAS_VBI 1 /* the current PIO request also requests VBI data */
+
/* per-ivtv, i_flags */
#define IVTV_F_I_DMA 0 /* DMA in progress */
#define IVTV_F_I_UDMA 1 /* UDMA in progress */
@@ -390,8 +395,11 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */
#define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */
#define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */
-#define IVTV_F_I_WORK_HANDLER_VBI 15 /* there is work to be done for VBI */
-#define IVTV_F_I_WORK_HANDLER_YUV 16 /* there is work to be done for YUV */
+#define IVTV_F_I_HAVE_WORK 15 /* Used in the interrupt handler: there is work to be done */
+#define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */
+#define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */
+#define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */
+#define IVTV_F_I_PIO 19 /* PIO in progress */
/* Event notifications */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
@@ -484,6 +492,7 @@ struct ivtv_stream {
/* Base Dev SG Array for cx23415/6 */
struct ivtv_SG_element *SGarray;
+ struct ivtv_SG_element *PIOarray;
dma_addr_t SG_handle;
int SG_length;
@@ -706,6 +715,7 @@ struct ivtv {
atomic_t decoding; /* count number of active decoding streams */
u32 irq_rr_idx; /* Round-robin stream index */
int cur_dma_stream; /* index of stream doing DMA */
+ int cur_pio_stream; /* index of stream doing PIO */
u32 dma_data_req_offset;
u32 dma_data_req_size;
int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c
index 8976487a65f..555d5e6369c 100644
--- a/drivers/media/video/ivtv/ivtv-fileops.c
+++ b/drivers/media/video/ivtv/ivtv-fileops.c
@@ -32,6 +32,8 @@
#include "ivtv-yuv.h"
#include "ivtv-controls.h"
#include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include <media/saa7115.h>
/* This function tries to claim the stream for a specific file descriptor.
If no one else is using this stream then the stream is claimed and
@@ -786,6 +788,13 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
/* Select correct audio input (i.e. TV tuner or Line in) */
ivtv_audio_set_io(itv);
+ if (itv->hw_flags & IVTV_HW_SAA711X)
+ {
+ struct v4l2_crystal_freq crystal_freq;
+ crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
+ crystal_freq.flags = 0;
+ ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
+ }
/* Done! Unmute and continue. */
ivtv_unmute(itv);
ivtv_release_stream(s);
@@ -872,6 +881,13 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
/* Select the correct audio input (i.e. radio tuner) */
ivtv_audio_set_io(itv);
+ if (itv->hw_flags & IVTV_HW_SAA711X)
+ {
+ struct v4l2_crystal_freq crystal_freq;
+ crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
+ crystal_freq.flags = SAA7115_FREQ_FL_APLL;
+ ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
+ }
/* Done! Unmute and continue. */
ivtv_unmute(itv);
}
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 1989ec1cb97..57af1762de1 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -532,11 +532,6 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
itv->yuv_info.yuv_forced_update = 1;
return 0;
}
- if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
- r.width, r.height, r.left, r.top))
- itv->main_rect = r;
- else
- return -EINVAL;
}
return 0;
}
@@ -799,9 +794,39 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
return ivtv_get_fmt(itv, id->type, fmt);
}
+ case VIDIOC_CROPCAP: {
+ struct v4l2_cropcap *cropcap = arg;
+
+ if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return -EINVAL;
+ cropcap->bounds.top = cropcap->bounds.left = 0;
+ cropcap->bounds.width = 720;
+ if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ cropcap->bounds.height = itv->is_50hz ? 576 : 480;
+ cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
+ cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
+ } else {
+ cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
+ cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
+ cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
+ }
+ cropcap->defrect = cropcap->bounds;
+ return 0;
+ }
+
case VIDIOC_S_CROP: {
struct v4l2_crop *crop = arg;
+ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+ crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
+ itv->main_rect = crop->c;
+ return 0;
+ }
+ return -EINVAL;
+ }
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
@@ -810,6 +835,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_G_CROP: {
struct v4l2_crop *crop = arg;
+ if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+ crop->c = itv->main_rect;
+ return 0;
+ }
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
@@ -977,7 +1007,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
if (itv->hw_flags & IVTV_HW_CX25840) {
itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
}
- IVTV_DEBUG_INFO("Switching standard to %llx.\n", itv->std);
+ IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
/* Tuner */
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
@@ -1207,7 +1237,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
(s->buffers - s->q_free.buffers) * 100 / s->buffers,
(s->buffers * s->buf_size) / 1024, s->buffers);
}
- IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", itv->mpg_data_received, itv->vbi_data_inserted);
+ IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
break;
}
@@ -1455,6 +1485,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT:
case VIDIOC_ENUM_FMT:
+ case VIDIOC_CROPCAP:
case VIDIOC_G_CROP:
case VIDIOC_S_CROP:
case VIDIOC_G_FREQUENCY:
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index c3a047b381b..ba98bf054f2 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -31,8 +31,6 @@
#define DMA_MAGIC_COOKIE 0x000001fe
-#define SLICED_VBI_PIO 1
-
static void ivtv_dma_dec_start(struct ivtv_stream *s);
static const int ivtv_stream_map[] = {
@@ -42,12 +40,40 @@ static const int ivtv_stream_map[] = {
IVTV_ENC_STREAM_TYPE_VBI,
};
-static inline int ivtv_use_pio(struct ivtv_stream *s)
+
+static void ivtv_pio_work_handler(struct ivtv *itv)
{
- struct ivtv *itv = s->itv;
+ struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
+ struct ivtv_buffer *buf;
+ struct list_head *p;
+ int i = 0;
+
+ IVTV_DEBUG_DMA("ivtv_pio_work_handler\n");
+ if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
+ s->v4l2dev == NULL || !ivtv_use_pio(s)) {
+ itv->cur_pio_stream = -1;
+ /* trigger PIO complete user interrupt */
+ write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
+ return;
+ }
+ IVTV_DEBUG_DMA("Process PIO %s\n", s->name);
+ buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list);
+ list_for_each(p, &s->q_dma.list) {
+ struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
+ u32 size = s->PIOarray[i].size & 0x3ffff;
- return s->dma == PCI_DMA_NONE ||
- (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
+ /* Copy the data from the card to the buffer */
+ if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+ memcpy_fromio(buf->buf, itv->dec_mem + s->PIOarray[i].src - IVTV_DECODER_OFFSET, size);
+ }
+ else {
+ memcpy_fromio(buf->buf, itv->enc_mem + s->PIOarray[i].src, size);
+ }
+ if (s->PIOarray[i].size & 0x80000000)
+ break;
+ i++;
+ }
+ write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
}
void ivtv_irq_work_handler(struct work_struct *work)
@@ -56,8 +82,11 @@ void ivtv_irq_work_handler(struct work_struct *work)
DEFINE_WAIT(wait);
+ if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
+ ivtv_pio_work_handler(itv);
+
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags))
- vbi_work_handler(itv);
+ ivtv_vbi_work_handler(itv);
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
ivtv_yuv_work_handler(itv);
@@ -173,8 +202,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
}
s->buffers_stolen = rc;
- /* got the buffers, now fill in SGarray (DMA) or copy the data from the card
- to the buffers (PIO). */
+ /* got the buffers, now fill in SGarray (DMA) */
buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
memset(buf->buf, 0, 128);
list_for_each(p, &s->q_predma.list) {
@@ -182,21 +210,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
if (skip_bufs-- > 0)
continue;
- if (!ivtv_use_pio(s)) {
- s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
- s->SGarray[idx].src = cpu_to_le32(offset);
- s->SGarray[idx].size = cpu_to_le32(s->buf_size);
- }
+ s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
+ s->SGarray[idx].src = cpu_to_le32(offset);
+ s->SGarray[idx].size = cpu_to_le32(s->buf_size);
buf->bytesused = (size < s->buf_size) ? size : s->buf_size;
- /* If PIO, then copy the data from the card to the buffer */
- if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
- memcpy_fromio(buf->buf, itv->dec_mem + offset - IVTV_DECODER_OFFSET, buf->bytesused);
- }
- else if (ivtv_use_pio(s)) {
- memcpy_fromio(buf->buf, itv->enc_mem + offset, buf->bytesused);
- }
-
s->q_predma.bytesused += buf->bytesused;
size -= buf->bytesused;
offset += s->buf_size;
@@ -224,11 +242,6 @@ static void dma_post(struct ivtv_stream *s)
u32 *u32buf;
int x = 0;
- if (ivtv_use_pio(s)) {
- if (s->q_predma.bytesused)
- ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
- s->SG_length = 0;
- }
IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
s->name, s->dma_offset);
list_for_each(p, &s->q_dma.list) {
@@ -278,10 +291,14 @@ static void dma_post(struct ivtv_stream *s)
if (buf)
buf->bytesused += s->dma_last_offset;
if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) {
- /* Parse and Groom VBI Data */
- s->q_dma.bytesused -= buf->bytesused;
- ivtv_process_vbi_data(itv, buf, 0, s->type);
- s->q_dma.bytesused += buf->bytesused;
+ list_for_each(p, &s->q_dma.list) {
+ buf = list_entry(p, struct ivtv_buffer, list);
+
+ /* Parse and Groom VBI Data */
+ s->q_dma.bytesused -= buf->bytesused;
+ ivtv_process_vbi_data(itv, buf, 0, s->type);
+ s->q_dma.bytesused += buf->bytesused;
+ }
if (s->id == -1) {
ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
return;
@@ -351,10 +368,14 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
int i;
+ IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
+
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
- IVTV_DEBUG_DMA("start DMA for %s\n", s->name);
- s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
+
+ if (ivtv_use_dma(s))
+ s->SGarray[s->SG_length - 1].size =
+ cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
/* If this is an MPEG stream, and VBI data is also pending, then append the
VBI DMA to the MPEG DMA and transfer both sets of data at once.
@@ -368,7 +389,8 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length &&
s->SG_length + s_vbi->SG_length <= s->buffers) {
ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
- s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
+ if (ivtv_use_dma(s_vbi))
+ s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
for (i = 0; i < s_vbi->SG_length; i++) {
s->SGarray[s->SG_length++] = s_vbi->SGarray[i];
}
@@ -381,14 +403,26 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
/* Mark last buffer size for Interrupt flag */
s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
- /* Sync Hardware SG List of buffers */
- ivtv_stream_sync_for_device(s);
- write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
- write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
- set_bit(IVTV_F_I_DMA, &itv->i_flags);
- itv->cur_dma_stream = s->type;
- itv->dma_timer.expires = jiffies + HZ / 10;
- add_timer(&itv->dma_timer);
+ if (ivtv_use_pio(s)) {
+ for (i = 0; i < s->SG_length; i++) {
+ s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src);
+ s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size);
+ }
+ set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags);
+ set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+ set_bit(IVTV_F_I_PIO, &itv->i_flags);
+ itv->cur_pio_stream = s->type;
+ }
+ else {
+ /* Sync Hardware SG List of buffers */
+ ivtv_stream_sync_for_device(s);
+ write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
+ write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
+ set_bit(IVTV_F_I_DMA, &itv->i_flags);
+ itv->cur_dma_stream = s->type;
+ itv->dma_timer.expires = jiffies + HZ / 10;
+ add_timer(&itv->dma_timer);
+ }
}
static void ivtv_dma_dec_start(struct ivtv_stream *s)
@@ -489,6 +523,40 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
wake_up(&itv->dma_waitq);
}
+static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
+{
+ struct ivtv_stream *s;
+
+ if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) {
+ itv->cur_pio_stream = -1;
+ return;
+ }
+ s = &itv->streams[itv->cur_pio_stream];
+ IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name);
+ s->SG_length = 0;
+ clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
+ clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+ itv->cur_pio_stream = -1;
+ dma_post(s);
+ if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+ ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0);
+ else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
+ ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1);
+ else if (s->type == IVTV_ENC_STREAM_TYPE_PCM)
+ ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2);
+ clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+ if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
+ u32 tmp;
+
+ s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+ tmp = s->dma_offset;
+ s->dma_offset = itv->vbi.dma_offset;
+ dma_post(s);
+ s->dma_offset = tmp;
+ }
+ wake_up(&itv->dma_waitq);
+}
+
static void ivtv_irq_dma_err(struct ivtv *itv)
{
u32 data[CX2341X_MBOX_MAX_DATA];
@@ -532,13 +600,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv)
clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
s = &itv->streams[ivtv_stream_map[data[0]]];
if (!stream_enc_dma_append(s, data)) {
- if (ivtv_use_pio(s)) {
- dma_post(s);
- ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[0]);
- }
- else {
- set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
- }
+ set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
}
}
@@ -551,15 +613,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
IVTV_DEBUG_IRQ("ENC START VBI CAP\n");
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
- if (ivtv_use_pio(s)) {
- if (stream_enc_dma_append(s, data))
- return;
- if (s->q_predma.bytesused)
- ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
- s->SG_length = 0;
- dma_post(s);
- return;
- }
/* If more than two VBI buffers are pending, then
clear the old ones and start with this new one.
This can happen during transition stages when MPEG capturing is
@@ -582,11 +635,11 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
if (!stream_enc_dma_append(s, data) &&
!test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) {
set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
- set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
+ set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
}
}
-static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv)
+static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
{
u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
@@ -594,7 +647,7 @@ static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv)
IVTV_DEBUG_IRQ("DEC VBI REINSERT\n");
if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) &&
!stream_enc_dma_append(s, data)) {
- dma_post(s);
+ set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags);
}
}
@@ -657,7 +710,6 @@ static void ivtv_irq_vsync(struct ivtv *itv)
}
if (frame != (itv->lastVsyncFrame & 1)) {
struct ivtv_stream *s = ivtv_get_output_stream(itv);
- int work = 0;
itv->lastVsyncFrame += 1;
if (frame == 0) {
@@ -678,7 +730,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
/* Send VBI to saa7127 */
if (frame) {
set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
- work = 1;
+ set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
}
/* Check if we need to update the yuv registers */
@@ -691,11 +743,9 @@ static void ivtv_irq_vsync(struct ivtv *itv)
itv->yuv_info.new_frame_info[last_dma_frame].update = 0;
itv->yuv_info.yuv_forced_update = 0;
set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
- work = 1;
+ set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
}
}
- if (work)
- queue_work(itv->irq_work_queues, &itv->irq_work_queue);
}
}
@@ -755,6 +805,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
ivtv_irq_enc_dma_complete(itv);
}
+ if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) {
+ ivtv_irq_enc_pio_complete(itv);
+ }
+
if (combo & IVTV_IRQ_DMA_ERR) {
ivtv_irq_dma_err(itv);
}
@@ -768,7 +822,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
}
if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) {
- ivtv_irq_dev_vbi_reinsert(itv);
+ ivtv_irq_dec_vbi_reinsert(itv);
}
if (combo & IVTV_IRQ_ENC_EOS) {
@@ -813,6 +867,22 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
}
}
+ if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) {
+ for (i = 0; i < IVTV_MAX_STREAMS; i++) {
+ int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS;
+ struct ivtv_stream *s = &itv->streams[idx];
+
+ if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags))
+ continue;
+ if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG)
+ ivtv_dma_enc_start(s);
+ break;
+ }
+ }
+
+ if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags))
+ queue_work(itv->irq_work_queues, &itv->irq_work_queue);
+
spin_unlock(&itv->dma_reg_lock);
/* If we've just handled a 'forced' vsync, it's safest to say it
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c
index ccfcef1ad91..a04f9387f63 100644
--- a/drivers/media/video/ivtv/ivtv-queue.c
+++ b/drivers/media/video/ivtv/ivtv-queue.c
@@ -195,14 +195,26 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
s->dma != PCI_DMA_NONE ? "DMA " : "",
s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
- /* Allocate DMA SG Arrays */
- if (s->dma != PCI_DMA_NONE) {
- s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
- if (s->SGarray == NULL) {
- IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
+ if (ivtv_might_use_pio(s)) {
+ s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
+ if (s->PIOarray == NULL) {
+ IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name);
return -ENOMEM;
}
- s->SG_length = 0;
+ }
+
+ /* Allocate DMA SG Arrays */
+ s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
+ if (s->SGarray == NULL) {
+ IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
+ if (ivtv_might_use_pio(s)) {
+ kfree(s->PIOarray);
+ s->PIOarray = NULL;
+ }
+ return -ENOMEM;
+ }
+ s->SG_length = 0;
+ if (ivtv_might_use_dma(s)) {
s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma);
ivtv_stream_sync_for_cpu(s);
}
@@ -219,7 +231,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
break;
}
INIT_LIST_HEAD(&buf->list);
- if (s->dma != PCI_DMA_NONE) {
+ if (ivtv_might_use_dma(s)) {
buf->dma_handle = pci_map_single(s->itv->dev,
buf->buf, s->buf_size + 256, s->dma);
ivtv_buf_sync_for_cpu(s, buf);
@@ -242,7 +254,7 @@ void ivtv_stream_free(struct ivtv_stream *s)
/* empty q_free */
while ((buf = ivtv_dequeue(s, &s->q_free))) {
- if (s->dma != PCI_DMA_NONE)
+ if (ivtv_might_use_dma(s))
pci_unmap_single(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma);
kfree(buf->buf);
@@ -256,6 +268,9 @@ void ivtv_stream_free(struct ivtv_stream *s)
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
s->SG_handle = IVTV_DMA_UNMAPPED;
}
+ kfree(s->SGarray);
+ kfree(s->PIOarray);
+ s->PIOarray = NULL;
s->SGarray = NULL;
s->SG_length = 0;
}
diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h
index 903edd4b438..2ed8d548255 100644
--- a/drivers/media/video/ivtv/ivtv-queue.h
+++ b/drivers/media/video/ivtv/ivtv-queue.h
@@ -20,18 +20,43 @@
*/
#define IVTV_DMA_UNMAPPED ((u32) -1)
+#define SLICED_VBI_PIO 1
/* ivtv_buffer utility functions */
+
+static inline int ivtv_might_use_pio(struct ivtv_stream *s)
+{
+ return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI);
+}
+
+static inline int ivtv_use_pio(struct ivtv_stream *s)
+{
+ struct ivtv *itv = s->itv;
+
+ return s->dma == PCI_DMA_NONE ||
+ (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
+}
+
+static inline int ivtv_might_use_dma(struct ivtv_stream *s)
+{
+ return s->dma != PCI_DMA_NONE;
+}
+
+static inline int ivtv_use_dma(struct ivtv_stream *s)
+{
+ return !ivtv_use_pio(s);
+}
+
static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf)
{
- if (s->dma != PCI_DMA_NONE)
+ if (ivtv_use_dma(s))
pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma);
}
static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf)
{
- if (s->dma != PCI_DMA_NONE)
+ if (ivtv_use_dma(s))
pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma);
}
@@ -53,12 +78,14 @@ void ivtv_stream_free(struct ivtv_stream *s);
static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s)
{
- pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle,
- sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
+ if (ivtv_use_dma(s))
+ pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle,
+ sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
}
static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s)
{
- pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle,
- sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
+ if (ivtv_use_dma(s))
+ pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle,
+ sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
}
diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c
index 01a41a844a3..6af88ae9295 100644
--- a/drivers/media/video/ivtv/ivtv-streams.c
+++ b/drivers/media/video/ivtv/ivtv-streams.c
@@ -868,7 +868,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
return 0;
- IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", pts, flags);
+ IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
/* Stop Decoder */
if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) {
diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c
index 5efa5a86781..3ba46e07ea1 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.c
+++ b/drivers/media/video/ivtv/ivtv-vbi.c
@@ -450,7 +450,7 @@ void ivtv_disable_vbi(struct ivtv *itv)
}
-void vbi_work_handler(struct ivtv *itv)
+void ivtv_vbi_work_handler(struct ivtv *itv)
{
struct v4l2_sliced_vbi_data data;
diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h
index cdaea697b3e..ec211b49702 100644
--- a/drivers/media/video/ivtv/ivtv-vbi.h
+++ b/drivers/media/video/ivtv/ivtv-vbi.h
@@ -23,4 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
int ivtv_used_line(struct ivtv *itv, int line, int field);
void ivtv_disable_vbi(struct ivtv *itv);
void ivtv_set_vbi(unsigned long arg);
-void vbi_work_handler(struct ivtv *itv);
+void ivtv_vbi_work_handler(struct ivtv *itv);
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 664aba8b4d8..7533fc20331 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -1809,7 +1809,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
{
int ret = -EBUSY;
unsigned long mchip_adr;
- u8 revision;
if (meye.mchip_dev != NULL) {
printk(KERN_ERR "meye: only one device allowed!\n");
@@ -1885,7 +1884,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
goto outreqirq;
}
- pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision);
pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);
pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);
@@ -1939,7 +1937,7 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n",
MEYE_DRIVER_VERSION);
printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n",
- revision, mchip_adr, meye.mchip_irq);
+ meye.mchip_dev->revision, mchip_adr, meye.mchip_irq);
return 0;
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 74839f98b7c..c1a392e4717 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -75,10 +75,6 @@ struct saa7111 {
int norm;
int input;
int enable;
- int bright;
- int contrast;
- int hue;
- int sat;
};
#define I2C_SAA7111 0x48
@@ -96,6 +92,17 @@ saa7111_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value);
}
+static inline void
+saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
+{
+ struct saa7111 *decoder = i2c_get_clientdata(client);
+
+ if (decoder->reg[reg] != value) {
+ decoder->reg[reg] = value;
+ i2c_smbus_write_byte_data(client, reg, value);
+ }
+}
+
static int
saa7111_write_block (struct i2c_client *client,
const u8 *data,
@@ -439,28 +446,14 @@ saa7111_command (struct i2c_client *client,
{
struct video_picture *pic = arg;
- if (decoder->bright != pic->brightness) {
- /* We want 0 to 255 we get 0-65535 */
- decoder->bright = pic->brightness;
- saa7111_write(client, 0x0a, decoder->bright >> 8);
- }
- if (decoder->contrast != pic->contrast) {
- /* We want 0 to 127 we get 0-65535 */
- decoder->contrast = pic->contrast;
- saa7111_write(client, 0x0b,
- decoder->contrast >> 9);
- }
- if (decoder->sat != pic->colour) {
- /* We want 0 to 127 we get 0-65535 */
- decoder->sat = pic->colour;
- saa7111_write(client, 0x0c, decoder->sat >> 9);
- }
- if (decoder->hue != pic->hue) {
- /* We want -128 to 127 we get 0-65535 */
- decoder->hue = pic->hue;
- saa7111_write(client, 0x0d,
- (decoder->hue - 32768) >> 8);
- }
+ /* We want 0 to 255 we get 0-65535 */
+ saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8);
+ /* We want 0 to 127 we get 0-65535 */
+ saa7111_write(client, 0x0b, pic->contrast >> 9);
+ /* We want 0 to 127 we get 0-65535 */
+ saa7111_write(client, 0x0c, pic->colour >> 9);
+ /* We want -128 to 127 we get 0-65535 */
+ saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
}
break;
@@ -524,10 +517,6 @@ saa7111_detect_client (struct i2c_adapter *adapter,
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
- decoder->bright = 32768;
- decoder->contrast = 32768;
- decoder->hue = 32768;
- decoder->sat = 32768;
i2c_set_clientdata(client, decoder);
i = i2c_attach_client(client);
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 7b56041186d..30395d6b5f1 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -1005,7 +1005,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
int saa7134_tvaudio_fini(struct saa7134_dev *dev)
{
/* shutdown tvaudio thread */
- if (dev->thread.pid >= 0) {
+ if (dev->thread.pid > 0) {
dev->thread.shutdown = 1;
wake_up_interruptible(&dev->thread.wq);
wait_for_completion(&dev->thread.exit);
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
index 9118a6227ea..7df071eb0a3 100644
--- a/drivers/media/video/usbvision/usbvision-core.c
+++ b/drivers/media/video/usbvision/usbvision-core.c
@@ -1414,6 +1414,11 @@ static void usbvision_isocIrq(struct urb *urb)
if (!USBVISION_IS_OPERATIONAL(usbvision))
return;
+ /* any urb with wrong status is ignored without acknowledgement */
+ if (urb->status == -ENOENT) {
+ return;
+ }
+
f = &usbvision->curFrame;
/* Manage streaming interruption */
@@ -1436,18 +1441,21 @@ static void usbvision_isocIrq(struct urb *urb)
if (usbvision->streaming == Stream_On) {
/* If we collected enough data let's parse! */
- if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */
- /*If we don't have a frame we're current working on, complain */
- if(!list_empty(&(usbvision->inqueue))) {
- if (!(*f)) {
- (*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame);
- }
- usbvision_parse_data(usbvision);
- }
- else {
- PDEBUG(DBG_IRQ, "received data, but no one needs it");
- scratch_reset(usbvision);
+ if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) &&
+ (!list_empty(&(usbvision->inqueue))) ) {
+ if (!(*f)) {
+ (*f) = list_entry(usbvision->inqueue.next,
+ struct usbvision_frame,
+ frame);
}
+ usbvision_parse_data(usbvision);
+ }
+ else {
+ /*If we don't have a frame
+ we're current working on, complain */
+ PDEBUG(DBG_IRQ,
+ "received data, but no one needs it");
+ scratch_reset(usbvision);
}
}
else {
@@ -1466,10 +1474,10 @@ static void usbvision_isocIrq(struct urb *urb)
urb->dev = usbvision->dev;
errCode = usb_submit_urb (urb, GFP_ATOMIC);
- /* Disable this warning. By design of the driver. */
- // if(errCode) {
- // err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode);
- // }
+ if(errCode) {
+ err("%s: usb_submit_urb failed: error %d",
+ __FUNCTION__, errCode);
+ }
return;
}
@@ -2394,7 +2402,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
{
struct usb_device *dev = usbvision->dev;
int bufIdx, errCode, regValue;
- const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+ int sb_size;
if (!USBVISION_IS_OPERATIONAL(usbvision))
return -EFAULT;
@@ -2408,11 +2416,14 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
usbvision->last_error = errCode;
return -EBUSY;
}
+ sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
- regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+ regValue = (16 - usbvision_read_reg(usbvision,
+ USBVISION_ALTER_REG)) & 0x0F;
usbvision->usb_bandwidth = regValue >> 1;
- PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+ PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
+ usbvision->usb_bandwidth);
@@ -2428,7 +2439,11 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
return -ENOMEM;
}
usbvision->sbuf[bufIdx].urb = urb;
- usbvision->sbuf[bufIdx].data = usb_buffer_alloc(usbvision->dev, sb_size, GFP_KERNEL,&urb->transfer_dma);
+ usbvision->sbuf[bufIdx].data =
+ usb_buffer_alloc(usbvision->dev,
+ sb_size,
+ GFP_KERNEL,
+ &urb->transfer_dma);
urb->dev = dev;
urb->context = usbvision;
urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
@@ -2442,21 +2457,26 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
k += usbvision->isocPacketSize) {
urb->iso_frame_desc[j].offset = k;
- urb->iso_frame_desc[j].length = usbvision->isocPacketSize;
+ urb->iso_frame_desc[j].length =
+ usbvision->isocPacketSize;
}
}
/* Submit all URBs */
for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
- errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL);
+ errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb,
+ GFP_KERNEL);
if (errCode) {
- err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode);
+ err("%s: usb_submit_urb(%d) failed: error %d",
+ __FUNCTION__, bufIdx, errCode);
}
}
usbvision->streaming = Stream_Idle;
- PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp);
+ PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
+ __FUNCTION__,
+ usbvision->video_endp);
return 0;
}
@@ -2470,7 +2490,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
void usbvision_stop_isoc(struct usb_usbvision *usbvision)
{
int bufIdx, errCode, regValue;
- const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE;
+ int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
return;
@@ -2499,15 +2519,19 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
errCode = usb_set_interface(usbvision->dev, usbvision->iface,
usbvision->ifaceAlt);
if (errCode < 0) {
- err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode);
+ err("%s: usb_set_interface() failed: error %d",
+ __FUNCTION__, errCode);
usbvision->last_error = errCode;
}
- regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
- usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1;
- PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize);
+ regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+ usbvision->isocPacketSize =
+ (regValue == 0) ? 0 : (regValue * 64) - 1;
+ PDEBUG(DBG_ISOC, "ISO Packet Length:%d",
+ usbvision->isocPacketSize);
usbvision->usb_bandwidth = regValue >> 1;
- PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth);
+ PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
+ usbvision->usb_bandwidth);
}
}
diff --git a/drivers/media/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
index bd6f6422ed5..c759d00d701 100644
--- a/drivers/media/video/usbvision/usbvision.h
+++ b/drivers/media/video/usbvision/usbvision.h
@@ -146,7 +146,6 @@
#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
#define USBVISION_URB_FRAMES 32
-#define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023
#define USBVISION_NUM_HEADERMARKER 20
#define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index e06f41c6fb1..6b3e0c00952 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -726,13 +726,15 @@ static int mptspi_slave_configure(struct scsi_device *sdev)
struct _MPT_SCSI_HOST *hd =
(struct _MPT_SCSI_HOST *)sdev->host->hostdata;
VirtTarget *vtarget = scsi_target(sdev)->hostdata;
- int ret = mptscsih_slave_configure(sdev);
+ int ret;
+
+ mptspi_initTarget(hd, vtarget, sdev);
+
+ ret = mptscsih_slave_configure(sdev);
if (ret)
return ret;
- mptspi_initTarget(hd, vtarget, sdev);
-
ddvprintk((MYIOC_s_INFO_FMT "id=%d min_period=0x%02x"
" max_offset=0x%02x max_width=%d\n", hd->ioc->name,
sdev->id, spi_min_period(scsi_target(sdev)),
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index b0b4458ae90..8135e4c3bf4 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -41,6 +41,9 @@ struct sm501_devdata {
struct resource *regs_claim;
struct sm501_platdata *platdata;
+ unsigned int in_suspend;
+ unsigned long pm_misc;
+
int unit_power[20];
unsigned int pdev_id;
unsigned int irq;
@@ -169,10 +172,41 @@ x "M %ld.%ld (%ld), MX1 %ld.%ld (%ld)\n",
fmt_freq(decode_div(pll2, pm1, 8, 1<<12, 15, misc_div)),
fmt_freq(decode_div(pll2, pm1, 0, 1<<4, 15, misc_div)));
}
-#else
-static void sm501_dump_clk(struct sm501_devdata *sm)
+
+static void sm501_dump_regs(struct sm501_devdata *sm)
{
+ void __iomem *regs = sm->regs;
+
+ dev_info(sm->dev, "System Control %08x\n",
+ readl(regs + SM501_SYSTEM_CONTROL));
+ dev_info(sm->dev, "Misc Control %08x\n",
+ readl(regs + SM501_MISC_CONTROL));
+ dev_info(sm->dev, "GPIO Control Low %08x\n",
+ readl(regs + SM501_GPIO31_0_CONTROL));
+ dev_info(sm->dev, "GPIO Control Hi %08x\n",
+ readl(regs + SM501_GPIO63_32_CONTROL));
+ dev_info(sm->dev, "DRAM Control %08x\n",
+ readl(regs + SM501_DRAM_CONTROL));
+ dev_info(sm->dev, "Arbitration Ctrl %08x\n",
+ readl(regs + SM501_ARBTRTN_CONTROL));
+ dev_info(sm->dev, "Misc Timing %08x\n",
+ readl(regs + SM501_MISC_TIMING));
}
+
+static void sm501_dump_gate(struct sm501_devdata *sm)
+{
+ dev_info(sm->dev, "CurrentGate %08x\n",
+ readl(sm->regs + SM501_CURRENT_GATE));
+ dev_info(sm->dev, "CurrentClock %08x\n",
+ readl(sm->regs + SM501_CURRENT_CLOCK));
+ dev_info(sm->dev, "PowerModeControl %08x\n",
+ readl(sm->regs + SM501_POWER_MODE_CONTROL));
+}
+
+#else
+static inline void sm501_dump_gate(struct sm501_devdata *sm) { }
+static inline void sm501_dump_regs(struct sm501_devdata *sm) { }
+static inline void sm501_dump_clk(struct sm501_devdata *sm) { }
#endif
/* sm501_sync_regs
@@ -185,9 +219,21 @@ static void sm501_sync_regs(struct sm501_devdata *sm)
readl(sm->regs);
}
+static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
+{
+ /* during suspend/resume, we are currently not allowed to sleep,
+ * so change to using mdelay() instead of msleep() if we
+ * are in one of these paths */
+
+ if (sm->in_suspend)
+ mdelay(delay);
+ else
+ msleep(delay);
+}
+
/* sm501_misc_control
*
- * alters the misceleneous control parameters
+ * alters the miscellaneous control parameters
*/
int sm501_misc_control(struct device *dev,
@@ -368,7 +414,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
gate, clock, mode);
- msleep(16);
+ sm501_mdelay(sm, 16);
already:
mutex_unlock(&sm->clock_lock);
@@ -538,7 +584,7 @@ unsigned long sm501_set_clock(struct device *dev,
dev_info(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
gate, clock, mode);
- msleep(16);
+ sm501_mdelay(sm, 16);
mutex_unlock(&sm->clock_lock);
sm501_dump_clk(sm);
@@ -767,6 +813,9 @@ static DEVICE_ATTR(dbg_regs, 0666, sm501_dbg_regs, NULL);
/* sm501_init_reg
*
* Helper function for the init code to setup a register
+ *
+ * clear the bits which are set in r->mask, and then set
+ * the bits set in r->set.
*/
static inline void sm501_init_reg(struct sm501_devdata *sm,
@@ -776,8 +825,8 @@ static inline void sm501_init_reg(struct sm501_devdata *sm,
unsigned long tmp;
tmp = readl(sm->regs + reg);
- tmp |= r->set;
tmp &= ~r->mask;
+ tmp |= r->set;
writel(tmp, sm->regs + reg);
}
@@ -797,15 +846,33 @@ static void sm501_init_regs(struct sm501_devdata *sm,
sm501_init_reg(sm, SM501_GPIO31_0_CONTROL, &init->gpio_low);
sm501_init_reg(sm, SM501_GPIO63_32_CONTROL, &init->gpio_high);
+ if (init->m1xclk) {
+ dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk);
+ sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk);
+ }
+
if (init->mclk) {
dev_info(sm->dev, "setting MCLK to %ld\n", init->mclk);
sm501_set_clock(sm->dev, SM501_CLOCK_MCLK, init->mclk);
}
- if (init->m1xclk) {
- dev_info(sm->dev, "setting M1XCLK to %ld\n", init->m1xclk);
- sm501_set_clock(sm->dev, SM501_CLOCK_M1XCLK, init->m1xclk);
- }
+}
+
+/* Check the PLL sources for the M1CLK and M1XCLK
+ *
+ * If the M1CLK and M1XCLKs are not sourced from the same PLL, then
+ * there is a risk (see errata AB-5) that the SM501 will cease proper
+ * function. If this happens, then it is likely the SM501 will
+ * hang the system.
+*/
+
+static int sm501_check_clocks(struct sm501_devdata *sm)
+{
+ unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK);
+ unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC);
+ unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC);
+
+ return ((msrc == 0 && m1src != 0) || (msrc != 0 && m1src == 0));
}
static unsigned int sm501_mem_local[] = {
@@ -826,6 +893,7 @@ static int sm501_init_dev(struct sm501_devdata *sm)
{
resource_size_t mem_avail;
unsigned long dramctrl;
+ unsigned long devid;
int ret;
mutex_init(&sm->clock_lock);
@@ -833,17 +901,20 @@ static int sm501_init_dev(struct sm501_devdata *sm)
INIT_LIST_HEAD(&sm->devices);
- dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+ devid = readl(sm->regs + SM501_DEVICEID);
+
+ if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) {
+ dev_err(sm->dev, "incorrect device id %08lx\n", devid);
+ return -EINVAL;
+ }
+ dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
- dev_info(sm->dev, "SM501 At %p: Version %08x, %ld Mb, IRQ %d\n",
- sm->regs, readl(sm->regs + SM501_DEVICEID),
- (unsigned long)mem_avail >> 20, sm->irq);
+ dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n",
+ sm->regs, devid, (unsigned long)mem_avail >> 20, sm->irq);
- dev_info(sm->dev, "CurrentGate %08x\n", readl(sm->regs+0x38));
- dev_info(sm->dev, "CurrentClock %08x\n", readl(sm->regs+0x3c));
- dev_info(sm->dev, "PowerModeControl %08x\n", readl(sm->regs+0x54));
+ sm501_dump_gate(sm);
ret = device_create_file(sm->dev, &dev_attr_dbg_regs);
if (ret)
@@ -864,6 +935,13 @@ static int sm501_init_dev(struct sm501_devdata *sm)
}
}
+ ret = sm501_check_clocks(sm);
+ if (ret) {
+ dev_err(sm->dev, "M1X and M clocks sourced from different "
+ "PLLs\n");
+ return -EINVAL;
+ }
+
/* always create a framebuffer */
sm501_register_display(sm, &mem_avail);
@@ -933,6 +1011,57 @@ static int sm501_plat_probe(struct platform_device *dev)
}
+#ifdef CONFIG_PM
+/* power management support */
+
+static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct sm501_devdata *sm = platform_get_drvdata(pdev);
+
+ sm->in_suspend = 1;
+ sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
+
+ sm501_dump_regs(sm);
+ return 0;
+}
+
+static int sm501_plat_resume(struct platform_device *pdev)
+{
+ struct sm501_devdata *sm = platform_get_drvdata(pdev);
+
+ sm501_dump_regs(sm);
+ sm501_dump_gate(sm);
+ sm501_dump_clk(sm);
+
+ /* check to see if we are in the same state as when suspended */
+
+ if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
+ dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n");
+ writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
+
+ /* our suspend causes the controller state to change,
+ * either by something attempting setup, power loss,
+ * or an external reset event on power change */
+
+ if (sm->platdata && sm->platdata->init) {
+ sm501_init_regs(sm, sm->platdata->init);
+ }
+ }
+
+ /* dump our state from resume */
+
+ sm501_dump_regs(sm);
+ sm501_dump_clk(sm);
+
+ sm->in_suspend = 0;
+
+ return 0;
+}
+#else
+#define sm501_plat_suspend NULL
+#define sm501_plat_resume NULL
+#endif
+
/* Initialisation data for PCI devices */
static struct sm501_initdata sm501_pci_initdata = {
@@ -950,8 +1079,12 @@ static struct sm501_initdata sm501_pci_initdata = {
},
.devices = SM501_USE_ALL,
- .mclk = 100 * MHZ,
- .m1xclk = 160 * MHZ,
+
+ /* Errata AB-3 says that 72MHz is the fastest available
+ * for 33MHZ PCI with proper bus-mastering operation */
+
+ .mclk = 72 * MHZ,
+ .m1xclk = 144 * MHZ,
};
static struct sm501_platdata_fbsub sm501_pdata_fbsub = {
@@ -1126,6 +1259,8 @@ static struct platform_driver sm501_plat_drv = {
},
.probe = sm501_plat_probe,
.remove = sm501_plat_remove,
+ .suspend = sm501_plat_suspend,
+ .resume = sm501_plat_resume,
};
static int __init sm501_base_init(void)
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 7772bd1d92b..38e815a2e87 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -291,7 +291,7 @@ static void ucb1x00_ts_irq(int idx, void *id)
static int ucb1x00_ts_open(struct input_dev *idev)
{
- struct ucb1x00_ts *ts = idev->private;
+ struct ucb1x00_ts *ts = input_get_drvdata(idev);
int ret = 0;
BUG_ON(ts->rtask);
@@ -328,7 +328,7 @@ static int ucb1x00_ts_open(struct input_dev *idev)
*/
static void ucb1x00_ts_close(struct input_dev *idev)
{
- struct ucb1x00_ts *ts = idev->private;
+ struct ucb1x00_ts *ts = input_get_drvdata(idev);
if (ts->rtask)
kthread_stop(ts->rtask);
@@ -380,7 +380,6 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
ts->idev = idev;
ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
- idev->private = ts;
idev->name = "Touchscreen panel";
idev->id.product = ts->ucb->id;
idev->open = ucb1x00_ts_open;
@@ -391,6 +390,8 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
__set_bit(ABS_Y, idev->absbit);
__set_bit(ABS_PRESSURE, idev->absbit);
+ input_set_drvdata(idev, ts);
+
err = input_register_device(idev);
if (err)
goto fail;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 2f2fbffafbe..bd601efa7bd 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -34,6 +34,11 @@ config PHANTOM
If you choose to build module, its name will be phantom. If unsure,
say N here.
+config EEPROM_93CX6
+ tristate "EEPROM 93CX6 support"
+ ---help---
+ This is a driver for the EEPROM chipsets 93c46 and 93c66.
+ The driver supports both read as well as write commands.
If unsure, say N.
@@ -187,13 +192,4 @@ config THINKPAD_ACPI_BAY
If you are not sure, say Y here.
-config BLINK
- tristate "Keyboard blink driver"
- help
- Driver that when loaded will blink the keyboard LEDs continuously.
- This is useful for debugging and for kernels that cannot necessarily
- output something to the screen like kexec kernels to give the user
- a visual indication that the kernel is doing something.
-
-
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 5b6d46de005..b5ce0e3dba8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/
obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/
obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
-obj-$(CONFIG_BLINK) += blink.o
obj-$(CONFIG_LKDTM) += lkdtm.o
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
@@ -15,3 +14,4 @@ obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SGI_IOC4) += ioc4.o
obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
+obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 4f9060a2a2f..7798f590e5a 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -737,8 +737,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
struct device_attribute dev_attr_##_name = { \
.attr = { \
.name = __stringify(_name), \
- .mode = 0, \
- .owner = THIS_MODULE }, \
+ .mode = 0 }, \
.show = NULL, \
.store = NULL, \
}
diff --git a/drivers/misc/blink.c b/drivers/misc/blink.c
deleted file mode 100644
index 634431ce118..00000000000
--- a/drivers/misc/blink.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-
-static void do_blink(unsigned long data);
-
-static DEFINE_TIMER(blink_timer, do_blink, 0 ,0);
-
-static void do_blink(unsigned long data)
-{
- static long count;
- if (panic_blink)
- panic_blink(count++);
- blink_timer.expires = jiffies + msecs_to_jiffies(1);
- add_timer(&blink_timer);
-}
-
-static int blink_init(void)
-{
- printk(KERN_INFO "Enabling keyboard blinking\n");
- do_blink(0);
- return 0;
-}
-
-module_init(blink_init);
-
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 00000000000..ea55654e594
--- /dev/null
+++ b/drivers/misc/eeprom_93cx6.c
@@ -0,0 +1,241 @@
+/*
+ Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Module: eeprom_93cx6
+ Abstract: EEPROM reader routines for 93cx6 chipsets.
+ Supported chipsets: 93c46 & 93c66.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/eeprom_93cx6.h>
+
+MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
+MODULE_LICENSE("GPL");
+
+static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
+{
+ eeprom->reg_data_clock = 1;
+ eeprom->register_write(eeprom);
+
+ /*
+ * Add a short delay for the pulse to work.
+ * According to the specifications the "maximum minimum"
+ * time should be 450ns.
+ */
+ ndelay(450);
+}
+
+static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
+{
+ eeprom->reg_data_clock = 0;
+ eeprom->register_write(eeprom);
+
+ /*
+ * Add a short delay for the pulse to work.
+ * According to the specifications the "maximum minimum"
+ * time should be 450ns.
+ */
+ ndelay(450);
+}
+
+static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
+{
+ /*
+ * Clear all flags, and enable chip select.
+ */
+ eeprom->register_read(eeprom);
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+ eeprom->reg_data_clock = 0;
+ eeprom->reg_chip_select = 1;
+ eeprom->register_write(eeprom);
+
+ /*
+ * kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
+{
+ /*
+ * Clear chip_select and data_in flags.
+ */
+ eeprom->register_read(eeprom);
+ eeprom->reg_data_in = 0;
+ eeprom->reg_chip_select = 0;
+ eeprom->register_write(eeprom);
+
+ /*
+ * kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+}
+
+static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
+ const u16 data, const u16 count)
+{
+ unsigned int i;
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data flags.
+ */
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+
+ /*
+ * Start writing all bits.
+ */
+ for (i = count; i > 0; i--) {
+ /*
+ * Check if this bit needs to be set.
+ */
+ eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+
+ /*
+ * Write the bit to the eeprom register.
+ */
+ eeprom->register_write(eeprom);
+
+ /*
+ * Kick a pulse.
+ */
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
+ eeprom->reg_data_in = 0;
+ eeprom->register_write(eeprom);
+}
+
+static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
+ u16 *data, const u16 count)
+{
+ unsigned int i;
+ u16 buf = 0;
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data flags.
+ */
+ eeprom->reg_data_in = 0;
+ eeprom->reg_data_out = 0;
+
+ /*
+ * Start reading all bits.
+ */
+ for (i = count; i > 0; i--) {
+ eeprom_93cx6_pulse_high(eeprom);
+
+ eeprom->register_read(eeprom);
+
+ /*
+ * Clear data_in flag.
+ */
+ eeprom->reg_data_in = 0;
+
+ /*
+ * Read if the bit has been set.
+ */
+ if (eeprom->reg_data_out)
+ buf |= (1 << (i - 1));
+
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
+ *data = buf;
+}
+
+/**
+ * eeprom_93cx6_read - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ *
+ * This function will read the eeprom data as host-endian word
+ * into the given data pointer.
+ */
+void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
+ u16 *data)
+{
+ u16 command;
+
+ /*
+ * Initialize the eeprom register
+ */
+ eeprom_93cx6_startup(eeprom);
+
+ /*
+ * Select the read opcode and the word to be read.
+ */
+ command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
+ eeprom_93cx6_write_bits(eeprom, command,
+ PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+
+ /*
+ * Read the requested 16 bits.
+ */
+ eeprom_93cx6_read_bits(eeprom, data, 16);
+
+ /*
+ * Cleanup eeprom register.
+ */
+ eeprom_93cx6_cleanup(eeprom);
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
+
+/**
+ * eeprom_93cx6_multiread - Read multiple words from eeprom
+ * @eeprom: Pointer to eeprom structure
+ * @word: Word index from where we should start reading
+ * @data: target pointer where the information will have to be stored
+ * @words: Number of words that should be read.
+ *
+ * This function will read all requested words from the eeprom,
+ * this is done by calling eeprom_93cx6_read() multiple times.
+ * But with the additional change that while the eeprom_93cx6_read
+ * will return host ordered bytes, this method will return little
+ * endian words.
+ */
+void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
+ __le16 *data, const u16 words)
+{
+ unsigned int i;
+ u16 tmp;
+
+ for (i = 0; i < words; i++) {
+ tmp = 0;
+ eeprom_93cx6_read(eeprom, word + i, &tmp);
+ data[i] = cpu_to_le16(tmp);
+ }
+}
+EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
+
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 41e901f53e7..932a415197b 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -23,6 +23,8 @@
* msi-laptop.c - MSI S270 laptop support. This laptop is sold under
* various brands, including "Cytron/TCM/Medion/Tchibo MD96100".
*
+ * Driver also supports S271, S420 models.
+ *
* This driver exports a few files in /sys/devices/platform/msi-laptop-pf/:
*
* lcd_level - Screen brightness: contains a single integer in the
@@ -281,25 +283,56 @@ static struct platform_device *msipf_device;
/* Initialization */
+static int dmi_check_cb(struct dmi_system_id *id)
+{
+ printk("msi-laptop: Identified laptop model '%s'.\n", id->ident);
+ return 0;
+}
+
static struct dmi_system_id __initdata msi_dmi_table[] = {
{
.ident = "MSI S270",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
- }
+ DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
+ DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
+ },
+ .callback = dmi_check_cb
+ },
+ {
+ .ident = "MSI S271",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MS-1058"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "0581"),
+ DMI_MATCH(DMI_BOARD_NAME, "MS-1058")
+ },
+ .callback = dmi_check_cb
+ },
+ {
+ .ident = "MSI S420",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MS-1412"),
+ DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+ DMI_MATCH(DMI_BOARD_NAME, "MS-1412")
+ },
+ .callback = dmi_check_cb
},
{
.ident = "Medion MD96100",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
- }
+ DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
+ DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT'L CO.,LTD")
+ },
+ .callback = dmi_check_cb
},
{ }
};
-
static int __init msi_init(void)
{
int ret;
@@ -394,3 +427,8 @@ MODULE_AUTHOR("Lennart Poettering");
MODULE_DESCRIPTION("MSI Laptop Support");
MODULE_VERSION(MSI_DRIVER_VERSION);
MODULE_LICENSE("GPL");
+
+MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*");
+MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
+MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 6c36a55cb3d..95c0b96e83f 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -740,7 +740,7 @@ static ssize_t hotkey_enable_store(struct device *dev,
}
static struct device_attribute dev_attr_hotkey_enable =
- __ATTR(enable, S_IWUSR | S_IRUGO,
+ __ATTR(hotkey_enable, S_IWUSR | S_IRUGO,
hotkey_enable_show, hotkey_enable_store);
/* sysfs hotkey mask --------------------------------------------------- */
@@ -775,7 +775,7 @@ static ssize_t hotkey_mask_store(struct device *dev,
}
static struct device_attribute dev_attr_hotkey_mask =
- __ATTR(mask, S_IWUSR | S_IRUGO,
+ __ATTR(hotkey_mask, S_IWUSR | S_IRUGO,
hotkey_mask_show, hotkey_mask_store);
/* sysfs hotkey bios_enabled ------------------------------------------- */
@@ -787,7 +787,7 @@ static ssize_t hotkey_bios_enabled_show(struct device *dev,
}
static struct device_attribute dev_attr_hotkey_bios_enabled =
- __ATTR(bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
+ __ATTR(hotkey_bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
/* sysfs hotkey bios_mask ---------------------------------------------- */
static ssize_t hotkey_bios_mask_show(struct device *dev,
@@ -798,7 +798,7 @@ static ssize_t hotkey_bios_mask_show(struct device *dev,
}
static struct device_attribute dev_attr_hotkey_bios_mask =
- __ATTR(bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
+ __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
/* --------------------------------------------------------------------- */
@@ -824,8 +824,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
str_supported(tp_features.hotkey));
if (tp_features.hotkey) {
- hotkey_dev_attributes = create_attr_set(4,
- TPACPI_HOTKEY_SYSFS_GROUP);
+ hotkey_dev_attributes = create_attr_set(4, NULL);
if (!hotkey_dev_attributes)
return -ENOMEM;
res = add_to_attr_set(hotkey_dev_attributes,
@@ -1050,7 +1049,7 @@ static ssize_t bluetooth_enable_store(struct device *dev,
}
static struct device_attribute dev_attr_bluetooth_enable =
- __ATTR(enable, S_IWUSR | S_IRUGO,
+ __ATTR(bluetooth_enable, S_IWUSR | S_IRUGO,
bluetooth_enable_show, bluetooth_enable_store);
/* --------------------------------------------------------------------- */
@@ -1061,7 +1060,6 @@ static struct attribute *bluetooth_attributes[] = {
};
static const struct attribute_group bluetooth_attr_group = {
- .name = TPACPI_BLUETH_SYSFS_GROUP,
.attrs = bluetooth_attributes,
};
@@ -1215,7 +1213,7 @@ static ssize_t wan_enable_store(struct device *dev,
}
static struct device_attribute dev_attr_wan_enable =
- __ATTR(enable, S_IWUSR | S_IRUGO,
+ __ATTR(wwan_enable, S_IWUSR | S_IRUGO,
wan_enable_show, wan_enable_store);
/* --------------------------------------------------------------------- */
@@ -1226,7 +1224,6 @@ static struct attribute *wan_attributes[] = {
};
static const struct attribute_group wan_attr_group = {
- .name = TPACPI_WAN_SYSFS_GROUP,
.attrs = wan_attributes,
};
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index 440145a0261..72d62f2dabb 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -278,8 +278,6 @@ static int beep_write(char *buf);
* Bluetooth subdriver
*/
-#define TPACPI_BLUETH_SYSFS_GROUP "bluetooth"
-
enum {
/* ACPI GBDC/SBDC bits */
TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */
@@ -416,8 +414,6 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc);
* Hotkey subdriver
*/
-#define TPACPI_HOTKEY_SYSFS_GROUP "hotkey"
-
static int hotkey_orig_status;
static int hotkey_orig_mask;
@@ -553,8 +549,6 @@ static int volume_write(char *buf);
* Wan subdriver
*/
-#define TPACPI_WAN_SYSFS_GROUP "wwan"
-
enum {
/* ACPI GWAN/SWAN bits */
TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index c08ad8f823d..2d1b3df95c5 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -343,7 +343,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
if (!fm->addr)
goto err_out_free;
- rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
+ rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
if (rc)
goto err_out_unmap;
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 9320a8c7323..a49cb9737cd 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -14,3 +14,21 @@ config MMC_BLOCK
mount the filesystem. Almost everyone wishing MMC support
should say Y or M here.
+config MMC_BLOCK_BOUNCE
+ bool "Use bounce buffer for simple hosts"
+ depends on MMC_BLOCK
+ default y
+ help
+ SD/MMC is a high latency protocol where it is crucial to
+ send large requests in order to get high performance. Many
+ controllers, however, are restricted to continuous memory
+ (i.e. they can't do scatter-gather), something the kernel
+ rarely can provide.
+
+ Say Y here to help these restricted hosts by bouncing
+ requests back and forth from a large buffer. You will get
+ a big performance gain at the cost of up to 64 KiB of
+ physical memory.
+
+ If unsure, say Y here.
+
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 540ff4bea54..cbd4b6e3e17 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -262,7 +262,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
}
brq.data.sg = mq->sg;
- brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);
+ brq.data.sg_len = mmc_queue_map_sg(mq);
+
+ mmc_queue_bounce_pre(mq);
if (brq.data.blocks !=
(req->nr_sectors >> (md->block_bits - 9))) {
@@ -279,6 +281,9 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
}
mmc_wait_for_req(card->host, &brq.mrq);
+
+ mmc_queue_bounce_post(mq);
+
if (brq.cmd.error) {
printk(KERN_ERR "%s: error %d sending read/write command\n",
req->rq_disk->disk_name, brq.cmd.error);
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index dd97bc79840..4fb2089dc69 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -17,6 +17,8 @@
#include <linux/mmc/host.h>
#include "queue.h"
+#define MMC_QUEUE_BOUNCESZ 65536
+
#define MMC_QUEUE_SUSPENDED (1 << 0)
/*
@@ -118,6 +120,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
struct mmc_host *host = card->host;
u64 limit = BLK_BOUNCE_HIGH;
int ret;
+ unsigned int bouncesz;
if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
limit = *mmc_dev(host)->dma_mask;
@@ -127,21 +130,61 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
if (!mq->queue)
return -ENOMEM;
- blk_queue_prep_rq(mq->queue, mmc_prep_request);
- blk_queue_bounce_limit(mq->queue, limit);
- blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
- blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
- blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
- blk_queue_max_segment_size(mq->queue, host->max_seg_size);
-
mq->queue->queuedata = mq;
mq->req = NULL;
- mq->sg = kmalloc(sizeof(struct scatterlist) * host->max_phys_segs,
- GFP_KERNEL);
- if (!mq->sg) {
- ret = -ENOMEM;
- goto cleanup_queue;
+ blk_queue_prep_rq(mq->queue, mmc_prep_request);
+
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+ if (host->max_hw_segs == 1) {
+ bouncesz = MMC_QUEUE_BOUNCESZ;
+
+ if (bouncesz > host->max_req_size)
+ bouncesz = host->max_req_size;
+ if (bouncesz > host->max_seg_size)
+ bouncesz = host->max_seg_size;
+
+ mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+ if (!mq->bounce_buf) {
+ printk(KERN_WARNING "%s: unable to allocate "
+ "bounce buffer\n", mmc_card_name(card));
+ } else {
+ blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH);
+ blk_queue_max_sectors(mq->queue, bouncesz / 512);
+ blk_queue_max_phys_segments(mq->queue, bouncesz / 512);
+ blk_queue_max_hw_segments(mq->queue, bouncesz / 512);
+ blk_queue_max_segment_size(mq->queue, bouncesz);
+
+ mq->sg = kmalloc(sizeof(struct scatterlist),
+ GFP_KERNEL);
+ if (!mq->sg) {
+ ret = -ENOMEM;
+ goto free_bounce_buf;
+ }
+
+ mq->bounce_sg = kmalloc(sizeof(struct scatterlist) *
+ bouncesz / 512, GFP_KERNEL);
+ if (!mq->bounce_sg) {
+ ret = -ENOMEM;
+ goto free_sg;
+ }
+ }
+ }
+#endif
+
+ if (!mq->bounce_buf) {
+ blk_queue_bounce_limit(mq->queue, limit);
+ blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
+ blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
+ blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
+ blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+
+ mq->sg = kmalloc(sizeof(struct scatterlist) *
+ host->max_phys_segs, GFP_KERNEL);
+ if (!mq->sg) {
+ ret = -ENOMEM;
+ goto cleanup_queue;
+ }
}
init_MUTEX(&mq->thread_sem);
@@ -149,14 +192,21 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd");
if (IS_ERR(mq->thread)) {
ret = PTR_ERR(mq->thread);
- goto free_sg;
+ goto free_bounce_sg;
}
return 0;
-
+ free_bounce_sg:
+ if (mq->bounce_sg)
+ kfree(mq->bounce_sg);
+ mq->bounce_sg = NULL;
free_sg:
kfree(mq->sg);
mq->sg = NULL;
+ free_bounce_buf:
+ if (mq->bounce_buf)
+ kfree(mq->bounce_buf);
+ mq->bounce_buf = NULL;
cleanup_queue:
blk_cleanup_queue(mq->queue);
return ret;
@@ -178,9 +228,17 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
/* Then terminate our worker thread */
kthread_stop(mq->thread);
+ if (mq->bounce_sg)
+ kfree(mq->bounce_sg);
+ mq->bounce_sg = NULL;
+
kfree(mq->sg);
mq->sg = NULL;
+ if (mq->bounce_buf)
+ kfree(mq->bounce_buf);
+ mq->bounce_buf = NULL;
+
blk_cleanup_queue(mq->queue);
mq->card = NULL;
@@ -231,3 +289,108 @@ void mmc_queue_resume(struct mmc_queue *mq)
}
}
+static void copy_sg(struct scatterlist *dst, unsigned int dst_len,
+ struct scatterlist *src, unsigned int src_len)
+{
+ unsigned int chunk;
+ char *dst_buf, *src_buf;
+ unsigned int dst_size, src_size;
+
+ dst_buf = NULL;
+ src_buf = NULL;
+ dst_size = 0;
+ src_size = 0;
+
+ while (src_len) {
+ BUG_ON(dst_len == 0);
+
+ if (dst_size == 0) {
+ dst_buf = page_address(dst->page) + dst->offset;
+ dst_size = dst->length;
+ }
+
+ if (src_size == 0) {
+ src_buf = page_address(src->page) + src->offset;
+ src_size = src->length;
+ }
+
+ chunk = min(dst_size, src_size);
+
+ memcpy(dst_buf, src_buf, chunk);
+
+ dst_buf += chunk;
+ src_buf += chunk;
+ dst_size -= chunk;
+ src_size -= chunk;
+
+ if (dst_size == 0) {
+ dst++;
+ dst_len--;
+ }
+
+ if (src_size == 0) {
+ src++;
+ src_len--;
+ }
+ }
+}
+
+unsigned int mmc_queue_map_sg(struct mmc_queue *mq)
+{
+ unsigned int sg_len;
+
+ if (!mq->bounce_buf)
+ return blk_rq_map_sg(mq->queue, mq->req, mq->sg);
+
+ BUG_ON(!mq->bounce_sg);
+
+ sg_len = blk_rq_map_sg(mq->queue, mq->req, mq->bounce_sg);
+
+ mq->bounce_sg_len = sg_len;
+
+ /*
+ * Shortcut in the event we only get a single entry.
+ */
+ if (sg_len == 1) {
+ memcpy(mq->sg, mq->bounce_sg, sizeof(struct scatterlist));
+ return 1;
+ }
+
+ mq->sg[0].page = virt_to_page(mq->bounce_buf);
+ mq->sg[0].offset = offset_in_page(mq->bounce_buf);
+ mq->sg[0].length = 0;
+
+ while (sg_len) {
+ mq->sg[0].length += mq->bounce_sg[sg_len - 1].length;
+ sg_len--;
+ }
+
+ return 1;
+}
+
+void mmc_queue_bounce_pre(struct mmc_queue *mq)
+{
+ if (!mq->bounce_buf)
+ return;
+
+ if (mq->bounce_sg_len == 1)
+ return;
+ if (rq_data_dir(mq->req) != WRITE)
+ return;
+
+ copy_sg(mq->sg, 1, mq->bounce_sg, mq->bounce_sg_len);
+}
+
+void mmc_queue_bounce_post(struct mmc_queue *mq)
+{
+ if (!mq->bounce_buf)
+ return;
+
+ if (mq->bounce_sg_len == 1)
+ return;
+ if (rq_data_dir(mq->req) != READ)
+ return;
+
+ copy_sg(mq->bounce_sg, mq->bounce_sg_len, mq->sg, 1);
+}
+
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 1590b3f3f1f..64e66e0d499 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -14,6 +14,9 @@ struct mmc_queue {
void *data;
struct request_queue *queue;
struct scatterlist *sg;
+ char *bounce_buf;
+ struct scatterlist *bounce_sg;
+ unsigned int bounce_sg_len;
};
extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
@@ -21,4 +24,8 @@ extern void mmc_cleanup_queue(struct mmc_queue *);
extern void mmc_queue_suspend(struct mmc_queue *);
extern void mmc_queue_resume(struct mmc_queue *);
+extern unsigned int mmc_queue_map_sg(struct mmc_queue *);
+extern void mmc_queue_bounce_pre(struct mmc_queue *);
+extern void mmc_queue_bounce_post(struct mmc_queue *);
+
#endif
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 1075b02ae75..3fdd08c7f14 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -7,5 +7,6 @@ ifeq ($(CONFIG_MMC_DEBUG),y)
endif
obj-$(CONFIG_MMC) += mmc_core.o
-mmc_core-y := core.o sysfs.o mmc.o mmc_ops.o sd.o sd_ops.o
+mmc_core-y := core.o sysfs.o bus.o host.o \
+ mmc.o mmc_ops.o sd.o sd_ops.o
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
new file mode 100644
index 00000000000..348b566bf4f
--- /dev/null
+++ b/drivers/mmc/core/bus.c
@@ -0,0 +1,253 @@
+/*
+ * linux/drivers/mmc/core/bus.c
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright (C) 2007 Pierre Ossman
+ *
+ * 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.
+ *
+ * MMC card bus driver model
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "sysfs.h"
+#include "core.h"
+#include "bus.h"
+
+#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
+#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
+
+static ssize_t mmc_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ switch (card->type) {
+ case MMC_TYPE_MMC:
+ return sprintf(buf, "MMC\n");
+ case MMC_TYPE_SD:
+ return sprintf(buf, "SD\n");
+ default:
+ return -EFAULT;
+ }
+}
+
+static struct device_attribute mmc_dev_attrs[] = {
+ MMC_ATTR_RO(type),
+ __ATTR_NULL,
+};
+
+/*
+ * This currently matches any MMC driver to any MMC card - drivers
+ * themselves make the decision whether to drive this card in their
+ * probe method.
+ */
+static int mmc_bus_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
+static int
+mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
+ int buf_size)
+{
+ struct mmc_card *card = dev_to_mmc_card(dev);
+ int retval = 0, i = 0, length = 0;
+
+#define add_env(fmt,val) do { \
+ retval = add_uevent_var(envp, num_envp, &i, \
+ buf, buf_size, &length, \
+ fmt, val); \
+ if (retval) \
+ return retval; \
+} while (0);
+
+ switch (card->type) {
+ case MMC_TYPE_MMC:
+ add_env("MMC_TYPE=%s", "MMC");
+ break;
+ case MMC_TYPE_SD:
+ add_env("MMC_TYPE=%s", "SD");
+ break;
+ }
+
+ add_env("MMC_NAME=%s", mmc_card_name(card));
+
+#undef add_env
+
+ envp[i] = NULL;
+
+ return 0;
+}
+
+static int mmc_bus_probe(struct device *dev)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ return drv->probe(card);
+}
+
+static int mmc_bus_remove(struct device *dev)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ drv->remove(card);
+
+ return 0;
+}
+
+static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = dev_to_mmc_card(dev);
+ int ret = 0;
+
+ if (dev->driver && drv->suspend)
+ ret = drv->suspend(card, state);
+ return ret;
+}
+
+static int mmc_bus_resume(struct device *dev)
+{
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = dev_to_mmc_card(dev);
+ int ret = 0;
+
+ if (dev->driver && drv->resume)
+ ret = drv->resume(card);
+ return ret;
+}
+
+static struct bus_type mmc_bus_type = {
+ .name = "mmc",
+ .dev_attrs = mmc_dev_attrs,
+ .match = mmc_bus_match,
+ .uevent = mmc_bus_uevent,
+ .probe = mmc_bus_probe,
+ .remove = mmc_bus_remove,
+ .suspend = mmc_bus_suspend,
+ .resume = mmc_bus_resume,
+};
+
+int mmc_register_bus(void)
+{
+ return bus_register(&mmc_bus_type);
+}
+
+void mmc_unregister_bus(void)
+{
+ bus_unregister(&mmc_bus_type);
+}
+
+/**
+ * mmc_register_driver - register a media driver
+ * @drv: MMC media driver
+ */
+int mmc_register_driver(struct mmc_driver *drv)
+{
+ drv->drv.bus = &mmc_bus_type;
+ return driver_register(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_register_driver);
+
+/**
+ * mmc_unregister_driver - unregister a media driver
+ * @drv: MMC media driver
+ */
+void mmc_unregister_driver(struct mmc_driver *drv)
+{
+ drv->drv.bus = &mmc_bus_type;
+ driver_unregister(&drv->drv);
+}
+
+EXPORT_SYMBOL(mmc_unregister_driver);
+
+static void mmc_release_card(struct device *dev)
+{
+ struct mmc_card *card = dev_to_mmc_card(dev);
+
+ kfree(card);
+}
+
+/*
+ * Allocate and initialise a new MMC card structure.
+ */
+struct mmc_card *mmc_alloc_card(struct mmc_host *host)
+{
+ struct mmc_card *card;
+
+ card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+ if (!card)
+ return ERR_PTR(-ENOMEM);
+
+ memset(card, 0, sizeof(struct mmc_card));
+
+ card->host = host;
+
+ device_initialize(&card->dev);
+
+ card->dev.parent = mmc_classdev(host);
+ card->dev.bus = &mmc_bus_type;
+ card->dev.release = mmc_release_card;
+
+ return card;
+}
+
+/*
+ * Register a new MMC card with the driver model.
+ */
+int mmc_add_card(struct mmc_card *card)
+{
+ int ret;
+
+ snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
+ "%s:%04x", mmc_hostname(card->host), card->rca);
+
+ card->dev.uevent_suppress = 1;
+
+ ret = device_add(&card->dev);
+ if (ret)
+ return ret;
+
+ if (card->host->bus_ops->sysfs_add) {
+ ret = card->host->bus_ops->sysfs_add(card->host, card);
+ if (ret) {
+ device_del(&card->dev);
+ return ret;
+ }
+ }
+
+ card->dev.uevent_suppress = 0;
+
+ kobject_uevent(&card->dev.kobj, KOBJ_ADD);
+
+ mmc_card_set_present(card);
+
+ return 0;
+}
+
+/*
+ * Unregister a new MMC card with the driver model, and
+ * (eventually) free it.
+ */
+void mmc_remove_card(struct mmc_card *card)
+{
+ if (mmc_card_present(card)) {
+ if (card->host->bus_ops->sysfs_remove)
+ card->host->bus_ops->sysfs_remove(card->host, card);
+ device_del(&card->dev);
+ }
+
+ put_device(&card->dev);
+}
+
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h
new file mode 100644
index 00000000000..4f35431116a
--- /dev/null
+++ b/drivers/mmc/core/bus.h
@@ -0,0 +1,22 @@
+/*
+ * linux/drivers/mmc/core/bus.h
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright 2007 Pierre Ossman
+ *
+ * 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 _MMC_CORE_BUS_H
+#define _MMC_CORE_BUS_H
+
+struct mmc_card *mmc_alloc_card(struct mmc_host *host);
+int mmc_add_card(struct mmc_card *card);
+void mmc_remove_card(struct mmc_card *card);
+
+int mmc_register_bus(void);
+void mmc_unregister_bus(void);
+
+#endif
+
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7385acfa1dd..b5d8a6d90cc 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -27,7 +27,8 @@
#include <linux/mmc/sd.h>
#include "core.h"
-#include "sysfs.h"
+#include "bus.h"
+#include "host.h"
#include "mmc_ops.h"
#include "sd_ops.h"
@@ -35,6 +36,25 @@
extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
+static struct workqueue_struct *workqueue;
+
+/*
+ * Internal function. Schedule delayed work in the MMC work queue.
+ */
+static int mmc_schedule_delayed_work(struct delayed_work *work,
+ unsigned long delay)
+{
+ return queue_delayed_work(workqueue, work, delay);
+}
+
+/*
+ * Internal function. Flush all scheduled work from the MMC work queue.
+ */
+static void mmc_flush_scheduled_work(void)
+{
+ flush_workqueue(workqueue);
+}
+
/**
* mmc_request_done - finish processing an MMC request
* @host: MMC host which completed request
@@ -369,22 +389,6 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing)
}
/*
- * Allocate a new MMC card
- */
-struct mmc_card *mmc_alloc_card(struct mmc_host *host)
-{
- struct mmc_card *card;
-
- card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
- if (!card)
- return ERR_PTR(-ENOMEM);
-
- mmc_init_card(card, host);
-
- return card;
-}
-
-/*
* Apply power to the MMC stack. This is a two-stage process.
* First, we enable power to the card without the clock running.
* We then wait a bit for the power to stabilise. Finally,
@@ -512,7 +516,7 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay)
EXPORT_SYMBOL(mmc_detect_change);
-static void mmc_rescan(struct work_struct *work)
+void mmc_rescan(struct work_struct *work)
{
struct mmc_host *host =
container_of(work, struct mmc_host, detect.work);
@@ -561,69 +565,13 @@ static void mmc_rescan(struct work_struct *work)
}
}
-
-/**
- * mmc_alloc_host - initialise the per-host structure.
- * @extra: sizeof private data structure
- * @dev: pointer to host device model structure
- *
- * Initialise the per-host structure.
- */
-struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+void mmc_start_host(struct mmc_host *host)
{
- struct mmc_host *host;
-
- host = mmc_alloc_host_sysfs(extra, dev);
- if (host) {
- spin_lock_init(&host->lock);
- init_waitqueue_head(&host->wq);
- INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-
- /*
- * By default, hosts do not support SGIO or large requests.
- * They have to set these according to their abilities.
- */
- host->max_hw_segs = 1;
- host->max_phys_segs = 1;
- host->max_seg_size = PAGE_CACHE_SIZE;
-
- host->max_req_size = PAGE_CACHE_SIZE;
- host->max_blk_size = 512;
- host->max_blk_count = PAGE_CACHE_SIZE / 512;
- }
-
- return host;
-}
-
-EXPORT_SYMBOL(mmc_alloc_host);
-
-/**
- * mmc_add_host - initialise host hardware
- * @host: mmc host
- */
-int mmc_add_host(struct mmc_host *host)
-{
- int ret;
-
- ret = mmc_add_host_sysfs(host);
- if (ret == 0) {
- mmc_power_off(host);
- mmc_detect_change(host, 0);
- }
-
- return ret;
+ mmc_power_off(host);
+ mmc_detect_change(host, 0);
}
-EXPORT_SYMBOL(mmc_add_host);
-
-/**
- * mmc_remove_host - remove host hardware
- * @host: mmc host
- *
- * Unregister and remove all cards associated with this host,
- * and power down the MMC bus.
- */
-void mmc_remove_host(struct mmc_host *host)
+void mmc_stop_host(struct mmc_host *host)
{
#ifdef CONFIG_MMC_DEBUG
unsigned long flags;
@@ -648,24 +596,8 @@ void mmc_remove_host(struct mmc_host *host)
BUG_ON(host->card);
mmc_power_off(host);
- mmc_remove_host_sysfs(host);
}
-EXPORT_SYMBOL(mmc_remove_host);
-
-/**
- * mmc_free_host - free the host structure
- * @host: mmc host
- *
- * Free the host once all references to it have been dropped.
- */
-void mmc_free_host(struct mmc_host *host)
-{
- mmc_free_host_sysfs(host);
-}
-
-EXPORT_SYMBOL(mmc_free_host);
-
#ifdef CONFIG_PM
/**
@@ -726,4 +658,31 @@ EXPORT_SYMBOL(mmc_resume_host);
#endif
+static int __init mmc_init(void)
+{
+ int ret;
+
+ workqueue = create_singlethread_workqueue("kmmcd");
+ if (!workqueue)
+ return -ENOMEM;
+
+ ret = mmc_register_bus();
+ if (ret == 0) {
+ ret = mmc_register_host_class();
+ if (ret)
+ mmc_unregister_bus();
+ }
+ return ret;
+}
+
+static void __exit mmc_exit(void)
+{
+ mmc_unregister_host_class();
+ mmc_unregister_bus();
+ destroy_workqueue(workqueue);
+}
+
+module_init(mmc_init);
+module_exit(mmc_exit);
+
MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 177264d090a..ae006b30dd8 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -18,6 +18,8 @@
struct mmc_bus_ops {
void (*remove)(struct mmc_host *);
void (*detect)(struct mmc_host *);
+ int (*sysfs_add)(struct mmc_host *, struct mmc_card *card);
+ void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card);
void (*suspend)(struct mmc_host *);
void (*resume)(struct mmc_host *);
};
@@ -54,8 +56,6 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width);
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr);
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
-struct mmc_card *mmc_alloc_card(struct mmc_host *host);
-
static inline void mmc_delay(unsigned int ms)
{
if (ms < 1000 / HZ) {
@@ -66,5 +66,9 @@ static inline void mmc_delay(unsigned int ms)
}
}
+void mmc_rescan(struct work_struct *work);
+void mmc_start_host(struct mmc_host *host);
+void mmc_stop_host(struct mmc_host *host);
+
#endif
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
new file mode 100644
index 00000000000..1433d95c40b
--- /dev/null
+++ b/drivers/mmc/core/host.c
@@ -0,0 +1,156 @@
+/*
+ * linux/drivers/mmc/core/host.c
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright (C) 2007 Pierre Ossman
+ *
+ * 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.
+ *
+ * MMC host class device management
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/pagemap.h>
+
+#include <linux/mmc/host.h>
+
+#include "core.h"
+#include "host.h"
+
+#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
+
+static void mmc_host_classdev_release(struct device *dev)
+{
+ struct mmc_host *host = cls_dev_to_mmc_host(dev);
+ kfree(host);
+}
+
+static struct class mmc_host_class = {
+ .name = "mmc_host",
+ .dev_release = mmc_host_classdev_release,
+};
+
+int mmc_register_host_class(void)
+{
+ return class_register(&mmc_host_class);
+}
+
+void mmc_unregister_host_class(void)
+{
+ class_unregister(&mmc_host_class);
+}
+
+static DEFINE_IDR(mmc_host_idr);
+static DEFINE_SPINLOCK(mmc_host_lock);
+
+/**
+ * mmc_alloc_host - initialise the per-host structure.
+ * @extra: sizeof private data structure
+ * @dev: pointer to host device model structure
+ *
+ * Initialise the per-host structure.
+ */
+struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
+{
+ struct mmc_host *host;
+
+ host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+ if (!host)
+ return NULL;
+
+ memset(host, 0, sizeof(struct mmc_host) + extra);
+
+ host->parent = dev;
+ host->class_dev.parent = dev;
+ host->class_dev.class = &mmc_host_class;
+ device_initialize(&host->class_dev);
+
+ spin_lock_init(&host->lock);
+ init_waitqueue_head(&host->wq);
+ INIT_DELAYED_WORK(&host->detect, mmc_rescan);
+
+ /*
+ * By default, hosts do not support SGIO or large requests.
+ * They have to set these according to their abilities.
+ */
+ host->max_hw_segs = 1;
+ host->max_phys_segs = 1;
+ host->max_seg_size = PAGE_CACHE_SIZE;
+
+ host->max_req_size = PAGE_CACHE_SIZE;
+ host->max_blk_size = 512;
+ host->max_blk_count = PAGE_CACHE_SIZE / 512;
+
+ return host;
+}
+
+EXPORT_SYMBOL(mmc_alloc_host);
+
+/**
+ * mmc_add_host - initialise host hardware
+ * @host: mmc host
+ */
+int mmc_add_host(struct mmc_host *host)
+{
+ int err;
+
+ if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
+ return -ENOMEM;
+
+ spin_lock(&mmc_host_lock);
+ err = idr_get_new(&mmc_host_idr, host, &host->index);
+ spin_unlock(&mmc_host_lock);
+ if (err)
+ return err;
+
+ snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
+ "mmc%d", host->index);
+
+ err = device_add(&host->class_dev);
+ if (err)
+ return err;
+
+ mmc_start_host(host);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(mmc_add_host);
+
+/**
+ * mmc_remove_host - remove host hardware
+ * @host: mmc host
+ *
+ * Unregister and remove all cards associated with this host,
+ * and power down the MMC bus.
+ */
+void mmc_remove_host(struct mmc_host *host)
+{
+ mmc_stop_host(host);
+
+ device_del(&host->class_dev);
+
+ spin_lock(&mmc_host_lock);
+ idr_remove(&mmc_host_idr, host->index);
+ spin_unlock(&mmc_host_lock);
+}
+
+EXPORT_SYMBOL(mmc_remove_host);
+
+/**
+ * mmc_free_host - free the host structure
+ * @host: mmc host
+ *
+ * Free the host once all references to it have been dropped.
+ */
+void mmc_free_host(struct mmc_host *host)
+{
+ put_device(&host->class_dev);
+}
+
+EXPORT_SYMBOL(mmc_free_host);
+
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
new file mode 100644
index 00000000000..c2dc3d2d9f9
--- /dev/null
+++ b/drivers/mmc/core/host.h
@@ -0,0 +1,18 @@
+/*
+ * linux/drivers/mmc/core/host.h
+ *
+ * Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright 2007 Pierre Ossman
+ *
+ * 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 _MMC_CORE_HOST_H
+#define _MMC_CORE_HOST_H
+
+int mmc_register_host_class(void);
+void mmc_unregister_host_class(void);
+
+#endif
+
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 42cc2867ed7..66f85bfa8db 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -18,6 +18,7 @@
#include "core.h"
#include "sysfs.h"
+#include "bus.h"
#include "mmc_ops.h"
static const unsigned int tran_exp[] = {
@@ -236,7 +237,7 @@ out:
* In the case of a resume, "curcard" will contain the card
* we're trying to reinitialise.
*/
-static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
+static int mmc_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
{
struct mmc_card *card;
@@ -413,8 +414,7 @@ static void mmc_detect(struct mmc_host *host)
mmc_release_host(host);
if (err != MMC_ERR_NONE) {
- mmc_remove_card(host->card);
- host->card = NULL;
+ mmc_remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
@@ -422,6 +422,53 @@ static void mmc_detect(struct mmc_host *host)
}
}
+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+ card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+ card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute mmc_dev_attrs[] = {
+ MMC_ATTR_RO(cid),
+ MMC_ATTR_RO(csd),
+ MMC_ATTR_RO(date),
+ MMC_ATTR_RO(fwrev),
+ MMC_ATTR_RO(hwrev),
+ MMC_ATTR_RO(manfid),
+ MMC_ATTR_RO(name),
+ MMC_ATTR_RO(oemid),
+ MMC_ATTR_RO(serial),
+ __ATTR_NULL,
+};
+
+/*
+ * Adds sysfs entries as relevant.
+ */
+static int mmc_sysfs_add(struct mmc_host *host, struct mmc_card *card)
+{
+ int ret;
+
+ ret = mmc_add_attrs(card, mmc_dev_attrs);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * Removes the sysfs entries added by mmc_sysfs_add().
+ */
+static void mmc_sysfs_remove(struct mmc_host *host, struct mmc_card *card)
+{
+ mmc_remove_attrs(card, mmc_dev_attrs);
+}
+
#ifdef CONFIG_MMC_UNSAFE_RESUME
/*
@@ -453,11 +500,9 @@ static void mmc_resume(struct mmc_host *host)
mmc_claim_host(host);
- err = mmc_sd_init_card(host, host->ocr, host->card);
+ err = mmc_init_card(host, host->ocr, host->card);
if (err != MMC_ERR_NONE) {
- mmc_remove_card(host->card);
- host->card = NULL;
-
+ mmc_remove(host);
mmc_detach_bus(host);
}
@@ -474,6 +519,8 @@ static void mmc_resume(struct mmc_host *host)
static const struct mmc_bus_ops mmc_ops = {
.remove = mmc_remove,
.detect = mmc_detect,
+ .sysfs_add = mmc_sysfs_add,
+ .sysfs_remove = mmc_sysfs_remove,
.suspend = mmc_suspend,
.resume = mmc_resume,
};
@@ -512,13 +559,13 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr)
/*
* Detect and init the card.
*/
- err = mmc_sd_init_card(host, host->ocr, NULL);
+ err = mmc_init_card(host, host->ocr, NULL);
if (err != MMC_ERR_NONE)
goto err;
mmc_release_host(host);
- err = mmc_register_card(host->card);
+ err = mmc_add_card(host->card);
if (err)
goto reclaim_host;
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index c1dfd03d559..1240684083f 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -15,14 +15,14 @@
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
#include "core.h"
#include "sysfs.h"
+#include "bus.h"
#include "mmc_ops.h"
#include "sd_ops.h"
-#include "core.h"
-
static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
@@ -192,6 +192,16 @@ static int mmc_read_switch(struct mmc_card *card)
int err;
u8 *status;
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ return MMC_ERR_NONE;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH)) {
+ printk(KERN_WARNING "%s: card lacks mandatory switch "
+ "function, performance might suffer.\n",
+ mmc_hostname(card->host));
+ return MMC_ERR_NONE;
+ }
+
err = MMC_ERR_FAILED;
status = kmalloc(64, GFP_KERNEL);
@@ -204,10 +214,9 @@ static int mmc_read_switch(struct mmc_card *card)
err = mmc_sd_switch(card, 0, 0, 1, status);
if (err != MMC_ERR_NONE) {
- /*
- * Card not supporting high-speed will ignore the
- * command.
- */
+ printk(KERN_WARNING "%s: problem reading switch "
+ "capabilities, performance might suffer.\n",
+ mmc_hostname(card->host));
err = MMC_ERR_NONE;
goto out;
}
@@ -229,6 +238,12 @@ static int mmc_switch_hs(struct mmc_card *card)
int err;
u8 *status;
+ if (card->scr.sda_vsn < SCR_SPEC_VER_1)
+ return MMC_ERR_NONE;
+
+ if (!(card->csd.cmdclass & CCC_SWITCH))
+ return MMC_ERR_NONE;
+
if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
return MMC_ERR_NONE;
@@ -402,7 +417,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
/*
* Switch to wider bus (if supported).
*/
- if ((host->caps && MMC_CAP_4_BIT_DATA) &&
+ if ((host->caps & MMC_CAP_4_BIT_DATA) &&
(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
if (err != MMC_ERR_NONE)
@@ -411,6 +426,21 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
}
+ /*
+ * Check if read-only switch is active.
+ */
+ if (!oldcard) {
+ if (!host->ops->get_ro) {
+ printk(KERN_WARNING "%s: host does not "
+ "support reading read-only "
+ "switch. assuming write-enable.\n",
+ mmc_hostname(host));
+ } else {
+ if (host->ops->get_ro(host))
+ mmc_card_set_readonly(card);
+ }
+ }
+
if (!oldcard)
host->card = card;
@@ -456,8 +486,7 @@ static void mmc_sd_detect(struct mmc_host *host)
mmc_release_host(host);
if (err != MMC_ERR_NONE) {
- mmc_remove_card(host->card);
- host->card = NULL;
+ mmc_sd_remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
@@ -465,6 +494,55 @@ static void mmc_sd_detect(struct mmc_host *host)
}
}
+MMC_ATTR_FN(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+ card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR_FN(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+ card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR_FN(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
+MMC_ATTR_FN(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR_FN(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR_FN(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR_FN(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR_FN(name, "%s\n", card->cid.prod_name);
+MMC_ATTR_FN(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR_FN(serial, "0x%08x\n", card->cid.serial);
+
+static struct device_attribute mmc_sd_dev_attrs[] = {
+ MMC_ATTR_RO(cid),
+ MMC_ATTR_RO(csd),
+ MMC_ATTR_RO(scr),
+ MMC_ATTR_RO(date),
+ MMC_ATTR_RO(fwrev),
+ MMC_ATTR_RO(hwrev),
+ MMC_ATTR_RO(manfid),
+ MMC_ATTR_RO(name),
+ MMC_ATTR_RO(oemid),
+ MMC_ATTR_RO(serial),
+ __ATTR_NULL,
+};
+
+/*
+ * Adds sysfs entries as relevant.
+ */
+static int mmc_sd_sysfs_add(struct mmc_host *host, struct mmc_card *card)
+{
+ int ret;
+
+ ret = mmc_add_attrs(card, mmc_sd_dev_attrs);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * Removes the sysfs entries added by mmc_sysfs_add().
+ */
+static void mmc_sd_sysfs_remove(struct mmc_host *host, struct mmc_card *card)
+{
+ mmc_remove_attrs(card, mmc_sd_dev_attrs);
+}
+
#ifdef CONFIG_MMC_UNSAFE_RESUME
/*
@@ -498,9 +576,7 @@ static void mmc_sd_resume(struct mmc_host *host)
err = mmc_sd_init_card(host, host->ocr, host->card);
if (err != MMC_ERR_NONE) {
- mmc_remove_card(host->card);
- host->card = NULL;
-
+ mmc_sd_remove(host);
mmc_detach_bus(host);
}
@@ -517,6 +593,8 @@ static void mmc_sd_resume(struct mmc_host *host)
static const struct mmc_bus_ops mmc_sd_ops = {
.remove = mmc_sd_remove,
.detect = mmc_sd_detect,
+ .sysfs_add = mmc_sd_sysfs_add,
+ .sysfs_remove = mmc_sd_sysfs_remove,
.suspend = mmc_sd_suspend,
.resume = mmc_sd_resume,
};
@@ -568,7 +646,7 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr)
mmc_release_host(host);
- err = mmc_register_card(host->card);
+ err = mmc_add_card(host->card);
if (err)
goto reclaim_host;
diff --git a/drivers/mmc/core/sysfs.c b/drivers/mmc/core/sysfs.c
index 843b1fbba55..00a97e70f91 100644
--- a/drivers/mmc/core/sysfs.c
+++ b/drivers/mmc/core/sysfs.c
@@ -2,6 +2,7 @@
* linux/drivers/mmc/core/sysfs.c
*
* Copyright (C) 2003 Russell King, All Rights Reserved.
+ * Copyright 2007 Pierre Ossman
*
* 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
@@ -9,352 +10,34 @@
*
* MMC sysfs/driver model support.
*/
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/device.h>
-#include <linux/idr.h>
-#include <linux/workqueue.h>
#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
#include "sysfs.h"
-#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev)
-#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
-#define cls_dev_to_mmc_host(d) container_of(d, struct mmc_host, class_dev)
-
-#define MMC_ATTR(name, fmt, args...) \
-static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
-{ \
- struct mmc_card *card = dev_to_mmc_card(dev); \
- return sprintf(buf, fmt, args); \
-}
-
-MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
- card->raw_cid[2], card->raw_cid[3]);
-MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
- card->raw_csd[2], card->raw_csd[3]);
-MMC_ATTR(scr, "%08x%08x\n", card->raw_scr[0], card->raw_scr[1]);
-MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
-MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
-MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
-MMC_ATTR(name, "%s\n", card->cid.prod_name);
-MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
-MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
-
-#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
-
-static struct device_attribute mmc_dev_attrs[] = {
- MMC_ATTR_RO(cid),
- MMC_ATTR_RO(csd),
- MMC_ATTR_RO(date),
- MMC_ATTR_RO(fwrev),
- MMC_ATTR_RO(hwrev),
- MMC_ATTR_RO(manfid),
- MMC_ATTR_RO(name),
- MMC_ATTR_RO(oemid),
- MMC_ATTR_RO(serial),
- __ATTR_NULL
-};
-
-static struct device_attribute mmc_dev_attr_scr = MMC_ATTR_RO(scr);
-
-
-static void mmc_release_card(struct device *dev)
-{
- struct mmc_card *card = dev_to_mmc_card(dev);
-
- kfree(card);
-}
-
-/*
- * This currently matches any MMC driver to any MMC card - drivers
- * themselves make the decision whether to drive this card in their
- * probe method.
- */
-static int mmc_bus_match(struct device *dev, struct device_driver *drv)
-{
- return 1;
-}
-
-static int
-mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
- int buf_size)
-{
- struct mmc_card *card = dev_to_mmc_card(dev);
- char ccc[13];
- int retval = 0, i = 0, length = 0;
-
-#define add_env(fmt,val) do { \
- retval = add_uevent_var(envp, num_envp, &i, \
- buf, buf_size, &length, \
- fmt, val); \
- if (retval) \
- return retval; \
-} while (0);
-
- for (i = 0; i < 12; i++)
- ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
- ccc[12] = '\0';
-
- add_env("MMC_CCC=%s", ccc);
- add_env("MMC_MANFID=%06x", card->cid.manfid);
- add_env("MMC_NAME=%s", mmc_card_name(card));
- add_env("MMC_OEMID=%04x", card->cid.oemid);
-#undef add_env
- envp[i] = NULL;
-
- return 0;
-}
-
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
-{
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = dev_to_mmc_card(dev);
- int ret = 0;
-
- if (dev->driver && drv->suspend)
- ret = drv->suspend(card, state);
- return ret;
-}
-
-static int mmc_bus_resume(struct device *dev)
-{
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = dev_to_mmc_card(dev);
- int ret = 0;
-
- if (dev->driver && drv->resume)
- ret = drv->resume(card);
- return ret;
-}
-
-static int mmc_bus_probe(struct device *dev)
-{
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = dev_to_mmc_card(dev);
-
- return drv->probe(card);
-}
-
-static int mmc_bus_remove(struct device *dev)
-{
- struct mmc_driver *drv = to_mmc_driver(dev->driver);
- struct mmc_card *card = dev_to_mmc_card(dev);
-
- drv->remove(card);
-
- return 0;
-}
-
-static struct bus_type mmc_bus_type = {
- .name = "mmc",
- .dev_attrs = mmc_dev_attrs,
- .match = mmc_bus_match,
- .uevent = mmc_bus_uevent,
- .probe = mmc_bus_probe,
- .remove = mmc_bus_remove,
- .suspend = mmc_bus_suspend,
- .resume = mmc_bus_resume,
-};
-
-/**
- * mmc_register_driver - register a media driver
- * @drv: MMC media driver
- */
-int mmc_register_driver(struct mmc_driver *drv)
-{
- drv->drv.bus = &mmc_bus_type;
- return driver_register(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_register_driver);
-
-/**
- * mmc_unregister_driver - unregister a media driver
- * @drv: MMC media driver
- */
-void mmc_unregister_driver(struct mmc_driver *drv)
-{
- drv->drv.bus = &mmc_bus_type;
- driver_unregister(&drv->drv);
-}
-
-EXPORT_SYMBOL(mmc_unregister_driver);
-
-
-/*
- * Internal function. Initialise a MMC card structure.
- */
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
-{
- memset(card, 0, sizeof(struct mmc_card));
- card->host = host;
- device_initialize(&card->dev);
- card->dev.parent = mmc_classdev(host);
- card->dev.bus = &mmc_bus_type;
- card->dev.release = mmc_release_card;
-}
-
-/*
- * Internal function. Register a new MMC card with the driver model.
- */
-int mmc_register_card(struct mmc_card *card)
+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs)
{
- int ret;
+ int error = 0;
+ int i;
- snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
- "%s:%04x", mmc_hostname(card->host), card->rca);
-
- ret = device_add(&card->dev);
- if (ret == 0) {
- if (mmc_card_sd(card)) {
- ret = device_create_file(&card->dev, &mmc_dev_attr_scr);
- if (ret)
- device_del(&card->dev);
+ for (i = 0; attr_name(attrs[i]); i++) {
+ error = device_create_file(&card->dev, &attrs[i]);
+ if (error) {
+ while (--i >= 0)
+ device_remove_file(&card->dev, &attrs[i]);
+ break;
}
}
- if (ret == 0)
- mmc_card_set_present(card);
- return ret;
-}
-
-/*
- * Internal function. Unregister a new MMC card with the
- * driver model, and (eventually) free it.
- */
-void mmc_remove_card(struct mmc_card *card)
-{
- if (mmc_card_present(card)) {
- if (mmc_card_sd(card))
- device_remove_file(&card->dev, &mmc_dev_attr_scr);
-
- device_del(&card->dev);
- }
-
- put_device(&card->dev);
-}
-
-
-static void mmc_host_classdev_release(struct device *dev)
-{
- struct mmc_host *host = cls_dev_to_mmc_host(dev);
- kfree(host);
-}
-
-static struct class mmc_host_class = {
- .name = "mmc_host",
- .dev_release = mmc_host_classdev_release,
-};
-
-static DEFINE_IDR(mmc_host_idr);
-static DEFINE_SPINLOCK(mmc_host_lock);
-
-/*
- * Internal function. Allocate a new MMC host.
- */
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
-{
- struct mmc_host *host;
-
- host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
- if (host) {
- memset(host, 0, sizeof(struct mmc_host) + extra);
-
- host->parent = dev;
- host->class_dev.parent = dev;
- host->class_dev.class = &mmc_host_class;
- device_initialize(&host->class_dev);
- }
- return host;
+ return error;
}
-/*
- * Internal function. Register a new MMC host with the MMC class.
- */
-int mmc_add_host_sysfs(struct mmc_host *host)
+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs)
{
- int err;
-
- if (!idr_pre_get(&mmc_host_idr, GFP_KERNEL))
- return -ENOMEM;
-
- spin_lock(&mmc_host_lock);
- err = idr_get_new(&mmc_host_idr, host, &host->index);
- spin_unlock(&mmc_host_lock);
- if (err)
- return err;
-
- snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
- "mmc%d", host->index);
-
- return device_add(&host->class_dev);
-}
+ int i;
-/*
- * Internal function. Unregister a MMC host with the MMC class.
- */
-void mmc_remove_host_sysfs(struct mmc_host *host)
-{
- device_del(&host->class_dev);
-
- spin_lock(&mmc_host_lock);
- idr_remove(&mmc_host_idr, host->index);
- spin_unlock(&mmc_host_lock);
-}
-
-/*
- * Internal function. Free a MMC host.
- */
-void mmc_free_host_sysfs(struct mmc_host *host)
-{
- put_device(&host->class_dev);
-}
-
-static struct workqueue_struct *workqueue;
-
-/*
- * Internal function. Schedule delayed work in the MMC work queue.
- */
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay)
-{
- return queue_delayed_work(workqueue, work, delay);
-}
-
-/*
- * Internal function. Flush all scheduled work from the MMC work queue.
- */
-void mmc_flush_scheduled_work(void)
-{
- flush_workqueue(workqueue);
-}
-
-static int __init mmc_init(void)
-{
- int ret;
-
- workqueue = create_singlethread_workqueue("kmmcd");
- if (!workqueue)
- return -ENOMEM;
-
- ret = bus_register(&mmc_bus_type);
- if (ret == 0) {
- ret = class_register(&mmc_host_class);
- if (ret)
- bus_unregister(&mmc_bus_type);
- }
- return ret;
-}
-
-static void __exit mmc_exit(void)
-{
- class_unregister(&mmc_host_class);
- bus_unregister(&mmc_bus_type);
- destroy_workqueue(workqueue);
+ for (i = 0; attr_name(attrs[i]); i++)
+ device_remove_file(&card->dev, &attrs[i]);
}
-module_init(mmc_init);
-module_exit(mmc_exit);
diff --git a/drivers/mmc/core/sysfs.h b/drivers/mmc/core/sysfs.h
index 80e29b35828..4b8f670bd10 100644
--- a/drivers/mmc/core/sysfs.h
+++ b/drivers/mmc/core/sysfs.h
@@ -11,17 +11,16 @@
#ifndef _MMC_CORE_SYSFS_H
#define _MMC_CORE_SYSFS_H
-void mmc_init_card(struct mmc_card *card, struct mmc_host *host);
-int mmc_register_card(struct mmc_card *card);
-void mmc_remove_card(struct mmc_card *card);
+#define MMC_ATTR_FN(name, fmt, args...) \
+static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct mmc_card *card = container_of(dev, struct mmc_card, dev);\
+ return sprintf(buf, fmt, args); \
+}
-struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev);
-int mmc_add_host_sysfs(struct mmc_host *host);
-void mmc_remove_host_sysfs(struct mmc_host *host);
-void mmc_free_host_sysfs(struct mmc_host *host);
+#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
-int mmc_schedule_work(struct work_struct *work);
-int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay);
-void mmc_flush_scheduled_work(void);
+int mmc_add_attrs(struct mmc_card *card, struct device_attribute *attrs);
+void mmc_remove_attrs(struct mmc_card *card, struct device_attribute *attrs);
#endif
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index e37943c314c..28c881895ab 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -78,8 +78,6 @@
#define DRIVER_NAME "at91_mci"
-#undef SUPPORT_4WIRE
-
#define FL_SENT_COMMAND (1 << 0)
#define FL_SENT_STOP (1 << 1)
@@ -131,7 +129,7 @@ struct at91mci_host
/*
* Copy from sg to a dma block - used for transfers
*/
-static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
+static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
{
unsigned int len, i, size;
unsigned *dmabuf = host->buffer;
@@ -180,7 +178,7 @@ static inline void at91mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
/*
* Prepare a dma read
*/
-static void at91mci_pre_dma_read(struct at91mci_host *host)
+static void at91_mci_pre_dma_read(struct at91mci_host *host)
{
int i;
struct scatterlist *sg;
@@ -248,7 +246,7 @@ static void at91mci_pre_dma_read(struct at91mci_host *host)
/*
* Handle after a dma read
*/
-static void at91mci_post_dma_read(struct at91mci_host *host)
+static void at91_mci_post_dma_read(struct at91mci_host *host)
{
struct mmc_command *cmd;
struct mmc_data *data;
@@ -268,8 +266,6 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
}
while (host->in_use_index < host->transfer_index) {
- unsigned int *buffer;
-
struct scatterlist *sg;
pr_debug("finishing index %d\n", host->in_use_index);
@@ -280,29 +276,31 @@ static void at91mci_post_dma_read(struct at91mci_host *host)
dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
- /* Swap the contents of the buffer */
- buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
- pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
-
data->bytes_xfered += sg->length;
if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
+ unsigned int *buffer;
int index;
+ /* Swap the contents of the buffer */
+ buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
+ pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
+
for (index = 0; index < (sg->length / 4); index++)
buffer[index] = swab32(buffer[index]);
+
+ kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
}
- kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
flush_dcache_page(sg->page);
}
/* Is there another transfer to trigger? */
if (host->transfer_index < data->sg_len)
- at91mci_pre_dma_read(host);
+ at91_mci_pre_dma_read(host);
else {
+ at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
}
pr_debug("post dma read done\n");
@@ -323,7 +321,6 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
/* Now wait for cmd ready */
at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
cmd = host->cmd;
if (!cmd) return;
@@ -331,18 +328,53 @@ static void at91_mci_handle_transmitted(struct at91mci_host *host)
data = cmd->data;
if (!data) return;
+ if (cmd->data->flags & MMC_DATA_MULTI) {
+ pr_debug("multiple write : wait for BLKE...\n");
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
+ } else
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+
data->bytes_xfered = host->total_length;
}
+/*Handle after command sent ready*/
+static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
+{
+ if (!host->cmd)
+ return 1;
+ else if (!host->cmd->data) {
+ if (host->flags & FL_SENT_STOP) {
+ /*After multi block write, we must wait for NOTBUSY*/
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
+ } else return 1;
+ } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
+ /*After sendding multi-block-write command, start DMA transfer*/
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE);
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
+ }
+
+ /* command not completed, have to wait */
+ return 0;
+}
+
+
/*
* Enable the controller
*/
static void at91_mci_enable(struct at91mci_host *host)
{
+ unsigned int mr;
+
at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
- at91_mci_write(host, AT91_MCI_MR, AT91_MCI_PDCMODE | 0x34a);
+ mr = AT91_MCI_PDCMODE | 0x34a;
+
+ if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+ mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
+
+ at91_mci_write(host, AT91_MCI_MR, mr);
/* use Slot A or B (only one at same time) */
at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
@@ -358,9 +390,8 @@ static void at91_mci_disable(struct at91mci_host *host)
/*
* Send a command
- * return the interrupts to enable
*/
-static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
+static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
{
unsigned int cmdr, mr;
unsigned int block_length;
@@ -371,8 +402,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
host->cmd = cmd;
- /* Not sure if this is needed */
-#if 0
+ /* Needed for leaving busy state before CMD1 */
if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
pr_debug("Clearing timeout\n");
at91_mci_write(host, AT91_MCI_ARGR, 0);
@@ -382,7 +412,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
}
}
-#endif
+
cmdr = cmd->opcode;
if (mmc_resp_type(cmd) == MMC_RSP_NONE)
@@ -417,7 +447,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
blocks = 0;
}
- if (cmd->opcode == MMC_STOP_TRANSMISSION)
+ if (host->flags & FL_SENT_STOP)
cmdr |= AT91_MCI_TRCMD_STOP;
if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
@@ -439,50 +469,48 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
at91_mci_write(host, ATMEL_PDC_TCR, 0);
at91_mci_write(host, ATMEL_PDC_TNPR, 0);
at91_mci_write(host, ATMEL_PDC_TNCR, 0);
+ ier = AT91_MCI_CMDRDY;
+ } else {
+ /* zero block length and PDC mode */
+ mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
+ at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
- at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
- at91_mci_write(host, AT91_MCI_CMDR, cmdr);
- return AT91_MCI_CMDRDY;
- }
-
- mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff; /* zero block length and PDC mode */
- at91_mci_write(host, AT91_MCI_MR, mr | (block_length << 16) | AT91_MCI_PDCMODE);
-
- /*
- * Disable the PDC controller
- */
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
- if (cmdr & AT91_MCI_TRCMD_START) {
- data->bytes_xfered = 0;
- host->transfer_index = 0;
- host->in_use_index = 0;
- if (cmdr & AT91_MCI_TRDIR) {
- /*
- * Handle a read
- */
- host->buffer = NULL;
- host->total_length = 0;
-
- at91mci_pre_dma_read(host);
- ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
- }
- else {
- /*
- * Handle a write
- */
- host->total_length = block_length * blocks;
- host->buffer = dma_alloc_coherent(NULL,
- host->total_length,
- &host->physical_address, GFP_KERNEL);
-
- at91mci_sg_to_dma(host, data);
-
- pr_debug("Transmitting %d bytes\n", host->total_length);
+ /*
+ * Disable the PDC controller
+ */
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
- at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
- at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
- ier = AT91_MCI_TXBUFE;
+ if (cmdr & AT91_MCI_TRCMD_START) {
+ data->bytes_xfered = 0;
+ host->transfer_index = 0;
+ host->in_use_index = 0;
+ if (cmdr & AT91_MCI_TRDIR) {
+ /*
+ * Handle a read
+ */
+ host->buffer = NULL;
+ host->total_length = 0;
+
+ at91_mci_pre_dma_read(host);
+ ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
+ }
+ else {
+ /*
+ * Handle a write
+ */
+ host->total_length = block_length * blocks;
+ host->buffer = dma_alloc_coherent(NULL,
+ host->total_length,
+ &host->physical_address, GFP_KERNEL);
+
+ at91_mci_sg_to_dma(host, data);
+
+ pr_debug("Transmitting %d bytes\n", host->total_length);
+
+ at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
+ at91_mci_write(host, ATMEL_PDC_TCR, host->total_length / 4);
+ ier = AT91_MCI_CMDRDY;
+ }
}
}
@@ -497,39 +525,24 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
if (cmdr & AT91_MCI_TRCMD_START) {
if (cmdr & AT91_MCI_TRDIR)
at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
- else
- at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
}
- return ier;
-}
-
-/*
- * Wait for a command to complete
- */
-static void at91mci_process_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
- unsigned int ier;
-
- ier = at91_mci_send_command(host, cmd);
-
- pr_debug("setting ier to %08X\n", ier);
- /* Stop on errors or the required value */
+ /* Enable selected interrupts */
at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
}
/*
* Process the next step in the request
*/
-static void at91mci_process_next(struct at91mci_host *host)
+static void at91_mci_process_next(struct at91mci_host *host)
{
if (!(host->flags & FL_SENT_COMMAND)) {
host->flags |= FL_SENT_COMMAND;
- at91mci_process_command(host, host->request->cmd);
+ at91_mci_send_command(host, host->request->cmd);
}
else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
host->flags |= FL_SENT_STOP;
- at91mci_process_command(host, host->request->stop);
+ at91_mci_send_command(host, host->request->stop);
}
else
mmc_request_done(host->mmc, host->request);
@@ -538,7 +551,7 @@ static void at91mci_process_next(struct at91mci_host *host)
/*
* Handle a command that has been completed
*/
-static void at91mci_completed_command(struct at91mci_host *host)
+static void at91_mci_completed_command(struct at91mci_host *host)
{
struct mmc_command *cmd = host->cmd;
unsigned int status;
@@ -563,8 +576,7 @@ static void at91mci_completed_command(struct at91mci_host *host)
if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
- if ((status & AT91_MCI_RCRCE) &&
- ((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
+ if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
cmd->error = MMC_ERR_NONE;
}
else {
@@ -584,7 +596,7 @@ static void at91mci_completed_command(struct at91mci_host *host)
else
cmd->error = MMC_ERR_NONE;
- at91mci_process_next(host);
+ at91_mci_process_next(host);
}
/*
@@ -596,7 +608,7 @@ static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->request = mrq;
host->flags = 0;
- at91mci_process_next(host);
+ at91_mci_process_next(host);
}
/*
@@ -699,29 +711,33 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
at91_mci_handle_transmitted(host);
}
+ if (int_status & AT91_MCI_ENDRX) {
+ pr_debug("ENDRX\n");
+ at91_mci_post_dma_read(host);
+ }
+
if (int_status & AT91_MCI_RXBUFF) {
pr_debug("RX buffer full\n");
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+ at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
+ at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
+ completed = 1;
}
if (int_status & AT91_MCI_ENDTX)
pr_debug("Transmit has ended\n");
- if (int_status & AT91_MCI_ENDRX) {
- pr_debug("Receive has ended\n");
- at91mci_post_dma_read(host);
- }
-
if (int_status & AT91_MCI_NOTBUSY) {
pr_debug("Card is ready\n");
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_CMDRDY);
+ completed = 1;
}
if (int_status & AT91_MCI_DTIP)
pr_debug("Data transfer in progress\n");
- if (int_status & AT91_MCI_BLKE)
+ if (int_status & AT91_MCI_BLKE) {
pr_debug("Block transfer has ended\n");
+ completed = 1;
+ }
if (int_status & AT91_MCI_TXRDY)
pr_debug("Ready to transmit\n");
@@ -731,14 +747,14 @@ static irqreturn_t at91_mci_irq(int irq, void *devid)
if (int_status & AT91_MCI_CMDRDY) {
pr_debug("Command ready\n");
- completed = 1;
+ completed = at91_mci_handle_cmdrdy(host);
}
}
if (completed) {
pr_debug("Completed command\n");
at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
- at91mci_completed_command(host);
+ at91_mci_completed_command(host);
} else
at91_mci_write(host, AT91_MCI_IDR, int_status);
@@ -831,11 +847,11 @@ static int __init at91_mci_probe(struct platform_device *pdev)
host->bus_mode = 0;
host->board = pdev->dev.platform_data;
if (host->board->wire4) {
-#ifdef SUPPORT_4WIRE
- mmc->caps |= MMC_CAP_4_BIT_DATA;
-#else
- printk("AT91 MMC: 4 wire bus mode not supported by this driver - using 1 wire\n");
-#endif
+ if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+ mmc->caps |= MMC_CAP_4_BIT_DATA;
+ else
+ printk("AT91 MMC: 4 wire bus mode not supported"
+ " - using 1 wire\n");
}
/*
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index f967226d750..52b63f11ddd 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -76,8 +76,7 @@ const struct {
#endif
};
-#define AU1XMMC_CONTROLLER_COUNT \
- (sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0]))
+#define AU1XMMC_CONTROLLER_COUNT (ARRAY_SIZE(au1xmmc_card_table))
/* This array stores pointers for the hosts (used by the IRQ handler) */
struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 1914e65d4db..b0824a38f42 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -522,28 +522,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
}
if (status & OMAP_MMC_STAT_CARD_ERR) {
- if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
- u32 response = OMAP_MMC_READ(host, RSP6)
- | (OMAP_MMC_READ(host, RSP7) << 16);
- /* STOP sometimes sets must-ignore bits */
- if (!(response & (R1_CC_ERROR
- | R1_ILLEGAL_COMMAND
- | R1_COM_CRC_ERROR))) {
- end_command = 1;
- continue;
- }
- }
-
- dev_dbg(mmc_dev(host->mmc), "card status error (CMD%d)\n",
+ dev_dbg(mmc_dev(host->mmc),
+ "ignoring card status error (CMD%d)\n",
host->cmd->opcode);
- if (host->cmd) {
- host->cmd->error = MMC_ERR_FAILED;
- end_command = 1;
- }
- if (host->data) {
- host->data->error = MMC_ERR_FAILED;
- transfer_error = 1;
- }
+ end_command = 1;
}
/*
diff --git a/drivers/mmc/host/pxamci.h b/drivers/mmc/host/pxamci.h
index 1b163220df2..df17c281278 100644
--- a/drivers/mmc/host/pxamci.h
+++ b/drivers/mmc/host/pxamci.h
@@ -1,25 +1,3 @@
-#undef MMC_STRPCL
-#undef MMC_STAT
-#undef MMC_CLKRT
-#undef MMC_SPI
-#undef MMC_CMDAT
-#undef MMC_RESTO
-#undef MMC_RDTO
-#undef MMC_BLKLEN
-#undef MMC_NOB
-#undef MMC_PRTBUF
-#undef MMC_I_MASK
-#undef END_CMD_RES
-#undef PRG_DONE
-#undef DATA_TRAN_DONE
-#undef MMC_I_REG
-#undef MMC_CMD
-#undef MMC_ARGH
-#undef MMC_ARGL
-#undef MMC_RES
-#undef MMC_RXFIFO
-#undef MMC_TXFIFO
-
#define MMC_STRPCL 0x0000
#define STOP_CLOCK (1 << 0)
#define START_CLOCK (2 << 0)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a359efdd77e..10d15c39d00 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -70,6 +70,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE,
},
+ {
+ .vendor = PCI_VENDOR_ID_ENE,
+ .device = PCI_DEVICE_ID_ENE_CB712_SD_2,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE,
+ },
+
{ /* Generic SD host controller */
PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
},
@@ -1022,7 +1030,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
}
- intmask &= SDHCI_INT_BUS_POWER;
+ intmask &= ~SDHCI_INT_BUS_POWER;
if (intmask) {
printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 92055405cb3..451adcc52b3 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -1,10 +1,9 @@
#
# Makefile for the memory technology device drivers.
#
-# $Id: Makefile.common,v 1.7 2005/07/11 10:39:27 gleixner Exp $
# Core functionality.
-mtd-y := mtdcore.o
+mtd-y := mtdcore.o mtdsuper.o
mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
obj-$(CONFIG_MTD) += $(mtd-y)
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 78872c3f376..b96ac8e119d 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -84,7 +84,7 @@ static unsigned long __initdata doc_locations[] = {
#elif defined(CONFIG_MOMENCO_OCELOT)
0x2f000000,
0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
##else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index a4873ab84e6..e8f686f7a35 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -650,7 +650,7 @@ MODULE_DESCRIPTION(PMC551_VERSION);
*/
static int msize = 0;
#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
-static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE
+static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE;
#else
static int asize = 0;
#endif
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index b665e4ac220..f88ebc5b685 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -258,12 +258,6 @@ config MTD_TSUNAMI
help
Support for the flash chip on Tsunami TIG bus.
-config MTD_LASAT
- tristate "LASAT flash device"
- depends on LASAT && MTD_CFI
- help
- Support for the flash chips on the Lasat 100 and 200 boards.
-
config MTD_NETtel
tristate "CFI flash device on SnapGear/SecureEdge"
depends on X86 && MTD_PARTITIONS && MTD_JEDECPROBE
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 3acbb5d01ca..970b189271a 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -47,7 +47,6 @@ obj-$(CONFIG_MTD_OCELOT) += ocelot.o
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
obj-$(CONFIG_MTD_PCI) += pci.o
obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o
-obj-$(CONFIG_MTD_LASAT) += lasat.o
obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_IMPA7) += impa7.o
diff --git a/drivers/mtd/maps/lasat.c b/drivers/mtd/maps/lasat.c
deleted file mode 100644
index e3437632105..00000000000
--- a/drivers/mtd/maps/lasat.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Flash device on Lasat 100 and 200 boards
- *
- * (C) 2002 Brian Murphy <brian@murphy.dk>
- *
- * 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.
- *
- * $Id: lasat.c,v 1.9 2004/11/04 13:24:15 gleixner Exp $
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/lasat/lasat.h>
-
-static struct mtd_info *lasat_mtd;
-
-static struct mtd_partition partition_info[LASAT_MTD_LAST];
-static char *lasat_mtd_partnames[] = {"Bootloader", "Service", "Normal", "Filesystem", "Config"};
-
-static void lasat_set_vpp(struct map_info *map, int vpp)
-{
- if (vpp)
- *lasat_misc->flash_wp_reg |= 1 << lasat_misc->flash_wp_bit;
- else
- *lasat_misc->flash_wp_reg &= ~(1 << lasat_misc->flash_wp_bit);
-}
-
-static struct map_info lasat_map = {
- .name = "LASAT flash",
- .bankwidth = 4,
- .set_vpp = lasat_set_vpp
-};
-
-static int __init init_lasat(void)
-{
- int i;
- /* since we use AMD chips and set_vpp is not implimented
- * for these (yet) we still have to permanently enable flash write */
- printk(KERN_NOTICE "Unprotecting flash\n");
- ENABLE_VPP((&lasat_map));
-
- lasat_map.phys = lasat_flash_partition_start(LASAT_MTD_BOOTLOADER);
- lasat_map.virt = ioremap_nocache(
- lasat_map.phys, lasat_board_info.li_flash_size);
- lasat_map.size = lasat_board_info.li_flash_size;
-
- simple_map_init(&lasat_map);
-
- for (i=0; i < LASAT_MTD_LAST; i++)
- partition_info[i].name = lasat_mtd_partnames[i];
-
- lasat_mtd = do_map_probe("cfi_probe", &lasat_map);
-
- if (!lasat_mtd)
- lasat_mtd = do_map_probe("jedec_probe", &lasat_map);
-
- if (lasat_mtd) {
- u32 size, offset = 0;
-
- lasat_mtd->owner = THIS_MODULE;
-
- for (i=0; i < LASAT_MTD_LAST; i++) {
- size = lasat_flash_partition_size(i);
- partition_info[i].size = size;
- partition_info[i].offset = offset;
- offset += size;
- }
-
- add_mtd_partitions( lasat_mtd, partition_info, LASAT_MTD_LAST );
- return 0;
- }
-
- iounmap(lasat_map.virt);
- return -ENXIO;
-}
-
-static void __exit cleanup_lasat(void)
-{
- if (lasat_mtd) {
- del_mtd_partitions(lasat_mtd);
- map_destroy(lasat_mtd);
- }
- if (lasat_map.virt) {
- iounmap(lasat_map.virt);
- lasat_map.virt = 0;
- }
-}
-
-module_init(init_lasat);
-module_exit(cleanup_lasat);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Brian Murphy <brian@murphy.dk>");
-MODULE_DESCRIPTION("Lasat Safepipe/Masquerade MTD map driver");
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index 389fea28b9a..14ffb1a9302 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -16,7 +16,6 @@
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/major.h>
-#include <linux/root_dev.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
@@ -89,10 +88,6 @@ int __init uclinux_mtd_init(void)
uclinux_ram_mtdinfo = mtd;
add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS);
- printk("uclinux[mtd]: set %s to be root filesystem\n",
- uclinux_romfs[0].name);
- ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0);
-
return(0);
}
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
new file mode 100644
index 00000000000..aca33197120
--- /dev/null
+++ b/drivers/mtd/mtdsuper.c
@@ -0,0 +1,232 @@
+/* MTD-based superblock management
+ *
+ * Copyright © 2001-2007 Red Hat, Inc. All Rights Reserved.
+ * Written by: David Howells <dhowells@redhat.com>
+ * David Woodhouse <dwmw2@infradead.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.
+ */
+
+#include <linux/mtd/super.h>
+#include <linux/namei.h>
+#include <linux/ctype.h>
+
+/*
+ * compare superblocks to see if they're equivalent
+ * - they are if the underlying MTD device is the same
+ */
+static int get_sb_mtd_compare(struct super_block *sb, void *_mtd)
+{
+ struct mtd_info *mtd = _mtd;
+
+ if (sb->s_mtd == mtd) {
+ DEBUG(2, "MTDSB: Match on device %d (\"%s\")\n",
+ mtd->index, mtd->name);
+ return 1;
+ }
+
+ DEBUG(2, "MTDSB: No match, device %d (\"%s\"), device %d (\"%s\")\n",
+ sb->s_mtd->index, sb->s_mtd->name, mtd->index, mtd->name);
+ return 0;
+}
+
+/*
+ * mark the superblock by the MTD device it is using
+ * - set the device number to be the correct MTD block device for pesuperstence
+ * of NFS exports
+ */
+static int get_sb_mtd_set(struct super_block *sb, void *_mtd)
+{
+ struct mtd_info *mtd = _mtd;
+
+ sb->s_mtd = mtd;
+ sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
+ return 0;
+}
+
+/*
+ * get a superblock on an MTD-backed filesystem
+ */
+static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data,
+ struct mtd_info *mtd,
+ int (*fill_super)(struct super_block *, void *, int),
+ struct vfsmount *mnt)
+{
+ struct super_block *sb;
+ int ret;
+
+ sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd);
+ if (IS_ERR(sb))
+ goto out_error;
+
+ if (sb->s_root)
+ goto already_mounted;
+
+ /* fresh new superblock */
+ DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n",
+ mtd->index, mtd->name);
+
+ ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
+ if (ret < 0) {
+ up_write(&sb->s_umount);
+ deactivate_super(sb);
+ return ret;
+ }
+
+ /* go */
+ sb->s_flags |= MS_ACTIVE;
+ return simple_set_mnt(mnt, sb);
+
+ /* new mountpoint for an already mounted superblock */
+already_mounted:
+ DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n",
+ mtd->index, mtd->name);
+ ret = simple_set_mnt(mnt, sb);
+ goto out_put;
+
+out_error:
+ ret = PTR_ERR(sb);
+out_put:
+ put_mtd_device(mtd);
+ return ret;
+}
+
+/*
+ * get a superblock on an MTD-backed filesystem by MTD device number
+ */
+static int get_sb_mtd_nr(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data, int mtdnr,
+ int (*fill_super)(struct super_block *, void *, int),
+ struct vfsmount *mnt)
+{
+ struct mtd_info *mtd;
+
+ mtd = get_mtd_device(NULL, mtdnr);
+ if (IS_ERR(mtd)) {
+ DEBUG(0, "MTDSB: Device #%u doesn't appear to exist\n", mtdnr);
+ return PTR_ERR(mtd);
+ }
+
+ return get_sb_mtd_aux(fs_type, flags, dev_name, data, mtd, fill_super,
+ mnt);
+}
+
+/*
+ * set up an MTD-based superblock
+ */
+int get_sb_mtd(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data,
+ int (*fill_super)(struct super_block *, void *, int),
+ struct vfsmount *mnt)
+{
+ struct nameidata nd;
+ int mtdnr, ret;
+
+ if (!dev_name)
+ return -EINVAL;
+
+ DEBUG(2, "MTDSB: dev_name \"%s\"\n", dev_name);
+
+ /* the preferred way of mounting in future; especially when
+ * CONFIG_BLOCK=n - we specify the underlying MTD device by number or
+ * by name, so that we don't require block device support to be present
+ * in the kernel. */
+ if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
+ if (dev_name[3] == ':') {
+ struct mtd_info *mtd;
+
+ /* mount by MTD device name */
+ DEBUG(1, "MTDSB: mtd:%%s, name \"%s\"\n",
+ dev_name + 4);
+
+ for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
+ mtd = get_mtd_device(NULL, mtdnr);
+ if (!IS_ERR(mtd)) {
+ if (!strcmp(mtd->name, dev_name + 4))
+ return get_sb_mtd_aux(
+ fs_type, flags,
+ dev_name, data, mtd,
+ fill_super, mnt);
+
+ put_mtd_device(mtd);
+ }
+ }
+
+ printk(KERN_NOTICE "MTD:"
+ " MTD device with name \"%s\" not found.\n",
+ dev_name + 4);
+
+ } else if (isdigit(dev_name[3])) {
+ /* mount by MTD device number name */
+ char *endptr;
+
+ mtdnr = simple_strtoul(dev_name + 3, &endptr, 0);
+ if (!*endptr) {
+ /* It was a valid number */
+ DEBUG(1, "MTDSB: mtd%%d, mtdnr %d\n",
+ mtdnr);
+ return get_sb_mtd_nr(fs_type, flags,
+ dev_name, data,
+ mtdnr, fill_super, mnt);
+ }
+ }
+ }
+
+ /* try the old way - the hack where we allowed users to mount
+ * /dev/mtdblock$(n) but didn't actually _use_ the blockdev
+ */
+ ret = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
+
+ DEBUG(1, "MTDSB: path_lookup() returned %d, inode %p\n",
+ ret, nd.dentry ? nd.dentry->d_inode : NULL);
+
+ if (ret)
+ return ret;
+
+ ret = -EINVAL;
+
+ if (!S_ISBLK(nd.dentry->d_inode->i_mode))
+ goto out;
+
+ if (nd.mnt->mnt_flags & MNT_NODEV) {
+ ret = -EACCES;
+ goto out;
+ }
+
+ if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR)
+ goto not_an_MTD_device;
+
+ mtdnr = iminor(nd.dentry->d_inode);
+ path_release(&nd);
+
+ return get_sb_mtd_nr(fs_type, flags, dev_name, data, mtdnr, fill_super,
+ mnt);
+
+not_an_MTD_device:
+ if (!(flags & MS_SILENT))
+ printk(KERN_NOTICE
+ "MTD: Attempt to mount non-MTD device \"%s\"\n",
+ dev_name);
+out:
+ path_release(&nd);
+ return ret;
+
+}
+
+EXPORT_SYMBOL_GPL(get_sb_mtd);
+
+/*
+ * destroy an MTD-based superblock
+ */
+void kill_mtd_super(struct super_block *sb)
+{
+ generic_shutdown_super(sb);
+ put_mtd_device(sb->s_mtd);
+ sb->s_mtd = NULL;
+}
+
+EXPORT_SYMBOL_GPL(kill_mtd_super);
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index fe94ae9ae1f..e3744eb8ecc 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -101,7 +101,7 @@ static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
struct nand_chip *chip = mtd->priv;
if (ctrl & NAND_CTRL_CHANGE) {
- void __iomem *addr
+ void __iomem *addr;
unsigned char bits;
addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 595208f965a..17c868034aa 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -59,7 +59,7 @@ static unsigned long __initdata doc_locations[] = {
#elif defined(CONFIG_MOMENCO_OCELOT)
0x2f000000,
0xff000000,
-#elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
+#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index eb7d4d443de..082073acf20 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -81,7 +81,7 @@ __setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase);
*/
static struct mtd_partition partition_info_hi[] = {
{ .name = "PPChameleon HI Nand Flash",
- offset = 0,
+ .offset = 0,
.size = 128 * 1024 * 1024
}
};
@@ -424,9 +424,9 @@ static void __exit ppchameleonevb_cleanup(void)
/* Release iomaps */
this = (struct nand_chip *) &ppchameleon_mtd[1];
- iounmap((void *) this->IO_ADDR_R;
+ iounmap((void *) this->IO_ADDR_R);
this = (struct nand_chip *) &ppchameleonevb_mtd[1];
- iounmap((void *) this->IO_ADDR_R;
+ iounmap((void *) this->IO_ADDR_R);
/* Free the MTD device structure */
kfree (ppchameleon_mtd);
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index da1a22c1386..ab18343e58e 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -990,7 +990,7 @@ static void elmc_rcv_int(struct net_device *dev)
if (skb != NULL) {
skb_reserve(skb, 2); /* 16 byte alignment */
skb_put(skb,totlen);
- eth_copy_and_sum(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen,0);
+ skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index f26ca331615..6deb20fc7a0 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -324,7 +324,7 @@ static struct vortex_chip_info {
{"3c980C Python-T",
PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
{"3cSOHO100-TX Hurricane",
- PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+ PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
{"3c555 Laptop Hurricane",
PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, },
{"3c556 Laptop Tornado",
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index 0877fc372f4..e89ace109a5 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -333,9 +333,9 @@ static int lance_rx (struct net_device *dev)
skb_reserve (skb, 2); /* 16 byte align */
skb_put (skb, len); /* make room */
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
(unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
- len, 0);
+ len);
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
dev->last_rx = jiffies;
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index e8c9f27817b..807e6992e61 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -107,11 +107,6 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered mu
#define PFX DRV_NAME ": "
-#ifndef TRUE
-#define FALSE 0
-#define TRUE (!FALSE)
-#endif
-
#define CP_DEF_MSG_ENABLE (NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
NETIF_MSG_LINK)
@@ -435,20 +430,12 @@ static void cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
spin_lock_irqsave(&cp->lock, flags);
cp->vlgrp = grp;
- cp->cpcmd |= RxVlanOn;
- cpw16(CpCmd, cp->cpcmd);
- spin_unlock_irqrestore(&cp->lock, flags);
-}
-
-static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct cp_private *cp = netdev_priv(dev);
- unsigned long flags;
+ if (grp)
+ cp->cpcmd |= RxVlanOn;
+ else
+ cp->cpcmd &= ~RxVlanOn;
- spin_lock_irqsave(&cp->lock, flags);
- cp->cpcmd &= ~RxVlanOn;
cpw16(CpCmd, cp->cpcmd);
- vlan_group_set_device(cp->vlgrp, vid, NULL);
spin_unlock_irqrestore(&cp->lock, flags);
}
#endif /* CP_VLAN_TAG_USED */
@@ -669,7 +656,7 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
if (status & (TxOK | TxErr | TxEmpty | SWInt))
cp_tx(cp);
if (status & LinkChg)
- mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
spin_unlock(&cp->lock);
@@ -1196,7 +1183,7 @@ static int cp_open (struct net_device *dev)
goto err_out_hw;
netif_carrier_off(dev);
- mii_check_media(&cp->mii_if, netif_msg_link(cp), TRUE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
netif_start_queue(dev);
return 0;
@@ -1812,7 +1799,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem *regs;
resource_size_t pciaddr;
unsigned int addr_len, i, pci_using_dac;
- u8 pci_rev;
#ifndef MODULE
static int version_printed;
@@ -1820,13 +1806,11 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
printk("%s", version);
#endif
- pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
- pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev < 0x20) {
+ pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision < 0x20) {
dev_err(&pdev->dev,
"This (id %04x:%04x rev %02x) is not an 8139C+ compatible chip\n",
- pdev->vendor, pdev->device, pci_rev);
+ pdev->vendor, pdev->device, pdev->revision);
dev_err(&pdev->dev, "Try the \"8139too\" driver instead.\n");
return -ENODEV;
}
@@ -1944,7 +1928,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
#if CP_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register = cp_vlan_rx_register;
- dev->vlan_rx_kill_vid = cp_vlan_rx_kill_vid;
#endif
if (pci_using_dac)
@@ -2059,7 +2042,7 @@ static int cp_resume (struct pci_dev *pdev)
spin_lock_irqsave (&cp->lock, flags);
- mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
+ mii_check_media(&cp->mii_if, netif_msg_link(cp), false);
spin_unlock_irqrestore (&cp->lock, flags);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index a844b1fe2dc..327eaa7b499 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -931,7 +931,6 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
int i, addr_len, option;
void __iomem *ioaddr;
static int board_idx = -1;
- u8 pci_rev;
assert (pdev != NULL);
assert (ent != NULL);
@@ -949,13 +948,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
}
#endif
- pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
if (pdev->vendor == PCI_VENDOR_ID_REALTEK &&
- pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pci_rev >= 0x20) {
+ pdev->device == PCI_DEVICE_ID_REALTEK_8139 && pdev->revision >= 0x20) {
dev_info(&pdev->dev,
"This (id %04x:%04x rev %02x) is an enhanced 8139C+ chip\n",
- pdev->vendor, pdev->device, pci_rev);
+ pdev->vendor, pdev->device, pdev->revision);
dev_info(&pdev->dev,
"Use the \"8139cp\" driver for improved performance and stability.\n");
}
@@ -2017,7 +2014,7 @@ no_early_rx:
#if RX_BUF_IDX == 3
wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
#else
- eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+ skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
#endif
skb_put (skb, pkt_size);
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 414de5bd228..04ddec0f4c6 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -73,6 +73,9 @@ struct ei_device {
u32 *reg_offset; /* Register mapping table */
spinlock_t page_lock; /* Page register locks */
unsigned long priv; /* Private field to store bus IDs etc. */
+#ifdef AX88796_PLATFORM
+ unsigned char rxcr_base; /* default value for RXCR */
+#endif
};
/* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -86,11 +89,19 @@ struct ei_device {
/* Some generic ethernet register configurations. */
#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */
#define E8390_RX_IRQ_MASK 0x5
+
+#ifdef AX88796_PLATFORM
+#define E8390_RXCONFIG (ei_status.rxcr_base | 0x04)
+#define E8390_RXOFF (ei_status.rxcr_base | 0x20)
+#else
#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */
#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */
+#endif
+
#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */
#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */
+
/* Register accessed at EN_CMD, the 8390 base addr. */
#define E8390_STOP 0x01 /* Stop and reset the chip */
#define E8390_START 0x02 /* Start the chip, clear reset */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 1798a9f9fb2..d17d64eb706 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3,10 +3,7 @@
# Network device configuration
#
-menu "Network device support"
- depends on NET
-
-config NETDEVICES
+menuconfig NETDEVICES
default y if UML
bool "Network device support"
---help---
@@ -28,6 +25,14 @@ config NETDEVICES
# that for each of the symbols.
if NETDEVICES
+config NETDEVICES_MULTIQUEUE
+ bool "Netdevice multiple hardware queue support"
+ ---help---
+ Say Y here if you want to allow the network stack to use multiple
+ hardware TX queues on an ethernet device.
+
+ Most people will say N here.
+
config IFB
tristate "Intermediate Functional Block support"
depends on NET_CLS_ACT
@@ -77,6 +82,16 @@ config BONDING
To compile this driver as a module, choose M here: the module
will be called bonding.
+config MACVLAN
+ tristate "MAC-VLAN support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ ---help---
+ This allows one to create virtual interfaces that map packets to
+ or from specific MAC addresses to a particular interface.
+
+ To compile this driver as a module, choose M here: the module
+ will be called macvlan.
+
config EQUALIZER
tristate "EQL (serial line load balancing) support"
---help---
@@ -151,11 +166,9 @@ source "drivers/net/phy/Kconfig"
# Ethernet
#
-menu "Ethernet (10 or 100Mbit)"
- depends on !UML
-
-config NET_ETHERNET
+menuconfig NET_ETHERNET
bool "Ethernet (10 or 100Mbit)"
+ depends on !UML
---help---
Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common
type of Local Area Network (LAN) in universities and companies.
@@ -180,9 +193,10 @@ config NET_ETHERNET
kernel: saying N will just cause the configurator to skip all
the questions about Ethernet network cards. If unsure, say N.
+if NET_ETHERNET
+
config MII
tristate "Generic Media Independent Interface device support"
- depends on NET_ETHERNET
help
Most ethernet controllers have MII transceiver either as an external
or internal device. It is safe to say Y or M here even if your
@@ -190,7 +204,7 @@ config MII
config MACB
tristate "Atmel MACB support"
- depends on NET_ETHERNET && (AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263)
+ depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263
select MII
help
The Atmel MACB ethernet interface is found on many AT32 and AT91
@@ -201,9 +215,18 @@ config MACB
source "drivers/net/arm/Kconfig"
+config AX88796
+ tristate "ASIX AX88796 NE2000 clone support"
+ depends on ARM || MIPS
+ select CRC32
+ select MII
+ help
+ AX88796 driver, using platform bus to provide
+ chip detection and resources
+
config MACE
tristate "MACE (Power Mac ethernet) support"
- depends on NET_ETHERNET && PPC_PMAC && PPC32
+ depends on PPC_PMAC && PPC32
select CRC32
help
Power Macintoshes and clones with Ethernet built-in on the
@@ -226,7 +249,7 @@ config MACE_AAUI_PORT
config BMAC
tristate "BMAC (G3 ethernet) support"
- depends on NET_ETHERNET && PPC_PMAC && PPC32
+ depends on PPC_PMAC && PPC32
select CRC32
help
Say Y for support of BMAC Ethernet interfaces. These are used on G3
@@ -237,7 +260,7 @@ config BMAC
config ARIADNE
tristate "Ariadne support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
help
If you have a Village Tronic Ariadne Ethernet adapter, say Y.
Otherwise, say N.
@@ -247,7 +270,7 @@ config ARIADNE
config A2065
tristate "A2065 support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
If you have a Commodore A2065 Ethernet adapter, say Y. Otherwise,
@@ -258,7 +281,7 @@ config A2065
config HYDRA
tristate "Hydra support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
@@ -268,7 +291,7 @@ config HYDRA
config ZORRO8390
tristate "Zorro NS8390-based Ethernet support"
- depends on NET_ETHERNET && ZORRO
+ depends on ZORRO
select CRC32
help
This driver is for Zorro Ethernet cards using an NS8390-compatible
@@ -281,7 +304,7 @@ config ZORRO8390
config APNE
tristate "PCMCIA NE2000 support"
- depends on NET_ETHERNET && AMIGA_PCMCIA
+ depends on AMIGA_PCMCIA
select CRC32
help
If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise,
@@ -292,7 +315,7 @@ config APNE
config APOLLO_ELPLUS
tristate "Apollo 3c505 support"
- depends on NET_ETHERNET && APOLLO
+ depends on APOLLO
help
Say Y or M here if your Apollo has a 3Com 3c505 ISA Ethernet card.
If you don't have one made for Apollos, you can use one from a PC,
@@ -301,7 +324,7 @@ config APOLLO_ELPLUS
config MAC8390
bool "Macintosh NS 8390 based ethernet cards"
- depends on NET_ETHERNET && MAC
+ depends on MAC
select CRC32
help
If you want to include a driver to support Nubus or LC-PDS
@@ -311,7 +334,7 @@ config MAC8390
config MAC89x0
tristate "Macintosh CS89x0 based ethernet cards"
- depends on NET_ETHERNET && MAC
+ depends on MAC
---help---
Support for CS89x0 chipset based Ethernet cards. If you have a
Nubus or LC-PDS network (Ethernet) card of this type, say Y and
@@ -324,7 +347,7 @@ config MAC89x0
config MACSONIC
tristate "Macintosh SONIC based ethernet (onboard, NuBus, LC, CS)"
- depends on NET_ETHERNET && MAC
+ depends on MAC
---help---
Support for NatSemi SONIC based Ethernet devices. This includes
the onboard Ethernet in many Quadras as well as some LC-PDS,
@@ -338,7 +361,7 @@ config MACSONIC
config MACMACE
bool "Macintosh (AV) onboard MACE ethernet"
- depends on NET_ETHERNET && MAC
+ depends on MAC
select CRC32
help
Support for the onboard AMD 79C940 MACE Ethernet controller used in
@@ -348,7 +371,7 @@ config MACMACE
config MVME147_NET
tristate "MVME147 (Lance) Ethernet support"
- depends on NET_ETHERNET && MVME147
+ depends on MVME147
select CRC32
help
Support for the on-board Ethernet interface on the Motorola MVME147
@@ -358,7 +381,7 @@ config MVME147_NET
config MVME16x_NET
tristate "MVME16x Ethernet support"
- depends on NET_ETHERNET && MVME16x
+ depends on MVME16x
help
This is the driver for the Ethernet interface on the Motorola
MVME162, 166, 167, 172 and 177 boards. Say Y here to include the
@@ -367,7 +390,7 @@ config MVME16x_NET
config BVME6000_NET
tristate "BVME6000 Ethernet support"
- depends on NET_ETHERNET && BVME6000
+ depends on BVME6000
help
This is the driver for the Ethernet interface on BVME4000 and
BVME6000 VME boards. Say Y here to include the driver for this chip
@@ -376,7 +399,7 @@ config BVME6000_NET
config ATARILANCE
tristate "Atari Lance support"
- depends on NET_ETHERNET && ATARI
+ depends on ATARI
help
Say Y to include support for several Atari Ethernet adapters based
on the AMD Lance chipset: RieblCard (with or without battery), or
@@ -384,7 +407,7 @@ config ATARILANCE
config ATARI_BIONET
tristate "BioNet-100 support"
- depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
+ depends on ATARI && ATARI_ACSI && BROKEN
help
Say Y to include support for BioData's BioNet-100 Ethernet adapter
for the ACSI port. The driver works (has to work...) with a polled
@@ -392,7 +415,7 @@ config ATARI_BIONET
config ATARI_PAMSNET
tristate "PAMsNet support"
- depends on NET_ETHERNET && ATARI && ATARI_ACSI && BROKEN
+ depends on ATARI && ATARI_ACSI && BROKEN
help
Say Y to include support for the PAMsNet Ethernet adapter for the
ACSI port ("ACSI node"). The driver works (has to work...) with a
@@ -400,7 +423,7 @@ config ATARI_PAMSNET
config SUN3LANCE
tristate "Sun3/Sun3x on-board LANCE support"
- depends on NET_ETHERNET && (SUN3 || SUN3X)
+ depends on SUN3 || SUN3X
help
Most Sun3 and Sun3x motherboards (including the 3/50, 3/60 and 3/80)
featured an AMD Lance 10Mbit Ethernet controller on board; say Y
@@ -413,7 +436,7 @@ config SUN3LANCE
config SUN3_82586
bool "Sun3 on-board Intel 82586 support"
- depends on NET_ETHERNET && SUN3
+ depends on SUN3
help
This driver enables support for the on-board Intel 82586 based
Ethernet adapter found on Sun 3/1xx and 3/2xx motherboards. Note
@@ -422,7 +445,7 @@ config SUN3_82586
config HPLANCE
bool "HP on-board LANCE support"
- depends on NET_ETHERNET && DIO
+ depends on DIO
select CRC32
help
If you want to use the builtin "LANCE" Ethernet controller on an
@@ -430,21 +453,28 @@ config HPLANCE
config LASI_82596
tristate "Lasi ethernet"
- depends on NET_ETHERNET && GSC
+ depends on GSC
help
Say Y here to support the builtin Intel 82596 ethernet controller
found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
+config SNI_82596
+ tristate "SNI RM ethernet"
+ depends on NET_ETHERNET && SNI_RM
+ help
+ Say Y here to support the on-board Intel 82596 ethernet controller
+ built into SNI RM machines.
+
config MIPS_JAZZ_SONIC
tristate "MIPS JAZZ onboard SONIC Ethernet support"
- depends on NET_ETHERNET && MACH_JAZZ
+ depends on MACH_JAZZ
help
This is the driver for the onboard card of MIPS Magnum 4000,
Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
- depends on NET_ETHERNET && SOC_AU1X00
+ depends on SOC_AU1X00
select PHYLIB
select CRC32
help
@@ -453,11 +483,11 @@ config MIPS_AU1X00_ENET
config NET_SB1250_MAC
tristate "SB1250 Ethernet support"
- depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC
+ depends on SIBYTE_SB1xxx_SOC
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
- depends on NET_ETHERNET && PCI && SGI_IP27
+ depends on PCI && SGI_IP27
select CRC32
select MII
help
@@ -487,7 +517,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM
config MIPS_SIM_NET
tristate "MIPS simulator Network device"
- depends on NET_ETHERNET && MIPS_SIM
+ depends on MIPS_SIM
help
The MIPSNET device is a simple Ethernet network device which is
emulated by the MIPS Simulator.
@@ -495,11 +525,11 @@ config MIPS_SIM_NET
config SGI_O2MACE_ETH
tristate "SGI O2 MACE Fast Ethernet support"
- depends on NET_ETHERNET && SGI_IP32=y
+ depends on SGI_IP32=y
config STNIC
tristate "National DP83902AV support"
- depends on NET_ETHERNET && SUPERH
+ depends on SUPERH
select CRC32
help
Support for cards based on the National Semiconductor DP83902AV
@@ -511,7 +541,7 @@ config STNIC
config SUNLANCE
tristate "Sun LANCE support"
- depends on NET_ETHERNET && SBUS
+ depends on SBUS
select CRC32
help
This driver supports the "le" interface present on all 32-bit Sparc
@@ -524,7 +554,7 @@ config SUNLANCE
config HAPPYMEAL
tristate "Sun Happy Meal 10/100baseT support"
- depends on NET_ETHERNET && (SBUS || PCI)
+ depends on SBUS || PCI
select CRC32
help
This driver supports the "hme" interface present on most Ultra
@@ -537,7 +567,7 @@ config HAPPYMEAL
config SUNBMAC
tristate "Sun BigMAC 10/100baseT support (EXPERIMENTAL)"
- depends on NET_ETHERNET && SBUS && EXPERIMENTAL
+ depends on SBUS && EXPERIMENTAL
select CRC32
help
This driver supports the "be" interface available as an Sbus option.
@@ -548,7 +578,7 @@ config SUNBMAC
config SUNQE
tristate "Sun QuadEthernet support"
- depends on NET_ETHERNET && SBUS
+ depends on SBUS
select CRC32
help
This driver supports the "qe" 10baseT Ethernet device, available as
@@ -560,7 +590,7 @@ config SUNQE
config SUNGEM
tristate "Sun GEM support"
- depends on NET_ETHERNET && PCI
+ depends on PCI
select CRC32
help
Support for the Sun GEM chip, aka Sun GigabitEthernet/P 2.0. See also
@@ -568,7 +598,7 @@ config SUNGEM
config CASSINI
tristate "Sun Cassini support"
- depends on NET_ETHERNET && PCI
+ depends on PCI
select CRC32
help
Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
@@ -576,7 +606,7 @@ config CASSINI
config NET_VENDOR_3COM
bool "3COM cards"
- depends on NET_ETHERNET && (ISA || EISA || MCA || PCI)
+ depends on ISA || EISA || MCA || PCI
help
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -736,7 +766,7 @@ config TYPHOON
config LANCE
tristate "AMD LANCE and PCnet (AT1500 and NE2100) support"
- depends on NET_ETHERNET && ISA && ISA_DMA_API
+ depends on ISA && ISA_DMA_API
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@@ -748,7 +778,7 @@ config LANCE
config NET_VENDOR_SMC
bool "Western Digital/SMC cards"
- depends on NET_ETHERNET && (ISA || MCA || EISA || MAC)
+ depends on ISA || MCA || EISA || MAC
help
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
@@ -818,11 +848,27 @@ config ULTRA32
<file:Documentation/networking/net-modules.txt>. The module
will be called smc-ultra32.
+config SMC9194
+ tristate "SMC 9194 support"
+ depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
+ select CRC32
+ ---help---
+ This is support for the SMC9xxx based Ethernet cards. Choose this
+ option if you have a DELL laptop with the docking station, or
+ another SMC9192/9194 based chipset. Say Y if you want it compiled
+ into the kernel, and read the file
+ <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
+ available from <http://www.tldp.org/docs.html#howto>.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module
+ will be called smc9194.
+
config SMC91X
tristate "SMC 91C9x/91C1xxx support"
select CRC32
select MII
- depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN)
+ depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || SOC_AU1X00 || BFIN
help
This is a driver for SMC's 91x series of Ethernet chipsets,
including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -836,26 +882,10 @@ config SMC91X
module, say M here and read <file:Documentation/kbuild/modules.txt>
as well as <file:Documentation/networking/net-modules.txt>.
-config SMC9194
- tristate "SMC 9194 support"
- depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN)
- select CRC32
- ---help---
- This is support for the SMC9xxx based Ethernet cards. Choose this
- option if you have a DELL laptop with the docking station, or
- another SMC9192/9194 based chipset. Say Y if you want it compiled
- into the kernel, and read the file
- <file:Documentation/networking/smc9.txt> and the Ethernet-HOWTO,
- available from <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
- will be called smc9194.
-
config NET_NETX
tristate "NetX Ethernet support"
select MII
- depends on NET_ETHERNET && ARCH_NETX
+ depends on ARCH_NETX
help
This is support for the Hilscher netX builtin Ethernet ports
@@ -865,7 +895,7 @@ config NET_NETX
config DM9000
tristate "DM9000 support"
- depends on (ARM || MIPS) && NET_ETHERNET
+ depends on ARM || BLACKFIN || MIPS
select CRC32
select MII
---help---
@@ -879,7 +909,7 @@ config SMC911X
tristate "SMSC LAN911[5678] support"
select CRC32
select MII
- depends on NET_ETHERNET && ARCH_PXA
+ depends on ARCH_PXA
help
This is a driver for SMSC's LAN911x series of Ethernet chipsets
including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -893,7 +923,7 @@ config SMC911X
config NET_VENDOR_RACAL
bool "Racal-Interlan (Micom) NI cards"
- depends on NET_ETHERNET && ISA
+ depends on ISA
help
If you have a network (Ethernet) card belonging to this class, such
as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
@@ -945,7 +975,7 @@ source "drivers/net/tulip/Kconfig"
config AT1700
tristate "AT1700/1720 support (EXPERIMENTAL)"
- depends on NET_ETHERNET && (ISA || MCA_LEGACY) && EXPERIMENTAL
+ depends on (ISA || MCA_LEGACY) && EXPERIMENTAL
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@@ -958,7 +988,7 @@ config AT1700
config DEPCA
tristate "DEPCA, DE10x, DE200, DE201, DE202, DE422 support"
- depends on NET_ETHERNET && (ISA || EISA || MCA)
+ depends on ISA || EISA || MCA
select CRC32
---help---
If you have a network (Ethernet) card of this type, say Y and read
@@ -972,7 +1002,7 @@ config DEPCA
config HP100
tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
- depends on NET_ETHERNET && (ISA || EISA || PCI)
+ depends on ISA || EISA || PCI
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
@@ -984,7 +1014,7 @@ config HP100
config NET_ISA
bool "Other ISA cards"
- depends on NET_ETHERNET && ISA
+ depends on ISA
---help---
If your network (Ethernet) card hasn't been mentioned yet and its
bus system (that's the way the cards talks to the other components
@@ -1147,7 +1177,7 @@ config SEEQ8005
config NE2_MCA
tristate "NE/2 (ne2000 MCA version) support"
- depends on NET_ETHERNET && MCA_LEGACY
+ depends on MCA_LEGACY
select CRC32
help
If you have a network (Ethernet) card of this type, say Y and read
@@ -1160,7 +1190,7 @@ config NE2_MCA
config IBMLANA
tristate "IBM LAN Adapter/A support"
- depends on NET_ETHERNET && MCA && MCA_LEGACY
+ depends on MCA && MCA_LEGACY
---help---
This is a Micro Channel Ethernet adapter. You need to set
CONFIG_MCA to use this driver. It is both available as an in-kernel
@@ -1176,7 +1206,7 @@ config IBMLANA
config IBMVETH
tristate "IBM LAN Virtual Ethernet support"
- depends on NET_ETHERNET && PPC_PSERIES
+ depends on PPC_PSERIES
---help---
This driver supports virtual ethernet adapters on newer IBM iSeries
and pSeries systems.
@@ -1187,7 +1217,7 @@ config IBMVETH
config IBM_EMAC
tristate "PowerPC 4xx on-chip Ethernet support"
- depends on 4xx
+ depends on 4xx && !PPC_MERGE
help
This driver supports the PowerPC 4xx EMAC family of on-chip
Ethernet controllers.
@@ -1257,7 +1287,7 @@ config IBM_EMAC_TAH
config NET_PCI
bool "EISA, VLB, PCI and on board controllers"
- depends on NET_ETHERNET && (ISA || EISA || PCI)
+ depends on ISA || EISA || PCI
help
This is another class of network cards which attach directly to the
bus. If you have one of those, say Y and read the Ethernet-HOWTO,
@@ -1313,6 +1343,7 @@ config AMD8111_ETH
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module
will be called amd8111e.
+
config AMD8111E_NAPI
bool "Enable NAPI support"
depends on AMD8111_ETH
@@ -1778,7 +1809,7 @@ config SC92031
config NET_POCKET
bool "Pocket and portable adapters"
- depends on NET_ETHERNET && PARPORT
+ depends on PARPORT
---help---
Cute little network (Ethernet) devices which attach to the parallel
port ("pocket adapters"), commonly used with laptops. If you have
@@ -1847,14 +1878,14 @@ config DE620
config SGISEEQ
tristate "SGI Seeq ethernet controller support"
- depends on NET_ETHERNET && SGI_IP22
+ depends on SGI_IP22
help
Say Y here if you have an Seeq based Ethernet network card. This is
used in many Silicon Graphics machines.
config DECLANCE
tristate "DEC LANCE ethernet controller support"
- depends on NET_ETHERNET && MACH_DECSTATION
+ depends on MACH_DECSTATION
select CRC32
help
This driver is for the series of Ethernet controllers produced by
@@ -1884,7 +1915,7 @@ config FEC2
config NE_H8300
tristate "NE2000 compatible support for H8/300"
- depends on H8300 && NET_ETHERNET
+ depends on H8300
help
Say Y here if you want to use the NE2000 compatible
controller on the Renesas H8/300 processor.
@@ -1892,7 +1923,7 @@ config NE_H8300
source "drivers/net/fec_8xx/Kconfig"
source "drivers/net/fs_enet/Kconfig"
-endmenu
+endif # NET_ETHERNET
#
# Gigabit Ethernet
@@ -2101,7 +2132,7 @@ config SKGE
with better performance and more complete ethtool support.
It does not support the link failover and network management
- features that "portable" vendor supplied sk98lin driver does.
+ features available in the hardware.
This driver supports adapters based on the original Yukon chipset:
Marvell 88E8001, Belkin F5D5005, CNet GigaCard, DLink DGE-530T,
@@ -2114,7 +2145,7 @@ config SKGE
will be called skge. This is recommended.
config SKY2
- tristate "SysKonnect Yukon2 support (EXPERIMENTAL)"
+ tristate "SysKonnect Yukon2 support"
depends on PCI
select CRC32
---help---
@@ -2129,92 +2160,15 @@ config SKY2
To compile this driver as a module, choose M here: the module
will be called sky2. This is recommended.
-config SK98LIN
- tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)"
- depends on PCI
- ---help---
- Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx
- compliant Gigabit Ethernet Adapter.
+config SKY2_DEBUG
+ bool "Debugging interface"
+ depends on SKY2 && DEBUG_FS
+ help
+ This option adds the ability to dump driver state for debugging.
+ The file debugfs/sky2/ethX displays the state of the internal
+ transmit and receive rings.
- This driver supports the original Yukon chipset. This driver is
- deprecated and will be removed from the kernel in the near future,
- it has been replaced by the skge driver. skge is cleaner and
- seems to work better.
-
- This driver does not support the newer Yukon2 chipset. A separate
- driver, sky2, is provided to support Yukon2-based adapters.
-
- The following adapters are supported by this driver:
- - 3Com 3C940 Gigabit LOM Ethernet Adapter
- - 3Com 3C941 Gigabit LOM Ethernet Adapter
- - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter
- - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
- - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
- - EG1032 v2 Instant Gigabit Network Adapter
- - EG1064 v2 Instant Gigabit Network Adapter
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
- - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
- - Marvell RDK-8001 Adapter
- - Marvell RDK-8002 Adapter
- - Marvell RDK-8003 Adapter
- - Marvell RDK-8004 Adapter
- - Marvell RDK-8006 Adapter
- - Marvell RDK-8007 Adapter
- - Marvell RDK-8008 Adapter
- - Marvell RDK-8009 Adapter
- - Marvell RDK-8010 Adapter
- - Marvell RDK-8011 Adapter
- - Marvell RDK-8012 Adapter
- - Marvell RDK-8052 Adapter
- - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
- - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
- - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
- - SK-9521 10/100/1000Base-T Adapter
- - SK-9521 V2.0 10/100/1000Base-T Adapter
- - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T)
- - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter
- - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link)
- - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX)
- - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter
- - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link)
- - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX)
- - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link)
- - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition)
- - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter
- - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link)
- - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
- - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
- - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
- - SMC EZ Card 1000 (SMC9452TXV.2)
-
- The adapters support Jumbo Frames.
- The dual link adapters support link-failover and dual port features.
- Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support
- the scatter-gather functionality with sendfile(). Please refer to
- <file:Documentation/networking/sk98lin.txt> for more information about
- optional driver parameters.
- Questions concerning this driver may be addressed to:
- <linux@syskonnect.de>
-
- If you want to compile this driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/kbuild/modules.txt>. The module will
- be called sk98lin. This is recommended.
+ If unsure, say N.
config VIA_VELOCITY
tristate "VIA Velocity support"
@@ -2264,6 +2218,16 @@ config TSI108_ETH
To compile this driver as a module, choose M here: the module
will be called tsi108_eth.
+config GELIC_NET
+ tristate "PS3 Gigabit Ethernet driver"
+ depends on PPC_PS3
+ help
+ This driver supports the network device on the PS3 game
+ console. This driver has built-in support for Ethernet.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ps3_gelic.
+
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx || PPC_86xx
@@ -2280,6 +2244,7 @@ config GFAR_NAPI
config UCC_GETH
tristate "Freescale QE Gigabit Ethernet"
depends on QUICC_ENGINE
+ select PHYLIB
help
This driver supports the Gigabit Ethernet mode of the QUICC Engine,
which is available on some Freescale SOCs.
@@ -2302,7 +2267,7 @@ config UGETH_TX_ON_DEMAND
config MV643XX_ETH
tristate "MV-643XX Ethernet support"
- depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MV64X60 || MOMENCO_OCELOT_3 || (PPC_MULTIPLATFORM && PPC32)
+ depends on MV64360 || MV64X60 || (PPC_MULTIPLATFORM && PPC32)
select MII
help
This driver supports the gigabit Ethernet on the Marvell MV643XX
@@ -2837,6 +2802,19 @@ config PPPOATM
which can lead to bad results if the ATM peer loses state and
changes its encapsulation unilaterally.
+config PPPOL2TP
+ tristate "PPP over L2TP (EXPERIMENTAL)"
+ depends on EXPERIMENTAL && PPP
+ help
+ Support for PPP-over-L2TP socket family. L2TP is a protocol
+ used by ISPs and enterprises to tunnel PPP traffic over UDP
+ tunnels. L2TP is replacing PPTP for VPN uses.
+
+ This kernel component handles only L2TP data packets: a
+ userland daemon handles L2TP the control protocol (tunnel
+ and session setup). One such daemon is OpenL2TP
+ (http://openl2tp.sourceforge.net/).
+
config SLIP
tristate "SLIP (serial line) support"
---help---
@@ -2947,8 +2925,6 @@ config NETCONSOLE
If you want to log kernel messages over the network, enable this.
See <file:Documentation/networking/netconsole.txt> for details.
-endif #NETDEVICES
-
config NETPOLL
def_bool NETCONSOLE
@@ -2960,4 +2936,4 @@ config NETPOLL_TRAP
config NET_POLL_CONTROLLER
def_bool NETPOLL
-endmenu
+endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a77affa4f6e..c26b8674213 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -60,10 +60,11 @@ obj-$(CONFIG_TIGON3) += tg3.o
obj-$(CONFIG_BNX2) += bnx2.o
spidernet-y += spider_net.o spider_net_ethtool.o
obj-$(CONFIG_SPIDER_NET) += spidernet.o sungem_phy.o
+obj-$(CONFIG_GELIC_NET) += ps3_gelic.o
+ps3_gelic-objs += ps3_gelic_net.o
obj-$(CONFIG_TC35815) += tc35815.o
obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SKY2) += sky2.o
-obj-$(CONFIG_SK98LIN) += sk98lin/
obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
@@ -107,6 +108,7 @@ obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o
obj-$(CONFIG_B44) += b44.o
obj-$(CONFIG_FORCEDETH) += forcedeth.o
obj-$(CONFIG_NE_H8300) += ne-h8300.o
+obj-$(CONFIG_AX88796) += ax88796.o
obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
@@ -119,12 +121,14 @@ obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o
obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o
obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o
obj-$(CONFIG_PPPOE) += pppox.o pppoe.o
+obj-$(CONFIG_PPPOL2TP) += pppox.o pppol2tp.o
obj-$(CONFIG_SLIP) += slip.o
obj-$(CONFIG_SLHC) += slhc.o
obj-$(CONFIG_DUMMY) += dummy.o
obj-$(CONFIG_IFB) += ifb.o
+obj-$(CONFIG_MACVLAN) += macvlan.o
obj-$(CONFIG_DE600) += de600.o
obj-$(CONFIG_DE620) += de620.o
obj-$(CONFIG_LANCE) += lance.o
@@ -157,6 +161,7 @@ obj-$(CONFIG_ELPLUS) += 3c505.o
obj-$(CONFIG_AC3200) += ac3200.o 8390.o
obj-$(CONFIG_APRICOT) += 82596.o
obj-$(CONFIG_LASI_82596) += lasi_82596.o
+obj-$(CONFIG_SNI_82596) += sni_82596.o
obj-$(CONFIG_MVME16x_NET) += 82596.o
obj-$(CONFIG_BVME6000_NET) += 82596.o
obj-$(CONFIG_SC92031) += sc92031.o
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 81d5a374042..a45de6975bf 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -322,9 +322,9 @@ static int lance_rx (struct net_device *dev)
skb_reserve (skb, 2); /* 16 byte align */
skb_put (skb, len); /* make room */
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
(unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
- len, 0);
+ len);
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
dev->last_rx = jiffies;
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 7122b7ba8d6..b78a4e5ceeb 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -159,10 +159,6 @@ static struct pci_device_id acenic_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
-#ifndef SET_NETDEV_DEV
-#define SET_NETDEV_DEV(net, pdev) do{} while(0)
-#endif
-
#define ace_sync_irq(irq) synchronize_irq(irq)
#ifndef offset_in_page
@@ -480,12 +476,10 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
#if ACENIC_DO_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register = ace_vlan_rx_register;
- dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid;
#endif
- if (1) {
- dev->tx_timeout = &ace_watchdog;
- dev->watchdog_timeo = 5*HZ;
- }
+
+ dev->tx_timeout = &ace_watchdog;
+ dev->watchdog_timeo = 5*HZ;
dev->open = &ace_open;
dev->stop = &ace_close;
@@ -2283,19 +2277,6 @@ static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
ace_unmask_irq(dev);
local_irq_restore(flags);
}
-
-
-static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct ace_private *ap = netdev_priv(dev);
- unsigned long flags;
-
- local_irq_save(flags);
- ace_mask_irq(dev);
- vlan_group_set_device(ap->vlgrp, vid, NULL);
- ace_unmask_irq(dev);
- local_irq_restore(flags);
-}
#endif /* ACENIC_DO_VLAN */
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index 8ca8534d70b..60ed1837fa8 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -787,7 +787,6 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev);
static int read_eeprom_byte(struct net_device *dev, unsigned long offset);
#if ACENIC_DO_VLAN
static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp);
-static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
#endif
#endif /* _ACENIC_H_ */
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 675fe918421..a61b2f89fc3 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -155,7 +155,7 @@ This function will write into PHY registers.
*/
static int amd8111e_write_phy(struct amd8111e_priv* lp,int phy_id, int reg, u32 val)
{
- unsigned int repeat = REPEAT_CNT
+ unsigned int repeat = REPEAT_CNT;
void __iomem *mmio = lp->mmio;
unsigned int reg_val;
@@ -1728,15 +1728,8 @@ static void amd8111e_vlan_rx_register(struct net_device *dev, struct vlan_group
lp->vlgrp = grp;
spin_unlock_irq(&lp->lock);
}
-
-static void amd8111e_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct amd8111e_priv *lp = netdev_priv(dev);
- spin_lock_irq(&lp->lock);
- vlan_group_set_device(lp->vlgrp, vid, NULL);
- spin_unlock_irq(&lp->lock);
-}
#endif
+
static int amd8111e_enable_magicpkt(struct amd8111e_priv* lp)
{
writel( VAL1|MPPLBA, lp->mmio + CMD3);
@@ -1996,7 +1989,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
#if AMD8111E_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX ;
dev->vlan_rx_register =amd8111e_vlan_rx_register;
- dev->vlan_rx_kill_vid = amd8111e_vlan_rx_kill_vid;
#endif
lp = netdev_priv(dev);
@@ -2049,7 +2041,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
#if AMD8111E_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register =amd8111e_vlan_rx_register;
- dev->vlan_rx_kill_vid = amd8111e_vlan_rx_kill_vid;
#endif
/* Probe the external PHY */
amd8111e_probe_ext_phy(dev);
diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h
index 2007510c4eb..e65080a5994 100644
--- a/drivers/net/amd8111e.h
+++ b/drivers/net/amd8111e.h
@@ -615,7 +615,7 @@ typedef enum {
#define SSTATE 2
/* Assume contoller gets data 10 times the maximum processing time */
-#define REPEAT_CNT 10;
+#define REPEAT_CNT 10
/* amd8111e decriptor flag definitions */
typedef enum {
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index a241ae7855a..bc5a38a6705 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -746,7 +746,7 @@ static int ariadne_rx(struct net_device *dev)
skb_reserve(skb,2); /* 16 byte align */
skb_put(skb,pkt_len); /* Make room */
- eth_copy_and_sum(skb, (char *)priv->rx_buff[entry], pkt_len,0);
+ skb_copy_to_linear_data(skb, (char *)priv->rx_buff[entry], pkt_len);
skb->protocol=eth_type_trans(skb,dev);
#if 0
printk(KERN_DEBUG "RX pkt type 0x%04x from ",
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 678e4f48d36..5bf2d33887a 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -4,7 +4,7 @@
#
config ARM_AM79C961A
bool "ARM EBSA110 AM79C961A support"
- depends on NET_ETHERNET && ARM && ARCH_EBSA110
+ depends on ARM && ARCH_EBSA110
select CRC32
help
If you wish to compile a kernel for the EBSA-110, then you should
@@ -12,21 +12,21 @@ config ARM_AM79C961A
config ARM_ETHER1
tristate "Acorn Ether1 support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
help
If you have an Acorn system with one of these (AKA25) network cards,
you should say Y to this option if you wish to use it with Linux.
config ARM_ETHER3
tristate "Acorn/ANT Ether3 support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
help
If you have an Acorn system with one of these network cards, you
should say Y to this option if you wish to use it with Linux.
config ARM_ETHERH
tristate "I-cubed EtherH/ANT EtherM support"
- depends on NET_ETHERNET && ARM && ARCH_ACORN
+ depends on ARM && ARCH_ACORN
select CRC32
help
If you have an Acorn system with one of these network cards, you
@@ -34,7 +34,7 @@ config ARM_ETHERH
config ARM_AT91_ETHER
tristate "AT91RM9200 Ethernet support"
- depends on NET_ETHERNET && ARM && ARCH_AT91RM9200
+ depends on ARM && ARCH_AT91RM9200
select MII
help
If you wish to compile a kernel for the AT91RM9200 and enable
@@ -42,7 +42,7 @@ config ARM_AT91_ETHER
config EP93XX_ETH
tristate "EP93xx Ethernet support"
- depends on NET_ETHERNET && ARM && ARCH_EP93XX
+ depends on ARM && ARCH_EP93XX
help
This is a driver for the ethernet hardware included in EP93xx CPUs.
Say Y if you are building a kernel for EP93xx based devices.
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index 8f0d7ce503c..2143eeb7a2b 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -634,7 +634,7 @@ static void am79c961_poll_controller(struct net_device *dev)
{
unsigned long flags;
local_irq_save(flags);
- am79c961_interrupt(dev->irq, dev, NULL);
+ am79c961_interrupt(dev->irq, dev);
local_irq_restore(flags);
}
#endif
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 2438c5bff23..f6ece1d43f6 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -258,7 +258,7 @@ static int ep93xx_rx(struct net_device *dev, int *budget)
skb_reserve(skb, 2);
dma_sync_single(NULL, ep->descs->rdesc[entry].buf_addr,
length, DMA_FROM_DEVICE);
- eth_copy_and_sum(skb, ep->rx_buf[entry], length, 0);
+ skb_copy_to_linear_data(skb, ep->rx_buf[entry], length);
skb_put(skb, length);
skb->protocol = eth_type_trans(skb, dev);
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index 54714409a09..f7356374a2e 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -295,10 +295,7 @@ int if_up = 0;
/* Setup the DMA counter */
static void
-setup_dma (address, rw_flag, num_blocks)
- void *address;
- unsigned rw_flag;
- int num_blocks;
+setup_dma (void *address, unsigned rw_flag, int num_blocks)
{
WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI |
A1);
@@ -317,9 +314,7 @@ setup_dma (address, rw_flag, num_blocks)
/* Send the first byte of an command block */
static int
-send_first (target, byte)
- int target;
- unsigned char byte;
+send_first (int target, unsigned char byte)
{
rw = READ;
acsi_delay_end(COMMAND_DELAY);
@@ -338,10 +333,7 @@ send_first (target, byte)
/* Send the rest of an command block */
static int
-send_1_5 (lun, command, dma)
- int lun;
- unsigned char *command;
- int dma;
+send_1_5 (int lun, unsigned char *command, int dma)
{
int i, j;
@@ -371,8 +363,7 @@ get_status (void)
/* Calculate the number of received bytes */
static int
-calc_received (start_address)
- void *start_address;
+calc_received (void *start_address)
{
return (int)(
(((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW)
@@ -384,8 +375,7 @@ calc_received (start_address)
/* start() starts the PAM's DMA adaptor */
static void
-start (target)
- int target;
+start (int target)
{
send_first(target, START);
}
@@ -393,8 +383,7 @@ start (target)
/* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */
static int
-stop (target)
- int target;
+stop (int target)
{
int ret = -1;
unsigned char cmd_buffer[5];
@@ -415,8 +404,7 @@ bad:
/* testpkt() returns the number of received packets waiting in the queue */
static int
-testpkt(target)
- int target;
+testpkt(int target)
{
int ret = -1;
@@ -431,9 +419,7 @@ bad:
/* Please note: The buffer is for internal use only but must be defined! */
static int
-inquiry (target, buffer)
- int target;
- unsigned char *buffer;
+inquiry (int target, unsigned char *buffer)
{
int ret = -1;
unsigned char *vbuffer = phys_to_virt((unsigned long)buffer);
@@ -468,9 +454,7 @@ bad:
*/
static HADDR
-*read_hw_addr(target, buffer)
- int target;
- unsigned char *buffer;
+*read_hw_addr(int target, unsigned char *buffer)
{
HADDR *ret = 0;
unsigned char cmd_buffer[5];
@@ -491,9 +475,7 @@ bad:
}
static irqreturn_t
-pamsnet_intr(irq, data, fp)
- int irq;
- void *data;
+pamsnet_intr(int irq, void *data)
{
return IRQ_HANDLED;
}
@@ -501,9 +483,7 @@ pamsnet_intr(irq, data, fp)
/* receivepkt() loads a packet to a given buffer and returns its length */
static int
-receivepkt (target, buffer)
- int target;
- unsigned char *buffer;
+receivepkt (int target, unsigned char *buffer)
{
int ret = -1;
unsigned char cmd_buffer[5];
@@ -526,10 +506,7 @@ bad:
successfully */
static int
-sendpkt (target, buffer, length)
- int target;
- unsigned char *buffer;
- int length;
+sendpkt (int target, unsigned char *buffer, int length)
{
int ret = -1;
unsigned char cmd_buffer[5];
@@ -665,7 +642,8 @@ struct net_device * __init pamsnet_probe (int unit)
there is non-reboot way to recover if something goes wrong.
*/
static int
-pamsnet_open(struct net_device *dev) {
+pamsnet_open(struct net_device *dev)
+{
struct net_local *lp = netdev_priv(dev);
if (pamsnet_debug > 0)
@@ -694,7 +672,8 @@ pamsnet_open(struct net_device *dev) {
}
static int
-pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
+pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
struct net_local *lp = netdev_priv(dev);
unsigned long flags;
@@ -741,7 +720,8 @@ pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
/* We have a good packet(s), get it/them out of the buffers.
*/
static void
-pamsnet_poll_rx(struct net_device *dev) {
+pamsnet_poll_rx(struct net_device *dev)
+{
struct net_local *lp = netdev_priv(dev);
int boguscount;
int pkt_len;
@@ -816,7 +796,8 @@ pamsnet_poll_rx(struct net_device *dev) {
* passes them to the higher layers and restarts the timer.
*/
static void
-pamsnet_tick(unsigned long data) {
+pamsnet_tick(unsigned long data)
+{
struct net_device *dev = (struct net_device *)data;
struct net_local *lp = netdev_priv(dev);
@@ -832,7 +813,8 @@ pamsnet_tick(unsigned long data) {
/* The inverse routine to pamsnet_open().
*/
static int
-pamsnet_close(struct net_device *dev) {
+pamsnet_close(struct net_device *dev)
+{
struct net_local *lp = netdev_priv(dev);
if (pamsnet_debug > 0)
diff --git a/drivers/net/atl1/atl1.h b/drivers/net/atl1/atl1.h
index b1c6034e68f..df4c1a0071a 100644
--- a/drivers/net/atl1/atl1.h
+++ b/drivers/net/atl1/atl1.h
@@ -210,7 +210,6 @@ struct atl1_hw {
u16 phy_spd_default;
u16 dev_rev;
- u8 revision_id;
/* spi flash */
u8 flash_vendor;
diff --git a/drivers/net/atl1/atl1_main.c b/drivers/net/atl1/atl1_main.c
index 78cf00ff3d3..501919eb7f5 100644
--- a/drivers/net/atl1/atl1_main.c
+++ b/drivers/net/atl1/atl1_main.c
@@ -118,10 +118,6 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
{
struct atl1_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
- struct pci_dev *pdev = adapter->pdev;
-
- /* PCI config space info */
- pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
@@ -634,14 +630,13 @@ static void atl1_intr_tx(struct atl1_adapter *adapter)
struct atl1_buffer *buffer_info;
u16 sw_tpd_next_to_clean;
u16 cmb_tpd_next_to_clean;
- u8 update = 0;
sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean);
cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx);
while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) {
struct tx_packet_desc *tpd;
- update = 1;
+
tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean);
buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean];
if (buffer_info->dma) {
@@ -1229,39 +1224,9 @@ static void atl1_vlan_rx_register(struct net_device *netdev,
spin_unlock_irqrestore(&adapter->lock, flags);
}
-/* FIXME: justify or remove -- CHS */
-static void atl1_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
- /* We don't do Vlan filtering */
- return;
-}
-
-/* FIXME: this looks wrong too -- CHS */
-static void atl1_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
- struct atl1_adapter *adapter = netdev_priv(netdev);
- unsigned long flags;
-
- spin_lock_irqsave(&adapter->lock, flags);
- /* atl1_irq_disable(adapter); */
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
- /* atl1_irq_enable(adapter); */
- spin_unlock_irqrestore(&adapter->lock, flags);
- /* We don't do Vlan filtering */
- return;
-}
-
static void atl1_restore_vlan(struct atl1_adapter *adapter)
{
atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp);
- if (adapter->vlgrp) {
- u16 vid;
- for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) {
- if (!vlan_group_get_device(adapter->vlgrp, vid))
- continue;
- atl1_vlan_rx_add_vid(adapter->netdev, vid);
- }
- }
}
static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring)
@@ -2203,8 +2168,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
netdev->poll_controller = atl1_poll_controller;
#endif
netdev->vlan_rx_register = atl1_vlan_rx_register;
- netdev->vlan_rx_add_vid = atl1_vlan_rx_add_vid;
- netdev->vlan_rx_kill_vid = atl1_vlan_rx_kill_vid;
+
netdev->ethtool_ops = &atl1_ethtool_ops;
adapter->bd_number = cards_found;
adapter->pci_using_64 = pci_using_64;
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index c39ab803c5d..e86b3691765 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -34,7 +34,7 @@
*
*
*/
-
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -1205,8 +1205,8 @@ static int au1000_rx(struct net_device *dev)
continue;
}
skb_reserve(skb, 2); /* 16 byte IP header align */
- eth_copy_and_sum(skb,
- (unsigned char *)pDB->vaddr, frmlen, 0);
+ skb_copy_to_linear_data(skb,
+ (unsigned char *)pDB->vaddr, frmlen);
skb_put(skb, frmlen);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb); /* pass the packet to upper layers */
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
new file mode 100644
index 00000000000..1d882360b34
--- /dev/null
+++ b/drivers/net/ax88796.c
@@ -0,0 +1,952 @@
+/* drivers/net/ax88796.c
+ *
+ * Copyright 2005,2007 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Asix AX88796 10/100 Ethernet controller support
+ * Based on ne.c, by Donald Becker, et-al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+#include <net/ax88796.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+static int phy_debug = 0;
+
+/* Rename the lib8390.c functions to show that they are in this driver */
+#define __ei_open ax_ei_open
+#define __ei_close ax_ei_close
+#define __ei_poll ax_ei_poll
+#define __ei_tx_timeout ax_ei_tx_timeout
+#define __ei_interrupt ax_ei_interrupt
+#define ____alloc_ei_netdev ax__alloc_ei_netdev
+#define __NS8390_init ax_NS8390_init
+
+/* force unsigned long back to 'void __iomem *' */
+#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
+
+#define ei_inb(_a) readb(ax_convert_addr(_a))
+#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
+
+#define ei_inb_p(_a) ei_inb(_a)
+#define ei_outb_p(_v, _a) ei_outb(_v, _a)
+
+/* define EI_SHIFT() to take into account our register offsets */
+#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
+
+/* Ensure we have our RCR base value */
+#define AX88796_PLATFORM
+
+static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
+
+#include "lib8390.c"
+
+#define DRV_NAME "ax88796"
+#define DRV_VERSION "1.00"
+
+/* from ne.c */
+#define NE_CMD EI_SHIFT(0x00)
+#define NE_RESET EI_SHIFT(0x1f)
+#define NE_DATAPORT EI_SHIFT(0x10)
+
+#define NE1SM_START_PG 0x20 /* First page of TX buffer */
+#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
+#define NESM_START_PG 0x40 /* First page of TX buffer */
+#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
+
+/* device private data */
+
+struct ax_device {
+ struct timer_list mii_timer;
+ spinlock_t mii_lock;
+ struct mii_if_info mii;
+
+ u32 msg_enable;
+ void __iomem *map2;
+ struct platform_device *dev;
+ struct resource *mem;
+ struct resource *mem2;
+ struct ax_plat_data *plat;
+
+ unsigned char running;
+ unsigned char resume_open;
+
+ u32 reg_offsets[0x20];
+};
+
+static inline struct ax_device *to_ax_dev(struct net_device *dev)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ return (struct ax_device *)(ei_local+1);
+}
+
+/* ax_initial_check
+ *
+ * do an initial probe for the card to check wether it exists
+ * and is functional
+ */
+
+static int ax_initial_check(struct net_device *dev)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ void __iomem *ioaddr = ei_local->mem;
+ int reg0;
+ int regd;
+
+ reg0 = ei_inb(ioaddr);
+ if (reg0 == 0xFF)
+ return -ENODEV;
+
+ ei_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+ regd = ei_inb(ioaddr + 0x0d);
+ ei_outb(0xff, ioaddr + 0x0d);
+ ei_outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+ ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+ if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
+ ei_outb(reg0, ioaddr);
+ ei_outb(regd, ioaddr + 0x0d); /* Restore the old values. */
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/* Hard reset the card. This used to pause for the same period that a
+ 8390 reset command required, but that shouldn't be necessary. */
+
+static void ax_reset_8390(struct net_device *dev)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ unsigned long reset_start_time = jiffies;
+ void __iomem *addr = (void __iomem *)dev->base_addr;
+
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+ ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
+
+ ei_status.txing = 0;
+ ei_status.dmaing = 0;
+
+ /* This check _should_not_ be necessary, omit eventually. */
+ while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
+ if (jiffies - reset_start_time > 2*HZ/100) {
+ printk(KERN_WARNING "%s: %s did not complete.\n",
+ __FUNCTION__, dev->name);
+ break;
+ }
+ }
+
+ ei_outb(ENISR_RESET, addr + EN0_ISR); /* Ack intr. */
+}
+
+
+static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+ int ring_page)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ void __iomem *nic_base = ei_local->mem;
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing) {
+ printk(KERN_EMERG "%s: DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n",
+ dev->name, __FUNCTION__,
+ ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+ ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+ ei_outb(0, nic_base + EN0_RCNTHI);
+ ei_outb(0, nic_base + EN0_RSARLO); /* On page boundary */
+ ei_outb(ring_page, nic_base + EN0_RSARHI);
+ ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ if (ei_status.word16)
+ readsw(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+ else
+ readsb(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+ ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
+
+ le16_to_cpus(&hdr->count);
+}
+
+
+/* Block input and output, similar to the Crynwr packet driver. If you
+ are porting to a new ethercard, look at the packet driver source for hints.
+ The NEx000 doesn't share the on-board packet memory -- you have to put
+ the packet out through the "remote DMA" dataport using ei_outb. */
+
+static void ax_block_input(struct net_device *dev, int count,
+ struct sk_buff *skb, int ring_offset)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ void __iomem *nic_base = ei_local->mem;
+ char *buf = skb->data;
+
+ if (ei_status.dmaing) {
+ printk(KERN_EMERG "%s: DMAing conflict in ax_block_input "
+ "[DMAstat:%d][irqlock:%d].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+
+ ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+ ei_outb(count >> 8, nic_base + EN0_RCNTHI);
+ ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
+ ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
+ ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ if (ei_status.word16) {
+ readsw(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);
+ }
+
+ ei_status.dmaing &= ~1;
+}
+
+static void ax_block_output(struct net_device *dev, int count,
+ const unsigned char *buf, const int start_page)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ void __iomem *nic_base = ei_local->mem;
+ unsigned long dma_start;
+
+ /* Round the count up for word writes. Do we need to do this?
+ What effect will an odd byte count have on the 8390?
+ I should check someday. */
+
+ if (ei_status.word16 && (count & 0x01))
+ count++;
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing) {
+ printk(KERN_EMERG "%s: DMAing conflict in %s."
+ "[DMAstat:%d][irqlock:%d]\n",
+ dev->name, __FUNCTION__,
+ ei_status.dmaing, ei_status.irqlock);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+ /* We should already be in page 0, but to be safe... */
+ ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+ ei_outb(ENISR_RDC, nic_base + EN0_ISR);
+
+ /* Now the normal output. */
+ ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+ ei_outb(count >> 8, nic_base + EN0_RCNTHI);
+ ei_outb(0x00, nic_base + EN0_RSARLO);
+ ei_outb(start_page, nic_base + EN0_RSARHI);
+
+ ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+ if (ei_status.word16) {
+ writesw(nic_base + NE_DATAPORT, buf, count>>1);
+ } else {
+ writesb(nic_base + NE_DATAPORT, buf, count);
+ }
+
+ dma_start = jiffies;
+
+ while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
+ if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
+ printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+ ax_reset_8390(dev);
+ ax_NS8390_init(dev,1);
+ break;
+ }
+ }
+
+ ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
+ return;
+}
+
+/* definitions for accessing MII/EEPROM interface */
+
+#define AX_MEMR EI_SHIFT(0x14)
+#define AX_MEMR_MDC (1<<0)
+#define AX_MEMR_MDIR (1<<1)
+#define AX_MEMR_MDI (1<<2)
+#define AX_MEMR_MDO (1<<3)
+#define AX_MEMR_EECS (1<<4)
+#define AX_MEMR_EEI (1<<5)
+#define AX_MEMR_EEO (1<<6)
+#define AX_MEMR_EECLK (1<<7)
+
+/* ax_mii_ei_outbits
+ *
+ * write the specified set of bits to the phy
+*/
+
+static void
+ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len)
+{
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
+ unsigned int memr;
+
+ /* clock low, data to output mode */
+ memr = ei_inb(memr_addr);
+ memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR);
+ ei_outb(memr, memr_addr);
+
+ for (len--; len >= 0; len--) {
+ if (bits & (1 << len))
+ memr |= AX_MEMR_MDO;
+ else
+ memr &= ~AX_MEMR_MDO;
+
+ ei_outb(memr, memr_addr);
+
+ /* clock high */
+
+ ei_outb(memr | AX_MEMR_MDC, memr_addr);
+ udelay(1);
+
+ /* clock low */
+ ei_outb(memr, memr_addr);
+ }
+
+ /* leaves the clock line low, mdir input */
+ memr |= AX_MEMR_MDIR;
+ ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR);
+}
+
+/* ax_phy_ei_inbits
+ *
+ * read a specified number of bits from the phy
+*/
+
+static unsigned int
+ax_phy_ei_inbits(struct net_device *dev, int no)
+{
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
+ unsigned int memr;
+ unsigned int result = 0;
+
+ /* clock low, data to input mode */
+ memr = ei_inb(memr_addr);
+ memr &= ~AX_MEMR_MDC;
+ memr |= AX_MEMR_MDIR;
+ ei_outb(memr, memr_addr);
+
+ for (no--; no >= 0; no--) {
+ ei_outb(memr | AX_MEMR_MDC, memr_addr);
+
+ udelay(1);
+
+ if (ei_inb(memr_addr) & AX_MEMR_MDI)
+ result |= (1<<no);
+
+ ei_outb(memr, memr_addr);
+ }
+
+ return result;
+}
+
+/* ax_phy_issueaddr
+ *
+ * use the low level bit shifting routines to send the address
+ * and command to the specified phy
+*/
+
+static void
+ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc)
+{
+ if (phy_debug)
+ pr_debug("%s: dev %p, %04x, %04x, %d\n",
+ __FUNCTION__, dev, phy_addr, reg, opc);
+
+ ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */
+ ax_mii_ei_outbits(dev, 1, 2); /* frame-start */
+ ax_mii_ei_outbits(dev, opc, 2); /* op code */
+ ax_mii_ei_outbits(dev, phy_addr, 5); /* phy address */
+ ax_mii_ei_outbits(dev, reg, 5); /* reg address */
+}
+
+static int
+ax_phy_read(struct net_device *dev, int phy_addr, int reg)
+{
+ struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
+ unsigned long flags;
+ unsigned int result;
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+
+ ax_phy_issueaddr(dev, phy_addr, reg, 2);
+
+ result = ax_phy_ei_inbits(dev, 17);
+ result &= ~(3<<16);
+
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+ if (phy_debug)
+ pr_debug("%s: %04x.%04x => read %04x\n", __FUNCTION__,
+ phy_addr, reg, result);
+
+ return result;
+}
+
+static void
+ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
+{
+ struct ei_device *ei = (struct ei_device *) netdev_priv(dev);
+ unsigned long flags;
+
+ printk(KERN_DEBUG "%s: %p, %04x, %04x %04x\n",
+ __FUNCTION__, dev, phy_addr, reg, value);
+
+ spin_lock_irqsave(&ei->page_lock, flags);
+
+ ax_phy_issueaddr(dev, phy_addr, reg, 1);
+ ax_mii_ei_outbits(dev, 2, 2); /* send TA */
+ ax_mii_ei_outbits(dev, value, 16);
+
+ spin_unlock_irqrestore(&ei->page_lock, flags);
+}
+
+static void ax_mii_expiry(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct ax_device *ax = to_ax_dev(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ax->mii_lock, flags);
+ mii_check_media(&ax->mii, netif_msg_link(ax), 0);
+ spin_unlock_irqrestore(&ax->mii_lock, flags);
+
+ if (ax->running) {
+ ax->mii_timer.expires = jiffies + HZ*2;
+ add_timer(&ax->mii_timer);
+ }
+}
+
+static int ax_open(struct net_device *dev)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ struct ei_device *ei_local = netdev_priv(dev);
+ int ret;
+
+ dev_dbg(&ax->dev->dev, "%s: open\n", dev->name);
+
+ ret = request_irq(dev->irq, ax_ei_interrupt, 0, dev->name, dev);
+ if (ret)
+ return ret;
+
+ ret = ax_ei_open(dev);
+ if (ret)
+ return ret;
+
+ /* turn the phy on (if turned off) */
+
+ ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17));
+ ax->running = 1;
+
+ /* start the MII timer */
+
+ init_timer(&ax->mii_timer);
+
+ ax->mii_timer.expires = jiffies+1;
+ ax->mii_timer.data = (unsigned long) dev;
+ ax->mii_timer.function = ax_mii_expiry;
+
+ add_timer(&ax->mii_timer);
+
+ return 0;
+}
+
+static int ax_close(struct net_device *dev)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ struct ei_device *ei_local = netdev_priv(dev);
+
+ dev_dbg(&ax->dev->dev, "%s: close\n", dev->name);
+
+ /* turn the phy off */
+
+ ei_outb(ax->plat->gpoc_val | (1<<6),
+ ei_local->mem + EI_SHIFT(0x17));
+
+ ax->running = 0;
+ wmb();
+
+ del_timer_sync(&ax->mii_timer);
+ ax_ei_close(dev);
+
+ free_irq(dev->irq, dev);
+ return 0;
+}
+
+static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ unsigned long flags;
+ int rc;
+
+ if (!netif_running(dev))
+ return -EINVAL;
+
+ spin_lock_irqsave(&ax->mii_lock, flags);
+ rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL);
+ spin_unlock_irqrestore(&ax->mii_lock, flags);
+
+ return rc;
+}
+
+/* ethtool ops */
+
+static void ax_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, ax->dev->name);
+}
+
+static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ax->mii_lock, flags);
+ mii_ethtool_gset(&ax->mii, cmd);
+ spin_lock_irqsave(&ax->mii_lock, flags);
+
+ return 0;
+}
+
+static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&ax->mii_lock, flags);
+ rc = mii_ethtool_sset(&ax->mii, cmd);
+ spin_lock_irqsave(&ax->mii_lock, flags);
+
+ return rc;
+}
+
+static int ax_nway_reset(struct net_device *dev)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ return mii_nway_restart(&ax->mii);
+}
+
+static u32 ax_get_link(struct net_device *dev)
+{
+ struct ax_device *ax = to_ax_dev(dev);
+ return mii_link_ok(&ax->mii);
+}
+
+static const struct ethtool_ops ax_ethtool_ops = {
+ .get_drvinfo = ax_get_drvinfo,
+ .get_settings = ax_get_settings,
+ .set_settings = ax_set_settings,
+ .nway_reset = ax_nway_reset,
+ .get_link = ax_get_link,
+ .get_perm_addr = ethtool_op_get_perm_addr,
+};
+
+/* setup code */
+
+static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
+{
+ void __iomem *ioaddr = ei_local->mem;
+ struct ax_device *ax = to_ax_dev(dev);
+
+ /* Select page 0*/
+ ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD);
+
+ /* set to byte access */
+ ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
+ ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
+}
+
+/* ax_init_dev
+ *
+ * initialise the specified device, taking care to note the MAC
+ * address it may already have (if configured), ensure
+ * the device is ready to be used by lib8390.c and registerd with
+ * the network layer.
+ */
+
+static int ax_init_dev(struct net_device *dev, int first_init)
+{
+ struct ei_device *ei_local = netdev_priv(dev);
+ struct ax_device *ax = to_ax_dev(dev);
+ void __iomem *ioaddr = ei_local->mem;
+ unsigned int start_page;
+ unsigned int stop_page;
+ int ret;
+ int i;
+
+ ret = ax_initial_check(dev);
+ if (ret)
+ goto err_out;
+
+ /* setup goes here */
+
+ ax_initial_setup(dev, ei_local);
+
+ /* read the mac from the card prom if we need it */
+
+ if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) {
+ unsigned char SA_prom[32];
+
+ for(i = 0; i < sizeof(SA_prom); i+=2) {
+ SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
+ SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT);
+ }
+
+ if (ax->plat->wordlength == 2)
+ for (i = 0; i < 16; i++)
+ SA_prom[i] = SA_prom[i+i];
+
+ memcpy(dev->dev_addr, SA_prom, 6);
+ }
+
+ if (ax->plat->wordlength == 2) {
+ /* We must set the 8390 for word mode. */
+ ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
+ start_page = NESM_START_PG;
+ stop_page = NESM_STOP_PG;
+ } else {
+ start_page = NE1SM_START_PG;
+ stop_page = NE1SM_STOP_PG;
+ }
+
+ /* load the mac-address from the device if this is the
+ * first time we've initialised */
+
+ if (first_init && ax->plat->flags & AXFLG_MAC_FROMDEV) {
+ ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+ ei_local->mem + E8390_CMD); /* 0x61 */
+
+ for (i = 0 ; i < ETHER_ADDR_LEN ; i++)
+ dev->dev_addr[i] = ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
+ }
+
+ ax_reset_8390(dev);
+
+ ei_status.name = "AX88796";
+ ei_status.tx_start_page = start_page;
+ ei_status.stop_page = stop_page;
+ ei_status.word16 = (ax->plat->wordlength == 2);
+ ei_status.rx_start_page = start_page + TX_PAGES;
+
+#ifdef PACKETBUF_MEMSIZE
+ /* Allow the packet buffer size to be overridden by know-it-alls. */
+ ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+ ei_status.reset_8390 = &ax_reset_8390;
+ ei_status.block_input = &ax_block_input;
+ ei_status.block_output = &ax_block_output;
+ ei_status.get_8390_hdr = &ax_get_8390_hdr;
+ ei_status.priv = 0;
+
+ dev->open = ax_open;
+ dev->stop = ax_close;
+ dev->do_ioctl = ax_ioctl;
+ dev->ethtool_ops = &ax_ethtool_ops;
+
+ ax->msg_enable = NETIF_MSG_LINK;
+ ax->mii.phy_id_mask = 0x1f;
+ ax->mii.reg_num_mask = 0x1f;
+ ax->mii.phy_id = 0x10; /* onboard phy */
+ ax->mii.force_media = 0;
+ ax->mii.full_duplex = 0;
+ ax->mii.mdio_read = ax_phy_read;
+ ax->mii.mdio_write = ax_phy_write;
+ ax->mii.dev = dev;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = ax_ei_poll;
+#endif
+ ax_NS8390_init(dev, 0);
+
+ if (first_init) {
+ printk("AX88796: %dbit, irq %d, %lx, MAC: ",
+ ei_status.word16 ? 16:8, dev->irq, dev->base_addr);
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ printk("%2.2x%c", dev->dev_addr[i],
+ (i < (ETHER_ADDR_LEN-1) ? ':' : ' '));
+
+ printk("\n");
+ }
+
+ ret = register_netdev(dev);
+ if (ret)
+ goto out_irq;
+
+ return 0;
+
+ out_irq:
+ /* cleanup irq */
+ free_irq(dev->irq, dev);
+ err_out:
+ return ret;
+}
+
+static int ax_remove(struct platform_device *_dev)
+{
+ struct net_device *dev = platform_get_drvdata(_dev);
+ struct ax_device *ax;
+
+ ax = to_ax_dev(dev);
+
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+
+ iounmap(ei_status.mem);
+ release_resource(ax->mem);
+ kfree(ax->mem);
+
+ if (ax->map2) {
+ iounmap(ax->map2);
+ release_resource(ax->mem2);
+ kfree(ax->mem2);
+ }
+
+ free_netdev(dev);
+
+ return 0;
+}
+
+/* ax_probe
+ *
+ * This is the entry point when the platform device system uses to
+ * notify us of a new device to attach to. Allocate memory, find
+ * the resources and information passed, and map the necessary registers.
+*/
+
+static int ax_probe(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct ax_device *ax;
+ struct resource *res;
+ size_t size;
+ int ret;
+
+ dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
+ if (dev == NULL)
+ return -ENOMEM;
+
+ /* ok, let's setup our device */
+ ax = to_ax_dev(dev);
+
+ memset(ax, 0, sizeof(struct ax_device));
+
+ spin_lock_init(&ax->mii_lock);
+
+ ax->dev = pdev;
+ ax->plat = pdev->dev.platform_data;
+ platform_set_drvdata(pdev, dev);
+
+ ei_status.rxcr_base = ax->plat->rcr_val;
+
+ /* find the platform resources */
+
+ dev->irq = platform_get_irq(pdev, 0);
+ if (dev->irq < 0) {
+ dev_err(&pdev->dev, "no IRQ specified\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no MEM specified\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ size = (res->end - res->start) + 1;
+
+ /* setup the register offsets from either the platform data
+ * or by using the size of the resource provided */
+
+ if (ax->plat->reg_offsets)
+ ei_status.reg_offset = ax->plat->reg_offsets;
+ else {
+ ei_status.reg_offset = ax->reg_offsets;
+ for (ret = 0; ret < 0x18; ret++)
+ ax->reg_offsets[ret] = (size / 0x18) * ret;
+ }
+
+ ax->mem = request_mem_region(res->start, size, pdev->name);
+ if (ax->mem == NULL) {
+ dev_err(&pdev->dev, "cannot reserve registers\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ ei_status.mem = ioremap(res->start, size);
+ dev->base_addr = (long)ei_status.mem;
+
+ if (ei_status.mem == NULL) {
+ dev_err(&pdev->dev, "Cannot ioremap area (%08zx,%08zx)\n",
+ res->start, res->end);
+
+ ret = -ENXIO;
+ goto exit_req;
+ }
+
+ /* look for reset area */
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res == NULL) {
+ if (!ax->plat->reg_offsets) {
+ for (ret = 0; ret < 0x20; ret++)
+ ax->reg_offsets[ret] = (size / 0x20) * ret;
+ }
+
+ ax->map2 = NULL;
+ } else {
+ size = (res->end - res->start) + 1;
+
+ ax->mem2 = request_mem_region(res->start, size, pdev->name);
+ if (ax->mem == NULL) {
+ dev_err(&pdev->dev, "cannot reserve registers\n");
+ ret = -ENXIO;
+ goto exit_mem1;
+ }
+
+ ax->map2 = ioremap(res->start, size);
+ if (ax->map2 == NULL) {
+ dev_err(&pdev->dev, "cannot map reset register");
+ ret = -ENXIO;
+ goto exit_mem2;
+ }
+
+ ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
+ }
+
+ /* got resources, now initialise and register device */
+
+ ret = ax_init_dev(dev, 1);
+ if (!ret)
+ return 0;
+
+ if (ax->map2 == NULL)
+ goto exit_mem1;
+
+ iounmap(ax->map2);
+
+ exit_mem2:
+ release_resource(ax->mem2);
+ kfree(ax->mem2);
+
+ exit_mem1:
+ iounmap(ei_status.mem);
+
+ exit_req:
+ release_resource(ax->mem);
+ kfree(ax->mem);
+
+ exit_mem:
+ free_netdev(dev);
+
+ return ret;
+}
+
+/* suspend and resume */
+
+#ifdef CONFIG_PM
+static int ax_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct net_device *ndev = platform_get_drvdata(dev);
+ struct ax_device *ax = to_ax_dev(ndev);
+
+ ax->resume_open = ax->running;
+
+ netif_device_detach(ndev);
+ ax_close(ndev);
+
+ return 0;
+}
+
+static int ax_resume(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ax_device *ax = to_ax_dev(ndev);
+
+ ax_initial_setup(ndev, netdev_priv(ndev));
+ ax_NS8390_init(ndev, ax->resume_open);
+ netif_device_attach(ndev);
+
+ if (ax->resume_open)
+ ax_open(ndev);
+
+ return 0;
+}
+
+#else
+#define ax_suspend NULL
+#define ax_resume NULL
+#endif
+
+static struct platform_driver axdrv = {
+ .driver = {
+ .name = "ax88796",
+ .owner = THIS_MODULE,
+ },
+ .probe = ax_probe,
+ .remove = ax_remove,
+ .suspend = ax_suspend,
+ .resume = ax_resume,
+};
+
+static int __init axdrv_init(void)
+{
+ return platform_driver_register(&axdrv);
+}
+
+static void __exit axdrv_exit(void)
+{
+ platform_driver_unregister(&axdrv);
+}
+
+module_init(axdrv_init);
+module_exit(axdrv_exit);
+
+MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 879a2fff474..96fb0ec905a 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -15,6 +15,7 @@
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
#include <linux/etherdevice.h>
#include <linux/pci.h>
#include <linux/delay.h>
@@ -68,8 +69,8 @@
(BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
-#define RX_PKT_BUF_SZ (1536 + bp->rx_offset + 64)
-#define TX_PKT_BUF_SZ (B44_MAX_MTU + ETH_HLEN + 8)
+#define RX_PKT_OFFSET 30
+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
@@ -599,8 +600,7 @@ static void b44_timer(unsigned long __opaque)
spin_unlock_irq(&bp->lock);
- bp->timer.expires = jiffies + HZ;
- add_timer(&bp->timer);
+ mod_timer(&bp->timer, round_jiffies(jiffies + HZ));
}
static void b44_tx(struct b44 *bp)
@@ -653,7 +653,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
src_map = &bp->rx_buffers[src_idx];
dest_idx = dest_idx_unmasked & (B44_RX_RING_SIZE - 1);
map = &bp->rx_buffers[dest_idx];
- skb = dev_alloc_skb(RX_PKT_BUF_SZ);
+ skb = netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ);
if (skb == NULL)
return -ENOMEM;
@@ -669,7 +669,7 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(skb);
- skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+ skb = __netdev_alloc_skb(bp->dev, RX_PKT_BUF_SZ, GFP_ATOMIC|GFP_DMA);
if (skb == NULL)
return -ENOMEM;
mapping = pci_map_single(bp->pdev, skb->data,
@@ -684,11 +684,9 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
}
}
- skb->dev = bp->dev;
- skb_reserve(skb, bp->rx_offset);
+ rh = (struct rx_header *) skb->data;
+ skb_reserve(skb, RX_PKT_OFFSET);
- rh = (struct rx_header *)
- (skb->data - bp->rx_offset);
rh->len = 0;
rh->flags = 0;
@@ -698,13 +696,13 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
if (src_map != NULL)
src_map->skb = NULL;
- ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - bp->rx_offset));
+ ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
if (dest_idx == (B44_RX_RING_SIZE - 1))
ctrl |= DESC_CTRL_EOT;
dp = &bp->rx_ring[dest_idx];
dp->ctrl = cpu_to_le32(ctrl);
- dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
+ dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
if (bp->flags & B44_FLAG_RX_RING_HACK)
b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
@@ -783,7 +781,7 @@ static int b44_rx(struct b44 *bp, int budget)
PCI_DMA_FROMDEVICE);
rh = (struct rx_header *) skb->data;
len = le16_to_cpu(rh->len);
- if ((len > (RX_PKT_BUF_SZ - bp->rx_offset)) ||
+ if ((len > (RX_PKT_BUF_SZ - RX_PKT_OFFSET)) ||
(rh->flags & cpu_to_le16(RX_FLAG_ERRORS))) {
drop_it:
b44_recycle_rx(bp, cons, bp->rx_prod);
@@ -815,8 +813,8 @@ static int b44_rx(struct b44 *bp, int budget)
pci_unmap_single(bp->pdev, map,
skb_size, PCI_DMA_FROMDEVICE);
/* Leave out rx_header */
- skb_put(skb, len+bp->rx_offset);
- skb_pull(skb,bp->rx_offset);
+ skb_put(skb, len + RX_PKT_OFFSET);
+ skb_pull(skb, RX_PKT_OFFSET);
} else {
struct sk_buff *copy_skb;
@@ -828,7 +826,7 @@ static int b44_rx(struct b44 *bp, int budget)
skb_reserve(copy_skb, 2);
skb_put(copy_skb, len);
/* DMA sync done above, copy just the actual packet */
- skb_copy_from_linear_data_offset(skb, bp->rx_offset,
+ skb_copy_from_linear_data_offset(skb, RX_PKT_OFFSET,
copy_skb->data, len);
skb = copy_skb;
}
@@ -969,7 +967,6 @@ static void b44_tx_timeout(struct net_device *dev)
static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct b44 *bp = netdev_priv(dev);
- struct sk_buff *bounce_skb;
int rc = NETDEV_TX_OK;
dma_addr_t mapping;
u32 len, entry, ctrl;
@@ -987,12 +984,13 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
+ struct sk_buff *bounce_skb;
+
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping, len, PCI_DMA_TODEVICE);
- bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
- GFP_ATOMIC|GFP_DMA);
+ bounce_skb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb)
goto err_out;
@@ -1001,13 +999,12 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
if (!dma_mapping_error(mapping))
pci_unmap_single(bp->pdev, mapping,
- len, PCI_DMA_TODEVICE);
+ len, PCI_DMA_TODEVICE);
dev_kfree_skb_any(bounce_skb);
goto err_out;
}
- skb_copy_from_linear_data(skb, skb_put(bounce_skb, len),
- skb->len);
+ skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
dev_kfree_skb_any(skb);
skb = bounce_skb;
}
@@ -1396,12 +1393,12 @@ static void b44_init_hw(struct b44 *bp, int reset_kind)
bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
if (reset_kind == B44_PARTIAL_RESET) {
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
- (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
} else {
bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
- (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ (RX_PKT_OFFSET << DMARX_CTRL_ROSHIFT)));
bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
bw32(bp, B44_DMARX_PTR, bp->rx_pending);
@@ -2093,11 +2090,6 @@ static int __devinit b44_get_invariants(struct b44 *bp)
bp->phy_addr = eeprom[90] & 0x1f;
- /* With this, plus the rx_header prepended to the data by the
- * hardware, we'll land the ethernet header on a 2-byte boundary.
- */
- bp->rx_offset = 30;
-
bp->imask = IMASK_DEF;
bp->core_unit = ssb_core_unit(bp);
@@ -2348,11 +2340,11 @@ static int b44_resume(struct pci_dev *pdev)
netif_device_attach(bp->dev);
spin_unlock_irq(&bp->lock);
- bp->timer.expires = jiffies + HZ;
- add_timer(&bp->timer);
-
b44_enable_ints(bp);
netif_wake_queue(dev);
+
+ mod_timer(&bp->timer, jiffies + 1);
+
return 0;
}
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 18fc1333662..e537e63f292 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -443,8 +443,6 @@ struct b44 {
#define B44_FLAG_TX_RING_HACK 0x40000000
#define B44_FLAG_WOL_ENABLE 0x80000000
- u32 rx_offset;
-
u32 msg_enable;
struct timer_list timer;
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 88b33c6ddda..d23861c8658 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -54,8 +54,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.5.10"
-#define DRV_MODULE_RELDATE "May 1, 2007"
+#define DRV_MODULE_VERSION "1.6.2"
+#define DRV_MODULE_RELDATE "July 6, 2007"
#define RUN_AT(x) (jiffies + (x))
@@ -550,6 +550,9 @@ bnx2_report_fw_link(struct bnx2 *bp)
{
u32 fw_link_status = 0;
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ return;
+
if (bp->link_up) {
u32 bmsr;
@@ -601,12 +604,21 @@ bnx2_report_fw_link(struct bnx2 *bp)
REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status);
}
+static char *
+bnx2_xceiver_str(struct bnx2 *bp)
+{
+ return ((bp->phy_port == PORT_FIBRE) ? "SerDes" :
+ ((bp->phy_flags & PHY_SERDES_FLAG) ? "Remote Copper" :
+ "Copper"));
+}
+
static void
bnx2_report_link(struct bnx2 *bp)
{
if (bp->link_up) {
netif_carrier_on(bp->dev);
- printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name);
+ printk(KERN_INFO PFX "%s NIC %s Link is Up, ", bp->dev->name,
+ bnx2_xceiver_str(bp));
printk("%d Mbps ", bp->line_speed);
@@ -630,7 +642,8 @@ bnx2_report_link(struct bnx2 *bp)
}
else {
netif_carrier_off(bp->dev);
- printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name);
+ printk(KERN_ERR PFX "%s NIC %s Link is Down\n", bp->dev->name,
+ bnx2_xceiver_str(bp));
}
bnx2_report_fw_link(bp);
@@ -1100,6 +1113,9 @@ bnx2_set_link(struct bnx2 *bp)
return 0;
}
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ return 0;
+
link_up = bp->link_up;
bnx2_enable_bmsr1(bp);
@@ -1210,12 +1226,74 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp)
return adv;
}
+static int bnx2_fw_sync(struct bnx2 *, u32, int);
+
static int
-bnx2_setup_serdes_phy(struct bnx2 *bp)
+bnx2_setup_remote_phy(struct bnx2 *bp, u8 port)
+{
+ u32 speed_arg = 0, pause_adv;
+
+ pause_adv = bnx2_phy_get_pause_adv(bp);
+
+ if (bp->autoneg & AUTONEG_SPEED) {
+ speed_arg |= BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG;
+ if (bp->advertising & ADVERTISED_10baseT_Half)
+ speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10HALF;
+ if (bp->advertising & ADVERTISED_10baseT_Full)
+ speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_10FULL;
+ if (bp->advertising & ADVERTISED_100baseT_Half)
+ speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100HALF;
+ if (bp->advertising & ADVERTISED_100baseT_Full)
+ speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_100FULL;
+ if (bp->advertising & ADVERTISED_1000baseT_Full)
+ speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
+ if (bp->advertising & ADVERTISED_2500baseX_Full)
+ speed_arg |= BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
+ } else {
+ if (bp->req_line_speed == SPEED_2500)
+ speed_arg = BNX2_NETLINK_SET_LINK_SPEED_2G5FULL;
+ else if (bp->req_line_speed == SPEED_1000)
+ speed_arg = BNX2_NETLINK_SET_LINK_SPEED_1GFULL;
+ else if (bp->req_line_speed == SPEED_100) {
+ if (bp->req_duplex == DUPLEX_FULL)
+ speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100FULL;
+ else
+ speed_arg = BNX2_NETLINK_SET_LINK_SPEED_100HALF;
+ } else if (bp->req_line_speed == SPEED_10) {
+ if (bp->req_duplex == DUPLEX_FULL)
+ speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10FULL;
+ else
+ speed_arg = BNX2_NETLINK_SET_LINK_SPEED_10HALF;
+ }
+ }
+
+ if (pause_adv & (ADVERTISE_1000XPAUSE | ADVERTISE_PAUSE_CAP))
+ speed_arg |= BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE;
+ if (pause_adv & (ADVERTISE_1000XPSE_ASYM | ADVERTISE_1000XPSE_ASYM))
+ speed_arg |= BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE;
+
+ if (port == PORT_TP)
+ speed_arg |= BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE |
+ BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED;
+
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB_ARG0, speed_arg);
+
+ spin_unlock_bh(&bp->phy_lock);
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_CMD_SET_LINK, 0);
+ spin_lock_bh(&bp->phy_lock);
+
+ return 0;
+}
+
+static int
+bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port)
{
u32 adv, bmcr;
u32 new_adv = 0;
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ return (bnx2_setup_remote_phy(bp, port));
+
if (!(bp->autoneg & AUTONEG_SPEED)) {
u32 new_bmcr;
int force_link_down = 0;
@@ -1323,7 +1401,9 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
}
#define ETHTOOL_ALL_FIBRE_SPEED \
- (ADVERTISED_1000baseT_Full)
+ (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ? \
+ (ADVERTISED_2500baseX_Full | ADVERTISED_1000baseT_Full) :\
+ (ADVERTISED_1000baseT_Full)
#define ETHTOOL_ALL_COPPER_SPEED \
(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
@@ -1335,6 +1415,188 @@ bnx2_setup_serdes_phy(struct bnx2 *bp)
#define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
+static void
+bnx2_set_default_remote_link(struct bnx2 *bp)
+{
+ u32 link;
+
+ if (bp->phy_port == PORT_TP)
+ link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_COPPER_LINK);
+ else
+ link = REG_RD_IND(bp, bp->shmem_base + BNX2_RPHY_SERDES_LINK);
+
+ if (link & BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG) {
+ bp->req_line_speed = 0;
+ bp->autoneg |= AUTONEG_SPEED;
+ bp->advertising = ADVERTISED_Autoneg;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
+ bp->advertising |= ADVERTISED_10baseT_Half;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_10FULL)
+ bp->advertising |= ADVERTISED_10baseT_Full;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
+ bp->advertising |= ADVERTISED_100baseT_Half;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_100FULL)
+ bp->advertising |= ADVERTISED_100baseT_Full;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
+ bp->advertising |= ADVERTISED_1000baseT_Full;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
+ bp->advertising |= ADVERTISED_2500baseX_Full;
+ } else {
+ bp->autoneg = 0;
+ bp->advertising = 0;
+ bp->req_duplex = DUPLEX_FULL;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_10) {
+ bp->req_line_speed = SPEED_10;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_10HALF)
+ bp->req_duplex = DUPLEX_HALF;
+ }
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_100) {
+ bp->req_line_speed = SPEED_100;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_100HALF)
+ bp->req_duplex = DUPLEX_HALF;
+ }
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_1GFULL)
+ bp->req_line_speed = SPEED_1000;
+ if (link & BNX2_NETLINK_SET_LINK_SPEED_2G5FULL)
+ bp->req_line_speed = SPEED_2500;
+ }
+}
+
+static void
+bnx2_set_default_link(struct bnx2 *bp)
+{
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ return bnx2_set_default_remote_link(bp);
+
+ bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
+ bp->req_line_speed = 0;
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ u32 reg;
+
+ bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
+
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
+ reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
+ if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
+ bp->autoneg = 0;
+ bp->req_line_speed = bp->line_speed = SPEED_1000;
+ bp->req_duplex = DUPLEX_FULL;
+ }
+ } else
+ bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
+}
+
+static void
+bnx2_send_heart_beat(struct bnx2 *bp)
+{
+ u32 msg;
+ u32 addr;
+
+ 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);
+ spin_unlock(&bp->indirect_lock);
+}
+
+static void
+bnx2_remote_phy_event(struct bnx2 *bp)
+{
+ u32 msg;
+ u8 link_up = bp->link_up;
+ u8 old_port;
+
+ msg = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
+
+ if (msg & BNX2_LINK_STATUS_HEART_BEAT_EXPIRED)
+ bnx2_send_heart_beat(bp);
+
+ msg &= ~BNX2_LINK_STATUS_HEART_BEAT_EXPIRED;
+
+ if ((msg & BNX2_LINK_STATUS_LINK_UP) == BNX2_LINK_STATUS_LINK_DOWN)
+ bp->link_up = 0;
+ else {
+ u32 speed;
+
+ bp->link_up = 1;
+ speed = msg & BNX2_LINK_STATUS_SPEED_MASK;
+ bp->duplex = DUPLEX_FULL;
+ switch (speed) {
+ case BNX2_LINK_STATUS_10HALF:
+ bp->duplex = DUPLEX_HALF;
+ case BNX2_LINK_STATUS_10FULL:
+ bp->line_speed = SPEED_10;
+ break;
+ case BNX2_LINK_STATUS_100HALF:
+ bp->duplex = DUPLEX_HALF;
+ case BNX2_LINK_STATUS_100BASE_T4:
+ case BNX2_LINK_STATUS_100FULL:
+ bp->line_speed = SPEED_100;
+ break;
+ case BNX2_LINK_STATUS_1000HALF:
+ bp->duplex = DUPLEX_HALF;
+ case BNX2_LINK_STATUS_1000FULL:
+ bp->line_speed = SPEED_1000;
+ break;
+ case BNX2_LINK_STATUS_2500HALF:
+ bp->duplex = DUPLEX_HALF;
+ case BNX2_LINK_STATUS_2500FULL:
+ bp->line_speed = SPEED_2500;
+ break;
+ default:
+ bp->line_speed = 0;
+ break;
+ }
+
+ spin_lock(&bp->phy_lock);
+ bp->flow_ctrl = 0;
+ if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
+ (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
+ if (bp->duplex == DUPLEX_FULL)
+ bp->flow_ctrl = bp->req_flow_ctrl;
+ } else {
+ if (msg & BNX2_LINK_STATUS_TX_FC_ENABLED)
+ bp->flow_ctrl |= FLOW_CTRL_TX;
+ if (msg & BNX2_LINK_STATUS_RX_FC_ENABLED)
+ bp->flow_ctrl |= FLOW_CTRL_RX;
+ }
+
+ old_port = bp->phy_port;
+ if (msg & BNX2_LINK_STATUS_SERDES_LINK)
+ bp->phy_port = PORT_FIBRE;
+ else
+ bp->phy_port = PORT_TP;
+
+ if (old_port != bp->phy_port)
+ bnx2_set_default_link(bp);
+
+ spin_unlock(&bp->phy_lock);
+ }
+ if (bp->link_up != link_up)
+ bnx2_report_link(bp);
+
+ bnx2_set_mac_link(bp);
+}
+
+static int
+bnx2_set_remote_link(struct bnx2 *bp)
+{
+ u32 evt_code;
+
+ evt_code = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_EVT_CODE_MB);
+ switch (evt_code) {
+ case BNX2_FW_EVT_CODE_LINK_EVENT:
+ bnx2_remote_phy_event(bp);
+ break;
+ case BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT:
+ default:
+ bnx2_send_heart_beat(bp);
+ break;
+ }
+ return 0;
+}
+
static int
bnx2_setup_copper_phy(struct bnx2 *bp)
{
@@ -1433,13 +1695,13 @@ bnx2_setup_copper_phy(struct bnx2 *bp)
}
static int
-bnx2_setup_phy(struct bnx2 *bp)
+bnx2_setup_phy(struct bnx2 *bp, u8 port)
{
if (bp->loopback == MAC_LOOPBACK)
return 0;
if (bp->phy_flags & PHY_SERDES_FLAG) {
- return (bnx2_setup_serdes_phy(bp));
+ return (bnx2_setup_serdes_phy(bp, port));
}
else {
return (bnx2_setup_copper_phy(bp));
@@ -1659,6 +1921,9 @@ bnx2_init_phy(struct bnx2 *bp)
REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ goto setup_phy;
+
bnx2_read_phy(bp, MII_PHYSID1, &val);
bp->phy_id = val << 16;
bnx2_read_phy(bp, MII_PHYSID2, &val);
@@ -1676,7 +1941,9 @@ bnx2_init_phy(struct bnx2 *bp)
rc = bnx2_init_copper_phy(bp);
}
- bnx2_setup_phy(bp);
+setup_phy:
+ if (!rc)
+ rc = bnx2_setup_phy(bp, bp->phy_port);
return rc;
}
@@ -1778,6 +2045,15 @@ bnx2_init_5709_context(struct bnx2 *bp)
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);
+ for (i = 0; i < 10; i++) {
+ val = REG_RD(bp, BNX2_CTX_COMMAND);
+ if (!(val & BNX2_CTX_COMMAND_MEM_INIT))
+ break;
+ udelay(2);
+ }
+ if (val & BNX2_CTX_COMMAND_MEM_INIT)
+ return -EBUSY;
+
for (i = 0; i < bp->ctx_pages; i++) {
int j;
@@ -1811,6 +2087,7 @@ bnx2_init_context(struct bnx2 *bp)
vcid = 96;
while (vcid) {
u32 vcid_addr, pcid_addr, offset;
+ int i;
vcid--;
@@ -1831,16 +2108,20 @@ bnx2_init_context(struct bnx2 *bp)
pcid_addr = vcid_addr;
}
- REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
- REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ for (i = 0; i < (CTX_SIZE / PHY_CTX_SIZE); i++) {
+ vcid_addr += (i << PHY_CTX_SHIFT);
+ pcid_addr += (i << PHY_CTX_SHIFT);
- /* Zero out the context. */
- for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) {
- CTX_WR(bp, 0x00, offset, 0);
- }
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+
+ /* Zero out the context. */
+ for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
+ CTX_WR(bp, 0x00, offset, 0);
- REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
- REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ }
}
}
@@ -1970,6 +2251,9 @@ bnx2_phy_int(struct bnx2 *bp)
bnx2_set_link(bp);
spin_unlock(&bp->phy_lock);
}
+ if (bnx2_phy_event_is_set(bp, STATUS_ATTN_BITS_TIMER_ABORT))
+ bnx2_set_remote_link(bp);
+
}
static void
@@ -2283,6 +2567,7 @@ bnx2_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct bnx2 *bp = netdev_priv(dev);
+ struct status_block *sblk = bp->status_blk;
/* When using INTx, it is possible for the interrupt to arrive
* at the CPU before the status block posted prior to the
@@ -2290,7 +2575,7 @@ bnx2_interrupt(int irq, void *dev_instance)
* When using MSI, the MSI message will always complete after
* the status block write.
*/
- if ((bp->status_blk->status_idx == bp->last_status_idx) &&
+ if ((sblk->status_idx == bp->last_status_idx) &&
(REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
return IRQ_NONE;
@@ -2299,16 +2584,25 @@ bnx2_interrupt(int irq, void *dev_instance)
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);
+
/* Return here if interrupt is shared and is disabled. */
if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED;
- netif_rx_schedule(dev);
+ if (netif_rx_schedule_prep(dev)) {
+ bp->last_status_idx = sblk->status_idx;
+ __netif_rx_schedule(dev);
+ }
return IRQ_HANDLED;
}
-#define STATUS_ATTN_EVENTS STATUS_ATTN_BITS_LINK_STATE
+#define STATUS_ATTN_EVENTS (STATUS_ATTN_BITS_LINK_STATE | \
+ STATUS_ATTN_BITS_TIMER_ABORT)
static inline int
bnx2_has_work(struct bnx2 *bp)
@@ -3548,6 +3842,36 @@ nvram_write_end:
return rc;
}
+static void
+bnx2_init_remote_phy(struct bnx2 *bp)
+{
+ u32 val;
+
+ bp->phy_flags &= ~REMOTE_PHY_CAP_FLAG;
+ if (!(bp->phy_flags & PHY_SERDES_FLAG))
+ return;
+
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_CAP_MB);
+ if ((val & BNX2_FW_CAP_SIGNATURE_MASK) != BNX2_FW_CAP_SIGNATURE)
+ return;
+
+ if (val & BNX2_FW_CAP_REMOTE_PHY_CAPABLE) {
+ if (netif_running(bp->dev)) {
+ val = BNX2_DRV_ACK_CAP_SIGNATURE |
+ BNX2_FW_CAP_REMOTE_PHY_CAPABLE;
+ REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_ACK_CAP_MB,
+ val);
+ }
+ bp->phy_flags |= REMOTE_PHY_CAP_FLAG;
+
+ val = REG_RD_IND(bp, bp->shmem_base + BNX2_LINK_STATUS);
+ if (val & BNX2_LINK_STATUS_SERDES_LINK)
+ bp->phy_port = PORT_FIBRE;
+ else
+ bp->phy_port = PORT_TP;
+ }
+}
+
static int
bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
{
@@ -3628,6 +3952,12 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
if (rc)
return rc;
+ spin_lock_bh(&bp->phy_lock);
+ bnx2_init_remote_phy(bp);
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ bnx2_set_default_remote_link(bp);
+ spin_unlock_bh(&bp->phy_lock);
+
if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
/* Adjust the voltage regular to two steps lower. The default
* of this register is 0x0000000e. */
@@ -3691,9 +4021,11 @@ bnx2_init_chip(struct bnx2 *bp)
/* Initialize context mapping and zero out the quick contexts. The
* context block must have already been enabled. */
- if (CHIP_NUM(bp) == CHIP_NUM_5709)
- bnx2_init_5709_context(bp);
- else
+ if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+ rc = bnx2_init_5709_context(bp);
+ if (rc)
+ return rc;
+ } else
bnx2_init_context(bp);
if ((rc = bnx2_init_cpus(bp)) != 0)
@@ -3772,7 +4104,10 @@ bnx2_init_chip(struct bnx2 *bp)
REG_WR(bp, BNX2_HC_CMD_TICKS,
(bp->cmd_ticks_int << 16) | bp->cmd_ticks);
- REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
+ if (CHIP_NUM(bp) == CHIP_NUM_5708)
+ REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
+ else
+ REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
if (CHIP_ID(bp) == CHIP_ID_5706_A1)
@@ -3799,10 +4134,15 @@ bnx2_init_chip(struct bnx2 *bp)
/* 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);
+ val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
+ REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+ }
rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
0);
- REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
udelay(20);
@@ -4045,8 +4385,8 @@ bnx2_init_nic(struct bnx2 *bp)
spin_lock_bh(&bp->phy_lock);
bnx2_init_phy(bp);
- spin_unlock_bh(&bp->phy_lock);
bnx2_set_link(bp);
+ spin_unlock_bh(&bp->phy_lock);
return 0;
}
@@ -4576,6 +4916,9 @@ bnx2_5706_serdes_timer(struct bnx2 *bp)
static void
bnx2_5708_serdes_timer(struct bnx2 *bp)
{
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ return;
+
if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) {
bp->serdes_an_pending = 0;
return;
@@ -4607,7 +4950,6 @@ static void
bnx2_timer(unsigned long data)
{
struct bnx2 *bp = (struct bnx2 *) data;
- u32 msg;
if (!netif_running(bp->dev))
return;
@@ -4615,11 +4957,15 @@ bnx2_timer(unsigned long data)
if (atomic_read(&bp->intr_sem) != 0)
goto bnx2_restart_timer;
- msg = (u32) ++bp->fw_drv_pulse_wr_seq;
- REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
+ bnx2_send_heart_beat(bp);
bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
+ /* workaround occasional corrupted counters */
+ if (CHIP_NUM(bp) == CHIP_NUM_5708 && bp->stats_ticks)
+ REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
+ BNX2_HC_COMMAND_STATS_NOW);
+
if (bp->phy_flags & PHY_SERDES_FLAG) {
if (CHIP_NUM(bp) == CHIP_NUM_5706)
bnx2_5706_serdes_timer(bp);
@@ -4786,19 +5132,6 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
bnx2_netif_start(bp);
}
-
-/* Called with rtnl_lock */
-static void
-bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
-{
- struct bnx2 *bp = netdev_priv(dev);
-
- bnx2_netif_stop(bp);
- vlan_group_set_device(bp->vlgrp, vid, NULL);
- bnx2_set_rx_mode(dev);
-
- bnx2_netif_start(bp);
-}
#endif
/* Called with netif_tx_lock.
@@ -5067,17 +5400,25 @@ static int
bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct bnx2 *bp = netdev_priv(dev);
+ int support_serdes = 0, support_copper = 0;
cmd->supported = SUPPORTED_Autoneg;
- if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
+ support_serdes = 1;
+ support_copper = 1;
+ } else if (bp->phy_port == PORT_FIBRE)
+ support_serdes = 1;
+ else
+ support_copper = 1;
+
+ if (support_serdes) {
cmd->supported |= SUPPORTED_1000baseT_Full |
SUPPORTED_FIBRE;
if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)
cmd->supported |= SUPPORTED_2500baseX_Full;
- cmd->port = PORT_FIBRE;
}
- else {
+ if (support_copper) {
cmd->supported |= SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
@@ -5085,9 +5426,10 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
SUPPORTED_1000baseT_Full |
SUPPORTED_TP;
- cmd->port = PORT_TP;
}
+ spin_lock_bh(&bp->phy_lock);
+ cmd->port = bp->phy_port;
cmd->advertising = bp->advertising;
if (bp->autoneg & AUTONEG_SPEED) {
@@ -5105,6 +5447,7 @@ bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->speed = -1;
cmd->duplex = -1;
}
+ spin_unlock_bh(&bp->phy_lock);
cmd->transceiver = XCVR_INTERNAL;
cmd->phy_address = bp->phy_addr;
@@ -5120,6 +5463,15 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
u8 req_duplex = bp->req_duplex;
u16 req_line_speed = bp->req_line_speed;
u32 advertising = bp->advertising;
+ int err = -EINVAL;
+
+ spin_lock_bh(&bp->phy_lock);
+
+ if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE)
+ goto err_out_unlock;
+
+ if (cmd->port != bp->phy_port && !(bp->phy_flags & REMOTE_PHY_CAP_FLAG))
+ goto err_out_unlock;
if (cmd->autoneg == AUTONEG_ENABLE) {
autoneg |= AUTONEG_SPEED;
@@ -5132,44 +5484,41 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
(cmd->advertising == ADVERTISED_100baseT_Half) ||
(cmd->advertising == ADVERTISED_100baseT_Full)) {
- if (bp->phy_flags & PHY_SERDES_FLAG)
- return -EINVAL;
+ if (cmd->port == PORT_FIBRE)
+ goto err_out_unlock;
advertising = cmd->advertising;
} else if (cmd->advertising == ADVERTISED_2500baseX_Full) {
- if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
- return -EINVAL;
- } else if (cmd->advertising == ADVERTISED_1000baseT_Full) {
+ if (!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) ||
+ (cmd->port == PORT_TP))
+ goto err_out_unlock;
+ } else if (cmd->advertising == ADVERTISED_1000baseT_Full)
advertising = cmd->advertising;
- }
- else if (cmd->advertising == ADVERTISED_1000baseT_Half) {
- return -EINVAL;
- }
+ else if (cmd->advertising == ADVERTISED_1000baseT_Half)
+ goto err_out_unlock;
else {
- if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if (cmd->port == PORT_FIBRE)
advertising = ETHTOOL_ALL_FIBRE_SPEED;
- }
- else {
+ else
advertising = ETHTOOL_ALL_COPPER_SPEED;
- }
}
advertising |= ADVERTISED_Autoneg;
}
else {
- if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if (cmd->port == PORT_FIBRE) {
if ((cmd->speed != SPEED_1000 &&
cmd->speed != SPEED_2500) ||
(cmd->duplex != DUPLEX_FULL))
- return -EINVAL;
+ goto err_out_unlock;
if (cmd->speed == SPEED_2500 &&
!(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG))
- return -EINVAL;
- }
- else if (cmd->speed == SPEED_1000) {
- return -EINVAL;
+ goto err_out_unlock;
}
+ else if (cmd->speed == SPEED_1000 || cmd->speed == SPEED_2500)
+ goto err_out_unlock;
+
autoneg &= ~AUTONEG_SPEED;
req_line_speed = cmd->speed;
req_duplex = cmd->duplex;
@@ -5181,13 +5530,12 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
bp->req_line_speed = req_line_speed;
bp->req_duplex = req_duplex;
- spin_lock_bh(&bp->phy_lock);
-
- bnx2_setup_phy(bp);
+ err = bnx2_setup_phy(bp, cmd->port);
+err_out_unlock:
spin_unlock_bh(&bp->phy_lock);
- return 0;
+ return err;
}
static void
@@ -5198,11 +5546,7 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
strcpy(info->driver, DRV_MODULE_NAME);
strcpy(info->version, DRV_MODULE_VERSION);
strcpy(info->bus_info, pci_name(bp->pdev));
- info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0';
- info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0';
- info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0';
- info->fw_version[1] = info->fw_version[3] = '.';
- info->fw_version[5] = 0;
+ strcpy(info->fw_version, bp->fw_version);
}
#define BNX2_REGDUMP_LEN (32 * 1024)
@@ -5314,6 +5658,14 @@ bnx2_nway_reset(struct net_device *dev)
spin_lock_bh(&bp->phy_lock);
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG) {
+ int rc;
+
+ rc = bnx2_setup_remote_phy(bp, bp->phy_port);
+ spin_unlock_bh(&bp->phy_lock);
+ return rc;
+ }
+
/* Force a link down visible on the other side */
if (bp->phy_flags & PHY_SERDES_FLAG) {
bnx2_write_phy(bp, bp->mii_bmcr, BMCR_LOOPBACK);
@@ -5430,6 +5782,10 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
0xff;
bp->stats_ticks = coal->stats_block_coalesce_usecs;
+ if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+ if (bp->stats_ticks != 0 && bp->stats_ticks != USEC_PER_SEC)
+ bp->stats_ticks = USEC_PER_SEC;
+ }
if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00;
bp->stats_ticks &= 0xffff00;
@@ -5523,7 +5879,7 @@ bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
spin_lock_bh(&bp->phy_lock);
- bnx2_setup_phy(bp);
+ bnx2_setup_phy(bp, bp->phy_port);
spin_unlock_bh(&bp->phy_lock);
@@ -5862,7 +6218,7 @@ bnx2_set_tx_csum(struct net_device *dev, u32 data)
struct bnx2 *bp = netdev_priv(dev);
if (CHIP_NUM(bp) == CHIP_NUM_5709)
- return (ethtool_op_set_tx_hw_csum(dev, data));
+ return (ethtool_op_set_tx_ipv6_csum(dev, data));
else
return (ethtool_op_set_tx_csum(dev, data));
}
@@ -5919,6 +6275,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
case SIOCGMIIREG: {
u32 mii_regval;
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ return -EOPNOTSUPP;
+
if (!netif_running(dev))
return -EAGAIN;
@@ -5935,6 +6294,9 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
+ if (bp->phy_flags & REMOTE_PHY_CAP_FLAG)
+ return -EOPNOTSUPP;
+
if (!netif_running(dev))
return -EAGAIN;
@@ -6096,7 +6458,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
{
struct bnx2 *bp;
unsigned long mem_len;
- int rc;
+ int rc, i, j;
u32 reg;
u64 dma_mask, persist_dma_mask;
@@ -6253,7 +6615,35 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
goto err_out_unmap;
}
- bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
+ for (i = 0, j = 0; i < 3; i++) {
+ u8 num, k, skip0;
+
+ num = (u8) (reg >> (24 - (i * 8)));
+ for (k = 100, skip0 = 1; k >= 1; num %= k, k /= 10) {
+ if (num >= k || !skip0 || k == 1) {
+ bp->fw_version[j++] = (num / k) + '0';
+ skip0 = 0;
+ }
+ }
+ if (i != 2)
+ bp->fw_version[j++] = '.';
+ }
+ reg = REG_RD_IND(bp, bp->shmem_base + BNX2_BC_STATE_CONDITION);
+ reg &= BNX2_CONDITION_MFW_RUN_MASK;
+ if (reg != BNX2_CONDITION_MFW_RUN_UNKNOWN &&
+ reg != BNX2_CONDITION_MFW_RUN_NONE) {
+ int i;
+ u32 addr = REG_RD_IND(bp, bp->shmem_base + BNX2_MFW_VER_PTR);
+
+ bp->fw_version[j++] = ' ';
+ for (i = 0; i < 3; i++) {
+ reg = REG_RD_IND(bp, addr + i * 4);
+ reg = swab32(reg);
+ memcpy(&bp->fw_version[j], &reg, 4);
+ j += 4;
+ }
+ }
reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER);
bp->mac_addr[0] = (u8) (reg >> 8);
@@ -6295,7 +6685,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
bp->phy_flags |= PHY_SERDES_FLAG;
+ bp->phy_port = PORT_TP;
if (bp->phy_flags & PHY_SERDES_FLAG) {
+ bp->phy_port = PORT_FIBRE;
bp->flags |= NO_WOL_FLAG;
if (CHIP_NUM(bp) != CHIP_NUM_5706) {
bp->phy_addr = 2;
@@ -6304,6 +6696,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
}
+ bnx2_init_remote_phy(bp);
+
} else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
CHIP_NUM(bp) == CHIP_NUM_5708)
bp->phy_flags |= PHY_CRC_FIX_FLAG;
@@ -6343,10 +6737,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD,
PCI_DEVICE_ID_AMD_8132_BRIDGE,
amd_8132))) {
- u8 rev;
- pci_read_config_byte(amd_8132, PCI_REVISION_ID, &rev);
- if (rev >= 0x10 && rev <= 0x13) {
+ if (amd_8132->revision >= 0x10 &&
+ amd_8132->revision <= 0x13) {
disable_msi = 1;
pci_dev_put(amd_8132);
break;
@@ -6354,23 +6747,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
}
}
- bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
- bp->req_line_speed = 0;
- if (bp->phy_flags & PHY_SERDES_FLAG) {
- bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
-
- reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
- reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
- if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
- bp->autoneg = 0;
- bp->req_line_speed = bp->line_speed = SPEED_1000;
- bp->req_duplex = DUPLEX_FULL;
- }
- }
- else {
- bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
- }
-
+ bnx2_set_default_link(bp);
bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
init_timer(&bp->timer);
@@ -6453,7 +6830,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->watchdog_timeo = TX_TIMEOUT;
#ifdef BCM_VLAN
dev->vlan_rx_register = bnx2_vlan_rx_register;
- dev->vlan_rx_kill_vid = bnx2_vlan_rx_kill_vid;
#endif
dev->poll = bnx2_poll;
dev->ethtool_ops = &bnx2_ethtool_ops;
@@ -6471,10 +6847,10 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
memcpy(dev->perm_addr, bp->mac_addr, 6);
bp->name = board_info[ent->driver_data].name;
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
if (CHIP_NUM(bp) == CHIP_NUM_5709)
- dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
- else
- dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+ dev->features |= NETIF_F_IPV6_CSUM;
+
#ifdef BCM_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
#endif
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index bd6288d6350..d8cd1afeb23 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -1373,6 +1373,7 @@ struct l2_fhdr {
#define BNX2_MISC_NEW_CORE_CTL 0x000008c8
#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0)
#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1)
+#define BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE (1L<<16)
#define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2)
#define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16)
@@ -6337,6 +6338,8 @@ struct l2_fhdr {
#define RX_COPY_THRESH 92
+#define BNX2_MISC_ENABLE_DEFAULT 0x7ffffff
+
#define DMA_READ_CHANS 5
#define DMA_WRITE_CHANS 3
@@ -6536,6 +6539,7 @@ struct bnx2 {
#define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100
#define PHY_INT_MODE_LINK_READY_FLAG 0x200
#define PHY_DIS_EARLY_DAC_FLAG 0x400
+#define REMOTE_PHY_CAP_FLAG 0x800
u32 mii_bmcr;
u32 mii_bmsr;
@@ -6624,6 +6628,7 @@ struct bnx2 {
u16 req_line_speed;
u8 req_duplex;
+ u8 phy_port;
u8 link_up;
u16 line_speed;
@@ -6655,7 +6660,7 @@ struct bnx2 {
u32 shmem_base;
- u32 fw_ver;
+ char fw_version[32];
int pm_cap;
int pcix_cap;
@@ -6769,7 +6774,7 @@ struct fw_info {
* the firmware has timed out, the driver will assume there is no firmware
* running and there won't be any firmware-driver synchronization during a
* driver reset. */
-#define FW_ACK_TIME_OUT_MS 100
+#define FW_ACK_TIME_OUT_MS 1000
#define BNX2_DRV_RESET_SIGNATURE 0x00000000
@@ -6787,6 +6792,7 @@ struct fw_info {
#define BNX2_DRV_MSG_CODE_DIAG 0x07000000
#define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000
#define BNX2_DRV_MSG_CODE_UNLOAD_LNK_DN 0x0b000000
+#define BNX2_DRV_MSG_CODE_CMD_SET_LINK 0x10000000
#define BNX2_DRV_MSG_DATA 0x00ff0000
#define BNX2_DRV_MSG_DATA_WAIT0 0x00010000
@@ -6835,6 +6841,7 @@ struct fw_info {
#define BNX2_LINK_STATUS_SERDES_LINK (1<<20)
#define BNX2_LINK_STATUS_PARTNER_AD_2500FULL (1<<21)
#define BNX2_LINK_STATUS_PARTNER_AD_2500HALF (1<<22)
+#define BNX2_LINK_STATUS_HEART_BEAT_EXPIRED (1<<31)
#define BNX2_DRV_PULSE_MB 0x00000010
#define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff
@@ -6844,6 +6851,30 @@ struct fw_info {
* This is used for debugging. */
#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000
+#define BNX2_DRV_MB_ARG0 0x00000014
+#define BNX2_NETLINK_SET_LINK_SPEED_10HALF (1<<0)
+#define BNX2_NETLINK_SET_LINK_SPEED_10FULL (1<<1)
+#define BNX2_NETLINK_SET_LINK_SPEED_10 \
+ (BNX2_NETLINK_SET_LINK_SPEED_10HALF | \
+ BNX2_NETLINK_SET_LINK_SPEED_10FULL)
+#define BNX2_NETLINK_SET_LINK_SPEED_100HALF (1<<2)
+#define BNX2_NETLINK_SET_LINK_SPEED_100FULL (1<<3)
+#define BNX2_NETLINK_SET_LINK_SPEED_100 \
+ (BNX2_NETLINK_SET_LINK_SPEED_100HALF | \
+ BNX2_NETLINK_SET_LINK_SPEED_100FULL)
+#define BNX2_NETLINK_SET_LINK_SPEED_1GHALF (1<<4)
+#define BNX2_NETLINK_SET_LINK_SPEED_1GFULL (1<<5)
+#define BNX2_NETLINK_SET_LINK_SPEED_2G5HALF (1<<6)
+#define BNX2_NETLINK_SET_LINK_SPEED_2G5FULL (1<<7)
+#define BNX2_NETLINK_SET_LINK_SPEED_10GHALF (1<<8)
+#define BNX2_NETLINK_SET_LINK_SPEED_10GFULL (1<<9)
+#define BNX2_NETLINK_SET_LINK_ENABLE_AUTONEG (1<<10)
+#define BNX2_NETLINK_SET_LINK_PHY_APP_REMOTE (1<<11)
+#define BNX2_NETLINK_SET_LINK_FC_SYM_PAUSE (1<<12)
+#define BNX2_NETLINK_SET_LINK_FC_ASYM_PAUSE (1<<13)
+#define BNX2_NETLINK_SET_LINK_ETH_AT_WIRESPEED (1<<14)
+#define BNX2_NETLINK_SET_LINK_PHY_RESET (1<<15)
+
#define BNX2_DEV_INFO_SIGNATURE 0x00000020
#define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900
#define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00
@@ -7005,6 +7036,8 @@ struct fw_info {
#define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff
#define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000
+#define BNX2_MFW_VER_PTR 0x00000014c
+
#define BNX2_BC_STATE_RESET_TYPE 0x000001c0
#define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254
#define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff
@@ -7058,12 +7091,42 @@ struct fw_info {
#define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600)
#define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700)
+#define BNX2_BC_STATE_CONDITION 0x000001c8
+#define BNX2_CONDITION_MFW_RUN_UNKNOWN 0x00000000
+#define BNX2_CONDITION_MFW_RUN_IPMI 0x00002000
+#define BNX2_CONDITION_MFW_RUN_UMP 0x00004000
+#define BNX2_CONDITION_MFW_RUN_NCSI 0x00006000
+#define BNX2_CONDITION_MFW_RUN_NONE 0x0000e000
+#define BNX2_CONDITION_MFW_RUN_MASK 0x0000e000
+
#define BNX2_BC_STATE_DEBUG_CMD 0x1dc
#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000
#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000
#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff
#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff
+#define BNX2_FW_EVT_CODE_MB 0x354
+#define BNX2_FW_EVT_CODE_SW_TIMER_EXPIRATION_EVENT 0x00000000
+#define BNX2_FW_EVT_CODE_LINK_EVENT 0x00000001
+
+#define BNX2_DRV_ACK_CAP_MB 0x364
+#define BNX2_DRV_ACK_CAP_SIGNATURE 0x35450000
+#define BNX2_CAPABILITY_SIGNATURE_MASK 0xFFFF0000
+
+#define BNX2_FW_CAP_MB 0x368
+#define BNX2_FW_CAP_SIGNATURE 0xaa550000
+#define BNX2_FW_ACK_DRV_SIGNATURE 0x52500000
+#define BNX2_FW_CAP_SIGNATURE_MASK 0xffff0000
+#define BNX2_FW_CAP_REMOTE_PHY_CAPABLE 0x00000001
+#define BNX2_FW_CAP_REMOTE_PHY_PRESENT 0x00000002
+
+#define BNX2_RPHY_SIGNATURE 0x36c
+#define BNX2_RPHY_LOAD_SIGNATURE 0x5a5a5a5a
+
+#define BNX2_RPHY_FLAGS 0x370
+#define BNX2_RPHY_SERDES_LINK 0x374
+#define BNX2_RPHY_COPPER_LINK 0x378
+
#define HOST_VIEW_SHMEM_BASE 0x167c00
#endif
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 7e03f41ae2c..f829e4ad8b4 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2303,19 +2303,18 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
}
/*
- * set link state for bonding master: if we have an active partnered
+ * set link state for bonding master: if we have an active
* aggregator, we're up, if not, we're down. Presumes that we cannot
* have an active aggregator if there are no slaves with link up.
*
+ * This behavior complies with IEEE 802.3 section 43.3.9.
+ *
* Called by bond_set_carrier(). Return zero if carrier state does not
* change, nonzero if it does.
*/
int bond_3ad_set_carrier(struct bonding *bond)
{
- struct aggregator *agg;
-
- agg = __get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator));
- if (agg && MAC_ADDRESS_COMPARE(&agg->partner_system, &null_mac_addr)) {
+ if (__get_active_agg(&(SLAVE_AD_INFO(bond->first_slave).aggregator))) {
if (!netif_carrier_ok(bond->dev)) {
netif_carrier_on(bond->dev);
return 1;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 223517dcbcf..cb9cb3013f4 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -187,7 +187,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond);
/*---------------------------- General routines -----------------------------*/
-const char *bond_mode_name(int mode)
+static const char *bond_mode_name(int mode)
{
switch (mode) {
case BOND_MODE_ROUNDROBIN :
@@ -1224,7 +1224,8 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave)
/*---------------------------------- IOCTL ----------------------------------*/
-int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev)
+static int bond_sethwaddr(struct net_device *bond_dev,
+ struct net_device *slave_dev)
{
dprintk("bond_dev=%p\n", bond_dev);
dprintk("slave_dev=%p\n", slave_dev);
@@ -1390,6 +1391,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_free;
}
+ res = netdev_set_master(slave_dev, bond_dev);
+ if (res) {
+ dprintk("Error %d calling netdev_set_master\n", res);
+ goto err_close;
+ }
/* open the slave since the application closed it */
res = dev_open(slave_dev);
if (res) {
@@ -1397,12 +1403,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_restore_mac;
}
- res = netdev_set_master(slave_dev, bond_dev);
- if (res) {
- dprintk("Error %d calling netdev_set_master\n", res);
- goto err_close;
- }
-
new_slave->dev = slave_dev;
slave_dev->priv_flags |= IFF_BONDING;
@@ -4345,8 +4345,8 @@ static void bond_free_all(void)
bond_mc_list_destroy(bond);
/* Release the bonded slaves */
bond_release_all(bond_dev);
- unregister_netdevice(bond_dev);
bond_deinit(bond_dev);
+ unregister_netdevice(bond_dev);
}
#ifdef CONFIG_PROC_FS
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index a122baa5c7b..60cccf2aa95 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -164,9 +164,9 @@ static ssize_t bonding_store_bonds(struct class *cls, const char *buffer, size_t
printk(KERN_INFO DRV_NAME
": %s is being deleted...\n",
bond->dev->name);
- unregister_netdevice(bond->dev);
bond_deinit(bond->dev);
bond_destroy_sysfs_entry(bond);
+ unregister_netdevice(bond->dev);
rtnl_unlock();
goto out;
}
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 41aa78bf1f7..6dcbd25e3ef 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -22,8 +22,8 @@
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "3.1.2"
-#define DRV_RELDATE "January 20, 2007"
+#define DRV_VERSION "3.1.3"
+#define DRV_RELDATE "June 13, 2007"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
@@ -301,13 +301,11 @@ int bond_create_slave_symlinks(struct net_device *master, struct net_device *sla
void bond_destroy_slave_symlinks(struct net_device *master, struct net_device *slave);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
-int bond_sethwaddr(struct net_device *bond_dev, struct net_device *slave_dev);
void bond_mii_monitor(struct net_device *bond_dev);
void bond_loadbalance_arp_mon(struct net_device *bond_dev);
void bond_activebackup_arp_mon(struct net_device *bond_dev);
void bond_set_mode_ops(struct bonding *bond, int mode);
int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
-const char *bond_mode_name(int mode);
void bond_select_active_slave(struct bonding *bond);
void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
void bond_register_arp(struct bonding *);
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 9fe3a38883e..f6e4030c73d 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -3422,21 +3422,19 @@ done:
static void cas_check_pci_invariants(struct cas *cp)
{
struct pci_dev *pdev = cp->pdev;
- u8 rev;
cp->cas_flags = 0;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
if ((pdev->vendor == PCI_VENDOR_ID_SUN) &&
(pdev->device == PCI_DEVICE_ID_SUN_CASSINI)) {
- if (rev >= CAS_ID_REVPLUS)
+ if (pdev->revision >= CAS_ID_REVPLUS)
cp->cas_flags |= CAS_FLAG_REG_PLUS;
- if (rev < CAS_ID_REVPLUS02u)
+ if (pdev->revision < CAS_ID_REVPLUS02u)
cp->cas_flags |= CAS_FLAG_TARGET_ABORT;
/* Original Cassini supports HW CSUM, but it's not
* enabled by default as it can trigger TX hangs.
*/
- if (rev < CAS_ID_REV2)
+ if (pdev->revision < CAS_ID_REV2)
cp->cas_flags |= CAS_FLAG_NO_HW_CSUM;
} else {
/* Only sun has original cassini chips. */
@@ -4919,13 +4917,13 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
pci_cmd &= ~PCI_COMMAND_SERR;
pci_cmd |= PCI_COMMAND_PARITY;
pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
- if (pci_set_mwi(pdev))
- printk(KERN_WARNING PFX "Could enable MWI for %s\n",
+ if (pci_try_set_mwi(pdev))
+ printk(KERN_WARNING PFX "Could not enable MWI for %s\n",
pci_name(pdev));
/*
* On some architectures, the default cache line size set
- * by pci_set_mwi reduces perforamnce. We have to increase
+ * by pci_try_set_mwi reduces perforamnce. We have to increase
* it for this case. To start, we'll print some configuration
* data.
*/
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 125c9b10586..231ce43b97c 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -883,15 +883,6 @@ static void vlan_rx_register(struct net_device *dev,
t1_set_vlan_accel(adapter, grp != NULL);
spin_unlock_irq(&adapter->async_lock);
}
-
-static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct adapter *adapter = dev->priv;
-
- spin_lock_irq(&adapter->async_lock);
- vlan_group_set_device(adapter->vlan_grp, vid, NULL);
- spin_unlock_irq(&adapter->async_lock);
-}
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1099,7 +1090,6 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->features |=
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
netdev->vlan_rx_register = vlan_rx_register;
- netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
#endif
/* T204: disable TSO */
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 80c3d8f268a..ab72563b81e 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -71,27 +71,29 @@ enum { /* adapter flags */
QUEUES_BOUND = (1 << 3),
};
+struct fl_pg_chunk {
+ struct page *page;
+ void *va;
+ unsigned int offset;
+};
+
struct rx_desc;
struct rx_sw_desc;
-struct sge_fl_page {
- struct skb_frag_struct frag;
- unsigned char *va;
-};
-
-struct sge_fl { /* SGE per free-buffer list state */
- unsigned int buf_size; /* size of each Rx buffer */
- unsigned int credits; /* # of available Rx buffers */
- unsigned int size; /* capacity of free list */
- unsigned int cidx; /* consumer index */
- unsigned int pidx; /* producer index */
- unsigned int gen; /* free list generation */
- unsigned int cntxt_id; /* SGE context id for the free list */
- struct sge_fl_page page;
- struct rx_desc *desc; /* address of HW Rx descriptor ring */
- struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
- dma_addr_t phys_addr; /* physical address of HW ring start */
- unsigned long empty; /* # of times queue ran out of buffers */
+struct sge_fl { /* SGE per free-buffer list state */
+ unsigned int buf_size; /* size of each Rx buffer */
+ unsigned int credits; /* # of available Rx buffers */
+ unsigned int size; /* capacity of free list */
+ unsigned int cidx; /* consumer index */
+ unsigned int pidx; /* producer index */
+ unsigned int gen; /* free list generation */
+ struct fl_pg_chunk pg_chunk;/* page chunk cache */
+ unsigned int use_pages; /* whether FL uses pages or sk_buffs */
+ struct rx_desc *desc; /* address of HW Rx descriptor ring */
+ struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */
+ dma_addr_t phys_addr; /* physical address of HW ring start */
+ unsigned int cntxt_id; /* SGE context id for the free list */
+ unsigned long empty; /* # of times queue ran out of buffers */
unsigned long alloc_failed; /* # of times buffer allocation failed */
};
diff --git a/drivers/net/cxgb3/ael1002.c b/drivers/net/cxgb3/ael1002.c
index 73a41e6a5bf..ee140e63ddc 100644
--- a/drivers/net/cxgb3/ael1002.c
+++ b/drivers/net/cxgb3/ael1002.c
@@ -219,7 +219,13 @@ static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok,
unsigned int status;
status = t3_read_reg(phy->adapter,
- XGM_REG(A_XGM_SERDES_STAT0, phy->addr));
+ XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) |
+ t3_read_reg(phy->adapter,
+ XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) |
+ t3_read_reg(phy->adapter,
+ XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) |
+ t3_read_reg(phy->adapter,
+ XGM_REG(A_XGM_SERDES_STAT3, phy->addr));
*link_ok = !(status & F_LOWSIG0);
}
if (speed)
@@ -247,5 +253,5 @@ static struct cphy_ops xaui_direct_ops = {
void t3_xaui_direct_phy_prep(struct cphy *phy, struct adapter *adapter,
int phy_addr, const struct mdio_ops *mdio_ops)
{
- cphy_init(phy, adapter, 1, &xaui_direct_ops, mdio_ops);
+ cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops);
}
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 8d137963369..16378004507 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -101,6 +101,7 @@ enum {
TCB_SIZE = 128, /* TCB size */
NMTUS = 16, /* size of MTU table */
NCCTRL_WIN = 32, /* # of congestion control windows */
+ PROTO_SRAM_LINES = 128, /* size of TP sram */
};
#define MAX_RX_COALESCING_LEN 16224U
@@ -124,6 +125,30 @@ enum { /* adapter interrupt-maintained statistics */
};
enum {
+ TP_VERSION_MAJOR = 1,
+ TP_VERSION_MINOR = 0,
+ TP_VERSION_MICRO = 44
+};
+
+#define S_TP_VERSION_MAJOR 16
+#define M_TP_VERSION_MAJOR 0xFF
+#define V_TP_VERSION_MAJOR(x) ((x) << S_TP_VERSION_MAJOR)
+#define G_TP_VERSION_MAJOR(x) \
+ (((x) >> S_TP_VERSION_MAJOR) & M_TP_VERSION_MAJOR)
+
+#define S_TP_VERSION_MINOR 8
+#define M_TP_VERSION_MINOR 0xFF
+#define V_TP_VERSION_MINOR(x) ((x) << S_TP_VERSION_MINOR)
+#define G_TP_VERSION_MINOR(x) \
+ (((x) >> S_TP_VERSION_MINOR) & M_TP_VERSION_MINOR)
+
+#define S_TP_VERSION_MICRO 0
+#define M_TP_VERSION_MICRO 0xFF
+#define V_TP_VERSION_MICRO(x) ((x) << S_TP_VERSION_MICRO)
+#define G_TP_VERSION_MICRO(x) \
+ (((x) >> S_TP_VERSION_MICRO) & M_TP_VERSION_MICRO)
+
+enum {
SGE_QSETS = 8, /* # of SGE Tx/Rx/RspQ sets */
SGE_RXQ_PER_SET = 2, /* # of Rx queues per set */
SGE_TXQ_PER_SET = 3 /* # of Tx queues per set */
@@ -654,6 +679,9 @@ const struct adapter_info *t3_get_adapter_info(unsigned int board_id);
int t3_seeprom_read(struct adapter *adapter, u32 addr, u32 *data);
int t3_seeprom_write(struct adapter *adapter, u32 addr, u32 data);
int t3_seeprom_wp(struct adapter *adapter, int enable);
+int t3_check_tpsram_version(struct adapter *adapter);
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_ram, unsigned int size);
+int t3_set_proto_sram(struct adapter *adap, u8 *data);
int t3_read_flash(struct adapter *adapter, unsigned int addr,
unsigned int nwords, u32 *data, int byte_oriented);
int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 67b4b219d92..6fd1e524183 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -43,6 +43,7 @@
#include <linux/proc_fs.h>
#include <linux/rtnetlink.h>
#include <linux/firmware.h>
+#include <linux/log2.h>
#include <asm/uaccess.h>
#include "common.h"
@@ -1818,8 +1819,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
return -EBUSY;
if (copy_from_user(&m, useraddr, sizeof(m)))
return -EFAULT;
- if (!m.rx_pg_sz || (m.rx_pg_sz & (m.rx_pg_sz - 1)) ||
- !m.tx_pg_sz || (m.tx_pg_sz & (m.tx_pg_sz - 1)))
+ if (!is_power_of_2(m.rx_pg_sz) ||
+ !is_power_of_2(m.tx_pg_sz))
return -EINVAL; /* not power of 2 */
if (!(m.rx_pg_sz & 0x14000))
return -EINVAL; /* not 16KB or 64KB */
@@ -2067,22 +2068,63 @@ static void vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
t3_synchronize_rx(adapter, pi);
}
-static void vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- /* nothing */
-}
-
#ifdef CONFIG_NET_POLL_CONTROLLER
static void cxgb_netpoll(struct net_device *dev)
{
struct adapter *adapter = dev->priv;
- struct sge_qset *qs = dev2qset(dev);
+ struct port_info *pi = netdev_priv(dev);
+ int qidx;
+
+ for (qidx = pi->first_qset; qidx < pi->first_qset + pi->nqsets; qidx++) {
+ struct sge_qset *qs = &adapter->sge.qs[qidx];
+ void *source;
+
+ if (adapter->flags & USING_MSIX)
+ source = qs;
+ else
+ source = adapter;
- t3_intr_handler(adapter, qs->rspq.polling) (adapter->pdev->irq,
- adapter);
+ t3_intr_handler(adapter, qs->rspq.polling) (0, source);
+ }
}
#endif
+#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin"
+int update_tpsram(struct adapter *adap)
+{
+ const struct firmware *tpsram;
+ char buf[64];
+ struct device *dev = &adap->pdev->dev;
+ int ret;
+ char rev;
+
+ rev = adap->params.rev == T3_REV_B2 ? 'b' : 'a';
+
+ snprintf(buf, sizeof(buf), TPSRAM_NAME, rev,
+ TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
+
+ ret = request_firmware(&tpsram, buf, dev);
+ if (ret < 0) {
+ dev_err(dev, "could not load TP SRAM: unable to load %s\n",
+ buf);
+ return ret;
+ }
+
+ ret = t3_check_tpsram(adap, tpsram->data, tpsram->size);
+ if (ret)
+ goto release_tpsram;
+
+ ret = t3_set_proto_sram(adap, tpsram->data);
+ if (ret)
+ dev_err(dev, "loading protocol SRAM failed\n");
+
+release_tpsram:
+ release_firmware(tpsram);
+
+ return ret;
+}
+
+
/*
* Periodic accumulation of MAC statistics.
*/
@@ -2409,7 +2451,6 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
netdev->vlan_rx_register = vlan_rx_register;
- netdev->vlan_rx_kill_vid = vlan_rx_kill_vid;
netdev->open = cxgb_open;
netdev->stop = cxgb_close;
@@ -2433,6 +2474,13 @@ static int __devinit init_one(struct pci_dev *pdev,
goto out_free_dev;
}
+ err = t3_check_tpsram_version(adapter);
+ if (err == -EINVAL)
+ err = update_tpsram(adapter);
+
+ if (err)
+ goto out_free_dev;
+
/*
* The card is now ready to go. If any errors occur during device
* registration we do not fail the whole card but rather proceed only
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index e5a553410e2..aa80313c922 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -1160,6 +1160,8 @@
#define A_TP_MOD_CHANNEL_WEIGHT 0x434
+#define A_TP_MOD_RATE_LIMIT 0x438
+
#define A_TP_PIO_ADDR 0x440
#define A_TP_PIO_DATA 0x444
@@ -1214,6 +1216,15 @@
#define G_TXDROPCNTCH0RCVD(x) (((x) >> S_TXDROPCNTCH0RCVD) & \
M_TXDROPCNTCH0RCVD)
+#define A_TP_PROXY_FLOW_CNTL 0x4b0
+
+#define A_TP_EMBED_OP_FIELD0 0x4e8
+#define A_TP_EMBED_OP_FIELD1 0x4ec
+#define A_TP_EMBED_OP_FIELD2 0x4f0
+#define A_TP_EMBED_OP_FIELD3 0x4f4
+#define A_TP_EMBED_OP_FIELD4 0x4f8
+#define A_TP_EMBED_OP_FIELD5 0x4fc
+
#define A_ULPRX_CTL 0x500
#define S_ROUND_ROBIN 4
@@ -1882,6 +1893,10 @@
#define V_COPYALLFRAMES(x) ((x) << S_COPYALLFRAMES)
#define F_COPYALLFRAMES V_COPYALLFRAMES(1U)
+#define S_DISBCAST 1
+#define V_DISBCAST(x) ((x) << S_DISBCAST)
+#define F_DISBCAST V_DISBCAST(1U)
+
#define A_XGM_RX_HASH_LOW 0x814
#define A_XGM_RX_HASH_HIGH 0x818
@@ -2128,6 +2143,8 @@
#define F_RESETPLL01 V_RESETPLL01(1U)
#define A_XGM_SERDES_STAT0 0x8f0
+#define A_XGM_SERDES_STAT1 0x8f4
+#define A_XGM_SERDES_STAT2 0x8f8
#define S_LOWSIG0 0
#define V_LOWSIG0(x) ((x) << S_LOWSIG0)
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index 3666586a483..a2cfd68ac75 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -46,23 +46,16 @@
#define SGE_RX_SM_BUF_SIZE 1536
-/*
- * If USE_RX_PAGE is defined, the small freelist populated with (partial)
- * pages instead of skbs. Pages are carved up into RX_PAGE_SIZE chunks (must
- * be a multiple of the host page size).
- */
-#define USE_RX_PAGE
-#define RX_PAGE_SIZE 2048
-
-/*
- * skb freelist packets are copied into a new skb (and the freelist one is
- * reused) if their len is <=
- */
#define SGE_RX_COPY_THRES 256
+#define SGE_RX_PULL_LEN 128
/*
- * Minimum number of freelist entries before we start dropping TUNNEL frames.
+ * Page chunk size for FL0 buffers if FL0 is to be populated with page chunks.
+ * It must be a divisor of PAGE_SIZE. If set to 0 FL0 will use sk_buffs
+ * directly.
*/
+#define FL0_PG_CHUNK_SIZE 2048
+
#define SGE_RX_DROP_THRES 16
/*
@@ -100,12 +93,12 @@ struct tx_sw_desc { /* SW state per Tx descriptor */
struct sk_buff *skb;
};
-struct rx_sw_desc { /* SW state per Rx descriptor */
+struct rx_sw_desc { /* SW state per Rx descriptor */
union {
struct sk_buff *skb;
- struct sge_fl_page page;
- } t;
- DECLARE_PCI_UNMAP_ADDR(dma_addr);
+ struct fl_pg_chunk pg_chunk;
+ };
+ DECLARE_PCI_UNMAP_ADDR(dma_addr);
};
struct rsp_desc { /* response queue descriptor */
@@ -351,27 +344,26 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
pci_unmap_single(pdev, pci_unmap_addr(d, dma_addr),
q->buf_size, PCI_DMA_FROMDEVICE);
-
- if (q->buf_size != RX_PAGE_SIZE) {
- kfree_skb(d->t.skb);
- d->t.skb = NULL;
+ if (q->use_pages) {
+ put_page(d->pg_chunk.page);
+ d->pg_chunk.page = NULL;
} else {
- if (d->t.page.frag.page)
- put_page(d->t.page.frag.page);
- d->t.page.frag.page = NULL;
+ kfree_skb(d->skb);
+ d->skb = NULL;
}
if (++cidx == q->size)
cidx = 0;
}
- if (q->page.frag.page)
- put_page(q->page.frag.page);
- q->page.frag.page = NULL;
+ if (q->pg_chunk.page) {
+ __free_page(q->pg_chunk.page);
+ q->pg_chunk.page = NULL;
+ }
}
/**
* add_one_rx_buf - add a packet buffer to a free-buffer list
- * @va: va of the buffer to add
+ * @va: buffer start VA
* @len: the buffer length
* @d: the HW Rx descriptor to write
* @sd: the SW Rx descriptor to write
@@ -381,7 +373,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q)
* Add a buffer of the given length to the supplied HW and SW Rx
* descriptors.
*/
-static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
+static inline void add_one_rx_buf(void *va, unsigned int len,
struct rx_desc *d, struct rx_sw_desc *sd,
unsigned int gen, struct pci_dev *pdev)
{
@@ -397,6 +389,27 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
d->gen2 = cpu_to_be32(V_FLD_GEN2(gen));
}
+static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp)
+{
+ if (!q->pg_chunk.page) {
+ q->pg_chunk.page = alloc_page(gfp);
+ if (unlikely(!q->pg_chunk.page))
+ return -ENOMEM;
+ q->pg_chunk.va = page_address(q->pg_chunk.page);
+ q->pg_chunk.offset = 0;
+ }
+ sd->pg_chunk = q->pg_chunk;
+
+ q->pg_chunk.offset += q->buf_size;
+ if (q->pg_chunk.offset == PAGE_SIZE)
+ q->pg_chunk.page = NULL;
+ else {
+ q->pg_chunk.va += q->buf_size;
+ get_page(q->pg_chunk.page);
+ }
+ return 0;
+}
+
/**
* refill_fl - refill an SGE free-buffer list
* @adapter: the adapter
@@ -410,49 +423,29 @@ static inline void add_one_rx_buf(unsigned char *va, unsigned int len,
*/
static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp)
{
+ void *buf_start;
struct rx_sw_desc *sd = &q->sdesc[q->pidx];
struct rx_desc *d = &q->desc[q->pidx];
- struct sge_fl_page *p = &q->page;
while (n--) {
- unsigned char *va;
-
- if (unlikely(q->buf_size != RX_PAGE_SIZE)) {
- struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
-
- if (!skb) {
- q->alloc_failed++;
+ if (q->use_pages) {
+ if (unlikely(alloc_pg_chunk(q, sd, gfp))) {
+nomem: q->alloc_failed++;
break;
}
- va = skb->data;
- sd->t.skb = skb;
+ buf_start = sd->pg_chunk.va;
} else {
- if (!p->frag.page) {
- p->frag.page = alloc_pages(gfp, 0);
- if (unlikely(!p->frag.page)) {
- q->alloc_failed++;
- break;
- } else {
- p->frag.size = RX_PAGE_SIZE;
- p->frag.page_offset = 0;
- p->va = page_address(p->frag.page);
- }
- }
+ struct sk_buff *skb = alloc_skb(q->buf_size, gfp);
- memcpy(&sd->t, p, sizeof(*p));
- va = p->va;
+ if (!skb)
+ goto nomem;
- p->frag.page_offset += RX_PAGE_SIZE;
- BUG_ON(p->frag.page_offset > PAGE_SIZE);
- p->va += RX_PAGE_SIZE;
- if (p->frag.page_offset == PAGE_SIZE)
- p->frag.page = NULL;
- else
- get_page(p->frag.page);
+ sd->skb = skb;
+ buf_start = skb->data;
}
- add_one_rx_buf(va, q->buf_size, d, sd, q->gen, adap->pdev);
-
+ add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen,
+ adap->pdev);
d++;
sd++;
if (++q->pidx == q->size) {
@@ -487,7 +480,7 @@ static void recycle_rx_buf(struct adapter *adap, struct sge_fl *q,
struct rx_desc *from = &q->desc[idx];
struct rx_desc *to = &q->desc[q->pidx];
- memcpy(&q->sdesc[q->pidx], &q->sdesc[idx], sizeof(struct rx_sw_desc));
+ q->sdesc[q->pidx] = q->sdesc[idx];
to->addr_lo = from->addr_lo; /* already big endian */
to->addr_hi = from->addr_hi; /* likewise */
wmb();
@@ -650,6 +643,132 @@ static inline unsigned int flits_to_desc(unsigned int n)
}
/**
+ * get_packet - return the next ingress packet buffer from a free list
+ * @adap: the adapter that received the packet
+ * @fl: the SGE free list holding the packet
+ * @len: the packet length including any SGE padding
+ * @drop_thres: # of remaining buffers before we start dropping packets
+ *
+ * Get the next packet from a free list and complete setup of the
+ * sk_buff. If the packet is small we make a copy and recycle the
+ * original buffer, otherwise we use the original buffer itself. If a
+ * positive drop threshold is supplied packets are dropped and their
+ * buffers recycled if (a) the number of remaining buffers is under the
+ * threshold and the packet is too big to copy, or (b) the packet should
+ * be copied but there is no memory for the copy.
+ */
+static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
+ unsigned int len, unsigned int drop_thres)
+{
+ struct sk_buff *skb = NULL;
+ struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+ prefetch(sd->skb->data);
+ fl->credits--;
+
+ if (len <= SGE_RX_COPY_THRES) {
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (likely(skb != NULL)) {
+ __skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, sd->skb->data, len);
+ pci_dma_sync_single_for_device(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ } else if (!drop_thres)
+ goto use_orig_buf;
+recycle:
+ recycle_rx_buf(adap, fl, fl->cidx);
+ return skb;
+ }
+
+ if (unlikely(fl->credits < drop_thres))
+ goto recycle;
+
+use_orig_buf:
+ pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+ fl->buf_size, PCI_DMA_FROMDEVICE);
+ skb = sd->skb;
+ skb_put(skb, len);
+ __refill_fl(adap, fl);
+ return skb;
+}
+
+/**
+ * get_packet_pg - return the next ingress packet buffer from a free list
+ * @adap: the adapter that received the packet
+ * @fl: the SGE free list holding the packet
+ * @len: the packet length including any SGE padding
+ * @drop_thres: # of remaining buffers before we start dropping packets
+ *
+ * Get the next packet from a free list populated with page chunks.
+ * If the packet is small we make a copy and recycle the original buffer,
+ * otherwise we attach the original buffer as a page fragment to a fresh
+ * sk_buff. If a positive drop threshold is supplied packets are dropped
+ * and their buffers recycled if (a) the number of remaining buffers is
+ * under the threshold and the packet is too big to copy, or (b) there's
+ * no system memory.
+ *
+ * Note: this function is similar to @get_packet but deals with Rx buffers
+ * that are page chunks rather than sk_buffs.
+ */
+static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl,
+ unsigned int len, unsigned int drop_thres)
+{
+ struct sk_buff *skb = NULL;
+ struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
+
+ if (len <= SGE_RX_COPY_THRES) {
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (likely(skb != NULL)) {
+ __skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ memcpy(skb->data, sd->pg_chunk.va, len);
+ pci_dma_sync_single_for_device(adap->pdev,
+ pci_unmap_addr(sd, dma_addr), len,
+ PCI_DMA_FROMDEVICE);
+ } else if (!drop_thres)
+ return NULL;
+recycle:
+ fl->credits--;
+ recycle_rx_buf(adap, fl, fl->cidx);
+ return skb;
+ }
+
+ if (unlikely(fl->credits <= drop_thres))
+ goto recycle;
+
+ skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC);
+ if (unlikely(!skb)) {
+ if (!drop_thres)
+ return NULL;
+ goto recycle;
+ }
+
+ pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
+ fl->buf_size, PCI_DMA_FROMDEVICE);
+ __skb_put(skb, SGE_RX_PULL_LEN);
+ memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN);
+ skb_fill_page_desc(skb, 0, sd->pg_chunk.page,
+ sd->pg_chunk.offset + SGE_RX_PULL_LEN,
+ len - SGE_RX_PULL_LEN);
+ skb->len = len;
+ skb->data_len = len - SGE_RX_PULL_LEN;
+ skb->truesize += skb->data_len;
+
+ fl->credits--;
+ /*
+ * We do not refill FLs here, we let the caller do it to overlap a
+ * prefetch.
+ */
+ return skb;
+}
+
+/**
* get_imm_packet - return the next ingress packet buffer from a response
* @resp: the response descriptor containing the packet data
*
@@ -1690,8 +1809,8 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
struct port_info *pi;
skb_pull(skb, sizeof(*p) + pad);
- skb->dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
+ skb->dev->last_rx = jiffies;
pi = netdev_priv(skb->dev);
if (pi->rx_csum_offload && p->csum_valid && p->csum == 0xffff &&
!p->fragment) {
@@ -1715,85 +1834,6 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
netif_rx(skb);
}
-#define SKB_DATA_SIZE 128
-
-static void skb_data_init(struct sk_buff *skb, struct sge_fl_page *p,
- unsigned int len)
-{
- skb->len = len;
- if (len <= SKB_DATA_SIZE) {
- skb_copy_to_linear_data(skb, p->va, len);
- skb->tail += len;
- put_page(p->frag.page);
- } else {
- skb_copy_to_linear_data(skb, p->va, SKB_DATA_SIZE);
- skb_shinfo(skb)->frags[0].page = p->frag.page;
- skb_shinfo(skb)->frags[0].page_offset =
- p->frag.page_offset + SKB_DATA_SIZE;
- skb_shinfo(skb)->frags[0].size = len - SKB_DATA_SIZE;
- skb_shinfo(skb)->nr_frags = 1;
- skb->data_len = len - SKB_DATA_SIZE;
- skb->tail += SKB_DATA_SIZE;
- skb->truesize += skb->data_len;
- }
-}
-
-/**
-* get_packet - return the next ingress packet buffer from a free list
-* @adap: the adapter that received the packet
-* @fl: the SGE free list holding the packet
-* @len: the packet length including any SGE padding
-* @drop_thres: # of remaining buffers before we start dropping packets
-*
-* Get the next packet from a free list and complete setup of the
-* sk_buff. If the packet is small we make a copy and recycle the
-* original buffer, otherwise we use the original buffer itself. If a
-* positive drop threshold is supplied packets are dropped and their
-* buffers recycled if (a) the number of remaining buffers is under the
-* threshold and the packet is too big to copy, or (b) the packet should
-* be copied but there is no memory for the copy.
-*/
-static struct sk_buff *get_packet(struct adapter *adap, struct sge_fl *fl,
- unsigned int len, unsigned int drop_thres)
-{
- struct sk_buff *skb = NULL;
- struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
-
- prefetch(sd->t.skb->data);
-
- if (len <= SGE_RX_COPY_THRES) {
- skb = alloc_skb(len, GFP_ATOMIC);
- if (likely(skb != NULL)) {
- struct rx_desc *d = &fl->desc[fl->cidx];
- dma_addr_t mapping =
- (dma_addr_t)((u64) be32_to_cpu(d->addr_hi) << 32 |
- be32_to_cpu(d->addr_lo));
-
- __skb_put(skb, len);
- pci_dma_sync_single_for_cpu(adap->pdev, mapping, len,
- PCI_DMA_FROMDEVICE);
- skb_copy_from_linear_data(sd->t.skb, skb->data, len);
- pci_dma_sync_single_for_device(adap->pdev, mapping, len,
- PCI_DMA_FROMDEVICE);
- } else if (!drop_thres)
- goto use_orig_buf;
-recycle:
- recycle_rx_buf(adap, fl, fl->cidx);
- return skb;
- }
-
- if (unlikely(fl->credits < drop_thres))
- goto recycle;
-
-use_orig_buf:
- pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr),
- fl->buf_size, PCI_DMA_FROMDEVICE);
- skb = sd->t.skb;
- skb_put(skb, len);
- __refill_fl(adap, fl);
- return skb;
-}
-
/**
* handle_rsp_cntrl_info - handles control information in a response
* @qs: the queue set corresponding to the response
@@ -1935,7 +1975,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
} else if (flags & F_RSPD_IMM_DATA_VALID) {
skb = get_imm_packet(r);
if (unlikely(!skb)) {
- no_mem:
+no_mem:
q->next_holdoff = NOMEM_INTR_DELAY;
q->nomem++;
/* consume one credit since we tried */
@@ -1945,53 +1985,29 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
q->imm_data++;
ethpad = 0;
} else if ((len = ntohl(r->len_cq)) != 0) {
- struct sge_fl *fl =
- (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+ struct sge_fl *fl;
- if (fl->buf_size == RX_PAGE_SIZE) {
- struct rx_sw_desc *sd = &fl->sdesc[fl->cidx];
- struct sge_fl_page *p = &sd->t.page;
-
- prefetch(p->va);
- prefetch(p->va + L1_CACHE_BYTES);
+ fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0];
+ if (fl->use_pages) {
+ void *addr = fl->sdesc[fl->cidx].pg_chunk.va;
+ prefetch(addr);
+#if L1_CACHE_BYTES < 128
+ prefetch(addr + L1_CACHE_BYTES);
+#endif
__refill_fl(adap, fl);
- pci_unmap_single(adap->pdev,
- pci_unmap_addr(sd, dma_addr),
- fl->buf_size,
- PCI_DMA_FROMDEVICE);
-
- if (eth) {
- if (unlikely(fl->credits <
- SGE_RX_DROP_THRES))
- goto eth_recycle;
-
- skb = alloc_skb(SKB_DATA_SIZE,
- GFP_ATOMIC);
- if (unlikely(!skb)) {
-eth_recycle:
- q->rx_drops++;
- recycle_rx_buf(adap, fl,
- fl->cidx);
- goto eth_done;
- }
- } else {
- skb = alloc_skb(SKB_DATA_SIZE,
- GFP_ATOMIC);
- if (unlikely(!skb))
- goto no_mem;
- }
-
- skb_data_init(skb, p, G_RSPD_LEN(len));
-eth_done:
- fl->credits--;
- q->eth_pkts++;
- } else {
- fl->credits--;
+ skb = get_packet_pg(adap, fl, G_RSPD_LEN(len),
+ eth ? SGE_RX_DROP_THRES : 0);
+ } else
skb = get_packet(adap, fl, G_RSPD_LEN(len),
eth ? SGE_RX_DROP_THRES : 0);
- }
+ if (unlikely(!skb)) {
+ if (!eth)
+ goto no_mem;
+ q->rx_drops++;
+ } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT))
+ __skb_pull(skb, 2);
if (++fl->cidx == fl->size)
fl->cidx = 0;
@@ -2016,20 +2032,15 @@ eth_done:
q->credits = 0;
}
- if (skb) {
- /* Preserve the RSS info in csum & priority */
- skb->csum = rss_hi;
- skb->priority = rss_lo;
-
+ if (likely(skb != NULL)) {
if (eth)
rx_eth(adap, q, skb, ethpad);
else {
- if (unlikely(r->rss_hdr.opcode ==
- CPL_TRACE_PKT))
- __skb_pull(skb, ethpad);
-
- ngathered = rx_offload(&adap->tdev, q,
- skb, offload_skbs,
+ /* Preserve the RSS info in csum & priority */
+ skb->csum = rss_hi;
+ skb->priority = rss_lo;
+ ngathered = rx_offload(&adap->tdev, q, skb,
+ offload_skbs,
ngathered);
}
}
@@ -2217,7 +2228,6 @@ irqreturn_t t3_sge_intr_msix_napi(int irq, void *cookie)
struct sge_rspq *q = &qs->rspq;
spin_lock(&q->lock);
- BUG_ON(napi_is_scheduled(qs->netdev));
if (handle_responses(adap, q) < 0)
q->unhandled_irqs++;
@@ -2636,25 +2646,15 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
q->txq[TXQ_ETH].stop_thres = nports *
flits_to_desc(sgl_len(MAX_SKB_FRAGS + 1) + 3);
- if (!is_offload(adapter)) {
-#ifdef USE_RX_PAGE
- q->fl[0].buf_size = RX_PAGE_SIZE;
+#if FL0_PG_CHUNK_SIZE > 0
+ q->fl[0].buf_size = FL0_PG_CHUNK_SIZE;
#else
- q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + 2 +
- sizeof(struct cpl_rx_pkt);
+ q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data);
#endif
- q->fl[1].buf_size = MAX_FRAME_SIZE + 2 +
- sizeof(struct cpl_rx_pkt);
- } else {
-#ifdef USE_RX_PAGE
- q->fl[0].buf_size = RX_PAGE_SIZE;
-#else
- q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE +
- sizeof(struct cpl_rx_data);
-#endif
- q->fl[1].buf_size = (16 * 1024) -
- SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- }
+ q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0;
+ q->fl[1].buf_size = is_offload(adapter) ?
+ (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
+ MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
spin_lock(&adapter->sge.reg_lock);
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index fb485d0a43d..dd3149d94ba 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -847,6 +847,64 @@ static int t3_write_flash(struct adapter *adapter, unsigned int addr,
return 0;
}
+/**
+ * t3_check_tpsram_version - read the tp sram version
+ * @adapter: the adapter
+ *
+ * Reads the protocol sram version from serial eeprom.
+ */
+int t3_check_tpsram_version(struct adapter *adapter)
+{
+ int ret;
+ u32 vers;
+ unsigned int major, minor;
+
+ /* Get version loaded in SRAM */
+ t3_write_reg(adapter, A_TP_EMBED_OP_FIELD0, 0);
+ ret = t3_wait_op_done(adapter, A_TP_EMBED_OP_FIELD0,
+ 1, 1, 5, 1);
+ if (ret)
+ return ret;
+
+ vers = t3_read_reg(adapter, A_TP_EMBED_OP_FIELD1);
+
+ major = G_TP_VERSION_MAJOR(vers);
+ minor = G_TP_VERSION_MINOR(vers);
+
+ if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * t3_check_tpsram - check if provided protocol SRAM
+ * is compatible with this driver
+ * @adapter: the adapter
+ * @tp_sram: the firmware image to write
+ * @size: image size
+ *
+ * Checks if an adapter's tp sram is compatible with the driver.
+ * Returns 0 if the versions are compatible, a negative error otherwise.
+ */
+int t3_check_tpsram(struct adapter *adapter, u8 *tp_sram, unsigned int size)
+{
+ u32 csum;
+ unsigned int i;
+ const u32 *p = (const u32 *)tp_sram;
+
+ /* Verify checksum */
+ for (csum = 0, i = 0; i < size / sizeof(csum); i++)
+ csum += ntohl(p[i]);
+ if (csum != 0xffffffff) {
+ CH_ERR(adapter, "corrupted protocol SRAM image, checksum %u\n",
+ csum);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
enum fw_version_type {
FW_VERSION_N3,
FW_VERSION_T3
@@ -921,7 +979,7 @@ static int t3_flash_erase_sectors(struct adapter *adapter, int start, int end)
/*
* t3_load_fw - download firmware
* @adapter: the adapter
- * @fw_data: the firrware image to write
+ * @fw_data: the firmware image to write
* @size: image size
*
* Write the supplied firmware image to the card's serial flash.
@@ -2362,7 +2420,7 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
F_TCPCHECKSUMOFFLOAD | V_IPTTL(64));
t3_write_reg(adap, A_TP_TCP_OPTIONS, V_MTUDEFAULT(576) |
F_MTUENABLE | V_WINDOWSCALEMODE(1) |
- V_TIMESTAMPSMODE(1) | V_SACKMODE(1) | V_SACKRX(1));
+ V_TIMESTAMPSMODE(0) | V_SACKMODE(1) | V_SACKRX(1));
t3_write_reg(adap, A_TP_DACK_CONFIG, V_AUTOSTATE3(1) |
V_AUTOSTATE2(1) | V_AUTOSTATE1(0) |
V_BYTETHRESHOLD(16384) | V_MSSTHRESHOLD(2) |
@@ -2371,16 +2429,18 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
F_IPV6ENABLE | F_NICMODE);
t3_write_reg(adap, A_TP_TX_RESOURCE_LIMIT, 0x18141814);
t3_write_reg(adap, A_TP_PARA_REG4, 0x5050105);
- t3_set_reg_field(adap, A_TP_PARA_REG6,
- adap->params.rev > 0 ? F_ENABLEESND : F_T3A_ENABLEESND,
- 0);
+ t3_set_reg_field(adap, A_TP_PARA_REG6, 0,
+ adap->params.rev > 0 ? F_ENABLEESND :
+ F_T3A_ENABLEESND);
t3_set_reg_field(adap, A_TP_PC_CONFIG,
- F_ENABLEEPCMDAFULL | F_ENABLEOCSPIFULL,
- F_TXDEFERENABLE | F_HEARBEATDACK | F_TXCONGESTIONMODE |
- F_RXCONGESTIONMODE);
+ F_ENABLEEPCMDAFULL,
+ F_ENABLEOCSPIFULL |F_TXDEFERENABLE | F_HEARBEATDACK |
+ F_TXCONGESTIONMODE | F_RXCONGESTIONMODE);
t3_set_reg_field(adap, A_TP_PC_CONFIG2, F_CHDRAFULL, 0);
-
+ t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1080);
+ t3_write_reg(adap, A_TP_PROXY_FLOW_CNTL, 1000);
+
if (adap->params.rev > 0) {
tp_wr_indirect(adap, A_TP_EGRESS_CONFIG, F_REWRITEFORCETOSIZE);
t3_set_reg_field(adap, A_TP_PARA_REG3, F_TXPACEAUTO,
@@ -2390,9 +2450,10 @@ static void tp_config(struct adapter *adap, const struct tp_params *p)
} else
t3_set_reg_field(adap, A_TP_PARA_REG3, 0, F_TXPACEFIXED);
- t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0x12121212);
- t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0x12121212);
- t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0x1212);
+ t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
+ t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
+ t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
+ t3_write_reg(adap, A_TP_MOD_RATE_LIMIT, 0xf2200000);
}
/* Desired TP timer resolution in usec */
@@ -2468,6 +2529,7 @@ int t3_tp_set_coalescing_size(struct adapter *adap, unsigned int size, int psh)
val |= F_RXCOALESCEENABLE;
if (psh)
val |= F_RXCOALESCEPSHEN;
+ size = min(MAX_RX_COALESCING_LEN, size);
t3_write_reg(adap, A_TP_PARA_REG2, V_RXCOALESCESIZE(size) |
V_MAXRXDATA(MAX_RX_COALESCING_LEN));
}
@@ -2496,11 +2558,11 @@ static void __devinit init_mtus(unsigned short mtus[])
* it can accomodate max size TCP/IP headers when SACK and timestamps
* are enabled and still have at least 8 bytes of payload.
*/
- mtus[0] = 88;
- mtus[1] = 256;
- mtus[2] = 512;
- mtus[3] = 576;
- mtus[4] = 808;
+ mtus[1] = 88;
+ mtus[1] = 88;
+ mtus[2] = 256;
+ mtus[3] = 512;
+ mtus[4] = 576;
mtus[5] = 1024;
mtus[6] = 1280;
mtus[7] = 1492;
@@ -2682,6 +2744,34 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p)
t3_write_reg(adap, A_ULPRX_TDDP_TAGMASK, 0xffffffff);
}
+/**
+ * t3_set_proto_sram - set the contents of the protocol sram
+ * @adapter: the adapter
+ * @data: the protocol image
+ *
+ * Write the contents of the protocol SRAM.
+ */
+int t3_set_proto_sram(struct adapter *adap, u8 *data)
+{
+ int i;
+ u32 *buf = (u32 *)data;
+
+ for (i = 0; i < PROTO_SRAM_LINES; i++) {
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD5, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD4, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD3, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD2, cpu_to_be32(*buf++));
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD1, cpu_to_be32(*buf++));
+
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, i << 1 | 1 << 31);
+ if (t3_wait_op_done(adap, A_TP_EMBED_OP_FIELD0, 1, 1, 5, 1))
+ return -EIO;
+ }
+ t3_write_reg(adap, A_TP_EMBED_OP_FIELD0, 0);
+
+ return 0;
+}
+
void t3_config_trace_filter(struct adapter *adapter,
const struct trace_params *tp, int filter_index,
int invert, int enable)
@@ -2802,7 +2892,7 @@ static void init_hw_for_avail_ports(struct adapter *adap, int nports)
t3_set_reg_field(adap, A_ULPTX_CONFIG, F_CFG_RR_ARB, 0);
t3_write_reg(adap, A_MPS_CFG, F_TPRXPORTEN | F_TPTXPORT0EN |
F_PORT0ACTIVE | F_ENFORCEPKT);
- t3_write_reg(adap, A_PM1_TX_CFG, 0xc000c000);
+ t3_write_reg(adap, A_PM1_TX_CFG, 0xffffffff);
} else {
t3_set_reg_field(adap, A_ULPRX_CTL, 0, F_ROUND_ROBIN);
t3_set_reg_field(adap, A_ULPTX_CONFIG, 0, F_CFG_RR_ARB);
@@ -3097,7 +3187,7 @@ int t3_init_hw(struct adapter *adapter, u32 fw_params)
else
t3_set_reg_field(adapter, A_PCIX_CFG, 0, F_CLIDECEN);
- t3_write_reg(adapter, A_PM1_RX_CFG, 0xf000f000);
+ t3_write_reg(adapter, A_PM1_RX_CFG, 0xffffffff);
init_hw_for_avail_ports(adapter, adapter->params.nports);
t3_sge_init(adapter, &adapter->params.sge);
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
index b112317f033..eb508bf8022 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/cxgb3/version.h
@@ -39,6 +39,6 @@
/* Firmware version */
#define FW_VERSION_MAJOR 4
-#define FW_VERSION_MINOR 0
+#define FW_VERSION_MINOR 3
#define FW_VERSION_MICRO 0
#endif /* __CHELSIO_VERSION_H */
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c
index a506792f957..c302b1a30cb 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/cxgb3/xgmac.c
@@ -231,6 +231,28 @@ int t3_mac_set_num_ucast(struct cmac *mac, int n)
return 0;
}
+static void disable_exact_filters(struct cmac *mac)
+{
+ unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
+
+ for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
+ u32 v = t3_read_reg(mac->adapter, reg);
+ t3_write_reg(mac->adapter, reg, v);
+ }
+ t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
+}
+
+static void enable_exact_filters(struct cmac *mac)
+{
+ unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
+
+ for (i = 0; i < EXACT_ADDR_FILTERS; i++, reg += 8) {
+ u32 v = t3_read_reg(mac->adapter, reg);
+ t3_write_reg(mac->adapter, reg, v);
+ }
+ t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
+}
+
/* Calculate the RX hash filter index of an Ethernet address */
static int hash_hw_addr(const u8 * addr)
{
@@ -281,6 +303,14 @@ int t3_mac_set_rx_mode(struct cmac *mac, struct t3_rx_mode *rm)
return 0;
}
+static int rx_fifo_hwm(int mtu)
+{
+ int hwm;
+
+ hwm = max(MAC_RXFIFO_SIZE - 3 * mtu, (MAC_RXFIFO_SIZE * 38) / 100);
+ return min(hwm, MAC_RXFIFO_SIZE - 8192);
+}
+
int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
{
int hwm, lwm;
@@ -305,12 +335,41 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
hwm = min(hwm, MAC_RXFIFO_SIZE - 8192);
lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
+ if (adap->params.rev == T3_REV_B2 &&
+ (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
+ disable_exact_filters(mac);
+ v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
+ t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
+ F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
+
+ /* drain rx FIFO */
+ if (t3_wait_op_done(adap,
+ A_XGM_RX_MAX_PKT_SIZE_ERR_CNT +
+ mac->offset,
+ 1 << 31, 1, 20, 5)) {
+ t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
+ enable_exact_filters(mac);
+ return -EIO;
+ }
+ t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
+ t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
+ enable_exact_filters(mac);
+ } else
+ t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
+
+ /*
+ * Adjust the PAUSE frame watermarks. We always set the LWM, and the
+ * HWM only if flow-control is enabled.
+ */
+ hwm = rx_fifo_hwm(mtu);
+ lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
v = t3_read_reg(adap, A_XGM_RXFIFO_CFG + mac->offset);
v &= ~V_RXFIFOPAUSELWM(M_RXFIFOPAUSELWM);
v |= V_RXFIFOPAUSELWM(lwm / 8);
if (G_RXFIFOPAUSEHWM(v))
v = (v & ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM)) |
V_RXFIFOPAUSEHWM(hwm / 8);
+
t3_write_reg(adap, A_XGM_RXFIFO_CFG + mac->offset, v);
/* Adjust the TX FIFO threshold based on the MTU */
@@ -329,7 +388,6 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
(hwm - lwm) * 4 / 8);
t3_write_reg(adap, A_XGM_TX_PAUSE_QUANTA + mac->offset,
MAC_RXFIFO_SIZE * 4 * 8 / 512);
-
return 0;
}
@@ -357,6 +415,15 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
V_PORTSPEED(M_PORTSPEED), val);
}
+ val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
+ val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
+ if (fc & PAUSE_TX)
+ val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(
+ t3_read_reg(adap,
+ A_XGM_RX_MAX_PKT_SIZE
+ + oft)) / 8);
+ t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
+
t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
(fc & PAUSE_RX) ? F_TXPAUSEEN : 0);
return 0;
@@ -436,6 +503,10 @@ int t3b2_mac_watchdog_task(struct cmac *mac)
unsigned int rx_xcnt;
int status;
+ status = 0;
+ tx_xcnt = 1; /* By default tx_xcnt is making progress */
+ tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt */
+ rx_xcnt = 1; /* By default rx_xcnt is making progress */
if (tx_mcnt == mac->tx_mcnt) {
tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
A_XGM_TX_SPI4_SOP_EOP_CNT +
@@ -446,37 +517,44 @@ int t3b2_mac_watchdog_task(struct cmac *mac)
tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
A_TP_PIO_DATA)));
} else {
- mac->toggle_cnt = 0;
- return 0;
+ goto rxcheck;
}
} else {
mac->toggle_cnt = 0;
- return 0;
+ goto rxcheck;
}
if (((tx_tcnt != mac->tx_tcnt) &&
(tx_xcnt == 0) && (mac->tx_xcnt == 0)) ||
((mac->tx_mcnt == tx_mcnt) &&
(tx_xcnt != 0) && (mac->tx_xcnt != 0))) {
- if (mac->toggle_cnt > 4)
+ if (mac->toggle_cnt > 4) {
status = 2;
- else
+ goto out;
+ } else {
status = 1;
+ goto out;
+ }
} else {
mac->toggle_cnt = 0;
- return 0;
+ goto rxcheck;
}
+rxcheck:
if (rx_mcnt != mac->rx_mcnt)
rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
A_XGM_RX_SPI4_SOP_EOP_CNT +
mac->offset)));
- else
- return 0;
+ else
+ goto out;
- if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0)
+ if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 &&
+ mac->rx_xcnt == 0) {
status = 2;
-
+ goto out;
+ }
+
+out:
mac->tx_tcnt = tx_tcnt;
mac->tx_xcnt = tx_xcnt;
mac->tx_mcnt = s->tx_frames;
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index 74ec64a1625..04e3710c908 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -250,7 +250,6 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
np->an_enable = 1;
mii_set_media (dev);
}
- pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id);
err = register_netdev (dev);
if (err)
@@ -866,9 +865,9 @@ receive_packet (struct net_device *dev)
PCI_DMA_FROMDEVICE);
/* 16 byte align the IP header */
skb_reserve (skb, 2);
- eth_copy_and_sum (skb,
+ skb_copy_to_linear_data (skb,
np->rx_skbuff[entry]->data,
- pkt_len, 0);
+ pkt_len);
skb_put (skb, pkt_len);
pci_dma_sync_single_for_device(np->pdev,
desc->fraginfo &
@@ -879,7 +878,7 @@ receive_packet (struct net_device *dev)
skb->protocol = eth_type_trans (skb, dev);
#if 0
/* Checksum done by hw, but csum value unavailable. */
- if (np->pci_rev_id >= 0x0c &&
+ if (np->pdev->pci_rev_id >= 0x0c &&
!(frame_status & (TCPError | UDPError | IPError))) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h
index 814c449c359..e443065a452 100644
--- a/drivers/net/dl2k.h
+++ b/drivers/net/dl2k.h
@@ -668,7 +668,6 @@ struct netdev_private {
unsigned int rx_flow:1; /* Rx flow control enable */
unsigned int phy_media:1; /* 1: fiber, 0: copper */
unsigned int link_status:1; /* Current link status */
- unsigned char pci_rev_id; /* PCI revision ID */
struct netdev_desc *last_tx; /* Last Tx descriptor used. */
unsigned long cur_rx, old_rx; /* Producer/consumer ring indices */
unsigned long cur_tx, old_tx;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 264fa0e2e07..c3de81bf090 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -104,6 +104,18 @@
#define PRINTK(args...) printk(KERN_DEBUG args)
#endif
+#ifdef CONFIG_BLACKFIN
+#define readsb insb
+#define readsw insw
+#define readsl insl
+#define writesb outsb
+#define writesw outsw
+#define writesl outsl
+#define DM9000_IRQ_FLAGS (IRQF_SHARED | IRQF_TRIGGER_HIGH)
+#else
+#define DM9000_IRQ_FLAGS IRQF_SHARED
+#endif
+
/*
* Transmit timeout, default 5 seconds.
*/
@@ -431,6 +443,9 @@ dm9000_probe(struct platform_device *pdev)
db->io_addr = (void __iomem *)base;
db->io_data = (void __iomem *)(base + 4);
+ /* ensure at least we have a default set of IO routines */
+ dm9000_set_io(db, 2);
+
} else {
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -614,7 +629,7 @@ dm9000_open(struct net_device *dev)
PRINTK2("entering dm9000_open\n");
- if (request_irq(dev->irq, &dm9000_interrupt, IRQF_SHARED, dev->name, dev))
+ if (request_irq(dev->irq, &dm9000_interrupt, DM9000_IRQ_FLAGS, dev->name, dev))
return -EAGAIN;
/* Initialize DM9000 board */
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 60673bc292c..756a6bcb038 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -34,11 +34,12 @@
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
+#include <linux/rtnetlink.h>
+#include <net/rtnetlink.h>
static int numdummies = 1;
static int dummy_xmit(struct sk_buff *skb, struct net_device *dev);
-static struct net_device_stats *dummy_get_stats(struct net_device *dev);
static int dummy_set_address(struct net_device *dev, void *p)
{
@@ -56,13 +57,13 @@ static void set_multicast_list(struct net_device *dev)
{
}
-static void __init dummy_setup(struct net_device *dev)
+static void dummy_setup(struct net_device *dev)
{
/* Initialize the device structure. */
- dev->get_stats = dummy_get_stats;
dev->hard_start_xmit = dummy_xmit;
dev->set_multicast_list = set_multicast_list;
dev->set_mac_address = dummy_set_address;
+ dev->destructor = free_netdev;
/* Fill in device structure with ethernet-generic values. */
ether_setup(dev);
@@ -76,77 +77,80 @@ static void __init dummy_setup(struct net_device *dev)
static int dummy_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct net_device_stats *stats = netdev_priv(dev);
-
- stats->tx_packets++;
- stats->tx_bytes+=skb->len;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
dev_kfree_skb(skb);
return 0;
}
-static struct net_device_stats *dummy_get_stats(struct net_device *dev)
+static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
{
- return netdev_priv(dev);
+ if (tb[IFLA_ADDRESS]) {
+ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+ return -EINVAL;
+ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+ return -EADDRNOTAVAIL;
+ }
+ return 0;
}
-static struct net_device **dummies;
+static struct rtnl_link_ops dummy_link_ops __read_mostly = {
+ .kind = "dummy",
+ .setup = dummy_setup,
+ .validate = dummy_validate,
+};
/* Number of dummy devices to be set up by this module. */
module_param(numdummies, int, 0);
MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
-static int __init dummy_init_one(int index)
+static int __init dummy_init_one(void)
{
struct net_device *dev_dummy;
int err;
- dev_dummy = alloc_netdev(sizeof(struct net_device_stats),
- "dummy%d", dummy_setup);
-
+ dev_dummy = alloc_netdev(0, "dummy%d", dummy_setup);
if (!dev_dummy)
return -ENOMEM;
- if ((err = register_netdev(dev_dummy))) {
- free_netdev(dev_dummy);
- dev_dummy = NULL;
- } else {
- dummies[index] = dev_dummy;
- }
+ err = dev_alloc_name(dev_dummy, dev_dummy->name);
+ if (err < 0)
+ goto err;
- return err;
-}
+ dev_dummy->rtnl_link_ops = &dummy_link_ops;
+ err = register_netdevice(dev_dummy);
+ if (err < 0)
+ goto err;
+ return 0;
-static void dummy_free_one(int index)
-{
- unregister_netdev(dummies[index]);
- free_netdev(dummies[index]);
+err:
+ free_netdev(dev_dummy);
+ return err;
}
static int __init dummy_init_module(void)
{
int i, err = 0;
- dummies = kmalloc(numdummies * sizeof(void *), GFP_KERNEL);
- if (!dummies)
- return -ENOMEM;
+
+ rtnl_lock();
+ err = __rtnl_link_register(&dummy_link_ops);
+
for (i = 0; i < numdummies && !err; i++)
- err = dummy_init_one(i);
- if (err) {
- i--;
- while (--i >= 0)
- dummy_free_one(i);
- }
+ err = dummy_init_one();
+ if (err < 0)
+ __rtnl_link_unregister(&dummy_link_ops);
+ rtnl_unlock();
+
return err;
}
static void __exit dummy_cleanup_module(void)
{
- int i;
- for (i = 0; i < numdummies; i++)
- dummy_free_one(i);
- kfree(dummies);
+ rtnl_link_unregister(&dummy_link_ops);
}
module_init(dummy_init_module);
module_exit(dummy_cleanup_module);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_RTNL_LINK("dummy");
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 61696637a21..6b6401e9304 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -159,7 +159,7 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.5.17-k4"DRV_EXT
+#define DRV_VERSION "3.5.23-k4"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation"
#define PFX DRV_NAME ": "
@@ -285,6 +285,12 @@ enum scb_status {
rus_mask = 0x3C,
};
+enum ru_state {
+ RU_SUSPENDED = 0,
+ RU_RUNNING = 1,
+ RU_UNINITIALIZED = -1,
+};
+
enum scb_stat_ack {
stat_ack_not_ours = 0x00,
stat_ack_sw_gen = 0x04,
@@ -526,6 +532,7 @@ struct nic {
struct rx *rx_to_use;
struct rx *rx_to_clean;
struct rfd blank_rfd;
+ enum ru_state ru_running;
spinlock_t cb_lock ____cacheline_aligned;
spinlock_t cmd_lock;
@@ -576,7 +583,6 @@ struct nic {
u32 rx_tco_frames;
u32 rx_over_length_errors;
- u8 rev_id;
u16 leds;
u16 eeprom_wc;
u16 eeprom[256];
@@ -930,9 +936,8 @@ static void e100_get_defaults(struct nic *nic)
struct param_range rfds = { .min = 16, .max = 256, .count = 256 };
struct param_range cbs = { .min = 64, .max = 256, .count = 128 };
- pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
/* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */
- nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id;
+ nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->pdev->revision;
if(nic->mac == mac_unknown)
nic->mac = mac_82557_D100_A;
@@ -947,7 +952,7 @@ static void e100_get_defaults(struct nic *nic)
((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
/* Template for a freshly allocated RFD */
- nic->blank_rfd.command = cpu_to_le16(cb_el & cb_s);
+ nic->blank_rfd.command = cpu_to_le16(cb_el);
nic->blank_rfd.rbd = 0xFFFFFFFF;
nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
@@ -1017,10 +1022,16 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
config->mwi_enable = 0x1; /* 1=enable, 0=disable */
config->standard_tcb = 0x0; /* 1=standard, 0=extended */
config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */
- if(nic->mac >= mac_82559_D101M)
+ if (nic->mac >= mac_82559_D101M) {
config->tno_intr = 0x1; /* TCO stats enable */
- else
+ /* Enable TCO in extended config */
+ if (nic->mac >= mac_82551_10) {
+ config->byte_count = 0x20; /* extended bytes */
+ config->rx_d102_mode = 0x1; /* GMRC for TCO */
+ }
+ } else {
config->standard_stat_counter = 0x0;
+ }
}
DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -1266,7 +1277,7 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb
if (nic->flags & ich)
goto noloaducode;
- /* Search for ucode match against h/w rev_id */
+ /* Search for ucode match against h/w revision */
for (opts = ucode_opts; opts->mac; opts++) {
int i;
u32 *ucode = opts->ucode;
@@ -1742,11 +1753,19 @@ static int e100_alloc_cbs(struct nic *nic)
return 0;
}
-static inline void e100_start_receiver(struct nic *nic)
+static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
{
- /* Start if RFA is non-NULL */
- if(nic->rx_to_clean->skb)
- e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr);
+ if(!nic->rxs) return;
+ if(RU_SUSPENDED != nic->ru_running) return;
+
+ /* handle init time starts */
+ if(!rx) rx = nic->rxs;
+
+ /* (Re)start RU if suspended or idle and RFA is non-NULL */
+ if(rx->skb) {
+ e100_exec_cmd(nic, ruc_start, rx->dma_addr);
+ nic->ru_running = RU_RUNNING;
+ }
}
#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN)
@@ -1775,7 +1794,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
put_unaligned(cpu_to_le32(rx->dma_addr),
(u32 *)&prev_rfd->link);
wmb();
- prev_rfd->command &= ~cpu_to_le16(cb_el & cb_s);
+ prev_rfd->command &= ~cpu_to_le16(cb_el);
pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr,
sizeof(struct rfd), PCI_DMA_TODEVICE);
}
@@ -1813,6 +1832,10 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
pci_unmap_single(nic->pdev, rx->dma_addr,
RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ /* this allows for a fast restart without re-enabling interrupts */
+ if(le16_to_cpu(rfd->command) & cb_el)
+ nic->ru_running = RU_SUSPENDED;
+
/* Pull off the RFD and put the actual data (minus eth hdr) */
skb_reserve(skb, sizeof(struct rfd));
skb_put(skb, actual_size);
@@ -1843,18 +1866,45 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
unsigned int work_to_do)
{
struct rx *rx;
+ int restart_required = 0;
+ struct rx *rx_to_start = NULL;
+
+ /* are we already rnr? then pay attention!!! this ensures that
+ * the state machine progression never allows a start with a
+ * partially cleaned list, avoiding a race between hardware
+ * and rx_to_clean when in NAPI mode */
+ if(RU_SUSPENDED == nic->ru_running)
+ restart_required = 1;
/* Indicate newly arrived packets */
for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
- if(e100_rx_indicate(nic, rx, work_done, work_to_do))
+ int err = e100_rx_indicate(nic, rx, work_done, work_to_do);
+ if(-EAGAIN == err) {
+ /* hit quota so have more work to do, restart once
+ * cleanup is complete */
+ restart_required = 0;
+ break;
+ } else if(-ENODATA == err)
break; /* No more to clean */
}
+ /* save our starting point as the place we'll restart the receiver */
+ if(restart_required)
+ rx_to_start = nic->rx_to_clean;
+
/* Alloc new skbs to refill list */
for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
if(unlikely(e100_rx_alloc_skb(nic, rx)))
break; /* Better luck next time (see watchdog) */
}
+
+ if(restart_required) {
+ // ack the rnr?
+ writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
+ e100_start_receiver(nic, rx_to_start);
+ if(work_done)
+ (*work_done)++;
+ }
}
static void e100_rx_clean_list(struct nic *nic)
@@ -1862,6 +1912,8 @@ static void e100_rx_clean_list(struct nic *nic)
struct rx *rx;
unsigned int i, count = nic->params.rfds.count;
+ nic->ru_running = RU_UNINITIALIZED;
+
if(nic->rxs) {
for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
if(rx->skb) {
@@ -1883,6 +1935,7 @@ static int e100_rx_alloc_list(struct nic *nic)
unsigned int i, count = nic->params.rfds.count;
nic->rx_to_use = nic->rx_to_clean = NULL;
+ nic->ru_running = RU_UNINITIALIZED;
if(!(nic->rxs = kcalloc(count, sizeof(struct rx), GFP_ATOMIC)))
return -ENOMEM;
@@ -1897,6 +1950,7 @@ static int e100_rx_alloc_list(struct nic *nic)
}
nic->rx_to_use = nic->rx_to_clean = nic->rxs;
+ nic->ru_running = RU_SUSPENDED;
return 0;
}
@@ -1916,6 +1970,10 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
/* Ack interrupt(s) */
iowrite8(stat_ack, &nic->csr->scb.stat_ack);
+ /* We hit Receive No Resource (RNR); restart RU after cleaning */
+ if(stat_ack & stat_ack_rnr)
+ nic->ru_running = RU_SUSPENDED;
+
if(likely(netif_rx_schedule_prep(netdev))) {
e100_disable_irq(nic);
__netif_rx_schedule(netdev);
@@ -2007,7 +2065,7 @@ static int e100_up(struct nic *nic)
if((err = e100_hw_init(nic)))
goto err_clean_cbs;
e100_set_multicast_list(nic->netdev);
- e100_start_receiver(nic);
+ e100_start_receiver(nic, NULL);
mod_timer(&nic->watchdog, jiffies);
if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
nic->netdev->name, nic->netdev)))
@@ -2088,7 +2146,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
BMCR_LOOPBACK);
- e100_start_receiver(nic);
+ e100_start_receiver(nic, NULL);
if(!(skb = netdev_alloc_skb(nic->netdev, ETH_DATA_LEN))) {
err = -ENOMEM;
@@ -2178,7 +2236,7 @@ static void e100_get_regs(struct net_device *netdev,
u32 *buff = p;
int i;
- regs->version = (1 << 24) | nic->rev_id;
+ regs->version = (1 << 24) | nic->pdev->revision;
buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
ioread8(&nic->csr->scb.cmd_lo) << 16 |
ioread16(&nic->csr->scb.status);
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 9ec35b7a820..f48b659e0c2 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1142,13 +1142,16 @@ e1000_probe(struct pci_dev *pdev,
!e1000_check_mng_mode(&adapter->hw))
e1000_get_hw_control(adapter);
- strcpy(netdev->name, "eth%d");
- if ((err = register_netdev(netdev)))
- goto err_register;
-
/* tell the stack to leave us alone until e1000_open() is called */
netif_carrier_off(netdev);
netif_stop_queue(netdev);
+#ifdef CONFIG_E1000_NAPI
+ netif_poll_disable(netdev);
+#endif
+
+ strcpy(netdev->name, "eth%d");
+ if ((err = register_netdev(netdev)))
+ goto err_register;
DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
@@ -1263,8 +1266,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
hw->device_id = pdev->device;
hw->subsystem_vendor_id = pdev->subsystem_vendor;
hw->subsystem_id = pdev->subsystem_device;
-
- pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+ hw->revision_id = pdev->revision;
pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 9800341956a..9afa47edfc5 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1801,7 +1801,7 @@ speedo_rx(struct net_device *dev)
#if 1 || USE_IP_CSUM
/* Packet is in one chunk -- we can copy + cksum. */
- eth_copy_and_sum(skb, sp->rx_skbuff[entry]->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len);
skb_put(skb, pkt_len);
#else
skb_copy_from_linear_data(sp->rx_skbuff[entry],
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index e85a933a476..f03f070451d 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -39,7 +39,13 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0061"
+#define DRV_VERSION "EHEA_0067"
+
+/* EHEA capability flags */
+#define DLPAR_PORT_ADD_REM 1
+#define DLPAR_MEM_ADD 2
+#define DLPAR_MEM_REM 4
+#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM)
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
@@ -136,10 +142,10 @@ void ehea_dump(void *adr, int len, char *msg);
(0xffffffffffffffffULL >> ((64 - (mask)) & 0xffff))
#define EHEA_BMASK_SET(mask, value) \
- ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
+ ((EHEA_BMASK_MASK(mask) & ((u64)(value))) << EHEA_BMASK_SHIFTPOS(mask))
#define EHEA_BMASK_GET(mask, value) \
- (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
+ (EHEA_BMASK_MASK(mask) & (((u64)(value)) >> EHEA_BMASK_SHIFTPOS(mask)))
/*
* Generic ehea page
@@ -190,7 +196,7 @@ struct ehea_av;
* Queue attributes passed to ehea_create_qp()
*/
struct ehea_qp_init_attr {
- /* input parameter */
+ /* input parameter */
u32 qp_token; /* queue token */
u8 low_lat_rq1;
u8 signalingtype; /* cqe generation flag */
@@ -212,7 +218,7 @@ struct ehea_qp_init_attr {
u64 recv_cq_handle;
u64 aff_eq_handle;
- /* output parameter */
+ /* output parameter */
u32 qp_nr;
u16 act_nr_send_wqes;
u16 act_nr_rwqes_rq1;
@@ -279,12 +285,12 @@ struct ehea_qp {
* Completion Queue attributes
*/
struct ehea_cq_attr {
- /* input parameter */
+ /* input parameter */
u32 max_nr_of_cqes;
u32 cq_token;
u64 eq_handle;
- /* output parameter */
+ /* output parameter */
u32 act_nr_of_cqes;
u32 nr_pages;
};
diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ehea/ehea_hw.h
index 1246757f2c2..1af7ca499ec 100644
--- a/drivers/net/ehea/ehea_hw.h
+++ b/drivers/net/ehea/ehea_hw.h
@@ -211,34 +211,34 @@ static inline void epa_store_acc(struct h_epa epa, u32 offset, u64 value)
}
#define epa_store_eq(epa, offset, value)\
- epa_store(epa, EQTEMM_OFFSET(offset), value)
+ epa_store(epa, EQTEMM_OFFSET(offset), value)
#define epa_load_eq(epa, offset)\
- epa_load(epa, EQTEMM_OFFSET(offset))
+ epa_load(epa, EQTEMM_OFFSET(offset))
#define epa_store_cq(epa, offset, value)\
- epa_store(epa, CQTEMM_OFFSET(offset), value)
+ epa_store(epa, CQTEMM_OFFSET(offset), value)
#define epa_load_cq(epa, offset)\
- epa_load(epa, CQTEMM_OFFSET(offset))
+ epa_load(epa, CQTEMM_OFFSET(offset))
#define epa_store_qp(epa, offset, value)\
- epa_store(epa, QPTEMM_OFFSET(offset), value)
+ epa_store(epa, QPTEMM_OFFSET(offset), value)
#define epa_load_qp(epa, offset)\
- epa_load(epa, QPTEMM_OFFSET(offset))
+ epa_load(epa, QPTEMM_OFFSET(offset))
#define epa_store_qped(epa, offset, value)\
- epa_store(epa, QPEDMM_OFFSET(offset), value)
+ epa_store(epa, QPEDMM_OFFSET(offset), value)
#define epa_load_qped(epa, offset)\
- epa_load(epa, QPEDMM_OFFSET(offset))
+ epa_load(epa, QPEDMM_OFFSET(offset))
#define epa_store_mrmw(epa, offset, value)\
- epa_store(epa, MRMWMM_OFFSET(offset), value)
+ epa_store(epa, MRMWMM_OFFSET(offset), value)
#define epa_load_mrmw(epa, offset)\
- epa_load(epa, MRMWMM_OFFSET(offset))
+ epa_load(epa, MRMWMM_OFFSET(offset))
#define epa_store_base(epa, offset, value)\
- epa_store(epa, HCAGR_OFFSET(offset), value)
+ epa_store(epa, HCAGR_OFFSET(offset), value)
#define epa_load_base(epa, offset)\
- epa_load(epa, HCAGR_OFFSET(offset))
+ epa_load(epa, HCAGR_OFFSET(offset))
static inline void ehea_update_sqa(struct ehea_qp *qp, u16 nr_wqes)
{
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 152bb2016a2..383144db4d1 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -81,7 +81,7 @@ MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
static int port_name_cnt = 0;
static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
- const struct of_device_id *id);
+ const struct of_device_id *id);
static int __devexit ehea_remove(struct ibmebus_dev *dev);
@@ -236,7 +236,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
rwqe = ehea_get_next_rwqe(qp, rq_nr);
rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
- | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
+ | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
rwqe->sg_list[0].vaddr = (u64)skb->data;
rwqe->sg_list[0].len = packet_size;
@@ -427,7 +427,7 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
break;
}
skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
- cqe->num_bytes_transfered - 4);
+ cqe->num_bytes_transfered - 4);
ehea_fill_skb(port->netdev, skb, cqe);
} else if (rq == 2) { /* RQ2 */
skb = get_skb_by_index(skb_arr_rq2,
@@ -451,7 +451,8 @@ static struct ehea_cqe *ehea_proc_rwqes(struct net_device *dev,
processed_rq3++;
}
- if (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
+ if ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
+ && port->vgrp)
vlan_hwaccel_receive_skb(skb, port->vgrp,
cqe->vlan_tag);
else
@@ -617,7 +618,7 @@ static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
for (i = 0; i < EHEA_MAX_PORTS; i++)
if (adapter->port[i])
- if (adapter->port[i]->logical_port_id == logical_port)
+ if (adapter->port[i]->logical_port_id == logical_port)
return adapter->port[i];
return NULL;
}
@@ -1694,6 +1695,7 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
{
if (skb->protocol == htons(ETH_P_IP)) {
const struct iphdr *iph = ip_hdr(skb);
+
/* IPv4 */
swqe->tx_control |= EHEA_SWQE_CRC
| EHEA_SWQE_IP_CHECKSUM
@@ -1704,13 +1706,12 @@ static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
write_ip_start_end(swqe, skb);
if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
+ if ((iph->frag_off & IP_MF)
+ || (iph->frag_off & IP_OFFSET))
/* IP fragment, so don't change cs */
swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
else
write_udp_offset_end(swqe, skb);
-
} else if (iph->protocol == IPPROTO_TCP) {
write_tcp_offset_end(swqe, skb);
}
@@ -1738,6 +1739,7 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
if (skb->protocol == htons(ETH_P_IP)) {
const struct iphdr *iph = ip_hdr(skb);
+
/* IPv4 */
write_ip_start_end(swqe, skb);
@@ -1750,8 +1752,8 @@ static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
write_tcp_offset_end(swqe, skb);
} else if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
+ if ((iph->frag_off & IP_MF)
+ || (iph->frag_off & IP_OFFSET))
/* IP fragment, so don't change cs */
swqe->tx_control |= EHEA_SWQE_CRC
| EHEA_SWQE_IMM_DATA_PRESENT;
@@ -1910,10 +1912,7 @@ static void ehea_vlan_rx_register(struct net_device *dev,
goto out;
}
- if (grp)
- memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
- else
- memset(cb1->vlan_filter, 0xFF, sizeof(cb1->vlan_filter));
+ memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
H_PORT_CB1, H_PORT_CB1_ALL, cb1);
@@ -1947,7 +1946,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
}
index = (vid / 64);
- cb1->vlan_filter[index] |= ((u64)(1 << (vid & 0x3F)));
+ cb1->vlan_filter[index] |= ((u64)(0x8000000000000000 >> (vid & 0x3F)));
hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
H_PORT_CB1, H_PORT_CB1_ALL, cb1);
@@ -1982,7 +1981,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
}
index = (vid / 64);
- cb1->vlan_filter[index] &= ~((u64)(1 << (vid & 0x3F)));
+ cb1->vlan_filter[index] &= ~((u64)(0x8000000000000000 >> (vid & 0x3F)));
hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
H_PORT_CB1, H_PORT_CB1_ALL, cb1);
@@ -2409,7 +2408,7 @@ static void __devinit logical_port_release(struct device *dev)
}
static int ehea_driver_sysfs_add(struct device *dev,
- struct device_driver *driver)
+ struct device_driver *driver)
{
int ret;
@@ -2426,7 +2425,7 @@ static int ehea_driver_sysfs_add(struct device *dev,
}
static void ehea_driver_sysfs_remove(struct device *dev,
- struct device_driver *driver)
+ struct device_driver *driver)
{
struct device_driver *drv = driver;
@@ -2455,7 +2454,7 @@ static struct device *ehea_register_port(struct ehea_port *port,
}
ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
- if (ret) {
+ if (ret) {
ehea_error("failed to register attributes, ret=%d", ret);
goto out_unreg_of_dev;
}
@@ -2603,6 +2602,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
{
struct device_node *lhea_dn;
struct device_node *eth_dn = NULL;
+
const u32 *dn_log_port_id;
int i = 0;
@@ -2610,7 +2610,7 @@ static int ehea_setup_ports(struct ehea_adapter *adapter)
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
- NULL);
+ NULL);
if (!dn_log_port_id) {
ehea_error("bad device node: eth_dn name=%s",
eth_dn->full_name);
@@ -2650,7 +2650,7 @@ static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
- NULL);
+ NULL);
if (dn_log_port_id)
if (*dn_log_port_id == logical_port_id)
return eth_dn;
@@ -2791,7 +2791,7 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
adapter->ebus_dev = dev;
adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
- NULL);
+ NULL);
if (adapter_handle)
adapter->handle = *adapter_handle;
@@ -2923,6 +2923,15 @@ static int check_module_parm(void)
return ret;
}
+static ssize_t ehea_show_capabilities(struct device_driver *drv,
+ char *buf)
+{
+ return sprintf(buf, "%d", EHEA_CAPABILITIES);
+}
+
+static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
+ ehea_show_capabilities, NULL);
+
int __init ehea_module_init(void)
{
int ret;
@@ -2934,8 +2943,19 @@ int __init ehea_module_init(void)
if (ret)
goto out;
ret = ibmebus_register_driver(&ehea_driver);
- if (ret)
+ if (ret) {
ehea_error("failed registering eHEA device driver on ebus");
+ goto out;
+ }
+
+ ret = driver_create_file(&ehea_driver.driver,
+ &driver_attr_capabilities);
+ if (ret) {
+ ehea_error("failed to register capabilities attribute, ret=%d",
+ ret);
+ ibmebus_unregister_driver(&ehea_driver);
+ goto out;
+ }
out:
return ret;
@@ -2943,6 +2963,7 @@ out:
static void __exit ehea_module_exit(void)
{
+ driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
ibmebus_unregister_driver(&ehea_driver);
}
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index f24a8862977..29eaa46948b 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -211,7 +211,7 @@ u64 ehea_destroy_cq_res(struct ehea_cq *cq, u64 force)
u64 hret;
u64 adapter_handle = cq->adapter->handle;
- /* deregister all previous registered pages */
+ /* deregister all previous registered pages */
hret = ehea_h_free_resource(adapter_handle, cq->fw_handle, force);
if (hret != H_SUCCESS)
return hret;
@@ -362,7 +362,7 @@ int ehea_destroy_eq(struct ehea_eq *eq)
if (hret != H_SUCCESS) {
ehea_error("destroy EQ failed");
return -EIO;
- }
+ }
return 0;
}
@@ -507,44 +507,44 @@ out_freemem:
u64 ehea_destroy_qp_res(struct ehea_qp *qp, u64 force)
{
- u64 hret;
- struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
+ u64 hret;
+ struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
- ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
- hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
- if (hret != H_SUCCESS)
- return hret;
+ ehea_h_disable_and_get_hea(qp->adapter->handle, qp->fw_handle);
+ hret = ehea_h_free_resource(qp->adapter->handle, qp->fw_handle, force);
+ if (hret != H_SUCCESS)
+ return hret;
- hw_queue_dtor(&qp->hw_squeue);
- hw_queue_dtor(&qp->hw_rqueue1);
+ hw_queue_dtor(&qp->hw_squeue);
+ hw_queue_dtor(&qp->hw_rqueue1);
- if (qp_attr->rq_count > 1)
- hw_queue_dtor(&qp->hw_rqueue2);
- if (qp_attr->rq_count > 2)
- hw_queue_dtor(&qp->hw_rqueue3);
- kfree(qp);
+ if (qp_attr->rq_count > 1)
+ hw_queue_dtor(&qp->hw_rqueue2);
+ if (qp_attr->rq_count > 2)
+ hw_queue_dtor(&qp->hw_rqueue3);
+ kfree(qp);
- return hret;
+ return hret;
}
int ehea_destroy_qp(struct ehea_qp *qp)
{
- u64 hret;
- if (!qp)
- return 0;
+ u64 hret;
+ if (!qp)
+ return 0;
- if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
- ehea_error_data(qp->adapter, qp->fw_handle);
- hret = ehea_destroy_qp_res(qp, FORCE_FREE);
- }
+ if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
+ ehea_error_data(qp->adapter, qp->fw_handle);
+ hret = ehea_destroy_qp_res(qp, FORCE_FREE);
+ }
- if (hret != H_SUCCESS) {
- ehea_error("destroy QP failed");
- return -EIO;
- }
+ if (hret != H_SUCCESS) {
+ ehea_error("destroy QP failed");
+ return -EIO;
+ }
- return 0;
+ return 0;
}
int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 5e517946f46..119778401e4 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1201,7 +1201,7 @@ static int epic_rx(struct net_device *dev, int budget)
ep->rx_ring[entry].bufaddr,
ep->rx_buf_sz,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, ep->rx_skbuff[entry]->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(ep->pci_dev,
ep->rx_ring[entry].bufaddr,
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index abe9b089c61..ff9f177d715 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -1727,8 +1727,8 @@ static int netdev_rx(struct net_device *dev)
/* Call copy + cksum if available. */
#if ! defined(__alpha__)
- eth_copy_and_sum(skb,
- np->cur_rx->skbuff->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb,
+ np->cur_rx->skbuff->data, pkt_len);
skb_put(skb, pkt_len);
#else
memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 255b09124e1..03023dd1782 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -648,7 +648,7 @@ while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
fep->stats.rx_dropped++;
} else {
skb_put(skb,pkt_len-4); /* Make room */
- eth_copy_and_sum(skb, data, pkt_len-4, 0);
+ skb_copy_to_linear_data(skb, data, pkt_len-4);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
}
diff --git a/drivers/net/fec_8xx/Kconfig b/drivers/net/fec_8xx/Kconfig
index a84c232395e..afb34ded26e 100644
--- a/drivers/net/fec_8xx/Kconfig
+++ b/drivers/net/fec_8xx/Kconfig
@@ -1,6 +1,6 @@
config FEC_8XX
tristate "Motorola 8xx FEC driver"
- depends on NET_ETHERNET && 8xx
+ depends on 8XX
select MII
config FEC_8XX_GENERIC_PHY
diff --git a/drivers/net/fec_8xx/fec_main.c b/drivers/net/fec_8xx/fec_main.c
index 88efe9731ba..e5502af5b8e 100644
--- a/drivers/net/fec_8xx/fec_main.c
+++ b/drivers/net/fec_8xx/fec_main.c
@@ -550,7 +550,7 @@ static int fec_enet_rx_common(struct net_device *dev, int *budget)
skbn = dev_alloc_skb(pkt_len + 2);
if (skbn != NULL) {
skb_reserve(skbn, 2); /* align IP header */
- skb_copy_from_linear_data(skb
+ skb_copy_from_linear_data(skb,
skbn->data,
pkt_len);
/* swap */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 4154fd00074..67046e8c21e 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -4605,12 +4605,7 @@ static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
spin_unlock_irq(&np->lock);
-};
-
-static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- /* nothing to do */
-};
+}
/* The mgmt unit and driver use a semaphore to access the phy during init */
static int nv_mgmt_acquire_sema(struct net_device *dev)
@@ -4830,8 +4825,10 @@ static int nv_close(struct net_device *dev)
drain_ring(dev);
- if (np->wolenabled)
+ if (np->wolenabled) {
+ writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
nv_start_rx(dev);
+ }
/* FIXME: power down nic */
@@ -4956,7 +4953,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
dev->vlan_rx_register = nv_vlan_rx_register;
- dev->vlan_rx_kill_vid = nv_vlan_rx_kill_vid;
}
np->msi_flags = 0;
@@ -5088,15 +5084,13 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->wolenabled = 0;
if (id->driver_data & DEV_HAS_POWER_CNTRL) {
- u8 revision_id;
- pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id);
/* take phy and nic out of low power mode */
powerstate = readl(base + NvRegPowerState2);
powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK;
if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 ||
id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) &&
- revision_id >= 0xA3)
+ pci_dev->revision >= 0xA3)
powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3;
writel(powerstate, base + NvRegPowerState2);
}
diff --git a/drivers/net/fs_enet/Kconfig b/drivers/net/fs_enet/Kconfig
index 6aaee67dd4b..e27ee210b60 100644
--- a/drivers/net/fs_enet/Kconfig
+++ b/drivers/net/fs_enet/Kconfig
@@ -1,6 +1,6 @@
config FS_ENET
tristate "Freescale Ethernet Driver"
- depends on NET_ETHERNET && (CPM1 || CPM2)
+ depends on CPM1 || CPM2
select MII
config FS_ENET_HAS_SCC
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index f5b3cba23fc..d7a1a58de76 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -130,6 +130,9 @@ static int gfar_remove(struct platform_device *pdev);
static void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
+static void gfar_configure_serdes(struct net_device *dev);
+extern int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id, int regnum, u16 value);
+extern int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum);
#ifdef CONFIG_GFAR_NAPI
static int gfar_poll(struct net_device *dev, int *budget);
#endif
@@ -140,7 +143,6 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
-static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
void gfar_halt(struct net_device *dev);
void gfar_start(struct net_device *dev);
static void gfar_clear_exact_match(struct net_device *dev);
@@ -284,7 +286,6 @@ static int gfar_probe(struct platform_device *pdev)
if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
dev->vlan_rx_register = gfar_vlan_rx_register;
- dev->vlan_rx_kill_vid = gfar_vlan_rx_kill_vid;
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
@@ -453,6 +454,9 @@ static int init_phy(struct net_device *dev)
phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
+ if (interface == PHY_INTERFACE_MODE_SGMII)
+ gfar_configure_serdes(dev);
+
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
return PTR_ERR(phydev);
@@ -467,6 +471,27 @@ static int init_phy(struct net_device *dev)
return 0;
}
+static void gfar_configure_serdes(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_mii __iomem *regs =
+ (void __iomem *)&priv->regs->gfar_mii_regs;
+
+ /* Initialise TBI i/f to communicate with serdes (lynx phy) */
+
+ /* Single clk mode, mii mode off(for aerdes communication) */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_TBICON, TBICON_CLK_SELECT);
+
+ /* Supported pause and full-duplex, no half-duplex */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_ADVERTISE,
+ ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
+ ADVERTISE_1000XPSE_ASYM);
+
+ /* ANEG enable, restart ANEG, full duplex mode, speed[1] set */
+ gfar_local_mdio_write(regs, TBIPA_VALUE, MII_BMCR, BMCR_ANENABLE |
+ BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
+}
+
static void init_registers(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
@@ -946,7 +971,7 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb)
flags |= TXFCB_UDP;
fcb->phcs = udp_hdr(skb)->check;
} else
- fcb->phcs = udp_hdr(skb)->check;
+ fcb->phcs = tcp_hdr(skb)->check;
/* l3os is the distance between the start of the
* frame (skb->data) and the start of the IP hdr.
@@ -1133,20 +1158,6 @@ static void gfar_vlan_rx_register(struct net_device *dev,
spin_unlock_irqrestore(&priv->rxlock, flags);
}
-
-static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
-{
- struct gfar_private *priv = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&priv->rxlock, flags);
-
- vlan_group_set_device(priv->vlgrp, vid, NULL);
-
- spin_unlock_irqrestore(&priv->rxlock, flags);
-}
-
-
static int gfar_change_mtu(struct net_device *dev, int new_mtu)
{
int tempsize, tempval;
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 39e9e321fcb..d8e779c102f 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -136,6 +136,12 @@ extern const char gfar_driver_version[];
#define MIIMCFG_RESET 0x80000000
#define MIIMIND_BUSY 0x00000001
+/* TBI register addresses */
+#define MII_TBICON 0x11
+
+/* TBICON register bit fields */
+#define TBICON_CLK_SELECT 0x0020
+
/* MAC register bits */
#define MACCFG1_SOFT_RESET 0x80000000
#define MACCFG1_RESET_RX_MC 0x00080000
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index bcc6b82f4a3..5dd34a1a7b8 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -43,13 +43,18 @@
#include "gianfar.h"
#include "gianfar_mii.h"
-/* Write value to the PHY at mii_id at register regnum,
- * on the bus, waiting until the write is done before returning.
- * All PHY configuration is done through the TSEC1 MIIM regs */
-int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+/*
+ * Write value to the PHY at mii_id at register regnum,
+ * on the bus attached to the local interface, which may be different from the
+ * generic mdio bus (tied to a single interface), waiting until the write is
+ * done before returning. This is helpful in programming interfaces like
+ * the TBI which control interfaces like onchip SERDES and are always tied to
+ * the local mdio pins, which may not be the same as system mdio bus, used for
+ * controlling the external PHYs, for example.
+ */
+int gfar_local_mdio_write(struct gfar_mii *regs, int mii_id,
+ int regnum, u16 value)
{
- struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
-
/* Set the PHY address and the register address we want to write */
gfar_write(&regs->miimadd, (mii_id << 8) | regnum);
@@ -63,12 +68,19 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
return 0;
}
-/* Read the bus for PHY at addr mii_id, register regnum, and
- * return the value. Clears miimcom first. All PHY
- * configuration has to be done through the TSEC1 MIIM regs */
-int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+/*
+ * Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY operation
+ * done on the bus attached to the local interface,
+ * which may be different from the generic mdio bus
+ * This is helpful in programming interfaces like
+ * the TBI which, inturn, control interfaces like onchip SERDES
+ * and are always tied to the local mdio pins, which may not be the
+ * same as system mdio bus, used for controlling the external PHYs, for eg.
+ */
+int gfar_local_mdio_read(struct gfar_mii *regs, int mii_id, int regnum)
+
{
- struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
u16 value;
/* Set the PHY address and the register address we want to read */
@@ -88,6 +100,27 @@ int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
return value;
}
+/* Write value to the PHY at mii_id at register regnum,
+ * on the bus, waiting until the write is done before returning.
+ * All PHY configuration is done through the TSEC1 MIIM regs */
+int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value)
+{
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+ /* Write to the local MII regs */
+ return(gfar_local_mdio_write(regs, mii_id, regnum, value));
+}
+
+/* Read the bus for PHY at addr mii_id, register regnum, and
+ * return the value. Clears miimcom first. All PHY
+ * configuration has to be done through the TSEC1 MIIM regs */
+int gfar_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct gfar_mii __iomem *regs = (void __iomem *)bus->priv;
+
+ /* Read the local MII regs */
+ return(gfar_local_mdio_read(regs, mii_id, regnum));
+}
/* Reset the MIIM registers, and wait for the bus to free */
int gfar_mdio_reset(struct mii_bus *bus)
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 2521b111b3a..15254dc7876 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -1575,8 +1575,8 @@ static int hamachi_rx(struct net_device *dev)
PCI_DMA_FROMDEVICE);
/* Call copy + cksum if available. */
#if 1 || USE_IP_COPYSUM
- eth_copy_and_sum(skb,
- hmp->rx_skbuff[entry]->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb,
+ hmp->rx_skbuff[entry]->data, pkt_len);
skb_put(skb, pkt_len);
#else
memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 8118a6750b6..8caa591c564 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -3005,7 +3005,7 @@ static int __init hp100_isa_init(void)
return cards > 0 ? 0 : -ENODEV;
}
-static void __exit hp100_isa_cleanup(void)
+static void hp100_isa_cleanup(void)
{
int i;
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 3bec0f733f0..d96eb722954 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -915,17 +915,36 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
{
struct ibmveth_adapter *adapter = dev->priv;
int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
- int i;
+ int reinit = 0;
+ int i, rc;
if (new_mtu < IBMVETH_MAX_MTU)
return -EINVAL;
+ for (i = 0; i < IbmVethNumBufferPools; i++)
+ if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size)
+ break;
+
+ if (i == IbmVethNumBufferPools)
+ return -EINVAL;
+
/* Look for an active buffer pool that can hold the new MTU */
for(i = 0; i<IbmVethNumBufferPools; i++) {
- if (!adapter->rx_buff_pool[i].active)
- continue;
+ if (!adapter->rx_buff_pool[i].active) {
+ adapter->rx_buff_pool[i].active = 1;
+ reinit = 1;
+ }
+
if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
- dev->mtu = new_mtu;
+ if (reinit && netif_running(adapter->netdev)) {
+ adapter->pool_config = 1;
+ ibmveth_close(adapter->netdev);
+ adapter->pool_config = 0;
+ dev->mtu = new_mtu;
+ if ((rc = ibmveth_open(adapter->netdev)))
+ return rc;
+ } else
+ dev->mtu = new_mtu;
return 0;
}
}
@@ -1243,16 +1262,19 @@ const char * buf, size_t count)
if (attr == &veth_active_attr) {
if (value && !pool->active) {
- if(ibmveth_alloc_buffer_pool(pool)) {
- ibmveth_error_printk("unable to alloc pool\n");
- return -ENOMEM;
- }
- pool->active = 1;
- adapter->pool_config = 1;
- ibmveth_close(netdev);
- adapter->pool_config = 0;
- if ((rc = ibmveth_open(netdev)))
- return rc;
+ if (netif_running(netdev)) {
+ if(ibmveth_alloc_buffer_pool(pool)) {
+ ibmveth_error_printk("unable to alloc pool\n");
+ return -ENOMEM;
+ }
+ pool->active = 1;
+ adapter->pool_config = 1;
+ ibmveth_close(netdev);
+ adapter->pool_config = 0;
+ if ((rc = ibmveth_open(netdev)))
+ return rc;
+ } else
+ pool->active = 1;
} else if (!value && pool->active) {
int mtu = netdev->mtu + IBMVETH_BUFF_OH;
int i;
@@ -1281,23 +1303,29 @@ const char * buf, size_t count)
if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
return -EINVAL;
else {
- adapter->pool_config = 1;
- ibmveth_close(netdev);
- adapter->pool_config = 0;
- pool->size = value;
- if ((rc = ibmveth_open(netdev)))
- return rc;
+ if (netif_running(netdev)) {
+ adapter->pool_config = 1;
+ ibmveth_close(netdev);
+ adapter->pool_config = 0;
+ pool->size = value;
+ if ((rc = ibmveth_open(netdev)))
+ return rc;
+ } else
+ pool->size = value;
}
} else if (attr == &veth_size_attr) {
if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
return -EINVAL;
else {
- adapter->pool_config = 1;
- ibmveth_close(netdev);
- adapter->pool_config = 0;
- pool->buff_size = value;
- if ((rc = ibmveth_open(netdev)))
- return rc;
+ if (netif_running(netdev)) {
+ adapter->pool_config = 1;
+ ibmveth_close(netdev);
+ adapter->pool_config = 0;
+ pool->buff_size = value;
+ if ((rc = ibmveth_open(netdev)))
+ return rc;
+ } else
+ pool->buff_size = value;
}
}
@@ -1309,7 +1337,7 @@ const char * buf, size_t count)
#define ATTR(_name, _mode) \
struct attribute veth_##_name##_attr = { \
- .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
+ .name = __stringify(_name), .mode = _mode, \
};
static ATTR(active, 0644);
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 07b4c0d7a75..f5c3598e59a 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -136,13 +136,14 @@ resched:
}
-static void __init ifb_setup(struct net_device *dev)
+static void ifb_setup(struct net_device *dev)
{
/* Initialize the device structure. */
dev->get_stats = ifb_get_stats;
dev->hard_start_xmit = ifb_xmit;
dev->open = &ifb_open;
dev->stop = &ifb_close;
+ dev->destructor = free_netdev;
/* Fill in device structure with ethernet-generic values. */
ether_setup(dev);
@@ -197,12 +198,6 @@ static struct net_device_stats *ifb_get_stats(struct net_device *dev)
return stats;
}
-static struct net_device **ifbs;
-
-/* Number of ifb devices to be set up by this module. */
-module_param(numifbs, int, 0);
-MODULE_PARM_DESC(numifbs, "Number of ifb devices");
-
static int ifb_close(struct net_device *dev)
{
struct ifb_private *dp = netdev_priv(dev);
@@ -226,6 +221,28 @@ static int ifb_open(struct net_device *dev)
return 0;
}
+static int ifb_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+ if (tb[IFLA_ADDRESS]) {
+ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+ return -EINVAL;
+ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+ return -EADDRNOTAVAIL;
+ }
+ return 0;
+}
+
+static struct rtnl_link_ops ifb_link_ops __read_mostly = {
+ .kind = "ifb",
+ .priv_size = sizeof(struct ifb_private),
+ .setup = ifb_setup,
+ .validate = ifb_validate,
+};
+
+/* Number of ifb devices to be set up by this module. */
+module_param(numifbs, int, 0);
+MODULE_PARM_DESC(numifbs, "Number of ifb devices");
+
static int __init ifb_init_one(int index)
{
struct net_device *dev_ifb;
@@ -237,49 +254,44 @@ static int __init ifb_init_one(int index)
if (!dev_ifb)
return -ENOMEM;
- if ((err = register_netdev(dev_ifb))) {
- free_netdev(dev_ifb);
- dev_ifb = NULL;
- } else {
- ifbs[index] = dev_ifb;
- }
+ err = dev_alloc_name(dev_ifb, dev_ifb->name);
+ if (err < 0)
+ goto err;
- return err;
-}
+ dev_ifb->rtnl_link_ops = &ifb_link_ops;
+ err = register_netdevice(dev_ifb);
+ if (err < 0)
+ goto err;
+ return 0;
-static void ifb_free_one(int index)
-{
- unregister_netdev(ifbs[index]);
- free_netdev(ifbs[index]);
+err:
+ free_netdev(dev_ifb);
+ return err;
}
static int __init ifb_init_module(void)
{
- int i, err = 0;
- ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL);
- if (!ifbs)
- return -ENOMEM;
+ int i, err;
+
+ rtnl_lock();
+ err = __rtnl_link_register(&ifb_link_ops);
+
for (i = 0; i < numifbs && !err; i++)
err = ifb_init_one(i);
- if (err) {
- i--;
- while (--i >= 0)
- ifb_free_one(i);
- }
+ if (err)
+ __rtnl_link_unregister(&ifb_link_ops);
+ rtnl_unlock();
return err;
}
static void __exit ifb_cleanup_module(void)
{
- int i;
-
- for (i = 0; i < numifbs; i++)
- ifb_free_one(i);
- kfree(ifbs);
+ rtnl_link_unregister(&ifb_link_ops);
}
module_init(ifb_init_module);
module_exit(ifb_cleanup_module);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jamal Hadi Salim");
+MODULE_ALIAS_RTNL_LINK("ifb");
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index f749e07c642..3ca1e8ece54 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -352,13 +352,12 @@ static u64 nic_find(struct ioc3 *ioc3, int *last)
static int nic_init(struct ioc3 *ioc3)
{
- const char *type;
+ const char *unknown = "unknown";
+ const char *type = unknown;
u8 crc;
u8 serial[6];
int save = 0, i;
- type = "unknown";
-
while (1) {
u64 reg;
reg = nic_find(ioc3, &save);
@@ -392,7 +391,7 @@ static int nic_init(struct ioc3 *ioc3)
}
printk("Found %s NIC", type);
- if (type != "unknown") {
+ if (type != unknown) {
printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x,"
" CRC %02x", serial[0], serial[1], serial[2],
serial[3], serial[4], serial[5], crc);
@@ -1103,20 +1102,28 @@ static int ioc3_close(struct net_device *dev)
* MiniDINs; all other subdevices are left swinging in the wind, leave
* them disabled.
*/
-static inline int ioc3_is_menet(struct pci_dev *pdev)
+
+static int ioc3_adjacent_is_ioc3(struct pci_dev *pdev, int slot)
+{
+ struct pci_dev *dev = pci_get_slot(pdev->bus, PCI_DEVFN(slot, 0));
+ int ret = 0;
+
+ if (dev) {
+ if (dev->vendor == PCI_VENDOR_ID_SGI &&
+ dev->device == PCI_DEVICE_ID_SGI_IOC3)
+ ret = 1;
+ pci_dev_put(dev);
+ }
+
+ return ret;
+}
+
+static int ioc3_is_menet(struct pci_dev *pdev)
{
- struct pci_dev *dev;
-
- return pdev->bus->parent == NULL
- && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(0, 0)))
- && dev->vendor == PCI_VENDOR_ID_SGI
- && dev->device == PCI_DEVICE_ID_SGI_IOC3
- && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(1, 0)))
- && dev->vendor == PCI_VENDOR_ID_SGI
- && dev->device == PCI_DEVICE_ID_SGI_IOC3
- && (dev = pci_find_slot(pdev->bus->number, PCI_DEVFN(2, 0)))
- && dev->vendor == PCI_VENDOR_ID_SGI
- && dev->device == PCI_DEVICE_ID_SGI_IOC3;
+ return pdev->bus->parent == NULL &&
+ ioc3_adjacent_is_ioc3(pdev, 0) &&
+ ioc3_adjacent_is_ioc3(pdev, 1) &&
+ ioc3_adjacent_is_ioc3(pdev, 2);
}
#ifdef CONFIG_SERIAL_8250
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 3098960dc2a..3078c419cb0 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -509,7 +509,7 @@ static void irport_timeout(struct net_device *dev)
IRDA_DEBUG(0, "%s(), iir=%02x, lsr=%02x, iobase=%#x\n",
__FUNCTION__, iir, lsr, iobase);
- IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%d\n",
+ IRDA_DEBUG(0, "%s(), transmitting=%d, remain=%d, done=%td\n",
__FUNCTION__, self->transmitting, self->tx_buff.len,
self->tx_buff.data - self->tx_buff.head);
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index 217429122e7..bdd5c979bea 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -4,7 +4,7 @@
* Version: 0.1.1
* Description: Irda KingSun/DonShine USB Dongle
* Status: Experimental
-* Author: Alex Villac�s Lasso <a_villacis@palosanto.com>
+* Author: Alex Villacís Lasso <a_villacis@palosanto.com>
*
* Based on stir4200 and mcs7780 drivers, with (strange?) differences
*
@@ -652,6 +652,6 @@ static void __exit kingsun_cleanup(void)
}
module_exit(kingsun_cleanup);
-MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>");
+MODULE_AUTHOR("Alex Villacís Lasso <a_villacis@palosanto.com>");
MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index 9043bf4aa49..36ab98386be 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -79,7 +79,7 @@ MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>");
MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver");
MODULE_LICENSE("GPL");
-static int smsc_nopnp;
+static int smsc_nopnp = 1;
module_param_named(nopnp, smsc_nopnp, bool, 0);
MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
@@ -416,6 +416,13 @@ static int __init smsc_ircc_legacy_probe(void)
{
int ret = 0;
+#ifdef CONFIG_PCI
+ if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
+ /* Ignore errors from preconfiguration */
+ IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
+ }
+#endif
+
if (ircc_fir > 0 && ircc_sir > 0) {
IRDA_MESSAGE(" Overriding FIR address 0x%04x\n", ircc_fir);
IRDA_MESSAGE(" Overriding SIR address 0x%04x\n", ircc_sir);
@@ -459,13 +466,6 @@ static int __init smsc_ircc_init(void)
return ret;
}
-#ifdef CONFIG_PCI
- if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) {
- /* Ignore errors from preconfiguration */
- IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name);
- }
-#endif
-
dev_count = 0;
if (smsc_nopnp || !pnp_platform_devices ||
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index bf78ef1120a..0538ca9ce05 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -44,6 +44,7 @@ MODULE_LICENSE("GPL");
#include <linux/time.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -1660,8 +1661,8 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
idev = ndev->priv;
spin_lock_init(&idev->lock);
- init_MUTEX(&idev->sem);
- down(&idev->sem);
+ mutex_init(&idev->mtx);
+ mutex_lock(&idev->mtx);
idev->pdev = pdev;
if (vlsi_irda_init(ndev) < 0)
@@ -1689,12 +1690,12 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
IRDA_MESSAGE("%s: registered device %s\n", drivername, ndev->name);
pci_set_drvdata(pdev, ndev);
- up(&idev->sem);
+ mutex_unlock(&idev->mtx);
return 0;
out_freedev:
- up(&idev->sem);
+ mutex_unlock(&idev->mtx);
free_netdev(ndev);
out_disable:
pci_disable_device(pdev);
@@ -1716,12 +1717,12 @@ static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
unregister_netdev(ndev);
idev = ndev->priv;
- down(&idev->sem);
+ mutex_lock(&idev->mtx);
if (idev->proc_entry) {
remove_proc_entry(ndev->name, vlsi_proc_root);
idev->proc_entry = NULL;
}
- up(&idev->sem);
+ mutex_unlock(&idev->mtx);
free_netdev(ndev);
@@ -1751,7 +1752,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
}
idev = ndev->priv;
- down(&idev->sem);
+ mutex_lock(&idev->mtx);
if (pdev->current_state != 0) { /* already suspended */
if (state.event > pdev->current_state) { /* simply go deeper */
pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -1759,7 +1760,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
}
else
IRDA_ERROR("%s - %s: invalid suspend request %u -> %u\n", __FUNCTION__, pci_name(pdev), pdev->current_state, state.event);
- up(&idev->sem);
+ mutex_unlock(&idev->mtx);
return 0;
}
@@ -1775,7 +1776,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
pci_set_power_state(pdev, pci_choose_state(pdev, state));
pdev->current_state = state.event;
idev->resume_ok = 1;
- up(&idev->sem);
+ mutex_unlock(&idev->mtx);
return 0;
}
@@ -1790,9 +1791,9 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
return 0;
}
idev = ndev->priv;
- down(&idev->sem);
+ mutex_lock(&idev->mtx);
if (pdev->current_state == 0) {
- up(&idev->sem);
+ mutex_unlock(&idev->mtx);
IRDA_WARNING("%s - %s: already resumed\n",
__FUNCTION__, pci_name(pdev));
return 0;
@@ -1814,7 +1815,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
* device and independently resume_ok should catch any garbage config.
*/
IRDA_WARNING("%s - hm, nothing to resume?\n", __FUNCTION__);
- up(&idev->sem);
+ mutex_unlock(&idev->mtx);
return 0;
}
@@ -1824,7 +1825,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
netif_device_attach(ndev);
}
idev->resume_ok = 0;
- up(&idev->sem);
+ mutex_unlock(&idev->mtx);
return 0;
}
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h
index 2d3b773d8e3..ca12a609641 100644
--- a/drivers/net/irda/vlsi_ir.h
+++ b/drivers/net/irda/vlsi_ir.h
@@ -728,7 +728,7 @@ typedef struct vlsi_irda_dev {
struct timeval last_rx;
spinlock_t lock;
- struct semaphore sem;
+ struct mutex mtx;
u8 resume_ok;
struct proc_dir_entry *proc_entry;
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 6683afc02aa..d9ce1aef148 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -111,7 +111,7 @@ static int ixpdev_rx(struct net_device *dev, int *budget)
skb = dev_alloc_skb(desc->pkt_length + 2);
if (likely(skb != NULL)) {
skb_reserve(skb, 2);
- eth_copy_and_sum(skb, buf, desc->pkt_length, 0);
+ skb_copy_to_linear_data(skb, buf, desc->pkt_length);
skb_put(skb, desc->pkt_length);
skb->protocol = eth_type_trans(skb, nds[desc->channel]);
@@ -222,7 +222,7 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
static void ixpdev_poll_controller(struct net_device *dev)
{
disable_irq(IRQ_IXP2000_THDA0);
- ixpdev_interrupt(IRQ_IXP2000_THDA0, dev, NULL);
+ ixpdev_interrupt(IRQ_IXP2000_THDA0, dev);
enable_irq(IRQ_IXP2000_THDA0);
}
#endif
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 0fe96c85828..a2f37e52b92 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -1186,9 +1186,9 @@ lance_rx(struct net_device *dev)
}
skb_reserve(skb,2); /* 16 byte align */
skb_put(skb,pkt_len); /* Make room */
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
(unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
- pkt_len,0);
+ pkt_len);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
dev->last_rx = jiffies;
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 6b49fc4bd1a..efbae4b8398 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -83,95 +83,39 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
-#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/pdc.h>
-#include <asm/cache.h>
#include <asm/parisc-device.h>
#define LASI_82596_DRIVER_VERSION "LASI 82596 driver - Revision: 1.30"
-/* DEBUG flags
- */
-
-#define DEB_INIT 0x0001
-#define DEB_PROBE 0x0002
-#define DEB_SERIOUS 0x0004
-#define DEB_ERRORS 0x0008
-#define DEB_MULTI 0x0010
-#define DEB_TDR 0x0020
-#define DEB_OPEN 0x0040
-#define DEB_RESET 0x0080
-#define DEB_ADDCMD 0x0100
-#define DEB_STATUS 0x0200
-#define DEB_STARTTX 0x0400
-#define DEB_RXADDR 0x0800
-#define DEB_TXADDR 0x1000
-#define DEB_RXFRAME 0x2000
-#define DEB_INTS 0x4000
-#define DEB_STRUCT 0x8000
-#define DEB_ANY 0xffff
-
-
-#define DEB(x,y) if (i596_debug & (x)) { y; }
-
-
-#define CHECK_WBACK(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_TO_DEVICE); } while (0)
-
-#define CHECK_INV(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_FROM_DEVICE); } while(0)
-
-#define CHECK_WBACK_INV(priv, addr,len) \
- do { dma_cache_sync((priv)->dev, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
-
-
#define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/
#define PA_CPU_PORT_L_ACCESS 4
#define PA_CHANNEL_ATTENTION 8
+#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */
-/*
- * Define various macros for Channel Attention, word swapping etc., dependent
- * on architecture. MVME and BVME are 680x0 based, otherwise it is Intel.
- */
+#define DMA_ALLOC dma_alloc_noncoherent
+#define DMA_FREE dma_free_noncoherent
+#define DMA_WBACK(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0)
-#ifdef __BIG_ENDIAN
-#define WSWAPrfd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPrbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPiscp(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPscb(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPcmd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPtbd(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define WSWAPchar(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
-#define ISCP_BUSY 0x00010000
-#define MACH_IS_APRICOT 0
-#else
-#define WSWAPrfd(x) ((struct i596_rfd *)(x))
-#define WSWAPrbd(x) ((struct i596_rbd *)(x))
-#define WSWAPiscp(x) ((struct i596_iscp *)(x))
-#define WSWAPscb(x) ((struct i596_scb *)(x))
-#define WSWAPcmd(x) ((struct i596_cmd *)(x))
-#define WSWAPtbd(x) ((struct i596_tbd *)(x))
-#define WSWAPchar(x) ((char *)(x))
-#define ISCP_BUSY 0x0001
-#define MACH_IS_APRICOT 1
-#endif
+#define DMA_INV(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_FROM_DEVICE); } while (0)
-/*
- * The MPU_PORT command allows direct access to the 82596. With PORT access
- * the following commands are available (p5-18). The 32-bit port command
- * must be word-swapped with the most significant word written first.
- * This only applies to VME boards.
- */
-#define PORT_RESET 0x00 /* reset 82596 */
-#define PORT_SELFTEST 0x01 /* selftest */
-#define PORT_ALTSCP 0x02 /* alternate SCB address */
-#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */
+#define DMA_WBACK_INV(ndev, addr, len) \
+ do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_BIDIRECTIONAL); } while (0)
+
+#define SYSBUS 0x0000006c;
+
+/* big endian CPU, 82596 "big" endian mode */
+#define SWAP32(x) (((u32)(x)<<16) | ((((u32)(x)))>>16))
+#define SWAP16(x) (x)
-static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+#include "lib82596.c"
MODULE_AUTHOR("Richard Hirst");
MODULE_DESCRIPTION("i82596 driver");
@@ -179,255 +123,15 @@ MODULE_LICENSE("GPL");
module_param(i596_debug, int, 0);
MODULE_PARM_DESC(i596_debug, "lasi_82596 debug mask");
-/* Copy frames shorter than rx_copybreak, otherwise pass on up in
- * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha).
- */
-static int rx_copybreak = 100;
-
-#define MAX_DRIVERS 4 /* max count of drivers */
-
-#define PKT_BUF_SZ 1536
-#define MAX_MC_CNT 64
-
-#define I596_NULL ((u32)0xffffffff)
-
-#define CMD_EOL 0x8000 /* The last command of the list, stop. */
-#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */
-#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */
-
-#define CMD_FLEX 0x0008 /* Enable flexible memory model */
-
-enum commands {
- CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
- CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
-};
-
-#define STAT_C 0x8000 /* Set to 0 after execution */
-#define STAT_B 0x4000 /* Command being executed */
-#define STAT_OK 0x2000 /* Command executed ok */
-#define STAT_A 0x1000 /* Command aborted */
-
-#define CUC_START 0x0100
-#define CUC_RESUME 0x0200
-#define CUC_SUSPEND 0x0300
-#define CUC_ABORT 0x0400
-#define RX_START 0x0010
-#define RX_RESUME 0x0020
-#define RX_SUSPEND 0x0030
-#define RX_ABORT 0x0040
-
-#define TX_TIMEOUT 5
-
-#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */
-
-
-struct i596_reg {
- unsigned short porthi;
- unsigned short portlo;
- u32 ca;
-};
-
-#define EOF 0x8000
-#define SIZE_MASK 0x3fff
-
-struct i596_tbd {
- unsigned short size;
- unsigned short pad;
- dma_addr_t next;
- dma_addr_t data;
- u32 cache_pad[5]; /* Total 32 bytes... */
-};
-
-/* The command structure has two 'next' pointers; v_next is the address of
- * the next command as seen by the CPU, b_next is the address of the next
- * command as seen by the 82596. The b_next pointer, as used by the 82596
- * always references the status field of the next command, rather than the
- * v_next field, because the 82596 is unaware of v_next. It may seem more
- * logical to put v_next at the end of the structure, but we cannot do that
- * because the 82596 expects other fields to be there, depending on command
- * type.
- */
-
-struct i596_cmd {
- struct i596_cmd *v_next; /* Address from CPUs viewpoint */
- unsigned short status;
- unsigned short command;
- dma_addr_t b_next; /* Address from i596 viewpoint */
-};
-
-struct tx_cmd {
- struct i596_cmd cmd;
- dma_addr_t tbd;
- unsigned short size;
- unsigned short pad;
- struct sk_buff *skb; /* So we can free it after tx */
- dma_addr_t dma_addr;
-#ifdef __LP64__
- u32 cache_pad[6]; /* Total 64 bytes... */
-#else
- u32 cache_pad[1]; /* Total 32 bytes... */
-#endif
-};
-
-struct tdr_cmd {
- struct i596_cmd cmd;
- unsigned short status;
- unsigned short pad;
-};
-
-struct mc_cmd {
- struct i596_cmd cmd;
- short mc_cnt;
- char mc_addrs[MAX_MC_CNT*6];
-};
-
-struct sa_cmd {
- struct i596_cmd cmd;
- char eth_addr[8];
-};
-
-struct cf_cmd {
- struct i596_cmd cmd;
- char i596_config[16];
-};
-
-struct i596_rfd {
- unsigned short stat;
- unsigned short cmd;
- dma_addr_t b_next; /* Address from i596 viewpoint */
- dma_addr_t rbd;
- unsigned short count;
- unsigned short size;
- struct i596_rfd *v_next; /* Address from CPUs viewpoint */
- struct i596_rfd *v_prev;
-#ifndef __LP64__
- u32 cache_pad[2]; /* Total 32 bytes... */
-#endif
-};
-
-struct i596_rbd {
- /* hardware data */
- unsigned short count;
- unsigned short zero1;
- dma_addr_t b_next;
- dma_addr_t b_data; /* Address from i596 viewpoint */
- unsigned short size;
- unsigned short zero2;
- /* driver data */
- struct sk_buff *skb;
- struct i596_rbd *v_next;
- dma_addr_t b_addr; /* This rbd addr from i596 view */
- unsigned char *v_data; /* Address from CPUs viewpoint */
- /* Total 32 bytes... */
-#ifdef __LP64__
- u32 cache_pad[4];
-#endif
-};
-
-/* These values as chosen so struct i596_private fits in one page... */
-
-#define TX_RING_SIZE 32
-#define RX_RING_SIZE 16
-
-struct i596_scb {
- unsigned short status;
- unsigned short command;
- dma_addr_t cmd;
- dma_addr_t rfd;
- u32 crc_err;
- u32 align_err;
- u32 resource_err;
- u32 over_err;
- u32 rcvdt_err;
- u32 short_err;
- unsigned short t_on;
- unsigned short t_off;
-};
-
-struct i596_iscp {
- u32 stat;
- dma_addr_t scb;
-};
-
-struct i596_scp {
- u32 sysbus;
- u32 pad;
- dma_addr_t iscp;
-};
-
-struct i596_private {
- volatile struct i596_scp scp __attribute__((aligned(32)));
- volatile struct i596_iscp iscp __attribute__((aligned(32)));
- volatile struct i596_scb scb __attribute__((aligned(32)));
- struct sa_cmd sa_cmd __attribute__((aligned(32)));
- struct cf_cmd cf_cmd __attribute__((aligned(32)));
- struct tdr_cmd tdr_cmd __attribute__((aligned(32)));
- struct mc_cmd mc_cmd __attribute__((aligned(32)));
- struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32)));
- struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32)));
- struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32)));
- struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32)));
- u32 stat;
- int last_restart;
- struct i596_rfd *rfd_head;
- struct i596_rbd *rbd_head;
- struct i596_cmd *cmd_tail;
- struct i596_cmd *cmd_head;
- int cmd_backlog;
- u32 last_cmd;
- struct net_device_stats stats;
- int next_tx_cmd;
- int options;
- spinlock_t lock;
- dma_addr_t dma_addr;
- struct device *dev;
-};
-
-static const char init_setup[] =
-{
- 0x8E, /* length, prefetch on */
- 0xC8, /* fifo to 8, monitor off */
- 0x80, /* don't save bad frames */
- 0x2E, /* No source address insertion, 8 byte preamble */
- 0x00, /* priority and backoff defaults */
- 0x60, /* interframe spacing */
- 0x00, /* slot time LSB */
- 0xf2, /* slot time and retries */
- 0x00, /* promiscuous mode */
- 0x00, /* collision detect */
- 0x40, /* minimum frame length */
- 0xff,
- 0x00,
- 0x7f /* *multi IA */ };
-
-static int i596_open(struct net_device *dev);
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id);
-static int i596_close(struct net_device *dev);
-static struct net_device_stats *i596_get_stats(struct net_device *dev);
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
-static void i596_tx_timeout (struct net_device *dev);
-static void print_eth(unsigned char *buf, char *str);
-static void set_multicast_list(struct net_device *dev);
-
-static int rx_ring_size = RX_RING_SIZE;
-static int ticks_limit = 100;
-static int max_cmd_backlog = TX_RING_SIZE-1;
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev);
-#endif
-
-
-static inline void CA(struct net_device *dev)
+static inline void ca(struct net_device *dev)
{
gsc_writel(0, dev->base_addr + PA_CHANNEL_ATTENTION);
}
-static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
u32 v = (u32) (c) | (u32) (x);
u16 a, b;
@@ -445,1078 +149,15 @@ static inline void MPU_PORT(struct net_device *dev, int c, dma_addr_t x)
gsc_writel(b, dev->base_addr + PA_CPU_PORT_L_ACCESS);
}
-
-static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
- CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
- while (--delcnt && lp->iscp.stat) {
- udelay(10);
- CHECK_INV(lp, &(lp->iscp), sizeof(struct i596_iscp));
- }
- if (!delcnt) {
- printk("%s: %s, iscp.stat %04x, didn't clear\n",
- dev->name, str, lp->iscp.stat);
- return -1;
- }
- else
- return 0;
-}
-
-
-static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
-{
- CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- while (--delcnt && lp->scb.command) {
- udelay(10);
- CHECK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- }
- if (!delcnt) {
- printk("%s: %s, status %4.4x, cmd %4.4x.\n",
- dev->name, str, lp->scb.status, lp->scb.command);
- return -1;
- }
- else
- return 0;
-}
-
-
-static void i596_display_data(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_cmd *cmd;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
-
- printk("lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
- &lp->scp, lp->scp.sysbus, lp->scp.iscp);
- printk("iscp at %p, iscp.stat = %08x, .scb = %08x\n",
- &lp->iscp, lp->iscp.stat, lp->iscp.scb);
- printk("scb at %p, scb.status = %04x, .command = %04x,"
- " .cmd = %08x, .rfd = %08x\n",
- &lp->scb, lp->scb.status, lp->scb.command,
- lp->scb.cmd, lp->scb.rfd);
- printk(" errors: crc %x, align %x, resource %x,"
- " over %x, rcvdt %x, short %x\n",
- lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err,
- lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err);
- cmd = lp->cmd_head;
- while (cmd != NULL) {
- printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %08x\n",
- cmd, cmd->status, cmd->command, cmd->b_next);
- cmd = cmd->v_next;
- }
- rfd = lp->rfd_head;
- printk("rfd_head = %p\n", rfd);
- do {
- printk(" %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
- " count %04x\n",
- rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd,
- rfd->count);
- rfd = rfd->v_next;
- } while (rfd != lp->rfd_head);
- rbd = lp->rbd_head;
- printk("rbd_head = %p\n", rbd);
- do {
- printk(" %p .count %04x, b_next %08x, b_data %08x, size %04x\n",
- rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
- rbd = rbd->v_next;
- } while (rbd != lp->rbd_head);
- CHECK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
-static void i596_error(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
-
- pcc2[0x28] = 1;
- pcc2[0x2b] = 0x1d;
- printk("%s: Error interrupt\n", dev->name);
- i596_display_data(dev);
-}
-#endif
-
-#define virt_to_dma(lp,v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)(lp)))
-
-static inline void init_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int i;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
-
- /* First build the Receive Buffer Descriptor List */
-
- for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
- dma_addr_t dma_addr;
- struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4);
-
- if (skb == NULL)
- panic("%s: alloc_skb() failed", __FILE__);
- skb_reserve(skb, 2);
- dma_addr = dma_map_single(lp->dev, skb->data,PKT_BUF_SZ,
- DMA_FROM_DEVICE);
- skb->dev = dev;
- rbd->v_next = rbd+1;
- rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1));
- rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd));
- rbd->skb = skb;
- rbd->v_data = skb->data;
- rbd->b_data = WSWAPchar(dma_addr);
- rbd->size = PKT_BUF_SZ;
- }
- lp->rbd_head = lp->rbds;
- rbd = lp->rbds + rx_ring_size - 1;
- rbd->v_next = lp->rbds;
- rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
- /* Now build the Receive Frame Descriptor List */
-
- for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
- rfd->rbd = I596_NULL;
- rfd->v_next = rfd+1;
- rfd->v_prev = rfd-1;
- rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1));
- rfd->cmd = CMD_FLEX;
- }
- lp->rfd_head = lp->rfds;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- rfd = lp->rfds;
- rfd->rbd = WSWAPrbd(virt_to_dma(lp,lp->rbd_head));
- rfd->v_prev = lp->rfds + rx_ring_size - 1;
- rfd = lp->rfds + rx_ring_size - 1;
- rfd->v_next = lp->rfds;
- rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- rfd->cmd = CMD_EOL|CMD_FLEX;
-
- CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-static inline void remove_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_rbd *rbd;
- int i;
-
- for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
- if (rbd->skb == NULL)
- break;
- dma_unmap_single(lp->dev,
- (dma_addr_t)WSWAPchar(rbd->b_data),
- PKT_BUF_SZ, DMA_FROM_DEVICE);
- dev_kfree_skb(rbd->skb);
- }
-}
-
-
-static void rebuild_rx_bufs(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int i;
-
- /* Ensure rx frame/buffer descriptors are tidy */
-
- for (i = 0; i < rx_ring_size; i++) {
- lp->rfds[i].rbd = I596_NULL;
- lp->rfds[i].cmd = CMD_FLEX;
- }
- lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
- lp->rfd_head = lp->rfds;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- lp->rbd_head = lp->rbds;
- lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds));
-
- CHECK_WBACK_INV(lp, lp, sizeof(struct i596_private));
-}
-
-
-static int init_i596_mem(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- disable_irq(dev->irq); /* disable IRQs from LAN */
- DEB(DEB_INIT,
- printk("RESET 82596 port: %lx (with IRQ %d disabled)\n",
- (dev->base_addr + PA_I82596_RESET),
- dev->irq));
-
- gsc_writel(0, (dev->base_addr + PA_I82596_RESET)); /* Hard Reset */
- udelay(100); /* Wait 100us - seems to help */
-
- /* change the scp address */
-
- lp->last_cmd = jiffies;
-
-
- lp->scp.sysbus = 0x0000006c;
- lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp)));
- lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb)));
- lp->iscp.stat = ISCP_BUSY;
- lp->cmd_backlog = 0;
-
- lp->cmd_head = NULL;
- lp->scb.cmd = I596_NULL;
-
- DEB(DEB_INIT, printk("%s: starting i82596.\n", dev->name));
-
- CHECK_WBACK(lp, &(lp->scp), sizeof(struct i596_scp));
- CHECK_WBACK(lp, &(lp->iscp), sizeof(struct i596_iscp));
-
- MPU_PORT(dev, PORT_ALTSCP, virt_to_dma(lp,&lp->scp));
-
- CA(dev);
-
- if (wait_istat(dev, lp, 1000, "initialization timed out"))
- goto failed;
- DEB(DEB_INIT, printk("%s: i82596 initialization successful\n", dev->name));
-
- /* Ensure rx frame/buffer descriptors are tidy */
- rebuild_rx_bufs(dev);
-
- lp->scb.command = 0;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
- enable_irq(dev->irq); /* enable IRQs from LAN */
-
- DEB(DEB_INIT, printk("%s: queuing CmdConfigure\n", dev->name));
- memcpy(lp->cf_cmd.i596_config, init_setup, sizeof(init_setup));
- lp->cf_cmd.cmd.command = CmdConfigure;
- CHECK_WBACK(lp, &(lp->cf_cmd), sizeof(struct cf_cmd));
- i596_add_cmd(dev, &lp->cf_cmd.cmd);
-
- DEB(DEB_INIT, printk("%s: queuing CmdSASetup\n", dev->name));
- memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
- lp->sa_cmd.cmd.command = CmdSASetup;
- CHECK_WBACK(lp, &(lp->sa_cmd), sizeof(struct sa_cmd));
- i596_add_cmd(dev, &lp->sa_cmd.cmd);
-
- DEB(DEB_INIT, printk("%s: queuing CmdTDR\n", dev->name));
- lp->tdr_cmd.cmd.command = CmdTDR;
- CHECK_WBACK(lp, &(lp->tdr_cmd), sizeof(struct tdr_cmd));
- i596_add_cmd(dev, &lp->tdr_cmd.cmd);
-
- spin_lock_irqsave (&lp->lock, flags);
-
- if (wait_cmd(dev, lp, 1000, "timed out waiting to issue RX_START")) {
- spin_unlock_irqrestore (&lp->lock, flags);
- goto failed;
- }
- DEB(DEB_INIT, printk("%s: Issuing RX_START\n", dev->name));
- lp->scb.command = RX_START;
- lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds));
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-
- CA(dev);
-
- spin_unlock_irqrestore (&lp->lock, flags);
-
- if (wait_cmd(dev, lp, 1000, "RX_START not processed"))
- goto failed;
- DEB(DEB_INIT, printk("%s: Receive unit started OK\n", dev->name));
-
- return 0;
-
-failed:
- printk("%s: Failed to initialise 82596\n", dev->name);
- MPU_PORT(dev, PORT_RESET, 0);
- return -1;
-}
-
-
-static inline int i596_rx(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct i596_rfd *rfd;
- struct i596_rbd *rbd;
- int frames = 0;
-
- DEB(DEB_RXFRAME, printk("i596_rx(), rfd_head %p, rbd_head %p\n",
- lp->rfd_head, lp->rbd_head));
-
-
- rfd = lp->rfd_head; /* Ref next frame to check */
-
- CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
- while ((rfd->stat) & STAT_C) { /* Loop while complete frames */
- if (rfd->rbd == I596_NULL)
- rbd = NULL;
- else if (rfd->rbd == lp->rbd_head->b_addr) {
- rbd = lp->rbd_head;
- CHECK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
- else {
- printk("%s: rbd chain broken!\n", dev->name);
- /* XXX Now what? */
- rbd = NULL;
- }
- DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
- rfd, rfd->rbd, rfd->stat));
-
- if (rbd != NULL && ((rfd->stat) & STAT_OK)) {
- /* a good frame */
- int pkt_len = rbd->count & 0x3fff;
- struct sk_buff *skb = rbd->skb;
- int rx_in_place = 0;
-
- DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));
- frames++;
-
- /* Check if the packet is long enough to just accept
- * without copying to a properly sized skbuff.
- */
-
- if (pkt_len > rx_copybreak) {
- struct sk_buff *newskb;
- dma_addr_t dma_addr;
-
- dma_unmap_single(lp->dev,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- /* Get fresh skbuff to replace filled one. */
- newskb = dev_alloc_skb(PKT_BUF_SZ + 4);
- if (newskb == NULL) {
- skb = NULL; /* drop pkt */
- goto memory_squeeze;
- }
- skb_reserve(newskb, 2);
-
- /* Pass up the skb already on the Rx ring. */
- skb_put(skb, pkt_len);
- rx_in_place = 1;
- rbd->skb = newskb;
- newskb->dev = dev;
- dma_addr = dma_map_single(lp->dev, newskb->data, PKT_BUF_SZ, DMA_FROM_DEVICE);
- rbd->v_data = newskb->data;
- rbd->b_data = WSWAPchar(dma_addr);
- CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
- else
- skb = dev_alloc_skb(pkt_len + 2);
-memory_squeeze:
- if (skb == NULL) {
- /* XXX tulip.c can defer packets here!! */
- printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- }
- else {
- if (!rx_in_place) {
- /* 16 byte align the data fields */
- dma_sync_single_for_cpu(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- skb_reserve(skb, 2);
- memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);
- dma_sync_single_for_device(lp->dev, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, DMA_FROM_DEVICE);
- }
- skb->len = pkt_len;
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
- lp->stats.rx_bytes+=pkt_len;
- }
- }
- else {
- DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n",
- dev->name, rfd->stat));
- lp->stats.rx_errors++;
- if ((rfd->stat) & 0x0001)
- lp->stats.collisions++;
- if ((rfd->stat) & 0x0080)
- lp->stats.rx_length_errors++;
- if ((rfd->stat) & 0x0100)
- lp->stats.rx_over_errors++;
- if ((rfd->stat) & 0x0200)
- lp->stats.rx_fifo_errors++;
- if ((rfd->stat) & 0x0400)
- lp->stats.rx_frame_errors++;
- if ((rfd->stat) & 0x0800)
- lp->stats.rx_crc_errors++;
- if ((rfd->stat) & 0x1000)
- lp->stats.rx_length_errors++;
- }
-
- /* Clear the buffer descriptor count and EOF + F flags */
-
- if (rbd != NULL && (rbd->count & 0x4000)) {
- rbd->count = 0;
- lp->rbd_head = rbd->v_next;
- CHECK_WBACK_INV(lp, rbd, sizeof(struct i596_rbd));
- }
-
- /* Tidy the frame descriptor, marking it as end of list */
-
- rfd->rbd = I596_NULL;
- rfd->stat = 0;
- rfd->cmd = CMD_EOL|CMD_FLEX;
- rfd->count = 0;
-
- /* Remove end-of-list from old end descriptor */
-
- rfd->v_prev->cmd = CMD_FLEX;
-
- /* Update record of next frame descriptor to process */
-
- lp->scb.rfd = rfd->b_next;
- lp->rfd_head = rfd->v_next;
- CHECK_WBACK_INV(lp, rfd->v_prev, sizeof(struct i596_rfd));
- CHECK_WBACK_INV(lp, rfd, sizeof(struct i596_rfd));
- rfd = lp->rfd_head;
- CHECK_INV(lp, rfd, sizeof(struct i596_rfd));
- }
-
- DEB(DEB_RXFRAME, printk("frames %d\n", frames));
-
- return 0;
-}
-
-
-static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
-{
- struct i596_cmd *ptr;
-
- while (lp->cmd_head != NULL) {
- ptr = lp->cmd_head;
- lp->cmd_head = ptr->v_next;
- lp->cmd_backlog--;
-
- switch ((ptr->command) & 0x7) {
- case CmdTx:
- {
- struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
- struct sk_buff *skb = tx_cmd->skb;
- dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
-
- dev_kfree_skb(skb);
-
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
-
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- tx_cmd->cmd.command = 0; /* Mark as free */
- break;
- }
- default:
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- }
- CHECK_WBACK_INV(lp, ptr, sizeof(struct i596_cmd));
- }
-
- wait_cmd(dev, lp, 100, "i596_cleanup_cmd timed out");
- lp->scb.cmd = I596_NULL;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
-}
-
-
-static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
-{
- unsigned long flags;
-
- DEB(DEB_RESET, printk("i596_reset\n"));
-
- spin_lock_irqsave (&lp->lock, flags);
-
- wait_cmd(dev, lp, 100, "i596_reset timed out");
-
- netif_stop_queue(dev);
-
- /* FIXME: this command might cause an lpmc */
- lp->scb.command = CUC_ABORT | RX_ABORT;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
- CA(dev);
-
- /* wait for shutdown */
- wait_cmd(dev, lp, 1000, "i596_reset 2 timed out");
- spin_unlock_irqrestore (&lp->lock, flags);
-
- i596_cleanup_cmd(dev,lp);
- i596_rx(dev);
-
- netif_start_queue(dev);
- init_i596_mem(dev);
-}
-
-
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- DEB(DEB_ADDCMD, printk("i596_add_cmd cmd_head %p\n", lp->cmd_head));
-
- cmd->status = 0;
- cmd->command |= (CMD_EOL | CMD_INTR);
- cmd->v_next = NULL;
- cmd->b_next = I596_NULL;
- CHECK_WBACK(lp, cmd, sizeof(struct i596_cmd));
-
- spin_lock_irqsave (&lp->lock, flags);
-
- if (lp->cmd_head != NULL) {
- lp->cmd_tail->v_next = cmd;
- lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status));
- CHECK_WBACK(lp, lp->cmd_tail, sizeof(struct i596_cmd));
- } else {
- lp->cmd_head = cmd;
- wait_cmd(dev, lp, 100, "i596_add_cmd timed out");
- lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status));
- lp->scb.command = CUC_START;
- CHECK_WBACK(lp, &(lp->scb), sizeof(struct i596_scb));
- CA(dev);
- }
- lp->cmd_tail = cmd;
- lp->cmd_backlog++;
-
- spin_unlock_irqrestore (&lp->lock, flags);
-
- if (lp->cmd_backlog > max_cmd_backlog) {
- unsigned long tickssofar = jiffies - lp->last_cmd;
-
- if (tickssofar < ticks_limit)
- return;
-
- printk("%s: command unit timed out, status resetting.\n", dev->name);
-#if 1
- i596_reset(dev, lp);
-#endif
- }
-}
-
-#if 0
-/* this function makes a perfectly adequate probe... but we have a
- device list */
-static int i596_test(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- volatile int *tint;
- u32 data;
-
- tint = (volatile int *)(&(lp->scp));
- data = virt_to_dma(lp,tint);
-
- tint[1] = -1;
- CHECK_WBACK(lp, tint, PAGE_SIZE);
-
- MPU_PORT(dev, 1, data);
-
- for(data = 1000000; data; data--) {
- CHECK_INV(lp, tint, PAGE_SIZE);
- if(tint[1] != -1)
- break;
-
- }
-
- printk("i596_test result %d\n", tint[1]);
-
-}
-#endif
-
-
-static int i596_open(struct net_device *dev)
-{
- DEB(DEB_OPEN, printk("%s: i596_open() irq %d.\n", dev->name, dev->irq));
-
- if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
- printk("%s: IRQ %d not free\n", dev->name, dev->irq);
- goto out;
- }
-
- init_rx_bufs(dev);
-
- if (init_i596_mem(dev)) {
- printk("%s: Failed to init memory\n", dev->name);
- goto out_remove_rx_bufs;
- }
-
- netif_start_queue(dev);
-
- return 0;
-
-out_remove_rx_bufs:
- remove_rx_bufs(dev);
- free_irq(dev->irq, dev);
-out:
- return -EAGAIN;
-}
-
-static void i596_tx_timeout (struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
-
- /* Transmitter timeout, serious problems. */
- DEB(DEB_ERRORS, printk("%s: transmit timed out, status resetting.\n",
- dev->name));
-
- lp->stats.tx_errors++;
-
- /* Try to restart the adaptor */
- if (lp->last_restart == lp->stats.tx_packets) {
- DEB(DEB_ERRORS, printk("Resetting board.\n"));
- /* Shutdown and restart */
- i596_reset (dev, lp);
- } else {
- /* Issue a channel attention signal */
- DEB(DEB_ERRORS, printk("Kicking board.\n"));
- lp->scb.command = CUC_START | RX_START;
- CHECK_WBACK_INV(lp, &(lp->scb), sizeof(struct i596_scb));
- CA (dev);
- lp->last_restart = lp->stats.tx_packets;
- }
-
- dev->trans_start = jiffies;
- netif_wake_queue (dev);
-}
-
-
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- struct tx_cmd *tx_cmd;
- struct i596_tbd *tbd;
- short length = skb->len;
- dev->trans_start = jiffies;
-
- DEB(DEB_STARTTX, printk("%s: i596_start_xmit(%x,%p) called\n", dev->name,
- skb->len, skb->data));
-
- if (length < ETH_ZLEN) {
- if (skb_padto(skb, ETH_ZLEN))
- return 0;
- length = ETH_ZLEN;
- }
-
- netif_stop_queue(dev);
-
- tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
- tbd = lp->tbds + lp->next_tx_cmd;
-
- if (tx_cmd->cmd.command) {
- DEB(DEB_ERRORS, printk("%s: xmit ring full, dropping packet.\n",
- dev->name));
- lp->stats.tx_dropped++;
-
- dev_kfree_skb(skb);
- } else {
- if (++lp->next_tx_cmd == TX_RING_SIZE)
- lp->next_tx_cmd = 0;
- tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd));
- tbd->next = I596_NULL;
-
- tx_cmd->cmd.command = CMD_FLEX | CmdTx;
- tx_cmd->skb = skb;
-
- tx_cmd->pad = 0;
- tx_cmd->size = 0;
- tbd->pad = 0;
- tbd->size = EOF | length;
-
- tx_cmd->dma_addr = dma_map_single(lp->dev, skb->data, skb->len,
- DMA_TO_DEVICE);
- tbd->data = WSWAPchar(tx_cmd->dma_addr);
-
- DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
- CHECK_WBACK_INV(lp, tx_cmd, sizeof(struct tx_cmd));
- CHECK_WBACK_INV(lp, tbd, sizeof(struct i596_tbd));
- i596_add_cmd(dev, &tx_cmd->cmd);
-
- lp->stats.tx_packets++;
- lp->stats.tx_bytes += length;
- }
-
- netif_start_queue(dev);
-
- return 0;
-}
-
-static void print_eth(unsigned char *add, char *str)
-{
- int i;
-
- printk("i596 0x%p, ", add);
- for (i = 0; i < 6; i++)
- printk(" %02X", add[i + 6]);
- printk(" -->");
- for (i = 0; i < 6; i++)
- printk(" %02X", add[i]);
- printk(" %02X%02X, %s\n", add[12], add[13], str);
-}
-
-
#define LAN_PROM_ADDR 0xF0810000
-static int __devinit i82596_probe(struct net_device *dev,
- struct device *gen_dev)
-{
- int i;
- struct i596_private *lp;
- char eth_addr[6];
- dma_addr_t dma_addr;
-
- /* This lot is ensure things have been cache line aligned. */
- BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
- BUILD_BUG_ON(sizeof(struct i596_rbd) & 31);
- BUILD_BUG_ON(sizeof(struct tx_cmd) & 31);
- BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
-#ifndef __LP64__
- BUILD_BUG_ON(sizeof(struct i596_private) > 4096);
-#endif
-
- if (!dev->base_addr || !dev->irq)
- return -ENODEV;
-
- if (pdc_lan_station_id(eth_addr, dev->base_addr)) {
- for (i=0; i < 6; i++) {
- eth_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
- }
- printk(KERN_INFO "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
- }
-
- dev->mem_start = (unsigned long) dma_alloc_noncoherent(gen_dev,
- sizeof(struct i596_private), &dma_addr, GFP_KERNEL);
- if (!dev->mem_start) {
- printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
- return -ENOMEM;
- }
-
- for (i = 0; i < 6; i++)
- dev->dev_addr[i] = eth_addr[i];
-
- /* The 82596-specific entries in the device structure. */
- dev->open = i596_open;
- dev->stop = i596_close;
- dev->hard_start_xmit = i596_start_xmit;
- dev->get_stats = i596_get_stats;
- dev->set_multicast_list = set_multicast_list;
- dev->tx_timeout = i596_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = i596_poll_controller;
-#endif
-
- dev->priv = (void *)(dev->mem_start);
-
- lp = dev->priv;
- memset(lp, 0, sizeof(struct i596_private));
-
- lp->scb.command = 0;
- lp->scb.cmd = I596_NULL;
- lp->scb.rfd = I596_NULL;
- spin_lock_init(&lp->lock);
- lp->dma_addr = dma_addr;
- lp->dev = gen_dev;
-
- CHECK_WBACK_INV(lp, dev->mem_start, sizeof(struct i596_private));
-
- i = register_netdev(dev);
- if (i) {
- lp = dev->priv;
- dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
- (void *)dev->mem_start, lp->dma_addr);
- return i;
- };
-
- DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr));
- for (i = 0; i < 6; i++)
- DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
- DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
- DEB(DEB_INIT, printk(KERN_INFO "%s: lp at 0x%p (%d bytes), lp->scb at 0x%p\n",
- dev->name, lp, (int)sizeof(struct i596_private), &lp->scb));
-
- return 0;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void i596_poll_controller(struct net_device *dev)
-{
- disable_irq(dev->irq);
- i596_interrupt(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-static irqreturn_t i596_interrupt(int irq, void *dev_id)
-{
- struct net_device *dev = dev_id;
- struct i596_private *lp;
- unsigned short status, ack_cmd = 0;
-
- if (dev == NULL) {
- printk("%s: irq %d for unknown device.\n", __FUNCTION__, irq);
- return IRQ_NONE;
- }
-
- lp = dev->priv;
-
- spin_lock (&lp->lock);
-
- wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
- status = lp->scb.status;
-
- DEB(DEB_INTS, printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n",
- dev->name, irq, status));
-
- ack_cmd = status & 0xf000;
-
- if (!ack_cmd) {
- DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name));
- spin_unlock (&lp->lock);
- return IRQ_NONE;
- }
-
- if ((status & 0x8000) || (status & 0x2000)) {
- struct i596_cmd *ptr;
-
- if ((status & 0x8000))
- DEB(DEB_INTS, printk("%s: i596 interrupt completed command.\n", dev->name));
- if ((status & 0x2000))
- DEB(DEB_INTS, printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
-
- while (lp->cmd_head != NULL) {
- CHECK_INV(lp, lp->cmd_head, sizeof(struct i596_cmd));
- if (!(lp->cmd_head->status & STAT_C))
- break;
-
- ptr = lp->cmd_head;
-
- DEB(DEB_STATUS, printk("cmd_head->status = %04x, ->command = %04x\n",
- lp->cmd_head->status, lp->cmd_head->command));
- lp->cmd_head = ptr->v_next;
- lp->cmd_backlog--;
-
- switch ((ptr->command) & 0x7) {
- case CmdTx:
- {
- struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
- struct sk_buff *skb = tx_cmd->skb;
-
- if ((ptr->status) & STAT_OK) {
- DEB(DEB_TXADDR, print_eth(skb->data, "tx-done"));
- } else {
- lp->stats.tx_errors++;
- if ((ptr->status) & 0x0020)
- lp->stats.collisions++;
- if (!((ptr->status) & 0x0040))
- lp->stats.tx_heartbeat_errors++;
- if ((ptr->status) & 0x0400)
- lp->stats.tx_carrier_errors++;
- if ((ptr->status) & 0x0800)
- lp->stats.collisions++;
- if ((ptr->status) & 0x1000)
- lp->stats.tx_aborted_errors++;
- }
- dma_unmap_single(lp->dev, tx_cmd->dma_addr, skb->len, DMA_TO_DEVICE);
- dev_kfree_skb_irq(skb);
-
- tx_cmd->cmd.command = 0; /* Mark free */
- break;
- }
- case CmdTDR:
- {
- unsigned short status = ((struct tdr_cmd *)ptr)->status;
-
- if (status & 0x8000) {
- DEB(DEB_ANY, printk("%s: link ok.\n", dev->name));
- } else {
- if (status & 0x4000)
- printk("%s: Transceiver problem.\n", dev->name);
- if (status & 0x2000)
- printk("%s: Termination problem.\n", dev->name);
- if (status & 0x1000)
- printk("%s: Short circuit.\n", dev->name);
-
- DEB(DEB_TDR, printk("%s: Time %d.\n", dev->name, status & 0x07ff));
- }
- break;
- }
- case CmdConfigure:
- /* Zap command so set_multicast_list() knows it is free */
- ptr->command = 0;
- break;
- }
- ptr->v_next = NULL;
- ptr->b_next = I596_NULL;
- CHECK_WBACK(lp, ptr, sizeof(struct i596_cmd));
- lp->last_cmd = jiffies;
- }
-
- /* This mess is arranging that only the last of any outstanding
- * commands has the interrupt bit set. Should probably really
- * only add to the cmd queue when the CU is stopped.
- */
- ptr = lp->cmd_head;
- while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
- struct i596_cmd *prev = ptr;
-
- ptr->command &= 0x1fff;
- ptr = ptr->v_next;
- CHECK_WBACK_INV(lp, prev, sizeof(struct i596_cmd));
- }
-
- if ((lp->cmd_head != NULL))
- ack_cmd |= CUC_START;
- lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status));
- CHECK_WBACK_INV(lp, &lp->scb, sizeof(struct i596_scb));
- }
- if ((status & 0x1000) || (status & 0x4000)) {
- if ((status & 0x4000))
- DEB(DEB_INTS, printk("%s: i596 interrupt received a frame.\n", dev->name));
- i596_rx(dev);
- /* Only RX_START if stopped - RGH 07-07-96 */
- if (status & 0x1000) {
- if (netif_running(dev)) {
- DEB(DEB_ERRORS, printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status));
- ack_cmd |= RX_START;
- lp->stats.rx_errors++;
- lp->stats.rx_fifo_errors++;
- rebuild_rx_bufs(dev);
- }
- }
- }
- wait_cmd(dev, lp, 100, "i596 interrupt, timeout");
- lp->scb.command = ack_cmd;
- CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
- /* DANGER: I suspect that some kind of interrupt
- acknowledgement aside from acking the 82596 might be needed
- here... but it's running acceptably without */
-
- CA(dev);
-
- wait_cmd(dev, lp, 100, "i596 interrupt, exit timeout");
- DEB(DEB_INTS, printk("%s: exiting interrupt.\n", dev->name));
-
- spin_unlock (&lp->lock);
- return IRQ_HANDLED;
-}
-
-static int i596_close(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- unsigned long flags;
-
- netif_stop_queue(dev);
-
- DEB(DEB_INIT, printk("%s: Shutting down ethercard, status was %4.4x.\n",
- dev->name, lp->scb.status));
-
- spin_lock_irqsave(&lp->lock, flags);
-
- wait_cmd(dev, lp, 100, "close1 timed out");
- lp->scb.command = CUC_ABORT | RX_ABORT;
- CHECK_WBACK(lp, &lp->scb, sizeof(struct i596_scb));
-
- CA(dev);
-
- wait_cmd(dev, lp, 100, "close2 timed out");
- spin_unlock_irqrestore(&lp->lock, flags);
- DEB(DEB_STRUCT,i596_display_data(dev));
- i596_cleanup_cmd(dev,lp);
-
- disable_irq(dev->irq);
-
- free_irq(dev->irq, dev);
- remove_rx_bufs(dev);
-
- return 0;
-}
-
-static struct net_device_stats *
- i596_get_stats(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
-
- return &lp->stats;
-}
-
-/*
- * Set or clear the multicast filter for this adaptor.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
- struct i596_private *lp = dev->priv;
- int config = 0, cnt;
-
- DEB(DEB_MULTI, printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
- dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF",
- dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
-
- if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) {
- lp->cf_cmd.i596_config[8] |= 0x01;
- config = 1;
- }
- if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) {
- lp->cf_cmd.i596_config[8] &= ~0x01;
- config = 1;
- }
- if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) {
- lp->cf_cmd.i596_config[11] &= ~0x20;
- config = 1;
- }
- if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) {
- lp->cf_cmd.i596_config[11] |= 0x20;
- config = 1;
- }
- if (config) {
- if (lp->cf_cmd.cmd.command)
- printk("%s: config change request already queued\n",
- dev->name);
- else {
- lp->cf_cmd.cmd.command = CmdConfigure;
- CHECK_WBACK_INV(lp, &lp->cf_cmd, sizeof(struct cf_cmd));
- i596_add_cmd(dev, &lp->cf_cmd.cmd);
- }
- }
-
- cnt = dev->mc_count;
- if (cnt > MAX_MC_CNT)
- {
- cnt = MAX_MC_CNT;
- printk("%s: Only %d multicast addresses supported",
- dev->name, cnt);
- }
-
- if (dev->mc_count > 0) {
- struct dev_mc_list *dmi;
- unsigned char *cp;
- struct mc_cmd *cmd;
-
- cmd = &lp->mc_cmd;
- cmd->cmd.command = CmdMulticastList;
- cmd->mc_cnt = dev->mc_count * 6;
- cp = cmd->mc_addrs;
- for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
- memcpy(cp, dmi->dmi_addr, 6);
- if (i596_debug > 1)
- DEB(DEB_MULTI, printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
- dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5]));
- }
- CHECK_WBACK_INV(lp, &lp->mc_cmd, sizeof(struct mc_cmd));
- i596_add_cmd(dev, &cmd->cmd);
- }
-}
-
-static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "lasi_82596 debug mask");
-
-static int num_drivers;
-static struct net_device *netdevs[MAX_DRIVERS];
-
static int __devinit
lan_init_chip(struct parisc_device *dev)
{
struct net_device *netdevice;
+ struct i596_private *lp;
int retval;
-
- if (num_drivers >= MAX_DRIVERS) {
- /* max count of possible i82596 drivers reached */
- return -ENOMEM;
- }
-
- if (num_drivers == 0)
- printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
+ int i;
if (!dev->irq) {
printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
@@ -1527,28 +168,45 @@ lan_init_chip(struct parisc_device *dev)
printk(KERN_INFO "Found i82596 at 0x%lx, IRQ %d\n", dev->hpa.start,
dev->irq);
- netdevice = alloc_etherdev(0);
+ netdevice = alloc_etherdev(sizeof(struct i596_private));
if (!netdevice)
return -ENOMEM;
+ SET_NETDEV_DEV(netdevice, &dev->dev);
+ parisc_set_drvdata (dev, netdevice);
netdevice->base_addr = dev->hpa.start;
netdevice->irq = dev->irq;
- retval = i82596_probe(netdevice, &dev->dev);
+ if (pdc_lan_station_id(netdevice->dev_addr, netdevice->base_addr)) {
+ for (i = 0; i < 6; i++) {
+ netdevice->dev_addr[i] = gsc_readb(LAN_PROM_ADDR + i);
+ }
+ printk(KERN_INFO
+ "%s: MAC of HP700 LAN read from EEPROM\n", __FILE__);
+ }
+
+ lp = netdev_priv(netdevice);
+ lp->options = dev->id.sversion == 0x72 ? OPT_SWAP_PORT : 0;
+
+ retval = i82596_probe(netdevice);
if (retval) {
free_netdev(netdevice);
return -ENODEV;
}
-
- if (dev->id.sversion == 0x72) {
- ((struct i596_private *)netdevice->priv)->options = OPT_SWAP_PORT;
- }
-
- netdevs[num_drivers++] = netdevice;
-
return retval;
}
+static int __devexit lan_remove_chip (struct parisc_device *pdev)
+{
+ struct net_device *dev = parisc_get_drvdata(pdev);
+ struct i596_private *lp = netdev_priv(dev);
+
+ unregister_netdev (dev);
+ DMA_FREE(&pdev->dev, sizeof(struct i596_private),
+ (void *)lp->dma, lp->dma_addr);
+ free_netdev (dev);
+ return 0;
+}
static struct parisc_device_id lan_tbl[] = {
{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008a },
@@ -1562,12 +220,12 @@ static struct parisc_driver lan_driver = {
.name = "lasi_82596",
.id_table = lan_tbl,
.probe = lan_init_chip,
+ .remove = __devexit_p(lan_remove_chip),
};
static int __devinit lasi_82596_init(void)
{
- if (debug >= 0)
- i596_debug = debug;
+ printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
return register_parisc_driver(&lan_driver);
}
@@ -1575,25 +233,6 @@ module_init(lasi_82596_init);
static void __exit lasi_82596_exit(void)
{
- int i;
-
- for (i=0; i<MAX_DRIVERS; i++) {
- struct i596_private *lp;
- struct net_device *netdevice;
-
- netdevice = netdevs[i];
- if (!netdevice)
- continue;
-
- unregister_netdev(netdevice);
-
- lp = netdevice->priv;
- dma_free_noncoherent(lp->dev, sizeof(struct i596_private),
- (void *)netdevice->mem_start, lp->dma_addr);
- free_netdev(netdevice);
- }
- num_drivers = 0;
-
unregister_parisc_driver(&lan_driver);
}
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
new file mode 100644
index 00000000000..5884f5bd04a
--- /dev/null
+++ b/drivers/net/lib82596.c
@@ -0,0 +1,1434 @@
+/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as
+ munged into HPPA boxen .
+
+ This driver is based upon 82596.c, original credits are below...
+ but there were too many hoops which HP wants jumped through to
+ keep this code in there in a sane manner.
+
+ 3 primary sources of the mess --
+ 1) hppa needs *lots* of cacheline flushing to keep this kind of
+ MMIO running.
+
+ 2) The 82596 needs to see all of its pointers as their physical
+ address. Thus virt_to_bus/bus_to_virt are *everywhere*.
+
+ 3) The implementation HP is using seems to be significantly pickier
+ about when and how the command and RX units are started. some
+ command ordering was changed.
+
+ Examination of the mach driver leads one to believe that there
+ might be a saner way to pull this off... anyone who feels like a
+ full rewrite can be my guest.
+
+ Split 02/13/2000 Sam Creasey (sammy@oh.verio.com)
+
+ 02/01/2000 Initial modifications for parisc by Helge Deller (deller@gmx.de)
+ 03/02/2000 changes for better/correct(?) cache-flushing (deller)
+*/
+
+/* 82596.c: A generic 82596 ethernet driver for linux. */
+/*
+ Based on Apricot.c
+ Written 1994 by Mark Evans.
+ This driver is for the Apricot 82596 bus-master interface
+
+ Modularised 12/94 Mark Evans
+
+
+ Modified to support the 82596 ethernet chips on 680x0 VME boards.
+ by Richard Hirst <richard@sleepie.demon.co.uk>
+ Renamed to be 82596.c
+
+ 980825: Changed to receive directly in to sk_buffs which are
+ allocated at open() time. Eliminates copy on incoming frames
+ (small ones are still copied). Shared data now held in a
+ non-cached page, so we can run on 68060 in copyback mode.
+
+ TBD:
+ * look at deferring rx frames rather than discarding (as per tulip)
+ * handle tx ring full as per tulip
+ * performace test to tune rx_copybreak
+
+ Most of my modifications relate to the braindead big-endian
+ implementation by Intel. When the i596 is operating in
+ 'big-endian' mode, it thinks a 32 bit value of 0x12345678
+ should be stored as 0x56781234. This is a real pain, when
+ you have linked lists which are shared by the 680x0 and the
+ i596.
+
+ Driver skeleton
+ Written 1993 by Donald Becker.
+ Copyright 1993 United States Government as represented by the Director,
+ National Security Agency. This software may only be used and distributed
+ according to the terms of the GNU General Public License as modified by SRC,
+ incorporated herein by reference.
+
+ The author may be reached as becker@scyld.com, or C/O
+ Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+/* DEBUG flags
+ */
+
+#define DEB_INIT 0x0001
+#define DEB_PROBE 0x0002
+#define DEB_SERIOUS 0x0004
+#define DEB_ERRORS 0x0008
+#define DEB_MULTI 0x0010
+#define DEB_TDR 0x0020
+#define DEB_OPEN 0x0040
+#define DEB_RESET 0x0080
+#define DEB_ADDCMD 0x0100
+#define DEB_STATUS 0x0200
+#define DEB_STARTTX 0x0400
+#define DEB_RXADDR 0x0800
+#define DEB_TXADDR 0x1000
+#define DEB_RXFRAME 0x2000
+#define DEB_INTS 0x4000
+#define DEB_STRUCT 0x8000
+#define DEB_ANY 0xffff
+
+
+#define DEB(x, y) if (i596_debug & (x)) { y; }
+
+
+/*
+ * The MPU_PORT command allows direct access to the 82596. With PORT access
+ * the following commands are available (p5-18). The 32-bit port command
+ * must be word-swapped with the most significant word written first.
+ * This only applies to VME boards.
+ */
+#define PORT_RESET 0x00 /* reset 82596 */
+#define PORT_SELFTEST 0x01 /* selftest */
+#define PORT_ALTSCP 0x02 /* alternate SCB address */
+#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */
+
+static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+
+/* Copy frames shorter than rx_copybreak, otherwise pass on up in
+ * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha).
+ */
+static int rx_copybreak = 100;
+
+#define PKT_BUF_SZ 1536
+#define MAX_MC_CNT 64
+
+#define ISCP_BUSY 0x0001
+
+#define I596_NULL ((u32)0xffffffff)
+
+#define CMD_EOL 0x8000 /* The last command of the list, stop. */
+#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */
+#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */
+
+#define CMD_FLEX 0x0008 /* Enable flexible memory model */
+
+enum commands {
+ CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
+ CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7
+};
+
+#define STAT_C 0x8000 /* Set to 0 after execution */
+#define STAT_B 0x4000 /* Command being executed */
+#define STAT_OK 0x2000 /* Command executed ok */
+#define STAT_A 0x1000 /* Command aborted */
+
+#define CUC_START 0x0100
+#define CUC_RESUME 0x0200
+#define CUC_SUSPEND 0x0300
+#define CUC_ABORT 0x0400
+#define RX_START 0x0010
+#define RX_RESUME 0x0020
+#define RX_SUSPEND 0x0030
+#define RX_ABORT 0x0040
+
+#define TX_TIMEOUT 5
+
+
+struct i596_reg {
+ unsigned short porthi;
+ unsigned short portlo;
+ u32 ca;
+};
+
+#define EOF 0x8000
+#define SIZE_MASK 0x3fff
+
+struct i596_tbd {
+ unsigned short size;
+ unsigned short pad;
+ dma_addr_t next;
+ dma_addr_t data;
+ u32 cache_pad[5]; /* Total 32 bytes... */
+};
+
+/* The command structure has two 'next' pointers; v_next is the address of
+ * the next command as seen by the CPU, b_next is the address of the next
+ * command as seen by the 82596. The b_next pointer, as used by the 82596
+ * always references the status field of the next command, rather than the
+ * v_next field, because the 82596 is unaware of v_next. It may seem more
+ * logical to put v_next at the end of the structure, but we cannot do that
+ * because the 82596 expects other fields to be there, depending on command
+ * type.
+ */
+
+struct i596_cmd {
+ struct i596_cmd *v_next; /* Address from CPUs viewpoint */
+ unsigned short status;
+ unsigned short command;
+ dma_addr_t b_next; /* Address from i596 viewpoint */
+};
+
+struct tx_cmd {
+ struct i596_cmd cmd;
+ dma_addr_t tbd;
+ unsigned short size;
+ unsigned short pad;
+ struct sk_buff *skb; /* So we can free it after tx */
+ dma_addr_t dma_addr;
+#ifdef __LP64__
+ u32 cache_pad[6]; /* Total 64 bytes... */
+#else
+ u32 cache_pad[1]; /* Total 32 bytes... */
+#endif
+};
+
+struct tdr_cmd {
+ struct i596_cmd cmd;
+ unsigned short status;
+ unsigned short pad;
+};
+
+struct mc_cmd {
+ struct i596_cmd cmd;
+ short mc_cnt;
+ char mc_addrs[MAX_MC_CNT*6];
+};
+
+struct sa_cmd {
+ struct i596_cmd cmd;
+ char eth_addr[8];
+};
+
+struct cf_cmd {
+ struct i596_cmd cmd;
+ char i596_config[16];
+};
+
+struct i596_rfd {
+ unsigned short stat;
+ unsigned short cmd;
+ dma_addr_t b_next; /* Address from i596 viewpoint */
+ dma_addr_t rbd;
+ unsigned short count;
+ unsigned short size;
+ struct i596_rfd *v_next; /* Address from CPUs viewpoint */
+ struct i596_rfd *v_prev;
+#ifndef __LP64__
+ u32 cache_pad[2]; /* Total 32 bytes... */
+#endif
+};
+
+struct i596_rbd {
+ /* hardware data */
+ unsigned short count;
+ unsigned short zero1;
+ dma_addr_t b_next;
+ dma_addr_t b_data; /* Address from i596 viewpoint */
+ unsigned short size;
+ unsigned short zero2;
+ /* driver data */
+ struct sk_buff *skb;
+ struct i596_rbd *v_next;
+ dma_addr_t b_addr; /* This rbd addr from i596 view */
+ unsigned char *v_data; /* Address from CPUs viewpoint */
+ /* Total 32 bytes... */
+#ifdef __LP64__
+ u32 cache_pad[4];
+#endif
+};
+
+/* These values as chosen so struct i596_dma fits in one page... */
+
+#define TX_RING_SIZE 32
+#define RX_RING_SIZE 16
+
+struct i596_scb {
+ unsigned short status;
+ unsigned short command;
+ dma_addr_t cmd;
+ dma_addr_t rfd;
+ u32 crc_err;
+ u32 align_err;
+ u32 resource_err;
+ u32 over_err;
+ u32 rcvdt_err;
+ u32 short_err;
+ unsigned short t_on;
+ unsigned short t_off;
+};
+
+struct i596_iscp {
+ u32 stat;
+ dma_addr_t scb;
+};
+
+struct i596_scp {
+ u32 sysbus;
+ u32 pad;
+ dma_addr_t iscp;
+};
+
+struct i596_dma {
+ struct i596_scp scp __attribute__((aligned(32)));
+ volatile struct i596_iscp iscp __attribute__((aligned(32)));
+ volatile struct i596_scb scb __attribute__((aligned(32)));
+ struct sa_cmd sa_cmd __attribute__((aligned(32)));
+ struct cf_cmd cf_cmd __attribute__((aligned(32)));
+ struct tdr_cmd tdr_cmd __attribute__((aligned(32)));
+ struct mc_cmd mc_cmd __attribute__((aligned(32)));
+ struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32)));
+ struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32)));
+ struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32)));
+ struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32)));
+};
+
+struct i596_private {
+ struct i596_dma *dma;
+ u32 stat;
+ int last_restart;
+ struct i596_rfd *rfd_head;
+ struct i596_rbd *rbd_head;
+ struct i596_cmd *cmd_tail;
+ struct i596_cmd *cmd_head;
+ int cmd_backlog;
+ u32 last_cmd;
+ struct net_device_stats stats;
+ int next_tx_cmd;
+ int options;
+ spinlock_t lock; /* serialize access to chip */
+ dma_addr_t dma_addr;
+ void __iomem *mpu_port;
+ void __iomem *ca;
+};
+
+static const char init_setup[] =
+{
+ 0x8E, /* length, prefetch on */
+ 0xC8, /* fifo to 8, monitor off */
+ 0x80, /* don't save bad frames */
+ 0x2E, /* No source address insertion, 8 byte preamble */
+ 0x00, /* priority and backoff defaults */
+ 0x60, /* interframe spacing */
+ 0x00, /* slot time LSB */
+ 0xf2, /* slot time and retries */
+ 0x00, /* promiscuous mode */
+ 0x00, /* collision detect */
+ 0x40, /* minimum frame length */
+ 0xff,
+ 0x00,
+ 0x7f /* *multi IA */ };
+
+static int i596_open(struct net_device *dev);
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static irqreturn_t i596_interrupt(int irq, void *dev_id);
+static int i596_close(struct net_device *dev);
+static struct net_device_stats *i596_get_stats(struct net_device *dev);
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
+static void i596_tx_timeout (struct net_device *dev);
+static void print_eth(unsigned char *buf, char *str);
+static void set_multicast_list(struct net_device *dev);
+static inline void ca(struct net_device *dev);
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x);
+
+static int rx_ring_size = RX_RING_SIZE;
+static int ticks_limit = 100;
+static int max_cmd_backlog = TX_RING_SIZE-1;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev);
+#endif
+
+
+static inline int wait_istat(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+ DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ while (--delcnt && dma->iscp.stat) {
+ udelay(10);
+ DMA_INV(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ }
+ if (!delcnt) {
+ printk(KERN_ERR "%s: %s, iscp.stat %04x, didn't clear\n",
+ dev->name, str, SWAP16(dma->iscp.stat));
+ return -1;
+ } else
+ return 0;
+}
+
+
+static inline int wait_cmd(struct net_device *dev, struct i596_dma *dma, int delcnt, char *str)
+{
+ DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+ while (--delcnt && dma->scb.command) {
+ udelay(10);
+ DMA_INV(dev, &(dma->scb), sizeof(struct i596_scb));
+ }
+ if (!delcnt) {
+ printk(KERN_ERR "%s: %s, status %4.4x, cmd %4.4x.\n",
+ dev->name, str,
+ SWAP16(dma->scb.status),
+ SWAP16(dma->scb.command));
+ return -1;
+ } else
+ return 0;
+}
+
+
+static void i596_display_data(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ struct i596_cmd *cmd;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+
+ printk(KERN_DEBUG "lp and scp at %p, .sysbus = %08x, .iscp = %08x\n",
+ &dma->scp, dma->scp.sysbus, SWAP32(dma->scp.iscp));
+ printk(KERN_DEBUG "iscp at %p, iscp.stat = %08x, .scb = %08x\n",
+ &dma->iscp, SWAP32(dma->iscp.stat), SWAP32(dma->iscp.scb));
+ printk(KERN_DEBUG "scb at %p, scb.status = %04x, .command = %04x,"
+ " .cmd = %08x, .rfd = %08x\n",
+ &dma->scb, SWAP16(dma->scb.status), SWAP16(dma->scb.command),
+ SWAP16(dma->scb.cmd), SWAP32(dma->scb.rfd));
+ printk(KERN_DEBUG " errors: crc %x, align %x, resource %x,"
+ " over %x, rcvdt %x, short %x\n",
+ SWAP32(dma->scb.crc_err), SWAP32(dma->scb.align_err),
+ SWAP32(dma->scb.resource_err), SWAP32(dma->scb.over_err),
+ SWAP32(dma->scb.rcvdt_err), SWAP32(dma->scb.short_err));
+ cmd = lp->cmd_head;
+ while (cmd != NULL) {
+ printk(KERN_DEBUG
+ "cmd at %p, .status = %04x, .command = %04x,"
+ " .b_next = %08x\n",
+ cmd, SWAP16(cmd->status), SWAP16(cmd->command),
+ SWAP32(cmd->b_next));
+ cmd = cmd->v_next;
+ }
+ rfd = lp->rfd_head;
+ printk(KERN_DEBUG "rfd_head = %p\n", rfd);
+ do {
+ printk(KERN_DEBUG
+ " %p .stat %04x, .cmd %04x, b_next %08x, rbd %08x,"
+ " count %04x\n",
+ rfd, SWAP16(rfd->stat), SWAP16(rfd->cmd),
+ SWAP32(rfd->b_next), SWAP32(rfd->rbd),
+ SWAP16(rfd->count));
+ rfd = rfd->v_next;
+ } while (rfd != lp->rfd_head);
+ rbd = lp->rbd_head;
+ printk(KERN_DEBUG "rbd_head = %p\n", rbd);
+ do {
+ printk(KERN_DEBUG
+ " %p .count %04x, b_next %08x, b_data %08x,"
+ " size %04x\n",
+ rbd, SWAP16(rbd->count), SWAP32(rbd->b_next),
+ SWAP32(rbd->b_data), SWAP16(rbd->size));
+ rbd = rbd->v_next;
+ } while (rbd != lp->rbd_head);
+ DMA_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+#define virt_to_dma(lp, v) ((lp)->dma_addr + (dma_addr_t)((unsigned long)(v)-(unsigned long)((lp)->dma)))
+
+static inline int init_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int i;
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+
+ /* First build the Receive Buffer Descriptor List */
+
+ for (i = 0, rbd = dma->rbds; i < rx_ring_size; i++, rbd++) {
+ dma_addr_t dma_addr;
+ struct sk_buff *skb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+
+ if (skb == NULL)
+ return -1;
+ skb_reserve(skb, 2);
+ dma_addr = dma_map_single(dev->dev.parent, skb->data,
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ rbd->v_next = rbd+1;
+ rbd->b_next = SWAP32(virt_to_dma(lp, rbd+1));
+ rbd->b_addr = SWAP32(virt_to_dma(lp, rbd));
+ rbd->skb = skb;
+ rbd->v_data = skb->data;
+ rbd->b_data = SWAP32(dma_addr);
+ rbd->size = SWAP16(PKT_BUF_SZ);
+ }
+ lp->rbd_head = dma->rbds;
+ rbd = dma->rbds + rx_ring_size - 1;
+ rbd->v_next = dma->rbds;
+ rbd->b_next = SWAP32(virt_to_dma(lp, dma->rbds));
+
+ /* Now build the Receive Frame Descriptor List */
+
+ for (i = 0, rfd = dma->rfds; i < rx_ring_size; i++, rfd++) {
+ rfd->rbd = I596_NULL;
+ rfd->v_next = rfd+1;
+ rfd->v_prev = rfd-1;
+ rfd->b_next = SWAP32(virt_to_dma(lp, rfd+1));
+ rfd->cmd = SWAP16(CMD_FLEX);
+ }
+ lp->rfd_head = dma->rfds;
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ rfd = dma->rfds;
+ rfd->rbd = SWAP32(virt_to_dma(lp, lp->rbd_head));
+ rfd->v_prev = dma->rfds + rx_ring_size - 1;
+ rfd = dma->rfds + rx_ring_size - 1;
+ rfd->v_next = dma->rfds;
+ rfd->b_next = SWAP32(virt_to_dma(lp, dma->rfds));
+ rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+ return 0;
+}
+
+static inline void remove_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_rbd *rbd;
+ int i;
+
+ for (i = 0, rbd = lp->dma->rbds; i < rx_ring_size; i++, rbd++) {
+ if (rbd->skb == NULL)
+ break;
+ dma_unmap_single(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ dev_kfree_skb(rbd->skb);
+ }
+}
+
+
+static void rebuild_rx_bufs(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int i;
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+
+ for (i = 0; i < rx_ring_size; i++) {
+ dma->rfds[i].rbd = I596_NULL;
+ dma->rfds[i].cmd = SWAP16(CMD_FLEX);
+ }
+ dma->rfds[rx_ring_size-1].cmd = SWAP16(CMD_EOL|CMD_FLEX);
+ lp->rfd_head = dma->rfds;
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ lp->rbd_head = dma->rbds;
+ dma->rfds[0].rbd = SWAP32(virt_to_dma(lp, dma->rbds));
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+}
+
+
+static int init_i596_mem(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ unsigned long flags;
+
+ mpu_port(dev, PORT_RESET, 0);
+ udelay(100); /* Wait 100us - seems to help */
+
+ /* change the scp address */
+
+ lp->last_cmd = jiffies;
+
+ dma->scp.sysbus = SYSBUS;
+ dma->scp.iscp = SWAP32(virt_to_dma(lp, &(dma->iscp)));
+ dma->iscp.scb = SWAP32(virt_to_dma(lp, &(dma->scb)));
+ dma->iscp.stat = SWAP32(ISCP_BUSY);
+ lp->cmd_backlog = 0;
+
+ lp->cmd_head = NULL;
+ dma->scb.cmd = I596_NULL;
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: starting i82596.\n", dev->name));
+
+ DMA_WBACK(dev, &(dma->scp), sizeof(struct i596_scp));
+ DMA_WBACK(dev, &(dma->iscp), sizeof(struct i596_iscp));
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ mpu_port(dev, PORT_ALTSCP, virt_to_dma(lp, &dma->scp));
+ ca(dev);
+ if (wait_istat(dev, dma, 1000, "initialization timed out"))
+ goto failed;
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: i82596 initialization successful\n",
+ dev->name));
+
+ if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
+ printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
+ goto failed;
+ }
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+ rebuild_rx_bufs(dev);
+
+ dma->scb.command = 0;
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: queuing CmdConfigure\n", dev->name));
+ memcpy(dma->cf_cmd.i596_config, init_setup, 14);
+ dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+ DMA_WBACK(dev, &(dma->cf_cmd), sizeof(struct cf_cmd));
+ i596_add_cmd(dev, &dma->cf_cmd.cmd);
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdSASetup\n", dev->name));
+ memcpy(dma->sa_cmd.eth_addr, dev->dev_addr, 6);
+ dma->sa_cmd.cmd.command = SWAP16(CmdSASetup);
+ DMA_WBACK(dev, &(dma->sa_cmd), sizeof(struct sa_cmd));
+ i596_add_cmd(dev, &dma->sa_cmd.cmd);
+
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: queuing CmdTDR\n", dev->name));
+ dma->tdr_cmd.cmd.command = SWAP16(CmdTDR);
+ DMA_WBACK(dev, &(dma->tdr_cmd), sizeof(struct tdr_cmd));
+ i596_add_cmd(dev, &dma->tdr_cmd.cmd);
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ if (wait_cmd(dev, dma, 1000, "timed out waiting to issue RX_START")) {
+ spin_unlock_irqrestore (&lp->lock, flags);
+ goto failed_free_irq;
+ }
+ DEB(DEB_INIT, printk(KERN_DEBUG "%s: Issuing RX_START\n", dev->name));
+ dma->scb.command = SWAP16(RX_START);
+ dma->scb.rfd = SWAP32(virt_to_dma(lp, dma->rfds));
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+
+ ca(dev);
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+ if (wait_cmd(dev, dma, 1000, "RX_START not processed"))
+ goto failed_free_irq;
+ DEB(DEB_INIT, printk(KERN_DEBUG
+ "%s: Receive unit started OK\n", dev->name));
+ return 0;
+
+failed_free_irq:
+ free_irq(dev->irq, dev);
+failed:
+ printk(KERN_ERR "%s: Failed to initialise 82596\n", dev->name);
+ mpu_port(dev, PORT_RESET, 0);
+ return -1;
+}
+
+
+static inline int i596_rx(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
+ int frames = 0;
+
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG
+ "i596_rx(), rfd_head %p, rbd_head %p\n",
+ lp->rfd_head, lp->rbd_head));
+
+
+ rfd = lp->rfd_head; /* Ref next frame to check */
+
+ DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+ while (rfd->stat & SWAP16(STAT_C)) { /* Loop while complete frames */
+ if (rfd->rbd == I596_NULL)
+ rbd = NULL;
+ else if (rfd->rbd == lp->rbd_head->b_addr) {
+ rbd = lp->rbd_head;
+ DMA_INV(dev, rbd, sizeof(struct i596_rbd));
+ } else {
+ printk(KERN_ERR "%s: rbd chain broken!\n", dev->name);
+ /* XXX Now what? */
+ rbd = NULL;
+ }
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG
+ " rfd %p, rfd.rbd %08x, rfd.stat %04x\n",
+ rfd, rfd->rbd, rfd->stat));
+
+ if (rbd != NULL && (rfd->stat & SWAP16(STAT_OK))) {
+ /* a good frame */
+ int pkt_len = SWAP16(rbd->count) & 0x3fff;
+ struct sk_buff *skb = rbd->skb;
+ int rx_in_place = 0;
+
+ DEB(DEB_RXADDR, print_eth(rbd->v_data, "received"));
+ frames++;
+
+ /* Check if the packet is long enough to just accept
+ * without copying to a properly sized skbuff.
+ */
+
+ if (pkt_len > rx_copybreak) {
+ struct sk_buff *newskb;
+ dma_addr_t dma_addr;
+
+ dma_unmap_single(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ /* Get fresh skbuff to replace filled one. */
+ newskb = netdev_alloc_skb(dev, PKT_BUF_SZ + 4);
+ if (newskb == NULL) {
+ skb = NULL; /* drop pkt */
+ goto memory_squeeze;
+ }
+ skb_reserve(newskb, 2);
+
+ /* Pass up the skb already on the Rx ring. */
+ skb_put(skb, pkt_len);
+ rx_in_place = 1;
+ rbd->skb = newskb;
+ dma_addr = dma_map_single(dev->dev.parent,
+ newskb->data,
+ PKT_BUF_SZ,
+ DMA_FROM_DEVICE);
+ rbd->v_data = newskb->data;
+ rbd->b_data = SWAP32(dma_addr);
+ DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+ } else
+ skb = netdev_alloc_skb(dev, pkt_len + 2);
+memory_squeeze:
+ if (skb == NULL) {
+ /* XXX tulip.c can defer packets here!! */
+ printk(KERN_ERR
+ "%s: i596_rx Memory squeeze, dropping packet.\n",
+ dev->name);
+ lp->stats.rx_dropped++;
+ } else {
+ if (!rx_in_place) {
+ /* 16 byte align the data fields */
+ dma_sync_single_for_cpu(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb, pkt_len), rbd->v_data, pkt_len);
+ dma_sync_single_for_device(dev->dev.parent,
+ (dma_addr_t)SWAP32(rbd->b_data),
+ PKT_BUF_SZ, DMA_FROM_DEVICE);
+ }
+ skb->len = pkt_len;
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ dev->last_rx = jiffies;
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes += pkt_len;
+ }
+ } else {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: Error, rfd.stat = 0x%04x\n",
+ dev->name, rfd->stat));
+ lp->stats.rx_errors++;
+ if (rfd->stat & SWAP16(0x0100))
+ lp->stats.collisions++;
+ if (rfd->stat & SWAP16(0x8000))
+ lp->stats.rx_length_errors++;
+ if (rfd->stat & SWAP16(0x0001))
+ lp->stats.rx_over_errors++;
+ if (rfd->stat & SWAP16(0x0002))
+ lp->stats.rx_fifo_errors++;
+ if (rfd->stat & SWAP16(0x0004))
+ lp->stats.rx_frame_errors++;
+ if (rfd->stat & SWAP16(0x0008))
+ lp->stats.rx_crc_errors++;
+ if (rfd->stat & SWAP16(0x0010))
+ lp->stats.rx_length_errors++;
+ }
+
+ /* Clear the buffer descriptor count and EOF + F flags */
+
+ if (rbd != NULL && (rbd->count & SWAP16(0x4000))) {
+ rbd->count = 0;
+ lp->rbd_head = rbd->v_next;
+ DMA_WBACK_INV(dev, rbd, sizeof(struct i596_rbd));
+ }
+
+ /* Tidy the frame descriptor, marking it as end of list */
+
+ rfd->rbd = I596_NULL;
+ rfd->stat = 0;
+ rfd->cmd = SWAP16(CMD_EOL|CMD_FLEX);
+ rfd->count = 0;
+
+ /* Update record of next frame descriptor to process */
+
+ lp->dma->scb.rfd = rfd->b_next;
+ lp->rfd_head = rfd->v_next;
+ DMA_WBACK_INV(dev, rfd, sizeof(struct i596_rfd));
+
+ /* Remove end-of-list from old end descriptor */
+
+ rfd->v_prev->cmd = SWAP16(CMD_FLEX);
+ DMA_WBACK_INV(dev, rfd->v_prev, sizeof(struct i596_rfd));
+ rfd = lp->rfd_head;
+ DMA_INV(dev, rfd, sizeof(struct i596_rfd));
+ }
+
+ DEB(DEB_RXFRAME, printk(KERN_DEBUG "frames %d\n", frames));
+
+ return 0;
+}
+
+
+static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
+{
+ struct i596_cmd *ptr;
+
+ while (lp->cmd_head != NULL) {
+ ptr = lp->cmd_head;
+ lp->cmd_head = ptr->v_next;
+ lp->cmd_backlog--;
+
+ switch (SWAP16(ptr->command) & 0x7) {
+ case CmdTx:
+ {
+ struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+ struct sk_buff *skb = tx_cmd->skb;
+ dma_unmap_single(dev->dev.parent,
+ tx_cmd->dma_addr,
+ skb->len, DMA_TO_DEVICE);
+
+ dev_kfree_skb(skb);
+
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ tx_cmd->cmd.command = 0; /* Mark as free */
+ break;
+ }
+ default:
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ }
+ DMA_WBACK_INV(dev, ptr, sizeof(struct i596_cmd));
+ }
+
+ wait_cmd(dev, lp->dma, 100, "i596_cleanup_cmd timed out");
+ lp->dma->scb.cmd = I596_NULL;
+ DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+}
+
+
+static inline void i596_reset(struct net_device *dev, struct i596_private *lp)
+{
+ unsigned long flags;
+
+ DEB(DEB_RESET, printk(KERN_DEBUG "i596_reset\n"));
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ wait_cmd(dev, lp->dma, 100, "i596_reset timed out");
+
+ netif_stop_queue(dev);
+
+ /* FIXME: this command might cause an lpmc */
+ lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+ DMA_WBACK(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+ ca(dev);
+
+ /* wait for shutdown */
+ wait_cmd(dev, lp->dma, 1000, "i596_reset 2 timed out");
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ i596_cleanup_cmd(dev, lp);
+ i596_rx(dev);
+
+ netif_start_queue(dev);
+ init_i596_mem(dev);
+}
+
+
+static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ unsigned long flags;
+
+ DEB(DEB_ADDCMD, printk(KERN_DEBUG "i596_add_cmd cmd_head %p\n",
+ lp->cmd_head));
+
+ cmd->status = 0;
+ cmd->command |= SWAP16(CMD_EOL | CMD_INTR);
+ cmd->v_next = NULL;
+ cmd->b_next = I596_NULL;
+ DMA_WBACK(dev, cmd, sizeof(struct i596_cmd));
+
+ spin_lock_irqsave (&lp->lock, flags);
+
+ if (lp->cmd_head != NULL) {
+ lp->cmd_tail->v_next = cmd;
+ lp->cmd_tail->b_next = SWAP32(virt_to_dma(lp, &cmd->status));
+ DMA_WBACK(dev, lp->cmd_tail, sizeof(struct i596_cmd));
+ } else {
+ lp->cmd_head = cmd;
+ wait_cmd(dev, dma, 100, "i596_add_cmd timed out");
+ dma->scb.cmd = SWAP32(virt_to_dma(lp, &cmd->status));
+ dma->scb.command = SWAP16(CUC_START);
+ DMA_WBACK(dev, &(dma->scb), sizeof(struct i596_scb));
+ ca(dev);
+ }
+ lp->cmd_tail = cmd;
+ lp->cmd_backlog++;
+
+ spin_unlock_irqrestore (&lp->lock, flags);
+
+ if (lp->cmd_backlog > max_cmd_backlog) {
+ unsigned long tickssofar = jiffies - lp->last_cmd;
+
+ if (tickssofar < ticks_limit)
+ return;
+
+ printk(KERN_ERR
+ "%s: command unit timed out, status resetting.\n",
+ dev->name);
+#if 1
+ i596_reset(dev, lp);
+#endif
+ }
+}
+
+static int i596_open(struct net_device *dev)
+{
+ DEB(DEB_OPEN, printk(KERN_DEBUG
+ "%s: i596_open() irq %d.\n", dev->name, dev->irq));
+
+ if (init_rx_bufs(dev)) {
+ printk(KERN_ERR "%s: Failed to init rx bufs\n", dev->name);
+ return -EAGAIN;
+ }
+ if (init_i596_mem(dev)) {
+ printk(KERN_ERR "%s: Failed to init memory\n", dev->name);
+ goto out_remove_rx_bufs;
+ }
+ netif_start_queue(dev);
+
+ return 0;
+
+out_remove_rx_bufs:
+ remove_rx_bufs(dev);
+ return -EAGAIN;
+}
+
+static void i596_tx_timeout (struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ /* Transmitter timeout, serious problems. */
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: transmit timed out, status resetting.\n",
+ dev->name));
+
+ lp->stats.tx_errors++;
+
+ /* Try to restart the adaptor */
+ if (lp->last_restart == lp->stats.tx_packets) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG "Resetting board.\n"));
+ /* Shutdown and restart */
+ i596_reset (dev, lp);
+ } else {
+ /* Issue a channel attention signal */
+ DEB(DEB_ERRORS, printk(KERN_DEBUG "Kicking board.\n"));
+ lp->dma->scb.command = SWAP16(CUC_START | RX_START);
+ DMA_WBACK_INV(dev, &(lp->dma->scb), sizeof(struct i596_scb));
+ ca (dev);
+ lp->last_restart = lp->stats.tx_packets;
+ }
+
+ dev->trans_start = jiffies;
+ netif_wake_queue (dev);
+}
+
+
+static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct tx_cmd *tx_cmd;
+ struct i596_tbd *tbd;
+ short length = skb->len;
+ dev->trans_start = jiffies;
+
+ DEB(DEB_STARTTX, printk(KERN_DEBUG
+ "%s: i596_start_xmit(%x,%p) called\n",
+ dev->name, skb->len, skb->data));
+
+ if (length < ETH_ZLEN) {
+ if (skb_padto(skb, ETH_ZLEN))
+ return 0;
+ length = ETH_ZLEN;
+ }
+
+ netif_stop_queue(dev);
+
+ tx_cmd = lp->dma->tx_cmds + lp->next_tx_cmd;
+ tbd = lp->dma->tbds + lp->next_tx_cmd;
+
+ if (tx_cmd->cmd.command) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: xmit ring full, dropping packet.\n",
+ dev->name));
+ lp->stats.tx_dropped++;
+
+ dev_kfree_skb(skb);
+ } else {
+ if (++lp->next_tx_cmd == TX_RING_SIZE)
+ lp->next_tx_cmd = 0;
+ tx_cmd->tbd = SWAP32(virt_to_dma(lp, tbd));
+ tbd->next = I596_NULL;
+
+ tx_cmd->cmd.command = SWAP16(CMD_FLEX | CmdTx);
+ tx_cmd->skb = skb;
+
+ tx_cmd->pad = 0;
+ tx_cmd->size = 0;
+ tbd->pad = 0;
+ tbd->size = SWAP16(EOF | length);
+
+ tx_cmd->dma_addr = dma_map_single(dev->dev.parent, skb->data,
+ skb->len, DMA_TO_DEVICE);
+ tbd->data = SWAP32(tx_cmd->dma_addr);
+
+ DEB(DEB_TXADDR, print_eth(skb->data, "tx-queued"));
+ DMA_WBACK_INV(dev, tx_cmd, sizeof(struct tx_cmd));
+ DMA_WBACK_INV(dev, tbd, sizeof(struct i596_tbd));
+ i596_add_cmd(dev, &tx_cmd->cmd);
+
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += length;
+ }
+
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static void print_eth(unsigned char *add, char *str)
+{
+ int i;
+
+ printk(KERN_DEBUG "i596 0x%p, ", add);
+ for (i = 0; i < 6; i++)
+ printk(" %02X", add[i + 6]);
+ printk(" -->");
+ for (i = 0; i < 6; i++)
+ printk(" %02X", add[i]);
+ printk(" %02X%02X, %s\n", add[12], add[13], str);
+}
+
+static int __devinit i82596_probe(struct net_device *dev)
+{
+ int i;
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma;
+
+ /* This lot is ensure things have been cache line aligned. */
+ BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
+ BUILD_BUG_ON(sizeof(struct i596_rbd) & 31);
+ BUILD_BUG_ON(sizeof(struct tx_cmd) & 31);
+ BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
+#ifndef __LP64__
+ BUILD_BUG_ON(sizeof(struct i596_dma) > 4096);
+#endif
+
+ if (!dev->base_addr || !dev->irq)
+ return -ENODEV;
+
+ dma = (struct i596_dma *) DMA_ALLOC(dev->dev.parent,
+ sizeof(struct i596_dma), &lp->dma_addr, GFP_KERNEL);
+ if (!dma) {
+ printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
+ return -ENOMEM;
+ }
+
+ /* The 82596-specific entries in the device structure. */
+ dev->open = i596_open;
+ dev->stop = i596_close;
+ dev->hard_start_xmit = i596_start_xmit;
+ dev->get_stats = i596_get_stats;
+ dev->set_multicast_list = set_multicast_list;
+ dev->tx_timeout = i596_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = i596_poll_controller;
+#endif
+
+ memset(dma, 0, sizeof(struct i596_dma));
+ lp->dma = dma;
+
+ dma->scb.command = 0;
+ dma->scb.cmd = I596_NULL;
+ dma->scb.rfd = I596_NULL;
+ spin_lock_init(&lp->lock);
+
+ DMA_WBACK_INV(dev, dma, sizeof(struct i596_dma));
+
+ i = register_netdev(dev);
+ if (i) {
+ DMA_FREE(dev->dev.parent, sizeof(struct i596_dma),
+ (void *)dma, lp->dma_addr);
+ return i;
+ };
+
+ DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx,",
+ dev->name, dev->base_addr));
+ for (i = 0; i < 6; i++)
+ DEB(DEB_PROBE, printk(" %2.2X", dev->dev_addr[i]));
+ DEB(DEB_PROBE, printk(" IRQ %d.\n", dev->irq));
+ DEB(DEB_INIT, printk(KERN_INFO
+ "%s: dma at 0x%p (%d bytes), lp->scb at 0x%p\n",
+ dev->name, dma, (int)sizeof(struct i596_dma),
+ &dma->scb));
+
+ return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void i596_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ i596_interrupt(dev->irq, dev);
+ enable_irq(dev->irq);
+}
+#endif
+
+static irqreturn_t i596_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct i596_private *lp;
+ struct i596_dma *dma;
+ unsigned short status, ack_cmd = 0;
+
+ if (dev == NULL) {
+ printk(KERN_WARNING "%s: irq %d for unknown device.\n",
+ __FUNCTION__, irq);
+ return IRQ_NONE;
+ }
+
+ lp = netdev_priv(dev);
+ dma = lp->dma;
+
+ spin_lock (&lp->lock);
+
+ wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+ status = SWAP16(dma->scb.status);
+
+ DEB(DEB_INTS, printk(KERN_DEBUG
+ "%s: i596 interrupt, IRQ %d, status %4.4x.\n",
+ dev->name, irq, status));
+
+ ack_cmd = status & 0xf000;
+
+ if (!ack_cmd) {
+ DEB(DEB_ERRORS, printk(KERN_DEBUG
+ "%s: interrupt with no events\n",
+ dev->name));
+ spin_unlock (&lp->lock);
+ return IRQ_NONE;
+ }
+
+ if ((status & 0x8000) || (status & 0x2000)) {
+ struct i596_cmd *ptr;
+
+ if ((status & 0x8000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt completed command.\n",
+ dev->name));
+ if ((status & 0x2000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt command unit inactive %x.\n",
+ dev->name, status & 0x0700));
+
+ while (lp->cmd_head != NULL) {
+ DMA_INV(dev, lp->cmd_head, sizeof(struct i596_cmd));
+ if (!(lp->cmd_head->status & SWAP16(STAT_C)))
+ break;
+
+ ptr = lp->cmd_head;
+
+ DEB(DEB_STATUS,
+ printk(KERN_DEBUG
+ "cmd_head->status = %04x, ->command = %04x\n",
+ SWAP16(lp->cmd_head->status),
+ SWAP16(lp->cmd_head->command)));
+ lp->cmd_head = ptr->v_next;
+ lp->cmd_backlog--;
+
+ switch (SWAP16(ptr->command) & 0x7) {
+ case CmdTx:
+ {
+ struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+ struct sk_buff *skb = tx_cmd->skb;
+
+ if (ptr->status & SWAP16(STAT_OK)) {
+ DEB(DEB_TXADDR,
+ print_eth(skb->data, "tx-done"));
+ } else {
+ lp->stats.tx_errors++;
+ if (ptr->status & SWAP16(0x0020))
+ lp->stats.collisions++;
+ if (!(ptr->status & SWAP16(0x0040)))
+ lp->stats.tx_heartbeat_errors++;
+ if (ptr->status & SWAP16(0x0400))
+ lp->stats.tx_carrier_errors++;
+ if (ptr->status & SWAP16(0x0800))
+ lp->stats.collisions++;
+ if (ptr->status & SWAP16(0x1000))
+ lp->stats.tx_aborted_errors++;
+ }
+ dma_unmap_single(dev->dev.parent,
+ tx_cmd->dma_addr,
+ skb->len, DMA_TO_DEVICE);
+ dev_kfree_skb_irq(skb);
+
+ tx_cmd->cmd.command = 0; /* Mark free */
+ break;
+ }
+ case CmdTDR:
+ {
+ unsigned short status = SWAP16(((struct tdr_cmd *)ptr)->status);
+
+ if (status & 0x8000) {
+ DEB(DEB_ANY,
+ printk(KERN_DEBUG "%s: link ok.\n",
+ dev->name));
+ } else {
+ if (status & 0x4000)
+ printk(KERN_ERR
+ "%s: Transceiver problem.\n",
+ dev->name);
+ if (status & 0x2000)
+ printk(KERN_ERR
+ "%s: Termination problem.\n",
+ dev->name);
+ if (status & 0x1000)
+ printk(KERN_ERR
+ "%s: Short circuit.\n",
+ dev->name);
+
+ DEB(DEB_TDR,
+ printk(KERN_DEBUG "%s: Time %d.\n",
+ dev->name, status & 0x07ff));
+ }
+ break;
+ }
+ case CmdConfigure:
+ /*
+ * Zap command so set_multicast_list() know
+ * it is free
+ */
+ ptr->command = 0;
+ break;
+ }
+ ptr->v_next = NULL;
+ ptr->b_next = I596_NULL;
+ DMA_WBACK(dev, ptr, sizeof(struct i596_cmd));
+ lp->last_cmd = jiffies;
+ }
+
+ /* This mess is arranging that only the last of any outstanding
+ * commands has the interrupt bit set. Should probably really
+ * only add to the cmd queue when the CU is stopped.
+ */
+ ptr = lp->cmd_head;
+ while ((ptr != NULL) && (ptr != lp->cmd_tail)) {
+ struct i596_cmd *prev = ptr;
+
+ ptr->command &= SWAP16(0x1fff);
+ ptr = ptr->v_next;
+ DMA_WBACK_INV(dev, prev, sizeof(struct i596_cmd));
+ }
+
+ if (lp->cmd_head != NULL)
+ ack_cmd |= CUC_START;
+ dma->scb.cmd = SWAP32(virt_to_dma(lp, &lp->cmd_head->status));
+ DMA_WBACK_INV(dev, &dma->scb, sizeof(struct i596_scb));
+ }
+ if ((status & 0x1000) || (status & 0x4000)) {
+ if ((status & 0x4000))
+ DEB(DEB_INTS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt received a frame.\n",
+ dev->name));
+ i596_rx(dev);
+ /* Only RX_START if stopped - RGH 07-07-96 */
+ if (status & 0x1000) {
+ if (netif_running(dev)) {
+ DEB(DEB_ERRORS,
+ printk(KERN_DEBUG
+ "%s: i596 interrupt receive unit inactive, status 0x%x\n",
+ dev->name, status));
+ ack_cmd |= RX_START;
+ lp->stats.rx_errors++;
+ lp->stats.rx_fifo_errors++;
+ rebuild_rx_bufs(dev);
+ }
+ }
+ }
+ wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
+ dma->scb.command = SWAP16(ack_cmd);
+ DMA_WBACK(dev, &dma->scb, sizeof(struct i596_scb));
+
+ /* DANGER: I suspect that some kind of interrupt
+ acknowledgement aside from acking the 82596 might be needed
+ here... but it's running acceptably without */
+
+ ca(dev);
+
+ wait_cmd(dev, dma, 100, "i596 interrupt, exit timeout");
+ DEB(DEB_INTS, printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name));
+
+ spin_unlock (&lp->lock);
+ return IRQ_HANDLED;
+}
+
+static int i596_close(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+
+ DEB(DEB_INIT,
+ printk(KERN_DEBUG
+ "%s: Shutting down ethercard, status was %4.4x.\n",
+ dev->name, SWAP16(lp->dma->scb.status)));
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ wait_cmd(dev, lp->dma, 100, "close1 timed out");
+ lp->dma->scb.command = SWAP16(CUC_ABORT | RX_ABORT);
+ DMA_WBACK(dev, &lp->dma->scb, sizeof(struct i596_scb));
+
+ ca(dev);
+
+ wait_cmd(dev, lp->dma, 100, "close2 timed out");
+ spin_unlock_irqrestore(&lp->lock, flags);
+ DEB(DEB_STRUCT, i596_display_data(dev));
+ i596_cleanup_cmd(dev, lp);
+
+ free_irq(dev->irq, dev);
+ remove_rx_bufs(dev);
+
+ return 0;
+}
+
+static struct net_device_stats *i596_get_stats(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ return &lp->stats;
+}
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+ struct i596_dma *dma = lp->dma;
+ int config = 0, cnt;
+
+ DEB(DEB_MULTI,
+ printk(KERN_DEBUG
+ "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
+ dev->name, dev->mc_count,
+ dev->flags & IFF_PROMISC ? "ON" : "OFF",
+ dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
+
+ if ((dev->flags & IFF_PROMISC) &&
+ !(dma->cf_cmd.i596_config[8] & 0x01)) {
+ dma->cf_cmd.i596_config[8] |= 0x01;
+ config = 1;
+ }
+ if (!(dev->flags & IFF_PROMISC) &&
+ (dma->cf_cmd.i596_config[8] & 0x01)) {
+ dma->cf_cmd.i596_config[8] &= ~0x01;
+ config = 1;
+ }
+ if ((dev->flags & IFF_ALLMULTI) &&
+ (dma->cf_cmd.i596_config[11] & 0x20)) {
+ dma->cf_cmd.i596_config[11] &= ~0x20;
+ config = 1;
+ }
+ if (!(dev->flags & IFF_ALLMULTI) &&
+ !(dma->cf_cmd.i596_config[11] & 0x20)) {
+ dma->cf_cmd.i596_config[11] |= 0x20;
+ config = 1;
+ }
+ if (config) {
+ if (dma->cf_cmd.cmd.command)
+ printk(KERN_INFO
+ "%s: config change request already queued\n",
+ dev->name);
+ else {
+ dma->cf_cmd.cmd.command = SWAP16(CmdConfigure);
+ DMA_WBACK_INV(dev, &dma->cf_cmd, sizeof(struct cf_cmd));
+ i596_add_cmd(dev, &dma->cf_cmd.cmd);
+ }
+ }
+
+ cnt = dev->mc_count;
+ if (cnt > MAX_MC_CNT) {
+ cnt = MAX_MC_CNT;
+ printk(KERN_NOTICE "%s: Only %d multicast addresses supported",
+ dev->name, cnt);
+ }
+
+ if (dev->mc_count > 0) {
+ struct dev_mc_list *dmi;
+ unsigned char *cp;
+ struct mc_cmd *cmd;
+
+ cmd = &dma->mc_cmd;
+ cmd->cmd.command = SWAP16(CmdMulticastList);
+ cmd->mc_cnt = SWAP16(dev->mc_count * 6);
+ cp = cmd->mc_addrs;
+ for (dmi = dev->mc_list;
+ cnt && dmi != NULL;
+ dmi = dmi->next, cnt--, cp += 6) {
+ memcpy(cp, dmi->dmi_addr, 6);
+ if (i596_debug > 1)
+ DEB(DEB_MULTI,
+ printk(KERN_DEBUG
+ "%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]));
+ }
+ DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd));
+ i596_add_cmd(dev, &cmd->cmd);
+ }
+}
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index fef3193121f..9a343b96597 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -577,7 +577,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
int intr, fs;
- unsigned int flags;
+ unsigned long flags;
/* don't want the dma interrupt handler to fire */
local_irq_save(flags);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
new file mode 100644
index 00000000000..dc74d006e01
--- /dev/null
+++ b/drivers/net/macvlan.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * The code this is based on carried the following copyright notice:
+ * ---
+ * (C) Copyright 2001-2006
+ * Alex Zeffertt, Cambridge Broadband Ltd, ajz@cambridgebroadband.com
+ * Re-worked by Ben Greear <greearb@candelatech.com>
+ * ---
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/notifier.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_arp.h>
+#include <linux/if_link.h>
+#include <linux/if_macvlan.h>
+#include <net/rtnetlink.h>
+
+#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)
+
+struct macvlan_port {
+ struct net_device *dev;
+ struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
+ struct list_head vlans;
+};
+
+struct macvlan_dev {
+ struct net_device *dev;
+ struct list_head list;
+ struct hlist_node hlist;
+ struct macvlan_port *port;
+ struct net_device *lowerdev;
+};
+
+
+static struct macvlan_dev *macvlan_hash_lookup(const struct macvlan_port *port,
+ const unsigned char *addr)
+{
+ struct macvlan_dev *vlan;
+ struct hlist_node *n;
+
+ hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[addr[5]], hlist) {
+ if (!compare_ether_addr(vlan->dev->dev_addr, addr))
+ return vlan;
+ }
+ return NULL;
+}
+
+static void macvlan_broadcast(struct sk_buff *skb,
+ const struct macvlan_port *port)
+{
+ const struct ethhdr *eth = eth_hdr(skb);
+ const struct macvlan_dev *vlan;
+ struct hlist_node *n;
+ struct net_device *dev;
+ struct sk_buff *nskb;
+ unsigned int i;
+
+ for (i = 0; i < MACVLAN_HASH_SIZE; i++) {
+ hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) {
+ dev = vlan->dev;
+ if (unlikely(!(dev->flags & IFF_UP)))
+ continue;
+
+ nskb = skb_clone(skb, GFP_ATOMIC);
+ if (nskb == NULL) {
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
+ continue;
+ }
+
+ dev->stats.rx_bytes += skb->len + ETH_HLEN;
+ dev->stats.rx_packets++;
+ dev->stats.multicast++;
+ dev->last_rx = jiffies;
+
+ nskb->dev = dev;
+ if (!compare_ether_addr(eth->h_dest, dev->broadcast))
+ nskb->pkt_type = PACKET_BROADCAST;
+ else
+ nskb->pkt_type = PACKET_MULTICAST;
+
+ netif_rx(nskb);
+ }
+ }
+}
+
+/* called under rcu_read_lock() from netif_receive_skb */
+static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
+{
+ const struct ethhdr *eth = eth_hdr(skb);
+ const struct macvlan_port *port;
+ const struct macvlan_dev *vlan;
+ struct net_device *dev;
+
+ port = rcu_dereference(skb->dev->macvlan_port);
+ if (port == NULL)
+ return skb;
+
+ if (is_multicast_ether_addr(eth->h_dest)) {
+ macvlan_broadcast(skb, port);
+ return skb;
+ }
+
+ vlan = macvlan_hash_lookup(port, eth->h_dest);
+ if (vlan == NULL)
+ return skb;
+
+ dev = vlan->dev;
+ if (unlikely(!(dev->flags & IFF_UP))) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (skb == NULL) {
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
+ return NULL;
+ }
+
+ dev->stats.rx_bytes += skb->len + ETH_HLEN;
+ dev->stats.rx_packets++;
+ dev->last_rx = jiffies;
+
+ skb->dev = dev;
+ skb->pkt_type = PACKET_HOST;
+
+ netif_rx(skb);
+ return NULL;
+}
+
+static int macvlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ const struct macvlan_dev *vlan = netdev_priv(dev);
+ unsigned int len = skb->len;
+ int ret;
+
+ skb->dev = vlan->lowerdev;
+ ret = dev_queue_xmit(skb);
+
+ if (likely(ret == NET_XMIT_SUCCESS)) {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += len;
+ } else {
+ dev->stats.tx_errors++;
+ dev->stats.tx_aborted_errors++;
+ }
+ return NETDEV_TX_OK;
+}
+
+static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, void *daddr, void *saddr,
+ unsigned len)
+{
+ const struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+
+ return lowerdev->hard_header(skb, lowerdev, type, daddr,
+ saddr ? : dev->dev_addr, len);
+}
+
+static int macvlan_open(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct macvlan_port *port = vlan->port;
+ struct net_device *lowerdev = vlan->lowerdev;
+ int err;
+
+ err = dev_unicast_add(lowerdev, dev->dev_addr, ETH_ALEN);
+ if (err < 0)
+ return err;
+ if (dev->flags & IFF_ALLMULTI)
+ dev_set_allmulti(lowerdev, 1);
+
+ hlist_add_head_rcu(&vlan->hlist, &port->vlan_hash[dev->dev_addr[5]]);
+ return 0;
+}
+
+static int macvlan_stop(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+
+ dev_mc_unsync(lowerdev, dev);
+ if (dev->flags & IFF_ALLMULTI)
+ dev_set_allmulti(lowerdev, -1);
+
+ dev_unicast_delete(lowerdev, dev->dev_addr, ETH_ALEN);
+
+ hlist_del_rcu(&vlan->hlist);
+ synchronize_rcu();
+ return 0;
+}
+
+static void macvlan_change_rx_flags(struct net_device *dev, int change)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+
+ if (change & IFF_ALLMULTI)
+ dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+}
+
+static void macvlan_set_multicast_list(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+
+ dev_mc_sync(vlan->lowerdev, dev);
+}
+
+static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+
+ if (new_mtu < 68 || vlan->lowerdev->mtu < new_mtu)
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+/*
+ * macvlan 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 macvlan_netdev_xmit_lock_key;
+
+#define MACVLAN_FEATURES \
+ (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
+ NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \
+ NETIF_F_TSO_ECN | NETIF_F_TSO6)
+
+#define MACVLAN_STATE_MASK \
+ ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
+
+static int macvlan_init(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ const struct net_device *lowerdev = vlan->lowerdev;
+
+ dev->state = (dev->state & ~MACVLAN_STATE_MASK) |
+ (lowerdev->state & MACVLAN_STATE_MASK);
+ dev->features = lowerdev->features & MACVLAN_FEATURES;
+ dev->iflink = lowerdev->ifindex;
+
+ lockdep_set_class(&dev->_xmit_lock, &macvlan_netdev_xmit_lock_key);
+ return 0;
+}
+
+static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ snprintf(drvinfo->driver, 32, "macvlan");
+ snprintf(drvinfo->version, 32, "0.1");
+}
+
+static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev)
+{
+ const struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+
+ if (lowerdev->ethtool_ops->get_rx_csum == NULL)
+ return 0;
+ return lowerdev->ethtool_ops->get_rx_csum(lowerdev);
+}
+
+static const struct ethtool_ops macvlan_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+ .get_rx_csum = macvlan_ethtool_get_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .get_tso = ethtool_op_get_tso,
+ .get_ufo = ethtool_op_get_ufo,
+ .get_sg = ethtool_op_get_sg,
+ .get_drvinfo = macvlan_ethtool_get_drvinfo,
+};
+
+static void macvlan_setup(struct net_device *dev)
+{
+ ether_setup(dev);
+
+ dev->init = macvlan_init;
+ dev->open = macvlan_open;
+ dev->stop = macvlan_stop;
+ dev->change_mtu = macvlan_change_mtu;
+ dev->change_rx_flags = macvlan_change_rx_flags;
+ dev->set_multicast_list = macvlan_set_multicast_list;
+ dev->hard_header = macvlan_hard_header;
+ dev->hard_start_xmit = macvlan_hard_start_xmit;
+ dev->destructor = free_netdev;
+ dev->ethtool_ops = &macvlan_ethtool_ops;
+ dev->tx_queue_len = 0;
+}
+
+static int macvlan_port_create(struct net_device *dev)
+{
+ struct macvlan_port *port;
+ unsigned int i;
+
+ if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK)
+ return -EINVAL;
+
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ if (port == NULL)
+ return -ENOMEM;
+
+ port->dev = dev;
+ INIT_LIST_HEAD(&port->vlans);
+ for (i = 0; i < MACVLAN_HASH_SIZE; i++)
+ INIT_HLIST_HEAD(&port->vlan_hash[i]);
+ rcu_assign_pointer(dev->macvlan_port, port);
+ return 0;
+}
+
+static void macvlan_port_destroy(struct net_device *dev)
+{
+ struct macvlan_port *port = dev->macvlan_port;
+
+ rcu_assign_pointer(dev->macvlan_port, NULL);
+ synchronize_rcu();
+ kfree(port);
+}
+
+static void macvlan_transfer_operstate(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ const struct net_device *lowerdev = vlan->lowerdev;
+
+ if (lowerdev->operstate == IF_OPER_DORMANT)
+ netif_dormant_on(dev);
+ else
+ netif_dormant_off(dev);
+
+ if (netif_carrier_ok(lowerdev)) {
+ if (!netif_carrier_ok(dev))
+ netif_carrier_on(dev);
+ } else {
+ if (netif_carrier_ok(lowerdev))
+ netif_carrier_off(dev);
+ }
+}
+
+static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+ if (tb[IFLA_ADDRESS]) {
+ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+ return -EINVAL;
+ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+ return -EADDRNOTAVAIL;
+ }
+ return 0;
+}
+
+static int macvlan_newlink(struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct macvlan_port *port;
+ struct net_device *lowerdev;
+ int err;
+
+ if (!tb[IFLA_LINK])
+ return -EINVAL;
+
+ lowerdev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK]));
+ if (lowerdev == NULL)
+ return -ENODEV;
+
+ if (!tb[IFLA_MTU])
+ dev->mtu = lowerdev->mtu;
+ else if (dev->mtu > lowerdev->mtu)
+ return -EINVAL;
+
+ if (!tb[IFLA_ADDRESS])
+ random_ether_addr(dev->dev_addr);
+
+ if (lowerdev->macvlan_port == NULL) {
+ err = macvlan_port_create(lowerdev);
+ if (err < 0)
+ return err;
+ }
+ port = lowerdev->macvlan_port;
+
+ vlan->lowerdev = lowerdev;
+ vlan->dev = dev;
+ vlan->port = port;
+
+ err = register_netdevice(dev);
+ if (err < 0)
+ return err;
+
+ list_add_tail(&vlan->list, &port->vlans);
+ macvlan_transfer_operstate(dev);
+ return 0;
+}
+
+static void macvlan_dellink(struct net_device *dev)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ struct macvlan_port *port = vlan->port;
+
+ list_del(&vlan->list);
+ unregister_netdevice(dev);
+
+ if (list_empty(&port->vlans))
+ macvlan_port_destroy(dev);
+}
+
+static struct rtnl_link_ops macvlan_link_ops __read_mostly = {
+ .kind = "macvlan",
+ .priv_size = sizeof(struct macvlan_dev),
+ .setup = macvlan_setup,
+ .validate = macvlan_validate,
+ .newlink = macvlan_newlink,
+ .dellink = macvlan_dellink,
+};
+
+static int macvlan_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct macvlan_dev *vlan, *next;
+ struct macvlan_port *port;
+
+ port = dev->macvlan_port;
+ if (port == NULL)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_CHANGE:
+ list_for_each_entry(vlan, &port->vlans, list)
+ macvlan_transfer_operstate(vlan->dev);
+ break;
+ case NETDEV_FEAT_CHANGE:
+ list_for_each_entry(vlan, &port->vlans, list) {
+ vlan->dev->features = dev->features & MACVLAN_FEATURES;
+ netdev_features_change(vlan->dev);
+ }
+ break;
+ case NETDEV_UNREGISTER:
+ list_for_each_entry_safe(vlan, next, &port->vlans, list)
+ macvlan_dellink(vlan->dev);
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block macvlan_notifier_block __read_mostly = {
+ .notifier_call = macvlan_device_event,
+};
+
+static int __init macvlan_init_module(void)
+{
+ int err;
+
+ register_netdevice_notifier(&macvlan_notifier_block);
+ macvlan_handle_frame_hook = macvlan_handle_frame;
+
+ err = rtnl_link_register(&macvlan_link_ops);
+ if (err < 0)
+ goto err1;
+ return 0;
+err1:
+ macvlan_handle_frame_hook = macvlan_handle_frame;
+ unregister_netdevice_notifier(&macvlan_notifier_block);
+ return err;
+}
+
+static void __exit macvlan_cleanup_module(void)
+{
+ rtnl_link_unregister(&macvlan_link_ops);
+ macvlan_handle_frame_hook = NULL;
+ unregister_netdevice_notifier(&macvlan_notifier_block);
+}
+
+module_init(macvlan_init_module);
+module_exit(macvlan_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("Driver for MAC address based VLANs");
+MODULE_ALIAS_RTNL_LINK("macvlan");
diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
index 638a279ec50..9853c74f6bb 100644
--- a/drivers/net/mipsnet.c
+++ b/drivers/net/mipsnet.c
@@ -240,7 +240,7 @@ static int __init mipsnet_probe(struct device *dev)
* TODO: probe for these or load them from PARAM
*/
netdev->base_addr = 0x4200;
- netdev->irq = MIPSCPU_INT_BASE + MIPSCPU_INT_MB0 +
+ netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 +
inl(mipsnet_reg_address(netdev, interruptInfo));
// Get the io region now, get irq on open()
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
index 437d78ad091..39253d0c159 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/mlx4/cq.c
@@ -61,7 +61,7 @@ struct mlx4_cq_context {
__be32 solicit_producer_index;
__be32 consumer_index;
__be32 producer_index;
- u8 reserved6[2];
+ u32 reserved6[2];
__be64 db_rec_addr;
};
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index 0f11adb8eb4..27a82cecd69 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -490,9 +490,11 @@ static void mlx4_free_irqs(struct mlx4_dev *dev)
if (eq_table->have_irq)
free_irq(dev->pdev->irq, dev);
- for (i = 0; i < MLX4_NUM_EQ; ++i)
+ for (i = 0; i < MLX4_EQ_CATAS; ++i)
if (eq_table->eq[i].have_irq)
free_irq(eq_table->eq[i].irq, eq_table->eq + i);
+ if (eq_table->eq[MLX4_EQ_CATAS].have_irq)
+ free_irq(eq_table->eq[MLX4_EQ_CATAS].irq, dev);
}
static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev)
diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
index cfa5cc07233..c45cbe43a0c 100644
--- a/drivers/net/mlx4/fw.c
+++ b/drivers/net/mlx4/fw.c
@@ -37,6 +37,12 @@
#include "fw.h"
#include "icm.h"
+enum {
+ MLX4_COMMAND_INTERFACE_MIN_REV = 2,
+ MLX4_COMMAND_INTERFACE_MAX_REV = 3,
+ MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS = 3,
+};
+
extern void __buggy_use_of_MLX4_GET(void);
extern void __buggy_use_of_MLX4_PUT(void);
@@ -103,6 +109,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
u16 size;
u16 stat_rate;
int err;
+ int i;
#define QUERY_DEV_CAP_OUT_SIZE 0x100
#define QUERY_DEV_CAP_MAX_SRQ_SZ_OFFSET 0x10
@@ -131,6 +138,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_ACK_DELAY_OFFSET 0x35
#define QUERY_DEV_CAP_MTU_WIDTH_OFFSET 0x36
#define QUERY_DEV_CAP_VL_PORT_OFFSET 0x37
+#define QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET 0x38
#define QUERY_DEV_CAP_MAX_GID_OFFSET 0x3b
#define QUERY_DEV_CAP_RATE_SUPPORT_OFFSET 0x3c
#define QUERY_DEV_CAP_MAX_PKEY_OFFSET 0x3f
@@ -172,7 +180,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
MLX4_CMD_TIME_CLASS_A);
-
if (err)
goto out;
@@ -212,18 +219,12 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->max_rdma_global = 1 << (field & 0x3f);
MLX4_GET(field, outbox, QUERY_DEV_CAP_ACK_DELAY_OFFSET);
dev_cap->local_ca_ack_delay = field & 0x1f;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
- dev_cap->max_mtu = field >> 4;
- dev_cap->max_port_width = field & 0xf;
MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
- dev_cap->max_vl = field >> 4;
dev_cap->num_ports = field & 0xf;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
- dev_cap->max_gids = 1 << (field & 0xf);
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
+ dev_cap->max_msg_sz = 1 << (field & 0x1f);
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
dev_cap->stat_rate_support = stat_rate;
- MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
- dev_cap->max_pkeys = 1 << (field & 0xf);
MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
dev_cap->reserved_uars = field >> 4;
@@ -300,6 +301,42 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_GET(dev_cap->max_icm_sz, outbox,
QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
+ if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
+ for (i = 1; i <= dev_cap->num_ports; ++i) {
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
+ dev_cap->max_vl[i] = field >> 4;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MTU_WIDTH_OFFSET);
+ dev_cap->max_mtu[i] = field >> 4;
+ dev_cap->max_port_width[i] = field & 0xf;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_GID_OFFSET);
+ dev_cap->max_gids[i] = 1 << (field & 0xf);
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_PKEY_OFFSET);
+ dev_cap->max_pkeys[i] = 1 << (field & 0xf);
+ }
+ } else {
+#define QUERY_PORT_MTU_OFFSET 0x01
+#define QUERY_PORT_WIDTH_OFFSET 0x06
+#define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07
+#define QUERY_PORT_MAX_VL_OFFSET 0x0b
+
+ for (i = 1; i <= dev_cap->num_ports; ++i) {
+ err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT,
+ MLX4_CMD_TIME_CLASS_B);
+ if (err)
+ goto out;
+
+ MLX4_GET(field, outbox, QUERY_PORT_MTU_OFFSET);
+ dev_cap->max_mtu[i] = field & 0xf;
+ MLX4_GET(field, outbox, QUERY_PORT_WIDTH_OFFSET);
+ dev_cap->max_port_width[i] = field & 0xf;
+ MLX4_GET(field, outbox, QUERY_PORT_MAX_GID_PKEY_OFFSET);
+ dev_cap->max_gids[i] = 1 << (field >> 4);
+ dev_cap->max_pkeys[i] = 1 << (field & 0xf);
+ MLX4_GET(field, outbox, QUERY_PORT_MAX_VL_OFFSET);
+ dev_cap->max_vl[i] = field & 0xf;
+ }
+ }
+
if (dev_cap->bmme_flags & 1)
mlx4_dbg(dev, "Base MM extensions: yes "
"(flags %d, rsvd L_Key %08x)\n",
@@ -334,8 +371,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
mlx4_dbg(dev, "Max CQEs: %d, max WQEs: %d, max SRQ WQEs: %d\n",
dev_cap->max_cq_sz, dev_cap->max_qp_sz, dev_cap->max_srq_sz);
mlx4_dbg(dev, "Local CA ACK delay: %d, max MTU: %d, port width cap: %d\n",
- dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu,
- dev_cap->max_port_width);
+ dev_cap->local_ca_ack_delay, 128 << dev_cap->max_mtu[1],
+ dev_cap->max_port_width[1]);
mlx4_dbg(dev, "Max SQ desc size: %d, max SQ S/G: %d\n",
dev_cap->max_sq_desc_sz, dev_cap->max_sq_sg);
mlx4_dbg(dev, "Max RQ desc size: %d, max RQ S/G: %d\n",
@@ -452,10 +489,12 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
u32 *outbox;
int err = 0;
u64 fw_ver;
+ u16 cmd_if_rev;
u8 lg;
#define QUERY_FW_OUT_SIZE 0x100
#define QUERY_FW_VER_OFFSET 0x00
+#define QUERY_FW_CMD_IF_REV_OFFSET 0x0a
#define QUERY_FW_MAX_CMD_OFFSET 0x0f
#define QUERY_FW_ERR_START_OFFSET 0x30
#define QUERY_FW_ERR_SIZE_OFFSET 0x38
@@ -477,21 +516,40 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET);
/*
- * FW subminor version is at more signifant bits than minor
+ * FW subminor version is at more significant bits than minor
* version, so swap here.
*/
dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) |
((fw_ver & 0xffff0000ull) >> 16) |
((fw_ver & 0x0000ffffull) << 16);
+ MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
+ if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV ||
+ cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) {
+ mlx4_err(dev, "Installed FW has unsupported "
+ "command interface revision %d.\n",
+ cmd_if_rev);
+ mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n",
+ (int) (dev->caps.fw_ver >> 32),
+ (int) (dev->caps.fw_ver >> 16) & 0xffff,
+ (int) dev->caps.fw_ver & 0xffff);
+ mlx4_err(dev, "This driver version supports only revisions %d to %d.\n",
+ MLX4_COMMAND_INTERFACE_MIN_REV, MLX4_COMMAND_INTERFACE_MAX_REV);
+ err = -ENODEV;
+ goto out;
+ }
+
+ if (cmd_if_rev < MLX4_COMMAND_INTERFACE_NEW_PORT_CMDS)
+ dev->flags |= MLX4_FLAG_OLD_PORT_CMDS;
+
MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
cmd->max_cmds = 1 << lg;
- mlx4_dbg(dev, "FW version %d.%d.%03d, max commands %d\n",
+ mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n",
(int) (dev->caps.fw_ver >> 32),
(int) (dev->caps.fw_ver >> 16) & 0xffff,
(int) dev->caps.fw_ver & 0xffff,
- cmd->max_cmds);
+ cmd_if_rev, cmd->max_cmds);
MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET);
MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
@@ -687,13 +745,15 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
return err;
}
-int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port)
+int mlx4_INIT_PORT(struct mlx4_dev *dev, int port)
{
struct mlx4_cmd_mailbox *mailbox;
u32 *inbox;
int err;
u32 flags;
+ u16 field;
+ if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
#define INIT_PORT_IN_SIZE 256
#define INIT_PORT_FLAGS_OFFSET 0x00
#define INIT_PORT_FLAG_SIG (1 << 18)
@@ -708,32 +768,32 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int
#define INIT_PORT_NODE_GUID_OFFSET 0x18
#define INIT_PORT_SI_GUID_OFFSET 0x20
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- inbox = mailbox->buf;
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+ inbox = mailbox->buf;
- memset(inbox, 0, INIT_PORT_IN_SIZE);
+ memset(inbox, 0, INIT_PORT_IN_SIZE);
- flags = 0;
- flags |= param->set_guid0 ? INIT_PORT_FLAG_G0 : 0;
- flags |= param->set_node_guid ? INIT_PORT_FLAG_NG : 0;
- flags |= param->set_si_guid ? INIT_PORT_FLAG_SIG : 0;
- flags |= (param->vl_cap & 0xf) << INIT_PORT_VL_SHIFT;
- flags |= (param->port_width_cap & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
- MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET);
+ flags = 0;
+ flags |= (dev->caps.vl_cap[port] & 0xf) << INIT_PORT_VL_SHIFT;
+ flags |= (dev->caps.port_width_cap[port] & 0xf) << INIT_PORT_PORT_WIDTH_SHIFT;
+ MLX4_PUT(inbox, flags, INIT_PORT_FLAGS_OFFSET);
- MLX4_PUT(inbox, param->mtu, INIT_PORT_MTU_OFFSET);
- MLX4_PUT(inbox, param->max_gid, INIT_PORT_MAX_GID_OFFSET);
- MLX4_PUT(inbox, param->max_pkey, INIT_PORT_MAX_PKEY_OFFSET);
- MLX4_PUT(inbox, param->guid0, INIT_PORT_GUID0_OFFSET);
- MLX4_PUT(inbox, param->node_guid, INIT_PORT_NODE_GUID_OFFSET);
- MLX4_PUT(inbox, param->si_guid, INIT_PORT_SI_GUID_OFFSET);
+ field = 128 << dev->caps.mtu_cap[port];
+ MLX4_PUT(inbox, field, INIT_PORT_MTU_OFFSET);
+ field = dev->caps.gid_table_len[port];
+ MLX4_PUT(inbox, field, INIT_PORT_MAX_GID_OFFSET);
+ field = dev->caps.pkey_table_len[port];
+ MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET);
- err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
- MLX4_CMD_TIME_CLASS_A);
+ err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT,
+ MLX4_CMD_TIME_CLASS_A);
- mlx4_free_cmd_mailbox(dev, mailbox);
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ } else
+ err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT,
+ MLX4_CMD_TIME_CLASS_A);
return err;
}
diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
index 2616fa53d4d..7e1dd9e25cf 100644
--- a/drivers/net/mlx4/fw.h
+++ b/drivers/net/mlx4/fw.h
@@ -59,13 +59,14 @@ struct mlx4_dev_cap {
int max_responder_per_qp;
int max_rdma_global;
int local_ca_ack_delay;
- int max_mtu;
- int max_port_width;
- int max_vl;
int num_ports;
- int max_gids;
+ u32 max_msg_sz;
+ int max_mtu[MLX4_MAX_PORTS + 1];
+ int max_port_width[MLX4_MAX_PORTS + 1];
+ int max_vl[MLX4_MAX_PORTS + 1];
+ int max_gids[MLX4_MAX_PORTS + 1];
+ int max_pkeys[MLX4_MAX_PORTS + 1];
u16 stat_rate_support;
- int max_pkeys;
u32 flags;
int reserved_uars;
int uar_size;
diff --git a/drivers/net/mlx4/intf.c b/drivers/net/mlx4/intf.c
index 65854f9e9c7..9ae951bf6aa 100644
--- a/drivers/net/mlx4/intf.c
+++ b/drivers/net/mlx4/intf.c
@@ -135,9 +135,6 @@ int mlx4_register_device(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_interface *intf;
- INIT_LIST_HEAD(&priv->ctx_list);
- spin_lock_init(&priv->ctx_lock);
-
mutex_lock(&intf_mutex);
list_add_tail(&priv->dev_list, &dev_list);
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 20b8c0d3ced..a4f2e0475a7 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -88,6 +88,7 @@ static struct mlx4_profile default_profile = {
static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
{
int err;
+ int i;
err = mlx4_QUERY_DEV_CAP(dev, dev_cap);
if (err) {
@@ -117,11 +118,15 @@ static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev
}
dev->caps.num_ports = dev_cap->num_ports;
+ for (i = 1; i <= dev->caps.num_ports; ++i) {
+ dev->caps.vl_cap[i] = dev_cap->max_vl[i];
+ dev->caps.mtu_cap[i] = dev_cap->max_mtu[i];
+ dev->caps.gid_table_len[i] = dev_cap->max_gids[i];
+ dev->caps.pkey_table_len[i] = dev_cap->max_pkeys[i];
+ dev->caps.port_width_cap[i] = dev_cap->max_port_width[i];
+ }
+
dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE;
- dev->caps.vl_cap = dev_cap->max_vl;
- dev->caps.mtu_cap = dev_cap->max_mtu;
- dev->caps.gid_table_len = dev_cap->max_gids;
- dev->caps.pkey_table_len = dev_cap->max_pkeys;
dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay;
dev->caps.bf_reg_size = dev_cap->bf_reg_size;
dev->caps.bf_regs_per_page = dev_cap->bf_regs_per_page;
@@ -148,8 +153,8 @@ static int __devinit mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev
dev->caps.reserved_mrws = dev_cap->reserved_mrws;
dev->caps.reserved_uars = dev_cap->reserved_uars;
dev->caps.reserved_pds = dev_cap->reserved_pds;
- dev->caps.port_width_cap = dev_cap->max_port_width;
dev->caps.mtt_entry_sz = MLX4_MTT_ENTRY_PER_SEG * dev_cap->mtt_entry_sz;
+ dev->caps.max_msg_sz = dev_cap->max_msg_sz;
dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1);
dev->caps.flags = dev_cap->flags;
dev->caps.stat_rate_support = dev_cap->stat_rate_support;
@@ -787,6 +792,8 @@ static int __devinit mlx4_init_one(struct pci_dev *pdev,
dev = &priv->dev;
dev->pdev = pdev;
+ INIT_LIST_HEAD(&priv->ctx_list);
+ spin_lock_init(&priv->ctx_lock);
/*
* Now reset the HCA before we touch the PCI capabilities or
@@ -905,6 +912,8 @@ static struct pci_device_id mlx4_pci_table[] = {
{ PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */
{ PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */
{ PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */
+ { PCI_VDEVICE(MELLANOX, 0x6732) }, /* MT25408 "Hermon" DDR PCIe gen2 */
+ { PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */
{ 0, }
};
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 3d3b6d24d8d..d9c91a71fc8 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -37,6 +37,7 @@
#ifndef MLX4_H
#define MLX4_H
+#include <linux/mutex.h>
#include <linux/radix-tree.h>
#include <linux/mlx4/device.h>
diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
index b33864dab17..d0808fa3ec8 100644
--- a/drivers/net/mlx4/mr.c
+++ b/drivers/net/mlx4/mr.c
@@ -324,15 +324,17 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
MLX4_MPT_FLAG_MIO |
MLX4_MPT_FLAG_REGION |
mr->access);
- if (mr->mtt.order < 0)
- mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key));
mpt_entry->pd = cpu_to_be32(mr->pd);
mpt_entry->start = cpu_to_be64(mr->iova);
mpt_entry->length = cpu_to_be64(mr->size);
mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
- mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt));
+ if (mr->mtt.order < 0) {
+ mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
+ mpt_entry->mtt_seg = 0;
+ } else
+ mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt));
err = mlx4_SW2HW_MPT(dev, mailbox,
key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1));
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index 7f8b7d55b6e..19b48c71cf7 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -113,8 +113,7 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
struct mlx4_cmd_mailbox *mailbox;
int ret = 0;
- if (cur_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
- new_state < 0 || cur_state >= MLX4_QP_NUM_STATE ||
+ if (cur_state >= MLX4_QP_NUM_STATE || cur_state >= MLX4_QP_NUM_STATE ||
!op[cur_state][new_state])
return -EINVAL;
@@ -278,3 +277,24 @@ void mlx4_cleanup_qp_table(struct mlx4_dev *dev)
mlx4_CONF_SPECIAL_QP(dev, 0);
mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap);
}
+
+int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
+ struct mlx4_qp_context *context)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ err = mlx4_cmd_box(dev, 0, mailbox->dma, qp->qpn, 0,
+ MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A);
+ if (!err)
+ memcpy(context, mailbox->buf + 8, sizeof *context);
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_qp_query);
+
diff --git a/drivers/net/mlx4/srq.c b/drivers/net/mlx4/srq.c
index 2134f83aed8..b061c86d683 100644
--- a/drivers/net/mlx4/srq.c
+++ b/drivers/net/mlx4/srq.c
@@ -102,6 +102,13 @@ static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark)
MLX4_CMD_TIME_CLASS_B);
}
+static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+ int srq_num)
+{
+ return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ,
+ MLX4_CMD_TIME_CLASS_A);
+}
+
int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
u64 db_rec, struct mlx4_srq *srq)
{
@@ -205,6 +212,29 @@ int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark
}
EXPORT_SYMBOL_GPL(mlx4_srq_arm);
+int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_srq_context *srq_context;
+ int err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ srq_context = mailbox->buf;
+
+ err = mlx4_QUERY_SRQ(dev, mailbox, srq->srqn);
+ if (err)
+ goto err_out;
+ *limit_watermark = srq_context->limit_watermark;
+
+err_out:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_srq_query);
+
int __devinit mlx4_init_srq_table(struct mlx4_dev *dev)
{
struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 5d14be7405a..e1732c164a4 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -60,6 +60,7 @@
#include <linux/crc32.h>
#include <linux/moduleparam.h>
#include <linux/io.h>
+#include <linux/log2.h>
#include <net/checksum.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -71,7 +72,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.3.0-1.233"
+#define MYRI10GE_VERSION_STR "1.3.1-1.248"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -279,6 +280,8 @@ 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\n");
+static int myri10ge_reset_recover = 1;
+
static int myri10ge_wcfifo = 0;
module_param(myri10ge_wcfifo, int, S_IRUGO);
MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");
@@ -1154,9 +1157,11 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
struct mcp_irq_data *stats = mgp->fw_stats;
if (unlikely(stats->stats_updated)) {
- if (mgp->link_state != stats->link_up) {
- mgp->link_state = stats->link_up;
- if (mgp->link_state) {
+ unsigned link_up = ntohl(stats->link_up);
+ if (mgp->link_state != link_up) {
+ mgp->link_state = link_up;
+
+ if (mgp->link_state == MXGEFW_LINK_UP) {
if (netif_msg_link(mgp))
printk(KERN_INFO
"myri10ge: %s: link up\n",
@@ -1166,8 +1171,11 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
} else {
if (netif_msg_link(mgp))
printk(KERN_INFO
- "myri10ge: %s: link down\n",
- mgp->dev->name);
+ "myri10ge: %s: link %s\n",
+ mgp->dev->name,
+ (link_up == MXGEFW_LINK_MYRINET ?
+ "mismatch (Myrinet detected)" :
+ "down"));
netif_carrier_off(mgp->dev);
mgp->link_changes++;
}
@@ -1472,6 +1480,7 @@ static const struct ethtool_ops myri10ge_ethtool_ops = {
.set_sg = ethtool_op_set_sg,
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
+ .get_link = ethtool_op_get_link,
.get_strings = myri10ge_get_strings,
.get_stats_count = myri10ge_get_stats_count,
.get_ethtool_stats = myri10ge_get_ethtool_stats,
@@ -1796,7 +1805,7 @@ static int myri10ge_open(struct net_device *dev)
*/
big_pow2 = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
if (big_pow2 < MYRI10GE_ALLOC_SIZE / 2) {
- while ((big_pow2 & (big_pow2 - 1)) != 0)
+ while (!is_power_of_2(big_pow2))
big_pow2++;
mgp->big_bytes = dev->mtu + ETH_HLEN + VLAN_HLEN + MXGEFW_PAD;
} else {
@@ -2729,8 +2738,14 @@ static void myri10ge_watchdog(struct work_struct *work)
* For now, just report it */
reboot = myri10ge_read_reboot(mgp);
printk(KERN_ERR
- "myri10ge: %s: NIC rebooted (0x%x), resetting\n",
- mgp->dev->name, reboot);
+ "myri10ge: %s: NIC rebooted (0x%x),%s resetting\n",
+ mgp->dev->name, reboot,
+ myri10ge_reset_recover ? " " : " not");
+ if (myri10ge_reset_recover == 0)
+ return;
+
+ myri10ge_reset_recover--;
+
/*
* A rebooted nic will come back with config space as
* it was after power was applied to PCIe bus.
@@ -2840,6 +2855,8 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENOMEM;
}
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
mgp = netdev_priv(netdev);
memset(mgp, 0, sizeof(*mgp));
mgp->dev = netdev;
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 4cf0d3fcb51..3450051ae56 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -690,7 +690,7 @@ static ssize_t natsemi_set_dspcfg_workaround(struct device *dev,
{
struct netdev_private *np = netdev_priv(to_net_dev(dev));
int new_setting;
- u32 flags;
+ unsigned long flags;
/* Find out the new setting */
if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
@@ -2357,8 +2357,8 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do)
np->rx_dma[entry],
buflen,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb,
- np->rx_skbuff[entry]->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb,
+ np->rx_skbuff[entry]->data, pkt_len);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(np->pci_dev,
np->rx_dma[entry],
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index ad6688eab26..325269d8ae3 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -68,9 +68,10 @@
#define _NETXEN_NIC_LINUX_SUBVERSION 2
#define NETXEN_NIC_LINUX_VERSIONID "3.4.2"
-#define NUM_FLASH_SECTORS (64)
-#define FLASH_SECTOR_SIZE (64 * 1024)
-#define FLASH_TOTAL_SIZE (NUM_FLASH_SECTORS * FLASH_SECTOR_SIZE)
+#define NETXEN_NUM_FLASH_SECTORS (64)
+#define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
+#define NETXEN_FLASH_TOTAL_SIZE (NETXEN_NUM_FLASH_SECTORS \
+ * NETXEN_FLASH_SECTOR_SIZE)
#define PHAN_VENDOR_ID 0x4040
@@ -677,28 +678,28 @@ struct netxen_new_user_info {
/* Flash memory map */
typedef enum {
- CRBINIT_START = 0, /* Crbinit section */
- BRDCFG_START = 0x4000, /* board config */
- INITCODE_START = 0x6000, /* pegtune code */
- BOOTLD_START = 0x10000, /* bootld */
- IMAGE_START = 0x43000, /* compressed image */
- SECONDARY_START = 0x200000, /* backup images */
- PXE_START = 0x3E0000, /* user defined region */
- USER_START = 0x3E8000, /* User defined region for new boards */
- FIXED_START = 0x3F0000 /* backup of crbinit */
+ NETXEN_CRBINIT_START = 0, /* Crbinit section */
+ NETXEN_BRDCFG_START = 0x4000, /* board config */
+ NETXEN_INITCODE_START = 0x6000, /* pegtune code */
+ NETXEN_BOOTLD_START = 0x10000, /* bootld */
+ NETXEN_IMAGE_START = 0x43000, /* compressed image */
+ NETXEN_SECONDARY_START = 0x200000, /* backup images */
+ NETXEN_PXE_START = 0x3E0000, /* user defined region */
+ NETXEN_USER_START = 0x3E8000, /* User defined region for new boards */
+ NETXEN_FIXED_START = 0x3F0000 /* backup of crbinit */
} netxen_flash_map_t;
-#define USER_START_OLD PXE_START /* for backward compatibility */
-
-#define FLASH_START (CRBINIT_START)
-#define INIT_SECTOR (0)
-#define PRIMARY_START (BOOTLD_START)
-#define FLASH_CRBINIT_SIZE (0x4000)
-#define FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info))
-#define FLASH_USER_SIZE (sizeof(struct netxen_user_info)/sizeof(u32))
-#define FLASH_SECONDARY_SIZE (USER_START-SECONDARY_START)
-#define NUM_PRIMARY_SECTORS (0x20)
-#define NUM_CONFIG_SECTORS (1)
+#define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */
+
+#define NETXEN_FLASH_START (NETXEN_CRBINIT_START)
+#define NETXEN_INIT_SECTOR (0)
+#define NETXEN_PRIMARY_START (NETXEN_BOOTLD_START)
+#define NETXEN_FLASH_CRBINIT_SIZE (0x4000)
+#define NETXEN_FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info))
+#define NETXEN_FLASH_USER_SIZE (sizeof(struct netxen_user_info)/sizeof(u32))
+#define NETXEN_FLASH_SECONDARY_SIZE (NETXEN_USER_START-NETXEN_SECONDARY_START)
+#define NETXEN_NUM_PRIMARY_SECTORS (0x20)
+#define NETXEN_NUM_CONFIG_SECTORS (1)
#define PFX "NetXen: "
extern char netxen_nic_driver_name[];
@@ -936,6 +937,7 @@ struct netxen_adapter {
struct netxen_ring_ctx *ctx_desc;
struct pci_dev *ctx_desc_pdev;
dma_addr_t ctx_desc_phys_addr;
+ int intr_scheme;
int (*enable_phy_interrupts) (struct netxen_adapter *);
int (*disable_phy_interrupts) (struct netxen_adapter *);
void (*handle_phy_intr) (struct netxen_adapter *);
@@ -950,6 +952,24 @@ struct netxen_adapter {
int (*stop_port) (struct netxen_adapter *);
}; /* netxen_adapter structure */
+/*
+ * NetXen dma watchdog control structure
+ *
+ * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive
+ * Bit 1 : disable_request => 1 req disable dma watchdog
+ * Bit 2 : enable_request => 1 req enable dma watchdog
+ * Bit 3-31 : unused
+ */
+
+#define netxen_set_dma_watchdog_disable_req(config_word) \
+ _netxen_set_bits(config_word, 1, 1, 1)
+#define netxen_set_dma_watchdog_enable_req(config_word) \
+ _netxen_set_bits(config_word, 2, 1, 1)
+#define netxen_get_dma_watchdog_enabled(config_word) \
+ ((config_word) & 0x1)
+#define netxen_get_dma_watchdog_disabled(config_word) \
+ (((config_word) >> 1) & 0x1)
+
/* Max number of xmit producer threads that can run simultaneously */
#define MAX_XMIT_PRODUCERS 16
@@ -1029,8 +1049,8 @@ int netxen_nic_erase_pxe(struct netxen_adapter *adapter);
/* Functions from netxen_nic_init.c */
void netxen_free_adapter_offload(struct netxen_adapter *adapter);
int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
-void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
-void netxen_load_firmware(struct netxen_adapter *adapter);
+int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
+int netxen_load_firmware(struct netxen_adapter *adapter);
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
@@ -1048,6 +1068,7 @@ int netxen_rom_se(struct netxen_adapter *adapter, int addr);
int netxen_do_rom_se(struct netxen_adapter *adapter, int addr);
/* Functions from netxen_nic_isr.c */
+int netxen_nic_link_ok(struct netxen_adapter *adapter);
void netxen_nic_isr_other(struct netxen_adapter *adapter);
void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 link);
void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable);
@@ -1076,40 +1097,6 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
int netxen_nic_set_mac(struct net_device *netdev, void *p);
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
-static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
-{
- /*
- * ISR_INT_MASK: Can be read from window 0 or 1.
- */
- writel(0x7ff, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
-
-}
-
-static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
-{
- u32 mask;
-
- switch (adapter->ahw.board_type) {
- case NETXEN_NIC_GBE:
- mask = 0x77b;
- break;
- case NETXEN_NIC_XGBE:
- mask = 0x77f;
- break;
- default:
- mask = 0x7ff;
- break;
- }
-
- writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
-
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
- mask = 0xbff;
- writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
- writel(mask, PCI_OFFSET_SECOND_RANGE(adapter,
- ISR_INT_TARGET_MASK));
- }
-}
/*
* NetXen Board information
@@ -1162,6 +1149,62 @@ static inline void get_brd_name_by_type(u32 type, char *name)
name = "Unknown";
}
+static inline int
+dma_watchdog_shutdown_request(struct netxen_adapter *adapter)
+{
+ u32 ctrl;
+
+ /* check if already inactive */
+ if (netxen_nic_hw_read_wx(adapter,
+ NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
+ printk(KERN_ERR "failed to read dma watchdog status\n");
+
+ if (netxen_get_dma_watchdog_enabled(ctrl) == 0)
+ return 1;
+
+ /* Send the disable request */
+ netxen_set_dma_watchdog_disable_req(ctrl);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
+
+ return 0;
+}
+
+static inline int
+dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter)
+{
+ u32 ctrl;
+
+ if (netxen_nic_hw_read_wx(adapter,
+ NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
+ printk(KERN_ERR "failed to read dma watchdog status\n");
+
+ return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) &&
+ (netxen_get_dma_watchdog_disabled(ctrl) == 0));
+}
+
+static inline int
+dma_watchdog_wakeup(struct netxen_adapter *adapter)
+{
+ u32 ctrl;
+
+ if (netxen_nic_hw_read_wx(adapter,
+ NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
+ printk(KERN_ERR "failed to read dma watchdog status\n");
+
+ if (netxen_get_dma_watchdog_enabled(ctrl))
+ return 1;
+
+ /* send the wakeup request */
+ netxen_set_dma_watchdog_enable_req(ctrl);
+
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl);
+
+ return 0;
+}
+
+
int netxen_is_flash_supported(struct netxen_adapter *adapter);
int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]);
extern void netxen_change_ringparam(struct netxen_adapter *adapter);
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 16fabb37748..0175f6c353f 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -94,7 +94,7 @@ static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
static int netxen_nic_get_eeprom_len(struct net_device *dev)
{
- return FLASH_TOTAL_SIZE;
+ return NETXEN_FLASH_TOTAL_SIZE;
}
static void
@@ -470,7 +470,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return 0;
}
- if (offset == BOOTLD_START) {
+ if (offset == NETXEN_BOOTLD_START) {
ret = netxen_flash_erase_primary(adapter);
if (ret != FLASH_SUCCESS) {
printk(KERN_ERR "%s: Flash erase failed.\n",
@@ -478,10 +478,10 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return ret;
}
- ret = netxen_rom_se(adapter, USER_START);
+ ret = netxen_rom_se(adapter, NETXEN_USER_START);
if (ret != FLASH_SUCCESS)
return ret;
- ret = netxen_rom_se(adapter, FIXED_START);
+ ret = netxen_rom_se(adapter, NETXEN_FIXED_START);
if (ret != FLASH_SUCCESS)
return ret;
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 608e37b349b..3276866b17e 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -687,4 +687,6 @@ enum {
#define PCIE_MAX_MASTER_SPLIT (0x14048)
+#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14)
+
#endif /* __NETXEN_NIC_HDR_H_ */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index baff17a24d6..aac15421bd1 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -257,7 +257,7 @@ u64 ctx_addr_sig_regs[][3] = {
#define ADDR_IN_RANGE(addr, low, high) \
(((addr) <= (high)) && ((addr) >= (low)))
-#define NETXEN_FLASH_BASE (BOOTLD_START)
+#define NETXEN_FLASH_BASE (NETXEN_BOOTLD_START)
#define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE)
#define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
#define NETXEN_MIN_MTU 64
@@ -377,7 +377,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
recv_crb_registers[ctx].
crb_rcvpeg_state));
while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
- udelay(100);
+ msleep(1);
/* Window 1 call */
state = readl(NETXEN_CRB_NORMALIZE(adapter,
recv_crb_registers
@@ -392,7 +392,11 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
return err;
}
}
- DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n");
+ adapter->intr_scheme = readl(
+ NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
+ printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name,
+ adapter->intr_scheme);
+ DPRINTK(INFO, "Receive Peg ready too. starting stuff\n");
addr = netxen_alloc(adapter->ahw.pdev,
sizeof(struct netxen_ring_ctx) +
@@ -611,7 +615,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
u32 *pmac = (u32 *) & mac[0];
if (netxen_get_flash_block(adapter,
- USER_START +
+ NETXEN_USER_START +
offsetof(struct netxen_new_user_info,
mac_addr),
FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) {
@@ -619,7 +623,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[])
}
if (*mac == ~0ULL) {
if (netxen_get_flash_block(adapter,
- USER_START_OLD +
+ NETXEN_USER_START_OLD +
offsetof(struct netxen_user_old_info,
mac_addr),
FLASH_NUM_PORTS * sizeof(u64),
@@ -697,7 +701,7 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
adapter->curr_window = 0;
}
-void netxen_load_firmware(struct netxen_adapter *adapter)
+int netxen_load_firmware(struct netxen_adapter *adapter)
{
int i;
u32 data, size = 0;
@@ -709,15 +713,24 @@ void netxen_load_firmware(struct netxen_adapter *adapter)
writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
for (i = 0; i < size; i++) {
- if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) {
- DPRINTK(ERR,
- "Error in netxen_rom_fast_read(). Will skip"
- "loading flash image\n");
- return;
- }
+ int retries = 10;
+ if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
+ return -EIO;
+
off = netxen_nic_pci_set_window(adapter, memaddr);
addr = pci_base_offset(adapter, off);
writel(data, addr);
+ do {
+ if (readl(addr) == data)
+ break;
+ msleep(100);
+ writel(data, addr);
+ } while (--retries);
+ if (!retries) {
+ printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n",
+ netxen_nic_driver_name, memaddr);
+ return -EIO;
+ }
flashaddr += 4;
memaddr += 4;
}
@@ -727,7 +740,7 @@ void netxen_load_firmware(struct netxen_adapter *adapter)
NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
- udelay(100);
+ return 0;
}
int
@@ -942,7 +955,7 @@ netxen_nic_pci_set_window(struct netxen_adapter *adapter,
int
netxen_nic_erase_pxe(struct netxen_adapter *adapter)
{
- if (netxen_rom_fast_write(adapter, PXE_START, 0) == -1) {
+ if (netxen_rom_fast_write(adapter, NETXEN_PXE_START, 0) == -1) {
printk(KERN_ERR "%s: erase pxe failed\n",
netxen_nic_driver_name);
return -1;
@@ -953,7 +966,7 @@ netxen_nic_erase_pxe(struct netxen_adapter *adapter)
int netxen_nic_get_board_info(struct netxen_adapter *adapter)
{
int rv = 0;
- int addr = BRDCFG_START;
+ int addr = NETXEN_BRDCFG_START;
struct netxen_board_info *boardinfo;
int index;
u32 *ptr32;
@@ -1115,7 +1128,7 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
u32 fw_build = 0;
char brd_name[NETXEN_MAX_SHORT_NAME];
struct netxen_new_user_info user_info;
- int i, addr = USER_START;
+ int i, addr = NETXEN_USER_START;
__le32 *ptr32;
struct netxen_board_info *board_info = &(adapter->ahw.boardcfg);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index a3689245776..1811bcb8c38 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -139,6 +139,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
return err;
}
/* Window 1 call */
+ writel(INTR_SCHEME_PERPORT,
+ NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST));
writel(MPORT_MULTI_FUNCTION_MODE,
NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
writel(PHAN_INITIALIZE_ACK,
@@ -405,10 +407,7 @@ static inline int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
static inline int
do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp)
{
- if (jiffies > (last_schedule_time + (8 * HZ))) {
- last_schedule_time = jiffies;
- schedule();
- }
+ cond_resched();
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr);
netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3);
@@ -585,7 +584,7 @@ int netxen_backup_crbinit(struct netxen_adapter *adapter)
{
int ret = FLASH_SUCCESS;
int val;
- char *buffer = kmalloc(FLASH_SECTOR_SIZE, GFP_KERNEL);
+ char *buffer = kmalloc(NETXEN_FLASH_SECTOR_SIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
@@ -601,13 +600,13 @@ int netxen_backup_crbinit(struct netxen_adapter *adapter)
goto out_kfree;
/* copy sector 0 to sector 63 */
- ret = netxen_rom_fast_read_words(adapter, CRBINIT_START,
- buffer, FLASH_SECTOR_SIZE);
+ ret = netxen_rom_fast_read_words(adapter, NETXEN_CRBINIT_START,
+ buffer, NETXEN_FLASH_SECTOR_SIZE);
if (ret != FLASH_SUCCESS)
goto out_kfree;
- ret = netxen_rom_fast_write_words(adapter, FIXED_START,
- buffer, FLASH_SECTOR_SIZE);
+ ret = netxen_rom_fast_write_words(adapter, NETXEN_FIXED_START,
+ buffer, NETXEN_FLASH_SECTOR_SIZE);
if (ret != FLASH_SUCCESS)
goto out_kfree;
@@ -654,7 +653,8 @@ void check_erased_flash(struct netxen_adapter *adapter, int addr)
int count = 0, erased_errors = 0;
int range;
- range = (addr == USER_START) ? FIXED_START : addr + FLASH_SECTOR_SIZE;
+ range = (addr == NETXEN_USER_START) ?
+ NETXEN_FIXED_START : addr + NETXEN_FLASH_SECTOR_SIZE;
for (i = addr; i < range; i += 4) {
netxen_rom_fast_read(adapter, i, &val);
@@ -689,7 +689,7 @@ netxen_flash_erase_sections(struct netxen_adapter *adapter, int start, int end)
int i;
for (i = start; i < end; i++) {
- ret = netxen_rom_se(adapter, i * FLASH_SECTOR_SIZE);
+ ret = netxen_rom_se(adapter, i * NETXEN_FLASH_SECTOR_SIZE);
if (ret)
break;
ret = netxen_rom_wip_poll(adapter);
@@ -706,8 +706,8 @@ netxen_flash_erase_secondary(struct netxen_adapter *adapter)
int ret = FLASH_SUCCESS;
int start, end;
- start = SECONDARY_START / FLASH_SECTOR_SIZE;
- end = USER_START / FLASH_SECTOR_SIZE;
+ start = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE;
+ end = NETXEN_USER_START / NETXEN_FLASH_SECTOR_SIZE;
ret = netxen_flash_erase_sections(adapter, start, end);
return ret;
@@ -719,8 +719,8 @@ netxen_flash_erase_primary(struct netxen_adapter *adapter)
int ret = FLASH_SUCCESS;
int start, end;
- start = PRIMARY_START / FLASH_SECTOR_SIZE;
- end = SECONDARY_START / FLASH_SECTOR_SIZE;
+ start = NETXEN_PRIMARY_START / NETXEN_FLASH_SECTOR_SIZE;
+ end = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE;
ret = netxen_flash_erase_sections(adapter, start, end);
return ret;
@@ -853,10 +853,10 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
netxen_nic_pci_change_crbwindow(adapter, 1);
}
if (init_delay == 1) {
- ssleep(1);
+ msleep(2000);
init_delay = 0;
}
- msleep(1);
+ msleep(20);
}
kfree(buf);
@@ -932,10 +932,6 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
void netxen_free_adapter_offload(struct netxen_adapter *adapter)
{
if (adapter->dummy_dma.addr) {
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- CRB_HOST_DUMMY_BUF_ADDR_HI));
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- CRB_HOST_DUMMY_BUF_ADDR_LO));
pci_free_consistent(adapter->ahw.pdev,
NETXEN_HOST_DUMMY_DMA_SIZE,
adapter->dummy_dma.addr,
@@ -944,25 +940,32 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
}
}
-void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
+int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
{
u32 val = 0;
- int loops = 0;
+ int retries = 30;
if (!pegtune_val) {
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
- while (val != PHAN_INITIALIZE_COMPLETE &&
- val != PHAN_INITIALIZE_ACK && loops < 200000) {
- udelay(100);
- schedule();
- val =
- readl(NETXEN_CRB_NORMALIZE
+ do {
+ val = readl(NETXEN_CRB_NORMALIZE
(adapter, CRB_CMDPEG_STATE));
- loops++;
+ pegtune_val = readl(NETXEN_CRB_NORMALIZE
+ (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+
+ if (val == PHAN_INITIALIZE_COMPLETE ||
+ val == PHAN_INITIALIZE_ACK)
+ return 0;
+
+ msleep(1000);
+ } while (--retries);
+ if (!retries) {
+ printk(KERN_WARNING "netxen_phantom_init: init failed, "
+ "pegtune_val=%x\n", pegtune_val);
+ return -1;
}
- if (val != PHAN_INITIALIZE_COMPLETE)
- printk("WARNING: Initial boot wait loop failed...\n");
}
+
+ return 0;
}
int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
@@ -1036,18 +1039,23 @@ void netxen_watchdog_task(struct work_struct *work)
if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter))
return;
+ if (adapter->handle_phy_intr)
+ adapter->handle_phy_intr(adapter);
+
netdev = adapter->netdev;
- if ((netif_running(netdev)) && !netif_carrier_ok(netdev)) {
- printk(KERN_INFO "%s port %d, %s carrier is now ok\n",
- netxen_nic_driver_name, adapter->portnum, netdev->name);
+ if ((netif_running(netdev)) && !netif_carrier_ok(netdev) &&
+ netxen_nic_link_ok(adapter) ) {
+ printk(KERN_INFO "%s %s (port %d), Link is up\n",
+ netxen_nic_driver_name, netdev->name, adapter->portnum);
netif_carrier_on(netdev);
- }
-
- if (netif_queue_stopped(netdev))
netif_wake_queue(netdev);
+ } else if(!(netif_running(netdev)) && netif_carrier_ok(netdev)) {
+ printk(KERN_ERR "%s %s Link is Down\n",
+ netxen_nic_driver_name, netdev->name);
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
- if (adapter->handle_phy_intr)
- adapter->handle_phy_intr(adapter);
mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
}
@@ -1114,6 +1122,7 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
adapter->stats.csummed++;
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
+ skb->dev = netdev;
if (desc_ctx == RCV_DESC_LRO_CTXID) {
/* True length was only available on the last pkt */
skb_put(skb, buffer->lro_length);
@@ -1218,6 +1227,7 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
NETXEN_CRB_NORMALIZE(adapter,
recv_crb_registers[adapter->portnum].
crb_rcv_status_consumer));
+ wmb();
}
return count;
@@ -1270,11 +1280,13 @@ int netxen_process_cmd_ring(unsigned long data)
if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) {
pci_unmap_single(pdev, frag->dma, frag->length,
PCI_DMA_TODEVICE);
+ frag->dma = 0ULL;
for (i = 1; i < buffer->frag_count; i++) {
DPRINTK(INFO, "getting fragment no %d\n", i);
frag++; /* Get the next frag */
pci_unmap_page(pdev, frag->dma, frag->length,
PCI_DMA_TODEVICE);
+ frag->dma = 0ULL;
}
adapter->stats.skbfreed++;
@@ -1440,6 +1452,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
writel(msg,
DB_NORMALIZE(adapter,
NETXEN_RCV_PRODUCER_OFFSET));
+ wmb();
}
}
}
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
index b213b062eb5..b2de6b6c2a7 100644
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ b/drivers/net/netxen/netxen_nic_isr.c
@@ -169,6 +169,24 @@ void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
netxen_nic_isr_other(adapter);
}
+int netxen_nic_link_ok(struct netxen_adapter *adapter)
+{
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ return ((adapter->ahw.qg_linksup) & 1);
+
+ case NETXEN_NIC_XGBE:
+ return ((adapter->ahw.xg_linkup) & 1);
+
+ default:
+ printk(KERN_ERR"%s: Function: %s, Unknown board type\n",
+ netxen_nic_driver_name, __FUNCTION__);
+ break;
+ }
+
+ return 0;
+}
+
void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -183,6 +201,10 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
printk(KERN_INFO "%s: %s NIC Link is down\n",
netxen_nic_driver_name, netdev->name);
adapter->ahw.xg_linkup = 0;
+ if (netif_running(netdev)) {
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
/* read twice to clear sticky bits */
/* WINDOW = 0 */
netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1);
@@ -196,5 +218,7 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
printk(KERN_INFO "%s: %s NIC Link is up\n",
netxen_nic_driver_name, netdev->name);
adapter->ahw.xg_linkup = 1;
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
}
}
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 2c5c6d20e6e..b703ccfe040 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -54,8 +54,6 @@ static char netxen_nic_driver_string[] = "NetXen Network Driver version "
#define NETXEN_ADAPTER_UP_MAGIC 777
#define NETXEN_NIC_PEG_TUNE 0
-u8 nx_p2_id = NX_P2_C0;
-
#define DMA_32BIT_MASK 0x00000000ffffffffULL
#define DMA_35BIT_MASK 0x00000007ffffffffULL
@@ -156,6 +154,103 @@ static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter
#define ADAPTER_LIST_SIZE 12
int netxen_cards_found;
+static void netxen_nic_disable_int(struct netxen_adapter *adapter)
+{
+ uint32_t mask = 0x7ff;
+ int retries = 32;
+
+ DPRINTK(1, INFO, "Entered ISR Disable \n");
+
+ switch (adapter->portnum) {
+ case 0:
+ writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+ break;
+ case 1:
+ writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+ break;
+ case 2:
+ writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+ break;
+ case 3:
+ writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+ break;
+ }
+
+ if (adapter->intr_scheme != -1 &&
+ adapter->intr_scheme != INTR_SCHEME_PERPORT)
+ writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+
+ /* Window = 0 or 1 */
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ do {
+ writel(0xffffffff,
+ PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS));
+ mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+ if (!(mask & 0x80))
+ break;
+ udelay(10);
+ } while (--retries);
+
+ if (!retries) {
+ printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
+ netxen_nic_driver_name);
+ }
+ }
+
+ DPRINTK(1, INFO, "Done with Disable Int\n");
+}
+
+static void netxen_nic_enable_int(struct netxen_adapter *adapter)
+{
+ u32 mask;
+
+ DPRINTK(1, INFO, "Entered ISR Enable \n");
+
+ if (adapter->intr_scheme != -1 &&
+ adapter->intr_scheme != INTR_SCHEME_PERPORT) {
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ mask = 0x77b;
+ break;
+ case NETXEN_NIC_XGBE:
+ mask = 0x77f;
+ break;
+ default:
+ mask = 0x7ff;
+ break;
+ }
+
+ writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ }
+
+ switch (adapter->portnum) {
+ case 0:
+ writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+ break;
+ case 1:
+ writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+ break;
+ case 2:
+ writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+ break;
+ case 3:
+ writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+ break;
+ }
+
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ mask = 0xbff;
+ if (adapter->intr_scheme != -1 &&
+ adapter->intr_scheme != INTR_SCHEME_PERPORT) {
+ writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ }
+ writel(mask,
+ PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK));
+ }
+
+ DPRINTK(1, INFO, "Done with enable Int\n");
+}
+
/*
* netxen_nic_probe()
*
@@ -210,8 +305,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_disable_pdev;
pci_set_master(pdev);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &nx_p2_id);
- if (nx_p2_id == NX_P2_C1 &&
+ if (pdev->revision == NX_P2_C1 &&
(pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
(pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
pci_using_dac = 1;
@@ -308,7 +402,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->netdev = netdev;
adapter->pdev = pdev;
+
+ /* this will be read from FW later */
+ adapter->intr_scheme = -1;
+
+ /* This will be reset for mezz cards */
adapter->portnum = pci_func_id;
+ adapter->status &= ~NETXEN_NETDEV_STATUS;
netdev->open = netxen_nic_open;
netdev->stop = netxen_nic_close;
@@ -336,11 +436,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
- if (pci_enable_msi(pdev)) {
+ if (pci_enable_msi(pdev))
adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
- printk(KERN_WARNING "%s: unable to allocate MSI interrupt"
- " error\n", netxen_nic_driver_name);
- } else
+ else
adapter->flags |= NETXEN_NIC_MSI_ENABLED;
netdev->irq = pdev->irq;
@@ -355,13 +453,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* initialize the adapter */
netxen_initialize_adapter_hw(adapter);
-#ifdef CONFIG_PPC
- if ((adapter->ahw.boardcfg.board_type ==
- NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) &&
- (pci_func_id == 2))
- goto err_out_free_adapter;
-#endif /* CONFIG_PPC */
-
/*
* Adapter in our case is quad port so initialize it before
* initializing the ports
@@ -458,7 +549,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
adapter->ahw.pdev = pdev;
adapter->proc_cmd_buf_counter = 0;
- adapter->ahw.revision_id = nx_p2_id;
+ adapter->ahw.revision_id = pdev->revision;
/* make sure Window == 1 */
netxen_nic_pci_change_crbwindow(adapter, 1);
@@ -509,22 +600,30 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
NETXEN_CAM_RAM(0x1fc)));
if (val == 0x55555555) {
/* This is the first boot after power up */
+ netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
+ if (!(val & 0x4)) {
+ val |= 0x4;
+ netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val);
+ netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
+ if (!(val & 0x4))
+ printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n",
+ netxen_nic_driver_name);
+ }
val = readl(NETXEN_CRB_NORMALIZE(adapter,
NETXEN_ROMUSB_GLB_SW_RESET));
printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val);
if (val != 0x80000f) {
/* clear the register for future unloads/loads */
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_CAM_RAM(0x1fc)));
- printk(KERN_ERR "ERROR in NetXen HW init sequence.\n");
- err = -ENODEV;
- goto err_out_free_dev;
+ writel(0, NETXEN_CRB_NORMALIZE(adapter,
+ NETXEN_CAM_RAM(0x1fc)));
+ printk(KERN_ERR "ERROR in NetXen HW init sequence.\n");
+ err = -ENODEV;
+ goto err_out_free_dev;
}
-
- /* clear the register for future unloads/loads */
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_CAM_RAM(0x1fc)));
}
+
+ /* clear the register for future unloads/loads */
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
printk(KERN_INFO "State: 0x%0x\n",
readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
@@ -632,8 +731,8 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
struct netxen_rx_buffer *buffer;
struct netxen_recv_context *recv_ctx;
struct netxen_rcv_desc_ctx *rcv_desc;
- int i;
- int ctxid, ring;
+ int i, ctxid, ring;
+ static int init_firmware_done = 0;
adapter = pci_get_drvdata(pdev);
if (adapter == NULL)
@@ -641,32 +740,20 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
netdev = adapter->netdev;
- netxen_nic_disable_int(adapter);
- if (adapter->irq)
- free_irq(adapter->irq, adapter);
-
+ unregister_netdev(netdev);
+
if (adapter->stop_port)
adapter->stop_port(adapter);
- if ((adapter->flags & NETXEN_NIC_MSI_ENABLED))
- pci_disable_msi(pdev);
-
- if (adapter->portnum == 0)
- netxen_free_adapter_offload(adapter);
+ netxen_nic_disable_int(adapter);
if (adapter->irq)
free_irq(adapter->irq, adapter);
- if(adapter->portnum == 0) {
- /* leave the hw in the same state as reboot */
- writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
- netxen_pinit_from_rom(adapter, 0);
- udelay(500);
- netxen_load_firmware(adapter);
- netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
- }
- if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
+ if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+ init_firmware_done++;
netxen_free_hw_resources(adapter);
+ }
for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
recv_ctx = &adapter->recv_ctx[ctxid];
@@ -686,17 +773,73 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
}
}
- unregister_netdev(netdev);
+ if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+ pci_disable_msi(pdev);
vfree(adapter->cmd_buf_arr);
+ pci_disable_device(pdev);
+
+ if (adapter->portnum == 0) {
+ if (init_firmware_done) {
+ dma_watchdog_shutdown_request(adapter);
+ msleep(100);
+ i = 100;
+ while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
+ printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
+ msleep(100);
+ i--;
+ }
+
+ if (i == 0) {
+ printk(KERN_ERR "dma_watchdog_shutdown_request failed\n");
+ return;
+ }
+
+ /* clear the register for future unloads/loads */
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
+ printk(KERN_INFO "State: 0x%0x\n",
+ readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
+
+ /* leave the hw in the same state as reboot */
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ if (netxen_pinit_from_rom(adapter, 0))
+ return;
+ msleep(1);
+ if (netxen_load_firmware(adapter))
+ return;
+ netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+ }
+
+ /* clear the register for future unloads/loads */
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
+ printk(KERN_INFO "State: 0x%0x\n",
+ readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
+
+ dma_watchdog_shutdown_request(adapter);
+ msleep(100);
+ i = 100;
+ while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
+ printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
+ msleep(100);
+ i--;
+ }
+
+ if (i) {
+ netxen_free_adapter_offload(adapter);
+ } else {
+ printk(KERN_ERR "failed to dma shutdown\n");
+ return;
+ }
+
+ }
+
iounmap(adapter->ahw.db_base);
iounmap(adapter->ahw.pci_base0);
iounmap(adapter->ahw.pci_base1);
iounmap(adapter->ahw.pci_base2);
pci_release_regions(pdev);
- pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
free_netdev(netdev);
@@ -793,7 +936,7 @@ static int netxen_nic_close(struct net_device *netdev)
if (buffrag->dma) {
pci_unmap_single(adapter->pdev, buffrag->dma,
buffrag->length, PCI_DMA_TODEVICE);
- buffrag->dma = (u64) NULL;
+ buffrag->dma = 0ULL;
}
for (j = 0; j < cmd_buff->frag_count; j++) {
buffrag++;
@@ -801,7 +944,7 @@ static int netxen_nic_close(struct net_device *netdev)
pci_unmap_page(adapter->pdev, buffrag->dma,
buffrag->length,
PCI_DMA_TODEVICE);
- buffrag->dma = (u64) NULL;
+ buffrag->dma = 0ULL;
}
}
/* Free the skb we received in netxen_nic_xmit_frame */
@@ -811,8 +954,10 @@ static int netxen_nic_close(struct net_device *netdev)
}
cmd_buff++;
}
- FLUSH_SCHEDULED_WORK();
- del_timer_sync(&adapter->watchdog_timer);
+ if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
+ FLUSH_SCHEDULED_WORK();
+ del_timer_sync(&adapter->watchdog_timer);
+ }
return 0;
}
@@ -1098,28 +1243,26 @@ static int
netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
{
u32 ret = 0;
+ u32 our_int = 0;
DPRINTK(INFO, "Entered handle ISR\n");
adapter->stats.ints++;
if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
- int count = 0;
- u32 mask;
- u32 our_int = 0;
our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
/* not our interrupt */
if ((our_int & (0x80 << adapter->portnum)) == 0)
return ret;
- netxen_nic_disable_int(adapter);
- /* Window = 0 or 1 */
- do {
- writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
- ISR_INT_TARGET_STATUS));
- mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
- } while (((mask & 0x80) != 0) && (++count < 32));
- if ((mask & 0x80) != 0)
- printk("Could not disable interrupt completely\n");
+ }
+ netxen_nic_disable_int(adapter);
+
+ if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
+ /* claim interrupt */
+ if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ writel(our_int & ~((u32)(0x80 << adapter->portnum)),
+ NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ }
}
if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
@@ -1131,7 +1274,7 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
} else {
static unsigned int intcount = 0;
if ((++intcount & 0xfff) == 0xfff)
- printk(KERN_ERR
+ DPRINTK(KERN_ERR
"%s: %s interrupt %d while in poll\n",
netxen_nic_driver_name, netdev->name,
intcount);
@@ -1253,6 +1396,7 @@ static void __exit netxen_exit_module(void)
/*
* Wait for some time to allow the dma to drain, if any.
*/
+ msleep(100);
pci_unregister_driver(&netxen_driver);
destroy_workqueue(netxen_workq);
}
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index cef90a78351..05e0577a0e1 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -454,16 +454,12 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
{
- u32 reg;
u32 portnum = physical_port[adapter->portnum];
netxen_crb_writelit_adapter(adapter,
- NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
- netxen_nic_hw_read_wx(adapter,
- NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), &reg, 4);
- reg = (reg & ~0x2000UL);
+ NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447);
netxen_crb_writelit_adapter(adapter,
- NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), reg);
+ NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
return 0;
}
@@ -728,7 +724,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
__u32 mac_cfg0;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ if (port > NETXEN_NIU_MAX_GBE_PORTS)
return -EINVAL;
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
@@ -761,7 +757,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
__u32 reg;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
+ if (port > NETXEN_NIU_MAX_GBE_PORTS)
return -EINVAL;
/* save previous contents */
@@ -898,7 +894,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
__u32 reg;
u32 port = physical_port[adapter->portnum];
- if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
+ if (port > NETXEN_NIU_MAX_XG_PORTS)
return -EINVAL;
if (netxen_nic_hw_read_wx(adapter,
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
index 9457fc7249c..10fe6fafa6f 100644
--- a/drivers/net/netxen/netxen_nic_phan_reg.h
+++ b/drivers/net/netxen/netxen_nic_phan_reg.h
@@ -114,6 +114,20 @@
#define CRB_V2P_3 NETXEN_NIC_REG(0x29c)
#define CRB_V2P(port) (CRB_V2P_0+((port)*4))
#define CRB_DRIVER_VERSION NETXEN_NIC_REG(0x2a0)
+/* sw int status/mask registers */
+#define CRB_SW_INT_MASK_0 NETXEN_NIC_REG(0x1d8)
+#define CRB_SW_INT_MASK_1 NETXEN_NIC_REG(0x1e0)
+#define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4)
+#define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8)
+
+/*
+ * capabilities register, can be used to selectively enable/disable features
+ * for backward compability
+ */
+#define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8)
+#define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc)
+
+#define INTR_SCHEME_PERPORT 0x1
/* used for ethtool tests */
#define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280)
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index 8dbd6d1900b..5e7999db209 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -936,7 +936,7 @@ static void ni52_rcv_int(struct net_device *dev)
{
skb_reserve(skb,2);
skb_put(skb,totlen);
- eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0);
+ skb_copy_to_linear_data(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
dev->last_rx = jiffies;
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 3818edf0ac1..4ef5fe34519 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -1096,7 +1096,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0)
#ifdef RCV_VIA_SKB
if( (unsigned long) (skb->data + R_BUF_SIZE) > 0x1000000) {
skb_put(skb,len);
- eth_copy_and_sum(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len,0);
+ skb_copy_to_linear_data(skb, (unsigned char *)(p->recv_skb[p->rmdnum]->data),len);
}
else {
struct sk_buff *skb1 = p->recv_skb[p->rmdnum];
@@ -1108,7 +1108,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0)
}
#else
skb_put(skb,len);
- eth_copy_and_sum(skb, (unsigned char *) p->recvbounce[p->rmdnum],len,0);
+ skb_copy_to_linear_data(skb, (unsigned char *) p->recvbounce[p->rmdnum],len);
#endif
p->stats.rx_packets++;
p->stats.rx_bytes += len;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 3439f8c649f..104aab3c957 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -506,17 +506,6 @@ static void ns83820_vlan_rx_register(struct net_device *ndev, struct vlan_group
spin_unlock(&dev->tx_lock);
spin_unlock_irq(&dev->misc_lock);
}
-
-static void ns83820_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid)
-{
- struct ns83820 *dev = PRIV(ndev);
-
- spin_lock_irq(&dev->misc_lock);
- spin_lock(&dev->tx_lock);
- vlan_group_set_device(dev->vlgrp, vid, NULL);
- spin_unlock(&dev->tx_lock);
- spin_unlock_irq(&dev->misc_lock);
-}
#endif
/* Packet Receiver
@@ -1842,11 +1831,13 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
ndev = alloc_etherdev(sizeof(struct ns83820));
dev = PRIV(ndev);
- dev->ndev = ndev;
+
err = -ENOMEM;
if (!dev)
goto out;
+ dev->ndev = ndev;
+
spin_lock_init(&dev->rx_info.lock);
spin_lock_init(&dev->tx_lock);
spin_lock_init(&dev->misc_lock);
@@ -2083,7 +2074,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
/* We also support hardware vlan acceleration */
ndev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
ndev->vlan_rx_register = ns83820_vlan_rx_register;
- ndev->vlan_rx_kill_vid = ns83820_vlan_rx_kill_vid;
#endif
if (using_dac) {
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 8d38425e46c..0b3066a6fe4 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -755,7 +755,7 @@ static int pasemi_mac_open(struct net_device *dev)
flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
- PAS_IOB_DMA_RXCH_CFG_CNTTH(1));
+ PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
pci_write_config_dword(mac->iob_pdev, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
PAS_IOB_DMA_TXCH_CFG_CNTTH(32));
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index df8998b4f37..3cdbe118200 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -1567,7 +1567,7 @@ static void netdrv_rx_interrupt (struct net_device *dev,
if (skb) {
skb_reserve (skb, 2); /* 16 byte align the IP fields. */
- eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+ skb_copy_to_linear_data (skb, &rx_ring[ring_offset + 4], pkt_size);
skb_put (skb, pkt_size);
skb->protocol = eth_type_trans (skb, dev);
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 143ae2ff309..503f2685fb7 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -629,9 +629,9 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
}
- dev_kfree_skb(skb);
pop_tx_status(dev);
spin_unlock_irqrestore(&priv->lock, flags);
+ dev_kfree_skb(skb);
return 0;
}
diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig
index 5d658bc9791..e8f55d8ed7a 100644
--- a/drivers/net/pcmcia/Kconfig
+++ b/drivers/net/pcmcia/Kconfig
@@ -19,7 +19,7 @@ menuconfig NET_PCMCIA
If unsure, say N.
-if NET_PCMCIA
+if NET_PCMCIA && PCMCIA
config PCMCIA_3C589
tristate "3Com 3c589 PCMCIA support"
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 808fae1577e..50dff1b81d3 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -521,6 +521,7 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
static int axnet_open(struct net_device *dev)
{
+ int ret;
axnet_dev_t *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
@@ -529,9 +530,11 @@ static int axnet_open(struct net_device *dev)
if (!pcmcia_dev_present(link))
return -ENODEV;
- link->open++;
+ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+ if (ret)
+ return ret;
- request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+ link->open++;
info->link_status = 0x00;
init_timer(&info->watchdog);
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 3f93d493323..85d5f2ca4bb 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -109,7 +109,7 @@ static const struct ethtool_ops netdev_ethtool_ops;
card type
*/
typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
- XXX10304
+ XXX10304, NEC, KME
} cardtype_t;
/*
@@ -374,6 +374,18 @@ static int fmvj18x_config(struct pcmcia_device *link)
link->io.NumPorts2 = 8;
}
break;
+ case MANFID_NEC:
+ cardtype = NEC; /* MultiFunction Card */
+ link->conf.ConfigBase = 0x800;
+ link->conf.ConfigIndex = 0x47;
+ link->io.NumPorts2 = 8;
+ break;
+ case MANFID_KME:
+ cardtype = KME; /* MultiFunction Card */
+ link->conf.ConfigBase = 0x800;
+ link->conf.ConfigIndex = 0x47;
+ link->io.NumPorts2 = 8;
+ break;
case MANFID_CONTEC:
cardtype = CONTEC;
break;
@@ -450,6 +462,8 @@ static int fmvj18x_config(struct pcmcia_device *link)
case TDK:
case LA501:
case CONTEC:
+ case NEC:
+ case KME:
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
@@ -469,6 +483,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
card_name = "TDK LAK-CD021";
} else if( cardtype == LA501 ) {
card_name = "LA501";
+ } else if( cardtype == NEC ) {
+ card_name = "PK-UG-J001";
+ } else if( cardtype == KME ) {
+ card_name = "Panasonic";
} else {
card_name = "C-NET(PC)C";
}
@@ -678,8 +696,11 @@ static struct pcmcia_device_id fmvj18x_ids[] = {
PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
+ PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
+ PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
+ PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
PCMCIA_DEVICE_NULL,
};
MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index d88e9b2e93c..63de89e93b7 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -960,6 +960,7 @@ static void mii_phy_probe(struct net_device *dev)
static int pcnet_open(struct net_device *dev)
{
+ int ret;
pcnet_dev_t *info = PRIV(dev);
struct pcmcia_device *link = info->p_dev;
@@ -968,10 +969,12 @@ static int pcnet_open(struct net_device *dev)
if (!pcmcia_dev_present(link))
return -ENODEV;
- link->open++;
-
set_misc_reg(dev);
- request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev);
+ if (ret)
+ return ret;
+
+ link->open++;
info->phy_id = info->eth_phy;
info->link_status = 0x00;
@@ -1552,6 +1555,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+ PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
@@ -1577,6 +1581,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
+ PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 9c171a7390e..465485a3fbc 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1235,9 +1235,9 @@ static void pcnet32_rx_entry(struct net_device *dev,
lp->rx_dma_addr[entry],
pkt_len,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
(unsigned char *)(lp->rx_skbuff[entry]->data),
- pkt_len, 0);
+ pkt_len);
pci_dma_sync_single_for_device(lp->pci_dev,
lp->rx_dma_addr[entry],
pkt_len,
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 09b6f259eb9..dd09011c7ee 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -55,6 +55,11 @@ config BROADCOM_PHY
---help---
Currently supports the BCM5411, BCM5421 and BCM5461 PHYs.
+config ICPLUS_PHY
+ tristate "Drivers for ICPlus PHYs"
+ ---help---
+ Currently supports the IP175C PHY.
+
config FIXED_PHY
tristate "Drivers for PHY emulation on fixed speed/link"
---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index bcd1efbd2a1..8885650647f 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -11,4 +11,5 @@ obj-$(CONFIG_QSEMI_PHY) += qsemi.o
obj-$(CONFIG_SMSC_PHY) += smsc.o
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
+obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_FIXED_PHY) += fixed.o
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
new file mode 100644
index 00000000000..af3f1f2a9f8
--- /dev/null
+++ b/drivers/net/phy/icplus.c
@@ -0,0 +1,134 @@
+/*
+ * Driver for ICPlus PHYs
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.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/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+MODULE_DESCRIPTION("ICPlus IP175C PHY driver");
+MODULE_AUTHOR("Michael Barkowski");
+MODULE_LICENSE("GPL");
+
+static int ip175c_config_init(struct phy_device *phydev)
+{
+ int err, i;
+ static int full_reset_performed = 0;
+
+ if (full_reset_performed == 0) {
+
+ /* master reset */
+ err = phydev->bus->write(phydev->bus, 30, 0, 0x175c);
+ if (err < 0)
+ return err;
+
+ /* ensure no bus delays overlap reset period */
+ err = phydev->bus->read(phydev->bus, 30, 0);
+
+ /* data sheet specifies reset period is 2 msec */
+ mdelay(2);
+
+ /* enable IP175C mode */
+ err = phydev->bus->write(phydev->bus, 29, 31, 0x175c);
+ if (err < 0)
+ return err;
+
+ /* Set MII0 speed and duplex (in PHY mode) */
+ err = phydev->bus->write(phydev->bus, 29, 22, 0x420);
+ if (err < 0)
+ return err;
+
+ /* reset switch ports */
+ for (i = 0; i < 5; i++) {
+ err = phydev->bus->write(phydev->bus, i,
+ MII_BMCR, BMCR_RESET);
+ if (err < 0)
+ return err;
+ }
+
+ for (i = 0; i < 5; i++)
+ err = phydev->bus->read(phydev->bus, i, MII_BMCR);
+
+ mdelay(2);
+
+ full_reset_performed = 1;
+ }
+
+ if (phydev->addr != 4) {
+ phydev->state = PHY_RUNNING;
+ phydev->speed = SPEED_100;
+ phydev->duplex = DUPLEX_FULL;
+ phydev->link = 1;
+ netif_carrier_on(phydev->attached_dev);
+ }
+
+ return 0;
+}
+
+static int ip175c_read_status(struct phy_device *phydev)
+{
+ if (phydev->addr == 4) /* WAN port */
+ genphy_read_status(phydev);
+ else
+ /* Don't need to read status for switch ports */
+ phydev->irq = PHY_IGNORE_INTERRUPT;
+
+ return 0;
+}
+
+static int ip175c_config_aneg(struct phy_device *phydev)
+{
+ if (phydev->addr == 4) /* WAN port */
+ genphy_config_aneg(phydev);
+
+ return 0;
+}
+
+static struct phy_driver ip175c_driver = {
+ .phy_id = 0x02430d80,
+ .name = "ICPlus IP175C",
+ .phy_id_mask = 0x0ffffff0,
+ .features = PHY_BASIC_FEATURES,
+ .config_init = &ip175c_config_init,
+ .config_aneg = &ip175c_config_aneg,
+ .read_status = &ip175c_read_status,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init ip175c_init(void)
+{
+ return phy_driver_register(&ip175c_driver);
+}
+
+static void __exit ip175c_exit(void)
+{
+ phy_driver_unregister(&ip175c_driver);
+}
+
+module_init(ip175c_init);
+module_exit(ip175c_exit);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 22aec5cce68..d2ede5ff9ff 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -54,6 +54,13 @@
#define MII_M1111_PHY_LED_CONTROL 0x18
#define MII_M1111_PHY_LED_DIRECT 0x4100
#define MII_M1111_PHY_LED_COMBINE 0x411c
+#define MII_M1111_PHY_EXT_CR 0x14
+#define MII_M1111_RX_DELAY 0x80
+#define MII_M1111_TX_DELAY 0x2
+#define MII_M1111_PHY_EXT_SR 0x1b
+#define MII_M1111_HWCFG_MODE_MASK 0xf
+#define MII_M1111_HWCFG_MODE_RGMII 0xb
+#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
MODULE_DESCRIPTION("Marvell PHY driver");
MODULE_AUTHOR("Andy Fleming");
@@ -131,6 +138,60 @@ static int marvell_config_aneg(struct phy_device *phydev)
return err;
}
+static int m88e1111_config_init(struct phy_device *phydev)
+{
+ int err;
+
+ if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) {
+ int temp;
+
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
+ temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
+ if (temp < 0)
+ return temp;
+
+ temp |= (MII_M1111_RX_DELAY | MII_M1111_TX_DELAY);
+
+ err = phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
+ if (err < 0)
+ return err;
+ }
+
+ temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
+ if (temp < 0)
+ return temp;
+
+ temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+ temp |= MII_M1111_HWCFG_MODE_RGMII;
+
+ err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+ if (err < 0)
+ return err;
+ }
+
+ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+ int temp;
+
+ temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
+ if (temp < 0)
+ return temp;
+
+ temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+ temp |= MII_M1111_HWCFG_MODE_SGMII_NO_CLK;
+
+ err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+ if (err < 0)
+ return err;
+ }
+
+ err = phy_write(phydev, MII_BMCR, BMCR_RESET);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static int m88e1145_config_init(struct phy_device *phydev)
{
int err;
@@ -152,7 +213,7 @@ static int m88e1145_config_init(struct phy_device *phydev)
if (err < 0)
return err;
- if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR);
if (temp < 0)
return temp;
@@ -193,76 +254,84 @@ static int m88e1145_config_init(struct phy_device *phydev)
return 0;
}
-static struct phy_driver m88e1101_driver = {
- .phy_id = 0x01410c60,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1101",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1111s_driver = {
- .phy_id = 0x01410cc0,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1111",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
-};
-
-static struct phy_driver m88e1145_driver = {
- .phy_id = 0x01410cd0,
- .phy_id_mask = 0xfffffff0,
- .name = "Marvell 88E1145",
- .features = PHY_GBIT_FEATURES,
- .flags = PHY_HAS_INTERRUPT,
- .config_init = &m88e1145_config_init,
- .config_aneg = &marvell_config_aneg,
- .read_status = &genphy_read_status,
- .ack_interrupt = &marvell_ack_interrupt,
- .config_intr = &marvell_config_intr,
- .driver = {.owner = THIS_MODULE,},
+static struct phy_driver marvell_drivers[] = {
+ {
+ .phy_id = 0x01410c60,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1101",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = 0x01410c90,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1112",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1111_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = 0x01410cc0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1111",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1111_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = 0x01410cd0,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Marvell 88E1145",
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &m88e1145_config_init,
+ .config_aneg = &marvell_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &marvell_ack_interrupt,
+ .config_intr = &marvell_config_intr,
+ .driver = {.owner = THIS_MODULE,},
+ }
};
static int __init marvell_init(void)
{
int ret;
+ int i;
- ret = phy_driver_register(&m88e1101_driver);
- if (ret)
- return ret;
+ for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++) {
+ ret = phy_driver_register(&marvell_drivers[i]);
- ret = phy_driver_register(&m88e1111s_driver);
- if (ret)
- goto err1111s;
-
- ret = phy_driver_register(&m88e1145_driver);
- if (ret)
- goto err1145;
+ if (ret) {
+ while (i-- > 0)
+ phy_driver_unregister(&marvell_drivers[i]);
+ return ret;
+ }
+ }
return 0;
-
- err1145:
- phy_driver_unregister(&m88e1111s_driver);
- err1111s:
- phy_driver_unregister(&m88e1101_driver);
- return ret;
}
static void __exit marvell_exit(void)
{
- phy_driver_unregister(&m88e1101_driver);
- phy_driver_unregister(&m88e1111s_driver);
- phy_driver_unregister(&m88e1145_driver);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(marvell_drivers); i++)
+ phy_driver_unregister(&marvell_drivers[i]);
}
module_init(marvell_init);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index fc4aee96cdf..fc2f0e695a1 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -131,7 +131,8 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv)
struct phy_device *phydev = to_phy_device(dev);
struct phy_driver *phydrv = to_phy_driver(drv);
- return (phydrv->phy_id == (phydev->phy_id & phydrv->phy_id_mask));
+ return ((phydrv->phy_id & phydrv->phy_id_mask) ==
+ (phydev->phy_id & phydrv->phy_id_mask));
}
/* Suspend and resume. Copied from platform_suspend and
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 792716beb05..596222b260d 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -84,7 +84,7 @@ static int vsc824x_config_intr(struct phy_device *phydev)
/* Vitesse 824x */
static struct phy_driver vsc8244_driver = {
- .phy_id = 0x000fc6c2,
+ .phy_id = 0x000fc6c0,
.name = "Vitesse VSC8244",
.phy_id_mask = 0x000fffc0,
.features = PHY_GBIT_FEATURES,
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 541168713f1..3ef0092dc09 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1708,7 +1708,18 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
goto err;
if (proto == PPP_COMP) {
- ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN);
+ int obuff_size;
+
+ switch(ppp->rcomp->compress_proto) {
+ case CI_MPPE:
+ obuff_size = ppp->mru + PPP_HDRLEN + 1;
+ break;
+ default:
+ obuff_size = ppp->mru + PPP_HDRLEN;
+ break;
+ }
+
+ ns = dev_alloc_skb(obuff_size);
if (ns == 0) {
printk(KERN_ERR "ppp_decompress_frame: no memory\n");
goto err;
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
new file mode 100644
index 00000000000..5891a0fbdc8
--- /dev/null
+++ b/drivers/net/pppol2tp.c
@@ -0,0 +1,2486 @@
+/*****************************************************************************
+ * Linux PPP over L2TP (PPPoX/PPPoL2TP) Sockets
+ *
+ * PPPoX --- Generic PPP encapsulation socket family
+ * PPPoL2TP --- PPP over L2TP (RFC 2661)
+ *
+ * Version: 1.0.0
+ *
+ * Authors: Martijn van Oosterhout <kleptog@svana.org>
+ * James Chapman (jchapman@katalix.com)
+ * Contributors:
+ * Michal Ostrowski <mostrows@speakeasy.net>
+ * Arnaldo Carvalho de Melo <acme@xconectiva.com.br>
+ * David S. Miller (davem@redhat.com)
+ *
+ * License:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 driver handles only L2TP data frames; control frames are handled by a
+ * userspace application.
+ *
+ * To send data in an L2TP session, userspace opens a PPPoL2TP socket and
+ * attaches it to a bound UDP socket with local tunnel_id / session_id and
+ * peer tunnel_id / session_id set. Data can then be sent or received using
+ * regular socket sendmsg() / recvmsg() calls. Kernel parameters of the socket
+ * can be read or modified using ioctl() or [gs]etsockopt() calls.
+ *
+ * When a PPPoL2TP socket is connected with local and peer session_id values
+ * zero, the socket is treated as a special tunnel management socket.
+ *
+ * Here's example userspace code to create a socket for sending/receiving data
+ * over an L2TP session:-
+ *
+ * struct sockaddr_pppol2tp sax;
+ * int fd;
+ * int session_fd;
+ *
+ * fd = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP);
+ *
+ * sax.sa_family = AF_PPPOX;
+ * sax.sa_protocol = PX_PROTO_OL2TP;
+ * sax.pppol2tp.fd = tunnel_fd; // bound UDP socket
+ * sax.pppol2tp.addr.sin_addr.s_addr = addr->sin_addr.s_addr;
+ * sax.pppol2tp.addr.sin_port = addr->sin_port;
+ * sax.pppol2tp.addr.sin_family = AF_INET;
+ * sax.pppol2tp.s_tunnel = tunnel_id;
+ * sax.pppol2tp.s_session = session_id;
+ * sax.pppol2tp.d_tunnel = peer_tunnel_id;
+ * sax.pppol2tp.d_session = peer_session_id;
+ *
+ * session_fd = connect(fd, (struct sockaddr *)&sax, sizeof(sax));
+ *
+ * A pppd plugin that allows PPP traffic to be carried over L2TP using
+ * this driver is available from the OpenL2TP project at
+ * http://openl2tp.sourceforge.net.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+
+#include <linux/netdevice.h>
+#include <linux/net.h>
+#include <linux/inetdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/if_pppox.h>
+#include <linux/if_pppol2tp.h>
+#include <net/sock.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/file.h>
+#include <linux/hash.h>
+#include <linux/sort.h>
+#include <linux/proc_fs.h>
+#include <net/dst.h>
+#include <net/ip.h>
+#include <net/udp.h>
+#include <net/xfrm.h>
+
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+
+
+#define PPPOL2TP_DRV_VERSION "V1.0"
+
+/* L2TP header constants */
+#define L2TP_HDRFLAG_T 0x8000
+#define L2TP_HDRFLAG_L 0x4000
+#define L2TP_HDRFLAG_S 0x0800
+#define L2TP_HDRFLAG_O 0x0200
+#define L2TP_HDRFLAG_P 0x0100
+
+#define L2TP_HDR_VER_MASK 0x000F
+#define L2TP_HDR_VER 0x0002
+
+/* Space for UDP, L2TP and PPP headers */
+#define PPPOL2TP_HEADER_OVERHEAD 40
+
+/* Just some random numbers */
+#define L2TP_TUNNEL_MAGIC 0x42114DDA
+#define L2TP_SESSION_MAGIC 0x0C04EB7D
+
+#define PPPOL2TP_HASH_BITS 4
+#define PPPOL2TP_HASH_SIZE (1 << PPPOL2TP_HASH_BITS)
+
+/* Default trace flags */
+#define PPPOL2TP_DEFAULT_DEBUG_FLAGS 0
+
+#define PRINTK(_mask, _type, _lvl, _fmt, args...) \
+ do { \
+ if ((_mask) & (_type)) \
+ printk(_lvl "PPPOL2TP: " _fmt, ##args); \
+ } while(0)
+
+/* Number of bytes to build transmit L2TP headers.
+ * Unfortunately the size is different depending on whether sequence numbers
+ * are enabled.
+ */
+#define PPPOL2TP_L2TP_HDR_SIZE_SEQ 10
+#define PPPOL2TP_L2TP_HDR_SIZE_NOSEQ 6
+
+struct pppol2tp_tunnel;
+
+/* Describes a session. It is the sk_user_data field in the PPPoL2TP
+ * socket. Contains information to determine incoming packets and transmit
+ * outgoing ones.
+ */
+struct pppol2tp_session
+{
+ int magic; /* should be
+ * L2TP_SESSION_MAGIC */
+ int owner; /* pid that opened the socket */
+
+ struct sock *sock; /* Pointer to the session
+ * PPPoX socket */
+ struct sock *tunnel_sock; /* Pointer to the tunnel UDP
+ * socket */
+
+ struct pppol2tp_addr tunnel_addr; /* Description of tunnel */
+
+ struct pppol2tp_tunnel *tunnel; /* back pointer to tunnel
+ * context */
+
+ char name[20]; /* "sess xxxxx/yyyyy", where
+ * x=tunnel_id, y=session_id */
+ int mtu;
+ int mru;
+ int flags; /* accessed by PPPIOCGFLAGS.
+ * Unused. */
+ unsigned recv_seq:1; /* expect receive packets with
+ * sequence numbers? */
+ unsigned send_seq:1; /* send packets with sequence
+ * numbers? */
+ unsigned lns_mode:1; /* behave as LNS? LAC enables
+ * sequence numbers under
+ * control of LNS. */
+ int debug; /* bitmask of debug message
+ * categories */
+ int reorder_timeout; /* configured reorder timeout
+ * (in jiffies) */
+ u16 nr; /* session NR state (receive) */
+ u16 ns; /* session NR state (send) */
+ struct sk_buff_head reorder_q; /* receive reorder queue */
+ struct pppol2tp_ioc_stats stats;
+ struct hlist_node hlist; /* Hash list node */
+};
+
+/* The sk_user_data field of the tunnel's UDP socket. It contains info to track
+ * all the associated sessions so incoming packets can be sorted out
+ */
+struct pppol2tp_tunnel
+{
+ int magic; /* Should be L2TP_TUNNEL_MAGIC */
+ rwlock_t hlist_lock; /* protect session_hlist */
+ struct hlist_head session_hlist[PPPOL2TP_HASH_SIZE];
+ /* hashed list of sessions,
+ * hashed by id */
+ int debug; /* bitmask of debug message
+ * categories */
+ char name[12]; /* "tunl xxxxx" */
+ struct pppol2tp_ioc_stats stats;
+
+ void (*old_sk_destruct)(struct sock *);
+
+ struct sock *sock; /* Parent socket */
+ struct list_head list; /* Keep a list of all open
+ * prepared sockets */
+
+ atomic_t ref_count;
+};
+
+/* Private data stored for received packets in the skb.
+ */
+struct pppol2tp_skb_cb {
+ u16 ns;
+ u16 nr;
+ u16 has_seq;
+ u16 length;
+ unsigned long expires;
+};
+
+#define PPPOL2TP_SKB_CB(skb) ((struct pppol2tp_skb_cb *) &skb->cb[sizeof(struct inet_skb_parm)])
+
+static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb);
+static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel);
+
+static atomic_t pppol2tp_tunnel_count;
+static atomic_t pppol2tp_session_count;
+static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL };
+static struct proto_ops pppol2tp_ops;
+static LIST_HEAD(pppol2tp_tunnel_list);
+static DEFINE_RWLOCK(pppol2tp_tunnel_list_lock);
+
+/* Helpers to obtain tunnel/session contexts from sockets.
+ */
+static inline struct pppol2tp_session *pppol2tp_sock_to_session(struct sock *sk)
+{
+ struct pppol2tp_session *session;
+
+ if (sk == NULL)
+ return NULL;
+
+ session = (struct pppol2tp_session *)(sk->sk_user_data);
+ if (session == NULL)
+ return NULL;
+
+ BUG_ON(session->magic != L2TP_SESSION_MAGIC);
+
+ return session;
+}
+
+static inline struct pppol2tp_tunnel *pppol2tp_sock_to_tunnel(struct sock *sk)
+{
+ struct pppol2tp_tunnel *tunnel;
+
+ if (sk == NULL)
+ return NULL;
+
+ tunnel = (struct pppol2tp_tunnel *)(sk->sk_user_data);
+ if (tunnel == NULL)
+ return NULL;
+
+ BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+ return tunnel;
+}
+
+/* Tunnel reference counts. Incremented per session that is added to
+ * the tunnel.
+ */
+static inline void pppol2tp_tunnel_inc_refcount(struct pppol2tp_tunnel *tunnel)
+{
+ atomic_inc(&tunnel->ref_count);
+}
+
+static inline void pppol2tp_tunnel_dec_refcount(struct pppol2tp_tunnel *tunnel)
+{
+ if (atomic_dec_and_test(&tunnel->ref_count))
+ pppol2tp_tunnel_free(tunnel);
+}
+
+/* Session hash list.
+ * The session_id SHOULD be random according to RFC2661, but several
+ * L2TP implementations (Cisco and Microsoft) use incrementing
+ * session_ids. So we do a real hash on the session_id, rather than a
+ * simple bitmask.
+ */
+static inline struct hlist_head *
+pppol2tp_session_id_hash(struct pppol2tp_tunnel *tunnel, u16 session_id)
+{
+ unsigned long hash_val = (unsigned long) session_id;
+ return &tunnel->session_hlist[hash_long(hash_val, PPPOL2TP_HASH_BITS)];
+}
+
+/* Lookup a session by id
+ */
+static struct pppol2tp_session *
+pppol2tp_session_find(struct pppol2tp_tunnel *tunnel, u16 session_id)
+{
+ struct hlist_head *session_list =
+ pppol2tp_session_id_hash(tunnel, session_id);
+ struct pppol2tp_session *session;
+ struct hlist_node *walk;
+
+ read_lock(&tunnel->hlist_lock);
+ hlist_for_each_entry(session, walk, session_list, hlist) {
+ if (session->tunnel_addr.s_session == session_id) {
+ read_unlock(&tunnel->hlist_lock);
+ return session;
+ }
+ }
+ read_unlock(&tunnel->hlist_lock);
+
+ return NULL;
+}
+
+/* Lookup a tunnel by id
+ */
+static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id)
+{
+ struct pppol2tp_tunnel *tunnel = NULL;
+
+ read_lock(&pppol2tp_tunnel_list_lock);
+ list_for_each_entry(tunnel, &pppol2tp_tunnel_list, list) {
+ if (tunnel->stats.tunnel_id == tunnel_id) {
+ read_unlock(&pppol2tp_tunnel_list_lock);
+ return tunnel;
+ }
+ }
+ read_unlock(&pppol2tp_tunnel_list_lock);
+
+ return NULL;
+}
+
+/*****************************************************************************
+ * Receive data handling
+ *****************************************************************************/
+
+/* Queue a skb in order. We come here only if the skb has an L2TP sequence
+ * number.
+ */
+static void pppol2tp_recv_queue_skb(struct pppol2tp_session *session, struct sk_buff *skb)
+{
+ struct sk_buff *skbp;
+ u16 ns = PPPOL2TP_SKB_CB(skb)->ns;
+
+ spin_lock(&session->reorder_q.lock);
+ skb_queue_walk(&session->reorder_q, skbp) {
+ if (PPPOL2TP_SKB_CB(skbp)->ns > ns) {
+ __skb_insert(skb, skbp->prev, skbp, &session->reorder_q);
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+ "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n",
+ session->name, ns, PPPOL2TP_SKB_CB(skbp)->ns,
+ skb_queue_len(&session->reorder_q));
+ session->stats.rx_oos_packets++;
+ goto out;
+ }
+ }
+
+ __skb_queue_tail(&session->reorder_q, skb);
+
+out:
+ spin_unlock(&session->reorder_q.lock);
+}
+
+/* Dequeue a single skb.
+ */
+static void pppol2tp_recv_dequeue_skb(struct pppol2tp_session *session, struct sk_buff *skb)
+{
+ struct pppol2tp_tunnel *tunnel = session->tunnel;
+ int length = PPPOL2TP_SKB_CB(skb)->length;
+ struct sock *session_sock = NULL;
+
+ /* We're about to requeue the skb, so unlink it and return resources
+ * to its current owner (a socket receive buffer).
+ */
+ skb_unlink(skb, &session->reorder_q);
+ skb_orphan(skb);
+
+ tunnel->stats.rx_packets++;
+ tunnel->stats.rx_bytes += length;
+ session->stats.rx_packets++;
+ session->stats.rx_bytes += length;
+
+ if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+ /* Bump our Nr */
+ session->nr++;
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+ "%s: updated nr to %hu\n", session->name, session->nr);
+ }
+
+ /* If the socket is bound, send it in to PPP's input queue. Otherwise
+ * queue it on the session socket.
+ */
+ session_sock = session->sock;
+ if (session_sock->sk_state & PPPOX_BOUND) {
+ struct pppox_sock *po;
+ PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+ "%s: recv %d byte data frame, passing to ppp\n",
+ session->name, length);
+
+ /* We need to forget all info related to the L2TP packet
+ * gathered in the skb as we are going to reuse the same
+ * skb for the inner packet.
+ * Namely we need to:
+ * - reset xfrm (IPSec) information as it applies to
+ * the outer L2TP packet and not to the inner one
+ * - release the dst to force a route lookup on the inner
+ * IP packet since skb->dst currently points to the dst
+ * of the UDP tunnel
+ * - reset netfilter information as it doesn't apply
+ * to the inner packet either
+ */
+ secpath_reset(skb);
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ nf_reset(skb);
+
+ po = pppox_sk(session_sock);
+ ppp_input(&po->chan, skb);
+ } else {
+ PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+ "%s: socket not bound\n", session->name);
+
+ /* Not bound. Nothing we can do, so discard. */
+ session->stats.rx_errors++;
+ kfree_skb(skb);
+ }
+
+ sock_put(session->sock);
+}
+
+/* Dequeue skbs from the session's reorder_q, subject to packet order.
+ * Skbs that have been in the queue for too long are simply discarded.
+ */
+static void pppol2tp_recv_dequeue(struct pppol2tp_session *session)
+{
+ struct sk_buff *skb;
+ struct sk_buff *tmp;
+
+ /* If the pkt at the head of the queue has the nr that we
+ * expect to send up next, dequeue it and any other
+ * in-sequence packets behind it.
+ */
+ spin_lock(&session->reorder_q.lock);
+ skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
+ if (time_after(jiffies, PPPOL2TP_SKB_CB(skb)->expires)) {
+ session->stats.rx_seq_discards++;
+ session->stats.rx_errors++;
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+ "%s: oos pkt %hu len %d discarded (too old), "
+ "waiting for %hu, reorder_q_len=%d\n",
+ session->name, PPPOL2TP_SKB_CB(skb)->ns,
+ PPPOL2TP_SKB_CB(skb)->length, session->nr,
+ skb_queue_len(&session->reorder_q));
+ __skb_unlink(skb, &session->reorder_q);
+ kfree_skb(skb);
+ continue;
+ }
+
+ if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+ if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) {
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+ "%s: holding oos pkt %hu len %d, "
+ "waiting for %hu, reorder_q_len=%d\n",
+ session->name, PPPOL2TP_SKB_CB(skb)->ns,
+ PPPOL2TP_SKB_CB(skb)->length, session->nr,
+ skb_queue_len(&session->reorder_q));
+ goto out;
+ }
+ }
+ spin_unlock(&session->reorder_q.lock);
+ pppol2tp_recv_dequeue_skb(session, skb);
+ spin_lock(&session->reorder_q.lock);
+ }
+
+out:
+ spin_unlock(&session->reorder_q.lock);
+}
+
+/* Internal receive frame. Do the real work of receiving an L2TP data frame
+ * here. The skb is not on a list when we get here.
+ * Returns 0 if the packet was a data packet and was successfully passed on.
+ * Returns 1 if the packet was not a good data packet and could not be
+ * forwarded. All such packets are passed up to userspace to deal with.
+ */
+static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
+{
+ struct pppol2tp_session *session = NULL;
+ struct pppol2tp_tunnel *tunnel;
+ unsigned char *ptr;
+ u16 hdrflags;
+ u16 tunnel_id, session_id;
+ int length;
+ struct udphdr *uh;
+
+ tunnel = pppol2tp_sock_to_tunnel(sock);
+ if (tunnel == NULL)
+ goto error;
+
+ /* Short packet? */
+ if (skb->len < sizeof(struct udphdr)) {
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+ "%s: recv short packet (len=%d)\n", tunnel->name, skb->len);
+ goto error;
+ }
+
+ /* Point to L2TP header */
+ ptr = skb->data + sizeof(struct udphdr);
+
+ /* Get L2TP header flags */
+ hdrflags = ntohs(*(__be16*)ptr);
+
+ /* Trace packet contents, if enabled */
+ if (tunnel->debug & PPPOL2TP_MSG_DATA) {
+ printk(KERN_DEBUG "%s: recv: ", tunnel->name);
+
+ for (length = 0; length < 16; length++)
+ printk(" %02X", ptr[length]);
+ printk("\n");
+ }
+
+ /* Get length of L2TP packet */
+ uh = (struct udphdr *) skb_transport_header(skb);
+ length = ntohs(uh->len) - sizeof(struct udphdr);
+
+ /* Too short? */
+ if (length < 12) {
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+ "%s: recv short L2TP packet (len=%d)\n", tunnel->name, length);
+ goto error;
+ }
+
+ /* If type is control packet, it is handled by userspace. */
+ if (hdrflags & L2TP_HDRFLAG_T) {
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+ "%s: recv control packet, len=%d\n", tunnel->name, length);
+ goto error;
+ }
+
+ /* Skip flags */
+ ptr += 2;
+
+ /* If length is present, skip it */
+ if (hdrflags & L2TP_HDRFLAG_L)
+ ptr += 2;
+
+ /* Extract tunnel and session ID */
+ tunnel_id = ntohs(*(__be16 *) ptr);
+ ptr += 2;
+ session_id = ntohs(*(__be16 *) ptr);
+ ptr += 2;
+
+ /* Find the session context */
+ session = pppol2tp_session_find(tunnel, session_id);
+ if (!session) {
+ /* Not found? Pass to userspace to deal with */
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_INFO,
+ "%s: no socket found (%hu/%hu). Passing up.\n",
+ tunnel->name, tunnel_id, session_id);
+ goto error;
+ }
+ sock_hold(session->sock);
+
+ /* The ref count on the socket was increased by the above call since
+ * we now hold a pointer to the session. Take care to do sock_put()
+ * when exiting this function from now on...
+ */
+
+ /* Handle the optional sequence numbers. If we are the LAC,
+ * enable/disable sequence numbers under the control of the LNS. If
+ * no sequence numbers present but we were expecting them, discard
+ * frame.
+ */
+ if (hdrflags & L2TP_HDRFLAG_S) {
+ u16 ns, nr;
+ ns = ntohs(*(__be16 *) ptr);
+ ptr += 2;
+ nr = ntohs(*(__be16 *) ptr);
+ ptr += 2;
+
+ /* Received a packet with sequence numbers. If we're the LNS,
+ * check if we sre sending sequence numbers and if not,
+ * configure it so.
+ */
+ if ((!session->lns_mode) && (!session->send_seq)) {
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_INFO,
+ "%s: requested to enable seq numbers by LNS\n",
+ session->name);
+ session->send_seq = -1;
+ }
+
+ /* Store L2TP info in the skb */
+ PPPOL2TP_SKB_CB(skb)->ns = ns;
+ PPPOL2TP_SKB_CB(skb)->nr = nr;
+ PPPOL2TP_SKB_CB(skb)->has_seq = 1;
+
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+ "%s: recv data ns=%hu, nr=%hu, session nr=%hu\n",
+ session->name, ns, nr, session->nr);
+ } else {
+ /* No sequence numbers.
+ * If user has configured mandatory sequence numbers, discard.
+ */
+ if (session->recv_seq) {
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_WARNING,
+ "%s: recv data has no seq numbers when required. "
+ "Discarding\n", session->name);
+ session->stats.rx_seq_discards++;
+ session->stats.rx_errors++;
+ goto discard;
+ }
+
+ /* If we're the LAC and we're sending sequence numbers, the
+ * LNS has requested that we no longer send sequence numbers.
+ * If we're the LNS and we're sending sequence numbers, the
+ * LAC is broken. Discard the frame.
+ */
+ if ((!session->lns_mode) && (session->send_seq)) {
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_INFO,
+ "%s: requested to disable seq numbers by LNS\n",
+ session->name);
+ session->send_seq = 0;
+ } else if (session->send_seq) {
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_WARNING,
+ "%s: recv data has no seq numbers when required. "
+ "Discarding\n", session->name);
+ session->stats.rx_seq_discards++;
+ session->stats.rx_errors++;
+ goto discard;
+ }
+
+ /* Store L2TP info in the skb */
+ PPPOL2TP_SKB_CB(skb)->has_seq = 0;
+ }
+
+ /* If offset bit set, skip it. */
+ if (hdrflags & L2TP_HDRFLAG_O)
+ ptr += 2 + ntohs(*(__be16 *) ptr);
+
+ skb_pull(skb, ptr - skb->data);
+
+ /* Skip PPP header, if present. In testing, Microsoft L2TP clients
+ * don't send the PPP header (PPP header compression enabled), but
+ * other clients can include the header. So we cope with both cases
+ * here. The PPP header is always FF03 when using L2TP.
+ *
+ * Note that skb->data[] isn't dereferenced from a u16 ptr here since
+ * the field may be unaligned.
+ */
+ if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03))
+ skb_pull(skb, 2);
+
+ /* Prepare skb for adding to the session's reorder_q. Hold
+ * packets for max reorder_timeout or 1 second if not
+ * reordering.
+ */
+ PPPOL2TP_SKB_CB(skb)->length = length;
+ PPPOL2TP_SKB_CB(skb)->expires = jiffies +
+ (session->reorder_timeout ? session->reorder_timeout : HZ);
+
+ /* Add packet to the session's receive queue. Reordering is done here, if
+ * enabled. Saved L2TP protocol info is stored in skb->sb[].
+ */
+ if (PPPOL2TP_SKB_CB(skb)->has_seq) {
+ if (session->reorder_timeout != 0) {
+ /* Packet reordering enabled. Add skb to session's
+ * reorder queue, in order of ns.
+ */
+ pppol2tp_recv_queue_skb(session, skb);
+ } else {
+ /* Packet reordering disabled. Discard out-of-sequence
+ * packets
+ */
+ if (PPPOL2TP_SKB_CB(skb)->ns != session->nr) {
+ session->stats.rx_seq_discards++;
+ session->stats.rx_errors++;
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+ "%s: oos pkt %hu len %d discarded, "
+ "waiting for %hu, reorder_q_len=%d\n",
+ session->name, PPPOL2TP_SKB_CB(skb)->ns,
+ PPPOL2TP_SKB_CB(skb)->length, session->nr,
+ skb_queue_len(&session->reorder_q));
+ goto discard;
+ }
+ skb_queue_tail(&session->reorder_q, skb);
+ }
+ } else {
+ /* No sequence numbers. Add the skb to the tail of the
+ * reorder queue. This ensures that it will be
+ * delivered after all previous sequenced skbs.
+ */
+ skb_queue_tail(&session->reorder_q, skb);
+ }
+
+ /* Try to dequeue as many skbs from reorder_q as we can. */
+ pppol2tp_recv_dequeue(session);
+
+ return 0;
+
+discard:
+ kfree_skb(skb);
+ sock_put(session->sock);
+
+ return 0;
+
+error:
+ return 1;
+}
+
+/* UDP encapsulation receive handler. See net/ipv4/udp.c.
+ * Return codes:
+ * 0 : success.
+ * <0: error
+ * >0: skb should be passed up to userspace as UDP.
+ */
+static int pppol2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
+{
+ struct pppol2tp_tunnel *tunnel;
+
+ tunnel = pppol2tp_sock_to_tunnel(sk);
+ if (tunnel == NULL)
+ goto pass_up;
+
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+ "%s: received %d bytes\n", tunnel->name, skb->len);
+
+ if (pppol2tp_recv_core(sk, skb))
+ goto pass_up;
+
+ return 0;
+
+pass_up:
+ return 1;
+}
+
+/* Receive message. This is the recvmsg for the PPPoL2TP socket.
+ */
+static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len,
+ int flags)
+{
+ int err;
+ struct sk_buff *skb;
+ struct sock *sk = sock->sk;
+
+ err = -EIO;
+ if (sk->sk_state & PPPOX_BOUND)
+ goto end;
+
+ msg->msg_namelen = 0;
+
+ err = 0;
+ skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+ flags & MSG_DONTWAIT, &err);
+ if (skb) {
+ err = memcpy_toiovec(msg->msg_iov, (unsigned char *) skb->data,
+ skb->len);
+ if (err < 0)
+ goto do_skb_free;
+ err = skb->len;
+ }
+do_skb_free:
+ kfree_skb(skb);
+end:
+ return err;
+}
+
+/************************************************************************
+ * Transmit handling
+ ***********************************************************************/
+
+/* Tell how big L2TP headers are for a particular session. This
+ * depends on whether sequence numbers are being used.
+ */
+static inline int pppol2tp_l2tp_header_len(struct pppol2tp_session *session)
+{
+ if (session->send_seq)
+ return PPPOL2TP_L2TP_HDR_SIZE_SEQ;
+
+ return PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+}
+
+/* Build an L2TP header for the session into the buffer provided.
+ */
+static void pppol2tp_build_l2tp_header(struct pppol2tp_session *session,
+ void *buf)
+{
+ __be16 *bufp = buf;
+ u16 flags = L2TP_HDR_VER;
+
+ if (session->send_seq)
+ flags |= L2TP_HDRFLAG_S;
+
+ /* Setup L2TP header.
+ * FIXME: Can this ever be unaligned? Is direct dereferencing of
+ * 16-bit header fields safe here for all architectures?
+ */
+ *bufp++ = htons(flags);
+ *bufp++ = htons(session->tunnel_addr.d_tunnel);
+ *bufp++ = htons(session->tunnel_addr.d_session);
+ if (session->send_seq) {
+ *bufp++ = htons(session->ns);
+ *bufp++ = 0;
+ session->ns++;
+ PRINTK(session->debug, PPPOL2TP_MSG_SEQ, KERN_DEBUG,
+ "%s: updated ns to %hu\n", session->name, session->ns);
+ }
+}
+
+/* This is the sendmsg for the PPPoL2TP pppol2tp_session socket. We come here
+ * when a user application does a sendmsg() on the session socket. L2TP and
+ * PPP headers must be inserted into the user's data.
+ */
+static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
+ size_t total_len)
+{
+ static const unsigned char ppph[2] = { 0xff, 0x03 };
+ struct sock *sk = sock->sk;
+ struct inet_sock *inet;
+ __wsum csum = 0;
+ struct sk_buff *skb;
+ int error;
+ int hdr_len;
+ struct pppol2tp_session *session;
+ struct pppol2tp_tunnel *tunnel;
+ struct udphdr *uh;
+
+ error = -ENOTCONN;
+ if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
+ goto error;
+
+ /* Get session and tunnel contexts */
+ error = -EBADF;
+ session = pppol2tp_sock_to_session(sk);
+ if (session == NULL)
+ goto error;
+
+ tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+ if (tunnel == NULL)
+ goto error;
+
+ /* What header length is configured for this session? */
+ hdr_len = pppol2tp_l2tp_header_len(session);
+
+ /* Allocate a socket buffer */
+ error = -ENOMEM;
+ skb = sock_wmalloc(sk, NET_SKB_PAD + sizeof(struct iphdr) +
+ sizeof(struct udphdr) + hdr_len +
+ sizeof(ppph) + total_len,
+ 0, GFP_KERNEL);
+ if (!skb)
+ goto error;
+
+ /* Reserve space for headers. */
+ skb_reserve(skb, NET_SKB_PAD);
+ skb_reset_network_header(skb);
+ skb_reserve(skb, sizeof(struct iphdr));
+ skb_reset_transport_header(skb);
+
+ /* Build UDP header */
+ inet = inet_sk(session->tunnel_sock);
+ uh = (struct udphdr *) skb->data;
+ uh->source = inet->sport;
+ uh->dest = inet->dport;
+ uh->len = htons(hdr_len + sizeof(ppph) + total_len);
+ uh->check = 0;
+ skb_put(skb, sizeof(struct udphdr));
+
+ /* Build L2TP header */
+ pppol2tp_build_l2tp_header(session, skb->data);
+ skb_put(skb, hdr_len);
+
+ /* Add PPP header */
+ skb->data[0] = ppph[0];
+ skb->data[1] = ppph[1];
+ skb_put(skb, 2);
+
+ /* Copy user data into skb */
+ error = memcpy_fromiovec(skb->data, m->msg_iov, total_len);
+ if (error < 0) {
+ kfree_skb(skb);
+ goto error;
+ }
+ skb_put(skb, total_len);
+
+ /* Calculate UDP checksum if configured to do so */
+ if (session->tunnel_sock->sk_no_check != UDP_CSUM_NOXMIT)
+ csum = udp_csum_outgoing(sk, skb);
+
+ /* Debug */
+ if (session->send_seq)
+ PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+ "%s: send %Zd bytes, ns=%hu\n", session->name,
+ total_len, session->ns - 1);
+ else
+ PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+ "%s: send %Zd bytes\n", session->name, total_len);
+
+ if (session->debug & PPPOL2TP_MSG_DATA) {
+ int i;
+ unsigned char *datap = skb->data;
+
+ printk(KERN_DEBUG "%s: xmit:", session->name);
+ for (i = 0; i < total_len; i++) {
+ printk(" %02X", *datap++);
+ if (i == 15) {
+ printk(" ...");
+ break;
+ }
+ }
+ printk("\n");
+ }
+
+ /* Queue the packet to IP for output */
+ error = ip_queue_xmit(skb, 1);
+
+ /* Update stats */
+ if (error >= 0) {
+ tunnel->stats.tx_packets++;
+ tunnel->stats.tx_bytes += skb->len;
+ session->stats.tx_packets++;
+ session->stats.tx_bytes += skb->len;
+ } else {
+ tunnel->stats.tx_errors++;
+ session->stats.tx_errors++;
+ }
+
+error:
+ return error;
+}
+
+/* Transmit function called by generic PPP driver. Sends PPP frame
+ * over PPPoL2TP socket.
+ *
+ * This is almost the same as pppol2tp_sendmsg(), but rather than
+ * being called with a msghdr from userspace, it is called with a skb
+ * from the kernel.
+ *
+ * The supplied skb from ppp doesn't have enough headroom for the
+ * insertion of L2TP, UDP and IP headers so we need to allocate more
+ * headroom in the skb. This will create a cloned skb. But we must be
+ * careful in the error case because the caller will expect to free
+ * the skb it supplied, not our cloned skb. So we take care to always
+ * leave the original skb unfreed if we return an error.
+ */
+static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+ static const u8 ppph[2] = { 0xff, 0x03 };
+ struct sock *sk = (struct sock *) chan->private;
+ struct sock *sk_tun;
+ int hdr_len;
+ struct pppol2tp_session *session;
+ struct pppol2tp_tunnel *tunnel;
+ int rc;
+ int headroom;
+ int data_len = skb->len;
+ struct inet_sock *inet;
+ __wsum csum = 0;
+ struct sk_buff *skb2 = NULL;
+ struct udphdr *uh;
+
+ if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
+ goto abort;
+
+ /* Get session and tunnel contexts from the socket */
+ session = pppol2tp_sock_to_session(sk);
+ if (session == NULL)
+ goto abort;
+
+ sk_tun = session->tunnel_sock;
+ if (sk_tun == NULL)
+ goto abort;
+ tunnel = pppol2tp_sock_to_tunnel(sk_tun);
+ if (tunnel == NULL)
+ goto abort;
+
+ /* What header length is configured for this session? */
+ hdr_len = pppol2tp_l2tp_header_len(session);
+
+ /* Check that there's enough headroom in the skb to insert IP,
+ * UDP and L2TP and PPP headers. If not enough, expand it to
+ * make room. Note that a new skb (or a clone) is
+ * allocated. If we return an error from this point on, make
+ * sure we free the new skb but do not free the original skb
+ * since that is done by the caller for the error case.
+ */
+ headroom = NET_SKB_PAD + sizeof(struct iphdr) +
+ sizeof(struct udphdr) + hdr_len + sizeof(ppph);
+ if (skb_headroom(skb) < headroom) {
+ skb2 = skb_realloc_headroom(skb, headroom);
+ if (skb2 == NULL)
+ goto abort;
+ } else
+ skb2 = skb;
+
+ /* Check that the socket has room */
+ if (atomic_read(&sk_tun->sk_wmem_alloc) < sk_tun->sk_sndbuf)
+ skb_set_owner_w(skb2, sk_tun);
+ else
+ goto discard;
+
+ /* Setup PPP header */
+ skb_push(skb2, sizeof(ppph));
+ skb2->data[0] = ppph[0];
+ skb2->data[1] = ppph[1];
+
+ /* Setup L2TP header */
+ skb_push(skb2, hdr_len);
+ pppol2tp_build_l2tp_header(session, skb2->data);
+
+ /* Setup UDP header */
+ inet = inet_sk(sk_tun);
+ skb_push(skb2, sizeof(struct udphdr));
+ skb_reset_transport_header(skb2);
+ uh = (struct udphdr *) skb2->data;
+ uh->source = inet->sport;
+ uh->dest = inet->dport;
+ uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len);
+ uh->check = 0;
+
+ /* Calculate UDP checksum if configured to do so */
+ if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT)
+ csum = udp_csum_outgoing(sk_tun, skb2);
+
+ /* Debug */
+ if (session->send_seq)
+ PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+ "%s: send %d bytes, ns=%hu\n", session->name,
+ data_len, session->ns - 1);
+ else
+ PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
+ "%s: send %d bytes\n", session->name, data_len);
+
+ if (session->debug & PPPOL2TP_MSG_DATA) {
+ int i;
+ unsigned char *datap = skb2->data;
+
+ printk(KERN_DEBUG "%s: xmit:", session->name);
+ for (i = 0; i < data_len; i++) {
+ printk(" %02X", *datap++);
+ if (i == 31) {
+ printk(" ...");
+ break;
+ }
+ }
+ printk("\n");
+ }
+
+ /* Get routing info from the tunnel socket */
+ skb2->dst = sk_dst_get(sk_tun);
+
+ /* Queue the packet to IP for output */
+ rc = ip_queue_xmit(skb2, 1);
+
+ /* Update stats */
+ if (rc >= 0) {
+ tunnel->stats.tx_packets++;
+ tunnel->stats.tx_bytes += skb2->len;
+ session->stats.tx_packets++;
+ session->stats.tx_bytes += skb2->len;
+ } else {
+ tunnel->stats.tx_errors++;
+ session->stats.tx_errors++;
+ }
+
+ /* Free the original skb */
+ kfree_skb(skb);
+
+ return 1;
+
+discard:
+ /* Free the new skb. Caller will free original skb. */
+ if (skb2 != skb)
+ kfree_skb(skb2);
+abort:
+ return 0;
+}
+
+/*****************************************************************************
+ * Session (and tunnel control) socket create/destroy.
+ *****************************************************************************/
+
+/* When the tunnel UDP socket is closed, all the attached sockets need to go
+ * too.
+ */
+static void pppol2tp_tunnel_closeall(struct pppol2tp_tunnel *tunnel)
+{
+ int hash;
+ struct hlist_node *walk;
+ struct hlist_node *tmp;
+ struct pppol2tp_session *session;
+ struct sock *sk;
+
+ if (tunnel == NULL)
+ BUG();
+
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: closing all sessions...\n", tunnel->name);
+
+ write_lock(&tunnel->hlist_lock);
+ for (hash = 0; hash < PPPOL2TP_HASH_SIZE; hash++) {
+again:
+ hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) {
+ session = hlist_entry(walk, struct pppol2tp_session, hlist);
+
+ sk = session->sock;
+
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: closing session\n", session->name);
+
+ hlist_del_init(&session->hlist);
+
+ /* Since we should hold the sock lock while
+ * doing any unbinding, we need to release the
+ * lock we're holding before taking that lock.
+ * Hold a reference to the sock so it doesn't
+ * disappear as we're jumping between locks.
+ */
+ sock_hold(sk);
+ write_unlock(&tunnel->hlist_lock);
+ lock_sock(sk);
+
+ if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+ pppox_unbind_sock(sk);
+ sk->sk_state = PPPOX_DEAD;
+ sk->sk_state_change(sk);
+ }
+
+ /* Purge any queued data */
+ skb_queue_purge(&sk->sk_receive_queue);
+ skb_queue_purge(&sk->sk_write_queue);
+ skb_queue_purge(&session->reorder_q);
+
+ release_sock(sk);
+ sock_put(sk);
+
+ /* Now restart from the beginning of this hash
+ * chain. We always remove a session from the
+ * list so we are guaranteed to make forward
+ * progress.
+ */
+ write_lock(&tunnel->hlist_lock);
+ goto again;
+ }
+ }
+ write_unlock(&tunnel->hlist_lock);
+}
+
+/* Really kill the tunnel.
+ * Come here only when all sessions have been cleared from the tunnel.
+ */
+static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel)
+{
+ /* Remove from socket list */
+ write_lock(&pppol2tp_tunnel_list_lock);
+ list_del_init(&tunnel->list);
+ write_unlock(&pppol2tp_tunnel_list_lock);
+
+ atomic_dec(&pppol2tp_tunnel_count);
+ kfree(tunnel);
+}
+
+/* Tunnel UDP socket destruct hook.
+ * The tunnel context is deleted only when all session sockets have been
+ * closed.
+ */
+static void pppol2tp_tunnel_destruct(struct sock *sk)
+{
+ struct pppol2tp_tunnel *tunnel;
+
+ tunnel = pppol2tp_sock_to_tunnel(sk);
+ if (tunnel == NULL)
+ goto end;
+
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: closing...\n", tunnel->name);
+
+ /* Close all sessions */
+ pppol2tp_tunnel_closeall(tunnel);
+
+ /* No longer an encapsulation socket. See net/ipv4/udp.c */
+ (udp_sk(sk))->encap_type = 0;
+ (udp_sk(sk))->encap_rcv = NULL;
+
+ /* Remove hooks into tunnel socket */
+ tunnel->sock = NULL;
+ sk->sk_destruct = tunnel->old_sk_destruct;
+ sk->sk_user_data = NULL;
+
+ /* Call original (UDP) socket descructor */
+ if (sk->sk_destruct != NULL)
+ (*sk->sk_destruct)(sk);
+
+ pppol2tp_tunnel_dec_refcount(tunnel);
+
+end:
+ return;
+}
+
+/* Really kill the session socket. (Called from sock_put() if
+ * refcnt == 0.)
+ */
+static void pppol2tp_session_destruct(struct sock *sk)
+{
+ struct pppol2tp_session *session = NULL;
+
+ if (sk->sk_user_data != NULL) {
+ struct pppol2tp_tunnel *tunnel;
+
+ session = pppol2tp_sock_to_session(sk);
+ if (session == NULL)
+ goto out;
+
+ /* Don't use pppol2tp_sock_to_tunnel() here to
+ * get the tunnel context because the tunnel
+ * socket might have already been closed (its
+ * sk->sk_user_data will be NULL) so use the
+ * session's private tunnel ptr instead.
+ */
+ tunnel = session->tunnel;
+ if (tunnel != NULL) {
+ BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+ /* If session_id is zero, this is a null
+ * session context, which was created for a
+ * socket that is being used only to manage
+ * tunnels.
+ */
+ if (session->tunnel_addr.s_session != 0) {
+ /* Delete the session socket from the
+ * hash
+ */
+ write_lock(&tunnel->hlist_lock);
+ hlist_del_init(&session->hlist);
+ write_unlock(&tunnel->hlist_lock);
+
+ atomic_dec(&pppol2tp_session_count);
+ }
+
+ /* This will delete the tunnel context if this
+ * is the last session on the tunnel.
+ */
+ session->tunnel = NULL;
+ session->tunnel_sock = NULL;
+ pppol2tp_tunnel_dec_refcount(tunnel);
+ }
+ }
+
+ kfree(session);
+out:
+ return;
+}
+
+/* Called when the PPPoX socket (session) is closed.
+ */
+static int pppol2tp_release(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ int error;
+
+ if (!sk)
+ return 0;
+
+ error = -EBADF;
+ lock_sock(sk);
+ if (sock_flag(sk, SOCK_DEAD) != 0)
+ goto error;
+
+ pppox_unbind_sock(sk);
+
+ /* Signal the death of the socket. */
+ sk->sk_state = PPPOX_DEAD;
+ sock_orphan(sk);
+ sock->sk = NULL;
+
+ /* Purge any queued data */
+ skb_queue_purge(&sk->sk_receive_queue);
+ skb_queue_purge(&sk->sk_write_queue);
+
+ release_sock(sk);
+
+ /* This will delete the session context via
+ * pppol2tp_session_destruct() if the socket's refcnt drops to
+ * zero.
+ */
+ sock_put(sk);
+
+ return 0;
+
+error:
+ release_sock(sk);
+ return error;
+}
+
+/* Internal function to prepare a tunnel (UDP) socket to have PPPoX
+ * sockets attached to it.
+ */
+static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
+ int *error)
+{
+ int err;
+ struct socket *sock = NULL;
+ struct sock *sk;
+ struct pppol2tp_tunnel *tunnel;
+ struct sock *ret = NULL;
+
+ /* Get the tunnel UDP socket from the fd, which was opened by
+ * the userspace L2TP daemon.
+ */
+ err = -EBADF;
+ sock = sockfd_lookup(fd, &err);
+ if (!sock) {
+ PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+ "tunl %hu: sockfd_lookup(fd=%d) returned %d\n",
+ tunnel_id, fd, err);
+ goto err;
+ }
+
+ /* Quick sanity checks */
+ err = -ESOCKTNOSUPPORT;
+ if (sock->type != SOCK_DGRAM) {
+ PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+ "tunl %hu: fd %d wrong type, got %d, expected %d\n",
+ tunnel_id, fd, sock->type, SOCK_DGRAM);
+ goto err;
+ }
+ err = -EAFNOSUPPORT;
+ if (sock->ops->family != AF_INET) {
+ PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_ERR,
+ "tunl %hu: fd %d wrong family, got %d, expected %d\n",
+ tunnel_id, fd, sock->ops->family, AF_INET);
+ goto err;
+ }
+
+ err = -ENOTCONN;
+ sk = sock->sk;
+
+ /* Check if this socket has already been prepped */
+ tunnel = (struct pppol2tp_tunnel *)sk->sk_user_data;
+ if (tunnel != NULL) {
+ /* User-data field already set */
+ err = -EBUSY;
+ BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+
+ /* This socket has already been prepped */
+ ret = tunnel->sock;
+ goto out;
+ }
+
+ /* This socket is available and needs prepping. Create a new tunnel
+ * context and init it.
+ */
+ sk->sk_user_data = tunnel = kzalloc(sizeof(struct pppol2tp_tunnel), GFP_KERNEL);
+ if (sk->sk_user_data == NULL) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ tunnel->magic = L2TP_TUNNEL_MAGIC;
+ sprintf(&tunnel->name[0], "tunl %hu", tunnel_id);
+
+ tunnel->stats.tunnel_id = tunnel_id;
+ tunnel->debug = PPPOL2TP_DEFAULT_DEBUG_FLAGS;
+
+ /* Hook on the tunnel socket destructor so that we can cleanup
+ * if the tunnel socket goes away.
+ */
+ tunnel->old_sk_destruct = sk->sk_destruct;
+ sk->sk_destruct = &pppol2tp_tunnel_destruct;
+
+ tunnel->sock = sk;
+ sk->sk_allocation = GFP_ATOMIC;
+
+ /* Misc init */
+ rwlock_init(&tunnel->hlist_lock);
+
+ /* Add tunnel to our list */
+ INIT_LIST_HEAD(&tunnel->list);
+ write_lock(&pppol2tp_tunnel_list_lock);
+ list_add(&tunnel->list, &pppol2tp_tunnel_list);
+ write_unlock(&pppol2tp_tunnel_list_lock);
+ atomic_inc(&pppol2tp_tunnel_count);
+
+ /* Bump the reference count. The tunnel context is deleted
+ * only when this drops to zero.
+ */
+ pppol2tp_tunnel_inc_refcount(tunnel);
+
+ /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
+ (udp_sk(sk))->encap_type = UDP_ENCAP_L2TPINUDP;
+ (udp_sk(sk))->encap_rcv = pppol2tp_udp_encap_recv;
+
+ ret = tunnel->sock;
+
+ *error = 0;
+out:
+ if (sock)
+ sockfd_put(sock);
+
+ return ret;
+
+err:
+ *error = err;
+ goto out;
+}
+
+static struct proto pppol2tp_sk_proto = {
+ .name = "PPPOL2TP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct pppox_sock),
+};
+
+/* socket() handler. Initialize a new struct sock.
+ */
+static int pppol2tp_create(struct socket *sock)
+{
+ int error = -ENOMEM;
+ struct sock *sk;
+
+ sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppol2tp_sk_proto, 1);
+ if (!sk)
+ goto out;
+
+ sock_init_data(sock, sk);
+
+ sock->state = SS_UNCONNECTED;
+ sock->ops = &pppol2tp_ops;
+
+ sk->sk_backlog_rcv = pppol2tp_recv_core;
+ sk->sk_protocol = PX_PROTO_OL2TP;
+ sk->sk_family = PF_PPPOX;
+ sk->sk_state = PPPOX_NONE;
+ sk->sk_type = SOCK_STREAM;
+ sk->sk_destruct = pppol2tp_session_destruct;
+
+ error = 0;
+
+out:
+ return error;
+}
+
+/* connect() handler. Attach a PPPoX socket to a tunnel UDP socket
+ */
+static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
+ int sockaddr_len, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_pppol2tp *sp = (struct sockaddr_pppol2tp *) uservaddr;
+ struct pppox_sock *po = pppox_sk(sk);
+ struct sock *tunnel_sock = NULL;
+ struct pppol2tp_session *session = NULL;
+ struct pppol2tp_tunnel *tunnel;
+ struct dst_entry *dst;
+ int error = 0;
+
+ lock_sock(sk);
+
+ error = -EINVAL;
+ if (sp->sa_protocol != PX_PROTO_OL2TP)
+ goto end;
+
+ /* Check for already bound sockets */
+ error = -EBUSY;
+ if (sk->sk_state & PPPOX_CONNECTED)
+ goto end;
+
+ /* We don't supporting rebinding anyway */
+ error = -EALREADY;
+ if (sk->sk_user_data)
+ goto end; /* socket is already attached */
+
+ /* Don't bind if s_tunnel is 0 */
+ error = -EINVAL;
+ if (sp->pppol2tp.s_tunnel == 0)
+ goto end;
+
+ /* Special case: prepare tunnel socket if s_session and
+ * d_session is 0. Otherwise look up tunnel using supplied
+ * tunnel id.
+ */
+ if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) {
+ tunnel_sock = pppol2tp_prepare_tunnel_socket(sp->pppol2tp.fd,
+ sp->pppol2tp.s_tunnel,
+ &error);
+ if (tunnel_sock == NULL)
+ goto end;
+
+ tunnel = tunnel_sock->sk_user_data;
+ } else {
+ tunnel = pppol2tp_tunnel_find(sp->pppol2tp.s_tunnel);
+
+ /* Error if we can't find the tunnel */
+ error = -ENOENT;
+ if (tunnel == NULL)
+ goto end;
+
+ tunnel_sock = tunnel->sock;
+ }
+
+ /* Check that this session doesn't already exist */
+ error = -EEXIST;
+ session = pppol2tp_session_find(tunnel, sp->pppol2tp.s_session);
+ if (session != NULL)
+ goto end;
+
+ /* Allocate and initialize a new session context. */
+ session = kzalloc(sizeof(struct pppol2tp_session), GFP_KERNEL);
+ if (session == NULL) {
+ error = -ENOMEM;
+ goto end;
+ }
+
+ skb_queue_head_init(&session->reorder_q);
+
+ session->magic = L2TP_SESSION_MAGIC;
+ session->owner = current->pid;
+ session->sock = sk;
+ session->tunnel = tunnel;
+ session->tunnel_sock = tunnel_sock;
+ session->tunnel_addr = sp->pppol2tp;
+ sprintf(&session->name[0], "sess %hu/%hu",
+ session->tunnel_addr.s_tunnel,
+ session->tunnel_addr.s_session);
+
+ session->stats.tunnel_id = session->tunnel_addr.s_tunnel;
+ session->stats.session_id = session->tunnel_addr.s_session;
+
+ INIT_HLIST_NODE(&session->hlist);
+
+ /* Inherit debug options from tunnel */
+ session->debug = tunnel->debug;
+
+ /* Default MTU must allow space for UDP/L2TP/PPP
+ * headers.
+ */
+ session->mtu = session->mru = 1500 - PPPOL2TP_HEADER_OVERHEAD;
+
+ /* If PMTU discovery was enabled, use the MTU that was discovered */
+ dst = sk_dst_get(sk);
+ if (dst != NULL) {
+ u32 pmtu = dst_mtu(__sk_dst_get(sk));
+ if (pmtu != 0)
+ session->mtu = session->mru = pmtu -
+ PPPOL2TP_HEADER_OVERHEAD;
+ dst_release(dst);
+ }
+
+ /* Special case: if source & dest session_id == 0x0000, this socket is
+ * being created to manage the tunnel. Don't add the session to the
+ * session hash list, just set up the internal context for use by
+ * ioctl() and sockopt() handlers.
+ */
+ if ((session->tunnel_addr.s_session == 0) &&
+ (session->tunnel_addr.d_session == 0)) {
+ error = 0;
+ sk->sk_user_data = session;
+ goto out_no_ppp;
+ }
+
+ /* Get tunnel context from the tunnel socket */
+ tunnel = pppol2tp_sock_to_tunnel(tunnel_sock);
+ if (tunnel == NULL) {
+ error = -EBADF;
+ goto end;
+ }
+
+ /* Right now, because we don't have a way to push the incoming skb's
+ * straight through the UDP layer, the only header we need to worry
+ * about is the L2TP header. This size is different depending on
+ * whether sequence numbers are enabled for the data channel.
+ */
+ po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+
+ po->chan.private = sk;
+ po->chan.ops = &pppol2tp_chan_ops;
+ po->chan.mtu = session->mtu;
+
+ error = ppp_register_channel(&po->chan);
+ if (error)
+ goto end;
+
+ /* This is how we get the session context from the socket. */
+ sk->sk_user_data = session;
+
+ /* Add session to the tunnel's hash list */
+ write_lock(&tunnel->hlist_lock);
+ hlist_add_head(&session->hlist,
+ pppol2tp_session_id_hash(tunnel,
+ session->tunnel_addr.s_session));
+ write_unlock(&tunnel->hlist_lock);
+
+ atomic_inc(&pppol2tp_session_count);
+
+out_no_ppp:
+ pppol2tp_tunnel_inc_refcount(tunnel);
+ sk->sk_state = PPPOX_CONNECTED;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: created\n", session->name);
+
+end:
+ release_sock(sk);
+
+ if (error != 0)
+ PRINTK(session ? session->debug : -1, PPPOL2TP_MSG_CONTROL, KERN_WARNING,
+ "%s: connect failed: %d\n", session->name, error);
+
+ return error;
+}
+
+/* getname() support.
+ */
+static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *usockaddr_len, int peer)
+{
+ int len = sizeof(struct sockaddr_pppol2tp);
+ struct sockaddr_pppol2tp sp;
+ int error = 0;
+ struct pppol2tp_session *session;
+
+ error = -ENOTCONN;
+ if (sock->sk->sk_state != PPPOX_CONNECTED)
+ goto end;
+
+ session = pppol2tp_sock_to_session(sock->sk);
+ if (session == NULL) {
+ error = -EBADF;
+ goto end;
+ }
+
+ sp.sa_family = AF_PPPOX;
+ sp.sa_protocol = PX_PROTO_OL2TP;
+ memcpy(&sp.pppol2tp, &session->tunnel_addr,
+ sizeof(struct pppol2tp_addr));
+
+ memcpy(uaddr, &sp, len);
+
+ *usockaddr_len = len;
+
+ error = 0;
+
+end:
+ return error;
+}
+
+/****************************************************************************
+ * ioctl() handlers.
+ *
+ * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP
+ * sockets. However, in order to control kernel tunnel features, we allow
+ * userspace to create a special "tunnel" PPPoX socket which is used for
+ * control only. Tunnel PPPoX sockets have session_id == 0 and simply allow
+ * the user application to issue L2TP setsockopt(), getsockopt() and ioctl()
+ * calls.
+ ****************************************************************************/
+
+/* Session ioctl helper.
+ */
+static int pppol2tp_session_ioctl(struct pppol2tp_session *session,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ifreq ifr;
+ int err = 0;
+ struct sock *sk = session->sock;
+ int val = (int) arg;
+
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG,
+ "%s: pppol2tp_session_ioctl(cmd=%#x, arg=%#lx)\n",
+ session->name, cmd, arg);
+
+ sock_hold(sk);
+
+ switch (cmd) {
+ case SIOCGIFMTU:
+ err = -ENXIO;
+ if (!(sk->sk_state & PPPOX_CONNECTED))
+ break;
+
+ err = -EFAULT;
+ if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq)))
+ break;
+ ifr.ifr_mtu = session->mtu;
+ if (copy_to_user((void __user *) arg, &ifr, sizeof(struct ifreq)))
+ break;
+
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get mtu=%d\n", session->name, session->mtu);
+ err = 0;
+ break;
+
+ case SIOCSIFMTU:
+ err = -ENXIO;
+ if (!(sk->sk_state & PPPOX_CONNECTED))
+ break;
+
+ err = -EFAULT;
+ if (copy_from_user(&ifr, (void __user *) arg, sizeof(struct ifreq)))
+ break;
+
+ session->mtu = ifr.ifr_mtu;
+
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set mtu=%d\n", session->name, session->mtu);
+ err = 0;
+ break;
+
+ case PPPIOCGMRU:
+ err = -ENXIO;
+ if (!(sk->sk_state & PPPOX_CONNECTED))
+ break;
+
+ err = -EFAULT;
+ if (put_user(session->mru, (int __user *) arg))
+ break;
+
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get mru=%d\n", session->name, session->mru);
+ err = 0;
+ break;
+
+ case PPPIOCSMRU:
+ err = -ENXIO;
+ if (!(sk->sk_state & PPPOX_CONNECTED))
+ break;
+
+ err = -EFAULT;
+ if (get_user(val,(int __user *) arg))
+ break;
+
+ session->mru = val;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set mru=%d\n", session->name, session->mru);
+ err = 0;
+ break;
+
+ case PPPIOCGFLAGS:
+ err = -EFAULT;
+ if (put_user(session->flags, (int __user *) arg))
+ break;
+
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get flags=%d\n", session->name, session->flags);
+ err = 0;
+ break;
+
+ case PPPIOCSFLAGS:
+ err = -EFAULT;
+ if (get_user(val, (int __user *) arg))
+ break;
+ session->flags = val;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set flags=%d\n", session->name, session->flags);
+ err = 0;
+ break;
+
+ case PPPIOCGL2TPSTATS:
+ err = -ENXIO;
+ if (!(sk->sk_state & PPPOX_CONNECTED))
+ break;
+
+ if (copy_to_user((void __user *) arg, &session->stats,
+ sizeof(session->stats)))
+ break;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get L2TP stats\n", session->name);
+ err = 0;
+ break;
+
+ default:
+ err = -ENOSYS;
+ break;
+ }
+
+ sock_put(sk);
+
+ return err;
+}
+
+/* Tunnel ioctl helper.
+ *
+ * Note the special handling for PPPIOCGL2TPSTATS below. If the ioctl data
+ * specifies a session_id, the session ioctl handler is called. This allows an
+ * application to retrieve session stats via a tunnel socket.
+ */
+static int pppol2tp_tunnel_ioctl(struct pppol2tp_tunnel *tunnel,
+ unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ struct sock *sk = tunnel->sock;
+ struct pppol2tp_ioc_stats stats_req;
+
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_DEBUG,
+ "%s: pppol2tp_tunnel_ioctl(cmd=%#x, arg=%#lx)\n", tunnel->name,
+ cmd, arg);
+
+ sock_hold(sk);
+
+ switch (cmd) {
+ case PPPIOCGL2TPSTATS:
+ err = -ENXIO;
+ if (!(sk->sk_state & PPPOX_CONNECTED))
+ break;
+
+ if (copy_from_user(&stats_req, (void __user *) arg,
+ sizeof(stats_req))) {
+ err = -EFAULT;
+ break;
+ }
+ if (stats_req.session_id != 0) {
+ /* resend to session ioctl handler */
+ struct pppol2tp_session *session =
+ pppol2tp_session_find(tunnel, stats_req.session_id);
+ if (session != NULL)
+ err = pppol2tp_session_ioctl(session, cmd, arg);
+ else
+ err = -EBADR;
+ break;
+ }
+#ifdef CONFIG_XFRM
+ tunnel->stats.using_ipsec = (sk->sk_policy[0] || sk->sk_policy[1]) ? 1 : 0;
+#endif
+ if (copy_to_user((void __user *) arg, &tunnel->stats,
+ sizeof(tunnel->stats))) {
+ err = -EFAULT;
+ break;
+ }
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get L2TP stats\n", tunnel->name);
+ err = 0;
+ break;
+
+ default:
+ err = -ENOSYS;
+ break;
+ }
+
+ sock_put(sk);
+
+ return err;
+}
+
+/* Main ioctl() handler.
+ * Dispatch to tunnel or session helpers depending on the socket.
+ */
+static int pppol2tp_ioctl(struct socket *sock, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sock *sk = sock->sk;
+ struct pppol2tp_session *session;
+ struct pppol2tp_tunnel *tunnel;
+ int err;
+
+ if (!sk)
+ return 0;
+
+ err = -EBADF;
+ if (sock_flag(sk, SOCK_DEAD) != 0)
+ goto end;
+
+ err = -ENOTCONN;
+ if ((sk->sk_user_data == NULL) ||
+ (!(sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND))))
+ goto end;
+
+ /* Get session context from the socket */
+ err = -EBADF;
+ session = pppol2tp_sock_to_session(sk);
+ if (session == NULL)
+ goto end;
+
+ /* Special case: if session's session_id is zero, treat ioctl as a
+ * tunnel ioctl
+ */
+ if ((session->tunnel_addr.s_session == 0) &&
+ (session->tunnel_addr.d_session == 0)) {
+ err = -EBADF;
+ tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+ if (tunnel == NULL)
+ goto end;
+
+ err = pppol2tp_tunnel_ioctl(tunnel, cmd, arg);
+ goto end;
+ }
+
+ err = pppol2tp_session_ioctl(session, cmd, arg);
+
+end:
+ return err;
+}
+
+/*****************************************************************************
+ * setsockopt() / getsockopt() support.
+ *
+ * The PPPoX socket is created for L2TP sessions: tunnels have their own UDP
+ * sockets. In order to control kernel tunnel features, we allow userspace to
+ * create a special "tunnel" PPPoX socket which is used for control only.
+ * Tunnel PPPoX sockets have session_id == 0 and simply allow the user
+ * application to issue L2TP setsockopt(), getsockopt() and ioctl() calls.
+ *****************************************************************************/
+
+/* Tunnel setsockopt() helper.
+ */
+static int pppol2tp_tunnel_setsockopt(struct sock *sk,
+ struct pppol2tp_tunnel *tunnel,
+ int optname, int val)
+{
+ int err = 0;
+
+ switch (optname) {
+ case PPPOL2TP_SO_DEBUG:
+ tunnel->debug = val;
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set debug=%x\n", tunnel->name, tunnel->debug);
+ break;
+
+ default:
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/* Session setsockopt helper.
+ */
+static int pppol2tp_session_setsockopt(struct sock *sk,
+ struct pppol2tp_session *session,
+ int optname, int val)
+{
+ int err = 0;
+
+ switch (optname) {
+ case PPPOL2TP_SO_RECVSEQ:
+ if ((val != 0) && (val != 1)) {
+ err = -EINVAL;
+ break;
+ }
+ session->recv_seq = val ? -1 : 0;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set recv_seq=%d\n", session->name,
+ session->recv_seq);
+ break;
+
+ case PPPOL2TP_SO_SENDSEQ:
+ if ((val != 0) && (val != 1)) {
+ err = -EINVAL;
+ break;
+ }
+ session->send_seq = val ? -1 : 0;
+ {
+ struct sock *ssk = session->sock;
+ struct pppox_sock *po = pppox_sk(ssk);
+ po->chan.hdrlen = val ? PPPOL2TP_L2TP_HDR_SIZE_SEQ :
+ PPPOL2TP_L2TP_HDR_SIZE_NOSEQ;
+ }
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set send_seq=%d\n", session->name, session->send_seq);
+ break;
+
+ case PPPOL2TP_SO_LNSMODE:
+ if ((val != 0) && (val != 1)) {
+ err = -EINVAL;
+ break;
+ }
+ session->lns_mode = val ? -1 : 0;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set lns_mode=%d\n", session->name,
+ session->lns_mode);
+ break;
+
+ case PPPOL2TP_SO_DEBUG:
+ session->debug = val;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set debug=%x\n", session->name, session->debug);
+ break;
+
+ case PPPOL2TP_SO_REORDERTO:
+ session->reorder_timeout = msecs_to_jiffies(val);
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: set reorder_timeout=%d\n", session->name,
+ session->reorder_timeout);
+ break;
+
+ default:
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/* Main setsockopt() entry point.
+ * Does API checks, then calls either the tunnel or session setsockopt
+ * handler, according to whether the PPPoL2TP socket is a for a regular
+ * session or the special tunnel type.
+ */
+static int pppol2tp_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int optlen)
+{
+ struct sock *sk = sock->sk;
+ struct pppol2tp_session *session = sk->sk_user_data;
+ struct pppol2tp_tunnel *tunnel;
+ int val;
+ int err;
+
+ if (level != SOL_PPPOL2TP)
+ return udp_prot.setsockopt(sk, level, optname, optval, optlen);
+
+ if (optlen < sizeof(int))
+ return -EINVAL;
+
+ if (get_user(val, (int __user *)optval))
+ return -EFAULT;
+
+ err = -ENOTCONN;
+ if (sk->sk_user_data == NULL)
+ goto end;
+
+ /* Get session context from the socket */
+ err = -EBADF;
+ session = pppol2tp_sock_to_session(sk);
+ if (session == NULL)
+ goto end;
+
+ /* Special case: if session_id == 0x0000, treat as operation on tunnel
+ */
+ if ((session->tunnel_addr.s_session == 0) &&
+ (session->tunnel_addr.d_session == 0)) {
+ err = -EBADF;
+ tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+ if (tunnel == NULL)
+ goto end;
+
+ err = pppol2tp_tunnel_setsockopt(sk, tunnel, optname, val);
+ } else
+ err = pppol2tp_session_setsockopt(sk, session, optname, val);
+
+ err = 0;
+
+end:
+ return err;
+}
+
+/* Tunnel getsockopt helper. Called with sock locked.
+ */
+static int pppol2tp_tunnel_getsockopt(struct sock *sk,
+ struct pppol2tp_tunnel *tunnel,
+ int optname, int __user *val)
+{
+ int err = 0;
+
+ switch (optname) {
+ case PPPOL2TP_SO_DEBUG:
+ *val = tunnel->debug;
+ PRINTK(tunnel->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get debug=%x\n", tunnel->name, tunnel->debug);
+ break;
+
+ default:
+ err = -ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/* Session getsockopt helper. Called with sock locked.
+ */
+static int pppol2tp_session_getsockopt(struct sock *sk,
+ struct pppol2tp_session *session,
+ int optname, int __user *val)
+{
+ int err = 0;
+
+ switch (optname) {
+ case PPPOL2TP_SO_RECVSEQ:
+ *val = session->recv_seq;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get recv_seq=%d\n", session->name, *val);
+ break;
+
+ case PPPOL2TP_SO_SENDSEQ:
+ *val = session->send_seq;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get send_seq=%d\n", session->name, *val);
+ break;
+
+ case PPPOL2TP_SO_LNSMODE:
+ *val = session->lns_mode;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get lns_mode=%d\n", session->name, *val);
+ break;
+
+ case PPPOL2TP_SO_DEBUG:
+ *val = session->debug;
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get debug=%d\n", session->name, *val);
+ break;
+
+ case PPPOL2TP_SO_REORDERTO:
+ *val = (int) jiffies_to_msecs(session->reorder_timeout);
+ PRINTK(session->debug, PPPOL2TP_MSG_CONTROL, KERN_INFO,
+ "%s: get reorder_timeout=%d\n", session->name, *val);
+ break;
+
+ default:
+ err = -ENOPROTOOPT;
+ }
+
+ return err;
+}
+
+/* Main getsockopt() entry point.
+ * Does API checks, then calls either the tunnel or session getsockopt
+ * handler, according to whether the PPPoX socket is a for a regular session
+ * or the special tunnel type.
+ */
+static int pppol2tp_getsockopt(struct socket *sock, int level,
+ int optname, char __user *optval, int __user *optlen)
+{
+ struct sock *sk = sock->sk;
+ struct pppol2tp_session *session = sk->sk_user_data;
+ struct pppol2tp_tunnel *tunnel;
+ int val, len;
+ int err;
+
+ if (level != SOL_PPPOL2TP)
+ return udp_prot.getsockopt(sk, level, optname, optval, optlen);
+
+ if (get_user(len, (int __user *) optlen))
+ return -EFAULT;
+
+ len = min_t(unsigned int, len, sizeof(int));
+
+ if (len < 0)
+ return -EINVAL;
+
+ err = -ENOTCONN;
+ if (sk->sk_user_data == NULL)
+ goto end;
+
+ /* Get the session context */
+ err = -EBADF;
+ session = pppol2tp_sock_to_session(sk);
+ if (session == NULL)
+ goto end;
+
+ /* Special case: if session_id == 0x0000, treat as operation on tunnel */
+ if ((session->tunnel_addr.s_session == 0) &&
+ (session->tunnel_addr.d_session == 0)) {
+ err = -EBADF;
+ tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+ if (tunnel == NULL)
+ goto end;
+
+ err = pppol2tp_tunnel_getsockopt(sk, tunnel, optname, &val);
+ } else
+ err = pppol2tp_session_getsockopt(sk, session, optname, &val);
+
+ err = -EFAULT;
+ if (put_user(len, (int __user *) optlen))
+ goto end;
+
+ if (copy_to_user((void __user *) optval, &val, len))
+ goto end;
+
+ err = 0;
+end:
+ return err;
+}
+
+/*****************************************************************************
+ * /proc filesystem for debug
+ *****************************************************************************/
+
+#ifdef CONFIG_PROC_FS
+
+#include <linux/seq_file.h>
+
+struct pppol2tp_seq_data {
+ struct pppol2tp_tunnel *tunnel; /* current tunnel */
+ struct pppol2tp_session *session; /* NULL means get first session in tunnel */
+};
+
+static struct pppol2tp_session *next_session(struct pppol2tp_tunnel *tunnel, struct pppol2tp_session *curr)
+{
+ struct pppol2tp_session *session = NULL;
+ struct hlist_node *walk;
+ int found = 0;
+ int next = 0;
+ int i;
+
+ read_lock(&tunnel->hlist_lock);
+ for (i = 0; i < PPPOL2TP_HASH_SIZE; i++) {
+ hlist_for_each_entry(session, walk, &tunnel->session_hlist[i], hlist) {
+ if (curr == NULL) {
+ found = 1;
+ goto out;
+ }
+ if (session == curr) {
+ next = 1;
+ continue;
+ }
+ if (next) {
+ found = 1;
+ goto out;
+ }
+ }
+ }
+out:
+ read_unlock(&tunnel->hlist_lock);
+ if (!found)
+ session = NULL;
+
+ return session;
+}
+
+static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_tunnel *curr)
+{
+ struct pppol2tp_tunnel *tunnel = NULL;
+
+ read_lock(&pppol2tp_tunnel_list_lock);
+ if (list_is_last(&curr->list, &pppol2tp_tunnel_list)) {
+ goto out;
+ }
+ tunnel = list_entry(curr->list.next, struct pppol2tp_tunnel, list);
+out:
+ read_unlock(&pppol2tp_tunnel_list_lock);
+
+ return tunnel;
+}
+
+static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs)
+{
+ struct pppol2tp_seq_data *pd = SEQ_START_TOKEN;
+ loff_t pos = *offs;
+
+ if (!pos)
+ goto out;
+
+ BUG_ON(m->private == NULL);
+ pd = m->private;
+
+ if (pd->tunnel == NULL) {
+ if (!list_empty(&pppol2tp_tunnel_list))
+ pd->tunnel = list_entry(pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list);
+ } else {
+ pd->session = next_session(pd->tunnel, pd->session);
+ if (pd->session == NULL) {
+ pd->tunnel = next_tunnel(pd->tunnel);
+ }
+ }
+
+ /* NULL tunnel and session indicates end of list */
+ if ((pd->tunnel == NULL) && (pd->session == NULL))
+ pd = NULL;
+
+out:
+ return pd;
+}
+
+static void *pppol2tp_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return NULL;
+}
+
+static void pppol2tp_seq_stop(struct seq_file *p, void *v)
+{
+ /* nothing to do */
+}
+
+static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)
+{
+ struct pppol2tp_tunnel *tunnel = v;
+
+ seq_printf(m, "\nTUNNEL '%s', %c %d\n",
+ tunnel->name,
+ (tunnel == tunnel->sock->sk_user_data) ? 'Y':'N',
+ atomic_read(&tunnel->ref_count) - 1);
+ seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n",
+ tunnel->debug,
+ tunnel->stats.tx_packets, tunnel->stats.tx_bytes,
+ tunnel->stats.tx_errors,
+ tunnel->stats.rx_packets, tunnel->stats.rx_bytes,
+ tunnel->stats.rx_errors);
+}
+
+static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
+{
+ struct pppol2tp_session *session = v;
+
+ seq_printf(m, " SESSION '%s' %08X/%d %04X/%04X -> "
+ "%04X/%04X %d %c\n",
+ session->name,
+ ntohl(session->tunnel_addr.addr.sin_addr.s_addr),
+ ntohs(session->tunnel_addr.addr.sin_port),
+ session->tunnel_addr.s_tunnel,
+ session->tunnel_addr.s_session,
+ session->tunnel_addr.d_tunnel,
+ session->tunnel_addr.d_session,
+ session->sock->sk_state,
+ (session == session->sock->sk_user_data) ?
+ 'Y' : 'N');
+ seq_printf(m, " %d/%d/%c/%c/%s %08x %u\n",
+ session->mtu, session->mru,
+ session->recv_seq ? 'R' : '-',
+ session->send_seq ? 'S' : '-',
+ session->lns_mode ? "LNS" : "LAC",
+ session->debug,
+ jiffies_to_msecs(session->reorder_timeout));
+ seq_printf(m, " %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n",
+ session->nr, session->ns,
+ session->stats.tx_packets,
+ session->stats.tx_bytes,
+ session->stats.tx_errors,
+ session->stats.rx_packets,
+ session->stats.rx_bytes,
+ session->stats.rx_errors);
+}
+
+static int pppol2tp_seq_show(struct seq_file *m, void *v)
+{
+ struct pppol2tp_seq_data *pd = v;
+
+ /* display header on line 1 */
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(m, "PPPoL2TP driver info, " PPPOL2TP_DRV_VERSION "\n");
+ seq_puts(m, "TUNNEL name, user-data-ok session-count\n");
+ seq_puts(m, " debug tx-pkts/bytes/errs rx-pkts/bytes/errs\n");
+ seq_puts(m, " SESSION name, addr/port src-tid/sid "
+ "dest-tid/sid state user-data-ok\n");
+ seq_puts(m, " mtu/mru/rcvseq/sendseq/lns debug reorderto\n");
+ seq_puts(m, " nr/ns tx-pkts/bytes/errs rx-pkts/bytes/errs\n");
+ goto out;
+ }
+
+ /* Show the tunnel or session context.
+ */
+ if (pd->session == NULL)
+ pppol2tp_seq_tunnel_show(m, pd->tunnel);
+ else
+ pppol2tp_seq_session_show(m, pd->session);
+
+out:
+ return 0;
+}
+
+static struct seq_operations pppol2tp_seq_ops = {
+ .start = pppol2tp_seq_start,
+ .next = pppol2tp_seq_next,
+ .stop = pppol2tp_seq_stop,
+ .show = pppol2tp_seq_show,
+};
+
+/* Called when our /proc file is opened. We allocate data for use when
+ * iterating our tunnel / session contexts and store it in the private
+ * data of the seq_file.
+ */
+static int pppol2tp_proc_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *m;
+ struct pppol2tp_seq_data *pd;
+ int ret = 0;
+
+ ret = seq_open(file, &pppol2tp_seq_ops);
+ if (ret < 0)
+ goto out;
+
+ m = file->private_data;
+
+ /* Allocate and fill our proc_data for access later */
+ ret = -ENOMEM;
+ m->private = kzalloc(sizeof(struct pppol2tp_seq_data), GFP_KERNEL);
+ if (m->private == NULL)
+ goto out;
+
+ pd = m->private;
+ ret = 0;
+
+out:
+ return ret;
+}
+
+/* Called when /proc file access completes.
+ */
+static int pppol2tp_proc_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *m = (struct seq_file *)file->private_data;
+
+ kfree(m->private);
+ m->private = NULL;
+
+ return seq_release(inode, file);
+}
+
+static struct file_operations pppol2tp_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = pppol2tp_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = pppol2tp_proc_release,
+};
+
+static struct proc_dir_entry *pppol2tp_proc;
+
+#endif /* CONFIG_PROC_FS */
+
+/*****************************************************************************
+ * Init and cleanup
+ *****************************************************************************/
+
+static struct proto_ops pppol2tp_ops = {
+ .family = AF_PPPOX,
+ .owner = THIS_MODULE,
+ .release = pppol2tp_release,
+ .bind = sock_no_bind,
+ .connect = pppol2tp_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .getname = pppol2tp_getname,
+ .poll = datagram_poll,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = pppol2tp_setsockopt,
+ .getsockopt = pppol2tp_getsockopt,
+ .sendmsg = pppol2tp_sendmsg,
+ .recvmsg = pppol2tp_recvmsg,
+ .mmap = sock_no_mmap,
+ .ioctl = pppox_ioctl,
+};
+
+static struct pppox_proto pppol2tp_proto = {
+ .create = pppol2tp_create,
+ .ioctl = pppol2tp_ioctl
+};
+
+static int __init pppol2tp_init(void)
+{
+ int err;
+
+ err = proto_register(&pppol2tp_sk_proto, 0);
+ if (err)
+ goto out;
+ err = register_pppox_proto(PX_PROTO_OL2TP, &pppol2tp_proto);
+ if (err)
+ goto out_unregister_pppol2tp_proto;
+
+#ifdef CONFIG_PROC_FS
+ pppol2tp_proc = create_proc_entry("pppol2tp", 0, proc_net);
+ if (!pppol2tp_proc) {
+ err = -ENOMEM;
+ goto out_unregister_pppox_proto;
+ }
+ pppol2tp_proc->proc_fops = &pppol2tp_proc_fops;
+#endif /* CONFIG_PROC_FS */
+ printk(KERN_INFO "PPPoL2TP kernel driver, %s\n",
+ PPPOL2TP_DRV_VERSION);
+
+out:
+ return err;
+
+out_unregister_pppox_proto:
+ unregister_pppox_proto(PX_PROTO_OL2TP);
+out_unregister_pppol2tp_proto:
+ proto_unregister(&pppol2tp_sk_proto);
+ goto out;
+}
+
+static void __exit pppol2tp_exit(void)
+{
+ unregister_pppox_proto(PX_PROTO_OL2TP);
+
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("pppol2tp", proc_net);
+#endif
+ proto_unregister(&pppol2tp_sk_proto);
+}
+
+module_init(pppol2tp_init);
+module_exit(pppol2tp_exit);
+
+MODULE_AUTHOR("Martijn van Oosterhout <kleptog@svana.org>,"
+ "James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("PPP over L2TP over UDP");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PPPOL2TP_DRV_VERSION);
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
new file mode 100644
index 00000000000..08d25066f05
--- /dev/null
+++ b/drivers/net/ps3_gelic_net.c
@@ -0,0 +1,1576 @@
+/*
+ * PS3 gelic network driver.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation
+ *
+ * This file is based on: spider_net.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, 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.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#include <linux/dma-mapping.h>
+#include <net/checksum.h>
+#include <asm/firmware.h>
+#include <asm/ps3.h>
+#include <asm/lv1call.h>
+
+#include "ps3_gelic_net.h"
+
+#define DRV_NAME "Gelic Network Driver"
+#define DRV_VERSION "1.0"
+
+MODULE_AUTHOR("SCE Inc.");
+MODULE_DESCRIPTION("Gelic Network driver");
+MODULE_LICENSE("GPL");
+
+static inline struct device *ctodev(struct gelic_net_card *card)
+{
+ return &card->dev->core;
+}
+static inline unsigned int bus_id(struct gelic_net_card *card)
+{
+ return card->dev->bus_id;
+}
+static inline unsigned int dev_id(struct gelic_net_card *card)
+{
+ return card->dev->dev_id;
+}
+
+/* set irq_mask */
+static int gelic_net_set_irq_mask(struct gelic_net_card *card, u64 mask)
+{
+ int status;
+
+ status = lv1_net_set_interrupt_mask(bus_id(card), dev_id(card),
+ mask, 0);
+ if (status)
+ dev_info(ctodev(card),
+ "lv1_net_set_interrupt_mask failed %d\n", status);
+ return status;
+}
+static inline void gelic_net_rx_irq_on(struct gelic_net_card *card)
+{
+ gelic_net_set_irq_mask(card, card->ghiintmask | GELIC_NET_RXINT);
+}
+static inline void gelic_net_rx_irq_off(struct gelic_net_card *card)
+{
+ gelic_net_set_irq_mask(card, card->ghiintmask & ~GELIC_NET_RXINT);
+}
+/**
+ * gelic_net_get_descr_status -- returns the status of a descriptor
+ * @descr: descriptor to look at
+ *
+ * returns the status as in the dmac_cmd_status field of the descriptor
+ */
+static enum gelic_net_descr_status
+gelic_net_get_descr_status(struct gelic_net_descr *descr)
+{
+ u32 cmd_status;
+
+ cmd_status = descr->dmac_cmd_status;
+ cmd_status >>= GELIC_NET_DESCR_IND_PROC_SHIFT;
+ return cmd_status;
+}
+
+/**
+ * gelic_net_set_descr_status -- sets the status of a descriptor
+ * @descr: descriptor to change
+ * @status: status to set in the descriptor
+ *
+ * changes the status to the specified value. Doesn't change other bits
+ * in the status
+ */
+static void gelic_net_set_descr_status(struct gelic_net_descr *descr,
+ enum gelic_net_descr_status status)
+{
+ u32 cmd_status;
+
+ /* read the status */
+ cmd_status = descr->dmac_cmd_status;
+ /* clean the upper 4 bits */
+ cmd_status &= GELIC_NET_DESCR_IND_PROC_MASKO;
+ /* add the status to it */
+ cmd_status |= ((u32)status) << GELIC_NET_DESCR_IND_PROC_SHIFT;
+ /* and write it back */
+ descr->dmac_cmd_status = cmd_status;
+ /*
+ * dma_cmd_status field is used to indicate whether the descriptor
+ * is valid or not.
+ * Usually caller of this function wants to inform that to the
+ * hardware, so we assure here the hardware sees the change.
+ */
+ wmb();
+}
+
+/**
+ * gelic_net_free_chain - free descriptor chain
+ * @card: card structure
+ * @descr_in: address of desc
+ */
+static void gelic_net_free_chain(struct gelic_net_card *card,
+ struct gelic_net_descr *descr_in)
+{
+ struct gelic_net_descr *descr;
+
+ for (descr = descr_in; descr && descr->bus_addr; descr = descr->next) {
+ dma_unmap_single(ctodev(card), descr->bus_addr,
+ GELIC_NET_DESCR_SIZE, DMA_BIDIRECTIONAL);
+ descr->bus_addr = 0;
+ }
+}
+
+/**
+ * gelic_net_init_chain - links descriptor chain
+ * @card: card structure
+ * @chain: address of chain
+ * @start_descr: address of descriptor array
+ * @no: number of descriptors
+ *
+ * we manage a circular list that mirrors the hardware structure,
+ * except that the hardware uses bus addresses.
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_init_chain(struct gelic_net_card *card,
+ struct gelic_net_descr_chain *chain,
+ struct gelic_net_descr *start_descr, int no)
+{
+ int i;
+ struct gelic_net_descr *descr;
+
+ descr = start_descr;
+ memset(descr, 0, sizeof(*descr) * no);
+
+ /* set up the hardware pointers in each descriptor */
+ for (i = 0; i < no; i++, descr++) {
+ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+ descr->bus_addr =
+ dma_map_single(ctodev(card), descr,
+ GELIC_NET_DESCR_SIZE,
+ DMA_BIDIRECTIONAL);
+
+ if (!descr->bus_addr)
+ goto iommu_error;
+
+ descr->next = descr + 1;
+ descr->prev = descr - 1;
+ }
+ /* make them as ring */
+ (descr - 1)->next = start_descr;
+ start_descr->prev = (descr - 1);
+
+ /* chain bus addr of hw descriptor */
+ descr = start_descr;
+ for (i = 0; i < no; i++, descr++) {
+ descr->next_descr_addr = descr->next->bus_addr;
+ }
+
+ chain->head = start_descr;
+ chain->tail = start_descr;
+
+ /* do not chain last hw descriptor */
+ (descr - 1)->next_descr_addr = 0;
+
+ return 0;
+
+iommu_error:
+ for (i--, descr--; 0 <= i; i--, descr--)
+ if (descr->bus_addr)
+ dma_unmap_single(ctodev(card), descr->bus_addr,
+ GELIC_NET_DESCR_SIZE,
+ DMA_BIDIRECTIONAL);
+ return -ENOMEM;
+}
+
+/**
+ * gelic_net_prepare_rx_descr - reinitializes a rx descriptor
+ * @card: card structure
+ * @descr: descriptor to re-init
+ *
+ * return 0 on succes, <0 on failure
+ *
+ * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
+ * Activate the descriptor state-wise
+ */
+static int gelic_net_prepare_rx_descr(struct gelic_net_card *card,
+ struct gelic_net_descr *descr)
+{
+ int offset;
+ unsigned int bufsize;
+
+ if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE) {
+ dev_info(ctodev(card), "%s: ERROR status \n", __func__);
+ }
+ /* we need to round up the buffer size to a multiple of 128 */
+ bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
+
+ /* and we need to have it 128 byte aligned, therefore we allocate a
+ * bit more */
+ descr->skb = netdev_alloc_skb(card->netdev,
+ bufsize + GELIC_NET_RXBUF_ALIGN - 1);
+ if (!descr->skb) {
+ descr->buf_addr = 0; /* tell DMAC don't touch memory */
+ dev_info(ctodev(card),
+ "%s:allocate skb failed !!\n", __func__);
+ return -ENOMEM;
+ }
+ descr->buf_size = bufsize;
+ descr->dmac_cmd_status = 0;
+ descr->result_size = 0;
+ descr->valid_size = 0;
+ descr->data_error = 0;
+
+ offset = ((unsigned long)descr->skb->data) &
+ (GELIC_NET_RXBUF_ALIGN - 1);
+ if (offset)
+ skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
+ /* io-mmu-map the skb */
+ descr->buf_addr = dma_map_single(ctodev(card), descr->skb->data,
+ GELIC_NET_MAX_MTU,
+ DMA_FROM_DEVICE);
+ if (!descr->buf_addr) {
+ dev_kfree_skb_any(descr->skb);
+ descr->skb = NULL;
+ dev_info(ctodev(card),
+ "%s:Could not iommu-map rx buffer\n", __func__);
+ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+ return -ENOMEM;
+ } else {
+ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_CARDOWNED);
+ return 0;
+ }
+}
+
+/**
+ * gelic_net_release_rx_chain - free all skb of rx descr
+ * @card: card structure
+ *
+ */
+static void gelic_net_release_rx_chain(struct gelic_net_card *card)
+{
+ struct gelic_net_descr *descr = card->rx_chain.head;
+
+ do {
+ if (descr->skb) {
+ dma_unmap_single(ctodev(card),
+ descr->buf_addr,
+ descr->skb->len,
+ DMA_FROM_DEVICE);
+ descr->buf_addr = 0;
+ dev_kfree_skb_any(descr->skb);
+ descr->skb = NULL;
+ descr->dmac_cmd_status = GELIC_NET_DESCR_NOT_IN_USE;
+ }
+ descr = descr->next;
+ } while (descr != card->rx_chain.head);
+}
+
+/**
+ * gelic_net_fill_rx_chain - fills descriptors/skbs in the rx chains
+ * @card: card structure
+ *
+ * fills all descriptors in the rx chain: allocates skbs
+ * and iommu-maps them.
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_fill_rx_chain(struct gelic_net_card *card)
+{
+ struct gelic_net_descr *descr = card->rx_chain.head;
+ int ret;
+
+ do {
+ if (!descr->skb) {
+ ret = gelic_net_prepare_rx_descr(card, descr);
+ if (ret)
+ goto rewind;
+ }
+ descr = descr->next;
+ } while (descr != card->rx_chain.head);
+
+ return 0;
+rewind:
+ gelic_net_release_rx_chain(card);
+ return ret;
+}
+
+/**
+ * gelic_net_alloc_rx_skbs - allocates rx skbs in rx descriptor chains
+ * @card: card structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_alloc_rx_skbs(struct gelic_net_card *card)
+{
+ struct gelic_net_descr_chain *chain;
+ int ret;
+ chain = &card->rx_chain;
+ ret = gelic_net_fill_rx_chain(card);
+ chain->head = card->rx_top->prev; /* point to the last */
+ return ret;
+}
+
+/**
+ * gelic_net_release_tx_descr - processes a used tx descriptor
+ * @card: card structure
+ * @descr: descriptor to release
+ *
+ * releases a used tx descriptor (unmapping, freeing of skb)
+ */
+static void gelic_net_release_tx_descr(struct gelic_net_card *card,
+ struct gelic_net_descr *descr)
+{
+ struct sk_buff *skb;
+
+
+ if (descr->data_status & (1 << GELIC_NET_TXDESC_TAIL)) {
+ /* 2nd descriptor */
+ skb = descr->skb;
+ dma_unmap_single(ctodev(card), descr->buf_addr, skb->len,
+ DMA_TO_DEVICE);
+ dev_kfree_skb_any(skb);
+ } else {
+ dma_unmap_single(ctodev(card), descr->buf_addr,
+ descr->buf_size, DMA_TO_DEVICE);
+ }
+
+ descr->buf_addr = 0;
+ descr->buf_size = 0;
+ descr->next_descr_addr = 0;
+ descr->result_size = 0;
+ descr->valid_size = 0;
+ descr->data_status = 0;
+ descr->data_error = 0;
+ descr->skb = NULL;
+
+ /* set descr status */
+ descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE;
+}
+
+/**
+ * gelic_net_release_tx_chain - processes sent tx descriptors
+ * @card: adapter structure
+ * @stop: net_stop sequence
+ *
+ * releases the tx descriptors that gelic has finished with
+ */
+static void gelic_net_release_tx_chain(struct gelic_net_card *card, int stop)
+{
+ struct gelic_net_descr_chain *tx_chain;
+ enum gelic_net_descr_status status;
+ int release = 0;
+
+ for (tx_chain = &card->tx_chain;
+ tx_chain->head != tx_chain->tail && tx_chain->tail;
+ tx_chain->tail = tx_chain->tail->next) {
+ status = gelic_net_get_descr_status(tx_chain->tail);
+ switch (status) {
+ case GELIC_NET_DESCR_RESPONSE_ERROR:
+ case GELIC_NET_DESCR_PROTECTION_ERROR:
+ case GELIC_NET_DESCR_FORCE_END:
+ if (printk_ratelimit())
+ dev_info(ctodev(card),
+ "%s: forcing end of tx descriptor " \
+ "with status %x\n",
+ __func__, status);
+ card->netdev_stats.tx_dropped++;
+ break;
+
+ case GELIC_NET_DESCR_COMPLETE:
+ card->netdev_stats.tx_packets++;
+ card->netdev_stats.tx_bytes +=
+ tx_chain->tail->skb->len;
+ break;
+
+ case GELIC_NET_DESCR_CARDOWNED:
+ /* pending tx request */
+ default:
+ /* any other value (== GELIC_NET_DESCR_NOT_IN_USE) */
+ goto out;
+ }
+ gelic_net_release_tx_descr(card, tx_chain->tail);
+ release = 1;
+ }
+out:
+ if (!stop && release)
+ netif_wake_queue(card->netdev);
+}
+
+/**
+ * gelic_net_set_multi - sets multicast addresses and promisc flags
+ * @netdev: interface device structure
+ *
+ * gelic_net_set_multi configures multicast addresses as needed for the
+ * netdev interface. It also sets up multicast, allmulti and promisc
+ * flags appropriately
+ */
+static void gelic_net_set_multi(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ struct dev_mc_list *mc;
+ unsigned int i;
+ uint8_t *p;
+ u64 addr;
+ int status;
+
+ /* clear all multicast address */
+ status = lv1_net_remove_multicast_address(bus_id(card), dev_id(card),
+ 0, 1);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_remove_multicast_address failed %d\n",
+ status);
+ /* set broadcast address */
+ status = lv1_net_add_multicast_address(bus_id(card), dev_id(card),
+ GELIC_NET_BROADCAST_ADDR, 0);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_add_multicast_address failed, %d\n",
+ status);
+
+ if (netdev->flags & IFF_ALLMULTI
+ || netdev->mc_count > GELIC_NET_MC_COUNT_MAX) { /* list max */
+ status = lv1_net_add_multicast_address(bus_id(card),
+ dev_id(card),
+ 0, 1);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_add_multicast_address failed, %d\n",
+ status);
+ return;
+ }
+
+ /* set multicast address */
+ for (mc = netdev->mc_list; mc; mc = mc->next) {
+ addr = 0;
+ p = mc->dmi_addr;
+ for (i = 0; i < ETH_ALEN; i++) {
+ addr <<= 8;
+ addr |= *p++;
+ }
+ status = lv1_net_add_multicast_address(bus_id(card),
+ dev_id(card),
+ addr, 0);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_add_multicast_address failed, %d\n",
+ status);
+ }
+}
+
+/**
+ * gelic_net_enable_rxdmac - enables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
+ * in the GDADMACCNTR register
+ */
+static inline void gelic_net_enable_rxdmac(struct gelic_net_card *card)
+{
+ int status;
+
+ status = lv1_net_start_rx_dma(bus_id(card), dev_id(card),
+ card->rx_chain.tail->bus_addr, 0);
+ if (status)
+ dev_info(ctodev(card),
+ "lv1_net_start_rx_dma failed, status=%d\n", status);
+}
+
+/**
+ * gelic_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * gelic_net_disable_rxdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static inline void gelic_net_disable_rxdmac(struct gelic_net_card *card)
+{
+ int status;
+
+ /* this hvc blocks until the DMA in progress really stopped */
+ status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_stop_rx_dma faild, %d\n", status);
+}
+
+/**
+ * gelic_net_disable_txdmac - disables the transmit DMA controller
+ * @card: card structure
+ *
+ * gelic_net_disable_txdmac terminates processing on the DMA controller by
+ * turing off DMA and issueing a force end
+ */
+static inline void gelic_net_disable_txdmac(struct gelic_net_card *card)
+{
+ int status;
+
+ /* this hvc blocks until the DMA in progress really stopped */
+ status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0);
+ if (status)
+ dev_err(ctodev(card),
+ "lv1_net_stop_tx_dma faild, status=%d\n", status);
+}
+
+/**
+ * gelic_net_stop - called upon ifconfig down
+ * @netdev: interface device structure
+ *
+ * always returns 0
+ */
+static int gelic_net_stop(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ netif_poll_disable(netdev);
+ netif_stop_queue(netdev);
+
+ /* turn off DMA, force end */
+ gelic_net_disable_rxdmac(card);
+ gelic_net_disable_txdmac(card);
+
+ gelic_net_set_irq_mask(card, 0);
+
+ /* disconnect event port */
+ free_irq(card->netdev->irq, card->netdev);
+ ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq);
+ card->netdev->irq = NO_IRQ;
+
+ netif_carrier_off(netdev);
+
+ /* release chains */
+ gelic_net_release_tx_chain(card, 1);
+ gelic_net_release_rx_chain(card);
+
+ gelic_net_free_chain(card, card->tx_top);
+ gelic_net_free_chain(card, card->rx_top);
+
+ return 0;
+}
+
+/**
+ * gelic_net_get_next_tx_descr - returns the next available tx descriptor
+ * @card: device structure to get descriptor from
+ *
+ * returns the address of the next descriptor, or NULL if not available.
+ */
+static struct gelic_net_descr *
+gelic_net_get_next_tx_descr(struct gelic_net_card *card)
+{
+ if (!card->tx_chain.head)
+ return NULL;
+ /* see if we can two consecutive free descrs */
+ if (card->tx_chain.tail != card->tx_chain.head->next &&
+ gelic_net_get_descr_status(card->tx_chain.head) ==
+ GELIC_NET_DESCR_NOT_IN_USE &&
+ card->tx_chain.tail != card->tx_chain.head->next->next &&
+ gelic_net_get_descr_status(card->tx_chain.head->next) ==
+ GELIC_NET_DESCR_NOT_IN_USE )
+ return card->tx_chain.head;
+ else
+ return NULL;
+
+}
+
+/**
+ * gelic_net_set_txdescr_cmdstat - sets the tx descriptor command field
+ * @descr: descriptor structure to fill out
+ * @skb: packet to consider
+ * @middle: middle of frame
+ *
+ * fills out the command and status field of the descriptor structure,
+ * depending on hardware checksum settings. This function assumes a wmb()
+ * has executed before.
+ */
+static void gelic_net_set_txdescr_cmdstat(struct gelic_net_descr *descr,
+ struct sk_buff *skb, int middle)
+{
+ u32 eofr;
+
+ if (middle)
+ eofr = 0;
+ else
+ eofr = GELIC_NET_DMAC_CMDSTAT_END_FRAME;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ descr->dmac_cmd_status = GELIC_NET_DMAC_CMDSTAT_NOCS | eofr;
+ else {
+ /* is packet ip?
+ * if yes: tcp? udp? */
+ if (skb->protocol == htons(ETH_P_IP)) {
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ descr->dmac_cmd_status =
+ GELIC_NET_DMAC_CMDSTAT_TCPCS | eofr;
+ else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ descr->dmac_cmd_status =
+ GELIC_NET_DMAC_CMDSTAT_UDPCS | eofr;
+ else /*
+ * the stack should checksum non-tcp and non-udp
+ * packets on his own: NETIF_F_IP_CSUM
+ */
+ descr->dmac_cmd_status =
+ GELIC_NET_DMAC_CMDSTAT_NOCS | eofr;
+ }
+ }
+}
+
+/**
+ * gelic_net_prepare_tx_descr_v - get dma address of skb_data
+ * @card: card structure
+ * @descr: descriptor structure
+ * @skb: packet to use
+ *
+ * returns 0 on success, <0 on failure.
+ *
+ */
+static int gelic_net_prepare_tx_descr_v(struct gelic_net_card *card,
+ struct gelic_net_descr *descr,
+ struct sk_buff *skb)
+{
+ dma_addr_t buf[2];
+ unsigned int vlan_len;
+
+ if (skb->len < GELIC_NET_VLAN_POS)
+ return -EINVAL;
+
+ memcpy(&descr->vlan, skb->data, GELIC_NET_VLAN_POS);
+ if (card->vlan_index != -1) {
+ descr->vlan.h_vlan_proto = htons(ETH_P_8021Q); /* vlan 0x8100*/
+ descr->vlan.h_vlan_TCI = htons(card->vlan_id[card->vlan_index]);
+ vlan_len = GELIC_NET_VLAN_POS + VLAN_HLEN; /* VLAN_HLEN=4 */
+ } else
+ vlan_len = GELIC_NET_VLAN_POS; /* no vlan tag */
+
+ /* first descr */
+ buf[0] = dma_map_single(ctodev(card), &descr->vlan,
+ vlan_len, DMA_TO_DEVICE);
+
+ if (!buf[0]) {
+ dev_err(ctodev(card),
+ "dma map 1 failed (%p, %i). Dropping packet\n",
+ skb->data, vlan_len);
+ return -ENOMEM;
+ }
+
+ descr->buf_addr = buf[0];
+ descr->buf_size = vlan_len;
+ descr->skb = skb; /* not used */
+ descr->data_status = 0;
+ gelic_net_set_txdescr_cmdstat(descr, skb, 1); /* not the frame end */
+
+ /* second descr */
+ card->tx_chain.head = card->tx_chain.head->next;
+ descr->next_descr_addr = descr->next->bus_addr;
+ descr = descr->next;
+ if (gelic_net_get_descr_status(descr) != GELIC_NET_DESCR_NOT_IN_USE)
+ /* XXX will be removed */
+ dev_err(ctodev(card), "descr is not free!\n");
+
+ buf[1] = dma_map_single(ctodev(card), skb->data + GELIC_NET_VLAN_POS,
+ skb->len - GELIC_NET_VLAN_POS,
+ DMA_TO_DEVICE);
+
+ if (!buf[1]) {
+ dev_err(ctodev(card),
+ "dma map 2 failed (%p, %i). Dropping packet\n",
+ skb->data + GELIC_NET_VLAN_POS,
+ skb->len - GELIC_NET_VLAN_POS);
+ dma_unmap_single(ctodev(card), buf[0], vlan_len,
+ DMA_TO_DEVICE);
+ return -ENOMEM;
+ }
+
+ descr->buf_addr = buf[1];
+ descr->buf_size = skb->len - GELIC_NET_VLAN_POS;
+ descr->skb = skb;
+ descr->data_status = 0;
+ descr->next_descr_addr = 0; /* terminate hw descr */
+ gelic_net_set_txdescr_cmdstat(descr, skb, 0);
+
+ return 0;
+}
+
+/**
+ * gelic_net_kick_txdma - enables TX DMA processing
+ * @card: card structure
+ * @descr: descriptor address to enable TX processing at
+ *
+ */
+static int gelic_net_kick_txdma(struct gelic_net_card *card,
+ struct gelic_net_descr *descr)
+{
+ int status = -ENXIO;
+ int count = 10;
+
+ if (card->tx_dma_progress)
+ return 0;
+
+ if (gelic_net_get_descr_status(descr) == GELIC_NET_DESCR_CARDOWNED) {
+ card->tx_dma_progress = 1;
+ /* sometimes we need retry here */
+ while (count--) {
+ status = lv1_net_start_tx_dma(bus_id(card),
+ dev_id(card),
+ descr->bus_addr, 0);
+ if (!status)
+ break;
+ }
+ if (!count)
+ dev_info(ctodev(card), "lv1_net_start_txdma failed," \
+ "status=%d %#lx\n",
+ status, card->irq_status);
+ }
+ return status;
+}
+
+/**
+ * gelic_net_xmit - transmits a frame over the device
+ * @skb: packet to send out
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ struct gelic_net_descr *descr = NULL;
+ int result;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->tx_dma_lock, flags);
+
+ gelic_net_release_tx_chain(card, 0);
+ if (!skb)
+ goto kick;
+ descr = gelic_net_get_next_tx_descr(card);
+ if (!descr) {
+ netif_stop_queue(netdev);
+ spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+ result = gelic_net_prepare_tx_descr_v(card, descr, skb);
+
+ if (result)
+ goto error;
+
+ card->tx_chain.head = card->tx_chain.head->next;
+
+ if (descr->prev)
+ descr->prev->next_descr_addr = descr->bus_addr;
+kick:
+ /*
+ * as hardware descriptor is modified in the above lines,
+ * ensure that the hardware sees it
+ */
+ wmb();
+ if (gelic_net_kick_txdma(card, card->tx_chain.tail))
+ goto error;
+
+ netdev->trans_start = jiffies;
+ spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+ return NETDEV_TX_OK;
+
+error:
+ card->netdev_stats.tx_dropped++;
+ spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+ return NETDEV_TX_LOCKED;
+}
+
+/**
+ * gelic_net_pass_skb_up - takes an skb from a descriptor and passes it on
+ * @descr: descriptor to process
+ * @card: card structure
+ *
+ * iommu-unmaps the skb, fills out skb structure and passes the data to the
+ * stack. The descriptor state is not changed.
+ */
+static void gelic_net_pass_skb_up(struct gelic_net_descr *descr,
+ struct gelic_net_card *card)
+{
+ struct sk_buff *skb;
+ struct net_device *netdev;
+ u32 data_status, data_error;
+
+ data_status = descr->data_status;
+ data_error = descr->data_error;
+ netdev = card->netdev;
+ /* unmap skb buffer */
+ skb = descr->skb;
+ dma_unmap_single(ctodev(card), descr->buf_addr, GELIC_NET_MAX_MTU,
+ DMA_FROM_DEVICE);
+
+ skb_put(skb, descr->valid_size? descr->valid_size : descr->result_size);
+ if (!descr->valid_size)
+ dev_info(ctodev(card), "buffer full %x %x %x\n",
+ descr->result_size, descr->buf_size,
+ descr->dmac_cmd_status);
+
+ descr->skb = NULL;
+ /*
+ * the card put 2 bytes vlan tag in front
+ * of the ethernet frame
+ */
+ skb_pull(skb, 2);
+ skb->protocol = eth_type_trans(skb, netdev);
+
+ /* checksum offload */
+ if (card->rx_csum) {
+ if ((data_status & GELIC_NET_DATA_STATUS_CHK_MASK) &&
+ (!(data_error & GELIC_NET_DATA_ERROR_CHK_MASK)))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+ } else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* update netdevice statistics */
+ card->netdev_stats.rx_packets++;
+ card->netdev_stats.rx_bytes += skb->len;
+
+ /* pass skb up to stack */
+ netif_receive_skb(skb);
+}
+
+/**
+ * gelic_net_decode_one_descr - processes an rx descriptor
+ * @card: card structure
+ *
+ * returns 1 if a packet has been sent to the stack, otherwise 0
+ *
+ * processes an rx descriptor by iommu-unmapping the data buffer and passing
+ * the packet up to the stack
+ */
+static int gelic_net_decode_one_descr(struct gelic_net_card *card)
+{
+ enum gelic_net_descr_status status;
+ struct gelic_net_descr_chain *chain = &card->rx_chain;
+ struct gelic_net_descr *descr = chain->tail;
+ int dmac_chain_ended;
+
+ status = gelic_net_get_descr_status(descr);
+ /* is this descriptor terminated with next_descr == NULL? */
+ dmac_chain_ended =
+ descr->dmac_cmd_status & GELIC_NET_DMAC_CMDSTAT_RXDCEIS;
+
+ if (status == GELIC_NET_DESCR_CARDOWNED)
+ return 0;
+
+ if (status == GELIC_NET_DESCR_NOT_IN_USE) {
+ dev_dbg(ctodev(card), "dormant descr? %p\n", descr);
+ return 0;
+ }
+
+ if ((status == GELIC_NET_DESCR_RESPONSE_ERROR) ||
+ (status == GELIC_NET_DESCR_PROTECTION_ERROR) ||
+ (status == GELIC_NET_DESCR_FORCE_END)) {
+ dev_info(ctodev(card), "dropping RX descriptor with state %x\n",
+ status);
+ card->netdev_stats.rx_dropped++;
+ goto refill;
+ }
+
+ if ((status != GELIC_NET_DESCR_COMPLETE) &&
+ (status != GELIC_NET_DESCR_FRAME_END)) {
+ dev_dbg(ctodev(card), "RX descriptor with state %x\n",
+ status);
+ goto refill;
+ }
+
+ /* ok, we've got a packet in descr */
+ gelic_net_pass_skb_up(descr, card); /* 1: skb_up sccess */
+
+refill:
+ descr->next_descr_addr = 0; /* unlink the descr */
+
+ /* change the descriptor state: */
+ gelic_net_set_descr_status(descr, GELIC_NET_DESCR_NOT_IN_USE);
+
+ /* refill one desc
+ * FIXME: this can fail, but for now, just leave this
+ * descriptor without skb
+ */
+ gelic_net_prepare_rx_descr(card, descr);
+ chain->head = descr;
+ chain->tail = descr->next;
+ descr->prev->next_descr_addr = descr->bus_addr;
+
+ if (dmac_chain_ended) {
+ gelic_net_enable_rxdmac(card);
+ dev_dbg(ctodev(card), "reenable rx dma\n");
+ }
+
+ return 1;
+}
+
+/**
+ * gelic_net_poll - NAPI poll function called by the stack to return packets
+ * @netdev: interface device structure
+ * @budget: number of packets we can pass to the stack at most
+ *
+ * returns 0 if no more packets available to the driver/stack. Returns 1,
+ * if the quota is exceeded, but the driver has still packets.
+ *
+ */
+static int gelic_net_poll(struct net_device *netdev, int *budget)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ int packets_to_do, packets_done = 0;
+ int no_more_packets = 0;
+
+ packets_to_do = min(*budget, netdev->quota);
+
+ while (packets_to_do) {
+ if (gelic_net_decode_one_descr(card)) {
+ packets_done++;
+ packets_to_do--;
+ } else {
+ /* no more packets for the stack */
+ no_more_packets = 1;
+ break;
+ }
+ }
+ netdev->quota -= packets_done;
+ *budget -= packets_done;
+ if (no_more_packets) {
+ netif_rx_complete(netdev);
+ gelic_net_rx_irq_on(card);
+ return 0;
+ } else
+ return 1;
+}
+
+/**
+ * gelic_net_get_stats - get interface statistics
+ * @netdev: interface device structure
+ *
+ * returns the interface statistics residing in the gelic_net_card struct
+ */
+static struct net_device_stats *gelic_net_get_stats(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ return &card->netdev_stats;
+}
+
+/**
+ * gelic_net_change_mtu - changes the MTU of an interface
+ * @netdev: interface device structure
+ * @new_mtu: new MTU value
+ *
+ * returns 0 on success, <0 on failure
+ */
+static int gelic_net_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ /* no need to re-alloc skbs or so -- the max mtu is about 2.3k
+ * and mtu is outbound only anyway */
+ if ((new_mtu < GELIC_NET_MIN_MTU) ||
+ (new_mtu > GELIC_NET_MAX_MTU)) {
+ return -EINVAL;
+ }
+ netdev->mtu = new_mtu;
+ return 0;
+}
+
+/**
+ * gelic_net_interrupt - event handler for gelic_net
+ */
+static irqreturn_t gelic_net_interrupt(int irq, void *ptr)
+{
+ unsigned long flags;
+ struct net_device *netdev = ptr;
+ struct gelic_net_card *card = netdev_priv(netdev);
+ u64 status;
+
+ status = card->irq_status;
+
+ if (!status)
+ return IRQ_NONE;
+
+ if (status & GELIC_NET_RXINT) {
+ gelic_net_rx_irq_off(card);
+ netif_rx_schedule(netdev);
+ }
+
+ if (status & GELIC_NET_TXINT) {
+ spin_lock_irqsave(&card->tx_dma_lock, flags);
+ card->tx_dma_progress = 0;
+ spin_unlock_irqrestore(&card->tx_dma_lock, flags);
+ /* start pending DMA */
+ gelic_net_xmit(NULL, netdev);
+ }
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/**
+ * gelic_net_poll_controller - artificial interrupt for netconsole etc.
+ * @netdev: interface device structure
+ *
+ * see Documentation/networking/netconsole.txt
+ */
+static void gelic_net_poll_controller(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ gelic_net_set_irq_mask(card, 0);
+ gelic_net_interrupt(netdev->irq, netdev);
+ gelic_net_set_irq_mask(card, card->ghiintmask);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+/**
+ * gelic_net_open_device - open device and map dma region
+ * @card: card structure
+ */
+static int gelic_net_open_device(struct gelic_net_card *card)
+{
+ int result;
+
+ result = ps3_sb_event_receive_port_setup(card->dev, PS3_BINDING_CPU_ANY,
+ &card->netdev->irq);
+
+ if (result) {
+ dev_info(ctodev(card),
+ "%s:%d: gelic_net_open_device failed (%d)\n",
+ __func__, __LINE__, result);
+ result = -EPERM;
+ goto fail_alloc_irq;
+ }
+
+ result = request_irq(card->netdev->irq, gelic_net_interrupt,
+ IRQF_DISABLED, "gelic network", card->netdev);
+
+ if (result) {
+ dev_info(ctodev(card), "%s:%d: request_irq failed (%d)\n",
+ __func__, __LINE__, result);
+ goto fail_request_irq;
+ }
+
+ return 0;
+
+fail_request_irq:
+ ps3_sb_event_receive_port_destroy(card->dev, card->netdev->irq);
+ card->netdev->irq = NO_IRQ;
+fail_alloc_irq:
+ return result;
+}
+
+
+/**
+ * gelic_net_open - called upon ifonfig up
+ * @netdev: interface device structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * gelic_net_open allocates all the descriptors and memory needed for
+ * operation, sets up multicast list and enables interrupts
+ */
+static int gelic_net_open(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ dev_dbg(ctodev(card), " -> %s:%d\n", __func__, __LINE__);
+
+ gelic_net_open_device(card);
+
+ if (gelic_net_init_chain(card, &card->tx_chain,
+ card->descr, GELIC_NET_TX_DESCRIPTORS))
+ goto alloc_tx_failed;
+ if (gelic_net_init_chain(card, &card->rx_chain,
+ card->descr + GELIC_NET_RX_DESCRIPTORS,
+ GELIC_NET_RX_DESCRIPTORS))
+ goto alloc_rx_failed;
+
+ /* head of chain */
+ card->tx_top = card->tx_chain.head;
+ card->rx_top = card->rx_chain.head;
+ dev_dbg(ctodev(card), "descr rx %p, tx %p, size %#lx, num %#x\n",
+ card->rx_top, card->tx_top, sizeof(struct gelic_net_descr),
+ GELIC_NET_RX_DESCRIPTORS);
+ /* allocate rx skbs */
+ if (gelic_net_alloc_rx_skbs(card))
+ goto alloc_skbs_failed;
+
+ card->tx_dma_progress = 0;
+ card->ghiintmask = GELIC_NET_RXINT | GELIC_NET_TXINT;
+
+ gelic_net_set_irq_mask(card, card->ghiintmask);
+ gelic_net_enable_rxdmac(card);
+
+ netif_start_queue(netdev);
+ netif_carrier_on(netdev);
+ netif_poll_enable(netdev);
+
+ return 0;
+
+alloc_skbs_failed:
+ gelic_net_free_chain(card, card->rx_top);
+alloc_rx_failed:
+ gelic_net_free_chain(card, card->tx_top);
+alloc_tx_failed:
+ return -ENOMEM;
+}
+
+#ifdef GELIC_NET_ETHTOOL
+static void gelic_net_get_drvinfo (struct net_device *netdev,
+ struct ethtool_drvinfo *info)
+{
+ strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1);
+ strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1);
+}
+
+static int gelic_net_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ int status;
+ u64 v1, v2;
+ int speed, duplex;
+
+ speed = duplex = -1;
+ status = lv1_net_control(bus_id(card), dev_id(card),
+ GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
+ &v1, &v2);
+ if (status) {
+ /* link down */
+ } else {
+ if (v1 & GELIC_NET_FULL_DUPLEX) {
+ duplex = DUPLEX_FULL;
+ } else {
+ duplex = DUPLEX_HALF;
+ }
+
+ if (v1 & GELIC_NET_SPEED_10 ) {
+ speed = SPEED_10;
+ } else if (v1 & GELIC_NET_SPEED_100) {
+ speed = SPEED_100;
+ } else if (v1 & GELIC_NET_SPEED_1000) {
+ speed = SPEED_1000;
+ }
+ }
+ cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg |
+ SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
+ cmd->advertising = cmd->supported;
+ cmd->speed = speed;
+ cmd->duplex = duplex;
+ cmd->autoneg = AUTONEG_ENABLE; /* always enabled */
+ cmd->port = PORT_TP;
+
+ return 0;
+}
+
+static u32 gelic_net_get_link(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+ int status;
+ u64 v1, v2;
+ int link;
+
+ status = lv1_net_control(bus_id(card), dev_id(card),
+ GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
+ &v1, &v2);
+ if (status)
+ return 0; /* link down */
+
+ if (v1 & GELIC_NET_LINK_UP)
+ link = 1;
+ else
+ link = 0;
+
+ return link;
+}
+
+static int gelic_net_nway_reset(struct net_device *netdev)
+{
+ if (netif_running(netdev)) {
+ gelic_net_stop(netdev);
+ gelic_net_open(netdev);
+ }
+ return 0;
+}
+
+static u32 gelic_net_get_tx_csum(struct net_device *netdev)
+{
+ return (netdev->features & NETIF_F_IP_CSUM) != 0;
+}
+
+static int gelic_net_set_tx_csum(struct net_device *netdev, u32 data)
+{
+ if (data)
+ netdev->features |= NETIF_F_IP_CSUM;
+ else
+ netdev->features &= ~NETIF_F_IP_CSUM;
+
+ return 0;
+}
+
+static u32 gelic_net_get_rx_csum(struct net_device *netdev)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ return card->rx_csum;
+}
+
+static int gelic_net_set_rx_csum(struct net_device *netdev, u32 data)
+{
+ struct gelic_net_card *card = netdev_priv(netdev);
+
+ card->rx_csum = data;
+ return 0;
+}
+
+static struct ethtool_ops gelic_net_ethtool_ops = {
+ .get_drvinfo = gelic_net_get_drvinfo,
+ .get_settings = gelic_net_get_settings,
+ .get_link = gelic_net_get_link,
+ .nway_reset = gelic_net_nway_reset,
+ .get_tx_csum = gelic_net_get_tx_csum,
+ .set_tx_csum = gelic_net_set_tx_csum,
+ .get_rx_csum = gelic_net_get_rx_csum,
+ .set_rx_csum = gelic_net_set_rx_csum,
+};
+#endif
+
+/**
+ * gelic_net_tx_timeout_task - task scheduled by the watchdog timeout
+ * function (to be called not under interrupt status)
+ * @work: work is context of tx timout task
+ *
+ * called as task when tx hangs, resets interface (if interface is up)
+ */
+static void gelic_net_tx_timeout_task(struct work_struct *work)
+{
+ struct gelic_net_card *card =
+ container_of(work, struct gelic_net_card, tx_timeout_task);
+ struct net_device *netdev = card->netdev;
+
+ dev_info(ctodev(card), "%s:Timed out. Restarting... \n", __func__);
+
+ if (!(netdev->flags & IFF_UP))
+ goto out;
+
+ netif_device_detach(netdev);
+ gelic_net_stop(netdev);
+
+ gelic_net_open(netdev);
+ netif_device_attach(netdev);
+
+out:
+ atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * gelic_net_tx_timeout - called when the tx timeout watchdog kicks in.
+ * @netdev: interface device structure
+ *
+ * called, if tx hangs. Schedules a task that resets the interface
+ */
+static void gelic_net_tx_timeout(struct net_device *netdev)
+{
+ struct gelic_net_card *card;
+
+ card = netdev_priv(netdev);
+ atomic_inc(&card->tx_timeout_task_counter);
+ if (netdev->flags & IFF_UP)
+ schedule_work(&card->tx_timeout_task);
+ else
+ atomic_dec(&card->tx_timeout_task_counter);
+}
+
+/**
+ * gelic_net_setup_netdev_ops - initialization of net_device operations
+ * @netdev: net_device structure
+ *
+ * fills out function pointers in the net_device structure
+ */
+static void gelic_net_setup_netdev_ops(struct net_device *netdev)
+{
+ netdev->open = &gelic_net_open;
+ netdev->stop = &gelic_net_stop;
+ netdev->hard_start_xmit = &gelic_net_xmit;
+ netdev->get_stats = &gelic_net_get_stats;
+ netdev->set_multicast_list = &gelic_net_set_multi;
+ netdev->change_mtu = &gelic_net_change_mtu;
+ /* tx watchdog */
+ netdev->tx_timeout = &gelic_net_tx_timeout;
+ netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
+ /* NAPI */
+ netdev->poll = &gelic_net_poll;
+ netdev->weight = GELIC_NET_NAPI_WEIGHT;
+#ifdef GELIC_NET_ETHTOOL
+ netdev->ethtool_ops = &gelic_net_ethtool_ops;
+#endif
+}
+
+/**
+ * gelic_net_setup_netdev - initialization of net_device
+ * @card: card structure
+ *
+ * Returns 0 on success or <0 on failure
+ *
+ * gelic_net_setup_netdev initializes the net_device structure
+ **/
+static int gelic_net_setup_netdev(struct gelic_net_card *card)
+{
+ struct net_device *netdev = card->netdev;
+ struct sockaddr addr;
+ unsigned int i;
+ int status;
+ u64 v1, v2;
+
+ SET_MODULE_OWNER(netdev);
+ SET_NETDEV_DEV(netdev, &card->dev->core);
+ spin_lock_init(&card->tx_dma_lock);
+
+ card->rx_csum = GELIC_NET_RX_CSUM_DEFAULT;
+
+ gelic_net_setup_netdev_ops(netdev);
+
+ netdev->features = NETIF_F_IP_CSUM;
+
+ status = lv1_net_control(bus_id(card), dev_id(card),
+ GELIC_NET_GET_MAC_ADDRESS,
+ 0, 0, 0, &v1, &v2);
+ if (status || !is_valid_ether_addr((u8 *)&v1)) {
+ dev_info(ctodev(card),
+ "%s:lv1_net_control GET_MAC_ADDR failed %d\n",
+ __func__, status);
+ return -EINVAL;
+ }
+ v1 <<= 16;
+ memcpy(addr.sa_data, &v1, ETH_ALEN);
+ memcpy(netdev->dev_addr, addr.sa_data, ETH_ALEN);
+ dev_info(ctodev(card), "MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+ netdev->dev_addr[0], netdev->dev_addr[1],
+ netdev->dev_addr[2], netdev->dev_addr[3],
+ netdev->dev_addr[4], netdev->dev_addr[5]);
+
+ card->vlan_index = -1; /* no vlan */
+ for (i = 0; i < GELIC_NET_VLAN_MAX; i++) {
+ status = lv1_net_control(bus_id(card), dev_id(card),
+ GELIC_NET_GET_VLAN_ID,
+ i + 1, /* index; one based */
+ 0, 0, &v1, &v2);
+ if (status == GELIC_NET_VLAN_NO_ENTRY) {
+ dev_dbg(ctodev(card),
+ "GELIC_VLAN_ID no entry:%d, VLAN disabled\n",
+ status);
+ card->vlan_id[i] = 0;
+ } else if (status) {
+ dev_dbg(ctodev(card),
+ "%s:GELIC_NET_VLAN_ID faild, status=%d\n",
+ __func__, status);
+ card->vlan_id[i] = 0;
+ } else {
+ card->vlan_id[i] = (u32)v1;
+ dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1);
+ }
+ }
+ if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1])
+ card->vlan_index = GELIC_NET_VLAN_WIRED - 1;
+
+ status = register_netdev(netdev);
+ if (status) {
+ dev_err(ctodev(card), "%s:Couldn't register net_device: %d\n",
+ __func__, status);
+ return status;
+ }
+
+ return 0;
+}
+
+/**
+ * gelic_net_alloc_card - allocates net_device and card structure
+ *
+ * returns the card structure or NULL in case of errors
+ *
+ * the card and net_device structures are linked to each other
+ */
+static struct gelic_net_card *gelic_net_alloc_card(void)
+{
+ struct net_device *netdev;
+ struct gelic_net_card *card;
+ size_t alloc_size;
+
+ alloc_size = sizeof (*card) +
+ sizeof (struct gelic_net_descr) * GELIC_NET_RX_DESCRIPTORS +
+ sizeof (struct gelic_net_descr) * GELIC_NET_TX_DESCRIPTORS;
+ /*
+ * we assume private data is allocated 32 bytes (or more) aligned
+ * so that gelic_net_descr should be 32 bytes aligned.
+ * Current alloc_etherdev() does do it because NETDEV_ALIGN
+ * is 32.
+ * check this assumption here.
+ */
+ BUILD_BUG_ON(NETDEV_ALIGN < 32);
+ BUILD_BUG_ON(offsetof(struct gelic_net_card, irq_status) % 8);
+ BUILD_BUG_ON(offsetof(struct gelic_net_card, descr) % 32);
+
+ netdev = alloc_etherdev(alloc_size);
+ if (!netdev)
+ return NULL;
+
+ card = netdev_priv(netdev);
+ card->netdev = netdev;
+ INIT_WORK(&card->tx_timeout_task, gelic_net_tx_timeout_task);
+ init_waitqueue_head(&card->waitq);
+ atomic_set(&card->tx_timeout_task_counter, 0);
+
+ return card;
+}
+
+/**
+ * ps3_gelic_driver_probe - add a device to the control of this driver
+ */
+static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev)
+{
+ struct gelic_net_card *card = gelic_net_alloc_card();
+ int result;
+
+ if (!card) {
+ dev_info(&dev->core, "gelic_net_alloc_card failed\n");
+ result = -ENOMEM;
+ goto fail_alloc_card;
+ }
+
+ ps3_system_bus_set_driver_data(dev, card);
+ card->dev = dev;
+
+ result = ps3_open_hv_device(dev);
+
+ if (result) {
+ dev_dbg(&dev->core, "ps3_open_hv_device failed\n");
+ goto fail_open;
+ }
+
+ result = ps3_dma_region_create(dev->d_region);
+
+ if (result) {
+ dev_dbg(&dev->core, "ps3_dma_region_create failed(%d)\n",
+ result);
+ BUG_ON("check region type");
+ goto fail_dma_region;
+ }
+
+ result = lv1_net_set_interrupt_status_indicator(bus_id(card),
+ dev_id(card),
+ ps3_mm_phys_to_lpar(__pa(&card->irq_status)),
+ 0);
+
+ if (result) {
+ dev_dbg(&dev->core,
+ "lv1_net_set_interrupt_status_indicator failed: %s\n",
+ ps3_result(result));
+ result = -EIO;
+ goto fail_status_indicator;
+ }
+
+ result = gelic_net_setup_netdev(card);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+ "(%d)\n", __func__, __LINE__, result);
+ goto fail_setup_netdev;
+ }
+
+ return 0;
+
+fail_setup_netdev:
+ lv1_net_set_interrupt_status_indicator(bus_id(card),
+ bus_id(card),
+ 0 , 0);
+fail_status_indicator:
+ ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+ ps3_close_hv_device(dev);
+fail_open:
+ ps3_system_bus_set_driver_data(dev, NULL);
+ free_netdev(card->netdev);
+fail_alloc_card:
+ return result;
+}
+
+/**
+ * ps3_gelic_driver_remove - remove a device from the control of this driver
+ */
+
+static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev)
+{
+ struct gelic_net_card *card = ps3_system_bus_get_driver_data(dev);
+
+ wait_event(card->waitq,
+ atomic_read(&card->tx_timeout_task_counter) == 0);
+
+ lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card),
+ 0 , 0);
+
+ unregister_netdev(card->netdev);
+ free_netdev(card->netdev);
+
+ ps3_system_bus_set_driver_data(dev, NULL);
+
+ ps3_dma_region_free(dev->d_region);
+
+ ps3_close_hv_device(dev);
+
+ return 0;
+}
+
+static struct ps3_system_bus_driver ps3_gelic_driver = {
+ .match_id = PS3_MATCH_ID_GELIC,
+ .probe = ps3_gelic_driver_probe,
+ .remove = ps3_gelic_driver_remove,
+ .shutdown = ps3_gelic_driver_remove,
+ .core.name = "ps3_gelic_driver",
+ .core.owner = THIS_MODULE,
+};
+
+static int __init ps3_gelic_driver_init (void)
+{
+ return firmware_has_feature(FW_FEATURE_PS3_LV1)
+ ? ps3_system_bus_driver_register(&ps3_gelic_driver)
+ : -ENODEV;
+}
+
+static void __exit ps3_gelic_driver_exit (void)
+{
+ ps3_system_bus_driver_unregister(&ps3_gelic_driver);
+}
+
+module_init (ps3_gelic_driver_init);
+module_exit (ps3_gelic_driver_exit);
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_GELIC);
+
diff --git a/drivers/net/ps3_gelic_net.h b/drivers/net/ps3_gelic_net.h
new file mode 100644
index 00000000000..5e1c28654e1
--- /dev/null
+++ b/drivers/net/ps3_gelic_net.h
@@ -0,0 +1,239 @@
+/*
+ * PS3 Platfom gelic network driver.
+ *
+ * Copyright (C) 2007 Sony Computer Entertainment Inc.
+ * Copyright 2006, 2007 Sony Corporation.
+ *
+ * This file is based on: spider_net.h
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.com>
+ * Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _GELIC_NET_H
+#define _GELIC_NET_H
+
+#define GELIC_NET_DRV_NAME "Gelic Network Driver"
+#define GELIC_NET_DRV_VERSION "1.0"
+
+#define GELIC_NET_ETHTOOL /* use ethtool */
+
+/* ioctl */
+#define GELIC_NET_GET_MODE (SIOCDEVPRIVATE + 0)
+#define GELIC_NET_SET_MODE (SIOCDEVPRIVATE + 1)
+
+/* descriptors */
+#define GELIC_NET_RX_DESCRIPTORS 128 /* num of descriptors */
+#define GELIC_NET_TX_DESCRIPTORS 128 /* num of descriptors */
+
+#define GELIC_NET_MAX_MTU 2308
+#define GELIC_NET_MIN_MTU 64
+#define GELIC_NET_RXBUF_ALIGN 128
+#define GELIC_NET_RX_CSUM_DEFAULT 1 /* hw chksum */
+#define GELIC_NET_WATCHDOG_TIMEOUT 5*HZ
+#define GELIC_NET_NAPI_WEIGHT (GELIC_NET_RX_DESCRIPTORS)
+#define GELIC_NET_BROADCAST_ADDR 0xffffffffffffL
+#define GELIC_NET_VLAN_POS (VLAN_ETH_ALEN * 2)
+#define GELIC_NET_VLAN_MAX 4
+#define GELIC_NET_MC_COUNT_MAX 32 /* multicast address list */
+
+enum gelic_net_int0_status {
+ GELIC_NET_GDTDCEINT = 24,
+ GELIC_NET_GRFANMINT = 28,
+};
+
+/* GHIINT1STS bits */
+enum gelic_net_int1_status {
+ GELIC_NET_GDADCEINT = 14,
+};
+
+/* interrupt mask */
+#define GELIC_NET_TXINT (1L << (GELIC_NET_GDTDCEINT + 32))
+
+#define GELIC_NET_RXINT0 (1L << (GELIC_NET_GRFANMINT + 32))
+#define GELIC_NET_RXINT1 (1L << GELIC_NET_GDADCEINT)
+#define GELIC_NET_RXINT (GELIC_NET_RXINT0 | GELIC_NET_RXINT1)
+
+ /* RX descriptor data_status bits */
+#define GELIC_NET_RXDMADU 0x80000000 /* destination MAC addr unknown */
+#define GELIC_NET_RXLSTFBF 0x40000000 /* last frame buffer */
+#define GELIC_NET_RXIPCHK 0x20000000 /* IP checksum performed */
+#define GELIC_NET_RXTCPCHK 0x10000000 /* TCP/UDP checksup performed */
+#define GELIC_NET_RXIPSPKT 0x08000000 /* IPsec packet */
+#define GELIC_NET_RXIPSAHPRT 0x04000000 /* IPsec AH protocol performed */
+#define GELIC_NET_RXIPSESPPRT 0x02000000 /* IPsec ESP protocol performed */
+#define GELIC_NET_RXSESPAH 0x01000000 /*
+ * IPsec ESP protocol auth
+ * performed
+ */
+
+#define GELIC_NET_RXWTPKT 0x00C00000 /*
+ * wakeup trigger packet
+ * 01: Magic Packet (TM)
+ * 10: ARP packet
+ * 11: Multicast MAC addr
+ */
+#define GELIC_NET_RXVLNPKT 0x00200000 /* VLAN packet */
+/* bit 20..16 reserved */
+#define GELIC_NET_RXRECNUM 0x0000ff00 /* reception receipt number */
+/* bit 7..0 reserved */
+
+#define GELIC_NET_TXDESC_TAIL 0
+#define GELIC_NET_DATA_STATUS_CHK_MASK (GELIC_NET_RXIPCHK | GELIC_NET_RXTCPCHK)
+
+/* RX descriptor data_error bits */
+/* bit 31 reserved */
+#define GELIC_NET_RXALNERR 0x40000000 /* alignement error 10/100M */
+#define GELIC_NET_RXOVERERR 0x20000000 /* oversize error */
+#define GELIC_NET_RXRNTERR 0x10000000 /* Runt error */
+#define GELIC_NET_RXIPCHKERR 0x08000000 /* IP checksum error */
+#define GELIC_NET_RXTCPCHKERR 0x04000000 /* TCP/UDP checksum error */
+#define GELIC_NET_RXUMCHSP 0x02000000 /* unmatched sp on sp */
+#define GELIC_NET_RXUMCHSPI 0x01000000 /* unmatched SPI on SAD */
+#define GELIC_NET_RXUMCHSAD 0x00800000 /* unmatched SAD */
+#define GELIC_NET_RXIPSAHERR 0x00400000 /* auth error on AH protocol
+ * processing */
+#define GELIC_NET_RXIPSESPAHERR 0x00200000 /* auth error on ESP protocol
+ * processing */
+#define GELIC_NET_RXDRPPKT 0x00100000 /* drop packet */
+#define GELIC_NET_RXIPFMTERR 0x00080000 /* IP packet format error */
+/* bit 18 reserved */
+#define GELIC_NET_RXDATAERR 0x00020000 /* IP packet format error */
+#define GELIC_NET_RXCALERR 0x00010000 /* cariier extension length
+ * error */
+#define GELIC_NET_RXCREXERR 0x00008000 /* carrier extention error */
+#define GELIC_NET_RXMLTCST 0x00004000 /* multicast address frame */
+/* bit 13..0 reserved */
+#define GELIC_NET_DATA_ERROR_CHK_MASK \
+ (GELIC_NET_RXIPCHKERR | GELIC_NET_RXTCPCHKERR)
+
+
+/* tx descriptor command and status */
+#define GELIC_NET_DMAC_CMDSTAT_NOCS 0xa0080000 /* middle of frame */
+#define GELIC_NET_DMAC_CMDSTAT_TCPCS 0xa00a0000
+#define GELIC_NET_DMAC_CMDSTAT_UDPCS 0xa00b0000
+#define GELIC_NET_DMAC_CMDSTAT_END_FRAME 0x00040000 /* end of frame */
+
+#define GELIC_NET_DMAC_CMDSTAT_RXDCEIS 0x00000002 /* descriptor chain end
+ * interrupt status */
+
+#define GELIC_NET_DMAC_CMDSTAT_CHAIN_END 0x00000002 /* RXDCEIS:DMA stopped */
+#define GELIC_NET_DMAC_CMDSTAT_NOT_IN_USE 0xb0000000
+#define GELIC_NET_DESCR_IND_PROC_SHIFT 28
+#define GELIC_NET_DESCR_IND_PROC_MASKO 0x0fffffff
+
+
+enum gelic_net_descr_status {
+ GELIC_NET_DESCR_COMPLETE = 0x00, /* used in rx and tx */
+ GELIC_NET_DESCR_RESPONSE_ERROR = 0x01, /* used in rx and tx */
+ GELIC_NET_DESCR_PROTECTION_ERROR = 0x02, /* used in rx and tx */
+ GELIC_NET_DESCR_FRAME_END = 0x04, /* used in rx */
+ GELIC_NET_DESCR_FORCE_END = 0x05, /* used in rx and tx */
+ GELIC_NET_DESCR_CARDOWNED = 0x0a, /* used in rx and tx */
+ GELIC_NET_DESCR_NOT_IN_USE /* any other value */
+};
+/* for lv1_net_control */
+#define GELIC_NET_GET_MAC_ADDRESS 0x0000000000000001
+#define GELIC_NET_GET_ETH_PORT_STATUS 0x0000000000000002
+#define GELIC_NET_SET_NEGOTIATION_MODE 0x0000000000000003
+#define GELIC_NET_GET_VLAN_ID 0x0000000000000004
+
+#define GELIC_NET_LINK_UP 0x0000000000000001
+#define GELIC_NET_FULL_DUPLEX 0x0000000000000002
+#define GELIC_NET_AUTO_NEG 0x0000000000000004
+#define GELIC_NET_SPEED_10 0x0000000000000010
+#define GELIC_NET_SPEED_100 0x0000000000000020
+#define GELIC_NET_SPEED_1000 0x0000000000000040
+
+#define GELIC_NET_VLAN_ALL 0x0000000000000001
+#define GELIC_NET_VLAN_WIRED 0x0000000000000002
+#define GELIC_NET_VLAN_WIRELESS 0x0000000000000003
+#define GELIC_NET_VLAN_PSP 0x0000000000000004
+#define GELIC_NET_VLAN_PORT0 0x0000000000000010
+#define GELIC_NET_VLAN_PORT1 0x0000000000000011
+#define GELIC_NET_VLAN_PORT2 0x0000000000000012
+#define GELIC_NET_VLAN_DAEMON_CLIENT_BSS 0x0000000000000013
+#define GELIC_NET_VLAN_LIBERO_CLIENT_BSS 0x0000000000000014
+#define GELIC_NET_VLAN_NO_ENTRY -6
+
+#define GELIC_NET_PORT 2 /* for port status */
+
+/* size of hardware part of gelic descriptor */
+#define GELIC_NET_DESCR_SIZE (32)
+struct gelic_net_descr {
+ /* as defined by the hardware */
+ u32 buf_addr;
+ u32 buf_size;
+ u32 next_descr_addr;
+ u32 dmac_cmd_status;
+ u32 result_size;
+ u32 valid_size; /* all zeroes for tx */
+ u32 data_status;
+ u32 data_error; /* all zeroes for tx */
+
+ /* used in the driver */
+ struct sk_buff *skb;
+ dma_addr_t bus_addr;
+ struct gelic_net_descr *next;
+ struct gelic_net_descr *prev;
+ struct vlan_ethhdr vlan;
+} __attribute__((aligned(32)));
+
+struct gelic_net_descr_chain {
+ /* we walk from tail to head */
+ struct gelic_net_descr *head;
+ struct gelic_net_descr *tail;
+};
+
+struct gelic_net_card {
+ struct net_device *netdev;
+ /*
+ * hypervisor requires irq_status should be
+ * 8 bytes aligned, but u64 member is
+ * always disposed in that manner
+ */
+ u64 irq_status;
+ u64 ghiintmask;
+
+ struct ps3_system_bus_device *dev;
+ u32 vlan_id[GELIC_NET_VLAN_MAX];
+ int vlan_index;
+
+ struct gelic_net_descr_chain tx_chain;
+ struct gelic_net_descr_chain rx_chain;
+ /* gurad dmac descriptor chain*/
+ spinlock_t chain_lock;
+
+ struct net_device_stats netdev_stats;
+ int rx_csum;
+ /* guard tx_dma_progress */
+ spinlock_t tx_dma_lock;
+ int tx_dma_progress;
+
+ struct work_struct tx_timeout_task;
+ atomic_t tx_timeout_task_counter;
+ wait_queue_head_t waitq;
+
+ struct gelic_net_descr *tx_top, *rx_top;
+ struct gelic_net_descr descr[0];
+};
+
+
+extern unsigned long p_to_lp(long pa);
+
+#endif /* _GELIC_NET_H */
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index d8766c0e825..8be8be451ad 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2433,37 +2433,22 @@ static int ql_get_seg_count(struct ql3_adapter *qdev,
return -1;
}
-static void ql_hw_csum_setup(struct sk_buff *skb,
+static void ql_hw_csum_setup(const struct sk_buff *skb,
struct ob_mac_iocb_req *mac_iocb_ptr)
{
- struct ethhdr *eth;
- struct iphdr *ip = NULL;
- u8 offset = ETH_HLEN;
+ const struct iphdr *ip = ip_hdr(skb);
- eth = (struct ethhdr *)(skb->data);
+ mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb);
+ mac_iocb_ptr->ip_hdr_len = ip->ihl;
- if (eth->h_proto == __constant_htons(ETH_P_IP)) {
- ip = (struct iphdr *)&skb->data[ETH_HLEN];
- } else if (eth->h_proto == htons(ETH_P_8021Q) &&
- ((struct vlan_ethhdr *)skb->data)->
- h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) {
- ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN];
- offset = VLAN_ETH_HLEN;
- }
-
- if (ip) {
- if (ip->protocol == IPPROTO_TCP) {
- mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
+ if (ip->protocol == IPPROTO_TCP) {
+ mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
OB_3032MAC_IOCB_REQ_IC;
- mac_iocb_ptr->ip_hdr_off = offset;
- mac_iocb_ptr->ip_hdr_len = ip->ihl;
- } else if (ip->protocol == IPPROTO_UDP) {
- mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
+ } else {
+ mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
OB_3032MAC_IOCB_REQ_IC;
- mac_iocb_ptr->ip_hdr_off = offset;
- mac_iocb_ptr->ip_hdr_len = ip->ihl;
- }
}
+
}
/*
@@ -4044,7 +4029,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
if (pci_using_dac)
ndev->features |= NETIF_F_HIGHDMA;
if (qdev->device_id == QL3032_DEVICE_ID)
- ndev->features |= (NETIF_F_HW_CSUM | NETIF_F_SG);
+ ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
qdev->mem_map_registers =
ioremap_nocache(pci_resource_start(pdev, 1),
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 45876a854f0..982a9010c7a 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1,53 +1,11 @@
/*
-=========================================================================
- r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver for Linux kernel 2.4.x.
- --------------------------------------------------------------------
-
- History:
- Feb 4 2002 - created initially by ShuChen <shuchen@realtek.com.tw>.
- May 20 2002 - Add link status force-mode and TBI mode support.
- 2004 - Massive updates. See kernel SCM system for details.
-=========================================================================
- 1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
- Command: 'insmod r8169 media = SET_MEDIA'
- Ex: 'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
-
- SET_MEDIA can be:
- _10_Half = 0x01
- _10_Full = 0x02
- _100_Half = 0x04
- _100_Full = 0x08
- _1000_Full = 0x10
-
- 2. Support TBI mode.
-=========================================================================
-VERSION 1.1 <2002/10/4>
-
- The bit4:0 of MII register 4 is called "selector field", and have to be
- 00001b to indicate support of IEEE std 802.3 during NWay process of
- exchanging Link Code Word (FLP).
-
-VERSION 1.2 <2002/11/30>
-
- - Large style cleanup
- - Use ether_crc in stock kernel (linux/crc32.h)
- - Copy mc_filter setup code from 8139cp
- (includes an optimization, and avoids set_bit use)
-
-VERSION 1.6LK <2004/04/14>
-
- - Merge of Realtek's version 1.6
- - Conversion to DMA API
- - Suspend/resume
- - Endianness
- - Misc Rx/Tx bugs
-
-VERSION 2.2LK <2005/01/25>
-
- - RX csum, TX csum/SG, TSO
- - VLAN
- - baby (< 7200) Jumbo frames support
- - Merge of Realtek's version 2.2 (new phy)
+ * r8169.c: RealTek 8169/8168/8101 ethernet driver.
+ *
+ * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
+ * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
+ * Copyright (c) a lot of people too. Please respect their work.
+ *
+ * See MAINTAINERS file for support contact information.
*/
#include <linux/module.h>
@@ -108,11 +66,6 @@ VERSION 2.2LK <2005/01/25>
#define rtl8169_rx_quota(count, quota) count
#endif
-/* media options */
-#define MAX_UNITS 8
-static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-static int num_media = 0;
-
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static const int max_interrupt_work = 20;
@@ -126,7 +79,7 @@ static const int multicast_filter_limit = 32;
#define RX_FIFO_THRESH 7 /* 7 means NO threshold, Rx buffer level before first PCI xfer. */
#define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */
-#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
+#define EarlyTxThld 0x3F /* 0x3F means NO early transmit */
#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */
#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
@@ -151,16 +104,17 @@ static const int multicast_filter_limit = 32;
#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
enum mac_version {
- RTL_GIGA_MAC_VER_01 = 0x00,
- RTL_GIGA_MAC_VER_02 = 0x01,
- RTL_GIGA_MAC_VER_03 = 0x02,
- RTL_GIGA_MAC_VER_04 = 0x03,
- RTL_GIGA_MAC_VER_05 = 0x04,
- RTL_GIGA_MAC_VER_11 = 0x0b,
- RTL_GIGA_MAC_VER_12 = 0x0c,
- RTL_GIGA_MAC_VER_13 = 0x0d,
- RTL_GIGA_MAC_VER_14 = 0x0e,
- RTL_GIGA_MAC_VER_15 = 0x0f
+ RTL_GIGA_MAC_VER_01 = 0x01, // 8169
+ RTL_GIGA_MAC_VER_02 = 0x02, // 8169S
+ RTL_GIGA_MAC_VER_03 = 0x03, // 8110S
+ RTL_GIGA_MAC_VER_04 = 0x04, // 8169SB
+ RTL_GIGA_MAC_VER_05 = 0x05, // 8110SCd
+ RTL_GIGA_MAC_VER_06 = 0x06, // 8110SCe
+ RTL_GIGA_MAC_VER_11 = 0x0b, // 8168Bb
+ RTL_GIGA_MAC_VER_12 = 0x0c, // 8168Be 8168Bf
+ RTL_GIGA_MAC_VER_13 = 0x0d, // 8101Eb 8101Ec
+ RTL_GIGA_MAC_VER_14 = 0x0e, // 8101
+ RTL_GIGA_MAC_VER_15 = 0x0f // 8101
};
enum phy_version {
@@ -180,11 +134,12 @@ static const struct {
u8 mac_version;
u32 RxConfigMask; /* Clears the bits supported by this chip */
} rtl_chip_info[] = {
- _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880),
- _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_02, 0xff7e1880),
- _R("RTL8169s/8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880),
- _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880),
- _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880),
+ _R("RTL8169", RTL_GIGA_MAC_VER_01, 0xff7e1880), // 8169
+ _R("RTL8169s", RTL_GIGA_MAC_VER_02, 0xff7e1880), // 8169S
+ _R("RTL8110s", RTL_GIGA_MAC_VER_03, 0xff7e1880), // 8110S
+ _R("RTL8169sb/8110sb", RTL_GIGA_MAC_VER_04, 0xff7e1880), // 8169SB
+ _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_05, 0xff7e1880), // 8110SCd
+ _R("RTL8169sc/8110sc", RTL_GIGA_MAC_VER_06, 0xff7e1880), // 8110SCe
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_11, 0xff7e1880), // PCI-E
_R("RTL8168b/8111b", RTL_GIGA_MAC_VER_12, 0xff7e1880), // PCI-E
_R("RTL8101e", RTL_GIGA_MAC_VER_13, 0xff7e1880), // PCI-E 8139
@@ -199,20 +154,15 @@ enum cfg_version {
RTL_CFG_2
};
-static const struct {
- unsigned int region;
- unsigned int align;
-} rtl_cfg_info[] = {
- [RTL_CFG_0] = { 1, NET_IP_ALIGN },
- [RTL_CFG_1] = { 2, NET_IP_ALIGN },
- [RTL_CFG_2] = { 2, 8 }
-};
+static void rtl_hw_start_8169(struct net_device *);
+static void rtl_hw_start_8168(struct net_device *);
+static void rtl_hw_start_8101(struct net_device *);
static struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_2 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(0x1259, 0xc107), 0, 0, RTL_CFG_0 },
@@ -230,62 +180,63 @@ static struct {
u32 msg_enable;
} debug = { -1 };
-enum RTL8169_registers {
- MAC0 = 0, /* Ethernet hardware address. */
- MAR0 = 8, /* Multicast filter. */
- CounterAddrLow = 0x10,
- CounterAddrHigh = 0x14,
- TxDescStartAddrLow = 0x20,
- TxDescStartAddrHigh = 0x24,
- TxHDescStartAddrLow = 0x28,
- TxHDescStartAddrHigh = 0x2c,
- FLASH = 0x30,
- ERSR = 0x36,
- ChipCmd = 0x37,
- TxPoll = 0x38,
- IntrMask = 0x3C,
- IntrStatus = 0x3E,
- TxConfig = 0x40,
- RxConfig = 0x44,
- RxMissed = 0x4C,
- Cfg9346 = 0x50,
- Config0 = 0x51,
- Config1 = 0x52,
- Config2 = 0x53,
- Config3 = 0x54,
- Config4 = 0x55,
- Config5 = 0x56,
- MultiIntr = 0x5C,
- PHYAR = 0x60,
- TBICSR = 0x64,
- TBI_ANAR = 0x68,
- TBI_LPAR = 0x6A,
- PHYstatus = 0x6C,
- RxMaxSize = 0xDA,
- CPlusCmd = 0xE0,
- IntrMitigate = 0xE2,
- RxDescAddrLow = 0xE4,
- RxDescAddrHigh = 0xE8,
- EarlyTxThres = 0xEC,
- FuncEvent = 0xF0,
- FuncEventMask = 0xF4,
- FuncPresetState = 0xF8,
- FuncForceEvent = 0xFC,
+enum rtl_registers {
+ MAC0 = 0, /* Ethernet hardware address. */
+ MAC4 = 4,
+ MAR0 = 8, /* Multicast filter. */
+ CounterAddrLow = 0x10,
+ CounterAddrHigh = 0x14,
+ TxDescStartAddrLow = 0x20,
+ TxDescStartAddrHigh = 0x24,
+ TxHDescStartAddrLow = 0x28,
+ TxHDescStartAddrHigh = 0x2c,
+ FLASH = 0x30,
+ ERSR = 0x36,
+ ChipCmd = 0x37,
+ TxPoll = 0x38,
+ IntrMask = 0x3c,
+ IntrStatus = 0x3e,
+ TxConfig = 0x40,
+ RxConfig = 0x44,
+ RxMissed = 0x4c,
+ Cfg9346 = 0x50,
+ Config0 = 0x51,
+ Config1 = 0x52,
+ Config2 = 0x53,
+ Config3 = 0x54,
+ Config4 = 0x55,
+ Config5 = 0x56,
+ MultiIntr = 0x5c,
+ PHYAR = 0x60,
+ TBICSR = 0x64,
+ TBI_ANAR = 0x68,
+ TBI_LPAR = 0x6a,
+ PHYstatus = 0x6c,
+ RxMaxSize = 0xda,
+ CPlusCmd = 0xe0,
+ IntrMitigate = 0xe2,
+ RxDescAddrLow = 0xe4,
+ RxDescAddrHigh = 0xe8,
+ EarlyTxThres = 0xec,
+ FuncEvent = 0xf0,
+ FuncEventMask = 0xf4,
+ FuncPresetState = 0xf8,
+ FuncForceEvent = 0xfc,
};
-enum RTL8169_register_content {
+enum rtl_register_content {
/* InterruptStatusBits */
- SYSErr = 0x8000,
- PCSTimeout = 0x4000,
- SWInt = 0x0100,
- TxDescUnavail = 0x80,
- RxFIFOOver = 0x40,
- LinkChg = 0x20,
- RxOverflow = 0x10,
- TxErr = 0x08,
- TxOK = 0x04,
- RxErr = 0x02,
- RxOK = 0x01,
+ SYSErr = 0x8000,
+ PCSTimeout = 0x4000,
+ SWInt = 0x0100,
+ TxDescUnavail = 0x0080,
+ RxFIFOOver = 0x0040,
+ LinkChg = 0x0020,
+ RxOverflow = 0x0010,
+ TxErr = 0x0008,
+ TxOK = 0x0004,
+ RxErr = 0x0002,
+ RxOK = 0x0001,
/* RxStatusDesc */
RxFOVF = (1 << 23),
@@ -295,26 +246,31 @@ enum RTL8169_register_content {
RxCRC = (1 << 19),
/* ChipCmdBits */
- CmdReset = 0x10,
- CmdRxEnb = 0x08,
- CmdTxEnb = 0x04,
- RxBufEmpty = 0x01,
+ CmdReset = 0x10,
+ CmdRxEnb = 0x08,
+ CmdTxEnb = 0x04,
+ RxBufEmpty = 0x01,
+
+ /* TXPoll register p.5 */
+ HPQ = 0x80, /* Poll cmd on the high prio queue */
+ NPQ = 0x40, /* Poll cmd on the low prio queue */
+ FSWInt = 0x01, /* Forced software interrupt */
/* Cfg9346Bits */
- Cfg9346_Lock = 0x00,
- Cfg9346_Unlock = 0xC0,
+ Cfg9346_Lock = 0x00,
+ Cfg9346_Unlock = 0xc0,
/* rx_mode_bits */
- AcceptErr = 0x20,
- AcceptRunt = 0x10,
- AcceptBroadcast = 0x08,
- AcceptMulticast = 0x04,
- AcceptMyPhys = 0x02,
- AcceptAllPhys = 0x01,
+ AcceptErr = 0x20,
+ AcceptRunt = 0x10,
+ AcceptBroadcast = 0x08,
+ AcceptMulticast = 0x04,
+ AcceptMyPhys = 0x02,
+ AcceptAllPhys = 0x01,
/* RxConfigBits */
- RxCfgFIFOShift = 13,
- RxCfgDMAShift = 8,
+ RxCfgFIFOShift = 13,
+ RxCfgDMAShift = 8,
/* TxConfigBits */
TxInterFrameGapShift = 24,
@@ -323,6 +279,10 @@ enum RTL8169_register_content {
/* Config1 register p.24 */
PMEnable = (1 << 0), /* Power Management Enable */
+ /* Config2 register p. 25 */
+ PCI_Clock_66MHz = 0x01,
+ PCI_Clock_33MHz = 0x00,
+
/* Config3 register p.25 */
MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */
LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */
@@ -343,36 +303,34 @@ enum RTL8169_register_content {
TBINwComplete = 0x01000000,
/* CPlusCmd p.31 */
+ PktCntrDisable = (1 << 7), // 8168
RxVlan = (1 << 6),
RxChkSum = (1 << 5),
PCIDAC = (1 << 4),
PCIMulRW = (1 << 3),
+ INTT_0 = 0x0000, // 8168
+ INTT_1 = 0x0001, // 8168
+ INTT_2 = 0x0002, // 8168
+ INTT_3 = 0x0003, // 8168
/* rtl8169_PHYstatus */
- TBI_Enable = 0x80,
- TxFlowCtrl = 0x40,
- RxFlowCtrl = 0x20,
- _1000bpsF = 0x10,
- _100bps = 0x08,
- _10bps = 0x04,
- LinkStatus = 0x02,
- FullDup = 0x01,
-
- /* _MediaType */
- _10_Half = 0x01,
- _10_Full = 0x02,
- _100_Half = 0x04,
- _100_Full = 0x08,
- _1000_Full = 0x10,
+ TBI_Enable = 0x80,
+ TxFlowCtrl = 0x40,
+ RxFlowCtrl = 0x20,
+ _1000bpsF = 0x10,
+ _100bps = 0x08,
+ _10bps = 0x04,
+ LinkStatus = 0x02,
+ FullDup = 0x01,
/* _TBICSRBit */
- TBILinkOK = 0x02000000,
+ TBILinkOK = 0x02000000,
/* DumpCounterCommand */
- CounterDump = 0x8,
+ CounterDump = 0x8,
};
-enum _DescStatusBit {
+enum desc_status_bit {
DescOwn = (1 << 31), /* Descriptor is owned by NIC */
RingEnd = (1 << 30), /* End of descriptor ring */
FirstFrag = (1 << 29), /* First segment of a packet */
@@ -405,15 +363,15 @@ enum _DescStatusBit {
#define RsvdMask 0x3fffc000
struct TxDesc {
- u32 opts1;
- u32 opts2;
- u64 addr;
+ __le32 opts1;
+ __le32 opts2;
+ __le64 addr;
};
struct RxDesc {
- u32 opts1;
- u32 opts2;
- u64 addr;
+ __le32 opts1;
+ __le32 opts2;
+ __le64 addr;
};
struct ring_info {
@@ -446,6 +404,8 @@ struct rtl8169_private {
unsigned rx_buf_sz;
struct timer_list timer;
u16 cp_cmd;
+ u16 intr_event;
+ u16 napi_event;
u16 intr_mask;
int phy_auto_nego_reg;
int phy_1000_ctrl_reg;
@@ -455,6 +415,7 @@ struct rtl8169_private {
int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
void (*get_settings)(struct net_device *, struct ethtool_cmd *);
void (*phy_reset_enable)(void __iomem *);
+ void (*hw_start)(struct net_device *);
unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *);
struct delayed_work task;
@@ -463,8 +424,6 @@ struct rtl8169_private {
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
-module_param_array(media, int, &num_media, 0);
-MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
module_param(rx_copybreak, int, 0);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
module_param(use_dac, int, 0);
@@ -478,9 +437,9 @@ static int rtl8169_open(struct net_device *dev);
static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance);
static int rtl8169_init_ring(struct net_device *dev);
-static void rtl8169_hw_start(struct net_device *dev);
+static void rtl_hw_start(struct net_device *dev);
static int rtl8169_close(struct net_device *dev);
-static void rtl8169_set_rx_mode(struct net_device *dev);
+static void rtl_set_rx_mode(struct net_device *dev);
static void rtl8169_tx_timeout(struct net_device *dev);
static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
@@ -493,35 +452,37 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp);
static int rtl8169_poll(struct net_device *dev, int *budget);
#endif
-static const u16 rtl8169_intr_mask =
- SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
-static const u16 rtl8169_napi_event =
- RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
static const unsigned int rtl8169_rx_config =
(RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
-static void mdio_write(void __iomem *ioaddr, int RegAddr, int value)
+static void mdio_write(void __iomem *ioaddr, int reg_addr, int value)
{
int i;
- RTL_W32(PHYAR, 0x80000000 | (RegAddr & 0xFF) << 16 | value);
+ RTL_W32(PHYAR, 0x80000000 | (reg_addr & 0xFF) << 16 | value);
for (i = 20; i > 0; i--) {
- /* Check if the RTL8169 has completed writing to the specified MII register */
+ /*
+ * Check if the RTL8169 has completed writing to the specified
+ * MII register.
+ */
if (!(RTL_R32(PHYAR) & 0x80000000))
break;
udelay(25);
}
}
-static int mdio_read(void __iomem *ioaddr, int RegAddr)
+static int mdio_read(void __iomem *ioaddr, int reg_addr)
{
int i, value = -1;
- RTL_W32(PHYAR, 0x0 | (RegAddr & 0xFF) << 16);
+ RTL_W32(PHYAR, 0x0 | (reg_addr & 0xFF) << 16);
for (i = 20; i > 0; i--) {
- /* Check if the RTL8169 has completed retrieving data from the specified MII register */
+ /*
+ * Check if the RTL8169 has completed retrieving data from
+ * the specified MII register.
+ */
if (RTL_R32(PHYAR) & 0x80000000) {
value = (int) (RTL_R32(PHYAR) & 0xFFFF);
break;
@@ -579,7 +540,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
}
static void rtl8169_check_link_status(struct net_device *dev,
- struct rtl8169_private *tp, void __iomem *ioaddr)
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned long flags;
@@ -596,38 +558,6 @@ static void rtl8169_check_link_status(struct net_device *dev,
spin_unlock_irqrestore(&tp->lock, flags);
}
-static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
-{
- struct {
- u16 speed;
- u8 duplex;
- u8 autoneg;
- u8 media;
- } link_settings[] = {
- { SPEED_10, DUPLEX_HALF, AUTONEG_DISABLE, _10_Half },
- { SPEED_10, DUPLEX_FULL, AUTONEG_DISABLE, _10_Full },
- { SPEED_100, DUPLEX_HALF, AUTONEG_DISABLE, _100_Half },
- { SPEED_100, DUPLEX_FULL, AUTONEG_DISABLE, _100_Full },
- { SPEED_1000, DUPLEX_FULL, AUTONEG_DISABLE, _1000_Full },
- /* Make TBI happy */
- { SPEED_1000, DUPLEX_FULL, AUTONEG_ENABLE, 0xff }
- }, *p;
- unsigned char option;
-
- option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
-
- if ((option != 0xff) && !idx && netif_msg_drv(&debug))
- printk(KERN_WARNING PFX "media option is deprecated.\n");
-
- for (p = link_settings; p->media != 0xff; p++) {
- if (p->media == option)
- break;
- }
- *autoneg = p->autoneg;
- *speed = p->speed;
- *duplex = p->duplex;
-}
-
static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -667,7 +597,7 @@ static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- int i;
+ unsigned int i;
static struct {
u32 opt;
u16 reg;
@@ -886,16 +816,6 @@ static void rtl8169_vlan_rx_register(struct net_device *dev,
spin_unlock_irqrestore(&tp->lock, flags);
}
-static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct rtl8169_private *tp = netdev_priv(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&tp->lock, flags);
- vlan_group_set_device(tp->vlgrp, vid, NULL);
- spin_unlock_irqrestore(&tp->lock, flags);
-}
-
static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
struct sk_buff *skb)
{
@@ -903,8 +823,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
int ret;
if (tp->vlgrp && (opts2 & RxVlanTag)) {
- rtl8169_rx_hwaccel_skb(skb, tp->vlgrp,
- swab16(opts2 & 0xffff));
+ rtl8169_rx_hwaccel_skb(skb, tp->vlgrp, swab16(opts2 & 0xffff));
ret = 0;
} else
ret = -1;
@@ -1125,7 +1044,6 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
}
}
-
static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
@@ -1151,8 +1069,8 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
.get_perm_addr = ethtool_op_get_perm_addr,
};
-static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
- int bitval)
+static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg,
+ int bitnum, int bitval)
{
int val;
@@ -1162,8 +1080,20 @@ static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum
mdio_write(ioaddr, reg, val & 0xffff);
}
-static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_mac_version(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
+ /*
+ * The driver currently handles the 8168Bf and the 8168Be identically
+ * but they can be identified more specifically through the test below
+ * if needed:
+ *
+ * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
+ *
+ * Same thing for the 8101Eb and the 8101Ec:
+ *
+ * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
+ */
const struct {
u32 mask;
int mac_version;
@@ -1173,6 +1103,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
{ 0x34000000, RTL_GIGA_MAC_VER_13 },
{ 0x30800000, RTL_GIGA_MAC_VER_14 },
{ 0x30000000, RTL_GIGA_MAC_VER_11 },
+ { 0x98000000, RTL_GIGA_MAC_VER_06 },
{ 0x18000000, RTL_GIGA_MAC_VER_05 },
{ 0x10000000, RTL_GIGA_MAC_VER_04 },
{ 0x04000000, RTL_GIGA_MAC_VER_03 },
@@ -1181,7 +1112,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp, void __iomem *io
}, *p = mac_info;
u32 reg;
- reg = RTL_R32(TxConfig) & 0x7c800000;
+ reg = RTL_R32(TxConfig) & 0xfc800000;
while ((reg & p->mask) != p->mask)
p++;
tp->mac_version = p->mac_version;
@@ -1192,7 +1123,8 @@ static void rtl8169_print_mac_version(struct rtl8169_private *tp)
dprintk("mac_version = 0x%02x\n", tp->mac_version);
}
-static void rtl8169_get_phy_version(struct rtl8169_private *tp, void __iomem *ioaddr)
+static void rtl8169_get_phy_version(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
const struct {
u16 mask;
@@ -1269,7 +1201,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
0xbf00 } //w 0 15 0 bf00
}
}, *p = phy_magic;
- int i;
+ unsigned int i;
rtl8169_print_mac_version(tp);
rtl8169_print_phy_version(tp);
@@ -1403,7 +1335,7 @@ static void rtl8169_phy_reset(struct net_device *dev,
struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- int i;
+ unsigned int i;
tp->phy_reset_enable(ioaddr);
for (i = 0; i < 100; i++) {
@@ -1418,21 +1350,16 @@ static void rtl8169_phy_reset(struct net_device *dev,
static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
- static int board_idx = -1;
- u8 autoneg, duplex;
- u16 speed;
-
- board_idx++;
rtl8169_hw_phy_config(dev);
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
RTL_W8(0x82, 0x01);
- if (tp->mac_version < RTL_GIGA_MAC_VER_03) {
- dprintk("Set PCI Latency=0x40\n");
- pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
- }
+ pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
+
+ if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
+ pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
if (tp->mac_version == RTL_GIGA_MAC_VER_02) {
dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
@@ -1441,16 +1368,52 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
}
- rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
-
rtl8169_phy_reset(dev, tp);
- rtl8169_set_speed(dev, autoneg, speed, duplex);
+ /*
+ * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
+ * only 8101. Don't panic.
+ */
+ rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
}
+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);
+
+ spin_lock_irq(&tp->lock);
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+ RTL_W32(MAC0, low);
+ RTL_W32(MAC4, high);
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ spin_unlock_irq(&tp->lock);
+}
+
+static int rtl_set_mac_address(struct net_device *dev, void *p)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ rtl_rar_set(tp, dev->dev_addr);
+
+ return 0;
+}
+
static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct rtl8169_private *tp = netdev_priv(dev);
@@ -1477,15 +1440,49 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EOPNOTSUPP;
}
+static const struct rtl_cfg_info {
+ void (*hw_start)(struct net_device *);
+ unsigned int region;
+ unsigned int align;
+ u16 intr_event;
+ u16 napi_event;
+} rtl_cfg_infos [] = {
+ [RTL_CFG_0] = {
+ .hw_start = rtl_hw_start_8169,
+ .region = 1,
+ .align = 0,
+ .intr_event = SYSErr | LinkChg | RxOverflow |
+ RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ },
+ [RTL_CFG_1] = {
+ .hw_start = rtl_hw_start_8168,
+ .region = 2,
+ .align = 8,
+ .intr_event = SYSErr | LinkChg | RxOverflow |
+ TxErr | TxOK | RxOK | RxErr,
+ .napi_event = TxErr | TxOK | RxOK | RxOverflow
+ },
+ [RTL_CFG_2] = {
+ .hw_start = rtl_hw_start_8101,
+ .region = 2,
+ .align = 8,
+ .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
+ RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
+ .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow
+ }
+};
+
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
- const unsigned int region = rtl_cfg_info[ent->driver_data].region;
+ const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
+ const unsigned int region = cfg->region;
struct rtl8169_private *tp;
struct net_device *dev;
void __iomem *ioaddr;
- unsigned int pm_cap;
- int i, rc;
+ unsigned int i;
+ int rc;
if (netif_msg_drv(&debug)) {
printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
@@ -1518,20 +1515,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc < 0)
goto err_out_disable_2;
- /* save power state before pci_enable_device overwrites it */
- pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
- if (pm_cap) {
- u16 pwr_command, acpi_idle_state;
-
- pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
- acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
- } else {
- if (netif_msg_probe(tp)) {
- dev_err(&pdev->dev,
- "PowerManagement capability not found.\n");
- }
- }
-
/* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) {
if (netif_msg_probe(tp)) {
@@ -1595,7 +1578,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
RTL_W8(ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */
- for (i = 100; i > 0; i--) {
+ for (i = 0; i < 100; i++) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break;
msleep_interruptible(1);
@@ -1657,11 +1640,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
dev->stop = rtl8169_close;
dev->tx_timeout = rtl8169_tx_timeout;
- dev->set_multicast_list = rtl8169_set_rx_mode;
+ dev->set_multicast_list = rtl_set_rx_mode;
dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr;
dev->change_mtu = rtl8169_change_mtu;
+ dev->set_mac_address = rtl_set_mac_address;
#ifdef CONFIG_R8169_NAPI
dev->poll = rtl8169_poll;
@@ -1671,7 +1655,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef CONFIG_R8169_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register = rtl8169_vlan_rx_register;
- dev->vlan_rx_kill_vid = rtl8169_vlan_rx_kill_vid;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1681,7 +1664,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->intr_mask = 0xffff;
tp->pci_dev = pdev;
tp->mmio_addr = ioaddr;
- tp->align = rtl_cfg_info[ent->driver_data].align;
+ tp->align = cfg->align;
+ tp->hw_start = cfg->hw_start;
+ tp->intr_event = cfg->intr_event;
+ tp->napi_event = cfg->napi_event;
init_timer(&tp->timer);
tp->timer.data = (unsigned long) dev;
@@ -1696,15 +1682,17 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
if (netif_msg_probe(tp)) {
+ u32 xid = RTL_R32(TxConfig) & 0x7cf0f8ff;
+
printk(KERN_INFO "%s: %s at 0x%lx, "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
- "IRQ %d\n",
+ "XID %08x IRQ %d\n",
dev->name,
rtl_chip_info[tp->chipset].name,
dev->base_addr,
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
- dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+ dev->dev_addr[4], dev->dev_addr[5], xid, dev->irq);
}
rtl8169_init_phy(dev, tp);
@@ -1725,15 +1713,11 @@ err_out_free_dev_1:
goto out;
}
-static void __devexit
-rtl8169_remove_one(struct pci_dev *pdev)
+static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct rtl8169_private *tp = netdev_priv(dev);
- assert(dev != NULL);
- assert(tp != NULL);
-
flush_scheduled_work();
unregister_netdev(dev);
@@ -1785,7 +1769,7 @@ static int rtl8169_open(struct net_device *dev)
if (retval < 0)
goto err_release_ring_2;
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
rtl8169_request_timer(dev);
@@ -1816,7 +1800,7 @@ static void rtl8169_hw_reset(void __iomem *ioaddr)
RTL_R8(ChipCmd);
}
-static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
+static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp)
{
void __iomem *ioaddr = tp->mmio_addr;
u32 cfg = rtl8169_rx_config;
@@ -1829,45 +1813,90 @@ static void rtl8169_set_rx_tx_config_registers(struct rtl8169_private *tp)
(InterFrameGap << TxInterFrameGapShift));
}
-static void rtl8169_hw_start(struct net_device *dev)
+static void rtl_hw_start(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
- struct pci_dev *pdev = tp->pci_dev;
- u16 cmd;
- u32 i;
+ unsigned int i;
/* Soft reset the chip. */
RTL_W8(ChipCmd, CmdReset);
/* Check that the chip has finished the reset. */
- for (i = 100; i > 0; i--) {
+ for (i = 0; i < 100; i++) {
if ((RTL_R8(ChipCmd) & CmdReset) == 0)
break;
msleep_interruptible(1);
}
- if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
- RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
- pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
- }
+ tp->hw_start(dev);
- if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
- pci_write_config_word(pdev, 0x68, 0x00);
- pci_write_config_word(pdev, 0x69, 0x08);
- }
+ netif_start_queue(dev);
+}
- /* Undocumented stuff. */
- if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
- /* Realtek's r1000_n.c driver uses '&& 0x01' here. Well... */
- if ((RTL_R8(Config2) & 0x07) & 0x01)
- RTL_W32(0x7c, 0x0007ffff);
- RTL_W32(0x7c, 0x0007ff00);
+static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp,
+ void __iomem *ioaddr)
+{
+ /*
+ * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
+ * register to be written before TxDescAddrLow to work.
+ * Switching from MMIO to I/O access fixes the issue as well.
+ */
+ RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
+ RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_32BIT_MASK);
+ RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
+ RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_32BIT_MASK);
+}
+
+static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
+{
+ u16 cmd;
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- cmd = cmd & 0xef;
- pci_write_config_word(pdev, PCI_COMMAND, cmd);
+ cmd = RTL_R16(CPlusCmd);
+ RTL_W16(CPlusCmd, cmd);
+ return cmd;
+}
+
+static void rtl_set_rx_max_size(void __iomem *ioaddr)
+{
+ /* Low hurts. Let's disable the filtering. */
+ RTL_W16(RxMaxSize, 16383);
+}
+
+static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
+{
+ struct {
+ u32 mac_version;
+ u32 clk;
+ u32 val;
+ } cfg2_info [] = {
+ { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd
+ { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
+ { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
+ { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
+ }, *p = cfg2_info;
+ unsigned int i;
+ u32 clk;
+
+ clk = RTL_R8(Config2) & PCI_Clock_66MHz;
+ for (i = 0; i < ARRAY_SIZE(cfg2_info); i++) {
+ if ((p->mac_version == mac_version) && (p->clk == clk)) {
+ RTL_W32(0x7c, p->val);
+ break;
+ }
+ }
+}
+
+static void rtl_hw_start_8169(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_05) {
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW);
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08);
}
RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -1879,19 +1908,11 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W8(EarlyTxThres, EarlyTxThld);
- /* Low hurts. Let's disable the filtering. */
- RTL_W16(RxMaxSize, 16383);
+ rtl_set_rx_max_size(ioaddr);
- if ((tp->mac_version == RTL_GIGA_MAC_VER_01) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_02) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_03) ||
- (tp->mac_version == RTL_GIGA_MAC_VER_04))
- rtl8169_set_rx_tx_config_registers(tp);
+ rtl_set_rx_tx_config_registers(tp);
- cmd = RTL_R16(CPlusCmd);
- RTL_W16(CPlusCmd, cmd);
-
- tp->cp_cmd |= cmd | PCIMulRW;
+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
if ((tp->mac_version == RTL_GIGA_MAC_VER_02) ||
(tp->mac_version == RTL_GIGA_MAC_VER_03)) {
@@ -1902,29 +1923,15 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W16(CPlusCmd, tp->cp_cmd);
+ rtl8169_set_magic_reg(ioaddr, tp->mac_version);
+
/*
* Undocumented corner. Supposedly:
* (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets
*/
RTL_W16(IntrMitigate, 0x0000);
- /*
- * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
- * register to be written before TxDescAddrLow to work.
- * Switching from MMIO to I/O access fixes the issue as well.
- */
- RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
- RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
- RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
- RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
-
- if ((tp->mac_version != RTL_GIGA_MAC_VER_01) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_02) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_03) &&
- (tp->mac_version != RTL_GIGA_MAC_VER_04)) {
- RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
- rtl8169_set_rx_tx_config_registers(tp);
- }
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
RTL_W8(Cfg9346, Cfg9346_Lock);
@@ -1933,15 +1940,107 @@ static void rtl8169_hw_start(struct net_device *dev)
RTL_W32(RxMissed, 0);
- rtl8169_set_rx_mode(dev);
+ rtl_set_rx_mode(dev);
/* no early-rx interrupts */
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
/* Enable all known interrupts by setting the interrupt mask. */
- RTL_W16(IntrMask, rtl8169_intr_mask);
+ RTL_W16(IntrMask, tp->intr_event);
- netif_start_queue(dev);
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+}
+
+static void rtl_hw_start_8168(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+ u8 ctl;
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ rtl_set_rx_tx_config_registers(tp);
+
+ tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1;
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ /* Tx performance tweak. */
+ pci_read_config_byte(pdev, 0x69, &ctl);
+ ctl = (ctl & ~0x70) | 0x50;
+ pci_write_config_byte(pdev, 0x69, ctl);
+
+ RTL_W16(IntrMitigate, 0x5151);
+
+ /* Work around for RxFIFO overflow. */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_11) {
+ tp->intr_event |= RxFIFOOver | PCSTimeout;
+ tp->intr_event &= ~RxOverflow;
+ }
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ RTL_R8(IntrMask);
+
+ RTL_W32(RxMissed, 0);
+
+ rtl_set_rx_mode(dev);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
+
+ RTL_W16(IntrMask, tp->intr_event);
+}
+
+static void rtl_hw_start_8101(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct pci_dev *pdev = tp->pci_dev;
+
+ if (tp->mac_version == RTL_GIGA_MAC_VER_13) {
+ pci_write_config_word(pdev, 0x68, 0x00);
+ pci_write_config_word(pdev, 0x69, 0x08);
+ }
+
+ RTL_W8(Cfg9346, Cfg9346_Unlock);
+
+ RTL_W8(EarlyTxThres, EarlyTxThld);
+
+ rtl_set_rx_max_size(ioaddr);
+
+ tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW;
+
+ RTL_W16(CPlusCmd, tp->cp_cmd);
+
+ RTL_W16(IntrMitigate, 0x0000);
+
+ rtl_set_rx_tx_desc_registers(tp, ioaddr);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+ rtl_set_rx_tx_config_registers(tp);
+
+ RTL_W8(Cfg9346, Cfg9346_Lock);
+
+ RTL_R8(IntrMask);
+
+ RTL_W32(RxMissed, 0);
+
+ rtl_set_rx_mode(dev);
+
+ RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
+
+ RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000);
+
+ RTL_W16(IntrMask, tp->intr_event);
}
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
@@ -1967,7 +2066,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
netif_poll_enable(dev);
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
rtl8169_request_timer(dev);
@@ -2008,38 +2107,38 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping,
rtl8169_mark_to_asic(desc, rx_buf_sz);
}
-static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
- struct RxDesc *desc, int rx_buf_sz,
- unsigned int align)
+static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev,
+ struct net_device *dev,
+ struct RxDesc *desc, int rx_buf_sz,
+ unsigned int align)
{
struct sk_buff *skb;
dma_addr_t mapping;
- int ret = 0;
+ unsigned int pad;
+
+ pad = align ? align : NET_IP_ALIGN;
- skb = dev_alloc_skb(rx_buf_sz + align);
+ skb = netdev_alloc_skb(dev, rx_buf_sz + pad);
if (!skb)
goto err_out;
- skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
- *sk_buff = skb;
+ skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad);
mapping = pci_map_single(pdev, skb->data, rx_buf_sz,
PCI_DMA_FROMDEVICE);
rtl8169_map_to_asic(desc, mapping, rx_buf_sz);
-
out:
- return ret;
+ return skb;
err_out:
- ret = -ENOMEM;
rtl8169_make_unusable_by_asic(desc);
goto out;
}
static void rtl8169_rx_clear(struct rtl8169_private *tp)
{
- int i;
+ unsigned int i;
for (i = 0; i < NUM_RX_DESC; i++) {
if (tp->Rx_skbuff[i]) {
@@ -2054,16 +2153,22 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
{
u32 cur;
- for (cur = start; end - cur > 0; cur++) {
- int ret, i = cur % NUM_RX_DESC;
+ for (cur = start; end - cur != 0; cur++) {
+ struct sk_buff *skb;
+ unsigned int i = cur % NUM_RX_DESC;
+
+ WARN_ON((s32)(end - cur) < 0);
if (tp->Rx_skbuff[i])
continue;
- ret = rtl8169_alloc_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
- tp->RxDescArray + i, tp->rx_buf_sz, tp->align);
- if (ret < 0)
+ skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev,
+ tp->RxDescArray + i,
+ tp->rx_buf_sz, tp->align);
+ if (!skb)
break;
+
+ tp->Rx_skbuff[i] = skb;
}
return cur - start;
}
@@ -2175,14 +2280,9 @@ static void rtl8169_reinit_task(struct work_struct *work)
ret = rtl8169_open(dev);
if (unlikely(ret < 0)) {
- if (net_ratelimit()) {
- struct rtl8169_private *tp = netdev_priv(dev);
-
- if (netif_msg_drv(tp)) {
- printk(PFX KERN_ERR
- "%s: reinit failure (status = %d)."
- " Rescheduling.\n", dev->name, ret);
- }
+ if (net_ratelimit() && netif_msg_drv(tp)) {
+ printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
+ " Rescheduling.\n", dev->name, ret);
}
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
@@ -2209,16 +2309,12 @@ static void rtl8169_reset_task(struct work_struct *work)
if (tp->dirty_rx == tp->cur_rx) {
rtl8169_init_ring_indexes(tp);
- rtl8169_hw_start(dev);
+ rtl_hw_start(dev);
netif_wake_queue(dev);
} else {
- if (net_ratelimit()) {
- struct rtl8169_private *tp = netdev_priv(dev);
-
- if (netif_msg_intr(tp)) {
- printk(PFX KERN_EMERG
- "%s: Rx buffers shortage\n", dev->name);
- }
+ if (net_ratelimit() && netif_msg_intr(tp)) {
+ printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
+ dev->name);
}
rtl8169_schedule_work(dev, rtl8169_reset_task);
}
@@ -2355,7 +2451,7 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
smp_wmb();
- RTL_W8(TxPoll, 0x40); /* set polling bit */
+ RTL_W8(TxPoll, NPQ); /* set polling bit */
if (TX_BUFFS_AVAIL(tp) < MAX_SKB_FRAGS) {
netif_stop_queue(dev);
@@ -2425,16 +2521,12 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
-static void
-rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
- void __iomem *ioaddr)
+static void rtl8169_tx_interrupt(struct net_device *dev,
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned int dirty_tx, tx_left;
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
dirty_tx = tp->dirty_tx;
smp_rmb();
tx_left = tp->cur_tx - dirty_tx;
@@ -2491,38 +2583,37 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
skb->ip_summed = CHECKSUM_NONE;
}
-static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
- struct RxDesc *desc, int rx_buf_sz,
- unsigned int align)
+static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
+ struct rtl8169_private *tp, int pkt_size,
+ dma_addr_t addr)
{
- int ret = -1;
+ struct sk_buff *skb;
+ bool done = false;
- if (pkt_size < rx_copybreak) {
- struct sk_buff *skb;
+ if (pkt_size >= rx_copybreak)
+ goto out;
- skb = dev_alloc_skb(pkt_size + align);
- if (skb) {
- skb_reserve(skb, (align - 1) & (unsigned long)skb->data);
- eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
- *sk_buff = skb;
- rtl8169_mark_to_asic(desc, rx_buf_sz);
- ret = 0;
- }
- }
- return ret;
+ skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN);
+ if (!skb)
+ goto out;
+
+ pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size,
+ PCI_DMA_FROMDEVICE);
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size);
+ *sk_buff = skb;
+ done = true;
+out:
+ return done;
}
-static int
-rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
- void __iomem *ioaddr)
+static int rtl8169_rx_interrupt(struct net_device *dev,
+ struct rtl8169_private *tp,
+ void __iomem *ioaddr)
{
unsigned int cur_rx, rx_left;
unsigned int delta, count;
- assert(dev != NULL);
- assert(tp != NULL);
- assert(ioaddr != NULL);
-
cur_rx = tp->cur_rx;
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
@@ -2555,9 +2646,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
} else {
struct sk_buff *skb = tp->Rx_skbuff[entry];
+ dma_addr_t addr = le64_to_cpu(desc->addr);
int pkt_size = (status & 0x00001FFF) - 4;
- void (*pci_action)(struct pci_dev *, dma_addr_t,
- size_t, int) = pci_dma_sync_single_for_device;
+ struct pci_dev *pdev = tp->pci_dev;
/*
* The driver does not support incoming fragmented
@@ -2573,19 +2664,16 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rtl8169_rx_csum(skb, desc);
- pci_dma_sync_single_for_cpu(tp->pci_dev,
- le64_to_cpu(desc->addr), tp->rx_buf_sz,
- PCI_DMA_FROMDEVICE);
-
- if (rtl8169_try_rx_copy(&skb, pkt_size, desc,
- tp->rx_buf_sz, tp->align)) {
- pci_action = pci_unmap_single;
+ if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) {
+ pci_dma_sync_single_for_device(pdev, addr,
+ pkt_size, PCI_DMA_FROMDEVICE);
+ rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+ } else {
+ pci_unmap_single(pdev, addr, pkt_size,
+ PCI_DMA_FROMDEVICE);
tp->Rx_skbuff[entry] = NULL;
}
- pci_action(tp->pci_dev, le64_to_cpu(desc->addr),
- tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
-
skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, dev);
@@ -2596,6 +2684,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
}
+
+ /* Work around for AMD plateform. */
+ if ((desc->opts2 & 0xfffe000) &&
+ (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
+ desc->opts2 = 0;
+ cur_rx++;
+ }
}
count = cur_rx - tp->cur_rx;
@@ -2619,11 +2714,9 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
return count;
}
-/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
-static irqreturn_t
-rtl8169_interrupt(int irq, void *dev_instance)
+static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
{
- struct net_device *dev = (struct net_device *) dev_instance;
+ struct net_device *dev = dev_instance;
struct rtl8169_private *tp = netdev_priv(dev);
int boguscnt = max_interrupt_work;
void __iomem *ioaddr = tp->mmio_addr;
@@ -2648,8 +2741,16 @@ rtl8169_interrupt(int irq, void *dev_instance)
RTL_W16(IntrStatus,
(status & RxFIFOOver) ? (status | RxOverflow) : status);
- if (!(status & rtl8169_intr_mask))
+ if (!(status & tp->intr_event))
+ break;
+
+ /* Work around for rx fifo overflow */
+ if (unlikely(status & RxFIFOOver) &&
+ (tp->mac_version == RTL_GIGA_MAC_VER_11)) {
+ netif_stop_queue(dev);
+ rtl8169_tx_timeout(dev);
break;
+ }
if (unlikely(status & SYSErr)) {
rtl8169_pcierr_interrupt(dev);
@@ -2660,8 +2761,8 @@ rtl8169_interrupt(int irq, void *dev_instance)
rtl8169_check_link_status(dev, tp, ioaddr);
#ifdef CONFIG_R8169_NAPI
- RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
- tp->intr_mask = ~rtl8169_napi_event;
+ RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
+ tp->intr_mask = ~tp->napi_event;
if (likely(netif_rx_schedule_prep(dev)))
__netif_rx_schedule(dev);
@@ -2672,9 +2773,9 @@ rtl8169_interrupt(int irq, void *dev_instance)
break;
#else
/* Rx interrupt */
- if (status & (RxOK | RxOverflow | RxFIFOOver)) {
+ if (status & (RxOK | RxOverflow | RxFIFOOver))
rtl8169_rx_interrupt(dev, tp, ioaddr);
- }
+
/* Tx interrupt */
if (status & (TxOK | TxErr))
rtl8169_tx_interrupt(dev, tp, ioaddr);
@@ -2718,7 +2819,7 @@ static int rtl8169_poll(struct net_device *dev, int *budget)
* write is safe - FR
*/
smp_wmb();
- RTL_W16(IntrMask, rtl8169_intr_mask);
+ RTL_W16(IntrMask, tp->intr_event);
}
return (work_done >= work_to_do);
@@ -2800,14 +2901,13 @@ static int rtl8169_close(struct net_device *dev)
return 0;
}
-static void
-rtl8169_set_rx_mode(struct net_device *dev)
+static void rtl_set_rx_mode(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
u32 mc_filter[2]; /* Multicast hash filter */
- int i, rx_mode;
+ int rx_mode;
u32 tmp = 0;
if (dev->flags & IFF_PROMISC) {
@@ -2827,6 +2927,8 @@ rtl8169_set_rx_mode(struct net_device *dev)
mc_filter[1] = mc_filter[0] = 0xffffffff;
} else {
struct dev_mc_list *mclist;
+ unsigned int i;
+
rx_mode = AcceptBroadcast | AcceptMyPhys;
mc_filter[1] = mc_filter[0] = 0;
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
@@ -2851,10 +2953,11 @@ rtl8169_set_rx_mode(struct net_device *dev)
mc_filter[1] = 0xffffffff;
}
- RTL_W32(RxConfig, tmp);
RTL_W32(MAR0 + 0, mc_filter[0]);
RTL_W32(MAR0 + 4, mc_filter[1]);
+ RTL_W32(RxConfig, tmp);
+
spin_unlock_irqrestore(&tp->lock, flags);
}
@@ -2942,14 +3045,12 @@ static struct pci_driver rtl8169_pci_driver = {
#endif
};
-static int __init
-rtl8169_init_module(void)
+static int __init rtl8169_init_module(void)
{
return pci_register_driver(&rtl8169_pci_driver);
}
-static void __exit
-rtl8169_cleanup_module(void)
+static void __exit rtl8169_cleanup_module(void)
{
pci_unregister_driver(&rtl8169_pci_driver);
}
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 25c73d47daa..5c2e41fac6d 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -516,7 +516,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv,
}
-static int __init rr_init(struct net_device *dev)
+static int __devinit rr_init(struct net_device *dev)
{
struct rr_private *rrpriv;
struct rr_regs __iomem *regs;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index e3e6d410d72..58bbfdd4f90 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -340,17 +340,6 @@ static void s2io_vlan_rx_register(struct net_device *dev,
/* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */
static int vlan_strip_flag;
-/* Unregister the vlan */
-static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
-{
- struct s2io_nic *nic = dev->priv;
- unsigned long flags;
-
- spin_lock_irqsave(&nic->tx_lock, flags);
- vlan_group_set_device(nic->vlgrp, vid, NULL);
- spin_unlock_irqrestore(&nic->tx_lock, flags);
-}
-
/*
* Constants to be programmed into the Xena's registers, to configure
* the XAUI.
@@ -480,11 +469,18 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, s2io_tbl);
+static struct pci_error_handlers s2io_err_handler = {
+ .error_detected = s2io_io_error_detected,
+ .slot_reset = s2io_io_slot_reset,
+ .resume = s2io_io_resume,
+};
+
static struct pci_driver s2io_driver = {
.name = "S2IO",
.id_table = s2io_tbl,
.probe = s2io_init_nic,
.remove = __devexit_p(s2io_rem_nic),
+ .err_handler = &s2io_err_handler,
};
/* A simplifier macro used both by init and free shared_mem Fns(). */
@@ -1139,7 +1135,7 @@ static int init_nic(struct s2io_nic *nic)
* SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
*/
if ((nic->device_type == XFRAME_I_DEVICE) &&
- (get_xena_rev_id(nic->pdev) < 4))
+ (nic->pdev->revision < 4))
writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable);
val64 = readq(&bar0->tx_fifo_partition_0);
@@ -1877,7 +1873,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag)
herc = (sp->device_type == XFRAME_II_DEVICE);
if (flag == FALSE) {
- if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
+ if ((!herc && (sp->pdev->revision >= 4)) || herc) {
if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE))
ret = 1;
} else {
@@ -1885,7 +1881,7 @@ static int verify_pcc_quiescent(struct s2io_nic *sp, int flag)
ret = 1;
}
} else {
- if ((!herc && (get_xena_rev_id(sp->pdev) >= 4)) || herc) {
+ if ((!herc && (sp->pdev->revision >= 4)) || herc) {
if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) ==
ADAPTER_STATUS_RMAC_PCC_IDLE))
ret = 1;
@@ -2700,6 +2696,9 @@ static void s2io_netpoll(struct net_device *dev)
u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
int i;
+ if (pci_channel_offline(nic->pdev))
+ return;
+
disable_irq(dev->irq);
atomic_inc(&nic->isr_cnt);
@@ -2879,6 +2878,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
struct tx_curr_get_info get_info, put_info;
struct sk_buff *skb;
struct TxD *txdlp;
+ u8 err_mask;
get_info = fifo_data->tx_curr_get_info;
memcpy(&put_info, &fifo_data->tx_curr_put_info, sizeof(put_info));
@@ -2897,8 +2897,8 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
}
/* update t_code statistics */
- err >>= 48;
- switch(err) {
+ err_mask = err >> 48;
+ switch(err_mask) {
case 2:
nic->mac_control.stats_info->sw_stat.
tx_buf_abort_cnt++;
@@ -3225,6 +3225,8 @@ static void alarm_intr_handler(struct s2io_nic *nic)
int i;
if (atomic_read(&nic->card_state) == CARD_DOWN)
return;
+ if (pci_channel_offline(nic->pdev))
+ return;
nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
/* Handling the XPAK counters update */
if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
@@ -3968,7 +3970,6 @@ static int s2io_close(struct net_device *dev)
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
- sp->device_close_flag = TRUE; /* Device is shut down. */
return 0;
}
@@ -4324,6 +4325,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
struct mac_info *mac_control;
struct config_param *config;
+ /* Pretend we handled any irq's from a disconnected card */
+ if (pci_channel_offline(sp->pdev))
+ return IRQ_NONE;
+
atomic_inc(&sp->isr_cnt);
mac_control = &sp->mac_control;
config = &sp->config;
@@ -6579,7 +6584,7 @@ static void s2io_rem_isr(struct s2io_nic * sp)
} while(cnt < 5);
}
-static void s2io_card_down(struct s2io_nic * sp)
+static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
{
int cnt = 0;
struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -6594,7 +6599,8 @@ static void s2io_card_down(struct s2io_nic * sp)
atomic_set(&sp->card_state, CARD_DOWN);
/* disable Tx and Rx traffic on the NIC */
- stop_nic(sp);
+ if (do_io)
+ stop_nic(sp);
s2io_rem_isr(sp);
@@ -6602,7 +6608,7 @@ static void s2io_card_down(struct s2io_nic * sp)
tasklet_kill(&sp->task);
/* Check if the device is Quiescent and then Reset the NIC */
- do {
+ while(do_io) {
/* As per the HW requirement we need to replenish the
* receive buffer to avoid the ring bump. Since there is
* no intention of processing the Rx frame at this pointwe are
@@ -6627,8 +6633,9 @@ static void s2io_card_down(struct s2io_nic * sp)
(unsigned long long) val64);
break;
}
- } while (1);
- s2io_reset(sp);
+ }
+ if (do_io)
+ s2io_reset(sp);
spin_lock_irqsave(&sp->tx_lock, flags);
/* Free all Tx buffers */
@@ -6643,6 +6650,11 @@ static void s2io_card_down(struct s2io_nic * sp)
clear_bit(0, &(sp->link_state));
}
+static void s2io_card_down(struct s2io_nic * sp)
+{
+ do_s2io_card_down(sp, 1);
+}
+
static int s2io_card_up(struct s2io_nic * sp)
{
int i, ret = 0;
@@ -6816,6 +6828,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
u16 l3_csum, l4_csum;
unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
struct lro *lro;
+ u8 err_mask;
skb->dev = dev;
@@ -6824,8 +6837,8 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
if (err & 0x1) {
sp->mac_control.stats_info->sw_stat.parity_err_cnt++;
}
- err >>= 48;
- switch(err) {
+ err_mask = err >> 48;
+ switch(err_mask) {
case 1:
sp->mac_control.stats_info->sw_stat.
rx_parity_err_cnt++;
@@ -6878,9 +6891,9 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
* Note that in this case, since checksum will be incorrect,
* stack will validate the same.
*/
- if (err != 0x5) {
- DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
- dev->name, err);
+ if (err_mask != 0x5) {
+ DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%x\n",
+ dev->name, err_mask);
sp->stats.rx_crc_errors++;
sp->mac_control.stats_info->sw_stat.mem_freed
+= skb->truesize;
@@ -7063,23 +7076,6 @@ static void s2io_link(struct s2io_nic * sp, int link)
}
/**
- * get_xena_rev_id - to identify revision ID of xena.
- * @pdev : PCI Dev structure
- * Description:
- * Function to identify the Revision ID of xena.
- * Return value:
- * returns the revision ID of the device.
- */
-
-static int get_xena_rev_id(struct pci_dev *pdev)
-{
- u8 id = 0;
- int ret;
- ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
- return id;
-}
-
-/**
* s2io_init_pci -Initialization of PCI and PCI-X configuration registers .
* @sp : private member of the device structure, which is a pointer to the
* s2io_nic structure.
@@ -7412,7 +7408,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register = s2io_vlan_rx_register;
- dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
/*
* will use eth_mac_addr() for dev->set_mac_address
@@ -7538,7 +7533,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
s2io_vpd_read(sp);
DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2007 Neterion Inc.\n");
DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name,
- sp->product_name, get_xena_rev_id(sp->pdev));
+ sp->product_name, pdev->revision);
DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
s2io_driver_version);
DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
@@ -8020,3 +8015,85 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
return;
}
+
+/**
+ * s2io_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev)) {
+ /* Bring down the card, while avoiding PCI I/O */
+ do_s2io_card_down(sp, 0);
+ }
+ pci_disable_device(pdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * s2io_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ * At this point, the card has exprienced a hard reset,
+ * followed by fixups by BIOS, and has its config space
+ * set up identically to what it was at cold boot.
+ */
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR "s2io: "
+ "Cannot re-enable PCI device after reset.\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ pci_set_master(pdev);
+ s2io_reset(sp);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * s2io_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells
+ * us that its OK to resume normal operation.
+ */
+static void s2io_io_resume(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct s2io_nic *sp = netdev->priv;
+
+ if (netif_running(netdev)) {
+ if (s2io_card_up(sp)) {
+ printk(KERN_ERR "s2io: "
+ "Can't bring device back up after reset.\n");
+ return;
+ }
+
+ if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
+ s2io_card_down(sp);
+ printk(KERN_ERR "s2io: "
+ "Can't resetore mac addr after reset.\n");
+ return;
+ }
+ }
+
+ netif_device_attach(netdev);
+ netif_wake_queue(netdev);
+}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 54baa0b8ec7..3887fe63a90 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -794,7 +794,6 @@ struct s2io_nic {
struct net_device_stats stats;
int high_dma_flag;
- int device_close_flag;
int device_enabled_once;
char name[60];
@@ -1034,7 +1033,6 @@ static void s2io_set_link(struct work_struct *work);
static int s2io_set_swapper(struct s2io_nic * sp);
static void s2io_card_down(struct s2io_nic *nic);
static int s2io_card_up(struct s2io_nic *nic);
-static int get_xena_rev_id(struct pci_dev *pdev);
static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit,
int bit_state);
static int s2io_add_isr(struct s2io_nic * sp);
@@ -1052,6 +1050,11 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
struct sk_buff *skb, u32 tcp_len);
static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
+static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state);
+static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev);
+static void s2io_io_resume(struct pci_dev *pdev);
+
#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type
diff --git a/drivers/net/saa9730.c b/drivers/net/saa9730.c
index ad94358ece8..451486b32f2 100644
--- a/drivers/net/saa9730.c
+++ b/drivers/net/saa9730.c
@@ -690,9 +690,9 @@ static int lan_saa9730_rx(struct net_device *dev)
lp->stats.rx_packets++;
skb_reserve(skb, 2); /* 16 byte align */
skb_put(skb, len); /* make room */
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
(unsigned char *) pData,
- len, 0);
+ len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 132e2148b21..e7fdcf15b5a 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -1159,7 +1159,7 @@ static void sbmac_netpoll(struct net_device *netdev)
__raw_writeq(0, sc->sbm_imr);
- sbmac_intr(irq, netdev, NULL);
+ sbmac_intr(irq, netdev);
#ifdef CONFIG_SBMAC_COALESCE
__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 2106becf699..384b4685e97 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -320,7 +320,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
skb_put(skb, len);
/* Copy out of kseg1 to avoid silly cache flush. */
- eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
+ skb_copy_to_linear_data(skb, pkt_pointer + 2, len);
skb->protocol = eth_type_trans(skb, dev);
/* We don't want to receive our own packets */
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index bc8de48da31..ec2ad9f0efa 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -548,7 +548,7 @@ static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN);
if (skb) {
skb_reserve(skb, NET_IP_ALIGN);
- eth_copy_and_sum(skb, sk_buff[0]->data, pkt_size, 0);
+ skb_copy_to_linear_data(skb, sk_buff[0]->data, pkt_size);
*sk_buff = skb;
sis190_give_to_asic(desc, rx_buf_sz);
ret = 0;
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 2cb2e156c75..7c6e4808399 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -573,7 +573,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
* return error if it failed to found.
*/
-static int __init sis900_mii_probe(struct net_device * net_dev)
+static int __devinit sis900_mii_probe(struct net_device * net_dev)
{
struct sis900_private * sis_priv = net_dev->priv;
const char *dev_name = pci_name(sis_priv->pci_dev);
diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile
deleted file mode 100644
index afd900d5d73..00000000000
--- a/drivers/net/sk98lin/Makefile
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# Makefile for the SysKonnect SK-98xx device driver.
-#
-
-
-#
-# Standalone driver params
-# SKPARAM += -DSK_KERNEL_24
-# SKPARAM += -DSK_KERNEL_24_26
-# SKPARAM += -DSK_KERNEL_26
-# SKPARAM += -DSK_KERNEL_22_24
-
-obj-$(CONFIG_SK98LIN) += sk98lin.o
-sk98lin-objs := \
- skge.o \
- skethtool.o \
- skdim.o \
- skaddr.o \
- skgehwt.o \
- skgeinit.o \
- skgepnmi.o \
- skgesirq.o \
- ski2c.o \
- sklm80.o \
- skqueue.o \
- skrlmt.o \
- sktimer.o \
- skvpd.o \
- skxmac2.o
-
-# DBGDEF = \
-# -DDEBUG
-
-ifdef DEBUG
-DBGDEF += \
--DSK_DEBUG_CHKMOD=0x00000000L \
--DSK_DEBUG_CHKCAT=0x00000000L
-endif
-
-
-# **** possible debug modules for SK_DEBUG_CHKMOD *****************
-# SK_DBGMOD_MERR 0x00000001L /* general module error indication */
-# SK_DBGMOD_HWM 0x00000002L /* Hardware init module */
-# SK_DBGMOD_RLMT 0x00000004L /* RLMT module */
-# SK_DBGMOD_VPD 0x00000008L /* VPD module */
-# SK_DBGMOD_I2C 0x00000010L /* I2C module */
-# SK_DBGMOD_PNMI 0x00000020L /* PNMI module */
-# SK_DBGMOD_CSUM 0x00000040L /* CSUM module */
-# SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
-# SK_DBGMOD_DRV 0x00010000L /* DRV module */
-
-# **** possible debug categories for SK_DEBUG_CHKCAT **************
-# *** common modules ***
-# SK_DBGCAT_INIT 0x00000001L module/driver initialization
-# SK_DBGCAT_CTRL 0x00000002L controlling: add/rmv MCA/MAC and other controls (IOCTL)
-# SK_DBGCAT_ERR 0x00000004L error handling paths
-# SK_DBGCAT_TX 0x00000008L transmit path
-# SK_DBGCAT_RX 0x00000010L receive path
-# SK_DBGCAT_IRQ 0x00000020L general IRQ handling
-# SK_DBGCAT_QUEUE 0x00000040L any queue management
-# SK_DBGCAT_DUMP 0x00000080L large data output e.g. hex dump
-# SK_DBGCAT_FATAL 0x00000100L large data output e.g. hex dump
-
-# *** driver (file skge.c) ***
-# SK_DBGCAT_DRV_ENTRY 0x00010000 entry points
-# SK_DBGCAT_DRV_??? 0x00020000 not used
-# SK_DBGCAT_DRV_MCA 0x00040000 multicast
-# SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 tx path
-# SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 rx path
-# SK_DBGCAT_DRV_PROGRESS 0x00200000 general runtime
-# SK_DBGCAT_DRV_??? 0x00400000 not used
-# SK_DBGCAT_DRV_PROM 0x00800000 promiscuous mode
-# SK_DBGCAT_DRV_TX_FRAME 0x01000000 display tx frames
-# SK_DBGCAT_DRV_ERROR 0x02000000 error conditions
-# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources
-# SK_DBGCAT_DRV_EVENT 0x08000000 driver events
-
-EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
-
-clean:
- rm -f core *.o *.a *.s
-
-
-
-
-
-
diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h
deleted file mode 100644
index 4e2dbbf7800..00000000000
--- a/drivers/net/sk98lin/h/lm80.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name: lm80.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.6 $
- * Date: $Date: 2003/05/13 17:26:52 $
- * Purpose: Contains all defines for the LM80 Chip
- * (National Semiconductor).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_LM80_H
-#define __INC_LM80_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * LM80 register definition
- *
- * All registers are 8 bit wide
- */
-#define LM80_CFG 0x00 /* Configuration Register */
-#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */
-#define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */
-#define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */
-#define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */
-#define LM80_FAN_CTRL 0x05 /* Fan Devisor/RST#/OS# Register */
-#define LM80_TEMP_CTRL 0x06 /* OS# Config, Temp Res. Reg */
- /* 0x07 - 0x1f reserved */
- /* current values */
-#define LM80_VT0_IN 0x20 /* current Voltage 0 value */
-#define LM80_VT1_IN 0x21 /* current Voltage 1 value */
-#define LM80_VT2_IN 0x22 /* current Voltage 2 value */
-#define LM80_VT3_IN 0x23 /* current Voltage 3 value */
-#define LM80_VT4_IN 0x24 /* current Voltage 4 value */
-#define LM80_VT5_IN 0x25 /* current Voltage 5 value */
-#define LM80_VT6_IN 0x26 /* current Voltage 6 value */
-#define LM80_TEMP_IN 0x27 /* current Temperature value */
-#define LM80_FAN1_IN 0x28 /* current Fan 1 count */
-#define LM80_FAN2_IN 0x29 /* current Fan 2 count */
- /* limit values */
-#define LM80_VT0_HIGH_LIM 0x2a /* high limit val for Voltage 0 */
-#define LM80_VT0_LOW_LIM 0x2b /* low limit val for Voltage 0 */
-#define LM80_VT1_HIGH_LIM 0x2c /* high limit val for Voltage 1 */
-#define LM80_VT1_LOW_LIM 0x2d /* low limit val for Voltage 1 */
-#define LM80_VT2_HIGH_LIM 0x2e /* high limit val for Voltage 2 */
-#define LM80_VT2_LOW_LIM 0x2f /* low limit val for Voltage 2 */
-#define LM80_VT3_HIGH_LIM 0x30 /* high limit val for Voltage 3 */
-#define LM80_VT3_LOW_LIM 0x31 /* low limit val for Voltage 3 */
-#define LM80_VT4_HIGH_LIM 0x32 /* high limit val for Voltage 4 */
-#define LM80_VT4_LOW_LIM 0x33 /* low limit val for Voltage 4 */
-#define LM80_VT5_HIGH_LIM 0x34 /* high limit val for Voltage 5 */
-#define LM80_VT5_LOW_LIM 0x35 /* low limit val for Voltage 5 */
-#define LM80_VT6_HIGH_LIM 0x36 /* high limit val for Voltage 6 */
-#define LM80_VT6_LOW_LIM 0x37 /* low limit val for Voltage 6 */
-#define LM80_THOT_LIM_UP 0x38 /* hot temperature limit (high) */
-#define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */
-#define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */
-#define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */
-#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */
-#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */
- /* 0x3e - 0x3f reserved */
-
-/*
- * LM80 bit definitions
- */
-
-/* LM80_CFG Configuration Register */
-#define LM80_CFG_START (1<<0) /* start monitoring operation */
-#define LM80_CFG_INT_ENA (1<<1) /* enables the INT# Interrupt output */
-#define LM80_CFG_INT_POL (1<<2) /* INT# pol: 0 act low, 1 act high */
-#define LM80_CFG_INT_CLR (1<<3) /* disables INT#/RST_OUT#/OS# outputs */
-#define LM80_CFG_RESET (1<<4) /* signals a reset */
-#define LM80_CFG_CHASS_CLR (1<<5) /* clears Chassis Intrusion (CI) pin */
-#define LM80_CFG_GPO (1<<6) /* drives the GPO# pin */
-#define LM80_CFG_INIT (1<<7) /* restore power on defaults */
-
-/* LM80_ISRC_1 Interrupt Status Register 1 */
-/* LM80_IMSK_1 Interrupt Mask Register 1 */
-#define LM80_IS_VT0 (1<<0) /* limit exceeded for Voltage 0 */
-#define LM80_IS_VT1 (1<<1) /* limit exceeded for Voltage 1 */
-#define LM80_IS_VT2 (1<<2) /* limit exceeded for Voltage 2 */
-#define LM80_IS_VT3 (1<<3) /* limit exceeded for Voltage 3 */
-#define LM80_IS_VT4 (1<<4) /* limit exceeded for Voltage 4 */
-#define LM80_IS_VT5 (1<<5) /* limit exceeded for Voltage 5 */
-#define LM80_IS_VT6 (1<<6) /* limit exceeded for Voltage 6 */
-#define LM80_IS_INT_IN (1<<7) /* state of INT_IN# */
-
-/* LM80_ISRC_2 Interrupt Status Register 2 */
-/* LM80_IMSK_2 Interrupt Mask Register 2 */
-#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */
-#define LM80_IS_BTI (1<<1) /* state of BTI# pin */
-#define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */
-#define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */
-#define LM80_IS_CI (1<<4) /* Chassis Intrusion occured */
-#define LM80_IS_OS (1<<5) /* OS temperature limit exceeded */
- /* bit 6 and 7 are reserved in LM80_ISRC_2 */
-#define LM80_IS_HT_IRQ_MD (1<<6) /* Hot temperature interrupt mode */
-#define LM80_IS_OT_IRQ_MD (1<<7) /* OS temperature interrupt mode */
-
-/* LM80_FAN_CTRL Fan Devisor/RST#/OS# Register */
-#define LM80_FAN1_MD_SEL (1<<0) /* Fan 1 mode select */
-#define LM80_FAN2_MD_SEL (1<<1) /* Fan 2 mode select */
-#define LM80_FAN1_PRM_CTL (3<<2) /* Fan 1 speed control */
-#define LM80_FAN2_PRM_CTL (3<<4) /* Fan 2 speed control */
-#define LM80_FAN_OS_ENA (1<<6) /* enable OS mode on RST_OUT#/OS# pins*/
-#define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */
-
-/* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */
-#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */
-#define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */
-#define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */
-#define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/
-#define LM80_TEMP_LSB (0xf<<4)/* 4 LSBs of 11 bit temp data */
-#define LM80_TEMP_LSB_9 (1<<7) /* LSB of 9 bit temperature data */
-
- /* 0x07 - 0x1f reserved */
-/* LM80_VT0_IN current Voltage 0 value */
-/* LM80_VT1_IN current Voltage 1 value */
-/* LM80_VT2_IN current Voltage 2 value */
-/* LM80_VT3_IN current Voltage 3 value */
-/* LM80_VT4_IN current Voltage 4 value */
-/* LM80_VT5_IN current Voltage 5 value */
-/* LM80_VT6_IN current Voltage 6 value */
-/* LM80_TEMP_IN current temperature value */
-/* LM80_FAN1_IN current Fan 1 count */
-/* LM80_FAN2_IN current Fan 2 count */
-/* LM80_VT0_HIGH_LIM high limit val for Voltage 0 */
-/* LM80_VT0_LOW_LIM low limit val for Voltage 0 */
-/* LM80_VT1_HIGH_LIM high limit val for Voltage 1 */
-/* LM80_VT1_LOW_LIM low limit val for Voltage 1 */
-/* LM80_VT2_HIGH_LIM high limit val for Voltage 2 */
-/* LM80_VT2_LOW_LIM low limit val for Voltage 2 */
-/* LM80_VT3_HIGH_LIM high limit val for Voltage 3 */
-/* LM80_VT3_LOW_LIM low limit val for Voltage 3 */
-/* LM80_VT4_HIGH_LIM high limit val for Voltage 4 */
-/* LM80_VT4_LOW_LIM low limit val for Voltage 4 */
-/* LM80_VT5_HIGH_LIM high limit val for Voltage 5 */
-/* LM80_VT5_LOW_LIM low limit val for Voltage 5 */
-/* LM80_VT6_HIGH_LIM high limit val for Voltage 6 */
-/* LM80_VT6_LOW_LIM low limit val for Voltage 6 */
-/* LM80_THOT_LIM_UP hot temperature limit (high) */
-/* LM80_THOT_LIM_LO hot temperature limit (low) */
-/* LM80_TOS_LIM_UP OS temperature limit (high) */
-/* LM80_TOS_LIM_LO OS temperature limit (low) */
-/* LM80_FAN1_COUNT_LIM Fan 1 count limit (high) */
-/* LM80_FAN2_COUNT_LIM Fan 2 count limit (low) */
- /* 0x3e - 0x3f reserved */
-
-#define LM80_ADDR 0x28 /* LM80 default addr */
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_LM80_H */
diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h
deleted file mode 100644
index 423ad063d09..00000000000
--- a/drivers/net/sk98lin/h/skaddr.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/******************************************************************************
- *
- * Name: skaddr.h
- * Project: Gigabit Ethernet Adapters, ADDR-Modul
- * Version: $Revision: 1.29 $
- * Date: $Date: 2003/05/13 16:57:24 $
- * Purpose: Header file for Address Management (MC, UC, Prom).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses and promiscuous mode
- * on GEnesis adapters.
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * ...
- * "sktypes.h"
- * "skqueue.h"
- * "skaddr.h"
- * ...
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKADDR_H
-#define __INC_SKADDR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_MAC_ADDR_LEN 6 /* Length of MAC address. */
-#define SK_MAX_ADDRS 14 /* #Addrs for exact match. */
-
-/* ----- Common return values ----- */
-
-#define SK_ADDR_SUCCESS 0 /* Function returned successfully. */
-#define SK_ADDR_ILLEGAL_PORT 100 /* Port number too high. */
-#define SK_ADDR_TOO_EARLY 101 /* Function called too early. */
-
-/* ----- Clear/Add flag bits ----- */
-
-#define SK_ADDR_PERMANENT 1 /* RLMT Address */
-
-/* ----- Additional Clear flag bits ----- */
-
-#define SK_MC_SW_ONLY 2 /* Do not update HW when clearing. */
-
-/* ----- Override flag bits ----- */
-
-#define SK_ADDR_LOGICAL_ADDRESS 0
-#define SK_ADDR_VIRTUAL_ADDRESS (SK_ADDR_LOGICAL_ADDRESS) /* old */
-#define SK_ADDR_PHYSICAL_ADDRESS 1
-#define SK_ADDR_CLEAR_LOGICAL 2
-#define SK_ADDR_SET_LOGICAL 4
-
-/* ----- Override return values ----- */
-
-#define SK_ADDR_OVERRIDE_SUCCESS (SK_ADDR_SUCCESS)
-#define SK_ADDR_DUPLICATE_ADDRESS 1
-#define SK_ADDR_MULTICAST_ADDRESS 2
-
-/* ----- Partitioning of excact match table ----- */
-
-#define SK_ADDR_EXACT_MATCHES 16 /* #Exact match entries. */
-
-#define SK_ADDR_FIRST_MATCH_RLMT 1
-#define SK_ADDR_LAST_MATCH_RLMT 2
-#define SK_ADDR_FIRST_MATCH_DRV 3
-#define SK_ADDR_LAST_MATCH_DRV (SK_ADDR_EXACT_MATCHES - 1)
-
-/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */
-
-#define SK_MC_FILTERING_EXACT 0 /* Exact filtering. */
-#define SK_MC_FILTERING_INEXACT 1 /* Inexact filtering. */
-
-/* ----- Additional SkAddrMcAdd return values ----- */
-
-#define SK_MC_ILLEGAL_ADDRESS 2 /* Illegal address. */
-#define SK_MC_ILLEGAL_PORT 3 /* Illegal port (not the active one). */
-#define SK_MC_RLMT_OVERFLOW 4 /* Too many RLMT mc addresses. */
-
-/* Promiscuous mode bits ----- */
-
-#define SK_PROM_MODE_NONE 0 /* Normal receive. */
-#define SK_PROM_MODE_LLC 1 /* Receive all LLC frames. */
-#define SK_PROM_MODE_ALL_MC 2 /* Receive all multicast frames. */
-/* #define SK_PROM_MODE_NON_LLC 4 */ /* Receive all non-LLC frames. */
-
-/* Macros */
-
-#ifdef OLD_STUFF
-#ifndef SK_ADDR_EQUAL
-/*
- * "&" instead of "&&" allows better optimization on IA-64.
- * The replacement is safe here, as all bytes exist.
- */
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2) ( \
- (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \
- (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \
- (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \
- (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \
- (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \
- (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0]))
-#else /* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2) ( \
- (*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \
- (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0])))
-#endif /* SK_ADDR_DWORD_COMPARE */
-#endif /* SK_ADDR_EQUAL */
-#endif /* 0 */
-
-#ifndef SK_ADDR_EQUAL
-#ifndef SK_ADDR_DWORD_COMPARE
-#define SK_ADDR_EQUAL(A1,A2) ( \
- (((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \
- (((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \
- (((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \
- (((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \
- (((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \
- (((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0]))
-#else /* SK_ADDR_DWORD_COMPARE */
-#define SK_ADDR_EQUAL(A1,A2) ( \
- (*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \
- *(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \
- (*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \
- *(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0])))
-#endif /* SK_ADDR_DWORD_COMPARE */
-#endif /* SK_ADDR_EQUAL */
-
-/* typedefs *******************************************************************/
-
-typedef struct s_MacAddr {
- SK_U8 a[SK_MAC_ADDR_LEN];
-} SK_MAC_ADDR;
-
-
-/* SK_FILTER is used to ensure alignment of the filter. */
-typedef union s_InexactFilter {
- SK_U8 Bytes[8];
- SK_U64 Val; /* Dummy entry for alignment only. */
-} SK_FILTER64;
-
-
-typedef struct s_AddrNet SK_ADDR_NET;
-
-
-typedef struct s_AddrPort {
-
-/* ----- Public part (read-only) ----- */
-
- SK_MAC_ADDR CurrentMacAddress; /* Current physical MAC Address. */
- SK_MAC_ADDR PermanentMacAddress; /* Permanent physical MAC Address. */
- int PromMode; /* Promiscuous Mode. */
-
-/* ----- Private part ----- */
-
- SK_MAC_ADDR PreviousMacAddress; /* Prev. phys. MAC Address. */
- SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */
- SK_U8 Align01;
-
- SK_U32 FirstExactMatchRlmt;
- SK_U32 NextExactMatchRlmt;
- SK_U32 FirstExactMatchDrv;
- SK_U32 NextExactMatchDrv;
- SK_MAC_ADDR Exact[SK_ADDR_EXACT_MATCHES];
- SK_FILTER64 InexactFilter; /* For 64-bit hash register. */
- SK_FILTER64 InexactRlmtFilter; /* For 64-bit hash register. */
- SK_FILTER64 InexactDrvFilter; /* For 64-bit hash register. */
-} SK_ADDR_PORT;
-
-
-struct s_AddrNet {
-/* ----- Public part (read-only) ----- */
-
- SK_MAC_ADDR CurrentMacAddress; /* Logical MAC Address. */
- SK_MAC_ADDR PermanentMacAddress; /* Logical MAC Address. */
-
-/* ----- Private part ----- */
-
- SK_U32 ActivePort; /* View of module ADDR. */
- SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */
- SK_U8 Align01;
- SK_U16 Align02;
-};
-
-
-typedef struct s_Addr {
-
-/* ----- Public part (read-only) ----- */
-
- SK_ADDR_NET Net[SK_MAX_NETS];
- SK_ADDR_PORT Port[SK_MAX_MACS];
-
-/* ----- Private part ----- */
-} SK_ADDR;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkAddr */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern int SkAddrInit(
- SK_AC *pAC,
- SK_IOC IoC,
- int Level);
-
-extern int SkAddrMcClear(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber,
- int Flags);
-
-extern int SkAddrMcAdd(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber,
- SK_MAC_ADDR *pMc,
- int Flags);
-
-extern int SkAddrMcUpdate(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber);
-
-extern int SkAddrOverride(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber,
- SK_MAC_ADDR SK_FAR *pNewAddr,
- int Flags);
-
-extern int SkAddrPromiscuousChange(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 PortNumber,
- int NewPromMode);
-
-#ifndef SK_SLIM
-extern int SkAddrSwap(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 FromPortNumber,
- SK_U32 ToPortNumber);
-#endif
-
-#else /* defined(SK_KR_PROTO)) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style prototypes are not yet provided.
-
-#endif /* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_SKADDR_H */
diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h
deleted file mode 100644
index 6e256bd9a28..00000000000
--- a/drivers/net/sk98lin/h/skcsum.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/******************************************************************************
- *
- * Name: skcsum.h
- * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
- * Version: $Revision: 1.10 $
- * Date: $Date: 2003/08/20 13:59:57 $
- * Purpose: Store/verify Internet checksum in send/receive packets.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2001 SysKonnect 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 by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * Public header file for the "GEnesis" common module "CSUM".
- *
- * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon"
- * and is the code name of this SysKonnect project.
- *
- * Compilation Options:
- *
- * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an
- * empty module.
- *
- * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id
- * definitions. In this case, all SKCS_PROTO_xxx definitions must be made
- * external.
- *
- * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status
- * definitions. In this case, all SKCS_STATUS_xxx definitions must be made
- * external.
- *
- * Include File Hierarchy:
- *
- * "h/skcsum.h"
- * "h/sktypes.h"
- * "h/skqueue.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKCSUM_H
-#define __INC_SKCSUM_H
-
-#include "h/sktypes.h"
-#include "h/skqueue.h"
-
-/* defines ********************************************************************/
-
-/*
- * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags' if no user
- * overwrite.
- */
-#ifndef SKCS_OVERWRITE_PROTO /* User overwrite? */
-#define SKCS_PROTO_IP 0x1 /* IP (Internet Protocol version 4) */
-#define SKCS_PROTO_TCP 0x2 /* TCP (Transmission Control Protocol) */
-#define SKCS_PROTO_UDP 0x4 /* UDP (User Datagram Protocol) */
-
-/* Indices for protocol statistics. */
-#define SKCS_PROTO_STATS_IP 0
-#define SKCS_PROTO_STATS_UDP 1
-#define SKCS_PROTO_STATS_TCP 2
-#define SKCS_NUM_PROTOCOLS 3 /* Number of supported protocols. */
-#endif /* !SKCS_OVERWRITE_PROTO */
-
-/*
- * Define the default SKCS_STATUS type and values if no user overwrite.
- *
- * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
- * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
- * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
- * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
- * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
- * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
- * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
- * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
- * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
- * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
- * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum.
- */
-#ifndef SKCS_OVERWRITE_STATUS /* User overwrite? */
-#define SKCS_STATUS int /* Define status type. */
-
-#define SKCS_STATUS_UNKNOWN_IP_VERSION 1
-#define SKCS_STATUS_IP_CSUM_ERROR 2
-#define SKCS_STATUS_IP_FRAGMENT 3
-#define SKCS_STATUS_IP_CSUM_OK 4
-#define SKCS_STATUS_TCP_CSUM_ERROR 5
-#define SKCS_STATUS_UDP_CSUM_ERROR 6
-#define SKCS_STATUS_TCP_CSUM_OK 7
-#define SKCS_STATUS_UDP_CSUM_OK 8
-/* needed for Microsoft */
-#define SKCS_STATUS_IP_CSUM_ERROR_UDP 9
-#define SKCS_STATUS_IP_CSUM_ERROR_TCP 10
-/* UDP checksum may be omitted */
-#define SKCS_STATUS_IP_CSUM_OK_NO_UDP 11
-#endif /* !SKCS_OVERWRITE_STATUS */
-
-/* Clear protocol statistics event. */
-#define SK_CSUM_EVENT_CLEAR_PROTO_STATS 1
-
-/*
- * Add two values in one's complement.
- *
- * Note: One of the two input values may be "longer" than 16-bit, but then the
- * resulting sum may be 17 bits long. In this case, add zero to the result using
- * SKCS_OC_ADD() again.
- *
- * Result = Value1 + Value2
- */
-#define SKCS_OC_ADD(Result, Value1, Value2) { \
- unsigned long Sum; \
- \
- Sum = (unsigned long) (Value1) + (unsigned long) (Value2); \
- /* Add-in any carry. */ \
- (Result) = (Sum & 0xffff) + (Sum >> 16); \
-}
-
-/*
- * Subtract two values in one's complement.
- *
- * Result = Value1 - Value2
- */
-#define SKCS_OC_SUB(Result, Value1, Value2) \
- SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff)
-
-/* typedefs *******************************************************************/
-
-/*
- * SKCS_PROTO_STATS - The CSUM protocol statistics structure.
- *
- * There is one instance of this structure for each protocol supported.
- */
-typedef struct s_CsProtocolStatistics {
- SK_U64 RxOkCts; /* Receive checksum ok. */
- SK_U64 RxUnableCts; /* Unable to verify receive checksum. */
- SK_U64 RxErrCts; /* Receive checksum error. */
- SK_U64 TxOkCts; /* Transmit checksum ok. */
- SK_U64 TxUnableCts; /* Unable to calculate checksum in hw. */
-} SKCS_PROTO_STATS;
-
-/*
- * s_Csum - The CSUM module context structure.
- */
-typedef struct s_Csum {
- /* Enabled receive SK_PROTO_XXX bit flags. */
- unsigned ReceiveFlags[SK_MAX_NETS];
-#ifdef TX_CSUM
- unsigned TransmitFlags[SK_MAX_NETS];
-#endif /* TX_CSUM */
-
- /* The protocol statistics structure; one per supported protocol. */
- SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
-} SK_CSUM;
-
-/*
- * SKCS_PACKET_INFO - The packet information structure.
- */
-typedef struct s_CsPacketInfo {
- /* Bit field specifiying the desired/found protocols. */
- unsigned ProtocolFlags;
-
- /* Length of complete IP header, including any option fields. */
- unsigned IpHeaderLength;
-
- /* IP header checksum. */
- unsigned IpHeaderChecksum;
-
- /* TCP/UDP pseudo header checksum. */
- unsigned PseudoHeaderChecksum;
-} SKCS_PACKET_INFO;
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_CS_CALCULATE_CHECKSUM
-extern unsigned SkCsCalculateChecksum(
- void *pData,
- unsigned Length);
-#endif /* SK_CS_CALCULATE_CHECKSUM */
-
-extern int SkCsEvent(
- SK_AC *pAc,
- SK_IOC Ioc,
- SK_U32 Event,
- SK_EVPARA Param);
-
-extern SKCS_STATUS SkCsGetReceiveInfo(
- SK_AC *pAc,
- void *pIpHeader,
- unsigned Checksum1,
- unsigned Checksum2,
- int NetNumber);
-
-extern void SkCsSetReceiveFlags(
- SK_AC *pAc,
- unsigned ReceiveFlags,
- unsigned *pChecksum1Offset,
- unsigned *pChecksum2Offset,
- int NetNumber);
-
-#endif /* __INC_SKCSUM_H */
diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h
deleted file mode 100644
index 3cba171d74b..00000000000
--- a/drivers/net/sk98lin/h/skdebug.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/******************************************************************************
- *
- * Name: skdebug.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.14 $
- * Date: $Date: 2003/05/13 17:26:00 $
- * Purpose: SK specific DEBUG support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDEBUG_H
-#define __INC_SKDEBUG_H
-
-#ifdef DEBUG
-#ifndef SK_DBG_MSG
-#define SK_DBG_MSG(pAC,comp,cat,arg) \
- if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \
- ((cat) & SK_DBG_CHKCAT(pAC)) ) { \
- SK_DBG_PRINTF arg ; \
- }
-#endif
-#else
-#define SK_DBG_MSG(pAC,comp,lev,arg)
-#endif
-
-/* PLS NOTE:
- * =========
- * Due to any restrictions of kernel printf routines do not use other
- * format identifiers as: %x %d %c %s .
- * Never use any combined format identifiers such as: %lx %ld in your
- * printf - argument (arg) because some OS specific kernel printfs may
- * only support some basic identifiers.
- */
-
-/* Debug modules */
-
-#define SK_DBGMOD_MERR 0x00000001L /* general module error indication */
-#define SK_DBGMOD_HWM 0x00000002L /* Hardware init module */
-#define SK_DBGMOD_RLMT 0x00000004L /* RLMT module */
-#define SK_DBGMOD_VPD 0x00000008L /* VPD module */
-#define SK_DBGMOD_I2C 0x00000010L /* I2C module */
-#define SK_DBGMOD_PNMI 0x00000020L /* PNMI module */
-#define SK_DBGMOD_CSUM 0x00000040L /* CSUM module */
-#define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
-#define SK_DBGMOD_PECP 0x00000100L /* PECP module */
-#define SK_DBGMOD_POWM 0x00000200L /* Power Management module */
-
-/* Debug events */
-
-#define SK_DBGCAT_INIT 0x00000001L /* module/driver initialization */
-#define SK_DBGCAT_CTRL 0x00000002L /* controlling devices */
-#define SK_DBGCAT_ERR 0x00000004L /* error handling paths */
-#define SK_DBGCAT_TX 0x00000008L /* transmit path */
-#define SK_DBGCAT_RX 0x00000010L /* receive path */
-#define SK_DBGCAT_IRQ 0x00000020L /* general IRQ handling */
-#define SK_DBGCAT_QUEUE 0x00000040L /* any queue management */
-#define SK_DBGCAT_DUMP 0x00000080L /* large data output e.g. hex dump */
-#define SK_DBGCAT_FATAL 0x00000100L /* fatal error */
-
-#endif /* __INC_SKDEBUG_H */
diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
deleted file mode 100644
index 91b8d4f4590..00000000000
--- a/drivers/net/sk98lin/h/skdrv1st.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/******************************************************************************
- *
- * Name: skdrv1st.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.4 $
- * Date: $Date: 2003/11/12 14:28:14 $
- * Purpose: First header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the first include file of the driver, which includes all
- * neccessary system header files and some of the GEnesis header files.
- * It also defines some basic items.
- *
- * Include File Hierarchy:
- *
- * see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#define __INC_SKDRV1ST_H
-
-typedef struct s_AC SK_AC;
-
-/* Set card versions */
-#define SK_FAR
-
-/* override some default functions with optimized linux functions */
-
-#define SK_PNMI_STORE_U16(p,v) memcpy((char*)(p),(char*)&(v),2)
-#define SK_PNMI_STORE_U32(p,v) memcpy((char*)(p),(char*)&(v),4)
-#define SK_PNMI_STORE_U64(p,v) memcpy((char*)(p),(char*)&(v),8)
-#define SK_PNMI_READ_U16(p,v) memcpy((char*)&(v),(char*)(p),2)
-#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),4)
-#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),8)
-
-#define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6))
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <net/checksum.h>
-
-#define SK_CS_CALCULATE_CHECKSUM
-#ifndef CONFIG_X86_64
-#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff)
-#else
-#define SkCsCalculateChecksum(p,l) ((~ip_fast_csum(p, l)) & 0xffff)
-#endif
-
-#include "h/sktypes.h"
-#include "h/skerror.h"
-#include "h/skdebug.h"
-#include "h/lm80.h"
-#include "h/xmac_ii.h"
-
-#ifdef __LITTLE_ENDIAN
-#define SK_LITTLE_ENDIAN
-#else
-#define SK_BIG_ENDIAN
-#endif
-
-#define SK_NET_DEVICE net_device
-
-
-/* we use gethrtime(), return unit: nanoseconds */
-#define SK_TICKS_PER_SEC 100
-
-#define SK_MEM_MAPPED_IO
-
-// #define SK_RLMT_SLOW_LOOKAHEAD
-
-#define SK_MAX_MACS 2
-#define SK_MAX_NETS 2
-
-#define SK_IOC char __iomem *
-
-typedef struct s_DrvRlmtMbuf SK_MBUF;
-
-#define SK_CONST64 INT64_C
-#define SK_CONSTU64 UINT64_C
-
-#define SK_MEMCPY(dest,src,size) memcpy(dest,src,size)
-#define SK_MEMCMP(s1,s2,size) memcmp(s1,s2,size)
-#define SK_MEMSET(dest,val,size) memset(dest,val,size)
-#define SK_STRLEN(pStr) strlen((char*)(pStr))
-#define SK_STRNCPY(pDest,pSrc,size) strncpy((char*)(pDest),(char*)(pSrc),size)
-#define SK_STRCMP(pStr1,pStr2) strcmp((char*)(pStr1),(char*)(pStr2))
-
-/* macros to access the adapter */
-#define SK_OUT8(b,a,v) writeb((v), ((b)+(a)))
-#define SK_OUT16(b,a,v) writew((v), ((b)+(a)))
-#define SK_OUT32(b,a,v) writel((v), ((b)+(a)))
-#define SK_IN8(b,a,pv) (*(pv) = readb((b)+(a)))
-#define SK_IN16(b,a,pv) (*(pv) = readw((b)+(a)))
-#define SK_IN32(b,a,pv) (*(pv) = readl((b)+(a)))
-
-#define int8_t char
-#define int16_t short
-#define int32_t long
-#define int64_t long long
-#define uint8_t u_char
-#define uint16_t u_short
-#define uint32_t u_long
-#define uint64_t unsigned long long
-#define t_scalar_t int
-#define t_uscalar_t unsigned int
-#define uintptr_t unsigned long
-
-#define __CONCAT__(A,B) A##B
-
-#define INT32_C(a) __CONCAT__(a,L)
-#define INT64_C(a) __CONCAT__(a,LL)
-#define UINT32_C(a) __CONCAT__(a,UL)
-#define UINT64_C(a) __CONCAT__(a,ULL)
-
-#ifdef DEBUG
-#define SK_DBG_PRINTF printk
-#ifndef SK_DEBUG_CHKMOD
-#define SK_DEBUG_CHKMOD 0
-#endif
-#ifndef SK_DEBUG_CHKCAT
-#define SK_DEBUG_CHKCAT 0
-#endif
-/* those come from the makefile */
-#define SK_DBG_CHKMOD(pAC) (SK_DEBUG_CHKMOD)
-#define SK_DBG_CHKCAT(pAC) (SK_DEBUG_CHKCAT)
-
-extern void SkDbgPrintf(const char *format,...);
-
-#define SK_DBGMOD_DRV 0x00010000
-
-/**** possible driver debug categories ********************************/
-#define SK_DBGCAT_DRV_ENTRY 0x00010000
-#define SK_DBGCAT_DRV_SAP 0x00020000
-#define SK_DBGCAT_DRV_MCA 0x00040000
-#define SK_DBGCAT_DRV_TX_PROGRESS 0x00080000
-#define SK_DBGCAT_DRV_RX_PROGRESS 0x00100000
-#define SK_DBGCAT_DRV_PROGRESS 0x00200000
-#define SK_DBGCAT_DRV_MSG 0x00400000
-#define SK_DBGCAT_DRV_PROM 0x00800000
-#define SK_DBGCAT_DRV_TX_FRAME 0x01000000
-#define SK_DBGCAT_DRV_ERROR 0x02000000
-#define SK_DBGCAT_DRV_INT_SRC 0x04000000
-#define SK_DBGCAT_DRV_EVENT 0x08000000
-
-#endif
-
-#define SK_ERR_LOG SkErrorLog
-
-extern void SkErrorLog(SK_AC*, int, int, char*);
-
-#endif
-
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
deleted file mode 100644
index 3fa67171e83..00000000000
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ /dev/null
@@ -1,447 +0,0 @@
-/******************************************************************************
- *
- * Name: skdrv2nd.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.10 $
- * Date: $Date: 2003/12/11 16:04:45 $
- * Purpose: Second header file for driver and all other modules
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the second include file of the driver, which includes all other
- * neccessary files and defines all structures and constants used by the
- * driver and the common modules.
- *
- * Include File Hierarchy:
- *
- * see skge.c
- *
- ******************************************************************************/
-
-#ifndef __INC_SKDRV2ND_H
-#define __INC_SKDRV2ND_H
-
-#include "h/skqueue.h"
-#include "h/skgehwt.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skgepnmi.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skaddr.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skrlmt.h"
-#include "h/skgedrv.h"
-
-
-extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
-extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
-extern SK_U64 SkOsGetTime(SK_AC*);
-extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
-extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*);
-extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*);
-extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16);
-extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8);
-extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
-
-#ifdef SK_DIAG_SUPPORT
-extern int SkDrvEnterDiagMode(SK_AC *pAc);
-extern int SkDrvLeaveDiagMode(SK_AC *pAc);
-#endif
-
-struct s_DrvRlmtMbuf {
- SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */
- SK_U8 *pData; /* Data buffer (virtually contig.). */
- unsigned Size; /* Data buffer size. */
- unsigned Length; /* Length of packet (<= Size). */
- SK_U32 PortIdx; /* Receiving/transmitting port. */
-#ifdef SK_RLMT_MBUF_PRIVATE
- SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */
-#endif /* SK_RLMT_MBUF_PRIVATE */
- struct sk_buff *pOs; /* Pointer to message block */
-};
-
-
-/*
- * Time macros
- */
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t) (t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t) * 100) / \
- (SK_TICKS_PER_SEC))
-#endif
-
-/*
- * New SkOsGetTime
- */
-#define SkOsGetTimeCurrent(pAC, pUsec) {\
- struct timeval t;\
- do_gettimeofday(&t);\
- *pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\
-}
-
-
-/*
- * ioctl definitions
- */
-#define SK_IOCTL_BASE (SIOCDEVPRIVATE)
-#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0)
-#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1)
-#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2)
-#define SK_IOCTL_GEN (SK_IOCTL_BASE + 3)
-#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4)
-
-typedef struct s_IOCTL SK_GE_IOCTL;
-
-struct s_IOCTL {
- char __user * pData;
- unsigned int Len;
-};
-
-
-/*
- * define sizes of descriptor rings in bytes
- */
-
-#define TX_RING_SIZE (8*1024)
-#define RX_RING_SIZE (24*1024)
-
-/*
- * Buffer size for ethernet packets
- */
-#define ETH_BUF_SIZE 1540
-#define ETH_MAX_MTU 1514
-#define ETH_MIN_MTU 60
-#define ETH_MULTICAST_BIT 0x01
-#define SK_JUMBO_MTU 9000
-
-/*
- * transmit priority selects the queue: LOW=asynchron, HIGH=synchron
- */
-#define TX_PRIO_LOW 0
-#define TX_PRIO_HIGH 1
-
-/*
- * alignment of rx/tx descriptors
- */
-#define DESCR_ALIGN 64
-
-/*
- * definitions for pnmi. TODO
- */
-#define SK_DRIVER_RESET(pAC, IoC) 0
-#define SK_DRIVER_SENDEVENT(pAC, IoC) 0
-#define SK_DRIVER_SELFTEST(pAC, IoC) 0
-/* For get mtu you must add an own function */
-#define SK_DRIVER_GET_MTU(pAc,IoC,i) 0
-#define SK_DRIVER_SET_MTU(pAc,IoC,i,v) 0
-#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0
-
-/*
-** Interim definition of SK_DRV_TIMER placed in this file until
-** common modules have been finalized
-*/
-#define SK_DRV_TIMER 11
-#define SK_DRV_MODERATION_TIMER 1
-#define SK_DRV_MODERATION_TIMER_LENGTH 1000000 /* 1 second */
-#define SK_DRV_RX_CLEANUP_TIMER 2
-#define SK_DRV_RX_CLEANUP_TIMER_LENGTH 1000000 /* 100 millisecs */
-
-/*
-** Definitions regarding transmitting frames
-** any calculating any checksum.
-*/
-#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
-#define C_LEN_ETHERMAC_HEADER_SRC_ADDR 6
-#define C_LEN_ETHERMAC_HEADER_LENTYPE 2
-#define C_LEN_ETHERMAC_HEADER ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \
- (C_LEN_ETHERMAC_HEADER_SRC_ADDR) + \
- (C_LEN_ETHERMAC_HEADER_LENTYPE) )
-
-#define C_LEN_ETHERMTU_MINSIZE 46
-#define C_LEN_ETHERMTU_MAXSIZE_STD 1500
-#define C_LEN_ETHERMTU_MAXSIZE_JUMBO 9000
-
-#define C_LEN_ETHERNET_MINSIZE ( (C_LEN_ETHERMAC_HEADER) + \
- (C_LEN_ETHERMTU_MINSIZE) )
-
-#define C_OFFSET_IPHEADER C_LEN_ETHERMAC_HEADER
-#define C_OFFSET_IPHEADER_IPPROTO 9
-#define C_OFFSET_TCPHEADER_TCPCS 16
-#define C_OFFSET_UDPHEADER_UDPCS 6
-
-#define C_OFFSET_IPPROTO ( (C_LEN_ETHERMAC_HEADER) + \
- (C_OFFSET_IPHEADER_IPPROTO) )
-
-#define C_PROTO_ID_UDP 17 /* refer to RFC 790 or Stevens' */
-#define C_PROTO_ID_TCP 6 /* TCP/IP illustrated for details */
-
-/* TX and RX descriptors *****************************************************/
-
-typedef struct s_RxD RXD; /* the receive descriptor */
-
-struct s_RxD {
- volatile SK_U32 RBControl; /* Receive Buffer Control */
- SK_U32 VNextRxd; /* Next receive descriptor,low dword */
- SK_U32 VDataLow; /* Receive buffer Addr, low dword */
- SK_U32 VDataHigh; /* Receive buffer Addr, high dword */
- SK_U32 FrameStat; /* Receive Frame Status word */
- SK_U32 TimeStamp; /* Time stamp from XMAC */
- SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */
- SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */
- RXD *pNextRxd; /* Pointer to next Rxd */
- struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
-};
-
-typedef struct s_TxD TXD; /* the transmit descriptor */
-
-struct s_TxD {
- volatile SK_U32 TBControl; /* Transmit Buffer Control */
- SK_U32 VNextTxd; /* Next transmit descriptor,low dword */
- SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */
- SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */
- SK_U32 FrameStat; /* Transmit Frame Status Word */
- SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */
- SK_U16 TcpSumSt; /* TCP Sum Start */
- SK_U16 TcpSumWr; /* TCP Sum Write */
- SK_U32 TcpReserved; /* not used */
- TXD *pNextTxd; /* Pointer to next Txd */
- struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
-};
-
-/* Used interrupt bits in the interrupts source register *********************/
-
-#define DRIVER_IRQS ((IS_IRQ_SW) | \
- (IS_R1_F) |(IS_R2_F) | \
- (IS_XS1_F) |(IS_XA1_F) | \
- (IS_XS2_F) |(IS_XA2_F))
-
-#define SPECIAL_IRQS ((IS_HW_ERR) |(IS_I2C_READY) | \
- (IS_EXT_REG) |(IS_TIMINT) | \
- (IS_PA_TO_RX1) |(IS_PA_TO_RX2) | \
- (IS_PA_TO_TX1) |(IS_PA_TO_TX2) | \
- (IS_MAC1) |(IS_LNK_SYNC_M1)| \
- (IS_MAC2) |(IS_LNK_SYNC_M2)| \
- (IS_R1_C) |(IS_R2_C) | \
- (IS_XS1_C) |(IS_XA1_C) | \
- (IS_XS2_C) |(IS_XA2_C))
-
-#define IRQ_MASK ((IS_IRQ_SW) | \
- (IS_R1_B) |(IS_R1_F) |(IS_R2_B) |(IS_R2_F) | \
- (IS_XS1_B) |(IS_XS1_F) |(IS_XA1_B)|(IS_XA1_F)| \
- (IS_XS2_B) |(IS_XS2_F) |(IS_XA2_B)|(IS_XA2_F)| \
- (IS_HW_ERR) |(IS_I2C_READY)| \
- (IS_EXT_REG) |(IS_TIMINT) | \
- (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
- (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
- (IS_MAC1) |(IS_MAC2) | \
- (IS_R1_C) |(IS_R2_C) | \
- (IS_XS1_C) |(IS_XA1_C) | \
- (IS_XS2_C) |(IS_XA2_C))
-
-#define IRQ_HWE_MASK (IS_ERR_MSK) /* enable all HW irqs */
-
-typedef struct s_DevNet DEV_NET;
-
-struct s_DevNet {
- int PortNr;
- int NetNr;
- SK_AC *pAC;
-};
-
-typedef struct s_TxPort TX_PORT;
-
-struct s_TxPort {
- /* the transmit descriptor rings */
- caddr_t pTxDescrRing; /* descriptor area memory */
- SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */
- TXD *pTxdRingHead; /* Head of Tx rings */
- TXD *pTxdRingTail; /* Tail of Tx rings */
- TXD *pTxdRingPrev; /* descriptor sent previously */
- int TxdRingFree; /* # of free entrys */
- spinlock_t TxDesRingLock; /* serialize descriptor accesses */
- SK_IOC HwAddr; /* bmu registers address */
- int PortIndex; /* index number of port (0 or 1) */
-};
-
-typedef struct s_RxPort RX_PORT;
-
-struct s_RxPort {
- /* the receive descriptor rings */
- caddr_t pRxDescrRing; /* descriptor area memory */
- SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */
- RXD *pRxdRingHead; /* Head of Rx rings */
- RXD *pRxdRingTail; /* Tail of Rx rings */
- RXD *pRxdRingPrev; /* descriptor given to BMU previously */
- int RxdRingFree; /* # of free entrys */
- int RxCsum; /* use receive checksum hardware */
- spinlock_t RxDesRingLock; /* serialize descriptor accesses */
- int RxFillLimit; /* limit for buffers in ring */
- SK_IOC HwAddr; /* bmu registers address */
- int PortIndex; /* index number of port (0 or 1) */
-};
-
-/* Definitions needed for interrupt moderation *******************************/
-
-#define IRQ_EOF_AS_TX ((IS_XA1_F) | (IS_XA2_F))
-#define IRQ_EOF_SY_TX ((IS_XS1_F) | (IS_XS2_F))
-#define IRQ_MASK_TX_ONLY ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX))
-#define IRQ_MASK_RX_ONLY ((IS_R1_F) | (IS_R2_F))
-#define IRQ_MASK_SP_ONLY (SPECIAL_IRQS)
-#define IRQ_MASK_TX_RX ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_RX ((SPECIAL_IRQS) | (IRQ_MASK_RX_ONLY))
-#define IRQ_MASK_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY))
-#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX))
-
-#define C_INT_MOD_NONE 1
-#define C_INT_MOD_STATIC 2
-#define C_INT_MOD_DYNAMIC 4
-
-#define C_CLK_FREQ_GENESIS 53215000 /* shorter: 53.125 MHz */
-#define C_CLK_FREQ_YUKON 78215000 /* shorter: 78.125 MHz */
-
-#define C_INTS_PER_SEC_DEFAULT 2000
-#define C_INT_MOD_ENABLE_PERCENTAGE 50 /* if higher 50% enable */
-#define C_INT_MOD_DISABLE_PERCENTAGE 50 /* if lower 50% disable */
-#define C_INT_MOD_IPS_LOWER_RANGE 30
-#define C_INT_MOD_IPS_UPPER_RANGE 40000
-
-
-typedef struct s_DynIrqModInfo DIM_INFO;
-struct s_DynIrqModInfo {
- unsigned long PrevTimeVal;
- unsigned int PrevSysLoad;
- unsigned int PrevUsedTime;
- unsigned int PrevTotalTime;
- int PrevUsedDescrRatio;
- int NbrProcessedDescr;
- SK_U64 PrevPort0RxIntrCts;
- SK_U64 PrevPort1RxIntrCts;
- SK_U64 PrevPort0TxIntrCts;
- SK_U64 PrevPort1TxIntrCts;
- SK_BOOL ModJustEnabled; /* Moderation just enabled yes/no */
-
- int MaxModIntsPerSec; /* Moderation Threshold */
- int MaxModIntsPerSecUpperLimit; /* Upper limit for DIM */
- int MaxModIntsPerSecLowerLimit; /* Lower limit for DIM */
-
- long MaskIrqModeration; /* ModIrqType (eg. 'TxRx') */
- SK_BOOL DisplayStats; /* Stats yes/no */
- SK_BOOL AutoSizing; /* Resize DIM-timer on/off */
- int IntModTypeSelect; /* EnableIntMod (eg. 'dynamic') */
-
- SK_TIMER ModTimer; /* just some timer */
-};
-
-typedef struct s_PerStrm PER_STRM;
-
-#define SK_ALLOC_IRQ 0x00000001
-
-#ifdef SK_DIAG_SUPPORT
-#define DIAG_ACTIVE 1
-#define DIAG_NOTACTIVE 0
-#endif
-
-/****************************************************************************
- * Per board structure / Adapter Context structure:
- * Allocated within attach(9e) and freed within detach(9e).
- * Contains all 'per device' necessary handles, flags, locks etc.:
- */
-struct s_AC {
- SK_GEINIT GIni; /* GE init struct */
- SK_PNMI Pnmi; /* PNMI data struct */
- SK_VPD vpd; /* vpd data struct */
- SK_QUEUE Event; /* Event queue */
- SK_HWT Hwt; /* Hardware Timer control struct */
- SK_TIMCTRL Tim; /* Software Timer control struct */
- SK_I2C I2c; /* I2C relevant data structure */
- SK_ADDR Addr; /* for Address module */
- SK_CSUM Csum; /* for checksum module */
- SK_RLMT Rlmt; /* for rlmt module */
- spinlock_t SlowPathLock; /* Normal IRQ lock */
- struct timer_list BlinkTimer; /* for LED blinking */
- int LedsOn;
- SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */
- int RlmtMode; /* link check mode to set */
- int RlmtNets; /* Number of nets */
-
- SK_IOC IoBase; /* register set of adapter */
- int BoardLevel; /* level of active hw init (0-2) */
-
- SK_U32 AllocFlag; /* flag allocation of resources */
- struct pci_dev *PciDev; /* for access to pci config space */
- struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */
-
- int RxBufSize; /* length of receive buffers */
- struct net_device_stats stats; /* linux 'netstat -i' statistics */
- int Index; /* internal board index number */
-
- /* adapter RAM sizes for queues of active port */
- int RxQueueSize; /* memory used for receive queue */
- int TxSQueueSize; /* memory used for sync. tx queue */
- int TxAQueueSize; /* memory used for async. tx queue */
-
- int PromiscCount; /* promiscuous mode counter */
- int AllMultiCount; /* allmulticast mode counter */
- int MulticCount; /* number of different MC */
- /* addresses for this board */
- /* (may be more than HW can)*/
-
- int HWRevision; /* Hardware revision */
- int ActivePort; /* the active XMAC port */
- int MaxPorts; /* number of activated ports */
- int TxDescrPerRing; /* # of descriptors per tx ring */
- int RxDescrPerRing; /* # of descriptors per rx ring */
-
- caddr_t pDescrMem; /* Pointer to the descriptor area */
- dma_addr_t pDescrMemDMA; /* PCI DMA address of area */
-
- /* the port structures with descriptor rings */
- TX_PORT TxPort[SK_MAX_MACS][2];
- RX_PORT RxPort[SK_MAX_MACS];
-
- SK_BOOL CheckQueue; /* check event queue soon */
- SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */
- DIM_INFO DynIrqModInfo; /* all data related to DIM */
-
- /* Only for tests */
- int PortDown;
- int ChipsetType; /* Chipset family type
- * 0 == Genesis family support
- * 1 == Yukon family support
- */
-#ifdef SK_DIAG_SUPPORT
- SK_U32 DiagModeActive; /* is diag active? */
- SK_BOOL DiagFlowCtrl; /* for control purposes */
- SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for all Pnmi-Data */
- SK_BOOL WasIfUp[SK_MAX_MACS]; /* for OpenClose while
- * DIAG is busy with NIC
- */
-#endif
-
-};
-
-
-#endif /* __INC_SKDRV2ND_H */
-
diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h
deleted file mode 100644
index da062f76623..00000000000
--- a/drivers/net/sk98lin/h/skerror.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/******************************************************************************
- *
- * Name: skerror.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.7 $
- * Date: $Date: 2003/05/13 17:25:13 $
- * Purpose: SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKERROR_H_
-#define _INC_SKERROR_H_
-
-/*
- * Define Error Classes
- */
-#define SK_ERRCL_OTHER (0) /* Other error */
-#define SK_ERRCL_CONFIG (1L<<0) /* Configuration error */
-#define SK_ERRCL_INIT (1L<<1) /* Initialization error */
-#define SK_ERRCL_NORES (1L<<2) /* Out of Resources error */
-#define SK_ERRCL_SW (1L<<3) /* Internal Software error */
-#define SK_ERRCL_HW (1L<<4) /* Hardware Failure */
-#define SK_ERRCL_COMM (1L<<5) /* Communication error */
-
-
-/*
- * Define Error Code Bases
- */
-#define SK_ERRBASE_RLMT 100 /* Base Error number for RLMT */
-#define SK_ERRBASE_HWINIT 200 /* Base Error number for HWInit */
-#define SK_ERRBASE_VPD 300 /* Base Error number for VPD */
-#define SK_ERRBASE_PNMI 400 /* Base Error number for PNMI */
-#define SK_ERRBASE_CSUM 500 /* Base Error number for Checksum */
-#define SK_ERRBASE_SIRQ 600 /* Base Error number for Special IRQ */
-#define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */
-#define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */
-#define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */
-#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */
-#define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */
-
-#endif /* _INC_SKERROR_H_ */
diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h
deleted file mode 100644
index 44fd4c3de81..00000000000
--- a/drivers/net/sk98lin/h/skgedrv.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/******************************************************************************
- *
- * Name: skgedrv.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.10 $
- * Date: $Date: 2003/07/04 12:25:01 $
- * Purpose: Interface with the driver
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEDRV_H_
-#define __INC_SKGEDRV_H_
-
-/* defines ********************************************************************/
-
-/*
- * Define the driver events.
- * Usually the events are defined by the destination module.
- * In case of the driver we put the definition of the events here.
- */
-#define SK_DRV_PORT_RESET 1 /* The port needs to be reset */
-#define SK_DRV_NET_UP 2 /* The net is operational */
-#define SK_DRV_NET_DOWN 3 /* The net is down */
-#define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */
-#define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */
-#define SK_DRV_RLMT_SEND 6 /* Send a RLMT packet */
-#define SK_DRV_ADAP_FAIL 7 /* The whole adapter fails */
-#define SK_DRV_PORT_FAIL 8 /* One port fails */
-#define SK_DRV_SWITCH_INTERN 9 /* Port switch by the driver itself */
-#define SK_DRV_POWER_DOWN 10 /* Power down mode */
-#define SK_DRV_TIMER 11 /* Timer for free use */
-#ifdef SK_NO_RLMT
-#define SK_DRV_LINK_UP 12 /* Link Up event for driver */
-#define SK_DRV_LINK_DOWN 13 /* Link Down event for driver */
-#endif
-#define SK_DRV_DOWNSHIFT_DET 14 /* Downshift 4-Pair / 2-Pair (YUKON only) */
-#endif /* __INC_SKGEDRV_H_ */
diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h
deleted file mode 100644
index f6282b7956d..00000000000
--- a/drivers/net/sk98lin/h/skgehw.h
+++ /dev/null
@@ -1,2126 +0,0 @@
-/******************************************************************************
- *
- * Name: skgehw.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.56 $
- * Date: $Date: 2003/09/23 09:01:00 $
- * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEHW_H
-#define __INC_SKGEHW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define BIT_31 (1UL << 31)
-#define BIT_30 (1L << 30)
-#define BIT_29 (1L << 29)
-#define BIT_28 (1L << 28)
-#define BIT_27 (1L << 27)
-#define BIT_26 (1L << 26)
-#define BIT_25 (1L << 25)
-#define BIT_24 (1L << 24)
-#define BIT_23 (1L << 23)
-#define BIT_22 (1L << 22)
-#define BIT_21 (1L << 21)
-#define BIT_20 (1L << 20)
-#define BIT_19 (1L << 19)
-#define BIT_18 (1L << 18)
-#define BIT_17 (1L << 17)
-#define BIT_16 (1L << 16)
-#define BIT_15 (1L << 15)
-#define BIT_14 (1L << 14)
-#define BIT_13 (1L << 13)
-#define BIT_12 (1L << 12)
-#define BIT_11 (1L << 11)
-#define BIT_10 (1L << 10)
-#define BIT_9 (1L << 9)
-#define BIT_8 (1L << 8)
-#define BIT_7 (1L << 7)
-#define BIT_6 (1L << 6)
-#define BIT_5 (1L << 5)
-#define BIT_4 (1L << 4)
-#define BIT_3 (1L << 3)
-#define BIT_2 (1L << 2)
-#define BIT_1 (1L << 1)
-#define BIT_0 1L
-
-#define BIT_15S (1U << 15)
-#define BIT_14S (1 << 14)
-#define BIT_13S (1 << 13)
-#define BIT_12S (1 << 12)
-#define BIT_11S (1 << 11)
-#define BIT_10S (1 << 10)
-#define BIT_9S (1 << 9)
-#define BIT_8S (1 << 8)
-#define BIT_7S (1 << 7)
-#define BIT_6S (1 << 6)
-#define BIT_5S (1 << 5)
-#define BIT_4S (1 << 4)
-#define BIT_3S (1 << 3)
-#define BIT_2S (1 << 2)
-#define BIT_1S (1 << 1)
-#define BIT_0S 1
-
-#define SHIFT31(x) ((x) << 31)
-#define SHIFT30(x) ((x) << 30)
-#define SHIFT29(x) ((x) << 29)
-#define SHIFT28(x) ((x) << 28)
-#define SHIFT27(x) ((x) << 27)
-#define SHIFT26(x) ((x) << 26)
-#define SHIFT25(x) ((x) << 25)
-#define SHIFT24(x) ((x) << 24)
-#define SHIFT23(x) ((x) << 23)
-#define SHIFT22(x) ((x) << 22)
-#define SHIFT21(x) ((x) << 21)
-#define SHIFT20(x) ((x) << 20)
-#define SHIFT19(x) ((x) << 19)
-#define SHIFT18(x) ((x) << 18)
-#define SHIFT17(x) ((x) << 17)
-#define SHIFT16(x) ((x) << 16)
-#define SHIFT15(x) ((x) << 15)
-#define SHIFT14(x) ((x) << 14)
-#define SHIFT13(x) ((x) << 13)
-#define SHIFT12(x) ((x) << 12)
-#define SHIFT11(x) ((x) << 11)
-#define SHIFT10(x) ((x) << 10)
-#define SHIFT9(x) ((x) << 9)
-#define SHIFT8(x) ((x) << 8)
-#define SHIFT7(x) ((x) << 7)
-#define SHIFT6(x) ((x) << 6)
-#define SHIFT5(x) ((x) << 5)
-#define SHIFT4(x) ((x) << 4)
-#define SHIFT3(x) ((x) << 3)
-#define SHIFT2(x) ((x) << 2)
-#define SHIFT1(x) ((x) << 1)
-#define SHIFT0(x) ((x) << 0)
-
-/*
- * Configuration Space header
- * Since this module is used for different OS', those may be
- * duplicate on some of them (e.g. Linux). But to keep the
- * common source, we have to live with this...
- */
-#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */
-#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */
-#define PCI_COMMAND 0x04 /* 16 bit Command */
-#define PCI_STATUS 0x06 /* 16 bit Status */
-#define PCI_REV_ID 0x08 /* 8 bit Revision ID */
-#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */
-#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */
-#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */
-#define PCI_HEADER_T 0x0e /* 8 bit Header Type */
-#define PCI_BIST 0x0f /* 8 bit Built-in selftest */
-#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */
-#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */
- /* Byte 0x18..0x2b: reserved */
-#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */
-#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */
-#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */
-#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */
- /* Byte 0x35..0x3b: reserved */
-#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */
-#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */
-#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */
-#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */
- /* Device Dependent Region */
-#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */
-#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */
- /* Power Management Region */
-#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */
-#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */
-#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */
-#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */
- /* Byte 0x4e: reserved */
-#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */
- /* VPD Region */
-#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */
-#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */
-#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */
-#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */
- /* Byte 0x58..0x59: reserved */
-#define PCI_SER_LD_CTRL 0x5a /* 16 bit SEEPROM Loader Ctrl (YUKON only) */
- /* Byte 0x5c..0xff: reserved */
-
-/*
- * I2C Address (PCI Config)
- *
- * Note: The temperature and voltage sensors are relocated on a different
- * I2C bus.
- */
-#define I2C_ADDR_VPD 0xa0 /* I2C address for the VPD EEPROM */
-
-/*
- * Define Bits and Values of the registers
- */
-/* PCI_COMMAND 16 bit Command */
- /* Bit 15..11: reserved */
-#define PCI_INT_DIS BIT_10S /* Interrupt INTx# disable (PCI 2.3) */
-#define PCI_FBTEN BIT_9S /* Fast Back-To-Back enable */
-#define PCI_SERREN BIT_8S /* SERR enable */
-#define PCI_ADSTEP BIT_7S /* Address Stepping */
-#define PCI_PERREN BIT_6S /* Parity Report Response enable */
-#define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */
-#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */
-#define PCI_SCYCEN BIT_3S /* Special Cycle enable */
-#define PCI_BMEN BIT_2S /* Bus Master enable */
-#define PCI_MEMEN BIT_1S /* Memory Space Access enable */
-#define PCI_IOEN BIT_0S /* I/O Space Access enable */
-
-#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\
- PCI_BMEN | PCI_MEMEN | PCI_IOEN)
-
-/* PCI_STATUS 16 bit Status */
-#define PCI_PERR BIT_15S /* Parity Error */
-#define PCI_SERR BIT_14S /* Signaled SERR */
-#define PCI_RMABORT BIT_13S /* Received Master Abort */
-#define PCI_RTABORT BIT_12S /* Received Target Abort */
- /* Bit 11: reserved */
-#define PCI_DEVSEL (3<<9) /* Bit 10.. 9: DEVSEL Timing */
-#define PCI_DEV_FAST (0<<9) /* fast */
-#define PCI_DEV_MEDIUM (1<<9) /* medium */
-#define PCI_DEV_SLOW (2<<9) /* slow */
-#define PCI_DATAPERR BIT_8S /* DATA Parity error detected */
-#define PCI_FB2BCAP BIT_7S /* Fast Back-to-Back Capability */
-#define PCI_UDF BIT_6S /* User Defined Features */
-#define PCI_66MHZCAP BIT_5S /* 66 MHz PCI bus clock capable */
-#define PCI_NEWCAP BIT_4S /* New cap. list implemented */
-#define PCI_INT_STAT BIT_3S /* Interrupt INTx# Status (PCI 2.3) */
- /* Bit 2.. 0: reserved */
-
-#define PCI_ERRBITS (PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\
- PCI_DATAPERR)
-
-/* PCI_CLASS_CODE 24 bit Class Code */
-/* Byte 2: Base Class (02) */
-/* Byte 1: SubClass (00) */
-/* Byte 0: Programming Interface (00) */
-
-/* PCI_CACHE_LSZ 8 bit Cache Line Size */
-/* Possible values: 0,2,4,8,16,32,64,128 */
-
-/* PCI_HEADER_T 8 bit Header Type */
-#define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */
-#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */
-
-/* PCI_BIST 8 bit Built-in selftest */
-/* Built-in Self test not supported (optional) */
-
-/* PCI_BASE_1ST 32 bit 1st Base address */
-#define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */
-#define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */
-#define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */
-#define PCI_PREFEN BIT_3 /* Prefetchable */
-#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */
-#define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */
-#define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */
-#define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */
-#define PCI_MEMSPACE BIT_0 /* Memory Space Indicator */
-
-/* PCI_BASE_2ND 32 bit 2nd Base address */
-#define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */
-#define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */
- /* Bit 1: reserved */
-#define PCI_IOSPACE BIT_0 /* I/O Space Indicator */
-
-/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */
-#define PCI_ROMBASE_MSK 0xfffe0000L /* Bit 31..17: ROM Base address */
-#define PCI_ROMBASE_SIZ (0x1cL<<14) /* Bit 16..14: Treat as Base or Size */
-#define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */
- /* Bit 10.. 1: reserved */
-#define PCI_ROMEN BIT_0 /* Address Decode enable */
-
-/* Device Dependent Region */
-/* PCI_OUR_REG_1 32 bit Our Register 1 */
- /* Bit 31..29: reserved */
-#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode (YUKON only) */
-#define PCI_TEST_CAL BIT_27 /* Test PCI buffer calib. (YUKON only) */
-#define PCI_EN_CAL BIT_26 /* Enable PCI buffer calib. (YUKON only) */
-#define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
-#define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */
-#define PCI_EN_IO BIT_23 /* Mapping to I/O space */
-#define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */
- /* 1 = Map Flash to memory */
- /* 0 = Disable addr. dec */
-#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */
-#define PCI_PAGE_16 (0L<<20) /* 16 k pages */
-#define PCI_PAGE_32K (1L<<20) /* 32 k pages */
-#define PCI_PAGE_64K (2L<<20) /* 64 k pages */
-#define PCI_PAGE_128K (3L<<20) /* 128 k pages */
- /* Bit 19: reserved */
-#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */
-#define PCI_NOTAR BIT_15 /* No turnaround cycle */
-#define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */
-#define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */
-#define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */
-#define PCI_DIS_MWI BIT_11 /* Disable Mem Write & Invalidate */
-#define PCI_DISC_CLS BIT_10 /* Disc: cacheLsz bound */
-#define PCI_BURST_DIS BIT_9 /* Burst Disable */
-#define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */
-#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */
-#define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */
-
-
-/* PCI_OUR_REG_2 32 bit Our Register 2 */
-#define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */
-#define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */
-#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */
- /* Bit 13..12: reserved */
-#define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */
-#define PCI_PATCH_DIR_3 BIT_11
-#define PCI_PATCH_DIR_2 BIT_10
-#define PCI_PATCH_DIR_1 BIT_9
-#define PCI_PATCH_DIR_0 BIT_8
-#define PCI_EXT_PATCHS (0xfL<<4) /* Bit 7.. 4: Extended Patches 3..0 */
-#define PCI_EXT_PATCH_3 BIT_7
-#define PCI_EXT_PATCH_2 BIT_6
-#define PCI_EXT_PATCH_1 BIT_5
-#define PCI_EXT_PATCH_0 BIT_4
-#define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */
-#define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */
- /* Bit 1: reserved */
-#define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */
-
-
-/* Power Management Region */
-/* PCI_PM_CAP_REG 16 bit Power Management Capabilities */
-#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */
-#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */
-#define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */
-#define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */
-#define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */
-#define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */
-#define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */
-#define PCI_PM_D1_SUP BIT_9S /* D1 Support */
- /* Bit 8.. 6: reserved */
-#define PCI_PM_DSI BIT_5S /* Device Specific Initialization */
-#define PCI_PM_APS BIT_4S /* Auxialiary Power Source */
-#define PCI_PME_CLOCK BIT_3S /* PM Event Clock */
-#define PCI_PM_VER_MSK 7 /* Bit 2.. 0: PM PCI Spec. version */
-
-/* PCI_PM_CTL_STS 16 bit Power Management Control/Status */
-#define PCI_PME_STATUS BIT_15S /* PME Status (YUKON only) */
-#define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */
-#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */
-#define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */
- /* Bit 7.. 2: reserved */
-#define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */
-
-#define PCI_PM_STATE_D0 0 /* D0: Operational (default) */
-#define PCI_PM_STATE_D1 1 /* D1: (YUKON only) */
-#define PCI_PM_STATE_D2 2 /* D2: (YUKON only) */
-#define PCI_PM_STATE_D3 3 /* D3: HOT, Power Down and Reset */
-
-/* VPD Region */
-/* PCI_VPD_ADR_REG 16 bit VPD Address Register */
-#define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */
-#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */
-
-/* Control Register File (Address Map) */
-
-/*
- * Bank 0
- */
-#define B0_RAP 0x0000 /* 8 bit Register Address Port */
- /* 0x0001 - 0x0003: reserved */
-#define B0_CTST 0x0004 /* 16 bit Control/Status register */
-#define B0_LED 0x0006 /* 8 Bit LED register */
-#define B0_POWER_CTRL 0x0007 /* 8 Bit Power Control reg (YUKON only) */
-#define B0_ISRC 0x0008 /* 32 bit Interrupt Source Register */
-#define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */
-#define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */
-#define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */
-#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */
- /* 0x001c: reserved */
-
-/* B0 XMAC 1 registers (GENESIS only) */
-#define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/
- /* 0x0022 - 0x0027: reserved */
-#define B0_XM1_ISRC 0x0028 /* 16 bit ro XMAC 1 Interrupt Status Reg */
- /* 0x002a - 0x002f: reserved */
-#define B0_XM1_PHY_ADDR 0x0030 /* 16 bit r/w XMAC 1 PHY Address Register */
- /* 0x0032 - 0x0033: reserved */
-#define B0_XM1_PHY_DATA 0x0034 /* 16 bit r/w XMAC 1 PHY Data Register */
- /* 0x0036 - 0x003f: reserved */
-
-/* B0 XMAC 2 registers (GENESIS only) */
-#define B0_XM2_IMSK 0x0040 /* 16 bit r/w XMAC 2 Interrupt Mask Register*/
- /* 0x0042 - 0x0047: reserved */
-#define B0_XM2_ISRC 0x0048 /* 16 bit ro XMAC 2 Interrupt Status Reg */
- /* 0x004a - 0x004f: reserved */
-#define B0_XM2_PHY_ADDR 0x0050 /* 16 bit r/w XMAC 2 PHY Address Register */
- /* 0x0052 - 0x0053: reserved */
-#define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */
- /* 0x0056 - 0x005f: reserved */
-
-/* BMU Control Status Registers */
-#define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */
-#define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */
-#define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
-#define B0_XA1_CSR 0x006c /* 32 bit BMU Ctrl/Stat Async Tx Queue 1*/
-#define B0_XS2_CSR 0x0070 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
-#define B0_XA2_CSR 0x0074 /* 32 bit BMU Ctrl/Stat Async Tx Queue 2*/
- /* 0x0078 - 0x007f: reserved */
-
-/*
- * Bank 1
- * - completely empty (this is the RAP Block window)
- * Note: if RAP = 1 this page is reserved
- */
-
-/*
- * Bank 2
- */
-/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */
-#define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */
- /* 0x0106 - 0x0107: reserved */
-#define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */
- /* 0x010e - 0x010f: reserved */
-#define B2_MAC_3 0x0110 /* NA reg MAC Address 3 */
- /* 0x0116 - 0x0117: reserved */
-#define B2_CONN_TYP 0x0118 /* 8 bit Connector type */
-#define B2_PMD_TYP 0x0119 /* 8 bit PMD type */
-#define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */
-#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */
- /* Eprom registers are currently of no use */
-#define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */
-#define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */
-#define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */
-#define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */
-#define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */
-#define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */
- /* 0x0125 - 0x0127: reserved */
-#define B2_LD_CTRL 0x0128 /* 8 bit EPROM loader control register */
-#define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */
- /* 0x012a - 0x012f: reserved */
-#define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */
-#define B2_TI_VAL 0x0134 /* 32 bit Timer Value */
-#define B2_TI_CTRL 0x0138 /* 8 bit Timer Control */
-#define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */
- /* 0x013a - 0x013f: reserved */
-#define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/
-#define B2_IRQM_VAL 0x0144 /* 32 bit IRQ Moderation Timer Value */
-#define B2_IRQM_CTRL 0x0148 /* 8 bit IRQ Moderation Timer Control */
-#define B2_IRQM_TEST 0x0149 /* 8 bit IRQ Moderation Timer Test */
-#define B2_IRQM_MSK 0x014c /* 32 bit IRQ Moderation Mask */
-#define B2_IRQM_HWE_MSK 0x0150 /* 32 bit IRQ Moderation HW Error Mask */
- /* 0x0154 - 0x0157: reserved */
-#define B2_TST_CTRL1 0x0158 /* 8 bit Test Control Register 1 */
-#define B2_TST_CTRL2 0x0159 /* 8 bit Test Control Register 2 */
- /* 0x015a - 0x015b: reserved */
-#define B2_GP_IO 0x015c /* 32 bit General Purpose I/O Register */
-#define B2_I2C_CTRL 0x0160 /* 32 bit I2C HW Control Register */
-#define B2_I2C_DATA 0x0164 /* 32 bit I2C HW Data Register */
-#define B2_I2C_IRQ 0x0168 /* 32 bit I2C HW IRQ Register */
-#define B2_I2C_SW 0x016c /* 32 bit I2C SW Port Register */
-
-/* Blink Source Counter (GENESIS only) */
-#define B2_BSC_INI 0x0170 /* 32 bit Blink Source Counter Init Val */
-#define B2_BSC_VAL 0x0174 /* 32 bit Blink Source Counter Value */
-#define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */
-#define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */
-#define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */
- /* 0x017c - 0x017f: reserved */
-
-/*
- * Bank 3
- */
-/* RAM Random Registers */
-#define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */
-#define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */
-#define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */
- /* 0x018c - 0x018f: reserved */
-
-/* RAM Interface Registers */
-/*
- * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
- * not usable in SW. Please notice these are NOT real timeouts, these are
- * the number of qWords transferred continuously.
- */
-#define B3_RI_WTO_R1 0x0190 /* 8 bit WR Timeout Queue R1 (TO0) */
-#define B3_RI_WTO_XA1 0x0191 /* 8 bit WR Timeout Queue XA1 (TO1) */
-#define B3_RI_WTO_XS1 0x0192 /* 8 bit WR Timeout Queue XS1 (TO2) */
-#define B3_RI_RTO_R1 0x0193 /* 8 bit RD Timeout Queue R1 (TO3) */
-#define B3_RI_RTO_XA1 0x0194 /* 8 bit RD Timeout Queue XA1 (TO4) */
-#define B3_RI_RTO_XS1 0x0195 /* 8 bit RD Timeout Queue XS1 (TO5) */
-#define B3_RI_WTO_R2 0x0196 /* 8 bit WR Timeout Queue R2 (TO6) */
-#define B3_RI_WTO_XA2 0x0197 /* 8 bit WR Timeout Queue XA2 (TO7) */
-#define B3_RI_WTO_XS2 0x0198 /* 8 bit WR Timeout Queue XS2 (TO8) */
-#define B3_RI_RTO_R2 0x0199 /* 8 bit RD Timeout Queue R2 (TO9) */
-#define B3_RI_RTO_XA2 0x019a /* 8 bit RD Timeout Queue XA2 (TO10)*/
-#define B3_RI_RTO_XS2 0x019b /* 8 bit RD Timeout Queue XS2 (TO11)*/
-#define B3_RI_TO_VAL 0x019c /* 8 bit Current Timeout Count Val */
- /* 0x019d - 0x019f: reserved */
-#define B3_RI_CTRL 0x01a0 /* 16 bit RAM Interface Control Register */
-#define B3_RI_TEST 0x01a2 /* 8 bit RAM Interface Test Register */
- /* 0x01a3 - 0x01af: reserved */
-
-/* MAC Arbiter Registers (GENESIS only) */
-/* these are the no. of qWord transferred continuously and NOT real timeouts */
-#define B3_MA_TOINI_RX1 0x01b0 /* 8 bit Timeout Init Val Rx Path MAC 1 */
-#define B3_MA_TOINI_RX2 0x01b1 /* 8 bit Timeout Init Val Rx Path MAC 2 */
-#define B3_MA_TOINI_TX1 0x01b2 /* 8 bit Timeout Init Val Tx Path MAC 1 */
-#define B3_MA_TOINI_TX2 0x01b3 /* 8 bit Timeout Init Val Tx Path MAC 2 */
-#define B3_MA_TOVAL_RX1 0x01b4 /* 8 bit Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_RX2 0x01b5 /* 8 bit Timeout Value Rx Path MAC 1 */
-#define B3_MA_TOVAL_TX1 0x01b6 /* 8 bit Timeout Value Tx Path MAC 2 */
-#define B3_MA_TOVAL_TX2 0x01b7 /* 8 bit Timeout Value Tx Path MAC 2 */
-#define B3_MA_TO_CTRL 0x01b8 /* 16 bit MAC Arbiter Timeout Ctrl Reg */
-#define B3_MA_TO_TEST 0x01ba /* 16 bit MAC Arbiter Timeout Test Reg */
- /* 0x01bc - 0x01bf: reserved */
-#define B3_MA_RCINI_RX1 0x01c0 /* 8 bit Recovery Init Val Rx Path MAC 1 */
-#define B3_MA_RCINI_RX2 0x01c1 /* 8 bit Recovery Init Val Rx Path MAC 2 */
-#define B3_MA_RCINI_TX1 0x01c2 /* 8 bit Recovery Init Val Tx Path MAC 1 */
-#define B3_MA_RCINI_TX2 0x01c3 /* 8 bit Recovery Init Val Tx Path MAC 2 */
-#define B3_MA_RCVAL_RX1 0x01c4 /* 8 bit Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_RX2 0x01c5 /* 8 bit Recovery Value Rx Path MAC 1 */
-#define B3_MA_RCVAL_TX1 0x01c6 /* 8 bit Recovery Value Tx Path MAC 2 */
-#define B3_MA_RCVAL_TX2 0x01c7 /* 8 bit Recovery Value Tx Path MAC 2 */
-#define B3_MA_RC_CTRL 0x01c8 /* 16 bit MAC Arbiter Recovery Ctrl Reg */
-#define B3_MA_RC_TEST 0x01ca /* 16 bit MAC Arbiter Recovery Test Reg */
- /* 0x01cc - 0x01cf: reserved */
-
-/* Packet Arbiter Registers (GENESIS only) */
-/* these are real timeouts */
-#define B3_PA_TOINI_RX1 0x01d0 /* 16 bit Timeout Init Val Rx Path MAC 1 */
- /* 0x01d2 - 0x01d3: reserved */
-#define B3_PA_TOINI_RX2 0x01d4 /* 16 bit Timeout Init Val Rx Path MAC 2 */
- /* 0x01d6 - 0x01d7: reserved */
-#define B3_PA_TOINI_TX1 0x01d8 /* 16 bit Timeout Init Val Tx Path MAC 1 */
- /* 0x01da - 0x01db: reserved */
-#define B3_PA_TOINI_TX2 0x01dc /* 16 bit Timeout Init Val Tx Path MAC 2 */
- /* 0x01de - 0x01df: reserved */
-#define B3_PA_TOVAL_RX1 0x01e0 /* 16 bit Timeout Val Rx Path MAC 1 */
- /* 0x01e2 - 0x01e3: reserved */
-#define B3_PA_TOVAL_RX2 0x01e4 /* 16 bit Timeout Val Rx Path MAC 2 */
- /* 0x01e6 - 0x01e7: reserved */
-#define B3_PA_TOVAL_TX1 0x01e8 /* 16 bit Timeout Val Tx Path MAC 1 */
- /* 0x01ea - 0x01eb: reserved */
-#define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */
- /* 0x01ee - 0x01ef: reserved */
-#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */
-#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */
- /* 0x01f4 - 0x01ff: reserved */
-
-/*
- * Bank 4 - 5
- */
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-#define TXA_ITI_INI 0x0200 /* 32 bit Tx Arb Interval Timer Init Val*/
-#define TXA_ITI_VAL 0x0204 /* 32 bit Tx Arb Interval Timer Value */
-#define TXA_LIM_INI 0x0208 /* 32 bit Tx Arb Limit Counter Init Val */
-#define TXA_LIM_VAL 0x020c /* 32 bit Tx Arb Limit Counter Value */
-#define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */
-#define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */
-#define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */
- /* 0x0213 - 0x027f: reserved */
- /* 0x0280 - 0x0292: MAC 2 */
- /* 0x0213 - 0x027f: reserved */
-
-/*
- * Bank 6
- */
-/* External registers (GENESIS only) */
-#define B6_EXT_REG 0x0300
-
-/*
- * Bank 7
- */
-/* This is a copy of the Configuration register file (lower half) */
-#define B7_CFG_SPC 0x0380
-
-/*
- * Bank 8 - 15
- */
-/* Receive and Transmit Queue Registers, use Q_ADDR() to access */
-#define B8_Q_REGS 0x0400
-
-/* Queue Register Offsets, use Q_ADDR() to access */
-#define Q_D 0x00 /* 8*32 bit Current Descriptor */
-#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low dWord */
-#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High dWord */
-#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low dWord */
-#define Q_AC_H 0x2c /* 32 bit Current Address Counter High dWord */
-#define Q_BC 0x30 /* 32 bit Current Byte Counter */
-#define Q_CSR 0x34 /* 32 bit BMU Control/Status Register */
-#define Q_F 0x38 /* 32 bit Flag Register */
-#define Q_T1 0x3c /* 32 bit Test Register 1 */
-#define Q_T1_TR 0x3c /* 8 bit Test Register 1 Transfer SM */
-#define Q_T1_WR 0x3d /* 8 bit Test Register 1 Write Descriptor SM */
-#define Q_T1_RD 0x3e /* 8 bit Test Register 1 Read Descriptor SM */
-#define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */
-#define Q_T2 0x40 /* 32 bit Test Register 2 */
-#define Q_T3 0x44 /* 32 bit Test Register 3 */
- /* 0x48 - 0x7f: reserved */
-
-/*
- * Bank 16 - 23
- */
-/* RAM Buffer Registers */
-#define B16_RAM_REGS 0x0800
-
-/* RAM Buffer Register Offsets, use RB_ADDR() to access */
-#define RB_START 0x00 /* 32 bit RAM Buffer Start Address */
-#define RB_END 0x04 /* 32 bit RAM Buffer End Address */
-#define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */
-#define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */
-#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */
-#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */
-#define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */
-#define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */
- /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
-#define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */
-#define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */
-#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */
-#define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */
-#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */
- /* 0x2c - 0x7f: reserved */
-
-/*
- * Bank 24
- */
-/*
- * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only)
- * use MR_ADDR() to access
- */
-#define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */
-#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */
- /* 0x0c08 - 0x0c0b: reserved */
-#define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */
-#define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */
-#define RX_MFF_LEV 0x0c14 /* 32 bit Receive MAC FIFO Level */
-#define RX_MFF_CTRL1 0x0c18 /* 16 bit Receive MAC FIFO Control Reg 1*/
-#define RX_MFF_STAT_TO 0x0c1a /* 8 bit Receive MAC Status Timeout */
-#define RX_MFF_TIST_TO 0x0c1b /* 8 bit Receive MAC Time Stamp Timeout */
-#define RX_MFF_CTRL2 0x0c1c /* 8 bit Receive MAC FIFO Control Reg 2*/
-#define RX_MFF_TST1 0x0c1d /* 8 bit Receive MAC FIFO Test Reg 1 */
-#define RX_MFF_TST2 0x0c1e /* 8 bit Receive MAC FIFO Test Reg 2 */
- /* 0x0c1f: reserved */
-#define RX_LED_INI 0x0c20 /* 32 bit Receive LED Cnt Init Value */
-#define RX_LED_VAL 0x0c24 /* 32 bit Receive LED Cnt Current Value */
-#define RX_LED_CTRL 0x0c28 /* 8 bit Receive LED Cnt Control Reg */
-#define RX_LED_TST 0x0c29 /* 8 bit Receive LED Cnt Test Register */
- /* 0x0c2a - 0x0c2f: reserved */
-#define LNK_SYNC_INI 0x0c30 /* 32 bit Link Sync Cnt Init Value */
-#define LNK_SYNC_VAL 0x0c34 /* 32 bit Link Sync Cnt Current Value */
-#define LNK_SYNC_CTRL 0x0c38 /* 8 bit Link Sync Cnt Control Register */
-#define LNK_SYNC_TST 0x0c39 /* 8 bit Link Sync Cnt Test Register */
- /* 0x0c3a - 0x0c3b: reserved */
-#define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */
- /* 0x0c3d - 0x0c3f: reserved */
-
-/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */
-#define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */
-#define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */
-#define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */
-#define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */
- /* 0x0c54 - 0x0c5f: reserved */
-#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */
- /* 0x0c64 - 0x0c67: reserved */
-#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */
- /* 0x0c6c - 0x0c6f: reserved */
-#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */
- /* 0x0c74 - 0x0c77: reserved */
-#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */
- /* 0x0c7c - 0x0c7f: reserved */
-
-/*
- * Bank 25
- */
- /* 0x0c80 - 0x0cbf: MAC 2 */
- /* 0x0cc0 - 0x0cff: reserved */
-
-/*
- * Bank 26
- */
-/*
- * Transmit MAC FIFO and Transmit LED Registers (GENESIS only),
- * use MR_ADDR() to access
- */
-#define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */
-#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */
-#define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */
-#define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */
-#define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */
-#define TX_MFF_LEV 0x0d14 /* 32 bit Transmit MAC FIFO Level */
-#define TX_MFF_CTRL1 0x0d18 /* 16 bit Transmit MAC FIFO Ctrl Reg 1 */
-#define TX_MFF_WAF 0x0d1a /* 8 bit Transmit MAC Wait after flush */
- /* 0x0c1b: reserved */
-#define TX_MFF_CTRL2 0x0d1c /* 8 bit Transmit MAC FIFO Ctrl Reg 2 */
-#define TX_MFF_TST1 0x0d1d /* 8 bit Transmit MAC FIFO Test Reg 1 */
-#define TX_MFF_TST2 0x0d1e /* 8 bit Transmit MAC FIFO Test Reg 2 */
- /* 0x0d1f: reserved */
-#define TX_LED_INI 0x0d20 /* 32 bit Transmit LED Cnt Init Value */
-#define TX_LED_VAL 0x0d24 /* 32 bit Transmit LED Cnt Current Val */
-#define TX_LED_CTRL 0x0d28 /* 8 bit Transmit LED Cnt Control Reg */
-#define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */
- /* 0x0d2a - 0x0d3f: reserved */
-
-/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */
-#define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */
-#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
-#define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */
- /* 0x0d4c - 0x0d5f: reserved */
-#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */
-#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */
-#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */
- /* 0x0d6c - 0x0d6f: reserved */
-#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */
-#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */
-#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */
- /* 0x0d7c - 0x0d7f: reserved */
-
-/*
- * Bank 27
- */
- /* 0x0d80 - 0x0dbf: MAC 2 */
- /* 0x0daa - 0x0dff: reserved */
-
-/*
- * Bank 28
- */
-/* Descriptor Poll Timer Registers */
-#define B28_DPT_INI 0x0e00 /* 24 bit Descriptor Poll Timer Init Val */
-#define B28_DPT_VAL 0x0e04 /* 24 bit Descriptor Poll Timer Curr Val */
-#define B28_DPT_CTRL 0x0e08 /* 8 bit Descriptor Poll Timer Ctrl Reg */
- /* 0x0e09: reserved */
-#define B28_DPT_TST 0x0e0a /* 8 bit Descriptor Poll Timer Test Reg */
- /* 0x0e0b: reserved */
-
-/* Time Stamp Timer Registers (YUKON only) */
- /* 0x0e10: reserved */
-#define GMAC_TI_ST_VAL 0x0e14 /* 32 bit Time Stamp Timer Curr Val */
-#define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */
- /* 0x0e19: reserved */
-#define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */
- /* 0x0e1b - 0x0e7f: reserved */
-
-/*
- * Bank 29
- */
- /* 0x0e80 - 0x0efc: reserved */
-
-/*
- * Bank 30
- */
-/* GMAC and GPHY Control Registers (YUKON only) */
-#define GMAC_CTRL 0x0f00 /* 32 bit GMAC Control Reg */
-#define GPHY_CTRL 0x0f04 /* 32 bit GPHY Control Reg */
-#define GMAC_IRQ_SRC 0x0f08 /* 8 bit GMAC Interrupt Source Reg */
- /* 0x0f09 - 0x0f0b: reserved */
-#define GMAC_IRQ_MSK 0x0f0c /* 8 bit GMAC Interrupt Mask Reg */
- /* 0x0f0d - 0x0f0f: reserved */
-#define GMAC_LINK_CTRL 0x0f10 /* 16 bit Link Control Reg */
- /* 0x0f14 - 0x0f1f: reserved */
-
-/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
-
-#define WOL_REG_OFFS 0x20 /* HW-Bug: Address is + 0x20 against spec. */
-
-#define WOL_CTRL_STAT 0x0f20 /* 16 bit WOL Control/Status Reg */
-#define WOL_MATCH_CTL 0x0f22 /* 8 bit WOL Match Control Reg */
-#define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */
-#define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */
-#define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */
-#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */
-
-/* use this macro to access above registers */
-#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs))
-
-
-/* WOL Pattern Length Registers (YUKON only) */
-
-#define WOL_PATT_LEN_LO 0x0f30 /* 32 bit WOL Pattern Length 3..0 */
-#define WOL_PATT_LEN_HI 0x0f34 /* 24 bit WOL Pattern Length 6..4 */
-
-/* WOL Pattern Counter Registers (YUKON only) */
-
-#define WOL_PATT_CNT_0 0x0f38 /* 32 bit WOL Pattern Counter 3..0 */
-#define WOL_PATT_CNT_4 0x0f3c /* 24 bit WOL Pattern Counter 6..4 */
- /* 0x0f40 - 0x0f7f: reserved */
-
-/*
- * Bank 31
- */
-/* 0x0f80 - 0x0fff: reserved */
-
-/*
- * Bank 32 - 33
- */
-#define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */
-
-/*
- * Bank 0x22 - 0x3f
- */
-/* 0x1100 - 0x1fff: reserved */
-
-/*
- * Bank 0x40 - 0x4f
- */
-#define BASE_XMAC_1 0x2000 /* XMAC 1 registers */
-
-/*
- * Bank 0x50 - 0x5f
- */
-
-#define BASE_GMAC_1 0x2800 /* GMAC 1 registers */
-
-/*
- * Bank 0x60 - 0x6f
- */
-#define BASE_XMAC_2 0x3000 /* XMAC 2 registers */
-
-/*
- * Bank 0x70 - 0x7f
- */
-#define BASE_GMAC_2 0x3800 /* GMAC 2 registers */
-
-/*
- * Control Register Bit Definitions:
- */
-/* B0_RAP 8 bit Register Address Port */
- /* Bit 7: reserved */
-#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */
-
-/* B0_CTST 16 bit Control/Status register */
- /* Bit 15..14: reserved */
-#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */
-#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */
-#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */
-#define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */
-#define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */
-#define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */
-#define CS_ST_SW_IRQ BIT_7S /* Set IRQ SW Request */
-#define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */
-#define CS_STOP_DONE BIT_5S /* Stop Master is finished */
-#define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */
-#define CS_MRST_CLR BIT_3S /* Clear Master reset */
-#define CS_MRST_SET BIT_2S /* Set Master reset */
-#define CS_RST_CLR BIT_1S /* Clear Software reset */
-#define CS_RST_SET BIT_0S /* Set Software reset */
-
-/* B0_LED 8 Bit LED register */
- /* Bit 7.. 2: reserved */
-#define LED_STAT_ON BIT_1S /* Status LED on */
-#define LED_STAT_OFF BIT_0S /* Status LED off */
-
-/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */
-#define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */
-#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */
-#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */
-#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */
-#define PC_VAUX_ON BIT_3 /* Switch VAUX On */
-#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */
-#define PC_VCC_ON BIT_1 /* Switch VCC On */
-#define PC_VCC_OFF BIT_0 /* Switch VCC Off */
-
-/* B0_ISRC 32 bit Interrupt Source Register */
-/* B0_IMSK 32 bit Interrupt Mask Register */
-/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */
-/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */
-#define IS_ALL_MSK 0xbfffffffUL /* All Interrupt bits */
-#define IS_HW_ERR BIT_31 /* Interrupt HW Error */
- /* Bit 30: reserved */
-#define IS_PA_TO_RX1 BIT_29 /* Packet Arb Timeout Rx1 */
-#define IS_PA_TO_RX2 BIT_28 /* Packet Arb Timeout Rx2 */
-#define IS_PA_TO_TX1 BIT_27 /* Packet Arb Timeout Tx1 */
-#define IS_PA_TO_TX2 BIT_26 /* Packet Arb Timeout Tx2 */
-#define IS_I2C_READY BIT_25 /* IRQ on end of I2C Tx */
-#define IS_IRQ_SW BIT_24 /* SW forced IRQ */
-#define IS_EXT_REG BIT_23 /* IRQ from LM80 or PHY (GENESIS only) */
- /* IRQ from PHY (YUKON only) */
-#define IS_TIMINT BIT_22 /* IRQ from Timer */
-#define IS_MAC1 BIT_21 /* IRQ from MAC 1 */
-#define IS_LNK_SYNC_M1 BIT_20 /* Link Sync Cnt wrap MAC 1 */
-#define IS_MAC2 BIT_19 /* IRQ from MAC 2 */
-#define IS_LNK_SYNC_M2 BIT_18 /* Link Sync Cnt wrap MAC 2 */
-/* Receive Queue 1 */
-#define IS_R1_B BIT_17 /* Q_R1 End of Buffer */
-#define IS_R1_F BIT_16 /* Q_R1 End of Frame */
-#define IS_R1_C BIT_15 /* Q_R1 Encoding Error */
-/* Receive Queue 2 */
-#define IS_R2_B BIT_14 /* Q_R2 End of Buffer */
-#define IS_R2_F BIT_13 /* Q_R2 End of Frame */
-#define IS_R2_C BIT_12 /* Q_R2 Encoding Error */
-/* Synchronous Transmit Queue 1 */
-#define IS_XS1_B BIT_11 /* Q_XS1 End of Buffer */
-#define IS_XS1_F BIT_10 /* Q_XS1 End of Frame */
-#define IS_XS1_C BIT_9 /* Q_XS1 Encoding Error */
-/* Asynchronous Transmit Queue 1 */
-#define IS_XA1_B BIT_8 /* Q_XA1 End of Buffer */
-#define IS_XA1_F BIT_7 /* Q_XA1 End of Frame */
-#define IS_XA1_C BIT_6 /* Q_XA1 Encoding Error */
-/* Synchronous Transmit Queue 2 */
-#define IS_XS2_B BIT_5 /* Q_XS2 End of Buffer */
-#define IS_XS2_F BIT_4 /* Q_XS2 End of Frame */
-#define IS_XS2_C BIT_3 /* Q_XS2 Encoding Error */
-/* Asynchronous Transmit Queue 2 */
-#define IS_XA2_B BIT_2 /* Q_XA2 End of Buffer */
-#define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */
-#define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */
-
-
-/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */
-/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */
-/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
-#define IS_ERR_MSK 0x00000fffL /* All Error bits */
- /* Bit 31..14: reserved */
-#define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */
-#define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */
-#define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */
-#define IS_IRQ_STAT BIT_10 /* IRQ status exception */
-#define IS_NO_STAT_M1 BIT_9 /* No Rx Status from MAC 1 */
-#define IS_NO_STAT_M2 BIT_8 /* No Rx Status from MAC 2 */
-#define IS_NO_TIST_M1 BIT_7 /* No Time Stamp from MAC 1 */
-#define IS_NO_TIST_M2 BIT_6 /* No Time Stamp from MAC 2 */
-#define IS_RAM_RD_PAR BIT_5 /* RAM Read Parity Error */
-#define IS_RAM_WR_PAR BIT_4 /* RAM Write Parity Error */
-#define IS_M1_PAR_ERR BIT_3 /* MAC 1 Parity Error */
-#define IS_M2_PAR_ERR BIT_2 /* MAC 2 Parity Error */
-#define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */
-#define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */
-
-/* B2_CONN_TYP 8 bit Connector type */
-/* B2_PMD_TYP 8 bit PMD type */
-/* Values of connector and PMD type comply to SysKonnect internal std */
-
-/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
-#define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */
- /* Bit 3.. 2: reserved */
-#define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */
-#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/
-
-/* B2_CHIP_ID 8 bit Chip Identification Number */
-#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */
-#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */
-#define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1-A3) */
-#define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */
-
-#define CHIP_REV_YU_LITE_A1 3 /* Chip Rev. for YUKON-Lite A1,A2 */
-#define CHIP_REV_YU_LITE_A3 7 /* Chip Rev. for YUKON-Lite A3 */
-
-/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */
-#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */
-
-/* B2_LD_CTRL 8 bit EPROM loader control register */
-/* Bits are currently reserved */
-
-/* B2_LD_TEST 8 bit EPROM loader test register */
- /* Bit 7.. 4: reserved */
-#define LD_T_ON BIT_3S /* Loader Test mode on */
-#define LD_T_OFF BIT_2S /* Loader Test mode off */
-#define LD_T_STEP BIT_1S /* Decrement FPROM addr. Counter */
-#define LD_START BIT_0S /* Start loading FPROM */
-
-/*
- * Timer Section
- */
-/* B2_TI_CTRL 8 bit Timer control */
-/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */
- /* Bit 7.. 3: reserved */
-#define TIM_START BIT_2S /* Start Timer */
-#define TIM_STOP BIT_1S /* Stop Timer */
-#define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */
-
-/* B2_TI_TEST 8 Bit Timer Test */
-/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */
-/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */
- /* Bit 7.. 3: reserved */
-#define TIM_T_ON BIT_2S /* Test mode on */
-#define TIM_T_OFF BIT_1S /* Test mode off */
-#define TIM_T_STEP BIT_0S /* Test step */
-
-/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */
-/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */
- /* Bit 31..24: reserved */
-#define DPT_MSK 0x00ffffffL /* Bit 23.. 0: Desc Poll Timer Bits */
-
-/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */
- /* Bit 7.. 2: reserved */
-#define DPT_START BIT_1S /* Start Descriptor Poll Timer */
-#define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */
-
-/* B2_E_3 8 bit lower 4 bits used for HW self test result */
-#define B2_E3_RES_MASK 0x0f
-
-/* B2_TST_CTRL1 8 bit Test Control Register 1 */
-#define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */
-#define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */
-#define TST_FRC_DPERR_TR BIT_5S /* force DATAPERR on TRG RD */
-#define TST_FRC_DPERR_TW BIT_4S /* force DATAPERR on TRG WR */
-#define TST_FRC_APERR_M BIT_3S /* force ADDRPERR on MST */
-#define TST_FRC_APERR_T BIT_2S /* force ADDRPERR on TRG */
-#define TST_CFG_WRITE_ON BIT_1S /* Enable Config Reg WR */
-#define TST_CFG_WRITE_OFF BIT_0S /* Disable Config Reg WR */
-
-/* B2_TST_CTRL2 8 bit Test Control Register 2 */
- /* Bit 7.. 4: reserved */
- /* force the following error on the next master read/write */
-#define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */
-#define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */
-#define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */
-#define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */
-
-/* B2_GP_IO 32 bit General Purpose I/O Register */
- /* Bit 31..26: reserved */
-#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=In/1=Out */
-#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=In/1=Out */
-#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=In/1=Out */
-#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=In/1=Out */
-#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=In/1=Out */
-#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=In/1=Out */
-#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=In/1=Out */
-#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=In/1=Out */
-#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=In/1=Out */
-#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=In/1=Out */
- /* Bit 15..10: reserved */
-#define GP_IO_9 BIT_9 /* IO_9 pin */
-#define GP_IO_8 BIT_8 /* IO_8 pin */
-#define GP_IO_7 BIT_7 /* IO_7 pin */
-#define GP_IO_6 BIT_6 /* IO_6 pin */
-#define GP_IO_5 BIT_5 /* IO_5 pin */
-#define GP_IO_4 BIT_4 /* IO_4 pin */
-#define GP_IO_3 BIT_3 /* IO_3 pin */
-#define GP_IO_2 BIT_2 /* IO_2 pin */
-#define GP_IO_1 BIT_1 /* IO_1 pin */
-#define GP_IO_0 BIT_0 /* IO_0 pin */
-
-/* B2_I2C_CTRL 32 bit I2C HW Control Register */
-#define I2C_FLAG BIT_31 /* Start read/write if WR */
-#define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */
-#define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */
- /* Bit 8.. 5: reserved */
-#define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */
-#define I2C_DEV_SIZE (7<<1) /* Bit 3.. 1: I2C Device Size */
-#define I2C_025K_DEV (0<<1) /* 0: 256 Bytes or smal. */
-#define I2C_05K_DEV (1<<1) /* 1: 512 Bytes */
-#define I2C_1K_DEV (2<<1) /* 2: 1024 Bytes */
-#define I2C_2K_DEV (3<<1) /* 3: 2048 Bytes */
-#define I2C_4K_DEV (4<<1) /* 4: 4096 Bytes */
-#define I2C_8K_DEV (5<<1) /* 5: 8192 Bytes */
-#define I2C_16K_DEV (6<<1) /* 6: 16384 Bytes */
-#define I2C_32K_DEV (7<<1) /* 7: 32768 Bytes */
-#define I2C_STOP BIT_0 /* Interrupt I2C transfer */
-
-/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */
- /* Bit 31.. 1 reserved */
-#define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */
-
-/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */
- /* Bit 7.. 3: reserved */
-#define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */
-#define I2C_DATA BIT_1S /* I2C Data Port */
-#define I2C_CLK BIT_0S /* I2C Clock Port */
-
-/*
- * I2C Address
- */
-#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/
-
-
-/* B2_BSC_CTRL 8 bit Blink Source Counter Control */
- /* Bit 7.. 2: reserved */
-#define BSC_START BIT_1S /* Start Blink Source Counter */
-#define BSC_STOP BIT_0S /* Stop Blink Source Counter */
-
-/* B2_BSC_STAT 8 bit Blink Source Counter Status */
- /* Bit 7.. 1: reserved */
-#define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */
-
-/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */
-#define BSC_T_ON BIT_2S /* Test mode on */
-#define BSC_T_OFF BIT_1S /* Test mode off */
-#define BSC_T_STEP BIT_0S /* Test step */
-
-
-/* B3_RAM_ADDR 32 bit RAM Address, to read or write */
- /* Bit 31..19: reserved */
-#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */
-
-/* RAM Interface Registers */
-/* B3_RI_CTRL 16 bit RAM Iface Control Register */
- /* Bit 15..10: reserved */
-#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */
-#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/
- /* Bit 7.. 2: reserved */
-#define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */
-#define RI_RST_SET BIT_0S /* Set RAM Interface Reset */
-
-/* B3_RI_TEST 8 bit RAM Iface Test Register */
- /* Bit 15.. 4: reserved */
-#define RI_T_EV BIT_3S /* Timeout Event occured */
-#define RI_T_ON BIT_2S /* Timeout Timer Test On */
-#define RI_T_OFF BIT_1S /* Timeout Timer Test Off */
-#define RI_T_STEP BIT_0S /* Timeout Timer Step */
-
-/* MAC Arbiter Registers */
-/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */
- /* Bit 15.. 4: reserved */
-#define MA_FOE_ON BIT_3S /* XMAC Fast Output Enable ON */
-#define MA_FOE_OFF BIT_2S /* XMAC Fast Output Enable OFF */
-#define MA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */
-#define MA_RST_SET BIT_0S /* Set MAC Arbiter Reset */
-
-/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */
- /* Bit 15.. 8: reserved */
-#define MA_ENA_REC_TX2 BIT_7S /* Enable Recovery Timer TX2 */
-#define MA_DIS_REC_TX2 BIT_6S /* Disable Recovery Timer TX2 */
-#define MA_ENA_REC_TX1 BIT_5S /* Enable Recovery Timer TX1 */
-#define MA_DIS_REC_TX1 BIT_4S /* Disable Recovery Timer TX1 */
-#define MA_ENA_REC_RX2 BIT_3S /* Enable Recovery Timer RX2 */
-#define MA_DIS_REC_RX2 BIT_2S /* Disable Recovery Timer RX2 */
-#define MA_ENA_REC_RX1 BIT_1S /* Enable Recovery Timer RX1 */
-#define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */
-
-/* Packet Arbiter Registers */
-/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */
- /* Bit 15..14: reserved */
-#define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */
-#define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */
-#define PA_CLR_TO_RX2 BIT_11S /* Clear IRQ Packet Timeout RX2 */
-#define PA_CLR_TO_RX1 BIT_10S /* Clear IRQ Packet Timeout RX1 */
-#define PA_ENA_TO_TX2 BIT_9S /* Enable Timeout Timer TX2 */
-#define PA_DIS_TO_TX2 BIT_8S /* Disable Timeout Timer TX2 */
-#define PA_ENA_TO_TX1 BIT_7S /* Enable Timeout Timer TX1 */
-#define PA_DIS_TO_TX1 BIT_6S /* Disable Timeout Timer TX1 */
-#define PA_ENA_TO_RX2 BIT_5S /* Enable Timeout Timer RX2 */
-#define PA_DIS_TO_RX2 BIT_4S /* Disable Timeout Timer RX2 */
-#define PA_ENA_TO_RX1 BIT_3S /* Enable Timeout Timer RX1 */
-#define PA_DIS_TO_RX1 BIT_2S /* Disable Timeout Timer RX1 */
-#define PA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */
-#define PA_RST_SET BIT_0S /* Set MAC Arbiter Reset */
-
-#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
- PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
-
-/* Rx/Tx Path related Arbiter Test Registers */
-/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */
-/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */
-/* B3_PA_TEST 16 bit Packet Arbiter Test Register */
-/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
-#define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */
-#define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */
-#define TX2_T_OFF BIT_13S /* TX2 Timeout/Recv Timer Tst Off */
-#define TX2_T_STEP BIT_12S /* TX2 Timeout/Recv Timer Step */
-#define TX1_T_EV BIT_11S /* TX1 Timeout/Recv Event occured */
-#define TX1_T_ON BIT_10S /* TX1 Timeout/Recv Timer Test On */
-#define TX1_T_OFF BIT_9S /* TX1 Timeout/Recv Timer Tst Off */
-#define TX1_T_STEP BIT_8S /* TX1 Timeout/Recv Timer Step */
-#define RX2_T_EV BIT_7S /* RX2 Timeout/Recv Event occured */
-#define RX2_T_ON BIT_6S /* RX2 Timeout/Recv Timer Test On */
-#define RX2_T_OFF BIT_5S /* RX2 Timeout/Recv Timer Tst Off */
-#define RX2_T_STEP BIT_4S /* RX2 Timeout/Recv Timer Step */
-#define RX1_T_EV BIT_3S /* RX1 Timeout/Recv Event occured */
-#define RX1_T_ON BIT_2S /* RX1 Timeout/Recv Timer Test On */
-#define RX1_T_OFF BIT_1S /* RX1 Timeout/Recv Timer Tst Off */
-#define RX1_T_STEP BIT_0S /* RX1 Timeout/Recv Timer Step */
-
-
-/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
-/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */
-/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */
-/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */
-/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */
- /* Bit 31..24: reserved */
-#define TXA_MAX_VAL 0x00ffffffUL/* Bit 23.. 0: Max TXA Timer/Cnt Val */
-
-/* TXA_CTRL 8 bit Tx Arbiter Control Register */
-#define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */
-#define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */
-#define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */
-#define TXA_DIS_ALLOC BIT_4S /* Disable alloc of free bandwidth */
-#define TXA_START_RC BIT_3S /* Start sync Rate Control */
-#define TXA_STOP_RC BIT_2S /* Stop sync Rate Control */
-#define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */
-#define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */
-
-/* TXA_TEST 8 bit Tx Arbiter Test Register */
- /* Bit 7.. 6: reserved */
-#define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */
-#define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */
-#define TXA_INT_T_STEP BIT_3S /* Tx Arb Interval Timer Step */
-#define TXA_LIM_T_ON BIT_2S /* Tx Arb Limit Timer Test On */
-#define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */
-#define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */
-
-/* TXA_STAT 8 bit Tx Arbiter Status Register */
- /* Bit 7.. 1: reserved */
-#define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */
-
-/* Q_BC 32 bit Current Byte Counter */
- /* Bit 31..16: reserved */
-#define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */
-
-/* BMU Control Status Registers */
-/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */
-/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */
-/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
-/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */
-/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
-/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */
-/* Q_CSR 32 bit BMU Control/Status Register */
- /* Bit 31..25: reserved */
-#define CSR_SV_IDLE BIT_24 /* BMU SM Idle */
- /* Bit 23..22: reserved */
-#define CSR_DESC_CLR BIT_21 /* Clear Reset for Descr */
-#define CSR_DESC_SET BIT_20 /* Set Reset for Descr */
-#define CSR_FIFO_CLR BIT_19 /* Clear Reset for FIFO */
-#define CSR_FIFO_SET BIT_18 /* Set Reset for FIFO */
-#define CSR_HPI_RUN BIT_17 /* Release HPI SM */
-#define CSR_HPI_RST BIT_16 /* Reset HPI SM to Idle */
-#define CSR_SV_RUN BIT_15 /* Release Supervisor SM */
-#define CSR_SV_RST BIT_14 /* Reset Supervisor SM */
-#define CSR_DREAD_RUN BIT_13 /* Release Descr Read SM */
-#define CSR_DREAD_RST BIT_12 /* Reset Descr Read SM */
-#define CSR_DWRITE_RUN BIT_11 /* Release Descr Write SM */
-#define CSR_DWRITE_RST BIT_10 /* Reset Descr Write SM */
-#define CSR_TRANS_RUN BIT_9 /* Release Transfer SM */
-#define CSR_TRANS_RST BIT_8 /* Reset Transfer SM */
-#define CSR_ENA_POL BIT_7 /* Enable Descr Polling */
-#define CSR_DIS_POL BIT_6 /* Disable Descr Polling */
-#define CSR_STOP BIT_5 /* Stop Rx/Tx Queue */
-#define CSR_START BIT_4 /* Start Rx/Tx Queue */
-#define CSR_IRQ_CL_P BIT_3 /* (Rx) Clear Parity IRQ */
-#define CSR_IRQ_CL_B BIT_2 /* Clear EOB IRQ */
-#define CSR_IRQ_CL_F BIT_1 /* Clear EOF IRQ */
-#define CSR_IRQ_CL_C BIT_0 /* Clear ERR IRQ */
-
-#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
- CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
- CSR_TRANS_RST)
-#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
- CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
- CSR_TRANS_RUN)
-
-/* Q_F 32 bit Flag Register */
- /* Bit 31..28: reserved */
-#define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */
-#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */
-#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */
-#define F_WM_REACHED BIT_25 /* Watermark reached */
- /* reserved */
-#define F_FIFO_LEVEL (0x1fL<<16) /* Bit 23..16: # of Qwords in FIFO */
- /* Bit 15..11: reserved */
-#define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */
-
-/* Q_T1 32 bit Test Register 1 */
-/* Holds four State Machine control Bytes */
-#define SM_CTRL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */
-#define SM_CTRL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */
-#define SM_CTRL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */
-#define SM_CTRL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */
-
-/* Q_T1_TR 8 bit Test Register 1 Transfer SM */
-/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */
-/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */
-/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */
-
-/* The control status byte of each machine looks like ... */
-#define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */
-#define SM_LOAD BIT_3S /* Load the SM with SM_STATE */
-#define SM_TEST_ON BIT_2S /* Switch on SM Test Mode */
-#define SM_TEST_OFF BIT_1S /* Go off the Test Mode */
-#define SM_STEP BIT_0S /* Step the State Machine */
-/* The encoding of the states is not supported by the Diagnostics Tool */
-
-/* Q_T2 32 bit Test Register 2 */
- /* Bit 31.. 8: reserved */
-#define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */
-#define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */
-#define T2_BC_T_ON BIT_5 /* Byte Counter Test Mode on */
-#define T2_BC_T_OFF BIT_4 /* Byte Counter Test Mode off */
-#define T2_STEP04 BIT_3 /* Inc AC/Dec BC by 4 */
-#define T2_STEP03 BIT_2 /* Inc AC/Dec BC by 3 */
-#define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */
-#define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */
-
-/* Q_T3 32 bit Test Register 3 */
- /* Bit 31.. 7: reserved */
-#define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */
- /* Bit 3: reserved */
-#define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */
-
-/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
-/* RB_START 32 bit RAM Buffer Start Address */
-/* RB_END 32 bit RAM Buffer End Address */
-/* RB_WP 32 bit RAM Buffer Write Pointer */
-/* RB_RP 32 bit RAM Buffer Read Pointer */
-/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */
-/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */
-/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */
-/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */
-/* RB_PC 32 bit RAM Buffer Packet Counter */
-/* RB_LEV 32 bit RAM Buffer Level Register */
- /* Bit 31..19: reserved */
-#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */
-
-/* RB_TST2 8 bit RAM Buffer Test Register 2 */
- /* Bit 7.. 4: reserved */
-#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */
-#define RB_PC_T_ON BIT_2S /* Packet Counter Test On */
-#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */
-#define RB_PC_INC BIT_0S /* Packet Counter Increm */
-
-/* RB_TST1 8 bit RAM Buffer Test Register 1 */
- /* Bit 7: reserved */
-#define RB_WP_T_ON BIT_6S /* Write Pointer Test On */
-#define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */
-#define RB_WP_INC BIT_4S /* Write Pointer Increm */
- /* Bit 3: reserved */
-#define RB_RP_T_ON BIT_2S /* Read Pointer Test On */
-#define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */
-#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */
-
-/* RB_CTRL 8 bit RAM Buffer Control Register */
- /* Bit 7.. 6: reserved */
-#define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */
-#define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */
-#define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */
-#define RB_DIS_OP_MD BIT_2S /* Disable Operation Mode */
-#define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */
-#define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */
-
-
-/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
-
-/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */
-/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */
-/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */
-/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */
-/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */
-/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */
-/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */
-/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */
-/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */
-/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */
-/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */
- /* Bit 31.. 6: reserved */
-#define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */
-
-/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */
- /* Bit 15..14: reserved */
-#define MFF_ENA_RDY_PAT BIT_13S /* Enable Ready Patch */
-#define MFF_DIS_RDY_PAT BIT_12S /* Disable Ready Patch */
-#define MFF_ENA_TIM_PAT BIT_11S /* Enable Timing Patch */
-#define MFF_DIS_TIM_PAT BIT_10S /* Disable Timing Patch */
-#define MFF_ENA_ALM_FUL BIT_9S /* Enable AlmostFull Sign */
-#define MFF_DIS_ALM_FUL BIT_8S /* Disable AlmostFull Sign */
-#define MFF_ENA_PAUSE BIT_7S /* Enable Pause Signaling */
-#define MFF_DIS_PAUSE BIT_6S /* Disable Pause Signaling */
-#define MFF_ENA_FLUSH BIT_5S /* Enable Frame Flushing */
-#define MFF_DIS_FLUSH BIT_4S /* Disable Frame Flushing */
-#define MFF_ENA_TIST BIT_3S /* Enable Time Stamp Gener */
-#define MFF_DIS_TIST BIT_2S /* Disable Time Stamp Gener */
-#define MFF_CLR_INTIST BIT_1S /* Clear IRQ No Time Stamp */
-#define MFF_CLR_INSTAT BIT_0S /* Clear IRQ No Status */
-
-#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
-
-/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */
-#define MFF_CLR_PERR BIT_15S /* Clear Parity Error IRQ */
- /* Bit 14: reserved */
-#define MFF_ENA_PKT_REC BIT_13S /* Enable Packet Recovery */
-#define MFF_DIS_PKT_REC BIT_12S /* Disable Packet Recovery */
-/* MFF_ENA_TIM_PAT (see RX_MFF_CTRL1) Bit 11: Enable Timing Patch */
-/* MFF_DIS_TIM_PAT (see RX_MFF_CTRL1) Bit 10: Disable Timing Patch */
-/* MFF_ENA_ALM_FUL (see RX_MFF_CTRL1) Bit 9: Enable Almost Full Sign */
-/* MFF_DIS_ALM_FUL (see RX_MFF_CTRL1) Bit 8: Disable Almost Full Sign */
-#define MFF_ENA_W4E BIT_7S /* Enable Wait for Empty */
-#define MFF_DIS_W4E BIT_6S /* Disable Wait for Empty */
-/* MFF_ENA_FLUSH (see RX_MFF_CTRL1) Bit 5: Enable Frame Flushing */
-/* MFF_DIS_FLUSH (see RX_MFF_CTRL1) Bit 4: Disable Frame Flushing */
-#define MFF_ENA_LOOPB BIT_3S /* Enable Loopback */
-#define MFF_DIS_LOOPB BIT_2S /* Disable Loopback */
-#define MFF_CLR_MAC_RST BIT_1S /* Clear XMAC Reset */
-#define MFF_SET_MAC_RST BIT_0S /* Set XMAC Reset */
-
-#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
-
-/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */
-/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */
- /* Bit 7: reserved */
-#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */
-#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */
-#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */
-#define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */
-#define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */
-#define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */
-#define MFF_PC_INC BIT_0S /* Packet Counter Increment */
-
-/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */
-/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */
- /* Bit 7: reserved */
-#define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */
-#define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */
-#define MFF_WP_INC BIT_4S /* Write Pointer Increm */
- /* Bit 3: reserved */
-#define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */
-#define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */
-#define MFF_RP_DEC BIT_0S /* Read Pointer Decrement */
-
-/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */
-/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */
- /* Bit 7..4: reserved */
-#define MFF_ENA_OP_MD BIT_3S /* Enable Operation Mode */
-#define MFF_DIS_OP_MD BIT_2S /* Disable Operation Mode */
-#define MFF_RST_CLR BIT_1S /* Clear MAC FIFO Reset */
-#define MFF_RST_SET BIT_0S /* Set MAC FIFO Reset */
-
-
-/* Link LED Counter Registers (GENESIS only) */
-
-/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */
-/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */
-/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */
- /* Bit 7.. 3: reserved */
-#define LED_START BIT_2S /* Start Timer */
-#define LED_STOP BIT_1S /* Stop Timer */
-#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */
-#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */
-
-/* RX_LED_TST 8 bit Receive LED Cnt Test Register */
-/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */
-/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */
- /* Bit 7.. 3: reserved */
-#define LED_T_ON BIT_2S /* LED Counter Test mode On */
-#define LED_T_OFF BIT_1S /* LED Counter Test mode Off */
-#define LED_T_STEP BIT_0S /* LED Counter Step */
-
-/* LNK_LED_REG 8 bit Link LED Register */
- /* Bit 7.. 6: reserved */
-#define LED_BLK_ON BIT_5S /* Link LED Blinking On */
-#define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */
-#define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */
-#define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */
-#define LED_ON BIT_1S /* switch LED on */
-#define LED_OFF BIT_0S /* switch LED off */
-
-/* Receive and Transmit GMAC FIFO Registers (YUKON only) */
-
-/* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */
-/* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */
-/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */
-/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */
-/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */
-/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */
-/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */
-/* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
-/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */
-/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */
-/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */
-/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */
-/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */
-/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */
-
-/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */
- /* Bits 31..15: reserved */
-#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */
-#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */
-#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */
- /* Bit 11: reserved */
-#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */
-#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */
-#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */
-#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */
-#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */
-#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */
-#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */
-#define GMF_OPER_ON BIT_3 /* Operational Mode On */
-#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */
-#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */
-#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */
-
-/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
- /* Bits 31..19: reserved */
-#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */
-#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */
-#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */
- /* Bits 15..7: same as for RX_GMF_CTRL_T */
-#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */
-#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */
-#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */
- /* Bits 3..0: same as for RX_GMF_CTRL_T */
-
-#define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON)
-#define GMF_TX_CTRL_DEF GMF_OPER_ON
-
-#define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */
-
-/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */
- /* Bit 7.. 3: reserved */
-#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */
-#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */
-#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */
-
-/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
- /* Bits 31.. 8: reserved */
-#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */
-#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */
-#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */
-#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */
-#define GMC_PAUSE_ON BIT_3 /* Pause On */
-#define GMC_PAUSE_OFF BIT_2 /* Pause Off */
-#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */
-#define GMC_RST_SET BIT_0 /* Set GMAC Reset */
-
-/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */
- /* Bits 31..29: reserved */
-#define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */
-#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */
-#define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */
-#define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */
-#define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */
-#define GPC_HWCFG_M_3 BIT_23 /* HWCFG_MODE[3] */
-#define GPC_HWCFG_M_2 BIT_22 /* HWCFG_MODE[2] */
-#define GPC_HWCFG_M_1 BIT_21 /* HWCFG_MODE[1] */
-#define GPC_HWCFG_M_0 BIT_20 /* HWCFG_MODE[0] */
-#define GPC_ANEG_0 BIT_19 /* ANEG[0] */
-#define GPC_ENA_XC BIT_18 /* Enable MDI crossover */
-#define GPC_DIS_125 BIT_17 /* Disable 125 MHz clock */
-#define GPC_ANEG_3 BIT_16 /* ANEG[3] */
-#define GPC_ANEG_2 BIT_15 /* ANEG[2] */
-#define GPC_ANEG_1 BIT_14 /* ANEG[1] */
-#define GPC_ENA_PAUSE BIT_13 /* Enable Pause (SYM_OR_REM) */
-#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of Phy Addr */
-#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of Phy Addr */
-#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of Phy Addr */
-#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of Phy Addr */
-#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of Phy Addr */
- /* Bits 7..2: reserved */
-#define GPC_RST_CLR BIT_1 /* Clear GPHY Reset */
-#define GPC_RST_SET BIT_0 /* Set GPHY Reset */
-
-#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \
- GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_HWCFG_GMII_FIB ( GPC_HWCFG_M_2 | \
- GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
-
-#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | \
- GPC_ANEG_1 | GPC_ANEG_0)
-
-/* forced speed and duplex mode (don't mix with other ANEG bits) */
-#define GPC_FRC10MBIT_HALF 0
-#define GPC_FRC10MBIT_FULL GPC_ANEG_0
-#define GPC_FRC100MBIT_HALF GPC_ANEG_1
-#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1)
-
-/* auto-negotiation with limited advertised speeds */
-/* mix only with master/slave settings (for copper) */
-#define GPC_ADV_1000_HALF GPC_ANEG_2
-#define GPC_ADV_1000_FULL GPC_ANEG_3
-#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3)
-
-/* master/slave settings */
-/* only for copper with 1000 Mbps */
-#define GPC_FORCE_MASTER 0
-#define GPC_FORCE_SLAVE GPC_ANEG_0
-#define GPC_PREF_MASTER GPC_ANEG_1
-#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0)
-
-/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */
-/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */
-#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */
-#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */
-#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */
-#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */
-#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */
-#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */
-
-#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \
- GM_IS_TX_FF_UR)
-
-/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
- /* Bits 15.. 2: reserved */
-#define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */
-#define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */
-
-
-/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */
-#define WOL_CTL_LINK_CHG_OCC BIT_15S
-#define WOL_CTL_MAGIC_PKT_OCC BIT_14S
-#define WOL_CTL_PATTERN_OCC BIT_13S
-
-#define WOL_CTL_CLEAR_RESULT BIT_12S
-
-#define WOL_CTL_ENA_PME_ON_LINK_CHG BIT_11S
-#define WOL_CTL_DIS_PME_ON_LINK_CHG BIT_10S
-#define WOL_CTL_ENA_PME_ON_MAGIC_PKT BIT_9S
-#define WOL_CTL_DIS_PME_ON_MAGIC_PKT BIT_8S
-#define WOL_CTL_ENA_PME_ON_PATTERN BIT_7S
-#define WOL_CTL_DIS_PME_ON_PATTERN BIT_6S
-
-#define WOL_CTL_ENA_LINK_CHG_UNIT BIT_5S
-#define WOL_CTL_DIS_LINK_CHG_UNIT BIT_4S
-#define WOL_CTL_ENA_MAGIC_PKT_UNIT BIT_3S
-#define WOL_CTL_DIS_MAGIC_PKT_UNIT BIT_2S
-#define WOL_CTL_ENA_PATTERN_UNIT BIT_1S
-#define WOL_CTL_DIS_PATTERN_UNIT BIT_0S
-
-#define WOL_CTL_DEFAULT \
- (WOL_CTL_DIS_PME_ON_LINK_CHG | \
- WOL_CTL_DIS_PME_ON_PATTERN | \
- WOL_CTL_DIS_PME_ON_MAGIC_PKT | \
- WOL_CTL_DIS_LINK_CHG_UNIT | \
- WOL_CTL_DIS_PATTERN_UNIT | \
- WOL_CTL_DIS_MAGIC_PKT_UNIT)
-
-/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */
-#define WOL_CTL_PATT_ENA(x) (BIT_0 << (x))
-
-#define SK_NUM_WOL_PATTERN 7
-#define SK_PATTERN_PER_WORD 4
-#define SK_BITMASK_PATTERN 7
-#define SK_POW_PATTERN_LENGTH 128
-
-#define WOL_LENGTH_MSK 0x7f
-#define WOL_LENGTH_SHIFT 8
-
-
-/* Receive and Transmit Descriptors ******************************************/
-
-/* Transmit Descriptor struct */
-typedef struct s_HwTxd {
- SK_U32 volatile TxCtrl; /* Transmit Buffer Control Field */
- SK_U32 TxNext; /* Physical Address Pointer to the next TxD */
- SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */
- SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */
- SK_U32 TxStat; /* Transmit Frame Status Word */
-#ifndef SK_USE_REV_DESC
- SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */
- SK_U16 TxRes1; /* 16 bit reserved field */
- SK_U16 TxTcpWp; /* TCP Checksum Write Position */
- SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
-#else /* SK_USE_REV_DESC */
- SK_U16 TxRes1; /* 16 bit reserved field */
- SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */
- SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
- SK_U16 TxTcpWp; /* TCP Checksum Write Position */
-#endif /* SK_USE_REV_DESC */
- SK_U32 TxRes2; /* 32 bit reserved field */
-} SK_HWTXD;
-
-/* Receive Descriptor struct */
-typedef struct s_HwRxd {
- SK_U32 volatile RxCtrl; /* Receive Buffer Control Field */
- SK_U32 RxNext; /* Physical Address Pointer to the next RxD */
- SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower dword */
- SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */
- SK_U32 RxStat; /* Receive Frame Status Word */
- SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */
-#ifndef SK_USE_REV_DESC
- SK_U16 RxTcpSum1; /* TCP Checksum 1 */
- SK_U16 RxTcpSum2; /* TCP Checksum 2 */
- SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
- SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
-#else /* SK_USE_REV_DESC */
- SK_U16 RxTcpSum2; /* TCP Checksum 2 */
- SK_U16 RxTcpSum1; /* TCP Checksum 1 */
- SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
- SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
-#endif /* SK_USE_REV_DESC */
-} SK_HWRXD;
-
-/*
- * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
- * should set the define SK_USE_REV_DESC.
- * Structures are 'normaly' not endianess dependent. But in
- * this case the SK_U16 fields are bound to bit positions inside the
- * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord.
- * The bit positions inside a DWord are of course endianess dependent and
- * swaps if the DWord is swapped by the hardware.
- */
-
-
-/* Descriptor Bit Definition */
-/* TxCtrl Transmit Buffer Control Field */
-/* RxCtrl Receive Buffer Control Field */
-#define BMU_OWN BIT_31 /* OWN bit: 0=host/1=BMU */
-#define BMU_STF BIT_30 /* Start of Frame */
-#define BMU_EOF BIT_29 /* End of Frame */
-#define BMU_IRQ_EOB BIT_28 /* Req "End of Buffer" IRQ */
-#define BMU_IRQ_EOF BIT_27 /* Req "End of Frame" IRQ */
-/* TxCtrl specific bits */
-#define BMU_STFWD BIT_26 /* (Tx) Store & Forward Frame */
-#define BMU_NO_FCS BIT_25 /* (Tx) Disable MAC FCS (CRC) generation */
-#define BMU_SW BIT_24 /* (Tx) 1 bit res. for SW use */
-/* RxCtrl specific bits */
-#define BMU_DEV_0 BIT_26 /* (Rx) Transfer data to Dev0 */
-#define BMU_STAT_VAL BIT_25 /* (Rx) Rx Status Valid */
-#define BMU_TIST_VAL BIT_24 /* (Rx) Rx TimeStamp Valid */
- /* Bit 23..16: BMU Check Opcodes */
-#define BMU_CHECK (0x55L<<16) /* Default BMU check */
-#define BMU_TCP_CHECK (0x56L<<16) /* Descr with TCP ext */
-#define BMU_UDP_CHECK (0x57L<<16) /* Descr with UDP ext (YUKON only) */
-#define BMU_BBC 0xffffL /* Bit 15.. 0: Buffer Byte Counter */
-
-/* TxStat Transmit Frame Status Word */
-/* RxStat Receive Frame Status Word */
-/*
- *Note: TxStat is reserved for ASIC loopback mode only
- *
- * The Bits of the Status words are defined in xmac_ii.h
- * (see XMR_FS bits)
- */
-
-/* macros ********************************************************************/
-
-/* Receive and Transmit Queues */
-#define Q_R1 0x0000 /* Receive Queue 1 */
-#define Q_R2 0x0080 /* Receive Queue 2 */
-#define Q_XS1 0x0200 /* Synchronous Transmit Queue 1 */
-#define Q_XA1 0x0280 /* Asynchronous Transmit Queue 1 */
-#define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */
-#define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */
-
-/*
- * Macro Q_ADDR()
- *
- * Use this macro to access the Receive and Transmit Queue Registers.
- *
- * para:
- * Queue Queue to access.
- * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- * Offs Queue register offset.
- * Values: Q_D, Q_DA_L ... Q_T2, Q_T3
- *
- * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal)
- */
-#define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs))
-
-/*
- * Macro RB_ADDR()
- *
- * Use this macro to access the RAM Buffer Registers.
- *
- * para:
- * Queue Queue to access.
- * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2
- * Offs Queue register offset.
- * Values: RB_START, RB_END ... RB_LEV, RB_CTRL
- *
- * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal)
- */
-#define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs))
-
-
-/* MAC Related Registers */
-#define MAC_1 0 /* belongs to the port near the slot */
-#define MAC_2 1 /* belongs to the port far away from the slot */
-
-/*
- * Macro MR_ADDR()
- *
- * Use this macro to access a MAC Related Registers inside the ASIC.
- *
- * para:
- * Mac MAC to access.
- * Values: MAC_1, MAC_2
- * Offs MAC register offset.
- * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
- * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
- *
- * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
- */
-#define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs))
-
-#ifdef SK_LITTLE_ENDIAN
-#define XM_WORD_LO 0
-#define XM_WORD_HI 1
-#else /* !SK_LITTLE_ENDIAN */
-#define XM_WORD_LO 1
-#define XM_WORD_HI 0
-#endif /* !SK_LITTLE_ENDIAN */
-
-
-/*
- * macros to access the XMAC (GENESIS only)
- *
- * XM_IN16(), to read a 16 bit register (e.g. XM_MMU_CMD)
- * XM_OUT16(), to write a 16 bit register (e.g. XM_MMU_CMD)
- * XM_IN32(), to read a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_OUT32(), to write a 32 bit register (e.g. XM_TX_EV_CNT)
- * XM_INADDR(), to read a network address register (e.g. XM_SRC_CHK)
- * XM_OUTADDR(), to write a network address register (e.g. XM_SRC_CHK)
- * XM_INHASH(), to read the XM_HSM_CHK register
- * XM_OUTHASH() to write the XM_HSM_CHK register
- *
- * para:
- * Mac XMAC to access values: MAC_1 or MAC_2
- * IoC I/O context needed for SK I/O macros
- * Reg XMAC Register to read or write
- * (p)Val Value or pointer to the value which should be read or written
- *
- * usage: XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value);
- */
-
-#define XMA(Mac, Reg) \
- ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
-
-#define XM_IN16(IoC, Mac, Reg, pVal) \
- SK_IN16((IoC), XMA((Mac), (Reg)), (pVal))
-
-#define XM_OUT16(IoC, Mac, Reg, Val) \
- SK_OUT16((IoC), XMA((Mac), (Reg)), (Val))
-
-#define XM_IN32(IoC, Mac, Reg, pVal) { \
- SK_IN16((IoC), XMA((Mac), (Reg)), \
- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \
- SK_IN16((IoC), XMA((Mac), (Reg+2)), \
- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \
-}
-
-#define XM_OUT32(IoC, Mac, Reg, Val) { \
- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \
- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
-
-#define XM_INADDR(IoC, Mac, Reg, pVal) { \
- SK_U16 Word; \
- SK_U8 *pByte; \
- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
- SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \
- pByte[0] = (SK_U8)(Word & 0x00ff); \
- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \
- pByte[2] = (SK_U8)(Word & 0x00ff); \
- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \
- pByte[4] = (SK_U8)(Word & 0x00ff); \
- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
-}
-
-#define XM_OUTADDR(IoC, Mac, Reg, pVal) { \
- SK_U8 SK_FAR *pByte; \
- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \
- (((SK_U16)(pByte[0]) & 0x00ff) | \
- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \
- (((SK_U16)(pByte[2]) & 0x00ff) | \
- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \
- (((SK_U16)(pByte[4]) & 0x00ff) | \
- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
-}
-
-#define XM_INHASH(IoC, Mac, Reg, pVal) { \
- SK_U16 Word; \
- SK_U8 SK_FAR *pByte; \
- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
- SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \
- pByte[0] = (SK_U8)(Word & 0x00ff); \
- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \
- pByte[2] = (SK_U8)(Word & 0x00ff); \
- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \
- pByte[4] = (SK_U8)(Word & 0x00ff); \
- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \
- pByte[6] = (SK_U8)(Word & 0x00ff); \
- pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \
-}
-
-#define XM_OUTHASH(IoC, Mac, Reg, pVal) { \
- SK_U8 SK_FAR *pByte; \
- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \
- (((SK_U16)(pByte[0]) & 0x00ff)| \
- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \
- (((SK_U16)(pByte[2]) & 0x00ff)| \
- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \
- (((SK_U16)(pByte[4]) & 0x00ff)| \
- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
- SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \
- (((SK_U16)(pByte[6]) & 0x00ff)| \
- (((SK_U16)(pByte[7]) << 8) & 0xff00))); \
-}
-
-/*
- * macros to access the GMAC (YUKON only)
- *
- * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT)
- * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL)
- * GM_IN32(), to read a 32 bit register (e.g. GM_)
- * GM_OUT32(), to write a 32 bit register (e.g. GM_)
- * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L)
- * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L)
- * GM_INHASH(), to read the GM_MC_ADDR_H1 register
- * GM_OUTHASH() to write the GM_MC_ADDR_H1 register
- *
- * para:
- * Mac GMAC to access values: MAC_1 or MAC_2
- * IoC I/O context needed for SK I/O macros
- * Reg GMAC Register to read or write
- * (p)Val Value or pointer to the value which should be read or written
- *
- * usage: GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value);
- */
-
-#define GMA(Mac, Reg) \
- ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
-
-#define GM_IN16(IoC, Mac, Reg, pVal) \
- SK_IN16((IoC), GMA((Mac), (Reg)), (pVal))
-
-#define GM_OUT16(IoC, Mac, Reg, Val) \
- SK_OUT16((IoC), GMA((Mac), (Reg)), (Val))
-
-#define GM_IN32(IoC, Mac, Reg, pVal) { \
- SK_IN16((IoC), GMA((Mac), (Reg)), \
- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \
- SK_IN16((IoC), GMA((Mac), (Reg+4)), \
- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \
-}
-
-#define GM_OUT32(IoC, Mac, Reg, Val) { \
- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \
- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\
-}
-
-#define GM_INADDR(IoC, Mac, Reg, pVal) { \
- SK_U16 Word; \
- SK_U8 *pByte; \
- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
- SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \
- pByte[0] = (SK_U8)(Word & 0x00ff); \
- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \
- pByte[2] = (SK_U8)(Word & 0x00ff); \
- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \
- pByte[4] = (SK_U8)(Word & 0x00ff); \
- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
-}
-
-#define GM_OUTADDR(IoC, Mac, Reg, pVal) { \
- SK_U8 SK_FAR *pByte; \
- pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \
- (((SK_U16)(pByte[0]) & 0x00ff) | \
- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \
- (((SK_U16)(pByte[2]) & 0x00ff) | \
- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \
- (((SK_U16)(pByte[4]) & 0x00ff) | \
- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
-}
-
-#define GM_INHASH(IoC, Mac, Reg, pVal) { \
- SK_U16 Word; \
- SK_U8 *pByte; \
- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
- SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \
- pByte[0] = (SK_U8)(Word & 0x00ff); \
- pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \
- pByte[2] = (SK_U8)(Word & 0x00ff); \
- pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \
- pByte[4] = (SK_U8)(Word & 0x00ff); \
- pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
- SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \
- pByte[6] = (SK_U8)(Word & 0x00ff); \
- pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \
-}
-
-#define GM_OUTHASH(IoC, Mac, Reg, pVal) { \
- SK_U8 *pByte; \
- pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \
- (((SK_U16)(pByte[0]) & 0x00ff)| \
- (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \
- (((SK_U16)(pByte[2]) & 0x00ff)| \
- (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \
- (((SK_U16)(pByte[4]) & 0x00ff)| \
- (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
- SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \
- (((SK_U16)(pByte[6]) & 0x00ff)| \
- (((SK_U16)(pByte[7]) << 8) & 0xff00))); \
-}
-
-/*
- * Different MAC Types
- */
-#define SK_MAC_XMAC 0 /* Xaqti XMAC II */
-#define SK_MAC_GMAC 1 /* Marvell GMAC */
-
-/*
- * Different PHY Types
- */
-#define SK_PHY_XMAC 0 /* integrated in XMAC II */
-#define SK_PHY_BCOM 1 /* Broadcom BCM5400 */
-#define SK_PHY_LONE 2 /* Level One LXT1000 */
-#define SK_PHY_NAT 3 /* National DP83891 */
-#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1011S */
-#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1011S working on fiber */
-
-/*
- * PHY addresses (bits 12..8 of PHY address reg)
- */
-#define PHY_ADDR_XMAC (0<<8)
-#define PHY_ADDR_BCOM (1<<8)
-#define PHY_ADDR_LONE (3<<8)
-#define PHY_ADDR_NAT (0<<8)
-
-/* GPHY address (bits 15..11 of SMI control reg) */
-#define PHY_ADDR_MARV 0
-
-/*
- * macros to access the PHY
- *
- * PHY_READ() read a 16 bit value from the PHY
- * PHY_WRITE() write a 16 bit value to the PHY
- *
- * para:
- * IoC I/O context needed for SK I/O macros
- * pPort Pointer to port struct for PhyAddr
- * Mac XMAC to access values: MAC_1 or MAC_2
- * PhyReg PHY Register to read or write
- * (p)Val Value or pointer to the value which should be read or
- * written.
- *
- * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
- * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
- * comes back. This is checked in DEBUG mode.
- */
-#ifndef DEBUG
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \
- SK_U16 Mmu; \
- \
- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
- if ((pPort)->PhyType != SK_PHY_XMAC) { \
- do { \
- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
- } while ((Mmu & XM_MMU_PHY_RDY) == 0); \
- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
- } \
-}
-#else
-#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \
- SK_U16 Mmu; \
- int __i = 0; \
- \
- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
- if ((pPort)->PhyType != SK_PHY_XMAC) { \
- do { \
- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
- __i++; \
- if (__i > 100000) { \
- SK_DBG_PRINTF("*****************************\n"); \
- SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n"); \
- SK_DBG_PRINTF("*****************************\n"); \
- break; \
- } \
- } while ((Mmu & XM_MMU_PHY_RDY) == 0); \
- XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
- } \
-}
-#endif /* DEBUG */
-
-#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) { \
- SK_U16 Mmu; \
- \
- if ((pPort)->PhyType != SK_PHY_XMAC) { \
- do { \
- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
- } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \
- } \
- XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
- XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \
- if ((pPort)->PhyType != SK_PHY_XMAC) { \
- do { \
- XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
- } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \
- } \
-}
-
-/*
- * Macro PCI_C()
- *
- * Use this macro to access PCI config register from the I/O space.
- *
- * para:
- * Addr PCI configuration register to access.
- * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
- *
- * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal);
- */
-#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */
-
-/*
- * Macro SK_HW_ADDR(Base, Addr)
- *
- * Calculates the effective HW address
- *
- * para:
- * Base I/O or memory base address
- * Addr Address offset
- *
- * usage: May be used in SK_INxx and SK_OUTxx macros
- * #define SK_IN8(pAC, Addr, pVal) ...\
- * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
- */
-#ifdef SK_MEM_MAPPED_IO
-#define SK_HW_ADDR(Base, Addr) ((Base) + (Addr))
-#else /* SK_MEM_MAPPED_IO */
-#define SK_HW_ADDR(Base, Addr) \
- ((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0)))
-#endif /* SK_MEM_MAPPED_IO */
-
-#define SZ_LONG (sizeof(SK_U32))
-
-/*
- * Macro SK_HWAC_LINK_LED()
- *
- * Use this macro to set the link LED mode.
- * para:
- * pAC Pointer to adapter context struct
- * IoC I/O context needed for SK I/O macros
- * Port Port number
- * Mode Mode to set for this LED
- */
-#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
- SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
-
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_SKGEHW_H */
diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h
deleted file mode 100644
index e6b0016a695..00000000000
--- a/drivers/net/sk98lin/h/skgehwt.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/******************************************************************************
- *
- * Name: skhwt.h
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.7 $
- * Date: $Date: 2003/09/16 12:55:08 $
- * Purpose: Defines for the hardware timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEHWT.H contains all defines and types for the timer functions
- */
-
-#ifndef _SKGEHWT_H_
-#define _SKGEHWT_H_
-
-/*
- * SK Hardware Timer
- * - needed wherever the HWT module is used
- * - use in Adapters context name pAC->Hwt
- */
-typedef struct s_Hwt {
- SK_U32 TStart; /* HWT start */
- SK_U32 TStop; /* HWT stop */
- int TActive; /* HWT: flag : active/inactive */
-} SK_HWT;
-
-extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time);
-extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc);
-extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc);
-extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc);
-#endif /* _SKGEHWT_H_ */
diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h
deleted file mode 100644
index d9b6f6d8dfe..00000000000
--- a/drivers/net/sk98lin/h/skgei2c.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/******************************************************************************
- *
- * Name: skgei2c.h
- * Project: Gigabit Ethernet Adapters, TWSI-Module
- * Version: $Revision: 1.25 $
- * Date: $Date: 2003/10/20 09:06:05 $
- * Purpose: Special defines for TWSI
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKGEI2C.H contains all SK-98xx specific defines for the TWSI handling
- */
-
-#ifndef _INC_SKGEI2C_H_
-#define _INC_SKGEI2C_H_
-
-/*
- * Macros to access the B2_I2C_CTRL
- */
-#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
- SK_OUT32(IoC, B2_I2C_CTRL,\
- (flag ? 0x80000000UL : 0x0L) | \
- (((SK_U32)reg << 16) & I2C_ADDR) | \
- (((SK_U32)dev << 9) & I2C_DEV_SEL) | \
- (dev_size & I2C_DEV_SIZE) | \
- ((burst << 4) & I2C_BURST_LEN))
-
-#define SK_I2C_STOP(IoC) { \
- SK_U32 I2cCtrl; \
- SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \
- SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \
-}
-
-#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
-
-/*
- * Macros to access the TWSI SW Registers
- */
-#define SK_I2C_SET_BIT(IoC, SetBits) { \
- SK_U8 OrgBits; \
- SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
- SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \
-}
-
-#define SK_I2C_CLR_BIT(IoC, ClrBits) { \
- SK_U8 OrgBits; \
- SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
- SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \
-}
-
-#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw)
-
-/*
- * define the possible sensor states
- */
-#define SK_SEN_IDLE 0 /* Idle: sensor not read */
-#define SK_SEN_VALUE 1 /* Value Read cycle */
-#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */
-
-/*
- * Conversion factor to convert read Voltage sensor to milli Volt
- * Conversion factor to convert read Temperature sensor to 10th degree Celsius
- */
-#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */
-#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */
-#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */
-
-/*
- * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
- * assuming: 6500rpm, 4 pulses, divisor 1
- */
-#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2))
-
-/*
- * Define sensor management data
- * Maximum is reached on Genesis copper dual port and Yukon-64
- * Board specific maximum is in pAC->I2c.MaxSens
- */
-#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */
-#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */
-
-/*
- * To watch the state machine (SM) use the timer in two ways
- * instead of one as hitherto
- */
-#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */
-#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */
-
-/*
- * Defines for the individual thresholds
- */
-
-/* Temperature sensor */
-#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */
-#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */
-#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */
-#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */
-
-/* VCC which should be 5 V */
-#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */
-#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */
-#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */
-#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */
-
-/*
- * VIO may be 5 V or 3.3 V. Initialization takes two parts:
- * 1. Initialize lowest lower limit and highest higher limit.
- * 2. After the first value is read correct the upper or the lower limit to
- * the appropriate C constant.
- *
- * Warning limits are +-5% of the exepected voltage.
- * Error limits are +-10% of the expected voltage.
- */
-
-/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
-
-#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */
-#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */
- /* 5000 mVolt */
-#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */
-#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */
-
-#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */
-
-/* correction values for the second pass */
-#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */
-#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */
- /* 3300 mVolt */
-#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */
-#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */
-
-/*
- * VDD voltage
- */
-#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */
-#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */
-#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */
-#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */
-
-/*
- * PHY PLL 3V3 voltage
- */
-#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */
-#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */
-#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */
-#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */
-
-/*
- * VAUX (YUKON only)
- */
-#define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */
-#define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */
-#define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */
-#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */
-#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */
-#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */
-
-/*
- * PHY 2V5 voltage
- */
-#define SK_SEN_PHY_2V5_HIGH_ERR 2750 /* Voltage PHY High Err Threshold */
-#define SK_SEN_PHY_2V5_HIGH_WARN 2640 /* Voltage PHY High Warn Threshold */
-#define SK_SEN_PHY_2V5_LOW_WARN 2376 /* Voltage PHY Low Warn Threshold */
-#define SK_SEN_PHY_2V5_LOW_ERR 2222 /* Voltage PHY Low Err Threshold */
-
-/*
- * ASIC Core 1V5 voltage (YUKON only)
- */
-#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */
-#define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */
-#define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */
-#define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */
-
-/*
- * FAN 1 speed
- */
-/* assuming: 6500rpm +-15%, 4 pulses,
- * warning at: 80 %
- * error at: 70 %
- * no upper limit
- */
-#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */
-#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */
-#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */
-#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */
-
-/*
- * Some Voltages need dynamic thresholds
- */
-#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */
-#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */
-#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */
-
-extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
-#endif /* n_INC_SKGEI2C_H */
diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h
deleted file mode 100644
index 143e635ec24..00000000000
--- a/drivers/net/sk98lin/h/skgeinit.h
+++ /dev/null
@@ -1,797 +0,0 @@
-/******************************************************************************
- *
- * Name: skgeinit.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.83 $
- * Date: $Date: 2003/09/16 14:07:37 $
- * Purpose: Structures and prototypes for the GE Init Module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_SKGEINIT_H_
-#define __INC_SKGEINIT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_TEST_VAL 0x11335577UL
-
-/* modifying Link LED behaviour (used with SkGeLinkLED()) */
-#define SK_LNK_OFF LED_OFF
-#define SK_LNK_ON (LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LNK_BLINK (LED_ON | LED_BLK_ON | LED_SYNC_ON)
-#define SK_LNK_PERM (LED_ON | LED_BLK_OFF | LED_SYNC_ON)
-#define SK_LNK_TST (LED_ON | LED_BLK_ON | LED_SYNC_OFF)
-
-/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */
-#define SK_LED_OFF LED_OFF
-#define SK_LED_ACTIVE (LED_ON | LED_BLK_OFF | LED_SYNC_OFF)
-#define SK_LED_STANDBY (LED_ON | LED_BLK_ON | LED_SYNC_OFF)
-
-/* addressing LED Registers in SkGeXmitLED() */
-#define XMIT_LED_INI 0
-#define XMIT_LED_CNT (RX_LED_VAL - RX_LED_INI)
-#define XMIT_LED_CTRL (RX_LED_CTRL- RX_LED_INI)
-#define XMIT_LED_TST (RX_LED_TST - RX_LED_INI)
-
-/* parameter 'Mode' when calling SkGeXmitLED() */
-#define SK_LED_DIS 0
-#define SK_LED_ENA 1
-#define SK_LED_TST 2
-
-/* Counter and Timer constants, for a host clock of 62.5 MHz */
-#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */
-#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */
-
-#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */
-
-#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */
- /* 215 ms at 78.12 MHz */
-
-#define SK_FACT_62 100 /* is given in percent */
-#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */
-#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */
-
-/* Timeout values */
-#define SK_MAC_TO_53 72 /* MAC arbiter timeout */
-#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */
-#define SK_PKT_TO_MAX 0xffff /* Maximum value */
-#define SK_RI_TO_53 36 /* RAM interface timeout */
-
-#define SK_PHY_ACC_TO 600000 /* PHY access timeout */
-
-/* RAM Buffer High Pause Threshold values */
-#define SK_RB_ULPP ( 8 * 1024) /* Upper Level in kB/8 */
-#define SK_RB_LLPP_S (10 * 1024) /* Lower Level for small Queues */
-#define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */
-
-#ifndef SK_BMU_RX_WM
-#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */
-#endif
-#ifndef SK_BMU_TX_WM
-#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */
-#endif
-
-/* XMAC II Rx High Watermark */
-#define SK_XM_RX_HI_WM 0x05aa /* 1450 */
-
-/* XMAC II Tx Threshold */
-#define SK_XM_THR_REDL 0x01fb /* .. for redundant link usage */
-#define SK_XM_THR_SL 0x01fb /* .. for single link adapters */
-#define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */
-#define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */
-
-/* values for GIPortUsage */
-#define SK_RED_LINK 1 /* redundant link usage */
-#define SK_MUL_LINK 2 /* multiple link usage */
-#define SK_JUMBO_LINK 3 /* driver uses jumbo frames */
-
-/* Minimum RAM Buffer Rx Queue Size */
-#define SK_MIN_RXQ_SIZE 16 /* 16 kB */
-
-/* Minimum RAM Buffer Tx Queue Size */
-#define SK_MIN_TXQ_SIZE 16 /* 16 kB */
-
-/* Queue Size units */
-#define QZ_UNITS 0x7
-#define QZ_STEP 8
-
-/* Percentage of queue size from whole memory */
-/* 80 % for receive */
-#define RAM_QUOTA_RX 80L
-/* 0% for sync transfer */
-#define RAM_QUOTA_SYNC 0L
-/* the rest (20%) is taken for async transfer */
-
-/* Get the rounded queue size in Bytes in 8k steps */
-#define ROUND_QUEUE_SIZE(SizeInBytes) \
- ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \
- ~(QZ_STEP-1))
-
-/* Get the rounded queue size in KBytes in 8k steps */
-#define ROUND_QUEUE_SIZE_KB(Kilobytes) \
- ROUND_QUEUE_SIZE((Kilobytes) * 1024L)
-
-/* Types of RAM Buffer Queues */
-#define SK_RX_SRAM_Q 1 /* small receive queue */
-#define SK_RX_BRAM_Q 2 /* big receive queue */
-#define SK_TX_RAM_Q 3 /* small or big transmit queue */
-
-/* parameter 'Dir' when calling SkGeStopPort() */
-#define SK_STOP_TX 1 /* Stops the transmit path, resets the XMAC */
-#define SK_STOP_RX 2 /* Stops the receive path */
-#define SK_STOP_ALL 3 /* Stops Rx and Tx path, resets the XMAC */
-
-/* parameter 'RstMode' when calling SkGeStopPort() */
-#define SK_SOFT_RST 1 /* perform a software reset */
-#define SK_HARD_RST 2 /* perform a hardware reset */
-
-/* Init Levels */
-#define SK_INIT_DATA 0 /* Init level 0: init data structures */
-#define SK_INIT_IO 1 /* Init level 1: init with IOs */
-#define SK_INIT_RUN 2 /* Init level 2: init for run time */
-
-/* Link Mode Parameter */
-#define SK_LMODE_HALF 1 /* Half Duplex Mode */
-#define SK_LMODE_FULL 2 /* Full Duplex Mode */
-#define SK_LMODE_AUTOHALF 3 /* AutoHalf Duplex Mode */
-#define SK_LMODE_AUTOFULL 4 /* AutoFull Duplex Mode */
-#define SK_LMODE_AUTOBOTH 5 /* AutoBoth Duplex Mode */
-#define SK_LMODE_AUTOSENSE 6 /* configured mode auto sensing */
-#define SK_LMODE_INDETERMINATED 7 /* indeterminated */
-
-/* Auto-negotiation timeout in 100ms granularity */
-#define SK_AND_MAX_TO 6 /* Wait 600 msec before link comes up */
-
-/* Auto-negotiation error codes */
-#define SK_AND_OK 0 /* no error */
-#define SK_AND_OTHER 1 /* other error than below */
-#define SK_AND_DUP_CAP 2 /* Duplex capabilities error */
-
-
-/* Link Speed Capabilities */
-#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */
-#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */
-#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */
-#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */
-#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Speed Parameter */
-#define SK_LSPEED_AUTO 1 /* Automatic resolution */
-#define SK_LSPEED_10MBPS 2 /* 10 Mbps */
-#define SK_LSPEED_100MBPS 3 /* 100 Mbps */
-#define SK_LSPEED_1000MBPS 4 /* 1000 Mbps */
-#define SK_LSPEED_INDETERMINATED 5 /* indeterminated */
-
-/* Link Speed Current State */
-#define SK_LSPEED_STAT_UNKNOWN 1
-#define SK_LSPEED_STAT_10MBPS 2
-#define SK_LSPEED_STAT_100MBPS 3
-#define SK_LSPEED_STAT_1000MBPS 4
-#define SK_LSPEED_STAT_INDETERMINATED 5
-
-
-/* Link Capability Parameter */
-#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */
-#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */
-#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */
-#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */
-#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */
-
-/* Link Mode Current State */
-#define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */
-#define SK_LMODE_STAT_HALF 2 /* Half Duplex Mode */
-#define SK_LMODE_STAT_FULL 3 /* Full Duplex Mode */
-#define SK_LMODE_STAT_AUTOHALF 4 /* Half Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_AUTOFULL 5 /* Full Duplex Mode obtained by Auto-Neg */
-#define SK_LMODE_STAT_INDETERMINATED 6 /* indeterminated */
-
-/* Flow Control Mode Parameter (and capabilities) */
-#define SK_FLOW_MODE_NONE 1 /* No Flow-Control */
-#define SK_FLOW_MODE_LOC_SEND 2 /* Local station sends PAUSE */
-#define SK_FLOW_MODE_SYMMETRIC 3 /* Both stations may send PAUSE */
-#define SK_FLOW_MODE_SYM_OR_REM 4 /* Both stations may send PAUSE or
- * just the remote station may send PAUSE
- */
-#define SK_FLOW_MODE_INDETERMINATED 5 /* indeterminated */
-
-/* Flow Control Status Parameter */
-#define SK_FLOW_STAT_NONE 1 /* No Flow Control */
-#define SK_FLOW_STAT_REM_SEND 2 /* Remote Station sends PAUSE */
-#define SK_FLOW_STAT_LOC_SEND 3 /* Local station sends PAUSE */
-#define SK_FLOW_STAT_SYMMETRIC 4 /* Both station may send PAUSE */
-#define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */
-
-/* Master/Slave Mode Capabilities */
-#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */
-#define SK_MS_CAP_MASTER (1<<1) /* This station is master */
-#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */
-#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */
-
-/* Set Master/Slave Mode Parameter (and capabilities) */
-#define SK_MS_MODE_AUTO 1 /* Automatic resolution */
-#define SK_MS_MODE_MASTER 2 /* This station is master */
-#define SK_MS_MODE_SLAVE 3 /* This station is slave */
-#define SK_MS_MODE_INDETERMINATED 4 /* indeterminated */
-
-/* Master/Slave Status Parameter */
-#define SK_MS_STAT_UNSET 1 /* The M/S status is not set */
-#define SK_MS_STAT_MASTER 2 /* This station is master */
-#define SK_MS_STAT_SLAVE 3 /* This station is slave */
-#define SK_MS_STAT_FAULT 4 /* M/S resolution failed */
-#define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */
-
-/* parameter 'Mode' when calling SkXmSetRxCmd() */
-#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */
-#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */
-#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */
-#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */
-#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */
-#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */
-#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */
-#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */
-#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */
-#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */
-
-/* parameter 'Para' when calling SkMacSetRxTxEn() */
-#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */
-#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */
-#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */
-#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */
-#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */
-#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */
-
-/* States of PState */
-#define SK_PRT_RESET 0 /* the port is reset */
-#define SK_PRT_STOP 1 /* the port is stopped (similar to SW reset) */
-#define SK_PRT_INIT 2 /* the port is initialized */
-#define SK_PRT_RUN 3 /* the port has an active link */
-
-/* PHY power down modes */
-#define PHY_PM_OPERATIONAL_MODE 0 /* PHY operational mode */
-#define PHY_PM_DEEP_SLEEP 1 /* coma mode --> minimal power */
-#define PHY_PM_IEEE_POWER_DOWN 2 /* IEEE 22.2.4.1.5 compl. power down */
-#define PHY_PM_ENERGY_DETECT 3 /* energy detect */
-#define PHY_PM_ENERGY_DETECT_PLUS 4 /* energy detect plus */
-
-/* Default receive frame limit for Workaround of XMAC Errata */
-#define SK_DEF_RX_WA_LIM SK_CONSTU64(100)
-
-/* values for GILedBlinkCtrl (LED Blink Control) */
-#define SK_ACT_LED_BLINK (1<<0) /* Active LED blinking */
-#define SK_DUP_LED_NORMAL (1<<1) /* Duplex LED normal */
-#define SK_LED_LINK100_ON (1<<2) /* Link 100M LED on */
-
-/* Link Partner Status */
-#define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */
-#define SK_LIPA_MANUAL 1 /* Link partner is in detected manual state */
-#define SK_LIPA_AUTO 2 /* Link partner is in auto-negotiation state */
-
-/* Maximum Restarts before restart is ignored (3Com WA) */
-#define SK_MAX_LRESTART 3 /* Max. 3 times the link is restarted */
-
-/* Max. Auto-neg. timeouts before link detection in sense mode is reset */
-#define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */
-
-/* structures *****************************************************************/
-
-/*
- * MAC specific functions
- */
-typedef struct s_GeMacFunc {
- int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
- int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
- SK_U16 StatAddr, SK_U32 SK_FAR *pVal);
- int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
- int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
- SK_U16 IStatus, SK_U64 SK_FAR *pVal);
-} SK_GEMACFUNC;
-
-/*
- * Port Structure
- */
-typedef struct s_GePort {
-#ifndef SK_DIAG
- SK_TIMER PWaTimer; /* Workaround Timer */
- SK_TIMER HalfDupChkTimer;
-#endif /* SK_DIAG */
- SK_U32 PPrevShorts; /* Previous Short Counter checking */
- SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */
- SK_U64 PPrevRx; /* Previous RxOk Counter checking */
- SK_U64 PRxLim; /* Previous RxOk Counter checking */
- SK_U64 LastOctets; /* For half duplex hang check */
- int PLinkResCt; /* Link Restart Counter */
- int PAutoNegTimeOut;/* Auto-negotiation timeout current value */
- int PAutoNegTOCt; /* Auto-negotiation Timeout Counter */
- int PRxQSize; /* Port Rx Queue Size in kB */
- int PXSQSize; /* Port Synchronous Transmit Queue Size in kB */
- int PXAQSize; /* Port Asynchronous Transmit Queue Size in kB */
- SK_U32 PRxQRamStart; /* Receive Queue RAM Buffer Start Address */
- SK_U32 PRxQRamEnd; /* Receive Queue RAM Buffer End Address */
- SK_U32 PXsQRamStart; /* Sync Tx Queue RAM Buffer Start Address */
- SK_U32 PXsQRamEnd; /* Sync Tx Queue RAM Buffer End Address */
- SK_U32 PXaQRamStart; /* Async Tx Queue RAM Buffer Start Address */
- SK_U32 PXaQRamEnd; /* Async Tx Queue RAM Buffer End Address */
- SK_U32 PRxOverCnt; /* Receive Overflow Counter */
- int PRxQOff; /* Rx Queue Address Offset */
- int PXsQOff; /* Synchronous Tx Queue Address Offset */
- int PXaQOff; /* Asynchronous Tx Queue Address Offset */
- int PhyType; /* PHY used on this port */
- int PState; /* Port status (reset, stop, init, run) */
- SK_U16 PhyId1; /* PHY Id1 on this port */
- SK_U16 PhyAddr; /* MDIO/MDC PHY address */
- SK_U16 PIsave; /* Saved Interrupt status word */
- SK_U16 PSsave; /* Saved PHY status word */
- SK_U16 PGmANegAdv; /* Saved GPhy AutoNegAdvertisment register */
- SK_BOOL PHWLinkUp; /* The hardware Link is up (wiring) */
- SK_BOOL PLinkBroken; /* Is Link broken ? */
- SK_BOOL PCheckPar; /* Do we check for parity errors ? */
- SK_BOOL HalfDupTimerActive;
- SK_U8 PLinkCap; /* Link Capabilities */
- SK_U8 PLinkModeConf; /* Link Mode configured */
- SK_U8 PLinkMode; /* Link Mode currently used */
- SK_U8 PLinkModeStatus;/* Link Mode Status */
- SK_U8 PLinkSpeedCap; /* Link Speed Capabilities(10/100/1000 Mbps) */
- SK_U8 PLinkSpeed; /* configured Link Speed (10/100/1000 Mbps) */
- SK_U8 PLinkSpeedUsed; /* current Link Speed (10/100/1000 Mbps) */
- SK_U8 PFlowCtrlCap; /* Flow Control Capabilities */
- SK_U8 PFlowCtrlMode; /* Flow Control Mode */
- SK_U8 PFlowCtrlStatus;/* Flow Control Status */
- SK_U8 PMSCap; /* Master/Slave Capabilities */
- SK_U8 PMSMode; /* Master/Slave Mode */
- SK_U8 PMSStatus; /* Master/Slave Status */
- SK_BOOL PAutoNegFail; /* Auto-negotiation fail flag */
- SK_U8 PLipaAutoNeg; /* Auto-negotiation possible with Link Partner */
- SK_U8 PCableLen; /* Cable Length */
- SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */
- SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */
- SK_U8 PPhyPowerState; /* PHY current power state */
- int PMacColThres; /* MAC Collision Threshold */
- int PMacJamLen; /* MAC Jam length */
- int PMacJamIpgVal; /* MAC Jam IPG */
- int PMacJamIpgData; /* MAC IPG Jam to Data */
- int PMacIpgData; /* MAC Data IPG */
- SK_BOOL PMacLimit4; /* reset collision counter and backoff algorithm */
-} SK_GEPORT;
-
-/*
- * Gigabit Ethernet Initialization Struct
- * (has to be included in the adapter context)
- */
-typedef struct s_GeInit {
- int GIChipId; /* Chip Identification Number */
- int GIChipRev; /* Chip Revision Number */
- SK_U8 GIPciHwRev; /* PCI HW Revision Number */
- SK_BOOL GIGenesis; /* Genesis adapter ? */
- SK_BOOL GIYukon; /* YUKON-A1/Bx chip */
- SK_BOOL GIYukonLite; /* YUKON-Lite chip */
- SK_BOOL GICopperType; /* Copper Type adapter ? */
- SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */
- SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */
- SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */
- SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */
- SK_U16 GILedBlinkCtrl; /* LED Blink Control */
- int GIMacsFound; /* Number of MACs found on this adapter */
- int GIMacType; /* MAC Type used on this adapter */
- int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */
- int GIPortUsage; /* Driver Port Usage */
- int GILevel; /* Initialization Level completed */
- int GIRamSize; /* The RAM size of the adapter in kB */
- int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */
- SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */
- SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */
- SK_U32 GIValIrqMask; /* Value for Interrupt Mask */
- SK_U32 GITimeStampCnt; /* Time Stamp High Counter (YUKON only) */
- SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */
- SK_GEMACFUNC GIFunc; /* MAC depedent functions */
-} SK_GEINIT;
-
-/*
- * Error numbers and messages for skxmac2.c and skgeinit.c
- */
-#define SKERR_HWI_E001 (SK_ERRBASE_HWINIT)
-#define SKERR_HWI_E001MSG "SkXmClrExactAddr() has got illegal parameters"
-#define SKERR_HWI_E002 (SKERR_HWI_E001+1)
-#define SKERR_HWI_E002MSG "SkGeInit(): Level 1 call missing"
-#define SKERR_HWI_E003 (SKERR_HWI_E002+1)
-#define SKERR_HWI_E003MSG "SkGeInit() called with illegal init Level"
-#define SKERR_HWI_E004 (SKERR_HWI_E003+1)
-#define SKERR_HWI_E004MSG "SkGeInitPort(): Queue Size illegal configured"
-#define SKERR_HWI_E005 (SKERR_HWI_E004+1)
-#define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports"
-#define SKERR_HWI_E006 (SKERR_HWI_E005+1)
-#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state"
-#define SKERR_HWI_E007 (SKERR_HWI_E006+1)
-#define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode"
-#define SKERR_HWI_E008 (SKERR_HWI_E007+1)
-#define SKERR_HWI_E008MSG "SkXmSetRxCmd() called with invalid Mode"
-#define SKERR_HWI_E009 (SKERR_HWI_E008+1)
-#define SKERR_HWI_E009MSG "SkGeCfgSync() called although PXSQSize zero"
-#define SKERR_HWI_E010 (SKERR_HWI_E009+1)
-#define SKERR_HWI_E010MSG "SkGeCfgSync() called with invalid parameters"
-#define SKERR_HWI_E011 (SKERR_HWI_E010+1)
-#define SKERR_HWI_E011MSG "SkGeInitPort(): Receive Queue Size too small"
-#define SKERR_HWI_E012 (SKERR_HWI_E011+1)
-#define SKERR_HWI_E012MSG "SkGeInitPort(): invalid Queue Size specified"
-#define SKERR_HWI_E013 (SKERR_HWI_E012+1)
-#define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue"
-#define SKERR_HWI_E014 (SKERR_HWI_E013+1)
-#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified"
-#define SKERR_HWI_E015 (SKERR_HWI_E014+1)
-#define SKERR_HWI_E015MSG "Illegal Link mode parameter"
-#define SKERR_HWI_E016 (SKERR_HWI_E015+1)
-#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter"
-#define SKERR_HWI_E017 (SKERR_HWI_E016+1)
-#define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal"
-#define SKERR_HWI_E018 (SKERR_HWI_E017+1)
-#define SKERR_HWI_E018MSG "FATAL: SkGeStopPort() does not terminate (Tx)"
-#define SKERR_HWI_E019 (SKERR_HWI_E018+1)
-#define SKERR_HWI_E019MSG "Illegal Speed parameter"
-#define SKERR_HWI_E020 (SKERR_HWI_E019+1)
-#define SKERR_HWI_E020MSG "Illegal Master/Slave parameter"
-#define SKERR_HWI_E021 (SKERR_HWI_E020+1)
-#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter"
-#define SKERR_HWI_E022 (SKERR_HWI_E021+1)
-#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address"
-#define SKERR_HWI_E023 (SKERR_HWI_E022+1)
-#define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small"
-#define SKERR_HWI_E024 (SKERR_HWI_E023+1)
-#define SKERR_HWI_E024MSG "FATAL: SkGeStopPort() does not terminate (Rx)"
-#define SKERR_HWI_E025 (SKERR_HWI_E024+1)
-#define SKERR_HWI_E025MSG ""
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-
-/*
- * public functions in skgeinit.c
- */
-extern void SkGePollTxD(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL PollTxD);
-
-extern void SkGeYellowLED(
- SK_AC *pAC,
- SK_IOC IoC,
- int State);
-
-extern int SkGeCfgSync(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_U32 IntTime,
- SK_U32 LimCount,
- int SyncMode);
-
-extern void SkGeLoadLnkSyncCnt(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_U32 CntVal);
-
-extern void SkGeStopPort(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Dir,
- int RstMode);
-
-extern int SkGeInit(
- SK_AC *pAC,
- SK_IOC IoC,
- int Level);
-
-extern void SkGeDeInit(
- SK_AC *pAC,
- SK_IOC IoC);
-
-extern int SkGeInitPort(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkGeXmitLED(
- SK_AC *pAC,
- SK_IOC IoC,
- int Led,
- int Mode);
-
-extern int SkGeInitAssignRamToQueues(
- SK_AC *pAC,
- int ActivePort,
- SK_BOOL DualNet);
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacSoftRst(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacHardRst(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkXmInitMac(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkGmInitMac(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacInitPhy(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL DoLoop);
-
-extern void SkMacIrqDisable(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacFlushTxFifo(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacIrq(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern int SkMacAutoNegDone(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacAutoNegLipaPhy(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_U16 IStatus);
-
-extern int SkMacRxTxEnable(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port);
-
-extern void SkMacPromiscMode(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-
-extern void SkMacHashing(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-
-extern void SkXmPhyRead(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 SK_FAR *pVal);
-
-extern void SkXmPhyWrite(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 Val);
-
-extern void SkGmPhyRead(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 SK_FAR *pVal);
-
-extern void SkGmPhyWrite(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 Val);
-
-extern void SkXmClrExactAddr(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int StartNum,
- int StopNum);
-
-extern void SkXmAutoNegLipaXmac(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_U16 IStatus);
-
-extern int SkXmUpdateStats(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port);
-
-extern int SkGmUpdateStats(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port);
-
-extern int SkXmMacStatistic(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port,
- SK_U16 StatAddr,
- SK_U32 SK_FAR *pVal);
-
-extern int SkGmMacStatistic(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port,
- SK_U16 StatAddr,
- SK_U32 SK_FAR *pVal);
-
-extern int SkXmResetCounter(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port);
-
-extern int SkGmResetCounter(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port);
-
-extern int SkXmOverflowStatus(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port,
- SK_U16 IStatus,
- SK_U64 SK_FAR *pStatus);
-
-extern int SkGmOverflowStatus(
- SK_AC *pAC,
- SK_IOC IoC,
- unsigned int Port,
- SK_U16 MacStatus,
- SK_U64 SK_FAR *pStatus);
-
-extern int SkGmCableDiagStatus(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL StartTest);
-
-#ifdef SK_DIAG
-extern void SkGePhyRead(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 *pVal);
-
-extern void SkGePhyWrite(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Addr,
- SK_U16 Val);
-
-extern void SkMacSetRxCmd(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- int Mode);
-extern void SkMacCrcGener(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-extern void SkMacTimeStamp(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-extern void SkXmSendCont(
- SK_AC *pAC,
- SK_IOC IoC,
- int Port,
- SK_BOOL Enable);
-#endif /* SK_DIAG */
-
-#else /* SK_KR_PROTO */
-
-/*
- * public functions in skgeinit.c
- */
-extern void SkGePollTxD();
-extern void SkGeYellowLED();
-extern int SkGeCfgSync();
-extern void SkGeLoadLnkSyncCnt();
-extern void SkGeStopPort();
-extern int SkGeInit();
-extern void SkGeDeInit();
-extern int SkGeInitPort();
-extern void SkGeXmitLED();
-extern int SkGeInitAssignRamToQueues();
-
-/*
- * public functions in skxmac2.c
- */
-extern void SkMacRxTxDisable();
-extern void SkMacSoftRst();
-extern void SkMacHardRst();
-extern void SkMacInitPhy();
-extern int SkMacRxTxEnable();
-extern void SkMacPromiscMode();
-extern void SkMacHashing();
-extern void SkMacIrqDisable();
-extern void SkMacFlushTxFifo();
-extern void SkMacIrq();
-extern int SkMacAutoNegDone();
-extern void SkMacAutoNegLipaPhy();
-extern void SkXmInitMac();
-extern void SkXmPhyRead();
-extern void SkXmPhyWrite();
-extern void SkGmInitMac();
-extern void SkGmPhyRead();
-extern void SkGmPhyWrite();
-extern void SkXmClrExactAddr();
-extern void SkXmAutoNegLipaXmac();
-extern int SkXmUpdateStats();
-extern int SkGmUpdateStats();
-extern int SkXmMacStatistic();
-extern int SkGmMacStatistic();
-extern int SkXmResetCounter();
-extern int SkGmResetCounter();
-extern int SkXmOverflowStatus();
-extern int SkGmOverflowStatus();
-extern int SkGmCableDiagStatus();
-
-#ifdef SK_DIAG
-extern void SkGePhyRead();
-extern void SkGePhyWrite();
-extern void SkMacSetRxCmd();
-extern void SkMacCrcGener();
-extern void SkMacTimeStamp();
-extern void SkXmSendCont();
-#endif /* SK_DIAG */
-
-#endif /* SK_KR_PROTO */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_SKGEINIT_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h
deleted file mode 100644
index ddd304f1a48..00000000000
--- a/drivers/net/sk98lin/h/skgepnm2.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*****************************************************************************
- *
- * Name: skgepnm2.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.36 $
- * Date: $Date: 2003/05/23 12:45:13 $
- * Purpose: Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNM2_H_
-#define _SKGEPNM2_H_
-
-/*
- * General definitions
- */
-#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */
-#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */
-
-#define SK_PNMI_BUS_PCI 1 /* PCI bus*/
-
-/*
- * Actions
- */
-#define SK_PNMI_ACT_IDLE 1
-#define SK_PNMI_ACT_RESET 2
-#define SK_PNMI_ACT_SELFTEST 3
-#define SK_PNMI_ACT_RESETCNT 4
-
-/*
- * VPD releated defines
- */
-
-#define SK_PNMI_VPD_RW 1
-#define SK_PNMI_VPD_RO 2
-
-#define SK_PNMI_VPD_OK 0
-#define SK_PNMI_VPD_NOTFOUND 1
-#define SK_PNMI_VPD_CUT 2
-#define SK_PNMI_VPD_TIMEOUT 3
-#define SK_PNMI_VPD_FULL 4
-#define SK_PNMI_VPD_NOWRITE 5
-#define SK_PNMI_VPD_FATAL 6
-
-#define SK_PNMI_VPD_IGNORE 0
-#define SK_PNMI_VPD_CREATE 1
-#define SK_PNMI_VPD_DELETE 2
-
-
-/*
- * RLMT related defines
- */
-#define SK_PNMI_DEF_RLMT_CHG_THRES 240 /* 4 changes per minute */
-
-
-/*
- * VCT internal status values
- */
-#define SK_PNMI_VCT_PENDING 32
-#define SK_PNMI_VCT_TEST_DONE 64
-#define SK_PNMI_VCT_LINK 128
-
-/*
- * Internal table definitions
- */
-#define SK_PNMI_GET 0
-#define SK_PNMI_PRESET 1
-#define SK_PNMI_SET 2
-
-#define SK_PNMI_RO 0
-#define SK_PNMI_RW 1
-#define SK_PNMI_WO 2
-
-typedef struct s_OidTabEntry {
- SK_U32 Id;
- SK_U32 InstanceNo;
- unsigned int StructSize;
- unsigned int Offset;
- int Access;
- int (* Func)(SK_AC *pAc, SK_IOC pIo, int action,
- SK_U32 Id, char* pBuf, unsigned int* pLen,
- SK_U32 Instance, unsigned int TableIndex,
- SK_U32 NetNumber);
- SK_U16 Param;
-} SK_PNMI_TAB_ENTRY;
-
-
-/*
- * Trap lengths
- */
-#define SK_PNMI_TRAP_SIMPLE_LEN 17
-#define SK_PNMI_TRAP_SENSOR_LEN_BASE 46
-#define SK_PNMI_TRAP_RLMT_CHANGE_LEN 23
-#define SK_PNMI_TRAP_RLMT_PORT_LEN 23
-
-/*
- * Number of MAC types supported
- */
-#define SK_PNMI_MAC_TYPES (SK_MAC_GMAC + 1)
-
-/*
- * MAC statistic data list (overall set for MAC types used)
- */
-enum SK_MACSTATS {
- SK_PNMI_HTX = 0,
- SK_PNMI_HTX_OCTET,
- SK_PNMI_HTX_OCTETHIGH = SK_PNMI_HTX_OCTET,
- SK_PNMI_HTX_OCTETLOW,
- SK_PNMI_HTX_BROADCAST,
- SK_PNMI_HTX_MULTICAST,
- SK_PNMI_HTX_UNICAST,
- SK_PNMI_HTX_BURST,
- SK_PNMI_HTX_PMACC,
- SK_PNMI_HTX_MACC,
- SK_PNMI_HTX_COL,
- SK_PNMI_HTX_SINGLE_COL,
- SK_PNMI_HTX_MULTI_COL,
- SK_PNMI_HTX_EXCESS_COL,
- SK_PNMI_HTX_LATE_COL,
- SK_PNMI_HTX_DEFFERAL,
- SK_PNMI_HTX_EXCESS_DEF,
- SK_PNMI_HTX_UNDERRUN,
- SK_PNMI_HTX_CARRIER,
- SK_PNMI_HTX_UTILUNDER,
- SK_PNMI_HTX_UTILOVER,
- SK_PNMI_HTX_64,
- SK_PNMI_HTX_127,
- SK_PNMI_HTX_255,
- SK_PNMI_HTX_511,
- SK_PNMI_HTX_1023,
- SK_PNMI_HTX_MAX,
- SK_PNMI_HTX_LONGFRAMES,
- SK_PNMI_HTX_SYNC,
- SK_PNMI_HTX_SYNC_OCTET,
- SK_PNMI_HTX_RESERVED,
-
- SK_PNMI_HRX,
- SK_PNMI_HRX_OCTET,
- SK_PNMI_HRX_OCTETHIGH = SK_PNMI_HRX_OCTET,
- SK_PNMI_HRX_OCTETLOW,
- SK_PNMI_HRX_BADOCTET,
- SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET,
- SK_PNMI_HRX_BADOCTETLOW,
- SK_PNMI_HRX_BROADCAST,
- SK_PNMI_HRX_MULTICAST,
- SK_PNMI_HRX_UNICAST,
- SK_PNMI_HRX_PMACC,
- SK_PNMI_HRX_MACC,
- SK_PNMI_HRX_PMACC_ERR,
- SK_PNMI_HRX_MACC_UNKWN,
- SK_PNMI_HRX_BURST,
- SK_PNMI_HRX_MISSED,
- SK_PNMI_HRX_FRAMING,
- SK_PNMI_HRX_UNDERSIZE,
- SK_PNMI_HRX_OVERFLOW,
- SK_PNMI_HRX_JABBER,
- SK_PNMI_HRX_CARRIER,
- SK_PNMI_HRX_IRLENGTH,
- SK_PNMI_HRX_SYMBOL,
- SK_PNMI_HRX_SHORTS,
- SK_PNMI_HRX_RUNT,
- SK_PNMI_HRX_TOO_LONG,
- SK_PNMI_HRX_FCS,
- SK_PNMI_HRX_CEXT,
- SK_PNMI_HRX_UTILUNDER,
- SK_PNMI_HRX_UTILOVER,
- SK_PNMI_HRX_64,
- SK_PNMI_HRX_127,
- SK_PNMI_HRX_255,
- SK_PNMI_HRX_511,
- SK_PNMI_HRX_1023,
- SK_PNMI_HRX_MAX,
- SK_PNMI_HRX_LONGFRAMES,
-
- SK_PNMI_HRX_RESERVED,
-
- SK_PNMI_MAX_IDX /* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */
-};
-
-/*
- * MAC specific data
- */
-typedef struct s_PnmiStatAddr {
- SK_U16 Reg; /* MAC register containing the value */
- SK_BOOL GetOffset; /* TRUE: Offset managed by PNMI (call GetStatVal())*/
-} SK_PNMI_STATADDR;
-
-
-/*
- * SK_PNMI_STRUCT_DATA copy offset evaluation macros
- */
-#define SK_PNMI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_MAI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e))
-#define SK_PNMI_VPD_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e))
-#define SK_PNMI_SEN_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e))
-#define SK_PNMI_CHK_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e))
-#define SK_PNMI_STA_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e))
-#define SK_PNMI_CNF_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e))
-#define SK_PNMI_RLM_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e))
-#define SK_PNMI_MON_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e))
-#define SK_PNMI_TRP_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e))
-
-#define SK_PNMI_SET_STAT(b,s,o) {SK_U32 Val32; char *pVal; \
- Val32 = (s); \
- pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
- &(((SK_PNMI_STRUCT_DATA *)0)-> \
- ReturnStatus.ErrorStatus)); \
- SK_PNMI_STORE_U32(pVal, Val32); \
- Val32 = (o); \
- pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \
- &(((SK_PNMI_STRUCT_DATA *)0)-> \
- ReturnStatus.ErrorOffset)); \
- SK_PNMI_STORE_U32(pVal, Val32);}
-
-/*
- * Time macros
- */
-#ifndef SK_PNMI_HUNDREDS_SEC
-#if SK_TICKS_PER_SEC == 100
-#define SK_PNMI_HUNDREDS_SEC(t) (t)
-#else
-#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC))
-#endif /* !SK_TICKS_PER_SEC */
-#endif /* !SK_PNMI_HUNDREDS_SEC */
-
-/*
- * Macros to work around alignment problems
- */
-#ifndef SK_PNMI_STORE_U16
-#define SK_PNMI_STORE_U16(p,v) {*(char *)(p) = *((char *)&(v)); \
- *((char *)(p) + 1) = \
- *(((char *)&(v)) + 1);}
-#endif
-
-#ifndef SK_PNMI_STORE_U32
-#define SK_PNMI_STORE_U32(p,v) {*(char *)(p) = *((char *)&(v)); \
- *((char *)(p) + 1) = \
- *(((char *)&(v)) + 1); \
- *((char *)(p) + 2) = \
- *(((char *)&(v)) + 2); \
- *((char *)(p) + 3) = \
- *(((char *)&(v)) + 3);}
-#endif
-
-#ifndef SK_PNMI_STORE_U64
-#define SK_PNMI_STORE_U64(p,v) {*(char *)(p) = *((char *)&(v)); \
- *((char *)(p) + 1) = \
- *(((char *)&(v)) + 1); \
- *((char *)(p) + 2) = \
- *(((char *)&(v)) + 2); \
- *((char *)(p) + 3) = \
- *(((char *)&(v)) + 3); \
- *((char *)(p) + 4) = \
- *(((char *)&(v)) + 4); \
- *((char *)(p) + 5) = \
- *(((char *)&(v)) + 5); \
- *((char *)(p) + 6) = \
- *(((char *)&(v)) + 6); \
- *((char *)(p) + 7) = \
- *(((char *)&(v)) + 7);}
-#endif
-
-#ifndef SK_PNMI_READ_U16
-#define SK_PNMI_READ_U16(p,v) {*((char *)&(v)) = *(char *)(p); \
- *(((char *)&(v)) + 1) = \
- *((char *)(p) + 1);}
-#endif
-
-#ifndef SK_PNMI_READ_U32
-#define SK_PNMI_READ_U32(p,v) {*((char *)&(v)) = *(char *)(p); \
- *(((char *)&(v)) + 1) = \
- *((char *)(p) + 1); \
- *(((char *)&(v)) + 2) = \
- *((char *)(p) + 2); \
- *(((char *)&(v)) + 3) = \
- *((char *)(p) + 3);}
-#endif
-
-#ifndef SK_PNMI_READ_U64
-#define SK_PNMI_READ_U64(p,v) {*((char *)&(v)) = *(char *)(p); \
- *(((char *)&(v)) + 1) = \
- *((char *)(p) + 1); \
- *(((char *)&(v)) + 2) = \
- *((char *)(p) + 2); \
- *(((char *)&(v)) + 3) = \
- *((char *)(p) + 3); \
- *(((char *)&(v)) + 4) = \
- *((char *)(p) + 4); \
- *(((char *)&(v)) + 5) = \
- *((char *)(p) + 5); \
- *(((char *)&(v)) + 6) = \
- *((char *)(p) + 6); \
- *(((char *)&(v)) + 7) = \
- *((char *)(p) + 7);}
-#endif
-
-/*
- * Macros for Debug
- */
-#ifdef DEBUG
-
-#define SK_PNMI_CHECKFLAGS(vSt) {if (pAC->Pnmi.MacUpdatedFlag > 0 || \
- pAC->Pnmi.RlmtUpdatedFlag > 0 || \
- pAC->Pnmi.SirqUpdatedFlag > 0) { \
- SK_DBG_MSG(pAC, \
- SK_DBGMOD_PNMI, \
- SK_DBGCAT_CTRL, \
- ("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \
- vSt, \
- pAC->Pnmi.MacUpdatedFlag, \
- pAC->Pnmi.RlmtUpdatedFlag, \
- pAC->Pnmi.SirqUpdatedFlag))}}
-
-#else /* !DEBUG */
-
-#define SK_PNMI_CHECKFLAGS(vSt) /* Nothing */
-
-#endif /* !DEBUG */
-
-#endif /* _SKGEPNM2_H_ */
diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h
deleted file mode 100644
index 1ed214ccb25..00000000000
--- a/drivers/net/sk98lin/h/skgepnmi.h
+++ /dev/null
@@ -1,962 +0,0 @@
-/*****************************************************************************
- *
- * Name: skgepnmi.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.62 $
- * Date: $Date: 2003/08/15 12:31:52 $
- * Purpose: Defines for Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _SKGEPNMI_H_
-#define _SKGEPNMI_H_
-
-/*
- * Include dependencies
- */
-#include "h/sktypes.h"
-#include "h/skerror.h"
-#include "h/sktimer.h"
-#include "h/ski2c.h"
-#include "h/skaddr.h"
-#include "h/skrlmt.h"
-#include "h/skvpd.h"
-
-/*
- * Management Database Version
- */
-#define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */
-
-
-/*
- * Event definitions
- */
-#define SK_PNMI_EVT_SIRQ_OVERFLOW 1 /* Counter overflow */
-#define SK_PNMI_EVT_SEN_WAR_LOW 2 /* Lower war thres exceeded */
-#define SK_PNMI_EVT_SEN_WAR_UPP 3 /* Upper war thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_LOW 4 /* Lower err thres exceeded */
-#define SK_PNMI_EVT_SEN_ERR_UPP 5 /* Upper err thres exceeded */
-#define SK_PNMI_EVT_CHG_EST_TIMER 6 /* Timer event for RLMT Chg */
-#define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */
-#define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */
-#define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */
-
-#define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */
-#define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */
-#define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */
-#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */
-#define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */
-#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets
- 1 = single net; 2 = dual net */
-#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */
-
-
-/*
- * Return values
- */
-#define SK_PNMI_ERR_OK 0
-#define SK_PNMI_ERR_GENERAL 1
-#define SK_PNMI_ERR_TOO_SHORT 2
-#define SK_PNMI_ERR_BAD_VALUE 3
-#define SK_PNMI_ERR_READ_ONLY 4
-#define SK_PNMI_ERR_UNKNOWN_OID 5
-#define SK_PNMI_ERR_UNKNOWN_INST 6
-#define SK_PNMI_ERR_UNKNOWN_NET 7
-#define SK_PNMI_ERR_NOT_SUPPORTED 10
-
-
-/*
- * Return values of driver reset function SK_DRIVER_RESET() and
- * driver event function SK_DRIVER_EVENT()
- */
-#define SK_PNMI_ERR_OK 0
-#define SK_PNMI_ERR_FAIL 1
-
-
-/*
- * Return values of driver test function SK_DRIVER_SELFTEST()
- */
-#define SK_PNMI_TST_UNKNOWN (1 << 0)
-#define SK_PNMI_TST_TRANCEIVER (1 << 1)
-#define SK_PNMI_TST_ASIC (1 << 2)
-#define SK_PNMI_TST_SENSOR (1 << 3)
-#define SK_PNMI_TST_POWERMGMT (1 << 4)
-#define SK_PNMI_TST_PCI (1 << 5)
-#define SK_PNMI_TST_MAC (1 << 6)
-
-
-/*
- * RLMT specific definitions
- */
-#define SK_PNMI_RLMT_STATUS_STANDBY 1
-#define SK_PNMI_RLMT_STATUS_ACTIVE 2
-#define SK_PNMI_RLMT_STATUS_ERROR 3
-
-#define SK_PNMI_RLMT_LSTAT_PHY_DOWN 1
-#define SK_PNMI_RLMT_LSTAT_AUTONEG 2
-#define SK_PNMI_RLMT_LSTAT_LOG_DOWN 3
-#define SK_PNMI_RLMT_LSTAT_LOG_UP 4
-#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5
-
-#define SK_PNMI_RLMT_MODE_CHK_LINK (SK_RLMT_CHECK_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_RX (SK_RLMT_CHECK_LOC_LINK)
-#define SK_PNMI_RLMT_MODE_CHK_SPT (SK_RLMT_CHECK_SEG)
-/* #define SK_PNMI_RLMT_MODE_CHK_EX */
-
-/*
- * OID definition
- */
-#ifndef _NDIS_ /* Check, whether NDIS already included OIDs */
-
-#define OID_GEN_XMIT_OK 0x00020101
-#define OID_GEN_RCV_OK 0x00020102
-#define OID_GEN_XMIT_ERROR 0x00020103
-#define OID_GEN_RCV_ERROR 0x00020104
-#define OID_GEN_RCV_NO_BUFFER 0x00020105
-
-/* #define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 */
-#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
-/* #define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 */
-#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
-/* #define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 */
-#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
-/* #define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 */
-#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
-/* #define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 */
-#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
-/* #define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B */
-#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
-#define OID_GEN_RCV_CRC_ERROR 0x0002020D
-#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
-
-#define OID_802_3_PERMANENT_ADDRESS 0x01010101
-#define OID_802_3_CURRENT_ADDRESS 0x01010102
-/* #define OID_802_3_MULTICAST_LIST 0x01010103 */
-/* #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 */
-/* #define OID_802_3_MAC_OPTIONS 0x01010105 */
-
-#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
-#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
-#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
-#define OID_802_3_XMIT_DEFERRED 0x01020201
-#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
-#define OID_802_3_RCV_OVERRUN 0x01020203
-#define OID_802_3_XMIT_UNDERRUN 0x01020204
-#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
-#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
-
-/*
- * PnP and PM OIDs
- */
-#ifdef SK_POWER_MGMT
-#define OID_PNP_CAPABILITIES 0xFD010100
-#define OID_PNP_SET_POWER 0xFD010101
-#define OID_PNP_QUERY_POWER 0xFD010102
-#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
-#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
-#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
-#endif /* SK_POWER_MGMT */
-
-#endif /* _NDIS_ */
-
-#define OID_SKGE_MDB_VERSION 0xFF010100
-#define OID_SKGE_SUPPORTED_LIST 0xFF010101
-#define OID_SKGE_VPD_FREE_BYTES 0xFF010102
-#define OID_SKGE_VPD_ENTRIES_LIST 0xFF010103
-#define OID_SKGE_VPD_ENTRIES_NUMBER 0xFF010104
-#define OID_SKGE_VPD_KEY 0xFF010105
-#define OID_SKGE_VPD_VALUE 0xFF010106
-#define OID_SKGE_VPD_ACCESS 0xFF010107
-#define OID_SKGE_VPD_ACTION 0xFF010108
-
-#define OID_SKGE_PORT_NUMBER 0xFF010110
-#define OID_SKGE_DEVICE_TYPE 0xFF010111
-#define OID_SKGE_DRIVER_DESCR 0xFF010112
-#define OID_SKGE_DRIVER_VERSION 0xFF010113
-#define OID_SKGE_HW_DESCR 0xFF010114
-#define OID_SKGE_HW_VERSION 0xFF010115
-#define OID_SKGE_CHIPSET 0xFF010116
-#define OID_SKGE_ACTION 0xFF010117
-#define OID_SKGE_RESULT 0xFF010118
-#define OID_SKGE_BUS_TYPE 0xFF010119
-#define OID_SKGE_BUS_SPEED 0xFF01011A
-#define OID_SKGE_BUS_WIDTH 0xFF01011B
-/* 0xFF01011C unused */
-#define OID_SKGE_DIAG_ACTION 0xFF01011D
-#define OID_SKGE_DIAG_RESULT 0xFF01011E
-#define OID_SKGE_MTU 0xFF01011F
-#define OID_SKGE_PHYS_CUR_ADDR 0xFF010120
-#define OID_SKGE_PHYS_FAC_ADDR 0xFF010121
-#define OID_SKGE_PMD 0xFF010122
-#define OID_SKGE_CONNECTOR 0xFF010123
-#define OID_SKGE_LINK_CAP 0xFF010124
-#define OID_SKGE_LINK_MODE 0xFF010125
-#define OID_SKGE_LINK_MODE_STATUS 0xFF010126
-#define OID_SKGE_LINK_STATUS 0xFF010127
-#define OID_SKGE_FLOWCTRL_CAP 0xFF010128
-#define OID_SKGE_FLOWCTRL_MODE 0xFF010129
-#define OID_SKGE_FLOWCTRL_STATUS 0xFF01012A
-#define OID_SKGE_PHY_OPERATION_CAP 0xFF01012B
-#define OID_SKGE_PHY_OPERATION_MODE 0xFF01012C
-#define OID_SKGE_PHY_OPERATION_STATUS 0xFF01012D
-#define OID_SKGE_MULTICAST_LIST 0xFF01012E
-#define OID_SKGE_CURRENT_PACKET_FILTER 0xFF01012F
-
-#define OID_SKGE_TRAP 0xFF010130
-#define OID_SKGE_TRAP_NUMBER 0xFF010131
-
-#define OID_SKGE_RLMT_MODE 0xFF010140
-#define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141
-#define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142
-#define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143
-#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160
-
-#define OID_SKGE_SPEED_CAP 0xFF010170
-#define OID_SKGE_SPEED_MODE 0xFF010171
-#define OID_SKGE_SPEED_STATUS 0xFF010172
-
-#define OID_SKGE_BOARDLEVEL 0xFF010180
-
-#define OID_SKGE_SENSOR_NUMBER 0xFF020100
-#define OID_SKGE_SENSOR_INDEX 0xFF020101
-#define OID_SKGE_SENSOR_DESCR 0xFF020102
-#define OID_SKGE_SENSOR_TYPE 0xFF020103
-#define OID_SKGE_SENSOR_VALUE 0xFF020104
-#define OID_SKGE_SENSOR_WAR_THRES_LOW 0xFF020105
-#define OID_SKGE_SENSOR_WAR_THRES_UPP 0xFF020106
-#define OID_SKGE_SENSOR_ERR_THRES_LOW 0xFF020107
-#define OID_SKGE_SENSOR_ERR_THRES_UPP 0xFF020108
-#define OID_SKGE_SENSOR_STATUS 0xFF020109
-#define OID_SKGE_SENSOR_WAR_CTS 0xFF02010A
-#define OID_SKGE_SENSOR_ERR_CTS 0xFF02010B
-#define OID_SKGE_SENSOR_WAR_TIME 0xFF02010C
-#define OID_SKGE_SENSOR_ERR_TIME 0xFF02010D
-
-#define OID_SKGE_CHKSM_NUMBER 0xFF020110
-#define OID_SKGE_CHKSM_RX_OK_CTS 0xFF020111
-#define OID_SKGE_CHKSM_RX_UNABLE_CTS 0xFF020112
-#define OID_SKGE_CHKSM_RX_ERR_CTS 0xFF020113
-#define OID_SKGE_CHKSM_TX_OK_CTS 0xFF020114
-#define OID_SKGE_CHKSM_TX_UNABLE_CTS 0xFF020115
-
-#define OID_SKGE_STAT_TX 0xFF020120
-#define OID_SKGE_STAT_TX_OCTETS 0xFF020121
-#define OID_SKGE_STAT_TX_BROADCAST 0xFF020122
-#define OID_SKGE_STAT_TX_MULTICAST 0xFF020123
-#define OID_SKGE_STAT_TX_UNICAST 0xFF020124
-#define OID_SKGE_STAT_TX_LONGFRAMES 0xFF020125
-#define OID_SKGE_STAT_TX_BURST 0xFF020126
-#define OID_SKGE_STAT_TX_PFLOWC 0xFF020127
-#define OID_SKGE_STAT_TX_FLOWC 0xFF020128
-#define OID_SKGE_STAT_TX_SINGLE_COL 0xFF020129
-#define OID_SKGE_STAT_TX_MULTI_COL 0xFF02012A
-#define OID_SKGE_STAT_TX_EXCESS_COL 0xFF02012B
-#define OID_SKGE_STAT_TX_LATE_COL 0xFF02012C
-#define OID_SKGE_STAT_TX_DEFFERAL 0xFF02012D
-#define OID_SKGE_STAT_TX_EXCESS_DEF 0xFF02012E
-#define OID_SKGE_STAT_TX_UNDERRUN 0xFF02012F
-#define OID_SKGE_STAT_TX_CARRIER 0xFF020130
-/* #define OID_SKGE_STAT_TX_UTIL 0xFF020131 */
-#define OID_SKGE_STAT_TX_64 0xFF020132
-#define OID_SKGE_STAT_TX_127 0xFF020133
-#define OID_SKGE_STAT_TX_255 0xFF020134
-#define OID_SKGE_STAT_TX_511 0xFF020135
-#define OID_SKGE_STAT_TX_1023 0xFF020136
-#define OID_SKGE_STAT_TX_MAX 0xFF020137
-#define OID_SKGE_STAT_TX_SYNC 0xFF020138
-#define OID_SKGE_STAT_TX_SYNC_OCTETS 0xFF020139
-#define OID_SKGE_STAT_RX 0xFF02013A
-#define OID_SKGE_STAT_RX_OCTETS 0xFF02013B
-#define OID_SKGE_STAT_RX_BROADCAST 0xFF02013C
-#define OID_SKGE_STAT_RX_MULTICAST 0xFF02013D
-#define OID_SKGE_STAT_RX_UNICAST 0xFF02013E
-#define OID_SKGE_STAT_RX_PFLOWC 0xFF02013F
-#define OID_SKGE_STAT_RX_FLOWC 0xFF020140
-#define OID_SKGE_STAT_RX_PFLOWC_ERR 0xFF020141
-#define OID_SKGE_STAT_RX_FLOWC_UNKWN 0xFF020142
-#define OID_SKGE_STAT_RX_BURST 0xFF020143
-#define OID_SKGE_STAT_RX_MISSED 0xFF020144
-#define OID_SKGE_STAT_RX_FRAMING 0xFF020145
-#define OID_SKGE_STAT_RX_OVERFLOW 0xFF020146
-#define OID_SKGE_STAT_RX_JABBER 0xFF020147
-#define OID_SKGE_STAT_RX_CARRIER 0xFF020148
-#define OID_SKGE_STAT_RX_IR_LENGTH 0xFF020149
-#define OID_SKGE_STAT_RX_SYMBOL 0xFF02014A
-#define OID_SKGE_STAT_RX_SHORTS 0xFF02014B
-#define OID_SKGE_STAT_RX_RUNT 0xFF02014C
-#define OID_SKGE_STAT_RX_CEXT 0xFF02014D
-#define OID_SKGE_STAT_RX_TOO_LONG 0xFF02014E
-#define OID_SKGE_STAT_RX_FCS 0xFF02014F
-/* #define OID_SKGE_STAT_RX_UTIL 0xFF020150 */
-#define OID_SKGE_STAT_RX_64 0xFF020151
-#define OID_SKGE_STAT_RX_127 0xFF020152
-#define OID_SKGE_STAT_RX_255 0xFF020153
-#define OID_SKGE_STAT_RX_511 0xFF020154
-#define OID_SKGE_STAT_RX_1023 0xFF020155
-#define OID_SKGE_STAT_RX_MAX 0xFF020156
-#define OID_SKGE_STAT_RX_LONGFRAMES 0xFF020157
-
-#define OID_SKGE_RLMT_CHANGE_CTS 0xFF020160
-#define OID_SKGE_RLMT_CHANGE_TIME 0xFF020161
-#define OID_SKGE_RLMT_CHANGE_ESTIM 0xFF020162
-#define OID_SKGE_RLMT_CHANGE_THRES 0xFF020163
-
-#define OID_SKGE_RLMT_PORT_INDEX 0xFF020164
-#define OID_SKGE_RLMT_STATUS 0xFF020165
-#define OID_SKGE_RLMT_TX_HELLO_CTS 0xFF020166
-#define OID_SKGE_RLMT_RX_HELLO_CTS 0xFF020167
-#define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168
-#define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169
-
-#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150
-#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151
-#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152
-#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153
-#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154
-#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155
-
-#define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170
-#define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171
-#define OID_SKGE_TX_RETRY 0xFF020172
-#define OID_SKGE_RX_INTR_CTS 0xFF020173
-#define OID_SKGE_TX_INTR_CTS 0xFF020174
-#define OID_SKGE_RX_NO_BUF_CTS 0xFF020175
-#define OID_SKGE_TX_NO_BUF_CTS 0xFF020176
-#define OID_SKGE_TX_USED_DESCR_NO 0xFF020177
-#define OID_SKGE_RX_DELIVERED_CTS 0xFF020178
-#define OID_SKGE_RX_OCTETS_DELIV_CTS 0xFF020179
-#define OID_SKGE_RX_HW_ERROR_CTS 0xFF02017A
-#define OID_SKGE_TX_HW_ERROR_CTS 0xFF02017B
-#define OID_SKGE_IN_ERRORS_CTS 0xFF02017C
-#define OID_SKGE_OUT_ERROR_CTS 0xFF02017D
-#define OID_SKGE_ERR_RECOVERY_CTS 0xFF02017E
-#define OID_SKGE_SYSUPTIME 0xFF02017F
-
-#define OID_SKGE_ALL_DATA 0xFF020190
-
-/* Defines for VCT. */
-#define OID_SKGE_VCT_GET 0xFF020200
-#define OID_SKGE_VCT_SET 0xFF020201
-#define OID_SKGE_VCT_STATUS 0xFF020202
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define OID_SKGE_DIAG_MODE 0xFF020204
-#endif /* SK_DIAG_SUPPORT */
-
-/* New OIDs */
-#define OID_SKGE_DRIVER_RELDATE 0xFF020210
-#define OID_SKGE_DRIVER_FILENAME 0xFF020211
-#define OID_SKGE_CHIPID 0xFF020212
-#define OID_SKGE_RAMSIZE 0xFF020213
-#define OID_SKGE_VAUXAVAIL 0xFF020214
-#define OID_SKGE_PHY_TYPE 0xFF020215
-#define OID_SKGE_PHY_LP_MODE 0xFF020216
-
-/* VCT struct to store a backup copy of VCT data after a port reset. */
-typedef struct s_PnmiVct {
- SK_U8 VctStatus;
- SK_U8 PCableLen;
- SK_U32 PMdiPairLen[4];
- SK_U8 PMdiPairSts[4];
-} SK_PNMI_VCT;
-
-
-/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
-#define SK_PNMI_VCT_NONE 0
-#define SK_PNMI_VCT_OLD_VCT_DATA 1
-#define SK_PNMI_VCT_NEW_VCT_DATA 2
-#define SK_PNMI_VCT_OLD_DSP_DATA 4
-#define SK_PNMI_VCT_NEW_DSP_DATA 8
-#define SK_PNMI_VCT_RUNNING 16
-
-
-/* VCT cable test status. */
-#define SK_PNMI_VCT_NORMAL_CABLE 0
-#define SK_PNMI_VCT_SHORT_CABLE 1
-#define SK_PNMI_VCT_OPEN_CABLE 2
-#define SK_PNMI_VCT_TEST_FAIL 3
-#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4
-
-#define OID_SKGE_TRAP_SEN_WAR_LOW 500
-#define OID_SKGE_TRAP_SEN_WAR_UPP 501
-#define OID_SKGE_TRAP_SEN_ERR_LOW 502
-#define OID_SKGE_TRAP_SEN_ERR_UPP 503
-#define OID_SKGE_TRAP_RLMT_CHANGE_THRES 520
-#define OID_SKGE_TRAP_RLMT_CHANGE_PORT 521
-#define OID_SKGE_TRAP_RLMT_PORT_DOWN 522
-#define OID_SKGE_TRAP_RLMT_PORT_UP 523
-#define OID_SKGE_TRAP_RLMT_SEGMENTATION 524
-
-#ifdef SK_DIAG_SUPPORT
-/* Defines for driver DIAG mode. */
-#define SK_DIAG_ATTACHED 2
-#define SK_DIAG_RUNNING 1
-#define SK_DIAG_IDLE 0
-#endif /* SK_DIAG_SUPPORT */
-
-/*
- * Generic PNMI IOCTL subcommand definitions.
- */
-#define SK_GET_SINGLE_VAR 1
-#define SK_SET_SINGLE_VAR 2
-#define SK_PRESET_SINGLE_VAR 3
-#define SK_GET_FULL_MIB 4
-#define SK_SET_FULL_MIB 5
-#define SK_PRESET_FULL_MIB 6
-
-
-/*
- * Define error numbers and messages for syslog
- */
-#define SK_PNMI_ERR001 (SK_ERRBASE_PNMI + 1)
-#define SK_PNMI_ERR001MSG "SkPnmiGetStruct: Unknown OID"
-#define SK_PNMI_ERR002 (SK_ERRBASE_PNMI + 2)
-#define SK_PNMI_ERR002MSG "SkPnmiGetStruct: Cannot read VPD keys"
-#define SK_PNMI_ERR003 (SK_ERRBASE_PNMI + 3)
-#define SK_PNMI_ERR003MSG "OidStruct: Called with wrong OID"
-#define SK_PNMI_ERR004 (SK_ERRBASE_PNMI + 4)
-#define SK_PNMI_ERR004MSG "OidStruct: Called with wrong action"
-#define SK_PNMI_ERR005 (SK_ERRBASE_PNMI + 5)
-#define SK_PNMI_ERR005MSG "Perform: Cannot reset driver"
-#define SK_PNMI_ERR006 (SK_ERRBASE_PNMI + 6)
-#define SK_PNMI_ERR006MSG "Perform: Unknown OID action command"
-#define SK_PNMI_ERR007 (SK_ERRBASE_PNMI + 7)
-#define SK_PNMI_ERR007MSG "General: Driver description not initialized"
-#define SK_PNMI_ERR008 (SK_ERRBASE_PNMI + 8)
-#define SK_PNMI_ERR008MSG "Addr: Tried to get unknown OID"
-#define SK_PNMI_ERR009 (SK_ERRBASE_PNMI + 9)
-#define SK_PNMI_ERR009MSG "Addr: Unknown OID"
-#define SK_PNMI_ERR010 (SK_ERRBASE_PNMI + 10)
-#define SK_PNMI_ERR010MSG "CsumStat: Unknown OID"
-#define SK_PNMI_ERR011 (SK_ERRBASE_PNMI + 11)
-#define SK_PNMI_ERR011MSG "SensorStat: Sensor descr string too long"
-#define SK_PNMI_ERR012 (SK_ERRBASE_PNMI + 12)
-#define SK_PNMI_ERR012MSG "SensorStat: Unknown OID"
-#define SK_PNMI_ERR013 (SK_ERRBASE_PNMI + 13)
-#define SK_PNMI_ERR013MSG ""
-#define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14)
-#define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys"
-#define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15)
-#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small"
-#define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16)
-#define SK_PNMI_ERR016MSG "Vpd: Key string too long"
-#define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17)
-#define SK_PNMI_ERR017MSG "Vpd: Invalid VPD status pointer"
-#define SK_PNMI_ERR018 (SK_ERRBASE_PNMI + 18)
-#define SK_PNMI_ERR018MSG "Vpd: VPD data not valid"
-#define SK_PNMI_ERR019 (SK_ERRBASE_PNMI + 19)
-#define SK_PNMI_ERR019MSG "Vpd: VPD entries list string too long"
-#define SK_PNMI_ERR021 (SK_ERRBASE_PNMI + 21)
-#define SK_PNMI_ERR021MSG "Vpd: VPD data string too long"
-#define SK_PNMI_ERR022 (SK_ERRBASE_PNMI + 22)
-#define SK_PNMI_ERR022MSG "Vpd: VPD data string too long should be errored before"
-#define SK_PNMI_ERR023 (SK_ERRBASE_PNMI + 23)
-#define SK_PNMI_ERR023MSG "Vpd: Unknown OID in get action"
-#define SK_PNMI_ERR024 (SK_ERRBASE_PNMI + 24)
-#define SK_PNMI_ERR024MSG "Vpd: Unknown OID in preset/set action"
-#define SK_PNMI_ERR025 (SK_ERRBASE_PNMI + 25)
-#define SK_PNMI_ERR025MSG "Vpd: Cannot write VPD after modify entry"
-#define SK_PNMI_ERR026 (SK_ERRBASE_PNMI + 26)
-#define SK_PNMI_ERR026MSG "Vpd: Cannot update VPD"
-#define SK_PNMI_ERR027 (SK_ERRBASE_PNMI + 27)
-#define SK_PNMI_ERR027MSG "Vpd: Cannot delete VPD entry"
-#define SK_PNMI_ERR028 (SK_ERRBASE_PNMI + 28)
-#define SK_PNMI_ERR028MSG "Vpd: Cannot update VPD after delete entry"
-#define SK_PNMI_ERR029 (SK_ERRBASE_PNMI + 29)
-#define SK_PNMI_ERR029MSG "General: Driver description string too long"
-#define SK_PNMI_ERR030 (SK_ERRBASE_PNMI + 30)
-#define SK_PNMI_ERR030MSG "General: Driver version not initialized"
-#define SK_PNMI_ERR031 (SK_ERRBASE_PNMI + 31)
-#define SK_PNMI_ERR031MSG "General: Driver version string too long"
-#define SK_PNMI_ERR032 (SK_ERRBASE_PNMI + 32)
-#define SK_PNMI_ERR032MSG "General: Cannot read VPD Name for HW descr"
-#define SK_PNMI_ERR033 (SK_ERRBASE_PNMI + 33)
-#define SK_PNMI_ERR033MSG "General: HW description string too long"
-#define SK_PNMI_ERR034 (SK_ERRBASE_PNMI + 34)
-#define SK_PNMI_ERR034MSG "General: Unknown OID"
-#define SK_PNMI_ERR035 (SK_ERRBASE_PNMI + 35)
-#define SK_PNMI_ERR035MSG "Rlmt: Unknown OID"
-#define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36)
-#define SK_PNMI_ERR036MSG ""
-#define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37)
-#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0"
-#define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38)
-#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0"
-#define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39)
-#define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID"
-#define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40)
-#define SK_PNMI_ERR040MSG "PowerManagement: Unknown OID"
-#define SK_PNMI_ERR041 (SK_ERRBASE_PNMI + 41)
-#define SK_PNMI_ERR041MSG "MacPrivateConf: Unknown OID"
-#define SK_PNMI_ERR042 (SK_ERRBASE_PNMI + 42)
-#define SK_PNMI_ERR042MSG "MacPrivateConf: SK_HWEV_SET_ROLE returned not 0"
-#define SK_PNMI_ERR043 (SK_ERRBASE_PNMI + 43)
-#define SK_PNMI_ERR043MSG "MacPrivateConf: SK_HWEV_SET_LMODE returned not 0"
-#define SK_PNMI_ERR044 (SK_ERRBASE_PNMI + 44)
-#define SK_PNMI_ERR044MSG "MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0"
-#define SK_PNMI_ERR045 (SK_ERRBASE_PNMI + 45)
-#define SK_PNMI_ERR045MSG "MacPrivateConf: SK_HWEV_SET_SPEED returned not 0"
-#define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46)
-#define SK_PNMI_ERR046MSG "Monitor: Unknown OID"
-#define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47)
-#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0"
-#define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48)
-#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0"
-#define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49)
-#define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
-#define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50)
-#define SK_PNMI_ERR050MSG "SkPnmiInit: Invalid size of 'StatAddr' table!!"
-#define SK_PNMI_ERR051 (SK_ERRBASE_PNMI + 51)
-#define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious"
-#define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52)
-#define SK_PNMI_ERR052MSG ""
-#define SK_PNMI_ERR053 (SK_ERRBASE_PNMI + 53)
-#define SK_PNMI_ERR053MSG "General: Driver release date not initialized"
-#define SK_PNMI_ERR054 (SK_ERRBASE_PNMI + 54)
-#define SK_PNMI_ERR054MSG "General: Driver release date string too long"
-#define SK_PNMI_ERR055 (SK_ERRBASE_PNMI + 55)
-#define SK_PNMI_ERR055MSG "General: Driver file name not initialized"
-#define SK_PNMI_ERR056 (SK_ERRBASE_PNMI + 56)
-#define SK_PNMI_ERR056MSG "General: Driver file name string too long"
-
-/*
- * Management counter macros called by the driver
- */
-#define SK_PNMI_SET_DRIVER_DESCR(pAC,v) ((pAC)->Pnmi.pDriverDescription = \
- (char *)(v))
-
-#define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \
- (char *)(v))
-
-#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v) ((pAC)->Pnmi.pDriverReleaseDate = \
- (char *)(v))
-
-#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v) ((pAC)->Pnmi.pDriverFileName = \
- (char *)(v))
-
-#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \
- { \
- (pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \
- if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \
- (pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \
- } \
- }
-#define SK_PNMI_CNT_TX_RETRY(pAC,p) (((pAC)->Pnmi.Port[p].TxRetryCts)++)
-#define SK_PNMI_CNT_RX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].RxIntrCts)++)
-#define SK_PNMI_CNT_TX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].TxIntrCts)++)
-#define SK_PNMI_CNT_NO_RX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].RxNoBufCts)++)
-#define SK_PNMI_CNT_NO_TX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].TxNoBufCts)++)
-#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \
- ((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v));
-#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \
- { \
- ((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \
- (pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \
- }
-#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p) (((pAC)->Pnmi.Port[p].ErrRecoveryCts)++);
-
-#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \
- { \
- if ((p) < SK_MAX_MACS) { \
- ((pAC)->Pnmi.Port[p].StatSyncCts)++; \
- (pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \
- } \
- }
-
-#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \
- { \
- if ((p) < SK_MAX_MACS) { \
- ((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \
- } \
- }
-
-#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \
- { \
- if ((p) < SK_MAX_MACS) { \
- ((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \
- } \
- }
-
-#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \
- { \
- if ((p) < SK_MAX_MACS) { \
- ((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \
- } \
- }
-
-/*
- * Conversion Macros
- */
-#define SK_PNMI_PORT_INST2LOG(i) ((unsigned int)(i) - 1)
-#define SK_PNMI_PORT_LOG2INST(l) ((unsigned int)(l) + 1)
-#define SK_PNMI_PORT_PHYS2LOG(p) ((unsigned int)(p) + 1)
-#define SK_PNMI_PORT_LOG2PHYS(pAC,l) ((unsigned int)(l) - 1)
-#define SK_PNMI_PORT_PHYS2INST(pAC,p) \
- (pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2))
-#define SK_PNMI_PORT_INST2PHYS(pAC,i) ((unsigned int)(i) - 2)
-
-/*
- * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct
- */
-#define SK_PNMI_VPD_KEY_SIZE 5
-#define SK_PNMI_VPD_BUFSIZE (VPD_SIZE)
-#define SK_PNMI_VPD_ENTRIES (VPD_SIZE / 4)
-#define SK_PNMI_VPD_DATALEN 128 /* Number of data bytes */
-
-#define SK_PNMI_MULTICAST_LISTLEN 64
-#define SK_PNMI_SENSOR_ENTRIES (SK_MAX_SENSORS)
-#define SK_PNMI_CHECKSUM_ENTRIES 3
-#define SK_PNMI_MAC_ENTRIES (SK_MAX_MACS + 1)
-#define SK_PNMI_MONITOR_ENTRIES 20
-#define SK_PNMI_TRAP_ENTRIES 10
-#define SK_PNMI_TRAPLEN 128
-#define SK_PNMI_STRINGLEN1 80
-#define SK_PNMI_STRINGLEN2 25
-#define SK_PNMI_TRAP_QUEUE_LEN 512
-
-typedef struct s_PnmiVpd {
- char VpdKey[SK_PNMI_VPD_KEY_SIZE];
- char VpdValue[SK_PNMI_VPD_DATALEN];
- SK_U8 VpdAccess;
- SK_U8 VpdAction;
-} SK_PNMI_VPD;
-
-typedef struct s_PnmiSensor {
- SK_U8 SensorIndex;
- char SensorDescr[SK_PNMI_STRINGLEN2];
- SK_U8 SensorType;
- SK_U32 SensorValue;
- SK_U32 SensorWarningThresholdLow;
- SK_U32 SensorWarningThresholdHigh;
- SK_U32 SensorErrorThresholdLow;
- SK_U32 SensorErrorThresholdHigh;
- SK_U8 SensorStatus;
- SK_U64 SensorWarningCts;
- SK_U64 SensorErrorCts;
- SK_U64 SensorWarningTimestamp;
- SK_U64 SensorErrorTimestamp;
-} SK_PNMI_SENSOR;
-
-typedef struct s_PnmiChecksum {
- SK_U64 ChecksumRxOkCts;
- SK_U64 ChecksumRxUnableCts;
- SK_U64 ChecksumRxErrCts;
- SK_U64 ChecksumTxOkCts;
- SK_U64 ChecksumTxUnableCts;
-} SK_PNMI_CHECKSUM;
-
-typedef struct s_PnmiStat {
- SK_U64 StatTxOkCts;
- SK_U64 StatTxOctetsOkCts;
- SK_U64 StatTxBroadcastOkCts;
- SK_U64 StatTxMulticastOkCts;
- SK_U64 StatTxUnicastOkCts;
- SK_U64 StatTxLongFramesCts;
- SK_U64 StatTxBurstCts;
- SK_U64 StatTxPauseMacCtrlCts;
- SK_U64 StatTxMacCtrlCts;
- SK_U64 StatTxSingleCollisionCts;
- SK_U64 StatTxMultipleCollisionCts;
- SK_U64 StatTxExcessiveCollisionCts;
- SK_U64 StatTxLateCollisionCts;
- SK_U64 StatTxDeferralCts;
- SK_U64 StatTxExcessiveDeferralCts;
- SK_U64 StatTxFifoUnderrunCts;
- SK_U64 StatTxCarrierCts;
- SK_U64 Dummy1; /* StatTxUtilization */
- SK_U64 StatTx64Cts;
- SK_U64 StatTx127Cts;
- SK_U64 StatTx255Cts;
- SK_U64 StatTx511Cts;
- SK_U64 StatTx1023Cts;
- SK_U64 StatTxMaxCts;
- SK_U64 StatTxSyncCts;
- SK_U64 StatTxSyncOctetsCts;
- SK_U64 StatRxOkCts;
- SK_U64 StatRxOctetsOkCts;
- SK_U64 StatRxBroadcastOkCts;
- SK_U64 StatRxMulticastOkCts;
- SK_U64 StatRxUnicastOkCts;
- SK_U64 StatRxLongFramesCts;
- SK_U64 StatRxPauseMacCtrlCts;
- SK_U64 StatRxMacCtrlCts;
- SK_U64 StatRxPauseMacCtrlErrorCts;
- SK_U64 StatRxMacCtrlUnknownCts;
- SK_U64 StatRxBurstCts;
- SK_U64 StatRxMissedCts;
- SK_U64 StatRxFramingCts;
- SK_U64 StatRxFifoOverflowCts;
- SK_U64 StatRxJabberCts;
- SK_U64 StatRxCarrierCts;
- SK_U64 StatRxIRLengthCts;
- SK_U64 StatRxSymbolCts;
- SK_U64 StatRxShortsCts;
- SK_U64 StatRxRuntCts;
- SK_U64 StatRxCextCts;
- SK_U64 StatRxTooLongCts;
- SK_U64 StatRxFcsCts;
- SK_U64 Dummy2; /* StatRxUtilization */
- SK_U64 StatRx64Cts;
- SK_U64 StatRx127Cts;
- SK_U64 StatRx255Cts;
- SK_U64 StatRx511Cts;
- SK_U64 StatRx1023Cts;
- SK_U64 StatRxMaxCts;
-} SK_PNMI_STAT;
-
-typedef struct s_PnmiConf {
- char ConfMacCurrentAddr[6];
- char ConfMacFactoryAddr[6];
- SK_U8 ConfPMD;
- SK_U8 ConfConnector;
- SK_U32 ConfPhyType;
- SK_U32 ConfPhyMode;
- SK_U8 ConfLinkCapability;
- SK_U8 ConfLinkMode;
- SK_U8 ConfLinkModeStatus;
- SK_U8 ConfLinkStatus;
- SK_U8 ConfFlowCtrlCapability;
- SK_U8 ConfFlowCtrlMode;
- SK_U8 ConfFlowCtrlStatus;
- SK_U8 ConfPhyOperationCapability;
- SK_U8 ConfPhyOperationMode;
- SK_U8 ConfPhyOperationStatus;
- SK_U8 ConfSpeedCapability;
- SK_U8 ConfSpeedMode;
- SK_U8 ConfSpeedStatus;
-} SK_PNMI_CONF;
-
-typedef struct s_PnmiRlmt {
- SK_U32 RlmtIndex;
- SK_U32 RlmtStatus;
- SK_U64 RlmtTxHelloCts;
- SK_U64 RlmtRxHelloCts;
- SK_U64 RlmtTxSpHelloReqCts;
- SK_U64 RlmtRxSpHelloCts;
-} SK_PNMI_RLMT;
-
-typedef struct s_PnmiRlmtMonitor {
- SK_U32 RlmtMonitorIndex;
- char RlmtMonitorAddr[6];
- SK_U64 RlmtMonitorErrorCts;
- SK_U64 RlmtMonitorTimestamp;
- SK_U8 RlmtMonitorAdmin;
-} SK_PNMI_RLMT_MONITOR;
-
-typedef struct s_PnmiRequestStatus {
- SK_U32 ErrorStatus;
- SK_U32 ErrorOffset;
-} SK_PNMI_REQUEST_STATUS;
-
-typedef struct s_PnmiStrucData {
- SK_U32 MgmtDBVersion;
- SK_PNMI_REQUEST_STATUS ReturnStatus;
- SK_U32 VpdFreeBytes;
- char VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE];
- SK_U32 VpdEntriesNumber;
- SK_PNMI_VPD Vpd[SK_PNMI_VPD_ENTRIES];
- SK_U32 PortNumber;
- SK_U32 DeviceType;
- char DriverDescr[SK_PNMI_STRINGLEN1];
- char DriverVersion[SK_PNMI_STRINGLEN2];
- char DriverReleaseDate[SK_PNMI_STRINGLEN1];
- char DriverFileName[SK_PNMI_STRINGLEN1];
- char HwDescr[SK_PNMI_STRINGLEN1];
- char HwVersion[SK_PNMI_STRINGLEN2];
- SK_U16 Chipset;
- SK_U32 ChipId;
- SK_U8 VauxAvail;
- SK_U32 RamSize;
- SK_U32 MtuSize;
- SK_U32 Action;
- SK_U32 TestResult;
- SK_U8 BusType;
- SK_U8 BusSpeed;
- SK_U8 BusWidth;
- SK_U8 SensorNumber;
- SK_PNMI_SENSOR Sensor[SK_PNMI_SENSOR_ENTRIES];
- SK_U8 ChecksumNumber;
- SK_PNMI_CHECKSUM Checksum[SK_PNMI_CHECKSUM_ENTRIES];
- SK_PNMI_STAT Stat[SK_PNMI_MAC_ENTRIES];
- SK_PNMI_CONF Conf[SK_PNMI_MAC_ENTRIES];
- SK_U8 RlmtMode;
- SK_U32 RlmtPortNumber;
- SK_U8 RlmtPortActive;
- SK_U8 RlmtPortPreferred;
- SK_U64 RlmtChangeCts;
- SK_U64 RlmtChangeTime;
- SK_U64 RlmtChangeEstimate;
- SK_U64 RlmtChangeThreshold;
- SK_PNMI_RLMT Rlmt[SK_MAX_MACS];
- SK_U32 RlmtMonitorNumber;
- SK_PNMI_RLMT_MONITOR RlmtMonitor[SK_PNMI_MONITOR_ENTRIES];
- SK_U32 TrapNumber;
- SK_U8 Trap[SK_PNMI_TRAP_QUEUE_LEN];
- SK_U64 TxSwQueueLen;
- SK_U64 TxSwQueueMax;
- SK_U64 TxRetryCts;
- SK_U64 RxIntrCts;
- SK_U64 TxIntrCts;
- SK_U64 RxNoBufCts;
- SK_U64 TxNoBufCts;
- SK_U64 TxUsedDescrNo;
- SK_U64 RxDeliveredCts;
- SK_U64 RxOctetsDeliveredCts;
- SK_U64 RxHwErrorsCts;
- SK_U64 TxHwErrorsCts;
- SK_U64 InErrorsCts;
- SK_U64 OutErrorsCts;
- SK_U64 ErrRecoveryCts;
- SK_U64 SysUpTime;
-} SK_PNMI_STRUCT_DATA;
-
-#define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA))
-#define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\
- &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
- /*
- * ReturnStatus field
- * must be located
- * before VpdFreeBytes
- */
-
-/*
- * Various definitions
- */
-#define SK_PNMI_MAX_PROTOS 3
-
-#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum
- * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK
- * for check while init phase 1
- */
-
-/*
- * Estimate data structure
- */
-typedef struct s_PnmiEstimate {
- unsigned int EstValueIndex;
- SK_U64 EstValue[7];
- SK_U64 Estimate;
- SK_TIMER EstTimer;
-} SK_PNMI_ESTIMATE;
-
-
-/*
- * VCT timer data structure
- */
-typedef struct s_VctTimer {
- SK_TIMER VctTimer;
-} SK_PNMI_VCT_TIMER;
-
-
-/*
- * PNMI specific adapter context structure
- */
-typedef struct s_PnmiPort {
- SK_U64 StatSyncCts;
- SK_U64 StatSyncOctetsCts;
- SK_U64 StatRxLongFrameCts;
- SK_U64 StatRxFrameTooLongCts;
- SK_U64 StatRxPMaccErr;
- SK_U64 TxSwQueueLen;
- SK_U64 TxSwQueueMax;
- SK_U64 TxRetryCts;
- SK_U64 RxIntrCts;
- SK_U64 TxIntrCts;
- SK_U64 RxNoBufCts;
- SK_U64 TxNoBufCts;
- SK_U64 TxUsedDescrNo;
- SK_U64 RxDeliveredCts;
- SK_U64 RxOctetsDeliveredCts;
- SK_U64 RxHwErrorsCts;
- SK_U64 TxHwErrorsCts;
- SK_U64 InErrorsCts;
- SK_U64 OutErrorsCts;
- SK_U64 ErrRecoveryCts;
- SK_U64 RxShortZeroMark;
- SK_U64 CounterOffset[SK_PNMI_CNT_NO];
- SK_U32 CounterHigh[SK_PNMI_CNT_NO];
- SK_BOOL ActiveFlag;
- SK_U8 Align[3];
-} SK_PNMI_PORT;
-
-
-typedef struct s_PnmiData {
- SK_PNMI_PORT Port [SK_MAX_MACS];
- SK_PNMI_PORT BufPort [SK_MAX_MACS]; /* 2002-09-13 pweber */
- SK_U64 VirtualCounterOffset[SK_PNMI_CNT_NO];
- SK_U32 TestResult;
- char HwVersion[10];
- SK_U16 Align01;
-
- char *pDriverDescription;
- char *pDriverVersion;
- char *pDriverReleaseDate;
- char *pDriverFileName;
-
- int MacUpdatedFlag;
- int RlmtUpdatedFlag;
- int SirqUpdatedFlag;
-
- SK_U64 RlmtChangeCts;
- SK_U64 RlmtChangeTime;
- SK_PNMI_ESTIMATE RlmtChangeEstimate;
- SK_U64 RlmtChangeThreshold;
-
- SK_U64 StartUpTime;
- SK_U32 DeviceType;
- char PciBusSpeed;
- char PciBusWidth;
- char Chipset;
- char PMD;
- char Connector;
- SK_BOOL DualNetActiveFlag;
- SK_U16 Align02;
-
- char TrapBuf[SK_PNMI_TRAP_QUEUE_LEN];
- unsigned int TrapBufFree;
- unsigned int TrapQueueBeg;
- unsigned int TrapQueueEnd;
- unsigned int TrapBufPad;
- unsigned int TrapUnique;
- SK_U8 VctStatus[SK_MAX_MACS];
- SK_PNMI_VCT VctBackup[SK_MAX_MACS];
- SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS];
-#ifdef SK_DIAG_SUPPORT
- SK_U32 DiagAttached;
-#endif /* SK_DIAG_SUPPORT */
-} SK_PNMI;
-
-
-/*
- * Function prototypes
- */
-extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level);
-extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf,
- unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event,
- SK_EVPARA Param);
-extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
- unsigned int * pLen, SK_U32 NetIndex);
-
-#endif
diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h
deleted file mode 100644
index 3eec6274e41..00000000000
--- a/drivers/net/sk98lin/h/skgesirq.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/******************************************************************************
- *
- * Name: skgesirq.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.30 $
- * Date: $Date: 2003/07/04 12:34:13 $
- * Purpose: SK specific Gigabit Ethernet special IRQ functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef _INC_SKGESIRQ_H_
-#define _INC_SKGESIRQ_H_
-
-/* Define return codes of SkGePortCheckUp and CheckShort */
-#define SK_HW_PS_NONE 0 /* No action needed */
-#define SK_HW_PS_RESTART 1 /* Restart needed */
-#define SK_HW_PS_LINK 2 /* Link Up actions needed */
-
-/*
- * Define the Event the special IRQ/INI module can handle
- */
-#define SK_HWEV_WATIM 1 /* Timeout for WA Errata #2 XMAC */
-#define SK_HWEV_PORT_START 2 /* Port Start Event by RLMT */
-#define SK_HWEV_PORT_STOP 3 /* Port Stop Event by RLMT */
-#define SK_HWEV_CLEAR_STAT 4 /* Clear Statistics by PNMI */
-#define SK_HWEV_UPDATE_STAT 5 /* Update Statistics by PNMI */
-#define SK_HWEV_SET_LMODE 6 /* Set Link Mode by PNMI */
-#define SK_HWEV_SET_FLOWMODE 7 /* Set Flow Control Mode by PNMI */
-#define SK_HWEV_SET_ROLE 8 /* Set Master/Slave (Role) by PNMI */
-#define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */
-#define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */
-
-#define SK_WA_ACT_TIME (5000000UL) /* 5 sec */
-#define SK_WA_INA_TIME (100000UL) /* 100 msec */
-
-#define SK_HALFDUP_CHK_TIME (10000UL) /* 10 msec */
-
-/*
- * Define the error numbers and messages
- */
-#define SKERR_SIRQ_E001 (SK_ERRBASE_SIRQ+0)
-#define SKERR_SIRQ_E001MSG "Unknown event"
-#define SKERR_SIRQ_E002 (SKERR_SIRQ_E001+1)
-#define SKERR_SIRQ_E002MSG "Packet timeout RX1"
-#define SKERR_SIRQ_E003 (SKERR_SIRQ_E002+1)
-#define SKERR_SIRQ_E003MSG "Packet timeout RX2"
-#define SKERR_SIRQ_E004 (SKERR_SIRQ_E003+1)
-#define SKERR_SIRQ_E004MSG "MAC 1 not correctly initialized"
-#define SKERR_SIRQ_E005 (SKERR_SIRQ_E004+1)
-#define SKERR_SIRQ_E005MSG "MAC 2 not correctly initialized"
-#define SKERR_SIRQ_E006 (SKERR_SIRQ_E005+1)
-#define SKERR_SIRQ_E006MSG "CHECK failure R1"
-#define SKERR_SIRQ_E007 (SKERR_SIRQ_E006+1)
-#define SKERR_SIRQ_E007MSG "CHECK failure R2"
-#define SKERR_SIRQ_E008 (SKERR_SIRQ_E007+1)
-#define SKERR_SIRQ_E008MSG "CHECK failure XS1"
-#define SKERR_SIRQ_E009 (SKERR_SIRQ_E008+1)
-#define SKERR_SIRQ_E009MSG "CHECK failure XA1"
-#define SKERR_SIRQ_E010 (SKERR_SIRQ_E009+1)
-#define SKERR_SIRQ_E010MSG "CHECK failure XS2"
-#define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1)
-#define SKERR_SIRQ_E011MSG "CHECK failure XA2"
-#define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1)
-#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error"
-#define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1)
-#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error"
-#define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1)
-#define SKERR_SIRQ_E014MSG "Parity error on RAM (read)"
-#define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1)
-#define SKERR_SIRQ_E015MSG "Parity error on RAM (write)"
-#define SKERR_SIRQ_E016 (SKERR_SIRQ_E015+1)
-#define SKERR_SIRQ_E016MSG "Parity error MAC 1"
-#define SKERR_SIRQ_E017 (SKERR_SIRQ_E016+1)
-#define SKERR_SIRQ_E017MSG "Parity error MAC 2"
-#define SKERR_SIRQ_E018 (SKERR_SIRQ_E017+1)
-#define SKERR_SIRQ_E018MSG "Parity error RX 1"
-#define SKERR_SIRQ_E019 (SKERR_SIRQ_E018+1)
-#define SKERR_SIRQ_E019MSG "Parity error RX 2"
-#define SKERR_SIRQ_E020 (SKERR_SIRQ_E019+1)
-#define SKERR_SIRQ_E020MSG "MAC transmit FIFO underrun"
-#define SKERR_SIRQ_E021 (SKERR_SIRQ_E020+1)
-#define SKERR_SIRQ_E021MSG "Spurious TWSI interrupt"
-#define SKERR_SIRQ_E022 (SKERR_SIRQ_E021+1)
-#define SKERR_SIRQ_E022MSG "Cable pair swap error"
-#define SKERR_SIRQ_E023 (SKERR_SIRQ_E022+1)
-#define SKERR_SIRQ_E023MSG "Auto-negotiation error"
-#define SKERR_SIRQ_E024 (SKERR_SIRQ_E023+1)
-#define SKERR_SIRQ_E024MSG "FIFO overflow error"
-#define SKERR_SIRQ_E025 (SKERR_SIRQ_E024+1)
-#define SKERR_SIRQ_E025MSG "2 Pair Downshift detected"
-
-extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
-extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
-
-#endif /* _INC_SKGESIRQ_H_ */
diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h
deleted file mode 100644
index 6a63f4a15de..00000000000
--- a/drivers/net/sk98lin/h/ski2c.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/******************************************************************************
- *
- * Name: ski2c.h
- * Project: Gigabit Ethernet Adapters, TWSI-Module
- * Version: $Revision: 1.35 $
- * Date: $Date: 2003/10/20 09:06:30 $
- * Purpose: Defines to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKI2C.H contains all I2C specific defines
- */
-
-#ifndef _SKI2C_H_
-#define _SKI2C_H_
-
-typedef struct s_Sensor SK_SENSOR;
-
-#include "h/skgei2c.h"
-
-/*
- * Define the I2C events.
- */
-#define SK_I2CEV_IRQ 1 /* IRQ happened Event */
-#define SK_I2CEV_TIM 2 /* Timeout event */
-#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */
-
-/*
- * Define READ and WRITE Constants.
- */
-#define I2C_READ 0
-#define I2C_WRITE 1
-#define I2C_BURST 1
-#define I2C_SINGLE 0
-
-#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0)
-#define SKERR_I2C_E001MSG "Sensor index unknown"
-#define SKERR_I2C_E002 (SKERR_I2C_E001+1)
-#define SKERR_I2C_E002MSG "TWSI: transfer does not complete"
-#define SKERR_I2C_E003 (SKERR_I2C_E002+1)
-#define SKERR_I2C_E003MSG "LM80: NAK on device send"
-#define SKERR_I2C_E004 (SKERR_I2C_E003+1)
-#define SKERR_I2C_E004MSG "LM80: NAK on register send"
-#define SKERR_I2C_E005 (SKERR_I2C_E004+1)
-#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send"
-#define SKERR_I2C_E006 (SKERR_I2C_E005+1)
-#define SKERR_I2C_E006MSG "Unknown event"
-#define SKERR_I2C_E007 (SKERR_I2C_E006+1)
-#define SKERR_I2C_E007MSG "LM80 read out of state"
-#define SKERR_I2C_E008 (SKERR_I2C_E007+1)
-#define SKERR_I2C_E008MSG "Unexpected sensor read completed"
-#define SKERR_I2C_E009 (SKERR_I2C_E008+1)
-#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range"
-#define SKERR_I2C_E010 (SKERR_I2C_E009+1)
-#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range"
-#define SKERR_I2C_E011 (SKERR_I2C_E010+1)
-#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range"
-#define SKERR_I2C_E012 (SKERR_I2C_E011+1)
-#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range"
-#define SKERR_I2C_E013 (SKERR_I2C_E012+1)
-#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor"
-#define SKERR_I2C_E014 (SKERR_I2C_E013+1)
-#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range"
-#define SKERR_I2C_E015 (SKERR_I2C_E014+1)
-#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range"
-#define SKERR_I2C_E016 (SKERR_I2C_E015+1)
-#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete"
-
-/*
- * Define Timeout values
- */
-#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */
-#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */
-#define SK_I2C_TIM_WATCH 1000000L /* 1 second */
-
-/*
- * Define trap and error log hold times
- */
-#ifndef SK_SEN_ERR_TR_HOLD
-#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC)
-#endif
-#ifndef SK_SEN_ERR_LOG_HOLD
-#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC)
-#endif
-#ifndef SK_SEN_WARN_TR_HOLD
-#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC)
-#endif
-#ifndef SK_SEN_WARN_LOG_HOLD
-#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC)
-#endif
-
-/*
- * Defines for SenType
- */
-#define SK_SEN_UNKNOWN 0
-#define SK_SEN_TEMP 1
-#define SK_SEN_VOLT 2
-#define SK_SEN_FAN 3
-
-/*
- * Define for the SenErrorFlag
- */
-#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */
-#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */
-#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */
-#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */
-#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */
-
-/*
- * Define the Sensor struct
- */
-struct s_Sensor {
- char *SenDesc; /* Description */
- int SenType; /* Voltage or Temperature */
- SK_I32 SenValue; /* Current value of the sensor */
- SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */
- SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */
- SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */
- SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */
- int SenErrFlag; /* Sensor indicated an error */
- SK_BOOL SenInit; /* Is sensor initialized ? */
- SK_U64 SenErrCts; /* Error trap counter */
- SK_U64 SenWarnCts; /* Warning trap counter */
- SK_U64 SenBegErrTS; /* Begin error timestamp */
- SK_U64 SenBegWarnTS; /* Begin warning timestamp */
- SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */
- SK_U64 SenLastErrLogTS; /* Last error log timestamp */
- SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */
- SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */
- int SenState; /* Sensor State (see HW specific include) */
- int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
- /* Sensors read function */
- SK_U16 SenReg; /* Register Address for this sensor */
- SK_U8 SenDev; /* Device Selection for this sensor */
-};
-
-typedef struct s_I2c {
- SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */
- int CurrSens; /* Which sensor is currently queried */
- int MaxSens; /* Max. number of sensors */
- int TimerMode; /* Use the timer also to watch the state machine */
- int InitLevel; /* Initialized Level */
-#ifndef SK_DIAG
- int DummyReads; /* Number of non-checked dummy reads */
- SK_TIMER SenTimer; /* Sensors timer */
-#endif /* !SK_DIAG */
-} SK_I2C;
-
-extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
-#ifdef SK_DIAG
-extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
- int Burst);
-#else /* !SK_DIAG */
-extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
-extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
-extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
-#endif /* !SK_DIAG */
-#endif /* n_SKI2C_H */
-
diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h
deleted file mode 100644
index 2ec40d4fdf6..00000000000
--- a/drivers/net/sk98lin/h/skqueue.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/******************************************************************************
- *
- * Name: skqueue.h
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.16 $
- * Date: $Date: 2003/09/16 12:50:32 $
- * Purpose: Defines for the Event queue
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKQUEUE.H contains all defines and types for the event queue
- */
-
-#ifndef _SKQUEUE_H_
-#define _SKQUEUE_H_
-
-
-/*
- * define the event classes to be served
- */
-#define SKGE_DRV 1 /* Driver Event Class */
-#define SKGE_RLMT 2 /* RLMT Event Class */
-#define SKGE_I2C 3 /* I2C Event Class */
-#define SKGE_PNMI 4 /* PNMI Event Class */
-#define SKGE_CSUM 5 /* Checksum Event Class */
-#define SKGE_HWAC 6 /* Hardware Access Event Class */
-
-#define SKGE_SWT 9 /* Software Timer Event Class */
-#define SKGE_LACP 10 /* LACP Aggregation Event Class */
-#define SKGE_RSF 11 /* RSF Aggregation Event Class */
-#define SKGE_MARKER 12 /* MARKER Aggregation Event Class */
-#define SKGE_FD 13 /* FD Distributor Event Class */
-
-/*
- * define event queue as circular buffer
- */
-#define SK_MAX_EVENT 64
-
-/*
- * Parameter union for the Para stuff
- */
-typedef union u_EvPara {
- void *pParaPtr; /* Parameter Pointer */
- SK_U64 Para64; /* Parameter 64bit version */
- SK_U32 Para32[2]; /* Parameter Array of 32bit parameters */
-} SK_EVPARA;
-
-/*
- * Event Queue
- * skqueue.c
- * events are class/value pairs
- * class is addressee, e.g. RLMT, PNMI etc.
- * value is command, e.g. line state change, ring op change etc.
- */
-typedef struct s_EventElem {
- SK_U32 Class; /* Event class */
- SK_U32 Event; /* Event value */
- SK_EVPARA Para; /* Event parameter */
-} SK_EVENTELEM;
-
-typedef struct s_Queue {
- SK_EVENTELEM EvQueue[SK_MAX_EVENT];
- SK_EVENTELEM *EvPut;
- SK_EVENTELEM *EvGet;
-} SK_QUEUE;
-
-extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event,
- SK_EVPARA Para);
-extern int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc);
-
-
-/* Define Error Numbers and messages */
-#define SKERR_Q_E001 (SK_ERRBASE_QUEUE+0)
-#define SKERR_Q_E001MSG "Event queue overflow"
-#define SKERR_Q_E002 (SKERR_Q_E001+1)
-#define SKERR_Q_E002MSG "Undefined event class"
-#endif /* _SKQUEUE_H_ */
-
diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h
deleted file mode 100644
index ca75dfdcf2d..00000000000
--- a/drivers/net/sk98lin/h/skrlmt.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/******************************************************************************
- *
- * Name: skrlmt.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.37 $
- * Date: $Date: 2003/04/15 09:43:43 $
- * Purpose: Header file for Redundant Link ManagemenT.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the header file for Redundant Link ManagemenT.
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * ...
- * "sktypes.h"
- * "skqueue.h"
- * "skaddr.h"
- * "skrlmt.h"
- * ...
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef __INC_SKRLMT_H
-#define __INC_SKRLMT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* cplusplus */
-
-/* defines ********************************************************************/
-
-#define SK_RLMT_NET_DOWN_TEMP 1 /* NET_DOWN due to last port down. */
-#define SK_RLMT_NET_DOWN_FINAL 2 /* NET_DOWN due to RLMT_STOP. */
-
-/* ----- Default queue sizes - must be multiples of 8 KB ----- */
-
-/* Less than 8 KB free in RX queue => pause frames. */
-#define SK_RLMT_STANDBY_QRXSIZE 128 /* Size of rx standby queue in KB. */
-#define SK_RLMT_STANDBY_QXASIZE 32 /* Size of async standby queue in KB. */
-#define SK_RLMT_STANDBY_QXSSIZE 0 /* Size of sync standby queue in KB. */
-
-#define SK_RLMT_MAX_TX_BUF_SIZE 60 /* Maximum RLMT transmit size. */
-
-/* ----- PORT states ----- */
-
-#define SK_RLMT_PS_INIT 0 /* Port state: Init. */
-#define SK_RLMT_PS_LINK_DOWN 1 /* Port state: Link down. */
-#define SK_RLMT_PS_DOWN 2 /* Port state: Port down. */
-#define SK_RLMT_PS_GOING_UP 3 /* Port state: Going up. */
-#define SK_RLMT_PS_UP 4 /* Port state: Up. */
-
-/* ----- RLMT states ----- */
-
-#define SK_RLMT_RS_INIT 0 /* RLMT state: Init. */
-#define SK_RLMT_RS_NET_DOWN 1 /* RLMT state: Net down. */
-#define SK_RLMT_RS_NET_UP 2 /* RLMT state: Net up. */
-
-/* ----- PORT events ----- */
-
-#define SK_RLMT_LINK_UP 1001 /* Link came up. */
-#define SK_RLMT_LINK_DOWN 1002 /* Link went down. */
-#define SK_RLMT_PORT_ADDR 1003 /* Port address changed. */
-
-/* ----- RLMT events ----- */
-
-#define SK_RLMT_START 2001 /* Start RLMT. */
-#define SK_RLMT_STOP 2002 /* Stop RLMT. */
-#define SK_RLMT_PACKET_RECEIVED 2003 /* Packet was received for RLMT. */
-#define SK_RLMT_STATS_CLEAR 2004 /* Clear statistics. */
-#define SK_RLMT_STATS_UPDATE 2005 /* Update statistics. */
-#define SK_RLMT_PREFPORT_CHANGE 2006 /* Change preferred port. */
-#define SK_RLMT_MODE_CHANGE 2007 /* New RlmtMode. */
-#define SK_RLMT_SET_NETS 2008 /* Number of Nets (1 or 2). */
-
-/* ----- RLMT mode bits ----- */
-
-/*
- * CAUTION: These defines are private to RLMT.
- * Please use the RLMT mode defines below.
- */
-
-#define SK_RLMT_CHECK_LINK 1 /* Check Link. */
-#define SK_RLMT_CHECK_LOC_LINK 2 /* Check other link on same adapter. */
-#define SK_RLMT_CHECK_SEG 4 /* Check segmentation. */
-
-#ifndef RLMT_CHECK_REMOTE
-#define SK_RLMT_CHECK_OTHERS SK_RLMT_CHECK_LOC_LINK
-#else /* RLMT_CHECK_REMOTE */
-#define SK_RLMT_CHECK_REM_LINK 8 /* Check link(s) on other adapter(s). */
-#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED 3
-#define SK_RLMT_CHECK_OTHERS \
- (SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-#endif /* RLMT_CHECK_REMOTE */
-
-#ifndef SK_RLMT_ENABLE_TRANSPARENT
-#define SK_RLMT_TRANSPARENT 0 /* RLMT transparent - inactive. */
-#else /* SK_RLMT_ENABLE_TRANSPARENT */
-#define SK_RLMT_TRANSPARENT 128 /* RLMT transparent. */
-#endif /* SK_RLMT_ENABLE_TRANSPARENT */
-
-/* ----- RLMT modes ----- */
-
-/* Check Link State. */
-#define SK_RLMT_MODE_CLS (SK_RLMT_CHECK_LINK)
-
-/* Check Local Ports: check other links on the same adapter. */
-#define SK_RLMT_MODE_CLP (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK)
-
-/* Check Local Ports and Segmentation Status. */
-#define SK_RLMT_MODE_CLPSS \
- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG)
-
-#ifdef RLMT_CHECK_REMOTE
-/* Check Local and Remote Ports: check links (local or remote). */
- Name of define TBD!
-#define SK_RLMT_MODE_CRP \
- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK)
-
-/* Check Local and Remote Ports and Segmentation Status. */
- Name of define TBD!
-#define SK_RLMT_MODE_CRPSS \
- (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \
- SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG)
-#endif /* RLMT_CHECK_REMOTE */
-
-/* ----- RLMT lookahead result bits ----- */
-
-#define SK_RLMT_RX_RLMT 1 /* Give packet to RLMT. */
-#define SK_RLMT_RX_PROTOCOL 2 /* Give packet to protocol. */
-
-/* Macros */
-
-#if 0
-SK_AC *pAC /* adapter context */
-SK_U32 PortNum /* receiving port */
-unsigned PktLen /* received packet's length */
-SK_BOOL IsBc /* Flag: packet is broadcast */
-unsigned *pOffset /* offs. of bytes to present to SK_RLMT_LOOKAHEAD */
-unsigned *pNumBytes /* #Bytes to present to SK_RLMT_LOOKAHEAD */
-#endif /* 0 */
-
-#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \
- SK_AC *_pAC; \
- SK_U32 _PortNum; \
- _pAC = (pAC); \
- _PortNum = (SK_U32)(PortNum); \
- /* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \
- _pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \
- if (_pAC->Rlmt.RlmtOff) { \
- *(pNumBytes) = 0; \
- } \
- else {\
- if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \
- *(pNumBytes) = 0; \
- } \
- else if (IsBc) { \
- if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \
- *(pNumBytes) = 6; \
- *(pOffset) = 6; \
- } \
- else { \
- *(pNumBytes) = 0; \
- } \
- } \
- else { \
- if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \
- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
- *(pNumBytes) = 0; \
- } \
- else { \
- *(pNumBytes) = 6; \
- *(pOffset) = 0; \
- } \
- } \
- } \
-}
-
-#if 0
-SK_AC *pAC /* adapter context */
-SK_U32 PortNum /* receiving port */
-SK_U8 *pLaPacket, /* received packet's data (points to pOffset) */
-SK_BOOL IsBc /* Flag: packet is broadcast */
-SK_BOOL IsMc /* Flag: packet is multicast */
-unsigned *pForRlmt /* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */
-SK_RLMT_LOOKAHEAD() expects *pNumBytes from
-packet offset *pOffset (s.a.) at *pLaPacket.
-
-If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is
-BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler
-can trash unneeded parts of the if construction.
-#endif /* 0 */
-
-#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \
- SK_AC *_pAC; \
- SK_U32 _PortNum; \
- SK_U8 *_pLaPacket; \
- _pAC = (pAC); \
- _PortNum = (SK_U32)(PortNum); \
- _pLaPacket = (SK_U8 *)(pLaPacket); \
- if (IsBc) {\
- if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \
- _PortNum].Net->NetNumber].CurrentMacAddress.a)) { \
- _pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \
- _pAC->Rlmt.CheckSwitch = SK_TRUE; \
- } \
- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
- } \
- else if (IsMc) { \
- if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \
- _pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \
- if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \
- *(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \
- } \
- else { \
- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
- } \
- } \
- else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \
- *(pForRlmt) = SK_RLMT_RX_RLMT; \
- } \
- else { \
- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
- } \
- } \
- else { \
- if (SK_ADDR_EQUAL( \
- _pLaPacket, \
- _pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \
- *(pForRlmt) = SK_RLMT_RX_RLMT; \
- } \
- else { \
- /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \
- *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \
- } \
- } \
-}
-
-#ifdef SK_RLMT_FAST_LOOKAHEAD
-Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif /* SK_RLMT_FAST_LOOKAHEAD */
-#ifdef SK_RLMT_SLOW_LOOKAHEAD
-Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead.
-#endif /* SK_RLMT_SLOW_LOOKAHEAD */
-
-/* typedefs *******************************************************************/
-
-#ifdef SK_RLMT_MBUF_PRIVATE
-typedef struct s_RlmtMbuf {
- some content
-} SK_RLMT_MBUF;
-#endif /* SK_RLMT_MBUF_PRIVATE */
-
-
-#ifdef SK_LA_INFO
-typedef struct s_Rlmt_PacketInfo {
- unsigned PacketLength; /* Length of packet. */
- unsigned PacketType; /* Directed/Multicast/Broadcast. */
-} SK_RLMT_PINFO;
-#endif /* SK_LA_INFO */
-
-
-typedef struct s_RootId {
- SK_U8 Id[8]; /* Root Bridge Id. */
-} SK_RLMT_ROOT_ID;
-
-
-typedef struct s_port {
- SK_MAC_ADDR CheckAddr;
- SK_BOOL SuspectTx;
-} SK_PORT_CHECK;
-
-
-typedef struct s_RlmtNet SK_RLMT_NET;
-
-
-typedef struct s_RlmtPort {
-
-/* ----- Public part (read-only) ----- */
-
- SK_U8 PortState; /* Current state of this port. */
-
- /* For PNMI */
- SK_BOOL LinkDown;
- SK_BOOL PortDown;
- SK_U8 Align01;
-
- SK_U32 PortNumber; /* Number of port on adapter. */
- SK_RLMT_NET * Net; /* Net port belongs to. */
-
- SK_U64 TxHelloCts;
- SK_U64 RxHelloCts;
- SK_U64 TxSpHelloReqCts;
- SK_U64 RxSpHelloCts;
-
-/* ----- Private part ----- */
-
-/* SK_U64 PacketsRx; */ /* Total packets received. */
- SK_U32 PacketsPerTimeSlot; /* Packets rxed between TOs. */
-/* SK_U32 DataPacketsPerTimeSlot; */ /* Data packets ... */
- SK_U32 BpduPacketsPerTimeSlot; /* BPDU packets rxed in TS. */
- SK_U64 BcTimeStamp; /* Time of last BC receive. */
- SK_U64 GuTimeStamp; /* Time of entering GOING_UP. */
-
- SK_TIMER UpTimer; /* Timer struct Link/Port up. */
- SK_TIMER DownRxTimer; /* Timer struct down rx. */
- SK_TIMER DownTxTimer; /* Timer struct down tx. */
-
- SK_U32 CheckingState; /* Checking State. */
-
- SK_ADDR_PORT * AddrPort;
-
- SK_U8 Random[4]; /* Random value. */
- unsigned PortsChecked; /* #ports checked. */
- unsigned PortsSuspect; /* #ports checked that are s. */
- SK_PORT_CHECK PortCheck[1];
-/* SK_PORT_CHECK PortCheck[SK_MAX_MACS - 1]; */
-
- SK_BOOL PortStarted; /* Port is started. */
- SK_BOOL PortNoRx; /* NoRx for >= 1 time slot. */
- SK_BOOL RootIdSet;
- SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */
-} SK_RLMT_PORT;
-
-
-struct s_RlmtNet {
-
-/* ----- Public part (read-only) ----- */
-
- SK_U32 NetNumber; /* Number of net. */
-
- SK_RLMT_PORT * Port[SK_MAX_MACS]; /* Ports that belong to this net. */
- SK_U32 NumPorts; /* Number of ports. */
- SK_U32 PrefPort; /* Preferred port. */
-
- /* For PNMI */
-
- SK_U32 ChgBcPrio; /* Change Priority of last broadcast received */
- SK_U32 RlmtMode; /* Check ... */
- SK_U32 ActivePort; /* Active port. */
- SK_U32 Preference; /* 0xFFFFFFFF: Automatic. */
-
- SK_U8 RlmtState; /* Current RLMT state. */
-
-/* ----- Private part ----- */
- SK_BOOL RootIdSet;
- SK_U16 Align01;
-
- int LinksUp; /* #Links up. */
- int PortsUp; /* #Ports up. */
- SK_U32 TimeoutValue; /* RLMT timeout value. */
-
- SK_U32 CheckingState; /* Checking State. */
- SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */
-
- SK_TIMER LocTimer; /* Timer struct. */
- SK_TIMER SegTimer; /* Timer struct. */
-};
-
-
-typedef struct s_Rlmt {
-
-/* ----- Public part (read-only) ----- */
-
- SK_U32 NumNets; /* Number of nets. */
- SK_U32 NetsStarted; /* Number of nets started. */
- SK_RLMT_NET Net[SK_MAX_NETS]; /* Array of available nets. */
- SK_RLMT_PORT Port[SK_MAX_MACS]; /* Array of available ports. */
-
-/* ----- Private part ----- */
- SK_BOOL CheckSwitch;
- SK_BOOL RlmtOff; /* set to zero if the Mac addresses
- are equal or the second one
- is zero */
- SK_U16 Align01;
-
-} SK_RLMT;
-
-
-extern SK_MAC_ADDR BridgeMcAddr;
-extern SK_MAC_ADDR SkRlmtMcAddr;
-
-/* function prototypes ********************************************************/
-
-
-#ifndef SK_KR_PROTO
-
-/* Functions provided by SkRlmt */
-
-/* ANSI/C++ compliant function prototypes */
-
-extern void SkRlmtInit(
- SK_AC *pAC,
- SK_IOC IoC,
- int Level);
-
-extern int SkRlmtEvent(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 Event,
- SK_EVPARA Para);
-
-#else /* defined(SK_KR_PROTO) */
-
-/* Non-ANSI/C++ compliant function prototypes */
-
-#error KR-style function prototypes are not yet provided.
-
-#endif /* defined(SK_KR_PROTO)) */
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_SKRLMT_H */
diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h
deleted file mode 100644
index 04e6d7c1ec3..00000000000
--- a/drivers/net/sk98lin/h/sktimer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/******************************************************************************
- *
- * Name: sktimer.h
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.11 $
- * Date: $Date: 2003/09/16 12:58:18 $
- * Purpose: Defines for the timer functions
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * SKTIMER.H contains all defines and types for the timer functions
- */
-
-#ifndef _SKTIMER_H_
-#define _SKTIMER_H_
-
-#include "h/skqueue.h"
-
-/*
- * SK timer
- * - needed wherever a timer is used. Put this in your data structure
- * wherever you want.
- */
-typedef struct s_Timer SK_TIMER;
-
-struct s_Timer {
- SK_TIMER *TmNext; /* linked list */
- SK_U32 TmClass; /* Timer Event class */
- SK_U32 TmEvent; /* Timer Event value */
- SK_EVPARA TmPara; /* Timer Event parameter */
- SK_U32 TmDelta; /* delta time */
- int TmActive; /* flag: active/inactive */
-};
-
-/*
- * Timer control struct.
- * - use in Adapters context name pAC->Tim
- */
-typedef struct s_TimCtrl {
- SK_TIMER *StQueue; /* Head of Timer queue */
-} SK_TIMCTRL;
-
-extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level);
-extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer);
-extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer,
- SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para);
-extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc);
-#endif /* _SKTIMER_H_ */
diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h
deleted file mode 100644
index 40edc96e105..00000000000
--- a/drivers/net/sk98lin/h/sktypes.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/******************************************************************************
- *
- * Name: sktypes.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.2 $
- * Date: $Date: 2003/10/07 08:16:51 $
- * Purpose: Define data types for Linux
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * In this file, all data types that are needed by the common modules
- * are mapped to Linux data types.
- *
- *
- * Include File Hierarchy:
- *
- *
- ******************************************************************************/
-
-#ifndef __INC_SKTYPES_H
-#define __INC_SKTYPES_H
-
-
-/* defines *******************************************************************/
-
-/*
- * Data types with a specific size. 'I' = signed, 'U' = unsigned.
- */
-#define SK_I8 s8
-#define SK_U8 u8
-#define SK_I16 s16
-#define SK_U16 u16
-#define SK_I32 s32
-#define SK_U32 u32
-#define SK_I64 s64
-#define SK_U64 u64
-
-#define SK_UPTR ulong /* casting pointer <-> integral */
-
-/*
-* Boolean type.
-*/
-#define SK_BOOL SK_U8
-#define SK_FALSE 0
-#define SK_TRUE (!SK_FALSE)
-
-/* typedefs *******************************************************************/
-
-/* function prototypes ********************************************************/
-
-#endif /* __INC_SKTYPES_H */
diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h
deleted file mode 100644
index a1a7294828e..00000000000
--- a/drivers/net/sk98lin/h/skversion.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/******************************************************************************
- *
- * Name: version.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.5 $
- * Date: $Date: 2003/10/07 08:16:51 $
- * Purpose: SK specific Error log support
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifdef lint
-static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
-static const char SysKonnectBuildNumber[] =
- "@(#)SK-BUILD: 6.23 PL: 01";
-#endif /* !defined(lint) */
-
-#define BOOT_STRING "sk98lin: Network Device Driver v6.23\n" \
- "(C)Copyright 1999-2004 Marvell(R)."
-
-#define VER_STRING "6.23"
-#define DRIVER_FILE_NAME "sk98lin"
-#define DRIVER_REL_DATE "Feb-13-2004"
-
-
diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h
deleted file mode 100644
index fdd9e48e804..00000000000
--- a/drivers/net/sk98lin/h/skvpd.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/******************************************************************************
- *
- * Name: skvpd.h
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.15 $
- * Date: $Date: 2003/01/13 10:39:38 $
- * Purpose: Defines and Macros for VPD handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2003 SysKonnect 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 by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * skvpd.h contains Diagnostic specific defines for VPD handling
- */
-
-#ifndef __INC_SKVPD_H_
-#define __INC_SKVPD_H_
-
-/*
- * Define Resource Type Identifiers and VPD keywords
- */
-#define RES_ID 0x82 /* Resource Type ID String (Product Name) */
-#define RES_VPD_R 0x90 /* start of VPD read only area */
-#define RES_VPD_W 0x91 /* start of VPD read/write area */
-#define RES_END 0x78 /* Resource Type End Tag */
-
-#ifndef VPD_NAME
-#define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */
-#endif /* VPD_NAME */
-#define VPD_PN "PN" /* Adapter Part Number */
-#define VPD_EC "EC" /* Adapter Engineering Level */
-#define VPD_MN "MN" /* Manufacture ID */
-#define VPD_SN "SN" /* Serial Number */
-#define VPD_CP "CP" /* Extended Capability */
-#define VPD_RV "RV" /* Checksum and Reserved */
-#define VPD_YA "YA" /* Asset Tag Identifier */
-#define VPD_VL "VL" /* First Error Log Message (SK specific) */
-#define VPD_VF "VF" /* Second Error Log Message (SK specific) */
-#define VPD_RW "RW" /* Remaining Read / Write Area */
-
-/* 'type' values for vpd_setup_para() */
-#define VPD_RO_KEY 1 /* RO keys are "PN", "EC", "MN", "SN", "RV" */
-#define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */
-
-/* 'op' values for vpd_setup_para() */
-#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */
-#define OWR_KEY 2 /* overwrite key if already exists */
-
-/*
- * Define READ and WRITE Constants.
- */
-
-#define VPD_DEV_ID_GENESIS 0x4300
-
-#define VPD_SIZE_YUKON 256
-#define VPD_SIZE_GENESIS 512
-#define VPD_SIZE 512
-#define VPD_READ 0x0000
-#define VPD_WRITE 0x8000
-
-#define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
-
-#define VPD_GET_RES_LEN(p) ((unsigned int) \
- (* (SK_U8 *)&(p)[1]) |\
- ((* (SK_U8 *)&(p)[2]) << 8))
-#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2]))
-#define VPD_GET_VAL(p) ((char *)&(p)[3])
-
-#define VPD_MAX_LEN 50
-
-/* VPD status */
- /* bit 7..1 reserved */
-#define VPD_VALID (1<<0) /* VPD data buffer, vpd_free_ro, */
- /* and vpd_free_rw valid */
-
-/*
- * VPD structs
- */
-typedef struct s_vpd_status {
- unsigned short Align01; /* Alignment */
- unsigned short vpd_status; /* VPD status, description see above */
- int vpd_free_ro; /* unused bytes in read only area */
- int vpd_free_rw; /* bytes available in read/write area */
-} SK_VPD_STATUS;
-
-typedef struct s_vpd {
- SK_VPD_STATUS v; /* VPD status structure */
- char vpd_buf[VPD_SIZE]; /* VPD buffer */
- int rom_size; /* VPD ROM Size from PCI_OUR_REG_2 */
- int vpd_size; /* saved VPD-size */
-} SK_VPD;
-
-typedef struct s_vpd_para {
- unsigned int p_len; /* parameter length */
- char *p_val; /* points to the value */
-} SK_VPD_PARA;
-
-/*
- * structure of Large Resource Type Identifiers
- */
-
-/* was removed because of alignment problems */
-
-/*
- * structure of VPD keywords
- */
-typedef struct s_vpd_key {
- char p_key[2]; /* 2 bytes ID string */
- unsigned char p_len; /* 1 byte length */
- char p_val; /* start of the value string */
-} SK_VPD_KEY;
-
-
-/*
- * System specific VPD macros
- */
-#ifndef SKDIAG
-#ifndef VPD_DO_IO
-#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal)
-#else /* VPD_DO_IO */
-#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val)
-#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val)
-#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal)
-#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal)
-#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal)
-#endif /* VPD_DO_IO */
-#else /* SKDIAG */
-#define VPD_OUT8(pAC,Ioc,Addr,Val) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciWriteCfgByte(pAC,Addr,Val); \
- else \
- SK_OUT8(pAC,PCI_C(Addr),Val); \
- }
-#define VPD_OUT16(pAC,Ioc,Addr,Val) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciWriteCfgWord(pAC,Addr,Val); \
- else \
- SK_OUT16(pAC,PCI_C(Addr),Val); \
- }
-#define VPD_IN8(pAC,Ioc,Addr,pVal) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciReadCfgByte(pAC,Addr,pVal); \
- else \
- SK_IN8(pAC,PCI_C(Addr),pVal); \
- }
-#define VPD_IN16(pAC,Ioc,Addr,pVal) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciReadCfgWord(pAC,Addr,pVal); \
- else \
- SK_IN16(pAC,PCI_C(Addr),pVal); \
- }
-#define VPD_IN32(pAC,Ioc,Addr,pVal) { \
- if ((pAC)->DgT.DgUseCfgCycle) \
- SkPciReadCfgDWord(pAC,Addr,pVal); \
- else \
- SK_IN32(pAC,PCI_C(Addr),pVal); \
- }
-#endif /* nSKDIAG */
-
-/* function prototypes ********************************************************/
-
-#ifndef SK_KR_PROTO
-#ifdef SKDIAG
-extern SK_U32 VpdReadDWord(
- SK_AC *pAC,
- SK_IOC IoC,
- int addr);
-#endif /* SKDIAG */
-
-extern SK_VPD_STATUS *VpdStat(
- SK_AC *pAC,
- SK_IOC IoC);
-
-extern int VpdKeys(
- SK_AC *pAC,
- SK_IOC IoC,
- char *buf,
- int *len,
- int *elements);
-
-extern int VpdRead(
- SK_AC *pAC,
- SK_IOC IoC,
- const char *key,
- char *buf,
- int *len);
-
-extern SK_BOOL VpdMayWrite(
- char *key);
-
-extern int VpdWrite(
- SK_AC *pAC,
- SK_IOC IoC,
- const char *key,
- const char *buf);
-
-extern int VpdDelete(
- SK_AC *pAC,
- SK_IOC IoC,
- char *key);
-
-extern int VpdUpdate(
- SK_AC *pAC,
- SK_IOC IoC);
-
-#ifdef SKDIAG
-extern int VpdReadBlock(
- SK_AC *pAC,
- SK_IOC IoC,
- char *buf,
- int addr,
- int len);
-
-extern int VpdWriteBlock(
- SK_AC *pAC,
- SK_IOC IoC,
- char *buf,
- int addr,
- int len);
-#endif /* SKDIAG */
-#else /* SK_KR_PROTO */
-extern SK_U32 VpdReadDWord();
-extern SK_VPD_STATUS *VpdStat();
-extern int VpdKeys();
-extern int VpdRead();
-extern SK_BOOL VpdMayWrite();
-extern int VpdWrite();
-extern int VpdDelete();
-extern int VpdUpdate();
-#endif /* SK_KR_PROTO */
-
-#endif /* __INC_SKVPD_H_ */
diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h
deleted file mode 100644
index 7f8e6d0084c..00000000000
--- a/drivers/net/sk98lin/h/xmac_ii.h
+++ /dev/null
@@ -1,1579 +0,0 @@
-/******************************************************************************
- *
- * Name: xmac_ii.h
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.52 $
- * Date: $Date: 2003/10/02 16:35:50 $
- * Purpose: Defines and Macros for Gigabit Ethernet Controller
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#ifndef __INC_XMAC_H
-#define __INC_XMAC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* defines ********************************************************************/
-
-/*
- * XMAC II registers
- *
- * The XMAC registers are 16 or 32 bits wide.
- * The XMACs host processor interface is set to 16 bit mode,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the XMAC registers
- * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(),
- * XM_INHASH(), and XM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note: NA reg = Network Address e.g DA, SA etc.
- *
- */
-#define XM_MMU_CMD 0x0000 /* 16 bit r/w MMU Command Register */
- /* 0x0004: reserved */
-#define XM_POFF 0x0008 /* 32 bit r/w Packet Offset Register */
-#define XM_BURST 0x000c /* 32 bit r/w Burst Register for half duplex*/
-#define XM_1L_VLAN_TAG 0x0010 /* 16 bit r/w One Level VLAN Tag ID */
-#define XM_2L_VLAN_TAG 0x0014 /* 16 bit r/w Two Level VLAN Tag ID */
- /* 0x0018 - 0x001e: reserved */
-#define XM_TX_CMD 0x0020 /* 16 bit r/w Transmit Command Register */
-#define XM_TX_RT_LIM 0x0024 /* 16 bit r/w Transmit Retry Limit Register */
-#define XM_TX_STIME 0x0028 /* 16 bit r/w Transmit Slottime Register */
-#define XM_TX_IPG 0x002c /* 16 bit r/w Transmit Inter Packet Gap */
-#define XM_RX_CMD 0x0030 /* 16 bit r/w Receive Command Register */
-#define XM_PHY_ADDR 0x0034 /* 16 bit r/w PHY Address Register */
-#define XM_PHY_DATA 0x0038 /* 16 bit r/w PHY Data Register */
- /* 0x003c: reserved */
-#define XM_GP_PORT 0x0040 /* 32 bit r/w General Purpose Port Register */
-#define XM_IMSK 0x0044 /* 16 bit r/w Interrupt Mask Register */
-#define XM_ISRC 0x0048 /* 16 bit r/o Interrupt Status Register */
-#define XM_HW_CFG 0x004c /* 16 bit r/w Hardware Config Register */
- /* 0x0050 - 0x005e: reserved */
-#define XM_TX_LO_WM 0x0060 /* 16 bit r/w Tx FIFO Low Water Mark */
-#define XM_TX_HI_WM 0x0062 /* 16 bit r/w Tx FIFO High Water Mark */
-#define XM_TX_THR 0x0064 /* 16 bit r/w Tx Request Threshold */
-#define XM_HT_THR 0x0066 /* 16 bit r/w Host Request Threshold */
-#define XM_PAUSE_DA 0x0068 /* NA reg r/w Pause Destination Address */
- /* 0x006e: reserved */
-#define XM_CTL_PARA 0x0070 /* 32 bit r/w Control Parameter Register */
-#define XM_MAC_OPCODE 0x0074 /* 16 bit r/w Opcode for MAC control frames */
-#define XM_MAC_PTIME 0x0076 /* 16 bit r/w Pause time for MAC ctrl frames*/
-#define XM_TX_STAT 0x0078 /* 32 bit r/o Tx Status LIFO Register */
-
- /* 0x0080 - 0x00fc: 16 NA reg r/w Exact Match Address Registers */
- /* use the XM_EXM() macro to address */
-#define XM_EXM_START 0x0080 /* r/w Start Address of the EXM Regs */
-
- /*
- * XM_EXM(Reg)
- *
- * returns the XMAC address offset of specified Exact Match Addr Reg
- *
- * para: Reg EXM register to addr (0 .. 15)
- *
- * usage: XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]);
- */
-#define XM_EXM(Reg) (XM_EXM_START + ((Reg) << 3))
-
-#define XM_SRC_CHK 0x0100 /* NA reg r/w Source Check Address Register */
-#define XM_SA 0x0108 /* NA reg r/w Station Address Register */
-#define XM_HSM 0x0110 /* 64 bit r/w Hash Match Address Registers */
-#define XM_RX_LO_WM 0x0118 /* 16 bit r/w Receive Low Water Mark */
-#define XM_RX_HI_WM 0x011a /* 16 bit r/w Receive High Water Mark */
-#define XM_RX_THR 0x011c /* 32 bit r/w Receive Request Threshold */
-#define XM_DEV_ID 0x0120 /* 32 bit r/o Device ID Register */
-#define XM_MODE 0x0124 /* 32 bit r/w Mode Register */
-#define XM_LSA 0x0128 /* NA reg r/o Last Source Register */
- /* 0x012e: reserved */
-#define XM_TS_READ 0x0130 /* 32 bit r/o Time Stamp Read Register */
-#define XM_TS_LOAD 0x0134 /* 32 bit r/o Time Stamp Load Value */
- /* 0x0138 - 0x01fe: reserved */
-#define XM_STAT_CMD 0x0200 /* 16 bit r/w Statistics Command Register */
-#define XM_RX_CNT_EV 0x0204 /* 32 bit r/o Rx Counter Event Register */
-#define XM_TX_CNT_EV 0x0208 /* 32 bit r/o Tx Counter Event Register */
-#define XM_RX_EV_MSK 0x020c /* 32 bit r/w Rx Counter Event Mask */
-#define XM_TX_EV_MSK 0x0210 /* 32 bit r/w Tx Counter Event Mask */
- /* 0x0204 - 0x027e: reserved */
-#define XM_TXF_OK 0x0280 /* 32 bit r/o Frames Transmitted OK Conuter */
-#define XM_TXO_OK_HI 0x0284 /* 32 bit r/o Octets Transmitted OK High Cnt*/
-#define XM_TXO_OK_LO 0x0288 /* 32 bit r/o Octets Transmitted OK Low Cnt */
-#define XM_TXF_BC_OK 0x028c /* 32 bit r/o Broadcast Frames Xmitted OK */
-#define XM_TXF_MC_OK 0x0290 /* 32 bit r/o Multicast Frames Xmitted OK */
-#define XM_TXF_UC_OK 0x0294 /* 32 bit r/o Unicast Frames Xmitted OK */
-#define XM_TXF_LONG 0x0298 /* 32 bit r/o Tx Long Frame Counter */
-#define XM_TXE_BURST 0x029c /* 32 bit r/o Tx Burst Event Counter */
-#define XM_TXF_MPAUSE 0x02a0 /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */
-#define XM_TXF_MCTRL 0x02a4 /* 32 bit r/o Tx MAC Ctrl Frame Counter */
-#define XM_TXF_SNG_COL 0x02a8 /* 32 bit r/o Tx Single Collision Counter */
-#define XM_TXF_MUL_COL 0x02ac /* 32 bit r/o Tx Multiple Collision Counter */
-#define XM_TXF_ABO_COL 0x02b0 /* 32 bit r/o Tx aborted due to Exces. Col. */
-#define XM_TXF_LAT_COL 0x02b4 /* 32 bit r/o Tx Late Collision Counter */
-#define XM_TXF_DEF 0x02b8 /* 32 bit r/o Tx Deferred Frame Counter */
-#define XM_TXF_EX_DEF 0x02bc /* 32 bit r/o Tx Excessive Deferall Counter */
-#define XM_TXE_FIFO_UR 0x02c0 /* 32 bit r/o Tx FIFO Underrun Event Cnt */
-#define XM_TXE_CS_ERR 0x02c4 /* 32 bit r/o Tx Carrier Sense Error Cnt */
-#define XM_TXP_UTIL 0x02c8 /* 32 bit r/o Tx Utilization in % */
- /* 0x02cc - 0x02ce: reserved */
-#define XM_TXF_64B 0x02d0 /* 32 bit r/o 64 Byte Tx Frame Counter */
-#define XM_TXF_127B 0x02d4 /* 32 bit r/o 65-127 Byte Tx Frame Counter */
-#define XM_TXF_255B 0x02d8 /* 32 bit r/o 128-255 Byte Tx Frame Counter */
-#define XM_TXF_511B 0x02dc /* 32 bit r/o 256-511 Byte Tx Frame Counter */
-#define XM_TXF_1023B 0x02e0 /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/
-#define XM_TXF_MAX_SZ 0x02e4 /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/
- /* 0x02e8 - 0x02fe: reserved */
-#define XM_RXF_OK 0x0300 /* 32 bit r/o Frames Received OK */
-#define XM_RXO_OK_HI 0x0304 /* 32 bit r/o Octets Received OK High Cnt */
-#define XM_RXO_OK_LO 0x0308 /* 32 bit r/o Octets Received OK Low Counter*/
-#define XM_RXF_BC_OK 0x030c /* 32 bit r/o Broadcast Frames Received OK */
-#define XM_RXF_MC_OK 0x0310 /* 32 bit r/o Multicast Frames Received OK */
-#define XM_RXF_UC_OK 0x0314 /* 32 bit r/o Unicast Frames Received OK */
-#define XM_RXF_MPAUSE 0x0318 /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */
-#define XM_RXF_MCTRL 0x031c /* 32 bit r/o Rx MAC Ctrl Frame Counter */
-#define XM_RXF_INV_MP 0x0320 /* 32 bit r/o Rx invalid Pause Frame Cnt */
-#define XM_RXF_INV_MOC 0x0324 /* 32 bit r/o Rx Frames with inv. MAC Opcode*/
-#define XM_RXE_BURST 0x0328 /* 32 bit r/o Rx Burst Event Counter */
-#define XM_RXE_FMISS 0x032c /* 32 bit r/o Rx Missed Frames Event Cnt */
-#define XM_RXF_FRA_ERR 0x0330 /* 32 bit r/o Rx Framing Error Counter */
-#define XM_RXE_FIFO_OV 0x0334 /* 32 bit r/o Rx FIFO overflow Event Cnt */
-#define XM_RXF_JAB_PKT 0x0338 /* 32 bit r/o Rx Jabber Packet Frame Cnt */
-#define XM_RXE_CAR_ERR 0x033c /* 32 bit r/o Rx Carrier Event Error Cnt */
-#define XM_RXF_LEN_ERR 0x0340 /* 32 bit r/o Rx in Range Length Error */
-#define XM_RXE_SYM_ERR 0x0344 /* 32 bit r/o Rx Symbol Error Counter */
-#define XM_RXE_SHT_ERR 0x0348 /* 32 bit r/o Rx Short Event Error Cnt */
-#define XM_RXE_RUNT 0x034c /* 32 bit r/o Rx Runt Event Counter */
-#define XM_RXF_LNG_ERR 0x0350 /* 32 bit r/o Rx Frame too Long Error Cnt */
-#define XM_RXF_FCS_ERR 0x0354 /* 32 bit r/o Rx Frame Check Seq. Error Cnt */
- /* 0x0358 - 0x035a: reserved */
-#define XM_RXF_CEX_ERR 0x035c /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/
-#define XM_RXP_UTIL 0x0360 /* 32 bit r/o Rx Utilization in % */
- /* 0x0364 - 0x0366: reserved */
-#define XM_RXF_64B 0x0368 /* 32 bit r/o 64 Byte Rx Frame Counter */
-#define XM_RXF_127B 0x036c /* 32 bit r/o 65-127 Byte Rx Frame Counter */
-#define XM_RXF_255B 0x0370 /* 32 bit r/o 128-255 Byte Rx Frame Counter */
-#define XM_RXF_511B 0x0374 /* 32 bit r/o 256-511 Byte Rx Frame Counter */
-#define XM_RXF_1023B 0x0378 /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/
-#define XM_RXF_MAX_SZ 0x037c /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/
- /* 0x02e8 - 0x02fe: reserved */
-
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- * (sc) self clearing
- * (ro) read only
- */
-
-/* XM_MMU_CMD 16 bit r/w MMU Command Register */
- /* Bit 15..13: reserved */
-#define XM_MMU_PHY_RDY (1<<12) /* Bit 12: PHY Read Ready */
-#define XM_MMU_PHY_BUSY (1<<11) /* Bit 11: PHY Busy */
-#define XM_MMU_IGN_PF (1<<10) /* Bit 10: Ignore Pause Frame */
-#define XM_MMU_MAC_LB (1<<9) /* Bit 9: Enable MAC Loopback */
- /* Bit 8: reserved */
-#define XM_MMU_FRC_COL (1<<7) /* Bit 7: Force Collision */
-#define XM_MMU_SIM_COL (1<<6) /* Bit 6: Simulate Collision */
-#define XM_MMU_NO_PRE (1<<5) /* Bit 5: No MDIO Preamble */
-#define XM_MMU_GMII_FD (1<<4) /* Bit 4: GMII uses Full Duplex */
-#define XM_MMU_RAT_CTRL (1<<3) /* Bit 3: Enable Rate Control */
-#define XM_MMU_GMII_LOOP (1<<2) /* Bit 2: PHY is in Loopback Mode */
-#define XM_MMU_ENA_RX (1<<1) /* Bit 1: Enable Receiver */
-#define XM_MMU_ENA_TX (1<<0) /* Bit 0: Enable Transmitter */
-
-
-/* XM_TX_CMD 16 bit r/w Transmit Command Register */
- /* Bit 15..7: reserved */
-#define XM_TX_BK2BK (1<<6) /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/
-#define XM_TX_ENC_BYP (1<<5) /* Bit 5: Set Encoder in Bypass Mode */
-#define XM_TX_SAM_LINE (1<<4) /* Bit 4: (sc) Start utilization calculation */
-#define XM_TX_NO_GIG_MD (1<<3) /* Bit 3: Disable Carrier Extension */
-#define XM_TX_NO_PRE (1<<2) /* Bit 2: Disable Preamble Generation */
-#define XM_TX_NO_CRC (1<<1) /* Bit 1: Disable CRC Generation */
-#define XM_TX_AUTO_PAD (1<<0) /* Bit 0: Enable Automatic Padding */
-
-
-/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */
- /* Bit 15..5: reserved */
-#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */
-
-
-/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */
- /* Bit 15..7: reserved */
-#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */
-
-
-/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */
- /* Bit 15..8: reserved */
-#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */
-
-
-/* XM_RX_CMD 16 bit r/w Receive Command Register */
- /* Bit 15..9: reserved */
-#define XM_RX_LENERR_OK (1<<8) /* Bit 8 don't set Rx Err bit for */
- /* inrange error packets */
-#define XM_RX_BIG_PK_OK (1<<7) /* Bit 7 don't set Rx Err bit for */
- /* jumbo packets */
-#define XM_RX_IPG_CAP (1<<6) /* Bit 6 repl. type field with IPG */
-#define XM_RX_TP_MD (1<<5) /* Bit 5: Enable transparent Mode */
-#define XM_RX_STRIP_FCS (1<<4) /* Bit 4: Enable FCS Stripping */
-#define XM_RX_SELF_RX (1<<3) /* Bit 3: Enable Rx of own packets */
-#define XM_RX_SAM_LINE (1<<2) /* Bit 2: (sc) Start utilization calculation */
-#define XM_RX_STRIP_PAD (1<<1) /* Bit 1: Strip pad bytes of Rx frames */
-#define XM_RX_DIS_CEXT (1<<0) /* Bit 0: Disable carrier ext. check */
-
-
-/* XM_PHY_ADDR 16 bit r/w PHY Address Register */
- /* Bit 15..5: reserved */
-#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */
-
-
-/* XM_GP_PORT 32 bit r/w General Purpose Port Register */
- /* Bit 31..7: reserved */
-#define XM_GP_ANIP (1L<<6) /* Bit 6: (ro) Auto-Neg. in progress */
-#define XM_GP_FRC_INT (1L<<5) /* Bit 5: (sc) Force Interrupt */
- /* Bit 4: reserved */
-#define XM_GP_RES_MAC (1L<<3) /* Bit 3: (sc) Reset MAC and FIFOs */
-#define XM_GP_RES_STAT (1L<<2) /* Bit 2: (sc) Reset the statistics module */
- /* Bit 1: reserved */
-#define XM_GP_INP_ASS (1L<<0) /* Bit 0: (ro) GP Input Pin asserted */
-
-
-/* XM_IMSK 16 bit r/w Interrupt Mask Register */
-/* XM_ISRC 16 bit r/o Interrupt Status Register */
- /* Bit 15: reserved */
-#define XM_IS_LNK_AE (1<<14) /* Bit 14: Link Asynchronous Event */
-#define XM_IS_TX_ABORT (1<<13) /* Bit 13: Transmit Abort, late Col. etc */
-#define XM_IS_FRC_INT (1<<12) /* Bit 12: Force INT bit set in GP */
-#define XM_IS_INP_ASS (1<<11) /* Bit 11: Input Asserted, GP bit 0 set */
-#define XM_IS_LIPA_RC (1<<10) /* Bit 10: Link Partner requests config */
-#define XM_IS_RX_PAGE (1<<9) /* Bit 9: Page Received */
-#define XM_IS_TX_PAGE (1<<8) /* Bit 8: Next Page Loaded for Transmit */
-#define XM_IS_AND (1<<7) /* Bit 7: Auto-Negotiation Done */
-#define XM_IS_TSC_OV (1<<6) /* Bit 6: Time Stamp Counter Overflow */
-#define XM_IS_RXC_OV (1<<5) /* Bit 5: Rx Counter Event Overflow */
-#define XM_IS_TXC_OV (1<<4) /* Bit 4: Tx Counter Event Overflow */
-#define XM_IS_RXF_OV (1<<3) /* Bit 3: Receive FIFO Overflow */
-#define XM_IS_TXF_UR (1<<2) /* Bit 2: Transmit FIFO Underrun */
-#define XM_IS_TX_COMP (1<<1) /* Bit 1: Frame Tx Complete */
-#define XM_IS_RX_COMP (1<<0) /* Bit 0: Frame Rx Complete */
-
-#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\
- XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR))
-
-
-/* XM_HW_CFG 16 bit r/w Hardware Config Register */
- /* Bit 15.. 4: reserved */
-#define XM_HW_GEN_EOP (1<<3) /* Bit 3: generate End of Packet pulse */
-#define XM_HW_COM4SIG (1<<2) /* Bit 2: use Comma Detect for Sig. Det.*/
- /* Bit 1: reserved */
-#define XM_HW_GMII_MD (1<<0) /* Bit 0: GMII Interface selected */
-
-
-/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */
-/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */
- /* Bit 15..10 reserved */
-#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */
-
-/* XM_TX_THR 16 bit r/w Tx Request Threshold */
-/* XM_HT_THR 16 bit r/w Host Request Threshold */
-/* XM_RX_THR 16 bit r/w Rx Request Threshold */
- /* Bit 15..11 reserved */
-#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */
-
-
-/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */
-#define XM_ST_VALID (1UL<<31) /* Bit 31: Status Valid */
-#define XM_ST_BYTE_CNT (0x3fffL<<17) /* Bit 30..17: Tx frame Length */
-#define XM_ST_RETRY_CNT (0x1fL<<12) /* Bit 16..12: Retry Count */
-#define XM_ST_EX_COL (1L<<11) /* Bit 11: Excessive Collisions */
-#define XM_ST_EX_DEF (1L<<10) /* Bit 10: Excessive Deferral */
-#define XM_ST_BURST (1L<<9) /* Bit 9: p. xmitted in burst md*/
-#define XM_ST_DEFER (1L<<8) /* Bit 8: packet was defered */
-#define XM_ST_BC (1L<<7) /* Bit 7: Broadcast packet */
-#define XM_ST_MC (1L<<6) /* Bit 6: Multicast packet */
-#define XM_ST_UC (1L<<5) /* Bit 5: Unicast packet */
-#define XM_ST_TX_UR (1L<<4) /* Bit 4: FIFO Underrun occured */
-#define XM_ST_CS_ERR (1L<<3) /* Bit 3: Carrier Sense Error */
-#define XM_ST_LAT_COL (1L<<2) /* Bit 2: Late Collision Error */
-#define XM_ST_MUL_COL (1L<<1) /* Bit 1: Multiple Collisions */
-#define XM_ST_SGN_COL (1L<<0) /* Bit 0: Single Collision */
-
-/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */
-/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */
- /* Bit 15..11: reserved */
-#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */
-
-
-/* XM_DEV_ID 32 bit r/o Device ID Register */
-#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */
-#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */
-
-
-/* XM_MODE 32 bit r/w Mode Register */
- /* Bit 31..27: reserved */
-#define XM_MD_ENA_REJ (1L<<26) /* Bit 26: Enable Frame Reject */
-#define XM_MD_SPOE_E (1L<<25) /* Bit 25: Send Pause on Edge */
- /* extern generated */
-#define XM_MD_TX_REP (1L<<24) /* Bit 24: Transmit Repeater Mode */
-#define XM_MD_SPOFF_I (1L<<23) /* Bit 23: Send Pause on FIFO full */
- /* intern generated */
-#define XM_MD_LE_STW (1L<<22) /* Bit 22: Rx Stat Word in Little Endian */
-#define XM_MD_TX_CONT (1L<<21) /* Bit 21: Send Continuous */
-#define XM_MD_TX_PAUSE (1L<<20) /* Bit 20: (sc) Send Pause Frame */
-#define XM_MD_ATS (1L<<19) /* Bit 19: Append Time Stamp */
-#define XM_MD_SPOL_I (1L<<18) /* Bit 18: Send Pause on Low */
- /* intern generated */
-#define XM_MD_SPOH_I (1L<<17) /* Bit 17: Send Pause on High */
- /* intern generated */
-#define XM_MD_CAP (1L<<16) /* Bit 16: Check Address Pair */
-#define XM_MD_ENA_HASH (1L<<15) /* Bit 15: Enable Hashing */
-#define XM_MD_CSA (1L<<14) /* Bit 14: Check Station Address */
-#define XM_MD_CAA (1L<<13) /* Bit 13: Check Address Array */
-#define XM_MD_RX_MCTRL (1L<<12) /* Bit 12: Rx MAC Control Frame */
-#define XM_MD_RX_RUNT (1L<<11) /* Bit 11: Rx Runt Frames */
-#define XM_MD_RX_IRLE (1L<<10) /* Bit 10: Rx in Range Len Err Frame */
-#define XM_MD_RX_LONG (1L<<9) /* Bit 9: Rx Long Frame */
-#define XM_MD_RX_CRCE (1L<<8) /* Bit 8: Rx CRC Error Frame */
-#define XM_MD_RX_ERR (1L<<7) /* Bit 7: Rx Error Frame */
-#define XM_MD_DIS_UC (1L<<6) /* Bit 6: Disable Rx Unicast */
-#define XM_MD_DIS_MC (1L<<5) /* Bit 5: Disable Rx Multicast */
-#define XM_MD_DIS_BC (1L<<4) /* Bit 4: Disable Rx Broadcast */
-#define XM_MD_ENA_PROM (1L<<3) /* Bit 3: Enable Promiscuous */
-#define XM_MD_ENA_BE (1L<<2) /* Bit 2: Enable Big Endian */
-#define XM_MD_FTF (1L<<1) /* Bit 1: (sc) Flush Tx FIFO */
-#define XM_MD_FRF (1L<<0) /* Bit 0: (sc) Flush Rx FIFO */
-
-#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
-#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
- XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
-
-/* XM_STAT_CMD 16 bit r/w Statistics Command Register */
- /* Bit 16..6: reserved */
-#define XM_SC_SNP_RXC (1<<5) /* Bit 5: (sc) Snap Rx Counters */
-#define XM_SC_SNP_TXC (1<<4) /* Bit 4: (sc) Snap Tx Counters */
-#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */
-#define XM_SC_CP_TXC (1<<2) /* Bit 2: Copy Tx Counters Continuously */
-#define XM_SC_CLR_RXC (1<<1) /* Bit 1: (sc) Clear Rx Counters */
-#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */
-
-
-/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */
-/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */
-#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov*/
-#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov*/
-#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov*/
-#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov*/
-#define XMR_127B_OV (1L<<27) /* Bit 27: 65-127 Byte Rx Cnt Ov */
-#define XMR_64B_OV (1L<<26) /* Bit 26: 64 Byte Rx Cnt Ov */
-#define XMR_UTIL_OV (1L<<25) /* Bit 25: Rx Util Cnt Overflow */
-#define XMR_UTIL_UR (1L<<24) /* Bit 24: Rx Util Cnt Underrun */
-#define XMR_CEX_ERR_OV (1L<<23) /* Bit 23: CEXT Err Cnt Ov */
- /* Bit 22: reserved */
-#define XMR_FCS_ERR_OV (1L<<21) /* Bit 21: Rx FCS Error Cnt Ov */
-#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov*/
-#define XMR_RUNT_OV (1L<<19) /* Bit 19: Runt Event Cnt Ov */
-#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov*/
-#define XMR_SYM_ERR_OV (1L<<17) /* Bit 17: Rx Sym Err Cnt Ov */
- /* Bit 16: reserved */
-#define XMR_CAR_ERR_OV (1L<<15) /* Bit 15: Rx Carr Ev Err Cnt Ov */
-#define XMR_JAB_PKT_OV (1L<<14) /* Bit 14: Rx Jabb Packet Cnt Ov */
-#define XMR_FIFO_OV (1L<<13) /* Bit 13: Rx FIFO Ov Ev Cnt Ov */
-#define XMR_FRA_ERR_OV (1L<<12) /* Bit 12: Rx Framing Err Cnt Ov */
-#define XMR_FMISS_OV (1L<<11) /* Bit 11: Rx Missed Ev Cnt Ov */
-#define XMR_BURST (1L<<10) /* Bit 10: Rx Burst Event Cnt Ov */
-#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov*/
-#define XMR_INV_MP (1L<<8) /* Bit 8: Rx inv Pause Frame Ov */
-#define XMR_MCTRL_OV (1L<<7) /* Bit 7: Rx MAC Ctrl-F Cnt Ov */
-#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov*/
-#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame CntOv*/
-#define XMR_MC_OK_OV (1L<<4) /* Bit 4: Rx Multicast Cnt Ov */
-#define XMR_BC_OK_OV (1L<<3) /* Bit 3: Rx Broadcast Cnt Ov */
-#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low CntOv*/
-#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK Hi Cnt Ov*/
-#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received Ok Ov */
-
-#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV)
-
-/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */
-/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */
- /* Bit 31..26: reserved */
-#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov*/
-#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov*/
-#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov*/
-#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov*/
-#define XMT_127B_OV (1L<<21) /* Bit 21: 65-127 Byte Tx Cnt Ov */
-#define XMT_64B_OV (1L<<20) /* Bit 20: 64 Byte Tx Cnt Ov */
-#define XMT_UTIL_OV (1L<<19) /* Bit 19: Tx Util Cnt Overflow */
-#define XMT_UTIL_UR (1L<<18) /* Bit 18: Tx Util Cnt Underrun */
-#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov*/
-#define XMT_FIFO_UR_OV (1L<<16) /* Bit 16: Tx FIFO Ur Ev Cnt Ov */
-#define XMT_EX_DEF_OV (1L<<15) /* Bit 15: Tx Ex Deferall Cnt Ov */
-#define XMT_DEF (1L<<14) /* Bit 14: Tx Deferred Cnt Ov */
-#define XMT_LAT_COL_OV (1L<<13) /* Bit 13: Tx Late Col Cnt Ov */
-#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov*/
-#define XMT_MUL_COL_OV (1L<<11) /* Bit 11: Tx Mult Col Cnt Ov */
-#define XMT_SNG_COL (1L<<10) /* Bit 10: Tx Single Col Cnt Ov */
-#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov*/
-#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov*/
-#define XMT_BURST (1L<<7) /* Bit 7: Tx Burst Event Cnt Ov */
-#define XMT_LONG (1L<<6) /* Bit 6: Tx Long Frame Cnt Ov */
-#define XMT_UC_OK_OV (1L<<5) /* Bit 5: Tx Unicast Cnt Ov */
-#define XMT_MC_OK_OV (1L<<4) /* Bit 4: Tx Multicast Cnt Ov */
-#define XMT_BC_OK_OV (1L<<3) /* Bit 3: Tx Broadcast Cnt Ov */
-#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low CntOv*/
-#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK Hi Cnt Ov*/
-#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx Ok Ov */
-
-#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV)
-
-/*
- * Receive Frame Status Encoding
- */
-#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */
-#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/
-#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/
-#define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */
-#define XMR_FS_MC (1L<<14) /* Bit 14: Multicast Frame */
-#define XMR_FS_UC (1L<<13) /* Bit 13: Unicast Frame */
- /* Bit 12: reserved */
-#define XMR_FS_BURST (1L<<11) /* Bit 11: Burst Mode */
-#define XMR_FS_CEX_ERR (1L<<10) /* Bit 10: Carrier Ext. Error */
-#define XMR_FS_802_3 (1L<<9) /* Bit 9: 802.3 Frame */
-#define XMR_FS_COL_ERR (1L<<8) /* Bit 8: Collision Error */
-#define XMR_FS_CAR_ERR (1L<<7) /* Bit 7: Carrier Event Error */
-#define XMR_FS_LEN_ERR (1L<<6) /* Bit 6: In-Range Length Error */
-#define XMR_FS_FRA_ERR (1L<<5) /* Bit 5: Framing Error */
-#define XMR_FS_RUNT (1L<<4) /* Bit 4: Runt Frame */
-#define XMR_FS_LNG_ERR (1L<<3) /* Bit 3: Giant (Jumbo) Frame */
-#define XMR_FS_FCS_ERR (1L<<2) /* Bit 2: Frame Check Sequ Err */
-#define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */
-#define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */
-
-/*
- * XMR_FS_ERR will be set if
- * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
- * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
- * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
- * XMR_FS_ERR unless the corresponding bit in the Receive Command
- * Register is set.
- */
-#define XMR_FS_ANY_ERR XMR_FS_ERR
-
-/*----------------------------------------------------------------------------*/
-/*
- * XMAC-PHY Registers, indirect addressed over the XMAC
- */
-#define PHY_XMAC_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_XMAC_STAT 0x01 /* 16 bit r/w PHY Status Register */
-#define PHY_XMAC_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_XMAC_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_XMAC_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */
-#define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
- /* 0x09 - 0x0e: reserved */
-#define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */
-#define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Broadcom-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_BCOM_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_BCOM_STAT 0x01 /* 16 bit r/o PHY Status Register */
-#define PHY_BCOM_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_BCOM_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_BCOM_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
-#define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
- /* Broadcom-specific registers */
-#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */
-#define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
- /* 0x0b - 0x0e: reserved */
-#define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
-#define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */
-#define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */
-#define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */
-#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carrier Sense Cnt */
-#define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */
- /* 0x15 - 0x17: reserved */
-#define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */
-#define PHY_BCOM_AUX_STAT 0x19 /* 16 bit r/o Auxiliary Stat Summary */
-#define PHY_BCOM_INT_STAT 0x1a /* 16 bit r/o Interrupt Status Reg */
-#define PHY_BCOM_INT_MASK 0x1b /* 16 bit r/w Interrupt Mask Reg */
- /* 0x1c: reserved */
- /* 0x1d - 0x1f: test registers */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Marvel-PHY Registers, indirect addressed over GMAC
- */
-#define PHY_MARV_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_MARV_STAT 0x01 /* 16 bit r/o PHY Status Register */
-#define PHY_MARV_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_MARV_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_MARV_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
-#define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
- /* Marvel-specific registers */
-#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */
-#define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
- /* 0x0b - 0x0e: reserved */
-#define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
-#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */
-#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */
-#define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */
-#define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */
-#define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */
-#define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */
-#define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */
- /* 0x17: reserved */
-#define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */
-#define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */
-#define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */
-#define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */
-#define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */
- /* 0x1d - 0x1f: reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * Level One-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_LONE_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_LONE_STAT 0x01 /* 16 bit r/o PHY Status Register */
-#define PHY_LONE_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_LONE_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_LONE_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */
-#define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
- /* Level One-specific registers */
-#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/
-#define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
- /* 0x0b -0x0e: reserved */
-#define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
-#define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/
-#define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */
-#define PHY_LONE_INT_ENAB 0x12 /* 16 bit r/w Interrupt Enable Reg */
-#define PHY_LONE_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */
-#define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */
-#define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */
-#define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */
- /* 0x17 -0x1c: reserved */
-
-/*----------------------------------------------------------------------------*/
-/*
- * National-PHY Registers, indirect addressed over XMAC
- */
-#define PHY_NAT_CTRL 0x00 /* 16 bit r/w PHY Control Register */
-#define PHY_NAT_STAT 0x01 /* 16 bit r/w PHY Status Register */
-#define PHY_NAT_ID0 0x02 /* 16 bit r/o PHY ID0 Register */
-#define PHY_NAT_ID1 0x03 /* 16 bit r/o PHY ID1 Register */
-#define PHY_NAT_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */
-#define PHY_NAT_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */
-#define PHY_NAT_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */
-#define PHY_NAT_NEPG 0x07 /* 16 bit r/w Next Page Register */
-#define PHY_NAT_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner Reg */
- /* National-specific registers */
-#define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */
-#define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
- /* 0x0b -0x0e: reserved */
-#define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */
-#define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */
-#define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */
-#define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */
-#define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */
-#define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */
- /* 0x15 -0x18: reserved */
-#define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */
-
-
-/*----------------------------------------------------------------------------*/
-
-/*
- * PHY bit definitions
- * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are
- * XMAC/Broadcom/LevelOne/National/Marvell-specific.
- * All other are general.
- */
-
-/***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/
-/***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/
-/***** PHY_MARV_CTRL 16 bit r/w PHY Status Register *****/
-/***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/
-#define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */
-#define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */
-#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */
-#define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */
-#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */
-#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */
-#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */
-#define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */
-#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */
-#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */
- /* Bit 5..0: reserved */
-
-#define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */
-#define PHY_CT_SP100 PHY_CT_SPS_LSB /* enable speed of 100 Mbps */
-#define PHY_CT_SP10 (0) /* enable speed of 10 Mbps */
-
-
-/***** PHY_XMAC_STAT 16 bit r/w PHY Status Register *****/
-/***** PHY_BCOM_STAT 16 bit r/w PHY Status Register *****/
-/***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/
-/***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/
- /* Bit 15..9: reserved */
- /* (BC/L1) 100/10 Mbps cap bits ignored*/
-#define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */
- /* Bit 7: reserved */
-#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */
-#define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */
-#define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */
-#define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */
-#define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */
-#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */
-#define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */
-
-
-/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */
-/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */
-/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */
-/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */
-#define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */
-#define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */
-#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */
-
-/* different Broadcom PHY Ids */
-#define PHY_BCOM_ID1_A1 0x6041
-#define PHY_BCOM_ID1_B2 0x6043
-#define PHY_BCOM_ID1_C0 0x6044
-#define PHY_BCOM_ID1_C5 0x6047
-
-
-/***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-#define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */
-#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */
-#define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */
- /* Bit 11.. 9: reserved */
-#define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */
-#define PHY_X_AN_HD (1<<6) /* Bit 6: Half Duplex */
-#define PHY_X_AN_FD (1<<5) /* Bit 5: Full Duplex */
- /* Bit 4.. 0: reserved */
-
-/***** PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
- /* Bit 14: reserved */
-#define PHY_B_AN_RF (1<<13) /* Bit 13: Remote Fault */
- /* Bit 12: reserved */
-#define PHY_B_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */
-#define PHY_B_AN_PC (1<<10) /* Bit 10: Pause Capable */
- /* Bit 9..5: 100/10 BT cap bits ingnored */
-#define PHY_B_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
-
-/***** PHY_LONE_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_LONE_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
- /* Bit 14: reserved */
-#define PHY_L_AN_RF (1<<13) /* Bit 13: Remote Fault */
- /* Bit 12: reserved */
-#define PHY_L_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */
-#define PHY_L_AN_PC (1<<10) /* Bit 10: Pause Capable */
- /* Bit 9..5: 100/10 BT cap bits ingnored */
-#define PHY_L_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
-
-/***** PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
-/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
- /* Bit 14: reserved */
-#define PHY_N_AN_RF (1<<13) /* Bit 13: Remote Fault */
- /* Bit 12: reserved */
-#define PHY_N_AN_100F (1<<11) /* Bit 11: 100Base-T2 FD Support */
-#define PHY_N_AN_100H (1<<10) /* Bit 10: 100Base-T2 HD Support */
- /* Bit 9..5: 100/10 BT cap bits ingnored */
-#define PHY_N_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/
-
-/* field type definition for PHY_x_AN_SEL */
-#define PHY_SEL_TYPE 0x01 /* 00001 = Ethernet */
-
-/***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
- /* Bit 15..4: reserved */
-#define PHY_ANE_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */
-#define PHY_ANE_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */
-#define PHY_ANE_RX_PG (1<<1) /* Bit 1: Page Received */
- /* Bit 0: reserved */
-
-/***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
-/***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
-/***** PHY_MARV_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/
- /* Bit 15..5: reserved */
-#define PHY_ANE_PAR_DF (1<<4) /* Bit 4: Parallel Detection Fault */
-/* PHY_ANE_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */
-/* PHY_ANE_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */
-/* PHY_ANE_RX_PG (see XMAC) Bit 1: Page Received */
-#define PHY_ANE_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */
-
-/***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/
-/***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/
-/***** PHY_LONE_NEPG 16 bit r/w Next Page Register *****/
-/***** PHY_XMAC_NEPG_LP 16 bit r/o Next Page Link Partner *****/
-/***** PHY_BCOM_NEPG_LP 16 bit r/o Next Page Link Partner *****/
-/***** PHY_LONE_NEPG_LP 16 bit r/o Next Page Link Partner *****/
-#define PHY_NP_MORE (1<<15) /* Bit 15: More, Next Pages to follow */
-#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack1, for receiving a message */
-#define PHY_NP_MSG_VAL (1<<13) /* Bit 13: Message Page valid */
-#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack2, comply with msg content */
-#define PHY_NP_TOG (1<<11) /* Bit 11: Toggle Bit, ensure sync */
-#define PHY_NP_MSG 0x07ff /* Bit 10..0: Message from/to Link Partner */
-
-/*
- * XMAC-Specific
- */
-/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/
-#define PHY_X_EX_FD (1<<15) /* Bit 15: Device Supports Full Duplex */
-#define PHY_X_EX_HD (1<<14) /* Bit 14: Device Supports Half Duplex */
- /* Bit 13..0: reserved */
-
-/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/
- /* Bit 15..9: reserved */
-#define PHY_X_RS_PAUSE (3<<7) /* Bit 8..7: selected Pause Mode */
-#define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */
-#define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */
-#define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */
-#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability mismatch */
- /* Bit 2..0: reserved */
-/*
- * Remote Fault Bits (PHY_X_AN_RFB) encoding
- */
-#define X_RFB_OK (0<<12) /* Bit 13..12 No errors, Link OK */
-#define X_RFB_LF (1<<12) /* Bit 13..12 Link Failure */
-#define X_RFB_OFF (2<<12) /* Bit 13..12 Offline */
-#define X_RFB_AN_ERR (3<<12) /* Bit 13..12 Auto-Negotiation Error */
-
-/*
- * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding
- */
-#define PHY_X_P_NO_PAUSE (0<<7) /* Bit 8..7: no Pause Mode */
-#define PHY_X_P_SYM_MD (1<<7) /* Bit 8..7: symmetric Pause Mode */
-#define PHY_X_P_ASYM_MD (2<<7) /* Bit 8..7: asymmetric Pause Mode */
-#define PHY_X_P_BOTH_MD (3<<7) /* Bit 8..7: both Pause Mode */
-
-
-/*
- * Broadcom-Specific
- */
-/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-#define PHY_B_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
-#define PHY_B_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
-#define PHY_B_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
-#define PHY_B_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
-#define PHY_B_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
-#define PHY_B_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
- /* Bit 7..0: reserved */
-
-/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-#define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
-#define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
-#define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
-#define PHY_B_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */
-#define PHY_B_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
-#define PHY_B_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
- /* Bit 9..8: reserved */
-#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
-
-/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/
-#define PHY_B_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
-#define PHY_B_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
-#define PHY_B_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
-#define PHY_B_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
- /* Bit 11..0: reserved */
-
-/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/
-#define PHY_B_PEC_MAC_PHY (1<<15) /* Bit 15: 10BIT/GMI-Interface */
-#define PHY_B_PEC_DIS_CROSS (1<<14) /* Bit 14: Disable MDI Crossover */
-#define PHY_B_PEC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */
-#define PHY_B_PEC_INT_DIS (1<<12) /* Bit 12: Interrupts Disabled */
-#define PHY_B_PEC_F_INT (1<<11) /* Bit 11: Force Interrupt */
-#define PHY_B_PEC_BY_45 (1<<10) /* Bit 10: Bypass 4B5B-Decoder */
-#define PHY_B_PEC_BY_SCR (1<<9) /* Bit 9: Bypass Scrambler */
-#define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */
-#define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */
-#define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */
-#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */
-#define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */
-#define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */
-#define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */
-#define PHY_B_PEC_3_LED (1<<1) /* Bit 1: Three Link LED mode */
-#define PHY_B_PEC_HIGH_LA (1<<0) /* Bit 0: GMII FIFO Elasticy */
-
-/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/
- /* Bit 15..14: reserved */
-#define PHY_B_PES_CROSS_STAT (1<<13) /* Bit 13: MDI Crossover Status */
-#define PHY_B_PES_INT_STAT (1<<12) /* Bit 12: Interrupt Status */
-#define PHY_B_PES_RRS (1<<11) /* Bit 11: Remote Receiver Stat. */
-#define PHY_B_PES_LRS (1<<10) /* Bit 10: Local Receiver Stat. */
-#define PHY_B_PES_LOCKED (1<<9) /* Bit 9: Locked */
-#define PHY_B_PES_LS (1<<8) /* Bit 8: Link Status */
-#define PHY_B_PES_RF (1<<7) /* Bit 7: Remote Fault */
-#define PHY_B_PES_CE_ER (1<<6) /* Bit 6: Carrier Ext Error */
-#define PHY_B_PES_BAD_SSD (1<<5) /* Bit 5: Bad SSD */
-#define PHY_B_PES_BAD_ESD (1<<4) /* Bit 4: Bad ESD */
-#define PHY_B_PES_RX_ER (1<<3) /* Bit 3: Receive Error */
-#define PHY_B_PES_TX_ER (1<<2) /* Bit 2: Transmit Error */
-#define PHY_B_PES_LOCK_ER (1<<1) /* Bit 1: Lock Error */
-#define PHY_B_PES_MLT3_ER (1<<0) /* Bit 0: MLT3 code Error */
-
-/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/
- /* Bit 15..8: reserved */
-#define PHY_B_FC_CTR 0xff /* Bit 7..0: False Carrier Counter */
-
-/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/
-#define PHY_B_RC_LOC_MSK 0xff00 /* Bit 15..8: Local Rx NOT_OK cnt */
-#define PHY_B_RC_REM_MSK 0x00ff /* Bit 7..0: Remote Rx NOT_OK cnt */
-
-/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/
-#define PHY_B_AC_L_SQE (1<<15) /* Bit 15: Low Squelch */
-#define PHY_B_AC_LONG_PACK (1<<14) /* Bit 14: Rx Long Packets */
-#define PHY_B_AC_ER_CTRL (3<<12) /* Bit 13..12: Edgerate Control */
- /* Bit 11: reserved */
-#define PHY_B_AC_TX_TST (1<<10) /* Bit 10: Tx test bit, always 1 */
- /* Bit 9.. 8: reserved */
-#define PHY_B_AC_DIS_PRF (1<<7) /* Bit 7: dis part resp filter */
- /* Bit 6: reserved */
-#define PHY_B_AC_DIS_PM (1<<5) /* Bit 5: dis power management */
- /* Bit 4: reserved */
-#define PHY_B_AC_DIAG (1<<3) /* Bit 3: Diagnostic Mode */
- /* Bit 2.. 0: reserved */
-
-/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/
-#define PHY_B_AS_AN_C (1<<15) /* Bit 15: AutoNeg complete */
-#define PHY_B_AS_AN_CA (1<<14) /* Bit 14: AN Complete Ack */
-#define PHY_B_AS_ANACK_D (1<<13) /* Bit 13: AN Ack Detect */
-#define PHY_B_AS_ANAB_D (1<<12) /* Bit 12: AN Ability Detect */
-#define PHY_B_AS_NPW (1<<11) /* Bit 11: AN Next Page Wait */
-#define PHY_B_AS_AN_RES_MSK (7<<8) /* Bit 10..8: AN HDC */
-#define PHY_B_AS_PDF (1<<7) /* Bit 7: Parallel Detect. Fault */
-#define PHY_B_AS_RF (1<<6) /* Bit 6: Remote Fault */
-#define PHY_B_AS_ANP_R (1<<5) /* Bit 5: AN Page Received */
-#define PHY_B_AS_LP_ANAB (1<<4) /* Bit 4: LP AN Ability */
-#define PHY_B_AS_LP_NPAB (1<<3) /* Bit 3: LP Next Page Ability */
-#define PHY_B_AS_LS (1<<2) /* Bit 2: Link Status */
-#define PHY_B_AS_PRR (1<<1) /* Bit 1: Pause Resolution-Rx */
-#define PHY_B_AS_PRT (1<<0) /* Bit 0: Pause Resolution-Tx */
-
-#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT)
-
-/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/
-/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
- /* Bit 15: reserved */
-#define PHY_B_IS_PSE (1<<14) /* Bit 14: Pair Swap Error */
-#define PHY_B_IS_MDXI_SC (1<<13) /* Bit 13: MDIX Status Change */
-#define PHY_B_IS_HCT (1<<12) /* Bit 12: counter above 32k */
-#define PHY_B_IS_LCT (1<<11) /* Bit 11: counter above 128 */
-#define PHY_B_IS_AN_PR (1<<10) /* Bit 10: Page Received */
-#define PHY_B_IS_NO_HDCL (1<<9) /* Bit 9: No HCD Link */
-#define PHY_B_IS_NO_HDC (1<<8) /* Bit 8: No HCD */
-#define PHY_B_IS_NEG_USHDC (1<<7) /* Bit 7: Negotiated Unsup. HCD */
-#define PHY_B_IS_SCR_S_ER (1<<6) /* Bit 6: Scrambler Sync Error */
-#define PHY_B_IS_RRS_CHANGE (1<<5) /* Bit 5: Remote Rx Stat Change */
-#define PHY_B_IS_LRS_CHANGE (1<<4) /* Bit 4: Local Rx Stat Change */
-#define PHY_B_IS_DUP_CHANGE (1<<3) /* Bit 3: Duplex Mode Change */
-#define PHY_B_IS_LSP_CHANGE (1<<2) /* Bit 2: Link Speed Change */
-#define PHY_B_IS_LST_CHANGE (1<<1) /* Bit 1: Link Status Changed */
-#define PHY_B_IS_CRC_ER (1<<0) /* Bit 0: CRC Error */
-
-#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
-
-/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
-#define PHY_B_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */
-#define PHY_B_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */
-#define PHY_B_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */
-#define PHY_B_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */
-
-/*
- * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
- */
-#define PHY_B_RES_1000FD (7<<8) /* Bit 10..8: 1000Base-T Full Dup. */
-#define PHY_B_RES_1000HD (6<<8) /* Bit 10..8: 1000Base-T Half Dup. */
-/* others: 100/10: invalid for us */
-
-/*
- * Level One-Specific
- */
-/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-#define PHY_L_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
-#define PHY_L_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
-#define PHY_L_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
-#define PHY_L_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
-#define PHY_L_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
-#define PHY_L_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
- /* Bit 7..0: reserved */
-
-/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-#define PHY_L_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
-#define PHY_L_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
-#define PHY_L_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
-#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */
-#define PHY_L_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
-#define PHY_L_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
- /* Bit 9..8: reserved */
-#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
-
-/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/
-#define PHY_L_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
-#define PHY_L_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
-#define PHY_L_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
-#define PHY_L_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
- /* Bit 11..0: reserved */
-
-/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/
-#define PHY_L_PC_REP_MODE (1<<15) /* Bit 15: Repeater Mode */
- /* Bit 14: reserved */
-#define PHY_L_PC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */
-#define PHY_L_PC_BY_SCR (1<<12) /* Bit 12: Bypass Scrambler */
-#define PHY_L_PC_BY_45 (1<<11) /* Bit 11: Bypass 4B5B-Decoder */
-#define PHY_L_PC_JAB_DIS (1<<10) /* Bit 10: Jabber Disabled */
-#define PHY_L_PC_SQE (1<<9) /* Bit 9: Enable Heartbeat */
-#define PHY_L_PC_TP_LOOP (1<<8) /* Bit 8: TP Loopback */
-#define PHY_L_PC_SSS (1<<7) /* Bit 7: Smart Speed Selection */
-#define PHY_L_PC_FIFO_SIZE (1<<6) /* Bit 6: FIFO Size */
-#define PHY_L_PC_PRE_EN (1<<5) /* Bit 5: Preamble Enable */
-#define PHY_L_PC_CIM (1<<4) /* Bit 4: Carrier Integrity Mon */
-#define PHY_L_PC_10_SER (1<<3) /* Bit 3: Use Serial Output */
-#define PHY_L_PC_ANISOL (1<<2) /* Bit 2: Unisolate Port */
-#define PHY_L_PC_TEN_BIT (1<<1) /* Bit 1: 10bit iface mode on */
-#define PHY_L_PC_ALTCLOCK (1<<0) /* Bit 0: (ro) ALTCLOCK Mode on */
-
-/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/
-#define PHY_L_QS_D_RATE (3<<14) /* Bit 15..14: Data Rate */
-#define PHY_L_QS_TX_STAT (1<<13) /* Bit 13: Transmitting */
-#define PHY_L_QS_RX_STAT (1<<12) /* Bit 12: Receiving */
-#define PHY_L_QS_COL_STAT (1<<11) /* Bit 11: Collision */
-#define PHY_L_QS_L_STAT (1<<10) /* Bit 10: Link is up */
-#define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */
-#define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */
-#define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */
-#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */
-#define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */
-#define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */
-#define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */
-#define PHY_L_QS_EVENT (1<<0) /* Bit 0: Event has occurred */
-
-/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/
-/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/
- /* Bit 15..14: reserved */
-#define PHY_L_IS_AN_F (1<<13) /* Bit 13: Auto-Negotiation fault */
- /* Bit 12: not described */
-#define PHY_L_IS_CROSS (1<<11) /* Bit 11: Crossover used */
-#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used */
-#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade */
-#define PHY_L_IS_CFULL (1<<8) /* Bit 8: Counter Full */
-#define PHY_L_IS_AN_C (1<<7) /* Bit 7: AutoNeg Complete */
-#define PHY_L_IS_SPEED (1<<6) /* Bit 6: Speed Changed */
-#define PHY_L_IS_DUP (1<<5) /* Bit 5: Duplex Changed */
-#define PHY_L_IS_LS (1<<4) /* Bit 4: Link Status Changed */
-#define PHY_L_IS_ISOL (1<<3) /* Bit 3: Isolate Occured */
-#define PHY_L_IS_MDINT (1<<2) /* Bit 2: (ro) STAT: MII Int Pending */
-#define PHY_L_IS_INTEN (1<<1) /* Bit 1: ENAB: Enable IRQs */
-#define PHY_L_IS_FORCE (1<<0) /* Bit 0: ENAB: Force Interrupt */
-
-/* int. mask */
-#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
-
-/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/
-#define PHY_L_LC_LEDC (3<<14) /* Bit 15..14: Col/Blink/On/Off */
-#define PHY_L_LC_LEDR (3<<12) /* Bit 13..12: Rx/Blink/On/Off */
-#define PHY_L_LC_LEDT (3<<10) /* Bit 11..10: Tx/Blink/On/Off */
-#define PHY_L_LC_LEDG (3<<8) /* Bit 9..8: Giga/Blink/On/Off */
-#define PHY_L_LC_LEDS (3<<6) /* Bit 7..6: 10-100/Blink/On/Off */
-#define PHY_L_LC_LEDL (3<<4) /* Bit 5..4: Link/Blink/On/Off */
-#define PHY_L_LC_LEDF (3<<2) /* Bit 3..2: Duplex/Blink/On/Off */
-#define PHY_L_LC_PSTRECH (1<<1) /* Bit 1: Strech LED Pulses */
-#define PHY_L_LC_FREQ (1<<0) /* Bit 0: 30/100 ms */
-
-/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/
-#define PHY_L_PC_TX_TCLK (1<<15) /* Bit 15: Enable TX_TCLK */
- /* Bit 14: reserved */
-#define PHY_L_PC_ALT_NP (1<<13) /* Bit 14: Alternate Next Page */
-#define PHY_L_PC_GMII_ALT (1<<12) /* Bit 13: Alternate GMII driver */
- /* Bit 11: reserved */
-#define PHY_L_PC_TEN_CRS (1<<10) /* Bit 10: Extend CRS*/
- /* Bit 9..0: not described */
-
-/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/
-#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */
-#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */
-
-
-/*
- * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
- */
-#define PHY_L_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */
-#define PHY_L_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */
-#define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */
-#define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */
-
-
-/*
- * National-Specific
- */
-/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-#define PHY_N_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
-#define PHY_N_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */
-#define PHY_N_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */
-#define PHY_N_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */
-#define PHY_N_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
-#define PHY_N_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
-#define PHY_N_1000C_APC (1<<7) /* Bit 7: Asymmetric Pause Cap. */
- /* Bit 6..0: reserved */
-
-/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
-#define PHY_N_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */
-#define PHY_N_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */
-#define PHY_N_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */
-#define PHY_N_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/
-#define PHY_N_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */
-#define PHY_N_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */
-#define PHY_N_1000C_LP_APC (1<<9) /* Bit 9: LP Asym. Pause Cap. */
- /* Bit 8: reserved */
-#define PHY_N_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */
-
-/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/
-#define PHY_N_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */
-#define PHY_N_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */
-#define PHY_N_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */
-#define PHY_N_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */
- /* Bit 11..0: reserved */
-
-/* todo: those are still missing */
-/***** PHY_NAT_EXT_CTRL1 16 bit r/o Extended Control Reg1 *****/
-/***** PHY_NAT_Q_STAT1 16 bit r/o Quick Status Reg1 *****/
-/***** PHY_NAT_10B_OP 16 bit r/o 10Base-T Operations Reg *****/
-/***** PHY_NAT_EXT_CTRL2 16 bit r/o Extended Control Reg1 *****/
-/***** PHY_NAT_Q_STAT2 16 bit r/o Quick Status Reg2 *****/
-/***** PHY_NAT_PHY_ADDR 16 bit r/o PHY Address Register *****/
-
-/*
- * Marvell-Specific
- */
-/***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
-/***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/
-#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */
-#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */
-#define PHY_M_AN_RF BIT_13 /* Remote Fault */
- /* Bit 12: reserved */
-#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */
-#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */
-#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */
-#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */
-#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */
-#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */
-
-/* special defines for FIBER (88E1011S only) */
-#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */
-#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */
-#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */
-#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */
-
-/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
-#define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */
-#define PHY_M_P_SYM_MD_X (1<<7) /* Bit 8.. 7: symmetric Pause Mode */
-#define PHY_M_P_ASYM_MD_X (2<<7) /* Bit 8.. 7: asymmetric Pause Mode */
-#define PHY_M_P_BOTH_MD_X (3<<7) /* Bit 8.. 7: both Pause Mode */
-
-/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
-#define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
-#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */
-#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */
-#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */
-#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
-#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
- /* Bit 7..0: reserved */
-
-/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/
-#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */
-#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */
-#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */
-#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */
-#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */
-#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */
-#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */
-#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */
-#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */
-#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */
-#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */
-#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */
-
-#define PHY_M_PC_EN_DET SHIFT8(2) /* Energy Detect (Mode 1) */
-#define PHY_M_PC_EN_DET_PLUS SHIFT8(3) /* Energy Detect Plus (Mode 2) */
-
-#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x)
-#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */
-#define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */
-#define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */
-
-/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/
-#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */
-#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */
-#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */
-#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */
-#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */
-#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */
-#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */
-#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */
-#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */
-#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */
-#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */
-#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */
-#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */
-#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */
-#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */
-#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */
-
-#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
-
-/***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
-/***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/
-#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */
-#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */
-#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */
-#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */
-#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */
-#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */
-#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */
-#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */
-#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */
-#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */
-#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */
-#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */
- /* Bit 3..2: reserved */
-#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */
-#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */
-
-#define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
- PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
-
-/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
-#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */
-#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */
-#define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */
-#define PHY_M_EC_FIB_AN_ENA (1<<3) /* Bit 3: Fiber Auto-Neg. Enable */
-
-#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */
-#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */
-#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */
-
-#define MAC_TX_CLK_0_MHZ 2
-#define MAC_TX_CLK_2_5_MHZ 6
-#define MAC_TX_CLK_25_MHZ 7
-
-/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/
-#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */
-#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */
-#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */
-#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */
- /* Bit 7.. 5: reserved */
-#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */
-#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */
-#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */
-#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */
-
-#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */
-
-#define PULS_NO_STR 0 /* no pulse stretching */
-#define PULS_21MS 1 /* 21 ms to 42 ms */
-#define PULS_42MS 2 /* 42 ms to 84 ms */
-#define PULS_84MS 3 /* 84 ms to 170 ms */
-#define PULS_170MS 4 /* 170 ms to 340 ms */
-#define PULS_340MS 5 /* 340 ms to 670 ms */
-#define PULS_670MS 6 /* 670 ms to 1.3 s */
-#define PULS_1300MS 7 /* 1.3 s to 2.7 s */
-
-#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */
-
-#define BLINK_42MS 0 /* 42 ms */
-#define BLINK_84MS 1 /* 84 ms */
-#define BLINK_170MS 2 /* 170 ms */
-#define BLINK_340MS 3 /* 340 ms */
-#define BLINK_670MS 4 /* 670 ms */
- /* values 5 - 7: reserved */
-
-/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/
-#define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */
-#define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */
-#define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */
-#define PHY_M_LED_MO_1000(x) SHIFT4(x) /* Bit 5.. 4: Link 1000 */
-#define PHY_M_LED_MO_RX(x) SHIFT2(x) /* Bit 3.. 2: Rx */
-#define PHY_M_LED_MO_TX(x) SHIFT0(x) /* Bit 1.. 0: Tx */
-
-#define MO_LED_NORM 0
-#define MO_LED_BLINK 1
-#define MO_LED_OFF 2
-#define MO_LED_ON 3
-
-/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/
- /* Bit 15.. 7: reserved */
-#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */
-#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */
-#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */
-#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */
-#define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */
-
-/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
-#define PHY_M_FC_AUTO_SEL (1<<15) /* Bit 15: Fiber/Copper Auto Sel. dis. */
-#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14: Fiber/Copper Autoneg. reg acc */
-#define PHY_M_FC_RESULUTION (1<<13) /* Bit 13: Fiber/Copper Resulution */
-#define PHY_M_SER_IF_AN_BP (1<<12) /* Bit 12: Ser IF autoneg. bypass enable */
-#define PHY_M_SER_IF_BP_ST (1<<11) /* Bit 11: Ser IF autoneg. bypass status */
-#define PHY_M_IRQ_POLARITY (1<<10) /* Bit 10: IRQ polarity */
- /* Bit 9..4: reserved */
-#define PHY_M_UNDOC1 (1<< 7) /* undocumented bit !! */
-#define PHY_M_MODE_MASK (0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */
-
-
-/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/
-#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */
-#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */
- /* Bit 12.. 8: reserved */
-#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */
-
-/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
-#define CABD_STAT_NORMAL 0
-#define CABD_STAT_SHORT 1
-#define CABD_STAT_OPEN 2
-#define CABD_STAT_FAIL 3
-
-
-/*
- * GMAC registers
- *
- * The GMAC registers are 16 or 32 bits wide.
- * The GMACs host processor interface is 16 bits wide,
- * therefore ALL registers will be addressed with 16 bit accesses.
- *
- * The following macros are provided to access the GMAC registers
- * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(),
- * GM_INHASH(), and GM_OUTHASH().
- * The macros are defined in SkGeHw.h.
- *
- * Note: NA reg = Network Address e.g DA, SA etc.
- *
- */
-
-/* Port Registers */
-#define GM_GP_STAT 0x0000 /* 16 bit r/o General Purpose Status */
-#define GM_GP_CTRL 0x0004 /* 16 bit r/w General Purpose Control */
-#define GM_TX_CTRL 0x0008 /* 16 bit r/w Transmit Control Reg. */
-#define GM_RX_CTRL 0x000c /* 16 bit r/w Receive Control Reg. */
-#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow-Control */
-#define GM_TX_PARAM 0x0014 /* 16 bit r/w Transmit Parameter Reg. */
-#define GM_SERIAL_MODE 0x0018 /* 16 bit r/w Serial Mode Register */
-
-/* Source Address Registers */
-#define GM_SRC_ADDR_1L 0x001c /* 16 bit r/w Source Address 1 (low) */
-#define GM_SRC_ADDR_1M 0x0020 /* 16 bit r/w Source Address 1 (middle) */
-#define GM_SRC_ADDR_1H 0x0024 /* 16 bit r/w Source Address 1 (high) */
-#define GM_SRC_ADDR_2L 0x0028 /* 16 bit r/w Source Address 2 (low) */
-#define GM_SRC_ADDR_2M 0x002c /* 16 bit r/w Source Address 2 (middle) */
-#define GM_SRC_ADDR_2H 0x0030 /* 16 bit r/w Source Address 2 (high) */
-
-/* Multicast Address Hash Registers */
-#define GM_MC_ADDR_H1 0x0034 /* 16 bit r/w Multicast Address Hash 1 */
-#define GM_MC_ADDR_H2 0x0038 /* 16 bit r/w Multicast Address Hash 2 */
-#define GM_MC_ADDR_H3 0x003c /* 16 bit r/w Multicast Address Hash 3 */
-#define GM_MC_ADDR_H4 0x0040 /* 16 bit r/w Multicast Address Hash 4 */
-
-/* Interrupt Source Registers */
-#define GM_TX_IRQ_SRC 0x0044 /* 16 bit r/o Tx Overflow IRQ Source */
-#define GM_RX_IRQ_SRC 0x0048 /* 16 bit r/o Rx Overflow IRQ Source */
-#define GM_TR_IRQ_SRC 0x004c /* 16 bit r/o Tx/Rx Over. IRQ Source */
-
-/* Interrupt Mask Registers */
-#define GM_TX_IRQ_MSK 0x0050 /* 16 bit r/w Tx Overflow IRQ Mask */
-#define GM_RX_IRQ_MSK 0x0054 /* 16 bit r/w Rx Overflow IRQ Mask */
-#define GM_TR_IRQ_MSK 0x0058 /* 16 bit r/w Tx/Rx Over. IRQ Mask */
-
-/* Serial Management Interface (SMI) Registers */
-#define GM_SMI_CTRL 0x0080 /* 16 bit r/w SMI Control Register */
-#define GM_SMI_DATA 0x0084 /* 16 bit r/w SMI Data Register */
-#define GM_PHY_ADDR 0x0088 /* 16 bit r/w GPHY Address Register */
-
-/* MIB Counters */
-#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */
-#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */
-
-/*
- * MIB Counters base address definitions (low word) -
- * use offset 4 for access to high word (32 bit r/o)
- */
-#define GM_RXF_UC_OK \
- (GM_MIB_CNT_BASE + 0) /* Unicast Frames Received OK */
-#define GM_RXF_BC_OK \
- (GM_MIB_CNT_BASE + 8) /* Broadcast Frames Received OK */
-#define GM_RXF_MPAUSE \
- (GM_MIB_CNT_BASE + 16) /* Pause MAC Ctrl Frames Received */
-#define GM_RXF_MC_OK \
- (GM_MIB_CNT_BASE + 24) /* Multicast Frames Received OK */
-#define GM_RXF_FCS_ERR \
- (GM_MIB_CNT_BASE + 32) /* Rx Frame Check Seq. Error */
- /* GM_MIB_CNT_BASE + 40: reserved */
-#define GM_RXO_OK_LO \
- (GM_MIB_CNT_BASE + 48) /* Octets Received OK Low */
-#define GM_RXO_OK_HI \
- (GM_MIB_CNT_BASE + 56) /* Octets Received OK High */
-#define GM_RXO_ERR_LO \
- (GM_MIB_CNT_BASE + 64) /* Octets Received Invalid Low */
-#define GM_RXO_ERR_HI \
- (GM_MIB_CNT_BASE + 72) /* Octets Received Invalid High */
-#define GM_RXF_SHT \
- (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */
-#define GM_RXE_FRAG \
- (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Received with FCS Err */
-#define GM_RXF_64B \
- (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */
-#define GM_RXF_127B \
- (GM_MIB_CNT_BASE + 104) /* 65-127 Byte Rx Frame */
-#define GM_RXF_255B \
- (GM_MIB_CNT_BASE + 112) /* 128-255 Byte Rx Frame */
-#define GM_RXF_511B \
- (GM_MIB_CNT_BASE + 120) /* 256-511 Byte Rx Frame */
-#define GM_RXF_1023B \
- (GM_MIB_CNT_BASE + 128) /* 512-1023 Byte Rx Frame */
-#define GM_RXF_1518B \
- (GM_MIB_CNT_BASE + 136) /* 1024-1518 Byte Rx Frame */
-#define GM_RXF_MAX_SZ \
- (GM_MIB_CNT_BASE + 144) /* 1519-MaxSize Byte Rx Frame */
-#define GM_RXF_LNG_ERR \
- (GM_MIB_CNT_BASE + 152) /* Rx Frame too Long Error */
-#define GM_RXF_JAB_PKT \
- (GM_MIB_CNT_BASE + 160) /* Rx Jabber Packet Frame */
- /* GM_MIB_CNT_BASE + 168: reserved */
-#define GM_RXE_FIFO_OV \
- (GM_MIB_CNT_BASE + 176) /* Rx FIFO overflow Event */
- /* GM_MIB_CNT_BASE + 184: reserved */
-#define GM_TXF_UC_OK \
- (GM_MIB_CNT_BASE + 192) /* Unicast Frames Xmitted OK */
-#define GM_TXF_BC_OK \
- (GM_MIB_CNT_BASE + 200) /* Broadcast Frames Xmitted OK */
-#define GM_TXF_MPAUSE \
- (GM_MIB_CNT_BASE + 208) /* Pause MAC Ctrl Frames Xmitted */
-#define GM_TXF_MC_OK \
- (GM_MIB_CNT_BASE + 216) /* Multicast Frames Xmitted OK */
-#define GM_TXO_OK_LO \
- (GM_MIB_CNT_BASE + 224) /* Octets Transmitted OK Low */
-#define GM_TXO_OK_HI \
- (GM_MIB_CNT_BASE + 232) /* Octets Transmitted OK High */
-#define GM_TXF_64B \
- (GM_MIB_CNT_BASE + 240) /* 64 Byte Tx Frame */
-#define GM_TXF_127B \
- (GM_MIB_CNT_BASE + 248) /* 65-127 Byte Tx Frame */
-#define GM_TXF_255B \
- (GM_MIB_CNT_BASE + 256) /* 128-255 Byte Tx Frame */
-#define GM_TXF_511B \
- (GM_MIB_CNT_BASE + 264) /* 256-511 Byte Tx Frame */
-#define GM_TXF_1023B \
- (GM_MIB_CNT_BASE + 272) /* 512-1023 Byte Tx Frame */
-#define GM_TXF_1518B \
- (GM_MIB_CNT_BASE + 280) /* 1024-1518 Byte Tx Frame */
-#define GM_TXF_MAX_SZ \
- (GM_MIB_CNT_BASE + 288) /* 1519-MaxSize Byte Tx Frame */
- /* GM_MIB_CNT_BASE + 296: reserved */
-#define GM_TXF_COL \
- (GM_MIB_CNT_BASE + 304) /* Tx Collision */
-#define GM_TXF_LAT_COL \
- (GM_MIB_CNT_BASE + 312) /* Tx Late Collision */
-#define GM_TXF_ABO_COL \
- (GM_MIB_CNT_BASE + 320) /* Tx aborted due to Exces. Col. */
-#define GM_TXF_MUL_COL \
- (GM_MIB_CNT_BASE + 328) /* Tx Multiple Collision */
-#define GM_TXF_SNG_COL \
- (GM_MIB_CNT_BASE + 336) /* Tx Single Collision */
-#define GM_TXE_FIFO_UR \
- (GM_MIB_CNT_BASE + 344) /* Tx FIFO Underrun Event */
-
-/*----------------------------------------------------------------------------*/
-/*
- * GMAC Bit Definitions
- *
- * If the bit access behaviour differs from the register access behaviour
- * (r/w, r/o) this is documented after the bit number.
- * The following bit access behaviours are used:
- * (sc) self clearing
- * (r/o) read only
- */
-
-/* GM_GP_STAT 16 bit r/o General Purpose Status Register */
-#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */
-#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */
-#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow-Control Mode Disabled */
-#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */
-#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */
-#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */
-#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */
-#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */
- /* Bit 7..6: reserved */
-#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */
-#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */
-#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */
-#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow-Control Mode Disabled */
-#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */
- /* Bit 0: reserved */
-
-/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
- /* Bit 15: reserved */
-#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */
-#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow-Control Mode */
-#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */
-#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */
-#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */
-#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */
-#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */
-#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */
-#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */
-#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */
-#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow-Control Mode */
-#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */
-#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update Duplex */
-#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update Flow-C. */
-#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update Speed */
-
-#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
-#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
- GM_GPCR_AU_SPD_DIS)
-
-/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
-#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */
-#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */
-#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */
-#define GM_TXCR_COL_THR_MSK (7<<10) /* Bit 12..10: Collision Threshold */
-
-#define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK)
-
-#define TX_COL_DEF 0x04
-
-/* GM_RX_CTRL 16 bit r/w Receive Control Register */
-#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */
-#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */
-#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */
-#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */
-
-/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
-#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */
-#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */
-#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */
- /* Bit 3..0: reserved */
-
-#define TX_JAM_LEN_VAL(x) (SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
-#define TX_JAM_IPG_VAL(x) (SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
-#define TX_IPG_JAM_DATA(x) (SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
-
-#define TX_JAM_LEN_DEF 0x03
-#define TX_JAM_IPG_DEF 0x0b
-#define TX_IPG_JAM_DEF 0x1c
-
-/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */
-#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder (r/o) */
-#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive Tx trials */
-#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Len) */
-#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Len) */
- /* Bit 7..5: reserved */
-#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
-
-#define DATA_BLIND_VAL(x) (SHIFT11(x) & GM_SMOD_DATABL_MSK)
-#define DATA_BLIND_DEF 0x04
-
-#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
-#define IPG_DATA_DEF 0x1e
-
-/* GM_SMI_CTRL 16 bit r/w SMI Control Register */
-#define GM_SMI_CT_PHY_A_MSK (0x1f<<11) /* Bit 15..11: PHY Device Address */
-#define GM_SMI_CT_REG_A_MSK (0x1f<<6) /* Bit 10.. 6: PHY Register Address */
-#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/
-#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */
-#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */
- /* Bit 2..0: reserved */
-
-#define GM_SMI_CT_PHY_AD(x) (SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
-#define GM_SMI_CT_REG_AD(x) (SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
-
- /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */
- /* Bit 15..6: reserved */
-#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */
-#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */
- /* Bit 3..0: reserved */
-
-/* Receive Frame Status Encoding */
-#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */
- /* Bit 15..14: reserved */
-#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */
-#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */
-#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */
-#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */
-#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */
-#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */
-#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */
-#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */
-#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */
-#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */
-#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */
- /* Bit 2: reserved */
-#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */
-#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */
-
-/*
- * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
- */
-#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \
- GMR_FS_LONG_ERR | \
- GMR_FS_MII_ERR | \
- GMR_FS_BAD_FC | \
- GMR_FS_GOOD_FC | \
- GMR_FS_JABBER)
-
-/* Rx GMAC FIFO Flush Mask (default) */
-#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \
- GMR_FS_RX_FF_OV | \
- GMR_FS_MII_ERR | \
- GMR_FS_BAD_FC | \
- GMR_FS_GOOD_FC | \
- GMR_FS_UN_SIZE | \
- GMR_FS_JABBER)
-
-/* typedefs *******************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __INC_XMAC_H */
diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
deleted file mode 100644
index 6e6c56aa6d6..00000000000
--- a/drivers/net/sk98lin/skaddr.c
+++ /dev/null
@@ -1,1788 +0,0 @@
-/******************************************************************************
- *
- * Name: skaddr.c
- * Project: Gigabit Ethernet Adapters, ADDR-Module
- * Version: $Revision: 1.52 $
- * Date: $Date: 2003/06/02 13:46:15 $
- * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage multicast addresses, address override,
- * and promiscuous mode on GEnesis and Yukon adapters.
- *
- * Address Layout:
- * port address: physical MAC address
- * 1st exact match: logical MAC address (GEnesis only)
- * 2nd exact match: RLMT multicast (GEnesis only)
- * exact match 3-13: OS-specific multicasts (GEnesis only)
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
-#endif /* DEBUG ||!LINT || !SK_SLIM */
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-
-#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
-#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
-#define HASH_BITS 6 /* #bits in hash */
-#define SK_MC_BIT 0x01
-
-/* Error numbers and messages. */
-
-#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0)
-#define SKERR_ADDR_E001MSG "Bad Flags."
-#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1)
-#define SKERR_ADDR_E002MSG "New Error."
-
-/* typedefs *******************************************************************/
-
-/* None. */
-
-/* global variables ***********************************************************/
-
-/* 64-bit hash values with all bits set. */
-
-static const SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
-
-/* local variables ************************************************************/
-
-#ifdef DEBUG
-static int Next0[SK_MAX_MACS] = {0};
-#endif /* DEBUG */
-
-static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
- SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
- int Flags);
-static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
- SK_U32 PortNumber, int NewPromMode);
-static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
- SK_MAC_ADDR *pMc, int Flags);
-static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber,
- int Flags);
-static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber);
-static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC,
- SK_U32 PortNumber, int NewPromMode);
-
-/* functions ******************************************************************/
-
-/******************************************************************************
- *
- * SkAddrInit - initialize data, set state to init
- *
- * Description:
- *
- * SK_INIT_DATA
- * ============
- *
- * This routine clears the multicast tables and resets promiscuous mode.
- * Some entries are reserved for the "logical MAC address", the
- * SK-RLMT multicast address, and the BPDU multicast address.
- *
- *
- * SK_INIT_IO
- * ==========
- *
- * All permanent MAC addresses are read from EPROM.
- * If the current MAC addresses are not already set in software,
- * they are set to the values of the permanent addresses.
- * The current addresses are written to the corresponding MAC.
- *
- *
- * SK_INIT_RUN
- * ===========
- *
- * Nothing.
- *
- * Context:
- * init, pageable
- *
- * Returns:
- * SK_ADDR_SUCCESS
- */
-int SkAddrInit(
-SK_AC *pAC, /* the adapter context */
-SK_IOC IoC, /* I/O context */
-int Level) /* initialization level */
-{
- int j;
- SK_U32 i;
- SK_U8 *InAddr;
- SK_U16 *OutAddr;
- SK_ADDR_PORT *pAPort;
-
- switch (Level) {
- case SK_INIT_DATA:
- SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
- (SK_U16) sizeof(SK_ADDR));
-
- for (i = 0; i < SK_MAX_MACS; i++) {
- pAPort = &pAC->Addr.Port[i];
- pAPort->PromMode = SK_PROM_MODE_NONE;
-
- pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
- pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
- pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
- pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
- }
-#ifdef xDEBUG
- for (i = 0; i < SK_MAX_MACS; i++) {
- if (pAC->Addr.Port[i].NextExactMatchRlmt <
- SK_ADDR_FIRST_MATCH_RLMT) {
- Next0[i] |= 4;
- }
- }
-#endif /* DEBUG */
- /* pAC->Addr.InitDone = SK_INIT_DATA; */
- break;
-
- case SK_INIT_IO:
-#ifndef SK_NO_RLMT
- for (i = 0; i < SK_MAX_NETS; i++) {
- pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
- }
-#endif /* !SK_NO_RLMT */
-#ifdef xDEBUG
- for (i = 0; i < SK_MAX_MACS; i++) {
- if (pAC->Addr.Port[i].NextExactMatchRlmt <
- SK_ADDR_FIRST_MATCH_RLMT) {
- Next0[i] |= 8;
- }
- }
-#endif /* DEBUG */
-
- /* Read permanent logical MAC address from Control Register File. */
- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
- InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
- SK_IN8(IoC, B2_MAC_1 + j, InAddr);
- }
-
- if (!pAC->Addr.Net[0].CurrentMacAddressSet) {
- /* Set the current logical MAC address to the permanent one. */
- pAC->Addr.Net[0].CurrentMacAddress =
- pAC->Addr.Net[0].PermanentMacAddress;
- pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE;
- }
-
- /* Set the current logical MAC address. */
- pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
- pAC->Addr.Net[0].CurrentMacAddress;
-#if SK_MAX_NETS > 1
- /* Set logical MAC address for net 2 to (log | 3). */
- if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
- pAC->Addr.Net[1].PermanentMacAddress =
- pAC->Addr.Net[0].PermanentMacAddress;
- pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
- /* Set the current logical MAC address to the permanent one. */
- pAC->Addr.Net[1].CurrentMacAddress =
- pAC->Addr.Net[1].PermanentMacAddress;
- pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE;
- }
-#endif /* SK_MAX_NETS > 1 */
-
-#ifdef DEBUG
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
- ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
- i,
- pAC->Addr.Net[i].PermanentMacAddress.a[0],
- pAC->Addr.Net[i].PermanentMacAddress.a[1],
- pAC->Addr.Net[i].PermanentMacAddress.a[2],
- pAC->Addr.Net[i].PermanentMacAddress.a[3],
- pAC->Addr.Net[i].PermanentMacAddress.a[4],
- pAC->Addr.Net[i].PermanentMacAddress.a[5]))
-
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
- ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
- i,
- pAC->Addr.Net[i].CurrentMacAddress.a[0],
- pAC->Addr.Net[i].CurrentMacAddress.a[1],
- pAC->Addr.Net[i].CurrentMacAddress.a[2],
- pAC->Addr.Net[i].CurrentMacAddress.a[3],
- pAC->Addr.Net[i].CurrentMacAddress.a[4],
- pAC->Addr.Net[i].CurrentMacAddress.a[5]))
- }
-#endif /* DEBUG */
-
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- pAPort = &pAC->Addr.Port[i];
-
- /* Read permanent port addresses from Control Register File. */
- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
- InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j];
- SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr);
- }
-
- if (!pAPort->CurrentMacAddressSet) {
- /*
- * Set the current and previous physical MAC address
- * of this port to its permanent MAC address.
- */
- pAPort->CurrentMacAddress = pAPort->PermanentMacAddress;
- pAPort->PreviousMacAddress = pAPort->PermanentMacAddress;
- pAPort->CurrentMacAddressSet = SK_TRUE;
- }
-
- /* Set port's current physical MAC address. */
- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- XM_OUTADDR(IoC, i, XM_SA, OutAddr);
- }
-#endif /* GENESIS */
-#ifdef YUKON
- if (!pAC->GIni.GIGenesis) {
- GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr);
- }
-#endif /* YUKON */
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
- ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAPort->PermanentMacAddress.a[0],
- pAPort->PermanentMacAddress.a[1],
- pAPort->PermanentMacAddress.a[2],
- pAPort->PermanentMacAddress.a[3],
- pAPort->PermanentMacAddress.a[4],
- pAPort->PermanentMacAddress.a[5]))
-
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
- ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAPort->CurrentMacAddress.a[0],
- pAPort->CurrentMacAddress.a[1],
- pAPort->CurrentMacAddress.a[2],
- pAPort->CurrentMacAddress.a[3],
- pAPort->CurrentMacAddress.a[4],
- pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
- }
- /* pAC->Addr.InitDone = SK_INIT_IO; */
- break;
-
- case SK_INIT_RUN:
-#ifdef xDEBUG
- for (i = 0; i < SK_MAX_MACS; i++) {
- if (pAC->Addr.Port[i].NextExactMatchRlmt <
- SK_ADDR_FIRST_MATCH_RLMT) {
- Next0[i] |= 16;
- }
- }
-#endif /* DEBUG */
-
- /* pAC->Addr.InitDone = SK_INIT_RUN; */
- break;
-
- default: /* error */
- break;
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrInit */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- * SkAddrMcClear - clear the multicast table
- *
- * Description:
- * This routine clears the multicast table.
- *
- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- * immediately.
- *
- * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according
- * to the adapter in use. The real work is done there.
- *
- * Context:
- * runtime, pageable
- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- * may be called after SK_INIT_IO without limitation
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-int SkAddrMcClear(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Index of affected port */
-int Flags) /* permanent/non-perm, sw-only */
-{
- int ReturnCode;
-
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (pAC->GIni.GIGenesis) {
- ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
- }
- else {
- ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
- }
-
- return (ReturnCode);
-
-} /* SkAddrMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- * SkAddrXmacMcClear - clear the multicast table
- *
- * Description:
- * This routine clears the multicast table
- * (either entry 2 or entries 3-16 and InexactFilter) of the given port.
- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- * immediately.
- *
- * Context:
- * runtime, pageable
- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- * may be called after SK_INIT_IO without limitation
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrXmacMcClear(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Index of affected port */
-int Flags) /* permanent/non-perm, sw-only */
-{
- int i;
-
- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
-
- /* Clear RLMT multicast addresses. */
- pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
- }
- else { /* not permanent => DRV */
-
- /* Clear InexactFilter */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
- }
-
- /* Clear DRV multicast addresses. */
-
- pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
- }
-
- if (!(Flags & SK_MC_SW_ONLY)) {
- (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrXmacMcClear */
-
-#endif /* !SK_SLIM */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- * SkAddrGmacMcClear - clear the multicast table
- *
- * Description:
- * This routine clears the multicast hashing table (InexactFilter)
- * (either the RLMT or the driver bits) of the given port.
- *
- * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated
- * immediately.
- *
- * Context:
- * runtime, pageable
- * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY
- * may be called after SK_INIT_IO without limitation
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrGmacMcClear(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Index of affected port */
-int Flags) /* permanent/non-perm, sw-only */
-{
- int i;
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif /* DEBUG */
-
- /* Clear InexactFilter */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
- }
-
- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
-
- /* Copy DRV bits to InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
-
- /* Clear InexactRlmtFilter. */
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
-
- }
- }
- else { /* not permanent => DRV */
-
- /* Copy RLMT bits to InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
-
- /* Clear InexactDrvFilter. */
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
- }
- }
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
-#endif /* DEBUG */
-
- if (!(Flags & SK_MC_SW_ONLY)) {
- (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrGmacMcClear */
-
-#ifndef SK_ADDR_CHEAT
-
-/******************************************************************************
- *
- * SkXmacMcHash - hash multicast address
- *
- * Description:
- * This routine computes the hash value for a multicast address.
- * A CRC32 algorithm is used.
- *
- * Notes:
- * The code was adapted from the XaQti data sheet.
- *
- * Context:
- * runtime, pageable
- *
- * Returns:
- * Hash value of multicast address.
- */
-static SK_U32 SkXmacMcHash(
-unsigned char *pMc) /* Multicast address */
-{
- SK_U32 Idx;
- SK_U32 Bit;
- SK_U32 Data;
- SK_U32 Crc;
-
- Crc = 0xFFFFFFFFUL;
- for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) {
- Data = *pMc++;
- for (Bit = 0; Bit < 8; Bit++, Data >>= 1) {
- Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0);
- }
- }
-
- return (Crc & ((1 << HASH_BITS) - 1));
-
-} /* SkXmacMcHash */
-
-
-/******************************************************************************
- *
- * SkGmacMcHash - hash multicast address
- *
- * Description:
- * This routine computes the hash value for a multicast address.
- * A CRC16 algorithm is used.
- *
- * Notes:
- *
- *
- * Context:
- * runtime, pageable
- *
- * Returns:
- * Hash value of multicast address.
- */
-static SK_U32 SkGmacMcHash(
-unsigned char *pMc) /* Multicast address */
-{
- SK_U32 Data;
- SK_U32 TmpData;
- SK_U32 Crc;
- int Byte;
- int Bit;
-
- Crc = 0xFFFFFFFFUL;
- for (Byte = 0; Byte < 6; Byte++) {
- /* Get next byte. */
- Data = (SK_U32) pMc[Byte];
-
- /* Change bit order in byte. */
- TmpData = Data;
- for (Bit = 0; Bit < 8; Bit++) {
- if (TmpData & 1L) {
- Data |= 1L << (7 - Bit);
- }
- else {
- Data &= ~(1L << (7 - Bit));
- }
- TmpData >>= 1;
- }
-
- Crc ^= (Data << 24);
- for (Bit = 0; Bit < 8; Bit++) {
- if (Crc & 0x80000000) {
- Crc = (Crc << 1) ^ GMAC_POLY;
- }
- else {
- Crc <<= 1;
- }
- }
- }
-
- return (Crc & ((1 << HASH_BITS) - 1));
-
-} /* SkGmacMcHash */
-
-#endif /* !SK_ADDR_CHEAT */
-
-/******************************************************************************
- *
- * SkAddrMcAdd - add a multicast address to a port
- *
- * Description:
- * This routine enables reception for a given address on the given port.
- *
- * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the
- * adapter in use. The real work is done there.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_DATA
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_MC_ILLEGAL_ADDRESS
- * SK_MC_ILLEGAL_PORT
- * SK_MC_RLMT_OVERFLOW
- */
-int SkAddrMcAdd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Port Number */
-SK_MAC_ADDR *pMc, /* multicast address to be added */
-int Flags) /* permanent/non-permanent */
-{
- int ReturnCode;
-
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (pAC->GIni.GIGenesis) {
- ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
- }
- else {
- ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
- }
-
- return (ReturnCode);
-
-} /* SkAddrMcAdd */
-
-
-/******************************************************************************
- *
- * SkAddrXmacMcAdd - add a multicast address to a port
- *
- * Description:
- * This routine enables reception for a given address on the given port.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * The multicast bit is only checked if there are no free exact match
- * entries.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_DATA
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_MC_ILLEGAL_ADDRESS
- * SK_MC_RLMT_OVERFLOW
- */
-static int SkAddrXmacMcAdd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Port Number */
-SK_MAC_ADDR *pMc, /* multicast address to be added */
-int Flags) /* permanent/non-permanent */
-{
- int i;
- SK_U8 Inexact;
-#ifndef SK_ADDR_CHEAT
- SK_U32 HashBit;
-#endif /* !defined(SK_ADDR_CHEAT) */
-
- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
-#ifdef xDEBUG
- if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt <
- SK_ADDR_FIRST_MATCH_RLMT) {
- Next0[PortNumber] |= 1;
- return (SK_MC_RLMT_OVERFLOW);
- }
-#endif /* DEBUG */
-
- if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
- SK_ADDR_LAST_MATCH_RLMT) {
- return (SK_MC_RLMT_OVERFLOW);
- }
-
- /* Set a RLMT multicast address. */
-
- pAC->Addr.Port[PortNumber].Exact[
- pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc;
-
- return (SK_MC_FILTERING_EXACT);
- }
-
-#ifdef xDEBUG
- if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <
- SK_ADDR_FIRST_MATCH_DRV) {
- Next0[PortNumber] |= 2;
- return (SK_MC_RLMT_OVERFLOW);
- }
-#endif /* DEBUG */
-
- if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-
- /* Set exact match entry. */
- pAC->Addr.Port[PortNumber].Exact[
- pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc;
-
- /* Clear InexactFilter */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
- }
- }
- else {
- if (!(pMc->a[0] & SK_MC_BIT)) {
- /* Hashing only possible with multicast addresses */
- return (SK_MC_ILLEGAL_ADDRESS);
- }
-#ifndef SK_ADDR_CHEAT
- /* Compute hash value of address. */
- HashBit = 63 - SkXmacMcHash(&pMc->a[0]);
-
- /* Add bit to InexactFilter. */
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |=
- 1 << (HashBit % 8);
-#else /* SK_ADDR_CHEAT */
- /* Set all bits in InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
- }
-#endif /* SK_ADDR_CHEAT */
- }
-
- for (Inexact = 0, i = 0; i < 8; i++) {
- Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
- }
-
- if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) {
- return (SK_MC_FILTERING_EXACT);
- }
- else {
- return (SK_MC_FILTERING_INEXACT);
- }
-
-} /* SkAddrXmacMcAdd */
-
-
-/******************************************************************************
- *
- * SkAddrGmacMcAdd - add a multicast address to a port
- *
- * Description:
- * This routine enables reception for a given address on the given port.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_DATA
- *
- * Returns:
- * SK_MC_FILTERING_INEXACT
- * SK_MC_ILLEGAL_ADDRESS
- */
-static int SkAddrGmacMcAdd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Port Number */
-SK_MAC_ADDR *pMc, /* multicast address to be added */
-int Flags) /* permanent/non-permanent */
-{
- int i;
-#ifndef SK_ADDR_CHEAT
- SK_U32 HashBit;
-#endif /* !defined(SK_ADDR_CHEAT) */
-
- if (!(pMc->a[0] & SK_MC_BIT)) {
- /* Hashing only possible with multicast addresses */
- return (SK_MC_ILLEGAL_ADDRESS);
- }
-
-#ifndef SK_ADDR_CHEAT
-
- /* Compute hash value of address. */
- HashBit = SkGmacMcHash(&pMc->a[0]);
-
- if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
-
- /* Add bit to InexactRlmtFilter. */
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
- 1 << (HashBit % 8);
-
- /* Copy bit to InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
- }
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
-#endif /* DEBUG */
- }
- else { /* not permanent => DRV */
-
- /* Add bit to InexactDrvFilter. */
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
- 1 << (HashBit % 8);
-
- /* Copy bit to InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
- }
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
-#endif /* DEBUG */
- }
-
-#else /* SK_ADDR_CHEAT */
-
- /* Set all bits in InexactFilter. */
- for (i = 0; i < 8; i++) {
- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
- }
-#endif /* SK_ADDR_CHEAT */
-
- return (SK_MC_FILTERING_INEXACT);
-
-} /* SkAddrGmacMcAdd */
-
-#endif /* !SK_SLIM */
-
-/******************************************************************************
- *
- * SkAddrMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- * This routine enables reception of the addresses contained in a local
- * table for a given port.
- * It also programs the port's current physical MAC address.
- *
- * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according
- * to the adapter in use. The real work is done there.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_ADDR_ILLEGAL_PORT
- */
-int SkAddrMcUpdate(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber) /* Port Number */
-{
- int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber);
- }
-#endif /* GENESIS */
-#ifdef YUKON
- if (!pAC->GIni.GIGenesis) {
- ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
- }
-#endif /* YUKON */
- return (ReturnCode);
-
-} /* SkAddrMcUpdate */
-
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- * This routine enables reception of the addresses contained in a local
- * table for a given port.
- * It also programs the port's current physical MAC address.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrXmacMcUpdate(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber) /* Port Number */
-{
- SK_U32 i;
- SK_U8 Inexact;
- SK_U16 *OutAddr;
- SK_ADDR_PORT *pAPort;
-
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
-
- pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-
- /* Start with 0 to also program the logical MAC address. */
- for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
- /* Set exact match address i on XMAC */
- OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
- XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
- }
-
- /* Clear other permanent exact match addresses on XMAC */
- if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
-
- SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
- SK_ADDR_LAST_MATCH_RLMT);
- }
-
- for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) {
- OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0];
- XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr);
- }
-
- /* Clear other non-permanent exact match addresses on XMAC */
- if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
-
- SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
- SK_ADDR_LAST_MATCH_DRV);
- }
-
- for (Inexact = 0, i = 0; i < 8; i++) {
- Inexact |= pAPort->InexactFilter.Bytes[i];
- }
-
- if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
-
- /* Set all bits in 64-bit hash register. */
- XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else if (Inexact != 0) {
-
- /* Set 64-bit hash register to InexactFilter. */
- XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else {
- /* Disable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
- }
-
- if (pAPort->PromMode != SK_PROM_MODE_NONE) {
- (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
- }
-
- /* Set port's current physical MAC address. */
- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
-
- XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
-
-#ifdef xDEBUG
- for (i = 0; i < pAPort->NextExactMatchRlmt; i++) {
- SK_U8 InAddr8[6];
- SK_U16 *InAddr;
-
- /* Get exact match address i from port PortNumber. */
- InAddr = (SK_U16 *) &InAddr8[0];
-
- XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
-
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
- "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
- i,
- PortNumber,
- InAddr8[0],
- InAddr8[1],
- InAddr8[2],
- InAddr8[3],
- InAddr8[4],
- InAddr8[5],
- pAPort->Exact[i].a[0],
- pAPort->Exact[i].a[1],
- pAPort->Exact[i].a[2],
- pAPort->Exact[i].a[3],
- pAPort->Exact[i].a[4],
- pAPort->Exact[i].a[5]))
- }
-#endif /* DEBUG */
-
- /* Determine return value. */
- if (Inexact == 0 && pAPort->PromMode == 0) {
- return (SK_MC_FILTERING_EXACT);
- }
- else {
- return (SK_MC_FILTERING_INEXACT);
- }
-
-} /* SkAddrXmacMcUpdate */
-
-#endif /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address
- *
- * Description:
- * This routine enables reception of the addresses contained in a local
- * table for a given port.
- * It also programs the port's current physical MAC address.
- *
- * Notes:
- * The return code is only valid for SK_PROM_MODE_NONE.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_MC_FILTERING_EXACT
- * SK_MC_FILTERING_INEXACT
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrGmacMcUpdate(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber) /* Port Number */
-{
-#ifndef SK_SLIM
- SK_U32 i;
- SK_U8 Inexact;
-#endif /* not SK_SLIM */
- SK_U16 *OutAddr;
- SK_ADDR_PORT *pAPort;
-
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
-
- pAPort = &pAC->Addr.Port[PortNumber];
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
-#endif /* DEBUG */
-
-#ifndef SK_SLIM
- for (Inexact = 0, i = 0; i < 8; i++) {
- Inexact |= pAPort->InexactFilter.Bytes[i];
- }
-
- /* Set 64-bit hash register to InexactFilter. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
- &pAPort->InexactFilter.Bytes[0]);
-
- if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
-
- /* Set all bits in 64-bit hash register. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else {
- /* Enable Hashing. */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
-
- if (pAPort->PromMode != SK_PROM_MODE_NONE) {
- (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
- }
-#else /* SK_SLIM */
-
- /* Set all bits in 64-bit hash register. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
-
- (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
-
-#endif /* SK_SLIM */
-
- /* Set port's current physical MAC address. */
- OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
-
- /* Set port's current logical MAC address. */
- OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAPort->Exact[0].a[0],
- pAPort->Exact[0].a[1],
- pAPort->Exact[0].a[2],
- pAPort->Exact[0].a[3],
- pAPort->Exact[0].a[4],
- pAPort->Exact[0].a[5]))
-
- SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAPort->CurrentMacAddress.a[0],
- pAPort->CurrentMacAddress.a[1],
- pAPort->CurrentMacAddress.a[2],
- pAPort->CurrentMacAddress.a[3],
- pAPort->CurrentMacAddress.a[4],
- pAPort->CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-
-#ifndef SK_SLIM
- /* Determine return value. */
- if (Inexact == 0 && pAPort->PromMode == 0) {
- return (SK_MC_FILTERING_EXACT);
- }
- else {
- return (SK_MC_FILTERING_INEXACT);
- }
-#else /* SK_SLIM */
- return (SK_MC_FILTERING_INEXACT);
-#endif /* SK_SLIM */
-
-} /* SkAddrGmacMcUpdate */
-
-#endif /* YUKON */
-
-#ifndef SK_NO_MAO
-
-/******************************************************************************
- *
- * SkAddrOverride - override a port's MAC address
- *
- * Description:
- * This routine overrides the MAC address of one port.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS if successful.
- * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address.
- * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address.
- * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before.
- */
-int SkAddrOverride(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* Port Number */
-SK_MAC_ADDR SK_FAR *pNewAddr, /* new MAC address */
-int Flags) /* logical/physical MAC address */
-{
-#ifndef SK_NO_RLMT
- SK_EVPARA Para;
-#endif /* !SK_NO_RLMT */
- SK_U32 NetNumber;
- SK_U32 i;
- SK_U16 SK_FAR *OutAddr;
-
-#ifndef SK_NO_RLMT
- NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber;
-#else
- NetNumber = 0;
-#endif /* SK_NO_RLMT */
-#if (!defined(SK_SLIM) || defined(DEBUG))
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-#endif /* !SK_SLIM || DEBUG */
- if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) {
- return (SK_ADDR_MULTICAST_ADDRESS);
- }
-
- if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
-
- if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */
- /* Parameter *pNewAddr is ignored. */
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
- }
-#ifndef SK_NO_RLMT
- /* Set PortNumber to number of net's active port. */
- PortNumber = pAC->Rlmt.Net[NetNumber].
- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
- pAC->Addr.Port[PortNumber].Exact[0] =
- pAC->Addr.Net[NetNumber].CurrentMacAddress;
-
- /* Write address to first exact match entry of active port. */
- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
- }
- else if (Flags & SK_ADDR_CLEAR_LOGICAL) {
- /* Deactivate logical MAC address. */
- /* Parameter *pNewAddr is ignored. */
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
- }
-#ifndef SK_NO_RLMT
- /* Set PortNumber to number of net's active port. */
- PortNumber = pAC->Rlmt.Net[NetNumber].
- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
- for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) {
- pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0;
- }
-
- /* Write address to first exact match entry of active port. */
- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
- }
- else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
- if (SK_ADDR_EQUAL(pNewAddr->a,
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
- return (SK_ADDR_DUPLICATE_ADDRESS);
- }
-
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
-
- if (SK_ADDR_EQUAL(pNewAddr->a,
- pAC->Addr.Port[i].CurrentMacAddress.a)) {
- if (i == PortNumber) {
- return (SK_ADDR_SUCCESS);
- }
- else {
- return (SK_ADDR_DUPLICATE_ADDRESS);
- }
- }
- }
-
- pAC->Addr.Port[PortNumber].PreviousMacAddress =
- pAC->Addr.Port[PortNumber].CurrentMacAddress;
- pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-
- /* Change port's physical MAC address. */
- OutAddr = (SK_U16 SK_FAR *) pNewAddr;
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
- }
-#endif /* GENESIS */
-#ifdef YUKON
- if (!pAC->GIni.GIGenesis) {
- GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
- }
-#endif /* YUKON */
-
-#ifndef SK_NO_RLMT
- /* Report address change to RLMT. */
- Para.Para32[0] = PortNumber;
- Para.Para32[0] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
- }
- else { /* Logical MAC address. */
- if (SK_ADDR_EQUAL(pNewAddr->a,
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
- return (SK_ADDR_SUCCESS);
- }
-
- for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
- return (SK_ADDR_TOO_EARLY);
- }
-
- if (SK_ADDR_EQUAL(pNewAddr->a,
- pAC->Addr.Port[i].CurrentMacAddress.a)) {
- return (SK_ADDR_DUPLICATE_ADDRESS);
- }
- }
-
- /*
- * In case that the physical and the logical MAC addresses are equal
- * we must also change the physical MAC address here.
- * In this case we have an adapter which initially was programmed with
- * two identical MAC addresses.
- */
- if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
- pAC->Addr.Port[PortNumber].Exact[0].a)) {
-
- pAC->Addr.Port[PortNumber].PreviousMacAddress =
- pAC->Addr.Port[PortNumber].CurrentMacAddress;
- pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
-
-#ifndef SK_NO_RLMT
- /* Report address change to RLMT. */
- Para.Para32[0] = PortNumber;
- Para.Para32[0] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
-#endif /* !SK_NO_RLMT */
- }
-
-#ifndef SK_NO_RLMT
- /* Set PortNumber to number of net's active port. */
- PortNumber = pAC->Rlmt.Net[NetNumber].
- Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber;
-#endif /* !SK_NO_RLMT */
- pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr;
- pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr;
-#ifdef DEBUG
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
-
- SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
- ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
-#endif /* DEBUG */
-
- /* Write address to first exact match entry of active port. */
- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrOverride */
-
-
-#endif /* SK_NO_MAO */
-
-/******************************************************************************
- *
- * SkAddrPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- * This routine manages promiscuous mode:
- * - none
- * - all LLC frames
- * - all MC frames
- *
- * It calls either SkAddrXmacPromiscuousChange or
- * SkAddrGmacPromiscuousChange, according to the adapter in use.
- * The real work is done there.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-int SkAddrPromiscuousChange(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* port whose promiscuous mode changes */
-int NewPromMode) /* new promiscuous mode */
-{
- int ReturnCode = 0;
-#if (!defined(SK_SLIM) || defined(DEBUG))
- if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-#endif /* !SK_SLIM || DEBUG */
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- ReturnCode =
- SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
- }
-#endif /* GENESIS */
-#ifdef YUKON
- if (!pAC->GIni.GIGenesis) {
- ReturnCode =
- SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode);
- }
-#endif /* YUKON */
-
- return (ReturnCode);
-
-} /* SkAddrPromiscuousChange */
-
-#ifdef GENESIS
-
-/******************************************************************************
- *
- * SkAddrXmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- * This routine manages promiscuous mode:
- * - none
- * - all LLC frames
- * - all MC frames
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrXmacPromiscuousChange(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* port whose promiscuous mode changes */
-int NewPromMode) /* new promiscuous mode */
-{
- int i;
- SK_BOOL InexactModeBit;
- SK_U8 Inexact;
- SK_U8 HwInexact;
- SK_FILTER64 HwInexactFilter;
- SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */
- int CurPromMode = SK_PROM_MODE_NONE;
-
- /* Read CurPromMode from Hardware. */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-
- if ((LoMode & XM_MD_ENA_PROM) != 0) {
- /* Promiscuous mode! */
- CurPromMode |= SK_PROM_MODE_LLC;
- }
-
- for (Inexact = 0xFF, i = 0; i < 8; i++) {
- Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
- }
- if (Inexact == 0xFF) {
- CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
- }
- else {
- /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
- XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
-
- InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
-
- /* Read 64-bit hash register from XMAC */
- XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]);
-
- for (HwInexact = 0xFF, i = 0; i < 8; i++) {
- HwInexact &= HwInexactFilter.Bytes[i];
- }
-
- if (InexactModeBit && (HwInexact == 0xFF)) {
- CurPromMode |= SK_PROM_MODE_ALL_MC;
- }
- }
-
- pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
- if (NewPromMode == CurPromMode) {
- return (SK_ADDR_SUCCESS);
- }
-
- if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
- !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
-
- /* Set all bits in 64-bit hash register. */
- XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
- !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */
- for (Inexact = 0, i = 0; i < 8; i++) {
- Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
- }
- if (Inexact == 0) {
- /* Disable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE);
- }
- else {
- /* Set 64-bit hash register to InexactFilter. */
- XM_OUTHASH(IoC, PortNumber, XM_HSM,
- &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- }
-
- if ((NewPromMode & SK_PROM_MODE_LLC) &&
- !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
- /* Set the MAC in Promiscuous Mode */
- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else if ((CurPromMode & SK_PROM_MODE_LLC) &&
- !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */
- /* Clear Promiscuous Mode */
- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrXmacPromiscuousChange */
-
-#endif /* GENESIS */
-
-#ifdef YUKON
-
-/******************************************************************************
- *
- * SkAddrGmacPromiscuousChange - set promiscuous mode for given port
- *
- * Description:
- * This routine manages promiscuous mode:
- * - none
- * - all LLC frames
- * - all MC frames
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-static int SkAddrGmacPromiscuousChange(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 PortNumber, /* port whose promiscuous mode changes */
-int NewPromMode) /* new promiscuous mode */
-{
- SK_U16 ReceiveControl; /* GMAC Receive Control Register */
- int CurPromMode = SK_PROM_MODE_NONE;
-
- /* Read CurPromMode from Hardware. */
- GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl);
-
- if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) {
- /* Promiscuous mode! */
- CurPromMode |= SK_PROM_MODE_LLC;
- }
-
- if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) {
- /* All Multicast mode! */
- CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
- }
-
- pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
-
- if (NewPromMode == CurPromMode) {
- return (SK_ADDR_SUCCESS);
- }
-
- if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
- !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
-
- /* Set all bits in 64-bit hash register. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
-
- /* Enable Hashing */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
-
- if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
- !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
-
- /* Set 64-bit hash register to InexactFilter. */
- GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
- &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]);
-
- /* Enable Hashing. */
- SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
-
- if ((NewPromMode & SK_PROM_MODE_LLC) &&
- !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
-
- /* Set the MAC to Promiscuous Mode. */
- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
- }
- else if ((CurPromMode & SK_PROM_MODE_LLC) &&
- !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
-
- /* Clear Promiscuous Mode. */
- SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
- }
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrGmacPromiscuousChange */
-
-#endif /* YUKON */
-
-#ifndef SK_SLIM
-
-/******************************************************************************
- *
- * SkAddrSwap - swap address info
- *
- * Description:
- * This routine swaps address info of two ports.
- *
- * Context:
- * runtime, pageable
- * may be called after SK_INIT_IO
- *
- * Returns:
- * SK_ADDR_SUCCESS
- * SK_ADDR_ILLEGAL_PORT
- */
-int SkAddrSwap(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-SK_U32 FromPortNumber, /* Port1 Index */
-SK_U32 ToPortNumber) /* Port2 Index */
-{
- int i;
- SK_U8 Byte;
- SK_MAC_ADDR MacAddr;
- SK_U32 DWord;
-
- if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) {
- return (SK_ADDR_ILLEGAL_PORT);
- }
-
- /*
- * Swap:
- * - Exact Match Entries (GEnesis and Yukon)
- * Yukon uses first entry for the logical MAC
- * address (stored in the second GMAC register).
- * - FirstExactMatchRlmt (GEnesis only)
- * - NextExactMatchRlmt (GEnesis only)
- * - FirstExactMatchDrv (GEnesis only)
- * - NextExactMatchDrv (GEnesis only)
- * - 64-bit filter (InexactFilter)
- * - Promiscuous Mode
- * of ports.
- */
-
- for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) {
- MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i];
- pAC->Addr.Port[FromPortNumber].Exact[i] =
- pAC->Addr.Port[ToPortNumber].Exact[i];
- pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr;
- }
-
- for (i = 0; i < 8; i++) {
- Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i];
- pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] =
- pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
- pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
- }
-
- i = pAC->Addr.Port[FromPortNumber].PromMode;
- pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
- pAC->Addr.Port[ToPortNumber].PromMode = i;
-
- if (pAC->GIni.GIGenesis) {
- DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
- pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
- pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
- pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
-
- DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
- pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
- pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
- pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
-
- DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
- pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
- pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
- pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
-
- DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
- pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
- pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
- pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
- }
-
- /* CAUTION: Solution works if only ports of one adapter are in use. */
- for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
- Net->NetNumber].NumPorts; i++) {
- if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
- Port[i]->PortNumber == ToPortNumber) {
- pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber].
- ActivePort = i;
- /* 20001207 RA: Was "ToPortNumber;". */
- }
- }
-
- (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
- (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
-
- return (SK_ADDR_SUCCESS);
-
-} /* SkAddrSwap */
-
-#endif /* !SK_SLIM */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c
deleted file mode 100644
index 37ce03fb8de..00000000000
--- a/drivers/net/sk98lin/skdim.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/******************************************************************************
- *
- * Name: skdim.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.5 $
- * Date: $Date: 2003/11/28 12:55:40 $
- * Purpose: All functions to maintain interrupt moderation
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module is intended to manage the dynamic interrupt moderation on both
- * GEnesis and Yukon adapters.
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef lint
-static const char SysKonnectFileId[] =
- "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
-#endif
-
-#define __SKADDR_C
-
-#ifdef __cplusplus
-#error C++ is not yet supported.
-extern "C" {
-#endif
-
-/*******************************************************************************
-**
-** Includes
-**
-*******************************************************************************/
-
-#ifndef __INC_SKDRV1ST_H
-#include "h/skdrv1st.h"
-#endif
-
-#ifndef __INC_SKDRV2ND_H
-#include "h/skdrv2nd.h"
-#endif
-
-#include <linux/kernel_stat.h>
-
-/*******************************************************************************
-**
-** Defines
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Typedefs
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local function prototypes
-**
-*******************************************************************************/
-
-static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
-static SK_U64 GetIsrCalls(SK_AC *pAC);
-static SK_BOOL IsIntModEnabled(SK_AC *pAC);
-static void SetCurrIntCtr(SK_AC *pAC);
-static void EnableIntMod(SK_AC *pAC);
-static void DisableIntMod(SK_AC *pAC);
-static void ResizeDimTimerDuration(SK_AC *pAC);
-static void DisplaySelectedModerationType(SK_AC *pAC);
-static void DisplaySelectedModerationMask(SK_AC *pAC);
-static void DisplayDescrRatio(SK_AC *pAC);
-
-/*******************************************************************************
-**
-** Global variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Local variables
-**
-*******************************************************************************/
-
-/*******************************************************************************
-**
-** Global functions
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function : SkDimModerate
-** Description : Called in every ISR to check if moderation is to be applied
-** or not for the current number of interrupts
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : void (!)
-** Notes : -
-*******************************************************************************/
-
-void
-SkDimModerate(SK_AC *pAC) {
- unsigned int CurrSysLoad = 0; /* expressed in percent */
- unsigned int LoadIncrease = 0; /* expressed in percent */
- SK_U64 ThresholdInts = 0;
- SK_U64 IsrCallsPerSec = 0;
-
-#define M_DIMINFO pAC->DynIrqModInfo
-
- if (!IsIntModEnabled(pAC)) {
- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
- CurrSysLoad = GetCurrentSystemLoad(pAC);
- if (CurrSysLoad > 75) {
- /*
- ** More than 75% total system load! Enable the moderation
- ** to shield the system against too many interrupts.
- */
- EnableIntMod(pAC);
- } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
- LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
- if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
- C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
- if (CurrSysLoad > 10) {
- /*
- ** More than 50% increase with respect to the
- ** previous load of the system. Most likely this
- ** is due to our ISR-proc...
- */
- EnableIntMod(pAC);
- }
- }
- } else {
- /*
- ** Neither too much system load at all nor too much increase
- ** with respect to the previous system load. Hence, we can leave
- ** the ISR-handling like it is without enabling moderation.
- */
- }
- M_DIMINFO.PrevSysLoad = CurrSysLoad;
- }
- } else {
- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
- ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
- C_INT_MOD_DISABLE_PERCENTAGE) / 100);
- IsrCallsPerSec = GetIsrCalls(pAC);
- if (IsrCallsPerSec <= ThresholdInts) {
- /*
- ** The number of interrupts within the last second is
- ** lower than the disable_percentage of the desried
- ** maxrate. Therefore we can disable the moderation.
- */
- DisableIntMod(pAC);
- M_DIMINFO.MaxModIntsPerSec =
- (M_DIMINFO.MaxModIntsPerSecUpperLimit +
- M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
- } else {
- /*
- ** The number of interrupts per sec is the same as expected.
- ** Evalulate the descriptor-ratio. If it has changed, a resize
- ** in the moderation timer might be useful
- */
- if (M_DIMINFO.AutoSizing) {
- ResizeDimTimerDuration(pAC);
- }
- }
- }
- }
-
- /*
- ** Some information to the log...
- */
- if (M_DIMINFO.DisplayStats) {
- DisplaySelectedModerationType(pAC);
- DisplaySelectedModerationMask(pAC);
- DisplayDescrRatio(pAC);
- }
-
- M_DIMINFO.NbrProcessedDescr = 0;
- SetCurrIntCtr(pAC);
-}
-
-/*******************************************************************************
-** Function : SkDimStartModerationTimer
-** Description : Starts the audit-timer for the dynamic interrupt moderation
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : void (!)
-** Notes : -
-*******************************************************************************/
-
-void
-SkDimStartModerationTimer(SK_AC *pAC) {
- SK_EVPARA EventParam; /* Event struct for timer event */
-
- SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
- SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
- SK_DRV_MODERATION_TIMER_LENGTH,
- SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*******************************************************************************
-** Function : SkDimEnableModerationIfNeeded
-** Description : Either enables or disables moderation
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : void (!)
-** Notes : This function is called when a particular adapter is opened
-** There is no Disable function, because when all interrupts
-** might be disable, the moderation timer has no meaning at all
-******************************************************************************/
-
-void
-SkDimEnableModerationIfNeeded(SK_AC *pAC) {
-
- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
- EnableIntMod(pAC); /* notification print in this function */
- } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
- SkDimStartModerationTimer(pAC);
- if (M_DIMINFO.DisplayStats) {
- printk("Dynamic moderation has been enabled\n");
- }
- } else {
- if (M_DIMINFO.DisplayStats) {
- printk("No moderation has been enabled\n");
- }
- }
-}
-
-/*******************************************************************************
-** Function : SkDimDisplayModerationSettings
-** Description : Displays the current settings regarding interrupt moderation
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : void (!)
-** Notes : -
-*******************************************************************************/
-
-void
-SkDimDisplayModerationSettings(SK_AC *pAC) {
- DisplaySelectedModerationType(pAC);
- DisplaySelectedModerationMask(pAC);
-}
-
-/*******************************************************************************
-**
-** Local functions
-**
-*******************************************************************************/
-
-/*******************************************************************************
-** Function : GetCurrentSystemLoad
-** Description : Retrieves the current system load of the system. This load
-** is evaluated for all processors within the system.
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : unsigned int: load expressed in percentage
-** Notes : The possible range being returned is from 0 up to 100.
-** Whereas 0 means 'no load at all' and 100 'system fully loaded'
-** It is impossible to determine what actually causes the system
-** to be in 100%, but maybe that is due to too much interrupts.
-*******************************************************************************/
-
-static unsigned int
-GetCurrentSystemLoad(SK_AC *pAC) {
- unsigned long jif = jiffies;
- unsigned int UserTime = 0;
- unsigned int SystemTime = 0;
- unsigned int NiceTime = 0;
- unsigned int IdleTime = 0;
- unsigned int TotalTime = 0;
- unsigned int UsedTime = 0;
- unsigned int SystemLoad = 0;
-
- /* unsigned int NbrCpu = 0; */
-
- /*
- ** The following lines have been commented out, because
- ** from kernel 2.5.44 onwards, the kernel-owned structure
- **
- ** struct kernel_stat kstat
- **
- ** is not marked as an exported symbol in the file
- **
- ** kernel/ksyms.c
- **
- ** As a consequence, using this driver as KLM is not possible
- ** and any access of the structure kernel_stat via the
- ** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
- **
- ** The kstat-information might be added again in future
- ** versions of the 2.5.xx kernel, but for the time being,
- ** number of interrupts will serve as indication how much
- ** load we currently have...
- **
- ** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
- ** UserTime = UserTime + kstat_cpu(NbrCpu).cpustat.user;
- ** NiceTime = NiceTime + kstat_cpu(NbrCpu).cpustat.nice;
- ** SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
- ** }
- */
- SK_U64 ThresholdInts = 0;
- SK_U64 IsrCallsPerSec = 0;
-
- ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
- C_INT_MOD_ENABLE_PERCENTAGE) + 100);
- IsrCallsPerSec = GetIsrCalls(pAC);
- if (IsrCallsPerSec >= ThresholdInts) {
- /*
- ** We do not know how much the real CPU-load is!
- ** Return 80% as a default in order to activate DIM
- */
- SystemLoad = 80;
- return (SystemLoad);
- }
-
- UsedTime = UserTime + NiceTime + SystemTime;
-
- IdleTime = jif * num_online_cpus() - UsedTime;
- TotalTime = UsedTime + IdleTime;
-
- SystemLoad = ( 100 * (UsedTime - M_DIMINFO.PrevUsedTime) ) /
- (TotalTime - M_DIMINFO.PrevTotalTime);
-
- if (M_DIMINFO.DisplayStats) {
- printk("Current system load is: %u\n", SystemLoad);
- }
-
- M_DIMINFO.PrevTotalTime = TotalTime;
- M_DIMINFO.PrevUsedTime = UsedTime;
-
- return (SystemLoad);
-}
-
-/*******************************************************************************
-** Function : GetIsrCalls
-** Description : Depending on the selected moderation mask, this function will
-** return the number of interrupts handled in the previous time-
-** frame. This evaluated number is based on the current number
-** of interrupts stored in PNMI-context and the previous stored
-** interrupts.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : int: the number of interrupts being executed in the last
-** timeframe
-** Notes : It makes only sense to call this function, when dynamic
-** interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetIsrCalls(SK_AC *pAC) {
- SK_U64 RxPort0IntDiff = 0;
- SK_U64 RxPort1IntDiff = 0;
- SK_U64 TxPort0IntDiff = 0;
- SK_U64 TxPort1IntDiff = 0;
-
- if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
- if (pAC->GIni.GIMacsFound == 2) {
- TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
- pAC->DynIrqModInfo.PrevPort1TxIntrCts;
- }
- TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
- pAC->DynIrqModInfo.PrevPort0TxIntrCts;
- } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
- if (pAC->GIni.GIMacsFound == 2) {
- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
- }
- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
- } else {
- if (pAC->GIni.GIMacsFound == 2) {
- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
- TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
- pAC->DynIrqModInfo.PrevPort1TxIntrCts;
- }
- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
- TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
- pAC->DynIrqModInfo.PrevPort0TxIntrCts;
- }
-
- return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function : GetRxCalls
-** Description : This function will return the number of times a receive inter-
-** rupt was processed. This is needed to evaluate any resizing
-** factor.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : SK_U64: the number of RX-ints being processed
-** Notes : It makes only sense to call this function, when dynamic
-** interrupt moderation is applied
-*******************************************************************************/
-
-static SK_U64
-GetRxCalls(SK_AC *pAC) {
- SK_U64 RxPort0IntDiff = 0;
- SK_U64 RxPort1IntDiff = 0;
-
- if (pAC->GIni.GIMacsFound == 2) {
- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
- }
- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
-
- return (RxPort0IntDiff + RxPort1IntDiff);
-}
-
-/*******************************************************************************
-** Function : SetCurrIntCtr
-** Description : Will store the current number orf occured interrupts in the
-** adapter context. This is needed to evaluated the number of
-** interrupts within a current timeframe.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : void (!)
-** Notes : -
-*******************************************************************************/
-
-static void
-SetCurrIntCtr(SK_AC *pAC) {
- if (pAC->GIni.GIMacsFound == 2) {
- pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
- pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
- }
- pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
- pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
-}
-
-/*******************************************************************************
-** Function : IsIntModEnabled()
-** Description : Retrieves the current value of the interrupts moderation
-** command register. Its content determines whether any
-** moderation is running or not.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : SK_TRUE : if mod timer running
-** SK_FALSE : if no moderation is being performed
-** Notes : -
-*******************************************************************************/
-
-static SK_BOOL
-IsIntModEnabled(SK_AC *pAC) {
- unsigned long CtrCmd;
-
- SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
- if ((CtrCmd & TIM_START) == TIM_START) {
- return SK_TRUE;
- } else {
- return SK_FALSE;
- }
-}
-
-/*******************************************************************************
-** Function : EnableIntMod()
-** Description : Enables the interrupt moderation using the values stored in
-** in the pAC->DynIntMod data structure
-** Programmer : Ralph Roesler
-** Last Modified: 22-mar-03
-** Returns : -
-** Notes : -
-*******************************************************************************/
-
-static void
-EnableIntMod(SK_AC *pAC) {
- unsigned long ModBase;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
- ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
- } else {
- ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
- }
-
- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
- SK_OUT32(pAC->IoBase, B2_IRQM_MSK, pAC->DynIrqModInfo.MaskIrqModeration);
- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
- if (M_DIMINFO.DisplayStats) {
- printk("Enabled interrupt moderation (%i ints/sec)\n",
- M_DIMINFO.MaxModIntsPerSec);
- }
-}
-
-/*******************************************************************************
-** Function : DisableIntMod()
-** Description : Disables the interrupt moderation independent of what inter-
-** rupts are running or not
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : -
-** Notes : -
-*******************************************************************************/
-
-static void
-DisableIntMod(SK_AC *pAC) {
-
- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
- if (M_DIMINFO.DisplayStats) {
- printk("Disabled interrupt moderation\n");
- }
-}
-
-/*******************************************************************************
-** Function : ResizeDimTimerDuration();
-** Description : Checks the current used descriptor ratio and resizes the
-** duration timer (longer/smaller) if possible.
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : -
-** Notes : There are both maximum and minimum timer duration value.
-** This function assumes that interrupt moderation is already
-** enabled!
-*******************************************************************************/
-
-static void
-ResizeDimTimerDuration(SK_AC *pAC) {
- SK_BOOL IncreaseTimerDuration;
- int TotalMaxNbrDescr;
- int UsedDescrRatio;
- int RatioDiffAbs;
- int RatioDiffRel;
- int NewMaxModIntsPerSec;
- int ModAdjValue;
- long ModBase;
-
- /*
- ** Check first if we are allowed to perform any modification
- */
- if (IsIntModEnabled(pAC)) {
- if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
- return;
- } else {
- if (M_DIMINFO.ModJustEnabled) {
- M_DIMINFO.ModJustEnabled = SK_FALSE;
- return;
- }
- }
- }
-
- /*
- ** If we got until here, we have to evaluate the amount of the
- ** descriptor ratio change...
- */
- TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
- UsedDescrRatio = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
-
- if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
- RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
- RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
- IncreaseTimerDuration = SK_FALSE; /* in other words: DECREASE */
- } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
- RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
- RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
- IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
- } else {
- RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
- RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
- IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
- }
-
- /*
- ** Now we can determine the change in percent
- */
- if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
- ModAdjValue = 1; /* 1% change - maybe some other value in future */
- } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
- ModAdjValue = 1; /* 1% change - maybe some other value in future */
- } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
- ModAdjValue = 1; /* 1% change - maybe some other value in future */
- } else {
- ModAdjValue = 1; /* 1% change - maybe some other value in future */
- }
-
- if (IncreaseTimerDuration) {
- NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec +
- (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
- } else {
- NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec -
- (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
- }
-
- /*
- ** Check if we exceed boundaries...
- */
- if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
- (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
- if (M_DIMINFO.DisplayStats) {
- printk("Cannot change ModTim from %i to %i ints/sec\n",
- M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
- }
- return;
- } else {
- if (M_DIMINFO.DisplayStats) {
- printk("Resized ModTim from %i to %i ints/sec\n",
- M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
- }
- }
-
- M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
- ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
- } else {
- ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
- }
-
- /*
- ** We do not need to touch any other registers
- */
- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
-}
-
-/*******************************************************************************
-** Function : DisplaySelectedModerationType()
-** Description : Displays what type of moderation we have
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : void!
-** Notes : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationType(SK_AC *pAC) {
-
- if (pAC->DynIrqModInfo.DisplayStats) {
- if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
- printk("Static int moderation runs with %i INTS/sec\n",
- pAC->DynIrqModInfo.MaxModIntsPerSec);
- } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
- if (IsIntModEnabled(pAC)) {
- printk("Dynamic int moderation runs with %i INTS/sec\n",
- pAC->DynIrqModInfo.MaxModIntsPerSec);
- } else {
- printk("Dynamic int moderation currently not applied\n");
- }
- } else {
- printk("No interrupt moderation selected!\n");
- }
- }
-}
-
-/*******************************************************************************
-** Function : DisplaySelectedModerationMask()
-** Description : Displays what interrupts are moderated
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : void!
-** Notes : -
-*******************************************************************************/
-
-static void
-DisplaySelectedModerationMask(SK_AC *pAC) {
-
- if (pAC->DynIrqModInfo.DisplayStats) {
- if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
- switch (pAC->DynIrqModInfo.MaskIrqModeration) {
- case IRQ_MASK_TX_ONLY:
- printk("Only Tx-interrupts are moderated\n");
- break;
- case IRQ_MASK_RX_ONLY:
- printk("Only Rx-interrupts are moderated\n");
- break;
- case IRQ_MASK_SP_ONLY:
- printk("Only special-interrupts are moderated\n");
- break;
- case IRQ_MASK_TX_RX:
- printk("Tx- and Rx-interrupts are moderated\n");
- break;
- case IRQ_MASK_SP_RX:
- printk("Special- and Rx-interrupts are moderated\n");
- break;
- case IRQ_MASK_SP_TX:
- printk("Special- and Tx-interrupts are moderated\n");
- break;
- case IRQ_MASK_RX_TX_SP:
- printk("All Rx-, Tx and special-interrupts are moderated\n");
- break;
- default:
- printk("Don't know what is moderated\n");
- break;
- }
- } else {
- printk("No specific interrupts masked for moderation\n");
- }
- }
-}
-
-/*******************************************************************************
-** Function : DisplayDescrRatio
-** Description : Like the name states...
-** Programmer : Ralph Roesler
-** Last Modified: 23-mar-03
-** Returns : void!
-** Notes : -
-*******************************************************************************/
-
-static void
-DisplayDescrRatio(SK_AC *pAC) {
- int TotalMaxNbrDescr = 0;
-
- if (pAC->DynIrqModInfo.DisplayStats) {
- TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
- printk("Ratio descriptors: %i/%i\n",
- M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
- }
-}
-
-/*******************************************************************************
-**
-** End of file
-**
-*******************************************************************************/
diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
deleted file mode 100644
index 36460694eb8..00000000000
--- a/drivers/net/sk98lin/skethtool.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/******************************************************************************
- *
- * Name: skethtool.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.7 $
- * Date: $Date: 2004/09/29 13:32:07 $
- * Purpose: All functions regarding ethtool handling
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2004 Marvell.
- *
- * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet
- * Server Adapters.
- *
- * Author: Ralph Roesler (rroesler@syskonnect.de)
- * Mirko Lindner (mlindner@syskonnect.de)
- *
- * Address all question to: linux@syskonnect.de
- *
- * The technical manual for the adapters is available from SysKonnect's
- * web pages: www.syskonnect.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.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- *****************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-#include "h/skversion.h"
-
-#include <linux/ethtool.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-
-/******************************************************************************
- *
- * Defines
- *
- *****************************************************************************/
-
-#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
- SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
- SUPPORTED_TP)
-
-#define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
- ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
- ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
- ADVERTISED_TP)
-
-#define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \
- SUPPORTED_FIBRE | \
- SUPPORTED_Autoneg)
-
-#define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \
- ADVERTISED_FIBRE | \
- ADVERTISED_Autoneg)
-
-
-/******************************************************************************
- *
- * Local Functions
- *
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * getSettings - retrieves the current settings of the selected adapter
- *
- * Description:
- * The current configuration of the selected adapter is returned.
- * This configuration involves a)speed, b)duplex and c)autoneg plus
- * a number of other variables.
- *
- * Returns: always 0
- *
- */
-static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
- const DEV_NET *pNet = netdev_priv(dev);
- int port = pNet->PortNr;
- const SK_AC *pAC = pNet->pAC;
- const SK_GEPORT *pPort = &pAC->GIni.GP[port];
-
- static int DuplexAutoNegConfMap[9][3]= {
- { -1 , -1 , -1 },
- { 0 , -1 , -1 },
- { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE },
- { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE },
- { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE },
- { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE },
- { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE },
- { SK_LMODE_AUTOSENSE , -1 , -1 },
- { SK_LMODE_INDETERMINATED, -1 , -1 }
- };
- static int SpeedConfMap[6][2] = {
- { 0 , -1 },
- { SK_LSPEED_AUTO , -1 },
- { SK_LSPEED_10MBPS , SPEED_10 },
- { SK_LSPEED_100MBPS , SPEED_100 },
- { SK_LSPEED_1000MBPS , SPEED_1000 },
- { SK_LSPEED_INDETERMINATED, -1 }
- };
- static int AdvSpeedMap[6][2] = {
- { 0 , -1 },
- { SK_LSPEED_AUTO , -1 },
- { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full },
- { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full },
- { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
- { SK_LSPEED_INDETERMINATED, -1 }
- };
-
- ecmd->phy_address = port;
- ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1];
- ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
- ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
- ecmd->transceiver = XCVR_INTERNAL;
-
- if (pAC->GIni.GICopperType) {
- ecmd->port = PORT_TP;
- ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
- if (pAC->GIni.GIGenesis) {
- ecmd->supported &= ~(SUPPORTED_10baseT_Half);
- ecmd->supported &= ~(SUPPORTED_10baseT_Full);
- ecmd->supported &= ~(SUPPORTED_100baseT_Half);
- ecmd->supported &= ~(SUPPORTED_100baseT_Full);
- } else {
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
- ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
- }
-#ifdef CHIP_ID_YUKON_FE
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
- ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
- ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
- }
-#endif
- }
- if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
- ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
- ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
- }
- } else {
- ecmd->advertising = ecmd->supported;
- }
-
- if (ecmd->autoneg == AUTONEG_ENABLE)
- ecmd->advertising |= ADVERTISED_Autoneg;
- } else {
- ecmd->port = PORT_FIBRE;
- ecmd->supported = SUPP_FIBRE_ALL;
- ecmd->advertising = ADV_FIBRE_ALL;
- }
- return 0;
-}
-
-/*
- * MIB infrastructure uses instance value starting at 1
- * based on board and port.
- */
-static inline u32 pnmiInstance(const DEV_NET *pNet)
-{
- return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr;
-}
-
-/*****************************************************************************
- *
- * setSettings - configures the settings of a selected adapter
- *
- * Description:
- * Possible settings that may be altered are a)speed, b)duplex or
- * c)autonegotiation.
- *
- * Returns:
- * 0: everything fine, no error
- * <0: the return value is the error code of the failure
- */
-static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- u32 instance;
- char buf[4];
- int len = 1;
-
- if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100
- && ecmd->speed != SPEED_1000)
- return -EINVAL;
-
- if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
- return -EINVAL;
-
- if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
- return -EINVAL;
-
- if (ecmd->autoneg == AUTONEG_DISABLE)
- *buf = (ecmd->duplex == DUPLEX_FULL)
- ? SK_LMODE_FULL : SK_LMODE_HALF;
- else
- *buf = (ecmd->duplex == DUPLEX_FULL)
- ? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF;
-
- instance = pnmiInstance(pNet);
- if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE,
- &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
- return -EINVAL;
-
- switch(ecmd->speed) {
- case SPEED_1000:
- *buf = SK_LSPEED_1000MBPS;
- break;
- case SPEED_100:
- *buf = SK_LSPEED_100MBPS;
- break;
- case SPEED_10:
- *buf = SK_LSPEED_10MBPS;
- }
-
- if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
- &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK)
- return -EINVAL;
-
- return 0;
-}
-
-/*****************************************************************************
- *
- * getDriverInfo - returns generic driver and adapter information
- *
- * Description:
- * Generic driver information is returned via this function, such as
- * the name of the driver, its version and and firmware version.
- * In addition to this, the location of the selected adapter is
- * returned as a bus info string (e.g. '01:05.0').
- *
- * Returns: N/A
- *
- */
-static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- const DEV_NET *pNet = netdev_priv(dev);
- const SK_AC *pAC = pNet->pAC;
- char vers[32];
-
- snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)",
- (pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf);
-
- strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
- strcpy(info->version, vers);
- strcpy(info->fw_version, "N/A");
- strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
-}
-
-/*
- * Ethtool statistics support.
- */
-static const char StringsStats[][ETH_GSTRING_LEN] = {
- "rx_packets", "tx_packets",
- "rx_bytes", "tx_bytes",
- "rx_errors", "tx_errors",
- "rx_dropped", "tx_dropped",
- "multicasts", "collisions",
- "rx_length_errors", "rx_buffer_overflow_errors",
- "rx_crc_errors", "rx_frame_errors",
- "rx_too_short_errors", "rx_too_long_errors",
- "rx_carrier_extension_errors", "rx_symbol_errors",
- "rx_llc_mac_size_errors", "rx_carrier_errors",
- "rx_jabber_errors", "rx_missed_errors",
- "tx_abort_collision_errors", "tx_carrier_errors",
- "tx_buffer_underrun_errors", "tx_heartbeat_errors",
- "tx_window_errors",
-};
-
-static int getStatsCount(struct net_device *dev)
-{
- return ARRAY_SIZE(StringsStats);
-}
-
-static void getStrings(struct net_device *dev, u32 stringset, u8 *data)
-{
- switch(stringset) {
- case ETH_SS_STATS:
- memcpy(data, *StringsStats, sizeof(StringsStats));
- break;
- }
-}
-
-static void getEthtoolStats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
-{
- const DEV_NET *pNet = netdev_priv(dev);
- const SK_AC *pAC = pNet->pAC;
- const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
-
- *data++ = pPnmiStruct->Stat[0].StatRxOkCts;
- *data++ = pPnmiStruct->Stat[0].StatTxOkCts;
- *data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts;
- *data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts;
- *data++ = pPnmiStruct->InErrorsCts;
- *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
- *data++ = pPnmiStruct->RxNoBufCts;
- *data++ = pPnmiStruct->TxNoBufCts;
- *data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts;
- *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts;
- *data++ = pPnmiStruct->Stat[0].StatRxRuntCts;
- *data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts;
- *data++ = pPnmiStruct->Stat[0].StatRxFcsCts;
- *data++ = pPnmiStruct->Stat[0].StatRxFramingCts;
- *data++ = pPnmiStruct->Stat[0].StatRxShortsCts;
- *data++ = pPnmiStruct->Stat[0].StatRxTooLongCts;
- *data++ = pPnmiStruct->Stat[0].StatRxCextCts;
- *data++ = pPnmiStruct->Stat[0].StatRxSymbolCts;
- *data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts;
- *data++ = pPnmiStruct->Stat[0].StatRxCarrierCts;
- *data++ = pPnmiStruct->Stat[0].StatRxJabberCts;
- *data++ = pPnmiStruct->Stat[0].StatRxMissedCts;
- *data++ = pAC->stats.tx_aborted_errors;
- *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
- *data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts;
- *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts;
- *data++ = pAC->stats.tx_window_errors;
-}
-
-
-/*****************************************************************************
- *
- * toggleLeds - Changes the LED state of an adapter
- *
- * Description:
- * This function changes the current state of all LEDs of an adapter so
- * that it can be located by a user.
- *
- * Returns: N/A
- *
- */
-static void toggleLeds(DEV_NET *pNet, int on)
-{
- SK_AC *pAC = pNet->pAC;
- int port = pNet->PortNr;
- void __iomem *io = pAC->IoBase;
-
- if (pAC->GIni.GIGenesis) {
- SK_OUT8(io, MR_ADDR(port,LNK_LED_REG),
- on ? SK_LNK_ON : SK_LNK_OFF);
- SkGeYellowLED(pAC, io,
- on ? (LED_ON >> 1) : (LED_OFF >> 1));
- SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI),
- on ? SK_LED_TST : SK_LED_DIS);
-
- if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM)
- SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL,
- on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF);
- else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE)
- SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG,
- on ? 0x0800 : PHY_L_LC_LEDT);
- else
- SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI),
- on ? SK_LED_TST : SK_LED_DIS);
- } else {
- const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON) |
- PHY_M_LED_MO_10(MO_LED_ON) |
- PHY_M_LED_MO_100(MO_LED_ON) |
- PHY_M_LED_MO_1000(MO_LED_ON) |
- PHY_M_LED_MO_RX(MO_LED_ON));
- const u16 YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF) |
- PHY_M_LED_MO_10(MO_LED_OFF) |
- PHY_M_LED_MO_100(MO_LED_OFF) |
- PHY_M_LED_MO_1000(MO_LED_OFF) |
- PHY_M_LED_MO_RX(MO_LED_OFF));
-
-
- SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0);
- SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER,
- on ? YukLedOn : YukLedOff);
- }
-}
-
-/*****************************************************************************
- *
- * skGeBlinkTimer - Changes the LED state of an adapter
- *
- * Description:
- * This function changes the current state of all LEDs of an adapter so
- * that it can be located by a user. If the requested time interval for
- * this test has elapsed, this function cleans up everything that was
- * temporarily setup during the locate NIC test. This involves of course
- * also closing or opening any adapter so that the initial board state
- * is recovered.
- *
- * Returns: N/A
- *
- */
-void SkGeBlinkTimer(unsigned long data)
-{
- struct net_device *dev = (struct net_device *) data;
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- toggleLeds(pNet, pAC->LedsOn);
-
- pAC->LedsOn = !pAC->LedsOn;
- mod_timer(&pAC->BlinkTimer, jiffies + HZ/4);
-}
-
-/*****************************************************************************
- *
- * locateDevice - start the locate NIC feature of the elected adapter
- *
- * Description:
- * This function is used if the user want to locate a particular NIC.
- * All LEDs are regularly switched on and off, so the NIC can easily
- * be identified.
- *
- * Returns:
- * ==0: everything fine, no error, locateNIC test was started
- * !=0: one locateNIC test runs already
- *
- */
-static int locateDevice(struct net_device *dev, u32 data)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
- data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
-
- /* start blinking */
- pAC->LedsOn = 0;
- mod_timer(&pAC->BlinkTimer, jiffies);
- msleep_interruptible(data * 1000);
- del_timer_sync(&pAC->BlinkTimer);
- toggleLeds(pNet, 0);
-
- return 0;
-}
-
-/*****************************************************************************
- *
- * getPauseParams - retrieves the pause parameters
- *
- * Description:
- * All current pause parameters of a selected adapter are placed
- * in the passed ethtool_pauseparam structure and are returned.
- *
- * Returns: N/A
- *
- */
-static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
-
- epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
- (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM);
-
- epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND);
- epause->autoneg = epause->rx_pause || epause->tx_pause;
-}
-
-/*****************************************************************************
- *
- * setPauseParams - configures the pause parameters of an adapter
- *
- * Description:
- * This function sets the Rx or Tx pause parameters
- *
- * Returns:
- * ==0: everything fine, no error
- * !=0: the return value is the error code of the failure
- */
-static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr];
- u32 instance = pnmiInstance(pNet);
- struct ethtool_pauseparam old;
- u8 oldspeed = pPort->PLinkSpeedUsed;
- char buf[4];
- int len = 1;
- int ret;
-
- /*
- ** we have to determine the current settings to see if
- ** the operator requested any modification of the flow
- ** control parameters...
- */
- getPauseParams(dev, &old);
-
- /*
- ** perform modifications regarding the changes
- ** requested by the operator
- */
- if (epause->autoneg != old.autoneg)
- *buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC;
- else {
- if (epause->rx_pause && epause->tx_pause)
- *buf = SK_FLOW_MODE_SYMMETRIC;
- else if (epause->rx_pause && !epause->tx_pause)
- *buf = SK_FLOW_MODE_SYM_OR_REM;
- else if (!epause->rx_pause && epause->tx_pause)
- *buf = SK_FLOW_MODE_LOC_SEND;
- else
- *buf = SK_FLOW_MODE_NONE;
- }
-
- ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
- &buf, &len, instance, pNet->NetNr);
-
- if (ret != SK_PNMI_ERR_OK) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
- ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret));
- goto err;
- }
-
- /*
- ** It may be that autoneg has been disabled! Therefore
- ** set the speed to the previously used value...
- */
- if (!epause->autoneg) {
- len = 1;
- ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
- &oldspeed, &len, instance, pNet->NetNr);
- if (ret != SK_PNMI_ERR_OK)
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
- ("ethtool (sk98lin): error setting speed (%i)\n", ret));
- }
- err:
- return ret ? -EIO : 0;
-}
-
-/* Only Yukon supports checksum offload. */
-static int setScatterGather(struct net_device *dev, u32 data)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
- return -EOPNOTSUPP;
- return ethtool_op_set_sg(dev, data);
-}
-
-static int setTxCsum(struct net_device *dev, u32 data)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
- return -EOPNOTSUPP;
-
- return ethtool_op_set_tx_csum(dev, data);
-}
-
-static u32 getRxCsum(struct net_device *dev)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- return pAC->RxPort[pNet->PortNr].RxCsum;
-}
-
-static int setRxCsum(struct net_device *dev, u32 data)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
-
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS)
- return -EOPNOTSUPP;
-
- pAC->RxPort[pNet->PortNr].RxCsum = data != 0;
- return 0;
-}
-
-static int getRegsLen(struct net_device *dev)
-{
- return 0x4000;
-}
-
-/*
- * Returns copy of whole control register region
- * Note: skip RAM address register because accessing it will
- * cause bus hangs!
- */
-static void getRegs(struct net_device *dev, struct ethtool_regs *regs,
- void *p)
-{
- DEV_NET *pNet = netdev_priv(dev);
- const void __iomem *io = pNet->pAC->IoBase;
-
- regs->version = 1;
- memset(p, 0, regs->len);
- memcpy_fromio(p, io, B3_RAM_ADDR);
-
- memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
- regs->len - B3_RI_WTO_R1);
-}
-
-const struct ethtool_ops SkGeEthtoolOps = {
- .get_settings = getSettings,
- .set_settings = setSettings,
- .get_drvinfo = getDriverInfo,
- .get_strings = getStrings,
- .get_stats_count = getStatsCount,
- .get_ethtool_stats = getEthtoolStats,
- .phys_id = locateDevice,
- .get_pauseparam = getPauseParams,
- .set_pauseparam = setPauseParams,
- .get_link = ethtool_op_get_link,
- .get_perm_addr = ethtool_op_get_perm_addr,
- .get_sg = ethtool_op_get_sg,
- .set_sg = setScatterGather,
- .get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = setTxCsum,
- .get_rx_csum = getRxCsum,
- .set_rx_csum = setRxCsum,
- .get_regs = getRegs,
- .get_regs_len = getRegsLen,
-};
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
deleted file mode 100644
index bf218621db1..00000000000
--- a/drivers/net/sk98lin/skge.c
+++ /dev/null
@@ -1,5211 +0,0 @@
-/******************************************************************************
- *
- * Name: skge.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.45 $
- * Date: $Date: 2004/02/12 14:41:02 $
- * Purpose: The main driver source module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet
- * Server Adapters.
- *
- * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
- * SysKonnects GEnesis Solaris driver
- * Author: Christoph Goos (cgoos@syskonnect.de)
- * Mirko Lindner (mlindner@syskonnect.de)
- *
- * Address all question to: linux@syskonnect.de
- *
- * The technical manual for the adapters is available from SysKonnect's
- * web pages: www.syskonnect.com
- * Goto "Support" and search Knowledge Base for "manual".
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Possible compiler options (#define xxx / -Dxxx):
- *
- * debugging can be enable by changing SK_DEBUG_CHKMOD and
- * SK_DEBUG_CHKCAT in makefile (described there).
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This is the main module of the Linux GE driver.
- *
- * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h
- * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters.
- * Those are used for drivers on multiple OS', so some thing may seem
- * unnecessary complicated on Linux. Please do not try to 'clean up'
- * them without VERY good reasons, because this will make it more
- * difficult to keep the Linux driver in synchronisation with the
- * other versions.
- *
- * Include file hierarchy:
- *
- * <linux/module.h>
- *
- * "h/skdrv1st.h"
- * <linux/types.h>
- * <linux/kernel.h>
- * <linux/string.h>
- * <linux/errno.h>
- * <linux/ioport.h>
- * <linux/slab.h>
- * <linux/interrupt.h>
- * <linux/pci.h>
- * <linux/bitops.h>
- * <asm/byteorder.h>
- * <asm/io.h>
- * <linux/netdevice.h>
- * <linux/etherdevice.h>
- * <linux/skbuff.h>
- * those three depending on kernel version used:
- * <linux/bios32.h>
- * <linux/init.h>
- * <asm/uaccess.h>
- * <net/checksum.h>
- *
- * "h/skerror.h"
- * "h/skdebug.h"
- * "h/sktypes.h"
- * "h/lm80.h"
- * "h/xmac_ii.h"
- *
- * "h/skdrv2nd.h"
- * "h/skqueue.h"
- * "h/skgehwt.h"
- * "h/sktimer.h"
- * "h/ski2c.h"
- * "h/skgepnmi.h"
- * "h/skvpd.h"
- * "h/skgehw.h"
- * "h/skgeinit.h"
- * "h/skaddr.h"
- * "h/skgesirq.h"
- * "h/skrlmt.h"
- *
- ******************************************************************************/
-
-#include "h/skversion.h"
-
-#include <linux/in.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/ip.h>
-#include <linux/mii.h>
-#include <linux/mm.h>
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/*******************************************************************************
- *
- * Defines
- *
- ******************************************************************************/
-
-/* for debuging on x86 only */
-/* #define BREAKPOINT() asm(" int $3"); */
-
-/* use the transmit hw checksum driver functionality */
-#define USE_SK_TX_CHECKSUM
-
-/* use the receive hw checksum driver functionality */
-#define USE_SK_RX_CHECKSUM
-
-/* use the scatter-gather functionality with sendfile() */
-#define SK_ZEROCOPY
-
-/* use of a transmit complete interrupt */
-#define USE_TX_COMPLETE
-
-/*
- * threshold for copying small receive frames
- * set to 0 to avoid copying, set to 9001 to copy all frames
- */
-#define SK_COPY_THRESHOLD 50
-
-/* number of adapters that can be configured via command line params */
-#define SK_MAX_CARD_PARAM 16
-
-
-
-/*
- * use those defines for a compile-in version of the driver instead
- * of command line parameters
- */
-// #define LINK_SPEED_A {"Auto", }
-// #define LINK_SPEED_B {"Auto", }
-// #define AUTO_NEG_A {"Sense", }
-// #define AUTO_NEG_B {"Sense", }
-// #define DUP_CAP_A {"Both", }
-// #define DUP_CAP_B {"Both", }
-// #define FLOW_CTRL_A {"SymOrRem", }
-// #define FLOW_CTRL_B {"SymOrRem", }
-// #define ROLE_A {"Auto", }
-// #define ROLE_B {"Auto", }
-// #define PREF_PORT {"A", }
-// #define CON_TYPE {"Auto", }
-// #define RLMT_MODE {"CheckLinkState", }
-
-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
-#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
-#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
-
-
-/* Set blink mode*/
-#define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \
- SK_DUP_LED_NORMAL | \
- SK_LED_LINK100_ON)
-
-
-/* Isr return value */
-#define SkIsrRetVar irqreturn_t
-#define SkIsrRetNone IRQ_NONE
-#define SkIsrRetHandled IRQ_HANDLED
-
-
-/*******************************************************************************
- *
- * Local Function Prototypes
- *
- ******************************************************************************/
-
-static void FreeResources(struct SK_NET_DEVICE *dev);
-static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
-static SK_BOOL BoardAllocMem(SK_AC *pAC);
-static void BoardFreeMem(SK_AC *pAC);
-static void BoardInitMem(SK_AC *pAC);
-static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
-static SkIsrRetVar SkGeIsr(int irq, void *dev_id);
-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id);
-static int SkGeOpen(struct SK_NET_DEVICE *dev);
-static int SkGeClose(struct SK_NET_DEVICE *dev);
-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev);
-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p);
-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev);
-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev);
-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd);
-static void GetConfiguration(SK_AC*);
-static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*);
-static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
-static void FillRxRing(SK_AC*, RX_PORT*);
-static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*);
-static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
-static void ClearAndStartRx(SK_AC*, int);
-static void ClearTxIrq(SK_AC*, int, int);
-static void ClearRxRing(SK_AC*, RX_PORT*);
-static void ClearTxRing(SK_AC*, TX_PORT*);
-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
-static void PortReInitBmu(SK_AC*, int);
-static int SkGeIocMib(DEV_NET*, unsigned int, int);
-static int SkGeInitPCI(SK_AC *pAC);
-static void StartDrvCleanupTimer(SK_AC *pAC);
-static void StopDrvCleanupTimer(SK_AC *pAC);
-static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
-
-#ifdef SK_DIAG_SUPPORT
-static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName);
-static int SkDrvInitAdapter(SK_AC *pAC, int devNbr);
-static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
-#endif
-
-/*******************************************************************************
- *
- * Extern Function Prototypes
- *
- ******************************************************************************/
-extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);
-extern void SkDimDisplayModerationSettings(SK_AC *pAC);
-extern void SkDimStartModerationTimer(SK_AC *pAC);
-extern void SkDimModerate(SK_AC *pAC);
-extern void SkGeBlinkTimer(unsigned long data);
-
-#ifdef DEBUG
-static void DumpMsg(struct sk_buff*, char*);
-static void DumpData(char*, int);
-static void DumpLong(char*, int);
-#endif
-
-/* global variables *********************************************************/
-static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
-extern const struct ethtool_ops SkGeEthtoolOps;
-
-/* local variables **********************************************************/
-static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
-static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
-
-/*****************************************************************************
- *
- * SkPciWriteCfgDWord - write a 32 bit value to pci config space
- *
- * Description:
- * This routine writes a 32 bit value to the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-static inline int SkPciWriteCfgDWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U32 Val) /* pointer to store the read value */
-{
- pci_write_config_dword(pAC->PciDev, PciAddr, Val);
- return(0);
-} /* SkPciWriteCfgDWord */
-
-/*****************************************************************************
- *
- * SkGeInitPCI - Init the PCI resources
- *
- * Description:
- * This function initialize the PCI resources and IO
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-static __devinit int SkGeInitPCI(SK_AC *pAC)
-{
- struct SK_NET_DEVICE *dev = pAC->dev[0];
- struct pci_dev *pdev = pAC->PciDev;
- int retval;
-
- dev->mem_start = pci_resource_start (pdev, 0);
- pci_set_master(pdev);
-
- retval = pci_request_regions(pdev, "sk98lin");
- if (retval)
- goto out;
-
-#ifdef SK_BIG_ENDIAN
- /*
- * On big endian machines, we use the adapter's aibility of
- * reading the descriptors as big endian.
- */
- {
- SK_U32 our2;
- SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2);
- our2 |= PCI_REV_DESC;
- SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2);
- }
-#endif
-
- /*
- * Remap the regs into kernel space.
- */
- pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000);
- if (!pAC->IoBase) {
- retval = -EIO;
- goto out_release;
- }
-
- return 0;
-
- out_release:
- pci_release_regions(pdev);
- out:
- return retval;
-}
-
-
-/*****************************************************************************
- *
- * FreeResources - release resources allocated for adapter
- *
- * Description:
- * This function releases the IRQ, unmaps the IO and
- * frees the desriptor ring.
- *
- * Returns: N/A
- *
- */
-static void FreeResources(struct SK_NET_DEVICE *dev)
-{
-SK_U32 AllocFlag;
-DEV_NET *pNet;
-SK_AC *pAC;
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
- AllocFlag = pAC->AllocFlag;
- if (pAC->PciDev) {
- pci_release_regions(pAC->PciDev);
- }
- if (AllocFlag & SK_ALLOC_IRQ) {
- free_irq(dev->irq, dev);
- }
- if (pAC->IoBase) {
- iounmap(pAC->IoBase);
- }
- if (pAC->pDescrMem) {
- BoardFreeMem(pAC);
- }
-
-} /* FreeResources */
-
-MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
-MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
-MODULE_LICENSE("GPL");
-
-#ifdef LINK_SPEED_A
-static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED;
-#else
-static char *Speed_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef LINK_SPEED_B
-static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED;
-#else
-static char *Speed_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_A
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;
-#else
-static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_A
-static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;
-#else
-static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_A
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;
-#else
-static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_A
-static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;
-#else
-static char *Role_A[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef AUTO_NEG_B
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;
-#else
-static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef DUP_CAP_B
-static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;
-#else
-static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef FLOW_CTRL_B
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;
-#else
-static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef ROLE_B
-static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;
-#else
-static char *Role_B[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef CON_TYPE
-static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE;
-#else
-static char *ConType[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef PREF_PORT
-static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;
-#else
-static char *PrefPort[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-#ifdef RLMT_MODE
-static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
-#else
-static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
-#endif
-
-static int IntsPerSec[SK_MAX_CARD_PARAM];
-static char *Moderation[SK_MAX_CARD_PARAM];
-static char *ModerationMask[SK_MAX_CARD_PARAM];
-static char *AutoSizing[SK_MAX_CARD_PARAM];
-static char *Stats[SK_MAX_CARD_PARAM];
-
-module_param_array(Speed_A, charp, NULL, 0);
-module_param_array(Speed_B, charp, NULL, 0);
-module_param_array(AutoNeg_A, charp, NULL, 0);
-module_param_array(AutoNeg_B, charp, NULL, 0);
-module_param_array(DupCap_A, charp, NULL, 0);
-module_param_array(DupCap_B, charp, NULL, 0);
-module_param_array(FlowCtrl_A, charp, NULL, 0);
-module_param_array(FlowCtrl_B, charp, NULL, 0);
-module_param_array(Role_A, charp, NULL, 0);
-module_param_array(Role_B, charp, NULL, 0);
-module_param_array(ConType, charp, NULL, 0);
-module_param_array(PrefPort, charp, NULL, 0);
-module_param_array(RlmtMode, charp, NULL, 0);
-/* used for interrupt moderation */
-module_param_array(IntsPerSec, int, NULL, 0);
-module_param_array(Moderation, charp, NULL, 0);
-module_param_array(Stats, charp, NULL, 0);
-module_param_array(ModerationMask, charp, NULL, 0);
-module_param_array(AutoSizing, charp, NULL, 0);
-
-/*****************************************************************************
- *
- * SkGeBoardInit - do level 0 and 1 initialization
- *
- * Description:
- * This function prepares the board hardware for running. The desriptor
- * ring is set up, the IRQ is allocated and the configuration settings
- * are examined.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC)
-{
-short i;
-unsigned long Flags;
-char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */
-char *VerStr = VER_STRING;
-int Ret; /* return code of request_irq */
-SK_BOOL DualNet;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("IoBase: %08lX\n", (unsigned long)pAC->IoBase));
- for (i=0; i<SK_MAX_MACS; i++) {
- pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0];
- pAC->TxPort[i][0].PortIndex = i;
- pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i];
- pAC->RxPort[i].PortIndex = i;
- }
-
- /* Initialize the mutexes */
- for (i=0; i<SK_MAX_MACS; i++) {
- spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
- spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
- }
- spin_lock_init(&pAC->SlowPathLock);
-
- /* setup phy_id blink timer */
- pAC->BlinkTimer.function = SkGeBlinkTimer;
- pAC->BlinkTimer.data = (unsigned long) dev;
- init_timer(&pAC->BlinkTimer);
-
- /* level 0 init common modules here */
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- /* Does a RESET on board ...*/
- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) {
- printk("HWInit (0) failed.\n");
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return -EIO;
- }
- SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA);
- SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA);
- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA);
- SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA);
- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA);
- SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
-
- pAC->BoardLevel = SK_INIT_DATA;
- pAC->RxBufSize = ETH_BUF_SIZE;
-
- SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
- SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
-
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- /* level 1 init common modules here (HW init) */
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
- printk("sk98lin: HWInit (1) failed.\n");
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return -EIO;
- }
- SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
-
- /* Set chipset type support */
- pAC->ChipsetType = 0;
- if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
- (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
- pAC->ChipsetType = 1;
- }
-
- GetConfiguration(pAC);
- if (pAC->RlmtNets == 2) {
- pAC->GIni.GIPortUsage = SK_MUL_LINK;
- }
-
- pAC->BoardLevel = SK_INIT_IO;
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- if (pAC->GIni.GIMacsFound == 2) {
- Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
- } else if (pAC->GIni.GIMacsFound == 1) {
- Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED,
- "sk98lin", dev);
- } else {
- printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
- pAC->GIni.GIMacsFound);
- return -EIO;
- }
-
- if (Ret) {
- printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
- dev->irq);
- return Ret;
- }
- pAC->AllocFlag |= SK_ALLOC_IRQ;
-
- /* Alloc memory for this board (Mem for RxD/TxD) : */
- if(!BoardAllocMem(pAC)) {
- printk("No memory for descriptor rings.\n");
- return -ENOMEM;
- }
-
- BoardInitMem(pAC);
- /* tschilling: New common function with minimum size check. */
- DualNet = SK_FALSE;
- if (pAC->RlmtNets == 2) {
- DualNet = SK_TRUE;
- }
-
- if (SkGeInitAssignRamToQueues(
- pAC,
- pAC->ActivePort,
- DualNet)) {
- BoardFreeMem(pAC);
- printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
- return -EIO;
- }
-
- return (0);
-} /* SkGeBoardInit */
-
-
-/*****************************************************************************
- *
- * BoardAllocMem - allocate the memory for the descriptor rings
- *
- * Description:
- * This function allocates the memory for all descriptor rings.
- * Each ring is aligned for the desriptor alignment and no ring
- * has a 4 GByte boundary in it (because the upper 32 bit must
- * be constant for all descriptiors in one rings).
- *
- * Returns:
- * SK_TRUE, if all memory could be allocated
- * SK_FALSE, if not
- */
-static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC)
-{
-caddr_t pDescrMem; /* pointer to descriptor memory area */
-size_t AllocLength; /* length of complete descriptor area */
-int i; /* loop counter */
-unsigned long BusAddr;
-
-
- /* rings plus one for alignment (do not cross 4 GB boundary) */
- /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */
-#if (BITS_PER_LONG == 32)
- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
- + RX_RING_SIZE + 8;
-#endif
-
- pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength,
- &pAC->pDescrMemDMA);
-
- if (pDescrMem == NULL) {
- return (SK_FALSE);
- }
- pAC->pDescrMem = pDescrMem;
- BusAddr = (unsigned long) pAC->pDescrMemDMA;
-
- /* Descriptors need 8 byte alignment, and this is ensured
- * by pci_alloc_consistent.
- */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
- ("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n",
- i, (unsigned long) pDescrMem,
- BusAddr));
- pAC->TxPort[i][0].pTxDescrRing = pDescrMem;
- pAC->TxPort[i][0].VTxDescrRing = BusAddr;
- pDescrMem += TX_RING_SIZE;
- BusAddr += TX_RING_SIZE;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
- ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n",
- i, (unsigned long) pDescrMem,
- (unsigned long)BusAddr));
- pAC->RxPort[i].pRxDescrRing = pDescrMem;
- pAC->RxPort[i].VRxDescrRing = BusAddr;
- pDescrMem += RX_RING_SIZE;
- BusAddr += RX_RING_SIZE;
- } /* for */
-
- return (SK_TRUE);
-} /* BoardAllocMem */
-
-
-/****************************************************************************
- *
- * BoardFreeMem - reverse of BoardAllocMem
- *
- * Description:
- * Free all memory allocated in BoardAllocMem: adapter context,
- * descriptor rings, locks.
- *
- * Returns: N/A
- */
-static void BoardFreeMem(
-SK_AC *pAC)
-{
-size_t AllocLength; /* length of complete descriptor area */
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("BoardFreeMem\n"));
-#if (BITS_PER_LONG == 32)
- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
-#else
- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
- + RX_RING_SIZE + 8;
-#endif
-
- pci_free_consistent(pAC->PciDev, AllocLength,
- pAC->pDescrMem, pAC->pDescrMemDMA);
- pAC->pDescrMem = NULL;
-} /* BoardFreeMem */
-
-
-/*****************************************************************************
- *
- * BoardInitMem - initiate the descriptor rings
- *
- * Description:
- * This function sets the descriptor rings up in memory.
- * The adapter is initialized with the descriptor start addresses.
- *
- * Returns: N/A
- */
-static __devinit void BoardInitMem(SK_AC *pAC)
-{
-int i; /* loop counter */
-int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/
-int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("BoardInitMem\n"));
-
- RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
- pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
- TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
- pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
-
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- SetupRing(
- pAC,
- pAC->TxPort[i][0].pTxDescrRing,
- pAC->TxPort[i][0].VTxDescrRing,
- (RXD**)&pAC->TxPort[i][0].pTxdRingHead,
- (RXD**)&pAC->TxPort[i][0].pTxdRingTail,
- (RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
- &pAC->TxPort[i][0].TxdRingFree,
- SK_TRUE);
- SetupRing(
- pAC,
- pAC->RxPort[i].pRxDescrRing,
- pAC->RxPort[i].VRxDescrRing,
- &pAC->RxPort[i].pRxdRingHead,
- &pAC->RxPort[i].pRxdRingTail,
- &pAC->RxPort[i].pRxdRingPrev,
- &pAC->RxPort[i].RxdRingFree,
- SK_FALSE);
- }
-} /* BoardInitMem */
-
-
-/*****************************************************************************
- *
- * SetupRing - create one descriptor ring
- *
- * Description:
- * This function creates one descriptor ring in the given memory area.
- * The head, tail and number of free descriptors in the ring are set.
- *
- * Returns:
- * none
- */
-static void SetupRing(
-SK_AC *pAC,
-void *pMemArea, /* a pointer to the memory area for the ring */
-uintptr_t VMemArea, /* the virtual bus address of the memory area */
-RXD **ppRingHead, /* address where the head should be written */
-RXD **ppRingTail, /* address where the tail should be written */
-RXD **ppRingPrev, /* address where the tail should be written */
-int *pRingFree, /* address where the # of free descr. goes */
-SK_BOOL IsTx) /* flag: is this a tx ring */
-{
-int i; /* loop counter */
-int DescrSize; /* the size of a descriptor rounded up to alignment*/
-int DescrNum; /* number of descriptors per ring */
-RXD *pDescr; /* pointer to a descriptor (receive or transmit) */
-RXD *pNextDescr; /* pointer to the next descriptor */
-RXD *pPrevDescr; /* pointer to the previous descriptor */
-uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */
-
- if (IsTx == SK_TRUE) {
- DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) *
- DESCR_ALIGN;
- DescrNum = TX_RING_SIZE / DescrSize;
- } else {
- DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) *
- DESCR_ALIGN;
- DescrNum = RX_RING_SIZE / DescrSize;
- }
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
- ("Descriptor size: %d Descriptor Number: %d\n",
- DescrSize,DescrNum));
-
- pDescr = (RXD*) pMemArea;
- pPrevDescr = NULL;
- pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
- VNextDescr = VMemArea + DescrSize;
- for(i=0; i<DescrNum; i++) {
- /* set the pointers right */
- pDescr->VNextRxd = VNextDescr & 0xffffffffULL;
- pDescr->pNextRxd = pNextDescr;
- if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN;
-
- /* advance one step */
- pPrevDescr = pDescr;
- pDescr = pNextDescr;
- pNextDescr = (RXD*) (((char*)pDescr) + DescrSize);
- VNextDescr += DescrSize;
- }
- pPrevDescr->pNextRxd = (RXD*) pMemArea;
- pPrevDescr->VNextRxd = VMemArea;
- pDescr = (RXD*) pMemArea;
- *ppRingHead = (RXD*) pMemArea;
- *ppRingTail = *ppRingHead;
- *ppRingPrev = pPrevDescr;
- *pRingFree = DescrNum;
-} /* SetupRing */
-
-
-/*****************************************************************************
- *
- * PortReInitBmu - re-initiate the descriptor rings for one port
- *
- * Description:
- * This function reinitializes the descriptor rings of one port
- * in memory. The port must be stopped before.
- * The HW is initialized with the descriptor start addresses.
- *
- * Returns:
- * none
- */
-static void PortReInitBmu(
-SK_AC *pAC, /* pointer to adapter context */
-int PortIndex) /* index of the port for which to re-init */
-{
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("PortReInitBmu "));
-
- /* set address of first descriptor of ring in BMU */
- SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L,
- (uint32_t)(((caddr_t)
- (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
- pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
- pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) &
- 0xFFFFFFFF));
- SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H,
- (uint32_t)(((caddr_t)
- (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) -
- pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing +
- pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32));
- SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L,
- (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
- pAC->RxPort[PortIndex].pRxDescrRing +
- pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF));
- SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H,
- (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) -
- pAC->RxPort[PortIndex].pRxDescrRing +
- pAC->RxPort[PortIndex].VRxDescrRing) >> 32));
-} /* PortReInitBmu */
-
-
-/****************************************************************************
- *
- * SkGeIsr - handle adapter interrupts
- *
- * Description:
- * The interrupt routine is called when the network adapter
- * generates an interrupt. It may also be called if another device
- * shares this interrupt vector with the driver.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsr(int irq, void *dev_id)
-{
-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
-DEV_NET *pNet;
-SK_AC *pAC;
-SK_U32 IntSrc; /* interrupts source register contents */
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- /*
- * Check and process if its our interrupt
- */
- SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
- if (IntSrc == 0) {
- return SkIsrRetNone;
- }
-
- while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
- if (IntSrc & IS_IRQ_SW) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("Software IRQ\n"));
- }
-#endif
- if (IntSrc & IS_R1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF RX1 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
- SK_PNMI_CNT_RX_INTR(pAC, 0);
- }
- if (IntSrc & IS_R2_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF RX2 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
- SK_PNMI_CNT_RX_INTR(pAC, 1);
- }
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IS_XA1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF AS TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 0);
- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- }
- if (IntSrc & IS_XA2_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF AS TX2 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 1);
- spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
- }
-#if 0 /* only if sync. queues used */
- if (IntSrc & IS_XS1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF SY TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 1);
- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
- }
- if (IntSrc & IS_XS2_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF SY TX2 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 1);
- spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
- ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
- }
-#endif
-#endif
-
- /* do all IO at once */
- if (IntSrc & IS_R1_F)
- ClearAndStartRx(pAC, 0);
- if (IntSrc & IS_R2_F)
- ClearAndStartRx(pAC, 1);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IS_XA1_F)
- ClearTxIrq(pAC, 0, TX_PRIO_LOW);
- if (IntSrc & IS_XA2_F)
- ClearTxIrq(pAC, 1, TX_PRIO_LOW);
-#endif
- SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
- } /* while (IntSrc & IRQ_MASK != 0) */
-
- IntSrc &= pAC->GIni.GIValIrqMask;
- if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
- ("SPECIAL IRQ DP-Cards => %x\n", IntSrc));
- pAC->CheckQueue = SK_FALSE;
- spin_lock(&pAC->SlowPathLock);
- if (IntSrc & SPECIAL_IRQS)
- SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
-
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock(&pAC->SlowPathLock);
- }
- /*
- * do it all again is case we cleared an interrupt that
- * came in after handling the ring (OUTs may be delayed
- * in hardware buffers, but are through after IN)
- *
- * rroesler: has been commented out and shifted to
- * SkGeDrvEvent(), because it is timer
- * guarded now
- *
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
- ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
- */
-
- if (pAC->CheckQueue) {
- pAC->CheckQueue = SK_FALSE;
- spin_lock(&pAC->SlowPathLock);
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock(&pAC->SlowPathLock);
- }
-
- /* IRQ is processed - Enable IRQs again*/
- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
- return SkIsrRetHandled;
-} /* SkGeIsr */
-
-
-/****************************************************************************
- *
- * SkGeIsrOnePort - handle adapter interrupts for single port adapter
- *
- * Description:
- * The interrupt routine is called when the network adapter
- * generates an interrupt. It may also be called if another device
- * shares this interrupt vector with the driver.
- * This is the same as above, but handles only one port.
- *
- * Returns: N/A
- *
- */
-static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id)
-{
-struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
-DEV_NET *pNet;
-SK_AC *pAC;
-SK_U32 IntSrc; /* interrupts source register contents */
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- /*
- * Check and process if its our interrupt
- */
- SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
- if (IntSrc == 0) {
- return SkIsrRetNone;
- }
-
- while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
-#if 0 /* software irq currently not used */
- if (IntSrc & IS_IRQ_SW) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("Software IRQ\n"));
- }
-#endif
- if (IntSrc & IS_R1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF RX1 IRQ\n"));
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
- SK_PNMI_CNT_RX_INTR(pAC, 0);
- }
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IS_XA1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF AS TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 0);
- spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
- }
-#if 0 /* only if sync. queues used */
- if (IntSrc & IS_XS1_F) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_INT_SRC,
- ("EOF SY TX1 IRQ\n"));
- SK_PNMI_CNT_TX_INTR(pAC, 0);
- spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
- spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
- ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
- }
-#endif
-#endif
-
- /* do all IO at once */
- if (IntSrc & IS_R1_F)
- ClearAndStartRx(pAC, 0);
-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
- if (IntSrc & IS_XA1_F)
- ClearTxIrq(pAC, 0, TX_PRIO_LOW);
-#endif
- SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
- } /* while (IntSrc & IRQ_MASK != 0) */
-
- IntSrc &= pAC->GIni.GIValIrqMask;
- if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
- ("SPECIAL IRQ SP-Cards => %x\n", IntSrc));
- pAC->CheckQueue = SK_FALSE;
- spin_lock(&pAC->SlowPathLock);
- if (IntSrc & SPECIAL_IRQS)
- SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
-
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock(&pAC->SlowPathLock);
- }
- /*
- * do it all again is case we cleared an interrupt that
- * came in after handling the ring (OUTs may be delayed
- * in hardware buffers, but are through after IN)
- *
- * rroesler: has been commented out and shifted to
- * SkGeDrvEvent(), because it is timer
- * guarded now
- *
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
- */
-
- /* IRQ is processed - Enable IRQs again*/
- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
-
- return SkIsrRetHandled;
-} /* SkGeIsrOnePort */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/****************************************************************************
- *
- * SkGePollController - polling receive, for netconsole
- *
- * Description:
- * Polling receive - used by netconsole and other diagnostic tools
- * to allow network i/o with interrupts disabled.
- *
- * Returns: N/A
- */
-static void SkGePollController(struct net_device *dev)
-{
- disable_irq(dev->irq);
- SkGeIsr(dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-/****************************************************************************
- *
- * SkGeOpen - handle start of initialized adapter
- *
- * Description:
- * This function starts the initialized adapter.
- * The board level variable is set and the adapter is
- * brought to full functionality.
- * The device flags are set for operation.
- * Do all necessary level 2 initialization, enable interrupts and
- * give start command to RLMT.
- *
- * Returns:
- * 0 on success
- * != 0 on error
- */
-static int SkGeOpen(
-struct SK_NET_DEVICE *dev)
-{
- DEV_NET *pNet;
- SK_AC *pAC;
- unsigned long Flags; /* for spin lock */
- int i;
- SK_EVPARA EvPara; /* an event parameter union */
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
-
-#ifdef SK_DIAG_SUPPORT
- if (pAC->DiagModeActive == DIAG_ACTIVE) {
- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
- return (-1); /* still in use by diag; deny actions */
- }
- }
-#endif
-
- /* Set blink mode */
- if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab ))
- pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE;
-
- if (pAC->BoardLevel == SK_INIT_DATA) {
- /* level 1 init common modules here */
- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
- printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name);
- return (-1);
- }
- SkI2cInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkEventInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkPnmiInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkAddrInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkRlmtInit (pAC, pAC->IoBase, SK_INIT_IO);
- SkTimerInit (pAC, pAC->IoBase, SK_INIT_IO);
- pAC->BoardLevel = SK_INIT_IO;
- }
-
- if (pAC->BoardLevel != SK_INIT_RUN) {
- /* tschilling: Level 2 init modules here, check return value. */
- if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) {
- printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name);
- return (-1);
- }
- SkI2cInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkEventInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkPnmiInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkAddrInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkRlmtInit (pAC, pAC->IoBase, SK_INIT_RUN);
- SkTimerInit (pAC, pAC->IoBase, SK_INIT_RUN);
- pAC->BoardLevel = SK_INIT_RUN;
- }
-
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- /* Enable transmit descriptor polling. */
- SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
- FillRxRing(pAC, &pAC->RxPort[i]);
- }
- SkGeYellowLED(pAC, pAC->IoBase, 1);
-
- StartDrvCleanupTimer(pAC);
- SkDimEnableModerationIfNeeded(pAC);
- SkDimDisplayModerationSettings(pAC);
-
- pAC->GIni.GIValIrqMask &= IRQ_MASK;
-
- /* enable Interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
- SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
- if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
- EvPara.Para32[0] = pAC->RlmtNets;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
- EvPara);
- EvPara.Para32[0] = pAC->RlmtMode;
- EvPara.Para32[1] = 0;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
- EvPara);
- }
-
- EvPara.Para32[0] = pNet->NetNr;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- pAC->MaxPorts++;
-
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeOpen suceeded\n"));
-
- return (0);
-} /* SkGeOpen */
-
-
-/****************************************************************************
- *
- * SkGeClose - Stop initialized adapter
- *
- * Description:
- * Close initialized adapter.
- *
- * Returns:
- * 0 - on success
- * error code - on error
- */
-static int SkGeClose(
-struct SK_NET_DEVICE *dev)
-{
- DEV_NET *pNet;
- DEV_NET *newPtrNet;
- SK_AC *pAC;
-
- unsigned long Flags; /* for spin lock */
- int i;
- int PortIdx;
- SK_EVPARA EvPara;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
-#ifdef SK_DIAG_SUPPORT
- if (pAC->DiagModeActive == DIAG_ACTIVE) {
- if (pAC->DiagFlowCtrl == SK_FALSE) {
- /*
- ** notify that the interface which has been closed
- ** by operator interaction must not be started up
- ** again when the DIAG has finished.
- */
- newPtrNet = netdev_priv(pAC->dev[0]);
- if (newPtrNet == pNet) {
- pAC->WasIfUp[0] = SK_FALSE;
- } else {
- pAC->WasIfUp[1] = SK_FALSE;
- }
- return 0; /* return to system everything is fine... */
- } else {
- pAC->DiagFlowCtrl = SK_FALSE;
- }
- }
-#endif
-
- netif_stop_queue(dev);
-
- if (pAC->RlmtNets == 1)
- PortIdx = pAC->ActivePort;
- else
- PortIdx = pNet->NetNr;
-
- StopDrvCleanupTimer(pAC);
-
- /*
- * Clear multicast table, promiscuous mode ....
- */
- SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
- SK_PROM_MODE_NONE);
-
- if (pAC->MaxPorts == 1) {
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- /* disable interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- EvPara.Para32[0] = pNet->NetNr;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- /* stop the hardware */
- SkGeDeInit(pAC, pAC->IoBase);
- pAC->BoardLevel = SK_INIT_DATA;
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- } else {
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- EvPara.Para32[0] = pNet->NetNr;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- /* Stop port */
- spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
- [TX_PRIO_LOW].TxDesRingLock, Flags);
- SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
- SK_STOP_ALL, SK_HARD_RST);
- spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
- [TX_PRIO_LOW].TxDesRingLock, Flags);
- }
-
- if (pAC->RlmtNets == 1) {
- /* clear all descriptor rings */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
- ClearRxRing(pAC, &pAC->RxPort[i]);
- ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
- }
- } else {
- /* clear port descriptor rings */
- ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
- ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
- ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
- }
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeClose: done "));
-
- SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
- SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct),
- sizeof(SK_PNMI_STRUCT_DATA));
-
- pAC->MaxPorts--;
-
- return (0);
-} /* SkGeClose */
-
-
-/*****************************************************************************
- *
- * SkGeXmit - Linux frame transmit function
- *
- * Description:
- * The system calls this function to send frames onto the wire.
- * It puts the frame in the tx descriptor ring. If the ring is
- * full then, the 'tbusy' flag is set.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- * WARNING: returning 1 in 'tbusy' case caused system crashes (double
- * allocated skb's) !!!
- */
-static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)
-{
-DEV_NET *pNet;
-SK_AC *pAC;
-int Rc; /* return code of XmitFrame */
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- if ((!skb_shinfo(skb)->nr_frags) ||
- (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) {
- /* Don't activate scatter-gather and hardware checksum */
-
- if (pAC->RlmtNets == 2)
- Rc = XmitFrame(
- pAC,
- &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
- skb);
- else
- Rc = XmitFrame(
- pAC,
- &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
- skb);
- } else {
- /* scatter-gather and hardware TCP checksumming anabled*/
- if (pAC->RlmtNets == 2)
- Rc = XmitFrameSG(
- pAC,
- &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW],
- skb);
- else
- Rc = XmitFrameSG(
- pAC,
- &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW],
- skb);
- }
-
- /* Transmitter out of resources? */
- if (Rc <= 0) {
- netif_stop_queue(dev);
- }
-
- /* If not taken, give buffer ownership back to the
- * queueing layer.
- */
- if (Rc < 0)
- return (1);
-
- dev->trans_start = jiffies;
- return (0);
-} /* SkGeXmit */
-
-
-/*****************************************************************************
- *
- * XmitFrame - fill one socket buffer into the transmit ring
- *
- * Description:
- * This function puts a message into the transmit descriptor ring
- * if there is a descriptors left.
- * Linux skb's consist of only one continuous buffer.
- * The first step locks the ring. It is held locked
- * all time to avoid problems with SWITCH_../PORT_RESET.
- * Then the descriptoris allocated.
- * The second part is linking the buffer to the descriptor.
- * At the very last, the Control field of the descriptor
- * is made valid for the BMU and a start TX command is given
- * if necessary.
- *
- * Returns:
- * > 0 - on succes: the number of bytes in the message
- * = 0 - on resource shortage: this frame sent or dropped, now
- * the ring is full ( -> set tbusy)
- * < 0 - on failure: other problems ( -> return failure to upper layers)
- */
-static int XmitFrame(
-SK_AC *pAC, /* pointer to adapter context */
-TX_PORT *pTxPort, /* pointer to struct of port to send to */
-struct sk_buff *pMessage) /* pointer to send-message */
-{
- TXD *pTxd; /* the rxd to fill */
- TXD *pOldTxd;
- unsigned long Flags;
- SK_U64 PhysAddr;
- int BytesSend = pMessage->len;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X"));
-
- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-#ifndef USE_TX_COMPLETE
- FreeTxDescriptors(pAC, pTxPort);
-#endif
- if (pTxPort->TxdRingFree == 0) {
- /*
- ** no enough free descriptors in ring at the moment.
- ** Maybe free'ing some old one help?
- */
- FreeTxDescriptors(pAC, pTxPort);
- if (pTxPort->TxdRingFree == 0) {
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
- SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_TX_PROGRESS,
- ("XmitFrame failed\n"));
- /*
- ** the desired message can not be sent
- ** Because tbusy seems to be set, the message
- ** should not be freed here. It will be used
- ** by the scheduler of the ethernet handler
- */
- return (-1);
- }
- }
-
- /*
- ** If the passed socket buffer is of smaller MTU-size than 60,
- ** copy everything into new buffer and fill all bytes between
- ** the original packet end and the new packet end of 60 with 0x00.
- ** This is to resolve faulty padding by the HW with 0xaa bytes.
- */
- if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
- if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
- return 0;
- }
- pMessage->len = C_LEN_ETHERNET_MINSIZE;
- }
-
- /*
- ** advance head counter behind descriptor needed for this frame,
- ** so that needed descriptor is reserved from that on. The next
- ** action will be to add the passed buffer to the TX-descriptor
- */
- pTxd = pTxPort->pTxdRingHead;
- pTxPort->pTxdRingHead = pTxd->pNextTxd;
- pTxPort->TxdRingFree--;
-
-#ifdef SK_DUMP_TX
- DumpMsg(pMessage, "XmitFrame");
-#endif
-
- /*
- ** First step is to map the data to be sent via the adapter onto
- ** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4
- ** and 2.6 need to use pci_map_page() for that mapping.
- */
- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
- virt_to_page(pMessage->data),
- ((unsigned long) pMessage->data & ~PAGE_MASK),
- pMessage->len,
- PCI_DMA_TODEVICE);
- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
- pTxd->pMBuf = pMessage;
-
- if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
- u16 hdrlen = skb_transport_offset(pMessage);
- u16 offset = hdrlen + pMessage->csum_offset;
-
- if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
- (pAC->GIni.GIChipRev == 0) &&
- (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
- pTxd->TBControl = BMU_TCP_CHECK;
- } else {
- pTxd->TBControl = BMU_UDP_CHECK;
- }
-
- pTxd->TcpSumOfs = 0;
- pTxd->TcpSumSt = hdrlen;
- pTxd->TcpSumWr = offset;
-
- pTxd->TBControl |= BMU_OWN | BMU_STF |
- BMU_SW | BMU_EOF |
-#ifdef USE_TX_COMPLETE
- BMU_IRQ_EOF |
-#endif
- pMessage->len;
- } else {
- pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK |
- BMU_SW | BMU_EOF |
-#ifdef USE_TX_COMPLETE
- BMU_IRQ_EOF |
-#endif
- pMessage->len;
- }
-
- /*
- ** If previous descriptor already done, give TX start cmd
- */
- pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd);
- if ((pOldTxd->TBControl & BMU_OWN) == 0) {
- SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
- }
-
- /*
- ** after releasing the lock, the skb may immediately be free'd
- */
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
- if (pTxPort->TxdRingFree != 0) {
- return (BytesSend);
- } else {
- return (0);
- }
-
-} /* XmitFrame */
-
-/*****************************************************************************
- *
- * XmitFrameSG - fill one socket buffer into the transmit ring
- * (use SG and TCP/UDP hardware checksumming)
- *
- * Description:
- * This function puts a message into the transmit descriptor ring
- * if there is a descriptors left.
- *
- * Returns:
- * > 0 - on succes: the number of bytes in the message
- * = 0 - on resource shortage: this frame sent or dropped, now
- * the ring is full ( -> set tbusy)
- * < 0 - on failure: other problems ( -> return failure to upper layers)
- */
-static int XmitFrameSG(
-SK_AC *pAC, /* pointer to adapter context */
-TX_PORT *pTxPort, /* pointer to struct of port to send to */
-struct sk_buff *pMessage) /* pointer to send-message */
-{
-
- TXD *pTxd;
- TXD *pTxdFst;
- TXD *pTxdLst;
- int CurrFrag;
- int BytesSend;
- skb_frag_t *sk_frag;
- SK_U64 PhysAddr;
- unsigned long Flags;
- SK_U32 Control;
-
- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
-#ifndef USE_TX_COMPLETE
- FreeTxDescriptors(pAC, pTxPort);
-#endif
- if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) {
- FreeTxDescriptors(pAC, pTxPort);
- if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) {
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
- SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex);
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_TX_PROGRESS,
- ("XmitFrameSG failed - Ring full\n"));
- /* this message can not be sent now */
- return(-1);
- }
- }
-
- pTxd = pTxPort->pTxdRingHead;
- pTxdFst = pTxd;
- pTxdLst = pTxd;
- BytesSend = 0;
-
- /*
- ** Map the first fragment (header) into the DMA-space
- */
- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
- virt_to_page(pMessage->data),
- ((unsigned long) pMessage->data & ~PAGE_MASK),
- skb_headlen(pMessage),
- PCI_DMA_TODEVICE);
-
- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
-
- /*
- ** Does the HW need to evaluate checksum for TCP or UDP packets?
- */
- if (pMessage->ip_summed == CHECKSUM_PARTIAL) {
- u16 hdrlen = skb_transport_offset(pMessage);
- u16 offset = hdrlen + pMessage->csum_offset;
-
- Control = BMU_STFWD;
-
- /*
- ** We have to use the opcode for tcp here, because the
- ** opcode for udp is not working in the hardware yet
- ** (Revision 2.0)
- */
- if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) &&
- (pAC->GIni.GIChipRev == 0) &&
- (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
- Control |= BMU_TCP_CHECK;
- } else {
- Control |= BMU_UDP_CHECK;
- }
-
- pTxd->TcpSumOfs = 0;
- pTxd->TcpSumSt = hdrlen;
- pTxd->TcpSumWr = offset;
- } else
- Control = BMU_CHECK | BMU_SW;
-
- pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage);
-
- pTxd = pTxd->pNextTxd;
- pTxPort->TxdRingFree--;
- BytesSend += skb_headlen(pMessage);
-
- /*
- ** Browse over all SG fragments and map each of them into the DMA space
- */
- for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) {
- sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag];
- /*
- ** we already have the proper value in entry
- */
- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
- sk_frag->page,
- sk_frag->page_offset,
- sk_frag->size,
- PCI_DMA_TODEVICE);
-
- pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
- pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
- pTxd->pMBuf = pMessage;
-
- pTxd->TBControl = Control | BMU_OWN | sk_frag->size;
-
- /*
- ** Do we have the last fragment?
- */
- if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) {
-#ifdef USE_TX_COMPLETE
- pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF;
-#else
- pTxd->TBControl |= BMU_EOF;
-#endif
- pTxdFst->TBControl |= BMU_OWN | BMU_SW;
- }
- pTxdLst = pTxd;
- pTxd = pTxd->pNextTxd;
- pTxPort->TxdRingFree--;
- BytesSend += sk_frag->size;
- }
-
- /*
- ** If previous descriptor already done, give TX start cmd
- */
- if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) {
- SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START);
- }
-
- pTxPort->pTxdRingPrev = pTxdLst;
- pTxPort->pTxdRingHead = pTxd;
-
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-
- if (pTxPort->TxdRingFree > 0) {
- return (BytesSend);
- } else {
- return (0);
- }
-}
-
-/*****************************************************************************
- *
- * FreeTxDescriptors - release descriptors from the descriptor ring
- *
- * Description:
- * This function releases descriptors from a transmit ring if they
- * have been sent by the BMU.
- * If a descriptors is sent, it can be freed and the message can
- * be freed, too.
- * The SOFTWARE controllable bit is used to prevent running around a
- * completely free ring for ever. If this bit is no set in the
- * frame (by XmitFrame), this frame has never been sent or is
- * already freed.
- * The Tx descriptor ring lock must be held while calling this function !!!
- *
- * Returns:
- * none
- */
-static void FreeTxDescriptors(
-SK_AC *pAC, /* pointer to the adapter context */
-TX_PORT *pTxPort) /* pointer to destination port structure */
-{
-TXD *pTxd; /* pointer to the checked descriptor */
-TXD *pNewTail; /* pointer to 'end' of the ring */
-SK_U32 Control; /* TBControl field of descriptor */
-SK_U64 PhysAddr; /* address of DMA mapping */
-
- pNewTail = pTxPort->pTxdRingTail;
- pTxd = pNewTail;
- /*
- ** loop forever; exits if BMU_SW bit not set in start frame
- ** or BMU_OWN bit set in any frame
- */
- while (1) {
- Control = pTxd->TBControl;
- if ((Control & BMU_SW) == 0) {
- /*
- ** software controllable bit is set in first
- ** fragment when given to BMU. Not set means that
- ** this fragment was never sent or is already
- ** freed ( -> ring completely free now).
- */
- pTxPort->pTxdRingTail = pTxd;
- netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
- return;
- }
- if (Control & BMU_OWN) {
- pTxPort->pTxdRingTail = pTxd;
- if (pTxPort->TxdRingFree > 0) {
- netif_wake_queue(pAC->dev[pTxPort->PortIndex]);
- }
- return;
- }
-
- /*
- ** release the DMA mapping, because until not unmapped
- ** this buffer is considered being under control of the
- ** adapter card!
- */
- PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32;
- PhysAddr |= (SK_U64) pTxd->VDataLow;
- pci_unmap_page(pAC->PciDev, PhysAddr,
- pTxd->pMBuf->len,
- PCI_DMA_TODEVICE);
-
- if (Control & BMU_EOF)
- DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */
-
- pTxPort->TxdRingFree++;
- pTxd->TBControl &= ~BMU_SW;
- pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */
- } /* while(forever) */
-} /* FreeTxDescriptors */
-
-/*****************************************************************************
- *
- * FillRxRing - fill the receive ring with valid descriptors
- *
- * Description:
- * This function fills the receive ring descriptors with data
- * segments and makes them valid for the BMU.
- * The active ring is filled completely, if possible.
- * The non-active ring is filled only partial to save memory.
- *
- * Description of rx ring structure:
- * head - points to the descriptor which will be used next by the BMU
- * tail - points to the next descriptor to give to the BMU
- *
- * Returns: N/A
- */
-static void FillRxRing(
-SK_AC *pAC, /* pointer to the adapter context */
-RX_PORT *pRxPort) /* ptr to port struct for which the ring
- should be filled */
-{
-unsigned long Flags;
-
- spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
- while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) {
- if(!FillRxDescriptor(pAC, pRxPort))
- break;
- }
- spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* FillRxRing */
-
-
-/*****************************************************************************
- *
- * FillRxDescriptor - fill one buffer into the receive ring
- *
- * Description:
- * The function allocates a new receive buffer and
- * puts it into the next descriptor.
- *
- * Returns:
- * SK_TRUE - a buffer was added to the ring
- * SK_FALSE - a buffer could not be added
- */
-static SK_BOOL FillRxDescriptor(
-SK_AC *pAC, /* pointer to the adapter context struct */
-RX_PORT *pRxPort) /* ptr to port struct of ring to fill */
-{
-struct sk_buff *pMsgBlock; /* pointer to a new message block */
-RXD *pRxd; /* the rxd to fill */
-SK_U16 Length; /* data fragment length */
-SK_U64 PhysAddr; /* physical address of a rx buffer */
-
- pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);
- if (pMsgBlock == NULL) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_ENTRY,
- ("%s: Allocation of rx buffer failed !\n",
- pAC->dev[pRxPort->PortIndex]->name));
- SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex);
- return(SK_FALSE);
- }
- skb_reserve(pMsgBlock, 2); /* to align IP frames */
- /* skb allocated ok, so add buffer */
- pRxd = pRxPort->pRxdRingTail;
- pRxPort->pRxdRingTail = pRxd->pNextRxd;
- pRxPort->RxdRingFree--;
- Length = pAC->RxBufSize;
- PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
- virt_to_page(pMsgBlock->data),
- ((unsigned long) pMsgBlock->data &
- ~PAGE_MASK),
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
-
- pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
- pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32);
- pRxd->pMBuf = pMsgBlock;
- pRxd->RBControl = BMU_OWN |
- BMU_STF |
- BMU_IRQ_EOF |
- BMU_TCP_CHECK |
- Length;
- return (SK_TRUE);
-
-} /* FillRxDescriptor */
-
-
-/*****************************************************************************
- *
- * ReQueueRxBuffer - fill one buffer back into the receive ring
- *
- * Description:
- * Fill a given buffer back into the rx ring. The buffer
- * has been previously allocated and aligned, and its phys.
- * address calculated, so this is no more necessary.
- *
- * Returns: N/A
- */
-static void ReQueueRxBuffer(
-SK_AC *pAC, /* pointer to the adapter context struct */
-RX_PORT *pRxPort, /* ptr to port struct of ring to fill */
-struct sk_buff *pMsg, /* pointer to the buffer */
-SK_U32 PhysHigh, /* phys address high dword */
-SK_U32 PhysLow) /* phys address low dword */
-{
-RXD *pRxd; /* the rxd to fill */
-SK_U16 Length; /* data fragment length */
-
- pRxd = pRxPort->pRxdRingTail;
- pRxPort->pRxdRingTail = pRxd->pNextRxd;
- pRxPort->RxdRingFree--;
- Length = pAC->RxBufSize;
-
- pRxd->VDataLow = PhysLow;
- pRxd->VDataHigh = PhysHigh;
- pRxd->pMBuf = pMsg;
- pRxd->RBControl = BMU_OWN |
- BMU_STF |
- BMU_IRQ_EOF |
- BMU_TCP_CHECK |
- Length;
- return;
-} /* ReQueueRxBuffer */
-
-/*****************************************************************************
- *
- * ReceiveIrq - handle a receive IRQ
- *
- * Description:
- * This function is called when a receive IRQ is set.
- * It walks the receive descriptor ring and sends up all
- * frames that are complete.
- *
- * Returns: N/A
- */
-static void ReceiveIrq(
- SK_AC *pAC, /* pointer to adapter context */
- RX_PORT *pRxPort, /* pointer to receive port struct */
- SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */
-{
-RXD *pRxd; /* pointer to receive descriptors */
-SK_U32 Control; /* control field of descriptor */
-struct sk_buff *pMsg; /* pointer to message holding frame */
-struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
-int FrameLength; /* total length of received frame */
-SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
-SK_EVPARA EvPara; /* an event parameter union */
-unsigned long Flags; /* for spin lock */
-int PortIndex = pRxPort->PortIndex;
-unsigned int Offset;
-unsigned int NumBytes;
-unsigned int ForRlmt;
-SK_BOOL IsBc;
-SK_BOOL IsMc;
-SK_BOOL IsBadFrame; /* Bad frame */
-
-SK_U32 FrameStat;
-SK_U64 PhysAddr;
-
-rx_start:
- /* do forever; exit if BMU_OWN found */
- for ( pRxd = pRxPort->pRxdRingHead ;
- pRxPort->RxdRingFree < pAC->RxDescrPerRing ;
- pRxd = pRxd->pNextRxd,
- pRxPort->pRxdRingHead = pRxd,
- pRxPort->RxdRingFree ++) {
-
- /*
- * For a better understanding of this loop
- * Go through every descriptor beginning at the head
- * Please note: the ring might be completely received so the OWN bit
- * set is not a good crirteria to leave that loop.
- * Therefore the RingFree counter is used.
- * On entry of this loop pRxd is a pointer to the Rxd that needs
- * to be checked next.
- */
-
- Control = pRxd->RBControl;
-
- /* check if this descriptor is ready */
- if ((Control & BMU_OWN) != 0) {
- /* this descriptor is not yet ready */
- /* This is the usual end of the loop */
- /* We don't need to start the ring again */
- FillRxRing(pAC, pRxPort);
- return;
- }
- pAC->DynIrqModInfo.NbrProcessedDescr++;
-
- /* get length of frame and check it */
- FrameLength = Control & BMU_BBC;
- if (FrameLength > pAC->RxBufSize) {
- goto rx_failed;
- }
-
- /* check for STF and EOF */
- if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) {
- goto rx_failed;
- }
-
- /* here we have a complete frame in the ring */
- pMsg = pRxd->pMBuf;
-
- FrameStat = pRxd->FrameStat;
-
- /* check for frame length mismatch */
-#define XMR_FS_LEN_SHIFT 18
-#define GMR_FS_LEN_SHIFT 16
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
- if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("skge: Frame length mismatch (%u/%u).\n",
- FrameLength,
- (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
- goto rx_failed;
- }
- }
- else {
- if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("skge: Frame length mismatch (%u/%u).\n",
- FrameLength,
- (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
- goto rx_failed;
- }
- }
-
- /* Set Rx Status */
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
- IsBc = (FrameStat & XMR_FS_BC) != 0;
- IsMc = (FrameStat & XMR_FS_MC) != 0;
- IsBadFrame = (FrameStat &
- (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0;
- } else {
- IsBc = (FrameStat & GMR_FS_BC) != 0;
- IsMc = (FrameStat & GMR_FS_MC) != 0;
- IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) ||
- ((FrameStat & GMR_FS_RX_OK) == 0));
- }
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
- ("Received frame of length %d on port %d\n",
- FrameLength, PortIndex));
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0,
- ("Number of free rx descriptors: %d\n",
- pRxPort->RxdRingFree));
-/* DumpMsg(pMsg, "Rx"); */
-
- if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
-#if 0
- (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
-#endif
- /* there is a receive error in this frame */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("skge: Error in received frame, dropped!\n"
- "Control: %x\nRxStat: %x\n",
- Control, FrameStat));
-
- ReQueueRxBuffer(pAC, pRxPort, pMsg,
- pRxd->VDataHigh, pRxd->VDataLow);
-
- continue;
- }
-
- /*
- * if short frame then copy data to reduce memory waste
- */
- if ((FrameLength < SK_COPY_THRESHOLD) &&
- ((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) {
- /*
- * Short frame detected and allocation successfull
- */
- /* use new skb and copy data */
- skb_reserve(pNewMsg, 2);
- skb_put(pNewMsg, FrameLength);
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
-
- pci_dma_sync_single_for_cpu(pAC->PciDev,
- (dma_addr_t) PhysAddr,
- FrameLength,
- PCI_DMA_FROMDEVICE);
- skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength);
-
- pci_dma_sync_single_for_device(pAC->PciDev,
- (dma_addr_t) PhysAddr,
- FrameLength,
- PCI_DMA_FROMDEVICE);
- ReQueueRxBuffer(pAC, pRxPort, pMsg,
- pRxd->VDataHigh, pRxd->VDataLow);
-
- pMsg = pNewMsg;
-
- }
- else {
- /*
- * if large frame, or SKB allocation failed, pass
- * the SKB directly to the networking
- */
-
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
-
- /* release the DMA mapping */
- pci_unmap_single(pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
-
- /* set length in message */
- skb_put(pMsg, FrameLength);
- } /* frame > SK_COPY_TRESHOLD */
-
-#ifdef USE_SK_RX_CHECKSUM
- pMsg->csum = pRxd->TcpSums & 0xffff;
- pMsg->ip_summed = CHECKSUM_COMPLETE;
-#else
- pMsg->ip_summed = CHECKSUM_NONE;
-#endif
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
- ForRlmt = SK_RLMT_RX_PROTOCOL;
-#if 0
- IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
-#endif
- SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
- IsBc, &Offset, &NumBytes);
- if (NumBytes != 0) {
-#if 0
- IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
-#endif
- SK_RLMT_LOOKAHEAD(pAC, PortIndex,
- &pMsg->data[Offset],
- IsBc, IsMc, &ForRlmt);
- }
- if (ForRlmt == SK_RLMT_RX_PROTOCOL) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W"));
- /* send up only frames from active port */
- if ((PortIndex == pAC->ActivePort) ||
- (pAC->RlmtNets == 2)) {
- /* frame for upper layer */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
-#ifdef xDEBUG
- DumpMsg(pMsg, "Rx");
-#endif
- SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
- FrameLength, pRxPort->PortIndex);
-
- pMsg->protocol = eth_type_trans(pMsg,
- pAC->dev[pRxPort->PortIndex]);
- netif_rx(pMsg);
- pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
- }
- else {
- /* drop frame */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("D"));
- DEV_KFREE_SKB(pMsg);
- }
-
- } /* if not for rlmt */
- else {
- /* packet for rlmt */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
- pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
- pAC->IoBase, FrameLength);
- if (pRlmtMbuf != NULL) {
- pRlmtMbuf->pNext = NULL;
- pRlmtMbuf->Length = FrameLength;
- pRlmtMbuf->PortIdx = PortIndex;
- EvPara.pParaPtr = pRlmtMbuf;
- memcpy((char*)(pRlmtMbuf->pData),
- (char*)(pMsg->data),
- FrameLength);
-
- /* SlowPathLock needed? */
- if (SlowPathLock == SK_TRUE) {
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- SkEventQueue(pAC, SKGE_RLMT,
- SK_RLMT_PACKET_RECEIVED,
- EvPara);
- pAC->CheckQueue = SK_TRUE;
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- } else {
- SkEventQueue(pAC, SKGE_RLMT,
- SK_RLMT_PACKET_RECEIVED,
- EvPara);
- pAC->CheckQueue = SK_TRUE;
- }
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
- SK_DBGCAT_DRV_RX_PROGRESS,
- ("Q"));
- }
- if ((pAC->dev[pRxPort->PortIndex]->flags &
- (IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
- (ForRlmt & SK_RLMT_RX_PROTOCOL) ==
- SK_RLMT_RX_PROTOCOL) {
- pMsg->protocol = eth_type_trans(pMsg,
- pAC->dev[pRxPort->PortIndex]);
- netif_rx(pMsg);
- pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
- }
- else {
- DEV_KFREE_SKB(pMsg);
- }
-
- } /* if packet for rlmt */
- } /* for ... scanning the RXD ring */
-
- /* RXD ring is empty -> fill and restart */
- FillRxRing(pAC, pRxPort);
- /* do not start if called from Close */
- if (pAC->BoardLevel > SK_INIT_DATA) {
- ClearAndStartRx(pAC, PortIndex);
- }
- return;
-
-rx_failed:
- /* remove error frame */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
- ("Schrottdescriptor, length: 0x%x\n", FrameLength));
-
- /* release the DMA mapping */
-
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_unmap_page(pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
- DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
- pRxd->pMBuf = NULL;
- pRxPort->RxdRingFree++;
- pRxPort->pRxdRingHead = pRxd->pNextRxd;
- goto rx_start;
-
-} /* ReceiveIrq */
-
-
-/*****************************************************************************
- *
- * ClearAndStartRx - give a start receive command to BMU, clear IRQ
- *
- * Description:
- * This function sends a start command and a clear interrupt
- * command for one receive queue to the BMU.
- *
- * Returns: N/A
- * none
- */
-static void ClearAndStartRx(
-SK_AC *pAC, /* pointer to the adapter context */
-int PortIndex) /* index of the receive port (XMAC) */
-{
- SK_OUT8(pAC->IoBase,
- RxQueueAddr[PortIndex]+Q_CSR,
- CSR_START | CSR_IRQ_CL_F);
-} /* ClearAndStartRx */
-
-
-/*****************************************************************************
- *
- * ClearTxIrq - give a clear transmit IRQ command to BMU
- *
- * Description:
- * This function sends a clear tx IRQ command for one
- * transmit queue to the BMU.
- *
- * Returns: N/A
- */
-static void ClearTxIrq(
-SK_AC *pAC, /* pointer to the adapter context */
-int PortIndex, /* index of the transmit port (XMAC) */
-int Prio) /* priority or normal queue */
-{
- SK_OUT8(pAC->IoBase,
- TxQueueAddr[PortIndex][Prio]+Q_CSR,
- CSR_IRQ_CL_F);
-} /* ClearTxIrq */
-
-
-/*****************************************************************************
- *
- * ClearRxRing - remove all buffers from the receive ring
- *
- * Description:
- * This function removes all receive buffers from the ring.
- * The receive BMU must be stopped before calling this function.
- *
- * Returns: N/A
- */
-static void ClearRxRing(
-SK_AC *pAC, /* pointer to adapter context */
-RX_PORT *pRxPort) /* pointer to rx port struct */
-{
-RXD *pRxd; /* pointer to the current descriptor */
-unsigned long Flags;
-SK_U64 PhysAddr;
-
- if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) {
- return;
- }
- spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags);
- pRxd = pRxPort->pRxdRingHead;
- do {
- if (pRxd->pMBuf != NULL) {
-
- PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
- PhysAddr |= (SK_U64) pRxd->VDataLow;
- pci_unmap_page(pAC->PciDev,
- PhysAddr,
- pAC->RxBufSize - 2,
- PCI_DMA_FROMDEVICE);
- DEV_KFREE_SKB(pRxd->pMBuf);
- pRxd->pMBuf = NULL;
- }
- pRxd->RBControl &= BMU_OWN;
- pRxd = pRxd->pNextRxd;
- pRxPort->RxdRingFree++;
- } while (pRxd != pRxPort->pRxdRingTail);
- pRxPort->pRxdRingTail = pRxPort->pRxdRingHead;
- spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);
-} /* ClearRxRing */
-
-/*****************************************************************************
- *
- * ClearTxRing - remove all buffers from the transmit ring
- *
- * Description:
- * This function removes all transmit buffers from the ring.
- * The transmit BMU must be stopped before calling this function
- * and transmitting at the upper level must be disabled.
- * The BMU own bit of all descriptors is cleared, the rest is
- * done by calling FreeTxDescriptors.
- *
- * Returns: N/A
- */
-static void ClearTxRing(
-SK_AC *pAC, /* pointer to adapter context */
-TX_PORT *pTxPort) /* pointer to tx prt struct */
-{
-TXD *pTxd; /* pointer to the current descriptor */
-int i;
-unsigned long Flags;
-
- spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
- pTxd = pTxPort->pTxdRingHead;
- for (i=0; i<pAC->TxDescrPerRing; i++) {
- pTxd->TBControl &= ~BMU_OWN;
- pTxd = pTxd->pNextTxd;
- }
- FreeTxDescriptors(pAC, pTxPort);
- spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
-} /* ClearTxRing */
-
-/*****************************************************************************
- *
- * SkGeSetMacAddr - Set the hardware MAC address
- *
- * Description:
- * This function sets the MAC address used by the adapter.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p)
-{
-
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC *pAC = pNet->pAC;
-
-struct sockaddr *addr = p;
-unsigned long Flags;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeSetMacAddr starts now...\n"));
- if(netif_running(dev))
- return -EBUSY;
-
- memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
- if (pAC->RlmtNets == 2)
- SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
- (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
- else
- SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
- (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
-
-
-
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return 0;
-} /* SkGeSetMacAddr */
-
-
-/*****************************************************************************
- *
- * SkGeSetRxMode - set receive mode
- *
- * Description:
- * This function sets the receive mode of an adapter. The adapter
- * supports promiscuous mode, allmulticast mode and a number of
- * multicast addresses. If more multicast addresses the available
- * are selected, a hash function in the hardware is used.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static void SkGeSetRxMode(struct SK_NET_DEVICE *dev)
-{
-
-DEV_NET *pNet;
-SK_AC *pAC;
-
-struct dev_mc_list *pMcList;
-int i;
-int PortIdx;
-unsigned long Flags;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeSetRxMode starts now... "));
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
- if (pAC->RlmtNets == 1)
- PortIdx = pAC->ActivePort;
- else
- PortIdx = pNet->NetNr;
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- if (dev->flags & IFF_PROMISC) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("PROMISCUOUS mode\n"));
- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
- SK_PROM_MODE_LLC);
- } else if (dev->flags & IFF_ALLMULTI) {
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("ALLMULTI mode\n"));
- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
- SK_PROM_MODE_ALL_MC);
- } else {
- SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx,
- SK_PROM_MODE_NONE);
- SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0);
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("Number of MC entries: %d ", dev->mc_count));
-
- pMcList = dev->mc_list;
- for (i=0; i<dev->mc_count; i++, pMcList = pMcList->next) {
- SkAddrMcAdd(pAC, pAC->IoBase, PortIdx,
- (SK_MAC_ADDR*)pMcList->dmi_addr, 0);
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA,
- ("%02x:%02x:%02x:%02x:%02x:%02x\n",
- pMcList->dmi_addr[0],
- pMcList->dmi_addr[1],
- pMcList->dmi_addr[2],
- pMcList->dmi_addr[3],
- pMcList->dmi_addr[4],
- pMcList->dmi_addr[5]));
- }
- SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx);
- }
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- return;
-} /* SkGeSetRxMode */
-
-
-/*****************************************************************************
- *
- * SkGeChangeMtu - set the MTU to another value
- *
- * Description:
- * This function sets is called whenever the MTU size is changed
- * (ifconfig mtu xxx dev ethX). If the MTU is bigger than standard
- * ethernet MTU size, long frame support is activated.
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
-{
-DEV_NET *pNet;
-struct net_device *pOtherDev;
-SK_AC *pAC;
-unsigned long Flags;
-int i;
-SK_EVPARA EvPara;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeChangeMtu starts now...\n"));
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
- return -EINVAL;
- }
-
- if(pAC->BoardLevel != SK_INIT_RUN) {
- return -EINVAL;
- }
-
-#ifdef SK_DIAG_SUPPORT
- if (pAC->DiagModeActive == DIAG_ACTIVE) {
- if (pAC->DiagFlowCtrl == SK_FALSE) {
- return -1; /* still in use, deny any actions of MTU */
- } else {
- pAC->DiagFlowCtrl = SK_FALSE;
- }
- }
-#endif
-
- pOtherDev = pAC->dev[1 - pNet->NetNr];
-
- if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500)
- && (NewMtu <= 1500))
- return 0;
-
- pAC->RxBufSize = NewMtu + 32;
- dev->mtu = NewMtu;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("New MTU: %d\n", NewMtu));
-
- /*
- ** Prevent any reconfiguration while changing the MTU
- ** by disabling any interrupts
- */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-
- /*
- ** Notify RLMT that any ports are to be stopped
- */
- EvPara.Para32[0] = 0;
- EvPara.Para32[1] = -1;
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- EvPara.Para32[0] = 1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- } else {
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- }
-
- /*
- ** After calling the SkEventDispatcher(), RLMT is aware about
- ** the stopped ports -> configuration can take place!
- */
- SkEventDispatcher(pAC, pAC->IoBase);
-
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
- netif_stop_queue(pAC->dev[i]);
-
- }
-
- /*
- ** Depending on the desired MTU size change, a different number of
- ** RX buffers need to be allocated
- */
- if (NewMtu > 1500) {
- /*
- ** Use less rx buffers
- */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
- (pAC->RxDescrPerRing / 4);
- } else {
- if (i == pAC->ActivePort) {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
- (pAC->RxDescrPerRing / 4);
- } else {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
- (pAC->RxDescrPerRing / 10);
- }
- }
- }
- } else {
- /*
- ** Use the normal amount of rx buffers
- */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- pAC->RxPort[i].RxFillLimit = 1;
- } else {
- if (i == pAC->ActivePort) {
- pAC->RxPort[i].RxFillLimit = 1;
- } else {
- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
- (pAC->RxDescrPerRing / 4);
- }
- }
- }
- }
-
- SkGeDeInit(pAC, pAC->IoBase);
-
- /*
- ** enable/disable hardware support for long frames
- */
- if (NewMtu > 1500) {
-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
- pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
- } else {
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- pAC->GIni.GIPortUsage = SK_MUL_LINK;
- } else {
- pAC->GIni.GIPortUsage = SK_RED_LINK;
- }
- }
-
- SkGeInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
- SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
-
- /*
- ** tschilling:
- ** Speed and others are set back to default in level 1 init!
- */
- GetConfiguration(pAC);
-
- SkGeInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkI2cInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
- SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
-
- /*
- ** clear and reinit the rx rings here
- */
- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
- ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
- ClearRxRing(pAC, &pAC->RxPort[i]);
- FillRxRing(pAC, &pAC->RxPort[i]);
-
- /*
- ** Enable transmit descriptor polling
- */
- SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
- FillRxRing(pAC, &pAC->RxPort[i]);
- };
-
- SkGeYellowLED(pAC, pAC->IoBase, 1);
- SkDimEnableModerationIfNeeded(pAC);
- SkDimDisplayModerationSettings(pAC);
-
- netif_start_queue(pAC->dev[pNet->PortNr]);
- for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
- spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
- }
-
- /*
- ** Enable Interrupts again
- */
- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
- SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
-
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
-
- /*
- ** Notify RLMT about the changing and restarting one (or more) ports
- */
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- EvPara.Para32[0] = pAC->RlmtNets;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
- EvPara.Para32[0] = pNet->PortNr;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
-
- if (netif_running(pOtherDev)) {
- DEV_NET *pOtherNet = netdev_priv(pOtherDev);
- EvPara.Para32[0] = pOtherNet->PortNr;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- }
- } else {
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
- }
-
- SkEventDispatcher(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- /*
- ** While testing this driver with latest kernel 2.5 (2.5.70), it
- ** seems as if upper layers have a problem to handle a successful
- ** return value of '0'. If such a zero is returned, the complete
- ** system hangs for several minutes (!), which is in acceptable.
- **
- ** Currently it is not clear, what the exact reason for this problem
- ** is. The implemented workaround for 2.5 is to return the desired
- ** new MTU size if all needed changes for the new MTU size where
- ** performed. In kernels 2.2 and 2.4, a zero value is returned,
- ** which indicates the successful change of the mtu-size.
- */
- return NewMtu;
-
-} /* SkGeChangeMtu */
-
-
-/*****************************************************************************
- *
- * SkGeStats - return ethernet device statistics
- *
- * Description:
- * This function return statistic data about the ethernet device
- * to the operating system.
- *
- * Returns:
- * pointer to the statistic structure.
- */
-static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev)
-{
-DEV_NET *pNet = netdev_priv(dev);
-SK_AC *pAC = pNet->pAC;
-SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */
-SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */
-SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
-unsigned int Size; /* size of pnmi struct */
-unsigned long Flags; /* for spin lock */
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeStats starts now...\n"));
- pPnmiStruct = &pAC->PnmiStruct;
-
-#ifdef SK_DIAG_SUPPORT
- if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
- (pAC->BoardLevel == SK_INIT_RUN)) {
-#endif
- SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- Size = SK_PNMI_STRUCT_SIZE;
- SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-#ifdef SK_DIAG_SUPPORT
- }
-#endif
-
- pPnmiStat = &pPnmiStruct->Stat[0];
- pPnmiConf = &pPnmiStruct->Conf[0];
-
- pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF;
- pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
- pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
- pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
-
- if (dev->mtu <= 1500) {
- pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
- } else {
- pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
- pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
- }
-
-
- if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12)
- pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts;
-
- pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
- pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF;
- pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF;
- pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF;
- pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF;
-
- /* detailed rx_errors: */
- pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF;
- pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
- pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF;
- pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF;
- pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF;
- pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF;
-
- /* detailed tx_errors */
- pAC->stats.tx_aborted_errors = (SK_U32) 0;
- pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
- pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF;
- pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF;
- pAC->stats.tx_window_errors = (SK_U32) 0;
-
- return(&pAC->stats);
-} /* SkGeStats */
-
-/*
- * Basic MII register access
- */
-static int SkGeMiiIoctl(struct net_device *dev,
- struct mii_ioctl_data *data, int cmd)
-{
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- SK_IOC IoC = pAC->IoBase;
- int Port = pNet->PortNr;
- SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
- unsigned long Flags;
- int err = 0;
- int reg = data->reg_num & 0x1f;
- SK_U16 val = data->val_in;
-
- if (!netif_running(dev))
- return -ENODEV; /* Phy still in reset */
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- switch(cmd) {
- case SIOCGMIIPHY:
- data->phy_id = pPrt->PhyAddr;
-
- /* fallthru */
- case SIOCGMIIREG:
- if (pAC->GIni.GIGenesis)
- SkXmPhyRead(pAC, IoC, Port, reg, &val);
- else
- SkGmPhyRead(pAC, IoC, Port, reg, &val);
-
- data->val_out = val;
- break;
-
- case SIOCSMIIREG:
- if (!capable(CAP_NET_ADMIN))
- err = -EPERM;
-
- else if (pAC->GIni.GIGenesis)
- SkXmPhyWrite(pAC, IoC, Port, reg, val);
- else
- SkGmPhyWrite(pAC, IoC, Port, reg, val);
- break;
- default:
- err = -EOPNOTSUPP;
- }
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- return err;
-}
-
-
-/*****************************************************************************
- *
- * SkGeIoctl - IO-control function
- *
- * Description:
- * This function is called if an ioctl is issued on the device.
- * There are three subfunction for reading, writing and test-writing
- * the private MIB data structure (useful for SysKonnect-internal tools).
- *
- * Returns:
- * 0, if everything is ok
- * !=0, on error
- */
-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
-{
-DEV_NET *pNet;
-SK_AC *pAC;
-void *pMemBuf;
-struct pci_dev *pdev = NULL;
-SK_GE_IOCTL Ioctl;
-unsigned int Err = 0;
-int Size = 0;
-int Ret = 0;
-unsigned int Length = 0;
-int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeIoctl starts now...\n"));
-
- pNet = netdev_priv(dev);
- pAC = pNet->pAC;
-
- if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG)
- return SkGeMiiIoctl(dev, if_mii(rq), cmd);
-
- if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
- return -EFAULT;
- }
-
- switch(cmd) {
- case SK_IOCTL_SETMIB:
- case SK_IOCTL_PRESETMIB:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- case SK_IOCTL_GETMIB:
- if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
- Ioctl.Len<sizeof(pAC->PnmiStruct)?
- Ioctl.Len : sizeof(pAC->PnmiStruct))) {
- return -EFAULT;
- }
- Size = SkGeIocMib(pNet, Ioctl.Len, cmd);
- if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct,
- Ioctl.Len<Size? Ioctl.Len : Size)) {
- return -EFAULT;
- }
- Ioctl.Len = Size;
- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
- return -EFAULT;
- }
- break;
- case SK_IOCTL_GEN:
- if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
- Length = Ioctl.Len;
- } else {
- Length = sizeof(pAC->PnmiStruct) + HeaderLength;
- }
- if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
- return -ENOMEM;
- }
- if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
- Err = -EFAULT;
- goto fault_gen;
- }
- if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) {
- Err = -EFAULT;
- goto fault_gen;
- }
- if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
- Err = -EFAULT;
- goto fault_gen;
- }
- Ioctl.Len = Length;
- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
- Err = -EFAULT;
- goto fault_gen;
- }
-fault_gen:
- kfree(pMemBuf); /* cleanup everything */
- break;
-#ifdef SK_DIAG_SUPPORT
- case SK_IOCTL_DIAG:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
- Length = Ioctl.Len;
- } else {
- Length = sizeof(pAC->PnmiStruct) + HeaderLength;
- }
- if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
- return -ENOMEM;
- }
- if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
- Err = -EFAULT;
- goto fault_diag;
- }
- pdev = pAC->PciDev;
- Length = 3 * sizeof(SK_U32); /* Error, Bus and Device */
- /*
- ** While coding this new IOCTL interface, only a few lines of code
- ** are to to be added. Therefore no dedicated function has been
- ** added. If more functionality is added, a separate function
- ** should be used...
- */
- * ((SK_U32 *)pMemBuf) = 0;
- * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
- * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
- if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
- Err = -EFAULT;
- goto fault_diag;
- }
- Ioctl.Len = Length;
- if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) {
- Err = -EFAULT;
- goto fault_diag;
- }
-fault_diag:
- kfree(pMemBuf); /* cleanup everything */
- break;
-#endif
- default:
- Err = -EOPNOTSUPP;
- }
-
- return(Err);
-
-} /* SkGeIoctl */
-
-
-/*****************************************************************************
- *
- * SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message
- *
- * Description:
- * This function reads/writes the MIB data using PNMI (Private Network
- * Management Interface).
- * The destination for the data must be provided with the
- * ioctl call and is given to the driver in the form of
- * a user space address.
- * Copying from the user-provided data area into kernel messages
- * and back is done by copy_from_user and copy_to_user calls in
- * SkGeIoctl.
- *
- * Returns:
- * returned size from PNMI call
- */
-static int SkGeIocMib(
-DEV_NET *pNet, /* pointer to the adapter context */
-unsigned int Size, /* length of ioctl data */
-int mode) /* flag for set/preset */
-{
-unsigned long Flags; /* for spin lock */
-SK_AC *pAC;
-
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("SkGeIocMib starts now...\n"));
- pAC = pNet->pAC;
- /* access MIB */
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- switch(mode) {
- case SK_IOCTL_GETMIB:
- SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
- pNet->NetNr);
- break;
- case SK_IOCTL_PRESETMIB:
- SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
- pNet->NetNr);
- break;
- case SK_IOCTL_SETMIB:
- SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size,
- pNet->NetNr);
- break;
- default:
- break;
- }
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
- ("MIB data access succeeded\n"));
- return (Size);
-} /* SkGeIocMib */
-
-
-/*****************************************************************************
- *
- * GetConfiguration - read configuration information
- *
- * Description:
- * This function reads per-adapter configuration information from
- * the options provided on the command line.
- *
- * Returns:
- * none
- */
-static void GetConfiguration(
-SK_AC *pAC) /* pointer to the adapter context structure */
-{
-SK_I32 Port; /* preferred port */
-SK_BOOL AutoSet;
-SK_BOOL DupSet;
-int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */
-int AutoNeg = 1; /* autoneg off (0) or on (1) */
-int DuplexCap = 0; /* 0=both,1=full,2=half */
-int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */
-int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */
-
-SK_BOOL IsConTypeDefined = SK_TRUE;
-SK_BOOL IsLinkSpeedDefined = SK_TRUE;
-SK_BOOL IsFlowCtrlDefined = SK_TRUE;
-SK_BOOL IsRoleDefined = SK_TRUE;
-SK_BOOL IsModeDefined = SK_TRUE;
-/*
- * The two parameters AutoNeg. and DuplexCap. map to one configuration
- * parameter. The mapping is described by this table:
- * DuplexCap -> | both | full | half |
- * AutoNeg | | | |
- * -----------------------------------------------------------------
- * Off | illegal | Full | Half |
- * -----------------------------------------------------------------
- * On | AutoBoth | AutoFull | AutoHalf |
- * -----------------------------------------------------------------
- * Sense | AutoSense | AutoSense | AutoSense |
- */
-int Capabilities[3][3] =
- { { -1, SK_LMODE_FULL , SK_LMODE_HALF },
- {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
- {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
-
-#define DC_BOTH 0
-#define DC_FULL 1
-#define DC_HALF 2
-#define AN_OFF 0
-#define AN_ON 1
-#define AN_SENS 2
-#define M_CurrPort pAC->GIni.GP[Port]
-
-
- /*
- ** Set the default values first for both ports!
- */
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
- }
-
- /*
- ** Check merged parameter ConType. If it has not been used,
- ** verify any other parameter (e.g. AutoNeg) and use default values.
- **
- ** Stating both ConType and other lowlevel link parameters is also
- ** possible. If this is the case, the passed ConType-parameter is
- ** overwritten by the lowlevel link parameter.
- **
- ** The following settings are used for a merged ConType-parameter:
- **
- ** ConType DupCap AutoNeg FlowCtrl Role Speed
- ** ------- ------ ------- -------- ---------- -----
- ** Auto Both On SymOrRem Auto Auto
- ** 100FD Full Off None <ignored> 100
- ** 100HD Half Off None <ignored> 100
- ** 10FD Full Off None <ignored> 10
- ** 10HD Half Off None <ignored> 10
- **
- ** This ConType parameter is used for all ports of the adapter!
- */
- if ( (ConType != NULL) &&
- (pAC->Index < SK_MAX_CARD_PARAM) &&
- (ConType[pAC->Index] != NULL) ) {
-
- /* Check chipset family */
- if ((!pAC->ChipsetType) &&
- (strcmp(ConType[pAC->Index],"Auto")!=0) &&
- (strcmp(ConType[pAC->Index],"")!=0)) {
- /* Set the speed parameter back */
- printk("sk98lin: Illegal value \"%s\" "
- "for ConType."
- " Using Auto.\n",
- ConType[pAC->Index]);
-
- sprintf(ConType[pAC->Index], "Auto");
- }
-
- if (strcmp(ConType[pAC->Index],"")==0) {
- IsConTypeDefined = SK_FALSE; /* No ConType defined */
- } else if (strcmp(ConType[pAC->Index],"Auto")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
- }
- } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
- }
- } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
- }
- } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
- }
- } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
- for (Port = 0; Port < SK_MAX_MACS; Port++) {
- M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
- M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
- M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
- M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
- }
- } else {
- printk("sk98lin: Illegal value \"%s\" for ConType\n",
- ConType[pAC->Index]);
- IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
- }
- } else {
- IsConTypeDefined = SK_FALSE; /* No ConType defined */
- }
-
- /*
- ** Parse any parameter settings for port A:
- ** a) any LinkSpeed stated?
- */
- if (Speed_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- Speed_A[pAC->Index] != NULL) {
- if (strcmp(Speed_A[pAC->Index],"")==0) {
- IsLinkSpeedDefined = SK_FALSE;
- } else if (strcmp(Speed_A[pAC->Index],"Auto")==0) {
- LinkSpeed = SK_LSPEED_AUTO;
- } else if (strcmp(Speed_A[pAC->Index],"10")==0) {
- LinkSpeed = SK_LSPEED_10MBPS;
- } else if (strcmp(Speed_A[pAC->Index],"100")==0) {
- LinkSpeed = SK_LSPEED_100MBPS;
- } else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
- LinkSpeed = SK_LSPEED_1000MBPS;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Speed_A\n",
- Speed_A[pAC->Index]);
- IsLinkSpeedDefined = SK_FALSE;
- }
- } else {
- IsLinkSpeedDefined = SK_FALSE;
- }
-
- /*
- ** Check speed parameter:
- ** Only copper type adapter and GE V2 cards
- */
- if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
- ((LinkSpeed != SK_LSPEED_AUTO) &&
- (LinkSpeed != SK_LSPEED_1000MBPS))) {
- printk("sk98lin: Illegal value for Speed_A. "
- "Not a copper card or GE V2 card\n Using "
- "speed 1000\n");
- LinkSpeed = SK_LSPEED_1000MBPS;
- }
-
- /*
- ** Decide whether to set new config value if somethig valid has
- ** been received.
- */
- if (IsLinkSpeedDefined) {
- pAC->GIni.GP[0].PLinkSpeed = LinkSpeed;
- }
-
- /*
- ** b) Any Autonegotiation and DuplexCapabilities set?
- ** Please note that both belong together...
- */
- AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */
- AutoSet = SK_FALSE;
- if (AutoNeg_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- AutoNeg_A[pAC->Index] != NULL) {
- AutoSet = SK_TRUE;
- if (strcmp(AutoNeg_A[pAC->Index],"")==0) {
- AutoSet = SK_FALSE;
- } else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) {
- AutoNeg = AN_ON;
- } else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) {
- AutoNeg = AN_OFF;
- } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) {
- AutoNeg = AN_SENS;
- } else {
- printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n",
- AutoNeg_A[pAC->Index]);
- }
- }
-
- DuplexCap = DC_BOTH;
- DupSet = SK_FALSE;
- if (DupCap_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- DupCap_A[pAC->Index] != NULL) {
- DupSet = SK_TRUE;
- if (strcmp(DupCap_A[pAC->Index],"")==0) {
- DupSet = SK_FALSE;
- } else if (strcmp(DupCap_A[pAC->Index],"Both")==0) {
- DuplexCap = DC_BOTH;
- } else if (strcmp(DupCap_A[pAC->Index],"Full")==0) {
- DuplexCap = DC_FULL;
- } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) {
- DuplexCap = DC_HALF;
- } else {
- printk("sk98lin: Illegal value \"%s\" for DupCap_A\n",
- DupCap_A[pAC->Index]);
- }
- }
-
- /*
- ** Check for illegal combinations
- */
- if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
- ((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
- (DuplexCap == SK_LMODE_STAT_HALF)) &&
- (pAC->ChipsetType)) {
- printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
- " Using Full Duplex.\n");
- DuplexCap = DC_FULL;
- }
-
- if ( AutoSet && AutoNeg==AN_SENS && DupSet) {
- printk("sk98lin, Port A: DuplexCapabilities"
- " ignored using Sense mode\n");
- }
-
- if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
- printk("sk98lin: Port A: Illegal combination"
- " of values AutoNeg. and DuplexCap.\n Using "
- "Full Duplex\n");
- DuplexCap = DC_FULL;
- }
-
- if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
- DuplexCap = DC_FULL;
- }
-
- if (!AutoSet && DupSet) {
- printk("sk98lin: Port A: Duplex setting not"
- " possible in\n default AutoNegotiation mode"
- " (Sense).\n Using AutoNegotiation On\n");
- AutoNeg = AN_ON;
- }
-
- /*
- ** set the desired mode
- */
- if (AutoSet || DupSet) {
- pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
- }
-
- /*
- ** c) Any Flowcontrol-parameter set?
- */
- if (FlowCtrl_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- FlowCtrl_A[pAC->Index] != NULL) {
- if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) {
- IsFlowCtrlDefined = SK_FALSE;
- } else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) {
- FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
- } else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) {
- FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
- } else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) {
- FlowCtrl = SK_FLOW_MODE_LOC_SEND;
- } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) {
- FlowCtrl = SK_FLOW_MODE_NONE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
- FlowCtrl_A[pAC->Index]);
- IsFlowCtrlDefined = SK_FALSE;
- }
- } else {
- IsFlowCtrlDefined = SK_FALSE;
- }
-
- if (IsFlowCtrlDefined) {
- if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
- printk("sk98lin: Port A: FlowControl"
- " impossible without AutoNegotiation,"
- " disabled\n");
- FlowCtrl = SK_FLOW_MODE_NONE;
- }
- pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl;
- }
-
- /*
- ** d) What is with the RoleParameter?
- */
- if (Role_A != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- Role_A[pAC->Index] != NULL) {
- if (strcmp(Role_A[pAC->Index],"")==0) {
- IsRoleDefined = SK_FALSE;
- } else if (strcmp(Role_A[pAC->Index],"Auto")==0) {
- MSMode = SK_MS_MODE_AUTO;
- } else if (strcmp(Role_A[pAC->Index],"Master")==0) {
- MSMode = SK_MS_MODE_MASTER;
- } else if (strcmp(Role_A[pAC->Index],"Slave")==0) {
- MSMode = SK_MS_MODE_SLAVE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Role_A\n",
- Role_A[pAC->Index]);
- IsRoleDefined = SK_FALSE;
- }
- } else {
- IsRoleDefined = SK_FALSE;
- }
-
- if (IsRoleDefined == SK_TRUE) {
- pAC->GIni.GP[0].PMSMode = MSMode;
- }
-
-
-
- /*
- ** Parse any parameter settings for port B:
- ** a) any LinkSpeed stated?
- */
- IsConTypeDefined = SK_TRUE;
- IsLinkSpeedDefined = SK_TRUE;
- IsFlowCtrlDefined = SK_TRUE;
- IsModeDefined = SK_TRUE;
-
- if (Speed_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- Speed_B[pAC->Index] != NULL) {
- if (strcmp(Speed_B[pAC->Index],"")==0) {
- IsLinkSpeedDefined = SK_FALSE;
- } else if (strcmp(Speed_B[pAC->Index],"Auto")==0) {
- LinkSpeed = SK_LSPEED_AUTO;
- } else if (strcmp(Speed_B[pAC->Index],"10")==0) {
- LinkSpeed = SK_LSPEED_10MBPS;
- } else if (strcmp(Speed_B[pAC->Index],"100")==0) {
- LinkSpeed = SK_LSPEED_100MBPS;
- } else if (strcmp(Speed_B[pAC->Index],"1000")==0) {
- LinkSpeed = SK_LSPEED_1000MBPS;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Speed_B\n",
- Speed_B[pAC->Index]);
- IsLinkSpeedDefined = SK_FALSE;
- }
- } else {
- IsLinkSpeedDefined = SK_FALSE;
- }
-
- /*
- ** Check speed parameter:
- ** Only copper type adapter and GE V2 cards
- */
- if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) &&
- ((LinkSpeed != SK_LSPEED_AUTO) &&
- (LinkSpeed != SK_LSPEED_1000MBPS))) {
- printk("sk98lin: Illegal value for Speed_B. "
- "Not a copper card or GE V2 card\n Using "
- "speed 1000\n");
- LinkSpeed = SK_LSPEED_1000MBPS;
- }
-
- /*
- ** Decide whether to set new config value if somethig valid has
- ** been received.
- */
- if (IsLinkSpeedDefined) {
- pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
- }
-
- /*
- ** b) Any Autonegotiation and DuplexCapabilities set?
- ** Please note that both belong together...
- */
- AutoNeg = AN_SENS; /* default: do auto Sense */
- AutoSet = SK_FALSE;
- if (AutoNeg_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- AutoNeg_B[pAC->Index] != NULL) {
- AutoSet = SK_TRUE;
- if (strcmp(AutoNeg_B[pAC->Index],"")==0) {
- AutoSet = SK_FALSE;
- } else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) {
- AutoNeg = AN_ON;
- } else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) {
- AutoNeg = AN_OFF;
- } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) {
- AutoNeg = AN_SENS;
- } else {
- printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n",
- AutoNeg_B[pAC->Index]);
- }
- }
-
- DuplexCap = DC_BOTH;
- DupSet = SK_FALSE;
- if (DupCap_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- DupCap_B[pAC->Index] != NULL) {
- DupSet = SK_TRUE;
- if (strcmp(DupCap_B[pAC->Index],"")==0) {
- DupSet = SK_FALSE;
- } else if (strcmp(DupCap_B[pAC->Index],"Both")==0) {
- DuplexCap = DC_BOTH;
- } else if (strcmp(DupCap_B[pAC->Index],"Full")==0) {
- DuplexCap = DC_FULL;
- } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) {
- DuplexCap = DC_HALF;
- } else {
- printk("sk98lin: Illegal value \"%s\" for DupCap_B\n",
- DupCap_B[pAC->Index]);
- }
- }
-
-
- /*
- ** Check for illegal combinations
- */
- if ((LinkSpeed == SK_LSPEED_1000MBPS) &&
- ((DuplexCap == SK_LMODE_STAT_AUTOHALF) ||
- (DuplexCap == SK_LMODE_STAT_HALF)) &&
- (pAC->ChipsetType)) {
- printk("sk98lin: Half Duplex not possible with Gigabit speed!\n"
- " Using Full Duplex.\n");
- DuplexCap = DC_FULL;
- }
-
- if (AutoSet && AutoNeg==AN_SENS && DupSet) {
- printk("sk98lin, Port B: DuplexCapabilities"
- " ignored using Sense mode\n");
- }
-
- if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){
- printk("sk98lin: Port B: Illegal combination"
- " of values AutoNeg. and DuplexCap.\n Using "
- "Full Duplex\n");
- DuplexCap = DC_FULL;
- }
-
- if (AutoSet && AutoNeg==AN_OFF && !DupSet) {
- DuplexCap = DC_FULL;
- }
-
- if (!AutoSet && DupSet) {
- printk("sk98lin: Port B: Duplex setting not"
- " possible in\n default AutoNegotiation mode"
- " (Sense).\n Using AutoNegotiation On\n");
- AutoNeg = AN_ON;
- }
-
- /*
- ** set the desired mode
- */
- if (AutoSet || DupSet) {
- pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap];
- }
-
- /*
- ** c) Any FlowCtrl parameter set?
- */
- if (FlowCtrl_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- FlowCtrl_B[pAC->Index] != NULL) {
- if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) {
- IsFlowCtrlDefined = SK_FALSE;
- } else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) {
- FlowCtrl = SK_FLOW_MODE_SYM_OR_REM;
- } else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) {
- FlowCtrl = SK_FLOW_MODE_SYMMETRIC;
- } else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) {
- FlowCtrl = SK_FLOW_MODE_LOC_SEND;
- } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) {
- FlowCtrl = SK_FLOW_MODE_NONE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n",
- FlowCtrl_B[pAC->Index]);
- IsFlowCtrlDefined = SK_FALSE;
- }
- } else {
- IsFlowCtrlDefined = SK_FALSE;
- }
-
- if (IsFlowCtrlDefined) {
- if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) {
- printk("sk98lin: Port B: FlowControl"
- " impossible without AutoNegotiation,"
- " disabled\n");
- FlowCtrl = SK_FLOW_MODE_NONE;
- }
- pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl;
- }
-
- /*
- ** d) What is the RoleParameter?
- */
- if (Role_B != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- Role_B[pAC->Index] != NULL) {
- if (strcmp(Role_B[pAC->Index],"")==0) {
- IsRoleDefined = SK_FALSE;
- } else if (strcmp(Role_B[pAC->Index],"Auto")==0) {
- MSMode = SK_MS_MODE_AUTO;
- } else if (strcmp(Role_B[pAC->Index],"Master")==0) {
- MSMode = SK_MS_MODE_MASTER;
- } else if (strcmp(Role_B[pAC->Index],"Slave")==0) {
- MSMode = SK_MS_MODE_SLAVE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Role_B\n",
- Role_B[pAC->Index]);
- IsRoleDefined = SK_FALSE;
- }
- } else {
- IsRoleDefined = SK_FALSE;
- }
-
- if (IsRoleDefined) {
- pAC->GIni.GP[1].PMSMode = MSMode;
- }
-
- /*
- ** Evaluate settings for both ports
- */
- pAC->ActivePort = 0;
- if (PrefPort != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- PrefPort[pAC->Index] != NULL) {
- if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */
- pAC->ActivePort = 0;
- pAC->Rlmt.Net[0].Preference = -1; /* auto */
- pAC->Rlmt.Net[0].PrefPort = 0;
- } else if (strcmp(PrefPort[pAC->Index],"A") == 0) {
- /*
- ** do not set ActivePort here, thus a port
- ** switch is issued after net up.
- */
- Port = 0;
- pAC->Rlmt.Net[0].Preference = Port;
- pAC->Rlmt.Net[0].PrefPort = Port;
- } else if (strcmp(PrefPort[pAC->Index],"B") == 0) {
- /*
- ** do not set ActivePort here, thus a port
- ** switch is issued after net up.
- */
- if (pAC->GIni.GIMacsFound == 1) {
- printk("sk98lin: Illegal value \"B\" for PrefPort.\n"
- " Port B not available on single port adapters.\n");
-
- pAC->ActivePort = 0;
- pAC->Rlmt.Net[0].Preference = -1; /* auto */
- pAC->Rlmt.Net[0].PrefPort = 0;
- } else {
- Port = 1;
- pAC->Rlmt.Net[0].Preference = Port;
- pAC->Rlmt.Net[0].PrefPort = Port;
- }
- } else {
- printk("sk98lin: Illegal value \"%s\" for PrefPort\n",
- PrefPort[pAC->Index]);
- }
- }
-
- pAC->RlmtNets = 1;
-
- if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
- RlmtMode[pAC->Index] != NULL) {
- if (strcmp(RlmtMode[pAC->Index], "") == 0) {
- pAC->RlmtMode = 0;
- } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK;
- } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK |
- SK_RLMT_CHECK_LOC_LINK;
- } else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK |
- SK_RLMT_CHECK_LOC_LINK |
- SK_RLMT_CHECK_SEG;
- } else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) &&
- (pAC->GIni.GIMacsFound == 2)) {
- pAC->RlmtMode = SK_RLMT_CHECK_LINK;
- pAC->RlmtNets = 2;
- } else {
- printk("sk98lin: Illegal value \"%s\" for"
- " RlmtMode, using default\n",
- RlmtMode[pAC->Index]);
- pAC->RlmtMode = 0;
- }
- } else {
- pAC->RlmtMode = 0;
- }
-
- /*
- ** Check the interrupt moderation parameters
- */
- if (Moderation[pAC->Index] != NULL) {
- if (strcmp(Moderation[pAC->Index], "") == 0) {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
- } else if (strcmp(Moderation[pAC->Index], "Static") == 0) {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
- } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC;
- } else if (strcmp(Moderation[pAC->Index], "None") == 0) {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
- } else {
- printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
- " Disable interrupt moderation.\n",
- Moderation[pAC->Index]);
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
- }
- } else {
- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
- }
-
- if (Stats[pAC->Index] != NULL) {
- if (strcmp(Stats[pAC->Index], "Yes") == 0) {
- pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
- } else {
- pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
- }
- } else {
- pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
- }
-
- if (ModerationMask[pAC->Index] != NULL) {
- if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
- } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
- } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
- } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
- } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
- } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
- } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
- } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
- } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
- } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
- } else { /* some rubbish */
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
- }
- } else { /* operator has stated nothing */
- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
- }
-
- if (AutoSizing[pAC->Index] != NULL) {
- if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
- } else {
- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
- }
- } else { /* operator has stated nothing */
- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
- }
-
- if (IntsPerSec[pAC->Index] != 0) {
- if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) ||
- (IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
- printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n"
- " Using default value of %i.\n",
- IntsPerSec[pAC->Index],
- C_INT_MOD_IPS_LOWER_RANGE,
- C_INT_MOD_IPS_UPPER_RANGE,
- C_INTS_PER_SEC_DEFAULT);
- pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
- } else {
- pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
- }
- } else {
- pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
- }
-
- /*
- ** Evaluate upper and lower moderation threshold
- */
- pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
- pAC->DynIrqModInfo.MaxModIntsPerSec +
- (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
-
- pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
- pAC->DynIrqModInfo.MaxModIntsPerSec -
- (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
-
- pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */
-
-
-} /* GetConfiguration */
-
-
-/*****************************************************************************
- *
- * ProductStr - return a adapter identification string from vpd
- *
- * Description:
- * This function reads the product name string from the vpd area
- * and puts it the field pAC->DeviceString.
- *
- * Returns: N/A
- */
-static inline int ProductStr(
- SK_AC *pAC, /* pointer to adapter context */
- char *DeviceStr, /* result string */
- int StrLen /* length of the string */
-)
-{
-char Keyword[] = VPD_NAME; /* vpd productname identifier */
-int ReturnCode; /* return code from vpd_read */
-unsigned long Flags;
-
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-
- return ReturnCode;
-} /* ProductStr */
-
-/*****************************************************************************
- *
- * StartDrvCleanupTimer - Start timer to check for descriptors which
- * might be placed in descriptor ring, but
- * havent been handled up to now
- *
- * Description:
- * This function requests a HW-timer fo the Yukon card. The actions to
- * perform when this timer expires, are located in the SkDrvEvent().
- *
- * Returns: N/A
- */
-static void
-StartDrvCleanupTimer(SK_AC *pAC) {
- SK_EVPARA EventParam; /* Event struct for timer event */
-
- SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
- SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
- SK_DRV_RX_CLEANUP_TIMER_LENGTH,
- SKGE_DRV, SK_DRV_TIMER, EventParam);
-}
-
-/*****************************************************************************
- *
- * StopDrvCleanupTimer - Stop timer to check for descriptors
- *
- * Description:
- * This function requests a HW-timer fo the Yukon card. The actions to
- * perform when this timer expires, are located in the SkDrvEvent().
- *
- * Returns: N/A
- */
-static void
-StopDrvCleanupTimer(SK_AC *pAC) {
- SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
- SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
-}
-
-/****************************************************************************/
-/* functions for common modules *********************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- * SkDrvAllocRlmtMbuf - allocate an RLMT mbuf
- *
- * Description:
- * This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure
- * is embedded into a socket buff data area.
- *
- * Context:
- * runtime
- *
- * Returns:
- * NULL or pointer to Mbuf.
- */
-SK_MBUF *SkDrvAllocRlmtMbuf(
-SK_AC *pAC, /* pointer to adapter context */
-SK_IOC IoC, /* the IO-context */
-unsigned BufferSize) /* size of the requested buffer */
-{
-SK_MBUF *pRlmtMbuf; /* pointer to a new rlmt-mbuf structure */
-struct sk_buff *pMsgBlock; /* pointer to a new message block */
-
- pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC);
- if (pMsgBlock == NULL) {
- return (NULL);
- }
- pRlmtMbuf = (SK_MBUF*) pMsgBlock->data;
- skb_reserve(pMsgBlock, sizeof(SK_MBUF));
- pRlmtMbuf->pNext = NULL;
- pRlmtMbuf->pOs = pMsgBlock;
- pRlmtMbuf->pData = pMsgBlock->data; /* Data buffer. */
- pRlmtMbuf->Size = BufferSize; /* Data buffer size. */
- pRlmtMbuf->Length = 0; /* Length of packet (<= Size). */
- return (pRlmtMbuf);
-
-} /* SkDrvAllocRlmtMbuf */
-
-
-/*****************************************************************************
- *
- * SkDrvFreeRlmtMbuf - free an RLMT mbuf
- *
- * Description:
- * This routine frees one or more RLMT mbuf(s).
- *
- * Context:
- * runtime
- *
- * Returns:
- * Nothing
- */
-void SkDrvFreeRlmtMbuf(
-SK_AC *pAC, /* pointer to adapter context */
-SK_IOC IoC, /* the IO-context */
-SK_MBUF *pMbuf) /* size of the requested buffer */
-{
-SK_MBUF *pFreeMbuf;
-SK_MBUF *pNextMbuf;
-
- pFreeMbuf = pMbuf;
- do {
- pNextMbuf = pFreeMbuf->pNext;
- DEV_KFREE_SKB_ANY(pFreeMbuf->pOs);
- pFreeMbuf = pNextMbuf;
- } while ( pFreeMbuf != NULL );
-} /* SkDrvFreeRlmtMbuf */
-
-
-/*****************************************************************************
- *
- * SkOsGetTime - provide a time value
- *
- * Description:
- * This routine provides a time value. The unit is 1/HZ (defined by Linux).
- * It is not used for absolute time, but only for time differences.
- *
- *
- * Returns:
- * Time value
- */
-SK_U64 SkOsGetTime(SK_AC *pAC)
-{
- SK_U64 PrivateJiffies;
- SkOsGetTimeCurrent(pAC, &PrivateJiffies);
- return PrivateJiffies;
-} /* SkOsGetTime */
-
-
-/*****************************************************************************
- *
- * SkPciReadCfgDWord - read a 32 bit value from pci config space
- *
- * Description:
- * This routine reads a 32 bit value from the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciReadCfgDWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U32 *pVal) /* pointer to store the read value */
-{
- pci_read_config_dword(pAC->PciDev, PciAddr, pVal);
- return(0);
-} /* SkPciReadCfgDWord */
-
-
-/*****************************************************************************
- *
- * SkPciReadCfgWord - read a 16 bit value from pci config space
- *
- * Description:
- * This routine reads a 16 bit value from the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciReadCfgWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U16 *pVal) /* pointer to store the read value */
-{
- pci_read_config_word(pAC->PciDev, PciAddr, pVal);
- return(0);
-} /* SkPciReadCfgWord */
-
-
-/*****************************************************************************
- *
- * SkPciReadCfgByte - read a 8 bit value from pci config space
- *
- * Description:
- * This routine reads a 8 bit value from the pci configuration
- * space.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciReadCfgByte(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U8 *pVal) /* pointer to store the read value */
-{
- pci_read_config_byte(pAC->PciDev, PciAddr, pVal);
- return(0);
-} /* SkPciReadCfgByte */
-
-
-/*****************************************************************************
- *
- * SkPciWriteCfgWord - write a 16 bit value to pci config space
- *
- * Description:
- * This routine writes a 16 bit value to the pci configuration
- * space. The flag PciConfigUp indicates whether the config space
- * is accesible or must be set up first.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciWriteCfgWord(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U16 Val) /* pointer to store the read value */
-{
- pci_write_config_word(pAC->PciDev, PciAddr, Val);
- return(0);
-} /* SkPciWriteCfgWord */
-
-
-/*****************************************************************************
- *
- * SkPciWriteCfgWord - write a 8 bit value to pci config space
- *
- * Description:
- * This routine writes a 8 bit value to the pci configuration
- * space. The flag PciConfigUp indicates whether the config space
- * is accesible or must be set up first.
- *
- * Returns:
- * 0 - indicate everything worked ok.
- * != 0 - error indication
- */
-int SkPciWriteCfgByte(
-SK_AC *pAC, /* Adapter Control structure pointer */
-int PciAddr, /* PCI register address */
-SK_U8 Val) /* pointer to store the read value */
-{
- pci_write_config_byte(pAC->PciDev, PciAddr, Val);
- return(0);
-} /* SkPciWriteCfgByte */
-
-
-/*****************************************************************************
- *
- * SkDrvEvent - handle driver events
- *
- * Description:
- * This function handles events from all modules directed to the driver
- *
- * Context:
- * Is called under protection of slow path lock.
- *
- * Returns:
- * 0 if everything ok
- * < 0 on error
- *
- */
-int SkDrvEvent(
-SK_AC *pAC, /* pointer to adapter context */
-SK_IOC IoC, /* io-context */
-SK_U32 Event, /* event-id */
-SK_EVPARA Param) /* event-parameter */
-{
-SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */
-struct sk_buff *pMsg; /* pointer to a message block */
-int FromPort; /* the port from which we switch away */
-int ToPort; /* the port we switch to */
-SK_EVPARA NewPara; /* parameter for further events */
-int Stat;
-unsigned long Flags;
-SK_BOOL DualNet;
-
- switch (Event) {
- case SK_DRV_ADAP_FAIL:
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("ADAPTER FAIL EVENT\n"));
- printk("%s: Adapter failed.\n", pAC->dev[0]->name);
- /* disable interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- /* cgoos */
- break;
- case SK_DRV_PORT_FAIL:
- FromPort = Param.Para32[0];
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("PORT FAIL EVENT, Port: %d\n", FromPort));
- if (FromPort == 0) {
- printk("%s: Port A failed.\n", pAC->dev[0]->name);
- } else {
- printk("%s: Port B failed.\n", pAC->dev[1]->name);
- }
- /* cgoos */
- break;
- case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */
- /* action list 4 */
- FromPort = Param.Para32[0];
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("PORT RESET EVENT, Port: %d ", FromPort));
- NewPara.Para64 = FromPort;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
- spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
-
- SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
- netif_carrier_off(pAC->dev[Param.Para32[0]]);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
-
- /* clear rx ring from received frames */
- ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
-
- ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
- spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
-
- /* tschilling: Handling of return value inserted. */
- if (SkGeInitPort(pAC, IoC, FromPort)) {
- if (FromPort == 0) {
- printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
- } else {
- printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
- }
- }
- SkAddrMcUpdate(pAC,IoC, FromPort);
- PortReInitBmu(pAC, FromPort);
- SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
- ClearAndStartRx(pAC, FromPort);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- break;
- case SK_DRV_NET_UP: /* SK_U32 PortIdx */
- { struct net_device *dev = pAC->dev[Param.Para32[0]];
- /* action list 5 */
- FromPort = Param.Para32[0];
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("NET UP EVENT, Port: %d ", Param.Para32[0]));
- /* Mac update */
- SkAddrMcUpdate(pAC,IoC, FromPort);
-
- if (DoPrintInterfaceChange) {
- printk("%s: network connection up using"
- " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
-
- /* tschilling: Values changed according to LinkSpeedUsed. */
- Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
- if (Stat == SK_LSPEED_STAT_10MBPS) {
- printk(" speed: 10\n");
- } else if (Stat == SK_LSPEED_STAT_100MBPS) {
- printk(" speed: 100\n");
- } else if (Stat == SK_LSPEED_STAT_1000MBPS) {
- printk(" speed: 1000\n");
- } else {
- printk(" speed: unknown\n");
- }
-
-
- Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
- if (Stat == SK_LMODE_STAT_AUTOHALF ||
- Stat == SK_LMODE_STAT_AUTOFULL) {
- printk(" autonegotiation: yes\n");
- }
- else {
- printk(" autonegotiation: no\n");
- }
- if (Stat == SK_LMODE_STAT_AUTOHALF ||
- Stat == SK_LMODE_STAT_HALF) {
- printk(" duplex mode: half\n");
- }
- else {
- printk(" duplex mode: full\n");
- }
- Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
- if (Stat == SK_FLOW_STAT_REM_SEND ) {
- printk(" flowctrl: remote send\n");
- }
- else if (Stat == SK_FLOW_STAT_LOC_SEND ){
- printk(" flowctrl: local send\n");
- }
- else if (Stat == SK_FLOW_STAT_SYMMETRIC ){
- printk(" flowctrl: symmetric\n");
- }
- else {
- printk(" flowctrl: none\n");
- }
-
- /* tschilling: Check against CopperType now. */
- if ((pAC->GIni.GICopperType == SK_TRUE) &&
- (pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
- SK_LSPEED_STAT_1000MBPS)) {
- Stat = pAC->GIni.GP[FromPort].PMSStatus;
- if (Stat == SK_MS_STAT_MASTER ) {
- printk(" role: master\n");
- }
- else if (Stat == SK_MS_STAT_SLAVE ) {
- printk(" role: slave\n");
- }
- else {
- printk(" role: ???\n");
- }
- }
-
- /*
- Display dim (dynamic interrupt moderation)
- informations
- */
- if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC)
- printk(" irq moderation: static (%d ints/sec)\n",
- pAC->DynIrqModInfo.MaxModIntsPerSec);
- else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC)
- printk(" irq moderation: dynamic (%d ints/sec)\n",
- pAC->DynIrqModInfo.MaxModIntsPerSec);
- else
- printk(" irq moderation: disabled\n");
-
-
- printk(" scatter-gather: %s\n",
- (dev->features & NETIF_F_SG) ? "enabled" : "disabled");
- printk(" tx-checksum: %s\n",
- (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled");
- printk(" rx-checksum: %s\n",
- pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled");
-
- } else {
- DoPrintInterfaceChange = SK_TRUE;
- }
-
- if ((Param.Para32[0] != pAC->ActivePort) &&
- (pAC->RlmtNets == 1)) {
- NewPara.Para32[0] = pAC->ActivePort;
- NewPara.Para32[1] = Param.Para32[0];
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
- NewPara);
- }
-
- /* Inform the world that link protocol is up. */
- netif_carrier_on(dev);
- break;
- }
- case SK_DRV_NET_DOWN: /* SK_U32 Reason */
- /* action list 7 */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("NET DOWN EVENT "));
- if (DoPrintInterfaceChange) {
- printk("%s: network connection down\n",
- pAC->dev[Param.Para32[1]]->name);
- } else {
- DoPrintInterfaceChange = SK_TRUE;
- }
- netif_carrier_off(pAC->dev[Param.Para32[1]]);
- break;
- case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("PORT SWITCH HARD "));
- case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
- /* action list 6 */
- printk("%s: switching to port %c\n", pAC->dev[0]->name,
- 'A'+Param.Para32[1]);
- case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
- FromPort = Param.Para32[0];
- ToPort = Param.Para32[1];
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ",
- FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
- NewPara.Para64 = FromPort;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
- NewPara.Para64 = ToPort;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
- spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
- SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
-
- ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
- ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
-
- ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
- ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
- spin_lock_irqsave(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- pAC->ActivePort = ToPort;
-#if 0
- SetQueueSizes(pAC);
-#else
- /* tschilling: New common function with minimum size check. */
- DualNet = SK_FALSE;
- if (pAC->RlmtNets == 2) {
- DualNet = SK_TRUE;
- }
-
- if (SkGeInitAssignRamToQueues(
- pAC,
- pAC->ActivePort,
- DualNet)) {
- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- printk("SkGeInitAssignRamToQueues failed.\n");
- break;
- }
-#endif
- /* tschilling: Handling of return values inserted. */
- if (SkGeInitPort(pAC, IoC, FromPort) ||
- SkGeInitPort(pAC, IoC, ToPort)) {
- printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
- }
- if (Event == SK_DRV_SWITCH_SOFT) {
- SkMacRxTxEnable(pAC, IoC, FromPort);
- }
- SkMacRxTxEnable(pAC, IoC, ToPort);
- SkAddrSwap(pAC, IoC, FromPort, ToPort);
- SkAddrMcUpdate(pAC, IoC, FromPort);
- SkAddrMcUpdate(pAC, IoC, ToPort);
- PortReInitBmu(pAC, FromPort);
- PortReInitBmu(pAC, ToPort);
- SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
- SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
- ClearAndStartRx(pAC, FromPort);
- ClearAndStartRx(pAC, ToPort);
- spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
- spin_unlock_irqrestore(
- &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
- Flags);
- break;
- case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("RLS "));
- pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
- pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
- skb_put(pMsg, pRlmtMbuf->Length);
- if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
- pMsg) < 0)
-
- DEV_KFREE_SKB_ANY(pMsg);
- break;
- case SK_DRV_TIMER:
- if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
- /*
- ** expiration of the moderation timer implies that
- ** dynamic moderation is to be applied
- */
- SkDimStartModerationTimer(pAC);
- SkDimModerate(pAC);
- if (pAC->DynIrqModInfo.DisplayStats) {
- SkDimDisplayModerationSettings(pAC);
- }
- } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
- /*
- ** check if we need to check for descriptors which
- ** haven't been handled the last millisecs
- */
- StartDrvCleanupTimer(pAC);
- if (pAC->GIni.GIMacsFound == 2) {
- ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
- }
- ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
- } else {
- printk("Expiration of unknown timer\n");
- }
- break;
- default:
- break;
- }
- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
- ("END EVENT "));
-
- return (0);
-} /* SkDrvEvent */
-
-
-/*****************************************************************************
- *
- * SkErrorLog - log errors
- *
- * Description:
- * This function logs errors to the system buffer and to the console
- *
- * Returns:
- * 0 if everything ok
- * < 0 on error
- *
- */
-void SkErrorLog(
-SK_AC *pAC,
-int ErrClass,
-int ErrNum,
-char *pErrorMsg)
-{
-char ClassStr[80];
-
- switch (ErrClass) {
- case SK_ERRCL_OTHER:
- strcpy(ClassStr, "Other error");
- break;
- case SK_ERRCL_CONFIG:
- strcpy(ClassStr, "Configuration error");
- break;
- case SK_ERRCL_INIT:
- strcpy(ClassStr, "Initialization error");
- break;
- case SK_ERRCL_NORES:
- strcpy(ClassStr, "Out of resources error");
- break;
- case SK_ERRCL_SW:
- strcpy(ClassStr, "internal Software error");
- break;
- case SK_ERRCL_HW:
- strcpy(ClassStr, "Hardware failure");
- break;
- case SK_ERRCL_COMM:
- strcpy(ClassStr, "Communication error");
- break;
- }
- printk(KERN_INFO "%s: -- ERROR --\n Class: %s\n"
- " Nr: 0x%x\n Msg: %s\n", pAC->dev[0]->name,
- ClassStr, ErrNum, pErrorMsg);
-
-} /* SkErrorLog */
-
-#ifdef SK_DIAG_SUPPORT
-
-/*****************************************************************************
- *
- * SkDrvEnterDiagMode - handles DIAG attach request
- *
- * Description:
- * Notify the kernel to NOT access the card any longer due to DIAG
- * Deinitialize the Card
- *
- * Returns:
- * int
- */
-int SkDrvEnterDiagMode(
-SK_AC *pAc) /* pointer to adapter context */
-{
- DEV_NET *pNet = netdev_priv(pAc->dev[0]);
- SK_AC *pAC = pNet->pAC;
-
- SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct),
- sizeof(SK_PNMI_STRUCT_DATA));
-
- pAC->DiagModeActive = DIAG_ACTIVE;
- if (pAC->BoardLevel > SK_INIT_DATA) {
- if (netif_running(pAC->dev[0])) {
- pAC->WasIfUp[0] = SK_TRUE;
- pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */
- } else {
- pAC->WasIfUp[0] = SK_FALSE;
- }
- if (pNet != netdev_priv(pAC->dev[1])) {
- pNet = netdev_priv(pAC->dev[1]);
- if (netif_running(pAC->dev[1])) {
- pAC->WasIfUp[1] = SK_TRUE;
- pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvDeInitAdapter(pAC, 1); /* do SkGeClose */
- } else {
- pAC->WasIfUp[1] = SK_FALSE;
- }
- }
- pAC->BoardLevel = SK_INIT_DATA;
- }
- return(0);
-}
-
-/*****************************************************************************
- *
- * SkDrvLeaveDiagMode - handles DIAG detach request
- *
- * Description:
- * Notify the kernel to may access the card again after use by DIAG
- * Initialize the Card
- *
- * Returns:
- * int
- */
-int SkDrvLeaveDiagMode(
-SK_AC *pAc) /* pointer to adapter control context */
-{
- SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup),
- sizeof(SK_PNMI_STRUCT_DATA));
- pAc->DiagModeActive = DIAG_NOTACTIVE;
- pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
- if (pAc->WasIfUp[0] == SK_TRUE) {
- pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvInitAdapter(pAc, 0); /* first device */
- }
- if (pAc->WasIfUp[1] == SK_TRUE) {
- pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvInitAdapter(pAc, 1); /* second device */
- }
- return(0);
-}
-
-/*****************************************************************************
- *
- * ParseDeviceNbrFromSlotName - Evaluate PCI device number
- *
- * Description:
- * This function parses the PCI slot name information string and will
- * retrieve the devcie number out of it. The slot_name maintianed by
- * linux is in the form of '02:0a.0', whereas the first two characters
- * represent the bus number in hex (in the sample above this is
- * pci bus 0x02) and the next two characters the device number (0x0a).
- *
- * Returns:
- * SK_U32: The device number from the PCI slot name
- */
-
-static SK_U32 ParseDeviceNbrFromSlotName(
-const char *SlotName) /* pointer to pci slot name eg. '02:0a.0' */
-{
- char *CurrCharPos = (char *) SlotName;
- int FirstNibble = -1;
- int SecondNibble = -1;
- SK_U32 Result = 0;
-
- while (*CurrCharPos != '\0') {
- if (*CurrCharPos == ':') {
- while (*CurrCharPos != '.') {
- CurrCharPos++;
- if ( (*CurrCharPos >= '0') &&
- (*CurrCharPos <= '9')) {
- if (FirstNibble == -1) {
- /* dec. value for '0' */
- FirstNibble = *CurrCharPos - 48;
- } else {
- SecondNibble = *CurrCharPos - 48;
- }
- } else if ( (*CurrCharPos >= 'a') &&
- (*CurrCharPos <= 'f') ) {
- if (FirstNibble == -1) {
- FirstNibble = *CurrCharPos - 87;
- } else {
- SecondNibble = *CurrCharPos - 87;
- }
- } else {
- Result = 0;
- }
- }
-
- Result = FirstNibble;
- Result = Result << 4; /* first nibble is higher one */
- Result = Result | SecondNibble;
- }
- CurrCharPos++; /* next character */
- }
- return (Result);
-}
-
-/****************************************************************************
- *
- * SkDrvDeInitAdapter - deinitialize adapter (this function is only
- * called if Diag attaches to that card)
- *
- * Description:
- * Close initialized adapter.
- *
- * Returns:
- * 0 - on success
- * error code - on error
- */
-static int SkDrvDeInitAdapter(
-SK_AC *pAC, /* pointer to adapter context */
-int devNbr) /* what device is to be handled */
-{
- struct SK_NET_DEVICE *dev;
-
- dev = pAC->dev[devNbr];
-
- /* On Linux 2.6 the network driver does NOT mess with reference
- ** counts. The driver MUST be able to be unloaded at any time
- ** due to the possibility of hotplug.
- */
- if (SkGeClose(dev) != 0) {
- return (-1);
- }
- return (0);
-
-} /* SkDrvDeInitAdapter() */
-
-/****************************************************************************
- *
- * SkDrvInitAdapter - Initialize adapter (this function is only
- * called if Diag deattaches from that card)
- *
- * Description:
- * Close initialized adapter.
- *
- * Returns:
- * 0 - on success
- * error code - on error
- */
-static int SkDrvInitAdapter(
-SK_AC *pAC, /* pointer to adapter context */
-int devNbr) /* what device is to be handled */
-{
- struct SK_NET_DEVICE *dev;
-
- dev = pAC->dev[devNbr];
-
- if (SkGeOpen(dev) != 0) {
- return (-1);
- }
-
- /*
- ** Use correct MTU size and indicate to kernel TX queue can be started
- */
- if (SkGeChangeMtu(dev, dev->mtu) != 0) {
- return (-1);
- }
- return (0);
-
-} /* SkDrvInitAdapter */
-
-#endif
-
-#ifdef DEBUG
-/****************************************************************************/
-/* "debug only" section *****************************************************/
-/****************************************************************************/
-
-
-/*****************************************************************************
- *
- * DumpMsg - print a frame
- *
- * Description:
- * This function prints frames to the system logfile/to the console.
- *
- * Returns: N/A
- *
- */
-static void DumpMsg(struct sk_buff *skb, char *str)
-{
- int msglen;
-
- if (skb == NULL) {
- printk("DumpMsg(): NULL-Message\n");
- return;
- }
-
- if (skb->data == NULL) {
- printk("DumpMsg(): Message empty\n");
- return;
- }
-
- msglen = skb->len;
- if (msglen > 64)
- msglen = 64;
-
- printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len);
-
- DumpData((char *)skb->data, msglen);
-
- printk("------- End of message ---------\n");
-} /* DumpMsg */
-
-
-
-/*****************************************************************************
- *
- * DumpData - print a data area
- *
- * Description:
- * This function prints a area of data to the system logfile/to the
- * console.
- *
- * Returns: N/A
- *
- */
-static void DumpData(char *p, int size)
-{
-register int i;
-int haddr, addr;
-char hex_buffer[180];
-char asc_buffer[180];
-char HEXCHAR[] = "0123456789ABCDEF";
-
- addr = 0;
- haddr = 0;
- hex_buffer[0] = 0;
- asc_buffer[0] = 0;
- for (i=0; i < size; ) {
- if (*p >= '0' && *p <='z')
- asc_buffer[addr] = *p;
- else
- asc_buffer[addr] = '.';
- addr++;
- asc_buffer[addr] = 0;
- hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[*p & 0x0f];
- haddr++;
- hex_buffer[haddr] = ' ';
- haddr++;
- hex_buffer[haddr] = 0;
- p++;
- i++;
- if (i%16 == 0) {
- printk("%s %s\n", hex_buffer, asc_buffer);
- addr = 0;
- haddr = 0;
- }
- }
-} /* DumpData */
-
-
-/*****************************************************************************
- *
- * DumpLong - print a data area as long values
- *
- * Description:
- * This function prints a area of data to the system logfile/to the
- * console.
- *
- * Returns: N/A
- *
- */
-static void DumpLong(char *pc, int size)
-{
-register int i;
-int haddr, addr;
-char hex_buffer[180];
-char asc_buffer[180];
-char HEXCHAR[] = "0123456789ABCDEF";
-long *p;
-int l;
-
- addr = 0;
- haddr = 0;
- hex_buffer[0] = 0;
- asc_buffer[0] = 0;
- p = (long*) pc;
- for (i=0; i < size; ) {
- l = (long) *p;
- hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf];
- haddr++;
- hex_buffer[haddr] = HEXCHAR[l & 0x0f];
- haddr++;
- hex_buffer[haddr] = ' ';
- haddr++;
- hex_buffer[haddr] = 0;
- p++;
- i++;
- if (i%8 == 0) {
- printk("%4x %s\n", (i-8)*4, hex_buffer);
- haddr = 0;
- }
- }
- printk("------------------------\n");
-} /* DumpLong */
-
-#endif
-
-static int __devinit skge_probe_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- SK_AC *pAC;
- DEV_NET *pNet = NULL;
- struct net_device *dev = NULL;
- static int boards_found = 0;
- int error = -ENODEV;
- int using_dac = 0;
- char DeviceStr[80];
-
- if (pci_enable_device(pdev))
- goto out;
-
- /* Configure DMA attributes. */
- if (sizeof(dma_addr_t) > sizeof(u32) &&
- !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {
- using_dac = 1;
- error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
- if (error < 0) {
- printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA "
- "for consistent allocations\n", pci_name(pdev));
- goto out_disable_device;
- }
- } else {
- error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
- if (error) {
- printk(KERN_ERR "sk98lin %s no usable DMA configuration\n",
- pci_name(pdev));
- goto out_disable_device;
- }
- }
-
- error = -ENOMEM;
- dev = alloc_etherdev(sizeof(DEV_NET));
- if (!dev) {
- printk(KERN_ERR "sk98lin: unable to allocate etherdev "
- "structure!\n");
- goto out_disable_device;
- }
-
- pNet = netdev_priv(dev);
- pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL);
- if (!pNet->pAC) {
- printk(KERN_ERR "sk98lin: unable to allocate adapter "
- "structure!\n");
- goto out_free_netdev;
- }
-
- pAC = pNet->pAC;
- pAC->PciDev = pdev;
-
- pAC->dev[0] = dev;
- pAC->dev[1] = dev;
- pAC->CheckQueue = SK_FALSE;
-
- dev->irq = pdev->irq;
-
- error = SkGeInitPCI(pAC);
- if (error) {
- printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error);
- goto out_free_netdev;
- }
-
- SET_MODULE_OWNER(dev);
- dev->open = &SkGeOpen;
- dev->stop = &SkGeClose;
- dev->hard_start_xmit = &SkGeXmit;
- dev->get_stats = &SkGeStats;
- dev->set_multicast_list = &SkGeSetRxMode;
- dev->set_mac_address = &SkGeSetMacAddr;
- dev->do_ioctl = &SkGeIoctl;
- dev->change_mtu = &SkGeChangeMtu;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &SkGePollController;
-#endif
- SET_NETDEV_DEV(dev, &pdev->dev);
- SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
- /* Use only if yukon hardware */
- if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
- dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
- dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
- pAC->RxPort[0].RxCsum = 1;
-#endif
- }
-
- if (using_dac)
- dev->features |= NETIF_F_HIGHDMA;
-
- pAC->Index = boards_found++;
-
- error = SkGeBoardInit(dev, pAC);
- if (error)
- goto out_free_netdev;
-
- /* Read Adapter name from VPD */
- if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) {
- error = -EIO;
- printk(KERN_ERR "sk98lin: Could not read VPD data.\n");
- goto out_free_resources;
- }
-
- /* Register net device */
- error = register_netdev(dev);
- if (error) {
- printk(KERN_ERR "sk98lin: Could not register device.\n");
- goto out_free_resources;
- }
-
- /* Print adapter specific string from vpd */
- printk("%s: %s\n", dev->name, DeviceStr);
-
- /* Print configuration settings */
- printk(" PrefPort:%c RlmtMode:%s\n",
- 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
- (pAC->RlmtMode==0) ? "Check Link State" :
- ((pAC->RlmtMode==1) ? "Check Link State" :
- ((pAC->RlmtMode==3) ? "Check Local Port" :
- ((pAC->RlmtMode==7) ? "Check Segmentation" :
- ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
- SkGeYellowLED(pAC, pAC->IoBase, 1);
-
- memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
- pNet->PortNr = 0;
- pNet->NetNr = 0;
-
- boards_found++;
-
- pci_set_drvdata(pdev, dev);
-
- /* More then one port found */
- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
- dev = alloc_etherdev(sizeof(DEV_NET));
- if (!dev) {
- printk(KERN_ERR "sk98lin: unable to allocate etherdev "
- "structure!\n");
- goto single_port;
- }
-
- pNet = netdev_priv(dev);
- pNet->PortNr = 1;
- pNet->NetNr = 1;
- pNet->pAC = pAC;
-
- dev->open = &SkGeOpen;
- dev->stop = &SkGeClose;
- dev->hard_start_xmit = &SkGeXmit;
- dev->get_stats = &SkGeStats;
- dev->set_multicast_list = &SkGeSetRxMode;
- dev->set_mac_address = &SkGeSetMacAddr;
- dev->do_ioctl = &SkGeIoctl;
- dev->change_mtu = &SkGeChangeMtu;
- SET_NETDEV_DEV(dev, &pdev->dev);
- SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
-
- if (pAC->ChipsetType) {
-#ifdef USE_SK_TX_CHECKSUM
- dev->features |= NETIF_F_IP_CSUM;
-#endif
-#ifdef SK_ZEROCOPY
- dev->features |= NETIF_F_SG;
-#endif
-#ifdef USE_SK_RX_CHECKSUM
- pAC->RxPort[1].RxCsum = 1;
-#endif
- }
-
- if (using_dac)
- dev->features |= NETIF_F_HIGHDMA;
-
- error = register_netdev(dev);
- if (error) {
- printk(KERN_ERR "sk98lin: Could not register device"
- " for second port. (%d)\n", error);
- free_netdev(dev);
- goto single_port;
- }
-
- pAC->dev[1] = dev;
- memcpy(&dev->dev_addr,
- &pAC->Addr.Net[1].CurrentMacAddress, 6);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
- printk("%s: %s\n", dev->name, DeviceStr);
- printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
- }
-
-single_port:
-
- /* Save the hardware revision */
- pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
- (pAC->GIni.GIPciHwRev & 0x0F);
-
- /* Set driver globals */
- pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME;
- pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
-
- memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
- memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
-
- return 0;
-
- out_free_resources:
- FreeResources(dev);
- out_free_netdev:
- free_netdev(dev);
- out_disable_device:
- pci_disable_device(pdev);
- out:
- return error;
-}
-
-static void __devexit skge_remove_one(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- struct net_device *otherdev = pAC->dev[1];
-
- unregister_netdev(dev);
-
- SkGeYellowLED(pAC, pAC->IoBase, 0);
-
- if (pAC->BoardLevel == SK_INIT_RUN) {
- SK_EVPARA EvPara;
- unsigned long Flags;
-
- /* board is still alive */
- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
- EvPara.Para32[0] = 0;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- EvPara.Para32[0] = 1;
- EvPara.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
- SkEventDispatcher(pAC, pAC->IoBase);
- /* disable interrupts */
- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
- SkGeDeInit(pAC, pAC->IoBase);
- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
- pAC->BoardLevel = SK_INIT_DATA;
- /* We do NOT check here, if IRQ was pending, of course*/
- }
-
- if (pAC->BoardLevel == SK_INIT_IO) {
- /* board is still alive */
- SkGeDeInit(pAC, pAC->IoBase);
- pAC->BoardLevel = SK_INIT_DATA;
- }
-
- FreeResources(dev);
- free_netdev(dev);
- if (otherdev != dev)
- free_netdev(otherdev);
- kfree(pAC);
-}
-
-#ifdef CONFIG_PM
-static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- struct net_device *otherdev = pAC->dev[1];
-
- if (netif_running(dev)) {
- netif_carrier_off(dev);
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */
- netif_device_detach(dev);
- }
- if (otherdev != dev) {
- if (netif_running(otherdev)) {
- netif_carrier_off(otherdev);
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */
- netif_device_detach(otherdev);
- }
- }
-
- pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
- if (pAC->AllocFlag & SK_ALLOC_IRQ) {
- free_irq(dev->irq, dev);
- }
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
- return 0;
-}
-
-static int skge_resume(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata(pdev);
- DEV_NET *pNet = netdev_priv(dev);
- SK_AC *pAC = pNet->pAC;
- struct net_device *otherdev = pAC->dev[1];
- int ret;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- ret = pci_enable_device(pdev);
- if (ret) {
- printk(KERN_WARNING "sk98lin: unable to enable device %s "
- "in resume\n", dev->name);
- goto err_out;
- }
- pci_set_master(pdev);
- if (pAC->GIni.GIMacsFound == 2)
- ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev);
- else
- ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev);
- if (ret) {
- printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq);
- ret = -EBUSY;
- goto err_out_disable_pdev;
- }
-
- netif_device_attach(dev);
- if (netif_running(dev)) {
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvInitAdapter(pAC, 0); /* first device */
- }
- if (otherdev != dev) {
- netif_device_attach(otherdev);
- if (netif_running(otherdev)) {
- DoPrintInterfaceChange = SK_FALSE;
- SkDrvInitAdapter(pAC, 1); /* second device */
- }
- }
-
- return 0;
-
-err_out_disable_pdev:
- pci_disable_device(pdev);
-err_out:
- pAC->AllocFlag &= ~SK_ALLOC_IRQ;
- dev->irq = 0;
- return ret;
-}
-#else
-#define skge_suspend NULL
-#define skge_resume NULL
-#endif
-
-static struct pci_device_id skge_pci_tbl[] = {
- { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-/* DLink card does not have valid VPD so this driver gags
- * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- */
- { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
- { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
-
-static struct pci_driver skge_driver = {
- .name = "sk98lin",
- .id_table = skge_pci_tbl,
- .probe = skge_probe_one,
- .remove = __devexit_p(skge_remove_one),
- .suspend = skge_suspend,
- .resume = skge_resume,
-};
-
-static int __init skge_init(void)
-{
- printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver"
- " and is scheduled for removal\n");
-
- return pci_register_driver(&skge_driver);
-}
-
-static void __exit skge_exit(void)
-{
- pci_unregister_driver(&skge_driver);
-}
-
-module_init(skge_init);
-module_exit(skge_exit);
diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c
deleted file mode 100644
index db670993c2d..00000000000
--- a/drivers/net/sk98lin/skgehwt.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/******************************************************************************
- *
- * Name: skgehwt.c
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.15 $
- * Date: $Date: 2003/09/16 13:41:23 $
- * Purpose: Hardware Timer
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- * Hardware Timer function queue management.
- */
-intro()
-{}
-#endif
-
-/*
- * Prototypes of local functions.
- */
-#define SK_HWT_MAX (65000)
-
-/* correction factor */
-#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100)
-
-/*
- * Initialize hardware timer.
- *
- * Must be called during init level 1.
- */
-void SkHwtInit(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- pAC->Hwt.TStart = 0 ;
- pAC->Hwt.TStop = 0 ;
- pAC->Hwt.TActive = SK_FALSE;
-
- SkHwtStop(pAC, Ioc);
-}
-
-/*
- *
- * Start hardware timer (clock ticks are 16us).
- *
- */
-void SkHwtStart(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-SK_U32 Time) /* Time in units of 16us to load the timer with. */
-{
- SK_U32 Cnt;
-
- if (Time > SK_HWT_MAX)
- Time = SK_HWT_MAX;
-
- pAC->Hwt.TStart = Time;
- pAC->Hwt.TStop = 0L;
-
- Cnt = Time;
-
- /*
- * if time < 16 us
- * time = 16 us
- */
- if (!Cnt) {
- Cnt++;
- }
-
- SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC);
-
- SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer. */
-
- pAC->Hwt.TActive = SK_TRUE;
-}
-
-/*
- * Stop hardware timer.
- * and clear the timer IRQ
- */
-void SkHwtStop(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
-
- SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
-
- pAC->Hwt.TActive = SK_FALSE;
-}
-
-
-/*
- * Stop hardware timer and read time elapsed since last start.
- *
- * returns
- * The elapsed time since last start in units of 16us.
- *
- */
-SK_U32 SkHwtRead(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- SK_U32 TRead;
- SK_U32 IStatus;
-
- if (pAC->Hwt.TActive) {
-
- SkHwtStop(pAC, Ioc);
-
- SK_IN32(Ioc, B2_TI_VAL, &TRead);
- TRead /= SK_HWT_FAC;
-
- SK_IN32(Ioc, B0_ISRC, &IStatus);
-
- /* Check if timer expired (or wraped around) */
- if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) {
-
- SkHwtStop(pAC, Ioc);
-
- pAC->Hwt.TStop = pAC->Hwt.TStart;
- }
- else {
-
- pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
- }
- }
- return(pAC->Hwt.TStop);
-}
-
-/*
- * interrupt source= timer
- */
-void SkHwtIsr(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- SkHwtStop(pAC, Ioc);
-
- pAC->Hwt.TStop = pAC->Hwt.TStart;
-
- SkTimerDone(pAC, Ioc);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c
deleted file mode 100644
index 67f1d6a5c15..00000000000
--- a/drivers/net/sk98lin/skgeinit.c
+++ /dev/null
@@ -1,2005 +0,0 @@
-/******************************************************************************
- *
- * Name: skgeinit.c
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.97 $
- * Date: $Date: 2003/10/02 16:45:31 $
- * Purpose: Contains functions to initialize the adapter
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* global variables ***********************************************************/
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell.";
-#endif
-
-struct s_QOffTab {
- int RxQOff; /* Receive Queue Address Offset */
- int XsQOff; /* Sync Tx Queue Address Offset */
- int XaQOff; /* Async Tx Queue Address Offset */
-};
-static struct s_QOffTab QOffTab[] = {
- {Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2}
-};
-
-struct s_Config {
- char ScanString[8];
- SK_U32 Value;
-};
-
-static struct s_Config OemConfig = {
- {'O','E','M','_','C','o','n','f'},
-#ifdef SK_OEM_CONFIG
- OEM_CONFIG_VALUE,
-#else
- 0,
-#endif
-};
-
-/******************************************************************************
- *
- * SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings
- *
- * Description:
- * Enable or disable the descriptor polling of the transmit descriptor
- * ring(s) (TxD) for port 'Port'.
- * The new configuration is *not* saved over any SkGeStopPort() and
- * SkGeInitPort() calls.
- *
- * Returns:
- * nothing
- */
-void SkGePollTxD(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
-{
- SK_GEPORT *pPrt;
- SK_U32 DWord;
-
- pPrt = &pAC->GIni.GP[Port];
-
- DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL);
-
- if (pPrt->PXSQSize != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
- }
-
- if (pPrt->PXAQSize != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
- }
-} /* SkGePollTxD */
-
-
-/******************************************************************************
- *
- * SkGeYellowLED() - Switch the yellow LED on or off.
- *
- * Description:
- * Switch the yellow LED on or off.
- *
- * Note:
- * This function may be called any time after SkGeInit(Level 1).
- *
- * Returns:
- * nothing
- */
-void SkGeYellowLED(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int State) /* yellow LED state, 0 = OFF, 0 != ON */
-{
- if (State == 0) {
- /* Switch yellow LED OFF */
- SK_OUT8(IoC, B0_LED, LED_STAT_OFF);
- }
- else {
- /* Switch yellow LED ON */
- SK_OUT8(IoC, B0_LED, LED_STAT_ON);
- }
-} /* SkGeYellowLED */
-
-
-#if (!defined(SK_SLIM) || defined(GENESIS))
-/******************************************************************************
- *
- * SkGeXmitLED() - Modify the Operational Mode of a transmission LED.
- *
- * Description:
- * The Rx or Tx LED which is specified by 'Led' will be
- * enabled, disabled or switched on in test mode.
- *
- * Note:
- * 'Led' must contain the address offset of the LEDs INI register.
- *
- * Usage:
- * SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
- *
- * Returns:
- * nothing
- */
-void SkGeXmitLED(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Led, /* offset to the LED Init Value register */
-int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
-{
- SK_U32 LedIni;
-
- switch (Mode) {
- case SK_LED_ENA:
- LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
- SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni);
- SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
- break;
- case SK_LED_TST:
- SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON);
- SK_OUT32(IoC, Led + XMIT_LED_CNT, 100);
- SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START);
- break;
- case SK_LED_DIS:
- default:
- /*
- * Do NOT stop the LED Timer here. The LED might be
- * in on state. But it needs to go off.
- */
- SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
- SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
- break;
- }
-
- /*
- * 1000BT: The Transmit LED is driven by the PHY.
- * But the default LED configuration is used for
- * Level One and Broadcom PHYs.
- * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.)
- * (In this case it has to be added here. But we will see. XXX)
- */
-} /* SkGeXmitLED */
-#endif /* !SK_SLIM || GENESIS */
-
-
-/******************************************************************************
- *
- * DoCalcAddr() - Calculates the start and the end address of a queue.
- *
- * Description:
- * This function calculates the start and the end address of a queue.
- * Afterwards the 'StartVal' is incremented to the next start position.
- * If the port is already initialized the calculated values
- * will be checked against the configured values and an
- * error will be returned, if they are not equal.
- * If the port is not initialized the values will be written to
- * *StartAdr and *EndAddr.
- *
- * Returns:
- * 0: success
- * 1: configuration error
- */
-static int DoCalcAddr(
-SK_AC *pAC, /* adapter context */
-SK_GEPORT SK_FAR *pPrt, /* port index */
-int QuSize, /* size of the queue to configure in kB */
-SK_U32 SK_FAR *StartVal, /* start value for address calculation */
-SK_U32 SK_FAR *QuStartAddr,/* start addr to calculate */
-SK_U32 SK_FAR *QuEndAddr) /* end address to calculate */
-{
- SK_U32 EndVal;
- SK_U32 NextStart;
- int Rtv;
-
- Rtv = 0;
- if (QuSize == 0) {
- EndVal = *StartVal;
- NextStart = EndVal;
- }
- else {
- EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1;
- NextStart = EndVal + 1;
- }
-
- if (pPrt->PState >= SK_PRT_INIT) {
- if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) {
- Rtv = 1;
- }
- }
- else {
- *QuStartAddr = *StartVal;
- *QuEndAddr = EndVal;
- }
-
- *StartVal = NextStart;
- return(Rtv);
-} /* DoCalcAddr */
-
-/******************************************************************************
- *
- * SkGeInitAssignRamToQueues() - allocate default queue sizes
- *
- * Description:
- * This function assigns the memory to the different queues and ports.
- * When DualNet is set to SK_TRUE all ports get the same amount of memory.
- * Otherwise the first port gets most of the memory and all the
- * other ports just the required minimum.
- * This function can only be called when pAC->GIni.GIRamSize and
- * pAC->GIni.GIMacsFound have been initialized, usually this happens
- * at init level 1
- *
- * Returns:
- * 0 - ok
- * 1 - invalid input values
- * 2 - not enough memory
- */
-
-int SkGeInitAssignRamToQueues(
-SK_AC *pAC, /* Adapter context */
-int ActivePort, /* Active Port in RLMT mode */
-SK_BOOL DualNet) /* adapter context */
-{
- int i;
- int UsedKilobytes; /* memory already assigned */
- int ActivePortKilobytes; /* memory available for active port */
- SK_GEPORT *pGePort;
-
- UsedKilobytes = 0;
-
- if (ActivePort >= pAC->GIni.GIMacsFound) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
- ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
- ActivePort));
- return(1);
- }
- if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) +
- ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
- ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
- pAC->GIni.GIRamSize));
- return(2);
- }
-
- if (DualNet) {
- /* every port gets the same amount of memory */
- ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound;
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
- pGePort = &pAC->GIni.GP[i];
-
- /* take away the minimum memory for active queues */
- ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
-
- /* receive queue gets the minimum + 80% of the rest */
- pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((
- ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100))
- + SK_MIN_RXQ_SIZE;
-
- ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
- /* synchronous transmit queue */
- pGePort->PXSQSize = 0;
-
- /* asynchronous transmit queue */
- pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes +
- SK_MIN_TXQ_SIZE);
- }
- }
- else {
- /* Rlmt Mode or single link adapter */
-
- /* Set standby queue size defaults for all standby ports */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
- if (i != ActivePort) {
- pGePort = &pAC->GIni.GP[i];
-
- pGePort->PRxQSize = SK_MIN_RXQ_SIZE;
- pGePort->PXAQSize = SK_MIN_TXQ_SIZE;
- pGePort->PXSQSize = 0;
-
- /* Count used RAM */
- UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize;
- }
- }
- /* what's left? */
- ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes;
-
- /* assign it to the active port */
- /* first take away the minimum memory */
- ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
- pGePort = &pAC->GIni.GP[ActivePort];
-
- /* receive queue get's the minimum + 80% of the rest */
- pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes *
- (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE;
-
- ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
-
- /* synchronous transmit queue */
- pGePort->PXSQSize = 0;
-
- /* asynchronous transmit queue */
- pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) +
- SK_MIN_TXQ_SIZE;
- }
-#ifdef VCPU
- VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n",
- pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize);
-#endif /* VCPU */
-
- return(0);
-} /* SkGeInitAssignRamToQueues */
-
-/******************************************************************************
- *
- * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
- *
- * Description:
- * This function verifies the Queue Size Configuration specified
- * in the variables PRxQSize, PXSQSize, and PXAQSize of all
- * used ports.
- * This requirements must be fullfilled to have a valid configuration:
- * - The size of all queues must not exceed GIRamSize.
- * - The queue sizes must be specified in units of 8 kB.
- * - The size of Rx queues of available ports must not be
- * smaller than 16 kB.
- * - The size of at least one Tx queue (synch. or asynch.)
- * of available ports must not be smaller than 16 kB
- * when Jumbo Frames are used.
- * - The RAM start and end addresses must not be changed
- * for ports which are already initialized.
- * Furthermore SkGeCheckQSize() defines the Start and End Addresses
- * of all ports and stores them into the HWAC port structure.
- *
- * Returns:
- * 0: Queue Size Configuration valid
- * 1: Queue Size Configuration invalid
- */
-static int SkGeCheckQSize(
-SK_AC *pAC, /* adapter context */
-int Port) /* port index */
-{
- SK_GEPORT *pPrt;
- int i;
- int Rtv;
- int Rtv2;
- SK_U32 StartAddr;
-#ifndef SK_SLIM
- int UsedMem; /* total memory used (max. found ports) */
-#endif
-
- Rtv = 0;
-
-#ifndef SK_SLIM
-
- UsedMem = 0;
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- pPrt = &pAC->GIni.GP[i];
-
- if ((pPrt->PRxQSize & QZ_UNITS) != 0 ||
- (pPrt->PXSQSize & QZ_UNITS) != 0 ||
- (pPrt->PXAQSize & QZ_UNITS) != 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
- return(1);
- }
-
- if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
- return(1);
- }
-
- /*
- * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
- * if Jumbo Frames are used, this size has to be >= 16 kB.
- */
- if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
- (pAC->GIni.GIPortUsage == SK_JUMBO_LINK &&
- ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
- (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
- return(1);
- }
-
- UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
- }
-
- if (UsedMem > pAC->GIni.GIRamSize) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
- return(1);
- }
-#endif /* !SK_SLIM */
-
- /* Now start address calculation */
- StartAddr = pAC->GIni.GIRamOffs;
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- pPrt = &pAC->GIni.GP[i];
-
- /* Calculate/Check values for the receive queue */
- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
- &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
- Rtv |= Rtv2;
-
- /* Calculate/Check values for the synchronous Tx queue */
- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr,
- &pPrt->PXsQRamStart, &pPrt->PXsQRamEnd);
- Rtv |= Rtv2;
-
- /* Calculate/Check values for the asynchronous Tx queue */
- Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr,
- &pPrt->PXaQRamStart, &pPrt->PXaQRamEnd);
- Rtv |= Rtv2;
-
- if (Rtv) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG);
- return(1);
- }
- }
-
- return(0);
-} /* SkGeCheckQSize */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGeInitMacArb() - Initialize the MAC Arbiter
- *
- * Description:
- * This function initializes the MAC Arbiter.
- * It must not be called if there is still an
- * initialized or active port.
- *
- * Returns:
- * nothing
- */
-static void SkGeInitMacArb(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- /* release local reset */
- SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
-
- /* configure timeout values */
- SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53);
- SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53);
- SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53);
- SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53);
-
- SK_OUT8(IoC, B3_MA_RCINI_RX1, 0);
- SK_OUT8(IoC, B3_MA_RCINI_RX2, 0);
- SK_OUT8(IoC, B3_MA_RCINI_TX1, 0);
- SK_OUT8(IoC, B3_MA_RCINI_TX2, 0);
-
- /* recovery values are needed for XMAC II Rev. B2 only */
- /* Fast Output Enable Mode was intended to use with Rev. B2, but now? */
-
- /*
- * There is no start or enable button to push, therefore
- * the MAC arbiter is configured and enabled now.
- */
-} /* SkGeInitMacArb */
-
-
-/******************************************************************************
- *
- * SkGeInitPktArb() - Initialize the Packet Arbiter
- *
- * Description:
- * This function initializes the Packet Arbiter.
- * It must not be called if there is still an
- * initialized or active port.
- *
- * Returns:
- * nothing
- */
-static void SkGeInitPktArb(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- /* release local reset */
- SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
-
- /* configure timeout values */
- SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
- SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
- SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
- SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
-
- /*
- * enable timeout timers if jumbo frames not used
- * NOTE: the packet arbiter timeout interrupt is needed for
- * half duplex hangup workaround
- */
- if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) {
- if (pAC->GIni.GIMacsFound == 1) {
- SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
- }
- else {
- SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2);
- }
- }
-} /* SkGeInitPktArb */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkGeInitMacFifo() - Initialize the MAC FIFOs
- *
- * Description:
- * Initialize all MAC FIFOs of the specified port
- *
- * Returns:
- * nothing
- */
-static void SkGeInitMacFifo(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 Word;
-#ifdef VCPU
- SK_U32 DWord;
-#endif /* VCPU */
- /*
- * For each FIFO:
- * - release local reset
- * - use default value for MAC FIFO size
- * - setup defaults for the control register
- * - enable the FIFO
- */
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* Configure Rx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
-
- /* Configure Tx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
-
- /* Enable frame flushing if jumbo frames used */
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* set Rx GMAC FIFO Flush Mask */
- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK);
-
- Word = (SK_U16)GMF_RX_CTRL_DEF;
-
- /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
- if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) {
-
- Word &= ~GMF_RX_F_FL_ON;
- }
-
- /* Configure Rx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
-
- /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */
- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
-
- /* Configure Tx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
- SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
-
-#ifdef VCPU
- SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord);
- SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord);
-#endif /* VCPU */
-
- /* set Tx GMAC FIFO Almost Empty Threshold */
-/* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */
- }
-#endif /* YUKON */
-
-} /* SkGeInitMacFifo */
-
-#ifdef SK_LNK_SYNC_CNT
-/******************************************************************************
- *
- * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
- *
- * Description:
- * This function starts the Link Sync Counter of the specified
- * port and enables the generation of an Link Sync IRQ.
- * The Link Sync Counter may be used to detect an active link,
- * if autonegotiation is not used.
- *
- * Note:
- * o To ensure receiving the Link Sync Event the LinkSyncCounter
- * should be initialized BEFORE clearing the XMAC's reset!
- * o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this
- * function.
- *
- * Returns:
- * nothing
- */
-void SkGeLoadLnkSyncCnt(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U32 CntVal) /* Counter value */
-{
- SK_U32 OrgIMsk;
- SK_U32 NewIMsk;
- SK_U32 ISrc;
- SK_BOOL IrqPend;
-
- /* stop counter */
- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP);
-
- /*
- * ASIC problem:
- * Each time starting the Link Sync Counter an IRQ is generated
- * by the adapter. See problem report entry from 21.07.98
- *
- * Workaround: Disable Link Sync IRQ and clear the unexpeced IRQ
- * if no IRQ is already pending.
- */
- IrqPend = SK_FALSE;
- SK_IN32(IoC, B0_ISRC, &ISrc);
- SK_IN32(IoC, B0_IMSK, &OrgIMsk);
- if (Port == MAC_1) {
- NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
- if ((ISrc & IS_LNK_SYNC_M1) != 0) {
- IrqPend = SK_TRUE;
- }
- }
- else {
- NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2;
- if ((ISrc & IS_LNK_SYNC_M2) != 0) {
- IrqPend = SK_TRUE;
- }
- }
- if (!IrqPend) {
- SK_OUT32(IoC, B0_IMSK, NewIMsk);
- }
-
- /* load counter */
- SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
-
- /* start counter */
- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START);
-
- if (!IrqPend) {
- /* clear the unexpected IRQ, and restore the interrupt mask */
- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ);
- SK_OUT32(IoC, B0_IMSK, OrgIMsk);
- }
-} /* SkGeLoadLnkSyncCnt*/
-#endif /* SK_LNK_SYNC_CNT */
-
-#if defined(SK_DIAG) || defined(SK_CFG_SYNC)
-/******************************************************************************
- *
- * SkGeCfgSync() - Configure synchronous bandwidth for this port.
- *
- * Description:
- * This function may be used to configure synchronous bandwidth
- * to the specified port. This may be done any time after
- * initializing the port. The configuration values are NOT saved
- * in the HWAC port structure and will be overwritten any
- * time when stopping and starting the port.
- * Any values for the synchronous configuration will be ignored
- * if the size of the synchronous queue is zero!
- *
- * The default configuration for the synchronous service is
- * TXA_ENA_FSYNC. This means if the size of
- * the synchronous queue is unequal zero but no specific
- * synchronous bandwidth is configured, the synchronous queue
- * will always have the 'unlimited' transmit priority!
- *
- * This mode will be restored if the synchronous bandwidth is
- * deallocated ('IntTime' = 0 and 'LimCount' = 0).
- *
- * Returns:
- * 0: success
- * 1: parameter configuration error
- * 2: try to configure quality of service although no
- * synchronous queue is configured
- */
-int SkGeCfgSync(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U32 IntTime, /* Interval Timer Value in units of 8ns */
-SK_U32 LimCount, /* Number of bytes to transfer during IntTime */
-int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */
-{
- int Rtv;
-
- Rtv = 0;
-
- /* check the parameters */
- if (LimCount > IntTime ||
- (LimCount == 0 && IntTime != 0) ||
- (LimCount != 0 && IntTime == 0)) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
- return(1);
- }
-
- if (pAC->GIni.GP[Port].PXSQSize == 0) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
- return(2);
- }
-
- /* calculate register values */
- IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
- LimCount = LimCount / 8;
-
- if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
- return(1);
- }
-
- /*
- * - Enable 'Force Sync' to ensure the synchronous queue
- * has the priority while configuring the new values.
- * - Also 'disable alloc' to ensure the settings complies
- * to the SyncMode parameter.
- * - Disable 'Rate Control' to configure the new values.
- * - write IntTime and LimCount
- * - start 'Rate Control' and disable 'Force Sync'
- * if Interval Timer or Limit Counter not zero.
- */
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
- TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-
- SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
- SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
-
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
- (SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
-
- if (IntTime != 0 || LimCount != 0) {
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
- }
-
- return(0);
-} /* SkGeCfgSync */
-#endif /* SK_DIAG || SK_CFG_SYNC*/
-
-
-/******************************************************************************
- *
- * DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue
- *
- * Desccription:
- * If the queue is used, enable and initialize it.
- * Make sure the queue is still reset, if it is not used.
- *
- * Returns:
- * nothing
- */
-static void DoInitRamQueue(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int QuIoOffs, /* Queue IO Address Offset */
-SK_U32 QuStartAddr, /* Queue Start Address */
-SK_U32 QuEndAddr, /* Queue End Address */
-int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
-{
- SK_U32 RxUpThresVal;
- SK_U32 RxLoThresVal;
-
- if (QuStartAddr != QuEndAddr) {
- /* calculate thresholds, assume we have a big Rx queue */
- RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8;
- RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8;
-
- /* build HW address format */
- QuStartAddr = QuStartAddr / 8;
- QuEndAddr = QuEndAddr / 8;
-
- /* release local reset */
- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR);
-
- /* configure addresses */
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr);
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr);
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr);
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr);
-
- switch (QuType) {
- case SK_RX_SRAM_Q:
- /* configure threshold for small Rx Queue */
- RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8;
-
- /* continue with SK_RX_BRAM_Q */
- case SK_RX_BRAM_Q:
- /* write threshold for Rx Queue */
-
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
- SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
-
- /* the high priority threshold not used */
- break;
- case SK_TX_RAM_Q:
- /*
- * Do NOT use Store & Forward under normal operation due to
- * performance optimization (GENESIS only).
- * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB)
- * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
- * we NEED Store & Forward of the RAM buffer.
- */
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK ||
- pAC->GIni.GIYukon) {
- /* enable Store & Forward Mode for the Tx Side */
- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
- }
- break;
- }
-
- /* set queue operational */
- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD);
- }
- else {
- /* ensure the queue is still disabled */
- SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET);
- }
-} /* DoInitRamQueue */
-
-
-/******************************************************************************
- *
- * SkGeInitRamBufs() - Initialize the RAM Buffer Queues
- *
- * Description:
- * Initialize all RAM Buffer Queues of the specified port
- *
- * Returns:
- * nothing
- */
-static void SkGeInitRamBufs(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- int RxQType;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) {
- RxQType = SK_RX_SRAM_Q; /* small Rx Queue */
- }
- else {
- RxQType = SK_RX_BRAM_Q; /* big Rx Queue */
- }
-
- DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
- pPrt->PRxQRamEnd, RxQType);
-
- DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
- pPrt->PXsQRamEnd, SK_TX_RAM_Q);
-
- DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
- pPrt->PXaQRamEnd, SK_TX_RAM_Q);
-
-} /* SkGeInitRamBufs */
-
-
-/******************************************************************************
- *
- * SkGeInitRamIface() - Initialize the RAM Interface
- *
- * Description:
- * This function initializes the Adapters RAM Interface.
- *
- * Note:
- * This function is used in the diagnostics.
- *
- * Returns:
- * nothing
- */
-static void SkGeInitRamIface(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- /* release local reset */
- SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR);
-
- /* configure timeout values */
- SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53);
- SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53);
-
-} /* SkGeInitRamIface */
-
-
-/******************************************************************************
- *
- * SkGeInitBmu() - Initialize the BMU state machines
- *
- * Description:
- * Initialize all BMU state machines of the specified port
- *
- * Returns:
- * nothing
- */
-static void SkGeInitBmu(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U32 RxWm;
- SK_U32 TxWm;
-
- pPrt = &pAC->GIni.GP[Port];
-
- RxWm = SK_BMU_RX_WM;
- TxWm = SK_BMU_TX_WM;
-
- if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
- /* for better performance */
- RxWm /= 2;
- TxWm /= 2;
- }
-
- /* Rx Queue: Release all local resets and set the watermark */
- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
-
- /*
- * Tx Queue: Release all local resets if the queue is used !
- * set watermark
- */
- if (pPrt->PXSQSize != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
- }
-
- if (pPrt->PXAQSize != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
- }
- /*
- * Do NOT enable the descriptor poll timers here, because
- * the descriptor addresses are not specified yet.
- */
-} /* SkGeInitBmu */
-
-
-/******************************************************************************
- *
- * TestStopBit() - Test the stop bit of the queue
- *
- * Description:
- * Stopping a queue is not as simple as it seems to be.
- * If descriptor polling is enabled, it may happen
- * that RX/TX stop is done and SV idle is NOT set.
- * In this case we have to issue another stop command.
- *
- * Returns:
- * The queues control status register
- */
-static SK_U32 TestStopBit(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int QuIoOffs) /* Queue IO Address Offset */
-{
- SK_U32 QuCsr; /* CSR contents */
-
- SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
-
- if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
- /* Stop Descriptor overridden by start command */
- SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
-
- SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
- }
-
- return(QuCsr);
-} /* TestStopBit */
-
-
-/******************************************************************************
- *
- * SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'.
- *
- * Description:
- * After calling this function the descriptor rings and Rx and Tx
- * queues of this port may be reconfigured.
- *
- * It is possible to stop the receive and transmit path separate or
- * both together.
- *
- * Dir = SK_STOP_TX Stops the transmit path only and resets the MAC.
- * The receive queue is still active and
- * the pending Rx frames may be still transferred
- * into the RxD.
- * SK_STOP_RX Stop the receive path. The tansmit path
- * has to be stopped once before.
- * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX
- *
- * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive.
- * SK_HARD_RST Resets the MAC and the PHY.
- *
- * Example:
- * 1) A Link Down event was signaled for a port. Therefore the activity
- * of this port should be stopped and a hardware reset should be issued
- * to enable the workaround of XMAC Errata #2. But the received frames
- * should not be discarded.
- * ...
- * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST);
- * (transfer all pending Rx frames)
- * SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST);
- * ...
- *
- * 2) An event was issued which request the driver to switch
- * the 'virtual active' link to an other already active port
- * as soon as possible. The frames in the receive queue of this
- * port may be lost. But the PHY must not be reset during this
- * event.
- * ...
- * SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST);
- * ...
- *
- * Extended Description:
- * If SK_STOP_TX is set,
- * o disable the MAC's receive and transmitter to prevent
- * from sending incomplete frames
- * o stop the port's transmit queues before terminating the
- * BMUs to prevent from performing incomplete PCI cycles
- * on the PCI bus
- * - The network Rx and Tx activity and PCI Tx transfer is
- * disabled now.
- * o reset the MAC depending on the RstMode
- * o Stop Interval Timer and Limit Counter of Tx Arbiter,
- * also disable Force Sync bit and Enable Alloc bit.
- * o perform a local reset of the port's Tx path
- * - reset the PCI FIFO of the async Tx queue
- * - reset the PCI FIFO of the sync Tx queue
- * - reset the RAM Buffer async Tx queue
- * - reset the RAM Buffer sync Tx queue
- * - reset the MAC Tx FIFO
- * o switch Link and Tx LED off, stop the LED counters
- *
- * If SK_STOP_RX is set,
- * o stop the port's receive queue
- * - The path data transfer activity is fully stopped now.
- * o perform a local reset of the port's Rx path
- * - reset the PCI FIFO of the Rx queue
- * - reset the RAM Buffer receive queue
- * - reset the MAC Rx FIFO
- * o switch Rx LED off, stop the LED counter
- *
- * If all ports are stopped,
- * o reset the RAM Interface.
- *
- * Notes:
- * o This function may be called during the driver states RESET_PORT and
- * SWITCH_PORT.
- */
-void SkGeStopPort(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* I/O context */
-int Port, /* port to stop (MAC_1 + n) */
-int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
-int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
-{
-#ifndef SK_DIAG
- SK_EVPARA Para;
-#endif /* !SK_DIAG */
- SK_GEPORT *pPrt;
- SK_U32 DWord;
- SK_U32 XsCsr;
- SK_U32 XaCsr;
- SK_U64 ToutStart;
- int i;
- int ToutCnt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if ((Dir & SK_STOP_TX) != 0) {
- /* disable receiver and transmitter */
- SkMacRxTxDisable(pAC, IoC, Port);
-
- /* stop both transmit queues */
- /*
- * If the BMU is in the reset state CSR_STOP will terminate
- * immediately.
- */
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP);
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP);
-
- ToutStart = SkOsGetTime(pAC);
- ToutCnt = 0;
- do {
- /*
- * Clear packet arbiter timeout to make sure
- * this loop will terminate.
- */
- SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
- PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
-
- /*
- * If the transfer stucks at the MAC the STOP command will not
- * terminate if we don't flush the XMAC's transmit FIFO !
- */
- SkMacFlushTxFifo(pAC, IoC, Port);
-
- XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
- XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
-
- if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
- /*
- * Timeout of 1/18 second reached.
- * This needs to be checked at 1/18 sec only.
- */
- ToutCnt++;
- if (ToutCnt > 1) {
- /* Might be a problem when the driver event handler
- * calls StopPort again. XXX.
- */
-
- /* Fatal Error, Loop aborted */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018,
- SKERR_HWI_E018MSG);
-#ifndef SK_DIAG
- Para.Para64 = Port;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-#endif /* !SK_DIAG */
- return;
- }
- /*
- * Cache incoherency workaround: Assume a start command
- * has been lost while sending the frame.
- */
- ToutStart = SkOsGetTime(pAC);
-
- if ((XsCsr & CSR_STOP) != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START);
- }
- if ((XaCsr & CSR_STOP) != 0) {
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START);
- }
- }
-
- /*
- * Because of the ASIC problem report entry from 21.08.1998 it is
- * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
- */
- } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE ||
- (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
- /* Reset the MAC depending on the RstMode */
- if (RstMode == SK_SOFT_RST) {
- SkMacSoftRst(pAC, IoC, Port);
- }
- else {
- SkMacHardRst(pAC, IoC, Port);
- }
-
- /* Disable Force Sync bit and Enable Alloc bit */
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
- TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
-
- /* Stop Interval Timer and Limit Counter of Tx Arbiter */
- SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
- SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
-
- /* Perform a local reset of the port's Tx path */
-
- /* Reset the PCI FIFO of the async Tx queue */
- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
- /* Reset the PCI FIFO of the sync Tx queue */
- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
- /* Reset the RAM Buffer async Tx queue */
- SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
- /* Reset the RAM Buffer sync Tx queue */
- SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
-
- /* Reset Tx MAC FIFO */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* Note: MFF_RST_SET does NOT reset the XMAC ! */
- SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET);
-
- /* switch Link and Tx LED off, stop the LED counters */
- /* Link LED is switched off by the RLMT and the Diag itself */
- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* Reset TX MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
- }
-#endif /* YUKON */
- }
-
- if ((Dir & SK_STOP_RX) != 0) {
- /*
- * The RX Stop Command will not terminate if no buffers
- * are queued in the RxD ring. But it will always reach
- * the Idle state. Therefore we can use this feature to
- * stop the transfer of received packets.
- */
- /* stop the port's receive queue */
- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP);
-
- i = 100;
- do {
- /*
- * Clear packet arbiter timeout to make sure
- * this loop will terminate
- */
- SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
- PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
-
- DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff);
-
- /* timeout if i==0 (bug fix for #10748) */
- if (--i == 0) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
- SKERR_HWI_E024MSG);
- break;
- }
- /*
- * because of the ASIC problem report entry from 21.08.98
- * it is required to wait until CSR_STOP is reset and
- * CSR_SV_IDLE is set.
- */
- } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
-
- /* The path data transfer activity is fully stopped now */
-
- /* Perform a local reset of the port's Rx path */
-
- /* Reset the PCI FIFO of the Rx queue */
- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
- /* Reset the RAM Buffer receive queue */
- SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
-
- /* Reset Rx MAC FIFO */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
-
- /* switch Rx LED off, stop the LED counter */
- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* Reset Rx MAC FIFO */
- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
- }
-#endif /* YUKON */
- }
-} /* SkGeStopPort */
-
-
-/******************************************************************************
- *
- * SkGeInit0() - Level 0 Initialization
- *
- * Description:
- * - Initialize the BMU address offsets
- *
- * Returns:
- * nothing
- */
-static void SkGeInit0(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- int i;
- SK_GEPORT *pPrt;
-
- for (i = 0; i < SK_MAX_MACS; i++) {
- pPrt = &pAC->GIni.GP[i];
-
- pPrt->PState = SK_PRT_RESET;
- pPrt->PRxQOff = QOffTab[i].RxQOff;
- pPrt->PXsQOff = QOffTab[i].XsQOff;
- pPrt->PXaQOff = QOffTab[i].XaQOff;
- pPrt->PCheckPar = SK_FALSE;
- pPrt->PIsave = 0;
- pPrt->PPrevShorts = 0;
- pPrt->PLinkResCt = 0;
- pPrt->PAutoNegTOCt = 0;
- pPrt->PPrevRx = 0;
- pPrt->PPrevFcs = 0;
- pPrt->PRxLim = SK_DEF_RX_WA_LIM;
- pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
- pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS;
- pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS;
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN;
- pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE;
- pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
- pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL |
- SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL);
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
- pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM;
- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
- pPrt->PMSCap = 0;
- pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO;
- pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET;
- pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
- pPrt->PAutoNegFail = SK_FALSE;
- pPrt->PHWLinkUp = SK_FALSE;
- pPrt->PLinkBroken = SK_TRUE; /* See WA code */
- pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
- pPrt->PMacColThres = TX_COL_DEF;
- pPrt->PMacJamLen = TX_JAM_LEN_DEF;
- pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF;
- pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
- pPrt->PMacIpgData = IPG_DATA_DEF;
- pPrt->PMacLimit4 = SK_FALSE;
- }
-
- pAC->GIni.GIPortUsage = SK_RED_LINK;
- pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
- pAC->GIni.GIValIrqMask = IS_ALL_MSK;
-
-} /* SkGeInit0*/
-
-
-/******************************************************************************
- *
- * SkGeInit1() - Level 1 Initialization
- *
- * Description:
- * o Do a software reset.
- * o Clear all reset bits.
- * o Verify that the detected hardware is present.
- * Return an error if not.
- * o Get the hardware configuration
- * + Read the number of MACs/Ports.
- * + Read the RAM size.
- * + Read the PCI Revision Id.
- * + Find out the adapters host clock speed
- * + Read and check the PHY type
- *
- * Returns:
- * 0: success
- * 5: Unexpected PHY type detected
- * 6: HW self test failed
- */
-static int SkGeInit1(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- SK_U8 Byte;
- SK_U16 Word;
- SK_U16 CtrlStat;
- SK_U32 DWord;
- int RetVal;
- int i;
-
- RetVal = 0;
-
- /* save CLK_RUN bits (YUKON-Lite) */
- SK_IN16(IoC, B0_CTST, &CtrlStat);
-
- /* do the SW-reset */
- SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-
- /* release the SW-reset */
- SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
-
- /* reset all error bits in the PCI STATUS register */
- /*
- * Note: PCI Cfg cycles cannot be used, because they are not
- * available on some platforms after 'boot time'.
- */
- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
- /* release Master Reset */
- SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
-
-#ifdef CLK_RUN
- CtrlStat |= CS_CLK_RUN_ENA;
-#endif /* CLK_RUN */
-
- /* restore CLK_RUN bits */
- SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
- (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
-
- /* read Chip Identification Number */
- SK_IN8(IoC, B2_CHIP_ID, &Byte);
- pAC->GIni.GIChipId = Byte;
-
- /* read number of MACs */
- SK_IN8(IoC, B2_MAC_CFG, &Byte);
- pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
-
- /* get Chip Revision Number */
- pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
-
- /* get diff. PCI parameters */
- SK_IN16(IoC, B0_CTST, &CtrlStat);
-
- /* read the adapters RAM size */
- SK_IN8(IoC, B2_E_0, &Byte);
-
- pAC->GIni.GIGenesis = SK_FALSE;
- pAC->GIni.GIYukon = SK_FALSE;
- pAC->GIni.GIYukonLite = SK_FALSE;
-
-#ifdef GENESIS
- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
-
- pAC->GIni.GIGenesis = SK_TRUE;
-
- if (Byte == (SK_U8)3) {
- /* special case: 4 x 64k x 36, offset = 0x80000 */
- pAC->GIni.GIRamSize = 1024;
- pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
- }
- else {
- pAC->GIni.GIRamSize = (int)Byte * 512;
- pAC->GIni.GIRamOffs = 0;
- }
- /* all GE adapters work with 53.125 MHz host clock */
- pAC->GIni.GIHstClkFact = SK_FACT_53;
-
- /* set Descr. Poll Timer Init Value to 250 ms */
- pAC->GIni.GIPollTimerVal =
- SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
-
- pAC->GIni.GIYukon = SK_TRUE;
-
- pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
-
- pAC->GIni.GIRamOffs = 0;
-
- /* WA for chip Rev. A */
- pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
- pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
-
- /* get PM Capabilities of PCI config space */
- SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word);
-
- /* check if VAUX is available */
- if (((CtrlStat & CS_VAUX_AVAIL) != 0) &&
- /* check also if PME from D3cold is set */
- ((Word & PCI_PME_D3C_SUP) != 0)) {
- /* set entry in GE init struct */
- pAC->GIni.GIVauxAvail = SK_TRUE;
- }
-
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
- /* this is Rev. A1 */
- pAC->GIni.GIYukonLite = SK_TRUE;
- }
- else {
- /* save Flash-Address Register */
- SK_IN32(IoC, B2_FAR, &DWord);
-
- /* test Flash-Address Register */
- SK_OUT8(IoC, B2_FAR + 3, 0xff);
- SK_IN8(IoC, B2_FAR + 3, &Byte);
-
- if (Byte != 0) {
- /* this is Rev. A0 */
- pAC->GIni.GIYukonLite = SK_TRUE;
-
- /* restore Flash-Address Register */
- SK_OUT32(IoC, B2_FAR, DWord);
- }
- }
-
- /* switch power to VCC (WA for VAUX problem) */
- SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
- PC_VAUX_OFF | PC_VCC_ON));
-
- /* read the Interrupt source */
- SK_IN32(IoC, B0_ISRC, &DWord);
-
- if ((DWord & IS_HW_ERR) != 0) {
- /* read the HW Error Interrupt source */
- SK_IN32(IoC, B0_HWE_ISRC, &DWord);
-
- if ((DWord & IS_IRQ_SENSOR) != 0) {
- /* disable HW Error IRQ */
- pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
- }
- }
-
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- /* set GMAC Link Control reset */
- SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET);
-
- /* clear GMAC Link Control reset */
- SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
- }
- /* all YU chips work with 78.125 MHz host clock */
- pAC->GIni.GIHstClkFact = SK_FACT_78;
-
- pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */
- }
-#endif /* YUKON */
-
- /* check if 64-bit PCI Slot is present */
- pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
-
- /* check if 66 MHz PCI Clock is active */
- pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
-
- /* read PCI HW Revision Id. */
- SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte);
- pAC->GIni.GIPciHwRev = Byte;
-
- /* read the PMD type */
- SK_IN8(IoC, B2_PMD_TYP, &Byte);
- pAC->GIni.GICopperType = (SK_U8)(Byte == 'T');
-
- /* read the PHY type */
- SK_IN8(IoC, B2_E_1, &Byte);
-
- Byte &= 0x0f; /* the PHY type is stored in the lower nibble */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- switch (Byte) {
- case SK_PHY_XMAC:
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC;
- break;
- case SK_PHY_BCOM:
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM;
- pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
- SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE;
- break;
- case SK_PHY_NAT:
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT;
- break;
-#endif /* OTHER_PHY */
- default:
- /* ERROR: unexpected PHY type detected */
- RetVal = 5;
- break;
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- if (Byte < (SK_U8)SK_PHY_MARV_COPPER) {
- /* if this field is not initialized */
- Byte = (SK_U8)SK_PHY_MARV_COPPER;
-
- pAC->GIni.GICopperType = SK_TRUE;
- }
-
- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV;
-
- if (pAC->GIni.GICopperType) {
-
- pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO |
- SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS |
- SK_LSPEED_CAP_1000MBPS);
-
- pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
-
- pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
- SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
- }
- else {
- Byte = (SK_U8)SK_PHY_MARV_FIBER;
- }
- }
-#endif /* YUKON */
-
- pAC->GIni.GP[i].PhyType = (int)Byte;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
- ("PHY type: %d PHY addr: %04x\n", Byte,
- pAC->GIni.GP[i].PhyAddr));
- }
-
- /* get MAC Type & set function pointers dependent on */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- pAC->GIni.GIMacType = SK_MAC_XMAC;
-
- pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats;
- pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic;
- pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter;
- pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus;
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- pAC->GIni.GIMacType = SK_MAC_GMAC;
-
- pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats;
- pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic;
- pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter;
- pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus;
-
-#ifdef SPECIAL_HANDLING
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
- /* check HW self test result */
- SK_IN8(IoC, B2_E_3, &Byte);
- if (Byte & B2_E3_RES_MASK) {
- RetVal = 6;
- }
- }
-#endif
- }
-#endif /* YUKON */
-
- return(RetVal);
-} /* SkGeInit1 */
-
-
-/******************************************************************************
- *
- * SkGeInit2() - Level 2 Initialization
- *
- * Description:
- * - start the Blink Source Counter
- * - start the Descriptor Poll Timer
- * - configure the MAC-Arbiter
- * - configure the Packet-Arbiter
- * - enable the Tx Arbiters
- * - enable the RAM Interface Arbiter
- *
- * Returns:
- * nothing
- */
-static void SkGeInit2(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
-#ifdef GENESIS
- SK_U32 DWord;
-#endif /* GENESIS */
- int i;
-
- /* start the Descriptor Poll Timer */
- if (pAC->GIni.GIPollTimerVal != 0) {
- if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) {
- pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX;
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG);
- }
- SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal);
- SK_OUT8(IoC, B28_DPT_CTRL, DPT_START);
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* start the Blink Source Counter */
- DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100;
-
- SK_OUT32(IoC, B2_BSC_INI, DWord);
- SK_OUT8(IoC, B2_BSC_CTRL, BSC_START);
-
- /*
- * Configure the MAC Arbiter and the Packet Arbiter.
- * They will be started once and never be stopped.
- */
- SkGeInitMacArb(pAC, IoC);
-
- SkGeInitPktArb(pAC, IoC);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* start Time Stamp Timer */
- SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
- }
-#endif /* YUKON */
-
- /* enable the Tx Arbiters */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB);
- }
-
- /* enable the RAM Interface Arbiter */
- SkGeInitRamIface(pAC, IoC);
-
-} /* SkGeInit2 */
-
-/******************************************************************************
- *
- * SkGeInit() - Initialize the GE Adapter with the specified level.
- *
- * Description:
- * Level 0: Initialize the Module structures.
- * Level 1: Generic Hardware Initialization. The IOP/MemBase pointer has
- * to be set before calling this level.
- *
- * o Do a software reset.
- * o Clear all reset bits.
- * o Verify that the detected hardware is present.
- * Return an error if not.
- * o Get the hardware configuration
- * + Set GIMacsFound with the number of MACs.
- * + Store the RAM size in GIRamSize.
- * + Save the PCI Revision ID in GIPciHwRev.
- * o return an error
- * if Number of MACs > SK_MAX_MACS
- *
- * After returning from Level 0 the adapter
- * may be accessed with IO operations.
- *
- * Level 2: start the Blink Source Counter
- *
- * Returns:
- * 0: success
- * 1: Number of MACs exceeds SK_MAX_MACS (after level 1)
- * 2: Adapter not present or not accessible
- * 3: Illegal initialization level
- * 4: Initialization Level 1 Call missing
- * 5: Unexpected PHY type detected
- * 6: HW self test failed
- */
-int SkGeInit(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Level) /* initialization level */
-{
- int RetVal; /* return value */
- SK_U32 DWord;
-
- RetVal = 0;
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
- ("SkGeInit(Level %d)\n", Level));
-
- switch (Level) {
- case SK_INIT_DATA:
- /* Initialization Level 0 */
- SkGeInit0(pAC, IoC);
- pAC->GIni.GILevel = SK_INIT_DATA;
- break;
-
- case SK_INIT_IO:
- /* Initialization Level 1 */
- RetVal = SkGeInit1(pAC, IoC);
- if (RetVal != 0) {
- break;
- }
-
- /* check if the adapter seems to be accessible */
- SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
- SK_IN32(IoC, B2_IRQM_INI, &DWord);
- SK_OUT32(IoC, B2_IRQM_INI, 0L);
-
- if (DWord != SK_TEST_VAL) {
- RetVal = 2;
- break;
- }
-
- /* check if the number of GIMacsFound matches SK_MAX_MACS */
- if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
- RetVal = 1;
- break;
- }
-
- /* Level 1 successfully passed */
- pAC->GIni.GILevel = SK_INIT_IO;
- break;
-
- case SK_INIT_RUN:
- /* Initialization Level 2 */
- if (pAC->GIni.GILevel != SK_INIT_IO) {
-#ifndef SK_DIAG
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG);
-#endif /* !SK_DIAG */
- RetVal = 4;
- break;
- }
- SkGeInit2(pAC, IoC);
-
- /* Level 2 successfully passed */
- pAC->GIni.GILevel = SK_INIT_RUN;
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
- RetVal = 3;
- break;
- }
-
- return(RetVal);
-} /* SkGeInit */
-
-
-/******************************************************************************
- *
- * SkGeDeInit() - Deinitialize the adapter
- *
- * Description:
- * All ports of the adapter will be stopped if not already done.
- * Do a software reset and switch off all LEDs.
- *
- * Returns:
- * nothing
- */
-void SkGeDeInit(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC) /* IO context */
-{
- int i;
- SK_U16 Word;
-
-#if (!defined(SK_SLIM) && !defined(VCPU))
- /* ensure I2C is ready */
- SkI2cWaitIrq(pAC, IoC);
-#endif
-
- /* stop all current transfer activity */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
- if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
- pAC->GIni.GP[i].PState != SK_PRT_RESET) {
-
- SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
- }
- }
-
- /* Reset all bits in the PCI STATUS register */
- /*
- * Note: PCI Cfg cycles cannot be used, because they are not
- * available on some platforms after 'boot time'.
- */
- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
- /* do the reset, all LEDs are switched off now */
- SK_OUT8(IoC, B0_CTST, CS_RST_SET);
-
- pAC->GIni.GILevel = SK_INIT_DATA;
-} /* SkGeDeInit */
-
-
-/******************************************************************************
- *
- * SkGeInitPort() Initialize the specified port.
- *
- * Description:
- * PRxQSize, PXSQSize, and PXAQSize has to be
- * configured for the specified port before calling this function.
- * The descriptor rings has to be initialized too.
- *
- * o (Re)configure queues of the specified port.
- * o configure the MAC of the specified port.
- * o put ASIC and MAC(s) in operational mode.
- * o initialize Rx/Tx and Sync LED
- * o initialize RAM Buffers and MAC FIFOs
- *
- * The port is ready to connect when returning.
- *
- * Note:
- * The MAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- * 0: success
- * 1: Queue size initialization error. The configured values
- * for PRxQSize, PXSQSize, or PXAQSize are invalid for one
- * or more queues. The specified port was NOT initialized.
- * An error log entry was generated.
- * 2: The port has to be stopped before it can be initialized again.
- */
-int SkGeInitPort(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port to configure */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (SkGeCheckQSize(pAC, Port) != 0) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
- return(1);
- }
-
- if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
- return(2);
- }
-
- /* configuration ok, initialize the Port now */
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* initialize Rx, Tx and Link LED */
- /*
- * If 1000BT Phy needs LED initialization than swap
- * LED and XMAC initialization order
- */
- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
- SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
- /* The Link LED is initialized by RLMT or Diagnostics itself */
-
- SkXmInitMac(pAC, IoC, Port);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- SkGmInitMac(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
- /* do NOT initialize the Link Sync Counter */
-
- SkGeInitMacFifo(pAC, IoC, Port);
-
- SkGeInitRamBufs(pAC, IoC, Port);
-
- if (pPrt->PXSQSize != 0) {
- /* enable Force Sync bit if synchronous queue available */
- SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
- }
-
- SkGeInitBmu(pAC, IoC, Port);
-
- /* mark port as initialized */
- pPrt->PState = SK_PRT_INIT;
-
- return(0);
-} /* SkGeInitPort */
diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c
deleted file mode 100644
index 0a6f67a7a39..00000000000
--- a/drivers/net/sk98lin/skgemib.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*****************************************************************************
- *
- * Name: skgemib.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.11 $
- * Date: $Date: 2003/09/15 13:38:12 $
- * Purpose: Private Network Management Interface Management Database
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * PRIVATE OID handler function prototypes
- */
-PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action,
- SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
- SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int* pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-
-#ifdef SK_POWER_MGMT
-PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance,
- unsigned int TableIndex, SK_U32 NetIndex);
-#endif /* SK_DIAG_SUPPORT */
-
-
-/* defines *******************************************************************/
-#define ID_TABLE_SIZE (sizeof(IdTable)/sizeof(IdTable[0]))
-
-
-/* global variables **********************************************************/
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = {
- {OID_GEN_XMIT_OK,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
- {OID_GEN_RCV_OK,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
- {OID_GEN_XMIT_ERROR,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_GEN_RCV_ERROR,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_GEN_RCV_NO_BUFFER,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_GEN_DIRECTED_FRAMES_XMIT,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
- {OID_GEN_MULTICAST_FRAMES_XMIT,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
- {OID_GEN_BROADCAST_FRAMES_XMIT,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
- {OID_GEN_DIRECTED_FRAMES_RCV,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
- {OID_GEN_MULTICAST_FRAMES_RCV,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
- {OID_GEN_BROADCAST_FRAMES_RCV,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
- {OID_GEN_RCV_CRC_ERROR,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
- {OID_GEN_TRANSMIT_QUEUE_LENGTH,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_802_3_PERMANENT_ADDRESS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, 0},
- {OID_802_3_CURRENT_ADDRESS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, 0},
- {OID_802_3_RCV_ERROR_ALIGNMENT,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
- {OID_802_3_XMIT_ONE_COLLISION,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
- {OID_802_3_XMIT_MORE_COLLISIONS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
- {OID_802_3_XMIT_DEFERRED,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
- {OID_802_3_XMIT_MAX_COLLISIONS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
- {OID_802_3_RCV_OVERRUN,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
- {OID_802_3_XMIT_UNDERRUN,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
- {OID_802_3_XMIT_TIMES_CRS_LOST,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
- {OID_802_3_XMIT_LATE_COLLISIONS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
-#ifdef SK_POWER_MGMT
- {OID_PNP_CAPABILITIES,
- 0,
- 0,
- 0,
- SK_PNMI_RO, PowerManagement, 0},
- {OID_PNP_SET_POWER,
- 0,
- 0,
- 0,
- SK_PNMI_WO, PowerManagement, 0},
- {OID_PNP_QUERY_POWER,
- 0,
- 0,
- 0,
- SK_PNMI_RO, PowerManagement, 0},
- {OID_PNP_ADD_WAKE_UP_PATTERN,
- 0,
- 0,
- 0,
- SK_PNMI_WO, PowerManagement, 0},
- {OID_PNP_REMOVE_WAKE_UP_PATTERN,
- 0,
- 0,
- 0,
- SK_PNMI_WO, PowerManagement, 0},
- {OID_PNP_ENABLE_WAKE_UP,
- 0,
- 0,
- 0,
- SK_PNMI_RW, PowerManagement, 0},
-#endif /* SK_POWER_MGMT */
-#ifdef SK_DIAG_SUPPORT
- {OID_SKGE_DIAG_MODE,
- 0,
- 0,
- 0,
- SK_PNMI_RW, DiagActions, 0},
-#endif /* SK_DIAG_SUPPORT */
- {OID_SKGE_MDB_VERSION,
- 1,
- 0,
- SK_PNMI_MAI_OFF(MgmtDBVersion),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_SUPPORTED_LIST,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
- {OID_SKGE_ALL_DATA,
- 0,
- 0,
- 0,
- SK_PNMI_RW, OidStruct, 0},
- {OID_SKGE_VPD_FREE_BYTES,
- 1,
- 0,
- SK_PNMI_MAI_OFF(VpdFreeBytes),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_ENTRIES_LIST,
- 1,
- 0,
- SK_PNMI_MAI_OFF(VpdEntriesList),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_ENTRIES_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(VpdEntriesNumber),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_KEY,
- SK_PNMI_VPD_ENTRIES,
- sizeof(SK_PNMI_VPD),
- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_VALUE,
- SK_PNMI_VPD_ENTRIES,
- sizeof(SK_PNMI_VPD),
- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_ACCESS,
- SK_PNMI_VPD_ENTRIES,
- sizeof(SK_PNMI_VPD),
- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
- SK_PNMI_RO, Vpd, 0},
- {OID_SKGE_VPD_ACTION,
- SK_PNMI_VPD_ENTRIES,
- sizeof(SK_PNMI_VPD),
- SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
- SK_PNMI_RW, Vpd, 0},
- {OID_SKGE_PORT_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(PortNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DEVICE_TYPE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DeviceType),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DRIVER_DESCR,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DriverDescr),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DRIVER_VERSION,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DriverVersion),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DRIVER_RELDATE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DriverReleaseDate),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_DRIVER_FILENAME,
- 1,
- 0,
- SK_PNMI_MAI_OFF(DriverFileName),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_HW_DESCR,
- 1,
- 0,
- SK_PNMI_MAI_OFF(HwDescr),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_HW_VERSION,
- 1,
- 0,
- SK_PNMI_MAI_OFF(HwVersion),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_CHIPSET,
- 1,
- 0,
- SK_PNMI_MAI_OFF(Chipset),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_CHIPID,
- 1,
- 0,
- SK_PNMI_MAI_OFF(ChipId),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RAMSIZE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RamSize),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_VAUXAVAIL,
- 1,
- 0,
- SK_PNMI_MAI_OFF(VauxAvail),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_ACTION,
- 1,
- 0,
- SK_PNMI_MAI_OFF(Action),
- SK_PNMI_RW, Perform, 0},
- {OID_SKGE_RESULT,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TestResult),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_BUS_TYPE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(BusType),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_BUS_SPEED,
- 1,
- 0,
- SK_PNMI_MAI_OFF(BusSpeed),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_BUS_WIDTH,
- 1,
- 0,
- SK_PNMI_MAI_OFF(BusWidth),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_SW_QUEUE_LEN,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxSwQueueLen),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_SW_QUEUE_MAX,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxSwQueueMax),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_RETRY,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxRetryCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_INTR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxIntrCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_INTR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxIntrCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_NO_BUF_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxNoBufCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_NO_BUF_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxNoBufCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_USED_DESCR_NO,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxUsedDescrNo),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_DELIVERED_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxDeliveredCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_OCTETS_DELIV_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RX_HW_ERROR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RxHwErrorsCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TX_HW_ERROR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TxHwErrorsCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_IN_ERRORS_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(InErrorsCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_OUT_ERROR_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(OutErrorsCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_ERR_RECOVERY_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(ErrRecoveryCts),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_SYSUPTIME,
- 1,
- 0,
- SK_PNMI_MAI_OFF(SysUpTime),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_SENSOR_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(SensorNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_SENSOR_INDEX,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_DESCR,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_TYPE,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_VALUE,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_WAR_THRES_LOW,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_WAR_THRES_UPP,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_ERR_THRES_LOW,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_ERR_THRES_UPP,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_STATUS,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_WAR_CTS,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_ERR_CTS,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_WAR_TIME,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_SENSOR_ERR_TIME,
- SK_PNMI_SENSOR_ENTRIES,
- sizeof(SK_PNMI_SENSOR),
- SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
- SK_PNMI_RO, SensorStat, 0},
- {OID_SKGE_CHKSM_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(ChecksumNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_CHKSM_RX_OK_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_CHKSM_RX_UNABLE_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_CHKSM_RX_ERR_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_CHKSM_TX_OK_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_CHKSM_TX_UNABLE_CTS,
- SKCS_NUM_PROTOCOLS,
- sizeof(SK_PNMI_CHECKSUM),
- SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
- SK_PNMI_RO, CsumStat, 0},
- {OID_SKGE_STAT_TX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
- {OID_SKGE_STAT_TX_OCTETS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
- {OID_SKGE_STAT_TX_BROADCAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
- {OID_SKGE_STAT_TX_MULTICAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
- {OID_SKGE_STAT_TX_UNICAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
- {OID_SKGE_STAT_TX_LONGFRAMES,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
- {OID_SKGE_STAT_TX_BURST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
- {OID_SKGE_STAT_TX_PFLOWC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
- {OID_SKGE_STAT_TX_FLOWC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
- {OID_SKGE_STAT_TX_SINGLE_COL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
- {OID_SKGE_STAT_TX_MULTI_COL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
- {OID_SKGE_STAT_TX_EXCESS_COL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
- {OID_SKGE_STAT_TX_LATE_COL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
- {OID_SKGE_STAT_TX_DEFFERAL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
- {OID_SKGE_STAT_TX_EXCESS_DEF,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
- {OID_SKGE_STAT_TX_UNDERRUN,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
- {OID_SKGE_STAT_TX_CARRIER,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
-/* {OID_SKGE_STAT_TX_UTIL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
- SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
- {OID_SKGE_STAT_TX_64,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
- {OID_SKGE_STAT_TX_127,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
- {OID_SKGE_STAT_TX_255,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
- {OID_SKGE_STAT_TX_511,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
- {OID_SKGE_STAT_TX_1023,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
- {OID_SKGE_STAT_TX_MAX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
- {OID_SKGE_STAT_TX_SYNC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
- {OID_SKGE_STAT_TX_SYNC_OCTETS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
- {OID_SKGE_STAT_RX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
- {OID_SKGE_STAT_RX_OCTETS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
- {OID_SKGE_STAT_RX_BROADCAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
- {OID_SKGE_STAT_RX_MULTICAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
- {OID_SKGE_STAT_RX_UNICAST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
- {OID_SKGE_STAT_RX_LONGFRAMES,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
- {OID_SKGE_STAT_RX_PFLOWC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
- {OID_SKGE_STAT_RX_FLOWC,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
- {OID_SKGE_STAT_RX_PFLOWC_ERR,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
- {OID_SKGE_STAT_RX_FLOWC_UNKWN,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
- {OID_SKGE_STAT_RX_BURST,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
- {OID_SKGE_STAT_RX_MISSED,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
- {OID_SKGE_STAT_RX_FRAMING,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
- {OID_SKGE_STAT_RX_OVERFLOW,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
- {OID_SKGE_STAT_RX_JABBER,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
- {OID_SKGE_STAT_RX_CARRIER,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
- {OID_SKGE_STAT_RX_IR_LENGTH,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
- {OID_SKGE_STAT_RX_SYMBOL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
- {OID_SKGE_STAT_RX_SHORTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
- {OID_SKGE_STAT_RX_RUNT,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
- {OID_SKGE_STAT_RX_CEXT,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
- {OID_SKGE_STAT_RX_TOO_LONG,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
- {OID_SKGE_STAT_RX_FCS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
-/* {OID_SKGE_STAT_RX_UTIL,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
- SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
- {OID_SKGE_STAT_RX_64,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
- {OID_SKGE_STAT_RX_127,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
- {OID_SKGE_STAT_RX_255,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
- {OID_SKGE_STAT_RX_511,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
- {OID_SKGE_STAT_RX_1023,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
- {OID_SKGE_STAT_RX_MAX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_STAT),
- SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
- SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
- {OID_SKGE_PHYS_CUR_ADDR,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
- SK_PNMI_RW, Addr, 0},
- {OID_SKGE_PHYS_FAC_ADDR,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
- SK_PNMI_RO, Addr, 0},
- {OID_SKGE_PMD,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_CONNECTOR,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_PHY_TYPE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_LINK_CAP,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_LINK_MODE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_LINK_MODE_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_LINK_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_FLOWCTRL_CAP,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_FLOWCTRL_MODE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_FLOWCTRL_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_PHY_OPERATION_CAP,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_PHY_OPERATION_MODE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_PHY_OPERATION_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_SPEED_CAP,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_SPEED_MODE,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_SPEED_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_CONF),
- SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus),
- SK_PNMI_RO, MacPrivateConf, 0},
- {OID_SKGE_TRAP,
- 1,
- 0,
- SK_PNMI_MAI_OFF(Trap),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_TRAP_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(TrapNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RLMT_MODE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtMode),
- SK_PNMI_RW, Rlmt, 0},
- {OID_SKGE_RLMT_PORT_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtPortNumber),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_PORT_ACTIVE,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtPortActive),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_PORT_PREFERRED,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtPortPreferred),
- SK_PNMI_RW, Rlmt, 0},
- {OID_SKGE_RLMT_CHANGE_CTS,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtChangeCts),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_CHANGE_TIME,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtChangeTime),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_CHANGE_ESTIM,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtChangeEstimate),
- SK_PNMI_RO, Rlmt, 0},
- {OID_SKGE_RLMT_CHANGE_THRES,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtChangeThreshold),
- SK_PNMI_RW, Rlmt, 0},
- {OID_SKGE_RLMT_PORT_INDEX,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_STATUS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_TX_HELLO_CTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_RX_HELLO_CTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_TX_SP_REQ_CTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_RX_SP_CTS,
- SK_PNMI_MAC_ENTRIES,
- sizeof(SK_PNMI_RLMT),
- SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
- SK_PNMI_RO, RlmtStat, 0},
- {OID_SKGE_RLMT_MONITOR_NUMBER,
- 1,
- 0,
- SK_PNMI_MAI_OFF(RlmtMonitorNumber),
- SK_PNMI_RO, General, 0},
- {OID_SKGE_RLMT_MONITOR_INDEX,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
- SK_PNMI_RO, Monitor, 0},
- {OID_SKGE_RLMT_MONITOR_ADDR,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
- SK_PNMI_RO, Monitor, 0},
- {OID_SKGE_RLMT_MONITOR_ERRS,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
- SK_PNMI_RO, Monitor, 0},
- {OID_SKGE_RLMT_MONITOR_TIMESTAMP,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
- SK_PNMI_RO, Monitor, 0},
- {OID_SKGE_RLMT_MONITOR_ADMIN,
- SK_PNMI_MONITOR_ENTRIES,
- sizeof(SK_PNMI_RLMT_MONITOR),
- SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
- SK_PNMI_RW, Monitor, 0},
- {OID_SKGE_MTU,
- 1,
- 0,
- SK_PNMI_MAI_OFF(MtuSize),
- SK_PNMI_RW, MacPrivateConf, 0},
- {OID_SKGE_VCT_GET,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Vct, 0},
- {OID_SKGE_VCT_SET,
- 0,
- 0,
- 0,
- SK_PNMI_WO, Vct, 0},
- {OID_SKGE_VCT_STATUS,
- 0,
- 0,
- 0,
- SK_PNMI_RO, Vct, 0},
- {OID_SKGE_BOARDLEVEL,
- 0,
- 0,
- 0,
- SK_PNMI_RO, General, 0},
-};
-
diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c
deleted file mode 100644
index b36dd9ac6b2..00000000000
--- a/drivers/net/sk98lin/skgepnmi.c
+++ /dev/null
@@ -1,8210 +0,0 @@
-/*****************************************************************************
- *
- * Name: skgepnmi.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.111 $
- * Date: $Date: 2003/09/15 13:35:35 $
- * Purpose: Private Network Management Interface
- *
- ****************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-#ifndef _lint
-static const char SysKonnectFileId[] =
- "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
-#endif /* !_lint */
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/xmac_ii.h"
-#include "h/skdebug.h"
-#include "h/skqueue.h"
-#include "h/skgepnmi.h"
-#include "h/skgesirq.h"
-#include "h/skcsum.h"
-#include "h/skvpd.h"
-#include "h/skgehw.h"
-#include "h/skgeinit.h"
-#include "h/skdrv2nd.h"
-#include "h/skgepnm2.h"
-#ifdef SK_POWER_MGMT
-#include "h/skgepmgt.h"
-#endif
-/* defines *******************************************************************/
-
-#ifndef DEBUG
-#define PNMI_STATIC static
-#else /* DEBUG */
-#define PNMI_STATIC
-#endif /* DEBUG */
-
-/*
- * Public Function prototypes
- */
-int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
-int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
- unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
-int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
- unsigned int * pLen, SK_U32 NetIndex);
-
-
-/*
- * Private Function prototypes
- */
-
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
- PhysPortIndex);
-PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
- PhysPortIndex);
-PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
-PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
-PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
- unsigned int PhysPortIndex, unsigned int StatIndex);
-PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
- unsigned int StatIndex, SK_U32 NetIndex);
-PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
-PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
- unsigned int *pEntries);
-PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
- unsigned int KeyArrLen, unsigned int *pKeyNo);
-PNMI_STATIC int LookupId(SK_U32 Id);
-PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
- unsigned int LastMac);
-PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
- unsigned int *pLen, SK_U32 NetIndex);
-PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
- char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
-PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
-PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
- unsigned int PortIndex);
-PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
- unsigned int SensorIndex);
-PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
-PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
-PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
-PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
-PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
- unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
-PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
-
-/*
- * Table to correlate OID with handler function and index to
- * hardware register stored in StatAddress if applicable.
- */
-#include "skgemib.c"
-
-/* global variables **********************************************************/
-
-/*
- * Overflow status register bit table and corresponding counter
- * dependent on MAC type - the number relates to the size of overflow
- * mask returned by the pFnMacOverflow function
- */
-PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
-/* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST},
-/* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST},
-/* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC},
-/* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST},
-/* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW},
-/* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH},
-/* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64},
-/* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127},
-/* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255},
-/* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511},
-/* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023},
-/* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX},
-/* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES},
-/* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED},
-/* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL},
-/* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL},
-/* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL},
-/* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL},
-/* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL},
-/* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN},
-/* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED},
-/* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED},
-/* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED},
-/* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED},
-/* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED},
-/* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED},
-/* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
-/* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST},
-/* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST},
-/* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC},
-/* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST},
-/* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS},
-/* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED},
-/* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW},
-/* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH},
-/* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW},
-/* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH},
-/* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE},
-/* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT},
-/* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64},
-/* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127},
-/* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255},
-/* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511},
-/* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023},
-/* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX},
-/* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES},
-/* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG},
-/* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER},
-/* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED},
-/* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW},
-/* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED},
-/* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED},
-/* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED},
-/* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED},
-/* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED},
-/* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED},
-/* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED},
-/* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED},
-/* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED}
-};
-
-/*
- * Table for hardware register saving on resets and port switches
- */
-PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
- /* SK_PNMI_HTX */
- {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_OCTETHIGH */
- {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
- /* SK_PNMI_HTX_OCTETLOW */
- {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
- /* SK_PNMI_HTX_BROADCAST */
- {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
- /* SK_PNMI_HTX_MULTICAST */
- {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
- /* SK_PNMI_HTX_UNICAST */
- {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
- /* SK_PNMI_HTX_BURST */
- {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_PMACC */
- {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
- /* SK_PNMI_HTX_MACC */
- {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_COL */
- {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
- /* SK_PNMI_HTX_SINGLE_COL */
- {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
- /* SK_PNMI_HTX_MULTI_COL */
- {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
- /* SK_PNMI_HTX_EXCESS_COL */
- {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
- /* SK_PNMI_HTX_LATE_COL */
- {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
- /* SK_PNMI_HTX_DEFFERAL */
- {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_EXCESS_DEF */
- {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_UNDERRUN */
- {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
- /* SK_PNMI_HTX_CARRIER */
- {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_UTILUNDER */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_UTILOVER */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_64 */
- {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
- /* SK_PNMI_HTX_127 */
- {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
- /* SK_PNMI_HTX_255 */
- {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
- /* SK_PNMI_HTX_511 */
- {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
- /* SK_PNMI_HTX_1023 */
- {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
- /* SK_PNMI_HTX_MAX */
- {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
- /* SK_PNMI_HTX_LONGFRAMES */
- {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
- /* SK_PNMI_HTX_SYNC */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_SYNC_OCTET */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HTX_RESERVED */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX */
- {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_OCTETHIGH */
- {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
- /* SK_PNMI_HRX_OCTETLOW */
- {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
- /* SK_PNMI_HRX_BADOCTETHIGH */
- {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
- /* SK_PNMI_HRX_BADOCTETLOW */
- {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
- /* SK_PNMI_HRX_BROADCAST */
- {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
- /* SK_PNMI_HRX_MULTICAST */
- {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
- /* SK_PNMI_HRX_UNICAST */
- {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
- /* SK_PNMI_HRX_PMACC */
- {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
- /* SK_PNMI_HRX_MACC */
- {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_PMACC_ERR */
- {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_MACC_UNKWN */
- {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_BURST */
- {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_MISSED */
- {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_FRAMING */
- {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_UNDERSIZE */
- {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
- /* SK_PNMI_HRX_OVERFLOW */
- {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
- /* SK_PNMI_HRX_JABBER */
- {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
- /* SK_PNMI_HRX_CARRIER */
- {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_IRLENGTH */
- {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_SYMBOL */
- {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_SHORTS */
- {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_RUNT */
- {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
- /* SK_PNMI_HRX_TOO_LONG */
- {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
- /* SK_PNMI_HRX_FCS */
- {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
- /* SK_PNMI_HRX_CEXT */
- {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_UTILUNDER */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_UTILOVER */
- {{0, SK_FALSE}, {0, SK_FALSE}},
- /* SK_PNMI_HRX_64 */
- {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
- /* SK_PNMI_HRX_127 */
- {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
- /* SK_PNMI_HRX_255 */
- {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
- /* SK_PNMI_HRX_511 */
- {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
- /* SK_PNMI_HRX_1023 */
- {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
- /* SK_PNMI_HRX_MAX */
- {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
- /* SK_PNMI_HRX_LONGFRAMES */
- {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
- /* SK_PNMI_HRX_RESERVED */
- {{0, SK_FALSE}, {0, SK_FALSE}}
-};
-
-
-/*****************************************************************************
- *
- * Public functions
- *
- */
-
-/*****************************************************************************
- *
- * SkPnmiInit - Init function of PNMI
- *
- * Description:
- * SK_INIT_DATA: Initialises the data structures
- * SK_INIT_IO: Resets the XMAC statistics, determines the device and
- * connector type.
- * SK_INIT_RUN: Starts a timer event for port switch per hour
- * calculation.
- *
- * Returns:
- * Always 0
- */
-int SkPnmiInit(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Level) /* Initialization level */
-{
- unsigned int PortMax; /* Number of ports */
- unsigned int PortIndex; /* Current port index in loop */
- SK_U16 Val16; /* Multiple purpose 16 bit variable */
- SK_U8 Val8; /* Mulitple purpose 8 bit variable */
- SK_EVPARA EventParam; /* Event struct for timer event */
- SK_PNMI_VCT *pVctBackupData;
-
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiInit: Called, level=%d\n", Level));
-
- switch (Level) {
-
- case SK_INIT_DATA:
- SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
- pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
- pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
- pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
- for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
-
- pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
- pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
- }
-
-#ifdef SK_PNMI_CHECK
- if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
- ("CounterOffset struct size (%d) differs from"
- "SK_PNMI_MAX_IDX (%d)\n",
- SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
- }
-
- if (SK_PNMI_MAX_IDX !=
- (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
- ("StatAddr table size (%d) differs from "
- "SK_PNMI_MAX_IDX (%d)\n",
- (sizeof(StatAddr) /
- (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)),
- SK_PNMI_MAX_IDX));
- }
-#endif /* SK_PNMI_CHECK */
- break;
-
- case SK_INIT_IO:
- /*
- * Reset MAC counters
- */
- PortMax = pAC->GIni.GIMacsFound;
-
- for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
-
- pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
- }
-
- /* Initialize DSP variables for Vct() to 0xff => Never written! */
- for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
- pAC->GIni.GP[PortIndex].PCableLen = 0xff;
- pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
- pVctBackupData->PCableLen = 0xff;
- }
-
- /*
- * Get pci bus speed
- */
- SK_IN16(IoC, B0_CTST, &Val16);
- if ((Val16 & CS_BUS_CLOCK) == 0) {
-
- pAC->Pnmi.PciBusSpeed = 33;
- }
- else {
- pAC->Pnmi.PciBusSpeed = 66;
- }
-
- /*
- * Get pci bus width
- */
- SK_IN16(IoC, B0_CTST, &Val16);
- if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
-
- pAC->Pnmi.PciBusWidth = 32;
- }
- else {
- pAC->Pnmi.PciBusWidth = 64;
- }
-
- /*
- * Get chipset
- */
- switch (pAC->GIni.GIChipId) {
- case CHIP_ID_GENESIS:
- pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
- break;
-
- case CHIP_ID_YUKON:
- pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
- break;
-
- default:
- break;
- }
-
- /*
- * Get PMD and DeviceType
- */
- SK_IN8(IoC, B2_PMD_TYP, &Val8);
- switch (Val8) {
- case 'S':
- pAC->Pnmi.PMD = 3;
- if (pAC->GIni.GIMacsFound > 1) {
-
- pAC->Pnmi.DeviceType = 0x00020002;
- }
- else {
- pAC->Pnmi.DeviceType = 0x00020001;
- }
- break;
-
- case 'L':
- pAC->Pnmi.PMD = 2;
- if (pAC->GIni.GIMacsFound > 1) {
-
- pAC->Pnmi.DeviceType = 0x00020004;
- }
- else {
- pAC->Pnmi.DeviceType = 0x00020003;
- }
- break;
-
- case 'C':
- pAC->Pnmi.PMD = 4;
- if (pAC->GIni.GIMacsFound > 1) {
-
- pAC->Pnmi.DeviceType = 0x00020006;
- }
- else {
- pAC->Pnmi.DeviceType = 0x00020005;
- }
- break;
-
- case 'T':
- pAC->Pnmi.PMD = 5;
- if (pAC->GIni.GIMacsFound > 1) {
-
- pAC->Pnmi.DeviceType = 0x00020008;
- }
- else {
- pAC->Pnmi.DeviceType = 0x00020007;
- }
- break;
-
- default :
- pAC->Pnmi.PMD = 1;
- pAC->Pnmi.DeviceType = 0;
- break;
- }
-
- /*
- * Get connector
- */
- SK_IN8(IoC, B2_CONN_TYP, &Val8);
- switch (Val8) {
- case 'C':
- pAC->Pnmi.Connector = 2;
- break;
-
- case 'D':
- pAC->Pnmi.Connector = 3;
- break;
-
- case 'F':
- pAC->Pnmi.Connector = 4;
- break;
-
- case 'J':
- pAC->Pnmi.Connector = 5;
- break;
-
- case 'V':
- pAC->Pnmi.Connector = 6;
- break;
-
- default:
- pAC->Pnmi.Connector = 1;
- break;
- }
- break;
-
- case SK_INIT_RUN:
- /*
- * Start timer for RLMT change counter
- */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
- 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
- EventParam);
- break;
-
- default:
- break; /* Nothing todo */
- }
-
- return (0);
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetVar - Retrieves the value of a single OID
- *
- * Description:
- * Calls a general sub-function for all this stuff. If the instance
- * -1 is passed, the values of all instances are returned in an
- * array of values.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed
- * SK_PNMI_ERR_GENERAL A general severe internal error occured
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
- * the data.
- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-static int SkPnmiGetVar(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Id, /* Object ID that is to be processed */
-void *pBuf, /* Buffer to which the management data will be copied */
-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
- Id, *pLen, Instance, NetIndex));
-
- return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
- Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetVar - Presets the value of a single OID
- *
- * Description:
- * Calls a general sub-function for all this stuff. The preset does
- * the same as a set, but returns just before finally setting the
- * new value. This is useful to check if a set might be successfull.
- * If the instance -1 is passed, an array of values is supposed and
- * all instances of the OID will be set.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-static int SkPnmiPreSetVar(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Id, /* Object ID that is to be processed */
-void *pBuf, /* Buffer to which the management data will be copied */
-unsigned int *pLen, /* Total length of management data */
-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
- Id, *pLen, Instance, NetIndex));
-
-
- return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
- Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetVar - Sets the value of a single OID
- *
- * Description:
- * Calls a general sub-function for all this stuff. The preset does
- * the same as a set, but returns just before finally setting the
- * new value. This is useful to check if a set might be successfull.
- * If the instance -1 is passed, an array of values is supposed and
- * all instances of the OID will be set.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-int SkPnmiSetVar(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Id, /* Object ID that is to be processed */
-void *pBuf, /* Buffer to which the management data will be copied */
-unsigned int *pLen, /* Total length of management data */
-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
- Id, *pLen, Instance, NetIndex));
-
- return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
- Instance, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- * Runs through the IdTable, queries the single OIDs and stores the
- * returned data into the management database structure
- * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
- * is stored in the IdTable. The return value of the function will also
- * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- * minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed
- * SK_PNMI_ERR_GENERAL A general severe internal error occured
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
- * the data.
- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
- */
-int SkPnmiGetStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-void *pBuf, /* Buffer to which the management data will be copied. */
-unsigned int *pLen, /* Length of buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int TableIndex;
- unsigned int DstOffset;
- unsigned int InstanceNo;
- unsigned int InstanceCnt;
- SK_U32 Instance;
- unsigned int TmpLen;
- char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
-
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
- *pLen, NetIndex));
-
- if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
- if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
- (SK_U32)(-1));
- }
-
- *pLen = SK_PNMI_STRUCT_SIZE;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Check NetIndex
- */
- if (NetIndex >= pAC->Rlmt.NumNets) {
- return (SK_PNMI_ERR_UNKNOWN_NET);
- }
-
- /* Update statistic */
- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
-
- if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
- SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- /*
- * Increment semaphores to indicate that an update was
- * already done
- */
- pAC->Pnmi.MacUpdatedFlag ++;
- pAC->Pnmi.RlmtUpdatedFlag ++;
- pAC->Pnmi.SirqUpdatedFlag ++;
-
- /* Get vpd keys for instance calculation */
- Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
- if (Ret != SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.MacUpdatedFlag --;
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Retrieve values */
- SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
- for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
- InstanceNo = IdTable[TableIndex].InstanceNo;
- for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
- InstanceCnt ++) {
-
- DstOffset = IdTable[TableIndex].Offset +
- (InstanceCnt - 1) *
- IdTable[TableIndex].StructSize;
-
- /*
- * For the VPD the instance is not an index number
- * but the key itself. Determin with the instance
- * counter the VPD key to be used.
- */
- if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
- IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
- IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
- IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
-
- SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
- }
- else {
- Instance = (SK_U32)InstanceCnt;
- }
-
- TmpLen = *pLen - DstOffset;
- Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
- IdTable[TableIndex].Id, (char *)pBuf +
- DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
-
- /*
- * An unknown instance error means that we reached
- * the last instance of that variable. Proceed with
- * the next OID in the table and ignore the return
- * code.
- */
- if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
- break;
- }
-
- if (Ret != SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.MacUpdatedFlag --;
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
- SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
- }
- }
-
- pAC->Pnmi.MacUpdatedFlag --;
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- *pLen = SK_PNMI_STRUCT_SIZE;
- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- * Calls a general sub-function for all this set stuff. The preset does
- * the same as a set, but returns just before finally setting the
- * new value. This is useful to check if a set might be successfull.
- * The sub-function runs through the IdTable, checks which OIDs are able
- * to set, and calls the handler function of the OID to perform the
- * preset. The return value of the function will also be stored in
- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- * SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- */
-int SkPnmiPreSetStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-void *pBuf, /* Buffer which contains the data to be set */
-unsigned int *pLen, /* Length of buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
- *pLen, NetIndex));
-
- return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
- pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
- *
- * Description:
- * Calls a general sub-function for all this set stuff. The return value
- * of the function will also be stored in SK_PNMI_STRUCT_DATA if the
- * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
- * The sub-function runs through the IdTable, checks which OIDs are able
- * to set, and calls the handler function of the OID to perform the
- * set. The return value of the function will also be stored in
- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- * SK_PNMI_MIN_STRUCT_SIZE.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- */
-int SkPnmiSetStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-void *pBuf, /* Buffer which contains the data to be set */
-unsigned int *pLen, /* Length of buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
- *pLen, NetIndex));
-
- return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
- pLen, NetIndex));
-}
-
-/*****************************************************************************
- *
- * SkPnmiEvent - Event handler
- *
- * Description:
- * Handles the following events:
- * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an
- * interrupt will be generated which is
- * first handled by SIRQ which generates a
- * this event. The event increments the
- * upper 32 bit of the 64 bit counter.
- * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module
- * when a sensor reports a warning or
- * error. The event will store a trap
- * message in the trap buffer.
- * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this
- * module and is used to calculate the
- * port switches per hour.
- * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and
- * timestamps.
- * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver
- * before a hard reset of the XMAC is
- * performed. All counters will be saved
- * and added to the hardware counter
- * values after reset to grant continuous
- * counter values.
- * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port
- * went logically up. A trap message will
- * be stored to the trap buffer.
- * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port
- * went logically down. A trap message will
- * be stored to the trap buffer.
- * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
- * spanning tree root bridges were
- * detected. A trap message will be stored
- * to the trap buffer.
- * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went
- * down. PNMI will not further add the
- * statistic values to the virtual port.
- * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and
- * is now an active port. PNMI will now
- * add the statistic data of this port to
- * the virtual port.
- * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter
- * contains the number of nets. 1 means single net, 2 means
- * dual net. The second parameter is -1
- *
- * Returns:
- * Always 0
- */
-int SkPnmiEvent(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Event, /* Event-Id */
-SK_EVPARA Param) /* Event dependent parameter */
-{
- unsigned int PhysPortIndex;
- unsigned int MaxNetNumber;
- int CounterIndex;
- int Ret;
- SK_U16 MacStatus;
- SK_U64 OverflowStatus;
- SK_U64 Mask;
- int MacType;
- SK_U64 Value;
- SK_U32 Val32;
- SK_U16 Register;
- SK_EVPARA EventParam;
- SK_U64 NewestValue;
- SK_U64 OldestValue;
- SK_U64 Delta;
- SK_PNMI_ESTIMATE *pEst;
- SK_U32 NetIndex;
- SK_GEPORT *pPrt;
- SK_PNMI_VCT *pVctBackupData;
- SK_U32 RetCode;
- int i;
- SK_U32 CableLength;
-
-
-#ifdef DEBUG
- if (Event != SK_PNMI_EVT_XMAC_RESET) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
- (unsigned int)Event, (unsigned int)Param.Para64));
- }
-#endif /* DEBUG */
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
-
- MacType = pAC->GIni.GIMacType;
-
- switch (Event) {
-
- case SK_PNMI_EVT_SIRQ_OVERFLOW:
- PhysPortIndex = (int)Param.Para32[0];
- MacStatus = (SK_U16)Param.Para32[1];
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
- " wrong, PhysPortIndex=0x%x\n",
- PhysPortIndex));
- return (0);
- }
-#endif /* DEBUG */
- OverflowStatus = 0;
-
- /*
- * Check which source caused an overflow interrupt.
- */
- if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
- MacStatus, &OverflowStatus) != 0) ||
- (OverflowStatus == 0)) {
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
- }
-
- /*
- * Check the overflow status register and increment
- * the upper dword of corresponding counter.
- */
- for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
- CounterIndex ++) {
-
- Mask = (SK_U64)1 << CounterIndex;
- if ((OverflowStatus & Mask) == 0) {
-
- continue;
- }
-
- switch (StatOvrflwBit[CounterIndex][MacType]) {
-
- case SK_PNMI_HTX_UTILUNDER:
- case SK_PNMI_HTX_UTILOVER:
- if (MacType == SK_MAC_XMAC) {
- XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
- Register |= XM_TX_SAM_LINE;
- XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
- }
- break;
-
- case SK_PNMI_HRX_UTILUNDER:
- case SK_PNMI_HRX_UTILOVER:
- if (MacType == SK_MAC_XMAC) {
- XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
- Register |= XM_RX_SAM_LINE;
- XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
- }
- break;
-
- case SK_PNMI_HTX_OCTETHIGH:
- case SK_PNMI_HTX_OCTETLOW:
- case SK_PNMI_HTX_RESERVED:
- case SK_PNMI_HRX_OCTETHIGH:
- case SK_PNMI_HRX_OCTETLOW:
- case SK_PNMI_HRX_IRLENGTH:
- case SK_PNMI_HRX_RESERVED:
-
- /*
- * the following counters aren't be handled (id > 63)
- */
- case SK_PNMI_HTX_SYNC:
- case SK_PNMI_HTX_SYNC_OCTET:
- break;
-
- case SK_PNMI_HRX_LONGFRAMES:
- if (MacType == SK_MAC_GMAC) {
- pAC->Pnmi.Port[PhysPortIndex].
- CounterHigh[CounterIndex] ++;
- }
- break;
-
- default:
- pAC->Pnmi.Port[PhysPortIndex].
- CounterHigh[CounterIndex] ++;
- }
- }
- break;
-
- case SK_PNMI_EVT_SEN_WAR_LOW:
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate
- * an event for user space applications with the
- * SK_DRIVER_SENDEVENT macro.
- */
- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
- (unsigned int)Param.Para64);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_SEN_WAR_UPP:
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate
- * an event for user space applications with the
- * SK_DRIVER_SENDEVENT macro.
- */
- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
- (unsigned int)Param.Para64);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_SEN_ERR_LOW:
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate
- * an event for user space applications with the
- * SK_DRIVER_SENDEVENT macro.
- */
- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
- (unsigned int)Param.Para64);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_SEN_ERR_UPP:
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate
- * an event for user space applications with the
- * SK_DRIVER_SENDEVENT macro.
- */
- QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
- (unsigned int)Param.Para64);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_CHG_EST_TIMER:
- /*
- * Calculate port switch average on a per hour basis
- * Time interval for check : 28125 ms
- * Number of values for average : 8
- *
- * Be careful in changing these values, on change check
- * - typedef of SK_PNMI_ESTIMATE (Size of EstValue
- * array one less than value number)
- * - Timer initialization SkTimerStart() in SkPnmiInit
- * - Delta value below must be multiplicated with
- * power of 2
- *
- */
- pEst = &pAC->Pnmi.RlmtChangeEstimate;
- CounterIndex = pEst->EstValueIndex + 1;
- if (CounterIndex == 7) {
-
- CounterIndex = 0;
- }
- pEst->EstValueIndex = CounterIndex;
-
- NewestValue = pAC->Pnmi.RlmtChangeCts;
- OldestValue = pEst->EstValue[CounterIndex];
- pEst->EstValue[CounterIndex] = NewestValue;
-
- /*
- * Calculate average. Delta stores the number of
- * port switches per 28125 * 8 = 225000 ms
- */
- if (NewestValue >= OldestValue) {
-
- Delta = NewestValue - OldestValue;
- }
- else {
- /* Overflow situation */
- Delta = (SK_U64)(0 - OldestValue) + NewestValue;
- }
-
- /*
- * Extrapolate delta to port switches per hour.
- * Estimate = Delta * (3600000 / 225000)
- * = Delta * 16
- * = Delta << 4
- */
- pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
-
- /*
- * Check if threshold is exceeded. If the threshold is
- * permanently exceeded every 28125 ms an event will be
- * generated to remind the user of this condition.
- */
- if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
- (pAC->Pnmi.RlmtChangeEstimate.Estimate >=
- pAC->Pnmi.RlmtChangeThreshold)) {
-
- QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- }
-
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
- 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
- EventParam);
- break;
-
- case SK_PNMI_EVT_CLEAR_COUNTER:
- /*
- * Param.Para32[0] contains the NetIndex (0 ..1).
- * Param.Para32[1] is reserved, contains -1.
- */
- NetIndex = (SK_U32)Param.Para32[0];
-
-#ifdef DEBUG
- if (NetIndex >= pAC->Rlmt.NumNets) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
- NetIndex));
-
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Set all counters and timestamps to zero.
- * The according NetIndex is required as a
- * parameter of the event.
- */
- ResetCounter(pAC, IoC, NetIndex);
- break;
-
- case SK_PNMI_EVT_XMAC_RESET:
- /*
- * To grant continuous counter values store the current
- * XMAC statistic values to the entries 1..n of the
- * CounterOffset array. XMAC Errata #2
- */
-#ifdef DEBUG
- if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
- (unsigned int)Param.Para64));
- return (0);
- }
-#endif
- PhysPortIndex = (unsigned int)Param.Para64;
-
- /*
- * Update XMAC statistic to get fresh values
- */
- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
- if (Ret != SK_PNMI_ERR_OK) {
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
- }
- /*
- * Increment semaphore to indicate that an update was
- * already done
- */
- pAC->Pnmi.MacUpdatedFlag ++;
-
- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
- CounterIndex ++) {
-
- if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
- continue;
- }
-
- pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
- GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
- pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
- }
-
- pAC->Pnmi.MacUpdatedFlag --;
- break;
-
- case SK_PNMI_EVT_RLMT_PORT_UP:
- PhysPortIndex = (unsigned int)Param.Para32[0];
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
- " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate an event for
- * user space applications with the SK_DRIVER_SENDEVENT macro.
- */
- QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
- /* Bugfix for XMAC errata (#10620)*/
- if (MacType == SK_MAC_XMAC) {
- /* Add incremental difference to offset (#10620)*/
- (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
- XM_RXE_SHT_ERR, &Val32);
-
- Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
- CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
- pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
- Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
- }
-
- /* Tell VctStatus() that a link was up meanwhile. */
- pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;
- break;
-
- case SK_PNMI_EVT_RLMT_PORT_DOWN:
- PhysPortIndex = (unsigned int)Param.Para32[0];
-
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
- " wrong, PhysPortIndex=%d\n", PhysPortIndex));
-
- return (0);
- }
-#endif /* DEBUG */
-
- /*
- * Store a trap message in the trap buffer and generate an event for
- * user space applications with the SK_DRIVER_SENDEVENT macro.
- */
- QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
- /* Bugfix #10620 - get zero level for incremental difference */
- if (MacType == SK_MAC_XMAC) {
-
- (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
- XM_RXE_SHT_ERR, &Val32);
-
- pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
- (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
- CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
- }
- break;
-
- case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
- PhysPortIndex = (unsigned int)Param.Para32[0];
- NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
- PhysPortIndex));
- }
-
- if (NetIndex >= pAC->Rlmt.NumNets) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
- NetIndex));
- }
-#endif /* DEBUG */
-
- /*
- * For now, ignore event if NetIndex != 0.
- */
- if (Param.Para32[1] != 0) {
-
- return (0);
- }
-
- /*
- * Nothing to do if port is already inactive
- */
- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- return (0);
- }
-
- /*
- * Update statistic counters to calculate new offset for the virtual
- * port and increment semaphore to indicate that an update was already
- * done.
- */
- if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
- SK_PNMI_ERR_OK) {
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /*
- * Calculate new counter offset for virtual port to grant continous
- * counting on port switches. The virtual port consists of all currently
- * active ports. The port down event indicates that a port is removed
- * from the virtual port. Therefore add the counter value of the removed
- * port to the CounterOffset for the virtual port to grant the same
- * counter value.
- */
- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
- CounterIndex ++) {
-
- if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
- continue;
- }
-
- Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
- pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
- }
-
- /*
- * Set port to inactive
- */
- pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
-
- pAC->Pnmi.MacUpdatedFlag --;
- break;
-
- case SK_PNMI_EVT_RLMT_ACTIVE_UP:
- PhysPortIndex = (unsigned int)Param.Para32[0];
- NetIndex = (SK_U32)Param.Para32[1];
-
-#ifdef DEBUG
- if (PhysPortIndex >= SK_MAX_MACS) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
- PhysPortIndex));
- }
-
- if (NetIndex >= pAC->Rlmt.NumNets) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
- NetIndex));
- }
-#endif /* DEBUG */
-
- /*
- * For now, ignore event if NetIndex != 0.
- */
- if (Param.Para32[1] != 0) {
-
- return (0);
- }
-
- /*
- * Nothing to do if port is already active
- */
- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- return (0);
- }
-
- /*
- * Statistic maintenance
- */
- pAC->Pnmi.RlmtChangeCts ++;
- pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
-
- /*
- * Store a trap message in the trap buffer and generate an event for
- * user space applications with the SK_DRIVER_SENDEVENT macro.
- */
- QueueRlmtNewMacTrap(pAC, PhysPortIndex);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
-
- /*
- * Update statistic counters to calculate new offset for the virtual
- * port and increment semaphore to indicate that an update was
- * already done.
- */
- if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
- SK_PNMI_ERR_OK) {
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /*
- * Calculate new counter offset for virtual port to grant continous
- * counting on port switches. A new port is added to the virtual port.
- * Therefore substract the counter value of the new port from the
- * CounterOffset for the virtual port to grant the same value.
- */
- for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
- CounterIndex ++) {
-
- if (!StatAddr[CounterIndex][MacType].GetOffset) {
-
- continue;
- }
-
- Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
-
- pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
- }
-
- /* Set port to active */
- pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
-
- pAC->Pnmi.MacUpdatedFlag --;
- break;
-
- case SK_PNMI_EVT_RLMT_SEGMENTATION:
- /*
- * Para.Para32[0] contains the NetIndex.
- */
-
- /*
- * Store a trap message in the trap buffer and generate an event for
- * user space applications with the SK_DRIVER_SENDEVENT macro.
- */
- QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
- (void)SK_DRIVER_SENDEVENT(pAC, IoC);
- break;
-
- case SK_PNMI_EVT_RLMT_SET_NETS:
- /*
- * Param.Para32[0] contains the number of Nets.
- * Param.Para32[1] is reserved, contains -1.
- */
- /*
- * Check number of nets
- */
- MaxNetNumber = pAC->GIni.GIMacsFound;
- if (((unsigned int)Param.Para32[0] < 1)
- || ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
- return (SK_PNMI_ERR_UNKNOWN_NET);
- }
-
- if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
- pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
- }
- else { /* dual net mode */
- pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
- }
- break;
-
- case SK_PNMI_EVT_VCT_RESET:
- PhysPortIndex = Param.Para32[0];
- pPrt = &pAC->GIni.GP[PhysPortIndex];
- pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-
- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
- if (RetCode == 2) {
- /*
- * VCT test is still running.
- * Start VCT timer counter again.
- */
- SK_MEMSET((char *) &Param, 0, sizeof(Param));
- Param.Para32[0] = PhysPortIndex;
- Param.Para32[1] = -1;
- SkTimerStart(pAC, IoC,
- &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
- 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
- break;
- }
- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
- pAC->Pnmi.VctStatus[PhysPortIndex] |=
- (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-
- /* Copy results for later use to PNMI struct. */
- for (i = 0; i < 4; i++) {
- if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
- if ((pPrt->PMdiPairLen[i] > 35) &&
- (pPrt->PMdiPairLen[i] < 0xff)) {
- pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
- }
- }
- if ((pPrt->PMdiPairLen[i] > 35) &&
- (pPrt->PMdiPairLen[i] != 0xff)) {
- CableLength = 1000 *
- (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
- }
- else {
- CableLength = 0;
- }
- pVctBackupData->PMdiPairLen[i] = CableLength;
- pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
- }
-
- Param.Para32[0] = PhysPortIndex;
- Param.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
- SkEventDispatcher(pAC, IoC);
- }
-
- break;
-
- default:
- break;
- }
-
- SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
- return (0);
-}
-
-
-/******************************************************************************
- *
- * Private functions
- *
- */
-
-/*****************************************************************************
- *
- * PnmiVar - Gets, presets, and sets single OIDs
- *
- * Description:
- * Looks up the requested OID, calls the corresponding handler
- * function, and passes the parameters with the get, preset, or
- * set command. The function is called by SkGePnmiGetVar,
- * SkGePnmiPreSetVar, or SkGePnmiSetVar.
- *
- * Returns:
- * SK_PNMI_ERR_XXX. For details have a look at the description of the
- * calling functions.
- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiVar(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* Total length of pBuf management data */
-SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int TableIndex;
- int Ret;
-
-
- if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_OID);
- }
-
- /* Check NetIndex */
- if (NetIndex >= pAC->Rlmt.NumNets) {
- return (SK_PNMI_ERR_UNKNOWN_NET);
- }
-
- SK_PNMI_CHECKFLAGS("PnmiVar: On call");
-
- Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
- Instance, TableIndex, NetIndex);
-
- SK_PNMI_CHECKFLAGS("PnmiVar: On return");
-
- return (Ret);
-}
-
-/*****************************************************************************
- *
- * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
- *
- * Description:
- * The return value of the function will also be stored in
- * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
- * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
- * checks which OIDs are able to set, and calls the handler function of
- * the OID to perform the set. The return value of the function will
- * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
- * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
- * by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
- *
- * Returns:
- * SK_PNMI_ERR_XXX. The codes are described in the calling functions.
- * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
- */
-PNMI_STATIC int PnmiStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* PRESET/SET action to be performed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* Length of pBuf management data buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int TableIndex;
- unsigned int DstOffset;
- unsigned int Len;
- unsigned int InstanceNo;
- unsigned int InstanceCnt;
- SK_U32 Instance;
- SK_U32 Id;
-
-
- /* Check if the passed buffer has the right size */
- if (*pLen < SK_PNMI_STRUCT_SIZE) {
-
- /* Check if we can return the error within the buffer */
- if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
-
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
- (SK_U32)(-1));
- }
-
- *pLen = SK_PNMI_STRUCT_SIZE;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /* Check NetIndex */
- if (NetIndex >= pAC->Rlmt.NumNets) {
- return (SK_PNMI_ERR_UNKNOWN_NET);
- }
-
- SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
-
- /*
- * Update the values of RLMT and SIRQ and increment semaphores to
- * indicate that an update was already done.
- */
- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (Ret);
- }
-
- pAC->Pnmi.RlmtUpdatedFlag ++;
- pAC->Pnmi.SirqUpdatedFlag ++;
-
- /* Preset/Set values */
- for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
-
- if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
- (IdTable[TableIndex].Access != SK_PNMI_WO)) {
-
- continue;
- }
-
- InstanceNo = IdTable[TableIndex].InstanceNo;
- Id = IdTable[TableIndex].Id;
-
- for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
- InstanceCnt ++) {
-
- DstOffset = IdTable[TableIndex].Offset +
- (InstanceCnt - 1) *
- IdTable[TableIndex].StructSize;
-
- /*
- * Because VPD multiple instance variables are
- * not setable we do not need to evaluate VPD
- * instances. Have a look to VPD instance
- * calculation in SkPnmiGetStruct().
- */
- Instance = (SK_U32)InstanceCnt;
-
- /*
- * Evaluate needed buffer length
- */
- Len = 0;
- Ret = IdTable[TableIndex].Func(pAC, IoC,
- SK_PNMI_GET, IdTable[TableIndex].Id,
- NULL, &Len, Instance, TableIndex, NetIndex);
-
- if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
-
- break;
- }
- if (Ret != SK_PNMI_ERR_TOO_SHORT) {
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
- SK_PNMI_SET_STAT(pBuf,
- SK_PNMI_ERR_GENERAL, DstOffset);
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (SK_PNMI_ERR_GENERAL);
- }
- if (Id == OID_SKGE_VPD_ACTION) {
-
- switch (*(pBuf + DstOffset)) {
-
- case SK_PNMI_VPD_CREATE:
- Len = 3 + *(pBuf + DstOffset + 3);
- break;
-
- case SK_PNMI_VPD_DELETE:
- Len = 3;
- break;
-
- default:
- Len = 1;
- break;
- }
- }
-
- /* Call the OID handler function */
- Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
- IdTable[TableIndex].Id, pBuf + DstOffset,
- &Len, Instance, TableIndex, NetIndex);
-
- if (Ret != SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
- DstOffset);
- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- }
- }
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * LookupId - Lookup an OID in the IdTable
- *
- * Description:
- * Scans the IdTable to find the table entry of an OID.
- *
- * Returns:
- * The table index or -1 if not found.
- */
-PNMI_STATIC int LookupId(
-SK_U32 Id) /* Object identifier to be searched */
-{
- int i;
-
- for (i = 0; i < ID_TABLE_SIZE; i++) {
-
- if (IdTable[i].Id == Id) {
-
- return i;
- }
- }
-
- return (-1);
-}
-
-/*****************************************************************************
- *
- * OidStruct - Handler of OID_SKGE_ALL_DATA
- *
- * Description:
- * This OID performs a Get/Preset/SetStruct call and returns all data
- * in a SK_PNMI_STRUCT_DATA structure.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int OidStruct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- if (Id != OID_SKGE_ALL_DATA) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
- SK_PNMI_ERR003MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Check instance. We only handle single instance variables
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- switch (Action) {
-
- case SK_PNMI_GET:
- return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
- case SK_PNMI_PRESET:
- return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
-
- case SK_PNMI_SET:
- return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
- }
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
-}
-
-/*****************************************************************************
- *
- * Perform - OID handler of OID_SKGE_ACTION
- *
- * Description:
- * None.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Perform(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- SK_U32 ActionOp;
-
-
- /*
- * Check instance. We only handle single instance variables
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /* Check if a get should be performed */
- if (Action == SK_PNMI_GET) {
-
- /* A get is easy. We always return the same value */
- ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
- SK_PNMI_STORE_U32(pBuf, ActionOp);
- *pLen = sizeof(SK_U32);
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Continue with PRESET/SET action */
- if (*pLen > sizeof(SK_U32)) {
-
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* Check if the command is a known one */
- SK_PNMI_READ_U32(pBuf, ActionOp);
- if (*pLen > sizeof(SK_U32) ||
- (ActionOp != SK_PNMI_ACT_IDLE &&
- ActionOp != SK_PNMI_ACT_RESET &&
- ActionOp != SK_PNMI_ACT_SELFTEST &&
- ActionOp != SK_PNMI_ACT_RESETCNT)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* A preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- switch (ActionOp) {
-
- case SK_PNMI_ACT_IDLE:
- /* Nothing to do */
- break;
-
- case SK_PNMI_ACT_RESET:
- /*
- * Perform a driver reset or something that comes near
- * to this.
- */
- Ret = SK_DRIVER_RESET(pAC, IoC);
- if (Ret != 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
- SK_PNMI_ERR005MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- case SK_PNMI_ACT_SELFTEST:
- /*
- * Perform a driver selftest or something similar to this.
- * Currently this feature is not used and will probably
- * implemented in another way.
- */
- Ret = SK_DRIVER_SELFTEST(pAC, IoC);
- pAC->Pnmi.TestResult = Ret;
- break;
-
- case SK_PNMI_ACT_RESETCNT:
- /* Set all counters and timestamps to zero */
- ResetCounter(pAC, IoC, NetIndex);
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
- SK_PNMI_ERR006MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
- *
- * Description:
- * Retrieves the statistic values of the virtual port (logical
- * index 0). Only special OIDs of NDIS are handled which consist
- * of a 32 bit instead of a 64 bit value. The OIDs are public
- * because perhaps some other platform can use them too.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Mac8023Stat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- SK_U64 StatVal;
- SK_U32 StatVal32;
- SK_BOOL Is64BitReq = SK_FALSE;
-
- /*
- * Only the active Mac is returned
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /*
- * Check action type
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check length */
- switch (Id) {
-
- case OID_802_3_PERMANENT_ADDRESS:
- case OID_802_3_CURRENT_ADDRESS:
- if (*pLen < sizeof(SK_MAC_ADDR)) {
-
- *pLen = sizeof(SK_MAC_ADDR);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
-#ifndef SK_NDIS_64BIT_CTR
- if (*pLen < sizeof(SK_U32)) {
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
-#else /* SK_NDIS_64BIT_CTR */
-
- /* for compatibility, at least 32bit are required for OID */
- if (*pLen < sizeof(SK_U32)) {
- /*
- * but indicate handling for 64bit values,
- * if insufficient space is provided
- */
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
- break;
- }
-
- /*
- * Update all statistics, because we retrieve virtual MAC, which
- * consists of multiple physical statistics and increment semaphore
- * to indicate that an update was already done.
- */
- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
- if ( Ret != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /*
- * Get value (MAC Index 0 identifies the virtual MAC)
- */
- switch (Id) {
-
- case OID_802_3_PERMANENT_ADDRESS:
- CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
- *pLen = sizeof(SK_MAC_ADDR);
- break;
-
- case OID_802_3_CURRENT_ADDRESS:
- CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
- *pLen = sizeof(SK_MAC_ADDR);
- break;
-
- default:
- StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
-
- /* by default 32bit values are evaluated */
- if (!Is64BitReq) {
- StatVal32 = (SK_U32)StatVal;
- SK_PNMI_STORE_U32(pBuf, StatVal32);
- *pLen = sizeof(SK_U32);
- }
- else {
- SK_PNMI_STORE_U64(pBuf, StatVal);
- *pLen = sizeof(SK_U64);
- }
- break;
- }
-
- pAC->Pnmi.MacUpdatedFlag --;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
- *
- * Description:
- * Retrieves the MAC statistic data.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int MacPrivateStat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int LogPortMax;
- unsigned int LogPortIndex;
- unsigned int PhysPortMax;
- unsigned int Limit;
- unsigned int Offset;
- int MacType;
- int Ret;
- SK_U64 StatVal;
-
-
-
- /* Calculate instance if wished. MAC index 0 is the virtual MAC */
- PhysPortMax = pAC->GIni.GIMacsFound;
- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
- MacType = pAC->GIni.GIMacType;
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
- LogPortMax--;
- }
-
- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
- /* Check instance range */
- if ((Instance < 1) || (Instance > LogPortMax)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
- Limit = LogPortIndex + 1;
- }
-
- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
- LogPortIndex = 0;
- Limit = LogPortMax;
- }
-
- /* Check action */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check length */
- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
-
- *pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Update MAC statistic and increment semaphore to indicate that
- * an update was already done.
- */
- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
- if (Ret != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /* Get value */
- Offset = 0;
- for (; LogPortIndex < Limit; LogPortIndex ++) {
-
- switch (Id) {
-
-/* XXX not yet implemented due to XMAC problems
- case OID_SKGE_STAT_TX_UTIL:
- return (SK_PNMI_ERR_GENERAL);
-*/
-/* XXX not yet implemented due to XMAC problems
- case OID_SKGE_STAT_RX_UTIL:
- return (SK_PNMI_ERR_GENERAL);
-*/
- case OID_SKGE_STAT_RX:
- if (MacType == SK_MAC_GMAC) {
- StatVal =
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HRX_BROADCAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HRX_MULTICAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HRX_UNICAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HRX_UNDERSIZE, NetIndex);
- }
- else {
- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
- IdTable[TableIndex].Param, NetIndex);
- }
- break;
-
- case OID_SKGE_STAT_TX:
- if (MacType == SK_MAC_GMAC) {
- StatVal =
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HTX_BROADCAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HTX_MULTICAST, NetIndex) +
- GetStatVal(pAC, IoC, LogPortIndex,
- SK_PNMI_HTX_UNICAST, NetIndex);
- }
- else {
- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
- IdTable[TableIndex].Param, NetIndex);
- }
- break;
-
- default:
- StatVal = GetStatVal(pAC, IoC, LogPortIndex,
- IdTable[TableIndex].Param, NetIndex);
- }
- SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
-
- Offset += sizeof(SK_U64);
- }
- *pLen = Offset;
-
- pAC->Pnmi.MacUpdatedFlag --;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
- *
- * Description:
- * Get/Presets/Sets the current and factory MAC address. The MAC
- * address of the virtual port, which is reported to the OS, may
- * not be changed, but the physical ones. A set to the virtual port
- * will be ignored. No error should be reported because otherwise
- * a multiple instance set (-1) would always fail.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Addr(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int LogPortMax;
- unsigned int PhysPortMax;
- unsigned int LogPortIndex;
- unsigned int PhysPortIndex;
- unsigned int Limit;
- unsigned int Offset = 0;
-
- /*
- * Calculate instance if wished. MAC index 0 is the virtual
- * MAC.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
- LogPortMax--;
- }
-
- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
- /* Check instance range */
- if ((Instance < 1) || (Instance > LogPortMax)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
- Limit = LogPortIndex + 1;
- }
- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
- LogPortIndex = 0;
- Limit = LogPortMax;
- }
-
- /*
- * Perform Action
- */
- if (Action == SK_PNMI_GET) {
-
- /* Check length */
- if (*pLen < (Limit - LogPortIndex) * 6) {
-
- *pLen = (Limit - LogPortIndex) * 6;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Get value
- */
- for (; LogPortIndex < Limit; LogPortIndex ++) {
-
- switch (Id) {
-
- case OID_SKGE_PHYS_CUR_ADDR:
- if (LogPortIndex == 0) {
- CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
- }
- else {
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-
- CopyMac(pBuf + Offset,
- &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
- }
- Offset += 6;
- break;
-
- case OID_SKGE_PHYS_FAC_ADDR:
- if (LogPortIndex == 0) {
- CopyMac(pBuf + Offset,
- &pAC->Addr.Net[NetIndex].PermanentMacAddress);
- }
- else {
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- CopyMac(pBuf + Offset,
- &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
- }
- Offset += 6;
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
- SK_PNMI_ERR008MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- *pLen = Offset;
- }
- else {
- /*
- * The logical MAC address may not be changed only
- * the physical ones
- */
- if (Id == OID_SKGE_PHYS_FAC_ADDR) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /*
- * Only the current address may be changed
- */
- if (Id != OID_SKGE_PHYS_CUR_ADDR) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
- SK_PNMI_ERR009MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Check length */
- if (*pLen < (Limit - LogPortIndex) * 6) {
-
- *pLen = (Limit - LogPortIndex) * 6;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- if (*pLen > (Limit - LogPortIndex) * 6) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /*
- * Check Action
- */
- if (Action == SK_PNMI_PRESET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_OK);
- }
-
- /*
- * Set OID_SKGE_MAC_CUR_ADDR
- */
- for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
-
- /*
- * A set to virtual port and set of broadcast
- * address will be ignored
- */
- if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
- "\xff\xff\xff\xff\xff\xff", 6) == 0) {
-
- continue;
- }
-
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
- LogPortIndex);
-
- Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
- (SK_MAC_ADDR *)(pBuf + Offset),
- (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
- SK_ADDR_PHYSICAL_ADDRESS));
- if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
-
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- *pLen = Offset;
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
- *
- * Description:
- * Retrieves the statistic values of the CSUM module. The CSUM data
- * structure must be available in the SK_AC even if the CSUM module
- * is not included, because PNMI reads the statistic data from the
- * CSUM part of SK_AC directly.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int CsumStat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int Index;
- unsigned int Limit;
- unsigned int Offset = 0;
- SK_U64 StatVal;
-
-
- /*
- * Calculate instance if wished
- */
- if (Instance != (SK_U32)(-1)) {
-
- if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- Index = (unsigned int)Instance - 1;
- Limit = Index + 1;
- }
- else {
- Index = 0;
- Limit = SKCS_NUM_PROTOCOLS;
- }
-
- /*
- * Check action
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check length */
- if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
- *pLen = (Limit - Index) * sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Get value
- */
- for (; Index < Limit; Index ++) {
-
- switch (Id) {
-
- case OID_SKGE_CHKSM_RX_OK_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
- break;
-
- case OID_SKGE_CHKSM_RX_UNABLE_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
- break;
-
- case OID_SKGE_CHKSM_RX_ERR_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
- break;
-
- case OID_SKGE_CHKSM_TX_OK_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
- break;
-
- case OID_SKGE_CHKSM_TX_UNABLE_CTS:
- StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
- SK_PNMI_ERR010MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
- Offset += sizeof(SK_U64);
- }
-
- /*
- * Store used buffer space
- */
- *pLen = Offset;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
- *
- * Description:
- * Retrieves the statistic values of the I2C module, which handles
- * the temperature and voltage sensors.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int SensorStat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int i;
- unsigned int Index;
- unsigned int Limit;
- unsigned int Offset;
- unsigned int Len;
- SK_U32 Val32;
- SK_U64 Val64;
-
-
- /*
- * Calculate instance if wished
- */
- if ((Instance != (SK_U32)(-1))) {
-
- if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- Index = (unsigned int)Instance -1;
- Limit = (unsigned int)Instance;
- }
- else {
- Index = 0;
- Limit = (unsigned int) pAC->I2c.MaxSens;
- }
-
- /*
- * Check action
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check length */
- switch (Id) {
-
- case OID_SKGE_SENSOR_VALUE:
- case OID_SKGE_SENSOR_WAR_THRES_LOW:
- case OID_SKGE_SENSOR_WAR_THRES_UPP:
- case OID_SKGE_SENSOR_ERR_THRES_LOW:
- case OID_SKGE_SENSOR_ERR_THRES_UPP:
- if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
-
- *pLen = (Limit - Index) * sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_SENSOR_DESCR:
- for (Offset = 0, i = Index; i < Limit; i ++) {
-
- Len = (unsigned int)
- SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
- if (Len >= SK_PNMI_STRINGLEN2) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
- SK_PNMI_ERR011MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- Offset += Len;
- }
- if (*pLen < Offset) {
-
- *pLen = Offset;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_SENSOR_INDEX:
- case OID_SKGE_SENSOR_TYPE:
- case OID_SKGE_SENSOR_STATUS:
- if (*pLen < Limit - Index) {
-
- *pLen = Limit - Index;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_SENSOR_WAR_CTS:
- case OID_SKGE_SENSOR_WAR_TIME:
- case OID_SKGE_SENSOR_ERR_CTS:
- case OID_SKGE_SENSOR_ERR_TIME:
- if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
-
- *pLen = (Limit - Index) * sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
- SK_PNMI_ERR012MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
-
- }
-
- /*
- * Get value
- */
- for (Offset = 0; Index < Limit; Index ++) {
-
- switch (Id) {
-
- case OID_SKGE_SENSOR_INDEX:
- *(pBuf + Offset) = (char)Index;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SENSOR_DESCR:
- Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
- SK_MEMCPY(pBuf + Offset + 1,
- pAC->I2c.SenTable[Index].SenDesc, Len);
- *(pBuf + Offset) = (char)Len;
- Offset += Len + 1;
- break;
-
- case OID_SKGE_SENSOR_TYPE:
- *(pBuf + Offset) =
- (char)pAC->I2c.SenTable[Index].SenType;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SENSOR_VALUE:
- Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_WAR_THRES_LOW:
- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
- SenThreWarnLow;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_WAR_THRES_UPP:
- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
- SenThreWarnHigh;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_ERR_THRES_LOW:
- Val32 = (SK_U32)pAC->I2c.SenTable[Index].
- SenThreErrLow;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_ERR_THRES_UPP:
- Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_STATUS:
- *(pBuf + Offset) =
- (char)pAC->I2c.SenTable[Index].SenErrFlag;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SENSOR_WAR_CTS:
- Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_SENSOR_ERR_CTS:
- Val64 = pAC->I2c.SenTable[Index].SenErrCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_SENSOR_WAR_TIME:
- Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
- SenBegWarnTS);
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_SENSOR_ERR_TIME:
- Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
- SenBegErrTS);
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("SensorStat: Unknown OID should be handled before"));
-
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- /*
- * Store used buffer space
- */
- *pLen = Offset;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Vpd - OID handler function of OID_SKGE_VPD_XXX
- *
- * Description:
- * Get/preset/set of VPD data. As instance the name of a VPD key
- * can be passed. The Instance parameter is a SK_U32 and can be
- * used as a string buffer for the VPD key, because their maximum
- * length is 4 byte.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Vpd(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_VPD_STATUS *pVpdStatus;
- unsigned int BufLen;
- char Buf[256];
- char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
- char KeyStr[SK_PNMI_VPD_KEY_SIZE];
- unsigned int KeyNo;
- unsigned int Offset;
- unsigned int Index;
- unsigned int FirstIndex;
- unsigned int LastIndex;
- unsigned int Len;
- int Ret;
- SK_U32 Val32;
-
- /*
- * Get array of all currently stored VPD keys
- */
- Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
- if (Ret != SK_PNMI_ERR_OK) {
- *pLen = 0;
- return (Ret);
- }
-
- /*
- * If instance is not -1, try to find the requested VPD key for
- * the multiple instance variables. The other OIDs as for example
- * OID VPD_ACTION are single instance variables and must be
- * handled separatly.
- */
- FirstIndex = 0;
- LastIndex = KeyNo;
-
- if ((Instance != (SK_U32)(-1))) {
-
- if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
- Id == OID_SKGE_VPD_ACCESS) {
-
- SK_STRNCPY(KeyStr, (char *)&Instance, 4);
- KeyStr[4] = 0;
-
- for (Index = 0; Index < KeyNo; Index ++) {
-
- if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
- FirstIndex = Index;
- LastIndex = Index+1;
- break;
- }
- }
- if (Index == KeyNo) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- }
- else if (Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- }
-
- /*
- * Get value, if a query should be performed
- */
- if (Action == SK_PNMI_GET) {
-
- switch (Id) {
-
- case OID_SKGE_VPD_FREE_BYTES:
- /* Check length of buffer */
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /* Get number of free bytes */
- pVpdStatus = VpdStat(pAC, IoC);
- if (pVpdStatus == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
- SK_PNMI_ERR017MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
- SK_PNMI_ERR018MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_VPD_ENTRIES_LIST:
- /* Check length */
- for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
-
- Len += SK_STRLEN(KeyArr[Index]) + 1;
- }
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /* Get value */
- *(pBuf) = (char)Len - 1;
- for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
-
- Len = SK_STRLEN(KeyArr[Index]);
- SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
-
- Offset += Len;
-
- if (Index < KeyNo - 1) {
-
- *(pBuf + Offset) = ' ';
- Offset ++;
- }
- }
- *pLen = Offset;
- break;
-
- case OID_SKGE_VPD_ENTRIES_NUMBER:
- /* Check length */
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- Val32 = (SK_U32)KeyNo;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_VPD_KEY:
- /* Check buffer length, if it is large enough */
- for (Len = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- Len += SK_STRLEN(KeyArr[Index]) + 1;
- }
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Get the key to an intermediate buffer, because
- * we have to prepend a length byte.
- */
- for (Offset = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- Len = SK_STRLEN(KeyArr[Index]);
-
- *(pBuf + Offset) = (char)Len;
- SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
- Len);
- Offset += Len + 1;
- }
- *pLen = Offset;
- break;
-
- case OID_SKGE_VPD_VALUE:
- /* Check the buffer length if it is large enough */
- for (Offset = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- BufLen = 256;
- if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
- (int *)&BufLen) > 0 ||
- BufLen >= SK_PNMI_VPD_DATALEN) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR021,
- SK_PNMI_ERR021MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
- Offset += BufLen + 1;
- }
- if (*pLen < Offset) {
-
- *pLen = Offset;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * Get the value to an intermediate buffer, because
- * we have to prepend a length byte.
- */
- for (Offset = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- BufLen = 256;
- if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
- (int *)&BufLen) > 0 ||
- BufLen >= SK_PNMI_VPD_DATALEN) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR022,
- SK_PNMI_ERR022MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- *(pBuf + Offset) = (char)BufLen;
- SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
- Offset += BufLen + 1;
- }
- *pLen = Offset;
- break;
-
- case OID_SKGE_VPD_ACCESS:
- if (*pLen < LastIndex - FirstIndex) {
-
- *pLen = LastIndex - FirstIndex;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- for (Offset = 0, Index = FirstIndex;
- Index < LastIndex; Index ++) {
-
- if (VpdMayWrite(KeyArr[Index])) {
-
- *(pBuf + Offset) = SK_PNMI_VPD_RW;
- }
- else {
- *(pBuf + Offset) = SK_PNMI_VPD_RO;
- }
- Offset ++;
- }
- *pLen = Offset;
- break;
-
- case OID_SKGE_VPD_ACTION:
- Offset = LastIndex - FirstIndex;
- if (*pLen < Offset) {
-
- *pLen = Offset;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- SK_MEMSET(pBuf, 0, Offset);
- *pLen = Offset;
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
- SK_PNMI_ERR023MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- else {
- /* The only OID which can be set is VPD_ACTION */
- if (Id != OID_SKGE_VPD_ACTION) {
-
- if (Id == OID_SKGE_VPD_FREE_BYTES ||
- Id == OID_SKGE_VPD_ENTRIES_LIST ||
- Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
- Id == OID_SKGE_VPD_KEY ||
- Id == OID_SKGE_VPD_VALUE ||
- Id == OID_SKGE_VPD_ACCESS) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
- SK_PNMI_ERR024MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * From this point we handle VPD_ACTION. Check the buffer
- * length. It should at least have the size of one byte.
- */
- if (*pLen < 1) {
-
- *pLen = 1;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- /*
- * The first byte contains the VPD action type we should
- * perform.
- */
- switch (*pBuf) {
-
- case SK_PNMI_VPD_IGNORE:
- /* Nothing to do */
- break;
-
- case SK_PNMI_VPD_CREATE:
- /*
- * We have to create a new VPD entry or we modify
- * an existing one. Check first the buffer length.
- */
- if (*pLen < 4) {
-
- *pLen = 4;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- KeyStr[0] = pBuf[1];
- KeyStr[1] = pBuf[2];
- KeyStr[2] = 0;
-
- /*
- * Is the entry writable or does it belong to the
- * read-only area?
- */
- if (!VpdMayWrite(KeyStr)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- Offset = (int)pBuf[3] & 0xFF;
-
- SK_MEMCPY(Buf, pBuf + 4, Offset);
- Buf[Offset] = 0;
-
- /* A preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Write the new entry or modify an existing one */
- Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
- if (Ret == SK_PNMI_VPD_NOWRITE ) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- else if (Ret != SK_PNMI_VPD_OK) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
- SK_PNMI_ERR025MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Perform an update of the VPD data. This is
- * not mandantory, but just to be sure.
- */
- Ret = VpdUpdate(pAC, IoC);
- if (Ret != SK_PNMI_VPD_OK) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
- SK_PNMI_ERR026MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- case SK_PNMI_VPD_DELETE:
- /* Check if the buffer size is plausible */
- if (*pLen < 3) {
-
- *pLen = 3;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- if (*pLen > 3) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- KeyStr[0] = pBuf[1];
- KeyStr[1] = pBuf[2];
- KeyStr[2] = 0;
-
- /* Find the passed key in the array */
- for (Index = 0; Index < KeyNo; Index ++) {
-
- if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
-
- break;
- }
- }
- /*
- * If we cannot find the key it is wrong, so we
- * return an appropriate error value.
- */
- if (Index == KeyNo) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Ok, you wanted it and you will get it */
- Ret = VpdDelete(pAC, IoC, KeyStr);
- if (Ret != SK_PNMI_VPD_OK) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
- SK_PNMI_ERR027MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Perform an update of the VPD data. This is
- * not mandantory, but just to be sure.
- */
- Ret = VpdUpdate(pAC, IoC);
- if (Ret != SK_PNMI_VPD_OK) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
- SK_PNMI_ERR028MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * General - OID handler function of various single instance OIDs
- *
- * Description:
- * The code is simple. No description necessary.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int General(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int Index;
- unsigned int Len;
- unsigned int Offset;
- unsigned int Val;
- SK_U8 Val8;
- SK_U16 Val16;
- SK_U32 Val32;
- SK_U64 Val64;
- SK_U64 Val64RxHwErrs = 0;
- SK_U64 Val64TxHwErrs = 0;
- SK_BOOL Is64BitReq = SK_FALSE;
- char Buf[256];
- int MacType;
-
- /*
- * Check instance. We only handle single instance variables.
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /*
- * Check action. We only allow get requests.
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- MacType = pAC->GIni.GIMacType;
-
- /*
- * Check length for the various supported OIDs
- */
- switch (Id) {
-
- case OID_GEN_XMIT_ERROR:
- case OID_GEN_RCV_ERROR:
- case OID_GEN_RCV_NO_BUFFER:
-#ifndef SK_NDIS_64BIT_CTR
- if (*pLen < sizeof(SK_U32)) {
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
-#else /* SK_NDIS_64BIT_CTR */
-
- /*
- * for compatibility, at least 32bit are required for oid
- */
- if (*pLen < sizeof(SK_U32)) {
- /*
- * but indicate handling for 64bit values,
- * if insufficient space is provided
- */
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
-
- Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
-#endif /* SK_NDIS_64BIT_CTR */
- break;
-
- case OID_SKGE_PORT_NUMBER:
- case OID_SKGE_DEVICE_TYPE:
- case OID_SKGE_RESULT:
- case OID_SKGE_RLMT_MONITOR_NUMBER:
- case OID_GEN_TRANSMIT_QUEUE_LENGTH:
- case OID_SKGE_TRAP_NUMBER:
- case OID_SKGE_MDB_VERSION:
- case OID_SKGE_BOARDLEVEL:
- case OID_SKGE_CHIPID:
- case OID_SKGE_RAMSIZE:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_CHIPSET:
- if (*pLen < sizeof(SK_U16)) {
-
- *pLen = sizeof(SK_U16);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_BUS_TYPE:
- case OID_SKGE_BUS_SPEED:
- case OID_SKGE_BUS_WIDTH:
- case OID_SKGE_SENSOR_NUMBER:
- case OID_SKGE_CHKSM_NUMBER:
- case OID_SKGE_VAUXAVAIL:
- if (*pLen < sizeof(SK_U8)) {
-
- *pLen = sizeof(SK_U8);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_TX_SW_QUEUE_LEN:
- case OID_SKGE_TX_SW_QUEUE_MAX:
- case OID_SKGE_TX_RETRY:
- case OID_SKGE_RX_INTR_CTS:
- case OID_SKGE_TX_INTR_CTS:
- case OID_SKGE_RX_NO_BUF_CTS:
- case OID_SKGE_TX_NO_BUF_CTS:
- case OID_SKGE_TX_USED_DESCR_NO:
- case OID_SKGE_RX_DELIVERED_CTS:
- case OID_SKGE_RX_OCTETS_DELIV_CTS:
- case OID_SKGE_RX_HW_ERROR_CTS:
- case OID_SKGE_TX_HW_ERROR_CTS:
- case OID_SKGE_IN_ERRORS_CTS:
- case OID_SKGE_OUT_ERROR_CTS:
- case OID_SKGE_ERR_RECOVERY_CTS:
- case OID_SKGE_SYSUPTIME:
- if (*pLen < sizeof(SK_U64)) {
-
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- /* Checked later */
- break;
- }
-
- /* Update statistic */
- if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
- Id == OID_SKGE_TX_HW_ERROR_CTS ||
- Id == OID_SKGE_IN_ERRORS_CTS ||
- Id == OID_SKGE_OUT_ERROR_CTS ||
- Id == OID_GEN_XMIT_ERROR ||
- Id == OID_GEN_RCV_ERROR) {
-
- /* Force the XMAC to update its statistic counters and
- * Increment semaphore to indicate that an update was
- * already done.
- */
- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
- if (Ret != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.MacUpdatedFlag ++;
-
- /*
- * Some OIDs consist of multiple hardware counters. Those
- * values which are contained in all of them will be added
- * now.
- */
- switch (Id) {
-
- case OID_SKGE_RX_HW_ERROR_CTS:
- case OID_SKGE_IN_ERRORS_CTS:
- case OID_GEN_RCV_ERROR:
- Val64RxHwErrs =
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
- break;
-
- case OID_SKGE_TX_HW_ERROR_CTS:
- case OID_SKGE_OUT_ERROR_CTS:
- case OID_GEN_XMIT_ERROR:
- Val64TxHwErrs =
- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
- break;
- }
- }
-
- /*
- * Retrieve value
- */
- switch (Id) {
-
- case OID_SKGE_SUPPORTED_LIST:
- Len = ID_TABLE_SIZE * sizeof(SK_U32);
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- for (Offset = 0, Index = 0; Offset < Len;
- Offset += sizeof(SK_U32), Index ++) {
-
- Val32 = (SK_U32)IdTable[Index].Id;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- }
- *pLen = Len;
- break;
-
- case OID_SKGE_BOARDLEVEL:
- Val32 = (SK_U32)pAC->GIni.GILevel;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_PORT_NUMBER:
- Val32 = (SK_U32)pAC->GIni.GIMacsFound;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_DEVICE_TYPE:
- Val32 = (SK_U32)pAC->Pnmi.DeviceType;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_DRIVER_DESCR:
- if (pAC->Pnmi.pDriverDescription == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
- SK_PNMI_ERR007MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
- SK_PNMI_ERR029MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_DRIVER_VERSION:
- if (pAC->Pnmi.pDriverVersion == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
- SK_PNMI_ERR030MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
- SK_PNMI_ERR031MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_DRIVER_RELDATE:
- if (pAC->Pnmi.pDriverReleaseDate == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
- SK_PNMI_ERR053MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
- SK_PNMI_ERR054MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_DRIVER_FILENAME:
- if (pAC->Pnmi.pDriverFileName == NULL) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
- SK_PNMI_ERR055MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
- SK_PNMI_ERR056MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_HW_DESCR:
- /*
- * The hardware description is located in the VPD. This
- * query may move to the initialisation routine. But
- * the VPD data is cached and therefore a call here
- * will not make much difference.
- */
- Len = 256;
- if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
- SK_PNMI_ERR032MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- Len ++;
- if (Len > SK_PNMI_STRINGLEN1) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
- SK_PNMI_ERR033MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- *pBuf = (char)(Len - 1);
- SK_MEMCPY(pBuf + 1, Buf, Len - 1);
- *pLen = Len;
- break;
-
- case OID_SKGE_HW_VERSION:
- /* Oh, I love to do some string manipulation */
- if (*pLen < 5) {
-
- *pLen = 5;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
- pBuf[0] = 4;
- pBuf[1] = 'v';
- pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
- pBuf[3] = '.';
- pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
- *pLen = 5;
- break;
-
- case OID_SKGE_CHIPSET:
- Val16 = pAC->Pnmi.Chipset;
- SK_PNMI_STORE_U16(pBuf, Val16);
- *pLen = sizeof(SK_U16);
- break;
-
- case OID_SKGE_CHIPID:
- Val32 = pAC->GIni.GIChipId;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_RAMSIZE:
- Val32 = pAC->GIni.GIRamSize;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_VAUXAVAIL:
- *pBuf = (char) pAC->GIni.GIVauxAvail;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_BUS_TYPE:
- *pBuf = (char) SK_PNMI_BUS_PCI;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_BUS_SPEED:
- *pBuf = pAC->Pnmi.PciBusSpeed;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_BUS_WIDTH:
- *pBuf = pAC->Pnmi.PciBusWidth;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_RESULT:
- Val32 = pAC->Pnmi.TestResult;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_SENSOR_NUMBER:
- *pBuf = (char)pAC->I2c.MaxSens;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_CHKSM_NUMBER:
- *pBuf = SKCS_NUM_PROTOCOLS;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_TRAP_NUMBER:
- GetTrapQueueLen(pAC, &Len, &Val);
- Val32 = (SK_U32)Val;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_TRAP:
- GetTrapQueueLen(pAC, &Len, &Val);
- if (*pLen < Len) {
-
- *pLen = Len;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- CopyTrapQueue(pAC, pBuf);
- *pLen = Len;
- break;
-
- case OID_SKGE_RLMT_MONITOR_NUMBER:
-/* XXX Not yet implemented by RLMT therefore we return zero elements */
- Val32 = 0;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_TX_SW_QUEUE_LEN:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
- pAC->Pnmi.BufPort[1].TxSwQueueLen;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
- pAC->Pnmi.Port[1].TxSwQueueLen;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
-
- case OID_SKGE_TX_SW_QUEUE_MAX:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
- pAC->Pnmi.BufPort[1].TxSwQueueMax;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
- pAC->Pnmi.Port[1].TxSwQueueMax;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_RETRY:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
- pAC->Pnmi.BufPort[1].TxRetryCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxRetryCts +
- pAC->Pnmi.Port[1].TxRetryCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_INTR_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
- pAC->Pnmi.BufPort[1].RxIntrCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].RxIntrCts +
- pAC->Pnmi.Port[1].RxIntrCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_INTR_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
- pAC->Pnmi.BufPort[1].TxIntrCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxIntrCts +
- pAC->Pnmi.Port[1].TxIntrCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_NO_BUF_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
- pAC->Pnmi.BufPort[1].RxNoBufCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
- pAC->Pnmi.Port[1].RxNoBufCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_NO_BUF_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
- pAC->Pnmi.BufPort[1].TxNoBufCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
- pAC->Pnmi.Port[1].TxNoBufCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_USED_DESCR_NO:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
- pAC->Pnmi.BufPort[1].TxUsedDescrNo;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
- pAC->Pnmi.Port[1].TxUsedDescrNo;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_DELIVERED_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
- pAC->Pnmi.BufPort[1].RxDeliveredCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
- pAC->Pnmi.Port[1].RxDeliveredCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_OCTETS_DELIV_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
- pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
- pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RX_HW_ERROR_CTS:
- SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_TX_HW_ERROR_CTS:
- SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_IN_ERRORS_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = Val64RxHwErrs +
- pAC->Pnmi.BufPort[0].RxNoBufCts +
- pAC->Pnmi.BufPort[1].RxNoBufCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = Val64RxHwErrs +
- pAC->Pnmi.Port[0].RxNoBufCts +
- pAC->Pnmi.Port[1].RxNoBufCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_OUT_ERROR_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = Val64TxHwErrs +
- pAC->Pnmi.BufPort[0].TxNoBufCts +
- pAC->Pnmi.BufPort[1].TxNoBufCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
- }
- /* Single net mode */
- else {
- Val64 = Val64TxHwErrs +
- pAC->Pnmi.Port[0].TxNoBufCts +
- pAC->Pnmi.Port[1].TxNoBufCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_ERR_RECOVERY_CTS:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
- pAC->Pnmi.BufPort[1].ErrRecoveryCts;
- }
- }
- else {
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
- }
- /* Single net mode */
- else {
- Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
- pAC->Pnmi.Port[1].ErrRecoveryCts;
- }
- }
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_SYSUPTIME:
- Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
- Val64 -= pAC->Pnmi.StartUpTime;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_MDB_VERSION:
- Val32 = SK_PNMI_MDB_VERSION;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_GEN_RCV_ERROR:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
- }
- else {
- Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
- }
-
- /*
- * by default 32bit values are evaluated
- */
- if (!Is64BitReq) {
- Val32 = (SK_U32)Val64;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- }
- else {
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- }
- break;
-
- case OID_GEN_XMIT_ERROR:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
- }
- else {
- Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
- }
-
- /*
- * by default 32bit values are evaluated
- */
- if (!Is64BitReq) {
- Val32 = (SK_U32)Val64;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- }
- else {
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- }
- break;
-
- case OID_GEN_RCV_NO_BUFFER:
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
- }
- else {
- Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
- }
-
- /*
- * by default 32bit values are evaluated
- */
- if (!Is64BitReq) {
- Val32 = (SK_U32)Val64;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- }
- else {
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- }
- break;
-
- case OID_GEN_TRANSMIT_QUEUE_LENGTH:
- Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
- SK_PNMI_ERR034MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
- Id == OID_SKGE_TX_HW_ERROR_CTS ||
- Id == OID_SKGE_IN_ERRORS_CTS ||
- Id == OID_SKGE_OUT_ERROR_CTS ||
- Id == OID_GEN_XMIT_ERROR ||
- Id == OID_GEN_RCV_ERROR) {
-
- pAC->Pnmi.MacUpdatedFlag --;
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
- *
- * Description:
- * Get/Presets/Sets the RLMT OIDs.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Rlmt(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- int Ret;
- unsigned int PhysPortIndex;
- unsigned int PhysPortMax;
- SK_EVPARA EventParam;
- SK_U32 Val32;
- SK_U64 Val64;
-
-
- /*
- * Check instance. Only single instance OIDs are allowed here.
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /*
- * Perform the requested action.
- */
- if (Action == SK_PNMI_GET) {
-
- /*
- * Check if the buffer length is large enough.
- */
-
- switch (Id) {
-
- case OID_SKGE_RLMT_MODE:
- case OID_SKGE_RLMT_PORT_ACTIVE:
- case OID_SKGE_RLMT_PORT_PREFERRED:
- if (*pLen < sizeof(SK_U8)) {
-
- *pLen = sizeof(SK_U8);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_RLMT_PORT_NUMBER:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_RLMT_CHANGE_CTS:
- case OID_SKGE_RLMT_CHANGE_TIME:
- case OID_SKGE_RLMT_CHANGE_ESTIM:
- case OID_SKGE_RLMT_CHANGE_THRES:
- if (*pLen < sizeof(SK_U64)) {
-
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
- SK_PNMI_ERR035MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Update RLMT statistic and increment semaphores to indicate
- * that an update was already done. Maybe RLMT will hold its
- * statistic always up to date some time. Then we can
- * remove this type of call.
- */
- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.RlmtUpdatedFlag ++;
-
- /*
- * Retrieve Value
- */
- switch (Id) {
-
- case OID_SKGE_RLMT_MODE:
- *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_RLMT_PORT_NUMBER:
- Val32 = (SK_U32)pAC->GIni.GIMacsFound;
- SK_PNMI_STORE_U32(pBuf, Val32);
- *pLen = sizeof(SK_U32);
- break;
-
- case OID_SKGE_RLMT_PORT_ACTIVE:
- *pBuf = 0;
- /*
- * If multiple ports may become active this OID
- * doesn't make sense any more. A new variable in
- * the port structure should be created. However,
- * for this variable the first active port is
- * returned.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
-
- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
- break;
- }
- }
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_RLMT_PORT_PREFERRED:
- *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
- *pLen = sizeof(char);
- break;
-
- case OID_SKGE_RLMT_CHANGE_CTS:
- Val64 = pAC->Pnmi.RlmtChangeCts;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_CHANGE_TIME:
- Val64 = pAC->Pnmi.RlmtChangeTime;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_CHANGE_ESTIM:
- Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_CHANGE_THRES:
- Val64 = pAC->Pnmi.RlmtChangeThreshold;
- SK_PNMI_STORE_U64(pBuf, Val64);
- *pLen = sizeof(SK_U64);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("Rlmt: Unknown OID should be handled before"));
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- }
- else {
- /* Perform a preset or set */
- switch (Id) {
-
- case OID_SKGE_RLMT_MODE:
- /* Check if the buffer length is plausible */
- if (*pLen < sizeof(char)) {
-
- *pLen = sizeof(char);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /* Check if the value range is correct */
- if (*pLen != sizeof(char) ||
- (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
- *(SK_U8 *)pBuf > 15) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_OK);
- }
- /* Send an event to RLMT to change the mode */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] |= (SK_U32)(*pBuf);
- EventParam.Para32[1] = 0;
- if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
- SK_PNMI_ERR037MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- case OID_SKGE_RLMT_PORT_PREFERRED:
- /* Check if the buffer length is plausible */
- if (*pLen < sizeof(char)) {
-
- *pLen = sizeof(char);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /* Check if the value range is correct */
- if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
- (SK_U8)pAC->GIni.GIMacsFound) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_OK);
- }
-
- /*
- * Send an event to RLMT change the preferred port.
- * A param of -1 means automatic mode. RLMT will
- * make the decision which is the preferred port.
- */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
- EventParam.Para32[1] = NetIndex;
- if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
- SK_PNMI_ERR038MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- break;
-
- case OID_SKGE_RLMT_CHANGE_THRES:
- /* Check if the buffer length is plausible */
- if (*pLen < sizeof(SK_U64)) {
-
- *pLen = sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /*
- * There are not many restrictions to the
- * value range.
- */
- if (*pLen != sizeof(SK_U64)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- /* A preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_OK);
- }
- /*
- * Store the new threshold, which will be taken
- * on the next timer event.
- */
- SK_PNMI_READ_U64(pBuf, Val64);
- pAC->Pnmi.RlmtChangeThreshold = Val64;
- break;
-
- default:
- /* The other OIDs are not be able for set */
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
- *
- * Description:
- * Performs get requests on multiple instance variables.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int RlmtStat(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int PhysPortMax;
- unsigned int PhysPortIndex;
- unsigned int Limit;
- unsigned int Offset;
- int Ret;
- SK_U32 Val32;
- SK_U64 Val64;
-
- /*
- * Calculate the port indexes from the instance.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
-
- if ((Instance != (SK_U32)(-1))) {
- /* Check instance range */
- if ((Instance < 1) || (Instance > PhysPortMax)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /* Single net mode */
- PhysPortIndex = Instance - 1;
-
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- PhysPortIndex = NetIndex;
- }
-
- /* Both net modes */
- Limit = PhysPortIndex + 1;
- }
- else {
- /* Single net mode */
- PhysPortIndex = 0;
- Limit = PhysPortMax;
-
- /* Dual net mode */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- PhysPortIndex = NetIndex;
- Limit = PhysPortIndex + 1;
- }
- }
-
- /*
- * Currently only get requests are allowed.
- */
- if (Action != SK_PNMI_GET) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /*
- * Check if the buffer length is large enough.
- */
- switch (Id) {
-
- case OID_SKGE_RLMT_PORT_INDEX:
- case OID_SKGE_RLMT_STATUS:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
-
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_RLMT_TX_HELLO_CTS:
- case OID_SKGE_RLMT_RX_HELLO_CTS:
- case OID_SKGE_RLMT_TX_SP_REQ_CTS:
- case OID_SKGE_RLMT_RX_SP_CTS:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
-
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
- SK_PNMI_ERR039MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
-
- }
-
- /*
- * Update statistic and increment semaphores to indicate that
- * an update was already done.
- */
- if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.RlmtUpdatedFlag ++;
-
- /*
- * Get value
- */
- Offset = 0;
- for (; PhysPortIndex < Limit; PhysPortIndex ++) {
-
- switch (Id) {
-
- case OID_SKGE_RLMT_PORT_INDEX:
- Val32 = PhysPortIndex;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_RLMT_STATUS:
- if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
- SK_RLMT_PS_INIT ||
- pAC->Rlmt.Port[PhysPortIndex].PortState ==
- SK_RLMT_PS_DOWN) {
-
- Val32 = SK_PNMI_RLMT_STATUS_ERROR;
- }
- else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
- }
- else {
- Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
- }
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_RLMT_TX_HELLO_CTS:
- Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_RX_HELLO_CTS:
- Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_TX_SP_REQ_CTS:
- Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- case OID_SKGE_RLMT_RX_SP_CTS:
- Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
- SK_PNMI_STORE_U64(pBuf + Offset, Val64);
- Offset += sizeof(SK_U64);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("RlmtStat: Unknown OID should be errored before"));
-
- pAC->Pnmi.RlmtUpdatedFlag --;
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- *pLen = Offset;
-
- pAC->Pnmi.RlmtUpdatedFlag --;
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacPrivateConf - OID handler function of OIDs concerning the configuration
- *
- * Description:
- * Get/Presets/Sets the OIDs concerning the configuration.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int MacPrivateConf(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int PhysPortMax;
- unsigned int PhysPortIndex;
- unsigned int LogPortMax;
- unsigned int LogPortIndex;
- unsigned int Limit;
- unsigned int Offset;
- char Val8;
- char *pBufPtr;
- int Ret;
- SK_EVPARA EventParam;
- SK_U32 Val32;
-
- /*
- * Calculate instance if wished. MAC index 0 is the virtual MAC.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
- LogPortMax--;
- }
-
- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
- /* Check instance range */
- if ((Instance < 1) || (Instance > LogPortMax)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
- LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
- Limit = LogPortIndex + 1;
- }
-
- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
-
- LogPortIndex = 0;
- Limit = LogPortMax;
- }
-
- /*
- * Perform action
- */
- if (Action == SK_PNMI_GET) {
-
- /* Check length */
- switch (Id) {
-
- case OID_SKGE_PMD:
- case OID_SKGE_CONNECTOR:
- case OID_SKGE_LINK_CAP:
- case OID_SKGE_LINK_MODE:
- case OID_SKGE_LINK_MODE_STATUS:
- case OID_SKGE_LINK_STATUS:
- case OID_SKGE_FLOWCTRL_CAP:
- case OID_SKGE_FLOWCTRL_MODE:
- case OID_SKGE_FLOWCTRL_STATUS:
- case OID_SKGE_PHY_OPERATION_CAP:
- case OID_SKGE_PHY_OPERATION_MODE:
- case OID_SKGE_PHY_OPERATION_STATUS:
- case OID_SKGE_SPEED_CAP:
- case OID_SKGE_SPEED_MODE:
- case OID_SKGE_SPEED_STATUS:
- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
-
- *pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_MTU:
- case OID_SKGE_PHY_TYPE:
- if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
-
- *pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
- SK_PNMI_ERR041MSG);
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Update statistic and increment semaphore to indicate
- * that an update was already done.
- */
- if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
-
- *pLen = 0;
- return (Ret);
- }
- pAC->Pnmi.SirqUpdatedFlag ++;
-
- /*
- * Get value
- */
- Offset = 0;
- for (; LogPortIndex < Limit; LogPortIndex ++) {
-
- pBufPtr = pBuf + Offset;
-
- switch (Id) {
-
- case OID_SKGE_PMD:
- *pBufPtr = pAC->Pnmi.PMD;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_CONNECTOR:
- *pBufPtr = pAC->Pnmi.Connector;
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_TYPE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- continue;
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
- SK_PNMI_STORE_U32(pBufPtr, Val32);
- }
- }
- else { /* DualNetMode */
-
- Val32 = pAC->GIni.GP[NetIndex].PhyType;
- SK_PNMI_STORE_U32(pBufPtr, Val32);
- }
- Offset += sizeof(SK_U32);
- break;
-
- case OID_SKGE_LINK_CAP:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_LINK_MODE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_LINK_MODE_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr =
- CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_LINK_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_FLOWCTRL_CAP:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_FLOWCTRL_MODE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_FLOWCTRL_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_OPERATION_CAP:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_OPERATION_MODE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_OPERATION_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
- }
- }
- else {
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SPEED_CAP:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical ports */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SPEED_MODE:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SPEED_STATUS:
- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
- if (LogPortIndex == 0) {
- /* Get value for virtual port */
- VirtualConf(pAC, IoC, Id, pBufPtr);
- }
- else {
- /* Get value for physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
-
- *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
- }
- }
- else { /* DualNetMode */
-
- *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_MTU:
- Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
- SK_PNMI_STORE_U32(pBufPtr, Val32);
- Offset += sizeof(SK_U32);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("MacPrivateConf: Unknown OID should be handled before"));
-
- pAC->Pnmi.SirqUpdatedFlag --;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- *pLen = Offset;
- pAC->Pnmi.SirqUpdatedFlag --;
-
- return (SK_PNMI_ERR_OK);
- }
-
- /*
- * From here SET or PRESET action. Check if the passed
- * buffer length is plausible.
- */
- switch (Id) {
-
- case OID_SKGE_LINK_MODE:
- case OID_SKGE_FLOWCTRL_MODE:
- case OID_SKGE_PHY_OPERATION_MODE:
- case OID_SKGE_SPEED_MODE:
- if (*pLen < Limit - LogPortIndex) {
-
- *pLen = Limit - LogPortIndex;
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- if (*pLen != Limit - LogPortIndex) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- break;
-
- case OID_SKGE_MTU:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- if (*pLen != sizeof(SK_U32)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /*
- * Perform preset or set
- */
- Offset = 0;
- for (; LogPortIndex < Limit; LogPortIndex ++) {
-
- switch (Id) {
-
- case OID_SKGE_LINK_MODE:
- /* Check the value range */
- Val8 = *(pBuf + Offset);
- if (Val8 == 0) {
-
- Offset += sizeof(char);
- break;
- }
- if (Val8 < SK_LMODE_HALF ||
- (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
- (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- if (LogPortIndex == 0) {
-
- /*
- * The virtual port consists of all currently
- * active ports. Find them and send an event
- * with the new link mode to SIRQ.
- */
- for (PhysPortIndex = 0;
- PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (!pAC->Pnmi.Port[PhysPortIndex].
- ActiveFlag) {
-
- continue;
- }
-
- EventParam.Para32[0] = PhysPortIndex;
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_LMODE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR043,
- SK_PNMI_ERR043MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- }
- else {
- /*
- * Send an event with the new link mode to
- * the SIRQ module.
- */
- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR043,
- SK_PNMI_ERR043MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_FLOWCTRL_MODE:
- /* Check the value range */
- Val8 = *(pBuf + Offset);
- if (Val8 == 0) {
-
- Offset += sizeof(char);
- break;
- }
- if (Val8 < SK_FLOW_MODE_NONE ||
- (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
- (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- if (LogPortIndex == 0) {
-
- /*
- * The virtual port consists of all currently
- * active ports. Find them and send an event
- * with the new flow control mode to SIRQ.
- */
- for (PhysPortIndex = 0;
- PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (!pAC->Pnmi.Port[PhysPortIndex].
- ActiveFlag) {
-
- continue;
- }
-
- EventParam.Para32[0] = PhysPortIndex;
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_FLOWMODE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR044,
- SK_PNMI_ERR044MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- }
- else {
- /*
- * Send an event with the new flow control
- * mode to the SIRQ module.
- */
- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_FLOWMODE, EventParam)
- > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR044,
- SK_PNMI_ERR044MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_PHY_OPERATION_MODE :
- /* Check the value range */
- Val8 = *(pBuf + Offset);
- if (Val8 == 0) {
- /* mode of this port remains unchanged */
- Offset += sizeof(char);
- break;
- }
- if (Val8 < SK_MS_MODE_AUTO ||
- (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
- (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- if (LogPortIndex == 0) {
-
- /*
- * The virtual port consists of all currently
- * active ports. Find them and send an event
- * with new master/slave (role) mode to SIRQ.
- */
- for (PhysPortIndex = 0;
- PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (!pAC->Pnmi.Port[PhysPortIndex].
- ActiveFlag) {
-
- continue;
- }
-
- EventParam.Para32[0] = PhysPortIndex;
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_ROLE,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR042,
- SK_PNMI_ERR042MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- }
- else {
- /*
- * Send an event with the new master/slave
- * (role) mode to the SIRQ module.
- */
- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_ROLE, EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR042,
- SK_PNMI_ERR042MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_SPEED_MODE:
- /* Check the value range */
- Val8 = *(pBuf + Offset);
- if (Val8 == 0) {
-
- Offset += sizeof(char);
- break;
- }
- if (Val8 < (SK_LSPEED_AUTO) ||
- (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
- (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- if (LogPortIndex == 0) {
-
- /*
- * The virtual port consists of all currently
- * active ports. Find them and send an event
- * with the new flow control mode to SIRQ.
- */
- for (PhysPortIndex = 0;
- PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- continue;
- }
-
- EventParam.Para32[0] = PhysPortIndex;
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_SPEED,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR045,
- SK_PNMI_ERR045MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- }
- else {
- /*
- * Send an event with the new flow control
- * mode to the SIRQ module.
- */
- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
- pAC, LogPortIndex);
- EventParam.Para32[1] = (SK_U32)Val8;
- if (SkGeSirqEvent(pAC, IoC,
- SK_HWEV_SET_SPEED,
- EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW,
- SK_PNMI_ERR045,
- SK_PNMI_ERR045MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- Offset += sizeof(char);
- break;
-
- case OID_SKGE_MTU :
- /* Check the value range */
- Val32 = *(SK_U32*)(pBuf + Offset);
- if (Val32 == 0) {
- /* mtu of this port remains unchanged */
- Offset += sizeof(SK_U32);
- break;
- }
- if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- /* The preset ends here */
- if (Action == SK_PNMI_PRESET) {
- return (SK_PNMI_ERR_OK);
- }
-
- if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
- return (SK_PNMI_ERR_GENERAL);
- }
-
- Offset += sizeof(SK_U32);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
- ("MacPrivateConf: Unknown OID should be handled before set"));
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * Monitor - OID handler function for RLMT_MONITOR_XXX
- *
- * Description:
- * Because RLMT currently does not support the monitoring of
- * remote adapter cards, we return always an empty table.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
- * value range.
- * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-PNMI_STATIC int Monitor(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- unsigned int Index;
- unsigned int Limit;
- unsigned int Offset;
- unsigned int Entries;
-
-
- /*
- * Calculate instance if wished.
- */
- /* XXX Not yet implemented. Return always an empty table. */
- Entries = 0;
-
- if ((Instance != (SK_U32)(-1))) {
-
- if ((Instance < 1) || (Instance > Entries)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- Index = (unsigned int)Instance - 1;
- Limit = (unsigned int)Instance;
- }
- else {
- Index = 0;
- Limit = Entries;
- }
-
- /*
- * Get/Set value
- */
- if (Action == SK_PNMI_GET) {
-
- for (Offset=0; Index < Limit; Index ++) {
-
- switch (Id) {
-
- case OID_SKGE_RLMT_MONITOR_INDEX:
- case OID_SKGE_RLMT_MONITOR_ADDR:
- case OID_SKGE_RLMT_MONITOR_ERRS:
- case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
- case OID_SKGE_RLMT_MONITOR_ADMIN:
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
- SK_PNMI_ERR046MSG);
-
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- }
- *pLen = Offset;
- }
- else {
- /* Only MONITOR_ADMIN can be set */
- if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_READ_ONLY);
- }
-
- /* Check if the length is plausible */
- if (*pLen < (Limit - Index)) {
-
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- /* Okay, we have a wide value range */
- if (*pLen != (Limit - Index)) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-/*
- for (Offset=0; Index < Limit; Index ++) {
- }
-*/
-/*
- * XXX Not yet implemented. Return always BAD_VALUE, because the table
- * is empty.
- */
- *pLen = 0;
- return (SK_PNMI_ERR_BAD_VALUE);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * VirtualConf - Calculates the values of configuration OIDs for virtual port
- *
- * Description:
- * We handle here the get of the configuration group OIDs, which are
- * a little bit complicated. The virtual port consists of all currently
- * active physical ports. If multiple ports are active and configured
- * differently we get in some trouble to return a single value. So we
- * get the value of the first active port and compare it with that of
- * the other active ports. If they are not the same, we return a value
- * that indicates that the state is indeterminated.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void VirtualConf(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf) /* Buffer used for the management data transfer */
-{
- unsigned int PhysPortMax;
- unsigned int PhysPortIndex;
- SK_U8 Val8;
- SK_U32 Val32;
- SK_BOOL PortActiveFlag;
- SK_GEPORT *pPrt;
-
- *pBuf = 0;
- PortActiveFlag = SK_FALSE;
- PhysPortMax = pAC->GIni.GIMacsFound;
-
- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- pPrt = &pAC->GIni.GP[PhysPortIndex];
-
- /* Check if the physical port is active */
- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- continue;
- }
-
- PortActiveFlag = SK_TRUE;
-
- switch (Id) {
-
- case OID_SKGE_PHY_TYPE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
- Val32 = pPrt->PhyType;
- SK_PNMI_STORE_U32(pBuf, Val32);
- continue;
- }
-
- case OID_SKGE_LINK_CAP:
-
- /*
- * Different capabilities should not happen, but
- * in the case of the cases OR them all together.
- * From a curious point of view the virtual port
- * is capable of all found capabilities.
- */
- *pBuf |= pPrt->PLinkCap;
- break;
-
- case OID_SKGE_LINK_MODE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PLinkModeConf;
- continue;
- }
-
- /*
- * If we find an active port with a different link
- * mode than the first one we return a value that
- * indicates that the link mode is indeterminated.
- */
- if (*pBuf != pPrt->PLinkModeConf) {
-
- *pBuf = SK_LMODE_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_LINK_MODE_STATUS:
- /* Get the link mode of the physical port */
- Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
-
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = Val8;
- continue;
- }
-
- /*
- * If we find an active port with a different link
- * mode status than the first one we return a value
- * that indicates that the link mode status is
- * indeterminated.
- */
- if (*pBuf != Val8) {
-
- *pBuf = SK_LMODE_STAT_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_LINK_STATUS:
- /* Get the link status of the physical port */
- Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
-
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = Val8;
- continue;
- }
-
- /*
- * If we find an active port with a different link
- * status than the first one, we return a value
- * that indicates that the link status is
- * indeterminated.
- */
- if (*pBuf != Val8) {
-
- *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_FLOWCTRL_CAP:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PFlowCtrlCap;
- continue;
- }
-
- /*
- * From a curious point of view the virtual port
- * is capable of all found capabilities.
- */
- *pBuf |= pPrt->PFlowCtrlCap;
- break;
-
- case OID_SKGE_FLOWCTRL_MODE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PFlowCtrlMode;
- continue;
- }
-
- /*
- * If we find an active port with a different flow
- * control mode than the first one, we return a value
- * that indicates that the mode is indeterminated.
- */
- if (*pBuf != pPrt->PFlowCtrlMode) {
-
- *pBuf = SK_FLOW_MODE_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_FLOWCTRL_STATUS:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PFlowCtrlStatus;
- continue;
- }
-
- /*
- * If we find an active port with a different flow
- * control status than the first one, we return a
- * value that indicates that the status is
- * indeterminated.
- */
- if (*pBuf != pPrt->PFlowCtrlStatus) {
-
- *pBuf = SK_FLOW_STAT_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_PHY_OPERATION_CAP:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PMSCap;
- continue;
- }
-
- /*
- * From a curious point of view the virtual port
- * is capable of all found capabilities.
- */
- *pBuf |= pPrt->PMSCap;
- break;
-
- case OID_SKGE_PHY_OPERATION_MODE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PMSMode;
- continue;
- }
-
- /*
- * If we find an active port with a different master/
- * slave mode than the first one, we return a value
- * that indicates that the mode is indeterminated.
- */
- if (*pBuf != pPrt->PMSMode) {
-
- *pBuf = SK_MS_MODE_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_PHY_OPERATION_STATUS:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PMSStatus;
- continue;
- }
-
- /*
- * If we find an active port with a different master/
- * slave status than the first one, we return a
- * value that indicates that the status is
- * indeterminated.
- */
- if (*pBuf != pPrt->PMSStatus) {
-
- *pBuf = SK_MS_STAT_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_SPEED_MODE:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PLinkSpeed;
- continue;
- }
-
- /*
- * If we find an active port with a different flow
- * control mode than the first one, we return a value
- * that indicates that the mode is indeterminated.
- */
- if (*pBuf != pPrt->PLinkSpeed) {
-
- *pBuf = SK_LSPEED_INDETERMINATED;
- }
- break;
-
- case OID_SKGE_SPEED_STATUS:
- /* Check if it is the first active port */
- if (*pBuf == 0) {
-
- *pBuf = pPrt->PLinkSpeedUsed;
- continue;
- }
-
- /*
- * If we find an active port with a different flow
- * control status than the first one, we return a
- * value that indicates that the status is
- * indeterminated.
- */
- if (*pBuf != pPrt->PLinkSpeedUsed) {
-
- *pBuf = SK_LSPEED_STAT_INDETERMINATED;
- }
- break;
- }
- }
-
- /*
- * If no port is active return an indeterminated answer
- */
- if (!PortActiveFlag) {
-
- switch (Id) {
-
- case OID_SKGE_LINK_CAP:
- *pBuf = SK_LMODE_CAP_INDETERMINATED;
- break;
-
- case OID_SKGE_LINK_MODE:
- *pBuf = SK_LMODE_INDETERMINATED;
- break;
-
- case OID_SKGE_LINK_MODE_STATUS:
- *pBuf = SK_LMODE_STAT_INDETERMINATED;
- break;
-
- case OID_SKGE_LINK_STATUS:
- *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
- break;
-
- case OID_SKGE_FLOWCTRL_CAP:
- case OID_SKGE_FLOWCTRL_MODE:
- *pBuf = SK_FLOW_MODE_INDETERMINATED;
- break;
-
- case OID_SKGE_FLOWCTRL_STATUS:
- *pBuf = SK_FLOW_STAT_INDETERMINATED;
- break;
-
- case OID_SKGE_PHY_OPERATION_CAP:
- *pBuf = SK_MS_CAP_INDETERMINATED;
- break;
-
- case OID_SKGE_PHY_OPERATION_MODE:
- *pBuf = SK_MS_MODE_INDETERMINATED;
- break;
-
- case OID_SKGE_PHY_OPERATION_STATUS:
- *pBuf = SK_MS_STAT_INDETERMINATED;
- break;
- case OID_SKGE_SPEED_CAP:
- *pBuf = SK_LSPEED_CAP_INDETERMINATED;
- break;
-
- case OID_SKGE_SPEED_MODE:
- *pBuf = SK_LSPEED_INDETERMINATED;
- break;
-
- case OID_SKGE_SPEED_STATUS:
- *pBuf = SK_LSPEED_STAT_INDETERMINATED;
- break;
- }
- }
-}
-
-/*****************************************************************************
- *
- * CalculateLinkStatus - Determins the link status of a physical port
- *
- * Description:
- * Determins the link status the following way:
- * LSTAT_PHY_DOWN: Link is down
- * LSTAT_AUTONEG: Auto-negotiation failed
- * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port
- * logically up.
- * LSTAT_LOG_UP: RLMT marked the port as up
- *
- * Returns:
- * Link status of physical port
- */
-PNMI_STATIC SK_U8 CalculateLinkStatus(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int PhysPortIndex) /* Physical port index */
-{
- SK_U8 Result;
-
- if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
-
- Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
- }
- else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
-
- Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
- }
- else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
-
- Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
- }
- else {
- Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
- }
-
- return (Result);
-}
-
-/*****************************************************************************
- *
- * CalculateLinkModeStatus - Determins the link mode status of a phys. port
- *
- * Description:
- * The COMMON module only tells us if the mode is half or full duplex.
- * But in the decade of auto sensing it is useful for the user to
- * know if the mode was negotiated or forced. Therefore we have a
- * look to the mode, which was last used by the negotiation process.
- *
- * Returns:
- * The link mode status
- */
-PNMI_STATIC SK_U8 CalculateLinkModeStatus(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int PhysPortIndex) /* Physical port index */
-{
- SK_U8 Result;
-
- /* Get the current mode, which can be full or half duplex */
- Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
-
- /* Check if no valid mode could be found (link is down) */
- if (Result < SK_LMODE_STAT_HALF) {
-
- Result = SK_LMODE_STAT_UNKNOWN;
- }
- else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
-
- /*
- * Auto-negotiation was used to bring up the link. Change
- * the already found duplex status that it indicates
- * auto-negotiation was involved.
- */
- if (Result == SK_LMODE_STAT_HALF) {
-
- Result = SK_LMODE_STAT_AUTOHALF;
- }
- else if (Result == SK_LMODE_STAT_FULL) {
-
- Result = SK_LMODE_STAT_AUTOFULL;
- }
- }
-
- return (Result);
-}
-
-/*****************************************************************************
- *
- * GetVpdKeyArr - Obtain an array of VPD keys
- *
- * Description:
- * Read the VPD keys and build an array of VPD keys, which are
- * easy to access.
- *
- * Returns:
- * SK_PNMI_ERR_OK Task successfully performed.
- * SK_PNMI_ERR_GENERAL Something went wrong.
- */
-PNMI_STATIC int GetVpdKeyArr(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-char *pKeyArr, /* Ptr KeyArray */
-unsigned int KeyArrLen, /* Length of array in bytes */
-unsigned int *pKeyNo) /* Number of keys */
-{
- unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE;
- char BufKeys[SK_PNMI_VPD_BUFSIZE];
- unsigned int StartOffset;
- unsigned int Offset;
- int Index;
- int Ret;
-
-
- SK_MEMSET(pKeyArr, 0, KeyArrLen);
-
- /*
- * Get VPD key list
- */
- Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
- (int *)pKeyNo);
- if (Ret > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
- SK_PNMI_ERR014MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
- /* If no keys are available return now */
- if (*pKeyNo == 0 || BufKeysLen == 0) {
-
- return (SK_PNMI_ERR_OK);
- }
- /*
- * If the key list is too long for us trunc it and give a
- * errorlog notification. This case should not happen because
- * the maximum number of keys is limited due to RAM limitations
- */
- if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
- SK_PNMI_ERR015MSG);
-
- *pKeyNo = SK_PNMI_VPD_ENTRIES;
- }
-
- /*
- * Now build an array of fixed string length size and copy
- * the keys together.
- */
- for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
- Offset ++) {
-
- if (BufKeys[Offset] != 0) {
-
- continue;
- }
-
- if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
- SK_PNMI_ERR016MSG);
- return (SK_PNMI_ERR_GENERAL);
- }
-
- SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
- &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
-
- Index ++;
- StartOffset = Offset + 1;
- }
-
- /* Last key not zero terminated? Get it anyway */
- if (StartOffset < Offset) {
-
- SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
- &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * SirqUpdate - Let the SIRQ update its internal values
- *
- * Description:
- * Just to be sure that the SIRQ module holds its internal data
- * structures up to date, we send an update event before we make
- * any access.
- *
- * Returns:
- * SK_PNMI_ERR_OK Task successfully performed.
- * SK_PNMI_ERR_GENERAL Something went wrong.
- */
-PNMI_STATIC int SirqUpdate(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC) /* IO context handle */
-{
- SK_EVPARA EventParam;
-
-
- /* Was the module already updated during the current PNMI call? */
- if (pAC->Pnmi.SirqUpdatedFlag > 0) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Send an synchronuous update event to the module */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
- SK_PNMI_ERR047MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * RlmtUpdate - Let the RLMT update its internal values
- *
- * Description:
- * Just to be sure that the RLMT module holds its internal data
- * structures up to date, we send an update event before we make
- * any access.
- *
- * Returns:
- * SK_PNMI_ERR_OK Task successfully performed.
- * SK_PNMI_ERR_GENERAL Something went wrong.
- */
-PNMI_STATIC int RlmtUpdate(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
-{
- SK_EVPARA EventParam;
-
-
- /* Was the module already updated during the current PNMI call? */
- if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Send an synchronuous update event to the module */
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
- EventParam.Para32[0] = NetIndex;
- EventParam.Para32[1] = (SK_U32)-1;
- if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
- SK_PNMI_ERR048MSG);
-
- return (SK_PNMI_ERR_GENERAL);
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * MacUpdate - Force the XMAC to output the current statistic
- *
- * Description:
- * The XMAC holds its statistic internally. To obtain the current
- * values we must send a command so that the statistic data will
- * be written to a predefined memory area on the adapter.
- *
- * Returns:
- * SK_PNMI_ERR_OK Task successfully performed.
- * SK_PNMI_ERR_GENERAL Something went wrong.
- */
-PNMI_STATIC int MacUpdate(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int FirstMac, /* Index of the first Mac to be updated */
-unsigned int LastMac) /* Index of the last Mac to be updated */
-{
- unsigned int MacIndex;
-
- /*
- * Were the statistics already updated during the
- * current PNMI call?
- */
- if (pAC->Pnmi.MacUpdatedFlag > 0) {
-
- return (SK_PNMI_ERR_OK);
- }
-
- /* Send an update command to all MACs specified */
- for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
-
- /*
- * 2002-09-13 pweber: Freeze the current SW counters.
- * (That should be done as close as
- * possible to the update of the
- * HW counters)
- */
- if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
- pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
- }
-
- /* 2002-09-13 pweber: Update the HW counter */
- if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
-
- return (SK_PNMI_ERR_GENERAL);
- }
- }
-
- return (SK_PNMI_ERR_OK);
-}
-
-/*****************************************************************************
- *
- * GetStatVal - Retrieve an XMAC statistic counter
- *
- * Description:
- * Retrieves the statistic counter of a virtual or physical port. The
- * virtual port is identified by the index 0. It consists of all
- * currently active ports. To obtain the counter value for this port
- * we must add the statistic counter of all active ports. To grant
- * continuous counter values for the virtual port even when port
- * switches occur we must additionally add a delta value, which was
- * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
- *
- * Returns:
- * Requested statistic value
- */
-PNMI_STATIC SK_U64 GetStatVal(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int LogPortIndex, /* Index of the logical Port to be processed */
-unsigned int StatIndex, /* Index to statistic value */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
-{
- unsigned int PhysPortIndex;
- unsigned int PhysPortMax;
- SK_U64 Val = 0;
-
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
-
- PhysPortIndex = NetIndex;
-
- Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
- }
- else { /* Single Net mode */
-
- if (LogPortIndex == 0) {
-
- PhysPortMax = pAC->GIni.GIMacsFound;
-
- /* Add counter of all active ports */
- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
- PhysPortIndex ++) {
-
- if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
-
- Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
- }
- }
-
- /* Correct value because of port switches */
- Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
- }
- else {
- /* Get counter value of physical port */
- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
-
- Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
- }
- }
- return (Val);
-}
-
-/*****************************************************************************
- *
- * GetPhysStatVal - Get counter value for physical port
- *
- * Description:
- * Builds a 64bit counter value. Except for the octet counters
- * the lower 32bit are counted in hardware and the upper 32bit
- * in software by monitoring counter overflow interrupts in the
- * event handler. To grant continous counter values during XMAC
- * resets (caused by a workaround) we must add a delta value.
- * The delta was calculated in the event handler when a
- * SK_PNMI_EVT_XMAC_RESET was received.
- *
- * Returns:
- * Counter value
- */
-PNMI_STATIC SK_U64 GetPhysStatVal(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-unsigned int PhysPortIndex, /* Index of the logical Port to be processed */
-unsigned int StatIndex) /* Index to statistic value */
-{
- SK_U64 Val = 0;
- SK_U32 LowVal = 0;
- SK_U32 HighVal = 0;
- SK_U16 Word;
- int MacType;
- unsigned int HelpIndex;
- SK_GEPORT *pPrt;
-
- SK_PNMI_PORT *pPnmiPrt;
- SK_GEMACFUNC *pFnMac;
-
- pPrt = &pAC->GIni.GP[PhysPortIndex];
-
- MacType = pAC->GIni.GIMacType;
-
- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
- if (MacType == SK_MAC_XMAC) {
- pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
- }
- else {
- pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
- }
-
- pFnMac = &pAC->GIni.GIFunc;
-
- switch (StatIndex) {
- case SK_PNMI_HTX:
- if (MacType == SK_MAC_GMAC) {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
- &LowVal);
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
- &HighVal);
- LowVal += HighVal;
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
- &HighVal);
- LowVal += HighVal;
- }
- else {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- }
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HRX:
- if (MacType == SK_MAC_GMAC) {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
- &LowVal);
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
- &HighVal);
- LowVal += HighVal;
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
- &HighVal);
- LowVal += HighVal;
- }
- else {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- }
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HTX_OCTET:
- case SK_PNMI_HRX_OCTET:
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &HighVal);
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex + 1][MacType].Reg,
- &LowVal);
- break;
-
- case SK_PNMI_HTX_BURST:
- case SK_PNMI_HTX_EXCESS_DEF:
- case SK_PNMI_HTX_CARRIER:
- /* Not supported by GMAC */
- if (MacType == SK_MAC_GMAC) {
- return (Val);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HTX_MACC:
- /* GMAC only supports PAUSE MAC control frames */
- if (MacType == SK_MAC_GMAC) {
- HelpIndex = SK_PNMI_HTX_PMACC;
- }
- else {
- HelpIndex = StatIndex;
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[HelpIndex][MacType].Reg,
- &LowVal);
-
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HTX_COL:
- case SK_PNMI_HRX_UNDERSIZE:
- /* Not supported by XMAC */
- if (MacType == SK_MAC_XMAC) {
- return (Val);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HTX_DEFFERAL:
- /* Not supported by GMAC */
- if (MacType == SK_MAC_GMAC) {
- return (Val);
- }
-
- /*
- * XMAC counts frames with deferred transmission
- * even in full-duplex mode.
- *
- * In full-duplex mode the counter remains constant!
- */
- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
- (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
-
- LowVal = 0;
- HighVal = 0;
- }
- else {
- /* Otherwise get contents of hardware register */
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- }
- break;
-
- case SK_PNMI_HRX_BADOCTET:
- /* Not supported by XMAC */
- if (MacType == SK_MAC_XMAC) {
- return (Val);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &HighVal);
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex + 1][MacType].Reg,
- &LowVal);
- break;
-
- case SK_PNMI_HTX_OCTETLOW:
- case SK_PNMI_HRX_OCTETLOW:
- case SK_PNMI_HRX_BADOCTETLOW:
- return (Val);
-
- case SK_PNMI_HRX_LONGFRAMES:
- /* For XMAC the SW counter is managed by PNMI */
- if (MacType == SK_MAC_XMAC) {
- return (pPnmiPrt->StatRxLongFrameCts);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HRX_TOO_LONG:
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
-
- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
- if (MacType == SK_MAC_GMAC) {
- /* For GMAC the SW counter is additionally managed by PNMI */
- Val += pPnmiPrt->StatRxFrameTooLongCts;
- }
- else {
- /*
- * Frames longer than IEEE 802.3 frame max size are counted
- * by XMAC in frame_too_long counter even reception of long
- * frames was enabled and the frame was correct.
- * So correct the value by subtracting RxLongFrame counter.
- */
- Val -= pPnmiPrt->StatRxLongFrameCts;
- }
-
- LowVal = (SK_U32)Val;
- HighVal = (SK_U32)(Val >> 32);
- break;
-
- case SK_PNMI_HRX_SHORTS:
- /* Not supported by GMAC */
- if (MacType == SK_MAC_GMAC) {
- /* GM_RXE_FRAG?? */
- return (Val);
- }
-
- /*
- * XMAC counts short frame errors even if link down (#10620)
- *
- * If link-down the counter remains constant
- */
- if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
-
- /* Otherwise get incremental difference */
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
-
- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
- Val -= pPnmiPrt->RxShortZeroMark;
-
- LowVal = (SK_U32)Val;
- HighVal = (SK_U32)(Val >> 32);
- }
- break;
-
- case SK_PNMI_HRX_MACC:
- case SK_PNMI_HRX_MACC_UNKWN:
- case SK_PNMI_HRX_BURST:
- case SK_PNMI_HRX_MISSED:
- case SK_PNMI_HRX_FRAMING:
- case SK_PNMI_HRX_CARRIER:
- case SK_PNMI_HRX_IRLENGTH:
- case SK_PNMI_HRX_SYMBOL:
- case SK_PNMI_HRX_CEXT:
- /* Not supported by GMAC */
- if (MacType == SK_MAC_GMAC) {
- return (Val);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- case SK_PNMI_HRX_PMACC_ERR:
- /* For GMAC the SW counter is managed by PNMI */
- if (MacType == SK_MAC_GMAC) {
- return (pPnmiPrt->StatRxPMaccErr);
- }
-
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
-
- /* SW counter managed by PNMI */
- case SK_PNMI_HTX_SYNC:
- LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
- HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
- break;
-
- /* SW counter managed by PNMI */
- case SK_PNMI_HTX_SYNC_OCTET:
- LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
- HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
- break;
-
- case SK_PNMI_HRX_FCS:
- /*
- * Broadcom filters FCS errors and counts it in
- * Receive Error Counter register
- */
- if (pPrt->PhyType == SK_PHY_BCOM) {
- /* do not read while not initialized (PHY_READ hangs!)*/
- if (pPrt->PState != SK_PRT_RESET) {
- SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
-
- LowVal = Word;
- }
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- }
- else {
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- }
- break;
-
- default:
- (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
- StatAddr[StatIndex][MacType].Reg,
- &LowVal);
- HighVal = pPnmiPrt->CounterHigh[StatIndex];
- break;
- }
-
- Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
-
- /* Correct value because of possible XMAC reset. XMAC Errata #2 */
- Val += pPnmiPrt->CounterOffset[StatIndex];
-
- return (Val);
-}
-
-/*****************************************************************************
- *
- * ResetCounter - Set all counters and timestamps to zero
- *
- * Description:
- * Notifies other common modules which store statistic data to
- * reset their counters and finally reset our own counters.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void ResetCounter(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-SK_U32 NetIndex)
-{
- unsigned int PhysPortIndex;
- SK_EVPARA EventParam;
-
-
- SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
-
- /* Notify sensor module */
- SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
-
- /* Notify RLMT module */
- EventParam.Para32[0] = NetIndex;
- EventParam.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
- EventParam.Para32[1] = 0;
-
- /* Notify SIRQ module */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
-
- /* Notify CSUM module */
-#ifdef SK_USE_CSUM
- EventParam.Para32[0] = NetIndex;
- EventParam.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
- EventParam);
-#endif /* SK_USE_CSUM */
-
- /* Clear XMAC statistic */
- for (PhysPortIndex = 0; PhysPortIndex <
- (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
-
- (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
-
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
- 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- CounterOffset, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].CounterOffset));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
- 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].StatSyncOctetsCts));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].StatRxLongFrameCts));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].StatRxFrameTooLongCts));
- SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
- StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
- PhysPortIndex].StatRxPMaccErr));
- }
-
- /*
- * Clear local statistics
- */
- SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
- sizeof(pAC->Pnmi.VirtualCounterOffset));
- pAC->Pnmi.RlmtChangeCts = 0;
- pAC->Pnmi.RlmtChangeTime = 0;
- SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
- sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
- pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
- pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
- pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
- pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
- pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
- pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
- pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
- pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
- pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
- pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
- pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
- pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
-}
-
-/*****************************************************************************
- *
- * GetTrapEntry - Get an entry in the trap buffer
- *
- * Description:
- * The trap buffer stores various events. A user application somehow
- * gets notified that an event occured and retrieves the trap buffer
- * contens (or simply polls the buffer). The buffer is organized as
- * a ring which stores the newest traps at the beginning. The oldest
- * traps are overwritten by the newest ones. Each trap entry has a
- * unique number, so that applications may detect new trap entries.
- *
- * Returns:
- * A pointer to the trap entry
- */
-PNMI_STATIC char* GetTrapEntry(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_U32 TrapId, /* SNMP ID of the trap */
-unsigned int Size) /* Space needed for trap entry */
-{
- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
- unsigned int BufFree = pAC->Pnmi.TrapBufFree;
- unsigned int Beg = pAC->Pnmi.TrapQueueBeg;
- unsigned int End = pAC->Pnmi.TrapQueueEnd;
- char *pBuf = &pAC->Pnmi.TrapBuf[0];
- int Wrap;
- unsigned int NeededSpace;
- unsigned int EntrySize;
- SK_U32 Val32;
- SK_U64 Val64;
-
-
- /* Last byte of entry will get a copy of the entry length */
- Size ++;
-
- /*
- * Calculate needed buffer space */
- if (Beg >= Size) {
-
- NeededSpace = Size;
- Wrap = SK_FALSE;
- }
- else {
- NeededSpace = Beg + Size;
- Wrap = SK_TRUE;
- }
-
- /*
- * Check if enough buffer space is provided. Otherwise
- * free some entries. Leave one byte space between begin
- * and end of buffer to make it possible to detect whether
- * the buffer is full or empty
- */
- while (BufFree < NeededSpace + 1) {
-
- if (End == 0) {
-
- End = SK_PNMI_TRAP_QUEUE_LEN;
- }
-
- EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
- BufFree += EntrySize;
- End -= EntrySize;
-#ifdef DEBUG
- SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
-#endif /* DEBUG */
- if (End == BufPad) {
-#ifdef DEBUG
- SK_MEMSET(pBuf, (char)(-1), End);
-#endif /* DEBUG */
- BufFree += End;
- End = 0;
- BufPad = 0;
- }
- }
-
- /*
- * Insert new entry as first entry. Newest entries are
- * stored at the beginning of the queue.
- */
- if (Wrap) {
-
- BufPad = Beg;
- Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
- }
- else {
- Beg = Beg - Size;
- }
- BufFree -= NeededSpace;
-
- /* Save the current offsets */
- pAC->Pnmi.TrapQueueBeg = Beg;
- pAC->Pnmi.TrapQueueEnd = End;
- pAC->Pnmi.TrapBufPad = BufPad;
- pAC->Pnmi.TrapBufFree = BufFree;
-
- /* Initialize the trap entry */
- *(pBuf + Beg + Size - 1) = (char)Size;
- *(pBuf + Beg) = (char)Size;
- Val32 = (pAC->Pnmi.TrapUnique) ++;
- SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
- SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
- Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
- SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
-
- return (pBuf + Beg);
-}
-
-/*****************************************************************************
- *
- * CopyTrapQueue - Copies the trap buffer for the TRAP OID
- *
- * Description:
- * On a query of the TRAP OID the trap buffer contents will be
- * copied continuously to the request buffer, which must be large
- * enough. No length check is performed.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void CopyTrapQueue(
-SK_AC *pAC, /* Pointer to adapter context */
-char *pDstBuf) /* Buffer to which the queued traps will be copied */
-{
- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
- unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
- unsigned int End = pAC->Pnmi.TrapQueueEnd;
- char *pBuf = &pAC->Pnmi.TrapBuf[0];
- unsigned int Len;
- unsigned int DstOff = 0;
-
-
- while (Trap != End) {
-
- Len = (unsigned int)*(pBuf + Trap);
-
- /*
- * Last byte containing a copy of the length will
- * not be copied.
- */
- *(pDstBuf + DstOff) = (char)(Len - 1);
- SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
- DstOff += Len - 1;
-
- Trap += Len;
- if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
- Trap = BufPad;
- }
- }
-}
-
-/*****************************************************************************
- *
- * GetTrapQueueLen - Get the length of the trap buffer
- *
- * Description:
- * Evaluates the number of currently stored traps and the needed
- * buffer size to retrieve them.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void GetTrapQueueLen(
-SK_AC *pAC, /* Pointer to adapter context */
-unsigned int *pLen, /* Length in Bytes of all queued traps */
-unsigned int *pEntries) /* Returns number of trapes stored in queue */
-{
- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
- unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
- unsigned int End = pAC->Pnmi.TrapQueueEnd;
- char *pBuf = &pAC->Pnmi.TrapBuf[0];
- unsigned int Len;
- unsigned int Entries = 0;
- unsigned int TotalLen = 0;
-
-
- while (Trap != End) {
-
- Len = (unsigned int)*(pBuf + Trap);
- TotalLen += Len - 1;
- Entries ++;
-
- Trap += Len;
- if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
-
- Trap = BufPad;
- }
- }
-
- *pEntries = Entries;
- *pLen = TotalLen;
-}
-
-/*****************************************************************************
- *
- * QueueSimpleTrap - Store a simple trap to the trap buffer
- *
- * Description:
- * A simple trap is a trap with now additional data. It consists
- * simply of a trap code.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void QueueSimpleTrap(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_U32 TrapId) /* Type of sensor trap */
-{
- GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
-}
-
-/*****************************************************************************
- *
- * QueueSensorTrap - Stores a sensor trap in the trap buffer
- *
- * Description:
- * Gets an entry in the trap buffer and fills it with sensor related
- * data.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void QueueSensorTrap(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_U32 TrapId, /* Type of sensor trap */
-unsigned int SensorIndex) /* Index of sensor which caused the trap */
-{
- char *pBuf;
- unsigned int Offset;
- unsigned int DescrLen;
- SK_U32 Val32;
-
-
- /* Get trap buffer entry */
- DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
- pBuf = GetTrapEntry(pAC, TrapId,
- SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
- Offset = SK_PNMI_TRAP_SIMPLE_LEN;
-
- /* Store additionally sensor trap related data */
- Val32 = OID_SKGE_SENSOR_INDEX;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- *(pBuf + Offset + 4) = 4;
- Val32 = (SK_U32)SensorIndex;
- SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
- Offset += 9;
-
- Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- *(pBuf + Offset + 4) = (char)DescrLen;
- SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
- DescrLen);
- Offset += DescrLen + 5;
-
- Val32 = OID_SKGE_SENSOR_TYPE;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- *(pBuf + Offset + 4) = 1;
- *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
- Offset += 6;
-
- Val32 = OID_SKGE_SENSOR_VALUE;
- SK_PNMI_STORE_U32(pBuf + Offset, Val32);
- *(pBuf + Offset + 4) = 4;
- Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
- SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
-}
-
-/*****************************************************************************
- *
- * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
- *
- * Description:
- * Nothing further to explain.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void QueueRlmtNewMacTrap(
-SK_AC *pAC, /* Pointer to adapter context */
-unsigned int ActiveMac) /* Index (0..n) of the currently active port */
-{
- char *pBuf;
- SK_U32 Val32;
-
-
- pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
- SK_PNMI_TRAP_RLMT_CHANGE_LEN);
-
- Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
- SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
-}
-
-/*****************************************************************************
- *
- * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
- *
- * Description:
- * Nothing further to explain.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void QueueRlmtPortTrap(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_U32 TrapId, /* Type of RLMT port trap */
-unsigned int PortIndex) /* Index of the port, which changed its state */
-{
- char *pBuf;
- SK_U32 Val32;
-
-
- pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
-
- Val32 = OID_SKGE_RLMT_PORT_INDEX;
- SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
- *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
-}
-
-/*****************************************************************************
- *
- * CopyMac - Copies a MAC address
- *
- * Description:
- * Nothing further to explain.
- *
- * Returns:
- * Nothing
- */
-PNMI_STATIC void CopyMac(
-char *pDst, /* Pointer to destination buffer */
-SK_MAC_ADDR *pMac) /* Pointer of Source */
-{
- int i;
-
-
- for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
-
- *(pDst + i) = pMac->a[i];
- }
-}
-
-#ifdef SK_POWER_MGMT
-/*****************************************************************************
- *
- * PowerManagement - OID handler function of PowerManagement OIDs
- *
- * Description:
- * The code is simple. No description necessary.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-
-PNMI_STATIC int PowerManagement(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* Get/PreSet/Set action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer to which to mgmt data will be retrieved */
-unsigned int *pLen, /* On call: buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
-{
-
- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
-
- /*
- * Check instance. We only handle single instance variables
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
-
- /* Check length */
- switch (Id) {
-
- case OID_PNP_CAPABILITIES:
- if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
-
- *pLen = sizeof(SK_PNP_CAPABILITIES);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_PNP_SET_POWER:
- case OID_PNP_QUERY_POWER:
- if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
- {
- *pLen = sizeof(SK_DEVICE_POWER_STATE);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_PNP_ADD_WAKE_UP_PATTERN:
- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
- if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
-
- *pLen = sizeof(SK_PM_PACKET_PATTERN);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_PNP_ENABLE_WAKE_UP:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
- }
-
- /*
- * Perform action
- */
- if (Action == SK_PNMI_GET) {
-
- /*
- * Get value
- */
- switch (Id) {
-
- case OID_PNP_CAPABILITIES:
- RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
- break;
-
- case OID_PNP_QUERY_POWER:
- /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
- the miniport to indicate whether it can transition its NIC
- to the low-power state.
- A miniport driver must always return NDIS_STATUS_SUCCESS
- to a query of OID_PNP_QUERY_POWER. */
- *pLen = sizeof(SK_DEVICE_POWER_STATE);
- RetCode = SK_PNMI_ERR_OK;
- break;
-
- /* NDIS handles these OIDs as write-only.
- * So in case of get action the buffer with written length = 0
- * is returned
- */
- case OID_PNP_SET_POWER:
- case OID_PNP_ADD_WAKE_UP_PATTERN:
- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
- *pLen = 0;
- RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
- break;
-
- case OID_PNP_ENABLE_WAKE_UP:
- RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
- break;
-
- default:
- RetCode = SK_PNMI_ERR_GENERAL;
- break;
- }
-
- return (RetCode);
- }
-
-
- /*
- * Perform preset or set
- */
-
- /* POWER module does not support PRESET action */
- if (Action == SK_PNMI_PRESET) {
- return (SK_PNMI_ERR_OK);
- }
-
- switch (Id) {
- case OID_PNP_SET_POWER:
- RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);
- break;
-
- case OID_PNP_ADD_WAKE_UP_PATTERN:
- RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);
- break;
-
- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
- RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);
- break;
-
- case OID_PNP_ENABLE_WAKE_UP:
- RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
- break;
-
- default:
- RetCode = SK_PNMI_ERR_READ_ONLY;
- }
-
- return (RetCode);
-}
-#endif /* SK_POWER_MGMT */
-
-#ifdef SK_DIAG_SUPPORT
-/*****************************************************************************
- *
- * DiagActions - OID handler function of Diagnostic driver
- *
- * Description:
- * The code is simple. No description necessary.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-
-PNMI_STATIC int DiagActions(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
-
- SK_U32 DiagStatus;
- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
-
- /*
- * Check instance. We only handle single instance variables.
- */
- if (Instance != (SK_U32)(-1) && Instance != 1) {
-
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- /*
- * Check length.
- */
- switch (Id) {
-
- case OID_SKGE_DIAG_MODE:
- if (*pLen < sizeof(SK_U32)) {
-
- *pLen = sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Perform action. */
-
- /* GET value. */
- if (Action == SK_PNMI_GET) {
-
- switch (Id) {
-
- case OID_SKGE_DIAG_MODE:
- DiagStatus = pAC->Pnmi.DiagAttached;
- SK_PNMI_STORE_U32(pBuf, DiagStatus);
- *pLen = sizeof(SK_U32);
- RetCode = SK_PNMI_ERR_OK;
- break;
-
- default:
- *pLen = 0;
- RetCode = SK_PNMI_ERR_GENERAL;
- break;
- }
- return (RetCode);
- }
-
- /* From here SET or PRESET value. */
-
- /* PRESET value is not supported. */
- if (Action == SK_PNMI_PRESET) {
- return (SK_PNMI_ERR_OK);
- }
-
- /* SET value. */
- switch (Id) {
- case OID_SKGE_DIAG_MODE:
-
- /* Handle the SET. */
- switch (*pBuf) {
-
- /* Attach the DIAG to this adapter. */
- case SK_DIAG_ATTACHED:
- /* Check if we come from running */
- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
- RetCode = SkDrvLeaveDiagMode(pAC);
-
- }
- else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
-
- RetCode = SK_PNMI_ERR_OK;
- }
-
- else {
-
- RetCode = SK_PNMI_ERR_GENERAL;
-
- }
-
- if (RetCode == SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
- }
- break;
-
- /* Enter the DIAG mode in the driver. */
- case SK_DIAG_RUNNING:
- RetCode = SK_PNMI_ERR_OK;
-
- /*
- * If DiagAttached is set, we can tell the driver
- * to enter the DIAG mode.
- */
- if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
- /* If DiagMode is not active, we can enter it. */
- if (!pAC->DiagModeActive) {
-
- RetCode = SkDrvEnterDiagMode(pAC);
- }
- else {
-
- RetCode = SK_PNMI_ERR_GENERAL;
- }
- }
- else {
-
- RetCode = SK_PNMI_ERR_GENERAL;
- }
-
- if (RetCode == SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
- }
- break;
-
- case SK_DIAG_IDLE:
- /* Check if we come from running */
- if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
-
- RetCode = SkDrvLeaveDiagMode(pAC);
-
- }
- else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
-
- RetCode = SK_PNMI_ERR_OK;
- }
-
- else {
-
- RetCode = SK_PNMI_ERR_GENERAL;
-
- }
-
- if (RetCode == SK_PNMI_ERR_OK) {
-
- pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
- }
- break;
-
- default:
- RetCode = SK_PNMI_ERR_BAD_VALUE;
- break;
- }
- break;
-
- default:
- RetCode = SK_PNMI_ERR_GENERAL;
- }
-
- if (RetCode == SK_PNMI_ERR_OK) {
- *pLen = sizeof(SK_U32);
- }
- else {
-
- *pLen = 0;
- }
- return (RetCode);
-}
-#endif /* SK_DIAG_SUPPORT */
-
-/*****************************************************************************
- *
- * Vct - OID handler function of OIDs
- *
- * Description:
- * The code is simple. No description necessary.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was performed successfully.
- * SK_PNMI_ERR_GENERAL A general severe internal error occured.
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
- * the correct data (e.g. a 32bit value is
- * needed, but a 16 bit value was passed).
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter).
- * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed.
- *
- */
-
-PNMI_STATIC int Vct(
-SK_AC *pAC, /* Pointer to adapter context */
-SK_IOC IoC, /* IO context handle */
-int Action, /* GET/PRESET/SET action */
-SK_U32 Id, /* Object ID that is to be processed */
-char *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
-SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */
-unsigned int TableIndex, /* Index to the Id table */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
- SK_GEPORT *pPrt;
- SK_PNMI_VCT *pVctBackupData;
- SK_U32 LogPortMax;
- SK_U32 PhysPortMax;
- SK_U32 PhysPortIndex;
- SK_U32 Limit;
- SK_U32 Offset;
- SK_BOOL Link;
- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
- int i;
- SK_EVPARA Para;
- SK_U32 CableLength;
-
- /*
- * Calculate the port indexes from the instance.
- */
- PhysPortMax = pAC->GIni.GIMacsFound;
- LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
-
- /* Dual net mode? */
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- LogPortMax--;
- }
-
- if ((Instance != (SK_U32) (-1))) {
- /* Check instance range. */
- if ((Instance < 2) || (Instance > LogPortMax)) {
- *pLen = 0;
- return (SK_PNMI_ERR_UNKNOWN_INST);
- }
-
- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
- PhysPortIndex = NetIndex;
- }
- else {
- PhysPortIndex = Instance - 2;
- }
- Limit = PhysPortIndex + 1;
- }
- else {
- /*
- * Instance == (SK_U32) (-1), get all Instances of that OID.
- *
- * Not implemented yet. May be used in future releases.
- */
- PhysPortIndex = 0;
- Limit = PhysPortMax;
- }
-
- pPrt = &pAC->GIni.GP[PhysPortIndex];
- if (pPrt->PHWLinkUp) {
- Link = SK_TRUE;
- }
- else {
- Link = SK_FALSE;
- }
-
- /* Check MAC type */
- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Initialize backup data pointer. */
- pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
-
- /* Check action type */
- if (Action == SK_PNMI_GET) {
- /* Check length */
- switch (Id) {
-
- case OID_SKGE_VCT_GET:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- case OID_SKGE_VCT_STATUS:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /* Get value */
- Offset = 0;
- for (; PhysPortIndex < Limit; PhysPortIndex++) {
- switch (Id) {
-
- case OID_SKGE_VCT_GET:
- if ((Link == SK_FALSE) &&
- (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
- if (RetCode == 0) {
- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
- pAC->Pnmi.VctStatus[PhysPortIndex] |=
- (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
-
- /* Copy results for later use to PNMI struct. */
- for (i = 0; i < 4; i++) {
- if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
- if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
- pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
- }
- }
- if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
- CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
- }
- else {
- CableLength = 0;
- }
- pVctBackupData->PMdiPairLen[i] = CableLength;
- pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
- }
-
- Para.Para32[0] = PhysPortIndex;
- Para.Para32[1] = -1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
- SkEventDispatcher(pAC, IoC);
- }
- else {
- ; /* VCT test is running. */
- }
- }
-
- /* Get all results. */
- CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
- Offset += sizeof(SK_U8);
- *(pBuf + Offset) = pPrt->PCableLen;
- Offset += sizeof(SK_U8);
- for (i = 0; i < 4; i++) {
- SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
- Offset += sizeof(SK_U32);
- }
- for (i = 0; i < 4; i++) {
- *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
- Offset += sizeof(SK_U8);
- }
-
- RetCode = SK_PNMI_ERR_OK;
- break;
-
- case OID_SKGE_VCT_STATUS:
- CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
- Offset += sizeof(SK_U8);
- RetCode = SK_PNMI_ERR_OK;
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- } /* for */
- *pLen = Offset;
- return (RetCode);
-
- } /* if SK_PNMI_GET */
-
- /*
- * From here SET or PRESET action. Check if the passed
- * buffer length is plausible.
- */
-
- /* Check length */
- switch (Id) {
- case OID_SKGE_VCT_SET:
- if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
- *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
- return (SK_PNMI_ERR_TOO_SHORT);
- }
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
-
- /*
- * Perform preset or set.
- */
-
- /* VCT does not support PRESET action. */
- if (Action == SK_PNMI_PRESET) {
- return (SK_PNMI_ERR_OK);
- }
-
- Offset = 0;
- for (; PhysPortIndex < Limit; PhysPortIndex++) {
- switch (Id) {
- case OID_SKGE_VCT_SET: /* Start VCT test. */
- if (Link == SK_FALSE) {
- SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
-
- RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
- if (RetCode == 0) { /* RetCode: 0 => Start! */
- pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
-
- /*
- * Start VCT timer counter.
- */
- SK_MEMSET((char *) &Para, 0, sizeof(Para));
- Para.Para32[0] = PhysPortIndex;
- Para.Para32[1] = -1;
- SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
- 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
- RetCode = SK_PNMI_ERR_OK;
- }
- else { /* RetCode: 2 => Running! */
- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
- RetCode = SK_PNMI_ERR_OK;
- }
- }
- else { /* RetCode: 4 => Link! */
- RetCode = 4;
- SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
- RetCode = SK_PNMI_ERR_OK;
- }
- Offset += sizeof(SK_U32);
- break;
-
- default:
- *pLen = 0;
- return (SK_PNMI_ERR_GENERAL);
- }
- } /* for */
- *pLen = Offset;
- return (RetCode);
-
-} /* Vct */
-
-
-PNMI_STATIC void CheckVctStatus(
-SK_AC *pAC,
-SK_IOC IoC,
-char *pBuf,
-SK_U32 Offset,
-SK_U32 PhysPortIndex)
-{
- SK_GEPORT *pPrt;
- SK_PNMI_VCT *pVctData;
- SK_U32 RetCode;
-
- pPrt = &pAC->GIni.GP[PhysPortIndex];
-
- pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
- pVctData->VctStatus = SK_PNMI_VCT_NONE;
-
- if (!pPrt->PHWLinkUp) {
-
- /* Was a VCT test ever made before? */
- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
- if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
- pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
- }
- else {
- pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
- }
- }
-
- /* Check VCT test status. */
- RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
- if (RetCode == 2) { /* VCT test is running. */
- pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
- }
- else { /* VCT data was copied to pAC here. Check PENDING state. */
- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
- pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
- }
- }
-
- if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
- pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
- }
- }
- else {
-
- /* Was a VCT test ever made before? */
- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
- pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
- pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
- }
-
- /* DSP only valid in 100/1000 modes. */
- if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
- SK_LSPEED_STAT_10MBPS) {
- pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
- }
- }
-} /* CheckVctStatus */
-
-
-/*****************************************************************************
- *
- * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
- * PNMI function depending on the subcommand and
- * returns all data belonging to the complete database
- * or OID request.
- *
- * Description:
- * Looks up the requested subcommand, calls the corresponding handler
- * function and passes all required parameters to it.
- * The function is called by the driver. It is needed to handle the new
- * generic PNMI IOCTL. This IOCTL is given to the driver and contains both
- * the OID and a subcommand to decide what kind of request has to be done.
- *
- * Returns:
- * SK_PNMI_ERR_OK The request was successfully performed
- * SK_PNMI_ERR_GENERAL A general severe internal error occured
- * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
- * the data.
- * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
- * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
- * exist (e.g. port instance 3 on a two port
- * adapter.
- */
-int SkPnmiGenIoctl(
-SK_AC *pAC, /* Pointer to adapter context struct */
-SK_IOC IoC, /* I/O context */
-void *pBuf, /* Buffer used for the management data transfer */
-unsigned int *pLen, /* Length of buffer */
-SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
-{
-SK_I32 Mode; /* Store value of subcommand. */
-SK_U32 Oid; /* Store value of OID. */
-int ReturnCode; /* Store return value to show status of PNMI action. */
-int HeaderLength; /* Length of desired action plus OID. */
-
- ReturnCode = SK_PNMI_ERR_GENERAL;
-
- SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
- SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
- HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
- *pLen = *pLen - HeaderLength;
- SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
-
- switch(Mode) {
- case SK_GET_SINGLE_VAR:
- ReturnCode = SkPnmiGetVar(pAC, IoC, Oid,
- (char *) pBuf + sizeof(SK_I32), pLen,
- ((SK_U32) (-1)), NetIndex);
- SK_PNMI_STORE_U32(pBuf, ReturnCode);
- *pLen = *pLen + sizeof(SK_I32);
- break;
- case SK_PRESET_SINGLE_VAR:
- ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid,
- (char *) pBuf + sizeof(SK_I32), pLen,
- ((SK_U32) (-1)), NetIndex);
- SK_PNMI_STORE_U32(pBuf, ReturnCode);
- *pLen = *pLen + sizeof(SK_I32);
- break;
- case SK_SET_SINGLE_VAR:
- ReturnCode = SkPnmiSetVar(pAC, IoC, Oid,
- (char *) pBuf + sizeof(SK_I32), pLen,
- ((SK_U32) (-1)), NetIndex);
- SK_PNMI_STORE_U32(pBuf, ReturnCode);
- *pLen = *pLen + sizeof(SK_I32);
- break;
- case SK_GET_FULL_MIB:
- ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
- break;
- case SK_PRESET_FULL_MIB:
- ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
- break;
- case SK_SET_FULL_MIB:
- ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
- break;
- default:
- break;
- }
-
- return (ReturnCode);
-
-} /* SkGeIocGen */
diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c
deleted file mode 100644
index 3e7aa49afd0..00000000000
--- a/drivers/net/sk98lin/skgesirq.c
+++ /dev/null
@@ -1,2229 +0,0 @@
-/******************************************************************************
- *
- * Name: skgesirq.c
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.92 $
- * Date: $Date: 2003/09/16 14:37:07 $
- * Purpose: Special IRQ module
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * Special Interrupt handler
- *
- * The following abstract should show how this module is included
- * in the driver path:
- *
- * In the ISR of the driver the bits for frame transmission complete and
- * for receive complete are checked and handled by the driver itself.
- * The bits of the slow path mask are checked after that and then the
- * entry into the so-called "slow path" is prepared. It is an implementors
- * decision whether this is executed directly or just scheduled by
- * disabling the mask. In the interrupt service routine some events may be
- * generated, so it would be a good idea to call the EventDispatcher
- * right after this ISR.
- *
- * The Interrupt source register of the adapter is NOT read by this module.
- * SO if the drivers implementor needs a while loop around the
- * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
- * each loop entered.
- *
- * However, the MAC Interrupt status registers are read in a while loop.
- *
- */
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#ifndef SK_SLIM
-#include "h/skgepnmi.h" /* PNMI Definitions */
-#include "h/skrlmt.h" /* RLMT Definitions */
-#endif
-#include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
-
-/* local function prototypes */
-#ifdef GENESIS
-static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* GENESIS */
-#ifdef YUKON
-static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
-#endif /* OTHER_PHY */
-
-#ifdef GENESIS
-/*
- * array of Rx counter from XMAC which are checked
- * in AutoSense mode to check whether a link is not able to auto-negotiate.
- */
-static const SK_U16 SkGeRxRegs[]= {
- XM_RXF_64B,
- XM_RXF_127B,
- XM_RXF_255B,
- XM_RXF_511B,
- XM_RXF_1023B,
- XM_RXF_MAX_SZ
-} ;
-#endif /* GENESIS */
-
-#ifdef __C2MAN__
-/*
- * Special IRQ function
- *
- * General Description:
- *
- */
-intro()
-{}
-#endif
-
-/******************************************************************************
- *
- * SkHWInitDefSense() - Default Autosensing mode initialization
- *
- * Description: sets the PLinkMode for HWInit
- *
- * Returns: N/A
- */
-static void SkHWInitDefSense(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- pPrt->PAutoNegTimeOut = 0;
-
- if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
- pPrt->PLinkMode = pPrt->PLinkModeConf;
- return;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("AutoSensing: First mode %d on Port %d\n",
- (int)SK_LMODE_AUTOFULL, Port));
-
- pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
-
- return;
-} /* SkHWInitDefSense */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkHWSenseGetNext() - Get Next Autosensing Mode
- *
- * Description: gets the appropriate next mode
- *
- * Note:
- *
- */
-static SK_U8 SkHWSenseGetNext(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- pPrt->PAutoNegTimeOut = 0;
-
- if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
- /* Leave all as configured */
- return(pPrt->PLinkModeConf);
- }
-
- if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
- /* Return next mode AUTOBOTH */
- return ((SK_U8)SK_LMODE_AUTOBOTH);
- }
-
- /* Return default autofull */
- return ((SK_U8)SK_LMODE_AUTOFULL);
-} /* SkHWSenseGetNext */
-
-
-/******************************************************************************
- *
- * SkHWSenseSetNext() - Autosensing Set next mode
- *
- * Description: sets the appropriate next mode
- *
- * Returns: N/A
- */
-static void SkHWSenseSetNext(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U8 NewMode) /* New Mode to be written in sense mode */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- pPrt->PAutoNegTimeOut = 0;
-
- if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
- return;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("AutoSensing: next mode %d on Port %d\n",
- (int)NewMode, Port));
-
- pPrt->PLinkMode = NewMode;
-
- return;
-} /* SkHWSenseSetNext */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkHWLinkDown() - Link Down handling
- *
- * Description: handles the hardware link down signal
- *
- * Returns: N/A
- */
-void SkHWLinkDown(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Disable all MAC interrupts */
- SkMacIrqDisable(pAC, IoC, Port);
-
- /* Disable Receiver and Transmitter */
- SkMacRxTxDisable(pAC, IoC, Port);
-
- /* Init default sense mode */
- SkHWInitDefSense(pAC, IoC, Port);
-
- if (pPrt->PHWLinkUp == SK_FALSE) {
- return;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link down Port %d\n", Port));
-
- /* Set Link to DOWN */
- pPrt->PHWLinkUp = SK_FALSE;
-
- /* Reset Port stati */
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
-
- /* Re-init Phy especially when the AutoSense default is set now */
- SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
- /* GP0: used for workaround of Rev. C Errata 2 */
-
- /* Do NOT signal to RLMT */
-
- /* Do NOT start the timer here */
-} /* SkHWLinkDown */
-
-
-/******************************************************************************
- *
- * SkHWLinkUp() - Link Up handling
- *
- * Description: handles the hardware link up signal
- *
- * Returns: N/A
- */
-static void SkHWLinkUp(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PHWLinkUp) {
- /* We do NOT need to proceed on active link */
- return;
- }
-
- pPrt->PHWLinkUp = SK_TRUE;
- pPrt->PAutoNegFail = SK_FALSE;
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
-
- if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
- pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
- pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
- /* Link is up and no Auto-negotiation should be done */
-
- /* Link speed should be the configured one */
- switch (pPrt->PLinkSpeed) {
- case SK_LSPEED_AUTO:
- /* default is 1000 Mbps */
- case SK_LSPEED_1000MBPS:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
- break;
- case SK_LSPEED_100MBPS:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
- break;
- case SK_LSPEED_10MBPS:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
- break;
- }
-
- /* Set Link Mode Status */
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
- }
- else {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
- }
-
- /* No flow control without auto-negotiation */
- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
-
- /* enable Rx/Tx */
- (void)SkMacRxTxEnable(pAC, IoC, Port);
- }
-} /* SkHWLinkUp */
-
-
-/******************************************************************************
- *
- * SkMacParity() - MAC parity workaround
- *
- * Description: handles MAC parity errors correctly
- *
- * Returns: N/A
- */
-static void SkMacParity(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index of the port failed */
-{
- SK_EVPARA Para;
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_U32 TxMax; /* Tx Max Size Counter */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Clear IRQ Tx Parity Error */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
- (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
- pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
- }
-#endif /* YUKON */
-
- if (pPrt->PCheckPar) {
-
- if (Port == MAC_1) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
- }
- Para.Para64 = Port;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-
- Para.Para32[0] = Port;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
- return;
- }
-
- /* Check whether frames with a size of 1k were sent */
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* Snap statistic counters */
- (void)SkXmUpdateStats(pAC, IoC, Port);
-
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
- }
-#endif /* YUKON */
-
- if (TxMax > 0) {
- /* From now on check the parity */
- pPrt->PCheckPar = SK_TRUE;
- }
-} /* SkMacParity */
-
-
-/******************************************************************************
- *
- * SkGeHwErr() - Hardware Error service routine
- *
- * Description: handles all HW Error interrupts
- *
- * Returns: N/A
- */
-static void SkGeHwErr(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-SK_U32 HwStatus) /* Interrupt status word */
-{
- SK_EVPARA Para;
- SK_U16 Word;
-
- if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
- /* PCI Errors occured */
- if ((HwStatus & IS_IRQ_STAT) != 0) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
- }
-
- /* Reset all bits in the PCI STATUS register */
- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
-
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-
- Para.Para64 = 0;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- if ((HwStatus & IS_NO_STAT_M1) != 0) {
- /* Ignore it */
- /* This situation is also indicated in the descriptor */
- SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
- }
-
- if ((HwStatus & IS_NO_STAT_M2) != 0) {
- /* Ignore it */
- /* This situation is also indicated in the descriptor */
- SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
- }
-
- if ((HwStatus & IS_NO_TIST_M1) != 0) {
- /* Ignore it */
- /* This situation is also indicated in the descriptor */
- SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
- }
-
- if ((HwStatus & IS_NO_TIST_M2) != 0) {
- /* Ignore it */
- /* This situation is also indicated in the descriptor */
- SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* This is necessary only for Rx timing measurements */
- if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
- /* increment Time Stamp Timer counter (high) */
- pAC->GIni.GITimeStampCnt++;
-
- /* Clear Time Stamp Timer IRQ */
- SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
- }
-
- if ((HwStatus & IS_IRQ_SENSOR) != 0) {
- /* no sensors on 32-bit Yukon */
- if (pAC->GIni.GIYukon32Bit) {
- /* disable HW Error IRQ */
- pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
- }
- }
- }
-#endif /* YUKON */
-
- if ((HwStatus & IS_RAM_RD_PAR) != 0) {
- SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
- Para.Para64 = 0;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
- }
-
- if ((HwStatus & IS_RAM_WR_PAR) != 0) {
- SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
- Para.Para64 = 0;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
- }
-
- if ((HwStatus & IS_M1_PAR_ERR) != 0) {
- SkMacParity(pAC, IoC, MAC_1);
- }
-
- if ((HwStatus & IS_M2_PAR_ERR) != 0) {
- SkMacParity(pAC, IoC, MAC_2);
- }
-
- if ((HwStatus & IS_R1_PAR_ERR) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
-
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
- Para.Para64 = MAC_1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-
- Para.Para32[0] = MAC_1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((HwStatus & IS_R2_PAR_ERR) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
-
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
- Para.Para64 = MAC_2;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
-
- Para.Para32[0] = MAC_2;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-} /* SkGeHwErr */
-
-
-/******************************************************************************
- *
- * SkGeSirqIsr() - Special Interrupt Service Routine
- *
- * Description: handles all non data transfer specific interrupts (slow path)
- *
- * Returns: N/A
- */
-void SkGeSirqIsr(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-SK_U32 Istatus) /* Interrupt status word */
-{
- SK_EVPARA Para;
- SK_U32 RegVal32; /* Read register value */
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_U16 PhyInt;
- int i;
-
- if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
- /* read the HW Error Interrupt source */
- SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-
- SkGeHwErr(pAC, IoC, RegVal32);
- }
-
- /*
- * Packet Timeout interrupts
- */
- /* Check whether MACs are correctly initialized */
- if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
- pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
- /* MAC 1 was not initialized but Packet timeout occured */
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
- SKERR_SIRQ_E004MSG);
- }
-
- if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
- pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
- /* MAC 2 was not initialized but Packet timeout occured */
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
- SKERR_SIRQ_E005MSG);
- }
-
- if ((Istatus & IS_PA_TO_RX1) != 0) {
- /* Means network is filling us up */
- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
- SKERR_SIRQ_E002MSG);
- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
- }
-
- if ((Istatus & IS_PA_TO_RX2) != 0) {
- /* Means network is filling us up */
- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
- SKERR_SIRQ_E003MSG);
- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
- }
-
- if ((Istatus & IS_PA_TO_TX1) != 0) {
-
- pPrt = &pAC->GIni.GP[0];
-
- /* May be a normal situation in a server with a slow network */
- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /*
- * workaround: if in half duplex mode, check for Tx hangup.
- * Read number of TX'ed bytes, wait for 10 ms, then compare
- * the number with current value. If nothing changed, we assume
- * that Tx is hanging and do a FIFO flush (see event routine).
- */
- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
- !pPrt->HalfDupTimerActive) {
- /*
- * many more pack. arb. timeouts may come in between,
- * we ignore those
- */
- pPrt->HalfDupTimerActive = SK_TRUE;
- /* Snap statistic counters */
- (void)SkXmUpdateStats(pAC, IoC, 0);
-
- (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
-
- pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-
- (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
-
- pPrt->LastOctets += RegVal32;
-
- Para.Para32[0] = 0;
- SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
- SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
- }
- }
-#endif /* GENESIS */
- }
-
- if ((Istatus & IS_PA_TO_TX2) != 0) {
-
- pPrt = &pAC->GIni.GP[1];
-
- /* May be a normal situation in a server with a slow network */
- SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* workaround: see above */
- if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
- !pPrt->HalfDupTimerActive) {
- pPrt->HalfDupTimerActive = SK_TRUE;
- /* Snap statistic counters */
- (void)SkXmUpdateStats(pAC, IoC, 1);
-
- (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
-
- pPrt->LastOctets = (SK_U64)RegVal32 << 32;
-
- (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
-
- pPrt->LastOctets += RegVal32;
-
- Para.Para32[0] = 1;
- SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
- SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
- }
- }
-#endif /* GENESIS */
- }
-
- /* Check interrupts of the particular queues */
- if ((Istatus & IS_R1_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
- SKERR_SIRQ_E006MSG);
- Para.Para64 = MAC_1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_R2_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
- SKERR_SIRQ_E007MSG);
- Para.Para64 = MAC_2;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_2;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_XS1_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
- SKERR_SIRQ_E008MSG);
- Para.Para64 = MAC_1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_XA1_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
- SKERR_SIRQ_E009MSG);
- Para.Para64 = MAC_1;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_1;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_XS2_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
- SKERR_SIRQ_E010MSG);
- Para.Para64 = MAC_2;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_2;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((Istatus & IS_XA2_C) != 0) {
- /* Clear IRQ */
- SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
- SKERR_SIRQ_E011MSG);
- Para.Para64 = MAC_2;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
- Para.Para32[0] = MAC_2;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- /* External reg interrupt */
- if ((Istatus & IS_EXT_REG) != 0) {
- /* Test IRQs from PHY */
- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
-
- pPrt = &pAC->GIni.GP[i];
-
- if (pPrt->PState == SK_PRT_RESET) {
- continue;
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- switch (pPrt->PhyType) {
-
- case SK_PHY_XMAC:
- break;
-
- case SK_PHY_BCOM:
- SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
-
- if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Port %d Bcom Int: 0x%04X\n",
- i, PhyInt));
- SkPhyIsrBcom(pAC, IoC, i, PhyInt);
- }
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
-
- if ((PhyInt & PHY_L_DEF_MSK) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Port %d Lone Int: %x\n",
- i, PhyInt));
- SkPhyIsrLone(pAC, IoC, i, PhyInt);
- }
- break;
-#endif /* OTHER_PHY */
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* Read PHY Interrupt Status */
- SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
-
- if ((PhyInt & PHY_M_DEF_MSK) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Port %d Marv Int: 0x%04X\n",
- i, PhyInt));
- SkPhyIsrGmac(pAC, IoC, i, PhyInt);
- }
- }
-#endif /* YUKON */
- }
- }
-
- /* I2C Ready interrupt */
- if ((Istatus & IS_I2C_READY) != 0) {
-#ifdef SK_SLIM
- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-#else
- SkI2cIsr(pAC, IoC);
-#endif
- }
-
- /* SW forced interrupt */
- if ((Istatus & IS_IRQ_SW) != 0) {
- /* clear the software IRQ */
- SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
- }
-
- if ((Istatus & IS_LNK_SYNC_M1) != 0) {
- /*
- * We do NOT need the Link Sync interrupt, because it shows
- * us only a link going down.
- */
- /* clear interrupt */
- SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
- }
-
- /* Check MAC after link sync counter */
- if ((Istatus & IS_MAC1) != 0) {
- /* IRQ from MAC 1 */
- SkMacIrq(pAC, IoC, MAC_1);
- }
-
- if ((Istatus & IS_LNK_SYNC_M2) != 0) {
- /*
- * We do NOT need the Link Sync interrupt, because it shows
- * us only a link going down.
- */
- /* clear interrupt */
- SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
- }
-
- /* Check MAC after link sync counter */
- if ((Istatus & IS_MAC2) != 0) {
- /* IRQ from MAC 2 */
- SkMacIrq(pAC, IoC, MAC_2);
- }
-
- /* Timer interrupt (served last) */
- if ((Istatus & IS_TIMINT) != 0) {
- /* check for HW Errors */
- if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
- /* read the HW Error Interrupt source */
- SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
-
- SkGeHwErr(pAC, IoC, RegVal32);
- }
-
- SkHwtIsr(pAC, IoC);
- }
-
-} /* SkGeSirqIsr */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- */
-static int SkGePortCheckShorts(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port) /* Which port should be checked */
-{
- SK_U32 Shorts; /* Short Event Counter */
- SK_U32 CheckShorts; /* Check value for Short Event Counter */
- SK_U64 RxCts; /* Rx Counter (packets on network) */
- SK_U32 RxTmp; /* Rx temp. Counter */
- SK_U32 FcsErrCts; /* FCS Error Counter */
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Rtv; /* Return value */
- int i;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Default: no action */
- Rtv = SK_HW_PS_NONE;
-
- (void)SkXmUpdateStats(pAC, IoC, Port);
-
- /* Extra precaution: check for short Event counter */
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
-
- /*
- * Read Rx counters (packets seen on the network and not necessarily
- * really received.
- */
- RxCts = 0;
-
- for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
-
- (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
-
- RxCts += (SK_U64)RxTmp;
- }
-
- /* On default: check shorts against zero */
- CheckShorts = 0;
-
- /* Extra precaution on active links */
- if (pPrt->PHWLinkUp) {
- /* Reset Link Restart counter */
- pPrt->PLinkResCt = 0;
- pPrt->PAutoNegTOCt = 0;
-
- /* If link is up check for 2 */
- CheckShorts = 2;
-
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
-
- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
- pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
- (pPrt->PLinkMode == SK_LMODE_HALF ||
- pPrt->PLinkMode == SK_LMODE_FULL)) {
- /*
- * This is autosensing and we are in the fallback
- * manual full/half duplex mode.
- */
- if (RxCts == pPrt->PPrevRx) {
- /* Nothing received, restart link */
- pPrt->PPrevFcs = FcsErrCts;
- pPrt->PPrevShorts = Shorts;
-
- return(SK_HW_PS_RESTART);
- }
- else {
- pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
- }
- }
-
- if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
- (!(FcsErrCts - pPrt->PPrevFcs))) {
- /*
- * Note: The compare with zero above has to be done the way shown,
- * otherwise the Linux driver will have a problem.
- */
- /*
- * We received a bunch of frames or no CRC error occured on the
- * network -> ok.
- */
- pPrt->PPrevRx = RxCts;
- pPrt->PPrevFcs = FcsErrCts;
- pPrt->PPrevShorts = Shorts;
-
- return(SK_HW_PS_NONE);
- }
-
- pPrt->PPrevFcs = FcsErrCts;
- }
-
-
- if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Short Event Count Restart Port %d \n", Port));
- Rtv = SK_HW_PS_RESTART;
- }
-
- pPrt->PPrevShorts = Shorts;
- pPrt->PPrevRx = RxCts;
-
- return(Rtv);
-} /* SkGePortCheckShorts */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUp() - Check if the link is up
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUp(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port) /* Which port should be checked */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
- int Rtv; /* Return value */
-
- Rtv = SK_HW_PS_NONE;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- AutoNeg = SK_FALSE;
- }
- else {
- AutoNeg = SK_TRUE;
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- switch (pPrt->PhyType) {
-
- case SK_PHY_XMAC:
- Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
- break;
- case SK_PHY_BCOM:
- Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
- break;
- case SK_PHY_NAT:
- Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
- break;
-#endif /* OTHER_PHY */
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
- }
-#endif /* YUKON */
-
- return(Rtv);
-} /* SkGePortCheckUp */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpXmac(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- SK_U32 Shorts; /* Short Event Counter */
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Done;
- SK_U32 GpReg; /* General Purpose register value */
- SK_U16 Isrc; /* Interrupt source register */
- SK_U16 IsrcSum; /* Interrupt source register sum */
- SK_U16 LpAb; /* Link Partner Ability */
- SK_U16 ResAb; /* Resolved Ability */
- SK_U16 ExtStat; /* Extended Status Register */
- SK_U8 NextMode; /* Next AutoSensing Mode */
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PHWLinkUp) {
- if (pPrt->PhyType != SK_PHY_XMAC) {
- return(SK_HW_PS_NONE);
- }
- else {
- return(SkGePortCheckShorts(pAC, IoC, Port));
- }
- }
-
- IsrcSum = pPrt->PIsave;
- pPrt->PIsave = 0;
-
- /* Now wait for each port's link */
- if (pPrt->PLinkBroken) {
- /* Link was broken */
- XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
-
- if ((GpReg & XM_GP_INP_ASS) == 0) {
- /* The Link is in sync */
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
- SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-
- if ((Isrc & XM_IS_INP_ASS) == 0) {
- /* It has been in sync since last time */
- /* Restart the PORT */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link in sync Restart Port %d\n", Port));
-
- (void)SkXmUpdateStats(pAC, IoC, Port);
-
- /* We now need to reinitialize the PrevShorts counter */
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
- pPrt->PPrevShorts = Shorts;
-
- pPrt->PLinkBroken = SK_FALSE;
-
- /*
- * Link Restart Workaround:
- * it may be possible that the other Link side
- * restarts its link as well an we detect
- * another LinkBroken. To prevent this
- * happening we check for a maximum number
- * of consecutive restart. If those happens,
- * we do NOT restart the active link and
- * check whether the link is now o.k.
- */
- pPrt->PLinkResCt++;
-
- pPrt->PAutoNegTimeOut = 0;
-
- if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
- return(SK_HW_PS_RESTART);
- }
-
- pPrt->PLinkResCt = 0;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
- }
- else {
- pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
-
- /* Do nothing more if link is broken */
- return(SK_HW_PS_NONE);
- }
- }
- else {
- /* Do nothing more if link is broken */
- return(SK_HW_PS_NONE);
- }
-
- }
- else {
- /* Link was not broken, check if it is */
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
- if ((Isrc & XM_IS_INP_ASS) != 0) {
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
- if ((Isrc & XM_IS_INP_ASS) != 0) {
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
- if ((Isrc & XM_IS_INP_ASS) != 0) {
- pPrt->PLinkBroken = SK_TRUE;
- /* Re-Init Link partner Autoneg flag */
- pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link broken Port %d\n", Port));
-
- /* Cable removed-> reinit sense mode */
- SkHWInitDefSense(pAC, IoC, Port);
-
- return(SK_HW_PS_RESTART);
- }
- }
- }
- else {
- SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
-
- if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
- return(SK_HW_PS_RESTART);
- }
- }
- }
-
- /*
- * here we usually can check whether the link is in sync and
- * auto-negotiation is done.
- */
- XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
- XM_IN16(IoC, Port, XM_ISRC, &Isrc);
- IsrcSum |= Isrc;
-
- SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
-
- if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
- if ((GpReg & XM_GP_INP_ASS) == 0) {
- /* Save Auto-negotiation Done interrupt only if link is in sync */
- pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
- }
-#ifdef DEBUG
- if ((pPrt->PIsave & XM_IS_AND) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg done rescheduled Port %d\n", Port));
- }
-#endif /* DEBUG */
- return(SK_HW_PS_NONE);
- }
-
- if (AutoNeg) {
- if ((IsrcSum & XM_IS_AND) != 0) {
- SkHWLinkUp(pAC, IoC, Port);
- Done = SkMacAutoNegDone(pAC, IoC, Port);
- if (Done != SK_AND_OK) {
- /* Get PHY parameters, for debugging only */
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
- Port, LpAb, ResAb));
-
- /* Try next possible mode */
- NextMode = SkHWSenseGetNext(pAC, IoC, Port);
- SkHWLinkDown(pAC, IoC, Port);
- if (Done == SK_AND_DUP_CAP) {
- /* GoTo next mode */
- SkHWSenseSetNext(pAC, IoC, Port, NextMode);
- }
-
- return(SK_HW_PS_RESTART);
- }
- /*
- * Dummy Read extended status to prevent extra link down/ups
- * (clear Page Received bit if set)
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
-
- return(SK_HW_PS_LINK);
- }
-
- /* AutoNeg not done, but HW link is up. Check for timeouts */
- pPrt->PAutoNegTimeOut++;
- if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
- /* Increase the Timeout counter */
- pPrt->PAutoNegTOCt++;
-
- /* Timeout occured */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("AutoNeg timeout Port %d\n", Port));
- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
- pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
- /* Set Link manually up */
- SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Set manual full duplex Port %d\n", Port));
- }
-
- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
- pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
- pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
- /*
- * This is rather complicated.
- * we need to check here whether the LIPA_AUTO
- * we saw before is false alert. We saw at one
- * switch ( SR8800) that on boot time it sends
- * just one auto-neg packet and does no further
- * auto-negotiation.
- * Solution: we restart the autosensing after
- * a few timeouts.
- */
- pPrt->PAutoNegTOCt = 0;
- pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
- SkHWInitDefSense(pAC, IoC, Port);
- }
-
- /* Do the restart */
- return(SK_HW_PS_RESTART);
- }
- }
- else {
- /* Link is up and we don't need more */
-#ifdef DEBUG
- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("ERROR: Lipa auto detected on port %d\n", Port));
- }
-#endif /* DEBUG */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link sync(GP), Port %d\n", Port));
- SkHWLinkUp(pAC, IoC, Port);
-
- /*
- * Link sync (GP) and so assume a good connection. But if not received
- * a bunch of frames received in a time slot (maybe broken tx cable)
- * the port is restart.
- */
- return(SK_HW_PS_LINK);
- }
-
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpXmac */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpBcom(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Done;
- SK_U16 Isrc; /* Interrupt source register */
- SK_U16 PhyStat; /* Phy Status Register */
- SK_U16 ResAb; /* Master/Slave resolution */
- SK_U16 Ctrl; /* Broadcom control flags */
-#ifdef DEBUG
- SK_U16 LpAb;
- SK_U16 ExtStat;
-#endif /* DEBUG */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Check for No HCD Link events (#10523) */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
-
-#ifdef xDEBUG
- if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) ==
- (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
-
- SK_U32 Stat1, Stat2, Stat3;
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "CheckUp1 - Stat: %x, Mask: %x",
- (void *)Isrc,
- (void *)Stat1);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "Ctrl/Stat: %x, AN Adv/LP: %x",
- (void *)Stat1,
- (void *)Stat2);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
- (void *)Stat1,
- (void *)Stat2);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
- (void *)Stat1,
- (void *)Stat2);
- }
-#endif /* DEBUG */
-
- if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
- /*
- * Workaround BCom Errata:
- * enable and disable loopback mode if "NO HCD" occurs.
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
- (SK_U16)(Ctrl | PHY_CT_LOOP));
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
- (SK_U16)(Ctrl & ~PHY_CT_LOOP));
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("No HCD Link event, Port %d\n", Port));
-#ifdef xDEBUG
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "No HCD link event, port %d.",
- (void *)Port,
- (void *)NULL);
-#endif /* DEBUG */
- }
-
- /* Not obsolete: link status bit is latched to 0 and autoclearing! */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
- if (pPrt->PHWLinkUp) {
- return(SK_HW_PS_NONE);
- }
-
-#ifdef xDEBUG
- {
- SK_U32 Stat1, Stat2, Stat3;
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "CheckUp1a - Stat: %x, Mask: %x",
- (void *)Isrc,
- (void *)Stat1);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
- Stat1 = Stat1 << 16 | PhyStat;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "Ctrl/Stat: %x, AN Adv/LP: %x",
- (void *)Stat1,
- (void *)Stat2);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
- Stat2 = Stat2 << 16 | ResAb;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
- (void *)Stat1,
- (void *)Stat2);
-
- Stat1 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
- Stat1 = Stat1 << 16 | Stat2;
- Stat2 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
- Stat3 = 0;
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
- Stat2 = Stat2 << 16 | Stat3;
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
- (void *)Stat1,
- (void *)Stat2);
- }
-#endif /* DEBUG */
-
- /*
- * Here we usually can check whether the link is in sync and
- * auto-negotiation is done.
- */
-
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
-
- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-
- if ((ResAb & PHY_B_1000S_MSF) != 0) {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault port %d\n", Port));
-
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
-
- return(SK_HW_PS_RESTART);
- }
-
- if ((PhyStat & PHY_ST_LSYNC) == 0) {
- return(SK_HW_PS_NONE);
- }
-
- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Port %d, ResAb: 0x%04X\n", Port, ResAb));
-
- if (AutoNeg) {
- if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-
- SkHWLinkUp(pAC, IoC, Port);
-
- Done = SkMacAutoNegDone(pAC, IoC, Port);
-
- if (Done != SK_AND_OK) {
-#ifdef DEBUG
- /* Get PHY parameters, for debugging only */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
- Port, LpAb, ExtStat));
-#endif /* DEBUG */
- return(SK_HW_PS_RESTART);
- }
- else {
-#ifdef xDEBUG
- /* Dummy read ISR to prevent extra link downs/ups */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
- if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "CheckUp2 - Stat: %x",
- (void *)ExtStat,
- (void *)NULL);
- }
-#endif /* DEBUG */
- return(SK_HW_PS_LINK);
- }
- }
- }
- else { /* !AutoNeg */
- /* Link is up and we don't need more. */
-#ifdef DEBUG
- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("ERROR: Lipa auto detected on port %d\n", Port));
- }
-#endif /* DEBUG */
-
-#ifdef xDEBUG
- /* Dummy read ISR to prevent extra link downs/ups */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
-
- if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
- CMSMPrintString(
- pAC->pConfigTable,
- MSG_TYPE_RUNTIME_INFO,
- "CheckUp3 - Stat: %x",
- (void *)ExtStat,
- (void *)NULL);
- }
-#endif /* DEBUG */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link sync(GP), Port %d\n", Port));
- SkHWLinkUp(pAC, IoC, Port);
-
- return(SK_HW_PS_LINK);
- }
-
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpGmac(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Done;
- SK_U16 PhyIsrc; /* PHY Interrupt source */
- SK_U16 PhyStat; /* PPY Status */
- SK_U16 PhySpecStat;/* PHY Specific Status */
- SK_U16 ResAb; /* Master/Slave resolution */
- SK_EVPARA Para;
-#ifdef DEBUG
- SK_U16 Word; /* I/O helper */
-#endif /* DEBUG */
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PHWLinkUp) {
- return(SK_HW_PS_NONE);
- }
-
- /* Read PHY Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
-
- /* Read PHY Interrupt Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
-
- if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
- }
-
- if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
- }
-
- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-
- if ((ResAb & PHY_B_1000S_MSF) != 0) {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault port %d\n", Port));
-
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
-
- return(SK_HW_PS_RESTART);
- }
-
- /* Read PHY Specific Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
-
-#ifdef DEBUG
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
-
- if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
- (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) {
- /* Read PHY Next Page Link Partner */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Page Received, NextPage: 0x%04X\n", Word));
- }
-#endif /* DEBUG */
-
- if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
- return(SK_HW_PS_NONE);
- }
-
- if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
- (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
- /* Downshift detected */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
-
- Para.Para64 = Port;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
- }
-
- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-
- pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
-
- if (AutoNeg) {
- /* Auto-Negotiation Over ? */
- if ((PhyStat & PHY_ST_AN_OVER) != 0) {
-
- SkHWLinkUp(pAC, IoC, Port);
-
- Done = SkMacAutoNegDone(pAC, IoC, Port);
-
- if (Done != SK_AND_OK) {
- return(SK_HW_PS_RESTART);
- }
-
- return(SK_HW_PS_LINK);
- }
- }
- else { /* !AutoNeg */
- /* Link is up and we don't need more */
-#ifdef DEBUG
- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("ERROR: Lipa auto detected on port %d\n", Port));
- }
-#endif /* DEBUG */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link sync, Port %d\n", Port));
- SkHWLinkUp(pAC, IoC, Port);
-
- return(SK_HW_PS_LINK);
- }
-
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpLone(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- int Done;
- SK_U16 Isrc; /* Interrupt source register */
- SK_U16 LpAb; /* Link Partner Ability */
- SK_U16 ExtStat; /* Extended Status Register */
- SK_U16 PhyStat; /* Phy Status Register */
- SK_U16 StatSum;
- SK_U8 NextMode; /* Next AutoSensing Mode */
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PHWLinkUp) {
- return(SK_HW_PS_NONE);
- }
-
- StatSum = pPrt->PIsave;
- pPrt->PIsave = 0;
-
- /*
- * here we usually can check whether the link is in sync and
- * auto-negotiation is done.
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
- StatSum |= PhyStat;
-
- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
-
- if ((PhyStat & PHY_ST_LSYNC) == 0) {
- /* Save Auto-negotiation Done bit */
- pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
-#ifdef DEBUG
- if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg done rescheduled Port %d\n", Port));
- }
-#endif /* DEBUG */
- return(SK_HW_PS_NONE);
- }
-
- if (AutoNeg) {
- if ((StatSum & PHY_ST_AN_OVER) != 0) {
- SkHWLinkUp(pAC, IoC, Port);
- Done = SkMacAutoNegDone(pAC, IoC, Port);
- if (Done != SK_AND_OK) {
- /* Get PHY parameters, for debugging only */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
- Port, LpAb, ExtStat));
-
- /* Try next possible mode */
- NextMode = SkHWSenseGetNext(pAC, IoC, Port);
- SkHWLinkDown(pAC, IoC, Port);
- if (Done == SK_AND_DUP_CAP) {
- /* GoTo next mode */
- SkHWSenseSetNext(pAC, IoC, Port, NextMode);
- }
-
- return(SK_HW_PS_RESTART);
-
- }
- else {
- /*
- * Dummy Read interrupt status to prevent
- * extra link down/ups
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
- return(SK_HW_PS_LINK);
- }
- }
-
- /* AutoNeg not done, but HW link is up. Check for timeouts */
- pPrt->PAutoNegTimeOut++;
- if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
- /* Timeout occured */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("AutoNeg timeout Port %d\n", Port));
- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
- pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
- /* Set Link manually up */
- SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Set manual full duplex Port %d\n", Port));
- }
-
- /* Do the restart */
- return(SK_HW_PS_RESTART);
- }
- }
- else {
- /* Link is up and we don't need more */
-#ifdef DEBUG
- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("ERROR: Lipa auto detected on port %d\n", Port));
- }
-#endif /* DEBUG */
-
- /*
- * Dummy Read interrupt status to prevent
- * extra link down/ups
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("Link sync(GP), Port %d\n", Port));
- SkHWLinkUp(pAC, IoC, Port);
-
- return(SK_HW_PS_LINK);
- }
-
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpLone */
-
-
-/******************************************************************************
- *
- * SkGePortCheckUpNat() - Check if the link is up on National PHY
- *
- * return:
- * 0 o.k. nothing needed
- * 1 Restart needed on this port
- * 2 Link came up
- */
-static int SkGePortCheckUpNat(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO Context */
-int Port, /* Which port should be checked */
-SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
-{
- /* todo: National */
- return(SK_HW_PS_NONE);
-} /* SkGePortCheckUpNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- * SkGeSirqEvent() - Event Service Routine
- *
- * Description:
- *
- * Notes:
- */
-int SkGeSirqEvent(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* Io Context */
-SK_U32 Event, /* Module specific Event */
-SK_EVPARA Para) /* Event specific Parameter */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_U32 Port;
- SK_U32 Val32;
- int PortStat;
- SK_U8 Val8;
-#ifdef GENESIS
- SK_U64 Octets;
-#endif /* GENESIS */
-
- Port = Para.Para32[0];
- pPrt = &pAC->GIni.GP[Port];
-
- switch (Event) {
- case SK_HWEV_WATIM:
- if (pPrt->PState == SK_PRT_RESET) {
-
- PortStat = SK_HW_PS_NONE;
- }
- else {
- /* Check whether port came up */
- PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
- }
-
- switch (PortStat) {
- case SK_HW_PS_RESTART:
- if (pPrt->PHWLinkUp) {
- /* Set Link to down */
- SkHWLinkDown(pAC, IoC, (int)Port);
-
- /*
- * Signal directly to RLMT to ensure correct
- * sequence of SWITCH and RESET event.
- */
- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
- }
-
- /* Restart needed */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
- break;
-
- case SK_HW_PS_LINK:
- /* Signal to RLMT */
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
- break;
- }
-
- /* Start again the check Timer */
- if (pPrt->PHWLinkUp) {
- Val32 = SK_WA_ACT_TIME;
- }
- else {
- Val32 = SK_WA_INA_TIME;
- }
-
- /* Todo: still needed for non-XMAC PHYs??? */
- /* Start workaround Errata #2 timer */
- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
- SKGE_HWAC, SK_HWEV_WATIM, Para);
- break;
-
- case SK_HWEV_PORT_START:
- if (pPrt->PHWLinkUp) {
- /*
- * Signal directly to RLMT to ensure correct
- * sequence of SWITCH and RESET event.
- */
- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
- }
-
- SkHWLinkDown(pAC, IoC, (int)Port);
-
- /* Schedule Port RESET */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
-
- /* Start workaround Errata #2 timer */
- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
- SKGE_HWAC, SK_HWEV_WATIM, Para);
- break;
-
- case SK_HWEV_PORT_STOP:
- if (pPrt->PHWLinkUp) {
- /*
- * Signal directly to RLMT to ensure correct
- * sequence of SWITCH and RESET event.
- */
- SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
- }
-
- /* Stop Workaround Timer */
- SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
-
- SkHWLinkDown(pAC, IoC, (int)Port);
- break;
-
- case SK_HWEV_UPDATE_STAT:
- /* We do NOT need to update any statistics */
- break;
-
- case SK_HWEV_CLEAR_STAT:
- /* We do NOT need to clear any statistics */
- for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
- pPrt->PPrevRx = 0;
- pPrt->PPrevFcs = 0;
- pPrt->PPrevShorts = 0;
- }
- break;
-
- case SK_HWEV_SET_LMODE:
- Val8 = (SK_U8)Para.Para32[1];
- if (pPrt->PLinkModeConf != Val8) {
- /* Set New link mode */
- pPrt->PLinkModeConf = Val8;
-
- /* Restart Port */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
- }
- break;
-
- case SK_HWEV_SET_FLOWMODE:
- Val8 = (SK_U8)Para.Para32[1];
- if (pPrt->PFlowCtrlMode != Val8) {
- /* Set New Flow Control mode */
- pPrt->PFlowCtrlMode = Val8;
-
- /* Restart Port */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
- }
- break;
-
- case SK_HWEV_SET_ROLE:
- /* not possible for fiber */
- if (!pAC->GIni.GICopperType) {
- break;
- }
- Val8 = (SK_U8)Para.Para32[1];
- if (pPrt->PMSMode != Val8) {
- /* Set New Role (Master/Slave) mode */
- pPrt->PMSMode = Val8;
-
- /* Restart Port */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
- }
- break;
-
- case SK_HWEV_SET_SPEED:
- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
- break;
- }
- Val8 = (SK_U8)Para.Para32[1];
- if (pPrt->PLinkSpeed != Val8) {
- /* Set New Speed parameter */
- pPrt->PLinkSpeed = Val8;
-
- /* Restart Port */
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
- }
- break;
-
-#ifdef GENESIS
- case SK_HWEV_HALFDUP_CHK:
- if (pAC->GIni.GIGenesis) {
- /*
- * half duplex hangup workaround.
- * See packet arbiter timeout interrupt for description
- */
- pPrt->HalfDupTimerActive = SK_FALSE;
- if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
- /* Snap statistic counters */
- (void)SkXmUpdateStats(pAC, IoC, Port);
-
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
-
- Octets = (SK_U64)Val32 << 32;
-
- (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
-
- Octets += Val32;
-
- if (pPrt->LastOctets == Octets) {
- /* Tx hanging, a FIFO flush restarts it */
- SkMacFlushTxFifo(pAC, IoC, Port);
- }
- }
- }
- break;
-#endif /* GENESIS */
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
- break;
- }
-
- return(0);
-} /* SkGeSirqEvent */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkPhyIsrBcom() - PHY interrupt service routine
- *
- * Description: handles all interrupts from BCom PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrBcom(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* Io Context */
-int Port, /* Port Num = PHY Num */
-SK_U16 IStatus) /* Interrupt Status */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_EVPARA Para;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if ((IStatus & PHY_B_IS_PSE) != 0) {
- /* Incorrectable pair swap error */
- SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
- SKERR_SIRQ_E022MSG);
- }
-
- if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
-
- SkHWLinkDown(pAC, IoC, Port);
-
- Para.Para32[0] = (SK_U32)Port;
- /* Signal to RLMT */
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
- /* Start workaround Errata #2 timer */
- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
- SKGE_HWAC, SK_HWEV_WATIM, Para);
- }
-
-} /* SkPhyIsrBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkPhyIsrGmac() - PHY interrupt service routine
- *
- * Description: handles all interrupts from Marvell PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrGmac(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* Io Context */
-int Port, /* Port Num = PHY Num */
-SK_U16 IStatus) /* Interrupt Status */
-{
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
- SK_EVPARA Para;
- SK_U16 Word;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
-
- SkHWLinkDown(pAC, IoC, Port);
-
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg.Adv: 0x%04X\n", Word));
-
- /* Set Auto-negotiation advertisement */
- if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
- /* restore Asymmetric Pause bit */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
- (SK_U16)(Word | PHY_M_AN_ASP));
- }
-
- Para.Para32[0] = (SK_U32)Port;
- /* Signal to RLMT */
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
- if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
- /* Auto-Negotiation Error */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
- }
-
- if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
- /* FIFO Overflow/Underrun Error */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
- }
-
-} /* SkPhyIsrGmac */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkPhyIsrLone() - PHY interrupt service routine
- *
- * Description: handles all interrupts from LONE PHY
- *
- * Returns: N/A
- */
-static void SkPhyIsrLone(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* Io Context */
-int Port, /* Port Num = PHY Num */
-SK_U16 IStatus) /* Interrupt Status */
-{
- SK_EVPARA Para;
-
- if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
-
- SkHWLinkDown(pAC, IoC, Port);
-
- Para.Para32[0] = (SK_U32)Port;
- /* Signal to RLMT */
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
- }
-
-} /* SkPhyIsrLone */
-#endif /* OTHER_PHY */
-
-/* End of File */
diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c
deleted file mode 100644
index 79bf57cb532..00000000000
--- a/drivers/net/sk98lin/ski2c.c
+++ /dev/null
@@ -1,1296 +0,0 @@
-/******************************************************************************
- *
- * Name: ski2c.c
- * Project: Gigabit Ethernet Adapters, TWSI-Module
- * Version: $Revision: 1.59 $
- * Date: $Date: 2003/10/20 09:07:25 $
- * Purpose: Functions to access Voltage and Temperature Sensor
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- * I2C Protocol
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- I2C protocol implementation.
-
- General Description:
-
- The I2C protocol is used for the temperature sensors and for
- the serial EEPROM which hold the configuration.
-
- This file covers functions that allow to read write and do
- some bulk requests a specified I2C address.
-
- The Genesis has 2 I2C buses. One for the EEPROM which holds
- the VPD Data and one for temperature and voltage sensor.
- The following picture shows the I2C buses, I2C devices and
- their control registers.
-
- Note: The VPD functions are in skvpd.c
-.
-. PCI Config I2C Bus for VPD Data:
-.
-. +------------+
-. | VPD EEPROM |
-. +------------+
-. |
-. | <-- I2C
-. |
-. +-----------+-----------+
-. | |
-. +-----------------+ +-----------------+
-. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG |
-. +-----------------+ +-----------------+
-.
-.
-. I2C Bus for LM80 sensor:
-.
-. +-----------------+
-. | Temperature and |
-. | Voltage Sensor |
-. | LM80 |
-. +-----------------+
-. |
-. |
-. I2C --> |
-. |
-. +----+
-. +-------------->| OR |<--+
-. | +----+ |
-. +------+------+ |
-. | | |
-. +--------+ +--------+ +----------+
-. | B2_I2C | | B2_I2C | | B2_I2C |
-. | _CTRL | | _DATA | | _SW |
-. +--------+ +--------+ +----------+
-.
- The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
- and B2_I2C_DATA registers.
- For driver software it is recommended to use the I2C control and
- data register, because I2C bus timing is done by the ASIC and
- an interrupt may be received when the I2C request is completed.
-
- Clock Rate Timing: MIN MAX generated by
- VPD EEPROM: 50 kHz 100 kHz HW
- LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW
- LM80 over B2_I2C_SW register 0 400 kHz SW
-
- Note: The clock generated by the hardware is dependend on the
- PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
- clock is 50 kHz.
- */
-intro()
-{}
-#endif
-
-#ifdef SK_DIAG
-/*
- * I2C Fast Mode timing values used by the LM80.
- * If new devices are added to the I2C bus the timing values have to be checked.
- */
-#ifndef I2C_SLOW_TIMING
-#define T_CLK_LOW 1300L /* clock low time in ns */
-#define T_CLK_HIGH 600L /* clock high time in ns */
-#define T_DATA_IN_SETUP 100L /* data in Set-up Time */
-#define T_START_HOLD 600L /* start condition hold time */
-#define T_START_SETUP 600L /* start condition Set-up time */
-#define T_STOP_SETUP 600L /* stop condition Set-up time */
-#define T_BUS_IDLE 1300L /* time the bus must free after Tx */
-#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */
-#else /* I2C_SLOW_TIMING */
-/* I2C Standard Mode Timing */
-#define T_CLK_LOW 4700L /* clock low time in ns */
-#define T_CLK_HIGH 4000L /* clock high time in ns */
-#define T_DATA_IN_SETUP 250L /* data in Set-up Time */
-#define T_START_HOLD 4000L /* start condition hold time */
-#define T_START_SETUP 4700L /* start condition Set-up time */
-#define T_STOP_SETUP 4000L /* stop condition Set-up time */
-#define T_BUS_IDLE 4700L /* time the bus must free after Tx */
-#endif /* !I2C_SLOW_TIMING */
-
-#define NS2BCLK(x) (((x)*125)/10000)
-
-/*
- * I2C Wire Operations
- *
- * About I2C_CLK_LOW():
- *
- * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
- * clock to low, to prevent the ASIC and the I2C data client from driving the
- * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
- * send an 'ACK'). See also Concentrator Bugreport No. 10192.
- */
-#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA)
-#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA)
-#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
-#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
-#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK)
-#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
-#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK)
-
-#define NS2CLKT(x) ((x*125L)/10000)
-
-/*--------------- I2C Interface Register Functions --------------- */
-
-/*
- * sending one bit
- */
-void SkI2cSndBit(
-SK_IOC IoC, /* I/O Context */
-SK_U8 Bit) /* Bit to send */
-{
- I2C_DATA_OUT(IoC);
- if (Bit) {
- I2C_DATA_HIGH(IoC);
- }
- else {
- I2C_DATA_LOW(IoC);
- }
- SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
- I2C_CLK_HIGH(IoC);
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
- I2C_CLK_LOW(IoC);
-} /* SkI2cSndBit*/
-
-
-/*
- * Signal a start to the I2C Bus.
- *
- * A start is signaled when data goes to low in a high clock cycle.
- *
- * Ends with Clock Low.
- *
- * Status: not tested
- */
-void SkI2cStart(
-SK_IOC IoC) /* I/O Context */
-{
- /* Init data and Clock to output lines */
- /* Set Data high */
- I2C_DATA_OUT(IoC);
- I2C_DATA_HIGH(IoC);
- /* Set Clock high */
- I2C_CLK_HIGH(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
-
- /* Set Data Low */
- I2C_DATA_LOW(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
-
- /* Clock low without Data to Input */
- I2C_START_COND(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
-} /* SkI2cStart */
-
-
-void SkI2cStop(
-SK_IOC IoC) /* I/O Context */
-{
- /* Init data and Clock to output lines */
- /* Set Data low */
- I2C_DATA_OUT(IoC);
- I2C_DATA_LOW(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
- /* Set Clock high */
- I2C_CLK_HIGH(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
-
- /*
- * Set Data High: Do it by setting the Data Line to Input.
- * Because of a pull up resistor the Data Line
- * floods to high.
- */
- I2C_DATA_IN(IoC);
-
- /*
- * When I2C activity is stopped
- * o DATA should be set to input and
- * o CLOCK should be set to high!
- */
- SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
-} /* SkI2cStop */
-
-
-/*
- * Receive just one bit via the I2C bus.
- *
- * Note: Clock must be set to LOW before calling this function.
- *
- * Returns The received bit.
- */
-int SkI2cRcvBit(
-SK_IOC IoC) /* I/O Context */
-{
- int Bit;
- SK_U8 I2cSwCtrl;
-
- /* Init data as input line */
- I2C_DATA_IN(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
-
- I2C_CLK_HIGH(IoC);
-
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
-
- SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-
- Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
-
- I2C_CLK_LOW(IoC);
- SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
-
- return(Bit);
-} /* SkI2cRcvBit */
-
-
-/*
- * Receive an ACK.
- *
- * returns 0 If acknowledged
- * 1 in case of an error
- */
-int SkI2cRcvAck(
-SK_IOC IoC) /* I/O Context */
-{
- /*
- * Received bit must be zero.
- */
- return(SkI2cRcvBit(IoC) != 0);
-} /* SkI2cRcvAck */
-
-
-/*
- * Send an NACK.
- */
-void SkI2cSndNAck(
-SK_IOC IoC) /* I/O Context */
-{
- /*
- * Received bit must be zero.
- */
- SkI2cSndBit(IoC, 1);
-} /* SkI2cSndNAck */
-
-
-/*
- * Send an ACK.
- */
-void SkI2cSndAck(
-SK_IOC IoC) /* I/O Context */
-{
- /*
- * Received bit must be zero.
- */
- SkI2cSndBit(IoC, 0);
-} /* SkI2cSndAck */
-
-
-/*
- * Send one byte to the I2C device and wait for ACK.
- *
- * Return acknowleged status.
- */
-int SkI2cSndByte(
-SK_IOC IoC, /* I/O Context */
-int Byte) /* byte to send */
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- if (Byte & (1<<(7-i))) {
- SkI2cSndBit(IoC, 1);
- }
- else {
- SkI2cSndBit(IoC, 0);
- }
- }
-
- return(SkI2cRcvAck(IoC));
-} /* SkI2cSndByte */
-
-
-/*
- * Receive one byte and ack it.
- *
- * Return byte.
- */
-int SkI2cRcvByte(
-SK_IOC IoC, /* I/O Context */
-int Last) /* Last Byte Flag */
-{
- int i;
- int Byte = 0;
-
- for (i = 0; i < 8; i++) {
- Byte <<= 1;
- Byte |= SkI2cRcvBit(IoC);
- }
-
- if (Last) {
- SkI2cSndNAck(IoC);
- }
- else {
- SkI2cSndAck(IoC);
- }
-
- return(Byte);
-} /* SkI2cRcvByte */
-
-
-/*
- * Start dialog and send device address
- *
- * Return 0 if acknowleged, 1 in case of an error
- */
-int SkI2cSndDev(
-SK_IOC IoC, /* I/O Context */
-int Addr, /* Device Address */
-int Rw) /* Read / Write Flag */
-{
- SkI2cStart(IoC);
- Rw = ~Rw;
- Rw &= I2C_WRITE;
- return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
-} /* SkI2cSndDev */
-
-#endif /* SK_DIAG */
-
-/*----------------- I2C CTRL Register Functions ----------*/
-
-/*
- * waits for a completion of an I2C transfer
- *
- * returns 0: success, transfer completes
- * 1: error, transfer does not complete, I2C transfer
- * killed, wait loop terminated.
- */
-static int SkI2cWait(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */
-{
- SK_U64 StartTime;
- SK_U64 CurrentTime;
- SK_U32 I2cCtrl;
-
- StartTime = SkOsGetTime(pAC);
-
- do {
- CurrentTime = SkOsGetTime(pAC);
-
- if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
-
- SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
-#endif /* !SK_DIAG */
- return(1);
- }
-
- SK_I2C_GET_CTL(IoC, &I2cCtrl);
-
-#ifdef xYUKON_DBG
- printf("StartTime=%lu, CurrentTime=%lu\n",
- StartTime, CurrentTime);
- if (kbhit()) {
- return(1);
- }
-#endif /* YUKON_DBG */
-
- } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
-
- return(0);
-} /* SkI2cWait */
-
-
-/*
- * waits for a completion of an I2C transfer
- *
- * Returns
- * Nothing
- */
-void SkI2cWaitIrq(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC) /* I/O Context */
-{
- SK_SENSOR *pSen;
- SK_U64 StartTime;
- SK_U32 IrqSrc;
-
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
-
- if (pSen->SenState == SK_SEN_IDLE) {
- return;
- }
-
- StartTime = SkOsGetTime(pAC);
-
- do {
- if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
-
- SK_I2C_STOP(IoC);
-#ifndef SK_DIAG
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
-#endif /* !SK_DIAG */
- return;
- }
-
- SK_IN32(IoC, B0_ISRC, &IrqSrc);
-
- } while ((IrqSrc & IS_I2C_READY) == 0);
-
- pSen->SenState = SK_SEN_IDLE;
- return;
-} /* SkI2cWaitIrq */
-
-/*
- * writes a single byte or 4 bytes into the I2C device
- *
- * returns 0: success
- * 1: error
- */
-static int SkI2cWrite(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 I2cData, /* I2C Data to write */
-int I2cDev, /* I2C Device Address */
-int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int I2cReg, /* I2C Device Register Address */
-int I2cBurst) /* I2C Burst Flag */
-{
- SK_OUT32(IoC, B2_I2C_DATA, I2cData);
-
- SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-
- return(SkI2cWait(pAC, IoC, I2C_WRITE));
-} /* SkI2cWrite*/
-
-
-#ifdef SK_DIAG
-/*
- * reads a single byte or 4 bytes from the I2C device
- *
- * returns the word read
- */
-SK_U32 SkI2cRead(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int I2cDev, /* I2C Device Address */
-int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
-int I2cReg, /* I2C Device Register Address */
-int I2cBurst) /* I2C Burst Flag */
-{
- SK_U32 Data;
-
- SK_OUT32(IoC, B2_I2C_DATA, 0);
- SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
-
- if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
- w_print("%s\n", SKERR_I2C_E002MSG);
- }
-
- SK_IN32(IoC, B2_I2C_DATA, &Data);
-
- return(Data);
-} /* SkI2cRead */
-#endif /* SK_DIAG */
-
-
-/*
- * read a sensor's value
- *
- * This function reads a sensor's value from the I2C sensor chip. The sensor
- * is defined by its index into the sensors database in the struct pAC points
- * to.
- * Returns
- * 1 if the read is completed
- * 0 if the read must be continued (I2C Bus still allocated)
- */
-static int SkI2cReadSensor(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_SENSOR *pSen) /* Sensor to be read */
-{
- if (pSen->SenRead != NULL) {
- return((*pSen->SenRead)(pAC, IoC, pSen));
- }
- else {
- return(0); /* no success */
- }
-} /* SkI2cReadSensor */
-
-/*
- * Do the Init state 0 initialization
- */
-static int SkI2cInit0(
-SK_AC *pAC) /* Adapter Context */
-{
- int i;
-
- /* Begin with first sensor */
- pAC->I2c.CurrSens = 0;
-
- /* Begin with timeout control for state machine */
- pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-
- /* Set sensor number to zero */
- pAC->I2c.MaxSens = 0;
-
-#ifndef SK_DIAG
- /* Initialize Number of Dummy Reads */
- pAC->I2c.DummyReads = SK_MAX_SENSORS;
-#endif
-
- for (i = 0; i < SK_MAX_SENSORS; i++) {
- pAC->I2c.SenTable[i].SenDesc = "unknown";
- pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
- pAC->I2c.SenTable[i].SenThreErrHigh = 0;
- pAC->I2c.SenTable[i].SenThreErrLow = 0;
- pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
- pAC->I2c.SenTable[i].SenThreWarnLow = 0;
- pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
- pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
- pAC->I2c.SenTable[i].SenValue = 0;
- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
- pAC->I2c.SenTable[i].SenErrCts = 0;
- pAC->I2c.SenTable[i].SenBegErrTS = 0;
- pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
- pAC->I2c.SenTable[i].SenRead = NULL;
- pAC->I2c.SenTable[i].SenDev = 0;
- }
-
- /* Now we are "INIT data"ed */
- pAC->I2c.InitLevel = SK_INIT_DATA;
- return(0);
-} /* SkI2cInit0*/
-
-
-/*
- * Do the init state 1 initialization
- *
- * initialize the following register of the LM80:
- * Configuration register:
- * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
- *
- * Interrupt Mask Register 1:
- * - all interrupts are Disabled (0xff)
- *
- * Interrupt Mask Register 2:
- * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
- *
- * Fan Divisor/RST_OUT register:
- * - Divisors set to 1 (bits 00), all others 0s.
- *
- * OS# Configuration/Temperature resolution Register:
- * - all 0s
- *
- */
-static int SkI2cInit1(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC) /* I/O Context */
-{
- int i;
- SK_U8 I2cSwCtrl;
- SK_GEPORT *pPrt; /* GIni Port struct pointer */
-
- if (pAC->I2c.InitLevel != SK_INIT_DATA) {
- /* ReInit not needed in I2C module */
- return(0);
- }
-
- /* Set the Direction of I2C-Data Pin to IN */
- SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
- /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
- SK_I2C_GET_SW(IoC, &I2cSwCtrl);
-
- if ((I2cSwCtrl & I2C_DATA) == 0) {
- /* this is a 32-Bit board */
- pAC->GIni.GIYukon32Bit = SK_TRUE;
- return(0);
- }
-
- /* Check for 64 Bit Yukon without sensors */
- if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
- return(0);
- }
-
- (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
-
- (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
-
- (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
-
- (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-
- (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
- LM80_CFG, 0);
-
- /*
- * MaxSens has to be updated here, because PhyType is not
- * set when performing Init Level 0
- */
- pAC->I2c.MaxSens = 5;
-
- pPrt = &pAC->GIni.GP[0];
-
- if (pAC->GIni.GIGenesis) {
- if (pPrt->PhyType == SK_PHY_BCOM) {
- if (pAC->GIni.GIMacsFound == 1) {
- pAC->I2c.MaxSens += 1;
- }
- else {
- pAC->I2c.MaxSens += 3;
- }
- }
- }
- else {
- pAC->I2c.MaxSens += 3;
- }
-
- for (i = 0; i < pAC->I2c.MaxSens; i++) {
- switch (i) {
- case 0:
- pAC->I2c.SenTable[i].SenDesc = "Temperature";
- pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
- break;
- case 1:
- pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
- break;
- case 2:
- pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
- pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
- break;
- case 3:
- pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
- break;
- case 4:
- if (pAC->GIni.GIGenesis) {
- if (pPrt->PhyType == SK_PHY_BCOM) {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
- }
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
- if (pAC->GIni.GIVauxAvail) {
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
- }
- else {
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
- }
- }
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
- break;
- case 5:
- if (pAC->GIni.GIGenesis) {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5";
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
- }
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
- break;
- case 6:
- if (pAC->GIni.GIGenesis) {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
- }
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
- break;
- case 7:
- if (pAC->GIni.GIGenesis) {
- pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
- pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
- }
- else {
- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
- pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
- }
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
- SKERR_I2C_E001, SKERR_I2C_E001MSG);
- break;
- }
-
- pAC->I2c.SenTable[i].SenValue = 0;
- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
- pAC->I2c.SenTable[i].SenErrCts = 0;
- pAC->I2c.SenTable[i].SenBegErrTS = 0;
- pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
- pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
- pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
- }
-
-#ifndef SK_DIAG
- pAC->I2c.DummyReads = pAC->I2c.MaxSens;
-#endif /* !SK_DIAG */
-
- /* Clear I2C IRQ */
- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-
- /* Now we are I/O initialized */
- pAC->I2c.InitLevel = SK_INIT_IO;
- return(0);
-} /* SkI2cInit1 */
-
-
-/*
- * Init level 2: Start first sensor read.
- */
-static int SkI2cInit2(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC) /* I/O Context */
-{
- int ReadComplete;
- SK_SENSOR *pSen;
-
- if (pAC->I2c.InitLevel != SK_INIT_IO) {
- /* ReInit not needed in I2C module */
- /* Init0 and Init2 not permitted */
- return(0);
- }
-
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
- if (ReadComplete) {
- SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
- }
-
- /* Now we are correctly initialized */
- pAC->I2c.InitLevel = SK_INIT_RUN;
-
- return(0);
-} /* SkI2cInit2*/
-
-
-/*
- * Initialize I2C devices
- *
- * Get the first voltage value and discard it.
- * Go into temperature read mode. A default pointer is not set.
- *
- * The things to be done depend on the init level in the parameter list:
- * Level 0:
- * Initialize only the data structures. Do NOT access hardware.
- * Level 1:
- * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
- * Level 2:
- * Everything is possible. Interrupts may be used from now on.
- *
- * return:
- * 0 = success
- * other = error.
- */
-int SkI2cInit(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */
-int Level) /* Init Level */
-{
-
- switch (Level) {
- case SK_INIT_DATA:
- return(SkI2cInit0(pAC));
- case SK_INIT_IO:
- return(SkI2cInit1(pAC, IoC));
- case SK_INIT_RUN:
- return(SkI2cInit2(pAC, IoC));
- default:
- break;
- }
-
- return(0);
-} /* SkI2cInit */
-
-
-#ifndef SK_DIAG
-
-/*
- * Interrupt service function for the I2C Interface
- *
- * Clears the Interrupt source
- *
- * Reads the register and check it for sending a trap.
- *
- * Starts the timer if necessary.
- */
-void SkI2cIsr(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC) /* I/O Context */
-{
- SK_EVPARA Para;
-
- /* Clear I2C IRQ */
- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
-
- Para.Para64 = 0;
- SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
-} /* SkI2cIsr */
-
-
-/*
- * Check this sensors Value against the threshold and send events.
- */
-static void SkI2cCheckSensor(
-SK_AC *pAC, /* Adapter Context */
-SK_SENSOR *pSen)
-{
- SK_EVPARA ParaLocal;
- SK_BOOL TooHigh; /* Is sensor too high? */
- SK_BOOL TooLow; /* Is sensor too low? */
- SK_U64 CurrTime; /* Current Time */
- SK_BOOL DoTrapSend; /* We need to send a trap */
- SK_BOOL DoErrLog; /* We need to log the error */
- SK_BOOL IsError; /* We need to log the error */
-
- /* Check Dummy Reads first */
- if (pAC->I2c.DummyReads > 0) {
- pAC->I2c.DummyReads--;
- return;
- }
-
- /* Get the current time */
- CurrTime = SkOsGetTime(pAC);
-
- /* Set para to the most useful setting: The current sensor. */
- ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
-
- /* Check the Value against the thresholds. First: Error Thresholds */
- TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
- TooLow = (pSen->SenValue < pSen->SenThreErrLow);
-
- IsError = SK_FALSE;
- if (TooHigh || TooLow) {
- /* Error condition is satisfied */
- DoTrapSend = SK_TRUE;
- DoErrLog = SK_TRUE;
-
- /* Now error condition is satisfied */
- IsError = SK_TRUE;
-
- if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
- /* This state is the former one */
-
- /* So check first whether we have to send a trap */
- if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
- CurrTime) {
- /*
- * Do NOT send the Trap. The hold back time
- * has to run out first.
- */
- DoTrapSend = SK_FALSE;
- }
-
- /* Check now whether we have to log an Error */
- if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
- CurrTime) {
- /*
- * Do NOT log the error. The hold back time
- * has to run out first.
- */
- DoErrLog = SK_FALSE;
- }
- }
- else {
- /* We came from a different state -> Set Begin Time Stamp */
- pSen->SenBegErrTS = CurrTime;
- pSen->SenErrFlag = SK_SEN_ERR_ERR;
- }
-
- if (DoTrapSend) {
- /* Set current Time */
- pSen->SenLastErrTrapTS = CurrTime;
- pSen->SenErrCts++;
-
- /* Queue PNMI Event */
- SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
- SK_PNMI_EVT_SEN_ERR_UPP :
- SK_PNMI_EVT_SEN_ERR_LOW),
- ParaLocal);
- }
-
- if (DoErrLog) {
- /* Set current Time */
- pSen->SenLastErrLogTS = CurrTime;
-
- if (pSen->SenType == SK_SEN_TEMP) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
- }
- else if (pSen->SenType == SK_SEN_VOLT) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
- }
- }
- }
-
- /* Check the Value against the thresholds */
- /* 2nd: Warning thresholds */
- TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
- TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
-
- if (!IsError && (TooHigh || TooLow)) {
- /* Error condition is satisfied */
- DoTrapSend = SK_TRUE;
- DoErrLog = SK_TRUE;
-
- if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
- /* This state is the former one */
-
- /* So check first whether we have to send a trap */
- if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
- /*
- * Do NOT send the Trap. The hold back time
- * has to run out first.
- */
- DoTrapSend = SK_FALSE;
- }
-
- /* Check now whether we have to log an Error */
- if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
- /*
- * Do NOT log the error. The hold back time
- * has to run out first.
- */
- DoErrLog = SK_FALSE;
- }
- }
- else {
- /* We came from a different state -> Set Begin Time Stamp */
- pSen->SenBegWarnTS = CurrTime;
- pSen->SenErrFlag = SK_SEN_ERR_WARN;
- }
-
- if (DoTrapSend) {
- /* Set current Time */
- pSen->SenLastWarnTrapTS = CurrTime;
- pSen->SenWarnCts++;
-
- /* Queue PNMI Event */
- SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
- SK_PNMI_EVT_SEN_WAR_UPP :
- SK_PNMI_EVT_SEN_WAR_LOW),
- ParaLocal);
- }
-
- if (DoErrLog) {
- /* Set current Time */
- pSen->SenLastWarnLogTS = CurrTime;
-
- if (pSen->SenType == SK_SEN_TEMP) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
- }
- else if (pSen->SenType == SK_SEN_VOLT) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
- }
- }
- }
-
- /* Check for NO error at all */
- if (!IsError && !TooHigh && !TooLow) {
- /* Set o.k. Status if no error and no warning condition */
- pSen->SenErrFlag = SK_SEN_ERR_OK;
- }
-
- /* End of check against the thresholds */
-
- /* Bug fix AF: 16.Aug.2001: Correct the init base
- * of LM80 sensor.
- */
- if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
-
- pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
- if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
- /* 5V PCI-IO Voltage */
- pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
- pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
- }
- else {
- /* 3.3V PCI-IO Voltage */
- pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
- pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
- }
- }
-
-#ifdef TEST_ONLY
- /* Dynamic thresholds also for VAUX of LM80 sensor */
- if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
-
- pSen->SenInit = SK_SEN_DYN_INIT_NONE;
-
- /* 3.3V VAUX Voltage */
- if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
- pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
- pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
- }
- /* 0V VAUX Voltage */
- else {
- pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
- pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
- }
- }
-
- /*
- * Check initialization state:
- * The VIO Thresholds need adaption
- */
- if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
- pSen->SenValue > SK_SEN_WARNLOW2C &&
- pSen->SenValue < SK_SEN_WARNHIGH2) {
- pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
- pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
- pSen->SenInit = SK_TRUE;
- }
-
- if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
- pSen->SenValue > SK_SEN_WARNLOW2 &&
- pSen->SenValue < SK_SEN_WARNHIGH2C) {
- pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
- pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
- pSen->SenInit = SK_TRUE;
- }
-#endif
-
- if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
- }
-} /* SkI2cCheckSensor */
-
-
-/*
- * The only Event to be served is the timeout event
- *
- */
-int SkI2cEvent(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Event, /* Module specific Event */
-SK_EVPARA Para) /* Event specific Parameter */
-{
- int ReadComplete;
- SK_SENSOR *pSen;
- SK_U32 Time;
- SK_EVPARA ParaLocal;
- int i;
-
- /* New case: no sensors */
- if (pAC->I2c.MaxSens == 0) {
- return(0);
- }
-
- switch (Event) {
- case SK_I2CEV_IRQ:
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
- if (ReadComplete) {
- /* Check sensor against defined thresholds */
- SkI2cCheckSensor(pAC, pSen);
-
- /* Increment Current sensor and set appropriate Timeout */
- pAC->I2c.CurrSens++;
- if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
- pAC->I2c.CurrSens = 0;
- Time = SK_I2C_TIM_LONG;
- }
- else {
- Time = SK_I2C_TIM_SHORT;
- }
-
- /* Start Timer */
- ParaLocal.Para64 = (SK_U64)0;
-
- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
- }
- else {
- /* Start Timer */
- ParaLocal.Para64 = (SK_U64)0;
-
- pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
-
- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
- }
- break;
- case SK_I2CEV_TIM:
- if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
-
- ParaLocal.Para64 = (SK_U64)0;
- SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
-
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
-
- if (ReadComplete) {
- /* Check sensor against defined thresholds */
- SkI2cCheckSensor(pAC, pSen);
-
- /* Increment Current sensor and set appropriate Timeout */
- pAC->I2c.CurrSens++;
- if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
- pAC->I2c.CurrSens = 0;
- Time = SK_I2C_TIM_LONG;
- }
- else {
- Time = SK_I2C_TIM_SHORT;
- }
-
- /* Start Timer */
- ParaLocal.Para64 = (SK_U64)0;
-
- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
- }
- }
- else {
- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
- pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
- SK_I2C_STOP(IoC);
-
- /* Increment Current sensor and set appropriate Timeout */
- pAC->I2c.CurrSens++;
- if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
- pAC->I2c.CurrSens = 0;
- Time = SK_I2C_TIM_LONG;
- }
- else {
- Time = SK_I2C_TIM_SHORT;
- }
-
- /* Start Timer */
- ParaLocal.Para64 = (SK_U64)0;
-
- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
-
- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
- }
- break;
- case SK_I2CEV_CLEAR:
- for (i = 0; i < SK_MAX_SENSORS; i++) {
- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
- pAC->I2c.SenTable[i].SenErrCts = 0;
- pAC->I2c.SenTable[i].SenWarnCts = 0;
- pAC->I2c.SenTable[i].SenBegErrTS = 0;
- pAC->I2c.SenTable[i].SenBegWarnTS = 0;
- pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
- pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
- pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
- pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
- }
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
- }
-
- return(0);
-} /* SkI2cEvent*/
-
-#endif /* !SK_DIAG */
diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c
deleted file mode 100644
index a204f5bb55d..00000000000
--- a/drivers/net/sk98lin/sklm80.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/******************************************************************************
- *
- * Name: sklm80.c
- * Project: Gigabit Ethernet Adapters, TWSI-Module
- * Version: $Revision: 1.22 $
- * Date: $Date: 2003/10/20 09:08:21 $
- * Purpose: Functions to access Voltage and Temperature Sensor (LM80)
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- LM80 functions
-*/
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. ";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/lm80.h"
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#define BREAK_OR_WAIT(pAC,IoC,Event) break
-
-/*
- * read a sensors value (LM80 specific)
- *
- * This function reads a sensors value from the I2C sensor chip LM80.
- * The sensor is defined by its index into the sensors database in the struct
- * pAC points to.
- *
- * Returns 1 if the read is completed
- * 0 if the read must be continued (I2C Bus still allocated)
- */
-int SkLm80ReadSensor(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context needed in level 1 and 2 */
-SK_SENSOR *pSen) /* Sensor to be read */
-{
- SK_I32 Value;
-
- switch (pSen->SenState) {
- case SK_SEN_IDLE:
- /* Send address to ADDR register */
- SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0);
-
- pSen->SenState = SK_SEN_VALUE ;
- BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-
- case SK_SEN_VALUE:
- /* Read value from data register */
- SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
-
- Value &= 0xff; /* only least significant byte is valid */
-
- /* Do NOT check the Value against the thresholds */
- /* Checking is done in the calling instance */
-
- if (pSen->SenType == SK_SEN_VOLT) {
- /* Voltage sensor */
- pSen->SenValue = Value * SK_LM80_VT_LSB;
- pSen->SenState = SK_SEN_IDLE ;
- return(1);
- }
-
- if (pSen->SenType == SK_SEN_FAN) {
- if (Value != 0 && Value != 0xff) {
- /* Fan speed counter */
- pSen->SenValue = SK_LM80_FAN_FAKTOR/Value;
- }
- else {
- /* Indicate Fan error */
- pSen->SenValue = 0;
- }
- pSen->SenState = SK_SEN_IDLE ;
- return(1);
- }
-
- /* First: correct the value: it might be negative */
- if ((Value & 0x80) != 0) {
- /* Value is negative */
- Value = Value - 256;
- }
-
- /* We have a temperature sensor and need to get the signed extension.
- * For now we get the extension from the last reading, so in the normal
- * case we won't see flickering temperatures.
- */
- pSen->SenValue = (Value * SK_LM80_TEMP_LSB) +
- (pSen->SenValue % SK_LM80_TEMP_LSB);
-
- /* Send address to ADDR register */
- SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
-
- pSen->SenState = SK_SEN_VALEXT ;
- BREAK_OR_WAIT(pAC, IoC, I2C_READ);
-
- case SK_SEN_VALEXT:
- /* Read value from data register */
- SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value));
- Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */
-
- /* cut the LSB bit */
- pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) *
- SK_LM80_TEMP_LSB);
-
- if (pSen->SenValue < 0) {
- /* Value negative: The bit value must be subtracted */
- pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
- }
- else {
- /* Value positive: The bit value must be added */
- pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB);
- }
-
- pSen->SenState = SK_SEN_IDLE ;
- return(1);
-
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG);
- return(1);
- }
-
- /* Not completed */
- return(0);
-}
-
diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c
deleted file mode 100644
index 0275b4f71d9..00000000000
--- a/drivers/net/sk98lin/skqueue.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/******************************************************************************
- *
- * Name: skqueue.c
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.20 $
- * Date: $Date: 2003/09/16 13:44:00 $
- * Purpose: Management of an event queue.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- * Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/skqueue.h" /* Queue Definitions */
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- Event queue management.
-
- General Description:
-
- */
-intro()
-{}
-#endif
-
-#define PRINTF(a,b,c)
-
-/*
- * init event queue management
- *
- * Must be called during init level 0.
- */
-void SkEventInit(
-SK_AC *pAC, /* Adapter context */
-SK_IOC Ioc, /* IO context */
-int Level) /* Init level */
-{
- switch (Level) {
- case SK_INIT_DATA:
- pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue;
- break;
- default:
- break;
- }
-}
-
-/*
- * add event to queue
- */
-void SkEventQueue(
-SK_AC *pAC, /* Adapters context */
-SK_U32 Class, /* Event Class */
-SK_U32 Event, /* Event to be queued */
-SK_EVPARA Para) /* Event parameter */
-{
- pAC->Event.EvPut->Class = Class;
- pAC->Event.EvPut->Event = Event;
- pAC->Event.EvPut->Para = Para;
-
- if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
- pAC->Event.EvPut = pAC->Event.EvQueue;
-
- if (pAC->Event.EvPut == pAC->Event.EvGet) {
- SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
- }
-}
-
-/*
- * event dispatcher
- * while event queue is not empty
- * get event from queue
- * send command to state machine
- * end
- * return error reported by individual Event function
- * 0 if no error occured.
- */
-int SkEventDispatcher(
-SK_AC *pAC, /* Adapters Context */
-SK_IOC Ioc) /* Io context */
-{
- SK_EVENTELEM *pEv; /* pointer into queue */
- SK_U32 Class;
- int Rtv;
-
- pEv = pAC->Event.EvGet;
-
- PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
-
- while (pEv != pAC->Event.EvPut) {
- PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event);
-
- switch (Class = pEv->Class) {
-#ifndef SK_USE_LAC_EV
-#ifndef SK_SLIM
- case SKGE_RLMT: /* RLMT Event */
- Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_I2C: /* I2C Event */
- Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_PNMI: /* PNMI Event */
- Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#endif /* not SK_SLIM */
-#endif /* not SK_USE_LAC_EV */
- case SKGE_DRV: /* Driver Event */
- Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#ifndef SK_USE_SW_TIMER
- case SKGE_HWAC:
- Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#else /* !SK_USE_SW_TIMER */
- case SKGE_SWT :
- Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#endif /* !SK_USE_SW_TIMER */
-#ifdef SK_USE_LAC_EV
- case SKGE_LACP :
- Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_RSF :
- Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_MARKER :
- Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
- case SKGE_FD :
- Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#endif /* SK_USE_LAC_EV */
-#ifdef SK_USE_CSUM
- case SKGE_CSUM :
- Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
- break;
-#endif /* SK_USE_CSUM */
- default :
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG);
- Rtv = 0;
- }
-
- if (Rtv != 0) {
- return(Rtv);
- }
-
- if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT])
- pEv = pAC->Event.EvQueue;
-
- /* Renew get: it is used in queue_events to detect overruns */
- pAC->Event.EvGet = pEv;
- }
-
- return(0);
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c
deleted file mode 100644
index be8d1ccddf6..00000000000
--- a/drivers/net/sk98lin/skrlmt.c
+++ /dev/null
@@ -1,3257 +0,0 @@
-/******************************************************************************
- *
- * Name: skrlmt.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.69 $
- * Date: $Date: 2003/04/15 09:39:22 $
- * Purpose: Manage links on SK-NET Adapters, esp. redundant ones.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * Description:
- *
- * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters.
- * It is mainly intended for adapters with more than one link.
- * For such adapters, this module realizes Redundant Link ManagemenT (RLMT).
- *
- * Include File Hierarchy:
- *
- * "skdrv1st.h"
- * "skdrv2nd.h"
- *
- ******************************************************************************/
-
-#ifndef lint
-static const char SysKonnectFileId[] =
- "@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell.";
-#endif /* !defined(lint) */
-
-#define __SKRLMT_C
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* cplusplus */
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* defines ********************************************************************/
-
-#ifndef SK_HWAC_LINK_LED
-#define SK_HWAC_LINK_LED(a,b,c,d)
-#endif /* !defined(SK_HWAC_LINK_LED) */
-
-#ifndef DEBUG
-#define RLMT_STATIC static
-#else /* DEBUG */
-#define RLMT_STATIC
-
-#ifndef SK_LITTLE_ENDIAN
-/* First 32 bits */
-#define OFFS_LO32 1
-
-/* Second 32 bits */
-#define OFFS_HI32 0
-#else /* SK_LITTLE_ENDIAN */
-/* First 32 bits */
-#define OFFS_LO32 0
-
-/* Second 32 bits */
-#define OFFS_HI32 1
-#endif /* SK_LITTLE_ENDIAN */
-
-#endif /* DEBUG */
-
-/* ----- Private timeout values ----- */
-
-#define SK_RLMT_MIN_TO_VAL 125000 /* 1/8 sec. */
-#define SK_RLMT_DEF_TO_VAL 1000000 /* 1 sec. */
-#define SK_RLMT_PORTDOWN_TIM_VAL 900000 /* another 0.9 sec. */
-#define SK_RLMT_PORTSTART_TIM_VAL 100000 /* 0.1 sec. */
-#define SK_RLMT_PORTUP_TIM_VAL 2500000 /* 2.5 sec. */
-#define SK_RLMT_SEG_TO_VAL 900000000 /* 15 min. */
-
-/* Assume tick counter increment is 1 - may be set OS-dependent. */
-#ifndef SK_TICK_INCR
-#define SK_TICK_INCR SK_CONSTU64(1)
-#endif /* !defined(SK_TICK_INCR) */
-
-/*
- * Amount that a time stamp must be later to be recognized as "substantially
- * later". This is about 1/128 sec, but above 1 tick counter increment.
- */
-#define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \
- (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR))
-
-/* ----- Private RLMT defaults ----- */
-
-#define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */
-#define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */
-
-/* ----- Private RLMT checking states ----- */
-
-#define SK_RLMT_RCS_SEG 1 /* RLMT Check State: check seg. */
-#define SK_RLMT_RCS_START_SEG 2 /* RLMT Check State: start check seg. */
-#define SK_RLMT_RCS_SEND_SEG 4 /* RLMT Check State: send BPDU packet */
-#define SK_RLMT_RCS_REPORT_SEG 8 /* RLMT Check State: report seg. */
-
-/* ----- Private PORT checking states ----- */
-
-#define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */
-#define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */
-
-/* ----- Private PORT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_PORTSTART_TIM 1100 /* Port start timeout. */
-#define SK_RLMT_PORTUP_TIM 1101 /* Port can now go up. */
-#define SK_RLMT_PORTDOWN_RX_TIM 1102 /* Port did not receive once ... */
-#define SK_RLMT_PORTDOWN 1103 /* Port went down. */
-#define SK_RLMT_PORTDOWN_TX_TIM 1104 /* Partner did not receive ... */
-
-/* ----- Private RLMT events ----- */
-
-/* Note: Update simulation when changing these. */
-#define SK_RLMT_TIM 2100 /* RLMT timeout. */
-#define SK_RLMT_SEG_TIM 2101 /* RLMT segmentation check timeout. */
-
-#define TO_SHORTEN(tim) ((tim) / 2)
-
-/* Error numbers and messages. */
-#define SKERR_RLMT_E001 (SK_ERRBASE_RLMT + 0)
-#define SKERR_RLMT_E001_MSG "No Packet."
-#define SKERR_RLMT_E002 (SKERR_RLMT_E001 + 1)
-#define SKERR_RLMT_E002_MSG "Short Packet."
-#define SKERR_RLMT_E003 (SKERR_RLMT_E002 + 1)
-#define SKERR_RLMT_E003_MSG "Unknown RLMT event."
-#define SKERR_RLMT_E004 (SKERR_RLMT_E003 + 1)
-#define SKERR_RLMT_E004_MSG "PortsUp incorrect."
-#define SKERR_RLMT_E005 (SKERR_RLMT_E004 + 1)
-#define SKERR_RLMT_E005_MSG \
- "Net seems to be segmented (different root bridges are reported on the ports)."
-#define SKERR_RLMT_E006 (SKERR_RLMT_E005 + 1)
-#define SKERR_RLMT_E006_MSG "Duplicate MAC Address detected."
-#define SKERR_RLMT_E007 (SKERR_RLMT_E006 + 1)
-#define SKERR_RLMT_E007_MSG "LinksUp incorrect."
-#define SKERR_RLMT_E008 (SKERR_RLMT_E007 + 1)
-#define SKERR_RLMT_E008_MSG "Port not started but link came up."
-#define SKERR_RLMT_E009 (SKERR_RLMT_E008 + 1)
-#define SKERR_RLMT_E009_MSG "Corrected illegal setting of Preferred Port."
-#define SKERR_RLMT_E010 (SKERR_RLMT_E009 + 1)
-#define SKERR_RLMT_E010_MSG "Ignored illegal Preferred Port."
-
-/* LLC field values. */
-#define LLC_COMMAND_RESPONSE_BIT 1
-#define LLC_TEST_COMMAND 0xE3
-#define LLC_UI 0x03
-
-/* RLMT Packet fields. */
-#define SK_RLMT_DSAP 0
-#define SK_RLMT_SSAP 0
-#define SK_RLMT_CTRL (LLC_TEST_COMMAND)
-#define SK_RLMT_INDICATOR0 0x53 /* S */
-#define SK_RLMT_INDICATOR1 0x4B /* K */
-#define SK_RLMT_INDICATOR2 0x2D /* - */
-#define SK_RLMT_INDICATOR3 0x52 /* R */
-#define SK_RLMT_INDICATOR4 0x4C /* L */
-#define SK_RLMT_INDICATOR5 0x4D /* M */
-#define SK_RLMT_INDICATOR6 0x54 /* T */
-#define SK_RLMT_PACKET_VERSION 0
-
-/* RLMT SPT Flag values. */
-#define SK_RLMT_SPT_FLAG_CHANGE 0x01
-#define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80
-
-/* RLMT SPT Packet fields. */
-#define SK_RLMT_SPT_DSAP 0x42
-#define SK_RLMT_SPT_SSAP 0x42
-#define SK_RLMT_SPT_CTRL (LLC_UI)
-#define SK_RLMT_SPT_PROTOCOL_ID0 0x00
-#define SK_RLMT_SPT_PROTOCOL_ID1 0x00
-#define SK_RLMT_SPT_PROTOCOL_VERSION_ID 0x00
-#define SK_RLMT_SPT_BPDU_TYPE 0x00
-#define SK_RLMT_SPT_FLAGS 0x00 /* ?? */
-#define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */
-#define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define SK_RLMT_SPT_ROOT_PATH_COST0 0x00
-#define SK_RLMT_SPT_ROOT_PATH_COST1 0x00
-#define SK_RLMT_SPT_ROOT_PATH_COST2 0x00
-#define SK_RLMT_SPT_ROOT_PATH_COST3 0x00
-#define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */
-#define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. */
-
-/* Remaining 6 bytes will be the current port address. */
-#define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */
-#define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */
-#define SK_RLMT_SPT_MSG_AGE0 0x00
-#define SK_RLMT_SPT_MSG_AGE1 0x00
-#define SK_RLMT_SPT_MAX_AGE0 0x00
-#define SK_RLMT_SPT_MAX_AGE1 0xFF
-#define SK_RLMT_SPT_HELLO_TIME0 0x00
-#define SK_RLMT_SPT_HELLO_TIME1 0xFF
-#define SK_RLMT_SPT_FWD_DELAY0 0x00
-#define SK_RLMT_SPT_FWD_DELAY1 0x40
-
-/* Size defines. */
-#define SK_RLMT_MIN_PACKET_SIZE 34
-#define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE)
-#define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \
- SK_RLMT_MIN_PACKET_SIZE)
-
-/* ----- RLMT packet types ----- */
-#define SK_PACKET_ANNOUNCE 1 /* Port announcement. */
-#define SK_PACKET_ALIVE 2 /* Alive packet to port. */
-#define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */
-#define SK_PACKET_CHECK_TX 4 /* Check your tx line. */
-
-#ifdef SK_LITTLE_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \
- SK_U8 *_Addr = (SK_U8*)(Addr); \
- SK_U16 _Val = (SK_U16)(Val); \
- *_Addr++ = (SK_U8)(_Val >> 8); \
- *_Addr = (SK_U8)(_Val & 0xFF); \
-}
-#endif /* SK_LITTLE_ENDIAN */
-
-#ifdef SK_BIG_ENDIAN
-#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))
-#endif /* SK_BIG_ENDIAN */
-
-#define AUTONEG_FAILED SK_FALSE
-#define AUTONEG_SUCCESS SK_TRUE
-
-
-/* typedefs *******************************************************************/
-
-/* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */
-typedef struct s_RlmtPacket {
- SK_U8 DstAddr[SK_MAC_ADDR_LEN];
- SK_U8 SrcAddr[SK_MAC_ADDR_LEN];
- SK_U8 TypeLen[2];
- SK_U8 DSap;
- SK_U8 SSap;
- SK_U8 Ctrl;
- SK_U8 Indicator[7];
- SK_U8 RlmtPacketType[2];
- SK_U8 Align1[2];
- SK_U8 Random[4]; /* Random value of requesting(!) station. */
- SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */
- SK_U8 Data[SK_PACKET_DATA_LEN];
-} SK_RLMT_PACKET;
-
-typedef struct s_SpTreeRlmtPacket {
- SK_U8 DstAddr[SK_MAC_ADDR_LEN];
- SK_U8 SrcAddr[SK_MAC_ADDR_LEN];
- SK_U8 TypeLen[2];
- SK_U8 DSap;
- SK_U8 SSap;
- SK_U8 Ctrl;
- SK_U8 ProtocolId[2];
- SK_U8 ProtocolVersionId;
- SK_U8 BpduType;
- SK_U8 Flags;
- SK_U8 RootId[8];
- SK_U8 RootPathCost[4];
- SK_U8 BridgeId[8];
- SK_U8 PortId[2];
- SK_U8 MessageAge[2];
- SK_U8 MaxAge[2];
- SK_U8 HelloTime[2];
- SK_U8 ForwardDelay[2];
-} SK_SPTREE_PACKET;
-
-/* global variables ***********************************************************/
-
-SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}};
-SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}};
-
-/* local variables ************************************************************/
-
-/* None. */
-
-/* functions ******************************************************************/
-
-RLMT_STATIC void SkRlmtCheckSwitch(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 NetIdx);
-RLMT_STATIC void SkRlmtCheckSeg(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_U32 NetIdx);
-RLMT_STATIC void SkRlmtEvtSetNets(
- SK_AC *pAC,
- SK_IOC IoC,
- SK_EVPARA Para);
-
-/******************************************************************************
- *
- * SkRlmtInit - initialize data, set state to init
- *
- * Description:
- *
- * SK_INIT_DATA
- * ============
- *
- * This routine initializes all RLMT-related variables to a known state.
- * The initial state is SK_RLMT_RS_INIT.
- * All ports are initialized to SK_RLMT_PS_INIT.
- *
- *
- * SK_INIT_IO
- * ==========
- *
- * Nothing.
- *
- *
- * SK_INIT_RUN
- * ===========
- *
- * Determine the adapter's random value.
- * Set the hw registers, the "logical MAC address", the
- * RLMT multicast address, and eventually the BPDU multicast address.
- *
- * Context:
- * init, pageable
- *
- * Returns:
- * Nothing.
- */
-void SkRlmtInit(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Level) /* Initialization Level */
-{
- SK_U32 i, j;
- SK_U64 Random;
- SK_EVPARA Para;
- SK_MAC_ADDR VirtualMacAddress;
- SK_MAC_ADDR PhysicalAMacAddress;
- SK_BOOL VirtualMacAddressSet;
- SK_BOOL PhysicalAMacAddressSet;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
- ("RLMT Init level %d.\n", Level))
-
- switch (Level) {
- case SK_INIT_DATA: /* Initialize data structures. */
- SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT));
-
- for (i = 0; i < SK_MAX_MACS; i++) {
- pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT;
- pAC->Rlmt.Port[i].LinkDown = SK_TRUE;
- pAC->Rlmt.Port[i].PortDown = SK_TRUE;
- pAC->Rlmt.Port[i].PortStarted = SK_FALSE;
- pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;
- pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;
- pAC->Rlmt.Port[i].PortNumber = i;
- pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0];
- pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i];
- }
-
- pAC->Rlmt.NumNets = 1;
- for (i = 0; i < SK_MAX_NETS; i++) {
- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */
- /* Just assuming. */
- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
- pAC->Rlmt.Net[i].NetNumber = i;
- }
-
- pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0];
- pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];
-#if SK_MAX_NETS > 1
- pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];
-#endif /* SK_MAX_NETS > 1 */
- break;
-
- case SK_INIT_IO: /* GIMacsFound first available here. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
- ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound))
-
- pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
- /* Initialize HW registers? */
- if (pAC->GIni.GIMacsFound == 1) {
- Para.Para32[0] = SK_RLMT_MODE_CLS;
- Para.Para32[1] = 0;
- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);
- }
- break;
-
- case SK_INIT_RUN:
- /* Ensure RLMT is set to one net. */
- if (pAC->Rlmt.NumNets > 1) {
- Para.Para32[0] = 1;
- Para.Para32[1] = -1;
- SkRlmtEvtSetNets(pAC, IoC, Para);
- }
-
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- Random = SkOsGetTime(pAC);
- *(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;
-
- for (j = 0; j < 4; j++) {
- pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort->
- CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j];
- }
-
- (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-
- /* Add RLMT MC address. */
- (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
- if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) {
- /* Add BPDU MC address. */
- (void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT);
- }
-
- (void)SkAddrMcUpdate(pAC, IoC, i);
- }
-
- VirtualMacAddressSet = SK_FALSE;
- /* Read virtual MAC address from Control Register File. */
- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-
- SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]);
- VirtualMacAddressSet |= VirtualMacAddress.a[j];
- }
-
- PhysicalAMacAddressSet = SK_FALSE;
- /* Read physical MAC address for MAC A from Control Register File. */
- for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
-
- SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]);
- PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j];
- }
-
- /* check if the two mac addresses contain reasonable values */
- if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) {
-
- pAC->Rlmt.RlmtOff = SK_TRUE;
- }
-
- /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD
- and the RLMT_LOOKAHEAD macros */
- else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) {
-
- pAC->Rlmt.RlmtOff = SK_TRUE;
- }
- else {
- pAC->Rlmt.RlmtOff = SK_FALSE;
- }
- break;
-
- default: /* error */
- break;
- }
- return;
-} /* SkRlmtInit */
-
-
-/******************************************************************************
- *
- * SkRlmtBuildCheckChain - build the check chain
- *
- * Description:
- * This routine builds the local check chain:
- * - Each port that is up checks the next port.
- * - The last port that is up checks the first port that is up.
- *
- * Notes:
- * - Currently only local ports are considered when building the chain.
- * - Currently the SuspectState is just reset;
- * it would be better to save it ...
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtBuildCheckChain(
-SK_AC *pAC, /* Adapter Context */
-SK_U32 NetIdx) /* Net Number */
-{
- SK_U32 i;
- SK_U32 NumMacsUp;
- SK_RLMT_PORT * FirstMacUp;
- SK_RLMT_PORT * PrevMacUp;
-
- FirstMacUp = NULL;
- PrevMacUp = NULL;
-
- if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
- for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) {
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
- }
- return; /* Done. */
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SkRlmtBuildCheckChain.\n"))
-
- NumMacsUp = 0;
-
- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0;
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0;
- pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &=
- ~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);
-
- /*
- * If more than two links are detected we should consider
- * checking at least two other ports:
- * 1. the next port that is not LinkDown and
- * 2. the next port that is not PortDown.
- */
- if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
- if (NumMacsUp == 0) {
- FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
- }
- else {
- PrevMacUp->PortCheck[
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr =
- pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress;
- PrevMacUp->PortCheck[
- PrevMacUp->PortsChecked].SuspectTx = SK_FALSE;
- PrevMacUp->PortsChecked++;
- }
- PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i];
- NumMacsUp++;
- }
- }
-
- if (NumMacsUp > 1) {
- PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr =
- FirstMacUp->AddrPort->CurrentMacAddress;
- PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx =
- SK_FALSE;
- PrevMacUp->PortsChecked++;
- }
-
-#ifdef DEBUG
- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Port %d checks %d other ports: %2X.\n", i,
- pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
- pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]))
- }
-#endif /* DEBUG */
-
- return;
-} /* SkRlmtBuildCheckChain */
-
-
-/******************************************************************************
- *
- * SkRlmtBuildPacket - build an RLMT packet
- *
- * Description:
- * This routine sets up an RLMT packet.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF *SkRlmtBuildPacket(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber, /* Sending port */
-SK_U16 PacketType, /* RLMT packet type */
-SK_MAC_ADDR *SrcAddr, /* Source address */
-SK_MAC_ADDR *DestAddr) /* Destination address */
-{
- int i;
- SK_U16 Length;
- SK_MBUF *pMb;
- SK_RLMT_PACKET *pPacket;
-
-#ifdef DEBUG
- SK_U8 CheckSrc = 0;
- SK_U8 CheckDest = 0;
-
- for (i = 0; i < SK_MAC_ADDR_LEN; ++i) {
- CheckSrc |= SrcAddr->a[i];
- CheckDest |= DestAddr->a[i];
- }
-
- if ((CheckSrc == 0) || (CheckDest == 0)) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
- ("SkRlmtBuildPacket: Invalid %s%saddr.\n",
- (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")))
- }
-#endif
-
- if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) {
- pPacket = (SK_RLMT_PACKET*)pMb->pData;
- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
- pPacket->DstAddr[i] = DestAddr->a[i];
- pPacket->SrcAddr[i] = SrcAddr->a[i];
- }
- pPacket->DSap = SK_RLMT_DSAP;
- pPacket->SSap = SK_RLMT_SSAP;
- pPacket->Ctrl = SK_RLMT_CTRL;
- pPacket->Indicator[0] = SK_RLMT_INDICATOR0;
- pPacket->Indicator[1] = SK_RLMT_INDICATOR1;
- pPacket->Indicator[2] = SK_RLMT_INDICATOR2;
- pPacket->Indicator[3] = SK_RLMT_INDICATOR3;
- pPacket->Indicator[4] = SK_RLMT_INDICATOR4;
- pPacket->Indicator[5] = SK_RLMT_INDICATOR5;
- pPacket->Indicator[6] = SK_RLMT_INDICATOR6;
-
- SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]);
-
- for (i = 0; i < 4; i++) {
- pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i];
- }
-
- SK_U16_TO_NETWORK_ORDER(
- SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]);
-
- for (i = 0; i < SK_PACKET_DATA_LEN; i++) {
- pPacket->Data[i] = 0x00;
- }
-
- Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */
- pMb->Length = Length;
- pMb->PortIdx = PortNumber;
- Length -= 14;
- SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);
-
- if (PacketType == SK_PACKET_ALIVE) {
- pAC->Rlmt.Port[PortNumber].TxHelloCts++;
- }
- }
-
- return (pMb);
-} /* SkRlmtBuildPacket */
-
-
-/******************************************************************************
- *
- * SkRlmtBuildSpanningTreePacket - build spanning tree check packet
- *
- * Description:
- * This routine sets up a BPDU packet for spanning tree check.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * NULL or pointer to RLMT mbuf
- */
-RLMT_STATIC SK_MBUF *SkRlmtBuildSpanningTreePacket(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Sending port */
-{
- unsigned i;
- SK_U16 Length;
- SK_MBUF *pMb;
- SK_SPTREE_PACKET *pSPacket;
-
- if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=
- NULL) {
- pSPacket = (SK_SPTREE_PACKET*)pMb->pData;
- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
- pSPacket->DstAddr[i] = BridgeMcAddr.a[i];
- pSPacket->SrcAddr[i] =
- pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
- }
- pSPacket->DSap = SK_RLMT_SPT_DSAP;
- pSPacket->SSap = SK_RLMT_SPT_SSAP;
- pSPacket->Ctrl = SK_RLMT_SPT_CTRL;
-
- pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;
- pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;
- pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;
- pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;
- pSPacket->Flags = SK_RLMT_SPT_FLAGS;
- pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;
- pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;
- pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;
- pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;
- pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;
- pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;
- pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;
- pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;
-
- /*
- * Use logical MAC address as bridge ID and filter these packets
- * on receive.
- */
- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
- pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =
- pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber].
- CurrentMacAddress.a[i];
- }
- pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;
- pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;
- pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;
- pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;
- pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;
- pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;
- pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;
- pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;
- pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;
- pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;
-
- Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */
- pMb->Length = Length;
- pMb->PortIdx = PortNumber;
- Length -= 14;
- SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);
-
- pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++;
- }
-
- return (pMb);
-} /* SkRlmtBuildSpanningTreePacket */
-
-
-/******************************************************************************
- *
- * SkRlmtSend - build and send check packets
- *
- * Description:
- * Depending on the RLMT state and the checking state, several packets
- * are sent through the indicated port.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtSend(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Sending port */
-{
- unsigned j;
- SK_EVPARA Para;
- SK_RLMT_PORT *pRPort;
-
- pRPort = &pAC->Rlmt.Port[PortNumber];
- if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
- if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {
- /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */
- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
- &SkRlmtMcAddr)) != NULL) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- }
- else {
- /*
- * Send a directed RLMT packet to all ports that are
- * checked by the indicated port.
- */
- for (j = 0; j < pRPort->PortsChecked; j++) {
- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
- &pRPort->PortCheck[j].CheckAddr)) != NULL) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- }
- }
- }
-
- if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
- (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) {
- /*
- * Send a BPDU packet to make a connected switch tell us
- * the correct root bridge.
- */
- if ((Para.pParaPtr =
- SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) {
- pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG;
- pRPort->RootIdSet = SK_FALSE;
-
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
- ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber))
- }
- }
- return;
-} /* SkRlmtSend */
-
-
-/******************************************************************************
- *
- * SkRlmtPortReceives - check if port is (going) down and bring it up
- *
- * Description:
- * This routine checks if a port who received a non-BPDU packet
- * needs to go up or needs to be stopped going down.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtPortReceives(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Port to check */
-{
- SK_RLMT_PORT *pRPort;
- SK_EVPARA Para;
-
- pRPort = &pAC->Rlmt.Port[PortNumber];
- pRPort->PortNoRx = SK_FALSE;
-
- if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
- !(pRPort->CheckingState & SK_RLMT_PCS_TX)) {
- /*
- * Port is marked down (rx), but received a non-BPDU packet.
- * Bring it up.
- */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Received on PortDown.\n"))
-
- pRPort->PortState = SK_RLMT_PS_GOING_UP;
- pRPort->GuTimeStamp = SkOsGetTime(pAC);
- Para.Para32[0] = PortNumber;
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
- SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para);
- pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
- /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- } /* PortDown && !SuspectTx */
- else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Stop bringing port down.\n"))
- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
- pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
- /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- } /* PortGoingDown */
-
- return;
-} /* SkRlmtPortReceives */
-
-
-/******************************************************************************
- *
- * SkRlmtPacketReceive - receive a packet for closer examination
- *
- * Description:
- * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtPacketReceive(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_MBUF *pMb) /* Received packet */
-{
-#ifdef xDEBUG
- extern void DumpData(char *p, int size);
-#endif /* DEBUG */
- int i;
- unsigned j;
- SK_U16 PacketType;
- SK_U32 PortNumber;
- SK_ADDR_PORT *pAPort;
- SK_RLMT_PORT *pRPort;
- SK_RLMT_PACKET *pRPacket;
- SK_SPTREE_PACKET *pSPacket;
- SK_EVPARA Para;
-
- PortNumber = pMb->PortIdx;
- pAPort = &pAC->Addr.Port[PortNumber];
- pRPort = &pAC->Rlmt.Port[PortNumber];
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber))
-
- pRPacket = (SK_RLMT_PACKET*)pMb->pData;
- pSPacket = (SK_SPTREE_PACKET*)pRPacket;
-
-#ifdef xDEBUG
- DumpData((char *)pRPacket, 32);
-#endif /* DEBUG */
-
- if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) {
- SkRlmtPortReceives(pAC, IoC, PortNumber);
- }
-
- /* Check destination address. */
-
- if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) &&
- !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) &&
- !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) {
-
- /* Not sent to current MAC or registered MC address => Trash it. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Not for me.\n"))
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- return;
- }
- else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) {
-
- /*
- * Was sent by same port (may happen during port switching
- * or in case of duplicate MAC addresses).
- */
-
- /*
- * Check for duplicate address here:
- * If Packet.Random != My.Random => DupAddr.
- */
- for (i = 3; i >= 0; i--) {
- if (pRPort->Random[i] != pRPacket->Random[i]) {
- break;
- }
- }
-
- /*
- * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply
- * packets (they have the LLC_COMMAND_RESPONSE_BIT set in
- * pRPacket->SSap).
- */
- if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP &&
- pRPacket->Ctrl == SK_RLMT_CTRL &&
- pRPacket->SSap == SK_RLMT_SSAP &&
- pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
- pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
- pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
- pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
- pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
- pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
- pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
-
- /* Error Log entry. */
- SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
- }
- else {
- /* Simply trash it. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Sent by me.\n"))
- }
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- return;
- }
-
- /* Check SuspectTx entries. */
- if (pRPort->PortsSuspect > 0) {
- for (j = 0; j < pRPort->PortsChecked; j++) {
- if (pRPort->PortCheck[j].SuspectTx &&
- SK_ADDR_EQUAL(
- pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) {
- pRPort->PortCheck[j].SuspectTx = SK_FALSE;
- pRPort->PortsSuspect--;
- break;
- }
- }
- }
-
- /* Determine type of packet. */
- if (pRPacket->DSap == SK_RLMT_DSAP &&
- pRPacket->Ctrl == SK_RLMT_CTRL &&
- (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP &&
- pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 &&
- pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 &&
- pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 &&
- pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 &&
- pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 &&
- pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
- pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
-
- /* It's an RLMT packet. */
- PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) |
- pRPacket->RlmtPacketType[1]);
-
- switch (PacketType) {
- case SK_PACKET_ANNOUNCE: /* Not yet used. */
-#if 0
- /* Build the check chain. */
- SkRlmtBuildCheckChain(pAC);
-#endif /* 0 */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Announce.\n"))
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- break;
-
- case SK_PACKET_ALIVE:
- if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Alive Reply.\n"))
-
- if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
- SK_ADDR_EQUAL(
- pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) {
- /* Obviously we could send something. */
- if (pRPort->CheckingState & SK_RLMT_PCS_TX) {
- pRPort->CheckingState &= ~SK_RLMT_PCS_TX;
- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
- }
-
- if ((pRPort->PortState == SK_RLMT_PS_DOWN) &&
- !(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
- pRPort->PortState = SK_RLMT_PS_GOING_UP;
- pRPort->GuTimeStamp = SkOsGetTime(pAC);
-
- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
- Para.Para32[0] = PortNumber;
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->UpTimer,
- SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT,
- SK_RLMT_PORTUP_TIM, Para);
- }
- }
-
- /* Mark sending port as alive? */
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- }
- else { /* Alive Request Packet. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Alive Request.\n"))
-
- pRPort->RxHelloCts++;
-
- /* Answer. */
- for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
- pRPacket->DstAddr[i] = pRPacket->SrcAddr[i];
- pRPacket->SrcAddr[i] =
- pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i];
- }
- pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT;
-
- Para.pParaPtr = pMb;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- break;
-
- case SK_PACKET_CHECK_TX:
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Check your tx line.\n"))
-
- /* A port checking us requests us to check our tx line. */
- pRPort->CheckingState |= SK_RLMT_PCS_TX;
-
- /* Start PortDownTx timer. */
- Para.Para32[0] = PortNumber;
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->DownTxTimer,
- SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
- SK_RLMT_PORTDOWN_TX_TIM, Para);
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
-
- if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber,
- SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress,
- &SkRlmtMcAddr)) != NULL) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- break;
-
- case SK_PACKET_ADDR_CHANGED:
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Address Change.\n"))
-
- /* Build the check chain. */
- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- break;
-
- default:
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
-
- /* RA;:;: ??? */
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- }
- }
- else if (pSPacket->DSap == SK_RLMT_SPT_DSAP &&
- pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
- (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: BPDU Packet.\n"))
-
- /* Spanning Tree packet. */
- pRPort->RxSpHelloCts++;
-
- if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt.
- Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) {
- /*
- * Check segmentation if a new root bridge is set and
- * the segmentation check is not currently running.
- */
- if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) &&
- (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
- (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG)
- != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState &
- SK_RLMT_RCS_SEG) == 0) {
- pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
- SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
- }
-
- /* Store tree view of this port. */
- for (i = 0; i < 8; i++) {
- pRPort->Root.Id[i] = pSPacket->RootId[i];
- }
- pRPort->RootIdSet = SK_TRUE;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
- ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
- PortNumber,
- pRPort->Root.Id[0], pRPort->Root.Id[1],
- pRPort->Root.Id[2], pRPort->Root.Id[3],
- pRPort->Root.Id[4], pRPort->Root.Id[5],
- pRPort->Root.Id[6], pRPort->Root.Id[7]))
- }
-
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState &
- SK_RLMT_RCS_REPORT_SEG) != 0) {
- SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber);
- }
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
- ("SkRlmtPacketReceive: Unknown Packet Type.\n"))
-
- /* Unknown packet. */
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- }
- return;
-} /* SkRlmtPacketReceive */
-
-
-/******************************************************************************
- *
- * SkRlmtCheckPort - check if a port works
- *
- * Description:
- * This routine checks if a port whose link is up received something
- * and if it seems to transmit successfully.
- *
- * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp
- * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg
- * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg
- *
- * if (Rx - RxBpdu == 0) { # No rx.
- * if (state == PsUp) {
- * PortCheckingState |= ChkRx
- * }
- * if (ModeCheckSeg && (Timeout ==
- * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) {
- * RlmtCheckingState |= ChkSeg)
- * PortCheckingState |= ChkSeg
- * }
- * NewTimeout = TO_SHORTEN(Timeout)
- * if (NewTimeout < RLMT_MIN_TIMEOUT) {
- * NewTimeout = RLMT_MIN_TIMEOUT
- * PortState = PsDown
- * ...
- * }
- * }
- * else { # something was received
- * # Set counter to 0 at LinkDown?
- * # No - rx may be reported after LinkDown ???
- * PortCheckingState &= ~ChkRx
- * NewTimeout = RLMT_DEFAULT_TIMEOUT
- * if (RxAck == 0) {
- * possible reasons:
- * is my tx line bad? --
- * send RLMT multicast and report
- * back internally? (only possible
- * between ports on same adapter)
- * }
- * if (RxChk == 0) {
- * possible reasons:
- * - tx line of port set to check me
- * maybe bad
- * - no other port/adapter available or set
- * to check me
- * - adapter checking me has a longer
- * timeout
- * ??? anything that can be done here?
- * }
- * }
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * New timeout value.
- */
-RLMT_STATIC SK_U32 SkRlmtCheckPort(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Port to check */
-{
- unsigned i;
- SK_U32 NewTimeout;
- SK_RLMT_PORT *pRPort;
- SK_EVPARA Para;
-
- pRPort = &pAC->Rlmt.Port[PortNumber];
-
- if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
- PortNumber, pRPort->PacketsPerTimeSlot))
-
- /*
- * Check segmentation if there was no receive at least twice
- * in a row (PortNoRx is already set) and the segmentation
- * check is not currently running.
- */
-
- if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) &&
- (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) &&
- !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) {
- pAC->Rlmt.Port[PortNumber].Net->CheckingState |=
- SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
- pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX))
-
- if (pRPort->PortState != SK_RLMT_PS_DOWN) {
- NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
- if (NewTimeout < SK_RLMT_MIN_TO_VAL) {
- NewTimeout = SK_RLMT_MIN_TO_VAL;
- }
-
- if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) {
- Para.Para32[0] = PortNumber;
- pRPort->CheckingState |= SK_RLMT_PCS_RX;
-
- /*
- * What shall we do if the port checked by this one receives
- * our request frames? What's bad - our rx line or his tx line?
- */
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->DownRxTimer,
- SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT,
- SK_RLMT_PORTDOWN_RX_TIM, Para);
-
- for (i = 0; i < pRPort->PortsChecked; i++) {
- if (pRPort->PortCheck[i].SuspectTx) {
- continue;
- }
- pRPort->PortCheck[i].SuspectTx = SK_TRUE;
- pRPort->PortsSuspect++;
- if ((Para.pParaPtr =
- SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX,
- &pAC->Addr.Port[PortNumber].CurrentMacAddress,
- &pRPort->PortCheck[i].CheckAddr)) != NULL) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- }
- }
- }
- else { /* PortDown -- or all partners suspect. */
- NewTimeout = SK_RLMT_DEF_TO_VAL;
- }
- pRPort->PortNoRx = SK_TRUE;
- }
- else { /* A non-BPDU packet was received. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
- PortNumber,
- pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
- pRPort->PacketsPerTimeSlot))
-
- SkRlmtPortReceives(pAC, IoC, PortNumber);
- if (pAC->Rlmt.CheckSwitch) {
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- }
-
- NewTimeout = SK_RLMT_DEF_TO_VAL;
- }
-
- return (NewTimeout);
-} /* SkRlmtCheckPort */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP)
- *
- * Description:
- * This routine selects the port that received a broadcast frame
- * substantially later than all other ports.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectBcRx(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect) /* New active port */
-{
- SK_U64 BcTimeStamp;
- SK_U32 i;
- SK_BOOL PortFound;
-
- BcTimeStamp = 0; /* Not totally necessary, but feeling better. */
- PortFound = SK_FALSE;
-
- /* Select port with the latest TimeStamp. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n",
- i,
- pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
- *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
- *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)))
-
- if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
- if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
- BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp;
- *pSelect = i;
- PortFound = SK_TRUE;
- }
- }
- }
-
- if (PortFound) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Port %d received the last broadcast.\n", *pSelect))
-
- /* Look if another port's time stamp is similar. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (i == *pSelect) {
- continue;
- }
- if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx &&
- (pAC->Rlmt.Port[i].BcTimeStamp >
- BcTimeStamp - SK_RLMT_BC_DELTA ||
- pAC->Rlmt.Port[i].BcTimeStamp +
- SK_RLMT_BC_DELTA > BcTimeStamp)) {
- PortFound = SK_FALSE;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Port %d received a broadcast at a similar time.\n", i))
- break;
- }
- }
- }
-
-#ifdef DEBUG
- if (PortFound) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
- "latest broadcast (%u).\n",
- *pSelect,
- BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp))
- }
-#endif /* DEBUG */
-
- return (PortFound);
-} /* SkRlmtSelectBcRx */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP)
- *
- * Description:
- * This routine selects a good port (it is PortUp && !SuspectRx).
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect) /* New active port */
-{
- SK_U32 i;
- SK_BOOL PortFound;
-
- PortFound = SK_FALSE;
-
- /* Select first port that is PortUp && !SuspectRx. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (!pAC->Rlmt.Port[i].PortDown &&
- !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) {
- *pSelect = i;
- if (!pAC->Rlmt.Port[Active].PortDown &&
- !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) {
- *pSelect = Active;
- }
- if (!pAC->Rlmt.Port[PrefPort].PortDown &&
- !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) {
- *pSelect = PrefPort;
- }
- PortFound = SK_TRUE;
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
- *pSelect))
- break;
- }
- }
- return (PortFound);
-} /* SkRlmtSelectNotSuspect */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP)
- *
- * Description:
- * This routine selects a port that is up.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectUp(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect, /* New active port */
-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
-{
- SK_U32 i;
- SK_BOOL PortFound;
-
- PortFound = SK_FALSE;
-
- /* Select first port that is PortUp. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP &&
- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
- *pSelect = i;
- if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP &&
- pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
- *pSelect = Active;
- }
- if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP &&
- pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
- *pSelect = PrefPort;
- }
- PortFound = SK_TRUE;
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect))
- break;
- }
- }
- return (PortFound);
-} /* SkRlmtSelectUp */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP)
- *
- * Description:
- * This routine selects the port that is going up for the longest time.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect, /* New active port */
-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
-{
- SK_U64 GuTimeStamp;
- SK_U32 i;
- SK_BOOL PortFound;
-
- GuTimeStamp = 0;
- PortFound = SK_FALSE;
-
- /* Select port that is PortGoingUp for the longest time. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
- GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
- *pSelect = i;
- PortFound = SK_TRUE;
- break;
- }
- }
-
- if (!PortFound) {
- return (SK_FALSE);
- }
-
- for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP &&
- pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp &&
- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
- GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp;
- *pSelect = i;
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect))
- return (SK_TRUE);
-} /* SkRlmtSelectGoingUp */
-
-
-/******************************************************************************
- *
- * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP)
- *
- * Description:
- * This routine selects a port that is down.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * SK_BOOL
- */
-RLMT_STATIC SK_BOOL SkRlmtSelectDown(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Active, /* Active port */
-SK_U32 PrefPort, /* Preferred port */
-SK_U32 *pSelect, /* New active port */
-SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */
-{
- SK_U32 i;
- SK_BOOL PortFound;
-
- PortFound = SK_FALSE;
-
- /* Select first port that is PortDown. */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN &&
- pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) {
- *pSelect = i;
- if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN &&
- pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) {
- *pSelect = Active;
- }
- if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN &&
- pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) {
- *pSelect = PrefPort;
- }
- PortFound = SK_TRUE;
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect))
- break;
- }
- }
- return (PortFound);
-} /* SkRlmtSelectDown */
-
-
-/******************************************************************************
- *
- * SkRlmtCheckSwitch - select new active port and switch to it
- *
- * Description:
- * This routine decides which port should be the active one and queues
- * port switching if necessary.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtCheckSwitch(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 NetIdx) /* Net index */
-{
- SK_EVPARA Para;
- SK_U32 Active;
- SK_U32 PrefPort;
- SK_U32 i;
- SK_BOOL PortFound;
-
- Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */
- PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */
- PortFound = SK_FALSE;
- pAC->Rlmt.CheckSwitch = SK_FALSE;
-
-#if 0 /* RW 2001/10/18 - active port becomes always prefered one */
- if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */
- /* disable auto-fail back */
- PrefPort = Active;
- }
-#endif
-
- if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) {
- /* Last link went down - shut down the net. */
- pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN;
- Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP;
- Para.Para32[1] = NetIdx;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para);
-
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
- Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
- Para.Para32[1] = NetIdx;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
- return;
- } /* pAC->Rlmt.LinksUp == 0 */
- else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 &&
- pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) {
- /* First link came up - get the net up. */
- pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP;
-
- /*
- * If pAC->Rlmt.ActivePort != Para.Para32[0],
- * the DRV switches to the port that came up.
- */
- for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) {
- if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) {
- if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) {
- i = Active;
- }
- if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) {
- i = PrefPort;
- }
- PortFound = SK_TRUE;
- break;
- }
- }
-
- if (PortFound) {
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
- Para.Para32[1] = NetIdx;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
-
- pAC->Rlmt.Net[NetIdx].ActivePort = i;
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber;
- Para.Para32[1] = NetIdx;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
-
- if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
- (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
- pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
- SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
- CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
- /*
- * Send announce packet to RLMT multicast address to force
- * switches to learn the new location of the logical MAC address.
- */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- }
- }
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG);
- }
-
- return;
- } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */
- else { /* Cannot be reached in dual-net mode. */
- Para.Para32[0] = Active;
-
- /*
- * Preselection:
- * If RLMT Mode != CheckLinkState
- * select port that received a broadcast frame substantially later
- * than all other ports
- * else select first port that is not SuspectRx
- * else select first port that is PortUp
- * else select port that is PortGoingUp for the longest time
- * else select first port that is PortDown
- * else stop.
- *
- * For the preselected port:
- * If ActivePort is equal in quality, select ActivePort.
- *
- * If PrefPort is equal in quality, select PrefPort.
- *
- * If ActivePort != SelectedPort,
- * If old ActivePort is LinkDown,
- * SwitchHard
- * else
- * SwitchSoft
- */
- /* check of ChgBcPrio flag added */
- if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
- (!pAC->Rlmt.Net[0].ChgBcPrio)) {
-
- if (!PortFound) {
- PortFound = SkRlmtSelectBcRx(
- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectNotSuspect(
- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
- }
- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
- /* with changed priority for last broadcast received */
- if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) &&
- (pAC->Rlmt.Net[0].ChgBcPrio)) {
- if (!PortFound) {
- PortFound = SkRlmtSelectNotSuspect(
- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectBcRx(
- pAC, IoC, Active, PrefPort, &Para.Para32[1]);
- }
- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
- if (!PortFound) {
- PortFound = SkRlmtSelectUp(
- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectUp(
- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectGoingUp(
- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectGoingUp(
- pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
- }
-
- if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) {
- if (!PortFound) {
- PortFound = SkRlmtSelectDown(pAC, IoC,
- Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS);
- }
-
- if (!PortFound) {
- PortFound = SkRlmtSelectDown(pAC, IoC,
- Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED);
- }
- } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */
-
- if (PortFound) {
-
- if (Para.Para32[1] != Active) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Active: %d, Para1: %d.\n", Active, Para.Para32[1]))
- pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
- Port[Para.Para32[0]]->PortNumber;
- Para.Para32[1] = pAC->Rlmt.Net[NetIdx].
- Port[Para.Para32[1]]->PortNumber;
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE);
- if (pAC->Rlmt.Port[Active].LinkDown) {
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para);
- }
- else {
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para);
- }
- Para.Para32[1] = NetIdx;
- Para.Para32[0] =
- pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para);
- Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
- Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para);
- if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
- (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0],
- SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress,
- &SkRlmtMcAddr)) != NULL) {
- /*
- * Send announce packet to RLMT multicast address to force
- * switches to learn the new location of the logical
- * MAC address.
- */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
- } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */
- } /* Para.Para32[1] != Active */
- } /* PortFound */
- else {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG);
- }
- } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */
- return;
-} /* SkRlmtCheckSwitch */
-
-
-/******************************************************************************
- *
- * SkRlmtCheckSeg - Report if segmentation is detected
- *
- * Description:
- * This routine checks if the ports see different root bridges and reports
- * segmentation in such a case.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing.
- */
-RLMT_STATIC void SkRlmtCheckSeg(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 NetIdx) /* Net number */
-{
- SK_EVPARA Para;
- SK_RLMT_NET *pNet;
- SK_U32 i, j;
- SK_BOOL Equal;
-
- pNet = &pAC->Rlmt.Net[NetIdx];
- pNet->RootIdSet = SK_FALSE;
- Equal = SK_TRUE;
-
- for (i = 0; i < pNet->NumPorts; i++) {
- if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) {
- continue;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP,
- ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i,
- pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
- pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
- pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
- pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]))
-
- if (!pNet->RootIdSet) {
- pNet->Root = pNet->Port[i]->Root;
- pNet->RootIdSet = SK_TRUE;
- continue;
- }
-
- for (j = 0; j < 8; j ++) {
- Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j];
- if (!Equal) {
- break;
- }
- }
-
- if (!Equal) {
- SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);
- Para.Para32[0] = NetIdx;
- Para.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para);
-
- pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG;
-
- /* 2000-03-06 RA: New. */
- Para.Para32[0] = NetIdx;
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL,
- SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
- break;
- }
- } /* for (i = 0; i < pNet->NumPorts; i++) */
-
- /* 2000-03-06 RA: Moved here. */
- /* Segmentation check not running anymore. */
- pNet->CheckingState &= ~SK_RLMT_RCS_SEG;
-
-} /* SkRlmtCheckSeg */
-
-
-/******************************************************************************
- *
- * SkRlmtPortStart - initialize port variables and start port
- *
- * Description:
- * This routine initializes a port's variables and issues a PORT_START
- * to the HWAC module. This handles retries if the start fails or the
- * link eventually goes down.
- *
- * Context:
- * runtime, pageable?
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtPortStart(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 PortNumber) /* Port number */
-{
- SK_EVPARA Para;
-
- pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN;
- pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE;
- pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE;
- pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE;
- pAC->Rlmt.Port[PortNumber].CheckingState = 0;
- pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
- Para.Para32[0] = PortNumber;
- Para.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
-} /* SkRlmtPortStart */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPortStartTim - PORT_START_TIM
- *
- * Description:
- * This routine handles PORT_START_TIM events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPortStartTim(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
-{
- SK_U32 i;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
- return;
- }
-
- /*
- * Used to start non-preferred ports if the preferred one
- * does not come up.
- * This timeout needs only be set when starting the first
- * (preferred) port.
- */
- if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
- /* PORT_START failed. */
- for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) {
- if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) {
- SkRlmtPortStart(pAC, IoC,
- pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber);
- }
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
-} /* SkRlmtEvtPortStartTim */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtLinkUp - LINK_UP
- *
- * Description:
- * This routine handles LLINK_UP events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtLinkUp(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */
-{
- SK_U32 i;
- SK_RLMT_PORT *pRPort;
- SK_EVPARA Para2;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]))
-
- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
- if (!pRPort->PortStarted) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_UP Event EMPTY.\n"))
- return;
- }
-
- if (!pRPort->LinkDown) {
- /* RA;:;: Any better solution? */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_UP Event EMPTY.\n"))
- return;
- }
-
- SkTimerStop(pAC, IoC, &pRPort->UpTimer);
- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
- /* Do something if timer already fired? */
-
- pRPort->LinkDown = SK_FALSE;
- pRPort->PortState = SK_RLMT_PS_GOING_UP;
- pRPort->GuTimeStamp = SkOsGetTime(pAC);
- pRPort->BcTimeStamp = 0;
- pRPort->Net->LinksUp++;
- if (pRPort->Net->LinksUp == 1) {
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE);
- }
- else {
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY);
- }
-
- for (i = 0; i < pRPort->Net->NumPorts; i++) {
- if (!pRPort->Net->Port[i]->PortStarted) {
- SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber);
- }
- }
-
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
-
- if (pRPort->Net->LinksUp >= 2) {
- if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) {
- /* Build the check chain. */
- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
- }
- }
-
- /* If the first link comes up, start the periodical RLMT timeout. */
- if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 &&
- (pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) {
- Para2.Para32[0] = pRPort->Net->NetNumber;
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer,
- pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2);
- }
-
- Para2 = Para;
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
- SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
-
- /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
- if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
- (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
- (Para2.pParaPtr =
- SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
- &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
- ) != NULL) {
- /* Send "new" packet to RLMT multicast address. */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
- }
-
- if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
- if ((Para2.pParaPtr =
- SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) {
- pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE;
- pRPort->Net->CheckingState |=
- SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
-
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
-
- Para.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer,
- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_UP Event END.\n"))
-} /* SkRlmtEvtLinkUp */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPortUpTim - PORT_UP_TIM
- *
- * Description:
- * This routine handles PORT_UP_TIM events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPortUpTim(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
-{
- SK_RLMT_PORT *pRPort;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
- return;
- }
-
- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
- if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]))
- return;
- }
-
- pRPort->PortDown = SK_FALSE;
- pRPort->PortState = SK_RLMT_PS_UP;
- pRPort->Net->PortsUp++;
- if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
- if (pAC->Rlmt.NumNets <= 1) {
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- }
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTUP_TIM Event END.\n"))
-} /* SkRlmtEvtPortUpTim */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPortDownTim - PORT_DOWN_*
- *
- * Description:
- * This routine handles PORT_DOWN_* events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPortDownX(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Event, /* Event code */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
-{
- SK_RLMT_PORT *pRPort;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
- Para.Para32[0], Event))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
- return;
- }
-
- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
- if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
- !(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event))
- return;
- }
-
- /* Stop port's timers. */
- SkTimerStop(pAC, IoC, &pRPort->UpTimer);
- SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
- SkTimerStop(pAC, IoC, &pRPort->DownTxTimer);
-
- if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) {
- pRPort->PortState = SK_RLMT_PS_DOWN;
- }
-
- if (!pRPort->PortDown) {
- pRPort->Net->PortsUp--;
- pRPort->PortDown = SK_TRUE;
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para);
- }
-
- pRPort->PacketsPerTimeSlot = 0;
- /* pRPort->DataPacketsPerTimeSlot = 0; */
- pRPort->BpduPacketsPerTimeSlot = 0;
- pRPort->BcTimeStamp = 0;
-
- /*
- * RA;:;: To be checked:
- * - actions at RLMT_STOP: We should not switch anymore.
- */
- if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) {
- if (Para.Para32[0] ==
- pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) {
- /* Active Port went down. */
- SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber);
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event))
-} /* SkRlmtEvtPortDownX */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtLinkDown - LINK_DOWN
- *
- * Description:
- * This routine handles LINK_DOWN events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtLinkDown(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */
-{
- SK_RLMT_PORT *pRPort;
-
- pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
- pRPort->Net->LinksUp--;
- pRPort->LinkDown = SK_TRUE;
- pRPort->PortState = SK_RLMT_PS_LINK_DOWN;
- SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF);
-
- if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) {
- /* Build the check chain. */
- SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
- }
-
- /* Ensure that port is marked down. */
- Para.Para32[1] = -1;
- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_LINK_DOWN Event END.\n"))
-} /* SkRlmtEvtLinkDown */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPortAddr - PORT_ADDR
- *
- * Description:
- * This routine handles PORT_ADDR events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPortAddr(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */
-{
- SK_U32 i, j;
- SK_RLMT_PORT *pRPort;
- SK_MAC_ADDR *pOldMacAddr;
- SK_MAC_ADDR *pNewMacAddr;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
- return;
- }
-
- /* Port's physical MAC address changed. */
- pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress;
- pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress;
-
- /*
- * NOTE: This is not scalable for solutions where ports are
- * checked remotely. There, we need to send an RLMT
- * address change packet - and how do we ensure delivery?
- */
- for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
- pRPort = &pAC->Rlmt.Port[i];
- for (j = 0; j < pRPort->PortsChecked; j++) {
- if (SK_ADDR_EQUAL(
- pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) {
- pRPort->PortCheck[j].CheckAddr = *pNewMacAddr;
- }
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PORT_ADDR Event END.\n"))
-} /* SkRlmtEvtPortAddr */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtStart - START
- *
- * Description:
- * This routine handles START events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtStart(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_EVPARA Para2;
- SK_U32 PortIdx;
- SK_U32 PortNumber;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("All nets should have been started.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >=
- pAC->Rlmt.Net[Para.Para32[0]].NumPorts) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG);
-
- /* Change PrefPort to internal default. */
- Para2.Para32[0] = 0xFFFFFFFF;
- Para2.Para32[1] = Para.Para32[0];
- (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2);
- }
-
- PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort;
- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber;
-
- pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0;
- pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0;
- pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0;
- pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN;
-
- /* Start preferred port. */
- SkRlmtPortStart(pAC, IoC, PortNumber);
-
- /* Start Timer (for first port only). */
- Para2.Para32[0] = PortNumber;
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer,
- SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2);
-
- pAC->Rlmt.NetsStarted++;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_START Event END.\n"))
-} /* SkRlmtEvtStart */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtStop - STOP
- *
- * Description:
- * This routine handles STOP events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtStop(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_EVPARA Para2;
- SK_U32 PortNumber;
- SK_U32 i;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event EMPTY.\n"))
- return;
- }
-
- if (pAC->Rlmt.NetsStarted == 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("All nets are stopped.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event EMPTY.\n"))
- return;
- }
-
- /* Stop RLMT timers. */
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer);
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer);
-
- /* Stop net. */
- pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT;
- pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE;
- Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL;
- Para2.Para32[1] = Para.Para32[0]; /* Net# */
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2);
-
- /* Stop ports. */
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
- if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) {
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer);
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer);
- SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer);
-
- pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT;
- pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE;
- pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE;
- Para2.Para32[0] = PortNumber;
- Para2.Para32[1] = (SK_U32)-1;
- SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2);
- }
- }
-
- pAC->Rlmt.NetsStarted--;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STOP Event END.\n"))
-} /* SkRlmtEvtStop */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtTim - TIM
- *
- * Description:
- * This routine handles TIM events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtTim(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_RLMT_PORT *pRPort;
- SK_U32 Timeout;
- SK_U32 NewTimeout;
- SK_U32 PortNumber;
- SK_U32 i;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_TIM Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_TIM Event EMPTY.\n"))
- return;
- }
-
- if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 ||
- pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) {
- /* Mode changed or all links down: No more link checking. */
- return;
- }
-
-#if 0
- pAC->Rlmt.SwitchCheckCounter--;
- if (pAC->Rlmt.SwitchCheckCounter == 0) {
- pAC->Rlmt.SwitchCheckCounter;
- }
-#endif /* 0 */
-
- NewTimeout = SK_RLMT_DEF_TO_VAL;
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
- PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber;
- pRPort = &pAC->Rlmt.Port[PortNumber];
- if (!pRPort->LinkDown) {
- Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber);
- if (Timeout < NewTimeout) {
- NewTimeout = Timeout;
- }
-
- /*
- * These counters should be set to 0 for all ports before the
- * first frame is sent in the next loop.
- */
- pRPort->PacketsPerTimeSlot = 0;
- /* pRPort->DataPacketsPerTimeSlot = 0; */
- pRPort->BpduPacketsPerTimeSlot = 0;
- }
- }
- pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout;
-
- if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) {
- /*
- * If checking remote ports, also send packets if
- * (LinksUp == 1) &&
- * this port checks at least one (remote) port.
- */
-
- /*
- * Must be new loop, as SkRlmtCheckPort can request to
- * check segmentation when e.g. checking the last port.
- */
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
- if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) {
- SkRlmtSend(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber);
- }
- }
- }
-
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer,
- pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM,
- Para);
-
- if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 &&
- (pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) &&
- (pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) {
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer,
- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para);
- pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG;
- pAC->Rlmt.Net[Para.Para32[0]].CheckingState |=
- SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_TIM Event END.\n"))
-} /* SkRlmtEvtTim */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtSegTim - SEG_TIM
- *
- * Description:
- * This routine handles SEG_TIM events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtSegTim(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
-#ifdef xDEBUG
- int j;
-#endif /* DEBUG */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SEG_TIM Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SEG_TIM Event EMPTY.\n"))
- return;
- }
-
-#ifdef xDEBUG
- for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) {
- SK_ADDR_PORT *pAPort;
- SK_U32 k;
- SK_U16 *InAddr;
- SK_U8 InAddr8[6];
-
- InAddr = (SK_U16 *)&InAddr8[0];
- pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort;
- for (k = 0; k < pAPort->NextExactMatchRlmt; k++) {
- /* Get exact match address k from port j. */
- XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
- XM_EXM(k), InAddr);
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n",
- k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber,
- InAddr8[0], InAddr8[1], InAddr8[2],
- InAddr8[3], InAddr8[4], InAddr8[5],
- pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
- pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
- pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]))
- }
- }
-#endif /* xDEBUG */
-
- SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SEG_TIM Event END.\n"))
-} /* SkRlmtEvtSegTim */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPacketRx - PACKET_RECEIVED
- *
- * Description:
- * This routine handles PACKET_RECEIVED events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPacketRx(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_MBUF *pMb */
-{
- SK_MBUF *pMb;
- SK_MBUF *pNextMb;
- SK_U32 NetNumber;
-
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
-
- /* Should we ignore frames during port switching? */
-
-#ifdef DEBUG
- pMb = Para.pParaPtr;
- if (pMb == NULL) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"))
- }
- else if (pMb->pNext != NULL) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("More than one mbuf or pMb->pNext not set.\n"))
- }
-#endif /* DEBUG */
-
- for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) {
- pNextMb = pMb->pNext;
- pMb->pNext = NULL;
-
- NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber;
- if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) {
- SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
- }
- else {
- SkRlmtPacketReceive(pAC, IoC, pMb);
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PACKET_RECEIVED Event END.\n"))
-} /* SkRlmtEvtPacketRx */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtStatsClear - STATS_CLEAR
- *
- * Description:
- * This routine handles STATS_CLEAR events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtStatsClear(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_U32 i;
- SK_RLMT_PORT *pRPort;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
- return;
- }
-
- /* Clear statistics for logical and physical ports. */
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) {
- pRPort =
- &pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber];
- pRPort->TxHelloCts = 0;
- pRPort->RxHelloCts = 0;
- pRPort->TxSpHelloReqCts = 0;
- pRPort->RxSpHelloCts = 0;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_CLEAR Event END.\n"))
-} /* SkRlmtEvtStatsClear */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtStatsUpdate - STATS_UPDATE
- *
- * Description:
- * This routine handles STATS_UPDATE events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtStatsUpdate(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
- return;
- }
-
- /* Update statistics - currently always up-to-date. */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_STATS_UPDATE Event END.\n"))
-} /* SkRlmtEvtStatsUpdate */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtPrefportChange - PREFPORT_CHANGE
- *
- * Description:
- * This routine handles PREFPORT_CHANGE events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtPrefportChange(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */
-{
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]))
-
- if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[1]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
- return;
- }
-
- /* 0xFFFFFFFF == auto-mode. */
- if (Para.Para32[0] == 0xFFFFFFFF) {
- pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT;
- }
- else {
- if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) {
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
- return;
- }
-
- pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0];
- }
-
- pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0];
-
- if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
- SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
-} /* SkRlmtEvtPrefportChange */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtSetNets - SET_NETS
- *
- * Description:
- * This routine handles SET_NETS events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtSetNets(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */
-{
- int i;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event BEGIN.\n"))
-
- if (Para.Para32[1] != (SK_U32)-1) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad Parameter.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
- Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad number of nets: %d.\n", Para.Para32[0]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- /* Entering and leaving dual mode only allowed while nets are stopped. */
- if (pAC->Rlmt.NetsStarted > 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Changing dual mode only allowed while all nets are stopped.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- if (Para.Para32[0] == 1) {
- if (pAC->Rlmt.NumNets > 1) {
- /* Clear logical MAC addr from second net's active port. */
- (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
- Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL);
- pAC->Rlmt.Net[1].NumPorts = 0;
- }
-
- pAC->Rlmt.NumNets = Para.Para32[0];
- for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */
- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
- /* Just assuming. */
- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
- pAC->Rlmt.Net[i].NetNumber = i;
- }
-
- pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0];
- pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
-
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("RLMT: Changed to one net with two ports.\n"))
- }
- else if (Para.Para32[0] == 2) {
- pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
- pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
- pAC->Rlmt.Net[0].NumPorts =
- pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts;
-
- pAC->Rlmt.NumNets = Para.Para32[0];
- for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) {
- pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT;
- pAC->Rlmt.Net[i].RootIdSet = SK_FALSE;
- pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */
- pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT;
- /* Just assuming. */
- pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort;
- pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE;
- pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL;
-
- pAC->Rlmt.Net[i].NetNumber = i;
- }
-
- /* Set logical MAC addr on second net's active port. */
- (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr.
- Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL);
-
- SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("RLMT: Changed to two nets with one port each.\n"))
- }
- else {
- /* Not implemented for more than two nets. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SetNets not implemented for more than two nets.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
- return;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_SET_NETS Event END.\n"))
-} /* SkRlmtSetNets */
-
-
-/******************************************************************************
- *
- * SkRlmtEvtModeChange - MODE_CHANGE
- *
- * Description:
- * This routine handles MODE_CHANGE events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * Nothing
- */
-RLMT_STATIC void SkRlmtEvtModeChange(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */
-{
- SK_EVPARA Para2;
- SK_U32 i;
- SK_U32 PrevRlmtMode;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
-
- if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Bad NetNumber %d.\n", Para.Para32[1]))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
- return;
- }
-
- Para.Para32[0] |= SK_RLMT_CHECK_LINK;
-
- if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) &&
- Para.Para32[0] != SK_RLMT_MODE_CLS) {
- pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Forced RLMT mode to CLS on single port net.\n"))
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
- return;
- }
-
- /* Update RLMT mode. */
- PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode;
- pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0];
-
- if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) !=
- (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {
- /* SK_RLMT_CHECK_LOC_LINK bit changed. */
- if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 &&
- pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 &&
- pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) {
- /* 20001207 RA: Was "PortsUp == 1". */
- Para2.Para32[0] = Para.Para32[1];
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer,
- pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue,
- SKGE_RLMT, SK_RLMT_TIM, Para2);
- }
- }
-
- if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) !=
- (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) {
- /* SK_RLMT_CHECK_SEG bit changed. */
- for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) {
- (void)SkAddrMcClear(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
- SK_ADDR_PERMANENT | SK_MC_SW_ONLY);
-
- /* Add RLMT MC address. */
- (void)SkAddrMcAdd(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
- &SkRlmtMcAddr, SK_ADDR_PERMANENT);
-
- if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode &
- SK_RLMT_CHECK_SEG) != 0) {
- /* Add BPDU MC address. */
- (void)SkAddrMcAdd(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber,
- &BridgeMcAddr, SK_ADDR_PERMANENT);
-
- if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) {
- if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown &&
- (Para2.pParaPtr = SkRlmtBuildSpanningTreePacket(
- pAC, IoC, i)) != NULL) {
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet =
- SK_FALSE;
- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
- }
- }
- }
- (void)SkAddrMcUpdate(pAC, IoC,
- pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber);
- } /* for ... */
-
- if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) {
- Para2.Para32[0] = Para.Para32[1];
- Para2.Para32[1] = (SK_U32)-1;
- SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer,
- SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2);
- }
- } /* SK_RLMT_CHECK_SEG bit changed. */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("SK_RLMT_MODE_CHANGE Event END.\n"))
-} /* SkRlmtEvtModeChange */
-
-
-/******************************************************************************
- *
- * SkRlmtEvent - a PORT- or an RLMT-specific event happened
- *
- * Description:
- * This routine calls subroutines to handle PORT- and RLMT-specific events.
- *
- * Context:
- * runtime, pageable?
- * may be called after SK_INIT_IO
- *
- * Returns:
- * 0
- */
-int SkRlmtEvent(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-SK_U32 Event, /* Event code */
-SK_EVPARA Para) /* Event-specific parameter */
-{
- switch (Event) {
-
- /* ----- PORT events ----- */
-
- case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */
- SkRlmtEvtPortStartTim(pAC, IoC, Para);
- break;
- case SK_RLMT_LINK_UP: /* From SIRQ. */
- SkRlmtEvtLinkUp(pAC, IoC, Para);
- break;
- case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */
- SkRlmtEvtPortUpTim(pAC, IoC, Para);
- break;
- case SK_RLMT_PORTDOWN: /* From RLMT. */
- case SK_RLMT_PORTDOWN_RX_TIM: /* From RLMT via TIME. */
- case SK_RLMT_PORTDOWN_TX_TIM: /* From RLMT via TIME. */
- SkRlmtEvtPortDownX(pAC, IoC, Event, Para);
- break;
- case SK_RLMT_LINK_DOWN: /* From SIRQ. */
- SkRlmtEvtLinkDown(pAC, IoC, Para);
- break;
- case SK_RLMT_PORT_ADDR: /* From ADDR. */
- SkRlmtEvtPortAddr(pAC, IoC, Para);
- break;
-
- /* ----- RLMT events ----- */
-
- case SK_RLMT_START: /* From DRV. */
- SkRlmtEvtStart(pAC, IoC, Para);
- break;
- case SK_RLMT_STOP: /* From DRV. */
- SkRlmtEvtStop(pAC, IoC, Para);
- break;
- case SK_RLMT_TIM: /* From RLMT via TIME. */
- SkRlmtEvtTim(pAC, IoC, Para);
- break;
- case SK_RLMT_SEG_TIM:
- SkRlmtEvtSegTim(pAC, IoC, Para);
- break;
- case SK_RLMT_PACKET_RECEIVED: /* From DRV. */
- SkRlmtEvtPacketRx(pAC, IoC, Para);
- break;
- case SK_RLMT_STATS_CLEAR: /* From PNMI. */
- SkRlmtEvtStatsClear(pAC, IoC, Para);
- break;
- case SK_RLMT_STATS_UPDATE: /* From PNMI. */
- SkRlmtEvtStatsUpdate(pAC, IoC, Para);
- break;
- case SK_RLMT_PREFPORT_CHANGE: /* From PNMI. */
- SkRlmtEvtPrefportChange(pAC, IoC, Para);
- break;
- case SK_RLMT_MODE_CHANGE: /* From PNMI. */
- SkRlmtEvtModeChange(pAC, IoC, Para);
- break;
- case SK_RLMT_SET_NETS: /* From DRV. */
- SkRlmtEvtSetNets(pAC, IoC, Para);
- break;
-
- /* ----- Unknown events ----- */
-
- default: /* Create error log entry. */
- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
- ("Unknown RLMT Event %d.\n", Event))
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
- break;
- } /* switch() */
-
- return (0);
-} /* SkRlmtEvent */
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c
deleted file mode 100644
index 4e462955ecd..00000000000
--- a/drivers/net/sk98lin/sktimer.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- *
- * Name: sktimer.c
- * Project: Gigabit Ethernet Adapters, Event Scheduler Module
- * Version: $Revision: 1.14 $
- * Date: $Date: 2003/09/16 13:46:51 $
- * Purpose: High level timer functions.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect GmbH.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-
-/*
- * Event queue and dispatcher
- */
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#include "h/skdrv1st.h" /* Driver Specific Definitions */
-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
-
-#ifdef __C2MAN__
-/*
- Event queue management.
-
- General Description:
-
- */
-intro()
-{}
-#endif
-
-
-/* Forward declaration */
-static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart);
-
-
-/*
- * Inits the software timer
- *
- * needs to be called during Init level 1.
- */
-void SkTimerInit(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-int Level) /* Init Level */
-{
- switch (Level) {
- case SK_INIT_DATA:
- pAC->Tim.StQueue = NULL;
- break;
- case SK_INIT_IO:
- SkHwtInit(pAC, Ioc);
- SkTimerDone(pAC, Ioc);
- break;
- default:
- break;
- }
-}
-
-/*
- * Stops a high level timer
- * - If a timer is not in the queue the function returns normally, too.
- */
-void SkTimerStop(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-SK_TIMER *pTimer) /* Timer Pointer to be started */
-{
- SK_TIMER **ppTimPrev;
- SK_TIMER *pTm;
-
- /*
- * remove timer from queue
- */
- pTimer->TmActive = SK_FALSE;
-
- if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
- SkHwtStop(pAC, Ioc);
- }
-
- for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
- ppTimPrev = &pTm->TmNext ) {
-
- if (pTm == pTimer) {
- /*
- * Timer found in queue
- * - dequeue it and
- * - correct delta of the next timer
- */
- *ppTimPrev = pTm->TmNext;
-
- if (pTm->TmNext) {
- /* correct delta of next timer in queue */
- pTm->TmNext->TmDelta += pTm->TmDelta;
- }
- return;
- }
- }
-}
-
-/*
- * Start a high level software timer
- */
-void SkTimerStart(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-SK_TIMER *pTimer, /* Timer Pointer to be started */
-SK_U32 Time, /* Time value */
-SK_U32 Class, /* Event Class for this timer */
-SK_U32 Event, /* Event Value for this timer */
-SK_EVPARA Para) /* Event Parameter for this timer */
-{
- SK_TIMER **ppTimPrev;
- SK_TIMER *pTm;
- SK_U32 Delta;
-
- Time /= 16; /* input is uS, clock ticks are 16uS */
-
- if (!Time)
- Time = 1;
-
- SkTimerStop(pAC, Ioc, pTimer);
-
- pTimer->TmClass = Class;
- pTimer->TmEvent = Event;
- pTimer->TmPara = Para;
- pTimer->TmActive = SK_TRUE;
-
- if (!pAC->Tim.StQueue) {
- /* First Timer to be started */
- pAC->Tim.StQueue = pTimer;
- pTimer->TmNext = NULL;
- pTimer->TmDelta = Time;
-
- SkHwtStart(pAC, Ioc, Time);
-
- return;
- }
-
- /*
- * timer correction
- */
- timer_done(pAC, Ioc, 0);
-
- /*
- * find position in queue
- */
- Delta = 0;
- for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
- ppTimPrev = &pTm->TmNext ) {
-
- if (Delta + pTm->TmDelta > Time) {
- /* Position found */
- /* Here the timer needs to be inserted. */
- break;
- }
- Delta += pTm->TmDelta;
- }
-
- /* insert in queue */
- *ppTimPrev = pTimer;
- pTimer->TmNext = pTm;
- pTimer->TmDelta = Time - Delta;
-
- if (pTm) {
- /* There is a next timer
- * -> correct its Delta value.
- */
- pTm->TmDelta -= pTimer->TmDelta;
- }
-
- /* restart with first */
- SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
-}
-
-
-void SkTimerDone(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc) /* IoContext */
-{
- timer_done(pAC, Ioc, 1);
-}
-
-
-static void timer_done(
-SK_AC *pAC, /* Adapters context */
-SK_IOC Ioc, /* IoContext */
-int Restart) /* Do we need to restart the Hardware timer ? */
-{
- SK_U32 Delta;
- SK_TIMER *pTm;
- SK_TIMER *pTComp; /* Timer completed now now */
- SK_TIMER **ppLast; /* Next field of Last timer to be deq */
- int Done = 0;
-
- Delta = SkHwtRead(pAC, Ioc);
-
- ppLast = &pAC->Tim.StQueue;
- pTm = pAC->Tim.StQueue;
- while (pTm && !Done) {
- if (Delta >= pTm->TmDelta) {
- /* Timer ran out */
- pTm->TmActive = SK_FALSE;
- Delta -= pTm->TmDelta;
- ppLast = &pTm->TmNext;
- pTm = pTm->TmNext;
- }
- else {
- /* We found the first timer that did not run out */
- pTm->TmDelta -= Delta;
- Delta = 0;
- Done = 1;
- }
- }
- *ppLast = NULL;
- /*
- * pTm points to the first Timer that did not run out.
- * StQueue points to the first Timer that run out.
- */
-
- for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
- SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
- }
-
- /* Set head of timer queue to the first timer that did not run out */
- pAC->Tim.StQueue = pTm;
-
- if (Restart && pAC->Tim.StQueue) {
- /* Restart HW timer */
- SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta);
- }
-}
-
-/* End of file */
diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c
deleted file mode 100644
index 1e662aaebf8..00000000000
--- a/drivers/net/sk98lin/skvpd.c
+++ /dev/null
@@ -1,1091 +0,0 @@
-/******************************************************************************
- *
- * Name: skvpd.c
- * Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.37 $
- * Date: $Date: 2003/01/13 10:42:45 $
- * Purpose: Shared software to read and write VPD data
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2003 SysKonnect 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 by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
- Please refer skvpd.txt for information how to include this module
- */
-static const char SysKonnectFileId[] =
- "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
-
-#include "h/skdrv1st.h"
-#include "h/sktypes.h"
-#include "h/skdebug.h"
-#include "h/skdrv2nd.h"
-
-/*
- * Static functions
- */
-#ifndef SK_KR_PROTO
-static SK_VPD_PARA *vpd_find_para(
- SK_AC *pAC,
- const char *key,
- SK_VPD_PARA *p);
-#else /* SK_KR_PROTO */
-static SK_VPD_PARA *vpd_find_para();
-#endif /* SK_KR_PROTO */
-
-/*
- * waits for a completion of a VPD transfer
- * The VPD transfer must complete within SK_TICKS_PER_SEC/16
- *
- * returns 0: success, transfer completes
- * error exit(9) with a error message
- */
-static int VpdWait(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-int event) /* event to wait for (VPD_READ / VPD_write) completion*/
-{
- SK_U64 start_time;
- SK_U16 state;
-
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD wait for %s\n", event?"Write":"Read"));
- start_time = SkOsGetTime(pAC);
- do {
- if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
-
- /* Bug fix AF: Thu Mar 28 2002
- * Do not call: VPD_STOP(pAC, IoC);
- * A pending VPD read cycle can not be aborted by writing
- * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register).
- * Although the write threshold in the OUR-register protects
- * VPD read only space from being overwritten this does not
- * protect a VPD read from being `converted` into a VPD write
- * operation (on the fly). As a consequence the VPD_STOP would
- * delete VPD read only data. In case of any problems with the
- * I2C bus we exit the loop here. The I2C read operation can
- * not be aborted except by a reset (->LR).
- */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR,
- ("ERROR:VPD wait timeout\n"));
- return(1);
- }
-
- VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("state = %x, event %x\n",state,event));
- } while((int)(state & PCI_VPD_FLAG) == event);
-
- return(0);
-}
-
-#ifdef SKDIAG
-
-/*
- * Read the dword at address 'addr' from the VPD EEPROM.
- *
- * Needed Time: MIN 1,3 ms MAX 2,6 ms
- *
- * Note: The DWord is returned in the endianess of the machine the routine
- * is running on.
- *
- * Returns the data read.
- */
-SK_U32 VpdReadDWord(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-int addr) /* VPD address */
-{
- SK_U32 Rtv;
-
- /* start VPD read */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD read dword at 0x%x\n",addr));
- addr &= ~VPD_WRITE; /* ensure the R/W bit is set to read */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr);
-
- /* ignore return code here */
- (void)VpdWait(pAC, IoC, VPD_READ);
-
- /* Don't swap here, it's a data stream of bytes */
- Rtv = 0;
-
- VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD read dword data = 0x%x\n",Rtv));
- return(Rtv);
-}
-
-#endif /* SKDIAG */
-
-/*
- * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- * or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdWriteStream(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-char *buf, /* data buffer */
-int Addr, /* VPD start address */
-int Len) /* number of bytes to read / to write */
-{
- int i;
- int j;
- SK_U16 AdrReg;
- int Rtv;
- SK_U8 * pComp; /* Compare pointer */
- SK_U8 Data; /* Input Data for Compare */
-
- /* Init Compare Pointer */
- pComp = (SK_U8 *) buf;
-
- for (i = 0; i < Len; i++, buf++) {
- if ((i%sizeof(SK_U32)) == 0) {
- /*
- * At the begin of each cycle read the Data Reg
- * So it is initialized even if only a few bytes
- * are written.
- */
- AdrReg = (SK_U16) Addr;
- AdrReg &= ~VPD_WRITE; /* READ operation */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
- /* Wait for termination */
- Rtv = VpdWait(pAC, IoC, VPD_READ);
- if (Rtv != 0) {
- return(i);
- }
- }
-
- /* Write current Byte */
- VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
- *(SK_U8*)buf);
-
- if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
- /* New Address needs to be written to VPD_ADDR reg */
- AdrReg = (SK_U16) Addr;
- Addr += sizeof(SK_U32);
- AdrReg |= VPD_WRITE; /* WRITE operation */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
- /* Wait for termination */
- Rtv = VpdWait(pAC, IoC, VPD_WRITE);
- if (Rtv != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("Write Timed Out\n"));
- return(i - (i%sizeof(SK_U32)));
- }
-
- /*
- * Now re-read to verify
- */
- AdrReg &= ~VPD_WRITE; /* READ operation */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
- /* Wait for termination */
- Rtv = VpdWait(pAC, IoC, VPD_READ);
- if (Rtv != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("Verify Timed Out\n"));
- return(i - (i%sizeof(SK_U32)));
- }
-
- for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
-
- VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
-
- if (Data != *pComp) {
- /* Verify Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("WriteStream Verify Error\n"));
- return(i - (i%sizeof(SK_U32)) + j);
- }
- }
- }
- }
-
- return(Len);
-}
-
-
-/*
- * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
- * or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdReadStream(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-char *buf, /* data buffer */
-int Addr, /* VPD start address */
-int Len) /* number of bytes to read / to write */
-{
- int i;
- SK_U16 AdrReg;
- int Rtv;
-
- for (i = 0; i < Len; i++, buf++) {
- if ((i%sizeof(SK_U32)) == 0) {
- /* New Address needs to be written to VPD_ADDR reg */
- AdrReg = (SK_U16) Addr;
- Addr += sizeof(SK_U32);
- AdrReg &= ~VPD_WRITE; /* READ operation */
-
- VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
-
- /* Wait for termination */
- Rtv = VpdWait(pAC, IoC, VPD_READ);
- if (Rtv != 0) {
- return(i);
- }
- }
- VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
- (SK_U8 *)buf);
- }
-
- return(Len);
-}
-
-/*
- * Read ore writes 'len' bytes of VPD data, starting at 'addr' from
- * or to the I2C EEPROM.
- *
- * Returns number of bytes read / written.
- */
-static int VpdTransferBlock(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC, /* IO Context */
-char *buf, /* data buffer */
-int addr, /* VPD start address */
-int len, /* number of bytes to read / to write */
-int dir) /* transfer direction may be VPD_READ or VPD_WRITE */
-{
- int Rtv; /* Return value */
- int vpd_rom_size;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD %s block, addr = 0x%x, len = %d\n",
- dir ? "write" : "read", addr, len));
-
- if (len == 0)
- return(0);
-
- vpd_rom_size = pAC->vpd.rom_size;
-
- if (addr > vpd_rom_size - 4) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Address error: 0x%x, exp. < 0x%x\n",
- addr, vpd_rom_size - 4));
- return(0);
- }
-
- if (addr + len > vpd_rom_size) {
- len = vpd_rom_size - addr;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("Warning: len was cut to %d\n", len));
- }
-
- if (dir == VPD_READ) {
- Rtv = VpdReadStream(pAC, IoC, buf, addr, len);
- }
- else {
- Rtv = VpdWriteStream(pAC, IoC, buf, addr, len);
- }
-
- return(Rtv);
-}
-
-#ifdef SKDIAG
-
-/*
- * Read 'len' bytes of VPD data, starting at 'addr'.
- *
- * Returns number of bytes read.
- */
-int VpdReadBlock(
-SK_AC *pAC, /* pAC pointer */
-SK_IOC IoC, /* IO Context */
-char *buf, /* buffer were the data should be stored */
-int addr, /* start reading at the VPD address */
-int len) /* number of bytes to read */
-{
- return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
-}
-
-/*
- * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
- *
- * Returns number of bytes writes.
- */
-int VpdWriteBlock(
-SK_AC *pAC, /* pAC pointer */
-SK_IOC IoC, /* IO Context */
-char *buf, /* buffer, holds the data to write */
-int addr, /* start writing at the VPD address */
-int len) /* number of bytes to write */
-{
- return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
-}
-#endif /* SKDIAG */
-
-/*
- * (re)initialize the VPD buffer
- *
- * Reads the VPD data from the EEPROM into the VPD buffer.
- * Get the remaining read only and read / write space.
- *
- * return 0: success
- * 1: fatal VPD error
- */
-static int VpdInit(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC) /* IO Context */
-{
- SK_VPD_PARA *r, rp; /* RW or RV */
- int i;
- unsigned char x;
- int vpd_size;
- SK_U16 dev_id;
- SK_U32 our_reg2;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
-
- VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
-
- VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
-
- pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
-
- /*
- * this function might get used before the hardware is initialized
- * therefore we cannot always trust in GIChipId
- */
- if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 &&
- dev_id != VPD_DEV_ID_GENESIS) ||
- ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 &&
- !pAC->GIni.GIGenesis)) {
-
- /* for Yukon the VPD size is always 256 */
- vpd_size = VPD_SIZE_YUKON;
- }
- else {
- /* Genesis uses the maximum ROM size up to 512 for VPD */
- if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) {
- vpd_size = VPD_SIZE_GENESIS;
- }
- else {
- vpd_size = pAC->vpd.rom_size;
- }
- }
-
- /* read the VPD data into the VPD buffer */
- if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ)
- != vpd_size) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("Block Read Error\n"));
- return(1);
- }
-
- pAC->vpd.vpd_size = vpd_size;
-
- /* Asus K8V Se Deluxe bugfix. Correct VPD content */
- /* MBo April 2004 */
- if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
- ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
- ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
- printk("sk98lin: Asus mainboard with buggy VPD? "
- "Correcting data.\n");
- pAC->vpd.vpd_buf[0x40] = 0x38;
- }
-
-
- /* find the end tag of the RO area */
- if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: RV Tag not found\n"));
- return(1);
- }
-
- if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: Invalid VPD struct size\n"));
- return(1);
- }
- pAC->vpd.v.vpd_free_ro = r->p_len - 1;
-
- /* test the checksum */
- for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
- x += pAC->vpd.vpd_buf[i];
- }
-
- if (x != 0) {
- /* checksum error */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("VPD Checksum Error\n"));
- return(1);
- }
-
- /* find and check the end tag of the RW area */
- if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: RV Tag not found\n"));
- return(1);
- }
-
- if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: Invalid VPD struct size\n"));
- return(1);
- }
- pAC->vpd.v.vpd_free_rw = r->p_len;
-
- /* everything seems to be ok */
- if (pAC->GIni.GIChipId != 0) {
- pAC->vpd.v.vpd_status |= VPD_VALID;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT,
- ("done. Free RO = %d, Free RW = %d\n",
- pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
- return(0);
-}
-
-/*
- * find the Keyword 'key' in the VPD buffer and fills the
- * parameter struct 'p' with it's values
- *
- * returns *p success
- * 0: parameter was not found or VPD encoding error
- */
-static SK_VPD_PARA *vpd_find_para(
-SK_AC *pAC, /* common data base */
-const char *key, /* keyword to find (e.g. "MN") */
-SK_VPD_PARA *p) /* parameter description struct */
-{
- char *v ; /* points to VPD buffer */
- int max; /* Maximum Number of Iterations */
-
- v = pAC->vpd.vpd_buf;
- max = 128;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD find para %s .. ",key));
-
- /* check mandatory resource type ID string (Product Name) */
- if (*v != (char)RES_ID) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Error: 0x%x missing\n", RES_ID));
- return NULL;
- }
-
- if (strcmp(key, VPD_NAME) == 0) {
- p->p_len = VPD_GET_RES_LEN(v);
- p->p_val = VPD_GET_VAL(v);
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("found, len = %d\n", p->p_len));
- return(p);
- }
-
- v += 3 + VPD_GET_RES_LEN(v) + 3;
- for (;; ) {
- if (SK_MEMCMP(key,v,2) == 0) {
- p->p_len = VPD_GET_VPD_LEN(v);
- p->p_val = VPD_GET_VAL(v);
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("found, len = %d\n",p->p_len));
- return(p);
- }
-
- /* exit when reaching the "RW" Tag or the maximum of itera. */
- max--;
- if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
- break;
- }
-
- if (SK_MEMCMP(VPD_RV,v,2) == 0) {
- v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */
- }
- else {
- v += 3 + VPD_GET_VPD_LEN(v);
- }
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("scanning '%c%c' len = %d\n",v[0],v[1],v[2]));
- }
-
-#ifdef DEBUG
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n"));
- if (max == 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Key/Len Encoding error\n"));
- }
-#endif /* DEBUG */
- return NULL;
-}
-
-/*
- * Move 'n' bytes. Begin with the last byte if 'n' is > 0,
- * Start with the last byte if n is < 0.
- *
- * returns nothing
- */
-static void vpd_move_para(
-char *start, /* start of memory block */
-char *end, /* end of memory block to move */
-int n) /* number of bytes the memory block has to be moved */
-{
- char *p;
- int i; /* number of byte copied */
-
- if (n == 0)
- return;
-
- i = (int) (end - start + 1);
- if (n < 0) {
- p = start + n;
- while (i != 0) {
- *p++ = *start++;
- i--;
- }
- }
- else {
- p = end + n;
- while (i != 0) {
- *p-- = *end--;
- i--;
- }
- }
-}
-
-/*
- * setup the VPD keyword 'key' at 'ip'.
- *
- * returns nothing
- */
-static void vpd_insert_key(
-const char *key, /* keyword to insert */
-const char *buf, /* buffer with the keyword value */
-int len, /* length of the value string */
-char *ip) /* inseration point */
-{
- SK_VPD_KEY *p;
-
- p = (SK_VPD_KEY *) ip;
- p->p_key[0] = key[0];
- p->p_key[1] = key[1];
- p->p_len = (unsigned char) len;
- SK_MEMCPY(&p->p_val,buf,len);
-}
-
-/*
- * Setup the VPD end tag "RV" / "RW".
- * Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
- *
- * returns 0: success
- * 1: encoding error
- */
-static int vpd_mod_endtag(
-SK_AC *pAC, /* common data base */
-char *etp) /* end pointer input position */
-{
- SK_VPD_KEY *p;
- unsigned char x;
- int i;
- int vpd_size;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1]));
-
- vpd_size = pAC->vpd.vpd_size;
-
- p = (SK_VPD_KEY *) etp;
-
- if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
- /* something wrong here, encoding error */
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
- ("Encoding Error: invalid end tag\n"));
- return(1);
- }
- if (etp > pAC->vpd.vpd_buf + vpd_size/2) {
- /* create "RW" tag */
- p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1);
- pAC->vpd.v.vpd_free_rw = (int) p->p_len;
- i = pAC->vpd.v.vpd_free_rw;
- etp += 3;
- }
- else {
- /* create "RV" tag */
- p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3);
- pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1;
-
- /* setup checksum */
- for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) {
- x += pAC->vpd.vpd_buf[i];
- }
- p->p_val = (char) 0 - x;
- i = pAC->vpd.v.vpd_free_ro;
- etp += 4;
- }
- while (i) {
- *etp++ = 0x00;
- i--;
- }
-
- return(0);
-}
-
-/*
- * Insert a VPD keyword into the VPD buffer.
- *
- * The keyword 'key' is inserted at the position 'ip' in the
- * VPD buffer.
- * The keywords behind the input position will
- * be moved. The VPD end tag "RV" or "RW" is generated again.
- *
- * returns 0: success
- * 2: value string was cut
- * 4: VPD full, keyword was not written
- * 6: fatal VPD error
- *
- */
-static int VpdSetupPara(
-SK_AC *pAC, /* common data base */
-const char *key, /* keyword to insert */
-const char *buf, /* buffer with the keyword value */
-int len, /* length of the keyword value */
-int type, /* VPD_RO_KEY or VPD_RW_KEY */
-int op) /* operation to do: ADD_KEY or OWR_KEY */
-{
- SK_VPD_PARA vp;
- char *etp; /* end tag position */
- int free; /* remaining space in selected area */
- char *ip; /* input position inside the VPD buffer */
- int rtv; /* return code */
- int head; /* additional haeder bytes to move */
- int found; /* additinoal bytes if the keyword was found */
- int vpd_size;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("VPD setup para key = %s, val = %s\n",key,buf));
-
- vpd_size = pAC->vpd.vpd_size;
-
- rtv = 0;
- ip = NULL;
- if (type == VPD_RW_KEY) {
- /* end tag is "RW" */
- free = pAC->vpd.v.vpd_free_rw;
- etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3);
- }
- else {
- /* end tag is "RV" */
- free = pAC->vpd.v.vpd_free_ro;
- etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4);
- }
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("Free RO = %d, Free RW = %d\n",
- pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw));
-
- head = 0;
- found = 0;
- if (op == OWR_KEY) {
- if (vpd_find_para(pAC, key, &vp)) {
- found = 3;
- ip = vp.p_val - 3;
- free += vp.p_len + 3;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("Overwrite Key\n"));
- }
- else {
- op = ADD_KEY;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
- ("Add Key\n"));
- }
- }
- if (op == ADD_KEY) {
- ip = etp;
- vp.p_len = 0;
- head = 3;
- }
-
- if (len + 3 > free) {
- if (free < 7) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD Buffer Overflow, keyword not written\n"));
- return(4);
- }
- /* cut it again */
- len = free - 3;
- rtv = 2;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD Buffer Full, Keyword was cut\n"));
- }
-
- vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head);
- vpd_insert_key(key, buf, len, ip);
- if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) {
- pAC->vpd.v.vpd_status &= ~VPD_VALID;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD Encoding Error\n"));
- return(6);
- }
-
- return(rtv);
-}
-
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the
- * VPD buffer if not already done.
- *
- * return: A pointer to the vpd_status structure. The structure contains
- * this fields.
- */
-SK_VPD_STATUS *VpdStat(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC) /* IO Context */
-{
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- (void)VpdInit(pAC, IoC);
- }
- return(&pAC->vpd.v);
-}
-
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the VPD
- * buffer if not already done.
- * Scan the VPD buffer for VPD keywords and create the VPD
- * keyword list by copying the keywords to 'buf', all after
- * each other and terminated with a '\0'.
- *
- * Exceptions: o The Resource Type ID String (product name) is called "Name"
- * o The VPD end tags 'RV' and 'RW' are not listed
- *
- * The number of copied keywords is counted in 'elements'.
- *
- * returns 0: success
- * 2: buffer overfull, one or more keywords are missing
- * 6: fatal VPD error
- *
- * example values after returning:
- *
- * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0"
- * *len = 30
- * *elements = 9
- */
-int VpdKeys(
-SK_AC *pAC, /* common data base */
-SK_IOC IoC, /* IO Context */
-char *buf, /* buffer where to copy the keywords */
-int *len, /* buffer length */
-int *elements) /* number of keywords returned */
-{
- char *v;
- int n;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. "));
- *elements = 0;
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- if (VpdInit(pAC, IoC) != 0) {
- *len = 0;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD Init Error, terminated\n"));
- return(6);
- }
- }
-
- if ((signed)strlen(VPD_NAME) + 1 <= *len) {
- v = pAC->vpd.vpd_buf;
- strcpy(buf,VPD_NAME);
- n = strlen(VPD_NAME) + 1;
- buf += n;
- *elements = 1;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
- ("'%c%c' ",v[0],v[1]));
- }
- else {
- *len = 0;
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
- ("buffer overflow\n"));
- return(2);
- }
-
- v += 3 + VPD_GET_RES_LEN(v) + 3;
- for (;; ) {
- /* exit when reaching the "RW" Tag */
- if (SK_MEMCMP(VPD_RW,v,2) == 0) {
- break;
- }
-
- if (SK_MEMCMP(VPD_RV,v,2) == 0) {
- v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */
- continue;
- }
-
- if (n+3 <= *len) {
- SK_MEMCPY(buf,v,2);
- buf += 2;
- *buf++ = '\0';
- n += 3;
- v += 3 + VPD_GET_VPD_LEN(v);
- *elements += 1;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
- ("'%c%c' ",v[0],v[1]));
- }
- else {
- *len = n;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("buffer overflow\n"));
- return(2);
- }
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n"));
- *len = n;
- return(0);
-}
-
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the
- * VPD buffer if not already done. Search for the VPD keyword
- * 'key' and copy its value to 'buf'. Add a terminating '\0'.
- * If the value does not fit into the buffer cut it after
- * 'len' - 1 bytes.
- *
- * returns 0: success
- * 1: keyword not found
- * 2: value string was cut
- * 3: VPD transfer timeout
- * 6: fatal VPD error
- */
-int VpdRead(
-SK_AC *pAC, /* common data base */
-SK_IOC IoC, /* IO Context */
-const char *key, /* keyword to read (e.g. "MN") */
-char *buf, /* buffer where to copy the keyword value */
-int *len) /* buffer length */
-{
- SK_VPD_PARA *p, vp;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key));
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- if (VpdInit(pAC, IoC) != 0) {
- *len = 0;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD init error\n"));
- return(6);
- }
- }
-
- if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
- if (p->p_len > (*(unsigned *)len)-1) {
- p->p_len = *len - 1;
- }
- SK_MEMCPY(buf, p->p_val, p->p_len);
- buf[p->p_len] = '\0';
- *len = p->p_len;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
- ("%c%c%c%c.., len = %d\n",
- buf[0],buf[1],buf[2],buf[3],*len));
- }
- else {
- *len = 0;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n"));
- return(1);
- }
- return(0);
-}
-
-
-/*
- * Check whether a given key may be written
- *
- * returns
- * SK_TRUE Yes it may be written
- * SK_FALSE No it may be written
- */
-SK_BOOL VpdMayWrite(
-char *key) /* keyword to write (allowed values "Yx", "Vx") */
-{
- if ((*key != 'Y' && *key != 'V') ||
- key[1] < '0' || key[1] > 'Z' ||
- (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
- return(SK_FALSE);
- }
- return(SK_TRUE);
-}
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the VPD
- * buffer if not already done. Insert/overwrite the keyword 'key'
- * in the VPD buffer. Cut the keyword value if it does not fit
- * into the VPD read / write area.
- *
- * returns 0: success
- * 2: value string was cut
- * 3: VPD transfer timeout
- * 4: VPD full, keyword was not written
- * 5: keyword cannot be written
- * 6: fatal VPD error
- */
-int VpdWrite(
-SK_AC *pAC, /* common data base */
-SK_IOC IoC, /* IO Context */
-const char *key, /* keyword to write (allowed values "Yx", "Vx") */
-const char *buf) /* buffer where the keyword value can be read from */
-{
- int len; /* length of the keyword to write */
- int rtv; /* return code */
- int rtv2;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX,
- ("VPD write %s = %s\n",key,buf));
-
- if ((*key != 'Y' && *key != 'V') ||
- key[1] < '0' || key[1] > 'Z' ||
- (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("illegal key tag, keyword not written\n"));
- return(5);
- }
-
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- if (VpdInit(pAC, IoC) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD init error\n"));
- return(6);
- }
- }
-
- rtv = 0;
- len = strlen(buf);
- if (len > VPD_MAX_LEN) {
- /* cut it */
- len = VPD_MAX_LEN;
- rtv = 2;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
- }
- if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD write error\n"));
- return(rtv2);
- }
-
- return(rtv);
-}
-
-/*
- * Read the contents of the VPD EEPROM and copy it to the
- * VPD buffer if not already done. Remove the VPD keyword
- * 'key' from the VPD buffer.
- * Only the keywords in the read/write area can be deleted.
- * Keywords in the read only area cannot be deleted.
- *
- * returns 0: success, keyword was removed
- * 1: keyword not found
- * 5: keyword cannot be deleted
- * 6: fatal VPD error
- */
-int VpdDelete(
-SK_AC *pAC, /* common data base */
-SK_IOC IoC, /* IO Context */
-char *key) /* keyword to read (e.g. "MN") */
-{
- SK_VPD_PARA *p, vp;
- char *etp;
- int vpd_size;
-
- vpd_size = pAC->vpd.vpd_size;
-
- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
- if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
- if (VpdInit(pAC, IoC) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD init error\n"));
- return(6);
- }
- }
-
- if ((p = vpd_find_para(pAC, key, &vp)) != NULL) {
- if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
- /* try to delete read only keyword */
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("cannot delete RO keyword\n"));
- return(5);
- }
-
- etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3);
-
- vpd_move_para(vp.p_val+vp.p_len, etp+2,
- - ((int)(vp.p_len + 3)));
- if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) {
- pAC->vpd.v.vpd_status &= ~VPD_VALID;
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("VPD encoding error\n"));
- return(6);
- }
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("keyword not found\n"));
- return(1);
- }
-
- return(0);
-}
-
-/*
- * If the VPD buffer contains valid data write the VPD
- * read/write area back to the VPD EEPROM.
- *
- * returns 0: success
- * 3: VPD transfer timeout
- */
-int VpdUpdate(
-SK_AC *pAC, /* Adapters context */
-SK_IOC IoC) /* IO Context */
-{
- int vpd_size;
-
- vpd_size = pAC->vpd.vpd_size;
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. "));
- if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) {
- if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2,
- vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
- ("transfer timed out\n"));
- return(3);
- }
- }
- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n"));
- return(0);
-}
-
diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c
deleted file mode 100644
index b4e75022a65..00000000000
--- a/drivers/net/sk98lin/skxmac2.c
+++ /dev/null
@@ -1,4160 +0,0 @@
-/******************************************************************************
- *
- * Name: skxmac2.c
- * Project: Gigabit Ethernet Adapters, Common Modules
- * Version: $Revision: 1.102 $
- * Date: $Date: 2003/10/02 16:53:58 $
- * Purpose: Contains functions to initialize the MACs and PHYs
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- * (C)Copyright 1998-2002 SysKonnect.
- * (C)Copyright 2002-2003 Marvell.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-#include "h/skdrv1st.h"
-#include "h/skdrv2nd.h"
-
-/* typedefs *******************************************************************/
-
-/* BCOM PHY magic pattern list */
-typedef struct s_PhyHack {
- int PhyReg; /* Phy register */
- SK_U16 PhyVal; /* Value to write */
-} BCOM_HACK;
-
-/* local variables ************************************************************/
-
-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
-static const char SysKonnectFileId[] =
- "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
-#endif
-
-#ifdef GENESIS
-static BCOM_HACK BcomRegA1Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
- { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
- { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-static BCOM_HACK BcomRegC0Hack[] = {
- { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
- { 0x15, 0x0A04 }, { 0x18, 0x0420 },
- { 0, 0 }
-};
-#endif
-
-/* function prototypes ********************************************************/
-#ifdef GENESIS
-static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
-static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
-#endif /* GENESIS */
-#ifdef YUKON
-static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
-#endif /* YUKON */
-#ifdef OTHER_PHY
-static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
-static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
-static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
-static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
-#endif /* OTHER_PHY */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmPhyRead() - Read from XMAC PHY register
- *
- * Description: reads a 16-bit word from XMAC PHY or ext. PHY
- *
- * Returns:
- * nothing
- */
-void SkXmPhyRead(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 SK_FAR *pVal) /* Pointer to Value */
-{
- SK_U16 Mmu;
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* write the PHY register's address */
- XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-
- /* get the PHY register's value */
- XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- do {
- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
- /* wait until 'Ready' is set */
- } while ((Mmu & XM_MMU_PHY_RDY) == 0);
-
- /* get the PHY register's value */
- XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
- }
-} /* SkXmPhyRead */
-
-
-/******************************************************************************
- *
- * SkXmPhyWrite() - Write to XMAC PHY register
- *
- * Description: writes a 16-bit word to XMAC PHY or ext. PHY
- *
- * Returns:
- * nothing
- */
-void SkXmPhyWrite(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 Val) /* Value */
-{
- SK_U16 Mmu;
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- do {
- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
- /* wait until 'Busy' is cleared */
- } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
- }
-
- /* write the PHY register's address */
- XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
-
- /* write the PHY register's value */
- XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- do {
- XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
- /* wait until 'Busy' is cleared */
- } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
- }
-} /* SkXmPhyWrite */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmPhyRead() - Read from GPHY register
- *
- * Description: reads a 16-bit word from GPHY through MDIO
- *
- * Returns:
- * nothing
- */
-void SkGmPhyRead(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 SK_FAR *pVal) /* Pointer to Value */
-{
- SK_U16 Ctrl;
- SK_GEPORT *pPrt;
-#ifdef VCPU
- u_long SimCyle;
- u_long SimLowTime;
-
- VCPUgetTime(&SimCyle, &SimLowTime);
- VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
- PhyReg, SimCyle, SimLowTime);
-#endif /* VCPU */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* set PHY-Register offset and 'Read' OpCode (= 1) */
- *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
- GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
-
- GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
-
- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
- /* additional check for MDC/MDIO activity */
- if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
- *pVal = 0;
- return;
- }
-
- *pVal |= GM_SMI_CT_BUSY;
-
- do {
-#ifdef VCPU
- VCPUwaitTime(1000);
-#endif /* VCPU */
-
- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
- /* wait until 'ReadValid' is set */
- } while (Ctrl == *pVal);
-
- /* get the PHY register's value */
- GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
-
-#ifdef VCPU
- VCPUgetTime(&SimCyle, &SimLowTime);
- VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
- SimCyle, SimLowTime);
-#endif /* VCPU */
-
-} /* SkGmPhyRead */
-
-
-/******************************************************************************
- *
- * SkGmPhyWrite() - Write to GPHY register
- *
- * Description: writes a 16-bit word to GPHY through MDIO
- *
- * Returns:
- * nothing
- */
-void SkGmPhyWrite(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 Val) /* Value */
-{
- SK_U16 Ctrl;
- SK_GEPORT *pPrt;
-#ifdef VCPU
- SK_U32 DWord;
- u_long SimCyle;
- u_long SimLowTime;
-
- VCPUgetTime(&SimCyle, &SimLowTime);
- VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
- PhyReg, Val, SimCyle, SimLowTime);
-#endif /* VCPU */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* write the PHY register's value */
- GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
-
- /* set PHY-Register offset and 'Write' OpCode (= 0) */
- Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
-
- GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
-
- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
- /* additional check for MDC/MDIO activity */
- if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
- return;
- }
-
- Val |= GM_SMI_CT_BUSY;
-
- do {
-#ifdef VCPU
- /* read Timer value */
- SK_IN32(IoC, B2_TI_VAL, &DWord);
-
- VCPUwaitTime(1000);
-#endif /* VCPU */
-
- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
-
- /* wait until 'Busy' is cleared */
- } while (Ctrl == Val);
-
-#ifdef VCPU
- VCPUgetTime(&SimCyle, &SimLowTime);
- VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
- SimCyle, SimLowTime);
-#endif /* VCPU */
-
-} /* SkGmPhyWrite */
-#endif /* YUKON */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- * SkGePhyRead() - Read from PHY register
- *
- * Description: calls a read PHY routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkGePhyRead(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 *pVal) /* Pointer to Value */
-{
- void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
-
- if (pAC->GIni.GIGenesis) {
- r_func = SkXmPhyRead;
- }
- else {
- r_func = SkGmPhyRead;
- }
-
- r_func(pAC, IoC, Port, PhyReg, pVal);
-} /* SkGePhyRead */
-
-
-/******************************************************************************
- *
- * SkGePhyWrite() - Write to PHY register
- *
- * Description: calls a write PHY routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkGePhyWrite(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* I/O Context */
-int Port, /* Port Index (MAC_1 + n) */
-int PhyReg, /* Register Address (Offset) */
-SK_U16 Val) /* Value */
-{
- void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
-
- if (pAC->GIni.GIGenesis) {
- w_func = SkXmPhyWrite;
- }
- else {
- w_func = SkGmPhyWrite;
- }
-
- w_func(pAC, IoC, Port, PhyReg, Val);
-} /* SkGePhyWrite */
-#endif /* SK_DIAG */
-
-
-/******************************************************************************
- *
- * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
- *
- * Description:
- * enables / disables promiscuous mode by setting Mode Register (XMAC) or
- * Receive Control Register (GMAC) dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacPromiscMode(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
-#ifdef YUKON
- SK_U16 RcReg;
-#endif
-#ifdef GENESIS
- SK_U32 MdReg;
-#endif
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
- /* enable or disable promiscuous mode */
- if (Enable) {
- MdReg |= XM_MD_ENA_PROM;
- }
- else {
- MdReg &= ~XM_MD_ENA_PROM;
- }
- /* setup Mode Register */
- XM_OUT32(IoC, Port, XM_MODE, MdReg);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-
- /* enable or disable unicast and multicast filtering */
- if (Enable) {
- RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
- }
- else {
- RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
- }
- /* setup Receive Control Register */
- GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
- }
-#endif /* YUKON */
-
-} /* SkMacPromiscMode*/
-
-
-/******************************************************************************
- *
- * SkMacHashing() - Enable / Disable Hashing
- *
- * Description:
- * enables / disables hashing by setting Mode Register (XMAC) or
- * Receive Control Register (GMAC) dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacHashing(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
-#ifdef YUKON
- SK_U16 RcReg;
-#endif
-#ifdef GENESIS
- SK_U32 MdReg;
-#endif
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
- /* enable or disable hashing */
- if (Enable) {
- MdReg |= XM_MD_ENA_HASH;
- }
- else {
- MdReg &= ~XM_MD_ENA_HASH;
- }
- /* setup Mode Register */
- XM_OUT32(IoC, Port, XM_MODE, MdReg);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
-
- /* enable or disable multicast filtering */
- if (Enable) {
- RcReg |= GM_RXCR_MCF_ENA;
- }
- else {
- RcReg &= ~GM_RXCR_MCF_ENA;
- }
- /* setup Receive Control Register */
- GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
- }
-#endif /* YUKON */
-
-} /* SkMacHashing*/
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
- *
- * Description:
- * The features
- * - FCS stripping, SK_STRIP_FCS_ON/OFF
- * - pad byte stripping, SK_STRIP_PAD_ON/OFF
- * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF
- * for inrange length error frames
- * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF
- * for frames > 1514 bytes
- * - enable Rx of own packets SK_SELF_RX_ON/OFF
- *
- * for incoming packets may be enabled/disabled by this function.
- * Additional modes may be added later.
- * Multiple modes can be enabled/disabled at the same time.
- * The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- * nothing
- */
-static void SkXmSetRxCmd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
- SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
- SK_U16 OldRxCmd;
- SK_U16 RxCmd;
-
- XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
-
- RxCmd = OldRxCmd;
-
- switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
- case SK_STRIP_FCS_ON:
- RxCmd |= XM_RX_STRIP_FCS;
- break;
- case SK_STRIP_FCS_OFF:
- RxCmd &= ~XM_RX_STRIP_FCS;
- break;
- }
-
- switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
- case SK_STRIP_PAD_ON:
- RxCmd |= XM_RX_STRIP_PAD;
- break;
- case SK_STRIP_PAD_OFF:
- RxCmd &= ~XM_RX_STRIP_PAD;
- break;
- }
-
- switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
- case SK_LENERR_OK_ON:
- RxCmd |= XM_RX_LENERR_OK;
- break;
- case SK_LENERR_OK_OFF:
- RxCmd &= ~XM_RX_LENERR_OK;
- break;
- }
-
- switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
- case SK_BIG_PK_OK_ON:
- RxCmd |= XM_RX_BIG_PK_OK;
- break;
- case SK_BIG_PK_OK_OFF:
- RxCmd &= ~XM_RX_BIG_PK_OK;
- break;
- }
-
- switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
- case SK_SELF_RX_ON:
- RxCmd |= XM_RX_SELF_RX;
- break;
- case SK_SELF_RX_OFF:
- RxCmd &= ~XM_RX_SELF_RX;
- break;
- }
-
- /* Write the new mode to the Rx command register if required */
- if (OldRxCmd != RxCmd) {
- XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
- }
-} /* SkXmSetRxCmd */
-
-
-/******************************************************************************
- *
- * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
- *
- * Description:
- * The features
- * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
- * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
- * for frames > 1514 bytes
- * - enable Rx of own packets SK_SELF_RX_ON/OFF
- *
- * for incoming packets may be enabled/disabled by this function.
- * Additional modes may be added later.
- * Multiple modes can be enabled/disabled at the same time.
- * The new configuration is written to the Rx Command register immediately.
- *
- * Returns:
- * nothing
- */
-static void SkGmSetRxCmd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
- SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
-{
- SK_U16 OldRxCmd;
- SK_U16 RxCmd;
-
- if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
-
- GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
-
- RxCmd = OldRxCmd;
-
- if ((Mode & SK_STRIP_FCS_ON) != 0) {
- RxCmd |= GM_RXCR_CRC_DIS;
- }
- else {
- RxCmd &= ~GM_RXCR_CRC_DIS;
- }
- /* Write the new mode to the Rx control register if required */
- if (OldRxCmd != RxCmd) {
- GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
- }
- }
-
- if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
-
- GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
-
- RxCmd = OldRxCmd;
-
- if ((Mode & SK_BIG_PK_OK_ON) != 0) {
- RxCmd |= GM_SMOD_JUMBO_ENA;
- }
- else {
- RxCmd &= ~GM_SMOD_JUMBO_ENA;
- }
- /* Write the new mode to the Rx control register if required */
- if (OldRxCmd != RxCmd) {
- GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
- }
- }
-} /* SkGmSetRxCmd */
-
-
-/******************************************************************************
- *
- * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
- *
- * Description: modifies the MAC's Rx Control reg. dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacSetRxCmd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-int Mode) /* Rx Mode */
-{
- if (pAC->GIni.GIGenesis) {
-
- SkXmSetRxCmd(pAC, IoC, Port, Mode);
- }
- else {
-
- SkGmSetRxCmd(pAC, IoC, Port, Mode);
- }
-
-} /* SkMacSetRxCmd */
-
-
-/******************************************************************************
- *
- * SkMacCrcGener() - Enable / Disable CRC Generation
- *
- * Description: enables / disables CRC generation dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacCrcGener(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
- SK_U16 Word;
-
- if (pAC->GIni.GIGenesis) {
-
- XM_IN16(IoC, Port, XM_TX_CMD, &Word);
-
- if (Enable) {
- Word &= ~XM_TX_NO_CRC;
- }
- else {
- Word |= XM_TX_NO_CRC;
- }
- /* setup Tx Command Register */
- XM_OUT16(IoC, Port, XM_TX_CMD, Word);
- }
- else {
-
- GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
-
- if (Enable) {
- Word &= ~GM_TXCR_CRC_DIS;
- }
- else {
- Word |= GM_TXCR_CRC_DIS;
- }
- /* setup Tx Control Register */
- GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
- }
-
-} /* SkMacCrcGener*/
-
-#endif /* SK_DIAG */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmClrExactAddr() - Clear Exact Match Address Registers
- *
- * Description:
- * All Exact Match Address registers of the XMAC 'Port' will be
- * cleared starting with 'StartNum' up to (and including) the
- * Exact Match address number of 'StopNum'.
- *
- * Returns:
- * nothing
- */
-void SkXmClrExactAddr(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-int StartNum, /* Begin with this Address Register Index (0..15) */
-int StopNum) /* Stop after finished with this Register Idx (0..15) */
-{
- int i;
- SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
-
- if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
- StartNum > StopNum) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
- return;
- }
-
- for (i = StartNum; i <= StopNum; i++) {
- XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
- }
-} /* SkXmClrExactAddr */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
- *
- * Description:
- * Flush the transmit FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- * nothing
- */
-void SkMacFlushTxFifo(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
- SK_U32 MdReg;
-
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
- XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* no way to flush the FIFO we have to issue a reset */
- /* TBD */
- }
-#endif /* YUKON */
-
-} /* SkMacFlushTxFifo */
-
-
-/******************************************************************************
- *
- * SkMacFlushRxFifo() - Flush the MAC's receive FIFO
- *
- * Description:
- * Flush the receive FIFO of the MAC specified by the index 'Port'
- *
- * Returns:
- * nothing
- */
-static void SkMacFlushRxFifo(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
- SK_U32 MdReg;
-
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
- XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* no way to flush the FIFO we have to issue a reset */
- /* TBD */
- }
-#endif /* YUKON */
-
-} /* SkMacFlushRxFifo */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmSoftRst() - Do a XMAC software reset
- *
- * Description:
- * The PHY registers should not be destroyed during this
- * kind of software reset. Therefore the XMAC Software Reset
- * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
- *
- * The software reset is done by
- * - disabling the Rx and Tx state machine,
- * - resetting the statistics module,
- * - clear all other significant XMAC Mode,
- * Command, and Control Registers
- * - clearing the Hash Register and the
- * Exact Match Address registers, and
- * - flushing the XMAC's Rx and Tx FIFOs.
- *
- * Note:
- * Another requirement when stopping the XMAC is to
- * avoid sending corrupted frames on the network.
- * Disabling the Tx state machine will NOT interrupt
- * the currently transmitted frame. But we must take care
- * that the Tx FIFO is cleared AFTER the current frame
- * is complete sent to the network.
- *
- * It takes about 12ns to send a frame with 1538 bytes.
- * One PCI clock goes at least 15ns (66MHz). Therefore
- * after reading XM_GP_PORT back, we are sure that the
- * transmitter is disabled AND idle. And this means
- * we may flush the transmit FIFO now.
- *
- * Returns:
- * nothing
- */
-static void SkXmSoftRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
-
- /* reset the statistics module */
- XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
-
- /* disable all XMAC IRQs */
- XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
-
- XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */
-
- XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */
- XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */
-
- /* disable all PHY IRQs */
- switch (pAC->GIni.GP[Port].PhyType) {
- case SK_PHY_BCOM:
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
- break;
- case SK_PHY_NAT:
- /* todo: National
- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
- break;
-#endif /* OTHER_PHY */
- }
-
- /* clear the Hash Register */
- XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
-
- /* clear the Exact Match Address registers */
- SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
-
- /* clear the Source Check Address registers */
- XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
-
-} /* SkXmSoftRst */
-
-
-/******************************************************************************
- *
- * SkXmHardRst() - Do a XMAC hardware reset
- *
- * Description:
- * The XMAC of the specified 'Port' and all connected devices
- * (PHY and SERDES) will receive a reset signal on its *Reset pins.
- * External PHYs must be reset by clearing a bit in the GPIO register
- * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns).
- *
- * ATTENTION:
- * It is absolutely necessary to reset the SW_RST Bit first
- * before calling this function.
- *
- * Returns:
- * nothing
- */
-static void SkXmHardRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U32 Reg;
- int i;
- int TOut;
- SK_U16 Word;
-
- for (i = 0; i < 4; i++) {
- /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
- TOut = 0;
- do {
- if (TOut++ > 10000) {
- /*
- * Adapter seems to be in RESET state.
- * Registers cannot be written.
- */
- return;
- }
-
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
-
- SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
-
- } while ((Word & MFF_SET_MAC_RST) == 0);
- }
-
- /* For external PHYs there must be special handling */
- if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-
- SK_IN32(IoC, B2_GP_IO, &Reg);
-
- if (Port == 0) {
- Reg |= GP_DIR_0; /* set to output */
- Reg &= ~GP_IO_0; /* set PHY reset (active low) */
- }
- else {
- Reg |= GP_DIR_2; /* set to output */
- Reg &= ~GP_IO_2; /* set PHY reset (active low) */
- }
- /* reset external PHY */
- SK_OUT32(IoC, B2_GP_IO, Reg);
-
- /* short delay */
- SK_IN32(IoC, B2_GP_IO, &Reg);
- }
-} /* SkXmHardRst */
-
-
-/******************************************************************************
- *
- * SkXmClearRst() - Release the PHY & XMAC reset
- *
- * Description:
- *
- * Returns:
- * nothing
- */
-static void SkXmClearRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U32 DWord;
-
- /* clear HW reset */
- SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
-
- if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
-
- SK_IN32(IoC, B2_GP_IO, &DWord);
-
- if (Port == 0) {
- DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
- }
- else {
- DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
- }
- /* Clear PHY reset */
- SK_OUT32(IoC, B2_GP_IO, DWord);
-
- /* Enable GMII interface */
- XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
- }
-} /* SkXmClearRst */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmSoftRst() - Do a GMAC software reset
- *
- * Description:
- * The GPHY registers should not be destroyed during this
- * kind of software reset.
- *
- * Returns:
- * nothing
- */
-static void SkGmSoftRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
- SK_U16 RxCtrl;
-
- /* reset the statistics module */
-
- /* disable all GMAC IRQs */
- SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-
- /* disable all PHY IRQs */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-
- /* clear the Hash Register */
- GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
-
- /* Enable Unicast and Multicast filtering */
- GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
-
- GM_OUT16(IoC, Port, GM_RX_CTRL,
- (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
-
-} /* SkGmSoftRst */
-
-
-/******************************************************************************
- *
- * SkGmHardRst() - Do a GMAC hardware reset
- *
- * Description:
- *
- * Returns:
- * nothing
- */
-static void SkGmHardRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U32 DWord;
-
- /* WA code for COMA mode */
- if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-
- SK_IN32(IoC, B2_GP_IO, &DWord);
-
- DWord |= (GP_DIR_9 | GP_IO_9);
-
- /* set PHY reset */
- SK_OUT32(IoC, B2_GP_IO, DWord);
- }
-
- /* set GPHY Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
-
- /* set GMAC Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-
-} /* SkGmHardRst */
-
-
-/******************************************************************************
- *
- * SkGmClearRst() - Release the GPHY & GMAC reset
- *
- * Description:
- *
- * Returns:
- * nothing
- */
-static void SkGmClearRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U32 DWord;
-
-#ifdef XXX
- /* clear GMAC Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
-
- /* set GMAC Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
-#endif /* XXX */
-
- /* WA code for COMA mode */
- if (pAC->GIni.GIYukonLite &&
- pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
-
- SK_IN32(IoC, B2_GP_IO, &DWord);
-
- DWord |= GP_DIR_9; /* set to output */
- DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
-
- /* clear PHY reset */
- SK_OUT32(IoC, B2_GP_IO, DWord);
- }
-
- /* set HWCFG_MODE */
- DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
- GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
- (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
- GPC_HWCFG_GMII_FIB);
-
- /* set GPHY Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
-
- /* release GPHY Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
-
-#ifdef VCPU
- VCpuWait(9000);
-#endif /* VCPU */
-
- /* clear GMAC Control reset */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
-
-#ifdef VCPU
- VCpuWait(2000);
-
- SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
-
- SK_IN32(IoC, B0_ISRC, &DWord);
-#endif /* VCPU */
-
-} /* SkGmClearRst */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- * SkMacSoftRst() - Do a MAC software reset
- *
- * Description: calls a MAC software reset routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacSoftRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* disable receiver and transmitter */
- SkMacRxTxDisable(pAC, IoC, Port);
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- SkXmSoftRst(pAC, IoC, Port);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- SkGmSoftRst(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
- /* flush the MAC's Rx and Tx FIFOs */
- SkMacFlushTxFifo(pAC, IoC, Port);
-
- SkMacFlushRxFifo(pAC, IoC, Port);
-
- pPrt->PState = SK_PRT_STOP;
-
-} /* SkMacSoftRst */
-
-
-/******************************************************************************
- *
- * SkMacHardRst() - Do a MAC hardware reset
- *
- * Description: calls a MAC hardware reset routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacHardRst(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- SkXmHardRst(pAC, IoC, Port);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- SkGmHardRst(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
- pAC->GIni.GP[Port].PState = SK_PRT_RESET;
-
-} /* SkMacHardRst */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmInitMac() - Initialize the XMAC II
- *
- * Description:
- * Initialize the XMAC of the specified port.
- * The XMAC must be reset or stopped before calling this function.
- *
- * Note:
- * The XMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- * nothing
- */
-void SkXmInitMac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- int i;
- SK_U16 SWord;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PState == SK_PRT_STOP) {
- /* Port State: SK_PRT_STOP */
- /* Verify that the reset bit is cleared */
- SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
-
- if ((SWord & MFF_SET_MAC_RST) != 0) {
- /* PState does not match HW state */
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
- /* Correct it */
- pPrt->PState = SK_PRT_RESET;
- }
- }
-
- if (pPrt->PState == SK_PRT_RESET) {
-
- SkXmClearRst(pAC, IoC, Port);
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- /* read Id from external PHY (all have the same address) */
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
-
- /*
- * Optimize MDIO transfer by suppressing preamble.
- * Must be done AFTER first access to BCOM chip.
- */
- XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
-
- XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
-
- if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
- /*
- * Workaround BCOM Errata for the C0 type.
- * Write magic patterns to reserved registers.
- */
- i = 0;
- while (BcomRegC0Hack[i].PhyReg != 0) {
- SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
- BcomRegC0Hack[i].PhyVal);
- i++;
- }
- }
- else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
- /*
- * Workaround BCOM Errata for the A1 type.
- * Write magic patterns to reserved registers.
- */
- i = 0;
- while (BcomRegA1Hack[i].PhyReg != 0) {
- SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
- BcomRegA1Hack[i].PhyVal);
- i++;
- }
- }
-
- /*
- * Workaround BCOM Errata (#10523) for all BCom PHYs.
- * Disable Power Management after reset.
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
-
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
- (SK_U16)(SWord | PHY_B_AC_DIS_PM));
-
- /* PHY LED initialization is done in SkGeXmitLED() */
- }
-
- /* Dummy read the Interrupt source register */
- XM_IN16(IoC, Port, XM_ISRC, &SWord);
-
- /*
- * The auto-negotiation process starts immediately after
- * clearing the reset. The auto-negotiation process should be
- * started by the SIRQ, therefore stop it here immediately.
- */
- SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
-
-#ifdef TEST_ONLY
- /* temp. code: enable signal detect */
- /* WARNING: do not override GMII setting above */
- XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
-#endif
- }
-
- /*
- * configure the XMACs Station Address
- * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
- * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
- */
- for (i = 0; i < 3; i++) {
- /*
- * The following 2 statements are together endianess
- * independent. Remember this when changing.
- */
- SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-
- XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
- }
-
- /* Tx Inter Packet Gap (XM_TX_IPG): use default */
- /* Tx High Water Mark (XM_TX_HI_WM): use default */
- /* Tx Low Water Mark (XM_TX_LO_WM): use default */
- /* Host Request Threshold (XM_HT_THR): use default */
- /* Rx Request Threshold (XM_RX_THR): use default */
- /* Rx Low Water Mark (XM_RX_LO_WM): use default */
-
- /* configure Rx High Water Mark (XM_RX_HI_WM) */
- XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
-
- /* Configure Tx Request Threshold */
- SWord = SK_XM_THR_SL; /* for single port */
-
- if (pAC->GIni.GIMacsFound > 1) {
- switch (pAC->GIni.GIPortUsage) {
- case SK_RED_LINK:
- SWord = SK_XM_THR_REDL; /* redundant link */
- break;
- case SK_MUL_LINK:
- SWord = SK_XM_THR_MULL; /* load balancing */
- break;
- case SK_JUMBO_LINK:
- SWord = SK_XM_THR_JUMBO; /* jumbo frames */
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
- break;
- }
- }
- XM_OUT16(IoC, Port, XM_TX_THR, SWord);
-
- /* setup register defaults for the Tx Command Register */
- XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
-
- /* setup register defaults for the Rx Command Register */
- SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
-
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
- SWord |= XM_RX_BIG_PK_OK;
- }
-
- if (pPrt->PLinkMode == SK_LMODE_HALF) {
- /*
- * If in manual half duplex mode the other side might be in
- * full duplex mode, so ignore if a carrier extension is not seen
- * on frames received
- */
- SWord |= XM_RX_DIS_CEXT;
- }
-
- XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
-
- /*
- * setup register defaults for the Mode Register
- * - Don't strip error frames to avoid Store & Forward
- * on the Rx side.
- * - Enable 'Check Station Address' bit
- * - Enable 'Check Address Array' bit
- */
- XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
-
- /*
- * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
- * - Enable all bits excepting 'Octets Rx OK Low CntOv'
- * and 'Octets Rx OK Hi Cnt Ov'.
- */
- XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
-
- /*
- * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
- * - Enable all bits excepting 'Octets Tx OK Low CntOv'
- * and 'Octets Tx OK Hi Cnt Ov'.
- */
- XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
-
- /*
- * Do NOT init XMAC interrupt mask here.
- * All interrupts remain disable until link comes up!
- */
-
- /*
- * Any additional configuration changes may be done now.
- * The last action is to enable the Rx and Tx state machine.
- * This should be done after the auto-negotiation process
- * has been completed successfully.
- */
-} /* SkXmInitMac */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmInitMac() - Initialize the GMAC
- *
- * Description:
- * Initialize the GMAC of the specified port.
- * The GMAC must be reset or stopped before calling this function.
- *
- * Note:
- * The GMAC's Rx and Tx state machine is still disabled when returning.
- *
- * Returns:
- * nothing
- */
-void SkGmInitMac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- int i;
- SK_U16 SWord;
- SK_U32 DWord;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PState == SK_PRT_STOP) {
- /* Port State: SK_PRT_STOP */
- /* Verify that the reset bit is cleared */
- SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
-
- if ((DWord & GMC_RST_SET) != 0) {
- /* PState does not match HW state */
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
- /* Correct it */
- pPrt->PState = SK_PRT_RESET;
- }
- }
-
- if (pPrt->PState == SK_PRT_RESET) {
-
- SkGmHardRst(pAC, IoC, Port);
-
- SkGmClearRst(pAC, IoC, Port);
-
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- /* Auto-negotiation disabled */
-
- /* get General Purpose Control */
- GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
-
- /* disable auto-update for speed, duplex and flow-control */
- SWord |= GM_GPCR_AU_ALL_DIS;
-
- /* setup General Purpose Control Register */
- GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-
- SWord = GM_GPCR_AU_ALL_DIS;
- }
- else {
- SWord = 0;
- }
-
- /* speed settings */
- switch (pPrt->PLinkSpeed) {
- case SK_LSPEED_AUTO:
- case SK_LSPEED_1000MBPS:
- SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
- break;
- case SK_LSPEED_100MBPS:
- SWord |= GM_GPCR_SPEED_100;
- break;
- case SK_LSPEED_10MBPS:
- break;
- }
-
- /* duplex settings */
- if (pPrt->PLinkMode != SK_LMODE_HALF) {
- /* set full duplex */
- SWord |= GM_GPCR_DUP_FULL;
- }
-
- /* flow-control settings */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- /* set Pause Off */
- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
- /* disable Tx & Rx flow-control */
- SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- /* disable Rx flow-control */
- SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- case SK_FLOW_MODE_SYM_OR_REM:
- /* enable Tx & Rx flow-control */
- break;
- }
-
- /* setup General Purpose Control Register */
- GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
-
- /* dummy read the Interrupt Source Register */
- SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
-
-#ifndef VCPU
- /* read Id from PHY */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
-
- SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
-#endif /* VCPU */
- }
-
- (void)SkGmResetCounter(pAC, IoC, Port);
-
- /* setup Transmit Control Register */
- GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
-
- /* setup Receive Control Register */
- GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
- GM_RXCR_CRC_DIS);
-
- /* setup Transmit Flow Control Register */
- GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
-
- /* setup Transmit Parameter Register */
-#ifdef VCPU
- GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
-#endif /* VCPU */
-
- SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
- TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
- TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
-
- GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
-
- /* configure the Serial Mode Register */
-#ifdef VCPU
- GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
-#endif /* VCPU */
-
- SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
-
- if (pPrt->PMacLimit4) {
- /* reset of collision counter after 4 consecutive collisions */
- SWord |= GM_SMOD_LIMIT_4;
- }
-
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
- /* enable jumbo mode (Max. Frame Length = 9018) */
- SWord |= GM_SMOD_JUMBO_ENA;
- }
-
- GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
-
- /*
- * configure the GMACs Station Addresses
- * in PROM you can find our addresses at:
- * B2_MAC_1 = xx xx xx xx xx x0 virtual address
- * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
- * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
- */
-
- for (i = 0; i < 3; i++) {
- /*
- * The following 2 statements are together endianess
- * independent. Remember this when changing.
- */
- /* physical address: will be used for pause frames */
- SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
-
-#ifdef WA_DEV_16
- /* WA for deviation #16 */
- if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
- /* swap the address bytes */
- SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
-
- /* write to register in reversed order */
- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
- }
- else {
- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
- }
-#else
- GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
-#endif /* WA_DEV_16 */
-
- /* virtual address: will be used for data */
- SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
-
- GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
-
- /* reset Multicast filtering Hash registers 1-3 */
- GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
- }
-
- /* reset Multicast filtering Hash register 4 */
- GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
-
- /* enable interrupt mask for counter overflows */
- GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
- GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
- GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
-
-#if defined(SK_DIAG) || defined(DEBUG)
- /* read General Purpose Status */
- GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("MAC Stat Reg.=0x%04X\n", SWord));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
- c_print("MAC Stat Reg=0x%04X\n", SWord);
-#endif /* SK_DIAG */
-
-} /* SkGmInitMac */
-#endif /* YUKON */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmInitDupMd() - Initialize the XMACs Duplex Mode
- *
- * Description:
- * This function initializes the XMACs Duplex Mode.
- * It should be called after successfully finishing
- * the Auto-negotiation Process
- *
- * Returns:
- * nothing
- */
-static void SkXmInitDupMd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- switch (pAC->GIni.GP[Port].PLinkModeStatus) {
- case SK_LMODE_STAT_AUTOHALF:
- case SK_LMODE_STAT_HALF:
- /* Configuration Actions for Half Duplex Mode */
- /*
- * XM_BURST = default value. We are probable not quick
- * enough at the 'XMAC' bus to burst 8kB.
- * The XMAC stops bursting if no transmit frames
- * are available or the burst limit is exceeded.
- */
- /* XM_TX_RT_LIM = default value (15) */
- /* XM_TX_STIME = default value (0xff = 4096 bit times) */
- break;
- case SK_LMODE_STAT_AUTOFULL:
- case SK_LMODE_STAT_FULL:
- /* Configuration Actions for Full Duplex Mode */
- /*
- * The duplex mode is configured by the PHY,
- * therefore it seems to be that there is nothing
- * to do here.
- */
- break;
- case SK_LMODE_STAT_UNKNOWN:
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
- break;
- }
-} /* SkXmInitDupMd */
-
-
-/******************************************************************************
- *
- * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
- *
- * Description:
- * This function initializes the Pause Mode which should
- * be used for this port.
- * It should be called after successfully finishing
- * the Auto-negotiation Process
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPauseMd(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U32 DWord;
- SK_U16 Word;
-
- pPrt = &pAC->GIni.GP[Port];
-
- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-
- if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
- pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
- /* Disable Pause Frame Reception */
- Word |= XM_MMU_IGN_PF;
- }
- else {
- /*
- * enabling pause frame reception is required for 1000BT
- * because the XMAC is not reset if the link is going down
- */
- /* Enable Pause Frame Reception */
- Word &= ~XM_MMU_IGN_PF;
- }
-
- XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
-
- XM_IN32(IoC, Port, XM_MODE, &DWord);
-
- if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
- pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
-
- /*
- * Configure Pause Frame Generation
- * Use internal and external Pause Frame Generation.
- * Sending pause frames is edge triggered.
- * Send a Pause frame with the maximum pause time if
- * internal oder external FIFO full condition occurs.
- * Send a zero pause time frame to re-start transmission.
- */
-
- /* XM_PAUSE_DA = '010000C28001' (default) */
-
- /* XM_MAC_PTIME = 0xffff (maximum) */
- /* remember this value is defined in big endian (!) */
- XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
-
- /* Set Pause Mode in Mode Register */
- DWord |= XM_PAUSE_MODE;
-
- /* Set Pause Mode in MAC Rx FIFO */
- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
- }
- else {
- /*
- * disable pause frame generation is required for 1000BT
- * because the XMAC is not reset if the link is going down
- */
- /* Disable Pause Mode in Mode Register */
- DWord &= ~XM_PAUSE_MODE;
-
- /* Disable Pause Mode in MAC Rx FIFO */
- SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
- }
-
- XM_OUT32(IoC, Port, XM_MODE, DWord);
-} /* SkXmInitPauseMd*/
-
-
-/******************************************************************************
- *
- * SkXmInitPhyXmac() - Initialize the XMAC Phy registers
- *
- * Description: initializes all the XMACs Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPhyXmac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
- SK_U16 Ctrl;
-
- pPrt = &pAC->GIni.GP[Port];
- Ctrl = 0;
-
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
- /* Set DuplexMode in Config register */
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- Ctrl |= PHY_CT_DUP_MD;
- }
-
- /*
- * Do NOT enable Auto-negotiation here. This would hold
- * the link down because no IDLEs are transmitted
- */
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
- /* Set Auto-negotiation advertisement */
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- Ctrl |= PHY_X_AN_HD;
- break;
- case SK_LMODE_AUTOFULL:
- Ctrl |= PHY_X_AN_FD;
- break;
- case SK_LMODE_AUTOBOTH:
- Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- Ctrl |= PHY_X_P_NO_PAUSE;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- Ctrl |= PHY_X_P_ASYM_MD;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- Ctrl |= PHY_X_P_SYM_MD;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- Ctrl |= PHY_X_P_BOTH_MD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
-
- /* Write AutoNeg Advertisement Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
-
- /* Restart Auto-negotiation */
- Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
- }
-
- if (DoLoop) {
- /* Set the Phy Loopback bit, too */
- Ctrl |= PHY_CT_LOOP;
- }
-
- /* Write to the Phy control register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
-} /* SkXmInitPhyXmac */
-
-
-/******************************************************************************
- *
- * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
- *
- * Description: initializes all the Broadcom Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPhyBcom(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
- SK_U16 Ctrl1;
- SK_U16 Ctrl2;
- SK_U16 Ctrl3;
- SK_U16 Ctrl4;
- SK_U16 Ctrl5;
-
- Ctrl1 = PHY_CT_SP1000;
- Ctrl2 = 0;
- Ctrl3 = PHY_SEL_TYPE;
- Ctrl4 = PHY_B_PEC_EN_LTR;
- Ctrl5 = PHY_B_AC_TX_TST;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* manually Master/Slave ? */
- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
- Ctrl2 |= PHY_B_1000C_MSE;
-
- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
- Ctrl2 |= PHY_B_1000C_MSC;
- }
- }
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
- /* Set DuplexMode in Config register */
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- Ctrl1 |= PHY_CT_DUP_MD;
- }
-
- /* Determine Master/Slave manually if not already done */
- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
- Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
- }
-
- /*
- * Do NOT enable Auto-negotiation here. This would hold
- * the link down because no IDLES are transmitted
- */
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
- /* Set Auto-negotiation advertisement */
-
- /*
- * Workaround BCOM Errata #1 for the C5 type.
- * 1000Base-T Link Acquisition Failure in Slave Mode
- * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
- */
- Ctrl2 |= PHY_B_1000C_RD;
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- Ctrl2 |= PHY_B_1000C_AHD;
- break;
- case SK_LMODE_AUTOFULL:
- Ctrl2 |= PHY_B_1000C_AFD;
- break;
- case SK_LMODE_AUTOBOTH:
- Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- Ctrl3 |= PHY_B_P_NO_PAUSE;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- Ctrl3 |= PHY_B_P_ASYM_MD;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- Ctrl3 |= PHY_B_P_SYM_MD;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- Ctrl3 |= PHY_B_P_BOTH_MD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
-
- /* Restart Auto-negotiation */
- Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
- }
-
- /* Initialize LED register here? */
- /* No. Please do it in SkDgXmitLed() (if required) and swap
- init order of LEDs and XMAC. (MAl) */
-
- /* Write 1000Base-T Control Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-
- /* Write AutoNeg Advertisement Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-
- if (DoLoop) {
- /* Set the Phy Loopback bit, too */
- Ctrl1 |= PHY_CT_LOOP;
- }
-
- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
- /* configure FIFO to high latency for transmission of ext. packets */
- Ctrl4 |= PHY_B_PEC_HIGH_LA;
-
- /* configure reception of extended packets */
- Ctrl5 |= PHY_B_AC_LONG_PACK;
-
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
- }
-
- /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
-
- /* Write to the Phy control register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Control Reg=0x%04X\n", Ctrl1));
-} /* SkXmInitPhyBcom */
-#endif /* GENESIS */
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmInitPhyMarv() - Initialize the Marvell Phy registers
- *
- * Description: initializes all the Marvell Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkGmInitPhyMarv(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
- SK_U16 PhyCtrl;
- SK_U16 C1000BaseT;
- SK_U16 AutoNegAdv;
- SK_U16 ExtPhyCtrl;
- SK_U16 LedCtrl;
- SK_BOOL AutoNeg;
-#if defined(SK_DIAG) || defined(DEBUG)
- SK_U16 PhyStat;
- SK_U16 PhyStat1;
- SK_U16 PhySpecStat;
-#endif /* SK_DIAG || DEBUG */
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- AutoNeg = SK_FALSE;
- }
- else {
- AutoNeg = SK_TRUE;
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyMarv: Port %d, auto-negotiation %s\n",
- Port, AutoNeg ? "ON" : "OFF"));
-
-#ifdef VCPU
- VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
- Port, DoLoop);
-#else /* VCPU */
- if (DoLoop) {
- /* Set 'MAC Power up'-bit, set Manual MDI configuration */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
- PHY_M_PC_MAC_POW_UP);
- }
- else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
- /* Read Ext. PHY Specific Control */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
-
- ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
- PHY_M_EC_MAC_S_MSK);
-
- ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
- PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
-
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
- }
-
- /* Read PHY Control */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
-
- if (!AutoNeg) {
- /* Disable Auto-negotiation */
- PhyCtrl &= ~PHY_CT_ANE;
- }
-
- PhyCtrl |= PHY_CT_RESET;
- /* Assert software reset */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
-#endif /* VCPU */
-
- PhyCtrl = 0 /* PHY_CT_COL_TST */;
- C1000BaseT = 0;
- AutoNegAdv = PHY_SEL_TYPE;
-
- /* manually Master/Slave ? */
- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
- /* enable Manual Master/Slave */
- C1000BaseT |= PHY_M_1000C_MSE;
-
- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
- C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
- }
- }
-
- /* Auto-negotiation ? */
- if (!AutoNeg) {
-
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- /* Set Full Duplex Mode */
- PhyCtrl |= PHY_CT_DUP_MD;
- }
-
- /* Set Master/Slave manually if not already done */
- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
- C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
- }
-
- /* Set Speed */
- switch (pPrt->PLinkSpeed) {
- case SK_LSPEED_AUTO:
- case SK_LSPEED_1000MBPS:
- PhyCtrl |= PHY_CT_SP1000;
- break;
- case SK_LSPEED_100MBPS:
- PhyCtrl |= PHY_CT_SP100;
- break;
- case SK_LSPEED_10MBPS:
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
- SKERR_HWI_E019MSG);
- }
-
- if (!DoLoop) {
- PhyCtrl |= PHY_CT_RESET;
- }
- }
- else {
- /* Set Auto-negotiation advertisement */
-
- if (pAC->GIni.GICopperType) {
- /* Set Speed capabilities */
- switch (pPrt->PLinkSpeed) {
- case SK_LSPEED_AUTO:
- C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
- AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
- PHY_M_AN_10_FD | PHY_M_AN_10_HD;
- break;
- case SK_LSPEED_1000MBPS:
- C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
- break;
- case SK_LSPEED_100MBPS:
- AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
- /* advertise 10Base-T also */
- PHY_M_AN_10_FD | PHY_M_AN_10_HD;
- break;
- case SK_LSPEED_10MBPS:
- AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
- SKERR_HWI_E019MSG);
- }
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- C1000BaseT &= ~PHY_M_1000C_AFD;
- AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
- break;
- case SK_LMODE_AUTOFULL:
- C1000BaseT &= ~PHY_M_1000C_AHD;
- AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
- break;
- case SK_LMODE_AUTOBOTH:
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- AutoNegAdv |= PHY_B_P_NO_PAUSE;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- AutoNegAdv |= PHY_B_P_ASYM_MD;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- AutoNegAdv |= PHY_B_P_SYM_MD;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- AutoNegAdv |= PHY_B_P_BOTH_MD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
- }
- else { /* special defines for FIBER (88E1011S only) */
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- AutoNegAdv |= PHY_M_AN_1000X_AHD;
- break;
- case SK_LMODE_AUTOFULL:
- AutoNegAdv |= PHY_M_AN_1000X_AFD;
- break;
- case SK_LMODE_AUTOBOTH:
- AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- AutoNegAdv |= PHY_M_P_ASYM_MD_X;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- AutoNegAdv |= PHY_M_P_SYM_MD_X;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- AutoNegAdv |= PHY_M_P_BOTH_MD_X;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
- }
-
- if (!DoLoop) {
- /* Restart Auto-negotiation */
- PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
- }
- }
-
-#ifdef VCPU
- /*
- * E-mail from Gu Lin (08-03-2002):
- */
-
- /* Program PHY register 30 as 16'h0708 for simulation speed up */
- SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
-
- VCpuWait(2000);
-
-#else /* VCPU */
-
- /* Write 1000Base-T Control Register */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
-
- /* Write AutoNeg Advertisement Register */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-#endif /* VCPU */
-
- if (DoLoop) {
- /* Set the PHY Loopback bit */
- PhyCtrl |= PHY_CT_LOOP;
-
-#ifdef XXX
- /* Program PHY register 16 as 16'h0400 to force link good */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
-#endif /* XXX */
-
-#ifndef VCPU
- if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
- /* Write Ext. PHY Specific Control */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
- (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
- }
-#endif /* VCPU */
- }
-#ifdef TEST_ONLY
- else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
- /* Write PHY Specific Control */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
- PHY_M_PC_EN_DET_MSK);
- }
-#endif
-
- /* Write to the PHY Control register */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-
-#ifdef VCPU
- VCpuWait(2000);
-#else
-
- LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
-
- if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
- LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
- }
-
- if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
- LedCtrl |= PHY_M_LEDC_DP_CTRL;
- }
-
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
-
- if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
- /* only in forced 100 Mbps mode */
- if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
-
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
- PHY_M_LED_MO_100(MO_LED_ON));
- }
- }
-
-#ifdef SK_DIAG
- c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
- c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
- c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
- c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
-#endif /* SK_DIAG */
-
-#if defined(SK_DIAG) || defined(DEBUG)
- /* Read PHY Control */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
-
- /* Read 1000Base-T Control Register */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
-
- /* Read AutoNeg Advertisement Register */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
-
- /* Read Ext. PHY Specific Control */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
-
- /* Read PHY Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Stat Reg.=0x%04X\n", PhyStat));
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Stat Reg.=0x%04X\n", PhyStat1));
-
- /* Read PHY Specific Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Spec Stat=0x%04X\n", PhySpecStat));
-#endif /* SK_DIAG || DEBUG */
-
-#ifdef SK_DIAG
- c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
- c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
- c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
- c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
- c_print("PHY Stat Reg=0x%04X\n", PhyStat);
- c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
- c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
-#endif /* SK_DIAG */
-
-#endif /* VCPU */
-
-} /* SkGmInitPhyMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkXmInitPhyLone() - Initialize the Level One Phy registers
- *
- * Description: initializes all the Level One Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPhyLone(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
- SK_U16 Ctrl1;
- SK_U16 Ctrl2;
- SK_U16 Ctrl3;
-
- Ctrl1 = PHY_CT_SP1000;
- Ctrl2 = 0;
- Ctrl3 = PHY_SEL_TYPE;
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* manually Master/Slave ? */
- if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
- Ctrl2 |= PHY_L_1000C_MSE;
-
- if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
- Ctrl2 |= PHY_L_1000C_MSC;
- }
- }
- /* Auto-negotiation ? */
- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
- /*
- * level one spec say: "1000 Mbps: manual mode not allowed"
- * but lets see what happens...
- */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyLone: no auto-negotiation Port %d\n", Port));
- /* Set DuplexMode in Config register */
- if (pPrt->PLinkMode == SK_LMODE_FULL) {
- Ctrl1 |= PHY_CT_DUP_MD;
- }
-
- /* Determine Master/Slave manually if not already done */
- if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
- Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
- }
-
- /*
- * Do NOT enable Auto-negotiation here. This would hold
- * the link down because no IDLES are transmitted
- */
- }
- else {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("InitPhyLone: with auto-negotiation Port %d\n", Port));
- /* Set Auto-negotiation advertisement */
-
- /* Set Full/half duplex capabilities */
- switch (pPrt->PLinkMode) {
- case SK_LMODE_AUTOHALF:
- Ctrl2 |= PHY_L_1000C_AHD;
- break;
- case SK_LMODE_AUTOFULL:
- Ctrl2 |= PHY_L_1000C_AFD;
- break;
- case SK_LMODE_AUTOBOTH:
- Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
- SKERR_HWI_E015MSG);
- }
-
- /* Set Flow-control capabilities */
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- Ctrl3 |= PHY_L_P_NO_PAUSE;
- break;
- case SK_FLOW_MODE_LOC_SEND:
- Ctrl3 |= PHY_L_P_ASYM_MD;
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- Ctrl3 |= PHY_L_P_SYM_MD;
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- Ctrl3 |= PHY_L_P_BOTH_MD;
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
-
- /* Restart Auto-negotiation */
- Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
- }
-
- /* Write 1000Base-T Control Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
-
- /* Write AutoNeg Advertisement Register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
-
- if (DoLoop) {
- /* Set the Phy Loopback bit, too */
- Ctrl1 |= PHY_CT_LOOP;
- }
-
- /* Write to the Phy control register */
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Control Reg=0x%04X\n", Ctrl1));
-} /* SkXmInitPhyLone */
-
-
-/******************************************************************************
- *
- * SkXmInitPhyNat() - Initialize the National Phy registers
- *
- * Description: initializes all the National Phy registers
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkXmInitPhyNat(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
-/* todo: National */
-} /* SkXmInitPhyNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- * SkMacInitPhy() - Initialize the PHY registers
- *
- * Description: calls the Init PHY routines dep. on board type
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-void SkMacInitPhy(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- switch (pPrt->PhyType) {
- case SK_PHY_XMAC:
- SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
- break;
- case SK_PHY_BCOM:
- SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
- break;
- case SK_PHY_NAT:
- SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
- break;
-#endif /* OTHER_PHY */
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
- }
-#endif /* YUKON */
-
-} /* SkMacInitPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmAutoNegDoneXmac() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkXmAutoNegDoneXmac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 ResAb; /* Resolved Ability */
- SK_U16 LPAb; /* Link Partner Ability */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegDoneXmac, Port %d\n", Port));
-
- pPrt = &pAC->GIni.GP[Port];
-
- /* Get PHY parameters */
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
-
- if ((LPAb & PHY_X_AN_RFB) != 0) {
- /* At least one of the remote fault bit is set */
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_OTHER);
- }
-
- /* Check Duplex mismatch */
- if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
- }
- else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
- }
- else {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_DUP_CAP);
- }
-
- /* Check PAUSE mismatch */
- /* We are NOT using chapter 4.23 of the Xaqti manual */
- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
- if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
- pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
- (LPAb & PHY_X_P_SYM_MD) != 0) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
- (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
- /* Enable PAUSE receive, disable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
- }
- else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
- (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
- /* Disable PAUSE receive, enable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
- }
- else {
- /* PAUSE mismatch -> no PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
- }
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
- return(SK_AND_OK);
-} /* SkXmAutoNegDoneXmac */
-
-
-/******************************************************************************
- *
- * SkXmAutoNegDoneBcom() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkXmAutoNegDoneBcom(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 LPAb; /* Link Partner Ability */
- SK_U16 AuxStat; /* Auxiliary Status */
-
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
- SK_U16 ResAb; /* Resolved Ability */
-#endif /* 0 */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegDoneBcom, Port %d\n", Port));
- pPrt = &pAC->GIni.GP[Port];
-
- /* Get PHY parameters */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
-#endif /* 0 */
-
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
-
- if ((LPAb & PHY_B_AN_RF) != 0) {
- /* Remote fault bit is set: Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_OTHER);
- }
-
- /* Check Duplex mismatch */
- if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
- }
- else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
- }
- else {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_DUP_CAP);
- }
-
-#ifdef TEST_ONLY
-01-Sep-2000 RA;:;:
- /* Check Master/Slave resolution */
- if ((ResAb & PHY_B_1000S_MSF) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
- return(SK_AND_OTHER);
- }
-
- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
-#endif /* 0 */
-
- /* Check PAUSE mismatch ??? */
- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
- if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
- /* Enable PAUSE receive, disable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
- }
- else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
- /* Disable PAUSE receive, enable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
- }
- else {
- /* PAUSE mismatch -> no PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
- }
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
-
- return(SK_AND_OK);
-} /* SkXmAutoNegDoneBcom */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmAutoNegDoneMarv() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkGmAutoNegDoneMarv(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 LPAb; /* Link Partner Ability */
- SK_U16 ResAb; /* Resolved Ability */
- SK_U16 AuxStat; /* Auxiliary Status */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegDoneMarv, Port %d\n", Port));
- pPrt = &pAC->GIni.GP[Port];
-
- /* Get PHY parameters */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Link P.Abil.=0x%04X\n", LPAb));
-
- if ((LPAb & PHY_M_AN_RF) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_OTHER);
- }
-
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
-
- /* Check Master/Slave resolution */
- if ((ResAb & PHY_B_1000S_MSF) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
- return(SK_AND_OTHER);
- }
-
- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
- (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
-
- /* Read PHY Specific Status */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
-
- /* Check Speed & Duplex resolved */
- if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
- return(SK_AND_DUP_CAP);
- }
-
- if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
- }
- else {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
- }
-
- /* Check PAUSE mismatch ??? */
- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
- if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
- /* Enable PAUSE receive, disable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
- }
- else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
- /* Disable PAUSE receive, enable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
- }
- else {
- /* PAUSE mismatch -> no PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
- }
-
- /* set used link speed */
- switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
- case (unsigned)PHY_M_PS_SPEED_1000:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
- break;
- case PHY_M_PS_SPEED_100:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
- break;
- default:
- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
- }
-
- return(SK_AND_OK);
-} /* SkGmAutoNegDoneMarv */
-#endif /* YUKON */
-
-
-#ifdef OTHER_PHY
-/******************************************************************************
- *
- * SkXmAutoNegDoneLone() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkXmAutoNegDoneLone(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 ResAb; /* Resolved Ability */
- SK_U16 LPAb; /* Link Partner Ability */
- SK_U16 QuickStat; /* Auxiliary Status */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegDoneLone, Port %d\n", Port));
- pPrt = &pAC->GIni.GP[Port];
-
- /* Get PHY parameters */
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
- SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
-
- if ((LPAb & PHY_L_AN_RF) != 0) {
- /* Remote fault bit is set */
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegFail: Remote fault bit set Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- return(SK_AND_OTHER);
- }
-
- /* Check Duplex mismatch */
- if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
- }
- else {
- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
- }
-
- /* Check Master/Slave resolution */
- if ((ResAb & PHY_L_1000S_MSF) != 0) {
- /* Error */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("Master/Slave Fault Port %d\n", Port));
- pPrt->PAutoNegFail = SK_TRUE;
- pPrt->PMSStatus = SK_MS_STAT_FAULT;
- return(SK_AND_OTHER);
- }
- else if (ResAb & PHY_L_1000S_MSR) {
- pPrt->PMSStatus = SK_MS_STAT_MASTER;
- }
- else {
- pPrt->PMSStatus = SK_MS_STAT_SLAVE;
- }
-
- /* Check PAUSE mismatch */
- /* We are using IEEE 802.3z/D5.0 Table 37-4 */
- /* we must manually resolve the abilities here */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
-
- switch (pPrt->PFlowCtrlMode) {
- case SK_FLOW_MODE_NONE:
- /* default */
- break;
- case SK_FLOW_MODE_LOC_SEND:
- if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
- (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
- /* Disable PAUSE receive, enable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
- }
- break;
- case SK_FLOW_MODE_SYMMETRIC:
- if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- break;
- case SK_FLOW_MODE_SYM_OR_REM:
- if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
- PHY_L_QS_AS_PAUSE) {
- /* Enable PAUSE receive, disable PAUSE transmit */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
- }
- else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
- /* Symmetric PAUSE */
- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
- }
- break;
- default:
- SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
- SKERR_HWI_E016MSG);
- }
-
- return(SK_AND_OK);
-} /* SkXmAutoNegDoneLone */
-
-
-/******************************************************************************
- *
- * SkXmAutoNegDoneNat() - Auto-negotiation handling
- *
- * Description:
- * This function handles the auto-negotiation if the Done bit is set.
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-static int SkXmAutoNegDoneNat(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-/* todo: National */
- return(SK_AND_OK);
-} /* SkXmAutoNegDoneNat */
-#endif /* OTHER_PHY */
-
-
-/******************************************************************************
- *
- * SkMacAutoNegDone() - Auto-negotiation handling
- *
- * Description: calls the auto-negotiation done routines dep. on board type
- *
- * Returns:
- * SK_AND_OK o.k.
- * SK_AND_DUP_CAP Duplex capability error happened
- * SK_AND_OTHER Other error happened
- */
-int SkMacAutoNegDone(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- int Rtv;
-
- Rtv = SK_AND_OK;
-
- pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- switch (pPrt->PhyType) {
-
- case SK_PHY_XMAC:
- Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
- break;
- case SK_PHY_BCOM:
- Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
- break;
- case SK_PHY_NAT:
- Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
- break;
-#endif /* OTHER_PHY */
- default:
- return(SK_AND_OTHER);
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
- if (Rtv != SK_AND_OK) {
- return(Rtv);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNeg done Port %d\n", Port));
-
- /* We checked everything and may now enable the link */
- pPrt->PAutoNegFail = SK_FALSE;
-
- SkMacRxTxEnable(pAC, IoC, Port);
-
- return(SK_AND_OK);
-} /* SkMacAutoNegDone */
-
-
-/******************************************************************************
- *
- * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
- *
- * Description: enables Rx/Tx dep. on board type
- *
- * Returns:
- * 0 o.k.
- * != 0 Error happened
- */
-int SkMacRxTxEnable(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 Reg; /* 16-bit register value */
- SK_U16 IntMask; /* MAC interrupt mask */
-#ifdef GENESIS
- SK_U16 SWord;
-#endif
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (!pPrt->PHWLinkUp) {
- /* The Hardware link is NOT up */
- return(0);
- }
-
- if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
- pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
- pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
- pPrt->PAutoNegFail) {
- /* Auto-negotiation is not done or failed */
- return(0);
- }
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* set Duplex Mode and Pause Mode */
- SkXmInitDupMd(pAC, IoC, Port);
-
- SkXmInitPauseMd(pAC, IoC, Port);
-
- /*
- * Initialize the Interrupt Mask Register. Default IRQs are...
- * - Link Asynchronous Event
- * - Link Partner requests config
- * - Auto Negotiation Done
- * - Rx Counter Event Overflow
- * - Tx Counter Event Overflow
- * - Transmit FIFO Underrun
- */
- IntMask = XM_DEF_MSK;
-
-#ifdef DEBUG
- /* add IRQ for Receive FIFO Overflow */
- IntMask &= ~XM_IS_RXF_OV;
-#endif /* DEBUG */
-
- if (pPrt->PhyType != SK_PHY_XMAC) {
- /* disable GP0 interrupt bit */
- IntMask |= XM_IS_INP_ASS;
- }
- XM_OUT16(IoC, Port, XM_IMSK, IntMask);
-
- /* get MMU Command Reg. */
- XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
-
- if (pPrt->PhyType != SK_PHY_XMAC &&
- (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
- /* set to Full Duplex */
- Reg |= XM_MMU_GMII_FD;
- }
-
- switch (pPrt->PhyType) {
- case SK_PHY_BCOM:
- /*
- * Workaround BCOM Errata (#10523) for all BCom Phys
- * Enable Power Management after link up
- */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
- (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
- (SK_U16)PHY_B_DEF_MSK);
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
- break;
- case SK_PHY_NAT:
- /* todo National:
- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
- /* no interrupts possible from National ??? */
- break;
-#endif /* OTHER_PHY */
- }
-
- /* enable Rx/Tx */
- XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /*
- * Initialize the Interrupt Mask Register. Default IRQs are...
- * - Rx Counter Event Overflow
- * - Tx Counter Event Overflow
- * - Transmit FIFO Underrun
- */
- IntMask = GMAC_DEF_MSK;
-
-#ifdef DEBUG
- /* add IRQ for Receive FIFO Overrun */
- IntMask |= GM_IS_RX_FF_OR;
-#endif /* DEBUG */
-
- SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
-
- /* get General Purpose Control */
- GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
-
- if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
- pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
- /* set to Full Duplex */
- Reg |= GM_GPCR_DUP_FULL;
- }
-
- /* enable Rx/Tx */
- GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
- GM_GPCR_TX_ENA));
-
-#ifndef VCPU
- /* Enable all PHY interrupts */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
- (SK_U16)PHY_M_DEF_MSK);
-#endif /* VCPU */
- }
-#endif /* YUKON */
-
- return(0);
-
-} /* SkMacRxTxEnable */
-
-
-/******************************************************************************
- *
- * SkMacRxTxDisable() - Disable Receiver and Transmitter
- *
- * Description: disables Rx/Tx dep. on board type
- *
- * Returns: N/A
- */
-void SkMacRxTxDisable(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 Word;
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
-
- XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
-
- /* dummy read to ensure writing */
- XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
-
- GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
-
- GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
- GM_GPCR_TX_ENA)));
-
- /* dummy read to ensure writing */
- GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
- }
-#endif /* YUKON */
-
-} /* SkMacRxTxDisable */
-
-
-/******************************************************************************
- *
- * SkMacIrqDisable() - Disable IRQ from MAC
- *
- * Description: sets the IRQ-mask to disable IRQ dep. on board type
- *
- * Returns: N/A
- */
-void SkMacIrqDisable(
-SK_AC *pAC, /* Adapter Context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
-#ifdef GENESIS
- SK_U16 Word;
-#endif
-
- pPrt = &pAC->GIni.GP[Port];
-
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
-
- /* disable all XMAC IRQs */
- XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
-
- /* Disable all PHY interrupts */
- switch (pPrt->PhyType) {
- case SK_PHY_BCOM:
- /* Make sure that PHY is initialized */
- if (pPrt->PState != SK_PRT_RESET) {
- /* NOT allowed if BCOM is in RESET state */
- /* Workaround BCOM Errata (#10523) all BCom */
- /* Disable Power Management if link is down */
- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
- (SK_U16)(Word | PHY_B_AC_DIS_PM));
- SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
- }
- break;
-#ifdef OTHER_PHY
- case SK_PHY_LONE:
- SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
- break;
- case SK_PHY_NAT:
- /* todo: National
- SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
- break;
-#endif /* OTHER_PHY */
- }
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* disable all GMAC IRQs */
- SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
-
-#ifndef VCPU
- /* Disable all PHY interrupts */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
-#endif /* VCPU */
- }
-#endif /* YUKON */
-
-} /* SkMacIrqDisable */
-
-
-#ifdef SK_DIAG
-/******************************************************************************
- *
- * SkXmSendCont() - Enable / Disable Send Continuous Mode
- *
- * Description: enable / disable Send Continuous Mode on XMAC
- *
- * Returns:
- * nothing
- */
-void SkXmSendCont(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
- SK_U32 MdReg;
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
- if (Enable) {
- MdReg |= XM_MD_TX_CONT;
- }
- else {
- MdReg &= ~XM_MD_TX_CONT;
- }
- /* setup Mode Register */
- XM_OUT32(IoC, Port, XM_MODE, MdReg);
-
-} /* SkXmSendCont */
-
-
-/******************************************************************************
- *
- * SkMacTimeStamp() - Enable / Disable Time Stamp
- *
- * Description: enable / disable Time Stamp generation for Rx packets
- *
- * Returns:
- * nothing
- */
-void SkMacTimeStamp(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL Enable) /* Enable / Disable */
-{
- SK_U32 MdReg;
- SK_U8 TimeCtrl;
-
- if (pAC->GIni.GIGenesis) {
-
- XM_IN32(IoC, Port, XM_MODE, &MdReg);
-
- if (Enable) {
- MdReg |= XM_MD_ATS;
- }
- else {
- MdReg &= ~XM_MD_ATS;
- }
- /* setup Mode Register */
- XM_OUT32(IoC, Port, XM_MODE, MdReg);
- }
- else {
- if (Enable) {
- TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
- }
- else {
- TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
- }
- /* Start/Stop Time Stamp Timer */
- SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
- }
-
-} /* SkMacTimeStamp*/
-
-#else /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
- *
- * This function analyses the Interrupt status word. If any of the
- * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
- * is set true.
- */
-void SkXmAutoNegLipaXmac(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U16 IStatus) /* Interrupt Status word to analyse */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
- (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
- Port, IStatus));
- pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
- }
-} /* SkXmAutoNegLipaXmac */
-#endif /* GENESIS */
-
-
-/******************************************************************************
- *
- * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
- *
- * This function analyses the PHY status word.
- * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
- * is set true.
- */
-void SkMacAutoNegLipaPhy(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_U16 PhyStat) /* PHY Status word to analyse */
-{
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
- (PhyStat & PHY_ST_AN_OVER) != 0) {
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
- Port, PhyStat));
- pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
- }
-} /* SkMacAutoNegLipaPhy */
-
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmIrq() - Interrupt Service Routine
- *
- * Description: services an Interrupt Request of the XMAC
- *
- * Note:
- * With an external PHY, some interrupt bits are not meaningfull any more:
- * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
- * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
- * - Page Received (bit #9) XM_IS_RX_PAGE
- * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
- * - AutoNegDone (bit #7) XM_IS_AND
- * Also probably not valid any more is the GP0 input bit:
- * - GPRegisterBit0set XM_IS_INP_ASS
- *
- * Returns:
- * nothing
- */
-static void SkXmIrq(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_EVPARA Para;
- SK_U16 IStatus; /* Interrupt status read from the XMAC */
- SK_U16 IStatus2;
-#ifdef SK_SLIM
- SK_U64 OverflowStatus;
-#endif
-
- pPrt = &pAC->GIni.GP[Port];
-
- XM_IN16(IoC, Port, XM_ISRC, &IStatus);
-
- /* LinkPartner Auto-negable? */
- if (pPrt->PhyType == SK_PHY_XMAC) {
- SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
- }
- else {
- /* mask bits that are not used with ext. PHY */
- IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
- XM_IS_RX_PAGE | XM_IS_TX_PAGE |
- XM_IS_AND | XM_IS_INP_ASS);
- }
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
- if (!pPrt->PHWLinkUp) {
- /* Spurious XMAC interrupt */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("SkXmIrq: spurious interrupt on Port %d\n", Port));
- return;
- }
-
- if ((IStatus & XM_IS_INP_ASS) != 0) {
- /* Reread ISR Register if link is not in sync */
- XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
- Port, IStatus, IStatus2));
- IStatus &= ~XM_IS_INP_ASS;
- IStatus |= IStatus2;
- }
-
- if ((IStatus & XM_IS_LNK_AE) != 0) {
- /* not used, GP0 is used instead */
- }
-
- if ((IStatus & XM_IS_TX_ABORT) != 0) {
- /* not used */
- }
-
- if ((IStatus & XM_IS_FRC_INT) != 0) {
- /* not used, use ASIC IRQ instead if needed */
- }
-
- if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
- SkHWLinkDown(pAC, IoC, Port);
-
- /* Signal to RLMT */
- Para.Para32[0] = (SK_U32)Port;
- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
-
- /* Start workaround Errata #2 timer */
- SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
- SKGE_HWAC, SK_HWEV_WATIM, Para);
- }
-
- if ((IStatus & XM_IS_RX_PAGE) != 0) {
- /* not used */
- }
-
- if ((IStatus & XM_IS_TX_PAGE) != 0) {
- /* not used */
- }
-
- if ((IStatus & XM_IS_AND) != 0) {
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("SkXmIrq: AND on link that is up Port %d\n", Port));
- }
-
- if ((IStatus & XM_IS_TSC_OV) != 0) {
- /* not used */
- }
-
- /* Combined Tx & Rx Counter Overflow SIRQ Event */
- if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
-#ifdef SK_SLIM
- SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
- Para.Para32[0] = (SK_U32)Port;
- Para.Para32[1] = (SK_U32)IStatus;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif /* SK_SLIM */
- }
-
- if ((IStatus & XM_IS_RXF_OV) != 0) {
- /* normal situation -> no effect */
-#ifdef DEBUG
- pPrt->PRxOverCnt++;
-#endif /* DEBUG */
- }
-
- if ((IStatus & XM_IS_TXF_UR) != 0) {
- /* may NOT happen -> error log */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
- }
-
- if ((IStatus & XM_IS_TX_COMP) != 0) {
- /* not served here */
- }
-
- if ((IStatus & XM_IS_RX_COMP) != 0) {
- /* not served here */
- }
-} /* SkXmIrq */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmIrq() - Interrupt Service Routine
- *
- * Description: services an Interrupt Request of the GMAC
- *
- * Note:
- *
- * Returns:
- * nothing
- */
-static void SkGmIrq(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U8 IStatus; /* Interrupt status */
-#ifdef SK_SLIM
- SK_U64 OverflowStatus;
-#else
- SK_EVPARA Para;
-#endif
-
- pPrt = &pAC->GIni.GP[Port];
-
- SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
-
-#ifdef XXX
- /* LinkPartner Auto-negable? */
- SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
-#endif /* XXX */
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
-
- /* Combined Tx & Rx Counter Overflow SIRQ Event */
- if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
- /* these IRQs will be cleared by reading GMACs register */
-#ifdef SK_SLIM
- SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
-#else
- Para.Para32[0] = (SK_U32)Port;
- Para.Para32[1] = (SK_U32)IStatus;
- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
-#endif
- }
-
- if (IStatus & GM_IS_RX_FF_OR) {
- /* clear GMAC Rx FIFO Overrun IRQ */
- SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
-#ifdef DEBUG
- pPrt->PRxOverCnt++;
-#endif /* DEBUG */
- }
-
- if (IStatus & GM_IS_TX_FF_UR) {
- /* clear GMAC Tx FIFO Underrun IRQ */
- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
- /* may NOT happen -> error log */
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
- }
-
- if (IStatus & GM_IS_TX_COMPL) {
- /* not served here */
- }
-
- if (IStatus & GM_IS_RX_COMPL) {
- /* not served here */
- }
-} /* SkGmIrq */
-#endif /* YUKON */
-
-
-/******************************************************************************
- *
- * SkMacIrq() - Interrupt Service Routine for MAC
- *
- * Description: calls the Interrupt Service Routine dep. on board type
- *
- * Returns:
- * nothing
- */
-void SkMacIrq(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port) /* Port Index (MAC_1 + n) */
-{
-#ifdef GENESIS
- if (pAC->GIni.GIGenesis) {
- /* IRQ from XMAC */
- SkXmIrq(pAC, IoC, Port);
- }
-#endif /* GENESIS */
-
-#ifdef YUKON
- if (pAC->GIni.GIYukon) {
- /* IRQ from GMAC */
- SkGmIrq(pAC, IoC, Port);
- }
-#endif /* YUKON */
-
-} /* SkMacIrq */
-
-#endif /* !SK_DIAG */
-
-#ifdef GENESIS
-/******************************************************************************
- *
- * SkXmUpdateStats() - Force the XMAC to output the current statistic
- *
- * Description:
- * The XMAC holds its statistic internally. To obtain the current
- * values a command must be sent so that the statistic data will
- * be written to a predefined memory area on the adapter.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkXmUpdateStats(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port) /* Port Index (MAC_1 + n) */
-{
- SK_GEPORT *pPrt;
- SK_U16 StatReg;
- int WaitIndex;
-
- pPrt = &pAC->GIni.GP[Port];
- WaitIndex = 0;
-
- /* Send an update command to XMAC specified */
- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
-
- /*
- * It is an auto-clearing register. If the command bits
- * went to zero again, the statistics are transferred.
- * Normally the command should be executed immediately.
- * But just to be sure we execute a loop.
- */
- do {
-
- XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
-
- if (++WaitIndex > 10) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
-
- return(1);
- }
- } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
-
- return(0);
-} /* SkXmUpdateStats */
-
-
-/******************************************************************************
- *
- * SkXmMacStatistic() - Get XMAC counter value
- *
- * Description:
- * Gets the 32bit counter value. Except for the octet counters
- * the lower 32bit are counted in hardware and the upper 32bit
- * must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkXmMacStatistic(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port, /* Port Index (MAC_1 + n) */
-SK_U16 StatAddr, /* MIB counter base address */
-SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
-{
- if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-
- return(1);
- }
-
- XM_IN32(IoC, Port, StatAddr, pVal);
-
- return(0);
-} /* SkXmMacStatistic */
-
-
-/******************************************************************************
- *
- * SkXmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- * Force the XMAC to clear its statistic counter.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkXmResetCounter(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port) /* Port Index (MAC_1 + n) */
-{
- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
- /* Clear two times according to Errata #3 */
- XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
-
- return(0);
-} /* SkXmResetCounter */
-
-
-/******************************************************************************
- *
- * SkXmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- * Checks the source causing an counter overflow interrupt. On success the
- * resulting counter overflow status is written to <pStatus>, whereas the
- * upper dword stores the XMAC ReceiveCounterEvent register and the lower
- * dword the XMAC TransmitCounterEvent register.
- *
- * Note:
- * For XMAC the interrupt source is a self-clearing register, so the source
- * must be checked only once. SIRQ module does another check to be sure
- * that no interrupt get lost during process time.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkXmOverflowStatus(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port, /* Port Index (MAC_1 + n) */
-SK_U16 IStatus, /* Interupt Status from MAC */
-SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
-{
- SK_U64 Status; /* Overflow status */
- SK_U32 RegVal;
-
- Status = 0;
-
- if ((IStatus & XM_IS_RXC_OV) != 0) {
-
- XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
- Status |= (SK_U64)RegVal << 32;
- }
-
- if ((IStatus & XM_IS_TXC_OV) != 0) {
-
- XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
- Status |= (SK_U64)RegVal;
- }
-
- *pStatus = Status;
-
- return(0);
-} /* SkXmOverflowStatus */
-#endif /* GENESIS */
-
-
-#ifdef YUKON
-/******************************************************************************
- *
- * SkGmUpdateStats() - Force the GMAC to output the current statistic
- *
- * Description:
- * Empty function for GMAC. Statistic data is accessible in direct way.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkGmUpdateStats(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port) /* Port Index (MAC_1 + n) */
-{
- return(0);
-}
-
-
-/******************************************************************************
- *
- * SkGmMacStatistic() - Get GMAC counter value
- *
- * Description:
- * Gets the 32bit counter value. Except for the octet counters
- * the lower 32bit are counted in hardware and the upper 32bit
- * must be counted in software by monitoring counter overflow interrupts.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkGmMacStatistic(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port, /* Port Index (MAC_1 + n) */
-SK_U16 StatAddr, /* MIB counter base address */
-SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
-{
-
- if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
-
- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
- return(1);
- }
-
- GM_IN32(IoC, Port, StatAddr, pVal);
-
- return(0);
-} /* SkGmMacStatistic */
-
-
-/******************************************************************************
- *
- * SkGmResetCounter() - Clear MAC statistic counter
- *
- * Description:
- * Force GMAC to clear its statistic counter.
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkGmResetCounter(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port) /* Port Index (MAC_1 + n) */
-{
- SK_U16 Reg; /* Phy Address Register */
- SK_U16 Word;
- int i;
-
- GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
-
- /* set MIB Clear Counter Mode */
- GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
-
- /* read all MIB Counters with Clear Mode set */
- for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
- /* the reset is performed only when the lower 16 bits are read */
- GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
- }
-
- /* clear MIB Clear Counter Mode */
- GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
-
- return(0);
-} /* SkGmResetCounter */
-
-
-/******************************************************************************
- *
- * SkGmOverflowStatus() - Gets the status of counter overflow interrupt
- *
- * Description:
- * Checks the source causing an counter overflow interrupt. On success the
- * resulting counter overflow status is written to <pStatus>, whereas the
- * the following bit coding is used:
- * 63:56 - unused
- * 55:48 - TxRx interrupt register bit7:0
- * 32:47 - Rx interrupt register
- * 31:24 - unused
- * 23:16 - TxRx interrupt register bit15:8
- * 15:0 - Tx interrupt register
- *
- * Returns:
- * 0: success
- * 1: something went wrong
- */
-int SkGmOverflowStatus(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-unsigned int Port, /* Port Index (MAC_1 + n) */
-SK_U16 IStatus, /* Interupt Status from MAC */
-SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
-{
- SK_U64 Status; /* Overflow status */
- SK_U16 RegVal;
-
- Status = 0;
-
- if ((IStatus & GM_IS_RX_CO_OV) != 0) {
- /* this register is self-clearing after read */
- GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
- Status |= (SK_U64)RegVal << 32;
- }
-
- if ((IStatus & GM_IS_TX_CO_OV) != 0) {
- /* this register is self-clearing after read */
- GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
- Status |= (SK_U64)RegVal;
- }
-
- /* this register is self-clearing after read */
- GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
- /* Rx overflow interrupt register bits (LoByte)*/
- Status |= (SK_U64)((SK_U8)RegVal) << 48;
- /* Tx overflow interrupt register bits (HiByte)*/
- Status |= (SK_U64)(RegVal >> 8) << 16;
-
- *pStatus = Status;
-
- return(0);
-} /* SkGmOverflowStatus */
-
-
-#ifndef SK_SLIM
-/******************************************************************************
- *
- * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
- *
- * Description:
- * starts the cable diagnostic test if 'StartTest' is true
- * gets the results if 'StartTest' is true
- *
- * NOTE: this test is meaningful only when link is down
- *
- * Returns:
- * 0: success
- * 1: no YUKON copper
- * 2: test in progress
- */
-int SkGmCableDiagStatus(
-SK_AC *pAC, /* adapter context */
-SK_IOC IoC, /* IO context */
-int Port, /* Port Index (MAC_1 + n) */
-SK_BOOL StartTest) /* flag for start / get result */
-{
- int i;
- SK_U16 RegVal;
- SK_GEPORT *pPrt;
-
- pPrt = &pAC->GIni.GP[Port];
-
- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
-
- return(1);
- }
-
- if (StartTest) {
- /* only start the cable test */
- if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
- /* apply TDR workaround from Marvell */
- SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
-
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
- SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
- }
-
- /* set address to 0 for MDI[0] */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
-
- /* Read Cable Diagnostic Reg */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
- /* start Cable Diagnostic Test */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
- (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
-
- return(0);
- }
-
- /* Read Cable Diagnostic Reg */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
- ("PHY Cable Diag.=0x%04X\n", RegVal));
-
- if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
- /* test is running */
- return(2);
- }
-
- /* get the test results */
- for (i = 0; i < 4; i++) {
- /* set address to i for MDI[i] */
- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
-
- /* get Cable Diagnostic values */
- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
-
- pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
-
- pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
- }
-
- return(0);
-} /* SkGmCableDiagStatus */
-#endif /* !SK_SLIM */
-#endif /* YUKON */
-
-/* End of file */
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
index fe847800acd..75afc1f07ba 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/skfp/smt.c
@@ -1748,7 +1748,7 @@ char *addr_to_string(struct fddi_addr *addr)
#endif
#ifdef AM29K
-smt_ifconfig(int argc, char *argv[])
+int smt_ifconfig(int argc, char *argv[])
{
if (argc >= 2 && !strcmp(argv[0],"opt_bypass") &&
!strcmp(argv[1],"yes")) {
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index adfbe81693a..a2f32151559 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -39,6 +39,7 @@
#include <linux/workqueue.h>
#include <linux/if_vlan.h>
#include <linux/prefetch.h>
+#include <linux/debugfs.h>
#include <linux/mii.h>
#include <asm/irq.h>
@@ -50,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.14"
+#define DRV_VERSION "1.16"
#define PFX DRV_NAME " "
/*
@@ -64,7 +65,6 @@
#define RX_MAX_PENDING (RX_LE_SIZE/6 - 2)
#define RX_DEF_PENDING RX_MAX_PENDING
#define RX_SKB_ALIGN 8
-#define RX_BUF_WRITE 16
#define TX_RING_SIZE 512
#define TX_DEF_PENDING (TX_RING_SIZE - 1)
@@ -77,6 +77,9 @@
#define NAPI_WEIGHT 64
#define PHY_RETRIES 1000
+#define SKY2_EEPROM_MAGIC 0x9955aabb
+
+
#define RING_NEXT(x,s) (((x)+1) & ((s)-1))
static const u32 default_msg =
@@ -96,7 +99,7 @@ static int disable_msi = 0;
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
-static int idle_timeout = 0;
+static int idle_timeout = 100;
module_param(idle_timeout, int, 0);
MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
@@ -130,7 +133,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4369) }, /* 88EC042 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436A) }, /* 88E8058 */
-// { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436B) }, /* 88E8071 */
{ 0 }
};
@@ -217,13 +220,24 @@ static void sky2_power_on(struct sky2_hw *hw)
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
- u32 reg1;
+ u32 reg;
- sky2_pci_write32(hw, PCI_DEV_REG3, 0);
- reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
- reg1 &= P_ASPM_CONTROL_MSK;
- sky2_pci_write32(hw, PCI_DEV_REG4, reg1);
- sky2_pci_write32(hw, PCI_DEV_REG5, 0);
+ reg = sky2_pci_read32(hw, PCI_DEV_REG4);
+ /* set all bits to 0 except bits 15..12 and 8 */
+ reg &= P_ASPM_CONTROL_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG4, reg);
+
+ reg = sky2_pci_read32(hw, PCI_DEV_REG5);
+ /* set all bits to 0 except bits 28 & 27 */
+ reg &= P_CTL_TIM_VMAIN_AV_MSK;
+ sky2_pci_write32(hw, PCI_DEV_REG5, reg);
+
+ sky2_pci_write32(hw, PCI_CFG_REG_1, 0);
+
+ /* Enable workaround for dev 4.107 on Yukon-Ultra & Extreme */
+ reg = sky2_read32(hw, B2_GP_IO);
+ reg |= GLB_GPIO_STAT_RACE_DIS;
+ sky2_write32(hw, B2_GP_IO, reg);
}
}
@@ -650,6 +664,30 @@ static void sky2_wol_init(struct sky2_port *sky2)
}
+static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
+{
+ if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_STFW_ENA |
+ (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
+ } else {
+ if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+ /* set Tx GMAC FIFO Almost Empty Threshold */
+ sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+ (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_ENA | TX_STFW_DIS);
+
+ /* Can't do offload because of lack of store/forward */
+ hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
+ | NETIF_F_ALL_CSUM);
+ } else
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_DIS | TX_STFW_ENA);
+ }
+}
+
static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
{
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
@@ -730,8 +768,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
/* Configure Rx MAC FIFO */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
- sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
- GMF_OPER_ON | GMF_RX_F_FL_ON);
+ reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ reg |= GMF_RX_OVER_ON;
+
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), reg);
/* Flush Rx MAC FIFO on any flow control or error */
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
@@ -747,16 +788,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
- /* set Tx GMAC FIFO Almost Empty Threshold */
- sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
- (ECU_JUMBO_WM << 16) | ECU_AE_THR);
-
- if (hw->dev[port]->mtu > ETH_DATA_LEN)
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_ENA | TX_STFW_DIS);
- else
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_DIS | TX_STFW_ENA);
+ sky2_set_tx_stfwd(hw, port);
}
}
@@ -861,24 +893,18 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
return le;
}
-/* Return high part of DMA address (could be 32 or 64 bit) */
-static inline u32 high32(dma_addr_t a)
-{
- return sizeof(a) > sizeof(u32) ? (a >> 16) >> 16 : 0;
-}
-
/* Build description to hardware for one receive segment */
static void sky2_rx_add(struct sky2_port *sky2, u8 op,
dma_addr_t map, unsigned len)
{
struct sky2_rx_le *le;
- u32 hi = high32(map);
+ u32 hi = upper_32_bits(map);
if (sky2->rx_addr64 != hi) {
le = sky2_next_rx(sky2);
le->addr = cpu_to_le32(hi);
le->opcode = OP_ADDR64 | HW_OWNER;
- sky2->rx_addr64 = high32(map + len);
+ sky2->rx_addr64 = upper_32_bits(map + len);
}
le = sky2_next_rx(sky2);
@@ -939,14 +965,16 @@ static void rx_set_checksum(struct sky2_port *sky2)
{
struct sky2_rx_le *le;
- le = sky2_next_rx(sky2);
- le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
- le->ctrl = 0;
- le->opcode = OP_TCPSTART | HW_OWNER;
+ if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
+ le = sky2_next_rx(sky2);
+ le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
- sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[sky2->port], Q_CSR),
- sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
+ }
}
@@ -1049,26 +1077,22 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
u16 port = sky2->port;
netif_tx_lock_bh(dev);
+ netif_poll_disable(sky2->hw->dev[0]);
- sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON);
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON);
sky2->vlgrp = grp;
+ if (grp) {
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+ RX_VLAN_STRIP_ON);
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_VLAN_TAG_ON);
+ } else {
+ sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T),
+ RX_VLAN_STRIP_OFF);
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_VLAN_TAG_OFF);
+ }
- netif_tx_unlock_bh(dev);
-}
-
-static void sky2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct sky2_port *sky2 = netdev_priv(dev);
- struct sky2_hw *hw = sky2->hw;
- u16 port = sky2->port;
-
- netif_tx_lock_bh(dev);
-
- sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_OFF);
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF);
- vlan_group_set_device(sky2->vlgrp, vid, NULL);
-
+ netif_poll_enable(sky2->hw->dev[0]);
netif_tx_unlock_bh(dev);
}
#endif
@@ -1110,6 +1134,11 @@ nomem:
return NULL;
}
+static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
+{
+ sky2_put_idx(sky2->hw, rxq, sky2->rx_put);
+}
+
/*
* Allocate and setup receiver buffer pool.
* Normal case this ends up creating one list element for skb
@@ -1138,15 +1167,14 @@ static int sky2_rx_start(struct sky2_port *sky2)
if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
(hw->chip_rev == CHIP_REV_YU_EC_U_A1
|| hw->chip_rev == CHIP_REV_YU_EC_U_B0))
- sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS);
+ sky2_write32(hw, Q_ADDR(rxq, Q_TEST), F_M_RX_RAM_DIS);
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
rx_set_checksum(sky2);
/* Space needed for frame data + headers rounded up */
- size = ALIGN(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8)
- + 8;
+ size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
/* Stopping point for hardware truncation */
thresh = (size - 8) / sizeof(u32);
@@ -1201,7 +1229,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
}
/* Tell chip about available buffers */
- sky2_put_idx(hw, rxq, sky2->rx_put);
+ sky2_rx_update(sky2, rxq);
return 0;
nomem:
sky2_rx_clean(sky2);
@@ -1238,6 +1266,8 @@ static int sky2_up(struct net_device *dev)
if (netif_msg_ifup(sky2))
printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
+ netif_carrier_off(dev);
+
/* must be power of 2 */
sky2->tx_le = pci_alloc_consistent(hw->pdev,
TX_RING_SIZE *
@@ -1289,6 +1319,10 @@ static int sky2_up(struct net_device *dev)
sky2_qset(hw, txqaddr[port]);
+ /* This is copied from sk98lin 10.0.5.3; no one tells me about erratta's */
+ if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev == CHIP_REV_YU_EX_B0)
+ sky2_write32(hw, Q_ADDR(txqaddr[port], Q_TEST), F_TX_CHK_AUTO_OFF);
+
/* Set almost empty threshold */
if (hw->chip_id == CHIP_ID_YUKON_EC_U
&& hw->chip_rev == CHIP_REV_YU_EC_U_A0)
@@ -1384,27 +1418,30 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
len = skb_headlen(skb);
mapping = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
- addr64 = high32(mapping);
+ addr64 = upper_32_bits(mapping);
/* Send high bits if changed or crosses boundary */
- if (addr64 != sky2->tx_addr64 || high32(mapping + len) != sky2->tx_addr64) {
+ if (addr64 != sky2->tx_addr64 ||
+ upper_32_bits(mapping + len) != sky2->tx_addr64) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(addr64);
le->opcode = OP_ADDR64 | HW_OWNER;
- sky2->tx_addr64 = high32(mapping + len);
+ sky2->tx_addr64 = upper_32_bits(mapping + len);
}
/* Check for TCP Segmentation Offload */
mss = skb_shinfo(skb)->gso_size;
if (mss != 0) {
- mss += tcp_optlen(skb); /* TCP options */
- mss += ip_hdrlen(skb) + sizeof(struct tcphdr);
- mss += ETH_HLEN;
-
- if (mss != sky2->tx_last_mss) {
- le = get_tx_le(sky2);
- le->addr = cpu_to_le32(mss);
- le->opcode = OP_LRGLEN | HW_OWNER;
+ if (hw->chip_id != CHIP_ID_YUKON_EX)
+ mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
+
+ if (mss != sky2->tx_last_mss) {
+ le = get_tx_le(sky2);
+ le->addr = cpu_to_le32(mss);
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ le->opcode = OP_MSS | HW_OWNER;
+ else
+ le->opcode = OP_LRGLEN | HW_OWNER;
sky2->tx_last_mss = mss;
}
}
@@ -1426,24 +1463,30 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
/* Handle TCP checksum offload */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- const unsigned offset = skb_transport_offset(skb);
- u32 tcpsum;
-
- tcpsum = offset << 16; /* sum start */
- tcpsum |= offset + skb->csum_offset; /* sum write */
-
- ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
- if (ip_hdr(skb)->protocol == IPPROTO_UDP)
- ctrl |= UDPTCP;
-
- if (tcpsum != sky2->tx_tcpsum) {
- sky2->tx_tcpsum = tcpsum;
-
- le = get_tx_le(sky2);
- le->addr = cpu_to_le32(tcpsum);
- le->length = 0; /* initial checksum value */
- le->ctrl = 1; /* one packet */
- le->opcode = OP_TCPLISW | HW_OWNER;
+ /* On Yukon EX (some versions) encoding change. */
+ if (hw->chip_id == CHIP_ID_YUKON_EX
+ && hw->chip_rev != CHIP_REV_YU_EX_B0)
+ ctrl |= CALSUM; /* auto checksum */
+ else {
+ const unsigned offset = skb_transport_offset(skb);
+ u32 tcpsum;
+
+ tcpsum = offset << 16; /* sum start */
+ tcpsum |= offset + skb->csum_offset; /* sum write */
+
+ ctrl |= CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
+ if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ ctrl |= UDPTCP;
+
+ if (tcpsum != sky2->tx_tcpsum) {
+ sky2->tx_tcpsum = tcpsum;
+
+ le = get_tx_le(sky2);
+ le->addr = cpu_to_le32(tcpsum);
+ le->length = 0; /* initial checksum value */
+ le->ctrl = 1; /* one packet */
+ le->opcode = OP_TCPLISW | HW_OWNER;
+ }
}
}
@@ -1463,7 +1506,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
mapping = pci_map_page(hw->pdev, frag->page, frag->page_offset,
frag->size, PCI_DMA_TODEVICE);
- addr64 = high32(mapping);
+ addr64 = upper_32_bits(mapping);
if (addr64 != sky2->tx_addr64) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(addr64);
@@ -1533,13 +1576,13 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
if (unlikely(netif_msg_tx_done(sky2)))
printk(KERN_DEBUG "%s: tx done %u\n",
dev->name, idx);
+
sky2->net_stats.tx_packets++;
sky2->net_stats.tx_bytes += re->skb->len;
dev_kfree_skb_any(re->skb);
+ sky2->tx_next = RING_NEXT(idx, TX_RING_SIZE);
}
-
- le->opcode = 0; /* paranoia */
}
sky2->tx_cons = idx;
@@ -1577,7 +1620,6 @@ static int sky2_down(struct net_device *dev)
/* Stop more packets from being queued */
netif_stop_queue(dev);
- netif_carrier_off(dev);
/* Disable port IRQ */
imask = sky2_read32(hw, B0_IMSK);
@@ -1629,6 +1671,8 @@ static int sky2_down(struct net_device *dev)
sky2_phy_power(hw, port, 0);
+ netif_carrier_off(dev);
+
/* turn off LED's */
sky2_write16(hw, B0_Y2LED, LED_STAT_OFF);
@@ -1693,7 +1737,6 @@ static void sky2_link_up(struct sky2_port *sky2)
gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
netif_carrier_on(sky2->netdev);
- netif_wake_queue(sky2->netdev);
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
@@ -1745,7 +1788,6 @@ static void sky2_link_down(struct sky2_port *sky2)
gma_write16(hw, port, GM_GP_CTRL, reg);
netif_carrier_off(sky2->netdev);
- netif_stop_queue(sky2->netdev);
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
@@ -1917,15 +1959,8 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
synchronize_irq(hw->pdev->irq);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
- if (new_mtu > ETH_DATA_LEN) {
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_ENA | TX_STFW_DIS);
- dev->features &= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
- } else
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_DIS | TX_STFW_ENA);
- }
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+ sky2_set_tx_stfwd(hw, port);
ctl = gma_read16(hw, port, GM_GP_CTRL);
gma_write16(hw, port, GM_GP_CTRL, ctl & ~GM_GPCR_RX_ENA);
@@ -2023,8 +2058,6 @@ static struct sk_buff *receive_new(struct sky2_port *sky2,
struct sk_buff *skb, *nskb;
unsigned hdr_space = sky2->rx_data_size;
- pr_debug(PFX "receive new length=%d\n", length);
-
/* Don't be tricky about reusing pages (yet) */
nskb = sky2_rx_alloc(sky2);
if (unlikely(!nskb))
@@ -2068,6 +2101,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
if (!(status & GMR_FS_RX_OK))
goto resubmit;
+ if (status >> 16 != length)
+ goto len_mismatch;
+
if (length < copybreak)
skb = receive_copy(sky2, re, length);
else
@@ -2077,6 +2113,11 @@ resubmit:
return skb;
+len_mismatch:
+ /* Truncation of overlength packets
+ causes PHY length to not match MAC length */
+ ++sky2->net_stats.rx_length_errors;
+
error:
++sky2->net_stats.rx_errors;
if (status & GMR_FS_RX_FF_OV) {
@@ -2113,15 +2154,16 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
/* Process status response ring */
static int sky2_status_intr(struct sky2_hw *hw, int to_do)
{
- struct sky2_port *sky2;
int work_done = 0;
- unsigned buf_write[2] = { 0, 0 };
+ unsigned rx[2] = { 0, 0 };
u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
rmb();
while (hw->st_idx != hwidx) {
+ struct sky2_port *sky2;
struct sky2_status_le *le = hw->st_le + hw->st_idx;
+ unsigned port = le->css & CSS_LINK_BIT;
struct net_device *dev;
struct sk_buff *skb;
u32 status;
@@ -2129,19 +2171,28 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
hw->st_idx = RING_NEXT(hw->st_idx, STATUS_RING_SIZE);
- BUG_ON(le->link >= 2);
- dev = hw->dev[le->link];
-
+ dev = hw->dev[port];
sky2 = netdev_priv(dev);
length = le16_to_cpu(le->length);
status = le32_to_cpu(le->status);
switch (le->opcode & ~HW_OWNER) {
case OP_RXSTAT:
+ ++rx[port];
skb = sky2_receive(dev, length, status);
if (unlikely(!skb)) {
sky2->net_stats.rx_dropped++;
- goto force_update;
+ break;
+ }
+
+ /* This chip reports checksum status differently */
+ if (hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (sky2->rx_csum &&
+ (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
+ (le->css & CSS_TCPUDPCSOK))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
}
skb->protocol = eth_type_trans(skb, dev);
@@ -2158,13 +2209,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
#endif
netif_receive_skb(skb);
- /* Update receiver after 16 frames */
- if (++buf_write[le->link] == RX_BUF_WRITE) {
-force_update:
- sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put);
- buf_write[le->link] = 0;
- }
-
/* Stop after net poll weight */
if (++work_done >= to_do)
goto exit_loop;
@@ -2183,6 +2227,9 @@ force_update:
if (!sky2->rx_csum)
break;
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ break;
+
/* Both checksum counters are programmed to start at
* the same offset, so unless there is a problem they
* should match. This failure is an early indication that
@@ -2198,7 +2245,7 @@ force_update:
dev->name, status);
sky2->rx_csum = 0;
sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[le->link], Q_CSR),
+ Q_ADDR(rxqaddr[port], Q_CSR),
BMU_DIS_RX_CHKSUM);
}
break;
@@ -2217,24 +2264,18 @@ force_update:
if (net_ratelimit())
printk(KERN_WARNING PFX
"unknown status opcode 0x%x\n", le->opcode);
- goto exit_loop;
}
}
/* Fully processed status ring so clear irq */
sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
- mmiowb();
exit_loop:
- if (buf_write[0]) {
- sky2 = netdev_priv(hw->dev[0]);
- sky2_put_idx(hw, Q_R1, sky2->rx_put);
- }
+ if (rx[0])
+ sky2_rx_update(netdev_priv(hw->dev[0]), Q_R1);
- if (buf_write[1]) {
- sky2 = netdev_priv(hw->dev[1]);
- sky2_put_idx(hw, Q_R2, sky2->rx_put);
- }
+ if (rx[1])
+ sky2_rx_update(netdev_priv(hw->dev[1]), Q_R2);
return work_done;
}
@@ -2431,8 +2472,7 @@ static void sky2_err_intr(struct sky2_hw *hw, u32 status)
static int sky2_poll(struct net_device *dev0, int *budget)
{
struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw;
- int work_limit = min(dev0->quota, *budget);
- int work_done = 0;
+ int work_done;
u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
if (unlikely(status & Y2_IS_ERROR))
@@ -2444,18 +2484,25 @@ static int sky2_poll(struct net_device *dev0, int *budget)
if (status & Y2_IS_IRQ_PHY2)
sky2_phy_intr(hw, 1);
- work_done = sky2_status_intr(hw, work_limit);
- if (work_done < work_limit) {
- netif_rx_complete(dev0);
+ work_done = sky2_status_intr(hw, min(dev0->quota, *budget));
+ *budget -= work_done;
+ dev0->quota -= work_done;
- /* end of interrupt, re-enables also acts as I/O synchronization */
- sky2_read32(hw, B0_Y2_SP_LISR);
- return 0;
- } else {
- *budget -= work_done;
- dev0->quota -= work_done;
+ /* More work? */
+ if (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX))
return 1;
+
+ /* Bug/Errata workaround?
+ * Need to kick the TX irq moderation timer.
+ */
+ if (sky2_read8(hw, STAT_TX_TIMER_CTRL) == TIM_START) {
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_STOP);
+ sky2_write8(hw, STAT_TX_TIMER_CTRL, TIM_START);
}
+ netif_rx_complete(dev0);
+
+ sky2_read32(hw, B0_Y2_SP_LISR);
+ return 0;
}
static irqreturn_t sky2_intr(int irq, void *dev_id)
@@ -2517,6 +2564,9 @@ static int __devinit sky2_init(struct sky2_hw *hw)
{
u8 t8;
+ /* Enable all clocks */
+ sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
sky2_write8(hw, B0_CTST, CS_RST_CLR);
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
@@ -2526,14 +2576,6 @@ static int __devinit sky2_init(struct sky2_hw *hw)
return -EOPNOTSUPP;
}
- if (hw->chip_id == CHIP_ID_YUKON_EX)
- dev_warn(&hw->pdev->dev, "this driver not yet tested on this chip type\n"
- "Please report success or failure to <netdev@vger.kernel.org>\n");
-
- /* Make sure and enable all clocks */
- if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
- sky2_pci_write32(hw, PCI_DEV_REG3, 0);
-
hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
/* This rev is really old, and requires untested workarounds */
@@ -2593,6 +2635,11 @@ static void sky2_reset(struct sky2_hw *hw)
for (i = 0; i < hw->ports; i++) {
sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+
+ if (hw->chip_id == CHIP_ID_YUKON_EX)
+ sky2_write16(hw, SK_REG(i, GMAC_CTRL),
+ GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
+ | GMC_BYP_RETR_ON);
}
sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
@@ -2679,8 +2726,6 @@ static void sky2_restart(struct work_struct *work)
struct net_device *dev;
int i, err;
- dev_dbg(&hw->pdev->dev, "restarting\n");
-
del_timer_sync(&hw->idle_timer);
rtnl_lock();
@@ -2739,7 +2784,7 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
sky2->wol = wol->wolopts;
- if (hw->chip_id == CHIP_ID_YUKON_EC_U)
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
sky2_write32(hw, B0_CTST, sky2->wol
? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
@@ -3334,7 +3379,7 @@ static int sky2_get_regs_len(struct net_device *dev)
/*
* Returns copy of control register region
- * Note: access to the RAM address register set will cause timeouts.
+ * Note: ethtool_get_regs always provides full size (16k) buffer
*/
static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *p)
@@ -3342,15 +3387,19 @@ static void sky2_get_regs(struct net_device *dev, struct ethtool_regs *regs,
const struct sky2_port *sky2 = netdev_priv(dev);
const void __iomem *io = sky2->hw->regs;
- BUG_ON(regs->len < B3_RI_WTO_R1);
regs->version = 1;
memset(p, 0, regs->len);
memcpy_fromio(p, io, B3_RAM_ADDR);
- memcpy_fromio(p + B3_RI_WTO_R1,
- io + B3_RI_WTO_R1,
- regs->len - B3_RI_WTO_R1);
+ /* skip diagnostic ram region */
+ memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, 0x2000 - B3_RI_WTO_R1);
+
+ /* copy GMAC registers */
+ memcpy_fromio(p + BASE_GMAC_1, io + BASE_GMAC_1, 0x1000);
+ if (sky2->hw->ports > 1)
+ memcpy_fromio(p + BASE_GMAC_2, io + BASE_GMAC_2, 0x1000);
+
}
/* In order to do Jumbo packets on these chips, need to turn off the
@@ -3361,9 +3410,7 @@ static int no_tx_offload(struct net_device *dev)
const struct sky2_port *sky2 = netdev_priv(dev);
const struct sky2_hw *hw = sky2->hw;
- return dev->mtu > ETH_DATA_LEN &&
- (hw->chip_id == CHIP_ID_YUKON_EX
- || hw->chip_id == CHIP_ID_YUKON_EC_U);
+ return dev->mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U;
}
static int sky2_set_tx_csum(struct net_device *dev, u32 data)
@@ -3383,39 +3430,315 @@ static int sky2_set_tso(struct net_device *dev, u32 data)
return ethtool_op_set_tso(dev, data);
}
+static int sky2_get_eeprom_len(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ u16 reg2;
+
+ reg2 = sky2_pci_read32(sky2->hw, PCI_DEV_REG2);
+ return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
+}
+
+static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset)
+{
+ sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
+
+ while (!(sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F))
+ cpu_relax();
+ return sky2_pci_read32(hw, cap + PCI_VPD_DATA);
+}
+
+static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val)
+{
+ sky2_pci_write32(hw, cap + PCI_VPD_DATA, val);
+ sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
+ do {
+ cpu_relax();
+ } while (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F);
+}
+
+static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+ int length = eeprom->len;
+ u16 offset = eeprom->offset;
+
+ if (!cap)
+ return -EINVAL;
+
+ eeprom->magic = SKY2_EEPROM_MAGIC;
+
+ while (length > 0) {
+ u32 val = sky2_vpd_read(sky2->hw, cap, offset);
+ int n = min_t(int, length, sizeof(val));
+
+ memcpy(data, &val, n);
+ length -= n;
+ data += n;
+ offset += n;
+ }
+ return 0;
+}
+
+static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *data)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
+ int length = eeprom->len;
+ u16 offset = eeprom->offset;
+
+ if (!cap)
+ return -EINVAL;
+
+ if (eeprom->magic != SKY2_EEPROM_MAGIC)
+ return -EINVAL;
+
+ while (length > 0) {
+ u32 val;
+ int n = min_t(int, length, sizeof(val));
+
+ if (n < sizeof(val))
+ val = sky2_vpd_read(sky2->hw, cap, offset);
+ memcpy(&val, data, n);
+
+ sky2_vpd_write(sky2->hw, cap, offset, val);
+
+ length -= n;
+ data += n;
+ offset += n;
+ }
+ return 0;
+}
+
+
static const struct ethtool_ops sky2_ethtool_ops = {
- .get_settings = sky2_get_settings,
- .set_settings = sky2_set_settings,
- .get_drvinfo = sky2_get_drvinfo,
- .get_wol = sky2_get_wol,
- .set_wol = sky2_set_wol,
- .get_msglevel = sky2_get_msglevel,
- .set_msglevel = sky2_set_msglevel,
- .nway_reset = sky2_nway_reset,
- .get_regs_len = sky2_get_regs_len,
- .get_regs = sky2_get_regs,
- .get_link = ethtool_op_get_link,
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
- .get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = sky2_set_tx_csum,
- .get_tso = ethtool_op_get_tso,
- .set_tso = sky2_set_tso,
- .get_rx_csum = sky2_get_rx_csum,
- .set_rx_csum = sky2_set_rx_csum,
- .get_strings = sky2_get_strings,
- .get_coalesce = sky2_get_coalesce,
- .set_coalesce = sky2_set_coalesce,
- .get_ringparam = sky2_get_ringparam,
- .set_ringparam = sky2_set_ringparam,
+ .get_settings = sky2_get_settings,
+ .set_settings = sky2_set_settings,
+ .get_drvinfo = sky2_get_drvinfo,
+ .get_wol = sky2_get_wol,
+ .set_wol = sky2_set_wol,
+ .get_msglevel = sky2_get_msglevel,
+ .set_msglevel = sky2_set_msglevel,
+ .nway_reset = sky2_nway_reset,
+ .get_regs_len = sky2_get_regs_len,
+ .get_regs = sky2_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = sky2_get_eeprom_len,
+ .get_eeprom = sky2_get_eeprom,
+ .set_eeprom = sky2_set_eeprom,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = sky2_set_tx_csum,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = sky2_set_tso,
+ .get_rx_csum = sky2_get_rx_csum,
+ .set_rx_csum = sky2_set_rx_csum,
+ .get_strings = sky2_get_strings,
+ .get_coalesce = sky2_get_coalesce,
+ .set_coalesce = sky2_set_coalesce,
+ .get_ringparam = sky2_get_ringparam,
+ .set_ringparam = sky2_set_ringparam,
.get_pauseparam = sky2_get_pauseparam,
.set_pauseparam = sky2_set_pauseparam,
- .phys_id = sky2_phys_id,
+ .phys_id = sky2_phys_id,
.get_stats_count = sky2_get_stats_count,
.get_ethtool_stats = sky2_get_ethtool_stats,
.get_perm_addr = ethtool_op_get_perm_addr,
};
+#ifdef CONFIG_SKY2_DEBUG
+
+static struct dentry *sky2_debug;
+
+static int sky2_debug_show(struct seq_file *seq, void *v)
+{
+ struct net_device *dev = seq->private;
+ const struct sky2_port *sky2 = netdev_priv(dev);
+ const struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ unsigned idx, last;
+ int sop;
+
+ if (!netif_running(dev))
+ return -ENETDOWN;
+
+ seq_printf(seq, "IRQ src=%x mask=%x control=%x\n",
+ sky2_read32(hw, B0_ISRC),
+ sky2_read32(hw, B0_IMSK),
+ sky2_read32(hw, B0_Y2_SP_ICR));
+
+ netif_poll_disable(hw->dev[0]);
+ last = sky2_read16(hw, STAT_PUT_IDX);
+
+ if (hw->st_idx == last)
+ seq_puts(seq, "Status ring (empty)\n");
+ else {
+ seq_puts(seq, "Status ring\n");
+ for (idx = hw->st_idx; idx != last && idx < STATUS_RING_SIZE;
+ idx = RING_NEXT(idx, STATUS_RING_SIZE)) {
+ const struct sky2_status_le *le = hw->st_le + idx;
+ seq_printf(seq, "[%d] %#x %d %#x\n",
+ idx, le->opcode, le->length, le->status);
+ }
+ seq_puts(seq, "\n");
+ }
+
+ seq_printf(seq, "Tx ring pending=%u...%u report=%d done=%d\n",
+ sky2->tx_cons, sky2->tx_prod,
+ sky2_read16(hw, port == 0 ? STAT_TXA1_RIDX : STAT_TXA2_RIDX),
+ sky2_read16(hw, Q_ADDR(txqaddr[port], Q_DONE)));
+
+ /* Dump contents of tx ring */
+ sop = 1;
+ for (idx = sky2->tx_next; idx != sky2->tx_prod && idx < TX_RING_SIZE;
+ idx = RING_NEXT(idx, TX_RING_SIZE)) {
+ const struct sky2_tx_le *le = sky2->tx_le + idx;
+ u32 a = le32_to_cpu(le->addr);
+
+ if (sop)
+ seq_printf(seq, "%u:", idx);
+ sop = 0;
+
+ switch(le->opcode & ~HW_OWNER) {
+ case OP_ADDR64:
+ seq_printf(seq, " %#x:", a);
+ break;
+ case OP_LRGLEN:
+ seq_printf(seq, " mtu=%d", a);
+ break;
+ case OP_VLAN:
+ seq_printf(seq, " vlan=%d", be16_to_cpu(le->length));
+ break;
+ case OP_TCPLISW:
+ seq_printf(seq, " csum=%#x", a);
+ break;
+ case OP_LARGESEND:
+ seq_printf(seq, " tso=%#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ case OP_PACKET:
+ seq_printf(seq, " %#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ case OP_BUFFER:
+ seq_printf(seq, " frag=%#x(%d)", a, le16_to_cpu(le->length));
+ break;
+ default:
+ seq_printf(seq, " op=%#x,%#x(%d)", le->opcode,
+ a, le16_to_cpu(le->length));
+ }
+
+ if (le->ctrl & EOP) {
+ seq_putc(seq, '\n');
+ sop = 1;
+ }
+ }
+
+ seq_printf(seq, "\nRx ring hw get=%d put=%d last=%d\n",
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_GET_IDX)),
+ last = sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_PUT_IDX)),
+ sky2_read16(hw, Y2_QADDR(rxqaddr[port], PREF_UNIT_LAST_IDX)));
+
+ netif_poll_enable(hw->dev[0]);
+ return 0;
+}
+
+static int sky2_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, sky2_debug_show, inode->i_private);
+}
+
+static const struct file_operations sky2_debug_fops = {
+ .owner = THIS_MODULE,
+ .open = sky2_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
+ * Use network device events to create/remove/rename
+ * debugfs file entries
+ */
+static int sky2_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+
+ if (dev->open == sky2_up) {
+ struct sky2_port *sky2 = netdev_priv(dev);
+
+ switch(event) {
+ case NETDEV_CHANGENAME:
+ if (!netif_running(dev))
+ break;
+ /* fallthrough */
+ case NETDEV_DOWN:
+ case NETDEV_GOING_DOWN:
+ if (sky2->debugfs) {
+ printk(KERN_DEBUG PFX "%s: remove debugfs\n",
+ dev->name);
+ debugfs_remove(sky2->debugfs);
+ sky2->debugfs = NULL;
+ }
+
+ if (event != NETDEV_CHANGENAME)
+ break;
+ /* fallthrough for changename */
+ case NETDEV_UP:
+ if (sky2_debug) {
+ struct dentry *d;
+ d = debugfs_create_file(dev->name, S_IRUGO,
+ sky2_debug, dev,
+ &sky2_debug_fops);
+ if (d == NULL || IS_ERR(d))
+ printk(KERN_INFO PFX
+ "%s: debugfs create failed\n",
+ dev->name);
+ else
+ sky2->debugfs = d;
+ }
+ break;
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block sky2_notifier = {
+ .notifier_call = sky2_device_event,
+};
+
+
+static __init void sky2_debug_init(void)
+{
+ struct dentry *ent;
+
+ ent = debugfs_create_dir("sky2", NULL);
+ if (!ent || IS_ERR(ent))
+ return;
+
+ sky2_debug = ent;
+ register_netdevice_notifier(&sky2_notifier);
+}
+
+static __exit void sky2_debug_cleanup(void)
+{
+ if (sky2_debug) {
+ unregister_netdevice_notifier(&sky2_notifier);
+ debugfs_remove(sky2_debug);
+ sky2_debug = NULL;
+ }
+}
+
+#else
+#define sky2_debug_init()
+#define sky2_debug_cleanup()
+#endif
+
+
/* Initialize network device */
static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
unsigned port,
@@ -3484,17 +3807,12 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
#ifdef SKY2_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register = sky2_vlan_rx_register;
- dev->vlan_rx_kill_vid = sky2_vlan_rx_kill_vid;
#endif
/* read the mac address */
memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- /* device is off until link detection */
- netif_carrier_off(dev);
- netif_stop_queue(dev);
-
return dev;
}
@@ -3911,12 +4229,14 @@ static struct pci_driver sky2_driver = {
static int __init sky2_init_module(void)
{
+ sky2_debug_init();
return pci_register_driver(&sky2_driver);
}
static void __exit sky2_cleanup_module(void)
{
pci_unregister_driver(&sky2_driver);
+ sky2_debug_cleanup();
}
module_init(sky2_init_module);
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index b8c4a3b5ead..dce4d276d44 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -14,6 +14,8 @@ enum {
PCI_DEV_REG3 = 0x80,
PCI_DEV_REG4 = 0x84,
PCI_DEV_REG5 = 0x88,
+ PCI_CFG_REG_0 = 0x90,
+ PCI_CFG_REG_1 = 0x94,
};
enum {
@@ -28,6 +30,7 @@ enum {
enum pci_dev_reg_1 {
PCI_Y2_PIG_ENA = 1<<31, /* Enable Plug-in-Go (YUKON-2) */
PCI_Y2_DLL_DIS = 1<<30, /* Disable PCI DLL (YUKON-2) */
+ PCI_SW_PWR_ON_RST= 1<<30, /* SW Power on Reset (Yukon-EX) */
PCI_Y2_PHY2_COMA = 1<<29, /* Set PHY 2 to Coma Mode (YUKON-2) */
PCI_Y2_PHY1_COMA = 1<<28, /* Set PHY 1 to Coma Mode (YUKON-2) */
PCI_Y2_PHY2_POWD = 1<<27, /* Set PHY 2 to Power Down (YUKON-2) */
@@ -67,6 +70,80 @@ enum pci_dev_reg_4 {
| P_ASPM_CLKRUN_REQUEST | P_ASPM_INT_FIFO_EMPTY,
};
+/* PCI_OUR_REG_5 32 bit Our Register 5 (Yukon-ECU only) */
+enum pci_dev_reg_5 {
+ /* Bit 31..27: for A3 & later */
+ P_CTL_DIV_CORE_CLK_ENA = 1<<31, /* Divide Core Clock Enable */
+ P_CTL_SRESET_VMAIN_AV = 1<<30, /* Soft Reset for Vmain_av De-Glitch */
+ P_CTL_BYPASS_VMAIN_AV = 1<<29, /* Bypass En. for Vmain_av De-Glitch */
+ P_CTL_TIM_VMAIN_AV_MSK = 3<<27, /* Bit 28..27: Timer Vmain_av Mask */
+ /* Bit 26..16: Release Clock on Event */
+ P_REL_PCIE_RST_DE_ASS = 1<<26, /* PCIe Reset De-Asserted */
+ P_REL_GPHY_REC_PACKET = 1<<25, /* GPHY Received Packet */
+ P_REL_INT_FIFO_N_EMPTY = 1<<24, /* Internal FIFO Not Empty */
+ P_REL_MAIN_PWR_AVAIL = 1<<23, /* Main Power Available */
+ P_REL_CLKRUN_REQ_REL = 1<<22, /* CLKRUN Request Release */
+ P_REL_PCIE_RESET_ASS = 1<<21, /* PCIe Reset Asserted */
+ P_REL_PME_ASSERTED = 1<<20, /* PME Asserted */
+ P_REL_PCIE_EXIT_L1_ST = 1<<19, /* PCIe Exit L1 State */
+ P_REL_LOADER_NOT_FIN = 1<<18, /* EPROM Loader Not Finished */
+ P_REL_PCIE_RX_EX_IDLE = 1<<17, /* PCIe Rx Exit Electrical Idle State */
+ P_REL_GPHY_LINK_UP = 1<<16, /* GPHY Link Up */
+
+ /* Bit 10.. 0: Mask for Gate Clock */
+ P_GAT_PCIE_RST_ASSERTED = 1<<10,/* PCIe Reset Asserted */
+ P_GAT_GPHY_N_REC_PACKET = 1<<9, /* GPHY Not Received Packet */
+ P_GAT_INT_FIFO_EMPTY = 1<<8, /* Internal FIFO Empty */
+ P_GAT_MAIN_PWR_N_AVAIL = 1<<7, /* Main Power Not Available */
+ P_GAT_CLKRUN_REQ_REL = 1<<6, /* CLKRUN Not Requested */
+ P_GAT_PCIE_RESET_ASS = 1<<5, /* PCIe Reset Asserted */
+ P_GAT_PME_DE_ASSERTED = 1<<4, /* PME De-Asserted */
+ P_GAT_PCIE_ENTER_L1_ST = 1<<3, /* PCIe Enter L1 State */
+ P_GAT_LOADER_FINISHED = 1<<2, /* EPROM Loader Finished */
+ P_GAT_PCIE_RX_EL_IDLE = 1<<1, /* PCIe Rx Electrical Idle State */
+ P_GAT_GPHY_LINK_DOWN = 1<<0, /* GPHY Link Down */
+
+ PCIE_OUR5_EVENT_CLK_D3_SET = P_REL_GPHY_REC_PACKET |
+ P_REL_INT_FIFO_N_EMPTY |
+ P_REL_PCIE_EXIT_L1_ST |
+ P_REL_PCIE_RX_EX_IDLE |
+ P_GAT_GPHY_N_REC_PACKET |
+ P_GAT_INT_FIFO_EMPTY |
+ P_GAT_PCIE_ENTER_L1_ST |
+ P_GAT_PCIE_RX_EL_IDLE,
+};
+
+#/* PCI_CFG_REG_1 32 bit Config Register 1 (Yukon-Ext only) */
+enum pci_cfg_reg1 {
+ P_CF1_DIS_REL_EVT_RST = 1<<24, /* Dis. Rel. Event during PCIE reset */
+ /* Bit 23..21: Release Clock on Event */
+ P_CF1_REL_LDR_NOT_FIN = 1<<23, /* EEPROM Loader Not Finished */
+ P_CF1_REL_VMAIN_AVLBL = 1<<22, /* Vmain available */
+ P_CF1_REL_PCIE_RESET = 1<<21, /* PCI-E reset */
+ /* Bit 20..18: Gate Clock on Event */
+ P_CF1_GAT_LDR_NOT_FIN = 1<<20, /* EEPROM Loader Finished */
+ P_CF1_GAT_PCIE_RX_IDLE = 1<<19, /* PCI-E Rx Electrical idle */
+ P_CF1_GAT_PCIE_RESET = 1<<18, /* PCI-E Reset */
+ P_CF1_PRST_PHY_CLKREQ = 1<<17, /* Enable PCI-E rst & PM2PHY gen. CLKREQ */
+ P_CF1_PCIE_RST_CLKREQ = 1<<16, /* Enable PCI-E rst generate CLKREQ */
+
+ P_CF1_ENA_CFG_LDR_DONE = 1<<8, /* Enable core level Config loader done */
+
+ P_CF1_ENA_TXBMU_RD_IDLE = 1<<1, /* Enable TX BMU Read IDLE for ASPM */
+ P_CF1_ENA_TXBMU_WR_IDLE = 1<<0, /* Enable TX BMU Write IDLE for ASPM */
+
+ PCIE_CFG1_EVENT_CLK_D3_SET = P_CF1_DIS_REL_EVT_RST |
+ P_CF1_REL_LDR_NOT_FIN |
+ P_CF1_REL_VMAIN_AVLBL |
+ P_CF1_REL_PCIE_RESET |
+ P_CF1_GAT_LDR_NOT_FIN |
+ P_CF1_GAT_PCIE_RESET |
+ P_CF1_PRST_PHY_CLKREQ |
+ P_CF1_ENA_CFG_LDR_DONE |
+ P_CF1_ENA_TXBMU_RD_IDLE |
+ P_CF1_ENA_TXBMU_WR_IDLE,
+};
+
#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
PCI_STATUS_SIG_SYSTEM_ERROR | \
@@ -364,6 +441,20 @@ enum {
TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
};
+/* B2_GPIO */
+enum {
+ GLB_GPIO_CLK_DEB_ENA = 1<<31, /* Clock Debug Enable */
+ GLB_GPIO_CLK_DBG_MSK = 0xf<<26, /* Clock Debug */
+
+ GLB_GPIO_INT_RST_D3_DIS = 1<<15, /* Disable Internal Reset After D3 to D0 */
+ GLB_GPIO_LED_PAD_SPEED_UP = 1<<14, /* LED PAD Speed Up */
+ GLB_GPIO_STAT_RACE_DIS = 1<<13, /* Status Race Disable */
+ GLB_GPIO_TEST_SEL_MSK = 3<<11, /* Testmode Select */
+ GLB_GPIO_TEST_SEL_BASE = 1<<11,
+ GLB_GPIO_RAND_ENA = 1<<10, /* Random Enable */
+ GLB_GPIO_RAND_BIT_1 = 1<<9, /* Random Bit 1 */
+};
+
/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
enum {
CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */
@@ -392,6 +483,11 @@ enum {
CHIP_REV_YU_FE_A2 = 2,
};
+enum yukon_ex_rev {
+ CHIP_REV_YU_EX_A0 = 1,
+ CHIP_REV_YU_EX_B0 = 2,
+};
+
/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
enum {
@@ -515,23 +611,15 @@ enum {
enum {
B8_Q_REGS = 0x0400, /* base of Queue registers */
Q_D = 0x00, /* 8*32 bit Current Descriptor */
- Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */
- Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */
+ Q_VLAN = 0x20, /* 16 bit Current VLAN Tag */
+ Q_DONE = 0x24, /* 16 bit Done Index */
Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */
Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */
Q_BC = 0x30, /* 32 bit Current Byte Counter */
Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */
- Q_F = 0x38, /* 32 bit Flag Register */
- Q_T1 = 0x3c, /* 32 bit Test Register 1 */
- Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */
- Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */
- Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */
- Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */
- Q_T2 = 0x40, /* 32 bit Test Register 2 */
- Q_T3 = 0x44, /* 32 bit Test Register 3 */
+ Q_TEST = 0x38, /* 32 bit Test/Control Register */
/* Yukon-2 */
- Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */
Q_WM = 0x40, /* 16 bit FIFO Watermark */
Q_AL = 0x42, /* 8 bit FIFO Alignment */
Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */
@@ -545,15 +633,16 @@ enum {
};
#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
-/* Q_F 32 bit Flag Register */
+/* Q_TEST 32 bit Test Register */
enum {
- F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
- F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
- F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
- F_WM_REACHED = 1<<25, /* Watermark reached */
+ /* Transmit */
+ F_TX_CHK_AUTO_OFF = 1<<31, /* Tx checksum auto calc off (Yukon EX) */
+ F_TX_CHK_AUTO_ON = 1<<30, /* Tx checksum auto calc off (Yukon EX) */
+
+ /* Receive */
F_M_RX_RAM_DIS = 1<<24, /* MAC Rx RAM Read Port disable */
- F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
- F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
+
+ /* Hardware testbits not used */
};
/* Queue Prefetch Unit Offsets, use Y2_QADDR() to address (Yukon-2 only)*/
@@ -1608,6 +1697,16 @@ enum {
RX_VLAN_STRIP_ON = 1<<25, /* enable VLAN stripping */
RX_VLAN_STRIP_OFF = 1<<24, /* disable VLAN stripping */
+ RX_MACSEC_FLUSH_ON = 1<<23,
+ RX_MACSEC_FLUSH_OFF = 1<<22,
+ RX_MACSEC_ASF_FLUSH_ON = 1<<21,
+ RX_MACSEC_ASF_FLUSH_OFF = 1<<20,
+
+ GMF_RX_OVER_ON = 1<<19, /* enable flushing on receive overrun */
+ GMF_RX_OVER_OFF = 1<<18, /* disable flushing on receive overrun */
+ GMF_ASF_RX_OVER_ON = 1<<17, /* enable flushing of ASF when overrun */
+ GMF_ASF_RX_OVER_OFF = 1<<16, /* disable flushing of ASF when overrun */
+
GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */
GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */
GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */
@@ -1720,6 +1819,15 @@ enum {
/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
enum {
+ GMC_SET_RST = 1<<15,/* MAC SEC RST */
+ GMC_SEC_RST_OFF = 1<<14,/* MAC SEC RSt OFF */
+ GMC_BYP_MACSECRX_ON = 1<<13,/* Bypass macsec RX */
+ GMC_BYP_MACSECRX_OFF= 1<<12,/* Bypass macsec RX off */
+ GMC_BYP_MACSECTX_ON = 1<<11,/* Bypass macsec TX */
+ GMC_BYP_MACSECTX_OFF= 1<<10,/* Bypass macsec TX off*/
+ GMC_BYP_RETR_ON = 1<<9, /* Bypass retransmit FIFO On */
+ GMC_BYP_RETR_OFF= 1<<8, /* Bypass retransmit FIFO Off */
+
GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */
GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */
GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */
@@ -1805,9 +1913,13 @@ enum {
OP_ADDR64VLAN = OP_ADDR64 | OP_VLAN,
OP_LRGLEN = 0x24,
OP_LRGLENVLAN = OP_LRGLEN | OP_VLAN,
+ OP_MSS = 0x28,
+ OP_MSSVLAN = OP_MSS | OP_VLAN,
+
OP_BUFFER = 0x40,
OP_PACKET = 0x41,
OP_LARGESEND = 0x43,
+ OP_LSOV2 = 0x45,
/* YUKON-2 STATUS opcodes defines */
OP_RXSTAT = 0x60,
@@ -1818,6 +1930,19 @@ enum {
OP_RXTIMEVLAN = OP_RXTIMESTAMP | OP_RXVLAN,
OP_RSS_HASH = 0x65,
OP_TXINDEXLE = 0x68,
+ OP_MACSEC = 0x6c,
+ OP_PUTIDX = 0x70,
+};
+
+enum status_css {
+ CSS_TCPUDPCSOK = 1<<7, /* TCP / UDP checksum is ok */
+ CSS_ISUDP = 1<<6, /* packet is a UDP packet */
+ CSS_ISTCP = 1<<5, /* packet is a TCP packet */
+ CSS_ISIPFRAG = 1<<4, /* packet is a TCP/UDP frag, CS calc not done */
+ CSS_ISIPV6 = 1<<3, /* packet is a IPv6 packet */
+ CSS_IPV4CSUMOK = 1<<2, /* IP v4: TCP header checksum is ok */
+ CSS_ISIPV4 = 1<<1, /* packet is a IPv4 packet */
+ CSS_LINK_BIT = 1<<0, /* port number (legacy) */
};
/* Yukon 2 hardware interface */
@@ -1838,7 +1963,7 @@ struct sky2_rx_le {
struct sky2_status_le {
__le32 status; /* also checksum */
__le16 length; /* also vlan tag */
- u8 link;
+ u8 css;
u8 opcode;
} __attribute((packed));
@@ -1873,6 +1998,7 @@ struct sky2_port {
struct sky2_tx_le *tx_le;
u16 tx_cons; /* next le to check */
u16 tx_prod; /* next le to use */
+ u16 tx_next; /* debug only */
u32 tx_addr64;
u16 tx_pending;
u16 tx_last_mss;
@@ -1903,6 +2029,9 @@ struct sky2_port {
enum flow_control flow_mode;
enum flow_control flow_status;
+#ifdef CONFIG_SKY2_DEBUG
+ struct dentry *debugfs;
+#endif
struct net_device_stats net_stats;
};
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 111f23d0576..f8429449dc1 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -58,6 +58,8 @@
#elif defined(CONFIG_BFIN)
#define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH
+#define RPC_LSA_DEFAULT RPC_LED_100_10
+#define RPC_LSB_DEFAULT RPC_LED_TX_RX
# if defined (CONFIG_BFIN561_EZKIT)
#define SMC_CAN_USE_8BIT 0
@@ -281,17 +283,14 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#elif defined(CONFIG_SUPERH)
-#if defined(CONFIG_SH_7780_SOLUTION_ENGINE) || defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+#ifdef CONFIG_SOLUTION_ENGINE
#define SMC_CAN_USE_8BIT 0
#define SMC_CAN_USE_16BIT 1
#define SMC_CAN_USE_32BIT 0
#define SMC_IO_SHIFT 0
#define SMC_NOWAIT 1
-#define SMC_inb(a, r) (inw((a) + ((r)&~1)) >> (8*(r%2)))&0xff
#define SMC_inw(a, r) inw((a) + (r))
-#define SMC_outb(v, a, r) outw(((inw((a)+((r)&~1))*(0xff<<8*(r%2)))) | ((v)<<(8*(r&2)))), (a) + ((r)&~1))
-
#define SMC_outw(v, a, r) outw(v, (a) + (r))
#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c
new file mode 100644
index 00000000000..2cf6794acb4
--- /dev/null
+++ b/drivers/net/sni_82596.c
@@ -0,0 +1,185 @@
+/*
+ * sni_82596.c -- driver for intel 82596 ethernet controller, as
+ * used in older SNI RM machines
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+
+#define SNI_82596_DRIVER_VERSION "SNI RM 82596 driver - Revision: 0.01"
+
+static const char sni_82596_string[] = "snirm_82596";
+
+#define DMA_ALLOC dma_alloc_coherent
+#define DMA_FREE dma_free_coherent
+#define DMA_WBACK(priv, addr, len) do { } while (0)
+#define DMA_INV(priv, addr, len) do { } while (0)
+#define DMA_WBACK_INV(priv, addr, len) do { } while (0)
+
+#define SYSBUS 0x00004400
+
+/* big endian CPU, 82596 little endian */
+#define SWAP32(x) cpu_to_le32((u32)(x))
+#define SWAP16(x) cpu_to_le16((u16)(x))
+
+#define OPT_MPU_16BIT 0x01
+
+#include "lib82596.c"
+
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("i82596 driver");
+MODULE_LICENSE("GPL");
+module_param(i596_debug, int, 0);
+MODULE_PARM_DESC(i596_debug, "82596 debug mask");
+
+static inline void ca(struct net_device *dev)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ writel(0, lp->ca);
+}
+
+
+static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
+{
+ struct i596_private *lp = netdev_priv(dev);
+
+ u32 v = (u32) (c) | (u32) (x);
+
+ if (lp->options & OPT_MPU_16BIT) {
+ writew(v & 0xffff, lp->mpu_port);
+ wmb(); /* order writes to MPU port */
+ udelay(1);
+ writew(v >> 16, lp->mpu_port);
+ } else {
+ writel(v, lp->mpu_port);
+ wmb(); /* order writes to MPU port */
+ udelay(1);
+ writel(v, lp->mpu_port);
+ }
+}
+
+
+static int __devinit sni_82596_probe(struct platform_device *dev)
+{
+ struct net_device *netdevice;
+ struct i596_private *lp;
+ struct resource *res, *ca, *idprom, *options;
+ int retval = -ENOMEM;
+ void __iomem *mpu_addr;
+ void __iomem *ca_addr;
+ u8 __iomem *eth_addr;
+
+ res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ ca = platform_get_resource(dev, IORESOURCE_MEM, 1);
+ options = platform_get_resource(dev, 0, 0);
+ idprom = platform_get_resource(dev, IORESOURCE_MEM, 2);
+ if (!res || !ca || !options || !idprom)
+ return -ENODEV;
+ mpu_addr = ioremap_nocache(res->start, 4);
+ if (!mpu_addr)
+ return -ENOMEM;
+ ca_addr = ioremap_nocache(ca->start, 4);
+ if (!ca_addr)
+ goto probe_failed_free_mpu;
+
+ printk(KERN_INFO "Found i82596 at 0x%x\n", res->start);
+
+ netdevice = alloc_etherdev(sizeof(struct i596_private));
+ if (!netdevice)
+ goto probe_failed_free_ca;
+
+ SET_NETDEV_DEV(netdevice, &dev->dev);
+ platform_set_drvdata (dev, netdevice);
+
+ netdevice->base_addr = res->start;
+ netdevice->irq = platform_get_irq(dev, 0);
+
+ eth_addr = ioremap_nocache(idprom->start, 0x10);
+ if (!eth_addr)
+ goto probe_failed;
+
+ /* someone seems to like messed up stuff */
+ netdevice->dev_addr[0] = readb(eth_addr + 0x0b);
+ netdevice->dev_addr[1] = readb(eth_addr + 0x0a);
+ netdevice->dev_addr[2] = readb(eth_addr + 0x09);
+ netdevice->dev_addr[3] = readb(eth_addr + 0x08);
+ netdevice->dev_addr[4] = readb(eth_addr + 0x07);
+ netdevice->dev_addr[5] = readb(eth_addr + 0x06);
+ iounmap(eth_addr);
+
+ if (!netdevice->irq) {
+ printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
+ __FILE__, netdevice->base_addr);
+ goto probe_failed;
+ }
+
+ lp = netdev_priv(netdevice);
+ lp->options = options->flags & IORESOURCE_BITS;
+ lp->ca = ca_addr;
+ lp->mpu_port = mpu_addr;
+
+ retval = i82596_probe(netdevice);
+ if (retval == 0)
+ return 0;
+
+probe_failed:
+ free_netdev(netdevice);
+probe_failed_free_ca:
+ iounmap(ca_addr);
+probe_failed_free_mpu:
+ iounmap(mpu_addr);
+ return retval;
+}
+
+static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct i596_private *lp = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ DMA_FREE(dev->dev.parent, sizeof(struct i596_private),
+ lp->dma, lp->dma_addr);
+ iounmap(lp->ca);
+ iounmap(lp->mpu_port);
+ free_netdev (dev);
+ return 0;
+}
+
+static struct platform_driver sni_82596_driver = {
+ .probe = sni_82596_probe,
+ .remove = __devexit_p(sni_82596_driver_remove),
+ .driver = {
+ .name = sni_82596_string,
+ },
+};
+
+static int __devinit sni_82596_init(void)
+{
+ printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
+ return platform_driver_register(&sni_82596_driver);
+}
+
+
+static void __exit sni_82596_exit(void)
+{
+ platform_driver_unregister(&sni_82596_driver);
+}
+
+module_init(sni_82596_init);
+module_exit(sni_82596_exit);
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index ef84d7c757a..590b12c7246 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -434,7 +434,8 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
bufsize + SPIDER_NET_RXBUF_ALIGN - 1);
if (!descr->skb) {
if (netif_msg_rx_err(card) && net_ratelimit())
- pr_err("Not enough memory to allocate rx buffer\n");
+ dev_err(&card->netdev->dev,
+ "Not enough memory to allocate rx buffer\n");
card->spider_stats.alloc_rx_skb_error++;
return -ENOMEM;
}
@@ -455,18 +456,14 @@ spider_net_prepare_rx_descr(struct spider_net_card *card,
dev_kfree_skb_any(descr->skb);
descr->skb = NULL;
if (netif_msg_rx_err(card) && net_ratelimit())
- pr_err("Could not iommu-map rx buffer\n");
+ dev_err(&card->netdev->dev, "Could not iommu-map rx buffer\n");
card->spider_stats.rx_iommu_map_error++;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
} else {
hwdescr->buf_addr = buf;
- hwdescr->next_descr_addr = 0;
wmb();
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_CARDOWNED |
SPIDER_NET_DMAC_NOINTR_COMPLETE;
-
- wmb();
- descr->prev->hwdescr->next_descr_addr = descr->bus_addr;
}
return 0;
@@ -504,6 +501,20 @@ spider_net_enable_rxdmac(struct spider_net_card *card)
}
/**
+ * spider_net_disable_rxdmac - disables the receive DMA controller
+ * @card: card structure
+ *
+ * spider_net_disable_rxdmac terminates processing on the DMA controller
+ * by turing off the DMA controller, with the force-end flag set.
+ */
+static inline void
+spider_net_disable_rxdmac(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
+ SPIDER_NET_DMA_RX_FEND_VALUE);
+}
+
+/**
* spider_net_refill_rx_chain - refills descriptors/skbs in the rx chains
* @card: card structure
*
@@ -541,12 +552,16 @@ spider_net_refill_rx_chain(struct spider_net_card *card)
static int
spider_net_alloc_rx_skbs(struct spider_net_card *card)
{
- int result;
- struct spider_net_descr_chain *chain;
+ struct spider_net_descr_chain *chain = &card->rx_chain;
+ struct spider_net_descr *start = chain->tail;
+ struct spider_net_descr *descr = start;
- result = -ENOMEM;
+ /* Link up the hardware chain pointers */
+ do {
+ descr->prev->hwdescr->next_descr_addr = descr->bus_addr;
+ descr = descr->next;
+ } while (descr != start);
- chain = &card->rx_chain;
/* Put at least one buffer into the chain. if this fails,
* we've got a problem. If not, spider_net_refill_rx_chain
* will do the rest at the end of this function. */
@@ -563,7 +578,7 @@ spider_net_alloc_rx_skbs(struct spider_net_card *card)
error:
spider_net_free_rx_chain_contents(card);
- return result;
+ return -ENOMEM;
}
/**
@@ -655,20 +670,6 @@ write_hash:
}
/**
- * spider_net_disable_rxdmac - disables the receive DMA controller
- * @card: card structure
- *
- * spider_net_disable_rxdmac terminates processing on the DMA controller by
- * turing off DMA and issueing a force end
- */
-static void
-spider_net_disable_rxdmac(struct spider_net_card *card)
-{
- spider_net_write_reg(card, SPIDER_NET_GDADMACCNTR,
- SPIDER_NET_DMA_RX_FEND_VALUE);
-}
-
-/**
* spider_net_prepare_tx_descr - fill tx descriptor with skb data
* @card: card structure
* @descr: descriptor structure to fill out
@@ -692,7 +693,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(buf)) {
if (netif_msg_tx_err(card) && net_ratelimit())
- pr_err("could not iommu-map packet (%p, %i). "
+ dev_err(&card->netdev->dev, "could not iommu-map packet (%p, %i). "
"Dropping packet\n", skb->data, skb->len);
card->spider_stats.tx_iommu_map_error++;
return -ENOMEM;
@@ -715,10 +716,10 @@ spider_net_prepare_tx_descr(struct spider_net_card *card,
hwdescr->data_status = 0;
hwdescr->dmac_cmd_status =
- SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+ SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_TXFRMTL;
spin_unlock_irqrestore(&chain->lock, flags);
- if (skb->protocol == htons(ETH_P_IP) && skb->ip_summed == CHECKSUM_PARTIAL)
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
switch (ip_hdr(skb)->protocol) {
case IPPROTO_TCP:
hwdescr->dmac_cmd_status |= SPIDER_NET_DMAC_TCP;
@@ -832,9 +833,8 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
case SPIDER_NET_DESCR_PROTECTION_ERROR:
case SPIDER_NET_DESCR_FORCE_END:
if (netif_msg_tx_err(card))
- pr_err("%s: forcing end of tx descriptor "
- "with status x%02x\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev, "forcing end of tx descriptor "
+ "with status x%02x\n", status);
card->netdev_stats.tx_errors++;
break;
@@ -1022,34 +1022,154 @@ spider_net_pass_skb_up(struct spider_net_descr *descr,
netif_receive_skb(skb);
}
-#ifdef DEBUG
static void show_rx_chain(struct spider_net_card *card)
{
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *start= chain->tail;
struct spider_net_descr *descr= start;
+ struct spider_net_hw_descr *hwd = start->hwdescr;
+ struct device *dev = &card->netdev->dev;
+ u32 curr_desc, next_desc;
int status;
+ int tot = 0;
int cnt = 0;
- int cstat = spider_net_get_descr_status(descr);
- printk(KERN_INFO "RX chain tail at descr=%ld\n",
- (start - card->descr) - card->tx_chain.num_desc);
+ int off = start - chain->ring;
+ int cstat = hwd->dmac_cmd_status;
+
+ dev_info(dev, "Total number of descrs=%d\n",
+ chain->num_desc);
+ dev_info(dev, "Chain tail located at descr=%d, status=0x%x\n",
+ off, cstat);
+
+ curr_desc = spider_net_read_reg(card, SPIDER_NET_GDACTDPA);
+ next_desc = spider_net_read_reg(card, SPIDER_NET_GDACNEXTDA);
+
status = cstat;
do
{
- status = spider_net_get_descr_status(descr);
+ hwd = descr->hwdescr;
+ off = descr - chain->ring;
+ status = hwd->dmac_cmd_status;
+
+ if (descr == chain->head)
+ dev_info(dev, "Chain head is at %d, head status=0x%x\n",
+ off, status);
+
+ if (curr_desc == descr->bus_addr)
+ dev_info(dev, "HW curr desc (GDACTDPA) is at %d, status=0x%x\n",
+ off, status);
+
+ if (next_desc == descr->bus_addr)
+ dev_info(dev, "HW next desc (GDACNEXTDA) is at %d, status=0x%x\n",
+ off, status);
+
+ if (hwd->next_descr_addr == 0)
+ dev_info(dev, "chain is cut at %d\n", off);
+
if (cstat != status) {
- printk(KERN_INFO "Have %d descrs with stat=x%08x\n", cnt, cstat);
+ int from = (chain->num_desc + off - cnt) % chain->num_desc;
+ int to = (chain->num_desc + off - 1) % chain->num_desc;
+ dev_info(dev, "Have %d (from %d to %d) descrs "
+ "with stat=0x%08x\n", cnt, from, to, cstat);
cstat = status;
cnt = 0;
}
+
cnt ++;
+ tot ++;
+ descr = descr->next;
+ } while (descr != start);
+
+ dev_info(dev, "Last %d descrs with stat=0x%08x "
+ "for a total of %d descrs\n", cnt, cstat, tot);
+
+#ifdef DEBUG
+ /* Now dump the whole ring */
+ descr = start;
+ do
+ {
+ struct spider_net_hw_descr *hwd = descr->hwdescr;
+ status = spider_net_get_descr_status(hwd);
+ cnt = descr - chain->ring;
+ dev_info(dev, "Descr %d stat=0x%08x skb=%p\n",
+ cnt, status, descr->skb);
+ dev_info(dev, "bus addr=%08x buf addr=%08x sz=%d\n",
+ descr->bus_addr, hwd->buf_addr, hwd->buf_size);
+ dev_info(dev, "next=%08x result sz=%d valid sz=%d\n",
+ hwd->next_descr_addr, hwd->result_size,
+ hwd->valid_size);
+ dev_info(dev, "dmac=%08x data stat=%08x data err=%08x\n",
+ hwd->dmac_cmd_status, hwd->data_status,
+ hwd->data_error);
+ dev_info(dev, "\n");
+
descr = descr->next;
} while (descr != start);
- printk(KERN_INFO "Last %d descrs with stat=x%08x\n", cnt, cstat);
-}
#endif
+}
+
+/**
+ * spider_net_resync_head_ptr - Advance head ptr past empty descrs
+ *
+ * If the driver fails to keep up and empty the queue, then the
+ * hardware wil run out of room to put incoming packets. This
+ * will cause the hardware to skip descrs that are full (instead
+ * of halting/retrying). Thus, once the driver runs, it wil need
+ * to "catch up" to where the hardware chain pointer is at.
+ */
+static void spider_net_resync_head_ptr(struct spider_net_card *card)
+{
+ unsigned long flags;
+ struct spider_net_descr_chain *chain = &card->rx_chain;
+ struct spider_net_descr *descr;
+ int i, status;
+
+ /* Advance head pointer past any empty descrs */
+ descr = chain->head;
+ status = spider_net_get_descr_status(descr->hwdescr);
+
+ if (status == SPIDER_NET_DESCR_NOT_IN_USE)
+ return;
+
+ spin_lock_irqsave(&chain->lock, flags);
+
+ descr = chain->head;
+ status = spider_net_get_descr_status(descr->hwdescr);
+ for (i=0; i<chain->num_desc; i++) {
+ if (status != SPIDER_NET_DESCR_CARDOWNED) break;
+ descr = descr->next;
+ status = spider_net_get_descr_status(descr->hwdescr);
+ }
+ chain->head = descr;
+
+ spin_unlock_irqrestore(&chain->lock, flags);
+}
+
+static int spider_net_resync_tail_ptr(struct spider_net_card *card)
+{
+ struct spider_net_descr_chain *chain = &card->rx_chain;
+ struct spider_net_descr *descr;
+ int i, status;
+
+ /* Advance tail pointer past any empty and reaped descrs */
+ descr = chain->tail;
+ status = spider_net_get_descr_status(descr->hwdescr);
+
+ for (i=0; i<chain->num_desc; i++) {
+ if ((status != SPIDER_NET_DESCR_CARDOWNED) &&
+ (status != SPIDER_NET_DESCR_NOT_IN_USE)) break;
+ descr = descr->next;
+ status = spider_net_get_descr_status(descr->hwdescr);
+ }
+ chain->tail = descr;
+
+ if ((i == chain->num_desc) || (i == 0))
+ return 1;
+ return 0;
+}
+
/**
* spider_net_decode_one_descr - processes an RX descriptor
* @card: card structure
@@ -1067,6 +1187,7 @@ spider_net_decode_one_descr(struct spider_net_card *card)
struct spider_net_descr_chain *chain = &card->rx_chain;
struct spider_net_descr *descr = chain->tail;
struct spider_net_hw_descr *hwdescr = descr->hwdescr;
+ u32 hw_buf_addr;
int status;
status = spider_net_get_descr_status(hwdescr);
@@ -1080,15 +1201,17 @@ spider_net_decode_one_descr(struct spider_net_card *card)
chain->tail = descr->next;
/* unmap descriptor */
- pci_unmap_single(card->pdev, hwdescr->buf_addr,
+ hw_buf_addr = hwdescr->buf_addr;
+ hwdescr->buf_addr = 0xffffffff;
+ pci_unmap_single(card->pdev, hw_buf_addr,
SPIDER_NET_MAX_FRAME, PCI_DMA_FROMDEVICE);
if ( (status == SPIDER_NET_DESCR_RESPONSE_ERROR) ||
(status == SPIDER_NET_DESCR_PROTECTION_ERROR) ||
(status == SPIDER_NET_DESCR_FORCE_END) ) {
if (netif_msg_rx_err(card))
- pr_err("%s: dropping RX descriptor with state %d\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev,
+ "dropping RX descriptor with state %d\n", status);
card->netdev_stats.rx_dropped++;
goto bad_desc;
}
@@ -1096,8 +1219,8 @@ spider_net_decode_one_descr(struct spider_net_card *card)
if ( (status != SPIDER_NET_DESCR_COMPLETE) &&
(status != SPIDER_NET_DESCR_FRAME_END) ) {
if (netif_msg_rx_err(card))
- pr_err("%s: RX descriptor with unknown state %d\n",
- card->netdev->name, status);
+ dev_err(&card->netdev->dev,
+ "RX descriptor with unknown state %d\n", status);
card->spider_stats.rx_desc_unk_state++;
goto bad_desc;
}
@@ -1105,18 +1228,17 @@ spider_net_decode_one_descr(struct spider_net_card *card)
/* The cases we'll throw away the packet immediately */
if (hwdescr->data_error & SPIDER_NET_DESTROY_RX_FLAGS) {
if (netif_msg_rx_err(card))
- pr_err("%s: error in received descriptor found, "
+ dev_err(&card->netdev->dev,
+ "error in received descriptor found, "
"data_status=x%08x, data_error=x%08x\n",
- card->netdev->name,
hwdescr->data_status, hwdescr->data_error);
goto bad_desc;
}
- if (hwdescr->dmac_cmd_status & 0xfefe) {
- pr_err("%s: bad status, cmd_status=x%08x\n",
- card->netdev->name,
+ if (hwdescr->dmac_cmd_status & SPIDER_NET_DESCR_BAD_STATUS) {
+ dev_err(&card->netdev->dev, "bad status, cmd_status=x%08x\n",
hwdescr->dmac_cmd_status);
- pr_err("buf_addr=x%08x\n", hwdescr->buf_addr);
+ pr_err("buf_addr=x%08x\n", hw_buf_addr);
pr_err("buf_size=x%08x\n", hwdescr->buf_size);
pr_err("next_descr_addr=x%08x\n", hwdescr->next_descr_addr);
pr_err("result_size=x%08x\n", hwdescr->result_size);
@@ -1131,10 +1253,13 @@ spider_net_decode_one_descr(struct spider_net_card *card)
/* Ok, we've got a packet in descr */
spider_net_pass_skb_up(descr, card);
+ descr->skb = NULL;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
return 1;
bad_desc:
+ if (netif_msg_rx_err(card))
+ show_rx_chain(card);
dev_kfree_skb_irq(descr->skb);
descr->skb = NULL;
hwdescr->dmac_cmd_status = SPIDER_NET_DESCR_NOT_IN_USE;
@@ -1160,7 +1285,6 @@ spider_net_poll(struct net_device *netdev, int *budget)
int packets_to_do, packets_done = 0;
int no_more_packets = 0;
- spider_net_cleanup_tx_ring(card);
packets_to_do = min(*budget, netdev->quota);
while (packets_to_do) {
@@ -1174,16 +1298,25 @@ spider_net_poll(struct net_device *netdev, int *budget)
}
}
+ if ((packets_done == 0) && (card->num_rx_ints != 0)) {
+ no_more_packets = spider_net_resync_tail_ptr(card);
+ spider_net_resync_head_ptr(card);
+ }
+ card->num_rx_ints = 0;
+
netdev->quota -= packets_done;
*budget -= packets_done;
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
+ spider_net_cleanup_tx_ring(card);
+
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
if (no_more_packets) {
netif_rx_complete(netdev);
spider_net_rx_irq_on(card);
+ card->ignore_rx_ramfull = 0;
return 0;
}
@@ -1191,43 +1324,6 @@ spider_net_poll(struct net_device *netdev, int *budget)
}
/**
- * spider_net_vlan_rx_reg - initializes VLAN structures in the driver and card
- * @netdev: interface device structure
- * @grp: vlan_group structure that is registered (NULL on destroying interface)
- */
-static void
-spider_net_vlan_rx_reg(struct net_device *netdev, struct vlan_group *grp)
-{
- /* further enhancement... yet to do */
- return;
-}
-
-/**
- * spider_net_vlan_rx_add - adds VLAN id to the card filter
- * @netdev: interface device structure
- * @vid: VLAN id to add
- */
-static void
-spider_net_vlan_rx_add(struct net_device *netdev, uint16_t vid)
-{
- /* further enhancement... yet to do */
- /* add vid to card's VLAN filter table */
- return;
-}
-
-/**
- * spider_net_vlan_rx_kill - removes VLAN id to the card filter
- * @netdev: interface device structure
- * @vid: VLAN id to remove
- */
-static void
-spider_net_vlan_rx_kill(struct net_device *netdev, uint16_t vid)
-{
- /* further enhancement... yet to do */
- /* remove vid from card's VLAN filter table */
-}
-
-/**
* spider_net_get_stats - get interface statistics
* @netdev: interface device structure
*
@@ -1345,11 +1441,17 @@ static void
spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
{
u32 error_reg1, error_reg2;
+ u32 mask_reg1, mask_reg2;
u32 i;
int show_error = 1;
error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS);
error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS);
+ mask_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1MSK);
+ mask_reg2 = spider_net_read_reg(card,SPIDER_NET_GHIINT2MSK);
+
+ error_reg1 &= mask_reg1;
+ error_reg2 &= mask_reg2;
/* check GHIINT0STS ************************************/
if (status_reg)
@@ -1384,7 +1486,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GPWFFINT:
/* PHY command queue full */
if (netif_msg_intr(card))
- pr_err("PHY write queue full\n");
+ dev_err(&card->netdev->dev, "PHY write queue full\n");
show_error = 0;
break;
@@ -1454,11 +1556,15 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GRFBFLLINT: /* fallthrough */
case SPIDER_NET_GRFAFLLINT: /* fallthrough */
case SPIDER_NET_GRMFLLINT:
- if (netif_msg_intr(card) && net_ratelimit())
- pr_err("Spider RX RAM full, incoming packets "
- "might be discarded!\n");
- spider_net_rx_irq_off(card);
- netif_rx_schedule(card->netdev);
+ /* Could happen when rx chain is full */
+ if (card->ignore_rx_ramfull == 0) {
+ card->ignore_rx_ramfull = 1;
+ spider_net_resync_head_ptr(card);
+ spider_net_refill_rx_chain(card);
+ spider_net_enable_rxdmac(card);
+ card->num_rx_ints ++;
+ netif_rx_schedule(card->netdev);
+ }
show_error = 0;
break;
@@ -1473,12 +1579,11 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GDCDCEINT: /* fallthrough */
case SPIDER_NET_GDBDCEINT: /* fallthrough */
case SPIDER_NET_GDADCEINT:
- if (netif_msg_intr(card) && net_ratelimit())
- pr_err("got descriptor chain end interrupt, "
- "restarting DMAC %c.\n",
- 'D'-(i-SPIDER_NET_GDDDCEINT)/3);
+ spider_net_resync_head_ptr(card);
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
+ card->num_rx_ints ++;
+ netif_rx_schedule(card->netdev);
show_error = 0;
break;
@@ -1487,9 +1592,12 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
case SPIDER_NET_GDCINVDINT: /* fallthrough */
case SPIDER_NET_GDBINVDINT: /* fallthrough */
case SPIDER_NET_GDAINVDINT:
- /* could happen when rx chain is full */
+ /* Could happen when rx chain is full */
+ spider_net_resync_head_ptr(card);
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
+ card->num_rx_ints ++;
+ netif_rx_schedule(card->netdev);
show_error = 0;
break;
@@ -1545,9 +1653,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
}
if ((show_error) && (netif_msg_intr(card)) && net_ratelimit())
- pr_err("Got error interrupt on %s, GHIINT0STS = 0x%08x, "
+ dev_err(&card->netdev->dev, "Error interrupt, GHIINT0STS = 0x%08x, "
"GHIINT1STS = 0x%08x, GHIINT2STS = 0x%08x\n",
- card->netdev->name,
status_reg, error_reg1, error_reg2);
/* clear interrupt sources */
@@ -1572,9 +1679,11 @@ spider_net_interrupt(int irq, void *ptr)
{
struct net_device *netdev = ptr;
struct spider_net_card *card = netdev_priv(netdev);
- u32 status_reg;
+ u32 status_reg, mask_reg;
status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS);
+ mask_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK);
+ status_reg &= mask_reg;
if (!status_reg)
return IRQ_NONE;
@@ -1582,6 +1691,7 @@ spider_net_interrupt(int irq, void *ptr)
if (status_reg & SPIDER_NET_RXINT ) {
spider_net_rx_irq_off(card);
netif_rx_schedule(netdev);
+ card->num_rx_ints ++;
}
if (status_reg & SPIDER_NET_TXINT)
netif_rx_schedule(netdev);
@@ -1615,6 +1725,38 @@ spider_net_poll_controller(struct net_device *netdev)
#endif /* CONFIG_NET_POLL_CONTROLLER */
/**
+ * spider_net_enable_interrupts - enable interrupts
+ * @card: card structure
+ *
+ * spider_net_enable_interrupt enables several interrupts
+ */
+static void
+spider_net_enable_interrupts(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
+ SPIDER_NET_INT0_MASK_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
+ SPIDER_NET_INT1_MASK_VALUE);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
+ SPIDER_NET_INT2_MASK_VALUE);
+}
+
+/**
+ * spider_net_disable_interrupts - disable interrupts
+ * @card: card structure
+ *
+ * spider_net_disable_interrupts disables all the interrupts
+ */
+static void
+spider_net_disable_interrupts(struct spider_net_card *card)
+{
+ spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
+ spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+}
+
+/**
* spider_net_init_card - initializes the card
* @card: card structure
*
@@ -1634,6 +1776,7 @@ spider_net_init_card(struct spider_net_card *card)
spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4);
+ spider_net_disable_interrupts(card);
}
/**
@@ -1721,14 +1864,6 @@ spider_net_enable_card(struct spider_net_card *card)
spider_net_write_reg(card, SPIDER_NET_GMACOPEMD,
SPIDER_NET_OPMODE_VALUE);
- /* set interrupt mask registers */
- spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK,
- SPIDER_NET_INT0_MASK_VALUE);
- spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK,
- SPIDER_NET_INT1_MASK_VALUE);
- spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK,
- SPIDER_NET_INT2_MASK_VALUE);
-
spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,
SPIDER_NET_GDTBSTA);
}
@@ -1811,7 +1946,8 @@ spider_net_init_firmware(struct spider_net_card *card)
SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
- pr_err("Incorrect size of spidernet firmware in " \
+ dev_err(&card->netdev->dev,
+ "Incorrect size of spidernet firmware in " \
"filesystem. Looking in host firmware...\n");
goto try_host_fw;
}
@@ -1835,8 +1971,8 @@ try_host_fw:
if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
- pr_err("Incorrect size of spidernet firmware in " \
- "host firmware\n");
+ dev_err(&card->netdev->dev,
+ "Incorrect size of spidernet firmware in host firmware\n");
goto done;
}
@@ -1846,7 +1982,8 @@ done:
return err;
out_err:
if (netif_msg_probe(card))
- pr_err("Couldn't find spidernet firmware in filesystem " \
+ dev_err(&card->netdev->dev,
+ "Couldn't find spidernet firmware in filesystem " \
"or host firmware\n");
return err;
}
@@ -1903,6 +2040,8 @@ spider_net_open(struct net_device *netdev)
netif_carrier_on(netdev);
netif_poll_enable(netdev);
+ spider_net_enable_interrupts(card);
+
return 0;
register_int_failed:
@@ -2075,11 +2214,7 @@ spider_net_stop(struct net_device *netdev)
del_timer_sync(&card->tx_timer);
del_timer_sync(&card->aneg_timer);
- /* disable/mask all interrupts */
- spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0);
- spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0);
- spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0);
- spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0);
+ spider_net_disable_interrupts(card);
free_irq(netdev->irq, netdev);
@@ -2177,9 +2312,6 @@ spider_net_setup_netdev_ops(struct net_device *netdev)
netdev->poll = &spider_net_poll;
netdev->weight = SPIDER_NET_NAPI_WEIGHT;
/* HW VLAN */
- netdev->vlan_rx_register = &spider_net_vlan_rx_reg;
- netdev->vlan_rx_add_vid = &spider_net_vlan_rx_add;
- netdev->vlan_rx_kill_vid = &spider_net_vlan_rx_kill;
#ifdef CONFIG_NET_POLL_CONTROLLER
/* poll controller */
netdev->poll_controller = &spider_net_poll_controller;
@@ -2225,11 +2357,13 @@ spider_net_setup_netdev(struct spider_net_card *card)
spider_net_setup_netdev_ops(netdev);
- netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
+ netdev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX;
/* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |
* NETIF_F_HW_VLAN_FILTER */
netdev->irq = card->pdev->irq;
+ card->num_rx_ints = 0;
+ card->ignore_rx_ramfull = 0;
dn = pci_device_to_OF_node(card->pdev);
if (!dn)
@@ -2242,13 +2376,14 @@ spider_net_setup_netdev(struct spider_net_card *card)
result = spider_net_set_mac(netdev, &addr);
if ((result) && (netif_msg_probe(card)))
- pr_err("Failed to set MAC address: %i\n", result);
+ dev_err(&card->netdev->dev,
+ "Failed to set MAC address: %i\n", result);
result = register_netdev(netdev);
if (result) {
if (netif_msg_probe(card))
- pr_err("Couldn't register net_device: %i\n",
- result);
+ dev_err(&card->netdev->dev,
+ "Couldn't register net_device: %i\n", result);
return result;
}
@@ -2326,17 +2461,19 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
unsigned long mmio_start, mmio_len;
if (pci_enable_device(pdev)) {
- pr_err("Couldn't enable PCI device\n");
+ dev_err(&pdev->dev, "Couldn't enable PCI device\n");
return NULL;
}
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
- pr_err("Couldn't find proper PCI device base address.\n");
+ dev_err(&pdev->dev,
+ "Couldn't find proper PCI device base address.\n");
goto out_disable_dev;
}
if (pci_request_regions(pdev, spider_net_driver_name)) {
- pr_err("Couldn't obtain PCI resources, aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't obtain PCI resources, aborting.\n");
goto out_disable_dev;
}
@@ -2344,8 +2481,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
card = spider_net_alloc_card();
if (!card) {
- pr_err("Couldn't allocate net_device structure, "
- "aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't allocate net_device structure, aborting.\n");
goto out_release_regions;
}
card->pdev = pdev;
@@ -2359,7 +2496,8 @@ spider_net_setup_pci_dev(struct pci_dev *pdev)
card->regs = ioremap(mmio_start, mmio_len);
if (!card->regs) {
- pr_err("Couldn't obtain PCI resources, aborting.\n");
+ dev_err(&pdev->dev,
+ "Couldn't obtain PCI resources, aborting.\n");
goto out_release_regions;
}
diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h
index 4a1e0d28a50..dbbdb8cee3c 100644
--- a/drivers/net/spider_net.h
+++ b/drivers/net/spider_net.h
@@ -25,7 +25,7 @@
#ifndef _SPIDER_NET_H
#define _SPIDER_NET_H
-#define VERSION "2.0 A"
+#define VERSION "2.0 B"
#include "sungem_phy.h"
@@ -222,6 +222,7 @@ extern char spider_net_driver_name[];
#define SPIDER_NET_GDTBSTA 0x00000300
#define SPIDER_NET_GDTDCEIDIS 0x00000002
#define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \
+ SPIDER_NET_GDTDCEIDIS | \
SPIDER_NET_GDTBSTA
#define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003
@@ -332,8 +333,7 @@ enum spider_net_int2_status {
SPIDER_NET_GRISPDNGINT
};
-#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GDTFDCINT) | \
- (1 << SPIDER_NET_GDTDCEINT) )
+#define SPIDER_NET_TXINT (1 << SPIDER_NET_GDTFDCINT)
/* We rely on flagged descriptor interrupts */
#define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) )
@@ -349,11 +349,23 @@ enum spider_net_int2_status {
#define SPIDER_NET_GPRDAT_MASK 0x0000ffff
#define SPIDER_NET_DMAC_NOINTR_COMPLETE 0x00800000
-#define SPIDER_NET_DMAC_NOCS 0x00040000
+#define SPIDER_NET_DMAC_TXFRMTL 0x00040000
#define SPIDER_NET_DMAC_TCP 0x00020000
#define SPIDER_NET_DMAC_UDP 0x00030000
#define SPIDER_NET_TXDCEST 0x08000000
+#define SPIDER_NET_DESCR_RXFDIS 0x00000001
+#define SPIDER_NET_DESCR_RXDCEIS 0x00000002
+#define SPIDER_NET_DESCR_RXDEN0IS 0x00000004
+#define SPIDER_NET_DESCR_RXINVDIS 0x00000008
+#define SPIDER_NET_DESCR_RXRERRIS 0x00000010
+#define SPIDER_NET_DESCR_RXFDCIMS 0x00000100
+#define SPIDER_NET_DESCR_RXDCEIMS 0x00000200
+#define SPIDER_NET_DESCR_RXDEN0IMS 0x00000400
+#define SPIDER_NET_DESCR_RXINVDIMS 0x00000800
+#define SPIDER_NET_DESCR_RXRERRMIS 0x00001000
+#define SPIDER_NET_DESCR_UNUSED 0x077fe0e0
+
#define SPIDER_NET_DESCR_IND_PROC_MASK 0xF0000000
#define SPIDER_NET_DESCR_COMPLETE 0x00000000 /* used in rx and tx */
#define SPIDER_NET_DESCR_RESPONSE_ERROR 0x10000000 /* used in rx and tx */
@@ -364,6 +376,13 @@ enum spider_net_int2_status {
#define SPIDER_NET_DESCR_NOT_IN_USE 0xF0000000
#define SPIDER_NET_DESCR_TXDESFLG 0x00800000
+#define SPIDER_NET_DESCR_BAD_STATUS (SPIDER_NET_DESCR_RXDEN0IS | \
+ SPIDER_NET_DESCR_RXRERRIS | \
+ SPIDER_NET_DESCR_RXDEN0IMS | \
+ SPIDER_NET_DESCR_RXINVDIMS | \
+ SPIDER_NET_DESCR_RXRERRMIS | \
+ SPIDER_NET_DESCR_UNUSED)
+
/* Descriptor, as defined by the hardware */
struct spider_net_hw_descr {
u32 buf_addr;
@@ -461,6 +480,8 @@ struct spider_net_card {
struct work_struct tx_timeout_task;
atomic_t tx_timeout_task_counter;
wait_queue_head_t waitq;
+ int num_rx_ints;
+ int ignore_rx_ramfull;
/* for ethtool */
int msg_enable;
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index 6bcf03fc89b..d940474e024 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -134,22 +134,6 @@ spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n)
return 0;
}
-static uint32_t
-spider_net_ethtool_get_tx_csum(struct net_device *netdev)
-{
- return (netdev->features & NETIF_F_HW_CSUM) != 0;
-}
-
-static int
-spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data)
-{
- if (data)
- netdev->features |= NETIF_F_HW_CSUM;
- else
- netdev->features &= ~NETIF_F_HW_CSUM;
-
- return 0;
-}
static void
spider_net_ethtool_get_ringparam(struct net_device *netdev,
@@ -200,11 +184,12 @@ const struct ethtool_ops spider_net_ethtool_ops = {
.get_wol = spider_net_ethtool_get_wol,
.get_msglevel = spider_net_ethtool_get_msglevel,
.set_msglevel = spider_net_ethtool_set_msglevel,
+ .get_link = ethtool_op_get_link,
.nway_reset = spider_net_ethtool_nway_reset,
.get_rx_csum = spider_net_ethtool_get_rx_csum,
.set_rx_csum = spider_net_ethtool_set_rx_csum,
- .get_tx_csum = spider_net_ethtool_get_tx_csum,
- .set_tx_csum = spider_net_ethtool_set_tx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
.get_ringparam = spider_net_ethtool_get_ringparam,
.get_strings = spider_net_get_strings,
.get_stats_count = spider_net_get_stats_count,
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 9d6e454a8f9..8b6478663a5 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -152,7 +152,7 @@ static int full_duplex[MAX_UNITS] = {0, };
* This SUCKS.
* We need a much better method to determine if dma_addr_t is 64-bit.
*/
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
/* 64-bit dma_addr_t */
#define ADDR_64BITS /* This chip uses 64 bit addresses. */
#define netdrv_addr_t u64
@@ -740,7 +740,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
pci_set_master(pdev);
/* enable MWI -- it vastly improves Rx performance on sparc64 */
- pci_set_mwi(pdev);
+ pci_try_set_mwi(pdev);
#ifdef ZEROCOPY
/* Starfire can do TCP/UDP checksumming */
@@ -1456,7 +1456,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
pci_dma_sync_single_for_cpu(np->pci_dev,
np->rx_info[entry].mapping,
pkt_len, PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb, np->rx_info[entry].skb->data, pkt_len);
pci_dma_sync_single_for_device(np->pci_dev,
np->rx_info[entry].mapping,
pkt_len, PCI_DMA_FROMDEVICE);
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
index a123ea87893..b77ab6e8fd3 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/sun3_82586.c
@@ -777,7 +777,7 @@ static void sun3_82586_rcv_int(struct net_device *dev)
{
skb_reserve(skb,2);
skb_put(skb,totlen);
- eth_copy_and_sum(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen,0);
+ skb_copy_to_linear_data(skb,(char *) p->base+swab32((unsigned long) rbd->buffer),totlen);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
p->stats.rx_packets++;
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 791e081fdc1..f1548c03332 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -853,10 +853,9 @@ static int lance_rx( struct net_device *dev )
skb_reserve( skb, 2 ); /* 16 byte align */
skb_put( skb, pkt_len ); /* Make room */
-// skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), pkt_len);
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
PKTBUF_ADDR(head),
- pkt_len, 0);
+ pkt_len);
skb->protocol = eth_type_trans( skb, dev );
netif_rx( skb );
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 2ad8d58dee3..b3e0158def4 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -860,7 +860,7 @@ static void bigmac_rx(struct bigmac *bp)
sbus_dma_sync_single_for_cpu(bp->bigmac_sdev,
this->rx_addr, len,
SBUS_DMA_FROMDEVICE);
- eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0);
+ skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len);
sbus_dma_sync_single_for_device(bp->bigmac_sdev,
this->rx_addr, len,
SBUS_DMA_FROMDEVICE);
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index e1f912d0404..af0c9831074 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -397,7 +397,6 @@ struct netdev_private {
unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */
struct pci_dev *pci_dev;
void __iomem *base;
- unsigned char pci_rev_id;
};
/* The station address location in the EEPROM. */
@@ -544,8 +543,6 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
dev->change_mtu = &change_mtu;
pci_set_drvdata(pdev, dev);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id);
-
i = register_netdev(dev);
if (i)
goto err_out_unmap_rx;
@@ -828,7 +825,7 @@ static int netdev_open(struct net_device *dev)
iowrite8(100, ioaddr + RxDMAPollPeriod);
iowrite8(127, ioaddr + TxDMAPollPeriod);
/* Fix DFE-580TX packet drop issue */
- if (np->pci_rev_id >= 0x14)
+ if (np->pci_dev->revision >= 0x14)
iowrite8(0x01, ioaddr + DebugCtrl1);
netif_start_queue(dev);
@@ -1194,7 +1191,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
hw_frame_id = ioread8(ioaddr + TxFrameId);
}
- if (np->pci_rev_id >= 0x14) {
+ if (np->pci_dev->revision >= 0x14) {
spin_lock(&np->lock);
for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
int entry = np->dirty_tx % TX_RING_SIZE;
@@ -1313,7 +1310,7 @@ static void rx_poll(unsigned long data)
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
pci_dma_sync_single_for_device(np->pci_dev,
desc->frag[0].addr,
np->rx_buf_sz,
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 51c3fe2108a..8b35f13318e 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2625,7 +2625,7 @@ static void quattro_sbus_free_irqs(void)
#endif /* CONFIG_SBUS */
#ifdef CONFIG_PCI
-static struct quattro * __init quattro_pci_find(struct pci_dev *pdev)
+static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
{
struct pci_dev *bdev = pdev->bus->self;
struct quattro *qp;
@@ -3095,12 +3095,8 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
#ifdef CONFIG_SPARC
hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff);
- if (hp->hm_revision == 0xff) {
- unsigned char prev;
-
- pci_read_config_byte(pdev, PCI_REVISION_ID, &prev);
- hp->hm_revision = 0xc0 | (prev & 0x0f);
- }
+ if (hp->hm_revision == 0xff)
+ hp->hm_revision = 0xc0 | (pdev->revision & 0x0f);
#else
/* works with this on non-sparc hosts */
hp->hm_revision = 0x20;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 42722530ab2..053b7cb0d94 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -549,9 +549,9 @@ static void lance_rx_dvma(struct net_device *dev)
skb_reserve(skb, 2); /* 16 byte align */
skb_put(skb, len); /* make room */
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
(unsigned char *)&(ib->rx_buf [entry][0]),
- len, 0);
+ len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index fa70e0b78af..1b65ae8a1c7 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -439,8 +439,8 @@ static void qe_rx(struct sunqe *qep)
} else {
skb_reserve(skb, 2);
skb_put(skb, len);
- eth_copy_and_sum(skb, (unsigned char *) this_qbuf,
- len, 0);
+ skb_copy_to_linear_data(skb, (unsigned char *) this_qbuf,
+ len);
skb->protocol = eth_type_trans(skb, qep->dev);
netif_rx(skb);
qep->dev->last_rx = jiffies;
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index 463d600ed83..75655add3f3 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -23,9 +23,9 @@
*/
#ifdef TC35815_NAPI
-#define DRV_VERSION "1.35-NAPI"
+#define DRV_VERSION "1.36-NAPI"
#else
-#define DRV_VERSION "1.35"
+#define DRV_VERSION "1.36"
#endif
static const char *version = "tc35815.c:v" DRV_VERSION "\n";
#define MODNAME "tc35815"
@@ -49,6 +49,7 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
#include <linux/pci.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
+#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/byteorder.h>
@@ -597,13 +598,46 @@ static int tc_mdio_read(struct net_device *dev, int phy_id, int location);
static void tc_mdio_write(struct net_device *dev, int phy_id, int location,
int val);
-static void __devinit tc35815_init_dev_addr (struct net_device *dev)
+#ifdef CONFIG_CPU_TX49XX
+/*
+ * Find a platform_device providing a MAC address. The platform code
+ * 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)
+{
+ struct platform_device *plat_dev = to_platform_device(dev);
+ struct pci_dev *pci_dev = data;
+ unsigned int id = (pci_dev->bus->number << 8) | pci_dev->devfn;
+ return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
+}
+
+static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+{
+ struct tc35815_local *lp = dev->priv;
+ struct device *pd = bus_find_device(&platform_bus_type, NULL,
+ lp->pci_dev, tc35815_mac_match);
+ if (pd) {
+ if (pd->platform_data)
+ memcpy(dev->dev_addr, pd->platform_data, ETH_ALEN);
+ put_device(pd);
+ return is_valid_ether_addr(dev->dev_addr) ? 0 : -ENODEV;
+ }
+ return -ENODEV;
+}
+#else
+static int __devinit tc35815_read_plat_dev_addr(struct device *dev)
+{
+ return -ENODEV;
+}
+#endif
+
+static int __devinit tc35815_init_dev_addr (struct net_device *dev)
{
struct tc35815_regs __iomem *tr =
(struct tc35815_regs __iomem *)dev->base_addr;
int i;
- /* dev_addr will be overwritten on NETDEV_REGISTER event */
while (tc_readl(&tr->PROM_Ctl) & PROM_Busy)
;
for (i = 0; i < 6; i += 2) {
@@ -615,6 +649,9 @@ static void __devinit tc35815_init_dev_addr (struct net_device *dev)
dev->dev_addr[i] = data & 0xff;
dev->dev_addr[i+1] = data >> 8;
}
+ if (!is_valid_ether_addr(dev->dev_addr))
+ return tc35815_read_plat_dev_addr(dev);
+ return 0;
}
static int __devinit tc35815_init_one (struct pci_dev *pdev,
@@ -724,7 +761,10 @@ static int __devinit tc35815_init_one (struct pci_dev *pdev,
tc35815_chip_reset(dev);
/* Retrieve the ethernet address. */
- tc35815_init_dev_addr(dev);
+ if (tc35815_init_dev_addr(dev)) {
+ dev_warn(&pdev->dev, "not valid ether addr\n");
+ random_ether_addr(dev->dev_addr);
+ }
rc = register_netdev (dev);
if (rc)
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 923b9c725cc..5ee14764fd7 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.76"
-#define DRV_MODULE_RELDATE "May 5, 2007"
+#define DRV_MODULE_VERSION "3.78"
+#define DRV_MODULE_RELDATE "July 11, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -721,6 +721,44 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
return ret;
}
+static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
+{
+ u32 phy;
+
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+ (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
+ return;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
+ u32 ephy;
+
+ if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &ephy)) {
+ tg3_writephy(tp, MII_TG3_EPHY_TEST,
+ ephy | MII_TG3_EPHY_SHADOW_EN);
+ if (!tg3_readphy(tp, MII_TG3_EPHYTST_MISCCTRL, &phy)) {
+ if (enable)
+ phy |= MII_TG3_EPHYTST_MISCCTRL_MDIX;
+ else
+ phy &= ~MII_TG3_EPHYTST_MISCCTRL_MDIX;
+ tg3_writephy(tp, MII_TG3_EPHYTST_MISCCTRL, phy);
+ }
+ tg3_writephy(tp, MII_TG3_EPHY_TEST, ephy);
+ }
+ } else {
+ phy = MII_TG3_AUXCTL_MISC_RDSEL_MISC |
+ MII_TG3_AUXCTL_SHDWSEL_MISC;
+ if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, phy) &&
+ !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy)) {
+ if (enable)
+ phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+ else
+ phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
+ phy |= MII_TG3_AUXCTL_MISC_WREN;
+ tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
+ }
+ }
+}
+
static void tg3_phy_set_wirespeed(struct tg3 *tp)
{
u32 val;
@@ -1045,23 +1083,11 @@ out:
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u32 phy_reg;
-
/* adjust output voltage */
tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x12);
-
- if (!tg3_readphy(tp, MII_TG3_EPHY_TEST, &phy_reg)) {
- u32 phy_reg2;
-
- tg3_writephy(tp, MII_TG3_EPHY_TEST,
- phy_reg | MII_TG3_EPHY_SHADOW_EN);
- /* Enable auto-MDIX */
- if (!tg3_readphy(tp, 0x10, &phy_reg2))
- tg3_writephy(tp, 0x10, phy_reg2 | 0x4000);
- tg3_writephy(tp, MII_TG3_EPHY_TEST, phy_reg);
- }
}
+ tg3_phy_toggle_automdix(tp, 1);
tg3_phy_set_wirespeed(tp);
return 0;
}
@@ -1162,6 +1188,19 @@ static void tg3_frob_aux_power(struct tg3 *tp)
}
}
+static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
+{
+ if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
+ return 1;
+ else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411) {
+ if (speed != SPEED_10)
+ return 1;
+ } else if (speed == SPEED_10)
+ return 1;
+
+ return 0;
+}
+
static int tg3_setup_phy(struct tg3 *, int);
#define RESET_KIND_SHUTDOWN 0
@@ -1320,9 +1359,17 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
else
mac_mode = MAC_MODE_PORT_MODE_MII;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 ||
- !(tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB))
- mac_mode |= MAC_MODE_LINK_POLARITY;
+ mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5700) {
+ u32 speed = (tp->tg3_flags &
+ TG3_FLAG_WOL_SPEED_100MB) ?
+ SPEED_100 : SPEED_10;
+ if (tg3_5700_link_polarity(tp, speed))
+ mac_mode |= MAC_MODE_LINK_POLARITY;
+ else
+ mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ }
} else {
mac_mode = MAC_MODE_PORT_MODE_TBI;
}
@@ -1990,15 +2037,12 @@ relink:
if (tp->link_config.active_duplex == DUPLEX_HALF)
tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
- tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
- if ((tp->led_ctrl == LED_CTRL_MODE_PHY_2) ||
- (current_link_up == 1 &&
- tp->link_config.active_speed == SPEED_10))
- tp->mac_mode |= MAC_MODE_LINK_POLARITY;
- } else {
- if (current_link_up == 1)
+ if (current_link_up == 1 &&
+ tg3_5700_link_polarity(tp, tp->link_config.active_speed))
tp->mac_mode |= MAC_MODE_LINK_POLARITY;
+ else
+ tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
}
/* ??? Without this setting Netgear GA302T PHY does not
@@ -2639,6 +2683,9 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
udelay(40);
+
+ tw32_f(MAC_MODE, tp->mac_mode);
+ udelay(40);
}
out:
@@ -2698,10 +2745,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
else
current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
- tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
- tw32_f(MAC_MODE, tp->mac_mode);
- udelay(40);
-
tp->hw_status->status =
(SD_STATUS_UPDATED |
(tp->hw_status->status & ~SD_STATUS_LINK_CHG));
@@ -3512,9 +3555,9 @@ static inline int tg3_irq_sync(struct tg3 *tp)
*/
static inline void tg3_full_lock(struct tg3 *tp, int irq_sync)
{
+ spin_lock_bh(&tp->lock);
if (irq_sync)
tg3_irq_quiesce(tp);
- spin_lock_bh(&tp->lock);
}
static inline void tg3_full_unlock(struct tg3 *tp)
@@ -6444,6 +6487,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+ !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
+ tp->mac_mode |= MAC_MODE_LINK_POLARITY;
tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
udelay(40);
@@ -8271,7 +8318,7 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
- ethtool_op_set_tx_hw_csum(dev, data);
+ ethtool_op_set_tx_ipv6_csum(dev, data);
else
ethtool_op_set_tx_csum(dev, data);
@@ -8805,7 +8852,9 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
return 0;
mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
- MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY;
+ MAC_MODE_PORT_INT_LPBACK;
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+ mac_mode |= MAC_MODE_LINK_POLARITY;
if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
mac_mode |= MAC_MODE_PORT_MODE_MII;
else
@@ -8824,19 +8873,18 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
phytest | MII_TG3_EPHY_SHADOW_EN);
if (!tg3_readphy(tp, 0x1b, &phy))
tg3_writephy(tp, 0x1b, phy & ~0x20);
- if (!tg3_readphy(tp, 0x10, &phy))
- tg3_writephy(tp, 0x10, phy & ~0x4000);
tg3_writephy(tp, MII_TG3_EPHY_TEST, phytest);
}
val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED100;
} else
val = BMCR_LOOPBACK | BMCR_FULLDPLX | BMCR_SPEED1000;
+ tg3_phy_toggle_automdix(tp, 0);
+
tg3_writephy(tp, MII_BMCR, val);
udelay(40);
- mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
- MAC_MODE_LINK_POLARITY;
+ mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
tg3_writephy(tp, MII_TG3_EPHY_PTEST, 0x1800);
mac_mode |= MAC_MODE_PORT_MODE_MII;
@@ -8849,8 +8897,11 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
udelay(10);
tw32_f(MAC_RX_MODE, tp->rx_mode);
}
- if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
- mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
+ if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+ mac_mode &= ~MAC_MODE_LINK_POLARITY;
+ else if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411)
+ mac_mode |= MAC_MODE_LINK_POLARITY;
tg3_writephy(tp, MII_TG3_EXT_CTRL,
MII_TG3_EXT_CTRL_LNK3_LED_MODE);
}
@@ -9116,25 +9167,10 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
/* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
__tg3_set_rx_mode(dev);
- tg3_full_unlock(tp);
-
if (netif_running(dev))
tg3_netif_start(tp);
-}
-
-static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct tg3 *tp = netdev_priv(dev);
-
- if (netif_running(dev))
- tg3_netif_stop(tp);
- tg3_full_lock(tp, 0);
- vlan_group_set_device(tp->vlgrp, vid, NULL);
tg3_full_unlock(tp);
-
- if (netif_running(dev))
- tg3_netif_start(tp);
}
#endif
@@ -9425,11 +9461,13 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
case FLASH_5755VENDOR_ATMEL_FLASH_1:
case FLASH_5755VENDOR_ATMEL_FLASH_2:
case FLASH_5755VENDOR_ATMEL_FLASH_3:
+ case FLASH_5755VENDOR_ATMEL_FLASH_5:
tp->nvram_jedecnum = JEDEC_ATMEL;
tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
tp->tg3_flags2 |= TG3_FLG2_FLASH;
tp->nvram_pagesize = 264;
- if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1)
+ if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_1 ||
+ nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_5)
tp->nvram_size = (protect ? 0x3e200 : 0x80000);
else if (nvcfg1 == FLASH_5755VENDOR_ATMEL_FLASH_2)
tp->nvram_size = (protect ? 0x1f200 : 0x40000);
@@ -10513,11 +10551,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
continue;
}
if (pci_id->rev != PCI_ANY_ID) {
- u8 rev;
-
- pci_read_config_byte(bridge, PCI_REVISION_ID,
- &rev);
- if (rev > pci_id->rev)
+ if (bridge->revision > pci_id->rev)
continue;
}
if (bridge->subordinate &&
@@ -10976,6 +11010,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
* upon subsystem IDs.
*/
if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
TG3_FLAG_USE_LINKCHG_REG);
@@ -11778,7 +11813,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
#if TG3_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
dev->vlan_rx_register = tg3_vlan_rx_register;
- dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid;
#endif
tp = netdev_priv(dev);
@@ -11959,12 +11993,11 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
* checksumming.
*/
if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
- dev->features |= NETIF_F_HW_CSUM;
- else
- dev->features |= NETIF_F_IP_CSUM;
- dev->features |= NETIF_F_SG;
+ dev->features |= NETIF_F_IPV6_CSUM;
+
tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
} else
tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index bd9f4f428e5..d84e75e7365 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1467,6 +1467,7 @@
#define FLASH_5755VENDOR_ATMEL_FLASH_2 0x03400002
#define FLASH_5755VENDOR_ATMEL_FLASH_3 0x03400000
#define FLASH_5755VENDOR_ATMEL_FLASH_4 0x00000003
+#define FLASH_5755VENDOR_ATMEL_FLASH_5 0x02000003
#define FLASH_5755VENDOR_ATMEL_EEPROM_64KHZ 0x03c00003
#define FLASH_5755VENDOR_ATMEL_EEPROM_376KHZ 0x03c00002
#define FLASH_5787VENDOR_ATMEL_EEPROM_64KHZ 0x03000003
@@ -1642,6 +1643,11 @@
#define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */
+#define MII_TG3_AUXCTL_MISC_WREN 0x8000
+#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200
+#define MII_TG3_AUXCTL_MISC_RDSEL_MISC 0x7000
+#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007
+
#define MII_TG3_AUX_STAT 0x19 /* auxilliary status register */
#define MII_TG3_AUX_STAT_LPASS 0x0004
#define MII_TG3_AUX_STAT_SPDMASK 0x0700
@@ -1667,6 +1673,9 @@
#define MII_TG3_EPHY_TEST 0x1f /* 5906 PHY register */
#define MII_TG3_EPHY_SHADOW_EN 0x80
+#define MII_TG3_EPHYTST_MISCCTRL 0x10 /* 5906 EPHY misc ctrl shadow register */
+#define MII_TG3_EPHYTST_MISCCTRL_MDIX 0x4000
+
#define MII_TG3_TEST1 0x1e
#define MII_TG3_TEST1_TRIM_EN 0x0010
#define MII_TG3_TEST1_CRC_EN 0x8000
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 106dc1ef0ac..74eb12107e6 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -533,7 +533,6 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
struct net_device *dev;
TLanPrivateInfo *priv;
- u8 pci_rev;
u16 device_id;
int reg, rc = -ENODEV;
@@ -577,8 +576,6 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
goto err_out_free_dev;
}
- pci_read_config_byte ( pdev, PCI_REVISION_ID, &pci_rev);
-
for ( reg= 0; reg <= 5; reg ++ ) {
if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) {
pci_io_base = pci_resource_start(pdev, reg);
@@ -595,7 +592,7 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
dev->base_addr = pci_io_base;
dev->irq = pdev->irq;
- priv->adapterRev = pci_rev;
+ priv->adapterRev = pdev->revision;
pci_set_master(pdev);
pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index e22a3f5333e..9f1b6ab9c22 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -363,7 +363,7 @@ static int __devinit xl_probe(struct pci_dev *pdev,
}
-static int __init xl_init(struct net_device *dev)
+static int __devinit xl_init(struct net_device *dev)
{
struct xl_private *xl_priv = (struct xl_private *)dev->priv ;
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 8c9634a98c1..1c537d5a306 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -2,17 +2,17 @@
# Tulip family network device configuration
#
-menu "Tulip family network device support"
- depends on NET_ETHERNET && (PCI || EISA || CARDBUS)
-
-config NET_TULIP
+menuconfig NET_TULIP
bool "\"Tulip\" family network device support"
+ depends on PCI || EISA || CARDBUS
help
This selects the "Tulip" family of EISA/PCI network cards.
+if NET_TULIP
+
config DE2104X
tristate "Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)"
- depends on NET_TULIP && PCI && EXPERIMENTAL
+ depends on PCI && EXPERIMENTAL
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
@@ -30,7 +30,7 @@ config DE2104X
config TULIP
tristate "DECchip Tulip (dc2114x) PCI support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is developed for the SMC EtherPower series Ethernet
@@ -95,7 +95,7 @@ config TULIP_NAPI_HW_MITIGATION
config DE4X5
tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
- depends on NET_TULIP && (PCI || EISA)
+ depends on PCI || EISA
select CRC32
---help---
This is support for the DIGITAL series of PCI/EISA Ethernet cards.
@@ -112,7 +112,7 @@ config DE4X5
config WINBOND_840
tristate "Winbond W89c840 Ethernet support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
select MII
help
@@ -123,7 +123,7 @@ config WINBOND_840
config DM9102
tristate "Davicom DM910x/DM980x support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
@@ -137,7 +137,7 @@ config DM9102
config ULI526X
tristate "ULi M526x controller support"
- depends on NET_TULIP && PCI
+ depends on PCI
select CRC32
---help---
This driver is for ULi M5261/M5263 10/100M Ethernet Controller
@@ -149,7 +149,7 @@ config ULI526X
config PCMCIA_XIRCOM
tristate "Xircom CardBus support (new driver)"
- depends on NET_TULIP && CARDBUS
+ depends on CARDBUS
---help---
This driver is for the Digital "Tulip" Ethernet CardBus adapters.
It should work with most DEC 21*4*-based chips/ethercards, as well
@@ -162,7 +162,7 @@ config PCMCIA_XIRCOM
config PCMCIA_XIRTULIP
tristate "Xircom Tulip-like CardBus support (old driver)"
- depends on NET_TULIP && CARDBUS && BROKEN_ON_SMP
+ depends on CARDBUS && BROKEN_ON_SMP
select CRC32
---help---
This driver is for the Digital "Tulip" Ethernet CardBus adapters.
@@ -174,5 +174,4 @@ config PCMCIA_XIRTULIP
<file:Documentation/networking/net-modules.txt>. The module will
be called xircom_tulip_cb. If unsure, say N.
-endmenu
-
+endif # NET_TULIP
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 861729806dc..d380e0b3f05 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -785,7 +785,6 @@ static void __de_set_rx_mode (struct net_device *dev)
de->tx_head = NEXT_TX(entry);
- BUG_ON(TX_BUFFS_AVAIL(de) < 0);
if (TX_BUFFS_AVAIL(de) == 0)
netif_stop_queue(dev);
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 62143f92c23..09902891a6e 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -597,7 +597,7 @@ static char *args;
#endif
struct parameters {
- int fdx;
+ bool fdx;
int autosense;
};
@@ -809,10 +809,10 @@ struct de4x5_private {
s32 irq_en; /* Summary interrupt bits */
int media; /* Media (eg TP), mode (eg 100B)*/
int c_media; /* Remember the last media conn */
- int fdx; /* media full duplex flag */
+ bool fdx; /* media full duplex flag */
int linkOK; /* Link is OK */
int autosense; /* Allow/disallow autosensing */
- int tx_enable; /* Enable descriptor polling */
+ bool tx_enable; /* Enable descriptor polling */
int setup_f; /* Setup frame filtering type */
int local_state; /* State within a 'media' state */
struct mii_phy phy[DE4X5_MAX_PHY]; /* List of attached PHY devices */
@@ -838,8 +838,8 @@ struct de4x5_private {
struct de4x5_srom srom; /* A copy of the SROM */
int cfrv; /* Card CFRV copy */
int rx_ovf; /* Check for 'RX overflow' tag */
- int useSROM; /* For non-DEC card use SROM */
- int useMII; /* Infoblock using the MII */
+ bool useSROM; /* For non-DEC card use SROM */
+ bool useMII; /* Infoblock using the MII */
int asBitValid; /* Autosense bits in GEP? */
int asPolarity; /* 0 => asserted high */
int asBit; /* Autosense bit number in GEP */
@@ -928,7 +928,7 @@ static int dc21040_state(struct net_device *dev, int csr13, int csr14, int c
static int test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
static int test_for_100Mb(struct net_device *dev, int msec);
static int wait_for_link(struct net_device *dev);
-static int test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec);
+static int test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec);
static int is_spd_100(struct net_device *dev);
static int is_100_up(struct net_device *dev);
static int is_10_up(struct net_device *dev);
@@ -1109,7 +1109,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
/*
** Now find out what kind of DC21040/DC21041/DC21140 board we have.
*/
- lp->useSROM = FALSE;
+ lp->useSROM = false;
if (lp->bus == PCI) {
PCI_signature(name, lp);
} else {
@@ -1137,7 +1137,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
lp->cache.gepc = GEP_INIT;
lp->asBit = GEP_SLNK;
lp->asPolarity = GEP_SLNK;
- lp->asBitValid = TRUE;
+ lp->asBitValid = ~0;
lp->timeout = -1;
lp->gendev = gendev;
spin_lock_init(&lp->lock);
@@ -1463,7 +1463,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
u_long flags = 0;
netif_stop_queue(dev);
- if (lp->tx_enable == NO) { /* Cannot send for now */
+ if (!lp->tx_enable) { /* Cannot send for now */
return -1;
}
@@ -2134,7 +2134,7 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
u_short vendor, status;
u_int irq = 0, device;
u_long iobase = 0; /* Clear upper 32 bits in Alphas */
- int i, j, cfrv;
+ int i, j;
struct de4x5_private *lp = netdev_priv(dev);
struct list_head *walk;
@@ -2150,7 +2150,6 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
/* Get the chip configuration revision register */
pb = this_dev->bus->number;
- pci_read_config_dword(this_dev, PCI_REVISION_ID, &cfrv);
/* Set the device number information */
lp->device = PCI_SLOT(this_dev->devfn);
@@ -2158,7 +2157,8 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
/* Set the chipset information */
if (is_DC2114x) {
- device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+ device = ((this_dev->revision & CFRV_RN) < DC2114x_BRK
+ ? DC21142 : DC21143);
}
lp->chipset = device;
@@ -2254,7 +2254,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
}
/* Get the chip configuration revision register */
- pci_read_config_dword(pdev, PCI_REVISION_ID, &lp->cfrv);
+ lp->cfrv = pdev->revision;
/* Set the device number information */
lp->device = dev_num;
@@ -2424,7 +2424,7 @@ dc21040_autoconf(struct net_device *dev)
switch (lp->media) {
case INIT:
DISABLE_IRQs;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
lp->timeout = -1;
de4x5_save_skbs(dev);
if ((lp->autosense == AUTO) || (lp->autosense == TP)) {
@@ -2477,7 +2477,7 @@ dc21040_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
break;
}
@@ -2578,7 +2578,7 @@ dc21041_autoconf(struct net_device *dev)
switch (lp->media) {
case INIT:
DISABLE_IRQs;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
lp->timeout = -1;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) {
@@ -2757,7 +2757,7 @@ dc21041_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = NO;
+ lp->tx_enable = false;
break;
}
@@ -2781,7 +2781,7 @@ dc21140m_autoconf(struct net_device *dev)
case INIT:
if (lp->timeout < 0) {
DISABLE_IRQs;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
lp->linkOK = 0;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
}
@@ -2830,7 +2830,7 @@ dc21140m_autoconf(struct net_device *dev)
if (lp->timeout < 0) {
mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
}
- cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+ cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
if (cr < 0) {
next_tick = cr & ~TIMER_CB;
} else {
@@ -2845,7 +2845,7 @@ dc21140m_autoconf(struct net_device *dev)
break;
case 1:
- if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+ if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) {
next_tick = sr & ~TIMER_CB;
} else {
lp->media = SPD_DET;
@@ -2857,10 +2857,10 @@ dc21140m_autoconf(struct net_device *dev)
if (!(anlpa & MII_ANLPA_RF) &&
(cap = anlpa & MII_ANLPA_TAF & ana)) {
if (cap & MII_ANA_100M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
lp->media = _100Mb;
} else if (cap & MII_ANA_10M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
lp->media = _10Mb;
}
@@ -2932,7 +2932,7 @@ dc21140m_autoconf(struct net_device *dev)
lp->c_media = lp->media;
}
lp->media = INIT;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
break;
}
@@ -2965,7 +2965,7 @@ dc2114x_autoconf(struct net_device *dev)
case INIT:
if (lp->timeout < 0) {
DISABLE_IRQs;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
lp->linkOK = 0;
lp->timeout = -1;
de4x5_save_skbs(dev); /* Save non transmitted skb's */
@@ -3013,7 +3013,7 @@ dc2114x_autoconf(struct net_device *dev)
if (lp->timeout < 0) {
mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
}
- cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
+ cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
if (cr < 0) {
next_tick = cr & ~TIMER_CB;
} else {
@@ -3028,7 +3028,8 @@ dc2114x_autoconf(struct net_device *dev)
break;
case 1:
- if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
+ sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000);
+ if (sr < 0) {
next_tick = sr & ~TIMER_CB;
} else {
lp->media = SPD_DET;
@@ -3040,10 +3041,10 @@ dc2114x_autoconf(struct net_device *dev)
if (!(anlpa & MII_ANLPA_RF) &&
(cap = anlpa & MII_ANLPA_TAF & ana)) {
if (cap & MII_ANA_100M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
lp->media = _100Mb;
} else if (cap & MII_ANA_10M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
+ lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
lp->media = _10Mb;
}
}
@@ -3222,14 +3223,14 @@ srom_map_media(struct net_device *dev)
{
struct de4x5_private *lp = netdev_priv(dev);
- lp->fdx = 0;
+ lp->fdx = false;
if (lp->infoblock_media == lp->media)
return 0;
switch(lp->infoblock_media) {
case SROM_10BASETF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_10BASET:
if (lp->params.fdx && !lp->fdx) return -1;
if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) {
@@ -3249,7 +3250,7 @@ srom_map_media(struct net_device *dev)
case SROM_100BASETF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_100BASET:
if (lp->params.fdx && !lp->fdx) return -1;
lp->media = _100Mb;
@@ -3261,7 +3262,7 @@ srom_map_media(struct net_device *dev)
case SROM_100BASEFF:
if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
+ lp->fdx = true;
case SROM_100BASEF:
if (lp->params.fdx && !lp->fdx) return -1;
lp->media = _100Mb;
@@ -3297,7 +3298,7 @@ de4x5_init_connection(struct net_device *dev)
spin_lock_irqsave(&lp->lock, flags);
de4x5_rst_desc_ring(dev);
de4x5_setup_intr(dev);
- lp->tx_enable = YES;
+ lp->tx_enable = true;
spin_unlock_irqrestore(&lp->lock, flags);
outl(POLL_DEMAND, DE4X5_TPD);
@@ -3336,7 +3337,7 @@ de4x5_reset_phy(struct net_device *dev)
}
}
if (lp->useMII) {
- next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500);
+ next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500);
}
} else if (lp->chipset == DC21140) {
PHY_HARD_RESET;
@@ -3466,7 +3467,7 @@ wait_for_link(struct net_device *dev)
**
*/
static int
-test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
+test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec)
{
struct de4x5_private *lp = netdev_priv(dev);
int test;
@@ -3476,9 +3477,8 @@ test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
lp->timeout = msec/100;
}
- if (pol) pol = ~0;
reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
- test = (reg ^ pol) & mask;
+ test = (reg ^ (pol ? ~0 : 0)) & mask;
if (test && --lp->timeout) {
reg = 100 | TIMER_CB;
@@ -3992,10 +3992,10 @@ PCI_signature(char *name, struct de4x5_private *lp)
)))))));
}
if (lp->chipset != DC21041) {
- lp->useSROM = TRUE; /* card is not recognisably DEC */
+ lp->useSROM = true; /* card is not recognisably DEC */
}
} else if ((lp->chipset & ~0x00ff) == DC2114x) {
- lp->useSROM = TRUE;
+ lp->useSROM = true;
}
return status;
@@ -4216,7 +4216,7 @@ srom_repair(struct net_device *dev, int card)
memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom));
memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN);
memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100);
- lp->useSROM = TRUE;
+ lp->useSROM = true;
break;
}
@@ -4392,7 +4392,7 @@ srom_infoleaf_info(struct net_device *dev)
if (lp->chipset == infoleaf_array[i].chipset) break;
}
if (i == INFOLEAF_SIZE) {
- lp->useSROM = FALSE;
+ lp->useSROM = false;
printk("%s: Cannot find correct chipset for SROM decoding!\n",
dev->name);
return -ENXIO;
@@ -4409,7 +4409,7 @@ srom_infoleaf_info(struct net_device *dev)
if (lp->device == *p) break;
}
if (i == 0) {
- lp->useSROM = FALSE;
+ lp->useSROM = false;
printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
dev->name, lp->device);
return -ENXIO;
@@ -4542,7 +4542,7 @@ dc21140_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4577,7 +4577,7 @@ dc21142_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4611,7 +4611,7 @@ dc21143_infoleaf(struct net_device *dev)
}
lp->media = INIT;
lp->tcount = 0;
- lp->tx_enable = FALSE;
+ lp->tx_enable = false;
}
return next_tick & ~TIMER_CB;
@@ -4650,7 +4650,7 @@ compact_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4691,7 +4691,7 @@ type0_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4731,7 +4731,7 @@ type1_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->ibn = 1;
lp->active = *p;
lp->infoblock_csr6 = OMR_MII_100;
- lp->useMII = TRUE;
+ lp->useMII = true;
lp->infoblock_media = ANS;
de4x5_switch_mac_port(dev);
@@ -4773,7 +4773,7 @@ type2_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
lp->cache.gep = ((s32)(TWIDDLE(p)) << 16);
lp->infoblock_csr6 = OMR_SIA;
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -4814,7 +4814,7 @@ type3_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->active = *p;
if (MOTO_SROM_BUG) lp->active = 0;
lp->infoblock_csr6 = OMR_MII_100;
- lp->useMII = TRUE;
+ lp->useMII = true;
lp->infoblock_media = ANS;
de4x5_switch_mac_port(dev);
@@ -4856,7 +4856,7 @@ type4_infoblock(struct net_device *dev, u_char count, u_char *p)
lp->asBit = 1 << ((csr6 >> 1) & 0x07);
lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
+ lp->useMII = false;
de4x5_switch_mac_port(dev);
}
@@ -5077,7 +5077,7 @@ mii_get_phy(struct net_device *dev)
int id;
lp->active = 0;
- lp->useMII = TRUE;
+ lp->useMII = true;
/* Search the MII address space for possible PHY devices */
for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
@@ -5127,7 +5127,7 @@ mii_get_phy(struct net_device *dev)
de4x5_dbg_mii(dev, k);
}
}
- if (!lp->mii_cnt) lp->useMII = FALSE;
+ if (!lp->mii_cnt) lp->useMII = false;
return lp->mii_cnt;
}
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index 57226e5eb8a..12af0cc037f 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -893,15 +893,6 @@
#define PHYS_ADDR_ONLY 1 /* Update the physical address only */
/*
-** Booleans
-*/
-#define NO 0
-#define FALSE 0
-
-#define YES ~0
-#define TRUE ~0
-
-/*
** Adapter state
*/
#define INITIALISED 0 /* After h/w initialised and mem alloc'd */
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 4ed67ff0e81..dab74feb44b 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -181,11 +181,12 @@
udelay(5);
#define __CHK_IO_SIZE(pci_id, dev_rev) \
- (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x02000030) ) ? \
+ (( ((pci_id)==PCI_DM9132_ID) || ((dev_rev) >= 0x30) ) ? \
DM9102A_IO_SIZE: DM9102_IO_SIZE)
-#define CHK_IO_SIZE(pci_dev, dev_rev) \
- (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, dev_rev))
+#define CHK_IO_SIZE(pci_dev) \
+ (__CHK_IO_SIZE(((pci_dev)->device << 16) | (pci_dev)->vendor, \
+ (pci_dev)->revision))
/* Sten Check */
#define DEVICE net_device
@@ -205,7 +206,7 @@ struct rx_desc {
struct dmfe_board_info {
u32 chip_id; /* Chip vendor/Device ID */
- u32 chip_revision; /* Chip revision */
+ u8 chip_revision; /* Chip revision */
struct DEVICE *next_dev; /* next device */
struct pci_dev *pdev; /* PCI device */
spinlock_t lock;
@@ -359,7 +360,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
{
struct dmfe_board_info *db; /* board information structure */
struct net_device *dev;
- u32 dev_rev, pci_pmr;
+ u32 pci_pmr;
int i, err;
DMFE_DBUG(0, "dmfe_init_one()", 0);
@@ -392,10 +393,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
goto err_out_disable;
}
- /* Read Chip revision */
- pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
-
- if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev, dev_rev)) ) {
+ if (pci_resource_len(pdev, 0) < (CHK_IO_SIZE(pdev)) ) {
printk(KERN_ERR DRV_NAME ": Allocated I/O size too small\n");
err = -ENODEV;
goto err_out_disable;
@@ -433,7 +431,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
db->chip_id = ent->driver_data;
db->ioaddr = pci_resource_start(pdev, 0);
- db->chip_revision = dev_rev;
+ db->chip_revision = pdev->revision;
db->wol_mode = 0;
db->pdev = pdev;
@@ -455,7 +453,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
pci_read_config_dword(pdev, 0x50, &pci_pmr);
pci_pmr &= 0x70000;
- if ( (pci_pmr == 0x10000) && (dev_rev == 0x02000031) )
+ if ( (pci_pmr == 0x10000) && (db->chip_revision == 0x31) )
db->chip_type = 1; /* DM9102A E3 */
else
db->chip_type = 0;
@@ -553,7 +551,7 @@ static int dmfe_open(struct DEVICE *dev)
/* CR6 operation mode decision */
if ( !chkmode || (db->chip_id == PCI_DM9132_ID) ||
- (db->chip_revision >= 0x02000030) ) {
+ (db->chip_revision >= 0x30) ) {
db->cr6_data |= DMFE_TXTH_256;
db->cr0_data = CR0_DEFAULT;
db->dm910x_chk_mode=4; /* Enter the normal mode */
@@ -1199,9 +1197,9 @@ static void dmfe_timer(unsigned long data)
tmp_cr12 = inb(db->ioaddr + DCR12); /* DM9102/DM9102A */
if ( ((db->chip_id == PCI_DM9102_ID) &&
- (db->chip_revision == 0x02000030)) ||
+ (db->chip_revision == 0x30)) ||
((db->chip_id == PCI_DM9132_ID) &&
- (db->chip_revision == 0x02000010)) ) {
+ (db->chip_revision == 0x10)) ) {
/* DM9102A Chip */
if (tmp_cr12 & 2)
link_ok = 0;
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index ea896777bca..53efd6694e7 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -197,8 +197,8 @@ int tulip_poll(struct net_device *dev, int *budget)
tp->rx_buffers[entry].mapping,
pkt_len, PCI_DMA_FROMDEVICE);
#if ! defined(__alpha__)
- eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
- pkt_len, 0);
+ skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+ pkt_len);
skb_put(skb, pkt_len);
#else
memcpy(skb_put(skb, pkt_len),
@@ -420,8 +420,8 @@ static int tulip_rx(struct net_device *dev)
tp->rx_buffers[entry].mapping,
pkt_len, PCI_DMA_FROMDEVICE);
#if ! defined(__alpha__)
- eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->data,
- pkt_len, 0);
+ skb_copy_to_linear_data(skb, tp->rx_buffers[entry].skb->data,
+ pkt_len);
skb_put(skb, pkt_len);
#else
memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index 041af63f281..f87d76981ab 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1155,7 +1155,7 @@ static void __devinit tulip_mwi_config (struct pci_dev *pdev,
/* set or disable MWI in the standard PCI command bit.
* Check for the case where mwi is desired but not available
*/
- if (csr0 & MWI) pci_set_mwi(pdev);
+ if (csr0 & MWI) pci_try_set_mwi(pdev);
else pci_clear_mwi(pdev);
/* read result from hardware (in case bit refused to enable) */
@@ -1238,7 +1238,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
};
static int last_irq;
static int multiport_cnt; /* For four-port boards w/one EEPROM */
- u8 chip_rev;
int i, irq;
unsigned short sum;
unsigned char *ee_data;
@@ -1274,10 +1273,8 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
if (pdev->vendor == 0x1282 && pdev->device == 0x9100)
{
- u32 dev_rev;
/* Read Chip revision */
- pci_read_config_dword(pdev, PCI_REVISION_ID, &dev_rev);
- if(dev_rev < 0x02000030)
+ if (pdev->revision < 0x30)
{
printk(KERN_ERR PFX "skipping early DM9100 with Crc bug (use dmfe)\n");
return -ENODEV;
@@ -1360,8 +1357,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
if (!ioaddr)
goto err_out_free_res;
- pci_read_config_byte (pdev, PCI_REVISION_ID, &chip_rev);
-
/*
* initialize private data structure 'tp'
* it is zeroed and aligned in alloc_etherdev
@@ -1382,7 +1377,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
tp->flags = tulip_tbl[chip_idx].flags;
tp->pdev = pdev;
tp->base_addr = ioaddr;
- tp->revision = chip_rev;
+ tp->revision = pdev->revision;
tp->csr0 = csr0;
spin_lock_init(&tp->lock);
spin_lock_init(&tp->mii_lock);
@@ -1399,7 +1394,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
tulip_mwi_config (pdev, dev);
#else
/* MWI is broken for DC21143 rev 65... */
- if (chip_idx == DC21143 && chip_rev == 65)
+ if (chip_idx == DC21143 && pdev->revision == 65)
tp->csr0 &= ~MWI;
#endif
@@ -1640,7 +1635,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
#else
"Port"
#endif
- " %#llx,", dev->name, chip_name, chip_rev,
+ " %#llx,", dev->name, chip_name, pdev->revision,
(unsigned long long) pci_resource_start(pdev, TULIP_BAR));
pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 38f3b99716b..5824f6a3549 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -1232,7 +1232,7 @@ static int netdev_rx(struct net_device *dev)
pci_dma_sync_single_for_cpu(np->pci_dev,np->rx_addr[entry],
np->rx_skbuff[entry]->len,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb, np->rx_skbuff[entry]->data, pkt_len);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(np->pci_dev,np->rx_addr[entry],
np->rx_skbuff[entry]->len,
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 2470b1ee33c..16a54e6b8d4 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -205,7 +205,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
{
struct net_device *dev = NULL;
struct xircom_private *private;
- unsigned char chip_rev;
unsigned long flags;
unsigned short tmp16;
enter("xircom_probe");
@@ -224,8 +223,6 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
pci_read_config_word (pdev,PCI_STATUS, &tmp16);
pci_write_config_word (pdev, PCI_STATUS,tmp16);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
-
if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) {
printk(KERN_ERR "xircom_probe: failed to allocate io-region\n");
return -ENODEV;
@@ -286,7 +283,7 @@ static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_
goto reg_fail;
}
- printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq);
+ printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, pdev->revision, pdev->irq);
/* start the transmitter to get a heartbeat */
/* TODO: send 2 dummy packets here */
transceiver_voodoo(private);
@@ -1208,7 +1205,7 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri
goto out;
}
skb_reserve(skb, 2);
- eth_copy_and_sum(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len, 0);
+ skb_copy_to_linear_data(skb, (unsigned char*)&card->rx_buffer[bufferoffset / 4], pkt_len);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
diff --git a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c
index f6417292737..fc439f33335 100644
--- a/drivers/net/tulip/xircom_tulip_cb.c
+++ b/drivers/net/tulip/xircom_tulip_cb.c
@@ -524,7 +524,6 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi
int chip_idx = id->driver_data;
long ioaddr;
int i;
- u8 chip_rev;
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -620,9 +619,8 @@ static int __devinit xircom_init_one(struct pci_dev *pdev, const struct pci_devi
if (register_netdev(dev))
goto err_out_cleardev;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
printk(KERN_INFO "%s: %s rev %d at %#3lx,",
- dev->name, xircom_tbl[chip_idx].chip_name, chip_rev, ioaddr);
+ dev->name, xircom_tbl[chip_idx].chip_name, pdev->revision, ioaddr);
for (i = 0; i < 6; i++)
printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
printk(", IRQ %d.\n", dev->irq);
@@ -1242,8 +1240,8 @@ xircom_rx(struct net_device *dev)
&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
#if ! defined(__alpha__)
- eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
- pkt_len, 0);
+ skb_copy_to_linear_data(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
+ pkt_len);
skb_put(skb, pkt_len);
#else
memcpy(skb_put(skb, pkt_len),
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a2c6caaaae9..62b2b300501 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -432,6 +432,7 @@ static void tun_setup(struct net_device *dev)
init_waitqueue_head(&tun->read_wait);
tun->owner = -1;
+ tun->group = -1;
SET_MODULE_OWNER(dev);
dev->open = tun_net_open;
@@ -467,8 +468,11 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
return -EBUSY;
/* Check permissions */
- if (tun->owner != -1 &&
- current->euid != tun->owner && !capable(CAP_NET_ADMIN))
+ if (((tun->owner != -1 &&
+ current->euid != tun->owner) ||
+ (tun->group != -1 &&
+ current->egid != tun->group)) &&
+ !capable(CAP_NET_ADMIN))
return -EPERM;
}
else if (__dev_get_by_name(ifr->ifr_name))
@@ -610,6 +614,13 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
break;
+ case TUNSETGROUP:
+ /* Set group of the device */
+ tun->group= (gid_t) arg;
+
+ DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
+ break;
+
case TUNSETLINK:
/* Only allow setting the type when the interface is down */
if (tun->dev->flags & IFF_UP) {
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index f7257359412..03587205546 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -741,15 +741,6 @@ typhoon_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
spin_unlock_bh(&tp->state_lock);
}
-static void
-typhoon_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
-{
- struct typhoon *tp = netdev_priv(dev);
- spin_lock_bh(&tp->state_lock);
- vlan_group_set_device(tp->vlgrp, vid, NULL);
- spin_unlock_bh(&tp->state_lock);
-}
-
static inline void
typhoon_tso_fill(struct sk_buff *skb, struct transmit_ring *txRing,
u32 ring_dma)
@@ -1712,7 +1703,7 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile u32 * ready,
pci_dma_sync_single_for_cpu(tp->pdev, dma_addr,
PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(new_skb, skb->data, pkt_len, 0);
+ skb_copy_to_linear_data(new_skb, skb->data, pkt_len);
pci_dma_sync_single_for_device(tp->pdev, dma_addr,
PKT_BUF_SZ,
PCI_DMA_FROMDEVICE);
@@ -2276,12 +2267,6 @@ need_resume:
typhoon_resume(pdev);
return -EBUSY;
}
-
-static int
-typhoon_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable)
-{
- return pci_enable_wake(pdev, state, enable);
-}
#endif
static int __devinit
@@ -2542,7 +2527,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->get_stats = typhoon_get_stats;
dev->set_mac_address = typhoon_set_mac_address;
dev->vlan_rx_register = typhoon_vlan_rx_register;
- dev->vlan_rx_kill_vid = typhoon_vlan_rx_kill_vid;
+
SET_ETHTOOL_OPS(dev, &typhoon_ethtool_ops);
/* We can handle scatter gather, up to 16 entries, and
@@ -2645,7 +2630,6 @@ static struct pci_driver typhoon_driver = {
#ifdef CONFIG_PM
.suspend = typhoon_suspend,
.resume = typhoon_resume,
- .enable_wake = typhoon_enable_wake,
#endif
};
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 18b731bb4da..e4736a3b1b7 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -2276,7 +2276,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
phy_stop(phydev);
/* Mask all interrupts */
- out_be32(ugeth->uccf->p_ucce, 0x00000000);
+ out_be32(ugeth->uccf->p_uccm, 0x00000000);
/* Clear all interrupts */
out_be32(ugeth->uccf->p_ucce, 0xffffffff);
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index 3de564b2314..8dc09a3790c 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -313,8 +313,8 @@ config USB_KC2190
boolean "KT Technology KC2190 based cables (InstaNet)"
depends on USB_NET_CDC_SUBSET && EXPERIMENTAL
help
-  Choose this option if you're using a host-to-host cable
-  with one of these chips.
+ Choose this option if you're using a host-to-host cable
+ with one of these chips.
config USB_NET_ZAURUS
tristate "Sharp Zaurus (stock ROMs) and compatible"
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 86e90c59d55..76752d84a30 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -255,7 +255,7 @@ static void catc_rx_done(struct urb *urb)
if (!(skb = dev_alloc_skb(pkt_len)))
return;
- eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
+ skb_copy_to_linear_data(skb, pkt_start + pkt_offset, pkt_len);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, catc->netdev);
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 675ac99a79c..a42acc3cc60 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -144,14 +144,14 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
* modem interface from an RNDIS non-modem.
*/
if (rndis) {
- struct usb_cdc_acm_descriptor *d;
+ struct usb_cdc_acm_descriptor *acm;
- d = (void *) buf;
- if (d->bmCapabilities) {
+ acm = (void *) buf;
+ if (acm->bmCapabilities) {
dev_dbg(&intf->dev,
"ACM capabilities %02x, "
"not really RNDIS?\n",
- d->bmCapabilities);
+ acm->bmCapabilities);
goto bad_desc;
}
}
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index a6763860147..16c7a0e8785 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -414,18 +414,16 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
dev->mii.reg_num_mask = 0x1f;
/* reset */
- ret = dm_write_reg(dev, DM_NET_CTRL, 1);
+ dm_write_reg(dev, DM_NET_CTRL, 1);
udelay(20);
/* read MAC */
- ret = dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
- if (ret < 0) {
+ if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr) < 0) {
printk(KERN_ERR "Error reading MAC address\n");
ret = -ENODEV;
goto out;
}
-
/* power up phy */
dm_write_reg(dev, DM_GPR_CTRL, 1);
dm_write_reg(dev, DM_GPR_DATA, 0);
@@ -489,6 +487,8 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
b3..n: packet data
*/
+ len = skb->len;
+
if (skb_headroom(skb) < DM_TX_OVERHEAD) {
struct sk_buff *skb2;
@@ -501,10 +501,9 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
__skb_push(skb, DM_TX_OVERHEAD);
- len = skb->len;
/* usbnet adds padding if length is a multiple of packet size
if so, adjust length value in header */
- if ((len % dev->maxpacket) == 0)
+ if ((skb->len % dev->maxpacket) == 0)
len++;
skb->data[0] = len;
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index 60d29440f31..524dc5f5e46 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -635,7 +635,7 @@ static void kaweth_usb_receive(struct urb *urb)
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
+ skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len);
skb_put(skb, pkt_len);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 5b16d9a1269..37bf4f2c0a4 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -192,7 +192,7 @@ static int init_status (struct usbnet *dev, struct usb_interface *intf)
usb_pipeendpoint(pipe), maxp, period);
}
}
- return 0;
+ return 0;
}
/* Passes this packet up the stack, updating its accounting.
@@ -326,7 +326,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
if (netif_running (dev->net)
&& netif_device_present (dev->net)
&& !test_bit (EVENT_RX_HALT, &dev->flags)) {
- switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){
+ switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) {
case -EPIPE:
usbnet_defer_kevent (dev, EVENT_RX_HALT);
break;
@@ -393,8 +393,8 @@ static void rx_complete (struct urb *urb)
entry->urb = NULL;
switch (urb_status) {
- // success
- case 0:
+ /* success */
+ case 0:
if (skb->len < dev->net->hard_header_len) {
entry->state = rx_cleanup;
dev->stats.rx_errors++;
@@ -404,28 +404,30 @@ static void rx_complete (struct urb *urb)
}
break;
- // stalls need manual reset. this is rare ... except that
- // when going through USB 2.0 TTs, unplug appears this way.
- // we avoid the highspeed version of the ETIMEOUT/EILSEQ
- // storm, recovering as needed.
- case -EPIPE:
+ /* stalls need manual reset. this is rare ... except that
+ * when going through USB 2.0 TTs, unplug appears this way.
+ * we avoid the highspeed version of the ETIMEOUT/EILSEQ
+ * storm, recovering as needed.
+ */
+ case -EPIPE:
dev->stats.rx_errors++;
usbnet_defer_kevent (dev, EVENT_RX_HALT);
// FALLTHROUGH
- // software-driven interface shutdown
- case -ECONNRESET: // async unlink
- case -ESHUTDOWN: // hardware gone
+ /* software-driven interface shutdown */
+ case -ECONNRESET: /* async unlink */
+ case -ESHUTDOWN: /* hardware gone */
if (netif_msg_ifdown (dev))
devdbg (dev, "rx shutdown, code %d", urb_status);
goto block;
- // we get controller i/o faults during khubd disconnect() delays.
- // throttle down resubmits, to avoid log floods; just temporarily,
- // so we still recover when the fault isn't a khubd delay.
- case -EPROTO:
- case -ETIME:
- case -EILSEQ:
+ /* we get controller i/o faults during khubd disconnect() delays.
+ * throttle down resubmits, to avoid log floods; just temporarily,
+ * so we still recover when the fault isn't a khubd delay.
+ */
+ case -EPROTO:
+ case -ETIME:
+ case -EILSEQ:
dev->stats.rx_errors++;
if (!timer_pending (&dev->delay)) {
mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@@ -438,12 +440,12 @@ block:
urb = NULL;
break;
- // data overrun ... flush fifo?
- case -EOVERFLOW:
+ /* data overrun ... flush fifo? */
+ case -EOVERFLOW:
dev->stats.rx_over_errors++;
// FALLTHROUGH
- default:
+ default:
entry->state = rx_cleanup;
dev->stats.rx_errors++;
if (netif_msg_rx_err (dev))
@@ -471,22 +473,22 @@ static void intr_complete (struct urb *urb)
int status = urb->status;
switch (status) {
- /* success */
- case 0:
+ /* success */
+ case 0:
dev->driver_info->status(dev, urb);
break;
- /* software-driven interface shutdown */
- case -ENOENT: // urb killed
- case -ESHUTDOWN: // hardware gone
+ /* software-driven interface shutdown */
+ case -ENOENT: /* urb killed */
+ case -ESHUTDOWN: /* hardware gone */
if (netif_msg_ifdown (dev))
devdbg (dev, "intr shutdown, code %d", status);
return;
- /* NOTE: not throttling like RX/TX, since this endpoint
- * already polls infrequently
- */
- default:
+ /* NOTE: not throttling like RX/TX, since this endpoint
+ * already polls infrequently
+ */
+ default:
devdbg (dev, "intr status %d", status);
break;
}
@@ -569,9 +571,9 @@ static int usbnet_stop (struct net_device *net)
temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq);
// maybe wait for deletions to finish.
- while (!skb_queue_empty(&dev->rxq) &&
- !skb_queue_empty(&dev->txq) &&
- !skb_queue_empty(&dev->done)) {
+ while (!skb_queue_empty(&dev->rxq)
+ && !skb_queue_empty(&dev->txq)
+ && !skb_queue_empty(&dev->done)) {
msleep(UNLINK_TIMEOUT_MS);
if (netif_msg_ifdown (dev))
devdbg (dev, "waited for %d urb completions", temp);
@@ -953,11 +955,14 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
/* don't assume the hardware handles USB_ZERO_PACKET
* NOTE: strictly conforming cdc-ether devices should expect
* the ZLP here, but ignore the one-byte packet.
- *
- * FIXME zero that byte, if it doesn't require a new skb.
*/
- if ((length % dev->maxpacket) == 0)
+ if ((length % dev->maxpacket) == 0) {
urb->transfer_buffer_length++;
+ if (skb_tailroom(skb)) {
+ skb->data[skb->len] = 0;
+ __skb_put(skb, 1);
+ }
+ }
spin_lock_irqsave (&dev->txq.lock, flags);
@@ -1008,16 +1013,16 @@ static void usbnet_bh (unsigned long param)
while ((skb = skb_dequeue (&dev->done))) {
entry = (struct skb_data *) skb->cb;
switch (entry->state) {
- case rx_done:
+ case rx_done:
entry->state = rx_cleanup;
rx_process (dev, skb);
continue;
- case tx_done:
- case rx_cleanup:
+ case tx_done:
+ case rx_cleanup:
usb_free_urb (entry->urb);
dev_kfree_skb (skb);
continue;
- default:
+ default:
devdbg (dev, "bogus skb state %d", entry->state);
}
}
@@ -1208,7 +1213,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
status = 0;
}
- if (status == 0 && dev->status)
+ if (status >= 0 && dev->status)
status = init_status (dev, udev);
if (status < 0)
goto out3;
diff --git a/drivers/net/usb/usbnet.h b/drivers/net/usb/usbnet.h
index a3f8b9e7bc0..a6c5820767d 100644
--- a/drivers/net/usb/usbnet.h
+++ b/drivers/net/usb/usbnet.h
@@ -47,7 +47,7 @@ struct usbnet {
unsigned long data [5];
u32 xid;
u32 hard_mtu; /* count any extra framing */
- size_t rx_urb_size; /* size for rx urbs */
+ size_t rx_urb_size; /* size for rx urbs */
struct mii_if_info mii;
/* various kinds of pending driver work */
@@ -85,7 +85,7 @@ struct driver_info {
#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */
#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */
-#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
+#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */
/* init device ... can sleep, or cause probe() failure */
int (*bind)(struct usbnet *, struct usb_interface *);
@@ -146,9 +146,9 @@ extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *);
/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */
#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
- |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
- |USB_CDC_PACKET_TYPE_PROMISCUOUS \
- |USB_CDC_PACKET_TYPE_DIRECTED)
+ |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+ |USB_CDC_PACKET_TYPE_PROMISCUOUS \
+ |USB_CDC_PACKET_TYPE_DIRECTED)
/* we record the state for each of our queued skbs */
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index adea290a9d5..f51c2c138f1 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -622,7 +622,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
struct net_device *dev;
struct rhine_private *rp;
int i, rc;
- u8 pci_rev;
u32 quirks;
long pioaddr;
long memaddr;
@@ -642,27 +641,25 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
printk(version);
#endif
- pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
-
io_size = 256;
phy_id = 0;
quirks = 0;
name = "Rhine";
- if (pci_rev < VTunknown0) {
+ if (pdev->revision < VTunknown0) {
quirks = rqRhineI;
io_size = 128;
}
- else if (pci_rev >= VT6102) {
+ else if (pdev->revision >= VT6102) {
quirks = rqWOL | rqForceReset;
- if (pci_rev < VT6105) {
+ if (pdev->revision < VT6105) {
name = "Rhine II";
quirks |= rqStatusWBRace; /* Rhine-II exclusive */
}
else {
phy_id = 1; /* Integrated PHY, phy_id fixed to 1 */
- if (pci_rev >= VT6105_B0)
+ if (pdev->revision >= VT6105_B0)
quirks |= rq6patterns;
- if (pci_rev < VT6105M)
+ if (pdev->revision < VT6105M)
name = "Rhine III";
else
name = "Rhine III (Management Adapter)";
@@ -1492,9 +1489,9 @@ static int rhine_rx(struct net_device *dev, int limit)
rp->rx_buf_sz,
PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb,
+ skb_copy_to_linear_data(skb,
rp->rx_skbuff[entry]->data,
- pkt_len, 0);
+ pkt_len);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(rp->pdev,
rp->rx_skbuff_dma[entry],
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 25b75b61518..f331843d110 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -890,8 +890,7 @@ static void __devinit velocity_init_info(struct pci_dev *pdev,
static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
{
- if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0)
- return -EIO;
+ vptr->rev_id = pdev->revision;
pci_set_master(pdev);
@@ -1562,7 +1561,7 @@ static void velocity_print_link_status(struct velocity_info *vptr)
if (vptr->mii_status & VELOCITY_LINK_FAIL) {
VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: failed to detect cable link\n", vptr->dev->name);
} else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
- VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link autonegation", vptr->dev->name);
+ VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: Link auto-negotiation", vptr->dev->name);
if (vptr->mii_status & VELOCITY_SPEED_1000)
VELOCITY_PRT(MSG_LEVEL_INFO, " speed 1000M bps");
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 999bf71937c..ec1c556a47c 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -3439,7 +3439,6 @@ static int __devinit
cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int first_time = 1;
- ucchar cpc_rev_id;
int err, eeprom_outdated = 0;
ucshort device_id;
pc300_t *card;
@@ -3480,7 +3479,6 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
card->hw.falcsize = pci_resource_len(pdev, 4);
card->hw.plxphys = pci_resource_start(pdev, 5);
card->hw.plxsize = pci_resource_len(pdev, 5);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &cpc_rev_id);
switch (device_id) {
case PCI_DEVICE_ID_PC300_RX_1:
@@ -3498,7 +3496,7 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
#ifdef PC300_DEBUG_PCI
printk("cpc (bus=0x0%x,pci_id=0x%x,", pdev->bus->number, pdev->devfn);
- printk("rev_id=%d) IRQ%d\n", cpc_rev_id, card->hw.irq);
+ printk("rev_id=%d) IRQ%d\n", pdev->revision, card->hw.irq);
printk("cpc:found ramaddr=0x%08lx plxaddr=0x%08lx "
"ctladdr=0x%08lx falcaddr=0x%08lx\n",
card->hw.ramphys, card->hw.plxphys, card->hw.scaphys,
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index aff05dba720..dfbd3b00f03 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -311,7 +311,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
card_t *card;
- u8 rev_id;
u32 __iomem *p;
int i;
u32 ramsize;
@@ -366,7 +365,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
return -ENOMEM;
}
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE ||
pci_resource_len(pdev, 2) != PC300_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index ca06a00d9d8..7f720de2e9f 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -289,7 +289,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
card_t *card;
- u8 rev_id;
u32 __iomem *p;
int i;
u32 ramsize;
@@ -330,7 +329,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
return -ENOMEM;
}
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index e3f5bb0fe60..ae27af0141c 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -266,16 +266,23 @@ config IPW2200_DEBUG
If you are not sure, say N here.
-config LIBERTAS_USB
- tristate "Marvell Libertas 8388 802.11a/b/g cards"
- depends on USB && WLAN_80211
+config LIBERTAS
+ tristate "Marvell 8xxx Libertas WLAN driver support"
+ depends on WLAN_80211
+ select IEEE80211
select FW_LOADER
---help---
+ A library for Marvell Libertas 8xxx devices.
+
+config LIBERTAS_USB
+ tristate "Marvell Libertas 8388 USB 802.11b/g cards"
+ depends on LIBERTAS && USB
+ ---help---
A driver for Marvell Libertas 8388 USB devices.
-config LIBERTAS_USB_DEBUG
- bool "Enable full debugging output in the Libertas USB module."
- depends on LIBERTAS_USB
+config LIBERTAS_DEBUG
+ bool "Enable full debugging output in the Libertas module."
+ depends on LIBERTAS
---help---
Debugging support.
@@ -539,6 +546,18 @@ config USB_ZD1201
To compile this driver as a module, choose M here: the
module will be called zd1201.
+config RTL8187
+ tristate "Realtek 8187 USB support"
+ depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
+ select EEPROM_93CX6
+ ---help---
+ This is a driver for RTL8187 based cards.
+ These are USB based chips found in cards such as:
+
+ Netgear WG111v2
+
+ Thanks to Realtek for their support!
+
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index d2124602263..ef35bc6c4a2 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -44,3 +44,6 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
obj-$(CONFIG_LIBERTAS_USB) += libertas/
+
+rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
+obj-$(CONFIG_RTL8187) += rtl8187.o
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index ef6b253a92c..c5d6753a55e 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -3741,10 +3741,8 @@ static int bcm43xx_attach_board(struct bcm43xx_private *bcm)
&bcm->board_type);
if (err)
goto err_iounmap;
- err = bcm43xx_pci_read_config16(bcm, PCI_REVISION_ID,
- &bcm->board_revision);
- if (err)
- goto err_iounmap;
+
+ bcm->board_revision = bcm->pci_dev->revision;
err = bcm43xx_chipset_attach(bcm);
if (err)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b37f1e34870..d779199c30d 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1638,7 +1638,7 @@ void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm,
return;
}
- if (phy->analog > 1) {
+ if (phy->analog == 1) {
value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C;
value |= (baseband_attenuation << 2) & 0x003C;
} else {
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 5b3abd54d0e..90900525379 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -326,7 +326,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
char *p = page;
struct ap_data *ap = (struct ap_data *) data;
char *policy_txt;
- struct list_head *ptr;
struct mac_entry *entry;
if (off != 0) {
@@ -352,14 +351,12 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries);
p += sprintf(p, "MAC list:\n");
spin_lock_bh(&ap->mac_restrictions.lock);
- for (ptr = ap->mac_restrictions.mac_list.next;
- ptr != &ap->mac_restrictions.mac_list; ptr = ptr->next) {
+ list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) {
if (p - page > PAGE_SIZE - 80) {
p += sprintf(p, "All entries did not fit one page.\n");
break;
}
- entry = list_entry(ptr, struct mac_entry, list);
p += sprintf(p, MACSTR "\n", MAC2STR(entry->addr));
}
spin_unlock_bh(&ap->mac_restrictions.lock);
@@ -413,7 +410,6 @@ int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac)
static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
u8 *mac)
{
- struct list_head *ptr;
struct mac_entry *entry;
int found = 0;
@@ -421,10 +417,7 @@ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions,
return 0;
spin_lock_bh(&mac_restrictions->lock);
- for (ptr = mac_restrictions->mac_list.next;
- ptr != &mac_restrictions->mac_list; ptr = ptr->next) {
- entry = list_entry(ptr, struct mac_entry, list);
-
+ list_for_each_entry(entry, &mac_restrictions->mac_list, list) {
if (memcmp(entry->addr, mac, ETH_ALEN) == 0) {
found = 1;
break;
@@ -519,7 +512,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
{
char *p = page;
struct ap_data *ap = (struct ap_data *) data;
- struct list_head *ptr;
+ struct sta_info *sta;
int i;
if (off > PROC_LIMIT) {
@@ -529,9 +522,7 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n");
spin_lock_bh(&ap->sta_table_lock);
- for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
- struct sta_info *sta = (struct sta_info *) ptr;
-
+ list_for_each_entry(sta, &ap->sta_list, list) {
if (!sta->ap)
continue;
@@ -861,7 +852,7 @@ void hostap_init_ap_proc(local_info_t *local)
void hostap_free_data(struct ap_data *ap)
{
- struct list_head *n, *ptr;
+ struct sta_info *n, *sta;
if (ap == NULL || !ap->initialized) {
printk(KERN_DEBUG "hostap_free_data: ap has not yet been "
@@ -875,8 +866,7 @@ void hostap_free_data(struct ap_data *ap)
ap->crypt = ap->crypt_priv = NULL;
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
- list_for_each_safe(ptr, n, &ap->sta_list) {
- struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry_safe(sta, n, &ap->sta_list, list) {
ap_sta_hash_del(ap, sta);
list_del(&sta->list);
if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local)
@@ -2704,6 +2694,8 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
if (hdr->addr1[0] & 0x01) {
/* broadcast/multicast frame - no AP related processing */
+ if (local->ap->num_sta <= 0)
+ ret = AP_TX_DROP;
goto out;
}
@@ -3198,15 +3190,14 @@ int hostap_update_rx_stats(struct ap_data *ap,
void hostap_update_rates(local_info_t *local)
{
- struct list_head *ptr;
+ struct sta_info *sta;
struct ap_data *ap = local->ap;
if (!ap)
return;
spin_lock_bh(&ap->sta_table_lock);
- for (ptr = ap->sta_list.next; ptr != &ap->sta_list; ptr = ptr->next) {
- struct sta_info *sta = (struct sta_info *) ptr;
+ list_for_each_entry(sta, &ap->sta_list, list) {
prism2_check_tx_rates(sta);
}
spin_unlock_bh(&ap->sta_table_lock);
@@ -3242,11 +3233,10 @@ void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
void hostap_add_wds_links(local_info_t *local)
{
struct ap_data *ap = local->ap;
- struct list_head *ptr;
+ struct sta_info *sta;
spin_lock_bh(&ap->sta_table_lock);
- list_for_each(ptr, &ap->sta_list) {
- struct sta_info *sta = list_entry(ptr, struct sta_info, list);
+ list_for_each_entry(sta, &ap->sta_list, list) {
if (sta->ap)
hostap_wds_link_oper(local, sta->addr, WDS_ADD);
}
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index c090a5aebb5..30acd39d76a 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -1,8 +1,6 @@
#ifndef HOSTAP_CONFIG_H
#define HOSTAP_CONFIG_H
-#define PRISM2_VERSION "0.4.4-kernel"
-
/* In the previous versions of Host AP driver, support for user space version
* of IEEE 802.11 management (hostapd) used to be disabled in the default
* configuration. From now on, support for hostapd is always included and it is
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ee1532b62e4..30e723f6597 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -22,7 +22,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static dev_info_t dev_info = "hostap_cs";
MODULE_AUTHOR("Jouni Malinen");
@@ -30,7 +29,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PC Card).");
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
static int ignore_cis_vcc;
@@ -910,14 +908,12 @@ static struct pcmcia_driver hostap_driver = {
static int __init init_prism2_pccard(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
return pcmcia_register_driver(&hostap_driver);
}
static void __exit exit_prism2_pccard(void)
{
pcmcia_unregister_driver(&hostap_driver);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index cdea7f71b9e..8c71077d653 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -3893,8 +3893,6 @@ static void prism2_get_drvinfo(struct net_device *dev,
local = iface->local;
strncpy(info->driver, "hostap", sizeof(info->driver) - 1);
- strncpy(info->version, PRISM2_VERSION,
- sizeof(info->version) - 1);
snprintf(info->fw_version, sizeof(info->fw_version) - 1,
"%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
(local->sta_fw_ver >> 8) & 0xff,
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 4743426cf6a..446de51bab7 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -37,7 +37,6 @@
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Host AP common routines");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
#define TX_TIMEOUT (2 * HZ)
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index db4899ed4bb..7da3664b851 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -20,7 +20,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static char *dev_info = "hostap_pci";
@@ -29,7 +28,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN "
"PCI cards.");
MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
/* struct local_info::hw_priv */
@@ -455,15 +453,11 @@ static struct pci_driver prism2_pci_drv_id = {
.suspend = prism2_pci_suspend,
.resume = prism2_pci_resume,
#endif /* CONFIG_PM */
- /* Linux 2.4.6 added save_state and enable_wake that are not used here
- */
};
static int __init init_prism2_pci(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
-
return pci_register_driver(&prism2_pci_drv_id);
}
@@ -471,7 +465,6 @@ static int __init init_prism2_pci(void)
static void __exit exit_prism2_pci(void)
{
pci_unregister_driver(&prism2_pci_drv_id);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c
index f0fd5ecdb24..040dc3e3641 100644
--- a/drivers/net/wireless/hostap/hostap_plx.c
+++ b/drivers/net/wireless/hostap/hostap_plx.c
@@ -23,7 +23,6 @@
#include "hostap_wlan.h"
-static char *version = PRISM2_VERSION " (Jouni Malinen <j@w1.fi>)";
static char *dev_info = "hostap_plx";
@@ -32,7 +31,6 @@ MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
"cards (PLX).");
MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)");
MODULE_LICENSE("GPL");
-MODULE_VERSION(PRISM2_VERSION);
static int ignore_cis;
@@ -615,16 +613,11 @@ static struct pci_driver prism2_plx_drv_id = {
.id_table = prism2_plx_id_table,
.probe = prism2_plx_probe,
.remove = prism2_plx_remove,
- .suspend = NULL,
- .resume = NULL,
- .enable_wake = NULL
};
static int __init init_prism2_plx(void)
{
- printk(KERN_INFO "%s: %s\n", dev_info, version);
-
return pci_register_driver(&prism2_plx_drv_id);
}
@@ -632,7 +625,6 @@ static int __init init_prism2_plx(void)
static void __exit exit_prism2_plx(void)
{
pci_unregister_driver(&prism2_plx_drv_id);
- printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c
index e0ecc4d483b..4cf0ff7b833 100644
--- a/drivers/net/wireless/libertas/11d.c
+++ b/drivers/net/wireless/libertas/11d.c
@@ -95,7 +95,7 @@ static u8 wlan_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 * chan)
for (i = 0; i < cfp_no; i++) {
if ((cfp + i)->channel == firstchan) {
- lbs_pr_debug(1, "firstchan found\n");
+ lbs_deb_11d("firstchan found\n");
break;
}
}
@@ -129,12 +129,12 @@ static u8 wlan_channel_known_11d(u8 chan,
for (i = 0; i < nr_chan; i++) {
if (chan == chanpwr[i].chan) {
- lbs_pr_debug(1, "11D: Found Chan:%d\n", chan);
+ lbs_deb_11d("11D: Found Chan:%d\n", chan);
return 1;
}
}
- lbs_pr_debug(1, "11D: Not Find Chan:%d\n", chan);
+ lbs_deb_11d("11D: Not Find Chan:%d\n", chan);
return 0;
}
@@ -174,7 +174,7 @@ static int generate_domain_info_11d(struct parsed_region_chan_11d
memcpy(domaininfo->countrycode, parsed_region_chan->countrycode,
COUNTRY_CODE_LEN);
- lbs_pr_debug(1, "11D:nrchan=%d\n", nr_chan);
+ lbs_deb_11d("11D:nrchan=%d\n", nr_chan);
lbs_dbg_hex("11D:parsed_region_chan:", (char *)parsed_region_chan,
sizeof(struct parsed_region_chan_11d));
@@ -212,7 +212,7 @@ static int generate_domain_info_11d(struct parsed_region_chan_11d
}
domaininfo->nr_subband = nr_subband;
- lbs_pr_debug(1, "nr_subband=%x\n", domaininfo->nr_subband);
+ lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
lbs_dbg_hex("11D:domaininfo:", (char *)domaininfo,
COUNTRY_CODE_LEN + 1 +
sizeof(struct ieeetypes_subbandset) * nr_subband);
@@ -233,13 +233,13 @@ static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_
struct chan_freq_power *cfp;
if (region_chan == NULL) {
- lbs_pr_debug(1, "11D: region_chan is NULL\n");
+ lbs_deb_11d("11D: region_chan is NULL\n");
return;
}
cfp = region_chan->CFP;
if (cfp == NULL) {
- lbs_pr_debug(1, "11D: cfp equal NULL \n");
+ lbs_deb_11d("11D: cfp equal NULL \n");
return;
}
@@ -248,19 +248,19 @@ static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_
memcpy(parsed_region_chan->countrycode,
wlan_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
- lbs_pr_debug(1, "11D: region[0x%x] band[%d]\n", parsed_region_chan->region,
+ lbs_deb_11d("11D: region[0x%x] band[%d]\n", parsed_region_chan->region,
parsed_region_chan->band);
for (i = 0; i < region_chan->nrcfp; i++, cfp++) {
parsed_region_chan->chanpwr[i].chan = cfp->channel;
parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower;
- lbs_pr_debug(1, "11D: Chan[%d] Pwr[%d]\n",
+ lbs_deb_11d("11D: Chan[%d] Pwr[%d]\n",
parsed_region_chan->chanpwr[i].chan,
parsed_region_chan->chanpwr[i].pwr);
}
parsed_region_chan->nr_chan = region_chan->nrcfp;
- lbs_pr_debug(1, "11D: nrchan[%d]\n", parsed_region_chan->nr_chan);
+ lbs_deb_11d("11D: nrchan[%d]\n", parsed_region_chan->nr_chan);
return;
}
@@ -277,8 +277,9 @@ static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
struct chan_freq_power *cfp;
int cfp_no;
u8 idx;
+ int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_11D);
cfp = libertas_get_region_cfp_table(region, band, &cfp_no);
if (cfp == NULL)
@@ -288,16 +289,19 @@ static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
if (chan == (cfp + idx)->channel) {
/* If Mrvl Chip Supported? */
if ((cfp + idx)->unsupported) {
- return 0;
+ ret = 0;
} else {
- return 1;
+ ret = 1;
}
+ goto done;
}
}
/*chan is not in the region table */
- LEAVE();
- return 0;
+
+done:
+ lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+ return ret;
}
/**
@@ -321,7 +325,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
u8 j, i;
- ENTER();
+ lbs_deb_enter(LBS_DEB_11D);
/*validation Rules:
1. valid region Code
@@ -337,15 +341,14 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
if ((*(countryinfo->countrycode)) == 0
|| (countryinfo->len <= COUNTRY_CODE_LEN)) {
/* No region Info or Wrong region info: treat as No 11D info */
- LEAVE();
- return 0;
+ goto done;
}
/*Step1: check region_code */
parsed_region_chan->region = region =
wlan_region_2_code(countryinfo->countrycode);
- lbs_pr_debug(1, "regioncode=%x\n", (u8) parsed_region_chan->region);
+ lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region);
lbs_dbg_hex("CountryCode:", (char *)countryinfo->countrycode,
COUNTRY_CODE_LEN);
@@ -361,7 +364,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
if (countryinfo->subband[j].firstchan <= lastchan) {
/*Step2&3. Check First Chan Num increment and no overlap */
- lbs_pr_debug(1, "11D: Chan[%d>%d] Overlap\n",
+ lbs_deb_11d("11D: Chan[%d>%d] Overlap\n",
countryinfo->subband[j].firstchan, lastchan);
continue;
}
@@ -374,7 +377,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
if (!wlan_get_chan_11d(band, firstchan, i, &curchan)) {
/* Chan is not found in UN table */
- lbs_pr_debug(1, "chan is not supported: %d \n", i);
+ lbs_deb_11d("chan is not supported: %d \n", i);
break;
}
@@ -389,7 +392,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
idx++;
} else {
/*not supported and ignore the chan */
- lbs_pr_debug(1,
+ lbs_deb_11d(
"11D:i[%d] chan[%d] unsupported in region[%x] band[%d]\n",
i, curchan, region, band);
}
@@ -401,11 +404,12 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
parsed_region_chan->nr_chan = idx;
- lbs_pr_debug(1, "nrchan=%x\n", parsed_region_chan->nr_chan);
+ lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan);
lbs_dbg_hex("11D:parsed_region_chan:", (u8 *) parsed_region_chan,
2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
- LEAVE();
+done:
+ lbs_deb_enter(LBS_DEB_11D);
return 0;
}
@@ -420,16 +424,16 @@ u8 libertas_get_scan_type_11d(u8 chan,
{
u8 scan_type = cmd_scan_type_passive;
- ENTER();
+ lbs_deb_enter(LBS_DEB_11D);
if (wlan_channel_known_11d(chan, parsed_region_chan)) {
- lbs_pr_debug(1, "11D: Found and do Active Scan\n");
+ lbs_deb_11d("11D: Found and do Active Scan\n");
scan_type = cmd_scan_type_active;
} else {
- lbs_pr_debug(1, "11D: Not Find and do Passive Scan\n");
+ lbs_deb_11d("11D: Not Find and do Passive Scan\n");
}
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type);
return scan_type;
}
@@ -456,7 +460,7 @@ static int wlan_enable_11d(wlan_private * priv, u8 flag)
OID_802_11D_ENABLE,
&priv->adapter->enable11d);
if (ret)
- lbs_pr_debug(1, "11D: Fail to enable 11D \n");
+ lbs_deb_11d("11D: Fail to enable 11D \n");
return 0;
}
@@ -471,7 +475,7 @@ static int set_domain_info_11d(wlan_private * priv)
int ret;
if (!priv->adapter->enable11d) {
- lbs_pr_debug(1, "11D: dnld domain Info with 11d disabled\n");
+ lbs_deb_11d("11D: dnld domain Info with 11d disabled\n");
return 0;
}
@@ -479,7 +483,7 @@ static int set_domain_info_11d(wlan_private * priv)
cmd_act_set,
cmd_option_waitforrsp, 0, NULL);
if (ret)
- lbs_pr_debug(1, "11D: Fail to dnld domain Info\n");
+ lbs_deb_11d("11D: Fail to dnld domain Info\n");
return ret;
}
@@ -501,7 +505,7 @@ int libertas_set_universaltable(wlan_private * priv, u8 band)
adapter->universal_channel[i].nrcfp =
sizeof(channel_freq_power_UN_BG) / size;
- lbs_pr_debug(1, "11D: BG-band nrcfp=%d\n",
+ lbs_deb_11d("11D: BG-band nrcfp=%d\n",
adapter->universal_channel[i].nrcfp);
adapter->universal_channel[i].CFP = channel_freq_power_UN_BG;
@@ -531,9 +535,9 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
u8 nr_subband = adapter->domainreg.nr_subband;
- ENTER();
+ lbs_deb_enter(LBS_DEB_11D);
- lbs_pr_debug(1, "nr_subband=%x\n", nr_subband);
+ lbs_deb_11d("nr_subband=%x\n", nr_subband);
cmd->command = cpu_to_le16(cmdno);
pdomaininfo->action = cpu_to_le16(cmdoption);
@@ -542,8 +546,7 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv,
cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
lbs_dbg_hex("11D: 802_11D_DOMAIN_INFO:", (u8 *) cmd,
(int)(cmd->size));
- LEAVE();
- return 0;
+ goto done;
}
domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
@@ -567,10 +570,10 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv,
cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
}
- lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, (int)(cmd->size));
-
- LEAVE();
+ lbs_dbg_hex("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, le16_to_cpu(cmd->size));
+done:
+ lbs_deb_enter(LBS_DEB_11D);
return 0;
}
@@ -585,17 +588,17 @@ int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq)
int data = 0;
int *val;
- ENTER();
+ lbs_deb_enter(LBS_DEB_11D);
data = SUBCMD_DATA(wrq);
- lbs_pr_debug(1, "enable 11D: %s\n",
+ lbs_deb_11d("enable 11D: %s\n",
(data == 1) ? "enable" : "Disable");
wlan_enable_11d(priv, data);
val = (int *)wrq->u.name;
*val = priv->adapter->enable11d;
- LEAVE();
+ lbs_deb_enter(LBS_DEB_11D);
return 0;
}
@@ -608,25 +611,24 @@ int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq)
int libertas_ret_802_11d_domain_info(wlan_private * priv,
struct cmd_ds_command *resp)
{
- struct cmd_ds_802_11d_domain_info
- *domaininfo = &resp->params.domaininforesp;
+ struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
u16 action = le16_to_cpu(domaininfo->action);
s16 ret = 0;
u8 nr_subband = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_11D);
lbs_dbg_hex("11D DOMAIN Info Rsp Data:", (u8 *) resp,
(int)le16_to_cpu(resp->size));
- nr_subband = (domain->header.len - 3) / sizeof(struct ieeetypes_subbandset);
- /* countrycode 3 bytes */
+ nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
+ sizeof(struct ieeetypes_subbandset);
- lbs_pr_debug(1, "11D Domain Info Resp: nr_subband=%d\n", nr_subband);
+ lbs_deb_11d("11D Domain Info Resp: nr_subband=%d\n", nr_subband);
if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
- lbs_pr_debug(1, "Invalid Numrer of Subband returned!!\n");
+ lbs_deb_11d("Invalid Numrer of Subband returned!!\n");
return -1;
}
@@ -637,12 +639,12 @@ int libertas_ret_802_11d_domain_info(wlan_private * priv,
case cmd_act_get:
break;
default:
- lbs_pr_debug(1, "Invalid action:%d\n", domaininfo->action);
+ lbs_deb_11d("Invalid action:%d\n", domaininfo->action);
ret = -1;
break;
}
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
return ret;
}
@@ -651,23 +653,22 @@ int libertas_ret_802_11d_domain_info(wlan_private * priv,
* @param priv pointer to wlan_private
* @return 0; -1
*/
-int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
+int libertas_parse_dnld_countryinfo_11d(wlan_private * priv,
+ struct bss_descriptor * bss)
{
int ret;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_11D);
if (priv->adapter->enable11d) {
memset(&adapter->parsed_region_chan, 0,
sizeof(struct parsed_region_chan_11d));
- ret = parse_domain_info_11d(&adapter->pattemptedbssdesc->
- countryinfo, 0,
+ ret = parse_domain_info_11d(&bss->countryinfo, 0,
&adapter->parsed_region_chan);
if (ret == -1) {
- lbs_pr_debug(1, "11D: Err Parse domain_info from AP..\n");
- LEAVE();
- return ret;
+ lbs_deb_11d("11D: Err Parse domain_info from AP..\n");
+ goto done;
}
memset(&adapter->domainreg, 0,
@@ -678,13 +679,15 @@ int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
ret = set_domain_info_11d(priv);
if (ret) {
- lbs_pr_debug(1, "11D: Err set domainInfo to FW\n");
- LEAVE();
- return ret;
+ lbs_deb_11d("11D: Err set domainInfo to FW\n");
+ goto done;
}
}
- LEAVE();
- return 0;
+ ret = 0;
+
+done:
+ lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+ return ret;
}
/**
@@ -699,8 +702,8 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
struct region_channel *region_chan;
u8 j;
- ENTER();
- lbs_pr_debug(1, "11D:curbssparams.band[%d]\n", adapter->curbssparams.band);
+ lbs_deb_enter(LBS_DEB_11D);
+ lbs_deb_11d("11D:curbssparams.band[%d]\n", adapter->curbssparams.band);
if (priv->adapter->enable11d) {
/* update parsed_region_chan_11; dnld domaininf to FW */
@@ -709,7 +712,7 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
sizeof(adapter->region_channel[0]); j++) {
region_chan = &adapter->region_channel[j];
- lbs_pr_debug(1, "11D:[%d] region_chan->band[%d]\n", j,
+ lbs_deb_11d("11D:[%d] region_chan->band[%d]\n", j,
region_chan->band);
if (!region_chan || !region_chan->valid
@@ -722,10 +725,10 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
if (j >= sizeof(adapter->region_channel) /
sizeof(adapter->region_channel[0])) {
- lbs_pr_debug(1, "11D:region_chan not found. band[%d]\n",
+ lbs_deb_11d("11D:region_chan not found. band[%d]\n",
adapter->curbssparams.band);
- LEAVE();
- return -1;
+ ret = -1;
+ goto done;
}
memset(&adapter->parsed_region_chan, 0,
@@ -742,13 +745,14 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
ret = set_domain_info_11d(priv);
if (ret) {
- lbs_pr_debug(1, "11D: Err set domainInfo to FW\n");
- LEAVE();
- return ret;
+ lbs_deb_11d("11D: Err set domainInfo to FW\n");
+ goto done;
}
}
+ ret = 0;
- LEAVE();
- return 0;
+done:
+ lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+ return ret;
}
diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h
index db2ebea9f23..73e42e71291 100644
--- a/drivers/net/wireless/libertas/11d.h
+++ b/drivers/net/wireless/libertas/11d.h
@@ -47,7 +47,7 @@ struct mrvlietypes_domainparamset {
} __attribute__ ((packed));
struct cmd_ds_802_11d_domain_info {
- u16 action;
+ __le16 action;
struct mrvlietypes_domainparamset domain;
} __attribute__ ((packed));
@@ -98,7 +98,9 @@ int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq);
int libertas_ret_802_11d_domain_info(wlan_private * priv,
struct cmd_ds_command *resp);
-int libertas_parse_dnld_countryinfo_11d(wlan_private * priv);
+struct bss_descriptor;
+int libertas_parse_dnld_countryinfo_11d(wlan_private * priv,
+ struct bss_descriptor * bss);
int libertas_create_dnld_countryinfo_11d(wlan_private * priv);
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 56a8ea1fbf0..32ed4136b0d 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -1,12 +1,12 @@
-usb8xxx-objs := main.o fw.o wext.o \
+libertas-objs := main.o fw.o wext.o \
rx.o tx.o cmd.o \
cmdresp.o scan.o \
join.o 11d.o \
- ioctl.o debugfs.o \
+ debugfs.o \
ethtool.o assoc.o
usb8xxx-objs += if_bootcmd.o
usb8xxx-objs += if_usb.o
+obj-$(CONFIG_LIBERTAS) += libertas.o
obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
-
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
index 378577200b5..0b133ce6380 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -1,7 +1,7 @@
================================================================================
README for USB8388
- (c) Copyright © 2003-2006, Marvell International Ltd.
+ (c) Copyright © 2003-2006, Marvell International Ltd.
All Rights Reserved
This software file (the "File") is distributed by Marvell International
@@ -28,293 +28,6 @@ DRIVER LOADING
insmod usb8388.ko [fw_name=usb8388.bin]
-=====================
-IWPRIV COMMAND
-=====================
-
-NAME
- This manual describes the usage of private commands used in Marvell WLAN
- Linux Driver. All the commands available in Wlanconfig will not be available
- in the iwpriv.
-
-SYNOPSIS
- iwpriv <ethX> <command> [sub-command] ...
-
- iwpriv ethX setregioncode <n>
- iwpriv ethX getregioncode
-
-Version 5 Command:
- iwpriv ethX ledgpio <n>
-
-BT Commands:
- The blinding table (BT) contains a list of mac addresses that should be
- ignored by the firmware. It is primarily used for debugging and
- testing networks. It can be edited and inspected with the following
- commands:
-
- iwpriv ethX bt_reset
- iwpriv ethX bt_add <mac_address>
- iwpriv ethX bt_del <mac_address>
- iwpriv ethX bt_list <id>
-
-FWT Commands:
- The forwarding table (FWT) is a feature used to manage mesh network
- routing in the firmware. The FWT is essentially a routing table that
- associates a destination mac address (da) with a next hop receiver
- address (ra). The FWT can be inspected and edited with the following
- iwpriv commands, which are described in greater detail below.
- Eventually, the table will be automatically maintained by a custom
- routing protocol.
-
- NOTE: FWT commands replace the previous DFT commands. What were the DFT
- commands?, you might ask. They were an earlier API to the firmware that
- implemented a simple MAC-layer forwarding mechanism. In the unlikely
- event that you were using these commands, you must migrate to the new
- FWT commands which can be used to achieve the same functionality.
-
- iwpriv ethX fwt_add [parameters]
- iwpriv ethX fwt_del [parameters]
- iwpriv ethX fwt_lookup [parameters]
- iwpriv ethX fwt_list [parameters]
- iwpriv ethX fwt_list_route [parameters]
- iwpriv ethX fwt_list_neigh [parameters]
- iwpriv ethX fwt_reset [parameters]
- iwpriv ethX fwt_cleanup
- iwpriv ethX fwt_time
-
-MESH Commands:
-
- The MESH commands are used to configure various features of the mesh
- routing protocol. The following commands are supported:
-
- iwpriv ethX mesh_get_ttl
- iwpriv ethX mesh_set_ttl ttl
-
-DESCRIPTION
- Those commands are used to send additional commands to the Marvell WLAN
- card via the Linux device driver.
-
- The ethX parameter specifies the network device that is to be used to
- perform this command on. it could be eth0, eth1 etc.
-
-setregioncode
- This command is used to set the region code in the station.
- where value is 'region code' for various regions like
- USA FCC, Canada IC, Spain, France, Europe ETSI, Japan ...
-
- Usage:
- iwpriv ethX setregioncode 0x10: set region code to USA (0x10).
-
-getregioncode
- This command is used to get the region code information set in the
- station.
-
-ledgpio
- This command is used to set/get LEDs.
-
- iwpriv ethX ledgpio <LEDs>
- will set the corresponding LED for the GPIO Line.
-
- iwpriv ethX ledgpio
- will give u which LEDs are Enabled.
-
- Usage:
- iwpriv eth1 ledgpio 1 0 2 1 3 4
- will enable
- LED 1 -> GPIO 0
- LED 2 -> GPIO 1
- LED 3 -> GPIO 4
-
- iwpriv eth1 ledgpio
- shows LED information in the format as mentioned above.
-
- Note: LED0 is invalid
- Note: Maximum Number of LEDs are 16.
-
-fwt_add
- This command is used to insert an entry into the FWT table. The list of
- parameters must follow the following structure:
-
- iwpriv ethX fwt_add da ra [metric dir ssn dsn hopcount ttl expiration sleepmode snr]
-
- The parameters between brackets are optional, but they must appear in
- the order specified. For example, if you want to specify the metric,
- you must also specify the dir, ssn, and dsn but you need not specify the
- hopcount, expiration, sleepmode, or snr. Any unspecified parameters
- will be assigned the defaults specified below.
-
- The different parameters are:-
- da -- DA MAC address in the form 00:11:22:33:44:55
- ra -- RA MAC address in the form 00:11:22:33:44:55
- metric -- route metric (cost: smaller-metric routes are
- preferred, default is 0)
- dir -- direction (1 for direct, 0 for reverse,
- default is 1)
- ssn -- Source Sequence Number (time at the RA for
- reverse routes. Default is 0)
- dsn -- Destination Sequence Number (time at the DA
- for direct routes. Default is 0)
- hopcount -- hop count (currently unused, default is 0)
- ttl -- TTL (Only used in reverse entries)
- expiration -- entry expiration (in ticks, where a tick is
- 1024us, or ~ 1ms. Use 0 for an indefinite
- entry, default is 0)
- sleepmode -- RA's sleep mode (currently unused, default is
- 0)
- snr -- SNR in the link to RA (currently unused,
- default is 0)
-
- The command does not return anything.
-
-fwt_del
- This command is used to remove an entry to the FWT table. The list of
- parameters must follow the following structure:
-
- iwpriv ethX fwt_del da ra [dir]
-
- where the different parameters are:-
- da -- DA MAC address (in the form "00:11:22:33:44:55")
- ra -- RA MAC address (in the form "00:11:22:33:44:55")
- dir -- direction (1 for direct, 0 for reverse,
- default is 1)
-
- The command does not return anything.
-
-fwt_lookup
- This command is used to get the best route in the FWT table to a given
- host. The only parameter is the MAC address of the host that is being
- looked for.
-
- iwpriv ethX fwt_lookup da
-
- where:-
- da -- DA MAC address (in the form "00:11:22:33:44:55")
-
- The command returns an output string identical to the one returned by
- fwt_list described below.
-
-
-fwt_list
- This command is used to list a route from the FWT table. The only
- parameter is the index into the table. If you want to list all the
- routes in a table, start with index=0, and keep listing until you get a
- "(null)" string. Note that the indicies may change as the fwt is
- updated. It is expected that most users will not use fwt_list directly,
- but that a utility similar to the traditional route command will be used
- to invoke fwt_list over and over.
-
- iwpriv ethX fwt_list index
-
- The output is a string of the following form:
-
- da ra metric dir ssn dsn hopcount ttl expiration sleepmode snr
-
- where the different fields are:-
- da -- DA MAC address (in the form "00:11:22:33:44:55")
- ra -- RA MAC address (in the form "00:11:22:33:44:55")
- metric -- route metric (cost: smaller-metric routes are preferred)
- dir -- direction (1 for direct, 0 for reverse)
- ssn -- Source Sequence Number (time at the RA for reverse routes)
- dsn -- Destination Sequence Number (time at the DA for direct routes)
- hopcount -- hop count (currently unused)
- ttl -- TTL (only used in reverse entries)
- expiration -- entry expiration (in ticks, where a tick is 1024us, or ~ 1ms. Use 0 for an indefinite entry)
- sleepmode -- RA's sleep mode (currently unused)
- snr -- SNR in the link to RA (currently unused)
-
-fwt_list_route
- This command is used to list a route from the FWT table. The only
- parameter is the route ID. If you want to list all the routes in a
- table, start with rid=0, and keep incrementing rid until you get a
- "(null)" string. This function is similar to fwt_list. The only
- difference is the output format. Also note that this command is meant
- for debugging. It is expected that users will use fwt_lookup and
- fwt_list. One important reason for this is that the route id may change
- as the route table is altered.
-
- iwpriv ethX fwt_list_route rid
-
- The output is a string of the following form:
-
- da metric dir nid ssn dsn hopcount ttl expiration
-
- where the different fields are:-
- da -- DA MAC address (in the form "00:11:22:33:44:55")
- metric -- route metric (cost: smaller-metric routes are preferred)
- dir -- direction (1 for direct, 0 for reverse)
- nid -- Next-hop (neighbor) host ID (nid)
- ssn -- Source Sequence Number (time at the RA for reverse routes)
- dsn -- Destination Sequence Number (time at the DA for direct routes)
- hopcount -- hop count (currently unused)
- ttl -- TTL count (only used in reverse entries)
- expiration -- entry expiration (in ticks, where a tick is 1024us, or ~ 1ms. Use 0 for an indefinite entry)
-
-fwt_list_neigh
- This command is used to list a neighbor from the FWT table. The only
- parameter is the neighbor ID. If you want to list all the neighbors in a
- table, start with nid=0, and keep incrementing nid until you get a
- "(null)" string. Note that the nid from a fwt_list_route command can be
- used as an input to this command. Also note that this command is meant
- mostly for debugging. It is expected that users will use fwt_lookup.
- One important reason for this is that the neighbor id may change as the
- neighbor table is altered.
-
- iwpriv ethX fwt_list_neigh nid
-
- The output is a string of the following form:
-
- ra sleepmode snr references
-
- where the different fields are:-
- ra -- RA MAC address (in the form "00:11:22:33:44:55")
- sleepmode -- RA's sleep mode (currently unused)
- snr -- SNR in the link to RA (currently unused)
- references -- RA's reference counter
-
-fwt_reset
- This command is used to reset the FWT table, getting rid of all the
- entries. There are no input parameters.
-
- iwpriv ethX fwt_reset
-
- The command does not return anything.
-
-fwt_cleanup
- This command is used to perform user-based garbage recollection. The
- FWT table is checked, and all the entries that are expired or invalid
- are cleaned. Note that this is exported to the driver for debugging
- purposes, as garbage collection is also fired by the firmware when in
- space problems. There are no input parameters.
-
- iwpriv ethX fwt_cleanup
-
- The command does returns the number of invalid/expired routes deleted.
-
-fwt_time
- This command returns a card's internal time representation. It is this
- time that is used to represent the expiration times of FWT entries. The
- number is not consistent from card to card; it is simply a timer count.
- The fwt_time command is used to inspect the timer so that expiration
- times reported by fwt_list can be properly interpreted.
-
- iwpriv ethX fwt_time
-
-mesh_get_ttl
-
- The mesh ttl is the number of hops a mesh packet can traverse before it
- is dropped. This parameter is used to prevent infinite loops in the
- mesh network. The value returned by this function is the ttl assigned
- to all mesh packets. Currently there is no way to control the ttl on a
- per packet or per socket basis.
-
- iwpriv ethX mesh_get_ttl
-
-mesh_set_ttl ttl
-
- Set the ttl. The argument must be between 0 and 255.
-
- iwpriv ethX mesh_set_ttl <ttl>
-
=========================
ETHTOOL
=========================
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index c260bd1b3d4..afd5617dd92 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -2,6 +2,7 @@
#include <linux/bitops.h>
#include <net/ieee80211.h>
+#include <linux/etherdevice.h>
#include "assoc.h"
#include "join.h"
@@ -13,59 +14,88 @@
static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static void print_assoc_req(const char * extra, struct assoc_request * assoc_req)
+{
+ lbs_deb_assoc(
+ "#### Association Request: %s\n"
+ " flags: 0x%08lX\n"
+ " SSID: '%s'\n"
+ " channel: %d\n"
+ " band: %d\n"
+ " mode: %d\n"
+ " BSSID: " MAC_FMT "\n"
+ " Encryption:%s%s%s\n"
+ " auth: %d\n",
+ extra, assoc_req->flags,
+ escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+ assoc_req->channel, assoc_req->band, assoc_req->mode,
+ MAC_ARG(assoc_req->bssid),
+ assoc_req->secinfo.WPAenabled ? " WPA" : "",
+ assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
+ assoc_req->secinfo.wep_enabled ? " WEP" : "",
+ assoc_req->secinfo.auth_mode);
+}
+
+
static int assoc_helper_essid(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
- int i;
+ struct bss_descriptor * bss;
+ int channel = -1;
+
+ lbs_deb_enter(LBS_DEB_ASSOC);
- ENTER();
+ /* FIXME: take channel into account when picking SSIDs if a channel
+ * is set.
+ */
+
+ if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
+ channel = assoc_req->channel;
- lbs_pr_debug(1, "New SSID requested: %s\n", assoc_req->ssid.ssid);
+ lbs_deb_assoc("New SSID requested: '%s'\n",
+ escape_essid(assoc_req->ssid, assoc_req->ssid_len));
if (assoc_req->mode == IW_MODE_INFRA) {
if (adapter->prescan) {
- libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 1);
+ libertas_send_specific_ssid_scan(priv, assoc_req->ssid,
+ assoc_req->ssid_len, 0);
}
- i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid,
- NULL, IW_MODE_INFRA);
- if (i >= 0) {
- lbs_pr_debug(1,
- "SSID found in scan list ... associating...\n");
-
- ret = wlan_associate(priv, &adapter->scantable[i]);
- if (ret == 0) {
- memcpy(&assoc_req->bssid,
- &adapter->scantable[i].macaddress,
- ETH_ALEN);
- }
+ bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid,
+ assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
+ if (bss != NULL) {
+ lbs_deb_assoc("SSID found in scan list, associating\n");
+ memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
+ ret = wlan_associate(priv, assoc_req);
} else {
- lbs_pr_debug(1, "SSID '%s' not found; cannot associate\n",
- assoc_req->ssid.ssid);
+ lbs_deb_assoc("SSID not found; cannot associate\n");
}
} else if (assoc_req->mode == IW_MODE_ADHOC) {
/* Scan for the network, do not save previous results. Stale
* scan data will cause us to join a non-existant adhoc network
*/
- libertas_send_specific_SSID_scan(priv, &assoc_req->ssid, 0);
+ libertas_send_specific_ssid_scan(priv, assoc_req->ssid,
+ assoc_req->ssid_len, 1);
/* Search for the requested SSID in the scan table */
- i = libertas_find_SSID_in_list(adapter, &assoc_req->ssid, NULL,
- IW_MODE_ADHOC);
- if (i >= 0) {
- lbs_pr_debug(1, "SSID found at %d in List, so join\n", ret);
- libertas_join_adhoc_network(priv, &adapter->scantable[i]);
+ bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid,
+ assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
+ if (bss != NULL) {
+ lbs_deb_assoc("SSID found, will join\n");
+ memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
+ libertas_join_adhoc_network(priv, assoc_req);
} else {
/* else send START command */
- lbs_pr_debug(1, "SSID not found in list, so creating adhoc"
- " with SSID '%s'\n", assoc_req->ssid.ssid);
- libertas_start_adhoc_network(priv, &assoc_req->ssid);
+ lbs_deb_assoc("SSID not found, creating adhoc network\n");
+ memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
+ IW_ESSID_MAX_SIZE);
+ assoc_req->bss.ssid_len = assoc_req->ssid_len;
+ libertas_start_adhoc_network(priv, assoc_req);
}
- memcpy(&assoc_req->bssid, &adapter->current_addr, ETH_ALEN);
}
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -74,33 +104,31 @@ static int assoc_helper_bssid(wlan_private *priv,
struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
- int i, ret = 0;
-
- ENTER();
+ int ret = 0;
+ struct bss_descriptor * bss;
- lbs_pr_debug(1, "ASSOC: WAP: BSSID = " MAC_FMT "\n",
+ lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID " MAC_FMT,
MAC_ARG(assoc_req->bssid));
/* Search for index position in list for requested MAC */
- i = libertas_find_BSSID_in_list(adapter, assoc_req->bssid,
+ bss = libertas_find_bssid_in_list(adapter, assoc_req->bssid,
assoc_req->mode);
- if (i < 0) {
- lbs_pr_debug(1, "ASSOC: WAP: BSSID " MAC_FMT " not found, "
+ if (bss == NULL) {
+ lbs_deb_assoc("ASSOC: WAP: BSSID " MAC_FMT " not found, "
"cannot associate.\n", MAC_ARG(assoc_req->bssid));
goto out;
}
+ memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
if (assoc_req->mode == IW_MODE_INFRA) {
- ret = wlan_associate(priv, &adapter->scantable[i]);
- lbs_pr_debug(1, "ASSOC: return from wlan_associate(bssd) was %d\n", ret);
+ ret = wlan_associate(priv, assoc_req);
+ lbs_deb_assoc("ASSOC: wlan_associate(bssid) returned %d\n", ret);
} else if (assoc_req->mode == IW_MODE_ADHOC) {
- libertas_join_adhoc_network(priv, &adapter->scantable[i]);
+ libertas_join_adhoc_network(priv, assoc_req);
}
- memcpy(&assoc_req->ssid, &adapter->scantable[i].ssid,
- sizeof(struct WLAN_802_11_SSID));
out:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -113,12 +141,12 @@ static int assoc_helper_associate(wlan_private *priv,
/* If we're given and 'any' BSSID, try associating based on SSID */
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- if (memcmp(bssid_any, assoc_req->bssid, ETH_ALEN)
- && memcmp(bssid_off, assoc_req->bssid, ETH_ALEN)) {
+ if (compare_ether_addr(bssid_any, assoc_req->bssid)
+ && compare_ether_addr(bssid_off, assoc_req->bssid)) {
ret = assoc_helper_bssid(priv, assoc_req);
done = 1;
if (ret) {
- lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret);
+ lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
}
}
}
@@ -126,7 +154,7 @@ static int assoc_helper_associate(wlan_private *priv,
if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
ret = assoc_helper_essid(priv, assoc_req);
if (ret) {
- lbs_pr_debug(1, "ASSOC: bssid: ret = %d\n", ret);
+ lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
}
}
@@ -140,12 +168,10 @@ static int assoc_helper_mode(wlan_private *priv,
wlan_adapter *adapter = priv->adapter;
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
- if (assoc_req->mode == adapter->mode) {
- LEAVE();
- return 0;
- }
+ if (assoc_req->mode == adapter->mode)
+ goto done;
if (assoc_req->mode == IW_MODE_INFRA) {
if (adapter->psstate != PS_STATE_FULL_POWER)
@@ -158,9 +184,81 @@ static int assoc_helper_mode(wlan_private *priv,
cmd_802_11_snmp_mib,
0, cmd_option_waitforrsp,
OID_802_11_INFRASTRUCTURE_MODE,
- (void *) (size_t) assoc_req->mode);
+ /* Shoot me now */ (void *) (size_t) assoc_req->mode);
- LEAVE();
+done:
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+ return ret;
+}
+
+
+static int update_channel(wlan_private * priv)
+{
+ /* the channel in f/w could be out of sync, get the current channel */
+ return libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
+ cmd_opt_802_11_rf_channel_get,
+ cmd_option_waitforrsp, 0, NULL);
+}
+
+void libertas_sync_channel(struct work_struct *work)
+{
+ wlan_private *priv = container_of(work, wlan_private, sync_channel);
+
+ if (update_channel(priv) != 0)
+ lbs_pr_info("Channel synchronization failed.");
+}
+
+static int assoc_helper_channel(wlan_private *priv,
+ struct assoc_request * assoc_req)
+{
+ wlan_adapter *adapter = priv->adapter;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
+ ret = update_channel(priv);
+ if (ret < 0) {
+ lbs_deb_assoc("ASSOC: channel: error getting channel.");
+ }
+
+ if (assoc_req->channel == adapter->curbssparams.channel)
+ goto done;
+
+ lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
+ adapter->curbssparams.channel, assoc_req->channel);
+
+ ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
+ cmd_opt_802_11_rf_channel_set,
+ cmd_option_waitforrsp, 0, &assoc_req->channel);
+ if (ret < 0) {
+ lbs_deb_assoc("ASSOC: channel: error setting channel.");
+ }
+
+ ret = update_channel(priv);
+ if (ret < 0) {
+ lbs_deb_assoc("ASSOC: channel: error getting channel.");
+ }
+
+ if (assoc_req->channel != adapter->curbssparams.channel) {
+ lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
+ assoc_req->channel);
+ goto done;
+ }
+
+ if ( assoc_req->secinfo.wep_enabled
+ && (assoc_req->wep_keys[0].len
+ || assoc_req->wep_keys[1].len
+ || assoc_req->wep_keys[2].len
+ || assoc_req->wep_keys[3].len)) {
+ /* Make sure WEP keys are re-sent to firmware */
+ set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
+ }
+
+ /* Must restart/rejoin adhoc networks after channel change */
+ set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
+
+done:
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -172,7 +270,7 @@ static int assoc_helper_wep_keys(wlan_private *priv,
int i;
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
/* Set or remove WEP keys */
if ( assoc_req->wep_keys[0].len
@@ -216,7 +314,7 @@ static int assoc_helper_wep_keys(wlan_private *priv,
mutex_unlock(&adapter->lock);
out:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -225,15 +323,49 @@ static int assoc_helper_secinfo(wlan_private *priv,
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
+ u32 do_wpa;
+ u32 rsn = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
memcpy(&adapter->secinfo, &assoc_req->secinfo,
sizeof(struct wlan_802_11_security));
ret = libertas_set_mac_packet_filter(priv);
+ if (ret)
+ goto out;
+
+ /* If RSN is already enabled, don't try to enable it again, since
+ * ENABLE_RSN resets internal state machines and will clobber the
+ * 4-way WPA handshake.
+ */
- LEAVE();
+ /* Get RSN enabled/disabled */
+ ret = libertas_prepare_and_send_command(priv,
+ cmd_802_11_enable_rsn,
+ cmd_act_set,
+ cmd_option_waitforrsp,
+ 0, &rsn);
+ if (ret) {
+ lbs_deb_assoc("Failed to get RSN status: %d", ret);
+ goto out;
+ }
+
+ /* Don't re-enable RSN if it's already enabled */
+ do_wpa = (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled);
+ if (do_wpa == rsn)
+ goto out;
+
+ /* Set RSN enabled/disabled */
+ rsn = do_wpa;
+ ret = libertas_prepare_and_send_command(priv,
+ cmd_802_11_enable_rsn,
+ cmd_act_set,
+ cmd_option_waitforrsp,
+ 0, &rsn);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -243,16 +375,7 @@ static int assoc_helper_wpa_keys(wlan_private *priv,
{
int ret = 0;
- ENTER();
-
- /* enable/Disable RSN */
- ret = libertas_prepare_and_send_command(priv,
- cmd_802_11_enable_rsn,
- cmd_act_set,
- cmd_option_waitforrsp,
- 0, assoc_req);
- if (ret)
- goto out;
+ lbs_deb_enter(LBS_DEB_ASSOC);
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_key_material,
@@ -260,8 +383,7 @@ static int assoc_helper_wpa_keys(wlan_private *priv,
cmd_option_waitforrsp,
0, assoc_req);
-out:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -272,7 +394,7 @@ static int assoc_helper_wpa_ie(wlan_private *priv,
wlan_adapter *adapter = priv->adapter;
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
memcpy(&adapter->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
@@ -282,7 +404,7 @@ static int assoc_helper_wpa_ie(wlan_private *priv,
adapter->wpa_ie_len = 0;
}
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
@@ -294,25 +416,30 @@ static int should_deauth_infrastructure(wlan_adapter *adapter,
return 0;
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- lbs_pr_debug(1, "Deauthenticating due to new SSID in "
+ lbs_deb_assoc("Deauthenticating due to new SSID in "
" configuration request.\n");
return 1;
}
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
if (adapter->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
- lbs_pr_debug(1, "Deauthenticating due to updated security "
+ lbs_deb_assoc("Deauthenticating due to updated security "
"info in configuration request.\n");
return 1;
}
}
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- lbs_pr_debug(1, "Deauthenticating due to new BSSID in "
+ lbs_deb_assoc("Deauthenticating due to new BSSID in "
" configuration request.\n");
return 1;
}
+ if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+ lbs_deb_assoc("Deauthenticating due to channel switch.\n");
+ return 1;
+ }
+
/* FIXME: deal with 'auto' mode somehow */
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
if (assoc_req->mode != IW_MODE_INFRA)
@@ -329,10 +456,9 @@ static int should_stop_adhoc(wlan_adapter *adapter,
if (adapter->connect_status != libertas_connected)
return 0;
- if (adapter->curbssparams.ssid.ssidlength != assoc_req->ssid.ssidlength)
- return 1;
- if (memcmp(adapter->curbssparams.ssid.ssid, assoc_req->ssid.ssid,
- adapter->curbssparams.ssid.ssidlength))
+ if (libertas_ssid_cmp(adapter->curbssparams.ssid,
+ adapter->curbssparams.ssid_len,
+ assoc_req->ssid, assoc_req->ssid_len) != 0)
return 1;
/* FIXME: deal with 'auto' mode somehow */
@@ -341,11 +467,16 @@ static int should_stop_adhoc(wlan_adapter *adapter,
return 1;
}
+ if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+ if (assoc_req->channel != adapter->curbssparams.channel)
+ return 1;
+ }
+
return 0;
}
-void wlan_association_worker(struct work_struct *work)
+void libertas_association_worker(struct work_struct *work)
{
wlan_private *priv = container_of(work, wlan_private, assoc_work.work);
wlan_adapter *adapter = priv->adapter;
@@ -353,40 +484,38 @@ void wlan_association_worker(struct work_struct *work)
int ret = 0;
int find_any_ssid = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
mutex_lock(&adapter->lock);
- assoc_req = adapter->assoc_req;
- adapter->assoc_req = NULL;
+ assoc_req = adapter->pending_assoc_req;
+ adapter->pending_assoc_req = NULL;
+ adapter->in_progress_assoc_req = assoc_req;
mutex_unlock(&adapter->lock);
- if (!assoc_req) {
- LEAVE();
- return;
- }
+ if (!assoc_req)
+ goto done;
- lbs_pr_debug(1, "ASSOC: starting new association request: flags = 0x%lX\n",
- assoc_req->flags);
+ print_assoc_req(__func__, assoc_req);
/* If 'any' SSID was specified, find an SSID to associate with */
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
- && !assoc_req->ssid.ssidlength)
+ && !assoc_req->ssid_len)
find_any_ssid = 1;
/* But don't use 'any' SSID if there's a valid locked BSSID to use */
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- if (memcmp(&assoc_req->bssid, bssid_any, ETH_ALEN)
- && memcmp(&assoc_req->bssid, bssid_off, ETH_ALEN))
+ if (compare_ether_addr(assoc_req->bssid, bssid_any)
+ && compare_ether_addr(assoc_req->bssid, bssid_off))
find_any_ssid = 0;
}
if (find_any_ssid) {
u8 new_mode;
- ret = libertas_find_best_network_SSID(priv, &assoc_req->ssid,
- assoc_req->mode, &new_mode);
+ ret = libertas_find_best_network_ssid(priv, assoc_req->ssid,
+ &assoc_req->ssid_len, assoc_req->mode, &new_mode);
if (ret) {
- lbs_pr_debug(1, "Could not find best network\n");
+ lbs_deb_assoc("Could not find best network\n");
ret = -ENETUNREACH;
goto out;
}
@@ -406,7 +535,7 @@ void wlan_association_worker(struct work_struct *work)
if (should_deauth_infrastructure(adapter, assoc_req)) {
ret = libertas_send_deauthentication(priv);
if (ret) {
- lbs_pr_debug(1, "Deauthentication due to new "
+ lbs_deb_assoc("Deauthentication due to new "
"configuration request failed: %d\n",
ret);
}
@@ -415,7 +544,7 @@ void wlan_association_worker(struct work_struct *work)
if (should_stop_adhoc(adapter, assoc_req)) {
ret = libertas_stop_adhoc_network(priv);
if (ret) {
- lbs_pr_debug(1, "Teardown of AdHoc network due to "
+ lbs_deb_assoc("Teardown of AdHoc network due to "
"new configuration request failed: %d\n",
ret);
}
@@ -427,7 +556,16 @@ void wlan_association_worker(struct work_struct *work)
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
ret = assoc_helper_mode(priv, assoc_req);
if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
+ goto out;
+ }
+ }
+
+ if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
+ ret = assoc_helper_channel(priv, assoc_req);
+ if (ret) {
+ lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n",
+ __LINE__, ret);
goto out;
}
}
@@ -436,7 +574,7 @@ lbs_pr_debug(1, "ASSOC(:%d) mode: ret = %d\n", __LINE__, ret);
|| test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
ret = assoc_helper_wep_keys(priv, assoc_req);
if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret);
goto out;
}
}
@@ -444,7 +582,7 @@ lbs_pr_debug(1, "ASSOC(:%d) wep_keys: ret = %d\n", __LINE__, ret);
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
ret = assoc_helper_secinfo(priv, assoc_req);
if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret);
goto out;
}
}
@@ -452,7 +590,7 @@ lbs_pr_debug(1, "ASSOC(:%d) secinfo: ret = %d\n", __LINE__, ret);
if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
ret = assoc_helper_wpa_ie(priv, assoc_req);
if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret);
goto out;
}
}
@@ -461,7 +599,7 @@ lbs_pr_debug(1, "ASSOC(:%d) wpa_ie: ret = %d\n", __LINE__, ret);
|| test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
ret = assoc_helper_wpa_keys(priv, assoc_req);
if (ret) {
-lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
+lbs_deb_assoc("ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
goto out;
}
}
@@ -475,21 +613,23 @@ lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
ret = assoc_helper_associate(priv, assoc_req);
if (ret) {
- lbs_pr_debug(1, "ASSOC: association attempt unsuccessful: %d\n",
+ lbs_deb_assoc("ASSOC: association attempt unsuccessful: %d\n",
ret);
success = 0;
}
if (adapter->connect_status != libertas_connected) {
- lbs_pr_debug(1, "ASSOC: assoication attempt unsuccessful, "
+ lbs_deb_assoc("ASSOC: assoication attempt unsuccessful, "
"not connected.\n");
success = 0;
}
if (success) {
- lbs_pr_debug(1, "ASSOC: association attempt successful. "
+ lbs_deb_assoc("ASSOC: association attempt successful. "
"Associated to '%s' (" MAC_FMT ")\n",
- assoc_req->ssid.ssid, MAC_ARG(assoc_req->bssid));
+ escape_essid(adapter->curbssparams.ssid,
+ adapter->curbssparams.ssid_len),
+ MAC_ARG(adapter->curbssparams.bssid));
libertas_prepare_and_send_command(priv,
cmd_802_11_rssi,
0, cmd_option_waitforrsp, 0, NULL);
@@ -498,18 +638,23 @@ lbs_pr_debug(1, "ASSOC(:%d) wpa_keys: ret = %d\n", __LINE__, ret);
cmd_802_11_get_log,
0, cmd_option_waitforrsp, 0, NULL);
} else {
-
ret = -1;
}
}
out:
if (ret) {
- lbs_pr_debug(1, "ASSOC: reconfiguration attempt unsuccessful: %d\n",
+ lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
ret);
}
+
+ mutex_lock(&adapter->lock);
+ adapter->in_progress_assoc_req = NULL;
+ mutex_unlock(&adapter->lock);
kfree(assoc_req);
- LEAVE();
+
+done:
+ lbs_deb_leave(LBS_DEB_ASSOC);
}
@@ -520,9 +665,10 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
{
struct assoc_request * assoc_req;
- if (!adapter->assoc_req) {
- adapter->assoc_req = kzalloc(sizeof(struct assoc_request), GFP_KERNEL);
- if (!adapter->assoc_req) {
+ if (!adapter->pending_assoc_req) {
+ adapter->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
+ GFP_KERNEL);
+ if (!adapter->pending_assoc_req) {
lbs_pr_info("Not enough memory to allocate association"
" request!\n");
return NULL;
@@ -532,15 +678,19 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
/* Copy current configuration attributes to the association request,
* but don't overwrite any that are already set.
*/
- assoc_req = adapter->assoc_req;
+ assoc_req = adapter->pending_assoc_req;
if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- memcpy(&assoc_req->ssid, adapter->curbssparams.ssid.ssid,
- adapter->curbssparams.ssid.ssidlength);
+ memcpy(&assoc_req->ssid, &adapter->curbssparams.ssid,
+ IW_ESSID_MAX_SIZE);
+ assoc_req->ssid_len = adapter->curbssparams.ssid_len;
}
if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
assoc_req->channel = adapter->curbssparams.channel;
+ if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
+ assoc_req->band = adapter->curbssparams.band;
+
if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
assoc_req->mode = adapter->mode;
@@ -581,7 +731,7 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
assoc_req->wpa_ie_len = adapter->wpa_ie_len;
}
+ print_assoc_req(__func__, assoc_req);
+
return assoc_req;
}
-
-
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
index 2ffd82d99b3..5e9c31f0932 100644
--- a/drivers/net/wireless/libertas/assoc.h
+++ b/drivers/net/wireless/libertas/assoc.h
@@ -5,10 +5,12 @@
#include "dev.h"
-void wlan_association_worker(struct work_struct *work);
+void libertas_association_worker(struct work_struct *work);
struct assoc_request * wlan_get_association_request(wlan_adapter *adapter);
+void libertas_sync_channel(struct work_struct *work);
+
#define ASSOC_DELAY (HZ / 2)
static inline void wlan_postpone_association_work(wlan_private *priv)
{
@@ -21,9 +23,9 @@ static inline void wlan_postpone_association_work(wlan_private *priv)
static inline void wlan_cancel_association_work(wlan_private *priv)
{
cancel_delayed_work(&priv->assoc_work);
- if (priv->adapter->assoc_req) {
- kfree(priv->adapter->assoc_req);
- priv->adapter->assoc_req = NULL;
+ if (priv->adapter->pending_assoc_req) {
+ kfree(priv->adapter->pending_assoc_req);
+ priv->adapter->pending_assoc_req = NULL;
}
}
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index de9cb46a70f..13f6528abb0 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -6,7 +6,6 @@
#include <net/iw_handler.h>
#include "host.h"
#include "hostcmd.h"
-#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
@@ -26,13 +25,11 @@ static u16 commands_allowed_in_ps[] = {
* @param command the command ID
* @return TRUE or FALSE
*/
-static u8 is_command_allowed_in_ps(u16 command)
+static u8 is_command_allowed_in_ps(__le16 command)
{
- int count = sizeof(commands_allowed_in_ps)
- / sizeof(commands_allowed_in_ps[0]);
int i;
- for (i = 0; i < count; i++) {
+ for (i = 0; i < ARRAY_SIZE(commands_allowed_in_ps); i++) {
if (command == cpu_to_le16(commands_allowed_in_ps[i]))
return 1;
}
@@ -44,14 +41,13 @@ static int wlan_cmd_hw_spec(wlan_private * priv, struct cmd_ds_command *cmd)
{
struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(cmd_get_hw_spec);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
memcpy(hwspec->permanentaddr, priv->adapter->current_addr, ETH_ALEN);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -60,21 +56,19 @@ static int wlan_cmd_802_11_ps_mode(wlan_private * priv,
u16 cmd_action)
{
struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
- u16 action = cmd_action;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(cmd_802_11_ps_mode);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
- S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
+ S_DS_GEN);
psm->action = cpu_to_le16(cmd_action);
psm->multipledtim = 0;
- switch (action) {
+ switch (cmd_action) {
case cmd_subcmd_enter_ps:
- lbs_pr_debug(1, "PS command:" "SubCode- Enter PS\n");
- lbs_pr_debug(1, "locallisteninterval = %d\n",
+ lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
+ lbs_deb_cmd("locallisteninterval = %d\n",
adapter->locallisteninterval);
psm->locallisteninterval =
@@ -86,18 +80,18 @@ static int wlan_cmd_802_11_ps_mode(wlan_private * priv,
break;
case cmd_subcmd_exit_ps:
- lbs_pr_debug(1, "PS command:" "SubCode- Exit PS\n");
+ lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
break;
case cmd_subcmd_sleep_confirmed:
- lbs_pr_debug(1, "PS command: SubCode- sleep confirm\n");
+ lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
break;
default:
break;
}
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -115,8 +109,7 @@ static int wlan_cmd_802_11_inactivity_timeout(wlan_private * priv,
cmd->params.inactivity_timeout.action = cpu_to_le16(cmd_action);
if (cmd_action)
- cmd->params.inactivity_timeout.timeout =
- cpu_to_le16(*timeout);
+ cmd->params.inactivity_timeout.timeout = cpu_to_le16(*timeout);
else
cmd->params.inactivity_timeout.timeout = 0;
@@ -130,11 +123,10 @@ static int wlan_cmd_802_11_sleep_params(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_sleep_params *sp = &cmd->params.sleep_params;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- cmd->size =
- cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
- S_DS_GEN);
+ cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
+ S_DS_GEN);
cmd->command = cpu_to_le16(cmd_802_11_sleep_params);
if (cmd_action == cmd_act_get) {
@@ -151,7 +143,7 @@ static int wlan_cmd_802_11_sleep_params(wlan_private * priv,
sp->reserved = cpu_to_le16(adapter->sp.sp_reserved);
}
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -165,17 +157,16 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv,
int ret = 0;
struct assoc_request * assoc_req = pdata_buf;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(cmd_802_11_set_wep);
- cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_set_wep))
- + S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(*wep) + S_DS_GEN);
if (cmd_act == cmd_act_add) {
int i;
if (!assoc_req) {
- lbs_pr_debug(1, "Invalid association request!");
+ lbs_deb_cmd("Invalid association request!");
ret = -1;
goto done;
}
@@ -183,11 +174,10 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv,
wep->action = cpu_to_le16(cmd_act_add);
/* default tx key index */
- wep->keyindex = cpu_to_le16((u16)
- (assoc_req->wep_tx_keyidx &
- (u32)cmd_WEP_KEY_INDEX_MASK));
+ wep->keyindex = cpu_to_le16((u16)(assoc_req->wep_tx_keyidx &
+ (u32)cmd_WEP_KEY_INDEX_MASK));
- lbs_pr_debug(1, "Tx key Index: %u\n", wep->keyindex);
+ lbs_deb_cmd("Tx key Index: %u\n", le16_to_cpu(wep->keyindex));
/* Copy key types and material to host command structure */
for (i = 0; i < 4; i++) {
@@ -195,19 +185,21 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv,
switch (pkey->len) {
case KEY_LEN_WEP_40:
- wep->keytype[i] = cmd_type_wep_40_bit;
+ wep->keytype[i] =
+ cpu_to_le16(cmd_type_wep_40_bit);
memmove(&wep->keymaterial[i], pkey->key,
pkey->len);
break;
case KEY_LEN_WEP_104:
- wep->keytype[i] = cmd_type_wep_104_bit;
+ wep->keytype[i] =
+ cpu_to_le16(cmd_type_wep_104_bit);
memmove(&wep->keymaterial[i], pkey->key,
pkey->len);
break;
case 0:
break;
default:
- lbs_pr_debug(1, "Invalid WEP key %d length of %d\n",
+ lbs_deb_cmd("Invalid WEP key %d length of %d\n",
i, pkey->len);
ret = -1;
goto done;
@@ -219,36 +211,39 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv,
wep->action = cpu_to_le16(cmd_act_remove);
/* default tx key index */
- wep->keyindex = cpu_to_le16((u16)
- (adapter->wep_tx_keyidx &
- (u32)cmd_WEP_KEY_INDEX_MASK));
+ wep->keyindex = cpu_to_le16((u16)(adapter->wep_tx_keyidx &
+ (u32)cmd_WEP_KEY_INDEX_MASK));
}
ret = 0;
done:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
struct cmd_ds_command *cmd,
- u16 cmd_action)
+ u16 cmd_action,
+ void * pdata_buf)
{
struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn;
- wlan_adapter *adapter = priv->adapter;
+ u32 * enable = pdata_buf;
+
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(cmd_802_11_enable_rsn);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_enable_rsn) +
- S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN);
penableRSN->action = cpu_to_le16(cmd_action);
- if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
- penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
- } else {
- penableRSN->enable = cpu_to_le16(cmd_disable_rsn);
+
+ if (cmd_action == cmd_act_set) {
+ if (*enable)
+ penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
+ else
+ penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
}
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -259,14 +254,12 @@ static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
if (pkey->flags & KEY_INFO_WPA_ENABLED) {
- pkeyparamset->keyinfo = cpu_to_le16(KEY_INFO_WPA_ENABLED);
- } else {
- pkeyparamset->keyinfo = cpu_to_le16(!KEY_INFO_WPA_ENABLED);
+ pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
}
-
if (pkey->flags & KEY_INFO_WPA_UNICAST) {
pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
- } else if (pkey->flags & KEY_INFO_WPA_MCAST) {
+ }
+ if (pkey->flags & KEY_INFO_WPA_MCAST) {
pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
}
@@ -284,46 +277,45 @@ static int wlan_cmd_802_11_key_material(wlan_private * priv,
u16 cmd_action,
u32 cmd_oid, void *pdata_buf)
{
- wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_key_material *pkeymaterial =
&cmd->params.keymaterial;
+ struct assoc_request * assoc_req = pdata_buf;
int ret = 0;
int index = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(cmd_802_11_key_material);
pkeymaterial->action = cpu_to_le16(cmd_action);
if (cmd_action == cmd_act_get) {
- cmd->size = cpu_to_le16( S_DS_GEN
- + sizeof (pkeymaterial->action));
+ cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
ret = 0;
goto done;
}
memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
- if (adapter->wpa_unicast_key.len) {
+ if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
set_one_wpa_key(&pkeymaterial->keyParamSet[index],
- &adapter->wpa_unicast_key);
+ &assoc_req->wpa_unicast_key);
index++;
}
- if (adapter->wpa_mcast_key.len) {
+ if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
set_one_wpa_key(&pkeymaterial->keyParamSet[index],
- &adapter->wpa_mcast_key);
+ &assoc_req->wpa_mcast_key);
index++;
}
cmd->size = cpu_to_le16( S_DS_GEN
- + sizeof (pkeymaterial->action)
- + index * sizeof(struct MrvlIEtype_keyParamSet));
+ + sizeof (pkeymaterial->action)
+ + (index * sizeof(struct MrvlIEtype_keyParamSet)));
ret = 0;
done:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -354,8 +346,7 @@ static int wlan_cmd_802_11_get_stat(wlan_private * priv,
{
cmd->command = cpu_to_le16(cmd_802_11_get_stat);
cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) +
- S_DS_GEN);
+ cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN);
return 0;
}
@@ -369,14 +360,12 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
u8 ucTemp;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- lbs_pr_debug(1, "SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
+ lbs_deb_cmd("SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
cmd->command = cpu_to_le16(cmd_802_11_snmp_mib);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_snmp_mib) +
- S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(*pSNMPMIB) + S_DS_GEN);
switch (cmd_oid) {
case OID_802_11_INFRASTRUCTURE_MODE:
@@ -407,7 +396,7 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
pSNMPMIB->querytype = cmd_act_set;
pSNMPMIB->bufsize = sizeof(u16);
ulTemp = *(u32 *)pdata_buf;
- *((unsigned short *)(pSNMPMIB->value)) =
+ *((__le16 *)(pSNMPMIB->value)) =
cpu_to_le16((u16) ulTemp);
}
break;
@@ -420,15 +409,12 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
pSNMPMIB->oid = cpu_to_le16((u16) fragthresh_i);
if (cmd_action == cmd_act_get) {
- pSNMPMIB->querytype =
- cpu_to_le16(cmd_act_get);
+ pSNMPMIB->querytype = cpu_to_le16(cmd_act_get);
} else if (cmd_action == cmd_act_set) {
- pSNMPMIB->querytype =
- cpu_to_le16(cmd_act_set);
- pSNMPMIB->bufsize =
- cpu_to_le16(sizeof(u16));
+ pSNMPMIB->querytype = cpu_to_le16(cmd_act_set);
+ pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
ulTemp = *((u32 *) pdata_buf);
- *((unsigned short *)(pSNMPMIB->value)) =
+ *((__le16 *)(pSNMPMIB->value)) =
cpu_to_le16((u16) ulTemp);
}
@@ -443,16 +429,12 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
pSNMPMIB->oid = le16_to_cpu((u16) rtsthresh_i);
if (cmd_action == cmd_act_get) {
- pSNMPMIB->querytype =
- cpu_to_le16(cmd_act_get);
+ pSNMPMIB->querytype = cpu_to_le16(cmd_act_get);
} else if (cmd_action == cmd_act_set) {
- pSNMPMIB->querytype =
- cpu_to_le16(cmd_act_set);
- pSNMPMIB->bufsize =
- cpu_to_le16(sizeof(u16));
- ulTemp = *((u32 *)
- pdata_buf);
- *(unsigned short *)(pSNMPMIB->value) =
+ pSNMPMIB->querytype = cpu_to_le16(cmd_act_set);
+ pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
+ ulTemp = *((u32 *)pdata_buf);
+ *(__le16 *)(pSNMPMIB->value) =
cpu_to_le16((u16) ulTemp);
}
@@ -462,13 +444,11 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
pSNMPMIB->oid = cpu_to_le16((u16) short_retrylim_i);
if (cmd_action == cmd_act_get) {
- pSNMPMIB->querytype =
- cpu_to_le16(cmd_act_get);
+ pSNMPMIB->querytype = cpu_to_le16(cmd_act_get);
} else if (cmd_action == cmd_act_set) {
- pSNMPMIB->querytype =
- cpu_to_le16(cmd_act_set);
+ pSNMPMIB->querytype = cpu_to_le16(cmd_act_set);
pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
- *((unsigned short *)(pSNMPMIB->value)) =
+ *((__le16 *)(pSNMPMIB->value)) =
cpu_to_le16((u16) adapter->txretrycount);
}
@@ -477,16 +457,18 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
break;
}
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"SNMP_CMD: command=0x%x, size=0x%x, seqnum=0x%x, result=0x%x\n",
- cmd->command, cmd->size, cmd->seqnum, cmd->result);
+ le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
+ le16_to_cpu(cmd->seqnum), le16_to_cpu(cmd->result));
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"SNMP_CMD: action=0x%x, oid=0x%x, oidsize=0x%x, value=0x%x\n",
- pSNMPMIB->querytype, pSNMPMIB->oid, pSNMPMIB->bufsize,
- *(u16 *) pSNMPMIB->value);
+ le16_to_cpu(pSNMPMIB->querytype), le16_to_cpu(pSNMPMIB->oid),
+ le16_to_cpu(pSNMPMIB->bufsize),
+ le16_to_cpu(*(__le16 *) pSNMPMIB->value));
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -495,10 +477,9 @@ static int wlan_cmd_802_11_radio_control(wlan_private * priv,
int cmd_action)
{
wlan_adapter *adapter = priv->adapter;
- struct cmd_ds_802_11_radio_control *pradiocontrol =
- &cmd->params.radio;
+ struct cmd_ds_802_11_radio_control *pradiocontrol = &cmd->params.radio;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->size =
cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control)) +
@@ -527,7 +508,7 @@ static int wlan_cmd_802_11_radio_control(wlan_private * priv,
else
pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -538,16 +519,16 @@ static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
struct cmd_ds_802_11_rf_tx_power *prtp = &cmd->params.txp;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->size =
- cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) +
- S_DS_GEN);
+ cpu_to_le16((sizeof(struct cmd_ds_802_11_rf_tx_power)) + S_DS_GEN);
cmd->command = cpu_to_le16(cmd_802_11_rf_tx_power);
- prtp->action = cmd_action;
+ prtp->action = cpu_to_le16(cmd_action);
- lbs_pr_debug(1, "RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n", cmd->size,
- cmd->command, prtp->action);
+ lbs_deb_cmd("RF_TX_POWER_CMD: size:%d cmd:0x%x Act:%d\n",
+ le16_to_cpu(cmd->size), le16_to_cpu(cmd->command),
+ le16_to_cpu(prtp->action));
switch (cmd_action) {
case cmd_act_tx_power_opt_get:
@@ -557,14 +538,12 @@ static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
case cmd_act_tx_power_opt_set_high:
prtp->action = cpu_to_le16(cmd_act_set);
- prtp->currentlevel =
- cpu_to_le16(cmd_act_tx_power_index_high);
+ prtp->currentlevel = cpu_to_le16(cmd_act_tx_power_index_high);
break;
case cmd_act_tx_power_opt_set_mid:
prtp->action = cpu_to_le16(cmd_act_set);
- prtp->currentlevel =
- cpu_to_le16(cmd_act_tx_power_index_mid);
+ prtp->currentlevel = cpu_to_le16(cmd_act_tx_power_index_mid);
break;
case cmd_act_tx_power_opt_set_low:
@@ -572,7 +551,8 @@ static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
prtp->currentlevel = cpu_to_le16(*((u16 *) pdata_buf));
break;
}
- LEAVE();
+
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -583,15 +563,12 @@ static int wlan_cmd_802_11_rf_antenna(wlan_private * priv,
struct cmd_ds_802_11_rf_antenna *rant = &cmd->params.rant;
cmd->command = cpu_to_le16(cmd_802_11_rf_antenna);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_antenna) +
- S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_antenna) +
+ S_DS_GEN);
rant->action = cpu_to_le16(cmd_action);
- if ((cmd_action == cmd_act_set_rx) ||
- (cmd_action == cmd_act_set_tx)) {
- rant->antennamode =
- cpu_to_le16((u16) (*(u32 *) pdata_buf));
+ if ((cmd_action == cmd_act_set_rx) || (cmd_action == cmd_act_set_tx)) {
+ rant->antennamode = cpu_to_le16((u16) (*(u32 *) pdata_buf));
}
return 0;
@@ -610,13 +587,13 @@ static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
+ S_DS_GEN);
cmd->command = cpu_to_le16(cmd_802_11_rate_adapt_rateset);
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- rateadapt->action = cmd_action;
- rateadapt->enablehwauto = adapter->enablehwauto;
- rateadapt->bitmap = adapter->ratebitmap;
+ rateadapt->action = cpu_to_le16(cmd_action);
+ rateadapt->enablehwauto = cpu_to_le16(adapter->enablehwauto);
+ rateadapt->bitmap = cpu_to_le16(adapter->ratebitmap);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -626,12 +603,10 @@ static int wlan_cmd_802_11_data_rate(wlan_private * priv,
{
struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate;
wlan_adapter *adapter = priv->adapter;
- u16 action = cmd_action;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
S_DS_GEN);
cmd->command = cpu_to_le16(cmd_802_11_data_rate);
@@ -640,15 +615,15 @@ static int wlan_cmd_802_11_data_rate(wlan_private * priv,
pdatarate->action = cpu_to_le16(cmd_action);
- if (action == cmd_act_set_tx_fix_rate) {
+ if (cmd_action == cmd_act_set_tx_fix_rate) {
pdatarate->datarate[0] = libertas_data_rate_to_index(adapter->datarate);
- lbs_pr_debug(1, "Setting FW for fixed rate 0x%02X\n",
+ lbs_deb_cmd("Setting FW for fixed rate 0x%02X\n",
adapter->datarate);
- } else if (action == cmd_act_set_tx_auto) {
- lbs_pr_debug(1, "Setting FW for AUTO rate\n");
+ } else if (cmd_action == cmd_act_set_tx_auto) {
+ lbs_deb_cmd("Setting FW for AUTO rate\n");
}
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -659,8 +634,7 @@ static int wlan_cmd_mac_multicast_adr(wlan_private * priv,
struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
wlan_adapter *adapter = priv->adapter;
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
S_DS_GEN);
cmd->command = cpu_to_le16(cmd_mac_multicast_adr);
@@ -680,8 +654,8 @@ static int wlan_cmd_802_11_rf_channel(wlan_private * priv,
struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
cmd->command = cpu_to_le16(cmd_802_11_rf_channel);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel)
- + S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
+ S_DS_GEN);
if (option == cmd_opt_802_11_rf_channel_set) {
rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
@@ -698,9 +672,8 @@ static int wlan_cmd_802_11_rssi(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
cmd->command = cpu_to_le16(cmd_802_11_rssi);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
- cmd->params.rssi.N = priv->adapter->bcn_avg_factor;
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
+ cmd->params.rssi.N = cpu_to_le16(priv->adapter->bcn_avg_factor);
/* reset Beacon SNR/NF/RSSI values */
adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
@@ -719,7 +692,7 @@ static int wlan_cmd_reg_access(wlan_private * priv,
{
struct wlan_offset_value *offval;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
offval = (struct wlan_offset_value *)pdata_buf;
@@ -729,9 +702,8 @@ static int wlan_cmd_reg_access(wlan_private * priv,
struct cmd_ds_mac_reg_access *macreg;
cmdptr->size =
- cpu_to_le16(sizeof
- (struct cmd_ds_mac_reg_access)
- + S_DS_GEN);
+ cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
+ + S_DS_GEN);
macreg =
(struct cmd_ds_mac_reg_access *)&cmdptr->params.
macreg;
@@ -785,7 +757,7 @@ static int wlan_cmd_reg_access(wlan_private * priv,
break;
}
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -796,8 +768,7 @@ static int wlan_cmd_802_11_mac_address(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
cmd->command = cpu_to_le16(cmd_802_11_mac_address);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) +
S_DS_GEN);
cmd->result = 0;
@@ -818,12 +789,11 @@ static int wlan_cmd_802_11_eeprom_access(wlan_private * priv,
{
struct wlan_ioctl_regrdwr *ea = pdata_buf;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(cmd_802_11_eeprom_access);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
- S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) +
+ S_DS_GEN);
cmd->result = 0;
cmd->params.rdeeprom.action = cpu_to_le16(ea->action);
@@ -839,11 +809,10 @@ static int wlan_cmd_bt_access(wlan_private * priv,
u16 cmd_action, void *pdata_buf)
{
struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
- lbs_pr_debug(1, "BT CMD(%d)\n", cmd_action);
+ lbs_deb_cmd("BT CMD(%d)\n", cmd_action);
cmd->command = cpu_to_le16(cmd_bt_access);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access)
- + S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
cmd->result = 0;
bt_access->action = cpu_to_le16(cmd_action);
@@ -861,6 +830,11 @@ static int wlan_cmd_bt_access(wlan_private * priv,
break;
case cmd_act_bt_access_reset:
break;
+ case cmd_act_bt_access_set_invert:
+ bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
+ break;
+ case cmd_act_bt_access_get_invert:
+ break;
default:
break;
}
@@ -872,11 +846,10 @@ static int wlan_cmd_fwt_access(wlan_private * priv,
u16 cmd_action, void *pdata_buf)
{
struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
- lbs_pr_debug(1, "FWT CMD(%d)\n", cmd_action);
+ lbs_deb_cmd("FWT CMD(%d)\n", cmd_action);
cmd->command = cpu_to_le16(cmd_fwt_access);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access)
- + S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
cmd->result = 0;
if (pdata_buf)
@@ -894,11 +867,10 @@ static int wlan_cmd_mesh_access(wlan_private * priv,
u16 cmd_action, void *pdata_buf)
{
struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh;
- lbs_pr_debug(1, "FWT CMD(%d)\n", cmd_action);
+ lbs_deb_cmd("FWT CMD(%d)\n", cmd_action);
cmd->command = cpu_to_le16(cmd_mesh_access);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access)
- + S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN);
cmd->result = 0;
if (pdata_buf)
@@ -916,23 +888,23 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u
unsigned long flags;
struct cmd_ds_command *cmdptr;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
if (!cmdnode) {
- lbs_pr_debug(1, "QUEUE_CMD: cmdnode is NULL\n");
+ lbs_deb_cmd("QUEUE_CMD: cmdnode is NULL\n");
goto done;
}
cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
if (!cmdptr) {
- lbs_pr_debug(1, "QUEUE_CMD: cmdptr is NULL\n");
+ lbs_deb_cmd("QUEUE_CMD: cmdptr is NULL\n");
goto done;
}
/* Exit_PS command needs to be queued in the header always. */
if (cmdptr->command == cmd_802_11_ps_mode) {
struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode;
- if (psm->action == cmd_subcmd_exit_ps) {
+ if (psm->action == cpu_to_le16(cmd_subcmd_exit_ps)) {
if (adapter->psstate != PS_STATE_FULL_POWER)
addtail = 0;
}
@@ -948,13 +920,12 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u
spin_unlock_irqrestore(&adapter->driver_lock, flags);
- lbs_pr_debug(1, "QUEUE_CMD: Inserted node=%p, cmd=0x%x in cmdpendingq\n",
+ lbs_deb_cmd("QUEUE_CMD: Inserted node=%p, cmd=0x%x in cmdpendingq\n",
cmdnode,
- ((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command);
+ le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command));
done:
- LEAVE();
- return;
+ lbs_deb_leave(LBS_DEB_CMD);
}
/*
@@ -974,10 +945,10 @@ static int DownloadcommandToStation(wlan_private * priv,
u16 cmdsize;
u16 command;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
if (!adapter || !cmdnode) {
- lbs_pr_debug(1, "DNLD_CMD: adapter = %p, cmdnode = %p\n",
+ lbs_deb_cmd("DNLD_CMD: adapter = %p, cmdnode = %p\n",
adapter, cmdnode);
if (cmdnode) {
spin_lock_irqsave(&adapter->driver_lock, flags);
@@ -993,7 +964,7 @@ static int DownloadcommandToStation(wlan_private * priv,
spin_lock_irqsave(&adapter->driver_lock, flags);
if (!cmdptr || !cmdptr->size) {
- lbs_pr_debug(1, "DNLD_CMD: cmdptr is Null or cmd size is Zero, "
+ lbs_deb_cmd("DNLD_CMD: cmdptr is Null or cmd size is Zero, "
"Not sending\n");
__libertas_cleanup_and_insert_cmd(priv, cmdnode);
spin_unlock_irqrestore(&adapter->driver_lock, flags);
@@ -1004,8 +975,8 @@ static int DownloadcommandToStation(wlan_private * priv,
adapter->cur_cmd = cmdnode;
adapter->cur_cmd_retcode = 0;
spin_unlock_irqrestore(&adapter->driver_lock, flags);
- lbs_pr_debug(1, "DNLD_CMD:: Before download, size of cmd = %d\n",
- cmdptr->size);
+ lbs_deb_cmd("DNLD_CMD:: Before download, size of cmd = %d\n",
+ le16_to_cpu(cmdptr->size));
cmdsize = cmdptr->size;
@@ -1014,10 +985,10 @@ static int DownloadcommandToStation(wlan_private * priv,
cmdnode->cmdwaitqwoken = 0;
cmdsize = cpu_to_le16(cmdsize);
- ret = libertas_sbi_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
+ ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
if (ret != 0) {
- lbs_pr_debug(1, "DNLD_CMD: Host to Card failed\n");
+ lbs_deb_cmd("DNLD_CMD: Host to Card failed\n");
spin_lock_irqsave(&adapter->driver_lock, flags);
__libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
adapter->cur_cmd = NULL;
@@ -1026,12 +997,11 @@ static int DownloadcommandToStation(wlan_private * priv,
goto done;
}
- lbs_pr_debug(1, "DNLD_CMD: Sent command 0x%x @ %lu\n", command, jiffies);
+ lbs_deb_cmd("DNLD_CMD: Sent command 0x%x @ %lu\n", command, jiffies);
lbs_dbg_hex("DNLD_CMD: command", cmdnode->bufvirtualaddr, cmdsize);
/* Setup the timer after transmit command */
- if (command == cmd_802_11_scan
- || command == cmd_802_11_authenticate
+ if (command == cmd_802_11_scan || command == cmd_802_11_authenticate
|| command == cmd_802_11_associate)
mod_timer(&adapter->command_timer, jiffies + (10*HZ));
else
@@ -1039,8 +1009,8 @@ static int DownloadcommandToStation(wlan_private * priv,
ret = 0;
- done:
- LEAVE();
+done:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -1049,17 +1019,16 @@ static int wlan_cmd_mac_control(wlan_private * priv,
{
struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(cmd_mac_control);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
mac->action = cpu_to_le16(priv->adapter->currentpacketfilter);
- lbs_pr_debug(1, "wlan_cmd_mac_control(): action=0x%X size=%d\n",
- mac->action, cmd->size);
+ lbs_deb_cmd("wlan_cmd_mac_control(): action=0x%X size=%d\n",
+ le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -1093,17 +1062,17 @@ int libertas_set_radio_control(wlan_private * priv)
{
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_radio_control,
cmd_act_set,
cmd_option_waitforrsp, 0, NULL);
- lbs_pr_debug(1, "RADIO_SET: on or off: 0x%X, preamble = 0x%X\n",
+ lbs_deb_cmd("RADIO_SET: on or off: 0x%X, preamble = 0x%X\n",
priv->adapter->radioon, priv->adapter->preamble);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -1111,16 +1080,16 @@ int libertas_set_mac_packet_filter(wlan_private * priv)
{
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- lbs_pr_debug(1, "libertas_set_mac_packet_filter value = %x\n",
+ lbs_deb_cmd("libertas_set_mac_packet_filter value = %x\n",
priv->adapter->currentpacketfilter);
/* Send MAC control command to station */
ret = libertas_prepare_and_send_command(priv,
cmd_mac_control, 0, 0, 0, NULL);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -1146,16 +1115,16 @@ int libertas_prepare_and_send_command(wlan_private * priv,
struct cmd_ds_command *cmdptr;
unsigned long flags;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
if (!adapter) {
- lbs_pr_debug(1, "PREP_CMD: adapter is Null\n");
+ lbs_deb_cmd("PREP_CMD: adapter is Null\n");
ret = -1;
goto done;
}
if (adapter->surpriseremoved) {
- lbs_pr_debug(1, "PREP_CMD: Card is Removed\n");
+ lbs_deb_cmd("PREP_CMD: Card is Removed\n");
ret = -1;
goto done;
}
@@ -1163,7 +1132,7 @@ int libertas_prepare_and_send_command(wlan_private * priv,
cmdnode = libertas_get_free_cmd_ctrl_node(priv);
if (cmdnode == NULL) {
- lbs_pr_debug(1, "PREP_CMD: No free cmdnode\n");
+ lbs_deb_cmd("PREP_CMD: No free cmdnode\n");
/* Wake up main thread to execute next command */
wake_up_interruptible(&priv->mainthread.waitq);
@@ -1175,11 +1144,11 @@ int libertas_prepare_and_send_command(wlan_private * priv,
cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
- lbs_pr_debug(1, "PREP_CMD: Val of cmd ptr=%p, command=0x%X\n",
+ lbs_deb_cmd("PREP_CMD: Val of cmd ptr=%p, command=0x%X\n",
cmdptr, cmd_no);
if (!cmdptr) {
- lbs_pr_debug(1, "PREP_CMD: bufvirtualaddr of cmdnode is NULL\n");
+ lbs_deb_cmd("PREP_CMD: bufvirtualaddr of cmdnode is NULL\n");
libertas_cleanup_and_insert_cmd(priv, cmdnode);
ret = -1;
goto done;
@@ -1189,7 +1158,7 @@ int libertas_prepare_and_send_command(wlan_private * priv,
adapter->seqnum++;
cmdptr->seqnum = cpu_to_le16(adapter->seqnum);
- cmdptr->command = cmd_no;
+ cmdptr->command = cpu_to_le16(cmd_no);
cmdptr->result = 0;
switch (cmd_no) {
@@ -1298,13 +1267,13 @@ int libertas_prepare_and_send_command(wlan_private * priv,
break;
case cmd_802_11_enable_rsn:
- ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action);
+ ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
+ pdata_buf);
break;
case cmd_802_11_key_material:
- ret = wlan_cmd_802_11_key_material(priv, cmdptr,
- cmd_action, cmd_oid,
- pdata_buf);
+ ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
+ cmd_oid, pdata_buf);
break;
case cmd_802_11_pairwise_tsc:
@@ -1325,9 +1294,8 @@ int libertas_prepare_and_send_command(wlan_private * priv,
case cmd_802_11_get_afc:
cmdptr->command = cpu_to_le16(cmd_no);
- cmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
- S_DS_GEN);
+ cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
+ S_DS_GEN);
memmove(&cmdptr->params.afc,
pdata_buf, sizeof(struct cmd_ds_802_11_afc));
@@ -1406,29 +1374,26 @@ int libertas_prepare_and_send_command(wlan_private * priv,
case cmd_get_tsf:
cmdptr->command = cpu_to_le16(cmd_get_tsf);
- cmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_get_tsf)
- + S_DS_GEN);
+ cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
+ S_DS_GEN);
ret = 0;
break;
case cmd_802_11_tx_rate_query:
- cmdptr->command =
- cpu_to_le16(cmd_802_11_tx_rate_query);
- cmdptr->size =
- cpu_to_le16(sizeof(struct cmd_tx_rate_query) +
- S_DS_GEN);
+ cmdptr->command = cpu_to_le16(cmd_802_11_tx_rate_query);
+ cmdptr->size = cpu_to_le16(sizeof(struct cmd_tx_rate_query) +
+ S_DS_GEN);
adapter->txrate = 0;
ret = 0;
break;
default:
- lbs_pr_debug(1, "PREP_CMD: unknown command- %#x\n", cmd_no);
+ lbs_deb_cmd("PREP_CMD: unknown command- %#x\n", cmd_no);
ret = -1;
break;
}
/* return error, since the command preparation failed */
if (ret != 0) {
- lbs_pr_debug(1, "PREP_CMD: command preparation failed\n");
+ lbs_deb_cmd("PREP_CMD: command preparation failed\n");
libertas_cleanup_and_insert_cmd(priv, cmdnode);
ret = -1;
goto done;
@@ -1441,7 +1406,7 @@ int libertas_prepare_and_send_command(wlan_private * priv,
wake_up_interruptible(&priv->mainthread.waitq);
if (wait_option & cmd_option_waitforrsp) {
- lbs_pr_debug(1, "PREP_CMD: Wait for CMD response\n");
+ lbs_deb_cmd("PREP_CMD: Wait for CMD response\n");
might_sleep();
wait_event_interruptible(cmdnode->cmdwait_q,
cmdnode->cmdwaitqwoken);
@@ -1449,7 +1414,7 @@ int libertas_prepare_and_send_command(wlan_private * priv,
spin_lock_irqsave(&adapter->driver_lock, flags);
if (adapter->cur_cmd_retcode) {
- lbs_pr_debug(1, "PREP_CMD: command failed with return code=%d\n",
+ lbs_deb_cmd("PREP_CMD: command failed with return code=%d\n",
adapter->cur_cmd_retcode);
adapter->cur_cmd_retcode = 0;
ret = -1;
@@ -1457,9 +1422,10 @@ int libertas_prepare_and_send_command(wlan_private * priv,
spin_unlock_irqrestore(&adapter->driver_lock, flags);
done:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
+EXPORT_SYMBOL_GPL(libertas_prepare_and_send_command);
/**
* @brief This function allocates the command buffer and link
@@ -1477,33 +1443,29 @@ int libertas_allocate_cmd_buffer(wlan_private * priv)
u8 *ptempvirtualaddr;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
/* Allocate and initialize cmdCtrlNode */
ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
- if (!(tempcmd_array = kmalloc(ulbufsize, GFP_KERNEL))) {
- lbs_pr_debug(1,
+ if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) {
+ lbs_deb_cmd(
"ALLOC_CMD_BUF: failed to allocate tempcmd_array\n");
ret = -1;
goto done;
}
-
adapter->cmd_array = tempcmd_array;
- memset(adapter->cmd_array, 0, ulbufsize);
/* Allocate and initialize command buffers */
ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
- if (!(ptempvirtualaddr = kmalloc(ulbufsize, GFP_KERNEL))) {
- lbs_pr_debug(1,
+ if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) {
+ lbs_deb_cmd(
"ALLOC_CMD_BUF: ptempvirtualaddr: out of memory\n");
ret = -1;
goto done;
}
- memset(ptempvirtualaddr, 0, ulbufsize);
-
/* Update command buffer virtual */
tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr;
}
@@ -1514,8 +1476,9 @@ int libertas_allocate_cmd_buffer(wlan_private * priv)
}
ret = 0;
- done:
- LEAVE();
+
+done:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -1527,16 +1490,16 @@ int libertas_allocate_cmd_buffer(wlan_private * priv)
*/
int libertas_free_cmd_buffer(wlan_private * priv)
{
- u32 ulbufsize;
+ u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */
unsigned int i;
struct cmd_ctrl_node *tempcmd_array;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
/* need to check if cmd array is allocated or not */
if (adapter->cmd_array == NULL) {
- lbs_pr_debug(1, "FREE_CMD_BUF: cmd_array is Null\n");
+ lbs_deb_cmd("FREE_CMD_BUF: cmd_array is Null\n");
goto done;
}
@@ -1546,7 +1509,7 @@ int libertas_free_cmd_buffer(wlan_private * priv)
ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
if (tempcmd_array[i].bufvirtualaddr) {
- lbs_pr_debug(1, "Free all the array\n");
+ lbs_deb_cmd("Free all the array\n");
kfree(tempcmd_array[i].bufvirtualaddr);
tempcmd_array[i].bufvirtualaddr = NULL;
}
@@ -1554,13 +1517,13 @@ int libertas_free_cmd_buffer(wlan_private * priv)
/* Release cmd_ctrl_node */
if (adapter->cmd_array) {
- lbs_pr_debug(1, "Free cmd_array\n");
+ lbs_deb_cmd("Free cmd_array\n");
kfree(adapter->cmd_array);
adapter->cmd_array = NULL;
}
done:
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
@@ -1586,16 +1549,18 @@ struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv)
tempnode = (struct cmd_ctrl_node *)adapter->cmdfreeq.next;
list_del((struct list_head *)tempnode);
} else {
- lbs_pr_debug(1, "GET_CMD_NODE: cmd_ctrl_node is not available\n");
+ lbs_deb_cmd("GET_CMD_NODE: cmd_ctrl_node is not available\n");
tempnode = NULL;
}
spin_unlock_irqrestore(&adapter->driver_lock, flags);
if (tempnode) {
+ /*
lbs_pr_debug(3, "GET_CMD_NODE: cmdCtrlNode available\n");
lbs_pr_debug(3, "GET_CMD_NODE: cmdCtrlNode Address = %p\n",
tempnode);
+ */
cleanup_cmdnode(tempnode);
}
@@ -1638,7 +1603,7 @@ void libertas_set_cmd_ctrl_node(wlan_private * priv,
struct cmd_ctrl_node *ptempnode,
u32 cmd_oid, u16 wait_option, void *pdata_buf)
{
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
if (!ptempnode)
return;
@@ -1647,7 +1612,7 @@ void libertas_set_cmd_ctrl_node(wlan_private * priv,
ptempnode->wait_option = wait_option;
ptempnode->pdata_buf = pdata_buf;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
}
/**
@@ -1666,7 +1631,7 @@ int libertas_execute_next_command(wlan_private * priv)
unsigned long flags;
int ret = 0;
- lbs_pr_debug(1, "libertas_execute_next_command\n");
+ lbs_deb_enter(LBS_DEB_CMD);
spin_lock_irqsave(&adapter->driver_lock, flags);
@@ -1685,23 +1650,24 @@ int libertas_execute_next_command(wlan_private * priv)
spin_unlock_irqrestore(&adapter->driver_lock, flags);
if (cmdnode) {
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"EXEC_NEXT_CMD: Got next command from cmdpendingq\n");
cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
if (is_command_allowed_in_ps(cmdptr->command)) {
- if ((adapter->psstate == PS_STATE_SLEEP)
- || (adapter->psstate == PS_STATE_PRE_SLEEP)
- ) {
- lbs_pr_debug(1,
+ if ((adapter->psstate == PS_STATE_SLEEP) ||
+ (adapter->psstate == PS_STATE_PRE_SLEEP)) {
+ lbs_deb_cmd(
"EXEC_NEXT_CMD: Cannot send cmd 0x%x in psstate %d\n",
- cmdptr->command, adapter->psstate);
+ le16_to_cpu(cmdptr->command),
+ adapter->psstate);
ret = -1;
goto done;
}
- lbs_pr_debug(1, "EXEC_NEXT_CMD: OK to send command "
+ lbs_deb_cmd("EXEC_NEXT_CMD: OK to send command "
"0x%x in psstate %d\n",
- cmdptr->command, adapter->psstate);
+ le16_to_cpu(cmdptr->command),
+ adapter->psstate);
} else if (adapter->psstate != PS_STATE_FULL_POWER) {
/*
* 1. Non-PS command:
@@ -1737,12 +1703,12 @@ int libertas_execute_next_command(wlan_private * priv)
struct cmd_ds_802_11_ps_mode *psm =
&cmdptr->params.psmode;
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"EXEC_NEXT_CMD: PS cmd- action=0x%x\n",
psm->action);
if (psm->action !=
cpu_to_le16(cmd_subcmd_exit_ps)) {
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"EXEC_NEXT_CMD: Ignore Enter PS cmd\n");
list_del((struct list_head *)cmdnode);
libertas_cleanup_and_insert_cmd(priv, cmdnode);
@@ -1751,10 +1717,9 @@ int libertas_execute_next_command(wlan_private * priv)
goto done;
}
- if ((adapter->psstate == PS_STATE_SLEEP)
- || (adapter->psstate == PS_STATE_PRE_SLEEP)
- ) {
- lbs_pr_debug(1,
+ if ((adapter->psstate == PS_STATE_SLEEP) ||
+ (adapter->psstate == PS_STATE_PRE_SLEEP)) {
+ lbs_deb_cmd(
"EXEC_NEXT_CMD: Ignore ExitPS cmd in sleep\n");
list_del((struct list_head *)cmdnode);
libertas_cleanup_and_insert_cmd(priv, cmdnode);
@@ -1764,13 +1729,13 @@ int libertas_execute_next_command(wlan_private * priv)
goto done;
}
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"EXEC_NEXT_CMD: Sending Exit_PS down...\n");
}
}
list_del((struct list_head *)cmdnode);
- lbs_pr_debug(1, "EXEC_NEXT_CMD: Sending 0x%04X command\n",
- cmdptr->command);
+ lbs_deb_cmd("EXEC_NEXT_CMD: Sending 0x%04X command\n",
+ le16_to_cpu(cmdptr->command));
DownloadcommandToStation(priv, cmdnode);
} else {
/*
@@ -1780,18 +1745,18 @@ int libertas_execute_next_command(wlan_private * priv)
if ((adapter->psmode != wlan802_11powermodecam) &&
(adapter->psstate == PS_STATE_FULL_POWER) &&
(adapter->connect_status == libertas_connected)) {
- if (adapter->secinfo.WPAenabled
- || adapter->secinfo.WPA2enabled) {
+ if (adapter->secinfo.WPAenabled ||
+ adapter->secinfo.WPA2enabled) {
/* check for valid WPA group keys */
- if (adapter->wpa_mcast_key.len
- || adapter->wpa_unicast_key.len) {
- lbs_pr_debug(1,
+ if (adapter->wpa_mcast_key.len ||
+ adapter->wpa_unicast_key.len) {
+ lbs_deb_cmd(
"EXEC_NEXT_CMD: WPA enabled and GTK_SET"
" go back to PS_SLEEP");
libertas_ps_sleep(priv, 0);
}
} else {
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"EXEC_NEXT_CMD: command PendQ is empty,"
" go back to PS_SLEEP");
libertas_ps_sleep(priv, 0);
@@ -1801,6 +1766,7 @@ int libertas_execute_next_command(wlan_private * priv)
ret = 0;
done:
+ lbs_deb_leave(LBS_DEB_CMD);
return ret;
}
@@ -1809,7 +1775,7 @@ void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
union iwreq_data iwrq;
u8 buf[50];
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
memset(&iwrq, 0, sizeof(union iwreq_data));
memset(buf, 0, sizeof(buf));
@@ -1819,15 +1785,13 @@ void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
/* Send Event to upper layer */
- lbs_pr_debug(1, "Event Indication string = %s\n",
- (char *)buf);
- lbs_pr_debug(1, "Event Indication String length = %d\n", iwrq.data.length);
+ lbs_deb_cmd("Event Indication string = %s\n", (char *)buf);
+ lbs_deb_cmd("Event Indication String length = %d\n", iwrq.data.length);
- lbs_pr_debug(1, "Sending wireless event IWEVCUSTOM for %s\n", str);
- wireless_send_event(priv->wlan_dev.netdev, IWEVCUSTOM, &iwrq, buf);
+ lbs_deb_cmd("Sending wireless event IWEVCUSTOM for %s\n", str);
+ wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
- LEAVE();
- return;
+ lbs_deb_leave(LBS_DEB_CMD);
}
static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
@@ -1836,19 +1800,19 @@ static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
wlan_adapter *adapter = priv->adapter;
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- lbs_pr_debug(1, "SEND_SLEEPC_CMD: Before download, size of cmd = %d\n",
+ lbs_deb_cmd("SEND_SLEEPC_CMD: Before download, size of cmd = %d\n",
size);
lbs_dbg_hex("SEND_SLEEPC_CMD: Sleep confirm command", cmdptr, size);
- ret = libertas_sbi_host_to_card(priv, MVMS_CMD, cmdptr, size);
- priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+ ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
+ priv->dnld_sent = DNLD_RES_RECEIVED;
spin_lock_irqsave(&adapter->driver_lock, flags);
if (adapter->intcounter || adapter->currenttxskb)
- lbs_pr_debug(1, "SEND_SLEEPC_CMD: intcounter=%d currenttxskb=%p\n",
+ lbs_deb_cmd("SEND_SLEEPC_CMD: intcounter=%d currenttxskb=%p\n",
adapter->intcounter, adapter->currenttxskb);
spin_unlock_irqrestore(&adapter->driver_lock, flags);
@@ -1860,23 +1824,22 @@ static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
if (!adapter->intcounter) {
adapter->psstate = PS_STATE_SLEEP;
} else {
- lbs_pr_debug(1, "SEND_SLEEPC_CMD: After sent,IntC=%d\n",
+ lbs_deb_cmd("SEND_SLEEPC_CMD: After sent,IntC=%d\n",
adapter->intcounter);
}
spin_unlock_irqrestore(&adapter->driver_lock, flags);
- lbs_pr_debug(1, "SEND_SLEEPC_CMD: Sent Confirm Sleep command\n");
- lbs_pr_debug(1, "+");
+ lbs_deb_cmd("SEND_SLEEPC_CMD: Sent Confirm Sleep command\n");
+ lbs_deb_cmd("+");
}
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
void libertas_ps_sleep(wlan_private * priv, int wait_option)
{
-
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
/*
* PS is currently supported only in Infrastructure mode
@@ -1886,8 +1849,7 @@ void libertas_ps_sleep(wlan_private * priv, int wait_option)
libertas_prepare_and_send_command(priv, cmd_802_11_ps_mode,
cmd_subcmd_enter_ps, wait_option, 0, NULL);
- LEAVE();
- return;
+ lbs_deb_leave(LBS_DEB_CMD);
}
/**
@@ -1899,20 +1861,19 @@ void libertas_ps_sleep(wlan_private * priv, int wait_option)
*/
void libertas_ps_wakeup(wlan_private * priv, int wait_option)
{
- enum WLAN_802_11_POWER_MODE Localpsmode;
+ __le32 Localpsmode;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- Localpsmode = wlan802_11powermodecam;
+ Localpsmode = cpu_to_le32(wlan802_11powermodecam);
- lbs_pr_debug(1, "Exit_PS: Localpsmode = %d\n", Localpsmode);
+ lbs_deb_cmd("Exit_PS: Localpsmode = %d\n", wlan802_11powermodecam);
libertas_prepare_and_send_command(priv, cmd_802_11_ps_mode,
cmd_subcmd_exit_ps,
wait_option, 0, &Localpsmode);
- LEAVE();
- return;
+ lbs_deb_leave(LBS_DEB_CMD);
}
/**
@@ -1929,31 +1890,31 @@ void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode)
wlan_adapter *adapter = priv->adapter;
u8 allowed = 1;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- if (priv->wlan_dev.dnld_sent) {
+ if (priv->dnld_sent) {
allowed = 0;
- lbs_pr_debug(1, "D");
+ lbs_deb_cmd("D");
}
spin_lock_irqsave(&adapter->driver_lock, flags);
if (adapter->cur_cmd) {
allowed = 0;
- lbs_pr_debug(1, "C");
+ lbs_deb_cmd("C");
}
if (adapter->intcounter > 0) {
allowed = 0;
- lbs_pr_debug(1, "I%d", adapter->intcounter);
+ lbs_deb_cmd("I%d", adapter->intcounter);
}
spin_unlock_irqrestore(&adapter->driver_lock, flags);
if (allowed) {
- lbs_pr_debug(1, "Sending libertas_ps_confirm_sleep\n");
+ lbs_deb_cmd("Sending libertas_ps_confirm_sleep\n");
sendconfirmsleep(priv, (u8 *) & adapter->libertas_ps_confirm_sleep,
sizeof(struct PS_CMD_ConfirmSleep));
} else {
- lbs_pr_debug(1, "Sleep Confirm has been delayed\n");
+ lbs_deb_cmd("Sleep Confirm has been delayed\n");
}
- LEAVE();
+ lbs_deb_leave(LBS_DEB_CMD);
}
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index c86454034b5..6ac0d4752fa 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -9,7 +9,6 @@
#include <net/iw_handler.h>
#include "host.h"
-#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
@@ -32,7 +31,7 @@ void libertas_mac_event_disconnected(wlan_private * priv)
if (adapter->connect_status != libertas_connected)
return;
- lbs_pr_debug(1, "Handles disconnect event.\n");
+ lbs_deb_cmd("Handles disconnect event.\n");
memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -43,15 +42,15 @@ void libertas_mac_event_disconnected(wlan_private * priv)
*/
msleep_interruptible(1000);
- wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
/* Free Tx and Rx packets */
kfree_skb(priv->adapter->currenttxskb);
priv->adapter->currenttxskb = NULL;
/* report disconnect to upper layer */
- netif_stop_queue(priv->wlan_dev.netdev);
- netif_carrier_off(priv->wlan_dev.netdev);
+ netif_stop_queue(priv->dev);
+ netif_carrier_off(priv->dev);
/* reset SNR/NF/RSSI values */
memset(adapter->SNR, 0x00, sizeof(adapter->SNR));
@@ -62,35 +61,32 @@ void libertas_mac_event_disconnected(wlan_private * priv)
adapter->nextSNRNF = 0;
adapter->numSNRNF = 0;
adapter->rxpd_rate = 0;
- lbs_pr_debug(1, "Current SSID=%s, ssid length=%u\n",
- adapter->curbssparams.ssid.ssid,
- adapter->curbssparams.ssid.ssidlength);
- lbs_pr_debug(1, "Previous SSID=%s, ssid length=%u\n",
- adapter->previousssid.ssid, adapter->previousssid.ssidlength);
-
- /* reset internal flags */
- adapter->secinfo.WPAenabled = 0;
- adapter->secinfo.WPA2enabled = 0;
- adapter->wpa_ie_len = 0;
+ lbs_deb_cmd("Current SSID='%s', ssid length=%u\n",
+ escape_essid(adapter->curbssparams.ssid,
+ adapter->curbssparams.ssid_len),
+ adapter->curbssparams.ssid_len);
+ lbs_deb_cmd("Previous SSID='%s', ssid length=%u\n",
+ escape_essid(adapter->prev_ssid, adapter->prev_ssid_len),
+ adapter->prev_ssid_len);
adapter->connect_status = libertas_disconnected;
- /*
- * memorize the previous SSID and BSSID
- * it could be used for re-assoc
- */
- memcpy(&adapter->previousssid,
- &adapter->curbssparams.ssid, sizeof(struct WLAN_802_11_SSID));
- memcpy(adapter->previousbssid,
- adapter->curbssparams.bssid, ETH_ALEN);
+ /* Save previous SSID and BSSID for possible reassociation */
+ memcpy(&adapter->prev_ssid, &adapter->curbssparams.ssid,
+ IW_ESSID_MAX_SIZE);
+ adapter->prev_ssid_len = adapter->curbssparams.ssid_len;
+ memcpy(adapter->prev_bssid, adapter->curbssparams.bssid, ETH_ALEN);
- /* need to erase the current SSID and BSSID info */
- adapter->pattemptedbssdesc = NULL;
- memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
+ /* Clear out associated SSID and BSSID since connection is
+ * no longer valid.
+ */
+ memset(&adapter->curbssparams.bssid, 0, ETH_ALEN);
+ memset(&adapter->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
+ adapter->curbssparams.ssid_len = 0;
if (adapter->psstate != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
- lbs_pr_debug(1, "Disconnected, so exit PS mode.\n");
+ lbs_deb_cmd("Disconnected, so exit PS mode.\n");
libertas_ps_wakeup(priv, 0);
}
}
@@ -122,55 +118,45 @@ static void handle_mic_failureevent(wlan_private * priv, u32 event)
static int wlan_ret_reg_access(wlan_private * priv,
u16 type, struct cmd_ds_command *resp)
{
+ int ret = 0;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
switch (type) {
case cmd_ret_mac_reg_access:
{
- struct cmd_ds_mac_reg_access *reg;
+ struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
- reg =
- (struct cmd_ds_mac_reg_access *)&resp->params.
- macreg;
-
- adapter->offsetvalue.offset = reg->offset;
- adapter->offsetvalue.value = reg->value;
+ adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
+ adapter->offsetvalue.value = le32_to_cpu(reg->value);
break;
}
case cmd_ret_bbp_reg_access:
{
- struct cmd_ds_bbp_reg_access *reg;
- reg =
- (struct cmd_ds_bbp_reg_access *)&resp->params.
- bbpreg;
+ struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
- adapter->offsetvalue.offset = reg->offset;
+ adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
adapter->offsetvalue.value = reg->value;
break;
}
case cmd_ret_rf_reg_access:
{
- struct cmd_ds_rf_reg_access *reg;
- reg =
- (struct cmd_ds_rf_reg_access *)&resp->params.
- rfreg;
+ struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
- adapter->offsetvalue.offset = reg->offset;
+ adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
adapter->offsetvalue.value = reg->value;
break;
}
default:
- LEAVE();
- return -1;
+ ret = -1;
}
- LEAVE();
- return 0;
+ lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
}
static int wlan_ret_get_hw_spec(wlan_private * priv,
@@ -181,19 +167,20 @@ static int wlan_ret_get_hw_spec(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
adapter->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
- adapter->fwreleasenumber = hwspec->fwreleasenumber;
+ memcpy(adapter->fwreleasenumber, hwspec->fwreleasenumber, 4);
- lbs_pr_debug(1, "GET_HW_SPEC: FWReleaseVersion- 0x%X\n",
- adapter->fwreleasenumber);
- lbs_pr_debug(1, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
+ lbs_deb_cmd("GET_HW_SPEC: FWReleaseVersion- %u.%u.%u.p%u\n",
+ adapter->fwreleasenumber[2], adapter->fwreleasenumber[1],
+ adapter->fwreleasenumber[0], adapter->fwreleasenumber[3]);
+ lbs_deb_cmd("GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
hwspec->permanentaddr[0], hwspec->permanentaddr[1],
hwspec->permanentaddr[2], hwspec->permanentaddr[3],
hwspec->permanentaddr[4], hwspec->permanentaddr[5]);
- lbs_pr_debug(1, "GET_HW_SPEC: hwifversion=0x%X version=0x%X\n",
+ lbs_deb_cmd("GET_HW_SPEC: hwifversion=0x%X version=0x%X\n",
hwspec->hwifversion, hwspec->version);
adapter->regioncode = le16_to_cpu(hwspec->regioncode);
@@ -210,17 +197,15 @@ static int wlan_ret_get_hw_spec(wlan_private * priv,
if (i >= MRVDRV_MAX_REGION_CODE) {
adapter->regioncode = 0x10;
adapter->regiontableindex = 0;
- lbs_pr_info(
- "unidentified region code, use the default (USA)\n");
+ lbs_pr_info("unidentified region code; using the default (USA)\n");
}
- if (adapter->current_addr[0] == 0xff) {
- memmove(adapter->current_addr, hwspec->permanentaddr,
- ETH_ALEN);
- }
+ if (adapter->current_addr[0] == 0xff)
+ memmove(adapter->current_addr, hwspec->permanentaddr, ETH_ALEN);
- memcpy(priv->wlan_dev.netdev->dev_addr, adapter->current_addr, ETH_ALEN);
- memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
+ memcpy(priv->dev->dev_addr, adapter->current_addr, ETH_ALEN);
+ if (priv->mesh_dev)
+ memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
if (libertas_set_regiontable(priv, adapter->regioncode, 0)) {
ret = -1;
@@ -232,8 +217,8 @@ static int wlan_ret_get_hw_spec(wlan_private * priv,
goto done;
}
- done:
- LEAVE();
+done:
+ lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -243,19 +228,21 @@ static int wlan_ret_802_11_sleep_params(wlan_private * priv,
struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ lbs_deb_cmd("error=%x offset=%x stabletime=%x calcontrol=%x\n"
+ " extsleepclk=%x\n", le16_to_cpu(sp->error),
+ le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
+ sp->calcontrol, sp->externalsleepclk);
- lbs_pr_debug(1, "error=%x offset=%x stabletime=%x calcontrol=%x\n"
- " extsleepclk=%x\n", sp->error, sp->offset,
- sp->stabletime, sp->calcontrol, sp->externalsleepclk);
adapter->sp.sp_error = le16_to_cpu(sp->error);
adapter->sp.sp_offset = le16_to_cpu(sp->offset);
adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
- adapter->sp.sp_calcontrol = le16_to_cpu(sp->calcontrol);
- adapter->sp.sp_extsleepclk = le16_to_cpu(sp->externalsleepclk);
+ adapter->sp.sp_calcontrol = sp->calcontrol;
+ adapter->sp.sp_extsleepclk = sp->externalsleepclk;
adapter->sp.sp_reserved = le16_to_cpu(sp->reserved);
- LEAVE();
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
@@ -281,42 +268,38 @@ static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
u16 oid = le16_to_cpu(smib->oid);
u16 querytype = le16_to_cpu(smib->querytype);
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- lbs_pr_debug(1, "SNMP_RESP: value of the oid = %x, querytype=%x\n", oid,
+ lbs_deb_cmd("SNMP_RESP: value of the oid = %x, querytype=%x\n", oid,
querytype);
- lbs_pr_debug(1, "SNMP_RESP: Buf size = %x\n",
- le16_to_cpu(smib->bufsize));
+ lbs_deb_cmd("SNMP_RESP: Buf size = %x\n", le16_to_cpu(smib->bufsize));
if (querytype == cmd_act_get) {
switch (oid) {
case fragthresh_i:
priv->adapter->fragthsd =
- le16_to_cpu(*
- ((unsigned short *)(smib->value)));
- lbs_pr_debug(1, "SNMP_RESP: fragthsd =%u\n",
- priv->adapter->fragthsd);
+ le16_to_cpu(*((__le16 *)(smib->value)));
+ lbs_deb_cmd("SNMP_RESP: fragthsd =%u\n",
+ priv->adapter->fragthsd);
break;
case rtsthresh_i:
priv->adapter->rtsthsd =
- le16_to_cpu(*
- ((unsigned short *)(smib->value)));
- lbs_pr_debug(1, "SNMP_RESP: rtsthsd =%u\n",
- priv->adapter->rtsthsd);
+ le16_to_cpu(*((__le16 *)(smib->value)));
+ lbs_deb_cmd("SNMP_RESP: rtsthsd =%u\n",
+ priv->adapter->rtsthsd);
break;
case short_retrylim_i:
priv->adapter->txretrycount =
- le16_to_cpu(*
- ((unsigned short *)(smib->value)));
- lbs_pr_debug(1, "SNMP_RESP: txretrycount =%u\n",
- priv->adapter->rtsthsd);
+ le16_to_cpu(*((__le16 *)(smib->value)));
+ lbs_deb_cmd("SNMP_RESP: txretrycount =%u\n",
+ priv->adapter->rtsthsd);
break;
default:
break;
}
}
- LEAVE();
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
@@ -328,7 +311,7 @@ static int wlan_ret_802_11_key_material(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
u16 action = le16_to_cpu(pkeymaterial->action);
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
/* Copy the returned key to driver private data */
if (action == cmd_act_get) {
@@ -371,7 +354,7 @@ static int wlan_ret_802_11_key_material(wlan_private * priv,
}
}
- LEAVE();
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
@@ -381,11 +364,11 @@ static int wlan_ret_802_11_mac_address(wlan_private * priv,
struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
memcpy(adapter->current_addr, macadd->macadd, ETH_ALEN);
- LEAVE();
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
@@ -395,13 +378,13 @@ static int wlan_ret_802_11_rf_tx_power(wlan_private * priv,
struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
adapter->txpowerlevel = le16_to_cpu(rtp->currentlevel);
- lbs_pr_debug(1, "Current TxPower Level = %d\n", adapter->txpowerlevel);
+ lbs_deb_cmd("Current TxPower Level = %d\n", adapter->txpowerlevel);
- LEAVE();
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
@@ -413,14 +396,12 @@ static int wlan_ret_802_11_rf_antenna(wlan_private * priv,
u16 action = le16_to_cpu(pAntenna->action);
if (action == cmd_act_get_rx)
- adapter->rxantennamode =
- le16_to_cpu(pAntenna->antennamode);
+ adapter->rxantennamode = le16_to_cpu(pAntenna->antennamode);
if (action == cmd_act_get_tx)
- adapter->txantennamode =
- le16_to_cpu(pAntenna->antennamode);
+ adapter->txantennamode = le16_to_cpu(pAntenna->antennamode);
- lbs_pr_debug(1, "RF_ANT_RESP: action = 0x%x, mode = 0x%04x\n",
+ lbs_deb_cmd("RF_ANT_RESP: action = 0x%x, mode = 0x%04x\n",
action, le16_to_cpu(pAntenna->antennamode));
return 0;
@@ -429,19 +410,17 @@ static int wlan_ret_802_11_rf_antenna(wlan_private * priv,
static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
struct cmd_ds_command *resp)
{
- struct cmd_ds_802_11_rate_adapt_rateset *rates =
- &resp->params.rateset;
+ struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
if (rates->action == cmd_act_get) {
- adapter->enablehwauto = rates->enablehwauto;
- adapter->ratebitmap = rates->bitmap;
+ adapter->enablehwauto = le16_to_cpu(rates->enablehwauto);
+ adapter->ratebitmap = le16_to_cpu(rates->bitmap);
}
- LEAVE();
-
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
@@ -452,43 +431,42 @@ static int wlan_ret_802_11_data_rate(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
u8 dot11datarate;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
lbs_dbg_hex("DATA_RATE_RESP: data_rate- ",
(u8 *) pdatarate, sizeof(struct cmd_ds_802_11_data_rate));
dot11datarate = pdatarate->datarate[0];
- if (pdatarate->action == cmd_act_get_tx_rate) {
+ if (pdatarate->action == cpu_to_le16(cmd_act_get_tx_rate)) {
memcpy(adapter->libertas_supported_rates, pdatarate->datarate,
sizeof(adapter->libertas_supported_rates));
}
adapter->datarate = libertas_index_to_data_rate(dot11datarate);
- LEAVE();
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
static int wlan_ret_802_11_rf_channel(wlan_private * priv,
struct cmd_ds_command *resp)
{
- struct cmd_ds_802_11_rf_channel *rfchannel =
- &resp->params.rfchannel;
+ struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
wlan_adapter *adapter = priv->adapter;
u16 action = le16_to_cpu(rfchannel->action);
u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
if (action == cmd_opt_802_11_rf_channel_get
&& adapter->curbssparams.channel != newchannel) {
- lbs_pr_debug(1, "channel Switch: %d to %d\n",
+ lbs_deb_cmd("channel Switch: %d to %d\n",
adapter->curbssparams.channel, newchannel);
/* Update the channel again */
adapter->curbssparams.channel = newchannel;
}
- LEAVE();
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
@@ -500,12 +478,10 @@ static int wlan_ret_802_11_rssi(wlan_private * priv,
/* store the non average value */
adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
- adapter->NF[TYPE_BEACON][TYPE_NOAVG] =
- le16_to_cpu(rssirsp->noisefloor);
+ adapter->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
- adapter->NF[TYPE_BEACON][TYPE_AVG] =
- le16_to_cpu(rssirsp->avgnoisefloor);
+ adapter->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
@@ -515,7 +491,7 @@ static int wlan_ret_802_11_rssi(wlan_private * priv,
CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
- lbs_pr_debug(1, "Beacon RSSI value = 0x%x\n",
+ lbs_deb_cmd("Beacon RSSI value = 0x%x\n",
adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
return 0;
@@ -528,11 +504,11 @@ static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
struct wlan_ioctl_regrdwr *pbuf;
pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom;
- lbs_pr_debug(1, "eeprom read len=%x\n",
+ lbs_deb_cmd("eeprom read len=%x\n",
le16_to_cpu(resp->params.rdeeprom.bytecount));
if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) {
pbuf->NOB = 0;
- lbs_pr_debug(1, "eeprom read return length is too big\n");
+ lbs_deb_cmd("eeprom read return length is too big\n");
return -1;
}
pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount);
@@ -549,17 +525,33 @@ static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
static int wlan_ret_get_log(wlan_private * priv,
struct cmd_ds_command *resp)
{
- struct cmd_ds_802_11_get_log *logmessage =
- (struct cmd_ds_802_11_get_log *)&resp->params.glog;
+ struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- /* TODO Convert it to Big Endian before copy */
- memcpy(&adapter->logmsg, logmessage,
- sizeof(struct cmd_ds_802_11_get_log));
+ /* Stored little-endian */
+ memcpy(&adapter->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
- LEAVE();
+ lbs_deb_enter(LBS_DEB_CMD);
+ return 0;
+}
+
+static int libertas_ret_802_11_enable_rsn(wlan_private * priv,
+ struct cmd_ds_command *resp)
+{
+ struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
+ wlan_adapter *adapter = priv->adapter;
+ u32 * pdata_buf = adapter->cur_cmd->pdata_buf;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ if (enable_rsn->action == cpu_to_le16(cmd_act_get)) {
+ if (pdata_buf)
+ *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
+ }
+
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
@@ -620,8 +612,7 @@ static inline int handle_cmd_response(u16 respcmd,
case cmd_ret_802_11_set_afc:
case cmd_ret_802_11_get_afc:
spin_lock_irqsave(&adapter->driver_lock, flags);
- memmove(adapter->cur_cmd->pdata_buf,
- &resp->params.afc,
+ memmove(adapter->cur_cmd->pdata_buf, &resp->params.afc,
sizeof(struct cmd_ds_802_11_afc));
spin_unlock_irqrestore(&adapter->driver_lock, flags);
@@ -637,7 +628,10 @@ static inline int handle_cmd_response(u16 respcmd,
case cmd_ret_802_11_authenticate:
case cmd_ret_802_11_radio_control:
case cmd_ret_802_11_beacon_stop:
+ break;
+
case cmd_ret_802_11_enable_rsn:
+ ret = libertas_ret_802_11_enable_rsn(priv, resp);
break;
case cmd_ret_802_11_data_rate:
@@ -663,7 +657,7 @@ static inline int handle_cmd_response(u16 respcmd,
break;
case cmd_ret_802_11_key_material:
- lbs_pr_debug(1, "CMD_RESP: KEY_MATERIAL command response\n");
+ lbs_deb_cmd("CMD_RESP: KEY_MATERIAL command response\n");
ret = wlan_ret_802_11_key_material(priv, resp);
break;
@@ -687,22 +681,19 @@ static inline int handle_cmd_response(u16 respcmd,
case cmd_ret_802_11_tpc_cfg:
spin_lock_irqsave(&adapter->driver_lock, flags);
- memmove(adapter->cur_cmd->pdata_buf,
- &resp->params.tpccfg,
+ memmove(adapter->cur_cmd->pdata_buf, &resp->params.tpccfg,
sizeof(struct cmd_ds_802_11_tpc_cfg));
spin_unlock_irqrestore(&adapter->driver_lock, flags);
break;
case cmd_ret_802_11_led_gpio_ctrl:
spin_lock_irqsave(&adapter->driver_lock, flags);
- memmove(adapter->cur_cmd->pdata_buf,
- &resp->params.ledgpio,
+ memmove(adapter->cur_cmd->pdata_buf, &resp->params.ledgpio,
sizeof(struct cmd_ds_802_11_led_ctrl));
spin_unlock_irqrestore(&adapter->driver_lock, flags);
break;
case cmd_ret_802_11_pwr_cfg:
spin_lock_irqsave(&adapter->driver_lock, flags);
- memmove(adapter->cur_cmd->pdata_buf,
- &resp->params.pwrcfg,
+ memmove(adapter->cur_cmd->pdata_buf, &resp->params.pwrcfg,
sizeof(struct cmd_ds_802_11_pwr_cfg));
spin_unlock_irqrestore(&adapter->driver_lock, flags);
@@ -724,23 +715,21 @@ static inline int handle_cmd_response(u16 respcmd,
case cmd_ret_fwt_access:
spin_lock_irqsave(&adapter->driver_lock, flags);
if (adapter->cur_cmd->pdata_buf)
- memcpy(adapter->cur_cmd->pdata_buf,
- &resp->params.fwt,
- sizeof(resp->params.fwt));
+ memcpy(adapter->cur_cmd->pdata_buf, &resp->params.fwt,
+ sizeof(resp->params.fwt));
spin_unlock_irqrestore(&adapter->driver_lock, flags);
break;
case cmd_ret_mesh_access:
if (adapter->cur_cmd->pdata_buf)
- memcpy(adapter->cur_cmd->pdata_buf,
- &resp->params.mesh,
+ memcpy(adapter->cur_cmd->pdata_buf, &resp->params.mesh,
sizeof(resp->params.mesh));
break;
case cmd_rte_802_11_tx_rate_query:
priv->adapter->txrate = resp->params.txrate.txrate;
break;
default:
- lbs_pr_debug(1, "CMD_RESP: Unknown command response %#x\n",
- resp->command);
+ lbs_deb_cmd("CMD_RESP: Unknown command response %#x\n",
+ resp->command);
break;
}
return ret;
@@ -755,9 +744,9 @@ int libertas_process_rx_command(wlan_private * priv)
ulong flags;
u16 result;
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- lbs_pr_debug(1, "CMD_RESP: @ %lu\n", jiffies);
+ lbs_deb_cmd("CMD_RESP: @ %lu\n", jiffies);
/* Now we got response from FW, cancel the command timer */
del_timer(&adapter->command_timer);
@@ -766,7 +755,7 @@ int libertas_process_rx_command(wlan_private * priv)
spin_lock_irqsave(&adapter->driver_lock, flags);
if (!adapter->cur_cmd) {
- lbs_pr_debug(1, "CMD_RESP: NULL cur_cmd=%p\n", adapter->cur_cmd);
+ lbs_deb_cmd("CMD_RESP: NULL cur_cmd=%p\n", adapter->cur_cmd);
ret = -1;
spin_unlock_irqrestore(&adapter->driver_lock, flags);
goto done;
@@ -774,17 +763,17 @@ int libertas_process_rx_command(wlan_private * priv)
resp = (struct cmd_ds_command *)(adapter->cur_cmd->bufvirtualaddr);
lbs_dbg_hex("CMD_RESP:", adapter->cur_cmd->bufvirtualaddr,
- priv->wlan_dev.upld_len);
+ priv->upld_len);
respcmd = le16_to_cpu(resp->command);
result = le16_to_cpu(resp->result);
- lbs_pr_debug(1, "CMD_RESP: %x result: %d length: %d\n", respcmd,
- result, priv->wlan_dev.upld_len);
+ lbs_deb_cmd("CMD_RESP: %x result: %d length: %d\n", respcmd,
+ result, priv->upld_len);
if (!(respcmd & 0x8000)) {
- lbs_pr_debug(1, "Invalid response to command!");
+ lbs_deb_cmd("Invalid response to command!");
adapter->cur_cmd_retcode = -1;
__libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
adapter->nr_cmd_pending--;
@@ -795,56 +784,52 @@ int libertas_process_rx_command(wlan_private * priv)
}
/* Store the response code to cur_cmd_retcode. */
- adapter->cur_cmd_retcode = le16_to_cpu(resp->result);
+ adapter->cur_cmd_retcode = result;;
if (respcmd == cmd_ret_802_11_ps_mode) {
- struct cmd_ds_802_11_ps_mode *psmode;
+ struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
+ u16 action = le16_to_cpu(psmode->action);
- psmode = &resp->params.psmode;
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
- resp->result, psmode->action);
- psmode->action = cpu_to_le16(psmode->action);
+ result, action);
if (result) {
- lbs_pr_debug(1, "CMD_RESP: PS command failed- %#x \n",
- resp->result);
- if (adapter->mode == IW_MODE_ADHOC) {
- /*
- * We should not re-try enter-ps command in
- * ad-hoc mode. It takes place in
- * libertas_execute_next_command().
- */
- if (psmode->action == cmd_subcmd_enter_ps)
- adapter->psmode =
- wlan802_11powermodecam;
- }
- } else if (psmode->action == cmd_subcmd_enter_ps) {
+ lbs_deb_cmd("CMD_RESP: PS command failed- %#x \n",
+ result);
+ /*
+ * We should not re-try enter-ps command in
+ * ad-hoc mode. It takes place in
+ * libertas_execute_next_command().
+ */
+ if (adapter->mode == IW_MODE_ADHOC &&
+ action == cmd_subcmd_enter_ps)
+ adapter->psmode = wlan802_11powermodecam;
+ } else if (action == cmd_subcmd_enter_ps) {
adapter->needtowakeup = 0;
adapter->psstate = PS_STATE_AWAKE;
- lbs_pr_debug(1, "CMD_RESP: Enter_PS command response\n");
+ lbs_deb_cmd("CMD_RESP: Enter_PS command response\n");
if (adapter->connect_status != libertas_connected) {
/*
* When Deauth Event received before Enter_PS command
* response, We need to wake up the firmware.
*/
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"Disconnected, Going to invoke libertas_ps_wakeup\n");
- mutex_unlock(&adapter->lock);
spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ mutex_unlock(&adapter->lock);
libertas_ps_wakeup(priv, 0);
mutex_lock(&adapter->lock);
spin_lock_irqsave(&adapter->driver_lock, flags);
}
- } else if (psmode->action == cmd_subcmd_exit_ps) {
+ } else if (action == cmd_subcmd_exit_ps) {
adapter->needtowakeup = 0;
adapter->psstate = PS_STATE_FULL_POWER;
- lbs_pr_debug(1, "CMD_RESP: Exit_PS command response\n");
+ lbs_deb_cmd("CMD_RESP: Exit_PS command response\n");
} else {
- lbs_pr_debug(1, "CMD_RESP: PS- action=0x%X\n",
- psmode->action);
+ lbs_deb_cmd("CMD_RESP: PS- action=0x%X\n", action);
}
__libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
@@ -865,15 +850,15 @@ int libertas_process_rx_command(wlan_private * priv)
/* If the command is not successful, cleanup and return failure */
if ((result != 0 || !(respcmd & 0x8000))) {
- lbs_pr_debug(1, "CMD_RESP: command reply %#x result=%#x\n",
- resp->command, resp->result);
+ lbs_deb_cmd("CMD_RESP: command reply %#x result=%#x\n",
+ respcmd, result);
/*
* Handling errors here
*/
switch (respcmd) {
case cmd_ret_hw_spec_info:
case cmd_ret_802_11_reset:
- lbs_pr_debug(1, "CMD_RESP: Reset command failed\n");
+ lbs_deb_cmd("CMD_RESP: Reset command failed\n");
break;
}
@@ -903,7 +888,7 @@ int libertas_process_rx_command(wlan_private * priv)
done:
mutex_unlock(&adapter->lock);
- LEAVE();
+ lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
@@ -917,37 +902,37 @@ int libertas_process_event(wlan_private * priv)
eventcause = adapter->eventcause;
spin_unlock_irq(&adapter->driver_lock);
- ENTER();
+ lbs_deb_enter(LBS_DEB_CMD);
- lbs_pr_debug(1, "EVENT Cause %x\n", eventcause);
+ lbs_deb_cmd("EVENT Cause %x\n", eventcause);
switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) {
case MACREG_INT_CODE_LINK_SENSED:
- lbs_pr_debug(1, "EVENT: MACREG_INT_CODE_LINK_SENSED\n");
+ lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
break;
case MACREG_INT_CODE_DEAUTHENTICATED:
- lbs_pr_debug(1, "EVENT: Deauthenticated\n");
+ lbs_deb_cmd("EVENT: Deauthenticated\n");
libertas_mac_event_disconnected(priv);
break;
case MACREG_INT_CODE_DISASSOCIATED:
- lbs_pr_debug(1, "EVENT: Disassociated\n");
+ lbs_deb_cmd("EVENT: Disassociated\n");
libertas_mac_event_disconnected(priv);
break;
case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
- lbs_pr_debug(1, "EVENT: Link lost\n");
+ lbs_deb_cmd("EVENT: Link lost\n");
libertas_mac_event_disconnected(priv);
break;
case MACREG_INT_CODE_PS_SLEEP:
- lbs_pr_debug(1, "EVENT: SLEEP\n");
- lbs_pr_debug(1, "_");
+ lbs_deb_cmd("EVENT: SLEEP\n");
+ lbs_deb_cmd("_");
/* handle unexpected PS SLEEP event */
if (adapter->psstate == PS_STATE_FULL_POWER) {
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"EVENT: In FULL POWER mode - ignore PS SLEEP\n");
break;
}
@@ -958,12 +943,12 @@ int libertas_process_event(wlan_private * priv)
break;
case MACREG_INT_CODE_PS_AWAKE:
- lbs_pr_debug(1, "EVENT: AWAKE \n");
- lbs_pr_debug(1, "|");
+ lbs_deb_cmd("EVENT: AWAKE \n");
+ lbs_deb_cmd("|");
/* handle unexpected PS AWAKE event */
if (adapter->psstate == PS_STATE_FULL_POWER) {
- lbs_pr_debug(1,
+ lbs_deb_cmd(
"EVENT: In FULL POWER mode - ignore PS AWAKE\n");
break;
}
@@ -977,18 +962,18 @@ int libertas_process_event(wlan_private * priv)
* adapter->needtowakeup will be set to FALSE
* in libertas_ps_wakeup()
*/
- lbs_pr_debug(1, "Waking up...\n");
+ lbs_deb_cmd("Waking up...\n");
libertas_ps_wakeup(priv, 0);
}
break;
case MACREG_INT_CODE_MIC_ERR_UNICAST:
- lbs_pr_debug(1, "EVENT: UNICAST MIC ERROR\n");
+ lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
break;
case MACREG_INT_CODE_MIC_ERR_MULTICAST:
- lbs_pr_debug(1, "EVENT: MULTICAST MIC ERROR\n");
+ lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
break;
case MACREG_INT_CODE_MIB_CHANGED:
@@ -996,7 +981,7 @@ int libertas_process_event(wlan_private * priv)
break;
case MACREG_INT_CODE_ADHOC_BCN_LOST:
- lbs_pr_debug(1, "EVENT: HWAC - ADHOC BCN LOST\n");
+ lbs_deb_cmd("EVENT: HWAC - ADHOC BCN LOST\n");
break;
case MACREG_INT_CODE_RSSI_LOW:
@@ -1015,6 +1000,17 @@ int libertas_process_event(wlan_private * priv)
lbs_pr_alert( "EVENT: SNR_HIGH\n");
break;
+ case MACREG_INT_CODE_MESH_AUTO_STARTED:
+ lbs_pr_alert( "EVENT: MESH_AUTO_STARTED\n");
+ adapter->connect_status = libertas_connected ;
+ if (priv->mesh_open == 1) {
+ netif_wake_queue(priv->mesh_dev) ;
+ netif_carrier_on(priv->mesh_dev) ;
+ }
+ adapter->mode = IW_MODE_ADHOC ;
+ schedule_work(&priv->sync_channel);
+ break;
+
default:
lbs_pr_alert( "EVENT: unknown event id: %#x\n",
eventcause >> SBI_EVENT_CAUSE_SHIFT);
@@ -1024,6 +1020,7 @@ int libertas_process_event(wlan_private * priv)
spin_lock_irq(&adapter->driver_lock);
adapter->eventcause = 0;
spin_unlock_irq(&adapter->driver_lock);
- LEAVE();
+
+ lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 7d7bc5e86a5..715cbdaa1d4 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -4,6 +4,7 @@
#include <linux/delay.h>
#include <linux/mm.h>
#include <net/iw_handler.h>
+
#include "dev.h"
#include "decl.h"
#include "host.h"
@@ -15,7 +16,9 @@ static char *szStates[] = {
"Disconnected"
};
-void libertas_debug_init(wlan_private * priv, struct net_device *dev);
+#ifdef PROC_DEBUG
+static void libertas_debug_init(wlan_private * priv, struct net_device *dev);
+#endif
static int open_file_generic(struct inode *inode, struct file *file)
{
@@ -60,43 +63,33 @@ static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
int numscansdone = 0, res;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
+ struct bss_descriptor * iter_bss;
pos += snprintf(buf+pos, len-pos,
- "---------------------------------------");
- pos += snprintf(buf+pos, len-pos,
- "---------------------------------------\n");
- pos += snprintf(buf+pos, len-pos,
"# | ch | ss | bssid | cap | TSF | Qual | SSID \n");
- pos += snprintf(buf+pos, len-pos,
- "---------------------------------------");
- pos += snprintf(buf+pos, len-pos,
- "---------------------------------------\n");
- while (numscansdone < priv->adapter->numinscantable) {
- struct bss_descriptor *pbssinfo;
+ mutex_lock(&priv->adapter->lock);
+ list_for_each_entry (iter_bss, &priv->adapter->network_list, list) {
u16 cap;
- pbssinfo = &priv->adapter->scantable[numscansdone];
- memcpy(&cap, &pbssinfo->cap, sizeof(cap));
+ memcpy(&cap, &iter_bss->cap, sizeof(cap));
pos += snprintf(buf+pos, len-pos,
- "%02u| %03d | %03ld | %02x:%02x:%02x:%02x:%02x:%02x |",
- numscansdone, pbssinfo->channel, pbssinfo->rssi,
- pbssinfo->macaddress[0], pbssinfo->macaddress[1],
- pbssinfo->macaddress[2], pbssinfo->macaddress[3],
- pbssinfo->macaddress[4], pbssinfo->macaddress[5]);
+ "%02u| %03d | %03ld | " MAC_FMT " |",
+ numscansdone, iter_bss->channel, iter_bss->rssi,
+ MAC_ARG(iter_bss->bssid));
pos += snprintf(buf+pos, len-pos, " %04x-", cap);
pos += snprintf(buf+pos, len-pos, "%c%c%c |",
- pbssinfo->cap.ibss ? 'A' : 'I',
- pbssinfo->cap.privacy ? 'P' : ' ',
- pbssinfo->cap.spectrummgmt ? 'S' : ' ');
- pos += snprintf(buf+pos, len-pos, " %08llx |", pbssinfo->networktsf);
- pos += snprintf(buf+pos, len-pos, " %d |",
- SCAN_RSSI(priv->adapter->scantable[numscansdone].rssi));
-
- pos += snprintf(buf+pos, len-pos, " %s\n", pbssinfo->ssid.ssid);
+ iter_bss->cap.ibss ? 'A' : 'I',
+ iter_bss->cap.privacy ? 'P' : ' ',
+ iter_bss->cap.spectrummgmt ? 'S' : ' ');
+ pos += snprintf(buf+pos, len-pos, " %08llx |", iter_bss->networktsf);
+ pos += snprintf(buf+pos, len-pos, " %d |", SCAN_RSSI(iter_bss->rssi));
+ pos += snprintf(buf+pos, len-pos, " %s\n",
+ escape_essid(iter_bss->ssid, iter_bss->ssid_len));
numscansdone++;
}
+ mutex_unlock(&priv->adapter->lock);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
@@ -111,7 +104,6 @@ static ssize_t libertas_sleepparams_write(struct file *file,
wlan_private *priv = file->private_data;
ssize_t buf_size, res;
int p1, p2, p3, p4, p5, p6;
- struct sleep_params sp;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
@@ -125,14 +117,12 @@ static ssize_t libertas_sleepparams_write(struct file *file,
res = -EFAULT;
goto out_unlock;
}
- sp.sp_error = p1;
- sp.sp_offset = p2;
- sp.sp_stabletime = p3;
- sp.sp_calcontrol = p4;
- sp.sp_extsleepclk = p5;
- sp.sp_reserved = p6;
-
- memcpy(&priv->adapter->sp, &sp, sizeof(struct sleep_params));
+ priv->adapter->sp.sp_error = p1;
+ priv->adapter->sp.sp_offset = p2;
+ priv->adapter->sp.sp_stabletime = p3;
+ priv->adapter->sp.sp_calcontrol = p4;
+ priv->adapter->sp.sp_extsleepclk = p5;
+ priv->adapter->sp.sp_reserved = p6;
res = libertas_prepare_and_send_command(priv,
cmd_802_11_sleep_params,
@@ -185,7 +175,6 @@ static ssize_t libertas_extscan(struct file *file, const char __user *userbuf,
{
wlan_private *priv = file->private_data;
ssize_t res, buf_size;
- struct WLAN_802_11_SSID extscan_ssid;
union iwreq_data wrqu;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
@@ -196,13 +185,10 @@ static ssize_t libertas_extscan(struct file *file, const char __user *userbuf,
goto out_unlock;
}
- memcpy(&extscan_ssid.ssid, buf, strlen(buf)-1);
- extscan_ssid.ssidlength = strlen(buf)-1;
-
- libertas_send_specific_SSID_scan(priv, &extscan_ssid, 1);
+ libertas_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
memset(&wrqu, 0, sizeof(union iwreq_data));
- wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL);
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
out_unlock:
free_page(addr);
@@ -251,16 +237,13 @@ static void libertas_parse_bssid(char *buf, size_t count,
{
char *hold;
unsigned int mac[ETH_ALEN];
- int i;
hold = strstr(buf, "bssid=");
if (!hold)
return;
hold += 6;
- sscanf(hold, "%2x:%2x:%2x:%2x:%2x:%2x", mac, mac+1, mac+2, mac+3,
- mac+4, mac+5);
- for(i=0;i<ETH_ALEN;i++)
- scan_cfg->specificBSSID[i] = mac[i];
+ sscanf(hold, MAC_FMT, mac, mac+1, mac+2, mac+3, mac+4, mac+5);
+ memcpy(scan_cfg->bssid, mac, ETH_ALEN);
}
static void libertas_parse_ssid(char *buf, size_t count,
@@ -278,28 +261,26 @@ static void libertas_parse_ssid(char *buf, size_t count,
end = buf + count - 1;
size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold));
- strncpy(scan_cfg->specificSSID, hold, size);
+ strncpy(scan_cfg->ssid, hold, size);
return;
}
-static void libertas_parse_keep(char *buf, size_t count,
- struct wlan_ioctl_user_scan_cfg *scan_cfg)
+static int libertas_parse_clear(char *buf, size_t count, const char *tag)
{
char *hold;
int val;
- hold = strstr(buf, "keep=");
+ hold = strstr(buf, tag);
if (!hold)
- return;
- hold += 5;
+ return 0;
+ hold += strlen(tag);
sscanf(hold, "%d", &val);
if (val != 0)
val = 1;
- scan_cfg->keeppreviousscan = val;
- return;
+ return val;
}
static int libertas_parse_dur(char *buf, size_t count,
@@ -382,17 +363,18 @@ static ssize_t libertas_setuserscan(struct file *file,
dur = libertas_parse_dur(buf, count, scan_cfg);
libertas_parse_chan(buf, count, scan_cfg, dur);
libertas_parse_bssid(buf, count, scan_cfg);
+ scan_cfg->clear_bssid = libertas_parse_clear(buf, count, "clear_bssid=");
libertas_parse_ssid(buf, count, scan_cfg);
- libertas_parse_keep(buf, count, scan_cfg);
+ scan_cfg->clear_ssid = libertas_parse_clear(buf, count, "clear_ssid=");
libertas_parse_probes(buf, count, scan_cfg);
libertas_parse_type(buf, count, scan_cfg);
- wlan_scan_networks(priv, scan_cfg);
+ wlan_scan_networks(priv, scan_cfg, 1);
wait_event_interruptible(priv->adapter->cmd_pending,
!priv->adapter->nr_cmd_pending);
memset(&wrqu, 0x00, sizeof(union iwreq_data));
- wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL);
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
out_unlock:
free_page(addr);
@@ -407,11 +389,11 @@ static int libertas_event_initcmd(wlan_private *priv, void **response_buf,
u16 wait_option = cmd_option_waitforrsp;
if (!(*cmdnode = libertas_get_free_cmd_ctrl_node(priv))) {
- lbs_pr_debug(1, "failed libertas_get_free_cmd_ctrl_node\n");
+ lbs_deb_debugfs("failed libertas_get_free_cmd_ctrl_node\n");
return -ENOMEM;
}
if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) {
- lbs_pr_debug(1, "failed to allocate response buffer!\n");
+ lbs_deb_debugfs("failed to allocate response buffer!\n");
return -ENOMEM;
}
libertas_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL);
@@ -420,8 +402,8 @@ static int libertas_event_initcmd(wlan_private *priv, void **response_buf,
(*cmdnode)->cmdflags |= CMD_F_HOSTCMD;
(*cmdnode)->cmdwaitqwoken = 0;
*cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr;
- (*cmd)->command = cmd_802_11_subscribe_event;
- (*cmd)->seqnum = ++priv->adapter->seqnum;
+ (*cmd)->command = cpu_to_le16(cmd_802_11_subscribe_event);
+ (*cmd)->seqnum = cpu_to_le16(++priv->adapter->seqnum);
(*cmd)->result = 0;
return 0;
}
@@ -447,26 +429,25 @@ static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf,
}
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_get;
- pcmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+ event->action = cpu_to_le16(cmd_act_get);
+ pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -474,17 +455,17 @@ static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf,
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
- while (cmd_len < pcmdptr->size) {
- struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
- switch(header->type) {
+ event = (void *)(response_buf + S_DS_GEN);
+ while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+ struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+ switch (header->type) {
struct mrvlietypes_rssithreshold *Lowrssi;
- case TLV_TYPE_RSSI_LOW:
- Lowrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- Lowrssi->rssivalue,
- Lowrssi->rssifreq,
- (event->events & 0x0001)?1:0);
+ case __constant_cpu_to_le16(TLV_TYPE_RSSI_LOW):
+ Lowrssi = (void *)(response_buf + cmd_len);
+ pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+ Lowrssi->rssivalue,
+ Lowrssi->rssifreq,
+ (event->events & cpu_to_le16(0x0001))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_snrthreshold);
break;
@@ -512,21 +493,20 @@ static u16 libertas_get_events_bitmap(wlan_private *priv)
return res;
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_get;
- pcmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+ event->action = cpu_to_le16(cmd_act_get);
+ pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
return 0;
}
@@ -538,7 +518,7 @@ static u16 libertas_get_events_bitmap(wlan_private *priv)
}
event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
- event_bitmap = event->events;
+ event_bitmap = le16_to_cpu(event->events);
kfree(response_buf);
return event_bitmap;
}
@@ -579,7 +559,7 @@ static ssize_t libertas_lowrssi_write(struct file *file,
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_set;
+ event->action = cpu_to_le16(cmd_act_set);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_rssithreshold));
@@ -588,30 +568,30 @@ static ssize_t libertas_lowrssi_write(struct file *file,
ptr = (u8*) pcmdptr+cmd_len;
rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
rssi_threshold->header.type = cpu_to_le16(0x0104);
- rssi_threshold->header.len = 2;
- rssi_threshold->rssivalue = cpu_to_le16(value);
- rssi_threshold->rssifreq = cpu_to_le16(freq);
+ rssi_threshold->header.len = cpu_to_le16(2);
+ rssi_threshold->rssivalue = value;
+ rssi_threshold->rssifreq = freq;
event_bitmap |= subscribed ? 0x0001 : 0x0;
- event->events = event_bitmap;
+ event->events = cpu_to_le16(event_bitmap);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -645,27 +625,26 @@ static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf,
}
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_get;
- pcmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+ event->action = cpu_to_le16(cmd_act_get);
+ pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -673,17 +652,17 @@ static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf,
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
- while (cmd_len < pcmdptr->size) {
- struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
- switch(header->type) {
+ event = (void *)(response_buf + S_DS_GEN);
+ while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+ struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+ switch (header->type) {
struct mrvlietypes_snrthreshold *LowSnr;
- case TLV_TYPE_SNR_LOW:
- LowSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- LowSnr->snrvalue,
- LowSnr->snrfreq,
- (event->events & 0x0002)?1:0);
+ case __constant_cpu_to_le16(TLV_TYPE_SNR_LOW):
+ LowSnr = (void *)(response_buf + cmd_len);
+ pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+ LowSnr->snrvalue,
+ LowSnr->snrfreq,
+ (event->events & cpu_to_le16(0x0002))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_snrthreshold);
break;
@@ -733,7 +712,7 @@ static ssize_t libertas_lowsnr_write(struct file *file,
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_set;
+ event->action = cpu_to_le16(cmd_act_set);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_snrthreshold));
@@ -741,30 +720,30 @@ static ssize_t libertas_lowsnr_write(struct file *file,
ptr = (u8*) pcmdptr+cmd_len;
snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW);
- snr_threshold->header.len = 2;
- snr_threshold->snrvalue = cpu_to_le16(value);
- snr_threshold->snrfreq = cpu_to_le16(freq);
+ snr_threshold->header.len = cpu_to_le16(2);
+ snr_threshold->snrvalue = value;
+ snr_threshold->snrfreq = freq;
event_bitmap |= subscribed ? 0x0002 : 0x0;
- event->events = event_bitmap;
+ event->events = cpu_to_le16(event_bitmap);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -799,27 +778,26 @@ static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf,
}
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_get;
- pcmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+ event->action = cpu_to_le16(cmd_act_get);
+ pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -827,17 +805,17 @@ static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf,
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
- while (cmd_len < pcmdptr->size) {
- struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
- switch(header->type) {
+ event = (void *)(response_buf + S_DS_GEN);
+ while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+ struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+ switch (header->type) {
struct mrvlietypes_failurecount *failcount;
- case TLV_TYPE_FAILCOUNT:
- failcount = (struct mrvlietypes_failurecount *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- failcount->failvalue,
- failcount->Failfreq,
- (event->events & 0x0004)?1:0);
+ case __constant_cpu_to_le16(TLV_TYPE_FAILCOUNT):
+ failcount = (void *)(response_buf + cmd_len);
+ pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+ failcount->failvalue,
+ failcount->Failfreq,
+ (event->events & cpu_to_le16(0x0004))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_failurecount);
break;
@@ -886,7 +864,7 @@ static ssize_t libertas_failcount_write(struct file *file,
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_set;
+ event->action = cpu_to_le16(cmd_act_set);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_failurecount));
@@ -894,30 +872,30 @@ static ssize_t libertas_failcount_write(struct file *file,
ptr = (u8*) pcmdptr+cmd_len;
failcount = (struct mrvlietypes_failurecount *)(ptr);
failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
- failcount->header.len = 2;
- failcount->failvalue = cpu_to_le16(value);
- failcount->Failfreq = cpu_to_le16(freq);
+ failcount->header.len = cpu_to_le16(2);
+ failcount->failvalue = value;
+ failcount->Failfreq = freq;
event_bitmap |= subscribed ? 0x0004 : 0x0;
- event->events = event_bitmap;
+ event->events = cpu_to_le16(event_bitmap);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = (struct cmd_ds_command *)response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -951,27 +929,26 @@ static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf,
}
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_get;
- pcmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+ event->action = cpu_to_le16(cmd_act_get);
+ pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
free_page(addr);
kfree(response_buf);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
free_page(addr);
kfree(response_buf);
@@ -979,16 +956,16 @@ static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf,
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
- while (cmd_len < pcmdptr->size) {
- struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
- switch(header->type) {
+ event = (void *)(response_buf + S_DS_GEN);
+ while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+ struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+ switch (header->type) {
struct mrvlietypes_beaconsmissed *bcnmiss;
- case TLV_TYPE_BCNMISS:
- bcnmiss = (struct mrvlietypes_beaconsmissed *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
- bcnmiss->beaconmissed,
- (event->events & 0x0008)?1:0);
+ case __constant_cpu_to_le16(TLV_TYPE_BCNMISS):
+ bcnmiss = (void *)(response_buf + cmd_len);
+ pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
+ bcnmiss->beaconmissed,
+ (event->events & cpu_to_le16(0x0008))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_beaconsmissed);
break;
@@ -1038,7 +1015,7 @@ static ssize_t libertas_bcnmiss_write(struct file *file,
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_set;
+ event->action = cpu_to_le16(cmd_act_set);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_beaconsmissed));
@@ -1046,29 +1023,29 @@ static ssize_t libertas_bcnmiss_write(struct file *file,
ptr = (u8*) pcmdptr+cmd_len;
bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr);
bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS);
- bcnmiss->header.len = 2;
- bcnmiss->beaconmissed = cpu_to_le16(value);
+ bcnmiss->header.len = cpu_to_le16(2);
+ bcnmiss->beaconmissed = value;
event_bitmap |= subscribed ? 0x0008 : 0x0;
- event->events = event_bitmap;
+ event->events = cpu_to_le16(event_bitmap);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
free_page(addr);
kfree(response_buf);
@@ -1102,27 +1079,26 @@ static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf,
}
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_get;
- pcmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+ event->action = cpu_to_le16(cmd_act_get);
+ pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -1130,17 +1106,17 @@ static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf,
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
- while (cmd_len < pcmdptr->size) {
- struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
- switch(header->type) {
+ event = (void *)(response_buf + S_DS_GEN);
+ while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+ struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+ switch (header->type) {
struct mrvlietypes_rssithreshold *Highrssi;
- case TLV_TYPE_RSSI_HIGH:
- Highrssi = (struct mrvlietypes_rssithreshold *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- Highrssi->rssivalue,
- Highrssi->rssifreq,
- (event->events & 0x0010)?1:0);
+ case __constant_cpu_to_le16(TLV_TYPE_RSSI_HIGH):
+ Highrssi = (void *)(response_buf + cmd_len);
+ pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+ Highrssi->rssivalue,
+ Highrssi->rssifreq,
+ (event->events & cpu_to_le16(0x0010))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_snrthreshold);
break;
@@ -1190,7 +1166,7 @@ static ssize_t libertas_highrssi_write(struct file *file,
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_set;
+ event->action = cpu_to_le16(cmd_act_set);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_rssithreshold));
@@ -1198,29 +1174,29 @@ static ssize_t libertas_highrssi_write(struct file *file,
ptr = (u8*) pcmdptr+cmd_len;
rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
- rssi_threshold->header.len = 2;
- rssi_threshold->rssivalue = cpu_to_le16(value);
- rssi_threshold->rssifreq = cpu_to_le16(freq);
+ rssi_threshold->header.len = cpu_to_le16(2);
+ rssi_threshold->rssivalue = value;
+ rssi_threshold->rssifreq = freq;
event_bitmap |= subscribed ? 0x0010 : 0x0;
- event->events = event_bitmap;
+ event->events = cpu_to_le16(event_bitmap);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
return 0;
@@ -1253,27 +1229,26 @@ static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf,
}
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_get;
- pcmdptr->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_subscribe_event) + S_DS_GEN);
+ event->action = cpu_to_le16(cmd_act_get);
+ pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -1281,17 +1256,17 @@ static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf,
}
cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
- while (cmd_len < pcmdptr->size) {
- struct mrvlietypesheader *header = (struct mrvlietypesheader *)(response_buf + cmd_len);
- switch(header->type) {
+ event = (void *)(response_buf + S_DS_GEN);
+ while (cmd_len < le16_to_cpu(pcmdptr->size)) {
+ struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
+ switch (header->type) {
struct mrvlietypes_snrthreshold *HighSnr;
- case TLV_TYPE_SNR_HIGH:
- HighSnr = (struct mrvlietypes_snrthreshold *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- HighSnr->snrvalue,
- HighSnr->snrfreq,
- (event->events & 0x0020)?1:0);
+ case __constant_cpu_to_le16(TLV_TYPE_SNR_HIGH):
+ HighSnr = (void *)(response_buf + cmd_len);
+ pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
+ HighSnr->snrvalue,
+ HighSnr->snrfreq,
+ (event->events & cpu_to_le16(0x0020))?1:0);
default:
cmd_len += sizeof(struct mrvlietypes_snrthreshold);
break;
@@ -1341,7 +1316,7 @@ static ssize_t libertas_highsnr_write(struct file *file,
goto out_unlock;
event = &pcmdptr->params.subscribe_event;
- event->action = cmd_act_set;
+ event->action = cpu_to_le16(cmd_act_set);
pcmdptr->size = cpu_to_le16(S_DS_GEN +
sizeof(struct cmd_ds_802_11_subscribe_event) +
sizeof(struct mrvlietypes_snrthreshold));
@@ -1349,30 +1324,30 @@ static ssize_t libertas_highsnr_write(struct file *file,
ptr = (u8*) pcmdptr+cmd_len;
snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH);
- snr_threshold->header.len = 2;
- snr_threshold->snrvalue = cpu_to_le16(value);
- snr_threshold->snrfreq = cpu_to_le16(freq);
+ snr_threshold->header.len = cpu_to_le16(2);
+ snr_threshold->snrvalue = value;
+ snr_threshold->snrfreq = freq;
event_bitmap |= subscribed ? 0x0020 : 0x0;
- event->events = event_bitmap;
+ event->events = cpu_to_le16(event_bitmap);
libertas_queue_cmd(adapter, pcmdnode, 1);
wake_up_interruptible(&priv->mainthread.waitq);
/* Sleep until response is generated by FW */
wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ pcmdnode->cmdwaitqwoken);
pcmdptr = response_buf;
if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __FUNCTION__,
- pcmdptr->result);
+ lbs_pr_err("%s: fail, result=%d\n", __func__,
+ le16_to_cpu(pcmdptr->result));
kfree(response_buf);
free_page(addr);
return 0;
}
- if (pcmdptr->command != cmd_ret_802_11_subscribe_event) {
+ if (pcmdptr->command != cpu_to_le16(cmd_ret_802_11_subscribe_event)) {
lbs_pr_err("command response incorrect!\n");
kfree(response_buf);
free_page(addr);
@@ -1760,7 +1735,7 @@ void libertas_debugfs_remove_one(wlan_private *priv)
debugfs_remove(priv->regs_dir);
- for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
+ for(i=0; i<ARRAY_SIZE(debugfs_events_files); i++)
debugfs_remove(priv->debugfs_events_files[i]);
debugfs_remove(priv->events_dir);
@@ -1769,13 +1744,19 @@ void libertas_debugfs_remove_one(wlan_private *priv)
#endif
for(i=0; i<ARRAY_SIZE(debugfs_files); i++)
debugfs_remove(priv->debugfs_files[i]);
+ debugfs_remove(priv->debugfs_dir);
}
+
+
/* debug entry */
+#ifdef PROC_DEBUG
+
#define item_size(n) (FIELD_SIZEOF(wlan_adapter, n))
#define item_addr(n) (offsetof(wlan_adapter, n))
+
struct debug_data {
char name[32];
u32 size;
@@ -1863,7 +1844,7 @@ static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf,
return 0;
if (copy_from_user(pdata, buf, cnt)) {
- lbs_pr_debug(1, "Copy from user failed\n");
+ lbs_deb_debugfs("Copy from user failed\n");
kfree(pdata);
return 0;
}
@@ -1913,7 +1894,7 @@ static struct file_operations libertas_debug_fops = {
* @param dev pointer net_device
* @return N/A
*/
-void libertas_debug_init(wlan_private * priv, struct net_device *dev)
+static void libertas_debug_init(wlan_private * priv, struct net_device *dev)
{
int i;
@@ -1927,4 +1908,5 @@ void libertas_debug_init(wlan_private * priv, struct net_device *dev)
priv->debugfs_dir, &items[0],
&libertas_debug_fops);
}
+#endif
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index dfe27642322..40f56bb1eac 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -6,6 +6,8 @@
#ifndef _WLAN_DECL_H_
#define _WLAN_DECL_H_
+#include <linux/device.h>
+
#include "defs.h"
/** Function Prototype Declaration */
@@ -66,18 +68,24 @@ void libertas_ps_wakeup(wlan_private * priv, int wait_option);
void libertas_tx_runqueue(wlan_private *priv);
-extern struct chan_freq_power *libertas_find_cfp_by_band_and_channel(
+struct chan_freq_power *libertas_find_cfp_by_band_and_channel(
wlan_adapter * adapter, u8 band, u16 channel);
-extern void libertas_mac_event_disconnected(wlan_private * priv);
+void libertas_mac_event_disconnected(wlan_private * priv);
void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str);
-int reset_device(wlan_private *priv);
+/* fw.c */
+int libertas_init_fw(wlan_private * priv, char *fw_name);
+
/* main.c */
-extern struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band,
+struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band,
int *cfp_no);
-wlan_private *wlan_add_card(void *card);
-int wlan_remove_card(void *card);
+wlan_private *libertas_add_card(void *card, struct device *dmdev);
+int libertas_activate_card(wlan_private *priv, char *fw_name);
+int libertas_remove_card(wlan_private *priv);
+int libertas_add_mesh(wlan_private *priv, struct device *dev);
+void libertas_remove_mesh(wlan_private *priv);
+
#endif /* _WLAN_DECL_H_ */
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 80dd9ea19c8..4dd43e59bda 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -7,14 +7,79 @@
#include <linux/spinlock.h>
-extern unsigned int libertas_debug;
-
#ifdef CONFIG_LIBERTAS_DEBUG
#define DEBUG
#define PROC_DEBUG
#endif
-#define DRV_NAME "usb8xxx"
+#ifndef DRV_NAME
+#define DRV_NAME "libertas"
+#endif
+
+
+#define LBS_DEB_ENTER 0x00000001
+#define LBS_DEB_LEAVE 0x00000002
+#define LBS_DEB_MAIN 0x00000004
+#define LBS_DEB_NET 0x00000008
+#define LBS_DEB_MESH 0x00000010
+#define LBS_DEB_WEXT 0x00000020
+#define LBS_DEB_IOCTL 0x00000040
+#define LBS_DEB_SCAN 0x00000080
+#define LBS_DEB_ASSOC 0x00000100
+#define LBS_DEB_JOIN 0x00000200
+#define LBS_DEB_11D 0x00000400
+#define LBS_DEB_DEBUGFS 0x00000800
+#define LBS_DEB_ETHTOOL 0x00001000
+#define LBS_DEB_HOST 0x00002000
+#define LBS_DEB_CMD 0x00004000
+#define LBS_DEB_RX 0x00008000
+#define LBS_DEB_TX 0x00010000
+#define LBS_DEB_USB 0x00020000
+#define LBS_DEB_CS 0x00040000
+#define LBS_DEB_FW 0x00080000
+#define LBS_DEB_THREAD 0x00100000
+#define LBS_DEB_HEX 0x00200000
+
+extern unsigned int libertas_debug;
+
+#ifdef DEBUG
+#define LBS_DEB_LL(grp, fmt, args...) \
+do { if ((libertas_debug & (grp)) == (grp)) \
+ printk(KERN_DEBUG DRV_NAME "%s: " fmt, \
+ in_interrupt() ? " (INT)" : "", ## args); } while (0)
+#else
+#define LBS_DEB_LL(grp, fmt, args...) do {} while (0)
+#endif
+
+#define lbs_deb_enter(grp) \
+ LBS_DEB_LL(grp | LBS_DEB_ENTER, "%s():%d enter\n", __FUNCTION__, __LINE__);
+#define lbs_deb_enter_args(grp, fmt, args...) \
+ LBS_DEB_LL(grp | LBS_DEB_ENTER, "%s(" fmt "):%d\n", __FUNCTION__, ## args, __LINE__);
+#define lbs_deb_leave(grp) \
+ LBS_DEB_LL(grp | LBS_DEB_LEAVE, "%s():%d leave\n", __FUNCTION__, __LINE__);
+#define lbs_deb_leave_args(grp, fmt, args...) \
+ LBS_DEB_LL(grp | LBS_DEB_LEAVE, "%s():%d leave, " fmt "\n", \
+ __FUNCTION__, __LINE__, ##args);
+#define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, fmt, ##args)
+#define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, fmt, ##args)
+#define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, fmt, ##args)
+#define lbs_deb_wext(fmt, args...) LBS_DEB_LL(LBS_DEB_WEXT, fmt, ##args)
+#define lbs_deb_ioctl(fmt, args...) LBS_DEB_LL(LBS_DEB_IOCTL, fmt, ##args)
+#define lbs_deb_scan(fmt, args...) LBS_DEB_LL(LBS_DEB_SCAN, fmt, ##args)
+#define lbs_deb_assoc(fmt, args...) LBS_DEB_LL(LBS_DEB_ASSOC, fmt, ##args)
+#define lbs_deb_join(fmt, args...) LBS_DEB_LL(LBS_DEB_JOIN, fmt, ##args)
+#define lbs_deb_11d(fmt, args...) LBS_DEB_LL(LBS_DEB_11D, fmt, ##args)
+#define lbs_deb_debugfs(fmt, args...) LBS_DEB_LL(LBS_DEB_DEBUGFS, fmt, ##args)
+#define lbs_deb_ethtool(fmt, args...) LBS_DEB_LL(LBS_DEB_ETHTOOL, fmt, ##args)
+#define lbs_deb_host(fmt, args...) LBS_DEB_LL(LBS_DEB_HOST, fmt, ##args)
+#define lbs_deb_cmd(fmt, args...) LBS_DEB_LL(LBS_DEB_CMD, fmt, ##args)
+#define lbs_deb_rx(fmt, args...) LBS_DEB_LL(LBS_DEB_RX, fmt, ##args)
+#define lbs_deb_tx(fmt, args...) LBS_DEB_LL(LBS_DEB_TX, fmt, ##args)
+#define lbs_deb_fw(fmt, args...) LBS_DEB_LL(LBS_DEB_FW, fmt, ##args)
+#define lbs_deb_usb(fmt, args...) LBS_DEB_LL(LBS_DEB_USB, fmt, ##args)
+#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, "%s:" fmt, (dev)->bus_id, ##args)
+#define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, fmt, ##args)
+#define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, fmt, ##args)
#define lbs_pr_info(format, args...) \
printk(KERN_INFO DRV_NAME": " format, ## args)
@@ -24,37 +89,25 @@ extern unsigned int libertas_debug;
printk(KERN_ALERT DRV_NAME": " format, ## args)
#ifdef DEBUG
-#define lbs_pr_debug(level, format, args...) \
- do { if (libertas_debug >= level) \
- printk(KERN_INFO DRV_NAME": " format, ##args); } while (0)
-#define lbs_dev_dbg(level, device, format, args...) \
- lbs_pr_debug(level, "%s: " format, \
- (device)->bus_id , ## args)
-
static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len)
{
int i = 0;
- if (!libertas_debug)
+ if (!(libertas_debug & LBS_DEB_HEX))
return;
printk(KERN_DEBUG "%s: ", prompt);
for (i = 1; i <= len; i++) {
- printk(KERN_DEBUG "%02x ", (u8) * buf);
+ printk("%02x ", (u8) * buf);
buf++;
}
printk("\n");
}
#else
-#define lbs_pr_debug(level, format, args...) do {} while (0)
-#define lbs_dev_dbg(level, device, format, args...) do {} while (0)
#define lbs_dbg_hex(x,y,z) do {} while (0)
#endif
-#define ENTER() lbs_pr_debug(1, "Enter: %s, %s:%i\n", \
- __FUNCTION__, __FILE__, __LINE__)
-#define LEAVE() lbs_pr_debug(1, "Leave: %s, %s:%i\n", \
- __FUNCTION__, __FILE__, __LINE__)
+
/** Buffer Constants */
@@ -74,7 +127,6 @@ static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len)
#define MRVDRV_NUM_OF_CMD_BUFFER 10
#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
#define MRVDRV_MAX_CHANNEL_SIZE 14
-#define MRVDRV_MAX_BSSID_LIST 64
#define MRVDRV_ASSOCIATION_TIME_OUT 255
#define MRVDRV_SNAP_HEADER_LEN 8
@@ -104,6 +156,13 @@ static inline void lbs_dbg_hex(char *prompt, u8 * buf, int len)
#define MRVDRV_MAX_BEACON_INTERVAL 1000
#define MRVDRV_BEACON_INTERVAL 100
+/** INT status Bit Definition*/
+#define his_cmddnldrdy 0x01
+#define his_cardevent 0x02
+#define his_cmdupldrdy 0x04
+
+#define SBI_EVENT_CAUSE_SHIFT 3
+
/** TxPD status */
/* Station firmware use TxPD status field to report final Tx transmit
@@ -205,8 +264,6 @@ typedef struct _wlan_adapter wlan_adapter;
extern const char libertas_driver_version[];
extern u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE];
-extern u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES];
-
extern u8 libertas_supported_rates[G_SUPPORTED_RATES];
extern u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES];
@@ -316,6 +373,8 @@ enum SNMP_MIB_VALUE_e {
/* Default values for fwt commands. */
#define FWT_DEFAULT_METRIC 0
#define FWT_DEFAULT_DIR 1
+/* Default Rate, 11Mbps */
+#define FWT_DEFAULT_RATE 3
#define FWT_DEFAULT_SSN 0xffffffff
#define FWT_DEFAULT_DSN 0
#define FWT_DEFAULT_HOPCOUNT 0
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index e8b9020f9bd..785192b884b 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -63,11 +63,11 @@ struct wlan_802_11_security {
/** Current Basic Service Set State Structure */
struct current_bss_params {
- struct bss_descriptor bssdescriptor;
/** bssid */
u8 bssid[ETH_ALEN];
/** ssid */
- struct WLAN_802_11_SSID ssid;
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 ssid_len;
/** band */
u8 band;
@@ -89,31 +89,6 @@ struct sleep_params {
u16 sp_reserved;
};
-/** Data structure for the Marvell WLAN device */
-typedef struct _wlan_dev {
- /** device name */
- char name[DEV_NAME_LEN];
- /** card pointer */
- void *card;
- /** IO port */
- u32 ioport;
- /** Upload received */
- u32 upld_rcv;
- /** Upload type */
- u32 upld_typ;
- /** Upload length */
- u32 upld_len;
- /** netdev pointer */
- struct net_device *netdev;
- /* Upload buffer */
- u8 upld_buf[WLAN_UPLD_SIZE];
- /* Download sent:
- bit0 1/0=data_sent/data_tx_done,
- bit1 1/0=cmd_sent/cmd_tx_done,
- all other bits reserved 0 */
- u8 dnld_sent;
-} wlan_dev_t, *pwlan_dev_t;
-
/* Mesh statistics */
struct wlan_mesh_stats {
u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
@@ -123,6 +98,7 @@ struct wlan_mesh_stats {
u32 fwd_drop_noroute; /* Fwd: No route to Destination */
u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
u32 drop_blind; /* Rx: Dropped by blinding table */
+ u32 tx_failed_cnt; /* Tx: Failed transmissions */
};
/** Private structure for the MV device */
@@ -131,8 +107,11 @@ struct _wlan_private {
int mesh_open;
int infra_open;
+ char name[DEV_NAME_LEN];
+
+ void *card;
wlan_adapter *adapter;
- wlan_dev_t wlan_dev;
+ struct net_device *dev;
struct net_device_stats stats;
struct net_device *mesh_dev ; /* Virtual device */
@@ -153,6 +132,16 @@ struct _wlan_private {
u32 bbp_offset;
u32 rf_offset;
+ /** Upload length */
+ u32 upld_len;
+ /* Upload buffer */
+ u8 upld_buf[WLAN_UPLD_SIZE];
+ /* Download sent:
+ bit0 1/0=data_sent/data_tx_done,
+ bit1 1/0=cmd_sent/cmd_tx_done,
+ all other bits reserved 0 */
+ u8 dnld_sent;
+
const struct firmware *firmware;
struct device *hotplug_device;
@@ -161,6 +150,15 @@ struct _wlan_private {
struct delayed_work assoc_work;
struct workqueue_struct *assoc_thread;
+ struct work_struct sync_channel;
+
+ /** Hardware access */
+ int (*hw_register_dev) (wlan_private * priv);
+ int (*hw_unregister_dev) (wlan_private *);
+ int (*hw_prog_firmware) (wlan_private *);
+ int (*hw_host_to_card) (wlan_private * priv, u8 type, u8 * payload, u16 nb);
+ int (*hw_get_int_status) (wlan_private * priv, u8 *);
+ int (*hw_read_event_cause) (wlan_private *);
};
/** Association request
@@ -171,18 +169,21 @@ struct _wlan_private {
struct assoc_request {
#define ASSOC_FLAG_SSID 1
#define ASSOC_FLAG_CHANNEL 2
-#define ASSOC_FLAG_MODE 3
-#define ASSOC_FLAG_BSSID 4
-#define ASSOC_FLAG_WEP_KEYS 5
-#define ASSOC_FLAG_WEP_TX_KEYIDX 6
-#define ASSOC_FLAG_WPA_MCAST_KEY 7
-#define ASSOC_FLAG_WPA_UCAST_KEY 8
-#define ASSOC_FLAG_SECINFO 9
-#define ASSOC_FLAG_WPA_IE 10
+#define ASSOC_FLAG_BAND 3
+#define ASSOC_FLAG_MODE 4
+#define ASSOC_FLAG_BSSID 5
+#define ASSOC_FLAG_WEP_KEYS 6
+#define ASSOC_FLAG_WEP_TX_KEYIDX 7
+#define ASSOC_FLAG_WPA_MCAST_KEY 8
+#define ASSOC_FLAG_WPA_UCAST_KEY 9
+#define ASSOC_FLAG_SECINFO 10
+#define ASSOC_FLAG_WPA_IE 11
unsigned long flags;
- struct WLAN_802_11_SSID ssid;
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 ssid_len;
u8 channel;
+ u8 band;
u8 mode;
u8 bssid[ETH_ALEN];
@@ -199,12 +200,15 @@ struct assoc_request {
/** WPA Information Elements*/
u8 wpa_ie[MAX_WPA_IE_LEN];
u8 wpa_ie_len;
+
+ /* BSS to associate with for infrastructure of Ad-Hoc join */
+ struct bss_descriptor bss;
};
/** Wlan adapter data structure*/
struct _wlan_adapter {
/** STATUS variables */
- u32 fwreleasenumber;
+ u8 fwreleasenumber[4];
u32 fwcapinfo;
/* protected with big lock */
@@ -255,13 +259,14 @@ struct _wlan_adapter {
/* IW_MODE_* */
u8 mode;
- struct bss_descriptor *pattemptedbssdesc;
-
- struct WLAN_802_11_SSID previousssid;
- u8 previousbssid[ETH_ALEN];
+ u8 prev_ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 prev_ssid_len;
+ u8 prev_bssid[ETH_ALEN];
- struct bss_descriptor *scantable;
- u32 numinscantable;
+ /* Scan results list */
+ struct list_head network_list;
+ struct list_head network_free_list;
+ struct bss_descriptor *networks;
u8 scantype;
u32 scanmode;
@@ -288,7 +293,6 @@ struct _wlan_adapter {
u32 txantenna;
u32 rxantenna;
- u8 adhocchannel;
u32 fragthsd;
u32 rtsthsd;
@@ -324,7 +328,8 @@ struct _wlan_adapter {
u16 locallisteninterval;
u16 nullpktinterval;
- struct assoc_request * assoc_req;
+ struct assoc_request * pending_assoc_req;
+ struct assoc_request * in_progress_assoc_req;
/** Encryption parameter */
struct wlan_802_11_security secinfo;
@@ -396,6 +401,8 @@ struct _wlan_adapter {
u32 radiomode;
u32 debugmode;
u8 fw_ready;
+
+ u8 last_scanned_channel;
};
#endif /* _WLAN_DEV_H_ */
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 0064de54296..96f1974685d 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -1,10 +1,8 @@
-
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
#include "host.h"
-#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
@@ -17,7 +15,8 @@ static const char * mesh_stat_strings[]= {
"drop_no_buffers",
"fwded_unicast_cnt",
"fwded_bcast_cnt",
- "drop_blind_table"
+ "drop_blind_table",
+ "tx_failed_cnt"
};
static void libertas_ethtool_get_drvinfo(struct net_device *dev,
@@ -69,7 +68,7 @@ static int libertas_ethtool_get_eeprom(struct net_device *dev,
/* +14 is for action, offset, and NOB in
* response */
- lbs_pr_debug(1, "action:%d offset: %x NOB: %02x\n",
+ lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n",
regctrl.action, regctrl.offset, regctrl.NOB);
ret = libertas_prepare_and_send_command(priv,
@@ -81,8 +80,7 @@ static int libertas_ethtool_get_eeprom(struct net_device *dev,
if (ret) {
if (adapter->prdeeprom)
kfree(adapter->prdeeprom);
- LEAVE();
- return ret;
+ goto done;
}
mdelay(10);
@@ -101,7 +99,11 @@ static int libertas_ethtool_get_eeprom(struct net_device *dev,
kfree(adapter->prdeeprom);
// mutex_unlock(&priv->mutex);
- return 0;
+ ret = 0;
+
+done:
+ lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret);
+ return ret;
}
static void libertas_ethtool_get_stats(struct net_device * dev,
@@ -109,7 +111,7 @@ static void libertas_ethtool_get_stats(struct net_device * dev,
{
wlan_private *priv = dev->priv;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ETHTOOL);
stats->cmd = ETHTOOL_GSTATS;
BUG_ON(stats->n_stats != MESH_STATS_NUM);
@@ -121,8 +123,9 @@ static void libertas_ethtool_get_stats(struct net_device * dev,
data[4] = priv->mstats.fwd_unicast_cnt;
data[5] = priv->mstats.fwd_bcast_cnt;
data[6] = priv->mstats.drop_blind;
+ data[7] = priv->mstats.tx_failed_cnt;
- LEAVE();
+ lbs_deb_enter(LBS_DEB_ETHTOOL);
}
static int libertas_ethtool_get_stats_count(struct net_device * dev)
@@ -131,27 +134,32 @@ static int libertas_ethtool_get_stats_count(struct net_device * dev)
wlan_private *priv = dev->priv;
struct cmd_ds_mesh_access mesh_access;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ETHTOOL);
+
/* Get Mesh Statistics */
ret = libertas_prepare_and_send_command(priv,
cmd_mesh_access, cmd_act_mesh_get_stats,
cmd_option_waitforrsp, 0, &mesh_access);
if (ret) {
- LEAVE();
- return 0;
+ ret = 0;
+ goto done;
}
- priv->mstats.fwd_drop_rbt = mesh_access.data[0];
- priv->mstats.fwd_drop_ttl = mesh_access.data[1];
- priv->mstats.fwd_drop_noroute = mesh_access.data[2];
- priv->mstats.fwd_drop_nobuf = mesh_access.data[3];
- priv->mstats.fwd_unicast_cnt = mesh_access.data[4];
- priv->mstats.fwd_bcast_cnt = mesh_access.data[5];
- priv->mstats.drop_blind = mesh_access.data[6];
+ priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
+ priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
+ priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
+ priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
+ priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
+ priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
+ priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
+ priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
- LEAVE();
- return MESH_STATS_NUM;
+ ret = MESH_STATS_NUM;
+
+done:
+ lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret);
+ return ret;
}
static void libertas_ethtool_get_strings (struct net_device * dev,
@@ -160,7 +168,8 @@ static void libertas_ethtool_get_strings (struct net_device * dev,
{
int i;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ETHTOOL);
+
switch (stringset) {
case ETH_SS_STATS:
for (i=0; i < MESH_STATS_NUM; i++) {
@@ -170,7 +179,7 @@ static void libertas_ethtool_get_strings (struct net_device * dev,
}
break;
}
- LEAVE();
+ lbs_deb_enter(LBS_DEB_ETHTOOL);
}
struct ethtool_ops libertas_ethtool_ops = {
diff --git a/drivers/net/wireless/libertas/fw.c b/drivers/net/wireless/libertas/fw.c
index 5c63c9b1659..2dc84ff7a54 100644
--- a/drivers/net/wireless/libertas/fw.c
+++ b/drivers/net/wireless/libertas/fw.c
@@ -1,28 +1,15 @@
/**
* This file contains the initialization for FW and HW
*/
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/vmalloc.h>
#include <linux/firmware.h>
-#include <linux/version.h>
#include "host.h"
-#include "sbi.h"
#include "defs.h"
#include "decl.h"
#include "dev.h"
-#include "fw.h"
#include "wext.h"
#include "if_usb.h"
-char *libertas_fw_name = NULL;
-module_param_named(fw_name, libertas_fw_name, charp, 0644);
-
-unsigned int libertas_debug = 0;
-module_param(libertas_debug, int, 0);
-
/**
* @brief This function checks the validity of Boot2/FW image.
*
@@ -32,7 +19,7 @@ module_param(libertas_debug, int, 0);
*/
static int check_fwfile_format(u8 *data, u32 totlen)
{
- u8 bincmd, exit;
+ u32 bincmd, exit;
u32 blksize, offset, len;
int ret;
@@ -40,8 +27,10 @@ static int check_fwfile_format(u8 *data, u32 totlen)
exit = len = 0;
do {
- bincmd = *data;
- blksize = *(u32*)(data + offsetof(struct fwheader, datalength));
+ struct fwheader *fwh = (void *)data;
+
+ bincmd = le32_to_cpu(fwh->dnldcmd);
+ blksize = le32_to_cpu(fwh->datalength);
switch (bincmd) {
case FW_HAS_DATA_TO_RECV:
offset = sizeof(struct fwheader) + blksize;
@@ -61,9 +50,9 @@ static int check_fwfile_format(u8 *data, u32 totlen)
} while (!exit);
if (ret)
- lbs_pr_err("bin file format check FAIL...\n");
+ lbs_pr_err("firmware file format check FAIL\n");
else
- lbs_pr_debug(1, "bin file format check PASS...\n");
+ lbs_deb_fw("firmware file format check PASS\n");
return ret;
}
@@ -76,32 +65,31 @@ static int check_fwfile_format(u8 *data, u32 totlen)
* @param priv A pointer to wlan_private structure
* @return 0 or -1
*/
-static int wlan_setup_station_hw(wlan_private * priv)
+static int wlan_setup_station_hw(wlan_private * priv, char *fw_name)
{
int ret = -1;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_FW);
- if ((ret = request_firmware(&priv->firmware, libertas_fw_name,
+ if ((ret = request_firmware(&priv->firmware, fw_name,
priv->hotplug_device)) < 0) {
- lbs_pr_err("request_firmware() failed, error code = %#x\n",
- ret);
- lbs_pr_err("%s not found in /lib/firmware\n", libertas_fw_name);
+ lbs_pr_err("request_firmware() failed with %#x\n", ret);
+ lbs_pr_err("firmware %s not found\n", fw_name);
goto done;
}
- if(check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
+ if (check_fwfile_format(priv->firmware->data, priv->firmware->size)) {
release_firmware(priv->firmware);
goto done;
}
- ret = libertas_sbi_prog_firmware(priv);
+ ret = priv->hw_prog_firmware(priv);
release_firmware(priv->firmware);
if (ret) {
- lbs_pr_debug(1, "Bootloader in invalid state!\n");
+ lbs_deb_fw("bootloader in invalid state\n");
ret = -1;
goto done;
}
@@ -133,28 +121,24 @@ static int wlan_setup_station_hw(wlan_private * priv)
ret = 0;
done:
- LEAVE();
-
- return (ret);
+ lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+ return ret;
}
static int wlan_allocate_adapter(wlan_private * priv)
{
- u32 ulbufsize;
+ size_t bufsize;
wlan_adapter *adapter = priv->adapter;
- struct bss_descriptor *ptempscantable;
-
/* Allocate buffer to store the BSSID list */
- ulbufsize = sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST;
- if (!(ptempscantable = kmalloc(ulbufsize, GFP_KERNEL))) {
+ bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
+ adapter->networks = kzalloc(bufsize, GFP_KERNEL);
+ if (!adapter->networks) {
+ lbs_pr_err("Out of memory allocating beacons\n");
libertas_free_adapter(priv);
- return -1;
+ return -ENOMEM;
}
- adapter->scantable = ptempscantable;
- memset(adapter->scantable, 0, ulbufsize);
-
/* Allocate the command buffers */
libertas_allocate_cmd_buffer(priv);
@@ -202,15 +186,23 @@ static void wlan_init_adapter(wlan_private * priv)
adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
adapter->mode = IW_MODE_INFRA;
- adapter->assoc_req = NULL;
+ adapter->pending_assoc_req = NULL;
+ adapter->in_progress_assoc_req = NULL;
+
+ /* Initialize scan result lists */
+ INIT_LIST_HEAD(&adapter->network_free_list);
+ INIT_LIST_HEAD(&adapter->network_list);
+ for (i = 0; i < MAX_NETWORK_COUNT; i++) {
+ list_add_tail(&adapter->networks[i].list,
+ &adapter->network_free_list);
+ }
- adapter->numinscantable = 0;
- adapter->pattemptedbssdesc = NULL;
mutex_init(&adapter->lock);
adapter->prescan = 1;
memset(&adapter->curbssparams, 0, sizeof(adapter->curbssparams));
+ adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
/* PnP and power profile */
adapter->surpriseremoved = 0;
@@ -230,8 +222,6 @@ static void wlan_init_adapter(wlan_private * priv)
memset(&adapter->capinfo, 0, sizeof(adapter->capinfo));
adapter->capinfo.shortpreamble = SHORT_PREAMBLE_ALLOWED;
- adapter->adhocchannel = DEFAULT_AD_HOC_CHANNEL;
-
adapter->psmode = wlan802_11powermodecam;
adapter->multipledtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
@@ -259,12 +249,12 @@ static void wlan_init_adapter(wlan_private * priv)
static void command_timer_fn(unsigned long data);
-int libertas_init_fw(wlan_private * priv)
+int libertas_init_fw(wlan_private * priv, char *fw_name)
{
int ret = -1;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_FW);
/* Allocate adapter structure */
if ((ret = wlan_allocate_adapter(priv)) != 0)
@@ -278,7 +268,7 @@ int libertas_init_fw(wlan_private * priv)
(unsigned long)priv);
/* download fimrware etc. */
- if ((ret = wlan_setup_station_hw(priv)) != 0) {
+ if ((ret = wlan_setup_station_hw(priv, fw_name)) != 0) {
del_timer_sync(&adapter->command_timer);
goto done;
}
@@ -288,7 +278,7 @@ int libertas_init_fw(wlan_private * priv)
ret = 0;
done:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
return ret;
}
@@ -297,25 +287,22 @@ void libertas_free_adapter(wlan_private * priv)
wlan_adapter *adapter = priv->adapter;
if (!adapter) {
- lbs_pr_debug(1, "Why double free adapter?:)\n");
+ lbs_deb_fw("why double free adapter?\n");
return;
}
- lbs_pr_debug(1, "Free command buffer\n");
+ lbs_deb_fw("free command buffer\n");
libertas_free_cmd_buffer(priv);
- lbs_pr_debug(1, "Free commandTimer\n");
+ lbs_deb_fw("free command_timer\n");
del_timer(&adapter->command_timer);
- lbs_pr_debug(1, "Free scantable\n");
- if (adapter->scantable) {
- kfree(adapter->scantable);
- adapter->scantable = NULL;
- }
-
- lbs_pr_debug(1, "Free adapter\n");
+ lbs_deb_fw("free scan results table\n");
+ kfree(adapter->networks);
+ adapter->networks = NULL;
/* Free the adapter object itself */
+ lbs_deb_fw("free adapter\n");
kfree(adapter);
priv->adapter = NULL;
}
@@ -334,17 +321,17 @@ static void command_timer_fn(unsigned long data)
ptempnode = adapter->cur_cmd;
if (ptempnode == NULL) {
- lbs_pr_debug(1, "PTempnode Empty\n");
+ lbs_deb_fw("ptempnode empty\n");
return;
}
cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr;
if (!cmd) {
- lbs_pr_debug(1, "cmd is NULL\n");
+ lbs_deb_fw("cmd is NULL\n");
return;
}
- lbs_pr_info("command_timer_fn fired (%x)\n", cmd->command);
+ lbs_deb_fw("command_timer_fn fired, cmd %x\n", cmd->command);
if (!adapter->fw_ready)
return;
@@ -353,7 +340,7 @@ static void command_timer_fn(unsigned long data)
adapter->cur_cmd = NULL;
spin_unlock_irqrestore(&adapter->driver_lock, flags);
- lbs_pr_debug(1, "Re-sending same command as it timeout...!\n");
+ lbs_deb_fw("re-sending same command because of timeout\n");
libertas_queue_cmd(adapter, ptempnode, 0);
wake_up_interruptible(&priv->mainthread.waitq);
diff --git a/drivers/net/wireless/libertas/fw.h b/drivers/net/wireless/libertas/fw.h
deleted file mode 100644
index 1f9ae267a9e..00000000000
--- a/drivers/net/wireless/libertas/fw.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * This header file contains FW interface related definitions.
- */
-#ifndef _WLAN_FW_H_
-#define _WLAN_FW_H_
-
-#ifndef DEV_NAME_LEN
-#define DEV_NAME_LEN 32
-#endif
-
-int libertas_init_fw(wlan_private * priv);
-
-#endif /* _WLAN_FW_H_ */
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index c0faaecaf5b..7509cc10af3 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -99,11 +99,11 @@
#define cmd_bt_access 0x0087
#define cmd_ret_bt_access 0x8087
-#define cmd_fwt_access 0x0088
-#define cmd_ret_fwt_access 0x8088
+#define cmd_fwt_access 0x0095
+#define cmd_ret_fwt_access 0x8095
-#define cmd_mesh_access 0x0090
-#define cmd_ret_mesh_access 0x8090
+#define cmd_mesh_access 0x009b
+#define cmd_ret_mesh_access 0x809b
/* For the IEEE Power Save */
#define cmd_subcmd_enter_ps 0x0030
@@ -287,7 +287,9 @@ enum cmd_bt_access_opts {
cmd_act_bt_access_add = 5,
cmd_act_bt_access_del,
cmd_act_bt_access_list,
- cmd_act_bt_access_reset
+ cmd_act_bt_access_reset,
+ cmd_act_bt_access_set_invert,
+ cmd_act_bt_access_get_invert
};
/* Define action or option for cmd_fwt_access */
@@ -308,8 +310,8 @@ enum cmd_mesh_access_opts {
cmd_act_mesh_get_ttl = 1,
cmd_act_mesh_set_ttl,
cmd_act_mesh_get_stats,
- cmd_act_mesh_get_mpp,
- cmd_act_mesh_set_mpp,
+ cmd_act_mesh_get_anycast,
+ cmd_act_mesh_set_anycast,
};
/** Card Event definition */
@@ -334,5 +336,6 @@ enum cmd_mesh_access_opts {
#define MACREG_INT_CODE_MAX_FAIL 0x0000001b
#define MACREG_INT_CODE_RSSI_HIGH 0x0000001c
#define MACREG_INT_CODE_SNR_HIGH 0x0000001d
+#define MACREG_INT_CODE_MESH_AUTO_STARTED 0x00000023
#endif /* _HOST_H_ */
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index f239e5d2435..09b898f6719 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -14,12 +14,12 @@
/* TxPD descriptor */
struct txpd {
/* Current Tx packet status */
- u32 tx_status;
+ __le32 tx_status;
/* Tx control */
- u32 tx_control;
- u32 tx_packet_location;
+ __le32 tx_control;
+ __le32 tx_packet_location;
/* Tx packet length */
- u16 tx_packet_length;
+ __le16 tx_packet_length;
/* First 2 byte of destination MAC address */
u8 tx_dest_addr_high[2];
/* Last 4 byte of destination MAC address */
@@ -37,7 +37,7 @@ struct txpd {
/* RxPD Descriptor */
struct rxpd {
/* Current Rx packet status */
- u16 status;
+ __le16 status;
/* SNR */
u8 snr;
@@ -46,7 +46,7 @@ struct rxpd {
u8 rx_control;
/* Pkt length */
- u16 pkt_len;
+ __le16 pkt_len;
/* Noise Floor */
u8 nf;
@@ -55,10 +55,10 @@ struct rxpd {
u8 rx_rate;
/* Pkt addr */
- u32 pkt_ptr;
+ __le32 pkt_ptr;
/* Next Rx RxPD addr */
- u32 next_rxpd_ptr;
+ __le32 next_rxpd_ptr;
/* Pkt Priority */
u8 priority;
@@ -89,30 +89,17 @@ struct cmd_ctrl_node {
* is determined from the keylength field.
*/
struct WLAN_802_11_KEY {
- u32 len;
- u32 flags; /* KEY_INFO_* from wlan_defs.h */
+ __le32 len;
+ __le32 flags; /* KEY_INFO_* from wlan_defs.h */
u8 key[MRVL_MAX_KEY_WPA_KEY_LENGTH];
- u16 type; /* KEY_TYPE_* from wlan_defs.h */
+ __le16 type; /* KEY_TYPE_* from wlan_defs.h */
};
struct IE_WPA {
u8 elementid;
u8 len;
u8 oui[4];
- u16 version;
-};
-
-struct WLAN_802_11_SSID {
- /* SSID length */
- u32 ssidlength;
-
- /* SSID information field */
- u8 ssid[IW_ESSID_MAX_SIZE];
-};
-
-struct WPA_SUPPLICANT {
- u8 wpa_ie[256];
- u8 wpa_ie_len;
+ __le16 version;
};
/* wlan_offset_value */
@@ -122,9 +109,9 @@ struct wlan_offset_value {
};
struct WLAN_802_11_FIXED_IEs {
- u8 timestamp[8];
- u16 beaconinterval;
- u16 capabilities;
+ __le64 timestamp;
+ __le16 beaconinterval;
+ u16 capabilities; /* Actually struct ieeetypes_capinfo */
};
struct WLAN_802_11_VARIABLE_IEs {
@@ -136,10 +123,10 @@ struct WLAN_802_11_VARIABLE_IEs {
/* Define general data structure */
/* cmd_DS_GEN */
struct cmd_ds_gen {
- u16 command;
- u16 size;
- u16 seqnum;
- u16 result;
+ __le16 command;
+ __le16 size;
+ __le16 seqnum;
+ __le16 result;
};
#define S_DS_GEN sizeof(struct cmd_ds_gen)
@@ -149,44 +136,44 @@ struct cmd_ds_gen {
*/
struct cmd_ds_get_hw_spec {
/* HW Interface version number */
- u16 hwifversion;
+ __le16 hwifversion;
/* HW version number */
- u16 version;
+ __le16 version;
/* Max number of TxPD FW can handle */
- u16 nr_txpd;
+ __le16 nr_txpd;
/* Max no of Multicast address */
- u16 nr_mcast_adr;
+ __le16 nr_mcast_adr;
/* MAC address */
u8 permanentaddr[6];
/* region Code */
- u16 regioncode;
+ __le16 regioncode;
/* Number of antenna used */
- u16 nr_antenna;
+ __le16 nr_antenna;
- /* FW release number, example 0x1234=1.2.3.4 */
- u32 fwreleasenumber;
+ /* FW release number, example 1,2,3,4 = 3.2.1p4 */
+ u8 fwreleasenumber[4];
/* Base Address of TxPD queue */
- u32 wcb_base;
+ __le32 wcb_base;
/* Read Pointer of RxPd queue */
- u32 rxpd_rdptr;
+ __le32 rxpd_rdptr;
/* Write Pointer of RxPd queue */
- u32 rxpd_wrptr;
+ __le32 rxpd_wrptr;
/*FW/HW capability */
- u32 fwcapinfo;
+ __le32 fwcapinfo;
} __attribute__ ((packed));
struct cmd_ds_802_11_reset {
- u16 action;
+ __le16 action;
};
struct cmd_ds_802_11_subscribe_event {
- u16 action;
- u16 events;
+ __le16 action;
+ __le16 events;
};
/*
@@ -205,35 +192,35 @@ struct cmd_ds_802_11_scan {
};
struct cmd_ds_802_11_scan_rsp {
- u16 bssdescriptsize;
+ __le16 bssdescriptsize;
u8 nr_sets;
u8 bssdesc_and_tlvbuffer[1];
};
struct cmd_ds_802_11_get_log {
- u32 mcasttxframe;
- u32 failed;
- u32 retry;
- u32 multiretry;
- u32 framedup;
- u32 rtssuccess;
- u32 rtsfailure;
- u32 ackfailure;
- u32 rxfrag;
- u32 mcastrxframe;
- u32 fcserror;
- u32 txframe;
- u32 wepundecryptable;
+ __le32 mcasttxframe;
+ __le32 failed;
+ __le32 retry;
+ __le32 multiretry;
+ __le32 framedup;
+ __le32 rtssuccess;
+ __le32 rtsfailure;
+ __le32 ackfailure;
+ __le32 rxfrag;
+ __le32 mcastrxframe;
+ __le32 fcserror;
+ __le32 txframe;
+ __le32 wepundecryptable;
};
struct cmd_ds_mac_control {
- u16 action;
- u16 reserved;
+ __le16 action;
+ __le16 reserved;
};
struct cmd_ds_mac_multicast_adr {
- u16 action;
- u16 nr_of_adrs;
+ __le16 action;
+ __le16 nr_of_adrs;
u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
};
@@ -245,14 +232,14 @@ struct cmd_ds_802_11_authenticate {
struct cmd_ds_802_11_deauthenticate {
u8 macaddr[6];
- u16 reasoncode;
+ __le16 reasoncode;
};
struct cmd_ds_802_11_associate {
u8 peerstaaddr[6];
struct ieeetypes_capinfo capinfo;
- u16 listeninterval;
- u16 bcnperiod;
+ __le16 listeninterval;
+ __le16 bcnperiod;
u8 dtimperiod;
#if 0
@@ -265,7 +252,7 @@ struct cmd_ds_802_11_associate {
struct cmd_ds_802_11_disassociate {
u8 destmacaddr[6];
- u16 reasoncode;
+ __le16 reasoncode;
};
struct cmd_ds_802_11_associate_rsp {
@@ -279,10 +266,10 @@ struct cmd_ds_802_11_ad_hoc_result {
struct cmd_ds_802_11_set_wep {
/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
- u16 action;
+ __le16 action;
/* key Index selected for Tx */
- u16 keyindex;
+ __le16 keyindex;
/* 40, 128bit or TXWEP */
u8 keytype[4];
@@ -290,96 +277,96 @@ struct cmd_ds_802_11_set_wep {
};
struct cmd_ds_802_3_get_stat {
- u32 xmitok;
- u32 rcvok;
- u32 xmiterror;
- u32 rcverror;
- u32 rcvnobuffer;
- u32 rcvcrcerror;
+ __le32 xmitok;
+ __le32 rcvok;
+ __le32 xmiterror;
+ __le32 rcverror;
+ __le32 rcvnobuffer;
+ __le32 rcvcrcerror;
};
struct cmd_ds_802_11_get_stat {
- u32 txfragmentcnt;
- u32 mcasttxframecnt;
- u32 failedcnt;
- u32 retrycnt;
- u32 Multipleretrycnt;
- u32 rtssuccesscnt;
- u32 rtsfailurecnt;
- u32 ackfailurecnt;
- u32 frameduplicatecnt;
- u32 rxfragmentcnt;
- u32 mcastrxframecnt;
- u32 fcserrorcnt;
- u32 bcasttxframecnt;
- u32 bcastrxframecnt;
- u32 txbeacon;
- u32 rxbeacon;
- u32 wepundecryptable;
+ __le32 txfragmentcnt;
+ __le32 mcasttxframecnt;
+ __le32 failedcnt;
+ __le32 retrycnt;
+ __le32 Multipleretrycnt;
+ __le32 rtssuccesscnt;
+ __le32 rtsfailurecnt;
+ __le32 ackfailurecnt;
+ __le32 frameduplicatecnt;
+ __le32 rxfragmentcnt;
+ __le32 mcastrxframecnt;
+ __le32 fcserrorcnt;
+ __le32 bcasttxframecnt;
+ __le32 bcastrxframecnt;
+ __le32 txbeacon;
+ __le32 rxbeacon;
+ __le32 wepundecryptable;
};
struct cmd_ds_802_11_snmp_mib {
- u16 querytype;
- u16 oid;
- u16 bufsize;
+ __le16 querytype;
+ __le16 oid;
+ __le16 bufsize;
u8 value[128];
};
struct cmd_ds_mac_reg_map {
- u16 buffersize;
+ __le16 buffersize;
u8 regmap[128];
- u16 reserved;
+ __le16 reserved;
};
struct cmd_ds_bbp_reg_map {
- u16 buffersize;
+ __le16 buffersize;
u8 regmap[128];
- u16 reserved;
+ __le16 reserved;
};
struct cmd_ds_rf_reg_map {
- u16 buffersize;
+ __le16 buffersize;
u8 regmap[64];
- u16 reserved;
+ __le16 reserved;
};
struct cmd_ds_mac_reg_access {
- u16 action;
- u16 offset;
- u32 value;
+ __le16 action;
+ __le16 offset;
+ __le32 value;
};
struct cmd_ds_bbp_reg_access {
- u16 action;
- u16 offset;
+ __le16 action;
+ __le16 offset;
u8 value;
u8 reserved[3];
};
struct cmd_ds_rf_reg_access {
- u16 action;
- u16 offset;
+ __le16 action;
+ __le16 offset;
u8 value;
u8 reserved[3];
};
struct cmd_ds_802_11_radio_control {
- u16 action;
- u16 control;
+ __le16 action;
+ __le16 control;
};
struct cmd_ds_802_11_sleep_params {
/* ACT_GET/ACT_SET */
- u16 action;
+ __le16 action;
/* Sleep clock error in ppm */
- u16 error;
+ __le16 error;
/* Wakeup offset in usec */
- u16 offset;
+ __le16 offset;
/* Clock stabilization time in usec */
- u16 stabletime;
+ __le16 stabletime;
/* control periodic calibration */
u8 calcontrol;
@@ -388,100 +375,100 @@ struct cmd_ds_802_11_sleep_params {
u8 externalsleepclk;
/* reserved field, should be set to zero */
- u16 reserved;
+ __le16 reserved;
};
struct cmd_ds_802_11_inactivity_timeout {
/* ACT_GET/ACT_SET */
- u16 action;
+ __le16 action;
/* Inactivity timeout in msec */
- u16 timeout;
+ __le16 timeout;
};
struct cmd_ds_802_11_rf_channel {
- u16 action;
- u16 currentchannel;
- u16 rftype;
- u16 reserved;
+ __le16 action;
+ __le16 currentchannel;
+ __le16 rftype;
+ __le16 reserved;
u8 channellist[32];
};
struct cmd_ds_802_11_rssi {
/* weighting factor */
- u16 N;
+ __le16 N;
- u16 reserved_0;
- u16 reserved_1;
- u16 reserved_2;
+ __le16 reserved_0;
+ __le16 reserved_1;
+ __le16 reserved_2;
};
struct cmd_ds_802_11_rssi_rsp {
- u16 SNR;
- u16 noisefloor;
- u16 avgSNR;
- u16 avgnoisefloor;
+ __le16 SNR;
+ __le16 noisefloor;
+ __le16 avgSNR;
+ __le16 avgnoisefloor;
};
struct cmd_ds_802_11_mac_address {
- u16 action;
+ __le16 action;
u8 macadd[ETH_ALEN];
};
struct cmd_ds_802_11_rf_tx_power {
- u16 action;
- u16 currentlevel;
+ __le16 action;
+ __le16 currentlevel;
};
struct cmd_ds_802_11_rf_antenna {
- u16 action;
+ __le16 action;
/* Number of antennas or 0xffff(diversity) */
- u16 antennamode;
+ __le16 antennamode;
};
struct cmd_ds_802_11_ps_mode {
- u16 action;
- u16 nullpktinterval;
- u16 multipledtim;
- u16 reserved;
- u16 locallisteninterval;
+ __le16 action;
+ __le16 nullpktinterval;
+ __le16 multipledtim;
+ __le16 reserved;
+ __le16 locallisteninterval;
};
struct PS_CMD_ConfirmSleep {
- u16 command;
- u16 size;
- u16 seqnum;
- u16 result;
+ __le16 command;
+ __le16 size;
+ __le16 seqnum;
+ __le16 result;
- u16 action;
- u16 reserved1;
- u16 multipledtim;
- u16 reserved;
- u16 locallisteninterval;
+ __le16 action;
+ __le16 reserved1;
+ __le16 multipledtim;
+ __le16 reserved;
+ __le16 locallisteninterval;
};
struct cmd_ds_802_11_data_rate {
- u16 action;
- u16 reserverd;
+ __le16 action;
+ __le16 reserverd;
u8 datarate[G_SUPPORTED_RATES];
};
struct cmd_ds_802_11_rate_adapt_rateset {
- u16 action;
- u16 enablehwauto;
- u16 bitmap;
+ __le16 action;
+ __le16 enablehwauto;
+ __le16 bitmap;
};
struct cmd_ds_802_11_ad_hoc_start {
u8 SSID[IW_ESSID_MAX_SIZE];
u8 bsstype;
- u16 beaconperiod;
+ __le16 beaconperiod;
u8 dtimperiod;
union IEEEtypes_ssparamset ssparamset;
union ieeetypes_phyparamset phyparamset;
- u16 probedelay;
+ __le16 probedelay;
struct ieeetypes_capinfo cap;
u8 datarate[G_SUPPORTED_RATES];
u8 tlv_memory_size_pad[100];
@@ -491,10 +478,10 @@ struct adhoc_bssdesc {
u8 BSSID[6];
u8 SSID[32];
u8 bsstype;
- u16 beaconperiod;
+ __le16 beaconperiod;
u8 dtimperiod;
- u8 timestamp[8];
- u8 localtime[8];
+ __le64 timestamp;
+ __le64 localtime;
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
struct ieeetypes_capinfo cap;
@@ -508,52 +495,52 @@ struct adhoc_bssdesc {
struct cmd_ds_802_11_ad_hoc_join {
struct adhoc_bssdesc bssdescriptor;
- u16 failtimeout;
- u16 probedelay;
+ __le16 failtimeout;
+ __le16 probedelay;
} __attribute__ ((packed));
struct cmd_ds_802_11_enable_rsn {
- u16 action;
- u16 enable;
-};
+ __le16 action;
+ __le16 enable;
+} __attribute__ ((packed));
struct MrvlIEtype_keyParamSet {
/* type ID */
- u16 type;
+ __le16 type;
/* length of Payload */
- u16 length;
+ __le16 length;
/* type of key: WEP=0, TKIP=1, AES=2 */
- u16 keytypeid;
+ __le16 keytypeid;
/* key control Info specific to a keytypeid */
- u16 keyinfo;
+ __le16 keyinfo;
/* length of key */
- u16 keylen;
+ __le16 keylen;
/* key material of size keylen */
u8 key[32];
};
struct cmd_ds_802_11_key_material {
- u16 action;
+ __le16 action;
struct MrvlIEtype_keyParamSet keyParamSet[2];
} __attribute__ ((packed));
struct cmd_ds_802_11_eeprom_access {
- u16 action;
+ __le16 action;
/* multiple 4 */
- u16 offset;
- u16 bytecount;
+ __le16 offset;
+ __le16 bytecount;
u8 value;
} __attribute__ ((packed));
struct cmd_ds_802_11_tpc_cfg {
- u16 action;
+ __le16 action;
u8 enable;
s8 P0;
s8 P1;
@@ -562,13 +549,13 @@ struct cmd_ds_802_11_tpc_cfg {
} __attribute__ ((packed));
struct cmd_ds_802_11_led_ctrl {
- u16 action;
- u16 numled;
+ __le16 action;
+ __le16 numled;
u8 data[256];
} __attribute__ ((packed));
struct cmd_ds_802_11_pwr_cfg {
- u16 action;
+ __le16 action;
u8 enable;
s8 PA_P0;
s8 PA_P1;
@@ -576,21 +563,21 @@ struct cmd_ds_802_11_pwr_cfg {
} __attribute__ ((packed));
struct cmd_ds_802_11_afc {
- u16 afc_auto;
+ __le16 afc_auto;
union {
struct {
- u16 threshold;
- u16 period;
+ __le16 threshold;
+ __le16 period;
};
struct {
- s16 timing_offset;
- s16 carrier_offset;
+ __le16 timing_offset; /* signed */
+ __le16 carrier_offset; /* signed */
};
};
} __attribute__ ((packed));
struct cmd_tx_rate_query {
- u16 txrate;
+ __le16 txrate;
} __attribute__ ((packed));
struct cmd_ds_get_tsf {
@@ -598,41 +585,46 @@ struct cmd_ds_get_tsf {
} __attribute__ ((packed));
struct cmd_ds_bt_access {
- u16 action;
- u32 id;
+ __le16 action;
+ __le32 id;
u8 addr1[ETH_ALEN];
u8 addr2[ETH_ALEN];
} __attribute__ ((packed));
struct cmd_ds_fwt_access {
- u16 action;
- u32 id;
+ __le16 action;
+ __le32 id;
+ u8 valid;
u8 da[ETH_ALEN];
u8 dir;
u8 ra[ETH_ALEN];
- u32 ssn;
- u32 dsn;
- u32 metric;
+ __le32 ssn;
+ __le32 dsn;
+ __le32 metric;
+ u8 rate;
u8 hopcount;
u8 ttl;
- u32 expiration;
+ __le32 expiration;
u8 sleepmode;
- u32 snr;
- u32 references;
+ __le32 snr;
+ __le32 references;
+ u8 prec[ETH_ALEN];
} __attribute__ ((packed));
-#define MESH_STATS_NUM 7
struct cmd_ds_mesh_access {
- u16 action;
- u32 data[MESH_STATS_NUM + 1]; /* last position reserved */
+ __le16 action;
+ __le32 data[32]; /* last position reserved */
} __attribute__ ((packed));
+/* Number of stats counters returned by the firmware */
+#define MESH_STATS_NUM 8
+
struct cmd_ds_command {
/* command header */
- u16 command;
- u16 size;
- u16 seqnum;
- u16 result;
+ __le16 command;
+ __le16 size;
+ __le16 seqnum;
+ __le16 result;
/* command Body */
union {
diff --git a/drivers/net/wireless/libertas/if_bootcmd.c b/drivers/net/wireless/libertas/if_bootcmd.c
index 567000c3e87..8bca306ffad 100644
--- a/drivers/net/wireless/libertas/if_bootcmd.c
+++ b/drivers/net/wireless/libertas/if_bootcmd.c
@@ -8,6 +8,8 @@
#include <linux/netdevice.h>
#include <linux/usb.h>
+#define DRV_NAME "usb8xxx"
+
#include "defs.h"
#include "dev.h"
#include "if_usb.h"
@@ -20,12 +22,12 @@
*/
int if_usb_issue_boot_command(wlan_private *priv, int ivalue)
{
- struct usb_card_rec *cardp = priv->wlan_dev.card;
+ struct usb_card_rec *cardp = priv->card;
struct bootcmdstr sbootcmd;
int i;
/* Prepare command */
- sbootcmd.u32magicnumber = BOOT_CMD_MAGIC_NUMBER;
+ sbootcmd.u32magicnumber = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
sbootcmd.u8cmd_tag = ivalue;
for (i=0; i<11; i++)
sbootcmd.au8dumy[i]=0x00;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index ae6f72a6cdf..998317571ec 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -2,12 +2,15 @@
* This file contains functions used in USB interface module.
*/
#include <linux/delay.h>
+#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
+#include <linux/list.h>
#include <linux/usb.h>
+#define DRV_NAME "usb8xxx"
+
#include "host.h"
-#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
@@ -16,15 +19,24 @@
#define MESSAGE_HEADER_LEN 4
static const char usbdriver_name[] = "usb8xxx";
+static u8 *default_fw_name = "usb8388.bin";
+
+char *libertas_fw_name = NULL;
+module_param_named(fw_name, libertas_fw_name, charp, 0644);
+
+/*
+ * We need to send a RESET command to all USB devices before
+ * we tear down the USB connection. Otherwise we would not
+ * be able to re-init device the device if the module gets
+ * loaded again. This is a list of all initialized USB devices,
+ * for the reset code see if_usb_reset_device()
+*/
+static LIST_HEAD(usb_devices);
static struct usb_device_id if_usb_table[] = {
/* Enter the device signature inside */
- {
- USB_DEVICE(USB8388_VID_1, USB8388_PID_1),
- },
- {
- USB_DEVICE(USB8388_VID_2, USB8388_PID_2),
- },
+ { USB_DEVICE(0x1286, 0x2001) },
+ { USB_DEVICE(0x05a3, 0x8388) },
{} /* Terminating entry */
};
@@ -32,6 +44,13 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
+static int if_usb_reset_device(wlan_private *priv);
+static int if_usb_register_dev(wlan_private * priv);
+static int if_usb_unregister_dev(wlan_private *);
+static int if_usb_prog_firmware(wlan_private *);
+static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
+static int if_usb_get_int_status(wlan_private * priv, u8 *);
+static int if_usb_read_event_cause(wlan_private *);
/**
* @brief call back function to handle the status of the URB
@@ -42,23 +61,27 @@ static void if_usb_write_bulk_callback(struct urb *urb)
{
wlan_private *priv = (wlan_private *) (urb->context);
wlan_adapter *adapter = priv->adapter;
- struct net_device *dev = priv->wlan_dev.netdev;
+ struct net_device *dev = priv->dev;
/* handle the transmission complete validations */
if (urb->status != 0) {
/* print the failure status number for debug */
- lbs_pr_info("URB in failure status\n");
+ lbs_pr_info("URB in failure status: %d\n", urb->status);
} else {
- lbs_dev_dbg(2, &urb->dev->dev, "URB status is successfull\n");
- lbs_dev_dbg(2, &urb->dev->dev, "Actual length transmitted %d\n",
+ /*
+ lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n");
+ lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n",
urb->actual_length);
- priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+ */
+ priv->dnld_sent = DNLD_RES_RECEIVED;
/* Wake main thread if commands are pending */
if (!adapter->cur_cmd)
wake_up_interruptible(&priv->mainthread.waitq);
- if ((adapter->connect_status == libertas_connected))
+ if ((adapter->connect_status == libertas_connected)) {
netif_wake_queue(dev);
+ netif_wake_queue(priv->mesh_dev);
+ }
}
return;
@@ -71,7 +94,7 @@ static void if_usb_write_bulk_callback(struct urb *urb)
*/
void if_usb_free(struct usb_card_rec *cardp)
{
- ENTER();
+ lbs_deb_enter(LBS_DEB_USB);
/* Unlink tx & rx urb */
usb_kill_urb(cardp->tx_urb);
@@ -86,8 +109,7 @@ void if_usb_free(struct usb_card_rec *cardp)
kfree(cardp->bulk_out_buffer);
cardp->bulk_out_buffer = NULL;
- LEAVE();
- return;
+ lbs_deb_leave(LBS_DEB_USB);
}
/**
@@ -102,27 +124,27 @@ static int if_usb_probe(struct usb_interface *intf,
struct usb_device *udev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
- wlan_private *pwlanpriv;
- struct usb_card_rec *usb_cardp;
+ wlan_private *priv;
+ struct usb_card_rec *cardp;
int i;
udev = interface_to_usbdev(intf);
- usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
- if (!usb_cardp) {
+ cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+ if (!cardp) {
lbs_pr_err("Out of memory allocating private data.\n");
goto error;
}
- usb_cardp->udev = udev;
+ cardp->udev = udev;
iface_desc = intf->cur_altsetting;
- lbs_dev_dbg(1, &udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
+ lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
" bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
- udev->descriptor.bcdUSB,
- udev->descriptor.bDeviceClass,
- udev->descriptor.bDeviceSubClass,
- udev->descriptor.bDeviceProtocol);
+ le16_to_cpu(udev->descriptor.bcdUSB),
+ udev->descriptor.bDeviceClass,
+ udev->descriptor.bDeviceSubClass,
+ udev->descriptor.bDeviceProtocol);
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
@@ -130,23 +152,21 @@ static int if_usb_probe(struct usb_interface *intf,
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk in endpoint */
- lbs_dev_dbg(1, &udev->dev, "Bulk in size is %d\n",
- endpoint->wMaxPacketSize);
- if (!
- (usb_cardp->rx_urb =
- usb_alloc_urb(0, GFP_KERNEL))) {
- lbs_dev_dbg(1, &udev->dev,
+ lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n",
+ le16_to_cpu(endpoint->wMaxPacketSize));
+ if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
+ lbs_deb_usbd(&udev->dev,
"Rx URB allocation failed\n");
goto dealloc;
}
- usb_cardp->rx_urb_recall = 0;
+ cardp->rx_urb_recall = 0;
- usb_cardp->bulk_in_size =
- endpoint->wMaxPacketSize;
- usb_cardp->bulk_in_endpointAddr =
+ cardp->bulk_in_size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ cardp->bulk_in_endpointAddr =
(endpoint->
bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
- lbs_dev_dbg(1, &udev->dev, "in_endpoint = %d\n",
+ lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n",
endpoint->bEndpointAddress);
}
@@ -156,55 +176,63 @@ static int if_usb_probe(struct usb_interface *intf,
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* We found bulk out endpoint */
- if (!
- (usb_cardp->tx_urb =
- usb_alloc_urb(0, GFP_KERNEL))) {
- lbs_dev_dbg(1,&udev->dev,
+ if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
+ lbs_deb_usbd(&udev->dev,
"Tx URB allocation failed\n");
goto dealloc;
}
- usb_cardp->bulk_out_size =
- endpoint->wMaxPacketSize;
- lbs_dev_dbg(1, &udev->dev,
- "Bulk out size is %d\n",
- endpoint->wMaxPacketSize);
- usb_cardp->bulk_out_endpointAddr =
+ cardp->bulk_out_size =
+ le16_to_cpu(endpoint->wMaxPacketSize);
+ lbs_deb_usbd(&udev->dev,
+ "Bulk out size is %d\n",
+ le16_to_cpu(endpoint->wMaxPacketSize));
+ cardp->bulk_out_endpointAddr =
endpoint->bEndpointAddress;
- lbs_dev_dbg(1, &udev->dev, "out_endpoint = %d\n",
+ lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n",
endpoint->bEndpointAddress);
- usb_cardp->bulk_out_buffer =
+ cardp->bulk_out_buffer =
kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
GFP_KERNEL);
- if (!usb_cardp->bulk_out_buffer) {
- lbs_dev_dbg(1, &udev->dev,
+ if (!cardp->bulk_out_buffer) {
+ lbs_deb_usbd(&udev->dev,
"Could not allocate buffer\n");
goto dealloc;
}
}
}
-
- /* At this point wlan_add_card() will be called. Don't worry
- * about keeping pwlanpriv around since it will be set on our
- * usb device data in -> add() -> libertas_sbi_register_dev().
- */
- if (!(pwlanpriv = wlan_add_card(usb_cardp)))
+ if (!(priv = libertas_add_card(cardp, &udev->dev)))
goto dealloc;
+ if (libertas_add_mesh(priv, &udev->dev))
+ goto err_add_mesh;
+
+ priv->hw_register_dev = if_usb_register_dev;
+ priv->hw_unregister_dev = if_usb_unregister_dev;
+ priv->hw_prog_firmware = if_usb_prog_firmware;
+ priv->hw_host_to_card = if_usb_host_to_card;
+ priv->hw_get_int_status = if_usb_get_int_status;
+ priv->hw_read_event_cause = if_usb_read_event_cause;
+
+ if (libertas_activate_card(priv, libertas_fw_name))
+ goto err_activate_card;
+
+ list_add_tail(&cardp->list, &usb_devices);
+
usb_get_dev(udev);
- usb_set_intfdata(intf, usb_cardp);
+ usb_set_intfdata(intf, cardp);
- /*
- * return card structure, which can be got back in the
- * diconnect function as the ptr
- * argument.
- */
return 0;
+err_activate_card:
+ libertas_remove_mesh(priv);
+err_add_mesh:
+ free_netdev(priv->dev);
+ kfree(priv->adapter);
dealloc:
- if_usb_free(usb_cardp);
+ if_usb_free(cardp);
error:
return -ENOMEM;
@@ -212,8 +240,7 @@ error:
/**
* @brief free resource and cleanup
- * @param udev pointer to usb_device
- * @param ptr pointer to usb_cardp
+ * @param intf USB interface structure
* @return N/A
*/
static void if_usb_disconnect(struct usb_interface *intf)
@@ -229,9 +256,12 @@ static void if_usb_disconnect(struct usb_interface *intf)
*/
adapter->surpriseremoved = 1;
+ list_del(&cardp->list);
+
/* card is removed and we can call wlan_remove_card */
- lbs_dev_dbg(1, &cardp->udev->dev, "call remove card\n");
- wlan_remove_card(cardp);
+ lbs_deb_usbd(&cardp->udev->dev, "call remove card\n");
+ libertas_remove_mesh(priv);
+ libertas_remove_card(priv);
/* Unlink and free urb */
if_usb_free(cardp);
@@ -249,7 +279,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
*/
static int if_prog_firmware(wlan_private * priv)
{
- struct usb_card_rec *cardp = priv->wlan_dev.card;
+ struct usb_card_rec *cardp = priv->card;
struct FWData *fwdata;
struct fwheader *fwheader;
u8 *firmware = priv->firmware->data;
@@ -266,8 +296,10 @@ static int if_prog_firmware(wlan_private * priv)
cardp->fwseqnum = cardp->lastseqnum - 1;
}
- lbs_dev_dbg(2, &cardp->udev->dev, "totalbytes = %d\n",
+ /*
+ lbs_deb_usbd(&cardp->udev->dev, "totalbytes = %d\n",
cardp->totalbytes);
+ */
memcpy(fwheader, &firmware[cardp->totalbytes],
sizeof(struct fwheader));
@@ -275,40 +307,48 @@ static int if_prog_firmware(wlan_private * priv)
cardp->fwlastblksent = cardp->totalbytes;
cardp->totalbytes += sizeof(struct fwheader);
- lbs_dev_dbg(2, &cardp->udev->dev,"Copy Data\n");
+ /* lbs_deb_usbd(&cardp->udev->dev,"Copy Data\n"); */
memcpy(fwdata->data, &firmware[cardp->totalbytes],
- fwdata->fwheader.datalength);
+ le32_to_cpu(fwdata->fwheader.datalength));
- lbs_dev_dbg(2, &cardp->udev->dev,
- "Data length = %d\n", fwdata->fwheader.datalength);
+ /*
+ lbs_deb_usbd(&cardp->udev->dev,
+ "Data length = %d\n", le32_to_cpu(fwdata->fwheader.datalength));
+ */
cardp->fwseqnum = cardp->fwseqnum + 1;
- fwdata->seqnum = cardp->fwseqnum;
- cardp->lastseqnum = fwdata->seqnum;
- cardp->totalbytes += fwdata->fwheader.datalength;
+ fwdata->seqnum = cpu_to_le32(cardp->fwseqnum);
+ cardp->lastseqnum = cardp->fwseqnum;
+ cardp->totalbytes += le32_to_cpu(fwdata->fwheader.datalength);
- if (fwheader->dnldcmd == FW_HAS_DATA_TO_RECV) {
- lbs_dev_dbg(2, &cardp->udev->dev, "There is data to follow\n");
- lbs_dev_dbg(2, &cardp->udev->dev,
+ if (fwheader->dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
+ /*
+ lbs_deb_usbd(&cardp->udev->dev, "There are data to follow\n");
+ lbs_deb_usbd(&cardp->udev->dev,
"seqnum = %d totalbytes = %d\n", cardp->fwseqnum,
cardp->totalbytes);
+ */
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
- } else if (fwdata->fwheader.dnldcmd == FW_HAS_LAST_BLOCK) {
- lbs_dev_dbg(2, &cardp->udev->dev,
+ } else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
+ /*
+ lbs_deb_usbd(&cardp->udev->dev,
"Host has finished FW downloading\n");
- lbs_dev_dbg(2, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"Donwloading FW JUMP BLOCK\n");
+ */
memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
cardp->fwfinalblk = 1;
}
- lbs_dev_dbg(2, &cardp->udev->dev,
+ /*
+ lbs_deb_usbd(&cardp->udev->dev,
"The firmware download is done size is %d\n",
cardp->totalbytes);
+ */
kfree(fwdata);
@@ -318,14 +358,19 @@ static int if_prog_firmware(wlan_private * priv)
static int libertas_do_reset(wlan_private *priv)
{
int ret;
- struct usb_card_rec *cardp = priv->wlan_dev.card;
+ struct usb_card_rec *cardp = priv->card;
+
+ lbs_deb_enter(LBS_DEB_USB);
ret = usb_reset_device(cardp->udev);
if (!ret) {
msleep(10);
- reset_device(priv);
+ if_usb_reset_device(priv);
msleep(10);
}
+
+ lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
+
return ret;
}
@@ -339,12 +384,12 @@ static int libertas_do_reset(wlan_private *priv)
int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
{
/* pointer to card structure */
- struct usb_card_rec *cardp = priv->wlan_dev.card;
+ struct usb_card_rec *cardp = priv->card;
int ret = -1;
/* check if device is removed */
if (priv->adapter->surpriseremoved) {
- lbs_dev_dbg(1, &cardp->udev->dev, "Device removed\n");
+ lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");
goto tx_ret;
}
@@ -357,10 +402,10 @@ int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
/* transfer failed */
- lbs_dev_dbg(1, &cardp->udev->dev, "usb_submit_urb failed\n");
+ lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed\n");
ret = -1;
} else {
- lbs_dev_dbg(2, &cardp->udev->dev, "usb_submit_urb success\n");
+ /* lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb success\n"); */
ret = 0;
}
@@ -372,7 +417,7 @@ static int __if_usb_submit_rx_urb(wlan_private * priv,
void (*callbackfn)
(struct urb *urb))
{
- struct usb_card_rec *cardp = priv->wlan_dev.card;
+ struct usb_card_rec *cardp = priv->card;
struct sk_buff *skb;
struct read_cb_info *rinfo = &cardp->rinfo;
int ret = -1;
@@ -394,13 +439,13 @@ static int __if_usb_submit_rx_urb(wlan_private * priv,
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
- lbs_dev_dbg(2, &cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
+ /* lbs_deb_usbd(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); */
if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
/* handle failure conditions */
- lbs_dev_dbg(1, &cardp->udev->dev, "Submit Rx URB failed\n");
+ lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed\n");
ret = -1;
} else {
- lbs_dev_dbg(2, &cardp->udev->dev, "Submit Rx URB success\n");
+ /* lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB success\n"); */
ret = 0;
}
@@ -423,12 +468,12 @@ static void if_usb_receive_fwload(struct urb *urb)
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
wlan_private *priv = rinfo->priv;
struct sk_buff *skb = rinfo->skb;
- struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+ struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
struct fwsyncheader *syncfwheader;
struct bootcmdrespStr bootcmdresp;
if (urb->status) {
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"URB status is failed during fw load\n");
kfree_skb(skb);
return;
@@ -437,18 +482,18 @@ static void if_usb_receive_fwload(struct urb *urb)
if (cardp->bootcmdresp == 0) {
memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
sizeof(bootcmdresp));
- if (cardp->udev->descriptor.bcdDevice < 0x3106) {
+ if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
kfree_skb(skb);
if_usb_submit_rx_urb_fwload(priv);
cardp->bootcmdresp = 1;
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"Received valid boot command response\n");
return;
}
- if (bootcmdresp.u32magicnumber != BOOT_CMD_MAGIC_NUMBER) {
+ if (bootcmdresp.u32magicnumber != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
lbs_pr_info(
"boot cmd response wrong magic number (0x%x)\n",
- bootcmdresp.u32magicnumber);
+ le32_to_cpu(bootcmdresp.u32magicnumber));
} else if (bootcmdresp.u8cmd_tag != BOOT_CMD_FW_BY_USB) {
lbs_pr_info(
"boot cmd response cmd_tag error (%d)\n",
@@ -459,7 +504,7 @@ static void if_usb_receive_fwload(struct urb *urb)
bootcmdresp.u8result);
} else {
cardp->bootcmdresp = 1;
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"Received valid boot command response\n");
}
kfree_skb(skb);
@@ -469,7 +514,7 @@ static void if_usb_receive_fwload(struct urb *urb)
syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
if (!syncfwheader) {
- lbs_dev_dbg(1, &cardp->udev->dev, "Failure to allocate syncfwheader\n");
+ lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
kfree_skb(skb);
return;
}
@@ -478,14 +523,16 @@ static void if_usb_receive_fwload(struct urb *urb)
sizeof(struct fwsyncheader));
if (!syncfwheader->cmd) {
- lbs_dev_dbg(2, &cardp->udev->dev,
+ /*
+ lbs_deb_usbd(&cardp->udev->dev,
"FW received Blk with correct CRC\n");
- lbs_dev_dbg(2, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"FW received Blk seqnum = %d\n",
syncfwheader->seqnum);
+ */
cardp->CRC_OK = 1;
} else {
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"FW received Blk with CRC error\n");
cardp->CRC_OK = 0;
}
@@ -515,7 +562,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
{
if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE +
MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) {
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"Packet length is Invalid\n");
kfree_skb(skb);
return;
@@ -525,7 +572,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
skb_put(skb, recvlength);
skb_pull(skb, MESSAGE_HEADER_LEN);
libertas_process_rxed_packet(priv, skb);
- priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN);
+ priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
}
static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
@@ -535,7 +582,7 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
{
u8 *cmdbuf;
if (recvlength > MRVDRV_SIZE_OF_CMD_BUFFER) {
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"The receive buffer is too large\n");
kfree_skb(skb);
return;
@@ -548,21 +595,21 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
/* take care of cur_cmd = NULL case by reading the
* data to clear the interrupt */
if (!priv->adapter->cur_cmd) {
- cmdbuf = priv->wlan_dev.upld_buf;
+ cmdbuf = priv->upld_buf;
priv->adapter->hisregcpy &= ~his_cmdupldrdy;
} else
cmdbuf = priv->adapter->cur_cmd->bufvirtualaddr;
cardp->usb_int_cause |= his_cmdupldrdy;
- priv->wlan_dev.upld_len = (recvlength - MESSAGE_HEADER_LEN);
+ priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
memcpy(cmdbuf, recvbuff + MESSAGE_HEADER_LEN,
- priv->wlan_dev.upld_len);
+ priv->upld_len);
kfree_skb(skb);
- libertas_interrupt(priv->wlan_dev.netdev);
+ libertas_interrupt(priv->dev);
spin_unlock(&priv->adapter->driver_lock);
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"Wake up main thread to handle cmd response\n");
return;
@@ -580,17 +627,17 @@ static void if_usb_receive(struct urb *urb)
struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
wlan_private *priv = rinfo->priv;
struct sk_buff *skb = rinfo->skb;
- struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+ struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
int recvlength = urb->actual_length;
u8 *recvbuff = NULL;
u32 recvtype;
- ENTER();
+ lbs_deb_enter(LBS_DEB_USB);
if (recvlength) {
if (urb->status) {
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"URB status is failed\n");
kfree_skb(skb);
goto setup_for_next;
@@ -598,12 +645,12 @@ static void if_usb_receive(struct urb *urb)
recvbuff = skb->data + IPFIELD_ALIGN_OFFSET;
memcpy(&recvtype, recvbuff, sizeof(u32));
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"Recv length = 0x%x\n", recvlength);
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"Receive type = 0x%X\n", recvtype);
recvtype = le32_to_cpu(recvtype);
- lbs_dev_dbg(1, &cardp->udev->dev,
+ lbs_deb_usbd(&cardp->udev->dev,
"Receive type after = 0x%X\n", recvtype);
} else if (urb->status)
goto rx_exit;
@@ -621,18 +668,18 @@ static void if_usb_receive(struct urb *urb)
case CMD_TYPE_INDICATION:
/* Event cause handling */
spin_lock(&priv->adapter->driver_lock);
- cardp->usb_event_cause = *(u32 *) (recvbuff + MESSAGE_HEADER_LEN);
- lbs_dev_dbg(1, &cardp->udev->dev,"**EVENT** 0x%X\n",
+ cardp->usb_event_cause = le32_to_cpu(*(__le32 *) (recvbuff + MESSAGE_HEADER_LEN));
+ lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n",
cardp->usb_event_cause);
if (cardp->usb_event_cause & 0xffff0000) {
libertas_send_tx_feedback(priv);
spin_unlock(&priv->adapter->driver_lock);
break;
}
- cardp->usb_event_cause = le32_to_cpu(cardp->usb_event_cause) << 3;
+ cardp->usb_event_cause <<= 3;
cardp->usb_int_cause |= his_cardevent;
kfree_skb(skb);
- libertas_interrupt(priv->wlan_dev.netdev);
+ libertas_interrupt(priv->dev);
spin_unlock(&priv->adapter->driver_lock);
goto rx_exit;
default:
@@ -643,8 +690,7 @@ static void if_usb_receive(struct urb *urb)
setup_for_next:
if_usb_submit_rx_urb(priv);
rx_exit:
- LEAVE();
- return;
+ lbs_deb_leave(LBS_DEB_USB);
}
/**
@@ -655,24 +701,24 @@ rx_exit:
* @param len number of bytes
* @return 0 or -1
*/
-int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
+static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
{
int ret = -1;
u32 tmp;
- struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+ struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
- lbs_dev_dbg(1, &cardp->udev->dev,"*** type = %u\n", type);
- lbs_dev_dbg(1, &cardp->udev->dev,"size after = %d\n", nb);
+ lbs_deb_usbd(&cardp->udev->dev,"*** type = %u\n", type);
+ lbs_deb_usbd(&cardp->udev->dev,"size after = %d\n", nb);
if (type == MVMS_CMD) {
tmp = cpu_to_le32(CMD_TYPE_REQUEST);
- priv->wlan_dev.dnld_sent = DNLD_CMD_SENT;
+ priv->dnld_sent = DNLD_CMD_SENT;
memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
MESSAGE_HEADER_LEN);
} else {
tmp = cpu_to_le32(CMD_TYPE_DATA);
- priv->wlan_dev.dnld_sent = DNLD_DATA_SENT;
+ priv->dnld_sent = DNLD_DATA_SENT;
memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
MESSAGE_HEADER_LEN);
}
@@ -686,39 +732,41 @@ int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb
}
/* called with adapter->driver_lock held */
-int libertas_sbi_get_int_status(wlan_private * priv, u8 * ireg)
+static int if_usb_get_int_status(wlan_private * priv, u8 * ireg)
{
- struct usb_card_rec *cardp = priv->wlan_dev.card;
+ struct usb_card_rec *cardp = priv->card;
*ireg = cardp->usb_int_cause;
cardp->usb_int_cause = 0;
- lbs_dev_dbg(1, &cardp->udev->dev,"Int cause is 0x%X\n", *ireg);
+ lbs_deb_usbd(&cardp->udev->dev,"Int cause is 0x%X\n", *ireg);
return 0;
}
-int libertas_sbi_read_event_cause(wlan_private * priv)
+static int if_usb_read_event_cause(wlan_private * priv)
{
- struct usb_card_rec *cardp = priv->wlan_dev.card;
+ struct usb_card_rec *cardp = priv->card;
priv->adapter->eventcause = cardp->usb_event_cause;
/* Re-submit rx urb here to avoid event lost issue */
if_usb_submit_rx_urb(priv);
return 0;
}
-int reset_device(wlan_private *priv)
+static int if_usb_reset_device(wlan_private *priv)
{
int ret;
+ lbs_deb_enter(LBS_DEB_USB);
ret = libertas_prepare_and_send_command(priv, cmd_802_11_reset,
cmd_act_halt, 0, 0, NULL);
msleep_interruptible(10);
+ lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
return ret;
}
-int libertas_sbi_unregister_dev(wlan_private * priv)
+static int if_usb_unregister_dev(wlan_private * priv)
{
int ret = 0;
@@ -727,7 +775,7 @@ int libertas_sbi_unregister_dev(wlan_private * priv)
* again.
*/
if (priv)
- reset_device(priv);
+ if_usb_reset_device(priv);
return ret;
}
@@ -738,42 +786,41 @@ int libertas_sbi_unregister_dev(wlan_private * priv)
* @param priv pointer to wlan_private
* @return 0 or -1
*/
-int libertas_sbi_register_dev(wlan_private * priv)
+static int if_usb_register_dev(wlan_private * priv)
{
+ struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
- struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
- ENTER();
+ lbs_deb_enter(LBS_DEB_USB);
cardp->priv = priv;
- cardp->eth_dev = priv->wlan_dev.netdev;
+ cardp->eth_dev = priv->dev;
priv->hotplug_device = &(cardp->udev->dev);
- SET_NETDEV_DEV(cardp->eth_dev, &(cardp->udev->dev));
-
- lbs_dev_dbg(1, &cardp->udev->dev, "udev pointer is at %p\n",
+ lbs_deb_usbd(&cardp->udev->dev, "udev pointer is at %p\n",
cardp->udev);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_USB);
return 0;
}
-int libertas_sbi_prog_firmware(wlan_private * priv)
+static int if_usb_prog_firmware(wlan_private * priv)
{
- struct usb_card_rec *cardp = priv->wlan_dev.card;
+ struct usb_card_rec *cardp = priv->card;
int i = 0;
static int reset_count = 10;
+ int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_USB);
cardp->rinfo.priv = priv;
restart:
if (if_usb_submit_rx_urb_fwload(priv) < 0) {
- lbs_dev_dbg(1, &cardp->udev->dev, "URB submission is failed\n");
- LEAVE();
- return -1;
+ lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
+ ret = -1;
+ goto done;
}
cardp->bootcmdresp = 0;
@@ -811,7 +858,7 @@ restart:
if_prog_firmware(priv);
do {
- lbs_dev_dbg(1, &cardp->udev->dev,"Wlan sched timeout\n");
+ lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n");
i++;
msleep_interruptible(100);
if (priv->adapter->surpriseremoved || i >= 20)
@@ -826,8 +873,8 @@ restart:
}
lbs_pr_info("FW download failure, time = %d ms\n", i * 100);
- LEAVE();
- return -1;
+ ret = -1;
+ goto done;
}
if_usb_submit_rx_urb(priv);
@@ -837,32 +884,10 @@ restart:
priv->adapter->fw_ready = 1;
- LEAVE();
- return 0;
-}
-
-/**
- * @brief Given a usb_card_rec return its wlan_private
- * @param card pointer to a usb_card_rec
- * @return pointer to wlan_private
- */
-wlan_private *libertas_sbi_get_priv(void *card)
-{
- struct usb_card_rec *cardp = card;
- return cardp->priv;
-}
-
-#ifdef ENABLE_PM
-int libertas_sbi_suspend(wlan_private * priv)
-{
- return 0;
-}
-
-int libertas_sbi_resume(wlan_private * priv)
-{
- return 0;
+done:
+ lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
+ return ret;
}
-#endif
#ifdef CONFIG_PM
static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
@@ -870,12 +895,13 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
struct usb_card_rec *cardp = usb_get_intfdata(intf);
wlan_private *priv = cardp->priv;
- ENTER();
+ lbs_deb_enter(LBS_DEB_USB);
if (priv->adapter->psstate != PS_STATE_FULL_POWER)
return -1;
netif_device_detach(cardp->eth_dev);
+ netif_device_detach(priv->mesh_dev);
/* Unlink tx & rx urb */
usb_kill_urb(cardp->tx_urb);
@@ -883,23 +909,25 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
cardp->rx_urb_recall = 1;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_USB);
return 0;
}
static int if_usb_resume(struct usb_interface *intf)
{
struct usb_card_rec *cardp = usb_get_intfdata(intf);
+ wlan_private *priv = cardp->priv;
- ENTER();
+ lbs_deb_enter(LBS_DEB_USB);
cardp->rx_urb_recall = 0;
if_usb_submit_rx_urb(cardp->priv);
netif_device_attach(cardp->eth_dev);
+ netif_device_attach(priv->mesh_dev);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_USB);
return 0;
}
#else
@@ -920,32 +948,40 @@ static struct usb_driver if_usb_driver = {
.resume = if_usb_resume,
};
-/**
- * @brief This function registers driver.
- * @param add pointer to add_card callback function
- * @param remove pointer to remove card callback function
- * @param arg pointer to call back function parameter
- * @return dummy success variable
- */
-int libertas_sbi_register(void)
+static int if_usb_init_module(void)
{
- /*
- * API registers the Marvell USB driver
- * to the USB system
- */
- usb_register(&if_usb_driver);
+ int ret = 0;
- /* Return success to wlan layer */
- return 0;
+ lbs_deb_enter(LBS_DEB_MAIN);
+
+ if (libertas_fw_name == NULL) {
+ libertas_fw_name = default_fw_name;
+ }
+
+ ret = usb_register(&if_usb_driver);
+
+ lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+ return ret;
}
-/**
- * @brief This function removes usb driver.
- * @return N/A
- */
-void libertas_sbi_unregister(void)
+static void if_usb_exit_module(void)
{
+ struct usb_card_rec *cardp, *cardp_temp;
+
+ lbs_deb_enter(LBS_DEB_MAIN);
+
+ list_for_each_entry_safe(cardp, cardp_temp, &usb_devices, list)
+ if_usb_reset_device((wlan_private *) cardp->priv);
+
/* API unregisters the driver from USB subsystem */
usb_deregister(&if_usb_driver);
- return;
+
+ lbs_deb_leave(LBS_DEB_MAIN);
}
+
+module_init(if_usb_init_module);
+module_exit(if_usb_exit_module);
+
+MODULE_DESCRIPTION("8388 USB WLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index 170dfe6809f..156bb485e1a 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -1,3 +1,8 @@
+#ifndef _LIBERTAS_IF_USB_H
+#define _LIBERTAS_IF_USB_H
+
+#include <linux/list.h>
+
/**
* This file contains definition for USB interface.
*/
@@ -7,11 +12,6 @@
#define IPFIELD_ALIGN_OFFSET 2
-#define USB8388_VID_1 0x1286
-#define USB8388_PID_1 0x2001
-#define USB8388_VID_2 0x05a3
-#define USB8388_PID_2 0x8388
-
#define BOOT_CMD_FW_BY_USB 0x01
#define BOOT_CMD_FW_IN_EEPROM 0x02
#define BOOT_CMD_UPDATE_BOOT2 0x03
@@ -20,7 +20,7 @@
struct bootcmdstr
{
- u32 u32magicnumber;
+ __le32 u32magicnumber;
u8 u8cmd_tag;
u8 au8dumy[11];
};
@@ -30,7 +30,7 @@ struct bootcmdstr
struct bootcmdrespStr
{
- u32 u32magicnumber;
+ __le32 u32magicnumber;
u8 u8cmd_tag;
u8 u8result;
u8 au8dumy[2];
@@ -44,6 +44,7 @@ struct read_cb_info {
/** USB card description structure*/
struct usb_card_rec {
+ struct list_head list;
struct net_device *eth_dev;
struct usb_device *udev;
struct urb *rx_urb, *tx_urb;
@@ -75,33 +76,34 @@ struct usb_card_rec {
/** fwheader */
struct fwheader {
- u32 dnldcmd;
- u32 baseaddr;
- u32 datalength;
- u32 CRC;
+ __le32 dnldcmd;
+ __le32 baseaddr;
+ __le32 datalength;
+ __le32 CRC;
};
#define FW_MAX_DATA_BLK_SIZE 600
/** FWData */
struct FWData {
struct fwheader fwheader;
- u32 seqnum;
+ __le32 seqnum;
u8 data[FW_MAX_DATA_BLK_SIZE];
};
/** fwsyncheader */
struct fwsyncheader {
- u32 cmd;
- u32 seqnum;
+ __le32 cmd;
+ __le32 seqnum;
};
#define FW_HAS_DATA_TO_RECV 0x00000001
#define FW_HAS_LAST_BLOCK 0x00000004
#define FW_DATA_XMIT_SIZE \
- sizeof(struct fwheader) + fwdata->fwheader.datalength + sizeof(u32)
+ sizeof(struct fwheader) + le32_to_cpu(fwdata->fwheader.datalength) + sizeof(u32)
int usb_tx_block(wlan_private *priv, u8 *payload, u16 nb);
void if_usb_free(struct usb_card_rec *cardp);
int if_usb_issue_boot_command(wlan_private *priv, int ivalue);
+#endif
diff --git a/drivers/net/wireless/libertas/ioctl.c b/drivers/net/wireless/libertas/ioctl.c
deleted file mode 100644
index a8f76c35899..00000000000
--- a/drivers/net/wireless/libertas/ioctl.c
+++ /dev/null
@@ -1,991 +0,0 @@
-/**
- * This file contains ioctl functions
- */
-
-#include <linux/ctype.h>
-#include <linux/delay.h>
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-
-#include <net/iw_handler.h>
-#include <net/ieee80211.h>
-
-#include "host.h"
-#include "radiotap.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "join.h"
-#include "wext.h"
-
-#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN + \
- IW_ESSID_MAX_SIZE + \
- IW_EV_UINT_LEN + IW_EV_FREQ_LEN + \
- IW_EV_QUAL_LEN + IW_ESSID_MAX_SIZE + \
- IW_EV_PARAM_LEN + 40) /* 40 for WPAIE */
-
-#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ)
-
-static int wlan_set_region(wlan_private * priv, u16 region_code)
-{
- int i;
-
- for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
- // use the region code to search for the index
- if (region_code == libertas_region_code_to_index[i]) {
- priv->adapter->regiontableindex = (u16) i;
- priv->adapter->regioncode = region_code;
- break;
- }
- }
-
- // if it's unidentified region code
- if (i >= MRVDRV_MAX_REGION_CODE) {
- lbs_pr_debug(1, "region Code not identified\n");
- LEAVE();
- return -1;
- }
-
- if (libertas_set_regiontable(priv, priv->adapter->regioncode, 0)) {
- LEAVE();
- return -EINVAL;
- }
-
- return 0;
-}
-
-static inline int hex2int(char c)
-{
- if (c >= '0' && c <= '9')
- return (c - '0');
- if (c >= 'a' && c <= 'f')
- return (c - 'a' + 10);
- if (c >= 'A' && c <= 'F')
- return (c - 'A' + 10);
- return -1;
-}
-
-/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
- into binary format (6 bytes).
-
- This function expects that each byte is represented with 2 characters
- (e.g., 11:2:11:11:11:11 is invalid)
-
- */
-static char *eth_str2addr(char *ethstr, u8 * addr)
-{
- int i, val, val2;
- char *pos = ethstr;
-
- /* get rid of initial blanks */
- while (*pos == ' ' || *pos == '\t')
- ++pos;
-
- for (i = 0; i < 6; i++) {
- val = hex2int(*pos++);
- if (val < 0)
- return NULL;
- val2 = hex2int(*pos++);
- if (val2 < 0)
- return NULL;
- addr[i] = (val * 16 + val2) & 0xff;
-
- if (i < 5 && *pos++ != ':')
- return NULL;
- }
- return pos;
-}
-
-/* this writes xx:xx:xx:xx:xx:xx into ethstr
- (ethstr must have space for 18 chars) */
-static int eth_addr2str(u8 * addr, char *ethstr)
-{
- int i;
- char *pos = ethstr;
-
- for (i = 0; i < 6; i++) {
- sprintf(pos, "%02x", addr[i] & 0xff);
- pos += 2;
- if (i < 5)
- *pos++ = ':';
- }
- return 17;
-}
-
-/**
- * @brief Add an entry to the BT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char ethaddrs_str[18];
- char *pos;
- u8 ethaddr[ETH_ALEN];
-
- ENTER();
- if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
- sizeof(ethaddrs_str)))
- return -EFAULT;
-
- if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
- lbs_pr_info("BT_ADD: Invalid MAC address\n");
- return -EINVAL;
- }
-
- lbs_pr_debug(1, "BT: adding %s\n", ethaddrs_str);
- LEAVE();
- return (libertas_prepare_and_send_command(priv, cmd_bt_access,
- cmd_act_bt_access_add,
- cmd_option_waitforrsp, 0, ethaddr));
-}
-
-/**
- * @brief Delete an entry from the BT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char ethaddrs_str[18];
- u8 ethaddr[ETH_ALEN];
- char *pos;
-
- ENTER();
- if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
- sizeof(ethaddrs_str)))
- return -EFAULT;
-
- if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
- lbs_pr_info("Invalid MAC address\n");
- return -EINVAL;
- }
-
- lbs_pr_debug(1, "BT: deleting %s\n", ethaddrs_str);
-
- return (libertas_prepare_and_send_command(priv,
- cmd_bt_access,
- cmd_act_bt_access_del,
- cmd_option_waitforrsp, 0, ethaddr));
- LEAVE();
- return 0;
-}
-
-/**
- * @brief Reset all entries from the BT table
- * @param priv A pointer to wlan_private structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_bt_reset_ioctl(wlan_private * priv)
-{
- ENTER();
-
- lbs_pr_alert( "BT: resetting\n");
-
- return (libertas_prepare_and_send_command(priv,
- cmd_bt_access,
- cmd_act_bt_access_reset,
- cmd_option_waitforrsp, 0, NULL));
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief List an entry from the BT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
-{
- int pos;
- char *addr1;
- struct iwreq *wrq = (struct iwreq *)req;
- /* used to pass id and store the bt entry returned by the FW */
- union {
- int id;
- char addr1addr2[2 * ETH_ALEN];
- } param;
- static char outstr[64];
- char *pbuf = outstr;
- int ret;
-
- ENTER();
-
- if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
- lbs_pr_debug(1, "Copy from user failed\n");
- return -1;
- }
- param.id = simple_strtoul(outstr, NULL, 10);
- pos = sprintf(pbuf, "%d: ", param.id);
- pbuf += pos;
-
- ret = libertas_prepare_and_send_command(priv, cmd_bt_access,
- cmd_act_bt_access_list,
- cmd_option_waitforrsp, 0,
- (char *)&param);
-
- if (ret == 0) {
- addr1 = param.addr1addr2;
-
- pos = sprintf(pbuf, "ignoring traffic from ");
- pbuf += pos;
- pos = eth_addr2str(addr1, pbuf);
- pbuf += pos;
- } else {
- sprintf(pbuf, "(null)");
- pbuf += pos;
- }
-
- wrq->u.data.length = strlen(outstr);
- if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
- wrq->u.data.length)) {
- lbs_pr_debug(1, "BT_LIST: Copy to user failed!\n");
- return -EFAULT;
- }
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief Find the next parameter in an input string
- * @param ptr A pointer to the input parameter string
- * @return A pointer to the next parameter, or 0 if no parameters left.
- */
-static char * next_param(char * ptr)
-{
- if (!ptr) return NULL;
- while (*ptr == ' ' || *ptr == '\t') ++ptr;
- return (*ptr == '\0') ? NULL : ptr;
-}
-
-/**
- * @brief Add an entry to the FWT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_add_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[128];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr;
-
- ENTER();
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
- lbs_pr_alert( "FWT_ADD: Invalid MAC address 1\n");
- return -EINVAL;
- }
-
- if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
- lbs_pr_alert( "FWT_ADD: Invalid MAC address 2\n");
- return -EINVAL;
- }
-
- if ((ptr = next_param(ptr)))
- fwt_access.metric =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.metric = FWT_DEFAULT_METRIC;
-
- if ((ptr = next_param(ptr)))
- fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.dir = FWT_DEFAULT_DIR;
-
- if ((ptr = next_param(ptr)))
- fwt_access.ssn =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.ssn = FWT_DEFAULT_SSN;
-
- if ((ptr = next_param(ptr)))
- fwt_access.dsn =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.dsn = FWT_DEFAULT_DSN;
-
- if ((ptr = next_param(ptr)))
- fwt_access.hopcount = simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.hopcount = FWT_DEFAULT_HOPCOUNT;
-
- if ((ptr = next_param(ptr)))
- fwt_access.ttl = simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.ttl = FWT_DEFAULT_TTL;
-
- if ((ptr = next_param(ptr)))
- fwt_access.expiration =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.expiration = FWT_DEFAULT_EXPIRATION;
-
- if ((ptr = next_param(ptr)))
- fwt_access.sleepmode = (u8)simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.sleepmode = FWT_DEFAULT_SLEEPMODE;
-
- if ((ptr = next_param(ptr)))
- fwt_access.snr =
- cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
- else
- fwt_access.snr = FWT_DEFAULT_SNR;
-
-#ifdef DEBUG
- {
- char ethaddr1_str[18], ethaddr2_str[18];
- eth_addr2str(fwt_access.da, ethaddr1_str);
- eth_addr2str(fwt_access.ra, ethaddr2_str);
- lbs_pr_debug(1, "FWT_ADD: adding (da:%s,%i,ra:%s)\n", ethaddr1_str,
- fwt_access.dir, ethaddr2_str);
- lbs_pr_debug(1, "FWT_ADD: ssn:%u dsn:%u met:%u hop:%u ttl:%u exp:%u slp:%u snr:%u\n",
- fwt_access.ssn, fwt_access.dsn, fwt_access.metric,
- fwt_access.hopcount, fwt_access.ttl, fwt_access.expiration,
- fwt_access.sleepmode, fwt_access.snr);
- }
-#endif
-
- LEAVE();
- return (libertas_prepare_and_send_command(priv, cmd_fwt_access,
- cmd_act_fwt_access_add,
- cmd_option_waitforrsp, 0,
- (void *)&fwt_access));
-}
-
-/**
- * @brief Delete an entry from the FWT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_del_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[64];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr;
-
- ENTER();
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
- lbs_pr_alert( "FWT_DEL: Invalid MAC address 1\n");
- return -EINVAL;
- }
-
- if ((ptr = eth_str2addr(ptr, fwt_access.ra)) == NULL) {
- lbs_pr_alert( "FWT_DEL: Invalid MAC address 2\n");
- return -EINVAL;
- }
-
- if ((ptr = next_param(ptr)))
- fwt_access.dir = (u8)simple_strtoul(ptr, &ptr, 10);
- else
- fwt_access.dir = FWT_DEFAULT_DIR;
-
-#ifdef DEBUG
- {
- char ethaddr1_str[18], ethaddr2_str[18];
- lbs_pr_debug(1, "FWT_DEL: line is %s\n", in_str);
- eth_addr2str(fwt_access.da, ethaddr1_str);
- eth_addr2str(fwt_access.ra, ethaddr2_str);
- lbs_pr_debug(1, "FWT_DEL: removing (da:%s,ra:%s,dir:%d)\n", ethaddr1_str,
- ethaddr2_str, fwt_access.dir);
- }
-#endif
-
- LEAVE();
- return (libertas_prepare_and_send_command(priv,
- cmd_fwt_access,
- cmd_act_fwt_access_del,
- cmd_option_waitforrsp, 0,
- (void *)&fwt_access));
-}
-
-
-/**
- * @brief Print route parameters
- * @param fwt_access struct cmd_ds_fwt_access with route info
- * @param buf destination buffer for route info
- */
-static void print_route(struct cmd_ds_fwt_access fwt_access, char *buf)
-{
- buf += sprintf(buf, " ");
- buf += eth_addr2str(fwt_access.da, buf);
- buf += sprintf(buf, " ");
- buf += eth_addr2str(fwt_access.ra, buf);
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.metric));
- buf += sprintf(buf, " %u", fwt_access.dir);
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.ssn));
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.dsn));
- buf += sprintf(buf, " %u", fwt_access.hopcount);
- buf += sprintf(buf, " %u", fwt_access.ttl);
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.expiration));
- buf += sprintf(buf, " %u", fwt_access.sleepmode);
- buf += sprintf(buf, " %u", le32_to_cpu(fwt_access.snr));
-}
-
-/**
- * @brief Lookup an entry in the FWT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_lookup_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[64];
- char *ptr;
- static struct cmd_ds_fwt_access fwt_access;
- static char out_str[128];
- int ret;
-
- ENTER();
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- if ((ptr = eth_str2addr(in_str, fwt_access.da)) == NULL) {
- lbs_pr_alert( "FWT_LOOKUP: Invalid MAC address\n");
- return -EINVAL;
- }
-
-#ifdef DEBUG
- {
- char ethaddr1_str[18];
- lbs_pr_debug(1, "FWT_LOOKUP: line is %s\n", in_str);
- eth_addr2str(fwt_access.da, ethaddr1_str);
- lbs_pr_debug(1, "FWT_LOOKUP: looking for (da:%s)\n", ethaddr1_str);
- }
-#endif
-
- ret = libertas_prepare_and_send_command(priv,
- cmd_fwt_access,
- cmd_act_fwt_access_lookup,
- cmd_option_waitforrsp, 0,
- (void *)&fwt_access);
-
- if (ret == 0)
- print_route(fwt_access, out_str);
- else
- sprintf(out_str, "(null)");
-
- wrq->u.data.length = strlen(out_str);
- if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
- wrq->u.data.length)) {
- lbs_pr_debug(1, "FWT_LOOKUP: Copy to user failed!\n");
- return -EFAULT;
- }
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief Reset all entries from the FWT table
- * @param priv A pointer to wlan_private structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_reset_ioctl(wlan_private * priv)
-{
- lbs_pr_debug(1, "FWT: resetting\n");
-
- return (libertas_prepare_and_send_command(priv,
- cmd_fwt_access,
- cmd_act_fwt_access_reset,
- cmd_option_waitforrsp, 0, NULL));
-}
-
-/**
- * @brief List an entry from the FWT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_list_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[8];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr = in_str;
- static char out_str[128];
- char *pbuf = out_str;
- int ret;
-
- ENTER();
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
- {
- lbs_pr_debug(1, "FWT_LIST: line is %s\n", in_str);
- lbs_pr_debug(1, "FWT_LIST: listing id:%i\n", le32_to_cpu(fwt_access.id));
- }
-#endif
-
- ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
- cmd_act_fwt_access_list,
- cmd_option_waitforrsp, 0, (void *)&fwt_access);
-
- if (ret == 0)
- print_route(fwt_access, pbuf);
- else
- pbuf += sprintf(pbuf, " (null)");
-
- wrq->u.data.length = strlen(out_str);
- if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
- wrq->u.data.length)) {
- lbs_pr_debug(1, "FWT_LIST: Copy to user failed!\n");
- return -EFAULT;
- }
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief List an entry from the FRT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_list_route_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[64];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr = in_str;
- static char out_str[128];
- char *pbuf = out_str;
- int ret;
-
- ENTER();
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
- {
- lbs_pr_debug(1, "FWT_LIST_ROUTE: line is %s\n", in_str);
- lbs_pr_debug(1, "FWT_LIST_ROUTE: listing id:%i\n", le32_to_cpu(fwt_access.id));
- }
-#endif
-
- ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
- cmd_act_fwt_access_list_route,
- cmd_option_waitforrsp, 0, (void *)&fwt_access);
-
- if (ret == 0) {
- pbuf += sprintf(pbuf, " ");
- pbuf += eth_addr2str(fwt_access.da, pbuf);
- pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.metric));
- pbuf += sprintf(pbuf, " %u", fwt_access.dir);
- /* note that the firmware returns the nid in the id field */
- pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.id));
- pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.ssn));
- pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.dsn));
- pbuf += sprintf(pbuf, " hop %u", fwt_access.hopcount);
- pbuf += sprintf(pbuf, " ttl %u", fwt_access.ttl);
- pbuf += sprintf(pbuf, " %u", le32_to_cpu(fwt_access.expiration));
- } else
- pbuf += sprintf(pbuf, " (null)");
-
- wrq->u.data.length = strlen(out_str);
- if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
- wrq->u.data.length)) {
- lbs_pr_debug(1, "FWT_LIST_ROUTE: Copy to user failed!\n");
- return -EFAULT;
- }
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief List an entry from the FNT table
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_list_neighbor_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- char in_str[8];
- static struct cmd_ds_fwt_access fwt_access;
- char *ptr = in_str;
- static char out_str[128];
- char *pbuf = out_str;
- int ret;
-
- ENTER();
- if (copy_from_user(in_str, wrq->u.data.pointer, sizeof(in_str)))
- return -EFAULT;
-
- memset(&fwt_access, 0, sizeof(fwt_access));
- fwt_access.id = cpu_to_le32(simple_strtoul(ptr, &ptr, 10));
-
-#ifdef DEBUG
- {
- lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: line is %s\n", in_str);
- lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: listing id:%i\n", le32_to_cpu(fwt_access.id));
- }
-#endif
-
- ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
- cmd_act_fwt_access_list_neighbor,
- cmd_option_waitforrsp, 0,
- (void *)&fwt_access);
-
- if (ret == 0) {
- pbuf += sprintf(pbuf, " ra ");
- pbuf += eth_addr2str(fwt_access.ra, pbuf);
- pbuf += sprintf(pbuf, " slp %u", fwt_access.sleepmode);
- pbuf += sprintf(pbuf, " snr %u", le32_to_cpu(fwt_access.snr));
- pbuf += sprintf(pbuf, " ref %u", le32_to_cpu(fwt_access.references));
- } else
- pbuf += sprintf(pbuf, " (null)");
-
- wrq->u.data.length = strlen(out_str);
- if (copy_to_user(wrq->u.data.pointer, (char *)out_str,
- wrq->u.data.length)) {
- lbs_pr_debug(1, "FWT_LIST_NEIGHBOR: Copy to user failed!\n");
- return -EFAULT;
- }
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief Cleans up the route (FRT) and neighbor (FNT) tables
- * (Garbage Collection)
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_cleanup_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- static struct cmd_ds_fwt_access fwt_access;
- int ret;
-
- ENTER();
-
- lbs_pr_debug(1, "FWT: cleaning up\n");
-
- memset(&fwt_access, 0, sizeof(fwt_access));
-
- ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
- cmd_act_fwt_access_cleanup,
- cmd_option_waitforrsp, 0,
- (void *)&fwt_access);
-
- if (ret == 0)
- wrq->u.param.value = le32_to_cpu(fwt_access.references);
- else
- return -EFAULT;
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief Gets firmware internal time (debug purposes)
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_fwt_time_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- static struct cmd_ds_fwt_access fwt_access;
- int ret;
-
- ENTER();
-
- lbs_pr_debug(1, "FWT: getting time\n");
-
- memset(&fwt_access, 0, sizeof(fwt_access));
-
- ret = libertas_prepare_and_send_command(priv, cmd_fwt_access,
- cmd_act_fwt_access_time,
- cmd_option_waitforrsp, 0,
- (void *)&fwt_access);
-
- if (ret == 0)
- wrq->u.param.value = le32_to_cpu(fwt_access.references);
- else
- return -EFAULT;
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief Gets mesh ttl from firmware
- * @param priv A pointer to wlan_private structure
- * @param req A pointer to ifreq structure
- * @return 0 --success, otherwise fail
- */
-static int wlan_mesh_get_ttl_ioctl(wlan_private * priv, struct ifreq *req)
-{
- struct iwreq *wrq = (struct iwreq *)req;
- struct cmd_ds_mesh_access mesh_access;
- int ret;
-
- ENTER();
-
- memset(&mesh_access, 0, sizeof(mesh_access));
-
- ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
- cmd_act_mesh_get_ttl,
- cmd_option_waitforrsp, 0,
- (void *)&mesh_access);
-
- if (ret == 0)
- wrq->u.param.value = le32_to_cpu(mesh_access.data[0]);
- else
- return -EFAULT;
-
- LEAVE();
- return 0;
-}
-
-/**
- * @brief Gets mesh ttl from firmware
- * @param priv A pointer to wlan_private structure
- * @param ttl New ttl value
- * @return 0 --success, otherwise fail
- */
-static int wlan_mesh_set_ttl_ioctl(wlan_private * priv, int ttl)
-{
- struct cmd_ds_mesh_access mesh_access;
- int ret;
-
- ENTER();
-
- if( (ttl > 0xff) || (ttl < 0) )
- return -EINVAL;
-
- memset(&mesh_access, 0, sizeof(mesh_access));
- mesh_access.data[0] = ttl;
-
- ret = libertas_prepare_and_send_command(priv, cmd_mesh_access,
- cmd_act_mesh_set_ttl,
- cmd_option_waitforrsp, 0,
- (void *)&mesh_access);
-
- if (ret != 0)
- ret = -EFAULT;
-
- LEAVE();
- return ret;
-}
-
-/**
- * @brief ioctl function - entry point
- *
- * @param dev A pointer to net_device structure
- * @param req A pointer to ifreq structure
- * @param cmd command
- * @return 0--success, otherwise fail
- */
-int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
- int subcmd = 0;
- int idata = 0;
- int *pdata;
- int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
- struct iwreq *wrq = (struct iwreq *)req;
-
- ENTER();
-
- lbs_pr_debug(1, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
- switch (cmd) {
- case WLAN_SETNONE_GETNONE: /* set WPA mode on/off ioctl #20 */
- switch (wrq->u.data.flags) {
- case WLAN_SUBCMD_BT_RESET: /* bt_reset */
- wlan_bt_reset_ioctl(priv);
- break;
- case WLAN_SUBCMD_FWT_RESET: /* fwt_reset */
- wlan_fwt_reset_ioctl(priv);
- break;
- } /* End of switch */
- break;
-
- case WLAN_SETONEINT_GETNONE:
- /* The first 4 bytes of req->ifr_data is sub-ioctl number
- * after 4 bytes sits the payload.
- */
- subcmd = wrq->u.data.flags;
- if (!subcmd)
- subcmd = (int)wrq->u.param.value;
-
- switch (subcmd) {
- case WLANSETREGION:
- idata = SUBCMD_DATA(wrq);
- ret = wlan_set_region(priv, (u16) idata);
- break;
- case WLAN_SUBCMD_MESH_SET_TTL:
- idata = SUBCMD_DATA(wrq);
- ret = wlan_mesh_set_ttl_ioctl(priv, idata);
- break;
-
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
- break;
-
- case WLAN_SET128CHAR_GET128CHAR:
- switch ((int)wrq->u.data.flags) {
- case WLAN_SUBCMD_BT_ADD:
- ret = wlan_bt_add_ioctl(priv, req);
- break;
- case WLAN_SUBCMD_BT_DEL:
- ret = wlan_bt_del_ioctl(priv, req);
- break;
- case WLAN_SUBCMD_BT_LIST:
- ret = wlan_bt_list_ioctl(priv, req);
- break;
- case WLAN_SUBCMD_FWT_ADD:
- ret = wlan_fwt_add_ioctl(priv, req);
- break;
- case WLAN_SUBCMD_FWT_DEL:
- ret = wlan_fwt_del_ioctl(priv, req);
- break;
- case WLAN_SUBCMD_FWT_LOOKUP:
- ret = wlan_fwt_lookup_ioctl(priv, req);
- break;
- case WLAN_SUBCMD_FWT_LIST_NEIGHBOR:
- ret = wlan_fwt_list_neighbor_ioctl(priv, req);
- break;
- case WLAN_SUBCMD_FWT_LIST:
- ret = wlan_fwt_list_ioctl(priv, req);
- break;
- case WLAN_SUBCMD_FWT_LIST_ROUTE:
- ret = wlan_fwt_list_route_ioctl(priv, req);
- break;
- }
- break;
-
- case WLAN_SETNONE_GETONEINT:
- switch (wrq->u.param.value) {
- case WLANGETREGION:
- pdata = (int *)wrq->u.name;
- *pdata = (int)adapter->regioncode;
- break;
- case WLAN_SUBCMD_FWT_CLEANUP: /* fwt_cleanup */
- ret = wlan_fwt_cleanup_ioctl(priv, req);
- break;
-
- case WLAN_SUBCMD_FWT_TIME: /* fwt_time */
- ret = wlan_fwt_time_ioctl(priv, req);
- break;
-
- case WLAN_SUBCMD_MESH_GET_TTL:
- ret = wlan_mesh_get_ttl_ioctl(priv, req);
- break;
-
- default:
- ret = -EOPNOTSUPP;
-
- }
-
- break;
-
- case WLAN_SET_GET_SIXTEEN_INT:
- switch ((int)wrq->u.data.flags) {
- case WLAN_LED_GPIO_CTRL:
- {
- int i;
- int data[16];
-
- struct cmd_ds_802_11_led_ctrl ctrl;
- struct mrvlietypes_ledgpio *gpio =
- (struct mrvlietypes_ledgpio *) ctrl.data;
-
- memset(&ctrl, 0, sizeof(ctrl));
- if (wrq->u.data.length > MAX_LEDS * 2)
- return -ENOTSUPP;
- if ((wrq->u.data.length % 2) != 0)
- return -ENOTSUPP;
- if (wrq->u.data.length == 0) {
- ctrl.action =
- cpu_to_le16
- (cmd_act_get);
- } else {
- if (copy_from_user
- (data, wrq->u.data.pointer,
- sizeof(int) *
- wrq->u.data.length)) {
- lbs_pr_debug(1,
- "Copy from user failed\n");
- return -EFAULT;
- }
-
- ctrl.action =
- cpu_to_le16
- (cmd_act_set);
- ctrl.numled = cpu_to_le16(0);
- gpio->header.type =
- cpu_to_le16(TLV_TYPE_LED_GPIO);
- gpio->header.len = wrq->u.data.length;
- for (i = 0; i < wrq->u.data.length;
- i += 2) {
- gpio->ledpin[i / 2].led =
- data[i];
- gpio->ledpin[i / 2].pin =
- data[i + 1];
- }
- }
- ret =
- libertas_prepare_and_send_command(priv,
- cmd_802_11_led_gpio_ctrl,
- 0,
- cmd_option_waitforrsp,
- 0, (void *)&ctrl);
- for (i = 0; i < gpio->header.len; i += 2) {
- data[i] = gpio->ledpin[i / 2].led;
- data[i + 1] = gpio->ledpin[i / 2].pin;
- }
- if (copy_to_user(wrq->u.data.pointer, data,
- sizeof(int) *
- gpio->header.len)) {
- lbs_pr_debug(1, "Copy to user failed\n");
- return -EFAULT;
- }
-
- wrq->u.data.length = gpio->header.len;
- }
- break;
- }
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
- LEAVE();
- return ret;
-}
-
-
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
index d4926b83e14..78ac3064a0b 100644
--- a/drivers/net/wireless/libertas/join.c
+++ b/drivers/net/wireless/libertas/join.c
@@ -7,6 +7,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/wireless.h>
+#include <linux/etherdevice.h>
#include <net/iw_handler.h>
@@ -14,6 +15,7 @@
#include "decl.h"
#include "join.h"
#include "dev.h"
+#include "assoc.h"
#define AD_HOC_CAP_PRIVACY_ON 1
@@ -60,7 +62,7 @@ static int get_common_rates(wlan_adapter * adapter, u8 * rate1,
lbs_dbg_hex("rate1 (AP) rates:", tmp, sizeof(tmp));
lbs_dbg_hex("rate2 (Card) rates:", rate2, rate2_size);
lbs_dbg_hex("Common rates:", ptr, rate1_size);
- lbs_pr_debug(1, "Tx datarate is set to 0x%X\n", adapter->datarate);
+ lbs_deb_join("Tx datarate is set to 0x%X\n", adapter->datarate);
if (!adapter->is_datarate_auto) {
while (*ptr) {
@@ -104,24 +106,22 @@ int libertas_send_deauth(wlan_private * priv)
*
* @return 0-success, otherwise fail
*/
-int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
+int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int ret;
- ENTER();
+ lbs_deb_enter(LBS_DEB_JOIN);
ret = libertas_prepare_and_send_command(priv, cmd_802_11_authenticate,
0, cmd_option_waitforrsp,
- 0, pbssdesc->macaddress);
+ 0, assoc_req->bss.bssid);
- if (ret) {
- LEAVE();
- return ret;
- }
+ if (ret)
+ goto done;
/* set preamble to firmware */
- if (adapter->capinfo.shortpreamble && pbssdesc->cap.shortpreamble)
+ if (adapter->capinfo.shortpreamble && assoc_req->bss.cap.shortpreamble)
adapter->preamble = cmd_type_short_preamble;
else
adapter->preamble = cmd_type_long_preamble;
@@ -129,9 +129,10 @@ int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
libertas_set_radio_control(priv);
ret = libertas_prepare_and_send_command(priv, cmd_802_11_associate,
- 0, cmd_option_waitforrsp, 0, pbssdesc);
+ 0, cmd_option_waitforrsp, 0, assoc_req);
- LEAVE();
+done:
+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
return ret;
}
@@ -142,7 +143,7 @@ int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc)
* @param adhocssid The ssid of the Adhoc Network
* @return 0--success, -1--fail
*/
-int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *adhocssid)
+int libertas_start_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
int ret = 0;
@@ -150,22 +151,20 @@ int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *a
adapter->adhoccreate = 1;
if (!adapter->capinfo.shortpreamble) {
- lbs_pr_debug(1, "AdhocStart: Long preamble\n");
+ lbs_deb_join("AdhocStart: Long preamble\n");
adapter->preamble = cmd_type_long_preamble;
} else {
- lbs_pr_debug(1, "AdhocStart: Short preamble\n");
+ lbs_deb_join("AdhocStart: Short preamble\n");
adapter->preamble = cmd_type_short_preamble;
}
libertas_set_radio_control(priv);
- lbs_pr_debug(1, "Adhoc channel = %d\n", adapter->adhocchannel);
- lbs_pr_debug(1, "curbssparams.channel = %d\n",
- adapter->curbssparams.channel);
- lbs_pr_debug(1, "curbssparams.band = %d\n", adapter->curbssparams.band);
+ lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
+ lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_start,
- 0, cmd_option_waitforrsp, 0, adhocssid);
+ 0, cmd_option_waitforrsp, 0, assoc_req);
return ret;
}
@@ -179,52 +178,53 @@ int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *a
*
* @return 0--success, -1--fail
*/
-int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pbssdesc)
+int libertas_join_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req)
{
wlan_adapter *adapter = priv->adapter;
+ struct bss_descriptor * bss = &assoc_req->bss;
int ret = 0;
- lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid =%s\n",
- adapter->curbssparams.ssid.ssid);
- lbs_pr_debug(1, "libertas_join_adhoc_network: CurBss.ssid_len =%u\n",
- adapter->curbssparams.ssid.ssidlength);
- lbs_pr_debug(1, "libertas_join_adhoc_network: ssid =%s\n", pbssdesc->ssid.ssid);
- lbs_pr_debug(1, "libertas_join_adhoc_network: ssid len =%u\n",
- pbssdesc->ssid.ssidlength);
+ lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
+ __func__,
+ escape_essid(adapter->curbssparams.ssid,
+ adapter->curbssparams.ssid_len),
+ adapter->curbssparams.ssid_len);
+ lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
+ __func__, escape_essid(bss->ssid, bss->ssid_len),
+ bss->ssid_len);
/* check if the requested SSID is already joined */
- if (adapter->curbssparams.ssid.ssidlength
- && !libertas_SSID_cmp(&pbssdesc->ssid, &adapter->curbssparams.ssid)
+ if (adapter->curbssparams.ssid_len
+ && !libertas_ssid_cmp(adapter->curbssparams.ssid,
+ adapter->curbssparams.ssid_len,
+ bss->ssid, bss->ssid_len)
&& (adapter->mode == IW_MODE_ADHOC)) {
-
- lbs_pr_debug(1,
+ lbs_deb_join(
"ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
"not attempting to re-join");
-
return -1;
}
/*Use shortpreamble only when both creator and card supports
short preamble */
- if (!pbssdesc->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
- lbs_pr_debug(1, "AdhocJoin: Long preamble\n");
+ if (!bss->cap.shortpreamble || !adapter->capinfo.shortpreamble) {
+ lbs_deb_join("AdhocJoin: Long preamble\n");
adapter->preamble = cmd_type_long_preamble;
} else {
- lbs_pr_debug(1, "AdhocJoin: Short preamble\n");
+ lbs_deb_join("AdhocJoin: Short preamble\n");
adapter->preamble = cmd_type_short_preamble;
}
libertas_set_radio_control(priv);
- lbs_pr_debug(1, "curbssparams.channel = %d\n",
- adapter->curbssparams.channel);
- lbs_pr_debug(1, "curbssparams.band = %c\n", adapter->curbssparams.band);
+ lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
+ lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
adapter->adhoccreate = 0;
ret = libertas_prepare_and_send_command(priv, cmd_802_11_ad_hoc_join,
0, cmd_option_waitforrsp,
- OID_802_11_SSID, pbssdesc);
+ OID_802_11_SSID, assoc_req);
return ret;
}
@@ -265,6 +265,8 @@ int libertas_cmd_80211_authenticate(wlan_private * priv,
int ret = -1;
u8 *bssid = pdata_buf;
+ lbs_deb_enter(LBS_DEB_JOIN);
+
cmd->command = cpu_to_le16(cmd_802_11_authenticate);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate)
+ S_DS_GEN);
@@ -281,18 +283,19 @@ int libertas_cmd_80211_authenticate(wlan_private * priv,
pauthenticate->authtype = 0x80;
break;
default:
- lbs_pr_debug(1, "AUTH_CMD: invalid auth alg 0x%X\n",
+ lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
adapter->secinfo.auth_mode);
goto out;
}
memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
- lbs_pr_debug(1, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n",
- bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+ lbs_deb_join("AUTH_CMD: BSSID is : " MAC_FMT " auth=0x%X\n",
+ MAC_ARG(bssid), pauthenticate->authtype);
ret = 0;
out:
+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
return ret;
}
@@ -302,22 +305,20 @@ int libertas_cmd_80211_deauthenticate(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
- ENTER();
+ lbs_deb_enter(LBS_DEB_JOIN);
cmd->command = cpu_to_le16(cmd_802_11_deauthenticate);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) +
S_DS_GEN);
/* set AP MAC address */
- memmove(dauth->macaddr, adapter->curbssparams.bssid,
- ETH_ALEN);
+ memmove(dauth->macaddr, adapter->curbssparams.bssid, ETH_ALEN);
/* Reason code 3 = Station is leaving */
#define REASON_CODE_STA_LEAVING 3
dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_JOIN);
return 0;
}
@@ -327,20 +328,20 @@ int libertas_cmd_80211_associate(wlan_private * priv,
wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
int ret = 0;
- struct bss_descriptor *pbssdesc;
+ struct assoc_request * assoc_req = pdata_buf;
+ struct bss_descriptor * bss = &assoc_req->bss;
u8 *card_rates;
u8 *pos;
int card_rates_size;
- u16 tmpcap;
+ u16 tmpcap, tmplen;
struct mrvlietypes_ssidparamset *ssid;
struct mrvlietypes_phyparamset *phy;
struct mrvlietypes_ssparamset *ss;
struct mrvlietypes_ratesparamset *rates;
struct mrvlietypes_rsnparamset *rsn;
- ENTER();
+ lbs_deb_enter(LBS_DEB_JOIN);
- pbssdesc = pdata_buf;
pos = (u8 *) passo;
if (!adapter) {
@@ -350,15 +351,11 @@ int libertas_cmd_80211_associate(wlan_private * priv,
cmd->command = cpu_to_le16(cmd_802_11_associate);
- /* Save so we know which BSS Desc to use in the response handler */
- adapter->pattemptedbssdesc = pbssdesc;
-
- memcpy(passo->peerstaaddr,
- pbssdesc->macaddress, sizeof(passo->peerstaaddr));
+ memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr));
pos += sizeof(passo->peerstaaddr);
/* set the listen interval */
- passo->listeninterval = adapter->listeninterval;
+ passo->listeninterval = cpu_to_le16(adapter->listeninterval);
pos += sizeof(passo->capinfo);
pos += sizeof(passo->listeninterval);
@@ -367,30 +364,30 @@ int libertas_cmd_80211_associate(wlan_private * priv,
ssid = (struct mrvlietypes_ssidparamset *) pos;
ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
- ssid->header.len = pbssdesc->ssid.ssidlength;
- memcpy(ssid->ssid, pbssdesc->ssid.ssid, ssid->header.len);
- pos += sizeof(ssid->header) + ssid->header.len;
- ssid->header.len = cpu_to_le16(ssid->header.len);
+ tmplen = bss->ssid_len;
+ ssid->header.len = cpu_to_le16(tmplen);
+ memcpy(ssid->ssid, bss->ssid, tmplen);
+ pos += sizeof(ssid->header) + tmplen;
phy = (struct mrvlietypes_phyparamset *) pos;
phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
- phy->header.len = sizeof(phy->fh_ds.dsparamset);
+ tmplen = sizeof(phy->fh_ds.dsparamset);
+ phy->header.len = cpu_to_le16(tmplen);
memcpy(&phy->fh_ds.dsparamset,
- &pbssdesc->phyparamset.dsparamset.currentchan,
- sizeof(phy->fh_ds.dsparamset));
- pos += sizeof(phy->header) + phy->header.len;
- phy->header.len = cpu_to_le16(phy->header.len);
+ &bss->phyparamset.dsparamset.currentchan,
+ tmplen);
+ pos += sizeof(phy->header) + tmplen;
ss = (struct mrvlietypes_ssparamset *) pos;
ss->header.type = cpu_to_le16(TLV_TYPE_CF);
- ss->header.len = sizeof(ss->cf_ibss.cfparamset);
- pos += sizeof(ss->header) + ss->header.len;
- ss->header.len = cpu_to_le16(ss->header.len);
+ tmplen = sizeof(ss->cf_ibss.cfparamset);
+ ss->header.len = cpu_to_le16(tmplen);
+ pos += sizeof(ss->header) + tmplen;
rates = (struct mrvlietypes_ratesparamset *) pos;
rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
- memcpy(&rates->rates, &pbssdesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
+ memcpy(&rates->rates, &bss->libertas_supported_rates, WLAN_SUPPORTED_RATES);
card_rates = libertas_supported_rates;
card_rates_size = sizeof(libertas_supported_rates);
@@ -401,41 +398,42 @@ int libertas_cmd_80211_associate(wlan_private * priv,
goto done;
}
- rates->header.len = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
- adapter->curbssparams.numofrates = rates->header.len;
+ tmplen = min_t(size_t, strlen(rates->rates), WLAN_SUPPORTED_RATES);
+ adapter->curbssparams.numofrates = tmplen;
- pos += sizeof(rates->header) + rates->header.len;
- rates->header.len = cpu_to_le16(rates->header.len);
+ pos += sizeof(rates->header) + tmplen;
+ rates->header.len = cpu_to_le16(tmplen);
- if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) {
+ if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
rsn = (struct mrvlietypes_rsnparamset *) pos;
- rsn->header.type = (u16) adapter->wpa_ie[0]; /* WPA_IE or WPA2_IE */
- rsn->header.type = cpu_to_le16(rsn->header.type);
- rsn->header.len = (u16) adapter->wpa_ie[1];
- memcpy(rsn->rsnie, &adapter->wpa_ie[2], rsn->header.len);
+ /* WPA_IE or WPA2_IE */
+ rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
+ tmplen = (u16) assoc_req->wpa_ie[1];
+ rsn->header.len = cpu_to_le16(tmplen);
+ memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
lbs_dbg_hex("ASSOC_CMD: RSN IE", (u8 *) rsn,
- sizeof(rsn->header) + rsn->header.len);
- pos += sizeof(rsn->header) + rsn->header.len;
- rsn->header.len = cpu_to_le16(rsn->header.len);
+ sizeof(rsn->header) + tmplen);
+ pos += sizeof(rsn->header) + tmplen;
}
/* update curbssparams */
- adapter->curbssparams.channel =
- (pbssdesc->phyparamset.dsparamset.currentchan);
+ adapter->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
/* Copy the infra. association rates into Current BSS state structure */
memcpy(&adapter->curbssparams.datarates, &rates->rates,
- min_t(size_t, sizeof(adapter->curbssparams.datarates), rates->header.len));
+ min_t(size_t, sizeof(adapter->curbssparams.datarates),
+ cpu_to_le16(rates->header.len)));
- lbs_pr_debug(1, "ASSOC_CMD: rates->header.len = %d\n", rates->header.len);
+ lbs_deb_join("ASSOC_CMD: rates->header.len = %d\n",
+ cpu_to_le16(rates->header.len));
/* set IBSS field */
- if (pbssdesc->mode == IW_MODE_INFRA) {
+ if (bss->mode == IW_MODE_INFRA) {
#define CAPINFO_ESS_MODE 1
passo->capinfo.ess = CAPINFO_ESS_MODE;
}
- if (libertas_parse_dnld_countryinfo_11d(priv)) {
+ if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
ret = -1;
goto done;
}
@@ -443,31 +441,28 @@ int libertas_cmd_80211_associate(wlan_private * priv,
cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN);
/* set the capability info at last */
- memcpy(&tmpcap, &pbssdesc->cap, sizeof(passo->capinfo));
+ memcpy(&tmpcap, &bss->cap, sizeof(passo->capinfo));
tmpcap &= CAPINFO_MASK;
- lbs_pr_debug(1, "ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
- tmpcap, CAPINFO_MASK);
- tmpcap = cpu_to_le16(tmpcap);
+ lbs_deb_join("ASSOC_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
+ tmpcap, CAPINFO_MASK);
memcpy(&passo->capinfo, &tmpcap, sizeof(passo->capinfo));
- done:
- LEAVE();
+done:
+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
return ret;
}
int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
- struct cmd_ds_command *cmd, void *pssid)
+ struct cmd_ds_command *cmd, void *pdata_buf)
{
wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
int ret = 0;
int cmdappendsize = 0;
int i;
- u16 tmpcap;
- struct bss_descriptor *pbssdesc;
- struct WLAN_802_11_SSID *ssid = pssid;
+ struct assoc_request * assoc_req = pdata_buf;
- ENTER();
+ lbs_deb_enter(LBS_DEB_JOIN);
if (!adapter) {
ret = -1;
@@ -476,9 +471,6 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_start);
- pbssdesc = &adapter->curbssparams.bssdescriptor;
- adapter->pattemptedbssdesc = pbssdesc;
-
/*
* Fill in the parameters for 2 data structures:
* 1. cmd_ds_802_11_ad_hoc_start command
@@ -492,20 +484,16 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
*/
memset(adhs->SSID, 0, IW_ESSID_MAX_SIZE);
+ memcpy(adhs->SSID, assoc_req->ssid, assoc_req->ssid_len);
- memcpy(adhs->SSID, ssid->ssid, ssid->ssidlength);
-
- lbs_pr_debug(1, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
-
- memset(pbssdesc->ssid.ssid, 0, IW_ESSID_MAX_SIZE);
- memcpy(pbssdesc->ssid.ssid, ssid->ssid, ssid->ssidlength);
-
- pbssdesc->ssid.ssidlength = ssid->ssidlength;
+ lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n",
+ escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+ assoc_req->ssid_len);
/* set the BSS type */
adhs->bsstype = cmd_bss_type_ibss;
- pbssdesc->mode = IW_MODE_ADHOC;
- adhs->beaconperiod = adapter->beaconperiod;
+ adapter->mode = IW_MODE_ADHOC;
+ adhs->beaconperiod = cpu_to_le16(adapter->beaconperiod);
/* set Physical param set */
#define DS_PARA_IE_ID 3
@@ -514,18 +502,12 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID;
adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN;
- WARN_ON(!adapter->adhocchannel);
+ WARN_ON(!assoc_req->channel);
- lbs_pr_debug(1, "ADHOC_S_CMD: Creating ADHOC on channel %d\n",
- adapter->adhocchannel);
+ lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n",
+ assoc_req->channel);
- adapter->curbssparams.channel = adapter->adhocchannel;
-
- pbssdesc->channel = adapter->adhocchannel;
- adhs->phyparamset.dsparamset.currentchan = adapter->adhocchannel;
-
- memcpy(&pbssdesc->phyparamset,
- &adhs->phyparamset, sizeof(union ieeetypes_phyparamset));
+ adhs->phyparamset.dsparamset.currentchan = assoc_req->channel;
/* set IBSS param set */
#define IBSS_PARA_IE_ID 6
@@ -533,26 +515,21 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID;
adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN;
- adhs->ssparamset.ibssparamset.atimwindow = adapter->atimwindow;
- memcpy(&pbssdesc->ssparamset,
- &adhs->ssparamset, sizeof(union IEEEtypes_ssparamset));
+ adhs->ssparamset.ibssparamset.atimwindow = cpu_to_le16(adapter->atimwindow);
/* set capability info */
adhs->cap.ess = 0;
adhs->cap.ibss = 1;
- pbssdesc->cap.ibss = 1;
/* probedelay */
adhs->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
/* set up privacy in adapter->scantable[i] */
- if (adapter->secinfo.wep_enabled) {
- lbs_pr_debug(1, "ADHOC_S_CMD: WEP enabled, setting privacy on\n");
- pbssdesc->privacy = wlan802_11privfilter8021xWEP;
+ if (assoc_req->secinfo.wep_enabled) {
+ lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n");
adhs->cap.privacy = AD_HOC_CAP_PRIVACY_ON;
} else {
- lbs_pr_debug(1, "ADHOC_S_CMD: WEP disabled, setting privacy off\n");
- pbssdesc->privacy = wlan802_11privfilteracceptall;
+ lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n");
}
memset(adhs->datarate, 0, sizeof(adhs->datarate));
@@ -574,29 +551,24 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
memcpy(&adapter->curbssparams.datarates,
&adhs->datarate, adapter->curbssparams.numofrates);
- lbs_pr_debug(1, "ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
+ lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
adhs->datarate[0], adhs->datarate[1],
adhs->datarate[2], adhs->datarate[3]);
- lbs_pr_debug(1, "ADHOC_S_CMD: AD HOC Start command is ready\n");
+ lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
if (libertas_create_dnld_countryinfo_11d(priv)) {
- lbs_pr_debug(1, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
+ lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
ret = -1;
goto done;
}
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start)
- + S_DS_GEN + cmdappendsize);
-
- memcpy(&tmpcap, &adhs->cap, sizeof(u16));
- tmpcap = cpu_to_le16(tmpcap);
- memcpy(&adhs->cap, &tmpcap, sizeof(u16));
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) +
+ S_DS_GEN + cmdappendsize);
ret = 0;
done:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
return ret;
}
@@ -614,7 +586,8 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
{
wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_ad_hoc_join *padhocjoin = &cmd->params.adj;
- struct bss_descriptor *pbssdesc = pdata_buf;
+ struct assoc_request * assoc_req = pdata_buf;
+ struct bss_descriptor *bss = &assoc_req->bss;
int cmdappendsize = 0;
int ret = 0;
u8 *card_rates;
@@ -622,70 +595,59 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
u16 tmpcap;
int i;
- ENTER();
-
- adapter->pattemptedbssdesc = pbssdesc;
+ lbs_deb_enter(LBS_DEB_JOIN);
cmd->command = cpu_to_le16(cmd_802_11_ad_hoc_join);
padhocjoin->bssdescriptor.bsstype = cmd_bss_type_ibss;
- padhocjoin->bssdescriptor.beaconperiod = pbssdesc->beaconperiod;
-
- memcpy(&padhocjoin->bssdescriptor.BSSID,
- &pbssdesc->macaddress, ETH_ALEN);
+ padhocjoin->bssdescriptor.beaconperiod = cpu_to_le16(bss->beaconperiod);
- memcpy(&padhocjoin->bssdescriptor.SSID,
- &pbssdesc->ssid.ssid, pbssdesc->ssid.ssidlength);
+ memcpy(&padhocjoin->bssdescriptor.BSSID, &bss->bssid, ETH_ALEN);
+ memcpy(&padhocjoin->bssdescriptor.SSID, &bss->ssid, bss->ssid_len);
memcpy(&padhocjoin->bssdescriptor.phyparamset,
- &pbssdesc->phyparamset, sizeof(union ieeetypes_phyparamset));
+ &bss->phyparamset, sizeof(union ieeetypes_phyparamset));
memcpy(&padhocjoin->bssdescriptor.ssparamset,
- &pbssdesc->ssparamset, sizeof(union IEEEtypes_ssparamset));
+ &bss->ssparamset, sizeof(union IEEEtypes_ssparamset));
- memcpy(&tmpcap, &pbssdesc->cap, sizeof(struct ieeetypes_capinfo));
+ memcpy(&tmpcap, &bss->cap, sizeof(struct ieeetypes_capinfo));
tmpcap &= CAPINFO_MASK;
- lbs_pr_debug(1, "ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
+ lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
tmpcap, CAPINFO_MASK);
memcpy(&padhocjoin->bssdescriptor.cap, &tmpcap,
sizeof(struct ieeetypes_capinfo));
/* information on BSSID descriptor passed to FW */
- lbs_pr_debug(1,
- "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
- padhocjoin->bssdescriptor.BSSID[0],
- padhocjoin->bssdescriptor.BSSID[1],
- padhocjoin->bssdescriptor.BSSID[2],
- padhocjoin->bssdescriptor.BSSID[3],
- padhocjoin->bssdescriptor.BSSID[4],
- padhocjoin->bssdescriptor.BSSID[5],
+ lbs_deb_join(
+ "ADHOC_J_CMD: BSSID = " MAC_FMT ", SSID = '%s'\n",
+ MAC_ARG(padhocjoin->bssdescriptor.BSSID),
padhocjoin->bssdescriptor.SSID);
/* failtimeout */
padhocjoin->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
/* probedelay */
- padhocjoin->probedelay =
- cpu_to_le16(cmd_scan_probe_delay_time);
+ padhocjoin->probedelay = cpu_to_le16(cmd_scan_probe_delay_time);
/* Copy Data rates from the rates recorded in scan response */
memset(padhocjoin->bssdescriptor.datarates, 0,
sizeof(padhocjoin->bssdescriptor.datarates));
- memcpy(padhocjoin->bssdescriptor.datarates, pbssdesc->datarates,
+ memcpy(padhocjoin->bssdescriptor.datarates, bss->datarates,
min(sizeof(padhocjoin->bssdescriptor.datarates),
- sizeof(pbssdesc->datarates)));
+ sizeof(bss->datarates)));
card_rates = libertas_supported_rates;
card_rates_size = sizeof(libertas_supported_rates);
- adapter->curbssparams.channel = pbssdesc->channel;
+ adapter->curbssparams.channel = bss->channel;
if (get_common_rates(adapter, padhocjoin->bssdescriptor.datarates,
sizeof(padhocjoin->bssdescriptor.datarates),
card_rates, card_rates_size)) {
- lbs_pr_debug(1, "ADHOC_J_CMD: get_common_rates returns error.\n");
+ lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
ret = -1;
goto done;
}
@@ -704,17 +666,17 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
adapter->curbssparams.numofrates);
padhocjoin->bssdescriptor.ssparamset.ibssparamset.atimwindow =
- cpu_to_le16(pbssdesc->atimwindow);
+ cpu_to_le16(bss->atimwindow);
- if (adapter->secinfo.wep_enabled) {
+ if (assoc_req->secinfo.wep_enabled) {
padhocjoin->bssdescriptor.cap.privacy = AD_HOC_CAP_PRIVACY_ON;
}
if (adapter->psmode == wlan802_11powermodemax_psp) {
/* wake up first */
- enum WLAN_802_11_POWER_MODE Localpsmode;
+ __le32 Localpsmode;
- Localpsmode = wlan802_11powermodecam;
+ Localpsmode = cpu_to_le32(wlan802_11powermodecam);
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_ps_mode,
cmd_act_set,
@@ -726,24 +688,16 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
}
}
- if (libertas_parse_dnld_countryinfo_11d(priv)) {
+ if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
ret = -1;
goto done;
}
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join)
- + S_DS_GEN + cmdappendsize);
-
- memcpy(&tmpcap, &padhocjoin->bssdescriptor.cap,
- sizeof(struct ieeetypes_capinfo));
- tmpcap = cpu_to_le16(tmpcap);
-
- memcpy(&padhocjoin->bssdescriptor.cap,
- &tmpcap, sizeof(struct ieeetypes_capinfo));
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) +
+ S_DS_GEN + cmdappendsize);
- done:
- LEAVE();
+done:
+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
return ret;
}
@@ -754,19 +708,24 @@ int libertas_ret_80211_associate(wlan_private * priv,
int ret = 0;
union iwreq_data wrqu;
struct ieeetypes_assocrsp *passocrsp;
- struct bss_descriptor *pbssdesc;
+ struct bss_descriptor * bss;
- ENTER();
+ lbs_deb_enter(LBS_DEB_JOIN);
- passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
+ if (!adapter->in_progress_assoc_req) {
+ lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
+ ret = -1;
+ goto done;
+ }
+ bss = &adapter->in_progress_assoc_req->bss;
- if (passocrsp->statuscode) {
+ passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
+ if (le16_to_cpu(passocrsp->statuscode)) {
libertas_mac_event_disconnected(priv);
- lbs_pr_debug(1,
- "ASSOC_RESP: Association failed, status code = %d\n",
- passocrsp->statuscode);
+ lbs_deb_join("ASSOC_RESP: Association failed, status code = %d\n",
+ le16_to_cpu(passocrsp->statuscode));
ret = -1;
goto done;
@@ -778,24 +737,15 @@ int libertas_ret_80211_associate(wlan_private * priv,
/* Send a Media Connected event, according to the Spec */
adapter->connect_status = libertas_connected;
- /* Set the attempted BSSID Index to current */
- pbssdesc = adapter->pattemptedbssdesc;
-
- lbs_pr_debug(1, "ASSOC_RESP: %s\n", pbssdesc->ssid.ssid);
+ lbs_deb_join("ASSOC_RESP: assocated to '%s'\n",
+ escape_essid(bss->ssid, bss->ssid_len));
- /* Set the new SSID to current SSID */
- memcpy(&adapter->curbssparams.ssid,
- &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
-
- /* Set the new BSSID (AP's MAC address) to current BSSID */
- memcpy(adapter->curbssparams.bssid,
- pbssdesc->macaddress, ETH_ALEN);
-
- /* Make a copy of current BSSID descriptor */
- memcpy(&adapter->curbssparams.bssdescriptor,
- pbssdesc, sizeof(struct bss_descriptor));
+ /* Update current SSID and BSSID */
+ memcpy(&adapter->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+ adapter->curbssparams.ssid_len = bss->ssid_len;
+ memcpy(adapter->curbssparams.bssid, bss->bssid, ETH_ALEN);
- lbs_pr_debug(1, "ASSOC_RESP: currentpacketfilter is %x\n",
+ lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
adapter->currentpacketfilter);
adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
@@ -806,28 +756,31 @@ int libertas_ret_80211_associate(wlan_private * priv,
adapter->nextSNRNF = 0;
adapter->numSNRNF = 0;
- netif_carrier_on(priv->wlan_dev.netdev);
- netif_wake_queue(priv->wlan_dev.netdev);
+ netif_carrier_on(priv->dev);
+ netif_wake_queue(priv->dev);
- lbs_pr_debug(1, "ASSOC_RESP: Associated \n");
+ netif_carrier_on(priv->mesh_dev);
+ netif_wake_queue(priv->mesh_dev);
+
+ lbs_deb_join("ASSOC_RESP: Associated \n");
memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
- done:
- LEAVE();
+done:
+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
return ret;
}
int libertas_ret_80211_disassociate(wlan_private * priv,
struct cmd_ds_command *resp)
{
- ENTER();
+ lbs_deb_enter(LBS_DEB_JOIN);
libertas_mac_event_disconnected(priv);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_JOIN);
return 0;
}
@@ -840,90 +793,85 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
u16 result = le16_to_cpu(resp->result);
struct cmd_ds_802_11_ad_hoc_result *padhocresult;
union iwreq_data wrqu;
- struct bss_descriptor *pbssdesc;
+ struct bss_descriptor *bss;
- ENTER();
+ lbs_deb_enter(LBS_DEB_JOIN);
padhocresult = &resp->params.result;
- lbs_pr_debug(1, "ADHOC_S_RESP: size = %d\n", le16_to_cpu(resp->size));
- lbs_pr_debug(1, "ADHOC_S_RESP: command = %x\n", command);
- lbs_pr_debug(1, "ADHOC_S_RESP: result = %x\n", result);
+ lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size));
+ lbs_deb_join("ADHOC_RESP: command = %x\n", command);
+ lbs_deb_join("ADHOC_RESP: result = %x\n", result);
- pbssdesc = adapter->pattemptedbssdesc;
+ if (!adapter->in_progress_assoc_req) {
+ lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
+ ret = -1;
+ goto done;
+ }
+ bss = &adapter->in_progress_assoc_req->bss;
/*
* Join result code 0 --> SUCCESS
*/
if (result) {
- lbs_pr_debug(1, "ADHOC_RESP failed\n");
+ lbs_deb_join("ADHOC_RESP: failed\n");
if (adapter->connect_status == libertas_connected) {
libertas_mac_event_disconnected(priv);
}
-
- memset(&adapter->curbssparams.bssdescriptor,
- 0x00, sizeof(adapter->curbssparams.bssdescriptor));
-
- LEAVE();
- return -1;
+ ret = -1;
+ goto done;
}
/*
* Now the join cmd should be successful
* If BSSID has changed use SSID to compare instead of BSSID
*/
- lbs_pr_debug(1, "ADHOC_J_RESP %s\n", pbssdesc->ssid.ssid);
+ lbs_deb_join("ADHOC_RESP: associated to '%s'\n",
+ escape_essid(bss->ssid, bss->ssid_len));
/* Send a Media Connected event, according to the Spec */
adapter->connect_status = libertas_connected;
if (command == cmd_ret_802_11_ad_hoc_start) {
/* Update the created network descriptor with the new BSSID */
- memcpy(pbssdesc->macaddress,
- padhocresult->BSSID, ETH_ALEN);
- } else {
-
- /* Make a copy of current BSSID descriptor, only needed for join since
- * the current descriptor is already being used for adhoc start
- */
- memmove(&adapter->curbssparams.bssdescriptor,
- pbssdesc, sizeof(struct bss_descriptor));
+ memcpy(bss->bssid, padhocresult->BSSID, ETH_ALEN);
}
/* Set the BSSID from the joined/started descriptor */
- memcpy(&adapter->curbssparams.bssid,
- pbssdesc->macaddress, ETH_ALEN);
+ memcpy(&adapter->curbssparams.bssid, bss->bssid, ETH_ALEN);
/* Set the new SSID to current SSID */
- memcpy(&adapter->curbssparams.ssid,
- &pbssdesc->ssid, sizeof(struct WLAN_802_11_SSID));
+ memcpy(&adapter->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+ adapter->curbssparams.ssid_len = bss->ssid_len;
- netif_carrier_on(priv->wlan_dev.netdev);
- netif_wake_queue(priv->wlan_dev.netdev);
+ netif_carrier_on(priv->dev);
+ netif_wake_queue(priv->dev);
+
+ netif_carrier_on(priv->mesh_dev);
+ netif_wake_queue(priv->mesh_dev);
memset(&wrqu, 0, sizeof(wrqu));
memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
- lbs_pr_debug(1, "ADHOC_RESP: - Joined/Started Ad Hoc\n");
- lbs_pr_debug(1, "ADHOC_RESP: channel = %d\n", adapter->adhocchannel);
- lbs_pr_debug(1, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
- padhocresult->BSSID[0], padhocresult->BSSID[1],
- padhocresult->BSSID[2], padhocresult->BSSID[3],
- padhocresult->BSSID[4], padhocresult->BSSID[5]);
+ lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
+ lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->curbssparams.channel);
+ lbs_deb_join("ADHOC_RESP: BSSID = " MAC_FMT "\n",
+ MAC_ARG(padhocresult->BSSID));
- LEAVE();
+done:
+ lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
return ret;
}
int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
struct cmd_ds_command *resp)
{
- ENTER();
+ lbs_deb_enter(LBS_DEB_JOIN);
libertas_mac_event_disconnected(priv);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_JOIN);
return 0;
}
diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h
index 115f5a8ba34..d522630ff8c 100644
--- a/drivers/net/wireless/libertas/join.h
+++ b/drivers/net/wireless/libertas/join.h
@@ -9,6 +9,7 @@
#define _WLAN_JOIN_H
#include "defs.h"
+#include "dev.h"
struct cmd_ds_command;
extern int libertas_cmd_80211_authenticate(wlan_private * priv,
@@ -21,7 +22,7 @@ extern int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
struct cmd_ds_command *cmd);
extern int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
struct cmd_ds_command *cmd,
- void *pssid);
+ void *pdata_buf);
extern int libertas_cmd_80211_deauthenticate(wlan_private * priv,
struct cmd_ds_command *cmd);
extern int libertas_cmd_80211_associate(wlan_private * priv,
@@ -39,12 +40,10 @@ extern int libertas_ret_80211_associate(wlan_private * priv,
extern int libertas_reassociation_thread(void *data);
-struct WLAN_802_11_SSID;
-struct bss_descriptor;
-
extern int libertas_start_adhoc_network(wlan_private * priv,
- struct WLAN_802_11_SSID *adhocssid);
-extern int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor *pbssdesc);
+ struct assoc_request * assoc_req);
+extern int libertas_join_adhoc_network(wlan_private * priv,
+ struct assoc_request * assoc_req);
extern int libertas_stop_adhoc_network(wlan_private * priv);
extern int libertas_send_deauthentication(wlan_private * priv);
@@ -52,6 +51,6 @@ extern int libertas_send_deauth(wlan_private * priv);
extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
-int wlan_associate(wlan_private * priv, struct bss_descriptor * pbssdesc);
+int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req);
#endif
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index b9b25ce6591..4a59306a3f0 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -4,6 +4,7 @@
* thread etc..
*/
+#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/etherdevice.h>
@@ -11,26 +12,28 @@
#include <linux/if_arp.h>
#include <net/iw_handler.h>
+#include <net/ieee80211.h>
#include "host.h"
-#include "sbi.h"
#include "decl.h"
#include "dev.h"
-#include "fw.h"
#include "wext.h"
#include "debugfs.h"
#include "assoc.h"
-#define DRIVER_RELEASE_VERSION "320.p0"
+#define DRIVER_RELEASE_VERSION "322.p0"
const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
#ifdef DEBUG
"-dbg"
#endif
"";
-#ifdef ENABLE_PM
-static struct pm_dev *wlan_pm_dev = NULL;
-#endif
+
+/* Module parameters */
+unsigned int libertas_debug = 0;
+module_param(libertas_debug, int, 0644);
+EXPORT_SYMBOL_GPL(libertas_debug);
+
#define WLAN_TX_PWR_DEFAULT 20 /*100mW */
#define WLAN_TX_PWR_US_DEFAULT 20 /*100mW */
@@ -146,14 +149,6 @@ static struct region_cfp_table region_cfp_table[] = {
};
/**
- * the rates supported by the card
- */
-u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] =
- { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
- 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
-};
-
-/**
* the rates supported
*/
u8 libertas_supported_rates[G_SUPPORTED_RATES] =
@@ -173,66 +168,57 @@ u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES] =
u8 libertas_adhoc_rates_b[4] = { 0x82, 0x84, 0x8b, 0x96 };
/**
- * the global variable of a pointer to wlan_private
- * structure variable
- */
-static wlan_private *wlanpriv = NULL;
-
-#define MAX_DEVS 5
-static struct net_device *libertas_devs[MAX_DEVS];
-static int libertas_found = 0;
-
-/**
* the table to keep region code
*/
u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
{ 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
-static u8 *default_fw_name = "usb8388.bin";
-
/**
* Attributes exported through sysfs
*/
/**
- * @brief Get function for sysfs attribute libertas_mpp
+ * @brief Get function for sysfs attribute anycast_mask
*/
-static ssize_t libertas_mpp_get(struct device * dev,
- struct device_attribute *attr, char * buf) {
+static ssize_t libertas_anycast_get(struct device * dev,
+ struct device_attribute *attr, char * buf)
+{
struct cmd_ds_mesh_access mesh_access;
memset(&mesh_access, 0, sizeof(mesh_access));
libertas_prepare_and_send_command(to_net_dev(dev)->priv,
cmd_mesh_access,
- cmd_act_mesh_get_mpp,
+ cmd_act_mesh_get_anycast,
cmd_option_waitforrsp, 0, (void *)&mesh_access);
- return snprintf(buf, 3, "%d\n", mesh_access.data[0]);
+ return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
}
/**
- * @brief Set function for sysfs attribute libertas_mpp
+ * @brief Set function for sysfs attribute anycast_mask
*/
-static ssize_t libertas_mpp_set(struct device * dev,
- struct device_attribute *attr, const char * buf, size_t count) {
+static ssize_t libertas_anycast_set(struct device * dev,
+ struct device_attribute *attr, const char * buf, size_t count)
+{
struct cmd_ds_mesh_access mesh_access;
-
+ uint32_t datum;
memset(&mesh_access, 0, sizeof(mesh_access));
- sscanf(buf, "%d", &(mesh_access.data[0]));
+ sscanf(buf, "%x", &datum);
+ mesh_access.data[0] = cpu_to_le32(datum);
+
libertas_prepare_and_send_command((to_net_dev(dev))->priv,
cmd_mesh_access,
- cmd_act_mesh_set_mpp,
+ cmd_act_mesh_set_anycast,
cmd_option_waitforrsp, 0, (void *)&mesh_access);
return strlen(buf);
}
/**
- * libertas_mpp attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/libertas-mpp)
+ * anycast_mask attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/anycast_mask)
*/
-static DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get,
- libertas_mpp_set );
+static DEVICE_ATTR(anycast_mask, 0644, libertas_anycast_get, libertas_anycast_set);
/**
* @brief Check if the device can be open and wait if necessary.
@@ -245,7 +231,8 @@ static DEVICE_ATTR(libertas_mpp, 0644, libertas_mpp_get,
* function to work around the issue.
*
*/
-static int pre_open_check(struct net_device *dev) {
+static int pre_open_check(struct net_device *dev)
+{
wlan_private *priv = (wlan_private *) dev->priv;
wlan_adapter *adapter = priv->adapter;
int i = 0;
@@ -255,8 +242,7 @@ static int pre_open_check(struct net_device *dev) {
msleep_interruptible(100);
}
if (!adapter->fw_ready) {
- lbs_pr_info("FW not ready, pre_open_check() return failure\n");
- LEAVE();
+ lbs_pr_err("firmware not ready\n");
return -1;
}
@@ -274,17 +260,19 @@ static int wlan_dev_open(struct net_device *dev)
wlan_private *priv = (wlan_private *) dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
-
+ lbs_deb_enter(LBS_DEB_NET);
priv->open = 1;
if (adapter->connect_status == libertas_connected) {
- netif_carrier_on(priv->wlan_dev.netdev);
- } else
- netif_carrier_off(priv->wlan_dev.netdev);
+ netif_carrier_on(priv->dev);
+ netif_carrier_on(priv->mesh_dev);
+ } else {
+ netif_carrier_off(priv->dev);
+ netif_carrier_off(priv->mesh_dev);
+ }
- LEAVE();
+ lbs_deb_leave(LBS_DEB_NET);
return 0;
}
/**
@@ -297,12 +285,12 @@ static int mesh_open(struct net_device *dev)
{
wlan_private *priv = (wlan_private *) dev->priv ;
- if(pre_open_check(dev) == -1)
+ if (pre_open_check(dev) == -1)
return -1;
priv->mesh_open = 1 ;
- netif_start_queue(priv->mesh_dev);
+ netif_wake_queue(priv->mesh_dev);
if (priv->infra_open == 0)
- return wlan_dev_open(priv->wlan_dev.netdev) ;
+ return wlan_dev_open(priv->dev) ;
return 0;
}
@@ -319,9 +307,9 @@ static int wlan_open(struct net_device *dev)
if(pre_open_check(dev) == -1)
return -1;
priv->infra_open = 1 ;
- netif_wake_queue(priv->wlan_dev.netdev);
+ netif_wake_queue(priv->dev);
if (priv->open == 0)
- return wlan_dev_open(priv->wlan_dev.netdev) ;
+ return wlan_dev_open(priv->dev) ;
return 0;
}
@@ -329,12 +317,12 @@ static int wlan_dev_close(struct net_device *dev)
{
wlan_private *priv = dev->priv;
- ENTER();
+ lbs_deb_enter(LBS_DEB_NET);
- netif_carrier_off(priv->wlan_dev.netdev);
+ netif_carrier_off(priv->dev);
priv->open = 0;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_NET);
return 0;
}
@@ -351,7 +339,7 @@ static int mesh_close(struct net_device *dev)
priv->mesh_open = 0;
netif_stop_queue(priv->mesh_dev);
if (priv->infra_open == 0)
- return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ;
+ return wlan_dev_close(dev);
else
return 0;
}
@@ -362,147 +350,38 @@ static int mesh_close(struct net_device *dev)
* @param dev A pointer to net_device structure
* @return 0
*/
-static int wlan_close(struct net_device *dev) {
+static int wlan_close(struct net_device *dev)
+{
wlan_private *priv = (wlan_private *) dev->priv;
- netif_stop_queue(priv->wlan_dev.netdev);
+ netif_stop_queue(dev);
priv->infra_open = 0;
if (priv->mesh_open == 0)
- return wlan_dev_close( ((wlan_private *) dev->priv)->wlan_dev.netdev) ;
+ return wlan_dev_close(dev);
else
return 0;
}
-#ifdef ENABLE_PM
-
-/**
- * @brief This function is a callback function. it is called by
- * kernel to enter or exit power saving mode.
- *
- * @param pmdev A pointer to pm_dev
- * @param pmreq pm_request_t
- * @param pmdata A pointer to pmdata
- * @return 0 or -1
- */
-static int wlan_pm_callback(struct pm_dev *pmdev, pm_request_t pmreq,
- void *pmdata)
-{
- wlan_private *priv = wlanpriv;
- wlan_adapter *adapter = priv->adapter;
- struct net_device *dev = priv->wlan_dev.netdev;
-
- lbs_pr_debug(1, "WPRM_PM_CALLBACK: pmreq = %d.\n", pmreq);
-
- switch (pmreq) {
- case PM_SUSPEND:
- lbs_pr_debug(1, "WPRM_PM_CALLBACK: enter PM_SUSPEND.\n");
-
- /* in associated mode */
- if (adapter->connect_status == libertas_connected) {
- if ((adapter->psstate != PS_STATE_SLEEP)
- ) {
- lbs_pr_debug(1,
- "wlan_pm_callback: can't enter sleep mode\n");
- return -1;
- } else {
-
- /*
- * Detach the network interface
- * if the network is running
- */
- if (netif_running(dev)) {
- netif_device_detach(dev);
- lbs_pr_debug(1,
- "netif_device_detach().\n");
- }
- libertas_sbi_suspend(priv);
- }
- break;
- }
-
- /* in non associated mode */
-
- /*
- * Detach the network interface
- * if the network is running
- */
- if (netif_running(dev))
- netif_device_detach(dev);
-
- /*
- * Storing and restoring of the regs be taken care
- * at the driver rest will be done at wlan driver
- * this makes driver independent of the card
- */
-
- libertas_sbi_suspend(priv);
-
- break;
-
- case PM_RESUME:
- /* in associated mode */
- if (adapter->connect_status == libertas_connected) {
- {
- /*
- * Bring the inteface up first
- * This case should not happen still ...
- */
- libertas_sbi_resume(priv);
-
- /*
- * Attach the network interface
- * if the network is running
- */
- if (netif_running(dev)) {
- netif_device_attach(dev);
- lbs_pr_debug(1,
- "after netif_device_attach().\n");
- }
- lbs_pr_debug(1,
- "After netif attach, in associated mode.\n");
- }
- break;
- }
-
- /* in non associated mode */
-
- /*
- * Bring the inteface up first
- * This case should not happen still ...
- */
-
- libertas_sbi_resume(priv);
-
- if (netif_running(dev))
- netif_device_attach(dev);
-
- lbs_pr_debug(1, "after netif attach, in NON associated mode.\n");
- break;
- }
-
- return 0;
-}
-#endif /* ENABLE_PM */
-
static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
int ret = 0;
wlan_private *priv = dev->priv;
- ENTER();
+ lbs_deb_enter(LBS_DEB_NET);
- if (priv->wlan_dev.dnld_sent || priv->adapter->TxLockFlag) {
+ if (priv->dnld_sent || priv->adapter->TxLockFlag) {
priv->stats.tx_dropped++;
goto done;
}
- netif_stop_queue(priv->wlan_dev.netdev);
+ netif_stop_queue(priv->dev);
+ netif_stop_queue(priv->mesh_dev);
if (libertas_process_tx(priv, skb) == 0)
dev->trans_start = jiffies;
done:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
@@ -513,33 +392,43 @@ done:
static int mesh_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
wlan_private *priv = dev->priv;
- ENTER();
+ int ret;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+
SET_MESH_FRAME(skb);
- LEAVE();
- return wlan_hard_start_xmit(skb, priv->wlan_dev.netdev);
+ ret = wlan_hard_start_xmit(skb, priv->dev);
+ lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+ return ret;
}
/**
* @brief Mark non-mesh packets and handover them to wlan_hard_start_xmit
*
*/
-static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev) {
- ENTER();
+static int wlan_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ int ret;
+
+ lbs_deb_enter(LBS_DEB_NET);
+
UNSET_MESH_FRAME(skb);
- LEAVE();
- return wlan_hard_start_xmit(skb, dev);
+
+ ret = wlan_hard_start_xmit(skb, dev);
+ lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+ return ret;
}
static void wlan_tx_timeout(struct net_device *dev)
{
wlan_private *priv = (wlan_private *) dev->priv;
- ENTER();
+ lbs_deb_enter(LBS_DEB_TX);
- lbs_pr_err("tx watch dog timeout!\n");
+ lbs_pr_err("tx watch dog timeout\n");
- priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+ priv->dnld_sent = DNLD_RES_RECEIVED;
dev->trans_start = jiffies;
if (priv->adapter->currenttxskb) {
@@ -550,10 +439,12 @@ static void wlan_tx_timeout(struct net_device *dev)
libertas_send_tx_feedback(priv);
} else
wake_up_interruptible(&priv->mainthread.waitq);
- } else if (priv->adapter->connect_status == libertas_connected)
- netif_wake_queue(priv->wlan_dev.netdev);
+ } else if (priv->adapter->connect_status == libertas_connected) {
+ netif_wake_queue(priv->dev);
+ netif_wake_queue(priv->mesh_dev);
+ }
- LEAVE();
+ lbs_deb_leave(LBS_DEB_TX);
}
/**
@@ -576,7 +467,10 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr)
wlan_adapter *adapter = priv->adapter;
struct sockaddr *phwaddr = addr;
- ENTER();
+ lbs_deb_enter(LBS_DEB_NET);
+
+ /* In case it was called from the mesh device */
+ dev = priv->dev ;
memset(adapter->current_addr, 0, ETH_ALEN);
@@ -591,17 +485,18 @@ static int wlan_set_mac_address(struct net_device *dev, void *addr)
cmd_option_waitforrsp, 0, NULL);
if (ret) {
- lbs_pr_debug(1, "set mac address failed.\n");
+ lbs_deb_net("set MAC address failed\n");
ret = -1;
goto done;
}
lbs_dbg_hex("adapter->macaddr:", adapter->current_addr, ETH_ALEN);
memcpy(dev->dev_addr, adapter->current_addr, ETH_ALEN);
- memcpy(((wlan_private *) dev->priv)->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
+ if (priv->mesh_dev)
+ memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
done:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
@@ -626,12 +521,12 @@ static void wlan_set_multicast_list(struct net_device *dev)
wlan_adapter *adapter = priv->adapter;
int oldpacketfilter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_NET);
oldpacketfilter = adapter->currentpacketfilter;
if (dev->flags & IFF_PROMISC) {
- lbs_pr_debug(1, "enable Promiscuous mode\n");
+ lbs_deb_net("enable promiscuous mode\n");
adapter->currentpacketfilter |=
cmd_act_mac_promiscuous_enable;
adapter->currentpacketfilter &=
@@ -644,7 +539,7 @@ static void wlan_set_multicast_list(struct net_device *dev)
if (dev->flags & IFF_ALLMULTI || dev->mc_count >
MRVDRV_MAX_MULTICAST_LIST_SIZE) {
- lbs_pr_debug(1, "Enabling All Multicast!\n");
+ lbs_deb_net( "enabling all multicast\n");
adapter->currentpacketfilter |=
cmd_act_mac_all_multicast_enable;
adapter->currentpacketfilter &=
@@ -654,8 +549,8 @@ static void wlan_set_multicast_list(struct net_device *dev)
~cmd_act_mac_all_multicast_enable;
if (!dev->mc_count) {
- lbs_pr_debug(1, "No multicast addresses - "
- "disabling multicast!\n");
+ lbs_deb_net("no multicast addresses, "
+ "disabling multicast\n");
adapter->currentpacketfilter &=
~cmd_act_mac_multicast_enable;
} else {
@@ -667,12 +562,12 @@ static void wlan_set_multicast_list(struct net_device *dev)
adapter->nr_of_multicastmacaddr =
wlan_copy_multicast_address(adapter, dev);
- lbs_pr_debug(1, "Multicast addresses: %d\n",
+ lbs_deb_net("multicast addresses: %d\n",
dev->mc_count);
for (i = 0; i < dev->mc_count; i++) {
- lbs_pr_debug(1, "Multicast address %d:"
- "%x %x %x %x %x %x\n", i,
+ lbs_deb_net("Multicast address %d:"
+ MAC_FMT "\n", i,
adapter->multicastlist[i][0],
adapter->multicastlist[i][1],
adapter->multicastlist[i][2],
@@ -680,7 +575,7 @@ static void wlan_set_multicast_list(struct net_device *dev)
adapter->multicastlist[i][4],
adapter->multicastlist[i][5]);
}
- /* set multicast addresses to firmware */
+ /* send multicast addresses to firmware */
libertas_prepare_and_send_command(priv,
cmd_mac_multicast_adr,
cmd_act_set, 0, 0,
@@ -693,13 +588,13 @@ static void wlan_set_multicast_list(struct net_device *dev)
libertas_set_mac_packet_filter(priv);
}
- LEAVE();
+ lbs_deb_leave(LBS_DEB_NET);
}
/**
- * @brief This function hanldes the major job in WLAN driver.
- * it handles the event generated by firmware, rx data received
- * from firmware and tx data sent from kernel.
+ * @brief This function handles the major jobs in the WLAN driver.
+ * It handles all events generated by firmware, RX data received
+ * from firmware and TX data sent from kernel.
*
* @param data A pointer to wlan_thread structure
* @return 0
@@ -712,26 +607,26 @@ static int wlan_service_main_thread(void *data)
wait_queue_t wait;
u8 ireg = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_THREAD);
wlan_activate_thread(thread);
init_waitqueue_entry(&wait, current);
for (;;) {
- lbs_pr_debug(1, "main-thread 111: intcounter=%d "
+ lbs_deb_thread( "main-thread 111: intcounter=%d "
"currenttxskb=%p dnld_sent=%d\n",
adapter->intcounter,
- adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+ adapter->currenttxskb, priv->dnld_sent);
add_wait_queue(&thread->waitq, &wait);
set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irq(&adapter->driver_lock);
if ((adapter->psstate == PS_STATE_SLEEP) ||
(!adapter->intcounter
- && (priv->wlan_dev.dnld_sent || adapter->cur_cmd ||
+ && (priv->dnld_sent || adapter->cur_cmd ||
list_empty(&adapter->cmdpendingq)))) {
- lbs_pr_debug(1,
+ lbs_deb_thread(
"main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
adapter->connect_status, adapter->intcounter,
adapter->psmode, adapter->psstate);
@@ -741,23 +636,23 @@ static int wlan_service_main_thread(void *data)
spin_unlock_irq(&adapter->driver_lock);
- lbs_pr_debug(1,
+ lbs_deb_thread(
"main-thread 222 (waking up): intcounter=%d currenttxskb=%p "
"dnld_sent=%d\n", adapter->intcounter,
- adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+ adapter->currenttxskb, priv->dnld_sent);
set_current_state(TASK_RUNNING);
remove_wait_queue(&thread->waitq, &wait);
try_to_freeze();
- lbs_pr_debug(1, "main-thread 333: intcounter=%d currenttxskb=%p "
+ lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p "
"dnld_sent=%d\n",
adapter->intcounter,
- adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+ adapter->currenttxskb, priv->dnld_sent);
if (kthread_should_stop()
|| adapter->surpriseremoved) {
- lbs_pr_debug(1,
+ lbs_deb_thread(
"main-thread: break from main thread: surpriseremoved=0x%x\n",
adapter->surpriseremoved);
break;
@@ -768,10 +663,10 @@ static int wlan_service_main_thread(void *data)
if (adapter->intcounter) {
u8 int_status;
adapter->intcounter = 0;
- int_status = libertas_sbi_get_int_status(priv, &ireg);
+ int_status = priv->hw_get_int_status(priv, &ireg);
if (int_status) {
- lbs_pr_debug(1,
+ lbs_deb_thread(
"main-thread: reading HOST_INT_STATUS_REG failed\n");
spin_unlock_irq(&adapter->driver_lock);
continue;
@@ -779,14 +674,14 @@ static int wlan_service_main_thread(void *data)
adapter->hisregcpy |= ireg;
}
- lbs_pr_debug(1, "main-thread 444: intcounter=%d currenttxskb=%p "
+ lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p "
"dnld_sent=%d\n",
adapter->intcounter,
- adapter->currenttxskb, priv->wlan_dev.dnld_sent);
+ adapter->currenttxskb, priv->dnld_sent);
/* command response? */
if (adapter->hisregcpy & his_cmdupldrdy) {
- lbs_pr_debug(1, "main-thread: cmd response ready.\n");
+ lbs_deb_thread("main-thread: cmd response ready\n");
adapter->hisregcpy &= ~his_cmdupldrdy;
spin_unlock_irq(&adapter->driver_lock);
@@ -796,13 +691,13 @@ static int wlan_service_main_thread(void *data)
/* Any Card Event */
if (adapter->hisregcpy & his_cardevent) {
- lbs_pr_debug(1, "main-thread: Card Event Activity.\n");
+ lbs_deb_thread("main-thread: Card Event Activity\n");
adapter->hisregcpy &= ~his_cardevent;
- if (libertas_sbi_read_event_cause(priv)) {
+ if (priv->hw_read_event_cause(priv)) {
lbs_pr_alert(
- "main-thread: libertas_sbi_read_event_cause failed.\n");
+ "main-thread: hw_read_event_cause failed\n");
spin_unlock_irq(&adapter->driver_lock);
continue;
}
@@ -813,15 +708,15 @@ static int wlan_service_main_thread(void *data)
/* Check if we need to confirm Sleep Request received previously */
if (adapter->psstate == PS_STATE_PRE_SLEEP) {
- if (!priv->wlan_dev.dnld_sent && !adapter->cur_cmd) {
+ if (!priv->dnld_sent && !adapter->cur_cmd) {
if (adapter->connect_status ==
libertas_connected) {
- lbs_pr_debug(1,
+ lbs_deb_thread(
"main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p "
"dnld_sent=%d cur_cmd=%p, confirm now\n",
adapter->intcounter,
adapter->currenttxskb,
- priv->wlan_dev.dnld_sent,
+ priv->dnld_sent,
adapter->cur_cmd);
libertas_ps_confirm_sleep(priv,
@@ -847,7 +742,7 @@ static int wlan_service_main_thread(void *data)
continue;
/* Execute the next command */
- if (!priv->wlan_dev.dnld_sent && !priv->adapter->cur_cmd)
+ if (!priv->dnld_sent && !priv->adapter->cur_cmd)
libertas_execute_next_command(priv);
/* Wake-up command waiters which can't sleep in
@@ -864,7 +759,7 @@ static int wlan_service_main_thread(void *data)
wake_up_all(&adapter->cmd_pending);
wlan_deactivate_thread(thread);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_THREAD);
return 0;
}
@@ -875,166 +770,203 @@ static int wlan_service_main_thread(void *data)
* @param card A pointer to card
* @return A pointer to wlan_private structure
*/
-wlan_private *wlan_add_card(void *card)
+wlan_private *libertas_add_card(void *card, struct device *dmdev)
{
struct net_device *dev = NULL;
- struct net_device *mesh_dev = NULL;
wlan_private *priv = NULL;
- ENTER();
+ lbs_deb_enter(LBS_DEB_NET);
/* Allocate an Ethernet device and register it */
if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
- lbs_pr_alert( "Init ethernet device failed!\n");
+ lbs_pr_err("init ethX device failed\n");
return NULL;
}
-
priv = dev->priv;
/* allocate buffer for wlan_adapter */
- if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
- lbs_pr_alert( "Allocate buffer for wlan_adapter failed!\n");
- goto err_kmalloc;
- }
-
- /* Allocate a virtual mesh device */
- if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
- lbs_pr_debug(1, "Init ethernet device failed!\n");
- return NULL;
+ if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
+ lbs_pr_err("allocate buffer for wlan_adapter failed\n");
+ goto err_kzalloc;
}
- /* Both intervaces share the priv structure */
- mesh_dev->priv = priv;
-
- /* init wlan_adapter */
- memset(priv->adapter, 0, sizeof(wlan_adapter));
-
- priv->wlan_dev.netdev = dev;
- priv->wlan_dev.card = card;
+ priv->dev = dev;
+ priv->card = card;
priv->mesh_open = 0;
priv->infra_open = 0;
- priv->mesh_dev = mesh_dev;
- wlanpriv = priv;
SET_MODULE_OWNER(dev);
- SET_MODULE_OWNER(mesh_dev);
/* Setup the OS Interface to our functions */
dev->open = wlan_open;
dev->hard_start_xmit = wlan_pre_start_xmit;
dev->stop = wlan_close;
- dev->do_ioctl = libertas_do_ioctl;
dev->set_mac_address = wlan_set_mac_address;
- mesh_dev->open = mesh_open;
- mesh_dev->hard_start_xmit = mesh_pre_start_xmit;
- mesh_dev->stop = mesh_close;
- mesh_dev->do_ioctl = libertas_do_ioctl;
- memcpy(mesh_dev->dev_addr, wlanpriv->wlan_dev.netdev->dev_addr,
- sizeof(wlanpriv->wlan_dev.netdev->dev_addr));
-
-#define WLAN_WATCHDOG_TIMEOUT (5 * HZ)
-
dev->tx_timeout = wlan_tx_timeout;
dev->get_stats = wlan_get_stats;
- dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT;
+ dev->watchdog_timeo = 5 * HZ;
dev->ethtool_ops = &libertas_ethtool_ops;
- mesh_dev->get_stats = wlan_get_stats;
- mesh_dev->ethtool_ops = &libertas_ethtool_ops;
-
#ifdef WIRELESS_EXT
dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
- mesh_dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
#endif
#define NETIF_F_DYNALLOC 16
dev->features |= NETIF_F_DYNALLOC;
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
dev->set_multicast_list = wlan_set_multicast_list;
+ SET_NETDEV_DEV(dev, dmdev);
+
INIT_LIST_HEAD(&priv->adapter->cmdfreeq);
INIT_LIST_HEAD(&priv->adapter->cmdpendingq);
spin_lock_init(&priv->adapter->driver_lock);
init_waitqueue_head(&priv->adapter->cmd_pending);
priv->adapter->nr_cmd_pending = 0;
+ goto done;
+
+err_kzalloc:
+ free_netdev(dev);
+ priv = NULL;
+done:
+ lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv);
+ return priv;
+}
+EXPORT_SYMBOL_GPL(libertas_add_card);
- lbs_pr_debug(1, "Starting kthread...\n");
+int libertas_activate_card(wlan_private *priv, char *fw_name)
+{
+ struct net_device *dev = priv->dev;
+ int ret = -1;
+
+ lbs_deb_enter(LBS_DEB_MAIN);
+
+ lbs_deb_thread("Starting kthread...\n");
priv->mainthread.priv = priv;
wlan_create_thread(wlan_service_main_thread,
&priv->mainthread, "wlan_main_service");
priv->assoc_thread =
create_singlethread_workqueue("libertas_assoc");
- INIT_DELAYED_WORK(&priv->assoc_work, wlan_association_worker);
+ INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
+ INIT_WORK(&priv->sync_channel, libertas_sync_channel);
/*
* Register the device. Fillup the private data structure with
* relevant information from the card and request for the required
* IRQ.
*/
- if (libertas_sbi_register_dev(priv) < 0) {
- lbs_pr_info("failed to register wlan device!\n");
+ if (priv->hw_register_dev(priv) < 0) {
+ lbs_pr_err("failed to register WLAN device\n");
goto err_registerdev;
}
/* init FW and HW */
- if (libertas_init_fw(priv)) {
- lbs_pr_debug(1, "Firmware Init failed\n");
+ if (fw_name && libertas_init_fw(priv, fw_name)) {
+ lbs_pr_err("firmware init failed\n");
goto err_registerdev;
}
if (register_netdev(dev)) {
- lbs_pr_err("Cannot register network device!\n");
- goto err_init_fw;
- }
-
- /* Register virtual mesh interface */
- if (register_netdev(mesh_dev)) {
- lbs_pr_info("Cannot register mesh virtual interface!\n");
+ lbs_pr_err("cannot register ethX device\n");
goto err_init_fw;
}
- lbs_pr_info("%s: Marvell Wlan 802.11 adapter ", dev->name);
+ lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
libertas_debugfs_init_one(priv, dev);
- if (libertas_found == MAX_DEVS)
- goto err_init_fw;
- libertas_devs[libertas_found] = dev;
- libertas_found++;
-#ifdef ENABLE_PM
- if (!(wlan_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, wlan_pm_callback)))
- lbs_pr_alert( "failed to register PM callback\n");
-#endif
- if (device_create_file(&(mesh_dev->dev), &dev_attr_libertas_mpp))
- goto err_create_file;
+ ret = 0;
+ goto done;
- LEAVE();
- return priv;
-
-err_create_file:
- device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp);
err_init_fw:
- libertas_sbi_unregister_dev(priv);
+ priv->hw_unregister_dev(priv);
err_registerdev:
destroy_workqueue(priv->assoc_thread);
/* Stop the thread servicing the interrupts */
wake_up_interruptible(&priv->mainthread.waitq);
wlan_terminate_thread(&priv->mainthread);
- kfree(priv->adapter);
-err_kmalloc:
- free_netdev(dev);
+done:
+ lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(libertas_activate_card);
+
+
+/**
+ * @brief This function adds mshX interface
+ *
+ * @param priv A pointer to the wlan_private structure
+ * @return 0 if successful, -X otherwise
+ */
+int libertas_add_mesh(wlan_private *priv, struct device *dev)
+{
+ struct net_device *mesh_dev = NULL;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_MESH);
+
+ /* Allocate a virtual mesh device */
+ if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
+ lbs_deb_mesh("init mshX device failed\n");
+ ret = -ENOMEM;
+ goto done;
+ }
+ mesh_dev->priv = priv;
+ priv->mesh_dev = mesh_dev;
+
+ SET_MODULE_OWNER(mesh_dev);
+
+ mesh_dev->open = mesh_open;
+ mesh_dev->hard_start_xmit = mesh_pre_start_xmit;
+ mesh_dev->stop = mesh_close;
+ mesh_dev->get_stats = wlan_get_stats;
+ mesh_dev->set_mac_address = wlan_set_mac_address;
+ mesh_dev->ethtool_ops = &libertas_ethtool_ops;
+ memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
+ sizeof(priv->dev->dev_addr));
+
+ SET_NETDEV_DEV(priv->mesh_dev, dev);
+
+#ifdef WIRELESS_EXT
+ mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
+#endif
+#define NETIF_F_DYNALLOC 16
+
+ /* Register virtual mesh interface */
+ ret = register_netdev(mesh_dev);
+ if (ret) {
+ lbs_pr_err("cannot register mshX virtual interface\n");
+ goto err_free;
+ }
+
+ ret = device_create_file(&(mesh_dev->dev), &dev_attr_anycast_mask);
+ if (ret)
+ goto err_unregister;
+
+ /* Everything successful */
+ ret = 0;
+ goto done;
+
+
+err_unregister:
+ unregister_netdev(mesh_dev);
+
+err_free:
free_netdev(mesh_dev);
- wlanpriv = NULL;
- LEAVE();
- return NULL;
+done:
+ lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+ return ret;
}
+EXPORT_SYMBOL_GPL(libertas_add_mesh);
static void wake_pending_cmdnodes(wlan_private *priv)
{
struct cmd_ctrl_node *cmdnode;
unsigned long flags;
+ lbs_deb_enter(LBS_DEB_CMD);
+
spin_lock_irqsave(&priv->adapter->driver_lock, flags);
list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {
cmdnode->cmdwaitqwoken = 1;
@@ -1044,40 +976,29 @@ static void wake_pending_cmdnodes(wlan_private *priv)
}
-int wlan_remove_card(void *card)
+int libertas_remove_card(wlan_private *priv)
{
- wlan_private *priv = libertas_sbi_get_priv(card);
wlan_adapter *adapter;
struct net_device *dev;
- struct net_device *mesh_dev;
union iwreq_data wrqu;
- int i;
- ENTER();
+ lbs_deb_enter(LBS_DEB_NET);
- if (!priv) {
- LEAVE();
- return 0;
- }
+ if (!priv)
+ goto out;
adapter = priv->adapter;
- if (!adapter) {
- LEAVE();
- return 0;
- }
+ if (!adapter)
+ goto out;
- dev = priv->wlan_dev.netdev;
- mesh_dev = priv->mesh_dev;
+ dev = priv->dev;
- netif_stop_queue(mesh_dev);
- netif_stop_queue(priv->wlan_dev.netdev);
- netif_carrier_off(priv->wlan_dev.netdev);
+ netif_stop_queue(priv->dev);
+ netif_carrier_off(priv->dev);
wake_pending_cmdnodes(priv);
- device_remove_file(&(mesh_dev->dev), &dev_attr_libertas_mpp);
- unregister_netdev(mesh_dev);
unregister_netdev(dev);
cancel_delayed_work(&priv->assoc_work);
@@ -1090,11 +1011,7 @@ int wlan_remove_card(void *card)
memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
-
-#ifdef ENABLE_PM
- pm_unregister(wlan_pm_dev);
-#endif
+ wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
adapter->surpriseremoved = 1;
@@ -1103,28 +1020,45 @@ int wlan_remove_card(void *card)
libertas_debugfs_remove_one(priv);
- lbs_pr_debug(1, "Free adapter\n");
+ lbs_deb_net("free adapter\n");
libertas_free_adapter(priv);
- for (i = 0; i<libertas_found; i++) {
- if (libertas_devs[i]==priv->wlan_dev.netdev) {
- libertas_devs[i] = libertas_devs[--libertas_found];
- libertas_devs[libertas_found] = NULL ;
- break ;
- }
- }
+ lbs_deb_net("unregister finish\n");
+
+ priv->dev = NULL;
+ free_netdev(dev);
+
+out:
+ lbs_deb_leave(LBS_DEB_NET);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(libertas_remove_card);
+
+
+void libertas_remove_mesh(wlan_private *priv)
+{
+ struct net_device *mesh_dev;
+
+ lbs_deb_enter(LBS_DEB_NET);
+
+ if (!priv)
+ goto out;
+
+ mesh_dev = priv->mesh_dev;
+
+ netif_stop_queue(mesh_dev);
+ netif_carrier_off(priv->mesh_dev);
- lbs_pr_debug(1, "Unregister finish\n");
+ device_remove_file(&(mesh_dev->dev), &dev_attr_anycast_mask);
+ unregister_netdev(mesh_dev);
- priv->wlan_dev.netdev = NULL;
priv->mesh_dev = NULL ;
free_netdev(mesh_dev);
- free_netdev(dev);
- wlanpriv = NULL;
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave(LBS_DEB_NET);
}
+EXPORT_SYMBOL_GPL(libertas_remove_mesh);
/**
* @brief This function finds the CFP in
@@ -1139,33 +1073,34 @@ struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *c
{
int i, end;
- ENTER();
+ lbs_deb_enter(LBS_DEB_MAIN);
end = sizeof(region_cfp_table)/sizeof(struct region_cfp_table);
for (i = 0; i < end ; i++) {
- lbs_pr_debug(1, "region_cfp_table[i].region=%d\n",
+ lbs_deb_main("region_cfp_table[i].region=%d\n",
region_cfp_table[i].region);
if (region_cfp_table[i].region == region) {
*cfp_no = region_cfp_table[i].cfp_no_BG;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_MAIN);
return region_cfp_table[i].cfp_BG;
}
}
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
return NULL;
}
int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band)
{
wlan_adapter *adapter = priv->adapter;
+ int ret = 0;
int i = 0;
struct chan_freq_power *cfp;
int cfp_no;
- ENTER();
+ lbs_deb_enter(LBS_DEB_MAIN);
memset(adapter->region_channel, 0, sizeof(adapter->region_channel));
@@ -1175,17 +1110,19 @@ int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band)
adapter->region_channel[i].nrcfp = cfp_no;
adapter->region_channel[i].CFP = cfp;
} else {
- lbs_pr_debug(1, "wrong region code %#x in band B-G\n",
+ lbs_deb_main("wrong region code %#x in band B/G\n",
region);
- return -1;
+ ret = -1;
+ goto out;
}
adapter->region_channel[i].valid = 1;
adapter->region_channel[i].region = region;
adapter->region_channel[i].band = band;
i++;
}
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+ return ret;
}
/**
@@ -1200,9 +1137,9 @@ void libertas_interrupt(struct net_device *dev)
{
wlan_private *priv = dev->priv;
- ENTER();
+ lbs_deb_enter(LBS_DEB_THREAD);
- lbs_pr_debug(1, "libertas_interrupt: intcounter=%d\n",
+ lbs_deb_thread("libertas_interrupt: intcounter=%d\n",
priv->adapter->intcounter);
priv->adapter->intcounter++;
@@ -1210,56 +1147,35 @@ void libertas_interrupt(struct net_device *dev)
if (priv->adapter->psstate == PS_STATE_SLEEP) {
priv->adapter->psstate = PS_STATE_AWAKE;
netif_wake_queue(dev);
+ netif_wake_queue(priv->mesh_dev);
}
wake_up_interruptible(&priv->mainthread.waitq);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_THREAD);
}
+EXPORT_SYMBOL_GPL(libertas_interrupt);
-static int wlan_init_module(void)
+static int libertas_init_module(void)
{
- int ret = 0;
-
- ENTER();
-
- if (libertas_fw_name == NULL) {
- libertas_fw_name = default_fw_name;
- }
-
+ lbs_deb_enter(LBS_DEB_MAIN);
libertas_debugfs_init();
-
- if (libertas_sbi_register()) {
- ret = -1;
- libertas_debugfs_remove();
- goto done;
- }
-
-done:
- LEAVE();
- return ret;
+ lbs_deb_leave(LBS_DEB_MAIN);
+ return 0;
}
-static void wlan_cleanup_module(void)
+static void libertas_exit_module(void)
{
- int i;
-
- ENTER();
-
- for (i = 0; i<libertas_found; i++) {
- wlan_private *priv = libertas_devs[i]->priv;
- reset_device(priv);
- }
+ lbs_deb_enter(LBS_DEB_MAIN);
- libertas_sbi_unregister();
libertas_debugfs_remove();
- LEAVE();
+ lbs_deb_leave(LBS_DEB_MAIN);
}
-module_init(wlan_init_module);
-module_exit(wlan_cleanup_module);
+module_init(libertas_init_module);
+module_exit(libertas_exit_module);
-MODULE_DESCRIPTION("M-WLAN Driver");
+MODULE_DESCRIPTION("Libertas WLAN Driver Library");
MODULE_AUTHOR("Marvell International Ltd.");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 96619a32951..88d9d2d787d 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -106,10 +106,10 @@ static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd)
{
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_RX);
- lbs_pr_debug(1, "rxpd: SNR = %d, NF = %d\n", p_rx_pd->snr, p_rx_pd->nf);
- lbs_pr_debug(1, "Before computing SNR: SNR- avg = %d, NF-avg = %d\n",
+ lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
+ lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
@@ -121,7 +121,7 @@ static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd)
adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getavgsnr(priv) * AVG_SCALE;
adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getavgnf(priv) * AVG_SCALE;
- lbs_pr_debug(1, "After computing SNR: SNR-avg = %d, NF-avg = %d\n",
+ lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
@@ -133,18 +133,17 @@ static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd)
CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_RX);
}
void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
{
- lbs_pr_debug(1, "skb->data=%p\n", skb->data);
+ lbs_deb_rx("skb->data %p\n", skb->data);
- if(IS_MESH_FRAME(skb))
- skb->dev = priv->mesh_dev;
+ if (priv->mesh_dev && IS_MESH_FRAME(skb))
+ skb->protocol = eth_type_trans(skb, priv->mesh_dev);
else
- skb->dev = priv->wlan_dev.netdev;
- skb->protocol = eth_type_trans(skb, priv->wlan_dev.netdev);
+ skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = CHECKSUM_UNNECESSARY;
netif_rx(skb);
@@ -171,7 +170,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
- ENTER();
+ lbs_deb_enter(LBS_DEB_RX);
if (priv->adapter->debugmode & MRVDRV_DEBUG_RX_PATH)
lbs_dbg_hex("RX packet: ", skb->data,
@@ -191,7 +190,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
min_t(unsigned int, skb->len, 100));
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
- lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n");
+ lbs_deb_rx("rx err: frame received with bad length\n");
priv->stats.rx_length_errors++;
ret = 0;
goto done;
@@ -200,15 +199,15 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
/*
* Check rxpd status and update 802.3 stat,
*/
- if (!(p_rx_pd->status & MRVDRV_RXPD_STATUS_OK)) {
- lbs_pr_debug(1, "RX error: frame received with bad status\n");
- lbs_pr_alert("rxpd Not OK\n");
+ if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
+ lbs_deb_rx("rx err: frame received with bad status\n");
+ lbs_pr_alert("rxpd not ok\n");
priv->stats.rx_errors++;
ret = 0;
goto done;
}
- lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %zd = %zd\n",
+ lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
lbs_dbg_hex("RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr,
@@ -266,7 +265,7 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
wlan_compute_rssi(priv, p_rx_pd);
- lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len);
+ lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
priv->stats.rx_bytes += skb->len;
priv->stats.rx_packets++;
@@ -274,10 +273,10 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
ret = 0;
done:
- LEAVE();
-
+ lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
return ret;
}
+EXPORT_SYMBOL_GPL(libertas_process_rxed_packet);
/**
* @brief This function converts Tx/Rx rates from the Marvell WLAN format
@@ -314,7 +313,7 @@ static u8 convert_mv_rate_to_radiotap(u8 rate)
case 11: /* 54 Mbps */
return 108;
}
- lbs_pr_alert( "Invalid Marvell WLAN rate (%i)\n", rate);
+ lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate);
return 0;
}
@@ -336,7 +335,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
struct rx_radiotap_hdr radiotap_hdr;
struct rx_radiotap_hdr *pradiotap_hdr;
- ENTER();
+ lbs_deb_enter(LBS_DEB_RX);
p_rx_pkt = (struct rx80211packethdr *) skb->data;
prxpd = &p_rx_pkt->rx_pd;
@@ -344,7 +343,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
// lbs_dbg_hex("RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
- lbs_pr_debug(1, "RX error: FRAME RECEIVED WITH BAD LENGTH\n");
+ lbs_deb_rx("rx err: frame received wit bad length\n");
priv->stats.rx_length_errors++;
ret = 0;
goto done;
@@ -353,12 +352,12 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
/*
* Check rxpd status and update 802.3 stat,
*/
- if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK)) {
- //lbs_pr_debug(1, "RX error: frame received with bad status\n");
+ if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) {
+ //lbs_deb_rx("rx err: frame received with bad status\n");
priv->stats.rx_errors++;
}
- lbs_pr_debug(1, "RX Data: skb->len - sizeof(RxPd) = %d - %zd = %zd\n",
+ lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
/* create the exported radio header */
@@ -386,7 +385,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
/* XXX must check no carryout */
radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
radiotap_hdr.rx_flags = 0;
- if (!(prxpd->status & MRVDRV_RXPD_STATUS_OK))
+ if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
//memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);
@@ -399,7 +398,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0,
GFP_ATOMIC)) {
- lbs_pr_alert( "%s: couldn't pskb_expand_head\n",
+ lbs_pr_alert("%s: couldn't pskb_expand_head\n",
__func__);
}
@@ -414,7 +413,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
default:
/* unknown header */
- lbs_pr_alert( "Unknown radiomode (%i)\n",
+ lbs_pr_alert("Unknown radiomode %i\n",
priv->adapter->radiomode);
/* don't export any header */
/* chop the rxpd */
@@ -431,15 +430,16 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
wlan_compute_rssi(priv, prxpd);
- lbs_pr_debug(1, "RX Data: size of actual packet = %d\n", skb->len);
+ lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
priv->stats.rx_bytes += skb->len;
priv->stats.rx_packets++;
libertas_upload_rx_packet(priv, skb);
ret = 0;
-done:
- LEAVE();
- return (ret);
+done:
+ skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */
+ lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
+ return ret;
}
diff --git a/drivers/net/wireless/libertas/sbi.h b/drivers/net/wireless/libertas/sbi.h
deleted file mode 100644
index 59d3a59ccef..00000000000
--- a/drivers/net/wireless/libertas/sbi.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * This file contains IF layer definitions.
- */
-
-#ifndef _SBI_H_
-#define _SBI_H_
-
-#include <linux/interrupt.h>
-
-#include "defs.h"
-
-/** INT status Bit Definition*/
-#define his_cmddnldrdy 0x01
-#define his_cardevent 0x02
-#define his_cmdupldrdy 0x04
-
-#ifndef DEV_NAME_LEN
-#define DEV_NAME_LEN 32
-#endif
-
-#define SBI_EVENT_CAUSE_SHIFT 3
-
-/* Probe and Check if the card is present*/
-int libertas_sbi_register_dev(wlan_private * priv);
-int libertas_sbi_unregister_dev(wlan_private *);
-int libertas_sbi_get_int_status(wlan_private * priv, u8 *);
-int libertas_sbi_register(void);
-void libertas_sbi_unregister(void);
-int libertas_sbi_prog_firmware(wlan_private *);
-
-int libertas_sbi_read_event_cause(wlan_private *);
-int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
-wlan_private *libertas_sbi_get_priv(void *card);
-
-#ifdef ENABLE_PM
-int libertas_sbi_suspend(wlan_private *);
-int libertas_sbi_resume(wlan_private *);
-#endif
-
-#endif /* _SBI_H */
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 3c0b1a2a172..c3043dcb541 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -8,6 +8,7 @@
#include <linux/if.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
+#include <linux/etherdevice.h>
#include <net/ieee80211.h>
#include <net/iw_handler.h>
@@ -58,12 +59,82 @@
//! Scan time specified in the channel TLV for each channel for active scans
#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
-//! Macro to enable/disable SSID checking before storing a scan table
-#ifdef DISCARD_BAD_SSID
-#define CHECK_SSID_IS_VALID(x) ssid_valid(&bssidEntry.ssid)
-#else
-#define CHECK_SSID_IS_VALID(x) 1
-#endif
+static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+static inline void clear_bss_descriptor (struct bss_descriptor * bss)
+{
+ /* Don't blow away ->list, just BSS data */
+ memset(bss, 0, offsetof(struct bss_descriptor, list));
+}
+
+static inline int match_bss_no_security(struct wlan_802_11_security * secinfo,
+ struct bss_descriptor * match_bss)
+{
+ if ( !secinfo->wep_enabled
+ && !secinfo->WPAenabled
+ && !secinfo->WPA2enabled
+ && match_bss->wpa_ie[0] != WPA_IE
+ && match_bss->rsn_ie[0] != WPA2_IE
+ && !match_bss->privacy) {
+ return 1;
+ }
+ return 0;
+}
+
+static inline int match_bss_static_wep(struct wlan_802_11_security * secinfo,
+ struct bss_descriptor * match_bss)
+{
+ if ( secinfo->wep_enabled
+ && !secinfo->WPAenabled
+ && !secinfo->WPA2enabled
+ && match_bss->privacy) {
+ return 1;
+ }
+ return 0;
+}
+
+static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
+ struct bss_descriptor * match_bss)
+{
+ if ( !secinfo->wep_enabled
+ && secinfo->WPAenabled
+ && (match_bss->wpa_ie[0] == WPA_IE)
+ /* privacy bit may NOT be set in some APs like LinkSys WRT54G
+ && bss->privacy */
+ ) {
+ return 1;
+ }
+ return 0;
+}
+
+static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
+ struct bss_descriptor * match_bss)
+{
+ if ( !secinfo->wep_enabled
+ && secinfo->WPA2enabled
+ && (match_bss->rsn_ie[0] == WPA2_IE)
+ /* privacy bit may NOT be set in some APs like LinkSys WRT54G
+ && bss->privacy */
+ ) {
+ return 1;
+ }
+ return 0;
+}
+
+static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,
+ struct bss_descriptor * match_bss)
+{
+ if ( !secinfo->wep_enabled
+ && !secinfo->WPAenabled
+ && !secinfo->WPA2enabled
+ && (match_bss->wpa_ie[0] != WPA_IE)
+ && (match_bss->rsn_ie[0] != WPA2_IE)
+ && match_bss->privacy) {
+ return 1;
+ }
+ return 0;
+}
/**
* @brief Check if a scanned network compatible with the driver settings
@@ -84,180 +155,63 @@
*
* @return Index in scantable, or error code if negative
*/
-static int is_network_compatible(wlan_adapter * adapter, int index, u8 mode)
+static int is_network_compatible(wlan_adapter * adapter,
+ struct bss_descriptor * bss, u8 mode)
{
- ENTER();
-
- if (adapter->scantable[index].mode == mode) {
- if ( !adapter->secinfo.wep_enabled
- && !adapter->secinfo.WPAenabled
- && !adapter->secinfo.WPA2enabled
- && adapter->scantable[index].wpa_ie[0] != WPA_IE
- && adapter->scantable[index].rsn_ie[0] != WPA2_IE
- && !adapter->scantable[index].privacy) {
- /* no security */
- LEAVE();
- return index;
- } else if ( adapter->secinfo.wep_enabled
- && !adapter->secinfo.WPAenabled
- && !adapter->secinfo.WPA2enabled
- && adapter->scantable[index].privacy) {
- /* static WEP enabled */
- LEAVE();
- return index;
- } else if ( !adapter->secinfo.wep_enabled
- && adapter->secinfo.WPAenabled
- && !adapter->secinfo.WPA2enabled
- && (adapter->scantable[index].wpa_ie[0] == WPA_IE)
- /* privacy bit may NOT be set in some APs like LinkSys WRT54G
- && adapter->scantable[index].privacy */
- ) {
- /* WPA enabled */
- lbs_pr_debug(1,
- "is_network_compatible() WPA: index=%d wpa_ie=%#x "
- "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
- "privacy=%#x\n", index,
- adapter->scantable[index].wpa_ie[0],
- adapter->scantable[index].rsn_ie[0],
- adapter->secinfo.wep_enabled ? "e" : "d",
- adapter->secinfo.WPAenabled ? "e" : "d",
- adapter->secinfo.WPA2enabled ? "e" : "d",
- adapter->scantable[index].privacy);
- LEAVE();
- return index;
- } else if ( !adapter->secinfo.wep_enabled
- && !adapter->secinfo.WPAenabled
- && adapter->secinfo.WPA2enabled
- && (adapter->scantable[index].rsn_ie[0] == WPA2_IE)
- /* privacy bit may NOT be set in some APs like LinkSys WRT54G
- && adapter->scantable[index].privacy */
- ) {
- /* WPA2 enabled */
- lbs_pr_debug(1,
- "is_network_compatible() WPA2: index=%d wpa_ie=%#x "
- "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
- "privacy=%#x\n", index,
- adapter->scantable[index].wpa_ie[0],
- adapter->scantable[index].rsn_ie[0],
- adapter->secinfo.wep_enabled ? "e" : "d",
- adapter->secinfo.WPAenabled ? "e" : "d",
- adapter->secinfo.WPA2enabled ? "e" : "d",
- adapter->scantable[index].privacy);
- LEAVE();
- return index;
- } else if ( !adapter->secinfo.wep_enabled
- && !adapter->secinfo.WPAenabled
- && !adapter->secinfo.WPA2enabled
- && (adapter->scantable[index].wpa_ie[0] != WPA_IE)
- && (adapter->scantable[index].rsn_ie[0] != WPA2_IE)
- && adapter->scantable[index].privacy) {
- /* dynamic WEP enabled */
- lbs_pr_debug(1,
- "is_network_compatible() dynamic WEP: index=%d "
- "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n",
- index,
- adapter->scantable[index].wpa_ie[0],
- adapter->scantable[index].rsn_ie[0],
- adapter->scantable[index].privacy);
- LEAVE();
- return index;
- }
-
- /* security doesn't match */
- lbs_pr_debug(1,
- "is_network_compatible() FAILED: index=%d wpa_ie=%#x "
- "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n",
- index,
- adapter->scantable[index].wpa_ie[0],
- adapter->scantable[index].rsn_ie[0],
+ int matched = 0;
+
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
+ if (bss->mode != mode)
+ goto done;
+
+ if ((matched = match_bss_no_security(&adapter->secinfo, bss))) {
+ goto done;
+ } else if ((matched = match_bss_static_wep(&adapter->secinfo, bss))) {
+ goto done;
+ } else if ((matched = match_bss_wpa(&adapter->secinfo, bss))) {
+ lbs_deb_scan(
+ "is_network_compatible() WPA: wpa_ie=%#x "
+ "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
+ "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0],
adapter->secinfo.wep_enabled ? "e" : "d",
adapter->secinfo.WPAenabled ? "e" : "d",
adapter->secinfo.WPA2enabled ? "e" : "d",
- adapter->scantable[index].privacy);
- LEAVE();
- return -ECONNREFUSED;
- }
-
- /* mode doesn't match */
- LEAVE();
- return -ENETUNREACH;
-}
-
-/**
- * @brief This function validates a SSID as being able to be printed
- *
- * @param pssid SSID structure to validate
- *
- * @return TRUE or FALSE
- */
-static u8 ssid_valid(struct WLAN_802_11_SSID *pssid)
-{
- int ssididx;
-
- for (ssididx = 0; ssididx < pssid->ssidlength; ssididx++) {
- if (!isprint(pssid->ssid[ssididx])) {
- return 0;
- }
- }
-
- return 1;
-}
-
-/**
- * @brief Post process the scan table after a new scan command has completed
- *
- * Inspect each entry of the scan table and try to find an entry that
- * matches our current associated/joined network from the scan. If
- * one is found, update the stored copy of the bssdescriptor for our
- * current network.
- *
- * Debug dump the current scan table contents if compiled accordingly.
- *
- * @param priv A pointer to wlan_private structure
- *
- * @return void
- */
-static void wlan_scan_process_results(wlan_private * priv)
-{
- wlan_adapter *adapter = priv->adapter;
- int foundcurrent;
- int i;
-
- foundcurrent = 0;
-
- if (adapter->connect_status == libertas_connected) {
- /* try to find the current BSSID in the new scan list */
- for (i = 0; i < adapter->numinscantable; i++) {
- if (!libertas_SSID_cmp(&adapter->scantable[i].ssid,
- &adapter->curbssparams.ssid) &&
- !memcmp(adapter->curbssparams.bssid,
- adapter->scantable[i].macaddress,
- ETH_ALEN)) {
- foundcurrent = 1;
- }
- }
-
- if (foundcurrent) {
- /* Make a copy of current BSSID descriptor */
- memcpy(&adapter->curbssparams.bssdescriptor,
- &adapter->scantable[i],
- sizeof(adapter->curbssparams.bssdescriptor));
- }
+ bss->privacy);
+ goto done;
+ } else if ((matched = match_bss_wpa2(&adapter->secinfo, bss))) {
+ lbs_deb_scan(
+ "is_network_compatible() WPA2: wpa_ie=%#x "
+ "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
+ "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0],
+ adapter->secinfo.wep_enabled ? "e" : "d",
+ adapter->secinfo.WPAenabled ? "e" : "d",
+ adapter->secinfo.WPA2enabled ? "e" : "d",
+ bss->privacy);
+ goto done;
+ } else if ((matched = match_bss_dynamic_wep(&adapter->secinfo, bss))) {
+ lbs_deb_scan(
+ "is_network_compatible() dynamic WEP: "
+ "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n",
+ bss->wpa_ie[0],
+ bss->rsn_ie[0],
+ bss->privacy);
+ goto done;
}
- for (i = 0; i < adapter->numinscantable; i++) {
- lbs_pr_debug(1, "Scan:(%02d) %02x:%02x:%02x:%02x:%02x:%02x, "
- "RSSI[%03d], SSID[%s]\n",
- i,
- adapter->scantable[i].macaddress[0],
- adapter->scantable[i].macaddress[1],
- adapter->scantable[i].macaddress[2],
- adapter->scantable[i].macaddress[3],
- adapter->scantable[i].macaddress[4],
- adapter->scantable[i].macaddress[5],
- (s32) adapter->scantable[i].rssi,
- adapter->scantable[i].ssid.ssid);
- }
+ /* bss security settings don't match those configured on card */
+ lbs_deb_scan(
+ "is_network_compatible() FAILED: wpa_ie=%#x "
+ "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n",
+ bss->wpa_ie[0], bss->rsn_ie[0],
+ adapter->secinfo.wep_enabled ? "e" : "d",
+ adapter->secinfo.WPAenabled ? "e" : "d",
+ adapter->secinfo.WPA2enabled ? "e" : "d",
+ bss->privacy);
+
+done:
+ lbs_deb_leave(LBS_DEB_SCAN);
+ return matched;
}
/**
@@ -338,14 +292,12 @@ static void wlan_scan_create_channel_list(wlan_private * priv,
if (scantype == cmd_scan_type_passive) {
scanchanlist[chanidx].maxscantime =
- cpu_to_le16
- (MRVDRV_PASSIVE_SCAN_CHAN_TIME);
+ cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
scanchanlist[chanidx].chanscanmode.passivescan =
1;
} else {
scanchanlist[chanidx].maxscantime =
- cpu_to_le16
- (MRVDRV_ACTIVE_SCAN_CHAN_TIME);
+ cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
scanchanlist[chanidx].chanscanmode.passivescan =
0;
}
@@ -408,13 +360,11 @@ wlan_scan_setup_scan_config(wlan_private * priv,
u8 * pscancurrentonly)
{
wlan_adapter *adapter = priv->adapter;
- const u8 zeromac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
struct mrvlietypes_numprobes *pnumprobestlv;
struct mrvlietypes_ssidparamset *pssidtlv;
struct wlan_scan_cmd_config * pscancfgout = NULL;
u8 *ptlvpos;
u16 numprobes;
- u16 ssidlen;
int chanidx;
int scantype;
int scandur;
@@ -471,21 +421,18 @@ wlan_scan_setup_scan_config(wlan_private * priv,
* Set the BSSID filter to the incoming configuration,
* if non-zero. If not set, it will remain disabled (all zeros).
*/
- memcpy(pscancfgout->specificBSSID,
- puserscanin->specificBSSID,
- sizeof(pscancfgout->specificBSSID));
-
- ssidlen = strlen(puserscanin->specificSSID);
+ memcpy(pscancfgout->bssid, puserscanin->bssid,
+ sizeof(pscancfgout->bssid));
- if (ssidlen) {
+ if (puserscanin->ssid_len) {
pssidtlv =
(struct mrvlietypes_ssidparamset *) pscancfgout->
tlvbuffer;
pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
- pssidtlv->header.len = cpu_to_le16(ssidlen);
- memcpy(pssidtlv->ssid, puserscanin->specificSSID,
- ssidlen);
- ptlvpos += sizeof(pssidtlv->header) + ssidlen;
+ pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len);
+ memcpy(pssidtlv->ssid, puserscanin->ssid,
+ puserscanin->ssid_len);
+ ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len;
}
/*
@@ -494,8 +441,8 @@ wlan_scan_setup_scan_config(wlan_private * priv,
* scan results. That is not an issue with an SSID or BSSID
* filter applied to the scan results in the firmware.
*/
- if (ssidlen || (memcmp(pscancfgout->specificBSSID,
- &zeromac, sizeof(zeromac)) != 0)) {
+ if ( puserscanin->ssid_len
+ || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) {
*pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN;
*pfilteredscan = 1;
}
@@ -507,16 +454,11 @@ wlan_scan_setup_scan_config(wlan_private * priv,
/* If the input config or adapter has the number of Probes set, add tlv */
if (numprobes) {
pnumprobestlv = (struct mrvlietypes_numprobes *) ptlvpos;
- pnumprobestlv->header.type =
- cpu_to_le16(TLV_TYPE_NUMPROBES);
- pnumprobestlv->header.len = sizeof(pnumprobestlv->numprobes);
+ pnumprobestlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
+ pnumprobestlv->header.len = cpu_to_le16(2);
pnumprobestlv->numprobes = cpu_to_le16(numprobes);
- ptlvpos +=
- sizeof(pnumprobestlv->header) + pnumprobestlv->header.len;
-
- pnumprobestlv->header.len =
- cpu_to_le16(pnumprobestlv->header.len);
+ ptlvpos += sizeof(*pnumprobestlv);
}
/*
@@ -529,7 +471,7 @@ wlan_scan_setup_scan_config(wlan_private * priv,
if (puserscanin && puserscanin->chanlist[0].channumber) {
- lbs_pr_debug(1, "Scan: Using supplied channel list\n");
+ lbs_deb_scan("Scan: Using supplied channel list\n");
for (chanidx = 0;
chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX
@@ -573,11 +515,11 @@ wlan_scan_setup_scan_config(wlan_private * priv,
==
priv->adapter->curbssparams.channel)) {
*pscancurrentonly = 1;
- lbs_pr_debug(1, "Scan: Scanning current channel only");
+ lbs_deb_scan("Scan: Scanning current channel only");
}
} else {
- lbs_pr_debug(1, "Scan: Creating full region channel list\n");
+ lbs_deb_scan("Scan: Creating full region channel list\n");
wlan_scan_create_channel_list(priv, pscanchanlist,
*pfilteredscan);
}
@@ -613,7 +555,9 @@ static int wlan_scan_channel_list(wlan_private * priv,
u8 filteredscan,
struct wlan_scan_cmd_config * pscancfgout,
struct mrvlietypes_chanlistparamset * pchantlvout,
- struct chanscanparamset * pscanchanlist)
+ struct chanscanparamset * pscanchanlist,
+ const struct wlan_ioctl_user_scan_cfg * puserscanin,
+ int full_scan)
{
struct chanscanparamset *ptmpchan;
struct chanscanparamset *pstartchan;
@@ -621,11 +565,13 @@ static int wlan_scan_channel_list(wlan_private * priv,
int doneearly;
int tlvidx;
int ret = 0;
+ int scanned = 0;
+ union iwreq_data wrqu;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
if (pscancfgout == 0 || pchantlvout == 0 || pscanchanlist == 0) {
- lbs_pr_debug(1, "Scan: Null detect: %p, %p, %p\n",
+ lbs_deb_scan("Scan: Null detect: %p, %p, %p\n",
pscancfgout, pchantlvout, pscanchanlist);
return -1;
}
@@ -635,6 +581,9 @@ static int wlan_scan_channel_list(wlan_private * priv,
/* Set the temp channel struct pointer to the start of the desired list */
ptmpchan = pscanchanlist;
+ if (priv->adapter->last_scanned_channel && !puserscanin)
+ ptmpchan += priv->adapter->last_scanned_channel;
+
/* Loop through the desired channel list, sending a new firmware scan
* commands for each maxchanperscan channels (or for 1,6,11 individually
* if configured accordingly)
@@ -654,9 +603,9 @@ static int wlan_scan_channel_list(wlan_private * priv,
* - doneearly is set (controlling individual scanning of 1,6,11)
*/
while (tlvidx < maxchanperscan && ptmpchan->channumber
- && !doneearly) {
+ && !doneearly && scanned < 2) {
- lbs_pr_debug(1,
+ lbs_deb_scan(
"Scan: Chan(%3d), Radio(%d), mode(%d,%d), Dur(%d)\n",
ptmpchan->channumber, ptmpchan->radiotype,
ptmpchan->chanscanmode.passivescan,
@@ -668,8 +617,11 @@ static int wlan_scan_channel_list(wlan_private * priv,
ptmpchan, sizeof(pchantlvout->chanscanparam));
/* Increment the TLV header length by the size appended */
- pchantlvout->header.len +=
- sizeof(pchantlvout->chanscanparam);
+ /* Ew, it would be _so_ nice if we could just declare the
+ variable little-endian and let GCC handle it for us */
+ pchantlvout->header.len =
+ cpu_to_le16(le16_to_cpu(pchantlvout->header.len) +
+ sizeof(pchantlvout->chanscanparam));
/*
* The tlv buffer length is set to the number of bytes of the
@@ -683,7 +635,7 @@ static int wlan_scan_channel_list(wlan_private * priv,
/* Add the size of the channel tlv header and the data length */
pscancfgout->tlvbufferlen +=
(sizeof(pchantlvout->header)
- + pchantlvout->header.len);
+ + le16_to_cpu(pchantlvout->header.len));
/* Increment the index to the channel tlv we are constructing */
tlvidx++;
@@ -701,6 +653,7 @@ static int wlan_scan_channel_list(wlan_private * priv,
/* Increment the tmp pointer to the next channel to be scanned */
ptmpchan++;
+ scanned++;
/* Stop the loop if the *next* channel is in the 1,6,11 set.
* This will cause it to be the only channel scanned on the next
@@ -716,12 +669,71 @@ static int wlan_scan_channel_list(wlan_private * priv,
/* Send the scan command to the firmware with the specified cfg */
ret = libertas_prepare_and_send_command(priv, cmd_802_11_scan, 0,
0, 0, pscancfgout);
+ if (scanned >= 2 && !full_scan) {
+ ret = 0;
+ goto done;
+ }
+ scanned = 0;
}
- LEAVE();
+done:
+ priv->adapter->last_scanned_channel = ptmpchan->channumber;
+
+ /* Tell userspace the scan table has been updated */
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+
+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
return ret;
}
+static void
+clear_selected_scan_list_entries(wlan_adapter * adapter,
+ const struct wlan_ioctl_user_scan_cfg * scan_cfg)
+{
+ struct bss_descriptor * bss;
+ struct bss_descriptor * safe;
+ u32 clear_ssid_flag = 0, clear_bssid_flag = 0;
+
+ if (!scan_cfg)
+ return;
+
+ if (scan_cfg->clear_ssid && scan_cfg->ssid_len)
+ clear_ssid_flag = 1;
+
+ if (scan_cfg->clear_bssid
+ && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0)
+ && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) {
+ clear_bssid_flag = 1;
+ }
+
+ if (!clear_ssid_flag && !clear_bssid_flag)
+ return;
+
+ mutex_lock(&adapter->lock);
+ list_for_each_entry_safe (bss, safe, &adapter->network_list, list) {
+ u32 clear = 0;
+
+ /* Check for an SSID match */
+ if ( clear_ssid_flag
+ && (bss->ssid_len == scan_cfg->ssid_len)
+ && !memcmp(bss->ssid, scan_cfg->ssid, bss->ssid_len))
+ clear = 1;
+
+ /* Check for a BSSID match */
+ if ( clear_bssid_flag
+ && !compare_ether_addr(bss->bssid, scan_cfg->bssid))
+ clear = 1;
+
+ if (clear) {
+ list_move_tail (&bss->list, &adapter->network_free_list);
+ clear_bss_descriptor(bss);
+ }
+ }
+ mutex_unlock(&adapter->lock);
+}
+
+
/**
* @brief Internal function used to start a scan based on an input config
*
@@ -736,19 +748,23 @@ static int wlan_scan_channel_list(wlan_private * priv,
* @return 0 or < 0 if error
*/
int wlan_scan_networks(wlan_private * priv,
- const struct wlan_ioctl_user_scan_cfg * puserscanin)
+ const struct wlan_ioctl_user_scan_cfg * puserscanin,
+ int full_scan)
{
- wlan_adapter *adapter = priv->adapter;
+ wlan_adapter * adapter = priv->adapter;
struct mrvlietypes_chanlistparamset *pchantlvout;
struct chanscanparamset * scan_chan_list = NULL;
struct wlan_scan_cmd_config * scan_cfg = NULL;
- u8 keeppreviousscan;
u8 filteredscan;
u8 scancurrentchanonly;
int maxchanperscan;
int ret;
+#ifdef CONFIG_LIBERTAS_DEBUG
+ struct bss_descriptor * iter_bss;
+ int i = 0;
+#endif
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
scan_chan_list = kzalloc(sizeof(struct chanscanparamset) *
WLAN_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
@@ -769,22 +785,14 @@ int wlan_scan_networks(wlan_private * priv,
goto out;
}
- keeppreviousscan = 0;
-
- if (puserscanin) {
- keeppreviousscan = puserscanin->keeppreviousscan;
- }
-
- if (!keeppreviousscan) {
- memset(adapter->scantable, 0x00,
- sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST);
- adapter->numinscantable = 0;
- }
+ clear_selected_scan_list_entries(adapter, puserscanin);
/* Keep the data path active if we are only scanning our current channel */
if (!scancurrentchanonly) {
- netif_stop_queue(priv->wlan_dev.netdev);
- netif_carrier_off(priv->wlan_dev.netdev);
+ netif_stop_queue(priv->dev);
+ netif_carrier_off(priv->dev);
+ netif_stop_queue(priv->mesh_dev);
+ netif_carrier_off(priv->mesh_dev);
}
ret = wlan_scan_channel_list(priv,
@@ -792,17 +800,26 @@ int wlan_scan_networks(wlan_private * priv,
filteredscan,
scan_cfg,
pchantlvout,
- scan_chan_list);
-
- /* Process the resulting scan table:
- * - Remove any bad ssids
- * - Update our current BSS information from scan data
- */
- wlan_scan_process_results(priv);
+ scan_chan_list,
+ puserscanin,
+ full_scan);
+
+#ifdef CONFIG_LIBERTAS_DEBUG
+ /* Dump the scan table */
+ mutex_lock(&adapter->lock);
+ list_for_each_entry (iter_bss, &adapter->network_list, list) {
+ lbs_deb_scan("Scan:(%02d) " MAC_FMT ", RSSI[%03d], SSID[%s]\n",
+ i++, MAC_ARG(iter_bss->bssid), (s32) iter_bss->rssi,
+ escape_essid(iter_bss->ssid, iter_bss->ssid_len));
+ }
+ mutex_unlock(&adapter->lock);
+#endif
if (priv->adapter->connect_status == libertas_connected) {
- netif_carrier_on(priv->wlan_dev.netdev);
- netif_wake_queue(priv->wlan_dev.netdev);
+ netif_carrier_on(priv->dev);
+ netif_wake_queue(priv->dev);
+ netif_carrier_on(priv->mesh_dev);
+ netif_wake_queue(priv->mesh_dev);
}
out:
@@ -812,7 +829,7 @@ out:
if (scan_chan_list)
kfree(scan_chan_list);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
return ret;
}
@@ -843,7 +860,7 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv,
tlvbufleft = tlvbufsize;
*ptsftlv = NULL;
- lbs_pr_debug(1, "SCAN_RESP: tlvbufsize = %d\n", tlvbufsize);
+ lbs_deb_scan("SCAN_RESP: tlvbufsize = %d\n", tlvbufsize);
lbs_dbg_hex("SCAN_RESP: TLV Buf", (u8 *) ptlv, tlvbufsize);
while (tlvbufleft >= sizeof(struct mrvlietypesheader)) {
@@ -856,7 +873,7 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv,
break;
default:
- lbs_pr_debug(1, "SCAN_RESP: Unhandled TLV = %d\n",
+ lbs_deb_scan("SCAN_RESP: Unhandled TLV = %d\n",
tlvtype);
/* Give up, this seems corrupted */
return;
@@ -875,12 +892,12 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv,
* response or beacon from the scan command. Record information as needed
* in the scan table struct bss_descriptor for that entry.
*
- * @param pBSSIDEntry Output parameter: Pointer to the BSS Entry
+ * @param bss Output parameter: Pointer to the BSS Entry
*
* @return 0 or -1
*/
-static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
- u8 ** pbeaconinfo, int *bytesleft)
+static int libertas_process_bss(struct bss_descriptor * bss,
+ u8 ** pbeaconinfo, int *bytesleft)
{
enum ieeetypes_elementid elemID;
struct ieeetypes_fhparamset *pFH;
@@ -897,13 +914,14 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
u16 beaconsize;
u8 founddatarateie;
int bytesleftforcurrentbeacon;
+ int ret;
struct IE_WPA *pIe;
const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 };
struct ieeetypes_countryinfoset *pcountryinfo;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
founddatarateie = 0;
ratesize = 0;
@@ -911,8 +929,7 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
if (*bytesleft >= sizeof(beaconsize)) {
/* Extract & convert beacon size from the command buffer */
- memcpy(&beaconsize, *pbeaconinfo, sizeof(beaconsize));
- beaconsize = le16_to_cpu(beaconsize);
+ beaconsize = le16_to_cpup((void *)*pbeaconinfo);
*bytesleft -= sizeof(beaconsize);
*pbeaconinfo += sizeof(beaconsize);
}
@@ -934,17 +951,14 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
bytesleftforcurrentbeacon = beaconsize;
- memcpy(pBSSEntry->macaddress, pcurrentptr, ETH_ALEN);
- lbs_pr_debug(1, "InterpretIE: AP MAC Addr-%x:%x:%x:%x:%x:%x\n",
- pBSSEntry->macaddress[0], pBSSEntry->macaddress[1],
- pBSSEntry->macaddress[2], pBSSEntry->macaddress[3],
- pBSSEntry->macaddress[4], pBSSEntry->macaddress[5]);
+ memcpy(bss->bssid, pcurrentptr, ETH_ALEN);
+ lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid));
pcurrentptr += ETH_ALEN;
bytesleftforcurrentbeacon -= ETH_ALEN;
if (bytesleftforcurrentbeacon < 12) {
- lbs_pr_debug(1, "InterpretIE: Not enough bytes left\n");
+ lbs_deb_scan("process_bss: Not enough bytes left\n");
return -1;
}
@@ -954,51 +968,48 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
*/
/* RSSI is 1 byte long */
- pBSSEntry->rssi = le32_to_cpu((long)(*pcurrentptr));
- lbs_pr_debug(1, "InterpretIE: RSSI=%02X\n", *pcurrentptr);
+ bss->rssi = *pcurrentptr;
+ lbs_deb_scan("process_bss: RSSI=%02X\n", *pcurrentptr);
pcurrentptr += 1;
bytesleftforcurrentbeacon -= 1;
/* time stamp is 8 bytes long */
- memcpy(fixedie.timestamp, pcurrentptr, 8);
- memcpy(pBSSEntry->timestamp, pcurrentptr, 8);
+ fixedie.timestamp = bss->timestamp = le64_to_cpup((void *)pcurrentptr);
pcurrentptr += 8;
bytesleftforcurrentbeacon -= 8;
/* beacon interval is 2 bytes long */
- memcpy(&fixedie.beaconinterval, pcurrentptr, 2);
- pBSSEntry->beaconperiod = le16_to_cpu(fixedie.beaconinterval);
+ fixedie.beaconinterval = bss->beaconperiod = le16_to_cpup((void *)pcurrentptr);
pcurrentptr += 2;
bytesleftforcurrentbeacon -= 2;
/* capability information is 2 bytes long */
- memcpy(&fixedie.capabilities, pcurrentptr, 2);
- lbs_pr_debug(1, "InterpretIE: fixedie.capabilities=0x%X\n",
+ memcpy(&fixedie.capabilities, pcurrentptr, 2);
+ lbs_deb_scan("process_bss: fixedie.capabilities=0x%X\n",
fixedie.capabilities);
- fixedie.capabilities = le16_to_cpu(fixedie.capabilities);
pcap = (struct ieeetypes_capinfo *) & fixedie.capabilities;
- memcpy(&pBSSEntry->cap, pcap, sizeof(struct ieeetypes_capinfo));
+ memcpy(&bss->cap, pcap, sizeof(struct ieeetypes_capinfo));
pcurrentptr += 2;
bytesleftforcurrentbeacon -= 2;
/* rest of the current buffer are IE's */
- lbs_pr_debug(1, "InterpretIE: IElength for this AP = %d\n",
+ lbs_deb_scan("process_bss: IE length for this AP = %d\n",
bytesleftforcurrentbeacon);
- lbs_dbg_hex("InterpretIE: IE info", (u8 *) pcurrentptr,
+ lbs_dbg_hex("process_bss: IE info", (u8 *) pcurrentptr,
bytesleftforcurrentbeacon);
if (pcap->privacy) {
- lbs_pr_debug(1, "InterpretIE: AP WEP enabled\n");
- pBSSEntry->privacy = wlan802_11privfilter8021xWEP;
+ lbs_deb_scan("process_bss: AP WEP enabled\n");
+ bss->privacy = wlan802_11privfilter8021xWEP;
} else {
- pBSSEntry->privacy = wlan802_11privfilteracceptall;
+ bss->privacy = wlan802_11privfilteracceptall;
}
if (pcap->ibss == 1) {
- pBSSEntry->mode = IW_MODE_ADHOC;
+ bss->mode = IW_MODE_ADHOC;
} else {
- pBSSEntry->mode = IW_MODE_INFRA;
+ bss->mode = IW_MODE_INFRA;
}
/* process variable IE */
@@ -1007,94 +1018,83 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
elemlen = *((u8 *) pcurrentptr + 1);
if (bytesleftforcurrentbeacon < elemlen) {
- lbs_pr_debug(1, "InterpretIE: error in processing IE, "
+ lbs_deb_scan("process_bss: error in processing IE, "
"bytes left < IE length\n");
bytesleftforcurrentbeacon = 0;
continue;
}
switch (elemID) {
-
case SSID:
- pBSSEntry->ssid.ssidlength = elemlen;
- memcpy(pBSSEntry->ssid.ssid, (pcurrentptr + 2),
- elemlen);
- lbs_pr_debug(1, "ssid: %32s", pBSSEntry->ssid.ssid);
+ bss->ssid_len = elemlen;
+ memcpy(bss->ssid, (pcurrentptr + 2), elemlen);
+ lbs_deb_scan("ssid '%s', ssid length %u\n",
+ escape_essid(bss->ssid, bss->ssid_len),
+ bss->ssid_len);
break;
case SUPPORTED_RATES:
- memcpy(pBSSEntry->datarates, (pcurrentptr + 2),
- elemlen);
- memmove(pBSSEntry->libertas_supported_rates, (pcurrentptr + 2),
+ memcpy(bss->datarates, (pcurrentptr + 2), elemlen);
+ memmove(bss->libertas_supported_rates, (pcurrentptr + 2),
elemlen);
ratesize = elemlen;
founddatarateie = 1;
break;
case EXTRA_IE:
- lbs_pr_debug(1, "InterpretIE: EXTRA_IE Found!\n");
- pBSSEntry->extra_ie = 1;
+ lbs_deb_scan("process_bss: EXTRA_IE Found!\n");
break;
case FH_PARAM_SET:
pFH = (struct ieeetypes_fhparamset *) pcurrentptr;
- memmove(&pBSSEntry->phyparamset.fhparamset, pFH,
+ memmove(&bss->phyparamset.fhparamset, pFH,
sizeof(struct ieeetypes_fhparamset));
- pBSSEntry->phyparamset.fhparamset.dwelltime
- =
- le16_to_cpu(pBSSEntry->phyparamset.fhparamset.
- dwelltime);
+#if 0 /* I think we can store these LE */
+ bss->phyparamset.fhparamset.dwelltime
+ = le16_to_cpu(bss->phyparamset.fhparamset.dwelltime);
+#endif
break;
case DS_PARAM_SET:
pDS = (struct ieeetypes_dsparamset *) pcurrentptr;
-
- pBSSEntry->channel = pDS->currentchan;
-
- memcpy(&pBSSEntry->phyparamset.dsparamset, pDS,
+ bss->channel = pDS->currentchan;
+ memcpy(&bss->phyparamset.dsparamset, pDS,
sizeof(struct ieeetypes_dsparamset));
break;
case CF_PARAM_SET:
pCF = (struct ieeetypes_cfparamset *) pcurrentptr;
-
- memcpy(&pBSSEntry->ssparamset.cfparamset, pCF,
+ memcpy(&bss->ssparamset.cfparamset, pCF,
sizeof(struct ieeetypes_cfparamset));
break;
case IBSS_PARAM_SET:
pibss = (struct ieeetypes_ibssparamset *) pcurrentptr;
- pBSSEntry->atimwindow =
- le32_to_cpu(pibss->atimwindow);
-
- memmove(&pBSSEntry->ssparamset.ibssparamset, pibss,
+ bss->atimwindow = le32_to_cpu(pibss->atimwindow);
+ memmove(&bss->ssparamset.ibssparamset, pibss,
sizeof(struct ieeetypes_ibssparamset));
-
- pBSSEntry->ssparamset.ibssparamset.atimwindow
- =
- le16_to_cpu(pBSSEntry->ssparamset.ibssparamset.
- atimwindow);
+#if 0
+ bss->ssparamset.ibssparamset.atimwindow
+ = le16_to_cpu(bss->ssparamset.ibssparamset.atimwindow);
+#endif
break;
/* Handle Country Info IE */
case COUNTRY_INFO:
- pcountryinfo =
- (struct ieeetypes_countryinfoset *) pcurrentptr;
-
- if (pcountryinfo->len <
- sizeof(pcountryinfo->countrycode)
+ pcountryinfo = (struct ieeetypes_countryinfoset *) pcurrentptr;
+ if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
|| pcountryinfo->len > 254) {
- lbs_pr_debug(1, "InterpretIE: 11D- Err "
+ lbs_deb_scan("process_bss: 11D- Err "
"CountryInfo len =%d min=%zd max=254\n",
pcountryinfo->len,
sizeof(pcountryinfo->countrycode));
- LEAVE();
- return -1;
+ ret = -1;
+ goto done;
}
- memcpy(&pBSSEntry->countryinfo,
+ memcpy(&bss->countryinfo,
pcountryinfo, pcountryinfo->len + 2);
- lbs_dbg_hex("InterpretIE: 11D- CountryInfo:",
+ lbs_dbg_hex("process_bss: 11D- CountryInfo:",
(u8 *) pcountryinfo,
(u32) (pcountryinfo->len + 2));
break;
@@ -1114,12 +1114,10 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
bytestocopy = elemlen;
}
- pRate = (u8 *) pBSSEntry->datarates;
+ pRate = (u8 *) bss->datarates;
pRate += ratesize;
memmove(pRate, (pcurrentptr + 2), bytestocopy);
-
- pRate = (u8 *) pBSSEntry->libertas_supported_rates;
-
+ pRate = (u8 *) bss->libertas_supported_rates;
pRate += ratesize;
memmove(pRate, (pcurrentptr + 2), bytestocopy);
}
@@ -1132,24 +1130,17 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
if (memcmp(pIe->oui, oui01, sizeof(oui01)))
break;
- pBSSEntry->wpa_ie_len = min_t(size_t,
- elemlen + IE_ID_LEN_FIELDS_BYTES,
- sizeof(pBSSEntry->wpa_ie));
- memcpy(pBSSEntry->wpa_ie, pcurrentptr,
- pBSSEntry->wpa_ie_len);
- lbs_dbg_hex("InterpretIE: Resp WPA_IE",
- pBSSEntry->wpa_ie, elemlen);
+ bss->wpa_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES,
+ MAX_WPA_IE_LEN);
+ memcpy(bss->wpa_ie, pcurrentptr, bss->wpa_ie_len);
+ lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie, elemlen);
break;
case WPA2_IE:
pIe = (struct IE_WPA *)pcurrentptr;
-
- pBSSEntry->rsn_ie_len = min_t(size_t,
- elemlen + IE_ID_LEN_FIELDS_BYTES,
- sizeof(pBSSEntry->rsn_ie));
- memcpy(pBSSEntry->rsn_ie, pcurrentptr,
- pBSSEntry->rsn_ie_len);
- lbs_dbg_hex("InterpretIE: Resp WPA2_IE",
- pBSSEntry->rsn_ie, elemlen);
+ bss->rsn_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES,
+ MAX_WPA_IE_LEN);
+ memcpy(bss->rsn_ie, pcurrentptr, bss->rsn_ie_len);
+ lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elemlen);
break;
case TIM:
break;
@@ -1165,7 +1156,14 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
} /* while (bytesleftforcurrentbeacon > 2) */
- return 0;
+ /* Timestamp */
+ bss->last_scanned = jiffies;
+
+ ret = 0;
+
+done:
+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+ return ret;
}
/**
@@ -1176,15 +1174,12 @@ static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
*
* @return 0--ssid is same, otherwise is different
*/
-int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, struct WLAN_802_11_SSID *ssid2)
+int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
{
- if (!ssid1 || !ssid2)
- return -1;
-
- if (ssid1->ssidlength != ssid2->ssidlength)
+ if (ssid1_len != ssid2_len)
return -1;
- return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssidlength);
+ return memcmp(ssid1, ssid2, ssid1_len);
}
/**
@@ -1196,38 +1191,41 @@ int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, struct WLAN_802_11_SSID *s
*
* @return index in BSSID list, or error return code (< 0)
*/
-int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode)
+struct bss_descriptor * libertas_find_bssid_in_list(wlan_adapter * adapter,
+ u8 * bssid, u8 mode)
{
- int ret = -ENETUNREACH;
- int i;
+ struct bss_descriptor * iter_bss;
+ struct bss_descriptor * found_bss = NULL;
if (!bssid)
- return -EFAULT;
+ return NULL;
- lbs_pr_debug(1, "FindBSSID: Num of BSSIDs = %d\n",
- adapter->numinscantable);
+ lbs_dbg_hex("libertas_find_BSSID_in_list: looking for ",
+ bssid, ETH_ALEN);
- /* Look through the scan table for a compatible match. The ret return
- * variable will be equal to the index in the scan table (greater
- * than zero) if the network is compatible. The loop will continue
- * past a matched bssid that is not compatible in case there is an
- * AP with multiple SSIDs assigned to the same BSSID
+ /* Look through the scan table for a compatible match. The loop will
+ * continue past a matched bssid that is not compatible in case there
+ * is an AP with multiple SSIDs assigned to the same BSSID
*/
- for (i = 0; ret < 0 && i < adapter->numinscantable; i++) {
- if (!memcmp(adapter->scantable[i].macaddress, bssid, ETH_ALEN)) {
- switch (mode) {
- case IW_MODE_INFRA:
- case IW_MODE_ADHOC:
- ret = is_network_compatible(adapter, i, mode);
- break;
- default:
- ret = i;
+ mutex_lock(&adapter->lock);
+ list_for_each_entry (iter_bss, &adapter->network_list, list) {
+ if (compare_ether_addr(iter_bss->bssid, bssid))
+ continue; /* bssid doesn't match */
+ switch (mode) {
+ case IW_MODE_INFRA:
+ case IW_MODE_ADHOC:
+ if (!is_network_compatible(adapter, iter_bss, mode))
break;
- }
+ found_bss = iter_bss;
+ break;
+ default:
+ found_bss = iter_bss;
+ break;
}
}
+ mutex_unlock(&adapter->lock);
- return ret;
+ return found_bss;
}
/**
@@ -1240,61 +1238,60 @@ int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode)
*
* @return index in BSSID list
*/
-int libertas_find_SSID_in_list(wlan_adapter * adapter,
- struct WLAN_802_11_SSID *ssid, u8 * bssid, u8 mode)
+struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
+ u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
+ int channel)
{
- int net = -ENETUNREACH;
u8 bestrssi = 0;
- int i;
- int j;
+ struct bss_descriptor * iter_bss = NULL;
+ struct bss_descriptor * found_bss = NULL;
+ struct bss_descriptor * tmp_oldest = NULL;
- lbs_pr_debug(1, "Num of Entries in Table = %d\n", adapter->numinscantable);
-
- for (i = 0; i < adapter->numinscantable; i++) {
- if (!libertas_SSID_cmp(&adapter->scantable[i].ssid, ssid) &&
- (!bssid ||
- !memcmp(adapter->scantable[i].
- macaddress, bssid, ETH_ALEN))) {
- switch (mode) {
- case IW_MODE_INFRA:
- case IW_MODE_ADHOC:
- j = is_network_compatible(adapter, i, mode);
-
- if (j >= 0) {
- if (bssid) {
- return i;
- }
-
- if (SCAN_RSSI
- (adapter->scantable[i].rssi)
- > bestrssi) {
- bestrssi =
- SCAN_RSSI(adapter->
- scantable[i].
- rssi);
- net = i;
- }
- } else {
- if (net == -ENETUNREACH) {
- net = j;
- }
- }
- break;
- case IW_MODE_AUTO:
- default:
- if (SCAN_RSSI(adapter->scantable[i].rssi)
- > bestrssi) {
- bestrssi =
- SCAN_RSSI(adapter->scantable[i].
- rssi);
- net = i;
- }
+ mutex_lock(&adapter->lock);
+
+ list_for_each_entry (iter_bss, &adapter->network_list, list) {
+ if ( !tmp_oldest
+ || (iter_bss->last_scanned < tmp_oldest->last_scanned))
+ tmp_oldest = iter_bss;
+
+ if (libertas_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
+ ssid, ssid_len) != 0)
+ continue; /* ssid doesn't match */
+ if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
+ continue; /* bssid doesn't match */
+ if ((channel > 0) && (iter_bss->channel != channel))
+ continue; /* channel doesn't match */
+
+ switch (mode) {
+ case IW_MODE_INFRA:
+ case IW_MODE_ADHOC:
+ if (!is_network_compatible(adapter, iter_bss, mode))
break;
+
+ if (bssid) {
+ /* Found requested BSSID */
+ found_bss = iter_bss;
+ goto out;
+ }
+
+ if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
+ bestrssi = SCAN_RSSI(iter_bss->rssi);
+ found_bss = iter_bss;
}
+ break;
+ case IW_MODE_AUTO:
+ default:
+ if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
+ bestrssi = SCAN_RSSI(iter_bss->rssi);
+ found_bss = iter_bss;
+ }
+ break;
}
}
- return net;
+out:
+ mutex_unlock(&adapter->lock);
+ return found_bss;
}
/**
@@ -1307,43 +1304,38 @@ int libertas_find_SSID_in_list(wlan_adapter * adapter,
*
* @return index in BSSID list
*/
-int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode)
+struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter,
+ u8 mode)
{
- int bestnet = -ENETUNREACH;
u8 bestrssi = 0;
- int i;
-
- ENTER();
+ struct bss_descriptor * iter_bss;
+ struct bss_descriptor * best_bss = NULL;
- lbs_pr_debug(1, "Num of BSSIDs = %d\n", adapter->numinscantable);
+ mutex_lock(&adapter->lock);
- for (i = 0; i < adapter->numinscantable; i++) {
+ list_for_each_entry (iter_bss, &adapter->network_list, list) {
switch (mode) {
case IW_MODE_INFRA:
case IW_MODE_ADHOC:
- if (is_network_compatible(adapter, i, mode) >= 0) {
- if (SCAN_RSSI(adapter->scantable[i].rssi) >
- bestrssi) {
- bestrssi =
- SCAN_RSSI(adapter->scantable[i].
- rssi);
- bestnet = i;
- }
- }
+ if (!is_network_compatible(adapter, iter_bss, mode))
+ break;
+ if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
+ break;
+ bestrssi = SCAN_RSSI(iter_bss->rssi);
+ best_bss = iter_bss;
break;
case IW_MODE_AUTO:
default:
- if (SCAN_RSSI(adapter->scantable[i].rssi) > bestrssi) {
- bestrssi =
- SCAN_RSSI(adapter->scantable[i].rssi);
- bestnet = i;
- }
+ if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
+ break;
+ bestrssi = SCAN_RSSI(iter_bss->rssi);
+ best_bss = iter_bss;
break;
}
}
- LEAVE();
- return bestnet;
+ mutex_unlock(&adapter->lock);
+ return best_bss;
}
/**
@@ -1354,41 +1346,30 @@ int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode)
*
* @return 0--success, otherwise--fail
*/
-int libertas_find_best_network_SSID(wlan_private * priv,
- struct WLAN_802_11_SSID *pSSID,
- u8 preferred_mode, u8 *out_mode)
+int libertas_find_best_network_ssid(wlan_private * priv,
+ u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode)
{
wlan_adapter *adapter = priv->adapter;
- int ret = 0;
- struct bss_descriptor *preqbssid;
- int i;
+ int ret = -1;
+ struct bss_descriptor * found;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
- memset(pSSID, 0, sizeof(struct WLAN_802_11_SSID));
-
- wlan_scan_networks(priv, NULL);
+ wlan_scan_networks(priv, NULL, 1);
if (adapter->surpriseremoved)
return -1;
- wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);
- i = libertas_find_best_SSID_in_list(adapter, preferred_mode);
- if (i < 0) {
- ret = -1;
- goto out;
- }
-
- preqbssid = &adapter->scantable[i];
- memcpy(pSSID, &preqbssid->ssid,
- sizeof(struct WLAN_802_11_SSID));
- *out_mode = preqbssid->mode;
+ wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);
- if (!pSSID->ssidlength) {
- ret = -1;
+ found = libertas_find_best_ssid_in_list(adapter, preferred_mode);
+ if (found && (found->ssid_len > 0)) {
+ memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
+ *out_ssid_len = found->ssid_len;
+ *out_mode = found->mode;
+ ret = 0;
}
-out:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
return ret;
}
@@ -1407,20 +1388,15 @@ int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
{
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- union iwreq_data wrqu;
- ENTER();
+ lbs_deb_enter(LBS_DEB_SCAN);
- if (!wlan_scan_networks(priv, NULL)) {
- memset(&wrqu, 0, sizeof(union iwreq_data));
- wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu,
- NULL);
- }
+ wlan_scan_networks(priv, NULL, 0);
if (adapter->surpriseremoved)
return -1;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_SCAN);
return 0;
}
@@ -1433,32 +1409,31 @@ int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
*
* @return 0-success, otherwise fail
*/
-int libertas_send_specific_SSID_scan(wlan_private * priv,
- struct WLAN_802_11_SSID *prequestedssid,
- u8 keeppreviousscan)
+int libertas_send_specific_ssid_scan(wlan_private * priv,
+ u8 *ssid, u8 ssid_len, u8 clear_ssid)
{
wlan_adapter *adapter = priv->adapter;
struct wlan_ioctl_user_scan_cfg scancfg;
+ int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
- if (prequestedssid == NULL) {
- return -1;
- }
+ if (!ssid_len)
+ goto out;
memset(&scancfg, 0x00, sizeof(scancfg));
+ memcpy(scancfg.ssid, ssid, ssid_len);
+ scancfg.ssid_len = ssid_len;
+ scancfg.clear_ssid = clear_ssid;
- memcpy(scancfg.specificSSID, prequestedssid->ssid,
- prequestedssid->ssidlength);
- scancfg.keeppreviousscan = keeppreviousscan;
-
- wlan_scan_networks(priv, &scancfg);
+ wlan_scan_networks(priv, &scancfg, 1);
if (adapter->surpriseremoved)
return -1;
wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave(LBS_DEB_ASSOC);
+ return ret;
}
/**
@@ -1470,304 +1445,235 @@ int libertas_send_specific_SSID_scan(wlan_private * priv,
*
* @return 0-success, otherwise fail
*/
-int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 keeppreviousscan)
+int libertas_send_specific_bssid_scan(wlan_private * priv, u8 * bssid, u8 clear_bssid)
{
struct wlan_ioctl_user_scan_cfg scancfg;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
- if (bssid == NULL) {
- return -1;
- }
+ if (bssid == NULL)
+ goto out;
memset(&scancfg, 0x00, sizeof(scancfg));
- memcpy(scancfg.specificBSSID, bssid, sizeof(scancfg.specificBSSID));
- scancfg.keeppreviousscan = keeppreviousscan;
+ memcpy(scancfg.bssid, bssid, ETH_ALEN);
+ scancfg.clear_bssid = clear_bssid;
- wlan_scan_networks(priv, &scancfg);
+ wlan_scan_networks(priv, &scancfg, 1);
if (priv->adapter->surpriseremoved)
return -1;
wait_event_interruptible(priv->adapter->cmd_pending,
!priv->adapter->nr_cmd_pending);
- LEAVE();
+out:
+ lbs_deb_leave(LBS_DEB_ASSOC);
return 0;
}
-/**
- * @brief Retrieve the scan table entries via wireless tools IOCTL call
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param dwrq A pointer to iw_point structure
- * @param extra A pointer to extra data buf
- *
- * @return 0 --success, otherwise fail
- */
-int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
- struct iw_point *dwrq, char *extra)
+static inline char *libertas_translate_scan(wlan_private *priv,
+ char *start, char *stop,
+ struct bss_descriptor *bss)
{
- wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- int ret = 0;
- char *current_ev = extra;
- char *end_buf = extra + IW_SCAN_MAX_DATA;
struct chan_freq_power *cfp;
- struct bss_descriptor *pscantable;
char *current_val; /* For rates */
struct iw_event iwe; /* Temporary buffer */
- int i;
int j;
- int rate;
#define PERFECT_RSSI ((u8)50)
#define WORST_RSSI ((u8)0)
#define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI))
u8 rssi;
- u8 buf[16 + 256 * 2];
- u8 *ptr;
-
- ENTER();
-
- /*
- * if there's either commands in the queue or one being
- * processed return -EAGAIN for iwlist to retry later.
- */
- if (adapter->nr_cmd_pending)
- return -EAGAIN;
-
- if (adapter->connect_status == libertas_connected)
- lbs_pr_debug(1, "Current ssid: %32s\n",
- adapter->curbssparams.ssid.ssid);
+ cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, bss->channel);
+ if (!cfp) {
+ lbs_deb_scan("Invalid channel number %d\n", bss->channel);
+ return NULL;
+ }
- lbs_pr_debug(1, "Scan: Get: numinscantable = %d\n",
- adapter->numinscantable);
+ /* First entry *MUST* be the AP BSSID */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_ADDR_LEN);
+
+ /* SSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE);
+ start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
+
+ /* Mode */
+ iwe.cmd = SIOCGIWMODE;
+ iwe.u.mode = bss->mode;
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_UINT_LEN);
+
+ /* Frequency */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = (long)cfp->freq * 100000;
+ iwe.u.freq.e = 1;
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_FREQ_LEN);
+
+ /* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
+ iwe.u.qual.level = SCAN_RSSI(bss->rssi);
+
+ rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
+ iwe.u.qual.qual =
+ (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
+ (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
+ (RSSI_DIFF * RSSI_DIFF);
+ if (iwe.u.qual.qual > 100)
+ iwe.u.qual.qual = 100;
+
+ if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+ iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
+ } else {
+ iwe.u.qual.noise =
+ CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+ }
- /* The old API using SIOCGIWAPLIST had a hard limit of IW_MAX_AP.
- * The new API using SIOCGIWSCAN is only limited by buffer size
- * WE-14 -> WE-16 the buffer is limited to IW_SCAN_MAX_DATA bytes
- * which is 4096.
+ /* Locally created ad-hoc BSSs won't have beacons if this is the
+ * only station in the adhoc network; so get signal strength
+ * from receive statistics.
*/
- for (i = 0; i < adapter->numinscantable; i++) {
- if ((current_ev + MAX_SCAN_CELL_SIZE) >= end_buf) {
- lbs_pr_debug(1, "i=%d break out: current_ev=%p end_buf=%p "
- "MAX_SCAN_CELL_SIZE=%zd\n",
- i, current_ev, end_buf, MAX_SCAN_CELL_SIZE);
- break;
- }
-
- pscantable = &adapter->scantable[i];
-
- lbs_pr_debug(1, "i=%d ssid: %32s\n", i, pscantable->ssid.ssid);
-
- cfp =
- libertas_find_cfp_by_band_and_channel(adapter, 0,
- pscantable->channel);
- if (!cfp) {
- lbs_pr_debug(1, "Invalid channel number %d\n",
- pscantable->channel);
- continue;
- }
-
- if (!ssid_valid(&adapter->scantable[i].ssid)) {
- continue;
- }
-
- /* First entry *MUST* be the AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data,
- &adapter->scantable[i].macaddress, ETH_ALEN);
-
- iwe.len = IW_EV_ADDR_LEN;
- current_ev =
- iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
-
- //Add the ESSID
- iwe.u.data.length = adapter->scantable[i].ssid.ssidlength;
-
- if (iwe.u.data.length > 32) {
- iwe.u.data.length = 32;
- }
-
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
- adapter->scantable[i].ssid.
- ssid);
-
- //Add mode
- iwe.cmd = SIOCGIWMODE;
- iwe.u.mode = adapter->scantable[i].mode;
- iwe.len = IW_EV_UINT_LEN;
- current_ev =
- iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
-
- //frequency
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = (long)cfp->freq * 100000;
- iwe.u.freq.e = 1;
- iwe.len = IW_EV_FREQ_LEN;
- current_ev =
- iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
-
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
- iwe.u.qual.level = SCAN_RSSI(adapter->scantable[i].rssi);
-
- rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
- iwe.u.qual.qual =
- (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
- (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
- (RSSI_DIFF * RSSI_DIFF);
- if (iwe.u.qual.qual > 100)
- iwe.u.qual.qual = 100;
- else if (iwe.u.qual.qual < 1)
- iwe.u.qual.qual = 0;
-
- if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
- iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
- } else {
- iwe.u.qual.noise =
- CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
- }
- if ((adapter->mode == IW_MODE_ADHOC) &&
- !libertas_SSID_cmp(&adapter->curbssparams.ssid,
- &adapter->scantable[i].ssid)
- && adapter->adhoccreate) {
- ret = libertas_prepare_and_send_command(priv,
- cmd_802_11_rssi,
- 0,
- cmd_option_waitforrsp,
- 0, NULL);
-
- if (!ret) {
- iwe.u.qual.level =
- CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] /
- AVG_SCALE,
- adapter->NF[TYPE_RXPD][TYPE_AVG] /
- AVG_SCALE);
- }
- }
- iwe.len = IW_EV_QUAL_LEN;
- current_ev =
- iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
-
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (adapter->scantable[i].privacy) {
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
- } else {
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- }
- iwe.u.data.length = 0;
- iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
- adapter->scantable->ssid.
- ssid);
+ if ((adapter->mode == IW_MODE_ADHOC)
+ && adapter->adhoccreate
+ && !libertas_ssid_cmp(adapter->curbssparams.ssid,
+ adapter->curbssparams.ssid_len,
+ bss->ssid, bss->ssid_len)) {
+ int snr, nf;
+ snr = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+ nf = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+ iwe.u.qual.level = CAL_RSSI(snr, nf);
+ }
+ start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
- current_val = current_ev + IW_EV_LCP_LEN;
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (bss->privacy) {
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ } else {
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ }
+ iwe.u.data.length = 0;
+ start = iwe_stream_add_point(start, stop, &iwe, bss->ssid);
- iwe.cmd = SIOCGIWRATE;
+ current_val = start + IW_EV_LCP_LEN;
- iwe.u.bitrate.fixed = 0;
- iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = 0;
+ iwe.cmd = SIOCGIWRATE;
+ iwe.u.bitrate.fixed = 0;
+ iwe.u.bitrate.disabled = 0;
+ iwe.u.bitrate.value = 0;
+ for (j = 0; j < sizeof(bss->libertas_supported_rates); j++) {
+ u8 rate = bss->libertas_supported_rates[j];
+ if (rate == 0)
+ break; /* no more rates */
/* Bit rate given in 500 kb/s units (+ 0x80) */
- for (j = 0; j < sizeof(adapter->scantable[i].libertas_supported_rates);
- j++) {
- if (adapter->scantable[i].libertas_supported_rates[j] == 0) {
- break;
- }
- rate =
- (adapter->scantable[i].libertas_supported_rates[j] & 0x7F) *
- 500000;
- if (rate > iwe.u.bitrate.value) {
- iwe.u.bitrate.value = rate;
- }
-
- iwe.u.bitrate.value =
- (adapter->scantable[i].libertas_supported_rates[j]
- & 0x7f) * 500000;
- iwe.len = IW_EV_PARAM_LEN;
- current_ev =
- iwe_stream_add_value(current_ev, current_val,
- end_buf, &iwe, iwe.len);
+ iwe.u.bitrate.value = (rate & 0x7f) * 500000;
+ current_val = iwe_stream_add_value(start, current_val,
+ stop, &iwe, IW_EV_PARAM_LEN);
+ }
+ if ((bss->mode == IW_MODE_ADHOC)
+ && !libertas_ssid_cmp(adapter->curbssparams.ssid,
+ adapter->curbssparams.ssid_len,
+ bss->ssid, bss->ssid_len)
+ && adapter->adhoccreate) {
+ iwe.u.bitrate.value = 22 * 500000;
+ current_val = iwe_stream_add_value(start, current_val,
+ stop, &iwe, IW_EV_PARAM_LEN);
+ }
+ /* Check if we added any event */
+ if((current_val - start) > IW_EV_LCP_LEN)
+ start = current_val;
+
+ memset(&iwe, 0, sizeof(iwe));
+ if (bss->wpa_ie_len) {
+ char buf[MAX_WPA_IE_LEN];
+ memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss->wpa_ie_len;
+ start = iwe_stream_add_point(start, stop, &iwe, buf);
+ }
- }
- if ((adapter->scantable[i].mode == IW_MODE_ADHOC)
- && !libertas_SSID_cmp(&adapter->curbssparams.ssid,
- &adapter->scantable[i].ssid)
- && adapter->adhoccreate) {
- iwe.u.bitrate.value = 22 * 500000;
- }
- iwe.len = IW_EV_PARAM_LEN;
- current_ev =
- iwe_stream_add_value(current_ev, current_val, end_buf, &iwe,
- iwe.len);
-
- /* Add new value to event */
- current_val = current_ev + IW_EV_LCP_LEN;
-
- if (adapter->scantable[i].rsn_ie[0] == WPA2_IE) {
- memset(&iwe, 0, sizeof(iwe));
- memset(buf, 0, sizeof(buf));
- memcpy(buf, adapter->scantable[i].rsn_ie,
- adapter->scantable[i].rsn_ie_len);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = adapter->scantable[i].rsn_ie_len;
- iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
- current_ev = iwe_stream_add_point(current_ev, end_buf,
- &iwe, buf);
- }
- if (adapter->scantable[i].wpa_ie[0] == WPA_IE) {
- memset(&iwe, 0, sizeof(iwe));
- memset(buf, 0, sizeof(buf));
- memcpy(buf, adapter->scantable[i].wpa_ie,
- adapter->scantable[i].wpa_ie_len);
- iwe.cmd = IWEVGENIE;
- iwe.u.data.length = adapter->scantable[i].wpa_ie_len;
- iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
- current_ev = iwe_stream_add_point(current_ev, end_buf,
- &iwe, buf);
- }
+ memset(&iwe, 0, sizeof(iwe));
+ if (bss->rsn_ie_len) {
+ char buf[MAX_WPA_IE_LEN];
+ memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = bss->rsn_ie_len;
+ start = iwe_stream_add_point(start, stop, &iwe, buf);
+ }
+ return start;
+}
- if (adapter->scantable[i].extra_ie != 0) {
- memset(&iwe, 0, sizeof(iwe));
- memset(buf, 0, sizeof(buf));
- ptr = buf;
- ptr += sprintf(ptr, "extra_ie");
- iwe.u.data.length = strlen(buf);
+/**
+ * @brief Retrieve the scan table entries via wireless tools IOCTL call
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param dwrq A pointer to iw_point structure
+ * @param extra A pointer to extra data buf
+ *
+ * @return 0 --success, otherwise fail
+ */
+int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+#define SCAN_ITEM_SIZE 128
+ wlan_private *priv = dev->priv;
+ wlan_adapter *adapter = priv->adapter;
+ int err = 0;
+ char *ev = extra;
+ char *stop = ev + dwrq->length;
+ struct bss_descriptor * iter_bss;
+ struct bss_descriptor * safe;
+
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
+ /* If we've got an uncompleted scan, schedule the next part */
+ if (!adapter->nr_cmd_pending && adapter->last_scanned_channel)
+ wlan_scan_networks(priv, NULL, 0);
+
+ /* Update RSSI if current BSS is a locally created ad-hoc BSS */
+ if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) {
+ libertas_prepare_and_send_command(priv, cmd_802_11_rssi, 0,
+ cmd_option_waitforrsp, 0, NULL);
+ }
- lbs_pr_debug(1, "iwe.u.data.length %d\n",
- iwe.u.data.length);
- lbs_pr_debug(1, "BUF: %s \n", buf);
+ mutex_lock(&adapter->lock);
+ list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) {
+ char * next_ev;
+ unsigned long stale_time;
- iwe.cmd = IWEVCUSTOM;
- iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
- current_ev =
- iwe_stream_add_point(current_ev, end_buf, &iwe,
- buf);
+ if (stop - ev < SCAN_ITEM_SIZE) {
+ err = -E2BIG;
+ break;
}
- current_val = current_ev + IW_EV_LCP_LEN;
+ /* Prune old an old scan result */
+ stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
+ if (time_after(jiffies, stale_time)) {
+ list_move_tail (&iter_bss->list,
+ &adapter->network_free_list);
+ clear_bss_descriptor(iter_bss);
+ continue;
+ }
- /*
- * Check if we added any event
- */
- if ((current_val - current_ev) > IW_EV_LCP_LEN)
- current_ev = current_val;
+ /* Translate to WE format this entry */
+ next_ev = libertas_translate_scan(priv, ev, stop, iter_bss);
+ if (next_ev == NULL)
+ continue;
+ ev = next_ev;
}
+ mutex_unlock(&adapter->lock);
- dwrq->length = (current_ev - extra);
+ dwrq->length = (ev - extra);
dwrq->flags = 0;
- LEAVE();
- return 0;
+ lbs_deb_leave(LBS_DEB_ASSOC);
+ return err;
}
/**
@@ -1796,13 +1702,13 @@ int libertas_cmd_80211_scan(wlan_private * priv,
struct cmd_ds_802_11_scan *pscan = &cmd->params.scan;
struct wlan_scan_cmd_config *pscancfg;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
pscancfg = pdata_buf;
/* Set fixed field variables in scan command */
pscan->bsstype = pscancfg->bsstype;
- memcpy(pscan->BSSID, pscancfg->specificBSSID, sizeof(pscan->BSSID));
+ memcpy(pscan->BSSID, pscancfg->bssid, sizeof(pscan->BSSID));
memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);
cmd->command = cpu_to_le16(cmd_802_11_scan);
@@ -1812,12 +1718,26 @@ int libertas_cmd_80211_scan(wlan_private * priv,
+ sizeof(pscan->BSSID)
+ pscancfg->tlvbufferlen + S_DS_GEN);
- lbs_pr_debug(1, "SCAN_CMD: command=%x, size=%x, seqnum=%x\n",
- cmd->command, cmd->size, cmd->seqnum);
- LEAVE();
+ lbs_deb_scan("SCAN_CMD: command=%x, size=%x, seqnum=%x\n",
+ le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
+ le16_to_cpu(cmd->seqnum));
+
+ lbs_deb_leave(LBS_DEB_ASSOC);
return 0;
}
+static inline int is_same_network(struct bss_descriptor *src,
+ struct bss_descriptor *dst)
+{
+ /* A network is only a duplicate if the channel, BSSID, and ESSID
+ * all match. We treat all <hidden> with the same BSSID and channel
+ * as one network */
+ return ((src->ssid_len == dst->ssid_len) &&
+ (src->channel == dst->channel) &&
+ !compare_ether_addr(src->bssid, dst->bssid) &&
+ !memcmp(src->ssid, dst->ssid, src->ssid_len));
+}
+
/**
* @brief This function handles the command response of scan
*
@@ -1846,38 +1766,45 @@ int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp)
{
wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_scan_rsp *pscan;
- struct bss_descriptor newbssentry;
struct mrvlietypes_data *ptlv;
struct mrvlietypes_tsftimestamp *ptsftlv;
+ struct bss_descriptor * iter_bss;
+ struct bss_descriptor * safe;
u8 *pbssinfo;
u16 scanrespsize;
int bytesleft;
- int numintable;
- int bssIdx;
int idx;
int tlvbufsize;
- u64 tsfval;
+ int ret;
- ENTER();
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
+ /* Prune old entries from scan table */
+ list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) {
+ unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
+ if (time_before(jiffies, stale_time))
+ continue;
+ list_move_tail (&iter_bss->list, &adapter->network_free_list);
+ clear_bss_descriptor(iter_bss);
+ }
pscan = &resp->params.scanresp;
- if (pscan->nr_sets > MRVDRV_MAX_BSSID_LIST) {
- lbs_pr_debug(1,
- "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
- pscan->nr_sets);
- LEAVE();
- return -1;
+ if (pscan->nr_sets > MAX_NETWORK_COUNT) {
+ lbs_deb_scan(
+ "SCAN_RESP: too many scan results (%d, max %d)!!\n",
+ pscan->nr_sets, MAX_NETWORK_COUNT);
+ ret = -1;
+ goto done;
}
bytesleft = le16_to_cpu(pscan->bssdescriptsize);
- lbs_pr_debug(1, "SCAN_RESP: bssdescriptsize %d\n", bytesleft);
+ lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
scanrespsize = le16_to_cpu(resp->size);
- lbs_pr_debug(1, "SCAN_RESP: returned %d AP before parsing\n",
+ lbs_deb_scan("SCAN_RESP: returned %d AP before parsing\n",
pscan->nr_sets);
- numintable = adapter->numinscantable;
pbssinfo = pscan->bssdesc_and_tlvbuffer;
/* The size of the TLV buffer is equal to the entire command response
@@ -1901,105 +1828,68 @@ int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp)
* or as an addition at the end of the table
*/
for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) {
- /* Zero out the newbssentry we are about to store info in */
- memset(&newbssentry, 0x00, sizeof(newbssentry));
+ struct bss_descriptor new;
+ struct bss_descriptor * found = NULL;
+ struct bss_descriptor * oldest = NULL;
/* Process the data fields and IEs returned for this BSS */
- if ((InterpretBSSDescriptionWithIE(&newbssentry,
- &pbssinfo,
- &bytesleft) ==
- 0)
- && CHECK_SSID_IS_VALID(&newbssentry.ssid)) {
-
- lbs_pr_debug(1,
- "SCAN_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
- newbssentry.macaddress[0],
- newbssentry.macaddress[1],
- newbssentry.macaddress[2],
- newbssentry.macaddress[3],
- newbssentry.macaddress[4],
- newbssentry.macaddress[5]);
-
- /*
- * Search the scan table for the same bssid
- */
- for (bssIdx = 0; bssIdx < numintable; bssIdx++) {
- if (memcmp(newbssentry.macaddress,
- adapter->scantable[bssIdx].
- macaddress,
- sizeof(newbssentry.macaddress)) ==
- 0) {
- /*
- * If the SSID matches as well, it is a duplicate of
- * this entry. Keep the bssIdx set to this
- * entry so we replace the old contents in the table
- */
- if ((newbssentry.ssid.ssidlength ==
- adapter->scantable[bssIdx].ssid.
- ssidlength)
- &&
- (memcmp
- (newbssentry.ssid.ssid,
- adapter->scantable[bssIdx].ssid.
- ssid,
- newbssentry.ssid.ssidlength) ==
- 0)) {
- lbs_pr_debug(1,
- "SCAN_RESP: Duplicate of index: %d\n",
- bssIdx);
- break;
- }
- }
- }
- /*
- * If the bssIdx is equal to the number of entries in the table,
- * the new entry was not a duplicate; append it to the scan
- * table
- */
- if (bssIdx == numintable) {
- /* Range check the bssIdx, keep it limited to the last entry */
- if (bssIdx == MRVDRV_MAX_BSSID_LIST) {
- bssIdx--;
- } else {
- numintable++;
- }
- }
-
- /*
- * If the TSF TLV was appended to the scan results, save the
- * this entries TSF value in the networktsf field. The
- * networktsf is the firmware's TSF value at the time the
- * beacon or probe response was received.
- */
- if (ptsftlv) {
- memcpy(&tsfval, &ptsftlv->tsftable[idx],
- sizeof(tsfval));
- tsfval = le64_to_cpu(tsfval);
+ memset(&new, 0, sizeof (struct bss_descriptor));
+ if (libertas_process_bss(&new, &pbssinfo, &bytesleft) != 0) {
+ /* error parsing the scan response, skipped */
+ lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
+ continue;
+ }
- memcpy(&newbssentry.networktsf,
- &tsfval, sizeof(newbssentry.networktsf));
+ /* Try to find this bss in the scan table */
+ list_for_each_entry (iter_bss, &adapter->network_list, list) {
+ if (is_same_network(iter_bss, &new)) {
+ found = iter_bss;
+ break;
}
- /* Copy the locally created newbssentry to the scan table */
- memcpy(&adapter->scantable[bssIdx],
- &newbssentry,
- sizeof(adapter->scantable[bssIdx]));
+ if ((oldest == NULL) ||
+ (iter_bss->last_scanned < oldest->last_scanned))
+ oldest = iter_bss;
+ }
+ if (found) {
+ /* found, clear it */
+ clear_bss_descriptor(found);
+ } else if (!list_empty(&adapter->network_free_list)) {
+ /* Pull one from the free list */
+ found = list_entry(adapter->network_free_list.next,
+ struct bss_descriptor, list);
+ list_move_tail(&found->list, &adapter->network_list);
+ } else if (oldest) {
+ /* If there are no more slots, expire the oldest */
+ found = oldest;
+ clear_bss_descriptor(found);
+ list_move_tail(&found->list, &adapter->network_list);
} else {
+ continue;
+ }
+
+ lbs_deb_scan("SCAN_RESP: BSSID = " MAC_FMT "\n",
+ new.bssid[0], new.bssid[1], new.bssid[2],
+ new.bssid[3], new.bssid[4], new.bssid[5]);
- /* error parsing/interpreting the scan response, skipped */
- lbs_pr_debug(1, "SCAN_RESP: "
- "InterpretBSSDescriptionWithIE returned ERROR\n");
+ /*
+ * If the TSF TLV was appended to the scan results, save the
+ * this entries TSF value in the networktsf field. The
+ * networktsf is the firmware's TSF value at the time the
+ * beacon or probe response was received.
+ */
+ if (ptsftlv) {
+ new.networktsf = le64_to_cpup(&ptsftlv->tsftable[idx]);
}
- }
- lbs_pr_debug(1, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
- pscan->nr_sets, numintable - adapter->numinscantable,
- numintable);
+ /* Copy the locally created newbssentry to the scan table */
+ memcpy(found, &new, offsetof(struct bss_descriptor, list));
+ }
- /* Update the total number of BSSIDs in the scan table */
- adapter->numinscantable = numintable;
+ ret = 0;
- LEAVE();
- return 0;
+done:
+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+ return ret;
}
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index 405f4f0fe57..bd019e5ff1e 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -51,7 +51,7 @@ struct wlan_scan_cmd_config {
/**
* @brief Specific BSSID used to filter scan results in the firmware
*/
- u8 specificBSSID[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
/**
* @brief length of TLVs sent in command starting at tlvBuffer
@@ -91,15 +91,6 @@ struct wlan_ioctl_user_scan_chan {
* @sa libertas_set_user_scan_ioctl
*/
struct wlan_ioctl_user_scan_cfg {
-
- /**
- * @brief Flag set to keep the previous scan table intact
- *
- * If set, the scan results will accumulate, replacing any previous
- * matched entries for a BSS with the new scan data
- */
- u8 keeppreviousscan; //!< Do not erase the existing scan results
-
/**
* @brief BSS type to be sent in the firmware command
*
@@ -117,15 +108,22 @@ struct wlan_ioctl_user_scan_cfg {
*/
u8 numprobes;
- /**
- * @brief BSSID filter sent in the firmware command to limit the results
- */
- u8 specificBSSID[ETH_ALEN];
+ /**
+ * @brief BSSID filter sent in the firmware command to limit the results
+ */
+ u8 bssid[ETH_ALEN];
- /**
- * @brief SSID filter sent in the firmware command to limit the results
- */
- char specificSSID[IW_ESSID_MAX_SIZE + 1];
+ /* Clear existing scan results matching this BSSID */
+ u8 clear_bssid;
+
+ /**
+ * @brief SSID filter sent in the firmware command to limit the results
+ */
+ char ssid[IW_ESSID_MAX_SIZE];
+ u8 ssid_len;
+
+ /* Clear existing scan results matching this SSID */
+ u8 clear_ssid;
/**
* @brief Variable number (fixed maximum) of channels to scan up
@@ -137,9 +135,10 @@ struct wlan_ioctl_user_scan_cfg {
* @brief Structure used to store information for each beacon/probe response
*/
struct bss_descriptor {
- u8 macaddress[ETH_ALEN];
+ u8 bssid[ETH_ALEN];
- struct WLAN_802_11_SSID ssid;
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 ssid_len;
/* WEP encryption requirement */
u32 privacy;
@@ -156,15 +155,15 @@ struct bss_descriptor {
u8 mode;
u8 libertas_supported_rates[WLAN_SUPPORTED_RATES];
- int extra_ie;
+ __le64 timestamp; //!< TSF value included in the beacon/probe response
+ unsigned long last_scanned;
- u8 timestamp[8]; //!< TSF value included in the beacon/probe response
union ieeetypes_phyparamset phyparamset;
union IEEEtypes_ssparamset ssparamset;
struct ieeetypes_capinfo cap;
u8 datarates[WLAN_SUPPORTED_RATES];
- __le64 networktsf; //!< TSF timestamp from the current firmware TSF
+ u64 networktsf; //!< TSF timestamp from the current firmware TSF
struct ieeetypes_countryinfofullset countryinfo;
@@ -172,24 +171,29 @@ struct bss_descriptor {
size_t wpa_ie_len;
u8 rsn_ie[MAX_WPA_IE_LEN];
size_t rsn_ie_len;
+
+ struct list_head list;
};
-extern int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1,
- struct WLAN_802_11_SSID *ssid2);
-extern int libertas_find_SSID_in_list(wlan_adapter * adapter, struct WLAN_802_11_SSID *ssid,
- u8 * bssid, u8 mode);
-int libertas_find_best_SSID_in_list(wlan_adapter * adapter, u8 mode);
-extern int libertas_find_BSSID_in_list(wlan_adapter * adapter, u8 * bssid, u8 mode);
+extern int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
+
+struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
+ u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
+ int channel);
+
+struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter,
+ u8 mode);
+
+extern struct bss_descriptor * libertas_find_bssid_in_list(wlan_adapter * adapter,
+ u8 * bssid, u8 mode);
-int libertas_find_best_network_SSID(wlan_private * priv,
- struct WLAN_802_11_SSID *pSSID,
- u8 preferred_mode, u8 *out_mode);
+int libertas_find_best_network_ssid(wlan_private * priv, u8 *out_ssid,
+ u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
-extern int libertas_send_specific_SSID_scan(wlan_private * priv,
- struct WLAN_802_11_SSID *prequestedssid,
- u8 keeppreviousscan);
-extern int libertas_send_specific_BSSID_scan(wlan_private * priv,
- u8 * bssid, u8 keeppreviousscan);
+extern int libertas_send_specific_ssid_scan(wlan_private * priv, u8 *ssid,
+ u8 ssid_len, u8 clear_ssid);
+extern int libertas_send_specific_bssid_scan(wlan_private * priv,
+ u8 * bssid, u8 clear_bssid);
extern int libertas_cmd_80211_scan(wlan_private * priv,
struct cmd_ds_command *cmd,
@@ -199,7 +203,8 @@ extern int libertas_ret_80211_scan(wlan_private * priv,
struct cmd_ds_command *resp);
int wlan_scan_networks(wlan_private * priv,
- const struct wlan_ioctl_user_scan_cfg * puserscanin);
+ const struct wlan_ioctl_user_scan_cfg * puserscanin,
+ int full_scan);
struct ifreq;
diff --git a/drivers/net/wireless/libertas/thread.h b/drivers/net/wireless/libertas/thread.h
index 207b8a6cc33..b1f34d92ff3 100644
--- a/drivers/net/wireless/libertas/thread.h
+++ b/drivers/net/wireless/libertas/thread.h
@@ -21,11 +21,11 @@ static inline void wlan_activate_thread(struct wlan_thread * thr)
static inline void wlan_deactivate_thread(struct wlan_thread * thr)
{
- ENTER();
+ lbs_deb_enter(LBS_DEB_THREAD);
thr->pid = 0;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_THREAD);
}
static inline void wlan_create_thread(int (*wlanfunc) (void *),
@@ -36,7 +36,7 @@ static inline void wlan_create_thread(int (*wlanfunc) (void *),
static inline int wlan_terminate_thread(struct wlan_thread * thr)
{
- ENTER();
+ lbs_deb_enter(LBS_DEB_THREAD);
/* Check if the thread is active or not */
if (!thr->pid) {
@@ -45,7 +45,7 @@ static inline int wlan_terminate_thread(struct wlan_thread * thr)
}
kthread_stop(thr->task);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_THREAD);
return 0;
}
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index d4b13478c9a..17c437635a0 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -5,7 +5,6 @@
#include "hostcmd.h"
#include "radiotap.h"
-#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
@@ -68,7 +67,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
u32 new_rate;
u8 *ptr = priv->adapter->tmptxbuf;
- ENTER();
+ lbs_deb_enter(LBS_DEB_TX);
if (priv->adapter->surpriseremoved)
return -1;
@@ -78,7 +77,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
min_t(unsigned int, skb->len, 100));
if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
- lbs_pr_debug(1, "Tx error: Bad skb length %d : %zd\n",
+ lbs_deb_tx("tx err: skb length %d 0 or > %zd\n",
skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
ret = -1;
goto done;
@@ -86,13 +85,13 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
memset(plocaltxpd, 0, sizeof(struct txpd));
- plocaltxpd->tx_packet_length = skb->len;
+ plocaltxpd->tx_packet_length = cpu_to_le16(skb->len);
/* offset of actual data */
- plocaltxpd->tx_packet_location = sizeof(struct txpd);
+ plocaltxpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
/* TxCtrl set by user or default */
- plocaltxpd->tx_control = adapter->pkttxctrl;
+ plocaltxpd->tx_control = cpu_to_le32(adapter->pkttxctrl);
p802x_hdr = skb->data;
if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
@@ -103,15 +102,16 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
/* set txpd fields from the radiotap header */
new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate);
if (new_rate != 0) {
- /* erase tx_control[4:0] */
- plocaltxpd->tx_control &= ~0x1f;
- /* write new tx_control[4:0] */
- plocaltxpd->tx_control |= new_rate;
+ /* use new tx_control[4:0] */
+ new_rate |= (adapter->pkttxctrl & ~0x1f);
+ plocaltxpd->tx_control = cpu_to_le32(new_rate);
}
/* skip the radiotap header */
p802x_hdr += sizeof(struct tx_radiotap_hdr);
- plocaltxpd->tx_packet_length -= sizeof(struct tx_radiotap_hdr);
+ plocaltxpd->tx_packet_length =
+ cpu_to_le16(le16_to_cpu(plocaltxpd->tx_packet_length)
+ - sizeof(struct tx_radiotap_hdr));
}
/* copy destination address from 802.3 or 802.11 header */
@@ -123,28 +123,28 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
lbs_dbg_hex("txpd", (u8 *) plocaltxpd, sizeof(struct txpd));
if (IS_MESH_FRAME(skb)) {
- plocaltxpd->tx_control |= TxPD_MESH_FRAME;
+ plocaltxpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
}
memcpy(ptr, plocaltxpd, sizeof(struct txpd));
ptr += sizeof(struct txpd);
- lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, plocaltxpd->tx_packet_length);
- memcpy(ptr, p802x_hdr, plocaltxpd->tx_packet_length);
- ret = libertas_sbi_host_to_card(priv, MVMS_DAT,
- priv->adapter->tmptxbuf,
- plocaltxpd->tx_packet_length +
- sizeof(struct txpd));
+ lbs_dbg_hex("Tx Data", (u8 *) p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length));
+ memcpy(ptr, p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length));
+ ret = priv->hw_host_to_card(priv, MVMS_DAT,
+ priv->adapter->tmptxbuf,
+ le16_to_cpu(plocaltxpd->tx_packet_length) +
+ sizeof(struct txpd));
if (ret) {
- lbs_pr_debug(1, "Tx error: libertas_sbi_host_to_card failed: 0x%X\n", ret);
+ lbs_deb_tx("tx err: hw_host_to_card returned 0x%X\n", ret);
goto done;
}
- lbs_pr_debug(1, "SendSinglePacket succeeds\n");
+ lbs_deb_tx("SendSinglePacket succeeds\n");
- done:
+done:
if (!ret) {
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len;
@@ -158,7 +158,8 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
received from FW */
skb_orphan(skb);
/* stop processing outgoing pkts */
- netif_stop_queue(priv->wlan_dev.netdev);
+ netif_stop_queue(priv->dev);
+ netif_stop_queue(priv->mesh_dev);
/* freeze any packets already in our queues */
priv->adapter->TxLockFlag = 1;
} else {
@@ -166,7 +167,7 @@ static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
priv->adapter->currenttxskb = NULL;
}
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
return ret;
}
@@ -195,10 +196,13 @@ static void wlan_tx_queue(wlan_private *priv, struct sk_buff *skb)
WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE);
adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb;
- if (adapter->tx_queue_idx == NR_TX_QUEUE)
- netif_stop_queue(priv->wlan_dev.netdev);
- else
- netif_start_queue(priv->wlan_dev.netdev);
+ if (adapter->tx_queue_idx == NR_TX_QUEUE) {
+ netif_stop_queue(priv->dev);
+ netif_stop_queue(priv->mesh_dev);
+ } else {
+ netif_start_queue(priv->dev);
+ netif_start_queue(priv->mesh_dev);
+ }
spin_unlock(&adapter->txqueue_lock);
}
@@ -214,13 +218,12 @@ int libertas_process_tx(wlan_private * priv, struct sk_buff *skb)
{
int ret = -1;
- ENTER();
-
+ lbs_deb_enter(LBS_DEB_TX);
lbs_dbg_hex("TX Data", skb->data, min_t(unsigned int, skb->len, 100));
- if (priv->wlan_dev.dnld_sent) {
+ if (priv->dnld_sent) {
lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n",
- priv->wlan_dev.dnld_sent);
+ priv->dnld_sent);
goto done;
}
@@ -234,7 +237,7 @@ int libertas_process_tx(wlan_private * priv, struct sk_buff *skb)
ret = SendSinglePacket(priv, skb);
done:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
return ret;
}
@@ -280,6 +283,9 @@ void libertas_send_tx_feedback(wlan_private * priv)
libertas_upload_rx_packet(priv, adapter->currenttxskb);
adapter->currenttxskb = NULL;
priv->adapter->TxLockFlag = 0;
- if (priv->adapter->connect_status == libertas_connected)
- netif_wake_queue(priv->wlan_dev.netdev);
+ if (priv->adapter->connect_status == libertas_connected) {
+ netif_wake_queue(priv->dev);
+ netif_wake_queue(priv->mesh_dev);
+ }
}
+EXPORT_SYMBOL_GPL(libertas_send_tx_feedback);
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index 09d62f8b1a1..028e2f3b53d 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -5,6 +5,7 @@
#define _WLAN_TYPES_
#include <linux/if_ether.h>
+#include <asm/byteorder.h>
/** IEEE type definitions */
enum ieeetypes_elementid {
@@ -29,9 +30,30 @@ enum ieeetypes_elementid {
EXTRA_IE = 133,
} __attribute__ ((packed));
+#ifdef __BIG_ENDIAN
#define CAPINFO_MASK (~(0xda00))
+#else
+#define CAPINFO_MASK (~(0x00da))
+#endif
struct ieeetypes_capinfo {
+#ifdef __BIG_ENDIAN_BITFIELD
+ u8 chanagility:1;
+ u8 pbcc:1;
+ u8 shortpreamble:1;
+ u8 privacy:1;
+ u8 cfpollrqst:1;
+ u8 cfpollable:1;
+ u8 ibss:1;
+ u8 ess:1;
+ u8 rsrvd1:2;
+ u8 dsssofdm:1;
+ u8 rsvrd2:1;
+ u8 apsd:1;
+ u8 shortslottime:1;
+ u8 rsrvd3:1;
+ u8 spectrummgmt:1;
+#else
u8 ess:1;
u8 ibss:1;
u8 cfpollable:1;
@@ -47,6 +69,7 @@ struct ieeetypes_capinfo {
u8 rsvrd2:1;
u8 dsssofdm:1;
u8 rsrvd1:2;
+#endif
} __attribute__ ((packed));
struct ieeetypes_cfparamset {
@@ -54,15 +77,15 @@ struct ieeetypes_cfparamset {
u8 len;
u8 cfpcnt;
u8 cfpperiod;
- u16 cfpmaxduration;
- u16 cfpdurationremaining;
+ __le16 cfpmaxduration;
+ __le16 cfpdurationremaining;
} __attribute__ ((packed));
struct ieeetypes_ibssparamset {
u8 elementid;
u8 len;
- u16 atimwindow;
+ __le16 atimwindow;
} __attribute__ ((packed));
union IEEEtypes_ssparamset {
@@ -73,7 +96,7 @@ union IEEEtypes_ssparamset {
struct ieeetypes_fhparamset {
u8 elementid;
u8 len;
- u16 dwelltime;
+ __le16 dwelltime;
u8 hopset;
u8 hoppattern;
u8 hopindex;
@@ -92,8 +115,8 @@ union ieeetypes_phyparamset {
struct ieeetypes_assocrsp {
struct ieeetypes_capinfo capability;
- u16 statuscode;
- u16 aid;
+ __le16 statuscode;
+ __le16 aid;
u8 iebuffer[1];
} __attribute__ ((packed));
@@ -138,8 +161,8 @@ struct ieeetypes_assocrsp {
/** TLV related data structures*/
struct mrvlietypesheader {
- u16 type;
- u16 len;
+ __le16 type;
+ __le16 len;
} __attribute__ ((packed));
struct mrvlietypes_data {
@@ -164,17 +187,23 @@ struct mrvlietypes_wildcardssidparamset {
} __attribute__ ((packed));
struct chanscanmode {
+#ifdef __BIG_ENDIAN_BITFIELD
+ u8 reserved_2_7:6;
+ u8 disablechanfilt:1;
+ u8 passivescan:1;
+#else
u8 passivescan:1;
u8 disablechanfilt:1;
u8 reserved_2_7:6;
+#endif
} __attribute__ ((packed));
struct chanscanparamset {
u8 radiotype;
u8 channumber;
struct chanscanmode chanscanmode;
- u16 minscantime;
- u16 maxscantime;
+ __le16 minscantime;
+ __le16 maxscantime;
} __attribute__ ((packed));
struct mrvlietypes_chanlistparamset {
@@ -185,12 +214,12 @@ struct mrvlietypes_chanlistparamset {
struct cfparamset {
u8 cfpcnt;
u8 cfpperiod;
- u16 cfpmaxduration;
- u16 cfpdurationremaining;
+ __le16 cfpmaxduration;
+ __le16 cfpdurationremaining;
} __attribute__ ((packed));
struct ibssparamset {
- u16 atimwindow;
+ __le16 atimwindow;
} __attribute__ ((packed));
struct mrvlietypes_ssparamset {
@@ -202,7 +231,7 @@ struct mrvlietypes_ssparamset {
} __attribute__ ((packed));
struct fhparamset {
- u16 dwelltime;
+ __le16 dwelltime;
u8 hopset;
u8 hoppattern;
u8 hopindex;
@@ -263,17 +292,17 @@ struct mrvlietypes_beaconsmissed {
struct mrvlietypes_numprobes {
struct mrvlietypesheader header;
- u16 numprobes;
+ __le16 numprobes;
} __attribute__ ((packed));
struct mrvlietypes_bcastprobe {
struct mrvlietypesheader header;
- u16 bcastprobe;
+ __le16 bcastprobe;
} __attribute__ ((packed));
struct mrvlietypes_numssidprobe {
struct mrvlietypesheader header;
- u16 numssidprobe;
+ __le16 numssidprobe;
} __attribute__ ((packed));
struct led_pin {
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 69f52b6e59c..f42b796b5e4 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -22,6 +22,14 @@
/**
+ * the rates supported by the card
+ */
+static u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] =
+ { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
+ 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
+};
+
+/**
* @brief Convert mw value to dbm value
*
* @param mw the value of mw
@@ -102,8 +110,8 @@ struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * ada
}
if (!cfp && channel)
- lbs_pr_debug(1, "libertas_find_cfp_by_band_and_channel(): cannot find "
- "cfp by band %d & channel %d\n", band, channel);
+ lbs_deb_wext("libertas_find_cfp_by_band_and_channel: can't find "
+ "cfp by band %d / channel %d\n", band, channel);
return cfp;
}
@@ -143,113 +151,12 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter,
}
if (!cfp && freq)
- lbs_pr_debug(1, "find_cfp_by_band_and_freql(): cannot find cfp by "
- "band %d & freq %d\n", band, freq);
+ lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by "
+ "band %d / freq %d\n", band, freq);
return cfp;
}
-static int updatecurrentchannel(wlan_private * priv)
-{
- int ret;
-
- /*
- ** the channel in f/w could be out of sync, get the current channel
- */
- ret = libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
- cmd_opt_802_11_rf_channel_get,
- cmd_option_waitforrsp, 0, NULL);
-
- lbs_pr_debug(1, "Current channel = %d\n",
- priv->adapter->curbssparams.channel);
-
- return ret;
-}
-
-static int setcurrentchannel(wlan_private * priv, int channel)
-{
- lbs_pr_debug(1, "Set channel = %d\n", channel);
-
- /*
- ** Current channel is not set to adhocchannel requested, set channel
- */
- return (libertas_prepare_and_send_command(priv, cmd_802_11_rf_channel,
- cmd_opt_802_11_rf_channel_set,
- cmd_option_waitforrsp, 0, &channel));
-}
-
-static int changeadhocchannel(wlan_private * priv, int channel)
-{
- int ret = 0;
- wlan_adapter *adapter = priv->adapter;
-
- adapter->adhocchannel = channel;
-
- updatecurrentchannel(priv);
-
- if (adapter->curbssparams.channel == adapter->adhocchannel) {
- /* adhocchannel is set to the current channel already */
- LEAVE();
- return 0;
- }
-
- lbs_pr_debug(1, "Updating channel from %d to %d\n",
- adapter->curbssparams.channel, adapter->adhocchannel);
-
- setcurrentchannel(priv, adapter->adhocchannel);
-
- updatecurrentchannel(priv);
-
- if (adapter->curbssparams.channel != adapter->adhocchannel) {
- lbs_pr_debug(1, "failed to updated channel to %d, channel = %d\n",
- adapter->adhocchannel, adapter->curbssparams.channel);
- LEAVE();
- return -1;
- }
-
- if (adapter->connect_status == libertas_connected) {
- int i;
- struct WLAN_802_11_SSID curadhocssid;
-
- lbs_pr_debug(1, "channel Changed while in an IBSS\n");
-
- /* Copy the current ssid */
- memcpy(&curadhocssid, &adapter->curbssparams.ssid,
- sizeof(struct WLAN_802_11_SSID));
-
- /* Exit Adhoc mode */
- lbs_pr_debug(1, "In changeadhocchannel(): Sending Adhoc Stop\n");
- ret = libertas_stop_adhoc_network(priv);
-
- if (ret) {
- LEAVE();
- return ret;
- }
- /* Scan for the network, do not save previous results. Stale
- * scan data will cause us to join a non-existant adhoc network
- */
- libertas_send_specific_SSID_scan(priv, &curadhocssid, 0);
-
- // find out the BSSID that matches the current SSID
- i = libertas_find_SSID_in_list(adapter, &curadhocssid, NULL,
- IW_MODE_ADHOC);
-
- if (i >= 0) {
- lbs_pr_debug(1, "SSID found at %d in List,"
- "so join\n", i);
- libertas_join_adhoc_network(priv, &adapter->scantable[i]);
- } else {
- // else send START command
- lbs_pr_debug(1, "SSID not found in list, "
- "so creating adhoc with ssid = %s\n",
- curadhocssid.ssid);
- libertas_start_adhoc_network(priv, &curadhocssid);
- } // end of else (START command)
- }
-
- LEAVE();
- return 0;
-}
/**
* @brief Set Radio On/OFF
@@ -263,10 +170,10 @@ int wlan_radio_ioctl(wlan_private * priv, u8 option)
int ret = 0;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (adapter->radioon != option) {
- lbs_pr_debug(1, "Switching %s the Radio\n", option ? "On" : "Off");
+ lbs_deb_wext("switching radio %s\n", option ? "on" : "off");
adapter->radioon = option;
ret = libertas_prepare_and_send_command(priv,
@@ -275,7 +182,7 @@ int wlan_radio_ioctl(wlan_private * priv, u8 option)
cmd_option_waitforrsp, 0, NULL);
}
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -312,15 +219,15 @@ static int get_active_data_rates(wlan_adapter * adapter,
{
int k = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (adapter->connect_status != libertas_connected) {
if (adapter->mode == IW_MODE_INFRA) {
- lbs_pr_debug(1, "Infra\n");
+ lbs_deb_wext("infra\n");
k = copyrates(rates, k, libertas_supported_rates,
sizeof(libertas_supported_rates));
} else {
- lbs_pr_debug(1, "Adhoc G\n");
+ lbs_deb_wext("Adhoc G\n");
k = copyrates(rates, k, libertas_adhoc_rates_g,
sizeof(libertas_adhoc_rates_g));
}
@@ -329,8 +236,7 @@ static int get_active_data_rates(wlan_adapter * adapter,
adapter->curbssparams.numofrates);
}
- LEAVE();
-
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", k);
return k;
}
@@ -342,7 +248,7 @@ static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
char mrvl[6] = { "MRVL-" };
int cnt;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
strcpy(cwrq, mrvl);
@@ -360,8 +266,7 @@ static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
}
*cwrq = '\0';
- LEAVE();
-
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -372,14 +277,14 @@ static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info,
wlan_adapter *adapter = priv->adapter;
struct chan_freq_power *cfp;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
cfp = libertas_find_cfp_by_band_and_channel(adapter, 0,
adapter->curbssparams.channel);
if (!cfp) {
if (adapter->curbssparams.channel)
- lbs_pr_debug(1, "Invalid channel=%d\n",
+ lbs_deb_wext("invalid channel %d\n",
adapter->curbssparams.channel);
return -EINVAL;
}
@@ -387,9 +292,8 @@ static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info,
fwrq->m = (long)cfp->freq * 100000;
fwrq->e = 1;
- lbs_pr_debug(1, "freq=%u\n", fwrq->m);
-
- LEAVE();
+ lbs_deb_wext("freq %u\n", fwrq->m);
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -399,7 +303,7 @@ static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (adapter->connect_status == libertas_connected) {
memcpy(awrq->sa_data, adapter->curbssparams.bssid, ETH_ALEN);
@@ -408,7 +312,7 @@ static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info,
}
awrq->sa_family = ARPHRD_ETHER;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -418,7 +322,7 @@ static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
/*
* Check the size of the string
@@ -433,7 +337,7 @@ static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info,
memcpy(adapter->nodename, extra, dwrq->length);
mutex_unlock(&adapter->lock);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -443,7 +347,7 @@ static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
/*
* Get the Nick Name saved
@@ -464,19 +368,43 @@ static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info,
*/
dwrq->length = strlen(extra) + 1;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
+static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ wlan_private *priv = dev->priv;
+ wlan_adapter *adapter = priv->adapter;
+
+ lbs_deb_enter(LBS_DEB_WEXT);
+
+ /* Use nickname to indicate that mesh is on */
+
+ if (adapter->connect_status == libertas_connected) {
+ strncpy(extra, "Mesh", 12);
+ extra[12] = '\0';
+ dwrq->length = strlen(extra) + 1;
+ }
+
+ else {
+ extra[0] = '\0';
+ dwrq->length = 1 ;
+ }
+
+ lbs_deb_leave(LBS_DEB_WEXT);
+ return 0;
+}
static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- int rthr = vwrq->value;
+ u32 rthr = vwrq->value;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
adapter->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
@@ -490,7 +418,7 @@ static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
cmd_act_set, cmd_option_waitforrsp,
OID_802_11_RTS_THRESHOLD, &rthr);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -501,35 +429,34 @@ static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
adapter->rtsthsd = 0;
ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib,
cmd_act_get, cmd_option_waitforrsp,
OID_802_11_RTS_THRESHOLD, NULL);
- if (ret) {
- LEAVE();
- return ret;
- }
+ if (ret)
+ goto out;
vwrq->value = adapter->rtsthsd;
vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
|| (vwrq->value > MRVDRV_RTS_MAX_VALUE));
vwrq->fixed = 1;
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- int fthr = vwrq->value;
+ u32 fthr = vwrq->value;
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
adapter->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
@@ -543,7 +470,8 @@ static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
ret = libertas_prepare_and_send_command(priv, cmd_802_11_snmp_mib,
cmd_act_set, cmd_option_waitforrsp,
OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
- LEAVE();
+
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -554,24 +482,23 @@ static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
adapter->fragthsd = 0;
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_snmp_mib,
cmd_act_get, cmd_option_waitforrsp,
OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
- if (ret) {
- LEAVE();
- return ret;
- }
+ if (ret)
+ goto out;
vwrq->value = adapter->fragthsd;
vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
|| (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
vwrq->fixed = 1;
- LEAVE();
+out:
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -581,11 +508,23 @@ static int wlan_get_mode(struct net_device *dev,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
*uwrq = adapter->mode;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_WEXT);
+ return 0;
+}
+
+static int mesh_wlan_get_mode(struct net_device *dev,
+ struct iw_request_info *info, u32 * uwrq,
+ char *extra)
+{
+ lbs_deb_enter(LBS_DEB_WEXT);
+
+ *uwrq = IW_MODE_REPEAT ;
+
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -597,19 +536,17 @@ static int wlan_get_txpow(struct net_device *dev,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_rf_tx_power,
cmd_act_tx_power_opt_get,
cmd_option_waitforrsp, 0, NULL);
- if (ret) {
- LEAVE();
- return ret;
- }
+ if (ret)
+ goto out;
- lbs_pr_debug(1, "TXPOWER GET %d dbm.\n", adapter->txpowerlevel);
+ lbs_deb_wext("tx power level %d dbm\n", adapter->txpowerlevel);
vwrq->value = adapter->txpowerlevel;
vwrq->fixed = 1;
if (adapter->radioon) {
@@ -619,8 +556,9 @@ static int wlan_get_txpow(struct net_device *dev,
vwrq->disabled = 1;
}
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
@@ -630,7 +568,7 @@ static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->flags == IW_RETRY_LIMIT) {
/* The MAC has a 4-bit Total_Tx_Count register
@@ -648,16 +586,15 @@ static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
cmd_option_waitforrsp,
OID_802_11_TX_RETRYCOUNT, NULL);
- if (ret) {
- LEAVE();
- return ret;
- }
+ if (ret)
+ goto out;
} else {
return -EOPNOTSUPP;
}
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
@@ -667,16 +604,16 @@ static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
wlan_adapter *adapter = priv->adapter;
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
+
adapter->txretrycount = 0;
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_snmp_mib,
cmd_act_get, cmd_option_waitforrsp,
OID_802_11_TX_RETRYCOUNT, NULL);
- if (ret) {
- LEAVE();
- return ret;
- }
+ if (ret)
+ goto out;
+
vwrq->disabled = 0;
if (!vwrq->flags) {
vwrq->flags = IW_RETRY_LIMIT;
@@ -684,8 +621,9 @@ static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
vwrq->value = adapter->txretrycount - 1;
}
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
static inline void sort_channels(struct iw_freq *freq, int num)
@@ -739,7 +677,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
u8 flag = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
dwrq->length = sizeof(struct iw_range);
memset(range, 0, sizeof(struct iw_range));
@@ -755,7 +693,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
range->bitrate[i] = (rates[i] & 0x7f) * 500000;
}
range->num_bitrates = i;
- lbs_pr_debug(1, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES,
+ lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES,
range->num_bitrates);
range->num_frequency = 0;
@@ -768,18 +706,17 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
&adapter->parsed_region_chan;
if (parsed_region_chan == NULL) {
- lbs_pr_debug(1, "11D:parsed_region_chan is NULL\n");
- LEAVE();
- return 0;
+ lbs_deb_wext("11d: parsed_region_chan is NULL\n");
+ goto out;
}
band = parsed_region_chan->band;
- lbs_pr_debug(1, "band=%d NoOfChan=%d\n", band,
+ lbs_deb_wext("band %d, nr_char %d\n", band,
parsed_region_chan->nr_chan);
for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
&& (i < parsed_region_chan->nr_chan); i++) {
chan_no = parsed_region_chan->chanpwr[i].chan;
- lbs_pr_debug(1, "chan_no=%d\n", chan_no);
+ lbs_deb_wext("chan_no %d\n", chan_no);
range->freq[range->num_frequency].i = (long)chan_no;
range->freq[range->num_frequency].m =
(long)libertas_chan_2_freq(chan_no, band) * 100000;
@@ -808,7 +745,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
}
}
- lbs_pr_debug(1, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n",
+ lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
IW_MAX_FREQUENCIES, range->num_frequency);
range->num_channels = range->num_frequency;
@@ -903,7 +840,8 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
| IW_ENC_CAPA_CIPHER_CCMP;
}
- LEAVE();
+out:
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -913,7 +851,7 @@ static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
/* PS is currently supported only in Infrastructure mode
* Remove this check if it is to be supported in IBSS mode also
@@ -929,11 +867,11 @@ static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
}
if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
- lbs_pr_debug(1,
- "Setting power timeout command is not supported\n");
+ lbs_deb_wext(
+ "setting power timeout is not supported\n");
return -EINVAL;
} else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
- lbs_pr_debug(1, "Setting power period command is not supported\n");
+ lbs_deb_wext("setting power period not supported\n");
return -EINVAL;
}
@@ -947,7 +885,7 @@ static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
libertas_ps_sleep(priv, cmd_option_waitforrsp);
}
- LEAVE();
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -958,154 +896,23 @@ static int wlan_get_power(struct net_device *dev, struct iw_request_info *info,
wlan_adapter *adapter = priv->adapter;
int mode;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
mode = adapter->psmode;
if ((vwrq->disabled = (mode == wlan802_11powermodecam))
- || adapter->connect_status == libertas_disconnected) {
- LEAVE();
- return 0;
+ || adapter->connect_status == libertas_disconnected)
+ {
+ goto out;
}
vwrq->value = 0;
- LEAVE();
+out:
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
-/*
- * iwpriv settable callbacks
- */
-
-static const iw_handler wlan_private_handler[] = {
- NULL, /* SIOCIWFIRSTPRIV */
-};
-
-static const struct iw_priv_args wlan_private_args[] = {
- /*
- * { cmd, set_args, get_args, name }
- */
- /* Using iwpriv sub-command feature */
- {
- WLAN_SETONEINT_GETNONE, /* IOCTL: 24 */
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- IW_PRIV_TYPE_NONE,
- ""},
- {
- WLANSETREGION,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- IW_PRIV_TYPE_NONE,
- "setregioncode"},
- {
- WLAN_SUBCMD_MESH_SET_TTL,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- IW_PRIV_TYPE_NONE,
- "mesh_set_ttl"},
- {
- WLAN_SETNONE_GETONEINT,
- IW_PRIV_TYPE_NONE,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- ""},
- {
- WLANGETREGION,
- IW_PRIV_TYPE_NONE,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- "getregioncode"},
- {
- WLAN_SUBCMD_FWT_CLEANUP,
- IW_PRIV_TYPE_NONE,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- "fwt_cleanup"},
- {
- WLAN_SUBCMD_FWT_TIME,
- IW_PRIV_TYPE_NONE,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- "fwt_time"},
- {
- WLAN_SUBCMD_MESH_GET_TTL,
- IW_PRIV_TYPE_NONE,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
- "mesh_get_ttl"},
- {
- WLAN_SETNONE_GETNONE,
- IW_PRIV_TYPE_NONE,
- IW_PRIV_TYPE_NONE,
- ""},
- {
- WLAN_SUBCMD_FWT_RESET,
- IW_PRIV_TYPE_NONE,
- IW_PRIV_TYPE_NONE,
- "fwt_reset"},
- {
- WLAN_SUBCMD_BT_RESET,
- IW_PRIV_TYPE_NONE,
- IW_PRIV_TYPE_NONE,
- "bt_reset"},
- {
- WLAN_SET128CHAR_GET128CHAR,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- ""},
- /* BT Management */
- {
- WLAN_SUBCMD_BT_ADD,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "bt_add"},
- {
- WLAN_SUBCMD_BT_DEL,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "bt_del"},
- {
- WLAN_SUBCMD_BT_LIST,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "bt_list"},
- /* FWT Management */
- {
- WLAN_SUBCMD_FWT_ADD,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "fwt_add"},
- {
- WLAN_SUBCMD_FWT_DEL,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "fwt_del"},
- {
- WLAN_SUBCMD_FWT_LOOKUP,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "fwt_lookup"},
- {
- WLAN_SUBCMD_FWT_LIST_NEIGHBOR,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "fwt_list_neigh"},
- {
- WLAN_SUBCMD_FWT_LIST,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "fwt_list"},
- {
- WLAN_SUBCMD_FWT_LIST_ROUTE,
- IW_PRIV_TYPE_CHAR | 128,
- IW_PRIV_TYPE_CHAR | 128,
- "fwt_list_route"},
- {
- WLAN_SET_GET_SIXTEEN_INT,
- IW_PRIV_TYPE_INT | 16,
- IW_PRIV_TYPE_INT | 16,
- ""},
- {
- WLAN_LED_GPIO_CTRL,
- IW_PRIV_TYPE_INT | 16,
- IW_PRIV_TYPE_INT | 16,
- "ledgpio"},
-};
-
static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
{
enum {
@@ -1125,7 +932,7 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
u8 rssi;
u32 tx_retries;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
priv->wstats.status = adapter->mode;
@@ -1145,8 +952,8 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
}
- lbs_pr_debug(1, "Signal Level = %#x\n", priv->wstats.qual.level);
- lbs_pr_debug(1, "Noise = %#x\n", priv->wstats.qual.noise);
+ lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
+ lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
rssi = priv->wstats.qual.level - priv->wstats.qual.noise;
if (rssi < 15)
@@ -1166,7 +973,7 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
/* Quality by TX errors */
priv->wstats.discard.retries = priv->stats.tx_errors;
- tx_retries = adapter->logmsg.retry;
+ tx_retries = le16_to_cpu(adapter->logmsg.retry);
if (tx_retries > 75)
tx_qual = (90 - tx_retries) * POOR / 15;
@@ -1182,10 +989,10 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
(PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
quality = min(quality, tx_qual);
- priv->wstats.discard.code = adapter->logmsg.wepundecryptable;
- priv->wstats.discard.fragment = adapter->logmsg.fcserror;
+ priv->wstats.discard.code = le16_to_cpu(adapter->logmsg.wepundecryptable);
+ priv->wstats.discard.fragment = le16_to_cpu(adapter->logmsg.rxfrag);
priv->wstats.discard.retries = tx_retries;
- priv->wstats.discard.misc = adapter->logmsg.ackfailure;
+ priv->wstats.discard.misc = le16_to_cpu(adapter->logmsg.ackfailure);
/* Calculate quality */
priv->wstats.qual.qual = max(quality, (u32)100);
@@ -1209,7 +1016,7 @@ out:
IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
}
- LEAVE ();
+ lbs_deb_leave(LBS_DEB_WEXT);
return &priv->wstats;
@@ -1218,81 +1025,59 @@ out:
static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
{
- int ret = 0;
+ int ret = -EINVAL;
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- int rc = -EINPROGRESS; /* Call commit handler */
struct chan_freq_power *cfp;
+ struct assoc_request * assoc_req;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
- /*
- * If setting by frequency, convert to a channel
- */
- if (fwrq->e == 1) {
+ mutex_lock(&adapter->lock);
+ assoc_req = wlan_get_association_request(adapter);
+ if (!assoc_req) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ /* If setting by frequency, convert to a channel */
+ if (fwrq->e == 1) {
long f = fwrq->m / 100000;
- int c = 0;
cfp = find_cfp_by_band_and_freq(adapter, 0, f);
if (!cfp) {
- lbs_pr_debug(1, "Invalid freq=%ld\n", f);
- return -EINVAL;
+ lbs_deb_wext("invalid freq %ld\n", f);
+ goto out;
}
- c = (int)cfp->channel;
-
- if (c < 0)
- return -EINVAL;
-
fwrq->e = 0;
- fwrq->m = c;
+ fwrq->m = (int) cfp->channel;
}
- /*
- * Setting by channel number
- */
+ /* Setting by channel number */
if (fwrq->m > 1000 || fwrq->e > 0) {
- rc = -EOPNOTSUPP;
- } else {
- int channel = fwrq->m;
+ goto out;
+ }
- cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, channel);
- if (!cfp) {
- rc = -EINVAL;
- } else {
- if (adapter->mode == IW_MODE_ADHOC) {
- rc = changeadhocchannel(priv, channel);
- /* If station is WEP enabled, send the
- * command to set WEP in firmware
- */
- if (adapter->secinfo.wep_enabled) {
- lbs_pr_debug(1, "set_freq: WEP enabled\n");
- ret = libertas_prepare_and_send_command(priv,
- cmd_802_11_set_wep,
- cmd_act_add,
- cmd_option_waitforrsp,
- 0,
- NULL);
-
- if (ret) {
- LEAVE();
- return ret;
- }
-
- adapter->currentpacketfilter |=
- cmd_act_mac_wep_enable;
-
- libertas_set_mac_packet_filter(priv);
- }
- } else {
- rc = -EOPNOTSUPP;
- }
- }
+ cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m);
+ if (!cfp) {
+ goto out;
}
- LEAVE();
- return rc;
+ assoc_req->channel = fwrq->m;
+ ret = 0;
+
+out:
+ if (ret == 0) {
+ set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
+ wlan_postpone_association_work(priv);
+ } else {
+ wlan_cancel_association_work(priv);
+ }
+ mutex_unlock(&adapter->lock);
+
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
/**
@@ -1338,9 +1123,9 @@ static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
u8 rates[WLAN_SUPPORTED_RATES];
u8 *rate;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
- lbs_pr_debug(1, "Vwrq->value = %d\n", vwrq->value);
+ lbs_deb_wext("vwrq->value %d\n", vwrq->value);
if (vwrq->value == -1) {
action = cmd_act_set_tx_auto; // Auto
@@ -1357,15 +1142,15 @@ static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
get_active_data_rates(adapter, rates);
rate = rates;
while (*rate) {
- lbs_pr_debug(1, "Rate=0x%X Wanted=0x%X\n", *rate,
+ lbs_deb_wext("rate=0x%X, wanted data_rate 0x%X\n", *rate,
data_rate);
if ((*rate & 0x7f) == (data_rate & 0x7f))
break;
rate++;
}
if (!*rate) {
- lbs_pr_alert( "The fixed data rate 0x%X is out "
- "of range.\n", data_rate);
+ lbs_pr_alert("fixed data rate 0x%X out "
+ "of range\n", data_rate);
return -EINVAL;
}
@@ -1377,7 +1162,7 @@ static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
ret = libertas_prepare_and_send_command(priv, cmd_802_11_data_rate,
action, cmd_option_waitforrsp, 0, NULL);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1387,7 +1172,7 @@ static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (adapter->is_datarate_auto) {
vwrq->fixed = 0;
@@ -1397,7 +1182,7 @@ static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
vwrq->value = adapter->datarate * 500000;
- LEAVE();
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -1409,12 +1194,12 @@ static int wlan_set_mode(struct net_device *dev,
wlan_adapter *adapter = priv->adapter;
struct assoc_request * assoc_req;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if ( (*uwrq != IW_MODE_ADHOC)
&& (*uwrq != IW_MODE_INFRA)
&& (*uwrq != IW_MODE_AUTO)) {
- lbs_pr_debug(1, "Invalid mode: 0x%x\n", *uwrq);
+ lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq);
ret = -EINVAL;
goto out;
}
@@ -1428,12 +1213,12 @@ static int wlan_set_mode(struct net_device *dev,
assoc_req->mode = *uwrq;
set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
wlan_postpone_association_work(priv);
- lbs_pr_debug(1, "Switching to mode: 0x%x\n", *uwrq);
+ lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
}
mutex_unlock(&adapter->lock);
out:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1455,9 +1240,9 @@ static int wlan_get_encode(struct net_device *dev,
wlan_adapter *adapter = priv->adapter;
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
- lbs_pr_debug(1, "flags=0x%x index=%d length=%d wep_tx_keyidx=%d\n",
+ lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n",
dwrq->flags, index, dwrq->length, adapter->wep_tx_keyidx);
dwrq->flags = 0;
@@ -1513,13 +1298,13 @@ static int wlan_get_encode(struct net_device *dev,
dwrq->flags |= IW_ENCODE_NOKEY;
- lbs_pr_debug(1, "key:%02x:%02x:%02x:%02x:%02x:%02x keylen=%d\n",
+ lbs_deb_wext("key: " MAC_FMT ", keylen %d\n",
extra[0], extra[1], extra[2],
extra[3], extra[4], extra[5], dwrq->length);
- lbs_pr_debug(1, "Return flags=0x%x\n", dwrq->flags);
+ lbs_deb_wext("return flags 0x%x\n", dwrq->flags);
- LEAVE();
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -1539,20 +1324,21 @@ static int wlan_set_wep_key(struct assoc_request *assoc_req,
u16 index,
int set_tx_key)
{
+ int ret = 0;
struct WLAN_802_11_KEY *pkey;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
/* Paranoid validation of key index */
if (index > 3) {
- LEAVE();
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
/* validate max key length */
if (key_length > KEY_LEN_WEP_104) {
- LEAVE();
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
pkey = &assoc_req->wep_keys[index];
@@ -1570,17 +1356,18 @@ static int wlan_set_wep_key(struct assoc_request *assoc_req,
if (set_tx_key) {
/* Ensure the chosen key is valid */
if (!pkey->len) {
- lbs_pr_debug(1, "key not set, so cannot enable it\n");
- LEAVE();
- return -EINVAL;
+ lbs_deb_wext("key not set, so cannot enable it\n");
+ ret = -EINVAL;
+ goto out;
}
assoc_req->wep_tx_keyidx = index;
}
assoc_req->secinfo.wep_enabled = 1;
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
static int validate_key_index(u16 def_index, u16 raw_index,
@@ -1605,6 +1392,8 @@ static void disable_wep(struct assoc_request *assoc_req)
{
int i;
+ lbs_deb_enter(LBS_DEB_WEXT);
+
/* Set Open System auth mode */
assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
@@ -1615,6 +1404,27 @@ static void disable_wep(struct assoc_request *assoc_req)
set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
+
+ lbs_deb_leave(LBS_DEB_WEXT);
+}
+
+static void disable_wpa(struct assoc_request *assoc_req)
+{
+ lbs_deb_enter(LBS_DEB_WEXT);
+
+ memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct WLAN_802_11_KEY));
+ assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
+ set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
+
+ memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct WLAN_802_11_KEY));
+ assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
+ set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
+
+ assoc_req->secinfo.WPAenabled = 0;
+ assoc_req->secinfo.WPA2enabled = 0;
+ set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
+
+ lbs_deb_leave(LBS_DEB_WEXT);
}
/**
@@ -1636,7 +1446,7 @@ static int wlan_set_encode(struct net_device *dev,
struct assoc_request * assoc_req;
u16 is_default = 0, index = 0, set_tx_key = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
mutex_lock(&adapter->lock);
assoc_req = wlan_get_association_request(adapter);
@@ -1647,6 +1457,7 @@ static int wlan_set_encode(struct net_device *dev,
if (dwrq->flags & IW_ENCODE_DISABLED) {
disable_wep (assoc_req);
+ disable_wpa (assoc_req);
goto out;
}
@@ -1688,7 +1499,7 @@ out:
}
mutex_unlock(&adapter->lock);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1712,7 +1523,7 @@ static int wlan_get_encodeext(struct net_device *dev,
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int index, max_key_len;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
max_key_len = dwrq->length - sizeof(*ext);
if (max_key_len < 0)
@@ -1748,6 +1559,7 @@ static int wlan_get_encodeext(struct net_device *dev,
if ( adapter->secinfo.wep_enabled
&& !adapter->secinfo.WPAenabled
&& !adapter->secinfo.WPA2enabled) {
+ /* WEP */
ext->alg = IW_ENCODE_ALG_WEP;
ext->key_len = adapter->wep_keys[index].len;
key = &adapter->wep_keys[index].key[0];
@@ -1755,8 +1567,27 @@ static int wlan_get_encodeext(struct net_device *dev,
&& (adapter->secinfo.WPAenabled ||
adapter->secinfo.WPA2enabled)) {
/* WPA */
- ext->alg = IW_ENCODE_ALG_TKIP;
- ext->key_len = 0;
+ struct WLAN_802_11_KEY * pkey = NULL;
+
+ if ( adapter->wpa_mcast_key.len
+ && (adapter->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
+ pkey = &adapter->wpa_mcast_key;
+ else if ( adapter->wpa_unicast_key.len
+ && (adapter->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
+ pkey = &adapter->wpa_unicast_key;
+
+ if (pkey) {
+ if (pkey->type == KEY_TYPE_ID_AES) {
+ ext->alg = IW_ENCODE_ALG_CCMP;
+ } else {
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ }
+ ext->key_len = pkey->len;
+ key = &pkey->key[0];
+ } else {
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ ext->key_len = 0;
+ }
} else {
goto out;
}
@@ -1775,7 +1606,7 @@ static int wlan_get_encodeext(struct net_device *dev,
ret = 0;
out:
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1800,7 +1631,7 @@ static int wlan_set_encodeext(struct net_device *dev,
int alg = ext->alg;
struct assoc_request * assoc_req;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
mutex_lock(&adapter->lock);
assoc_req = wlan_get_association_request(adapter);
@@ -1811,6 +1642,7 @@ static int wlan_set_encodeext(struct net_device *dev,
if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
disable_wep (assoc_req);
+ disable_wpa (assoc_req);
} else if (alg == IW_ENCODE_ALG_WEP) {
u16 is_default = 0, index, set_tx_key = 0;
@@ -1846,7 +1678,6 @@ static int wlan_set_encodeext(struct net_device *dev,
set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
if (set_tx_key)
set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
-
} else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
struct WLAN_802_11_KEY * pkey;
@@ -1855,36 +1686,43 @@ static int wlan_set_encodeext(struct net_device *dev,
&& (ext->key_len != KEY_LEN_WPA_TKIP))
|| ((alg == IW_ENCODE_ALG_CCMP)
&& (ext->key_len != KEY_LEN_WPA_AES))) {
- lbs_pr_debug(1, "Invalid size %d for key of alg"
- "type %d.\n",
+ lbs_deb_wext("invalid size %d for key of alg"
+ "type %d\n",
ext->key_len,
alg);
ret = -EINVAL;
goto out;
}
- if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
pkey = &assoc_req->wpa_mcast_key;
- else
+ set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
+ } else {
pkey = &assoc_req->wpa_unicast_key;
+ set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
+ }
memset(pkey, 0, sizeof (struct WLAN_802_11_KEY));
memcpy(pkey->key, ext->key, ext->key_len);
pkey->len = ext->key_len;
- pkey->flags = KEY_INFO_WPA_ENABLED;
+ if (pkey->len)
+ pkey->flags |= KEY_INFO_WPA_ENABLED;
+ /* Do this after zeroing key structure */
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
pkey->flags |= KEY_INFO_WPA_MCAST;
- set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
} else {
pkey->flags |= KEY_INFO_WPA_UNICAST;
- set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
}
- if (alg == IW_ENCODE_ALG_TKIP)
+ if (alg == IW_ENCODE_ALG_TKIP) {
pkey->type = KEY_TYPE_ID_TKIP;
- else if (alg == IW_ENCODE_ALG_CCMP)
+ } else if (alg == IW_ENCODE_ALG_CCMP) {
pkey->type = KEY_TYPE_ID_AES;
+ } else {
+ ret = -EINVAL;
+ goto out;
+ }
/* If WPA isn't enabled yet, do that now */
if ( assoc_req->secinfo.WPAenabled == 0
@@ -1905,7 +1743,7 @@ out:
}
mutex_unlock(&adapter->lock);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1920,7 +1758,7 @@ static int wlan_set_genie(struct net_device *dev,
int ret = 0;
struct assoc_request * assoc_req;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
mutex_lock(&adapter->lock);
assoc_req = wlan_get_association_request(adapter);
@@ -1952,7 +1790,7 @@ out:
}
mutex_unlock(&adapter->lock);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1961,27 +1799,28 @@ static int wlan_get_genie(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
+ int ret = 0;
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (adapter->wpa_ie_len == 0) {
dwrq->length = 0;
- LEAVE();
- return 0;
+ goto out;
}
if (dwrq->length < adapter->wpa_ie_len) {
- LEAVE();
- return -E2BIG;
+ ret = -E2BIG;
+ goto out;
}
dwrq->length = adapter->wpa_ie_len;
memcpy(extra, &adapter->wpa_ie[0], adapter->wpa_ie_len);
- LEAVE();
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
@@ -1996,7 +1835,7 @@ static int wlan_set_auth(struct net_device *dev,
int ret = 0;
int updated = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
mutex_lock(&adapter->lock);
assoc_req = wlan_get_association_request(adapter);
@@ -2010,6 +1849,7 @@ static int wlan_set_auth(struct net_device *dev,
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_KEY_MGMT:
+ case IW_AUTH_DROP_UNENCRYPTED:
/*
* libertas does not use these parameters
*/
@@ -2019,6 +1859,7 @@ static int wlan_set_auth(struct net_device *dev,
if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0;
+ disable_wpa (assoc_req);
}
if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
assoc_req->secinfo.WPAenabled = 1;
@@ -2033,17 +1874,6 @@ static int wlan_set_auth(struct net_device *dev,
updated = 1;
break;
- case IW_AUTH_DROP_UNENCRYPTED:
- if (dwrq->value) {
- adapter->currentpacketfilter |=
- cmd_act_mac_strict_protection_enable;
- } else {
- adapter->currentpacketfilter &=
- ~cmd_act_mac_strict_protection_enable;
- }
- updated = 1;
- break;
-
case IW_AUTH_80211_AUTH_ALG:
if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
@@ -2069,6 +1899,7 @@ static int wlan_set_auth(struct net_device *dev,
} else {
assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0;
+ disable_wpa (assoc_req);
}
updated = 1;
break;
@@ -2088,7 +1919,7 @@ out:
}
mutex_unlock(&adapter->lock);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -2097,10 +1928,11 @@ static int wlan_get_auth(struct net_device *dev,
struct iw_param *dwrq,
char *extra)
{
+ int ret = 0;
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
switch (dwrq->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
@@ -2113,13 +1945,6 @@ static int wlan_get_auth(struct net_device *dev,
dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
break;
- case IW_AUTH_DROP_UNENCRYPTED:
- dwrq->value = 0;
- if (adapter->currentpacketfilter &
- cmd_act_mac_strict_protection_enable)
- dwrq->value = 1;
- break;
-
case IW_AUTH_80211_AUTH_ALG:
dwrq->value = adapter->secinfo.auth_mode;
break;
@@ -2130,12 +1955,11 @@ static int wlan_get_auth(struct net_device *dev,
break;
default:
- LEAVE();
- return -EOPNOTSUPP;
+ ret = -EOPNOTSUPP;
}
- LEAVE();
- return 0;
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
}
@@ -2148,7 +1972,7 @@ static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
u16 dbm;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
wlan_radio_ioctl(priv, RADIO_OFF);
@@ -2169,14 +1993,14 @@ static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
if (vwrq->fixed == 0)
dbm = 0xffff;
- lbs_pr_debug(1, "<1>TXPOWER SET %d dbm.\n", dbm);
+ lbs_deb_wext("txpower set %d dbm\n", dbm);
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_rf_tx_power,
cmd_act_tx_power_opt_set_low,
cmd_option_waitforrsp, 0, (void *)&dbm);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -2186,7 +2010,8 @@ static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
+
/*
* Note : if dwrq->flags != 0, we should get the relevant SSID from
* the SSID list...
@@ -2196,12 +2021,12 @@ static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
* Get the current SSID
*/
if (adapter->connect_status == libertas_connected) {
- memcpy(extra, adapter->curbssparams.ssid.ssid,
- adapter->curbssparams.ssid.ssidlength);
- extra[adapter->curbssparams.ssid.ssidlength] = '\0';
+ memcpy(extra, adapter->curbssparams.ssid,
+ adapter->curbssparams.ssid_len);
+ extra[adapter->curbssparams.ssid_len] = '\0';
} else {
memset(extra, 0, 32);
- extra[adapter->curbssparams.ssid.ssidlength] = '\0';
+ extra[adapter->curbssparams.ssid_len] = '\0';
}
/*
* If none, we may want to get the one that was set
@@ -2209,14 +2034,14 @@ static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
/* To make the driver backward compatible with WPA supplicant v0.2.4 */
if (dwrq->length == 32) /* check with WPA supplicant buffer size */
- dwrq->length = min_t(size_t, adapter->curbssparams.ssid.ssidlength,
+ dwrq->length = min_t(size_t, adapter->curbssparams.ssid_len,
IW_ESSID_MAX_SIZE);
else
- dwrq->length = adapter->curbssparams.ssid.ssidlength + 1;
+ dwrq->length = adapter->curbssparams.ssid_len + 1;
dwrq->flags = 1; /* active */
- LEAVE();
+ lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
@@ -2226,38 +2051,43 @@ static int wlan_set_essid(struct net_device *dev, struct iw_request_info *info,
wlan_private *priv = dev->priv;
wlan_adapter *adapter = priv->adapter;
int ret = 0;
- struct WLAN_802_11_SSID ssid;
+ u8 ssid[IW_ESSID_MAX_SIZE];
+ u8 ssid_len = 0;
struct assoc_request * assoc_req;
- int ssid_len = dwrq->length;
+ int in_ssid_len = dwrq->length;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
/*
* WE-20 and earlier NULL pad the end of the SSID and increment
* SSID length so it can be used like a string. WE-21 and later don't,
* but some userspace tools aren't able to cope with the change.
*/
- if ((ssid_len > 0) && (extra[ssid_len - 1] == '\0'))
- ssid_len--;
+ if ((in_ssid_len > 0) && (extra[in_ssid_len - 1] == '\0'))
+ in_ssid_len--;
/* Check the size of the string */
- if (ssid_len > IW_ESSID_MAX_SIZE) {
+ if (in_ssid_len > IW_ESSID_MAX_SIZE) {
ret = -E2BIG;
goto out;
}
- memset(&ssid, 0, sizeof(struct WLAN_802_11_SSID));
+ memset(&ssid, 0, sizeof(ssid));
- if (!dwrq->flags || !ssid_len) {
+ if (!dwrq->flags || !in_ssid_len) {
/* "any" SSID requested; leave SSID blank */
} else {
/* Specific SSID requested */
- memcpy(&ssid.ssid, extra, ssid_len);
- ssid.ssidlength = ssid_len;
+ memcpy(&ssid, extra, in_ssid_len);
+ ssid_len = in_ssid_len;
}
- lbs_pr_debug(1, "Requested new SSID = %s\n",
- (ssid.ssidlength > 0) ? (char *)ssid.ssid : "any");
+ if (!ssid_len) {
+ lbs_deb_wext("requested any SSID\n");
+ } else {
+ lbs_deb_wext("requested SSID '%s'\n",
+ escape_essid(ssid, ssid_len));
+ }
out:
mutex_lock(&adapter->lock);
@@ -2268,7 +2098,8 @@ out:
ret = -ENOMEM;
} else {
/* Copy the SSID to the association request */
- memcpy(&assoc_req->ssid, &ssid, sizeof(struct WLAN_802_11_SSID));
+ memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
+ assoc_req->ssid_len = ssid_len;
set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
wlan_postpone_association_work(priv);
}
@@ -2281,7 +2112,7 @@ out:
mutex_unlock(&adapter->lock);
- LEAVE();
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -2302,12 +2133,12 @@ static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info,
struct assoc_request * assoc_req;
int ret = 0;
- ENTER();
+ lbs_deb_enter(LBS_DEB_WEXT);
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
- lbs_pr_debug(1, "ASSOC: WAP: sa_data: " MAC_FMT "\n", MAC_ARG(awrq->sa_data));
+ lbs_deb_wext("ASSOC: WAP: sa_data " MAC_FMT "\n", MAC_ARG(awrq->sa_data));
mutex_lock(&adapter->lock);
@@ -2330,22 +2161,23 @@ static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info,
void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen)
{
- union {
- u32 l;
- u8 c[4];
- } ver;
char fwver[32];
mutex_lock(&adapter->lock);
- ver.l = adapter->fwreleasenumber;
- mutex_unlock(&adapter->lock);
- if (ver.c[3] == 0)
- sprintf(fwver, "%u.%u.%u", ver.c[2], ver.c[1], ver.c[0]);
+ if (adapter->fwreleasenumber[3] == 0)
+ sprintf(fwver, "%u.%u.%u",
+ adapter->fwreleasenumber[2],
+ adapter->fwreleasenumber[1],
+ adapter->fwreleasenumber[0]);
else
sprintf(fwver, "%u.%u.%u.p%u",
- ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
+ adapter->fwreleasenumber[2],
+ adapter->fwreleasenumber[1],
+ adapter->fwreleasenumber[0],
+ adapter->fwreleasenumber[3]);
+ mutex_unlock(&adapter->lock);
snprintf(fwversion, maxlen, fwver);
}
@@ -2411,13 +2243,71 @@ static const iw_handler wlan_handler[] = {
(iw_handler) NULL, /* SIOCSIWPMKSA */
};
+static const iw_handler mesh_wlan_handler[] = {
+ (iw_handler) NULL, /* SIOCSIWCOMMIT */
+ (iw_handler) wlan_get_name, /* SIOCGIWNAME */
+ (iw_handler) NULL, /* SIOCSIWNWID */
+ (iw_handler) NULL, /* SIOCGIWNWID */
+ (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */
+ (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */
+ (iw_handler) NULL, /* SIOCSIWMODE */
+ (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */
+ (iw_handler) NULL, /* SIOCSIWSENS */
+ (iw_handler) NULL, /* SIOCGIWSENS */
+ (iw_handler) NULL, /* SIOCSIWRANGE */
+ (iw_handler) wlan_get_range, /* SIOCGIWRANGE */
+ (iw_handler) NULL, /* SIOCSIWPRIV */
+ (iw_handler) NULL, /* SIOCGIWPRIV */
+ (iw_handler) NULL, /* SIOCSIWSTATS */
+ (iw_handler) NULL, /* SIOCGIWSTATS */
+ iw_handler_set_spy, /* SIOCSIWSPY */
+ iw_handler_get_spy, /* SIOCGIWSPY */
+ iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
+ iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
+ (iw_handler) NULL, /* SIOCSIWAP */
+ (iw_handler) NULL, /* SIOCGIWAP */
+ (iw_handler) NULL, /* SIOCSIWMLME */
+ (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
+ (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */
+ (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) NULL, /* SIOCSIWESSID */
+ (iw_handler) NULL, /* SIOCGIWESSID */
+ (iw_handler) NULL, /* SIOCSIWNICKN */
+ (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) wlan_set_rate, /* SIOCSIWRATE */
+ (iw_handler) wlan_get_rate, /* SIOCGIWRATE */
+ (iw_handler) wlan_set_rts, /* SIOCSIWRTS */
+ (iw_handler) wlan_get_rts, /* SIOCGIWRTS */
+ (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */
+ (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */
+ (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */
+ (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */
+ (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */
+ (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */
+ (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */
+ (iw_handler) wlan_set_power, /* SIOCSIWPOWER */
+ (iw_handler) wlan_get_power, /* SIOCGIWPOWER */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */
+ (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */
+ (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */
+ (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */
+ (iw_handler) NULL, /* SIOCSIWPMKSA */
+};
struct iw_handler_def libertas_handler_def = {
.num_standard = sizeof(wlan_handler) / sizeof(iw_handler),
- .num_private = sizeof(wlan_private_handler) / sizeof(iw_handler),
- .num_private_args = sizeof(wlan_private_args) /
- sizeof(struct iw_priv_args),
.standard = (iw_handler *) wlan_handler,
- .private = (iw_handler *) wlan_private_handler,
- .private_args = (struct iw_priv_args *)wlan_private_args,
+ .get_wireless_stats = wlan_get_wireless_stats,
+};
+
+struct iw_handler_def mesh_handler_def = {
+ .num_standard = sizeof(mesh_wlan_handler) / sizeof(iw_handler),
+ .standard = (iw_handler *) mesh_wlan_handler,
.get_wireless_stats = wlan_get_wireless_stats,
};
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
index 15cfaaf0797..3d5196c9553 100644
--- a/drivers/net/wireless/libertas/wext.h
+++ b/drivers/net/wireless/libertas/wext.h
@@ -7,43 +7,6 @@
#define SUBCMD_OFFSET 4
#define SUBCMD_DATA(x) *((int *)(x->u.name + SUBCMD_OFFSET))
-/** PRIVATE CMD ID */
-#define WLANIOCTL SIOCIWFIRSTPRIV
-
-#define WLAN_SETNONE_GETNONE (WLANIOCTL + 8)
-#define WLAN_SUBCMD_BT_RESET 13
-#define WLAN_SUBCMD_FWT_RESET 14
-
-#define WLAN_SETNONE_GETONEINT (WLANIOCTL + 15)
-#define WLANGETREGION 1
-
-#define WLAN_SUBCMD_FWT_CLEANUP 15
-#define WLAN_SUBCMD_FWT_TIME 16
-#define WLAN_SUBCMD_MESH_GET_TTL 17
-
-#define WLAN_SETONEINT_GETNONE (WLANIOCTL + 24)
-#define WLANSETREGION 8
-#define WLAN_SUBCMD_MESH_SET_TTL 18
-
-#define WLAN_SET128CHAR_GET128CHAR (WLANIOCTL + 25)
-#define WLAN_SUBCMD_BT_ADD 18
-#define WLAN_SUBCMD_BT_DEL 19
-#define WLAN_SUBCMD_BT_LIST 20
-#define WLAN_SUBCMD_FWT_ADD 21
-#define WLAN_SUBCMD_FWT_DEL 22
-#define WLAN_SUBCMD_FWT_LOOKUP 23
-#define WLAN_SUBCMD_FWT_LIST_NEIGHBOR 24
-#define WLAN_SUBCMD_FWT_LIST 25
-#define WLAN_SUBCMD_FWT_LIST_ROUTE 26
-
-#define WLAN_SET_GET_SIXTEEN_INT (WLANIOCTL + 29)
-#define WLAN_LED_GPIO_CTRL 5
-
-#define WLAN_LINKMODE_802_3 0
-#define WLAN_LINKMODE_802_11 2
-#define WLAN_RADIOMODE_NONE 0
-#define WLAN_RADIOMODE_RADIOTAP 2
-
/** wlan_ioctl_regrdwr */
struct wlan_ioctl_regrdwr {
/** Which register to access */
@@ -55,8 +18,13 @@ struct wlan_ioctl_regrdwr {
u32 value;
};
+#define WLAN_LINKMODE_802_3 0
+#define WLAN_LINKMODE_802_11 2
+#define WLAN_RADIOMODE_NONE 0
+#define WLAN_RADIOMODE_RADIOTAP 2
+
extern struct iw_handler_def libertas_handler_def;
-int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int i);
+extern struct iw_handler_def mesh_handler_def;
int wlan_radio_ioctl(wlan_private * priv, u8 option);
#endif /* _WLAN_WEXT_H_ */
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index 3dcb13bb7d5..af2e4f2405f 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -87,7 +87,6 @@ static struct pci_driver prism54_driver = {
.remove = prism54_remove,
.suspend = prism54_suspend,
.resume = prism54_resume,
- /* .enable_wake ; we don't support this yet */
};
/******************************************************************************
@@ -167,8 +166,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
/* enable MWI */
- if (!pci_set_mwi(pdev))
- printk(KERN_INFO "%s: pci_set_mwi(pdev) succeeded\n", DRV_NAME);
+ pci_try_set_mwi(pdev);
/* setup the network device interface and its structure */
if (!(ndev = islpci_setup(pdev))) {
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
new file mode 100644
index 00000000000..6124e467b15
--- /dev/null
+++ b/drivers/net/wireless/rtl8187.h
@@ -0,0 +1,145 @@
+/*
+ * Definitions for RTL8187 hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * 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 RTL8187_H
+#define RTL8187_H
+
+#include "rtl818x.h"
+
+#define RTL8187_EEPROM_TXPWR_BASE 0x05
+#define RTL8187_EEPROM_MAC_ADDR 0x07
+#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */
+#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */
+
+#define RTL8187_REQT_READ 0xC0
+#define RTL8187_REQT_WRITE 0x40
+#define RTL8187_REQ_GET_REG 0x05
+#define RTL8187_REQ_SET_REG 0x05
+
+#define RTL8187_MAX_RX 0x9C4
+
+struct rtl8187_rx_info {
+ struct urb *urb;
+ struct ieee80211_hw *dev;
+};
+
+struct rtl8187_rx_hdr {
+ __le16 len;
+ __le16 rate;
+ u8 noise;
+ u8 signal;
+ u8 agc;
+ u8 reserved;
+ __le64 mac_time;
+} __attribute__((packed));
+
+struct rtl8187_tx_info {
+ struct ieee80211_tx_control *control;
+ struct urb *urb;
+ struct ieee80211_hw *dev;
+};
+
+struct rtl8187_tx_hdr {
+ __le32 flags;
+#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15)
+#define RTL8187_TX_FLAG_MORE_FRAG (1 << 17)
+#define RTL8187_TX_FLAG_CTS (1 << 18)
+#define RTL8187_TX_FLAG_RTS (1 << 23)
+ __le16 rts_duration;
+ __le16 len;
+ __le32 retry;
+} __attribute__((packed));
+
+struct rtl8187_priv {
+ /* common between rtl818x drivers */
+ struct rtl818x_csr *map;
+ void (*rf_init)(struct ieee80211_hw *);
+ int mode;
+
+ /* rtl8187 specific */
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+ struct ieee80211_hw_mode modes[2];
+ struct usb_device *udev;
+ u8 *hwaddr;
+ u16 txpwr_base;
+ u8 asic_rev;
+ struct sk_buff_head rx_queue;
+};
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
+
+static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
+{
+ u8 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return val;
+}
+
+static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
+{
+ __le16 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return le16_to_cpu(val);
+}
+
+static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
+{
+ __le32 val;
+
+ usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
+ RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+
+ return le32_to_cpu(val);
+}
+
+static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
+ u8 *addr, u8 val)
+{
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+}
+
+static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
+ __le16 *addr, u16 val)
+{
+ __le16 buf = cpu_to_le16(val);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
+ __le32 *addr, u32 val)
+{
+ __le32 buf = cpu_to_le32(val);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+}
+
+#endif /* RTL8187_H */
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
new file mode 100644
index 00000000000..cea85894b7f
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -0,0 +1,731 @@
+/*
+ * Linux device driver for RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays and register offsets below are taken from the original
+ * r8187 driver sources. Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/eeprom_93cx6.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
+MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
+MODULE_DESCRIPTION("RTL8187 USB wireless driver");
+MODULE_LICENSE("GPL");
+
+static struct usb_device_id rtl8187_table[] __devinitdata = {
+ /* Realtek */
+ {USB_DEVICE(0x0bda, 0x8187)},
+ /* Netgear */
+ {USB_DEVICE(0x0846, 0x6100)},
+ {USB_DEVICE(0x0846, 0x6a00)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(usb, rtl8187_table);
+
+void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ data <<= 8;
+ data |= addr | 0x80;
+
+ rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
+ rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
+
+ msleep(1);
+}
+
+static void rtl8187_tx_cb(struct urb *urb)
+{
+ struct ieee80211_tx_status status = { {0} };
+ struct sk_buff *skb = (struct sk_buff *)urb->context;
+ struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
+
+ usb_free_urb(info->urb);
+ if (info->control)
+ memcpy(&status.control, info->control, sizeof(status.control));
+ kfree(info->control);
+ skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
+ status.flags |= IEEE80211_TX_STATUS_ACK;
+ ieee80211_tx_status_irqsafe(info->dev, skb, &status);
+}
+
+static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_tx_hdr *hdr;
+ struct rtl8187_tx_info *info;
+ struct urb *urb;
+ u32 tmp;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ kfree_skb(skb);
+ return 0;
+ }
+
+ hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ tmp = skb->len - sizeof(*hdr);
+ tmp |= RTL8187_TX_FLAG_NO_ENCRYPT;
+ tmp |= control->rts_cts_rate << 19;
+ tmp |= control->tx_rate << 24;
+ if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb))
+ tmp |= RTL8187_TX_FLAG_MORE_FRAG;
+ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
+ tmp |= RTL8187_TX_FLAG_RTS;
+ hdr->rts_duration =
+ ieee80211_rts_duration(dev, skb->len, control);
+ }
+ if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+ tmp |= RTL8187_TX_FLAG_CTS;
+ hdr->flags = cpu_to_le32(tmp);
+ hdr->len = 0;
+ tmp = control->retry_limit << 8;
+ hdr->retry = cpu_to_le32(tmp);
+
+ info = (struct rtl8187_tx_info *)skb->cb;
+ info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
+ info->urb = urb;
+ info->dev = dev;
+ usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
+ hdr, skb->len, rtl8187_tx_cb, skb);
+ usb_submit_urb(urb, GFP_ATOMIC);
+
+ return 0;
+}
+
+static void rtl8187_rx_cb(struct urb *urb)
+{
+ struct sk_buff *skb = (struct sk_buff *)urb->context;
+ struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
+ struct ieee80211_hw *dev = info->dev;
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_rx_hdr *hdr;
+ struct ieee80211_rx_status rx_status = { 0 };
+ int rate, signal;
+
+ spin_lock(&priv->rx_queue.lock);
+ if (skb->next)
+ __skb_unlink(skb, &priv->rx_queue);
+ else {
+ spin_unlock(&priv->rx_queue.lock);
+ return;
+ }
+ spin_unlock(&priv->rx_queue.lock);
+
+ if (unlikely(urb->status)) {
+ usb_free_urb(urb);
+ dev_kfree_skb_irq(skb);
+ return;
+ }
+
+ skb_put(skb, urb->actual_length);
+ hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
+ skb_trim(skb, le16_to_cpu(hdr->len) & 0x0FFF);
+
+ signal = hdr->agc >> 1;
+ rate = (le16_to_cpu(hdr->rate) >> 4) & 0xF;
+ if (rate > 3) { /* OFDM rate */
+ if (signal > 90)
+ signal = 90;
+ else if (signal < 25)
+ signal = 25;
+ signal = 90 - signal;
+ } else { /* CCK rate */
+ if (signal > 95)
+ signal = 95;
+ else if (signal < 30)
+ signal = 30;
+ signal = 95 - signal;
+ }
+
+ rx_status.antenna = (hdr->signal >> 7) & 1;
+ rx_status.signal = 64 - min(hdr->noise, (u8)64);
+ rx_status.ssi = signal;
+ rx_status.rate = rate;
+ rx_status.freq = dev->conf.freq;
+ rx_status.channel = dev->conf.channel;
+ rx_status.phymode = dev->conf.phymode;
+ rx_status.mactime = le64_to_cpu(hdr->mac_time);
+ ieee80211_rx_irqsafe(dev, skb, &rx_status);
+
+ skb = dev_alloc_skb(RTL8187_MAX_RX);
+ if (unlikely(!skb)) {
+ usb_free_urb(urb);
+ /* TODO check rx queue length and refill *somewhere* */
+ return;
+ }
+
+ info = (struct rtl8187_rx_info *)skb->cb;
+ info->urb = urb;
+ info->dev = dev;
+ urb->transfer_buffer = skb_tail_pointer(skb);
+ urb->context = skb;
+ skb_queue_tail(&priv->rx_queue, skb);
+
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int rtl8187_init_urbs(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct urb *entry;
+ struct sk_buff *skb;
+ struct rtl8187_rx_info *info;
+
+ while (skb_queue_len(&priv->rx_queue) < 8) {
+ skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
+ if (!skb)
+ break;
+ entry = usb_alloc_urb(0, GFP_KERNEL);
+ if (!entry) {
+ kfree_skb(skb);
+ break;
+ }
+ usb_fill_bulk_urb(entry, priv->udev,
+ usb_rcvbulkpipe(priv->udev, 1),
+ skb_tail_pointer(skb),
+ RTL8187_MAX_RX, rtl8187_rx_cb, skb);
+ info = (struct rtl8187_rx_info *)skb->cb;
+ info->urb = entry;
+ info->dev = dev;
+ skb_queue_tail(&priv->rx_queue, skb);
+ usb_submit_urb(entry, GFP_KERNEL);
+ }
+
+ return 0;
+}
+
+static int rtl8187_init_hw(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg;
+ int i;
+
+ /* reset */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+ msleep(200);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11);
+ rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00);
+ msleep(200);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= (1 << 1);
+ reg |= RTL818X_CMD_RESET;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ i = 10;
+ do {
+ msleep(2);
+ if (!(rtl818x_ioread8(priv, &priv->map->CMD) &
+ RTL818X_CMD_RESET))
+ break;
+ } while (--i);
+
+ if (!i) {
+ printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
+ return -ETIMEDOUT;
+ }
+
+ /* reload registers from eeprom */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
+
+ i = 10;
+ do {
+ msleep(4);
+ if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) &
+ RTL818X_EEPROM_CMD_CONFIG))
+ break;
+ } while (--i);
+
+ if (!i) {
+ printk(KERN_ERR "%s: eeprom reset timeout!\n",
+ wiphy_name(dev->wiphy));
+ return -ETIMEDOUT;
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ /* setup card */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 1);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl818x_iowrite8(priv, &priv->map->MAC[i], priv->hwaddr[i]);
+
+ rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG1);
+ reg &= 0x3F;
+ reg |= 0x80;
+ rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+ rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
+ rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+
+ // TODO: set RESP_RATE and BRSR properly
+ rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+
+ /* host_usb_init */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0);
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0);
+ reg = rtl818x_ioread8(priv, (u8 *)0xFE53);
+ rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8));
+ rtl818x_iowrite8(priv, &priv->map->GPIO, 0x20);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80);
+ msleep(100);
+
+ rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+ rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
+ msleep(100);
+
+ priv->rf_init(dev);
+
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+ reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
+ rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
+ rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
+ rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+
+ return 0;
+}
+
+static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
+{
+ u32 reg;
+ struct rtl8187_priv *priv = dev->priv;
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ /* Enable TX loopback on MAC level to avoid TX during channel
+ * changes, as this has be seen to causes problems and the
+ * card will stop work until next reset
+ */
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+ reg | RTL818X_TX_CONF_LOOPBACK_MAC);
+ msleep(10);
+ rtl8225_rf_set_channel(dev, channel);
+ msleep(10);
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+}
+
+static int rtl8187_open(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u32 reg;
+ int ret;
+
+ ret = rtl8187_init_hw(dev);
+ if (ret)
+ return ret;
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+
+ rtl8187_init_urbs(dev);
+
+ reg = RTL818X_RX_CONF_ONLYERLPKT |
+ RTL818X_RX_CONF_RX_AUTORESETPHY |
+ RTL818X_RX_CONF_BSSID |
+ RTL818X_RX_CONF_MGMT |
+ RTL818X_RX_CONF_CTRL |
+ RTL818X_RX_CONF_DATA |
+ (7 << 13 /* RX FIFO threshold NONE */) |
+ (7 << 10 /* MAX RX DMA */) |
+ RTL818X_RX_CONF_BROADCAST |
+ RTL818X_RX_CONF_MULTICAST |
+ RTL818X_RX_CONF_NICMAC;
+ if (priv->mode == IEEE80211_IF_TYPE_MNTR)
+ reg |= RTL818X_RX_CONF_MONITOR;
+
+ rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
+ reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
+ reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+ rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+ reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
+ rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
+
+ reg = RTL818X_TX_CONF_CW_MIN |
+ (7 << 21 /* MAX TX DMA */) |
+ RTL818X_TX_CONF_NO_ICV;
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg |= RTL818X_CMD_TX_ENABLE;
+ reg |= RTL818X_CMD_RX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ return 0;
+}
+
+static int rtl8187_stop(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct rtl8187_rx_info *info;
+ struct sk_buff *skb;
+ u32 reg;
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= ~RTL818X_CMD_TX_ENABLE;
+ reg &= ~RTL818X_CMD_RX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ rtl8225_rf_stop(dev);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ while ((skb = skb_dequeue(&priv->rx_queue))) {
+ info = (struct rtl8187_rx_info *)skb->cb;
+ usb_kill_urb(info->urb);
+ kfree_skb(skb);
+ }
+ return 0;
+}
+
+static int rtl8187_add_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ /* NOTE: using IEEE80211_IF_TYPE_MGMT to indicate no mode selected */
+ if (priv->mode != IEEE80211_IF_TYPE_MGMT)
+ return -1;
+
+ switch (conf->type) {
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_MNTR:
+ priv->mode = conf->type;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ priv->hwaddr = conf->mac_addr;
+
+ return 0;
+}
+
+static void rtl8187_remove_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ priv->mode = IEEE80211_IF_TYPE_MGMT;
+}
+
+static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ rtl8187_set_channel(dev, conf->channel);
+
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+
+ if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
+ rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
+ rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
+ rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
+ return 0;
+}
+
+static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
+ struct ieee80211_if_conf *conf)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
+
+ if (is_valid_ether_addr(conf->bssid))
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
+ else
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
+
+ return 0;
+}
+
+static const struct ieee80211_ops rtl8187_ops = {
+ .tx = rtl8187_tx,
+ .open = rtl8187_open,
+ .stop = rtl8187_stop,
+ .add_interface = rtl8187_add_interface,
+ .remove_interface = rtl8187_remove_interface,
+ .config = rtl8187_config,
+ .config_interface = rtl8187_config_interface,
+};
+
+static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+ struct ieee80211_hw *dev = eeprom->data;
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+
+ eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+ eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+ eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+ eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+ struct ieee80211_hw *dev = eeprom->data;
+ struct rtl8187_priv *priv = dev->priv;
+ u8 reg = RTL818X_EEPROM_CMD_PROGRAM;
+
+ if (eeprom->reg_data_in)
+ reg |= RTL818X_EEPROM_CMD_WRITE;
+ if (eeprom->reg_data_out)
+ reg |= RTL818X_EEPROM_CMD_READ;
+ if (eeprom->reg_data_clock)
+ reg |= RTL818X_EEPROM_CMD_CK;
+ if (eeprom->reg_chip_select)
+ reg |= RTL818X_EEPROM_CMD_CS;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+ udelay(10);
+}
+
+static int __devinit rtl8187_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct ieee80211_hw *dev;
+ struct rtl8187_priv *priv;
+ struct eeprom_93cx6 eeprom;
+ struct ieee80211_channel *channel;
+ u16 txpwr, reg;
+ int err, i;
+
+ dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
+ if (!dev) {
+ printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n");
+ return -ENOMEM;
+ }
+
+ priv = dev->priv;
+
+ SET_IEEE80211_DEV(dev, &intf->dev);
+ usb_set_intfdata(intf, dev);
+ priv->udev = udev;
+
+ usb_get_dev(udev);
+
+ skb_queue_head_init(&priv->rx_queue);
+ memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+ memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+ priv->map = (struct rtl818x_csr *)0xFF00;
+ priv->modes[0].mode = MODE_IEEE80211G;
+ priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+ priv->modes[0].rates = priv->rates;
+ priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+ priv->modes[0].channels = priv->channels;
+ priv->modes[1].mode = MODE_IEEE80211B;
+ priv->modes[1].num_rates = 4;
+ priv->modes[1].rates = priv->rates;
+ priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+ priv->modes[1].channels = priv->channels;
+ priv->mode = IEEE80211_IF_TYPE_MGMT;
+ dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_WEP_INCLUDE_IV |
+ IEEE80211_HW_DATA_NULLFUNC_ACK;
+ dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
+ dev->queues = 1;
+ dev->max_rssi = 65;
+ dev->max_signal = 64;
+
+ for (i = 0; i < 2; i++)
+ if ((err = ieee80211_register_hwmode(dev, &priv->modes[i])))
+ goto err_free_dev;
+
+ eeprom.data = dev;
+ eeprom.register_read = rtl8187_eeprom_register_read;
+ eeprom.register_write = rtl8187_eeprom_register_write;
+ if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
+ eeprom.width = PCI_EEPROM_WIDTH_93C66;
+ else
+ eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ udelay(10);
+
+ eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR,
+ (__le16 __force *)dev->wiphy->perm_addr, 3);
+ if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+ printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly "
+ "generated MAC address\n");
+ random_ether_addr(dev->wiphy->perm_addr);
+ }
+
+ channel = priv->channels;
+ for (i = 0; i < 3; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+ for (i = 0; i < 2; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+ for (i = 0; i < 2; i++) {
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+ &txpwr);
+ (*channel++).val = txpwr & 0xFF;
+ (*channel++).val = txpwr >> 8;
+ }
+
+ eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
+ &priv->txpwr_base);
+
+ reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
+ /* 0 means asic B-cut, we should use SW 3 wire
+ * bit-by-bit banging for radio. 1 means we can use
+ * USB specific request to write radio registers */
+ priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
+ rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write(dev, 0, 0x1B7);
+
+ if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
+ priv->rf_init = rtl8225_rf_init;
+ else
+ priv->rf_init = rtl8225z2_rf_init;
+
+ rtl8225_write(dev, 0, 0x0B7);
+
+ err = ieee80211_register_hw(dev);
+ if (err) {
+ printk(KERN_ERR "rtl8187: Cannot register device\n");
+ goto err_free_dev;
+ }
+
+ printk(KERN_INFO "%s: hwaddr " MAC_FMT ", rtl8187 V%d + %s\n",
+ wiphy_name(dev->wiphy), MAC_ARG(dev->wiphy->perm_addr),
+ priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
+ "rtl8225" : "rtl8225z2");
+
+ return 0;
+
+ err_free_dev:
+ ieee80211_free_hw(dev);
+ usb_set_intfdata(intf, NULL);
+ usb_put_dev(udev);
+ return err;
+}
+
+static void __devexit rtl8187_disconnect(struct usb_interface *intf)
+{
+ struct ieee80211_hw *dev = usb_get_intfdata(intf);
+ struct rtl8187_priv *priv;
+
+ if (!dev)
+ return;
+
+ ieee80211_unregister_hw(dev);
+
+ priv = dev->priv;
+ usb_put_dev(interface_to_usbdev(intf));
+ ieee80211_free_hw(dev);
+}
+
+static struct usb_driver rtl8187_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = rtl8187_table,
+ .probe = rtl8187_probe,
+ .disconnect = rtl8187_disconnect,
+};
+
+static int __init rtl8187_init(void)
+{
+ return usb_register(&rtl8187_driver);
+}
+
+static void __exit rtl8187_exit(void)
+{
+ usb_deregister(&rtl8187_driver);
+}
+
+module_init(rtl8187_init);
+module_exit(rtl8187_exit);
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
new file mode 100644
index 00000000000..e25a09f1b06
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -0,0 +1,745 @@
+/*
+ * Radio tuning for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Magic delays, register offsets, and phy value tables below are
+ * taken from the original r8187 driver sources. Thanks to Realtek
+ * for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/usb.h>
+#include <net/mac80211.h>
+
+#include "rtl8187.h"
+#include "rtl8187_rtl8225.h"
+
+static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg84, reg82;
+ u32 bangdata;
+ int i;
+
+ bangdata = (data << 4) | (addr & 0xf);
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
+
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(10);
+
+ for (i = 15; i >= 0; i--) {
+ u16 reg = reg80 | (bangdata & (1 << i)) >> i;
+
+ if (i & 1)
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+
+ if (!(i & 1))
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ msleep(2);
+}
+
+static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg82, reg84;
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+ reg80 &= ~(0x3 << 2);
+ reg84 &= ~0xF;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(10);
+
+ usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
+ RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
+ addr, 0x8225, &data, sizeof(data), HZ / 2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ msleep(2);
+}
+
+void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ if (priv->asic_rev)
+ rtl8225_write_8051(dev, addr, data);
+ else
+ rtl8225_write_bitbang(dev, addr, data);
+}
+
+u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u16 reg80, reg82, reg84, out;
+ int i;
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+
+ reg80 &= ~0xF;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ udelay(4);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ udelay(5);
+
+ for (i = 4; i >= 0; i--) {
+ u16 reg = reg80 | ((addr >> i) & 1);
+
+ if (!(i & 1)) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ udelay(1);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ udelay(2);
+
+ if (i & 1) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ udelay(1);
+ }
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+
+ out = 0;
+ for (i = 11; i >= 0; i--) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(1);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ udelay(2);
+
+ if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
+ out |= 1 << i;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ udelay(2);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 2));
+ udelay(2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
+
+ return out;
+}
+
+static const u16 rtl8225bcd_rxgain[] = {
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static const u8 rtl8225_agc[] = {
+ 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
+ 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+ 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
+ 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+ 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
+ 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+ 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
+ 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+ 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+ 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
+ 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+ 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
+ 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const u8 rtl8225_gain[] = {
+ 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
+ 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
+ 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
+ 0x33, 0x80, 0x79, 0xc5, /* -78dBm */
+ 0x43, 0x78, 0x76, 0xc5, /* -74dBm */
+ 0x53, 0x60, 0x73, 0xc5, /* -70dBm */
+ 0x63, 0x58, 0x70, 0xc5, /* -66dBm */
+};
+
+static const u8 rtl8225_threshold[] = {
+ 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
+};
+
+static const u8 rtl8225_tx_gain_cck_ofdm[] = {
+ 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static const u8 rtl8225_tx_power_cck[] = {
+ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static const u8 rtl8225_tx_power_cck_ch14[] = {
+ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225_tx_power_ofdm[] = {
+ 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static const u32 rtl8225_chan[] = {
+ 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
+ 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
+};
+
+static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ u32 reg;
+ int i;
+
+ cck_power = priv->channels[channel - 1].val & 0xF;
+ ofdm_power = priv->channels[channel - 1].val >> 4;
+
+ cck_power = min(cck_power, (u8)11);
+ ofdm_power = min(ofdm_power, (u8)35);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+ rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
+
+ if (channel == 14)
+ tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
+ else
+ tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ msleep(1); // FIXME: optional?
+
+ /* anaparam2 on */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write_phy_ofdm(dev, 2, 0x42);
+ rtl8225_write_phy_ofdm(dev, 6, 0x00);
+ rtl8225_write_phy_ofdm(dev, 8, 0x00);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+ rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
+
+ tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
+
+ rtl8225_write_phy_ofdm(dev, 5, *tmp);
+ rtl8225_write_phy_ofdm(dev, 7, *tmp);
+
+ msleep(1);
+}
+
+void rtl8225_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ rtl8225_write(dev, 0x0, 0x067); msleep(1);
+ rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+ rtl8225_write(dev, 0x3, 0x441); msleep(1);
+ rtl8225_write(dev, 0x4, 0x486); msleep(1);
+ rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
+ rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
+ rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+ rtl8225_write(dev, 0x8, 0x01F); msleep(1);
+ rtl8225_write(dev, 0x9, 0x334); msleep(1);
+ rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
+ rtl8225_write(dev, 0xB, 0x391); msleep(1);
+ rtl8225_write(dev, 0xC, 0x050); msleep(1);
+ rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
+ rtl8225_write(dev, 0xE, 0x029); msleep(1);
+ rtl8225_write(dev, 0xF, 0x914); msleep(100);
+
+ rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(200);
+
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0c4d);
+ msleep(200);
+ rtl8225_write(dev, 0x02, 0x044d);
+ msleep(100);
+ if (!(rtl8225_read(dev, 6) & (1 << 7)))
+ printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+ wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+ }
+
+ rtl8225_write(dev, 0x0, 0x127);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x0, 0x027);
+ rtl8225_write(dev, 0x0, 0x22F);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ msleep(1);
+ }
+
+ msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+ rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+ rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
+
+ rtl8225_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ msleep(1);
+ rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+
+ /* set sensitivity */
+ rtl8225_write(dev, 0x0c, 0x50);
+ rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
+ rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
+ rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
+}
+
+static const u8 rtl8225z2_tx_power_cck_ch14[] = {
+ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225z2_tx_power_cck[] = {
+ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_ofdm[] = {
+ 0x42, 0x00, 0x40, 0x00, 0x40
+};
+
+static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
+ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
+};
+
+static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ u32 reg;
+ int i;
+
+ cck_power = priv->channels[channel - 1].val & 0xF;
+ ofdm_power = priv->channels[channel - 1].val >> 4;
+
+ cck_power = min(cck_power, (u8)15);
+ cck_power += priv->txpwr_base & 0xF;
+ cck_power = min(cck_power, (u8)35);
+
+ ofdm_power = min(ofdm_power, (u8)15);
+ ofdm_power += priv->txpwr_base >> 4;
+ ofdm_power = min(ofdm_power, (u8)35);
+
+ if (channel == 14)
+ tmp = rtl8225z2_tx_power_cck_ch14;
+ else
+ tmp = rtl8225z2_tx_power_cck;
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+ rtl8225z2_tx_gain_cck_ofdm[cck_power]);
+ msleep(1);
+
+ /* anaparam2 on */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write_phy_ofdm(dev, 2, 0x42);
+ rtl8225_write_phy_ofdm(dev, 5, 0x00);
+ rtl8225_write_phy_ofdm(dev, 6, 0x40);
+ rtl8225_write_phy_ofdm(dev, 7, 0x00);
+ rtl8225_write_phy_ofdm(dev, 8, 0x40);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+ rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
+ msleep(1);
+}
+
+static const u16 rtl8225z2_rxgain[] = {
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static const u8 rtl8225z2_gain_bg[] = {
+ 0x23, 0x15, 0xa5, /* -82-1dBm */
+ 0x23, 0x15, 0xb5, /* -82-2dBm */
+ 0x23, 0x15, 0xc5, /* -82-3dBm */
+ 0x33, 0x15, 0xc5, /* -78dBm */
+ 0x43, 0x15, 0xc5, /* -74dBm */
+ 0x53, 0x15, 0xc5, /* -70dBm */
+ 0x63, 0x15, 0xc5 /* -66dBm */
+};
+
+void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ int i;
+
+ rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
+ rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+ rtl8225_write(dev, 0x3, 0x441); msleep(1);
+ rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
+ rtl8225_write(dev, 0x5, 0xC72); msleep(1);
+ rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
+ rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+ rtl8225_write(dev, 0x8, 0x03F); msleep(1);
+ rtl8225_write(dev, 0x9, 0x335); msleep(1);
+ rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
+ rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
+ rtl8225_write(dev, 0xc, 0x850); msleep(1);
+ rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
+ rtl8225_write(dev, 0xe, 0x02B); msleep(1);
+ rtl8225_write(dev, 0xf, 0x114); msleep(100);
+
+ rtl8225_write(dev, 0x0, 0x1B7);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x3, 0x080);
+ rtl8225_write(dev, 0x5, 0x004);
+ rtl8225_write(dev, 0x0, 0x0B7);
+ rtl8225_write(dev, 0x2, 0xc4D);
+
+ msleep(200);
+ rtl8225_write(dev, 0x2, 0x44D);
+ msleep(100);
+
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0C4D);
+ msleep(200);
+ rtl8225_write(dev, 0x02, 0x044D);
+ msleep(100);
+ if (!(rtl8225_read(dev, 6) & (1 << 7)))
+ printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
+ wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+ }
+
+ msleep(200);
+
+ rtl8225_write(dev, 0x0, 0x2BF);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ msleep(1);
+ }
+
+ msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+ rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
+
+ rtl8225z2_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ msleep(1);
+ rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
+}
+
+void rtl8225_rf_stop(struct ieee80211_hw *dev)
+{
+ u8 reg;
+ struct rtl8187_priv *priv = dev->priv;
+
+ rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ if (priv->rf_init == rtl8225_rf_init)
+ rtl8225_rf_set_tx_power(dev, channel);
+ else
+ rtl8225z2_rf_set_tx_power(dev, channel);
+
+ rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
+ msleep(10);
+}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
new file mode 100644
index 00000000000..798ba4a9737
--- /dev/null
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -0,0 +1,44 @@
+/*
+ * Radio tuning definitions for RTL8225 on RTL8187
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * 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 RTL8187_RTL8225_H
+#define RTL8187_RTL8225_H
+
+#define RTL8225_ANAPARAM_ON 0xa0000a59
+#define RTL8225_ANAPARAM2_ON 0x860c7312
+#define RTL8225_ANAPARAM_OFF 0xa00beb59
+#define RTL8225_ANAPARAM2_OFF 0x840dec11
+
+void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
+u16 rtl8225_read(struct ieee80211_hw *, u8 addr);
+
+void rtl8225_rf_init(struct ieee80211_hw *);
+void rtl8225z2_rf_init(struct ieee80211_hw *);
+void rtl8225_rf_stop(struct ieee80211_hw *);
+void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
+
+
+static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
+ u8 addr, u32 data)
+{
+ rtl8187_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
+ u8 addr, u32 data)
+{
+ rtl8187_write_phy(dev, addr, data | 0x10000);
+}
+
+#endif /* RTL8187_RTL8225_H */
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
new file mode 100644
index 00000000000..283de30628e
--- /dev/null
+++ b/drivers/net/wireless/rtl818x.h
@@ -0,0 +1,226 @@
+/*
+ * Definitions for RTL818x hardware
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8187 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * 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 RTL818X_H
+#define RTL818X_H
+
+struct rtl818x_csr {
+ u8 MAC[6];
+ u8 reserved_0[2];
+ __le32 MAR[2];
+ u8 RX_FIFO_COUNT;
+ u8 reserved_1;
+ u8 TX_FIFO_COUNT;
+ u8 BQREQ;
+ u8 reserved_2[4];
+ __le32 TSFT[2];
+ __le32 TLPDA;
+ __le32 TNPDA;
+ __le32 THPDA;
+ __le16 BRSR;
+ u8 BSSID[6];
+ u8 RESP_RATE;
+ u8 EIFS;
+ u8 reserved_3[1];
+ u8 CMD;
+#define RTL818X_CMD_TX_ENABLE (1 << 2)
+#define RTL818X_CMD_RX_ENABLE (1 << 3)
+#define RTL818X_CMD_RESET (1 << 4)
+ u8 reserved_4[4];
+ __le16 INT_MASK;
+ __le16 INT_STATUS;
+#define RTL818X_INT_RX_OK (1 << 0)
+#define RTL818X_INT_RX_ERR (1 << 1)
+#define RTL818X_INT_TXL_OK (1 << 2)
+#define RTL818X_INT_TXL_ERR (1 << 3)
+#define RTL818X_INT_RX_DU (1 << 4)
+#define RTL818X_INT_RX_FO (1 << 5)
+#define RTL818X_INT_TXN_OK (1 << 6)
+#define RTL818X_INT_TXN_ERR (1 << 7)
+#define RTL818X_INT_TXH_OK (1 << 8)
+#define RTL818X_INT_TXH_ERR (1 << 9)
+#define RTL818X_INT_TXB_OK (1 << 10)
+#define RTL818X_INT_TXB_ERR (1 << 11)
+#define RTL818X_INT_ATIM (1 << 12)
+#define RTL818X_INT_BEACON (1 << 13)
+#define RTL818X_INT_TIME_OUT (1 << 14)
+#define RTL818X_INT_TX_FO (1 << 15)
+ __le32 TX_CONF;
+#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17)
+#define RTL818X_TX_CONF_NO_ICV (1 << 19)
+#define RTL818X_TX_CONF_DISCW (1 << 20)
+#define RTL818X_TX_CONF_R8180_ABCD (2 << 25)
+#define RTL818X_TX_CONF_R8180_F (3 << 25)
+#define RTL818X_TX_CONF_R8185_ABC (4 << 25)
+#define RTL818X_TX_CONF_R8185_D (5 << 25)
+#define RTL818X_TX_CONF_HWVER_MASK (7 << 25)
+#define RTL818X_TX_CONF_CW_MIN (1 << 31)
+ __le32 RX_CONF;
+#define RTL818X_RX_CONF_MONITOR (1 << 0)
+#define RTL818X_RX_CONF_NICMAC (1 << 1)
+#define RTL818X_RX_CONF_MULTICAST (1 << 2)
+#define RTL818X_RX_CONF_BROADCAST (1 << 3)
+#define RTL818X_RX_CONF_DATA (1 << 18)
+#define RTL818X_RX_CONF_CTRL (1 << 19)
+#define RTL818X_RX_CONF_MGMT (1 << 20)
+#define RTL818X_RX_CONF_BSSID (1 << 23)
+#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28)
+#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31)
+ __le32 INT_TIMEOUT;
+ __le32 TBDA;
+ u8 EEPROM_CMD;
+#define RTL818X_EEPROM_CMD_READ (1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
+#define RTL818X_EEPROM_CMD_CK (1 << 2)
+#define RTL818X_EEPROM_CMD_CS (1 << 3)
+#define RTL818X_EEPROM_CMD_NORMAL (0 << 6)
+#define RTL818X_EEPROM_CMD_LOAD (1 << 6)
+#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6)
+#define RTL818X_EEPROM_CMD_CONFIG (3 << 6)
+ u8 CONFIG0;
+ u8 CONFIG1;
+ u8 CONFIG2;
+ __le32 ANAPARAM;
+ u8 MSR;
+#define RTL818X_MSR_NO_LINK (0 << 2)
+#define RTL818X_MSR_ADHOC (1 << 2)
+#define RTL818X_MSR_INFRA (2 << 2)
+ u8 CONFIG3;
+#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6)
+ u8 CONFIG4;
+#define RTL818X_CONFIG4_POWEROFF (1 << 6)
+#define RTL818X_CONFIG4_VCOOFF (1 << 7)
+ u8 TESTR;
+ u8 reserved_9[2];
+ __le16 PGSELECT;
+ __le32 ANAPARAM2;
+ u8 reserved_10[12];
+ __le16 BEACON_INTERVAL;
+ __le16 ATIM_WND;
+ __le16 BEACON_INTERVAL_TIME;
+ __le16 ATIMTR_INTERVAL;
+ u8 reserved_11[4];
+ u8 PHY[4];
+ __le16 RFPinsOutput;
+ __le16 RFPinsEnable;
+ __le16 RFPinsSelect;
+ __le16 RFPinsInput;
+ __le32 RF_PARA;
+ __le32 RF_TIMING;
+ u8 GP_ENABLE;
+ u8 GPIO;
+ u8 reserved_12[10];
+ u8 TX_AGC_CTL;
+#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0)
+#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1)
+#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2)
+ u8 TX_GAIN_CCK;
+ u8 TX_GAIN_OFDM;
+ u8 TX_ANTENNA;
+ u8 reserved_13[16];
+ u8 WPA_CONF;
+ u8 reserved_14[3];
+ u8 SIFS;
+ u8 DIFS;
+ u8 SLOT;
+ u8 reserved_15[5];
+ u8 CW_CONF;
+#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0)
+#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1)
+ u8 CW_VAL;
+ u8 RATE_FALLBACK;
+ u8 reserved_16[25];
+ u8 CONFIG5;
+ u8 TX_DMA_POLLING;
+ u8 reserved_17[2];
+ __le16 CWR;
+ u8 RETRY_CTR;
+ u8 reserved_18[5];
+ __le32 RDSAR;
+ u8 reserved_19[18];
+ u16 TALLY_CNT;
+ u8 TALLY_SEL;
+} __attribute__((packed));
+
+static const struct ieee80211_rate rtl818x_rates[] = {
+ { .rate = 10,
+ .val = 0,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 20,
+ .val = 1,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 55,
+ .val = 2,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 110,
+ .val = 3,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 60,
+ .val = 4,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 90,
+ .val = 5,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 120,
+ .val = 6,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 180,
+ .val = 7,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 240,
+ .val = 8,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 360,
+ .val = 9,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 480,
+ .val = 10,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 540,
+ .val = 11,
+ .flags = IEEE80211_RATE_OFDM },
+};
+
+static const struct ieee80211_channel rtl818x_channels[] = {
+ { .chan = 1,
+ .freq = 2412},
+ { .chan = 2,
+ .freq = 2417},
+ { .chan = 3,
+ .freq = 2422},
+ { .chan = 4,
+ .freq = 2427},
+ { .chan = 5,
+ .freq = 2432},
+ { .chan = 6,
+ .freq = 2437},
+ { .chan = 7,
+ .freq = 2442},
+ { .chan = 8,
+ .freq = 2447},
+ { .chan = 9,
+ .freq = 2452},
+ { .chan = 10,
+ .freq = 2457},
+ { .chan = 11,
+ .freq = 2462},
+ { .chan = 12,
+ .freq = 2467},
+ { .chan = 13,
+ .freq = 2472},
+ { .chan = 14,
+ .freq = 2484}
+};
+
+#endif /* RTL818X_H */
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index ce9230b2f63..c8b5c227193 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1011,7 +1011,7 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev,
} else {
skb->dev = dev;
skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
- eth_copy_and_sum(skb, (unsigned char *)&sig.daddr, 12, 0);
+ skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12);
wl3501_receive(this, skb->data, pkt_len);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, dev);
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 6603ad5be63..4d505903352 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -3,7 +3,7 @@ obj-$(CONFIG_ZD1211RW) += zd1211rw.o
zd1211rw-objs := zd_chip.o zd_ieee80211.o \
zd_mac.o zd_netdev.o \
zd_rf_al2230.o zd_rf_rf2959.o \
- zd_rf_al7230b.o \
+ zd_rf_al7230b.o zd_rf_uw2453.o \
zd_rf.o zd_usb.o zd_util.o
ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 95b4a2a2670..5b624bfc01a 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1253,6 +1253,9 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
{
int r;
+ if (!zd_rf_should_update_pwr_int(&chip->rf))
+ return 0;
+
r = update_pwr_int(chip, channel);
if (r)
return r;
@@ -1283,7 +1286,7 @@ static int patch_cck_gain(struct zd_chip *chip)
int r;
u32 value;
- if (!chip->patch_cck_gain)
+ if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf))
return 0;
ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ce0a5f6da0d..79d0288c193 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -608,6 +608,9 @@ enum {
#define CR_ZD1211B_TXOP CTL_REG(0x0b20)
#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28)
+/* Used to detect PLL lock */
+#define UW2453_INTR_REG ((zd_addr_t)0x85c1)
+
#define CWIN_SIZE 0x007f043f
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index 549c23bcd6c..7407409b60b 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -52,34 +52,38 @@ const char *zd_rf_name(u8 type)
void zd_rf_init(struct zd_rf *rf)
{
memset(rf, 0, sizeof(*rf));
+
+ /* default to update channel integration, as almost all RF's do want
+ * this */
+ rf->update_channel_int = 1;
}
void zd_rf_clear(struct zd_rf *rf)
{
+ if (rf->clear)
+ rf->clear(rf);
ZD_MEMCLEAR(rf, sizeof(*rf));
}
int zd_rf_init_hw(struct zd_rf *rf, u8 type)
{
- int r, t;
+ int r = 0;
+ int t;
struct zd_chip *chip = zd_rf_to_chip(rf);
ZD_ASSERT(mutex_is_locked(&chip->mutex));
switch (type) {
case RF2959_RF:
r = zd_rf_init_rf2959(rf);
- if (r)
- return r;
break;
case AL2230_RF:
r = zd_rf_init_al2230(rf);
- if (r)
- return r;
break;
case AL7230B_RF:
r = zd_rf_init_al7230b(rf);
- if (r)
- return r;
+ break;
+ case UW2453_RF:
+ r = zd_rf_init_uw2453(rf);
break;
default:
dev_err(zd_chip_dev(chip),
@@ -88,6 +92,9 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type)
return -ENODEV;
}
+ if (r)
+ return r;
+
rf->type = type;
r = zd_chip_lock_phy_regs(chip);
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index aa9cc105ce6..c6dfd8227f6 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -48,12 +48,26 @@ struct zd_rf {
u8 channel;
+ /* whether channel integration and calibration should be updated
+ * defaults to 1 (yes) */
+ u8 update_channel_int:1;
+
+ /* whether CR47 should be patched from the EEPROM, if the appropriate
+ * flag is set in the POD. The vendor driver suggests that this should
+ * be done for all RF's, but a bug in their code prevents but their
+ * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */
+ u8 patch_cck_gain:1;
+
+ /* private RF driver data */
+ void *priv;
+
/* RF-specific functions */
int (*init_hw)(struct zd_rf *rf);
int (*set_channel)(struct zd_rf *rf, u8 channel);
int (*switch_radio_on)(struct zd_rf *rf);
int (*switch_radio_off)(struct zd_rf *rf);
int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel);
+ void (*clear)(struct zd_rf *rf);
};
const char *zd_rf_name(u8 type);
@@ -71,10 +85,24 @@ int zd_switch_radio_off(struct zd_rf *rf);
int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf)
+{
+ return rf->update_channel_int;
+}
+
+static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf)
+{
+ return rf->patch_cck_gain;
+}
+
+int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel);
+int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel);
+
/* Functions for individual RF chips */
int zd_rf_init_rf2959(struct zd_rf *rf);
int zd_rf_init_al2230(struct zd_rf *rf);
int zd_rf_init_al7230b(struct zd_rf *rf);
+int zd_rf_init_uw2453(struct zd_rf *rf);
#endif /* _ZD_RF_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 511392acfed..e7a4ecf7b6e 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -432,5 +432,6 @@ int zd_rf_init_al2230(struct zd_rf *rf)
rf->switch_radio_on = zd1211_al2230_switch_radio_on;
}
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->patch_cck_gain = 1;
return 0;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index 5e5e9ddc6a7..f4e8b6ada85 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -483,6 +483,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf)
rf->switch_radio_on = zd1211_al7230b_switch_radio_on;
rf->set_channel = zd1211_al7230b_set_channel;
rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->patch_cck_gain = 1;
}
rf->switch_radio_off = al7230b_switch_radio_off;
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
new file mode 100644
index 00000000000..414e40d571a
--- /dev/null
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -0,0 +1,534 @@
+/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+
+#include "zd_rf.h"
+#include "zd_usb.h"
+#include "zd_chip.h"
+
+/* This RF programming code is based upon the code found in v2.16.0.0 of the
+ * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs
+ * for this RF on their website, so we're able to understand more than
+ * usual as to what is going on. Thumbs up for Ubec for doing that. */
+
+/* The 3-wire serial interface provides access to 8 write-only registers.
+ * The data format is a 4 bit register address followed by a 20 bit value. */
+#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff))
+
+/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth
+ * fractional divide ratio) and 3 (VCO config).
+ *
+ * We configure the RF to produce an interrupt when the PLL is locked onto
+ * the configured frequency. During initialization, we run through a variety
+ * of different VCO configurations on channel 1 until we detect a PLL lock.
+ * When this happens, we remember which VCO configuration produced the lock
+ * and use it later. Actually, we use the configuration *after* the one that
+ * produced the lock, which seems odd, but it works.
+ *
+ * If we do not see a PLL lock on any standard VCO config, we fall back on an
+ * autocal configuration, which has a fixed (as opposed to per-channel) VCO
+ * config and different synth values from the standard set (divide ratio
+ * is still shared with the standard set). */
+
+/* The per-channel synth values for all standard VCO configurations. These get
+ * written to register 1. */
+static const u8 uw2453_std_synth[] = {
+ RF_CHANNEL( 1) = 0x47,
+ RF_CHANNEL( 2) = 0x47,
+ RF_CHANNEL( 3) = 0x67,
+ RF_CHANNEL( 4) = 0x67,
+ RF_CHANNEL( 5) = 0x67,
+ RF_CHANNEL( 6) = 0x67,
+ RF_CHANNEL( 7) = 0x57,
+ RF_CHANNEL( 8) = 0x57,
+ RF_CHANNEL( 9) = 0x57,
+ RF_CHANNEL(10) = 0x57,
+ RF_CHANNEL(11) = 0x77,
+ RF_CHANNEL(12) = 0x77,
+ RF_CHANNEL(13) = 0x77,
+ RF_CHANNEL(14) = 0x4f,
+};
+
+/* This table stores the synthesizer fractional divide ratio for *all* VCO
+ * configurations (both standard and autocal). These get written to register 2.
+ */
+static const u16 uw2453_synth_divide[] = {
+ RF_CHANNEL( 1) = 0x999,
+ RF_CHANNEL( 2) = 0x99b,
+ RF_CHANNEL( 3) = 0x998,
+ RF_CHANNEL( 4) = 0x99a,
+ RF_CHANNEL( 5) = 0x999,
+ RF_CHANNEL( 6) = 0x99b,
+ RF_CHANNEL( 7) = 0x998,
+ RF_CHANNEL( 8) = 0x99a,
+ RF_CHANNEL( 9) = 0x999,
+ RF_CHANNEL(10) = 0x99b,
+ RF_CHANNEL(11) = 0x998,
+ RF_CHANNEL(12) = 0x99a,
+ RF_CHANNEL(13) = 0x999,
+ RF_CHANNEL(14) = 0xccc,
+};
+
+/* Here is the data for all the standard VCO configurations. We shrink our
+ * table a little by observing that both channels in a consecutive pair share
+ * the same value. We also observe that the high 4 bits ([0:3] in the specs)
+ * are all 'Reserved' and are always set to 0x4 - we chop them off in the data
+ * below. */
+#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2)
+#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)]
+static const u16 uw2453_std_vco_cfg[][7] = {
+ { /* table 1 */
+ RF_CHANPAIR( 1, 2) = 0x664d,
+ RF_CHANPAIR( 3, 4) = 0x604d,
+ RF_CHANPAIR( 5, 6) = 0x6675,
+ RF_CHANPAIR( 7, 8) = 0x6475,
+ RF_CHANPAIR( 9, 10) = 0x6655,
+ RF_CHANPAIR(11, 12) = 0x6455,
+ RF_CHANPAIR(13, 14) = 0x6665,
+ },
+ { /* table 2 */
+ RF_CHANPAIR( 1, 2) = 0x666d,
+ RF_CHANPAIR( 3, 4) = 0x606d,
+ RF_CHANPAIR( 5, 6) = 0x664d,
+ RF_CHANPAIR( 7, 8) = 0x644d,
+ RF_CHANPAIR( 9, 10) = 0x6675,
+ RF_CHANPAIR(11, 12) = 0x6475,
+ RF_CHANPAIR(13, 14) = 0x6655,
+ },
+ { /* table 3 */
+ RF_CHANPAIR( 1, 2) = 0x665d,
+ RF_CHANPAIR( 3, 4) = 0x605d,
+ RF_CHANPAIR( 5, 6) = 0x666d,
+ RF_CHANPAIR( 7, 8) = 0x646d,
+ RF_CHANPAIR( 9, 10) = 0x664d,
+ RF_CHANPAIR(11, 12) = 0x644d,
+ RF_CHANPAIR(13, 14) = 0x6675,
+ },
+ { /* table 4 */
+ RF_CHANPAIR( 1, 2) = 0x667d,
+ RF_CHANPAIR( 3, 4) = 0x607d,
+ RF_CHANPAIR( 5, 6) = 0x665d,
+ RF_CHANPAIR( 7, 8) = 0x645d,
+ RF_CHANPAIR( 9, 10) = 0x666d,
+ RF_CHANPAIR(11, 12) = 0x646d,
+ RF_CHANPAIR(13, 14) = 0x664d,
+ },
+ { /* table 5 */
+ RF_CHANPAIR( 1, 2) = 0x6643,
+ RF_CHANPAIR( 3, 4) = 0x6043,
+ RF_CHANPAIR( 5, 6) = 0x667d,
+ RF_CHANPAIR( 7, 8) = 0x647d,
+ RF_CHANPAIR( 9, 10) = 0x665d,
+ RF_CHANPAIR(11, 12) = 0x645d,
+ RF_CHANPAIR(13, 14) = 0x666d,
+ },
+ { /* table 6 */
+ RF_CHANPAIR( 1, 2) = 0x6663,
+ RF_CHANPAIR( 3, 4) = 0x6063,
+ RF_CHANPAIR( 5, 6) = 0x6643,
+ RF_CHANPAIR( 7, 8) = 0x6443,
+ RF_CHANPAIR( 9, 10) = 0x667d,
+ RF_CHANPAIR(11, 12) = 0x647d,
+ RF_CHANPAIR(13, 14) = 0x665d,
+ },
+ { /* table 7 */
+ RF_CHANPAIR( 1, 2) = 0x6653,
+ RF_CHANPAIR( 3, 4) = 0x6053,
+ RF_CHANPAIR( 5, 6) = 0x6663,
+ RF_CHANPAIR( 7, 8) = 0x6463,
+ RF_CHANPAIR( 9, 10) = 0x6643,
+ RF_CHANPAIR(11, 12) = 0x6443,
+ RF_CHANPAIR(13, 14) = 0x667d,
+ },
+ { /* table 8 */
+ RF_CHANPAIR( 1, 2) = 0x6673,
+ RF_CHANPAIR( 3, 4) = 0x6073,
+ RF_CHANPAIR( 5, 6) = 0x6653,
+ RF_CHANPAIR( 7, 8) = 0x6453,
+ RF_CHANPAIR( 9, 10) = 0x6663,
+ RF_CHANPAIR(11, 12) = 0x6463,
+ RF_CHANPAIR(13, 14) = 0x6643,
+ },
+ { /* table 9 */
+ RF_CHANPAIR( 1, 2) = 0x664b,
+ RF_CHANPAIR( 3, 4) = 0x604b,
+ RF_CHANPAIR( 5, 6) = 0x6673,
+ RF_CHANPAIR( 7, 8) = 0x6473,
+ RF_CHANPAIR( 9, 10) = 0x6653,
+ RF_CHANPAIR(11, 12) = 0x6453,
+ RF_CHANPAIR(13, 14) = 0x6663,
+ },
+ { /* table 10 */
+ RF_CHANPAIR( 1, 2) = 0x666b,
+ RF_CHANPAIR( 3, 4) = 0x606b,
+ RF_CHANPAIR( 5, 6) = 0x664b,
+ RF_CHANPAIR( 7, 8) = 0x644b,
+ RF_CHANPAIR( 9, 10) = 0x6673,
+ RF_CHANPAIR(11, 12) = 0x6473,
+ RF_CHANPAIR(13, 14) = 0x6653,
+ },
+ { /* table 11 */
+ RF_CHANPAIR( 1, 2) = 0x665b,
+ RF_CHANPAIR( 3, 4) = 0x605b,
+ RF_CHANPAIR( 5, 6) = 0x666b,
+ RF_CHANPAIR( 7, 8) = 0x646b,
+ RF_CHANPAIR( 9, 10) = 0x664b,
+ RF_CHANPAIR(11, 12) = 0x644b,
+ RF_CHANPAIR(13, 14) = 0x6673,
+ },
+
+};
+
+/* The per-channel synth values for autocal. These get written to register 1. */
+static const u16 uw2453_autocal_synth[] = {
+ RF_CHANNEL( 1) = 0x6847,
+ RF_CHANNEL( 2) = 0x6847,
+ RF_CHANNEL( 3) = 0x6867,
+ RF_CHANNEL( 4) = 0x6867,
+ RF_CHANNEL( 5) = 0x6867,
+ RF_CHANNEL( 6) = 0x6867,
+ RF_CHANNEL( 7) = 0x6857,
+ RF_CHANNEL( 8) = 0x6857,
+ RF_CHANNEL( 9) = 0x6857,
+ RF_CHANNEL(10) = 0x6857,
+ RF_CHANNEL(11) = 0x6877,
+ RF_CHANNEL(12) = 0x6877,
+ RF_CHANNEL(13) = 0x6877,
+ RF_CHANNEL(14) = 0x684f,
+};
+
+/* The VCO configuration for autocal (all channels) */
+static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662;
+
+/* TX gain settings. The array index corresponds to the TX power integration
+ * values found in the EEPROM. The values get written to register 7. */
+static u32 uw2453_txgain[] = {
+ [0x00] = 0x0e313,
+ [0x01] = 0x0fb13,
+ [0x02] = 0x0e093,
+ [0x03] = 0x0f893,
+ [0x04] = 0x0ea93,
+ [0x05] = 0x1f093,
+ [0x06] = 0x1f493,
+ [0x07] = 0x1f693,
+ [0x08] = 0x1f393,
+ [0x09] = 0x1f35b,
+ [0x0a] = 0x1e6db,
+ [0x0b] = 0x1ff3f,
+ [0x0c] = 0x1ffff,
+ [0x0d] = 0x361d7,
+ [0x0e] = 0x37fbf,
+ [0x0f] = 0x3ff8b,
+ [0x10] = 0x3ff33,
+ [0x11] = 0x3fb3f,
+ [0x12] = 0x3ffff,
+};
+
+/* RF-specific structure */
+struct uw2453_priv {
+ /* index into synth/VCO config tables where PLL lock was found
+ * -1 means autocal */
+ int config;
+};
+
+#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv)
+
+static int uw2453_synth_set_channel(struct zd_chip *chip, int channel,
+ bool autocal)
+{
+ int r;
+ int idx = channel - 1;
+ u32 val;
+
+ if (autocal)
+ val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]);
+ else
+ val = UW2453_REGWRITE(1, uw2453_std_synth[idx]);
+
+ r = zd_rfwrite_locked(chip, val, RF_RV_BITS);
+ if (r)
+ return r;
+
+ return zd_rfwrite_locked(chip,
+ UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS);
+}
+
+static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value)
+{
+ /* vendor driver always sets these upper bits even though the specs say
+ * they are reserved */
+ u32 val = 0x40000 | value;
+ return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS);
+}
+
+static int uw2453_init_mode(struct zd_chip *chip)
+{
+ static const u32 rv[] = {
+ UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */
+ UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */
+ UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */
+ UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */
+ };
+
+ return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+}
+
+static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel)
+{
+ u8 int_value = chip->pwr_int_values[channel - 1];
+
+ if (int_value >= ARRAY_SIZE(uw2453_txgain)) {
+ dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for "
+ "int value %x on channel %d\n", int_value, channel);
+ return 0;
+ }
+
+ return zd_rfwrite_locked(chip,
+ UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS);
+}
+
+static int uw2453_init_hw(struct zd_rf *rf)
+{
+ int i, r;
+ int found_config = -1;
+ u16 intr_status;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR10, 0x89 }, { CR15, 0x20 },
+ { CR17, 0x28 }, /* 6112 no change */
+ { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 },
+ { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 },
+ { CR33, 0x28 }, { CR34, 0x30 },
+ { CR35, 0x43 }, /* 6112 3e->43 */
+ { CR41, 0x24 }, { CR44, 0x32 },
+ { CR46, 0x92 }, /* 6112 96->92 */
+ { CR47, 0x1e },
+ { CR48, 0x04 }, /* 5602 Roger */
+ { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 },
+ { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 },
+ { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d },
+ { CR99, 0x28 }, { CR100, 0x02 },
+ { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */
+ { CR102, 0x27 },
+ { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */
+ { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */
+ { CR109, 0x13 },
+ { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */
+ { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 },
+ { CR114, 0x23 }, /* 6221 27->23 */
+ { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */
+ { CR116, 0x24 }, /* 6220 1c->24 */
+ { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */
+ { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */
+ { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */
+ { CR120, 0x4f },
+ { CR121, 0x1f }, /* 6220 4f->1f */
+ { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad },
+ { CR126, 0x6c }, { CR127, 0x03 },
+ { CR128, 0x14 }, /* 6302 12->11 */
+ { CR129, 0x12 }, /* 6301 10->0f */
+ { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 },
+ { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff },
+ { CR253, 0xff },
+ };
+
+ static const u32 rv[] = {
+ UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */
+ UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
+ UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
+ UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
+
+ /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins,
+ * RSSI circuit powered down, reduced RSSI range */
+ UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */
+
+ /* synthesizer configuration for channel 1 */
+ UW2453_REGWRITE(1, 0x47),
+ UW2453_REGWRITE(2, 0x999),
+
+ /* disable manual VCO band selection */
+ UW2453_REGWRITE(3, 0x7602),
+
+ /* enable manual VCO band selection, configure current level */
+ UW2453_REGWRITE(3, 0x46063),
+ };
+
+ r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+ if (r)
+ return r;
+
+ r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS);
+ if (r)
+ return r;
+
+ r = uw2453_init_mode(chip);
+ if (r)
+ return r;
+
+ /* Try all standard VCO configuration settings on channel 1 */
+ for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) {
+ /* Configure synthesizer for channel 1 */
+ r = uw2453_synth_set_channel(chip, 1, false);
+ if (r)
+ return r;
+
+ /* Write VCO config */
+ r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]);
+ if (r)
+ return r;
+
+ /* ack interrupt event */
+ r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG);
+ if (r)
+ return r;
+
+ /* check interrupt status */
+ r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG);
+ if (r)
+ return r;
+
+ if (!intr_status & 0xf) {
+ dev_dbg_f(zd_chip_dev(chip),
+ "PLL locked on configuration %d\n", i);
+ found_config = i;
+ break;
+ }
+ }
+
+ if (found_config == -1) {
+ /* autocal */
+ dev_dbg_f(zd_chip_dev(chip),
+ "PLL did not lock, using autocal\n");
+
+ r = uw2453_synth_set_channel(chip, 1, true);
+ if (r)
+ return r;
+
+ r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG);
+ if (r)
+ return r;
+ }
+
+ /* To match the vendor driver behaviour, we use the configuration after
+ * the one that produced a lock. */
+ UW2453_PRIV(rf)->config = found_config + 1;
+
+ return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_set_channel(struct zd_rf *rf, u8 channel)
+{
+ int r;
+ u16 vco_cfg;
+ int config = UW2453_PRIV(rf)->config;
+ bool autocal = (config == -1);
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 },
+ { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 },
+ };
+
+ r = uw2453_synth_set_channel(chip, channel, autocal);
+ if (r)
+ return r;
+
+ if (autocal)
+ vco_cfg = UW2453_AUTOCAL_VCO_CFG;
+ else
+ vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)];
+
+ r = uw2453_write_vco_cfg(chip, vco_cfg);
+ if (r)
+ return r;
+
+ r = uw2453_init_mode(chip);
+ if (r)
+ return r;
+
+ r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+ if (r)
+ return r;
+
+ r = uw2453_set_tx_gain_level(chip, channel);
+ if (r)
+ return r;
+
+ return zd_iowrite16_locked(chip, 0x06, CR203);
+}
+
+static int uw2453_switch_radio_on(struct zd_rf *rf)
+{
+ int r;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+ struct zd_ioreq16 ioreqs[] = {
+ { CR11, 0x00 }, { CR251, 0x3f },
+ };
+
+ /* enter RXTX mode */
+ r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS);
+ if (r)
+ return r;
+
+ if (chip->is_zd1211b)
+ ioreqs[1].value = 0x7f;
+
+ return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static int uw2453_switch_radio_off(struct zd_rf *rf)
+{
+ int r;
+ struct zd_chip *chip = zd_rf_to_chip(rf);
+ static const struct zd_ioreq16 ioreqs[] = {
+ { CR11, 0x04 }, { CR251, 0x2f },
+ };
+
+ /* enter IDLE mode */
+ /* FIXME: shouldn't we go to SLEEP? sent email to zydas */
+ r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS);
+ if (r)
+ return r;
+
+ return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
+static void uw2453_clear(struct zd_rf *rf)
+{
+ kfree(rf->priv);
+}
+
+int zd_rf_init_uw2453(struct zd_rf *rf)
+{
+ rf->init_hw = uw2453_init_hw;
+ rf->set_channel = uw2453_set_channel;
+ rf->switch_radio_on = uw2453_switch_radio_on;
+ rf->switch_radio_off = uw2453_switch_radio_off;
+ rf->patch_6m_band_edge = zd_rf_generic_patch_6m;
+ rf->clear = uw2453_clear;
+ /* we have our own TX integration code */
+ rf->update_channel_int = 0;
+
+ rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL);
+ if (rf->priv == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 8459549d0ce..ca24299a26c 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -15,7 +15,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <asm/unaligned.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -26,6 +25,7 @@
#include <linux/usb.h>
#include <linux/workqueue.h>
#include <net/ieee80211.h>
+#include <asm/unaligned.h>
#include "zd_def.h"
#include "zd_netdev.h"
@@ -54,6 +54,7 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
/* ZD1211B */
{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index f2a90a7fa2d..870c5393c21 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -1137,7 +1137,7 @@ static int yellowfin_rx(struct net_device *dev)
if (skb == NULL)
break;
skb_reserve(skb, 2); /* 16 byte align the IP header */
- eth_copy_and_sum(skb, rx_skb->data, pkt_len, 0);
+ skb_copy_to_linear_data(skb, rx_skb->data, pkt_len);
skb_put(skb, pkt_len);
pci_dma_sync_single_for_device(yp->pci_dev, desc->addr,
yp->rx_buf_sz,
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index 894fdb9d44c..b3c4dbff26b 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -32,6 +32,7 @@
*/
#include <linux/types.h>
+#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
@@ -292,7 +293,6 @@ static int ioc_count;
#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT)
#define MKIOVP(pdir_idx) ((long)(pdir_idx) << IOVP_SHIFT)
#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
-#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
/*
** Don't worry about the 150% average search length on a miss.
@@ -668,7 +668,7 @@ ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
size_t saved_byte_cnt;
/* round up to nearest page size */
- saved_byte_cnt = byte_cnt = ROUNDUP(byte_cnt, IOVP_SIZE);
+ saved_byte_cnt = byte_cnt = ALIGN(byte_cnt, IOVP_SIZE);
while(byte_cnt > 0) {
/* invalidate one page at a time */
@@ -751,7 +751,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
offset = ((unsigned long) addr) & ~IOVP_MASK;
/* round up to nearest IOVP_SIZE */
- size = ROUNDUP(size + offset, IOVP_SIZE);
+ size = ALIGN(size + offset, IOVP_SIZE);
spin_lock_irqsave(&ioc->res_lock, flags);
#ifdef CCIO_MAP_STATS
@@ -814,7 +814,7 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
iova ^= offset; /* clear offset bits */
size += offset;
- size = ROUNDUP(size, IOVP_SIZE);
+ size = ALIGN(size, IOVP_SIZE);
spin_lock_irqsave(&ioc->res_lock, flags);
@@ -1227,7 +1227,7 @@ ccio_get_iotlb_size(struct parisc_device *dev)
#endif /* 0 */
/* We *can't* support JAVA (T600). Venture there at your own risk. */
-static struct parisc_device_id ccio_tbl[] = {
+static const struct parisc_device_id ccio_tbl[] = {
{ HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */
{ HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */
{ 0, }
@@ -1370,7 +1370,7 @@ ccio_ioc_init(struct ioc *ioc)
}
}
-static void
+static void __init
ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr)
{
int result;
@@ -1537,7 +1537,7 @@ int ccio_request_resource(const struct parisc_device *dev,
* If so, initialize the chip and tell other partners in crime they
* have work to do.
*/
-static int ccio_probe(struct parisc_device *dev)
+static int __init ccio_probe(struct parisc_device *dev)
{
int i;
struct ioc *ioc, **ioc_p = &ioc_list;
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 309076b3985..771cef59254 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -307,7 +307,7 @@ static void init_eisa_pic(void)
#define is_mongoose(dev) (dev->id.sversion == 0x00076)
-static int __devinit eisa_probe(struct parisc_device *dev)
+static int __init eisa_probe(struct parisc_device *dev)
{
int i, result;
@@ -387,7 +387,7 @@ static int __devinit eisa_probe(struct parisc_device *dev)
return 0;
}
-static struct parisc_device_id eisa_tbl[] = {
+static const struct parisc_device_id eisa_tbl[] = {
{ HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00076 }, /* Mongoose */
{ HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00090 }, /* Wax EISA */
{ 0, }
diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h
index 38d9e1aba1d..0a1f99a2e93 100644
--- a/drivers/parisc/iommu-helpers.h
+++ b/drivers/parisc/iommu-helpers.h
@@ -138,7 +138,7 @@ iommu_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents,
** exceed DMA_CHUNK_SIZE if we coalesce the
** next entry.
*/
- if(unlikely(ROUNDUP(dma_len + dma_offset + startsg->length,
+ if(unlikely(ALIGN(dma_len + dma_offset + startsg->length,
IOVP_SIZE) > DMA_CHUNK_SIZE))
break;
@@ -158,7 +158,7 @@ iommu_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents,
** Allocate space for DMA stream.
*/
sg_dma_len(contig_sg) = dma_len;
- dma_len = ROUNDUP(dma_len + dma_offset, IOVP_SIZE);
+ dma_len = ALIGN(dma_len + dma_offset, IOVP_SIZE);
sg_dma_address(contig_sg) =
PIDE_FLAG
| (iommu_alloc_range(ioc, dma_len) << IOVP_SHIFT)
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index 98be2880757..e5d7ed92d6f 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -195,12 +195,6 @@ static int led_proc_write(struct file *file, const char *buf,
cur = lbuf;
- /* skip initial spaces */
- while (*cur && isspace(*cur))
- {
- cur++;
- }
-
switch ((long)data)
{
case LED_NOLCD:
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 815e445c312..fc4bde259dc 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -121,14 +121,14 @@ struct pdcspath_entry pdcspath_entry_##_name = { \
#define PDCS_ATTR(_name, _mode, _show, _store) \
struct subsys_attribute pdcs_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+ .attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};
#define PATHS_ATTR(_name, _mode, _show, _store) \
struct pdcspath_attribute paths_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+ .attr = {.name = __stringify(_name), .mode = _mode}, \
.show = _show, \
.store = _store, \
};
@@ -1067,7 +1067,7 @@ pdc_stable_init(void)
error = subsys_create_file(&stable_subsys, attr);
/* register the paths subsys as a subsystem of stable subsys */
- kset_set_kset_s(&paths_subsys, stable_subsys);
+ kobj_set_kset_s(&paths_subsys, stable_subsys);
if ((rc = subsystem_register(&paths_subsys)))
goto fail_subsysreg;
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index 6dedbdef710..90cca5e3805 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -41,6 +41,7 @@
#include <linux/reboot.h>
#include <linux/sched.h>
#include <linux/kthread.h>
+#include <linux/pm.h>
#include <asm/pdc.h>
#include <asm/io.h>
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 322957ac2ad..d044c48323e 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -113,8 +113,6 @@ module_param(sba_reserve_agpgart, int, 0444);
MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART");
#endif
-#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
-
/************************************
** SBA register read and write support
@@ -352,7 +350,7 @@ sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
** SBA HW features in the unmap path.
*/
unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT);
- uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
+ uint bitshiftcnt = ALIGN(ioc->res_bitshift, o);
unsigned long mask;
if (bitshiftcnt >= BITS_PER_LONG) {
@@ -779,7 +777,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size,
offset = iova & ~IOVP_MASK;
iova ^= offset; /* clear offset bits */
size += offset;
- size = ROUNDUP(size, IOVP_SIZE);
+ size = ALIGN(size, IOVP_SIZE);
spin_lock_irqsave(&ioc->res_lock, flags);
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 1fd97f7c8b9..a708c329675 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -389,7 +389,7 @@ int superio_fixup_irq(struct pci_dev *pcidev)
return local_irq;
}
-static void __devinit superio_serial_init(void)
+static void __init superio_serial_init(void)
{
#ifdef CONFIG_SERIAL_8250
int retval;
@@ -423,7 +423,7 @@ static void __devinit superio_serial_init(void)
}
-static void __devinit superio_parport_init(void)
+static void __init superio_parport_init(void)
{
#ifdef CONFIG_PARPORT_PC
if (!parport_pc_probe_port(sio_dev.pp_base,
@@ -450,7 +450,7 @@ static void superio_fixup_pci(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci);
-static int __devinit
+static int __init
superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct superio_device *sio = &sio_dev;
@@ -485,7 +485,7 @@ superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENODEV;
}
-static struct pci_device_id superio_tbl[] = {
+static const struct pci_device_id superio_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) },
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 17bf9937d27..43652ba523e 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -350,7 +350,7 @@ struct parport *__devinit parport_gsc_probe_port (unsigned long base,
#define PARPORT_GSC_OFFSET 0x800
-static int __initdata parport_count;
+static int __devinitdata parport_count;
static int __devinit parport_init_chip(struct parisc_device *dev)
{
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e3beb784406..006054a4099 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -41,9 +41,7 @@ obj-$(CONFIG_ACPI) += pci-acpi.o
# Cardbus & CompactPCI use setup-bus
obj-$(CONFIG_HOTPLUG) += setup-bus.o
-ifndef CONFIG_X86
-obj-y += syscall.o
-endif
+obj-$(CONFIG_PCI_SYSCALL) += syscall.o
ifeq ($(CONFIG_PCI_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index ddbadd95387..f6cc0c5b565 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -211,6 +211,7 @@ typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
+extern int acpiphp_eject_slot (struct acpiphp_slot *slot);
extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index fa5c0197d57..a0ca63adad5 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -156,11 +156,15 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
static int disable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
+ int retval;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
/* disable the specified slot */
- return acpiphp_disable_slot(slot->acpi_slot);
+ retval = acpiphp_disable_slot(slot->acpi_slot);
+ if (!retval)
+ retval = acpiphp_eject_slot(slot->acpi_slot);
+ return retval;
}
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 9ef4e989afc..1e125b56c9a 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1282,7 +1282,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
/**
* acpiphp_eject_slot - physically eject the slot
*/
-static int acpiphp_eject_slot(struct acpiphp_slot *slot)
+int acpiphp_eject_slot(struct acpiphp_slot *slot)
{
acpi_status status;
struct acpiphp_func *func;
@@ -1368,6 +1368,9 @@ static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
return;
+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+ return;
+
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
bridge->hpp.t0->cache_line_size);
pci_write_config_byte(dev, PCI_LATENCY_TIMER,
@@ -1502,6 +1505,37 @@ static void handle_bridge_insertion(acpi_handle handle, u32 type)
* ACPI event handlers
*/
+static acpi_status
+count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ int *count = (int *)context;
+ struct acpiphp_bridge *bridge;
+
+ bridge = acpiphp_handle_to_bridge(handle);
+ if (bridge)
+ (*count)++;
+ return AE_OK ;
+}
+
+static acpi_status
+check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ struct acpiphp_bridge *bridge;
+ char objname[64];
+ struct acpi_buffer buffer = { .length = sizeof(objname),
+ .pointer = objname };
+
+ bridge = acpiphp_handle_to_bridge(handle);
+ if (bridge) {
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+ dbg("%s: re-enumerating slots under %s\n",
+ __FUNCTION__, objname);
+ acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+ acpiphp_check_bridge(bridge);
+ }
+ return AE_OK ;
+}
+
/**
* handle_hotplug_event_bridge - handle ACPI event on bridges
*
@@ -1519,6 +1553,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
struct acpi_device *device;
+ int num_sub_bridges = 0;
if (acpi_bus_get_device(handle, &device)) {
/* This bridge must have just been physically inserted */
@@ -1527,7 +1562,12 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
}
bridge = acpiphp_handle_to_bridge(handle);
- if (!bridge) {
+ if (type == ACPI_NOTIFY_BUS_CHECK) {
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
+ count_sub_bridges, &num_sub_bridges, NULL);
+ }
+
+ if (!bridge && !num_sub_bridges) {
err("cannot get bridge info\n");
return;
}
@@ -1538,7 +1578,14 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
case ACPI_NOTIFY_BUS_CHECK:
/* bus re-enumerate */
dbg("%s: Bus check notify on %s\n", __FUNCTION__, objname);
- acpiphp_check_bridge(bridge);
+ if (bridge) {
+ dbg("%s: re-enumerating slots under %s\n",
+ __FUNCTION__, objname);
+ acpiphp_check_bridge(bridge);
+ }
+ if (num_sub_bridges)
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+ ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
break;
case ACPI_NOTIFY_DEVICE_CHECK:
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index e7322c25d37..70db38c0ced 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -106,7 +106,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status);
static void ibm_handle_events(acpi_handle handle, u32 event, void *context);
static int ibm_get_table_from_acpi(char **bufp);
static ssize_t ibm_read_apci_table(struct kobject *kobj,
- char *buffer, loff_t pos, size_t size);
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t size);
static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
u32 lvl, void *context, void **rv);
static int __init ibm_acpiphp_init(void);
@@ -117,7 +118,6 @@ static struct notification ibm_note;
static struct bin_attribute ibm_apci_table_attr = {
.attr = {
.name = "apci_table",
- .owner = THIS_MODULE,
.mode = S_IRUGO,
},
.read = ibm_read_apci_table,
@@ -358,7 +358,8 @@ read_table_done:
* our solution is to only allow reading the table in all at once
**/
static ssize_t ibm_read_apci_table(struct kobject *kobj,
- char *buffer, loff_t pos, size_t size)
+ struct bin_attribute *bin_attr,
+ char *buffer, loff_t pos, size_t size)
{
int bytes_read = -EINVAL;
char *table = NULL;
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index 684551559d4..ed4d44e3332 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -35,6 +35,7 @@
#include <linux/smp_lock.h>
#include <asm/atomic.h>
#include <linux/delay.h>
+#include <linux/kthread.h>
#include "cpci_hotplug.h"
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
@@ -59,9 +60,8 @@ static int slots;
static atomic_t extracting;
int cpci_debug;
static struct cpci_hp_controller *controller;
-static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
-static struct semaphore thread_exit; /* guard ensure thread has exited before calling it quits */
-static int thread_finished = 1;
+static struct task_struct *cpci_thread;
+static int thread_finished;
static int enable_slot(struct hotplug_slot *slot);
static int disable_slot(struct hotplug_slot *slot);
@@ -357,9 +357,7 @@ cpci_hp_intr(int irq, void *data)
controller->ops->disable_irq();
/* Trigger processing by the event thread */
- dbg("Signal event_semaphore");
- up(&event_semaphore);
- dbg("exited cpci_hp_intr");
+ wake_up_process(cpci_thread);
return IRQ_HANDLED;
}
@@ -521,17 +519,12 @@ event_thread(void *data)
{
int rc;
- lock_kernel();
- daemonize("cpci_hp_eventd");
- unlock_kernel();
-
dbg("%s - event thread started", __FUNCTION__);
while (1) {
dbg("event thread sleeping");
- down_interruptible(&event_semaphore);
- dbg("event thread woken, thread_finished = %d",
- thread_finished);
- if (thread_finished || signal_pending(current))
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ if (kthread_should_stop())
break;
do {
rc = check_slots();
@@ -541,18 +534,17 @@ event_thread(void *data)
} else if (rc < 0) {
dbg("%s - error checking slots", __FUNCTION__);
thread_finished = 1;
- break;
+ goto out;
}
- } while (atomic_read(&extracting) && !thread_finished);
- if (thread_finished)
+ } while (atomic_read(&extracting) && !kthread_should_stop());
+ if (kthread_should_stop())
break;
/* Re-enable ENUM# interrupt */
dbg("%s - re-enabling irq", __FUNCTION__);
controller->ops->enable_irq();
}
- dbg("%s - event thread signals exit", __FUNCTION__);
- up(&thread_exit);
+ out:
return 0;
}
@@ -562,12 +554,8 @@ poll_thread(void *data)
{
int rc;
- lock_kernel();
- daemonize("cpci_hp_polld");
- unlock_kernel();
-
while (1) {
- if (thread_finished || signal_pending(current))
+ if (kthread_should_stop() || signal_pending(current))
break;
if (controller->ops->query_enum()) {
do {
@@ -578,48 +566,36 @@ poll_thread(void *data)
} else if (rc < 0) {
dbg("%s - error checking slots", __FUNCTION__);
thread_finished = 1;
- break;
+ goto out;
}
- } while (atomic_read(&extracting) && !thread_finished);
+ } while (atomic_read(&extracting) && !kthread_should_stop());
}
msleep(100);
}
- dbg("poll thread signals exit");
- up(&thread_exit);
+ out:
return 0;
}
static int
cpci_start_thread(void)
{
- int pid;
-
- /* initialize our semaphores */
- init_MUTEX_LOCKED(&event_semaphore);
- init_MUTEX_LOCKED(&thread_exit);
- thread_finished = 0;
-
if (controller->irq)
- pid = kernel_thread(event_thread, NULL, 0);
+ cpci_thread = kthread_run(event_thread, NULL, "cpci_hp_eventd");
else
- pid = kernel_thread(poll_thread, NULL, 0);
- if (pid < 0) {
+ cpci_thread = kthread_run(poll_thread, NULL, "cpci_hp_polld");
+ if (IS_ERR(cpci_thread)) {
err("Can't start up our thread");
- return -1;
+ return PTR_ERR(cpci_thread);
}
- dbg("Our thread pid = %d", pid);
+ thread_finished = 0;
return 0;
}
static void
cpci_stop_thread(void)
{
+ kthread_stop(cpci_thread);
thread_finished = 1;
- dbg("thread finish command given");
- if (controller->irq)
- up(&event_semaphore);
- dbg("wait for thread to exit");
- down(&thread_exit);
}
int
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 7b1beaad275..5e9be44817c 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -45,8 +45,6 @@ extern int cpci_debug;
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
-#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
-
u8 cpci_get_attention_status(struct slot* slot)
{
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 5617cfdadc5..d590a99930f 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -796,7 +796,6 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
u8 num_of_slots = 0;
u8 hp_slot = 0;
u8 device;
- u8 rev;
u8 bus_cap;
u16 temp_word;
u16 vendor_id;
@@ -823,9 +822,8 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
dbg("Vendor ID: %x\n", vendor_id);
- rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
- dbg("revision: %d\n", rev);
- if (rc || ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!rev))) {
+ dbg("revision: %d\n", pdev->revision);
+ if ((vendor_id == PCI_VENDOR_ID_COMPAQ) && (!pdev->revision)) {
err(msg_HPC_rev_error);
rc = -ENODEV;
goto err_disable_device;
@@ -836,7 +834,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
* For Intel, each SSID bit identifies a PHP capability.
* Also Intel HPC's may have RID=0.
*/
- if ((rev > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
+ if ((pdev->revision > 2) || (vendor_id == PCI_VENDOR_ID_INTEL)) {
// TODO: This code can be made to support non-Compaq or Intel subsystem IDs
rc = pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vid);
if (rc) {
@@ -870,7 +868,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
switch (subsystem_vid) {
case PCI_VENDOR_ID_COMPAQ:
- if (rev >= 0x13) { /* CIOBX */
+ if (pdev->revision >= 0x13) { /* CIOBX */
ctrl->push_flag = 1;
ctrl->slot_switch_type = 1;
ctrl->push_button = 1;
@@ -1075,7 +1073,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus));
ctrl->bus = pdev->bus->number;
- ctrl->rev = rev;
+ ctrl->rev = pdev->revision;
dbg("bus device function rev: %d %d %d %d\n", ctrl->bus,
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), ctrl->rev);
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index ccc57627201..7959c222dc2 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -103,6 +103,7 @@ struct controller {
u8 cap_base;
struct timer_list poll_timer;
volatile int cmd_busy;
+ spinlock_t lock;
};
#define INT_BUTTON_IGNORE 0
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 7f22caa7017..98e541ffef3 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -197,6 +197,12 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
__FUNCTION__);
return;
}
+ /*
+ * After turning power off, we must wait for at least
+ * 1 second before taking any action that relies on
+ * power having been removed from the slot/adapter.
+ */
+ msleep(1000);
}
}
@@ -615,6 +621,12 @@ int pciehp_disable_slot(struct slot *p_slot)
mutex_unlock(&p_slot->ctrl->crit_sect);
return -EINVAL;
}
+ /*
+ * After turning power off, we must wait for at least
+ * 1 second before taking any action that relies on
+ * power having been removed from the slot/adapter.
+ */
+ msleep(1000);
}
ret = remove_board(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 9aac6a87eb5..016eea94a8a 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -275,11 +275,19 @@ static inline int pcie_wait_cmd(struct controller *ctrl)
return retval;
}
-static int pcie_write_cmd(struct slot *slot, u16 cmd)
+/**
+ * pcie_write_cmd - Issue controller command
+ * @slot: slot to which the command is issued
+ * @cmd: command value written to slot control register
+ * @mask: bitmask of slot control register to be modified
+ */
+static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
{
struct controller *ctrl = slot->ctrl;
int retval = 0;
u16 slot_status;
+ u16 slot_ctrl;
+ unsigned long flags;
DBG_ENTER_ROUTINE
@@ -299,17 +307,29 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
__FUNCTION__);
}
- ctrl->cmd_busy = 1;
- retval = pciehp_writew(ctrl, SLOTCTRL, (cmd | CMD_CMPL_INTR_ENABLE));
+ spin_lock_irqsave(&ctrl->lock, flags);
+ retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (retval) {
- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
- goto out;
+ err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+ goto out_spin_unlock;
}
+ slot_ctrl &= ~mask;
+ slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE);
+
+ ctrl->cmd_busy = 1;
+ retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
+ if (retval)
+ err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+
+ out_spin_unlock:
+ spin_unlock_irqrestore(&ctrl->lock, flags);
+
/*
* Wait for command completion.
*/
- retval = pcie_wait_cmd(ctrl);
+ if (!retval)
+ retval = pcie_wait_cmd(ctrl);
out:
mutex_unlock(&ctrl->ctrl_lock);
DBG_LEAVE_ROUTINE
@@ -502,25 +522,20 @@ static int hpc_get_emi_status(struct slot *slot, u8 *status)
static int hpc_toggle_emi(struct slot *slot)
{
- struct controller *ctrl = slot->ctrl;
- u16 slot_cmd = 0;
- u16 slot_ctrl;
- int rc = 0;
+ u16 slot_cmd;
+ u16 cmd_mask;
+ int rc;
DBG_ENTER_ROUTINE
- rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
- if (rc) {
- err("%s : hp_register_read_word SLOT_CTRL failed\n",
- __FUNCTION__);
- return rc;
- }
-
- slot_cmd = (slot_ctrl | EMI_CTRL);
- if (!pciehp_poll_mode)
+ slot_cmd = EMI_CTRL;
+ cmd_mask = EMI_CTRL;
+ if (!pciehp_poll_mode) {
slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ cmd_mask = cmd_mask | HP_INTR_ENABLE;
+ }
- pcie_write_cmd(slot, slot_cmd);
+ rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
slot->last_emi_toggle = get_seconds();
DBG_LEAVE_ROUTINE
return rc;
@@ -529,35 +544,32 @@ static int hpc_toggle_emi(struct slot *slot)
static int hpc_set_attention_status(struct slot *slot, u8 value)
{
struct controller *ctrl = slot->ctrl;
- u16 slot_cmd = 0;
- u16 slot_ctrl;
- int rc = 0;
+ u16 slot_cmd;
+ u16 cmd_mask;
+ int rc;
DBG_ENTER_ROUTINE
- rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
- if (rc) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- return rc;
- }
-
+ cmd_mask = ATTN_LED_CTRL;
switch (value) {
case 0 : /* turn off */
- slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0;
+ slot_cmd = 0x00C0;
break;
case 1: /* turn on */
- slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040;
+ slot_cmd = 0x0040;
break;
case 2: /* turn blink */
- slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080;
+ slot_cmd = 0x0080;
break;
default:
return -1;
}
- if (!pciehp_poll_mode)
- slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ if (!pciehp_poll_mode) {
+ slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ cmd_mask = cmd_mask | HP_INTR_ENABLE;
+ }
- pcie_write_cmd(slot, slot_cmd);
+ rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
dbg("%s: SLOTCTRL %x write cmd %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -570,21 +582,18 @@ static void hpc_set_green_led_on(struct slot *slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
- u16 slot_ctrl;
- int rc = 0;
+ u16 cmd_mask;
DBG_ENTER_ROUTINE
- rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
- if (rc) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- return;
+ slot_cmd = 0x0100;
+ cmd_mask = PWR_LED_CTRL;
+ if (!pciehp_poll_mode) {
+ slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ cmd_mask = cmd_mask | HP_INTR_ENABLE;
}
- slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
- if (!pciehp_poll_mode)
- slot_cmd = slot_cmd | HP_INTR_ENABLE;
- pcie_write_cmd(slot, slot_cmd);
+ pcie_write_cmd(slot, slot_cmd, cmd_mask);
dbg("%s: SLOTCTRL %x write cmd %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -596,22 +605,18 @@ static void hpc_set_green_led_off(struct slot *slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
- u16 slot_ctrl;
- int rc = 0;
+ u16 cmd_mask;
DBG_ENTER_ROUTINE
- rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
- if (rc) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- return;
+ slot_cmd = 0x0300;
+ cmd_mask = PWR_LED_CTRL;
+ if (!pciehp_poll_mode) {
+ slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ cmd_mask = cmd_mask | HP_INTR_ENABLE;
}
- slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
-
- if (!pciehp_poll_mode)
- slot_cmd = slot_cmd | HP_INTR_ENABLE;
- pcie_write_cmd(slot, slot_cmd);
+ pcie_write_cmd(slot, slot_cmd, cmd_mask);
dbg("%s: SLOTCTRL %x write cmd %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -623,22 +628,18 @@ static void hpc_set_green_led_blink(struct slot *slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
- u16 slot_ctrl;
- int rc = 0;
+ u16 cmd_mask;
DBG_ENTER_ROUTINE
- rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
- if (rc) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- return;
+ slot_cmd = 0x0200;
+ cmd_mask = PWR_LED_CTRL;
+ if (!pciehp_poll_mode) {
+ slot_cmd = slot_cmd | HP_INTR_ENABLE;
+ cmd_mask = cmd_mask | HP_INTR_ENABLE;
}
- slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
-
- if (!pciehp_poll_mode)
- slot_cmd = slot_cmd | HP_INTR_ENABLE;
- pcie_write_cmd(slot, slot_cmd);
+ pcie_write_cmd(slot, slot_cmd, cmd_mask);
dbg("%s: SLOTCTRL %x write cmd %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -669,7 +670,8 @@ static int hpc_power_on_slot(struct slot * slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
- u16 slot_ctrl, slot_status;
+ u16 cmd_mask;
+ u16 slot_status;
int retval = 0;
DBG_ENTER_ROUTINE
@@ -692,23 +694,23 @@ static int hpc_power_on_slot(struct slot * slot)
}
}
- retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
- if (retval) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- return retval;
- }
-
- slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
-
+ slot_cmd = POWER_ON;
+ cmd_mask = PWR_CTRL;
/* Enable detection that we turned off at slot power-off time */
- if (!pciehp_poll_mode)
+ if (!pciehp_poll_mode) {
slot_cmd = slot_cmd |
PWR_FAULT_DETECT_ENABLE |
MRL_DETECT_ENABLE |
PRSN_DETECT_ENABLE |
HP_INTR_ENABLE;
+ cmd_mask = cmd_mask |
+ PWR_FAULT_DETECT_ENABLE |
+ MRL_DETECT_ENABLE |
+ PRSN_DETECT_ENABLE |
+ HP_INTR_ENABLE;
+ }
- retval = pcie_write_cmd(slot, slot_cmd);
+ retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
if (retval) {
err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
@@ -726,21 +728,15 @@ static int hpc_power_off_slot(struct slot * slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
- u16 slot_ctrl;
+ u16 cmd_mask;
int retval = 0;
DBG_ENTER_ROUTINE
dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
- retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
- if (retval) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- return retval;
- }
-
- slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
-
+ slot_cmd = POWER_OFF;
+ cmd_mask = PWR_CTRL;
/*
* If we get MRL or presence detect interrupts now, the isr
* will notice the sticky power-fault bit too and issue power
@@ -748,14 +744,19 @@ static int hpc_power_off_slot(struct slot * slot)
* of command completions, since the power-fault bit remains on
* till the slot is powered on again.
*/
- if (!pciehp_poll_mode)
+ if (!pciehp_poll_mode) {
slot_cmd = (slot_cmd &
~PWR_FAULT_DETECT_ENABLE &
~MRL_DETECT_ENABLE &
~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
+ cmd_mask = cmd_mask |
+ PWR_FAULT_DETECT_ENABLE |
+ MRL_DETECT_ENABLE |
+ PRSN_DETECT_ENABLE |
+ HP_INTR_ENABLE;
+ }
- retval = pcie_write_cmd(slot, slot_cmd);
-
+ retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
if (retval) {
err("%s: Write command failed!\n", __FUNCTION__);
return -1;
@@ -775,6 +776,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
u16 temp_word;
int hp_slot = 0; /* only 1 slot per PCI Express port */
int rc = 0;
+ unsigned long flags;
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (rc) {
@@ -794,10 +796,12 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
/* Mask Hot-plug Interrupt Enable */
if (!pciehp_poll_mode) {
+ spin_lock_irqsave(&ctrl->lock, flags);
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
if (rc) {
err("%s: Cannot read SLOT_CTRL register\n",
__FUNCTION__);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return IRQ_NONE;
}
@@ -808,8 +812,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
if (rc) {
err("%s: Cannot write to SLOTCTRL register\n",
__FUNCTION__);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return IRQ_NONE;
}
+ spin_unlock_irqrestore(&ctrl->lock, flags);
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (rc) {
@@ -859,10 +865,12 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
}
/* Unmask Hot-plug Interrupt Enable */
if (!pciehp_poll_mode) {
+ spin_lock_irqsave(&ctrl->lock, flags);
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
if (rc) {
err("%s: Cannot read SLOTCTRL register\n",
__FUNCTION__);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return IRQ_NONE;
}
@@ -873,8 +881,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
if (rc) {
err("%s: Cannot write to SLOTCTRL register\n",
__FUNCTION__);
+ spin_unlock_irqrestore(&ctrl->lock, flags);
return IRQ_NONE;
}
+ spin_unlock_irqrestore(&ctrl->lock, flags);
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (rc) {
@@ -1237,6 +1247,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
mutex_init(&ctrl->crit_sect);
mutex_init(&ctrl->ctrl_lock);
+ spin_lock_init(&ctrl->lock);
/* setup wait queue */
init_waitqueue_head(&ctrl->queue);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d9cbd586ae4..be1df85e5e2 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -15,10 +15,10 @@
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/msi.h>
+#include <linux/smp.h>
#include <asm/errno.h>
#include <asm/io.h>
-#include <asm/smp.h>
#include "pci.h"
#include "msi.h"
@@ -333,7 +333,7 @@ static int msi_capability_init(struct pci_dev *dev)
msi_mask_bits_reg(pos, is_64bit_address(control)),
maskbits);
}
- list_add(&entry->list, &dev->msi_list);
+ list_add_tail(&entry->list, &dev->msi_list);
/* Configure MSI capability structure */
ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI);
@@ -404,7 +404,7 @@ static int msix_capability_init(struct pci_dev *dev,
entry->dev = dev;
entry->mask_base = base;
- list_add(&entry->list, &dev->msi_list);
+ list_add_tail(&entry->list, &dev->msi_list);
}
ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
@@ -558,12 +558,12 @@ static int msi_free_irqs(struct pci_dev* dev)
list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) {
- if (list_is_last(&entry->list, &dev->msi_list))
- iounmap(entry->mask_base);
-
writel(1, entry->mask_base + entry->msi_attrib.entry_nr
* PCI_MSIX_ENTRY_SIZE
+ PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+
+ if (list_is_last(&entry->list, &dev->msi_list))
+ iounmap(entry->mask_base);
}
list_del(&entry->list);
kfree(entry);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index b5ac810404c..c8062494009 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -55,8 +55,6 @@ acpi_query_osc (
status = acpi_evaluate_object(handle, "_OSC", &input, &output);
if (ACPI_FAILURE (status)) {
- printk(KERN_DEBUG
- "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
*ret_status = status;
return status;
}
@@ -124,11 +122,9 @@ acpi_run_osc (
in_params[3].buffer.pointer = (u8 *)context;
status = acpi_evaluate_object(handle, "_OSC", &input, &output);
- if (ACPI_FAILURE (status)) {
- printk(KERN_DEBUG
- "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
+ if (ACPI_FAILURE (status))
return status;
- }
+
out_obj = output.pointer;
if (out_obj->type != ACPI_TYPE_BUFFER) {
printk(KERN_DEBUG
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 284e83a527f..10dbdec8041 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -213,7 +213,8 @@ struct device_attribute pci_dev_attrs[] = {
};
static ssize_t
-pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
unsigned int size = 64;
@@ -285,7 +286,8 @@ pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
static ssize_t
-pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
unsigned int size = count;
@@ -352,7 +354,8 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
* callback routine (pci_legacy_read).
*/
ssize_t
-pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
struct class_device,
@@ -376,7 +379,8 @@ pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
* callback routine (pci_legacy_write).
*/
ssize_t
-pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
struct class_device,
@@ -499,7 +503,6 @@ static int pci_create_resource_files(struct pci_dev *pdev)
sprintf(res_attr_name, "resource%d", i);
res_attr->attr.name = res_attr_name;
res_attr->attr.mode = S_IRUSR | S_IWUSR;
- res_attr->attr.owner = THIS_MODULE;
res_attr->size = pci_resource_len(pdev, i);
res_attr->mmap = pci_mmap_resource;
res_attr->private = &pdev->resource[i];
@@ -529,7 +532,8 @@ static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
* writing anything except 0 enables it
*/
static ssize_t
-pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
@@ -552,7 +556,8 @@ pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
* device corresponding to @kobj.
*/
static ssize_t
-pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
void __iomem *rom;
@@ -582,7 +587,6 @@ static struct bin_attribute pci_config_attr = {
.attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 256,
.read = pci_read_config,
@@ -593,13 +597,17 @@ static struct bin_attribute pcie_config_attr = {
.attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 4096,
.read = pci_read_config,
.write = pci_write_config,
};
+int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
+{
+ return 0;
+}
+
int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
{
struct bin_attribute *rom_attr = NULL;
@@ -628,7 +636,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
rom_attr->attr.name = "rom";
rom_attr->attr.mode = S_IRUSR;
- rom_attr->attr.owner = THIS_MODULE;
rom_attr->read = pci_read_rom;
rom_attr->write = pci_write_rom;
retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
@@ -640,10 +647,14 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
}
}
/* add platform-specific attributes */
- pcibios_add_platform_entries(pdev);
+ if (pcibios_add_platform_entries(pdev))
+ goto err_rom_file;
return 0;
+err_rom_file:
+ if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
+ sysfs_remove_bin_file(&pdev->dev.kobj, rom_attr);
err_rom:
kfree(rom_attr);
err_resource_files:
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index fd47ac0c473..03fd59e80fe 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -406,6 +406,13 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
return 0;
+ /* find PCI PM capability in list */
+ pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+
+ /* abort if the device doesn't support PM capabilities */
+ if (!pm)
+ return -EIO;
+
/* Validate current state:
* Can enter D0 from any state, but if we can only go deeper
* to sleep if we're already in a low power state
@@ -418,13 +425,6 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
return 0; /* we're already there */
- /* find PCI PM capability in list */
- pm = pci_find_capability(dev, PCI_CAP_ID_PM);
-
- /* abort if the device doesn't support PM capabilities */
- if (!pm)
- return -EIO;
-
pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
if ((pmc & PCI_PM_CAP_VER_MASK) > 3) {
printk(KERN_DEBUG
@@ -1186,6 +1186,11 @@ int pci_set_mwi(struct pci_dev *dev)
return 0;
}
+int pci_try_set_mwi(struct pci_dev *dev)
+{
+ return 0;
+}
+
void pci_clear_mwi(struct pci_dev *dev)
{
}
@@ -1242,9 +1247,7 @@ pci_set_cacheline_size(struct pci_dev *dev)
* pci_set_mwi - enables memory-write-invalidate PCI transaction
* @dev: the PCI device for which MWI is enabled
*
- * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND,
- * and then calls @pcibios_set_mwi to do the needed arch specific
- * operations or a generic mwi-prep function.
+ * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND.
*
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
*/
@@ -1260,7 +1263,8 @@ pci_set_mwi(struct pci_dev *dev)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (! (cmd & PCI_COMMAND_INVALIDATE)) {
- pr_debug("PCI: Enabling Mem-Wr-Inval for device %s\n", pci_name(dev));
+ pr_debug("PCI: Enabling Mem-Wr-Inval for device %s\n",
+ pci_name(dev));
cmd |= PCI_COMMAND_INVALIDATE;
pci_write_config_word(dev, PCI_COMMAND, cmd);
}
@@ -1269,6 +1273,21 @@ pci_set_mwi(struct pci_dev *dev)
}
/**
+ * pci_try_set_mwi - enables memory-write-invalidate PCI transaction
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * Enables the Memory-Write-Invalidate transaction in %PCI_COMMAND.
+ * Callers are not required to check the return value.
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+int pci_try_set_mwi(struct pci_dev *dev)
+{
+ int rc = pci_set_mwi(dev);
+ return rc;
+}
+
+/**
* pci_clear_mwi - disables Memory-Write-Invalidate for device dev
* @dev: the PCI device to disable
*
@@ -1375,6 +1394,164 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
#endif
/**
+ * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
+ * @dev: PCI device to query
+ *
+ * Returns mmrbc: maximum designed memory read count in bytes
+ * or appropriate error value.
+ */
+int pcix_get_max_mmrbc(struct pci_dev *dev)
+{
+ int err, cap;
+ u32 stat;
+
+ cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (!cap)
+ return -EINVAL;
+
+ err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
+ if (err)
+ return -EINVAL;
+
+ return (stat & PCI_X_STATUS_MAX_READ) >> 12;
+}
+EXPORT_SYMBOL(pcix_get_max_mmrbc);
+
+/**
+ * pcix_get_mmrbc - get PCI-X maximum memory read byte count
+ * @dev: PCI device to query
+ *
+ * Returns mmrbc: maximum memory read count in bytes
+ * or appropriate error value.
+ */
+int pcix_get_mmrbc(struct pci_dev *dev)
+{
+ int ret, cap;
+ u32 cmd;
+
+ cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (!cap)
+ return -EINVAL;
+
+ ret = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
+ if (!ret)
+ ret = 512 << ((cmd & PCI_X_CMD_MAX_READ) >> 2);
+
+ return ret;
+}
+EXPORT_SYMBOL(pcix_get_mmrbc);
+
+/**
+ * pcix_set_mmrbc - set PCI-X maximum memory read byte count
+ * @dev: PCI device to query
+ * @mmrbc: maximum memory read count in bytes
+ * valid values are 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum memory read byte count, some bridges have erratas
+ * that prevent this.
+ */
+int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
+{
+ int cap, err = -EINVAL;
+ u32 stat, cmd, v, o;
+
+ if (mmrbc < 512 || mmrbc > 4096 || (mmrbc & (mmrbc-1)))
+ goto out;
+
+ v = ffs(mmrbc) - 10;
+
+ cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+ if (!cap)
+ goto out;
+
+ err = pci_read_config_dword(dev, cap + PCI_X_STATUS, &stat);
+ if (err)
+ goto out;
+
+ if (v > (stat & PCI_X_STATUS_MAX_READ) >> 21)
+ return -E2BIG;
+
+ err = pci_read_config_dword(dev, cap + PCI_X_CMD, &cmd);
+ if (err)
+ goto out;
+
+ o = (cmd & PCI_X_CMD_MAX_READ) >> 2;
+ if (o != v) {
+ if (v > o && dev->bus &&
+ (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC))
+ return -EIO;
+
+ cmd &= ~PCI_X_CMD_MAX_READ;
+ cmd |= v << 2;
+ err = pci_write_config_dword(dev, cap + PCI_X_CMD, cmd);
+ }
+out:
+ return err;
+}
+EXPORT_SYMBOL(pcix_set_mmrbc);
+
+/**
+ * pcie_get_readrq - get PCI Express read request size
+ * @dev: PCI device to query
+ *
+ * Returns maximum memory read request in bytes
+ * or appropriate error value.
+ */
+int pcie_get_readrq(struct pci_dev *dev)
+{
+ int ret, cap;
+ u16 ctl;
+
+ cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (!cap)
+ return -EINVAL;
+
+ ret = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+ if (!ret)
+ ret = 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
+
+ return ret;
+}
+EXPORT_SYMBOL(pcie_get_readrq);
+
+/**
+ * pcie_set_readrq - set PCI Express maximum memory read request
+ * @dev: PCI device to query
+ * @count: maximum memory read count in bytes
+ * valid values are 128, 256, 512, 1024, 2048, 4096
+ *
+ * If possible sets maximum read byte count
+ */
+int pcie_set_readrq(struct pci_dev *dev, int rq)
+{
+ int cap, err = -EINVAL;
+ u16 ctl, v;
+
+ if (rq < 128 || rq > 4096 || (rq & (rq-1)))
+ goto out;
+
+ v = (ffs(rq) - 8) << 12;
+
+ cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (!cap)
+ goto out;
+
+ err = pci_read_config_word(dev, cap + PCI_EXP_DEVCTL, &ctl);
+ if (err)
+ goto out;
+
+ if ((ctl & PCI_EXP_DEVCTL_READRQ) != v) {
+ ctl &= ~PCI_EXP_DEVCTL_READRQ;
+ ctl |= v;
+ err = pci_write_config_dword(dev, cap + PCI_EXP_DEVCTL, ctl);
+ }
+
+out:
+ return err;
+}
+EXPORT_SYMBOL(pcie_set_readrq);
+
+/**
* pci_select_bars - Make BAR mask from the type of resource
* @dev: the PCI device for which BAR mask is made
* @flags: resource type mask to be selected
@@ -1442,6 +1619,7 @@ EXPORT_SYMBOL(pci_release_selected_regions);
EXPORT_SYMBOL(pci_request_selected_regions);
EXPORT_SYMBOL(pci_set_master);
EXPORT_SYMBOL(pci_set_mwi);
+EXPORT_SYMBOL(pci_try_set_mwi);
EXPORT_SYMBOL(pci_clear_mwi);
EXPORT_SYMBOL_GPL(pci_intx);
EXPORT_SYMBOL(pci_set_dma_mask);
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
index 3f37a60a643..c3bde588aa1 100644
--- a/drivers/pci/pcie/aer/Kconfig
+++ b/drivers/pci/pcie/aer/Kconfig
@@ -4,7 +4,7 @@
config PCIEAER
boolean "Root Port Advanced Error Reporting support"
- depends on PCIEPORTBUS && ACPI
+ depends on PCIEPORTBUS
default y
help
This enables PCI Express Root Port Advanced Error Reporting
diff --git a/drivers/pci/pcie/aer/Makefile b/drivers/pci/pcie/aer/Makefile
index 15a4f40d520..8da3bd8455a 100644
--- a/drivers/pci/pcie/aer/Makefile
+++ b/drivers/pci/pcie/aer/Makefile
@@ -4,5 +4,6 @@
obj-$(CONFIG_PCIEAER) += aerdriver.o
-aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o aerdrv_acpi.o
+aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o
+aerdriver-$(CONFIG_ACPI) += aerdrv_acpi.o
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index db6ad8e763a..6846fb42b39 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -157,7 +157,7 @@ static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev)
* Initialize Root lock access, e_lock, to Root Error Status Reg,
* Root Error ID Reg, and Root error producer/consumer index.
*/
- rpc->e_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&rpc->e_lock);
rpc->rpd = dev;
INIT_WORK(&rpc->dpc_handler, aer_isr);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index 5cca394d599..c7ad68b6c6d 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -19,10 +19,6 @@
#define AER_ERROR_MASK 0x001fffff
#define AER_ERROR(d) (d & AER_ERROR_MASK)
-#define OSC_METHOD_RUN_SUCCESS 0
-#define OSC_METHOD_NOT_SUPPORTED 1
-#define OSC_METHOD_RUN_FAILURE 2
-
/* Root Error Status Register Bits */
#define ROOT_ERR_STATUS_MASKS 0x0f
@@ -121,6 +117,14 @@ extern void aer_delete_rootport(struct aer_rpc *rpc);
extern int aer_init(struct pcie_device *dev);
extern void aer_isr(struct work_struct *work);
extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
-extern int aer_osc_setup(struct pci_dev *dev);
+
+#ifdef CONFIG_ACPI
+extern int aer_osc_setup(struct pcie_device *pciedev);
+#else
+static inline int aer_osc_setup(struct pcie_device *pciedev)
+{
+ return 0;
+}
+#endif
#endif //_AERDRV_H_
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index fa68e89ebec..1a1eb45a779 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -20,19 +20,18 @@
/**
* aer_osc_setup - run ACPI _OSC method
+ * @pciedev: pcie_device which AER is being enabled on
*
- * Return:
- * Zero if success. Nonzero for otherwise.
+ * @return: Zero on success. Nonzero otherwise.
*
* Invoked when PCIE bus loads AER service driver. To avoid conflict with
* BIOS AER support requires BIOS to yield AER control to OS native driver.
**/
-int aer_osc_setup(struct pci_dev *dev)
+int aer_osc_setup(struct pcie_device *pciedev)
{
- int retval = OSC_METHOD_RUN_SUCCESS;
- acpi_status status;
- acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
- struct pci_dev *pdev = dev;
+ acpi_status status = AE_NOT_FOUND;
+ struct pci_dev *pdev = pciedev->port;
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&pdev->dev);
struct pci_bus *parent;
while (!handle) {
@@ -50,19 +49,20 @@ int aer_osc_setup(struct pci_dev *dev)
pdev = parent->self;
}
- if (!handle)
- return OSC_METHOD_NOT_SUPPORTED;
+ if (handle) {
+ pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+ status = pci_osc_control_set(handle,
+ OSC_PCI_EXPRESS_AER_CONTROL |
+ OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+ }
- pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
- status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_AER_CONTROL |
- OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
if (ACPI_FAILURE(status)) {
- if (status == AE_SUPPORT)
- retval = OSC_METHOD_NOT_SUPPORTED;
- else
- retval = OSC_METHOD_RUN_FAILURE;
+ printk(KERN_DEBUG "AER service couldn't init device %s - %s\n",
+ pciedev->device.bus_id,
+ (status == AE_SUPPORT || status == AE_NOT_FOUND) ?
+ "no _OSC support" : "Run ACPI _OSC fails");
+ return -1;
}
- return retval;
+ return 0;
}
-
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 08e13033ced..92a8469b21b 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -22,8 +22,6 @@
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/suspend.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
#include <linux/delay.h>
#include "aerdrv.h"
@@ -119,6 +117,21 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
return 0;
}
+int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
+{
+ int pos;
+ u32 status;
+
+ pos = pci_find_aer_capability(dev);
+ if (!pos)
+ return -EIO;
+
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
+
+ return 0;
+}
+
static int find_device_iter(struct device *device, void *data)
{
struct pci_dev *dev;
@@ -733,20 +746,8 @@ void aer_delete_rootport(struct aer_rpc *rpc)
**/
int aer_init(struct pcie_device *dev)
{
- int status;
-
- /* Run _OSC Method */
- status = aer_osc_setup(dev->port);
-
- if(status != OSC_METHOD_RUN_SUCCESS) {
- printk(KERN_DEBUG "%s: AER service init fails - %s\n",
- __FUNCTION__,
- (status == OSC_METHOD_NOT_SUPPORTED) ?
- "No ACPI _OSC support" : "Run ACPI _OSC fails");
-
- if (!forceload)
- return status;
- }
+ if (aer_osc_setup(dev) && !forceload)
+ return -ENXIO;
return AER_SUCCESS;
}
@@ -755,4 +756,5 @@ EXPORT_SYMBOL_GPL(pci_find_aer_capability);
EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+EXPORT_SYMBOL_GPL(pci_cleanup_aer_correct_error_status);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index e48fcf08962..a7bce75c673 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -39,7 +39,6 @@ static void pci_create_legacy_files(struct pci_bus *b)
b->legacy_io->attr.name = "legacy_io";
b->legacy_io->size = 0xffff;
b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
- b->legacy_io->attr.owner = THIS_MODULE;
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
class_device_create_bin_file(&b->class_dev, b->legacy_io);
@@ -49,7 +48,6 @@ static void pci_create_legacy_files(struct pci_bus *b)
b->legacy_mem->attr.name = "legacy_mem";
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
- b->legacy_mem->attr.owner = THIS_MODULE;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
class_device_create_bin_file(&b->class_dev, b->legacy_mem);
}
@@ -656,7 +654,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
pcibios_assign_all_busses() ? " " :
" (try 'pci=assign-busses')");
printk(KERN_WARNING "Please report the result to "
- "linux-kernel to fix this permanently\n");
+ "<bk@suse.de> to fix this permanently\n");
}
bus = bus->parent;
}
@@ -702,6 +700,7 @@ static int pci_setup_device(struct pci_dev * dev)
dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+ dev->revision = class & 0xff;
class >>= 8; /* upper 3 bytes */
dev->class = class;
class >>= 8;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 0425a7b7350..cfa0dfe61b1 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -480,7 +480,6 @@ static int __init pci_proc_init(void)
__initcall(pci_proc_init);
#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pci_proc_attach_device);
EXPORT_SYMBOL(pci_proc_detach_bus);
#endif
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 6ccc2e95930..c559085c89a 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -587,10 +587,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_v
*/
static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
{
- u8 rev;
-
- pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
- if (rev >= 0x02) {
+ if (dev->revision >= 0x02) {
printk(KERN_WARNING "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
printk(KERN_WARNING " : booting with the \"noapic\" option.\n");
}
@@ -610,13 +607,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
#define AMD8131_NIOAMODE_BIT 0
static void quirk_amd_8131_ioapic(struct pci_dev *dev)
{
- unsigned char revid, tmp;
+ unsigned char tmp;
if (nr_ioapics == 0)
return;
- pci_read_config_byte(dev, PCI_REVISION_ID, &revid);
- if (revid == AMD8131_revA0 || revid == AMD8131_revB0) {
+ if (dev->revision == AMD8131_revA0 || dev->revision == AMD8131_revB0) {
printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n");
pci_read_config_byte( dev, AMD8131_MISC, &tmp);
tmp &= ~(1 << AMD8131_NIOAMODE_BIT);
@@ -627,6 +623,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
#endif /* CONFIG_X86_IO_APIC */
+/*
+ * Some settings of MMRBC can lead to data corruption so block changes.
+ * See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide
+ */
+static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
+{
+ unsigned char revid;
+
+ pci_read_config_byte(dev, PCI_REVISION_ID, &revid);
+ if (dev->subordinate && revid <= 0x12) {
+ printk(KERN_INFO "AMD8131 rev %x detected, disabling PCI-X "
+ "MMRBC\n", revid);
+ dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC;
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_mmrbc);
/*
* FIXME: it is questionable that quirk_via_acpi
@@ -843,10 +855,8 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, qu
static void quirk_disable_pxb(struct pci_dev *pdev)
{
u16 config;
- u8 rev;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
- if (rev != 0x04) /* Only C0 requires this */
+ if (pdev->revision != 0x04) /* Only C0 requires this */
return;
pci_read_config_word(pdev, 0x40, &config);
if (config & (1<<6)) {
@@ -1625,18 +1635,22 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_pcie_aer_ext_cap);
#ifdef CONFIG_PCI_MSI
-/* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely
- * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
- * some other busses controlled by the chipset even if Linux is not aware of it.
- * Instead of setting the flag on all busses in the machine, simply disable MSI
- * globally.
+/* Some chipsets do not support MSI. We cannot easily rely on setting
+ * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
+ * some other busses controlled by the chipset even if Linux is not
+ * aware of it. Instead of setting the flag on all busses in the
+ * machine, simply disable MSI globally.
*/
-static void __init quirk_svw_msi(struct pci_dev *dev)
+static void __init quirk_disable_all_msi(struct pci_dev *dev)
{
pci_no_msi();
printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n");
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
/* Disable MSI on chipsets that are known to not support it */
static void __devinit quirk_disable_msi(struct pci_dev *dev)
@@ -1649,8 +1663,6 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev)
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_msi);
/* Go through the list of Hypertransport capabilities and
* return 1 if a HT MSI capability is found and enabled */
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index d087e081771..dbbcc04abd1 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -54,6 +54,49 @@ static void pci_disable_rom(struct pci_dev *pdev)
}
/**
+ * pci_get_rom_size - obtain the actual size of the ROM image
+ * @rom: kernel virtual pointer to image of ROM
+ * @size: size of PCI window
+ * return: size of actual ROM image
+ *
+ * Determine the actual length of the ROM image.
+ * The PCI window size could be much larger than the
+ * actual image size.
+ */
+size_t pci_get_rom_size(void __iomem *rom, size_t size)
+{
+ void __iomem *image;
+ int last_image;
+
+ image = rom;
+ do {
+ void __iomem *pds;
+ /* Standard PCI ROMs start out with these bytes 55 AA */
+ if (readb(image) != 0x55)
+ break;
+ if (readb(image + 1) != 0xAA)
+ break;
+ /* get the PCI data structure and check its signature */
+ pds = image + readw(image + 24);
+ if (readb(pds) != 'P')
+ break;
+ if (readb(pds + 1) != 'C')
+ break;
+ if (readb(pds + 2) != 'I')
+ break;
+ if (readb(pds + 3) != 'R')
+ break;
+ last_image = readb(pds + 21) & 0x80;
+ /* this length is reliable */
+ image += readw(pds + 16) * 512;
+ } while (!last_image);
+
+ /* never return a size larger than the PCI resource window */
+ /* there are known ROMs that get the size wrong */
+ return min((size_t)(image - rom), size);
+}
+
+/**
* pci_map_rom - map a PCI ROM to kernel space
* @pdev: pointer to pci device struct
* @size: pointer to receive size of pci window over ROM
@@ -68,8 +111,6 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
loff_t start;
void __iomem *rom;
- void __iomem *image;
- int last_image;
/*
* IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
@@ -117,33 +158,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
* size is much larger than the actual size of the ROM.
* True size is important if the ROM is going to be copied.
*/
- image = rom;
- do {
- void __iomem *pds;
- /* Standard PCI ROMs start out with these bytes 55 AA */
- if (readb(image) != 0x55)
- break;
- if (readb(image + 1) != 0xAA)
- break;
- /* get the PCI data structure and check its signature */
- pds = image + readw(image + 24);
- if (readb(pds) != 'P')
- break;
- if (readb(pds + 1) != 'C')
- break;
- if (readb(pds + 2) != 'I')
- break;
- if (readb(pds + 3) != 'R')
- break;
- last_image = readb(pds + 21) & 0x80;
- /* this length is reliable */
- image += readw(pds + 16) * 512;
- } while (!last_image);
-
- /* never return a size larger than the PCI resource window */
- /* there are known ROMs that get the size wrong */
- *size = min((size_t)(image - rom), *size);
-
+ *size = pci_get_rom_size(rom, *size);
return rom;
}
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index b137a27472c..9f7090fa877 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -139,12 +139,14 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
}
/**
- * pci_get_bus_and_slot - locate PCI device from a given PCI slot
+ * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
* @bus: number of PCI bus on which desired PCI device resides
* @devfn: encodes number of PCI slot in which the desired PCI
* device resides and the logical device number within that slot
* in case of multi-function devices.
*
+ * Note: the bus/slot search is limited to PCI domain (segment) 0.
+ *
* Given a PCI bus and slot/function number, the desired PCI device
* is located in system global list of PCI devices. If the device
* is found, a pointer to its data structure is returned. If no
@@ -157,7 +159,8 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
struct pci_dev *dev = NULL;
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- if (dev->bus->number == bus && dev->devfn == devfn)
+ if (pci_domain_nr(dev->bus) == 0 &&
+ (dev->bus->number == bus && dev->devfn == devfn))
return dev;
}
return NULL;
@@ -403,10 +406,11 @@ const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
while (ids->vendor || ids->subvendor || ids->class_mask) {
list_for_each_entry(dev, &pci_devices, global_list) {
if ((found = pci_match_one_device(ids, dev)) != NULL)
- break;
+ goto exit;
}
ids++;
}
+exit:
up_read(&pci_bus_sem);
return found;
}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 5ec297d7a5b..5e5191ec8de 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -34,8 +34,6 @@
#define DBG(x...)
#endif
-#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
-
static void pbus_assign_resources_sorted(struct pci_bus *bus)
{
struct pci_dev *dev;
@@ -310,7 +308,7 @@ static void pbus_size_io(struct pci_bus *bus)
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
size = (size & 0xff) + ((size & ~0xffUL) << 2);
#endif
- size = ROUND_UP(size + size1, 4096);
+ size = ALIGN(size + size1, 4096);
if (!size) {
b_res->flags = 0;
return;
@@ -378,11 +376,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
if (!align)
min_align = align1;
- else if (ROUND_UP(align + min_align, min_align) < align1)
+ else if (ALIGN(align + min_align, min_align) < align1)
min_align = align1 >> 1;
align += aligns[order];
}
- size = ROUND_UP(size, min_align);
+ size = ALIGN(size, min_align);
if (!size) {
b_res->flags = 0;
return 1;
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 9d37fec27f2..2ac050d7f8c 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -23,14 +23,14 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
u8 byte;
u16 word;
u32 dword;
- long err, cfg_ret;
+ long err;
+ long cfg_ret;
- err = -EPERM;
if (!capable(CAP_SYS_ADMIN))
- goto error;
+ return -EPERM;
err = -ENODEV;
- dev = pci_find_slot(bus, dfn);
+ dev = pci_get_bus_and_slot(bus, dfn);
if (!dev)
goto error;
@@ -66,7 +66,8 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
case 4:
err = put_user(dword, (unsigned int __user *)buf);
break;
- };
+ }
+ pci_dev_put(dev);
return err;
error:
@@ -83,7 +84,8 @@ error:
case 4:
put_user(-1, (unsigned int __user *)buf);
break;
- };
+ }
+ pci_dev_put(dev);
return err;
}
@@ -101,7 +103,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- dev = pci_find_slot(bus, dfn);
+ dev = pci_get_bus_and_slot(bus, dfn);
if (!dev)
return -ENODEV;
@@ -137,8 +139,8 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
default:
err = -EINVAL;
break;
- };
+ }
unlock_kernel();
-
+ pci_dev_put(dev);
return err;
}
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index 948efc775a7..eb6abd3f922 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -336,16 +336,21 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
enable_irq_wake(board->det_pin);
if (board->irq_pin)
enable_irq_wake(board->irq_pin);
- } else {
- disable_irq_wake(board->det_pin);
- if (board->irq_pin)
- disable_irq_wake(board->irq_pin);
}
return 0;
}
static int at91_cf_resume(struct platform_device *pdev)
{
+ struct at91_cf_socket *cf = platform_get_drvdata(pdev);
+ struct at91_cf_data *board = cf->board;
+
+ if (device_may_wakeup(&pdev->dev)) {
+ disable_irq_wake(board->det_pin);
+ if (board->irq_pin)
+ disable_irq_wake(board->irq_pin);
+ }
+
pcmcia_socket_dev_resume(&pdev->dev);
return 0;
}
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index a2bb46526b5..b4409002b7f 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -283,7 +283,9 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, loff_t off
return (ret);
}
-static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t pccard_show_cis(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
unsigned int size = 0x200;
@@ -311,7 +313,9 @@ static ssize_t pccard_show_cis(struct kobject *kobj, char *buf, loff_t off, size
return (count);
}
-static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t pccard_store_cis(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct pcmcia_socket *s = to_socket(container_of(kobj, struct device, kobj));
cisdump_t *cis;
@@ -366,7 +370,7 @@ static struct device_attribute *pccard_socket_attributes[] = {
};
static struct bin_attribute pccard_cis_attr = {
- .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR, .owner = THIS_MODULE},
+ .attr = { .name = "cis", .mode = S_IRUGO | S_IWUSR },
.size = 0x200,
.read = pccard_show_cis,
.write = pccard_store_cis,
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 277df50c89a..7c3236690cc 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -107,31 +107,106 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
return;
}
+static int quirk_smc_fir_enabled(struct pnp_dev *dev)
+{
+ unsigned long firbase;
+ u8 bank, high, low, chip;
+
+ if (!pnp_port_valid(dev, 1))
+ return 0;
+
+ firbase = pnp_port_start(dev, 1);
+
+ /* Select register bank 3 */
+ bank = inb(firbase + 7);
+ bank &= 0xf0;
+ bank |= 3;
+ outb(bank, firbase + 7);
+
+ high = inb(firbase + 0);
+ low = inb(firbase + 1);
+ chip = inb(firbase + 2);
+
+ /* This corresponds to the check in smsc_ircc_present() */
+ if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2))
+ return 1;
+
+ return 0;
+}
+
static void quirk_smc_enable(struct pnp_dev *dev)
{
- unsigned int firbase;
+ struct resource fir, sir, irq;
- if (!dev->active || !pnp_port_valid(dev, 1))
+ pnp_activate_dev(dev);
+ if (quirk_smc_fir_enabled(dev))
return;
/*
- * On the HP/Compaq nw8240 (and probably other similar machines),
- * there is an SMCF010 device with two I/O port regions:
- *
- * 0x3e8-0x3ef SIR
- * 0x100-0x10f FIR
+ * Sometimes the BIOS claims the device is enabled, but it reports
+ * the wrong FIR resources or doesn't properly configure ISA or LPC
+ * bridges on the way to the device.
*
- * _STA reports the device is enabled, but in fact, the BIOS
- * neglects to enable the FIR range. Fortunately, it does fully
- * enable the device if we call _SRS.
+ * HP nc6000 and nc8000/nw8000 laptops have known problems like
+ * this. Fortunately, they do fix things up if we auto-configure
+ * the device using its _PRS and _SRS methods.
*/
- firbase = pnp_port_start(dev, 1);
- if (inb(firbase + 0x7 /* IRCC_MASTER */) == 0xff) {
- pnp_err("%s (%s) enabled but not responding, disabling and "
- "re-enabling", dev->dev.bus_id, pnp_dev_name(dev));
- pnp_disable_dev(dev);
- pnp_activate_dev(dev);
+ dev_err(&dev->dev, "%s not responding at SIR 0x%lx, FIR 0x%lx; "
+ "auto-configuring\n", dev->id->id,
+ (unsigned long) pnp_port_start(dev, 0),
+ (unsigned long) pnp_port_start(dev, 1));
+
+ pnp_disable_dev(dev);
+ pnp_init_resource_table(&dev->res);
+ pnp_auto_config_dev(dev);
+ pnp_activate_dev(dev);
+ if (quirk_smc_fir_enabled(dev)) {
+ dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n",
+ (unsigned long) pnp_port_start(dev, 0),
+ (unsigned long) pnp_port_start(dev, 1));
+ return;
}
+
+ /*
+ * The Toshiba Portege 4000 _CRS reports the FIR region first,
+ * followed by the SIR region. The BIOS will configure the bridge,
+ * but only if we call _SRS with SIR first, then FIR. It also
+ * reports the IRQ as active high, when it is really active low.
+ */
+ dev_err(&dev->dev, "not responding at SIR 0x%lx, FIR 0x%lx; "
+ "swapping SIR/FIR and reconfiguring\n",
+ (unsigned long) pnp_port_start(dev, 0),
+ (unsigned long) pnp_port_start(dev, 1));
+
+ /*
+ * Clear IORESOURCE_AUTO so pnp_activate_dev() doesn't reassign
+ * these resources any more.
+ */
+ fir = dev->res.port_resource[0];
+ sir = dev->res.port_resource[1];
+ fir.flags &= ~IORESOURCE_AUTO;
+ sir.flags &= ~IORESOURCE_AUTO;
+
+ irq = dev->res.irq_resource[0];
+ irq.flags &= ~IORESOURCE_AUTO;
+ irq.flags &= ~IORESOURCE_BITS;
+ irq.flags |= IORESOURCE_IRQ_LOWEDGE;
+
+ pnp_disable_dev(dev);
+ dev->res.port_resource[0] = sir;
+ dev->res.port_resource[1] = fir;
+ dev->res.irq_resource[0] = irq;
+ pnp_activate_dev(dev);
+
+ if (quirk_smc_fir_enabled(dev)) {
+ dev_err(&dev->dev, "responds at SIR 0x%lx, FIR 0x%lx\n",
+ (unsigned long) pnp_port_start(dev, 0),
+ (unsigned long) pnp_port_start(dev, 1));
+ return;
+ }
+
+ dev_err(&dev->dev, "giving up; try \"smsc-ircc2.nopnp\" and "
+ "email bjorn.helgaas@hp.com\n");
}
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
new file mode 100644
index 00000000000..3f6e176e6ea
--- /dev/null
+++ b/drivers/power/Kconfig
@@ -0,0 +1,52 @@
+menuconfig POWER_SUPPLY
+ tristate "Power supply class support"
+ help
+ Say Y here to enable power supply class support. This allows
+ power supply (batteries, AC, USB) monitoring by userspace
+ via sysfs and uevent (if available) and/or APM kernel interface
+ (if selected below).
+
+if POWER_SUPPLY
+
+config POWER_SUPPLY_DEBUG
+ bool "Power supply debug"
+ help
+ Say Y here to enable debugging messages for power supply class
+ and drivers.
+
+config PDA_POWER
+ tristate "Generic PDA/phone power driver"
+ depends on !S390
+ help
+ Say Y here to enable generic power driver for PDAs and phones with
+ one or two external power supplies (AC/USB) connected to main and
+ backup batteries, and optional builtin charger.
+
+config APM_POWER
+ tristate "APM emulation for class batteries"
+ depends on APM_EMULATION
+ help
+ Say Y here to enable support APM status emulation using
+ battery class devices.
+
+config BATTERY_DS2760
+ tristate "DS2760 battery driver (HP iPAQ & others)"
+ select W1
+ select W1_SLAVE_DS2760
+ help
+ Say Y here to enable support for batteries with ds2760 chip.
+
+config BATTERY_PMU
+ tristate "Apple PMU battery"
+ depends on ADB_PMU
+ help
+ Say Y here to expose battery information on Apple machines
+ through the generic battery class.
+
+config BATTERY_OLPC
+ tristate "One Laptop Per Child battery"
+ depends on X86_32 && OLPC
+ help
+ Say Y to enable support for the battery on the OLPC laptop.
+
+endif # POWER_SUPPLY
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
new file mode 100644
index 00000000000..6413ded5fe5
--- /dev/null
+++ b/drivers/power/Makefile
@@ -0,0 +1,22 @@
+power_supply-objs := power_supply_core.o
+
+ifeq ($(CONFIG_SYSFS),y)
+power_supply-objs += power_supply_sysfs.o
+endif
+
+ifeq ($(CONFIG_LEDS_TRIGGERS),y)
+power_supply-objs += power_supply_leds.o
+endif
+
+ifeq ($(CONFIG_POWER_SUPPLY_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
+
+obj-$(CONFIG_PDA_POWER) += pda_power.o
+obj-$(CONFIG_APM_POWER) += apm_power.o
+
+obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o
+obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o
+obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c
new file mode 100644
index 00000000000..042bd950d03
--- /dev/null
+++ b/drivers/power/apm_power.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2007 Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Author: Eugeny Boger <eugenyboger@dgap.mipt.ru>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ */
+
+#include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/apm-emulation.h>
+
+#define PSY_PROP(psy, prop, val) psy->get_property(psy, \
+ POWER_SUPPLY_PROP_##prop, val)
+
+#define _MPSY_PROP(prop, val) main_battery->get_property(main_battery, \
+ prop, val)
+
+#define MPSY_PROP(prop, val) _MPSY_PROP(POWER_SUPPLY_PROP_##prop, val)
+
+static struct power_supply *main_battery;
+
+static void find_main_battery(void)
+{
+ struct device *dev;
+ struct power_supply *bat, *batm;
+ union power_supply_propval full;
+ int max_charge = 0;
+
+ main_battery = NULL;
+ batm = NULL;
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ bat = dev_get_drvdata(dev);
+ /* If none of battery devices cantains 'use_for_apm' flag,
+ choice one with maximum design charge */
+ if (!PSY_PROP(bat, CHARGE_FULL_DESIGN, &full)) {
+ if (full.intval > max_charge) {
+ batm = bat;
+ max_charge = full.intval;
+ }
+ }
+
+ if (bat->use_for_apm)
+ main_battery = bat;
+ }
+ if (!main_battery)
+ main_battery = batm;
+
+ return;
+}
+
+static int calculate_time(int status)
+{
+ union power_supply_propval charge_full, charge_empty;
+ union power_supply_propval charge, I;
+
+ if (MPSY_PROP(CHARGE_FULL, &charge_full)) {
+ /* if battery can't report this property, use design value */
+ if (MPSY_PROP(CHARGE_FULL_DESIGN, &charge_full))
+ return -1;
+ }
+
+ if (MPSY_PROP(CHARGE_EMPTY, &charge_empty)) {
+ /* if battery can't report this property, use design value */
+ if (MPSY_PROP(CHARGE_EMPTY_DESIGN, &charge_empty))
+ charge_empty.intval = 0;
+ }
+
+ if (MPSY_PROP(CHARGE_AVG, &charge)) {
+ /* if battery can't report average value, use momentary */
+ if (MPSY_PROP(CHARGE_NOW, &charge))
+ return -1;
+ }
+
+ if (MPSY_PROP(CURRENT_AVG, &I)) {
+ /* if battery can't report average value, use momentary */
+ if (MPSY_PROP(CURRENT_NOW, &I))
+ return -1;
+ }
+
+ if (status == POWER_SUPPLY_STATUS_CHARGING)
+ return ((charge.intval - charge_full.intval) * 60L) /
+ I.intval;
+ else
+ return -((charge.intval - charge_empty.intval) * 60L) /
+ I.intval;
+}
+
+static int calculate_capacity(int using_charge)
+{
+ enum power_supply_property full_prop, empty_prop;
+ enum power_supply_property full_design_prop, empty_design_prop;
+ enum power_supply_property now_prop, avg_prop;
+ union power_supply_propval empty, full, cur;
+ int ret;
+
+ if (using_charge) {
+ full_prop = POWER_SUPPLY_PROP_CHARGE_FULL;
+ empty_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY;
+ full_design_prop = POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN;
+ empty_design_prop = POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN;
+ now_prop = POWER_SUPPLY_PROP_CHARGE_NOW;
+ avg_prop = POWER_SUPPLY_PROP_CHARGE_AVG;
+ } else {
+ full_prop = POWER_SUPPLY_PROP_ENERGY_FULL;
+ empty_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY;
+ full_design_prop = POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN;
+ empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN;
+ now_prop = POWER_SUPPLY_PROP_ENERGY_NOW;
+ avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG;
+ }
+
+ if (_MPSY_PROP(full_prop, &full)) {
+ /* if battery can't report this property, use design value */
+ if (_MPSY_PROP(full_design_prop, &full))
+ return -1;
+ }
+
+ if (_MPSY_PROP(avg_prop, &cur)) {
+ /* if battery can't report average value, use momentary */
+ if (_MPSY_PROP(now_prop, &cur))
+ return -1;
+ }
+
+ if (_MPSY_PROP(empty_prop, &empty)) {
+ /* if battery can't report this property, use design value */
+ if (_MPSY_PROP(empty_design_prop, &empty))
+ empty.intval = 0;
+ }
+
+ if (full.intval - empty.intval)
+ ret = ((cur.intval - empty.intval) * 100L) /
+ (full.intval - empty.intval);
+ else
+ return -1;
+
+ if (ret > 100)
+ return 100;
+ else if (ret < 0)
+ return 0;
+
+ return ret;
+}
+
+static void apm_battery_apm_get_power_status(struct apm_power_info *info)
+{
+ union power_supply_propval status;
+ union power_supply_propval capacity, time_to_full, time_to_empty;
+
+ down(&power_supply_class->sem);
+ find_main_battery();
+ if (!main_battery) {
+ up(&power_supply_class->sem);
+ return;
+ }
+
+ /* status */
+
+ if (MPSY_PROP(STATUS, &status))
+ status.intval = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ /* ac line status */
+
+ if ((status.intval == POWER_SUPPLY_STATUS_CHARGING) ||
+ (status.intval == POWER_SUPPLY_STATUS_NOT_CHARGING) ||
+ (status.intval == POWER_SUPPLY_STATUS_FULL))
+ info->ac_line_status = APM_AC_ONLINE;
+ else
+ info->ac_line_status = APM_AC_OFFLINE;
+
+ /* battery life (i.e. capacity, in percents) */
+
+ if (MPSY_PROP(CAPACITY, &capacity) == 0) {
+ info->battery_life = capacity.intval;
+ } else {
+ /* try calculate using energy */
+ info->battery_life = calculate_capacity(0);
+ /* if failed try calculate using charge instead */
+ if (info->battery_life == -1)
+ info->battery_life = calculate_capacity(1);
+ }
+
+ /* charging status */
+
+ if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+ info->battery_status = APM_BATTERY_STATUS_CHARGING;
+ } else {
+ if (info->battery_life > 50)
+ info->battery_status = APM_BATTERY_STATUS_HIGH;
+ else if (info->battery_life > 5)
+ info->battery_status = APM_BATTERY_STATUS_LOW;
+ else
+ info->battery_status = APM_BATTERY_STATUS_CRITICAL;
+ }
+ info->battery_flag = info->battery_status;
+
+ /* time */
+
+ info->units = APM_UNITS_MINS;
+
+ if (status.intval == POWER_SUPPLY_STATUS_CHARGING) {
+ if (MPSY_PROP(TIME_TO_FULL_AVG, &time_to_full)) {
+ if (MPSY_PROP(TIME_TO_FULL_NOW, &time_to_full))
+ info->time = calculate_time(status.intval);
+ else
+ info->time = time_to_full.intval / 60;
+ }
+ } else {
+ if (MPSY_PROP(TIME_TO_EMPTY_AVG, &time_to_empty)) {
+ if (MPSY_PROP(TIME_TO_EMPTY_NOW, &time_to_empty))
+ info->time = calculate_time(status.intval);
+ else
+ info->time = time_to_empty.intval / 60;
+ }
+ }
+
+ up(&power_supply_class->sem);
+ return;
+}
+
+static int __init apm_battery_init(void)
+{
+ printk(KERN_INFO "APM Battery Driver\n");
+
+ apm_get_power_status = apm_battery_apm_get_power_status;
+ return 0;
+}
+
+static void __exit apm_battery_exit(void)
+{
+ apm_get_power_status = NULL;
+ return;
+}
+
+module_init(apm_battery_init);
+module_exit(apm_battery_exit);
+
+MODULE_AUTHOR("Eugeny Boger <eugenyboger@dgap.mipt.ru>");
+MODULE_DESCRIPTION("APM emulation driver for battery monitoring class");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
new file mode 100644
index 00000000000..00e1ea6f1de
--- /dev/null
+++ b/drivers/power/ds2760_battery.c
@@ -0,0 +1,470 @@
+/*
+ * Driver for batteries with DS2760 chips inside.
+ *
+ * Copyright © 2007 Anton Vorontsov
+ * 2004-2007 Matt Reimer
+ * 2004 Szabolcs Gyurko
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * Author: Anton Vorontsov <cbou@mail.ru>
+ * February 2007
+ *
+ * Matt Reimer <mreimer@vpop.net>
+ * April 2004, 2005, 2007
+ *
+ * Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ * September 2004
+ */
+
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include "../w1/w1.h"
+#include "../w1/slaves/w1_ds2760.h"
+
+struct ds2760_device_info {
+ struct device *dev;
+
+ /* DS2760 data, valid after calling ds2760_battery_read_status() */
+ unsigned long update_time; /* jiffies when data read */
+ char raw[DS2760_DATA_SIZE]; /* raw DS2760 data */
+ int voltage_raw; /* units of 4.88 mV */
+ int voltage_uV; /* units of µV */
+ int current_raw; /* units of 0.625 mA */
+ int current_uA; /* units of µA */
+ int accum_current_raw; /* units of 0.25 mAh */
+ int accum_current_uAh; /* units of µAh */
+ int temp_raw; /* units of 0.125 °C */
+ int temp_C; /* units of 0.1 °C */
+ int rated_capacity; /* units of µAh */
+ int rem_capacity; /* percentage */
+ int full_active_uAh; /* units of µAh */
+ int empty_uAh; /* units of µAh */
+ int life_sec; /* units of seconds */
+ int charge_status; /* POWER_SUPPLY_STATUS_* */
+
+ int full_counter;
+ struct power_supply bat;
+ struct device *w1_dev;
+ struct workqueue_struct *monitor_wqueue;
+ struct delayed_work monitor_work;
+};
+
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+
+/* Some batteries have their rated capacity stored a N * 10 mAh, while
+ * others use an index into this table. */
+static int rated_capacities[] = {
+ 0,
+ 920, /* Samsung */
+ 920, /* BYD */
+ 920, /* Lishen */
+ 920, /* NEC */
+ 1440, /* Samsung */
+ 1440, /* BYD */
+ 1440, /* Lishen */
+ 1440, /* NEC */
+ 2880, /* Samsung */
+ 2880, /* BYD */
+ 2880, /* Lishen */
+ 2880 /* NEC */
+};
+
+/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C
+ * temp is in Celsius */
+static int battery_interpolate(int array[], int temp)
+{
+ int index, dt;
+
+ if (temp <= 0)
+ return array[0];
+ if (temp >= 40)
+ return array[4];
+
+ index = temp / 10;
+ dt = temp % 10;
+
+ return array[index] + (((array[index + 1] - array[index]) * dt) / 10);
+}
+
+static int ds2760_battery_read_status(struct ds2760_device_info *di)
+{
+ int ret, i, start, count, scale[5];
+
+ if (di->update_time && time_before(jiffies, di->update_time +
+ msecs_to_jiffies(cache_time)))
+ return 0;
+
+ /* The first time we read the entire contents of SRAM/EEPROM,
+ * but after that we just read the interesting bits that change. */
+ if (di->update_time == 0) {
+ start = 0;
+ count = DS2760_DATA_SIZE;
+ } else {
+ start = DS2760_VOLTAGE_MSB;
+ count = DS2760_TEMP_LSB - start + 1;
+ }
+
+ ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);
+ if (ret != count) {
+ dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",
+ di->w1_dev);
+ return 1;
+ }
+
+ di->update_time = jiffies;
+
+ /* DS2760 reports voltage in units of 4.88mV, but the battery class
+ * reports in units of uV, so convert by multiplying by 4880. */
+ di->voltage_raw = (di->raw[DS2760_VOLTAGE_MSB] << 3) |
+ (di->raw[DS2760_VOLTAGE_LSB] >> 5);
+ di->voltage_uV = di->voltage_raw * 4880;
+
+ /* DS2760 reports current in signed units of 0.625mA, but the battery
+ * class reports in units of µA, so convert by multiplying by 625. */
+ di->current_raw =
+ (((signed char)di->raw[DS2760_CURRENT_MSB]) << 5) |
+ (di->raw[DS2760_CURRENT_LSB] >> 3);
+ di->current_uA = di->current_raw * 625;
+
+ /* DS2760 reports accumulated current in signed units of 0.25mAh. */
+ di->accum_current_raw =
+ (((signed char)di->raw[DS2760_CURRENT_ACCUM_MSB]) << 8) |
+ di->raw[DS2760_CURRENT_ACCUM_LSB];
+ di->accum_current_uAh = di->accum_current_raw * 250;
+
+ /* DS2760 reports temperature in signed units of 0.125°C, but the
+ * battery class reports in units of 1/10 °C, so we convert by
+ * multiplying by .125 * 10 = 1.25. */
+ di->temp_raw = (((signed char)di->raw[DS2760_TEMP_MSB]) << 3) |
+ (di->raw[DS2760_TEMP_LSB] >> 5);
+ di->temp_C = di->temp_raw + (di->temp_raw / 4);
+
+ /* At least some battery monitors (e.g. HP iPAQ) store the battery's
+ * maximum rated capacity. */
+ if (di->raw[DS2760_RATED_CAPACITY] < ARRAY_SIZE(rated_capacities))
+ di->rated_capacity = rated_capacities[
+ (unsigned int)di->raw[DS2760_RATED_CAPACITY]];
+ else
+ di->rated_capacity = di->raw[DS2760_RATED_CAPACITY] * 10;
+
+ di->rated_capacity *= 1000; /* convert to µAh */
+
+ /* Calculate the full level at the present temperature. */
+ di->full_active_uAh = di->raw[DS2760_ACTIVE_FULL] << 8 |
+ di->raw[DS2760_ACTIVE_FULL + 1];
+
+ scale[0] = di->raw[DS2760_ACTIVE_FULL] << 8 |
+ di->raw[DS2760_ACTIVE_FULL + 1];
+ for (i = 1; i < 5; i++)
+ scale[i] = scale[i - 1] + di->raw[DS2760_ACTIVE_FULL + 2 + i];
+
+ di->full_active_uAh = battery_interpolate(scale, di->temp_C / 10);
+ di->full_active_uAh *= 1000; /* convert to µAh */
+
+ /* Calculate the empty level at the present temperature. */
+ scale[4] = di->raw[DS2760_ACTIVE_EMPTY + 4];
+ for (i = 3; i >= 0; i--)
+ scale[i] = scale[i + 1] + di->raw[DS2760_ACTIVE_EMPTY + i];
+
+ di->empty_uAh = battery_interpolate(scale, di->temp_C / 10);
+ di->empty_uAh *= 1000; /* convert to µAh */
+
+ /* From Maxim Application Note 131: remaining capacity =
+ * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */
+ di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) /
+ (di->full_active_uAh - di->empty_uAh);
+
+ if (di->rem_capacity < 0)
+ di->rem_capacity = 0;
+ if (di->rem_capacity > 100)
+ di->rem_capacity = 100;
+
+ if (di->current_uA)
+ di->life_sec = -((di->accum_current_uAh - di->empty_uAh) *
+ 3600L) / di->current_uA;
+ else
+ di->life_sec = 0;
+
+ return 0;
+}
+
+static void ds2760_battery_update_status(struct ds2760_device_info *di)
+{
+ int old_charge_status = di->charge_status;
+
+ ds2760_battery_read_status(di);
+
+ if (di->charge_status == POWER_SUPPLY_STATUS_UNKNOWN)
+ di->full_counter = 0;
+
+ if (power_supply_am_i_supplied(&di->bat)) {
+ if (di->current_uA > 10000) {
+ di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+ di->full_counter = 0;
+ } else if (di->current_uA < -5000) {
+ if (di->charge_status != POWER_SUPPLY_STATUS_NOT_CHARGING)
+ dev_notice(di->dev, "not enough power to "
+ "charge\n");
+ di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ di->full_counter = 0;
+ } else if (di->current_uA < 10000 &&
+ di->charge_status != POWER_SUPPLY_STATUS_FULL) {
+
+ /* Don't consider the battery to be full unless
+ * we've seen the current < 10 mA at least two
+ * consecutive times. */
+
+ di->full_counter++;
+
+ if (di->full_counter < 2) {
+ di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else {
+ unsigned char acr[2];
+ int acr_val;
+
+ /* acr is in units of 0.25 mAh */
+ acr_val = di->full_active_uAh * 4L / 1000;
+
+ acr[0] = acr_val >> 8;
+ acr[1] = acr_val & 0xff;
+
+ if (w1_ds2760_write(di->w1_dev, acr,
+ DS2760_CURRENT_ACCUM_MSB, 2) < 2)
+ dev_warn(di->dev,
+ "ACR reset failed\n");
+
+ di->charge_status = POWER_SUPPLY_STATUS_FULL;
+ }
+ }
+ } else {
+ di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
+ di->full_counter = 0;
+ }
+
+ if (di->charge_status != old_charge_status)
+ power_supply_changed(&di->bat);
+
+ return;
+}
+
+static void ds2760_battery_work(struct work_struct *work)
+{
+ struct ds2760_device_info *di = container_of(work,
+ struct ds2760_device_info, monitor_work.work);
+ const int interval = HZ * 60;
+
+ dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+ ds2760_battery_update_status(di);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, interval);
+
+ return;
+}
+
+#define to_ds2760_device_info(x) container_of((x), struct ds2760_device_info, \
+ bat);
+
+static void ds2760_battery_external_power_changed(struct power_supply *psy)
+{
+ struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+ dev_dbg(di->dev, "%s\n", __FUNCTION__);
+
+ cancel_delayed_work(&di->monitor_work);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ/10);
+
+ return;
+}
+
+static int ds2760_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct ds2760_device_info *di = to_ds2760_device_info(psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = di->charge_status;
+ return 0;
+ default:
+ break;
+ }
+
+ ds2760_battery_read_status(di);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ val->intval = di->voltage_uV;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ val->intval = di->current_uA;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ val->intval = di->rated_capacity;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = di->full_active_uAh;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_EMPTY:
+ val->intval = di->empty_uAh;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ val->intval = di->accum_current_uAh;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = di->temp_C;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property ds2760_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_TEMP,
+};
+
+static int ds2760_battery_probe(struct platform_device *pdev)
+{
+ int retval = 0;
+ struct ds2760_device_info *di;
+ struct ds2760_platform_data *pdata;
+
+ di = kzalloc(sizeof(*di), GFP_KERNEL);
+ if (!di) {
+ retval = -ENOMEM;
+ goto di_alloc_failed;
+ }
+
+ platform_set_drvdata(pdev, di);
+
+ pdata = pdev->dev.platform_data;
+ di->dev = &pdev->dev;
+ di->w1_dev = pdev->dev.parent;
+ di->bat.name = pdev->dev.bus_id;
+ di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
+ di->bat.properties = ds2760_battery_props;
+ di->bat.num_properties = ARRAY_SIZE(ds2760_battery_props);
+ di->bat.get_property = ds2760_battery_get_property;
+ di->bat.external_power_changed =
+ ds2760_battery_external_power_changed;
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ retval = power_supply_register(&pdev->dev, &di->bat);
+ if (retval) {
+ dev_err(di->dev, "failed to register battery");
+ goto batt_failed;
+ }
+
+ INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
+ di->monitor_wqueue = create_singlethread_workqueue(pdev->dev.bus_id);
+ if (!di->monitor_wqueue) {
+ retval = -ESRCH;
+ goto workqueue_failed;
+ }
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
+
+ goto success;
+
+workqueue_failed:
+ power_supply_unregister(&di->bat);
+batt_failed:
+ kfree(di);
+di_alloc_failed:
+success:
+ return retval;
+}
+
+static int ds2760_battery_remove(struct platform_device *pdev)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ cancel_rearming_delayed_workqueue(di->monitor_wqueue,
+ &di->monitor_work);
+ destroy_workqueue(di->monitor_wqueue);
+ power_supply_unregister(&di->bat);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int ds2760_battery_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+
+ return 0;
+}
+
+static int ds2760_battery_resume(struct platform_device *pdev)
+{
+ struct ds2760_device_info *di = platform_get_drvdata(pdev);
+
+ di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ power_supply_changed(&di->bat);
+
+ cancel_delayed_work(&di->monitor_work);
+ queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
+
+ return 0;
+}
+
+#else
+
+#define ds2760_battery_suspend NULL
+#define ds2760_battery_resume NULL
+
+#endif /* CONFIG_PM */
+
+static struct platform_driver ds2760_battery_driver = {
+ .driver = {
+ .name = "ds2760-battery",
+ },
+ .probe = ds2760_battery_probe,
+ .remove = ds2760_battery_remove,
+ .suspend = ds2760_battery_suspend,
+ .resume = ds2760_battery_resume,
+};
+
+static int __init ds2760_battery_init(void)
+{
+ return platform_driver_register(&ds2760_battery_driver);
+}
+
+static void __exit ds2760_battery_exit(void)
+{
+ platform_driver_unregister(&ds2760_battery_driver);
+ return;
+}
+
+module_init(ds2760_battery_init);
+module_exit(ds2760_battery_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
+ "Matt Reimer <mreimer@vpop.net>, "
+ "Anton Vorontsov <cbou@mail.ru>");
+MODULE_DESCRIPTION("ds2760 battery driver");
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
new file mode 100644
index 00000000000..878684df766
--- /dev/null
+++ b/drivers/power/olpc_battery.c
@@ -0,0 +1,352 @@
+/*
+ * Battery driver for One Laptop Per Child board.
+ *
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
+ *
+ * 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/err.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <asm/olpc.h>
+
+
+#define EC_BAT_VOLTAGE 0x10 /* uint16_t, *9.76/32, mV */
+#define EC_BAT_CURRENT 0x11 /* int16_t, *15.625/120, mA */
+#define EC_BAT_ACR 0x12
+#define EC_BAT_TEMP 0x13 /* uint16_t, *100/256, °C */
+#define EC_AMB_TEMP 0x14 /* uint16_t, *100/256, °C */
+#define EC_BAT_STATUS 0x15 /* uint8_t, bitmask */
+#define EC_BAT_SOC 0x16 /* uint8_t, percentage */
+#define EC_BAT_SERIAL 0x17 /* uint8_t[6] */
+#define EC_BAT_EEPROM 0x18 /* uint8_t adr as input, uint8_t output */
+#define EC_BAT_ERRCODE 0x1f /* uint8_t, bitmask */
+
+#define BAT_STAT_PRESENT 0x01
+#define BAT_STAT_FULL 0x02
+#define BAT_STAT_LOW 0x04
+#define BAT_STAT_DESTROY 0x08
+#define BAT_STAT_AC 0x10
+#define BAT_STAT_CHARGING 0x20
+#define BAT_STAT_DISCHARGING 0x40
+
+#define BAT_ERR_INFOFAIL 0x02
+#define BAT_ERR_OVERVOLTAGE 0x04
+#define BAT_ERR_OVERTEMP 0x05
+#define BAT_ERR_GAUGESTOP 0x06
+#define BAT_ERR_OUT_OF_CONTROL 0x07
+#define BAT_ERR_ID_FAIL 0x09
+#define BAT_ERR_ACR_FAIL 0x10
+
+#define BAT_ADDR_MFR_TYPE 0x5F
+
+/*********************************************************************
+ * Power
+ *********************************************************************/
+
+static int olpc_ac_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret = 0;
+ uint8_t status;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+ if (ret)
+ return ret;
+
+ val->intval = !!(status & BAT_STAT_AC);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property olpc_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply olpc_ac = {
+ .name = "olpc-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = olpc_ac_props,
+ .num_properties = ARRAY_SIZE(olpc_ac_props),
+ .get_property = olpc_ac_get_prop,
+};
+
+/*********************************************************************
+ * Battery properties
+ *********************************************************************/
+static int olpc_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret = 0;
+ int16_t ec_word;
+ uint8_t ec_byte;
+
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ /* Theoretically there's a race here -- the battery could be
+ removed immediately after we check whether it's present, and
+ then we query for some other property of the now-absent battery.
+ It doesn't matter though -- the EC will return the last-known
+ information, and it's as if we just ran that _little_ bit faster
+ and managed to read it out before the battery went away. */
+ if (!(ec_byte & BAT_STAT_PRESENT) && psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (olpc_platform_info.ecver > 0x44) {
+ if (ec_byte & BAT_STAT_CHARGING)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (ec_byte & BAT_STAT_DISCHARGING)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else /* er,... */
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ /* Older EC didn't report charge/discharge bits */
+ if (!(ec_byte & BAT_STAT_AC)) /* No AC means discharging */
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ else if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else /* Not _necessarily_ true but EC doesn't tell all yet */
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ }
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(ec_byte & BAT_STAT_PRESENT);
+ break;
+
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (ec_byte & BAT_STAT_DESTROY)
+ val->intval = POWER_SUPPLY_HEALTH_DEAD;
+ else {
+ ret = olpc_ec_cmd(EC_BAT_ERRCODE, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte) {
+ case 0:
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+
+ case BAT_ERR_OVERTEMP:
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ break;
+
+ case BAT_ERR_OVERVOLTAGE:
+ val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ break;
+
+ case BAT_ERR_INFOFAIL:
+ case BAT_ERR_OUT_OF_CONTROL:
+ case BAT_ERR_ID_FAIL:
+ case BAT_ERR_ACR_FAIL:
+ val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+ break;
+
+ default:
+ /* Eep. We don't know this failure code */
+ return -EIO;
+ }
+ }
+ break;
+
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ ec_byte = BAT_ADDR_MFR_TYPE;
+ ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte >> 4) {
+ case 1:
+ val->strval = "Gold Peak";
+ break;
+ case 2:
+ val->strval = "BYD";
+ break;
+ default:
+ val->strval = "Unknown";
+ break;
+ }
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ ec_byte = BAT_ADDR_MFR_TYPE;
+ ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1);
+ if (ret)
+ return ret;
+
+ switch (ec_byte & 0xf) {
+ case 1:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_NiMH;
+ break;
+ case 2:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LiFe;
+ break;
+ default:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+ break;
+ }
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ ret = olpc_ec_cmd(EC_BAT_VOLTAGE, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 9760L / 32;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 15625L / 120;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
+ if (ret)
+ return ret;
+ val->intval = ec_byte;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ if (ec_byte & BAT_STAT_FULL)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (ec_byte & BAT_STAT_LOW)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ ret = olpc_ec_cmd(EC_BAT_TEMP, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 100 / 256;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+ ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
+ if (ret)
+ return ret;
+
+ ec_word = be16_to_cpu(ec_word);
+ val->intval = ec_word * 100 / 256;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static enum power_supply_property olpc_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+/*********************************************************************
+ * Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static struct power_supply olpc_bat = {
+ .properties = olpc_bat_props,
+ .num_properties = ARRAY_SIZE(olpc_bat_props),
+ .get_property = olpc_bat_get_property,
+ .use_for_apm = 1,
+};
+
+void olpc_battery_trigger_uevent(unsigned long cause)
+{
+ if (cause & EC_SCI_SRC_ACPWR)
+ kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE);
+ if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY))
+ kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE);
+}
+
+static int __init olpc_bat_init(void)
+{
+ int ret = 0;
+ uint8_t status;
+
+ if (!olpc_platform_info.ecver)
+ return -ENXIO;
+ if (olpc_platform_info.ecver < 0x43) {
+ printk(KERN_NOTICE "OLPC EC version 0x%02x too old for battery driver.\n", olpc_platform_info.ecver);
+ return -ENXIO;
+ }
+
+ ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
+ if (ret)
+ return ret;
+
+ /* Ignore the status. It doesn't actually matter */
+
+ bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0);
+ if (IS_ERR(bat_pdev))
+ return PTR_ERR(bat_pdev);
+
+ ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
+ if (ret)
+ goto ac_failed;
+
+ olpc_bat.name = bat_pdev->name;
+
+ ret = power_supply_register(&bat_pdev->dev, &olpc_bat);
+ if (ret)
+ goto battery_failed;
+
+ olpc_register_battery_callback(&olpc_battery_trigger_uevent);
+ goto success;
+
+battery_failed:
+ power_supply_unregister(&olpc_ac);
+ac_failed:
+ platform_device_unregister(bat_pdev);
+success:
+ return ret;
+}
+
+static void __exit olpc_bat_exit(void)
+{
+ olpc_deregister_battery_callback();
+ power_supply_unregister(&olpc_bat);
+ power_supply_unregister(&olpc_ac);
+ platform_device_unregister(bat_pdev);
+ return;
+}
+
+module_init(olpc_bat_init);
+module_exit(olpc_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Battery driver for One Laptop Per Child 'XO' machine");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
new file mode 100644
index 00000000000..4e1eb040e14
--- /dev/null
+++ b/drivers/power/pda_power.c
@@ -0,0 +1,261 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/power_supply.h>
+#include <linux/pda_power.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+
+static inline unsigned int get_irq_flags(struct resource *res)
+{
+ unsigned int flags = IRQF_DISABLED | IRQF_SHARED;
+
+ flags |= res->flags & IRQF_TRIGGER_MASK;
+
+ return flags;
+}
+
+static struct device *dev;
+static struct pda_power_pdata *pdata;
+static struct resource *ac_irq, *usb_irq;
+static struct timer_list charger_timer;
+static struct timer_list supply_timer;
+
+static int pda_power_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ if (psy->type == POWER_SUPPLY_TYPE_MAINS)
+ val->intval = pdata->is_ac_online ?
+ pdata->is_ac_online() : 0;
+ else
+ val->intval = pdata->is_usb_online ?
+ pdata->is_usb_online() : 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static enum power_supply_property pda_power_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static char *pda_power_supplied_to[] = {
+ "main-battery",
+ "backup-battery",
+};
+
+static struct power_supply pda_power_supplies[] = {
+ {
+ .name = "ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .supplied_to = pda_power_supplied_to,
+ .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+ .properties = pda_power_props,
+ .num_properties = ARRAY_SIZE(pda_power_props),
+ .get_property = pda_power_get_property,
+ },
+ {
+ .name = "usb",
+ .type = POWER_SUPPLY_TYPE_USB,
+ .supplied_to = pda_power_supplied_to,
+ .num_supplicants = ARRAY_SIZE(pda_power_supplied_to),
+ .properties = pda_power_props,
+ .num_properties = ARRAY_SIZE(pda_power_props),
+ .get_property = pda_power_get_property,
+ },
+};
+
+static void update_charger(void)
+{
+ if (!pdata->set_charge)
+ return;
+
+ if (pdata->is_ac_online && pdata->is_ac_online()) {
+ dev_dbg(dev, "charger on (AC)\n");
+ pdata->set_charge(PDA_POWER_CHARGE_AC);
+ } else if (pdata->is_usb_online && pdata->is_usb_online()) {
+ dev_dbg(dev, "charger on (USB)\n");
+ pdata->set_charge(PDA_POWER_CHARGE_USB);
+ } else {
+ dev_dbg(dev, "charger off\n");
+ pdata->set_charge(0);
+ }
+
+ return;
+}
+
+static void supply_timer_func(unsigned long irq)
+{
+ if (ac_irq && irq == ac_irq->start)
+ power_supply_changed(&pda_power_supplies[0]);
+ else if (usb_irq && irq == usb_irq->start)
+ power_supply_changed(&pda_power_supplies[1]);
+ return;
+}
+
+static void charger_timer_func(unsigned long irq)
+{
+ update_charger();
+
+ /* Okay, charger set. Now wait a bit before notifying supplicants,
+ * charge power should stabilize. */
+ supply_timer.data = irq;
+ mod_timer(&supply_timer,
+ jiffies + msecs_to_jiffies(pdata->wait_for_charger));
+ return;
+}
+
+static irqreturn_t power_changed_isr(int irq, void *unused)
+{
+ /* Wait a bit before reading ac/usb line status and setting charger,
+ * because ac/usb status readings may lag from irq. */
+ charger_timer.data = irq;
+ mod_timer(&charger_timer,
+ jiffies + msecs_to_jiffies(pdata->wait_for_status));
+ return IRQ_HANDLED;
+}
+
+static int pda_power_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ dev = &pdev->dev;
+
+ if (pdev->id != -1) {
+ dev_err(dev, "it's meaningless to register several "
+ "pda_powers; use id = -1\n");
+ ret = -EINVAL;
+ goto wrongid;
+ }
+
+ pdata = pdev->dev.platform_data;
+
+ update_charger();
+
+ if (!pdata->wait_for_status)
+ pdata->wait_for_status = 500;
+
+ if (!pdata->wait_for_charger)
+ pdata->wait_for_charger = 500;
+
+ setup_timer(&charger_timer, charger_timer_func, 0);
+ setup_timer(&supply_timer, supply_timer_func, 0);
+
+ ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
+ usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
+ if (!ac_irq && !usb_irq) {
+ dev_err(dev, "no ac/usb irq specified\n");
+ ret = -ENODEV;
+ goto noirqs;
+ }
+
+ if (pdata->supplied_to) {
+ pda_power_supplies[0].supplied_to = pdata->supplied_to;
+ pda_power_supplies[1].supplied_to = pdata->supplied_to;
+ pda_power_supplies[0].num_supplicants = pdata->num_supplicants;
+ pda_power_supplies[1].num_supplicants = pdata->num_supplicants;
+ }
+
+ ret = power_supply_register(&pdev->dev, &pda_power_supplies[0]);
+ if (ret) {
+ dev_err(dev, "failed to register %s power supply\n",
+ pda_power_supplies[0].name);
+ goto supply0_failed;
+ }
+
+ ret = power_supply_register(&pdev->dev, &pda_power_supplies[1]);
+ if (ret) {
+ dev_err(dev, "failed to register %s power supply\n",
+ pda_power_supplies[1].name);
+ goto supply1_failed;
+ }
+
+ if (ac_irq) {
+ ret = request_irq(ac_irq->start, power_changed_isr,
+ get_irq_flags(ac_irq), ac_irq->name,
+ &pda_power_supplies[0]);
+ if (ret) {
+ dev_err(dev, "request ac irq failed\n");
+ goto ac_irq_failed;
+ }
+ }
+
+ if (usb_irq) {
+ ret = request_irq(usb_irq->start, power_changed_isr,
+ get_irq_flags(usb_irq), usb_irq->name,
+ &pda_power_supplies[1]);
+ if (ret) {
+ dev_err(dev, "request usb irq failed\n");
+ goto usb_irq_failed;
+ }
+ }
+
+ goto success;
+
+usb_irq_failed:
+ if (ac_irq)
+ free_irq(ac_irq->start, &pda_power_supplies[0]);
+ac_irq_failed:
+ power_supply_unregister(&pda_power_supplies[1]);
+supply1_failed:
+ power_supply_unregister(&pda_power_supplies[0]);
+supply0_failed:
+noirqs:
+wrongid:
+success:
+ return ret;
+}
+
+static int pda_power_remove(struct platform_device *pdev)
+{
+ if (usb_irq)
+ free_irq(usb_irq->start, &pda_power_supplies[1]);
+ if (ac_irq)
+ free_irq(ac_irq->start, &pda_power_supplies[0]);
+ del_timer_sync(&charger_timer);
+ del_timer_sync(&supply_timer);
+ power_supply_unregister(&pda_power_supplies[1]);
+ power_supply_unregister(&pda_power_supplies[0]);
+ return 0;
+}
+
+static struct platform_driver pda_power_pdrv = {
+ .driver = {
+ .name = "pda-power",
+ },
+ .probe = pda_power_probe,
+ .remove = pda_power_remove,
+};
+
+static int __init pda_power_init(void)
+{
+ return platform_driver_register(&pda_power_pdrv);
+}
+
+static void __exit pda_power_exit(void)
+{
+ platform_driver_unregister(&pda_power_pdrv);
+ return;
+}
+
+module_init(pda_power_init);
+module_exit(pda_power_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c
new file mode 100644
index 00000000000..2fea4af0e40
--- /dev/null
+++ b/drivers/power/pmu_battery.c
@@ -0,0 +1,215 @@
+/*
+ * Battery class driver for Apple PMU
+ *
+ * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+static struct pmu_battery_dev {
+ struct power_supply bat;
+ struct pmu_battery_info *pbi;
+ char name[16];
+ int propval;
+} *pbats[PMU_MAX_BATTERIES];
+
+#define to_pmu_battery_dev(x) container_of(x, struct pmu_battery_dev, bat)
+
+/*********************************************************************
+ * Power
+ *********************************************************************/
+
+static int pmu_get_ac_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = (!!(pmu_power_flags & PMU_PWR_AC_PRESENT)) ||
+ (pmu_battery_count == 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property pmu_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static struct power_supply pmu_ac = {
+ .name = "pmu-ac",
+ .type = POWER_SUPPLY_TYPE_MAINS,
+ .properties = pmu_ac_props,
+ .num_properties = ARRAY_SIZE(pmu_ac_props),
+ .get_property = pmu_get_ac_prop,
+};
+
+/*********************************************************************
+ * Battery properties
+ *********************************************************************/
+
+static char *pmu_batt_types[] = {
+ "Smart", "Comet", "Hooper", "Unknown"
+};
+
+static char *pmu_bat_get_model_name(struct pmu_battery_info *pbi)
+{
+ switch (pbi->flags & PMU_BATT_TYPE_MASK) {
+ case PMU_BATT_TYPE_SMART:
+ return pmu_batt_types[0];
+ case PMU_BATT_TYPE_COMET:
+ return pmu_batt_types[1];
+ case PMU_BATT_TYPE_HOOPER:
+ return pmu_batt_types[2];
+ default: break;
+ }
+ return pmu_batt_types[3];
+}
+
+static int pmu_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct pmu_battery_dev *pbat = to_pmu_battery_dev(psy);
+ struct pmu_battery_info *pbi = pbat->pbi;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (pbi->flags & PMU_BATT_CHARGING)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = !!(pbi->flags & PMU_BATT_PRESENT);
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ val->strval = pmu_bat_get_model_name(pbi);
+ break;
+ case POWER_SUPPLY_PROP_ENERGY_AVG:
+ val->intval = pbi->charge * 1000; /* mWh -> µWh */
+ break;
+ case POWER_SUPPLY_PROP_ENERGY_FULL:
+ val->intval = pbi->max_charge * 1000; /* mWh -> µWh */
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ val->intval = pbi->amperage * 1000; /* mA -> µA */
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ val->intval = pbi->voltage * 1000; /* mV -> µV */
+ break;
+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+ val->intval = pbi->time_remaining;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum power_supply_property pmu_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_ENERGY_AVG,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+};
+
+/*********************************************************************
+ * Initialisation
+ *********************************************************************/
+
+static struct platform_device *bat_pdev;
+
+static int __init pmu_bat_init(void)
+{
+ int ret;
+ int i;
+
+ bat_pdev = platform_device_register_simple("pmu-battery",
+ 0, NULL, 0);
+ if (IS_ERR(bat_pdev)) {
+ ret = PTR_ERR(bat_pdev);
+ goto pdev_register_failed;
+ }
+
+ ret = power_supply_register(&bat_pdev->dev, &pmu_ac);
+ if (ret)
+ goto ac_register_failed;
+
+ for (i = 0; i < pmu_battery_count; i++) {
+ struct pmu_battery_dev *pbat = kzalloc(sizeof(*pbat),
+ GFP_KERNEL);
+ if (!pbat)
+ break;
+
+ sprintf(pbat->name, "PMU battery %d", i);
+ pbat->bat.name = pbat->name;
+ pbat->bat.properties = pmu_bat_props;
+ pbat->bat.num_properties = ARRAY_SIZE(pmu_bat_props);
+ pbat->bat.get_property = pmu_bat_get_property;
+ pbat->pbi = &pmu_batteries[i];
+
+ ret = power_supply_register(&bat_pdev->dev, &pbat->bat);
+ if (ret) {
+ kfree(pbat);
+ goto battery_register_failed;
+ }
+ pbats[i] = pbat;
+ }
+
+ goto success;
+
+battery_register_failed:
+ while (i--) {
+ if (!pbats[i])
+ continue;
+ power_supply_unregister(&pbats[i]->bat);
+ kfree(pbats[i]);
+ }
+ power_supply_unregister(&pmu_ac);
+ac_register_failed:
+ platform_device_unregister(bat_pdev);
+pdev_register_failed:
+success:
+ return ret;
+}
+
+static void __exit pmu_bat_exit(void)
+{
+ int i;
+
+ for (i = 0; i < PMU_MAX_BATTERIES; i++) {
+ if (!pbats[i])
+ continue;
+ power_supply_unregister(&pbats[i]->bat);
+ kfree(pbats[i]);
+ }
+ power_supply_unregister(&pmu_ac);
+ platform_device_unregister(bat_pdev);
+
+ return;
+}
+
+module_init(pmu_bat_init);
+module_exit(pmu_bat_exit);
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PMU battery driver");
diff --git a/drivers/power/power_supply.h b/drivers/power/power_supply.h
new file mode 100644
index 00000000000..a9880d468ee
--- /dev/null
+++ b/drivers/power/power_supply.h
@@ -0,0 +1,42 @@
+/*
+ * Functions private to power supply class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#ifdef CONFIG_SYSFS
+
+extern int power_supply_create_attrs(struct power_supply *psy);
+extern void power_supply_remove_attrs(struct power_supply *psy);
+extern int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size);
+
+#else
+
+static inline int power_supply_create_attrs(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_attrs(struct power_supply *psy) {}
+#define power_supply_uevent NULL
+
+#endif /* CONFIG_SYSFS */
+
+#ifdef CONFIG_LEDS_TRIGGERS
+
+extern void power_supply_update_leds(struct power_supply *psy);
+extern int power_supply_create_triggers(struct power_supply *psy);
+extern void power_supply_remove_triggers(struct power_supply *psy);
+
+#else
+
+static inline void power_supply_update_leds(struct power_supply *psy) {}
+static inline int power_supply_create_triggers(struct power_supply *psy)
+{ return 0; }
+static inline void power_supply_remove_triggers(struct power_supply *psy) {}
+
+#endif /* CONFIG_LEDS_TRIGGERS */
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
new file mode 100644
index 00000000000..e87ea515675
--- /dev/null
+++ b/drivers/power/power_supply_core.c
@@ -0,0 +1,168 @@
+/*
+ * Universal power supply monitor class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include "power_supply.h"
+
+struct class *power_supply_class;
+
+static void power_supply_changed_work(struct work_struct *work)
+{
+ struct power_supply *psy = container_of(work, struct power_supply,
+ changed_work);
+ int i;
+
+ dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+ for (i = 0; i < psy->num_supplicants; i++) {
+ struct device *dev;
+
+ down(&power_supply_class->sem);
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ struct power_supply *pst = dev_get_drvdata(dev);
+
+ if (!strcmp(psy->supplied_to[i], pst->name)) {
+ if (pst->external_power_changed)
+ pst->external_power_changed(pst);
+ }
+ }
+ up(&power_supply_class->sem);
+ }
+
+ power_supply_update_leds(psy);
+
+ kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
+
+ return;
+}
+
+void power_supply_changed(struct power_supply *psy)
+{
+ dev_dbg(psy->dev, "%s\n", __FUNCTION__);
+
+ schedule_work(&psy->changed_work);
+
+ return;
+}
+
+int power_supply_am_i_supplied(struct power_supply *psy)
+{
+ union power_supply_propval ret = {0,};
+ struct device *dev;
+
+ down(&power_supply_class->sem);
+ list_for_each_entry(dev, &power_supply_class->devices, node) {
+ struct power_supply *epsy = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < epsy->num_supplicants; i++) {
+ if (!strcmp(epsy->supplied_to[i], psy->name)) {
+ if (epsy->get_property(epsy,
+ POWER_SUPPLY_PROP_ONLINE, &ret))
+ continue;
+ if (ret.intval)
+ goto out;
+ }
+ }
+ }
+out:
+ up(&power_supply_class->sem);
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, ret.intval);
+
+ return ret.intval;
+}
+
+int power_supply_register(struct device *parent, struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->dev = device_create(power_supply_class, parent, 0,
+ "%s", psy->name);
+ if (IS_ERR(psy->dev)) {
+ rc = PTR_ERR(psy->dev);
+ goto dev_create_failed;
+ }
+
+ dev_set_drvdata(psy->dev, psy);
+
+ INIT_WORK(&psy->changed_work, power_supply_changed_work);
+
+ rc = power_supply_create_attrs(psy);
+ if (rc)
+ goto create_attrs_failed;
+
+ rc = power_supply_create_triggers(psy);
+ if (rc)
+ goto create_triggers_failed;
+
+ power_supply_changed(psy);
+
+ goto success;
+
+create_triggers_failed:
+ power_supply_remove_attrs(psy);
+create_attrs_failed:
+ device_unregister(psy->dev);
+dev_create_failed:
+success:
+ return rc;
+}
+
+void power_supply_unregister(struct power_supply *psy)
+{
+ flush_scheduled_work();
+ power_supply_remove_triggers(psy);
+ power_supply_remove_attrs(psy);
+ device_unregister(psy->dev);
+ return;
+}
+
+static int __init power_supply_class_init(void)
+{
+ power_supply_class = class_create(THIS_MODULE, "power_supply");
+
+ if (IS_ERR(power_supply_class))
+ return PTR_ERR(power_supply_class);
+
+ power_supply_class->dev_uevent = power_supply_uevent;
+
+ return 0;
+}
+
+static void __exit power_supply_class_exit(void)
+{
+ class_destroy(power_supply_class);
+ return;
+}
+
+EXPORT_SYMBOL_GPL(power_supply_changed);
+EXPORT_SYMBOL_GPL(power_supply_am_i_supplied);
+EXPORT_SYMBOL_GPL(power_supply_register);
+EXPORT_SYMBOL_GPL(power_supply_unregister);
+
+/* exported for the APM Power driver, APM emulation */
+EXPORT_SYMBOL_GPL(power_supply_class);
+
+subsys_initcall(power_supply_class_init);
+module_exit(power_supply_class_exit);
+
+MODULE_DESCRIPTION("Universal power supply monitor class");
+MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, "
+ "Szabolcs Gyurko, "
+ "Anton Vorontsov <cbou@mail.ru>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c
new file mode 100644
index 00000000000..7232490bb59
--- /dev/null
+++ b/drivers/power/power_supply_leds.c
@@ -0,0 +1,176 @@
+/*
+ * LEDs triggers for power supply class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/power_supply.h>
+
+/* Battery specific LEDs triggers. */
+
+static void power_supply_update_bat_leds(struct power_supply *psy)
+{
+ union power_supply_propval status;
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
+ return;
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, status.intval);
+
+ switch (status.intval) {
+ case POWER_SUPPLY_STATUS_FULL:
+ led_trigger_event(psy->charging_full_trig, LED_FULL);
+ led_trigger_event(psy->charging_trig, LED_OFF);
+ led_trigger_event(psy->full_trig, LED_FULL);
+ break;
+ case POWER_SUPPLY_STATUS_CHARGING:
+ led_trigger_event(psy->charging_full_trig, LED_FULL);
+ led_trigger_event(psy->charging_trig, LED_FULL);
+ led_trigger_event(psy->full_trig, LED_OFF);
+ break;
+ default:
+ led_trigger_event(psy->charging_full_trig, LED_OFF);
+ led_trigger_event(psy->charging_trig, LED_OFF);
+ led_trigger_event(psy->full_trig, LED_OFF);
+ break;
+ }
+
+ return;
+}
+
+static int power_supply_create_bat_triggers(struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->charging_full_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-charging-or-full"), GFP_KERNEL);
+ if (!psy->charging_full_trig_name)
+ goto charging_full_failed;
+
+ psy->charging_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-charging"), GFP_KERNEL);
+ if (!psy->charging_trig_name)
+ goto charging_failed;
+
+ psy->full_trig_name = kmalloc(strlen(psy->name) +
+ sizeof("-full"), GFP_KERNEL);
+ if (!psy->full_trig_name)
+ goto full_failed;
+
+ strcpy(psy->charging_full_trig_name, psy->name);
+ strcat(psy->charging_full_trig_name, "-charging-or-full");
+ strcpy(psy->charging_trig_name, psy->name);
+ strcat(psy->charging_trig_name, "-charging");
+ strcpy(psy->full_trig_name, psy->name);
+ strcat(psy->full_trig_name, "-full");
+
+ led_trigger_register_simple(psy->charging_full_trig_name,
+ &psy->charging_full_trig);
+ led_trigger_register_simple(psy->charging_trig_name,
+ &psy->charging_trig);
+ led_trigger_register_simple(psy->full_trig_name,
+ &psy->full_trig);
+
+ goto success;
+
+full_failed:
+ kfree(psy->charging_trig_name);
+charging_failed:
+ kfree(psy->charging_full_trig_name);
+charging_full_failed:
+ rc = -ENOMEM;
+success:
+ return rc;
+}
+
+static void power_supply_remove_bat_triggers(struct power_supply *psy)
+{
+ led_trigger_unregister_simple(psy->charging_full_trig);
+ led_trigger_unregister_simple(psy->charging_trig);
+ led_trigger_unregister_simple(psy->full_trig);
+ kfree(psy->full_trig_name);
+ kfree(psy->charging_trig_name);
+ kfree(psy->charging_full_trig_name);
+ return;
+}
+
+/* Generated power specific LEDs triggers. */
+
+static void power_supply_update_gen_leds(struct power_supply *psy)
+{
+ union power_supply_propval online;
+
+ if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online))
+ return;
+
+ dev_dbg(psy->dev, "%s %d\n", __FUNCTION__, online.intval);
+
+ if (online.intval)
+ led_trigger_event(psy->online_trig, LED_FULL);
+ else
+ led_trigger_event(psy->online_trig, LED_OFF);
+
+ return;
+}
+
+static int power_supply_create_gen_triggers(struct power_supply *psy)
+{
+ int rc = 0;
+
+ psy->online_trig_name = kmalloc(strlen(psy->name) + sizeof("-online"),
+ GFP_KERNEL);
+ if (!psy->online_trig_name)
+ goto online_failed;
+
+ strcpy(psy->online_trig_name, psy->name);
+ strcat(psy->online_trig_name, "-online");
+
+ led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
+
+ goto success;
+
+online_failed:
+ rc = -ENOMEM;
+success:
+ return rc;
+}
+
+static void power_supply_remove_gen_triggers(struct power_supply *psy)
+{
+ led_trigger_unregister_simple(psy->online_trig);
+ kfree(psy->online_trig_name);
+ return;
+}
+
+/* Choice what triggers to create&update. */
+
+void power_supply_update_leds(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ power_supply_update_bat_leds(psy);
+ else
+ power_supply_update_gen_leds(psy);
+ return;
+}
+
+int power_supply_create_triggers(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ return power_supply_create_bat_triggers(psy);
+ return power_supply_create_gen_triggers(psy);
+}
+
+void power_supply_remove_triggers(struct power_supply *psy)
+{
+ if (psy->type == POWER_SUPPLY_TYPE_BATTERY)
+ power_supply_remove_bat_triggers(psy);
+ else
+ power_supply_remove_gen_triggers(psy);
+ return;
+}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
new file mode 100644
index 00000000000..c07d4258d34
--- /dev/null
+++ b/drivers/power/power_supply_sysfs.c
@@ -0,0 +1,299 @@
+/*
+ * Sysfs interface for the universal power supply monitor class
+ *
+ * Copyright © 2007 David Woodhouse <dwmw2@infradead.org>
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#include <linux/ctype.h>
+#include <linux/power_supply.h>
+
+/*
+ * This is because the name "current" breaks the device attr macro.
+ * The "current" word resolves to "(get_current())" so instead of
+ * "current" "(get_current())" appears in the sysfs.
+ *
+ * The source of this definition is the device.h which calls __ATTR
+ * macro in sysfs.h which calls the __stringify macro.
+ *
+ * Only modification that the name is not tried to be resolved
+ * (as a macro let's say).
+ */
+
+#define POWER_SUPPLY_ATTR(_name) \
+{ \
+ .attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE }, \
+ .show = power_supply_show_property, \
+ .store = NULL, \
+}
+
+static struct device_attribute power_supply_attrs[];
+
+static ssize_t power_supply_show_property(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ static char *status_text[] = {
+ "Unknown", "Charging", "Discharging", "Not charging", "Full"
+ };
+ static char *health_text[] = {
+ "Unknown", "Good", "Overheat", "Dead", "Over voltage",
+ "Unspecified failure"
+ };
+ static char *technology_text[] = {
+ "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd"
+ };
+ static char *capacity_level_text[] = {
+ "Unknown", "Critical", "Low", "Normal", "High", "Full"
+ };
+ ssize_t ret;
+ struct power_supply *psy = dev_get_drvdata(dev);
+ const ptrdiff_t off = attr - power_supply_attrs;
+ union power_supply_propval value;
+
+ ret = psy->get_property(psy, off, &value);
+
+ if (ret < 0) {
+ if (ret != -ENODEV)
+ dev_err(dev, "driver failed to report `%s' property\n",
+ attr->attr.name);
+ return ret;
+ }
+
+ if (off == POWER_SUPPLY_PROP_STATUS)
+ return sprintf(buf, "%s\n", status_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_HEALTH)
+ return sprintf(buf, "%s\n", health_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_TECHNOLOGY)
+ return sprintf(buf, "%s\n", technology_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_CAPACITY_LEVEL)
+ return sprintf(buf, "%s\n",
+ capacity_level_text[value.intval]);
+ else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
+ return sprintf(buf, "%s\n", value.strval);
+
+ return sprintf(buf, "%d\n", value.intval);
+}
+
+/* Must be in the same order as POWER_SUPPLY_PROP_* */
+static struct device_attribute power_supply_attrs[] = {
+ /* Properties of type `int' */
+ POWER_SUPPLY_ATTR(status),
+ POWER_SUPPLY_ATTR(health),
+ POWER_SUPPLY_ATTR(present),
+ POWER_SUPPLY_ATTR(online),
+ POWER_SUPPLY_ATTR(technology),
+ POWER_SUPPLY_ATTR(voltage_max_design),
+ POWER_SUPPLY_ATTR(voltage_min_design),
+ POWER_SUPPLY_ATTR(voltage_now),
+ POWER_SUPPLY_ATTR(voltage_avg),
+ POWER_SUPPLY_ATTR(current_now),
+ POWER_SUPPLY_ATTR(current_avg),
+ POWER_SUPPLY_ATTR(charge_full_design),
+ POWER_SUPPLY_ATTR(charge_empty_design),
+ POWER_SUPPLY_ATTR(charge_full),
+ POWER_SUPPLY_ATTR(charge_empty),
+ POWER_SUPPLY_ATTR(charge_now),
+ POWER_SUPPLY_ATTR(charge_avg),
+ POWER_SUPPLY_ATTR(energy_full_design),
+ POWER_SUPPLY_ATTR(energy_empty_design),
+ POWER_SUPPLY_ATTR(energy_full),
+ POWER_SUPPLY_ATTR(energy_empty),
+ POWER_SUPPLY_ATTR(energy_now),
+ POWER_SUPPLY_ATTR(energy_avg),
+ POWER_SUPPLY_ATTR(capacity),
+ POWER_SUPPLY_ATTR(capacity_level),
+ POWER_SUPPLY_ATTR(temp),
+ POWER_SUPPLY_ATTR(temp_ambient),
+ POWER_SUPPLY_ATTR(time_to_empty_now),
+ POWER_SUPPLY_ATTR(time_to_empty_avg),
+ POWER_SUPPLY_ATTR(time_to_full_now),
+ POWER_SUPPLY_ATTR(time_to_full_avg),
+ /* Properties of type `const char *' */
+ POWER_SUPPLY_ATTR(model_name),
+ POWER_SUPPLY_ATTR(manufacturer),
+};
+
+static ssize_t power_supply_show_static_attrs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ static char *type_text[] = { "Battery", "UPS", "Mains", "USB" };
+ struct power_supply *psy = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", type_text[psy->type]);
+}
+
+static struct device_attribute power_supply_static_attrs[] = {
+ __ATTR(type, 0444, power_supply_show_static_attrs, NULL),
+};
+
+int power_supply_create_attrs(struct power_supply *psy)
+{
+ int rc = 0;
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++) {
+ rc = device_create_file(psy->dev,
+ &power_supply_static_attrs[i]);
+ if (rc)
+ goto statics_failed;
+ }
+
+ for (j = 0; j < psy->num_properties; j++) {
+ rc = device_create_file(psy->dev,
+ &power_supply_attrs[psy->properties[j]]);
+ if (rc)
+ goto dynamics_failed;
+ }
+
+ goto succeed;
+
+dynamics_failed:
+ while (j--)
+ device_remove_file(psy->dev,
+ &power_supply_attrs[psy->properties[j]]);
+statics_failed:
+ while (i--)
+ device_remove_file(psy->dev,
+ &power_supply_static_attrs[psy->properties[i]]);
+succeed:
+ return rc;
+}
+
+void power_supply_remove_attrs(struct power_supply *psy)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(power_supply_static_attrs); i++)
+ device_remove_file(psy->dev,
+ &power_supply_static_attrs[i]);
+
+ for (i = 0; i < psy->num_properties; i++)
+ device_remove_file(psy->dev,
+ &power_supply_attrs[psy->properties[i]]);
+
+ return;
+}
+
+static char *kstruprdup(const char *str, gfp_t gfp)
+{
+ char *ret, *ustr;
+
+ ustr = ret = kmalloc(strlen(str) + 1, gfp);
+
+ if (!ret)
+ return NULL;
+
+ while (*str)
+ *ustr++ = toupper(*str++);
+
+ *ustr = 0;
+
+ return ret;
+}
+
+int power_supply_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ struct power_supply *psy = dev_get_drvdata(dev);
+ int i = 0, length = 0, ret = 0, j;
+ char *prop_buf;
+ char *attrname;
+
+ dev_dbg(dev, "uevent\n");
+
+ if (!psy) {
+ dev_dbg(dev, "No power supply yet\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "POWER_SUPPLY_NAME=%s\n", psy->name);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_NAME=%s", psy->name);
+ if (ret)
+ return ret;
+
+ prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!prop_buf)
+ return -ENOMEM;
+
+ for (j = 0; j < ARRAY_SIZE(power_supply_static_attrs); j++) {
+ struct device_attribute *attr;
+ char *line;
+
+ attr = &power_supply_static_attrs[j];
+
+ ret = power_supply_show_static_attrs(dev, attr, prop_buf);
+ if (ret < 0)
+ goto out;
+
+ line = strchr(prop_buf, '\n');
+ if (line)
+ *line = 0;
+
+ attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+ if (!attrname) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_dbg(dev, "Static prop %s=%s\n", attrname, prop_buf);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_%s=%s",
+ attrname, prop_buf);
+ kfree(attrname);
+ if (ret)
+ goto out;
+ }
+
+ dev_dbg(dev, "%zd dynamic props\n", psy->num_properties);
+
+ for (j = 0; j < psy->num_properties; j++) {
+ struct device_attribute *attr;
+ char *line;
+
+ attr = &power_supply_attrs[psy->properties[j]];
+
+ ret = power_supply_show_property(dev, attr, prop_buf);
+ if (ret == -ENODEV) {
+ /* When a battery is absent, we expect -ENODEV. Don't abort;
+ send the uevent with at least the the PRESENT=0 property */
+ ret = 0;
+ continue;
+ }
+
+ if (ret < 0)
+ goto out;
+
+ line = strchr(prop_buf, '\n');
+ if (line)
+ *line = 0;
+
+ attrname = kstruprdup(attr->attr.name, GFP_KERNEL);
+ if (!attrname) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
+
+ ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
+ &length, "POWER_SUPPLY_%s=%s",
+ attrname, prop_buf);
+ kfree(attrname);
+ if (ret)
+ goto out;
+ }
+
+out:
+ free_page((unsigned long)prop_buf);
+
+ return ret;
+}
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index eed91434417..659e31164cf 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -67,7 +67,8 @@ struct device_attribute rio_dev_attrs[] = {
};
static ssize_t
-rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct rio_dev *dev =
to_rio_dev(container_of(kobj, struct device, kobj));
@@ -137,7 +138,8 @@ rio_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
static ssize_t
-rio_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct rio_dev *dev =
to_rio_dev(container_of(kobj, struct device, kobj));
@@ -197,7 +199,6 @@ static struct bin_attribute rio_config_attr = {
.attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 0x200000,
.read = rio_read_config,
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 6085261aa2c..e24ea82dc35 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -641,9 +641,16 @@ cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
* drivers can't provide shutdown() methods to disable IRQs.
* Or better yet, fix PNP to allow those methods...
*/
- return cmos_do_probe(&pnp->dev,
- &pnp->res.port_resource[0],
- pnp->res.irq_resource[0].start);
+ if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0))
+ /* Some machines contain a PNP entry for the RTC, but
+ * don't define the IRQ. It should always be safe to
+ * hardcode it in these cases
+ */
+ return cmos_do_probe(&pnp->dev, &pnp->res.port_resource[0], 8);
+ else
+ return cmos_do_probe(&pnp->dev,
+ &pnp->res.port_resource[0],
+ pnp->res.irq_resource[0].start);
}
static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index afa64c7fa2e..f98a83a11aa 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -258,8 +258,9 @@ static const struct rtc_class_ops ds1553_rtc_ops = {
.ioctl = ds1553_rtc_ioctl,
};
-static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
- loff_t pos, size_t size)
+static ssize_t ds1553_nvram_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
{
struct platform_device *pdev =
to_platform_device(container_of(kobj, struct device, kobj));
@@ -272,8 +273,9 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
return count;
}
-static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
- loff_t pos, size_t size)
+static ssize_t ds1553_nvram_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
{
struct platform_device *pdev =
to_platform_device(container_of(kobj, struct device, kobj));
@@ -290,7 +292,6 @@ static struct bin_attribute ds1553_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUGO,
- .owner = THIS_MODULE,
},
.size = RTC_OFFSET,
.read = ds1553_nvram_read,
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index d68288b389d..d1778ae8bca 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -127,8 +127,9 @@ static const struct rtc_class_ops ds1742_rtc_ops = {
.set_time = ds1742_rtc_set_time,
};
-static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
- loff_t pos, size_t size)
+static ssize_t ds1742_nvram_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
{
struct platform_device *pdev =
to_platform_device(container_of(kobj, struct device, kobj));
@@ -141,8 +142,9 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
return count;
}
-static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
- loff_t pos, size_t size)
+static ssize_t ds1742_nvram_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t size)
{
struct platform_device *pdev =
to_platform_device(container_of(kobj, struct device, kobj));
@@ -159,7 +161,6 @@ static struct bin_attribute ds1742_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUGO | S_IWUGO,
- .owner = THIS_MODULE,
},
.read = ds1742_nvram_read,
.write = ds1742_nvram_write,
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index af7596ef29e..ce2f78de7a8 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -17,10 +17,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/err.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
@@ -30,25 +31,11 @@
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/uaccess.h>
-#include <asm/vr41xx/irq.h>
MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
MODULE_LICENSE("GPL");
-#define RTC1_TYPE1_START 0x0b0000c0UL
-#define RTC1_TYPE1_END 0x0b0000dfUL
-#define RTC2_TYPE1_START 0x0b0001c0UL
-#define RTC2_TYPE1_END 0x0b0001dfUL
-
-#define RTC1_TYPE2_START 0x0f000100UL
-#define RTC1_TYPE2_END 0x0f00011fUL
-#define RTC2_TYPE2_START 0x0f000120UL
-#define RTC2_TYPE2_END 0x0f00013fUL
-
-#define RTC1_SIZE 0x20
-#define RTC2_SIZE 0x20
-
/* RTC 1 registers */
#define ETIMELREG 0x00
#define ETIMEMREG 0x02
@@ -98,13 +85,8 @@ static char rtc_name[] = "RTC";
static unsigned long periodic_frequency;
static unsigned long periodic_count;
static unsigned int alarm_enabled;
-
-struct resource rtc_resource[2] = {
- { .name = rtc_name,
- .flags = IORESOURCE_MEM, },
- { .name = rtc_name,
- .flags = IORESOURCE_MEM, },
-};
+static int aie_irq = -1;
+static int pie_irq = -1;
static inline unsigned long read_elapsed_second(void)
{
@@ -150,8 +132,8 @@ static void vr41xx_rtc_release(struct device *dev)
spin_unlock_irq(&rtc_lock);
- disable_irq(ELAPSEDTIME_IRQ);
- disable_irq(RTCLONG1_IRQ);
+ disable_irq(aie_irq);
+ disable_irq(pie_irq);
}
static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
@@ -209,14 +191,14 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
spin_lock_irq(&rtc_lock);
if (alarm_enabled)
- disable_irq(ELAPSEDTIME_IRQ);
+ disable_irq(aie_irq);
rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15));
rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1));
rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17));
if (wkalrm->enabled)
- enable_irq(ELAPSEDTIME_IRQ);
+ enable_irq(aie_irq);
alarm_enabled = wkalrm->enabled;
@@ -234,7 +216,7 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
spin_lock_irq(&rtc_lock);
if (!alarm_enabled) {
- enable_irq(ELAPSEDTIME_IRQ);
+ enable_irq(aie_irq);
alarm_enabled = 1;
}
@@ -244,17 +226,17 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
spin_lock_irq(&rtc_lock);
if (alarm_enabled) {
- disable_irq(ELAPSEDTIME_IRQ);
+ disable_irq(aie_irq);
alarm_enabled = 0;
}
spin_unlock_irq(&rtc_lock);
break;
case RTC_PIE_ON:
- enable_irq(RTCLONG1_IRQ);
+ enable_irq(pie_irq);
break;
case RTC_PIE_OFF:
- disable_irq(RTCLONG1_IRQ);
+ disable_irq(pie_irq);
break;
case RTC_IRQP_READ:
return put_user(periodic_frequency, (unsigned long __user *)arg);
@@ -331,31 +313,37 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {
static int __devinit rtc_probe(struct platform_device *pdev)
{
+ struct resource *res;
struct rtc_device *rtc;
- unsigned int irq;
int retval;
- if (pdev->num_resources != 2)
+ if (pdev->num_resources != 4)
return -EBUSY;
- rtc1_base = ioremap(pdev->resource[0].start, RTC1_SIZE);
- if (rtc1_base == NULL)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
return -EBUSY;
- rtc2_base = ioremap(pdev->resource[1].start, RTC2_SIZE);
- if (rtc2_base == NULL) {
- iounmap(rtc1_base);
- rtc1_base = NULL;
+ rtc1_base = ioremap(res->start, res->end - res->start + 1);
+ if (!rtc1_base)
return -EBUSY;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ retval = -EBUSY;
+ goto err_rtc1_iounmap;
+ }
+
+ rtc2_base = ioremap(res->start, res->end - res->start + 1);
+ if (!rtc2_base) {
+ retval = -EBUSY;
+ goto err_rtc1_iounmap;
}
rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
- iounmap(rtc1_base);
- iounmap(rtc2_base);
- rtc1_base = NULL;
- rtc2_base = NULL;
- return PTR_ERR(rtc);
+ retval = PTR_ERR(rtc);
+ goto err_iounmap_all;
}
spin_lock_irq(&rtc_lock);
@@ -368,35 +356,50 @@ static int __devinit rtc_probe(struct platform_device *pdev)
spin_unlock_irq(&rtc_lock);
- irq = ELAPSEDTIME_IRQ;
- retval = request_irq(irq, elapsedtime_interrupt, IRQF_DISABLED,
- "elapsed_time", pdev);
- if (retval == 0) {
- irq = RTCLONG1_IRQ;
- retval = request_irq(irq, rtclong1_interrupt, IRQF_DISABLED,
- "rtclong1", pdev);
+ aie_irq = platform_get_irq(pdev, 0);
+ if (aie_irq < 0 || aie_irq >= NR_IRQS) {
+ retval = -EBUSY;
+ goto err_device_unregister;
}
- if (retval < 0) {
- printk(KERN_ERR "rtc: IRQ%d is busy\n", irq);
- rtc_device_unregister(rtc);
- if (irq == RTCLONG1_IRQ)
- free_irq(ELAPSEDTIME_IRQ, NULL);
- iounmap(rtc1_base);
- iounmap(rtc2_base);
- rtc1_base = NULL;
- rtc2_base = NULL;
- return retval;
- }
+ retval = request_irq(aie_irq, elapsedtime_interrupt, IRQF_DISABLED,
+ "elapsed_time", pdev);
+ if (retval < 0)
+ goto err_device_unregister;
+
+ pie_irq = platform_get_irq(pdev, 1);
+ if (pie_irq < 0 || pie_irq >= NR_IRQS)
+ goto err_free_irq;
+
+ retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
+ "rtclong1", pdev);
+ if (retval < 0)
+ goto err_free_irq;
platform_set_drvdata(pdev, rtc);
- disable_irq(ELAPSEDTIME_IRQ);
- disable_irq(RTCLONG1_IRQ);
+ disable_irq(aie_irq);
+ disable_irq(pie_irq);
printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n");
return 0;
+
+err_free_irq:
+ free_irq(aie_irq, pdev);
+
+err_device_unregister:
+ rtc_device_unregister(rtc);
+
+err_iounmap_all:
+ iounmap(rtc2_base);
+ rtc2_base = NULL;
+
+err_rtc1_iounmap:
+ iounmap(rtc1_base);
+ rtc1_base = NULL;
+
+ return retval;
}
static int __devexit rtc_remove(struct platform_device *pdev)
@@ -404,23 +407,21 @@ static int __devexit rtc_remove(struct platform_device *pdev)
struct rtc_device *rtc;
rtc = platform_get_drvdata(pdev);
- if (rtc != NULL)
+ if (rtc)
rtc_device_unregister(rtc);
platform_set_drvdata(pdev, NULL);
- free_irq(ELAPSEDTIME_IRQ, NULL);
- free_irq(RTCLONG1_IRQ, NULL);
- if (rtc1_base != NULL)
+ free_irq(aie_irq, pdev);
+ free_irq(pie_irq, pdev);
+ if (rtc1_base)
iounmap(rtc1_base);
- if (rtc2_base != NULL)
+ if (rtc2_base)
iounmap(rtc2_base);
return 0;
}
-static struct platform_device *rtc_platform_device;
-
static struct platform_driver rtc_platform_driver = {
.probe = rtc_probe,
.remove = __devexit_p(rtc_remove),
@@ -432,55 +433,12 @@ static struct platform_driver rtc_platform_driver = {
static int __init vr41xx_rtc_init(void)
{
- int retval;
-
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- rtc_resource[0].start = RTC1_TYPE1_START;
- rtc_resource[0].end = RTC1_TYPE1_END;
- rtc_resource[1].start = RTC2_TYPE1_START;
- rtc_resource[1].end = RTC2_TYPE1_END;
- break;
- case CPU_VR4122:
- case CPU_VR4131:
- case CPU_VR4133:
- rtc_resource[0].start = RTC1_TYPE2_START;
- rtc_resource[0].end = RTC1_TYPE2_END;
- rtc_resource[1].start = RTC2_TYPE2_START;
- rtc_resource[1].end = RTC2_TYPE2_END;
- break;
- default:
- return -ENODEV;
- break;
- }
-
- rtc_platform_device = platform_device_alloc("RTC", -1);
- if (rtc_platform_device == NULL)
- return -ENOMEM;
-
- retval = platform_device_add_resources(rtc_platform_device,
- rtc_resource, ARRAY_SIZE(rtc_resource));
-
- if (retval == 0)
- retval = platform_device_add(rtc_platform_device);
-
- if (retval < 0) {
- platform_device_put(rtc_platform_device);
- return retval;
- }
-
- retval = platform_driver_register(&rtc_platform_driver);
- if (retval < 0)
- platform_device_unregister(rtc_platform_device);
-
- return retval;
+ return platform_driver_register(&rtc_platform_driver);
}
static void __exit vr41xx_rtc_exit(void)
{
platform_driver_unregister(&rtc_platform_driver);
- platform_device_unregister(rtc_platform_device);
}
module_init(vr41xx_rtc_init);
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index 513d1a611aa..b3fae357ca4 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -9,6 +9,9 @@
*
* based on a lot of other RTC drivers.
*
+ * Information and datasheet:
+ * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
+ *
* 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.
@@ -26,7 +29,7 @@
* Two bytes need to be written to read a single register,
* while most other chips just require one and take the second
* one as the data to be written. To prevent corrupting
- * unknown chips, the user must explicitely set the probe parameter.
+ * unknown chips, the user must explicitly set the probe parameter.
*/
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index a1dc8c466ec..0c081a664ee 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -14,9 +14,9 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/poll.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
-#include <asm/semaphore.h>
#include <asm/atomic.h>
#include <asm/ebcdic.h>
@@ -514,7 +514,7 @@ void dasd_eer_disable(struct dasd_device *device)
* to transfer in a readbuffer, which is protected by the readbuffer_mutex.
*/
static char readbuffer[PAGE_SIZE];
-static DECLARE_MUTEX(readbuffer_mutex);
+static DEFINE_MUTEX(readbuffer_mutex);
static int dasd_eer_open(struct inode *inp, struct file *filp)
{
@@ -579,7 +579,7 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
struct eerbuffer *eerb;
eerb = (struct eerbuffer *) filp->private_data;
- if (down_interruptible(&readbuffer_mutex))
+ if (mutex_lock_interruptible(&readbuffer_mutex))
return -ERESTARTSYS;
spin_lock_irqsave(&bufferlock, flags);
@@ -588,7 +588,7 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
/* has been deleted */
eerb->residual = 0;
spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
+ mutex_unlock(&readbuffer_mutex);
return -EIO;
} else if (eerb->residual > 0) {
/* OK we still have a second half of a record to deliver */
@@ -602,7 +602,7 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
if (!tc) {
/* no data available */
spin_unlock_irqrestore(&bufferlock, flags);
- up(&readbuffer_mutex);
+ mutex_unlock(&readbuffer_mutex);
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
rc = wait_event_interruptible(
@@ -610,7 +610,7 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
eerb->head != eerb->tail);
if (rc)
return rc;
- if (down_interruptible(&readbuffer_mutex))
+ if (mutex_lock_interruptible(&readbuffer_mutex))
return -ERESTARTSYS;
spin_lock_irqsave(&bufferlock, flags);
}
@@ -626,11 +626,11 @@ static ssize_t dasd_eer_read(struct file *filp, char __user *buf,
spin_unlock_irqrestore(&bufferlock, flags);
if (copy_to_user(buf, readbuffer, effective_count)) {
- up(&readbuffer_mutex);
+ mutex_unlock(&readbuffer_mutex);
return -EFAULT;
}
- up(&readbuffer_mutex);
+ mutex_unlock(&readbuffer_mutex);
return effective_count;
}
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index 8b3b0f4a157..ac7e8ef504c 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -28,6 +28,7 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL;
static struct proc_dir_entry *dasd_devices_entry = NULL;
static struct proc_dir_entry *dasd_statistics_entry = NULL;
+#ifdef CONFIG_DASD_PROFILE
static char *
dasd_get_user_string(const char __user *user_buf, size_t user_len)
{
@@ -47,6 +48,7 @@ dasd_get_user_string(const char __user *user_buf, size_t user_len)
buffer[user_len] = 0;
return buffer;
}
+#endif /* CONFIG_DASD_PROFILE */
static int
dasd_devices_show(struct seq_file *m, void *v)
@@ -167,6 +169,7 @@ dasd_calc_metrics(char *page, char **start, off_t off,
return len;
}
+#ifdef CONFIG_DASD_PROFILE
static char *
dasd_statistics_array(char *str, unsigned int *array, int shift)
{
@@ -180,6 +183,7 @@ dasd_statistics_array(char *str, unsigned int *array, int shift)
str += sprintf(str,"\n");
return str;
}
+#endif /* CONFIG_DASD_PROFILE */
static int
dasd_statistics_read(char *page, char **start, off_t off,
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index f6ef90ee3e7..743944ad61e 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -487,7 +487,7 @@ struct raw3270_ua { /* Query Reply structure for Usable Area */
} __attribute__ ((packed));
static struct diag210 raw3270_init_diag210;
-static DECLARE_MUTEX(raw3270_init_sem);
+static DEFINE_MUTEX(raw3270_init_mutex);
static int
raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
@@ -713,7 +713,7 @@ raw3270_size_device(struct raw3270 *rp)
{
int rc;
- down(&raw3270_init_sem);
+ mutex_lock(&raw3270_init_mutex);
rp->view = &raw3270_init_view;
raw3270_init_view.dev = rp;
if (MACHINE_IS_VM)
@@ -722,7 +722,7 @@ raw3270_size_device(struct raw3270 *rp)
rc = __raw3270_size_device(rp);
raw3270_init_view.dev = NULL;
rp->view = NULL;
- up(&raw3270_init_sem);
+ mutex_unlock(&raw3270_init_mutex);
if (rc == 0) { /* Found something. */
/* Try to find a model. */
rp->model = 0;
@@ -749,7 +749,7 @@ raw3270_reset_device(struct raw3270 *rp)
{
int rc;
- down(&raw3270_init_sem);
+ mutex_lock(&raw3270_init_mutex);
memset(&rp->init_request, 0, sizeof(rp->init_request));
memset(&rp->init_data, 0, sizeof(rp->init_data));
/* Store reset data stream to init_data/init_request */
@@ -764,7 +764,7 @@ raw3270_reset_device(struct raw3270 *rp)
rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request);
raw3270_init_view.dev = NULL;
rp->view = NULL;
- up(&raw3270_init_sem);
+ mutex_unlock(&raw3270_init_mutex);
return rc;
}
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index dbb99d1b6f5..c7318a12585 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -72,6 +72,18 @@ typedef unsigned int sclp_cmdw_t;
typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
+struct sccb_header {
+ u16 length;
+ u8 function_code;
+ u8 control_mask[3];
+ u16 response_code;
+} __attribute__((packed));
+
+extern u64 sclp_facilities;
+
+#define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL)
+#define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL)
+
struct gds_subvector {
u8 length;
u8 key;
diff --git a/drivers/s390/char/sclp_chp.c b/drivers/s390/char/sclp_chp.c
index a66b914519b..c68f5e7e63a 100644
--- a/drivers/s390/char/sclp_chp.c
+++ b/drivers/s390/char/sclp_chp.c
@@ -55,6 +55,8 @@ static int do_configure(sclp_cmdw_t cmd)
struct chp_cfg_data *data;
int rc;
+ if (!SCLP_HAS_CHP_RECONFIG)
+ return -EOPNOTSUPP;
/* Prepare sccb. */
data = (struct chp_cfg_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!data)
@@ -152,6 +154,8 @@ int sclp_chp_read_info(struct sclp_chp_info *info)
struct chp_info_data *data;
int rc;
+ if (!SCLP_HAS_CHP_INFO)
+ return -EOPNOTSUPP;
/* Prepare sccb. */
data = (struct chp_info_data *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!data)
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
index 7bcbe643b08..a1136e05275 100644
--- a/drivers/s390/char/sclp_info.c
+++ b/drivers/s390/char/sclp_info.c
@@ -11,47 +11,106 @@
#include <asm/sclp.h>
#include "sclp.h"
-struct sclp_readinfo_sccb s390_readinfo_sccb;
+struct sclp_readinfo_sccb {
+ struct sccb_header header; /* 0-7 */
+ u16 rnmax; /* 8-9 */
+ u8 rnsize; /* 10 */
+ u8 _reserved0[24 - 11]; /* 11-23 */
+ u8 loadparm[8]; /* 24-31 */
+ u8 _reserved1[48 - 32]; /* 32-47 */
+ u64 facilities; /* 48-55 */
+ u8 _reserved2[91 - 56]; /* 56-90 */
+ u8 flags; /* 91 */
+ u8 _reserved3[100 - 92]; /* 92-99 */
+ u32 rnsize2; /* 100-103 */
+ u64 rnmax2; /* 104-111 */
+ u8 _reserved4[4096 - 112]; /* 112-4095 */
+} __attribute__((packed, aligned(4096)));
+
+static struct sclp_readinfo_sccb __initdata early_readinfo_sccb;
+static int __initdata early_readinfo_sccb_valid;
+
+u64 sclp_facilities;
void __init sclp_readinfo_early(void)
{
- sclp_cmdw_t command;
- struct sccb_header *sccb;
int ret;
+ int i;
+ struct sclp_readinfo_sccb *sccb;
+ sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED,
+ SCLP_CMDW_READ_SCP_INFO};
- __ctl_set_bit(0, 9); /* enable service signal subclass mask */
-
- sccb = &s390_readinfo_sccb.header;
- command = SCLP_CMDW_READ_SCP_INFO_FORCED;
- while (1) {
- u16 response;
-
- memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
- sccb->length = sizeof(s390_readinfo_sccb);
- sccb->control_mask[2] = 0x80;
-
- ret = sclp_service_call(command, &s390_readinfo_sccb);
-
- if (ret == -EIO)
- goto out;
- if (ret == -EBUSY)
- continue;
+ /* Enable service signal subclass mask. */
+ __ctl_set_bit(0, 9);
+ sccb = &early_readinfo_sccb;
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ do {
+ memset(sccb, 0, sizeof(*sccb));
+ sccb->header.length = sizeof(*sccb);
+ sccb->header.control_mask[2] = 0x80;
+ ret = sclp_service_call(commands[i], sccb);
+ } while (ret == -EBUSY);
+ if (ret)
+ break;
__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
PSW_MASK_WAIT | PSW_DEFAULT_KEY);
local_irq_disable();
+ /*
+ * Contents of the sccb might have changed
+ * therefore a barrier is needed.
+ */
barrier();
+ if (sccb->header.response_code == 0x10) {
+ early_readinfo_sccb_valid = 1;
+ break;
+ }
+ if (sccb->header.response_code != 0x1f0)
+ break;
+ }
+ /* Disable service signal subclass mask again. */
+ __ctl_clear_bit(0, 9);
+}
- response = sccb->response_code;
+void __init sclp_facilities_detect(void)
+{
+ if (!early_readinfo_sccb_valid)
+ return;
+ sclp_facilities = early_readinfo_sccb.facilities;
+}
- if (response == 0x10)
- break;
+unsigned long long __init sclp_memory_detect(void)
+{
+ unsigned long long memsize;
+ struct sclp_readinfo_sccb *sccb;
- if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
- break;
+ if (!early_readinfo_sccb_valid)
+ return 0;
+ sccb = &early_readinfo_sccb;
+ if (sccb->rnsize)
+ memsize = sccb->rnsize << 20;
+ else
+ memsize = sccb->rnsize2 << 20;
+ if (sccb->rnmax)
+ memsize *= sccb->rnmax;
+ else
+ memsize *= sccb->rnmax2;
+ return memsize;
+}
- command = SCLP_CMDW_READ_SCP_INFO;
- }
-out:
- __ctl_clear_bit(0, 9); /* disable service signal subclass mask */
+/*
+ * This function will be called after sclp_memory_detect(), which gets called
+ * early from early.c code. Therefore the sccb should have valid contents.
+ */
+void __init sclp_get_ipl_info(struct sclp_ipl_info *info)
+{
+ struct sclp_readinfo_sccb *sccb;
+
+ if (!early_readinfo_sccb_valid)
+ return;
+ sccb = &early_readinfo_sccb;
+ info->is_valid = 1;
+ if (sccb->flags & 0x2)
+ info->has_dump = 1;
+ memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN);
}
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index fce3dac5cb3..82e6a6b253e 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -175,13 +175,12 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static const struct file_operations vmcp_fops = {
.owner = THIS_MODULE,
- .open = &vmcp_open,
- .release = &vmcp_release,
- .read = &vmcp_read,
- .llseek = &no_llseek,
- .write = &vmcp_write,
- .unlocked_ioctl = &vmcp_ioctl,
- .compat_ioctl = &vmcp_ioctl
+ .open = vmcp_open,
+ .release = vmcp_release,
+ .read = vmcp_read,
+ .write = vmcp_write,
+ .unlocked_ioctl = vmcp_ioctl,
+ .compat_ioctl = vmcp_ioctl
};
static struct miscdevice vmcp_dev = {
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index a5a00e9ae4d..12f7a4ce82c 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -835,7 +835,7 @@ static void vmlogrdr_cleanup(void)
}
-static int vmlogrdr_init(void)
+static int __init vmlogrdr_init(void)
{
int rc;
int i;
@@ -885,7 +885,7 @@ cleanup:
}
-static void vmlogrdr_exit(void)
+static void __exit vmlogrdr_exit(void)
{
vmlogrdr_cleanup();
printk (KERN_INFO "vmlogrdr: driver unloaded\n");
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 66eb0688d52..3712ede1672 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -156,7 +156,7 @@ static int memcpy_real(void *dest, unsigned long src, size_t count)
return rc;
}
-static int memcpy_real_user(__user void *dest, unsigned long src, size_t count)
+static int memcpy_real_user(void __user *dest, unsigned long src, size_t count)
{
static char buf[4096];
int offs = 0, size;
@@ -267,7 +267,9 @@ struct zcore_header {
u64 tod;
cpuid_t cpu_id;
u32 arch_id;
+ u32 volnr;
u32 build_arch;
+ u64 rmem_size;
char pad2[4016];
} __attribute__((packed,__aligned__(16)));
@@ -559,6 +561,7 @@ static void __init zcore_header_init(int arch, struct zcore_header *hdr)
else
hdr->arch_id = DUMP_ARCH_S390;
hdr->mem_size = sys_info.mem_size;
+ hdr->rmem_size = sys_info.mem_size;
hdr->mem_end = sys_info.mem_size;
hdr->num_pages = sys_info.mem_size / PAGE_SIZE;
hdr->tod = get_clock();
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index ac289e6eadf..b57d93d986c 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -141,8 +141,9 @@ static int s390_vary_chpid(struct chp_id chpid, int on)
/*
* Channel measurement related functions
*/
-static ssize_t chp_measurement_chars_read(struct kobject *kobj, char *buf,
- loff_t off, size_t count)
+static ssize_t chp_measurement_chars_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct channel_path *chp;
unsigned int size;
@@ -165,7 +166,6 @@ static struct bin_attribute chp_measurement_chars_attr = {
.attr = {
.name = "measurement_chars",
.mode = S_IRUSR,
- .owner = THIS_MODULE,
},
.size = sizeof(struct cmg_chars),
.read = chp_measurement_chars_read,
@@ -193,8 +193,9 @@ static void chp_measurement_copy_block(struct cmg_entry *buf,
} while (reference_buf.values[0] != buf->values[0]);
}
-static ssize_t chp_measurement_read(struct kobject *kobj, char *buf,
- loff_t off, size_t count)
+static ssize_t chp_measurement_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct channel_path *chp;
struct channel_subsystem *css;
@@ -217,7 +218,6 @@ static struct bin_attribute chp_measurement_attr = {
.attr = {
.name = "measurement",
.mode = S_IRUSR,
- .owner = THIS_MODULE,
},
.size = sizeof(struct cmg_entry),
.read = chp_measurement_read,
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index a8b373f69cf..6b264bdb5bf 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -296,30 +296,57 @@ static void ccw_device_unregister(struct ccw_device *cdev)
device_del(&cdev->dev);
}
+static void ccw_device_remove_orphan_cb(struct device *dev)
+{
+ struct ccw_device *cdev = to_ccwdev(dev);
+
+ ccw_device_unregister(cdev);
+ put_device(&cdev->dev);
+}
+
+static void ccw_device_remove_sch_cb(struct device *dev)
+{
+ struct subchannel *sch;
+
+ sch = to_subchannel(dev);
+ css_sch_device_unregister(sch);
+ /* Reset intparm to zeroes. */
+ sch->schib.pmcw.intparm = 0;
+ cio_modify(sch);
+ put_device(&sch->dev);
+}
+
static void
ccw_device_remove_disconnected(struct ccw_device *cdev)
{
- struct subchannel *sch;
unsigned long flags;
+ int rc;
+
/*
* Forced offline in disconnected state means
* 'throw away device'.
*/
if (ccw_device_is_orphan(cdev)) {
- /* Deregister ccw device. */
+ /*
+ * Deregister ccw device.
+ * Unfortunately, we cannot do this directly from the
+ * attribute method.
+ */
spin_lock_irqsave(cdev->ccwlock, flags);
cdev->private->state = DEV_STATE_NOT_OPER;
spin_unlock_irqrestore(cdev->ccwlock, flags);
- ccw_device_unregister(cdev);
- put_device(&cdev->dev);
- return ;
+ rc = device_schedule_callback(&cdev->dev,
+ ccw_device_remove_orphan_cb);
+ if (rc)
+ dev_info(&cdev->dev, "Couldn't unregister orphan\n");
+ return;
}
- sch = to_subchannel(cdev->dev.parent);
- css_sch_device_unregister(sch);
- /* Reset intparm to zeroes. */
- sch->schib.pmcw.intparm = 0;
- cio_modify(sch);
- put_device(&sch->dev);
+ /* Deregister subchannel, which will kill the ccw device. */
+ rc = device_schedule_callback(cdev->dev.parent,
+ ccw_device_remove_sch_cb);
+ if (rc)
+ dev_info(&cdev->dev,
+ "Couldn't unregister disconnected device\n");
}
int
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 898ec3b2beb..6bba8092957 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -688,6 +688,12 @@ ccw_device_disband_done(struct ccw_device *cdev, int err)
ccw_device_done(cdev, DEV_STATE_BOXED);
break;
default:
+ cdev->private->flags.donotify = 0;
+ if (get_device(&cdev->dev)) {
+ PREPARE_WORK(&cdev->private->kick_work,
+ ccw_device_call_sch_unregister);
+ queue_work(ccw_device_work, &cdev->private->kick_work);
+ }
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
break;
}
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 997f4687453..60b9347f7c9 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -27,7 +27,6 @@
/*
* diag210 is used under VM to get information about a virtual device
*/
-#ifdef CONFIG_64BIT
int
diag210(struct diag210 * addr)
{
@@ -43,6 +42,7 @@ diag210(struct diag210 * addr)
spin_lock_irqsave(&diag210_lock, flags);
diag210_tmp = *addr;
+#ifdef CONFIG_64BIT
asm volatile(
" lhi %0,-1\n"
" sam31\n"
@@ -51,19 +51,8 @@ diag210(struct diag210 * addr)
" srl %0,28\n"
"1: sam64\n"
EX_TABLE(0b,1b)
- : "=&d" (ccode) : "a" (__pa(&diag210_tmp)) : "cc", "memory");
-
- *addr = diag210_tmp;
- spin_unlock_irqrestore(&diag210_lock, flags);
-
- return ccode;
-}
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
#else
-int
-diag210(struct diag210 * addr)
-{
- int ccode;
-
asm volatile(
" lhi %0,-1\n"
" diag %1,0,0x210\n"
@@ -71,11 +60,14 @@ diag210(struct diag210 * addr)
" srl %0,28\n"
"1:\n"
EX_TABLE(0b,1b)
- : "=&d" (ccode) : "a" (__pa(addr)) : "cc", "memory");
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#endif
+
+ *addr = diag210_tmp;
+ spin_unlock_irqrestore(&diag210_lock, flags);
return ccode;
}
-#endif
/*
* Input :
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 5aac0ec3636..90bd2201451 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -43,6 +43,7 @@ static void ap_poll_all(unsigned long);
static void ap_poll_timeout(unsigned long);
static int ap_poll_thread_start(void);
static void ap_poll_thread_stop(void);
+static void ap_request_timeout(unsigned long);
/**
* Module description.
@@ -189,6 +190,7 @@ int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length)
case AP_RESPONSE_NORMAL:
return 0;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
return -EBUSY;
default: /* Device is gone. */
return -ENODEV;
@@ -252,6 +254,8 @@ int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length)
if (status.queue_empty)
return -ENOENT;
return -EBUSY;
+ case AP_RESPONSE_RESET_IN_PROGRESS:
+ return -EBUSY;
default:
return -ENODEV;
}
@@ -326,11 +330,12 @@ static int ap_init_queue(ap_qid_t qid)
i = AP_MAX_RESET; /* return with -ENODEV */
break;
case AP_RESPONSE_RESET_IN_PROGRESS:
+ rc = -EBUSY;
case AP_RESPONSE_BUSY:
default:
break;
}
- if (rc != -ENODEV)
+ if (rc != -ENODEV && rc != -EBUSY)
break;
if (i < AP_MAX_RESET - 1) {
udelay(5);
@@ -341,6 +346,40 @@ static int ap_init_queue(ap_qid_t qid)
}
/**
+ * Arm request timeout if a AP device was idle and a new request is submitted.
+ */
+static void ap_increase_queue_count(struct ap_device *ap_dev)
+{
+ int timeout = ap_dev->drv->request_timeout;
+
+ ap_dev->queue_count++;
+ if (ap_dev->queue_count == 1) {
+ mod_timer(&ap_dev->timeout, jiffies + timeout);
+ ap_dev->reset = AP_RESET_ARMED;
+ }
+}
+
+/**
+ * AP device is still alive, re-schedule request timeout if there are still
+ * pending requests.
+ */
+static void ap_decrease_queue_count(struct ap_device *ap_dev)
+{
+ int timeout = ap_dev->drv->request_timeout;
+
+ ap_dev->queue_count--;
+ if (ap_dev->queue_count > 0)
+ mod_timer(&ap_dev->timeout, jiffies + timeout);
+ else
+ /**
+ * The timeout timer should to be disabled now - since
+ * del_timer_sync() is very expensive, we just tell via the
+ * reset flag to ignore the pending timeout timer.
+ */
+ ap_dev->reset = AP_RESET_IGNORE;
+}
+
+/**
* AP device related attributes.
*/
static ssize_t ap_hwtype_show(struct device *dev,
@@ -498,6 +537,7 @@ static int ap_device_remove(struct device *dev)
struct ap_driver *ap_drv = ap_dev->drv;
ap_flush_queue(ap_dev);
+ del_timer_sync(&ap_dev->timeout);
if (ap_drv->remove)
ap_drv->remove(ap_dev);
spin_lock_bh(&ap_device_lock);
@@ -759,17 +799,21 @@ static void ap_scan_bus(struct work_struct *unused)
__ap_scan_bus);
rc = ap_query_queue(qid, &queue_depth, &device_type);
if (dev) {
+ if (rc == -EBUSY) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(AP_RESET_TIMEOUT);
+ rc = ap_query_queue(qid, &queue_depth,
+ &device_type);
+ }
ap_dev = to_ap_dev(dev);
spin_lock_bh(&ap_dev->lock);
if (rc || ap_dev->unregistered) {
spin_unlock_bh(&ap_dev->lock);
- put_device(dev);
device_unregister(dev);
+ put_device(dev);
continue;
- } else
- spin_unlock_bh(&ap_dev->lock);
- }
- if (dev) {
+ }
+ spin_unlock_bh(&ap_dev->lock);
put_device(dev);
continue;
}
@@ -788,6 +832,8 @@ static void ap_scan_bus(struct work_struct *unused)
INIT_LIST_HEAD(&ap_dev->pendingq);
INIT_LIST_HEAD(&ap_dev->requestq);
INIT_LIST_HEAD(&ap_dev->list);
+ setup_timer(&ap_dev->timeout, ap_request_timeout,
+ (unsigned long) ap_dev);
if (device_type == 0)
ap_probe_device_type(ap_dev);
else
@@ -853,7 +899,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
atomic_dec(&ap_poll_requests);
- ap_dev->queue_count--;
+ ap_decrease_queue_count(ap_dev);
list_for_each_entry(ap_msg, &ap_dev->pendingq, list) {
if (ap_msg->psmid != ap_dev->reply->psmid)
continue;
@@ -904,7 +950,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
atomic_inc(&ap_poll_requests);
- ap_dev->queue_count++;
+ ap_increase_queue_count(ap_dev);
list_move_tail(&ap_msg->list, &ap_dev->pendingq);
ap_dev->requestq_count--;
ap_dev->pendingq_count++;
@@ -914,6 +960,7 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
*flags |= 2;
break;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
*flags |= 2;
break;
case AP_RESPONSE_MESSAGE_TOO_BIG:
@@ -960,10 +1007,11 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms
list_add_tail(&ap_msg->list, &ap_dev->pendingq);
atomic_inc(&ap_poll_requests);
ap_dev->pendingq_count++;
- ap_dev->queue_count++;
+ ap_increase_queue_count(ap_dev);
ap_dev->total_request_count++;
break;
case AP_RESPONSE_Q_FULL:
+ case AP_RESPONSE_RESET_IN_PROGRESS:
list_add_tail(&ap_msg->list, &ap_dev->requestq);
ap_dev->requestq_count++;
ap_dev->total_request_count++;
@@ -1046,6 +1094,25 @@ static void ap_poll_timeout(unsigned long unused)
}
/**
+ * Reset a not responding AP device and move all requests from the
+ * pending queue to the request queue.
+ */
+static void ap_reset(struct ap_device *ap_dev)
+{
+ int rc;
+
+ ap_dev->reset = AP_RESET_IGNORE;
+ atomic_sub(ap_dev->queue_count, &ap_poll_requests);
+ ap_dev->queue_count = 0;
+ list_splice_init(&ap_dev->pendingq, &ap_dev->requestq);
+ ap_dev->requestq_count += ap_dev->pendingq_count;
+ ap_dev->pendingq_count = 0;
+ rc = ap_init_queue(ap_dev->qid);
+ if (rc == -ENODEV)
+ ap_dev->unregistered = 1;
+}
+
+/**
* Poll all AP devices on the bus in a round robin fashion. Continue
* polling until bit 2^0 of the control flags is not set. If bit 2^1
* of the control flags has been set arm the poll timer.
@@ -1056,6 +1123,8 @@ static int __ap_poll_all(struct ap_device *ap_dev, unsigned long *flags)
if (!ap_dev->unregistered) {
if (ap_poll_queue(ap_dev, flags))
ap_dev->unregistered = 1;
+ if (ap_dev->reset == AP_RESET_DO)
+ ap_reset(ap_dev);
}
spin_unlock(&ap_dev->lock);
return 0;
@@ -1147,6 +1216,17 @@ static void ap_poll_thread_stop(void)
mutex_unlock(&ap_poll_thread_mutex);
}
+/**
+ * Handling of request timeouts
+ */
+static void ap_request_timeout(unsigned long data)
+{
+ struct ap_device *ap_dev = (struct ap_device *) data;
+
+ if (ap_dev->reset == AP_RESET_ARMED)
+ ap_dev->reset = AP_RESET_DO;
+}
+
static void ap_reset_domain(void)
{
int i;
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 008559ea742..87c2d644287 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -33,6 +33,7 @@
#define AP_DEVICES 64 /* Number of AP devices. */
#define AP_DOMAINS 16 /* Number of AP domains. */
#define AP_MAX_RESET 90 /* Maximum number of resets. */
+#define AP_RESET_TIMEOUT (HZ/2) /* Time in ticks for reset timeouts. */
#define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */
#define AP_POLL_TIME 1 /* Time in ticks between receive polls. */
@@ -83,6 +84,13 @@ struct ap_queue_status {
#define AP_DEVICE_TYPE_CEX2A 6
#define AP_DEVICE_TYPE_CEX2C 7
+/**
+ * AP reset flag states
+ */
+#define AP_RESET_IGNORE 0 /* request timeout will be ignored */
+#define AP_RESET_ARMED 1 /* request timeout timer is active */
+#define AP_RESET_DO 2 /* AP reset required */
+
struct ap_device;
struct ap_message;
@@ -95,6 +103,7 @@ struct ap_driver {
/* receive is called from tasklet context */
void (*receive)(struct ap_device *, struct ap_message *,
struct ap_message *);
+ int request_timeout; /* request timeout in jiffies */
};
#define to_ap_drv(x) container_of((x), struct ap_driver, driver)
@@ -112,6 +121,8 @@ struct ap_device {
int queue_depth; /* AP queue depth.*/
int device_type; /* AP device type. */
int unregistered; /* marks AP device as unregistered */
+ struct timer_list timeout; /* Timer for request timeouts. */
+ int reset; /* Reset required after req. timeout. */
int queue_count; /* # messages currently on AP queue. */
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 5bb13a9d089..08657f604b8 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_cex2a_driver = {
.remove = zcrypt_cex2a_remove,
.receive = zcrypt_cex2a_receive,
.ids = zcrypt_cex2a_ids,
+ .request_timeout = CEX2A_CLEANUP_TIME,
};
/**
@@ -306,18 +307,13 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, CEX2A_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
@@ -348,18 +344,13 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, CEX2A_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 818ffe05ac0..6e93b475178 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -70,6 +70,7 @@ static struct ap_driver zcrypt_pcica_driver = {
.remove = zcrypt_pcica_remove,
.receive = zcrypt_pcica_receive,
.ids = zcrypt_pcica_ids,
+ .request_timeout = PCICA_CLEANUP_TIME,
};
/**
@@ -290,18 +291,13 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICA_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
@@ -332,18 +328,13 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICA_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
kfree(ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index f295a403b29..d6d59bf9ac3 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -82,6 +82,7 @@ static struct ap_driver zcrypt_pcicc_driver = {
.remove = zcrypt_pcicc_remove,
.receive = zcrypt_pcicc_receive,
.ids = zcrypt_pcicc_ids,
+ .request_timeout = PCICC_CLEANUP_TIME,
};
/**
@@ -501,18 +502,13 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -544,18 +540,13 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &work, PCICC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&work);
+ if (rc == 0)
rc = convert_response(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 252443b6bd1..64948788d30 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -93,6 +93,7 @@ static struct ap_driver zcrypt_pcixcc_driver = {
.remove = zcrypt_pcixcc_remove,
.receive = zcrypt_pcixcc_receive,
.ids = zcrypt_pcixcc_ids,
+ .request_timeout = PCIXCC_CLEANUP_TIME,
};
/**
@@ -641,18 +642,13 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
mex->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -685,18 +681,13 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
crt->outputdatalength);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
free_page((unsigned long) ap_msg.message);
return rc;
@@ -729,17 +720,12 @@ static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
goto out_free;
init_completion(&resp_type.work);
ap_queue_message(zdev->ap_dev, &ap_msg);
- rc = wait_for_completion_interruptible_timeout(
- &resp_type.work, PCIXCC_CLEANUP_TIME);
- if (rc > 0)
+ rc = wait_for_completion_interruptible(&resp_type.work);
+ if (rc == 0)
rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
- else {
- /* Signal pending or message timed out. */
+ else
+ /* Signal pending. */
ap_cancel_message(zdev->ap_dev, &ap_msg);
- if (rc == 0)
- /* Message timed out. */
- rc = -ETIME;
- }
out_free:
memset(ap_msg.message, 0x0, ap_msg.length);
kfree(ap_msg.message);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 6dd64d0c8d4..348bb7b8277 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -3912,6 +3912,7 @@ static int
add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
{
struct chbk *p_ch;
+ struct ccw_dev_id dev_id;
#ifdef FUNCTRACE
printk(KERN_INFO "%s:%s Enter\n",cdev->dev.bus_id,__FUNCTION__);
@@ -3921,7 +3922,8 @@ add_channel(struct ccw_device *cdev,int i,struct claw_privbk *privptr)
p_ch = &privptr->channel[i];
p_ch->cdev = cdev;
snprintf(p_ch->id, CLAW_ID_SIZE, "cl-%s", cdev->dev.bus_id);
- sscanf(cdev->dev.bus_id+4,"%x",&p_ch->devno);
+ ccw_device_get_id(cdev, &dev_id);
+ p_ch->devno = dev_id.devno;
if ((p_ch->irb = kmalloc(sizeof (struct irb),GFP_KERNEL)) == NULL) {
printk(KERN_WARNING "%s Out of memory in %s for irb\n",
p_ch->id,__FUNCTION__);
@@ -3955,6 +3957,7 @@ claw_new_device(struct ccwgroup_device *cgdev)
struct claw_env *p_env;
struct net_device *dev;
int ret;
+ struct ccw_dev_id dev_id;
pr_debug("%s() called\n", __FUNCTION__);
printk(KERN_INFO "claw: add for %s\n",cgdev->cdev[READ]->dev.bus_id);
@@ -3965,10 +3968,10 @@ claw_new_device(struct ccwgroup_device *cgdev)
if (!privptr)
return -ENODEV;
p_env = privptr->p_env;
- sscanf(cgdev->cdev[READ]->dev.bus_id+4,"%x",
- &p_env->devno[READ]);
- sscanf(cgdev->cdev[WRITE]->dev.bus_id+4,"%x",
- &p_env->devno[WRITE]);
+ ccw_device_get_id(cgdev->cdev[READ], &dev_id);
+ p_env->devno[READ] = dev_id.devno;
+ ccw_device_get_id(cgdev->cdev[WRITE], &dev_id);
+ p_env->devno[WRITE] = dev_id.devno;
ret = add_channel(cgdev->cdev[0],0,privptr);
if (ret == 0)
ret = add_channel(cgdev->cdev[1],1,privptr);
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index c358764f326..3d28e1a5bf7 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -134,18 +134,6 @@ PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \
*(((char*)ptr)+28),*(((char*)ptr)+29), \
*(((char*)ptr)+30),*(((char*)ptr)+31));
-static inline void iucv_hex_dump(unsigned char *buf, size_t len)
-{
- size_t i;
-
- for (i = 0; i < len; i++) {
- if (i && !(i % 16))
- printk("\n");
- printk("%02x ", *(buf + i));
- }
- printk("\n");
-}
-
#define PRINTK_HEADER " iucv: " /* for debugging */
static struct device_driver netiucv_driver = {
@@ -212,7 +200,7 @@ struct iucv_connection {
*/
static struct list_head iucv_connection_list =
LIST_HEAD_INIT(iucv_connection_list);
-static rwlock_t iucv_connection_rwlock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(iucv_connection_rwlock);
/**
* Representation of event-data for the
@@ -280,7 +268,7 @@ static u8 iucvMagic[16] = {
*
* @returns The printable string (static data!!)
*/
-static inline char *netiucv_printname(char *name)
+static char *netiucv_printname(char *name)
{
static char tmp[9];
char *p = tmp;
@@ -1315,7 +1303,8 @@ static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
* and throw away packet.
*/
if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
- fsm_event(privptr->fsm, DEV_EVENT_START, dev);
+ if (!in_atomic())
+ fsm_event(privptr->fsm, DEV_EVENT_START, dev);
dev_kfree_skb(skb);
privptr->stats.tx_dropped++;
privptr->stats.tx_errors++;
@@ -1729,7 +1718,7 @@ static struct attribute_group netiucv_stat_attr_group = {
.attrs = netiucv_stat_attrs,
};
-static inline int netiucv_add_files(struct device *dev)
+static int netiucv_add_files(struct device *dev)
{
int ret;
@@ -1743,7 +1732,7 @@ static inline int netiucv_add_files(struct device *dev)
return ret;
}
-static inline void netiucv_remove_files(struct device *dev)
+static void netiucv_remove_files(struct device *dev)
{
IUCV_DBF_TEXT(trace, 3, __FUNCTION__);
sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group);
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 4640f32daae..70108fb1690 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -424,8 +424,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
/* prepare qdio hdr */
if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
eddp->qh.hdr.l2.pkt_length = data_len + ETH_HLEN +
- eddp->nhl + eddp->thl -
- sizeof(struct qeth_hdr);
+ eddp->nhl + eddp->thl;
#ifdef CONFIG_QETH_VLAN
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
eddp->qh.hdr.l2.pkt_length += VLAN_HLEN;
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 0b96d49dd63..86b0c44165c 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -986,15 +986,15 @@ qeth_recover(void *ptr)
card->use_hard_stop = 1;
__qeth_set_offline(card->gdev,1);
rc = __qeth_set_online(card->gdev,1);
+ /* don't run another scheduled recovery */
+ qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
+ qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
if (!rc)
PRINT_INFO("Device %s successfully recovered!\n",
CARD_BUS_ID(card));
else
PRINT_INFO("Device %s could not be recovered!\n",
CARD_BUS_ID(card));
- /* don't run another scheduled recovery */
- qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
- qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0;
}
@@ -2176,13 +2176,6 @@ qeth_ulp_enable(struct qeth_card *card)
}
-static inline __u16
-__raw_devno_from_bus_id(char *id)
-{
- id += (strlen(id) - 4);
- return (__u16) simple_strtoul(id, &id, 16);
-}
-
static int
qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
unsigned long data)
@@ -2205,6 +2198,7 @@ qeth_ulp_setup(struct qeth_card *card)
int rc;
__u16 temp;
struct qeth_cmd_buffer *iob;
+ struct ccw_dev_id dev_id;
QETH_DBF_TEXT(setup,2,"ulpsetup");
@@ -2218,8 +2212,8 @@ qeth_ulp_setup(struct qeth_card *card)
memcpy(QETH_ULP_SETUP_FILTER_TOKEN(iob->data),
&card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH);
- temp = __raw_devno_from_bus_id(CARD_DDEV_ID(card));
- memcpy(QETH_ULP_SETUP_CUA(iob->data), &temp, 2);
+ ccw_device_get_id(CARD_DDEV(card), &dev_id);
+ memcpy(QETH_ULP_SETUP_CUA(iob->data), &dev_id.devno, 2);
temp = (card->info.cula << 8) + card->info.unit_addr2;
memcpy(QETH_ULP_SETUP_REAL_DEVADDR(iob->data), &temp, 2);
rc = qeth_send_control_data(card, ULP_SETUP_SIZE, iob,
@@ -5850,9 +5844,9 @@ qeth_add_vlan_mc6(struct qeth_card *card)
in_dev = in6_dev_get(netdev);
if (!in_dev)
continue;
- read_lock(&in_dev->lock);
+ read_lock_bh(&in_dev->lock);
qeth_add_mc6(card,in_dev);
- read_unlock(&in_dev->lock);
+ read_unlock_bh(&in_dev->lock);
in6_dev_put(in_dev);
}
#endif /* CONFIG_QETH_VLAN */
@@ -5869,10 +5863,10 @@ qeth_add_multicast_ipv6(struct qeth_card *card)
in6_dev = in6_dev_get(card->dev);
if (in6_dev == NULL)
return;
- read_lock(&in6_dev->lock);
+ read_lock_bh(&in6_dev->lock);
qeth_add_mc6(card, in6_dev);
qeth_add_vlan_mc6(card);
- read_unlock(&in6_dev->lock);
+ read_unlock_bh(&in6_dev->lock);
in6_dev_put(in6_dev);
}
#endif /* CONFIG_QETH_IPV6 */
@@ -7476,11 +7470,11 @@ qeth_softsetup_card(struct qeth_card *card)
QETH_DBF_TEXT_(setup, 2, "1err%d", rc);
if (rc == 0xe080){
PRINT_WARN("LAN on card %s if offline! "
- "Continuing softsetup.\n",
+ "Waiting for STARTLAN from card.\n",
CARD_BUS_ID(card));
card->lan_online = 0;
- } else
- return rc;
+ }
+ return rc;
} else
card->lan_online = 1;
if (card->info.type==QETH_CARD_TYPE_OSN)
@@ -7797,15 +7791,17 @@ qeth_print_status_message(struct qeth_card *card)
}
/* fallthrough */
case QETH_CARD_TYPE_IQD:
- card->info.mcl_level[0] = (char) _ebcasc[(__u8)
- card->info.mcl_level[0]];
- card->info.mcl_level[1] = (char) _ebcasc[(__u8)
- card->info.mcl_level[1]];
- card->info.mcl_level[2] = (char) _ebcasc[(__u8)
- card->info.mcl_level[2]];
- card->info.mcl_level[3] = (char) _ebcasc[(__u8)
- card->info.mcl_level[3]];
- card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+ if (card->info.guestlan) {
+ card->info.mcl_level[0] = (char) _ebcasc[(__u8)
+ card->info.mcl_level[0]];
+ card->info.mcl_level[1] = (char) _ebcasc[(__u8)
+ card->info.mcl_level[1]];
+ card->info.mcl_level[2] = (char) _ebcasc[(__u8)
+ card->info.mcl_level[2]];
+ card->info.mcl_level[3] = (char) _ebcasc[(__u8)
+ card->info.mcl_level[3]];
+ card->info.mcl_level[QETH_MCL_LENGTH] = 0;
+ }
break;
default:
memset(&card->info.mcl_level[0], 0, QETH_MCL_LENGTH + 1);
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 65ffc21afc3..bb0287ad1aa 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -991,7 +991,7 @@ static struct attribute_group qeth_osn_device_attr_group = {
#define QETH_DEVICE_ATTR(_id,_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_id = { \
- .attr = {.name=__stringify(_name), .mode=_mode, .owner=THIS_MODULE },\
+ .attr = {.name=__stringify(_name), .mode=_mode, },\
.show = _show, \
.store = _store, \
};
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 262f01e6859..44e039865aa 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
+#include <linux/mm.h>
#include <asm/system.h>
#include <asm/uaccess.h>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index ed0ca150802..9d2119b53ac 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -65,6 +65,7 @@ config BLK_DEV_SD
depends on SCSI
---help---
If you want to use SCSI hard disks, Fibre Channel disks,
+ Serial ATA (SATA) or Parallel ATA (PATA) hard disks,
USB storage or the SCSI or parallel port version of
the IOMEGA ZIP drive, say Y and read the SCSI-HOWTO,
the Disk-HOWTO and the Multi-Disk-HOWTO, available from
@@ -1542,6 +1543,7 @@ source "drivers/scsi/arm/Kconfig"
config JAZZ_ESP
bool "MIPS JAZZ FAS216 SCSI support"
depends on MACH_JAZZ && SCSI
+ select SCSI_SPI_ATTRS
help
This is the driver for the onboard SCSI host adapter of MIPS Magnum
4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
@@ -1766,6 +1768,7 @@ config SUN3X_ESP
config SCSI_SUNESP
tristate "Sparc ESP Scsi Driver"
depends on SBUS && SCSI
+ select SCSI_SPI_ATTRS
help
This is the driver for the Sun ESP SCSI host adapter. The ESP
chipset is present in most SPARC SBUS-based computers.
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 37de6b37b08..f8e449a98d2 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -2627,7 +2627,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) {
#ifdef REAL_DMA
static void NCR5380_dma_complete(NCR5380_instance * instance) {
NCR5380_local_declare();
- struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata * instance->hostdata);
+ struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
int transferred;
NCR5380_setup(instance);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 4fda01e97f4..d76e1a8cb93 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -943,6 +943,14 @@ static struct scsi_host_template aac_driver_template = {
.emulated = 1,
};
+static void __aac_shutdown(struct aac_dev * aac)
+{
+ kthread_stop(aac->thread);
+ aac_send_shutdown(aac);
+ aac_adapter_disable_int(aac);
+ free_irq(aac->pdev->irq, aac);
+}
+
static int __devinit aac_probe_one(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -1095,10 +1103,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
return 0;
out_deinit:
- kthread_stop(aac->thread);
- aac_send_shutdown(aac);
- aac_adapter_disable_int(aac);
- free_irq(pdev->irq, aac);
+ __aac_shutdown(aac);
out_unmap:
aac_fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
@@ -1118,7 +1123,8 @@ static void aac_shutdown(struct pci_dev *dev)
{
struct Scsi_Host *shost = pci_get_drvdata(dev);
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
- aac_send_shutdown(aac);
+ scsi_block_requests(shost);
+ __aac_shutdown(aac);
}
static void __devexit aac_remove_one(struct pci_dev *pdev)
@@ -1128,16 +1134,12 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
scsi_remove_host(shost);
- kthread_stop(aac->thread);
-
- aac_send_shutdown(aac);
- aac_adapter_disable_int(aac);
+ __aac_shutdown(aac);
aac_fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr,
aac->comm_phys);
kfree(aac->queues);
- free_irq(pdev->irq, aac);
aac_adapter_ioremap(aac, 0);
kfree(aac->fibs);
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 9ddc6e4a74b..05f692bd0ad 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -5180,7 +5180,7 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
cur_lun = lun;
max_lun = lun;
}
- for (cur_lun <= max_lun; cur_lun++) {
+ for (;cur_lun <= max_lun; cur_lun++) {
struct ahd_tmode_lstate* lstate;
lstate = tstate->enabled_luns[cur_lun];
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 27852b43b90..1c0d7578e79 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -223,13 +223,8 @@ static int __devinit asd_common_setup(struct asd_ha_struct *asd_ha)
{
int err, i;
- err = pci_read_config_byte(asd_ha->pcidev, PCI_REVISION_ID,
- &asd_ha->revision_id);
- if (err) {
- asd_printk("couldn't read REVISION ID register of %s\n",
- pci_name(asd_ha->pcidev));
- goto Err;
- }
+ asd_ha->revision_id = asd_ha->pcidev->revision;
+
err = -ENODEV;
if (asd_ha->revision_id < AIC9410_DEV_REV_B0) {
asd_printk("%s is revision %s (%X), which is not supported\n",
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c
index 03bfed61bff..06c0dce3b83 100644
--- a/drivers/scsi/arcmsr/arcmsr_attr.c
+++ b/drivers/scsi/arcmsr/arcmsr_attr.c
@@ -59,8 +59,9 @@
struct class_device_attribute *arcmsr_host_attrs[];
static ssize_t
-arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+arcmsr_sysfs_iop_message_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev);
@@ -105,8 +106,9 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
-arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+arcmsr_sysfs_iop_message_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev);
@@ -152,8 +154,9 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
-arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev);
@@ -188,7 +191,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
.attr = {
.name = "mu_read",
.mode = S_IRUSR ,
- .owner = THIS_MODULE,
},
.size = 1032,
.read = arcmsr_sysfs_iop_message_read,
@@ -198,7 +200,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
.attr = {
.name = "mu_write",
.mode = S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 1032,
.write = arcmsr_sysfs_iop_message_write,
@@ -208,7 +209,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
.attr = {
.name = "mu_clear",
.mode = S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 1,
.write = arcmsr_sysfs_iop_message_clear,
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index eff846ae0af..03dbe60c264 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -894,45 +894,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
}
/*
- * our own old-style timeout update
- */
-/*
- * The strategy is to cause the timer code to call scsi_times_out()
- * when the soonest timeout is pending.
- * The arguments are used when we are queueing a new command, because
- * we do not want to subtract the time used from this time, but when we
- * set the timer, we want to take this value into account.
- */
-
-int atari_scsi_update_timeout(Scsi_Cmnd * SCset, int timeout)
-{
- int rtn;
-
- /*
- * We are using the new error handling code to actually register/deregister
- * timers for timeout.
- */
-
- if (!timer_pending(&SCset->eh_timeout))
- rtn = 0;
- else
- rtn = SCset->eh_timeout.expires - jiffies;
-
- if (timeout == 0) {
- del_timer(&SCset->eh_timeout);
- SCset->eh_timeout.data = (unsigned long)NULL;
- SCset->eh_timeout.expires = 0;
- } else {
- if (SCset->eh_timeout.data != (unsigned long)NULL)
- del_timer(&SCset->eh_timeout);
- SCset->eh_timeout.data = (unsigned long)SCset;
- SCset->eh_timeout.expires = jiffies + timeout;
- add_timer(&SCset->eh_timeout);
- }
- return rtn;
-}
-
-/*
* Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,
* void (*done)(Scsi_Cmnd *))
*
@@ -956,7 +917,6 @@ static int NCR5380_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
Scsi_Cmnd *tmp;
int oldto;
unsigned long flags;
- // extern int update_timeout(Scsi_Cmnd * SCset, int timeout);
#if (NDEBUG & NDEBUG_NO_WRITE)
switch (cmd->cmnd[0]) {
@@ -1029,9 +989,9 @@ static int NCR5380_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
* alter queues and touch the lock.
*/
if (!IS_A_TT()) {
- oldto = atari_scsi_update_timeout(cmd, 0);
+ /* perhaps stop command timer here */
falcon_get_lock();
- atari_scsi_update_timeout(cmd, oldto);
+ /* perhaps restart command timer here */
}
if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
LIST(cmd, hostdata->issue_queue);
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index c1d50e669c4..77b06a983fa 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -2029,6 +2029,7 @@ static void esp_reset_cleanup(struct esp *esp)
starget_for_each_device(tp->starget, NULL,
esp_clear_hold);
}
+ esp->flags &= ~ESP_FLAG_RESETTING;
}
/* Runs under host->lock */
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 8263f752809..bb90df8bdce 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -463,7 +463,7 @@ static inline unsigned long get_timeout(idescsi_pc_t *pc)
static int idescsi_expiry(ide_drive_t *drive)
{
- idescsi_scsi_t *scsi = drive->driver_data;
+ idescsi_scsi_t *scsi = drive_to_idescsi(drive);
idescsi_pc_t *pc = scsi->pc;
#if IDESCSI_DEBUG_LOG
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 072f5771565..f142eafb6fc 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -2439,6 +2439,7 @@ restart:
/**
* ipr_read_trace - Dump the adapter trace
* @kobj: kobject struct
+ * @bin_attr: bin_attribute struct
* @buf: buffer
* @off: offset
* @count: buffer size
@@ -2446,8 +2447,9 @@ restart:
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_read_trace(struct kobject *kobj, char *buf,
- loff_t off, size_t count)
+static ssize_t ipr_read_trace(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
@@ -3140,6 +3142,7 @@ static struct class_device_attribute *ipr_ioa_attrs[] = {
/**
* ipr_read_dump - Dump the adapter
* @kobj: kobject struct
+ * @bin_attr: bin_attribute struct
* @buf: buffer
* @off: offset
* @count: buffer size
@@ -3147,8 +3150,9 @@ static struct class_device_attribute *ipr_ioa_attrs[] = {
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
- loff_t off, size_t count)
+static ssize_t ipr_read_dump(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
@@ -3301,6 +3305,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
/**
* ipr_write_dump - Setup dump state of adapter
* @kobj: kobject struct
+ * @bin_attr: bin_attribute struct
* @buf: buffer
* @off: offset
* @count: buffer size
@@ -3308,8 +3313,9 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_write_dump(struct kobject *kobj, char *buf,
- loff_t off, size_t count)
+static ssize_t ipr_write_dump(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
@@ -5303,18 +5309,12 @@ static const u16 ipr_blocked_processors[] = {
**/
static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg)
{
- u8 rev_id;
int i;
- if (ioa_cfg->type == 0x5702) {
- if (pci_read_config_byte(ioa_cfg->pdev, PCI_REVISION_ID,
- &rev_id) == PCIBIOS_SUCCESSFUL) {
- if (rev_id < 4) {
- for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){
- if (__is_processor(ipr_blocked_processors[i]))
- return 1;
- }
- }
+ if ((ioa_cfg->type == 0x5702) && (ioa_cfg->pdev->revision < 4)) {
+ for (i = 0; i < ARRAY_SIZE(ipr_blocked_processors); i++){
+ if (__is_processor(ipr_blocked_processors[i]))
+ return 1;
}
}
return 0;
@@ -7471,13 +7471,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
else
ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
- rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &ioa_cfg->revid);
-
- if (rc != PCIBIOS_SUCCESSFUL) {
- dev_err(&pdev->dev, "Failed to read PCI revision ID\n");
- rc = -EIO;
- goto out_scsi_host_put;
- }
+ ioa_cfg->revid = pdev->revision;
ipr_regs_pci = pci_resource_start(pdev, 0);
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index f9fce70f396..9f8ed6b8157 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -6987,7 +6987,6 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
uint32_t mem_addr;
uint32_t io_len;
uint32_t mem_len;
- uint8_t revision_id;
uint8_t bus;
uint8_t func;
uint8_t irq;
@@ -7066,12 +7065,6 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
}
}
- /* get the revision ID */
- if (pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id)) {
- IPS_PRINTK(KERN_WARNING, pci_dev, "Can't get revision id.\n");
- return -1;
- }
-
subdevice_id = pci_dev->subsystem_device;
/* found a controller */
@@ -7097,7 +7090,7 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr)
ha->mem_ptr = mem_ptr;
ha->ioremap_ptr = ioremap_ptr;
ha->host_num = (uint32_t) index;
- ha->revision_id = revision_id;
+ ha->revision_id = pci_dev->revision;
ha->slot_num = PCI_SLOT(pci_dev->devfn);
ha->device_id = pci_dev->device;
ha->subdevice_id = subdevice_id;
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index e34442e405e..23e90c5f8f3 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -38,8 +38,10 @@ static int sas_disable_routing(struct domain_device *dev, u8 *sas_addr);
#if 0
/* FIXME: smp needs to migrate into the sas class */
-static ssize_t smp_portal_read(struct kobject *, char *, loff_t, size_t);
-static ssize_t smp_portal_write(struct kobject *, char *, loff_t, size_t);
+static ssize_t smp_portal_read(struct kobject *, struct bin_attribute *,
+ char *, loff_t, size_t);
+static ssize_t smp_portal_write(struct kobject *, struct bin_attribute *,
+ char *, loff_t, size_t);
#endif
/* ---------- SMP task management ---------- */
@@ -1368,7 +1370,6 @@ static void sas_ex_smp_hook(struct domain_device *dev)
memset(bin_attr, 0, sizeof(*bin_attr));
bin_attr->attr.name = SMP_BIN_ATTR_NAME;
- bin_attr->attr.owner = THIS_MODULE;
bin_attr->attr.mode = 0600;
bin_attr->size = 0;
@@ -1846,8 +1847,9 @@ out:
#if 0
/* ---------- SMP portal ---------- */
-static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
- size_t size)
+static ssize_t smp_portal_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t offs, size_t size)
{
struct domain_device *dev = to_dom_device(kobj);
struct expander_device *ex = &dev->ex_dev;
@@ -1873,8 +1875,9 @@ static ssize_t smp_portal_write(struct kobject *kobj, char *buf, loff_t offs,
return size;
}
-static ssize_t smp_portal_read(struct kobject *kobj, char *buf, loff_t offs,
- size_t size)
+static ssize_t smp_portal_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t offs, size_t size)
{
struct domain_device *dev = to_dom_device(kobj);
struct expander_device *ex = &dev->ex_dev;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 6a2c1ac4244..860a52c090f 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1405,7 +1405,8 @@ struct class_device_attribute *lpfc_hba_attrs[] = {
};
static ssize_t
-sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
size_t buf_off;
struct class_device *cdev = container_of(kobj, struct class_device,
@@ -1437,7 +1438,8 @@ sysfs_ctlreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
static ssize_t
-sysfs_ctlreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
size_t buf_off;
uint32_t * tmp_ptr;
@@ -1474,7 +1476,6 @@ static struct bin_attribute sysfs_ctlreg_attr = {
.attr = {
.name = "ctlreg",
.mode = S_IRUSR | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 256,
.read = sysfs_ctlreg_read,
@@ -1496,7 +1497,8 @@ sysfs_mbox_idle(struct lpfc_hba *phba)
}
static ssize_t
-sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj, struct class_device,
kobj);
@@ -1550,7 +1552,8 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
}
static ssize_t
-sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct class_device *cdev = container_of(kobj, struct class_device,
kobj);
@@ -1699,7 +1702,6 @@ static struct bin_attribute sysfs_mbox_attr = {
.attr = {
.name = "mbox",
.mode = S_IRUSR | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = MAILBOX_CMD_SIZE,
.read = sysfs_mbox_read,
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 4a50e0a2147..f81f85ee190 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1768,10 +1768,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
phba->fabric_block_timer.data = (unsigned long) phba;
pci_set_master(pdev);
- retval = pci_set_mwi(pdev);
- if (retval)
- dev_printk(KERN_WARNING, &pdev->dev,
- "Warning: pci_set_mwi returned %d\n", retval);
+ pci_try_set_mwi(pdev);
if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0)
if (pci_set_dma_mask(phba->pcidev, DMA_32BIT_MASK) != 0)
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 8cc9e64bbdf..7fed3537215 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -3379,15 +3379,6 @@ static int nsp32_resume(struct pci_dev *pdev)
return 0;
}
-/* Enable wake event */
-static int nsp32_enable_wake(struct pci_dev *pdev, pci_power_t state, int enable)
-{
- struct Scsi_Host *host = pci_get_drvdata(pdev);
-
- nsp32_msg(KERN_INFO, "pci-enable_wake: stub, pdev=0x%p, enable=%d, slot=%s, host=0x%p", pdev, enable, pci_name(pdev), host);
-
- return 0;
-}
#endif
/************************************************************************
@@ -3451,7 +3442,6 @@ static struct pci_driver nsp32_driver = {
#ifdef CONFIG_PM
.suspend = nsp32_suspend,
.resume = nsp32_resume,
- .enable_wake = nsp32_enable_wake,
#endif
};
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index b79c4dfc2a9..3eb2208675a 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -14,8 +14,9 @@ int qla24xx_vport_disable(struct fc_vport *, bool);
/* SYSFS attributes --------------------------------------------------------- */
static ssize_t
-qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -34,8 +35,9 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
-qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -76,7 +78,6 @@ static struct bin_attribute sysfs_fw_dump_attr = {
.attr = {
.name = "fw_dump",
.mode = S_IRUSR | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 0,
.read = qla2x00_sysfs_read_fw_dump,
@@ -84,8 +85,9 @@ static struct bin_attribute sysfs_fw_dump_attr = {
};
static ssize_t
-qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_read_nvram(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -104,8 +106,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
-qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_write_nvram(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -152,7 +155,6 @@ static struct bin_attribute sysfs_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUSR | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 512,
.read = qla2x00_sysfs_read_nvram,
@@ -160,8 +162,9 @@ static struct bin_attribute sysfs_nvram_attr = {
};
static ssize_t
-qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_read_optrom(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -179,8 +182,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
-qla2x00_sysfs_write_optrom(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_write_optrom(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -201,7 +205,6 @@ static struct bin_attribute sysfs_optrom_attr = {
.attr = {
.name = "optrom",
.mode = S_IRUSR | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = OPTROM_SIZE_24XX,
.read = qla2x00_sysfs_read_optrom,
@@ -209,8 +212,9 @@ static struct bin_attribute sysfs_optrom_attr = {
};
static ssize_t
-qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -282,15 +286,15 @@ static struct bin_attribute sysfs_optrom_ctl_attr = {
.attr = {
.name = "optrom_ctl",
.mode = S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 0,
.write = qla2x00_sysfs_write_optrom_ctl,
};
static ssize_t
-qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_read_vpd(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -308,8 +312,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, char *buf, loff_t off,
}
static ssize_t
-qla2x00_sysfs_write_vpd(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_write_vpd(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -330,7 +335,6 @@ static struct bin_attribute sysfs_vpd_attr = {
.attr = {
.name = "vpd",
.mode = S_IRUSR | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = 0,
.read = qla2x00_sysfs_read_vpd,
@@ -338,8 +342,9 @@ static struct bin_attribute sysfs_vpd_attr = {
};
static ssize_t
-qla2x00_sysfs_read_sfp(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+qla2x00_sysfs_read_sfp(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
@@ -378,7 +383,6 @@ static struct bin_attribute sysfs_sfp_attr = {
.attr = {
.name = "sfp",
.mode = S_IRUSR | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = SFP_DEV_SIZE * 2,
.read = qla2x00_sysfs_read_sfp,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index bd95f7dc5cf..cc6ebb609e9 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -296,7 +296,7 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
d &= ~PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
- pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->chip_revision);
+ ha->chip_revision = ha->pdev->revision;
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a8658b1d284..b5a77b0c0de 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2610,7 +2610,7 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
return 0;
if (msleep_interruptible(step))
break;
- } while (--iterations >= 0);
+ } while (--iterations > 0);
return -ETIMEDOUT;
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 0827df2ebb6..a86e62f4b3b 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -184,6 +184,15 @@ int scsi_complete_async_scans(void)
/* Only exported for the benefit of scsi_wait_scan */
EXPORT_SYMBOL_GPL(scsi_complete_async_scans);
+#ifndef MODULE
+/*
+ * For async scanning we need to wait for all the scans to complete before
+ * trying to mount the root fs. Otherwise non-modular drivers may not be ready
+ * yet.
+ */
+late_initcall(scsi_complete_async_scans);
+#endif
+
/**
* scsi_unlock_floptical - unlock device via a special MODE SENSE command
* @sdev: scsi device to send command to
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 315ea991645..2adbed4e10f 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -556,7 +556,7 @@ choice
config SERIAL_BFIN_DMA
bool "DMA mode"
- depends on DMA_UNCACHED_1M
+ depends on DMA_UNCACHED_1M && !KGDB_UART
help
This driver works under DMA mode. If this option is selected, the
blackfin simple dma driver is also enabled.
@@ -599,7 +599,7 @@ config UART0_RTS_PIN
config SERIAL_BFIN_UART1
bool "Enable UART1"
- depends on SERIAL_BFIN && (BF534 || BF536 || BF537)
+ depends on SERIAL_BFIN && (BF534 || BF536 || BF537 || BF54x)
help
Enable UART1
@@ -612,18 +612,58 @@ config BFIN_UART1_CTSRTS
config UART1_CTS_PIN
int "UART1 CTS pin"
- depends on BFIN_UART1_CTSRTS
+ depends on BFIN_UART1_CTSRTS && (BF53x || BF561)
default -1
help
Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
config UART1_RTS_PIN
int "UART1 RTS pin"
- depends on BFIN_UART1_CTSRTS
+ depends on BFIN_UART1_CTSRTS && (BF53x || BF561)
default -1
help
Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+config SERIAL_BFIN_UART2
+ bool "Enable UART2"
+ depends on SERIAL_BFIN && (BF54x)
+ help
+ Enable UART2
+
+config BFIN_UART2_CTSRTS
+ bool "Enable UART2 hardware flow control"
+ depends on SERIAL_BFIN_UART2
+ help
+ Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
+ signal.
+
+config UART2_CTS_PIN
+ int "UART2 CTS pin"
+ depends on BFIN_UART2_CTSRTS
+ default -1
+ help
+ Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config UART2_RTS_PIN
+ int "UART2 RTS pin"
+ depends on BFIN_UART2_CTSRTS
+ default -1
+ help
+ Refer to ./include/asm-blackfin/gpio.h to see the GPIO map.
+
+config SERIAL_BFIN_UART3
+ bool "Enable UART3"
+ depends on SERIAL_BFIN && (BF54x)
+ help
+ Enable UART3
+
+config BFIN_UART3_CTSRTS
+ bool "Enable UART3 hardware flow control"
+ depends on SERIAL_BFIN_UART3
+ help
+ Enable hardware flow control in the driver. Using GPIO emulate the CTS/RTS
+ signal.
+
config SERIAL_IMX
bool "IMX serial port support"
depends on ARM && ARCH_IMX
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 00d1255e4c1..e88da72f830 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -167,9 +167,9 @@ static void pl010_rx_chars(struct uart_amba_port *uap)
ignore_char:
status = readb(uap->port.membase + UART01x_FR);
}
- spin_unlock(&port->lock);
+ spin_unlock(&uap->port.lock);
tty_flip_buffer_push(tty);
- spin_lock(&port->lock);
+ spin_lock(&uap->port.lock);
}
static void pl010_tx_chars(struct uart_amba_port *uap)
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 787dc7168f3..66c92bc36f3 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -41,6 +41,11 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
+#ifdef CONFIG_KGDB_UART
+#include <linux/kgdb.h>
+#include <asm/irq_regs.h>
+#endif
+
#include <asm/gpio.h>
#include <asm/mach/bfin_serial_5xx.h>
@@ -81,15 +86,29 @@ static void bfin_serial_stop_tx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+#ifdef CONFIG_BF54x
+ while (!(UART_GET_LSR(uart) & TEMT))
+ continue;
+#endif
+
#ifdef CONFIG_SERIAL_BFIN_DMA
disable_dma(uart->tx_dma_channel);
#else
+#ifdef CONFIG_BF54x
+ /* Waiting for Transmission Finished */
+ while (!(UART_GET_LSR(uart) & TFI))
+ continue;
+ /* Clear TFI bit */
+ UART_PUT_LSR(uart, TFI);
+ UART_CLEAR_IER(uart, ETBEI);
+#else
unsigned short ier;
ier = UART_GET_IER(uart);
ier &= ~ETBEI;
UART_PUT_IER(uart, ier);
#endif
+#endif
}
/*
@@ -102,12 +121,16 @@ static void bfin_serial_start_tx(struct uart_port *port)
#ifdef CONFIG_SERIAL_BFIN_DMA
bfin_serial_dma_tx_chars(uart);
#else
+#ifdef CONFIG_BF54x
+ UART_SET_IER(uart, ETBEI);
+#else
unsigned short ier;
ier = UART_GET_IER(uart);
ier |= ETBEI;
UART_PUT_IER(uart, ier);
bfin_serial_tx_chars(uart);
#endif
+#endif
}
/*
@@ -116,11 +139,18 @@ static void bfin_serial_start_tx(struct uart_port *port)
static void bfin_serial_stop_rx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+#ifdef CONFIG_BF54x
+ UART_CLEAR_IER(uart, ERBFI);
+#else
unsigned short ier;
ier = UART_GET_IER(uart);
+#ifdef CONFIG_KGDB_UART
+ if (uart->port.line != CONFIG_KGDB_UART_PORT)
+#endif
ier &= ~ERBFI;
UART_PUT_IER(uart, ier);
+#endif
}
/*
@@ -130,6 +160,49 @@ static void bfin_serial_enable_ms(struct uart_port *port)
{
}
+#ifdef CONFIG_KGDB_UART
+static int kgdb_entry_state;
+
+void kgdb_put_debug_char(int chr)
+{
+ struct bfin_serial_port *uart;
+
+ if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+ uart = &bfin_serial_ports[0];
+ else
+ uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+
+ while (!(UART_GET_LSR(uart) & THRE)) {
+ __builtin_bfin_ssync();
+ }
+ UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB));
+ __builtin_bfin_ssync();
+ UART_PUT_CHAR(uart, (unsigned char)chr);
+ __builtin_bfin_ssync();
+}
+
+int kgdb_get_debug_char(void)
+{
+ struct bfin_serial_port *uart;
+ unsigned char chr;
+
+ if (CONFIG_KGDB_UART_PORT<0 || CONFIG_KGDB_UART_PORT>=NR_PORTS)
+ uart = &bfin_serial_ports[0];
+ else
+ uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+
+ while(!(UART_GET_LSR(uart) & DR)) {
+ __builtin_bfin_ssync();
+ }
+ UART_PUT_LCR(uart, UART_GET_LCR(uart)&(~DLAB));
+ __builtin_bfin_ssync();
+ chr = UART_GET_CHAR(uart);
+ __builtin_bfin_ssync();
+
+ return chr;
+}
+#endif
+
#ifdef CONFIG_SERIAL_BFIN_PIO
static void local_put_char(struct bfin_serial_port *uart, char ch)
{
@@ -152,6 +225,9 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
{
struct tty_struct *tty = uart->port.info->tty;
unsigned int status, ch, flg;
+#ifdef CONFIG_KGDB_UART
+ struct pt_regs *regs = get_irq_regs();
+#endif
#ifdef BF533_FAMILY
static int in_break = 0;
#endif
@@ -160,6 +236,27 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
ch = UART_GET_CHAR(uart);
uart->port.icount.rx++;
+#ifdef CONFIG_KGDB_UART
+ if (uart->port.line == CONFIG_KGDB_UART_PORT) {
+ if (uart->port.cons->index == CONFIG_KGDB_UART_PORT && ch == 0x1) { /* Ctrl + A */
+ kgdb_breakkey_pressed(regs);
+ return;
+ } else if (kgdb_entry_state == 0 && ch == '$') {/* connection from KGDB */
+ kgdb_entry_state = 1;
+ } else if (kgdb_entry_state == 1 && ch == 'q') {
+ kgdb_entry_state = 0;
+ kgdb_breakkey_pressed(regs);
+ return;
+ } else if (ch == 0x3) {/* Ctrl + C */
+ kgdb_entry_state = 0;
+ kgdb_breakkey_pressed(regs);
+ return;
+ } else {
+ kgdb_entry_state = 0;
+ }
+ }
+#endif
+
#ifdef BF533_FAMILY
/* The BF533 family of processors have a nice misbehavior where
* they continuously generate characters for a "single" break.
@@ -185,6 +282,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
uart->port.icount.brk++;
if (uart_handle_break(&uart->port))
goto ignore_char;
+ status &= ~(PE | FE);
}
if (status & PE)
uart->port.icount.parity++;
@@ -249,10 +347,21 @@ static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
+#ifdef CONFIG_BF54x
+ unsigned short status;
+ spin_lock(&uart->port.lock);
+ status = UART_GET_LSR(uart);
+ while ((UART_GET_IER(uart) & ERBFI) && (status & DR)) {
+ bfin_serial_rx_chars(uart);
+ status = UART_GET_LSR(uart);
+ }
+ spin_unlock(&uart->port.lock);
+#else
spin_lock(&uart->port.lock);
while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY)
bfin_serial_rx_chars(uart);
spin_unlock(&uart->port.lock);
+#endif
return IRQ_HANDLED;
}
@@ -260,10 +369,21 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
+#ifdef CONFIG_BF54x
+ unsigned short status;
+ spin_lock(&uart->port.lock);
+ status = UART_GET_LSR(uart);
+ while ((UART_GET_IER(uart) & ETBEI) && (status & THRE)) {
+ bfin_serial_tx_chars(uart);
+ status = UART_GET_LSR(uart);
+ }
+ spin_unlock(&uart->port.lock);
+#else
spin_lock(&uart->port.lock);
while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY)
bfin_serial_tx_chars(uart);
spin_unlock(&uart->port.lock);
+#endif
return IRQ_HANDLED;
}
@@ -274,7 +394,6 @@ static void bfin_serial_do_work(struct work_struct *work)
bfin_serial_mctrl_check(uart);
}
-
#endif
#ifdef CONFIG_SERIAL_BFIN_DMA
@@ -323,9 +442,13 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
set_dma_x_modify(uart->tx_dma_channel, 1);
enable_dma(uart->tx_dma_channel);
+#ifdef CONFIG_BF54x
+ UART_SET_IER(uart, ETBEI);
+#else
ier = UART_GET_IER(uart);
ier |= ETBEI;
UART_PUT_IER(uart, ier);
+#endif
spin_unlock_irqrestore(&uart->port.lock, flags);
}
@@ -341,6 +464,7 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
uart->port.icount.brk++;
if (uart_handle_break(&uart->port))
goto dma_ignore_char;
+ status &= ~(PE | FE);
}
if (status & PE)
uart->port.icount.parity++;
@@ -404,9 +528,13 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
clear_dma_irqstat(uart->tx_dma_channel);
disable_dma(uart->tx_dma_channel);
+#ifdef CONFIG_BF54x
+ UART_CLEAR_IER(uart, ETBEI);
+#else
ier = UART_GET_IER(uart);
ier &= ~ETBEI;
UART_PUT_IER(uart, ier);
+#endif
xmit->tail = (xmit->tail+uart->tx_count) &(UART_XMIT_SIZE -1);
uart->port.icount.tx+=uart->tx_count;
@@ -517,6 +645,14 @@ static void bfin_serial_mctrl_check(struct bfin_serial_port *uart)
*/
static void bfin_serial_break_ctl(struct uart_port *port, int break_state)
{
+ struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
+ u16 lcr = UART_GET_LCR(uart);
+ if (break_state)
+ lcr |= SB;
+ else
+ lcr &= ~SB;
+ UART_PUT_LCR(uart, lcr);
+ SSYNC();
}
static int bfin_serial_startup(struct uart_port *port)
@@ -561,7 +697,11 @@ static int bfin_serial_startup(struct uart_port *port)
uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES;
add_timer(&(uart->rx_dma_timer));
#else
+# ifdef CONFIG_KGDB_UART
+ if (uart->port.line != CONFIG_KGDB_UART_PORT && request_irq
+# else
if (request_irq
+# endif
(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED,
"BFIN_UART_RX", uart)) {
printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n");
@@ -576,7 +716,11 @@ static int bfin_serial_startup(struct uart_port *port)
return -EBUSY;
}
#endif
+#ifdef CONFIG_BF54x
+ UART_SET_IER(uart, ERBFI);
+#else
UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
+#endif
return 0;
}
@@ -591,6 +735,9 @@ static void bfin_serial_shutdown(struct uart_port *port)
free_dma(uart->rx_dma_channel);
del_timer(&(uart->rx_dma_timer));
#else
+#ifdef CONFIG_KGDB_UART
+ if (uart->port.line != CONFIG_KGDB_UART_PORT)
+#endif
free_irq(uart->port.irq, uart);
free_irq(uart->port.irq+1, uart);
#endif
@@ -625,11 +772,12 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
if (termios->c_cflag & CSTOPB)
lcr |= STB;
- if (termios->c_cflag & PARENB) {
+ if (termios->c_cflag & PARENB)
lcr |= PEN;
- if (!(termios->c_cflag & PARODD))
- lcr |= EPS;
- }
+ if (!(termios->c_cflag & PARODD))
+ lcr |= EPS;
+ if (termios->c_cflag & CMSPAR)
+ lcr |= STP;
port->read_status_mask = OE;
if (termios->c_iflag & INPCK)
@@ -663,29 +811,41 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
/* Disable UART */
ier = UART_GET_IER(uart);
+#ifdef CONFIG_BF54x
+ UART_CLEAR_IER(uart, 0xF);
+#else
UART_PUT_IER(uart, 0);
+#endif
+#ifndef CONFIG_BF54x
/* Set DLAB in LCR to Access DLL and DLH */
val = UART_GET_LCR(uart);
val |= DLAB;
UART_PUT_LCR(uart, val);
SSYNC();
+#endif
UART_PUT_DLL(uart, quot & 0xFF);
SSYNC();
UART_PUT_DLH(uart, (quot >> 8) & 0xFF);
SSYNC();
+#ifndef CONFIG_BF54x
/* Clear DLAB in LCR to Access THR RBR IER */
val = UART_GET_LCR(uart);
val &= ~DLAB;
UART_PUT_LCR(uart, val);
SSYNC();
+#endif
UART_PUT_LCR(uart, lcr);
/* Enable UART */
+#ifdef CONFIG_BF54x
+ UART_SET_IER(uart, ier);
+#else
UART_PUT_IER(uart, ier);
+#endif
val = UART_GET_GCTL(uart);
val |= UCEN;
@@ -797,15 +957,15 @@ static void __init bfin_serial_init_ports(void)
bfin_serial_resource[i].uart_rts_pin;
#endif
bfin_serial_hw_init(&bfin_serial_ports[i]);
-
}
+
}
#ifdef CONFIG_SERIAL_BFIN_CONSOLE
static void bfin_serial_console_putchar(struct uart_port *port, int ch)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
- while (!(UART_GET_LSR(uart)))
+ while (!(UART_GET_LSR(uart) & THRE))
barrier();
UART_PUT_CHAR(uart, ch);
SSYNC();
@@ -857,18 +1017,22 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud,
case 2: *bits = 7; break;
case 3: *bits = 8; break;
}
+#ifndef CONFIG_BF54x
/* Set DLAB in LCR to Access DLL and DLH */
val = UART_GET_LCR(uart);
val |= DLAB;
UART_PUT_LCR(uart, val);
+#endif
dll = UART_GET_DLL(uart);
dlh = UART_GET_DLH(uart);
+#ifndef CONFIG_BF54x
/* Clear DLAB in LCR to Access THR RBR IER */
val = UART_GET_LCR(uart);
val &= ~DLAB;
UART_PUT_LCR(uart, val);
+#endif
*baud = get_sclk() / (16*(dll | dlh << 8));
}
@@ -920,6 +1084,10 @@ static int __init bfin_serial_rs_console_init(void)
{
bfin_serial_init_ports();
register_console(&bfin_serial_console);
+#ifdef CONFIG_KGDB_UART
+ kgdb_entry_state = 0;
+ init_kgdb_uart();
+#endif
return 0;
}
console_initcall(bfin_serial_rs_console_init);
@@ -1012,6 +1180,10 @@ static struct platform_driver bfin_serial_driver = {
static int __init bfin_serial_init(void)
{
int ret;
+#ifdef CONFIG_KGDB_UART
+ struct bfin_serial_port *uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT];
+ struct termios t;
+#endif
pr_info("Serial: Blackfin serial driver\n");
@@ -1025,6 +1197,21 @@ static int __init bfin_serial_init(void)
uart_unregister_driver(&bfin_serial_reg);
}
}
+#ifdef CONFIG_KGDB_UART
+ if (uart->port.cons->index != CONFIG_KGDB_UART_PORT) {
+ request_irq(uart->port.irq, bfin_serial_int,
+ IRQF_DISABLED, "BFIN_UART_RX", uart);
+ pr_info("Request irq for kgdb uart port\n");
+ UART_PUT_IER(uart, UART_GET_IER(uart) | ERBFI);
+ __builtin_bfin_ssync();
+ t.c_cflag = CS8|B57600;
+ t.c_iflag = 0;
+ t.c_oflag = 0;
+ t.c_lflag = ICANON;
+ t.c_line = CONFIG_KGDB_UART_PORT;
+ bfin_serial_set_termios(&uart->port, &t, &t);
+ }
+#endif
return ret;
}
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 81792e6eeb2..6767ee381cd 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -88,7 +88,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&brd->bd_intr_lock);
/* store which revision we have */
- pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev);
+ brd->rev = pdev->revision;
brd->irq = pdev->irq;
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index d09f2097d5b..00924feaf62 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -503,7 +503,8 @@ mpsc_sdma_intr_ack(struct mpsc_port_info *pi)
if (pi->mirror_regs)
pi->shared_regs->SDMA_INTR_CAUSE_m = 0;
- writel(0, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE);
+ writeb(0x00, pi->shared_regs->sdma_intr_base + SDMA_INTR_CAUSE +
+ pi->port.line);
return;
}
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 6b76babc7fb..a0ea4359851 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -842,12 +842,16 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+ PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
PCMCIA_PFC_DEVICE_PROD_ID12(1, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x0a05),
+ PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0032, 0x1101),
PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0104, 0x0070),
PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0101, 0x0562),
PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0104, 0x0070),
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index cf0e663b42e..85309acb75f 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -1,7 +1,7 @@
/*
* Driver for NEC VR4100 series Serial Interface Unit.
*
- * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2004-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
*
* Based on drivers/serial/8250.c, by Russell King.
*
@@ -25,12 +25,12 @@
#endif
#include <linux/console.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/ioport.h>
+#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/ioport.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
@@ -38,11 +38,9 @@
#include <linux/tty_flip.h>
#include <asm/io.h>
-#include <asm/vr41xx/irq.h>
#include <asm/vr41xx/siu.h>
#include <asm/vr41xx/vr41xx.h>
-#define SIU_PORTS_MAX 2
#define SIU_BAUD_BASE 1152000
#define SIU_MAJOR 204
#define SIU_MINOR_BASE 82
@@ -60,32 +58,13 @@
#define IRUSESEL 0x02
#define SIRSEL 0x01
-struct siu_port {
- unsigned int type;
- unsigned int irq;
- unsigned long start;
-};
-
-static const struct siu_port siu_type1_ports[] = {
- { .type = PORT_VR41XX_SIU,
- .irq = SIU_IRQ,
- .start = 0x0c000000UL, },
-};
-
-#define SIU_TYPE1_NR_PORTS (sizeof(siu_type1_ports) / sizeof(struct siu_port))
-
-static const struct siu_port siu_type2_ports[] = {
- { .type = PORT_VR41XX_SIU,
- .irq = SIU_IRQ,
- .start = 0x0f000800UL, },
- { .type = PORT_VR41XX_DSIU,
- .irq = DSIU_IRQ,
- .start = 0x0f000820UL, },
+static struct uart_port siu_uart_ports[SIU_PORTS_MAX] = {
+ [0 ... SIU_PORTS_MAX-1] = {
+ .lock = __SPIN_LOCK_UNLOCKED(siu_uart_ports->lock),
+ .irq = -1,
+ },
};
-#define SIU_TYPE2_NR_PORTS (sizeof(siu_type2_ports) / sizeof(struct siu_port))
-
-static struct uart_port siu_uart_ports[SIU_PORTS_MAX];
static uint8_t lsr_break_flag[SIU_PORTS_MAX];
#define siu_read(port, offset) readb((port)->membase + (offset))
@@ -110,7 +89,6 @@ void vr41xx_select_siu_interface(siu_interface_t interface)
spin_unlock_irqrestore(&port->lock, flags);
}
-
EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface);
void vr41xx_use_irda(irda_use_t use)
@@ -132,7 +110,6 @@ void vr41xx_use_irda(irda_use_t use)
spin_unlock_irqrestore(&port->lock, flags);
}
-
EXPORT_SYMBOL_GPL(vr41xx_use_irda);
void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
@@ -166,7 +143,6 @@ void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
spin_unlock_irqrestore(&port->lock, flags);
}
-
EXPORT_SYMBOL_GPL(vr41xx_select_irda_module);
static inline void siu_clear_fifo(struct uart_port *port)
@@ -177,21 +153,6 @@ static inline void siu_clear_fifo(struct uart_port *port)
siu_write(port, UART_FCR, 0);
}
-static inline int siu_probe_ports(void)
-{
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- return SIU_TYPE1_NR_PORTS;
- case CPU_VR4122:
- case CPU_VR4131:
- case CPU_VR4133:
- return SIU_TYPE2_NR_PORTS;
- }
-
- return 0;
-}
-
static inline unsigned long siu_port_size(struct uart_port *port)
{
switch (port->type) {
@@ -206,21 +167,10 @@ static inline unsigned long siu_port_size(struct uart_port *port)
static inline unsigned int siu_check_type(struct uart_port *port)
{
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- if (port->line == 0)
- return PORT_VR41XX_SIU;
- break;
- case CPU_VR4122:
- case CPU_VR4131:
- case CPU_VR4133:
- if (port->line == 0)
- return PORT_VR41XX_SIU;
- else if (port->line == 1)
- return PORT_VR41XX_DSIU;
- break;
- }
+ if (port->line == 0)
+ return PORT_VR41XX_SIU;
+ if (port->line == 1 && port->irq != -1)
+ return PORT_VR41XX_DSIU;
return PORT_UNKNOWN;
}
@@ -751,44 +701,34 @@ static struct uart_ops siu_uart_ops = {
.verify_port = siu_verify_port,
};
-static int siu_init_ports(void)
+static int siu_init_ports(struct platform_device *pdev)
{
- const struct siu_port *siu;
struct uart_port *port;
- int i, num;
+ struct resource *res;
+ int *type = pdev->dev.platform_data;
+ int i;
- switch (current_cpu_data.cputype) {
- case CPU_VR4111:
- case CPU_VR4121:
- siu = siu_type1_ports;
- break;
- case CPU_VR4122:
- case CPU_VR4131:
- case CPU_VR4133:
- siu = siu_type2_ports;
- break;
- default:
+ if (!type)
return 0;
- }
port = siu_uart_ports;
- num = siu_probe_ports();
- for (i = 0; i < num; i++) {
- spin_lock_init(&port->lock);
- port->irq = siu->irq;
+ for (i = 0; i < SIU_PORTS_MAX; i++) {
+ port->type = type[i];
+ if (port->type == PORT_UNKNOWN)
+ continue;
+ port->irq = platform_get_irq(pdev, i);
port->uartclk = SIU_BAUD_BASE * 16;
port->fifosize = 16;
port->regshift = 0;
port->iotype = UPIO_MEM;
port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
- port->type = siu->type;
port->line = i;
- port->mapbase = siu->start;
- siu++;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ port->mapbase = res->start;
port++;
}
- return num;
+ return i;
}
#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
@@ -883,13 +823,9 @@ static struct console siu_console = {
static int __devinit siu_console_init(void)
{
struct uart_port *port;
- int num, i;
-
- num = siu_init_ports();
- if (num <= 0)
- return -ENODEV;
+ int i;
- for (i = 0; i < num; i++) {
+ for (i = 0; i < SIU_PORTS_MAX; i++) {
port = &siu_uart_ports[i];
port->ops = &siu_uart_ops;
}
@@ -920,7 +856,7 @@ static int __devinit siu_probe(struct platform_device *dev)
struct uart_port *port;
int num, i, retval;
- num = siu_init_ports();
+ num = siu_init_ports(dev);
if (num <= 0)
return -ENODEV;
@@ -998,8 +934,6 @@ static int siu_resume(struct platform_device *dev)
return 0;
}
-static struct platform_device *siu_platform_device;
-
static struct platform_driver siu_device_driver = {
.probe = siu_probe,
.remove = __devexit_p(siu_remove),
@@ -1013,29 +947,12 @@ static struct platform_driver siu_device_driver = {
static int __init vr41xx_siu_init(void)
{
- int retval;
-
- siu_platform_device = platform_device_alloc("SIU", -1);
- if (!siu_platform_device)
- return -ENOMEM;
-
- retval = platform_device_add(siu_platform_device);
- if (retval < 0) {
- platform_device_put(siu_platform_device);
- return retval;
- }
-
- retval = platform_driver_register(&siu_device_driver);
- if (retval < 0)
- platform_device_unregister(siu_platform_device);
-
- return retval;
+ return platform_driver_register(&siu_device_driver);
}
static void __exit vr41xx_siu_exit(void)
{
platform_driver_unregister(&siu_device_driver);
- platform_device_unregister(siu_platform_device);
}
module_init(vr41xx_siu_init);
diff --git a/drivers/spi/at25.c b/drivers/spi/at25.c
index 8efa07e8b8c..e007833cca5 100644
--- a/drivers/spi/at25.c
+++ b/drivers/spi/at25.c
@@ -111,7 +111,8 @@ at25_ee_read(
}
static ssize_t
-at25_bin_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct device *dev;
struct at25_data *at25;
@@ -236,7 +237,8 @@ at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count)
}
static ssize_t
-at25_bin_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct device *dev;
struct at25_data *at25;
@@ -314,7 +316,6 @@ static int at25_probe(struct spi_device *spi)
*/
at25->bin.attr.name = "eeprom";
at25->bin.attr.mode = S_IRUSR;
- at25->bin.attr.owner = THIS_MODULE;
at25->bin.read = at25_bin_read;
at25->bin.size = at25->chip.byte_len;
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
index 1d8a2f6bb8e..8b2601de363 100644
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -113,16 +113,16 @@ static void atmel_spi_next_xfer(struct spi_master *master,
len = as->remaining_bytes;
- tx_dma = xfer->tx_dma;
- rx_dma = xfer->rx_dma;
+ tx_dma = xfer->tx_dma + xfer->len - len;
+ rx_dma = xfer->rx_dma + xfer->len - len;
/* use scratch buffer only when rx or tx data is unspecified */
- if (rx_dma == INVALID_DMA_ADDRESS) {
+ if (!xfer->rx_buf) {
rx_dma = as->buffer_dma;
if (len > BUFFER_SIZE)
len = BUFFER_SIZE;
}
- if (tx_dma == INVALID_DMA_ADDRESS) {
+ if (!xfer->tx_buf) {
tx_dma = as->buffer_dma;
if (len > BUFFER_SIZE)
len = BUFFER_SIZE;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index c3219b29b5a..4831edbae2d 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -411,7 +411,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
*/
int spi_register_master(struct spi_master *master)
{
- static atomic_t dyn_bus_id = ATOMIC_INIT((1<<16) - 1);
+ static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
struct device *dev = master->cdev.dev;
int status = -ENODEV;
int dynamic = 0;
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 7d2d9ec6cac..48587c27050 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -582,14 +582,19 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
dev_dbg(&drv_data->pdev->dev, "in dma_irq_handler\n");
clear_dma_irqstat(CH_SPI);
+ /* Wait for DMA to complete */
+ while (get_dma_curr_irqstat(CH_SPI) & DMA_RUN)
+ continue;
+
/*
- * wait for the last transaction shifted out. yes, these two
- * while loops are supposed to be the same (see the HRM).
+ * wait for the last transaction shifted out. HRM states:
+ * at this point there may still be data in the SPI DMA FIFO waiting
+ * to be transmitted ... software needs to poll TXS in the SPI_STAT
+ * register until it goes low for 2 successive reads
*/
if (drv_data->tx != NULL) {
- while (bfin_read_SPI_STAT() & TXS)
- continue;
- while (bfin_read_SPI_STAT() & TXS)
+ while ((bfin_read_SPI_STAT() & TXS) ||
+ (bfin_read_SPI_STAT() & TXS))
continue;
}
@@ -1082,7 +1087,7 @@ static int setup(struct spi_device *spi)
*/
static void cleanup(struct spi_device *spi)
{
- struct chip_data *chip = spi_get_ctldata((struct spi_device *)spi);
+ struct chip_data *chip = spi_get_ctldata(spi);
kfree(chip);
}
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 51daa212c6b..656be4a5094 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -121,7 +121,7 @@
32.768 KHz Clock */
/* SPI DMA Register Bit Fields & Masks */
-#define SPI_DMA_RHDMA (0xF << 4) /* RXFIFO Half Status */
+#define SPI_DMA_RHDMA (0x1 << 4) /* RXFIFO Half Status */
#define SPI_DMA_RFDMA (0x1 << 5) /* RXFIFO Full Status */
#define SPI_DMA_TEDMA (0x1 << 6) /* TXFIFO Empty Status */
#define SPI_DMA_THDMA (0x1 << 7) /* TXFIFO Half Status */
@@ -1355,6 +1355,7 @@ static int setup(struct spi_device *spi)
spi->bits_per_word,
spi_speed_hz(SPI_CONTROL_DATARATE_MIN),
spi->max_speed_hz);
+ return status;
err_first_setup:
kfree(chip);
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 3524e3fc08b..ed979f13908 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -136,7 +136,7 @@ struct dec_serial *zs_chain; /* list of all channels */
struct tty_struct zs_ttys[NUM_CHANNELS];
#ifdef CONFIG_SERIAL_DEC_CONSOLE
-static struct console sercons;
+static struct console zs_console;
#endif
#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
!defined(MODULE)
@@ -383,7 +383,7 @@ static void receive_chars(struct dec_serial *info)
#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
!defined(MODULE)
- if (break_pressed && info->line == sercons.index) {
+ if (break_pressed && info->line == zs_console.index) {
/* Ignore the null char got when BREAK is removed. */
if (ch == 0)
continue;
@@ -446,7 +446,7 @@ static void status_handle(struct dec_serial *info)
if ((stat & BRK_ABRT) && !(info->read_reg_zero & BRK_ABRT)) {
#if defined(CONFIG_SERIAL_DEC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && \
!defined(MODULE)
- if (info->line == sercons.index) {
+ if (info->line == zs_console.index) {
if (!break_pressed)
break_pressed = jiffies;
} else
@@ -1557,9 +1557,9 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
}
#ifdef CONFIG_SERIAL_DEC_CONSOLE
- if (sercons.cflag && sercons.index == line) {
- tty->termios->c_cflag = sercons.cflag;
- sercons.cflag = 0;
+ if (zs_console.cflag && zs_console.index == line) {
+ tty->termios->c_cflag = zs_console.cflag;
+ zs_console.cflag = 0;
change_speed(info);
}
#endif
@@ -2069,7 +2069,7 @@ static int __init serial_console_setup(struct console *co, char *options)
return 0;
}
-static struct console sercons = {
+static struct console zs_console = {
.name = "ttyS",
.write = serial_console_write,
.device = serial_console_device,
@@ -2083,7 +2083,7 @@ static struct console sercons = {
*/
void __init zs_serial_console_init(void)
{
- register_console(&sercons);
+ register_console(&zs_console);
}
#endif /* ifdef CONFIG_SERIAL_DEC_CONSOLE */
@@ -2182,7 +2182,7 @@ struct dec_serial_hook zs_kgdbhook = {
.init_info = kgdbhook_init_info,
.rx_char = kgdbhook_rx_char,
.cflags = B38400 | CS8 | CLOCAL,
-}
+};
void __init zs_kgdb_hook(int tty_num)
{
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 15499b7e33f..071b9675a78 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -2,8 +2,12 @@
# USB device configuration
#
-menu "USB support"
+menuconfig USB_SUPPORT
+ bool "USB support"
depends on HAS_IOMEM
+ default y
+
+if USB_SUPPORT
# Host-side USB depends on having a host controller
# NOTE: dummy_hcd is always an option, but it's ignored here ...
@@ -12,6 +16,7 @@ config USB_ARCH_HAS_HCD
boolean
default y if USB_ARCH_HAS_OHCI
default y if USB_ARCH_HAS_EHCI
+ default y if PCMCIA # sl811_cs
default y if ARM # SL-811
default PCI
@@ -130,5 +135,4 @@ source "drivers/usb/atm/Kconfig"
source "drivers/usb/gadget/Kconfig"
-endmenu
-
+endif # USB_SUPPORT
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 72464b58699..befff5f9d58 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_USB_OHCI_HCD) += host/
obj-$(CONFIG_USB_UHCI_HCD) += host/
obj-$(CONFIG_USB_SL811_HCD) += host/
obj-$(CONFIG_USB_U132_HCD) += host/
-obj-$(CONFIG_USB_OHCI_AT91) += host/
+obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_ACM) += class/
obj-$(CONFIG_USB_PRINTER) += class/
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 30b7bfbc985..1bc884051e0 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -171,7 +171,7 @@ struct cxacru_data {
struct delayed_work poll_work;
u32 card_info[CXINF_MAX];
struct mutex poll_state_serialize;
- int poll_state;
+ enum cxacru_poll_state poll_state;
/* contol handles */
struct mutex cm_serialize;
@@ -226,58 +226,48 @@ static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf)
static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf)
{
- if (unlikely(value < 0)) {
- return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
- value / 100, -value % 100);
- } else {
- return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
- value / 100, value % 100);
- }
+ return snprintf(buf, PAGE_SIZE, "%d.%02u\n",
+ value / 100, abs(value) % 100);
}
static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
{
- switch (value) {
- case 0: return snprintf(buf, PAGE_SIZE, "no\n");
- case 1: return snprintf(buf, PAGE_SIZE, "yes\n");
- default: return 0;
- }
+ static char *str[] = { "no", "yes" };
+ if (unlikely(value >= ARRAY_SIZE(str)))
+ return snprintf(buf, PAGE_SIZE, "%u\n", value);
+ return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
}
static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
{
- switch (value) {
- case 1: return snprintf(buf, PAGE_SIZE, "not connected\n");
- case 2: return snprintf(buf, PAGE_SIZE, "connected\n");
- case 3: return snprintf(buf, PAGE_SIZE, "lost\n");
- default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
- }
+ static char *str[] = { NULL, "not connected", "connected", "lost" };
+ if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+ return snprintf(buf, PAGE_SIZE, "%u\n", value);
+ return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
}
static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf)
{
- switch (value) {
- case 0: return snprintf(buf, PAGE_SIZE, "down\n");
- case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n");
- case 2: return snprintf(buf, PAGE_SIZE, "training\n");
- case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n");
- case 4: return snprintf(buf, PAGE_SIZE, "exchange\n");
- case 5: return snprintf(buf, PAGE_SIZE, "up\n");
- case 6: return snprintf(buf, PAGE_SIZE, "waiting\n");
- case 7: return snprintf(buf, PAGE_SIZE, "initialising\n");
- default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
- }
+ static char *str[] = { "down", "attempting to activate",
+ "training", "channel analysis", "exchange", "up",
+ "waiting", "initialising"
+ };
+ if (unlikely(value >= ARRAY_SIZE(str)))
+ return snprintf(buf, PAGE_SIZE, "%u\n", value);
+ return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
}
static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf)
{
- switch (value) {
- case 0: return 0;
- case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n");
- case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n");
- case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n");
- default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
- }
+ static char *str[] = {
+ NULL,
+ "ANSI T1.413",
+ "ITU-T G.992.1 (G.DMT)",
+ "ITU-T G.992.2 (G.LITE)"
+ };
+ if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
+ return snprintf(buf, PAGE_SIZE, "%u\n", value);
+ return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
}
/*
@@ -308,11 +298,10 @@ static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev,
struct cxacru_data *instance = usbatm_instance->driver_data;
u32 value = instance->card_info[CXINF_LINE_STARTABLE];
- switch (value) {
- case 0: return snprintf(buf, PAGE_SIZE, "running\n");
- case 1: return snprintf(buf, PAGE_SIZE, "stopped\n");
- default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value);
- }
+ static char *str[] = { "running", "stopped" };
+ if (unlikely(value >= ARRAY_SIZE(str)))
+ return snprintf(buf, PAGE_SIZE, "%u\n", value);
+ return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
}
static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
@@ -476,8 +465,6 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
add_timer(&timer);
wait_for_completion(done);
status = urb->status;
- if (status == -ECONNRESET)
- status = -ETIMEDOUT;
del_timer_sync(&timer);
if (actual_length)
@@ -629,10 +616,22 @@ static int cxacru_card_status(struct cxacru_data *instance)
return 0;
}
+static void cxacru_remove_device_files(struct usbatm_data *usbatm_instance,
+ struct atm_dev *atm_dev)
+{
+ struct usb_interface *intf = usbatm_instance->usb_intf;
+
+ #define CXACRU_DEVICE_REMOVE_FILE(_name) \
+ device_remove_file(&intf->dev, &dev_attr_##_name);
+ CXACRU_ALL_FILES(REMOVE);
+ #undef CXACRU_DEVICE_REMOVE_FILE
+}
+
static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
struct atm_dev *atm_dev)
{
struct cxacru_data *instance = usbatm_instance->driver_data;
+ struct usb_interface *intf = usbatm_instance->usb_intf;
/*
struct atm_dev *atm_dev = usbatm_instance->atm_dev;
*/
@@ -649,14 +648,18 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
return ret;
}
+ #define CXACRU_DEVICE_CREATE_FILE(_name) \
+ ret = device_create_file(&intf->dev, &dev_attr_##_name); \
+ if (unlikely(ret)) \
+ goto fail_sysfs;
+ CXACRU_ALL_FILES(CREATE);
+ #undef CXACRU_DEVICE_CREATE_FILE
+
/* start ADSL */
mutex_lock(&instance->adsl_state_serialize);
ret = cxacru_cm(instance, CM_REQUEST_CHIP_ADSL_LINE_START, NULL, 0, NULL, 0);
- if (ret < 0) {
+ if (ret < 0)
atm_err(usbatm_instance, "cxacru_atm_start: CHIP_ADSL_LINE_START returned %d\n", ret);
- mutex_unlock(&instance->adsl_state_serialize);
- return ret;
- }
/* Start status polling */
mutex_lock(&instance->poll_state_serialize);
@@ -680,6 +683,11 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
if (start_polling)
cxacru_poll_status(&instance->poll_work.work);
return 0;
+
+fail_sysfs:
+ usb_err(usbatm_instance, "cxacru_atm_start: device_create_file failed (%d)\n", ret);
+ cxacru_remove_device_files(usbatm_instance, atm_dev);
+ return ret;
}
static void cxacru_poll_status(struct work_struct *work)
@@ -1065,13 +1073,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
goto fail;
}
- #define CXACRU_DEVICE_CREATE_FILE(_name) \
- ret = device_create_file(&intf->dev, &dev_attr_##_name); \
- if (unlikely(ret)) \
- goto fail_sysfs;
- CXACRU_ALL_FILES(CREATE);
- #undef CXACRU_DEVICE_CREATE_FILE
-
usb_fill_int_urb(instance->rcv_urb,
usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD),
instance->rcv_buf, PAGE_SIZE,
@@ -1092,14 +1093,6 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance,
return 0;
- fail_sysfs:
- dbg("cxacru_bind: device_create_file failed (%d)\n", ret);
-
- #define CXACRU_DEVICE_REMOVE_FILE(_name) \
- device_remove_file(&intf->dev, &dev_attr_##_name);
- CXACRU_ALL_FILES(REMOVE);
- #undef CXACRU_DEVICE_REVOVE_FILE
-
fail:
free_page((unsigned long) instance->snd_buf);
free_page((unsigned long) instance->rcv_buf);
@@ -1146,11 +1139,6 @@ static void cxacru_unbind(struct usbatm_data *usbatm_instance,
free_page((unsigned long) instance->snd_buf);
free_page((unsigned long) instance->rcv_buf);
- #define CXACRU_DEVICE_REMOVE_FILE(_name) \
- device_remove_file(&intf->dev, &dev_attr_##_name);
- CXACRU_ALL_FILES(REMOVE);
- #undef CXACRU_DEVICE_REVOVE_FILE
-
kfree(instance);
usbatm_instance->driver_data = NULL;
@@ -1231,6 +1219,7 @@ static struct usbatm_driver cxacru_driver = {
.heavy_init = cxacru_heavy_init,
.unbind = cxacru_unbind,
.atm_start = cxacru_atm_start,
+ .atm_stop = cxacru_remove_device_files,
.bulk_in = CXACRU_EP_DATA,
.bulk_out = CXACRU_EP_DATA,
.rx_padding = 3,
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 0081c1d1268..cd51520c7e7 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1157,6 +1157,9 @@ static struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
+ { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */
+ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+ },
{ USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 7b1edfe46b2..9a1478972bf 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -1,5 +1,5 @@
/*
- * usblp.c Version 0.13
+ * usblp.c
*
* Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
@@ -61,11 +61,11 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.13"
#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
#define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192
+#define USBLP_BUF_SIZE_IN 1024
#define USBLP_DEVICE_ID_SIZE 1024
/* ioctls: */
@@ -127,14 +127,22 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
*/
#define STATUS_BUF_SIZE 8
+/*
+ * Locks down the locking order:
+ * ->wmut locks wstatus.
+ * ->mut locks the whole usblp, except [rw]complete, and thus, by indirection,
+ * [rw]status. We only touch status when we know the side idle.
+ * ->lock locks what interrupt accesses.
+ */
struct usblp {
struct usb_device *dev; /* USB device */
- struct mutex mut; /* locks this struct, especially "dev" */
- char *writebuf; /* write transfer_buffer */
+ struct mutex wmut;
+ struct mutex mut;
+ spinlock_t lock; /* locks rcomplete, wcomplete */
char *readbuf; /* read transfer_buffer */
char *statusbuf; /* status transfer_buffer */
- struct urb *readurb, *writeurb; /* The urbs */
- wait_queue_head_t wait; /* Zzzzz ... */
+ struct usb_anchor urbs;
+ wait_queue_head_t rwait, wwait;
int readcount; /* Counter for reads */
int ifnum; /* Interface number */
struct usb_interface *intf; /* The interface */
@@ -147,8 +155,9 @@ struct usblp {
} protocol[USBLP_MAX_PROTOCOLS];
int current_protocol;
int minor; /* minor number of device */
- int wcomplete; /* writing is completed */
- int rcomplete; /* reading is completed */
+ int wcomplete, rcomplete;
+ int wstatus; /* bytes written or error */
+ int rstatus; /* bytes ready or error */
unsigned int quirks; /* quirks flags */
unsigned char used; /* True if open */
unsigned char present; /* True if not disconnected */
@@ -166,9 +175,6 @@ static void usblp_dump(struct usblp *usblp) {
dbg("dev=0x%p", usblp->dev);
dbg("present=%d", usblp->present);
dbg("readbuf=0x%p", usblp->readbuf);
- dbg("writebuf=0x%p", usblp->writebuf);
- dbg("readurb=0x%p", usblp->readurb);
- dbg("writeurb=0x%p", usblp->writeurb);
dbg("readcount=%d", usblp->readcount);
dbg("ifnum=%d", usblp->ifnum);
for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
@@ -178,8 +184,8 @@ static void usblp_dump(struct usblp *usblp) {
}
dbg("current_protocol=%d", usblp->current_protocol);
dbg("minor=%d", usblp->minor);
- dbg("wcomplete=%d", usblp->wcomplete);
- dbg("rcomplete=%d", usblp->rcomplete);
+ dbg("wstatus=%d", usblp->wstatus);
+ dbg("rstatus=%d", usblp->rstatus);
dbg("quirks=%d", usblp->quirks);
dbg("used=%d", usblp->used);
dbg("bidir=%d", usblp->bidir);
@@ -222,6 +228,11 @@ static const struct quirk_printer_struct quirk_printers[] = {
{ 0, 0 }
};
+static int usblp_wwait(struct usblp *usblp, int nonblock);
+static int usblp_wtest(struct usblp *usblp, int nonblock);
+static int usblp_rwait_and_lock(struct usblp *usblp, int nonblock);
+static int usblp_rtest(struct usblp *usblp, int nonblock);
+static int usblp_submit_read(struct usblp *usblp);
static int usblp_select_alts(struct usblp *usblp);
static int usblp_set_protocol(struct usblp *usblp, int protocol);
static int usblp_cache_device_id_string(struct usblp *usblp);
@@ -279,33 +290,47 @@ static void usblp_bulk_read(struct urb *urb)
{
struct usblp *usblp = urb->context;
- if (unlikely(!usblp || !usblp->dev || !usblp->used))
- return;
-
- if (unlikely(!usblp->present))
- goto unplug;
- if (unlikely(urb->status))
- warn("usblp%d: nonzero read/write bulk status received: %d",
- usblp->minor, urb->status);
+ if (usblp->present && usblp->used) {
+ if (urb->status)
+ printk(KERN_WARNING "usblp%d: "
+ "nonzero read bulk status received: %d\n",
+ usblp->minor, urb->status);
+ }
+ spin_lock(&usblp->lock);
+ if (urb->status < 0)
+ usblp->rstatus = urb->status;
+ else
+ usblp->rstatus = urb->actual_length;
usblp->rcomplete = 1;
-unplug:
- wake_up_interruptible(&usblp->wait);
+ wake_up(&usblp->rwait);
+ spin_unlock(&usblp->lock);
+
+ usb_free_urb(urb);
}
static void usblp_bulk_write(struct urb *urb)
{
struct usblp *usblp = urb->context;
- if (unlikely(!usblp || !usblp->dev || !usblp->used))
- return;
- if (unlikely(!usblp->present))
- goto unplug;
- if (unlikely(urb->status))
- warn("usblp%d: nonzero read/write bulk status received: %d",
- usblp->minor, urb->status);
+ if (usblp->present && usblp->used) {
+ if (urb->status)
+ printk(KERN_WARNING "usblp%d: "
+ "nonzero write bulk status received: %d\n",
+ usblp->minor, urb->status);
+ }
+ spin_lock(&usblp->lock);
+ if (urb->status < 0)
+ usblp->wstatus = urb->status;
+ else
+ usblp->wstatus = urb->actual_length;
usblp->wcomplete = 1;
-unplug:
- wake_up_interruptible(&usblp->wait);
+ wake_up(&usblp->wwait);
+ spin_unlock(&usblp->lock);
+
+ /* XXX Use usb_setup_bulk_urb when available. Talk to Marcel. */
+ kfree(urb->transfer_buffer);
+ urb->transfer_buffer = NULL; /* Not refcounted, so to be safe... */
+ usb_free_urb(urb);
}
/*
@@ -322,7 +347,8 @@ static int usblp_check_status(struct usblp *usblp, int err)
error = usblp_read_status (usblp, usblp->statusbuf);
if (error < 0) {
if (printk_ratelimit())
- err("usblp%d: error %d reading printer status",
+ printk(KERN_ERR
+ "usblp%d: error %d reading printer status\n",
usblp->minor, error);
return 0;
}
@@ -336,8 +362,10 @@ static int usblp_check_status(struct usblp *usblp, int err)
if (~status & LP_PSELECD)
newerr = 2;
- if (newerr != err)
- info("usblp%d: %s", usblp->minor, usblp_messages[newerr]);
+ if (newerr != err) {
+ printk(KERN_INFO "usblp%d: %s\n",
+ usblp->minor, usblp_messages[newerr]);
+ }
return newerr;
}
@@ -345,14 +373,9 @@ static int usblp_check_status(struct usblp *usblp, int err)
static int handle_bidir (struct usblp *usblp)
{
if (usblp->bidir && usblp->used && !usblp->sleeping) {
- usblp->readcount = 0;
- usblp->readurb->dev = usblp->dev;
- if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
- usblp->used = 0;
+ if (usblp_submit_read(usblp) < 0)
return -EIO;
- }
}
-
return 0;
}
@@ -405,13 +428,12 @@ static int usblp_open(struct inode *inode, struct file *file)
usblp->used = 1;
file->private_data = usblp;
- usblp->writeurb->transfer_buffer_length = 0;
usblp->wcomplete = 1; /* we begin writeable */
+ usblp->wstatus = 0;
usblp->rcomplete = 0;
- usblp->writeurb->status = 0;
- usblp->readurb->status = 0;
if (handle_bidir(usblp) < 0) {
+ usblp->used = 0;
file->private_data = NULL;
retval = -EIO;
}
@@ -422,20 +444,17 @@ out:
static void usblp_cleanup (struct usblp *usblp)
{
- info("usblp%d: removed", usblp->minor);
+ printk(KERN_INFO "usblp%d: removed\n", usblp->minor);
+ kfree(usblp->readbuf);
kfree (usblp->device_id_string);
kfree (usblp->statusbuf);
- usb_free_urb(usblp->writeurb);
- usb_free_urb(usblp->readurb);
kfree (usblp);
}
static void usblp_unlink_urbs(struct usblp *usblp)
{
- usb_kill_urb(usblp->writeurb);
- if (usblp->bidir)
- usb_kill_urb(usblp->readurb);
+ usb_kill_anchored_urbs(&usblp->urbs);
}
static int usblp_release(struct inode *inode, struct file *file)
@@ -456,10 +475,18 @@ static int usblp_release(struct inode *inode, struct file *file)
/* No kernel lock - fine */
static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
{
+ int ret;
+ unsigned long flags;
+
struct usblp *usblp = file->private_data;
- poll_wait(file, &usblp->wait, wait);
- return ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN | POLLRDNORM)
+ /* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */
+ poll_wait(file, &usblp->rwait, wait);
+ poll_wait(file, &usblp->wwait, wait);
+ spin_lock_irqsave(&usblp->lock, flags);
+ ret = ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN | POLLRDNORM)
| (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
+ spin_unlock_irqrestore(&usblp->lock, flags);
+ return ret;
}
static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -633,10 +660,11 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
switch (cmd) {
case LPGETSTATUS:
- if (usblp_read_status(usblp, usblp->statusbuf)) {
+ if ((retval = usblp_read_status(usblp, usblp->statusbuf))) {
if (printk_ratelimit())
- err("usblp%d: failed reading printer status",
- usblp->minor);
+ printk(KERN_ERR "usblp%d:"
+ "failed reading printer status (%d)\n",
+ usblp->minor, retval);
retval = -EIO;
goto done;
}
@@ -657,168 +685,303 @@ done:
static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
- int timeout, intr, rv, err = 0, transfer_length = 0;
- size_t writecount = 0;
+ char *writebuf;
+ struct urb *writeurb;
+ int rv;
+ int transfer_length;
+ ssize_t writecount = 0;
+
+ if (mutex_lock_interruptible(&usblp->wmut)) {
+ rv = -EINTR;
+ goto raise_biglock;
+ }
+ if ((rv = usblp_wwait(usblp, !!(file->f_flags & O_NONBLOCK))) < 0)
+ goto raise_wait;
while (writecount < count) {
- if (!usblp->wcomplete) {
- barrier();
- if (file->f_flags & O_NONBLOCK) {
- writecount += transfer_length;
- return writecount ? writecount : -EAGAIN;
- }
-
- timeout = USBLP_WRITE_TIMEOUT;
-
- rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout);
- if (rv < 0)
- return writecount ? writecount : -EINTR;
- }
- intr = mutex_lock_interruptible (&usblp->mut);
- if (intr)
- return writecount ? writecount : -EINTR;
- if (!usblp->present) {
- mutex_unlock (&usblp->mut);
- return -ENODEV;
- }
-
- if (usblp->sleeping) {
- mutex_unlock (&usblp->mut);
- return writecount ? writecount : -ENODEV;
- }
-
- if (usblp->writeurb->status != 0) {
- if (usblp->quirks & USBLP_QUIRK_BIDIR) {
- if (!usblp->wcomplete)
- err("usblp%d: error %d writing to printer",
- usblp->minor, usblp->writeurb->status);
- err = usblp->writeurb->status;
- } else
- err = usblp_check_status(usblp, err);
- mutex_unlock (&usblp->mut);
-
- /* if the fault was due to disconnect, let khubd's
- * call to usblp_disconnect() grab usblp->mut ...
- */
- schedule ();
- continue;
- }
-
- /* We must increment writecount here, and not at the
- * end of the loop. Otherwise, the final loop iteration may
- * be skipped, leading to incomplete printer output.
+ /*
+ * Step 1: Submit next block.
*/
- writecount += transfer_length;
- if (writecount == count) {
- mutex_unlock(&usblp->mut);
- break;
- }
-
- transfer_length=(count - writecount);
- if (transfer_length > USBLP_BUF_SIZE)
+ if ((transfer_length = count - writecount) > USBLP_BUF_SIZE)
transfer_length = USBLP_BUF_SIZE;
- usblp->writeurb->transfer_buffer_length = transfer_length;
-
- if (copy_from_user(usblp->writeurb->transfer_buffer,
+ rv = -ENOMEM;
+ if ((writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL)) == NULL)
+ goto raise_buf;
+ if ((writeurb = usb_alloc_urb(0, GFP_KERNEL)) == NULL)
+ goto raise_urb;
+ usb_fill_bulk_urb(writeurb, usblp->dev,
+ usb_sndbulkpipe(usblp->dev,
+ usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress),
+ writebuf, transfer_length, usblp_bulk_write, usblp);
+ usb_anchor_urb(writeurb, &usblp->urbs);
+
+ if (copy_from_user(writebuf,
buffer + writecount, transfer_length)) {
- mutex_unlock(&usblp->mut);
- return writecount ? writecount : -EFAULT;
+ rv = -EFAULT;
+ goto raise_badaddr;
}
- usblp->writeurb->dev = usblp->dev;
+ spin_lock_irq(&usblp->lock);
usblp->wcomplete = 0;
- err = usb_submit_urb(usblp->writeurb, GFP_KERNEL);
- if (err) {
+ spin_unlock_irq(&usblp->lock);
+ if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) {
+ usblp->wstatus = 0;
+ spin_lock_irq(&usblp->lock);
usblp->wcomplete = 1;
- if (err != -ENOMEM)
- count = -EIO;
- else
- count = writecount ? writecount : -ENOMEM;
- mutex_unlock (&usblp->mut);
- break;
+ wake_up(&usblp->wwait);
+ spin_unlock_irq(&usblp->lock);
+ if (rv != -ENOMEM)
+ rv = -EIO;
+ goto raise_submit;
+ }
+
+ /*
+ * Step 2: Wait for transfer to end, collect results.
+ */
+ rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK));
+ if (rv < 0) {
+ /*
+ * If interrupted, we simply leave the URB to dangle,
+ * so the ->release will call usb_kill_urb().
+ */
+ goto collect_error;
}
- mutex_unlock (&usblp->mut);
+
+ if (usblp->wstatus < 0) {
+ usblp_check_status(usblp, 0);
+ rv = -EIO;
+ goto collect_error;
+ }
+ /*
+ * This is critical: it must be our URB, not other writer's.
+ * The wmut exists mainly to cover us here.
+ */
+ writecount += usblp->wstatus;
}
- return count;
+ mutex_unlock(&usblp->wmut);
+ return writecount;
+
+raise_submit:
+raise_badaddr:
+ usb_unanchor_urb(writeurb);
+ usb_free_urb(writeurb);
+raise_urb:
+ kfree(writebuf);
+raise_buf:
+raise_wait:
+collect_error: /* Out of raise sequence */
+ mutex_unlock(&usblp->wmut);
+raise_biglock:
+ return writecount ? writecount : rv;
}
-static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+/*
+ * Notice that we fail to restart in a few cases: on EFAULT, on restart
+ * error, etc. This is the historical behaviour. In all such cases we return
+ * EIO, and applications loop in order to get the new read going.
+ */
+static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, loff_t *ppos)
{
struct usblp *usblp = file->private_data;
- int rv, intr;
+ ssize_t count;
+ ssize_t avail;
+ int rv;
if (!usblp->bidir)
return -EINVAL;
- intr = mutex_lock_interruptible (&usblp->mut);
- if (intr)
- return -EINTR;
- if (!usblp->present) {
- count = -ENODEV;
+ rv = usblp_rwait_and_lock(usblp, !!(file->f_flags & O_NONBLOCK));
+ if (rv < 0)
+ return rv;
+
+ if ((avail = usblp->rstatus) < 0) {
+ printk(KERN_ERR "usblp%d: error %d reading from printer\n",
+ usblp->minor, (int)avail);
+ usblp_submit_read(usblp);
+ count = -EIO;
goto done;
}
- if (!usblp->rcomplete) {
- barrier();
+ count = len < avail - usblp->readcount ? len : avail - usblp->readcount;
+ if (count != 0 &&
+ copy_to_user(buffer, usblp->readbuf + usblp->readcount, count)) {
+ count = -EFAULT;
+ goto done;
+ }
- if (file->f_flags & O_NONBLOCK) {
- count = -EAGAIN;
- goto done;
- }
- mutex_unlock(&usblp->mut);
- rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present);
- mutex_lock(&usblp->mut);
- if (rv < 0) {
- count = -EINTR;
+ if ((usblp->readcount += count) == avail) {
+ if (usblp_submit_read(usblp) < 0) {
+ /* We don't want to leak USB return codes into errno. */
+ if (count == 0)
+ count = -EIO;
goto done;
}
}
- if (!usblp->present) {
- count = -ENODEV;
- goto done;
+done:
+ mutex_unlock (&usblp->mut);
+ return count;
+}
+
+/*
+ * Wait for the write path to come idle.
+ * This is called under the ->wmut, so the idle path stays idle.
+ *
+ * Our write path has a peculiar property: it does not buffer like a tty,
+ * but waits for the write to succeed. This allows our ->release to bug out
+ * without waiting for writes to drain. But it obviously does not work
+ * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use
+ * select(2) or poll(2) to wait for the buffer to drain before closing.
+ * Alternatively, set blocking mode with fcntl and issue a zero-size write.
+ *
+ * Old v0.13 code had a non-functional timeout for wait_event(). Someone forgot
+ * to check the return code for timeout expiration, so it had no effect.
+ * Apparently, it was intended to check for error conditons, such as out
+ * of paper. It is going to return when we settle things with CUPS. XXX
+ */
+static int usblp_wwait(struct usblp *usblp, int nonblock)
+{
+ DECLARE_WAITQUEUE(waita, current);
+ int rc;
+
+ add_wait_queue(&usblp->wwait, &waita);
+ for (;;) {
+ if (mutex_lock_interruptible(&usblp->mut)) {
+ rc = -EINTR;
+ break;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ((rc = usblp_wtest(usblp, nonblock)) < 0) {
+ mutex_unlock(&usblp->mut);
+ break;
+ }
+ mutex_unlock(&usblp->mut);
+ if (rc == 0)
+ break;
+ schedule();
}
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&usblp->wwait, &waita);
+ return rc;
+}
- if (usblp->sleeping) {
- count = -ENODEV;
- goto done;
+static int usblp_wtest(struct usblp *usblp, int nonblock)
+{
+ unsigned long flags;
+
+ if (!usblp->present)
+ return -ENODEV;
+ if (signal_pending(current))
+ return -EINTR;
+ spin_lock_irqsave(&usblp->lock, flags);
+ if (usblp->wcomplete) {
+ spin_unlock_irqrestore(&usblp->lock, flags);
+ return 0;
}
+ spin_unlock_irqrestore(&usblp->lock, flags);
+ if (usblp->sleeping)
+ return -ENODEV;
+ if (nonblock)
+ return -EAGAIN;
+ return 1;
+}
- if (usblp->readurb->status) {
- err("usblp%d: error %d reading from printer",
- usblp->minor, usblp->readurb->status);
- usblp->readurb->dev = usblp->dev;
- usblp->readcount = 0;
- usblp->rcomplete = 0;
- if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0)
- dbg("error submitting urb");
- count = -EIO;
- goto done;
+/*
+ * Wait for read bytes to become available. This probably should have been
+ * called usblp_r_lock_and_wait(), because we lock first. But it's a traditional
+ * name for functions which lock and return.
+ *
+ * We do not use wait_event_interruptible because it makes locking iffy.
+ */
+static int usblp_rwait_and_lock(struct usblp *usblp, int nonblock)
+{
+ DECLARE_WAITQUEUE(waita, current);
+ int rc;
+
+ add_wait_queue(&usblp->rwait, &waita);
+ for (;;) {
+ if (mutex_lock_interruptible(&usblp->mut)) {
+ rc = -EINTR;
+ break;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ((rc = usblp_rtest(usblp, nonblock)) < 0) {
+ mutex_unlock(&usblp->mut);
+ break;
+ }
+ if (rc == 0) /* Keep it locked */
+ break;
+ mutex_unlock(&usblp->mut);
+ schedule();
}
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&usblp->rwait, &waita);
+ return rc;
+}
- count = count < usblp->readurb->actual_length - usblp->readcount ?
- count : usblp->readurb->actual_length - usblp->readcount;
+static int usblp_rtest(struct usblp *usblp, int nonblock)
+{
+ unsigned long flags;
- if (copy_to_user(buffer, usblp->readurb->transfer_buffer + usblp->readcount, count)) {
- count = -EFAULT;
- goto done;
+ if (!usblp->present)
+ return -ENODEV;
+ if (signal_pending(current))
+ return -EINTR;
+ spin_lock_irqsave(&usblp->lock, flags);
+ if (usblp->rcomplete) {
+ spin_unlock_irqrestore(&usblp->lock, flags);
+ return 0;
}
+ spin_unlock_irqrestore(&usblp->lock, flags);
+ if (usblp->sleeping)
+ return -ENODEV;
+ if (nonblock)
+ return -EAGAIN;
+ return 1;
+}
- if ((usblp->readcount += count) == usblp->readurb->actual_length) {
- usblp->readcount = 0;
- usblp->readurb->dev = usblp->dev;
- usblp->rcomplete = 0;
- if (usb_submit_urb(usblp->readurb, GFP_KERNEL)) {
- count = -EIO;
- goto done;
- }
+/*
+ * Please check ->bidir and other such things outside for now.
+ */
+static int usblp_submit_read(struct usblp *usblp)
+{
+ struct urb *urb;
+ unsigned long flags;
+ int rc;
+
+ rc = -ENOMEM;
+ if ((urb = usb_alloc_urb(0, GFP_KERNEL)) == NULL)
+ goto raise_urb;
+
+ usb_fill_bulk_urb(urb, usblp->dev,
+ usb_rcvbulkpipe(usblp->dev,
+ usblp->protocol[usblp->current_protocol].epread->bEndpointAddress),
+ usblp->readbuf, USBLP_BUF_SIZE_IN,
+ usblp_bulk_read, usblp);
+ usb_anchor_urb(urb, &usblp->urbs);
+
+ spin_lock_irqsave(&usblp->lock, flags);
+ usblp->readcount = 0; /* XXX Why here? */
+ usblp->rcomplete = 0;
+ spin_unlock_irqrestore(&usblp->lock, flags);
+ if ((rc = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
+ dbg("error submitting urb (%d)", rc);
+ spin_lock_irqsave(&usblp->lock, flags);
+ usblp->rstatus = rc;
+ usblp->rcomplete = 1;
+ spin_unlock_irqrestore(&usblp->lock, flags);
+ goto raise_submit;
}
-done:
- mutex_unlock (&usblp->mut);
- return count;
+ return 0;
+
+raise_submit:
+ usb_unanchor_urb(urb);
+ usb_free_urb(urb);
+raise_urb:
+ return rc;
}
/*
@@ -892,55 +1055,41 @@ static int usblp_probe(struct usb_interface *intf,
/* Malloc and start initializing usblp structure so we can use it
* directly. */
if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
- err("out of memory for usblp");
+ retval = -ENOMEM;
goto abort;
}
usblp->dev = dev;
+ mutex_init(&usblp->wmut);
mutex_init (&usblp->mut);
- init_waitqueue_head(&usblp->wait);
+ spin_lock_init(&usblp->lock);
+ init_waitqueue_head(&usblp->rwait);
+ init_waitqueue_head(&usblp->wwait);
+ init_usb_anchor(&usblp->urbs);
usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
usblp->intf = intf;
- usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
- if (!usblp->writeurb) {
- err("out of memory");
- goto abort;
- }
- usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
- if (!usblp->readurb) {
- err("out of memory");
- goto abort;
- }
-
/* Malloc device ID string buffer to the largest expected length,
* since we can re-query it on an ioctl and a dynamic string
* could change in length. */
if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) {
- err("out of memory for device_id_string");
+ retval = -ENOMEM;
goto abort;
}
- usblp->writebuf = usblp->readbuf = NULL;
- usblp->writeurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
- usblp->readurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
- /* Malloc write & read buffers. We somewhat wastefully
+ /*
+ * Allocate read buffer. We somewhat wastefully
* malloc both regardless of bidirectionality, because the
- * alternate setting can be changed later via an ioctl. */
- if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
- GFP_KERNEL, &usblp->writeurb->transfer_dma))) {
- err("out of memory for write buf");
- goto abort;
- }
- if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE,
- GFP_KERNEL, &usblp->readurb->transfer_dma))) {
- err("out of memory for read buf");
+ * alternate setting can be changed later via an ioctl.
+ */
+ if (!(usblp->readbuf = kmalloc(USBLP_BUF_SIZE_IN, GFP_KERNEL))) {
+ retval = -ENOMEM;
goto abort;
}
/* Allocate buffer for printer status */
usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL);
if (!usblp->statusbuf) {
- err("out of memory for statusbuf");
+ retval = -ENOMEM;
goto abort;
}
@@ -955,12 +1104,15 @@ static int usblp_probe(struct usb_interface *intf,
dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
+ retval = -ENODEV;
goto abort;
}
/* Setup the selected alternate setting and endpoints. */
- if (usblp_set_protocol(usblp, protocol) < 0)
+ if (usblp_set_protocol(usblp, protocol) < 0) {
+ retval = -ENODEV; /* ->probe isn't ->ioctl */
goto abort;
+ }
/* Retrieve and store the device ID string. */
usblp_cache_device_id_string(usblp);
@@ -978,12 +1130,14 @@ static int usblp_probe(struct usb_interface *intf,
retval = usb_register_dev(intf, &usblp_class);
if (retval) {
- err("Not able to get a minor for this device.");
+ printk(KERN_ERR "usblp: Not able to get a minor"
+ " (base %u, slice default): %d\n",
+ USBLP_MINOR_BASE, retval);
goto abort_intfdata;
}
usblp->minor = intf->minor;
- info("usblp%d: USB %sdirectional printer dev %d "
- "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
+ printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d "
+ "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n",
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
usblp->ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
@@ -998,19 +1152,12 @@ abort_intfdata:
device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
abort:
if (usblp) {
- if (usblp->writebuf)
- usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
- usblp->writebuf, usblp->writeurb->transfer_dma);
- if (usblp->readbuf)
- usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
- usblp->readbuf, usblp->readurb->transfer_dma);
+ kfree(usblp->readbuf);
kfree(usblp->statusbuf);
kfree(usblp->device_id_string);
- usb_free_urb(usblp->writeurb);
- usb_free_urb(usblp->readurb);
kfree(usblp);
}
- return -EIO;
+ return retval;
}
/*
@@ -1079,8 +1226,9 @@ static int usblp_select_alts(struct usblp *usblp)
if (ifd->desc.bInterfaceProtocol == 1) {
epread = NULL;
} else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
- info("Disabling reads from problem bidirectional "
- "printer on usblp%d", usblp->minor);
+ printk(KERN_INFO "usblp%d: Disabling reads from "
+ "problematic bidirectional printer\n",
+ usblp->minor);
epread = NULL;
}
@@ -1120,25 +1268,12 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol)
return -EINVAL;
r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
if (r < 0) {
- err("can't set desired altsetting %d on interface %d",
+ printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n",
alts, usblp->ifnum);
return r;
}
- usb_fill_bulk_urb(usblp->writeurb, usblp->dev,
- usb_sndbulkpipe(usblp->dev,
- usblp->protocol[protocol].epwrite->bEndpointAddress),
- usblp->writebuf, 0,
- usblp_bulk_write, usblp);
-
usblp->bidir = (usblp->protocol[protocol].epread != NULL);
- if (usblp->bidir)
- usb_fill_bulk_urb(usblp->readurb, usblp->dev,
- usb_rcvbulkpipe(usblp->dev,
- usblp->protocol[protocol].epread->bEndpointAddress),
- usblp->readbuf, USBLP_BUF_SIZE,
- usblp_bulk_read, usblp);
-
usblp->current_protocol = protocol;
dbg("usblp%d set protocol %d", usblp->minor, protocol);
return 0;
@@ -1191,13 +1326,11 @@ static void usblp_disconnect(struct usb_interface *intf)
mutex_lock (&usblp_mutex);
mutex_lock (&usblp->mut);
usblp->present = 0;
+ wake_up(&usblp->wwait);
+ wake_up(&usblp->rwait);
usb_set_intfdata (intf, NULL);
usblp_unlink_urbs(usblp);
- usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
- usblp->writebuf, usblp->writeurb->transfer_dma);
- usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
- usblp->readbuf, usblp->readurb->transfer_dma);
mutex_unlock (&usblp->mut);
if (!usblp->used)
@@ -1212,6 +1345,11 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
/* we take no more IO */
usblp->sleeping = 1;
usblp_unlink_urbs(usblp);
+#if 0 /* XXX Do we want this? What if someone is reading, should we fail? */
+ /* not strictly necessary, but just in case */
+ wake_up(&usblp->wwait);
+ wake_up(&usblp->rwait);
+#endif
return 0;
}
@@ -1252,12 +1390,7 @@ static struct usb_driver usblp_driver = {
static int __init usblp_init(void)
{
- int retval;
- retval = usb_register(&usblp_driver);
- if (!retval)
- info(DRIVER_VERSION ": " DRIVER_DESC);
-
- return retval;
+ return usb_register(&usblp_driver);
}
static void __exit usblp_exit(void)
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f493fb1eaa2..97b09f28270 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -40,21 +40,25 @@ config USB_DEVICEFS
config USB_DEVICE_CLASS
bool "USB device class-devices (DEPRECATED)"
depends on USB
- default n
+ default y
---help---
Userspace access to USB devices is granted by device-nodes exported
directly from the usbdev in sysfs. Old versions of the driver
core and udev needed additional class devices to export device nodes.
These additional devices are difficult to handle in userspace, if
- information about USB interfaces must be available. One device contains
- the device node, the other device contains the interface data. Both
- devices are at the same level in sysfs (siblings) and one can't access
- the other. The device node created directly by the usbdev is the parent
- device of the interface and therefore easily accessible from the interface
- event.
-
- This option provides backward compatibility if needed.
+ information about USB interfaces must be available. One device
+ contains the device node, the other device contains the interface
+ data. Both devices are at the same level in sysfs (siblings) and one
+ can't access the other. The device node created directly by the
+ usb device is the parent device of the interface and therefore
+ easily accessible from the interface event.
+
+ This option provides backward compatibility for libusb device
+ nodes (lsusb) when usbfs is not used, and the following udev rule
+ doesn't exist:
+ SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", \
+ NAME="bus/usb/$env{BUSNUM}/$env{DEVNUM}", MODE="0644"
config USB_DYNAMIC_MINORS
bool "Dynamic USB minor allocation (EXPERIMENTAL)"
@@ -82,6 +86,31 @@ config USB_SUSPEND
If you are unsure about this, say N here.
+config USB_PERSIST
+ bool "USB device persistence during system suspend (DANGEROUS)"
+ depends on USB && PM && EXPERIMENTAL
+ default n
+ help
+
+ If you say Y here and enable the "power/persist" attribute
+ for a USB device, the device's data structures will remain
+ persistent across system suspend, even if the USB bus loses
+ power. (This includes hibernation, also known as swsusp or
+ suspend-to-disk.) The devices will reappear as if by magic
+ when the system wakes up, with no need to unmount USB
+ filesystems, rmmod host-controller drivers, or do anything
+ else.
+
+ WARNING: This option can be dangerous!
+
+ If a USB device is replaced by another of the same type while
+ the system is asleep, there's a good chance the kernel won't
+ detect the change. Likewise if the media in a USB storage
+ device is replaced. When this happens it's almost certain to
+ cause data corruption and maybe even crash your system.
+
+ If you are unsure, say N here.
+
config USB_OTG
bool
depends on USB && EXPERIMENTAL
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 2d4fd530e5e..cb69aa1e02e 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -1,4 +1,5 @@
#include <linux/usb.h>
+#include <linux/usb/ch9.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -49,7 +50,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
unsigned char *buffer0 = buffer;
struct usb_endpoint_descriptor *d;
struct usb_host_endpoint *endpoint;
- int n, i;
+ int n, i, j;
d = (struct usb_endpoint_descriptor *) buffer;
buffer += d->bLength;
@@ -84,6 +85,66 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
memcpy(&endpoint->desc, d, n);
INIT_LIST_HEAD(&endpoint->urb_list);
+ /* Fix up bInterval values outside the legal range. Use 32 ms if no
+ * proper value can be guessed. */
+ i = 0; /* i = min, j = max, n = default */
+ j = 255;
+ if (usb_endpoint_xfer_int(d)) {
+ i = 1;
+ switch (to_usb_device(ddev)->speed) {
+ case USB_SPEED_HIGH:
+ /* Many device manufacturers are using full-speed
+ * bInterval values in high-speed interrupt endpoint
+ * descriptors. Try to fix those and fall back to a
+ * 32 ms default value otherwise. */
+ n = fls(d->bInterval*8);
+ if (n == 0)
+ n = 9; /* 32 ms = 2^(9-1) uframes */
+ j = 16;
+ break;
+ default: /* USB_SPEED_FULL or _LOW */
+ /* For low-speed, 10 ms is the official minimum.
+ * But some "overclocked" devices might want faster
+ * polling so we'll allow it. */
+ n = 32;
+ break;
+ }
+ } else if (usb_endpoint_xfer_isoc(d)) {
+ i = 1;
+ j = 16;
+ switch (to_usb_device(ddev)->speed) {
+ case USB_SPEED_HIGH:
+ n = 9; /* 32 ms = 2^(9-1) uframes */
+ break;
+ default: /* USB_SPEED_FULL */
+ n = 6; /* 32 ms = 2^(6-1) frames */
+ break;
+ }
+ }
+ if (d->bInterval < i || d->bInterval > j) {
+ dev_warn(ddev, "config %d interface %d altsetting %d "
+ "endpoint 0x%X has an invalid bInterval %d, "
+ "changing to %d\n",
+ cfgno, inum, asnum,
+ d->bEndpointAddress, d->bInterval, n);
+ endpoint->desc.bInterval = n;
+ }
+
+ /* Some buggy low-speed devices have Bulk endpoints, which is
+ * explicitly forbidden by the USB spec. In an attempt to make
+ * them usable, we will try treating them as Interrupt endpoints.
+ */
+ if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
+ usb_endpoint_xfer_bulk(d)) {
+ dev_warn(ddev, "config %d interface %d altsetting %d "
+ "endpoint 0x%X is Bulk; changing to Interrupt\n",
+ cfgno, inum, asnum, d->bEndpointAddress);
+ endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
+ endpoint->desc.bInterval = 1;
+ if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8)
+ endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
+ }
+
/* Skip over any Class Specific or Vendor Specific descriptors;
* find the next endpoint or interface descriptor */
endpoint->extra = buffer;
@@ -234,6 +295,7 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
struct usb_descriptor_header *header;
int len, retval;
u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES];
+ unsigned iad_num = 0;
memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
if (config->desc.bDescriptorType != USB_DT_CONFIG ||
@@ -311,6 +373,20 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx,
++n;
}
+ } else if (header->bDescriptorType ==
+ USB_DT_INTERFACE_ASSOCIATION) {
+ if (iad_num == USB_MAXIADS) {
+ dev_warn(ddev, "found more Interface "
+ "Association Descriptors "
+ "than allocated for in "
+ "configuration %d\n", cfgno);
+ } else {
+ config->intf_assoc[iad_num] =
+ (struct usb_interface_assoc_descriptor
+ *)header;
+ iad_num++;
+ }
+
} else if (header->bDescriptorType == USB_DT_DEVICE ||
header->bDescriptorType == USB_DT_CONFIG)
dev_warn(ddev, "config %d contains an unexpected "
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 6753ca059ee..87c794d60aa 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -102,6 +102,10 @@ static const char *format_config =
/* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
"C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
+static const char *format_iad =
+/* A: FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */
+ "A: FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
+
static const char *format_iface =
/* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
"I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
@@ -146,6 +150,7 @@ static const struct class_info clas_info[] =
{USB_CLASS_STILL_IMAGE, "still"},
{USB_CLASS_CSCID, "scard"},
{USB_CLASS_CONTENT_SEC, "c-sec"},
+ {USB_CLASS_VIDEO, "video"},
{-1, "unk."} /* leave as last */
};
@@ -286,6 +291,21 @@ static char *usb_dump_interface(
return start;
}
+static char *usb_dump_iad_descriptor(char *start, char *end,
+ const struct usb_interface_assoc_descriptor *iad)
+{
+ if (start > end)
+ return start;
+ start += sprintf(start, format_iad,
+ iad->bFirstInterface,
+ iad->bInterfaceCount,
+ iad->bFunctionClass,
+ class_decode(iad->bFunctionClass),
+ iad->bFunctionSubClass,
+ iad->bFunctionProtocol);
+ return start;
+}
+
/* TBD:
* 0. TBDs
* 1. marking active interface altsettings (code lists all, but should mark
@@ -322,6 +342,12 @@ static char *usb_dump_config (
if (!config) /* getting these some in 2.3.7; none in 2.3.6 */
return start + sprintf(start, "(null Cfg. desc.)\n");
start = usb_dump_config_descriptor(start, end, &config->desc, active);
+ for (i = 0; i < USB_MAXIADS; i++) {
+ if (config->intf_assoc[i] == NULL)
+ break;
+ start = usb_dump_iad_descriptor(start, end,
+ config->intf_assoc[i]);
+ }
for (i = 0; i < config->desc.bNumInterfaces; i++) {
intfc = config->intf_cache[i];
interface = config->interface[i];
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 2619986e530..73c49362cd4 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -24,10 +24,19 @@
#include <linux/device.h>
#include <linux/usb.h>
+#include <linux/usb/quirks.h>
#include <linux/workqueue.h>
#include "hcd.h"
#include "usb.h"
+#define VERBOSE_DEBUG 0
+
+#if VERBOSE_DEBUG
+#define dev_vdbg dev_dbg
+#else
+#define dev_vdbg(dev, fmt, args...) do { } while (0)
+#endif
+
#ifdef CONFIG_HOTPLUG
/*
@@ -802,18 +811,17 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
udev->state == USB_STATE_SUSPENDED)
goto done;
- /* For devices that don't have a driver, we do a standard suspend. */
- if (udev->dev.driver == NULL) {
+ /* For devices that don't have a driver, we do a generic suspend. */
+ if (udev->dev.driver)
+ udriver = to_usb_device_driver(udev->dev.driver);
+ else {
udev->do_remote_wakeup = 0;
- status = usb_port_suspend(udev);
- goto done;
+ udriver = &usb_generic_driver;
}
-
- udriver = to_usb_device_driver(udev->dev.driver);
status = udriver->suspend(udev, msg);
-done:
- // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ done:
+ dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
if (status == 0)
udev->dev.power.power_state.event = msg.event;
return status;
@@ -825,8 +833,9 @@ static int usb_resume_device(struct usb_device *udev)
struct usb_device_driver *udriver;
int status = 0;
- if (udev->state == USB_STATE_NOTATTACHED ||
- udev->state != USB_STATE_SUSPENDED)
+ if (udev->state == USB_STATE_NOTATTACHED)
+ goto done;
+ if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume)
goto done;
/* Can't resume it if it doesn't have a driver. */
@@ -835,11 +844,14 @@ static int usb_resume_device(struct usb_device *udev)
goto done;
}
+ if (udev->quirks & USB_QUIRK_RESET_RESUME)
+ udev->reset_resume = 1;
+
udriver = to_usb_device_driver(udev->dev.driver);
status = udriver->resume(udev);
-done:
- // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ done:
+ dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
if (status == 0) {
udev->autoresume_disabled = 0;
udev->dev.power.power_state.event = PM_EVENT_ON;
@@ -877,15 +889,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
mark_quiesced(intf);
}
-done:
- // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
- if (status == 0)
- intf->dev.power.power_state.event = msg.event;
+ done:
+ dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
return status;
}
/* Caller has locked intf's usb_device's pm_mutex */
-static int usb_resume_interface(struct usb_interface *intf)
+static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
{
struct usb_driver *driver;
int status = 0;
@@ -905,23 +915,37 @@ static int usb_resume_interface(struct usb_interface *intf)
}
driver = to_usb_driver(intf->dev.driver);
- if (driver->resume) {
- status = driver->resume(intf);
- if (status)
- dev_err(&intf->dev, "%s error %d\n",
- "resume", status);
- else
- mark_active(intf);
+ if (reset_resume) {
+ if (driver->reset_resume) {
+ status = driver->reset_resume(intf);
+ if (status)
+ dev_err(&intf->dev, "%s error %d\n",
+ "reset_resume", status);
+ } else {
+ // status = -EOPNOTSUPP;
+ dev_warn(&intf->dev, "no %s for driver %s?\n",
+ "reset_resume", driver->name);
+ }
} else {
- dev_warn(&intf->dev, "no resume for driver %s?\n",
- driver->name);
- mark_active(intf);
+ if (driver->resume) {
+ status = driver->resume(intf);
+ if (status)
+ dev_err(&intf->dev, "%s error %d\n",
+ "resume", status);
+ } else {
+ // status = -EOPNOTSUPP;
+ dev_warn(&intf->dev, "no %s for driver %s?\n",
+ "resume", driver->name);
+ }
}
done:
- // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+ dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
if (status == 0)
- intf->dev.power.power_state.event = PM_EVENT_ON;
+ mark_active(intf);
+
+ /* FIXME: Unbind the driver and reprobe if the resume failed
+ * (not possible if auto_pm is set) */
return status;
}
@@ -958,6 +982,18 @@ static int autosuspend_check(struct usb_device *udev)
"for autosuspend\n");
return -EOPNOTSUPP;
}
+
+ /* Don't allow autosuspend if the device will need
+ * a reset-resume and any of its interface drivers
+ * doesn't include support.
+ */
+ if (udev->quirks & USB_QUIRK_RESET_RESUME) {
+ struct usb_driver *driver;
+
+ driver = to_usb_driver(intf->dev.driver);
+ if (!driver->reset_resume)
+ return -EOPNOTSUPP;
+ }
}
}
@@ -974,7 +1010,7 @@ static int autosuspend_check(struct usb_device *udev)
* or for the past.
*/
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
- suspend_time - jiffies);
+ round_jiffies_relative(suspend_time - jiffies));
}
return -EAGAIN;
}
@@ -1054,14 +1090,21 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
break;
}
}
- if (status == 0)
+ if (status == 0) {
+
+ /* Non-root devices don't need to do anything for FREEZE
+ * or PRETHAW. */
+ if (udev->parent && (msg.event == PM_EVENT_FREEZE ||
+ msg.event == PM_EVENT_PRETHAW))
+ goto done;
status = usb_suspend_device(udev, msg);
+ }
/* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) {
while (--i >= 0) {
intf = udev->actconfig->interface[i];
- usb_resume_interface(intf);
+ usb_resume_interface(intf, 0);
}
/* Try another autosuspend when the interfaces aren't busy */
@@ -1076,7 +1119,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
}
done:
- // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
return status;
}
@@ -1131,7 +1174,8 @@ static int usb_resume_both(struct usb_device *udev)
status = usb_autoresume_device(parent);
if (status == 0) {
status = usb_resume_device(udev);
- if (status) {
+ if (status || udev->state ==
+ USB_STATE_NOTATTACHED) {
usb_autosuspend_device(parent);
/* It's possible usb_resume_device()
@@ -1152,28 +1196,25 @@ static int usb_resume_both(struct usb_device *udev)
/* We can't progagate beyond the USB subsystem,
* so if a root hub's controller is suspended
* then we're stuck. */
- if (udev->dev.parent->power.power_state.event !=
- PM_EVENT_ON)
- status = -EHOSTUNREACH;
- else
- status = usb_resume_device(udev);
+ status = usb_resume_device(udev);
}
} else {
- /* Needed only for setting udev->dev.power.power_state.event
- * and for possible debugging message. */
+ /* Needed for setting udev->dev.power.power_state.event,
+ * for possible debugging message, and for reset_resume. */
status = usb_resume_device(udev);
}
if (status == 0 && udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
- usb_resume_interface(intf);
+ usb_resume_interface(intf, udev->reset_resume);
}
}
done:
- // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+ udev->reset_resume = 0;
return status;
}
@@ -1240,8 +1281,8 @@ void usb_autosuspend_device(struct usb_device *udev)
int status;
status = usb_autopm_do_device(udev, -1);
- // dev_dbg(&udev->dev, "%s: cnt %d\n",
- // __FUNCTION__, udev->pm_usage_cnt);
+ dev_vdbg(&udev->dev, "%s: cnt %d\n",
+ __FUNCTION__, udev->pm_usage_cnt);
}
/**
@@ -1260,8 +1301,8 @@ void usb_autosuspend_device(struct usb_device *udev)
void usb_try_autosuspend_device(struct usb_device *udev)
{
usb_autopm_do_device(udev, 0);
- // dev_dbg(&udev->dev, "%s: cnt %d\n",
- // __FUNCTION__, udev->pm_usage_cnt);
+ dev_vdbg(&udev->dev, "%s: cnt %d\n",
+ __FUNCTION__, udev->pm_usage_cnt);
}
/**
@@ -1288,8 +1329,8 @@ int usb_autoresume_device(struct usb_device *udev)
int status;
status = usb_autopm_do_device(udev, 1);
- // dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
- // __FUNCTION__, status, udev->pm_usage_cnt);
+ dev_vdbg(&udev->dev, "%s: status %d cnt %d\n",
+ __FUNCTION__, status, udev->pm_usage_cnt);
return status;
}
@@ -1361,8 +1402,8 @@ void usb_autopm_put_interface(struct usb_interface *intf)
int status;
status = usb_autopm_do_interface(intf, -1);
- // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
- // __FUNCTION__, status, intf->pm_usage_cnt);
+ dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+ __FUNCTION__, status, intf->pm_usage_cnt);
}
EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
@@ -1405,8 +1446,8 @@ int usb_autopm_get_interface(struct usb_interface *intf)
int status;
status = usb_autopm_do_interface(intf, 1);
- // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
- // __FUNCTION__, status, intf->pm_usage_cnt);
+ dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+ __FUNCTION__, status, intf->pm_usage_cnt);
return status;
}
EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
@@ -1427,8 +1468,8 @@ int usb_autopm_set_interface(struct usb_interface *intf)
int status;
status = usb_autopm_do_interface(intf, 0);
- // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
- // __FUNCTION__, status, intf->pm_usage_cnt);
+ dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
+ __FUNCTION__, status, intf->pm_usage_cnt);
return status;
}
EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
@@ -1508,8 +1549,15 @@ static int usb_resume(struct device *dev)
if (!is_usb_device(dev)) /* Ignore PM for interfaces */
return 0;
udev = to_usb_device(dev);
- if (udev->autoresume_disabled)
- return -EPERM;
+
+ /* If autoresume is disabled then we also want to prevent resume
+ * during system wakeup. However, a "persistent-device" reset-resume
+ * after power loss counts as a wakeup event. So allow a
+ * reset-resume to occur if remote wakeup is enabled. */
+ if (udev->autoresume_disabled) {
+ if (!(udev->reset_resume && udev->do_remote_wakeup))
+ return -EPERM;
+ }
return usb_external_resume_device(udev);
}
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 01c857ac27a..5d860bc9b42 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -16,15 +16,15 @@
*/
#include <linux/module.h>
-#include <linux/spinlock.h>
#include <linux/errno.h>
+#include <linux/rwsem.h>
#include <linux/usb.h>
#include "usb.h"
#define MAX_USB_MINORS 256
static const struct file_operations *usb_minors[MAX_USB_MINORS];
-static DEFINE_SPINLOCK(minor_lock);
+static DECLARE_RWSEM(minor_rwsem);
static int usb_open(struct inode * inode, struct file * file)
{
@@ -33,14 +33,11 @@ static int usb_open(struct inode * inode, struct file * file)
int err = -ENODEV;
const struct file_operations *old_fops, *new_fops = NULL;
- spin_lock (&minor_lock);
+ down_read(&minor_rwsem);
c = usb_minors[minor];
- if (!c || !(new_fops = fops_get(c))) {
- spin_unlock(&minor_lock);
- return err;
- }
- spin_unlock(&minor_lock);
+ if (!c || !(new_fops = fops_get(c)))
+ goto done;
old_fops = file->f_op;
file->f_op = new_fops;
@@ -52,6 +49,8 @@ static int usb_open(struct inode * inode, struct file * file)
file->f_op = fops_get(old_fops);
}
fops_put(old_fops);
+ done:
+ up_read(&minor_rwsem);
return err;
}
@@ -166,7 +165,7 @@ int usb_register_dev(struct usb_interface *intf,
if (class_driver->fops == NULL)
goto exit;
- spin_lock (&minor_lock);
+ down_write(&minor_rwsem);
for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {
if (usb_minors[minor])
continue;
@@ -176,7 +175,7 @@ int usb_register_dev(struct usb_interface *intf,
retval = 0;
break;
}
- spin_unlock (&minor_lock);
+ up_write(&minor_rwsem);
if (retval)
goto exit;
@@ -197,9 +196,9 @@ int usb_register_dev(struct usb_interface *intf,
intf->usb_dev = device_create(usb_class->class, &intf->dev,
MKDEV(USB_MAJOR, minor), "%s", temp);
if (IS_ERR(intf->usb_dev)) {
- spin_lock (&minor_lock);
+ down_write(&minor_rwsem);
usb_minors[intf->minor] = NULL;
- spin_unlock (&minor_lock);
+ up_write(&minor_rwsem);
retval = PTR_ERR(intf->usb_dev);
}
exit:
@@ -236,9 +235,9 @@ void usb_deregister_dev(struct usb_interface *intf,
dbg ("removing %d minor", intf->minor);
- spin_lock (&minor_lock);
+ down_write(&minor_rwsem);
usb_minors[intf->minor] = NULL;
- spin_unlock (&minor_lock);
+ up_write(&minor_rwsem);
snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
@@ -247,5 +246,3 @@ void usb_deregister_dev(struct usb_interface *intf,
destroy_usb_class();
}
EXPORT_SYMBOL(usb_deregister_dev);
-
-
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 9bbcb20e2d9..b2fc2b11525 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -19,6 +19,7 @@
#include <linux/usb.h>
#include "usb.h"
+#include "hcd.h"
static inline const char *plural(int n)
{
@@ -193,16 +194,34 @@ static void generic_disconnect(struct usb_device *udev)
static int generic_suspend(struct usb_device *udev, pm_message_t msg)
{
- /* USB devices enter SUSPEND state through their hubs, but can be
- * marked for FREEZE as soon as their children are already idled.
- * But those semantics are useless, so we equate the two (sigh).
+ int rc;
+
+ /* Normal USB devices suspend through their upstream port.
+ * Root hubs don't have upstream ports to suspend,
+ * so we have to shut down their downstream HC-to-USB
+ * interfaces manually by doing a bus (or "global") suspend.
*/
- return usb_port_suspend(udev);
+ if (!udev->parent)
+ rc = hcd_bus_suspend(udev);
+ else
+ rc = usb_port_suspend(udev);
+ return rc;
}
static int generic_resume(struct usb_device *udev)
{
- return usb_port_resume(udev);
+ int rc;
+
+ /* Normal USB devices resume/reset through their upstream port.
+ * Root hubs don't have upstream ports to resume or reset,
+ * so we have to start up their downstream HC-to-USB
+ * interfaces manually by doing a bus (or "global") resume.
+ */
+ if (!udev->parent)
+ rc = hcd_bus_resume(udev);
+ else
+ rc = usb_port_resume(udev);
+ return rc;
}
#endif /* CONFIG_PM */
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index edf4300a3f7..5cf6d5f9acb 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -207,7 +207,8 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
* We must ignore the FREEZE vs SUSPEND distinction here, because
* otherwise the swsusp will save (and restore) garbage state.
*/
- if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON)
+ if (!(hcd->state == HC_STATE_SUSPENDED ||
+ hcd->state == HC_STATE_HALT))
return -EBUSY;
if (hcd->driver->suspend) {
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 8969e42434b..963520fbef9 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -582,10 +582,12 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
}
/* The USB 2.0 spec says 256 ms. This is close enough and won't
- * exceed that limit if HZ is 100. */
+ * exceed that limit if HZ is 100. The math is more clunky than
+ * maybe expected, this is to make sure that all timers for USB devices
+ * fire at the same time to give the CPU a break inbetween */
if (hcd->uses_new_polling ? hcd->poll_rh :
(length == 0 && hcd->status_urb != NULL))
- mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250));
+ mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4));
}
EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status);
@@ -614,8 +616,8 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb)
urb->hcpriv = hcd; /* indicate it's queued */
if (!hcd->uses_new_polling)
- mod_timer (&hcd->rh_timer, jiffies +
- msecs_to_jiffies(250));
+ mod_timer (&hcd->rh_timer,
+ (jiffies/(HZ/4) + 1) * (HZ/4));
/* If a status change has already occurred, report it ASAP */
else if (hcd->poll_pending)
@@ -901,17 +903,32 @@ EXPORT_SYMBOL (usb_calc_bus_time);
/*-------------------------------------------------------------------------*/
-static void urb_unlink (struct urb *urb)
+static void urb_unlink(struct usb_hcd *hcd, struct urb *urb)
{
unsigned long flags;
+ int at_root_hub = (urb->dev == hcd->self.root_hub);
/* clear all state linking urb to this dev (and hcd) */
-
spin_lock_irqsave (&hcd_data_lock, flags);
list_del_init (&urb->urb_list);
spin_unlock_irqrestore (&hcd_data_lock, flags);
-}
+ if (hcd->self.uses_dma && !at_root_hub) {
+ if (usb_pipecontrol (urb->pipe)
+ && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+ dma_unmap_single (hcd->self.controller, urb->setup_dma,
+ sizeof (struct usb_ctrlrequest),
+ DMA_TO_DEVICE);
+ if (urb->transfer_buffer_length != 0
+ && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+ dma_unmap_single (hcd->self.controller,
+ urb->transfer_dma,
+ urb->transfer_buffer_length,
+ usb_pipein (urb->pipe)
+ ? DMA_FROM_DEVICE
+ : DMA_TO_DEVICE);
+ }
+}
/* may be called in any context with a valid urb->dev usecount
* caller surrenders "ownership" of urb
@@ -948,19 +965,9 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
else switch (hcd->state) {
case HC_STATE_RUNNING:
case HC_STATE_RESUMING:
-doit:
list_add_tail (&urb->urb_list, &ep->urb_list);
status = 0;
break;
- case HC_STATE_SUSPENDED:
- /* HC upstream links (register access, wakeup signaling) can work
- * even when the downstream links (and DMA etc) are quiesced; let
- * usbcore talk to the root hub.
- */
- if (hcd->self.controller->power.power_state.event == PM_EVENT_ON
- && urb->dev->parent == NULL)
- goto doit;
- /* FALL THROUGH */
default:
status = -ESHUTDOWN;
break;
@@ -1014,7 +1021,7 @@ doit:
status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
done:
if (unlikely (status)) {
- urb_unlink (urb);
+ urb_unlink(hcd, urb);
atomic_dec (&urb->use_count);
if (urb->reject)
wake_up (&usb_kill_urb_queue);
@@ -1255,42 +1262,59 @@ rescan:
#ifdef CONFIG_PM
-int hcd_bus_suspend (struct usb_bus *bus)
+int hcd_bus_suspend(struct usb_device *rhdev)
{
- struct usb_hcd *hcd;
- int status;
+ struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);
+ int status;
+ int old_state = hcd->state;
- hcd = container_of (bus, struct usb_hcd, self);
- if (!hcd->driver->bus_suspend)
- return -ENOENT;
- hcd->state = HC_STATE_QUIESCING;
- status = hcd->driver->bus_suspend (hcd);
- if (status == 0)
+ dev_dbg(&rhdev->dev, "bus %s%s\n",
+ rhdev->auto_pm ? "auto-" : "", "suspend");
+ if (!hcd->driver->bus_suspend) {
+ status = -ENOENT;
+ } else {
+ hcd->state = HC_STATE_QUIESCING;
+ status = hcd->driver->bus_suspend(hcd);
+ }
+ if (status == 0) {
+ usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;
- else
- dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+ } else {
+ hcd->state = old_state;
+ dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
"suspend", status);
+ }
return status;
}
-int hcd_bus_resume (struct usb_bus *bus)
+int hcd_bus_resume(struct usb_device *rhdev)
{
- struct usb_hcd *hcd;
- int status;
+ struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self);
+ int status;
+ int old_state = hcd->state;
- hcd = container_of (bus, struct usb_hcd, self);
+ dev_dbg(&rhdev->dev, "usb %s%s\n",
+ rhdev->auto_pm ? "auto-" : "", "resume");
if (!hcd->driver->bus_resume)
return -ENOENT;
if (hcd->state == HC_STATE_RUNNING)
return 0;
+
hcd->state = HC_STATE_RESUMING;
- status = hcd->driver->bus_resume (hcd);
- if (status == 0)
+ status = hcd->driver->bus_resume(hcd);
+ if (status == 0) {
+ /* TRSMRCY = 10 msec */
+ msleep(10);
+ usb_set_device_state(rhdev, rhdev->actconfig
+ ? USB_STATE_CONFIGURED
+ : USB_STATE_ADDRESS);
hcd->state = HC_STATE_RUNNING;
- else {
- dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n",
+ } else {
+ hcd->state = old_state;
+ dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
"resume", status);
- usb_hc_died(hcd);
+ if (status != -ESHUTDOWN)
+ usb_hc_died(hcd);
}
return status;
}
@@ -1384,30 +1408,10 @@ EXPORT_SYMBOL (usb_bus_start_enum);
*/
void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb)
{
- int at_root_hub;
-
- at_root_hub = (urb->dev == hcd->self.root_hub);
- urb_unlink (urb);
-
- /* lower level hcd code should use *_dma exclusively if the
- * host controller does DMA */
- if (hcd->self.uses_dma && !at_root_hub) {
- if (usb_pipecontrol (urb->pipe)
- && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
- dma_unmap_single (hcd->self.controller, urb->setup_dma,
- sizeof (struct usb_ctrlrequest),
- DMA_TO_DEVICE);
- if (urb->transfer_buffer_length != 0
- && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
- dma_unmap_single (hcd->self.controller,
- urb->transfer_dma,
- urb->transfer_buffer_length,
- usb_pipein (urb->pipe)
- ? DMA_FROM_DEVICE
- : DMA_TO_DEVICE);
- }
-
+ urb_unlink(hcd, urb);
usbmon_urb_complete (&hcd->self, urb);
+ usb_unanchor_urb(urb);
+
/* pass ownership to the completion handler */
urb->complete (urb);
atomic_dec (&urb->use_count);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index ef50fa494e4..b5ebb73c233 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -364,23 +364,13 @@ extern int usb_find_interface_driver (struct usb_device *dev,
#ifdef CONFIG_PM
extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
extern void usb_root_hub_lost_power (struct usb_device *rhdev);
-extern int hcd_bus_suspend (struct usb_bus *bus);
-extern int hcd_bus_resume (struct usb_bus *bus);
+extern int hcd_bus_suspend(struct usb_device *rhdev);
+extern int hcd_bus_resume(struct usb_device *rhdev);
#else
static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
{
return;
}
-
-static inline int hcd_bus_suspend(struct usb_bus *bus)
-{
- return 0;
-}
-
-static inline int hcd_bus_resume (struct usb_bus *bus)
-{
- return 0;
-}
#endif /* CONFIG_PM */
/*
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 24f10a19dbd..50e79010401 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -31,9 +31,16 @@
#include "hcd.h"
#include "hub.h"
+#ifdef CONFIG_USB_PERSIST
+#define USB_PERSIST 1
+#else
+#define USB_PERSIST 0
+#endif
+
struct usb_hub {
struct device *intfdev; /* the "interface" device */
struct usb_device *hdev;
+ struct kref kref;
struct urb *urb; /* for interrupt polling pipe */
/* buffer for urb ... with extra space in case of babble */
@@ -66,6 +73,7 @@ struct usb_hub {
unsigned limited_power:1;
unsigned quiescing:1;
unsigned activating:1;
+ unsigned disconnected:1;
unsigned has_indicators:1;
u8 indicator[USB_MAXCHILDREN];
@@ -321,7 +329,7 @@ static void kick_khubd(struct usb_hub *hub)
to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
spin_lock_irqsave(&hub_event_lock, flags);
- if (list_empty(&hub->event_list)) {
+ if (!hub->disconnected & list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list);
wake_up(&khubd_wait);
}
@@ -330,6 +338,7 @@ static void kick_khubd(struct usb_hub *hub)
void usb_kick_khubd(struct usb_device *hdev)
{
+ /* FIXME: What if hdev isn't bound to the hub driver? */
kick_khubd(hdev_to_hub(hdev));
}
@@ -400,9 +409,10 @@ static void hub_tt_kevent (struct work_struct *work)
struct usb_hub *hub =
container_of(work, struct usb_hub, tt.kevent);
unsigned long flags;
+ int limit = 100;
spin_lock_irqsave (&hub->tt.lock, flags);
- while (!list_empty (&hub->tt.clear_list)) {
+ while (--limit && !list_empty (&hub->tt.clear_list)) {
struct list_head *temp;
struct usb_tt_clear *clear;
struct usb_device *hdev = hub->hdev;
@@ -550,48 +560,68 @@ static int hub_hub_status(struct usb_hub *hub,
static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
{
struct usb_device *hdev = hub->hdev;
- int ret;
+ int ret = 0;
- if (hdev->children[port1-1] && set_state) {
+ if (hdev->children[port1-1] && set_state)
usb_set_device_state(hdev->children[port1-1],
USB_STATE_NOTATTACHED);
- }
- ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+ if (!hub->error)
+ ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
if (ret)
dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
- port1, ret);
-
+ port1, ret);
return ret;
}
+/*
+ * Disable a port and mark a logical connnect-change event, so that some
+ * time later khubd will disconnect() any existing usb_device on the port
+ * and will re-enumerate if there actually is a device attached.
+ */
+static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
+{
+ dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
+ hub_port_disable(hub, port1, 1);
+
+ /* FIXME let caller ask to power down the port:
+ * - some devices won't enumerate without a VBUS power cycle
+ * - SRP saves power that way
+ * - ... new call, TBD ...
+ * That's easy if this hub can switch power per-port, and
+ * khubd reactivates the port later (timer, SRP, etc).
+ * Powerdown must be optional, because of reset/DFU.
+ */
+
+ set_bit(port1, hub->change_bits);
+ kick_khubd(hub);
+}
/* caller has locked the hub device */
-static void hub_pre_reset(struct usb_interface *intf)
+static int hub_pre_reset(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
struct usb_device *hdev = hub->hdev;
- int port1;
+ int i;
- for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
- if (hdev->children[port1 - 1]) {
- usb_disconnect(&hdev->children[port1 - 1]);
- if (hub->error == 0)
- hub_port_disable(hub, port1, 0);
- }
+ /* Disconnect all the children */
+ for (i = 0; i < hdev->maxchild; ++i) {
+ if (hdev->children[i])
+ usb_disconnect(&hdev->children[i]);
}
hub_quiesce(hub);
+ return 0;
}
/* caller has locked the hub device */
-static void hub_post_reset(struct usb_interface *intf)
+static int hub_post_reset(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
- hub_activate(hub);
hub_power_on(hub);
+ hub_activate(hub);
+ return 0;
}
-
static int hub_configure(struct usb_hub *hub,
struct usb_endpoint_descriptor *endpoint)
{
@@ -845,43 +875,42 @@ fail:
return ret;
}
+static void hub_release(struct kref *kref)
+{
+ struct usb_hub *hub = container_of(kref, struct usb_hub, kref);
+
+ usb_put_intf(to_usb_interface(hub->intfdev));
+ kfree(hub);
+}
+
static unsigned highspeed_hubs;
static void hub_disconnect(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata (intf);
- struct usb_device *hdev;
+
+ /* Take the hub off the event list and don't let it be added again */
+ spin_lock_irq(&hub_event_lock);
+ list_del_init(&hub->event_list);
+ hub->disconnected = 1;
+ spin_unlock_irq(&hub_event_lock);
/* Disconnect all children and quiesce the hub */
hub->error = 0;
hub_pre_reset(intf);
usb_set_intfdata (intf, NULL);
- hdev = hub->hdev;
- if (hdev->speed == USB_SPEED_HIGH)
+ if (hub->hdev->speed == USB_SPEED_HIGH)
highspeed_hubs--;
usb_free_urb(hub->urb);
- hub->urb = NULL;
-
- spin_lock_irq(&hub_event_lock);
- list_del_init(&hub->event_list);
- spin_unlock_irq(&hub_event_lock);
-
kfree(hub->descriptor);
- hub->descriptor = NULL;
-
kfree(hub->status);
- hub->status = NULL;
-
- if (hub->buffer) {
- usb_buffer_free(hdev, sizeof(*hub->buffer), hub->buffer,
- hub->buffer_dma);
- hub->buffer = NULL;
- }
+ usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer,
+ hub->buffer_dma);
- kfree(hub);
+ kref_put(&hub->kref, hub_release);
}
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -929,10 +958,12 @@ descriptor_error:
return -ENOMEM;
}
+ kref_init(&hub->kref);
INIT_LIST_HEAD(&hub->event_list);
hub->intfdev = &intf->dev;
hub->hdev = hdev;
INIT_DELAYED_WORK(&hub->leds, led_work);
+ usb_get_intf(intf);
usb_set_intfdata (intf, hub);
intf->needs_remote_wakeup = 1;
@@ -982,49 +1013,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
}
-/* grab device/port lock, returning index of that port (zero based).
- * protects the upstream link used by this device from concurrent
- * tree operations like suspend, resume, reset, and disconnect, which
- * apply to everything downstream of a given port.
- */
-static int locktree(struct usb_device *udev)
-{
- int t;
- struct usb_device *hdev;
-
- if (!udev)
- return -ENODEV;
-
- /* root hub is always the first lock in the series */
- hdev = udev->parent;
- if (!hdev) {
- usb_lock_device(udev);
- return 0;
- }
-
- /* on the path from root to us, lock everything from
- * top down, dropping parent locks when not needed
- */
- t = locktree(hdev);
- if (t < 0)
- return t;
-
- /* everything is fail-fast once disconnect
- * processing starts
- */
- if (udev->state == USB_STATE_NOTATTACHED) {
- usb_unlock_device(hdev);
- return -ENODEV;
- }
-
- /* when everyone grabs locks top->bottom,
- * non-overlapping work may be concurrent
- */
- usb_lock_device(udev);
- usb_unlock_device(hdev);
- return udev->portnum;
-}
-
static void recursively_mark_NOTATTACHED(struct usb_device *udev)
{
int i;
@@ -1089,46 +1077,6 @@ void usb_set_device_state(struct usb_device *udev,
spin_unlock_irqrestore(&device_state_lock, flags);
}
-
-#ifdef CONFIG_PM
-
-/**
- * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
- * @rhdev: struct usb_device for the root hub
- *
- * The USB host controller driver calls this function when its root hub
- * is resumed and Vbus power has been interrupted or the controller
- * has been reset. The routine marks all the children of the root hub
- * as NOTATTACHED and marks logical connect-change events on their ports.
- */
-void usb_root_hub_lost_power(struct usb_device *rhdev)
-{
- struct usb_hub *hub;
- int port1;
- unsigned long flags;
-
- dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
-
- /* Make sure no potential wakeup events get lost,
- * by forcing the root hub to be resumed.
- */
- rhdev->dev.power.prev_state.event = PM_EVENT_ON;
-
- spin_lock_irqsave(&device_state_lock, flags);
- hub = hdev_to_hub(rhdev);
- for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
- if (rhdev->children[port1 - 1]) {
- recursively_mark_NOTATTACHED(
- rhdev->children[port1 - 1]);
- set_bit(port1, hub->change_bits);
- }
- }
- spin_unlock_irqrestore(&device_state_lock, flags);
-}
-EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
-
-#endif /* CONFIG_PM */
-
static void choose_address(struct usb_device *udev)
{
int devnum;
@@ -1269,7 +1217,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
#ifdef CONFIG_USB_OTG
#include "otg_whitelist.h"
-static int __usb_port_suspend(struct usb_device *, int port1);
#endif
/**
@@ -1375,11 +1322,11 @@ int usb_new_device(struct usb_device *udev)
* (Includes HNP test device.)
*/
if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
- err = __usb_port_suspend(udev, udev->bus->otg_port);
+ err = usb_port_suspend(udev);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
}
- err = -ENODEV;
+ err = -ENOTSUPP;
goto fail;
}
#endif
@@ -1476,9 +1423,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
if (!(portstatus & USB_PORT_STAT_CONNECTION))
return -ENOTCONN;
- /* bomb out completely if something weird happened */
+ /* bomb out completely if the connection bounced */
if ((portchange & USB_PORT_STAT_C_CONNECTION))
- return -EINVAL;
+ return -ENOTCONN;
/* if we`ve finished resetting, then break out of the loop */
if (!(portstatus & USB_PORT_STAT_RESET) &&
@@ -1557,34 +1504,24 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
return status;
}
-/*
- * Disable a port and mark a logical connnect-change event, so that some
- * time later khubd will disconnect() any existing usb_device on the port
- * and will re-enumerate if there actually is a device attached.
- */
-static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
-{
- dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
- hub_port_disable(hub, port1, 1);
-
- /* FIXME let caller ask to power down the port:
- * - some devices won't enumerate without a VBUS power cycle
- * - SRP saves power that way
- * - ... new call, TBD ...
- * That's easy if this hub can switch power per-port, and
- * khubd reactivates the port later (timer, SRP, etc).
- * Powerdown must be optional, because of reset/DFU.
- */
-
- set_bit(port1, hub->change_bits);
- kick_khubd(hub);
-}
-
#ifdef CONFIG_PM
#ifdef CONFIG_USB_SUSPEND
/*
+ * usb_port_suspend - suspend a usb device's upstream port
+ * @udev: device that's no longer in active use, not a root hub
+ * Context: must be able to sleep; device not locked; pm locks held
+ *
+ * Suspends a USB device that isn't in active use, conserving power.
+ * Devices may wake out of a suspend, if anything important happens,
+ * using the remote wakeup mechanism. They may also be taken out of
+ * suspend by the host, using usb_port_resume(). It's also routine
+ * to disconnect devices while they are suspended.
+ *
+ * This only affects the USB hardware for a device; its interfaces
+ * (and, for hubs, child devices) must already have been suspended.
+ *
* Selective port suspend reduces power; most suspended devices draw
* less than 500 uA. It's also used in OTG, along with remote wakeup.
* All devices below the suspended port are also suspended.
@@ -1593,11 +1530,35 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
* also support "remote wakeup", where the device can activate the USB
* tree above them to deliver data, such as a keypress or packet. In
* some cases, this wakes the USB host.
+ *
+ * Suspending OTG devices may trigger HNP, if that's been enabled
+ * between a pair of dual-role devices. That will change roles, such
+ * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
+ *
+ * Devices on USB hub ports have only one "suspend" state, corresponding
+ * to ACPI D2, "may cause the device to lose some context".
+ * State transitions include:
+ *
+ * - suspend, resume ... when the VBUS power link stays live
+ * - suspend, disconnect ... VBUS lost
+ *
+ * Once VBUS drop breaks the circuit, the port it's using has to go through
+ * normal re-enumeration procedures, starting with enabling VBUS power.
+ * Other than re-initializing the hub (plug/unplug, except for root hubs),
+ * Linux (2.6) currently has NO mechanisms to initiate that: no khubd
+ * timer, no SRP, no requests through sysfs.
+ *
+ * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
+ * the root hub for their bus goes into global suspend ... so we don't
+ * (falsely) update the device power state to say it suspended.
+ *
+ * Returns 0 on success, else negative errno.
*/
-static int hub_port_suspend(struct usb_hub *hub, int port1,
- struct usb_device *udev)
+int usb_port_suspend(struct usb_device *udev)
{
- int status;
+ struct usb_hub *hub = hdev_to_hub(udev->parent);
+ int port1 = udev->portnum;
+ int status;
// dev_dbg(hub->intfdev, "suspend port %d\n", port1);
@@ -1614,17 +1575,15 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
NULL, 0,
USB_CTRL_SET_TIMEOUT);
if (status)
- dev_dbg(&udev->dev,
- "won't remote wakeup, status %d\n",
- status);
+ dev_dbg(&udev->dev, "won't remote wakeup, status %d\n",
+ status);
}
/* see 7.1.7.6 */
status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND);
if (status) {
- dev_dbg(hub->intfdev,
- "can't suspend port %d, status %d\n",
- port1, status);
+ dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
+ port1, status);
/* paranoia: "should not happen" */
(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
@@ -1642,85 +1601,24 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
}
/*
- * Devices on USB hub ports have only one "suspend" state, corresponding
- * to ACPI D2, "may cause the device to lose some context".
- * State transitions include:
- *
- * - suspend, resume ... when the VBUS power link stays live
- * - suspend, disconnect ... VBUS lost
- *
- * Once VBUS drop breaks the circuit, the port it's using has to go through
- * normal re-enumeration procedures, starting with enabling VBUS power.
- * Other than re-initializing the hub (plug/unplug, except for root hubs),
- * Linux (2.6) currently has NO mechanisms to initiate that: no khubd
- * timer, no SRP, no requests through sysfs.
- *
- * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
- * the root hub for their bus goes into global suspend ... so we don't
- * (falsely) update the device power state to say it suspended.
- */
-static int __usb_port_suspend (struct usb_device *udev, int port1)
-{
- int status = 0;
-
- /* caller owns the udev device lock */
- if (port1 < 0)
- return port1;
-
- /* we change the device's upstream USB link,
- * but root hubs have no upstream USB link.
- */
- if (udev->parent)
- status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
- udev);
- else {
- dev_dbg(&udev->dev, "usb %ssuspend\n",
- udev->auto_pm ? "auto-" : "");
- usb_set_device_state(udev, USB_STATE_SUSPENDED);
- }
- return status;
-}
-
-/*
- * usb_port_suspend - suspend a usb device's upstream port
- * @udev: device that's no longer in active use
- * Context: must be able to sleep; device not locked; pm locks held
- *
- * Suspends a USB device that isn't in active use, conserving power.
- * Devices may wake out of a suspend, if anything important happens,
- * using the remote wakeup mechanism. They may also be taken out of
- * suspend by the host, using usb_port_resume(). It's also routine
- * to disconnect devices while they are suspended.
- *
- * This only affects the USB hardware for a device; its interfaces
- * (and, for hubs, child devices) must already have been suspended.
- *
- * Suspending OTG devices may trigger HNP, if that's been enabled
- * between a pair of dual-role devices. That will change roles, such
- * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
- *
- * Returns 0 on success, else negative errno.
- */
-int usb_port_suspend(struct usb_device *udev)
-{
- return __usb_port_suspend(udev, udev->portnum);
-}
-
-/*
* If the USB "suspend" state is in use (rather than "global suspend"),
* many devices will be individually taken out of suspend state using
- * special" resume" signaling. These routines kick in shortly after
+ * special "resume" signaling. This routine kicks in shortly after
* hardware resume signaling is finished, either because of selective
* resume (by host) or remote wakeup (by device) ... now see what changed
* in the tree that's rooted at this device.
+ *
+ * If @udev->reset_resume is set then the device is reset before the
+ * status check is done.
*/
static int finish_port_resume(struct usb_device *udev)
{
- int status;
+ int status = 0;
u16 devstatus;
/* caller owns the udev device lock */
- dev_dbg(&udev->dev, "finish resume\n");
+ dev_dbg(&udev->dev, "finish %sresume\n",
+ udev->reset_resume ? "reset-" : "");
/* usb ch9 identifies four variants of SUSPENDED, based on what
* state the device resumes to. Linux currently won't see the
@@ -1731,22 +1629,30 @@ static int finish_port_resume(struct usb_device *udev)
? USB_STATE_CONFIGURED
: USB_STATE_ADDRESS);
+ /* 10.5.4.5 says not to reset a suspended port if the attached
+ * device is enabled for remote wakeup. Hence the reset
+ * operation is carried out here, after the port has been
+ * resumed.
+ */
+ if (udev->reset_resume)
+ status = usb_reset_device(udev);
+
/* 10.5.4.5 says be sure devices in the tree are still there.
* For now let's assume the device didn't go crazy on resume,
* and device drivers will know about any resume quirks.
*/
- status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
- if (status >= 0)
- status = (status == 2 ? 0 : -ENODEV);
+ if (status == 0) {
+ status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+ if (status >= 0)
+ status = (status == 2 ? 0 : -ENODEV);
+ }
- if (status)
- dev_dbg(&udev->dev,
- "gone after usb resume? status %d\n",
- status);
- else if (udev->actconfig) {
+ if (status) {
+ dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
+ status);
+ } else if (udev->actconfig) {
le16_to_cpus(&devstatus);
- if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
- && udev->parent) {
+ if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
status = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
USB_REQ_CLEAR_FEATURE,
@@ -1759,19 +1665,52 @@ static int finish_port_resume(struct usb_device *udev)
"wakeup, status %d\n", status);
}
status = 0;
-
- } else if (udev->devnum <= 0) {
- dev_dbg(&udev->dev, "bogus resume!\n");
- status = -EINVAL;
}
return status;
}
-static int
-hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+/*
+ * usb_port_resume - re-activate a suspended usb device's upstream port
+ * @udev: device to re-activate, not a root hub
+ * Context: must be able to sleep; device not locked; pm locks held
+ *
+ * This will re-activate the suspended device, increasing power usage
+ * while letting drivers communicate again with its endpoints.
+ * USB resume explicitly guarantees that the power session between
+ * the host and the device is the same as it was when the device
+ * suspended.
+ *
+ * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this
+ * routine won't check that the port is still enabled. Furthermore,
+ * if @udev->reset_resume is set then finish_port_resume() above will
+ * reset @udev. The end result is that a broken power session can be
+ * recovered and @udev will appear to persist across a loss of VBUS power.
+ *
+ * For example, if a host controller doesn't maintain VBUS suspend current
+ * during a system sleep or is reset when the system wakes up, all the USB
+ * power sessions below it will be broken. This is especially troublesome
+ * for mass-storage devices containing mounted filesystems, since the
+ * device will appear to have disconnected and all the memory mappings
+ * to it will be lost. Using the USB_PERSIST facility, the device can be
+ * made to appear as if it had not disconnected.
+ *
+ * This facility is inherently dangerous. Although usb_reset_device()
+ * makes every effort to insure that the same device is present after the
+ * reset as before, it cannot provide a 100% guarantee. Furthermore it's
+ * quite possible for a device to remain unaltered but its media to be
+ * changed. If the user replaces a flash memory card while the system is
+ * asleep, he will have only himself to blame when the filesystem on the
+ * new card is corrupted and the system crashes.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_port_resume(struct usb_device *udev)
{
- int status;
- u16 portchange, portstatus;
+ struct usb_hub *hub = hdev_to_hub(udev->parent);
+ int port1 = udev->portnum;
+ int status;
+ u16 portchange, portstatus;
+ unsigned mask_flags, want_flags;
/* Skip the initial Clear-Suspend step for a remote wakeup */
status = hub_port_status(hub, port1, &portstatus, &portchange);
@@ -1786,30 +1725,31 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
status = clear_port_feature(hub->hdev,
port1, USB_PORT_FEAT_SUSPEND);
if (status) {
- dev_dbg(hub->intfdev,
- "can't resume port %d, status %d\n",
- port1, status);
+ dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
+ port1, status);
} else {
/* drive resume for at least 20 msec */
- if (udev)
- dev_dbg(&udev->dev, "usb %sresume\n",
- udev->auto_pm ? "auto-" : "");
+ dev_dbg(&udev->dev, "usb %sresume\n",
+ udev->auto_pm ? "auto-" : "");
msleep(25);
-#define LIVE_FLAGS ( USB_PORT_STAT_POWER \
- | USB_PORT_STAT_ENABLE \
- | USB_PORT_STAT_CONNECTION)
-
/* Virtual root hubs can trigger on GET_PORT_STATUS to
* stop resume signaling. Then finish the resume
* sequence.
*/
status = hub_port_status(hub, port1, &portstatus, &portchange);
-SuspendCleared:
- if (status < 0
- || (portstatus & LIVE_FLAGS) != LIVE_FLAGS
- || (portstatus & USB_PORT_STAT_SUSPEND) != 0
- ) {
+
+ SuspendCleared:
+ if (USB_PERSIST && udev->reset_resume)
+ want_flags = USB_PORT_STAT_POWER
+ | USB_PORT_STAT_CONNECTION;
+ else
+ want_flags = USB_PORT_STAT_POWER
+ | USB_PORT_STAT_CONNECTION
+ | USB_PORT_STAT_ENABLE;
+ mask_flags = want_flags | USB_PORT_STAT_SUSPEND;
+
+ if (status < 0 || (portstatus & mask_flags) != want_flags) {
dev_dbg(hub->intfdev,
"port %d status %04x.%04x after resume, %d\n",
port1, portchange, portstatus, status);
@@ -1821,51 +1761,19 @@ SuspendCleared:
USB_PORT_FEAT_C_SUSPEND);
/* TRSMRCY = 10 msec */
msleep(10);
- if (udev)
- status = finish_port_resume(udev);
}
}
- if (status < 0)
- hub_port_logical_disconnect(hub, port1);
clear_bit(port1, hub->busy_bits);
if (!hub->hdev->parent && !hub->busy_bits[0])
usb_enable_root_hub_irq(hub->hdev->bus);
- return status;
-}
-
-/*
- * usb_port_resume - re-activate a suspended usb device's upstream port
- * @udev: device to re-activate
- * Context: must be able to sleep; device not locked; pm locks held
- *
- * This will re-activate the suspended device, increasing power usage
- * while letting drivers communicate again with its endpoints.
- * USB resume explicitly guarantees that the power session between
- * the host and the device is the same as it was when the device
- * suspended.
- *
- * Returns 0 on success, else negative errno.
- */
-int usb_port_resume(struct usb_device *udev)
-{
- int status;
-
- /* we change the device's upstream USB link,
- * but root hubs have no upstream USB link.
- */
- if (udev->parent) {
- // NOTE this fails if parent is also suspended...
- status = hub_port_resume(hdev_to_hub(udev->parent),
- udev->portnum, udev);
- } else {
- dev_dbg(&udev->dev, "usb %sresume\n",
- udev->auto_pm ? "auto-" : "");
+ if (status == 0)
status = finish_port_resume(udev);
- }
- if (status < 0)
+ if (status < 0) {
dev_dbg(&udev->dev, "can't resume, status %d\n", status);
+ hub_port_logical_disconnect(hub, port1);
+ }
return status;
}
@@ -1892,21 +1800,16 @@ int usb_port_suspend(struct usb_device *udev)
return 0;
}
-static inline int
-finish_port_resume(struct usb_device *udev)
-{
- return 0;
-}
-
-static inline int
-hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
-{
- return 0;
-}
-
int usb_port_resume(struct usb_device *udev)
{
- return 0;
+ int status = 0;
+
+ /* However we may need to do a reset-resume */
+ if (udev->reset_resume) {
+ dev_dbg(&udev->dev, "reset-resume\n");
+ status = usb_reset_device(udev);
+ }
+ return status;
}
static inline int remote_wakeup(struct usb_device *udev)
@@ -1921,7 +1824,6 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
unsigned port1;
- int status = 0;
/* fail if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
@@ -1947,49 +1849,75 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
/* stop khubd and related activity */
hub_quiesce(hub);
-
- /* "global suspend" of the downstream HC-to-USB interface */
- if (!hdev->parent) {
- status = hcd_bus_suspend(hdev->bus);
- if (status != 0) {
- dev_dbg(&hdev->dev, "'global' suspend %d\n", status);
- hub_activate(hub);
- }
- }
- return status;
+ return 0;
}
static int hub_resume(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata (intf);
- struct usb_device *hdev = hub->hdev;
- int status;
dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
- /* "global resume" of the downstream HC-to-USB interface */
- if (!hdev->parent) {
- struct usb_bus *bus = hdev->bus;
- if (bus) {
- status = hcd_bus_resume (bus);
- if (status) {
- dev_dbg(&intf->dev, "'global' resume %d\n",
- status);
- return status;
+ /* tell khubd to look for changes on this hub */
+ hub_activate(hub);
+ return 0;
+}
+
+static int hub_reset_resume(struct usb_interface *intf)
+{
+ struct usb_hub *hub = usb_get_intfdata(intf);
+ struct usb_device *hdev = hub->hdev;
+ int port1;
+
+ hub_power_on(hub);
+
+ for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
+ struct usb_device *child = hdev->children[port1-1];
+
+ if (child) {
+
+ /* For "USB_PERSIST"-enabled children we must
+ * mark the child device for reset-resume and
+ * turn off the connect-change status to prevent
+ * khubd from disconnecting it later.
+ */
+ if (USB_PERSIST && child->persist_enabled) {
+ child->reset_resume = 1;
+ clear_port_feature(hdev, port1,
+ USB_PORT_FEAT_C_CONNECTION);
+
+ /* Otherwise we must disconnect the child,
+ * but as we may not lock the child device here
+ * we have to do a "logical" disconnect.
+ */
+ } else {
+ hub_port_logical_disconnect(hub, port1);
}
- } else
- return -EOPNOTSUPP;
- if (status == 0) {
- /* TRSMRCY = 10 msec */
- msleep(10);
}
}
- /* tell khubd to look for changes on this hub */
hub_activate(hub);
return 0;
}
+/**
+ * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
+ * @rhdev: struct usb_device for the root hub
+ *
+ * The USB host controller driver calls this function when its root hub
+ * is resumed and Vbus power has been interrupted or the controller
+ * has been reset. The routine marks @rhdev as having lost power. When
+ * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST
+ * is enabled then it will carry out power-session recovery, otherwise
+ * it will disconnect all the child devices.
+ */
+void usb_root_hub_lost_power(struct usb_device *rhdev)
+{
+ dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+ rhdev->reset_resume = 1;
+}
+EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
+
#else /* CONFIG_PM */
static inline int remote_wakeup(struct usb_device *udev)
@@ -1997,8 +1925,9 @@ static inline int remote_wakeup(struct usb_device *udev)
return 0;
}
-#define hub_suspend NULL
-#define hub_resume NULL
+#define hub_suspend NULL
+#define hub_resume NULL
+#define hub_reset_resume NULL
#endif
@@ -2461,19 +2390,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
return;
}
-#ifdef CONFIG_USB_SUSPEND
- /* If something is connected, but the port is suspended, wake it up. */
- if (portstatus & USB_PORT_STAT_SUSPEND) {
- status = hub_port_resume(hub, port1, NULL);
- if (status < 0) {
- dev_dbg(hub_dev,
- "can't clear suspend on port %d; %d\n",
- port1, status);
- goto done;
- }
- }
-#endif
-
for (i = 0; i < SET_CONFIG_TRIES; i++) {
struct usb_device *udev;
@@ -2584,7 +2500,7 @@ loop:
ep0_reinit(udev);
release_address(udev);
usb_put_dev(udev);
- if (status == -ENOTCONN)
+ if ((status == -ENOTCONN) || (status == -ENOTSUPP))
break;
}
@@ -2625,10 +2541,12 @@ static void hub_events(void)
list_del_init(tmp);
hub = list_entry(tmp, struct usb_hub, event_list);
- hdev = hub->hdev;
- intf = to_usb_interface(hub->intfdev);
- hub_dev = &intf->dev;
+ kref_get(&hub->kref);
+ spin_unlock_irq(&hub_event_lock);
+ hdev = hub->hdev;
+ hub_dev = hub->intfdev;
+ intf = to_usb_interface(hub_dev);
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
hdev->state, hub->descriptor
? hub->descriptor->bNbrPorts
@@ -2637,16 +2555,10 @@ static void hub_events(void)
(u16) hub->change_bits[0],
(u16) hub->event_bits[0]);
- usb_get_intf(intf);
- spin_unlock_irq(&hub_event_lock);
-
/* Lock the device, then check to see if we were
* disconnected while waiting for the lock to succeed. */
- if (locktree(hdev) < 0) {
- usb_put_intf(intf);
- continue;
- }
- if (hub != usb_get_intfdata(intf))
+ usb_lock_device(hdev);
+ if (unlikely(hub->disconnected))
goto loop;
/* If the hub has died, clean up after it */
@@ -2809,7 +2721,7 @@ loop_autopm:
usb_autopm_enable(intf);
loop:
usb_unlock_device(hdev);
- usb_put_intf(intf);
+ kref_put(&hub->kref, hub_release);
} /* end while (1) */
}
@@ -2844,6 +2756,7 @@ static struct usb_driver hub_driver = {
.disconnect = hub_disconnect,
.suspend = hub_suspend,
.resume = hub_resume,
+ .reset_resume = hub_reset_resume,
.pre_reset = hub_pre_reset,
.post_reset = hub_post_reset,
.ioctl = hub_ioctl,
@@ -2946,6 +2859,11 @@ static int config_descriptors_changed(struct usb_device *udev)
* this from a driver probe() routine after downloading new firmware.
* For calls that might not occur during probe(), drivers should lock
* the device using usb_lock_device_for_reset().
+ *
+ * Locking exception: This routine may also be called from within an
+ * autoresume handler. Such usage won't conflict with other tasks
+ * holding the device lock because these tasks should always call
+ * usb_autopm_resume_device(), thereby preventing any unwanted autoresume.
*/
int usb_reset_device(struct usb_device *udev)
{
@@ -2976,7 +2894,7 @@ int usb_reset_device(struct usb_device *udev)
* Other endpoints will be handled by re-enumeration. */
ep0_reinit(udev);
ret = hub_port_init(parent_hub, udev, port1, i);
- if (ret >= 0)
+ if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
break;
}
clear_bit(port1, parent_hub->busy_bits);
@@ -3092,6 +3010,7 @@ int usb_reset_composite_device(struct usb_device *udev,
drv = to_usb_driver(cintf->dev.driver);
if (drv->pre_reset)
(drv->pre_reset)(cintf);
+ /* FIXME: Unbind if pre_reset returns an error or isn't defined */
}
}
}
@@ -3110,6 +3029,7 @@ int usb_reset_composite_device(struct usb_device *udev,
drv = to_usb_driver(cintf->dev.driver);
if (drv->post_reset)
(drv->post_reset)(cintf);
+ /* FIXME: Unbind if post_reset returns an error or isn't defined */
}
if (cintf != iface)
up(&cintf->dev.sem);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f9fed34bf7d..530e854961c 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -404,8 +404,6 @@ int usb_sg_init (
io->urbs [i]->complete = sg_complete;
io->urbs [i]->context = io;
- io->urbs [i]->status = -EINPROGRESS;
- io->urbs [i]->actual_length = 0;
/*
* Some systems need to revert to PIO when DMA is temporarily
@@ -499,7 +497,8 @@ void usb_sg_wait (struct usb_sg_request *io)
/* queue the urbs. */
spin_lock_irq (&io->lock);
- for (i = 0; i < entries && !io->status; i++) {
+ i = 0;
+ while (i < entries && !io->status) {
int retval;
io->urbs [i]->dev = io->dev;
@@ -516,7 +515,6 @@ void usb_sg_wait (struct usb_sg_request *io)
case -ENOMEM:
io->urbs[i]->dev = NULL;
retval = 0;
- i--;
yield ();
break;
@@ -527,6 +525,7 @@ void usb_sg_wait (struct usb_sg_request *io)
* URBs are queued at once; N milliseconds?
*/
case 0:
+ ++i;
cpu_relax ();
break;
@@ -1385,6 +1384,36 @@ struct device_type usb_if_device_type = {
.uevent = usb_if_uevent,
};
+static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
+ struct usb_host_config *config,
+ u8 inum)
+{
+ struct usb_interface_assoc_descriptor *retval = NULL;
+ struct usb_interface_assoc_descriptor *intf_assoc;
+ int first_intf;
+ int last_intf;
+ int i;
+
+ for (i = 0; (i < USB_MAXIADS && config->intf_assoc[i]); i++) {
+ intf_assoc = config->intf_assoc[i];
+ if (intf_assoc->bInterfaceCount == 0)
+ continue;
+
+ first_intf = intf_assoc->bFirstInterface;
+ last_intf = first_intf + (intf_assoc->bInterfaceCount - 1);
+ if (inum >= first_intf && inum <= last_intf) {
+ if (!retval)
+ retval = intf_assoc;
+ else
+ dev_err(&dev->dev, "Interface #%d referenced"
+ " by multiple IADs\n", inum);
+ }
+ }
+
+ return retval;
+}
+
+
/*
* usb_set_configuration - Makes a particular device setting be current
* @dev: the device whose configuration is being updated
@@ -1531,6 +1560,7 @@ free_interfaces:
intfc = cp->intf_cache[i];
intf->altsetting = intfc->altsetting;
intf->num_altsetting = intfc->num_altsetting;
+ intf->intf_assoc = find_iad(dev, cp, i);
kref_get(&intfc->ref);
alt = usb_altnum_to_altsetting(intf, 0);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 739f520908a..aa21b38a31c 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -30,10 +30,28 @@
static const struct usb_device_id usb_quirk_list[] = {
/* HP 5300/5370C scanner */
{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+ /* Benq S2W 3300U */
+ { USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Seiko Epson Corp. Perfection 1200 */
+ { USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Seiko Epson Corp - Perfection 1670 */
{ USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Samsung ML-2510 Series printer */
+ { USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Elsa MicroLink 56k (V.250) */
{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Ultima Electronics Corp.*/
+ { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Umax [hex] Astra 3400U */
+ { USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+
+ /* Philips PSC805 audio device */
+ { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME },
+
+ /* RIM Blackberry */
+ { USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ { USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ { USB_DEVICE(0x0fca, 0x0006), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
{ } /* terminating entry must be last */
};
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index be37c863fdf..d47ae89154a 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -169,6 +169,73 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
+
+#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
+static const char power_group[] = "power";
+#endif
+
+#ifdef CONFIG_USB_PERSIST
+
+static ssize_t
+show_persist(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct usb_device *udev = to_usb_device(dev);
+
+ return sprintf(buf, "%d\n", udev->persist_enabled);
+}
+
+static ssize_t
+set_persist(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct usb_device *udev = to_usb_device(dev);
+ int value;
+
+ /* Hubs are always enabled for USB_PERSIST */
+ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+ return -EPERM;
+
+ if (sscanf(buf, "%d", &value) != 1)
+ return -EINVAL;
+ usb_pm_lock(udev);
+ udev->persist_enabled = !!value;
+ usb_pm_unlock(udev);
+ return count;
+}
+
+static DEVICE_ATTR(persist, S_IRUGO | S_IWUSR, show_persist, set_persist);
+
+static int add_persist_attributes(struct device *dev)
+{
+ int rc = 0;
+
+ if (is_usb_device(dev)) {
+ struct usb_device *udev = to_usb_device(dev);
+
+ /* Hubs are automatically enabled for USB_PERSIST */
+ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+ udev->persist_enabled = 1;
+ rc = sysfs_add_file_to_group(&dev->kobj,
+ &dev_attr_persist.attr,
+ power_group);
+ }
+ return rc;
+}
+
+static void remove_persist_attributes(struct device *dev)
+{
+ sysfs_remove_file_from_group(&dev->kobj,
+ &dev_attr_persist.attr,
+ power_group);
+}
+
+#else
+
+#define add_persist_attributes(dev) 0
+#define remove_persist_attributes(dev) do {} while (0)
+
+#endif /* CONFIG_USB_PERSIST */
+
#ifdef CONFIG_USB_SUSPEND
static ssize_t
@@ -276,8 +343,6 @@ set_level(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level);
-static char power_group[] = "power";
-
static int add_power_attributes(struct device *dev)
{
int rc = 0;
@@ -311,6 +376,7 @@ static void remove_power_attributes(struct device *dev)
#endif /* CONFIG_USB_SUSPEND */
+
/* Descriptor fields */
#define usb_descriptor_attr_le16(field, format_string) \
static ssize_t \
@@ -384,6 +450,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev)
if (retval)
return retval;
+ retval = add_persist_attributes(dev);
+ if (retval)
+ goto error;
+
retval = add_power_attributes(dev);
if (retval)
goto error;
@@ -421,9 +491,29 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev)
device_remove_file(dev, &dev_attr_product);
device_remove_file(dev, &dev_attr_serial);
remove_power_attributes(dev);
+ remove_persist_attributes(dev);
sysfs_remove_group(&dev->kobj, &dev_attr_grp);
}
+/* Interface Accociation Descriptor fields */
+#define usb_intf_assoc_attr(field, format_string) \
+static ssize_t \
+show_iad_##field (struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface (dev); \
+ \
+ return sprintf (buf, format_string, \
+ intf->intf_assoc->field); \
+} \
+static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL);
+
+usb_intf_assoc_attr (bFirstInterface, "%02x\n")
+usb_intf_assoc_attr (bInterfaceCount, "%02d\n")
+usb_intf_assoc_attr (bFunctionClass, "%02x\n")
+usb_intf_assoc_attr (bFunctionSubClass, "%02x\n")
+usb_intf_assoc_attr (bFunctionProtocol, "%02x\n")
+
/* Interface fields */
#define usb_intf_attr(field, format_string) \
static ssize_t \
@@ -487,6 +577,18 @@ static ssize_t show_modalias(struct device *dev,
}
static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+static struct attribute *intf_assoc_attrs[] = {
+ &dev_attr_iad_bFirstInterface.attr,
+ &dev_attr_iad_bInterfaceCount.attr,
+ &dev_attr_iad_bFunctionClass.attr,
+ &dev_attr_iad_bFunctionSubClass.attr,
+ &dev_attr_iad_bFunctionProtocol.attr,
+ NULL,
+};
+static struct attribute_group intf_assoc_attr_grp = {
+ .attrs = intf_assoc_attrs,
+};
+
static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceNumber.attr,
&dev_attr_bAlternateSetting.attr,
@@ -538,6 +640,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
alt->string = usb_cache_string(udev, alt->desc.iInterface);
if (alt->string)
retval = device_create_file(dev, &dev_attr_interface);
+ if (intf->intf_assoc)
+ retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp);
usb_create_intf_ep_files(intf, udev);
return 0;
}
@@ -549,4 +653,5 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf)
usb_remove_intf_ep_files(intf);
device_remove_file(dev, &dev_attr_interface);
sysfs_remove_group(&dev->kobj, &intf_attr_grp);
+ sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp);
}
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 94ea9727ff5..52ec44b828f 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -4,6 +4,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/usb.h>
+#include <linux/wait.h>
#include "hcd.h"
#define to_urb(d) container_of(d, struct urb, kref)
@@ -11,6 +12,10 @@
static void urb_destroy(struct kref *kref)
{
struct urb *urb = to_urb(kref);
+
+ if (urb->transfer_flags & URB_FREE_BUFFER)
+ kfree(urb->transfer_buffer);
+
kfree(urb);
}
@@ -34,6 +39,7 @@ void usb_init_urb(struct urb *urb)
memset(urb, 0, sizeof(*urb));
kref_init(&urb->kref);
spin_lock_init(&urb->lock);
+ INIT_LIST_HEAD(&urb->anchor_list);
}
}
@@ -100,8 +106,60 @@ struct urb * usb_get_urb(struct urb *urb)
kref_get(&urb->kref);
return urb;
}
-
-
+
+/**
+ * usb_anchor_urb - anchors an URB while it is processed
+ * @urb: pointer to the urb to anchor
+ * @anchor: pointer to the anchor
+ *
+ * This can be called to have access to URBs which are to be executed
+ * without bothering to track them
+ */
+void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&anchor->lock, flags);
+ usb_get_urb(urb);
+ list_add_tail(&urb->anchor_list, &anchor->urb_list);
+ urb->anchor = anchor;
+ spin_unlock_irqrestore(&anchor->lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_anchor_urb);
+
+/**
+ * usb_unanchor_urb - unanchors an URB
+ * @urb: pointer to the urb to anchor
+ *
+ * Call this to stop the system keeping track of this URB
+ */
+void usb_unanchor_urb(struct urb *urb)
+{
+ unsigned long flags;
+ struct usb_anchor *anchor;
+
+ if (!urb)
+ return;
+
+ anchor = urb->anchor;
+ if (!anchor)
+ return;
+
+ spin_lock_irqsave(&anchor->lock, flags);
+ if (unlikely(anchor != urb->anchor)) {
+ /* we've lost the race to another thread */
+ spin_unlock_irqrestore(&anchor->lock, flags);
+ return;
+ }
+ urb->anchor = NULL;
+ list_del(&urb->anchor_list);
+ spin_unlock_irqrestore(&anchor->lock, flags);
+ usb_put_urb(urb);
+ if (list_empty(&anchor->urb_list))
+ wake_up(&anchor->wait);
+}
+EXPORT_SYMBOL_GPL(usb_unanchor_urb);
+
/*-------------------------------------------------------------------*/
/**
@@ -478,6 +536,48 @@ void usb_kill_urb(struct urb *urb)
spin_unlock_irq(&urb->lock);
}
+/**
+ * usb_kill_anchored_urbs - cancel transfer requests en masse
+ * @anchor: anchor the requests are bound to
+ *
+ * this allows all outstanding URBs to be killed starting
+ * from the back of the queue
+ */
+void usb_kill_anchored_urbs(struct usb_anchor *anchor)
+{
+ struct urb *victim;
+
+ spin_lock_irq(&anchor->lock);
+ while (!list_empty(&anchor->urb_list)) {
+ victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list);
+ /* we must make sure the URB isn't freed before we kill it*/
+ usb_get_urb(victim);
+ spin_unlock_irq(&anchor->lock);
+ /* this will unanchor the URB */
+ usb_kill_urb(victim);
+ usb_put_urb(victim);
+ spin_lock_irq(&anchor->lock);
+ }
+ spin_unlock_irq(&anchor->lock);
+}
+EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs);
+
+/**
+ * usb_wait_anchor_empty_timeout - wait for an anchor to be unused
+ * @anchor: the anchor you want to become unused
+ * @timeout: how long you are willing to wait in milliseconds
+ *
+ * Call this is you want to be sure all an anchor's
+ * URBs have finished
+ */
+int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+ unsigned int timeout)
+{
+ return wait_event_timeout(anchor->wait, list_empty(&anchor->urb_list),
+ msecs_to_jiffies(timeout));
+}
+EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout);
+
EXPORT_SYMBOL(usb_init_urb);
EXPORT_SYMBOL(usb_alloc_urb);
EXPORT_SYMBOL(usb_free_urb);
@@ -485,4 +585,3 @@ EXPORT_SYMBOL(usb_get_urb);
EXPORT_SYMBOL(usb_submit_urb);
EXPORT_SYMBOL(usb_unlink_urb);
EXPORT_SYMBOL(usb_kill_urb);
-
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 4a6299bd004..0fee5c66fd6 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -253,6 +253,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
dev->dev.bus = &usb_bus_type;
dev->dev.type = &usb_device_type;
dev->dev.dma_mask = bus->controller->dma_mask;
+ set_dev_node(&dev->dev, dev_to_node(bus->controller));
dev->state = USB_STATE_ATTACHED;
INIT_LIST_HEAD(&dev->ep0.urb_list);
@@ -578,11 +579,12 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
* address (through the pointer provided).
*
* These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags
- * to avoid behaviors like using "DMA bounce buffers", or tying down I/O
- * mapping hardware for long idle periods. The implementation varies between
+ * to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU
+ * hardware during URB completion/resubmit. The implementation varies between
* platforms, depending on details of how DMA will work to this device.
- * Using these buffers also helps prevent cacheline sharing problems on
- * architectures where CPU caches are not DMA-coherent.
+ * Using these buffers also eliminates cacheline sharing problems on
+ * architectures where CPU caches are not DMA-coherent. On systems without
+ * bus-snooping caches, these buffers are uncached.
*
* When the buffer is no longer used, free it with usb_buffer_free().
*/
@@ -607,7 +609,7 @@ void *usb_buffer_alloc(
*
* This reclaims an I/O buffer, letting it be reused. The memory must have
* been allocated using usb_buffer_alloc(), and the parameters must match
- * those provided in that allocation request.
+ * those provided in that allocation request.
*/
void usb_buffer_free(
struct usb_device *dev,
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index bf2eb0dae2e..ad5fa0338f4 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -52,8 +52,16 @@ static inline void usb_pm_unlock(struct usb_device *udev)
#else
-#define usb_port_suspend(dev) 0
-#define usb_port_resume(dev) 0
+static inline int usb_port_suspend(struct usb_device *udev)
+{
+ return 0;
+}
+
+static inline int usb_port_resume(struct usb_device *udev)
+{
+ return 0;
+}
+
static inline void usb_pm_lock(struct usb_device *udev) {}
static inline void usb_pm_unlock(struct usb_device *udev) {}
@@ -100,11 +108,13 @@ static inline int is_usb_device_driver(struct device_driver *drv)
static inline void mark_active(struct usb_interface *f)
{
f->is_active = 1;
+ f->dev.power.power_state.event = PM_EVENT_ON;
}
static inline void mark_quiesced(struct usb_interface *f)
{
f->is_active = 0;
+ f->dev.power.power_state.event = PM_EVENT_SUSPEND;
}
static inline int is_active(const struct usb_interface *f)
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index f771a7cae9e..45e01e28945 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -42,6 +42,20 @@ config USB_GADGET
For more information, see <http://www.linux-usb.org/gadget> and
the kernel DocBook documentation for this API.
+config USB_GADGET_DEBUG
+ boolean "Debugging messages"
+ depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL
+ help
+ Many controller and gadget drivers will print some debugging
+ messages if you use this option to ask for those messages.
+
+ Avoid enabling these messages, even if you're actively
+ debugging such a driver. Many drivers will emit so many
+ messages that the driver timings are affected, which will
+ either create new failure modes or remove the one you're
+ trying to track down. Never enable these messages for a
+ production build.
+
config USB_GADGET_DEBUG_FILES
boolean "Debugging information files"
depends on USB_GADGET && PROC_FS
@@ -208,6 +222,27 @@ config USB_OTG
Select this only if your OMAP board has a Mini-AB connector.
+config USB_GADGET_S3C2410
+ boolean "S3C2410 USB Device Controller"
+ depends on ARCH_S3C2410
+ help
+ Samsung's S3C2410 is an ARM-4 processor with an integrated
+ full speed USB 1.1 device controller. It has 4 configurable
+ endpoints, as well as endpoint zero (for control transfers).
+
+ This driver has been tested on the S3C2410, S3C2412, and
+ S3C2440 processors.
+
+config USB_S3C2410
+ tristate
+ depends on USB_GADGET_S3C2410
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+
+config USB_S3C2410_DEBUG
+ boolean "S3C2410 udc debug messages"
+ depends on USB_GADGET_S3C2410
+
config USB_GADGET_AT91
boolean "AT91 USB Device Port"
depends on ARCH_AT91 && !ARCH_AT91SAM9RL
@@ -226,6 +261,24 @@ config USB_AT91
depends on USB_GADGET_AT91
default USB_GADGET
+config USB_GADGET_M66592
+ boolean "M66592 driver"
+ select USB_GADGET_DUALSPEED
+ help
+ M66592 is a USB 2.0 peripheral controller.
+
+ It has seven configurable endpoints, and endpoint zero.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "m66592_udc" and force all
+ gadget drivers to also be dynamically linked.
+
+config USB_M66592
+ tristate
+ depends on USB_GADGET_M66592
+ default USB_GADGET
+ select USB_GADGET_SELECTED
+
config USB_GADGET_DUMMY_HCD
boolean "Dummy HCD (DEVELOPMENT)"
depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 5db19396631..8ae76f73863 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -1,14 +1,20 @@
#
# USB peripheral controller drivers
#
+ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
+ EXTRA_CFLAGS += -DDEBUG
+endif
+
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2280) += net2280.o
obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o
obj-$(CONFIG_USB_GOKU) += goku_udc.o
obj-$(CONFIG_USB_OMAP) += omap_udc.o
obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o
+obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o
obj-$(CONFIG_USB_AT91) += at91_udc.o
obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
+obj-$(CONFIG_USB_M66592) += m66592-udc.o
#
# USB gadget drivers
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index ba163f35bf2..63d7d656869 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -601,25 +601,6 @@ static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
kfree(req);
}
-static void *at91_ep_alloc_buffer(
- struct usb_ep *_ep,
- unsigned bytes,
- dma_addr_t *dma,
- gfp_t gfp_flags)
-{
- *dma = ~0;
- return kmalloc(bytes, gfp_flags);
-}
-
-static void at91_ep_free_buffer(
- struct usb_ep *ep,
- void *buf,
- dma_addr_t dma,
- unsigned bytes)
-{
- kfree(buf);
-}
-
static int at91_ep_queue(struct usb_ep *_ep,
struct usb_request *_req, gfp_t gfp_flags)
{
@@ -788,8 +769,6 @@ static const struct usb_ep_ops at91_ep_ops = {
.disable = at91_ep_disable,
.alloc_request = at91_ep_alloc_request,
.free_request = at91_ep_free_request,
- .alloc_buffer = at91_ep_alloc_buffer,
- .free_buffer = at91_ep_free_buffer,
.queue = at91_ep_queue,
.dequeue = at91_ep_dequeue,
.set_halt = at91_ep_set_halt,
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index fcb5526cb08..f2fbdc7fe37 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -497,38 +497,6 @@ dummy_free_request (struct usb_ep *_ep, struct usb_request *_req)
kfree (req);
}
-static void *
-dummy_alloc_buffer (
- struct usb_ep *_ep,
- unsigned bytes,
- dma_addr_t *dma,
- gfp_t mem_flags
-) {
- char *retval;
- struct dummy_ep *ep;
- struct dummy *dum;
-
- ep = usb_ep_to_dummy_ep (_ep);
- dum = ep_to_dummy (ep);
-
- if (!dum->driver)
- return NULL;
- retval = kmalloc (bytes, mem_flags);
- *dma = (dma_addr_t) retval;
- return retval;
-}
-
-static void
-dummy_free_buffer (
- struct usb_ep *_ep,
- void *buf,
- dma_addr_t dma,
- unsigned bytes
-) {
- if (bytes)
- kfree (buf);
-}
-
static void
fifo_complete (struct usb_ep *ep, struct usb_request *req)
{
@@ -659,10 +627,6 @@ static const struct usb_ep_ops dummy_ep_ops = {
.alloc_request = dummy_alloc_request,
.free_request = dummy_free_request,
- .alloc_buffer = dummy_alloc_buffer,
- .free_buffer = dummy_free_buffer,
- /* map, unmap, ... eventually hook the "generic" dma calls */
-
.queue = dummy_queue,
.dequeue = dummy_dequeue,
@@ -1784,8 +1748,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd)
spin_lock_irq (&dum->lock);
if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n");
- rc = -ENODEV;
+ rc = -ESHUTDOWN;
} else {
dum->rh_state = DUMMY_RH_RUNNING;
set_link_state (dum);
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index f28af06905a..6042364402b 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -132,7 +132,7 @@ ep_matches (
* where it's an output parameter representing the full speed limit.
* the usb spec fixes high speed bulk maxpacket at 512 bytes.
*/
- max = 0x7ff & le16_to_cpup (&desc->wMaxPacketSize);
+ max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
switch (type) {
case USB_ENDPOINT_XFER_INT:
/* INT: limit 64 bytes full speed, 1024 high speed */
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 325bf7cfb83..dbaf867436d 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -277,7 +277,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_CDC
#endif
-#ifdef CONFIG_USB_GADGET_HUSB2DEV
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
#define DEV_CONFIG_CDC
#endif
@@ -292,7 +292,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_SUBSET
#endif
-#ifdef CONFIG_USB_GADGET_SH
+#ifdef CONFIG_USB_GADGET_SUPERH
#define DEV_CONFIG_SUBSET
#endif
@@ -301,6 +301,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_SUBSET
#endif
+#ifdef CONFIG_USB_GADGET_M66592
+#define DEV_CONFIG_CDC
+#endif
+
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index c6b6479fa4d..8712ef98717 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -686,7 +686,6 @@ struct fsg_dev {
int thread_wakeup_needed;
struct completion thread_notifier;
struct task_struct *thread_task;
- sigset_t thread_signal_mask;
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
@@ -3277,8 +3276,7 @@ static void handle_exception(struct fsg_dev *fsg)
/* Clear the existing signals. Anything but SIGUSR1 is converted
* into a high-priority EXIT exception. */
for (;;) {
- sig = dequeue_signal_lock(current, &fsg->thread_signal_mask,
- &info);
+ sig = dequeue_signal_lock(current, &current->blocked, &info);
if (!sig)
break;
if (sig != SIGUSR1) {
@@ -3431,10 +3429,10 @@ static int fsg_main_thread(void *fsg_)
/* Allow the thread to be killed by a signal, but set the signal mask
* to block everything but INT, TERM, KILL, and USR1. */
- siginitsetinv(&fsg->thread_signal_mask, sigmask(SIGINT) |
- sigmask(SIGTERM) | sigmask(SIGKILL) |
- sigmask(SIGUSR1));
- sigprocmask(SIG_SETMASK, &fsg->thread_signal_mask, NULL);
+ allow_signal(SIGINT);
+ allow_signal(SIGTERM);
+ allow_signal(SIGKILL);
+ allow_signal(SIGUSR1);
/* Arrange for userspace references to be interpreted as kernel
* pointers. That way we can pass a kernel pointer to a routine
@@ -3735,19 +3733,12 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget)
}
/* Free the data buffers */
- for (i = 0; i < NUM_BUFFERS; ++i) {
- struct fsg_buffhd *bh = &fsg->buffhds[i];
-
- if (bh->buf)
- usb_ep_free_buffer(fsg->bulk_in, bh->buf, bh->dma,
- mod_data.buflen);
- }
+ for (i = 0; i < NUM_BUFFERS; ++i)
+ kfree(fsg->buffhds[i].buf);
/* Free the request and buffer for endpoint 0 */
if (req) {
- if (req->buf)
- usb_ep_free_buffer(fsg->ep0, req->buf,
- req->dma, EP0_BUFSIZE);
+ kfree(req->buf);
usb_ep_free_request(fsg->ep0, req);
}
@@ -3965,8 +3956,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
#endif
if (gadget->is_otg) {
- otg_desc.bmAttributes |= USB_OTG_HNP,
- config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ otg_desc.bmAttributes |= USB_OTG_HNP;
}
rc = -ENOMEM;
@@ -3975,8 +3965,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL);
if (!req)
goto out;
- req->buf = usb_ep_alloc_buffer(fsg->ep0, EP0_BUFSIZE,
- &req->dma, GFP_KERNEL);
+ req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL);
if (!req->buf)
goto out;
req->complete = ep0_complete;
@@ -3988,8 +3977,7 @@ static int __init fsg_bind(struct usb_gadget *gadget)
/* Allocate for the bulk-in endpoint. We assume that
* the buffer will also work with the bulk-out (and
* interrupt-in) endpoint. */
- bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen,
- &bh->dma, GFP_KERNEL);
+ bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL);
if (!bh->buf)
goto out;
bh->next = bh + 1;
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c
index 3ca2b3159f0..10b2b33b869 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.c
+++ b/drivers/usb/gadget/fsl_usb2_udc.c
@@ -228,7 +228,7 @@ static int dr_controller_setup(struct fsl_udc *udc)
/* Config PHY interface */
portctrl = fsl_readl(&dr_regs->portsc1);
- portctrl &= ~(PORTSCX_PHY_TYPE_SEL & PORTSCX_PORT_WIDTH);
+ portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH);
switch (udc->phy_mode) {
case FSL_USB2_PHY_ULPI:
portctrl |= PORTSCX_PTS_ULPI;
@@ -601,39 +601,6 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req)
kfree(req);
}
-/*------------------------------------------------------------------
- * Allocate an I/O buffer
-*---------------------------------------------------------------------*/
-static void *fsl_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
- dma_addr_t *dma, gfp_t gfp_flags)
-{
- struct fsl_ep *ep;
-
- if (!_ep)
- return NULL;
-
- ep = container_of(_ep, struct fsl_ep, ep);
-
- return dma_alloc_coherent(ep->udc->gadget.dev.parent,
- bytes, dma, gfp_flags);
-}
-
-/*------------------------------------------------------------------
- * frees an i/o buffer
-*---------------------------------------------------------------------*/
-static void fsl_free_buffer(struct usb_ep *_ep, void *buf,
- dma_addr_t dma, unsigned bytes)
-{
- struct fsl_ep *ep;
-
- if (!_ep)
- return;
-
- ep = container_of(_ep, struct fsl_ep, ep);
-
- dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma);
-}
-
/*-------------------------------------------------------------------------*/
static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
{
@@ -1047,9 +1014,6 @@ static struct usb_ep_ops fsl_ep_ops = {
.alloc_request = fsl_alloc_request,
.free_request = fsl_free_request,
- .alloc_buffer = fsl_alloc_buffer,
- .free_buffer = fsl_free_buffer,
-
.queue = fsl_ep_queue,
.dequeue = fsl_ep_dequeue,
@@ -2189,27 +2153,19 @@ static void fsl_udc_release(struct device *dev)
* init resource for globle controller
* Return the udc handle on success or NULL on failure
------------------------------------------------------------------*/
-static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
+static int __init struct_udc_setup(struct fsl_udc *udc,
+ struct platform_device *pdev)
{
- struct fsl_udc *udc;
struct fsl_usb2_platform_data *pdata;
size_t size;
- udc = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
- if (udc == NULL) {
- ERR("malloc udc failed\n");
- return NULL;
- }
-
pdata = pdev->dev.platform_data;
udc->phy_mode = pdata->phy_mode;
- /* max_ep_nr is bidirectional ep number, max_ep doubles the number */
- udc->max_ep = pdata->max_ep_nr * 2;
udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
if (!udc->eps) {
ERR("malloc fsl_ep failed\n");
- goto cleanup;
+ return -1;
}
/* initialized QHs, take care of alignment */
@@ -2225,7 +2181,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
if (!udc->ep_qh) {
ERR("malloc QHs for udc failed\n");
kfree(udc->eps);
- goto cleanup;
+ return -1;
}
udc->ep_qh_size = size;
@@ -2244,11 +2200,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev)
udc->remote_wakeup = 0; /* default to 0 on reset */
spin_lock_init(&udc->lock);
- return udc;
-
-cleanup:
- kfree(udc);
- return NULL;
+ return 0;
}
/*----------------------------------------------------------------
@@ -2287,35 +2239,37 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
}
/* Driver probe function
- * all intialize operations implemented here except enabling usb_intr reg
+ * all intialization operations implemented here except enabling usb_intr reg
+ * board setup should have been done in the platform code
*/
static int __init fsl_udc_probe(struct platform_device *pdev)
{
struct resource *res;
int ret = -ENODEV;
unsigned int i;
+ u32 dccparams;
if (strcmp(pdev->name, driver_name)) {
VDBG("Wrong device\n");
return -ENODEV;
}
- /* board setup should have been done in the platform code */
-
- /* Initialize the udc structure including QH member and other member */
- udc_controller = struct_udc_setup(pdev);
- if (!udc_controller) {
- VDBG("udc_controller is NULL \n");
+ udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
+ if (udc_controller == NULL) {
+ ERR("malloc udc failed\n");
return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
+ if (!res) {
+ kfree(udc_controller);
return -ENXIO;
+ }
if (!request_mem_region(res->start, res->end - res->start + 1,
driver_name)) {
ERR("request mem region for %s failed \n", pdev->name);
+ kfree(udc_controller);
return -EBUSY;
}
@@ -2328,13 +2282,24 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
usb_sys_regs = (struct usb_sys_interface *)
((u32)dr_regs + USB_DR_SYS_OFFSET);
+ /* Read Device Controller Capability Parameters register */
+ dccparams = fsl_readl(&dr_regs->dccparams);
+ if (!(dccparams & DCCPARAMS_DC)) {
+ ERR("This SOC doesn't support device role\n");
+ ret = -ENODEV;
+ goto err2;
+ }
+ /* Get max device endpoints */
+ /* DEN is bidirectional ep number, max_ep doubles the number */
+ udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2;
+
udc_controller->irq = platform_get_irq(pdev, 0);
if (!udc_controller->irq) {
ret = -ENODEV;
goto err2;
}
- ret = request_irq(udc_controller->irq, fsl_udc_irq, SA_SHIRQ,
+ ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED,
driver_name, udc_controller);
if (ret != 0) {
ERR("cannot request irq %d err %d \n",
@@ -2342,6 +2307,13 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
goto err2;
}
+ /* Initialize the udc structure including QH member and other member */
+ if (struct_udc_setup(udc_controller, pdev)) {
+ ERR("Can't initialize udc data structure\n");
+ ret = -ENOMEM;
+ goto err3;
+ }
+
/* initialize usb hw reg except for regs for EP,
* leave usbintr reg untouched */
dr_controller_setup(udc_controller);
@@ -2403,6 +2375,7 @@ err2:
iounmap(dr_regs);
err1:
release_mem_region(res->start, res->end - res->start + 1);
+ kfree(udc_controller);
return ret;
}
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index c6291e04650..832ab82b488 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -101,6 +101,10 @@ struct usb_sys_interface {
#define WAIT_FOR_OUT_STATUS 3
#define DATA_STATE_RECV 4
+/* Device Controller Capability Parameter register */
+#define DCCPARAMS_DC 0x00000080
+#define DCCPARAMS_DEN_MASK 0x0000001f
+
/* Frame Index Register Bit Masks */
#define USB_FRINDEX_MASKS 0x3fff
/* USB CMD Register Bit Masks */
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index d041b919e7b..53e9139ba38 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -8,6 +8,8 @@
* (And avoiding all runtime comparisons in typical one-choice configs!)
*
* NOTE: some of these controller drivers may not be available yet.
+ * Some are available on 2.4 kernels; several are available, but not
+ * yet pushed in the 2.6 mainline tree.
*/
#ifdef CONFIG_USB_GADGET_NET2280
#define gadget_is_net2280(g) !strcmp("net2280", (g)->name)
@@ -33,12 +35,14 @@
#define gadget_is_goku(g) 0
#endif
+/* SH3 UDC -- not yet ported 2.4 --> 2.6 */
#ifdef CONFIG_USB_GADGET_SUPERH
#define gadget_is_sh(g) !strcmp("sh_udc", (g)->name)
#else
#define gadget_is_sh(g) 0
#endif
+/* not yet stable on 2.6 (would help "original Zaurus") */
#ifdef CONFIG_USB_GADGET_SA1100
#define gadget_is_sa1100(g) !strcmp("sa1100_udc", (g)->name)
#else
@@ -51,6 +55,7 @@
#define gadget_is_lh7a40x(g) 0
#endif
+/* handhelds.org tree (?) */
#ifdef CONFIG_USB_GADGET_MQ11XX
#define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name)
#else
@@ -63,22 +68,24 @@
#define gadget_is_omap(g) 0
#endif
+/* not yet ported 2.4 --> 2.6 */
#ifdef CONFIG_USB_GADGET_N9604
#define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name)
#else
#define gadget_is_n9604(g) 0
#endif
+/* various unstable versions available */
#ifdef CONFIG_USB_GADGET_PXA27X
#define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name)
#else
#define gadget_is_pxa27x(g) 0
#endif
-#ifdef CONFIG_USB_GADGET_HUSB2DEV
-#define gadget_is_husb2dev(g) !strcmp("husb2_udc", (g)->name)
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+#define gadget_is_atmel_usba(g) !strcmp("atmel_usba_udc", (g)->name)
#else
-#define gadget_is_husb2dev(g) 0
+#define gadget_is_atmel_usba(g) 0
#endif
#ifdef CONFIG_USB_GADGET_S3C2410
@@ -93,6 +100,7 @@
#define gadget_is_at91(g) 0
#endif
+/* status unclear */
#ifdef CONFIG_USB_GADGET_IMX
#define gadget_is_imx(g) !strcmp("imx_udc", (g)->name)
#else
@@ -106,6 +114,7 @@
#endif
/* Mentor high speed function controller */
+/* from Montavista kernel (?) */
#ifdef CONFIG_USB_GADGET_MUSBHSFC
#define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name)
#else
@@ -119,12 +128,20 @@
#define gadget_is_musbhdrc(g) 0
#endif
+/* from Montavista kernel (?) */
#ifdef CONFIG_USB_GADGET_MPC8272
#define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name)
#else
#define gadget_is_mpc8272(g) 0
#endif
+#ifdef CONFIG_USB_GADGET_M66592
+#define gadget_is_m66592(g) !strcmp("m66592_udc", (g)->name)
+#else
+#define gadget_is_m66592(g) 0
+#endif
+
+
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
// ...
@@ -181,9 +198,11 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x16;
else if (gadget_is_mpc8272(gadget))
return 0x17;
- else if (gadget_is_husb2dev(gadget))
+ else if (gadget_is_atmel_usba(gadget))
return 0x18;
else if (gadget_is_fsl_usb2(gadget))
return 0x19;
+ else if (gadget_is_m66592(gadget))
+ return 0x20;
return -ENOENT;
}
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
index d08a8d0e642..1c5aa49d743 100644
--- a/drivers/usb/gadget/gmidi.c
+++ b/drivers/usb/gadget/gmidi.c
@@ -1248,17 +1248,11 @@ autoconf_fail:
tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev);
/* preallocate control response and buffer */
- dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+ dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ);
if (!dev->req) {
err = -ENOMEM;
goto fail;
}
- dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ,
- &dev->req->dma, GFP_KERNEL);
- if (!dev->req->buf) {
- err = -ENOMEM;
- goto fail;
- }
dev->req->complete = gmidi_setup_complete;
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index ae931af05ce..d6c5f1150ae 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -20,7 +20,6 @@
* - DMA works with ep1 (OUT transfers) and ep2 (IN transfers).
*/
-#undef DEBUG
// #define VERBOSE /* extra debug messages (success too) */
// #define USB_TRACE /* packet-level success messages */
@@ -296,51 +295,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req)
/*-------------------------------------------------------------------------*/
-/* allocating buffers this way eliminates dma mapping overhead, which
- * on some platforms will mean eliminating a per-io buffer copy. with
- * some kinds of system caches, further tweaks may still be needed.
- */
-static void *
-goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
- dma_addr_t *dma, gfp_t gfp_flags)
-{
- void *retval;
- struct goku_ep *ep;
-
- ep = container_of(_ep, struct goku_ep, ep);
- if (!_ep)
- return NULL;
- *dma = DMA_ADDR_INVALID;
-
- if (ep->dma) {
- /* the main problem with this call is that it wastes memory
- * on typical 1/N page allocations: it allocates 1-N pages.
- */
-#warning Using dma_alloc_coherent even with buffers smaller than a page.
- retval = dma_alloc_coherent(&ep->dev->pdev->dev,
- bytes, dma, gfp_flags);
- } else
- retval = kmalloc(bytes, gfp_flags);
- return retval;
-}
-
-static void
-goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes)
-{
- /* free memory into the right allocator */
- if (dma != DMA_ADDR_INVALID) {
- struct goku_ep *ep;
-
- ep = container_of(_ep, struct goku_ep, ep);
- if (!_ep)
- return;
- dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
- } else
- kfree (buf);
-}
-
-/*-------------------------------------------------------------------------*/
-
static void
done(struct goku_ep *ep, struct goku_request *req, int status)
{
@@ -485,7 +439,7 @@ top:
/* use ep1/ep2 double-buffering for OUT */
if (!(size & PACKET_ACTIVE))
size = readl(&regs->EPxSizeLB[ep->num]);
- if (!(size & PACKET_ACTIVE)) // "can't happen"
+ if (!(size & PACKET_ACTIVE)) /* "can't happen" */
break;
size &= DATASIZE; /* EPxSizeH == 0 */
@@ -1026,9 +980,6 @@ static struct usb_ep_ops goku_ep_ops = {
.alloc_request = goku_alloc_request,
.free_request = goku_free_request,
- .alloc_buffer = goku_alloc_buffer,
- .free_buffer = goku_free_buffer,
-
.queue = goku_queue,
.dequeue = goku_dequeue,
@@ -1140,17 +1091,17 @@ udc_proc_read(char *buffer, char **start, off_t off, int count,
is_usb_connected
? ((tmp & PW_PULLUP) ? "full speed" : "powered")
: "disconnected",
- ({char *tmp;
+ ({char *state;
switch(dev->ep0state){
- case EP0_DISCONNECT: tmp = "ep0_disconnect"; break;
- case EP0_IDLE: tmp = "ep0_idle"; break;
- case EP0_IN: tmp = "ep0_in"; break;
- case EP0_OUT: tmp = "ep0_out"; break;
- case EP0_STATUS: tmp = "ep0_status"; break;
- case EP0_STALL: tmp = "ep0_stall"; break;
- case EP0_SUSPEND: tmp = "ep0_suspend"; break;
- default: tmp = "ep0_?"; break;
- } tmp; })
+ case EP0_DISCONNECT: state = "ep0_disconnect"; break;
+ case EP0_IDLE: state = "ep0_idle"; break;
+ case EP0_IN: state = "ep0_in"; break;
+ case EP0_OUT: state = "ep0_out"; break;
+ case EP0_STATUS: state = "ep0_status"; break;
+ case EP0_STALL: state = "ep0_stall"; break;
+ case EP0_SUSPEND: state = "ep0_suspend"; break;
+ default: state = "ep0_?"; break;
+ } state; })
);
size -= t;
next += t;
@@ -1195,7 +1146,6 @@ udc_proc_read(char *buffer, char **start, off_t off, int count,
for (i = 0; i < 4; i++) {
struct goku_ep *ep = &dev->ep [i];
struct goku_request *req;
- int t;
if (i && !ep->desc)
continue;
@@ -1283,7 +1233,7 @@ done:
static void udc_reinit (struct goku_udc *dev)
{
static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" };
-
+
unsigned i;
INIT_LIST_HEAD (&dev->gadget.ep_list);
@@ -1896,9 +1846,9 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* done */
the_controller = dev;
- device_register(&dev->gadget.dev);
-
- return 0;
+ retval = device_register(&dev->gadget.dev);
+ if (retval == 0)
+ return 0;
done:
if (dev)
@@ -1910,8 +1860,8 @@ done:
/*-------------------------------------------------------------------------*/
static struct pci_device_id pci_ids [] = { {
- .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
- .class_mask = ~0,
+ .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+ .class_mask = ~0,
.vendor = 0x102f, /* Toshiba */
.device = 0x0107, /* this UDC */
.subvendor = PCI_ANY_ID,
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h
index ea8c8e58cab..bc4eb1e0b50 100644
--- a/drivers/usb/gadget/goku_udc.h
+++ b/drivers/usb/gadget/goku_udc.h
@@ -41,8 +41,10 @@ struct goku_udc_regs {
#define INT_SYSERROR 0x40000
#define INT_PWRDETECT 0x80000
-#define INT_DEVWIDE (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
-#define INT_EP0 (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
+#define INT_DEVWIDE \
+ (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND)
+#define INT_EP0 \
+ (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK)
u32 dma_master;
#define MST_EOPB_DIS 0x0800
@@ -231,7 +233,7 @@ struct goku_request {
enum ep0state {
EP0_DISCONNECT, /* no host */
EP0_IDLE, /* between STATUS ack and SETUP report */
- EP0_IN, EP0_OUT, /* data stage */
+ EP0_IN, EP0_OUT, /* data stage */
EP0_STATUS, /* status stage */
EP0_STALL, /* data or status stages */
EP0_SUSPEND, /* usb suspend */
@@ -242,7 +244,7 @@ struct goku_udc {
struct usb_gadget gadget;
spinlock_t lock;
struct goku_ep ep[4];
- struct usb_gadget_driver *driver;
+ struct usb_gadget_driver *driver;
enum ep0state ep0state;
unsigned got_irq:1,
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 188c74a9521..e60745ffaf8 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -37,7 +37,7 @@
#include <linux/device.h>
#include <linux/moduleparam.h>
-#include <linux/usb_gadgetfs.h>
+#include <linux/usb/gadgetfs.h>
#include <linux/usb_gadget.h>
@@ -923,7 +923,7 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)
struct dev_data *dev = ep->driver_data;
if (req->buf != dev->rbuf) {
- usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
+ kfree(req->buf);
req->buf = dev->rbuf;
req->dma = DMA_ADDR_INVALID;
}
@@ -963,7 +963,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
return -EBUSY;
}
if (len > sizeof (dev->rbuf))
- req->buf = usb_ep_alloc_buffer (ep, len, &req->dma, GFP_ATOMIC);
+ req->buf = kmalloc(len, GFP_ATOMIC);
if (req->buf == 0) {
req->buf = dev->rbuf;
return -ENOMEM;
@@ -1369,12 +1369,12 @@ config_buf (struct dev_data *dev, u8 type, unsigned index)
hs = !hs;
if (hs) {
dev->req->buf = dev->hs_config;
- len = le16_to_cpup (&dev->hs_config->wTotalLength);
+ len = le16_to_cpu(dev->hs_config->wTotalLength);
} else
#endif
{
dev->req->buf = dev->config;
- len = le16_to_cpup (&dev->config->wTotalLength);
+ len = le16_to_cpu(dev->config->wTotalLength);
}
((u8 *)dev->req->buf) [1] = type;
return len;
@@ -1505,7 +1505,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
}
break;
-#ifndef CONFIG_USB_GADGETFS_PXA2XX
+#ifndef CONFIG_USB_GADGET_PXA2XX
/* PXA automagically handles this request too */
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != 0x80)
@@ -1885,7 +1885,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* full or low speed config */
dev->config = (void *) kbuf;
- total = le16_to_cpup (&dev->config->wTotalLength);
+ total = le16_to_cpu(dev->config->wTotalLength);
if (!is_valid_config (dev->config) || total >= length)
goto fail;
kbuf += total;
@@ -1894,7 +1894,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* optional high speed config */
if (kbuf [1] == USB_DT_CONFIG) {
dev->hs_config = (void *) kbuf;
- total = le16_to_cpup (&dev->hs_config->wTotalLength);
+ total = le16_to_cpu(dev->hs_config->wTotalLength);
if (!is_valid_config (dev->hs_config) || total >= length)
goto fail;
kbuf += total;
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
index a0a73c08a34..e78c2ddc1f8 100644
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ b/drivers/usb/gadget/lh7a40x_udc.c
@@ -75,10 +75,6 @@ static int lh7a40x_ep_enable(struct usb_ep *ep,
static int lh7a40x_ep_disable(struct usb_ep *ep);
static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t);
static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
-static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *,
- gfp_t);
-static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t,
- unsigned);
static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
static int lh7a40x_set_halt(struct usb_ep *ep, int);
@@ -104,9 +100,6 @@ static struct usb_ep_ops lh7a40x_ep_ops = {
.alloc_request = lh7a40x_alloc_request,
.free_request = lh7a40x_free_request,
- .alloc_buffer = lh7a40x_alloc_buffer,
- .free_buffer = lh7a40x_free_buffer,
-
.queue = lh7a40x_queue,
.dequeue = lh7a40x_dequeue,
@@ -1134,26 +1127,6 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
kfree(req);
}
-static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes,
- dma_addr_t * dma, gfp_t gfp_flags)
-{
- char *retval;
-
- DEBUG("%s (%p, %d, %d)\n", __FUNCTION__, ep, bytes, gfp_flags);
-
- retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA | __GFP_HIGHMEM));
- if (retval)
- *dma = virt_to_bus(retval);
- return retval;
-}
-
-static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma,
- unsigned bytes)
-{
- DEBUG("%s, %p\n", __FUNCTION__, ep);
- kfree(buf);
-}
-
/** Queue one request
* Kickstart transfer if needed
* NOTE: Sets INDEX register
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
new file mode 100644
index 00000000000..0174a322e00
--- /dev/null
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -0,0 +1,1634 @@
+/*
+ * M66592 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb_gadget.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "m66592-udc.h"
+
+MODULE_DESCRIPTION("M66592 USB gadget driiver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+
+#define DRIVER_VERSION "29 May 2007"
+
+/* module parameters */
+static unsigned short clock = M66592_XTAL24;
+module_param(clock, ushort, 0644);
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=16384)");
+static unsigned short vif = M66592_LDRV;
+module_param(vif, ushort, 0644);
+MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
+static unsigned short endian = 0;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+static unsigned short irq_sense = M66592_INTL;
+module_param(irq_sense, ushort, 0644);
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0(default=2)");
+
+static const char udc_name[] = "m66592_udc";
+static const char *m66592_ep_name[] = {
+ "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7"
+};
+
+static void disable_controller(struct m66592 *m66592);
+static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req);
+static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req);
+static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
+ gfp_t gfp_flags);
+
+static void transfer_complete(struct m66592_ep *ep,
+ struct m66592_request *req,
+ int status);
+/*-------------------------------------------------------------------------*/
+static inline u16 get_usb_speed(struct m66592 *m66592)
+{
+ return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST);
+}
+
+static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum,
+ unsigned long reg)
+{
+ u16 tmp;
+
+ tmp = m66592_read(m66592, M66592_INTENB0);
+ m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
+ M66592_INTENB0);
+ m66592_bset(m66592, (1 << pipenum), reg);
+ m66592_write(m66592, tmp, M66592_INTENB0);
+}
+
+static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum,
+ unsigned long reg)
+{
+ u16 tmp;
+
+ tmp = m66592_read(m66592, M66592_INTENB0);
+ m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE,
+ M66592_INTENB0);
+ m66592_bclr(m66592, (1 << pipenum), reg);
+ m66592_write(m66592, tmp, M66592_INTENB0);
+}
+
+static void m66592_usb_connect(struct m66592 *m66592)
+{
+ m66592_bset(m66592, M66592_CTRE, M66592_INTENB0);
+ m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
+ M66592_INTENB0);
+ m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
+
+ m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG);
+}
+
+static void m66592_usb_disconnect(struct m66592 *m66592)
+{
+ m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0);
+ m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL,
+ M66592_INTENB0);
+ m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0);
+ m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+
+ m66592->gadget.speed = USB_SPEED_UNKNOWN;
+ spin_unlock(&m66592->lock);
+ m66592->driver->disconnect(&m66592->gadget);
+ spin_lock(&m66592->lock);
+
+ disable_controller(m66592);
+ INIT_LIST_HEAD(&m66592->ep[0].queue);
+}
+
+static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum)
+{
+ u16 pid = 0;
+ unsigned long offset;
+
+ if (pipenum == 0)
+ pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID;
+ else if (pipenum < M66592_MAX_NUM_PIPE) {
+ offset = get_pipectr_addr(pipenum);
+ pid = m66592_read(m66592, offset) & M66592_PID;
+ } else
+ printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+
+ return pid;
+}
+
+static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum,
+ u16 pid)
+{
+ unsigned long offset;
+
+ if (pipenum == 0)
+ m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR);
+ else if (pipenum < M66592_MAX_NUM_PIPE) {
+ offset = get_pipectr_addr(pipenum);
+ m66592_mdfy(m66592, pid, M66592_PID, offset);
+ } else
+ printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+}
+
+static inline void pipe_start(struct m66592 *m66592, u16 pipenum)
+{
+ control_reg_set_pid(m66592, pipenum, M66592_PID_BUF);
+}
+
+static inline void pipe_stop(struct m66592 *m66592, u16 pipenum)
+{
+ control_reg_set_pid(m66592, pipenum, M66592_PID_NAK);
+}
+
+static inline void pipe_stall(struct m66592 *m66592, u16 pipenum)
+{
+ control_reg_set_pid(m66592, pipenum, M66592_PID_STALL);
+}
+
+static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum)
+{
+ u16 ret = 0;
+ unsigned long offset;
+
+ if (pipenum == 0)
+ ret = m66592_read(m66592, M66592_DCPCTR);
+ else if (pipenum < M66592_MAX_NUM_PIPE) {
+ offset = get_pipectr_addr(pipenum);
+ ret = m66592_read(m66592, offset);
+ } else
+ printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum);
+
+ return ret;
+}
+
+static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum)
+{
+ unsigned long offset;
+
+ pipe_stop(m66592, pipenum);
+
+ if (pipenum == 0)
+ m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR);
+ else if (pipenum < M66592_MAX_NUM_PIPE) {
+ offset = get_pipectr_addr(pipenum);
+ m66592_bset(m66592, M66592_SQCLR, offset);
+ } else
+ printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
+}
+
+static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum)
+{
+ u16 tmp;
+ int size;
+
+ if (pipenum == 0) {
+ tmp = m66592_read(m66592, M66592_DCPCFG);
+ if ((tmp & M66592_CNTMD) != 0)
+ size = 256;
+ else {
+ tmp = m66592_read(m66592, M66592_DCPMAXP);
+ size = tmp & M66592_MAXP;
+ }
+ } else {
+ m66592_write(m66592, pipenum, M66592_PIPESEL);
+ tmp = m66592_read(m66592, M66592_PIPECFG);
+ if ((tmp & M66592_CNTMD) != 0) {
+ tmp = m66592_read(m66592, M66592_PIPEBUF);
+ size = ((tmp >> 10) + 1) * 64;
+ } else {
+ tmp = m66592_read(m66592, M66592_PIPEMAXP);
+ size = tmp & M66592_MXPS;
+ }
+ }
+
+ return size;
+}
+
+static inline void pipe_change(struct m66592 *m66592, u16 pipenum)
+{
+ struct m66592_ep *ep = m66592->pipenum2ep[pipenum];
+
+ if (ep->use_dma)
+ return;
+
+ m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel);
+
+ ndelay(450);
+
+ m66592_bset(m66592, M66592_MBW, ep->fifosel);
+}
+
+static int pipe_buffer_setting(struct m66592 *m66592,
+ struct m66592_pipe_info *info)
+{
+ u16 bufnum = 0, buf_bsize = 0;
+ u16 pipecfg = 0;
+
+ if (info->pipe == 0)
+ return -EINVAL;
+
+ m66592_write(m66592, info->pipe, M66592_PIPESEL);
+
+ if (info->dir_in)
+ pipecfg |= M66592_DIR;
+ pipecfg |= info->type;
+ pipecfg |= info->epnum;
+ switch (info->type) {
+ case M66592_INT:
+ bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT);
+ buf_bsize = 0;
+ break;
+ case M66592_BULK:
+ bufnum = m66592->bi_bufnum +
+ (info->pipe - M66592_BASE_PIPENUM_BULK) * 16;
+ m66592->bi_bufnum += 16;
+ buf_bsize = 7;
+ pipecfg |= M66592_DBLB;
+ if (!info->dir_in)
+ pipecfg |= M66592_SHTNAK;
+ break;
+ case M66592_ISO:
+ bufnum = m66592->bi_bufnum +
+ (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16;
+ m66592->bi_bufnum += 16;
+ buf_bsize = 7;
+ break;
+ }
+ if (m66592->bi_bufnum > M66592_MAX_BUFNUM) {
+ printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n",
+ m66592->bi_bufnum);
+ return -ENOMEM;
+ }
+
+ m66592_write(m66592, pipecfg, M66592_PIPECFG);
+ m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF);
+ m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP);
+ if (info->interval)
+ info->interval--;
+ m66592_write(m66592, info->interval, M66592_PIPEPERI);
+
+ return 0;
+}
+
+static void pipe_buffer_release(struct m66592 *m66592,
+ struct m66592_pipe_info *info)
+{
+ if (info->pipe == 0)
+ return;
+
+ switch (info->type) {
+ case M66592_BULK:
+ if (is_bulk_pipe(info->pipe))
+ m66592->bi_bufnum -= 16;
+ break;
+ case M66592_ISO:
+ if (is_isoc_pipe(info->pipe))
+ m66592->bi_bufnum -= 16;
+ break;
+ }
+
+ if (is_bulk_pipe(info->pipe)) {
+ m66592->bulk--;
+ } else if (is_interrupt_pipe(info->pipe))
+ m66592->interrupt--;
+ else if (is_isoc_pipe(info->pipe)) {
+ m66592->isochronous--;
+ if (info->type == M66592_BULK)
+ m66592->bulk--;
+ } else
+ printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n",
+ info->pipe);
+}
+
+static void pipe_initialize(struct m66592_ep *ep)
+{
+ struct m66592 *m66592 = ep->m66592;
+
+ m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel);
+
+ m66592_write(m66592, M66592_ACLRM, ep->pipectr);
+ m66592_write(m66592, 0, ep->pipectr);
+ m66592_write(m66592, M66592_SQCLR, ep->pipectr);
+ if (ep->use_dma) {
+ m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel);
+
+ ndelay(450);
+
+ m66592_bset(m66592, M66592_MBW, ep->fifosel);
+ }
+}
+
+static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep,
+ const struct usb_endpoint_descriptor *desc,
+ u16 pipenum, int dma)
+{
+ if ((pipenum != 0) && dma) {
+ if (m66592->num_dma == 0) {
+ m66592->num_dma++;
+ ep->use_dma = 1;
+ ep->fifoaddr = M66592_D0FIFO;
+ ep->fifosel = M66592_D0FIFOSEL;
+ ep->fifoctr = M66592_D0FIFOCTR;
+ ep->fifotrn = M66592_D0FIFOTRN;
+ } else if (m66592->num_dma == 1) {
+ m66592->num_dma++;
+ ep->use_dma = 1;
+ ep->fifoaddr = M66592_D1FIFO;
+ ep->fifosel = M66592_D1FIFOSEL;
+ ep->fifoctr = M66592_D1FIFOCTR;
+ ep->fifotrn = M66592_D1FIFOTRN;
+ } else {
+ ep->use_dma = 0;
+ ep->fifoaddr = M66592_CFIFO;
+ ep->fifosel = M66592_CFIFOSEL;
+ ep->fifoctr = M66592_CFIFOCTR;
+ ep->fifotrn = 0;
+ }
+ } else {
+ ep->use_dma = 0;
+ ep->fifoaddr = M66592_CFIFO;
+ ep->fifosel = M66592_CFIFOSEL;
+ ep->fifoctr = M66592_CFIFOCTR;
+ ep->fifotrn = 0;
+ }
+
+ ep->pipectr = get_pipectr_addr(pipenum);
+ ep->pipenum = pipenum;
+ ep->ep.maxpacket = desc->wMaxPacketSize;
+ m66592->pipenum2ep[pipenum] = ep;
+ m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep;
+ INIT_LIST_HEAD(&ep->queue);
+}
+
+static void m66592_ep_release(struct m66592_ep *ep)
+{
+ struct m66592 *m66592 = ep->m66592;
+ u16 pipenum = ep->pipenum;
+
+ if (pipenum == 0)
+ return;
+
+ if (ep->use_dma)
+ m66592->num_dma--;
+ ep->pipenum = 0;
+ ep->busy = 0;
+ ep->use_dma = 0;
+}
+
+static int alloc_pipe_config(struct m66592_ep *ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct m66592 *m66592 = ep->m66592;
+ struct m66592_pipe_info info;
+ int dma = 0;
+ int *counter;
+ int ret;
+
+ ep->desc = desc;
+
+ BUG_ON(ep->pipenum);
+
+ switch(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_BULK:
+ if (m66592->bulk >= M66592_MAX_NUM_BULK) {
+ if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
+ printk(KERN_ERR "bulk pipe is insufficient\n");
+ return -ENODEV;
+ } else {
+ info.pipe = M66592_BASE_PIPENUM_ISOC +
+ m66592->isochronous;
+ counter = &m66592->isochronous;
+ }
+ } else {
+ info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk;
+ counter = &m66592->bulk;
+ }
+ info.type = M66592_BULK;
+ dma = 1;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ if (m66592->interrupt >= M66592_MAX_NUM_INT) {
+ printk(KERN_ERR "interrupt pipe is insufficient\n");
+ return -ENODEV;
+ }
+ info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt;
+ info.type = M66592_INT;
+ counter = &m66592->interrupt;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (m66592->isochronous >= M66592_MAX_NUM_ISOC) {
+ printk(KERN_ERR "isochronous pipe is insufficient\n");
+ return -ENODEV;
+ }
+ info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous;
+ info.type = M66592_ISO;
+ counter = &m66592->isochronous;
+ break;
+ default:
+ printk(KERN_ERR "unexpect xfer type\n");
+ return -EINVAL;
+ }
+ ep->type = info.type;
+
+ info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ info.maxpacket = desc->wMaxPacketSize;
+ info.interval = desc->bInterval;
+ if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ info.dir_in = 1;
+ else
+ info.dir_in = 0;
+
+ ret = pipe_buffer_setting(m66592, &info);
+ if (ret < 0) {
+ printk(KERN_ERR "pipe_buffer_setting fail\n");
+ return ret;
+ }
+
+ (*counter)++;
+ if ((counter == &m66592->isochronous) && info.type == M66592_BULK)
+ m66592->bulk++;
+
+ m66592_ep_setting(m66592, ep, desc, info.pipe, dma);
+ pipe_initialize(ep);
+
+ return 0;
+}
+
+static int free_pipe_config(struct m66592_ep *ep)
+{
+ struct m66592 *m66592 = ep->m66592;
+ struct m66592_pipe_info info;
+
+ info.pipe = ep->pipenum;
+ info.type = ep->type;
+ pipe_buffer_release(m66592, &info);
+ m66592_ep_release(ep);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+static void pipe_irq_enable(struct m66592 *m66592, u16 pipenum)
+{
+ enable_irq_ready(m66592, pipenum);
+ enable_irq_nrdy(m66592, pipenum);
+}
+
+static void pipe_irq_disable(struct m66592 *m66592, u16 pipenum)
+{
+ disable_irq_ready(m66592, pipenum);
+ disable_irq_nrdy(m66592, pipenum);
+}
+
+/* if complete is true, gadget driver complete function is not call */
+static void control_end(struct m66592 *m66592, unsigned ccpl)
+{
+ m66592->ep[0].internal_ccpl = ccpl;
+ pipe_start(m66592, 0);
+ m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR);
+}
+
+static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+ struct m66592 *m66592 = ep->m66592;
+
+ pipe_change(m66592, ep->pipenum);
+ m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0,
+ (M66592_ISEL | M66592_CURPIPE),
+ M66592_CFIFOSEL);
+ m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+ if (req->req.length == 0) {
+ m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+ pipe_start(m66592, 0);
+ transfer_complete(ep, req, 0);
+ } else {
+ m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
+ irq_ep0_write(ep, req);
+ }
+}
+
+static void start_packet_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+ struct m66592 *m66592 = ep->m66592;
+ u16 tmp;
+
+ pipe_change(m66592, ep->pipenum);
+ disable_irq_empty(m66592, ep->pipenum);
+ pipe_start(m66592, ep->pipenum);
+
+ tmp = m66592_read(m66592, ep->fifoctr);
+ if (unlikely((tmp & M66592_FRDY) == 0))
+ pipe_irq_enable(m66592, ep->pipenum);
+ else
+ irq_packet_write(ep, req);
+}
+
+static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req)
+{
+ struct m66592 *m66592 = ep->m66592;
+ u16 pipenum = ep->pipenum;
+
+ if (ep->pipenum == 0) {
+ m66592_mdfy(m66592, M66592_PIPE0,
+ (M66592_ISEL | M66592_CURPIPE),
+ M66592_CFIFOSEL);
+ m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+ pipe_start(m66592, pipenum);
+ pipe_irq_enable(m66592, pipenum);
+ } else {
+ if (ep->use_dma) {
+ m66592_bset(m66592, M66592_TRCLR, ep->fifosel);
+ pipe_change(m66592, pipenum);
+ m66592_bset(m66592, M66592_TRENB, ep->fifosel);
+ m66592_write(m66592,
+ (req->req.length + ep->ep.maxpacket - 1) /
+ ep->ep.maxpacket, ep->fifotrn);
+ }
+ pipe_start(m66592, pipenum); /* trigger once */
+ pipe_irq_enable(m66592, pipenum);
+ }
+}
+
+static void start_packet(struct m66592_ep *ep, struct m66592_request *req)
+{
+ if (ep->desc->bEndpointAddress & USB_DIR_IN)
+ start_packet_write(ep, req);
+ else
+ start_packet_read(ep, req);
+}
+
+static void start_ep0(struct m66592_ep *ep, struct m66592_request *req)
+{
+ u16 ctsq;
+
+ ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ;
+
+ switch (ctsq) {
+ case M66592_CS_RDDS:
+ start_ep0_write(ep, req);
+ break;
+ case M66592_CS_WRDS:
+ start_packet_read(ep, req);
+ break;
+
+ case M66592_CS_WRND:
+ control_end(ep->m66592, 0);
+ break;
+ default:
+ printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq);
+ break;
+ }
+}
+
+static void init_controller(struct m66592 *m66592)
+{
+ m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND),
+ M66592_PINCFG);
+ m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */
+ m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG);
+
+ m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG);
+ m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG);
+ m66592_bset(m66592, M66592_USBE, M66592_SYSCFG);
+
+ m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+
+ msleep(3);
+
+ m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+
+ msleep(1);
+
+ m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+
+ m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1);
+ m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR,
+ M66592_DMA0CFG);
+}
+
+static void disable_controller(struct m66592 *m66592)
+{
+ m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG);
+ udelay(1);
+ m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG);
+ udelay(1);
+ m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG);
+ udelay(1);
+ m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG);
+}
+
+static void m66592_start_xclock(struct m66592 *m66592)
+{
+ u16 tmp;
+
+ tmp = m66592_read(m66592, M66592_SYSCFG);
+ if (!(tmp & M66592_XCKE))
+ m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG);
+}
+
+/*-------------------------------------------------------------------------*/
+static void transfer_complete(struct m66592_ep *ep,
+ struct m66592_request *req,
+ int status)
+{
+ int restart = 0;
+
+ if (unlikely(ep->pipenum == 0)) {
+ if (ep->internal_ccpl) {
+ ep->internal_ccpl = 0;
+ return;
+ }
+ }
+
+ list_del_init(&req->queue);
+ if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
+ req->req.status = -ESHUTDOWN;
+ else
+ req->req.status = status;
+
+ if (!list_empty(&ep->queue))
+ restart = 1;
+
+ if (likely(req->req.complete))
+ req->req.complete(&ep->ep, &req->req);
+
+ if (restart) {
+ req = list_entry(ep->queue.next, struct m66592_request, queue);
+ if (ep->desc)
+ start_packet(ep, req);
+ }
+}
+
+static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+ int i;
+ volatile u16 tmp;
+ unsigned bufsize;
+ size_t size;
+ void *buf;
+ u16 pipenum = ep->pipenum;
+ struct m66592 *m66592 = ep->m66592;
+
+ pipe_change(m66592, pipenum);
+ m66592_bset(m66592, M66592_ISEL, ep->fifosel);
+
+ i = 0;
+ do {
+ tmp = m66592_read(m66592, ep->fifoctr);
+ if (i++ > 100000) {
+ printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus"
+ "conflict. please power off this controller.");
+ return;
+ }
+ ndelay(1);
+ } while ((tmp & M66592_FRDY) == 0);
+
+ /* prepare parameters */
+ bufsize = get_buffer_size(m66592, pipenum);
+ buf = req->req.buf + req->req.actual;
+ size = min(bufsize, req->req.length - req->req.actual);
+
+ /* write fifo */
+ if (req->req.buf) {
+ if (size > 0)
+ m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
+ if ((size == 0) || ((size % ep->ep.maxpacket) != 0))
+ m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+ }
+
+ /* update parameters */
+ req->req.actual += size;
+
+ /* check transfer finish */
+ if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+ (size % ep->ep.maxpacket) || (size == 0)) {
+ disable_irq_ready(m66592, pipenum);
+ disable_irq_empty(m66592, pipenum);
+ } else {
+ disable_irq_ready(m66592, pipenum);
+ enable_irq_empty(m66592, pipenum);
+ }
+ pipe_start(m66592, pipenum);
+}
+
+static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req)
+{
+ u16 tmp;
+ unsigned bufsize;
+ size_t size;
+ void *buf;
+ u16 pipenum = ep->pipenum;
+ struct m66592 *m66592 = ep->m66592;
+
+ pipe_change(m66592, pipenum);
+ tmp = m66592_read(m66592, ep->fifoctr);
+ if (unlikely((tmp & M66592_FRDY) == 0)) {
+ pipe_stop(m66592, pipenum);
+ pipe_irq_disable(m66592, pipenum);
+ printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum);
+ return;
+ }
+
+ /* prepare parameters */
+ bufsize = get_buffer_size(m66592, pipenum);
+ buf = req->req.buf + req->req.actual;
+ size = min(bufsize, req->req.length - req->req.actual);
+
+ /* write fifo */
+ if (req->req.buf) {
+ m66592_write_fifo(m66592, ep->fifoaddr, buf, size);
+ if ((size == 0) || ((size % ep->ep.maxpacket) != 0) ||
+ ((bufsize != ep->ep.maxpacket) && (bufsize > size)))
+ m66592_bset(m66592, M66592_BVAL, ep->fifoctr);
+ }
+
+ /* update parameters */
+ req->req.actual += size;
+ /* check transfer finish */
+ if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+ (size % ep->ep.maxpacket) || (size == 0)) {
+ disable_irq_ready(m66592, pipenum);
+ enable_irq_empty(m66592, pipenum);
+ } else {
+ disable_irq_empty(m66592, pipenum);
+ pipe_irq_enable(m66592, pipenum);
+ }
+}
+
+static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req)
+{
+ u16 tmp;
+ int rcv_len, bufsize, req_len;
+ int size;
+ void *buf;
+ u16 pipenum = ep->pipenum;
+ struct m66592 *m66592 = ep->m66592;
+ int finish = 0;
+
+ pipe_change(m66592, pipenum);
+ tmp = m66592_read(m66592, ep->fifoctr);
+ if (unlikely((tmp & M66592_FRDY) == 0)) {
+ req->req.status = -EPIPE;
+ pipe_stop(m66592, pipenum);
+ pipe_irq_disable(m66592, pipenum);
+ printk(KERN_ERR "read fifo not ready");
+ return;
+ }
+
+ /* prepare parameters */
+ rcv_len = tmp & M66592_DTLN;
+ bufsize = get_buffer_size(m66592, pipenum);
+
+ buf = req->req.buf + req->req.actual;
+ req_len = req->req.length - req->req.actual;
+ if (rcv_len < bufsize)
+ size = min(rcv_len, req_len);
+ else
+ size = min(bufsize, req_len);
+
+ /* update parameters */
+ req->req.actual += size;
+
+ /* check transfer finish */
+ if ((!req->req.zero && (req->req.actual == req->req.length)) ||
+ (size % ep->ep.maxpacket) || (size == 0)) {
+ pipe_stop(m66592, pipenum);
+ pipe_irq_disable(m66592, pipenum);
+ finish = 1;
+ }
+
+ /* read fifo */
+ if (req->req.buf) {
+ if (size == 0)
+ m66592_write(m66592, M66592_BCLR, ep->fifoctr);
+ else
+ m66592_read_fifo(m66592, ep->fifoaddr, buf, size);
+ }
+
+ if ((ep->pipenum != 0) && finish)
+ transfer_complete(ep, req, 0);
+}
+
+static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb)
+{
+ u16 check;
+ u16 pipenum;
+ struct m66592_ep *ep;
+ struct m66592_request *req;
+
+ if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) {
+ m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS);
+ m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE,
+ M66592_CFIFOSEL);
+
+ ep = &m66592->ep[0];
+ req = list_entry(ep->queue.next, struct m66592_request, queue);
+ irq_packet_read(ep, req);
+ } else {
+ for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
+ check = 1 << pipenum;
+ if ((status & check) && (enb & check)) {
+ m66592_write(m66592, ~check, M66592_BRDYSTS);
+ ep = m66592->pipenum2ep[pipenum];
+ req = list_entry(ep->queue.next,
+ struct m66592_request, queue);
+ if (ep->desc->bEndpointAddress & USB_DIR_IN)
+ irq_packet_write(ep, req);
+ else
+ irq_packet_read(ep, req);
+ }
+ }
+ }
+}
+
+static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb)
+{
+ u16 tmp;
+ u16 check;
+ u16 pipenum;
+ struct m66592_ep *ep;
+ struct m66592_request *req;
+
+ if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) {
+ m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS);
+
+ ep = &m66592->ep[0];
+ req = list_entry(ep->queue.next, struct m66592_request, queue);
+ irq_ep0_write(ep, req);
+ } else {
+ for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) {
+ check = 1 << pipenum;
+ if ((status & check) && (enb & check)) {
+ m66592_write(m66592, ~check, M66592_BEMPSTS);
+ tmp = control_reg_get(m66592, pipenum);
+ if ((tmp & M66592_INBUFM) == 0) {
+ disable_irq_empty(m66592, pipenum);
+ pipe_irq_disable(m66592, pipenum);
+ pipe_stop(m66592, pipenum);
+ ep = m66592->pipenum2ep[pipenum];
+ req = list_entry(ep->queue.next,
+ struct m66592_request,
+ queue);
+ if (!list_empty(&ep->queue))
+ transfer_complete(ep, req, 0);
+ }
+ }
+ }
+ }
+}
+
+static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+ struct m66592_ep *ep;
+ u16 pid;
+ u16 status = 0;
+
+ switch (ctrl->bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ status = 1; /* selfpower */
+ break;
+ case USB_RECIP_INTERFACE:
+ status = 0;
+ break;
+ case USB_RECIP_ENDPOINT:
+ ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+ pid = control_reg_get_pid(m66592, ep->pipenum);
+ if (pid == M66592_PID_STALL)
+ status = 1;
+ else
+ status = 0;
+ break;
+ default:
+ pipe_stall(m66592, 0);
+ return; /* exit */
+ }
+
+ *m66592->ep0_buf = status;
+ m66592->ep0_req->buf = m66592->ep0_buf;
+ m66592->ep0_req->length = 2;
+ /* AV: what happens if we get called again before that gets through? */
+ m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL);
+}
+
+static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+ switch (ctrl->bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ control_end(m66592, 1);
+ break;
+ case USB_RECIP_INTERFACE:
+ control_end(m66592, 1);
+ break;
+ case USB_RECIP_ENDPOINT: {
+ struct m66592_ep *ep;
+ struct m66592_request *req;
+
+ ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+ pipe_stop(m66592, ep->pipenum);
+ control_reg_sqclr(m66592, ep->pipenum);
+
+ control_end(m66592, 1);
+
+ req = list_entry(ep->queue.next,
+ struct m66592_request, queue);
+ if (ep->busy) {
+ ep->busy = 0;
+ if (list_empty(&ep->queue))
+ break;
+ start_packet(ep, req);
+ } else if (!list_empty(&ep->queue))
+ pipe_start(m66592, ep->pipenum);
+ }
+ break;
+ default:
+ pipe_stall(m66592, 0);
+ break;
+ }
+}
+
+static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+
+ switch (ctrl->bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ control_end(m66592, 1);
+ break;
+ case USB_RECIP_INTERFACE:
+ control_end(m66592, 1);
+ break;
+ case USB_RECIP_ENDPOINT: {
+ struct m66592_ep *ep;
+
+ ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK];
+ pipe_stall(m66592, ep->pipenum);
+
+ control_end(m66592, 1);
+ }
+ break;
+ default:
+ pipe_stall(m66592, 0);
+ break;
+ }
+}
+
+/* if return value is true, call class driver's setup() */
+static int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
+{
+ u16 *p = (u16 *)ctrl;
+ unsigned long offset = M66592_USBREQ;
+ int i, ret = 0;
+
+ /* read fifo */
+ m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0);
+
+ for (i = 0; i < 4; i++)
+ p[i] = m66592_read(m66592, offset + i*2);
+
+ /* check request */
+ if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+ switch (ctrl->bRequest) {
+ case USB_REQ_GET_STATUS:
+ get_status(m66592, ctrl);
+ break;
+ case USB_REQ_CLEAR_FEATURE:
+ clear_feature(m66592, ctrl);
+ break;
+ case USB_REQ_SET_FEATURE:
+ set_feature(m66592, ctrl);
+ break;
+ default:
+ ret = 1;
+ break;
+ }
+ } else
+ ret = 1;
+ return ret;
+}
+
+static void m66592_update_usb_speed(struct m66592 *m66592)
+{
+ u16 speed = get_usb_speed(m66592);
+
+ switch (speed) {
+ case M66592_HSMODE:
+ m66592->gadget.speed = USB_SPEED_HIGH;
+ break;
+ case M66592_FSMODE:
+ m66592->gadget.speed = USB_SPEED_FULL;
+ break;
+ default:
+ m66592->gadget.speed = USB_SPEED_UNKNOWN;
+ printk(KERN_ERR "USB speed unknown\n");
+ }
+}
+
+static void irq_device_state(struct m66592 *m66592)
+{
+ u16 dvsq;
+
+ dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ;
+ m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0);
+
+ if (dvsq == M66592_DS_DFLT) { /* bus reset */
+ m66592->driver->disconnect(&m66592->gadget);
+ m66592_update_usb_speed(m66592);
+ }
+ if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG)
+ m66592_update_usb_speed(m66592);
+ if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS) &&
+ m66592->gadget.speed == USB_SPEED_UNKNOWN)
+ m66592_update_usb_speed(m66592);
+
+ m66592->old_dvsq = dvsq;
+}
+
+static void irq_control_stage(struct m66592 *m66592)
+{
+ struct usb_ctrlrequest ctrl;
+ u16 ctsq;
+
+ ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ;
+ m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0);
+
+ switch (ctsq) {
+ case M66592_CS_IDST: {
+ struct m66592_ep *ep;
+ struct m66592_request *req;
+ ep = &m66592->ep[0];
+ req = list_entry(ep->queue.next, struct m66592_request, queue);
+ transfer_complete(ep, req, 0);
+ }
+ break;
+
+ case M66592_CS_RDDS:
+ case M66592_CS_WRDS:
+ case M66592_CS_WRND:
+ if (setup_packet(m66592, &ctrl)) {
+ if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0)
+ pipe_stall(m66592, 0);
+ }
+ break;
+ case M66592_CS_RDSS:
+ case M66592_CS_WRSS:
+ control_end(m66592, 0);
+ break;
+ default:
+ printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq);
+ break;
+ }
+}
+
+static irqreturn_t m66592_irq(int irq, void *_m66592)
+{
+ struct m66592 *m66592 = _m66592;
+ u16 intsts0;
+ u16 intenb0;
+ u16 brdysts, nrdysts, bempsts;
+ u16 brdyenb, nrdyenb, bempenb;
+ u16 savepipe;
+ u16 mask0;
+
+ intsts0 = m66592_read(m66592, M66592_INTSTS0);
+ intenb0 = m66592_read(m66592, M66592_INTENB0);
+
+ savepipe = m66592_read(m66592, M66592_CFIFOSEL);
+
+ mask0 = intsts0 & intenb0;
+ if (mask0) {
+ brdysts = m66592_read(m66592, M66592_BRDYSTS);
+ nrdysts = m66592_read(m66592, M66592_NRDYSTS);
+ bempsts = m66592_read(m66592, M66592_BEMPSTS);
+ brdyenb = m66592_read(m66592, M66592_BRDYENB);
+ nrdyenb = m66592_read(m66592, M66592_NRDYENB);
+ bempenb = m66592_read(m66592, M66592_BEMPENB);
+
+ if (mask0 & M66592_VBINT) {
+ m66592_write(m66592, (u16)~M66592_VBINT,
+ M66592_INTSTS0);
+ m66592_start_xclock(m66592);
+
+ /* start vbus sampling */
+ m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0)
+ & M66592_VBSTS;
+ m66592->scount = M66592_MAX_SAMPLING;
+
+ mod_timer(&m66592->timer,
+ jiffies + msecs_to_jiffies(50));
+ }
+ if (intsts0 & M66592_DVSQ)
+ irq_device_state(m66592);
+
+ if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE) &&
+ (brdysts & brdyenb)) {
+ irq_pipe_ready(m66592, brdysts, brdyenb);
+ }
+ if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE) &&
+ (bempsts & bempenb)) {
+ irq_pipe_empty(m66592, bempsts, bempenb);
+ }
+
+ if (intsts0 & M66592_CTRT)
+ irq_control_stage(m66592);
+ }
+
+ m66592_write(m66592, savepipe, M66592_CFIFOSEL);
+
+ return IRQ_HANDLED;
+}
+
+static void m66592_timer(unsigned long _m66592)
+{
+ struct m66592 *m66592 = (struct m66592 *)_m66592;
+ unsigned long flags;
+ u16 tmp;
+
+ spin_lock_irqsave(&m66592->lock, flags);
+ tmp = m66592_read(m66592, M66592_SYSCFG);
+ if (!(tmp & M66592_RCKE)) {
+ m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG);
+ udelay(10);
+ m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG);
+ }
+ if (m66592->scount > 0) {
+ tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS;
+ if (tmp == m66592->old_vbus) {
+ m66592->scount--;
+ if (m66592->scount == 0) {
+ if (tmp == M66592_VBSTS)
+ m66592_usb_connect(m66592);
+ else
+ m66592_usb_disconnect(m66592);
+ } else {
+ mod_timer(&m66592->timer,
+ jiffies + msecs_to_jiffies(50));
+ }
+ } else {
+ m66592->scount = M66592_MAX_SAMPLING;
+ m66592->old_vbus = tmp;
+ mod_timer(&m66592->timer,
+ jiffies + msecs_to_jiffies(50));
+ }
+ }
+ spin_unlock_irqrestore(&m66592->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+static int m66592_enable(struct usb_ep *_ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct m66592_ep *ep;
+
+ ep = container_of(_ep, struct m66592_ep, ep);
+ return alloc_pipe_config(ep, desc);
+}
+
+static int m66592_disable(struct usb_ep *_ep)
+{
+ struct m66592_ep *ep;
+ struct m66592_request *req;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct m66592_ep, ep);
+ BUG_ON(!ep);
+
+ while (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct m66592_request, queue);
+ spin_lock_irqsave(&ep->m66592->lock, flags);
+ transfer_complete(ep, req, -ECONNRESET);
+ spin_unlock_irqrestore(&ep->m66592->lock, flags);
+ }
+
+ pipe_irq_disable(ep->m66592, ep->pipenum);
+ return free_pipe_config(ep);
+}
+
+static struct usb_request *m66592_alloc_request(struct usb_ep *_ep,
+ gfp_t gfp_flags)
+{
+ struct m66592_request *req;
+
+ req = kzalloc(sizeof(struct m66592_request), gfp_flags);
+ if (!req)
+ return NULL;
+
+ INIT_LIST_HEAD(&req->queue);
+
+ return &req->req;
+}
+
+static void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct m66592_request *req;
+
+ req = container_of(_req, struct m66592_request, req);
+ kfree(req);
+}
+
+static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
+ gfp_t gfp_flags)
+{
+ struct m66592_ep *ep;
+ struct m66592_request *req;
+ unsigned long flags;
+ int request = 0;
+
+ ep = container_of(_ep, struct m66592_ep, ep);
+ req = container_of(_req, struct m66592_request, req);
+
+ if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN)
+ return -ESHUTDOWN;
+
+ spin_lock_irqsave(&ep->m66592->lock, flags);
+
+ if (list_empty(&ep->queue))
+ request = 1;
+
+ list_add_tail(&req->queue, &ep->queue);
+ req->req.actual = 0;
+ req->req.status = -EINPROGRESS;
+
+ if (ep->desc == 0) /* control */
+ start_ep0(ep, req);
+ else {
+ if (request && !ep->busy)
+ start_packet(ep, req);
+ }
+
+ spin_unlock_irqrestore(&ep->m66592->lock, flags);
+
+ return 0;
+}
+
+static int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct m66592_ep *ep;
+ struct m66592_request *req;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct m66592_ep, ep);
+ req = container_of(_req, struct m66592_request, req);
+
+ spin_lock_irqsave(&ep->m66592->lock, flags);
+ if (!list_empty(&ep->queue))
+ transfer_complete(ep, req, -ECONNRESET);
+ spin_unlock_irqrestore(&ep->m66592->lock, flags);
+
+ return 0;
+}
+
+static int m66592_set_halt(struct usb_ep *_ep, int value)
+{
+ struct m66592_ep *ep;
+ struct m66592_request *req;
+ unsigned long flags;
+ int ret = 0;
+
+ ep = container_of(_ep, struct m66592_ep, ep);
+ req = list_entry(ep->queue.next, struct m66592_request, queue);
+
+ spin_lock_irqsave(&ep->m66592->lock, flags);
+ if (!list_empty(&ep->queue)) {
+ ret = -EAGAIN;
+ goto out;
+ }
+ if (value) {
+ ep->busy = 1;
+ pipe_stall(ep->m66592, ep->pipenum);
+ } else {
+ ep->busy = 0;
+ pipe_stop(ep->m66592, ep->pipenum);
+ }
+
+out:
+ spin_unlock_irqrestore(&ep->m66592->lock, flags);
+ return ret;
+}
+
+static int m66592_fifo_status(struct usb_ep *_ep)
+{
+ return -EOPNOTSUPP;
+}
+
+static void m66592_fifo_flush(struct usb_ep *_ep)
+{
+ struct m66592_ep *ep;
+ unsigned long flags;
+
+ ep = container_of(_ep, struct m66592_ep, ep);
+ spin_lock_irqsave(&ep->m66592->lock, flags);
+ if (list_empty(&ep->queue) && !ep->busy) {
+ pipe_stop(ep->m66592, ep->pipenum);
+ m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr);
+ }
+ spin_unlock_irqrestore(&ep->m66592->lock, flags);
+}
+
+static struct usb_ep_ops m66592_ep_ops = {
+ .enable = m66592_enable,
+ .disable = m66592_disable,
+
+ .alloc_request = m66592_alloc_request,
+ .free_request = m66592_free_request,
+
+ .queue = m66592_queue,
+ .dequeue = m66592_dequeue,
+
+ .set_halt = m66592_set_halt,
+ .fifo_status = m66592_fifo_status,
+ .fifo_flush = m66592_fifo_flush,
+};
+
+/*-------------------------------------------------------------------------*/
+static struct m66592 *the_controller;
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+ struct m66592 *m66592 = the_controller;
+ int retval;
+
+ if (!driver ||
+ driver->speed != USB_SPEED_HIGH ||
+ !driver->bind ||
+ !driver->unbind ||
+ !driver->setup)
+ return -EINVAL;
+ if (!m66592)
+ return -ENODEV;
+ if (m66592->driver)
+ return -EBUSY;
+
+ /* hook up the driver */
+ driver->driver.bus = NULL;
+ m66592->driver = driver;
+ m66592->gadget.dev.driver = &driver->driver;
+
+ retval = device_add(&m66592->gadget.dev);
+ if (retval) {
+ printk(KERN_ERR "device_add error (%d)\n", retval);
+ goto error;
+ }
+
+ retval = driver->bind (&m66592->gadget);
+ if (retval) {
+ printk(KERN_ERR "bind to driver error (%d)\n", retval);
+ device_del(&m66592->gadget.dev);
+ goto error;
+ }
+
+ m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
+ if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
+ m66592_start_xclock(m66592);
+ /* start vbus sampling */
+ m66592->old_vbus = m66592_read(m66592,
+ M66592_INTSTS0) & M66592_VBSTS;
+ m66592->scount = M66592_MAX_SAMPLING;
+ mod_timer(&m66592->timer,
+ jiffies + msecs_to_jiffies(50));
+ }
+
+ return 0;
+
+error:
+ m66592->driver = NULL;
+ m66592->gadget.dev.driver = NULL;
+
+ return retval;
+}
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+ struct m66592 *m66592 = the_controller;
+ unsigned long flags;
+
+ spin_lock_irqsave(&m66592->lock, flags);
+ if (m66592->gadget.speed != USB_SPEED_UNKNOWN)
+ m66592_usb_disconnect(m66592);
+ spin_unlock_irqrestore(&m66592->lock, flags);
+
+ m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
+
+ driver->unbind(&m66592->gadget);
+
+ init_controller(m66592);
+ disable_controller(m66592);
+
+ device_del(&m66592->gadget.dev);
+ m66592->driver = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------*/
+static int m66592_get_frame(struct usb_gadget *_gadget)
+{
+ struct m66592 *m66592 = gadget_to_m66592(_gadget);
+ return m66592_read(m66592, M66592_FRMNUM) & 0x03FF;
+}
+
+static struct usb_gadget_ops m66592_gadget_ops = {
+ .get_frame = m66592_get_frame,
+};
+
+#if defined(CONFIG_PM)
+static int m66592_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ pdev->dev.power.power_state = state;
+ return 0;
+}
+
+static int m66592_resume(struct platform_device *pdev)
+{
+ pdev->dev.power.power_state = PMSG_ON;
+ return 0;
+}
+#else /* if defined(CONFIG_PM) */
+#define m66592_suspend NULL
+#define m66592_resume NULL
+#endif
+
+static int __init_or_module m66592_remove(struct platform_device *pdev)
+{
+ struct m66592 *m66592 = dev_get_drvdata(&pdev->dev);
+
+ del_timer_sync(&m66592->timer);
+ iounmap(m66592->reg);
+ free_irq(platform_get_irq(pdev, 0), m66592);
+ kfree(m66592);
+ return 0;
+}
+
+#define resource_len(r) (((r)->end - (r)->start) + 1)
+static int __init m66592_probe(struct platform_device *pdev)
+{
+ struct resource *res = NULL;
+ int irq = -1;
+ void __iomem *reg = NULL;
+ struct m66592 *m66592 = NULL;
+ int ret = 0;
+ int i;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ (char *)udc_name);
+ if (!res) {
+ ret = -ENODEV;
+ printk(KERN_ERR "platform_get_resource_byname error.\n");
+ goto clean_up;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = -ENODEV;
+ printk(KERN_ERR "platform_get_irq error.\n");
+ goto clean_up;
+ }
+
+ reg = ioremap(res->start, resource_len(res));
+ if (reg == NULL) {
+ ret = -ENOMEM;
+ printk(KERN_ERR "ioremap error.\n");
+ goto clean_up;
+ }
+
+ /* initialize ucd */
+ m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
+ if (m66592 == NULL) {
+ printk(KERN_ERR "kzalloc error\n");
+ goto clean_up;
+ }
+
+ spin_lock_init(&m66592->lock);
+ dev_set_drvdata(&pdev->dev, m66592);
+
+ m66592->gadget.ops = &m66592_gadget_ops;
+ device_initialize(&m66592->gadget.dev);
+ strcpy(m66592->gadget.dev.bus_id, "gadget");
+ m66592->gadget.is_dualspeed = 1;
+ m66592->gadget.dev.parent = &pdev->dev;
+ m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
+ m66592->gadget.dev.release = pdev->dev.release;
+ m66592->gadget.name = udc_name;
+
+ init_timer(&m66592->timer);
+ m66592->timer.function = m66592_timer;
+ m66592->timer.data = (unsigned long)m66592;
+ m66592->reg = reg;
+
+ m66592->bi_bufnum = M66592_BASE_BUFNUM;
+
+ ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED,
+ udc_name, m66592);
+ if (ret < 0) {
+ printk(KERN_ERR "request_irq error (%d)\n", ret);
+ goto clean_up;
+ }
+
+ INIT_LIST_HEAD(&m66592->gadget.ep_list);
+ m66592->gadget.ep0 = &m66592->ep[0].ep;
+ INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list);
+ for (i = 0; i < M66592_MAX_NUM_PIPE; i++) {
+ struct m66592_ep *ep = &m66592->ep[i];
+
+ if (i != 0) {
+ INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list);
+ list_add_tail(&m66592->ep[i].ep.ep_list,
+ &m66592->gadget.ep_list);
+ }
+ ep->m66592 = m66592;
+ INIT_LIST_HEAD(&ep->queue);
+ ep->ep.name = m66592_ep_name[i];
+ ep->ep.ops = &m66592_ep_ops;
+ ep->ep.maxpacket = 512;
+ }
+ m66592->ep[0].ep.maxpacket = 64;
+ m66592->ep[0].pipenum = 0;
+ m66592->ep[0].fifoaddr = M66592_CFIFO;
+ m66592->ep[0].fifosel = M66592_CFIFOSEL;
+ m66592->ep[0].fifoctr = M66592_CFIFOCTR;
+ m66592->ep[0].fifotrn = 0;
+ m66592->ep[0].pipectr = get_pipectr_addr(0);
+ m66592->pipenum2ep[0] = &m66592->ep[0];
+ m66592->epaddr2ep[0] = &m66592->ep[0];
+
+ the_controller = m66592;
+
+ /* AV: leaks */
+ m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL);
+ if (m66592->ep0_req == NULL)
+ goto clean_up;
+ /* AV: leaks, and do we really need it separately allocated? */
+ m66592->ep0_buf = kzalloc(2, GFP_KERNEL);
+ if (m66592->ep0_buf == NULL)
+ goto clean_up;
+
+ init_controller(m66592);
+
+ printk("driver %s, %s\n", udc_name, DRIVER_VERSION);
+ return 0;
+
+clean_up:
+ if (m66592) {
+ if (m66592->ep0_req)
+ m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
+ kfree(m66592);
+ }
+ if (reg)
+ iounmap(reg);
+
+ return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+static struct platform_driver m66592_driver = {
+ .probe = m66592_probe,
+ .remove = m66592_remove,
+ .suspend = m66592_suspend,
+ .resume = m66592_resume,
+ .driver = {
+ .name = (char *) udc_name,
+ },
+};
+
+static int __init m66592_udc_init(void)
+{
+ return platform_driver_register(&m66592_driver);
+}
+module_init(m66592_udc_init);
+
+static void __exit m66592_udc_cleanup(void)
+{
+ platform_driver_unregister(&m66592_driver);
+}
+module_exit(m66592_udc_cleanup);
+
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h
new file mode 100644
index 00000000000..26b54f8b894
--- /dev/null
+++ b/drivers/usb/gadget/m66592-udc.h
@@ -0,0 +1,577 @@
+/*
+ * M66592 UDC (USB gadget)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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 __M66592_UDC_H__
+#define __M66592_UDC_H__
+
+#define M66592_SYSCFG 0x00
+#define M66592_XTAL 0xC000 /* b15-14: Crystal selection */
+#define M66592_XTAL48 0x8000 /* 48MHz */
+#define M66592_XTAL24 0x4000 /* 24MHz */
+#define M66592_XTAL12 0x0000 /* 12MHz */
+#define M66592_XCKE 0x2000 /* b13: External clock enable */
+#define M66592_RCKE 0x1000 /* b12: Register clock enable */
+#define M66592_PLLC 0x0800 /* b11: PLL control */
+#define M66592_SCKE 0x0400 /* b10: USB clock enable */
+#define M66592_ATCKM 0x0100 /* b8: Automatic supply functional enable */
+#define M66592_HSE 0x0080 /* b7: Hi-speed enable */
+#define M66592_DCFM 0x0040 /* b6: Controller function select */
+#define M66592_DMRPD 0x0020 /* b5: D- pull down control */
+#define M66592_DPRPU 0x0010 /* b4: D+ pull up control */
+#define M66592_FSRPC 0x0004 /* b2: Full-speed receiver enable */
+#define M66592_PCUT 0x0002 /* b1: Low power sleep enable */
+#define M66592_USBE 0x0001 /* b0: USB module operation enable */
+
+#define M66592_SYSSTS 0x02
+#define M66592_LNST 0x0003 /* b1-0: D+, D- line status */
+#define M66592_SE1 0x0003 /* SE1 */
+#define M66592_KSTS 0x0002 /* K State */
+#define M66592_JSTS 0x0001 /* J State */
+#define M66592_SE0 0x0000 /* SE0 */
+
+#define M66592_DVSTCTR 0x04
+#define M66592_WKUP 0x0100 /* b8: Remote wakeup */
+#define M66592_RWUPE 0x0080 /* b7: Remote wakeup sense */
+#define M66592_USBRST 0x0040 /* b6: USB reset enable */
+#define M66592_RESUME 0x0020 /* b5: Resume enable */
+#define M66592_UACT 0x0010 /* b4: USB bus enable */
+#define M66592_RHST 0x0003 /* b1-0: Reset handshake status */
+#define M66592_HSMODE 0x0003 /* Hi-Speed mode */
+#define M66592_FSMODE 0x0002 /* Full-Speed mode */
+#define M66592_HSPROC 0x0001 /* HS handshake is processing */
+
+#define M66592_TESTMODE 0x06
+#define M66592_UTST 0x000F /* b4-0: Test select */
+#define M66592_H_TST_PACKET 0x000C /* HOST TEST Packet */
+#define M66592_H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */
+#define M66592_H_TST_K 0x000A /* HOST TEST K */
+#define M66592_H_TST_J 0x0009 /* HOST TEST J */
+#define M66592_H_TST_NORMAL 0x0000 /* HOST Normal Mode */
+#define M66592_P_TST_PACKET 0x0004 /* PERI TEST Packet */
+#define M66592_P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */
+#define M66592_P_TST_K 0x0002 /* PERI TEST K */
+#define M66592_P_TST_J 0x0001 /* PERI TEST J */
+#define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */
+
+#define M66592_PINCFG 0x0A
+#define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */
+#define M66592_BIGEND 0x0100 /* b8: Big endian mode */
+
+#define M66592_DMA0CFG 0x0C
+#define M66592_DMA1CFG 0x0E
+#define M66592_DREQA 0x4000 /* b14: Dreq active select */
+#define M66592_BURST 0x2000 /* b13: Burst mode */
+#define M66592_DACKA 0x0400 /* b10: Dack active select */
+#define M66592_DFORM 0x0380 /* b9-7: DMA mode select */
+#define M66592_CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */
+#define M66592_CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */
+#define M66592_CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */
+#define M66592_SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */
+#define M66592_SPLIT_DACK_DSTB 0x0300 /* DACK + DSTB0 mode (SPLIT bus) */
+#define M66592_DENDA 0x0040 /* b6: Dend active select */
+#define M66592_PKTM 0x0020 /* b5: Packet mode */
+#define M66592_DENDE 0x0010 /* b4: Dend enable */
+#define M66592_OBUS 0x0004 /* b2: OUTbus mode */
+
+#define M66592_CFIFO 0x10
+#define M66592_D0FIFO 0x14
+#define M66592_D1FIFO 0x18
+
+#define M66592_CFIFOSEL 0x1E
+#define M66592_D0FIFOSEL 0x24
+#define M66592_D1FIFOSEL 0x2A
+#define M66592_RCNT 0x8000 /* b15: Read count mode */
+#define M66592_REW 0x4000 /* b14: Buffer rewind */
+#define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */
+#define M66592_DREQE 0x1000 /* b12: DREQ output enable */
+#define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO access */
+#define M66592_MBW_8 0x0000 /* 8bit */
+#define M66592_MBW_16 0x0400 /* 16bit */
+#define M66592_TRENB 0x0200 /* b9: Transaction counter enable */
+#define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */
+#define M66592_DEZPM 0x0080 /* b7: Zero-length packet additional mode */
+#define M66592_ISEL 0x0020 /* b5: DCP FIFO port direction select */
+#define M66592_CURPIPE 0x0007 /* b2-0: PIPE select */
+
+#define M66592_CFIFOCTR 0x20
+#define M66592_D0FIFOCTR 0x26
+#define M66592_D1FIFOCTR 0x2c
+#define M66592_BVAL 0x8000 /* b15: Buffer valid flag */
+#define M66592_BCLR 0x4000 /* b14: Buffer clear */
+#define M66592_FRDY 0x2000 /* b13: FIFO ready */
+#define M66592_DTLN 0x0FFF /* b11-0: FIFO received data length */
+
+#define M66592_CFIFOSIE 0x22
+#define M66592_TGL 0x8000 /* b15: Buffer toggle */
+#define M66592_SCLR 0x4000 /* b14: Buffer clear */
+#define M66592_SBUSY 0x2000 /* b13: SIE_FIFO busy */
+
+#define M66592_D0FIFOTRN 0x28
+#define M66592_D1FIFOTRN 0x2E
+#define M66592_TRNCNT 0xFFFF /* b15-0: Transaction counter */
+
+#define M66592_INTENB0 0x30
+#define M66592_VBSE 0x8000 /* b15: VBUS interrupt */
+#define M66592_RSME 0x4000 /* b14: Resume interrupt */
+#define M66592_SOFE 0x2000 /* b13: Frame update interrupt */
+#define M66592_DVSE 0x1000 /* b12: Device state transition interrupt */
+#define M66592_CTRE 0x0800 /* b11: Control transfer stage transition interrupt */
+#define M66592_BEMPE 0x0400 /* b10: Buffer empty interrupt */
+#define M66592_NRDYE 0x0200 /* b9: Buffer not ready interrupt */
+#define M66592_BRDYE 0x0100 /* b8: Buffer ready interrupt */
+#define M66592_URST 0x0080 /* b7: USB reset detected interrupt */
+#define M66592_SADR 0x0040 /* b6: Set address executed interrupt */
+#define M66592_SCFG 0x0020 /* b5: Set configuration executed interrupt */
+#define M66592_SUSP 0x0010 /* b4: Suspend detected interrupt */
+#define M66592_WDST 0x0008 /* b3: Control write data stage completed interrupt */
+#define M66592_RDST 0x0004 /* b2: Control read data stage completed interrupt */
+#define M66592_CMPL 0x0002 /* b1: Control transfer complete interrupt */
+#define M66592_SERR 0x0001 /* b0: Sequence error interrupt */
+
+#define M66592_INTENB1 0x32
+#define M66592_BCHGE 0x4000 /* b14: USB us chenge interrupt */
+#define M66592_DTCHE 0x1000 /* b12: Detach sense interrupt */
+#define M66592_SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */
+#define M66592_SACKE 0x0010 /* b4: SETUP ACK interrupt */
+#define M66592_BRDYM 0x0004 /* b2: BRDY clear timing */
+#define M66592_INTL 0x0002 /* b1: Interrupt sense select */
+#define M66592_PCSE 0x0001 /* b0: PCUT enable by CS assert */
+
+#define M66592_BRDYENB 0x36
+#define M66592_BRDYSTS 0x46
+#define M66592_BRDY7 0x0080 /* b7: PIPE7 */
+#define M66592_BRDY6 0x0040 /* b6: PIPE6 */
+#define M66592_BRDY5 0x0020 /* b5: PIPE5 */
+#define M66592_BRDY4 0x0010 /* b4: PIPE4 */
+#define M66592_BRDY3 0x0008 /* b3: PIPE3 */
+#define M66592_BRDY2 0x0004 /* b2: PIPE2 */
+#define M66592_BRDY1 0x0002 /* b1: PIPE1 */
+#define M66592_BRDY0 0x0001 /* b1: PIPE0 */
+
+#define M66592_NRDYENB 0x38
+#define M66592_NRDYSTS 0x48
+#define M66592_NRDY7 0x0080 /* b7: PIPE7 */
+#define M66592_NRDY6 0x0040 /* b6: PIPE6 */
+#define M66592_NRDY5 0x0020 /* b5: PIPE5 */
+#define M66592_NRDY4 0x0010 /* b4: PIPE4 */
+#define M66592_NRDY3 0x0008 /* b3: PIPE3 */
+#define M66592_NRDY2 0x0004 /* b2: PIPE2 */
+#define M66592_NRDY1 0x0002 /* b1: PIPE1 */
+#define M66592_NRDY0 0x0001 /* b1: PIPE0 */
+
+#define M66592_BEMPENB 0x3A
+#define M66592_BEMPSTS 0x4A
+#define M66592_BEMP7 0x0080 /* b7: PIPE7 */
+#define M66592_BEMP6 0x0040 /* b6: PIPE6 */
+#define M66592_BEMP5 0x0020 /* b5: PIPE5 */
+#define M66592_BEMP4 0x0010 /* b4: PIPE4 */
+#define M66592_BEMP3 0x0008 /* b3: PIPE3 */
+#define M66592_BEMP2 0x0004 /* b2: PIPE2 */
+#define M66592_BEMP1 0x0002 /* b1: PIPE1 */
+#define M66592_BEMP0 0x0001 /* b0: PIPE0 */
+
+#define M66592_SOFCFG 0x3C
+#define M66592_SOFM 0x000C /* b3-2: SOF palse mode */
+#define M66592_SOF_125US 0x0008 /* SOF OUT 125us uFrame Signal */
+#define M66592_SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */
+#define M66592_SOF_DISABLE 0x0000 /* SOF OUT Disable */
+
+#define M66592_INTSTS0 0x40
+#define M66592_VBINT 0x8000 /* b15: VBUS interrupt */
+#define M66592_RESM 0x4000 /* b14: Resume interrupt */
+#define M66592_SOFR 0x2000 /* b13: SOF frame update interrupt */
+#define M66592_DVST 0x1000 /* b12: Device state transition interrupt */
+#define M66592_CTRT 0x0800 /* b11: Control transfer stage transition interrupt */
+#define M66592_BEMP 0x0400 /* b10: Buffer empty interrupt */
+#define M66592_NRDY 0x0200 /* b9: Buffer not ready interrupt */
+#define M66592_BRDY 0x0100 /* b8: Buffer ready interrupt */
+#define M66592_VBSTS 0x0080 /* b7: VBUS input port */
+#define M66592_DVSQ 0x0070 /* b6-4: Device state */
+#define M66592_DS_SPD_CNFG 0x0070 /* Suspend Configured */
+#define M66592_DS_SPD_ADDR 0x0060 /* Suspend Address */
+#define M66592_DS_SPD_DFLT 0x0050 /* Suspend Default */
+#define M66592_DS_SPD_POWR 0x0040 /* Suspend Powered */
+#define M66592_DS_SUSP 0x0040 /* Suspend */
+#define M66592_DS_CNFG 0x0030 /* Configured */
+#define M66592_DS_ADDS 0x0020 /* Address */
+#define M66592_DS_DFLT 0x0010 /* Default */
+#define M66592_DS_POWR 0x0000 /* Powered */
+#define M66592_DVSQS 0x0030 /* b5-4: Device state */
+#define M66592_VALID 0x0008 /* b3: Setup packet detected flag */
+#define M66592_CTSQ 0x0007 /* b2-0: Control transfer stage */
+#define M66592_CS_SQER 0x0006 /* Sequence error */
+#define M66592_CS_WRND 0x0005 /* Control write nodata status stage */
+#define M66592_CS_WRSS 0x0004 /* Control write status stage */
+#define M66592_CS_WRDS 0x0003 /* Control write data stage */
+#define M66592_CS_RDSS 0x0002 /* Control read status stage */
+#define M66592_CS_RDDS 0x0001 /* Control read data stage */
+#define M66592_CS_IDST 0x0000 /* Idle or setup stage */
+
+#define M66592_INTSTS1 0x42
+#define M66592_BCHG 0x4000 /* b14: USB bus chenge interrupt */
+#define M66592_DTCH 0x1000 /* b12: Detach sense interrupt */
+#define M66592_SIGN 0x0020 /* b5: SETUP IGNORE interrupt */
+#define M66592_SACK 0x0010 /* b4: SETUP ACK interrupt */
+
+#define M66592_FRMNUM 0x4C
+#define M66592_OVRN 0x8000 /* b15: Overrun error */
+#define M66592_CRCE 0x4000 /* b14: Received data error */
+#define M66592_SOFRM 0x0800 /* b11: SOF output mode */
+#define M66592_FRNM 0x07FF /* b10-0: Frame number */
+
+#define M66592_UFRMNUM 0x4E
+#define M66592_UFRNM 0x0007 /* b2-0: Micro frame number */
+
+#define M66592_RECOVER 0x50
+#define M66592_STSRECOV 0x0700 /* Status recovery */
+#define M66592_STSR_HI 0x0400 /* FULL(0) or HI(1) Speed */
+#define M66592_STSR_DEFAULT 0x0100 /* Default state */
+#define M66592_STSR_ADDRESS 0x0200 /* Address state */
+#define M66592_STSR_CONFIG 0x0300 /* Configured state */
+#define M66592_USBADDR 0x007F /* b6-0: USB address */
+
+#define M66592_USBREQ 0x54
+#define M66592_bRequest 0xFF00 /* b15-8: bRequest */
+#define M66592_GET_STATUS 0x0000
+#define M66592_CLEAR_FEATURE 0x0100
+#define M66592_ReqRESERVED 0x0200
+#define M66592_SET_FEATURE 0x0300
+#define M66592_ReqRESERVED1 0x0400
+#define M66592_SET_ADDRESS 0x0500
+#define M66592_GET_DESCRIPTOR 0x0600
+#define M66592_SET_DESCRIPTOR 0x0700
+#define M66592_GET_CONFIGURATION 0x0800
+#define M66592_SET_CONFIGURATION 0x0900
+#define M66592_GET_INTERFACE 0x0A00
+#define M66592_SET_INTERFACE 0x0B00
+#define M66592_SYNCH_FRAME 0x0C00
+#define M66592_bmRequestType 0x00FF /* b7-0: bmRequestType */
+#define M66592_bmRequestTypeDir 0x0080 /* b7 : Data transfer direction */
+#define M66592_HOST_TO_DEVICE 0x0000
+#define M66592_DEVICE_TO_HOST 0x0080
+#define M66592_bmRequestTypeType 0x0060 /* b6-5: Type */
+#define M66592_STANDARD 0x0000
+#define M66592_CLASS 0x0020
+#define M66592_VENDOR 0x0040
+#define M66592_bmRequestTypeRecip 0x001F /* b4-0: Recipient */
+#define M66592_DEVICE 0x0000
+#define M66592_INTERFACE 0x0001
+#define M66592_ENDPOINT 0x0002
+
+#define M66592_USBVAL 0x56
+#define M66592_wValue 0xFFFF /* b15-0: wValue */
+/* Standard Feature Selector */
+#define M66592_ENDPOINT_HALT 0x0000
+#define M66592_DEVICE_REMOTE_WAKEUP 0x0001
+#define M66592_TEST_MODE 0x0002
+/* Descriptor Types */
+#define M66592_DT_TYPE 0xFF00
+#define M66592_GET_DT_TYPE(v) (((v) & DT_TYPE) >> 8)
+#define M66592_DT_DEVICE 0x01
+#define M66592_DT_CONFIGURATION 0x02
+#define M66592_DT_STRING 0x03
+#define M66592_DT_INTERFACE 0x04
+#define M66592_DT_ENDPOINT 0x05
+#define M66592_DT_DEVICE_QUALIFIER 0x06
+#define M66592_DT_OTHER_SPEED_CONFIGURATION 0x07
+#define M66592_DT_INTERFACE_POWER 0x08
+#define M66592_DT_INDEX 0x00FF
+#define M66592_CONF_NUM 0x00FF
+#define M66592_ALT_SET 0x00FF
+
+#define M66592_USBINDEX 0x58
+#define M66592_wIndex 0xFFFF /* b15-0: wIndex */
+#define M66592_TEST_SELECT 0xFF00 /* b15-b8: Test Mode Selectors */
+#define M66592_TEST_J 0x0100 /* Test_J */
+#define M66592_TEST_K 0x0200 /* Test_K */
+#define M66592_TEST_SE0_NAK 0x0300 /* Test_SE0_NAK */
+#define M66592_TEST_PACKET 0x0400 /* Test_Packet */
+#define M66592_TEST_FORCE_ENABLE 0x0500 /* Test_Force_Enable */
+#define M66592_TEST_STSelectors 0x0600 /* Standard test selectors */
+#define M66592_TEST_Reserved 0x4000 /* Reserved */
+#define M66592_TEST_VSTModes 0xC000 /* Vendor-specific test modes */
+#define M66592_EP_DIR 0x0080 /* b7: Endpoint Direction */
+#define M66592_EP_DIR_IN 0x0080
+#define M66592_EP_DIR_OUT 0x0000
+
+#define M66592_USBLENG 0x5A
+#define M66592_wLength 0xFFFF /* b15-0: wLength */
+
+#define M66592_DCPCFG 0x5C
+#define M66592_CNTMD 0x0100 /* b8: Continuous transfer mode select */
+#define M66592_DIR 0x0010 /* b4: Control transfer DIR select */
+
+#define M66592_DCPMAXP 0x5E
+#define M66592_DEVSEL 0xC000 /* b15-14: Device address select */
+#define M66592_DEVICE_0 0x0000 /* Device address 0 */
+#define M66592_DEVICE_1 0x4000 /* Device address 1 */
+#define M66592_DEVICE_2 0x8000 /* Device address 2 */
+#define M66592_DEVICE_3 0xC000 /* Device address 3 */
+#define M66592_MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */
+
+#define M66592_DCPCTR 0x60
+#define M66592_BSTS 0x8000 /* b15: Buffer status */
+#define M66592_SUREQ 0x4000 /* b14: Send USB request */
+#define M66592_SQCLR 0x0100 /* b8: Sequence toggle bit clear */
+#define M66592_SQSET 0x0080 /* b7: Sequence toggle bit set */
+#define M66592_SQMON 0x0040 /* b6: Sequence toggle bit monitor */
+#define M66592_CCPL 0x0004 /* b2: Enable control transfer complete */
+#define M66592_PID 0x0003 /* b1-0: Response PID */
+#define M66592_PID_STALL 0x0002 /* STALL */
+#define M66592_PID_BUF 0x0001 /* BUF */
+#define M66592_PID_NAK 0x0000 /* NAK */
+
+#define M66592_PIPESEL 0x64
+#define M66592_PIPENM 0x0007 /* b2-0: Pipe select */
+#define M66592_PIPE0 0x0000 /* PIPE 0 */
+#define M66592_PIPE1 0x0001 /* PIPE 1 */
+#define M66592_PIPE2 0x0002 /* PIPE 2 */
+#define M66592_PIPE3 0x0003 /* PIPE 3 */
+#define M66592_PIPE4 0x0004 /* PIPE 4 */
+#define M66592_PIPE5 0x0005 /* PIPE 5 */
+#define M66592_PIPE6 0x0006 /* PIPE 6 */
+#define M66592_PIPE7 0x0007 /* PIPE 7 */
+
+#define M66592_PIPECFG 0x66
+#define M66592_TYP 0xC000 /* b15-14: Transfer type */
+#define M66592_ISO 0xC000 /* Isochronous */
+#define M66592_INT 0x8000 /* Interrupt */
+#define M66592_BULK 0x4000 /* Bulk */
+#define M66592_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */
+#define M66592_DBLB 0x0200 /* b9: Double buffer mode select */
+#define M66592_CNTMD 0x0100 /* b8: Continuous transfer mode select */
+#define M66592_SHTNAK 0x0080 /* b7: Transfer end NAK */
+#define M66592_DIR 0x0010 /* b4: Transfer direction select */
+#define M66592_DIR_H_OUT 0x0010 /* HOST OUT */
+#define M66592_DIR_P_IN 0x0010 /* PERI IN */
+#define M66592_DIR_H_IN 0x0000 /* HOST IN */
+#define M66592_DIR_P_OUT 0x0000 /* PERI OUT */
+#define M66592_EPNUM 0x000F /* b3-0: Eendpoint number select */
+#define M66592_EP1 0x0001
+#define M66592_EP2 0x0002
+#define M66592_EP3 0x0003
+#define M66592_EP4 0x0004
+#define M66592_EP5 0x0005
+#define M66592_EP6 0x0006
+#define M66592_EP7 0x0007
+#define M66592_EP8 0x0008
+#define M66592_EP9 0x0009
+#define M66592_EP10 0x000A
+#define M66592_EP11 0x000B
+#define M66592_EP12 0x000C
+#define M66592_EP13 0x000D
+#define M66592_EP14 0x000E
+#define M66592_EP15 0x000F
+
+#define M66592_PIPEBUF 0x68
+#define M66592_BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */
+#define M66592_BUF_SIZE(x) ((((x) / 64) - 1) << 10)
+#define M66592_BUFNMB 0x00FF /* b7-0: Pipe buffer number */
+
+#define M66592_PIPEMAXP 0x6A
+#define M66592_MXPS 0x07FF /* b10-0: Maxpacket size */
+
+#define M66592_PIPEPERI 0x6C
+#define M66592_IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */
+#define M66592_IITV 0x0007 /* b2-0: Isochronous interval */
+
+#define M66592_PIPE1CTR 0x70
+#define M66592_PIPE2CTR 0x72
+#define M66592_PIPE3CTR 0x74
+#define M66592_PIPE4CTR 0x76
+#define M66592_PIPE5CTR 0x78
+#define M66592_PIPE6CTR 0x7A
+#define M66592_PIPE7CTR 0x7C
+#define M66592_BSTS 0x8000 /* b15: Buffer status */
+#define M66592_INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define M66592_ACLRM 0x0200 /* b9: Out buffer auto clear mode */
+#define M66592_SQCLR 0x0100 /* b8: Sequence toggle bit clear */
+#define M66592_SQSET 0x0080 /* b7: Sequence toggle bit set */
+#define M66592_SQMON 0x0040 /* b6: Sequence toggle bit monitor */
+#define M66592_PID 0x0003 /* b1-0: Response PID */
+
+#define M66592_INVALID_REG 0x7E
+
+
+#define __iomem
+
+#define get_pipectr_addr(pipenum) (M66592_PIPE1CTR + (pipenum - 1) * 2)
+
+#define M66592_MAX_SAMPLING 10
+
+#define M66592_MAX_NUM_PIPE 8
+#define M66592_MAX_NUM_BULK 3
+#define M66592_MAX_NUM_ISOC 2
+#define M66592_MAX_NUM_INT 2
+
+#define M66592_BASE_PIPENUM_BULK 3
+#define M66592_BASE_PIPENUM_ISOC 1
+#define M66592_BASE_PIPENUM_INT 6
+
+#define M66592_BASE_BUFNUM 6
+#define M66592_MAX_BUFNUM 0x4F
+
+struct m66592_pipe_info {
+ u16 pipe;
+ u16 epnum;
+ u16 maxpacket;
+ u16 type;
+ u16 interval;
+ u16 dir_in;
+};
+
+struct m66592_request {
+ struct usb_request req;
+ struct list_head queue;
+};
+
+struct m66592_ep {
+ struct usb_ep ep;
+ struct m66592 *m66592;
+
+ struct list_head queue;
+ unsigned busy:1;
+ unsigned internal_ccpl:1; /* use only control */
+
+ /* this member can able to after m66592_enable */
+ unsigned use_dma:1;
+ u16 pipenum;
+ u16 type;
+ const struct usb_endpoint_descriptor *desc;
+ /* register address */
+ unsigned long fifoaddr;
+ unsigned long fifosel;
+ unsigned long fifoctr;
+ unsigned long fifotrn;
+ unsigned long pipectr;
+};
+
+struct m66592 {
+ spinlock_t lock;
+ void __iomem *reg;
+
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *driver;
+
+ struct m66592_ep ep[M66592_MAX_NUM_PIPE];
+ struct m66592_ep *pipenum2ep[M66592_MAX_NUM_PIPE];
+ struct m66592_ep *epaddr2ep[16];
+
+ struct usb_request *ep0_req; /* for internal request */
+ u16 *ep0_buf; /* for internal request */
+
+ struct timer_list timer;
+
+ u16 old_vbus;
+ int scount;
+
+ int old_dvsq;
+
+ /* pipe config */
+ int bulk;
+ int interrupt;
+ int isochronous;
+ int num_dma;
+ int bi_bufnum; /* bulk and isochronous's bufnum */
+};
+
+#define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget)
+#define m66592_to_gadget(m66592) (&m66592->gadget)
+
+#define is_bulk_pipe(pipenum) \
+ ((pipenum >= M66592_BASE_PIPENUM_BULK) && \
+ (pipenum < (M66592_BASE_PIPENUM_BULK + M66592_MAX_NUM_BULK)))
+#define is_interrupt_pipe(pipenum) \
+ ((pipenum >= M66592_BASE_PIPENUM_INT) && \
+ (pipenum < (M66592_BASE_PIPENUM_INT + M66592_MAX_NUM_INT)))
+#define is_isoc_pipe(pipenum) \
+ ((pipenum >= M66592_BASE_PIPENUM_ISOC) && \
+ (pipenum < (M66592_BASE_PIPENUM_ISOC + M66592_MAX_NUM_ISOC)))
+
+#define enable_irq_ready(m66592, pipenum) \
+ enable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
+#define disable_irq_ready(m66592, pipenum) \
+ disable_pipe_irq(m66592, pipenum, M66592_BRDYENB)
+#define enable_irq_empty(m66592, pipenum) \
+ enable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
+#define disable_irq_empty(m66592, pipenum) \
+ disable_pipe_irq(m66592, pipenum, M66592_BEMPENB)
+#define enable_irq_nrdy(m66592, pipenum) \
+ enable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
+#define disable_irq_nrdy(m66592, pipenum) \
+ disable_pipe_irq(m66592, pipenum, M66592_NRDYENB)
+
+/*-------------------------------------------------------------------------*/
+static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset)
+{
+ return inw((unsigned long)m66592->reg + offset);
+}
+
+static inline void m66592_read_fifo(struct m66592 *m66592,
+ unsigned long offset,
+ void *buf, unsigned long len)
+{
+ unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+
+ len = (len + 1) / 2;
+ insw(fifoaddr, buf, len);
+}
+
+static inline void m66592_write(struct m66592 *m66592, u16 val,
+ unsigned long offset)
+{
+ outw(val, (unsigned long)m66592->reg + offset);
+}
+
+static inline void m66592_write_fifo(struct m66592 *m66592,
+ unsigned long offset,
+ void *buf, unsigned long len)
+{
+ unsigned long fifoaddr = (unsigned long)m66592->reg + offset;
+ unsigned long odd = len & 0x0001;
+
+ len = len / 2;
+ outsw(fifoaddr, buf, len);
+ if (odd) {
+ unsigned char *p = buf + len*2;
+ outb(*p, fifoaddr);
+ }
+}
+
+static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat,
+ unsigned long offset)
+{
+ u16 tmp;
+ tmp = m66592_read(m66592, offset);
+ tmp = tmp & (~pat);
+ tmp = tmp | val;
+ m66592_write(m66592, tmp, offset);
+}
+
+#define m66592_bclr(m66592, val, offset) \
+ m66592_mdfy(m66592, 0, val, offset)
+#define m66592_bset(m66592, val, offset) \
+ m66592_mdfy(m66592, val, 0, offset)
+
+#endif /* ifndef __M66592_UDC_H__ */
+
+
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 52779c52b56..c3d364ecd4f 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -450,100 +450,6 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
/*-------------------------------------------------------------------------*/
-/*
- * dma-coherent memory allocation (for dma-capable endpoints)
- *
- * NOTE: the dma_*_coherent() API calls suck. Most implementations are
- * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
- * respect to calls with irqs disabled: alloc is safe, free is not.
- * We currently work around (b), but not (a).
- */
-
-static void *
-net2280_alloc_buffer (
- struct usb_ep *_ep,
- unsigned bytes,
- dma_addr_t *dma,
- gfp_t gfp_flags
-)
-{
- void *retval;
- struct net2280_ep *ep;
-
- ep = container_of (_ep, struct net2280_ep, ep);
- if (!_ep)
- return NULL;
- *dma = DMA_ADDR_INVALID;
-
- if (ep->dma)
- retval = dma_alloc_coherent(&ep->dev->pdev->dev,
- bytes, dma, gfp_flags);
- else
- retval = kmalloc(bytes, gfp_flags);
- return retval;
-}
-
-static DEFINE_SPINLOCK(buflock);
-static LIST_HEAD(buffers);
-
-struct free_record {
- struct list_head list;
- struct device *dev;
- unsigned bytes;
- dma_addr_t dma;
-};
-
-static void do_free(unsigned long ignored)
-{
- spin_lock_irq(&buflock);
- while (!list_empty(&buffers)) {
- struct free_record *buf;
-
- buf = list_entry(buffers.next, struct free_record, list);
- list_del(&buf->list);
- spin_unlock_irq(&buflock);
-
- dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
-
- spin_lock_irq(&buflock);
- }
- spin_unlock_irq(&buflock);
-}
-
-static DECLARE_TASKLET(deferred_free, do_free, 0);
-
-static void
-net2280_free_buffer (
- struct usb_ep *_ep,
- void *address,
- dma_addr_t dma,
- unsigned bytes
-) {
- /* free memory into the right allocator */
- if (dma != DMA_ADDR_INVALID) {
- struct net2280_ep *ep;
- struct free_record *buf = address;
- unsigned long flags;
-
- ep = container_of(_ep, struct net2280_ep, ep);
- if (!_ep)
- return;
-
- ep = container_of (_ep, struct net2280_ep, ep);
- buf->dev = &ep->dev->pdev->dev;
- buf->bytes = bytes;
- buf->dma = dma;
-
- spin_lock_irqsave(&buflock, flags);
- list_add_tail(&buf->list, &buffers);
- tasklet_schedule(&deferred_free);
- spin_unlock_irqrestore(&buflock, flags);
- } else
- kfree (address);
-}
-
-/*-------------------------------------------------------------------------*/
-
/* load a packet into the fifo we use for usb IN transfers.
* works for all endpoints.
*
@@ -1392,9 +1298,6 @@ static const struct usb_ep_ops net2280_ep_ops = {
.alloc_request = net2280_alloc_request,
.free_request = net2280_free_request,
- .alloc_buffer = net2280_alloc_buffer,
- .free_buffer = net2280_free_buffer,
-
.queue = net2280_queue,
.dequeue = net2280_dequeue,
@@ -2440,9 +2343,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
tmp = 0;
-#define w_value le16_to_cpup (&u.r.wValue)
-#define w_index le16_to_cpup (&u.r.wIndex)
-#define w_length le16_to_cpup (&u.r.wLength)
+#define w_value le16_to_cpu(u.r.wValue)
+#define w_index le16_to_cpu(u.r.wIndex)
+#define w_length le16_to_cpu(u.r.wLength)
/* ack the irq */
writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
@@ -2964,7 +2867,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
, &dev->pci->pcimstctl);
/* erratum 0115 shouldn't appear: Linux inits PCI_LATENCY_TIMER */
pci_set_master (pdev);
- pci_set_mwi (pdev);
+ pci_try_set_mwi (pdev);
/* ... also flushes any posted pci writes */
dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index b394e63894d..9b0f0925ddd 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -296,111 +296,6 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req)
/*-------------------------------------------------------------------------*/
-/*
- * dma-coherent memory allocation (for dma-capable endpoints)
- *
- * NOTE: the dma_*_coherent() API calls suck. Most implementations are
- * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
- * respect to calls with irqs disabled: alloc is safe, free is not.
- * We currently work around (b), but not (a).
- */
-
-static void *
-omap_alloc_buffer(
- struct usb_ep *_ep,
- unsigned bytes,
- dma_addr_t *dma,
- gfp_t gfp_flags
-)
-{
- void *retval;
- struct omap_ep *ep;
-
- if (!_ep)
- return NULL;
-
- ep = container_of(_ep, struct omap_ep, ep);
- if (use_dma && ep->has_dma) {
- static int warned;
- if (!warned && bytes < PAGE_SIZE) {
- dev_warn(ep->udc->gadget.dev.parent,
- "using dma_alloc_coherent for "
- "small allocations wastes memory\n");
- warned++;
- }
- return dma_alloc_coherent(ep->udc->gadget.dev.parent,
- bytes, dma, gfp_flags);
- }
-
- retval = kmalloc(bytes, gfp_flags);
- if (retval)
- *dma = virt_to_phys(retval);
- return retval;
-}
-
-static DEFINE_SPINLOCK(buflock);
-static LIST_HEAD(buffers);
-
-struct free_record {
- struct list_head list;
- struct device *dev;
- unsigned bytes;
- dma_addr_t dma;
-};
-
-static void do_free(unsigned long ignored)
-{
- spin_lock_irq(&buflock);
- while (!list_empty(&buffers)) {
- struct free_record *buf;
-
- buf = list_entry(buffers.next, struct free_record, list);
- list_del(&buf->list);
- spin_unlock_irq(&buflock);
-
- dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
-
- spin_lock_irq(&buflock);
- }
- spin_unlock_irq(&buflock);
-}
-
-static DECLARE_TASKLET(deferred_free, do_free, 0);
-
-static void omap_free_buffer(
- struct usb_ep *_ep,
- void *buf,
- dma_addr_t dma,
- unsigned bytes
-)
-{
- if (!_ep) {
- WARN_ON(1);
- return;
- }
-
- /* free memory into the right allocator */
- if (dma != DMA_ADDR_INVALID) {
- struct omap_ep *ep;
- struct free_record *rec = buf;
- unsigned long flags;
-
- ep = container_of(_ep, struct omap_ep, ep);
-
- rec->dev = ep->udc->gadget.dev.parent;
- rec->bytes = bytes;
- rec->dma = dma;
-
- spin_lock_irqsave(&buflock, flags);
- list_add_tail(&rec->list, &buffers);
- tasklet_schedule(&deferred_free);
- spin_unlock_irqrestore(&buflock, flags);
- } else
- kfree(buf);
-}
-
-/*-------------------------------------------------------------------------*/
-
static void
done(struct omap_ep *ep, struct omap_req *req, int status)
{
@@ -1271,9 +1166,6 @@ static struct usb_ep_ops omap_ep_ops = {
.alloc_request = omap_alloc_request,
.free_request = omap_free_request,
- .alloc_buffer = omap_alloc_buffer,
- .free_buffer = omap_free_buffer,
-
.queue = omap_ep_queue,
.dequeue = omap_ep_dequeue,
@@ -1651,9 +1543,9 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src)
UDC_EP_NUM_REG = 0;
} while (UDC_IRQ_SRC_REG & UDC_SETUP);
-#define w_value le16_to_cpup (&u.r.wValue)
-#define w_index le16_to_cpup (&u.r.wIndex)
-#define w_length le16_to_cpup (&u.r.wLength)
+#define w_value le16_to_cpu(u.r.wValue)
+#define w_index le16_to_cpu(u.r.wIndex)
+#define w_length le16_to_cpu(u.r.wLength)
/* Delegate almost all control requests to the gadget driver,
* except for a handful of ch9 status/feature requests that
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 84392e835d5..63b9521c132 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -24,9 +24,9 @@
*
*/
-#undef DEBUG
// #define VERBOSE DBG_VERBOSE
+#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
@@ -46,19 +46,17 @@
#include <asm/byteorder.h>
#include <asm/dma.h>
+#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/mach-types.h>
#include <asm/unaligned.h>
#include <asm/hardware.h>
-#ifdef CONFIG_ARCH_PXA
-#include <asm/arch/pxa-regs.h>
-#endif
#include <linux/usb/ch9.h>
#include <linux/usb_gadget.h>
-#include <asm/arch/udc.h>
+#include <asm/mach/udc_pxa2xx.h>
/*
@@ -76,9 +74,17 @@
* it constrains the sorts of USB configuration change events that work.
* The errata for these chips are misleading; some "fixed" bugs from
* pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
+ *
+ * Note that the UDC hardware supports DMA (except on IXP) but that's
+ * not used here. IN-DMA (to host) is simple enough, when the data is
+ * suitably aligned (16 bytes) ... the network stack doesn't do that,
+ * other software can. OUT-DMA is buggy in most chip versions, as well
+ * as poorly designed (data toggle not automatic). So this driver won't
+ * bother using DMA. (Mostly-working IN-DMA support was available in
+ * kernels before 2.6.23, but was never enabled or well tested.)
*/
-#define DRIVER_VERSION "4-May-2005"
+#define DRIVER_VERSION "30-June-2007"
#define DRIVER_DESC "PXA 25x USB Device Controller driver"
@@ -87,12 +93,9 @@ static const char driver_name [] = "pxa2xx_udc";
static const char ep0name [] = "ep0";
-// #define USE_DMA
-// #define USE_OUT_DMA
// #define DISABLE_TEST_MODE
#ifdef CONFIG_ARCH_IXP4XX
-#undef USE_DMA
/* cpu-specific register addresses are compiled in to this code */
#ifdef CONFIG_ARCH_PXA
@@ -104,25 +107,6 @@ static const char ep0name [] = "ep0";
#include "pxa2xx_udc.h"
-#ifdef USE_DMA
-static int use_dma = 1;
-module_param(use_dma, bool, 0);
-MODULE_PARM_DESC (use_dma, "true to use dma");
-
-static void dma_nodesc_handler (int dmach, void *_ep);
-static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req);
-
-#ifdef USE_OUT_DMA
-#define DMASTR " (dma support)"
-#else
-#define DMASTR " (dma in)"
-#endif
-
-#else /* !USE_DMA */
-#define DMASTR " (pio only)"
-#undef USE_OUT_DMA
-#endif
-
#ifdef CONFIG_USB_PXA2XX_SMALL
#define SIZE_STR " (small)"
#else
@@ -155,7 +139,7 @@ static int is_vbus_present(void)
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
if (mach->gpio_vbus)
- return udc_gpio_get(mach->gpio_vbus);
+ return gpio_get_value(mach->gpio_vbus);
if (mach->udc_is_connected)
return mach->udc_is_connected();
return 1;
@@ -167,7 +151,7 @@ static void pullup_off(void)
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
if (mach->gpio_pullup)
- udc_gpio_set(mach->gpio_pullup, 0);
+ gpio_set_value(mach->gpio_pullup, 0);
else if (mach->udc_command)
mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
}
@@ -177,7 +161,7 @@ static void pullup_on(void)
struct pxa2xx_udc_mach_info *mach = the_controller->mach;
if (mach->gpio_pullup)
- udc_gpio_set(mach->gpio_pullup, 1);
+ gpio_set_value(mach->gpio_pullup, 1);
else if (mach->udc_command)
mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
}
@@ -281,9 +265,8 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
}
ep->desc = desc;
- ep->dma = -1;
ep->stopped = 0;
- ep->pio_irqs = ep->dma_irqs = 0;
+ ep->pio_irqs = 0;
ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize);
/* flush fifo (mostly for OUT buffers) */
@@ -291,30 +274,6 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
/* ... reset halt state too, if we could ... */
-#ifdef USE_DMA
- /* for (some) bulk and ISO endpoints, try to get a DMA channel and
- * bind it to the endpoint. otherwise use PIO.
- */
- switch (ep->bmAttributes) {
- case USB_ENDPOINT_XFER_ISOC:
- if (le16_to_cpu(desc->wMaxPacketSize) % 32)
- break;
- // fall through
- case USB_ENDPOINT_XFER_BULK:
- if (!use_dma || !ep->reg_drcmr)
- break;
- ep->dma = pxa_request_dma ((char *)_ep->name,
- (le16_to_cpu (desc->wMaxPacketSize) > 64)
- ? DMA_PRIO_MEDIUM /* some iso */
- : DMA_PRIO_LOW,
- dma_nodesc_handler, ep);
- if (ep->dma >= 0) {
- *ep->reg_drcmr = DRCMR_MAPVLD | ep->dma;
- DMSG("%s using dma%d\n", _ep->name, ep->dma);
- }
- }
-#endif
-
DBG(DBG_VERBOSE, "enabled %s\n", _ep->name);
return 0;
}
@@ -334,14 +293,6 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep)
nuke (ep, -ESHUTDOWN);
-#ifdef USE_DMA
- if (ep->dma >= 0) {
- *ep->reg_drcmr = 0;
- pxa_free_dma (ep->dma);
- ep->dma = -1;
- }
-#endif
-
/* flush fifo (mostly for IN buffers) */
pxa2xx_ep_fifo_flush (_ep);
@@ -390,35 +341,6 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req)
kfree(req);
}
-
-/* PXA cache needs flushing with DMA I/O (it's dma-incoherent), but there's
- * no device-affinity and the heap works perfectly well for i/o buffers.
- * It wastes much less memory than dma_alloc_coherent() would, and even
- * prevents cacheline (32 bytes wide) sharing problems.
- */
-static void *
-pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes,
- dma_addr_t *dma, gfp_t gfp_flags)
-{
- char *retval;
-
- retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM));
- if (retval)
-#ifdef USE_DMA
- *dma = virt_to_bus (retval);
-#else
- *dma = (dma_addr_t)~0;
-#endif
- return retval;
-}
-
-static void
-pxa2xx_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma,
- unsigned bytes)
-{
- kfree (buf);
-}
-
/*-------------------------------------------------------------------------*/
/*
@@ -518,18 +440,8 @@ write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
/* requests complete when all IN data is in the FIFO */
if (is_last) {
done (ep, req, 0);
- if (list_empty(&ep->queue) || unlikely(ep->dma >= 0)) {
+ if (list_empty(&ep->queue))
pio_irq_disable (ep->bEndpointAddress);
-#ifdef USE_DMA
- /* unaligned data and zlps couldn't use dma */
- if (unlikely(!list_empty(&ep->queue))) {
- req = list_entry(ep->queue.next,
- struct pxa2xx_request, queue);
- kick_dma(ep,req);
- return 0;
- }
-#endif
- }
return 1;
}
@@ -728,182 +640,6 @@ read_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
return 0;
}
-#ifdef USE_DMA
-
-#define MAX_IN_DMA ((DCMD_LENGTH + 1) - BULK_FIFO_SIZE)
-
-static void
-start_dma_nodesc(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int is_in)
-{
- u32 dcmd = req->req.length;
- u32 buf = req->req.dma;
- u32 fifo = io_v2p ((u32)ep->reg_uddr);
-
- /* caller guarantees there's a packet or more remaining
- * - IN may end with a short packet (TSP set separately),
- * - OUT is always full length
- */
- buf += req->req.actual;
- dcmd -= req->req.actual;
- ep->dma_fixup = 0;
-
- /* no-descriptor mode can be simple for bulk-in, iso-in, iso-out */
- DCSR(ep->dma) = DCSR_NODESC;
- if (is_in) {
- DSADR(ep->dma) = buf;
- DTADR(ep->dma) = fifo;
- if (dcmd > MAX_IN_DMA)
- dcmd = MAX_IN_DMA;
- else
- ep->dma_fixup = (dcmd % ep->ep.maxpacket) != 0;
- dcmd |= DCMD_BURST32 | DCMD_WIDTH1
- | DCMD_FLOWTRG | DCMD_INCSRCADDR;
- } else {
-#ifdef USE_OUT_DMA
- DSADR(ep->dma) = fifo;
- DTADR(ep->dma) = buf;
- if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC)
- dcmd = ep->ep.maxpacket;
- dcmd |= DCMD_BURST32 | DCMD_WIDTH1
- | DCMD_FLOWSRC | DCMD_INCTRGADDR;
-#endif
- }
- DCMD(ep->dma) = dcmd;
- DCSR(ep->dma) = DCSR_RUN | DCSR_NODESC
- | (unlikely(is_in)
- ? DCSR_STOPIRQEN /* use dma_nodesc_handler() */
- : 0); /* use handle_ep() */
-}
-
-static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req)
-{
- int is_in = ep->bEndpointAddress & USB_DIR_IN;
-
- if (is_in) {
- /* unaligned tx buffers and zlps only work with PIO */
- if ((req->req.dma & 0x0f) != 0
- || unlikely((req->req.length - req->req.actual)
- == 0)) {
- pio_irq_enable(ep->bEndpointAddress);
- if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0)
- (void) write_fifo(ep, req);
- } else {
- start_dma_nodesc(ep, req, USB_DIR_IN);
- }
- } else {
- if ((req->req.length - req->req.actual) < ep->ep.maxpacket) {
- DMSG("%s short dma read...\n", ep->ep.name);
- /* we're always set up for pio out */
- read_fifo (ep, req);
- } else {
- *ep->reg_udccs = UDCCS_BO_DME
- | (*ep->reg_udccs & UDCCS_BO_FST);
- start_dma_nodesc(ep, req, USB_DIR_OUT);
- }
- }
-}
-
-static void cancel_dma(struct pxa2xx_ep *ep)
-{
- struct pxa2xx_request *req;
- u32 tmp;
-
- if (DCSR(ep->dma) == 0 || list_empty(&ep->queue))
- return;
-
- DCSR(ep->dma) = 0;
- while ((DCSR(ep->dma) & DCSR_STOPSTATE) == 0)
- cpu_relax();
-
- req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
- tmp = DCMD(ep->dma) & DCMD_LENGTH;
- req->req.actual = req->req.length - (tmp & DCMD_LENGTH);
-
- /* the last tx packet may be incomplete, so flush the fifo.
- * FIXME correct req.actual if we can
- */
- if (ep->bEndpointAddress & USB_DIR_IN)
- *ep->reg_udccs = UDCCS_BI_FTF;
-}
-
-/* dma channel stopped ... normal tx end (IN), or on error (IN/OUT) */
-static void dma_nodesc_handler(int dmach, void *_ep)
-{
- struct pxa2xx_ep *ep = _ep;
- struct pxa2xx_request *req;
- u32 tmp, completed;
-
- local_irq_disable();
-
- req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
-
- ep->dma_irqs++;
- ep->dev->stats.irqs++;
- HEX_DISPLAY(ep->dev->stats.irqs);
-
- /* ack/clear */
- tmp = DCSR(ep->dma);
- DCSR(ep->dma) = tmp;
- if ((tmp & DCSR_STOPSTATE) == 0
- || (DDADR(ep->dma) & DDADR_STOP) != 0) {
- DBG(DBG_VERBOSE, "%s, dcsr %08x ddadr %08x\n",
- ep->ep.name, DCSR(ep->dma), DDADR(ep->dma));
- goto done;
- }
- DCSR(ep->dma) = 0; /* clear DCSR_STOPSTATE */
-
- /* update transfer status */
- completed = tmp & DCSR_BUSERR;
- if (ep->bEndpointAddress & USB_DIR_IN)
- tmp = DSADR(ep->dma);
- else
- tmp = DTADR(ep->dma);
- req->req.actual = tmp - req->req.dma;
-
- /* FIXME seems we sometimes see partial transfers... */
-
- if (unlikely(completed != 0))
- req->req.status = -EIO;
- else if (req->req.actual) {
- /* these registers have zeroes in low bits; they miscount
- * some (end-of-transfer) short packets: tx 14 as tx 12
- */
- if (ep->dma_fixup)
- req->req.actual = min(req->req.actual + 3,
- req->req.length);
-
- tmp = (req->req.length - req->req.actual);
- completed = (tmp == 0);
- if (completed && (ep->bEndpointAddress & USB_DIR_IN)) {
-
- /* maybe validate final short packet ... */
- if ((req->req.actual % ep->ep.maxpacket) != 0)
- *ep->reg_udccs = UDCCS_BI_TSP/*|UDCCS_BI_TPC*/;
-
- /* ... or zlp, using pio fallback */
- else if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK
- && req->req.zero) {
- DMSG("%s zlp terminate ...\n", ep->ep.name);
- completed = 0;
- }
- }
- }
-
- if (likely(completed)) {
- done(ep, req, 0);
-
- /* maybe re-activate after completion */
- if (ep->stopped || list_empty(&ep->queue))
- goto done;
- req = list_entry(ep->queue.next, struct pxa2xx_request, queue);
- }
- kick_dma(ep, req);
-done:
- local_irq_enable();
-}
-
-#endif
-
/*-------------------------------------------------------------------------*/
static int
@@ -942,19 +678,8 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
(ep->desc->wMaxPacketSize)))
return -EMSGSIZE;
-#ifdef USE_DMA
- // FIXME caller may already have done the dma mapping
- if (ep->dma >= 0) {
- _req->dma = dma_map_single(dev->dev,
- _req->buf, _req->length,
- ((ep->bEndpointAddress & USB_DIR_IN) != 0)
- ? DMA_TO_DEVICE
- : DMA_FROM_DEVICE);
- }
-#endif
-
DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n",
- _ep->name, _req, _req->length, _req->buf);
+ _ep->name, _req, _req->length, _req->buf);
local_irq_save(flags);
@@ -1002,11 +727,6 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
local_irq_restore (flags);
return -EL2HLT;
}
-#ifdef USE_DMA
- /* either start dma or prime pio pump */
- } else if (ep->dma >= 0) {
- kick_dma(ep, req);
-#endif
/* can the FIFO can satisfy the request immediately? */
} else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0
@@ -1017,7 +737,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req = NULL;
}
- if (likely (req && ep->desc) && ep->dma < 0)
+ if (likely (req && ep->desc))
pio_irq_enable(ep->bEndpointAddress);
}
@@ -1038,10 +758,6 @@ static void nuke(struct pxa2xx_ep *ep, int status)
struct pxa2xx_request *req;
/* called with irqs blocked */
-#ifdef USE_DMA
- if (ep->dma >= 0 && !ep->stopped)
- cancel_dma(ep);
-#endif
while (!list_empty(&ep->queue)) {
req = list_entry(ep->queue.next,
struct pxa2xx_request,
@@ -1076,19 +792,7 @@ static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
return -EINVAL;
}
-#ifdef USE_DMA
- if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) {
- cancel_dma(ep);
- done(ep, req, -ECONNRESET);
- /* restart i/o */
- if (!list_empty(&ep->queue)) {
- req = list_entry(ep->queue.next,
- struct pxa2xx_request, queue);
- kick_dma(ep, req);
- }
- } else
-#endif
- done(ep, req, -ECONNRESET);
+ done(ep, req, -ECONNRESET);
local_irq_restore(flags);
return 0;
@@ -1203,9 +907,6 @@ static struct usb_ep_ops pxa2xx_ep_ops = {
.alloc_request = pxa2xx_ep_alloc_request,
.free_request = pxa2xx_ep_free_request,
- .alloc_buffer = pxa2xx_ep_alloc_buffer,
- .free_buffer = pxa2xx_ep_free_buffer,
-
.queue = pxa2xx_ep_queue,
.dequeue = pxa2xx_ep_dequeue,
@@ -1325,7 +1026,7 @@ udc_proc_read(char *page, char **start, off_t off, int count,
/* basic device status */
t = scnprintf(next, size, DRIVER_DESC "\n"
"%s version: %s\nGadget driver: %s\nHost %s\n\n",
- driver_name, DRIVER_VERSION SIZE_STR DMASTR,
+ driver_name, DRIVER_VERSION SIZE_STR "(pio)",
dev->driver ? dev->driver->driver.name : "(none)",
is_vbus_present() ? "full speed" : "disconnected");
size -= t;
@@ -1390,7 +1091,6 @@ udc_proc_read(char *page, char **start, off_t off, int count,
for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
struct pxa2xx_ep *ep = &dev->ep [i];
struct pxa2xx_request *req;
- int t;
if (i != 0) {
const struct usb_endpoint_descriptor *d;
@@ -1400,10 +1100,9 @@ udc_proc_read(char *page, char **start, off_t off, int count,
continue;
tmp = *dev->ep [i].reg_udccs;
t = scnprintf(next, size,
- "%s max %d %s udccs %02x irqs %lu/%lu\n",
+ "%s max %d %s udccs %02x irqs %lu\n",
ep->ep.name, le16_to_cpu (d->wMaxPacketSize),
- (ep->dma >= 0) ? "dma" : "pio", tmp,
- ep->pio_irqs, ep->dma_irqs);
+ "pio", tmp, ep->pio_irqs);
/* TODO translate all five groups of udccs bits! */
} else /* ep0 should only have one transfer queued */
@@ -1423,19 +1122,7 @@ udc_proc_read(char *page, char **start, off_t off, int count,
continue;
}
list_for_each_entry(req, &ep->queue, queue) {
-#ifdef USE_DMA
- if (ep->dma >= 0 && req->queue.prev == &ep->queue)
- t = scnprintf(next, size,
- "\treq %p len %d/%d "
- "buf %p (dma%d dcmd %08x)\n",
- &req->req, req->req.actual,
- req->req.length, req->req.buf,
- ep->dma, DCMD(ep->dma)
- // low 13 bits == bytes-to-go
- );
- else
-#endif
- t = scnprintf(next, size,
+ t = scnprintf(next, size,
"\treq %p len %d/%d buf %p\n",
&req->req, req->req.actual,
req->req.length, req->req.buf);
@@ -1488,7 +1175,6 @@ static void udc_disable(struct pxa2xx_udc *dev)
ep0_idle (dev);
dev->gadget.speed = USB_SPEED_UNKNOWN;
- LED_CONNECTED_OFF;
}
@@ -1514,7 +1200,7 @@ static void udc_reinit(struct pxa2xx_udc *dev)
ep->desc = NULL;
ep->stopped = 0;
INIT_LIST_HEAD (&ep->queue);
- ep->pio_irqs = ep->dma_irqs = 0;
+ ep->pio_irqs = 0;
}
/* the rest was statically initialized, and is read-only */
@@ -1666,7 +1352,6 @@ stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver)
del_timer_sync(&dev->timer);
/* report disconnect; the driver is already quiesced */
- LED_CONNECTED_OFF;
if (driver)
driver->disconnect(&dev->gadget);
@@ -1715,16 +1400,13 @@ lubbock_vbus_irq(int irq, void *_dev)
int vbus;
dev->stats.irqs++;
- HEX_DISPLAY(dev->stats.irqs);
switch (irq) {
case LUBBOCK_USB_IRQ:
- LED_CONNECTED_ON;
vbus = 1;
disable_irq(LUBBOCK_USB_IRQ);
enable_irq(LUBBOCK_USB_DISC_IRQ);
break;
case LUBBOCK_USB_DISC_IRQ:
- LED_CONNECTED_OFF;
vbus = 0;
disable_irq(LUBBOCK_USB_DISC_IRQ);
enable_irq(LUBBOCK_USB_IRQ);
@@ -1742,7 +1424,7 @@ lubbock_vbus_irq(int irq, void *_dev)
static irqreturn_t udc_vbus_irq(int irq, void *_dev)
{
struct pxa2xx_udc *dev = _dev;
- int vbus = udc_gpio_get(dev->mach->gpio_vbus);
+ int vbus = gpio_get_value(dev->mach->gpio_vbus);
pxa2xx_udc_vbus_session(&dev->gadget, vbus);
return IRQ_HANDLED;
@@ -2040,18 +1722,6 @@ static void handle_ep(struct pxa2xx_ep *ep)
/* fifos can hold packets, ready for reading... */
if (likely(req)) {
-#ifdef USE_OUT_DMA
-// TODO didn't yet debug out-dma. this approach assumes
-// the worst about short packets and RPC; it might be better.
-
- if (likely(ep->dma >= 0)) {
- if (!(udccs & UDCCS_BO_RSP)) {
- *ep->reg_udccs = UDCCS_BO_RPC;
- ep->dma_irqs++;
- return;
- }
- }
-#endif
completed = read_fifo(ep, req);
} else
pio_irq_disable (ep->bEndpointAddress);
@@ -2074,7 +1744,6 @@ pxa2xx_udc_irq(int irq, void *_dev)
int handled;
dev->stats.irqs++;
- HEX_DISPLAY(dev->stats.irqs);
do {
u32 udccr = UDCCR;
@@ -2125,7 +1794,6 @@ pxa2xx_udc_irq(int irq, void *_dev)
} else {
DBG(DBG_VERBOSE, "USB reset end\n");
dev->gadget.speed = USB_SPEED_FULL;
- LED_CONNECTED_ON;
memset(&dev->stats, 0, sizeof dev->stats);
/* driver and endpoints are still reset */
}
@@ -2217,7 +1885,6 @@ static struct pxa2xx_udc memory = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.reg_udccs = &UDCCS1,
.reg_uddr = &UDDR1,
- drcmr (25)
},
.ep[2] = {
.ep = {
@@ -2232,7 +1899,6 @@ static struct pxa2xx_udc memory = {
.reg_udccs = &UDCCS2,
.reg_ubcr = &UBCR2,
.reg_uddr = &UDDR2,
- drcmr (26)
},
#ifndef CONFIG_USB_PXA2XX_SMALL
.ep[3] = {
@@ -2247,7 +1913,6 @@ static struct pxa2xx_udc memory = {
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.reg_udccs = &UDCCS3,
.reg_uddr = &UDDR3,
- drcmr (27)
},
.ep[4] = {
.ep = {
@@ -2262,7 +1927,6 @@ static struct pxa2xx_udc memory = {
.reg_udccs = &UDCCS4,
.reg_ubcr = &UBCR4,
.reg_uddr = &UDDR4,
- drcmr (28)
},
.ep[5] = {
.ep = {
@@ -2291,7 +1955,6 @@ static struct pxa2xx_udc memory = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.reg_udccs = &UDCCS6,
.reg_uddr = &UDDR6,
- drcmr (30)
},
.ep[7] = {
.ep = {
@@ -2306,7 +1969,6 @@ static struct pxa2xx_udc memory = {
.reg_udccs = &UDCCS7,
.reg_ubcr = &UBCR7,
.reg_uddr = &UDDR7,
- drcmr (31)
},
.ep[8] = {
.ep = {
@@ -2320,7 +1982,6 @@ static struct pxa2xx_udc memory = {
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.reg_udccs = &UDCCS8,
.reg_uddr = &UDDR8,
- drcmr (32)
},
.ep[9] = {
.ep = {
@@ -2335,7 +1996,6 @@ static struct pxa2xx_udc memory = {
.reg_udccs = &UDCCS9,
.reg_ubcr = &UBCR9,
.reg_uddr = &UDDR9,
- drcmr (33)
},
.ep[10] = {
.ep = {
@@ -2364,7 +2024,6 @@ static struct pxa2xx_udc memory = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.reg_udccs = &UDCCS11,
.reg_uddr = &UDDR11,
- drcmr (35)
},
.ep[12] = {
.ep = {
@@ -2379,7 +2038,6 @@ static struct pxa2xx_udc memory = {
.reg_udccs = &UDCCS12,
.reg_ubcr = &UBCR12,
.reg_uddr = &UDDR12,
- drcmr (36)
},
.ep[13] = {
.ep = {
@@ -2393,7 +2051,6 @@ static struct pxa2xx_udc memory = {
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.reg_udccs = &UDCCS13,
.reg_uddr = &UDDR13,
- drcmr (37)
},
.ep[14] = {
.ep = {
@@ -2408,7 +2065,6 @@ static struct pxa2xx_udc memory = {
.reg_udccs = &UDCCS14,
.reg_ubcr = &UBCR14,
.reg_uddr = &UDDR14,
- drcmr (38)
},
.ep[15] = {
.ep = {
@@ -2466,7 +2122,7 @@ static struct pxa2xx_udc memory = {
static int __init pxa2xx_udc_probe(struct platform_device *pdev)
{
struct pxa2xx_udc *dev = &memory;
- int retval, out_dma = 1, vbus_irq, irq;
+ int retval, vbus_irq, irq;
u32 chiprev;
/* insist on Intel/ARM/XScale */
@@ -2489,7 +2145,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
case PXA250_B2: case PXA210_B2:
case PXA250_B1: case PXA210_B1:
case PXA250_B0: case PXA210_B0:
- out_dma = 0;
+ /* OUT-DMA is broken ... */
/* fall through */
case PXA250_C0: case PXA210_C0:
break;
@@ -2498,11 +2154,9 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
case IXP425_B0:
case IXP465_AD:
dev->has_cfr = 1;
- out_dma = 0;
break;
#endif
default:
- out_dma = 0;
printk(KERN_ERR "%s: unrecognized processor: %08x\n",
driver_name, chiprev);
/* iop3xx, ixp4xx, ... */
@@ -2513,36 +2167,41 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
if (irq < 0)
return -ENODEV;
- pr_debug("%s: IRQ %d%s%s%s\n", driver_name, irq,
+ pr_debug("%s: IRQ %d%s%s\n", driver_name, irq,
dev->has_cfr ? "" : " (!cfr)",
- out_dma ? "" : " (broken dma-out)",
- SIZE_STR DMASTR
+ SIZE_STR "(pio)"
);
-#ifdef USE_DMA
-#ifndef USE_OUT_DMA
- out_dma = 0;
-#endif
- /* pxa 250 erratum 130 prevents using OUT dma (fixed C0) */
- if (!out_dma) {
- DMSG("disabled OUT dma\n");
- dev->ep[ 2].reg_drcmr = dev->ep[ 4].reg_drcmr = 0;
- dev->ep[ 7].reg_drcmr = dev->ep[ 9].reg_drcmr = 0;
- dev->ep[12].reg_drcmr = dev->ep[14].reg_drcmr = 0;
- }
-#endif
-
/* other non-static parts of init */
dev->dev = &pdev->dev;
dev->mach = pdev->dev.platform_data;
+
if (dev->mach->gpio_vbus) {
- udc_gpio_init_vbus(dev->mach->gpio_vbus);
- vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus);
+ if ((retval = gpio_request(dev->mach->gpio_vbus,
+ "pxa2xx_udc GPIO VBUS"))) {
+ dev_dbg(&pdev->dev,
+ "can't get vbus gpio %d, err: %d\n",
+ dev->mach->gpio_vbus, retval);
+ return -EBUSY;
+ }
+ gpio_direction_input(dev->mach->gpio_vbus);
+ vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
set_irq_type(vbus_irq, IRQT_BOTHEDGE);
} else
vbus_irq = 0;
- if (dev->mach->gpio_pullup)
- udc_gpio_init_pullup(dev->mach->gpio_pullup);
+
+ if (dev->mach->gpio_pullup) {
+ if ((retval = gpio_request(dev->mach->gpio_pullup,
+ "pca2xx_udc GPIO PULLUP"))) {
+ dev_dbg(&pdev->dev,
+ "can't get pullup gpio %d, err: %d\n",
+ dev->mach->gpio_pullup, retval);
+ if (dev->mach->gpio_vbus)
+ gpio_free(dev->mach->gpio_vbus);
+ return -EBUSY;
+ }
+ gpio_direction_output(dev->mach->gpio_pullup, 0);
+ }
init_timer(&dev->timer);
dev->timer.function = udc_watchdog;
@@ -2566,6 +2225,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
if (retval != 0) {
printk(KERN_ERR "%s: can't get irq %d, err %d\n",
driver_name, irq, retval);
+ if (dev->mach->gpio_pullup)
+ gpio_free(dev->mach->gpio_pullup);
+ if (dev->mach->gpio_vbus)
+ gpio_free(dev->mach->gpio_vbus);
return -EBUSY;
}
dev->got_irq = 1;
@@ -2581,6 +2244,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
driver_name, LUBBOCK_USB_DISC_IRQ, retval);
lubbock_fail0:
free_irq(irq, dev);
+ if (dev->mach->gpio_pullup)
+ gpio_free(dev->mach->gpio_pullup);
+ if (dev->mach->gpio_vbus)
+ gpio_free(dev->mach->gpio_vbus);
return -EBUSY;
}
retval = request_irq(LUBBOCK_USB_IRQ,
@@ -2593,11 +2260,6 @@ lubbock_fail0:
free_irq(LUBBOCK_USB_DISC_IRQ, dev);
goto lubbock_fail0;
}
-#ifdef DEBUG
- /* with U-Boot (but not BLOB), hex is off by default */
- HEX_DISPLAY(dev->stats.irqs);
- LUB_DISC_BLNK_LED &= 0xff;
-#endif
} else
#endif
if (vbus_irq) {
@@ -2608,6 +2270,10 @@ lubbock_fail0:
printk(KERN_ERR "%s: can't get irq %i, err %d\n",
driver_name, vbus_irq, retval);
free_irq(irq, dev);
+ if (dev->mach->gpio_pullup)
+ gpio_free(dev->mach->gpio_pullup);
+ if (dev->mach->gpio_vbus)
+ gpio_free(dev->mach->gpio_vbus);
return -EBUSY;
}
}
@@ -2641,8 +2307,13 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
free_irq(LUBBOCK_USB_IRQ, dev);
}
#endif
- if (dev->mach->gpio_vbus)
- free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev);
+ if (dev->mach->gpio_vbus) {
+ free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
+ gpio_free(dev->mach->gpio_vbus);
+ }
+ if (dev->mach->gpio_pullup)
+ gpio_free(dev->mach->gpio_pullup);
+
platform_set_drvdata(pdev, NULL);
the_controller = NULL;
return 0;
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h
index 773e549aff3..0e5d0e6fb0e 100644
--- a/drivers/usb/gadget/pxa2xx_udc.h
+++ b/drivers/usb/gadget/pxa2xx_udc.h
@@ -54,8 +54,6 @@ struct pxa2xx_ep {
const struct usb_endpoint_descriptor *desc;
struct list_head queue;
unsigned long pio_irqs;
- unsigned long dma_irqs;
- short dma;
unsigned short fifo_size;
u8 bEndpointAddress;
@@ -63,7 +61,7 @@ struct pxa2xx_ep {
unsigned stopped : 1;
unsigned dma_fixup : 1;
-
+
/* UDCCS = UDC Control/Status for this EP
* UBCR = UDC Byte Count Remaining (contents of OUT fifo)
* UDDR = UDC Endpoint Data Register (the fifo)
@@ -72,12 +70,6 @@ struct pxa2xx_ep {
volatile u32 *reg_udccs;
volatile u32 *reg_ubcr;
volatile u32 *reg_uddr;
-#ifdef USE_DMA
- volatile u32 *reg_drcmr;
-#define drcmr(n) .reg_drcmr = & DRCMR ## n ,
-#else
-#define drcmr(n)
-#endif
};
struct pxa2xx_request {
@@ -85,7 +77,7 @@ struct pxa2xx_request {
struct list_head queue;
};
-enum ep0_state {
+enum ep0_state {
EP0_IDLE,
EP0_IN_DATA_PHASE,
EP0_OUT_DATA_PHASE,
@@ -108,7 +100,6 @@ struct udc_stats {
#ifdef CONFIG_USB_PXA2XX_SMALL
/* when memory's tight, SMALL config saves code+data. */
-#undef USE_DMA
#define PXA_UDC_NUM_ENDPOINTS 3
#endif
@@ -144,37 +135,8 @@ struct pxa2xx_udc {
#ifdef CONFIG_ARCH_LUBBOCK
#include <asm/arch/lubbock.h>
/* lubbock can also report usb connect/disconnect irqs */
-
-#ifdef DEBUG
-#define HEX_DISPLAY(n) if (machine_is_lubbock()) { LUB_HEXLED = (n); }
#endif
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/* LEDs are only for debug */
-#ifndef HEX_DISPLAY
-#define HEX_DISPLAY(n) do {} while(0)
-#endif
-
-#ifdef DEBUG
-#include <asm/leds.h>
-
-#define LED_CONNECTED_ON leds_event(led_green_on)
-#define LED_CONNECTED_OFF do { \
- leds_event(led_green_off); \
- HEX_DISPLAY(0); \
- } while(0)
-#endif
-
-#ifndef LED_CONNECTED_ON
-#define LED_CONNECTED_ON do {} while(0)
-#define LED_CONNECTED_OFF do {} while(0)
-#endif
-
-/*-------------------------------------------------------------------------*/
-
static struct pxa2xx_udc *the_controller;
/*-------------------------------------------------------------------------*/
@@ -204,7 +166,7 @@ static const char *state_name[] = {
# define UDC_DEBUG DBG_NORMAL
#endif
-static void __attribute__ ((__unused__))
+static void __maybe_unused
dump_udccr(const char *label)
{
u32 udccr = UDCCR;
@@ -220,7 +182,7 @@ dump_udccr(const char *label)
(udccr & UDCCR_UDE) ? " ude" : "");
}
-static void __attribute__ ((__unused__))
+static void __maybe_unused
dump_udccs0(const char *label)
{
u32 udccs0 = UDCCS0;
@@ -237,7 +199,7 @@ dump_udccs0(const char *label)
(udccs0 & UDCCS0_OPR) ? " opr" : "");
}
-static void __attribute__ ((__unused__))
+static void __maybe_unused
dump_state(struct pxa2xx_udc *dev)
{
u32 tmp;
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 6ec8cf1a3cc..db1b2bfcee4 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -53,7 +53,7 @@
*/
#if 0
-#define DEBUG(str,args...) do { \
+#define DBG(str,args...) do { \
if (rndis_debug) \
printk(KERN_DEBUG str , ## args ); \
} while (0)
@@ -65,7 +65,7 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging");
#else
#define rndis_debug 0
-#define DEBUG(str,args...) do{}while(0)
+#define DBG(str,args...) do{}while(0)
#endif
#define RNDIS_MAX_CONFIGS 1
@@ -183,13 +183,17 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
if (!resp) return -ENOMEM;
if (buf_len && rndis_debug > 1) {
- DEBUG("query OID %08x value, len %d:\n", OID, buf_len);
+ DBG("query OID %08x value, len %d:\n", OID, buf_len);
for (i = 0; i < buf_len; i += 16) {
- DEBUG ("%03d: %08x %08x %08x %08x\n", i,
- le32_to_cpup((__le32 *)&buf[i]),
- le32_to_cpup((__le32 *)&buf[i + 4]),
- le32_to_cpup((__le32 *)&buf[i + 8]),
- le32_to_cpup((__le32 *)&buf[i + 12]));
+ DBG("%03d: %08x %08x %08x %08x\n", i,
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 4])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 8])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 12])));
}
}
@@ -203,7 +207,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_SUPPORTED_LIST:
- DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
+ DBG("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
length = sizeof (oid_supported_list);
count = length / sizeof (u32);
for (i = 0; i < count; i++)
@@ -213,7 +217,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_HARDWARE_STATUS:
- DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
+ DBG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
/* Bogus question!
* Hardware must be ready to receive high level protocols.
* BTW:
@@ -226,14 +230,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_MEDIA_SUPPORTED:
- DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
retval = 0;
break;
/* mandatory */
case OID_GEN_MEDIA_IN_USE:
- DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
/* one medium, one transport... (maybe you do it better) */
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
retval = 0;
@@ -241,7 +245,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_MAXIMUM_FRAME_SIZE:
- DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
@@ -252,7 +256,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_LINK_SPEED:
if (rndis_debug > 1)
- DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
+ DBG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].media_state
== NDIS_MEDIA_STATE_DISCONNECTED)
*outbuf = __constant_cpu_to_le32 (0);
@@ -264,7 +268,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_TRANSMIT_BLOCK_SIZE:
- DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
+ DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
@@ -274,7 +278,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RECEIVE_BLOCK_SIZE:
- DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
+ DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].dev->mtu);
@@ -284,7 +288,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_VENDOR_ID:
- DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
+ DBG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].vendorID);
retval = 0;
@@ -292,7 +296,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_VENDOR_DESCRIPTION:
- DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
+ DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
length = strlen (rndis_per_dev_params [configNr].vendorDescr);
memcpy (outbuf,
rndis_per_dev_params [configNr].vendorDescr, length);
@@ -300,7 +304,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_VENDOR_DRIVER_VERSION:
- DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
+ DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
/* Created as LE */
*outbuf = rndis_driver_version;
retval = 0;
@@ -308,14 +312,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_CURRENT_PACKET_FILTER:
- DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
+ DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
*outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter);
retval = 0;
break;
/* mandatory */
case OID_GEN_MAXIMUM_TOTAL_SIZE:
- DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
*outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
retval = 0;
break;
@@ -323,14 +327,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_MEDIA_CONNECT_STATUS:
if (rndis_debug > 1)
- DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.media_state);
retval = 0;
break;
case OID_GEN_PHYSICAL_MEDIUM:
- DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
+ DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -340,7 +344,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
* versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
*/
case OID_GEN_MAC_OPTIONS: /* from WinME */
- DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
*outbuf = __constant_cpu_to_le32(
NDIS_MAC_OPTION_RECEIVE_SERIALIZED
| NDIS_MAC_OPTION_FULL_DUPLEX);
@@ -352,7 +356,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_XMIT_OK:
if (rndis_debug > 1)
- DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
+ DBG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].stats->tx_packets -
@@ -365,7 +369,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RCV_OK:
if (rndis_debug > 1)
- DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
+ DBG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].stats->rx_packets -
@@ -378,7 +382,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_XMIT_ERROR:
if (rndis_debug > 1)
- DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
+ DBG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->tx_errors);
@@ -389,7 +393,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RCV_ERROR:
if (rndis_debug > 1)
- DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
+ DBG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->rx_errors);
@@ -399,7 +403,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_RCV_NO_BUFFER:
- DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
+ DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->rx_dropped);
@@ -409,7 +413,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
#ifdef RNDIS_OPTIONAL_STATS
case OID_GEN_DIRECTED_BYTES_XMIT:
- DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
+ DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
/*
* Aunt Tilly's size of shoes
* minus antarctica count of penguins
@@ -429,7 +433,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_DIRECTED_FRAMES_XMIT:
- DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
+ DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
/* dito */
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (
@@ -445,7 +449,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_MULTICAST_BYTES_XMIT:
- DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->multicast*1234);
@@ -454,7 +458,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_MULTICAST_FRAMES_XMIT:
- DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->multicast);
@@ -463,7 +467,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_BROADCAST_BYTES_XMIT:
- DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
+ DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->tx_packets/42*255);
@@ -472,7 +476,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_BROADCAST_FRAMES_XMIT:
- DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
+ DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->tx_packets/42);
@@ -481,19 +485,19 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_DIRECTED_BYTES_RCV:
- DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
+ DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
case OID_GEN_DIRECTED_FRAMES_RCV:
- DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
+ DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
case OID_GEN_MULTICAST_BYTES_RCV:
- DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->multicast * 1111);
@@ -502,7 +506,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_MULTICAST_FRAMES_RCV:
- DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
+ DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->multicast);
@@ -511,7 +515,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_BROADCAST_BYTES_RCV:
- DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
+ DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->rx_packets/42*255);
@@ -520,7 +524,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_BROADCAST_FRAMES_RCV:
- DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
+ DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->rx_packets/42);
@@ -529,7 +533,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_RCV_CRC_ERROR:
- DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
+ DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->rx_crc_errors);
@@ -538,7 +542,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
break;
case OID_GEN_TRANSMIT_QUEUE_LENGTH:
- DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
+ DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
@@ -548,7 +552,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_PERMANENT_ADDRESS:
- DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
+ DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = ETH_ALEN;
memcpy (outbuf,
@@ -560,7 +564,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_CURRENT_ADDRESS:
- DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
+ DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = ETH_ALEN;
memcpy (outbuf,
@@ -572,7 +576,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_MULTICAST_LIST:
- DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+ DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
/* Multicast base address only */
*outbuf = __constant_cpu_to_le32 (0xE0000000);
retval = 0;
@@ -580,21 +584,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_MAXIMUM_LIST_SIZE:
- DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
+ DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
/* Multicast base address only */
*outbuf = __constant_cpu_to_le32 (1);
retval = 0;
break;
case OID_802_3_MAC_OPTIONS:
- DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
+ DBG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
break;
/* ieee802.3 statistics OIDs (table 4-4) */
/* mandatory */
case OID_802_3_RCV_ERROR_ALIGNMENT:
- DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
+ DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].stats) {
*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr]
.stats->rx_frame_errors);
@@ -604,51 +608,51 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_802_3_XMIT_ONE_COLLISION:
- DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
+ DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
/* mandatory */
case OID_802_3_XMIT_MORE_COLLISIONS:
- DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
+ DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
*outbuf = __constant_cpu_to_le32 (0);
retval = 0;
break;
#ifdef RNDIS_OPTIONAL_STATS
case OID_802_3_XMIT_DEFERRED:
- DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
+ DBG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
/* TODO */
break;
case OID_802_3_XMIT_MAX_COLLISIONS:
- DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
+ DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
/* TODO */
break;
case OID_802_3_RCV_OVERRUN:
- DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
+ DBG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
/* TODO */
break;
case OID_802_3_XMIT_UNDERRUN:
- DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
+ DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
/* TODO */
break;
case OID_802_3_XMIT_HEARTBEAT_FAILURE:
- DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
+ DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
/* TODO */
break;
case OID_802_3_XMIT_TIMES_CRS_LOST:
- DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
+ DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
/* TODO */
break;
case OID_802_3_XMIT_LATE_COLLISIONS:
- DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
+ DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
/* TODO */
break;
#endif /* RNDIS_OPTIONAL_STATS */
@@ -656,7 +660,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
#ifdef RNDIS_PM
/* power management OIDs (table 4-5) */
case OID_PNP_CAPABILITIES:
- DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
+ DBG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
/* for now, no wakeup capabilities */
length = sizeof (struct NDIS_PNP_CAPABILITIES);
@@ -664,8 +668,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
retval = 0;
break;
case OID_PNP_QUERY_POWER:
- DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
- le32_to_cpup((__le32 *) buf) - 1);
+ DBG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
+ le32_to_cpu(get_unaligned((__le32 *)buf)) - 1);
/* only suspend is a real power state, and
* it can't be entered by OID_PNP_SET_POWER...
*/
@@ -701,13 +705,17 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
return -ENOMEM;
if (buf_len && rndis_debug > 1) {
- DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
+ DBG("set OID %08x value, len %d:\n", OID, buf_len);
for (i = 0; i < buf_len; i += 16) {
- DEBUG ("%03d: %08x %08x %08x %08x\n", i,
- le32_to_cpup((__le32 *)&buf[i]),
- le32_to_cpup((__le32 *)&buf[i + 4]),
- le32_to_cpup((__le32 *)&buf[i + 8]),
- le32_to_cpup((__le32 *)&buf[i + 12]));
+ DBG("%03d: %08x %08x %08x %08x\n", i,
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 4])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 8])),
+ le32_to_cpu(get_unaligned((__le32 *)
+ &buf[i + 12])));
}
}
@@ -721,8 +729,9 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
* PROMISCUOUS, DIRECTED,
* MULTICAST, ALL_MULTICAST, BROADCAST
*/
- *params->filter = (u16) le32_to_cpup((__le32 *)buf);
- DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+ *params->filter = (u16) le32_to_cpu(get_unaligned(
+ (__le32 *)buf));
+ DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
__FUNCTION__, *params->filter);
/* this call has a significant side effect: it's
@@ -747,7 +756,7 @@ update_linkstate:
case OID_802_3_MULTICAST_LIST:
/* I think we can ignore this */
- DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+ DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
retval = 0;
break;
#if 0
@@ -755,7 +764,7 @@ update_linkstate:
{
struct rndis_config_parameter *param;
param = (struct rndis_config_parameter *) buf;
- DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
+ DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
__FUNCTION__,
min(cpu_to_le32(param->ParameterNameLength),80),
buf + param->ParameterNameOffset);
@@ -771,8 +780,8 @@ update_linkstate:
* resuming, Windows forces a reset, and then SET_POWER D0.
* FIXME ... then things go batty; Windows wedges itself.
*/
- i = le32_to_cpup((__force __le32 *)buf);
- DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
+ i = le32_to_cpu(get_unaligned((__le32 *)buf));
+ DBG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1);
switch (i) {
case NdisDeviceStateD0:
*params->filter = params->saved_filter;
@@ -849,7 +858,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
rndis_query_cmplt_type *resp;
rndis_resp_t *r;
- // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
+ // DBG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
/*
@@ -902,15 +911,15 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
BufOffset = le32_to_cpu (buf->InformationBufferOffset);
#ifdef VERBOSE
- DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
- DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
- DEBUG("%s: InfoBuffer: ", __FUNCTION__);
+ DBG("%s: Length: %d\n", __FUNCTION__, BufLength);
+ DBG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
+ DBG("%s: InfoBuffer: ", __FUNCTION__);
for (i = 0; i < BufLength; i++) {
- DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+ DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
}
- DEBUG ("\n");
+ DBG("\n");
#endif
resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
@@ -1058,8 +1067,8 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
return -ENOMEM;
tmp = (__le32 *) buf;
- MsgType = le32_to_cpup(tmp++);
- MsgLength = le32_to_cpup(tmp++);
+ MsgType = le32_to_cpu(get_unaligned(tmp++));
+ MsgLength = le32_to_cpu(get_unaligned(tmp++));
if (configNr >= RNDIS_MAX_CONFIGS)
return -ENOTSUPP;
@@ -1073,14 +1082,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
/* For USB: responses may take up to 10 seconds */
switch (MsgType) {
case REMOTE_NDIS_INITIALIZE_MSG:
- DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
+ DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
__FUNCTION__ );
params->state = RNDIS_INITIALIZED;
return rndis_init_response (configNr,
(rndis_init_msg_type *) buf);
case REMOTE_NDIS_HALT_MSG:
- DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
+ DBG("%s: REMOTE_NDIS_HALT_MSG\n",
__FUNCTION__ );
params->state = RNDIS_UNINITIALIZED;
if (params->dev) {
@@ -1098,7 +1107,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
(rndis_set_msg_type *) buf);
case REMOTE_NDIS_RESET_MSG:
- DEBUG("%s: REMOTE_NDIS_RESET_MSG\n",
+ DBG("%s: REMOTE_NDIS_RESET_MSG\n",
__FUNCTION__ );
return rndis_reset_response (configNr,
(rndis_reset_msg_type *) buf);
@@ -1106,7 +1115,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
case REMOTE_NDIS_KEEPALIVE_MSG:
/* For USB: host does this every 5 seconds */
if (rndis_debug > 1)
- DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
+ DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
__FUNCTION__ );
return rndis_keepalive_response (configNr,
(rndis_keepalive_msg_type *)
@@ -1123,7 +1132,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
{
unsigned i;
for (i = 0; i < MsgLength; i += 16) {
- DEBUG ("%03d: "
+ DBG("%03d: "
" %02x %02x %02x %02x"
" %02x %02x %02x %02x"
" %02x %02x %02x %02x"
@@ -1154,18 +1163,18 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *))
if (!rndis_per_dev_params [i].used) {
rndis_per_dev_params [i].used = 1;
rndis_per_dev_params [i].ack = rndis_control_ack;
- DEBUG("%s: configNr = %d\n", __FUNCTION__, i);
+ DBG("%s: configNr = %d\n", __FUNCTION__, i);
return i;
}
}
- DEBUG("failed\n");
+ DBG("failed\n");
return -1;
}
void rndis_deregister (int configNr)
{
- DEBUG("%s: \n", __FUNCTION__ );
+ DBG("%s: \n", __FUNCTION__ );
if (configNr >= RNDIS_MAX_CONFIGS) return;
rndis_per_dev_params [configNr].used = 0;
@@ -1177,7 +1186,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
struct net_device_stats *stats,
u16 *cdc_filter)
{
- DEBUG("%s:\n", __FUNCTION__ );
+ DBG("%s:\n", __FUNCTION__ );
if (!dev || !stats) return -1;
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
@@ -1190,7 +1199,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev,
int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
{
- DEBUG("%s:\n", __FUNCTION__ );
+ DBG("%s:\n", __FUNCTION__ );
if (!vendorDescr) return -1;
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
@@ -1202,7 +1211,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
{
- DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed);
+ DBG("%s: %u %u\n", __FUNCTION__, medium, speed);
if (configNr >= RNDIS_MAX_CONFIGS) return -1;
rndis_per_dev_params [configNr].medium = medium;
@@ -1381,7 +1390,7 @@ static int rndis_proc_write (struct file *file, const char __user *buffer,
break;
default:
if (fl_speed) p->speed = speed;
- else DEBUG ("%c is not valid\n", c);
+ else DBG("%c is not valid\n", c);
break;
}
@@ -1410,12 +1419,12 @@ int __devinit rndis_init (void)
if (!(rndis_connect_state [i]
= create_proc_entry (name, 0660, NULL)))
{
- DEBUG ("%s :remove entries", __FUNCTION__);
+ DBG("%s :remove entries", __FUNCTION__);
while (i) {
sprintf (name, NAME_TEMPLATE, --i);
remove_proc_entry (name, NULL);
}
- DEBUG ("\n");
+ DBG("\n");
return -EIO;
}
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
new file mode 100644
index 00000000000..0be80c635c4
--- /dev/null
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -0,0 +1,2045 @@
+/*
+ * linux/drivers/usb/gadget/s3c2410_udc.c
+ *
+ * Samsung S3C24xx series on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
+ * Additional cleanups by Ben Dooks <ben-linux@fluff.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/version.h>
+#include <linux/clk.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <linux/usb.h>
+#include <linux/usb_gadget.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+#include <asm/arch/irqs.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-udc.h>
+#include <asm/arch/udc.h>
+
+#include <asm/mach-types.h>
+
+#include "s3c2410_udc.h"
+
+#define DRIVER_DESC "S3C2410 USB Device Controller Gadget"
+#define DRIVER_VERSION "29 Apr 2007"
+#define DRIVER_AUTHOR "Herbert Pötzl <herbert@13thfloor.at>, " \
+ "Arnaud Patard <arnaud.patard@rtp-net.org>"
+
+static const char gadget_name[] = "s3c2410_udc";
+static const char driver_desc[] = DRIVER_DESC;
+
+static struct s3c2410_udc *the_controller;
+static struct clk *udc_clock;
+static struct clk *usb_bus_clock;
+static void __iomem *base_addr;
+static u64 rsrc_start;
+static u64 rsrc_len;
+static struct dentry *s3c2410_udc_debugfs_root;
+
+static inline u32 udc_read(u32 reg)
+{
+ return readb(base_addr + reg);
+}
+
+static inline void udc_write(u32 value, u32 reg)
+{
+ writeb(value, base_addr + reg);
+}
+
+static inline void udc_writeb(void __iomem *base, u32 value, u32 reg)
+{
+ writeb(value, base + reg);
+}
+
+static struct s3c2410_udc_mach_info *udc_info;
+
+/*************************** DEBUG FUNCTION ***************************/
+#define DEBUG_NORMAL 1
+#define DEBUG_VERBOSE 2
+
+#ifdef CONFIG_USB_S3C2410_DEBUG
+#define USB_S3C2410_DEBUG_LEVEL 0
+
+static uint32_t s3c2410_ticks = 0;
+
+static int dprintk(int level, const char *fmt, ...)
+{
+ static char printk_buf[1024];
+ static long prevticks;
+ static int invocation;
+ va_list args;
+ int len;
+
+ if (level > USB_S3C2410_DEBUG_LEVEL)
+ return 0;
+
+ if (s3c2410_ticks != prevticks) {
+ prevticks = s3c2410_ticks;
+ invocation = 0;
+ }
+
+ len = scnprintf(printk_buf,
+ sizeof(printk_buf), "%1lu.%02d USB: ",
+ prevticks, invocation++);
+
+ va_start(args, fmt);
+ len = vscnprintf(printk_buf+len,
+ sizeof(printk_buf)-len, fmt, args);
+ va_end(args);
+
+ return printk(KERN_DEBUG "%s", printk_buf);
+}
+#else
+static int dprintk(int level, const char *fmt, ...)
+{
+ return 0;
+}
+#endif
+static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
+{
+ u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
+ u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;
+ u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2;
+ u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2;
+
+ addr_reg = udc_read(S3C2410_UDC_FUNC_ADDR_REG);
+ pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
+ ep_int_reg = udc_read(S3C2410_UDC_EP_INT_REG);
+ usb_int_reg = udc_read(S3C2410_UDC_USB_INT_REG);
+ ep_int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+ usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG);
+ udc_write(0, S3C2410_UDC_INDEX_REG);
+ ep0_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ udc_write(1, S3C2410_UDC_INDEX_REG);
+ ep1_i_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ ep1_i_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG);
+ ep1_o_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ ep1_o_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG);
+ udc_write(2, S3C2410_UDC_INDEX_REG);
+ ep2_i_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ ep2_i_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG);
+ ep2_o_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ ep2_o_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG);
+
+ seq_printf(m, "FUNC_ADDR_REG : 0x%04X\n"
+ "PWR_REG : 0x%04X\n"
+ "EP_INT_REG : 0x%04X\n"
+ "USB_INT_REG : 0x%04X\n"
+ "EP_INT_EN_REG : 0x%04X\n"
+ "USB_INT_EN_REG : 0x%04X\n"
+ "EP0_CSR : 0x%04X\n"
+ "EP1_I_CSR1 : 0x%04X\n"
+ "EP1_I_CSR2 : 0x%04X\n"
+ "EP1_O_CSR1 : 0x%04X\n"
+ "EP1_O_CSR2 : 0x%04X\n"
+ "EP2_I_CSR1 : 0x%04X\n"
+ "EP2_I_CSR2 : 0x%04X\n"
+ "EP2_O_CSR1 : 0x%04X\n"
+ "EP2_O_CSR2 : 0x%04X\n",
+ addr_reg,pwr_reg,ep_int_reg,usb_int_reg,
+ ep_int_en_reg, usb_int_en_reg, ep0_csr,
+ ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2,
+ ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2
+ );
+
+ return 0;
+}
+
+static int s3c2410_udc_debugfs_fops_open(struct inode *inode,
+ struct file *file)
+{
+ return single_open(file, s3c2410_udc_debugfs_seq_show, NULL);
+}
+
+static const struct file_operations s3c2410_udc_debugfs_fops = {
+ .open = s3c2410_udc_debugfs_fops_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+/* io macros */
+
+static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base)
+{
+ udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY,
+ S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base)
+{
+ udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_clear_ep0_se(void __iomem *base)
+{
+ udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base)
+{
+ udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de(void __iomem *base)
+{
+ udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG);
+}
+
+inline void s3c2410_udc_set_ep0_ss(void __iomem *b)
+{
+ udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base)
+{
+ udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+
+ udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY
+ | S3C2410_UDC_EP0_CSR_DE),
+ S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base)
+{
+ udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
+ | S3C2410_UDC_EP0_CSR_SSE),
+ S3C2410_UDC_EP0_CSR_REG);
+}
+
+static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base)
+{
+ udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY
+ | S3C2410_UDC_EP0_CSR_DE),
+ S3C2410_UDC_EP0_CSR_REG);
+}
+
+/*------------------------- I/O ----------------------------------*/
+
+/*
+ * s3c2410_udc_done
+ */
+static void s3c2410_udc_done(struct s3c2410_ep *ep,
+ struct s3c2410_request *req, int status)
+{
+ unsigned halted = ep->halted;
+
+ list_del_init(&req->queue);
+
+ if (likely (req->req.status == -EINPROGRESS))
+ req->req.status = status;
+ else
+ status = req->req.status;
+
+ ep->halted = 1;
+ req->req.complete(&ep->ep, &req->req);
+ ep->halted = halted;
+}
+
+static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
+ struct s3c2410_ep *ep, int status)
+{
+ /* Sanity check */
+ if (&ep->queue == NULL)
+ return;
+
+ while (!list_empty (&ep->queue)) {
+ struct s3c2410_request *req;
+ req = list_entry (ep->queue.next, struct s3c2410_request,
+ queue);
+ s3c2410_udc_done(ep, req, status);
+ }
+}
+
+static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev)
+{
+ unsigned i;
+
+ /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
+ * fifos, and pending transactions mustn't be continued in any case.
+ */
+
+ for (i = 1; i < S3C2410_ENDPOINTS; i++)
+ s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED);
+}
+
+static inline int s3c2410_udc_fifo_count_out(void)
+{
+ int tmp;
+
+ tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;
+ tmp |= udc_read(S3C2410_UDC_OUT_FIFO_CNT1_REG);
+ return tmp;
+}
+
+/*
+ * s3c2410_udc_write_packet
+ */
+static inline int s3c2410_udc_write_packet(int fifo,
+ struct s3c2410_request *req,
+ unsigned max)
+{
+ unsigned len = min(req->req.length - req->req.actual, max);
+ u8 *buf = req->req.buf + req->req.actual;
+
+ prefetch(buf);
+
+ dprintk(DEBUG_VERBOSE, "%s %d %d %d %d\n", __func__,
+ req->req.actual, req->req.length, len, req->req.actual + len);
+
+ req->req.actual += len;
+
+ udelay(5);
+ writesb(base_addr + fifo, buf, len);
+ return len;
+}
+
+/*
+ * s3c2410_udc_write_fifo
+ *
+ * return: 0 = still running, 1 = completed, negative = errno
+ */
+static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep,
+ struct s3c2410_request *req)
+{
+ unsigned count;
+ int is_last;
+ u32 idx;
+ int fifo_reg;
+ u32 ep_csr;
+
+ idx = ep->bEndpointAddress & 0x7F;
+ switch (idx) {
+ default:
+ idx = 0;
+ case 0:
+ fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
+ break;
+ case 1:
+ fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
+ break;
+ case 2:
+ fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
+ break;
+ case 3:
+ fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
+ break;
+ case 4:
+ fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
+ break;
+ }
+
+ count = s3c2410_udc_write_packet(fifo_reg, req, ep->ep.maxpacket);
+
+ /* last packet is often short (sometimes a zlp) */
+ if (count != ep->ep.maxpacket)
+ is_last = 1;
+ else if (req->req.length != req->req.actual || req->req.zero)
+ is_last = 0;
+ else
+ is_last = 2;
+
+ /* Only ep0 debug messages are interesting */
+ if (idx == 0)
+ dprintk(DEBUG_NORMAL,
+ "Written ep%d %d.%d of %d b [last %d,z %d]\n",
+ idx, count, req->req.actual, req->req.length,
+ is_last, req->req.zero);
+
+ if (is_last) {
+ /* The order is important. It prevents sending 2 packets
+ * at the same time */
+
+ if (idx == 0) {
+ /* Reset signal => no need to say 'data sent' */
+ if (! (udc_read(S3C2410_UDC_USB_INT_REG)
+ & S3C2410_UDC_USBINT_RESET))
+ s3c2410_udc_set_ep0_de_in(base_addr);
+ ep->dev->ep0state=EP0_IDLE;
+ } else {
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
+ S3C2410_UDC_IN_CSR1_REG);
+ }
+
+ s3c2410_udc_done(ep, req, 0);
+ is_last = 1;
+ } else {
+ if (idx == 0) {
+ /* Reset signal => no need to say 'data sent' */
+ if (! (udc_read(S3C2410_UDC_USB_INT_REG)
+ & S3C2410_UDC_USBINT_RESET))
+ s3c2410_udc_set_ep0_ipr(base_addr);
+ } else {
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY,
+ S3C2410_UDC_IN_CSR1_REG);
+ }
+ }
+
+ return is_last;
+}
+
+static inline int s3c2410_udc_read_packet(int fifo, u8 *buf,
+ struct s3c2410_request *req, unsigned avail)
+{
+ unsigned len;
+
+ len = min(req->req.length - req->req.actual, avail);
+ req->req.actual += len;
+
+ readsb(fifo + base_addr, buf, len);
+ return len;
+}
+
+/*
+ * return: 0 = still running, 1 = queue empty, negative = errno
+ */
+static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep,
+ struct s3c2410_request *req)
+{
+ u8 *buf;
+ u32 ep_csr;
+ unsigned bufferspace;
+ int is_last=1;
+ unsigned avail;
+ int fifo_count = 0;
+ u32 idx;
+ int fifo_reg;
+
+ idx = ep->bEndpointAddress & 0x7F;
+
+ switch (idx) {
+ default:
+ idx = 0;
+ case 0:
+ fifo_reg = S3C2410_UDC_EP0_FIFO_REG;
+ break;
+ case 1:
+ fifo_reg = S3C2410_UDC_EP1_FIFO_REG;
+ break;
+ case 2:
+ fifo_reg = S3C2410_UDC_EP2_FIFO_REG;
+ break;
+ case 3:
+ fifo_reg = S3C2410_UDC_EP3_FIFO_REG;
+ break;
+ case 4:
+ fifo_reg = S3C2410_UDC_EP4_FIFO_REG;
+ break;
+ }
+
+ if (!req->req.length)
+ return 1;
+
+ buf = req->req.buf + req->req.actual;
+ bufferspace = req->req.length - req->req.actual;
+ if (!bufferspace) {
+ dprintk(DEBUG_NORMAL, "%s: buffer full!\n", __func__);
+ return -1;
+ }
+
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+
+ fifo_count = s3c2410_udc_fifo_count_out();
+ dprintk(DEBUG_NORMAL, "%s fifo count : %d\n", __func__, fifo_count);
+
+ if (fifo_count > ep->ep.maxpacket)
+ avail = ep->ep.maxpacket;
+ else
+ avail = fifo_count;
+
+ fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail);
+
+ /* checking this with ep0 is not accurate as we already
+ * read a control request
+ **/
+ if (idx != 0 && fifo_count < ep->ep.maxpacket) {
+ is_last = 1;
+ /* overflowed this request? flush extra data */
+ if (fifo_count != avail)
+ req->req.status = -EOVERFLOW;
+ } else {
+ is_last = (req->req.length <= req->req.actual) ? 1 : 0;
+ }
+
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ fifo_count = s3c2410_udc_fifo_count_out();
+
+ /* Only ep0 debug messages are interesting */
+ if (idx == 0)
+ dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n",
+ __func__, fifo_count,is_last);
+
+ if (is_last) {
+ if (idx == 0) {
+ s3c2410_udc_set_ep0_de_out(base_addr);
+ ep->dev->ep0state = EP0_IDLE;
+ } else {
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
+ S3C2410_UDC_OUT_CSR1_REG);
+ }
+
+ s3c2410_udc_done(ep, req, 0);
+ } else {
+ if (idx == 0) {
+ s3c2410_udc_clear_ep0_opr(base_addr);
+ } else {
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY,
+ S3C2410_UDC_OUT_CSR1_REG);
+ }
+ }
+
+ return is_last;
+}
+
+static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq)
+{
+ unsigned char *outbuf = (unsigned char*)crq;
+ int bytes_read = 0;
+
+ udc_write(0, S3C2410_UDC_INDEX_REG);
+
+ bytes_read = s3c2410_udc_fifo_count_out();
+
+ dprintk(DEBUG_NORMAL, "%s: fifo_count=%d\n", __func__, bytes_read);
+
+ if (bytes_read > sizeof(struct usb_ctrlrequest))
+ bytes_read = sizeof(struct usb_ctrlrequest);
+
+ readsb(S3C2410_UDC_EP0_FIFO_REG + base_addr, outbuf, bytes_read);
+
+ dprintk(DEBUG_VERBOSE, "%s: len=%d %02x:%02x {%x,%x,%x}\n", __func__,
+ bytes_read, crq->bRequest, crq->bRequestType,
+ crq->wValue, crq->wIndex, crq->wLength);
+
+ return bytes_read;
+}
+
+static int s3c2410_udc_get_status(struct s3c2410_udc *dev,
+ struct usb_ctrlrequest *crq)
+{
+ u16 status = 0;
+ u8 ep_num = crq->wIndex & 0x7F;
+ u8 is_in = crq->wIndex & USB_DIR_IN;
+
+ switch (crq->bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_INTERFACE:
+ break;
+
+ case USB_RECIP_DEVICE:
+ status = dev->devstatus;
+ break;
+
+ case USB_RECIP_ENDPOINT:
+ if (ep_num > 4 || crq->wLength > 2)
+ return 1;
+
+ if (ep_num == 0) {
+ udc_write(0, S3C2410_UDC_INDEX_REG);
+ status = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ status = status & S3C2410_UDC_EP0_CSR_SENDSTL;
+ } else {
+ udc_write(ep_num, S3C2410_UDC_INDEX_REG);
+ if (is_in) {
+ status = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ status = status & S3C2410_UDC_ICSR1_SENDSTL;
+ } else {
+ status = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+ status = status & S3C2410_UDC_OCSR1_SENDSTL;
+ }
+ }
+
+ status = status ? 1 : 0;
+ break;
+
+ default:
+ return 1;
+ }
+
+ /* Seems to be needed to get it working. ouch :( */
+ udelay(5);
+ udc_write(status & 0xFF, S3C2410_UDC_EP0_FIFO_REG);
+ udc_write(status >> 8, S3C2410_UDC_EP0_FIFO_REG);
+ s3c2410_udc_set_ep0_de_in(base_addr);
+
+ return 0;
+}
+/*------------------------- usb state machine -------------------------------*/
+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value);
+
+static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev,
+ struct s3c2410_ep *ep,
+ struct usb_ctrlrequest *crq,
+ u32 ep0csr)
+{
+ int len, ret, tmp;
+
+ /* start control request? */
+ if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY))
+ return;
+
+ s3c2410_udc_nuke(dev, ep, -EPROTO);
+
+ len = s3c2410_udc_read_fifo_crq(crq);
+ if (len != sizeof(*crq)) {
+ dprintk(DEBUG_NORMAL, "setup begin: fifo READ ERROR"
+ " wanted %d bytes got %d. Stalling out...\n",
+ sizeof(*crq), len);
+ s3c2410_udc_set_ep0_ss(base_addr);
+ return;
+ }
+
+ dprintk(DEBUG_NORMAL, "bRequest = %d bRequestType %d wLength = %d\n",
+ crq->bRequest, crq->bRequestType, crq->wLength);
+
+ /* cope with automagic for some standard requests. */
+ dev->req_std = (crq->bRequestType & USB_TYPE_MASK)
+ == USB_TYPE_STANDARD;
+ dev->req_config = 0;
+ dev->req_pending = 1;
+
+ switch (crq->bRequest) {
+ case USB_REQ_SET_CONFIGURATION:
+ dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ... \n");
+
+ if (crq->bRequestType == USB_RECIP_DEVICE) {
+ dev->req_config = 1;
+ s3c2410_udc_set_ep0_de_out(base_addr);
+ }
+ break;
+
+ case USB_REQ_SET_INTERFACE:
+ dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ... \n");
+
+ if (crq->bRequestType == USB_RECIP_INTERFACE) {
+ dev->req_config = 1;
+ s3c2410_udc_set_ep0_de_out(base_addr);
+ }
+ break;
+
+ case USB_REQ_SET_ADDRESS:
+ dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ... \n");
+
+ if (crq->bRequestType == USB_RECIP_DEVICE) {
+ tmp = crq->wValue & 0x7F;
+ dev->address = tmp;
+ udc_write((tmp | S3C2410_UDC_FUNCADDR_UPDATE),
+ S3C2410_UDC_FUNC_ADDR_REG);
+ s3c2410_udc_set_ep0_de_out(base_addr);
+ return;
+ }
+ break;
+
+ case USB_REQ_GET_STATUS:
+ dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ... \n");
+ s3c2410_udc_clear_ep0_opr(base_addr);
+
+ if (dev->req_std) {
+ if (!s3c2410_udc_get_status(dev, crq)) {
+ return;
+ }
+ }
+ break;
+
+ case USB_REQ_CLEAR_FEATURE:
+ s3c2410_udc_clear_ep0_opr(base_addr);
+
+ if (crq->bRequestType != USB_RECIP_ENDPOINT)
+ break;
+
+ if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
+ break;
+
+ s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 0);
+ s3c2410_udc_set_ep0_de_out(base_addr);
+ return;
+
+ case USB_REQ_SET_FEATURE:
+ s3c2410_udc_clear_ep0_opr(base_addr);
+
+ if (crq->bRequestType != USB_RECIP_ENDPOINT)
+ break;
+
+ if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0)
+ break;
+
+ s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 1);
+ s3c2410_udc_set_ep0_de_out(base_addr);
+ return;
+
+ default:
+ s3c2410_udc_clear_ep0_opr(base_addr);
+ break;
+ }
+
+ if (crq->bRequestType & USB_DIR_IN)
+ dev->ep0state = EP0_IN_DATA_PHASE;
+ else
+ dev->ep0state = EP0_OUT_DATA_PHASE;
+
+ ret = dev->driver->setup(&dev->gadget, crq);
+ if (ret < 0) {
+ if (dev->req_config) {
+ dprintk(DEBUG_NORMAL, "config change %02x fail %d?\n",
+ crq->bRequest, ret);
+ return;
+ }
+
+ if (ret == -EOPNOTSUPP)
+ dprintk(DEBUG_NORMAL, "Operation not supported\n");
+ else
+ dprintk(DEBUG_NORMAL,
+ "dev->driver->setup failed. (%d)\n", ret);
+
+ udelay(5);
+ s3c2410_udc_set_ep0_ss(base_addr);
+ s3c2410_udc_set_ep0_de_out(base_addr);
+ dev->ep0state = EP0_IDLE;
+ /* deferred i/o == no response yet */
+ } else if (dev->req_pending) {
+ dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n");
+ dev->req_pending=0;
+ }
+
+ dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]);
+}
+
+static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev)
+{
+ u32 ep0csr;
+ struct s3c2410_ep *ep = &dev->ep[0];
+ struct s3c2410_request *req;
+ struct usb_ctrlrequest crq;
+
+ if (list_empty(&ep->queue))
+ req = NULL;
+ else
+ req = list_entry(ep->queue.next, struct s3c2410_request, queue);
+
+ /* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to
+ * S3C2410_UDC_EP0_CSR_REG when index is zero */
+
+ udc_write(0, S3C2410_UDC_INDEX_REG);
+ ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+
+ dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n",
+ ep0csr, ep0states[dev->ep0state]);
+
+ /* clear stall status */
+ if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) {
+ s3c2410_udc_nuke(dev, ep, -EPIPE);
+ dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n");
+ s3c2410_udc_clear_ep0_sst(base_addr);
+ dev->ep0state = EP0_IDLE;
+ return;
+ }
+
+ /* clear setup end */
+ if (ep0csr & S3C2410_UDC_EP0_CSR_SE) {
+ dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n");
+ s3c2410_udc_nuke(dev, ep, 0);
+ s3c2410_udc_clear_ep0_se(base_addr);
+ dev->ep0state = EP0_IDLE;
+ }
+
+ switch (dev->ep0state) {
+ case EP0_IDLE:
+ s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr);
+ break;
+
+ case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */
+ dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n");
+ if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) {
+ s3c2410_udc_write_fifo(ep, req);
+ }
+ break;
+
+ case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */
+ dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n");
+ if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) {
+ s3c2410_udc_read_fifo(ep,req);
+ }
+ break;
+
+ case EP0_END_XFER:
+ dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n");
+ dev->ep0state = EP0_IDLE;
+ break;
+
+ case EP0_STALL:
+ dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n");
+ dev->ep0state = EP0_IDLE;
+ break;
+ }
+}
+
+/*
+ * handle_ep - Manage I/O endpoints
+ */
+
+static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
+{
+ struct s3c2410_request *req;
+ int is_in = ep->bEndpointAddress & USB_DIR_IN;
+ u32 ep_csr1;
+ u32 idx;
+
+ if (likely (!list_empty(&ep->queue)))
+ req = list_entry(ep->queue.next,
+ struct s3c2410_request, queue);
+ else
+ req = NULL;
+
+ idx = ep->bEndpointAddress & 0x7F;
+
+ if (is_in) {
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n",
+ idx, ep_csr1, req ? 1 : 0);
+
+ if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
+ dprintk(DEBUG_VERBOSE, "st\n");
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL,
+ S3C2410_UDC_IN_CSR1_REG);
+ return;
+ }
+
+ if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) {
+ s3c2410_udc_write_fifo(ep,req);
+ }
+ } else {
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
+ dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1);
+
+ if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL,
+ S3C2410_UDC_OUT_CSR1_REG);
+ return;
+ }
+
+ if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
+ s3c2410_udc_read_fifo(ep,req);
+ }
+ }
+}
+
+#include <asm/arch/regs-irq.h>
+
+/*
+ * s3c2410_udc_irq - interrupt handler
+ */
+static irqreturn_t s3c2410_udc_irq(int irq, void *_dev)
+{
+ struct s3c2410_udc *dev = _dev;
+ int usb_status;
+ int usbd_status;
+ int pwr_reg;
+ int ep0csr;
+ int i;
+ u32 idx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ /* Driver connected ? */
+ if (!dev->driver) {
+ /* Clear interrupts */
+ udc_write(udc_read(S3C2410_UDC_USB_INT_REG),
+ S3C2410_UDC_USB_INT_REG);
+ udc_write(udc_read(S3C2410_UDC_EP_INT_REG),
+ S3C2410_UDC_EP_INT_REG);
+ }
+
+ /* Save index */
+ idx = udc_read(S3C2410_UDC_INDEX_REG);
+
+ /* Read status registers */
+ usb_status = udc_read(S3C2410_UDC_USB_INT_REG);
+ usbd_status = udc_read(S3C2410_UDC_EP_INT_REG);
+ pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
+
+ udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
+ ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+
+ dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n",
+ usb_status, usbd_status, pwr_reg, ep0csr);
+
+ /*
+ * Now, handle interrupts. There's two types :
+ * - Reset, Resume, Suspend coming -> usb_int_reg
+ * - EP -> ep_int_reg
+ */
+
+ /* RESET */
+ if (usb_status & S3C2410_UDC_USBINT_RESET) {
+ /* two kind of reset :
+ * - reset start -> pwr reg = 8
+ * - reset end -> pwr reg = 0
+ **/
+ dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n",
+ ep0csr, pwr_reg);
+
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+ udc_write(0x00, S3C2410_UDC_INDEX_REG);
+ udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3,
+ S3C2410_UDC_MAXP_REG);
+ dev->address = 0;
+
+ dev->ep0state = EP0_IDLE;
+ dev->gadget.speed = USB_SPEED_FULL;
+
+ /* clear interrupt */
+ udc_write(S3C2410_UDC_USBINT_RESET,
+ S3C2410_UDC_USB_INT_REG);
+
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return IRQ_HANDLED;
+ }
+
+ /* RESUME */
+ if (usb_status & S3C2410_UDC_USBINT_RESUME) {
+ dprintk(DEBUG_NORMAL, "USB resume\n");
+
+ /* clear interrupt */
+ udc_write(S3C2410_UDC_USBINT_RESUME,
+ S3C2410_UDC_USB_INT_REG);
+
+ if (dev->gadget.speed != USB_SPEED_UNKNOWN
+ && dev->driver
+ && dev->driver->resume)
+ dev->driver->resume(&dev->gadget);
+ }
+
+ /* SUSPEND */
+ if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {
+ dprintk(DEBUG_NORMAL, "USB suspend\n");
+
+ /* clear interrupt */
+ udc_write(S3C2410_UDC_USBINT_SUSPEND,
+ S3C2410_UDC_USB_INT_REG);
+
+ if (dev->gadget.speed != USB_SPEED_UNKNOWN
+ && dev->driver
+ && dev->driver->suspend)
+ dev->driver->suspend(&dev->gadget);
+
+ dev->ep0state = EP0_IDLE;
+ }
+
+ /* EP */
+ /* control traffic */
+ /* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready
+ * generate an interrupt
+ */
+ if (usbd_status & S3C2410_UDC_INT_EP0) {
+ dprintk(DEBUG_VERBOSE, "USB ep0 irq\n");
+ /* Clear the interrupt bit by setting it to 1 */
+ udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
+ s3c2410_udc_handle_ep0(dev);
+ }
+
+ /* endpoint data transfers */
+ for (i = 1; i < S3C2410_ENDPOINTS; i++) {
+ u32 tmp = 1 << i;
+ if (usbd_status & tmp) {
+ dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i);
+
+ /* Clear the interrupt bit by setting it to 1 */
+ udc_write(tmp, S3C2410_UDC_EP_INT_REG);
+ s3c2410_udc_handle_ep(&dev->ep[i]);
+ }
+ }
+
+ dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", irq);
+
+ /* Restore old index */
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ return IRQ_HANDLED;
+}
+/*------------------------- s3c2410_ep_ops ----------------------------------*/
+
+static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep)
+{
+ return container_of(ep, struct s3c2410_ep, ep);
+}
+
+static inline struct s3c2410_udc *to_s3c2410_udc(struct usb_gadget *gadget)
+{
+ return container_of(gadget, struct s3c2410_udc, gadget);
+}
+
+static inline struct s3c2410_request *to_s3c2410_req(struct usb_request *req)
+{
+ return container_of(req, struct s3c2410_request, req);
+}
+
+/*
+ * s3c2410_udc_ep_enable
+ */
+static int s3c2410_udc_ep_enable(struct usb_ep *_ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct s3c2410_udc *dev;
+ struct s3c2410_ep *ep;
+ u32 max, tmp;
+ unsigned long flags;
+ u32 csr1,csr2;
+ u32 int_en_reg;
+
+ ep = to_s3c2410_ep(_ep);
+
+ if (!_ep || !desc || ep->desc
+ || _ep->name == ep0name
+ || desc->bDescriptorType != USB_DT_ENDPOINT)
+ return -EINVAL;
+
+ dev = ep->dev;
+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+ return -ESHUTDOWN;
+
+ max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff;
+
+ local_irq_save (flags);
+ _ep->maxpacket = max & 0x7ff;
+ ep->desc = desc;
+ ep->halted = 0;
+ ep->bEndpointAddress = desc->bEndpointAddress;
+
+ /* set max packet */
+ udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+ udc_write(max >> 3, S3C2410_UDC_MAXP_REG);
+
+ /* set type, direction, address; reset fifo counters */
+ if (desc->bEndpointAddress & USB_DIR_IN) {
+ csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT;
+ csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN;
+
+ udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+ udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
+ udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+ udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
+ } else {
+ /* don't flush in fifo or it will cause endpoint interrupt */
+ csr1 = S3C2410_UDC_ICSR1_CLRDT;
+ csr2 = S3C2410_UDC_ICSR2_DMAIEN;
+
+ udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+ udc_write(csr1, S3C2410_UDC_IN_CSR1_REG);
+ udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+ udc_write(csr2, S3C2410_UDC_IN_CSR2_REG);
+
+ csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT;
+ csr2 = S3C2410_UDC_OCSR2_DMAIEN;
+
+ udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+ udc_write(csr1, S3C2410_UDC_OUT_CSR1_REG);
+ udc_write(ep->num, S3C2410_UDC_INDEX_REG);
+ udc_write(csr2, S3C2410_UDC_OUT_CSR2_REG);
+ }
+
+ /* enable irqs */
+ int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+ udc_write(int_en_reg | (1 << ep->num), S3C2410_UDC_EP_INT_EN_REG);
+
+ /* print some debug message */
+ tmp = desc->bEndpointAddress;
+ dprintk (DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n",
+ _ep->name,ep->num, tmp,
+ desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max);
+
+ local_irq_restore (flags);
+ s3c2410_udc_set_halt(_ep, 0);
+
+ return 0;
+}
+
+/*
+ * s3c2410_udc_ep_disable
+ */
+static int s3c2410_udc_ep_disable(struct usb_ep *_ep)
+{
+ struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
+ unsigned long flags;
+ u32 int_en_reg;
+
+ if (!_ep || !ep->desc) {
+ dprintk(DEBUG_NORMAL, "%s not enabled\n",
+ _ep ? ep->ep.name : NULL);
+ return -EINVAL;
+ }
+
+ local_irq_save(flags);
+
+ dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name);
+
+ ep->desc = NULL;
+ ep->halted = 1;
+
+ s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN);
+
+ /* disable irqs */
+ int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
+ udc_write(int_en_reg & ~(1<<ep->num), S3C2410_UDC_EP_INT_EN_REG);
+
+ local_irq_restore(flags);
+
+ dprintk(DEBUG_NORMAL, "%s disabled\n", _ep->name);
+
+ return 0;
+}
+
+/*
+ * s3c2410_udc_alloc_request
+ */
+static struct usb_request *
+s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags)
+{
+ struct s3c2410_request *req;
+
+ dprintk(DEBUG_VERBOSE,"%s(%p,%d)\n", __func__, _ep, mem_flags);
+
+ if (!_ep)
+ return NULL;
+
+ req = kzalloc (sizeof(struct s3c2410_request), mem_flags);
+ if (!req)
+ return NULL;
+
+ INIT_LIST_HEAD (&req->queue);
+ return &req->req;
+}
+
+/*
+ * s3c2410_udc_free_request
+ */
+static void
+s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
+ struct s3c2410_request *req = to_s3c2410_req(_req);
+
+ dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
+
+ if (!ep || !_req || (!ep->desc && _ep->name != ep0name))
+ return;
+
+ WARN_ON (!list_empty (&req->queue));
+ kfree(req);
+}
+
+/*
+ * s3c2410_udc_queue
+ */
+static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req,
+ gfp_t gfp_flags)
+{
+ struct s3c2410_request *req = to_s3c2410_req(_req);
+ struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
+ struct s3c2410_udc *dev;
+ u32 ep_csr = 0;
+ int fifo_count = 0;
+ unsigned long flags;
+
+ if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+ dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
+ return -EINVAL;
+ }
+
+ dev = ep->dev;
+ if (unlikely (!dev->driver
+ || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
+ return -ESHUTDOWN;
+ }
+
+ local_irq_save (flags);
+
+ if (unlikely(!_req || !_req->complete
+ || !_req->buf || !list_empty(&req->queue))) {
+ if (!_req)
+ dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__);
+ else {
+ dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n",
+ __func__, !_req->complete,!_req->buf,
+ !list_empty(&req->queue));
+ }
+
+ local_irq_restore(flags);
+ return -EINVAL;
+ }
+
+ _req->status = -EINPROGRESS;
+ _req->actual = 0;
+
+ dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n",
+ __func__, ep->bEndpointAddress, _req->length);
+
+ if (ep->bEndpointAddress) {
+ udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG);
+
+ ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN)
+ ? S3C2410_UDC_IN_CSR1_REG
+ : S3C2410_UDC_OUT_CSR1_REG);
+ fifo_count = s3c2410_udc_fifo_count_out();
+ } else {
+ udc_write(0, S3C2410_UDC_INDEX_REG);
+ ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
+ fifo_count = s3c2410_udc_fifo_count_out();
+ }
+
+ /* kickstart this i/o queue? */
+ if (list_empty(&ep->queue) && !ep->halted) {
+ if (ep->bEndpointAddress == 0 /* ep0 */) {
+ switch (dev->ep0state) {
+ case EP0_IN_DATA_PHASE:
+ if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY)
+ && s3c2410_udc_write_fifo(ep,
+ req)) {
+ dev->ep0state = EP0_IDLE;
+ req = NULL;
+ }
+ break;
+
+ case EP0_OUT_DATA_PHASE:
+ if ((!_req->length)
+ || ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
+ && s3c2410_udc_read_fifo(ep,
+ req))) {
+ dev->ep0state = EP0_IDLE;
+ req = NULL;
+ }
+ break;
+
+ default:
+ local_irq_restore(flags);
+ return -EL2HLT;
+ }
+ } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0
+ && (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY))
+ && s3c2410_udc_write_fifo(ep, req)) {
+ req = NULL;
+ } else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)
+ && fifo_count
+ && s3c2410_udc_read_fifo(ep, req)) {
+ req = NULL;
+ }
+ }
+
+ /* pio or dma irq handler advances the queue. */
+ if (likely (req != 0))
+ list_add_tail(&req->queue, &ep->queue);
+
+ local_irq_restore(flags);
+
+ dprintk(DEBUG_VERBOSE, "%s ok\n", __func__);
+ return 0;
+}
+
+/*
+ * s3c2410_udc_dequeue
+ */
+static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
+ struct s3c2410_udc *udc;
+ int retval = -EINVAL;
+ unsigned long flags;
+ struct s3c2410_request *req = NULL;
+
+ dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req);
+
+ if (!the_controller->driver)
+ return -ESHUTDOWN;
+
+ if (!_ep || !_req)
+ return retval;
+
+ udc = to_s3c2410_udc(ep->gadget);
+
+ local_irq_save (flags);
+
+ list_for_each_entry (req, &ep->queue, queue) {
+ if (&req->req == _req) {
+ list_del_init (&req->queue);
+ _req->status = -ECONNRESET;
+ retval = 0;
+ break;
+ }
+ }
+
+ if (retval == 0) {
+ dprintk(DEBUG_VERBOSE,
+ "dequeued req %p from %s, len %d buf %p\n",
+ req, _ep->name, _req->length, _req->buf);
+
+ s3c2410_udc_done(ep, req, -ECONNRESET);
+ }
+
+ local_irq_restore (flags);
+ return retval;
+}
+
+/*
+ * s3c2410_udc_set_halt
+ */
+static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value)
+{
+ struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
+ u32 ep_csr = 0;
+ unsigned long flags;
+ u32 idx;
+
+ if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
+ dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__);
+ return -EINVAL;
+ }
+
+ local_irq_save (flags);
+
+ idx = ep->bEndpointAddress & 0x7F;
+
+ if (idx == 0) {
+ s3c2410_udc_set_ep0_ss(base_addr);
+ s3c2410_udc_set_ep0_de_out(base_addr);
+ } else {
+ udc_write(idx, S3C2410_UDC_INDEX_REG);
+ ep_csr = udc_read((ep->bEndpointAddress &USB_DIR_IN)
+ ? S3C2410_UDC_IN_CSR1_REG
+ : S3C2410_UDC_OUT_CSR1_REG);
+
+ if ((ep->bEndpointAddress & USB_DIR_IN) != 0) {
+ if (value)
+ udc_write(ep_csr | S3C2410_UDC_ICSR1_SENDSTL,
+ S3C2410_UDC_IN_CSR1_REG);
+ else {
+ ep_csr &= ~S3C2410_UDC_ICSR1_SENDSTL;
+ udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
+ ep_csr |= S3C2410_UDC_ICSR1_CLRDT;
+ udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG);
+ }
+ } else {
+ if (value)
+ udc_write(ep_csr | S3C2410_UDC_OCSR1_SENDSTL,
+ S3C2410_UDC_OUT_CSR1_REG);
+ else {
+ ep_csr &= ~S3C2410_UDC_OCSR1_SENDSTL;
+ udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
+ ep_csr |= S3C2410_UDC_OCSR1_CLRDT;
+ udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG);
+ }
+ }
+ }
+
+ ep->halted = value ? 1 : 0;
+ local_irq_restore (flags);
+
+ return 0;
+}
+
+static const struct usb_ep_ops s3c2410_ep_ops = {
+ .enable = s3c2410_udc_ep_enable,
+ .disable = s3c2410_udc_ep_disable,
+
+ .alloc_request = s3c2410_udc_alloc_request,
+ .free_request = s3c2410_udc_free_request,
+
+ .queue = s3c2410_udc_queue,
+ .dequeue = s3c2410_udc_dequeue,
+
+ .set_halt = s3c2410_udc_set_halt,
+};
+
+/*------------------------- usb_gadget_ops ----------------------------------*/
+
+/*
+ * s3c2410_udc_get_frame
+ */
+static int s3c2410_udc_get_frame(struct usb_gadget *_gadget)
+{
+ int tmp;
+
+ dprintk(DEBUG_VERBOSE, "%s()\n", __func__);
+
+ tmp = udc_read(S3C2410_UDC_FRAME_NUM2_REG) << 8;
+ tmp |= udc_read(S3C2410_UDC_FRAME_NUM1_REG);
+ return tmp;
+}
+
+/*
+ * s3c2410_udc_wakeup
+ */
+static int s3c2410_udc_wakeup(struct usb_gadget *_gadget)
+{
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+ return 0;
+}
+
+/*
+ * s3c2410_udc_set_selfpowered
+ */
+static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value)
+{
+ struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+ if (value)
+ udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
+ else
+ udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
+
+ return 0;
+}
+
+static void s3c2410_udc_disable(struct s3c2410_udc *dev);
+static void s3c2410_udc_enable(struct s3c2410_udc *dev);
+
+static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
+{
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+ if (udc_info && udc_info->udc_command) {
+ if (is_on)
+ s3c2410_udc_enable(udc);
+ else {
+ if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+ if (udc->driver && udc->driver->disconnect)
+ udc->driver->disconnect(&udc->gadget);
+
+ }
+ s3c2410_udc_disable(udc);
+ }
+ }
+ else
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int s3c2410_udc_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+ struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+ udc->vbus = (is_active != 0);
+ s3c2410_udc_set_pullup(udc, is_active);
+ return 0;
+}
+
+static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on)
+{
+ struct s3c2410_udc *udc = to_s3c2410_udc(gadget);
+
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+ s3c2410_udc_set_pullup(udc, is_on ? 0 : 1);
+ return 0;
+}
+
+static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev)
+{
+ struct s3c2410_udc *dev = _dev;
+ unsigned int value;
+
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+ value = s3c2410_gpio_getpin(udc_info->vbus_pin);
+
+ if (udc_info->vbus_pin_inverted)
+ value = !value;
+
+ if (value != dev->vbus)
+ s3c2410_udc_vbus_session(&dev->gadget, value);
+
+ return IRQ_HANDLED;
+}
+
+static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
+{
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+ if (udc_info && udc_info->vbus_draw) {
+ udc_info->vbus_draw(ma);
+ return 0;
+ }
+
+ return -ENOTSUPP;
+}
+
+static const struct usb_gadget_ops s3c2410_ops = {
+ .get_frame = s3c2410_udc_get_frame,
+ .wakeup = s3c2410_udc_wakeup,
+ .set_selfpowered = s3c2410_udc_set_selfpowered,
+ .pullup = s3c2410_udc_pullup,
+ .vbus_session = s3c2410_udc_vbus_session,
+ .vbus_draw = s3c2410_vbus_draw,
+};
+
+/*------------------------- gadget driver handling---------------------------*/
+/*
+ * s3c2410_udc_disable
+ */
+static void s3c2410_udc_disable(struct s3c2410_udc *dev)
+{
+ dprintk(DEBUG_NORMAL, "%s()\n", __func__);
+
+ /* Disable all interrupts */
+ udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG);
+ udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG);
+
+ /* Clear the interrupt registers */
+ udc_write(S3C2410_UDC_USBINT_RESET
+ | S3C2410_UDC_USBINT_RESUME
+ | S3C2410_UDC_USBINT_SUSPEND,
+ S3C2410_UDC_USB_INT_REG);
+
+ udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
+
+ /* Good bye, cruel world */
+ if (udc_info && udc_info->udc_command)
+ udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+
+ /* Set speed to unknown */
+ dev->gadget.speed = USB_SPEED_UNKNOWN;
+}
+
+/*
+ * s3c2410_udc_reinit
+ */
+static void s3c2410_udc_reinit(struct s3c2410_udc *dev)
+{
+ u32 i;
+
+ /* device/ep0 records init */
+ INIT_LIST_HEAD (&dev->gadget.ep_list);
+ INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
+ dev->ep0state = EP0_IDLE;
+
+ for (i = 0; i < S3C2410_ENDPOINTS; i++) {
+ struct s3c2410_ep *ep = &dev->ep[i];
+
+ if (i != 0)
+ list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);
+
+ ep->dev = dev;
+ ep->desc = NULL;
+ ep->halted = 0;
+ INIT_LIST_HEAD (&ep->queue);
+ }
+}
+
+/*
+ * s3c2410_udc_enable
+ */
+static void s3c2410_udc_enable(struct s3c2410_udc *dev)
+{
+ int i;
+
+ dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n");
+
+ /* dev->gadget.speed = USB_SPEED_UNKNOWN; */
+ dev->gadget.speed = USB_SPEED_FULL;
+
+ /* Set MAXP for all endpoints */
+ for (i = 0; i < S3C2410_ENDPOINTS; i++) {
+ udc_write(i, S3C2410_UDC_INDEX_REG);
+ udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3,
+ S3C2410_UDC_MAXP_REG);
+ }
+
+ /* Set default power state */
+ udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);
+
+ /* Enable reset and suspend interrupt interrupts */
+ udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND,
+ S3C2410_UDC_USB_INT_EN_REG);
+
+ /* Enable ep0 interrupt */
+ udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);
+
+ /* time to say "hello, world" */
+ if (udc_info && udc_info->udc_command)
+ udc_info->udc_command(S3C2410_UDC_P_ENABLE);
+}
+
+/*
+ * usb_gadget_register_driver
+ */
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+ struct s3c2410_udc *udc = the_controller;
+ int retval;
+
+ dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",
+ driver->driver.name);
+
+ /* Sanity checks */
+ if (!udc)
+ return -ENODEV;
+
+ if (udc->driver)
+ return -EBUSY;
+
+ if (!driver->bind || !driver->setup
+ || driver->speed != USB_SPEED_FULL) {
+ printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",
+ driver->bind, driver->setup, driver->speed);
+ return -EINVAL;
+ }
+#if defined(MODULE)
+ if (!driver->unbind) {
+ printk(KERN_ERR "Invalid driver: no unbind method\n");
+ return -EINVAL;
+ }
+#endif
+
+ /* Hook the driver */
+ udc->driver = driver;
+ udc->gadget.dev.driver = &driver->driver;
+
+ /* Bind the driver */
+ if ((retval = device_add(&udc->gadget.dev)) != 0) {
+ printk(KERN_ERR "Error in device_add() : %d\n",retval);
+ goto register_error;
+ }
+
+ dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",
+ driver->driver.name);
+
+ if ((retval = driver->bind (&udc->gadget)) != 0) {
+ device_del(&udc->gadget.dev);
+ goto register_error;
+ }
+
+ /* Enable udc */
+ s3c2410_udc_enable(udc);
+
+ return 0;
+
+register_error:
+ udc->driver = NULL;
+ udc->gadget.dev.driver = NULL;
+ return retval;
+}
+
+/*
+ * usb_gadget_unregister_driver
+ */
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+ struct s3c2410_udc *udc = the_controller;
+
+ if (!udc)
+ return -ENODEV;
+
+ if (!driver || driver != udc->driver || !driver->unbind)
+ return -EINVAL;
+
+ dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
+ driver->driver.name);
+
+ if (driver->disconnect)
+ driver->disconnect(&udc->gadget);
+
+ device_del(&udc->gadget.dev);
+ udc->driver = NULL;
+
+ /* Disable udc */
+ s3c2410_udc_disable(udc);
+
+ return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+static struct s3c2410_udc memory = {
+ .gadget = {
+ .ops = &s3c2410_ops,
+ .ep0 = &memory.ep[0].ep,
+ .name = gadget_name,
+ .dev = {
+ .bus_id = "gadget",
+ },
+ },
+
+ /* control endpoint */
+ .ep[0] = {
+ .num = 0,
+ .ep = {
+ .name = ep0name,
+ .ops = &s3c2410_ep_ops,
+ .maxpacket = EP0_FIFO_SIZE,
+ },
+ .dev = &memory,
+ },
+
+ /* first group of endpoints */
+ .ep[1] = {
+ .num = 1,
+ .ep = {
+ .name = "ep1-bulk",
+ .ops = &s3c2410_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = EP_FIFO_SIZE,
+ .bEndpointAddress = 1,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ },
+ .ep[2] = {
+ .num = 2,
+ .ep = {
+ .name = "ep2-bulk",
+ .ops = &s3c2410_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = EP_FIFO_SIZE,
+ .bEndpointAddress = 2,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ },
+ .ep[3] = {
+ .num = 3,
+ .ep = {
+ .name = "ep3-bulk",
+ .ops = &s3c2410_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = EP_FIFO_SIZE,
+ .bEndpointAddress = 3,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ },
+ .ep[4] = {
+ .num = 4,
+ .ep = {
+ .name = "ep4-bulk",
+ .ops = &s3c2410_ep_ops,
+ .maxpacket = EP_FIFO_SIZE,
+ },
+ .dev = &memory,
+ .fifo_size = EP_FIFO_SIZE,
+ .bEndpointAddress = 4,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ }
+
+};
+
+/*
+ * probe - binds to the platform device
+ */
+static int s3c2410_udc_probe(struct platform_device *pdev)
+{
+ struct s3c2410_udc *udc = &memory;
+ struct device *dev = &pdev->dev;
+ int retval;
+ unsigned int irq;
+
+ dev_dbg(dev, "%s()\n", __func__);
+
+ usb_bus_clock = clk_get(NULL, "usb-bus-gadget");
+ if (IS_ERR(usb_bus_clock)) {
+ dev_err(dev, "failed to get usb bus clock source\n");
+ return PTR_ERR(usb_bus_clock);
+ }
+
+ clk_enable(usb_bus_clock);
+
+ udc_clock = clk_get(NULL, "usb-device");
+ if (IS_ERR(udc_clock)) {
+ dev_err(dev, "failed to get udc clock source\n");
+ return PTR_ERR(udc_clock);
+ }
+
+ clk_enable(udc_clock);
+
+ mdelay(10);
+
+ dev_dbg(dev, "got and enabled clocks\n");
+
+ if (strncmp(pdev->name, "s3c2440", 7) == 0) {
+ dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n");
+ memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE;
+ memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE;
+ memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE;
+ memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE;
+ }
+
+ spin_lock_init (&udc->lock);
+ udc_info = pdev->dev.platform_data;
+
+ rsrc_start = S3C2410_PA_USBDEV;
+ rsrc_len = S3C24XX_SZ_USBDEV;
+
+ if (!request_mem_region(rsrc_start, rsrc_len, gadget_name))
+ return -EBUSY;
+
+ base_addr = ioremap(rsrc_start, rsrc_len);
+ if (!base_addr) {
+ retval = -ENOMEM;
+ goto err_mem;
+ }
+
+ device_initialize(&udc->gadget.dev);
+ udc->gadget.dev.parent = &pdev->dev;
+ udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
+
+ the_controller = udc;
+ platform_set_drvdata(pdev, udc);
+
+ s3c2410_udc_disable(udc);
+ s3c2410_udc_reinit(udc);
+
+ /* irq setup after old hardware state is cleaned up */
+ retval = request_irq(IRQ_USBD, s3c2410_udc_irq,
+ IRQF_DISABLED, gadget_name, udc);
+
+ if (retval != 0) {
+ dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval);
+ retval = -EBUSY;
+ goto err_map;
+ }
+
+ dev_dbg(dev, "got irq %i\n", IRQ_USBD);
+
+ if (udc_info && udc_info->vbus_pin > 0) {
+ irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
+ retval = request_irq(irq, s3c2410_udc_vbus_irq,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING
+ | IRQF_TRIGGER_FALLING,
+ gadget_name, udc);
+
+ if (retval != 0) {
+ dev_err(dev, "can't get vbus irq %i, err %d\n",
+ irq, retval);
+ retval = -EBUSY;
+ goto err_int;
+ }
+
+ dev_dbg(dev, "got irq %i\n", irq);
+ } else {
+ udc->vbus = 1;
+ }
+
+ if (s3c2410_udc_debugfs_root) {
+ udc->regs_info = debugfs_create_file("registers", S_IRUGO,
+ s3c2410_udc_debugfs_root,
+ udc, &s3c2410_udc_debugfs_fops);
+ if (IS_ERR(udc->regs_info)) {
+ dev_warn(dev, "debugfs file creation failed %ld\n",
+ PTR_ERR(udc->regs_info));
+ udc->regs_info = NULL;
+ }
+ }
+
+ dev_dbg(dev, "probe ok\n");
+
+ return 0;
+
+err_int:
+ free_irq(IRQ_USBD, udc);
+err_map:
+ iounmap(base_addr);
+err_mem:
+ release_mem_region(rsrc_start, rsrc_len);
+
+ return retval;
+}
+
+/*
+ * s3c2410_udc_remove
+ */
+static int s3c2410_udc_remove(struct platform_device *pdev)
+{
+ struct s3c2410_udc *udc = platform_get_drvdata(pdev);
+ unsigned int irq;
+
+ dev_dbg(&pdev->dev, "%s()\n", __func__);
+ if (udc->driver)
+ return -EBUSY;
+
+ debugfs_remove(udc->regs_info);
+
+ if (udc_info && udc_info->vbus_pin > 0) {
+ irq = s3c2410_gpio_getirq(udc_info->vbus_pin);
+ free_irq(irq, udc);
+ }
+
+ free_irq(IRQ_USBD, udc);
+
+ iounmap(base_addr);
+ release_mem_region(rsrc_start, rsrc_len);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (!IS_ERR(udc_clock) && udc_clock != NULL) {
+ clk_disable(udc_clock);
+ clk_put(udc_clock);
+ udc_clock = NULL;
+ }
+
+ if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
+ clk_disable(usb_bus_clock);
+ clk_put(usb_bus_clock);
+ usb_bus_clock = NULL;
+ }
+
+ dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
+{
+ if (udc_info && udc_info->udc_command)
+ udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+
+ return 0;
+}
+
+static int s3c2410_udc_resume(struct platform_device *pdev)
+{
+ if (udc_info && udc_info->udc_command)
+ udc_info->udc_command(S3C2410_UDC_P_ENABLE);
+
+ return 0;
+}
+#else
+#define s3c2410_udc_suspend NULL
+#define s3c2410_udc_resume NULL
+#endif
+
+static struct platform_driver udc_driver_2410 = {
+ .driver = {
+ .name = "s3c2410-usbgadget",
+ .owner = THIS_MODULE,
+ },
+ .probe = s3c2410_udc_probe,
+ .remove = s3c2410_udc_remove,
+ .suspend = s3c2410_udc_suspend,
+ .resume = s3c2410_udc_resume,
+};
+
+static struct platform_driver udc_driver_2440 = {
+ .driver = {
+ .name = "s3c2440-usbgadget",
+ .owner = THIS_MODULE,
+ },
+ .probe = s3c2410_udc_probe,
+ .remove = s3c2410_udc_remove,
+ .suspend = s3c2410_udc_suspend,
+ .resume = s3c2410_udc_resume,
+};
+
+static int __init udc_init(void)
+{
+ int retval;
+
+ dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
+
+ s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
+ if (IS_ERR(s3c2410_udc_debugfs_root)) {
+ printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
+ gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
+ s3c2410_udc_debugfs_root = NULL;
+ }
+
+ retval = platform_driver_register(&udc_driver_2410);
+ if (retval)
+ goto err;
+
+ retval = platform_driver_register(&udc_driver_2440);
+ if (retval)
+ goto err;
+
+ return 0;
+
+err:
+ debugfs_remove(s3c2410_udc_debugfs_root);
+ return retval;
+}
+
+static void __exit udc_exit(void)
+{
+ platform_driver_unregister(&udc_driver_2410);
+ platform_driver_unregister(&udc_driver_2440);
+ debugfs_remove(s3c2410_udc_debugfs_root);
+}
+
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+module_init(udc_init);
+module_exit(udc_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h
new file mode 100644
index 00000000000..9e0bece4f24
--- /dev/null
+++ b/drivers/usb/gadget/s3c2410_udc.h
@@ -0,0 +1,110 @@
+/*
+ * linux/drivers/usb/gadget/s3c2410_udc.h
+ * Samsung on-chip full speed USB device controllers
+ *
+ * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard
+ * Additional cleanups by Ben Dooks <ben-linux@fluff.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _S3C2410_UDC_H
+#define _S3C2410_UDC_H
+
+struct s3c2410_ep {
+ struct list_head queue;
+ unsigned long last_io; /* jiffies timestamp */
+ struct usb_gadget *gadget;
+ struct s3c2410_udc *dev;
+ const struct usb_endpoint_descriptor *desc;
+ struct usb_ep ep;
+ u8 num;
+
+ unsigned short fifo_size;
+ u8 bEndpointAddress;
+ u8 bmAttributes;
+
+ unsigned halted : 1;
+ unsigned already_seen : 1;
+ unsigned setup_stage : 1;
+};
+
+
+/* Warning : ep0 has a fifo of 16 bytes */
+/* Don't try to set 32 or 64 */
+/* also testusb 14 fails wit 16 but is */
+/* fine with 8 */
+#define EP0_FIFO_SIZE 8
+#define EP_FIFO_SIZE 64
+#define DEFAULT_POWER_STATE 0x00
+
+#define S3C2440_EP_FIFO_SIZE 128
+
+static const char ep0name [] = "ep0";
+
+static const char *const ep_name[] = {
+ ep0name, /* everyone has ep0 */
+ /* s3c2410 four bidirectional bulk endpoints */
+ "ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk",
+};
+
+#define S3C2410_ENDPOINTS ARRAY_SIZE(ep_name)
+
+struct s3c2410_request {
+ struct list_head queue; /* ep's requests */
+ struct usb_request req;
+};
+
+enum ep0_state {
+ EP0_IDLE,
+ EP0_IN_DATA_PHASE,
+ EP0_OUT_DATA_PHASE,
+ EP0_END_XFER,
+ EP0_STALL,
+};
+
+static const char *ep0states[]= {
+ "EP0_IDLE",
+ "EP0_IN_DATA_PHASE",
+ "EP0_OUT_DATA_PHASE",
+ "EP0_END_XFER",
+ "EP0_STALL",
+};
+
+struct s3c2410_udc {
+ spinlock_t lock;
+
+ struct s3c2410_ep ep[S3C2410_ENDPOINTS];
+ int address;
+ struct usb_gadget gadget;
+ struct usb_gadget_driver *driver;
+ struct s3c2410_request fifo_req;
+ u8 fifo_buf[EP_FIFO_SIZE];
+ u16 devstatus;
+
+ u32 port_status;
+ int ep0state;
+
+ unsigned got_irq : 1;
+
+ unsigned req_std : 1;
+ unsigned req_config : 1;
+ unsigned req_pending : 1;
+ u8 vbus;
+ struct dentry *regs_info;
+};
+
+#endif
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index f847c3414be..dd33ff0ae4c 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -2215,7 +2215,7 @@ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags)
*
* Free the buffer and all associated memory.
*/
-void gs_buf_free(struct gs_buf *gb)
+static void gs_buf_free(struct gs_buf *gb)
{
if (gb) {
kfree(gb->buf_buf);
@@ -2228,7 +2228,7 @@ void gs_buf_free(struct gs_buf *gb)
*
* Clear out all data in the circular buffer.
*/
-void gs_buf_clear(struct gs_buf *gb)
+static void gs_buf_clear(struct gs_buf *gb)
{
if (gb != NULL)
gb->buf_get = gb->buf_put;
@@ -2241,7 +2241,7 @@ void gs_buf_clear(struct gs_buf *gb)
* Return the number of bytes of data available in the circular
* buffer.
*/
-unsigned int gs_buf_data_avail(struct gs_buf *gb)
+static unsigned int gs_buf_data_avail(struct gs_buf *gb)
{
if (gb != NULL)
return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
@@ -2255,7 +2255,7 @@ unsigned int gs_buf_data_avail(struct gs_buf *gb)
* Return the number of bytes of space available in the circular
* buffer.
*/
-unsigned int gs_buf_space_avail(struct gs_buf *gb)
+static unsigned int gs_buf_space_avail(struct gs_buf *gb)
{
if (gb != NULL)
return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
@@ -2271,7 +2271,8 @@ unsigned int gs_buf_space_avail(struct gs_buf *gb)
*
* Return the number of bytes copied.
*/
-unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
+static unsigned int
+gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
{
unsigned int len;
@@ -2309,7 +2310,8 @@ unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
*
* Return the number of bytes copied.
*/
-unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
+static unsigned int
+gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
{
unsigned int len;
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 7078374d0b7..a2e6e3fc8c8 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -481,8 +481,7 @@ alloc_ep_req (struct usb_ep *ep, unsigned length)
req = usb_ep_alloc_request (ep, GFP_ATOMIC);
if (req) {
req->length = length;
- req->buf = usb_ep_alloc_buffer (ep, length,
- &req->dma, GFP_ATOMIC);
+ req->buf = kmalloc(length, GFP_ATOMIC);
if (!req->buf) {
usb_ep_free_request (ep, req);
req = NULL;
@@ -493,8 +492,7 @@ alloc_ep_req (struct usb_ep *ep, unsigned length)
static void free_ep_req (struct usb_ep *ep, struct usb_request *req)
{
- if (req->buf)
- usb_ep_free_buffer (ep, req->buf, req->dma, req->length);
+ kfree(req->buf);
usb_ep_free_request (ep, req);
}
@@ -1199,8 +1197,7 @@ autoconf_fail:
dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL);
if (!dev->req)
goto enomem;
- dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ,
- &dev->req->dma, GFP_KERNEL);
+ dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);
if (!dev->req->buf)
goto enomem;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 62711870f8e..2f529828c74 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -69,8 +69,20 @@ config USB_EHCI_TT_NEWSCHED
config USB_EHCI_BIG_ENDIAN_MMIO
bool
- depends on USB_EHCI_HCD
- default n
+ depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX)
+ default y
+
+config USB_EHCI_BIG_ENDIAN_DESC
+ bool
+ depends on USB_EHCI_HCD && 440EPX
+ default y
+
+config USB_EHCI_FSL
+ bool
+ select USB_EHCI_ROOT_HUB_TT
+ default y if MPC834x || PPC_MPC831x
+ ---help---
+ Variation of ARC USB block used in some Freescale chips.
config USB_ISP116X_HCD
tristate "ISP116X HCD support"
@@ -224,3 +236,15 @@ config USB_SL811_CS
To compile this driver as a module, choose M here: the
module will be called "sl811_cs".
+config USB_R8A66597_HCD
+ tristate "R8A66597 HCD suppoort"
+ depends on USB
+ help
+ The R8A66597 is a USB 2.0 host and peripheral controller.
+
+ Enable this option if your board has this chip, and you want
+ to use it as a host controller. If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called r8a66597-hcd.
+
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 2ff396bd180..bb8e9d44f37 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -15,3 +15,5 @@ obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o
+obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
+
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 43eddaecc3d..c9cc4413198 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -52,7 +52,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
HCS_INDICATOR (params) ? " ind" : "",
HCS_N_CC (params),
HCS_N_PCC (params),
- HCS_PORTROUTED (params) ? "" : " ordered",
+ HCS_PORTROUTED (params) ? "" : " ordered",
HCS_PPC (params) ? "" : " !ppc",
HCS_N_PORTS (params)
);
@@ -91,20 +91,20 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label)
if (HCC_ISOC_CACHE (params)) {
ehci_dbg (ehci,
- "%s hcc_params %04x caching frame %s%s%s\n",
- label, params,
- HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
- HCC_CANPARK (params) ? " park" : "",
- HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+ "%s hcc_params %04x caching frame %s%s%s\n",
+ label, params,
+ HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+ HCC_CANPARK(params) ? " park" : "",
+ HCC_64BIT_ADDR(params) ? " 64 bit addr" : "");
} else {
ehci_dbg (ehci,
- "%s hcc_params %04x thresh %d uframes %s%s%s\n",
- label,
- params,
- HCC_ISOC_THRES (params),
- HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024",
- HCC_CANPARK (params) ? " park" : "",
- HCC_64BIT_ADDR (params) ? " 64 bit addr" : "");
+ "%s hcc_params %04x thresh %d uframes %s%s%s\n",
+ label,
+ params,
+ HCC_ISOC_THRES(params),
+ HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+ HCC_CANPARK(params) ? " park" : "",
+ HCC_64BIT_ADDR(params) ? " 64 bit addr" : "");
}
}
#else
@@ -115,23 +115,23 @@ static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {}
#ifdef DEBUG
-static void __attribute__((__unused__))
+static void __maybe_unused
dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
{
- ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
- le32_to_cpup (&qtd->hw_next),
- le32_to_cpup (&qtd->hw_alt_next),
- le32_to_cpup (&qtd->hw_token),
- le32_to_cpup (&qtd->hw_buf [0]));
+ ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
+ hc32_to_cpup(ehci, &qtd->hw_next),
+ hc32_to_cpup(ehci, &qtd->hw_alt_next),
+ hc32_to_cpup(ehci, &qtd->hw_token),
+ hc32_to_cpup(ehci, &qtd->hw_buf [0]));
if (qtd->hw_buf [1])
- ehci_dbg (ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n",
- le32_to_cpup (&qtd->hw_buf [1]),
- le32_to_cpup (&qtd->hw_buf [2]),
- le32_to_cpup (&qtd->hw_buf [3]),
- le32_to_cpup (&qtd->hw_buf [4]));
+ ehci_dbg(ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n",
+ hc32_to_cpup(ehci, &qtd->hw_buf[1]),
+ hc32_to_cpup(ehci, &qtd->hw_buf[2]),
+ hc32_to_cpup(ehci, &qtd->hw_buf[3]),
+ hc32_to_cpup(ehci, &qtd->hw_buf[4]));
}
-static void __attribute__((__unused__))
+static void __maybe_unused
dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
{
ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label,
@@ -140,51 +140,53 @@ dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next);
}
-static void __attribute__((__unused__))
+static void __maybe_unused
dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
{
ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n",
- label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb);
+ label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next),
+ itd->urb);
ehci_dbg (ehci,
" trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
- le32_to_cpu(itd->hw_transaction[0]),
- le32_to_cpu(itd->hw_transaction[1]),
- le32_to_cpu(itd->hw_transaction[2]),
- le32_to_cpu(itd->hw_transaction[3]),
- le32_to_cpu(itd->hw_transaction[4]),
- le32_to_cpu(itd->hw_transaction[5]),
- le32_to_cpu(itd->hw_transaction[6]),
- le32_to_cpu(itd->hw_transaction[7]));
+ hc32_to_cpu(ehci, itd->hw_transaction[0]),
+ hc32_to_cpu(ehci, itd->hw_transaction[1]),
+ hc32_to_cpu(ehci, itd->hw_transaction[2]),
+ hc32_to_cpu(ehci, itd->hw_transaction[3]),
+ hc32_to_cpu(ehci, itd->hw_transaction[4]),
+ hc32_to_cpu(ehci, itd->hw_transaction[5]),
+ hc32_to_cpu(ehci, itd->hw_transaction[6]),
+ hc32_to_cpu(ehci, itd->hw_transaction[7]));
ehci_dbg (ehci,
" buf: %08x %08x %08x %08x %08x %08x %08x\n",
- le32_to_cpu(itd->hw_bufp[0]),
- le32_to_cpu(itd->hw_bufp[1]),
- le32_to_cpu(itd->hw_bufp[2]),
- le32_to_cpu(itd->hw_bufp[3]),
- le32_to_cpu(itd->hw_bufp[4]),
- le32_to_cpu(itd->hw_bufp[5]),
- le32_to_cpu(itd->hw_bufp[6]));
+ hc32_to_cpu(ehci, itd->hw_bufp[0]),
+ hc32_to_cpu(ehci, itd->hw_bufp[1]),
+ hc32_to_cpu(ehci, itd->hw_bufp[2]),
+ hc32_to_cpu(ehci, itd->hw_bufp[3]),
+ hc32_to_cpu(ehci, itd->hw_bufp[4]),
+ hc32_to_cpu(ehci, itd->hw_bufp[5]),
+ hc32_to_cpu(ehci, itd->hw_bufp[6]));
ehci_dbg (ehci, " index: %d %d %d %d %d %d %d %d\n",
itd->index[0], itd->index[1], itd->index[2],
itd->index[3], itd->index[4], itd->index[5],
itd->index[6], itd->index[7]);
}
-static void __attribute__((__unused__))
+static void __maybe_unused
dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
{
ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
- label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb);
+ label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next),
+ sitd->urb);
ehci_dbg (ehci,
" addr %08x sched %04x result %08x buf %08x %08x\n",
- le32_to_cpu(sitd->hw_fullspeed_ep),
- le32_to_cpu(sitd->hw_uframe),
- le32_to_cpu(sitd->hw_results),
- le32_to_cpu(sitd->hw_buf [0]),
- le32_to_cpu(sitd->hw_buf [1]));
+ hc32_to_cpu(ehci, sitd->hw_fullspeed_ep),
+ hc32_to_cpu(ehci, sitd->hw_uframe),
+ hc32_to_cpu(ehci, sitd->hw_results),
+ hc32_to_cpu(ehci, sitd->hw_buf[0]),
+ hc32_to_cpu(ehci, sitd->hw_buf[1]));
}
-static int __attribute__((__unused__))
+static int __maybe_unused
dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
{
return scnprintf (buf, len,
@@ -203,7 +205,7 @@ dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
);
}
-static int __attribute__((__unused__))
+static int __maybe_unused
dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
{
return scnprintf (buf, len,
@@ -267,28 +269,27 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
(status & PORT_PEC) ? " PEC" : "",
(status & PORT_PE) ? " PE" : "",
(status & PORT_CSC) ? " CSC" : "",
- (status & PORT_CONNECT) ? " CONNECT" : ""
- );
+ (status & PORT_CONNECT) ? " CONNECT" : "");
}
#else
-static inline void __attribute__((__unused__))
+static inline void __maybe_unused
dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
{}
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
{ return 0; }
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
{ return 0; }
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
{ return 0; }
-static inline int __attribute__((__unused__))
+static inline int __maybe_unused
dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
{ return 0; }
@@ -332,9 +333,10 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
default: tmp = '?'; break; \
}; tmp; })
-static inline char token_mark (__le32 token)
+static inline char token_mark(struct ehci_hcd *ehci, __hc32 token)
{
- __u32 v = le32_to_cpu (token);
+ __u32 v = hc32_to_cpu(ehci, token);
+
if (v & QTD_STS_ACTIVE)
return '*';
if (v & QTD_STS_HALT)
@@ -360,46 +362,48 @@ static void qh_lines (
unsigned size = *sizep;
char *next = *nextp;
char mark;
+ u32 list_end = EHCI_LIST_END(ehci);
- if (qh->hw_qtd_next == EHCI_LIST_END) /* NEC does this */
+ if (qh->hw_qtd_next == list_end) /* NEC does this */
mark = '@';
else
- mark = token_mark (qh->hw_token);
+ mark = token_mark(ehci, qh->hw_token);
if (mark == '/') { /* qh_alt_next controls qh advance? */
- if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next)
+ if ((qh->hw_alt_next & QTD_MASK(ehci))
+ == ehci->async->hw_alt_next)
mark = '#'; /* blocked */
- else if (qh->hw_alt_next == EHCI_LIST_END)
+ else if (qh->hw_alt_next == list_end)
mark = '.'; /* use hw_qtd_next */
/* else alt_next points to some other qtd */
}
- scratch = le32_to_cpup (&qh->hw_info1);
- hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0;
+ scratch = hc32_to_cpup(ehci, &qh->hw_info1);
+ hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &qh->hw_current) : 0;
temp = scnprintf (next, size,
"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
qh, scratch & 0x007f,
speed_char (scratch),
(scratch >> 8) & 0x000f,
- scratch, le32_to_cpup (&qh->hw_info2),
- le32_to_cpup (&qh->hw_token), mark,
- (__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
+ scratch, hc32_to_cpup(ehci, &qh->hw_info2),
+ hc32_to_cpup(ehci, &qh->hw_token), mark,
+ (cpu_to_hc32(ehci, QTD_TOGGLE) & qh->hw_token)
? "data1" : "data0",
- (le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f);
+ (hc32_to_cpup(ehci, &qh->hw_alt_next) >> 1) & 0x0f);
size -= temp;
next += temp;
/* hc may be modifying the list as we read it ... */
list_for_each (entry, &qh->qtd_list) {
td = list_entry (entry, struct ehci_qtd, qtd_list);
- scratch = le32_to_cpup (&td->hw_token);
+ scratch = hc32_to_cpup(ehci, &td->hw_token);
mark = ' ';
if (hw_curr == td->qtd_dma)
mark = '*';
- else if (qh->hw_qtd_next == cpu_to_le32(td->qtd_dma))
+ else if (qh->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma))
mark = '+';
else if (QTD_LENGTH (scratch)) {
if (td->hw_alt_next == ehci->async->hw_alt_next)
mark = '#';
- else if (td->hw_alt_next != EHCI_LIST_END)
+ else if (td->hw_alt_next != list_end)
mark = '/';
}
temp = snprintf (next, size,
@@ -490,7 +494,7 @@ show_periodic (struct class_device *class_dev, char *buf)
unsigned temp, size, seen_count;
char *next;
unsigned i;
- __le32 tag;
+ __hc32 tag;
if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC)))
return 0;
@@ -514,18 +518,19 @@ show_periodic (struct class_device *class_dev, char *buf)
p = ehci->pshadow [i];
if (likely (!p.ptr))
continue;
- tag = Q_NEXT_TYPE (ehci->periodic [i]);
+ tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]);
temp = scnprintf (next, size, "%4d: ", i);
size -= temp;
next += temp;
do {
- switch (tag) {
+ switch (hc32_to_cpu(ehci, tag)) {
case Q_TYPE_QH:
temp = scnprintf (next, size, " qh%d-%04x/%p",
p.qh->period,
- le32_to_cpup (&p.qh->hw_info2)
+ hc32_to_cpup(ehci,
+ &p.qh->hw_info2)
/* uframe masks */
& (QH_CMASK | QH_SMASK),
p.qh);
@@ -543,7 +548,7 @@ show_periodic (struct class_device *class_dev, char *buf)
}
/* show more info the first time around */
if (temp == seen_count && p.ptr) {
- u32 scratch = le32_to_cpup (
+ u32 scratch = hc32_to_cpup(ehci,
&p.qh->hw_info1);
struct ehci_qtd *qtd;
char *type = "";
@@ -554,7 +559,8 @@ show_periodic (struct class_device *class_dev, char *buf)
&p.qh->qtd_list,
qtd_list) {
temp++;
- switch (0x03 & (le32_to_cpu (
+ switch (0x03 & (hc32_to_cpu(
+ ehci,
qtd->hw_token) >> 8)) {
case 0: type = "out"; continue;
case 1: type = "in"; continue;
@@ -576,7 +582,7 @@ show_periodic (struct class_device *class_dev, char *buf)
} else
temp = 0;
if (p.qh) {
- tag = Q_NEXT_TYPE (p.qh->hw_next);
+ tag = Q_NEXT_TYPE(ehci, p.qh->hw_next);
p = p.qh->qh_next;
}
break;
@@ -584,23 +590,23 @@ show_periodic (struct class_device *class_dev, char *buf)
temp = scnprintf (next, size,
" fstn-%8x/%p", p.fstn->hw_prev,
p.fstn);
- tag = Q_NEXT_TYPE (p.fstn->hw_next);
+ tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next);
p = p.fstn->fstn_next;
break;
case Q_TYPE_ITD:
temp = scnprintf (next, size,
" itd/%p", p.itd);
- tag = Q_NEXT_TYPE (p.itd->hw_next);
+ tag = Q_NEXT_TYPE(ehci, p.itd->hw_next);
p = p.itd->itd_next;
break;
case Q_TYPE_SITD:
temp = scnprintf (next, size,
" sitd%d-%04x/%p",
p.sitd->stream->interval,
- le32_to_cpup (&p.sitd->hw_uframe)
+ hc32_to_cpup(ehci, &p.sitd->hw_uframe)
& 0x0000ffff,
p.sitd);
- tag = Q_NEXT_TYPE (p.sitd->hw_next);
+ tag = Q_NEXT_TYPE(ehci, p.sitd->hw_next);
p = p.sitd->sitd_next;
break;
}
@@ -673,7 +679,8 @@ show_registers (struct class_device *class_dev, char *buf)
unsigned count = 256/4;
pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller);
- offset = HCC_EXT_CAPS (ehci_readl(ehci, &ehci->caps->hcc_params));
+ offset = HCC_EXT_CAPS(ehci_readl(ehci,
+ &ehci->caps->hcc_params));
while (offset && count--) {
pci_read_config_dword (pdev, offset, &cap);
switch (cap & 0xff) {
@@ -740,14 +747,16 @@ show_registers (struct class_device *class_dev, char *buf)
for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) {
temp = dbg_port_buf (scratch, sizeof scratch, label, i,
- ehci_readl(ehci, &ehci->regs->port_status [i - 1]));
+ ehci_readl(ehci,
+ &ehci->regs->port_status[i - 1]));
temp = scnprintf (next, size, fmt, temp, scratch);
size -= temp;
next += temp;
if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) {
temp = scnprintf (next, size,
" debug control %08x\n",
- ehci_readl(ehci, &ehci->debug->control));
+ ehci_readl(ehci,
+ &ehci->debug->control));
size -= temp;
next += temp;
}
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index c7a7c590426..b7b7bfbce52 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -67,7 +67,8 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
* in host mode.
*/
if (!((pdata->operating_mode == FSL_USB2_DR_HOST) ||
- (pdata->operating_mode == FSL_USB2_MPH_HOST))) {
+ (pdata->operating_mode == FSL_USB2_MPH_HOST) ||
+ (pdata->operating_mode == FSL_USB2_DR_OTG))) {
dev_err(&pdev->dev,
"Non Host Mode configured for %s. Wrong driver linked.\n",
pdev->dev.bus_id);
@@ -185,12 +186,14 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct fsl_usb2_platform_data *pdata;
void __iomem *non_ehci = hcd->regs;
+ u32 temp;
pdata =
(struct fsl_usb2_platform_data *)hcd->self.controller->
platform_data;
/* Enable PHY interface in the control reg. */
- out_be32(non_ehci + FSL_SOC_USB_CTRL, 0x00000004);
+ temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+ out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
@@ -206,7 +209,8 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
#endif
- if (pdata->operating_mode == FSL_USB2_DR_HOST)
+ if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
+ (pdata->operating_mode == FSL_USB2_DR_OTG))
mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 099aff64f53..c4e15ed1405 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -41,10 +41,6 @@
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
-
/*-------------------------------------------------------------------------*/
@@ -201,9 +197,15 @@ static void tdi_reset (struct ehci_hcd *ehci)
u32 __iomem *reg_ptr;
u32 tmp;
- reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68);
+ reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
tmp = ehci_readl(ehci, reg_ptr);
- tmp |= 0x3;
+ tmp |= USBMODE_CM_HC;
+ /* The default byte access to MMR space is LE after
+ * controller reset. Set the required endian mode
+ * for transfer buffers to match the host microprocessor
+ */
+ if (ehci_big_endian_mmio(ehci))
+ tmp |= USBMODE_BE;
ehci_writel(ehci, tmp, reg_ptr);
}
@@ -273,6 +275,58 @@ static void ehci_work(struct ehci_hcd *ehci);
/*-------------------------------------------------------------------------*/
+#ifdef CONFIG_CPU_FREQ
+
+#include <linux/cpufreq.h>
+
+static void ehci_cpufreq_pause (struct ehci_hcd *ehci)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ehci->lock, flags);
+ if (!ehci->cpufreq_changing++)
+ qh_inactivate_split_intr_qhs(ehci);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_cpufreq_unpause (struct ehci_hcd *ehci)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ehci->lock, flags);
+ if (!--ehci->cpufreq_changing)
+ qh_reactivate_split_intr_qhs(ehci);
+ spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+/*
+ * ehci_cpufreq_notifier is needed to avoid MMF errors that occur when
+ * EHCI controllers that don't cache many uframes get delayed trying to
+ * read main memory during CPU frequency transitions. This can cause
+ * split interrupt transactions to not be completed in the required uframe.
+ * This has been observed on the Broadcom/ServerWorks HT1000 controller.
+ */
+static int ehci_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct ehci_hcd *ehci = container_of(nb, struct ehci_hcd,
+ cpufreq_transition);
+
+ switch (val) {
+ case CPUFREQ_PRECHANGE:
+ ehci_cpufreq_pause(ehci);
+ break;
+ case CPUFREQ_POSTCHANGE:
+ ehci_cpufreq_unpause(ehci);
+ break;
+ }
+ return 0;
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
static void ehci_watchdog (unsigned long param)
{
struct ehci_hcd *ehci = (struct ehci_hcd *) param;
@@ -347,6 +401,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
is_on ? SetPortFeature : ClearPortFeature,
USB_PORT_FEAT_POWER,
port--, NULL, 0);
+ /* Flush those writes */
+ ehci_readl(ehci, &ehci->regs->command);
msleep(20);
}
@@ -404,6 +460,10 @@ static void ehci_stop (struct usb_hcd *hcd)
ehci_writel(ehci, 0, &ehci->regs->intr_enable);
spin_unlock_irq(&ehci->lock);
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_unregister_notifier(&ehci->cpufreq_transition,
+ CPUFREQ_TRANSITION_NOTIFIER);
+#endif
/* let companion controllers work when we aren't */
ehci_writel(ehci, 0, &ehci->regs->configured_flag);
@@ -470,12 +530,12 @@ static int ehci_init(struct usb_hcd *hcd)
* from automatically advancing to the next td after short reads.
*/
ehci->async->qh_next.qh = NULL;
- ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma);
- ehci->async->hw_info1 = cpu_to_le32(QH_HEAD);
- ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT);
- ehci->async->hw_qtd_next = EHCI_LIST_END;
+ ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
+ ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
+ ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
+ ehci->async->hw_qtd_next = EHCI_LIST_END(ehci);
ehci->async->qh_state = QH_STATE_LINKED;
- ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma);
+ ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
/* clear interrupt enables, set irq latency */
if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
@@ -509,6 +569,17 @@ static int ehci_init(struct usb_hcd *hcd)
}
ehci->command = temp;
+#ifdef CONFIG_CPU_FREQ
+ INIT_LIST_HEAD(&ehci->split_intr_qhs);
+ /*
+ * If the EHCI controller caches enough uframes, this probably
+ * isn't needed unless there are so many low/full speed devices
+ * that the controller's can't cache it all.
+ */
+ ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier;
+ cpufreq_register_notifier(&ehci->cpufreq_transition,
+ CPUFREQ_TRANSITION_NOTIFIER);
+#endif
return 0;
}
@@ -925,7 +996,7 @@ MODULE_LICENSE ("GPL");
#define PCI_DRIVER ehci_pci_driver
#endif
-#ifdef CONFIG_MPC834x
+#ifdef CONFIG_USB_EHCI_FSL
#include "ehci-fsl.c"
#define PLATFORM_DRIVER ehci_fsl_driver
#endif
@@ -937,7 +1008,12 @@ MODULE_LICENSE ("GPL");
#ifdef CONFIG_PPC_PS3
#include "ehci-ps3.c"
-#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_sb_driver
+#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver
+#endif
+
+#ifdef CONFIG_440EPX
+#include "ehci-ppc-soc.c"
+#define PLATFORM_DRIVER ehci_ppc_soc_driver
#endif
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
@@ -971,18 +1047,15 @@ static int __init ehci_hcd_init(void)
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
- if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
- retval = ps3_system_bus_driver_register(
- &PS3_SYSTEM_BUS_DRIVER);
- if (retval < 0) {
+ retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+ if (retval < 0) {
#ifdef PLATFORM_DRIVER
- platform_driver_unregister(&PLATFORM_DRIVER);
+ platform_driver_unregister(&PLATFORM_DRIVER);
#endif
#ifdef PCI_DRIVER
- pci_unregister_driver(&PCI_DRIVER);
+ pci_unregister_driver(&PCI_DRIVER);
#endif
- return retval;
- }
+ return retval;
}
#endif
@@ -999,8 +1072,7 @@ static void __exit ehci_hcd_cleanup(void)
pci_unregister_driver(&PCI_DRIVER);
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
- if (firmware_has_feature(FW_FEATURE_PS3_LV1))
- ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+ ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
}
module_exit(ehci_hcd_cleanup);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index f4d301bc83b..0dcb4164dc8 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -28,6 +28,89 @@
/*-------------------------------------------------------------------------*/
+#ifdef CONFIG_USB_PERSIST
+
+static int ehci_hub_control(
+ struct usb_hcd *hcd,
+ u16 typeReq,
+ u16 wValue,
+ u16 wIndex,
+ char *buf,
+ u16 wLength
+);
+
+/* After a power loss, ports that were owned by the companion must be
+ * reset so that the companion can still own them.
+ */
+static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+{
+ u32 __iomem *reg;
+ u32 status;
+ int port;
+ __le32 buf;
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+
+ if (!ehci->owned_ports)
+ return;
+
+ /* Give the connections some time to appear */
+ msleep(20);
+
+ port = HCS_N_PORTS(ehci->hcs_params);
+ while (port--) {
+ if (test_bit(port, &ehci->owned_ports)) {
+ reg = &ehci->regs->port_status[port];
+ status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+
+ /* Port already owned by companion? */
+ if (status & PORT_OWNER)
+ clear_bit(port, &ehci->owned_ports);
+ else if (test_bit(port, &ehci->companion_ports))
+ ehci_writel(ehci, status & ~PORT_PE, reg);
+ else
+ ehci_hub_control(hcd, SetPortFeature,
+ USB_PORT_FEAT_RESET, port + 1,
+ NULL, 0);
+ }
+ }
+
+ if (!ehci->owned_ports)
+ return;
+ msleep(90); /* Wait for resets to complete */
+
+ port = HCS_N_PORTS(ehci->hcs_params);
+ while (port--) {
+ if (test_bit(port, &ehci->owned_ports)) {
+ ehci_hub_control(hcd, GetPortStatus,
+ 0, port + 1,
+ (char *) &buf, sizeof(buf));
+
+ /* The companion should now own the port,
+ * but if something went wrong the port must not
+ * remain enabled.
+ */
+ reg = &ehci->regs->port_status[port];
+ status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
+ if (status & PORT_OWNER)
+ ehci_writel(ehci, status | PORT_CSC, reg);
+ else {
+ ehci_dbg(ehci, "failed handover port %d: %x\n",
+ port + 1, status);
+ ehci_writel(ehci, status & ~PORT_PE, reg);
+ }
+ }
+ }
+
+ ehci->owned_ports = 0;
+}
+
+#else /* CONFIG_USB_PERSIST */
+
+static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci)
+{ }
+
+#endif
+
#ifdef CONFIG_PM
static int ehci_bus_suspend (struct usb_hcd *hcd)
@@ -60,14 +143,16 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
* then manually resume them in the bus_resume() routine.
*/
ehci->bus_suspended = 0;
+ ehci->owned_ports = 0;
while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port];
u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
u32 t2 = t1;
/* keep track of which ports we suspend */
- if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
- !(t1 & PORT_SUSPEND)) {
+ if (t1 & PORT_OWNER)
+ set_bit(port, &ehci->owned_ports);
+ else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
t2 |= PORT_SUSPEND;
set_bit(port, &ehci->bus_suspended);
}
@@ -108,11 +193,16 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
+ u32 power_okay;
int i;
if (time_before (jiffies, ehci->next_statechange))
msleep(5);
spin_lock_irq (&ehci->lock);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+ spin_unlock_irq(&ehci->lock);
+ return -ESHUTDOWN;
+ }
/* Ideally and we've got a real resume here, and no port's power
* was lost. (For PCI, that means Vaux was maintained.) But we
@@ -120,8 +210,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
* the last user of the controller, not reset/pm hardware keeping
* state we gave to it.
*/
- temp = ehci_readl(ehci, &ehci->regs->intr_enable);
- ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
+ power_okay = ehci_readl(ehci, &ehci->regs->intr_enable);
+ ehci_dbg(ehci, "resume root hub%s\n",
+ power_okay ? "" : " after power loss");
/* at least some APM implementations will try to deliver
* IRQs right away, so delay them until we're ready.
@@ -184,6 +275,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
spin_unlock_irq (&ehci->lock);
+
+ if (!power_okay)
+ ehci_handover_companion_ports(ehci);
return 0;
}
@@ -448,7 +542,8 @@ static int ehci_hub_control (
) {
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
int ports = HCS_N_PORTS (ehci->hcs_params);
- u32 __iomem *status_reg = &ehci->regs->port_status[wIndex - 1];
+ u32 __iomem *status_reg = &ehci->regs->port_status[
+ (wIndex & 0xff) - 1];
u32 temp, status;
unsigned long flags;
int retval = 0;
@@ -556,9 +651,24 @@ static int ehci_hub_control (
status |= 1 << USB_PORT_FEAT_C_CONNECTION;
if (temp & PORT_PEC)
status |= 1 << USB_PORT_FEAT_C_ENABLE;
- if ((temp & PORT_OCC) && !ignore_oc)
+
+ if ((temp & PORT_OCC) && !ignore_oc){
status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
+ /*
+ * Hubs should disable port power on over-current.
+ * However, not all EHCI implementations do this
+ * automatically, even if they _do_ support per-port
+ * power switching; they're allowed to just limit the
+ * current. khubd will turn the power back on.
+ */
+ if (HCS_PPC (ehci->hcs_params)){
+ ehci_writel(ehci,
+ temp & ~(PORT_RWC_BITS | PORT_POWER),
+ status_reg);
+ }
+ }
+
/* whoever resumes must GetPortStatus to complete it!! */
if (temp & PORT_RESUME) {
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index a8ba2e1497a..8816d09903d 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -27,7 +27,7 @@
* need to use dma_pool or dma_alloc_coherent
* - driver buffers, read/written by HC ... single shot DMA mapped
*
- * There's also PCI "register" data, which is memory mapped.
+ * There's also "register" data (e.g. PCI or SOC), which is memory mapped.
* No memory seen by this driver is pageable.
*/
@@ -35,13 +35,14 @@
/* Allocate the key transfer structures from the previously allocated pool */
-static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma)
+static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
+ dma_addr_t dma)
{
memset (qtd, 0, sizeof *qtd);
qtd->qtd_dma = dma;
qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
- qtd->hw_next = EHCI_LIST_END;
- qtd->hw_alt_next = EHCI_LIST_END;
+ qtd->hw_next = EHCI_LIST_END(ehci);
+ qtd->hw_alt_next = EHCI_LIST_END(ehci);
INIT_LIST_HEAD (&qtd->qtd_list);
}
@@ -52,7 +53,7 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags)
qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma);
if (qtd != NULL) {
- ehci_qtd_init (qtd, dma);
+ ehci_qtd_init(ehci, qtd, dma);
}
return qtd;
}
@@ -63,9 +64,8 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd)
}
-static void qh_destroy (struct kref *kref)
+static void qh_destroy(struct ehci_qh *qh)
{
- struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref);
struct ehci_hcd *ehci = qh->ehci;
/* clean qtds first, and know this is not linked */
@@ -89,11 +89,14 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
return qh;
memset (qh, 0, sizeof *qh);
- kref_init(&qh->kref);
+ qh->refcount = 1;
qh->ehci = ehci;
qh->qh_dma = dma;
// INIT_LIST_HEAD (&qh->qh_list);
INIT_LIST_HEAD (&qh->qtd_list);
+#ifdef CONFIG_CPU_FREQ
+ INIT_LIST_HEAD (&qh->split_intr_qhs);
+#endif
/* dummy td enables safe urb queuing */
qh->dummy = ehci_qtd_alloc (ehci, flags);
@@ -108,13 +111,15 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
/* to share a qh (cpu threads, or hc) */
static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
{
- kref_get(&qh->kref);
+ WARN_ON(!qh->refcount);
+ qh->refcount++;
return qh;
}
static inline void qh_put (struct ehci_qh *qh)
{
- kref_put(&qh->kref, qh_destroy);
+ if (!--qh->refcount)
+ qh_destroy(qh);
}
/*-------------------------------------------------------------------------*/
@@ -217,7 +222,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
goto fail;
}
for (i = 0; i < ehci->periodic_size; i++)
- ehci->periodic [i] = EHCI_LIST_END;
+ ehci->periodic [i] = EHCI_LIST_END(ehci);
/* software shadow of hardware table */
ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 12edc723ec7..a7816e392a8 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -149,8 +149,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
* fixed in newer silicon.
*/
case 0x0068:
- pci_read_config_dword(pdev, PCI_REVISION_ID, &temp);
- if ((temp & 0xff) < 0xa4)
+ if (pdev->revision < 0xa4)
ehci->no_selective_suspend = 1;
break;
}
@@ -313,13 +312,14 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
ehci_work(ehci);
spin_unlock_irq(&ehci->lock);
- /* here we "know" root ports should always stay powered */
- ehci_port_power(ehci, 1);
-
ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
+ /* here we "know" root ports should always stay powered */
+ ehci_port_power(ehci, 1);
+ ehci_handover_companion_ports(ehci);
+
hcd->state = HC_STATE_SUSPENDED;
return 0;
}
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
new file mode 100644
index 00000000000..c2cedb09ed8
--- /dev/null
+++ b/drivers/usb/host/ehci-ppc-soc.c
@@ -0,0 +1,182 @@
+/*
+ * EHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 2006-2007 Stefan Roese <sr@denx.de>, DENX Software Engineering
+ *
+ * Bus Glue for PPC On-Chip EHCI driver
+ * Tested on AMCC 440EPx
+ *
+ * Based on "ehci-au12xx.c" by David Brownell <dbrownell@users.sourceforge.net>
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/platform_device.h>
+
+extern int usb_disabled(void);
+
+/**
+ * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ */
+int usb_ehci_ppc_soc_probe(const struct hc_driver *driver,
+ struct usb_hcd **hcd_out,
+ struct platform_device *dev)
+{
+ int retval;
+ struct usb_hcd *hcd;
+ struct ehci_hcd *ehci;
+
+ if (dev->resource[1].flags != IORESOURCE_IRQ) {
+ pr_debug("resource[1] is not IORESOURCE_IRQ");
+ retval = -ENOMEM;
+ }
+ hcd = usb_create_hcd(driver, &dev->dev, "PPC-SOC EHCI");
+ if (!hcd)
+ return -ENOMEM;
+ hcd->rsrc_start = dev->resource[0].start;
+ hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ pr_debug("request_mem_region failed");
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ pr_debug("ioremap failed");
+ retval = -ENOMEM;
+ goto err2;
+ }
+
+ ehci = hcd_to_ehci(hcd);
+ ehci->big_endian_mmio = 1;
+ ehci->big_endian_desc = 1;
+ ehci->caps = hcd->regs;
+ ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
+ /* cache this readonly data; minimize chip reads */
+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+#if defined(CONFIG_440EPX)
+ /*
+ * 440EPx Errata USBH_3
+ * Fix: Enable Break Memory Transfer (BMT) in INSNREG3
+ */
+ out_be32((void *)((ulong)(&ehci->regs->command) + 0x8c), (1 << 0));
+ ehci_dbg(ehci, "Break Memory Transfer (BMT) has beed enabled!\n");
+#endif
+
+ retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
+ if (retval == 0)
+ return retval;
+
+ iounmap(hcd->regs);
+err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+ usb_put_hcd(hcd);
+ return retval;
+}
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_ehci_hcd_ppc_soc_remove - shutdown processing for PPC-SoC-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_ehci_hcd_ppc_soc_probe(), first invoking
+ * the HCD's stop() method. It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+void usb_ehci_ppc_soc_remove(struct usb_hcd *hcd, struct platform_device *dev)
+{
+ usb_remove_hcd(hcd);
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+}
+
+static const struct hc_driver ehci_ppc_soc_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "PPC-SOC EHCI",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
+
+ /*
+ * generic hardware linkage
+ */
+ .irq = ehci_irq,
+ .flags = HCD_MEMORY | HCD_USB2,
+
+ /*
+ * basic lifecycle operations
+ */
+ .reset = ehci_init,
+ .start = ehci_run,
+ .stop = ehci_stop,
+ .shutdown = ehci_shutdown,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = ehci_urb_enqueue,
+ .urb_dequeue = ehci_urb_dequeue,
+ .endpoint_disable = ehci_endpoint_disable,
+
+ /*
+ * scheduling support
+ */
+ .get_frame_number = ehci_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = ehci_hub_status_data,
+ .hub_control = ehci_hub_control,
+#ifdef CONFIG_PM
+ .hub_suspend = ehci_hub_suspend,
+ .hub_resume = ehci_hub_resume,
+#endif
+};
+
+static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = NULL;
+ int ret;
+
+ pr_debug("In ehci_hcd_ppc_soc_drv_probe\n");
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev);
+ return ret;
+}
+
+static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
+{
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+ usb_ehci_ppc_soc_remove(hcd, pdev);
+ return 0;
+}
+
+MODULE_ALIAS("ppc-soc-ehci");
+static struct platform_driver ehci_ppc_soc_driver = {
+ .probe = ehci_hcd_ppc_soc_drv_probe,
+ .remove = ehci_hcd_ppc_soc_drv_remove,
+ .shutdown = usb_hcd_platform_shutdown,
+ .driver = {
+ .name = "ppc-soc-ehci",
+ .bus = &platform_bus_type
+ }
+};
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 37b83ba0996..829fe649a98 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <asm/firmware.h>
#include <asm/ps3.h>
static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
@@ -73,7 +74,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
#endif
};
-static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
+static int ps3_ehci_probe(struct ps3_system_bus_device *dev)
{
int result;
struct usb_hcd *hcd;
@@ -85,13 +86,30 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
goto fail_start;
}
+ result = ps3_open_hv_device(dev);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed\n",
+ __func__, __LINE__);
+ goto fail_open;
+ }
+
+ result = ps3_dma_region_create(dev->d_region);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+ "(%d)\n", __func__, __LINE__, result);
+ BUG_ON("check region type");
+ goto fail_dma_region;
+ }
+
result = ps3_mmio_region_create(dev->m_region);
if (result) {
dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n",
__func__, __LINE__);
result = -EPERM;
- goto fail_mmio;
+ goto fail_mmio_region;
}
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
@@ -120,6 +138,11 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
hcd->rsrc_start = dev->m_region->lpar_addr;
hcd->rsrc_len = dev->m_region->len;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name))
+ dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n",
+ __func__, __LINE__);
+
hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len);
if (!hcd->regs) {
@@ -153,34 +176,73 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev)
fail_add_hcd:
iounmap(hcd->regs);
fail_ioremap:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
fail_create_hcd:
ps3_io_irq_destroy(virq);
fail_irq:
ps3_free_mmio_region(dev->m_region);
-fail_mmio:
+fail_mmio_region:
+ ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+ ps3_close_hv_device(dev);
+fail_open:
fail_start:
return result;
}
-static int ps3_ehci_sb_remove(struct ps3_system_bus_device *dev)
+static int ps3_ehci_remove(struct ps3_system_bus_device *dev)
{
+ unsigned int tmp;
struct usb_hcd *hcd =
(struct usb_hcd *)ps3_system_bus_get_driver_data(dev);
- usb_put_hcd(hcd);
+ BUG_ON(!hcd);
+
+ dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs);
+ dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq);
+
+ tmp = hcd->irq;
+
+ usb_remove_hcd(hcd);
+
ps3_system_bus_set_driver_data(dev, NULL);
+ BUG_ON(!hcd->regs);
+ iounmap(hcd->regs);
+
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+
+ ps3_io_irq_destroy(tmp);
+ ps3_free_mmio_region(dev->m_region);
+
+ ps3_dma_region_free(dev->d_region);
+ ps3_close_hv_device(dev);
+
return 0;
}
-MODULE_ALIAS("ps3-ehci");
+static int ps3_ehci_driver_register(struct ps3_system_bus_driver *drv)
+{
+ return firmware_has_feature(FW_FEATURE_PS3_LV1)
+ ? ps3_system_bus_driver_register(drv)
+ : 0;
+}
+
+static void ps3_ehci_driver_unregister(struct ps3_system_bus_driver *drv)
+{
+ if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+ ps3_system_bus_driver_unregister(drv);
+}
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_EHCI);
-static struct ps3_system_bus_driver ps3_ehci_sb_driver = {
+static struct ps3_system_bus_driver ps3_ehci_driver = {
+ .core.name = "ps3-ehci-driver",
+ .core.owner = THIS_MODULE,
.match_id = PS3_MATCH_ID_EHCI,
- .core = {
- .name = "ps3-ehci-driver",
- },
- .probe = ps3_ehci_sb_probe,
- .remove = ps3_ehci_sb_remove,
+ .probe = ps3_ehci_probe,
+ .remove = ps3_ehci_remove,
+ .shutdown = ps3_ehci_remove,
};
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index e7fbbd00e7c..2284028f8aa 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -43,15 +43,15 @@
/* fill a qtd, returning how much of the buffer we were able to queue up */
static int
-qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
- int token, int maxpacket)
+qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf,
+ size_t len, int token, int maxpacket)
{
int i, count;
u64 addr = buf;
/* one buffer entry per 4K ... first might be short or unaligned */
- qtd->hw_buf [0] = cpu_to_le32 ((u32)addr);
- qtd->hw_buf_hi [0] = cpu_to_le32 ((u32)(addr >> 32));
+ qtd->hw_buf[0] = cpu_to_hc32(ehci, (u32)addr);
+ qtd->hw_buf_hi[0] = cpu_to_hc32(ehci, (u32)(addr >> 32));
count = 0x1000 - (buf & 0x0fff); /* rest of that page */
if (likely (len < count)) /* ... iff needed */
count = len;
@@ -62,8 +62,9 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
/* per-qtd limit: from 16K to 20K (best alignment) */
for (i = 1; count < len && i < 5; i++) {
addr = buf;
- qtd->hw_buf [i] = cpu_to_le32 ((u32)addr);
- qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32));
+ qtd->hw_buf[i] = cpu_to_hc32(ehci, (u32)addr);
+ qtd->hw_buf_hi[i] = cpu_to_hc32(ehci,
+ (u32)(addr >> 32));
buf += 0x1000;
if ((count + 0x1000) < len)
count += 0x1000;
@@ -75,7 +76,7 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len,
if (count != len)
count -= (count % maxpacket);
}
- qtd->hw_token = cpu_to_le32 ((count << 16) | token);
+ qtd->hw_token = cpu_to_hc32(ehci, (count << 16) | token);
qtd->length = count;
return count;
@@ -89,28 +90,28 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
/* writes to an active overlay are unsafe */
BUG_ON(qh->qh_state != QH_STATE_IDLE);
- qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma);
- qh->hw_alt_next = EHCI_LIST_END;
+ qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
+ qh->hw_alt_next = EHCI_LIST_END(ehci);
/* Except for control endpoints, we make hardware maintain data
* toggle (like OHCI) ... here (re)initialize the toggle in the QH,
* and set the pseudo-toggle in udev. Only usb_clear_halt() will
* ever clear it.
*/
- if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) {
+ if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
unsigned is_out, epnum;
- is_out = !(qtd->hw_token & cpu_to_le32(1 << 8));
- epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f;
+ is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
+ epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
- qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE);
+ qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
usb_settoggle (qh->dev, epnum, is_out, 1);
}
}
/* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
wmb ();
- qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING);
+ qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
}
/* if it weren't for a common silicon quirk (writing the dummy into the qh
@@ -128,7 +129,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
qtd = list_entry (qh->qtd_list.next,
struct ehci_qtd, qtd_list);
/* first qtd may already be partially processed */
- if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current)
+ if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current)
qtd = NULL;
}
@@ -222,7 +223,7 @@ __acquires(ehci->lock)
struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv;
/* S-mask in a QH means it's an interrupt urb */
- if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) {
+ if ((qh->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) {
/* ... update hc-wide periodic stats (for usbfs) */
ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
@@ -277,7 +278,6 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
* Chases up to qh->hw_current. Returns number of completions called,
* indicating how much "real" work we did.
*/
-#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT)
static unsigned
qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
@@ -287,6 +287,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
unsigned count = 0;
int do_status = 0;
u8 state;
+ u32 halt = HALT_BIT(ehci);
if (unlikely (list_empty (&qh->qtd_list)))
return count;
@@ -311,6 +312,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
struct urb *urb;
u32 token = 0;
+ /* ignore QHs that are currently inactive */
+ if (qh->hw_info1 & __constant_cpu_to_le32(QH_INACTIVATE))
+ break;
+
qtd = list_entry (entry, struct ehci_qtd, qtd_list);
urb = qtd->urb;
@@ -330,7 +335,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* hardware copies qtd out of qh overlay */
rmb ();
- token = le32_to_cpu (qtd->hw_token);
+ token = hc32_to_cpu(ehci, qtd->hw_token);
/* always clean up qtds the hc de-activated */
if ((token & QTD_STS_ACTIVE) == 0) {
@@ -342,7 +347,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
* that silicon quirk can kick in with this dummy too.
*/
} else if (IS_SHORT_READ (token)
- && !(qtd->hw_alt_next & EHCI_LIST_END)) {
+ && !(qtd->hw_alt_next
+ & EHCI_LIST_END(ehci))) {
stopped = 1;
goto halt;
}
@@ -374,17 +380,17 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* token in overlay may be most current */
if (state == QH_STATE_IDLE
- && cpu_to_le32 (qtd->qtd_dma)
+ && cpu_to_hc32(ehci, qtd->qtd_dma)
== qh->hw_current)
- token = le32_to_cpu (qh->hw_token);
+ token = hc32_to_cpu(ehci, qh->hw_token);
/* force halt for unlinked or blocked qh, so we'll
* patch the qh later and so that completions can't
* activate it while we "know" it's stopped.
*/
- if ((HALT_BIT & qh->hw_token) == 0) {
+ if ((halt & qh->hw_token) == 0) {
halt:
- qh->hw_token |= HALT_BIT;
+ qh->hw_token |= halt;
wmb ();
}
}
@@ -419,7 +425,7 @@ halt:
* it after fault cleanup, or recovering from silicon wrongly
* overlaying the dummy qtd (which reduces DMA chatter).
*/
- if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END) {
+ if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) {
switch (state) {
case QH_STATE_IDLE:
qh_refresh(ehci, qh);
@@ -428,7 +434,7 @@ halt:
/* should be rare for periodic transfers,
* except maybe high bandwidth ...
*/
- if ((__constant_cpu_to_le32 (QH_SMASK)
+ if ((cpu_to_hc32(ehci, QH_SMASK)
& qh->hw_info2) != 0) {
intr_deschedule (ehci, qh);
(void) qh_schedule (ehci, qh);
@@ -502,8 +508,9 @@ qh_urb_transaction (
is_input = usb_pipein (urb->pipe);
if (usb_pipecontrol (urb->pipe)) {
/* SETUP pid */
- qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
- token | (2 /* "setup" */ << 8), 8);
+ qtd_fill(ehci, qtd, urb->setup_dma,
+ sizeof (struct usb_ctrlrequest),
+ token | (2 /* "setup" */ << 8), 8);
/* ... and always at least one more pid */
token ^= QTD_TOGGLE;
@@ -512,7 +519,7 @@ qh_urb_transaction (
if (unlikely (!qtd))
goto cleanup;
qtd->urb = urb;
- qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+ qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
list_add_tail (&qtd->qtd_list, head);
/* for zero length DATA stages, STATUS is always IN */
@@ -539,7 +546,7 @@ qh_urb_transaction (
for (;;) {
int this_qtd_len;
- this_qtd_len = qtd_fill (qtd, buf, len, token, maxpacket);
+ this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket);
len -= this_qtd_len;
buf += this_qtd_len;
if (is_input)
@@ -557,7 +564,7 @@ qh_urb_transaction (
if (unlikely (!qtd))
goto cleanup;
qtd->urb = urb;
- qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+ qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
list_add_tail (&qtd->qtd_list, head);
}
@@ -566,7 +573,7 @@ qh_urb_transaction (
*/
if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
|| usb_pipecontrol (urb->pipe)))
- qtd->hw_alt_next = EHCI_LIST_END;
+ qtd->hw_alt_next = EHCI_LIST_END(ehci);
/*
* control requests may need a terminating data "status" ack;
@@ -590,17 +597,17 @@ qh_urb_transaction (
if (unlikely (!qtd))
goto cleanup;
qtd->urb = urb;
- qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma);
+ qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);
list_add_tail (&qtd->qtd_list, head);
/* never any data in such packets */
- qtd_fill (qtd, 0, 0, token, 0);
+ qtd_fill(ehci, qtd, 0, 0, token, 0);
}
}
/* by default, enable interrupt on urb completion */
if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
- qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC);
+ qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC);
return head;
cleanup:
@@ -769,8 +776,8 @@ done:
/* init as live, toggle clear, advance to dummy */
qh->qh_state = QH_STATE_IDLE;
- qh->hw_info1 = cpu_to_le32 (info1);
- qh->hw_info2 = cpu_to_le32 (info2);
+ qh->hw_info1 = cpu_to_hc32(ehci, info1);
+ qh->hw_info2 = cpu_to_hc32(ehci, info2);
usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
qh_refresh (ehci, qh);
return qh;
@@ -782,7 +789,7 @@ done:
static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
- __le32 dma = QH_NEXT (qh->qh_dma);
+ __hc32 dma = QH_NEXT(ehci, qh->qh_dma);
struct ehci_qh *head;
/* (re)start the async schedule? */
@@ -820,8 +827,6 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
/*-------------------------------------------------------------------------*/
-#define QH_ADDR_MASK __constant_cpu_to_le32(0x7f)
-
/*
* For control/bulk/interrupt, return QH with these TDs appended.
* Allocates and initializes the QH if necessary.
@@ -837,6 +842,7 @@ static struct ehci_qh *qh_append_tds (
)
{
struct ehci_qh *qh = NULL;
+ u32 qh_addr_mask = cpu_to_hc32(ehci, 0x7f);
qh = (struct ehci_qh *) *ptr;
if (unlikely (qh == NULL)) {
@@ -858,7 +864,7 @@ static struct ehci_qh *qh_append_tds (
/* usb_reset_device() briefly reverts to address 0 */
if (usb_pipedevice (urb->pipe) == 0)
- qh->hw_info1 &= ~QH_ADDR_MASK;
+ qh->hw_info1 &= ~qh_addr_mask;
}
/* just one way to queue requests: swap with the dummy qtd.
@@ -867,7 +873,7 @@ static struct ehci_qh *qh_append_tds (
if (likely (qtd != NULL)) {
struct ehci_qtd *dummy;
dma_addr_t dma;
- __le32 token;
+ __hc32 token;
/* to avoid racing the HC, use the dummy td instead of
* the first td of our list (becomes new dummy). both
@@ -875,7 +881,7 @@ static struct ehci_qh *qh_append_tds (
* HC is allowed to fetch the old dummy (4.10.2).
*/
token = qtd->hw_token;
- qtd->hw_token = HALT_BIT;
+ qtd->hw_token = HALT_BIT(ehci);
wmb ();
dummy = qh->dummy;
@@ -887,14 +893,14 @@ static struct ehci_qh *qh_append_tds (
list_add (&dummy->qtd_list, qtd_list);
__list_splice (qtd_list, qh->qtd_list.prev);
- ehci_qtd_init (qtd, qtd->qtd_dma);
+ ehci_qtd_init(ehci, qtd, qtd->qtd_dma);
qh->dummy = qtd;
/* hc must see the new dummy at list end */
dma = qtd->qtd_dma;
qtd = list_entry (qh->qtd_list.prev,
struct ehci_qtd, qtd_list);
- qtd->hw_next = QTD_NEXT (dma);
+ qtd->hw_next = QTD_NEXT(ehci, dma);
/* let the hc process these next qtds */
wmb ();
@@ -970,7 +976,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
timer_action_done (ehci, TIMER_IAA_WATCHDOG);
- // qh->hw_next = cpu_to_le32 (qh->qh_dma);
+ // qh->hw_next = cpu_to_hc32(qh->qh_dma);
qh->qh_state = QH_STATE_IDLE;
qh->qh_next.qh = NULL;
qh_put (qh); // refcount from reclaim
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 7b5ae7111f2..d4a8ace4967 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -44,9 +44,10 @@ static int ehci_get_frame (struct usb_hcd *hcd);
* @tag: hardware tag for type of this record
*/
static union ehci_shadow *
-periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
+periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic,
+ __hc32 tag)
{
- switch (tag) {
+ switch (hc32_to_cpu(ehci, tag)) {
case Q_TYPE_QH:
return &periodic->qh->qh_next;
case Q_TYPE_FSTN:
@@ -62,13 +63,14 @@ periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
/* caller must hold ehci->lock */
static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
{
- union ehci_shadow *prev_p = &ehci->pshadow [frame];
- __le32 *hw_p = &ehci->periodic [frame];
+ union ehci_shadow *prev_p = &ehci->pshadow[frame];
+ __hc32 *hw_p = &ehci->periodic[frame];
union ehci_shadow here = *prev_p;
/* find predecessor of "ptr"; hw and shadow lists are in sync */
while (here.ptr && here.ptr != ptr) {
- prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
+ prev_p = periodic_next_shadow(ehci, prev_p,
+ Q_NEXT_TYPE(ehci, *hw_p));
hw_p = here.hw_next;
here = *prev_p;
}
@@ -79,7 +81,8 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
/* update shadow and hardware lists ... the old "next" pointers
* from ptr may still be in use, the caller updates them.
*/
- *prev_p = *periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
+ *prev_p = *periodic_next_shadow(ehci, &here,
+ Q_NEXT_TYPE(ehci, *hw_p));
*hw_p = *here.hw_next;
}
@@ -87,18 +90,19 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
static unsigned short
periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
{
- __le32 *hw_p = &ehci->periodic [frame];
+ __hc32 *hw_p = &ehci->periodic [frame];
union ehci_shadow *q = &ehci->pshadow [frame];
unsigned usecs = 0;
while (q->ptr) {
- switch (Q_NEXT_TYPE (*hw_p)) {
+ switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
case Q_TYPE_QH:
/* is it in the S-mask? */
- if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe))
+ if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << uframe))
usecs += q->qh->usecs;
/* ... or C-mask? */
- if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe)))
+ if (q->qh->hw_info2 & cpu_to_hc32(ehci,
+ 1 << (8 + uframe)))
usecs += q->qh->c_usecs;
hw_p = &q->qh->hw_next;
q = &q->qh->qh_next;
@@ -108,7 +112,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
/* for "save place" FSTNs, count the relevant INTR
* bandwidth from the previous frame
*/
- if (q->fstn->hw_prev != EHCI_LIST_END) {
+ if (q->fstn->hw_prev != EHCI_LIST_END(ehci)) {
ehci_dbg (ehci, "ignoring FSTN cost ...\n");
}
hw_p = &q->fstn->hw_next;
@@ -121,9 +125,10 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
break;
case Q_TYPE_SITD:
/* is it in the S-mask? (count SPLIT, DATA) */
- if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) {
+ if (q->sitd->hw_uframe & cpu_to_hc32(ehci,
+ 1 << uframe)) {
if (q->sitd->hw_fullspeed_ep &
- __constant_cpu_to_le32 (1<<31))
+ cpu_to_hc32(ehci, 1<<31))
usecs += q->sitd->stream->usecs;
else /* worst case for OUT start-split */
usecs += HS_USECS_ISO (188);
@@ -131,7 +136,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
/* ... C-mask? (count CSPLIT, DATA) */
if (q->sitd->hw_uframe &
- cpu_to_le32 (1 << (8 + uframe))) {
+ cpu_to_hc32(ehci, 1 << (8 + uframe))) {
/* worst case for IN complete-split */
usecs += q->sitd->stream->c_usecs;
}
@@ -173,9 +178,9 @@ static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
* will cause a transfer in "B-frame" uframe 0. "B-frames" lag
* "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7.
*/
-static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask)
+static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
{
- unsigned char smask = QH_SMASK & le32_to_cpu(mask);
+ unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask);
if (!smask) {
ehci_err(ehci, "invalid empty smask!\n");
/* uframe 7 can't have bw so this will indicate failure */
@@ -217,14 +222,14 @@ periodic_tt_usecs (
unsigned short tt_usecs[8]
)
{
- __le32 *hw_p = &ehci->periodic [frame];
+ __hc32 *hw_p = &ehci->periodic [frame];
union ehci_shadow *q = &ehci->pshadow [frame];
unsigned char uf;
memset(tt_usecs, 0, 16);
while (q->ptr) {
- switch (Q_NEXT_TYPE(*hw_p)) {
+ switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) {
case Q_TYPE_ITD:
hw_p = &q->itd->hw_next;
q = &q->itd->itd_next;
@@ -247,8 +252,8 @@ periodic_tt_usecs (
continue;
// case Q_TYPE_FSTN:
default:
- ehci_dbg(ehci,
- "ignoring periodic frame %d FSTN\n", frame);
+ ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n",
+ frame);
hw_p = &q->fstn->hw_next;
q = &q->fstn->fstn_next;
}
@@ -368,41 +373,42 @@ static int tt_no_collision (
*/
for (; frame < ehci->periodic_size; frame += period) {
union ehci_shadow here;
- __le32 type;
+ __hc32 type;
here = ehci->pshadow [frame];
- type = Q_NEXT_TYPE (ehci->periodic [frame]);
+ type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]);
while (here.ptr) {
- switch (type) {
+ switch (hc32_to_cpu(ehci, type)) {
case Q_TYPE_ITD:
- type = Q_NEXT_TYPE (here.itd->hw_next);
+ type = Q_NEXT_TYPE(ehci, here.itd->hw_next);
here = here.itd->itd_next;
continue;
case Q_TYPE_QH:
if (same_tt (dev, here.qh->dev)) {
u32 mask;
- mask = le32_to_cpu (here.qh->hw_info2);
+ mask = hc32_to_cpu(ehci,
+ here.qh->hw_info2);
/* "knows" no gap is needed */
mask |= mask >> 8;
if (mask & uf_mask)
break;
}
- type = Q_NEXT_TYPE (here.qh->hw_next);
+ type = Q_NEXT_TYPE(ehci, here.qh->hw_next);
here = here.qh->qh_next;
continue;
case Q_TYPE_SITD:
if (same_tt (dev, here.sitd->urb->dev)) {
u16 mask;
- mask = le32_to_cpu (here.sitd
+ mask = hc32_to_cpu(ehci, here.sitd
->hw_uframe);
/* FIXME assumes no gap for IN! */
mask |= mask >> 8;
if (mask & uf_mask)
break;
}
- type = Q_NEXT_TYPE (here.sitd->hw_next);
+ type = Q_NEXT_TYPE(ehci, here.sitd->hw_next);
here = here.sitd->sitd_next;
continue;
// case Q_TYPE_FSTN:
@@ -473,6 +479,109 @@ static int disable_periodic (struct ehci_hcd *ehci)
}
/*-------------------------------------------------------------------------*/
+#ifdef CONFIG_CPU_FREQ
+
+static int safe_to_modify_i (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ int now; /* current (frame * 8) + uframe */
+ int prev_start, next_start; /* uframes from/to split start */
+ int start_uframe = ffs(le32_to_cpup (&qh->hw_info2) & QH_SMASK);
+ int end_uframe = fls((le32_to_cpup (&qh->hw_info2) & QH_CMASK) >> 8);
+ int split_duration = end_uframe - start_uframe;
+
+ now = readl(&ehci->regs->frame_index) % (ehci->periodic_size << 3);
+
+ next_start = ((1024 << 3) + (qh->start << 3) + start_uframe - now)
+ % (qh->period << 3);
+ prev_start = (qh->period << 3) - next_start;
+
+ /*
+ * Make sure there will be at least one uframe when qh is safe.
+ */
+ if ((qh->period << 3) <= (ehci->i_thresh + 2 + split_duration))
+ /* never safe */
+ return -EINVAL;
+
+ /*
+ * Wait 1 uframe after transaction should have started, to make
+ * sure controller has time to write back overlay, so we can
+ * check QTD_STS_STS to see if transaction is in progress.
+ */
+ if ((next_start > ehci->i_thresh) && (prev_start > 1))
+ /* safe to set "i" bit if split isn't in progress */
+ return (qh->hw_token & STATUS_BIT(ehci)) ? 0 : 1;
+ else
+ return 0;
+}
+
+/* Set inactivate bit for all the split interrupt QHs. */
+static void qh_inactivate_split_intr_qhs (struct ehci_hcd *ehci)
+{
+ struct ehci_qh *qh;
+ int not_done, safe;
+ u32 inactivate = INACTIVATE_BIT(ehci);
+ u32 active = ACTIVE_BIT(ehci);
+
+ do {
+ not_done = 0;
+ list_for_each_entry(qh, &ehci->split_intr_qhs,
+ split_intr_qhs) {
+ if (qh->hw_info1 & inactivate)
+ /* already off */
+ continue;
+ /*
+ * To avoid setting "I" after the start split happens,
+ * don't set it if the QH might be cached in the
+ * controller. Some HCs (Broadcom/ServerWorks HT1000)
+ * will stop in the middle of a split transaction when
+ * the "I" bit is set.
+ */
+ safe = safe_to_modify_i(ehci, qh);
+ if (safe == 0) {
+ not_done = 1;
+ } else if (safe > 0) {
+ qh->was_active = qh->hw_token & active;
+ qh->hw_info1 |= inactivate;
+ }
+ }
+ } while (not_done);
+ wmb();
+}
+
+static void qh_reactivate_split_intr_qhs (struct ehci_hcd *ehci)
+{
+ struct ehci_qh *qh;
+ u32 token;
+ int not_done, safe;
+ u32 inactivate = INACTIVATE_BIT(ehci);
+ u32 active = ACTIVE_BIT(ehci);
+ u32 halt = HALT_BIT(ehci);
+
+ do {
+ not_done = 0;
+ list_for_each_entry(qh, &ehci->split_intr_qhs, split_intr_qhs) {
+ if (!(qh->hw_info1 & inactivate)) /* already on */
+ continue;
+ /*
+ * Don't reactivate if cached, or controller might
+ * overwrite overlay after we modify it!
+ */
+ safe = safe_to_modify_i(ehci, qh);
+ if (safe == 0) {
+ not_done = 1;
+ } else if (safe > 0) {
+ /* See EHCI 1.0 section 4.15.2.4. */
+ token = qh->hw_token;
+ qh->hw_token = (token | halt) & ~active;
+ wmb();
+ qh->hw_info1 &= ~inactivate;
+ wmb();
+ qh->hw_token = (token & ~halt) | qh->was_active;
+ }
+ }
+ } while (not_done);
+}
+#endif
/* periodic schedule slots have iso tds (normal or split) first, then a
* sparse tree for active interrupt transfers.
@@ -487,25 +596,36 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
dev_dbg (&qh->dev->dev,
"link qh%d-%04x/%p start %d [%d/%d us]\n",
- period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
+ period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
+#ifdef CONFIG_CPU_FREQ
+ /*
+ * If low/full speed interrupt QHs are inactive (because of
+ * cpufreq changing processor speeds), start QH with I flag set--
+ * it will automatically be cleared when cpufreq is done.
+ */
+ if (ehci->cpufreq_changing)
+ if (!(qh->hw_info1 & (cpu_to_le32(1 << 13))))
+ qh->hw_info1 |= INACTIVATE_BIT(ehci);
+#endif
+
/* high bandwidth, or otherwise every microframe */
if (period == 0)
period = 1;
for (i = qh->start; i < ehci->periodic_size; i += period) {
- union ehci_shadow *prev = &ehci->pshadow [i];
- __le32 *hw_p = &ehci->periodic [i];
+ union ehci_shadow *prev = &ehci->pshadow[i];
+ __hc32 *hw_p = &ehci->periodic[i];
union ehci_shadow here = *prev;
- __le32 type = 0;
+ __hc32 type = 0;
/* skip the iso nodes at list head */
while (here.ptr) {
- type = Q_NEXT_TYPE (*hw_p);
- if (type == Q_TYPE_QH)
+ type = Q_NEXT_TYPE(ehci, *hw_p);
+ if (type == cpu_to_hc32(ehci, Q_TYPE_QH))
break;
- prev = periodic_next_shadow (prev, type);
+ prev = periodic_next_shadow(ehci, prev, type);
hw_p = &here.qh->hw_next;
here = *prev;
}
@@ -527,7 +647,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->hw_next = *hw_p;
wmb ();
prev->qh = qh;
- *hw_p = QH_NEXT (qh->qh_dma);
+ *hw_p = QH_NEXT (ehci, qh->qh_dma);
}
}
qh->qh_state = QH_STATE_LINKED;
@@ -538,6 +658,12 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
? ((qh->usecs + qh->c_usecs) / qh->period)
: (qh->usecs * 8);
+#ifdef CONFIG_CPU_FREQ
+ /* add qh to list of low/full speed interrupt QHs, if applicable */
+ if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) {
+ list_add(&qh->split_intr_qhs, &ehci->split_intr_qhs);
+ }
+#endif
/* maybe enable periodic schedule processing */
if (!ehci->periodic_sched++)
return enable_periodic (ehci);
@@ -555,7 +681,14 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
// and this qh is active in the current uframe
// (and overlay token SplitXstate is false?)
// THEN
- // qh->hw_info1 |= __constant_cpu_to_le32 (1 << 7 /* "ignore" */);
+ // qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */);
+
+#ifdef CONFIG_CPU_FREQ
+ /* remove qh from list of low/full speed interrupt QHs */
+ if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) {
+ list_del_init(&qh->split_intr_qhs);
+ }
+#endif
/* high bandwidth, or otherwise part of every microframe */
if ((period = qh->period) == 0)
@@ -572,7 +705,7 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
dev_dbg (&qh->dev->dev,
"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
qh->period,
- le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
+ hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
/* qh->qh_next still "live" to HC */
@@ -598,7 +731,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
* active high speed queues may need bigger delays...
*/
if (list_empty (&qh->qtd_list)
- || (__constant_cpu_to_le32 (QH_CMASK)
+ || (cpu_to_hc32(ehci, QH_CMASK)
& qh->hw_info2) != 0)
wait = 2;
else
@@ -606,7 +739,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
udelay (wait);
qh->qh_state = QH_STATE_IDLE;
- qh->hw_next = EHCI_LIST_END;
+ qh->hw_next = EHCI_LIST_END(ehci);
wmb ();
}
@@ -663,7 +796,7 @@ static int check_intr_schedule (
unsigned frame,
unsigned uframe,
const struct ehci_qh *qh,
- __le32 *c_maskp
+ __hc32 *c_maskp
)
{
int retval = -ENOSPC;
@@ -695,7 +828,7 @@ static int check_intr_schedule (
retval = 0;
- *c_maskp = cpu_to_le32 (mask << 8);
+ *c_maskp = cpu_to_hc32(ehci, mask << 8);
}
#else
/* Make sure this tt's buffer is also available for CSPLITs.
@@ -706,7 +839,7 @@ static int check_intr_schedule (
* one smart pass...
*/
mask = 0x03 << (uframe + qh->gap_uf);
- *c_maskp = cpu_to_le32 (mask << 8);
+ *c_maskp = cpu_to_hc32(ehci, mask << 8);
mask |= 1 << uframe;
if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) {
@@ -726,20 +859,20 @@ done:
/* "first fit" scheduling policy used the first time through,
* or when the previous schedule slot can't be re-used.
*/
-static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
{
int status;
unsigned uframe;
- __le32 c_mask;
+ __hc32 c_mask;
unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
qh_refresh(ehci, qh);
- qh->hw_next = EHCI_LIST_END;
+ qh->hw_next = EHCI_LIST_END(ehci);
frame = qh->start;
/* reuse the previous schedule slots, if we can */
if (frame < qh->period) {
- uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK);
+ uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK);
status = check_intr_schedule (ehci, frame, --uframe,
qh, &c_mask);
} else {
@@ -775,10 +908,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */
- qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK));
+ qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK));
qh->hw_info2 |= qh->period
- ? cpu_to_le32 (1 << uframe)
- : __constant_cpu_to_le32 (QH_SMASK);
+ ? cpu_to_hc32(ehci, 1 << uframe)
+ : cpu_to_hc32(ehci, QH_SMASK);
qh->hw_info2 |= c_mask;
} else
ehci_dbg (ehci, "reused qh %p schedule\n", qh);
@@ -808,7 +941,7 @@ static int intr_submit (
spin_lock_irqsave (&ehci->lock, flags);
if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
- &ehci_to_hcd(ehci)->flags))) {
+ &ehci_to_hcd(ehci)->flags))) {
status = -ESHUTDOWN;
goto done;
}
@@ -898,9 +1031,9 @@ iso_stream_init (
buf1 |= maxp;
maxp *= multi;
- stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum);
- stream->buf1 = cpu_to_le32 (buf1);
- stream->buf2 = cpu_to_le32 (multi);
+ stream->buf0 = cpu_to_hc32(ehci, (epnum << 8) | dev->devnum);
+ stream->buf1 = cpu_to_hc32(ehci, buf1);
+ stream->buf2 = cpu_to_hc32(ehci, multi);
/* usbfs wants to report the average usecs per frame tied up
* when transfers on this endpoint are scheduled ...
@@ -943,7 +1076,7 @@ iso_stream_init (
bandwidth /= 1 << (interval + 2);
/* stream->splits gets created from raw_mask later */
- stream->address = cpu_to_le32 (addr);
+ stream->address = cpu_to_hc32(ehci, addr);
}
stream->bandwidth = bandwidth;
@@ -1077,7 +1210,8 @@ iso_sched_alloc (unsigned packets, gfp_t mem_flags)
}
static inline void
-itd_sched_init (
+itd_sched_init(
+ struct ehci_hcd *ehci,
struct ehci_iso_sched *iso_sched,
struct ehci_iso_stream *stream,
struct urb *urb
@@ -1107,7 +1241,7 @@ itd_sched_init (
&& !(urb->transfer_flags & URB_NO_INTERRUPT))
trans |= EHCI_ITD_IOC;
trans |= length << 16;
- uframe->transaction = cpu_to_le32 (trans);
+ uframe->transaction = cpu_to_hc32(ehci, trans);
/* might need to cross a buffer page within a uframe */
uframe->bufp = (buf & ~(u64)0x0fff);
@@ -1149,7 +1283,7 @@ itd_urb_transaction (
if (unlikely (sched == NULL))
return -ENOMEM;
- itd_sched_init (sched, stream, urb);
+ itd_sched_init(ehci, sched, stream, urb);
if (urb->interval < 8)
num_itds = 1 + (sched->span + 7) / 8;
@@ -1167,7 +1301,7 @@ itd_urb_transaction (
/* prefer previously-allocated itds */
if (likely (!list_empty(&stream->free_list))) {
itd = list_entry (stream->free_list.prev,
- struct ehci_itd, itd_list);
+ struct ehci_itd, itd_list);
list_del (&itd->itd_list);
itd_dma = itd->itd_dma;
} else
@@ -1294,7 +1428,7 @@ sitd_slot_ok (
uframe += period_uframes;
} while (uframe < mod);
- stream->splits = cpu_to_le32(stream->raw_mask << (uframe & 7));
+ stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7));
return 1;
}
@@ -1415,12 +1549,13 @@ ready:
/*-------------------------------------------------------------------------*/
static inline void
-itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
+itd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream,
+ struct ehci_itd *itd)
{
int i;
/* it's been recently zeroed */
- itd->hw_next = EHCI_LIST_END;
+ itd->hw_next = EHCI_LIST_END(ehci);
itd->hw_bufp [0] = stream->buf0;
itd->hw_bufp [1] = stream->buf1;
itd->hw_bufp [2] = stream->buf2;
@@ -1432,7 +1567,8 @@ itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
}
static inline void
-itd_patch (
+itd_patch(
+ struct ehci_hcd *ehci,
struct ehci_itd *itd,
struct ehci_iso_sched *iso_sched,
unsigned index,
@@ -1447,17 +1583,18 @@ itd_patch (
uframe &= 0x07;
itd->index [uframe] = index;
- itd->hw_transaction [uframe] = uf->transaction;
- itd->hw_transaction [uframe] |= cpu_to_le32 (pg << 12);
- itd->hw_bufp [pg] |= cpu_to_le32 (uf->bufp & ~(u32)0);
- itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32));
+ itd->hw_transaction[uframe] = uf->transaction;
+ itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12);
+ itd->hw_bufp[pg] |= cpu_to_hc32(ehci, uf->bufp & ~(u32)0);
+ itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32));
/* iso_frame_desc[].offset must be strictly increasing */
if (unlikely (uf->cross)) {
u64 bufp = uf->bufp + 4096;
+
itd->pg = ++pg;
- itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0);
- itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(bufp >> 32));
+ itd->hw_bufp[pg] |= cpu_to_hc32(ehci, bufp & ~(u32)0);
+ itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(bufp >> 32));
}
}
@@ -1470,7 +1607,7 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
ehci->pshadow [frame].itd = itd;
itd->frame = frame;
wmb ();
- ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD;
+ ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
}
/* fit urb's itds into the selected schedule slot; activate as needed */
@@ -1515,14 +1652,14 @@ itd_link_urb (
list_move_tail (&itd->itd_list, &stream->td_list);
itd->stream = iso_stream_get (stream);
itd->urb = usb_get_urb (urb);
- itd_init (stream, itd);
+ itd_init (ehci, stream, itd);
}
uframe = next_uframe & 0x07;
frame = next_uframe >> 3;
itd->usecs [uframe] = stream->usecs;
- itd_patch (itd, iso_sched, packet, uframe);
+ itd_patch(ehci, itd, iso_sched, packet, uframe);
next_uframe += stream->interval;
stream->depth += stream->interval;
@@ -1570,7 +1707,7 @@ itd_complete (
urb_index = itd->index[uframe];
desc = &urb->iso_frame_desc [urb_index];
- t = le32_to_cpup (&itd->hw_transaction [uframe]);
+ t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]);
itd->hw_transaction [uframe] = 0;
stream->depth -= stream->interval;
@@ -1700,7 +1837,8 @@ done:
*/
static inline void
-sitd_sched_init (
+sitd_sched_init(
+ struct ehci_hcd *ehci,
struct ehci_iso_sched *iso_sched,
struct ehci_iso_stream *stream,
struct urb *urb
@@ -1729,7 +1867,7 @@ sitd_sched_init (
&& !(urb->transfer_flags & URB_NO_INTERRUPT))
trans |= SITD_IOC;
trans |= length << 16;
- packet->transaction = cpu_to_le32 (trans);
+ packet->transaction = cpu_to_hc32(ehci, trans);
/* might need to cross a buffer page within a td */
packet->bufp = buf;
@@ -1765,7 +1903,7 @@ sitd_urb_transaction (
if (iso_sched == NULL)
return -ENOMEM;
- sitd_sched_init (iso_sched, stream, urb);
+ sitd_sched_init(ehci, iso_sched, stream, urb);
/* allocate/init sITDs */
spin_lock_irqsave (&ehci->lock, flags);
@@ -1817,7 +1955,8 @@ sitd_urb_transaction (
/*-------------------------------------------------------------------------*/
static inline void
-sitd_patch (
+sitd_patch(
+ struct ehci_hcd *ehci,
struct ehci_iso_stream *stream,
struct ehci_sitd *sitd,
struct ehci_iso_sched *iso_sched,
@@ -1827,20 +1966,20 @@ sitd_patch (
struct ehci_iso_packet *uf = &iso_sched->packet [index];
u64 bufp = uf->bufp;
- sitd->hw_next = EHCI_LIST_END;
+ sitd->hw_next = EHCI_LIST_END(ehci);
sitd->hw_fullspeed_ep = stream->address;
sitd->hw_uframe = stream->splits;
sitd->hw_results = uf->transaction;
- sitd->hw_backpointer = EHCI_LIST_END;
+ sitd->hw_backpointer = EHCI_LIST_END(ehci);
bufp = uf->bufp;
- sitd->hw_buf [0] = cpu_to_le32 (bufp);
- sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32);
+ sitd->hw_buf[0] = cpu_to_hc32(ehci, bufp);
+ sitd->hw_buf_hi[0] = cpu_to_hc32(ehci, bufp >> 32);
- sitd->hw_buf [1] = cpu_to_le32 (uf->buf1);
+ sitd->hw_buf[1] = cpu_to_hc32(ehci, uf->buf1);
if (uf->cross)
bufp += 4096;
- sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32);
+ sitd->hw_buf_hi[1] = cpu_to_hc32(ehci, bufp >> 32);
sitd->index = index;
}
@@ -1853,7 +1992,7 @@ sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd)
ehci->pshadow [frame].sitd = sitd;
sitd->frame = frame;
wmb ();
- ehci->periodic [frame] = cpu_to_le32 (sitd->sitd_dma) | Q_TYPE_SITD;
+ ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD);
}
/* fit urb's sitds into the selected schedule slot; activate as needed */
@@ -1881,7 +2020,7 @@ sitd_link_urb (
urb->dev->devpath, stream->bEndpointAddress & 0x0f,
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
(next_uframe >> 3) % ehci->periodic_size,
- stream->interval, le32_to_cpu (stream->splits));
+ stream->interval, hc32_to_cpu(ehci, stream->splits));
stream->start = jiffies;
}
ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -1902,7 +2041,7 @@ sitd_link_urb (
sitd->stream = iso_stream_get (stream);
sitd->urb = usb_get_urb (urb);
- sitd_patch (stream, sitd, sched, packet);
+ sitd_patch(ehci, stream, sitd, sched, packet);
sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size,
sitd);
@@ -1940,7 +2079,7 @@ sitd_complete (
urb_index = sitd->index;
desc = &urb->iso_frame_desc [urb_index];
- t = le32_to_cpup (&sitd->hw_results);
+ t = hc32_to_cpup(ehci, &sitd->hw_results);
/* report transfer status */
if (t & SITD_ERRS) {
@@ -2095,7 +2234,7 @@ scan_periodic (struct ehci_hcd *ehci)
for (;;) {
union ehci_shadow q, *q_p;
- __le32 type, *hw_p;
+ __hc32 type, *hw_p;
unsigned uframes;
/* don't scan past the live uframe */
@@ -2113,7 +2252,7 @@ restart:
q_p = &ehci->pshadow [frame];
hw_p = &ehci->periodic [frame];
q.ptr = q_p->ptr;
- type = Q_NEXT_TYPE (*hw_p);
+ type = Q_NEXT_TYPE(ehci, *hw_p);
modified = 0;
while (q.ptr != NULL) {
@@ -2122,11 +2261,11 @@ restart:
int live;
live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state);
- switch (type) {
+ switch (hc32_to_cpu(ehci, type)) {
case Q_TYPE_QH:
/* handle any completions */
temp.qh = qh_get (q.qh);
- type = Q_NEXT_TYPE (q.qh->hw_next);
+ type = Q_NEXT_TYPE(ehci, q.qh->hw_next);
q = q.qh->qh_next;
modified = qh_completions (ehci, temp.qh);
if (unlikely (list_empty (&temp.qh->qtd_list)))
@@ -2137,10 +2276,10 @@ restart:
/* for "save place" FSTNs, look at QH entries
* in the previous frame for completions.
*/
- if (q.fstn->hw_prev != EHCI_LIST_END) {
+ if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) {
dbg ("ignoring completions from FSTNs");
}
- type = Q_NEXT_TYPE (q.fstn->hw_next);
+ type = Q_NEXT_TYPE(ehci, q.fstn->hw_next);
q = q.fstn->fstn_next;
break;
case Q_TYPE_ITD:
@@ -2148,11 +2287,12 @@ restart:
rmb ();
for (uf = live ? uframes : 8; uf < 8; uf++) {
if (0 == (q.itd->hw_transaction [uf]
- & ITD_ACTIVE))
+ & ITD_ACTIVE(ehci)))
continue;
q_p = &q.itd->itd_next;
hw_p = &q.itd->hw_next;
- type = Q_NEXT_TYPE (q.itd->hw_next);
+ type = Q_NEXT_TYPE(ehci,
+ q.itd->hw_next);
q = *q_p;
break;
}
@@ -2164,23 +2304,24 @@ restart:
*/
*q_p = q.itd->itd_next;
*hw_p = q.itd->hw_next;
- type = Q_NEXT_TYPE (q.itd->hw_next);
+ type = Q_NEXT_TYPE(ehci, q.itd->hw_next);
wmb();
modified = itd_complete (ehci, q.itd);
q = *q_p;
break;
case Q_TYPE_SITD:
- if ((q.sitd->hw_results & SITD_ACTIVE)
+ if ((q.sitd->hw_results & SITD_ACTIVE(ehci))
&& live) {
q_p = &q.sitd->sitd_next;
hw_p = &q.sitd->hw_next;
- type = Q_NEXT_TYPE (q.sitd->hw_next);
+ type = Q_NEXT_TYPE(ehci,
+ q.sitd->hw_next);
q = *q_p;
break;
}
*q_p = q.sitd->sitd_next;
*hw_p = q.sitd->hw_next;
- type = Q_NEXT_TYPE (q.sitd->hw_next);
+ type = Q_NEXT_TYPE(ehci, q.sitd->hw_next);
wmb();
modified = sitd_complete (ehci, q.sitd);
q = *q_p;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 46fa57a520d..2c68a04230c 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -21,6 +21,22 @@
/* definitions used for the EHCI driver */
+/*
+ * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
+ * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on
+ * the host controller implementation.
+ *
+ * To facilitate the strongest possible byte-order checking from "sparse"
+ * and so on, we use __leXX unless that's not practical.
+ */
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+typedef __u32 __bitwise __hc32;
+typedef __u16 __bitwise __hc16;
+#else
+#define __hc32 __le32
+#define __hc16 __le16
+#endif
+
/* statistics can be kept for for tuning/monitoring */
struct ehci_stats {
/* irq usage */
@@ -55,6 +71,12 @@ struct ehci_hcd { /* one per controller */
__u32 hcs_params; /* cached register copy */
spinlock_t lock;
+#ifdef CONFIG_CPU_FREQ
+ struct notifier_block cpufreq_transition;
+ int cpufreq_changing;
+ struct list_head split_intr_qhs;
+#endif
+
/* async schedule support */
struct ehci_qh *async;
struct ehci_qh *reclaim;
@@ -64,7 +86,7 @@ struct ehci_hcd { /* one per controller */
/* periodic schedule support */
#define DEFAULT_I_TDPS 1024 /* some HCs can do less */
unsigned periodic_size;
- __le32 *periodic; /* hw periodic table */
+ __hc32 *periodic; /* hw periodic table */
dma_addr_t periodic_dma;
unsigned i_thresh; /* uframes HC might cache */
@@ -74,11 +96,14 @@ struct ehci_hcd { /* one per controller */
/* per root hub port */
unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
+
/* bit vectors (one bit per port) */
unsigned long bus_suspended; /* which ports were
already suspended at the start of a bus suspend */
unsigned long companion_ports; /* which ports are
dedicated to the companion controller */
+ unsigned long owned_ports; /* which ports are
+ owned by the companion during a bus suspend */
/* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */
@@ -97,6 +122,7 @@ struct ehci_hcd { /* one per controller */
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
unsigned big_endian_mmio:1;
+ unsigned big_endian_desc:1;
u8 sbrn; /* packed release number */
@@ -276,6 +302,12 @@ struct ehci_regs {
#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
} __attribute__ ((packed));
+#define USBMODE 0x68 /* USB Device mode */
+#define USBMODE_SDIS (1<<3) /* Stream disable */
+#define USBMODE_BE (1<<2) /* BE/LE endianness select */
+#define USBMODE_CM_HC (3<<0) /* host controller mode */
+#define USBMODE_CM_IDLE (0<<0) /* idle state */
+
/* Appendix C, Debug port ... intended for use with special "debug devices"
* that can help if there's no serial console. (nonstandard enumeration.)
*/
@@ -303,7 +335,7 @@ struct ehci_dbg_port {
/*-------------------------------------------------------------------------*/
-#define QTD_NEXT(dma) cpu_to_le32((u32)dma)
+#define QTD_NEXT(ehci, dma) cpu_to_hc32(ehci, (u32)dma)
/*
* EHCI Specification 0.95 Section 3.5
@@ -315,9 +347,9 @@ struct ehci_dbg_port {
*/
struct ehci_qtd {
/* first part defined by EHCI spec */
- __le32 hw_next; /* see EHCI 3.5.1 */
- __le32 hw_alt_next; /* see EHCI 3.5.2 */
- __le32 hw_token; /* see EHCI 3.5.3 */
+ __hc32 hw_next; /* see EHCI 3.5.1 */
+ __hc32 hw_alt_next; /* see EHCI 3.5.2 */
+ __hc32 hw_token; /* see EHCI 3.5.3 */
#define QTD_TOGGLE (1 << 31) /* data toggle */
#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
#define QTD_IOC (1 << 15) /* interrupt on complete */
@@ -331,8 +363,13 @@ struct ehci_qtd {
#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */
#define QTD_STS_STS (1 << 1) /* split transaction state */
#define QTD_STS_PING (1 << 0) /* issue PING? */
- __le32 hw_buf [5]; /* see EHCI 3.5.4 */
- __le32 hw_buf_hi [5]; /* Appendix B */
+
+#define ACTIVE_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_ACTIVE)
+#define HALT_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_HALT)
+#define STATUS_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_STS)
+
+ __hc32 hw_buf [5]; /* see EHCI 3.5.4 */
+ __hc32 hw_buf_hi [5]; /* Appendix B */
/* the rest is HCD-private */
dma_addr_t qtd_dma; /* qtd address */
@@ -342,26 +379,33 @@ struct ehci_qtd {
} __attribute__ ((aligned (32)));
/* mask NakCnt+T in qh->hw_alt_next */
-#define QTD_MASK __constant_cpu_to_le32 (~0x1f)
+#define QTD_MASK(ehci) cpu_to_hc32 (ehci, ~0x1f)
#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
/*-------------------------------------------------------------------------*/
/* type tag from {qh,itd,sitd,fstn}->hw_next */
-#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
+#define Q_NEXT_TYPE(ehci,dma) ((dma) & cpu_to_hc32(ehci, 3 << 1))
+/*
+ * Now the following defines are not converted using the
+ * __constant_cpu_to_le32() macro anymore, since we have to support
+ * "dynamic" switching between be and le support, so that the driver
+ * can be used on one system with SoC EHCI controller using big-endian
+ * descriptors as well as a normal little-endian PCI EHCI controller.
+ */
/* values for that type tag */
-#define Q_TYPE_ITD __constant_cpu_to_le32 (0 << 1)
-#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1)
-#define Q_TYPE_SITD __constant_cpu_to_le32 (2 << 1)
-#define Q_TYPE_FSTN __constant_cpu_to_le32 (3 << 1)
+#define Q_TYPE_ITD (0 << 1)
+#define Q_TYPE_QH (1 << 1)
+#define Q_TYPE_SITD (2 << 1)
+#define Q_TYPE_FSTN (3 << 1)
/* next async queue entry, or pointer to interrupt/periodic QH */
-#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
+#define QH_NEXT(ehci,dma) (cpu_to_hc32(ehci, (((u32)dma)&~0x01f)|Q_TYPE_QH))
/* for periodic/async schedules and qtd lists, mark end of list */
-#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */
+#define EHCI_LIST_END(ehci) cpu_to_hc32(ehci, 1) /* "null pointer" to hw */
/*
* Entries in periodic shadow table are pointers to one of four kinds
@@ -376,7 +420,7 @@ union ehci_shadow {
struct ehci_itd *itd; /* Q_TYPE_ITD */
struct ehci_sitd *sitd; /* Q_TYPE_SITD */
struct ehci_fstn *fstn; /* Q_TYPE_FSTN */
- __le32 *hw_next; /* (all types) */
+ __hc32 *hw_next; /* (all types) */
void *ptr;
};
@@ -392,23 +436,27 @@ union ehci_shadow {
struct ehci_qh {
/* first part defined by EHCI spec */
- __le32 hw_next; /* see EHCI 3.6.1 */
- __le32 hw_info1; /* see EHCI 3.6.2 */
+ __hc32 hw_next; /* see EHCI 3.6.1 */
+ __hc32 hw_info1; /* see EHCI 3.6.2 */
#define QH_HEAD 0x00008000
- __le32 hw_info2; /* see EHCI 3.6.2 */
+#define QH_INACTIVATE 0x00000080
+
+#define INACTIVATE_BIT(ehci) cpu_to_hc32(ehci, QH_INACTIVATE)
+
+ __hc32 hw_info2; /* see EHCI 3.6.2 */
#define QH_SMASK 0x000000ff
#define QH_CMASK 0x0000ff00
#define QH_HUBADDR 0x007f0000
#define QH_HUBPORT 0x3f800000
#define QH_MULT 0xc0000000
- __le32 hw_current; /* qtd list - see EHCI 3.6.4 */
+ __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */
/* qtd overlay (hardware parts of a struct ehci_qtd) */
- __le32 hw_qtd_next;
- __le32 hw_alt_next;
- __le32 hw_token;
- __le32 hw_buf [5];
- __le32 hw_buf_hi [5];
+ __hc32 hw_qtd_next;
+ __hc32 hw_alt_next;
+ __hc32 hw_token;
+ __hc32 hw_buf [5];
+ __hc32 hw_buf_hi [5];
/* the rest is HCD-private */
dma_addr_t qh_dma; /* address of qh */
@@ -418,7 +466,14 @@ struct ehci_qh {
struct ehci_qh *reclaim; /* next to reclaim */
struct ehci_hcd *ehci;
- struct kref kref;
+
+ /*
+ * Do NOT use atomic operations for QH refcounting. On some CPUs
+ * (PPC7448 for example), atomic operations cannot be performed on
+ * memory that is cache-inhibited (i.e. being used for DMA).
+ * Spinlocks are used to protect all QH fields.
+ */
+ u32 refcount;
unsigned stamp;
u8 qh_state;
@@ -437,6 +492,10 @@ struct ehci_qh {
unsigned short start; /* where polling starts */
#define NO_FRAME ((unsigned short)~0) /* pick new start */
struct usb_device *dev; /* access to TT */
+#ifdef CONFIG_CPU_FREQ
+ struct list_head split_intr_qhs; /* list of split qhs */
+ __le32 was_active; /* active bit before "i" set */
+#endif
} __attribute__ ((aligned (32)));
/*-------------------------------------------------------------------------*/
@@ -445,7 +504,7 @@ struct ehci_qh {
struct ehci_iso_packet {
/* These will be copied to iTD when scheduling */
u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */
- __le32 transaction; /* itd->hw_transaction[i] |= */
+ __hc32 transaction; /* itd->hw_transaction[i] |= */
u8 cross; /* buf crosses pages */
/* for full speed OUT splits */
u32 buf1;
@@ -467,8 +526,8 @@ struct ehci_iso_sched {
*/
struct ehci_iso_stream {
/* first two fields match QH, but info1 == 0 */
- __le32 hw_next;
- __le32 hw_info1;
+ __hc32 hw_next;
+ __hc32 hw_info1;
u32 refcount;
u8 bEndpointAddress;
@@ -483,7 +542,7 @@ struct ehci_iso_stream {
unsigned long start; /* jiffies */
unsigned long rescheduled;
int next_uframe;
- __le32 splits;
+ __hc32 splits;
/* the rest is derived from the endpoint descriptor,
* trusting urb->interval == f(epdesc->bInterval) and
@@ -497,12 +556,12 @@ struct ehci_iso_stream {
unsigned bandwidth;
/* This is used to initialize iTD's hw_bufp fields */
- __le32 buf0;
- __le32 buf1;
- __le32 buf2;
+ __hc32 buf0;
+ __hc32 buf1;
+ __hc32 buf2;
/* this is used to initialize sITD's tt info */
- __le32 address;
+ __hc32 address;
};
/*-------------------------------------------------------------------------*/
@@ -515,8 +574,8 @@ struct ehci_iso_stream {
*/
struct ehci_itd {
/* first part defined by EHCI spec */
- __le32 hw_next; /* see EHCI 3.3.1 */
- __le32 hw_transaction [8]; /* see EHCI 3.3.2 */
+ __hc32 hw_next; /* see EHCI 3.3.1 */
+ __hc32 hw_transaction [8]; /* see EHCI 3.3.2 */
#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */
#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */
#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */
@@ -524,10 +583,10 @@ struct ehci_itd {
#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff)
#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */
-#define ITD_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
+#define ITD_ACTIVE(ehci) cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE)
- __le32 hw_bufp [7]; /* see EHCI 3.3.3 */
- __le32 hw_bufp_hi [7]; /* Appendix B */
+ __hc32 hw_bufp [7]; /* see EHCI 3.3.3 */
+ __hc32 hw_bufp_hi [7]; /* Appendix B */
/* the rest is HCD-private */
dma_addr_t itd_dma; /* for this itd */
@@ -554,11 +613,11 @@ struct ehci_itd {
*/
struct ehci_sitd {
/* first part defined by EHCI spec */
- __le32 hw_next;
+ __hc32 hw_next;
/* uses bit field macros above - see EHCI 0.95 Table 3-8 */
- __le32 hw_fullspeed_ep; /* EHCI table 3-9 */
- __le32 hw_uframe; /* EHCI table 3-10 */
- __le32 hw_results; /* EHCI table 3-11 */
+ __hc32 hw_fullspeed_ep; /* EHCI table 3-9 */
+ __hc32 hw_uframe; /* EHCI table 3-10 */
+ __hc32 hw_results; /* EHCI table 3-11 */
#define SITD_IOC (1 << 31) /* interrupt on completion */
#define SITD_PAGE (1 << 30) /* buffer 0/1 */
#define SITD_LENGTH(x) (0x3ff & ((x)>>16))
@@ -570,11 +629,11 @@ struct ehci_sitd {
#define SITD_STS_MMF (1 << 2) /* incomplete split transaction */
#define SITD_STS_STS (1 << 1) /* split transaction state */
-#define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE)
+#define SITD_ACTIVE(ehci) cpu_to_hc32(ehci, SITD_STS_ACTIVE)
- __le32 hw_buf [2]; /* EHCI table 3-12 */
- __le32 hw_backpointer; /* EHCI table 3-13 */
- __le32 hw_buf_hi [2]; /* Appendix B */
+ __hc32 hw_buf [2]; /* EHCI table 3-12 */
+ __hc32 hw_backpointer; /* EHCI table 3-13 */
+ __hc32 hw_buf_hi [2]; /* Appendix B */
/* the rest is HCD-private */
dma_addr_t sitd_dma;
@@ -599,8 +658,8 @@ struct ehci_sitd {
* it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
*/
struct ehci_fstn {
- __le32 hw_next; /* any periodic q entry */
- __le32 hw_prev; /* qh or EHCI_LIST_END */
+ __hc32 hw_next; /* any periodic q entry */
+ __hc32 hw_prev; /* qh or EHCI_LIST_END */
/* the rest is HCD-private */
dma_addr_t fstn_dma;
@@ -672,8 +731,21 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
#define ehci_big_endian_mmio(e) 0
#endif
-static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
- __u32 __iomem * regs)
+/*
+ * Big-endian read/write functions are arch-specific.
+ * Other arches can be added if/when they're needed.
+ *
+ * REVISIT: arch/powerpc now has readl/writel_be, so the
+ * definition below can die once the 4xx support is
+ * finally ported over.
+ */
+#if defined(CONFIG_PPC)
+#define readl_be(addr) in_be32((__force unsigned *)addr)
+#define writel_be(val, addr) out_be32((__force unsigned *)addr, val)
+#endif
+
+static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
+ __u32 __iomem * regs)
{
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
return ehci_big_endian_mmio(ehci) ?
@@ -684,8 +756,8 @@ static inline unsigned int ehci_readl (const struct ehci_hcd *ehci,
#endif
}
-static inline void ehci_writel (const struct ehci_hcd *ehci,
- const unsigned int val, __u32 __iomem *regs)
+static inline void ehci_writel(const struct ehci_hcd *ehci,
+ const unsigned int val, __u32 __iomem *regs)
{
#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
ehci_big_endian_mmio(ehci) ?
@@ -698,6 +770,62 @@ static inline void ehci_writel (const struct ehci_hcd *ehci,
/*-------------------------------------------------------------------------*/
+/*
+ * The AMCC 440EPx not only implements its EHCI registers in big-endian
+ * format, but also its DMA data structures (descriptors).
+ *
+ * EHCI controllers accessed through PCI work normally (little-endian
+ * everywhere), so we won't bother supporting a BE-only mode for now.
+ */
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC
+#define ehci_big_endian_desc(e) ((e)->big_endian_desc)
+
+/* cpu to ehci */
+static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x)
+{
+ return ehci_big_endian_desc(ehci)
+ ? (__force __hc32)cpu_to_be32(x)
+ : (__force __hc32)cpu_to_le32(x);
+}
+
+/* ehci to cpu */
+static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x)
+{
+ return ehci_big_endian_desc(ehci)
+ ? be32_to_cpu((__force __be32)x)
+ : le32_to_cpu((__force __le32)x);
+}
+
+static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+{
+ return ehci_big_endian_desc(ehci)
+ ? be32_to_cpup((__force __be32 *)x)
+ : le32_to_cpup((__force __le32 *)x);
+}
+
+#else
+
+/* cpu to ehci */
+static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x)
+{
+ return cpu_to_le32(x);
+}
+
+/* ehci to cpu */
+static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x)
+{
+ return le32_to_cpu(x);
+}
+
+static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
+{
+ return le32_to_cpup(x);
+}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
#ifndef DEBUG
#define STUB_DEBUG_FILES
#endif /* DEBUG */
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 273d5ddb72b..6f9e43e9a6c 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -23,7 +23,7 @@
/* debug| print the main components of an URB
* small: 0) header + data packets 1) just header
*/
-static void __attribute__((unused))
+static void __maybe_unused
urb_print (struct urb * urb, char * str, int small)
{
unsigned int pipe= urb->pipe;
@@ -338,7 +338,7 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label,
}
/* caller MUST own hcd spinlock if verbose is set! */
-static void __attribute__((unused))
+static void __maybe_unused
ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
const struct ed *ed, int verbose)
{
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index a66637e725f..2038125b7f8 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -35,15 +35,13 @@
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/reboot.h>
+#include <linux/workqueue.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/byteorder.h>
-#ifdef CONFIG_PPC_PS3
-#include <asm/firmware.h>
-#endif
#include "../core/hcd.h"
@@ -82,6 +80,8 @@ static const char hcd_name [] = "ohci_hcd";
static void ohci_dump (struct ohci_hcd *ohci, int verbose);
static int ohci_init (struct ohci_hcd *ohci);
static void ohci_stop (struct usb_hcd *hcd);
+static int ohci_restart (struct ohci_hcd *ohci);
+static void ohci_quirk_nec_worker (struct work_struct *work);
#include "ohci-hub.c"
#include "ohci-dbg.c"
@@ -510,15 +510,7 @@ static int ohci_run (struct ohci_hcd *ohci)
// flush the writes
(void) ohci_readl (ohci, &ohci->regs->control);
msleep(temp);
- temp = roothub_a (ohci);
- if (!(temp & RH_A_NPS)) {
- /* power down each port */
- for (temp = 0; temp < ohci->num_ports; temp++)
- ohci_writel (ohci, RH_PS_LSDA,
- &ohci->regs->roothub.portstatus [temp]);
- }
- // flush those writes
- (void) ohci_readl (ohci, &ohci->regs->control);
+
memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
/* 2msec timelimit here means no irqs/preempt */
@@ -659,9 +651,20 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
}
if (ints & OHCI_INTR_UE) {
- disable (ohci);
- ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
// e.g. due to PCI Master/Target Abort
+ if (ohci->flags & OHCI_QUIRK_NEC) {
+ /* Workaround for a silicon bug in some NEC chips used
+ * in Apple's PowerBooks. Adapted from Darwin code.
+ */
+ ohci_err (ohci, "OHCI Unrecoverable Error, scheduling NEC chip restart\n");
+
+ ohci_writel (ohci, OHCI_INTR_UE, &regs->intrdisable);
+
+ schedule_work (&ohci->nec_work);
+ } else {
+ disable (ohci);
+ ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
+ }
ohci_dump (ohci, 1);
ohci_usb_reset (ohci);
@@ -763,23 +766,16 @@ static void ohci_stop (struct usb_hcd *hcd)
/*-------------------------------------------------------------------------*/
/* must not be called from interrupt context */
-
-#ifdef CONFIG_PM
-
static int ohci_restart (struct ohci_hcd *ohci)
{
int temp;
int i;
struct urb_priv *priv;
- /* mark any devices gone, so they do nothing till khubd disconnects.
- * recycle any "live" eds/tds (and urbs) right away.
- * later, khubd disconnect processing will recycle the other state,
- * (either as disconnect/reconnect, or maybe someday as a reset).
- */
spin_lock_irq(&ohci->lock);
disable (ohci);
- usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub);
+
+ /* Recycle any "live" eds/tds (and urbs). */
if (!list_empty (&ohci->pending))
ohci_dbg(ohci, "abort schedule...\n");
list_for_each_entry (priv, &ohci->pending, pending) {
@@ -826,20 +822,31 @@ static int ohci_restart (struct ohci_hcd *ohci)
if ((temp = ohci_run (ohci)) < 0) {
ohci_err (ohci, "can't restart, %d\n", temp);
return temp;
- } else {
- /* here we "know" root ports should always stay powered,
- * and that if we try to turn them back on the root hub
- * will respond to CSC processing.
- */
- i = ohci->num_ports;
- while (i--)
- ohci_writel (ohci, RH_PS_PSS,
- &ohci->regs->roothub.portstatus [i]);
- ohci_dbg (ohci, "restart complete\n");
}
+ ohci_dbg(ohci, "restart complete\n");
return 0;
}
-#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* NEC workaround */
+static void ohci_quirk_nec_worker(struct work_struct *work)
+{
+ struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work);
+ int status;
+
+ status = ohci_init(ohci);
+ if (status != 0) {
+ ohci_err(ohci, "Restarting NEC controller failed "
+ "in ohci_init, %d\n", status);
+ return;
+ }
+
+ status = ohci_restart(ohci);
+ if (status != 0)
+ ohci_err(ohci, "Restarting NEC controller failed "
+ "in ohci_restart, %d\n", status);
+}
/*-------------------------------------------------------------------------*/
@@ -917,7 +924,7 @@ MODULE_LICENSE ("GPL");
#ifdef CONFIG_PPC_PS3
#include "ohci-ps3.c"
-#define PS3_SYSTEM_BUS_DRIVER ps3_ohci_sb_driver
+#define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver
#endif
#if !defined(PCI_DRIVER) && \
@@ -940,12 +947,9 @@ static int __init ohci_hcd_mod_init(void)
sizeof (struct ed), sizeof (struct td));
#ifdef PS3_SYSTEM_BUS_DRIVER
- if (firmware_has_feature(FW_FEATURE_PS3_LV1)) {
- retval = ps3_system_bus_driver_register(
- &PS3_SYSTEM_BUS_DRIVER);
- if (retval < 0)
- goto error_ps3;
- }
+ retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
+ if (retval < 0)
+ goto error_ps3;
#endif
#ifdef PLATFORM_DRIVER
@@ -991,8 +995,7 @@ static int __init ohci_hcd_mod_init(void)
error_platform:
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
- if (firmware_has_feature(FW_FEATURE_PS3_LV1))
- ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+ ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
error_ps3:
#endif
return retval;
@@ -1014,8 +1017,7 @@ static void __exit ohci_hcd_mod_exit(void)
platform_driver_unregister(&PLATFORM_DRIVER);
#endif
#ifdef PS3_SYSTEM_BUS_DRIVER
- if (firmware_has_feature(FW_FEATURE_PS3_LV1))
- ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
+ ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
#endif
}
module_exit(ohci_hcd_mod_exit);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 216c9c9d4d6..48e4b11f4d3 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -55,8 +55,6 @@ static void dl_done_list (struct ohci_hcd *);
static void finish_unlinks (struct ohci_hcd *, u16);
#ifdef CONFIG_PM
-static int ohci_restart(struct ohci_hcd *ohci);
-
static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
__releases(ohci->lock)
__acquires(ohci->lock)
@@ -191,6 +189,9 @@ __acquires(ohci->lock)
spin_unlock_irq (&ohci->lock);
(void) ohci_init (ohci);
status = ohci_restart (ohci);
+
+ usb_root_hub_lost_power(hcd->self.root_hub);
+
spin_lock_irq (&ohci->lock);
}
return status;
@@ -417,6 +418,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+ goto done;
/* undocumented erratum seen on at least rev D */
if ((ohci->flags & OHCI_QUIRK_AMD756)
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 2f20d3dc895..450c7b460c5 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -28,6 +28,7 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
ohci->next_statechange = jiffies;
spin_lock_init (&ohci->lock);
INIT_LIST_HEAD (&ohci->pending);
+ INIT_WORK (&ohci->nec_work, ohci_quirk_nec_worker);
}
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index ca62cb58322..a5e2eb85d07 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -111,6 +111,18 @@ static int ohci_quirk_toshiba_scc(struct usb_hcd *hcd)
#endif
}
+/* Check for NEC chip and apply quirk for allegedly lost interrupts.
+ */
+static int ohci_quirk_nec(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+
+ ohci->flags |= OHCI_QUIRK_NEC;
+ ohci_dbg (ohci, "enabled NEC chipset lost interrupt quirk\n");
+
+ return 0;
+}
+
/* List of quirks for OHCI */
static const struct pci_device_id ohci_pci_quirks[] = {
{
@@ -134,6 +146,10 @@ static const struct pci_device_id ohci_pci_quirks[] = {
.driver_data = (unsigned long)ohci_quirk_toshiba_scc,
},
{
+ PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB),
+ .driver_data = (unsigned long)ohci_quirk_nec,
+ },
+ {
/* Toshiba portege 4000 */
.vendor = PCI_VENDOR_ID_AL,
.device = 0x5237,
@@ -202,6 +218,42 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd)
return ret;
}
+#if defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \
+ defined(CONFIG_USB_EHCI_HCD_MODULE))
+
+/* Following a power loss, we must prepare to regain control of the ports
+ * we used to own. This means turning on the port power before ehci-hcd
+ * tries to switch ownership.
+ *
+ * This isn't a 100% perfect solution. On most systems the OHCI controllers
+ * lie at lower PCI addresses than the EHCI controller, so they will be
+ * discovered (and hence resumed) first. But there is no guarantee things
+ * will always work this way. If the EHCI controller is resumed first and
+ * the OHCI ports are unpowered, then the handover will fail.
+ */
+static void prepare_for_handover(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+ int port;
+
+ /* Here we "know" root ports should always stay powered */
+ ohci_dbg(ohci, "powerup ports\n");
+ for (port = 0; port < ohci->num_ports; port++)
+ ohci_writel(ohci, RH_PS_PPS,
+ &ohci->regs->roothub.portstatus[port]);
+
+ /* Flush those writes */
+ ohci_readl(ohci, &ohci->regs->control);
+ msleep(20);
+}
+
+#else
+
+static inline void prepare_for_handover(struct usb_hcd *hcd)
+{ }
+
+#endif /* CONFIG_USB_PERSIST etc. */
+
#ifdef CONFIG_PM
static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
@@ -241,7 +293,10 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
static int ohci_pci_resume (struct usb_hcd *hcd)
{
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- usb_hcd_resume_root_hub(hcd);
+
+ /* FIXME: we should try to detect loss of VBUS power here */
+ prepare_for_handover(hcd);
+
return 0;
}
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index d601bbb9387..ca2a6abbc11 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -134,7 +134,7 @@ static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct i2c_client *c;
- c = (struct i2c_client *)kzalloc(sizeof(*c), GFP_KERNEL);
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return -ENOMEM;
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c
index d7cf07288b0..01a0caeaa6b 100644
--- a/drivers/usb/host/ohci-ps3.c
+++ b/drivers/usb/host/ohci-ps3.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <asm/firmware.h>
#include <asm/ps3.h>
static int ps3_ohci_hc_reset(struct usb_hcd *hcd)
@@ -75,7 +76,7 @@ static const struct hc_driver ps3_ohci_hc_driver = {
#endif
};
-static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
+static int ps3_ohci_probe(struct ps3_system_bus_device *dev)
{
int result;
struct usb_hcd *hcd;
@@ -87,13 +88,31 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
goto fail_start;
}
+ result = ps3_open_hv_device(dev);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed: %s\n",
+ __func__, __LINE__, ps3_result(result));
+ result = -EPERM;
+ goto fail_open;
+ }
+
+ result = ps3_dma_region_create(dev->d_region);
+
+ if (result) {
+ dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
+ "(%d)\n", __func__, __LINE__, result);
+ BUG_ON("check region type");
+ goto fail_dma_region;
+ }
+
result = ps3_mmio_region_create(dev->m_region);
if (result) {
dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n",
__func__, __LINE__);
result = -EPERM;
- goto fail_mmio;
+ goto fail_mmio_region;
}
dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__,
@@ -122,6 +141,11 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
hcd->rsrc_start = dev->m_region->lpar_addr;
hcd->rsrc_len = dev->m_region->len;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name))
+ dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n",
+ __func__, __LINE__);
+
hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len);
if (!hcd->regs) {
@@ -155,34 +179,73 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev)
fail_add_hcd:
iounmap(hcd->regs);
fail_ioremap:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd);
fail_create_hcd:
ps3_io_irq_destroy(virq);
fail_irq:
ps3_free_mmio_region(dev->m_region);
-fail_mmio:
+fail_mmio_region:
+ ps3_dma_region_free(dev->d_region);
+fail_dma_region:
+ ps3_close_hv_device(dev);
+fail_open:
fail_start:
return result;
}
-static int ps3_ohci_sb_remove (struct ps3_system_bus_device *dev)
+static int ps3_ohci_remove (struct ps3_system_bus_device *dev)
{
+ unsigned int tmp;
struct usb_hcd *hcd =
(struct usb_hcd *)ps3_system_bus_get_driver_data(dev);
- usb_put_hcd(hcd);
+ BUG_ON(!hcd);
+
+ dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs);
+ dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq);
+
+ tmp = hcd->irq;
+
+ usb_remove_hcd(hcd);
+
ps3_system_bus_set_driver_data(dev, NULL);
+ BUG_ON(!hcd->regs);
+ iounmap(hcd->regs);
+
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+
+ ps3_io_irq_destroy(tmp);
+ ps3_free_mmio_region(dev->m_region);
+
+ ps3_dma_region_free(dev->d_region);
+ ps3_close_hv_device(dev);
+
return 0;
}
-MODULE_ALIAS("ps3-ohci");
+static int ps3_ohci_driver_register(struct ps3_system_bus_driver *drv)
+{
+ return firmware_has_feature(FW_FEATURE_PS3_LV1)
+ ? ps3_system_bus_driver_register(drv)
+ : 0;
+}
+
+static void ps3_ohci_driver_unregister(struct ps3_system_bus_driver *drv)
+{
+ if (firmware_has_feature(FW_FEATURE_PS3_LV1))
+ ps3_system_bus_driver_unregister(drv);
+}
+
+MODULE_ALIAS(PS3_MODULE_ALIAS_OHCI);
-static struct ps3_system_bus_driver ps3_ohci_sb_driver = {
+static struct ps3_system_bus_driver ps3_ohci_driver = {
+ .core.name = "ps3-ohci-driver",
+ .core.owner = THIS_MODULE,
.match_id = PS3_MATCH_ID_OHCI,
- .core = {
- .name = "ps3-ohci-driver",
- },
- .probe = ps3_ohci_sb_probe,
- .remove = ps3_ohci_sb_remove,
+ .probe = ps3_ohci_probe,
+ .remove = ps3_ohci_remove,
+ .shutdown = ps3_ohci_remove,
};
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index c2b5ecfe5e9..4ada43cf138 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -397,8 +397,10 @@ struct ohci_hcd {
#define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */
#define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */
#define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/
+#define OHCI_QUIRK_NEC 0x40 /* lost interrupts */
// there are also chip quirks/bugs in init logic
+ struct work_struct nec_work; /* Worker for NEC quirk */
};
/* convert between an hcd pointer and the corresponding ohci_hcd */
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
new file mode 100644
index 00000000000..a7a7070c6e2
--- /dev/null
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -0,0 +1,2244 @@
+/*
+ * R8A66597 HCD (Host Controller Driver)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
+ * Portions Copyright (C) 2004-2005 David Brownell
+ * Portions Copyright (C) 1999 Roman Weissgaerber
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "../core/hcd.h"
+#include "r8a66597.h"
+
+MODULE_DESCRIPTION("R8A66597 USB Host Controller Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+
+#define DRIVER_VERSION "29 May 2007"
+
+static const char hcd_name[] = "r8a66597_hcd";
+
+/* module parameters */
+static unsigned short clock = XTAL12;
+module_param(clock, ushort, 0644);
+MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=0)");
+static unsigned short vif = LDRV;
+module_param(vif, ushort, 0644);
+MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)");
+static unsigned short endian = 0;
+module_param(endian, ushort, 0644);
+MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)");
+static unsigned short irq_sense = INTL;
+module_param(irq_sense, ushort, 0644);
+MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0(default=32)");
+
+static void packet_write(struct r8a66597 *r8a66597, u16 pipenum);
+static int r8a66597_get_frame(struct usb_hcd *hcd);
+
+/* this function must be called with interrupt disabled */
+static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+ unsigned long reg)
+{
+ u16 tmp;
+
+ tmp = r8a66597_read(r8a66597, INTENB0);
+ r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+ r8a66597_bset(r8a66597, 1 << pipenum, reg);
+ r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+/* this function must be called with interrupt disabled */
+static void disable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum,
+ unsigned long reg)
+{
+ u16 tmp;
+
+ tmp = r8a66597_read(r8a66597, INTENB0);
+ r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+ r8a66597_bclr(r8a66597, 1 << pipenum, reg);
+ r8a66597_write(r8a66597, tmp, INTENB0);
+}
+
+static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address,
+ u16 usbspd, u8 upphub, u8 hubport, int port)
+{
+ u16 val;
+ unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
+
+ val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001);
+ r8a66597_write(r8a66597, val, devadd_reg);
+}
+
+static int enable_controller(struct r8a66597 *r8a66597)
+{
+ u16 tmp;
+ int i = 0;
+
+ do {
+ r8a66597_write(r8a66597, USBE, SYSCFG0);
+ tmp = r8a66597_read(r8a66597, SYSCFG0);
+ if (i++ > 1000) {
+ err("register access fail.");
+ return -ENXIO;
+ }
+ } while ((tmp & USBE) != USBE);
+ r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+ r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0);
+
+ i = 0;
+ r8a66597_bset(r8a66597, XCKE, SYSCFG0);
+ do {
+ msleep(1);
+ tmp = r8a66597_read(r8a66597, SYSCFG0);
+ if (i++ > 500) {
+ err("register access fail.");
+ return -ENXIO;
+ }
+ } while ((tmp & SCKE) != SCKE);
+
+ r8a66597_bset(r8a66597, DCFM | DRPD, SYSCFG0);
+ r8a66597_bset(r8a66597, DRPD, SYSCFG1);
+
+ r8a66597_bset(r8a66597, vif & LDRV, PINCFG);
+ r8a66597_bset(r8a66597, HSE, SYSCFG0);
+ r8a66597_bset(r8a66597, HSE, SYSCFG1);
+ r8a66597_bset(r8a66597, USBE, SYSCFG0);
+
+ r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0);
+ r8a66597_bset(r8a66597, irq_sense & INTL, SOFCFG);
+ r8a66597_bset(r8a66597, BRDY0, BRDYENB);
+ r8a66597_bset(r8a66597, BEMP0, BEMPENB);
+
+ r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA0CFG);
+ r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA1CFG);
+
+ r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL);
+ r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL);
+ r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL);
+
+ r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
+
+ r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);
+ r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+ r8a66597_bset(r8a66597, ATTCHE, INTENB1);
+ r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+ r8a66597_bset(r8a66597, ATTCHE, INTENB2);
+
+ return 0;
+}
+
+static void disable_controller(struct r8a66597 *r8a66597)
+{
+ u16 tmp;
+
+ r8a66597_write(r8a66597, 0, INTENB0);
+ r8a66597_write(r8a66597, 0, INTENB1);
+ r8a66597_write(r8a66597, 0, INTENB2);
+ r8a66597_write(r8a66597, 0, INTSTS0);
+ r8a66597_write(r8a66597, 0, INTSTS1);
+ r8a66597_write(r8a66597, 0, INTSTS2);
+
+ r8a66597_port_power(r8a66597, 0, 0);
+ r8a66597_port_power(r8a66597, 1, 0);
+
+ do {
+ tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS;
+ udelay(640);
+ } while (tmp == EDGESTS);
+
+ r8a66597_bclr(r8a66597, DCFM | DRPD, SYSCFG0);
+ r8a66597_bclr(r8a66597, DRPD, SYSCFG1);
+ r8a66597_bclr(r8a66597, HSE, SYSCFG0);
+ r8a66597_bclr(r8a66597, HSE, SYSCFG1);
+
+ r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
+ udelay(1);
+ r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
+ r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
+ r8a66597_bclr(r8a66597, USBE, SYSCFG0);
+}
+
+static int get_parent_r8a66597_address(struct r8a66597 *r8a66597,
+ struct usb_device *udev)
+{
+ struct r8a66597_device *dev;
+
+ if (udev->parent && udev->parent->devnum != 1)
+ udev = udev->parent;
+
+ dev = dev_get_drvdata(&udev->dev);
+ if (dev)
+ return dev->address;
+ else
+ return 0;
+}
+
+static int is_child_device(char *devpath)
+{
+ return (devpath[2] ? 1 : 0);
+}
+
+static int is_hub_limit(char *devpath)
+{
+ return ((strlen(devpath) >= 4) ? 1 : 0);
+}
+
+static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port)
+{
+ if (root_port) {
+ *root_port = (devpath[0] & 0x0F) - 1;
+ if (*root_port >= R8A66597_MAX_ROOT_HUB)
+ err("illegal root port number");
+ }
+ if (hub_port)
+ *hub_port = devpath[2] & 0x0F;
+}
+
+static u16 get_r8a66597_usb_speed(enum usb_device_speed speed)
+{
+ u16 usbspd = 0;
+
+ switch (speed) {
+ case USB_SPEED_LOW:
+ usbspd = LSMODE;
+ break;
+ case USB_SPEED_FULL:
+ usbspd = FSMODE;
+ break;
+ case USB_SPEED_HIGH:
+ usbspd = HSMODE;
+ break;
+ default:
+ err("unknown speed");
+ break;
+ }
+
+ return usbspd;
+}
+
+static void set_child_connect_map(struct r8a66597 *r8a66597, int address)
+{
+ int idx;
+
+ idx = address / 32;
+ r8a66597->child_connect_map[idx] |= 1 << (address % 32);
+}
+
+static void put_child_connect_map(struct r8a66597 *r8a66597, int address)
+{
+ int idx;
+
+ idx = address / 32;
+ r8a66597->child_connect_map[idx] &= ~(1 << (address % 32));
+}
+
+static void set_pipe_reg_addr(struct r8a66597_pipe *pipe, u8 dma_ch)
+{
+ u16 pipenum = pipe->info.pipenum;
+ unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO};
+ unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL};
+ unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR};
+
+ if (dma_ch > R8A66597_PIPE_NO_DMA) /* dma fifo not use? */
+ dma_ch = R8A66597_PIPE_NO_DMA;
+
+ pipe->fifoaddr = fifoaddr[dma_ch];
+ pipe->fifosel = fifosel[dma_ch];
+ pipe->fifoctr = fifoctr[dma_ch];
+
+ if (pipenum == 0)
+ pipe->pipectr = DCPCTR;
+ else
+ pipe->pipectr = get_pipectr_addr(pipenum);
+
+ if (check_bulk_or_isoc(pipenum)) {
+ pipe->pipetre = get_pipetre_addr(pipenum);
+ pipe->pipetrn = get_pipetrn_addr(pipenum);
+ } else {
+ pipe->pipetre = 0;
+ pipe->pipetrn = 0;
+ }
+}
+
+static struct r8a66597_device *
+get_urb_to_r8a66597_dev(struct r8a66597 *r8a66597, struct urb *urb)
+{
+ if (usb_pipedevice(urb->pipe) == 0)
+ return &r8a66597->device0;
+
+ return dev_get_drvdata(&urb->dev->dev);
+}
+
+static int make_r8a66597_device(struct r8a66597 *r8a66597,
+ struct urb *urb, u8 addr)
+{
+ struct r8a66597_device *dev;
+ int usb_address = urb->setup_packet[2]; /* urb->pipe is address 0 */
+
+ dev = kzalloc(sizeof(struct r8a66597_device), GFP_KERNEL);
+ if (dev == NULL)
+ return -ENOMEM;
+
+ dev_set_drvdata(&urb->dev->dev, dev);
+ dev->udev = urb->dev;
+ dev->address = addr;
+ dev->usb_address = usb_address;
+ dev->state = USB_STATE_ADDRESS;
+ dev->ep_in_toggle = 0;
+ dev->ep_out_toggle = 0;
+ INIT_LIST_HEAD(&dev->device_list);
+ list_add_tail(&dev->device_list, &r8a66597->child_device);
+
+ get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port);
+ if (!is_child_device(urb->dev->devpath))
+ r8a66597->root_hub[dev->root_port].dev = dev;
+
+ set_devadd_reg(r8a66597, dev->address,
+ get_r8a66597_usb_speed(urb->dev->speed),
+ get_parent_r8a66597_address(r8a66597, urb->dev),
+ dev->hub_port, dev->root_port);
+
+ return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
+{
+ u8 addr; /* R8A66597's address */
+ struct r8a66597_device *dev;
+
+ if (is_hub_limit(urb->dev->devpath)) {
+ err("Externel hub limit reached.");
+ return 0;
+ }
+
+ dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+ if (dev && dev->state >= USB_STATE_ADDRESS)
+ return dev->address;
+
+ for (addr = 1; addr <= R8A66597_MAX_DEVICE; addr++) {
+ if (r8a66597->address_map & (1 << addr))
+ continue;
+
+ dbg("alloc_address: r8a66597_addr=%d", addr);
+ r8a66597->address_map |= 1 << addr;
+
+ if (make_r8a66597_device(r8a66597, urb, addr) < 0)
+ return 0;
+
+ return addr;
+ }
+
+ err("cannot communicate with a USB device more than 10.(%x)",
+ r8a66597->address_map);
+
+ return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void free_usb_address(struct r8a66597 *r8a66597,
+ struct r8a66597_device *dev)
+{
+ int port;
+
+ if (!dev)
+ return;
+
+ dbg("free_addr: addr=%d", dev->address);
+
+ dev->state = USB_STATE_DEFAULT;
+ r8a66597->address_map &= ~(1 << dev->address);
+ dev->address = 0;
+ dev_set_drvdata(&dev->udev->dev, NULL);
+ list_del(&dev->device_list);
+ kfree(dev);
+
+ for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
+ if (r8a66597->root_hub[port].dev == dev) {
+ r8a66597->root_hub[port].dev = NULL;
+ break;
+ }
+ }
+}
+
+static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg,
+ u16 mask, u16 loop)
+{
+ u16 tmp;
+ int i = 0;
+
+ do {
+ tmp = r8a66597_read(r8a66597, reg);
+ if (i++ > 1000000) {
+ err("register%lx, loop %x is timeout", reg, loop);
+ break;
+ }
+ ndelay(1);
+ } while ((tmp & mask) != loop);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_start(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe)
+{
+ u16 tmp;
+
+ tmp = r8a66597_read(r8a66597, pipe->pipectr) & PID;
+ if ((pipe->info.pipenum != 0) & ((tmp & PID_STALL) != 0)) /* stall? */
+ r8a66597_mdfy(r8a66597, PID_NAK, PID, pipe->pipectr);
+ r8a66597_mdfy(r8a66597, PID_BUF, PID, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_stop(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe)
+{
+ u16 tmp;
+
+ tmp = r8a66597_read(r8a66597, pipe->pipectr) & PID;
+ if ((tmp & PID_STALL11) != PID_STALL11) /* force stall? */
+ r8a66597_mdfy(r8a66597, PID_STALL, PID, pipe->pipectr);
+ r8a66597_mdfy(r8a66597, PID_NAK, PID, pipe->pipectr);
+ r8a66597_reg_wait(r8a66597, pipe->pipectr, PBUSY, 0);
+}
+
+/* this function must be called with interrupt disabled */
+static void clear_all_buffer(struct r8a66597 *r8a66597,
+ struct r8a66597_pipe *pipe)
+{
+ u16 tmp;
+
+ if (!pipe || pipe->info.pipenum == 0)
+ return;
+
+ pipe_stop(r8a66597, pipe);
+ r8a66597_bset(r8a66597, ACLRM, pipe->pipectr);
+ tmp = r8a66597_read(r8a66597, pipe->pipectr);
+ tmp = r8a66597_read(r8a66597, pipe->pipectr);
+ tmp = r8a66597_read(r8a66597, pipe->pipectr);
+ r8a66597_bclr(r8a66597, ACLRM, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597,
+ struct r8a66597_pipe *pipe, int toggle)
+{
+ if (toggle)
+ r8a66597_bset(r8a66597, SQSET, pipe->pipectr);
+ else
+ r8a66597_bset(r8a66597, SQCLR, pipe->pipectr);
+}
+
+/* this function must be called with interrupt disabled */
+static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
+{
+ r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
+}
+
+/* this function must be called with interrupt disabled */
+static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597,
+ struct r8a66597_pipe *pipe)
+{
+ cfifo_change(r8a66597, 0);
+ r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL);
+ r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL);
+
+ r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE,
+ pipe->fifosel);
+ r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum);
+}
+
+static u16 r8a66597_get_pipenum(struct urb *urb, struct usb_host_endpoint *hep)
+{
+ struct r8a66597_pipe *pipe = hep->hcpriv;
+
+ if (usb_pipeendpoint(urb->pipe) == 0)
+ return 0;
+ else
+ return pipe->info.pipenum;
+}
+
+static u16 get_urb_to_r8a66597_addr(struct r8a66597 *r8a66597, struct urb *urb)
+{
+ struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+
+ return (usb_pipedevice(urb->pipe) == 0) ? 0 : dev->address;
+}
+
+static unsigned short *get_toggle_pointer(struct r8a66597_device *dev,
+ int urb_pipe)
+{
+ if (!dev)
+ return NULL;
+
+ return usb_pipein(urb_pipe) ? &dev->ep_in_toggle : &dev->ep_out_toggle;
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_set(struct r8a66597 *r8a66597,
+ struct r8a66597_pipe *pipe,
+ struct urb *urb, int set)
+{
+ struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+ unsigned char endpoint = usb_pipeendpoint(urb->pipe);
+ unsigned short *toggle = get_toggle_pointer(dev, urb->pipe);
+
+ if (!toggle)
+ return;
+
+ if (set)
+ *toggle |= 1 << endpoint;
+ else
+ *toggle &= ~(1 << endpoint);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_save(struct r8a66597 *r8a66597,
+ struct r8a66597_pipe *pipe,
+ struct urb *urb)
+{
+ if (r8a66597_read(r8a66597, pipe->pipectr) & SQMON)
+ pipe_toggle_set(r8a66597, pipe, urb, 1);
+ else
+ pipe_toggle_set(r8a66597, pipe, urb, 0);
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_toggle_restore(struct r8a66597 *r8a66597,
+ struct r8a66597_pipe *pipe,
+ struct urb *urb)
+{
+ struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+ unsigned char endpoint = usb_pipeendpoint(urb->pipe);
+ unsigned short *toggle = get_toggle_pointer(dev, urb->pipe);
+
+ if (!toggle)
+ return;
+
+ r8a66597_pipe_toggle(r8a66597, pipe, *toggle & (1 << endpoint));
+}
+
+/* this function must be called with interrupt disabled */
+static void pipe_buffer_setting(struct r8a66597 *r8a66597,
+ struct r8a66597_pipe_info *info)
+{
+ u16 val = 0;
+
+ if (info->pipenum == 0)
+ return;
+
+ r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(info->pipenum));
+ r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(info->pipenum));
+ r8a66597_write(r8a66597, info->pipenum, PIPESEL);
+ if (!info->dir_in)
+ val |= R8A66597_DIR;
+ if (info->type == R8A66597_BULK && info->dir_in)
+ val |= R8A66597_DBLB | R8A66597_SHTNAK;
+ val |= info->type | info->epnum;
+ r8a66597_write(r8a66597, val, PIPECFG);
+
+ r8a66597_write(r8a66597, (info->buf_bsize << 10) | (info->bufnum),
+ PIPEBUF);
+ r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket,
+ PIPEMAXP);
+ if (info->interval)
+ info->interval--;
+ r8a66597_write(r8a66597, info->interval, PIPEPERI);
+}
+
+
+
+/* this function must be called with interrupt disabled */
+static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+ struct r8a66597_pipe_info *info;
+ struct urb *urb = td->urb;
+
+ if (td->pipenum > 0) {
+ info = &td->pipe->info;
+ cfifo_change(r8a66597, 0);
+ pipe_buffer_setting(r8a66597, info);
+
+ if (!usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe)) &&
+ !usb_pipecontrol(urb->pipe)) {
+ r8a66597_pipe_toggle(r8a66597, td->pipe, 0);
+ pipe_toggle_set(r8a66597, td->pipe, urb, 0);
+ clear_all_buffer(r8a66597, td->pipe);
+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe), 1);
+ }
+ pipe_toggle_restore(r8a66597, td->pipe, urb);
+ }
+}
+
+/* this function must be called with interrupt disabled */
+static u16 get_empty_pipenum(struct r8a66597 *r8a66597,
+ struct usb_endpoint_descriptor *ep)
+{
+ u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min;
+
+ memset(array, 0, sizeof(array));
+ switch(ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_BULK:
+ if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ array[i++] = 4;
+ else {
+ array[i++] = 3;
+ array[i++] = 5;
+ }
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+ array[i++] = 6;
+ array[i++] = 7;
+ array[i++] = 8;
+ } else
+ array[i++] = 9;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ array[i++] = 2;
+ else
+ array[i++] = 1;
+ break;
+ default:
+ err("Illegal type");
+ return 0;
+ }
+
+ i = 1;
+ min = array[0];
+ while (array[i] != 0) {
+ if (r8a66597->pipe_cnt[min] > r8a66597->pipe_cnt[array[i]])
+ min = array[i];
+ i++;
+ }
+
+ return min;
+}
+
+static u16 get_r8a66597_type(__u8 type)
+{
+ u16 r8a66597_type;
+
+ switch(type) {
+ case USB_ENDPOINT_XFER_BULK:
+ r8a66597_type = R8A66597_BULK;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ r8a66597_type = R8A66597_INT;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ r8a66597_type = R8A66597_ISO;
+ break;
+ default:
+ err("Illegal type");
+ r8a66597_type = 0x0000;
+ break;
+ }
+
+ return r8a66597_type;
+}
+
+static u16 get_bufnum(u16 pipenum)
+{
+ u16 bufnum = 0;
+
+ if (pipenum == 0)
+ bufnum = 0;
+ else if (check_bulk_or_isoc(pipenum))
+ bufnum = 8 + (pipenum - 1) * R8A66597_BUF_BSIZE*2;
+ else if (check_interrupt(pipenum))
+ bufnum = 4 + (pipenum - 6);
+ else
+ err("Illegal pipenum (%d)", pipenum);
+
+ return bufnum;
+}
+
+static u16 get_buf_bsize(u16 pipenum)
+{
+ u16 buf_bsize = 0;
+
+ if (pipenum == 0)
+ buf_bsize = 3;
+ else if (check_bulk_or_isoc(pipenum))
+ buf_bsize = R8A66597_BUF_BSIZE - 1;
+ else if (check_interrupt(pipenum))
+ buf_bsize = 0;
+ else
+ err("Illegal pipenum (%d)", pipenum);
+
+ return buf_bsize;
+}
+
+/* this function must be called with interrupt disabled */
+static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
+ struct r8a66597_device *dev,
+ struct r8a66597_pipe *pipe,
+ struct urb *urb)
+{
+ int i;
+ struct r8a66597_pipe_info *info = &pipe->info;
+
+ if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) {
+ for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) {
+ if ((r8a66597->dma_map & (1 << i)) != 0)
+ continue;
+
+ info("address %d, EndpointAddress 0x%02x use DMA FIFO",
+ usb_pipedevice(urb->pipe),
+ info->dir_in ? USB_ENDPOINT_DIR_MASK + info->epnum
+ : info->epnum);
+
+ r8a66597->dma_map |= 1 << i;
+ dev->dma_map |= 1 << i;
+ set_pipe_reg_addr(pipe, i);
+
+ cfifo_change(r8a66597, 0);
+ r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum,
+ MBW | CURPIPE, pipe->fifosel);
+
+ r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE,
+ pipe->info.pipenum);
+ r8a66597_bset(r8a66597, BCLR, pipe->fifoctr);
+ break;
+ }
+ }
+}
+
+/* this function must be called with interrupt disabled */
+static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb,
+ struct usb_host_endpoint *hep,
+ struct r8a66597_pipe_info *info)
+{
+ struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+ struct r8a66597_pipe *pipe = hep->hcpriv;
+
+ dbg("enable_pipe:");
+
+ pipe->info = *info;
+ set_pipe_reg_addr(pipe, R8A66597_PIPE_NO_DMA);
+ r8a66597->pipe_cnt[pipe->info.pipenum]++;
+ dev->pipe_cnt[pipe->info.pipenum]++;
+
+ enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb);
+}
+
+/* this function must be called with interrupt disabled */
+static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
+{
+ struct r8a66597_td *td, *next;
+ struct urb *urb;
+ struct list_head *list = &r8a66597->pipe_queue[pipenum];
+
+ if (list_empty(list))
+ return;
+
+ list_for_each_entry_safe(td, next, list, queue) {
+ if (!td)
+ continue;
+ if (td->address != address)
+ continue;
+
+ urb = td->urb;
+ list_del(&td->queue);
+ kfree(td);
+
+ if (urb) {
+ urb->status = -ENODEV;
+ urb->hcpriv = NULL;
+ spin_unlock(&r8a66597->lock);
+ usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb);
+ spin_lock(&r8a66597->lock);
+ }
+ break;
+ }
+}
+
+/* this function must be called with interrupt disabled */
+static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597,
+ struct r8a66597_device *dev)
+{
+ int check_ep0 = 0;
+ u16 pipenum;
+
+ if (!dev)
+ return;
+
+ for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+ if (!dev->pipe_cnt[pipenum])
+ continue;
+
+ if (!check_ep0) {
+ check_ep0 = 1;
+ force_dequeue(r8a66597, 0, dev->address);
+ }
+
+ r8a66597->pipe_cnt[pipenum] -= dev->pipe_cnt[pipenum];
+ dev->pipe_cnt[pipenum] = 0;
+ force_dequeue(r8a66597, pipenum, dev->address);
+ }
+
+ dbg("disable_pipe");
+
+ r8a66597->dma_map &= ~(dev->dma_map);
+ dev->dma_map = 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb,
+ struct usb_host_endpoint *hep,
+ struct usb_endpoint_descriptor *ep)
+{
+ struct r8a66597_pipe_info info;
+
+ info.pipenum = get_empty_pipenum(r8a66597, ep);
+ info.address = get_urb_to_r8a66597_addr(r8a66597, urb);
+ info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ info.maxpacket = ep->wMaxPacketSize;
+ info.type = get_r8a66597_type(ep->bmAttributes
+ & USB_ENDPOINT_XFERTYPE_MASK);
+ info.bufnum = get_bufnum(info.pipenum);
+ info.buf_bsize = get_buf_bsize(info.pipenum);
+ info.interval = ep->bInterval;
+ if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ info.dir_in = 1;
+ else
+ info.dir_in = 0;
+
+ enable_r8a66597_pipe(r8a66597, urb, hep, &info);
+}
+
+static void init_pipe_config(struct r8a66597 *r8a66597, struct urb *urb)
+{
+ struct r8a66597_device *dev;
+
+ dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+ dev->state = USB_STATE_CONFIGURED;
+}
+
+static void pipe_irq_enable(struct r8a66597 *r8a66597, struct urb *urb,
+ u16 pipenum)
+{
+ if (pipenum == 0 && usb_pipeout(urb->pipe))
+ enable_irq_empty(r8a66597, pipenum);
+ else
+ enable_irq_ready(r8a66597, pipenum);
+
+ if (!usb_pipeisoc(urb->pipe))
+ enable_irq_nrdy(r8a66597, pipenum);
+}
+
+static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum)
+{
+ disable_irq_ready(r8a66597, pipenum);
+ disable_irq_nrdy(r8a66597, pipenum);
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port)
+{
+ r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION)
+ | (1 << USB_PORT_FEAT_C_CONNECTION);
+ r8a66597_write(r8a66597, (u16)~DTCH, get_intsts_reg(port));
+ r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
+{
+ u16 speed = get_rh_usb_speed(r8a66597, port);
+ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+ if (speed == HSMODE)
+ rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED);
+ else if (speed == LSMODE)
+ rh->port |= (1 << USB_PORT_FEAT_LOWSPEED);
+
+ rh->port &= ~(1 << USB_PORT_FEAT_RESET);
+ rh->port |= 1 << USB_PORT_FEAT_ENABLE;
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)
+{
+ struct r8a66597_device *dev = r8a66597->root_hub[port].dev;
+
+ r8a66597->root_hub[port].port &= ~(1 << USB_PORT_FEAT_CONNECTION);
+ r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_C_CONNECTION);
+
+ disable_r8a66597_pipe_all(r8a66597, dev);
+ free_usb_address(r8a66597, dev);
+
+ r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_setup_packet(struct r8a66597 *r8a66597,
+ struct r8a66597_td *td)
+{
+ int i;
+ u16 *p = (u16 *)td->urb->setup_packet;
+ unsigned long setup_addr = USBREQ;
+
+ r8a66597_write(r8a66597, make_devsel(td->address) | td->maxpacket,
+ DCPMAXP);
+ r8a66597_write(r8a66597, (u16)~(SIGN | SACK), INTSTS1);
+
+ for (i = 0; i < 4; i++) {
+ r8a66597_write(r8a66597, p[i], setup_addr);
+ setup_addr += 2;
+ }
+ r8a66597_write(r8a66597, SUREQ, DCPCTR);
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_packet_read(struct r8a66597 *r8a66597,
+ struct r8a66597_td *td)
+{
+ struct urb *urb = td->urb;
+
+ if (usb_pipecontrol(urb->pipe)) {
+ r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+ r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ if (urb->actual_length == 0) {
+ r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+ r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+ }
+ pipe_irq_disable(r8a66597, td->pipenum);
+ pipe_start(r8a66597, td->pipe);
+ pipe_irq_enable(r8a66597, urb, td->pipenum);
+ } else {
+ if (urb->actual_length == 0) {
+ pipe_irq_disable(r8a66597, td->pipenum);
+ pipe_setting(r8a66597, td);
+ pipe_stop(r8a66597, td->pipe);
+ r8a66597_write(r8a66597, (u16)~(1 << td->pipenum),
+ BRDYSTS);
+
+ if (td->pipe->pipetre) {
+ r8a66597_write(r8a66597, TRCLR,
+ td->pipe->pipetre);
+ r8a66597_write(r8a66597,
+ (urb->transfer_buffer_length
+ + td->maxpacket - 1)
+ / td->maxpacket,
+ td->pipe->pipetrn);
+ r8a66597_bset(r8a66597, TRENB,
+ td->pipe->pipetre);
+ }
+
+ pipe_start(r8a66597, td->pipe);
+ pipe_irq_enable(r8a66597, urb, td->pipenum);
+ }
+ }
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_packet_write(struct r8a66597 *r8a66597,
+ struct r8a66597_td *td)
+{
+ u16 tmp;
+ struct urb *urb = td->urb;
+
+ if (usb_pipecontrol(urb->pipe)) {
+ pipe_stop(r8a66597, td->pipe);
+ r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+ r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ if (urb->actual_length == 0) {
+ r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+ r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+ }
+ } else {
+ if (urb->actual_length == 0)
+ pipe_setting(r8a66597, td);
+ if (td->pipe->pipetre)
+ r8a66597_bclr(r8a66597, TRENB, td->pipe->pipetre);
+ }
+ r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), BRDYSTS);
+
+ fifo_change_from_pipe(r8a66597, td->pipe);
+ tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+ if (unlikely((tmp & FRDY) == 0))
+ pipe_irq_enable(r8a66597, urb, td->pipenum);
+ else
+ packet_write(r8a66597, td->pipenum);
+ pipe_start(r8a66597, td->pipe);
+}
+
+/* this function must be called with interrupt disabled */
+static void prepare_status_packet(struct r8a66597 *r8a66597,
+ struct r8a66597_td *td)
+{
+ struct urb *urb = td->urb;
+
+ r8a66597_pipe_toggle(r8a66597, td->pipe, 1);
+
+ if (urb->setup_packet[0] & USB_ENDPOINT_DIR_MASK) {
+ r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG);
+ r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ r8a66597_write(r8a66597, BVAL | BCLR, CFIFOCTR);
+ r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS);
+ enable_irq_empty(r8a66597, 0);
+ } else {
+ r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG);
+ r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL);
+ r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0);
+ r8a66597_write(r8a66597, BCLR, CFIFOCTR);
+ r8a66597_write(r8a66597, (u16)~BRDY0, BRDYSTS);
+ r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS);
+ enable_irq_ready(r8a66597, 0);
+ }
+ enable_irq_nrdy(r8a66597, 0);
+ pipe_start(r8a66597, td->pipe);
+}
+
+/* this function must be called with interrupt disabled */
+static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+ BUG_ON(!td);
+
+ switch (td->type) {
+ case USB_PID_SETUP:
+ if (td->urb->setup_packet[1] == USB_REQ_SET_ADDRESS) {
+ td->set_address = 1;
+ td->urb->setup_packet[2] = alloc_usb_address(r8a66597,
+ td->urb);
+ if (td->urb->setup_packet[2] == 0)
+ return -EPIPE;
+ }
+ prepare_setup_packet(r8a66597, td);
+ break;
+ case USB_PID_IN:
+ prepare_packet_read(r8a66597, td);
+ break;
+ case USB_PID_OUT:
+ prepare_packet_write(r8a66597, td);
+ break;
+ case USB_PID_ACK:
+ prepare_status_packet(r8a66597, td);
+ break;
+ default:
+ err("invalid type.");
+ break;
+ }
+
+ return 0;
+}
+
+static int check_transfer_finish(struct r8a66597_td *td, struct urb *urb)
+{
+ if (usb_pipeisoc(urb->pipe)) {
+ if (urb->number_of_packets == td->iso_cnt)
+ return 1;
+ }
+
+ /* control or bulk or interrupt */
+ if ((urb->transfer_buffer_length <= urb->actual_length) ||
+ (td->short_packet) || (td->zero_packet))
+ return 1;
+
+ return 0;
+}
+
+/* this function must be called with interrupt disabled */
+static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
+{
+ unsigned long time;
+
+ BUG_ON(!td);
+
+ if (!list_empty(&r8a66597->pipe_queue[td->pipenum]) &&
+ !usb_pipecontrol(td->urb->pipe) && usb_pipein(td->urb->pipe)) {
+ r8a66597->timeout_map |= 1 << td->pipenum;
+ switch (usb_pipetype(td->urb->pipe)) {
+ case PIPE_INTERRUPT:
+ case PIPE_ISOCHRONOUS:
+ time = 30;
+ break;
+ default:
+ time = 300;
+ break;
+ }
+
+ mod_timer(&r8a66597->td_timer[td->pipenum],
+ jiffies + msecs_to_jiffies(time));
+ }
+}
+
+/* this function must be called with interrupt disabled */
+static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+ u16 pipenum, struct urb *urb)
+{
+ int restart = 0;
+ struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
+
+ r8a66597->timeout_map &= ~(1 << pipenum);
+
+ if (likely(td)) {
+ if (td->set_address && urb->status != 0)
+ r8a66597->address_map &= ~(1 << urb->setup_packet[2]);
+
+ pipe_toggle_save(r8a66597, td->pipe, urb);
+ list_del(&td->queue);
+ kfree(td);
+ }
+
+ if (!list_empty(&r8a66597->pipe_queue[pipenum]))
+ restart = 1;
+
+ if (likely(urb)) {
+ if (usb_pipeisoc(urb->pipe))
+ urb->start_frame = r8a66597_get_frame(hcd);
+
+ urb->hcpriv = NULL;
+ spin_unlock(&r8a66597->lock);
+ usb_hcd_giveback_urb(hcd, urb);
+ spin_lock(&r8a66597->lock);
+ }
+
+ if (restart) {
+ td = r8a66597_get_td(r8a66597, pipenum);
+ if (unlikely(!td))
+ return;
+
+ start_transfer(r8a66597, td);
+ set_td_timer(r8a66597, td);
+ }
+}
+
+/* this function must be called with interrupt disabled */
+static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td,
+ u16 pipenum, struct urb *urb)
+__releases(r8a66597->lock) __acquires(r8a66597->lock)
+{
+ done(r8a66597, td, pipenum, urb);
+}
+
+static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
+{
+ u16 tmp;
+ int rcv_len, bufsize, urb_len, size;
+ u16 *buf;
+ struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+ struct urb *urb;
+ int finish = 0;
+
+ if (unlikely(!td))
+ return;
+ urb = td->urb;
+
+ fifo_change_from_pipe(r8a66597, td->pipe);
+ tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+ if (unlikely((tmp & FRDY) == 0)) {
+ urb->status = -EPIPE;
+ pipe_stop(r8a66597, td->pipe);
+ pipe_irq_disable(r8a66597, pipenum);
+ err("in fifo not ready (%d)", pipenum);
+ finish_request(r8a66597, td, pipenum, td->urb);
+ return;
+ }
+
+ /* prepare parameters */
+ rcv_len = tmp & DTLN;
+ bufsize = td->maxpacket;
+ if (usb_pipeisoc(urb->pipe)) {
+ buf = (u16 *)(urb->transfer_buffer +
+ urb->iso_frame_desc[td->iso_cnt].offset);
+ urb_len = urb->iso_frame_desc[td->iso_cnt].length;
+ } else {
+ buf = (void *)urb->transfer_buffer + urb->actual_length;
+ urb_len = urb->transfer_buffer_length - urb->actual_length;
+ }
+ if (rcv_len < bufsize)
+ size = min(rcv_len, urb_len);
+ else
+ size = min(bufsize, urb_len);
+
+ /* update parameters */
+ urb->actual_length += size;
+ if (rcv_len == 0)
+ td->zero_packet = 1;
+ if ((size % td->maxpacket) > 0) {
+ td->short_packet = 1;
+ if (urb->transfer_buffer_length != urb->actual_length &&
+ urb->transfer_flags & URB_SHORT_NOT_OK)
+ td->urb->status = -EREMOTEIO;
+ }
+ if (usb_pipeisoc(urb->pipe)) {
+ urb->iso_frame_desc[td->iso_cnt].actual_length = size;
+ urb->iso_frame_desc[td->iso_cnt].status = 0;
+ td->iso_cnt++;
+ }
+
+ /* check transfer finish */
+ if (check_transfer_finish(td, urb)) {
+ pipe_stop(r8a66597, td->pipe);
+ pipe_irq_disable(r8a66597, pipenum);
+ finish = 1;
+ }
+
+ /* read fifo */
+ if (urb->transfer_buffer) {
+ if (size == 0)
+ r8a66597_write(r8a66597, BCLR, td->pipe->fifoctr);
+ else
+ r8a66597_read_fifo(r8a66597, td->pipe->fifoaddr,
+ buf, size);
+ }
+
+ if (finish && pipenum != 0) {
+ if (td->urb->status == -EINPROGRESS)
+ td->urb->status = 0;
+ finish_request(r8a66597, td, pipenum, urb);
+ }
+}
+
+static void packet_write(struct r8a66597 *r8a66597, u16 pipenum)
+{
+ u16 tmp;
+ int bufsize, size;
+ u16 *buf;
+ struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+ struct urb *urb;
+
+ if (unlikely(!td))
+ return;
+ urb = td->urb;
+
+ fifo_change_from_pipe(r8a66597, td->pipe);
+ tmp = r8a66597_read(r8a66597, td->pipe->fifoctr);
+ if (unlikely((tmp & FRDY) == 0)) {
+ urb->status = -EPIPE;
+ pipe_stop(r8a66597, td->pipe);
+ pipe_irq_disable(r8a66597, pipenum);
+ err("out write fifo not ready. (%d)", pipenum);
+ finish_request(r8a66597, td, pipenum, td->urb);
+ return;
+ }
+
+ /* prepare parameters */
+ bufsize = td->maxpacket;
+ if (usb_pipeisoc(urb->pipe)) {
+ buf = (u16 *)(urb->transfer_buffer +
+ urb->iso_frame_desc[td->iso_cnt].offset);
+ size = min(bufsize,
+ (int)urb->iso_frame_desc[td->iso_cnt].length);
+ } else {
+ buf = (u16 *)(urb->transfer_buffer + urb->actual_length);
+ size = min((int)bufsize,
+ urb->transfer_buffer_length - urb->actual_length);
+ }
+
+ /* write fifo */
+ if (pipenum > 0)
+ r8a66597_write(r8a66597, (u16)~(1 << pipenum), BEMPSTS);
+ if (urb->transfer_buffer) {
+ r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size);
+ if (!usb_pipebulk(urb->pipe) || td->maxpacket != size)
+ r8a66597_write(r8a66597, BVAL, td->pipe->fifoctr);
+ }
+
+ /* update parameters */
+ urb->actual_length += size;
+ if (usb_pipeisoc(urb->pipe)) {
+ urb->iso_frame_desc[td->iso_cnt].actual_length = size;
+ urb->iso_frame_desc[td->iso_cnt].status = 0;
+ td->iso_cnt++;
+ }
+
+ /* check transfer finish */
+ if (check_transfer_finish(td, urb)) {
+ disable_irq_ready(r8a66597, pipenum);
+ enable_irq_empty(r8a66597, pipenum);
+ if (!usb_pipeisoc(urb->pipe))
+ enable_irq_nrdy(r8a66597, pipenum);
+ } else
+ pipe_irq_enable(r8a66597, urb, pipenum);
+}
+
+
+static void check_next_phase(struct r8a66597 *r8a66597)
+{
+ struct r8a66597_td *td = r8a66597_get_td(r8a66597, 0);
+ struct urb *urb;
+ u8 finish = 0;
+
+ if (unlikely(!td))
+ return;
+ urb = td->urb;
+
+ switch (td->type) {
+ case USB_PID_IN:
+ case USB_PID_OUT:
+ if (urb->status != -EINPROGRESS) {
+ finish = 1;
+ break;
+ }
+ if (check_transfer_finish(td, urb))
+ td->type = USB_PID_ACK;
+ break;
+ case USB_PID_SETUP:
+ if (urb->status != -EINPROGRESS)
+ finish = 1;
+ else if (urb->transfer_buffer_length == urb->actual_length) {
+ td->type = USB_PID_ACK;
+ urb->status = 0;
+ } else if (usb_pipeout(urb->pipe))
+ td->type = USB_PID_OUT;
+ else
+ td->type = USB_PID_IN;
+ break;
+ case USB_PID_ACK:
+ finish = 1;
+ if (urb->status == -EINPROGRESS)
+ urb->status = 0;
+ break;
+ }
+
+ if (finish)
+ finish_request(r8a66597, td, 0, urb);
+ else
+ start_transfer(r8a66597, td);
+}
+
+static void set_urb_error(struct r8a66597 *r8a66597, u16 pipenum)
+{
+ struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum);
+
+ if (td && td->urb) {
+ u16 pid = r8a66597_read(r8a66597, td->pipe->pipectr) & PID;
+
+ if (pid == PID_NAK)
+ td->urb->status = -ECONNRESET;
+ else
+ td->urb->status = -EPIPE;
+ }
+}
+
+static void irq_pipe_ready(struct r8a66597 *r8a66597)
+{
+ u16 check;
+ u16 pipenum;
+ u16 mask;
+ struct r8a66597_td *td;
+
+ mask = r8a66597_read(r8a66597, BRDYSTS)
+ & r8a66597_read(r8a66597, BRDYENB);
+ r8a66597_write(r8a66597, (u16)~mask, BRDYSTS);
+ if (mask & BRDY0) {
+ td = r8a66597_get_td(r8a66597, 0);
+ if (td && td->type == USB_PID_IN)
+ packet_read(r8a66597, 0);
+ else
+ pipe_irq_disable(r8a66597, 0);
+ check_next_phase(r8a66597);
+ }
+
+ for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+ check = 1 << pipenum;
+ if (mask & check) {
+ td = r8a66597_get_td(r8a66597, pipenum);
+ if (unlikely(!td))
+ continue;
+
+ if (td->type == USB_PID_IN)
+ packet_read(r8a66597, pipenum);
+ else if (td->type == USB_PID_OUT)
+ packet_write(r8a66597, pipenum);
+ }
+ }
+}
+
+static void irq_pipe_empty(struct r8a66597 *r8a66597)
+{
+ u16 tmp;
+ u16 check;
+ u16 pipenum;
+ u16 mask;
+ struct r8a66597_td *td;
+
+ mask = r8a66597_read(r8a66597, BEMPSTS)
+ & r8a66597_read(r8a66597, BEMPENB);
+ r8a66597_write(r8a66597, (u16)~mask, BEMPSTS);
+ if (mask & BEMP0) {
+ cfifo_change(r8a66597, 0);
+ td = r8a66597_get_td(r8a66597, 0);
+ if (td && td->type != USB_PID_OUT)
+ disable_irq_empty(r8a66597, 0);
+ check_next_phase(r8a66597);
+ }
+
+ for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+ check = 1 << pipenum;
+ if (mask & check) {
+ struct r8a66597_td *td;
+ td = r8a66597_get_td(r8a66597, pipenum);
+ if (unlikely(!td))
+ continue;
+
+ tmp = r8a66597_read(r8a66597, td->pipe->pipectr);
+ if ((tmp & INBUFM) == 0) {
+ disable_irq_empty(r8a66597, pipenum);
+ pipe_irq_disable(r8a66597, pipenum);
+ if (td->urb->status == -EINPROGRESS)
+ td->urb->status = 0;
+ finish_request(r8a66597, td, pipenum, td->urb);
+ }
+ }
+ }
+}
+
+static void irq_pipe_nrdy(struct r8a66597 *r8a66597)
+{
+ u16 check;
+ u16 pipenum;
+ u16 mask;
+
+ mask = r8a66597_read(r8a66597, NRDYSTS)
+ & r8a66597_read(r8a66597, NRDYENB);
+ r8a66597_write(r8a66597, (u16)~mask, NRDYSTS);
+ if (mask & NRDY0) {
+ cfifo_change(r8a66597, 0);
+ set_urb_error(r8a66597, 0);
+ pipe_irq_disable(r8a66597, 0);
+ check_next_phase(r8a66597);
+ }
+
+ for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+ check = 1 << pipenum;
+ if (mask & check) {
+ struct r8a66597_td *td;
+ td = r8a66597_get_td(r8a66597, pipenum);
+ if (unlikely(!td))
+ continue;
+
+ set_urb_error(r8a66597, pipenum);
+ pipe_irq_disable(r8a66597, pipenum);
+ pipe_stop(r8a66597, td->pipe);
+ finish_request(r8a66597, td, pipenum, td->urb);
+ }
+ }
+}
+
+static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port)
+{
+ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+ rh->old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+ rh->scount = R8A66597_MAX_SAMPLING;
+ mod_timer(&r8a66597->rh_timer, jiffies + msecs_to_jiffies(50));
+}
+
+static irqreturn_t r8a66597_irq(struct usb_hcd *hcd)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ u16 intsts0, intsts1, intsts2;
+ u16 intenb0, intenb1, intenb2;
+ u16 mask0, mask1, mask2;
+
+ spin_lock(&r8a66597->lock);
+
+ intsts0 = r8a66597_read(r8a66597, INTSTS0);
+ intsts1 = r8a66597_read(r8a66597, INTSTS1);
+ intsts2 = r8a66597_read(r8a66597, INTSTS2);
+ intenb0 = r8a66597_read(r8a66597, INTENB0);
+ intenb1 = r8a66597_read(r8a66597, INTENB1);
+ intenb2 = r8a66597_read(r8a66597, INTENB2);
+
+ mask2 = intsts2 & intenb2;
+ mask1 = intsts1 & intenb1;
+ mask0 = intsts0 & intenb0 & (BEMP | NRDY | BRDY);
+ if (mask2) {
+ if (mask2 & ATTCH) {
+ r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS2);
+ r8a66597_bclr(r8a66597, ATTCHE, INTENB2);
+
+ /* start usb bus sampling */
+ start_root_hub_sampling(r8a66597, 1);
+ }
+ if (mask2 & DTCH) {
+ r8a66597_write(r8a66597, (u16)~DTCH, INTSTS2);
+ r8a66597_bclr(r8a66597, DTCHE, INTENB2);
+ r8a66597_usb_disconnect(r8a66597, 1);
+ }
+ }
+
+ if (mask1) {
+ if (mask1 & ATTCH) {
+ r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS1);
+ r8a66597_bclr(r8a66597, ATTCHE, INTENB1);
+
+ /* start usb bus sampling */
+ start_root_hub_sampling(r8a66597, 0);
+ }
+ if (mask1 & DTCH) {
+ r8a66597_write(r8a66597, (u16)~DTCH, INTSTS1);
+ r8a66597_bclr(r8a66597, DTCHE, INTENB1);
+ r8a66597_usb_disconnect(r8a66597, 0);
+ }
+ if (mask1 & SIGN) {
+ r8a66597_write(r8a66597, (u16)~SIGN, INTSTS1);
+ set_urb_error(r8a66597, 0);
+ check_next_phase(r8a66597);
+ }
+ if (mask1 & SACK) {
+ r8a66597_write(r8a66597, (u16)~SACK, INTSTS1);
+ check_next_phase(r8a66597);
+ }
+ }
+ if (mask0) {
+ if (mask0 & BRDY)
+ irq_pipe_ready(r8a66597);
+ if (mask0 & BEMP)
+ irq_pipe_empty(r8a66597);
+ if (mask0 & NRDY)
+ irq_pipe_nrdy(r8a66597);
+ }
+
+ spin_unlock(&r8a66597->lock);
+ return IRQ_HANDLED;
+}
+
+/* this function must be called with interrupt disabled */
+static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port)
+{
+ u16 tmp;
+ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+
+ if (rh->port & (1 << USB_PORT_FEAT_RESET)) {
+ unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+ tmp = r8a66597_read(r8a66597, dvstctr_reg);
+ if ((tmp & USBRST) == USBRST) {
+ r8a66597_mdfy(r8a66597, UACT, USBRST | UACT,
+ dvstctr_reg);
+ mod_timer(&r8a66597->rh_timer,
+ jiffies + msecs_to_jiffies(50));
+ } else
+ r8a66597_usb_connect(r8a66597, port);
+ }
+
+ if (rh->scount > 0) {
+ tmp = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST;
+ if (tmp == rh->old_syssts) {
+ rh->scount--;
+ if (rh->scount == 0) {
+ if (tmp == FS_JSTS) {
+ r8a66597_bset(r8a66597, HSE,
+ get_syscfg_reg(port));
+ r8a66597_usb_preconnect(r8a66597, port);
+ } else if (tmp == LS_JSTS) {
+ r8a66597_bclr(r8a66597, HSE,
+ get_syscfg_reg(port));
+ r8a66597_usb_preconnect(r8a66597, port);
+ } else if (tmp == SE0)
+ r8a66597_bset(r8a66597, ATTCHE,
+ get_intenb_reg(port));
+ } else {
+ mod_timer(&r8a66597->rh_timer,
+ jiffies + msecs_to_jiffies(50));
+ }
+ } else {
+ rh->scount = R8A66597_MAX_SAMPLING;
+ rh->old_syssts = tmp;
+ mod_timer(&r8a66597->rh_timer,
+ jiffies + msecs_to_jiffies(50));
+ }
+ }
+}
+
+static void r8a66597_td_timer(unsigned long _r8a66597)
+{
+ struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+ unsigned long flags;
+ u16 pipenum;
+ struct r8a66597_td *td, *new_td = NULL;
+ struct r8a66597_pipe *pipe;
+
+ spin_lock_irqsave(&r8a66597->lock, flags);
+ for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) {
+ if (!(r8a66597->timeout_map & (1 << pipenum)))
+ continue;
+ if (timer_pending(&r8a66597->td_timer[pipenum]))
+ continue;
+
+ td = r8a66597_get_td(r8a66597, pipenum);
+ if (!td) {
+ r8a66597->timeout_map &= ~(1 << pipenum);
+ continue;
+ }
+
+ if (td->urb->actual_length) {
+ set_td_timer(r8a66597, td);
+ break;
+ }
+
+ pipe = td->pipe;
+ pipe_stop(r8a66597, pipe);
+
+ new_td = td;
+ do {
+ list_move_tail(&new_td->queue,
+ &r8a66597->pipe_queue[pipenum]);
+ new_td = r8a66597_get_td(r8a66597, pipenum);
+ if (!new_td) {
+ new_td = td;
+ break;
+ }
+ } while (td != new_td && td->address == new_td->address);
+
+ start_transfer(r8a66597, new_td);
+
+ if (td == new_td)
+ r8a66597->timeout_map &= ~(1 << pipenum);
+ else
+ set_td_timer(r8a66597, new_td);
+ break;
+ }
+ spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static void r8a66597_timer(unsigned long _r8a66597)
+{
+ struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597;
+ unsigned long flags;
+
+ spin_lock_irqsave(&r8a66597->lock, flags);
+
+ r8a66597_root_hub_control(r8a66597, 0);
+ r8a66597_root_hub_control(r8a66597, 1);
+
+ spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static int check_pipe_config(struct r8a66597 *r8a66597, struct urb *urb)
+{
+ struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb);
+
+ if (dev && dev->address && dev->state != USB_STATE_CONFIGURED &&
+ (urb->dev->state == USB_STATE_CONFIGURED))
+ return 1;
+ else
+ return 0;
+}
+
+static int r8a66597_start(struct usb_hcd *hcd)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ int ret;
+
+ hcd->state = HC_STATE_RUNNING;
+ if ((ret = enable_controller(r8a66597)) < 0)
+ return ret;
+
+ return 0;
+}
+
+static void r8a66597_stop(struct usb_hcd *hcd)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+
+ disable_controller(r8a66597);
+}
+
+static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb)
+{
+ unsigned int usb_address = usb_pipedevice(urb->pipe);
+ u16 root_port, hub_port;
+
+ if (usb_address == 0) {
+ get_port_number(urb->dev->devpath,
+ &root_port, &hub_port);
+ set_devadd_reg(r8a66597, 0,
+ get_r8a66597_usb_speed(urb->dev->speed),
+ get_parent_r8a66597_address(r8a66597, urb->dev),
+ hub_port, root_port);
+ }
+}
+
+static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597,
+ struct urb *urb,
+ struct usb_host_endpoint *hep,
+ gfp_t mem_flags)
+{
+ struct r8a66597_td *td;
+ u16 pipenum;
+
+ td = kzalloc(sizeof(struct r8a66597_td), mem_flags);
+ if (td == NULL)
+ return NULL;
+
+ pipenum = r8a66597_get_pipenum(urb, hep);
+ td->pipenum = pipenum;
+ td->pipe = hep->hcpriv;
+ td->urb = urb;
+ td->address = get_urb_to_r8a66597_addr(r8a66597, urb);
+ td->maxpacket = usb_maxpacket(urb->dev, urb->pipe,
+ !usb_pipein(urb->pipe));
+ if (usb_pipecontrol(urb->pipe))
+ td->type = USB_PID_SETUP;
+ else if (usb_pipein(urb->pipe))
+ td->type = USB_PID_IN;
+ else
+ td->type = USB_PID_OUT;
+ INIT_LIST_HEAD(&td->queue);
+
+ return td;
+}
+
+static int r8a66597_urb_enqueue(struct usb_hcd *hcd,
+ struct usb_host_endpoint *hep,
+ struct urb *urb,
+ gfp_t mem_flags)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ struct r8a66597_td *td = NULL;
+ int ret = 0, request = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&r8a66597->lock, flags);
+ if (!get_urb_to_r8a66597_dev(r8a66597, urb)) {
+ ret = -ENODEV;
+ goto error;
+ }
+
+ if (!hep->hcpriv) {
+ hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), mem_flags);
+ if (!hep->hcpriv) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ set_pipe_reg_addr(hep->hcpriv, R8A66597_PIPE_NO_DMA);
+ if (usb_pipeendpoint(urb->pipe))
+ init_pipe_info(r8a66597, urb, hep, &hep->desc);
+ }
+
+ if (unlikely(check_pipe_config(r8a66597, urb)))
+ init_pipe_config(r8a66597, urb);
+
+ set_address_zero(r8a66597, urb);
+ td = r8a66597_make_td(r8a66597, urb, hep, mem_flags);
+ if (td == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ if (list_empty(&r8a66597->pipe_queue[td->pipenum]))
+ request = 1;
+ list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]);
+
+ spin_lock(&urb->lock);
+ if (urb->status != -EINPROGRESS) {
+ spin_unlock(&urb->lock);
+ ret = -EPIPE;
+ goto error;
+ }
+ urb->hcpriv = td;
+ spin_unlock(&urb->lock);
+
+ if (request) {
+ ret = start_transfer(r8a66597, td);
+ if (ret < 0) {
+ list_del(&td->queue);
+ kfree(td);
+ }
+ } else
+ set_td_timer(r8a66597, td);
+
+error:
+ spin_unlock_irqrestore(&r8a66597->lock, flags);
+ return ret;
+}
+
+static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ struct r8a66597_td *td;
+ unsigned long flags;
+
+ spin_lock_irqsave(&r8a66597->lock, flags);
+ if (urb->hcpriv) {
+ td = urb->hcpriv;
+ pipe_stop(r8a66597, td->pipe);
+ pipe_irq_disable(r8a66597, td->pipenum);
+ disable_irq_empty(r8a66597, td->pipenum);
+ done(r8a66597, td, td->pipenum, urb);
+ }
+ spin_unlock_irqrestore(&r8a66597->lock, flags);
+ return 0;
+}
+
+static void r8a66597_endpoint_disable(struct usb_hcd *hcd,
+ struct usb_host_endpoint *hep)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ struct r8a66597_pipe *pipe = (struct r8a66597_pipe *)hep->hcpriv;
+ struct r8a66597_td *td;
+ struct urb *urb = NULL;
+ u16 pipenum;
+ unsigned long flags;
+
+ if (pipe == NULL)
+ return;
+ pipenum = pipe->info.pipenum;
+
+ if (pipenum == 0) {
+ kfree(hep->hcpriv);
+ hep->hcpriv = NULL;
+ return;
+ }
+
+ spin_lock_irqsave(&r8a66597->lock, flags);
+ pipe_stop(r8a66597, pipe);
+ pipe_irq_disable(r8a66597, pipenum);
+ disable_irq_empty(r8a66597, pipenum);
+ td = r8a66597_get_td(r8a66597, pipenum);
+ if (td)
+ urb = td->urb;
+ done(r8a66597, td, pipenum, urb);
+ kfree(hep->hcpriv);
+ hep->hcpriv = NULL;
+ spin_unlock_irqrestore(&r8a66597->lock, flags);
+}
+
+static int r8a66597_get_frame(struct usb_hcd *hcd)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ return r8a66597_read(r8a66597, FRMNUM) & 0x03FF;
+}
+
+static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
+{
+ int chix;
+
+ if (udev->state == USB_STATE_CONFIGURED &&
+ udev->parent && udev->parent->devnum > 1 &&
+ udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
+ map[udev->devnum/32] |= (1 << (udev->devnum % 32));
+
+ for (chix = 0; chix < udev->maxchild; chix++) {
+ struct usb_device *childdev = udev->children[chix];
+
+ if (childdev)
+ collect_usb_address_map(childdev, map);
+ }
+}
+
+/* this function must be called with interrupt disabled */
+static struct r8a66597_device *get_r8a66597_device(struct r8a66597 *r8a66597,
+ int addr)
+{
+ struct r8a66597_device *dev;
+ struct list_head *list = &r8a66597->child_device;
+
+ list_for_each_entry(dev, list, device_list) {
+ if (!dev)
+ continue;
+ if (dev->usb_address != addr)
+ continue;
+
+ return dev;
+ }
+
+ err("get_r8a66597_device fail.(%d)\n", addr);
+ return NULL;
+}
+
+static void update_usb_address_map(struct r8a66597 *r8a66597,
+ struct usb_device *root_hub,
+ unsigned long *map)
+{
+ int i, j, addr;
+ unsigned long diff;
+ unsigned long flags;
+
+ for (i = 0; i < 4; i++) {
+ diff = r8a66597->child_connect_map[i] ^ map[i];
+ if (!diff)
+ continue;
+
+ for (j = 0; j < 32; j++) {
+ if (!(diff & (1 << j)))
+ continue;
+
+ addr = i * 32 + j;
+ if (map[i] & (1 << j))
+ set_child_connect_map(r8a66597, addr);
+ else {
+ struct r8a66597_device *dev;
+
+ spin_lock_irqsave(&r8a66597->lock, flags);
+ dev = get_r8a66597_device(r8a66597, addr);
+ disable_r8a66597_pipe_all(r8a66597, dev);
+ free_usb_address(r8a66597, dev);
+ put_child_connect_map(r8a66597, addr);
+ spin_unlock_irqrestore(&r8a66597->lock, flags);
+ }
+ }
+ }
+}
+
+static void r8a66597_check_detect_child(struct r8a66597 *r8a66597,
+ struct usb_hcd *hcd)
+{
+ struct usb_bus *bus;
+ unsigned long now_map[4];
+
+ memset(now_map, 0, sizeof(now_map));
+
+ list_for_each_entry(bus, &usb_bus_list, bus_list) {
+ if (!bus->root_hub)
+ continue;
+
+ if (bus->busnum != hcd->self.busnum)
+ continue;
+
+ collect_usb_address_map(bus->root_hub, now_map);
+ update_usb_address_map(r8a66597, bus->root_hub, now_map);
+ }
+}
+
+static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ unsigned long flags;
+ int i;
+
+ r8a66597_check_detect_child(r8a66597, hcd);
+
+ spin_lock_irqsave(&r8a66597->lock, flags);
+
+ *buf = 0; /* initialize (no change) */
+
+ for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) {
+ if (r8a66597->root_hub[i].port & 0xffff0000)
+ *buf |= 1 << (i + 1);
+ }
+
+ spin_unlock_irqrestore(&r8a66597->lock, flags);
+
+ return (*buf != 0);
+}
+
+static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
+ struct usb_hub_descriptor *desc)
+{
+ desc->bDescriptorType = 0x29;
+ desc->bHubContrCurrent = 0;
+ desc->bNbrPorts = R8A66597_MAX_ROOT_HUB;
+ desc->bDescLength = 9;
+ desc->bPwrOn2PwrGood = 0;
+ desc->wHubCharacteristics = cpu_to_le16(0x0011);
+ desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1;
+ desc->bitmap[1] = ~0;
+}
+
+static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+ u16 wIndex, char *buf, u16 wLength)
+{
+ struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd);
+ int ret;
+ int port = (wIndex & 0x00FF) - 1;
+ struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+ unsigned long flags;
+
+ ret = 0;
+
+ spin_lock_irqsave(&r8a66597->lock, flags);
+ switch (typeReq) {
+ case ClearHubFeature:
+ case SetHubFeature:
+ switch (wValue) {
+ case C_HUB_OVER_CURRENT:
+ case C_HUB_LOCAL_POWER:
+ break;
+ default:
+ goto error;
+ }
+ break;
+ case ClearPortFeature:
+ if (wIndex > R8A66597_MAX_ROOT_HUB)
+ goto error;
+ if (wLength != 0)
+ goto error;
+
+ switch (wValue) {
+ case USB_PORT_FEAT_ENABLE:
+ rh->port &= (1 << USB_PORT_FEAT_POWER);
+ break;
+ case USB_PORT_FEAT_SUSPEND:
+ break;
+ case USB_PORT_FEAT_POWER:
+ r8a66597_port_power(r8a66597, port, 0);
+ break;
+ case USB_PORT_FEAT_C_ENABLE:
+ case USB_PORT_FEAT_C_SUSPEND:
+ case USB_PORT_FEAT_C_CONNECTION:
+ case USB_PORT_FEAT_C_OVER_CURRENT:
+ case USB_PORT_FEAT_C_RESET:
+ break;
+ default:
+ goto error;
+ }
+ rh->port &= ~(1 << wValue);
+ break;
+ case GetHubDescriptor:
+ r8a66597_hub_descriptor(r8a66597,
+ (struct usb_hub_descriptor *)buf);
+ break;
+ case GetHubStatus:
+ *buf = 0x00;
+ break;
+ case GetPortStatus:
+ if (wIndex > R8A66597_MAX_ROOT_HUB)
+ goto error;
+ *(u32 *)buf = rh->port;
+ break;
+ case SetPortFeature:
+ if (wIndex > R8A66597_MAX_ROOT_HUB)
+ goto error;
+ if (wLength != 0)
+ goto error;
+
+ switch (wValue) {
+ case USB_PORT_FEAT_SUSPEND:
+ break;
+ case USB_PORT_FEAT_POWER:
+ r8a66597_port_power(r8a66597, port, 1);
+ rh->port |= (1 << USB_PORT_FEAT_POWER);
+ break;
+ case USB_PORT_FEAT_RESET: {
+ struct r8a66597_device *dev = rh->dev;
+
+ rh->port |= (1 << USB_PORT_FEAT_RESET);
+
+ disable_r8a66597_pipe_all(r8a66597, dev);
+ free_usb_address(r8a66597, dev);
+
+ r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,
+ get_dvstctr_reg(port));
+ mod_timer(&r8a66597->rh_timer,
+ jiffies + msecs_to_jiffies(50));
+ }
+ break;
+ default:
+ goto error;
+ }
+ rh->port |= 1 << wValue;
+ break;
+ default:
+error:
+ ret = -EPIPE;
+ break;
+ }
+
+ spin_unlock_irqrestore(&r8a66597->lock, flags);
+ return ret;
+}
+
+static struct hc_driver r8a66597_hc_driver = {
+ .description = hcd_name,
+ .hcd_priv_size = sizeof(struct r8a66597),
+ .irq = r8a66597_irq,
+
+ /*
+ * generic hardware linkage
+ */
+ .flags = HCD_USB2,
+
+ .start = r8a66597_start,
+ .stop = r8a66597_stop,
+
+ /*
+ * managing i/o requests and associated device resources
+ */
+ .urb_enqueue = r8a66597_urb_enqueue,
+ .urb_dequeue = r8a66597_urb_dequeue,
+ .endpoint_disable = r8a66597_endpoint_disable,
+
+ /*
+ * periodic schedule support
+ */
+ .get_frame_number = r8a66597_get_frame,
+
+ /*
+ * root hub support
+ */
+ .hub_status_data = r8a66597_hub_status_data,
+ .hub_control = r8a66597_hub_control,
+};
+
+#if defined(CONFIG_PM)
+static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ pdev->dev.power.power_state = state;
+ return 0;
+}
+
+static int r8a66597_resume(struct platform_device *pdev)
+{
+ pdev->dev.power.power_state = PMSG_ON;
+ return 0;
+}
+#else /* if defined(CONFIG_PM) */
+#define r8a66597_suspend NULL
+#define r8a66597_resume NULL
+#endif
+
+static int __init_or_module r8a66597_remove(struct platform_device *pdev)
+{
+ struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev);
+ struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597);
+
+ del_timer_sync(&r8a66597->rh_timer);
+ iounmap((void *)r8a66597->reg);
+ usb_remove_hcd(hcd);
+ usb_put_hcd(hcd);
+ return 0;
+}
+
+#define resource_len(r) (((r)->end - (r)->start) + 1)
+static int __init r8a66597_probe(struct platform_device *pdev)
+{
+ struct resource *res = NULL;
+ int irq = -1;
+ void __iomem *reg = NULL;
+ struct usb_hcd *hcd = NULL;
+ struct r8a66597 *r8a66597;
+ int ret = 0;
+ int i;
+
+ if (pdev->dev.dma_mask) {
+ ret = -EINVAL;
+ err("dma not support");
+ goto clean_up;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ (char *)hcd_name);
+ if (!res) {
+ ret = -ENODEV;
+ err("platform_get_resource_byname error.");
+ goto clean_up;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = -ENODEV;
+ err("platform_get_irq error.");
+ goto clean_up;
+ }
+
+ reg = ioremap(res->start, resource_len(res));
+ if (reg == NULL) {
+ ret = -ENOMEM;
+ err("ioremap error.");
+ goto clean_up;
+ }
+
+ /* initialize hcd */
+ hcd = usb_create_hcd(&r8a66597_hc_driver, &pdev->dev, (char *)hcd_name);
+ if (!hcd) {
+ ret = -ENOMEM;
+ err("Failed to create hcd");
+ goto clean_up;
+ }
+ r8a66597 = hcd_to_r8a66597(hcd);
+ memset(r8a66597, 0, sizeof(struct r8a66597));
+ dev_set_drvdata(&pdev->dev, r8a66597);
+
+ spin_lock_init(&r8a66597->lock);
+ init_timer(&r8a66597->rh_timer);
+ r8a66597->rh_timer.function = r8a66597_timer;
+ r8a66597->rh_timer.data = (unsigned long)r8a66597;
+ r8a66597->reg = (unsigned long)reg;
+
+ for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) {
+ INIT_LIST_HEAD(&r8a66597->pipe_queue[i]);
+ init_timer(&r8a66597->td_timer[i]);
+ r8a66597->td_timer[i].function = r8a66597_td_timer;
+ r8a66597->td_timer[i].data = (unsigned long)r8a66597;
+ }
+ INIT_LIST_HEAD(&r8a66597->child_device);
+
+ hcd->rsrc_start = res->start;
+ ret = usb_add_hcd(hcd, irq, 0);
+ if (ret != 0) {
+ err("Failed to add hcd");
+ goto clean_up;
+ }
+
+ return 0;
+
+clean_up:
+ if (reg)
+ iounmap(reg);
+ if (res)
+ release_mem_region(res->start, 1);
+
+ return ret;
+}
+
+static struct platform_driver r8a66597_driver = {
+ .probe = r8a66597_probe,
+ .remove = r8a66597_remove,
+ .suspend = r8a66597_suspend,
+ .resume = r8a66597_resume,
+ .driver = {
+ .name = (char *) hcd_name,
+ },
+};
+
+static int __init r8a66597_init(void)
+{
+ if (usb_disabled())
+ return -ENODEV;
+
+ info("driver %s, %s", hcd_name, DRIVER_VERSION);
+ return platform_driver_register(&r8a66597_driver);
+}
+module_init(r8a66597_init);
+
+static void __exit r8a66597_cleanup(void)
+{
+ platform_driver_unregister(&r8a66597_driver);
+}
+module_exit(r8a66597_cleanup);
+
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h
new file mode 100644
index 00000000000..97c2a71ac7a
--- /dev/null
+++ b/drivers/usb/host/r8a66597.h
@@ -0,0 +1,634 @@
+/*
+ * R8A66597 HCD (Host Controller Driver)
+ *
+ * Copyright (C) 2006-2007 Renesas Solutions Corp.
+ * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
+ * Portions Copyright (C) 2004-2005 David Brownell
+ * Portions Copyright (C) 1999 Roman Weissgaerber
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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 __R8A66597_H__
+#define __R8A66597_H__
+
+#define SYSCFG0 0x00
+#define SYSCFG1 0x02
+#define SYSSTS0 0x04
+#define SYSSTS1 0x06
+#define DVSTCTR0 0x08
+#define DVSTCTR1 0x0A
+#define TESTMODE 0x0C
+#define PINCFG 0x0E
+#define DMA0CFG 0x10
+#define DMA1CFG 0x12
+#define CFIFO 0x14
+#define D0FIFO 0x18
+#define D1FIFO 0x1C
+#define CFIFOSEL 0x20
+#define CFIFOCTR 0x22
+#define CFIFOSIE 0x24
+#define D0FIFOSEL 0x28
+#define D0FIFOCTR 0x2A
+#define D1FIFOSEL 0x2C
+#define D1FIFOCTR 0x2E
+#define INTENB0 0x30
+#define INTENB1 0x32
+#define INTENB2 0x34
+#define BRDYENB 0x36
+#define NRDYENB 0x38
+#define BEMPENB 0x3A
+#define SOFCFG 0x3C
+#define INTSTS0 0x40
+#define INTSTS1 0x42
+#define INTSTS2 0x44
+#define BRDYSTS 0x46
+#define NRDYSTS 0x48
+#define BEMPSTS 0x4A
+#define FRMNUM 0x4C
+#define UFRMNUM 0x4E
+#define USBADDR 0x50
+#define USBREQ 0x54
+#define USBVAL 0x56
+#define USBINDX 0x58
+#define USBLENG 0x5A
+#define DCPCFG 0x5C
+#define DCPMAXP 0x5E
+#define DCPCTR 0x60
+#define PIPESEL 0x64
+#define PIPECFG 0x68
+#define PIPEBUF 0x6A
+#define PIPEMAXP 0x6C
+#define PIPEPERI 0x6E
+#define PIPE1CTR 0x70
+#define PIPE2CTR 0x72
+#define PIPE3CTR 0x74
+#define PIPE4CTR 0x76
+#define PIPE5CTR 0x78
+#define PIPE6CTR 0x7A
+#define PIPE7CTR 0x7C
+#define PIPE8CTR 0x7E
+#define PIPE9CTR 0x80
+#define PIPE1TRE 0x90
+#define PIPE1TRN 0x92
+#define PIPE2TRE 0x94
+#define PIPE2TRN 0x96
+#define PIPE3TRE 0x98
+#define PIPE3TRN 0x9A
+#define PIPE4TRE 0x9C
+#define PIPE4TRN 0x9E
+#define PIPE5TRE 0xA0
+#define PIPE5TRN 0xA2
+#define DEVADD0 0xD0
+#define DEVADD1 0xD2
+#define DEVADD2 0xD4
+#define DEVADD3 0xD6
+#define DEVADD4 0xD8
+#define DEVADD5 0xDA
+#define DEVADD6 0xDC
+#define DEVADD7 0xDE
+#define DEVADD8 0xE0
+#define DEVADD9 0xE2
+#define DEVADDA 0xE4
+
+/* System Configuration Control Register */
+#define XTAL 0xC000 /* b15-14: Crystal selection */
+#define XTAL48 0x8000 /* 48MHz */
+#define XTAL24 0x4000 /* 24MHz */
+#define XTAL12 0x0000 /* 12MHz */
+#define XCKE 0x2000 /* b13: External clock enable */
+#define PLLC 0x0800 /* b11: PLL control */
+#define SCKE 0x0400 /* b10: USB clock enable */
+#define PCSDIS 0x0200 /* b9: not CS wakeup */
+#define LPSME 0x0100 /* b8: Low power sleep mode */
+#define HSE 0x0080 /* b7: Hi-speed enable */
+#define DCFM 0x0040 /* b6: Controller function select */
+#define DRPD 0x0020 /* b5: D+/- pull down control */
+#define DPRPU 0x0010 /* b4: D+ pull up control */
+#define USBE 0x0001 /* b0: USB module operation enable */
+
+/* System Configuration Status Register */
+#define OVCBIT 0x8000 /* b15-14: Over-current bit */
+#define OVCMON 0xC000 /* b15-14: Over-current monitor */
+#define SOFEA 0x0020 /* b5: SOF monitor */
+#define IDMON 0x0004 /* b3: ID-pin monitor */
+#define LNST 0x0003 /* b1-0: D+, D- line status */
+#define SE1 0x0003 /* SE1 */
+#define FS_KSTS 0x0002 /* Full-Speed K State */
+#define FS_JSTS 0x0001 /* Full-Speed J State */
+#define LS_JSTS 0x0002 /* Low-Speed J State */
+#define LS_KSTS 0x0001 /* Low-Speed K State */
+#define SE0 0x0000 /* SE0 */
+
+/* Device State Control Register */
+#define EXTLP0 0x0400 /* b10: External port */
+#define VBOUT 0x0200 /* b9: VBUS output */
+#define WKUP 0x0100 /* b8: Remote wakeup */
+#define RWUPE 0x0080 /* b7: Remote wakeup sense */
+#define USBRST 0x0040 /* b6: USB reset enable */
+#define RESUME 0x0020 /* b5: Resume enable */
+#define UACT 0x0010 /* b4: USB bus enable */
+#define RHST 0x0007 /* b1-0: Reset handshake status */
+#define HSPROC 0x0004 /* HS handshake is processing */
+#define HSMODE 0x0003 /* Hi-Speed mode */
+#define FSMODE 0x0002 /* Full-Speed mode */
+#define LSMODE 0x0001 /* Low-Speed mode */
+#define UNDECID 0x0000 /* Undecided */
+
+/* Test Mode Register */
+#define UTST 0x000F /* b3-0: Test select */
+#define H_TST_PACKET 0x000C /* HOST TEST Packet */
+#define H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */
+#define H_TST_K 0x000A /* HOST TEST K */
+#define H_TST_J 0x0009 /* HOST TEST J */
+#define H_TST_NORMAL 0x0000 /* HOST Normal Mode */
+#define P_TST_PACKET 0x0004 /* PERI TEST Packet */
+#define P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */
+#define P_TST_K 0x0002 /* PERI TEST K */
+#define P_TST_J 0x0001 /* PERI TEST J */
+#define P_TST_NORMAL 0x0000 /* PERI Normal Mode */
+
+/* Data Pin Configuration Register */
+#define LDRV 0x8000 /* b15: Drive Current Adjust */
+#define VIF1 0x0000 /* VIF = 1.8V */
+#define VIF3 0x8000 /* VIF = 3.3V */
+#define INTA 0x0001 /* b1: USB INT-pin active */
+
+/* DMAx Pin Configuration Register */
+#define DREQA 0x4000 /* b14: Dreq active select */
+#define BURST 0x2000 /* b13: Burst mode */
+#define DACKA 0x0400 /* b10: Dack active select */
+#define DFORM 0x0380 /* b9-7: DMA mode select */
+#define CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */
+#define CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */
+#define CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */
+#define SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */
+#define DENDA 0x0040 /* b6: Dend active select */
+#define PKTM 0x0020 /* b5: Packet mode */
+#define DENDE 0x0010 /* b4: Dend enable */
+#define OBUS 0x0004 /* b2: OUTbus mode */
+
+/* CFIFO/DxFIFO Port Select Register */
+#define RCNT 0x8000 /* b15: Read count mode */
+#define REW 0x4000 /* b14: Buffer rewind */
+#define DCLRM 0x2000 /* b13: DMA buffer clear mode */
+#define DREQE 0x1000 /* b12: DREQ output enable */
+#define MBW 0x0400 /* b10: Maximum bit width for FIFO access */
+#define MBW_8 0x0000 /* 8bit */
+#define MBW_16 0x0400 /* 16bit */
+#define BIGEND 0x0100 /* b8: Big endian mode */
+#define BYTE_LITTLE 0x0000 /* little dendian */
+#define BYTE_BIG 0x0100 /* big endifan */
+#define ISEL 0x0020 /* b5: DCP FIFO port direction select */
+#define CURPIPE 0x000F /* b2-0: PIPE select */
+
+/* CFIFO/DxFIFO Port Control Register */
+#define BVAL 0x8000 /* b15: Buffer valid flag */
+#define BCLR 0x4000 /* b14: Buffer clear */
+#define FRDY 0x2000 /* b13: FIFO ready */
+#define DTLN 0x0FFF /* b11-0: FIFO received data length */
+
+/* Interrupt Enable Register 0 */
+#define VBSE 0x8000 /* b15: VBUS interrupt */
+#define RSME 0x4000 /* b14: Resume interrupt */
+#define SOFE 0x2000 /* b13: Frame update interrupt */
+#define DVSE 0x1000 /* b12: Device state transition interrupt */
+#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */
+#define BEMPE 0x0400 /* b10: Buffer empty interrupt */
+#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */
+#define BRDYE 0x0100 /* b8: Buffer ready interrupt */
+
+/* Interrupt Enable Register 1 */
+#define OVRCRE 0x8000 /* b15: Over-current interrupt */
+#define BCHGE 0x4000 /* b14: USB us chenge interrupt */
+#define DTCHE 0x1000 /* b12: Detach sense interrupt */
+#define ATTCHE 0x0800 /* b11: Attach sense interrupt */
+#define EOFERRE 0x0040 /* b6: EOF error interrupt */
+#define SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */
+#define SACKE 0x0010 /* b4: SETUP ACK interrupt */
+
+/* BRDY Interrupt Enable/Status Register */
+#define BRDY9 0x0200 /* b9: PIPE9 */
+#define BRDY8 0x0100 /* b8: PIPE8 */
+#define BRDY7 0x0080 /* b7: PIPE7 */
+#define BRDY6 0x0040 /* b6: PIPE6 */
+#define BRDY5 0x0020 /* b5: PIPE5 */
+#define BRDY4 0x0010 /* b4: PIPE4 */
+#define BRDY3 0x0008 /* b3: PIPE3 */
+#define BRDY2 0x0004 /* b2: PIPE2 */
+#define BRDY1 0x0002 /* b1: PIPE1 */
+#define BRDY0 0x0001 /* b1: PIPE0 */
+
+/* NRDY Interrupt Enable/Status Register */
+#define NRDY9 0x0200 /* b9: PIPE9 */
+#define NRDY8 0x0100 /* b8: PIPE8 */
+#define NRDY7 0x0080 /* b7: PIPE7 */
+#define NRDY6 0x0040 /* b6: PIPE6 */
+#define NRDY5 0x0020 /* b5: PIPE5 */
+#define NRDY4 0x0010 /* b4: PIPE4 */
+#define NRDY3 0x0008 /* b3: PIPE3 */
+#define NRDY2 0x0004 /* b2: PIPE2 */
+#define NRDY1 0x0002 /* b1: PIPE1 */
+#define NRDY0 0x0001 /* b1: PIPE0 */
+
+/* BEMP Interrupt Enable/Status Register */
+#define BEMP9 0x0200 /* b9: PIPE9 */
+#define BEMP8 0x0100 /* b8: PIPE8 */
+#define BEMP7 0x0080 /* b7: PIPE7 */
+#define BEMP6 0x0040 /* b6: PIPE6 */
+#define BEMP5 0x0020 /* b5: PIPE5 */
+#define BEMP4 0x0010 /* b4: PIPE4 */
+#define BEMP3 0x0008 /* b3: PIPE3 */
+#define BEMP2 0x0004 /* b2: PIPE2 */
+#define BEMP1 0x0002 /* b1: PIPE1 */
+#define BEMP0 0x0001 /* b0: PIPE0 */
+
+/* SOF Pin Configuration Register */
+#define TRNENSEL 0x0100 /* b8: Select transaction enable period */
+#define BRDYM 0x0040 /* b6: BRDY clear timing */
+#define INTL 0x0020 /* b5: Interrupt sense select */
+#define EDGESTS 0x0010 /* b4: */
+#define SOFMODE 0x000C /* b3-2: SOF pin select */
+#define SOF_125US 0x0008 /* SOF OUT 125us Frame Signal */
+#define SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */
+#define SOF_DISABLE 0x0000 /* SOF OUT Disable */
+
+/* Interrupt Status Register 0 */
+#define VBINT 0x8000 /* b15: VBUS interrupt */
+#define RESM 0x4000 /* b14: Resume interrupt */
+#define SOFR 0x2000 /* b13: SOF frame update interrupt */
+#define DVST 0x1000 /* b12: Device state transition interrupt */
+#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */
+#define BEMP 0x0400 /* b10: Buffer empty interrupt */
+#define NRDY 0x0200 /* b9: Buffer not ready interrupt */
+#define BRDY 0x0100 /* b8: Buffer ready interrupt */
+#define VBSTS 0x0080 /* b7: VBUS input port */
+#define DVSQ 0x0070 /* b6-4: Device state */
+#define DS_SPD_CNFG 0x0070 /* Suspend Configured */
+#define DS_SPD_ADDR 0x0060 /* Suspend Address */
+#define DS_SPD_DFLT 0x0050 /* Suspend Default */
+#define DS_SPD_POWR 0x0040 /* Suspend Powered */
+#define DS_SUSP 0x0040 /* Suspend */
+#define DS_CNFG 0x0030 /* Configured */
+#define DS_ADDS 0x0020 /* Address */
+#define DS_DFLT 0x0010 /* Default */
+#define DS_POWR 0x0000 /* Powered */
+#define DVSQS 0x0030 /* b5-4: Device state */
+#define VALID 0x0008 /* b3: Setup packet detected flag */
+#define CTSQ 0x0007 /* b2-0: Control transfer stage */
+#define CS_SQER 0x0006 /* Sequence error */
+#define CS_WRND 0x0005 /* Control write nodata status stage */
+#define CS_WRSS 0x0004 /* Control write status stage */
+#define CS_WRDS 0x0003 /* Control write data stage */
+#define CS_RDSS 0x0002 /* Control read status stage */
+#define CS_RDDS 0x0001 /* Control read data stage */
+#define CS_IDST 0x0000 /* Idle or setup stage */
+
+/* Interrupt Status Register 1 */
+#define OVRCR 0x8000 /* b15: Over-current interrupt */
+#define BCHG 0x4000 /* b14: USB bus chenge interrupt */
+#define DTCH 0x1000 /* b12: Detach sense interrupt */
+#define ATTCH 0x0800 /* b11: Attach sense interrupt */
+#define EOFERR 0x0040 /* b6: EOF-error interrupt */
+#define SIGN 0x0020 /* b5: Setup ignore interrupt */
+#define SACK 0x0010 /* b4: Setup acknowledge interrupt */
+
+/* Frame Number Register */
+#define OVRN 0x8000 /* b15: Overrun error */
+#define CRCE 0x4000 /* b14: Received data error */
+#define FRNM 0x07FF /* b10-0: Frame number */
+
+/* Micro Frame Number Register */
+#define UFRNM 0x0007 /* b2-0: Micro frame number */
+
+/* USB Address / Low Power Status Recovery Register */
+//#define USBADDR 0x007F /* b6-0: USB address */
+
+/* Default Control Pipe Maxpacket Size Register */
+/* Pipe Maxpacket Size Register */
+#define DEVSEL 0xF000 /* b15-14: Device address select */
+#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */
+
+/* Default Control Pipe Control Register */
+#define BSTS 0x8000 /* b15: Buffer status */
+#define SUREQ 0x4000 /* b14: Send USB request */
+#define CSCLR 0x2000 /* b13: complete-split status clear */
+#define CSSTS 0x1000 /* b12: complete-split status */
+#define SUREQCLR 0x0800 /* b11: stop setup request */
+#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */
+#define SQSET 0x0080 /* b7: Sequence toggle bit set */
+#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */
+#define PBUSY 0x0020 /* b5: pipe busy */
+#define PINGE 0x0010 /* b4: ping enable */
+#define CCPL 0x0004 /* b2: Enable control transfer complete */
+#define PID 0x0003 /* b1-0: Response PID */
+#define PID_STALL11 0x0003 /* STALL */
+#define PID_STALL 0x0002 /* STALL */
+#define PID_BUF 0x0001 /* BUF */
+#define PID_NAK 0x0000 /* NAK */
+
+/* Pipe Window Select Register */
+#define PIPENM 0x0007 /* b2-0: Pipe select */
+
+/* Pipe Configuration Register */
+#define R8A66597_TYP 0xC000 /* b15-14: Transfer type */
+#define R8A66597_ISO 0xC000 /* Isochronous */
+#define R8A66597_INT 0x8000 /* Interrupt */
+#define R8A66597_BULK 0x4000 /* Bulk */
+#define R8A66597_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */
+#define R8A66597_DBLB 0x0200 /* b9: Double buffer mode select */
+#define R8A66597_CNTMD 0x0100 /* b8: Continuous transfer mode select */
+#define R8A66597_SHTNAK 0x0080 /* b7: Transfer end NAK */
+#define R8A66597_DIR 0x0010 /* b4: Transfer direction select */
+#define R8A66597_EPNUM 0x000F /* b3-0: Eendpoint number select */
+
+/* Pipe Buffer Configuration Register */
+#define BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */
+#define BUFNMB 0x007F /* b6-0: Pipe buffer number */
+#define PIPE0BUF 256
+#define PIPExBUF 64
+
+/* Pipe Maxpacket Size Register */
+#define MXPS 0x07FF /* b10-0: Maxpacket size */
+
+/* Pipe Cycle Configuration Register */
+#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */
+#define IITV 0x0007 /* b2-0: Isochronous interval */
+
+/* Pipex Control Register */
+#define BSTS 0x8000 /* b15: Buffer status */
+#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */
+#define CSCLR 0x2000 /* b13: complete-split status clear */
+#define CSSTS 0x1000 /* b12: complete-split status */
+#define ATREPM 0x0400 /* b10: Auto repeat mode */
+#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */
+#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */
+#define SQSET 0x0080 /* b7: Sequence toggle bit set */
+#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */
+#define PBUSY 0x0020 /* b5: pipe busy */
+#define PID 0x0003 /* b1-0: Response PID */
+
+/* PIPExTRE */
+#define TRENB 0x0200 /* b9: Transaction counter enable */
+#define TRCLR 0x0100 /* b8: Transaction counter clear */
+
+/* PIPExTRN */
+#define TRNCNT 0xFFFF /* b15-0: Transaction counter */
+
+/* DEVADDx */
+#define UPPHUB 0x7800
+#define HUBPORT 0x0700
+#define USBSPD 0x00C0
+#define RTPORT 0x0001
+
+#define R8A66597_MAX_NUM_PIPE 10
+#define R8A66597_BUF_BSIZE 8
+#define R8A66597_MAX_DEVICE 10
+#define R8A66597_MAX_ROOT_HUB 2
+#define R8A66597_MAX_SAMPLING 10
+#define R8A66597_MAX_DMA_CHANNEL 2
+#define R8A66597_PIPE_NO_DMA R8A66597_MAX_DMA_CHANNEL
+#define check_bulk_or_isoc(pipenum) ((pipenum >= 1 && pipenum <= 5))
+#define check_interrupt(pipenum) ((pipenum >= 6 && pipenum <= 9))
+#define make_devsel(addr) (addr << 12)
+
+struct r8a66597_pipe_info {
+ u16 pipenum;
+ u16 address; /* R8A66597 HCD usb addres */
+ u16 epnum;
+ u16 maxpacket;
+ u16 type;
+ u16 bufnum;
+ u16 buf_bsize;
+ u16 interval;
+ u16 dir_in;
+};
+
+struct r8a66597_pipe {
+ struct r8a66597_pipe_info info;
+
+ unsigned long fifoaddr;
+ unsigned long fifosel;
+ unsigned long fifoctr;
+ unsigned long pipectr;
+ unsigned long pipetre;
+ unsigned long pipetrn;
+};
+
+struct r8a66597_td {
+ struct r8a66597_pipe *pipe;
+ struct urb *urb;
+ struct list_head queue;
+
+ u16 type;
+ u16 pipenum;
+ int iso_cnt;
+
+ u16 address; /* R8A66597's USB address */
+ u16 maxpacket;
+
+ unsigned zero_packet:1;
+ unsigned short_packet:1;
+ unsigned set_address:1;
+};
+
+struct r8a66597_device {
+ u16 address; /* R8A66597's USB address */
+ u16 hub_port;
+ u16 root_port;
+
+ unsigned short ep_in_toggle;
+ unsigned short ep_out_toggle;
+ unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+ unsigned char dma_map;
+
+ enum usb_device_state state;
+
+ struct usb_device *udev;
+ int usb_address;
+ struct list_head device_list;
+};
+
+struct r8a66597_root_hub {
+ u32 port;
+ u16 old_syssts;
+ int scount;
+
+ struct r8a66597_device *dev;
+};
+
+struct r8a66597 {
+ spinlock_t lock;
+ unsigned long reg;
+
+ struct r8a66597_device device0;
+ struct r8a66597_root_hub root_hub[R8A66597_MAX_ROOT_HUB];
+ struct list_head pipe_queue[R8A66597_MAX_NUM_PIPE];
+
+ struct timer_list rh_timer;
+ struct timer_list td_timer[R8A66597_MAX_NUM_PIPE];
+
+ unsigned short address_map;
+ unsigned short timeout_map;
+ unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE];
+ unsigned char dma_map;
+
+ struct list_head child_device;
+ unsigned long child_connect_map[4];
+};
+
+static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd)
+{
+ return (struct r8a66597 *)(hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *r8a66597_to_hcd(struct r8a66597 *r8a66597)
+{
+ return container_of((void *)r8a66597, struct usb_hcd, hcd_priv);
+}
+
+static inline struct r8a66597_td *r8a66597_get_td(struct r8a66597 *r8a66597,
+ u16 pipenum)
+{
+ if (unlikely(list_empty(&r8a66597->pipe_queue[pipenum])))
+ return NULL;
+
+ return list_entry(r8a66597->pipe_queue[pipenum].next,
+ struct r8a66597_td, queue);
+}
+
+static inline struct urb *r8a66597_get_urb(struct r8a66597 *r8a66597,
+ u16 pipenum)
+{
+ struct r8a66597_td *td;
+
+ td = r8a66597_get_td(r8a66597, pipenum);
+ return (td ? td->urb : NULL);
+}
+
+static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
+{
+ return inw(r8a66597->reg + offset);
+}
+
+static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
+ unsigned long offset, u16 *buf,
+ int len)
+{
+ len = (len + 1) / 2;
+ insw(r8a66597->reg + offset, buf, len);
+}
+
+static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
+ unsigned long offset)
+{
+ outw(val, r8a66597->reg + offset);
+}
+
+static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
+ unsigned long offset, u16 *buf,
+ int len)
+{
+ unsigned long fifoaddr = r8a66597->reg + offset;
+ int odd = len & 0x0001;
+
+ len = len / 2;
+ outsw(fifoaddr, buf, len);
+ if (unlikely(odd)) {
+ buf = &buf[len];
+ outb((unsigned char)*buf, fifoaddr);
+ }
+}
+
+static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
+ u16 val, u16 pat, unsigned long offset)
+{
+ u16 tmp;
+ tmp = r8a66597_read(r8a66597, offset);
+ tmp = tmp & (~pat);
+ tmp = tmp | val;
+ r8a66597_write(r8a66597, tmp, offset);
+}
+
+#define r8a66597_bclr(r8a66597, val, offset) \
+ r8a66597_mdfy(r8a66597, 0, val, offset)
+#define r8a66597_bset(r8a66597, val, offset) \
+ r8a66597_mdfy(r8a66597, val, 0, offset)
+
+static inline unsigned long get_syscfg_reg(int port)
+{
+ return port == 0 ? SYSCFG0 : SYSCFG1;
+}
+
+static inline unsigned long get_syssts_reg(int port)
+{
+ return port == 0 ? SYSSTS0 : SYSSTS1;
+}
+
+static inline unsigned long get_dvstctr_reg(int port)
+{
+ return port == 0 ? DVSTCTR0 : DVSTCTR1;
+}
+
+static inline unsigned long get_intenb_reg(int port)
+{
+ return port == 0 ? INTENB1 : INTENB2;
+}
+
+static inline unsigned long get_intsts_reg(int port)
+{
+ return port == 0 ? INTSTS1 : INTSTS2;
+}
+
+static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port)
+{
+ unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+ return r8a66597_read(r8a66597, dvstctr_reg) & RHST;
+}
+
+static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port,
+ int power)
+{
+ unsigned long dvstctr_reg = get_dvstctr_reg(port);
+
+ if (power)
+ r8a66597_bset(r8a66597, VBOUT, dvstctr_reg);
+ else
+ r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg);
+}
+
+#define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2)
+#define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4)
+#define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4)
+#define get_devadd_addr(address) (DEVADD0 + address * 2)
+
+#define enable_irq_ready(r8a66597, pipenum) \
+ enable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define disable_irq_ready(r8a66597, pipenum) \
+ disable_pipe_irq(r8a66597, pipenum, BRDYENB)
+#define enable_irq_empty(r8a66597, pipenum) \
+ enable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define disable_irq_empty(r8a66597, pipenum) \
+ disable_pipe_irq(r8a66597, pipenum, BEMPENB)
+#define enable_irq_nrdy(r8a66597, pipenum) \
+ enable_pipe_irq(r8a66597, pipenum, NRDYENB)
+#define disable_irq_nrdy(r8a66597, pipenum) \
+ disable_pipe_irq(r8a66597, pipenum, NRDYENB)
+
+#endif /* __R8A66597_H__ */
+
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index d22da26ff16..76c555a67da 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -730,10 +730,9 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
int rc = 0;
spin_lock_irq(&uhci->lock);
- if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
- dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
+ if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
rc = -ESHUTDOWN;
- } else if (!uhci->dead)
+ else if (!uhci->dead)
wakeup_rh(uhci);
spin_unlock_irq(&uhci->lock);
return rc;
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
index 77145f9db04..d72c42e5f22 100644
--- a/drivers/usb/misc/adutux.c
+++ b/drivers/usb/misc/adutux.c
@@ -108,8 +108,6 @@ struct adu_device {
struct urb* interrupt_out_urb;
};
-/* prevent races between open() and disconnect */
-static DEFINE_MUTEX(disconnect_mutex);
static struct usb_driver adu_driver;
static void adu_debug_data(int level, const char *function, int size,
@@ -256,8 +254,6 @@ static int adu_open(struct inode *inode, struct file *file)
subminor = iminor(inode);
- mutex_lock(&disconnect_mutex);
-
interface = usb_find_interface(&adu_driver, subminor);
if (!interface) {
err("%s - error, can't find device for minor %d",
@@ -306,7 +302,6 @@ static int adu_open(struct inode *inode, struct file *file)
up(&dev->sem);
exit_no_device:
- mutex_unlock(&disconnect_mutex);
dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
return retval;
@@ -318,12 +313,6 @@ static int adu_release_internal(struct adu_device *dev)
dbg(2," %s : enter", __FUNCTION__);
- if (dev->udev == NULL) {
- /* the device was unplugged before the file was released */
- adu_delete(dev);
- goto exit;
- }
-
/* decrement our usage count for the device */
--dev->open_count;
dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
@@ -332,7 +321,6 @@ static int adu_release_internal(struct adu_device *dev)
dev->open_count = 0;
}
-exit:
dbg(2," %s : leave", __FUNCTION__);
return retval;
}
@@ -367,8 +355,15 @@ static int adu_release(struct inode *inode, struct file *file)
goto exit;
}
- /* do the work */
- retval = adu_release_internal(dev);
+ if (dev->udev == NULL) {
+ /* the device was unplugged before the file was released */
+ up(&dev->sem);
+ adu_delete(dev);
+ dev = NULL;
+ } else {
+ /* do the work */
+ retval = adu_release_internal(dev);
+ }
exit:
if (dev)
@@ -831,19 +826,17 @@ static void adu_disconnect(struct usb_interface *interface)
dbg(2," %s : enter", __FUNCTION__);
- mutex_lock(&disconnect_mutex); /* not interruptible */
-
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
- down(&dev->sem); /* not interruptible */
-
minor = dev->minor;
/* give back our minor */
usb_deregister_dev(interface, &adu_class);
dev->minor = 0;
+ down(&dev->sem); /* not interruptible */
+
/* if the device is not opened, then we clean up right now */
dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
if (!dev->open_count) {
@@ -854,8 +847,6 @@ static void adu_disconnect(struct usb_interface *interface)
up(&dev->sem);
}
- mutex_unlock(&disconnect_mutex);
-
dev_info(&interface->dev, "ADU device adutux%d now disconnected",
(minor - ADU_MINOR_BASE));
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index cac1500cba6..1fd5fc220cd 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -2034,12 +2034,12 @@ static void auerswald_disconnect (struct usb_interface *intf)
if (!cp)
return;
- down (&cp->mutex);
- info ("device /dev/%s now disconnecting", cp->name);
-
/* give back our USB minor number */
usb_deregister_dev(intf, &auerswald_class);
+ down (&cp->mutex);
+ info ("device /dev/%s now disconnecting", cp->name);
+
/* Stop the interrupt endpoint */
auerswald_int_release (cp);
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c
index b15f2fd8dab..92c1d2768df 100644
--- a/drivers/usb/misc/berry_charge.c
+++ b/drivers/usb/misc/berry_charge.c
@@ -26,8 +26,11 @@
#define RIM_VENDOR 0x0fca
#define BLACKBERRY 0x0001
+#define BLACKBERRY_PEARL_DUAL 0x0004
+#define BLACKBERRY_PEARL 0x0006
static int debug;
+static int pearl_dual_mode = 1;
#ifdef dbg
#undef dbg
@@ -38,6 +41,8 @@ static int debug;
static struct usb_device_id id_table [] = {
{ USB_DEVICE(RIM_VENDOR, BLACKBERRY) },
+ { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) },
+ { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) },
{ }, /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -86,6 +91,30 @@ static int magic_charge(struct usb_device *udev)
return retval;
}
+static int magic_dual_mode(struct usb_device *udev)
+{
+ char *dummy_buffer = kzalloc(2, GFP_KERNEL);
+ int retval;
+
+ if (!dummy_buffer)
+ return -ENOMEM;
+
+ /* send magic command so that the Blackberry Pearl device exposes
+ * two interfaces: both the USB mass-storage one and one which can
+ * be used for database access. */
+ dbg(&udev->dev, "Sending magic pearl command\n");
+ retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100);
+ dbg(&udev->dev, "Magic pearl command returned %d\n", retval);
+
+ dbg(&udev->dev, "Calling set_configuration\n");
+ retval = usb_driver_set_configuration(udev, 1);
+ if (retval)
+ dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval);
+
+ return retval;
+}
+
static int berry_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -105,6 +134,10 @@ static int berry_probe(struct usb_interface *intf,
/* turn the power on */
magic_charge(udev);
+ if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) &&
+ (pearl_dual_mode))
+ magic_dual_mode(udev);
+
/* we don't really want to bind to the device, userspace programs can
* handle the syncing just fine, so get outta here. */
return -ENODEV;
@@ -138,3 +171,5 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
+module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode");
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index 8d0e360636e..e6fd024024f 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -119,9 +119,6 @@ static struct usb_driver idmouse_driver = {
.id_table = idmouse_table,
};
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
static int idmouse_create_image(struct usb_idmouse *dev)
{
int bytes_read;
@@ -211,21 +208,15 @@ static int idmouse_open(struct inode *inode, struct file *file)
struct usb_interface *interface;
int result;
- /* prevent disconnects */
- mutex_lock(&disconnect_mutex);
-
/* get the interface from minor number and driver information */
interface = usb_find_interface (&idmouse_driver, iminor (inode));
- if (!interface) {
- mutex_unlock(&disconnect_mutex);
+ if (!interface)
return -ENODEV;
- }
+
/* get the device information block from the interface */
dev = usb_get_intfdata(interface);
- if (!dev) {
- mutex_unlock(&disconnect_mutex);
+ if (!dev)
return -ENODEV;
- }
/* lock this device */
down(&dev->sem);
@@ -255,9 +246,6 @@ error:
/* unlock this device */
up(&dev->sem);
-
- /* unlock the disconnect semaphore */
- mutex_unlock(&disconnect_mutex);
return result;
}
@@ -265,15 +253,10 @@ static int idmouse_release(struct inode *inode, struct file *file)
{
struct usb_idmouse *dev;
- /* prevent a race condition with open() */
- mutex_lock(&disconnect_mutex);
-
dev = file->private_data;
- if (dev == NULL) {
- mutex_unlock(&disconnect_mutex);
+ if (dev == NULL)
return -ENODEV;
- }
/* lock our device */
down(&dev->sem);
@@ -281,7 +264,6 @@ static int idmouse_release(struct inode *inode, struct file *file)
/* are we really open? */
if (dev->open <= 0) {
up(&dev->sem);
- mutex_unlock(&disconnect_mutex);
return -ENODEV;
}
@@ -291,12 +273,9 @@ static int idmouse_release(struct inode *inode, struct file *file)
/* the device was unplugged before the file was released */
up(&dev->sem);
idmouse_delete(dev);
- mutex_unlock(&disconnect_mutex);
- return 0;
+ } else {
+ up(&dev->sem);
}
-
- up(&dev->sem);
- mutex_unlock(&disconnect_mutex);
return 0;
}
@@ -391,30 +370,27 @@ static void idmouse_disconnect(struct usb_interface *interface)
{
struct usb_idmouse *dev;
- /* prevent races with open() */
- mutex_lock(&disconnect_mutex);
-
/* get device structure */
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
- /* lock it */
- down(&dev->sem);
-
/* give back our minor */
usb_deregister_dev(interface, &idmouse_class);
+ /* lock it */
+ down(&dev->sem);
+
/* prevent device read, write and ioctl */
dev->present = 0;
- /* unlock */
- up(&dev->sem);
-
/* if the device is opened, idmouse_release will clean this up */
- if (!dev->open)
+ if (!dev->open) {
+ up(&dev->sem);
idmouse_delete(dev);
-
- mutex_unlock(&disconnect_mutex);
+ } else {
+ /* unlock */
+ up(&dev->sem);
+ }
info("%s disconnected", DRIVER_DESC);
}
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index fc51207b71b..28548d18671 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -100,8 +100,6 @@ struct iowarrior {
/*--------------*/
/* globals */
/*--------------*/
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX(disconnect_sem);
/*
* USB spec identifies 5 second timeouts.
@@ -495,8 +493,8 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file,
/* verify that the device wasn't unplugged */
if (!dev->present) {
- mutex_unlock(&dev->mutex);
- return -ENODEV;
+ retval = -ENODEV;
+ goto error_out;
}
dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __func__, dev->minor, cmd,
@@ -579,9 +577,10 @@ static int iowarrior_ioctl(struct inode *inode, struct file *file,
retval = -ENOTTY;
break;
}
-
+error_out:
/* unlock the device */
mutex_unlock(&dev->mutex);
+ kfree(buffer);
return retval;
}
@@ -599,22 +598,18 @@ static int iowarrior_open(struct inode *inode, struct file *file)
subminor = iminor(inode);
- /* prevent disconnects */
- down(&disconnect_sem);
-
interface = usb_find_interface(&iowarrior_driver, subminor);
if (!interface) {
err("%s - error, can't find device for minor %d", __FUNCTION__,
subminor);
- retval = -ENODEV;
- goto out;
+ return -ENODEV;
}
dev = usb_get_intfdata(interface);
- if (!dev) {
- retval = -ENODEV;
- goto out;
- }
+ if (!dev)
+ return -ENODEV;
+
+ mutex_lock(&dev->mutex);
/* Only one process can open each device, no sharing. */
if (dev->opened) {
@@ -635,7 +630,7 @@ static int iowarrior_open(struct inode *inode, struct file *file)
retval = 0;
out:
- up(&disconnect_sem);
+ mutex_unlock(&dev->mutex);
return retval;
}
@@ -867,19 +862,16 @@ static void iowarrior_disconnect(struct usb_interface *interface)
struct iowarrior *dev;
int minor;
- /* prevent races with open() */
- down(&disconnect_sem);
-
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
- mutex_lock(&dev->mutex);
-
minor = dev->minor;
/* give back our minor */
usb_deregister_dev(interface, &iowarrior_class);
+ mutex_lock(&dev->mutex);
+
/* prevent device read, write and ioctl */
dev->present = 0;
@@ -897,7 +889,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
/* no process is using the device, cleanup now */
iowarrior_delete(dev);
}
- up(&disconnect_sem);
dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
minor - IOWARRIOR_MINOR_BASE);
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 7bad4940476..5e950b90c54 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -176,9 +176,6 @@ struct ld_usb {
int interrupt_out_busy;
};
-/* prevent races between open() and disconnect() */
-static DEFINE_MUTEX(disconnect_mutex);
-
static struct usb_driver ld_usb_driver;
/**
@@ -298,35 +295,28 @@ static int ld_usb_open(struct inode *inode, struct file *file)
{
struct ld_usb *dev;
int subminor;
- int retval = 0;
+ int retval;
struct usb_interface *interface;
nonseekable_open(inode, file);
subminor = iminor(inode);
- mutex_lock(&disconnect_mutex);
-
interface = usb_find_interface(&ld_usb_driver, subminor);
if (!interface) {
err("%s - error, can't find device for minor %d\n",
__FUNCTION__, subminor);
- retval = -ENODEV;
- goto unlock_disconnect_exit;
+ return -ENODEV;
}
dev = usb_get_intfdata(interface);
- if (!dev) {
- retval = -ENODEV;
- goto unlock_disconnect_exit;
- }
+ if (!dev)
+ return -ENODEV;
/* lock this device */
- if (down_interruptible(&dev->sem)) {
- retval = -ERESTARTSYS;
- goto unlock_disconnect_exit;
- }
+ if (down_interruptible(&dev->sem))
+ return -ERESTARTSYS;
/* allow opening only once */
if (dev->open_count) {
@@ -366,9 +356,6 @@ static int ld_usb_open(struct inode *inode, struct file *file)
unlock_exit:
up(&dev->sem);
-unlock_disconnect_exit:
- mutex_unlock(&disconnect_mutex);
-
return retval;
}
@@ -766,18 +753,16 @@ static void ld_usb_disconnect(struct usb_interface *intf)
struct ld_usb *dev;
int minor;
- mutex_lock(&disconnect_mutex);
-
dev = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
- down(&dev->sem);
-
minor = intf->minor;
/* give back our minor */
usb_deregister_dev(intf, &ld_usb_class);
+ down(&dev->sem);
+
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
up(&dev->sem);
@@ -787,8 +772,6 @@ static void ld_usb_disconnect(struct usb_interface *intf)
up(&dev->sem);
}
- mutex_unlock(&disconnect_mutex);
-
dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
(minor - USB_LD_MINOR_BASE));
}
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index 1713e19a789..2ed0daea894 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -254,9 +254,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_devic
static void tower_disconnect (struct usb_interface *interface);
-/* prevent races between open() and disconnect */
-static DEFINE_MUTEX (disconnect_mutex);
-
/* file operations needed when we register this driver */
static const struct file_operations tower_fops = {
.owner = THIS_MODULE,
@@ -344,28 +341,26 @@ static int tower_open (struct inode *inode, struct file *file)
nonseekable_open(inode, file);
subminor = iminor(inode);
- mutex_lock (&disconnect_mutex);
-
interface = usb_find_interface (&tower_driver, subminor);
if (!interface) {
err ("%s - error, can't find device for minor %d",
__FUNCTION__, subminor);
retval = -ENODEV;
- goto unlock_disconnect_exit;
+ goto exit;
}
dev = usb_get_intfdata(interface);
if (!dev) {
retval = -ENODEV;
- goto unlock_disconnect_exit;
+ goto exit;
}
/* lock this device */
if (down_interruptible (&dev->sem)) {
retval = -ERESTARTSYS;
- goto unlock_disconnect_exit;
+ goto exit;
}
/* allow opening only once */
@@ -421,9 +416,7 @@ static int tower_open (struct inode *inode, struct file *file)
unlock_exit:
up (&dev->sem);
-unlock_disconnect_exit:
- mutex_unlock (&disconnect_mutex);
-
+exit:
dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval);
return retval;
@@ -993,19 +986,16 @@ static void tower_disconnect (struct usb_interface *interface)
dbg(2, "%s: enter", __FUNCTION__);
- mutex_lock (&disconnect_mutex);
-
dev = usb_get_intfdata (interface);
usb_set_intfdata (interface, NULL);
-
- down (&dev->sem);
-
minor = dev->minor;
/* give back our minor */
usb_deregister_dev (interface, &tower_class);
+ down (&dev->sem);
+
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
up (&dev->sem);
@@ -1015,8 +1005,6 @@ static void tower_disconnect (struct usb_interface *interface)
up (&dev->sem);
}
- mutex_unlock (&disconnect_mutex);
-
info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE));
dbg(2, "%s: leave", __FUNCTION__);
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 6f8b134a79c..9f37ba44c13 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -72,8 +72,6 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES
static struct usb_driver sisusb_driver;
-DEFINE_MUTEX(disconnect_mutex);
-
static void
sisusb_free_buffers(struct sisusb_usb_data *sisusb)
{
@@ -2511,31 +2509,24 @@ sisusb_open(struct inode *inode, struct file *file)
struct usb_interface *interface;
int subminor = iminor(inode);
- mutex_lock(&disconnect_mutex);
-
if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
subminor);
- mutex_unlock(&disconnect_mutex);
return -ENODEV;
}
- if (!(sisusb = usb_get_intfdata(interface))) {
- mutex_unlock(&disconnect_mutex);
+ if (!(sisusb = usb_get_intfdata(interface)))
return -ENODEV;
- }
mutex_lock(&sisusb->lock);
if (!sisusb->present || !sisusb->ready) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return -ENODEV;
}
if (sisusb->isopen) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return -EBUSY;
}
@@ -2543,7 +2534,6 @@ sisusb_open(struct inode *inode, struct file *file)
if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
if (sisusb_init_gfxdevice(sisusb, 0)) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
printk(KERN_ERR
"sisusbvga[%d]: Failed to initialize "
"device\n",
@@ -2552,7 +2542,6 @@ sisusb_open(struct inode *inode, struct file *file)
}
} else {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
printk(KERN_ERR
"sisusbvga[%d]: Device not attached to "
"USB 2.0 hub\n",
@@ -2570,8 +2559,6 @@ sisusb_open(struct inode *inode, struct file *file)
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
-
return 0;
}
@@ -2601,12 +2588,8 @@ sisusb_release(struct inode *inode, struct file *file)
struct sisusb_usb_data *sisusb;
int myminor;
- mutex_lock(&disconnect_mutex);
-
- if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
- mutex_unlock(&disconnect_mutex);
+ if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
return -ENODEV;
- }
mutex_lock(&sisusb->lock);
@@ -2626,8 +2609,6 @@ sisusb_release(struct inode *inode, struct file *file)
/* decrement the usage count on our device */
kref_put(&sisusb->kref, sisusb_delete);
- mutex_unlock(&disconnect_mutex);
-
return 0;
}
@@ -3383,12 +3364,9 @@ static void sisusb_disconnect(struct usb_interface *intf)
sisusb_console_exit(sisusb);
#endif
- /* The above code doesn't need the disconnect
- * semaphore to be down; its meaning is to
- * protect all other routines from the disconnect
- * case, not the other way round.
- */
- mutex_lock(&disconnect_mutex);
+ minor = sisusb->minor;
+
+ usb_deregister_dev(intf, &usb_sisusb_class);
mutex_lock(&sisusb->lock);
@@ -3396,12 +3374,8 @@ static void sisusb_disconnect(struct usb_interface *intf)
if (!sisusb_wait_all_out_complete(sisusb))
sisusb_kill_all_busy(sisusb);
- minor = sisusb->minor;
-
usb_set_intfdata(intf, NULL);
- usb_deregister_dev(intf, &usb_sisusb_class);
-
#ifdef SISUSB_OLD_CONFIG_COMPAT
if (sisusb->ioctl32registered) {
int ret;
@@ -3426,8 +3400,6 @@ static void sisusb_disconnect(struct usb_interface *intf)
/* decrement our usage count */
kref_put(&sisusb->kref, sisusb_delete);
- mutex_unlock(&disconnect_mutex);
-
printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
}
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index 5947afb0017..8d0edc867f3 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -214,18 +214,13 @@ sisusbcon_init(struct vc_data *c, int init)
* are set up/restored.
*/
- mutex_lock(&disconnect_mutex);
-
- if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
- mutex_unlock(&disconnect_mutex);
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
return;
- }
mutex_lock(&sisusb->lock);
if (!sisusb_sisusb_valid(sisusb)) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return;
}
@@ -264,8 +259,6 @@ sisusbcon_init(struct vc_data *c, int init)
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
-
if (init) {
c->vc_cols = cols;
c->vc_rows = rows;
@@ -284,12 +277,8 @@ sisusbcon_deinit(struct vc_data *c)
* and others, ie not under our control.
*/
- mutex_lock(&disconnect_mutex);
-
- if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
- mutex_unlock(&disconnect_mutex);
+ if (!(sisusb = sisusb_get_sisusb(c->vc_num)))
return;
- }
mutex_lock(&sisusb->lock);
@@ -314,8 +303,6 @@ sisusbcon_deinit(struct vc_data *c)
/* decrement the usage count on our sisusb */
kref_put(&sisusb->kref, sisusb_delete);
-
- mutex_unlock(&disconnect_mutex);
}
/* interface routine */
@@ -1490,14 +1477,11 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
{
int i, ret, minor = sisusb->minor;
- mutex_lock(&disconnect_mutex);
-
mutex_lock(&sisusb->lock);
/* Erm.. that should not happen */
if (sisusb->haveconsole || !sisusb->SiS_Pr) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return 1;
}
@@ -1508,14 +1492,12 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
first > MAX_NR_CONSOLES ||
last > MAX_NR_CONSOLES) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return 1;
}
/* If gfxcore not initialized or no consoles given, quit graciously */
if (!sisusb->gfxinit || first < 1 || last < 1) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
return 0;
}
@@ -1526,7 +1508,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
/* Set up text mode (and upload default font) */
if (sisusb_reset_text_mode(sisusb, 1)) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
printk(KERN_ERR
"sisusbvga[%d]: Failed to set up text mode\n",
minor);
@@ -1550,7 +1531,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
/* Allocate screen buffer */
if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
printk(KERN_ERR
"sisusbvga[%d]: Failed to allocate screen buffer\n",
minor);
@@ -1558,7 +1538,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last)
}
mutex_unlock(&sisusb->lock);
- mutex_unlock(&disconnect_mutex);
/* Now grab the desired console(s) */
ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
index f05f83268af..864bc0e9659 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_init.h
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -808,8 +808,6 @@ static const struct SiS_VCLKData SiSUSB_VCLKData[] =
{ 0x2b,0xc2, 35} /* 0x71 768@576@60 */
};
-extern struct mutex disconnect_mutex;
-
int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 887ef953f3d..504f7221b0d 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -42,12 +42,16 @@ struct usb_lcd {
size_t bulk_in_size; /* the size of the receive buffer */
__u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
__u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
- struct kref kref;
+ struct kref kref;
+ struct semaphore limit_sem; /* to stop writes at full throttle from
+ * using up all RAM */
+ struct usb_anchor submitted; /* URBs to wait for before suspend */
};
#define to_lcd_dev(d) container_of(d, struct usb_lcd, kref)
+#define USB_LCD_CONCURRENT_WRITES 5
+
static struct usb_driver lcd_driver;
-static DEFINE_MUTEX(usb_lcd_open_mutex);
static void lcd_delete(struct kref *kref)
@@ -64,35 +68,35 @@ static int lcd_open(struct inode *inode, struct file *file)
{
struct usb_lcd *dev;
struct usb_interface *interface;
- int subminor;
- int retval = 0;
+ int subminor, r;
subminor = iminor(inode);
- mutex_lock(&usb_lcd_open_mutex);
interface = usb_find_interface(&lcd_driver, subminor);
if (!interface) {
err ("USBLCD: %s - error, can't find device for minor %d",
__FUNCTION__, subminor);
- retval = -ENODEV;
- goto exit;
+ return -ENODEV;
}
dev = usb_get_intfdata(interface);
- if (!dev) {
- retval = -ENODEV;
- goto exit;
- }
+ if (!dev)
+ return -ENODEV;
/* increment our usage count for the device */
kref_get(&dev->kref);
+ /* grab a power reference */
+ r = usb_autopm_get_interface(interface);
+ if (r < 0) {
+ kref_put(&dev->kref, lcd_delete);
+ return r;
+ }
+
/* save our object in the file's private structure */
file->private_data = dev;
-exit:
- mutex_unlock(&usb_lcd_open_mutex);
- return retval;
+ return 0;
}
static int lcd_release(struct inode *inode, struct file *file)
@@ -104,6 +108,7 @@ static int lcd_release(struct inode *inode, struct file *file)
return -ENODEV;
/* decrement the count on our device */
+ usb_autopm_put_interface(dev->interface);
kref_put(&dev->kref, lcd_delete);
return 0;
}
@@ -186,12 +191,13 @@ static void lcd_write_bulk_callback(struct urb *urb)
/* free up our allocated buffer */
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
+ up(&dev->limit_sem);
}
static ssize_t lcd_write(struct file *file, const char __user * user_buffer, size_t count, loff_t *ppos)
{
struct usb_lcd *dev;
- int retval = 0;
+ int retval = 0, r;
struct urb *urb = NULL;
char *buf = NULL;
@@ -201,10 +207,16 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
if (count == 0)
goto exit;
+ r = down_interruptible(&dev->limit_sem);
+ if (r < 0)
+ return -EINTR;
+
/* create a urb, and a buffer for it, and copy the data to the urb */
urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
+ if (!urb) {
+ retval = -ENOMEM;
+ goto err_no_buf;
+ }
buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
if (!buf) {
@@ -222,12 +234,14 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
buf, count, lcd_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ usb_anchor_urb(urb, &dev->submitted);
/* send the data out the bulk port */
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval);
- goto error;
+ goto error_unanchor;
}
/* release our reference to this urb, the USB core will eventually free it entirely */
@@ -235,10 +249,13 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz
exit:
return count;
-
+error_unanchor:
+ usb_unanchor_urb(urb);
error:
usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
usb_free_urb(urb);
+err_no_buf:
+ up(&dev->limit_sem);
return retval;
}
@@ -277,6 +294,8 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
goto error;
}
kref_init(&dev->kref);
+ sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES);
+ init_usb_anchor(&dev->submitted);
dev->udev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
@@ -344,22 +363,41 @@ error:
return retval;
}
+static void lcd_draw_down(struct usb_lcd *dev)
+{
+ int time;
+
+ time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+ if (!time)
+ usb_kill_anchored_urbs(&dev->submitted);
+}
+
+static int lcd_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usb_lcd *dev = usb_get_intfdata(intf);
+
+ if (!dev)
+ return 0;
+ lcd_draw_down(dev);
+ return 0;
+}
+
+static int lcd_resume (struct usb_interface *intf)
+{
+ return 0;
+}
+
static void lcd_disconnect(struct usb_interface *interface)
{
struct usb_lcd *dev;
int minor = interface->minor;
- /* prevent skel_open() from racing skel_disconnect() */
- mutex_lock(&usb_lcd_open_mutex);
-
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &lcd_class);
- mutex_unlock(&usb_lcd_open_mutex);
-
/* decrement our usage count */
kref_put(&dev->kref, lcd_delete);
@@ -370,7 +408,10 @@ static struct usb_driver lcd_driver = {
.name = "usblcd",
.probe = lcd_probe,
.disconnect = lcd_disconnect,
+ .suspend = lcd_suspend,
+ .resume = lcd_resume,
.id_table = id_table,
+ .supports_autosuspend = 1,
};
static int __init usb_lcd_init(void)
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 70250252ae2..1a60f9c473a 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -336,7 +336,7 @@ static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
memcpy(priv->reg, buffer, 4);
/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
if (priv->reg[2] & priv->reg[1] & 0x10)
- parport_generic_irq(0, pp, NULL);
+ parport_generic_irq(0, pp);
return 1;
}
#endif
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 0af11a66207..c03dfd7a9d3 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -4,7 +4,7 @@
* This is a binary format reader.
*
* Copyright (C) 2006 Paolo Abeni (paolo.abeni@email.it)
- * Copyright (C) 2006 Pete Zaitcev (zaitcev@redhat.com)
+ * Copyright (C) 2006,2007 Pete Zaitcev (zaitcev@redhat.com)
*/
#include <linux/kernel.h>
@@ -172,6 +172,7 @@ static inline struct mon_bin_hdr *MON_OFF2HDR(const struct mon_reader_bin *rp,
#define MON_RING_EMPTY(rp) ((rp)->b_cnt == 0)
+static struct class *mon_bin_class;
static dev_t mon_bin_dev0;
static struct cdev mon_bin_cdev;
@@ -1144,10 +1145,38 @@ static void mon_free_buff(struct mon_pgmap *map, int npages)
free_page((unsigned long) map[n].ptr);
}
+int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
+{
+ struct device *dev;
+ unsigned minor = ubus? ubus->busnum: 0;
+
+ if (minor >= MON_BIN_MAX_MINOR)
+ return 0;
+
+ dev = device_create(mon_bin_class, ubus? ubus->controller: NULL,
+ MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor);
+ if (IS_ERR(dev))
+ return 0;
+
+ mbus->classdev = dev;
+ return 1;
+}
+
+void mon_bin_del(struct mon_bus *mbus)
+{
+ device_destroy(mon_bin_class, mbus->classdev->devt);
+}
+
int __init mon_bin_init(void)
{
int rc;
+ mon_bin_class = class_create(THIS_MODULE, "usbmon");
+ if (IS_ERR(mon_bin_class)) {
+ rc = PTR_ERR(mon_bin_class);
+ goto err_class;
+ }
+
rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon");
if (rc < 0)
goto err_dev;
@@ -1164,6 +1193,8 @@ int __init mon_bin_init(void)
err_add:
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
err_dev:
+ class_destroy(mon_bin_class);
+err_class:
return rc;
}
@@ -1171,4 +1202,5 @@ void mon_bin_exit(void)
{
cdev_del(&mon_bin_cdev);
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
+ class_destroy(mon_bin_class);
}
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 8977ec0d0f9..ce61d8b0fd8 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -220,6 +220,8 @@ static void mon_bus_remove(struct usb_bus *ubus)
list_del(&mbus->bus_link);
if (mbus->text_inited)
mon_text_del(mbus);
+ if (mbus->bin_inited)
+ mon_bin_del(mbus);
mon_dissolve(mbus, ubus);
kref_put(&mbus->ref, mon_bus_drop);
@@ -301,8 +303,8 @@ static void mon_bus_init(struct usb_bus *ubus)
mbus->u_bus = ubus;
ubus->mon_bus = mbus;
- mbus->text_inited = mon_text_add(mbus, ubus->busnum);
- // mon_bin_add(...)
+ mbus->text_inited = mon_text_add(mbus, ubus);
+ mbus->bin_inited = mon_bin_add(mbus, ubus);
mutex_lock(&mon_lock);
list_add_tail(&mbus->bus_link, &mon_buses);
@@ -321,8 +323,8 @@ static void mon_bus0_init(void)
spin_lock_init(&mbus->lock);
INIT_LIST_HEAD(&mbus->r_list);
- mbus->text_inited = mon_text_add(mbus, 0);
- // mbus->bin_inited = mon_bin_add(mbus, 0);
+ mbus->text_inited = mon_text_add(mbus, NULL);
+ mbus->bin_inited = mon_bin_add(mbus, NULL);
}
/*
@@ -403,6 +405,8 @@ static void __exit mon_exit(void)
if (mbus->text_inited)
mon_text_del(mbus);
+ if (mbus->bin_inited)
+ mon_bin_del(mbus);
/*
* This never happens, because the open/close paths in
@@ -423,6 +427,8 @@ static void __exit mon_exit(void)
mbus = &mon_bus0;
if (mbus->text_inited)
mon_text_del(mbus);
+ if (mbus->bin_inited)
+ mon_bin_del(mbus);
mutex_unlock(&mon_lock);
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index ec0cc51e39a..982b773d71e 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -655,20 +655,24 @@ static const struct file_operations mon_fops_text_u = {
.release = mon_text_release,
};
-int mon_text_add(struct mon_bus *mbus, int busnum)
+int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
{
struct dentry *d;
enum { NAMESZ = 10 };
char name[NAMESZ];
+ int busnum = ubus? ubus->busnum: 0;
int rc;
- rc = snprintf(name, NAMESZ, "%dt", busnum);
- if (rc <= 0 || rc >= NAMESZ)
- goto err_print_t;
- d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_t);
- if (d == NULL)
- goto err_create_t;
- mbus->dent_t = d;
+ if (ubus != NULL) {
+ rc = snprintf(name, NAMESZ, "%dt", busnum);
+ if (rc <= 0 || rc >= NAMESZ)
+ goto err_print_t;
+ d = debugfs_create_file(name, 0600, mon_dir, mbus,
+ &mon_fops_text_t);
+ if (d == NULL)
+ goto err_create_t;
+ mbus->dent_t = d;
+ }
rc = snprintf(name, NAMESZ, "%du", busnum);
if (rc <= 0 || rc >= NAMESZ)
@@ -694,8 +698,10 @@ err_print_s:
mbus->dent_u = NULL;
err_create_u:
err_print_u:
- debugfs_remove(mbus->dent_t);
- mbus->dent_t = NULL;
+ if (ubus != NULL) {
+ debugfs_remove(mbus->dent_t);
+ mbus->dent_t = NULL;
+ }
err_create_t:
err_print_t:
return 0;
@@ -704,7 +710,8 @@ err_print_t:
void mon_text_del(struct mon_bus *mbus)
{
debugfs_remove(mbus->dent_u);
- debugfs_remove(mbus->dent_t);
+ if (mbus->dent_t != NULL)
+ debugfs_remove(mbus->dent_t);
debugfs_remove(mbus->dent_s);
}
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index 13d63255283..f68ad6d99ad 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -20,9 +20,11 @@ struct mon_bus {
struct usb_bus *u_bus;
int text_inited;
+ int bin_inited;
struct dentry *dent_s; /* Debugging file */
struct dentry *dent_t; /* Text interface file */
struct dentry *dent_u; /* Second text interface file */
+ struct device *classdev; /* Device in usbmon class */
/* Ref */
int nreaders; /* Under mon_lock AND mbus->lock */
@@ -52,9 +54,10 @@ void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r);
struct mon_bus *mon_bus_lookup(unsigned int num);
-int /*bool*/ mon_text_add(struct mon_bus *mbus, int busnum);
+int /*bool*/ mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus);
void mon_text_del(struct mon_bus *mbus);
-// void mon_bin_add(struct mon_bus *);
+int /*bool*/ mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus);
+void mon_bin_del(struct mon_bus *mbus);
int __init mon_text_init(void);
void mon_text_exit(void);
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 3efe67092f1..43d6db696f9 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -464,6 +464,16 @@ config USB_SERIAL_PL2303
To compile this driver as a module, choose M here: the
module will be called pl2303.
+config USB_SERIAL_OTI6858
+ tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller (EXPERIMENTAL)"
+ depends on USB_SERIAL
+ help
+ Say Y here if you want to use the OTi-6858 single port USB to serial
+ converter device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called oti6858.
+
config USB_SERIAL_HP4X
tristate "USB HP4x Calculators support"
depends on USB_SERIAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 61166ad450e..07a976eca6b 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o
obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o
obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
obj-$(CONFIG_USB_SERIAL_OPTION) += option.o
+obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
index fbc8c27d5d9..1cd29cd6bd0 100644
--- a/drivers/usb/serial/aircable.c
+++ b/drivers/usb/serial/aircable.c
@@ -411,12 +411,13 @@ static int aircable_write(struct usb_serial_port *port,
static void aircable_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
+ int status = urb->status;
int result;
- dbg("%s - urb->status: %d", __FUNCTION__ , urb->status);
+ dbg("%s - urb status: %d", __FUNCTION__ , status);
/* This has been taken from cypress_m8.c cypress_write_int_callback */
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -425,14 +426,14 @@ static void aircable_write_bulk_callback(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
port->write_urb_busy = 0;
return;
default:
/* error in the urb, so we have to resubmit it */
dbg("%s - Overflow in write", __FUNCTION__);
dbg("%s - nonzero write bulk status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
port->write_urb->transfer_buffer_length = 1;
port->write_urb->dev = port->serial->dev;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
@@ -457,16 +458,17 @@ static void aircable_read_bulk_callback(struct urb *urb)
unsigned long no_packages, remaining, package_length, i;
int result, shift = 0;
unsigned char *temp;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - urb status = %d", __FUNCTION__, status);
if (!port->open_count) {
dbg("%s - port is closed, exiting.", __FUNCTION__);
return;
}
- if (urb->status == -EPROTO) {
+ if (status == -EPROTO) {
dbg("%s - caught -EPROTO, resubmitting the urb",
__FUNCTION__);
usb_fill_bulk_urb(port->read_urb, port->serial->dev,
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 39a49836259..cff6fd190a2 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -82,12 +82,13 @@ static void airprime_read_bulk_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
+ if (status) {
dbg("%s - nonzero read bulk status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
return;
}
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -109,6 +110,7 @@ static void airprime_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
struct airprime_private *priv = usb_get_serial_port_data(port);
+ int status = urb->status;
unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -116,9 +118,9 @@ static void airprime_write_bulk_callback(struct urb *urb)
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
- if (urb->status)
+ if (status)
dbg("%s - nonzero write bulk status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs;
spin_unlock_irqrestore(&priv->lock, flags);
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index fe437125f14..c9fd486c1c7 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -172,7 +172,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
dbg("%s - port %d", __FUNCTION__, port->number);
- if ((!port->tty) || (!port->tty->termios)) {
+ if (!port->tty || !port->tty->termios) {
dbg("%s - no tty structures", __FUNCTION__);
return;
}
@@ -188,16 +188,6 @@ static void ark3116_set_termios(struct usb_serial_port *port,
cflag = port->tty->termios->c_cflag;
- /* check that they really want us to change something: */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
- RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s - nothing to change...", __FUNCTION__);
- return;
- }
- }
-
buf = kmalloc(1, GFP_KERNEL);
if (!buf) {
dbg("error kmalloc");
@@ -220,7 +210,7 @@ static void ark3116_set_termios(struct usb_serial_port *port,
dbg("setting CS7");
break;
default:
- err("CSIZE was set but not CS5-CS8, using CS8!");
+ dbg("CSIZE was set but not CS5-CS8, using CS8!");
/* fall through */
case CS8:
config |= 0x03;
@@ -251,38 +241,33 @@ static void ark3116_set_termios(struct usb_serial_port *port,
}
/* set baudrate */
- baud = 0;
- switch (cflag & CBAUD) {
- case B0:
- err("can't set 0 baud, using 9600 instead");
+ baud = tty_get_baud_rate(port->tty);
+
+ switch (baud) {
+ case 75:
+ case 150:
+ case 300:
+ case 600:
+ case 1200:
+ case 1800:
+ case 2400:
+ case 4800:
+ case 9600:
+ case 19200:
+ case 38400:
+ case 57600:
+ case 115200:
+ case 230400:
+ case 460800:
break;
- case B75: baud = 75; break;
- case B150: baud = 150; break;
- case B300: baud = 300; break;
- case B600: baud = 600; break;
- case B1200: baud = 1200; break;
- case B1800: baud = 1800; break;
- case B2400: baud = 2400; break;
- case B4800: baud = 4800; break;
- case B9600: baud = 9600; break;
- case B19200: baud = 19200; break;
- case B38400: baud = 38400; break;
- case B57600: baud = 57600; break;
- case B115200: baud = 115200; break;
- case B230400: baud = 230400; break;
- case B460800: baud = 460800; break;
+ /* set 9600 as default (if given baudrate is invalid for example) */
default:
- dbg("does not support the baudrate requested (fix it)");
- break;
+ baud = 9600;
}
- /* set 9600 as default (if given baudrate is invalid for example) */
- if (baud == 0)
- baud = 9600;
-
/*
* found by try'n'error, be careful, maybe there are other options
- * for multiplicator etc!
+ * for multiplicator etc! (3.5 for example)
*/
if (baud == 460800)
/* strange, for 460800 the formula is wrong
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 3b800d277c4..e67ce25f751 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -255,9 +255,10 @@ static void belkin_sa_read_int_callback (struct urb *urb)
struct belkin_sa_private *priv;
unsigned char *data = urb->transfer_buffer;
int retval;
+ int status = urb->status;
unsigned long flags;
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -265,10 +266,12 @@ static void belkin_sa_read_int_callback (struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, status);
goto exit;
}
@@ -346,6 +349,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
unsigned long flags;
unsigned long control_state;
int bad_flow_control;
+ speed_t baud;
if ((!port->tty) || (!port->tty->termios)) {
dbg ("%s - no tty or termios structure", __FUNCTION__);
@@ -361,16 +365,8 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
bad_flow_control = priv->bad_flow_control;
spin_unlock_irqrestore(&priv->lock, flags);
- /* check that they really want us to change something */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s - nothing to change...", __FUNCTION__);
- return;
- }
- old_iflag = old_termios->c_iflag;
- old_cflag = old_termios->c_cflag;
- }
+ old_iflag = old_termios->c_iflag;
+ old_cflag = old_termios->c_cflag;
/* Set the baud rate */
if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
@@ -384,38 +380,30 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0)
err("Set RTS error");
}
+ }
- switch(cflag & CBAUD) {
- case B0: /* handled below */ break;
- case B300: urb_value = BELKIN_SA_BAUD(300); break;
- case B600: urb_value = BELKIN_SA_BAUD(600); break;
- case B1200: urb_value = BELKIN_SA_BAUD(1200); break;
- case B2400: urb_value = BELKIN_SA_BAUD(2400); break;
- case B4800: urb_value = BELKIN_SA_BAUD(4800); break;
- case B9600: urb_value = BELKIN_SA_BAUD(9600); break;
- case B19200: urb_value = BELKIN_SA_BAUD(19200); break;
- case B38400: urb_value = BELKIN_SA_BAUD(38400); break;
- case B57600: urb_value = BELKIN_SA_BAUD(57600); break;
- case B115200: urb_value = BELKIN_SA_BAUD(115200); break;
- case B230400: urb_value = BELKIN_SA_BAUD(230400); break;
- default: err("BELKIN USB Serial Adapter: unsupported baudrate request, using default of 9600");
- urb_value = BELKIN_SA_BAUD(9600); break;
- }
- if ((cflag & CBAUD) != B0 ) {
- if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
- err("Set baudrate error");
- } else {
- /* Disable flow control */
- if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
- err("Disable flowcontrol error");
-
- /* Drop RTS and DTR */
- control_state &= ~(TIOCM_DTR | TIOCM_RTS);
- if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
- err("DTR LOW error");
- if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
- err("RTS LOW error");
- }
+ baud = tty_get_baud_rate(port->tty);
+ urb_value = BELKIN_SA_BAUD(baud);
+ /* Clip to maximum speed */
+ if (urb_value == 0)
+ urb_value = 1;
+ /* Turn it back into a resulting real baud rate */
+ baud = BELKIN_SA_BAUD(urb_value);
+ /* FIXME: Once the tty updates are done then push this back to the tty */
+
+ if ((cflag & CBAUD) != B0 ) {
+ if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0)
+ err("Set baudrate error");
+ } else {
+ /* Disable flow control */
+ if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0)
+ err("Disable flowcontrol error");
+ /* Drop RTS and DTR */
+ control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0)
+ err("DTR LOW error");
+ if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0)
+ err("RTS LOW error");
}
/* set the parity */
@@ -435,7 +423,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios
case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break;
case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break;
case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break;
- default: err("CSIZE was not CS5-CS8, using default of 8");
+ default: dbg("CSIZE was not CS5-CS8, using default of 8");
urb_value = BELKIN_SA_DATA_BITS(8);
break;
}
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 4167753ed31..4353df92487 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -305,12 +305,13 @@ static void cyberjack_read_int_callback( struct urb *urb )
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
/* the urb might have been killed. */
- if (urb->status)
+ if (status)
return;
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
@@ -365,12 +366,14 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
unsigned char *data = urb->transfer_buffer;
short todo;
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
-
+
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -411,12 +414,14 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct cyberjack_private *priv = usb_get_serial_port_data(port);
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
port->write_urb_busy = 0;
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
return;
}
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 57b8e27285f..163386336a5 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -1275,10 +1275,11 @@ static void cypress_read_int_callback(struct urb *urb)
int bytes = 0;
int result;
int i = 0;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- switch (urb->status) {
+ switch (status) {
case 0: /* success */
break;
case -ECONNRESET:
@@ -1292,7 +1293,7 @@ static void cypress_read_int_callback(struct urb *urb)
default:
/* something ugly is going on... */
dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
- __FUNCTION__,urb->status);
+ __FUNCTION__, status);
cypress_set_dead(port);
return;
}
@@ -1419,10 +1420,11 @@ static void cypress_write_int_callback(struct urb *urb)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct cypress_private *priv = usb_get_serial_port_data(port);
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
-
- switch (urb->status) {
+
+ switch (status) {
case 0:
/* success */
break;
@@ -1430,7 +1432,8 @@ static void cypress_write_int_callback(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
priv->write_urb_in_use = 0;
return;
case -EPIPE: /* no break needed; clear halt and resubmit */
@@ -1438,7 +1441,8 @@ static void cypress_write_int_callback(struct urb *urb)
break;
usb_clear_halt(port->serial->dev, 0x02);
/* error in the urb, so we have to resubmit it */
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
port->interrupt_out_urb->transfer_buffer_length = 1;
port->interrupt_out_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
@@ -1450,7 +1454,7 @@ static void cypress_write_int_callback(struct urb *urb)
break;
default:
dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
- __FUNCTION__,urb->status);
+ __FUNCTION__, status);
cypress_set_dead(port);
break;
}
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index d78692c01cf..976f54ec26e 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -416,9 +416,6 @@ struct digi_port {
int dp_port_num;
int dp_out_buf_len;
unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
- int dp_in_buf_len;
- unsigned char dp_in_buf[DIGI_IN_BUF_SIZE];
- unsigned char dp_in_flag_buf[DIGI_IN_BUF_SIZE];
int dp_write_urb_in_use;
unsigned int dp_modem_signals;
wait_queue_head_t dp_modem_change_wait;
@@ -920,7 +917,6 @@ dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num );
spin_lock_irqsave( &priv->dp_port_lock, flags );
priv->dp_throttled = 1;
priv->dp_throttle_restart = 0;
- priv->dp_in_buf_len = 0;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
}
@@ -930,23 +926,16 @@ static void digi_rx_unthrottle( struct usb_serial_port *port )
{
int ret = 0;
- int len;
unsigned long flags;
struct digi_port *priv = usb_get_serial_port_data(port);
- struct tty_struct *tty = port->tty;
-
dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
spin_lock_irqsave( &priv->dp_port_lock, flags );
- /* send any buffered chars from throttle time on to tty subsystem */
-
- len = tty_buffer_request_room(tty, priv->dp_in_buf_len);
- if( len > 0 ) {
- tty_insert_flip_string_flags(tty, priv->dp_in_buf, priv->dp_in_flag_buf, len);
- tty_flip_buffer_push( tty );
- }
+ /* turn throttle off */
+ priv->dp_throttled = 0;
+ priv->dp_throttle_restart = 0;
/* restart read chain */
if( priv->dp_throttle_restart ) {
@@ -954,11 +943,6 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
ret = usb_submit_urb( port->read_urb, GFP_ATOMIC );
}
- /* turn throttle off */
- priv->dp_throttled = 0;
- priv->dp_in_buf_len = 0;
- priv->dp_throttle_restart = 0;
-
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
if( ret ) {
@@ -1340,19 +1324,21 @@ static void digi_write_bulk_callback( struct urb *urb )
struct digi_port *priv;
struct digi_serial *serial_priv;
int ret = 0;
+ int status = urb->status;
-dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
+ dbg("digi_write_bulk_callback: TOP, urb status=%d", status);
/* port and serial sanity check */
if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) {
- err("%s: port or port->private is NULL, status=%d", __FUNCTION__,
- urb->status );
+ err("%s: port or port->private is NULL, status=%d",
+ __FUNCTION__, status);
return;
}
serial = port->serial;
if( serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL ) {
- err("%s: serial or serial->private is NULL, status=%d", __FUNCTION__, urb->status );
+ err("%s: serial or serial->private is NULL, status=%d",
+ __FUNCTION__, status);
return;
}
@@ -1687,7 +1673,6 @@ dbg( "digi_startup: TOP" );
spin_lock_init( &priv->dp_port_lock );
priv->dp_port_num = i;
priv->dp_out_buf_len = 0;
- priv->dp_in_buf_len = 0;
priv->dp_write_urb_in_use = 0;
priv->dp_modem_signals = 0;
init_waitqueue_head( &priv->dp_modem_change_wait );
@@ -1757,25 +1742,28 @@ static void digi_read_bulk_callback( struct urb *urb )
struct digi_port *priv;
struct digi_serial *serial_priv;
int ret;
+ int status = urb->status;
dbg( "digi_read_bulk_callback: TOP" );
/* port sanity check, do not resubmit if port is not valid */
if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) {
- err("%s: port or port->private is NULL, status=%d", __FUNCTION__,
- urb->status );
+ err("%s: port or port->private is NULL, status=%d",
+ __FUNCTION__, status);
return;
}
if( port->serial == NULL
|| (serial_priv=usb_get_serial_data(port->serial)) == NULL ) {
- err("%s: serial is bad or serial->private is NULL, status=%d", __FUNCTION__, urb->status );
+ err("%s: serial is bad or serial->private is NULL, status=%d",
+ __FUNCTION__, status);
return;
}
/* do not resubmit urb if it has any status error */
- if( urb->status ) {
- err("%s: nonzero read bulk status: status=%d, port=%d", __FUNCTION__, urb->status, priv->dp_port_num );
+ if (status) {
+ err("%s: nonzero read bulk status: status=%d, port=%d",
+ __FUNCTION__, status, priv->dp_port_num);
return;
}
@@ -1816,10 +1804,11 @@ static int digi_read_inb_callback( struct urb *urb )
struct digi_port *priv = usb_get_serial_port_data(port);
int opcode = ((unsigned char *)urb->transfer_buffer)[0];
int len = ((unsigned char *)urb->transfer_buffer)[1];
- int status = ((unsigned char *)urb->transfer_buffer)[2];
+ int port_status = ((unsigned char *)urb->transfer_buffer)[2];
unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
int flag,throttled;
int i;
+ int status = urb->status;
/* do not process callbacks on closed ports */
/* but do continue the read chain */
@@ -1828,7 +1817,10 @@ static int digi_read_inb_callback( struct urb *urb )
/* short/multiple packet check */
if( urb->actual_length != len + 2 ) {
- err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", __FUNCTION__, urb->status, priv->dp_port_num, opcode, len, urb->actual_length, status );
+ err("%s: INCOMPLETE OR MULTIPLE PACKET, urb status=%d, "
+ "port=%d, opcode=%d, len=%d, actual_length=%d, "
+ "port_status=%d", __FUNCTION__, status, priv->dp_port_num,
+ opcode, len, urb->actual_length, port_status);
return( -1 );
}
@@ -1843,52 +1835,37 @@ static int digi_read_inb_callback( struct urb *urb )
/* receive data */
if( opcode == DIGI_CMD_RECEIVE_DATA ) {
- /* get flag from status */
+ /* get flag from port_status */
flag = 0;
/* overrun is special, not associated with a char */
- if( status & DIGI_OVERRUN_ERROR ) {
+ if (port_status & DIGI_OVERRUN_ERROR) {
tty_insert_flip_char( tty, 0, TTY_OVERRUN );
}
/* break takes precedence over parity, */
/* which takes precedence over framing errors */
- if( status & DIGI_BREAK_ERROR ) {
+ if (port_status & DIGI_BREAK_ERROR) {
flag = TTY_BREAK;
- } else if( status & DIGI_PARITY_ERROR ) {
+ } else if (port_status & DIGI_PARITY_ERROR) {
flag = TTY_PARITY;
- } else if( status & DIGI_FRAMING_ERROR ) {
+ } else if (port_status & DIGI_FRAMING_ERROR) {
flag = TTY_FRAME;
}
- /* data length is len-1 (one byte of len is status) */
+ /* data length is len-1 (one byte of len is port_status) */
--len;
- if( throttled ) {
-
- len = min( len,
- DIGI_IN_BUF_SIZE - priv->dp_in_buf_len );
-
- if( len > 0 ) {
- memcpy( priv->dp_in_buf + priv->dp_in_buf_len,
- data, len );
- memset( priv->dp_in_flag_buf
- + priv->dp_in_buf_len, flag, len );
- priv->dp_in_buf_len += len;
- }
-
- } else {
- len = tty_buffer_request_room(tty, len);
- if( len > 0 ) {
- /* Hot path */
- if(flag == TTY_NORMAL)
- tty_insert_flip_string(tty, data, len);
- else {
- for(i = 0; i < len; i++)
- tty_insert_flip_char(tty, data[i], flag);
- }
- tty_flip_buffer_push( tty );
+ len = tty_buffer_request_room(tty, len);
+ if( len > 0 ) {
+ /* Hot path */
+ if(flag == TTY_NORMAL)
+ tty_insert_flip_string(tty, data, len);
+ else {
+ for(i = 0; i < len; i++)
+ tty_insert_flip_char(tty, data[i], flag);
}
+ tty_flip_buffer_push( tty );
}
}
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 4703c8f8538..050fcc996f5 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -326,12 +326,14 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port)
static void empeg_write_bulk_callback (struct urb *urb)
{
- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial_port *port = urb->context;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -345,11 +347,13 @@ static void empeg_read_bulk_callback (struct urb *urb)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
return;
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 2353679f601..7b1673a4407 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -271,26 +271,58 @@ static int debug;
static __u16 vendor = FTDI_VID;
static __u16 product;
+struct ftdi_private {
+ ftdi_chip_type_t chip_type;
+ /* type of the device, either SIO or FT8U232AM */
+ int baud_base; /* baud base clock for divisor setting */
+ int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
+ __u16 last_set_data_urb_value ;
+ /* the last data state set - needed for doing a break */
+ int write_offset; /* This is the offset in the usb data block to write the serial data -
+ * it is different between devices
+ */
+ int flags; /* some ASYNC_xxxx flags are supported */
+ unsigned long last_dtr_rts; /* saved modem control outputs */
+ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
+ char prev_status, diff_status; /* Used for TIOCMIWAIT */
+ __u8 rx_flags; /* receive state flags (throttling) */
+ spinlock_t rx_lock; /* spinlock for receive state */
+ struct delayed_work rx_work;
+ struct usb_serial_port *port;
+ int rx_processed;
+ unsigned long rx_bytes;
+
+ __u16 interface; /* FT2232C port interface (0 for FT232/245) */
+
+ int force_baud; /* if non-zero, force the baud rate to this value */
+ int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
+
+ spinlock_t tx_lock; /* spinlock for transmit state */
+ unsigned long tx_bytes;
+ unsigned long tx_outstanding_bytes;
+ unsigned long tx_outstanding_urbs;
+};
+
/* struct ftdi_sio_quirk is used by devices requiring special attention. */
struct ftdi_sio_quirk {
int (*probe)(struct usb_serial *);
- void (*setup)(struct usb_serial *); /* Special settings during startup. */
+ void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */
};
static int ftdi_olimex_probe (struct usb_serial *serial);
-static void ftdi_USB_UIRT_setup (struct usb_serial *serial);
-static void ftdi_HE_TIRA1_setup (struct usb_serial *serial);
+static void ftdi_USB_UIRT_setup (struct ftdi_private *priv);
+static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv);
static struct ftdi_sio_quirk ftdi_olimex_quirk = {
.probe = ftdi_olimex_probe,
};
static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
- .setup = ftdi_USB_UIRT_setup,
+ .port_probe = ftdi_USB_UIRT_setup,
};
static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
- .setup = ftdi_HE_TIRA1_setup,
+ .port_probe = ftdi_HE_TIRA1_setup,
};
/*
@@ -317,6 +349,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IPLUS2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DMX4ALL) },
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
@@ -566,38 +599,6 @@ static const char *ftdi_chip_name[] = {
#define THROTTLED 0x01
#define ACTUALLY_THROTTLED 0x02
-struct ftdi_private {
- ftdi_chip_type_t chip_type;
- /* type of the device, either SIO or FT8U232AM */
- int baud_base; /* baud base clock for divisor setting */
- int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */
- __u16 last_set_data_urb_value ;
- /* the last data state set - needed for doing a break */
- int write_offset; /* This is the offset in the usb data block to write the serial data -
- * it is different between devices
- */
- int flags; /* some ASYNC_xxxx flags are supported */
- unsigned long last_dtr_rts; /* saved modem control outputs */
- wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
- char prev_status, diff_status; /* Used for TIOCMIWAIT */
- __u8 rx_flags; /* receive state flags (throttling) */
- spinlock_t rx_lock; /* spinlock for receive state */
- struct delayed_work rx_work;
- struct usb_serial_port *port;
- int rx_processed;
- unsigned long rx_bytes;
-
- __u16 interface; /* FT2232C port interface (0 for FT232/245) */
-
- int force_baud; /* if non-zero, force the baud rate to this value */
- int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */
-
- spinlock_t tx_lock; /* spinlock for transmit state */
- unsigned long tx_bytes;
- unsigned long tx_outstanding_bytes;
- unsigned long tx_outstanding_urbs;
-};
-
/* Used for TIOCMIWAIT */
#define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)
#define FTDI_STATUS_B1_MASK (FTDI_RS_BI)
@@ -608,7 +609,6 @@ struct ftdi_private {
/* function prototypes for a FTDI serial converter */
static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id);
-static int ftdi_sio_attach (struct usb_serial *serial);
static void ftdi_shutdown (struct usb_serial *serial);
static int ftdi_sio_port_probe (struct usb_serial_port *port);
static int ftdi_sio_port_remove (struct usb_serial_port *port);
@@ -662,7 +662,6 @@ static struct usb_serial_driver ftdi_sio_device = {
.ioctl = ftdi_ioctl,
.set_termios = ftdi_set_termios,
.break_ctl = ftdi_break_ctl,
- .attach = ftdi_sio_attach,
.shutdown = ftdi_shutdown,
};
@@ -1148,7 +1147,9 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
retval = device_create_file(&port->dev, &dev_attr_event_char);
if ((!retval) &&
- (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
+ (priv->chip_type == FT232BM ||
+ priv->chip_type == FT2232C ||
+ priv->chip_type == FT232RL)) {
retval = device_create_file(&port->dev,
&dev_attr_latency_timer);
}
@@ -1197,6 +1198,8 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id
static int ftdi_sio_port_probe(struct usb_serial_port *port)
{
struct ftdi_private *priv;
+ struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
+
dbg("%s",__FUNCTION__);
@@ -1213,6 +1216,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
than queue a task to deliver them */
priv->flags = ASYNC_LOW_LATENCY;
+ if (quirk && quirk->port_probe)
+ quirk->port_probe(priv);
+
/* Increase the size of read buffers */
kfree(port->bulk_in_buffer);
port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL);
@@ -1243,29 +1249,13 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
return 0;
}
-/* attach subroutine */
-static int ftdi_sio_attach (struct usb_serial *serial)
-{
- /* Check for device requiring special set up. */
- struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial);
-
- if (quirk && quirk->setup)
- quirk->setup(serial);
-
- return 0;
-} /* ftdi_sio_attach */
-
-
/* Setup for the USB-UIRT device, which requires hardwired
* baudrate (38400 gets mapped to 312500) */
/* Called from usbserial:serial_probe */
-static void ftdi_USB_UIRT_setup (struct usb_serial *serial)
+static void ftdi_USB_UIRT_setup (struct ftdi_private *priv)
{
- struct ftdi_private *priv;
-
dbg("%s",__FUNCTION__);
- priv = usb_get_serial_port_data(serial->port[0]);
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 77;
priv->force_baud = B38400;
@@ -1273,13 +1263,10 @@ static void ftdi_USB_UIRT_setup (struct usb_serial *serial)
/* Setup for the HE-TIRA1 device, which requires hardwired
* baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */
-static void ftdi_HE_TIRA1_setup (struct usb_serial *serial)
+static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv)
{
- struct ftdi_private *priv;
-
dbg("%s",__FUNCTION__);
- priv = usb_get_serial_port_data(serial->port[0]);
priv->flags |= ASYNC_SPD_CUST;
priv->custom_divisor = 240;
priv->force_baud = B38400;
@@ -1573,14 +1560,15 @@ static void ftdi_write_bulk_callback (struct urb *urb)
struct ftdi_private *priv;
int data_offset; /* will be 1 for the SIO and 0 otherwise */
unsigned long countback;
+ int status = urb->status;
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("nonzero write bulk status received: %d", urb->status);
+ if (status) {
+ dbg("nonzero write bulk status received: %d", status);
return;
}
@@ -1656,6 +1644,7 @@ static void ftdi_read_bulk_callback (struct urb *urb)
struct ftdi_private *priv;
unsigned long countread;
unsigned long flags;
+ int status = urb->status;
if (urb->number_of_packets > 0) {
err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__,
@@ -1684,9 +1673,10 @@ static void ftdi_read_bulk_callback (struct urb *urb)
err("%s - Not my urb!", __FUNCTION__);
}
- if (urb->status) {
+ if (status) {
/* This will happen at close every time so it is a dbg not an err */
- dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status);
+ dbg("(this is ok on close) nonzero read bulk status received: "
+ "%d", status);
return;
}
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 33aee904724..d9e49716db1 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -56,6 +56,7 @@
/* iPlus device */
#define FTDI_IPLUS_PID 0xD070 /* Product Id */
+#define FTDI_IPLUS2_PID 0xD071 /* Product Id */
/* DMX4ALL DMX Interfaces */
#define FTDI_DMX4ALL 0xC850
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 74660a3aa67..04bd3b7a298 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1036,15 +1036,16 @@ static void garmin_write_bulk_callback (struct urb *urb)
unsigned long flags;
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ int status = urb->status;
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
+ if (status) {
dbg("%s - nonzero write bulk status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
@@ -1281,7 +1282,8 @@ static void garmin_read_bulk_callback (struct urb *urb)
struct usb_serial *serial = port->serial;
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
- int status;
+ int status = urb->status;
+ int retval;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1290,9 +1292,9 @@ static void garmin_read_bulk_callback (struct urb *urb)
return;
}
- if (urb->status) {
+ if (status) {
dbg("%s - nonzero read bulk status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
return;
}
@@ -1306,19 +1308,19 @@ static void garmin_read_bulk_callback (struct urb *urb)
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART;
spin_unlock_irqrestore(&garmin_data_p->lock, flags);
- status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (status)
+ retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (retval)
dev_err(&port->dev,
"%s - failed resubmitting read urb, error %d\n",
- __FUNCTION__, status);
+ __FUNCTION__, retval);
} else if (urb->actual_length > 0) {
/* Continue trying to read until nothing more is received */
if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
- status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (status)
+ retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (retval)
dev_err(&port->dev,
- "%s - failed resubmitting read urb, error %d\n",
- __FUNCTION__, status);
+ "%s - failed resubmitting read urb, "
+ "error %d\n", __FUNCTION__, retval);
}
} else {
dbg("%s - end of bulk data", __FUNCTION__);
@@ -1333,13 +1335,14 @@ static void garmin_read_bulk_callback (struct urb *urb)
static void garmin_read_int_callback (struct urb *urb)
{
unsigned long flags;
- int status;
+ int retval;
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = port->serial;
struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -1348,11 +1351,11 @@ static void garmin_read_int_callback (struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
return;
default:
dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
return;
}
@@ -1374,11 +1377,11 @@ static void garmin_read_int_callback (struct urb *urb)
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
garmin_read_bulk_callback, port);
- status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (status) {
+ retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (retval) {
dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n",
- __FUNCTION__, status);
+ __FUNCTION__, retval);
} else {
spin_lock_irqsave(&garmin_data_p->lock, flags);
garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
@@ -1422,11 +1425,11 @@ static void garmin_read_int_callback (struct urb *urb)
}
port->interrupt_in_urb->dev = port->serial->dev;
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status)
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
dev_err(&urb->dev->dev,
"%s - Error %d submitting interrupt urb\n",
- __FUNCTION__, status);
+ __FUNCTION__, retval);
}
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4f8282ad772..88a2c7dce33 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -69,6 +69,7 @@ struct usb_serial_driver usb_serial_generic_device = {
.shutdown = usb_serial_generic_shutdown,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
+ .resume = usb_serial_generic_resume,
};
static int generic_probe(struct usb_interface *interface,
@@ -169,6 +170,23 @@ static void generic_cleanup (struct usb_serial_port *port)
}
}
+int usb_serial_generic_resume(struct usb_serial *serial)
+{
+ struct usb_serial_port *port;
+ int i, c = 0, r;
+
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+ if (port->open_count && port->read_urb) {
+ r = usb_submit_urb(port->read_urb, GFP_NOIO);
+ if (r < 0)
+ c++;
+ }
+ }
+
+ return c ? -EIO : 0;
+}
+
void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp)
{
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -263,79 +281,82 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
return (chars);
}
-/* Push data to tty layer and resubmit the bulk read URB */
-static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+
+static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
{
- struct usb_serial *serial = port->serial;
struct urb *urb = port->read_urb;
- struct tty_struct *tty = port->tty;
+ struct usb_serial *serial = port->serial;
int result;
- /* Push data to tty */
- if (tty && urb->actual_length) {
- tty_buffer_request_room(tty, urb->actual_length);
- tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
- tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
- }
-
/* Continue reading from device */
- usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_fill_bulk_urb (urb, serial->dev,
usb_rcvbulkpipe (serial->dev,
port->bulk_in_endpointAddress),
- port->read_urb->transfer_buffer,
- port->read_urb->transfer_buffer_length,
+ urb->transfer_buffer,
+ urb->transfer_buffer_length,
((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback :
usb_serial_generic_read_bulk_callback), port);
- result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ result = usb_submit_urb(urb, mem_flags);
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
+/* Push data to tty layer and resubmit the bulk read URB */
+static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
+{
+ struct urb *urb = port->read_urb;
+ struct tty_struct *tty = port->tty;
+ int room;
+
+ /* Push data to tty */
+ if (tty && urb->actual_length) {
+ room = tty_buffer_request_room(tty, urb->actual_length);
+ if (room) {
+ tty_insert_flip_string(tty, urb->transfer_buffer, room);
+ tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
+ }
+ }
+
+ resubmit_read_urb(port, GFP_ATOMIC);
+}
+
void usb_serial_generic_read_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
unsigned char *data = urb->transfer_buffer;
- int is_throttled;
- unsigned long flags;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (unlikely(status != 0)) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
return;
}
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
/* Throttle the device if requested by tty */
- if (urb->actual_length) {
- spin_lock_irqsave(&port->lock, flags);
- is_throttled = port->throttled = port->throttle_req;
- spin_unlock_irqrestore(&port->lock, flags);
- if (is_throttled) {
- /* Let the received data linger in the read URB;
- * usb_serial_generic_unthrottle() will pick it
- * up later. */
- dbg("%s - throttling device", __FUNCTION__);
- return;
- }
- }
-
- /* Handle data and continue reading from device */
- flush_and_resubmit_read_urb(port);
+ spin_lock(&port->lock);
+ if (!(port->throttled = port->throttle_req))
+ /* Handle data and continue reading from device */
+ flush_and_resubmit_read_urb(port);
+ spin_unlock(&port->lock);
}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
void usb_serial_generic_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
port->write_urb_busy = 0;
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -370,8 +391,8 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port)
spin_unlock_irqrestore(&port->lock, flags);
if (was_throttled) {
- /* Handle pending data and resume reading from device */
- flush_and_resubmit_read_urb(port);
+ /* Resume reading from device */
+ resubmit_read_urb(port, GFP_KERNEL);
}
}
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 4807f960150..dd42f57089f 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -599,10 +599,11 @@ static void edge_interrupt_callback (struct urb *urb)
int txCredits;
int portNumber;
int result;
+ int status = urb->status;
dbg("%s", __FUNCTION__);
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -610,10 +611,12 @@ static void edge_interrupt_callback (struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, status);
goto exit;
}
@@ -688,13 +691,15 @@ static void edge_bulk_in_callback (struct urb *urb)
{
struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
unsigned char *data = urb->transfer_buffer;
- int status;
+ int retval;
__u16 raw_data_length;
+ int status = urb->status;
dbg("%s", __FUNCTION__);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
edge_serial->read_in_progress = false;
return;
}
@@ -722,9 +727,11 @@ static void edge_bulk_in_callback (struct urb *urb)
if (edge_serial->rxBytesAvail > 0) {
dbg("%s - posting a read", __FUNCTION__);
edge_serial->read_urb->dev = edge_serial->serial->dev;
- status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
- if (status) {
- dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status);
+ retval = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
+ if (retval) {
+ dev_err(&urb->dev->dev,
+ "%s - usb_submit_urb(read bulk) failed, "
+ "retval = %d\n", __FUNCTION__, retval);
edge_serial->read_in_progress = false;
}
} else {
@@ -744,11 +751,13 @@ static void edge_bulk_out_data_callback (struct urb *urb)
{
struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
struct tty_struct *tty;
+ int status = urb->status;
dbg("%s", __FUNCTION__);
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
}
tty = edge_port->port->tty;
@@ -1504,15 +1513,6 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
}
cflag = tty->termios->c_cflag;
- /* check that they really want us to change something */
- if (old_termios) {
- if (cflag == old_termios->c_cflag &&
- tty->termios->c_iflag == old_termios->c_iflag) {
- dbg("%s - nothing to change", __FUNCTION__);
- return;
- }
- }
-
dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
tty->termios->c_cflag, tty->termios->c_iflag);
if (old_termios) {
@@ -3046,11 +3046,11 @@ static void edge_shutdown (struct usb_serial *serial)
}
/* free up our endpoint stuff */
if (edge_serial->is_epic) {
- usb_unlink_urb(edge_serial->interrupt_read_urb);
+ usb_kill_urb(edge_serial->interrupt_read_urb);
usb_free_urb(edge_serial->interrupt_read_urb);
kfree(edge_serial->interrupt_in_buffer);
- usb_unlink_urb(edge_serial->read_urb);
+ usb_kill_urb(edge_serial->read_urb);
usb_free_urb(edge_serial->read_urb);
kfree(edge_serial->bulk_in_buffer);
}
diff --git a/drivers/usb/serial/io_fw_down3.h b/drivers/usb/serial/io_fw_down3.h
index 93b56d68a27..4496b068c50 100644
--- a/drivers/usb/serial/io_fw_down3.h
+++ b/drivers/usb/serial/io_fw_down3.h
@@ -5,7 +5,7 @@
//**************************************************************
-static int IMAGE_SIZE = 12749;
+static int IMAGE_SIZE = 12938;
struct EDGE_FIRMWARE_VERSION_INFO
{
@@ -16,7 +16,7 @@ struct EDGE_FIRMWARE_VERSION_INFO
static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME =
{
- 4, 10, 0 // Major, Minor, Build
+ 4, 80, 0 // Major, Minor, Build
};
@@ -27,16 +27,16 @@ static unsigned char IMAGE_ARRAY_NAME[] =
// WORD Length;
// BYTE CheckSum;
// };
-0xca, 0x31,
-0xa8,
+0x87, 0x32,
+0x9a,
-0x02, 0x26, 0xfe, 0x02, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00,
+0x02, 0x27, 0xbf, 0x02, 0x21, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f,
0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00,
0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e,
0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75,
0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81,
-0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x94, 0xe6, 0xf0, 0x08, 0xa3, 0xd9,
+0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0xdc, 0xe6, 0xf0, 0x08, 0xa3, 0xd9,
0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e,
0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86,
0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83,
@@ -49,387 +49,398 @@ static unsigned char IMAGE_ARRAY_NAME[] =
0xc9, 0xf0, 0x69, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0, 0xca, 0xf0, 0x6a, 0x60, 0x02, 0x7e, 0x04,
0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0,
0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05,
-0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03,
-0x02, 0x11, 0x94, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xaf, 0xf5, 0x82, 0x74, 0xfa, 0xf5,
-0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c,
-0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20,
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27,
-0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82,
-0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c,
-0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25,
-0xb4, 0x02, 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27,
-0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82,
-0x80, 0x03, 0x02, 0x02, 0x62, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04,
-0xf1, 0x20, 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0,
-0x14, 0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62,
-0x7e, 0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x33, 0x12, 0x00, 0xc9, 0xee,
-0x64, 0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64,
-0x02, 0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x33, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02,
-0x33, 0x7c, 0x0a, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0,
-0xa3, 0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0,
-0x80, 0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0,
-0xd2, 0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6,
-0x60, 0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d,
-0x60, 0x13, 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11,
-0x0f, 0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0,
-0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32,
-0x90, 0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa,
-0xec, 0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e,
-0x01, 0x7f, 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec,
-0xff, 0xea, 0x90, 0xfa, 0xba, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0x30, 0xe4, 0xf5, 0x4d, 0xe5,
-0x4d, 0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0x11, 0xe4, 0x12, 0x1a, 0x38, 0x05, 0x4d, 0x04,
-0x12, 0x1c, 0x02, 0x80, 0xea, 0x12, 0x1c, 0x30, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24,
-0xc0, 0x70, 0x03, 0x02, 0x08, 0xc5, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6,
-0xe0, 0xfe, 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a,
-0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0x4c, 0x03, 0x56, 0x00, 0x04, 0x29, 0x01, 0x05, 0x3c, 0x03,
-0x06, 0x03, 0x05, 0x06, 0x45, 0x06, 0x07, 0xa7, 0x08, 0x07, 0xef, 0x09, 0x08, 0x4b, 0x0a, 0x08,
-0x8b, 0x0b, 0x00, 0x00, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa,
-0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x02, 0x45,
-0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24,
-0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x11, 0x74,
-0x01, 0x12, 0x1a, 0x38, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0x11, 0x74, 0x02, 0x12,
-0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb6, 0xe0,
-0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f,
-0x26, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb6, 0xe0, 0xff,
-0x60, 0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f,
-0x26, 0xe5, 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0x0e, 0x12, 0x1a,
-0x38, 0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 0x38, 0x80, 0x19, 0x15, 0x4d,
-0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x80, 0x09, 0x12, 0x1c,
-0xb3, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x12, 0x1c, 0x11, 0x12, 0x19, 0xf2, 0x60, 0x05, 0x74,
-0x01, 0x12, 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f,
-0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x14, 0x60, 0x2d,
-0x14, 0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x04,
-0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02,
-0x0f, 0x26, 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20,
-0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb6,
-0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb6, 0xe0, 0xd3,
-0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0,
-0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f,
-0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0,
-0x07, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0,
-0x54, 0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60,
-0x20, 0x24, 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33,
-0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80,
-0x1d, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x0e,
-0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0x32, 0x15, 0x4d,
-0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1c,
-0xb3, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7,
-0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9,
-0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba,
-0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0,
-0x60, 0x03, 0x02, 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1,
-0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x07,
-0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94,
-0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 0x70,
-0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x12, 0x31, 0x82,
-0x40, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26,
-0xe5, 0x4d, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1d, 0x64, 0x02, 0x1d, 0x2f, 0xe5, 0x35, 0x20,
-0xe1, 0x03, 0x02, 0x0f, 0x26, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0,
-0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x1c, 0xb3, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff,
-0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60,
-0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9,
-0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xbb,
-0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe,
-0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45,
-0x3b, 0x70, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa,
-0xba, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02,
-0x60, 0x03, 0x02, 0x0f, 0x26, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x30, 0x12, 0x1d,
-0x5d, 0x7d, 0x03, 0x12, 0x0f, 0x6d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa,
-0xb3, 0xe0, 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b,
-0xaf, 0x3c, 0x02, 0x0f, 0xba, 0x12, 0x1c, 0x30, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x0d, 0x12,
-0x1d, 0x5d, 0x7d, 0x14, 0x12, 0x0f, 0x6d, 0x60, 0x10, 0x02, 0x0f, 0x26, 0x12, 0x1d, 0x5d, 0x7d,
-0x04, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 0xb3, 0xe0,
-0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c,
-0x02, 0x0f, 0xba, 0x12, 0x1d, 0x5d, 0x7d, 0x05, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26,
-0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x12, 0x1c, 0x78, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa,
-0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb2, 0xf0,
-0xe4, 0xf5, 0x4c, 0x90, 0xfa, 0xb2, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1c,
-0x72, 0x12, 0x0f, 0xcc, 0xff, 0xfd, 0x90, 0xfa, 0xb4, 0xe4, 0x8d, 0xf0, 0x12, 0x1a, 0x6c, 0x90,
-0xfa, 0xb3, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x26, 0x05, 0x4c,
-0x80, 0xd1, 0x12, 0x1c, 0x72, 0x12, 0x0f, 0xcc, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb3, 0xf0, 0xfd,
-0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0x7a, 0xf9, 0x79, 0x6f, 0x7b, 0x01, 0x8b, 0x36,
-0x8a, 0x37, 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1c, 0x78, 0x12, 0x25,
-0xd7, 0x8f, 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0x11, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x12,
-0x1c, 0x11, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0x4a, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef,
-0x95, 0x3c, 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f,
-0x3a, 0x02, 0x2c, 0x07, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5,
-0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03,
-0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26,
-0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03,
-0x02, 0x0f, 0x26, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xa9, 0xe5,
-0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26,
-0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 0xe0, 0x94, 0x01,
-0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03,
-0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa,
-0xbb, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06,
-0x53, 0x35, 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03,
-0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa,
-0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60,
-0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35,
-0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x7f, 0x01, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03,
-0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb,
-0xe0, 0x94, 0x00, 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c,
-0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26,
-0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xff, 0x01, 0x12, 0x1d, 0x74, 0xef, 0x12, 0x1a, 0x38, 0x90,
-0xfa, 0xb6, 0x12, 0x1d, 0x74, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0x4a, 0x90, 0x00, 0x02, 0xe4,
-0x12, 0x1a, 0x4a, 0x74, 0x03, 0x12, 0x1c, 0x02, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0xa3, 0xe0, 0x85,
-0x38, 0x82, 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b,
-0x4c, 0x09, 0x4a, 0x02, 0x09, 0x6c, 0x04, 0x09, 0x8e, 0x05, 0x09, 0xba, 0x06, 0x09, 0xd8, 0x07,
-0x09, 0xf6, 0x08, 0x0a, 0x14, 0x09, 0x0a, 0x32, 0x0b, 0x0a, 0xe7, 0x80, 0x0d, 0x6f, 0x81, 0x0d,
-0xa0, 0x82, 0x0b, 0x2e, 0x83, 0x0b, 0x77, 0x84, 0x0b, 0x96, 0x85, 0x0b, 0xdb, 0x86, 0x0c, 0x26,
-0x87, 0x0c, 0xb7, 0x88, 0x0d, 0x42, 0x89, 0x0a, 0x50, 0x92, 0x0a, 0x50, 0x93, 0x0e, 0x53, 0xc0,
-0x0e, 0x7f, 0xc1, 0x0e, 0x90, 0xc2, 0x00, 0x00, 0x0f, 0x15, 0xe5, 0x35, 0x20, 0xe7, 0x05, 0x7f,
-0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00,
-0x7f, 0x07, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 0x20, 0xe7,
-0x05, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd,
-0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35,
-0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1d, 0x92, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, 0x70,
-0x05, 0x7f, 0x02, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, 0x02,
-0x80, 0x03, 0x02, 0x31, 0x6f, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02,
-0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x08,
-0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29,
-0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, 0x11,
-0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c,
-0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x16, 0x7f,
-0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60,
-0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02,
-0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04,
-0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec,
-0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1c, 0xc9, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c,
-0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75,
-0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1b, 0x72, 0x12,
-0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x05, 0x12, 0x31, 0xbd,
-0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38,
-0x72, 0x02, 0x2c, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0x18, 0x12, 0x1c, 0xc9, 0x60, 0x05,
-0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1d, 0x92, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x30, 0xec, 0x90,
-0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5,
-0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5,
-0x4c, 0x12, 0x1b, 0x72, 0x02, 0x31, 0x6f, 0x12, 0x1d, 0x9c, 0x12, 0x2a, 0x06, 0x12, 0x1c, 0x83,
-0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x78, 0x68, 0x12, 0x1b,
-0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a,
-0x4a, 0x90, 0xfa, 0xb7, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, 0x8c,
-0x83, 0x12, 0x1c, 0x8b, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa,
-0xb6, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3,
-0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbb, 0xe0, 0x42,
-0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 0xe0,
-0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 0xb0,
-0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0xb4, 0x01,
-0x0a, 0x12, 0x1c, 0x11, 0xe5, 0x90, 0x12, 0x1a, 0x38, 0x80, 0x08, 0x12, 0x1c, 0x11, 0xe5, 0xb0,
-0x12, 0x1a, 0x38, 0x02, 0x0f, 0xa9, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0x12, 0x12, 0x1c, 0x41,
-0x20, 0xe1, 0x33, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa,
-0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1d, 0xa6,
-0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0,
-0x80, 0x04, 0x12, 0x1d, 0xad, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0xff,
-0x24, 0x12, 0x12, 0x1c, 0x41, 0x20, 0xe1, 0x39, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x1b,
-0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0,
-0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb7, 0xe0, 0x60,
-0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf,
-0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x12, 0x1c, 0xc1, 0x60, 0x4d, 0x04, 0x60,
-0x03, 0x02, 0x0c, 0xb2, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, 0x3a,
-0x30, 0xe1, 0x6f, 0x12, 0x1d, 0x7c, 0x02, 0x0c, 0xb2, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, 0x12,
-0x1c, 0x3d, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1d, 0x7c, 0x80,
-0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1d, 0x7c,
-0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xb7, 0xe0, 0x60,
-0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0x3a, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02,
-0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0x3d, 0x30, 0xe1, 0x13, 0x30,
-0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54,
-0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc,
-0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, 0x44,
-0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90,
-0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, 0x44,
-0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, 0xf0,
-0x80, 0x3b, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, 0xa3,
-0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, 0xef,
-0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, 0xc2,
-0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02,
-0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, 0x16,
-0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x80, 0x0a, 0x90, 0xff, 0xb6, 0xe0,
-0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0x07, 0xe4,
-0xff, 0x12, 0x30, 0xec, 0x12, 0x1d, 0x37, 0x7f, 0x03, 0x12, 0x12, 0x19, 0x90, 0xf9, 0x15, 0xe0,
-0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54,
-0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, 0x16, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd,
-0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbc, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa,
-0xb4, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa,
-0xb9, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa,
-0xb9, 0xf0, 0x12, 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x73, 0x12, 0x1c, 0x4a, 0x90, 0xfa,
-0xbc, 0x12, 0x1d, 0x56, 0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90,
-0xfa, 0xb9, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x12,
-0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, 0x12, 0x1c, 0x4a, 0x80, 0xd1, 0x75, 0x4c, 0x02,
-0x90, 0xfa, 0xbc, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb4, 0xe4, 0xf0, 0xa3, 0x74, 0x0f,
-0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, 0xfa, 0xbd, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c,
-0x00, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4,
-0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31,
-0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x64, 0xf0,
-0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb7, 0xe0, 0x54, 0x0f, 0x90,
-0xf9, 0x63, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12,
-0x1d, 0x9c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x30, 0xec,
-0x12, 0x1c, 0xd0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03,
-0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 0x12, 0x1d, 0xa6, 0x12, 0x0f, 0x78,
-0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x78, 0xff,
-0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 0x1d, 0xa6, 0xf0, 0x90, 0xfa, 0xb7,
-0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60,
-0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1d, 0xad,
-0x12, 0x0f, 0x98, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12,
-0x0f, 0x98, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1d, 0xad, 0xf0,
-0xe4, 0xff, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f,
-0x18, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x31, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3,
-0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90,
-0xfa, 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22,
-0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, 0xb4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa,
-0xb9, 0xe0, 0xf5, 0x4a, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x22, 0xa0,
-0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff,
-0xa6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x12, 0x25, 0xd7, 0x8f, 0x4c, 0x7e, 0x00,
-0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff,
-0xb6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02,
-0x2c, 0x07, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x02, 0x31, 0x82, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c,
-0x07, 0x12, 0x22, 0xa0, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x25,
-0xd7, 0x90, 0xfa, 0xb1, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf,
-0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94,
-0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd,
-0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24,
-0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 0x10, 0x78, 0x7f, 0x00, 0x7e, 0x00,
-0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83,
-0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3,
-0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0,
-0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0,
-0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x12, 0x11, 0x0f, 0xd0, 0x05, 0xd0,
-0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70,
-0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x66,
-0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10,
-0x78, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0,
-0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80,
-0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0,
-0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83,
-0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6,
-0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08,
-0xee, 0x12, 0x11, 0x0f, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75,
-0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24,
-0xe8, 0x50, 0x05, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xef, 0x60, 0x31, 0x90, 0x30, 0x54, 0xe4, 0x93,
-0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x10, 0x78, 0xd0, 0x04, 0x43, 0x07, 0x80,
-0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef,
-0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x43, 0x12, 0x11, 0x0f, 0xd0, 0x83, 0xd0, 0x82,
-0xd0, 0xf0, 0x22, 0x02, 0x11, 0x94, 0xc0, 0x04, 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04,
-0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00,
-0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00,
-0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90,
-0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1,
-0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc,
-0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0xd2, 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12,
-0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc,
-0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee,
-0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc,
-0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f,
-0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0,
-0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6,
-0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0x66, 0x80,
-0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5,
-0x12, 0x11, 0x66, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00,
-0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24,
-0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78,
-0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x36, 0xf5, 0x82,
-0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0,
-0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04,
-0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43,
-0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90,
-0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x30, 0x54, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8,
-0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75,
-0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf,
-0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79,
-0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08,
-0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x12, 0x41, 0xad, 0x07, 0xaf, 0x02,
-0x12, 0x12, 0x58, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x11, 0x66, 0x80, 0xc1, 0x8f,
-0x24, 0x12, 0x2a, 0x06, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12,
-0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xed, 0xf0,
-0x12, 0x22, 0x56, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x12, 0x22, 0x99, 0x24, 0x09, 0x12,
-0x21, 0xf3, 0xef, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0x09, 0xc0,
-0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15,
-0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x80, 0x12, 0x22, 0x09,
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x21,
-0xf3, 0xef, 0xf0, 0xed, 0x12, 0x22, 0x99, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xed, 0xf0, 0x12, 0x21,
-0xfb, 0xe0, 0xff, 0x30, 0xe7, 0x19, 0x12, 0x22, 0x6e, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x09, 0x12,
-0x21, 0xfb, 0xef, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x12, 0x21, 0xfb, 0xef, 0x54, 0xfd, 0xf0, 0x78,
-0x7e, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6,
-0xfd, 0x12, 0x22, 0x43, 0xa3, 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24,
-0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x31, 0x94, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x78, 0x80,
-0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x06, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x03, 0x43, 0x07,
-0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x22, 0x7a, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x42,
-0x07, 0x43, 0x07, 0x80, 0x12, 0x22, 0x8a, 0xf5, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12,
-0x22, 0x99, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0,
-0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 0x03, 0x43, 0x07, 0x20, 0xec,
-0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 0x12, 0x21, 0xfb, 0xe0, 0xfe,
-0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x69, 0x78, 0x80, 0x12, 0x22, 0x6f,
-0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x14, 0xa6, 0x00, 0x14, 0xda, 0x01, 0x14, 0xdf, 0x03,
-0x14, 0xda, 0x05, 0x14, 0xdf, 0x07, 0x14, 0xda, 0x09, 0x14, 0xdf, 0x0b, 0x14, 0xda, 0x0d, 0x14,
-0xdf, 0x0f, 0x00, 0x00, 0x14, 0xe7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x21, 0x90, 0xf9, 0x15, 0xe0,
-0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27,
-0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05,
-0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53,
-0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x22, 0x78, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xef,
-0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 0x54,
-0x03, 0x70, 0x03, 0x02, 0x15, 0xd7, 0xee, 0x20, 0xe1, 0x03, 0x02, 0x15, 0xd4, 0x12, 0x22, 0x6e,
-0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x15, 0x36, 0x00, 0x15, 0x6c, 0x01, 0x15, 0x6c, 0x03,
-0x15, 0xa0, 0x05, 0x15, 0xa0, 0x07, 0x15, 0x86, 0x09, 0x15, 0x86, 0x0b, 0x15, 0xba, 0x0d, 0x15,
-0xba, 0x0f, 0x00, 0x00, 0x15, 0xd7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x15, 0xe0,
-0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, 0x07, 0x7f, 0x02, 0x15, 0xd7, 0x43, 0x07, 0x80, 0x02,
-0x15, 0xd7, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30,
-0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03,
-0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf,
-0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44,
-0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37,
-0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff,
-0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90,
-0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43,
-0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x80, 0x12, 0x22, 0x3f, 0xe0, 0xfc, 0xa3, 0xe0,
-0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05,
-0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80,
-0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7,
-0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05,
-0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80,
-0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0x3f, 0xa3, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0x7f,
-0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74,
-0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc,
-0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x12, 0x18, 0xe2, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2,
-0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, 0xcc, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5,
-0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b,
-0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe5,
-0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64,
-0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5,
-0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16,
-0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x02, 0xf0, 0xa3,
-0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, 0x41, 0x12, 0x90, 0xf9, 0x15, 0xe0, 0x44,
-0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x15,
-0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60,
-0x05, 0xe5, 0x23, 0xb4, 0x43, 0x0c, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x80, 0xf0, 0xa3, 0xe0, 0x44,
-0x80, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x18, 0xe2, 0x90, 0xff,
-0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1d, 0x84,
-0x12, 0x1c, 0x30, 0x12, 0x1d, 0x8b, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x43, 0x90, 0xf9, 0x6c, 0x12,
-0x1b, 0x43, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81,
+0xc0, 0x06, 0xc0, 0x07, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x60, 0x23, 0x74,
+0x66, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 0xf0, 0x70, 0x16, 0x74, 0xff, 0xf0, 0x74,
+0x1c, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x60, 0x04, 0x14, 0xf0, 0x70, 0x04, 0xc2, 0x90,
+0x80, 0xfc, 0x90, 0xff, 0x93, 0x74, 0x81, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 0x02, 0x11,
+0xdc, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xb2, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 0x83, 0xe0,
+0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff,
+0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 0xb4, 0x02,
+0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x28, 0x4e, 0x80,
+0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 0xa3, 0xe0,
+0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff,
+0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 0xb4, 0x02,
+0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x28, 0x4e, 0x80,
+0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x80, 0x03,
+0x02, 0x02, 0x90, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 0xf1, 0x20,
+0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x19, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 0xfc,
+0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, 0x01,
+0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x61, 0x12, 0x00, 0xc9, 0xee, 0x64, 0x04,
+0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, 0x60,
+0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x61, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x61, 0x7c,
+0x0a, 0x74, 0x19, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee,
+0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, 0x10,
+0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, 0xb1,
+0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, 0x08,
+0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 0x60, 0x13,
+0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x57, 0xd2,
+0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0,
+0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, 0xff,
+0x04, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff,
+0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, 0x7f,
+0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, 0xea,
+0x90, 0xfa, 0xbd, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0xe0, 0xe4, 0xf5, 0x4d, 0xe5, 0x4d, 0xc3,
+0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0xc1, 0xe4, 0x12, 0x1a, 0xe8, 0x05, 0x4d, 0x04, 0x12, 0x1c,
+0xb2, 0x80, 0xea, 0x12, 0x1c, 0xe0, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, 0x70,
+0x03, 0x02, 0x08, 0xf3, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xfe,
+0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, 0xff,
+0x01, 0xe0, 0x12, 0x1b, 0xfc, 0x03, 0x84, 0x00, 0x04, 0x57, 0x01, 0x05, 0x6a, 0x03, 0x06, 0x31,
+0x05, 0x06, 0x73, 0x06, 0x07, 0xd5, 0x08, 0x08, 0x1d, 0x09, 0x08, 0x79, 0x0a, 0x08, 0xb9, 0x0b,
+0x00, 0x00, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0,
+0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x64, 0x02, 0x45, 0x3b, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1c, 0xc1, 0x74, 0x01, 0x12,
+0x1a, 0xe8, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0xc1, 0x74, 0x02, 0x12, 0x1a, 0xe8,
+0x7f, 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x7f,
+0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x60, 0x07,
+0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0xfa, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0xbe, 0x12, 0x1a, 0xe8, 0x80,
+0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0xbe, 0x12, 0x1a, 0xe8, 0x80, 0x19, 0x15, 0x4d, 0x30, 0x0a,
+0x0b, 0x12, 0x1d, 0x55, 0x12, 0x1c, 0xbc, 0x12, 0x1a, 0xe8, 0x80, 0x09, 0x12, 0x1d, 0x63, 0x12,
+0x1c, 0xbc, 0x12, 0x1a, 0xe8, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xa2, 0x60, 0x05, 0x74, 0x01, 0x12,
+0x1a, 0xe8, 0x7f, 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x14, 0x60, 0x2d, 0x14, 0x60,
+0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x04, 0xa3, 0xe0,
+0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e,
+0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x06,
+0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb9, 0xe0, 0x60,
+0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb9, 0xe0, 0xd3, 0x94, 0x01,
+0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02,
+0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0xfa, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe5,
+0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x07, 0xe5,
+0x4d, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7,
+0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 0x20, 0x24,
+0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f,
+0x03, 0x12, 0x2e, 0x79, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2e, 0x79, 0x80, 0x1d, 0x30,
+0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2e, 0x79, 0x80, 0x0e, 0xe4, 0xfd,
+0x7f, 0x04, 0x12, 0x2e, 0x79, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0xef, 0x15, 0x4d, 0x30, 0x0a,
+0x0b, 0x12, 0x1d, 0x55, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1d, 0x63, 0xf5,
+0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02,
+0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x14, 0x60,
+0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70,
+0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35,
+0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x07, 0xe5, 0x4d,
+0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 0x01, 0x40,
+0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3,
+0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x12, 0x32, 0x3f, 0x40, 0x03,
+0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x4d,
+0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1e, 0x14, 0x02, 0x1d, 0xdf, 0xe5, 0x35, 0x20, 0xe1, 0x03,
+0x02, 0x0f, 0x6e, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1d, 0x55, 0xf5, 0x83, 0xe0, 0x44, 0x08,
+0xf0, 0x80, 0x09, 0x12, 0x1d, 0x63, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 0x02, 0x32,
+0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02,
+0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbe, 0xe0, 0x90,
+0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 0xe4, 0xff,
+0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x70,
+0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0,
+0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 0x60, 0x03,
+0x02, 0x0f, 0x6e, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1c, 0xe0, 0x12, 0x1e, 0x0d, 0x7d,
+0x03, 0x12, 0x0f, 0xb5, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0x72, 0x90, 0xfa, 0xb6, 0xe0,
+0xfd, 0xa3, 0x12, 0x1d, 0x2b, 0x12, 0x0f, 0xd1, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c,
+0x02, 0x10, 0x02, 0x12, 0x1c, 0xe0, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 0x1e, 0x0d,
+0x7d, 0x14, 0x12, 0x0f, 0xb5, 0x60, 0x10, 0x02, 0x0f, 0x6e, 0x12, 0x1e, 0x0d, 0x7d, 0x04, 0x12,
+0x10, 0x09, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0x72, 0x90, 0xfa, 0xb6, 0xe0, 0xfd, 0xa3,
+0x12, 0x1d, 0x2b, 0x12, 0x0f, 0xd1, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x02, 0x10,
+0x02, 0x12, 0x1e, 0x0d, 0x7d, 0x05, 0x12, 0x10, 0x09, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x7b, 0x01,
+0x7a, 0xfa, 0x79, 0xb6, 0x12, 0x1d, 0x28, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb7, 0xe4,
+0x75, 0xf0, 0x03, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xbe, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0xe4, 0xf5,
+0x4c, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1d, 0x22, 0x12,
+0x10, 0x14, 0xff, 0xfd, 0x90, 0xfa, 0xb7, 0xe4, 0x8d, 0xf0, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xb6,
+0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x6e, 0x05, 0x4c, 0x80, 0xd1,
+0x12, 0x1d, 0x22, 0x12, 0x10, 0x14, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0xfd, 0xa3, 0xe4,
+0x75, 0xf0, 0x02, 0x12, 0x1b, 0x1c, 0x7a, 0xf9, 0x79, 0x72, 0x7b, 0x01, 0x8b, 0x36, 0x8a, 0x37,
+0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1d, 0x28, 0x12, 0x26, 0x98, 0x8f,
+0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0xc1, 0xe5, 0x4c, 0x12, 0x1a, 0xe8, 0x12, 0x1c, 0xc1,
+0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0xfa, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x3c,
+0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 0x3a, 0x02,
+0x2c, 0xd8, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x64,
+0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f,
+0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d,
+0x79, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f,
+0x6e, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xf1, 0xe5, 0x35, 0x30,
+0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa,
+0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xd3, 0x90, 0xfa, 0xbe, 0xe0, 0x94, 0x01, 0x90, 0xfa,
+0xbd, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbe, 0xe0,
+0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 0x53, 0x35,
+0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0,
+0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02,
+0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1,
+0x03, 0x02, 0x0f, 0x6e, 0x7f, 0x01, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f,
+0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xd3, 0x90, 0xfa, 0xbe, 0xe0, 0x94,
+0x00, 0x90, 0xfa, 0xbd, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x64,
+0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff,
+0x02, 0x32, 0x6e, 0x90, 0xff, 0x01, 0x12, 0x1e, 0x24, 0xef, 0x12, 0x1a, 0xe8, 0x90, 0xfa, 0xb9,
+0x12, 0x1e, 0x24, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0xfa, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a,
+0xfa, 0x74, 0x03, 0x12, 0x1c, 0xb2, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 0x38, 0x82,
+0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0xfc, 0x09,
+0x7b, 0x02, 0x09, 0x9d, 0x04, 0x09, 0xbf, 0x05, 0x09, 0xeb, 0x06, 0x0a, 0x09, 0x07, 0x0a, 0x27,
+0x08, 0x0a, 0x45, 0x09, 0x0a, 0x63, 0x0b, 0x0b, 0x18, 0x80, 0x0d, 0xb7, 0x81, 0x0d, 0xe8, 0x82,
+0x0b, 0x5f, 0x83, 0x0b, 0xa8, 0x84, 0x0b, 0xc7, 0x85, 0x0c, 0x0c, 0x86, 0x0c, 0x57, 0x87, 0x0c,
+0xe8, 0x88, 0x0d, 0x73, 0x89, 0x0a, 0x81, 0x92, 0x0a, 0x81, 0x93, 0x0d, 0xa0, 0xb0, 0x0e, 0x9b,
+0xc0, 0x0e, 0xc7, 0xc1, 0x0e, 0xd8, 0xc2, 0x00, 0x00, 0x0f, 0x5d, 0xe5, 0x35, 0x20, 0xe7, 0x05,
+0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c,
+0x00, 0x7f, 0x07, 0x02, 0x11, 0x5e, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0xb4, 0xe5, 0x35, 0x20,
+0xe7, 0x05, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef,
+0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x5e, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0xb4, 0xe5,
+0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1e, 0x42, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b,
+0x70, 0x05, 0x7f, 0x02, 0x02, 0x31, 0xa9, 0x90, 0xfa, 0xb9, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50,
+0x02, 0x80, 0x03, 0x02, 0x32, 0x2c, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03,
+0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f,
+0x08, 0x02, 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f,
+0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02,
+0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12,
+0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x5e,
+0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71,
+0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x5e, 0x7f, 0x07,
+0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03,
+0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31,
+0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1d, 0x79, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5,
+0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05,
+0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1c, 0x22,
+0x12, 0x1e, 0x3b, 0x12, 0x25, 0xfa, 0x12, 0x1d, 0x89, 0x12, 0x1a, 0xbb, 0x60, 0x05, 0x12, 0x32,
+0x7a, 0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75,
+0x38, 0x75, 0x02, 0x2c, 0xd8, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0xb4, 0x12, 0x1d, 0x79, 0x60,
+0x05, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1e, 0x42, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x31, 0xa9,
+0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12,
+0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04,
+0xf5, 0x4c, 0x12, 0x1c, 0x22, 0x02, 0x32, 0x2c, 0x12, 0x1e, 0x4c, 0x12, 0x2a, 0xc7, 0x12, 0x1d,
+0x33, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xba, 0xf0, 0x78, 0x68, 0x12,
+0x1b, 0xd8, 0x90, 0x00, 0x02, 0x12, 0x1a, 0xbb, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12,
+0x1a, 0xfa, 0x90, 0xfa, 0xba, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6,
+0x8c, 0x83, 0x12, 0x1d, 0x3b, 0xef, 0xf0, 0x12, 0x32, 0x84, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x90,
+0xfa, 0xb9, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06,
+0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbe, 0xe0,
+0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3,
+0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbe, 0xe0, 0x42,
+0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1c, 0xe0, 0x90, 0xfa, 0xb9, 0xe0, 0xb4,
+0x01, 0x0a, 0x12, 0x1c, 0xc1, 0xe5, 0x90, 0x12, 0x1a, 0xe8, 0x80, 0x08, 0x12, 0x1c, 0xc1, 0xe5,
+0xb0, 0x12, 0x1a, 0xe8, 0x02, 0x0f, 0xf1, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x24, 0x13, 0x12, 0x1c,
+0xf1, 0x20, 0xe1, 0x33, 0x12, 0x1d, 0x80, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90,
+0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1e,
+0x56, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10,
+0xf0, 0x80, 0x04, 0x12, 0x1e, 0x5d, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x90, 0xfa, 0xb9, 0xe0,
+0xff, 0x24, 0x13, 0x12, 0x1c, 0xf1, 0x20, 0xe1, 0x39, 0x12, 0x1d, 0x80, 0xef, 0x24, 0xfc, 0x60,
+0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20,
+0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xba, 0xe0,
+0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54,
+0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x12, 0x1d, 0x71, 0x60, 0x4d, 0x04,
+0x60, 0x03, 0x02, 0x0c, 0xe3, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c,
+0xea, 0x30, 0xe1, 0x6f, 0x12, 0x1e, 0x2c, 0x02, 0x0c, 0xe3, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb,
+0x12, 0x1c, 0xed, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1e, 0x2c,
+0x80, 0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1e,
+0x2c, 0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xba, 0xe0,
+0x60, 0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0xea, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44,
+0x02, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0xed, 0x30, 0xe1, 0x13,
+0x30, 0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0,
+0x54, 0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x90, 0xfa, 0xb9, 0xe0, 0x24,
+0xfc, 0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0,
+0x44, 0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0,
+0x90, 0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0,
+0x44, 0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf,
+0xf0, 0x80, 0x3b, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0,
+0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3,
+0xef, 0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0,
+0xc2, 0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff,
+0x02, 0x31, 0xa9, 0x12, 0x1c, 0xe0, 0x90, 0xfa, 0xb9, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70,
+0x16, 0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x80, 0x0a, 0x90, 0xff, 0xb6,
+0xe0, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0xd8,
+0x90, 0xf9, 0x15, 0x74, 0x01, 0xf0, 0x90, 0xf9, 0x1c, 0x74, 0x19, 0xf0, 0x90, 0xf9, 0x66, 0x74,
+0xff, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0xe4, 0xff, 0x12, 0x31, 0xa9, 0x12, 0x1d, 0xe7, 0x7f,
+0x03, 0x12, 0x12, 0x61, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80,
+0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30,
+0xd3, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbf,
+0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb7, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54,
+0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xbc, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e,
+0x40, 0x08, 0x90, 0xfa, 0xc0, 0xe0, 0x90, 0xfa, 0xbc, 0xf0, 0x12, 0x0f, 0x98, 0xe5, 0x31, 0x45,
+0x30, 0x70, 0x73, 0x12, 0x1c, 0xfa, 0x90, 0xfa, 0xbf, 0x12, 0x1e, 0x06, 0x60, 0x27, 0xd3, 0xef,
+0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90,
+0xfa, 0xc0, 0xe0, 0x90, 0xfa, 0xbc, 0xf0, 0x12, 0x0f, 0x98, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46,
+0x12, 0x1c, 0xfa, 0x80, 0xd1, 0x75, 0x4c, 0x02, 0x90, 0xfa, 0xbf, 0xe4, 0xf0, 0xa3, 0x04, 0xf0,
+0x90, 0xfa, 0xb7, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90,
+0xfa, 0xc0, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x29, 0x60, 0x75, 0x30, 0x00, 0x8f,
+0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26,
+0x98, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x30, 0xe7,
+0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x67, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80,
+0x11, 0x90, 0xfa, 0xba, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x65, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02,
+0xc2, 0x94, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1e, 0x4c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80,
+0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x54, 0x03, 0x14, 0x60, 0x0a,
+0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91,
+0x80, 0x23, 0x12, 0x1e, 0x56, 0x12, 0x0f, 0xc0, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff,
+0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0xc0, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2,
+0x91, 0x12, 0x1e, 0x56, 0xf0, 0x90, 0xfa, 0xba, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f,
+0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80,
+0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1e, 0x5d, 0x12, 0x0f, 0xe0, 0x60, 0x04, 0xd2, 0x92, 0x80,
+0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0xe0, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92,
+0x80, 0x02, 0xd2, 0x92, 0x12, 0x1e, 0x5d, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30,
+0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0xb4, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x32,
+0x7a, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb6, 0x90, 0xfa, 0xb7, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
+0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb7, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1b,
+0x1c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa,
+0xb7, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x4a, 0x12, 0x29, 0x60, 0x75,
+0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x23, 0x61, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22,
+0xf0, 0x7f, 0x01, 0x12, 0x12, 0x61, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xbb, 0xf0, 0x54, 0xa0,
+0x22, 0x12, 0x26, 0x98, 0x8f, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22,
+0xf0, 0x7f, 0x01, 0x12, 0x12, 0x61, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xbb, 0xf0, 0x54, 0xa0,
+0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0xd8, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x02,
+0x32, 0x3f, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 0xd8, 0x12, 0x23, 0x61, 0x7e, 0x00, 0x8e, 0x30,
+0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb4, 0xe0, 0x22, 0xef, 0x90,
+0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd,
+0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70,
+0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0,
+0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c,
+0xff, 0x12, 0x10, 0xc0, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1d,
+0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff,
+0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82,
+0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83,
+0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3,
+0x80, 0xda, 0x12, 0x11, 0x57, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22,
+0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e,
+0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0xae, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02,
+0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 0xc0, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9,
+0x1d, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43,
+0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80,
+0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3,
+0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78,
+0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77,
+0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x11, 0x57, 0xd0, 0x06, 0xd0, 0x04,
+0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0,
+0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x11, 0xae, 0x80, 0xf4,
+0xef, 0x60, 0x31, 0x90, 0x31, 0x11, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff,
+0x12, 0x10, 0xc0, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1d,
+0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05,
+0x43, 0x12, 0x11, 0x57, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0xdc, 0xc0, 0x04,
+0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75,
+0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04,
+0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90,
+0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90,
+0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10,
+0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0xd2,
+0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10,
+0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04,
+0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f,
+0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f,
+0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f,
+0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8,
+0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7,
+0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0xae, 0x80, 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08,
+0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 0x12, 0x11, 0xae, 0x80, 0xee, 0xd0, 0x00, 0x22,
+0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8,
+0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83,
+0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f,
+0x75, 0xf0, 0x02, 0xa4, 0x24, 0xf3, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93,
+0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24,
+0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82,
+0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76,
+0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x31, 0x11, 0xe4,
+0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f,
+0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75,
+0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1d,
+0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6,
+0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0,
+0x07, 0x12, 0x12, 0x89, 0xad, 0x07, 0xaf, 0x02, 0x12, 0x12, 0xa0, 0xd0, 0x07, 0xa3, 0xa3, 0xa3,
+0xdf, 0xce, 0x12, 0x11, 0xae, 0x80, 0xc1, 0x8f, 0x24, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xb5, 0xa3,
+0xa3, 0xe0, 0xa3, 0x30, 0xe7, 0x28, 0x78, 0x7e, 0x12, 0x22, 0x99, 0xe0, 0x44, 0x01, 0xf0, 0x12,
+0x22, 0xfa, 0x12, 0x22, 0x9d, 0xe0, 0x20, 0xe0, 0xf6, 0x12, 0x23, 0x50, 0x74, 0x02, 0xf0, 0x12,
+0x22, 0xda, 0xe0, 0xa3, 0x30, 0xe5, 0x07, 0x12, 0x23, 0x50, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x80,
+0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0x12, 0x23,
+0x39, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x22, 0xa1, 0xed, 0xf0, 0x12, 0x23, 0x06, 0x24, 0x07, 0x12,
+0x22, 0xa1, 0xe0, 0xff, 0x12, 0x23, 0x5a, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0x90, 0xf9,
+0x16, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0xb7, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25,
+0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0,
+0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x22, 0xb5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12,
+0x23, 0x39, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0xed, 0x12, 0x23, 0x5a, 0x24,
+0x07, 0x12, 0x22, 0xa1, 0xed, 0xf0, 0x12, 0x22, 0xa9, 0xe0, 0x30, 0xe6, 0x0a, 0x12, 0x23, 0x41,
+0x24, 0x09, 0x12, 0x22, 0xa1, 0xe4, 0xf0, 0x12, 0x22, 0xa9, 0xe0, 0xff, 0x30, 0xe7, 0x1b, 0x12,
+0x23, 0x1e, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x60, 0x09, 0x12, 0x22, 0xa9, 0xef, 0x44, 0x02,
+0xf0, 0x80, 0x07, 0x12, 0x22, 0xa9, 0xef, 0x54, 0xfd, 0xf0, 0x78, 0x7e, 0x12, 0x22, 0xb7, 0xa3,
+0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x22, 0xe0, 0xa3,
+0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x22, 0xa1, 0xe0,
+0x90, 0x32, 0x51, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x23, 0x1e, 0x24, 0x06, 0x12, 0x22,
+0xa1, 0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x23, 0x29, 0x24,
+0x04, 0x12, 0x22, 0xa1, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x23, 0x39, 0xf5, 0x82, 0x8a,
+0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x5a, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0xff, 0x8d,
+0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf,
+0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07,
+0x10, 0x12, 0x22, 0xa9, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1,
+0x69, 0x12, 0x23, 0x1e, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x12, 0x1b, 0xfc, 0x15, 0x2c, 0x00,
+0x15, 0x60, 0x01, 0x15, 0x65, 0x03, 0x15, 0x60, 0x05, 0x15, 0x65, 0x07, 0x15, 0x60, 0x09, 0x15,
+0x65, 0x0b, 0x15, 0x60, 0x0d, 0x15, 0x65, 0x0f, 0x00, 0x00, 0x15, 0x6d, 0xe5, 0x24, 0x64, 0x03,
+0x70, 0x21, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80,
+0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07,
+0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d,
+0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x23, 0x27,
+0x24, 0x04, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff,
+0x12, 0x22, 0xa9, 0xe0, 0xfe, 0x54, 0x03, 0x70, 0x03, 0x02, 0x16, 0x60, 0xee, 0x20, 0xe1, 0x03,
+0x02, 0x16, 0x5d, 0x08, 0x12, 0x23, 0x20, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x12, 0x1b, 0xfc,
+0x15, 0xbf, 0x00, 0x15, 0xf5, 0x01, 0x15, 0xf5, 0x03, 0x16, 0x29, 0x05, 0x16, 0x29, 0x07, 0x16,
+0x0f, 0x09, 0x16, 0x0f, 0x0b, 0x16, 0x43, 0x0d, 0x16, 0x43, 0x0f, 0x00, 0x00, 0x16, 0x60, 0xe5,
+0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53,
+0x07, 0x7f, 0x02, 0x16, 0x60, 0x43, 0x07, 0x80, 0x02, 0x16, 0x60, 0x30, 0x94, 0x05, 0x53, 0x07,
+0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70,
+0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef,
+0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5,
+0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e,
+0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff,
+0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07,
+0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80,
+0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f,
+0x12, 0x22, 0xda, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03,
+0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec,
+0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43,
+0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03,
+0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed,
+0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0xdc,
+0xa3, 0xef, 0xf0, 0x12, 0x32, 0x84, 0x7f, 0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3,
+0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcf, 0xe4,
+0xfd, 0x12, 0x23, 0x61, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1b, 0x1c, 0x12, 0x19,
+0x92, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa,
+0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xcf,
+0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5,
+0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0xe5, 0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23,
+0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12,
+0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02,
+0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90,
+0xf9, 0x16, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4,
+0x41, 0x12, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1,
+0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x44,
+0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 0x0c, 0xe5, 0x23, 0x64, 0x43, 0x60, 0x06, 0xe5, 0x23,
+0x64, 0x44, 0x70, 0x2e, 0x90, 0xf9, 0x16, 0xe0, 0xff, 0xe5, 0x23, 0xb4, 0x44, 0x04, 0x7e, 0x40,
+0x80, 0x02, 0x7e, 0x00, 0xee, 0x24, 0x80, 0x4f, 0x90, 0xf9, 0x16, 0xf0, 0xa3, 0xe0, 0xff, 0xe5,
+0x23, 0xb4, 0x44, 0x04, 0x7e, 0x40, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x24, 0x80, 0x4f, 0x90, 0xf9,
+0x17, 0xf0, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x19, 0x92, 0x90, 0xff,
+0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1e, 0x34,
+0x12, 0x1c, 0xe0, 0x12, 0x1e, 0x3b, 0x90, 0xf9, 0x6a, 0x12, 0x1b, 0xf3, 0x90, 0xf9, 0x6f, 0x12,
+0x1b, 0xf3, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81,
0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23,
-0x12, 0x1c, 0xa7, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1c, 0xb5, 0xf5, 0x83, 0xe4, 0xf0,
-0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x31,
-0x4d, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x31, 0x5a, 0xe4, 0x93, 0xff,
-0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1c, 0x97, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0,
+0x12, 0x1d, 0x57, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1d, 0x65, 0xf5, 0x83, 0xe4, 0xf0,
+0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x32,
+0x0a, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x32, 0x17, 0xe4, 0x93, 0xff,
+0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1d, 0x47, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0,
0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0,
-0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0x28, 0xce, 0xc3, 0x13, 0xce,
-0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1c, 0xf8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0x1e, 0xe4, 0xf5,
-0x23, 0xe5, 0x23, 0x90, 0x31, 0x47, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0,
-0x24, 0x4e, 0xf5, 0x82, 0xe4, 0x34, 0x31, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7,
-0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0x97, 0x12, 0x1d, 0x06, 0x24, 0x47, 0xf5, 0x82,
-0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12,
-0x1c, 0xf8, 0xef, 0xf0, 0x12, 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d,
-0x0b, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0x1e,
+0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0xd8, 0xce, 0xc3, 0x13, 0xce,
+0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1d, 0xa8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0xce, 0xe4, 0xf5,
+0x23, 0xe5, 0x23, 0x90, 0x32, 0x04, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0,
+0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x34, 0x32, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7,
+0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1d, 0x47, 0x12, 0x1d, 0xb6, 0x24, 0x47, 0xf5, 0x82,
+0xe4, 0x34, 0xff, 0x12, 0x1c, 0xc8, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12,
+0x1d, 0xa8, 0xef, 0xf0, 0x12, 0x1c, 0xcf, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d,
+0xbb, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0xce,
0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80,
-0xf0, 0x02, 0x18, 0xb7, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0xea, 0x12, 0x1d, 0x06,
-0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8,
-0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12,
-0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x05, 0xf5, 0x82,
+0xf0, 0x02, 0x19, 0x67, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1d, 0x9a, 0x12, 0x1d, 0xb6,
+0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0xc8, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8,
+0xf9, 0x12, 0x1d, 0xbb, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12,
+0x1c, 0xcf, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0xbb, 0x24, 0x05, 0xf5, 0x82,
0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82,
0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82,
0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02,
-0x17, 0xe1, 0x90, 0x31, 0x4c, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1c, 0xe8, 0xe4, 0xf0,
-0x90, 0x31, 0x4b, 0x93, 0xff, 0xf6, 0x12, 0x1c, 0x95, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05,
-0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12,
-0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0xe7, 0x09, 0xf6, 0x08,
+0x18, 0x91, 0x90, 0x32, 0x09, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1d, 0x98, 0xe4, 0xf0,
+0x90, 0x32, 0x08, 0x93, 0xff, 0xf6, 0x12, 0x1d, 0x45, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05,
+0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12,
+0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x26, 0x98, 0xe7, 0x09, 0xf6, 0x08,
0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83,
0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78,
0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3,
@@ -445,7 +456,7 @@ static unsigned char IMAGE_ARRAY_NAME[] =
0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60,
0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5,
0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19,
-0x4c, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb,
+0xfc, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb,
0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82,
0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8,
0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82,
@@ -469,364 +480,365 @@ static unsigned char IMAGE_ARRAY_NAME[] =
0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82,
0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01,
0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3,
-0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25,
+0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25,
0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12,
-0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06,
-0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38,
-0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0x38, 0x04, 0x25,
+0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06,
+0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38,
+0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0xe8, 0x04, 0x25,
0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a,
-0x38, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab,
-0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35,
-0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38,
+0xe8, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab,
+0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35,
+0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8,
0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54,
0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3,
0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22,
-0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x6f, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x12,
-0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e,
-0x00, 0xc3, 0x90, 0xfa, 0xbd, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbc, 0xe0, 0x9e, 0xf0, 0x90, 0xfa,
-0xb4, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5,
-0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb1, 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
+0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x72, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x13,
+0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xbc, 0xe0, 0xff, 0x7e,
+0x00, 0xc3, 0x90, 0xfa, 0xc0, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x9e, 0xf0, 0x90, 0xfa,
+0xb7, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5,
+0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb4, 0x90, 0xfa, 0xb7, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4,
0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4,
0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4,
0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff,
-0x22, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22,
-0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9,
-0x6c, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00,
+0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22,
+0x90, 0xfa, 0xbe, 0xe0, 0x90, 0xfa, 0xba, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9,
+0x6f, 0x12, 0x1b, 0xea, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00,
0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82,
0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08,
-0xa4, 0x22, 0x74, 0xaf, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0,
+0xa4, 0x22, 0x74, 0xb2, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0,
0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90,
0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff,
0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74,
-0x65, 0xf0, 0x22, 0x12, 0x1b, 0x1c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a,
-0xfa, 0x79, 0xb4, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0,
-0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x67, 0x02, 0x1b, 0x3a, 0x90, 0xff, 0xa4, 0xe0,
+0x65, 0xf0, 0x22, 0x12, 0x1b, 0xcc, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a,
+0xfa, 0x79, 0xb7, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0,
+0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x6a, 0x02, 0x1b, 0xea, 0x90, 0xff, 0xa4, 0xe0,
0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79,
-0x6f, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbb, 0xe0,
-0xff, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4,
-0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0x06, 0x12, 0x22,
-0x4a, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x0a,
-0x12, 0x22, 0x52, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0x4a, 0x12,
-0x22, 0x4a, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x22, 0x56, 0x24,
-0x04, 0x12, 0x21, 0xf3, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55,
+0x72, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbe, 0xe0,
+0xff, 0x90, 0xfa, 0xba, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4,
+0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x4b, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0xc7, 0x12, 0x22,
+0xfa, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x0a,
+0x12, 0x23, 0x02, 0x24, 0x0a, 0x12, 0x22, 0xa1, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0xfa, 0x12,
+0x22, 0xfa, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x23, 0x06, 0x24,
+0x04, 0x12, 0x22, 0xa1, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55,
0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06,
-0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x0c, 0xef,
-0x12, 0x1a, 0x4a, 0x78, 0x80, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53,
-0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20,
-0xe5, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02,
-0xe5, 0x53, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20,
-0xe5, 0x53, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07,
-0x80, 0xe5, 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06,
-0x08, 0xe5, 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7,
-0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0,
-0x12, 0x1a, 0xef, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22,
-0x2c, 0x90, 0x00, 0x08, 0xef, 0x12, 0x1a, 0x4a, 0x80, 0x0a, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x08,
-0xe4, 0x12, 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x07, 0xef, 0x12,
-0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0x4a, 0x90,
-0x00, 0x07, 0x12, 0x1a, 0x0b, 0x70, 0x13, 0x12, 0x22, 0x2d, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a,
-0xfa, 0x12, 0x19, 0xf2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0x38, 0x12, 0x22, 0x78, 0x24, 0x08, 0x12,
-0x21, 0xf3, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0,
-0xfd, 0xee, 0xed, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0xef, 0x12,
-0x31, 0xc7, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0x90, 0xfa, 0xe3, 0xe0,
-0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xd7,
-0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xff, 0x7e, 0x00, 0x90, 0xfa,
-0xd3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1a,
-0x98, 0xff, 0x90, 0xfa, 0xd5, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e,
-0x50, 0x8f, 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa,
-0xd8, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd6, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90,
-0xfa, 0xda, 0xf0, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0x90, 0xfa, 0xd3, 0xe0, 0x94, 0x00, 0x50,
-0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12,
-0x2d, 0x5a, 0x90, 0xfa, 0xd3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xd7,
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xda,
-0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd4, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03,
-0xe0, 0xff, 0x22, 0x12, 0x2d, 0x5a, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5,
-0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b,
-0x01, 0x90, 0xfa, 0xd5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xda, 0xe0, 0xf5, 0x4a, 0x12,
-0x28, 0x9f, 0x90, 0xfa, 0xd9, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60,
-0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x20, 0xbb, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0x03, 0x78,
-0x71, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33,
-0x90, 0xfa, 0x91, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 0x22, 0x78,
-0x72, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43,
-0x90, 0xfa, 0x93, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb0, 0x74, 0x01, 0xf0, 0x22, 0x90,
-0xfa, 0x9d, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0x03, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa,
-0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff,
-0xa6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa,
-0xcb, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2c, 0xb4, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xcb, 0xe0,
-0xff, 0x74, 0x34, 0x90, 0xfa, 0x95, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa7, 0xe0, 0xa3,
-0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca,
-0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xb6,
-0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12,
-0x2c, 0xb4, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x97, 0xf0,
-0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0,
-0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0,
-0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc9, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef,
-0x12, 0x1b, 0x4c, 0x21, 0xbb, 0x26, 0x21, 0xbb, 0x2e, 0x21, 0x5e, 0x30, 0x21, 0x5e, 0x32, 0x21,
-0x6c, 0x38, 0x21, 0x7e, 0x3a, 0x21, 0xb0, 0x3e, 0x21, 0x9b, 0x44, 0x21, 0x90, 0x46, 0x21, 0xa6,
-0x50, 0x21, 0xa6, 0x52, 0x21, 0xa6, 0x54, 0x21, 0xa6, 0x56, 0x00, 0x00, 0x21, 0xc0, 0x90, 0xfa,
-0xc9, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x16, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01,
-0x7f, 0x03, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00,
-0x7d, 0x01, 0x7f, 0x02, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e,
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x16, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f,
-0x06, 0x12, 0x11, 0x16, 0x80, 0x28, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x12, 0x20, 0x18, 0x80, 0x1e,
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x16, 0x80, 0x13, 0x12, 0x27, 0x8d, 0x80, 0x0e,
-0x90, 0xfa, 0xc9, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2c, 0xb4, 0xd0, 0x07,
-0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0,
-0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24,
-0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x12, 0x25, 0x24, 0xf5,
-0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e,
-0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b,
-0xff, 0x7a, 0x31, 0x79, 0x99, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x19, 0xcc, 0xff, 0x90, 0xf9, 0x6c,
-0x02, 0x1b, 0x3a, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x04, 0x02, 0x1a, 0x0b, 0xe6,
-0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6,
-0xff, 0x22, 0xed, 0x12, 0x1a, 0x4a, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90,
-0xfa, 0xcb, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x08, 0xe6,
-0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x09, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c,
-0x83, 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6,
-0xfb, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, 0x22,
-0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x02,
-0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5,
-0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xce, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, 0xe0,
-0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xce, 0xe0,
-0xff, 0x90, 0xfa, 0xd1, 0xe4, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xd1,
-0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xcf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xce, 0xe0,
-0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x04, 0x12, 0x1a,
-0x6c, 0x02, 0x22, 0xb1, 0x90, 0xfa, 0xd0, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xcf, 0xe0, 0x34,
-0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1a, 0xd0, 0x7f, 0x00, 0x22, 0x7b,
-0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x6c, 0x85,
-0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0x8f, 0x62, 0x12, 0x2a, 0x06, 0x12, 0x22,
-0x4a, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, 0x08,
-0x12, 0x22, 0x3f, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x22, 0x56, 0x24, 0x0b, 0x12, 0x21, 0xf3,
-0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0,
-0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, 0x24,
-0x04, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0x74,
-0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x21, 0xf3, 0xc0,
-0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x96, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83,
-0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e,
-0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0,
-0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12,
-0x10, 0x03, 0x7f, 0x02, 0x12, 0x12, 0x19, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2,
-0xb1, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, 0xd2,
-0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7c,
-0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x7a,
-0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40,
-0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe4, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff,
-0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87,
-0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0,
-0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7a, 0xe0,
-0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe4, 0xe0,
-0xf5, 0xa8, 0x02, 0x10, 0x86, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2d, 0x3c, 0x90, 0xfa,
-0xc0, 0x12, 0x1b, 0x43, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x43, 0x90, 0xfa,
-0xc4, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x3a, 0xe9, 0x24,
-0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xab, 0x5c, 0xaa, 0x5d, 0xa9,
-0x5e, 0x12, 0x2d, 0x48, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, 0xbe,
-0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc0, 0x12, 0x2d, 0x1d, 0xff,
-0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0x1d, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, 0xf6,
-0x12, 0x2d, 0x1a, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0x23, 0x75, 0xf0, 0x02, 0x12,
-0x1a, 0x6c, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0xab, 0x5c, 0xaa, 0x5d,
-0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x0b, 0x30, 0xe4, 0x03, 0x12, 0x2d, 0x32, 0x78, 0x82,
-0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbf, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, 0x90,
-0xfa, 0xbf, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60,
-0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x24, 0x95,
-0x80, 0x62, 0x12, 0x2d, 0x53, 0x12, 0x1f, 0x2c, 0x90, 0xfa, 0xbf, 0xef, 0xf0, 0x80, 0x55, 0x90,
-0xfa, 0xbf, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e,
-0x12, 0x2c, 0x5f, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, 0x01,
-0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xfd,
-0x90, 0x00, 0x08, 0x12, 0x1a, 0x98, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, 0xd0,
-0x03, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa,
-0xbf, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x02, 0x12, 0x1a,
-0x4a, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, 0xe5,
-0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2d, 0x82, 0x70, 0x16, 0x12, 0x2d, 0xa1, 0xe5, 0x2d,
-0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x26, 0x64, 0x40, 0x0b, 0x7f, 0x00,
-0x22, 0x12, 0x2d, 0xa1, 0x12, 0x26, 0x64, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5,
-0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0,
-0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0x04, 0x40,
-0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0,
-0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2d, 0x94, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, 0xe4,
-0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0x04, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2d,
-0x94, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0x1b, 0x12, 0x10, 0x03,
-0x78, 0x84, 0x12, 0x22, 0x82, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x30, 0xec, 0x02, 0x26, 0xfb,
-0x78, 0x84, 0xe6, 0xf9, 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, 0x03,
-0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, 0x04,
-0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x39,
-0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x80,
-0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, 0x54,
-0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07,
-0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x17, 0xe0, 0x04, 0xf0, 0xaf,
-0x01, 0x12, 0x22, 0x33, 0xfd, 0x12, 0x2f, 0x49, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x75, 0xa8,
-0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x27, 0x48, 0x02, 0x30, 0xcf,
-0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4,
-0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f,
-0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b,
-0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0x4c, 0xe4, 0x7e, 0x01, 0x93, 0x60,
-0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01,
-0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93,
-0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8,
-0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x22,
-0x12, 0x1d, 0x12, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x2f, 0x77, 0x12,
-0x1d, 0x12, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x22,
-0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1d, 0x53, 0x60, 0x2c, 0x12, 0x2c, 0xb4,
-0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1b, 0x1c, 0xe4, 0xf0,
-0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0x9d, 0x12, 0x1b, 0x1c, 0xe0, 0xa3, 0x30,
-0xe6, 0x33, 0x12, 0x1d, 0x12, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa,
-0x95, 0x12, 0x1d, 0x53, 0x60, 0x16, 0x12, 0x2c, 0xb4, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5,
-0x22, 0x90, 0xfa, 0x95, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, 0x22,
-0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef,
-0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12,
-0x1c, 0x11, 0x12, 0x1a, 0x38, 0x0f, 0x12, 0x1c, 0x00, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x3a,
-0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, 0x39,
-0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x84,
-0x12, 0x1d, 0x76, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70,
-0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0x0b, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, 0xef,
-0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x16, 0x12, 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c,
-0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 0x12, 0x31, 0xb1, 0x22, 0x8b,
-0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2d, 0x82, 0x70, 0x16,
-0x12, 0x2d, 0xa1, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x29,
-0x14, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x29, 0x14, 0x50, 0xf8, 0xe4, 0xf5,
-0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0x04, 0x40, 0x03,
-0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, 0x46,
-0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0x04, 0x40, 0x03, 0x7f, 0x18,
-0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x19, 0xf2, 0x90, 0xff, 0xf1,
-0xf0, 0x02, 0x31, 0x1b, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0x1b, 0x7b, 0x01, 0x7a,
-0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x09, 0x12,
-0x1a, 0x6c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12,
-0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xff, 0xf7, 0xe5,
-0x23, 0x12, 0x29, 0x78, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3,
-0x74, 0x06, 0x12, 0x29, 0x78, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0,
-0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90,
-0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01,
-0x02, 0x25, 0xd7, 0x90, 0xff, 0x93, 0x74, 0x2a, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90,
-0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, 0x15,
-0xf0, 0xa3, 0xf0, 0x12, 0x2a, 0x78, 0x12, 0x16, 0x42, 0x12, 0x2f, 0xcd, 0x7e, 0x07, 0x7f, 0xd0,
-0x12, 0x11, 0xe2, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0xfc, 0xe4, 0x78, 0x77, 0xf6, 0x78, 0x77,
-0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, 0x06,
-0x80, 0xec, 0x7f, 0x03, 0x12, 0x2e, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 0x04,
-0x12, 0x2e, 0xb3, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 0xe0,
-0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, 0x12,
-0x11, 0x66, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, 0x76,
-0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, 0xff,
-0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, 0x9b,
-0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x22, 0x92, 0x7b, 0x01, 0x7a, 0xff,
-0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0x31, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, 0xa4,
-0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x22, 0x92, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0x31, 0x78,
-0x6d, 0xef, 0x12, 0x22, 0x92, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, 0xe0,
-0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4,
-0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7e, 0x00, 0x90, 0xfa, 0xe1, 0xee, 0xf0,
-0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x52, 0x09, 0x90, 0xf9,
-0x15, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe1, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64,
-0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x10,
-0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe3, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x54, 0xef, 0xf0,
-0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x12, 0x10, 0x03, 0x78, 0x8a, 0xef, 0xf6, 0x12,
-0x2a, 0x06, 0x12, 0x22, 0x33, 0x30, 0xe0, 0x25, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x7f, 0xf0, 0x78,
-0x6b, 0x12, 0x1b, 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02,
-0xe4, 0x12, 0x1a, 0x4a, 0x80, 0xe9, 0x12, 0x22, 0x07, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x22, 0x33,
-0x30, 0xe1, 0x1e, 0x12, 0x21, 0xe9, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x31, 0x5c, 0x78, 0x68, 0x12,
-0x1b, 0x28, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0x4a, 0x12, 0x21, 0xe9, 0xe0, 0x44, 0x80,
-0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x03, 0x68, 0x01, 0xff,
-0x48, 0x03, 0x6b, 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x95, 0x00, 0x00, 0x00,
-0x00, 0x44, 0xfa, 0x91, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xaf, 0x00, 0x00, 0x42, 0xfa, 0x7b,
-0x00, 0x00, 0x42, 0xfa, 0x79, 0x00, 0x00, 0x42, 0xf9, 0x6a, 0xff, 0xff, 0x42, 0xfa, 0x77, 0x00,
-0x00, 0x43, 0xf9, 0x18, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x65, 0x20, 0x41, 0xf9, 0x66, 0x20, 0x41,
-0xf9, 0x63, 0x00, 0x41, 0xf9, 0x64, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9,
-0x15, 0x00, 0x00, 0x41, 0xf9, 0x17, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12,
-0x10, 0x03, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x30, 0x93, 0x12, 0x30, 0xec, 0x78, 0x85, 0xe6, 0xff,
-0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff,
-0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, 0x19,
-0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0,
-0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x14, 0xf0, 0xe0,
-0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0x86, 0x12, 0x1d, 0x6c, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04,
-0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, 0x40,
-0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39,
-0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1d, 0x84, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, 0x1c,
-0x11, 0x12, 0x19, 0xf2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed,
-0xf0, 0x0e, 0x12, 0x1c, 0x00, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b,
-0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2d, 0x48, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab,
-0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xe5, 0x5b,
-0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x43, 0xe4, 0x90, 0xfa,
-0xbf, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, 0x50,
-0x12, 0x12, 0x2d, 0x1a, 0xff, 0x12, 0x2d, 0x23, 0x12, 0x2d, 0x36, 0x78, 0x8b, 0x06, 0x12, 0x2d,
-0x32, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x31, 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x74,
-0xf6, 0x54, 0x0f, 0x12, 0x1c, 0xf8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, 0x29,
-0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee,
-0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00,
-0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0,
-0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x90,
-0x00, 0x03, 0x12, 0x1a, 0x0b, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x3a,
-0x02, 0x19, 0xf2, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x3a, 0xef, 0x12, 0x1a, 0x38, 0x90, 0xfa, 0xc7,
-0xe4, 0x22, 0x90, 0xfa, 0xc1, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1a, 0x6c, 0x90, 0x00, 0x08, 0x12,
-0x1a, 0x98, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0x90, 0xfa,
-0xbe, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xda, 0xe0, 0xff, 0x7e,
-0x00, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd3, 0xe0, 0x9e, 0xf0, 0x90, 0xfa,
-0xd5, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, 0xf5,
-0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe3,
-0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, 0x1a,
-0x38, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, 0xb4,
-0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0x32, 0x7f, 0x02, 0x02, 0x31, 0x32, 0xaf, 0x64, 0x12, 0x2a,
-0x06, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1c, 0x83, 0xe0,
-0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, 0x31,
-0x32, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0x32, 0x30, 0x09, 0x07, 0x12, 0x1c, 0x83, 0xe0, 0x44,
-0x80, 0xf0, 0x12, 0x31, 0xc7, 0x22, 0x12, 0x10, 0x03, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0,
-0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13,
-0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01,
-0xf0, 0x80, 0x0d, 0x12, 0x1d, 0x2f, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0,
-0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xb0, 0x12, 0x1d, 0x37, 0x02, 0x10, 0x86,
-0x12, 0x10, 0x03, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0x06, 0x90, 0xf9, 0x67, 0x12,
-0x1b, 0x3a, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, 0x08,
-0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0x25, 0x12, 0x31, 0xc7,
-0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x3f, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x8f, 0x63, 0x12,
-0x2a, 0x06, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3,
-0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3,
-0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6,
-0x7f, 0x00, 0x22, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 0x78, 0x7e, 0x12,
-0x21, 0xeb, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x22, 0x4a, 0x12, 0x21, 0xef, 0xe0, 0x20, 0xe0, 0xf6,
-0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7,
-0xaf, 0x23, 0x12, 0x13, 0x3f, 0x22, 0x12, 0x10, 0x03, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x4a, 0x24,
-0x06, 0x12, 0x21, 0xf1, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x03, 0x12, 0x22, 0x52, 0x24,
-0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x4a, 0x12, 0x31, 0xc7, 0x7d, 0x02,
-0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0xae, 0x05, 0x12, 0x1c, 0xde, 0xef, 0x12, 0x1a,
-0x4a, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee,
-0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02,
-0x12, 0x1a, 0x4a, 0xaf, 0x06, 0x12, 0x31, 0xb1, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01,
-0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22,
-0x74, 0x6e, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 0x74, 0x96, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa,
-0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04,
-0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04,
-0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f,
-0x00, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60,
-0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00,
-0x40, 0x05, 0x12, 0x28, 0x16, 0x80, 0x03, 0x12, 0x31, 0xbd, 0x02, 0x10, 0x86, 0x90, 0xff, 0xfc,
-0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04,
-0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4,
-0xf0, 0x80, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0,
-0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x19,
-0x12, 0x1d, 0x46, 0x02, 0x10, 0x86, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f,
-0x70, 0x02, 0x15, 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0,
-0x12, 0x0f, 0xdc, 0x80, 0xe5, 0x22, 0x11, 0x94, 0x2d, 0xf6, 0x23, 0xef, 0x31, 0xa3, 0x2f, 0xf4,
-0x2f, 0xa2, 0x30, 0xb2, 0x2e, 0xe6, 0x26, 0x6d, 0x2b, 0xaf, 0x30, 0x55, 0x30, 0x74, 0x1d, 0xb4,
-0x2e, 0x40, 0x2a, 0xe8, 0x0e, 0x12, 0x10, 0x03, 0x78, 0x86, 0x12, 0x22, 0x82, 0x20, 0xe1, 0x07,
-0x7f, 0x12, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x23, 0x49, 0x12, 0x30,
-0xec, 0x02, 0x10, 0x86, 0x12, 0x10, 0x03, 0x78, 0x87, 0x12, 0x22, 0x82, 0x20, 0xe2, 0x07, 0x7f,
-0x11, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2e, 0x7d, 0x12, 0x30, 0xec,
-0x02, 0x10, 0x86, 0x8f, 0x61, 0x12, 0x2e, 0x7d, 0xaf, 0x61, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12,
-0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13,
-0x3f, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60,
-0x05, 0x12, 0x2c, 0x07, 0x80, 0x06, 0x12, 0x1d, 0x64, 0x12, 0x1d, 0x6c, 0x02, 0x10, 0x86, 0x12,
-0x29, 0x93, 0x12, 0x12, 0xbb, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12,
-0x58, 0x12, 0x29, 0x1d, 0x12, 0x12, 0xf7, 0x12, 0x11, 0x74, 0x80, 0xe3, 0x12, 0x1c, 0xde, 0xef,
-0x12, 0x1a, 0x4a, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff,
-0x12, 0x31, 0xb1, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5,
-0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff,
-0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22,
-0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 0x1c, 0x95, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12,
-0x1c, 0xe8, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00,
-0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22,
-0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85,
-0x3b, 0x39, 0x85, 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f,
-0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x31, 0x47, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe,
-0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x12, 0x10, 0x03, 0x7f, 0x02, 0x12, 0x10, 0x92, 0x12, 0x1d, 0x46, 0x02, 0x10,
-0x86, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0x30, 0x12, 0x2c, 0x07, 0x22, 0x12, 0x1d, 0x6c,
-0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x64, 0x22, 0xc2, 0x08, 0x22,
+0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x0c, 0xef,
+0x12, 0x1a, 0xfa, 0x12, 0x22, 0xb5, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0x0c,
+0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 0xe5, 0x0e,
+0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 0xe5, 0x53,
+0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 0xe5, 0x53,
+0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 0x80, 0xe5,
+0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 0x08, 0xe5,
+0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43,
+0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 0x12, 0x1b,
+0x9f, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 0xe7, 0x90,
+0x00, 0x08, 0xef, 0x12, 0x1a, 0xfa, 0x80, 0x0a, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x08, 0xe4, 0x12,
+0x1a, 0xfa, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x07, 0xef, 0x12, 0x1a, 0xfa,
+0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0xfa, 0x90, 0x00, 0x07,
+0x12, 0x1a, 0xbb, 0x70, 0x13, 0x12, 0x22, 0xe8, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 0xfa, 0x12,
+0x1a, 0xa2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0xe8, 0x12, 0x23, 0x27, 0x24, 0x08, 0x12, 0x22, 0xa1,
+0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0xee,
+0xed, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x9f, 0x12, 0x32, 0x84,
+0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0xb4, 0x02, 0x10, 0xce, 0x90, 0xfa, 0xe6, 0xe0, 0xb4, 0x03,
+0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xda, 0xee, 0xf0,
+0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, 0xff, 0x7e, 0x00, 0x90, 0xfa, 0xd6, 0xee,
+0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1b, 0x48, 0xff,
+0x90, 0xfa, 0xd8, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 0x50, 0x8f,
+0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 0xdb, 0xe0,
+0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd9, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 0xfa, 0xdd,
+0xf0, 0xc3, 0x90, 0xfa, 0xd7, 0xe0, 0x9f, 0x90, 0xfa, 0xd6, 0xe0, 0x94, 0x00, 0x50, 0x06, 0xa3,
+0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x12, 0x20, 0xa9, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2e, 0x2b,
+0x90, 0xfa, 0xd6, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xda, 0xe0, 0xfc,
+0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x80,
+0x08, 0x90, 0xfa, 0xd7, 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x12, 0x20, 0xa9, 0x60, 0x03, 0xe0, 0xff,
+0x22, 0x12, 0x2e, 0x2b, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x2d, 0xf5,
+0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 0x01, 0x90,
+0xfa, 0xd8, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xdd, 0xe0, 0xf5, 0x4a, 0x12, 0x29, 0x60,
+0x90, 0xfa, 0xdc, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 0x2e, 0x24,
+0xfe, 0x70, 0x03, 0x02, 0x21, 0x69, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0xb1, 0x78, 0x71, 0xe6,
+0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 0x90, 0xfa,
+0x94, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb2, 0x74, 0x01, 0xf0, 0x22, 0x78, 0x72, 0xe6,
+0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 0x90, 0xfa,
+0x96, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb3, 0x74, 0x01, 0xf0, 0x22, 0x90, 0xfa, 0xa0,
+0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0xb1, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0,
+0xa3, 0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xa6, 0x12,
+0x23, 0x0d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xce, 0xe0,
+0xff, 0x74, 0x34, 0xfe, 0x12, 0x2d, 0x85, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74,
+0x34, 0x90, 0xfa, 0x98, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xaa, 0xe0, 0xa3, 0x30, 0xe5,
+0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xff,
+0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x23, 0x0d, 0x90, 0xff, 0xb6, 0xe0, 0x90,
+0xfa, 0xcd, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 0x2d, 0x85,
+0xef, 0x70, 0x0e, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x9a, 0xf0, 0xef, 0xa3,
+0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0,
+0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x90,
+0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xcc, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 0x12, 0x1b,
+0xfc, 0x22, 0x69, 0x26, 0x22, 0x69, 0x2e, 0x22, 0x0c, 0x30, 0x22, 0x0c, 0x32, 0x22, 0x1a, 0x38,
+0x22, 0x2c, 0x3a, 0x22, 0x5e, 0x3e, 0x22, 0x49, 0x44, 0x22, 0x3e, 0x46, 0x22, 0x54, 0x50, 0x22,
+0x54, 0x52, 0x22, 0x54, 0x54, 0x22, 0x54, 0x56, 0x00, 0x00, 0x22, 0x6e, 0x90, 0xfa, 0xcc, 0xe0,
+0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x5e, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x03,
+0x12, 0x11, 0x5e, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 0x7d, 0x01,
+0x7f, 0x02, 0x12, 0x11, 0x5e, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 0x7c, 0x00,
+0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x5e, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x06, 0x12,
+0x11, 0x5e, 0x80, 0x28, 0x90, 0xfa, 0xcc, 0xe0, 0xff, 0x12, 0x20, 0xc6, 0x80, 0x1e, 0x7c, 0x00,
+0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x5e, 0x80, 0x13, 0x12, 0x28, 0x4e, 0x80, 0x0e, 0x90, 0xfa,
+0xcc, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2d, 0x85, 0xd0, 0x07, 0xd0, 0x06,
+0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82,
+0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 0x04, 0x8e,
+0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x13, 0x25, 0x24, 0xf5, 0x82, 0xe4,
+0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22,
+0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a,
+0x32, 0x79, 0x56, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x1a, 0x7c, 0x78, 0x80, 0xe6, 0xfc, 0x08, 0xe6,
+0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0xff, 0x90, 0xf9, 0x6f, 0x02, 0x1b, 0xea, 0x90, 0xf9,
+0x6a, 0x12, 0x1b, 0xea, 0x90, 0x00, 0x04, 0x02, 0x1a, 0xbb, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6,
+0xff, 0x22, 0xed, 0x12, 0x1a, 0xfa, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90,
+0xfa, 0xce, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x80,
+0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83,
+0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 0xfb,
+0x22, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22,
+0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82,
+0x22, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xd2, 0xe4, 0xf0, 0xa3, 0x74,
+0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xd1, 0x90, 0xfa, 0xd2, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0,
+0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xd1, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3,
+0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0xf0, 0x90, 0xfa, 0xd1,
+0xe0, 0xff, 0x90, 0xfa, 0xd4, 0xe4, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0x12, 0x23, 0xf0, 0x90, 0xfa,
+0xd4, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xd2, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xd1,
+0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xd2, 0xe4, 0x75, 0xf0, 0x04, 0x12,
+0x1b, 0x1c, 0x02, 0x23, 0x72, 0x90, 0xfa, 0xd3, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xd2, 0xe0,
+0x34, 0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1b, 0x80, 0x7f, 0x00, 0x22,
+0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xd1, 0x90, 0xfa, 0xd2, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1b, 0x1c,
+0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x26, 0x98, 0x8f, 0x62, 0x12, 0x2a, 0xc7, 0x12,
+0x22, 0xfa, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0,
+0x08, 0x12, 0x22, 0xdc, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x23, 0x06, 0x24, 0x0b, 0x12, 0x22,
+0xa1, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83,
+0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82,
+0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3,
+0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x22, 0xa1,
+0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x99, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5,
+0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82,
+0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x44, 0x80,
+0xf0, 0x12, 0x32, 0x84, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22,
+0x12, 0x10, 0x4b, 0x7f, 0x02, 0x12, 0x12, 0x61, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0,
+0xd2, 0xb1, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36,
+0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7e, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa,
+0x7f, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x7c, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa,
+0x7d, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74,
+0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe7, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90,
+0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43,
+0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7e, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7f,
+0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7d,
+0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x18, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe7,
+0xe0, 0xf5, 0xa8, 0x02, 0x10, 0xce, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2e, 0x0d, 0x90,
+0xfa, 0xc3, 0x12, 0x1b, 0xf3, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0xf3, 0x90,
+0xfa, 0xc7, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0xea, 0xe9,
+0x24, 0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc9, 0x12, 0x1b, 0xf3, 0xab, 0x5c, 0xaa, 0x5d,
+0xa9, 0x5e, 0x12, 0x2e, 0x19, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa,
+0xc1, 0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0xee,
+0xff, 0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc6, 0x12, 0x2d, 0xee, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83,
+0xf6, 0x12, 0x2d, 0xeb, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0xf4, 0x75, 0xf0, 0x02,
+0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xc7, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1b, 0x1c, 0xab, 0x5c, 0xaa,
+0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0xbb, 0x30, 0xe4, 0x03, 0x12, 0x2e, 0x03, 0x78,
+0x82, 0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xc2, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58,
+0x90, 0xfa, 0xc2, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xc1, 0xf0, 0x12, 0x1a, 0xa2, 0x24, 0x6e,
+0x60, 0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0xda, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x25,
+0x56, 0x80, 0x62, 0x12, 0x2e, 0x24, 0x12, 0x1f, 0xda, 0x90, 0xfa, 0xc2, 0xef, 0xf0, 0x80, 0x55,
+0x90, 0xfa, 0xc2, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0xda, 0x60, 0x09, 0x24, 0x30, 0x70,
+0x3e, 0x12, 0x2d, 0x30, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b,
+0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2e, 0x24, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb,
+0xfd, 0x90, 0x00, 0x08, 0x12, 0x1b, 0x48, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02,
+0xd0, 0x03, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xc1, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90,
+0xfa, 0xc2, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xc2, 0xe0, 0x12, 0x2e, 0x24, 0x90, 0x00, 0x02, 0x12,
+0x1a, 0xfa, 0x90, 0xfa, 0xc1, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c,
+0xe5, 0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2e, 0x53, 0x70, 0x16, 0x12, 0x2e, 0x72, 0xe5,
+0x2d, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0xd8, 0x50, 0xf2, 0x12, 0x27, 0x25, 0x40, 0x0b, 0x7f,
+0x00, 0x22, 0x12, 0x2e, 0x72, 0x12, 0x27, 0x25, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0,
+0xe5, 0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4,
+0xf0, 0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0xc1,
+0x40, 0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff,
+0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2e, 0x65, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b,
+0xe4, 0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0xc1, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12,
+0x2e, 0x65, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0xd8, 0x12, 0x10,
+0x4b, 0x78, 0x84, 0x12, 0x23, 0x31, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x31, 0xa9, 0x02, 0x27,
+0xbc, 0x78, 0x84, 0xe6, 0xf9, 0x24, 0x13, 0x12, 0x22, 0xad, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54,
+0x03, 0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44,
+0x04, 0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80,
+0x39, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0,
+0x80, 0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef,
+0x54, 0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80,
+0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x18, 0xe0, 0x04, 0xf0,
+0xaf, 0x01, 0x12, 0x22, 0xee, 0xfd, 0x12, 0x2f, 0xe5, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, 0x75,
+0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x28, 0x09, 0x02, 0x31,
+0x8c, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf,
+0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54,
+0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80,
+0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0xa9, 0xe4, 0x7e, 0x01, 0x93,
+0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60,
+0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4,
+0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3,
+0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5,
+0x22, 0x12, 0x1d, 0xc2, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x30, 0x13,
+0x12, 0x1d, 0xc2, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5,
+0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x94, 0x12, 0x1e, 0x03, 0x60, 0x2c, 0x12, 0x2d,
+0x85, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x94, 0x12, 0x1b, 0xcc, 0xe4,
+0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0xa0, 0x12, 0x1b, 0xcc, 0xe0, 0xa3,
+0x30, 0xe6, 0x33, 0x12, 0x1d, 0xc2, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90,
+0xfa, 0x98, 0x12, 0x1e, 0x03, 0x60, 0x16, 0x12, 0x2d, 0x85, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02,
+0xe5, 0x22, 0x90, 0xfa, 0x98, 0x12, 0x1b, 0xcc, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5,
+0x22, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe,
+0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0,
+0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x0f, 0x12, 0x1c, 0xb0, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5,
+0x3a, 0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5,
+0x39, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0xdf, 0x12, 0x1e,
+0x34, 0x12, 0x1e, 0x26, 0x12, 0x1a, 0xa2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e,
+0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0xbb, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f,
+0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x5e, 0x12, 0x1e, 0x3b, 0x12, 0x25, 0xfa, 0x12,
+0x1d, 0x89, 0x12, 0x1a, 0xbb, 0x60, 0x03, 0x02, 0x32, 0x7a, 0xe4, 0xff, 0x12, 0x32, 0x6e, 0x22,
+0x8b, 0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2e, 0x53, 0x70,
+0x16, 0x12, 0x2e, 0x72, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0xd8, 0x50, 0xf2, 0x12,
+0x29, 0xd5, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2e, 0x72, 0x12, 0x29, 0xd5, 0x50, 0xf8, 0xe4,
+0xf5, 0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0xc5, 0x40,
+0x03, 0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5,
+0x46, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0xc5, 0x40, 0x03, 0x7f,
+0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x1a, 0xa2, 0x90, 0xff,
+0xf1, 0xf0, 0x02, 0x31, 0xd8, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0xd8, 0x7b, 0x01,
+0x7a, 0xfa, 0x79, 0xcf, 0xe4, 0xfd, 0x12, 0x23, 0x61, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x09,
+0x12, 0x1b, 0x1c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01,
+0x12, 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xff, 0xf7,
+0xe5, 0x23, 0x12, 0x2a, 0x39, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcf, 0xe4, 0xf0,
+0xa3, 0x74, 0x06, 0x12, 0x2a, 0x39, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94,
+0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23,
+0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d,
+0x01, 0x02, 0x26, 0x98, 0x90, 0xff, 0x93, 0x74, 0x81, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06,
+0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9,
+0x16, 0xf0, 0xa3, 0xf0, 0x12, 0x2b, 0x39, 0x12, 0x16, 0xc9, 0x12, 0x30, 0x69, 0x7e, 0x07, 0x7f,
+0xd0, 0x12, 0x12, 0x2a, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x12, 0x44, 0xe4, 0x78, 0x77, 0xf6, 0x78,
+0x77, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77,
+0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x30, 0xb2, 0x90, 0xf9, 0x16, 0xe0, 0x20, 0xe4, 0x05, 0x7f,
+0x04, 0x12, 0x30, 0xb2, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8,
+0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05,
+0x12, 0x11, 0xae, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c,
+0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76,
+0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76,
+0x9e, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x23, 0x49, 0x7b, 0x01, 0x7a,
+0xff, 0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0xe1, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08,
+0xa4, 0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x23, 0x49, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0xe1,
+0x78, 0x6d, 0xef, 0x12, 0x23, 0x49, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0,
+0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe6, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcf,
+0xe4, 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x7e, 0x00, 0x90, 0xfa, 0xe4, 0xee,
+0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcf, 0xe0, 0xb4, 0x52, 0x09, 0x90,
+0xf9, 0x16, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe4, 0xe0, 0x70, 0x04, 0xa3, 0xe0,
+0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcf, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x16, 0xe0, 0x44,
+0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe6, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x54, 0xef,
+0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x03, 0x68, 0x01, 0xff, 0x48, 0x03, 0x6b,
+0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x98, 0x00, 0x00, 0x00, 0x00, 0x44, 0xfa,
+0x94, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xb2, 0x00, 0x00, 0x42, 0xfa, 0x7e, 0x00, 0x00, 0x42,
+0xfa, 0x7c, 0x00, 0x00, 0x42, 0xf9, 0x6d, 0xff, 0xff, 0x42, 0xfa, 0x7a, 0x00, 0x00, 0x41, 0xf9,
+0x66, 0xff, 0x41, 0xf9, 0x1c, 0x19, 0x41, 0xf9, 0x15, 0x00, 0x43, 0xf9, 0x19, 0x0a, 0x32, 0x02,
+0x41, 0xf9, 0x68, 0x20, 0x41, 0xf9, 0x69, 0x20, 0x41, 0xf9, 0x65, 0x00, 0x41, 0xf9, 0x67, 0x00,
+0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 0x16, 0x00, 0x00, 0x41, 0xf9, 0x18, 0x00,
+0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x10, 0x4b, 0x78, 0x8a, 0xef, 0xf6, 0x12,
+0x2a, 0xc7, 0x12, 0x22, 0xee, 0x30, 0xe0, 0x29, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x54, 0x7f,
+0xf0, 0x78, 0x6b, 0x12, 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x12, 0x1a, 0xbb, 0x30, 0xe7, 0x09, 0x90,
+0x00, 0x02, 0xe4, 0x12, 0x1a, 0xfa, 0x80, 0xe9, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x44, 0x80,
+0xf0, 0x12, 0x22, 0xee, 0x30, 0xe1, 0x1e, 0x12, 0x22, 0x97, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x32,
+0x19, 0x78, 0x68, 0x12, 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0xfa, 0x12, 0x22,
+0x97, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x32, 0x84, 0xe4, 0xff, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce,
+0x12, 0x10, 0x4b, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x31, 0x50, 0x12, 0x31, 0xa9, 0x78, 0x85, 0xe6,
+0xff, 0x24, 0x13, 0x12, 0x22, 0xad, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90,
+0xff, 0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80,
+0x19, 0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20,
+0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x18, 0xe0, 0x14, 0xf0,
+0xe0, 0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0xce, 0x12, 0x1e, 0x1c, 0xe5, 0x3a, 0x64, 0x09, 0x70,
+0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00,
+0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5,
+0x39, 0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1e, 0x34, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12,
+0x1c, 0xc1, 0x12, 0x1a, 0xa2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83,
+0xed, 0xf0, 0x0e, 0x12, 0x1c, 0xb0, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22,
+0x8b, 0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2e, 0x19, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22,
+0xab, 0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2e, 0x0d, 0x90, 0xfa, 0xc9, 0x12, 0x1b, 0xf3, 0xe5,
+0x5b, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0xf3, 0xe4, 0x90,
+0xfa, 0xc2, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xc1, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f,
+0x50, 0x12, 0x12, 0x2d, 0xeb, 0xff, 0x12, 0x2d, 0xf4, 0x12, 0x2e, 0x07, 0x78, 0x8b, 0x06, 0x12,
+0x2e, 0x03, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x32, 0x0a, 0xe4, 0x93, 0xff, 0x78,
+0x74, 0xf6, 0x54, 0x0f, 0x12, 0x1d, 0xa8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c,
+0xd9, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6,
+0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f,
+0x00, 0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed,
+0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58,
+0x90, 0x00, 0x03, 0x12, 0x1a, 0xbb, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc9, 0x12, 0x1b,
+0xea, 0x02, 0x1a, 0xa2, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0xea, 0xef, 0x12, 0x1a, 0xe8, 0x90, 0xfa,
+0xca, 0xe4, 0x22, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1b, 0x1c, 0x90, 0x00, 0x08,
+0x12, 0x1b, 0x48, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, 0x90,
+0xfa, 0xc1, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xdd, 0xe0, 0xff,
+0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd7, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd6, 0xe0, 0x9e, 0xf0, 0x90,
+0xfa, 0xd8, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50,
+0xf5, 0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa,
+0xe6, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02,
+0x1a, 0xe8, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64,
+0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0xef, 0x7f, 0x02, 0x02, 0x31, 0xef, 0xaf, 0x64, 0x12,
+0x2a, 0xc7, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1d, 0x33,
+0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12,
+0x31, 0xef, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0xef, 0x30, 0x09, 0x07, 0x12, 0x1d, 0x33, 0xe0,
+0x44, 0x80, 0xf0, 0x12, 0x32, 0x84, 0x22, 0x12, 0x10, 0x4b, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60,
+0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7,
+0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44,
+0x01, 0xf0, 0x80, 0x0d, 0x12, 0x1d, 0xdf, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe,
+0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xde, 0x12, 0x1d, 0xe7, 0x02, 0x10,
+0xce, 0x12, 0x10, 0x4b, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0xc7, 0x90, 0xf9, 0x6a,
+0x12, 0x1b, 0xea, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe,
+0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0xd3, 0x12, 0x32,
+0x84, 0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x87, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, 0x8f, 0x63,
+0x12, 0x2a, 0xc7, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04,
+0x12, 0x22, 0xa1, 0xe0, 0x54, 0x3f, 0xf0, 0x12, 0x23, 0x41, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0,
+0x54, 0xf8, 0xf0, 0x12, 0x32, 0x84, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f,
+0x00, 0x22, 0x12, 0x10, 0x4b, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xfa, 0x24, 0x06, 0x12, 0x22, 0x9f,
+0xe0, 0xfd, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x03, 0x12, 0x23, 0x02, 0x24, 0x05, 0x12, 0x22, 0xa1,
+0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0xfa, 0x12, 0x32, 0x84, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2f,
+0xb4, 0x02, 0x10, 0xce, 0xae, 0x05, 0x12, 0x1d, 0x8e, 0xef, 0x12, 0x1a, 0xfa, 0x0e, 0x0e, 0x0e,
+0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 0xd3, 0x94, 0x08, 0x74,
+0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x1a, 0xfa, 0xaf,
+0x06, 0x12, 0x32, 0x6e, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10,
+0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x6e, 0x2e, 0xf8,
+0x74, 0x02, 0x46, 0xf6, 0x74, 0x99, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0,
+0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2,
+0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0,
+0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x10,
+0x4b, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83,
+0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 0x40, 0x05, 0x12, 0x28,
+0xd7, 0x80, 0x03, 0x12, 0x32, 0x7a, 0x02, 0x10, 0xce, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f,
+0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f,
+0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22,
+0x12, 0x10, 0x4b, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f,
+0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x61, 0x12, 0x1d, 0xf6, 0x02,
+0x10, 0xce, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xc0, 0x78, 0x7e, 0x12, 0x23,
+0x42, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x32, 0x84, 0xaf, 0x23, 0x12,
+0x13, 0x87, 0x22, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 0x70, 0x02, 0x15,
+0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x10, 0x24,
+0x80, 0xe5, 0x22, 0x11, 0xdc, 0x2e, 0xc7, 0x24, 0xb0, 0x32, 0x60, 0x30, 0x90, 0x30, 0x3e, 0x31,
+0x6f, 0x2f, 0x82, 0x27, 0x2e, 0x2c, 0x80, 0x31, 0x12, 0x31, 0x31, 0x1e, 0x64, 0x2f, 0x11, 0x2c,
+0x18, 0x0e, 0x12, 0x10, 0x4b, 0x78, 0x86, 0x12, 0x23, 0x31, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12,
+0x31, 0xa9, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x24, 0x0a, 0x12, 0x31, 0xa9, 0x02, 0x10,
+0xce, 0x12, 0x10, 0x4b, 0x78, 0x87, 0x12, 0x23, 0x31, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x31,
+0xa9, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2f, 0x4e, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce,
+0x8f, 0x61, 0x12, 0x2f, 0x4e, 0xaf, 0x61, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xc0, 0x12, 0x32, 0x84,
+0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 0x87, 0x22, 0x12,
+0x10, 0x4b, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x05, 0x12, 0x2c,
+0xd8, 0x80, 0x06, 0x12, 0x1e, 0x14, 0x12, 0x1e, 0x1c, 0x02, 0x10, 0xce, 0x12, 0x2a, 0x54, 0x12,
+0x13, 0x03, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 0xa0, 0x12, 0x29,
+0xde, 0x12, 0x13, 0x3f, 0x12, 0x11, 0xbc, 0x80, 0xe3, 0x12, 0x1d, 0x8e, 0xef, 0x12, 0x1a, 0xfa,
+0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x32, 0x7a, 0xe4, 0xff, 0x12, 0x32, 0x6e,
+0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff,
+0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60,
+0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef,
+0x30, 0xe7, 0x08, 0x12, 0x1d, 0x45, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x1d, 0x98, 0xe0,
+0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40,
+0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 0xb7, 0xa3, 0xa3,
+0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x3b, 0x39, 0x85,
+0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4,
+0xfe, 0xee, 0x90, 0x32, 0x04, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3,
+0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x90, 0x0a, 0x02, 0x00, 0x00, 0x11, 0x13, 0x00,
+0x12, 0x10, 0x4b, 0x7f, 0x02, 0x12, 0x10, 0xda, 0x12, 0x1d, 0xf6, 0x02, 0x10, 0xce, 0x75, 0x39,
+0x00, 0x8f, 0x3a, 0x12, 0x1c, 0xe0, 0x12, 0x2c, 0xd8, 0x22, 0x12, 0x1e, 0x1c, 0x12, 0x1d, 0xdf,
+0x12, 0x1e, 0x14, 0x22, 0xc2, 0x08, 0x22,
};
#undef IMAGE_VERSION_NAME
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 544098d2b77..0d3903691e8 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -48,7 +48,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.7"
+#define DRIVER_VERSION "v0.7mode043006"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
#define DRIVER_DESC "Edgeport USB Serial Driver"
@@ -173,8 +173,12 @@ static struct usb_device_id edgeport_2port_id_table [] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
-// The 4-port shows up as two 2-port devices
+ /* The 4, 8 and 16 port devices show up as multiple 2 port devices */
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
{ }
};
@@ -209,6 +213,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) },
{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) },
+ { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) },
{ }
};
@@ -231,6 +239,7 @@ static int TIStayInBootMode = 0;
static int low_latency = EDGE_LOW_LATENCY;
static int closing_wait = EDGE_CLOSING_WAIT;
static int ignore_cpu_rev = 0;
+static int default_uart_mode = 0; /* RS232 */
static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length);
@@ -241,6 +250,10 @@ static int restart_read(struct edgeport_port *edge_port);
static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
static void edge_send(struct usb_serial_port *port);
+/* sysfs attributes */
+static int edge_create_sysfs_attrs(struct usb_serial_port *port);
+static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
+
/* circular buffer */
static struct edge_buf *edge_buf_alloc(unsigned int size);
static void edge_buf_free(struct edge_buf *eb);
@@ -1706,13 +1719,14 @@ static void edge_interrupt_callback (struct urb *urb)
int length = urb->actual_length;
int port_number;
int function;
- int status;
+ int retval;
__u8 lsr;
__u8 msr;
+ int status = urb->status;
dbg("%s", __FUNCTION__);
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -1720,10 +1734,12 @@ static void edge_interrupt_callback (struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
return;
default:
- dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status);
+ dev_err(&urb->dev->dev, "%s - nonzero urb status received: "
+ "%d\n", __FUNCTION__, status);
goto exit;
}
@@ -1781,10 +1797,10 @@ static void edge_interrupt_callback (struct urb *urb)
}
exit:
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status)
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
- __FUNCTION__, status);
+ __FUNCTION__, retval);
}
static void edge_bulk_in_callback (struct urb *urb)
@@ -1792,12 +1808,13 @@ static void edge_bulk_in_callback (struct urb *urb)
struct edgeport_port *edge_port = (struct edgeport_port *)urb->context;
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
- int status = 0;
+ int retval = 0;
int port_number;
+ int status = urb->status;
dbg("%s", __FUNCTION__);
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -1805,17 +1822,18 @@ static void edge_bulk_in_callback (struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
return;
default:
dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n",
- __FUNCTION__, urb->status );
+ __FUNCTION__, status);
}
- if (urb->status == -EPIPE)
+ if (status == -EPIPE)
goto exit;
- if (urb->status) {
+ if (status) {
dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__);
return;
}
@@ -1849,14 +1867,14 @@ exit:
spin_lock(&edge_port->ep_lock);
if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) {
urb->dev = edge_port->port->serial->dev;
- status = usb_submit_urb(urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
} else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) {
edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED;
}
spin_unlock(&edge_port->ep_lock);
- if (status)
+ if (retval)
dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
- __FUNCTION__, status);
+ __FUNCTION__, retval);
}
static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length)
@@ -1883,12 +1901,13 @@ static void edge_bulk_out_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ int status = urb->status;
dbg ("%s - port %d", __FUNCTION__, port->number);
edge_port->ep_write_urb_in_use = 0;
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -1896,11 +1915,12 @@ static void edge_bulk_out_callback (struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
return;
default:
- dev_err (&urb->dev->dev,"%s - nonzero write bulk status received: %d\n",
- __FUNCTION__, urb->status);
+ dev_err(&urb->dev->dev, "%s - nonzero write bulk status "
+ "received: %d\n", __FUNCTION__, status);
}
/* send any buffered data */
@@ -2351,7 +2371,7 @@ static int restart_read(struct edgeport_port *edge_port)
urb->complete = edge_bulk_in_callback;
urb->context = edge_port;
urb->dev = edge_port->port->serial->dev;
- status = usb_submit_urb(urb, GFP_KERNEL);
+ status = usb_submit_urb(urb, GFP_ATOMIC);
}
edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING;
edge_port->shadow_mcr |= MCR_RTS;
@@ -2524,14 +2544,6 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old
}
cflag = tty->termios->c_cflag;
- /* check that they really want us to change something */
- if (old_termios) {
- if (cflag == old_termios->c_cflag &&
- tty->termios->c_iflag == old_termios->c_iflag) {
- dbg ("%s - nothing to change", __FUNCTION__);
- return;
- }
- }
dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
tty->termios->c_cflag, tty->termios->c_iflag);
@@ -2758,7 +2770,7 @@ static int edge_startup (struct usb_serial *serial)
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 = 0; /* Default is RS232 */
+ edge_port->bUartMode = default_uart_mode;
}
return 0;
@@ -2784,6 +2796,7 @@ static void edge_shutdown (struct usb_serial *serial)
for (i=0; i < serial->num_ports; ++i) {
edge_port = usb_get_serial_port_data(serial->port[i]);
+ edge_remove_sysfs_attrs(edge_port->port);
if (edge_port) {
edge_buf_free(edge_port->ep_out_buf);
kfree(edge_port);
@@ -2795,6 +2808,48 @@ static void edge_shutdown (struct usb_serial *serial)
}
+/* Sysfs Attributes */
+
+static ssize_t show_uart_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+
+ return sprintf(buf, "%d\n", edge_port->bUartMode);
+}
+
+static ssize_t store_uart_mode(struct device *dev,
+ struct device_attribute *attr, const char *valbuf, size_t count)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
+ unsigned int v = simple_strtoul(valbuf, NULL, 0);
+
+ dbg("%s: setting uart_mode = %d", __FUNCTION__, v);
+
+ if (v < 256)
+ edge_port->bUartMode = v;
+ else
+ dev_err(dev, "%s - uart_mode %d is invalid\n", __FUNCTION__, v);
+
+ return count;
+}
+
+static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode, store_uart_mode);
+
+static int edge_create_sysfs_attrs(struct usb_serial_port *port)
+{
+ return device_create_file(&port->dev, &dev_attr_uart_mode);
+}
+
+static int edge_remove_sysfs_attrs(struct usb_serial_port *port)
+{
+ device_remove_file(&port->dev, &dev_attr_uart_mode);
+ return 0;
+}
+
+
/* Circular Buffer */
/*
@@ -2991,6 +3046,7 @@ static struct usb_serial_driver edgeport_1port_device = {
.unthrottle = edge_unthrottle,
.attach = edge_startup,
.shutdown = edge_shutdown,
+ .port_probe = edge_create_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -3022,6 +3078,7 @@ static struct usb_serial_driver edgeport_2port_device = {
.unthrottle = edge_unthrottle,
.attach = edge_startup,
.shutdown = edge_shutdown,
+ .port_probe = edge_create_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -3085,3 +3142,6 @@ MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs");
module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device");
+module_param(default_uart_mode, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(default_uart_mode, "Default uart_mode, 0=RS232, ...");
+
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
index e57fa117e48..8e1a491e52a 100644
--- a/drivers/usb/serial/io_usbvend.h
+++ b/drivers/usb/serial/io_usbvend.h
@@ -131,7 +131,7 @@
#define ION_DEVICE_ID_TI_EDGEPORT_2I 0x0207 // Edgeport/2i RS422/RS485
#define ION_DEVICE_ID_TI_EDGEPORT_421 0x020C // Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port)
#define ION_DEVICE_ID_TI_EDGEPORT_21 0x020D // Edgeport/21 2 RS232 + Parallel (lucent on a different hub port)
-#define ION_DEVICE_ID_TI_EDGEPORT_8 0x020F // Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_416 0x0212 // Edgeport/416
#define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 // Edgeport/1 RS232
#define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 // Edgeport/42 4 hub 2 RS232
#define ION_DEVICE_ID_TI_EDGEPORT_22I 0x021A // Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
@@ -143,12 +143,14 @@
#define ION_DEVICE_ID_TI_EDGEPORT_21C 0x021E // Edgeport/21c is a TI based Edgeport/2 with lucent chip
// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C)
-#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1 0x240 // Edgeport/1 RS232
-#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I 0x241 // Edgeport/1i- RS422 model
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1 0x0240 // Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I 0x0241 // Edgeport/1i- RS422 model
// Ti based software switchable RS232/RS422/RS485 devices
-#define ION_DEVICE_ID_TI_EDGEPORT_4S 0x242 // Edgeport/4s - software switchable model
-#define ION_DEVICE_ID_IT_EDGEPORT_8S 0x243 // Edgeport/8s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_4S 0x0242 // Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_8S 0x0243 // Edgeport/8s - software switchable model
+#define ION_DEVICE_ID_TI_EDGEPORT_8 0x0244 // Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_416B 0x0247 // Edgeport/416
/************************************************************************
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 4df0ec74e0b..0455c1552ae 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -732,11 +732,13 @@ static void ipaq_read_bulk_callback(struct urb *urb)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -870,11 +872,13 @@ static void ipaq_write_bulk_callback(struct urb *urb)
struct ipaq_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
-
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
return;
}
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index 1bc586064c7..1b94daa6158 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -167,11 +167,13 @@ static void ipw_read_bulk_callback(struct urb *urb)
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -369,13 +371,15 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp)
static void ipw_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
+ int status = urb->status;
dbg("%s", __FUNCTION__);
port->write_urb_busy = 0;
- if (urb->status)
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
usb_serial_port_softint(port);
}
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 9d847f69291..5ab6a0c5ac5 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -21,6 +21,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * 2007_Jun_21 Alan Cox <alan@redhat.com>
+ * Minimal cleanups for some of the driver problens and tty layer abuse.
+ * Still needs fixing to allow multiple dongles.
+ *
* 2002_Mar_07 greg kh
* moved some needed structures and #define values from the
* net/irda/irda-usb.h file into our file, as we don't want to depend on
@@ -109,6 +113,7 @@ static void ir_write_bulk_callback (struct urb *urb);
static void ir_read_bulk_callback (struct urb *urb);
static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios);
+/* Not that this lot means you can only have one per system */
static u8 ir_baud = 0;
static u8 ir_xbof = 0;
static u8 ir_add_bof = 0;
@@ -392,12 +397,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
static void ir_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
port->write_urb_busy = 0;
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -417,6 +424,7 @@ static void ir_read_bulk_callback (struct urb *urb)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -425,8 +433,7 @@ static void ir_read_bulk_callback (struct urb *urb)
return;
}
- switch (urb->status) {
-
+ switch (status) {
case 0: /* Successful */
/*
@@ -444,22 +451,12 @@ static void ir_read_bulk_callback (struct urb *urb)
urb->actual_length,
data);
- /*
- * Bypass flip-buffers, and feed the ldisc directly
- * due to our potentially large buffer size. Since we
- * used to set low_latency, this is exactly what the
- * tty layer did anyway :)
- */
tty = port->tty;
- /*
- * FIXME: must not do this in IRQ context
- */
- tty->ldisc.receive_buf(
- tty,
- data+1,
- NULL,
- urb->actual_length-1);
+ if (tty_buffer_request_room(tty, urb->actual_length - 1)) {
+ tty_insert_flip_string(tty, data+1, urb->actual_length - 1);
+ tty_flip_buffer_push(tty);
+ }
/*
* No break here.
@@ -490,7 +487,7 @@ static void ir_read_bulk_callback (struct urb *urb)
default:
dbg("%s - nonzero read bulk status received: %d",
__FUNCTION__,
- urb->status);
+ status);
break ;
}
@@ -501,8 +498,9 @@ static void ir_read_bulk_callback (struct urb *urb)
static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned char *transfer_buffer;
- unsigned int cflag;
int result;
+ speed_t baud;
+ int ir_baud;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -511,77 +509,59 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t
return;
}
- cflag = port->tty->termios->c_cflag;
- /* check that they really want us to change something */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s - nothing to change...", __FUNCTION__);
- return;
- }
+ baud = tty_get_baud_rate(port->tty);
+
+ /*
+ * FIXME, we should compare the baud request against the
+ * capability stated in the IR header that we got in the
+ * startup function.
+ */
+
+ switch (baud) {
+ case 2400: ir_baud = SPEED_2400; break;
+ case 9600: ir_baud = SPEED_9600; break;
+ case 19200: ir_baud = SPEED_19200; break;
+ case 38400: ir_baud = SPEED_38400; break;
+ case 57600: ir_baud = SPEED_57600; break;
+ case 115200: ir_baud = SPEED_115200; break;
+ case 576000: ir_baud = SPEED_576000; break;
+ case 1152000: ir_baud = SPEED_1152000; break;
+ case 4000000: ir_baud = SPEED_4000000; break;
+ break;
+ default:
+ ir_baud = SPEED_9600;
+ baud = 9600;
+ /* And once the new tty stuff is all done we need to
+ call back to correct the baud bits */
}
- /* All we can change is the baud rate */
- if (cflag & CBAUD) {
-
- dbg ("%s - asking for baud %d",
- __FUNCTION__,
- tty_get_baud_rate(port->tty));
-
- /*
- * FIXME, we should compare the baud request against the
- * capability stated in the IR header that we got in the
- * startup function.
- */
- switch (cflag & CBAUD) {
- case B2400: ir_baud = SPEED_2400; break;
- default:
- case B9600: ir_baud = SPEED_9600; break;
- case B19200: ir_baud = SPEED_19200; break;
- case B38400: ir_baud = SPEED_38400; break;
- case B57600: ir_baud = SPEED_57600; break;
- case B115200: ir_baud = SPEED_115200; break;
- case B576000: ir_baud = SPEED_576000; break;
- case B1152000: ir_baud = SPEED_1152000; break;
-#ifdef B4000000
- case B4000000: ir_baud = SPEED_4000000; break;
-#endif
- }
+ if (xbof == -1)
+ ir_xbof = ir_xbof_change(ir_add_bof);
+ else
+ ir_xbof = ir_xbof_change(xbof) ;
- if (xbof == -1) {
- ir_xbof = ir_xbof_change(ir_add_bof);
- } else {
- ir_xbof = ir_xbof_change(xbof) ;
- }
+ /* FIXME need to check to see if our write urb is busy right
+ * now, or use a urb pool.
+ *
+ * send the baud change out on an "empty" data packet
+ */
+ transfer_buffer = port->write_urb->transfer_buffer;
+ *transfer_buffer = ir_xbof | ir_baud;
- /* Notify the tty driver that the termios have changed. */
- port->tty->ldisc.set_termios(port->tty, NULL);
-
- /* FIXME need to check to see if our write urb is busy right
- * now, or use a urb pool.
- *
- * send the baud change out on an "empty" data packet
- */
- transfer_buffer = port->write_urb->transfer_buffer;
- *transfer_buffer = ir_xbof | ir_baud;
-
- usb_fill_bulk_urb (
- port->write_urb,
- port->serial->dev,
- usb_sndbulkpipe(port->serial->dev,
- port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer,
- 1,
- ir_write_bulk_callback,
- port);
-
- port->write_urb->transfer_flags = URB_ZERO_PACKET;
-
- result = usb_submit_urb (port->write_urb, GFP_KERNEL);
- if (result)
- dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
- }
- return;
+ usb_fill_bulk_urb (
+ port->write_urb,
+ port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer,
+ 1,
+ ir_write_bulk_callback,
+ port);
+
+ port->write_urb->transfer_flags = URB_ZERO_PACKET;
+
+ result = usb_submit_urb (port->write_urb, GFP_KERNEL);
+ if (result)
+ dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
}
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index e6966f12ed5..f2a6fce5de1 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -115,12 +115,13 @@ static int debug;
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.1.4"
+#define DRIVER_VERSION "v1.1.5"
#define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu"
#define DRIVER_DESC "Keyspan USB to Serial Converter Driver"
#define INSTAT_BUFLEN 32
#define GLOCONT_BUFLEN 64
+#define INDAT49W_BUFLEN 512
/* Per device and per port private data */
struct keyspan_serial_private {
@@ -129,9 +130,15 @@ struct keyspan_serial_private {
struct urb *instat_urb;
char instat_buf[INSTAT_BUFLEN];
+ /* added to support 49wg, where data from all 4 ports comes in on 1 EP */
+ /* and high-speed supported */
+ struct urb *indat_urb;
+ char indat_buf[INDAT49W_BUFLEN];
+
/* XXX this one probably will need a lock */
struct urb *glocont_urb;
char glocont_buf[GLOCONT_BUFLEN];
+ char ctrl_buf[8]; // for EP0 control message
};
struct keyspan_port_private {
@@ -179,12 +186,13 @@ struct keyspan_port_private {
/* Include Keyspan message headers. All current Keyspan Adapters
- make use of one of four message formats which are referred
- to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */
+ make use of one of five message formats which are referred
+ to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */
#include "keyspan_usa26msg.h"
#include "keyspan_usa28msg.h"
#include "keyspan_usa49msg.h"
#include "keyspan_usa90msg.h"
+#include "keyspan_usa67msg.h"
/* Functions used by new usb-serial code. */
@@ -419,14 +427,15 @@ static void usa26_indat_callback(struct urb *urb)
struct usb_serial_port *port;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
dbg ("%s", __FUNCTION__);
endpoint = usb_pipeendpoint(urb->pipe);
- if (urb->status) {
+ if (status) {
dbg("%s - nonzero status: %x on endpoint %d.",
- __FUNCTION__, urb->status, endpoint);
+ __FUNCTION__, status, endpoint);
return;
}
@@ -511,11 +520,12 @@ static void usa26_instat_callback(struct urb *urb)
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
int old_dcd_state, err;
+ int status = urb->status;
serial = (struct usb_serial *) urb->context;
- if (urb->status) {
- dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero status: %x", __FUNCTION__, status);
return;
}
if (urb->actual_length != 9) {
@@ -579,6 +589,7 @@ static void usa28_indat_callback(struct urb *urb)
struct tty_struct *tty;
unsigned char *data;
struct keyspan_port_private *p_priv;
+ int status = urb->status;
dbg ("%s", __FUNCTION__);
@@ -590,9 +601,9 @@ static void usa28_indat_callback(struct urb *urb)
return;
do {
- if (urb->status) {
+ if (status) {
dbg("%s - nonzero status: %x on endpoint %d.",
- __FUNCTION__, urb->status, usb_pipeendpoint(urb->pipe));
+ __FUNCTION__, status, usb_pipeendpoint(urb->pipe));
return;
}
@@ -648,11 +659,12 @@ static void usa28_instat_callback(struct urb *urb)
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
int old_dcd_state;
+ int status = urb->status;
serial = (struct usb_serial *) urb->context;
- if (urb->status) {
- dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero status: %x", __FUNCTION__, status);
return;
}
@@ -739,13 +751,14 @@ static void usa49_instat_callback(struct urb *urb)
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
int old_dcd_state;
+ int status = urb->status;
dbg ("%s", __FUNCTION__);
serial = (struct usb_serial *) urb->context;
- if (urb->status) {
- dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero status: %x", __FUNCTION__, status);
return;
}
@@ -805,14 +818,15 @@ static void usa49_indat_callback(struct urb *urb)
struct usb_serial_port *port;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
dbg ("%s", __FUNCTION__);
endpoint = usb_pipeendpoint(urb->pipe);
- if (urb->status) {
+ if (status) {
dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__,
- urb->status, endpoint);
+ status, endpoint);
return;
}
@@ -850,13 +864,90 @@ static void usa49_indat_callback(struct urb *urb)
}
}
+static void usa49wg_indat_callback(struct urb *urb)
+{
+ int i, len, x, err;
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+ dbg ("%s", __FUNCTION__);
+
+ serial = urb->context;
+
+ if (status) {
+ dbg("%s - nonzero status: %x", __FUNCTION__, status);
+ return;
+ }
+
+ /* inbound data is in the form P#, len, status, data */
+ i = 0;
+ len = 0;
+
+ if (urb->actual_length) {
+ while (i < urb->actual_length) {
+
+ /* Check port number from message*/
+ if (data[i] >= serial->num_ports) {
+ dbg ("%s - Unexpected port number %d",
+ __FUNCTION__, data[i]);
+ return;
+ }
+ port = serial->port[data[i++]];
+ tty = port->tty;
+ len = data[i++];
+
+ /* 0x80 bit is error flag */
+ if ((data[i] & 0x80) == 0) {
+ /* no error on any byte */
+ i++;
+ for (x = 1; x < len ; ++x)
+ if (port->open_count)
+ tty_insert_flip_char(tty,
+ data[i++], 0);
+ else
+ i++;
+ } else {
+ /*
+ * some bytes had errors, every byte has status
+ */
+ for (x = 0; x + 1 < len; x += 2) {
+ int stat = data[i], flag = 0;
+ if (stat & RXERROR_OVERRUN)
+ flag |= TTY_OVERRUN;
+ if (stat & RXERROR_FRAMING)
+ flag |= TTY_FRAME;
+ if (stat & RXERROR_PARITY)
+ flag |= TTY_PARITY;
+ /* XXX should handle break (0x10) */
+ if (port->open_count)
+ tty_insert_flip_char(tty,
+ data[i+1], flag);
+ i += 2;
+ }
+ }
+ if (port->open_count)
+ tty_flip_buffer_push(tty);
+ }
+ }
+
+ /* Resubmit urb so we continue receiving */
+ urb->dev = serial->dev;
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+}
+
/* not used, usa-49 doesn't have per-port control endpoints */
-static void usa49_outcont_callback(struct urb *urb)
+static void usa49_outcont_callback(struct urb *urb)
{
dbg ("%s", __FUNCTION__);
}
-static void usa90_indat_callback(struct urb *urb)
+static void usa90_indat_callback(struct urb *urb)
{
int i, err;
int endpoint;
@@ -864,15 +955,15 @@ static void usa90_indat_callback(struct urb *urb)
struct keyspan_port_private *p_priv;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
dbg ("%s", __FUNCTION__);
endpoint = usb_pipeendpoint(urb->pipe);
-
- if (urb->status) {
+ if (status) {
dbg("%s - nonzero status: %x on endpoint %d.",
- __FUNCTION__, urb->status, endpoint);
+ __FUNCTION__, status, endpoint);
return;
}
@@ -938,11 +1029,12 @@ static void usa90_instat_callback(struct urb *urb)
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
int old_dcd_state, err;
+ int status = urb->status;
serial = (struct usb_serial *) urb->context;
- if (urb->status) {
- dbg("%s - nonzero status: %x", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero status: %x", __FUNCTION__, status);
return;
}
if (urb->actual_length < 14) {
@@ -995,6 +1087,88 @@ static void usa90_outcont_callback(struct urb *urb)
}
}
+/* Status messages from the 28xg */
+static void usa67_instat_callback(struct urb *urb)
+{
+ int err;
+ unsigned char *data = urb->transfer_buffer;
+ struct keyspan_usa67_portStatusMessage *msg;
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+ int old_dcd_state;
+ int status = urb->status;
+
+ dbg ("%s", __FUNCTION__);
+
+ serial = urb->context;
+
+ if (status) {
+ dbg("%s - nonzero status: %x", __FUNCTION__, status);
+ return;
+ }
+
+ if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) {
+ dbg("%s - bad length %d", __FUNCTION__, urb->actual_length);
+ return;
+ }
+
+
+ /* Now do something useful with the data */
+ msg = (struct keyspan_usa67_portStatusMessage *)data;
+
+ /* Check port number from message and retrieve private data */
+ if (msg->port >= serial->num_ports) {
+ dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port);
+ return;
+ }
+
+ port = serial->port[msg->port];
+ p_priv = usb_get_serial_port_data(port);
+
+ /* Update handshaking pin state information */
+ old_dcd_state = p_priv->dcd_state;
+ p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0);
+ p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0);
+
+ if (port->tty && !C_CLOCAL(port->tty)
+ && old_dcd_state != p_priv->dcd_state) {
+ if (old_dcd_state)
+ tty_hangup(port->tty);
+ /* else */
+ /* wake_up_interruptible(&p_priv->open_wait); */
+ }
+
+ /* Resubmit urb so we continue receiving */
+ urb->dev = serial->dev;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err);
+}
+
+static void usa67_glocont_callback(struct urb *urb)
+{
+ struct usb_serial *serial;
+ struct usb_serial_port *port;
+ struct keyspan_port_private *p_priv;
+ int i;
+
+ dbg ("%s", __FUNCTION__);
+
+ serial = urb->context;
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ p_priv = usb_get_serial_port_data(port);
+
+ if (p_priv->resend_cont) {
+ dbg ("%s - sending setup", __FUNCTION__);
+ keyspan_usa67_send_setup(serial, port,
+ p_priv->resend_cont - 1);
+ break;
+ }
+ }
+}
+
static int keyspan_write_room (struct usb_serial_port *port)
{
struct keyspan_port_private *p_priv;
@@ -1311,6 +1485,11 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint,
return NULL;
}
+ if (endpoint == 0) {
+ /* control EP filled in when used */
+ return urb;
+ }
+
ep_desc = find_ep(serial, endpoint);
if (!ep_desc) {
/* leak the urb, something's wrong and the callers don't care */
@@ -1380,6 +1559,14 @@ static struct callbacks {
.outdat_callback = usa2x_outdat_callback,
.inack_callback = usa28_inack_callback,
.outcont_callback = usa90_outcont_callback,
+ }, {
+ /* msg_usa67 callbacks */
+ .instat_callback = usa67_instat_callback,
+ .glocont_callback = usa67_glocont_callback,
+ .indat_callback = usa26_indat_callback,
+ .outdat_callback = usa2x_outdat_callback,
+ .inack_callback = usa26_inack_callback,
+ .outcont_callback = usa26_outcont_callback,
}
};
@@ -1410,6 +1597,11 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
serial, s_priv->instat_buf, INSTAT_BUFLEN,
cback->instat_callback);
+ s_priv->indat_urb = keyspan_setup_urb
+ (serial, d_details->indat_endpoint, USB_DIR_IN,
+ serial, s_priv->indat_buf, INDAT49W_BUFLEN,
+ usa49wg_indat_callback);
+
s_priv->glocont_urb = keyspan_setup_urb
(serial, d_details->glocont_endpoint, USB_DIR_OUT,
serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
@@ -1685,8 +1877,8 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
}
/* Save reset port val for resend.
- Don't overwrite resend for close condition. */
- if (p_priv->resend_cont != 3)
+ Don't overwrite resend for open/close condition. */
+ if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
/* dbg ("%s - already writing", __FUNCTION__); */
@@ -1836,8 +2028,8 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
}
/* Save reset port val for resend.
- Don't overwrite resend for close condition. */
- if (p_priv->resend_cont != 3)
+ Don't overwrite resend for open/close condition. */
+ if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
if (this_urb->status == -EINPROGRESS) {
dbg ("%s already writing", __FUNCTION__);
@@ -1940,11 +2132,11 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
struct usb_serial_port *port,
int reset_port)
{
- struct keyspan_usa49_portControlMessage msg;
+ struct keyspan_usa49_portControlMessage msg;
+ struct usb_ctrlrequest *dr = NULL;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
- int glocont_urb;
struct urb *this_urb;
int err, device_port;
@@ -1954,10 +2146,9 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
- glocont_urb = d_details->glocont_endpoint;
this_urb = s_priv->glocont_urb;
- /* Work out which port within the device is being setup */
+ /* Work out which port within the device is being setup */
device_port = port->number - port->serial->minor;
dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port);
@@ -1969,9 +2160,10 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
}
/* Save reset port val for resend.
- Don't overwrite resend for close condition. */
- if (p_priv->resend_cont != 3)
+ Don't overwrite resend for open/close condition. */
+ if ((reset_port + 1) > p_priv->resend_cont)
p_priv->resend_cont = reset_port + 1;
+
if (this_urb->status == -EINPROGRESS) {
/* dbg ("%s - already writing", __FUNCTION__); */
mdelay(5);
@@ -2083,20 +2275,39 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
msg.dtr = p_priv->dtr_state;
p_priv->resend_cont = 0;
- memcpy (this_urb->transfer_buffer, &msg, sizeof(msg));
+
+ /* if the device is a 49wg, we send control message on usb control EP 0 */
+
+ if (d_details->product_id == keyspan_usa49wg_product_id) {
+ dr = (void *)(s_priv->ctrl_buf);
+ dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT;
+ dr->bRequest = 0xB0; /* 49wg control message */;
+ dr->wValue = 0;
+ dr->wIndex = 0;
+ dr->wLength = cpu_to_le16(sizeof(msg));
+
+ memcpy (s_priv->glocont_buf, &msg, sizeof(msg));
+
+ usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0),
+ (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg),
+ usa49_glocont_callback, serial);
+
+ } else {
+ memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
- /* send the data out the device on control endpoint */
- this_urb->transfer_buffer_length = sizeof(msg);
+ /* send the data out the device on control endpoint */
+ this_urb->transfer_buffer_length = sizeof(msg);
- this_urb->dev = serial->dev;
+ this_urb->dev = serial->dev;
+ }
if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err);
}
#if 0
else {
dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__,
- outcont_urb, this_urb->transfer_buffer_length,
- usb_pipeendpoint(this_urb->pipe));
+ outcont_urb, this_urb->transfer_buffer_length,
+ usb_pipeendpoint(this_urb->pipe));
}
#endif
@@ -2241,6 +2452,154 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial,
return (0);
}
+static int keyspan_usa67_send_setup(struct usb_serial *serial,
+ struct usb_serial_port *port,
+ int reset_port)
+{
+ struct keyspan_usa67_portControlMessage msg;
+ struct keyspan_serial_private *s_priv;
+ struct keyspan_port_private *p_priv;
+ const struct keyspan_device_details *d_details;
+ struct urb *this_urb;
+ int err, device_port;
+
+ dbg ("%s", __FUNCTION__);
+
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
+ d_details = s_priv->device_details;
+
+ this_urb = s_priv->glocont_urb;
+
+ /* Work out which port within the device is being setup */
+ device_port = port->number - port->serial->minor;
+
+ /* Make sure we have an urb then send the message */
+ if (this_urb == NULL) {
+ dbg("%s - oops no urb for port %d.", __FUNCTION__,
+ port->number);
+ return -1;
+ }
+
+ /* Save reset port val for resend.
+ Don't overwrite resend for open/close condition. */
+ if ((reset_port + 1) > p_priv->resend_cont)
+ p_priv->resend_cont = reset_port + 1;
+ if (this_urb->status == -EINPROGRESS) {
+ /* dbg ("%s - already writing", __FUNCTION__); */
+ mdelay(5);
+ return(-1);
+ }
+
+ memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage));
+
+ msg.port = device_port;
+
+ /* Only set baud rate if it's changed */
+ if (p_priv->old_baud != p_priv->baud) {
+ p_priv->old_baud = p_priv->baud;
+ msg.setClocking = 0xff;
+ if (d_details->calculate_baud_rate
+ (p_priv->baud, d_details->baudclk, &msg.baudHi,
+ &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) {
+ dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__,
+ p_priv->baud);
+ msg.baudLo = 0;
+ msg.baudHi = 125; /* Values for 9600 baud */
+ msg.prescaler = 10;
+ }
+ msg.setPrescaler = 0xff;
+ }
+
+ msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1;
+ switch (p_priv->cflag & CSIZE) {
+ case CS5:
+ msg.lcr |= USA_DATABITS_5;
+ break;
+ case CS6:
+ msg.lcr |= USA_DATABITS_6;
+ break;
+ case CS7:
+ msg.lcr |= USA_DATABITS_7;
+ break;
+ case CS8:
+ msg.lcr |= USA_DATABITS_8;
+ break;
+ }
+ if (p_priv->cflag & PARENB) {
+ /* note USA_PARITY_NONE == 0 */
+ msg.lcr |= (p_priv->cflag & PARODD)?
+ USA_PARITY_ODD: USA_PARITY_EVEN;
+ }
+ msg.setLcr = 0xff;
+
+ msg.ctsFlowControl = (p_priv->flow_control == flow_cts);
+ msg.xonFlowControl = 0;
+ msg.setFlowControl = 0xff;
+ msg.forwardingLength = 16;
+ msg.xonChar = 17;
+ msg.xoffChar = 19;
+
+ if (reset_port == 1) {
+ /* Opening port */
+ msg._txOn = 1;
+ msg._txOff = 0;
+ msg.txFlush = 0;
+ msg.txBreak = 0;
+ msg.rxOn = 1;
+ msg.rxOff = 0;
+ msg.rxFlush = 1;
+ msg.rxForward = 0;
+ msg.returnStatus = 0;
+ msg.resetDataToggle = 0xff;
+ } else if (reset_port == 2) {
+ /* Closing port */
+ msg._txOn = 0;
+ msg._txOff = 1;
+ msg.txFlush = 0;
+ msg.txBreak = 0;
+ msg.rxOn = 0;
+ msg.rxOff = 1;
+ msg.rxFlush = 1;
+ msg.rxForward = 0;
+ msg.returnStatus = 0;
+ msg.resetDataToggle = 0;
+ } else {
+ /* Sending intermediate configs */
+ msg._txOn = (! p_priv->break_on);
+ msg._txOff = 0;
+ msg.txFlush = 0;
+ msg.txBreak = (p_priv->break_on);
+ msg.rxOn = 0;
+ msg.rxOff = 0;
+ msg.rxFlush = 0;
+ msg.rxForward = 0;
+ msg.returnStatus = 0;
+ msg.resetDataToggle = 0x0;
+ }
+
+ /* Do handshaking outputs */
+ msg.setTxTriState_setRts = 0xff;
+ msg.txTriState_rts = p_priv->rts_state;
+
+ msg.setHskoa_setDtr = 0xff;
+ msg.hskoa_dtr = p_priv->dtr_state;
+
+ p_priv->resend_cont = 0;
+
+ memcpy(this_urb->transfer_buffer, &msg, sizeof(msg));
+
+ /* send the data out the device on control endpoint */
+ this_urb->transfer_buffer_length = sizeof(msg);
+ this_urb->dev = serial->dev;
+
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err != 0)
+ dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__,
+ err);
+ return (0);
+}
+
static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
{
struct usb_serial *serial = port->serial;
@@ -2265,6 +2624,9 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
case msg_usa90:
keyspan_usa90_send_setup(serial, port, reset_port);
break;
+ case msg_usa67:
+ keyspan_usa67_send_setup(serial, port, reset_port);
+ break;
}
}
@@ -2313,9 +2675,19 @@ static int keyspan_startup (struct usb_serial *serial)
keyspan_setup_urbs(serial);
- s_priv->instat_urb->dev = serial->dev;
- if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) {
- dbg("%s - submit instat urb failed %d", __FUNCTION__, err);
+ if (s_priv->instat_urb != NULL) {
+ s_priv->instat_urb->dev = serial->dev;
+ err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL);
+ if (err != 0)
+ dbg("%s - submit instat urb failed %d", __FUNCTION__,
+ err);
+ }
+ if (s_priv->indat_urb != NULL) {
+ s_priv->indat_urb->dev = serial->dev;
+ err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL);
+ if (err != 0)
+ dbg("%s - submit indat urb failed %d", __FUNCTION__,
+ err);
}
return (0);
@@ -2335,6 +2707,7 @@ static void keyspan_shutdown (struct usb_serial *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);
@@ -2348,6 +2721,7 @@ static void keyspan_shutdown (struct usb_serial *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];
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index c6830cbdc6d..8a0d1740152 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -99,6 +99,10 @@ static int keyspan_usa90_send_setup (struct usb_serial *serial,
struct usb_serial_port *port,
int reset_port);
+static int keyspan_usa67_send_setup (struct usb_serial *serial,
+ struct usb_serial_port *port,
+ int reset_port);
+
/* Struct used for firmware - increased size of data section
to allow Keyspan's 'C' firmware struct to be used unmodified */
struct ezusb_hex_record {
@@ -229,15 +233,17 @@ struct ezusb_hex_record {
#define keyspan_usa28_product_id 0x010f
#define keyspan_usa28x_product_id 0x0110
#define keyspan_usa28xa_product_id 0x0115
+#define keyspan_usa28xb_product_id 0x0110
+#define keyspan_usa28xg_product_id 0x0135
#define keyspan_usa49w_product_id 0x010a
#define keyspan_usa49wlc_product_id 0x012a
-
+#define keyspan_usa49wg_product_id 0x0131
struct keyspan_device_details {
/* product ID value */
int product_id;
- enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format;
+ enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} msg_format;
/* Number of physical ports */
int num_ports;
@@ -264,6 +270,9 @@ struct keyspan_device_details {
/* Endpoint used for input status */
int instat_endpoint;
+ /* Endpoint used for input data 49WG only */
+ int indat_endpoint;
+
/* Endpoint used for global control functions */
int glocont_endpoint;
@@ -287,6 +296,7 @@ static const struct keyspan_device_details usa18x_device_details = {
.inack_endpoints = {0x85},
.outcont_endpoints = {0x05},
.instat_endpoint = 0x87,
+ .indat_endpoint = -1,
.glocont_endpoint = 0x07,
.calculate_baud_rate = keyspan_usa19w_calc_baud,
.baudclk = KEYSPAN_USA18X_BAUDCLK,
@@ -303,6 +313,7 @@ static const struct keyspan_device_details usa19_device_details = {
.inack_endpoints = {0x83},
.outcont_endpoints = {0x03},
.instat_endpoint = 0x84,
+ .indat_endpoint = -1,
.glocont_endpoint = -1,
.calculate_baud_rate = keyspan_usa19_calc_baud,
.baudclk = KEYSPAN_USA19_BAUDCLK,
@@ -319,6 +330,7 @@ static const struct keyspan_device_details usa19qi_device_details = {
.inack_endpoints = {0x83},
.outcont_endpoints = {0x03},
.instat_endpoint = 0x84,
+ .indat_endpoint = -1,
.glocont_endpoint = -1,
.calculate_baud_rate = keyspan_usa28_calc_baud,
.baudclk = KEYSPAN_USA19_BAUDCLK,
@@ -335,6 +347,7 @@ static const struct keyspan_device_details mpr_device_details = {
.inack_endpoints = {0x83},
.outcont_endpoints = {0x03},
.instat_endpoint = 0x84,
+ .indat_endpoint = -1,
.glocont_endpoint = -1,
.calculate_baud_rate = keyspan_usa28_calc_baud,
.baudclk = KEYSPAN_USA19_BAUDCLK,
@@ -351,6 +364,7 @@ static const struct keyspan_device_details usa19qw_device_details = {
.inack_endpoints = {0x85},
.outcont_endpoints = {0x05},
.instat_endpoint = 0x87,
+ .indat_endpoint = -1,
.glocont_endpoint = 0x07,
.calculate_baud_rate = keyspan_usa19w_calc_baud,
.baudclk = KEYSPAN_USA19W_BAUDCLK,
@@ -367,6 +381,7 @@ static const struct keyspan_device_details usa19w_device_details = {
.inack_endpoints = {0x85},
.outcont_endpoints = {0x05},
.instat_endpoint = 0x87,
+ .indat_endpoint = -1,
.glocont_endpoint = 0x07,
.calculate_baud_rate = keyspan_usa19w_calc_baud,
.baudclk = KEYSPAN_USA19W_BAUDCLK,
@@ -383,6 +398,7 @@ static const struct keyspan_device_details usa19hs_device_details = {
.inack_endpoints = {-1},
.outcont_endpoints = {0x02},
.instat_endpoint = 0x82,
+ .indat_endpoint = -1,
.glocont_endpoint = -1,
.calculate_baud_rate = keyspan_usa19hs_calc_baud,
.baudclk = KEYSPAN_USA19HS_BAUDCLK,
@@ -399,6 +415,7 @@ static const struct keyspan_device_details usa28_device_details = {
.inack_endpoints = {0x85, 0x86},
.outcont_endpoints = {0x05, 0x06},
.instat_endpoint = 0x87,
+ .indat_endpoint = -1,
.glocont_endpoint = 0x07,
.calculate_baud_rate = keyspan_usa28_calc_baud,
.baudclk = KEYSPAN_USA28_BAUDCLK,
@@ -415,6 +432,7 @@ static const struct keyspan_device_details usa28x_device_details = {
.inack_endpoints = {0x85, 0x86},
.outcont_endpoints = {0x05, 0x06},
.instat_endpoint = 0x87,
+ .indat_endpoint = -1,
.glocont_endpoint = 0x07,
.calculate_baud_rate = keyspan_usa19w_calc_baud,
.baudclk = KEYSPAN_USA28X_BAUDCLK,
@@ -431,11 +449,28 @@ static const struct keyspan_device_details usa28xa_device_details = {
.inack_endpoints = {0x85, 0x86},
.outcont_endpoints = {0x05, 0x06},
.instat_endpoint = 0x87,
+ .indat_endpoint = -1,
.glocont_endpoint = 0x07,
.calculate_baud_rate = keyspan_usa19w_calc_baud,
.baudclk = KEYSPAN_USA28X_BAUDCLK,
};
+static const struct keyspan_device_details usa28xg_device_details = {
+ .product_id = keyspan_usa28xg_product_id,
+ .msg_format = msg_usa67,
+ .num_ports = 2,
+ .indat_endp_flip = 0,
+ .outdat_endp_flip = 0,
+ .indat_endpoints = {0x84, 0x88},
+ .outdat_endpoints = {0x02, 0x06},
+ .inack_endpoints = {-1, -1},
+ .outcont_endpoints = {-1, -1},
+ .instat_endpoint = 0x81,
+ .indat_endpoint = -1,
+ .glocont_endpoint = 0x01,
+ .calculate_baud_rate = keyspan_usa19w_calc_baud,
+ .baudclk = KEYSPAN_USA28X_BAUDCLK,
+};
/* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */
static const struct keyspan_device_details usa49w_device_details = {
@@ -449,6 +484,7 @@ static const struct keyspan_device_details usa49w_device_details = {
.inack_endpoints = {-1, -1, -1, -1},
.outcont_endpoints = {-1, -1, -1, -1},
.instat_endpoint = 0x87,
+ .indat_endpoint = -1,
.glocont_endpoint = 0x07,
.calculate_baud_rate = keyspan_usa19w_calc_baud,
.baudclk = KEYSPAN_USA49W_BAUDCLK,
@@ -465,11 +501,29 @@ static const struct keyspan_device_details usa49wlc_device_details = {
.inack_endpoints = {-1, -1, -1, -1},
.outcont_endpoints = {-1, -1, -1, -1},
.instat_endpoint = 0x87,
+ .indat_endpoint = -1,
.glocont_endpoint = 0x07,
.calculate_baud_rate = keyspan_usa19w_calc_baud,
.baudclk = KEYSPAN_USA19W_BAUDCLK,
};
+static const struct keyspan_device_details usa49wg_device_details = {
+ .product_id = keyspan_usa49wg_product_id,
+ .msg_format = msg_usa49,
+ .num_ports = 4,
+ .indat_endp_flip = 0,
+ .outdat_endp_flip = 0,
+ .indat_endpoints = {-1, -1, -1, -1}, /* single 'global' data in EP */
+ .outdat_endpoints = {0x01, 0x02, 0x04, 0x06},
+ .inack_endpoints = {-1, -1, -1, -1},
+ .outcont_endpoints = {-1, -1, -1, -1},
+ .instat_endpoint = 0x81,
+ .indat_endpoint = 0x88,
+ .glocont_endpoint = 0x00, /* uses control EP */
+ .calculate_baud_rate = keyspan_usa19w_calc_baud,
+ .baudclk = KEYSPAN_USA19W_BAUDCLK,
+};
+
static const struct keyspan_device_details *keyspan_devices[] = {
&usa18x_device_details,
&usa19_device_details,
@@ -481,9 +535,11 @@ static const struct keyspan_device_details *keyspan_devices[] = {
&usa28_device_details,
&usa28x_device_details,
&usa28xa_device_details,
+ &usa28xg_device_details,
/* 28xb not required as it renumerates as a 28x */
&usa49w_device_details,
&usa49wlc_device_details,
+ &usa49wg_device_details,
NULL,
};
@@ -510,8 +566,11 @@ static struct usb_device_id keyspan_ids_combined[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)},
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
{ } /* Terminating entry */
};
@@ -557,12 +616,15 @@ static struct usb_device_id keyspan_2port_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) },
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) },
{ } /* Terminating entry */
};
static struct usb_device_id keyspan_4port_ids[] = {
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) },
{ USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)},
+ { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)},
{ } /* Terminating entry */
};
@@ -573,7 +635,6 @@ static struct usb_serial_driver keyspan_pre_device = {
.name = "keyspan_no_firm",
},
.description = "Keyspan - (without firmware)",
- .usb_driver = &keyspan_driver,
.id_table = keyspan_pre_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -588,7 +649,6 @@ static struct usb_serial_driver keyspan_1port_device = {
.name = "keyspan_1",
},
.description = "Keyspan 1 port adapter",
- .usb_driver = &keyspan_driver,
.id_table = keyspan_1port_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -616,7 +676,6 @@ static struct usb_serial_driver keyspan_2port_device = {
.name = "keyspan_2",
},
.description = "Keyspan 2 port adapter",
- .usb_driver = &keyspan_driver,
.id_table = keyspan_2port_ids,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
@@ -644,11 +703,10 @@ static struct usb_serial_driver keyspan_4port_device = {
.name = "keyspan_4",
},
.description = "Keyspan 4 port adapter",
- .usb_driver = &keyspan_driver,
.id_table = keyspan_4port_ids,
.num_interrupt_in = NUM_DONT_CARE,
- .num_bulk_in = 5,
- .num_bulk_out = 5,
+ .num_bulk_in = NUM_DONT_CARE,
+ .num_bulk_out = NUM_DONT_CARE,
.num_ports = 4,
.open = keyspan_open,
.close = keyspan_close,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index dd0b66a6ed5..be9ac20a8f1 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -218,11 +218,12 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
struct tty_struct *tty = port->tty;
unsigned char *data = urb->transfer_buffer;
int i;
- int status;
+ int retval;
+ int status = urb->status;
struct keyspan_pda_private *priv;
priv = usb_get_serial_port_data(port);
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -230,10 +231,12 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, status);
goto exit;
}
@@ -268,10 +271,10 @@ static void keyspan_pda_rx_interrupt (struct urb *urb)
}
exit:
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status)
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
+ __FUNCTION__, retval);
}
diff --git a/drivers/usb/serial/keyspan_usa67msg.h b/drivers/usb/serial/keyspan_usa67msg.h
new file mode 100644
index 00000000000..20fa3e2f718
--- /dev/null
+++ b/drivers/usb/serial/keyspan_usa67msg.h
@@ -0,0 +1,254 @@
+/*
+ usa67msg.h
+
+ Copyright (c) 1998-2007 InnoSys Incorporated. All Rights Reserved
+ This file is available under a BSD-style copyright
+
+ Keyspan USB Async Firmware to run on Anchor FX1
+
+ 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 this licence text
+ without modification, this list of conditions, and the following
+ disclaimer. The following copyright notice must appear immediately at
+ the beginning of all source files:
+
+ Copyright (c) 1998-2007 InnoSys Incorporated. All Rights Reserved
+
+ This file is available under a BSD-style copyright
+
+ 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.
+
+ 3. The name of InnoSys Incorprated may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``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.
+
+ Fourth revision: This message format supports the USA28XG
+
+ Buffer formats for RX/TX data messages are not defined by
+ a structure, but are described here:
+
+ USB OUT (host -> USAxx, transmit) messages contain a
+ REQUEST_ACK indicator (set to 0xff to request an ACK at the
+ completion of transmit; 0x00 otherwise), followed by data:
+
+ RQSTACK DAT DAT DAT ...
+
+ with a total data length of up to 63.
+
+ USB IN (USAxx -> host, receive) messages begin with a status
+ byte in which the 0x80 bit is either:
+
+ (a) 0x80 bit clear
+ indicates that the bytes following it are all data
+ bytes:
+
+ STAT DATA DATA DATA DATA DATA ...
+
+ for a total of up to 63 DATA bytes,
+
+ or:
+
+ (b) 0x80 bit set
+ indiates that the bytes following alternate data and
+ status bytes:
+
+ STAT DATA STAT DATA STAT DATA STAT DATA ...
+
+ for a total of up to 32 DATA bytes.
+
+ The valid bits in the STAT bytes are:
+
+ OVERRUN 0x02
+ PARITY 0x04
+ FRAMING 0x08
+ BREAK 0x10
+
+ Notes:
+
+ (1) The OVERRUN bit can appear in either (a) or (b) format
+ messages, but the but the PARITY/FRAMING/BREAK bits
+ only appear in (b) format messages.
+ (2) For the host to determine the exact point at which the
+ overrun occurred (to identify the point in the data
+ stream at which the data was lost), it needs to count
+ 128 characters, starting at the first character of the
+ message in which OVERRUN was reported; the lost character(s)
+ would have been received between the 128th and 129th
+ characters.
+ (3) An RX data message in which the first byte has 0x80 clear
+ serves as a "break off" indicator.
+
+ revision history:
+
+ 1999feb10 add reportHskiaChanges to allow us to ignore them
+ 1999feb10 add txAckThreshold for fast+loose throughput enhancement
+ 1999mar30 beef up support for RX error reporting
+ 1999apr14 add resetDataToggle to control message
+ 2000jan04 merge with usa17msg.h
+ 2000jun01 add extended BSD-style copyright text
+ 2001jul05 change message format to improve OVERRUN case
+ 2002jun05 update copyright date, improve comments
+ 2006feb06 modify for FX1 chip
+
+*/
+
+#ifndef __USA67MSG__
+#define __USA67MSG__
+
+
+// all things called "ControlMessage" are sent on the 'control' endpoint
+
+typedef struct keyspan_usa67_portControlMessage
+{
+ u8 port; // 0 or 1 (selects port)
+ /*
+ there are three types of "commands" sent in the control message:
+
+ 1. configuration changes which must be requested by setting
+ the corresponding "set" flag (and should only be requested
+ when necessary, to reduce overhead on the device):
+ */
+ u8 setClocking, // host requests baud rate be set
+ baudLo, // host does baud divisor calculation
+ baudHi, // baudHi is only used for first port (gives lower rates)
+ externalClock_txClocking,
+ // 0=internal, other=external
+
+ setLcr, // host requests lcr be set
+ lcr, // use PARITY, STOPBITS, DATABITS below
+
+ setFlowControl, // host requests flow control be set
+ ctsFlowControl, // 1=use CTS flow control, 0=don't
+ xonFlowControl, // 1=use XON/XOFF flow control, 0=don't
+ xonChar, // specified in current character format
+ xoffChar, // specified in current character format
+
+ setTxTriState_setRts,
+ // host requests TX tri-state be set
+ txTriState_rts, // 1=active (normal), 0=tristate (off)
+
+ setHskoa_setDtr,
+ // host requests HSKOA output be set
+ hskoa_dtr, // 1=on, 0=off
+
+ setPrescaler, // host requests prescalar be set (default: 13)
+ prescaler; // specified as N/8; values 8-ff are valid
+ // must be set any time internal baud rate is set;
+ // must not be set when external clocking is used
+
+ /*
+ 3. configuration data which is simply used as is (no overhead,
+ but must be specified correctly in every host message).
+ */
+ u8 forwardingLength, // forward when this number of chars available
+ reportHskiaChanges_dsrFlowControl,
+ // 1=normal; 0=ignore external clock
+ // 1=use DSR flow control, 0=don't
+ txAckThreshold, // 0=not allowed, 1=normal, 2-255 deliver ACK faster
+ loopbackMode; // 0=no loopback, 1=loopback enabled
+
+ /*
+ 4. commands which are flags only; these are processed in order
+ (so that, e.g., if both _txOn and _txOff flags are set, the
+ port ends in a TX_OFF state); any non-zero value is respected
+ */
+ u8 _txOn, // enable transmitting (and continue if there's data)
+ _txOff, // stop transmitting
+ txFlush, // toss outbound data
+ txBreak, // turn on break (cleared by _txOn)
+ rxOn, // turn on receiver
+ rxOff, // turn off receiver
+ rxFlush, // toss inbound data
+ rxForward, // forward all inbound data, NOW (as if fwdLen==1)
+ returnStatus, // return current status (even if it hasn't changed)
+ resetDataToggle;// reset data toggle state to DATA0
+
+} keyspan_usa67_portControlMessage;
+
+// defines for bits in lcr
+#define USA_DATABITS_5 0x00
+#define USA_DATABITS_6 0x01
+#define USA_DATABITS_7 0x02
+#define USA_DATABITS_8 0x03
+#define STOPBITS_5678_1 0x00 // 1 stop bit for all byte sizes
+#define STOPBITS_5_1p5 0x04 // 1.5 stop bits for 5-bit byte
+#define STOPBITS_678_2 0x04 // 2 stop bits for 6/7/8-bit byte
+#define USA_PARITY_NONE 0x00
+#define USA_PARITY_ODD 0x08
+#define USA_PARITY_EVEN 0x18
+#define PARITY_1 0x28
+#define PARITY_0 0x38
+
+// all things called "StatusMessage" are sent on the status endpoint
+
+typedef struct keyspan_usa67_portStatusMessage // one for each port
+{
+ u8 port, // 0=first, 1=second, other=see below
+ hskia_cts, // reports HSKIA pin
+ gpia_dcd, // reports GPIA pin
+ _txOff, // port has been disabled (by host)
+ _txXoff, // port is in XOFF state (either host or RX XOFF)
+ txAck, // indicates a TX message acknowledgement
+ rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off
+ controlResponse;// 1=a control message has been processed
+} keyspan_usa67_portStatusMessage;
+
+// bits in RX data message when STAT byte is included
+#define RXERROR_OVERRUN 0x02
+#define RXERROR_PARITY 0x04
+#define RXERROR_FRAMING 0x08
+#define RXERROR_BREAK 0x10
+
+typedef struct keyspan_usa67_globalControlMessage
+{
+ u8 port, // 3
+ sendGlobalStatus, // 2=request for two status responses
+ resetStatusToggle, // 1=reset global status toggle
+ resetStatusCount; // a cycling value
+} keyspan_usa67_globalControlMessage;
+
+typedef struct keyspan_usa67_globalStatusMessage
+{
+ u8 port, // 3
+ sendGlobalStatus, // from request, decremented
+ resetStatusCount; // as in request
+} keyspan_usa67_globalStatusMessage;
+
+typedef struct keyspan_usa67_globalDebugMessage
+{
+ u8 port, // 2
+ a,
+ b,
+ c,
+ d;
+} keyspan_usa67_globalDebugMessage;
+
+// ie: the maximum length of an FX1 endpoint buffer
+#define MAX_DATA_LEN 64
+
+// update status approx. 60 times a second (16.6666 ms)
+#define STATUS_UPDATE_INTERVAL 16
+
+// status rationing tuning value (each port gets checked each n ms)
+#define STATUS_RATION 10
+
+#endif
+
+
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 7b085f334ce..5a4127e62c4 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -567,12 +567,13 @@ exit:
static void klsi_105_write_bulk_callback ( struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
-
- if (urb->status) {
+
+ if (status) {
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
- urb->status);
+ status);
return;
}
@@ -631,16 +632,17 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int rc;
+ int status = urb->status;
- dbg("%s - port %d", __FUNCTION__, port->number);
+ dbg("%s - port %d", __FUNCTION__, port->number);
/* The urb might have been killed. */
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
- urb->status);
- return;
- }
-
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d", __FUNCTION__,
+ status);
+ return;
+ }
+
/* The data received is again preceded by a length double-byte in LSB-
* first order (see klsi_105_write() )
*/
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 0683b51f093..02a86dbc0e9 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -358,24 +358,26 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
}
-static void kobil_read_int_callback( struct urb *purb)
+static void kobil_read_int_callback(struct urb *urb)
{
int result;
- struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
+ struct usb_serial_port *port = urb->context;
struct tty_struct *tty;
- unsigned char *data = purb->transfer_buffer;
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
// char *dbg_data;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (purb->status) {
- dbg("%s - port %d Read int status not zero: %d", __FUNCTION__, port->number, purb->status);
+ if (status) {
+ dbg("%s - port %d Read int status not zero: %d",
+ __FUNCTION__, port->number, status);
return;
}
-
- tty = port->tty;
- if (purb->actual_length) {
-
+
+ tty = port->tty;
+ if (urb->actual_length) {
+
// BEGIN DEBUG
/*
dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
@@ -390,15 +392,15 @@ static void kobil_read_int_callback( struct urb *purb)
*/
// END DEBUG
- tty_buffer_request_room(tty, purb->actual_length);
- tty_insert_flip_string(tty, data, purb->actual_length);
+ tty_buffer_request_room(tty, urb->actual_length);
+ tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty);
}
// someone sets the dev to 0 if the close method has been called
port->interrupt_in_urb->dev = port->serial->dev;
- result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC );
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
}
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 3db1adc25f8..2a3fabcf518 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -81,7 +81,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "z2.0" /* Linux in-kernel version */
+#define DRIVER_VERSION "z2.1" /* Linux in-kernel version */
#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
@@ -110,6 +110,10 @@ static int mct_u232_tiocmget (struct usb_serial_port *port,
static int mct_u232_tiocmset (struct usb_serial_port *port,
struct file *file, unsigned int set,
unsigned int clear);
+static void mct_u232_throttle (struct usb_serial_port *port);
+static void mct_u232_unthrottle (struct usb_serial_port *port);
+
+
/*
* All of the device info needed for the MCT USB-RS232 converter.
*/
@@ -145,6 +149,8 @@ static struct usb_serial_driver mct_u232_device = {
.num_ports = 1,
.open = mct_u232_open,
.close = mct_u232_close,
+ .throttle = mct_u232_throttle,
+ .unthrottle = mct_u232_unthrottle,
.read_int_callback = mct_u232_read_int_callback,
.ioctl = mct_u232_ioctl,
.set_termios = mct_u232_set_termios,
@@ -162,8 +168,11 @@ struct mct_u232_private {
unsigned char last_lcr; /* Line Control Register */
unsigned char last_lsr; /* Line Status Register */
unsigned char last_msr; /* Modem Status Register */
+ unsigned int rx_flags; /* Throttling flags */
};
+#define THROTTLED 0x01
+
/*
* Handle vendor specific USB requests
*/
@@ -216,11 +225,13 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value)
}
}
-static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
+static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
+ int value)
{
__le32 divisor;
int rc;
unsigned char zero_byte = 0;
+ unsigned char cts_enable_byte = 0;
divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
@@ -238,10 +249,17 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
'baud rate change' message. The actual functionality of the
request codes in these messages is not fully understood but these
particular codes are never seen in any operation besides a baud
- rate change. Both of these messages send a single byte of data
- whose value is always zero. The second of these two extra messages
- is required in order for data to be properly written to an RS-232
- device which does not assert the 'CTS' signal. */
+ rate change. Both of these messages send a single byte of data.
+ In the first message, the value of this byte is always zero.
+
+ The second message has been determined experimentally to control
+ whether data will be transmitted to a device which is not asserting
+ the 'CTS' signal. If the second message's data byte is zero, data
+ will be transmitted even if 'CTS' is not asserted (i.e. no hardware
+ flow control). if the second message's data byte is nonzero (a value
+ of 1 is used by this driver), data will not be transmitted to a device
+ which is not asserting 'CTS'.
+ */
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
MCT_U232_SET_UNKNOWN1_REQUEST,
@@ -252,14 +270,19 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
err("Sending USB device request code %d failed (error = %d)",
MCT_U232_SET_UNKNOWN1_REQUEST, rc);
+ if (port && C_CRTSCTS(port->tty)) {
+ cts_enable_byte = 1;
+ }
+
+ dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte);
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
- MCT_U232_SET_UNKNOWN2_REQUEST,
+ MCT_U232_SET_CTS_REQUEST,
MCT_U232_SET_REQUEST_TYPE,
- 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN2_SIZE,
+ 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE,
WDR_TIMEOUT);
if (rc < 0)
- err("Sending USB device request code %d failed (error = %d)",
- MCT_U232_SET_UNKNOWN2_REQUEST, rc);
+ err("Sending USB device request code %d failed (error = %d)",
+ MCT_U232_SET_CTS_REQUEST, rc);
return rc;
} /* mct_u232_set_baud_rate */
@@ -458,8 +481,25 @@ error:
static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
{
+ unsigned int c_cflag;
+ unsigned long flags;
+ unsigned int control_state;
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
dbg("%s port %d", __FUNCTION__, port->number);
+ if (port->tty) {
+ c_cflag = port->tty->termios->c_cflag;
+ if (c_cflag & HUPCL) {
+ /* drop DTR and RTS */
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+ control_state = priv->control_state;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ mct_u232_set_modem_ctrl(port->serial, control_state);
+ }
+ }
+
+
if (port->serial->dev) {
/* shutdown our urbs */
usb_kill_urb(port->write_urb);
@@ -476,10 +516,11 @@ static void mct_u232_read_int_callback (struct urb *urb)
struct usb_serial *serial = port->serial;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
- int status;
+ int retval;
+ int status = urb->status;
unsigned long flags;
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -487,10 +528,12 @@ static void mct_u232_read_int_callback (struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
- dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down with status: %d",
+ __FUNCTION__, status);
return;
default:
- dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, status);
goto exit;
}
@@ -554,10 +597,10 @@ static void mct_u232_read_int_callback (struct urb *urb)
#endif
spin_unlock_irqrestore(&priv->lock, flags);
exit:
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status)
+ retval = usb_submit_urb (urb, GFP_ATOMIC);
+ if (retval)
err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
+ __FUNCTION__, retval);
} /* mct_u232_read_int_callback */
static void mct_u232_set_termios (struct usb_serial_port *port,
@@ -565,11 +608,10 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
{
struct usb_serial *serial = port->serial;
struct mct_u232_private *priv = usb_get_serial_port_data(port);
- unsigned int iflag = port->tty->termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag;
unsigned int old_cflag = old_termios->c_cflag;
unsigned long flags;
- unsigned int control_state, new_state;
+ unsigned int control_state;
unsigned char last_lcr;
/* get a local copy of the current port settings */
@@ -585,18 +627,14 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
* Premature optimization is the root of all evil.
*/
- /* reassert DTR and (maybe) RTS on transition from B0 */
+ /* reassert DTR and RTS on transition from B0 */
if ((old_cflag & CBAUD) == B0) {
dbg("%s: baud was B0", __FUNCTION__);
- control_state |= TIOCM_DTR;
- /* don't set RTS if using hardware flow control */
- if (!(old_cflag & CRTSCTS)) {
- control_state |= TIOCM_RTS;
- }
+ control_state |= TIOCM_DTR | TIOCM_RTS;
mct_u232_set_modem_ctrl(serial, control_state);
}
- mct_u232_set_baud_rate(serial, cflag & CBAUD);
+ mct_u232_set_baud_rate(serial, port, cflag & CBAUD);
if ((cflag & CBAUD) == B0 ) {
dbg("%s: baud is B0", __FUNCTION__);
@@ -638,21 +676,6 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
mct_u232_set_line_ctrl(serial, last_lcr);
- /*
- * Set flow control: well, I do not really now how to handle DTR/RTS.
- * Just do what we have seen with SniffUSB on Win98.
- */
- /* Drop DTR/RTS if no flow control otherwise assert */
- new_state = control_state;
- if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
- new_state |= TIOCM_DTR | TIOCM_RTS;
- else
- new_state &= ~(TIOCM_DTR | TIOCM_RTS);
- if (new_state != control_state) {
- mct_u232_set_modem_ctrl(serial, new_state);
- control_state = new_state;
- }
-
/* save off the modified port settings */
spin_lock_irqsave(&priv->lock, flags);
priv->control_state = control_state;
@@ -747,6 +770,50 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
return 0;
} /* mct_u232_ioctl */
+static void mct_u232_throttle (struct usb_serial_port *port)
+{
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ unsigned int control_state;
+ struct tty_struct *tty;
+
+ tty = port->tty;
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->rx_flags |= THROTTLED;
+ if (C_CRTSCTS(tty)) {
+ priv->control_state &= ~TIOCM_RTS;
+ control_state = priv->control_state;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+ } else {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+}
+
+
+static void mct_u232_unthrottle (struct usb_serial_port *port)
+{
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ unsigned int control_state;
+ struct tty_struct *tty;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ tty = port->tty;
+ spin_lock_irqsave(&priv->lock, flags);
+ if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
+ priv->rx_flags &= ~THROTTLED;
+ priv->control_state |= TIOCM_RTS;
+ control_state = priv->control_state;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ (void) mct_u232_set_modem_ctrl(port->serial, control_state);
+ } else {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+}
static int __init mct_u232_init (void)
{
diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h
index 73dd0d984cd..a61bac8f224 100644
--- a/drivers/usb/serial/mct_u232.h
+++ b/drivers/usb/serial/mct_u232.h
@@ -63,14 +63,15 @@
#define MCT_U232_SET_UNKNOWN1_REQUEST 11 /* Unknown functionality */
#define MCT_U232_SET_UNKNOWN1_SIZE 1
-/* This USB device request code is not well understood. It is transmitted by
- the MCT-supplied Windows driver whenever the baud rate changes.
+/* This USB device request code appears to control whether CTS is required
+ during transmission.
- Without this USB device request, the USB/RS-232 adapter will not write to
- RS-232 devices which do not assert the 'CTS' signal.
+ Sending a zero byte allows data transmission to a device which is not
+ asserting CTS. Sending a '1' byte will cause transmission to be deferred
+ until the device asserts CTS.
*/
-#define MCT_U232_SET_UNKNOWN2_REQUEST 12 /* Unknown functionality */
-#define MCT_U232_SET_UNKNOWN2_SIZE 1
+#define MCT_U232_SET_CTS_REQUEST 12
+#define MCT_U232_SET_CTS_SIZE 1
/*
* Baud rate (divisor)
@@ -439,7 +440,7 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value);
* which says "U232-P9" ;-)
*
* The circuit board inside the adaptor contains a Philips PDIUSBD12
- * USB endpoint chip and a Phillips P87C52UBAA microcontroller with
+ * USB endpoint chip and a Philips P87C52UBAA microcontroller with
* embedded UART. Exhaustive documentation for these is available at:
*
* http://www.semiconductors.philips.com/pip/p87c52ubaa
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index b563e2ad872..231b584f6d0 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -9,9 +9,9 @@
* the Free Software Foundation, version 2 of the License.
*
* Developed by:
- * VijayaKumar.G.N. <vijaykumar@aspirecom.net>
- * AjayKumar <ajay@aspirecom.net>
- * Gurudeva.N. <gurudev@aspirecom.net>
+ * Vijaya Kumar <vijaykumar.gn@gmail.com>
+ * Ajay Kumar <naanuajay@yahoo.com>
+ * Gurudeva <ngurudeva@yahoo.com>
*
* Cleaned up from the original by:
* Greg Kroah-Hartman <gregkh@suse.de>
@@ -103,6 +103,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
{
int result;
int length;
+ int status = urb->status;
__u8 *data;
__u8 sp1;
__u8 sp2;
@@ -114,7 +115,7 @@ static void mos7720_interrupt_callback(struct urb *urb)
return;
}
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -123,11 +124,11 @@ static void mos7720_interrupt_callback(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__,
- urb->status);
+ status);
return;
default:
dbg("%s - nonzero urb status received: %d", __FUNCTION__,
- urb->status);
+ status);
goto exit;
}
@@ -198,14 +199,15 @@ exit:
*/
static void mos7720_bulk_in_callback(struct urb *urb)
{
- int status;
+ int retval;
unsigned char *data ;
struct usb_serial_port *port;
struct moschip_port *mos7720_port;
struct tty_struct *tty;
+ int status = urb->status;
- if (urb->status) {
- dbg("nonzero read bulk status received: %d",urb->status);
+ if (status) {
+ dbg("nonzero read bulk status received: %d", status);
return;
}
@@ -236,10 +238,10 @@ static void mos7720_bulk_in_callback(struct urb *urb)
if (port->read_urb->status != -EINPROGRESS) {
port->read_urb->dev = port->serial->dev;
- status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- if (status)
- dbg("usb_submit_urb(read bulk) failed, status = %d",
- status);
+ retval = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (retval)
+ dbg("usb_submit_urb(read bulk) failed, retval = %d",
+ retval);
}
}
@@ -252,9 +254,10 @@ static void mos7720_bulk_out_data_callback(struct urb *urb)
{
struct moschip_port *mos7720_port;
struct tty_struct *tty;
+ int status = urb->status;
- if (urb->status) {
- dbg("nonzero write bulk status received:%d", urb->status);
+ if (status) {
+ dbg("nonzero write bulk status received:%d", status);
return;
}
@@ -1235,16 +1238,6 @@ static void mos7720_set_termios(struct usb_serial_port *port,
return;
}
- /* check that they really want us to change something */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(tty->termios->c_iflag) ==
- RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("Nothing to change");
- return;
- }
- }
-
dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
tty->termios->c_cflag,
RELEVANT_IFLAG(tty->termios->c_iflag));
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 36620c65107..37f41f576d3 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -434,6 +434,7 @@ static void mos7840_control_callback(struct urb *urb)
struct moschip_port *mos7840_port;
__u8 regval = 0x0;
int result = 0;
+ int status = urb->status;
if (!urb) {
dbg("%s", "Invalid Pointer !!!!:\n");
@@ -442,7 +443,7 @@ static void mos7840_control_callback(struct urb *urb)
mos7840_port = (struct moschip_port *)urb->context;
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -451,11 +452,11 @@ static void mos7840_control_callback(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__,
- urb->status);
+ status);
return;
default:
dbg("%s - nonzero urb status received: %d", __FUNCTION__,
- urb->status);
+ status);
goto exit;
}
@@ -521,6 +522,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
__u8 sp[5], st;
int i, rv = 0;
__u16 wval, wreg = 0;
+ int status = urb->status;
dbg("%s", " : Entering\n");
if (!urb) {
@@ -528,7 +530,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
return;
}
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -537,11 +539,11 @@ static void mos7840_interrupt_callback(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__,
- urb->status);
+ status);
return;
default:
dbg("%s - nonzero urb status received: %d", __FUNCTION__,
- urb->status);
+ status);
goto exit;
}
@@ -666,20 +668,21 @@ static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
static void mos7840_bulk_in_callback(struct urb *urb)
{
- int status;
+ int retval;
unsigned char *data;
struct usb_serial *serial;
struct usb_serial_port *port;
struct moschip_port *mos7840_port;
struct tty_struct *tty;
+ int status = urb->status;
if (!urb) {
dbg("%s", "Invalid Pointer !!!!:\n");
return;
}
- if (urb->status) {
- dbg("nonzero read bulk status received: %d", urb->status);
+ if (status) {
+ dbg("nonzero read bulk status received: %d", status);
return;
}
@@ -729,11 +732,11 @@ static void mos7840_bulk_in_callback(struct urb *urb)
mos7840_port->read_urb->dev = serial->dev;
- status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+ retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
- if (status) {
- dbg(" usb_submit_urb(read bulk) failed, status = %d",
- status);
+ if (retval) {
+ dbg(" usb_submit_urb(read bulk) failed, retval = %d",
+ retval);
}
}
@@ -747,6 +750,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
{
struct moschip_port *mos7840_port;
struct tty_struct *tty;
+ int status = urb->status;
int i;
if (!urb) {
@@ -764,8 +768,8 @@ static void mos7840_bulk_out_data_callback(struct urb *urb)
}
spin_unlock(&mos7840_port->pool_lock);
- if (urb->status) {
- dbg("nonzero write bulk status received:%d\n", urb->status);
+ if (status) {
+ dbg("nonzero write bulk status received:%d\n", status);
return;
}
@@ -2185,16 +2189,6 @@ static void mos7840_set_termios(struct usb_serial_port *port,
return;
}
- /* check that they really want us to change something */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(tty->termios->c_iflag) ==
- RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s\n", "Nothing to change");
- return;
- }
- }
-
dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
@@ -2254,30 +2248,6 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
}
/*****************************************************************************
- * mos7840_get_bytes_avail - get number of bytes available
- *
- * Purpose: Let user call ioctl to get the count of number of bytes available.
- *****************************************************************************/
-
-static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port,
- unsigned int __user *value)
-{
- unsigned int result = 0;
- struct tty_struct *tty = mos7840_port->port->tty;
-
- if (!tty)
- return -ENOIOCTLCMD;
-
- result = tty->read_cnt;
-
- dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result);
- if (copy_to_user(value, &result, sizeof(int)))
- return -EFAULT;
-
- return -ENOIOCTLCMD;
-}
-
-/*****************************************************************************
* mos7840_set_modem_info
* function to set modem info
*****************************************************************************/
@@ -2425,8 +2395,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
struct async_icount cprev;
struct serial_icounter_struct icount;
int mosret = 0;
- int retval;
- struct tty_ldisc *ld;
if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
dbg("%s", "Invalid port \n");
@@ -2445,42 +2413,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
switch (cmd) {
/* return number of bytes available */
- case TIOCINQ:
- dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
- return mos7840_get_bytes_avail(mos7840_port, argp);
-
- case TIOCOUTQ:
- dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number);
- return put_user(tty->driver->chars_in_buffer ?
- tty->driver->chars_in_buffer(tty) : 0,
- (int __user *)arg);
-
- case TCFLSH:
- retval = tty_check_change(tty);
- if (retval)
- return retval;
-
- ld = tty_ldisc_ref(tty);
- switch (arg) {
- case TCIFLUSH:
- if (ld && ld->flush_buffer)
- ld->flush_buffer(tty);
- break;
- case TCIOFLUSH:
- if (ld && ld->flush_buffer)
- ld->flush_buffer(tty);
- /* fall through */
- case TCOFLUSH:
- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
- break;
- default:
- tty_ldisc_deref(ld);
- return -EINVAL;
- }
- tty_ldisc_deref(ld);
- return 0;
-
case TIOCSERGETLSR:
dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
return mos7840_get_lsr_info(mos7840_port, argp);
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 90701111d74..7f337c9aeb5 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -37,9 +37,10 @@ static void navman_read_int_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
struct tty_struct *tty;
+ int status = urb->status;
int result;
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -48,11 +49,11 @@ static void navman_read_int_callback(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
return;
default:
dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
goto exit;
}
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 00afc1712c3..ee94d9616d8 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -1,10 +1,9 @@
/*
* USB ZyXEL omni.net LCD PLUS driver
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is 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.
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
@@ -201,14 +200,15 @@ static void omninet_read_bulk_callback (struct urb *urb)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
unsigned char *data = urb->transfer_buffer;
struct omninet_header *header = (struct omninet_header *) &data[0];
-
+ int status = urb->status;
int i;
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -312,12 +312,14 @@ static void omninet_write_bulk_callback (struct urb *urb)
{
/* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+ int status = urb->status;
dbg("%s - port %0x\n", __FUNCTION__, port->number);
port->write_urb_busy = 0;
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
return;
}
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 89f067d9507..84c12b5f127 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -38,6 +38,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
+#include <linux/bitops.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
@@ -111,7 +112,8 @@ static int option_send_setup(struct usb_serial_port *port);
#define NOVATELWIRELESS_VENDOR_ID 0x1410
#define ANYDATA_VENDOR_ID 0x16d5
-#define ANYDATA_PRODUCT_ID 0x6501
+#define ANYDATA_PRODUCT_ADU_E100A 0x6501
+#define ANYDATA_PRODUCT_ADU_500A 0x6502
#define BANDRICH_VENDOR_ID 0x1A8D
#define BANDRICH_PRODUCT_C100_1 0x1002
@@ -169,7 +171,8 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
- { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) },
+ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
+ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
{ USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard */
@@ -238,6 +241,7 @@ struct option_port_private {
/* Output endpoints and buffer for this port */
struct urb *out_urbs[N_OUT_URB];
char out_buffer[N_OUT_URB][OUT_BUFLEN];
+ unsigned long out_busy; /* Bit vector of URBs in use */
/* Settings for the port */
int rts_state; /* Handshaking pins (outputs) */
@@ -368,7 +372,7 @@ static int option_write(struct usb_serial_port *port,
todo = OUT_BUFLEN;
this_urb = portdata->out_urbs[i];
- if (this_urb->status == -EINPROGRESS) {
+ if (test_and_set_bit(i, &portdata->out_busy)) {
if (time_before(jiffies,
portdata->tx_start_time[i] + 10 * HZ))
continue;
@@ -392,6 +396,7 @@ static int option_write(struct usb_serial_port *port,
dbg("usb_submit_urb %p (write bulk) failed "
"(%d, has %d)", this_urb,
err, this_urb->status);
+ clear_bit(i, &portdata->out_busy);
continue;
}
portdata->tx_start_time[i] = jiffies;
@@ -411,15 +416,16 @@ static void option_indat_callback(struct urb *urb)
struct usb_serial_port *port;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
dbg("%s: %p", __FUNCTION__, urb);
endpoint = usb_pipeendpoint(urb->pipe);
port = (struct usb_serial_port *) urb->context;
- if (urb->status) {
+ if (status) {
dbg("%s: nonzero status: %d on endpoint %02x.",
- __FUNCTION__, urb->status, endpoint);
+ __FUNCTION__, status, endpoint);
} else {
tty = port->tty;
if (urb->actual_length) {
@@ -431,7 +437,7 @@ static void option_indat_callback(struct urb *urb)
}
/* Resubmit urb so we continue receiving */
- if (port->open_count && urb->status != -ESHUTDOWN) {
+ if (port->open_count && status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
printk(KERN_ERR "%s: resubmit read urb failed. "
@@ -444,17 +450,29 @@ static void option_indat_callback(struct urb *urb)
static void option_outdat_callback(struct urb *urb)
{
struct usb_serial_port *port;
+ struct option_port_private *portdata;
+ int i;
dbg("%s", __FUNCTION__);
port = (struct usb_serial_port *) urb->context;
usb_serial_port_softint(port);
+
+ portdata = usb_get_serial_port_data(port);
+ for (i = 0; i < N_OUT_URB; ++i) {
+ if (portdata->out_urbs[i] == urb) {
+ smp_mb__before_clear_bit();
+ clear_bit(i, &portdata->out_busy);
+ break;
+ }
+ }
}
static void option_instat_callback(struct urb *urb)
{
int err;
+ int status = urb->status;
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
struct option_port_private *portdata = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
@@ -462,7 +480,7 @@ static void option_instat_callback(struct urb *urb)
dbg("%s", __FUNCTION__);
dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
- if (urb->status == 0) {
+ if (status == 0) {
struct usb_ctrlrequest *req_pkt =
(struct usb_ctrlrequest *)urb->transfer_buffer;
@@ -493,10 +511,10 @@ static void option_instat_callback(struct urb *urb)
req_pkt->bRequestType,req_pkt->bRequest);
}
} else
- dbg("%s: error %d", __FUNCTION__, urb->status);
+ dbg("%s: error %d", __FUNCTION__, status);
/* Resubmit urb so we continue receiving IRQ data */
- if (urb->status != -ESHUTDOWN) {
+ if (status != -ESHUTDOWN) {
urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
@@ -516,7 +534,7 @@ static int option_write_room(struct usb_serial_port *port)
for (i=0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i];
- if (this_urb && this_urb->status != -EINPROGRESS)
+ if (this_urb && !test_bit(i, &portdata->out_busy))
data_len += OUT_BUFLEN;
}
@@ -535,7 +553,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
for (i=0; i < N_OUT_URB; i++) {
this_urb = portdata->out_urbs[i];
- if (this_urb && this_urb->status == -EINPROGRESS)
+ if (this_urb && test_bit(i, &portdata->out_busy))
data_len += this_urb->transfer_buffer_length;
}
dbg("%s: %d", __FUNCTION__, data_len);
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
new file mode 100644
index 00000000000..d7db71eca52
--- /dev/null
+++ b/drivers/usb/serial/oti6858.c
@@ -0,0 +1,1342 @@
+/*
+ * Ours Technology Inc. OTi-6858 USB to serial adapter driver.
+ *
+ * Copyleft (C) 2007 Kees Lemmens (adapted for kernel 2.6.20)
+ * Copyright (C) 2006 Tomasz Michal Lukaszewski (FIXME: add e-mail)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2003 IBM Corp.
+ *
+ * Many thanks to the authors of pl2303 driver: all functions in this file
+ * are heavily based on pl2303 code, buffering code is a 1-to-1 copy.
+ *
+ * Warning! You use this driver on your own risk! The only official
+ * description of this device I have is datasheet from manufacturer,
+ * and it doesn't contain almost any information needed to write a driver.
+ * Almost all knowlegde used while writing this driver was gathered by:
+ * - analyzing traffic between device and the M$ Windows 2000 driver,
+ * - trying different bit combinations and checking pin states
+ * with a voltmeter,
+ * - receiving malformed frames and producing buffer overflows
+ * to learn how errors are reported,
+ * So, THIS CODE CAN DESTROY OTi-6858 AND ANY OTHER DEVICES, THAT ARE
+ * CONNECTED TO IT!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ *
+ * TODO:
+ * - implement correct flushing for ioctls and oti6858_close()
+ * - check how errors (rx overflow, parity error, framing error) are reported
+ * - implement oti6858_break_ctl()
+ * - implement more ioctls
+ * - test/implement flow control
+ * - allow setting custom baud rates
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+#include "oti6858.h"
+
+#define OTI6858_DESCRIPTION \
+ "Ours Technology Inc. OTi-6858 USB to serial adapter driver"
+#define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>"
+#define OTI6858_VERSION "0.1"
+
+static struct usb_device_id id_table [] = {
+ { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static struct usb_driver oti6858_driver = {
+ .name = "oti6858",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+ .no_dynamic_id = 1,
+};
+
+static int debug;
+
+
+/* buffering code, copied from pl2303 driver */
+#define PL2303_BUF_SIZE 1024
+#define PL2303_TMP_BUF_SIZE 1024
+
+struct pl2303_buf {
+ unsigned int buf_size;
+ char *buf_buf;
+ char *buf_get;
+ char *buf_put;
+};
+
+/* requests */
+#define OTI6858_REQ_GET_STATUS (USB_DIR_IN | USB_TYPE_VENDOR | 0x00)
+#define OTI6858_REQ_T_GET_STATUS 0x01
+
+#define OTI6858_REQ_SET_LINE (USB_DIR_OUT | USB_TYPE_VENDOR | 0x00)
+#define OTI6858_REQ_T_SET_LINE 0x00
+
+#define OTI6858_REQ_CHECK_TXBUFF (USB_DIR_IN | USB_TYPE_VENDOR | 0x01)
+#define OTI6858_REQ_T_CHECK_TXBUFF 0x00
+
+/* format of the control packet */
+struct oti6858_control_pkt {
+ u16 divisor; /* baud rate = 96000000 / (16 * divisor), LE */
+#define OTI6858_MAX_BAUD_RATE 3000000
+ u8 frame_fmt;
+#define FMT_STOP_BITS_MASK 0xc0
+#define FMT_STOP_BITS_1 0x00
+#define FMT_STOP_BITS_2 0x40 /* 1.5 stop bits if FMT_DATA_BITS_5 */
+#define FMT_PARITY_MASK 0x38
+#define FMT_PARITY_NONE 0x00
+#define FMT_PARITY_ODD 0x08
+#define FMT_PARITY_EVEN 0x18
+#define FMT_PARITY_MARK 0x28
+#define FMT_PARITY_SPACE 0x38
+#define FMT_DATA_BITS_MASK 0x03
+#define FMT_DATA_BITS_5 0x00
+#define FMT_DATA_BITS_6 0x01
+#define FMT_DATA_BITS_7 0x02
+#define FMT_DATA_BITS_8 0x03
+ u8 something; /* always equals 0x43 */
+ u8 control; /* settings of flow control lines */
+#define CONTROL_MASK 0x0c
+#define CONTROL_DTR_HIGH 0x08
+#define CONTROL_RTS_HIGH 0x04
+ u8 tx_status;
+#define TX_BUFFER_EMPTIED 0x09
+ u8 pin_state;
+#define PIN_MASK 0x3f
+#define PIN_RTS 0x20 /* output pin */
+#define PIN_CTS 0x10 /* input pin, active low */
+#define PIN_DSR 0x08 /* input pin, active low */
+#define PIN_DTR 0x04 /* output pin */
+#define PIN_RI 0x02 /* input pin, active low */
+#define PIN_DCD 0x01 /* input pin, active low */
+ u8 rx_bytes_avail; /* number of bytes in rx buffer */;
+};
+
+#define OTI6858_CTRL_PKT_SIZE sizeof(struct oti6858_control_pkt)
+#define OTI6858_CTRL_EQUALS_PENDING(a, priv) \
+ ( ((a)->divisor == (priv)->pending_setup.divisor) \
+ && ((a)->control == (priv)->pending_setup.control) \
+ && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) )
+
+/* function prototypes */
+static int oti6858_open(struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct usb_serial_port *port, struct file *filp);
+static void oti6858_set_termios(struct usb_serial_port *port,
+ struct ktermios *old);
+static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void oti6858_read_int_callback(struct urb *urb);
+static void oti6858_read_bulk_callback(struct urb *urb);
+static void oti6858_write_bulk_callback(struct urb *urb);
+static int oti6858_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+static int oti6858_write_room(struct usb_serial_port *port);
+static void oti6858_break_ctl(struct usb_serial_port *port, int break_state);
+static int oti6858_chars_in_buffer(struct usb_serial_port *port);
+static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file);
+static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear);
+static int oti6858_startup(struct usb_serial *serial);
+static void oti6858_shutdown(struct usb_serial *serial);
+
+/* functions operating on buffers */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
+static void pl2303_buf_free(struct pl2303_buf *pb);
+static void pl2303_buf_clear(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb);
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+ unsigned int count);
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+ unsigned int count);
+
+
+/* device info */
+static struct usb_serial_driver oti6858_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "oti6858",
+ },
+ .id_table = id_table,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = oti6858_open,
+ .close = oti6858_close,
+ .write = oti6858_write,
+ .ioctl = oti6858_ioctl,
+ .break_ctl = oti6858_break_ctl,
+ .set_termios = oti6858_set_termios,
+ .tiocmget = oti6858_tiocmget,
+ .tiocmset = oti6858_tiocmset,
+ .read_bulk_callback = oti6858_read_bulk_callback,
+ .read_int_callback = oti6858_read_int_callback,
+ .write_bulk_callback = oti6858_write_bulk_callback,
+ .write_room = oti6858_write_room,
+ .chars_in_buffer = oti6858_chars_in_buffer,
+ .attach = oti6858_startup,
+ .shutdown = oti6858_shutdown,
+};
+
+struct oti6858_private {
+ spinlock_t lock;
+
+ struct pl2303_buf *buf;
+ struct oti6858_control_pkt status;
+
+ struct {
+ u8 read_urb_in_use;
+ u8 write_urb_in_use;
+ u8 termios_initialized;
+ } flags;
+ struct delayed_work delayed_write_work;
+
+ struct {
+ u16 divisor;
+ u8 frame_fmt;
+ u8 control;
+ } pending_setup;
+ u8 transient;
+ u8 setup_done;
+ struct delayed_work delayed_setup_work;
+
+ wait_queue_head_t intr_wait;
+ struct usb_serial_port *port; /* USB port with which associated */
+};
+
+#undef dbg
+/* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */
+#define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg)
+
+static void setup_line(struct work_struct *work)
+{
+ struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work);
+ struct usb_serial_port *port = priv->port;
+ struct oti6858_control_pkt *new_setup;
+ unsigned long flags;
+ int result;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+ dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
+ /* we will try again */
+ schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+ return;
+ }
+
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ OTI6858_REQ_T_GET_STATUS,
+ OTI6858_REQ_GET_STATUS,
+ 0, 0,
+ new_setup, OTI6858_CTRL_PKT_SIZE,
+ 100);
+
+ if (result != OTI6858_CTRL_PKT_SIZE) {
+ dev_err(&port->dev, "%s(): error reading status", __FUNCTION__);
+ kfree(new_setup);
+ /* we will try again */
+ schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2));
+ return;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!OTI6858_CTRL_EQUALS_PENDING(new_setup, priv)) {
+ new_setup->divisor = priv->pending_setup.divisor;
+ new_setup->control = priv->pending_setup.control;
+ new_setup->frame_fmt = priv->pending_setup.frame_fmt;
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ result = usb_control_msg(port->serial->dev,
+ usb_sndctrlpipe(port->serial->dev, 0),
+ OTI6858_REQ_T_SET_LINE,
+ OTI6858_REQ_SET_LINE,
+ 0, 0,
+ new_setup, OTI6858_CTRL_PKT_SIZE,
+ 100);
+ } else {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ result = 0;
+ }
+ kfree(new_setup);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (result != OTI6858_CTRL_PKT_SIZE)
+ priv->transient = 0;
+ priv->setup_done = 1;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ dbg("%s(): submitting interrupt urb", __FUNCTION__);
+ port->interrupt_in_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+ " with error %d\n", __FUNCTION__, result);
+ }
+}
+
+void send_data(struct work_struct *work)
+{
+ struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work);
+ struct usb_serial_port *port = priv->port;
+ int count = 0, result;
+ unsigned long flags;
+ unsigned char allow;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->flags.write_urb_in_use) {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2));
+ return;
+ }
+ priv->flags.write_urb_in_use = 1;
+
+ count = pl2303_buf_data_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ if (count > port->bulk_out_size)
+ count = port->bulk_out_size;
+
+ if (count != 0) {
+ result = usb_control_msg(port->serial->dev,
+ usb_rcvctrlpipe(port->serial->dev, 0),
+ OTI6858_REQ_T_CHECK_TXBUFF,
+ OTI6858_REQ_CHECK_TXBUFF,
+ count, 0, &allow, 1, 100);
+ if (result != 1 || allow != 0)
+ count = 0;
+ }
+
+ if (count == 0) {
+ priv->flags.write_urb_in_use = 0;
+
+ dbg("%s(): submitting interrupt urb", __FUNCTION__);
+ port->interrupt_in_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+ " with error %d\n", __FUNCTION__, result);
+ }
+ return;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, count);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ port->write_urb->transfer_buffer_length = count;
+ port->write_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+ " with error %d\n", __FUNCTION__, result);
+ priv->flags.write_urb_in_use = 0;
+ }
+
+ usb_serial_port_softint(port);
+}
+
+static int oti6858_startup(struct usb_serial *serial)
+{
+ 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;
+ priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE);
+ if (priv->buf == NULL) {
+ kfree(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]);
+ pl2303_buf_free(priv->buf);
+ kfree(priv);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+ return -ENOMEM;
+}
+
+static int oti6858_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+ dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count);
+
+ if (!count)
+ return count;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ count = pl2303_buf_put(priv->buf, buf, count);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return count;
+}
+
+static int oti6858_write_room(struct usb_serial_port *port)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ int room = 0;
+ unsigned long flags;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ room = pl2303_buf_space_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return room;
+}
+
+static int oti6858_chars_in_buffer(struct usb_serial_port *port)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ int chars = 0;
+ unsigned long flags;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ chars = pl2303_buf_data_avail(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return chars;
+}
+
+static void oti6858_set_termios(struct usb_serial_port *port,
+ struct ktermios *old_termios)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ unsigned int cflag;
+ u8 frame_fmt, control;
+ u16 divisor;
+ int br;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ if ((!port->tty) || (!port->tty->termios)) {
+ dbg("%s(): no tty structures", __FUNCTION__);
+ return;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->flags.termios_initialized) {
+ *(port->tty->termios) = tty_std_termios;
+ port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
+ priv->flags.termios_initialized = 1;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ cflag = port->tty->termios->c_cflag;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ divisor = priv->pending_setup.divisor;
+ frame_fmt = priv->pending_setup.frame_fmt;
+ control = priv->pending_setup.control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ frame_fmt &= ~FMT_DATA_BITS_MASK;
+ switch (cflag & CSIZE) {
+ case CS5:
+ frame_fmt |= FMT_DATA_BITS_5;
+ break;
+ case CS6:
+ frame_fmt |= FMT_DATA_BITS_6;
+ break;
+ case CS7:
+ frame_fmt |= FMT_DATA_BITS_7;
+ break;
+ default:
+ case CS8:
+ frame_fmt |= FMT_DATA_BITS_8;
+ break;
+ }
+
+ /* manufacturer claims that this device can work with baud rates
+ * up to 3 Mbps; I've tested it only on 115200 bps, so I can't
+ * guarantee that any other baud rate will work (especially
+ * the higher ones)
+ */
+ br = tty_get_baud_rate(port->tty);
+ if (br == 0) {
+ divisor = 0;
+ } else if (br <= OTI6858_MAX_BAUD_RATE) {
+ int real_br;
+
+ divisor = (96000000 + 8 * br) / (16 * br);
+ real_br = 96000000 / (16 * divisor);
+ if ((((real_br - br) * 100 + br - 1) / br) > 2) {
+ dbg("%s(): baud rate %d is invalid", __FUNCTION__, br);
+ return;
+ }
+ divisor = cpu_to_le16(divisor);
+ } else {
+ dbg("%s(): baud rate %d is too high", __FUNCTION__, br);
+ return;
+ }
+
+ frame_fmt &= ~FMT_STOP_BITS_MASK;
+ if ((cflag & CSTOPB) != 0) {
+ frame_fmt |= FMT_STOP_BITS_2;
+ } else {
+ frame_fmt |= FMT_STOP_BITS_1;
+ }
+
+ frame_fmt &= ~FMT_PARITY_MASK;
+ if ((cflag & PARENB) != 0) {
+ if ((cflag & PARODD) != 0) {
+ frame_fmt |= FMT_PARITY_ODD;
+ } else {
+ frame_fmt |= FMT_PARITY_EVEN;
+ }
+ } else {
+ frame_fmt |= FMT_PARITY_NONE;
+ }
+
+ control &= ~CONTROL_MASK;
+ if ((cflag & CRTSCTS) != 0)
+ control |= (CONTROL_DTR_HIGH | CONTROL_RTS_HIGH);
+
+ /* change control lines if we are switching to or from B0 */
+ /* FIXME:
+ spin_lock_irqsave(&priv->lock, flags);
+ control = priv->line_control;
+ if ((cflag & CBAUD) == B0)
+ priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+ else
+ priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+ if (control != priv->line_control) {
+ control = priv->line_control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ set_control_lines(serial->dev, control);
+ } else {
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ */
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (divisor != priv->pending_setup.divisor
+ || control != priv->pending_setup.control
+ || frame_fmt != priv->pending_setup.frame_fmt) {
+ priv->pending_setup.divisor = divisor;
+ priv->pending_setup.control = control;
+ priv->pending_setup.frame_fmt = frame_fmt;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int oti6858_open(struct usb_serial_port *port, struct file *filp)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ struct ktermios tmp_termios;
+ struct usb_serial *serial = port->serial;
+ struct oti6858_control_pkt *buf;
+ unsigned long flags;
+ int result;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ usb_clear_halt(serial->dev, port->write_urb->pipe);
+ usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+ if (port->open_count != 1)
+ return 0;
+
+ if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) {
+ dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ OTI6858_REQ_T_GET_STATUS,
+ OTI6858_REQ_GET_STATUS,
+ 0, 0,
+ buf, OTI6858_CTRL_PKT_SIZE,
+ 100);
+ if (result != OTI6858_CTRL_PKT_SIZE) {
+ /* assume default (after power-on reset) values */
+ buf->divisor = cpu_to_le16(0x009c); /* 38400 bps */
+ buf->frame_fmt = 0x03; /* 8N1 */
+ buf->something = 0x43;
+ buf->control = 0x4c; /* DTR, RTS */
+ buf->tx_status = 0x00;
+ buf->pin_state = 0x5b; /* RTS, CTS, DSR, DTR, RI, DCD */
+ buf->rx_bytes_avail = 0x00;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ memcpy(&priv->status, buf, OTI6858_CTRL_PKT_SIZE);
+ priv->pending_setup.divisor = buf->divisor;
+ priv->pending_setup.frame_fmt = buf->frame_fmt;
+ priv->pending_setup.control = buf->control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ kfree(buf);
+
+ dbg("%s(): submitting interrupt urb", __FUNCTION__);
+ port->interrupt_in_urb->dev = serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed"
+ " with error %d\n", __FUNCTION__, result);
+ oti6858_close(port, NULL);
+ return -EPROTO;
+ }
+
+ /* setup termios */
+ if (port->tty)
+ oti6858_set_termios(port, &tmp_termios);
+
+ return 0;
+}
+
+static void oti6858_close(struct usb_serial_port *port, struct file *filp)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ long timeout;
+ wait_queue_t wait;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ /* wait for data to drain from the buffer */
+ spin_lock_irqsave(&priv->lock, flags);
+ timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&port->tty->write_wait, &wait);
+ dbg("%s(): entering wait loop", __FUNCTION__);
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (pl2303_buf_data_avail(priv->buf) == 0
+ || timeout == 0 || signal_pending(current)
+ || !usb_get_intfdata(port->serial->interface)) /* disconnect */
+ break;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ timeout = schedule_timeout(timeout);
+ spin_lock_irqsave(&priv->lock, flags);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&port->tty->write_wait, &wait);
+ dbg("%s(): after wait loop", __FUNCTION__);
+
+ /* clear out any remaining data in the buffer */
+ pl2303_buf_clear(priv->buf);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* wait for characters to drain from the device */
+ /* (this is long enough for the entire 256 byte */
+ /* pl2303 hardware buffer to drain with no flow */
+ /* control for data rates of 1200 bps or more, */
+ /* for lower rates we should really know how much */
+ /* data is in the buffer to compute a delay */
+ /* that is not unnecessarily long) */
+ /* FIXME
+ bps = tty_get_baud_rate(port->tty);
+ if (bps > 1200)
+ timeout = max((HZ*2560)/bps,HZ/10);
+ else
+ */
+ timeout = 2*HZ;
+ schedule_timeout_interruptible(timeout);
+ dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__);
+
+ /* cancel scheduled setup */
+ cancel_delayed_work(&priv->delayed_setup_work);
+ cancel_delayed_work(&priv->delayed_write_work);
+ flush_scheduled_work();
+
+ /* shutdown our urbs */
+ dbg("%s(): shutting down urbs", __FUNCTION__);
+ usb_kill_urb(port->write_urb);
+ usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->interrupt_in_urb);
+
+ /*
+ if (port->tty && (port->tty->termios->c_cflag) & HUPCL) {
+ // drop DTR and RTS
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->pending_setup.control &= ~CONTROL_MASK;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ */
+}
+
+static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ u8 control;
+
+ dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)",
+ __FUNCTION__, port->number, set, clear);
+
+ if (!usb_get_intfdata(port->serial->interface))
+ return -ENODEV;
+
+ /* FIXME: check if this is correct (active high/low) */
+ spin_lock_irqsave(&priv->lock, flags);
+ control = priv->pending_setup.control;
+ if ((set & TIOCM_RTS) != 0)
+ control |= CONTROL_RTS_HIGH;
+ if ((set & TIOCM_DTR) != 0)
+ control |= CONTROL_DTR_HIGH;
+ if ((clear & TIOCM_RTS) != 0)
+ control &= ~CONTROL_RTS_HIGH;
+ if ((clear & TIOCM_DTR) != 0)
+ control &= ~CONTROL_DTR_HIGH;
+
+ if (control != priv->pending_setup.control) {
+ priv->pending_setup.control = control;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+}
+
+static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ unsigned pin_state;
+ unsigned result = 0;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ if (!usb_get_intfdata(port->serial->interface))
+ return -ENODEV;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ pin_state = priv->status.pin_state & PIN_MASK;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* FIXME: check if this is correct (active high/low) */
+ if ((pin_state & PIN_RTS) != 0)
+ result |= TIOCM_RTS;
+ if ((pin_state & PIN_CTS) != 0)
+ result |= TIOCM_CTS;
+ if ((pin_state & PIN_DSR) != 0)
+ result |= TIOCM_DSR;
+ if ((pin_state & PIN_DTR) != 0)
+ result |= TIOCM_DTR;
+ if ((pin_state & PIN_RI) != 0)
+ result |= TIOCM_RI;
+ if ((pin_state & PIN_DCD) != 0)
+ result |= TIOCM_CD;
+
+ dbg("%s() = 0x%08x", __FUNCTION__, result);
+
+ return result;
+}
+
+static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+{
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ unsigned int prev, status;
+ unsigned int changed;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ prev = priv->status.pin_state;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ while (1) {
+ wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ status = priv->status.pin_state & PIN_MASK;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ changed = prev ^ status;
+ /* FIXME: check if this is correct (active high/low) */
+ if ( ((arg & TIOCM_RNG) && (changed & PIN_RI)) ||
+ ((arg & TIOCM_DSR) && (changed & PIN_DSR)) ||
+ ((arg & TIOCM_CD) && (changed & PIN_DCD)) ||
+ ((arg & TIOCM_CTS) && (changed & PIN_CTS))) {
+ return 0;
+ }
+ prev = status;
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+static int oti6858_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *user_arg = (void __user *) arg;
+ unsigned int x;
+
+ dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)",
+ __FUNCTION__, port->number, cmd, arg);
+
+ switch (cmd) {
+ case TCGETS:
+ if (copy_to_user(user_arg, port->tty->termios,
+ sizeof(struct ktermios))) {
+ return -EFAULT;
+ }
+ return 0;
+
+ case TCSETS:
+ case TCSETSW: /* FIXME: this is not the same! */
+ case TCSETSF: /* FIXME: this is not the same! */
+ if (copy_from_user(port->tty->termios, user_arg,
+ sizeof(struct ktermios))) {
+ return -EFAULT;
+ }
+ oti6858_set_termios(port, NULL);
+ return 0;
+
+ case TCFLSH:
+ /* FIXME */
+ return 0;
+
+ case TIOCMBIS:
+ if (copy_from_user(&x, user_arg, sizeof(x)))
+ return -EFAULT;
+ return oti6858_tiocmset(port, NULL, x, 0);
+
+ case TIOCMBIC:
+ if (copy_from_user(&x, user_arg, sizeof(x)))
+ return -EFAULT;
+ return oti6858_tiocmset(port, NULL, 0, x);
+
+ case TIOCGSERIAL:
+ if (copy_to_user(user_arg, port->tty->termios,
+ sizeof(struct ktermios))) {
+ return -EFAULT;
+ }
+ return 0;
+
+ case TIOCSSERIAL:
+ if (copy_from_user(port->tty->termios, user_arg,
+ sizeof(struct ktermios))) {
+ return -EFAULT;
+ }
+ oti6858_set_termios(port, NULL);
+ return 0;
+
+ case TIOCMIWAIT:
+ dbg("%s(): TIOCMIWAIT", __FUNCTION__);
+ return wait_modem_info(port, arg);
+
+ default:
+ dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd);
+ break;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static void oti6858_break_ctl(struct usb_serial_port *port, int break_state)
+{
+ int state;
+
+ dbg("%s(port = %d)", __FUNCTION__, port->number);
+
+ state = (break_state == 0) ? 0 : 1;
+ dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off");
+
+ /* FIXME */
+/*
+ result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
+ BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+ 0, NULL, 0, 100);
+ if (result != 0)
+ dbg("%s(): error sending break", __FUNCTION__);
+ */
+}
+
+static void oti6858_shutdown(struct usb_serial *serial)
+{
+ struct oti6858_private *priv;
+ int i;
+
+ dbg("%s()", __FUNCTION__);
+
+ for (i = 0; i < serial->num_ports; ++i) {
+ priv = usb_get_serial_port_data(serial->port[i]);
+ if (priv) {
+ pl2303_buf_free(priv->buf);
+ kfree(priv);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+ }
+}
+
+static void oti6858_read_int_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ int transient = 0, can_recv = 0, resubmit = 1;
+ int status = urb->status;
+
+ dbg("%s(port = %d, status = %d)",
+ __FUNCTION__, port->number, status);
+
+ switch (status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s(): urb shutting down with status: %d",
+ __FUNCTION__, status);
+ return;
+ default:
+ dbg("%s(): nonzero urb status received: %d",
+ __FUNCTION__, status);
+ break;
+ }
+
+ if (status == 0 && urb->actual_length == OTI6858_CTRL_PKT_SIZE) {
+ struct oti6858_control_pkt *xs = urb->transfer_buffer;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (!priv->transient) {
+ if (!OTI6858_CTRL_EQUALS_PENDING(xs, priv)) {
+ if (xs->rx_bytes_avail == 0) {
+ priv->transient = 4;
+ priv->setup_done = 0;
+ resubmit = 0;
+ dbg("%s(): scheduling setup_line()",
+ __FUNCTION__);
+ schedule_delayed_work(&priv->delayed_setup_work, 0);
+ }
+ }
+ } else {
+ if (OTI6858_CTRL_EQUALS_PENDING(xs, priv)) {
+ priv->transient = 0;
+ } else if (!priv->setup_done) {
+ resubmit = 0;
+ } else if (--priv->transient == 0) {
+ if (xs->rx_bytes_avail == 0) {
+ priv->transient = 4;
+ priv->setup_done = 0;
+ resubmit = 0;
+ dbg("%s(): scheduling setup_line()",
+ __FUNCTION__);
+ schedule_delayed_work(&priv->delayed_setup_work, 0);
+ }
+ }
+ }
+
+ if (!priv->transient) {
+ if (xs->pin_state != priv->status.pin_state)
+ wake_up_interruptible(&priv->intr_wait);
+ memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
+ }
+
+ if (!priv->transient && xs->rx_bytes_avail != 0) {
+ can_recv = xs->rx_bytes_avail;
+ priv->flags.read_urb_in_use = 1;
+ }
+
+ transient = priv->transient;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+ if (can_recv) {
+ int result;
+
+ port->read_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (result != 0) {
+ priv->flags.read_urb_in_use = 0;
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+ " error %d\n", __FUNCTION__, result);
+ } else {
+ resubmit = 0;
+ }
+ } else if (!transient) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->flags.write_urb_in_use == 0
+ && pl2303_buf_data_avail(priv->buf) != 0) {
+ schedule_delayed_work(&priv->delayed_write_work,0);
+ resubmit = 0;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
+ if (resubmit) {
+ int result;
+
+// dbg("%s(): submitting interrupt urb", __FUNCTION__);
+ urb->dev = port->serial->dev;
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&urb->dev->dev,
+ "%s(): usb_submit_urb() failed with"
+ " error %d\n", __FUNCTION__, result);
+ }
+ }
+}
+
+static void oti6858_read_bulk_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+ unsigned long flags;
+ int i, result;
+ int status = urb->status;
+ char tty_flag;
+
+ dbg("%s(port = %d, status = %d)",
+ __FUNCTION__, port->number, status);
+
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->flags.read_urb_in_use = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (status != 0) {
+ if (!port->open_count) {
+ dbg("%s(): port is closed, exiting", __FUNCTION__);
+ return;
+ }
+ /*
+ if (status == -EPROTO) {
+ // PL2303 mysteriously fails with -EPROTO reschedule the read
+ dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
+ result = usb_submit_urb(urb, GFP_ATOMIC);
+ if (result)
+ dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+ return;
+ }
+ */
+ dbg("%s(): unable to handle the error, exiting", __FUNCTION__);
+ return;
+ }
+
+ // get tty_flag from status
+ tty_flag = TTY_NORMAL;
+
+/* FIXME: probably, errors will be signalled using interrupt pipe! */
+/*
+ // break takes precedence over parity,
+ // which takes precedence over framing errors
+ if (status & UART_BREAK_ERROR )
+ tty_flag = TTY_BREAK;
+ else if (status & UART_PARITY_ERROR)
+ tty_flag = TTY_PARITY;
+ else if (status & UART_FRAME_ERROR)
+ tty_flag = TTY_FRAME;
+ dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
+*/
+
+ tty = port->tty;
+ if (tty != NULL && urb->actual_length > 0) {
+ tty_buffer_request_room(tty, urb->actual_length);
+ for (i = 0; i < urb->actual_length; ++i)
+ tty_insert_flip_char(tty, data[i], tty_flag);
+ tty_flip_buffer_push(tty);
+ }
+
+ // schedule the interrupt urb if we are still open */
+ if (port->open_count != 0) {
+ port->interrupt_in_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+ " error %d\n", __FUNCTION__, result);
+ }
+ }
+}
+
+static void oti6858_write_bulk_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+ struct oti6858_private *priv = usb_get_serial_port_data(port);
+ int status = urb->status;
+ int result;
+
+ dbg("%s(port = %d, status = %d)",
+ __FUNCTION__, port->number, status);
+
+ switch (status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s(): urb shutting down with status: %d",
+ __FUNCTION__, status);
+ priv->flags.write_urb_in_use = 0;
+ return;
+ default:
+ /* error in the urb, so we have to resubmit it */
+ dbg("%s(): nonzero write bulk status received: %d",
+ __FUNCTION__, status);
+ dbg("%s(): overflow in write", __FUNCTION__);
+
+ port->write_urb->transfer_buffer_length = 1;
+ port->write_urb->dev = port->serial->dev;
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+ dev_err(&port->dev, "%s(): usb_submit_urb() failed,"
+ " error %d\n", __FUNCTION__, result);
+ } else {
+ return;
+ }
+ }
+
+ priv->flags.write_urb_in_use = 0;
+
+ // schedule the interrupt urb if we are still open */
+ port->interrupt_in_urb->dev = port->serial->dev;
+ dbg("%s(): submitting interrupt urb", __FUNCTION__);
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
+ if (result != 0) {
+ dev_err(&port->dev, "%s(): failed submitting int urb,"
+ " error %d\n", __FUNCTION__, result);
+ }
+}
+
+
+/*
+ * pl2303_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+{
+ struct pl2303_buf *pb;
+
+ if (size == 0)
+ return NULL;
+
+ pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+ if (pb == NULL)
+ return NULL;
+
+ pb->buf_buf = kmalloc(size, GFP_KERNEL);
+ if (pb->buf_buf == NULL) {
+ kfree(pb);
+ return NULL;
+ }
+
+ pb->buf_size = size;
+ pb->buf_get = pb->buf_put = pb->buf_buf;
+
+ return pb;
+}
+
+/*
+ * pl2303_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void pl2303_buf_free(struct pl2303_buf *pb)
+{
+ if (pb) {
+ kfree(pb->buf_buf);
+ kfree(pb);
+ }
+}
+
+/*
+ * pl2303_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void pl2303_buf_clear(struct pl2303_buf *pb)
+{
+ if (pb != NULL) {
+ /* equivalent to a get of all data available */
+ pb->buf_get = pb->buf_put;
+ }
+}
+
+/*
+ * pl2303_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
+{
+ if (pb == NULL)
+ return 0;
+ return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
+{
+ if (pb == NULL)
+ return 0;
+ return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+ unsigned int count)
+{
+ unsigned int len;
+
+ if (pb == NULL)
+ return 0;
+
+ len = pl2303_buf_space_avail(pb);
+ if (count > len)
+ count = len;
+
+ if (count == 0)
+ return 0;
+
+ len = pb->buf_buf + pb->buf_size - pb->buf_put;
+ if (count > len) {
+ memcpy(pb->buf_put, buf, len);
+ memcpy(pb->buf_buf, buf+len, count - len);
+ pb->buf_put = pb->buf_buf + count - len;
+ } else {
+ memcpy(pb->buf_put, buf, count);
+ if (count < len)
+ pb->buf_put += count;
+ else /* count == len */
+ pb->buf_put = pb->buf_buf;
+ }
+
+ return count;
+}
+
+/*
+ * pl2303_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+ unsigned int count)
+{
+ unsigned int len;
+
+ if (pb == NULL)
+ return 0;
+
+ len = pl2303_buf_data_avail(pb);
+ if (count > len)
+ count = len;
+
+ if (count == 0)
+ return 0;
+
+ len = pb->buf_buf + pb->buf_size - pb->buf_get;
+ if (count > len) {
+ memcpy(buf, pb->buf_get, len);
+ memcpy(buf+len, pb->buf_buf, count - len);
+ pb->buf_get = pb->buf_buf + count - len;
+ } else {
+ memcpy(buf, pb->buf_get, count);
+ if (count < len)
+ pb->buf_get += count;
+ else /* count == len */
+ pb->buf_get = pb->buf_buf;
+ }
+
+ return count;
+}
+
+/* module description and (de)initialization */
+
+static int __init oti6858_init(void)
+{
+ int retval;
+
+ if ((retval = usb_serial_register(&oti6858_device)) == 0) {
+ if ((retval = usb_register(&oti6858_driver)) != 0)
+ usb_serial_deregister(&oti6858_device);
+ else
+ return 0;
+ }
+
+ return retval;
+}
+
+static void __exit oti6858_exit(void)
+{
+ usb_deregister(&oti6858_driver);
+ usb_serial_deregister(&oti6858_device);
+}
+
+module_init(oti6858_init);
+module_exit(oti6858_exit);
+
+MODULE_DESCRIPTION(OTI6858_DESCRIPTION);
+MODULE_AUTHOR(OTI6858_AUTHOR);
+MODULE_VERSION(OTI6858_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "enable debug output");
+
diff --git a/drivers/usb/serial/oti6858.h b/drivers/usb/serial/oti6858.h
new file mode 100644
index 00000000000..704ac3a532b
--- /dev/null
+++ b/drivers/usb/serial/oti6858.h
@@ -0,0 +1,15 @@
+/*
+ * Ours Technology Inc. OTi-6858 USB to serial adapter driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __LINUX_USB_SERIAL_OTI6858_H
+#define __LINUX_USB_SERIAL_OTI6858_H
+
+#define OTI6858_VENDOR_ID 0x0ea0
+#define OTI6858_PRODUCT_ID 0x6858
+
+#endif
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 83dfae93a45..f9f85f56f0d 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -1,14 +1,14 @@
/*
* Prolific PL2303 USB to serial adaptor driver
*
- * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2003 IBM Corp.
*
* Original driver for 2.2.x by anonymous
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License.
+ * This program is 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.
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
@@ -484,15 +484,6 @@ static void pl2303_set_termios(struct usb_serial_port *port,
spin_unlock_irqrestore(&priv->lock, flags);
cflag = port->tty->termios->c_cflag;
- /* check that they really want us to change something */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
- RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s - nothing to change...", __FUNCTION__);
- return;
- }
- }
buf = kzalloc(7, GFP_KERNEL);
if (!buf) {
@@ -517,29 +508,7 @@ static void pl2303_set_termios(struct usb_serial_port *port,
dbg("%s - data bits = %d", __FUNCTION__, buf[6]);
}
- baud = 0;
- switch (cflag & CBAUD) {
- case B0: baud = 0; break;
- case B75: baud = 75; break;
- case B150: baud = 150; break;
- case B300: baud = 300; break;
- case B600: baud = 600; break;
- case B1200: baud = 1200; break;
- case B1800: baud = 1800; break;
- case B2400: baud = 2400; break;
- case B4800: baud = 4800; break;
- case B9600: baud = 9600; break;
- case B19200: baud = 19200; break;
- case B38400: baud = 38400; break;
- case B57600: baud = 57600; break;
- case B115200: baud = 115200; break;
- case B230400: baud = 230400; break;
- case B460800: baud = 460800; break;
- default:
- dev_err(&port->dev, "pl2303 driver does not support"
- " the baudrate requested (fix it)\n");
- break;
- }
+ baud = tty_get_baud_rate(port->tty);;
dbg("%s - baud = %d", __FUNCTION__, baud);
if (baud) {
buf[0] = baud & 0xff;
@@ -617,6 +586,13 @@ static void pl2303_set_termios(struct usb_serial_port *port,
VENDOR_WRITE_REQUEST_TYPE,
0x0, index, NULL, 0, 100);
dbg("0x40:0x1:0x0:0x%x %d", index, i);
+ } else {
+ i = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ VENDOR_WRITE_REQUEST,
+ VENDOR_WRITE_REQUEST_TYPE,
+ 0x0, 0x0, NULL, 0, 100);
+ dbg ("0x40:0x1:0x0:0x0 %d", i);
}
kfree(buf);
@@ -954,11 +930,12 @@ static void pl2303_read_int_callback(struct urb *urb)
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
unsigned char *data = urb->transfer_buffer;
unsigned int actual_length = urb->actual_length;
- int status;
+ int status = urb->status;
+ int retval;
dbg("%s (%d)", __FUNCTION__, port->number);
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -967,11 +944,11 @@ static void pl2303_read_int_callback(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__,
- urb->status);
+ status);
return;
default:
dbg("%s - nonzero urb status received: %d", __FUNCTION__,
- urb->status);
+ status);
goto exit;
}
@@ -981,11 +958,11 @@ static void pl2303_read_int_callback(struct urb *urb)
pl2303_update_line_status(port, data, actual_length);
exit:
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status)
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
dev_err(&urb->dev->dev,
"%s - usb_submit_urb failed with result %d\n",
- __FUNCTION__, status);
+ __FUNCTION__, retval);
}
static void pl2303_read_bulk_callback(struct urb *urb)
@@ -997,23 +974,23 @@ static void pl2303_read_bulk_callback(struct urb *urb)
unsigned long flags;
int i;
int result;
- u8 status;
+ int status = urb->status;
+ u8 line_status;
char tty_flag;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - urb status = %d", __FUNCTION__, status);
if (!port->open_count) {
dbg("%s - port is closed, exiting.", __FUNCTION__);
return;
}
- if (urb->status == -EPROTO) {
+ if (status == -EPROTO) {
/* PL2303 mysteriously fails with -EPROTO reschedule
* the read */
dbg("%s - caught -EPROTO, resubmitting the urb",
__FUNCTION__);
- urb->status = 0;
urb->dev = port->serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
@@ -1033,18 +1010,18 @@ static void pl2303_read_bulk_callback(struct urb *urb)
tty_flag = TTY_NORMAL;
spin_lock_irqsave(&priv->lock, flags);
- status = priv->line_status;
+ line_status = priv->line_status;
priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
spin_unlock_irqrestore(&priv->lock, flags);
wake_up_interruptible(&priv->delta_msr_wait);
/* break takes precedence over parity, */
/* which takes precedence over framing errors */
- if (status & UART_BREAK_ERROR )
+ if (line_status & UART_BREAK_ERROR )
tty_flag = TTY_BREAK;
- else if (status & UART_PARITY_ERROR)
+ else if (line_status & UART_PARITY_ERROR)
tty_flag = TTY_PARITY;
- else if (status & UART_FRAME_ERROR)
+ else if (line_status & UART_FRAME_ERROR)
tty_flag = TTY_FRAME;
dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag);
@@ -1052,7 +1029,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
if (tty && urb->actual_length) {
tty_buffer_request_room(tty, urb->actual_length + 1);
/* overrun is special, not associated with a char */
- if (status & UART_OVERRUN_ERROR)
+ if (line_status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
for (i = 0; i < urb->actual_length; ++i)
tty_insert_flip_char(tty, data[i], tty_flag);
@@ -1076,10 +1053,11 @@ static void pl2303_write_bulk_callback(struct urb *urb)
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
struct pl2303_private *priv = usb_get_serial_port_data(port);
int result;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -1088,14 +1066,14 @@ static void pl2303_write_bulk_callback(struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__,
- urb->status);
+ status);
priv->write_urb_in_use = 0;
return;
default:
/* error in the urb, so we have to resubmit it */
dbg("%s - Overflow in write", __FUNCTION__);
dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
- urb->status);
+ status);
port->write_urb->transfer_buffer_length = 1;
port->write_urb->dev = port->serial->dev;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c
index 5a03a3fc938..86899d55d8d 100644
--- a/drivers/usb/serial/safe_serial.c
+++ b/drivers/usb/serial/safe_serial.c
@@ -211,11 +211,13 @@ static void safe_read_bulk_callback (struct urb *urb)
unsigned char length = urb->actual_length;
int i;
int result;
+ int status = urb->status;
dbg ("%s", __FUNCTION__);
- if (urb->status) {
- dbg ("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
return;
}
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index ac1829c6e8f..e7db20343d1 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -86,15 +86,14 @@ static int debug;
#define N_IN_URB 4
#define N_OUT_URB 4
#define IN_BUFLEN 4096
-#define OUT_BUFLEN 128
struct sierra_port_private {
+ spinlock_t lock; /* lock the structure */
+ int outstanding_urbs; /* number of out urbs in flight */
+
/* Input endpoints and buffer for this port */
struct urb *in_urbs[N_IN_URB];
char in_buffer[N_IN_URB][IN_BUFLEN];
- /* Output endpoints and buffer for this port */
- struct urb *out_urbs[N_OUT_URB];
- char out_buffer[N_OUT_URB][OUT_BUFLEN];
/* Settings for the port */
int rts_state; /* Handshaking pins (outputs) */
@@ -103,8 +102,6 @@ struct sierra_port_private {
int dsr_state;
int dcd_state;
int ri_state;
-
- unsigned long tx_start_time[N_OUT_URB];
};
static int sierra_send_setup(struct usb_serial_port *port)
@@ -197,61 +194,98 @@ static int sierra_ioctl(struct usb_serial_port *port, struct file *file,
return -ENOIOCTLCMD;
}
+static void sierra_outdat_callback(struct urb *urb)
+{
+ struct usb_serial_port *port = urb->context;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ int status = urb->status;
+ unsigned long flags;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /* free up the transfer buffer, as usb_free_urb() does not do this */
+ kfree(urb->transfer_buffer);
+
+ if (status)
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
+
+ spin_lock_irqsave(&portdata->lock, flags);
+ --portdata->outstanding_urbs;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+
+ usb_serial_port_softint(port);
+}
+
/* Write */
static int sierra_write(struct usb_serial_port *port,
const unsigned char *buf, int count)
{
- struct sierra_port_private *portdata;
- int i;
- int left, todo;
- struct urb *this_urb = NULL; /* spurious */
- int err;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+ unsigned long flags;
+ unsigned char *buffer;
+ struct urb *urb;
+ int status;
portdata = usb_get_serial_port_data(port);
dbg("%s: write (%d chars)", __FUNCTION__, count);
- i = 0;
- left = count;
- for (i=0; left > 0 && i < N_OUT_URB; i++) {
- todo = left;
- if (todo > OUT_BUFLEN)
- todo = OUT_BUFLEN;
-
- this_urb = portdata->out_urbs[i];
- if (this_urb->status == -EINPROGRESS) {
- if (time_before(jiffies,
- portdata->tx_start_time[i] + 10 * HZ))
- continue;
- usb_unlink_urb(this_urb);
- continue;
- }
- if (this_urb->status != 0)
- dbg("usb_write %p failed (err=%d)",
- this_urb, this_urb->status);
-
- dbg("%s: endpoint %d buf %d", __FUNCTION__,
- usb_pipeendpoint(this_urb->pipe), i);
-
- /* send the data */
- memcpy (this_urb->transfer_buffer, buf, todo);
- this_urb->transfer_buffer_length = todo;
-
- this_urb->dev = port->serial->dev;
- err = usb_submit_urb(this_urb, GFP_ATOMIC);
- if (err) {
- dbg("usb_submit_urb %p (write bulk) failed "
- "(%d, has %d)", this_urb,
- err, this_urb->status);
- continue;
- }
- portdata->tx_start_time[i] = jiffies;
- buf += todo;
- left -= todo;
+ spin_lock_irqsave(&portdata->lock, flags);
+ if (portdata->outstanding_urbs > N_OUT_URB) {
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ dbg("%s - write limit hit\n", __FUNCTION__);
+ return 0;
+ }
+ portdata->outstanding_urbs++;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+
+ buffer = kmalloc(count, GFP_ATOMIC);
+ if (!buffer) {
+ dev_err(&port->dev, "out of memory\n");
+ count = -ENOMEM;
+ goto error_no_buffer;
+ }
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ dev_err(&port->dev, "no more free urbs\n");
+ count = -ENOMEM;
+ goto error_no_urb;
+ }
+
+ memcpy(buffer, buf, count);
+
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
+ buffer, count, sierra_outdat_callback, port);
+
+ /* send it down the pipe */
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ "with status = %d\n", __FUNCTION__, status);
+ count = status;
+ goto error;
}
- count -= left;
- dbg("%s: wrote (did %d)", __FUNCTION__, count);
+ /* we are done with this urb, so let the host driver
+ * really free it when it is finished with it */
+ usb_free_urb(urb);
+
+ return count;
+error:
+ usb_free_urb(urb);
+error_no_urb:
+ kfree(buffer);
+error_no_buffer:
+ spin_lock_irqsave(&portdata->lock, flags);
+ --portdata->outstanding_urbs;
+ spin_unlock_irqrestore(&portdata->lock, flags);
return count;
}
@@ -262,15 +296,16 @@ static void sierra_indat_callback(struct urb *urb)
struct usb_serial_port *port;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
dbg("%s: %p", __FUNCTION__, urb);
endpoint = usb_pipeendpoint(urb->pipe);
port = (struct usb_serial_port *) urb->context;
- if (urb->status) {
+ if (status) {
dbg("%s: nonzero status: %d on endpoint %02x.",
- __FUNCTION__, urb->status, endpoint);
+ __FUNCTION__, status, endpoint);
} else {
tty = port->tty;
if (urb->actual_length) {
@@ -282,30 +317,20 @@ static void sierra_indat_callback(struct urb *urb)
}
/* Resubmit urb so we continue receiving */
- if (port->open_count && urb->status != -ESHUTDOWN) {
+ if (port->open_count && status != -ESHUTDOWN) {
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
- printk(KERN_ERR "%s: resubmit read urb failed. "
- "(%d)", __FUNCTION__, err);
+ dev_err(&port->dev, "resubmit read urb failed."
+ "(%d)", err);
}
}
return;
}
-static void sierra_outdat_callback(struct urb *urb)
-{
- struct usb_serial_port *port;
-
- dbg("%s", __FUNCTION__);
-
- port = (struct usb_serial_port *) urb->context;
-
- usb_serial_port_softint(port);
-}
-
static void sierra_instat_callback(struct urb *urb)
{
int err;
+ int status = urb->status;
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
struct sierra_port_private *portdata = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
@@ -313,7 +338,7 @@ static void sierra_instat_callback(struct urb *urb)
dbg("%s", __FUNCTION__);
dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
- if (urb->status == 0) {
+ if (status == 0) {
struct usb_ctrlrequest *req_pkt =
(struct usb_ctrlrequest *)urb->transfer_buffer;
@@ -344,10 +369,10 @@ static void sierra_instat_callback(struct urb *urb)
req_pkt->bRequestType,req_pkt->bRequest);
}
} else
- dbg("%s: error %d", __FUNCTION__, urb->status);
+ dbg("%s: error %d", __FUNCTION__, status);
/* Resubmit urb so we continue receiving IRQ data */
- if (urb->status != -ESHUTDOWN) {
+ if (status != -ESHUTDOWN) {
urb->dev = serial->dev;
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err)
@@ -358,46 +383,42 @@ static void sierra_instat_callback(struct urb *urb)
static int sierra_write_room(struct usb_serial_port *port)
{
- struct sierra_port_private *portdata;
- int i;
- int data_len = 0;
- struct urb *this_urb;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ unsigned long flags;
- portdata = usb_get_serial_port_data(port);
+ dbg("%s - port %d", __FUNCTION__, port->number);
- for (i=0; i < N_OUT_URB; i++) {
- this_urb = portdata->out_urbs[i];
- if (this_urb && this_urb->status != -EINPROGRESS)
- data_len += OUT_BUFLEN;
+ /* try to give a good number back based on if we have any free urbs at
+ * this point in time */
+ spin_lock_irqsave(&portdata->lock, flags);
+ if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) {
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ dbg("%s - write limit hit\n", __FUNCTION__);
+ return 0;
}
+ spin_unlock_irqrestore(&portdata->lock, flags);
- dbg("%s: %d", __FUNCTION__, data_len);
- return data_len;
+ return 2048;
}
static int sierra_chars_in_buffer(struct usb_serial_port *port)
{
- struct sierra_port_private *portdata;
- int i;
- int data_len = 0;
- struct urb *this_urb;
-
- portdata = usb_get_serial_port_data(port);
-
- for (i=0; i < N_OUT_URB; i++) {
- this_urb = portdata->out_urbs[i];
- if (this_urb && this_urb->status == -EINPROGRESS)
- data_len += this_urb->transfer_buffer_length;
- }
- dbg("%s: %d", __FUNCTION__, data_len);
- return data_len;
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /*
+ * We can't really account for how much data we
+ * have sent out, but hasn't made it through to the
+ * device as we can't see the backend here, so just
+ * tell the tty layer that everything is flushed.
+ */
+ return 0;
}
static int sierra_open(struct usb_serial_port *port, struct file *filp)
{
struct sierra_port_private *portdata;
struct usb_serial *serial = port->serial;
- int i, err;
+ int i;
struct urb *urb;
int result;
__u16 set_mode_dzero = 0x0000;
@@ -413,7 +434,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
/* Reset low level data toggle and start reading from endpoints */
for (i = 0; i < N_IN_URB; i++) {
urb = portdata->in_urbs[i];
- if (! urb)
+ if (!urb)
continue;
if (urb->dev != serial->dev) {
dbg("%s: dev %p != %p", __FUNCTION__,
@@ -427,24 +448,13 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
*/
usb_clear_halt(urb->dev, urb->pipe);
- err = usb_submit_urb(urb, GFP_KERNEL);
- if (err) {
- dbg("%s: submit urb %d failed (%d) %d",
- __FUNCTION__, i, err,
- urb->transfer_buffer_length);
+ result = usb_submit_urb(urb, GFP_KERNEL);
+ if (result) {
+ dev_err(&port->dev, "submit urb %d failed (%d) %d",
+ i, result, urb->transfer_buffer_length);
}
}
- /* Reset low level data toggle on out endpoints */
- for (i = 0; i < N_OUT_URB; i++) {
- urb = portdata->out_urbs[i];
- if (! urb)
- continue;
- urb->dev = serial->dev;
- /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe), 0); */
- }
-
port->tty->low_latency = 1;
/* set mode to D0 */
@@ -455,7 +465,14 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp)
sierra_send_setup(port);
- return (0);
+ /* start up the interrupt endpoint if we have one */
+ if (port->interrupt_in_urb) {
+ result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (result)
+ dev_err(&port->dev, "submit irq_in urb failed %d",
+ result);
+ }
+ return 0;
}
static void sierra_close(struct usb_serial_port *port, struct file *filp)
@@ -475,71 +492,21 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp)
/* Stop reading/writing urbs */
for (i = 0; i < N_IN_URB; i++)
- usb_unlink_urb(portdata->in_urbs[i]);
- for (i = 0; i < N_OUT_URB; i++)
- usb_unlink_urb(portdata->out_urbs[i]);
+ usb_kill_urb(portdata->in_urbs[i]);
}
- port->tty = NULL;
-}
-
-/* Helper functions used by sierra_setup_urbs */
-static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint,
- int dir, void *ctx, char *buf, int len,
- usb_complete_t callback)
-{
- struct urb *urb;
-
- if (endpoint == -1)
- return NULL; /* endpoint not needed */
-
- urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
- if (urb == NULL) {
- dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
- return NULL;
- }
-
- /* Fill URB using supplied data. */
- usb_fill_bulk_urb(urb, serial->dev,
- usb_sndbulkpipe(serial->dev, endpoint) | dir,
- buf, len, callback, ctx);
-
- return urb;
-}
-/* Setup urbs */
-static void sierra_setup_urbs(struct usb_serial *serial)
-{
- int i,j;
- struct usb_serial_port *port;
- struct sierra_port_private *portdata;
-
- dbg("%s", __FUNCTION__);
+ usb_kill_urb(port->interrupt_in_urb);
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- portdata = usb_get_serial_port_data(port);
-
- /* Do indat endpoints first */
- for (j = 0; j < N_IN_URB; ++j) {
- portdata->in_urbs[j] = sierra_setup_urb (serial,
- port->bulk_in_endpointAddress, USB_DIR_IN, port,
- portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback);
- }
-
- /* outdat endpoints */
- for (j = 0; j < N_OUT_URB; ++j) {
- portdata->out_urbs[j] = sierra_setup_urb (serial,
- port->bulk_out_endpointAddress, USB_DIR_OUT, port,
- portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback);
- }
- }
+ port->tty = NULL;
}
static int sierra_startup(struct usb_serial *serial)
{
- int i, err;
struct usb_serial_port *port;
struct sierra_port_private *portdata;
+ struct urb *urb;
+ int i;
+ int j;
dbg("%s", __FUNCTION__);
@@ -550,22 +517,31 @@ static int sierra_startup(struct usb_serial *serial)
if (!portdata) {
dbg("%s: kmalloc for sierra_port_private (%d) failed!.",
__FUNCTION__, i);
- return (1);
+ return -ENOMEM;
}
+ spin_lock_init(&portdata->lock);
usb_set_serial_port_data(port, portdata);
- if (! port->interrupt_in_urb)
- continue;
- err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
- if (err)
- dbg("%s: submit irq_in urb failed %d",
- __FUNCTION__, err);
+ /* initialize the in urbs */
+ for (j = 0; j < N_IN_URB; ++j) {
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (urb == NULL) {
+ dbg("%s: alloc for in port failed.",
+ __FUNCTION__);
+ continue;
+ }
+ /* Fill URB using supplied data. */
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ portdata->in_buffer[j], IN_BUFLEN,
+ sierra_indat_callback, port);
+ portdata->in_urbs[j] = urb;
+ }
}
- sierra_setup_urbs(serial);
-
- return (0);
+ return 0;
}
static void sierra_shutdown(struct usb_serial *serial)
@@ -576,22 +552,6 @@ static void sierra_shutdown(struct usb_serial *serial)
dbg("%s", __FUNCTION__);
- /* Stop reading/writing urbs */
- 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;
-
- for (j = 0; j < N_IN_URB; j++)
- usb_unlink_urb(portdata->in_urbs[j]);
- for (j = 0; j < N_OUT_URB; j++)
- usb_unlink_urb(portdata->out_urbs[j]);
- }
-
- /* Now free them */
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (!port)
@@ -601,25 +561,12 @@ static void sierra_shutdown(struct usb_serial *serial)
continue;
for (j = 0; j < N_IN_URB; j++) {
- if (portdata->in_urbs[j]) {
- usb_free_urb(portdata->in_urbs[j]);
- portdata->in_urbs[j] = NULL;
- }
+ usb_kill_urb(portdata->in_urbs[j]);
+ usb_free_urb(portdata->in_urbs[j]);
+ portdata->in_urbs[j] = NULL;
}
- for (j = 0; j < N_OUT_URB; j++) {
- if (portdata->out_urbs[j]) {
- usb_free_urb(portdata->out_urbs[j]);
- portdata->out_urbs[j] = NULL;
- }
- }
- }
-
- /* Now free per port private data */
- for (i = 0; i < serial->num_ports; i++) {
- port = serial->port[i];
- if (!port)
- continue;
- kfree(usb_get_serial_port_data(port));
+ kfree(portdata);
+ usb_set_serial_port_data(port, NULL);
}
}
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index 4203e2b1a76..f98626ae75f 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1112,22 +1112,24 @@ static void ti_interrupt_callback(struct urb *urb)
int length = urb->actual_length;
int port_number;
int function;
- int status;
+ int status = urb->status;
+ int retval;
__u8 msr;
dbg("%s", __FUNCTION__);
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
- dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down, %d", __FUNCTION__, status);
tdev->td_urb_error = 1;
return;
default:
- dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status);
+ dev_err(dev, "%s - nonzero urb status, %d\n",
+ __FUNCTION__, status);
tdev->td_urb_error = 1;
goto exit;
}
@@ -1175,9 +1177,10 @@ static void ti_interrupt_callback(struct urb *urb)
}
exit:
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status)
- dev_err(dev, "%s - resubmit interrupt urb failed, %d\n", __FUNCTION__, status);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(dev, "%s - resubmit interrupt urb failed, %d\n",
+ __FUNCTION__, retval);
}
@@ -1186,30 +1189,32 @@ static void ti_bulk_in_callback(struct urb *urb)
struct ti_port *tport = (struct ti_port *)urb->context;
struct usb_serial_port *port = tport->tp_port;
struct device *dev = &urb->dev->dev;
- int status = 0;
+ int status = urb->status;
+ int retval = 0;
dbg("%s", __FUNCTION__);
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
- dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down, %d", __FUNCTION__, status);
tport->tp_tdev->td_urb_error = 1;
wake_up_interruptible(&tport->tp_write_wait);
return;
default:
- dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status );
+ dev_err(dev, "%s - nonzero urb status, %d\n",
+ __FUNCTION__, status );
tport->tp_tdev->td_urb_error = 1;
wake_up_interruptible(&tport->tp_write_wait);
}
- if (urb->status == -EPIPE)
+ if (status == -EPIPE)
goto exit;
- if (urb->status) {
+ if (status) {
dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
return;
}
@@ -1234,13 +1239,14 @@ exit:
spin_lock(&tport->tp_lock);
if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) {
urb->dev = port->serial->dev;
- status = usb_submit_urb(urb, GFP_ATOMIC);
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
} else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING) {
tport->tp_read_urb_state = TI_READ_URB_STOPPED;
}
spin_unlock(&tport->tp_lock);
- if (status)
- dev_err(dev, "%s - resubmit read urb failed, %d\n", __FUNCTION__, status);
+ if (retval)
+ dev_err(dev, "%s - resubmit read urb failed, %d\n",
+ __FUNCTION__, retval);
}
@@ -1249,23 +1255,25 @@ static void ti_bulk_out_callback(struct urb *urb)
struct ti_port *tport = (struct ti_port *)urb->context;
struct usb_serial_port *port = tport->tp_port;
struct device *dev = &urb->dev->dev;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
tport->tp_write_urb_in_use = 0;
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
- dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+ dbg("%s - urb shutting down, %d", __FUNCTION__, status);
tport->tp_tdev->td_urb_error = 1;
wake_up_interruptible(&tport->tp_write_wait);
return;
default:
- dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status);
+ dev_err(dev, "%s - nonzero urb status, %d\n",
+ __FUNCTION__, status);
tport->tp_tdev->td_urb_error = 1;
wake_up_interruptible(&tport->tp_write_wait);
}
@@ -1555,15 +1563,17 @@ static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty)
spin_lock_irqsave(&tport->tp_lock, flags);
if (tport->tp_read_urb_state == TI_READ_URB_STOPPED) {
+ tport->tp_read_urb_state = TI_READ_URB_RUNNING;
urb = tport->tp_port->read_urb;
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
urb->complete = ti_bulk_in_callback;
urb->context = tport;
urb->dev = tport->tp_port->serial->dev;
status = usb_submit_urb(urb, GFP_KERNEL);
+ } else {
+ tport->tp_read_urb_state = TI_READ_URB_RUNNING;
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
}
- tport->tp_read_urb_state = TI_READ_URB_RUNNING;
-
- spin_unlock_irqrestore(&tport->tp_lock, flags);
return status;
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 87f378806db..a3665659d13 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -46,6 +46,8 @@ static struct usb_driver usb_serial_driver = {
.name = "usbserial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
+ .suspend = usb_serial_suspend,
+ .resume = usb_serial_resume,
.no_dynamic_id = 1,
};
@@ -120,11 +122,9 @@ static void return_serial(struct usb_serial *serial)
if (serial == NULL)
return;
- spin_lock(&table_lock);
for (i = 0; i < serial->num_ports; ++i) {
serial_table[serial->minor + i] = NULL;
}
- spin_unlock(&table_lock);
}
static void destroy_serial(struct kref *kref)
@@ -172,7 +172,9 @@ static void destroy_serial(struct kref *kref)
void usb_serial_put(struct usb_serial *serial)
{
+ spin_lock(&table_lock);
kref_put(&serial->kref, destroy_serial);
+ spin_unlock(&table_lock);
}
/*****************************************************************************
@@ -1069,6 +1071,35 @@ void usb_serial_disconnect(struct usb_interface *interface)
dev_info(dev, "device disconnected\n");
}
+int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usb_serial *serial = usb_get_intfdata(intf);
+ struct usb_serial_port *port;
+ int i, r = 0;
+
+ if (serial) {
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (port)
+ kill_traffic(port);
+ }
+ }
+
+ if (serial->type->suspend)
+ serial->type->suspend(serial, message);
+
+ return r;
+}
+EXPORT_SYMBOL(usb_serial_suspend);
+
+int usb_serial_resume(struct usb_interface *intf)
+{
+ struct usb_serial *serial = usb_get_intfdata(intf);
+
+ return serial->type->resume(serial);
+}
+EXPORT_SYMBOL(usb_serial_resume);
+
static const struct tty_operations serial_ops = {
.open = serial_open,
.close = serial_close,
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index ffbe601cde2..7d84a7647e8 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -5,9 +5,9 @@
* Copyright (C) 1999 - 2004
* Greg Kroah-Hartman (greg@kroah.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.
+ * 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.
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
@@ -273,7 +273,8 @@ struct visor_private {
int bytes_in;
int bytes_out;
int outstanding_urbs;
- int throttled;
+ unsigned char throttled;
+ unsigned char actually_throttled;
};
/* number of outstanding urbs to prevent userspace DoS from happening */
@@ -484,16 +485,17 @@ static void visor_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct visor_private *priv = usb_get_serial_port_data(port);
+ int status = urb->status;
unsigned long flags;
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree (urb->transfer_buffer);
dbg("%s - port %d", __FUNCTION__, port->number);
-
- if (urb->status)
+
+ if (status)
dbg("%s - nonzero write bulk status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
spin_lock_irqsave(&priv->lock, flags);
--priv->outstanding_urbs;
@@ -508,15 +510,16 @@ static void visor_read_bulk_callback (struct urb *urb)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct visor_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
struct tty_struct *tty;
- unsigned long flags;
- int throttled;
int result;
+ int available_room;
dbg("%s - port %d", __FUNCTION__, port->number);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -524,17 +527,20 @@ static void visor_read_bulk_callback (struct urb *urb)
tty = port->tty;
if (tty && urb->actual_length) {
- tty_buffer_request_room(tty, urb->actual_length);
- tty_insert_flip_string(tty, data, urb->actual_length);
- tty_flip_buffer_push(tty);
+ available_room = tty_buffer_request_room(tty, urb->actual_length);
+ if (available_room) {
+ tty_insert_flip_string(tty, data, available_room);
+ tty_flip_buffer_push(tty);
+ }
+ spin_lock(&priv->lock);
+ priv->bytes_in += available_room;
+
+ } else {
+ spin_lock(&priv->lock);
}
- spin_lock_irqsave(&priv->lock, flags);
- priv->bytes_in += urb->actual_length;
- throttled = priv->throttled;
- spin_unlock_irqrestore(&priv->lock, flags);
/* Continue trying to always read if we should */
- if (!throttled) {
+ if (!priv->throttled) {
usb_fill_bulk_urb (port->read_urb, port->serial->dev,
usb_rcvbulkpipe(port->serial->dev,
port->bulk_in_endpointAddress),
@@ -544,16 +550,19 @@ static void visor_read_bulk_callback (struct urb *urb)
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+ } else {
+ priv->actually_throttled = 1;
}
- return;
+ spin_unlock(&priv->lock);
}
static void visor_read_int_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ int status = urb->status;
int result;
- switch (urb->status) {
+ switch (status) {
case 0:
/* success */
break;
@@ -562,11 +571,11 @@ static void visor_read_int_callback (struct urb *urb)
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
return;
default:
dbg("%s - nonzero urb status received: %d",
- __FUNCTION__, urb->status);
+ __FUNCTION__, status);
goto exit;
}
@@ -608,6 +617,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
dbg("%s - port %d", __FUNCTION__, port->number);
spin_lock_irqsave(&priv->lock, flags);
priv->throttled = 0;
+ priv->actually_throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags);
port->read_urb->dev = port->serial->dev;
@@ -938,14 +948,6 @@ static void visor_set_termios (struct usb_serial_port *port, struct ktermios *ol
}
cflag = port->tty->termios->c_cflag;
- /* check that they really want us to change something */
- if (old_termios) {
- if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
- dbg("%s - nothing to change...", __FUNCTION__);
- return;
- }
- }
/* get the byte size */
switch (cflag & CSIZE) {
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 27c5f8f9a2d..cc8b44c0871 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -74,6 +74,7 @@
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/termbits.h>
#include <linux/usb.h>
@@ -203,7 +204,7 @@ static struct usb_serial_driver whiteheat_device = {
struct whiteheat_command_private {
- spinlock_t lock;
+ struct mutex mutex;
__u8 port_running;
__u8 command_finished;
wait_queue_head_t wait_command; /* for handling sleeping while waiting for a command to finish */
@@ -232,6 +233,7 @@ struct whiteheat_private {
struct usb_serial_port *port;
struct list_head tx_urbs_free;
struct list_head tx_urbs_submitted;
+ struct mutex deathwarrant;
};
@@ -425,6 +427,7 @@ static int whiteheat_attach (struct usb_serial *serial)
}
spin_lock_init(&info->lock);
+ mutex_init(&info->deathwarrant);
info->flags = 0;
info->mcr = 0;
INIT_WORK(&info->rx_work, rx_data_softint);
@@ -495,7 +498,7 @@ static int whiteheat_attach (struct usb_serial *serial)
goto no_command_private;
}
- spin_lock_init(&command_info->lock);
+ mutex_init(&command_info->mutex);
command_info->port_running = 0;
init_waitqueue_head(&command_info->wait_command);
usb_set_serial_port_data(command_port, command_info);
@@ -654,7 +657,6 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
struct urb *urb;
struct list_head *tmp;
struct list_head *tmp2;
- unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -683,24 +685,32 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
firm_close(port);
+printk(KERN_ERR"Before processing rx_urbs_submitted.\n");
/* shutdown our bulk reads and writes */
- spin_lock_irqsave(&info->lock, flags);
+ mutex_lock(&info->deathwarrant);
+ spin_lock_irq(&info->lock);
list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
+ list_del(tmp);
+ spin_unlock_irq(&info->lock);
usb_kill_urb(urb);
- list_move(tmp, &info->rx_urbs_free);
+ spin_lock_irq(&info->lock);
+ list_add(tmp, &info->rx_urbs_free);
}
list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
list_move(tmp, &info->rx_urbs_free);
-
list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
+ list_del(tmp);
+ spin_unlock_irq(&info->lock);
usb_kill_urb(urb);
- list_move(tmp, &info->tx_urbs_free);
+ spin_lock_irq(&info->lock);
+ list_add(tmp, &info->tx_urbs_free);
}
- spin_unlock_irqrestore(&info->lock, flags);
+ spin_unlock_irq(&info->lock);
+ mutex_unlock(&info->deathwarrant);
stop_command_port(port->serial);
@@ -872,7 +882,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un
}
-static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios)
+static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios)
{
dbg("%s -port %d", __FUNCTION__, port->number);
@@ -881,15 +891,6 @@ static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios
goto exit;
}
- /* check that they really want us to change something */
- if (old_termios) {
- if ((port->tty->termios->c_cflag == old_termios->c_cflag) &&
- (port->tty->termios->c_iflag == old_termios->c_iflag)) {
- dbg("%s - nothing to change...", __FUNCTION__);
- goto exit;
- }
- }
-
firm_setup_port(port);
exit:
@@ -920,7 +921,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
spin_unlock_irqrestore(&info->lock, flags);
dbg ("%s - returns %d", __FUNCTION__, chars);
- return (chars);
+ return chars;
}
@@ -962,54 +963,57 @@ static void whiteheat_unthrottle (struct usb_serial_port *port)
/*****************************************************************************
* Connect Tech's White Heat callback routines
*****************************************************************************/
-static void command_port_write_callback (struct urb *urb)
+static void command_port_write_callback(struct urb *urb)
{
+ int status = urb->status;
+
dbg("%s", __FUNCTION__);
- if (urb->status) {
- dbg ("nonzero urb status: %d", urb->status);
+ if (status) {
+ dbg("nonzero urb status: %d", status);
return;
}
}
-static void command_port_read_callback (struct urb *urb)
+static void command_port_read_callback(struct urb *urb)
{
struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context;
struct whiteheat_command_private *command_info;
+ int status = urb->status;
unsigned char *data = urb->transfer_buffer;
int result;
- unsigned long flags;
dbg("%s", __FUNCTION__);
- if (urb->status) {
- dbg("%s - nonzero urb status: %d", __FUNCTION__, urb->status);
- return;
- }
-
- usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
-
command_info = usb_get_serial_port_data(command_port);
if (!command_info) {
dbg ("%s - command_info is NULL, exiting.", __FUNCTION__);
return;
}
- spin_lock_irqsave(&command_info->lock, flags);
+ if (status) {
+ dbg("%s - nonzero urb status: %d", __FUNCTION__, status);
+ if (status != -ENOENT)
+ command_info->command_finished = WHITEHEAT_CMD_FAILURE;
+ wake_up(&command_info->wait_command);
+ return;
+ }
+
+ usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data);
if (data[0] == WHITEHEAT_CMD_COMPLETE) {
command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
- wake_up_interruptible(&command_info->wait_command);
+ wake_up(&command_info->wait_command);
} else if (data[0] == WHITEHEAT_CMD_FAILURE) {
command_info->command_finished = WHITEHEAT_CMD_FAILURE;
- wake_up_interruptible(&command_info->wait_command);
+ wake_up(&command_info->wait_command);
} else if (data[0] == WHITEHEAT_EVENT) {
/* These are unsolicited reports from the firmware, hence no waiting command to wakeup */
dbg("%s - event received", __FUNCTION__);
} else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1);
command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
- wake_up_interruptible(&command_info->wait_command);
+ wake_up(&command_info->wait_command);
} else {
dbg("%s - bad reply from firmware", __FUNCTION__);
}
@@ -1017,7 +1021,6 @@ static void command_port_read_callback (struct urb *urb)
/* Continue trying to always read */
command_port->read_urb->dev = command_port->serial->dev;
result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC);
- spin_unlock_irqrestore(&command_info->lock, flags);
if (result)
dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
}
@@ -1029,6 +1032,7 @@ static void whiteheat_read_callback(struct urb *urb)
struct whiteheat_urb_wrap *wrap;
unsigned char *data = urb->transfer_buffer;
struct whiteheat_private *info = usb_get_serial_port_data(port);
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1042,8 +1046,9 @@ static void whiteheat_read_callback(struct urb *urb)
list_del(&wrap->list);
spin_unlock(&info->lock);
- if (urb->status) {
- dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, status);
spin_lock(&info->lock);
list_add(&wrap->list, &info->rx_urbs_free);
spin_unlock(&info->lock);
@@ -1070,6 +1075,7 @@ static void whiteheat_write_callback(struct urb *urb)
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct whiteheat_private *info = usb_get_serial_port_data(port);
struct whiteheat_urb_wrap *wrap;
+ int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1083,8 +1089,9 @@ static void whiteheat_write_callback(struct urb *urb)
list_move(&wrap->list, &info->tx_urbs_free);
spin_unlock(&info->lock);
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+ if (status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, status);
return;
}
@@ -1095,20 +1102,20 @@ static void whiteheat_write_callback(struct urb *urb)
/*****************************************************************************
* Connect Tech's White Heat firmware interface
*****************************************************************************/
-static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
+static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
struct whiteheat_private *info;
__u8 *transfer_buffer;
int retval = 0;
- unsigned long flags;
+ int t;
dbg("%s - command %d", __FUNCTION__, command);
command_port = port->serial->port[COMMAND_PORT];
command_info = usb_get_serial_port_data(command_port);
- spin_lock_irqsave(&command_info->lock, flags);
+ mutex_lock(&command_info->mutex);
command_info->command_finished = false;
transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer;
@@ -1116,18 +1123,17 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *
memcpy (&transfer_buffer[1], data, datasize);
command_port->write_urb->transfer_buffer_length = datasize + 1;
command_port->write_urb->dev = port->serial->dev;
- retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL);
+ retval = usb_submit_urb (command_port->write_urb, GFP_NOIO);
if (retval) {
dbg("%s - submit urb failed", __FUNCTION__);
goto exit;
}
- spin_unlock_irqrestore(&command_info->lock, flags);
/* wait for the command to complete */
- wait_event_interruptible_timeout(command_info->wait_command,
+ t = wait_event_timeout(command_info->wait_command,
(bool)command_info->command_finished, COMMAND_TIMEOUT);
-
- spin_lock_irqsave(&command_info->lock, flags);
+ if (!t)
+ usb_kill_urb(command_port->write_urb);
if (command_info->command_finished == false) {
dbg("%s - command timed out.", __FUNCTION__);
@@ -1152,7 +1158,7 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *
}
exit:
- spin_unlock_irqrestore(&command_info->lock, flags);
+ mutex_unlock(&command_info->mutex);
return retval;
}
@@ -1305,12 +1311,11 @@ static int start_command_port(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
- unsigned long flags;
int retval = 0;
command_port = serial->port[COMMAND_PORT];
command_info = usb_get_serial_port_data(command_port);
- spin_lock_irqsave(&command_info->lock, flags);
+ mutex_lock(&command_info->mutex);
if (!command_info->port_running) {
/* Work around HCD bugs */
usb_clear_halt(serial->dev, command_port->read_urb->pipe);
@@ -1325,7 +1330,7 @@ static int start_command_port(struct usb_serial *serial)
command_info->port_running++;
exit:
- spin_unlock_irqrestore(&command_info->lock, flags);
+ mutex_unlock(&command_info->mutex);
return retval;
}
@@ -1334,15 +1339,14 @@ static void stop_command_port(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
- unsigned long flags;
command_port = serial->port[COMMAND_PORT];
command_info = usb_get_serial_port_data(command_port);
- spin_lock_irqsave(&command_info->lock, flags);
+ mutex_lock(&command_info->mutex);
command_info->port_running--;
if (!command_info->port_running)
usb_kill_urb(command_port->read_urb);
- spin_unlock_irqrestore(&command_info->lock, flags);
+ mutex_unlock(&command_info->mutex);
}
@@ -1363,17 +1367,23 @@ static int start_port_read(struct usb_serial_port *port)
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
urb->dev = port->serial->dev;
+ spin_unlock_irqrestore(&info->lock, flags);
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
+ spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->rx_urbs_free);
list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) {
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
urb = wrap->urb;
+ list_del(tmp);
+ spin_unlock_irqrestore(&info->lock, flags);
usb_kill_urb(urb);
- list_move(tmp, &info->rx_urbs_free);
+ spin_lock_irqsave(&info->lock, flags);
+ list_add(tmp, &info->rx_urbs_free);
}
break;
}
+ spin_lock_irqsave(&info->lock, flags);
list_add(tmp, &info->rx_urbs_submitted);
}
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index e227f64d564..47e56079925 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -285,10 +285,15 @@ static int device_reset(struct scsi_cmnd *srb)
US_DEBUGP("%s called\n", __FUNCTION__);
- /* lock the device pointers and do the reset */
- mutex_lock(&(us->dev_mutex));
- result = us->transport_reset(us);
- mutex_unlock(&us->dev_mutex);
+ result = usb_autopm_get_interface(us->pusb_intf);
+ if (result == 0) {
+
+ /* lock the device pointers and do the reset */
+ mutex_lock(&(us->dev_mutex));
+ result = us->transport_reset(us);
+ mutex_unlock(&us->dev_mutex);
+ usb_autopm_put_interface(us->pusb_intf);
+ }
return result < 0 ? FAILED : SUCCESS;
}
@@ -321,10 +326,14 @@ void usb_stor_report_device_reset(struct us_data *us)
/* Report a driver-initiated bus reset to the SCSI layer.
* Calling this for a SCSI-initiated reset is unnecessary but harmless.
- * The caller must own the SCSI host lock. */
+ * The caller must not own the SCSI host lock. */
void usb_stor_report_bus_reset(struct us_data *us)
{
- scsi_report_bus_reset(us_to_host(us), 0);
+ struct Scsi_Host *host = us_to_host(us);
+
+ scsi_lock(host);
+ scsi_report_bus_reset(host, 0);
+ scsi_unlock(host);
}
/***********************************************************************
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index d230ee72f9c..b6bf31a97b6 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -50,10 +50,10 @@
/* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr>
*/
UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100,
- "ATMEL",
- "SND1 Storage",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_RESIDUE),
+ "ATMEL",
+ "SND1 Storage",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE),
/* modified by Tobias Lorenz <tobias.lorenz@gmx.net> */
UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0200,
@@ -69,18 +69,18 @@ UNUSUAL_DEV( 0x03ee, 0x6906, 0x0003, 0x0003,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
-UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200,
+UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200,
"HP",
"CD-Writer+",
- US_SC_8070, US_PR_CB, NULL, 0),
+ US_SC_8070, US_PR_CB, NULL, 0),
#ifdef CONFIG_USB_STORAGE_USBAT
-UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
+UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
"HP",
"CD-Writer+ 8200e",
US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
-UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
+UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
"HP",
"CD-Writer+ CD-4e",
US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
@@ -115,10 +115,10 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113,
/* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */
UNUSUAL_DEV( 0x0419, 0x0100, 0x0100, 0x0100,
- "Samsung Info. Systems America, Inc.",
- "MP3 Player",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_RESIDUE ),
+ "Samsung Info. Systems America, Inc.",
+ "MP3 Player",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
/* Reported by Orgad Shaneh <orgads@gmail.com> */
UNUSUAL_DEV( 0x0419, 0xaace, 0x0100, 0x0100,
@@ -256,10 +256,10 @@ UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100,
* the revision to my model only
*/
UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100,
- "USB 2.0",
- "Flash Disk",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_NOT_LOCKABLE ),
+ "USB 2.0",
+ "Flash Disk",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_NOT_LOCKABLE ),
#ifdef CONFIG_USB_STORAGE_KARMA
UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101,
@@ -408,19 +408,19 @@ UNUSUAL_DEV( 0x04da, 0x2373, 0x0000, 0x9999,
/* Most of the following entries were developed with the help of
* Shuttle/SCM directly.
*/
-UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200,
+UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200,
"Matshita",
"LS-120",
US_SC_8020, US_PR_CB, NULL, 0),
-UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100,
"Shuttle",
"eUSCSI Bridge",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
+ US_FL_SCM_MULT_TARG ),
#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999,
+UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999,
"Sandisk",
"ImageMate SDDR09",
US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -431,52 +431,52 @@ UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208,
"SCM Microsystems",
"eUSB SmartMedia / CompactFlash Adapter",
US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init,
- 0),
+ 0),
#endif
/* Reported by Markus Demleitner <msdemlei@cl.uni-heidelberg.de> */
-UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0100,
"SCM Microsystems Inc.",
"eUSB MMC Adapter",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN),
+ US_SC_SCSI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN),
/* Reported by Daniel Nouri <dpunktnpunkt@web.de> */
-UNUSUAL_DEV( 0x04e6, 0x0006, 0x0205, 0x0205,
+UNUSUAL_DEV( 0x04e6, 0x0006, 0x0205, 0x0205,
"Shuttle",
"eUSB MMC Adapter",
- US_SC_SCSI, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN),
+ US_SC_SCSI, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN),
-UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200,
+UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200,
"Sony",
"Hifd",
- US_SC_SCSI, US_PR_CB, NULL,
- US_FL_SINGLE_LUN),
+ US_SC_SCSI, US_PR_CB, NULL,
+ US_FL_SINGLE_LUN),
-UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200,
+UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200,
"Shuttle",
"eUSB ATA/ATAPI Adapter",
US_SC_8020, US_PR_CB, NULL, 0),
-UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200,
+UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200,
"Shuttle",
"eUSB CompactFlash Adapter",
US_SC_8020, US_PR_CB, NULL, 0),
-UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100,
"Shuttle",
"eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+ US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ),
-UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100,
"Shuttle",
"eUSCSI Bridge",
- US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
+ US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
+ US_FL_SCM_MULT_TARG ),
-UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200,
+UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200,
"Shuttle",
"CD-RW Device",
US_SC_8020, US_PR_CB, NULL, 0),
@@ -556,9 +556,9 @@ UNUSUAL_DEV( 0x052b, 0x1911, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
-UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
+UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
"Sony",
- "DSC-S30/S70/S75/505V/F505/F707/F717/P8",
+ "DSC-S30/S70/S75/505V/F505/F707/F717/P8",
US_SC_SCSI, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ),
@@ -572,7 +572,7 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0610,
/* Reported by wim@geeks.nl */
-UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100,
"Sony",
"Memorystick NW-MS7",
US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -593,21 +593,21 @@ UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x2000,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN ),
-UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
"Sony",
"Memorystick MSAC-US1",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN ),
/* Submitted by Klaus Mueller <k.mueller@intershop.de> */
-UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310,
+UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310,
"Sony",
"Handycam",
US_SC_SCSI, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN ),
/* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */
-UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500,
+UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500,
"Sony",
"Handycam HC-85",
US_SC_UFI, US_PR_DEVICE, NULL,
@@ -648,26 +648,26 @@ UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999,
/* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */
UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999,
- "Sony",
- "PEG Mass Storage",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_INQUIRY ),
+ "Sony",
+ "PEG Mass Storage",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_INQUIRY ),
/* floppy reports multiple luns */
UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210,
- "SAMSUNG",
- "SFD-321U [FW 0C]",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN ),
+ "SAMSUNG",
+ "SFD-321U [FW 0C]",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
-UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299,
+UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299,
"Y-E Data",
"Flashbuster-U",
US_SC_DEVICE, US_PR_CB, NULL,
US_FL_SINGLE_LUN),
-UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
+UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
"Y-E Data",
"Flashbuster-U",
US_SC_DEVICE, US_PR_DEVICE, NULL,
@@ -677,7 +677,7 @@ UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
* This entry is needed only because the device reports
* bInterfaceClass = 0xff (vendor-specific)
*/
-UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999,
+UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999,
"Y-E Data",
"Silicon Media R/W",
US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
@@ -825,13 +825,13 @@ UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999,
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_FIX_INQUIRY ),
-UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100,
"TEAC",
"Floppy Drive",
- US_SC_UFI, US_PR_CB, NULL, 0 ),
+ US_SC_UFI, US_PR_CB, NULL, 0 ),
#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
"Olympus",
"Camedia MAUSB-2",
US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -867,14 +867,14 @@ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
/* Reported by Miguel A. Fosas <amn3s1a@ono.com> */
UNUSUAL_DEV( 0x0686, 0x4017, 0x0001, 0x0001,
- "Minolta",
- "DIMAGE E223",
- US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
+ "Minolta",
+ "DIMAGE E223",
+ US_SC_SCSI, US_PR_DEVICE, NULL, 0 ),
UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100,
"Hagiwara",
"Flashgate",
- US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+ US_SC_SCSI, US_PR_BULK, NULL, 0 ),
/* Reported by David Hamilton <niftimusmaximus@lycos.com> */
UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001,
@@ -918,7 +918,7 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
US_FL_SINGLE_LUN ),
#ifdef CONFIG_USB_STORAGE_SDDR09
-UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999,
+UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999,
"Sandisk",
"ImageMate SDDR-09",
US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init,
@@ -939,17 +939,17 @@ UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
-UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133,
+UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133,
"Microtech",
"USB-SCSI-DB25",
US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ),
-UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100,
+UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100,
"Microtech",
"USB-SCSI-HD50",
US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
- US_FL_SCM_MULT_TARG ),
+ US_FL_SCM_MULT_TARG ),
#ifdef CONFIG_USB_STORAGE_DPCM
UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100,
@@ -1053,10 +1053,10 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff,
* as "DualSlot CompactFlash(TM) & MStick Drive USB"
*/
UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff,
- "DataFab Systems Inc.",
- "USB CF+MS",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- 0 ),
+ "DataFab Systems Inc.",
+ "USB CF+MS",
+ US_SC_SCSI, US_PR_DATAFAB, NULL,
+ 0 ),
#endif
@@ -1119,10 +1119,10 @@ UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000,
* US_FL_IGNORE_RESIDUE Needed
*/
UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100,
- "AIPTEK",
- "Aiptek USB Keychain MP3 Player",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_RESIDUE),
+ "AIPTEK",
+ "Aiptek USB Keychain MP3 Player",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE),
/* Entry needed for flags. Moreover, all devices with this ID use
* bulk-only transport, but _some_ falsely report Control/Bulk instead.
@@ -1166,26 +1166,26 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
- "Pentax",
- "Optio 2/3/400",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_INQUIRY ),
+ "Pentax",
+ "Optio 2/3/400",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_INQUIRY ),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
- "Pentax",
- "Optio S/S4",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_FIX_INQUIRY ),
+ "Pentax",
+ "Optio S/S4",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_INQUIRY ),
-/* These are virtual windows driver CDs, which the zd1211rw driver automatically
- * converts into a WLAN devices. */
+/* These are virtual windows driver CDs, which the zd1211rw driver
+ * automatically converts into WLAN devices. */
UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101,
- "ZyXEL",
- "G-220F USB-WLAN Install",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_IGNORE_DEVICE ),
+ "ZyXEL",
+ "G-220F USB-WLAN Install",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_DEVICE ),
UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101,
"SiteCom",
@@ -1193,6 +1193,14 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_DEVICE ),
+/* SanDisk that has a second LUN for a driver ISO, reported by
+ * Ben Collins <bcollins@ubuntu.com> */
+UNUSUAL_DEV( 0x0781, 0x5406, 0x0000, 0xffff,
+ "SanDisk",
+ "U3 Cruzer Micro driver ISO",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
"ATI",
@@ -1203,17 +1211,17 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110,
#ifdef CONFIG_USB_STORAGE_DATAFAB
UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
- "Acomdata",
- "CF",
- US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_SINGLE_LUN ),
+ "Acomdata",
+ "CF",
+ US_SC_SCSI, US_PR_DATAFAB, NULL,
+ US_FL_SINGLE_LUN ),
#endif
#ifdef CONFIG_USB_STORAGE_SDDR55
UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff,
- "Acomdata",
- "SM",
- US_SC_SCSI, US_PR_SDDR55, NULL,
- US_FL_SINGLE_LUN ),
+ "Acomdata",
+ "SM",
+ US_SC_SCSI, US_PR_SDDR55, NULL,
+ US_FL_SINGLE_LUN ),
#endif
/* Submitted by: Nick Sillik <n.sillik@temple.edu>
@@ -1271,6 +1279,15 @@ UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
+/* Reported by Edward Chapman (taken from linux-usb mailing list)
+ Netac OnlyDisk Mini U2CV2 512MB USB 2.0 Flash Drive */
+UNUSUAL_DEV( 0x0dd8, 0xd202, 0x0000, 0x9999,
+ "Netac",
+ "USB Flash Disk",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_IGNORE_RESIDUE ),
+
+
/* Patch by Stephan Walter <stephan.walter@epfl.ch>
* I don't know why, but it works... */
UNUSUAL_DEV( 0x0dda, 0x0001, 0x0012, 0x0012,
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 8e898e3d861..bef8bcd9bd9 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -191,16 +191,13 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message)
{
struct us_data *us = usb_get_intfdata(iface);
+ US_DEBUGP("%s\n", __FUNCTION__);
+
/* Wait until no command is running */
mutex_lock(&us->dev_mutex);
- US_DEBUGP("%s\n", __FUNCTION__);
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_SUSPEND);
- iface->dev.power.power_state.event = message.event;
-
- /* When runtime PM is working, we'll set a flag to indicate
- * whether we should autoresume when a SCSI request arrives. */
mutex_unlock(&us->dev_mutex);
return 0;
@@ -210,14 +207,25 @@ static int storage_resume(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
- mutex_lock(&us->dev_mutex);
-
US_DEBUGP("%s\n", __FUNCTION__);
+
if (us->suspend_resume_hook)
(us->suspend_resume_hook)(us, US_RESUME);
- iface->dev.power.power_state.event = PM_EVENT_ON;
- mutex_unlock(&us->dev_mutex);
+ return 0;
+}
+
+static int storage_reset_resume(struct usb_interface *iface)
+{
+ struct us_data *us = usb_get_intfdata(iface);
+
+ US_DEBUGP("%s\n", __FUNCTION__);
+
+ /* Report the reset to the SCSI core */
+ usb_stor_report_bus_reset(us);
+
+ /* FIXME: Notify the subdrivers that they need to reinitialize
+ * the device */
return 0;
}
@@ -228,7 +236,7 @@ static int storage_resume(struct usb_interface *iface)
* a USB port reset, whether from this driver or a different one.
*/
-static void storage_pre_reset(struct usb_interface *iface)
+static int storage_pre_reset(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
@@ -236,22 +244,23 @@ static void storage_pre_reset(struct usb_interface *iface)
/* Make sure no command runs during the reset */
mutex_lock(&us->dev_mutex);
+ return 0;
}
-static void storage_post_reset(struct usb_interface *iface)
+static int storage_post_reset(struct usb_interface *iface)
{
struct us_data *us = usb_get_intfdata(iface);
US_DEBUGP("%s\n", __FUNCTION__);
/* Report the reset to the SCSI core */
- scsi_lock(us_to_host(us));
usb_stor_report_bus_reset(us);
- scsi_unlock(us_to_host(us));
/* FIXME: Notify the subdrivers that they need to reinitialize
* the device */
+
mutex_unlock(&us->dev_mutex);
+ return 0;
}
/*
@@ -300,6 +309,7 @@ static int usb_stor_control_thread(void * __us)
{
struct us_data *us = (struct us_data *)__us;
struct Scsi_Host *host = us_to_host(us);
+ int autopm_rc;
current->flags |= PF_NOFREEZE;
@@ -310,6 +320,9 @@ static int usb_stor_control_thread(void * __us)
US_DEBUGP("*** thread awakened.\n");
+ /* Autoresume the device */
+ autopm_rc = usb_autopm_get_interface(us->pusb_intf);
+
/* lock the device pointers */
mutex_lock(&(us->dev_mutex));
@@ -368,6 +381,12 @@ static int usb_stor_control_thread(void * __us)
us->srb->result = SAM_STAT_GOOD;
}
+ /* Did the autoresume fail? */
+ else if (autopm_rc < 0) {
+ US_DEBUGP("Could not wake device\n");
+ us->srb->result = DID_ERROR << 16;
+ }
+
/* we've got a command, let's do it! */
else {
US_DEBUG(usb_stor_show_command(us->srb));
@@ -410,25 +429,21 @@ SkipForAbort:
/* unlock the device pointers */
mutex_unlock(&us->dev_mutex);
- } /* for (;;) */
- scsi_host_put(host);
+ /* Start an autosuspend */
+ if (autopm_rc == 0)
+ usb_autopm_put_interface(us->pusb_intf);
+ } /* for (;;) */
- /* notify the exit routine that we're actually exiting now
- *
- * complete()/wait_for_completion() is similar to up()/down(),
- * except that complete() is safe in the case where the structure
- * is getting deleted in a parallel mode of execution (i.e. just
- * after the down() -- that's necessary for the thread-shutdown
- * case.
- *
- * complete_and_exit() goes even further than this -- it is safe in
- * the case that the thread of the caller is going away (not just
- * the structure) -- this is necessary for the module-remove case.
- * This is important in preemption kernels, which transfer the flow
- * of execution immediately upon a complete().
- */
- complete_and_exit(&threads_gone, 0);
+ /* Wait until we are told to stop */
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (kthread_should_stop())
+ break;
+ schedule();
+ }
+ __set_current_state(TASK_RUNNING);
+ return 0;
}
/***********************************************************************
@@ -796,19 +811,13 @@ static int usb_stor_acquire_resources(struct us_data *us)
}
/* Start up our control thread */
- th = kthread_create(usb_stor_control_thread, us, "usb-storage");
+ th = kthread_run(usb_stor_control_thread, us, "usb-storage");
if (IS_ERR(th)) {
printk(KERN_WARNING USB_STORAGE
"Unable to start control thread\n");
return PTR_ERR(th);
}
-
- /* Take a reference to the host for the control thread and
- * count it among all the threads we have launched. Then
- * start it up. */
- scsi_host_get(us_to_host(us));
- atomic_inc(&total_threads);
- wake_up_process(th);
+ us->ctl_thread = th;
return 0;
}
@@ -825,6 +834,8 @@ static void usb_stor_release_resources(struct us_data *us)
US_DEBUGP("-- sending exit command to thread\n");
set_bit(US_FLIDX_DISCONNECTING, &us->flags);
up(&us->sema);
+ if (us->ctl_thread)
+ kthread_stop(us->ctl_thread);
/* Call the destructor routine, if it exists */
if (us->extra_destructor) {
@@ -938,6 +949,7 @@ retry:
}
scsi_host_put(us_to_host(us));
+ usb_autopm_put_interface(us->pusb_intf);
complete_and_exit(&threads_gone, 0);
}
@@ -1027,6 +1039,7 @@ static int storage_probe(struct usb_interface *intf,
* start it up. */
scsi_host_get(us_to_host(us));
atomic_inc(&total_threads);
+ usb_autopm_get_interface(intf); /* dropped in the scanning thread */
wake_up_process(th);
return 0;
@@ -1059,10 +1072,12 @@ static struct usb_driver usb_storage_driver = {
#ifdef CONFIG_PM
.suspend = storage_suspend,
.resume = storage_resume,
+ .reset_resume = storage_reset_resume,
#endif
.pre_reset = storage_pre_reset,
.post_reset = storage_post_reset,
.id_table = storage_usb_ids,
+ .supports_autosuspend = 1,
};
static int __init usb_stor_init(void)
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 6dac1ffdde8..6445665b157 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -144,6 +144,7 @@ struct us_data {
unsigned char *sensebuf; /* sense data buffer */
dma_addr_t cr_dma; /* buffer DMA addresses */
dma_addr_t iobuf_dma;
+ struct task_struct *ctl_thread; /* the control thread */
/* mutual exclusion and synchronization structures */
struct semaphore sema; /* to sleep thread on */
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 8432bf171d2..8de11deb5d1 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -34,9 +34,6 @@ static struct usb_device_id skel_table [] = {
};
MODULE_DEVICE_TABLE(usb, skel_table);
-/* to prevent a race between open and disconnect */
-static DEFINE_MUTEX(skel_open_lock);
-
/* Get a minor range for your devices from the usb maintainer */
#define USB_SKEL_MINOR_BASE 192
@@ -54,16 +51,21 @@ struct usb_skel {
struct usb_device *udev; /* the usb device for this device */
struct usb_interface *interface; /* the interface for this device */
struct semaphore limit_sem; /* limiting the number of writes in progress */
+ struct usb_anchor submitted; /* in case we need to retract our submissions */
unsigned char *bulk_in_buffer; /* the buffer to receive data */
size_t bulk_in_size; /* the size of the receive buffer */
__u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */
__u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */
+ int errors; /* the last request tanked */
+ int open_count; /* count the number of openers */
+ spinlock_t err_lock; /* lock for errors */
struct kref kref;
struct mutex io_mutex; /* synchronize I/O with disconnect */
};
#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
static struct usb_driver skel_driver;
+static void skel_draw_down(struct usb_skel *dev);
static void skel_delete(struct kref *kref)
{
@@ -83,10 +85,8 @@ static int skel_open(struct inode *inode, struct file *file)
subminor = iminor(inode);
- mutex_lock(&skel_open_lock);
interface = usb_find_interface(&skel_driver, subminor);
if (!interface) {
- mutex_unlock(&skel_open_lock);
err ("%s - error, can't find device for minor %d",
__FUNCTION__, subminor);
retval = -ENODEV;
@@ -95,22 +95,33 @@ static int skel_open(struct inode *inode, struct file *file)
dev = usb_get_intfdata(interface);
if (!dev) {
- mutex_unlock(&skel_open_lock);
retval = -ENODEV;
goto exit;
}
/* increment our usage count for the device */
kref_get(&dev->kref);
- /* now we can drop the lock */
- mutex_unlock(&skel_open_lock);
- /* prevent the device from being autosuspended */
- retval = usb_autopm_get_interface(interface);
- if (retval) {
+ /* lock the device to allow correctly handling errors
+ * in resumption */
+ mutex_lock(&dev->io_mutex);
+
+ if (!dev->open_count++) {
+ retval = usb_autopm_get_interface(interface);
+ if (retval) {
+ dev->open_count--;
+ mutex_unlock(&dev->io_mutex);
+ kref_put(&dev->kref, skel_delete);
+ goto exit;
+ }
+ } /* else { //uncomment this block if you want exclusive open
+ retval = -EBUSY;
+ dev->open_count--;
+ mutex_unlock(&dev->io_mutex);
kref_put(&dev->kref, skel_delete);
goto exit;
- }
+ } */
+ /* prevent the device from being autosuspended */
/* save our object in the file's private structure */
file->private_data = dev;
@@ -129,7 +140,7 @@ static int skel_release(struct inode *inode, struct file *file)
/* allow the device to be autosuspended */
mutex_lock(&dev->io_mutex);
- if (dev->interface)
+ if (!--dev->open_count && dev->interface)
usb_autopm_put_interface(dev->interface);
mutex_unlock(&dev->io_mutex);
@@ -138,6 +149,30 @@ static int skel_release(struct inode *inode, struct file *file)
return 0;
}
+static int skel_flush(struct file *file, fl_owner_t id)
+{
+ struct usb_skel *dev;
+ int res;
+
+ dev = (struct usb_skel *)file->private_data;
+ if (dev == NULL)
+ return -ENODEV;
+
+ /* wait for io to stop */
+ mutex_lock(&dev->io_mutex);
+ skel_draw_down(dev);
+
+ /* read out errors, leave subsequent opens a clean slate */
+ spin_lock_irq(&dev->err_lock);
+ res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0;
+ dev->errors = 0;
+ spin_unlock_irq(&dev->err_lock);
+
+ mutex_unlock(&dev->io_mutex);
+
+ return res;
+}
+
static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct usb_skel *dev;
@@ -179,12 +214,16 @@ static void skel_write_bulk_callback(struct urb *urb)
dev = (struct usb_skel *)urb->context;
/* sync/async unlink faults aren't errors */
- if (urb->status &&
- !(urb->status == -ENOENT ||
- urb->status == -ECONNRESET ||
- urb->status == -ESHUTDOWN)) {
- err("%s - nonzero write bulk status received: %d",
- __FUNCTION__, urb->status);
+ if (urb->status) {
+ if(!(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ err("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, urb->status);
+
+ spin_lock(&dev->err_lock);
+ dev->errors = urb->status;
+ spin_unlock(&dev->err_lock);
}
/* free up our allocated buffer */
@@ -213,6 +252,17 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
goto exit;
}
+ spin_lock_irq(&dev->err_lock);
+ if ((retval = dev->errors) < 0) {
+ /* any error is reported once */
+ dev->errors = 0;
+ /* to preserve notifications about reset */
+ retval = (retval == -EPIPE) ? retval : -EIO;
+ }
+ spin_unlock_irq(&dev->err_lock);
+ if (retval < 0)
+ goto error;
+
/* create a urb, and a buffer for it, and copy the data to the urb */
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
@@ -244,13 +294,14 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
buf, writesize, skel_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &dev->submitted);
/* send the data out the bulk port */
retval = usb_submit_urb(urb, GFP_KERNEL);
mutex_unlock(&dev->io_mutex);
if (retval) {
err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
- goto error;
+ goto error_unanchor;
}
/* release our reference to this urb, the USB core will eventually free it entirely */
@@ -259,6 +310,8 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
return writesize;
+error_unanchor:
+ usb_unanchor_urb(urb);
error:
if (urb) {
usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
@@ -276,6 +329,7 @@ static const struct file_operations skel_fops = {
.write = skel_write,
.open = skel_open,
.release = skel_release,
+ .flush = skel_flush,
};
/*
@@ -306,6 +360,8 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
kref_init(&dev->kref);
sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
mutex_init(&dev->io_mutex);
+ spin_lock_init(&dev->err_lock);
+ init_usb_anchor(&dev->submitted);
dev->udev = usb_get_dev(interface_to_usbdev(interface));
dev->interface = interface;
@@ -368,22 +424,18 @@ static void skel_disconnect(struct usb_interface *interface)
struct usb_skel *dev;
int minor = interface->minor;
- /* prevent skel_open() from racing skel_disconnect() */
- mutex_lock(&skel_open_lock);
-
dev = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &skel_class);
- mutex_unlock(&skel_open_lock);
/* prevent more I/O from starting */
mutex_lock(&dev->io_mutex);
dev->interface = NULL;
mutex_unlock(&dev->io_mutex);
-
+ usb_kill_anchored_urbs(&dev->submitted);
/* decrement our usage count */
kref_put(&dev->kref, skel_delete);
@@ -391,10 +443,59 @@ static void skel_disconnect(struct usb_interface *interface)
info("USB Skeleton #%d now disconnected", minor);
}
+static void skel_draw_down(struct usb_skel *dev)
+{
+ int time;
+
+ time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+ if (!time)
+ usb_kill_anchored_urbs(&dev->submitted);
+}
+
+static int skel_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ if (!dev)
+ return 0;
+ skel_draw_down(dev);
+ return 0;
+}
+
+static int skel_resume (struct usb_interface *intf)
+{
+ return 0;
+}
+
+static int skel_pre_reset(struct usb_interface *intf)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ mutex_lock(&dev->io_mutex);
+ skel_draw_down(dev);
+
+ return 0;
+}
+
+static int skel_post_reset(struct usb_interface *intf)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ /* we are sure no URBs are active - no locking needed */
+ dev->errors = -EPIPE;
+ mutex_unlock(&dev->io_mutex);
+
+ return 0;
+}
+
static struct usb_driver skel_driver = {
.name = "skeleton",
.probe = skel_probe,
.disconnect = skel_disconnect,
+ .suspend = skel_suspend,
+ .resume = skel_resume,
+ .pre_reset = skel_pre_reset,
+ .post_reset = skel_post_reset,
.id_table = skel_table,
.supports_autosuspend = 1,
};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6e1f1ea21b3..403dac787eb 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -755,7 +755,7 @@ config FB_LEO
config FB_IGA
bool "IGA 168x display support"
- depends on FB && SPARC32
+ depends on (FB = y) && SPARC32
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -765,7 +765,7 @@ config FB_IGA
config FB_XVR500
bool "Sun XVR-500 3DLABS Wildcat support"
- depends on FB && PCI && SPARC64
+ depends on (FB = y) && PCI && SPARC64
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -778,7 +778,7 @@ config FB_XVR500
config FB_XVR2500
bool "Sun XVR-2500 3DLABS Wildcat support"
- depends on FB && PCI && SPARC64
+ depends on (FB = y) && PCI && SPARC64
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c
index ba6fede5c46..8a1b07c7439 100644
--- a/drivers/video/arkfb.c
+++ b/drivers/video/arkfb.c
@@ -1055,9 +1055,10 @@ err_enable_device:
static void __devexit ark_pci_remove(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct arkfb_info *par = info->par;
if (info) {
+ struct arkfb_info *par = info->par;
+
#ifdef CONFIG_MTRR
if (par->mtrr_reg >= 0) {
mtrr_del(par->mtrr_reg, 0, 0);
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 8d3455da663..2fbff631743 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2290,15 +2290,6 @@ static int __devinit aty_init(struct fb_info *info)
init_waitqueue_head(&par->vblank.wait);
spin_lock_init(&par->int_lock);
-#ifdef CONFIG_PPC_PMAC
- /* The Apple iBook1 uses non-standard memory frequencies. We detect it
- * and set the frequency manually. */
- if (machine_is_compatible("PowerBook2,1")) {
- par->pll_limits.mclk = 70;
- par->pll_limits.xclk = 53;
- }
-#endif
-
#ifdef CONFIG_FB_ATY_GX
if (!M64_HAS(INTEGRATED)) {
u32 stat0;
@@ -2383,6 +2374,14 @@ static int __devinit aty_init(struct fb_info *info)
par->pll_limits.xclk = (par->pll_limits.xclk + 1) >> 1;
}
#endif
+#ifdef CONFIG_PPC_PMAC
+ /* The Apple iBook1 uses non-standard memory frequencies. We detect it
+ * and set the frequency manually. */
+ if (machine_is_compatible("PowerBook2,1")) {
+ par->pll_limits.mclk = 70;
+ par->pll_limits.xclk = 53;
+ }
+#endif
/* Allow command line to override clocks. */
if (pll)
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 2ce05019301..2349e71b008 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2102,7 +2102,9 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u
}
-static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid1(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct pci_dev *pdev = to_pci_dev(dev);
@@ -2113,7 +2115,9 @@ static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, si
}
-static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid2(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct pci_dev *pdev = to_pci_dev(dev);
@@ -2126,7 +2130,6 @@ static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, si
static struct bin_attribute edid1_attr = {
.attr = {
.name = "edid1",
- .owner = THIS_MODULE,
.mode = 0444,
},
.size = EDID_LENGTH,
@@ -2136,7 +2139,6 @@ static struct bin_attribute edid1_attr = {
static struct bin_attribute edid2_attr = {
.attr = {
.name = "edid2",
- .owner = THIS_MODULE,
.mode = 0444,
},
.size = EDID_LENGTH,
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index c65e81ff357..7e06223bca9 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -172,7 +172,7 @@ static struct class backlight_class = {
#define DECLARE_ATTR(_name,_mode,_show,_store) \
{ \
- .attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
+ .attr = { .name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 6ef8f0a7a13..648b53c1fde 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -157,7 +157,7 @@ static struct class lcd_class = {
#define DECLARE_ATTR(_name,_mode,_show,_store) \
{ \
- .attr = { .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
+ .attr = { .name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index af313bf1a2d..f48e8c534c8 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -292,7 +292,7 @@ static void __init chips_hw_init(void)
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
}
-static struct fb_fix_screeninfo chipsfb_fix __initdata = {
+static struct fb_fix_screeninfo chipsfb_fix __devinitdata = {
.id = "C&T 65550",
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR,
@@ -309,7 +309,7 @@ static struct fb_fix_screeninfo chipsfb_fix __initdata = {
.smem_len = 0x100000, /* 1MB */
};
-static struct fb_var_screeninfo chipsfb_var __initdata = {
+static struct fb_var_screeninfo chipsfb_var __devinitdata = {
.xres = 800,
.yres = 600,
.xres_virtual = 800,
@@ -330,7 +330,7 @@ static struct fb_var_screeninfo chipsfb_var __initdata = {
.vsync_len = 8,
};
-static void __init init_chips(struct fb_info *p, unsigned long addr)
+static void __devinit init_chips(struct fb_info *p, unsigned long addr)
{
memset(p->screen_base, 0, 0x100000);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 63b85bf81a6..d3b8a6be291 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -6,7 +6,7 @@ menu "Console display driver support"
config VGA_CONSOLE
bool "VGA text console" if EMBEDDED || !X86
- depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH
+ depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH && !BFIN
default y
help
Saying Y here will allow you to use Linux in text mode through a
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index 9b26dda18a3..ac46cc3f6a2 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -47,7 +47,7 @@ targets := promcon_tbl.c
quiet_cmd_conmakehash = CNMKHSH $@
cmd_conmakehash = scripts/conmakehash $< | \
sed -e '/\#include <[^>]*>/p' -e 's/types/init/' \
- -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > $@
+ -e 's/dfont\(_uni.*\]\)/promfont\1 /' > $@
$(obj)/promcon_tbl.c: $(src)/prom.uni
$(call cmd,conmakehash)
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 71f24e00fcd..8e6ef4bc7a5 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -176,7 +176,6 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
#endif
extern void fbcon_set_bitops(struct fbcon_ops *ops);
extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
-extern struct class *fb_class;
#define FBCON_ATTRIBUTE_UNDERLINE 1
#define FBCON_ATTRIBUTE_REVERSE 2
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 717b360d041..870017d4497 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -240,7 +240,7 @@ static void sti_flush(unsigned long from, unsigned long len)
flush_icache_range(from, from+len);
}
-void __init
+void __devinit
sti_rom_copy(unsigned long base, unsigned long count, void *dest)
{
unsigned long dest_len = count;
@@ -269,7 +269,7 @@ sti_rom_copy(unsigned long base, unsigned long count, void *dest)
static char default_sti_path[21] __read_mostly;
#ifndef MODULE
-static int __init sti_setup(char *str)
+static int __devinit sti_setup(char *str)
{
if (str)
strlcpy (default_sti_path, str, sizeof (default_sti_path));
@@ -288,12 +288,12 @@ __setup("sti=", sti_setup);
-static char __initdata *font_name[MAX_STI_ROMS] = { "VGA8x16", };
-static int __initdata font_index[MAX_STI_ROMS],
- font_height[MAX_STI_ROMS],
- font_width[MAX_STI_ROMS];
+static char __devinitdata *font_name[MAX_STI_ROMS] = { "VGA8x16", };
+static int __devinitdata font_index[MAX_STI_ROMS],
+ font_height[MAX_STI_ROMS],
+ font_width[MAX_STI_ROMS];
#ifndef MODULE
-static int __init sti_font_setup(char *str)
+static int __devinit sti_font_setup(char *str)
{
char *x;
int i = 0;
@@ -346,7 +346,7 @@ __setup("sti_font=", sti_font_setup);
-static void __init
+static void __devinit
sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request)
{
struct sti_glob_cfg_ext *cfg;
@@ -386,7 +386,7 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request)
cfg->sti_mem_addr, sti_mem_request));
}
-static void __init
+static void __devinit
sti_dump_outptr(struct sti_struct *sti)
{
DPRINTK((KERN_INFO
@@ -400,7 +400,7 @@ sti_dump_outptr(struct sti_struct *sti)
sti->outptr.attributes));
}
-static int __init
+static int __devinit
sti_init_glob_cfg(struct sti_struct *sti,
unsigned long rom_address, unsigned long hpa)
{
@@ -482,7 +482,7 @@ sti_init_glob_cfg(struct sti_struct *sti,
}
#ifdef CONFIG_FB
-struct sti_cooked_font * __init
+struct sti_cooked_font * __devinit
sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
{
const struct font_desc *fbfont;
@@ -538,14 +538,14 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
return cooked_font;
}
#else
-struct sti_cooked_font * __init
+struct sti_cooked_font * __devinit
sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
{
return NULL;
}
#endif
-struct sti_cooked_font * __init
+struct sti_cooked_font * __devinit
sti_select_font(struct sti_cooked_rom *rom,
int (*search_font_fnc) (struct sti_cooked_rom *,int,int) )
{
@@ -572,7 +572,7 @@ sti_select_font(struct sti_cooked_rom *rom,
}
-static void __init
+static void __devinit
sti_dump_rom(struct sti_rom *rom)
{
printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n",
@@ -590,7 +590,7 @@ sti_dump_rom(struct sti_rom *rom)
}
-static int __init
+static int __devinit
sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
struct sti_rom *raw_rom)
{
@@ -625,7 +625,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
}
-static int __init
+static int __devinit
sti_search_font(struct sti_cooked_rom *rom, int height, int width)
{
struct sti_cooked_font *font;
@@ -642,7 +642,7 @@ sti_search_font(struct sti_cooked_rom *rom, int height, int width)
#define BMODE_RELOCATE(offset) offset = (offset) / 4;
#define BMODE_LAST_ADDR_OFFS 0x50
-static void * __init
+static void * __devinit
sti_bmode_font_raw(struct sti_cooked_font *f)
{
unsigned char *n, *p, *q;
@@ -660,7 +660,7 @@ sti_bmode_font_raw(struct sti_cooked_font *f)
return n + 3;
}
-static void __init
+static void __devinit
sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest)
{
unsigned long dest_len = count;
@@ -675,7 +675,7 @@ sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest)
sti_flush(dest_start, dest_len);
}
-static struct sti_rom * __init
+static struct sti_rom * __devinit
sti_get_bmode_rom (unsigned long address)
{
struct sti_rom *raw;
@@ -711,7 +711,7 @@ sti_get_bmode_rom (unsigned long address)
return raw;
}
-struct sti_rom * __init
+struct sti_rom * __devinit
sti_get_wmode_rom (unsigned long address)
{
struct sti_rom *raw;
@@ -727,7 +727,7 @@ sti_get_wmode_rom (unsigned long address)
return raw;
}
-int __init
+int __devinit
sti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address)
{
struct sti_cooked_rom *cooked;
@@ -783,7 +783,7 @@ out_err:
return 0;
}
-static struct sti_struct * __init
+static struct sti_struct * __devinit
sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd)
{
struct sti_struct *sti;
@@ -898,7 +898,7 @@ out_err:
return NULL;
}
-static void __init sticore_check_for_default_sti(struct sti_struct *sti, char *path)
+static void __devinit sticore_check_for_default_sti(struct sti_struct *sti, char *path)
{
if (strcmp (path, default_sti_path) == 0)
default_sti = sti;
@@ -909,7 +909,7 @@ static void __init sticore_check_for_default_sti(struct sti_struct *sti, char *p
* in the additional address field addr[1] while on
* older Systems the PDC stores it in page0->proc_sti
*/
-static int __init sticore_pa_init(struct parisc_device *dev)
+static int __devinit sticore_pa_init(struct parisc_device *dev)
{
char pa_path[21];
struct sti_struct *sti = NULL;
@@ -1015,7 +1015,7 @@ static struct parisc_driver pa_sti_driver = {
static int sticore_initialized __read_mostly;
-static void __init sti_init_roms(void)
+static void __devinit sti_init_roms(void)
{
if (sticore_initialized)
return;
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 1d4e8354b56..3f6c98fad43 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -656,7 +656,7 @@ static int ffb_setcolreg(unsigned regno,
{
u32 value;
- if (regno >= 256)
+ if (regno >= 16)
return 1;
red >>= 8;
@@ -903,7 +903,7 @@ ffb_init_fix(struct fb_info *info)
struct all_info {
struct fb_info info;
struct ffb_par par;
- u32 pseudo_palette[256];
+ u32 pseudo_palette[16];
};
static int ffb_init_one(struct of_device *op)
diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/kyro/STG4000InitDevice.c
index ab5285a7f1d..1d3f2080aa6 100644
--- a/drivers/video/kyro/STG4000InitDevice.c
+++ b/drivers/video/kyro/STG4000InitDevice.c
@@ -247,7 +247,6 @@ int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev)
u32 ulCoreClock;
u32 tmp;
u32 ulChipSpeed;
- u8 rev;
STG_WRITE_REG(IntMask, 0xFFFF);
@@ -276,9 +275,9 @@ int SetCoreClockPLL(volatile STG4000REG __iomem *pSTGReg, struct pci_dev *pDev)
PMX2_SOFTRESET_ROM_RST);
pci_read_config_word(pDev, PCI_CONFIG_SUBSYS_ID, &sub);
- pci_read_config_byte(pDev, PCI_REVISION_ID, &rev);
- ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub, (u32)rev);
+ ulChipSpeed = InitSDRAMRegisters(pSTGReg, (u32)sub,
+ (u32)pDev->revision);
if (ulChipSpeed == 0)
return -EINVAL;
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index c8559a756b7..886e475f22f 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1994,7 +1994,6 @@ static void matroxfb_unregister_device(struct matrox_fb_info* minfo) {
static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dummy) {
struct board* b;
- u_int8_t rev;
u_int16_t svid;
u_int16_t sid;
struct matrox_fb_info* minfo;
@@ -2005,11 +2004,10 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
#endif
DBG(__FUNCTION__)
- pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
svid = pdev->subsystem_vendor;
sid = pdev->subsystem_device;
for (b = dev_list; b->vendor; b++) {
- if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < rev)) continue;
+ if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < pdev->revision)) continue;
if (b->svid)
if ((b->svid != svid) || (b->sid != sid)) continue;
break;
diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h
index 608e40bb20e..177177609be 100644
--- a/drivers/video/matrox/matroxfb_crtc2.h
+++ b/drivers/video/matrox/matroxfb_crtc2.h
@@ -2,8 +2,6 @@
#define __MATROXFB_CRTC2_H__
#include <linux/ioctl.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
#include "matroxfb_base.h"
struct matroxfb_dh_fb_info {
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index bd30aba242d..731d7a5c5aa 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1286,34 +1286,36 @@ static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if (regno >= fb->cmap.len || regno > 255)
return -EINVAL;
- switch (fb->var.bits_per_pixel) {
- case 8:
+ if (fb->var.bits_per_pixel <= 8) {
outb(regno, 0x3c8);
outb(red >> 10, 0x3c9);
outb(green >> 10, 0x3c9);
outb(blue >> 10, 0x3c9);
- break;
- case 16:
- ((u32 *) fb->pseudo_palette)[regno] =
+ } else if (regno < 16) {
+ switch (fb->var.bits_per_pixel) {
+ case 16:
+ ((u32 *) fb->pseudo_palette)[regno] =
((red & 0xf800)) | ((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
- break;
- case 24:
- ((u32 *) fb->pseudo_palette)[regno] =
+ break;
+ case 24:
+ ((u32 *) fb->pseudo_palette)[regno] =
((red & 0xff00) << 8) | ((green & 0xff00)) |
((blue & 0xff00) >> 8);
- break;
+ break;
#ifdef NO_32BIT_SUPPORT_YET
- case 32:
- ((u32 *) fb->pseudo_palette)[regno] =
+ case 32:
+ ((u32 *) fb->pseudo_palette)[regno] =
((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
- break;
+ break;
#endif
- default:
- return 1;
+ default:
+ return 1;
+ }
}
+
return 0;
}
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 616a0c08e30..b52e883f0a5 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -498,7 +498,7 @@ static int pm3fb_set_par(struct fb_info *info)
else
par->video |= PM3VideoControl_LINE_DOUBLE_OFF;
- if (info->var.activate == FB_ACTIVATE_NOW)
+ if ((info->var.activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
par->video |= PM3VideoControl_ENABLE;
else {
par->video |= PM3VideoControl_DISABLE;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index a30e1e13d8b..93d07ef8527 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -5789,7 +5789,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ivideo->warncount = 0;
ivideo->chip_id = pdev->device;
ivideo->chip_vendor = pdev->vendor;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
+ ivideo->revision_id = pdev->revision;
ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
pci_read_config_word(pdev, PCI_COMMAND, &reg16);
ivideo->sisvga_enabled = reg16 & 0x01;
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 836a612af97..64779e70408 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -132,7 +132,6 @@ static struct fb_info info;
static struct xxx_par __initdata current_par;
int xxxfb_init(void);
-int xxxfb_setup(char*);
/**
* xxxfb_open - Optional function. Called when the framebuffer is
@@ -975,6 +974,21 @@ static struct platform_device xxxfb_device = {
.name = "xxxfb",
};
+#ifndef MODULE
+ /*
+ * Setup
+ */
+
+/*
+ * Only necessary if your driver takes special options,
+ * otherwise we fall back on the generic fb_setup().
+ */
+int __init xxxfb_setup(char *options)
+{
+ /* Parse user speficied options (`video=xxxfb:') */
+}
+#endif /* MODULE */
+
static int __init xxxfb_init(void)
{
int ret;
@@ -1006,21 +1020,6 @@ static void __exit xxxfb_exit(void)
}
#endif /* CONFIG_PCI */
-#ifdef MODULE
- /*
- * Setup
- */
-
-/*
- * Only necessary if your driver takes special options,
- * otherwise we fall back on the generic fb_setup().
- */
-int __init xxxfb_setup(char *options)
-{
- /* Parse user speficied options (`video=xxxfb:') */
-}
-#endif /* MODULE */
-
/* ------------------------------------------------------------------------- */
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index 62fa5500361..5eff28ce4f4 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1348,7 +1348,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
f_ddprintk("found device : %s\n", spec->name);
par->dev = pdev;
- pci_read_config_byte(pdev, PCI_REVISION_ID, &par->revision);
+ par->revision = pdev->revision;
fix->mmio_start = pci_resource_start(pdev,0);
fix->mmio_len = 0x400000;
diff --git a/drivers/video/sunxvr2500.c b/drivers/video/sunxvr2500.c
index 4316c7fe8e2..c3869a96ab5 100644
--- a/drivers/video/sunxvr2500.c
+++ b/drivers/video/sunxvr2500.c
@@ -28,7 +28,7 @@ struct s3d_info {
unsigned int depth;
unsigned int fb_size;
- u32 pseudo_palette[256];
+ u32 pseudo_palette[16];
};
static int __devinit s3d_get_props(struct s3d_info *sp)
@@ -52,15 +52,14 @@ static int s3d_setcolreg(unsigned regno,
{
u32 value;
- if (regno >= 256)
- return 1;
+ if (regno < 16) {
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
- red >>= 8;
- green >>= 8;
- blue >>= 8;
-
- value = (blue << 24) | (green << 16) | (red << 8);
- ((u32 *)info->pseudo_palette)[regno] = value;
+ value = (blue << 24) | (green << 16) | (red << 8);
+ ((u32 *)info->pseudo_palette)[regno] = value;
+ }
return 0;
}
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c
index 08880a62bfa..71bf3f1f00b 100644
--- a/drivers/video/sunxvr500.c
+++ b/drivers/video/sunxvr500.c
@@ -50,7 +50,7 @@ struct e3d_info {
u32 fb8_0_off;
u32 fb8_1_off;
- u32 pseudo_palette[256];
+ u32 pseudo_palette[16];
};
static int __devinit e3d_get_props(struct e3d_info *ep)
@@ -126,7 +126,9 @@ static int e3d_setcolreg(unsigned regno,
blue_8 = blue >> 8;
value = (blue_8 << 24) | (green_8 << 16) | (red_8 << 8);
- ((u32 *)info->pseudo_palette)[regno] = value;
+
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 16)
+ ((u32 *)info->pseudo_palette)[regno] = value;
red_10 = red >> 6;
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index f0fde6ea7c3..5c0dab62809 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1625,8 +1625,7 @@ tgafb_register(struct device *dev)
par->tga_regs_base = mem_base + TGA_REGS_OFFSET;
par->tga_type = tga_type;
if (tga_bus_pci)
- pci_read_config_byte(to_pci_dev(dev), PCI_REVISION_ID,
- &par->tga_chip_rev);
+ par->tga_chip_rev = (to_pci_dev(dev))->revision;
if (tga_bus_tc)
par->tga_chip_rev = TGA_READ_REG(par, TGA_START_REG) & 0xff;
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c
index 5e9755e464a..30c0b948852 100644
--- a/drivers/video/vt8623fb.c
+++ b/drivers/video/vt8623fb.c
@@ -778,9 +778,10 @@ err_enable_device:
static void __devexit vt8623_pci_remove(struct pci_dev *dev)
{
struct fb_info *info = pci_get_drvdata(dev);
- struct vt8623fb_info *par = info->par;
if (info) {
+ struct vt8623fb_info *par = info->par;
+
#ifdef CONFIG_MTRR
if (par->mtrr_reg >= 0) {
mtrr_del(par->mtrr_reg, 0, 0);
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 904e5aeb696..df95d6c2cef 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -35,4 +35,17 @@ config W1_SLAVE_DS2433_CRC
Each block has 30 bytes of data and a two byte CRC16.
Full block writes are only allowed if the CRC is valid.
+config W1_SLAVE_DS2760
+ tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
+ depends on W1
+ help
+ If you enable this you will have the DS2760 battery monitor
+ chip support.
+
+ The battery monitor chip is used in many batteries/devices
+ as the one who is responsible for charging/discharging/monitoring
+ Li+ batteries.
+
+ If you are unsure, say N.
+
endmenu
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index 725dcfdfddb..a8eb7524df1 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o
obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o
obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o
+obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index 8ea17a53eed..cab56005dd4 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -91,8 +91,9 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
}
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
-static ssize_t w1_f23_read_bin(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t w1_f23_read_bin(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
#ifdef CONFIG_W1_SLAVE_DS2433_CRC
@@ -199,8 +200,9 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
return 0;
}
-static ssize_t w1_f23_write_bin(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t w1_f23_write_bin(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
int addr, len, idx;
@@ -252,7 +254,6 @@ static struct bin_attribute w1_f23_bin_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = W1_EEPROM_SIZE,
.read = w1_f23_read_bin,
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
new file mode 100644
index 00000000000..1f2b1a4d5fb
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.c
@@ -0,0 +1,213 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/idr.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_family.h"
+#include "w1_ds2760.h"
+
+static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
+ int io)
+{
+ struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+ if (!dev)
+ return 0;
+
+ mutex_lock(&sl->master->mutex);
+
+ if (addr > DS2760_DATA_SIZE || addr < 0) {
+ count = 0;
+ goto out;
+ }
+ if (addr + count > DS2760_DATA_SIZE)
+ count = DS2760_DATA_SIZE - addr;
+
+ if (!w1_reset_select_slave(sl)) {
+ if (!io) {
+ w1_write_8(sl->master, W1_DS2760_READ_DATA);
+ w1_write_8(sl->master, addr);
+ count = w1_read_block(sl->master, buf, count);
+ } else {
+ w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
+ w1_write_8(sl->master, addr);
+ w1_write_block(sl->master, buf, count);
+ /* XXX w1_write_block returns void, not n_written */
+ }
+ }
+
+out:
+ mutex_unlock(&sl->master->mutex);
+
+ return count;
+}
+
+int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count)
+{
+ return w1_ds2760_io(dev, buf, addr, count, 0);
+}
+
+int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count)
+{
+ return w1_ds2760_io(dev, buf, addr, count, 1);
+}
+
+static ssize_t w1_ds2760_read_bin(struct kobject *kobj, struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ return w1_ds2760_read(dev, buf, off, count);
+}
+
+static struct bin_attribute w1_ds2760_bin_attr = {
+ .attr = {
+ .name = "w1_slave",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = DS2760_DATA_SIZE,
+ .read = w1_ds2760_read_bin,
+};
+
+static DEFINE_IDR(bat_idr);
+static DEFINE_MUTEX(bat_idr_lock);
+
+static int new_bat_id(void)
+{
+ int ret;
+
+ while (1) {
+ int id;
+
+ ret = idr_pre_get(&bat_idr, GFP_KERNEL);
+ if (ret == 0)
+ return -ENOMEM;
+
+ mutex_lock(&bat_idr_lock);
+ ret = idr_get_new(&bat_idr, NULL, &id);
+ mutex_unlock(&bat_idr_lock);
+
+ if (ret == 0) {
+ ret = id & MAX_ID_MASK;
+ break;
+ } else if (ret == -EAGAIN) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void release_bat_id(int id)
+{
+ mutex_lock(&bat_idr_lock);
+ idr_remove(&bat_idr, id);
+ mutex_unlock(&bat_idr_lock);
+
+ return;
+}
+
+static int w1_ds2760_add_slave(struct w1_slave *sl)
+{
+ int ret;
+ int id;
+ struct platform_device *pdev;
+
+ id = new_bat_id();
+ if (id < 0) {
+ ret = id;
+ goto noid;
+ }
+
+ pdev = platform_device_alloc("ds2760-battery", id);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto pdev_alloc_failed;
+ }
+ pdev->dev.parent = &sl->dev;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto pdev_add_failed;
+
+ ret = sysfs_create_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+ if (ret)
+ goto bin_attr_failed;
+
+ dev_set_drvdata(&sl->dev, pdev);
+
+ goto success;
+
+bin_attr_failed:
+pdev_add_failed:
+ platform_device_unregister(pdev);
+pdev_alloc_failed:
+ release_bat_id(id);
+noid:
+success:
+ return ret;
+}
+
+static void w1_ds2760_remove_slave(struct w1_slave *sl)
+{
+ struct platform_device *pdev = dev_get_drvdata(&sl->dev);
+ int id = pdev->id;
+
+ platform_device_unregister(pdev);
+ release_bat_id(id);
+ sysfs_remove_bin_file(&sl->dev.kobj, &w1_ds2760_bin_attr);
+
+ return;
+}
+
+static struct w1_family_ops w1_ds2760_fops = {
+ .add_slave = w1_ds2760_add_slave,
+ .remove_slave = w1_ds2760_remove_slave,
+};
+
+static struct w1_family w1_ds2760_family = {
+ .fid = W1_FAMILY_DS2760,
+ .fops = &w1_ds2760_fops,
+};
+
+static int __init w1_ds2760_init(void)
+{
+ printk(KERN_INFO "1-Wire driver for the DS2760 battery monitor "
+ " chip - (c) 2004-2005, Szabolcs Gyurko\n");
+ idr_init(&bat_idr);
+ return w1_register_family(&w1_ds2760_family);
+}
+
+static void __exit w1_ds2760_exit(void)
+{
+ w1_unregister_family(&w1_ds2760_family);
+ idr_destroy(&bat_idr);
+}
+
+EXPORT_SYMBOL(w1_ds2760_read);
+EXPORT_SYMBOL(w1_ds2760_write);
+
+module_init(w1_ds2760_init);
+module_exit(w1_ds2760_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>");
+MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
diff --git a/drivers/w1/slaves/w1_ds2760.h b/drivers/w1/slaves/w1_ds2760.h
new file mode 100644
index 00000000000..f1302429cb0
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds2760.h
@@ -0,0 +1,50 @@
+/*
+ * 1-Wire implementation for the ds2760 chip
+ *
+ * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ */
+
+#ifndef __w1_ds2760_h__
+#define __w1_ds2760_h__
+
+/* Known commands to the DS2760 chip */
+#define W1_DS2760_SWAP 0xAA
+#define W1_DS2760_READ_DATA 0x69
+#define W1_DS2760_WRITE_DATA 0x6C
+#define W1_DS2760_COPY_DATA 0x48
+#define W1_DS2760_RECALL_DATA 0xB8
+#define W1_DS2760_LOCK 0x6A
+
+/* Number of valid register addresses */
+#define DS2760_DATA_SIZE 0x40
+
+#define DS2760_PROTECTION_REG 0x00
+#define DS2760_STATUS_REG 0x01
+#define DS2760_EEPROM_REG 0x07
+#define DS2760_SPECIAL_FEATURE_REG 0x08
+#define DS2760_VOLTAGE_MSB 0x0c
+#define DS2760_VOLTAGE_LSB 0x0d
+#define DS2760_CURRENT_MSB 0x0e
+#define DS2760_CURRENT_LSB 0x0f
+#define DS2760_CURRENT_ACCUM_MSB 0x10
+#define DS2760_CURRENT_ACCUM_LSB 0x11
+#define DS2760_TEMP_MSB 0x18
+#define DS2760_TEMP_LSB 0x19
+#define DS2760_EEPROM_BLOCK0 0x20
+#define DS2760_ACTIVE_FULL 0x20
+#define DS2760_EEPROM_BLOCK1 0x30
+#define DS2760_RATED_CAPACITY 0x32
+#define DS2760_CURRENT_OFFSET_BIAS 0x33
+#define DS2760_ACTIVE_EMPTY 0x3b
+
+extern int w1_ds2760_read(struct device *dev, char *buf, int addr,
+ size_t count);
+extern int w1_ds2760_write(struct device *dev, char *buf, int addr,
+ size_t count);
+
+#endif /* !__w1_ds2760_h__ */
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 732db478004..4318935678c 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -42,13 +42,13 @@ static u8 bad_roms[][9] = {
{}
};
-static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
+static ssize_t w1_therm_read_bin(struct kobject *, struct bin_attribute *,
+ char *, loff_t, size_t);
static struct bin_attribute w1_therm_bin_attr = {
.attr = {
.name = "w1_slave",
.mode = S_IRUGO,
- .owner = THIS_MODULE,
},
.size = W1_SLAVE_DATA_SIZE,
.read = w1_therm_read_bin,
@@ -159,7 +159,9 @@ static int w1_therm_check_rom(u8 rom[9])
return 0;
}
-static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_therm_read_bin(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
struct w1_master *dev = sl->master;
@@ -191,11 +193,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
w1_write_8(dev, W1_CONVERT_TEMP);
- while (tm) {
- tm = msleep_interruptible(tm);
- if (signal_pending(current))
- flush_signals(current);
- }
+ msleep(tm);
if (!w1_reset_select_slave(sl)) {
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 7d6876dbcc9..f5c5b760ed7 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -105,7 +105,9 @@ static ssize_t w1_slave_read_name(struct device *dev, struct device_attribute *a
return sprintf(buf, "%s\n", sl->name);
}
-static ssize_t w1_slave_read_id(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_slave_read_id(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -128,7 +130,6 @@ static struct bin_attribute w1_slave_attr_bin_id = {
.attr = {
.name = "id",
.mode = S_IRUGO,
- .owner = THIS_MODULE,
},
.size = 8,
.read = w1_slave_read_id,
@@ -136,7 +137,9 @@ static struct bin_attribute w1_slave_attr_bin_id = {
/* Default family */
-static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_default_write(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -153,7 +156,9 @@ out_up:
return count;
}
-static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t w1_default_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -167,7 +172,6 @@ static struct bin_attribute w1_default_attr = {
.attr = {
.name = "rw",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE,
},
.size = PAGE_SIZE,
.read = w1_default_read,
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 1e2ac40c2c1..ef1e1dafa19 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -33,6 +33,7 @@
#define W1_THERM_DS1822 0x22
#define W1_EEPROM_DS2433 0x23
#define W1_THERM_DS18B20 0x28
+#define W1_FAMILY_DS2760 0x30
#define MAXNAMELEN 32
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index c3ba0ec334c..9130f1c12c2 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -49,8 +49,9 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *
static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL);
-static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off,
- size_t count)
+static ssize_t zorro_read_config(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
kobj));
@@ -78,7 +79,6 @@ static struct bin_attribute zorro_config_attr = {
.attr = {
.name = "config",
.mode = S_IRUGO | S_IWUSR,
- .owner = THIS_MODULE
},
.size = sizeof(struct ConfigDev),
.read = zorro_read_config,
diff --git a/fs/9p/9p.h b/fs/9p/9p.h
deleted file mode 100644
index 94e2f92ab2e..00000000000
--- a/fs/9p/9p.h
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * linux/fs/9p/9p.h
- *
- * 9P protocol definitions.
- *
- * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- * 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:
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02111-1301 USA
- *
- */
-
-/* Message Types */
-enum {
- TVERSION = 100,
- RVERSION,
- TAUTH = 102,
- RAUTH,
- TATTACH = 104,
- RATTACH,
- TERROR = 106,
- RERROR,
- TFLUSH = 108,
- RFLUSH,
- TWALK = 110,
- RWALK,
- TOPEN = 112,
- ROPEN,
- TCREATE = 114,
- RCREATE,
- TREAD = 116,
- RREAD,
- TWRITE = 118,
- RWRITE,
- TCLUNK = 120,
- RCLUNK,
- TREMOVE = 122,
- RREMOVE,
- TSTAT = 124,
- RSTAT,
- TWSTAT = 126,
- RWSTAT,
-};
-
-/* modes */
-enum {
- V9FS_OREAD = 0x00,
- V9FS_OWRITE = 0x01,
- V9FS_ORDWR = 0x02,
- V9FS_OEXEC = 0x03,
- V9FS_OEXCL = 0x04,
- V9FS_OTRUNC = 0x10,
- V9FS_OREXEC = 0x20,
- V9FS_ORCLOSE = 0x40,
- V9FS_OAPPEND = 0x80,
-};
-
-/* permissions */
-enum {
- V9FS_DMDIR = 0x80000000,
- V9FS_DMAPPEND = 0x40000000,
- V9FS_DMEXCL = 0x20000000,
- V9FS_DMMOUNT = 0x10000000,
- V9FS_DMAUTH = 0x08000000,
- V9FS_DMTMP = 0x04000000,
- V9FS_DMSYMLINK = 0x02000000,
- V9FS_DMLINK = 0x01000000,
- /* 9P2000.u extensions */
- V9FS_DMDEVICE = 0x00800000,
- V9FS_DMNAMEDPIPE = 0x00200000,
- V9FS_DMSOCKET = 0x00100000,
- V9FS_DMSETUID = 0x00080000,
- V9FS_DMSETGID = 0x00040000,
-};
-
-/* qid.types */
-enum {
- V9FS_QTDIR = 0x80,
- V9FS_QTAPPEND = 0x40,
- V9FS_QTEXCL = 0x20,
- V9FS_QTMOUNT = 0x10,
- V9FS_QTAUTH = 0x08,
- V9FS_QTTMP = 0x04,
- V9FS_QTSYMLINK = 0x02,
- V9FS_QTLINK = 0x01,
- V9FS_QTFILE = 0x00,
-};
-
-#define V9FS_NOTAG (u16)(~0)
-#define V9FS_NOFID (u32)(~0)
-#define V9FS_MAXWELEM 16
-
-/* ample room for Twrite/Rread header (iounit) */
-#define V9FS_IOHDRSZ 24
-
-struct v9fs_str {
- u16 len;
- char *str;
-};
-
-/* qids are the unique ID for a file (like an inode */
-struct v9fs_qid {
- u8 type;
- u32 version;
- u64 path;
-};
-
-/* Plan 9 file metadata (stat) structure */
-struct v9fs_stat {
- u16 size;
- u16 type;
- u32 dev;
- struct v9fs_qid qid;
- u32 mode;
- u32 atime;
- u32 mtime;
- u64 length;
- struct v9fs_str name;
- struct v9fs_str uid;
- struct v9fs_str gid;
- struct v9fs_str muid;
- struct v9fs_str extension; /* 9p2000.u extensions */
- u32 n_uid; /* 9p2000.u extensions */
- u32 n_gid; /* 9p2000.u extensions */
- u32 n_muid; /* 9p2000.u extensions */
-};
-
-/* file metadata (stat) structure used to create Twstat message
- The is similar to v9fs_stat, but the strings don't point to
- the same memory block and should be freed separately
-*/
-struct v9fs_wstat {
- u16 size;
- u16 type;
- u32 dev;
- struct v9fs_qid qid;
- u32 mode;
- u32 atime;
- u32 mtime;
- u64 length;
- char *name;
- char *uid;
- char *gid;
- char *muid;
- char *extension; /* 9p2000.u extensions */
- u32 n_uid; /* 9p2000.u extensions */
- u32 n_gid; /* 9p2000.u extensions */
- u32 n_muid; /* 9p2000.u extensions */
-};
-
-/* Structures for Protocol Operations */
-
-struct Tversion {
- u32 msize;
- struct v9fs_str version;
-};
-
-struct Rversion {
- u32 msize;
- struct v9fs_str version;
-};
-
-struct Tauth {
- u32 afid;
- struct v9fs_str uname;
- struct v9fs_str aname;
-};
-
-struct Rauth {
- struct v9fs_qid qid;
-};
-
-struct Rerror {
- struct v9fs_str error;
- u32 errno; /* 9p2000.u extension */
-};
-
-struct Tflush {
- u16 oldtag;
-};
-
-struct Rflush {
-};
-
-struct Tattach {
- u32 fid;
- u32 afid;
- struct v9fs_str uname;
- struct v9fs_str aname;
-};
-
-struct Rattach {
- struct v9fs_qid qid;
-};
-
-struct Twalk {
- u32 fid;
- u32 newfid;
- u16 nwname;
- struct v9fs_str wnames[16];
-};
-
-struct Rwalk {
- u16 nwqid;
- struct v9fs_qid wqids[16];
-};
-
-struct Topen {
- u32 fid;
- u8 mode;
-};
-
-struct Ropen {
- struct v9fs_qid qid;
- u32 iounit;
-};
-
-struct Tcreate {
- u32 fid;
- struct v9fs_str name;
- u32 perm;
- u8 mode;
- struct v9fs_str extension;
-};
-
-struct Rcreate {
- struct v9fs_qid qid;
- u32 iounit;
-};
-
-struct Tread {
- u32 fid;
- u64 offset;
- u32 count;
-};
-
-struct Rread {
- u32 count;
- u8 *data;
-};
-
-struct Twrite {
- u32 fid;
- u64 offset;
- u32 count;
- u8 *data;
-};
-
-struct Rwrite {
- u32 count;
-};
-
-struct Tclunk {
- u32 fid;
-};
-
-struct Rclunk {
-};
-
-struct Tremove {
- u32 fid;
-};
-
-struct Rremove {
-};
-
-struct Tstat {
- u32 fid;
-};
-
-struct Rstat {
- struct v9fs_stat stat;
-};
-
-struct Twstat {
- u32 fid;
- struct v9fs_stat stat;
-};
-
-struct Rwstat {
-};
-
-/*
- * fcall is the primary packet structure
- *
- */
-
-struct v9fs_fcall {
- u32 size;
- u8 id;
- u16 tag;
- void *sdata;
-
- union {
- struct Tversion tversion;
- struct Rversion rversion;
- struct Tauth tauth;
- struct Rauth rauth;
- struct Rerror rerror;
- struct Tflush tflush;
- struct Rflush rflush;
- struct Tattach tattach;
- struct Rattach rattach;
- struct Twalk twalk;
- struct Rwalk rwalk;
- struct Topen topen;
- struct Ropen ropen;
- struct Tcreate tcreate;
- struct Rcreate rcreate;
- struct Tread tread;
- struct Rread rread;
- struct Twrite twrite;
- struct Rwrite rwrite;
- struct Tclunk tclunk;
- struct Rclunk rclunk;
- struct Tremove tremove;
- struct Rremove rremove;
- struct Tstat tstat;
- struct Rstat rstat;
- struct Twstat twstat;
- struct Rwstat rwstat;
- } params;
-};
-
-#define PRINT_FCALL_ERROR(s, fcall) dprintk(DEBUG_ERROR, "%s: %.*s\n", s, \
- fcall?fcall->params.rerror.error.len:0, \
- fcall?fcall->params.rerror.error.str:"");
-
-int v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
- char *version, struct v9fs_fcall **rcall);
-
-int v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
- u32 fid, u32 afid, struct v9fs_fcall **rcall);
-
-int v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid);
-
-int v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid,
- struct v9fs_fcall **rcall);
-
-int v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
- struct v9fs_wstat *wstat, struct v9fs_fcall **rcall);
-
-int v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
- char *name, struct v9fs_fcall **rcall);
-
-int v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
- struct v9fs_fcall **rcall);
-
-int v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
- struct v9fs_fcall **rcall);
-
-int v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name,
- u32 perm, u8 mode, char *extension, struct v9fs_fcall **rcall);
-
-int v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid,
- u64 offset, u32 count, struct v9fs_fcall **rcall);
-
-int v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
- u32 count, const char __user * data,
- struct v9fs_fcall **rcall);
-int v9fs_printfcall(char *, int, struct v9fs_fcall *, int);
diff --git a/fs/9p/Makefile b/fs/9p/Makefile
index 87897f84dfb..bc7f0d1551e 100644
--- a/fs/9p/Makefile
+++ b/fs/9p/Makefile
@@ -1,18 +1,12 @@
obj-$(CONFIG_9P_FS) := 9p.o
9p-objs := \
- trans_fd.o \
- mux.o \
- fcall.o \
- conv.o \
vfs_super.o \
vfs_inode.o \
vfs_addr.o \
vfs_file.o \
vfs_dir.o \
vfs_dentry.o \
- error.o \
v9fs.o \
fid.o \
- fcprint.o
diff --git a/fs/9p/conv.h b/fs/9p/conv.h
deleted file mode 100644
index dd5b6b1b610..00000000000
--- a/fs/9p/conv.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * linux/fs/9p/conv.h
- *
- * 9P protocol conversion definitions.
- *
- * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- * 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:
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02111-1301 USA
- *
- */
-
-int v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
- int extended);
-int v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
- int extended);
-
-void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag);
-
-struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version);
-struct v9fs_fcall *v9fs_create_tattach(u32 fid, u32 afid, char *uname,
- char *aname);
-struct v9fs_fcall *v9fs_create_tflush(u16 oldtag);
-struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
- char **wnames);
-struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode);
-struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
- char *extension, int extended);
-struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count);
-struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
- const char __user *data);
-struct v9fs_fcall *v9fs_create_tclunk(u32 fid);
-struct v9fs_fcall *v9fs_create_tremove(u32 fid);
-struct v9fs_fcall *v9fs_create_tstat(u32 fid);
-struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
- int extended);
diff --git a/fs/9p/debug.h b/fs/9p/debug.h
deleted file mode 100644
index 4228c0bb3c3..00000000000
--- a/fs/9p/debug.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * linux/fs/9p/debug.h - V9FS Debug Definitions
- *
- * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- * 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:
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02111-1301 USA
- *
- */
-
-#define DEBUG_ERROR (1<<0)
-#define DEBUG_CURRENT (1<<1)
-#define DEBUG_9P (1<<2)
-#define DEBUG_VFS (1<<3)
-#define DEBUG_CONV (1<<4)
-#define DEBUG_MUX (1<<5)
-#define DEBUG_TRANS (1<<6)
-#define DEBUG_SLABS (1<<7)
-#define DEBUG_FCALL (1<<8)
-
-#define DEBUG_DUMP_PKT 0
-
-extern int v9fs_debug_level;
-
-#define dprintk(level, format, arg...) \
-do { \
- if((v9fs_debug_level & level)==level) \
- printk(KERN_NOTICE "-- %s (%d): " \
- format , __FUNCTION__, current->pid , ## arg); \
-} while(0)
-
-#define eprintk(level, format, arg...) \
-do { \
- printk(level "v9fs: %s (%d): " \
- format , __FUNCTION__, current->pid , ## arg); \
-} while(0)
-
-#if DEBUG_DUMP_PKT
-static inline void dump_data(const unsigned char *data, unsigned int datalen)
-{
- int i, n;
- char buf[5*8];
-
- n = 0;
- i = 0;
- while (i < datalen) {
- n += snprintf(buf+n, sizeof(buf)-n, "%02x", data[i++]);
- if (i%4 == 0)
- n += snprintf(buf+n, sizeof(buf)-n, " ");
-
- if (i%16 == 0) {
- dprintk(DEBUG_ERROR, "%s\n", buf);
- n = 0;
- }
- }
-
- dprintk(DEBUG_ERROR, "%s\n", buf);
-}
-#else /* DEBUG_DUMP_PKT */
-static inline void dump_data(const unsigned char *data, unsigned int datalen)
-{
-
-}
-#endif /* DEBUG_DUMP_PKT */
diff --git a/fs/9p/error.c b/fs/9p/error.c
deleted file mode 100644
index 0d7fa4e0881..00000000000
--- a/fs/9p/error.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * linux/fs/9p/error.c
- *
- * Error string handling
- *
- * Plan 9 uses error strings, Unix uses error numbers. These functions
- * try to help manage that and provide for dynamically adding error
- * mappings.
- *
- * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- * 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:
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02111-1301 USA
- *
- */
-
-#include <linux/module.h>
-
-#include <linux/list.h>
-#include <linux/jhash.h>
-
-#include "debug.h"
-#include "error.h"
-
-/**
- * v9fs_error_init - preload
- * @errstr: error string
- *
- */
-
-int v9fs_error_init(void)
-{
- struct errormap *c;
- int bucket;
-
- /* initialize hash table */
- for (bucket = 0; bucket < ERRHASHSZ; bucket++)
- INIT_HLIST_HEAD(&hash_errmap[bucket]);
-
- /* load initial error map into hash table */
- for (c = errmap; c->name != NULL; c++) {
- c->namelen = strlen(c->name);
- bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
- INIT_HLIST_NODE(&c->list);
- hlist_add_head(&c->list, &hash_errmap[bucket]);
- }
-
- return 1;
-}
-
-/**
- * errstr2errno - convert error string to error number
- * @errstr: error string
- *
- */
-
-int v9fs_errstr2errno(char *errstr, int len)
-{
- int errno = 0;
- struct hlist_node *p = NULL;
- struct errormap *c = NULL;
- int bucket = jhash(errstr, len, 0) % ERRHASHSZ;
-
- hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
- if (c->namelen==len && !memcmp(c->name, errstr, len)) {
- errno = c->val;
- break;
- }
- }
-
- if (errno == 0) {
- /* TODO: if error isn't found, add it dynamically */
- errstr[len] = 0;
- printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
- errstr);
- errno = 1;
- }
-
- return -errno;
-}
diff --git a/fs/9p/fcall.c b/fs/9p/fcall.c
deleted file mode 100644
index dc336a67592..00000000000
--- a/fs/9p/fcall.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * linux/fs/9p/fcall.c
- *
- * This file contains functions to perform synchronous 9P calls
- *
- * Copyright (C) 2004 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
- *
- * 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:
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02111-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/idr.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "9p.h"
-#include "conv.h"
-#include "mux.h"
-
-/**
- * v9fs_t_version - negotiate protocol parameters with sever
- * @v9ses: 9P2000 session information
- * @msize: requested max size packet
- * @version: requested version.extension string
- * @fcall: pointer to response fcall pointer
- *
- */
-
-int
-v9fs_t_version(struct v9fs_session_info *v9ses, u32 msize,
- char *version, struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc;
-
- dprintk(DEBUG_9P, "msize: %d version: %s\n", msize, version);
- tc = v9fs_create_tversion(msize, version);
-
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-/**
- * v9fs_t_attach - mount the server
- * @v9ses: 9P2000 session information
- * @uname: user name doing the attach
- * @aname: remote name being attached to
- * @fid: mount fid to attatch to root node
- * @afid: authentication fid (in this case result key)
- * @fcall: pointer to response fcall pointer
- *
- */
-
-int
-v9fs_t_attach(struct v9fs_session_info *v9ses, char *uname, char *aname,
- u32 fid, u32 afid, struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall* tc;
-
- dprintk(DEBUG_9P, "uname '%s' aname '%s' fid %d afid %d\n", uname,
- aname, fid, afid);
-
- tc = v9fs_create_tattach(fid, afid, uname, aname);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-static void v9fs_t_clunk_cb(void *a, struct v9fs_fcall *tc,
- struct v9fs_fcall *rc, int err)
-{
- int fid, id;
- struct v9fs_session_info *v9ses;
-
- id = 0;
- fid = tc->params.tclunk.fid;
- if (rc)
- id = rc->id;
-
- kfree(tc);
- kfree(rc);
- if (id == RCLUNK) {
- v9ses = a;
- v9fs_put_idpool(fid, &v9ses->fidpool);
- }
-}
-
-/**
- * v9fs_t_clunk - release a fid (finish a transaction)
- * @v9ses: 9P2000 session information
- * @fid: fid to release
- * @fcall: pointer to response fcall pointer
- *
- */
-
-int
-v9fs_t_clunk(struct v9fs_session_info *v9ses, u32 fid)
-{
- int ret;
- struct v9fs_fcall *tc, *rc;
-
- dprintk(DEBUG_9P, "fid %d\n", fid);
-
- rc = NULL;
- tc = v9fs_create_tclunk(fid);
- if (!IS_ERR(tc))
- ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
- else
- ret = PTR_ERR(tc);
-
- if (ret)
- dprintk(DEBUG_ERROR, "failed fid %d err %d\n", fid, ret);
-
- v9fs_t_clunk_cb(v9ses, tc, rc, ret);
- return ret;
-}
-
-#if 0
-/**
- * v9fs_v9fs_t_flush - flush a pending transaction
- * @v9ses: 9P2000 session information
- * @tag: tag to release
- *
- */
-int v9fs_t_flush(struct v9fs_session_info *v9ses, u16 oldtag)
-{
- int ret;
- struct v9fs_fcall *tc;
-
- dprintk(DEBUG_9P, "oldtag %d\n", oldtag);
-
- tc = v9fs_create_tflush(oldtag);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, NULL);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-#endif
-
-/**
- * v9fs_t_stat - read a file's meta-data
- * @v9ses: 9P2000 session information
- * @fid: fid pointing to file or directory to get info about
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_stat(struct v9fs_session_info *v9ses, u32 fid, struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc;
-
- dprintk(DEBUG_9P, "fid %d\n", fid);
-
- ret = -ENOMEM;
- tc = v9fs_create_tstat(fid);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-/**
- * v9fs_t_wstat - write a file's meta-data
- * @v9ses: 9P2000 session information
- * @fid: fid pointing to file or directory to write info about
- * @stat: metadata
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_wstat(struct v9fs_session_info *v9ses, u32 fid,
- struct v9fs_wstat *wstat, struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc;
-
- dprintk(DEBUG_9P, "fid %d\n", fid);
-
- tc = v9fs_create_twstat(fid, wstat, v9ses->extended);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-/**
- * v9fs_t_walk - walk a fid to a new file or directory
- * @v9ses: 9P2000 session information
- * @fid: fid to walk
- * @newfid: new fid (for clone operations)
- * @name: path to walk fid to
- * @fcall: pointer to response fcall
- *
- */
-
-/* TODO: support multiple walk */
-
-int
-v9fs_t_walk(struct v9fs_session_info *v9ses, u32 fid, u32 newfid,
- char *name, struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc;
- int nwname;
-
- dprintk(DEBUG_9P, "fid %d newfid %d wname '%s'\n", fid, newfid, name);
-
- if (name)
- nwname = 1;
- else
- nwname = 0;
-
- tc = v9fs_create_twalk(fid, newfid, nwname, &name);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-/**
- * v9fs_t_open - open a file
- *
- * @v9ses - 9P2000 session information
- * @fid - fid to open
- * @mode - mode to open file (R, RW, etc)
- * @fcall - pointer to response fcall
- *
- */
-
-int
-v9fs_t_open(struct v9fs_session_info *v9ses, u32 fid, u8 mode,
- struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc;
-
- dprintk(DEBUG_9P, "fid %d mode %d\n", fid, mode);
-
- tc = v9fs_create_topen(fid, mode);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-/**
- * v9fs_t_remove - remove a file or directory
- * @v9ses: 9P2000 session information
- * @fid: fid to remove
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_remove(struct v9fs_session_info *v9ses, u32 fid,
- struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc;
-
- dprintk(DEBUG_9P, "fid %d\n", fid);
-
- tc = v9fs_create_tremove(fid);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-/**
- * v9fs_t_create - create a file or directory
- * @v9ses: 9P2000 session information
- * @fid: fid to create
- * @name: name of the file or directory to create
- * @perm: permissions to create with
- * @mode: mode to open file (R, RW, etc)
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_create(struct v9fs_session_info *v9ses, u32 fid, char *name, u32 perm,
- u8 mode, char *extension, struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc;
-
- dprintk(DEBUG_9P, "fid %d name '%s' perm %x mode %d\n",
- fid, name, perm, mode);
-
- tc = v9fs_create_tcreate(fid, name, perm, mode, extension,
- v9ses->extended);
-
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, rcp);
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-/**
- * v9fs_t_read - read data
- * @v9ses: 9P2000 session information
- * @fid: fid to read from
- * @offset: offset to start read at
- * @count: how many bytes to read
- * @fcall: pointer to response fcall (with data)
- *
- */
-
-int
-v9fs_t_read(struct v9fs_session_info *v9ses, u32 fid, u64 offset,
- u32 count, struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc, *rc;
-
- dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
- (long long unsigned) offset, count);
-
- tc = v9fs_create_tread(fid, offset, count);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
- if (!ret)
- ret = rc->params.rread.count;
- if (rcp)
- *rcp = rc;
- else
- kfree(rc);
-
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
-/**
- * v9fs_t_write - write data
- * @v9ses: 9P2000 session information
- * @fid: fid to write to
- * @offset: offset to start write at
- * @count: how many bytes to write
- * @fcall: pointer to response fcall
- *
- */
-
-int
-v9fs_t_write(struct v9fs_session_info *v9ses, u32 fid, u64 offset, u32 count,
- const char __user *data, struct v9fs_fcall **rcp)
-{
- int ret;
- struct v9fs_fcall *tc, *rc;
-
- dprintk(DEBUG_9P, "fid %d offset 0x%llux count 0x%x\n", fid,
- (long long unsigned) offset, count);
-
- tc = v9fs_create_twrite(fid, offset, count, data);
- if (!IS_ERR(tc)) {
- ret = v9fs_mux_rpc(v9ses->mux, tc, &rc);
-
- if (!ret)
- ret = rc->params.rwrite.count;
- if (rcp)
- *rcp = rc;
- else
- kfree(rc);
-
- kfree(tc);
- } else
- ret = PTR_ERR(tc);
-
- return ret;
-}
-
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 90419715c7e..08fa320b7e6 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -26,10 +26,10 @@
#include <linux/sched.h>
#include <linux/idr.h>
#include <asm/semaphore.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
-#include "debug.h"
#include "v9fs.h"
-#include "9p.h"
#include "v9fs_vfs.h"
#include "fid.h"
@@ -40,67 +40,29 @@
*
*/
-int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
+int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
{
- struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
- dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid,
- dentry->d_iname, dentry);
- if (dentry->d_fsdata == NULL) {
- dentry->d_fsdata =
- kmalloc(sizeof(struct list_head), GFP_KERNEL);
- if (dentry->d_fsdata == NULL) {
- dprintk(DEBUG_ERROR, "Out of memory\n");
- return -ENOMEM;
- }
- fid_list = (struct list_head *)dentry->d_fsdata;
- INIT_LIST_HEAD(fid_list); /* Initialize list head */
- }
+ struct v9fs_dentry *dent;
- fid->uid = current->uid;
- list_add(&fid->list, fid_list);
- return 0;
-}
+ P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n",
+ fid->fid, dentry->d_iname);
-/**
- * v9fs_fid_create - allocate a FID structure
- * @dentry - dentry to link newly created fid to
- *
- */
-
-struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid)
-{
- struct v9fs_fid *new;
+ dent = dentry->d_fsdata;
+ if (!dent) {
+ dent = kmalloc(sizeof(struct v9fs_dentry), GFP_KERNEL);
+ if (!dent)
+ return -ENOMEM;
- dprintk(DEBUG_9P, "fid create fid %d\n", fid);
- new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
- if (new == NULL) {
- dprintk(DEBUG_ERROR, "Out of Memory\n");
- return ERR_PTR(-ENOMEM);
+ spin_lock_init(&dent->lock);
+ INIT_LIST_HEAD(&dent->fidlist);
+ dentry->d_fsdata = dent;
}
- new->fid = fid;
- new->v9ses = v9ses;
- new->fidopen = 0;
- new->fidclunked = 0;
- new->iounit = 0;
- new->rdir_pos = 0;
- new->rdir_fcall = NULL;
- init_MUTEX(&new->lock);
- INIT_LIST_HEAD(&new->list);
-
- return new;
-}
-
-/**
- * v9fs_fid_destroy - deallocate a FID structure
- * @fid: fid to destroy
- *
- */
+ spin_lock(&dent->lock);
+ list_add(&fid->dlist, &dent->fidlist);
+ spin_unlock(&dent->lock);
-void v9fs_fid_destroy(struct v9fs_fid *fid)
-{
- list_del(&fid->list);
- kfree(fid);
+ return 0;
}
/**
@@ -114,30 +76,42 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
*
*/
-struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
+struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
{
- struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
- struct v9fs_fid *return_fid = NULL;
-
- dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry);
-
- if (fid_list)
- return_fid = list_entry(fid_list->next, struct v9fs_fid, list);
+ struct v9fs_dentry *dent;
+ struct p9_fid *fid;
+
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ dent = dentry->d_fsdata;
+ if (dent)
+ fid = list_entry(dent->fidlist.next, struct p9_fid, dlist);
+ else
+ fid = ERR_PTR(-EBADF);
+
+ P9_DPRINTK(P9_DEBUG_VFS, " fid: %p\n", fid);
+ return fid;
+}
- if (!return_fid) {
- dprintk(DEBUG_ERROR, "Couldn't find a fid in dentry\n");
- return_fid = ERR_PTR(-EBADF);
+struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry)
+{
+ struct p9_fid *fid;
+ struct v9fs_dentry *dent;
+
+ dent = dentry->d_fsdata;
+ fid = v9fs_fid_lookup(dentry);
+ if (!IS_ERR(fid)) {
+ spin_lock(&dent->lock);
+ list_del(&fid->dlist);
+ spin_unlock(&dent->lock);
}
- if(down_interruptible(&return_fid->lock))
- return ERR_PTR(-EINTR);
-
- return return_fid;
+ return fid;
}
+
/**
* v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
- * release it
+ * release it
* @dentry: dentry to look for fid in
*
* find a fid in the dentry and then clone to a new private fid
@@ -146,49 +120,15 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
*
*/
-struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry)
+struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
{
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
- struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF);
- struct v9fs_fcall *fcall = NULL;
- int fid, err;
-
- base_fid = v9fs_fid_lookup(dentry);
-
- if(IS_ERR(base_fid))
- return base_fid;
-
- if(base_fid) { /* clone fid */
- fid = v9fs_get_idpool(&v9ses->fidpool);
- if (fid < 0) {
- eprintk(KERN_WARNING, "newfid fails!\n");
- new_fid = ERR_PTR(-ENOSPC);
- goto Release_Fid;
- }
-
- err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall);
- if (err < 0) {
- dprintk(DEBUG_ERROR, "clone walk didn't work\n");
- v9fs_put_idpool(fid, &v9ses->fidpool);
- new_fid = ERR_PTR(err);
- goto Free_Fcall;
- }
- new_fid = v9fs_fid_create(v9ses, fid);
- if (new_fid == NULL) {
- dprintk(DEBUG_ERROR, "out of memory\n");
- new_fid = ERR_PTR(-ENOMEM);
- }
-Free_Fcall:
- kfree(fcall);
- }
+ struct p9_fid *ofid, *fid;
-Release_Fid:
- up(&base_fid->lock);
- return new_fid;
-}
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ ofid = v9fs_fid_lookup(dentry);
+ if (IS_ERR(ofid))
+ return ofid;
-void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid)
-{
- v9fs_t_clunk(v9ses, fid->fid);
- v9fs_fid_destroy(fid);
+ fid = p9_client_walk(ofid, 0, NULL, 1);
+ return fid;
}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 48fc170c26c..47a0ba74287 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -22,41 +22,12 @@
#include <linux/list.h>
-#define FID_OP 0
-#define FID_WALK 1
-#define FID_CREATE 2
-
-struct v9fs_fid {
- struct list_head list; /* list of fids associated with a dentry */
- struct list_head active; /* XXX - debug */
-
- struct semaphore lock;
-
- u32 fid;
- unsigned char fidopen; /* set when fid is opened */
- unsigned char fidclunked; /* set when fid has already been clunked */
-
- struct v9fs_qid qid;
- u32 iounit;
-
- /* readdir stuff */
- int rdir_fpos;
- loff_t rdir_pos;
- struct v9fs_fcall *rdir_fcall;
-
- /* management stuff */
- uid_t uid; /* user associated with this fid */
-
- /* private data */
- struct file *filp; /* backpointer to File struct for open files */
- struct v9fs_session_info *v9ses; /* session info for this FID */
+struct v9fs_dentry {
+ spinlock_t lock; /* protect fidlist */
+ struct list_head fidlist;
};
-struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry);
-struct v9fs_fid *v9fs_fid_get_created(struct dentry *);
-void v9fs_fid_destroy(struct v9fs_fid *fid);
-struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *, int fid);
-int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry);
-struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry);
-void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid);
-
+struct p9_fid *v9fs_fid_lookup(struct dentry *dentry);
+struct p9_fid *v9fs_fid_lookup_remove(struct dentry *dentry);
+struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
+int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
diff --git a/fs/9p/trans_fd.c b/fs/9p/trans_fd.c
deleted file mode 100644
index 34d43355beb..00000000000
--- a/fs/9p/trans_fd.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * linux/fs/9p/trans_fd.c
- *
- * Fd transport layer. Includes deprecated socket layer.
- *
- * Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
- * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
- * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
- * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.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:
- * Free Software Foundation
- * 51 Franklin Street, Fifth Floor
- * Boston, MA 02111-1301 USA
- *
- */
-
-#include <linux/in.h>
-#include <linux/module.h>
-#include <linux/net.h>
-#include <linux/ipv6.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/un.h>
-#include <asm/uaccess.h>
-#include <linux/inet.h>
-#include <linux/idr.h>
-#include <linux/file.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "transport.h"
-
-#define V9FS_PORT 564
-
-struct v9fs_trans_fd {
- struct file *rd;
- struct file *wr;
-};
-
-/**
- * v9fs_fd_read- read from a fd
- * @v9ses: session information
- * @v: buffer to receive data into
- * @len: size of receive buffer
- *
- */
-static int v9fs_fd_read(struct v9fs_transport *trans, void *v, int len)
-{
- int ret;
- struct v9fs_trans_fd *ts;
-
- if (!trans || trans->status == Disconnected || !(ts = trans->priv))
- return -EREMOTEIO;
-
- if (!(ts->rd->f_flags & O_NONBLOCK))
- dprintk(DEBUG_ERROR, "blocking read ...\n");
-
- ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
- if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
- trans->status = Disconnected;
- return ret;
-}
-
-/**
- * v9fs_fd_write - write to a socket
- * @v9ses: session information
- * @v: buffer to send data from
- * @len: size of send buffer
- *
- */
-static int v9fs_fd_write(struct v9fs_transport *trans, void *v, int len)
-{
- int ret;
- mm_segment_t oldfs;
- struct v9fs_trans_fd *ts;
-
- if (!trans || trans->status == Disconnected || !(ts = trans->priv))
- return -EREMOTEIO;
-
- if (!(ts->wr->f_flags & O_NONBLOCK))
- dprintk(DEBUG_ERROR, "blocking write ...\n");
-
- oldfs = get_fs();
- set_fs(get_ds());
- /* The cast to a user pointer is valid due to the set_fs() */
- ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
- set_fs(oldfs);
-
- if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
- trans->status = Disconnected;
- return ret;
-}
-
-static unsigned int
-v9fs_fd_poll(struct v9fs_transport *trans, struct poll_table_struct *pt)
-{
- int ret, n;
- struct v9fs_trans_fd *ts;
- mm_segment_t oldfs;
-
- if (!trans || trans->status != Connected || !(ts = trans->priv))
- return -EREMOTEIO;
-
- if (!ts->rd->f_op || !ts->rd->f_op->poll)
- return -EIO;
-
- if (!ts->wr->f_op || !ts->wr->f_op->poll)
- return -EIO;
-
- oldfs = get_fs();
- set_fs(get_ds());
-
- ret = ts->rd->f_op->poll(ts->rd, pt);
- if (ret < 0)
- goto end;
-
- if (ts->rd != ts->wr) {
- n = ts->wr->f_op->poll(ts->wr, pt);
- if (n < 0) {
- ret = n;
- goto end;
- }
- ret = (ret & ~POLLOUT) | (n & ~POLLIN);
- }
-
- end:
- set_fs(oldfs);
- return ret;
-}
-
-static int v9fs_fd_open(struct v9fs_session_info *v9ses, int rfd, int wfd)
-{
- struct v9fs_transport *trans = v9ses->transport;
- struct v9fs_trans_fd *ts = kmalloc(sizeof(struct v9fs_trans_fd),
- GFP_KERNEL);
- if (!ts)
- return -ENOMEM;
-
- ts->rd = fget(rfd);
- ts->wr = fget(wfd);
- if (!ts->rd || !ts->wr) {
- if (ts->rd)
- fput(ts->rd);
- if (ts->wr)
- fput(ts->wr);
- kfree(ts);
- return -EIO;
- }
-
- trans->priv = ts;
- trans->status = Connected;
-
- return 0;
-}
-
-static int v9fs_fd_init(struct v9fs_session_info *v9ses, const char *addr,
- char *data)
-{
- if (v9ses->rfdno == ~0 || v9ses->wfdno == ~0) {
- printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
- return -ENOPROTOOPT;
- }
-
- return v9fs_fd_open(v9ses, v9ses->rfdno, v9ses->wfdno);
-}
-
-static int v9fs_socket_open(struct v9fs_session_info *v9ses,
- struct socket *csocket)
-{
- int fd, ret;
-
- csocket->sk->sk_allocation = GFP_NOIO;
- if ((fd = sock_map_fd(csocket)) < 0) {
- eprintk(KERN_ERR, "v9fs_socket_open: failed to map fd\n");
- ret = fd;
- release_csocket:
- sock_release(csocket);
- return ret;
- }
-
- if ((ret = v9fs_fd_open(v9ses, fd, fd)) < 0) {
- sockfd_put(csocket);
- eprintk(KERN_ERR, "v9fs_socket_open: failed to open fd\n");
- goto release_csocket;
- }
-
- ((struct v9fs_trans_fd *)v9ses->transport->priv)->rd->f_flags |=
- O_NONBLOCK;
- return 0;
-}
-
-static int v9fs_tcp_init(struct v9fs_session_info *v9ses, const char *addr,
- char *data)
-{
- int ret;
- struct socket *csocket = NULL;
- struct sockaddr_in sin_server;
-
- sin_server.sin_family = AF_INET;
- sin_server.sin_addr.s_addr = in_aton(addr);
- sin_server.sin_port = htons(v9ses->port);
- sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
-
- if (!csocket) {
- eprintk(KERN_ERR, "v9fs_trans_tcp: problem creating socket\n");
- return -1;
- }
-
- ret = csocket->ops->connect(csocket,
- (struct sockaddr *)&sin_server,
- sizeof(struct sockaddr_in), 0);
- if (ret < 0) {
- eprintk(KERN_ERR,
- "v9fs_trans_tcp: problem connecting socket to %s\n",
- addr);
- return ret;
- }
-
- return v9fs_socket_open(v9ses, csocket);
-}
-
-static int
-v9fs_unix_init(struct v9fs_session_info *v9ses, const char *addr, char *data)
-{
- int ret;
- struct socket *csocket;
- struct sockaddr_un sun_server;
-
- if (strlen(addr) > UNIX_PATH_MAX) {
- eprintk(KERN_ERR, "v9fs_trans_unix: address too long: %s\n",
- addr);
- return -ENAMETOOLONG;
- }
-
- sun_server.sun_family = PF_UNIX;
- strcpy(sun_server.sun_path, addr);
- sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
- ret = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
- sizeof(struct sockaddr_un) - 1, 0);
- if (ret < 0) {
- eprintk(KERN_ERR,
- "v9fs_trans_unix: problem connecting socket: %s: %d\n",
- addr, ret);
- return ret;
- }
-
- return v9fs_socket_open(v9ses, csocket);
-}
-
-/**
- * v9fs_sock_close - shutdown socket
- * @trans: private socket structure
- *
- */
-static void v9fs_fd_close(struct v9fs_transport *trans)
-{
- struct v9fs_trans_fd *ts;
-
- if (!trans)
- return;
-
- ts = xchg(&trans->priv, NULL);
-
- if (!ts)
- return;
-
- trans->status = Disconnected;
- if (ts->rd)
- fput(ts->rd);
- if (ts->wr)
- fput(ts->wr);
- kfree(ts);
-}
-
-struct v9fs_transport v9fs_trans_fd = {
- .init = v9fs_fd_init,
- .write = v9fs_fd_write,
- .read = v9fs_fd_read,
- .close = v9fs_fd_close,
- .poll = v9fs_fd_poll,
-};
-
-struct v9fs_transport v9fs_trans_tcp = {
- .init = v9fs_tcp_init,
- .write = v9fs_fd_write,
- .read = v9fs_fd_read,
- .close = v9fs_fd_close,
- .poll = v9fs_fd_poll,
-};
-
-struct v9fs_transport v9fs_trans_unix = {
- .init = v9fs_unix_init,
- .write = v9fs_fd_write,
- .read = v9fs_fd_read,
- .close = v9fs_fd_close,
- .poll = v9fs_fd_poll,
-};
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 6ad6f192b6e..45c35986d49 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -29,16 +29,12 @@
#include <linux/sched.h>
#include <linux/parser.h>
#include <linux/idr.h>
-
-#include "debug.h"
+#include <net/9p/9p.h>
+#include <net/9p/transport.h>
+#include <net/9p/conn.h>
+#include <net/9p/client.h>
#include "v9fs.h"
-#include "9p.h"
#include "v9fs_vfs.h"
-#include "transport.h"
-#include "mux.h"
-
-/* TODO: sysfs or debugfs interface */
-int v9fs_debug_level = 0; /* feature-rific global debug level */
/*
* Option Parsing (code inspired by NFS code)
@@ -47,12 +43,12 @@ int v9fs_debug_level = 0; /* feature-rific global debug level */
enum {
/* Options that take integer arguments */
- Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid, Opt_debug,
+ Opt_debug, Opt_port, Opt_msize, Opt_uid, Opt_gid, Opt_afid,
Opt_rfdno, Opt_wfdno,
/* String options */
Opt_uname, Opt_remotename,
/* Options that take no arguments */
- Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
+ Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, Opt_pci,
/* Cache options */
Opt_cache_loose,
/* Error token */
@@ -60,6 +56,7 @@ enum {
};
static match_table_t tokens = {
+ {Opt_debug, "debug=%x"},
{Opt_port, "port=%u"},
{Opt_msize, "msize=%u"},
{Opt_uid, "uid=%u"},
@@ -67,12 +64,14 @@ static match_table_t tokens = {
{Opt_afid, "afid=%u"},
{Opt_rfdno, "rfdno=%u"},
{Opt_wfdno, "wfdno=%u"},
- {Opt_debug, "debug=%x"},
{Opt_uname, "uname=%s"},
{Opt_remotename, "aname=%s"},
{Opt_unix, "proto=unix"},
{Opt_tcp, "proto=tcp"},
{Opt_fd, "proto=fd"},
+#ifdef CONFIG_PCI_9P
+ {Opt_pci, "proto=pci"},
+#endif
{Opt_tcp, "tcp"},
{Opt_unix, "unix"},
{Opt_fd, "fd"},
@@ -83,6 +82,8 @@ static match_table_t tokens = {
{Opt_err, NULL}
};
+extern struct p9_transport *p9pci_trans_create(void);
+
/*
* Parse option string.
*/
@@ -122,12 +123,16 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
token = match_token(p, tokens, args);
if (token < Opt_uname) {
if ((ret = match_int(&args[0], &option)) < 0) {
- dprintk(DEBUG_ERROR,
+ P9_DPRINTK(P9_DEBUG_ERROR,
"integer field, but no integer?\n");
continue;
}
}
switch (token) {
+ case Opt_debug:
+ v9ses->debug = option;
+ p9_debug_level = option;
+ break;
case Opt_port:
v9ses->port = option;
break;
@@ -149,15 +154,15 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
case Opt_wfdno:
v9ses->wfdno = option;
break;
- case Opt_debug:
- v9ses->debug = option;
- break;
case Opt_tcp:
v9ses->proto = PROTO_TCP;
break;
case Opt_unix:
v9ses->proto = PROTO_UNIX;
break;
+ case Opt_pci:
+ v9ses->proto = PROTO_PCI;
+ break;
case Opt_fd:
v9ses->proto = PROTO_FD;
break;
@@ -183,82 +188,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
}
/**
- * v9fs_inode2v9ses - safely extract v9fs session info from super block
- * @inode: inode to extract information from
- *
- * Paranoid function to extract v9ses information from superblock,
- * if anything is missing it will report an error.
- *
- */
-
-struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
-{
- return (inode->i_sb->s_fs_info);
-}
-
-/**
- * v9fs_get_idpool - allocate numeric id from pool
- * @p - pool to allocate from
- *
- * XXX - This seems to be an awful generic function, should it be in idr.c with
- * the lock included in struct idr?
- */
-
-int v9fs_get_idpool(struct v9fs_idpool *p)
-{
- int i = 0;
- int error;
-
-retry:
- if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
- return 0;
-
- if (down_interruptible(&p->lock) == -EINTR) {
- eprintk(KERN_WARNING, "Interrupted while locking\n");
- return -1;
- }
-
- /* no need to store exactly p, we just need something non-null */
- error = idr_get_new(&p->pool, p, &i);
- up(&p->lock);
-
- if (error == -EAGAIN)
- goto retry;
- else if (error)
- return -1;
-
- return i;
-}
-
-/**
- * v9fs_put_idpool - release numeric id from pool
- * @p - pool to allocate from
- *
- * XXX - This seems to be an awful generic function, should it be in idr.c with
- * the lock included in struct idr?
- */
-
-void v9fs_put_idpool(int id, struct v9fs_idpool *p)
-{
- if (down_interruptible(&p->lock) == -EINTR) {
- eprintk(KERN_WARNING, "Interrupted while locking\n");
- return;
- }
- idr_remove(&p->pool, id);
- up(&p->lock);
-}
-
-/**
- * v9fs_check_idpool - check if the specified id is available
- * @id - id to check
- * @p - pool
- */
-int v9fs_check_idpool(int id, struct v9fs_idpool *p)
-{
- return idr_find(&p->pool, id) != NULL;
-}
-
-/**
* v9fs_session_init - initialize session
* @v9ses: session information structure
* @dev_name: device being mounted
@@ -266,25 +195,21 @@ int v9fs_check_idpool(int id, struct v9fs_idpool *p)
*
*/
-int
-v9fs_session_init(struct v9fs_session_info *v9ses,
+struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
const char *dev_name, char *data)
{
- struct v9fs_fcall *fcall = NULL;
- struct v9fs_transport *trans_proto;
- int n = 0;
- int newfid = -1;
int retval = -EINVAL;
- struct v9fs_str *version;
+ struct p9_transport *trans;
+ struct p9_fid *fid;
v9ses->name = __getname();
if (!v9ses->name)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
v9ses->remotename = __getname();
if (!v9ses->remotename) {
__putname(v9ses->name);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
strcpy(v9ses->name, V9FS_DEFUSER);
@@ -292,130 +217,60 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
v9fs_parse_options(data, v9ses);
- /* set global debug level */
- v9fs_debug_level = v9ses->debug;
-
- /* id pools that are session-dependent: fids and tags */
- idr_init(&v9ses->fidpool.pool);
- init_MUTEX(&v9ses->fidpool.lock);
-
switch (v9ses->proto) {
case PROTO_TCP:
- trans_proto = &v9fs_trans_tcp;
+ trans = p9_trans_create_tcp(dev_name, v9ses->port);
break;
case PROTO_UNIX:
- trans_proto = &v9fs_trans_unix;
+ trans = p9_trans_create_unix(dev_name);
*v9ses->remotename = 0;
break;
case PROTO_FD:
- trans_proto = &v9fs_trans_fd;
+ trans = p9_trans_create_fd(v9ses->rfdno, v9ses->wfdno);
*v9ses->remotename = 0;
break;
+#ifdef CONFIG_PCI_9P
+ case PROTO_PCI:
+ trans = p9pci_trans_create();
+ *v9ses->remotename = 0;
+ break;
+#endif
default:
printk(KERN_ERR "v9fs: Bad mount protocol %d\n", v9ses->proto);
retval = -ENOPROTOOPT;
- goto SessCleanUp;
+ goto error;
};
- v9ses->transport = kmalloc(sizeof(*v9ses->transport), GFP_KERNEL);
- if (!v9ses->transport) {
- retval = -ENOMEM;
- goto SessCleanUp;
+ if (IS_ERR(trans)) {
+ retval = PTR_ERR(trans);
+ trans = NULL;
+ goto error;
}
- memmove(v9ses->transport, trans_proto, sizeof(*v9ses->transport));
+ v9ses->clnt = p9_client_create(trans, v9ses->maxdata + P9_IOHDRSZ,
+ v9ses->extended);
- if ((retval = v9ses->transport->init(v9ses, dev_name, data)) < 0) {
- eprintk(KERN_ERR, "problem initializing transport\n");
- goto SessCleanUp;
+ if (IS_ERR(v9ses->clnt)) {
+ retval = PTR_ERR(v9ses->clnt);
+ v9ses->clnt = NULL;
+ P9_DPRINTK(P9_DEBUG_ERROR, "problem initializing 9p client\n");
+ goto error;
}
- v9ses->inprogress = 0;
- v9ses->shutdown = 0;
- v9ses->session_hung = 0;
-
- v9ses->mux = v9fs_mux_init(v9ses->transport, v9ses->maxdata + V9FS_IOHDRSZ,
- &v9ses->extended);
-
- if (IS_ERR(v9ses->mux)) {
- retval = PTR_ERR(v9ses->mux);
- v9ses->mux = NULL;
- dprintk(DEBUG_ERROR, "problem initializing mux\n");
- goto SessCleanUp;
+ fid = p9_client_attach(v9ses->clnt, NULL, v9ses->name,
+ v9ses->remotename);
+ if (IS_ERR(fid)) {
+ retval = PTR_ERR(fid);
+ fid = NULL;
+ P9_DPRINTK(P9_DEBUG_ERROR, "cannot attach\n");
+ goto error;
}
- if (v9ses->afid == ~0) {
- if (v9ses->extended)
- retval =
- v9fs_t_version(v9ses, v9ses->maxdata, "9P2000.u",
- &fcall);
- else
- retval = v9fs_t_version(v9ses, v9ses->maxdata, "9P2000",
- &fcall);
-
- if (retval < 0) {
- dprintk(DEBUG_ERROR, "v9fs_t_version failed\n");
- goto FreeFcall;
- }
-
- version = &fcall->params.rversion.version;
- if (version->len==8 && !memcmp(version->str, "9P2000.u", 8)) {
- dprintk(DEBUG_9P, "9P2000 UNIX extensions enabled\n");
- v9ses->extended = 1;
- } else if (version->len==6 && !memcmp(version->str, "9P2000", 6)) {
- dprintk(DEBUG_9P, "9P2000 legacy mode enabled\n");
- v9ses->extended = 0;
- } else {
- retval = -EREMOTEIO;
- goto FreeFcall;
- }
+ return fid;
- n = fcall->params.rversion.msize;
- kfree(fcall);
-
- if (n < v9ses->maxdata)
- v9ses->maxdata = n;
- }
-
- newfid = v9fs_get_idpool(&v9ses->fidpool);
- if (newfid < 0) {
- eprintk(KERN_WARNING, "couldn't allocate FID\n");
- retval = -ENOMEM;
- goto SessCleanUp;
- }
- /* it is a little bit ugly, but we have to prevent newfid */
- /* being the same as afid, so if it is, get a new fid */
- if (v9ses->afid != ~0 && newfid == v9ses->afid) {
- newfid = v9fs_get_idpool(&v9ses->fidpool);
- if (newfid < 0) {
- eprintk(KERN_WARNING, "couldn't allocate FID\n");
- retval = -ENOMEM;
- goto SessCleanUp;
- }
- }
-
- if ((retval =
- v9fs_t_attach(v9ses, v9ses->name, v9ses->remotename, newfid,
- v9ses->afid, NULL))
- < 0) {
- dprintk(DEBUG_ERROR, "cannot attach\n");
- goto SessCleanUp;
- }
-
- if (v9ses->afid != ~0) {
- dprintk(DEBUG_ERROR, "afid not equal to ~0\n");
- if (v9fs_t_clunk(v9ses, v9ses->afid))
- dprintk(DEBUG_ERROR, "clunk failed\n");
- }
-
- return newfid;
-
- FreeFcall:
- kfree(fcall);
-
- SessCleanUp:
+error:
v9fs_session_close(v9ses);
- return retval;
+ return ERR_PTR(retval);
}
/**
@@ -426,15 +281,9 @@ v9fs_session_init(struct v9fs_session_info *v9ses,
void v9fs_session_close(struct v9fs_session_info *v9ses)
{
- if (v9ses->mux) {
- v9fs_mux_destroy(v9ses->mux);
- v9ses->mux = NULL;
- }
-
- if (v9ses->transport) {
- v9ses->transport->close(v9ses->transport);
- kfree(v9ses->transport);
- v9ses->transport = NULL;
+ if (v9ses->clnt) {
+ p9_client_destroy(v9ses->clnt);
+ v9ses->clnt = NULL;
}
__putname(v9ses->name);
@@ -446,9 +295,8 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
* and cancel all pending requests.
*/
void v9fs_session_cancel(struct v9fs_session_info *v9ses) {
- dprintk(DEBUG_ERROR, "cancel session %p\n", v9ses);
- v9ses->transport->status = Disconnected;
- v9fs_mux_cancel(v9ses->mux, -EIO);
+ P9_DPRINTK(P9_DEBUG_ERROR, "cancel session %p\n", v9ses);
+ p9_client_disconnect(v9ses->clnt);
}
extern int v9fs_error_init(void);
@@ -460,24 +308,9 @@ extern int v9fs_error_init(void);
static int __init init_v9fs(void)
{
- int ret;
-
- v9fs_error_init();
-
printk(KERN_INFO "Installing v9fs 9p2000 file system support\n");
- ret = v9fs_mux_global_init();
- if (ret) {
- printk(KERN_WARNING "v9fs: starting mux failed\n");
- return ret;
- }
- ret = register_filesystem(&v9fs_fs_type);
- if (ret) {
- printk(KERN_WARNING "v9fs: registering file system failed\n");
- v9fs_mux_global_exit();
- }
-
- return ret;
+ return register_filesystem(&v9fs_fs_type);
}
/**
@@ -487,13 +320,13 @@ static int __init init_v9fs(void)
static void __exit exit_v9fs(void)
{
- v9fs_mux_global_exit();
unregister_filesystem(&v9fs_fs_type);
}
module_init(init_v9fs)
module_exit(exit_v9fs)
+MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
MODULE_LICENSE("GPL");
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index 820bf5ca35d..abc4b1668ac 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -22,16 +22,6 @@
*/
/*
- * Idpool structure provides lock and id management
- *
- */
-
-struct v9fs_idpool {
- struct semaphore lock;
- struct idr pool;
-};
-
-/*
* Session structure provides information for an opened session
*
*/
@@ -54,15 +44,7 @@ struct v9fs_session_info {
unsigned int uid; /* default uid/muid for legacy support */
unsigned int gid; /* default gid for legacy support */
- /* book keeping */
- struct v9fs_idpool fidpool; /* The FID pool for file descriptors */
-
- struct v9fs_transport *transport;
- struct v9fs_mux_data *mux;
-
- int inprogress; /* session in progress => true */
- int shutdown; /* session shutting down. no more attaches. */
- unsigned char session_hung;
+ struct p9_client *clnt; /* 9p client */
struct dentry *debugfs_dir;
};
@@ -71,6 +53,7 @@ enum {
PROTO_TCP,
PROTO_UNIX,
PROTO_FD,
+ PROTO_PCI,
};
/* possible values of ->cache */
@@ -82,12 +65,9 @@ enum {
extern struct dentry *v9fs_debugfs_root;
-int v9fs_session_init(struct v9fs_session_info *, const char *, char *);
-struct v9fs_session_info *v9fs_inode2v9ses(struct inode *);
+struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
+ char *);
void v9fs_session_close(struct v9fs_session_info *v9ses);
-int v9fs_get_idpool(struct v9fs_idpool *p);
-void v9fs_put_idpool(int id, struct v9fs_idpool *p);
-int v9fs_check_idpool(int id, struct v9fs_idpool *p);
void v9fs_session_cancel(struct v9fs_session_info *v9ses);
#define V9FS_MAGIC 0x01021997
@@ -97,3 +77,7 @@ void v9fs_session_cancel(struct v9fs_session_info *v9ses);
#define V9FS_DEFUSER "nobody"
#define V9FS_DEFANAME ""
+static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
+{
+ return (inode->i_sb->s_fs_info);
+}
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 6a82d39dc49..fd01d90cada 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -45,10 +45,10 @@ extern struct dentry_operations v9fs_dentry_operations;
extern struct dentry_operations v9fs_cached_dentry_operations;
struct inode *v9fs_get_inode(struct super_block *sb, int mode);
-ino_t v9fs_qid2ino(struct v9fs_qid *qid);
-void v9fs_stat2inode(struct v9fs_stat *, struct inode *, struct super_block *);
+ino_t v9fs_qid2ino(struct p9_qid *qid);
+void v9fs_stat2inode(struct p9_stat *, struct inode *, struct super_block *);
int v9fs_dir_release(struct inode *inode, struct file *filp);
int v9fs_file_open(struct inode *inode, struct file *file);
-void v9fs_inode2stat(struct inode *inode, struct v9fs_stat *stat);
+void v9fs_inode2stat(struct inode *inode, struct p9_stat *stat);
void v9fs_dentry_release(struct dentry *);
int v9fs_uflags2omode(int uflags);
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 9ac4ffe9ac7..6248f0e727a 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -33,10 +33,10 @@
#include <linux/pagemap.h>
#include <linux/idr.h>
#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
-#include "debug.h"
#include "v9fs.h"
-#include "9p.h"
#include "v9fs_vfs.h"
#include "fid.h"
@@ -50,55 +50,26 @@
static int v9fs_vfs_readpage(struct file *filp, struct page *page)
{
- char *buffer = NULL;
- int retval = -EIO;
- loff_t offset = page_offset(page);
- int count = PAGE_CACHE_SIZE;
- struct inode *inode = filp->f_path.dentry->d_inode;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
- int rsize = v9ses->maxdata - V9FS_IOHDRSZ;
- struct v9fs_fid *v9f = filp->private_data;
- struct v9fs_fcall *fcall = NULL;
- int fid = v9f->fid;
- int total = 0;
- int result = 0;
-
- dprintk(DEBUG_VFS, "\n");
+ int retval;
+ loff_t offset;
+ char *buffer;
+ struct p9_fid *fid;
+ P9_DPRINTK(P9_DEBUG_VFS, "\n");
+ fid = filp->private_data;
buffer = kmap(page);
- do {
- if (count < rsize)
- rsize = count;
-
- result = v9fs_t_read(v9ses, fid, offset, rsize, &fcall);
-
- if (result < 0) {
- printk(KERN_ERR "v9fs_t_read returned %d\n",
- result);
-
- kfree(fcall);
- goto UnmapAndUnlock;
- } else
- offset += result;
-
- memcpy(buffer, fcall->params.rread.data, result);
-
- count -= result;
- buffer += result;
- total += result;
-
- kfree(fcall);
+ offset = page_offset(page);
- if (result < rsize)
- break;
- } while (count);
+ retval = p9_client_readn(fid, buffer, offset, PAGE_CACHE_SIZE);
+ if (retval < 0)
+ goto done;
- memset(buffer, 0, count);
+ memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval);
flush_dcache_page(page);
SetPageUptodate(page);
retval = 0;
-UnmapAndUnlock:
+done:
kunmap(page);
unlock_page(page);
return retval;
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index d93960429c0..f9534f18df0 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -34,10 +34,10 @@
#include <linux/namei.h>
#include <linux/idr.h>
#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
-#include "debug.h"
#include "v9fs.h"
-#include "9p.h"
#include "v9fs_vfs.h"
#include "fid.h"
@@ -52,7 +52,7 @@
static int v9fs_dentry_delete(struct dentry *dentry)
{
- dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
return 1;
}
@@ -69,7 +69,7 @@ static int v9fs_dentry_delete(struct dentry *dentry)
static int v9fs_cached_dentry_delete(struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
- dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
if(!inode)
return 1;
@@ -85,26 +85,19 @@ static int v9fs_cached_dentry_delete(struct dentry *dentry)
void v9fs_dentry_release(struct dentry *dentry)
{
- int err;
-
- dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
-
- if (dentry->d_fsdata != NULL) {
- struct list_head *fid_list = dentry->d_fsdata;
- struct v9fs_fid *temp = NULL;
- struct v9fs_fid *current_fid = NULL;
-
- list_for_each_entry_safe(current_fid, temp, fid_list, list) {
- err = v9fs_t_clunk(current_fid->v9ses, current_fid->fid);
-
- if (err < 0)
- dprintk(DEBUG_ERROR, "clunk failed: %d name %s\n",
- err, dentry->d_iname);
-
- v9fs_fid_destroy(current_fid);
+ struct v9fs_dentry *dent;
+ struct p9_fid *temp, *current_fid;
+
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ dent = dentry->d_fsdata;
+ if (dent) {
+ list_for_each_entry_safe(current_fid, temp, &dent->fidlist,
+ dlist) {
+ p9_client_clunk(current_fid);
}
- kfree(dentry->d_fsdata); /* free the list_head */
+ kfree(dent);
+ dentry->d_fsdata = NULL;
}
}
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 1dd86ee90bc..0924d4477da 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -32,11 +32,10 @@
#include <linux/sched.h>
#include <linux/inet.h>
#include <linux/idr.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
-#include "debug.h"
#include "v9fs.h"
-#include "9p.h"
-#include "conv.h"
#include "v9fs_vfs.h"
#include "fid.h"
@@ -46,14 +45,14 @@
*
*/
-static inline int dt_type(struct v9fs_stat *mistat)
+static inline int dt_type(struct p9_stat *mistat)
{
unsigned long perm = mistat->mode;
int rettype = DT_REG;
- if (perm & V9FS_DMDIR)
+ if (perm & P9_DMDIR)
rettype = DT_DIR;
- if (perm & V9FS_DMSYMLINK)
+ if (perm & P9_DMSYMLINK)
rettype = DT_LNK;
return rettype;
@@ -69,106 +68,36 @@ static inline int dt_type(struct v9fs_stat *mistat)
static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
- struct v9fs_fcall *fcall = NULL;
- struct inode *inode = filp->f_path.dentry->d_inode;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
- struct v9fs_fid *file = filp->private_data;
- unsigned int i, n, s;
- int fid = -1;
- int ret = 0;
- struct v9fs_stat stat;
- int over = 0;
-
- dprintk(DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
-
- fid = file->fid;
-
- if (file->rdir_fcall && (filp->f_pos != file->rdir_pos)) {
- kfree(file->rdir_fcall);
- file->rdir_fcall = NULL;
- }
-
- if (file->rdir_fcall) {
- n = file->rdir_fcall->params.rread.count;
- i = file->rdir_fpos;
- while (i < n) {
- s = v9fs_deserialize_stat(
- file->rdir_fcall->params.rread.data + i,
- n - i, &stat, v9ses->extended);
-
- if (s == 0) {
- dprintk(DEBUG_ERROR,
- "error while deserializing stat\n");
- ret = -EIO;
- goto FreeStructs;
- }
-
- over = filldir(dirent, stat.name.str, stat.name.len,
- filp->f_pos, v9fs_qid2ino(&stat.qid),
- dt_type(&stat));
-
- if (over) {
- file->rdir_fpos = i;
- file->rdir_pos = filp->f_pos;
- break;
- }
-
- i += s;
- filp->f_pos += s;
- }
-
- if (!over) {
- kfree(file->rdir_fcall);
- file->rdir_fcall = NULL;
- }
- }
-
- while (!over) {
- ret = v9fs_t_read(v9ses, fid, filp->f_pos,
- v9ses->maxdata-V9FS_IOHDRSZ, &fcall);
- if (ret < 0) {
- dprintk(DEBUG_ERROR, "error while reading: %d: %p\n",
- ret, fcall);
- goto FreeStructs;
- } else if (ret == 0)
+ int over;
+ struct p9_fid *fid;
+ struct v9fs_session_info *v9ses;
+ struct inode *inode;
+ struct p9_stat *st;
+
+ P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
+ inode = filp->f_path.dentry->d_inode;
+ v9ses = v9fs_inode2v9ses(inode);
+ fid = filp->private_data;
+ while ((st = p9_client_dirread(fid, filp->f_pos)) != NULL) {
+ if (IS_ERR(st))
+ return PTR_ERR(st);
+
+ over = filldir(dirent, st->name.str, st->name.len, filp->f_pos,
+ v9fs_qid2ino(&st->qid), dt_type(st));
+
+ if (over)
break;
- n = ret;
- i = 0;
- while (i < n) {
- s = v9fs_deserialize_stat(fcall->params.rread.data + i,
- n - i, &stat, v9ses->extended);
-
- if (s == 0) {
- dprintk(DEBUG_ERROR,
- "error while deserializing stat\n");
- return -EIO;
- }
-
- over = filldir(dirent, stat.name.str, stat.name.len,
- filp->f_pos, v9fs_qid2ino(&stat.qid),
- dt_type(&stat));
-
- if (over) {
- file->rdir_fcall = fcall;
- file->rdir_fpos = i;
- file->rdir_pos = filp->f_pos;
- fcall = NULL;
- break;
- }
-
- i += s;
- filp->f_pos += s;
- }
-
- kfree(fcall);
+ filp->f_pos += st->size;
+ kfree(st);
+ st = NULL;
}
- FreeStructs:
- kfree(fcall);
- return ret;
+ kfree(st);
+ return 0;
}
+
/**
* v9fs_dir_release - close a directory
* @inode: inode of the directory
@@ -178,29 +107,13 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
int v9fs_dir_release(struct inode *inode, struct file *filp)
{
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
- struct v9fs_fid *fid = filp->private_data;
- int fidnum = -1;
-
- dprintk(DEBUG_VFS, "inode: %p filp: %p fid: %d\n", inode, filp,
- fid->fid);
- fidnum = fid->fid;
+ struct p9_fid *fid;
+ fid = filp->private_data;
+ P9_DPRINTK(P9_DEBUG_VFS,
+ "inode: %p filp: %p fid: %d\n", inode, filp, fid->fid);
filemap_write_and_wait(inode->i_mapping);
-
- if (fidnum >= 0) {
- dprintk(DEBUG_VFS, "fidopen: %d v9f->fid: %d\n", fid->fidopen,
- fid->fid);
-
- if (v9fs_t_clunk(v9ses, fidnum))
- dprintk(DEBUG_ERROR, "clunk failed\n");
-
- kfree(fid->rdir_fcall);
- kfree(fid);
-
- filp->private_data = NULL;
- }
-
+ p9_client_clunk(fid);
return 0;
}
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 6e7678e4852..2a40c2946d0 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -34,10 +34,10 @@
#include <linux/list.h>
#include <asm/uaccess.h>
#include <linux/idr.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
-#include "debug.h"
#include "v9fs.h"
-#include "9p.h"
#include "v9fs_vfs.h"
#include "fid.h"
@@ -52,48 +52,40 @@ static const struct file_operations v9fs_cached_file_operations;
int v9fs_file_open(struct inode *inode, struct file *file)
{
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
- struct v9fs_fid *vfid;
- struct v9fs_fcall *fcall = NULL;
- int omode;
int err;
+ struct v9fs_session_info *v9ses;
+ struct p9_fid *fid;
+ int omode;
- dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
-
- vfid = v9fs_fid_clone(file->f_path.dentry);
- if (IS_ERR(vfid))
- return PTR_ERR(vfid);
-
+ P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file);
+ v9ses = v9fs_inode2v9ses(inode);
omode = v9fs_uflags2omode(file->f_flags);
- err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall);
- if (err < 0) {
- PRINT_FCALL_ERROR("open failed", fcall);
- goto Clunk_Fid;
+ fid = file->private_data;
+ if (!fid) {
+ fid = v9fs_fid_clone(file->f_path.dentry);
+ if (IS_ERR(fid))
+ return PTR_ERR(fid);
+
+ err = p9_client_open(fid, omode);
+ if (err < 0) {
+ p9_client_clunk(fid);
+ return err;
+ }
+ if (omode & P9_OTRUNC) {
+ inode->i_size = 0;
+ inode->i_blocks = 0;
+ }
}
- file->private_data = vfid;
- vfid->fidopen = 1;
- vfid->fidclunked = 0;
- vfid->iounit = fcall->params.ropen.iounit;
- vfid->rdir_pos = 0;
- vfid->rdir_fcall = NULL;
- vfid->filp = file;
- kfree(fcall);
-
- if((vfid->qid.version) && (v9ses->cache)) {
- dprintk(DEBUG_VFS, "cached");
+ file->private_data = fid;
+ if ((fid->qid.version) && (v9ses->cache)) {
+ P9_DPRINTK(P9_DEBUG_VFS, "cached");
/* enable cached file options */
if(file->f_op == &v9fs_file_operations)
file->f_op = &v9fs_cached_file_operations;
}
return 0;
-
-Clunk_Fid:
- v9fs_fid_clunk(v9ses, vfid);
- kfree(fcall);
-
- return err;
}
/**
@@ -110,7 +102,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl)
int res = 0;
struct inode *inode = filp->f_path.dentry->d_inode;
- dprintk(DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
+ P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl);
/* No mandatory locks */
if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
@@ -136,55 +128,16 @@ static ssize_t
v9fs_file_read(struct file *filp, char __user * data, size_t count,
loff_t * offset)
{
- struct inode *inode = filp->f_path.dentry->d_inode;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
- struct v9fs_fid *v9f = filp->private_data;
- struct v9fs_fcall *fcall = NULL;
- int fid = v9f->fid;
- int rsize = 0;
- int result = 0;
- int total = 0;
- int n;
-
- dprintk(DEBUG_VFS, "\n");
-
- rsize = v9ses->maxdata - V9FS_IOHDRSZ;
- if (v9f->iounit != 0 && rsize > v9f->iounit)
- rsize = v9f->iounit;
-
- do {
- if (count < rsize)
- rsize = count;
+ int ret;
+ struct p9_fid *fid;
- result = v9fs_t_read(v9ses, fid, *offset, rsize, &fcall);
+ P9_DPRINTK(P9_DEBUG_VFS, "\n");
+ fid = filp->private_data;
+ ret = p9_client_uread(fid, data, *offset, count);
+ if (ret > 0)
+ *offset += ret;
- if (result < 0) {
- printk(KERN_ERR "9P2000: v9fs_t_read returned %d\n",
- result);
-
- kfree(fcall);
- return total;
- } else
- *offset += result;
-
- n = copy_to_user(data, fcall->params.rread.data, result);
- if (n) {
- dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n);
- kfree(fcall);
- return -EFAULT;
- }
-
- count -= result;
- data += result;
- total += result;
-
- kfree(fcall);
-
- if (result < rsize)
- break;
- } while (count);
-
- return total;
+ return ret;
}
/**
@@ -200,50 +153,25 @@ static ssize_t
v9fs_file_write(struct file *filp, const char __user * data,
size_t count, loff_t * offset)
{
+ int ret;
+ struct p9_fid *fid;
struct inode *inode = filp->f_path.dentry->d_inode;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
- struct v9fs_fid *v9fid = filp->private_data;
- struct v9fs_fcall *fcall;
- int fid = v9fid->fid;
- int result = -EIO;
- int rsize = 0;
- int total = 0;
-
- dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count,
- (int)*offset);
- rsize = v9ses->maxdata - V9FS_IOHDRSZ;
- if (v9fid->iounit != 0 && rsize > v9fid->iounit)
- rsize = v9fid->iounit;
-
- do {
- if (count < rsize)
- rsize = count;
- result = v9fs_t_write(v9ses, fid, *offset, rsize, data, &fcall);
- if (result < 0) {
- PRINT_FCALL_ERROR("error while writing", fcall);
- kfree(fcall);
- return result;
- } else
- *offset += result;
+ P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
+ (int)count, (int)*offset);
- kfree(fcall);
- fcall = NULL;
+ fid = filp->private_data;
+ ret = p9_client_uwrite(fid, data, *offset, count);
+ if (ret > 0)
+ *offset += ret;
- if (result != rsize) {
- eprintk(KERN_ERR,
- "short write: v9fs_t_write returned %d\n",
- result);
- break;
- }
-
- count -= result;
- data += result;
- total += result;
- } while (count);
+ if (*offset > inode->i_size) {
+ inode->i_size = *offset;
+ inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
+ }
invalidate_inode_pages2(inode->i_mapping);
- return total;
+ return ret;
}
static const struct file_operations v9fs_cached_file_operations = {
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index c76cd8fa3f6..e5c45eed58a 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -34,10 +34,10 @@
#include <linux/namei.h>
#include <linux/idr.h>
#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
-#include "debug.h"
#include "v9fs.h"
-#include "9p.h"
#include "v9fs_vfs.h"
#include "fid.h"
@@ -58,27 +58,27 @@ static int unixmode2p9mode(struct v9fs_session_info *v9ses, int mode)
int res;
res = mode & 0777;
if (S_ISDIR(mode))
- res |= V9FS_DMDIR;
+ res |= P9_DMDIR;
if (v9ses->extended) {
if (S_ISLNK(mode))
- res |= V9FS_DMSYMLINK;
+ res |= P9_DMSYMLINK;
if (v9ses->nodev == 0) {
if (S_ISSOCK(mode))
- res |= V9FS_DMSOCKET;
+ res |= P9_DMSOCKET;
if (S_ISFIFO(mode))
- res |= V9FS_DMNAMEDPIPE;
+ res |= P9_DMNAMEDPIPE;
if (S_ISBLK(mode))
- res |= V9FS_DMDEVICE;
+ res |= P9_DMDEVICE;
if (S_ISCHR(mode))
- res |= V9FS_DMDEVICE;
+ res |= P9_DMDEVICE;
}
if ((mode & S_ISUID) == S_ISUID)
- res |= V9FS_DMSETUID;
+ res |= P9_DMSETUID;
if ((mode & S_ISGID) == S_ISGID)
- res |= V9FS_DMSETGID;
- if ((mode & V9FS_DMLINK))
- res |= V9FS_DMLINK;
+ res |= P9_DMSETGID;
+ if ((mode & P9_DMLINK))
+ res |= P9_DMLINK;
}
return res;
@@ -97,27 +97,27 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode)
res = mode & 0777;
- if ((mode & V9FS_DMDIR) == V9FS_DMDIR)
+ if ((mode & P9_DMDIR) == P9_DMDIR)
res |= S_IFDIR;
- else if ((mode & V9FS_DMSYMLINK) && (v9ses->extended))
+ else if ((mode & P9_DMSYMLINK) && (v9ses->extended))
res |= S_IFLNK;
- else if ((mode & V9FS_DMSOCKET) && (v9ses->extended)
+ else if ((mode & P9_DMSOCKET) && (v9ses->extended)
&& (v9ses->nodev == 0))
res |= S_IFSOCK;
- else if ((mode & V9FS_DMNAMEDPIPE) && (v9ses->extended)
+ else if ((mode & P9_DMNAMEDPIPE) && (v9ses->extended)
&& (v9ses->nodev == 0))
res |= S_IFIFO;
- else if ((mode & V9FS_DMDEVICE) && (v9ses->extended)
+ else if ((mode & P9_DMDEVICE) && (v9ses->extended)
&& (v9ses->nodev == 0))
res |= S_IFBLK;
else
res |= S_IFREG;
if (v9ses->extended) {
- if ((mode & V9FS_DMSETUID) == V9FS_DMSETUID)
+ if ((mode & P9_DMSETUID) == P9_DMSETUID)
res |= S_ISUID;
- if ((mode & V9FS_DMSETGID) == V9FS_DMSETGID)
+ if ((mode & P9_DMSETGID) == P9_DMSETGID)
res |= S_ISGID;
}
@@ -132,26 +132,26 @@ int v9fs_uflags2omode(int uflags)
switch (uflags&3) {
default:
case O_RDONLY:
- ret = V9FS_OREAD;
+ ret = P9_OREAD;
break;
case O_WRONLY:
- ret = V9FS_OWRITE;
+ ret = P9_OWRITE;
break;
case O_RDWR:
- ret = V9FS_ORDWR;
+ ret = P9_ORDWR;
break;
}
if (uflags & O_EXCL)
- ret |= V9FS_OEXCL;
+ ret |= P9_OEXCL;
if (uflags & O_TRUNC)
- ret |= V9FS_OTRUNC;
+ ret |= P9_OTRUNC;
if (uflags & O_APPEND)
- ret |= V9FS_OAPPEND;
+ ret |= P9_OAPPEND;
return ret;
}
@@ -164,7 +164,7 @@ int v9fs_uflags2omode(int uflags)
*/
static void
-v9fs_blank_wstat(struct v9fs_wstat *wstat)
+v9fs_blank_wstat(struct p9_wstat *wstat)
{
wstat->type = ~0;
wstat->dev = ~0;
@@ -197,7 +197,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
struct inode *inode;
struct v9fs_session_info *v9ses = sb->s_fs_info;
- dprintk(DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
+ P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
inode = new_inode(sb);
if (inode) {
@@ -215,7 +215,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
case S_IFCHR:
case S_IFSOCK:
if(!v9ses->extended) {
- dprintk(DEBUG_ERROR, "special files without extended mode\n");
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "special files without extended mode\n");
return ERR_PTR(-EINVAL);
}
init_special_inode(inode, inode->i_mode,
@@ -227,7 +228,8 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
break;
case S_IFLNK:
if(!v9ses->extended) {
- dprintk(DEBUG_ERROR, "extended modes used w/o 9P2000.u\n");
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "extended modes used w/o 9P2000.u\n");
return ERR_PTR(-EINVAL);
}
inode->i_op = &v9fs_symlink_inode_operations;
@@ -241,71 +243,19 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
inode->i_fop = &v9fs_dir_operations;
break;
default:
- dprintk(DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "BAD mode 0x%x S_IFMT 0x%x\n",
mode, mode & S_IFMT);
return ERR_PTR(-EINVAL);
}
} else {
- eprintk(KERN_WARNING, "Problem allocating inode\n");
+ P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
return ERR_PTR(-ENOMEM);
}
return inode;
}
-static int
-v9fs_create(struct v9fs_session_info *v9ses, u32 pfid, char *name, u32 perm,
- u8 mode, char *extension, u32 *fidp, struct v9fs_qid *qid, u32 *iounit)
-{
- int fid;
- int err;
- struct v9fs_fcall *fcall;
-
- fid = v9fs_get_idpool(&v9ses->fidpool);
- if (fid < 0) {
- eprintk(KERN_WARNING, "no free fids available\n");
- return -ENOSPC;
- }
-
- err = v9fs_t_walk(v9ses, pfid, fid, NULL, &fcall);
- if (err < 0) {
- PRINT_FCALL_ERROR("clone error", fcall);
- if (fcall && fcall->id == RWALK)
- goto clunk_fid;
- else
- goto put_fid;
- }
- kfree(fcall);
-
- err = v9fs_t_create(v9ses, fid, name, perm, mode, extension, &fcall);
- if (err < 0) {
- PRINT_FCALL_ERROR("create fails", fcall);
- goto clunk_fid;
- }
-
- if (iounit)
- *iounit = fcall->params.rcreate.iounit;
-
- if (qid)
- *qid = fcall->params.rcreate.qid;
-
- if (fidp)
- *fidp = fid;
-
- kfree(fcall);
- return 0;
-
-clunk_fid:
- v9fs_t_clunk(v9ses, fid);
- fid = V9FS_NOFID;
-
-put_fid:
- if (fid != V9FS_NOFID)
- v9fs_put_idpool(fid, &v9ses->fidpool);
-
- kfree(fcall);
- return err;
-}
-
+/*
static struct v9fs_fid*
v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry)
{
@@ -355,23 +305,25 @@ error:
kfree(fcall);
return ERR_PTR(err);
}
+*/
static struct inode *
-v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
+v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
struct super_block *sb)
{
int err, umode;
struct inode *ret;
- struct v9fs_fcall *fcall;
+ struct p9_stat *st;
ret = NULL;
- err = v9fs_t_stat(v9ses, fid, &fcall);
- if (err) {
- PRINT_FCALL_ERROR("stat error", fcall);
+ st = p9_client_stat(fid);
+ if (IS_ERR(st)) {
+ err = PTR_ERR(st);
+ st = NULL;
goto error;
}
- umode = p9mode2unixmode(v9ses, fcall->params.rstat.stat.mode);
+ umode = p9mode2unixmode(v9ses, st->mode);
ret = v9fs_get_inode(sb, umode);
if (IS_ERR(ret)) {
err = PTR_ERR(ret);
@@ -379,12 +331,13 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, u32 fid,
goto error;
}
- v9fs_stat2inode(&fcall->params.rstat.stat, ret, sb);
- kfree(fcall);
+ v9fs_stat2inode(st, ret, sb);
+ ret->i_ino = v9fs_qid2ino(&st->qid);
+ kfree(st);
return ret;
error:
- kfree(fcall);
+ kfree(st);
if (ret)
iput(ret);
@@ -401,43 +354,20 @@ error:
static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
{
- struct v9fs_fcall *fcall = NULL;
- struct super_block *sb = NULL;
- struct v9fs_session_info *v9ses = NULL;
- struct v9fs_fid *v9fid = NULL;
- struct inode *file_inode = NULL;
- int fid = -1;
- int result = 0;
+ struct inode *file_inode;
+ struct v9fs_session_info *v9ses;
+ struct p9_fid *v9fid;
- dprintk(DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
+ P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
rmdir);
file_inode = file->d_inode;
- sb = file_inode->i_sb;
v9ses = v9fs_inode2v9ses(file_inode);
v9fid = v9fs_fid_clone(file);
if(IS_ERR(v9fid))
return PTR_ERR(v9fid);
- fid = v9fid->fid;
- if (fid < 0) {
- dprintk(DEBUG_ERROR, "inode #%lu, no fid!\n",
- file_inode->i_ino);
- return -EBADF;
- }
-
- result = v9fs_t_remove(v9ses, fid, &fcall);
- if (result < 0) {
- PRINT_FCALL_ERROR("remove fails", fcall);
- goto Error;
- }
-
- v9fs_put_idpool(fid, &v9ses->fidpool);
- v9fs_fid_destroy(v9fid);
-
-Error:
- kfree(fcall);
- return result;
+ return p9_client_remove(v9fid);
}
static int
@@ -446,61 +376,59 @@ v9fs_open_created(struct inode *inode, struct file *file)
return 0;
}
+
/**
- * v9fs_vfs_create - VFS hook to create files
- * @inode: directory inode that is being deleted
- * @dentry: dentry that is being deleted
- * @mode: create permissions
- * @nd: path information
+ * v9fs_create - Create a file
+ * @dentry: dentry that is being created
+ * @perm: create permissions
+ * @mode: open mode
*
*/
-
-static int
-v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
+static struct p9_fid *
+v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
+ struct dentry *dentry, char *extension, u32 perm, u8 mode)
{
int err;
- u32 fid, perm, iounit;
- int flags;
- struct v9fs_session_info *v9ses;
- struct v9fs_fid *dfid, *vfid, *ffid;
+ char *name;
+ struct p9_fid *dfid, *ofid, *fid;
struct inode *inode;
- struct v9fs_qid qid;
- struct file *filp;
- inode = NULL;
- vfid = NULL;
- v9ses = v9fs_inode2v9ses(dir);
+ err = 0;
+ ofid = NULL;
+ fid = NULL;
+ name = (char *) dentry->d_name.name;
dfid = v9fs_fid_clone(dentry->d_parent);
if(IS_ERR(dfid)) {
err = PTR_ERR(dfid);
+ dfid = NULL;
goto error;
}
- perm = unixmode2p9mode(v9ses, mode);
- if (nd && nd->flags & LOOKUP_OPEN)
- flags = nd->intent.open.flags - 1;
- else
- flags = O_RDWR;
-
- err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
+ /* clone a fid to use for creation */
+ ofid = p9_client_walk(dfid, 0, NULL, 1);
+ if (IS_ERR(ofid)) {
+ err = PTR_ERR(ofid);
+ ofid = NULL;
+ goto error;
+ }
- if (err)
- goto clunk_dfid;
+ err = p9_client_fcreate(ofid, name, perm, mode, extension);
+ if (err < 0)
+ goto error;
- vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
- v9fs_fid_clunk(v9ses, dfid);
- if (IS_ERR(vfid)) {
- err = PTR_ERR(vfid);
- vfid = NULL;
+ /* now walk from the parent so we can get unopened fid */
+ fid = p9_client_walk(dfid, 1, &name, 0);
+ if (IS_ERR(fid)) {
+ err = PTR_ERR(fid);
+ fid = NULL;
goto error;
- }
+ } else
+ dfid = NULL;
- inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
+ /* instantiate inode and assign the unopened fid to the dentry */
+ inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
- inode = NULL;
goto error;
}
@@ -508,35 +436,78 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
dentry->d_op = &v9fs_cached_dentry_operations;
else
dentry->d_op = &v9fs_dentry_operations;
+
d_instantiate(dentry, inode);
+ v9fs_fid_add(dentry, fid);
+ return ofid;
- if (nd && nd->flags & LOOKUP_OPEN) {
- ffid = v9fs_fid_create(v9ses, fid);
- if (!ffid)
- return -ENOMEM;
+error:
+ if (dfid)
+ p9_client_clunk(dfid);
+
+ if (ofid)
+ p9_client_clunk(ofid);
+
+ if (fid)
+ p9_client_clunk(fid);
+
+ return ERR_PTR(err);
+}
+
+/**
+ * v9fs_vfs_create - VFS hook to create files
+ * @inode: directory inode that is being created
+ * @dentry: dentry that is being deleted
+ * @mode: create permissions
+ * @nd: path information
+ *
+ */
+static int
+v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
+{
+ int err;
+ u32 perm;
+ int flags;
+ struct v9fs_session_info *v9ses;
+ struct p9_fid *fid;
+ struct file *filp;
+
+ err = 0;
+ fid = NULL;
+ v9ses = v9fs_inode2v9ses(dir);
+ perm = unixmode2p9mode(v9ses, mode);
+ if (nd && nd->flags & LOOKUP_OPEN)
+ flags = nd->intent.open.flags - 1;
+ else
+ flags = O_RDWR;
+
+ fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
+ v9fs_uflags2omode(flags));
+ if (IS_ERR(fid)) {
+ err = PTR_ERR(fid);
+ fid = NULL;
+ goto error;
+ }
+
+ /* if we are opening a file, assign the open fid to the file */
+ if (nd && nd->flags & LOOKUP_OPEN) {
filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
if (IS_ERR(filp)) {
- v9fs_fid_destroy(ffid);
- return PTR_ERR(filp);
+ err = PTR_ERR(filp);
+ goto error;
}
- ffid->rdir_pos = 0;
- ffid->rdir_fcall = NULL;
- ffid->fidopen = 1;
- ffid->iounit = iounit;
- ffid->filp = filp;
- filp->private_data = ffid;
- }
+ filp->private_data = fid;
+ } else
+ p9_client_clunk(fid);
return 0;
-clunk_dfid:
- v9fs_fid_clunk(v9ses, dfid);
-
error:
- if (vfid)
- v9fs_fid_destroy(vfid);
+ if (fid)
+ p9_client_clunk(fid);
return err;
}
@@ -552,57 +523,23 @@ error:
static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
int err;
- u32 fid, perm;
+ u32 perm;
struct v9fs_session_info *v9ses;
- struct v9fs_fid *dfid, *vfid;
- struct inode *inode;
+ struct p9_fid *fid;
- inode = NULL;
- vfid = NULL;
+ P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
+ err = 0;
v9ses = v9fs_inode2v9ses(dir);
- dfid = v9fs_fid_clone(dentry->d_parent);
- if(IS_ERR(dfid)) {
- err = PTR_ERR(dfid);
- goto error;
- }
-
perm = unixmode2p9mode(v9ses, mode | S_IFDIR);
-
- err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, V9FS_OREAD, NULL, &fid, NULL, NULL);
-
- if (err) {
- dprintk(DEBUG_ERROR, "create error %d\n", err);
- goto clean_up_dfid;
+ fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD);
+ if (IS_ERR(fid)) {
+ err = PTR_ERR(fid);
+ fid = NULL;
}
- vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
- if (IS_ERR(vfid)) {
- err = PTR_ERR(vfid);
- vfid = NULL;
- goto clean_up_dfid;
- }
+ if (fid)
+ p9_client_clunk(fid);
- v9fs_fid_clunk(v9ses, dfid);
- inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
- if (IS_ERR(inode)) {
- err = PTR_ERR(inode);
- inode = NULL;
- v9fs_fid_destroy(vfid);
- goto error;
- }
-
- if(v9ses->cache)
- dentry->d_op = &v9fs_cached_dentry_operations;
- else
- dentry->d_op = &v9fs_dentry_operations;
- d_instantiate(dentry, inode);
- return 0;
-
-clean_up_dfid:
- v9fs_fid_clunk(v9ses, dfid);
-
-error:
return err;
}
@@ -619,104 +556,54 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
{
struct super_block *sb;
struct v9fs_session_info *v9ses;
- struct v9fs_fid *dirfid;
- struct v9fs_fid *fid;
+ struct p9_fid *dfid, *fid;
struct inode *inode;
- struct v9fs_fcall *fcall = NULL;
- int dirfidnum = -1;
- int newfid = -1;
+ char *name;
int result = 0;
- dprintk(DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
+ P9_DPRINTK(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
dir, dentry->d_name.name, dentry, nameidata);
sb = dir->i_sb;
v9ses = v9fs_inode2v9ses(dir);
- dirfid = v9fs_fid_lookup(dentry->d_parent);
-
- if(IS_ERR(dirfid))
- return ERR_PTR(PTR_ERR(dirfid));
-
- dirfidnum = dirfid->fid;
-
- newfid = v9fs_get_idpool(&v9ses->fidpool);
- if (newfid < 0) {
- eprintk(KERN_WARNING, "newfid fails!\n");
- result = -ENOSPC;
- goto Release_Dirfid;
- }
-
- result = v9fs_t_walk(v9ses, dirfidnum, newfid,
- (char *)dentry->d_name.name, &fcall);
-
- up(&dirfid->lock);
-
- if (result < 0) {
- if (fcall && fcall->id == RWALK)
- v9fs_t_clunk(v9ses, newfid);
- else
- v9fs_put_idpool(newfid, &v9ses->fidpool);
-
+ dfid = v9fs_fid_lookup(dentry->d_parent);
+ if (IS_ERR(dfid))
+ return ERR_PTR(PTR_ERR(dfid));
+
+ name = (char *) dentry->d_name.name;
+ fid = p9_client_walk(dfid, 1, &name, 1);
+ if (IS_ERR(fid)) {
+ result = PTR_ERR(fid);
if (result == -ENOENT) {
d_add(dentry, NULL);
- dprintk(DEBUG_VFS,
- "Return negative dentry %p count %d\n",
- dentry, atomic_read(&dentry->d_count));
- kfree(fcall);
return NULL;
}
- dprintk(DEBUG_ERROR, "walk error:%d\n", result);
- goto FreeFcall;
- }
- kfree(fcall);
-
- result = v9fs_t_stat(v9ses, newfid, &fcall);
- if (result < 0) {
- dprintk(DEBUG_ERROR, "stat error\n");
- goto FreeFcall;
- }
-
- inode = v9fs_get_inode(sb, p9mode2unixmode(v9ses,
- fcall->params.rstat.stat.mode));
- if (IS_ERR(inode) && (PTR_ERR(inode) == -ENOSPC)) {
- eprintk(KERN_WARNING, "inode alloc failes, returns %ld\n",
- PTR_ERR(inode));
-
- result = -ENOSPC;
- goto FreeFcall;
+ return ERR_PTR(result);
}
- inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid);
-
- fid = v9fs_fid_create(v9ses, newfid);
- if (fid == NULL) {
- dprintk(DEBUG_ERROR, "couldn't insert\n");
- result = -ENOMEM;
- goto FreeFcall;
+ inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+ if (IS_ERR(inode)) {
+ result = PTR_ERR(inode);
+ inode = NULL;
+ goto error;
}
- result = v9fs_fid_insert(fid, dentry);
+ result = v9fs_fid_add(dentry, fid);
if (result < 0)
- goto FreeFcall;
+ goto error;
- fid->qid = fcall->params.rstat.stat.qid;
- v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
if((fid->qid.version)&&(v9ses->cache))
dentry->d_op = &v9fs_cached_dentry_operations;
else
dentry->d_op = &v9fs_dentry_operations;
d_add(dentry, inode);
- kfree(fcall);
-
return NULL;
-Release_Dirfid:
- up(&dirfid->lock);
-
-FreeFcall:
- kfree(fcall);
+error:
+ if (fid)
+ p9_client_clunk(fid);
return ERR_PTR(result);
}
@@ -758,73 +645,54 @@ static int
v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
- struct inode *old_inode = old_dentry->d_inode;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(old_inode);
- struct v9fs_fid *oldfid = v9fs_fid_lookup(old_dentry);
- struct v9fs_fid *olddirfid;
- struct v9fs_fid *newdirfid;
- struct v9fs_wstat wstat;
- struct v9fs_fcall *fcall = NULL;
- int fid = -1;
- int olddirfidnum = -1;
- int newdirfidnum = -1;
- int retval = 0;
-
- dprintk(DEBUG_VFS, "\n");
+ struct inode *old_inode;
+ struct v9fs_session_info *v9ses;
+ struct p9_fid *oldfid;
+ struct p9_fid *olddirfid;
+ struct p9_fid *newdirfid;
+ struct p9_wstat wstat;
+ int retval;
+ P9_DPRINTK(P9_DEBUG_VFS, "\n");
+ retval = 0;
+ old_inode = old_dentry->d_inode;
+ v9ses = v9fs_inode2v9ses(old_inode);
+ oldfid = v9fs_fid_lookup(old_dentry);
if(IS_ERR(oldfid))
return PTR_ERR(oldfid);
olddirfid = v9fs_fid_clone(old_dentry->d_parent);
if(IS_ERR(olddirfid)) {
retval = PTR_ERR(olddirfid);
- goto Release_lock;
+ goto done;
}
newdirfid = v9fs_fid_clone(new_dentry->d_parent);
if(IS_ERR(newdirfid)) {
retval = PTR_ERR(newdirfid);
- goto Clunk_olddir;
+ goto clunk_olddir;
}
/* 9P can only handle file rename in the same directory */
if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) {
- dprintk(DEBUG_ERROR, "old dir and new dir are different\n");
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "old dir and new dir are different\n");
retval = -EXDEV;
- goto Clunk_newdir;
- }
-
- fid = oldfid->fid;
- olddirfidnum = olddirfid->fid;
- newdirfidnum = newdirfid->fid;
-
- if (fid < 0) {
- dprintk(DEBUG_ERROR, "no fid for old file #%lu\n",
- old_inode->i_ino);
- retval = -EBADF;
- goto Clunk_newdir;
+ goto clunk_newdir;
}
v9fs_blank_wstat(&wstat);
wstat.muid = v9ses->name;
wstat.name = (char *) new_dentry->d_name.name;
+ retval = p9_client_wstat(oldfid, &wstat);
- retval = v9fs_t_wstat(v9ses, fid, &wstat, &fcall);
+clunk_newdir:
+ p9_client_clunk(olddirfid);
- if (retval < 0)
- PRINT_FCALL_ERROR("wstat error", fcall);
-
- kfree(fcall);
-
-Clunk_newdir:
- v9fs_fid_clunk(v9ses, newdirfid);
-
-Clunk_olddir:
- v9fs_fid_clunk(v9ses, olddirfid);
-
-Release_lock:
- up(&oldfid->lock);
+clunk_olddir:
+ p9_client_clunk(newdirfid);
+done:
return retval;
}
@@ -840,28 +708,30 @@ static int
v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
- struct v9fs_fcall *fcall = NULL;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
- struct v9fs_fid *fid = v9fs_fid_clone(dentry);
- int err = -EPERM;
+ int err;
+ struct v9fs_session_info *v9ses;
+ struct p9_fid *fid;
+ struct p9_stat *st;
- dprintk(DEBUG_VFS, "dentry: %p\n", dentry);
- if(IS_ERR(fid))
+ P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
+ err = -EPERM;
+ v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ if (v9ses->cache == CACHE_LOOSE)
+ return simple_getattr(mnt, dentry, stat);
+
+ fid = v9fs_fid_lookup(dentry);
+ if (IS_ERR(fid))
return PTR_ERR(fid);
- err = v9fs_t_stat(v9ses, fid->fid, &fcall);
+ st = p9_client_stat(fid);
+ if (IS_ERR(st))
+ return PTR_ERR(st);
- if (err < 0)
- dprintk(DEBUG_ERROR, "stat error\n");
- else {
- v9fs_stat2inode(&fcall->params.rstat.stat, dentry->d_inode,
- dentry->d_inode->i_sb);
+ v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb);
generic_fillattr(dentry->d_inode, stat);
- }
- kfree(fcall);
- v9fs_fid_clunk(v9ses, fid);
- return err;
+ kfree(st);
+ return 0;
}
/**
@@ -873,13 +743,15 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
{
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
- struct v9fs_fid *fid = v9fs_fid_clone(dentry);
- struct v9fs_fcall *fcall = NULL;
- struct v9fs_wstat wstat;
- int res = -EPERM;
+ int retval;
+ struct v9fs_session_info *v9ses;
+ struct p9_fid *fid;
+ struct p9_wstat wstat;
- dprintk(DEBUG_VFS, "\n");
+ P9_DPRINTK(P9_DEBUG_VFS, "\n");
+ retval = -EPERM;
+ v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ fid = v9fs_fid_lookup(dentry);
if(IS_ERR(fid))
return PTR_ERR(fid);
@@ -904,17 +776,11 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
wstat.n_gid = iattr->ia_gid;
}
- res = v9fs_t_wstat(v9ses, fid->fid, &wstat, &fcall);
+ retval = p9_client_wstat(fid, &wstat);
+ if (retval >= 0)
+ retval = inode_setattr(dentry->d_inode, iattr);
- if (res < 0)
- PRINT_FCALL_ERROR("wstat error", fcall);
-
- kfree(fcall);
- if (res >= 0)
- res = inode_setattr(dentry->d_inode, iattr);
-
- v9fs_fid_clunk(v9ses, fid);
- return res;
+ return retval;
}
/**
@@ -926,7 +792,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
*/
void
-v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
+v9fs_stat2inode(struct p9_stat *stat, struct inode *inode,
struct super_block *sb)
{
int n;
@@ -967,8 +833,9 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
case 'b':
break;
default:
- dprintk(DEBUG_ERROR, "Unknown special type %c (%.*s)\n",
- type, stat->extension.len, stat->extension.str);
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "Unknown special type %c (%.*s)\n", type,
+ stat->extension.len, stat->extension.str);
};
inode->i_rdev = MKDEV(major, minor);
} else
@@ -976,8 +843,8 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
inode->i_size = stat->length;
- inode->i_blocks =
- (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+ /* not real number of blocks, but 512 byte ones ... */
+ inode->i_blocks = (inode->i_size + 512 - 1) >> 9;
}
/**
@@ -987,7 +854,7 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
* BUG: potential for inode number collisions?
*/
-ino_t v9fs_qid2ino(struct v9fs_qid *qid)
+ino_t v9fs_qid2ino(struct p9_qid *qid)
{
u64 path = qid->path + 2;
ino_t i = 0;
@@ -1010,56 +877,46 @@ ino_t v9fs_qid2ino(struct v9fs_qid *qid)
static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- int retval = -EPERM;
+ int retval;
- struct v9fs_fcall *fcall = NULL;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
- struct v9fs_fid *fid = v9fs_fid_clone(dentry);
+ struct v9fs_session_info *v9ses;
+ struct p9_fid *fid;
+ struct p9_stat *st;
+ P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
+ retval = -EPERM;
+ v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ fid = v9fs_fid_lookup(dentry);
if(IS_ERR(fid))
return PTR_ERR(fid);
- if (!v9ses->extended) {
- retval = -EBADF;
- dprintk(DEBUG_ERROR, "not extended\n");
- goto ClunkFid;
- }
-
- dprintk(DEBUG_VFS, " %s\n", dentry->d_name.name);
- retval = v9fs_t_stat(v9ses, fid->fid, &fcall);
-
- if (retval < 0) {
- dprintk(DEBUG_ERROR, "stat error\n");
- goto FreeFcall;
- }
+ if (!v9ses->extended)
+ return -EBADF;
- if (!fcall) {
- retval = -EIO;
- goto ClunkFid;
- }
+ st = p9_client_stat(fid);
+ if (IS_ERR(st))
+ return PTR_ERR(st);
- if (!(fcall->params.rstat.stat.mode & V9FS_DMSYMLINK)) {
+ if (!(st->mode & P9_DMSYMLINK)) {
retval = -EINVAL;
- goto FreeFcall;
+ goto done;
}
/* copy extension buffer into buffer */
- if (fcall->params.rstat.stat.extension.len < buflen)
- buflen = fcall->params.rstat.stat.extension.len + 1;
+ if (st->extension.len < buflen)
+ buflen = st->extension.len + 1;
- memmove(buffer, fcall->params.rstat.stat.extension.str, buflen - 1);
+ memmove(buffer, st->extension.str, buflen - 1);
buffer[buflen-1] = 0;
- dprintk(DEBUG_ERROR, "%s -> %.*s (%s)\n", dentry->d_name.name, fcall->params.rstat.stat.extension.len,
- fcall->params.rstat.stat.extension.str, buffer);
- retval = buflen;
+ P9_DPRINTK(P9_DEBUG_VFS,
+ "%s -> %.*s (%s)\n", dentry->d_name.name, st->extension.len,
+ st->extension.str, buffer);
-FreeFcall:
- kfree(fcall);
-
-ClunkFid:
- v9fs_fid_clunk(v9ses, fid);
+ retval = buflen;
+done:
+ kfree(st);
return retval;
}
@@ -1084,14 +941,14 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer,
if (buflen > PATH_MAX)
buflen = PATH_MAX;
- dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
+ P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
retval = v9fs_readlink(dentry, link, buflen);
if (retval > 0) {
if ((ret = copy_to_user(buffer, link, retval)) != 0) {
- dprintk(DEBUG_ERROR, "problem copying to user: %d\n",
- ret);
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "problem copying to user: %d\n", ret);
retval = ret;
}
}
@@ -1112,7 +969,7 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
int len = 0;
char *link = __getname();
- dprintk(DEBUG_VFS, "%s n", dentry->d_name.name);
+ P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name);
if (!link)
link = ERR_PTR(-ENOMEM);
@@ -1141,7 +998,7 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
{
char *s = nd_get_link(nd);
- dprintk(DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
+ P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, s);
if (!IS_ERR(s))
__putname(s);
}
@@ -1149,66 +1006,24 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void
static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
int mode, const char *extension)
{
- int err;
- u32 fid, perm;
+ u32 perm;
struct v9fs_session_info *v9ses;
- struct v9fs_fid *dfid, *vfid = NULL;
- struct inode *inode = NULL;
+ struct p9_fid *fid;
v9ses = v9fs_inode2v9ses(dir);
if (!v9ses->extended) {
- dprintk(DEBUG_ERROR, "not extended\n");
+ P9_DPRINTK(P9_DEBUG_ERROR, "not extended\n");
return -EPERM;
}
- dfid = v9fs_fid_clone(dentry->d_parent);
- if(IS_ERR(dfid)) {
- err = PTR_ERR(dfid);
- goto error;
- }
-
perm = unixmode2p9mode(v9ses, mode);
+ fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm,
+ P9_OREAD);
+ if (IS_ERR(fid))
+ return PTR_ERR(fid);
- err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
- perm, V9FS_OREAD, (char *) extension, &fid, NULL, NULL);
-
- if (err)
- goto clunk_dfid;
-
- err = v9fs_t_clunk(v9ses, fid);
- if (err)
- goto clunk_dfid;
-
- vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
- if (IS_ERR(vfid)) {
- err = PTR_ERR(vfid);
- vfid = NULL;
- goto clunk_dfid;
- }
-
- inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
- if (IS_ERR(inode)) {
- err = PTR_ERR(inode);
- inode = NULL;
- goto free_vfid;
- }
-
- if(v9ses->cache)
- dentry->d_op = &v9fs_cached_dentry_operations;
- else
- dentry->d_op = &v9fs_dentry_operations;
- d_instantiate(dentry, inode);
+ p9_client_clunk(fid);
return 0;
-
-free_vfid:
- v9fs_fid_destroy(vfid);
-
-clunk_dfid:
- v9fs_fid_clunk(v9ses, dfid);
-
-error:
- return err;
-
}
/**
@@ -1224,8 +1039,8 @@ error:
static int
v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
{
- dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
- symname);
+ P9_DPRINTK(P9_DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino,
+ dentry->d_name.name, symname);
return v9fs_vfs_mkspecial(dir, dentry, S_IFLNK, symname);
}
@@ -1247,11 +1062,11 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *dentry)
{
int retval;
- struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
- struct v9fs_fid *oldfid;
+ struct p9_fid *oldfid;
char *name;
- dprintk(DEBUG_VFS, " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
+ P9_DPRINTK(P9_DEBUG_VFS,
+ " %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
old_dentry->d_name.name);
oldfid = v9fs_fid_clone(old_dentry);
@@ -1265,11 +1080,11 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
}
sprintf(name, "%d\n", oldfid->fid);
- retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
+ retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
__putname(name);
clunk_fid:
- v9fs_fid_clunk(v9ses, oldfid);
+ p9_client_clunk(oldfid);
return retval;
}
@@ -1288,7 +1103,8 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
int retval;
char *name;
- dprintk(DEBUG_VFS, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
+ P9_DPRINTK(P9_DEBUG_VFS,
+ " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev));
if (!new_valid_dev(rdev))
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 7bdf8b32684..ba904371218 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -37,10 +37,10 @@
#include <linux/mount.h>
#include <linux/idr.h>
#include <linux/sched.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
-#include "debug.h"
#include "v9fs.h"
-#include "9p.h"
#include "v9fs_vfs.h"
#include "fid.h"
@@ -107,41 +107,48 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
struct vfsmount *mnt)
{
struct super_block *sb = NULL;
- struct v9fs_fcall *fcall = NULL;
struct inode *inode = NULL;
struct dentry *root = NULL;
struct v9fs_session_info *v9ses = NULL;
- struct v9fs_fid *root_fid = NULL;
+ struct p9_stat *st = NULL;
int mode = S_IRWXUGO | S_ISVTX;
uid_t uid = current->fsuid;
gid_t gid = current->fsgid;
- int stat_result = 0;
- int newfid = 0;
+ struct p9_fid *fid;
int retval = 0;
- dprintk(DEBUG_VFS, " \n");
+ P9_DPRINTK(P9_DEBUG_VFS, " \n");
v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
if (!v9ses)
return -ENOMEM;
- if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
- dprintk(DEBUG_ERROR, "problem initiating session\n");
- retval = newfid;
- goto out_free_session;
+ fid = v9fs_session_init(v9ses, dev_name, data);
+ if (IS_ERR(fid)) {
+ retval = PTR_ERR(fid);
+ fid = NULL;
+ kfree(v9ses);
+ v9ses = NULL;
+ goto error;
+ }
+
+ st = p9_client_stat(fid);
+ if (IS_ERR(st)) {
+ retval = PTR_ERR(st);
+ goto error;
}
sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
if (IS_ERR(sb)) {
retval = PTR_ERR(sb);
- goto out_close_session;
+ goto error;
}
v9fs_fill_super(sb, v9ses, flags);
inode = v9fs_get_inode(sb, S_IFDIR | mode);
if (IS_ERR(inode)) {
retval = PTR_ERR(inode);
- goto put_back_sb;
+ goto error;
}
inode->i_uid = uid;
@@ -150,54 +157,30 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
root = d_alloc_root(inode);
if (!root) {
retval = -ENOMEM;
- goto put_back_sb;
+ goto error;
}
sb->s_root = root;
+ root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
+ v9fs_stat2inode(st, root->d_inode, sb);
+ v9fs_fid_add(root, fid);
- stat_result = v9fs_t_stat(v9ses, newfid, &fcall);
- if (stat_result < 0) {
- dprintk(DEBUG_ERROR, "stat error\n");
- v9fs_t_clunk(v9ses, newfid);
- } else {
- /* Setup the Root Inode */
- root_fid = v9fs_fid_create(v9ses, newfid);
- if (root_fid == NULL) {
- retval = -ENOMEM;
- goto put_back_sb;
- }
-
- retval = v9fs_fid_insert(root_fid, root);
- if (retval < 0) {
- kfree(fcall);
- goto put_back_sb;
- }
-
- root_fid->qid = fcall->params.rstat.stat.qid;
- root->d_inode->i_ino =
- v9fs_qid2ino(&fcall->params.rstat.stat.qid);
- v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb);
- }
+ return simple_set_mnt(mnt, sb);
- kfree(fcall);
+error:
+ if (fid)
+ p9_client_clunk(fid);
- if (stat_result < 0) {
- retval = stat_result;
- goto put_back_sb;
+ if (v9ses) {
+ v9fs_session_close(v9ses);
+ kfree(v9ses);
}
- return simple_set_mnt(mnt, sb);
-
-out_close_session:
- v9fs_session_close(v9ses);
-out_free_session:
- kfree(v9ses);
- return retval;
+ if (sb) {
+ up_write(&sb->s_umount);
+ deactivate_super(sb);
+ }
-put_back_sb:
- /* deactivate_super calls v9fs_kill_super which will frees the rest */
- up_write(&sb->s_umount);
- deactivate_super(sb);
return retval;
}
@@ -211,7 +194,7 @@ static void v9fs_kill_super(struct super_block *s)
{
struct v9fs_session_info *v9ses = s->s_fs_info;
- dprintk(DEBUG_VFS, " %p\n", s);
+ P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
v9fs_dentry_release(s->s_root); /* clunk root */
@@ -219,7 +202,7 @@ static void v9fs_kill_super(struct super_block *s)
v9fs_session_close(v9ses);
kfree(v9ses);
- dprintk(DEBUG_VFS, "exiting kill_super\n");
+ P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
}
/**
@@ -234,7 +217,7 @@ static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
if (v9ses->debug != 0)
- seq_printf(m, ",debug=%u", v9ses->debug);
+ seq_printf(m, ",debug=%x", v9ses->debug);
if (v9ses->port != V9FS_PORT)
seq_printf(m, ",port=%u", v9ses->port);
if (v9ses->maxdata != 9000)
diff --git a/fs/Kconfig b/fs/Kconfig
index 0fa0c1193e8..94b9d861bf9 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -2048,7 +2048,7 @@ config AFS_DEBUG
config 9P_FS
tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
- depends on INET && EXPERIMENTAL
+ depends on INET && NET_9P && EXPERIMENTAL
help
If you say Y here, you will get experimental support for
Plan 9 resource sharing via the 9P2000 protocol.
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index f544a285592..36e381c6a99 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -33,7 +33,7 @@ const struct file_operations adfs_file_operations = {
.fsync = file_fsync,
.write = do_sync_write,
.aio_write = generic_file_aio_write,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations adfs_file_inode_operations = {
diff --git a/fs/affs/file.c b/fs/affs/file.c
index c8796906f58..c314a35f091 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -35,7 +35,7 @@ const struct file_operations affs_file_operations = {
.open = affs_file_open,
.release = affs_file_release,
.fsync = file_fsync,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations affs_file_inode_operations = {
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 9c0e721d9fc..aede7eb66dd 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -32,7 +32,7 @@ const struct file_operations afs_file_operations = {
.aio_read = generic_file_aio_read,
.aio_write = afs_file_write,
.mmap = generic_file_readonly_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.fsync = afs_fsync,
};
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 2dac3ad2c44..2c55dd94a1d 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -17,6 +17,8 @@
#include <linux/rxrpc.h>
#include <linux/key.h>
#include <linux/workqueue.h>
+#include <linux/sched.h>
+
#include "afs.h"
#include "afs_vl.h"
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 329ee473eed..521ff7caadb 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -114,12 +114,6 @@ static int bad_file_lock(struct file *file, int cmd, struct file_lock *fl)
return -EIO;
}
-static ssize_t bad_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
-{
- return -EIO;
-}
-
static ssize_t bad_file_sendpage(struct file *file, struct page *page,
int off, size_t len, loff_t *pos, int more)
{
@@ -182,7 +176,6 @@ static const struct file_operations bad_file_ops =
.aio_fsync = bad_file_aio_fsync,
.fasync = bad_file_fasync,
.lock = bad_file_lock,
- .sendfile = bad_file_sendfile,
.sendpage = bad_file_sendpage,
.get_unmapped_area = bad_file_get_unmapped_area,
.check_flags = bad_file_check_flags,
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index ef4d1fa04e6..24310e9ee05 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -24,7 +24,7 @@ const struct file_operations bfs_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index fa8ea33ab0b..08e4414b837 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1499,6 +1499,9 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
#endif
int thread_status_size = 0;
elf_addr_t *auxv;
+#ifdef ELF_CORE_WRITE_EXTRA_NOTES
+ int extra_notes_size;
+#endif
/*
* We no longer stop all VM operations.
@@ -1628,7 +1631,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
sz += thread_status_size;
#ifdef ELF_CORE_WRITE_EXTRA_NOTES
- sz += ELF_CORE_EXTRA_NOTES_SIZE;
+ extra_notes_size = ELF_CORE_EXTRA_NOTES_SIZE;
+ sz += extra_notes_size;
#endif
fill_elf_note_phdr(&phdr, sz, offset);
@@ -1674,6 +1678,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
#ifdef ELF_CORE_WRITE_EXTRA_NOTES
ELF_CORE_WRITE_EXTRA_NOTES;
+ foffset += extra_notes_size;
#endif
/* write out the thread status notes section */
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 7b0265d7f3a..861141b4f6d 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -558,7 +558,7 @@ static int load_flat_file(struct linux_binprm * bprm,
if (!realdatastart)
realdatastart = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process data, errno %d\n",
- (int)-datapos);
+ (int)-realdatastart);
do_munmap(current->mm, textpos, text_len);
ret = realdatastart;
goto err;
diff --git a/fs/bio.c b/fs/bio.c
index 093345f0012..33e46340a76 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1223,8 +1223,6 @@ EXPORT_SYMBOL(bio_hw_segments);
EXPORT_SYMBOL(bio_add_page);
EXPORT_SYMBOL(bio_add_pc_page);
EXPORT_SYMBOL(bio_get_nr_vecs);
-EXPORT_SYMBOL(bio_map_user);
-EXPORT_SYMBOL(bio_unmap_user);
EXPORT_SYMBOL(bio_map_kern);
EXPORT_SYMBOL(bio_pair_release);
EXPORT_SYMBOL(bio_split);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index ea1480a16f5..b3e9bfa748c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1346,7 +1346,6 @@ const struct file_operations def_blk_fops = {
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_blkdev_ioctl,
#endif
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 6017c465440..07838b2ac1c 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -7,16 +7,16 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * 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
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
@@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length)
char *charptr = data;
char buf[10], line[80];
- printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
+ printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
label, length, data);
for (i = 0; i < length; i += 16) {
line[0] = 0;
@@ -60,10 +60,10 @@ cifs_dump_mem(char *label, void *data, int length)
#ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr * smb)
{
- cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
+ cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
smb->Command, smb->Status.CifsError,
smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
- cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
+ cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
}
@@ -72,36 +72,35 @@ void cifs_dump_mids(struct TCP_Server_Info * server)
struct list_head *tmp;
struct mid_q_entry * mid_entry;
- if(server == NULL)
+ if (server == NULL)
return;
- cERROR(1,("Dump pending requests:"));
+ cERROR(1, ("Dump pending requests:"));
spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
- if(mid_entry) {
- cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
+ if (mid_entry) {
+ cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
mid_entry->midState,
(int)mid_entry->command,
mid_entry->pid,
mid_entry->tsk,
mid_entry->mid));
#ifdef CONFIG_CIFS_STATS2
- cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
+ cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
mid_entry->largeBuf,
mid_entry->resp_buf,
mid_entry->when_received,
jiffies));
#endif /* STATS2 */
- cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
+ cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
mid_entry->multiEnd));
- if(mid_entry->resp_buf) {
+ if (mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf);
cifs_dump_mem("existing buf: ",
mid_entry->resp_buf,
62 /* fixme */);
}
-
}
}
spin_unlock(&GlobalMid_Lock);
@@ -129,9 +128,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
"Display Internal CIFS Data Structures for Debugging\n"
"---------------------------------------------------\n");
buf += length;
- length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION);
+ length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
buf += length;
- length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid);
+ length = sprintf(buf,
+ "Active VFS Requests: %d\n", GlobalTotalActiveXid);
buf += length;
length = sprintf(buf, "Servers:");
buf += length;
@@ -141,7 +141,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
list_for_each(tmp, &GlobalSMBSessionList) {
i++;
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
- if((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
+ if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
(ses->serverNOS == NULL)) {
buf += sprintf(buf, "\nentry for %s not fully "
"displayed\n\t", ses->serverName);
@@ -149,15 +149,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
} else {
length =
sprintf(buf,
- "\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t",
+ "\n%d) Name: %s Domain: %s Mounts: %d OS:"
+ " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
+ " session status: %d\t",
i, ses->serverName, ses->serverDomain,
atomic_read(&ses->inUse),
ses->serverOS, ses->serverNOS,
- ses->capabilities,ses->status);
+ ses->capabilities, ses->status);
buf += length;
}
- if(ses->server) {
- buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d",
+ if (ses->server) {
+ buf += sprintf(buf, "TCP status: %d\n\tLocal Users To "
+ "Server: %d SecMode: 0x%x Req On Wire: %d",
ses->server->tcpStatus,
atomic_read(&ses->server->socketUseCount),
ses->server->secMode,
@@ -165,7 +168,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
#ifdef CONFIG_CIFS_STATS2
buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
- atomic_read(&ses->server->inSend),
+ atomic_read(&ses->server->inSend),
atomic_read(&ses->server->num_waiters));
#endif
@@ -177,17 +180,19 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
mid_entry = list_entry(tmp1, struct
mid_q_entry,
qhead);
- if(mid_entry) {
- length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",
- mid_entry->midState,
- (int)mid_entry->command,
- mid_entry->pid,
- mid_entry->tsk,
- mid_entry->mid);
+ if (mid_entry) {
+ length = sprintf(buf,
+ "State: %d com: %d pid:"
+ " %d tsk: %p mid %d\n",
+ mid_entry->midState,
+ (int)mid_entry->command,
+ mid_entry->pid,
+ mid_entry->tsk,
+ mid_entry->mid);
buf += length;
}
}
- spin_unlock(&GlobalMid_Lock);
+ spin_unlock(&GlobalMid_Lock);
}
}
@@ -207,7 +212,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
length =
sprintf(buf,
- "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
+ "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
+ "Attributes: 0x%x\nPathComponentMax: %d Status: %d",
i, tcon->treeName,
atomic_read(&tcon->useCount),
tcon->nativeFileSystem,
@@ -215,7 +221,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
le32_to_cpu(tcon->fsAttrInfo.Attributes),
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
tcon->tidStatus);
- buf += length;
+ buf += length;
if (dev_type == FILE_DEVICE_DISK)
length = sprintf(buf, " type: DISK ");
else if (dev_type == FILE_DEVICE_CD_ROM)
@@ -224,7 +230,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
length =
sprintf(buf, " type: %d ", dev_type);
buf += length;
- if(tcon->tidStatus == CifsNeedReconnect) {
+ if (tcon->tidStatus == CifsNeedReconnect) {
buf += sprintf(buf, "\tDISCONNECTED ");
length += 14;
}
@@ -238,9 +244,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
/* Now calculate total size of returned data */
length = buf - original_buf;
- if(offset + count >= length)
+ if (offset + count >= length)
*eof = 1;
- if(length < offset) {
+ if (length < offset) {
*eof = 1;
return 0;
} else {
@@ -256,18 +262,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
static int
cifs_stats_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+ unsigned long count, void *data)
{
- char c;
- int rc;
+ char c;
+ int rc;
struct list_head *tmp;
struct cifsTconInfo *tcon;
- rc = get_user(c, buffer);
- if (rc)
- return rc;
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
- if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
+ if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
read_lock(&GlobalSMBSeslock);
#ifdef CONFIG_CIFS_STATS2
atomic_set(&totBufAllocCount, 0);
@@ -297,14 +303,14 @@ cifs_stats_write(struct file *file, const char __user *buffer,
read_unlock(&GlobalSMBSeslock);
}
- return count;
+ return count;
}
static int
cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
int count, int *eof, void *data)
{
- int item_length,i,length;
+ int item_length, i, length;
struct list_head *tmp;
struct cifsTconInfo *tcon;
@@ -314,44 +320,44 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
"Resources in use\nCIFS Session: %d\n",
sesInfoAllocCount.counter);
buf += length;
- item_length =
- sprintf(buf,"Share (unique mount targets): %d\n",
+ item_length =
+ sprintf(buf, "Share (unique mount targets): %d\n",
tconInfoAllocCount.counter);
length += item_length;
- buf += item_length;
- item_length =
- sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n",
+ buf += item_length;
+ item_length =
+ sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n",
bufAllocCount.counter,
cifs_min_rcv + tcpSesAllocCount.counter);
length += item_length;
buf += item_length;
- item_length =
- sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n",
- smBufAllocCount.counter,cifs_min_small);
+ item_length =
+ sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
+ smBufAllocCount.counter, cifs_min_small);
length += item_length;
buf += item_length;
#ifdef CONFIG_CIFS_STATS2
- item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
+ item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
atomic_read(&totBufAllocCount),
- atomic_read(&totSmBufAllocCount));
+ atomic_read(&totSmBufAllocCount));
length += item_length;
buf += item_length;
#endif /* CONFIG_CIFS_STATS2 */
- item_length =
- sprintf(buf,"Operations (MIDs): %d\n",
+ item_length =
+ sprintf(buf, "Operations (MIDs): %d\n",
midCount.counter);
length += item_length;
buf += item_length;
item_length = sprintf(buf,
"\n%d session %d share reconnects\n",
- tcpSesReconnectCount.counter,tconInfoReconnectCount.counter);
+ tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
length += item_length;
buf += item_length;
item_length = sprintf(buf,
"Total vfs operations: %d maximum at one time: %d\n",
- GlobalCurrentXid,GlobalMaxActiveXid);
+ GlobalCurrentXid, GlobalMaxActiveXid);
length += item_length;
buf += item_length;
@@ -360,10 +366,10 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
list_for_each(tmp, &GlobalTreeConnectionList) {
i++;
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
- item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName);
+ item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName);
buf += item_length;
length += item_length;
- if(tcon->tidStatus == CifsNeedReconnect) {
+ if (tcon->tidStatus == CifsNeedReconnect) {
buf += sprintf(buf, "\tDISCONNECTED ");
length += 14;
}
@@ -380,15 +386,15 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
atomic_read(&tcon->num_writes),
(long long)(tcon->bytes_written));
- buf += item_length;
- length += item_length;
- item_length = sprintf(buf,
+ buf += item_length;
+ length += item_length;
+ item_length = sprintf(buf,
"\nLocks: %d HardLinks: %d Symlinks: %d",
- atomic_read(&tcon->num_locks),
+ atomic_read(&tcon->num_locks),
atomic_read(&tcon->num_hardlinks),
atomic_read(&tcon->num_symlinks));
- buf += item_length;
- length += item_length;
+ buf += item_length;
+ length += item_length;
item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
atomic_read(&tcon->num_opens),
@@ -415,12 +421,12 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
}
read_unlock(&GlobalSMBSeslock);
- buf += sprintf(buf,"\n");
+ buf += sprintf(buf, "\n");
length++;
- if(offset + count >= length)
+ if (offset + count >= length)
*eof = 1;
- if(length < offset) {
+ if (length < offset) {
*eof = 1;
return 0;
} else {
@@ -428,7 +434,7 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
}
if (length > count)
length = count;
-
+
return length;
}
#endif
@@ -547,11 +553,11 @@ cifs_proc_clean(void)
remove_proc_entry("MultiuserMount", proc_fs_cifs);
remove_proc_entry("OplockEnabled", proc_fs_cifs);
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
- remove_proc_entry("SecurityFlags",proc_fs_cifs);
-/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
- remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
- remove_proc_entry("Experimental",proc_fs_cifs);
- remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
+ remove_proc_entry("SecurityFlags", proc_fs_cifs);
+/* remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */
+ remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
+ remove_proc_entry("Experimental", proc_fs_cifs);
+ remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
remove_proc_entry("cifs", proc_root_fs);
}
@@ -590,7 +596,7 @@ cifsFYI_write(struct file *file, const char __user *buffer,
cifsFYI = 0;
else if (c == '1' || c == 'y' || c == 'Y')
cifsFYI = 1;
- else if((c > '1') && (c <= '9'))
+ else if ((c > '1') && (c <= '9'))
cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
return count;
@@ -637,28 +643,28 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
static int
experimEnabled_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
- int len;
+ int len;
- len = sprintf(page, "%d\n", experimEnabled);
+ len = sprintf(page, "%d\n", experimEnabled);
- len -= off;
- *start = page + off;
+ len -= off;
+ *start = page + off;
- if (len > count)
- len = count;
- else
- *eof = 1;
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
- if (len < 0)
- len = 0;
+ if (len < 0)
+ len = 0;
- return len;
+ return len;
}
static int
experimEnabled_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+ unsigned long count, void *data)
{
char c;
int rc;
@@ -678,46 +684,46 @@ experimEnabled_write(struct file *file, const char __user *buffer,
static int
linuxExtensionsEnabled_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
- int len;
+ int len;
- len = sprintf(page, "%d\n", linuxExtEnabled);
- len -= off;
- *start = page + off;
+ len = sprintf(page, "%d\n", linuxExtEnabled);
+ len -= off;
+ *start = page + off;
- if (len > count)
- len = count;
- else
- *eof = 1;
+ if (len > count)
+ len = count;
+ else
+ *eof = 1;
- if (len < 0)
- len = 0;
+ if (len < 0)
+ len = 0;
- return len;
+ return len;
}
static int
linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+ unsigned long count, void *data)
{
- char c;
- int rc;
-
- rc = get_user(c, buffer);
- if (rc)
- return rc;
- if (c == '0' || c == 'n' || c == 'N')
- linuxExtEnabled = 0;
- else if (c == '1' || c == 'y' || c == 'Y')
- linuxExtEnabled = 1;
-
- return count;
+ char c;
+ int rc;
+
+ rc = get_user(c, buffer);
+ if (rc)
+ return rc;
+ if (c == '0' || c == 'n' || c == 'N')
+ linuxExtEnabled = 0;
+ else if (c == '1' || c == 'y' || c == 'Y')
+ linuxExtEnabled = 1;
+
+ return count;
}
static int
lookupFlag_read(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
int len;
@@ -860,15 +866,15 @@ security_flags_write(struct file *file, const char __user *buffer,
char flags_string[12];
char c;
- if((count < 1) || (count > 11))
+ if ((count < 1) || (count > 11))
return -EINVAL;
memset(flags_string, 0, 12);
- if(copy_from_user(flags_string, buffer, count))
+ if (copy_from_user(flags_string, buffer, count))
return -EFAULT;
- if(count < 3) {
+ if (count < 3) {
/* single char or single char followed by null */
c = flags_string[0];
if (c == '0' || c == 'n' || c == 'N')
@@ -881,15 +887,15 @@ security_flags_write(struct file *file, const char __user *buffer,
flags = simple_strtoul(flags_string, NULL, 0);
- cFYI(1,("sec flags 0x%x", flags));
+ cFYI(1, ("sec flags 0x%x", flags));
- if(flags <= 0) {
- cERROR(1,("invalid security flags %s",flags_string));
+ if (flags <= 0) {
+ cERROR(1, ("invalid security flags %s", flags_string));
return -EINVAL;
}
- if(flags & ~CIFSSEC_MASK) {
- cERROR(1,("attempt to set unsupported security flags 0x%x",
+ if (flags & ~CIFSSEC_MASK) {
+ cERROR(1, ("attempt to set unsupported security flags 0x%x",
flags & ~CIFSSEC_MASK));
return -EINVAL;
}
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 793c4b95c16..701e9a9185f 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -6,16 +6,16 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * 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
+ * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/fs.h>
@@ -32,7 +32,7 @@
*
*/
int
-cifs_strfromUCS_le(char *to, const __le16 * from,
+cifs_strfromUCS_le(char *to, const __le16 * from,
int len, const struct nls_table *codepage)
{
int i;
@@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
{
int charlen;
int i;
- wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
+ wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
@@ -79,7 +79,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
/* A question mark */
to[i] = cpu_to_le16(0x003f);
charlen = 1;
- } else
+ } else
to[i] = cpu_to_le16(wchar_to[i]);
}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d38c69b591c..8b0cbf4a4ad 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -616,7 +616,7 @@ const struct file_operations cifs_file_ops = {
.fsync = cifs_fsync,
.flush = cifs_flush,
.mmap = cifs_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
@@ -637,7 +637,7 @@ const struct file_operations cifs_file_direct_ops = {
.lock = cifs_lock,
.fsync = cifs_fsync,
.flush = cifs_flush,
- .sendfile = generic_file_sendfile, /* BB removeme BB */
+ .splice_read = generic_file_splice_read,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
@@ -656,7 +656,7 @@ const struct file_operations cifs_file_nobrl_ops = {
.fsync = cifs_fsync,
.flush = cifs_flush,
.mmap = cifs_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
@@ -676,7 +676,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
.release = cifs_close,
.fsync = cifs_fsync,
.flush = cifs_flush,
- .sendfile = generic_file_sendfile, /* BB removeme BB */
+ .splice_read = generic_file_splice_read,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
@@ -825,8 +825,8 @@ cifs_init_mids(void)
sizeof (struct oplock_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (cifs_oplock_cachep == NULL) {
- kmem_cache_destroy(cifs_mid_cachep);
mempool_destroy(cifs_mid_poolp);
+ kmem_cache_destroy(cifs_mid_cachep);
return -ENOMEM;
}
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 14de58fa143..57419a17668 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -433,8 +433,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
cFYI(1,("secFlags 0x%x",secFlags));
pSMB->hdr.Mid = GetNextMid(server);
- pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
- if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
+ pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
+ if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
count = 0;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 216fb625843..f4e92661b22 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2069,8 +2069,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
srvTcp->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
if (srvTcp->tsk) {
+ struct task_struct *tsk;
+ /* If we could verify that kthread_stop would
+ always wake up processes blocked in
+ tcp in recv_mesg then we could remove the
+ send_sig call */
send_sig(SIGKILL,srvTcp->tsk,1);
- kthread_stop(srvTcp->tsk);
+ tsk = srvTcp->tsk;
+ if(tsk)
+ kthread_stop(tsk);
}
}
/* If find_unc succeeded then rc == 0 so we can not end */
@@ -2085,8 +2092,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* if the socketUseCount is now zero */
if ((temp_rc == -ESHUTDOWN) &&
(pSesInfo->server) && (pSesInfo->server->tsk)) {
+ struct task_struct *tsk;
send_sig(SIGKILL,pSesInfo->server->tsk,1);
- kthread_stop(pSesInfo->server->tsk);
+ tsk = pSesInfo->server->tsk;
+ if (tsk)
+ kthread_stop(tsk);
}
} else
cFYI(1, ("No session or bad tcon"));
@@ -3334,7 +3344,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
return 0;
} else if (rc == -ESHUTDOWN) {
cFYI(1,("Waking up socket by sending it signal"));
- if(cifsd_task) {
+ if (cifsd_task) {
send_sig(SIGKILL,cifsd_task,1);
kthread_stop(cifsd_task);
}
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e5210519ac4..8e86aaceb68 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -2,7 +2,7 @@
* fs/cifs/dir.c
*
* vfs operations that deal with dentries
- *
+ *
* Copyright (C) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com)
*
@@ -34,11 +34,12 @@
static void
renew_parental_timestamps(struct dentry *direntry)
{
- /* BB check if there is a way to get the kernel to do this or if we really need this */
+ /* BB check if there is a way to get the kernel to do this or if we
+ really need this */
do {
direntry->d_time = jiffies;
direntry = direntry->d_parent;
- } while (!IS_ROOT(direntry));
+ } while (!IS_ROOT(direntry));
}
/* Note: caller must free return buffer */
@@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry)
char *full_path;
char dirsep;
- if(direntry == NULL)
+ if (direntry == NULL)
return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly
when the server crashed */
@@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry)
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
pplen = CIFS_SB(direntry->d_sb)->prepathlen;
cifs_bp_rename_retry:
- namelen = pplen;
+ namelen = pplen;
for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len);
temp = temp->d_parent;
- if(temp == NULL) {
- cERROR(1,("corrupt dentry"));
+ if (temp == NULL) {
+ cERROR(1, ("corrupt dentry"));
return NULL;
}
}
full_path = kmalloc(namelen+1, GFP_KERNEL);
- if(full_path == NULL)
+ if (full_path == NULL)
return full_path;
full_path[namelen] = 0; /* trailing null */
for (temp = direntry; !IS_ROOT(temp);) {
@@ -84,8 +85,8 @@ cifs_bp_rename_retry:
cFYI(0, ("name: %s", full_path + namelen));
}
temp = temp->d_parent;
- if(temp == NULL) {
- cERROR(1,("corrupt dentry"));
+ if (temp == NULL) {
+ cERROR(1, ("corrupt dentry"));
kfree(full_path);
return NULL;
}
@@ -94,7 +95,7 @@ cifs_bp_rename_retry:
cERROR(1,
("did not end path lookup where expected namelen is %d",
namelen));
- /* presumably this is only possible if racing with a rename
+ /* presumably this is only possible if racing with a rename
of one of the parent directories (we can not lock the dentries
above us to prevent this, but retrying should be harmless) */
kfree(full_path);
@@ -106,7 +107,7 @@ cifs_bp_rename_retry:
since the '\' is a valid posix character so we can not switch
those safely to '/' if any are found in the middle of the prepath */
/* BB test paths to Windows with '/' in the midst of prepath */
- strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen);
+ strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen);
return full_path;
}
@@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return -ENOMEM;
}
- if(nd && (nd->flags & LOOKUP_OPEN)) {
+ if (nd && (nd->flags & LOOKUP_OPEN)) {
int oflags = nd->intent.open.flags;
desiredAccess = 0;
@@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
write_only = TRUE;
}
- if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+ if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
disposition = FILE_CREATE;
- else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+ else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
disposition = FILE_OVERWRITE_IF;
- else if((oflags & O_CREAT) == O_CREAT)
+ else if ((oflags & O_CREAT) == O_CREAT)
disposition = FILE_OPEN_IF;
else {
- cFYI(1,("Create flag not set in create function"));
+ cFYI(1, ("Create flag not set in create function"));
}
}
- /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */
+ /* BB add processing to set equivalent of mode - e.g. via CreateX with
+ ACLs */
if (oplockEnabled)
oplock = REQ_OPLOCK;
- buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf == NULL) {
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (buf == NULL) {
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
}
- if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+ if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
@@ -193,27 +195,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
else
rc = -EIO; /* no NT SMB support fall into legacy open below */
- if(rc == -EIO) {
+ if (rc == -EIO) {
/* old server, retry the open legacy style */
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
- }
+ }
if (rc) {
cFYI(1, ("cifs_create returned 0x%x", rc));
} else {
/* If Open reported that we actually created a file
then we now have to set the mode if possible */
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
- (oplock & CIFS_CREATE_ACTION))
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ (oplock & CIFS_CREATE_ACTION)) {
+ mode &= ~current->fs->umask;
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)current->fsuid,
(__u64)current->fsgid,
0 /* dev */,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
} else {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
@@ -221,26 +224,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
(__u64)-1,
0 /* dev */,
cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
}
- else {
- /* BB implement mode setting via Windows security descriptors */
- /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
- /* could set r/o dos attribute if mode & 0222 == 0 */
+ } else {
+ /* BB implement mode setting via Windows security
+ descriptors e.g. */
+ /* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/
+
+ /* Could set r/o dos attribute if mode & 0222 == 0 */
}
/* BB server might mask mode so we have to query for Unix case*/
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newinode, full_path,
- inode->i_sb,xid);
+ inode->i_sb, xid);
else {
rc = cifs_get_inode_info(&newinode, full_path,
- buf, inode->i_sb,xid);
- if(newinode) {
+ buf, inode->i_sb, xid);
+ if (newinode) {
newinode->i_mode = mode;
- if((oplock & CIFS_CREATE_ACTION) &&
- (cifs_sb->mnt_cifs_flags &
+ if ((oplock & CIFS_CREATE_ACTION) &&
+ (cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_SET_UID)) {
newinode->i_uid = current->fsuid;
newinode->i_gid = current->fsgid;
@@ -259,14 +264,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode);
}
- if((nd->flags & LOOKUP_OPEN) == FALSE) {
+ if ((nd->flags & LOOKUP_OPEN) == FALSE) {
/* mknod case - do not leave file open */
CIFSSMBClose(xid, pTcon, fileHandle);
- } else if(newinode) {
+ } else if (newinode) {
pCifsFile =
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
-
- if(pCifsFile == NULL)
+
+ if (pCifsFile == NULL)
goto cifs_create_out;
pCifsFile->netfid = fileHandle;
pCifsFile->pid = current->tgid;
@@ -276,33 +281,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
init_MUTEX(&pCifsFile->fh_sem);
mutex_init(&pCifsFile->lock_mutex);
INIT_LIST_HEAD(&pCifsFile->llist);
- atomic_set(&pCifsFile->wrtPending,0);
+ atomic_set(&pCifsFile->wrtPending, 0);
- /* set the following in open now
+ /* set the following in open now
pCifsFile->pfile = file; */
write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist,&pTcon->openFileList);
+ list_add(&pCifsFile->tlist, &pTcon->openFileList);
pCifsInode = CIFS_I(newinode);
- if(pCifsInode) {
+ if (pCifsInode) {
/* if readable file instance put first in list*/
if (write_only == TRUE) {
- list_add_tail(&pCifsFile->flist,
+ list_add_tail(&pCifsFile->flist,
&pCifsInode->openFileList);
} else {
list_add(&pCifsFile->flist,
&pCifsInode->openFileList);
}
- if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE;
- cFYI(1,("Exclusive Oplock for inode %p",
+ cFYI(1, ("Exclusive Oplock inode %p",
newinode));
- } else if((oplock & 0xF) == OPLOCK_READ)
+ } else if ((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE;
}
write_unlock(&GlobalSMBSeslock);
}
- }
+ }
cifs_create_out:
kfree(buf);
kfree(full_path);
@@ -310,8 +315,8 @@ cifs_create_out:
return rc;
}
-int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
- dev_t device_number)
+int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
+ dev_t device_number)
{
int rc = -EPERM;
int xid;
@@ -329,43 +334,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry);
- if(full_path == NULL)
+ if (full_path == NULL)
rc = -ENOMEM;
else if (pTcon->ses->capabilities & CAP_UNIX) {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ mode &= ~current->fs->umask;
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
- mode,(__u64)current->fsuid,(__u64)current->fsgid,
+ mode, (__u64)current->fsuid,
+ (__u64)current->fsgid,
device_number, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
} else {
rc = CIFSSMBUnixSetPerms(xid, pTcon,
full_path, mode, (__u64)-1, (__u64)-1,
device_number, cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
}
- if(!rc) {
+ if (!rc) {
rc = cifs_get_inode_info_unix(&newinode, full_path,
- inode->i_sb,xid);
+ inode->i_sb, xid);
if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops;
else
direntry->d_op = &cifs_dentry_ops;
- if(rc == 0)
+ if (rc == 0)
d_instantiate(direntry, newinode);
}
} else {
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
int oplock = 0;
u16 fileHandle;
FILE_ALL_INFO * buf;
- cFYI(1,("sfu compat create special file"));
+ cFYI(1, ("sfu compat create special file"));
- buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
- if(buf == NULL) {
+ buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (buf == NULL) {
kfree(full_path);
FreeXid(xid);
return -ENOMEM;
@@ -373,39 +380,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
rc = CIFSSMBOpen(xid, pTcon, full_path,
FILE_CREATE, /* fail if exists */
- GENERIC_WRITE /* BB would
+ GENERIC_WRITE /* BB would
WRITE_OWNER | WRITE_DAC be better? */,
/* Create a file and set the
file attribute to SYSTEM */
CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
&fileHandle, &oplock, buf,
cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
+ cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB FIXME - add handling for backlevel servers
which need legacy open and check for all
- calls to SMBOpen for fallback to
- SMBLeagcyOpen */
- if(!rc) {
+ calls to SMBOpen for fallback to SMBLeagcyOpen */
+ if (!rc) {
/* BB Do not bother to decode buf since no
local inode yet to put timestamps in,
but we can reuse it safely */
int bytes_written;
struct win_dev *pdev;
pdev = (struct win_dev *)buf;
- if(S_ISCHR(mode)) {
+ if (S_ISCHR(mode)) {
memcpy(pdev->type, "IntxCHR", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
- pdev->minor =
+ pdev->minor =
cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon,
fileHandle,
sizeof(struct win_dev),
0, &bytes_written, (char *)pdev,
NULL, 0);
- } else if(S_ISBLK(mode)) {
+ } else if (S_ISBLK(mode)) {
memcpy(pdev->type, "IntxBLK", 8);
pdev->major =
cpu_to_le64(MAJOR(device_number));
@@ -432,7 +438,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
struct dentry *
-cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
+ struct nameidata *nd)
{
int xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */
@@ -447,8 +454,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
(" parent inode = 0x%p name is: %s and dentry = 0x%p",
parent_dir_inode, direntry->d_name.name, direntry));
- /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
-
/* check whether path exists */
cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
@@ -472,7 +477,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */
full_path = build_path_from_dentry(direntry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
FreeXid(xid);
return ERR_PTR(-ENOMEM);
}
@@ -487,10 +492,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newInode, full_path,
- parent_dir_inode->i_sb,xid);
+ parent_dir_inode->i_sb, xid);
else
rc = cifs_get_inode_info(&newInode, full_path, NULL,
- parent_dir_inode->i_sb,xid);
+ parent_dir_inode->i_sb, xid);
if ((rc == 0) && (newInode != NULL)) {
if (pTcon->nocase)
@@ -499,7 +504,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
direntry->d_op = &cifs_dentry_ops;
d_add(direntry, newInode);
- /* since paths are not looked up by component - the parent
+ /* since paths are not looked up by component - the parent
directories are presumed to be good here */
renew_parental_timestamps(direntry);
@@ -511,13 +516,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
else
direntry->d_op = &cifs_dentry_ops;
d_add(direntry, NULL);
- /* if it was once a directory (but how can we tell?) we could do
- shrink_dcache_parent(direntry); */
+ /* if it was once a directory (but how can we tell?) we could do
+ shrink_dcache_parent(direntry); */
} else {
- cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
- rc,full_path));
- /* BB special case check for Access Denied - watch security
- exposure of returning dir info implicitly via different rc
+ cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s",
+ rc, full_path));
+ /* BB special case check for Access Denied - watch security
+ exposure of returning dir info implicitly via different rc
if file exists or not but no access BB */
}
@@ -538,11 +543,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
} else {
cFYI(1, ("neg dentry 0x%p name = %s",
direntry, direntry->d_name.name));
- if(time_after(jiffies, direntry->d_time + HZ) ||
+ if (time_after(jiffies, direntry->d_time + HZ) ||
!lookupCacheEnabled) {
d_drop(direntry);
isValid = 0;
- }
+ }
}
return isValid;
@@ -559,8 +564,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
struct dentry_operations cifs_dentry_ops = {
.d_revalidate = cifs_d_revalidate,
-/* d_delete: cifs_d_delete, *//* not needed except for debugging */
- /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
+/* d_delete: cifs_d_delete, */ /* not needed except for debugging */
};
static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index da12b482ebe..8e375bb4b37 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -2,7 +2,7 @@
* fs/cifs/fcntl.c
*
* vfs operations that deal with the file control API
- *
+ *
* Copyright (C) International Business Machines Corp., 2003,2004
* Author(s): Steve French (sfrench@us.ibm.com)
*
@@ -35,35 +35,34 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
/* No way on Linux VFS to ask to monitor xattr
changes (and no stream support either */
- if(fcntl_notify_flags & DN_ACCESS) {
+ if (fcntl_notify_flags & DN_ACCESS) {
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
- if(fcntl_notify_flags & DN_MODIFY) {
+ if (fcntl_notify_flags & DN_MODIFY) {
/* What does this mean on directories? */
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_SIZE;
}
- if(fcntl_notify_flags & DN_CREATE) {
- cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
+ if (fcntl_notify_flags & DN_CREATE) {
+ cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_LAST_WRITE;
}
- if(fcntl_notify_flags & DN_DELETE) {
+ if (fcntl_notify_flags & DN_DELETE) {
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
}
- if(fcntl_notify_flags & DN_RENAME) {
+ if (fcntl_notify_flags & DN_RENAME) {
/* BB review this - checking various server behaviors */
- cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
+ cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_FILE_NAME;
}
- if(fcntl_notify_flags & DN_ATTRIB) {
- cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
+ if (fcntl_notify_flags & DN_ATTRIB) {
+ cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
FILE_NOTIFY_CHANGE_ATTRIBUTES;
}
-/* if(fcntl_notify_flags & DN_MULTISHOT) {
+/* if (fcntl_notify_flags & DN_MULTISHOT) {
cifs_ntfy_flags |= ;
} */ /* BB fixme - not sure how to handle this with CIFS yet */
-
return cifs_ntfy_flags;
}
@@ -78,8 +77,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
__u16 netfid;
-
- if(experimEnabled == 0)
+ if (experimEnabled == 0)
return 0;
xid = GetXid();
@@ -88,21 +86,21 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
full_path = build_path_from_dentry(file->f_path.dentry);
- if(full_path == NULL) {
+ if (full_path == NULL) {
rc = -ENOMEM;
} else {
- cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg));
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
+ cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg));
+ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
- &netfid, &oplock,NULL, cifs_sb->local_nls,
+ &netfid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB fixme - add this handle to a notify handle list */
- if(rc) {
- cFYI(1,("Could not open directory for notify"));
+ if (rc) {
+ cFYI(1, ("Could not open directory for notify"));
} else {
filter = convert_to_cifs_notify_flags(arg);
- if(filter != 0) {
- rc = CIFSSMBNotify(xid, pTcon,
+ if (filter != 0) {
+ rc = CIFSSMBNotify(xid, pTcon,
0 /* no subdirs */, netfid,
filter, file, arg & DN_MULTISHOT,
cifs_sb->local_nls);
@@ -113,10 +111,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
it would close automatically but may be a way
to do it easily when inode freed or when
notify info is cleared/changed */
- cFYI(1,("notify rc %d",rc));
+ cFYI(1, ("notify rc %d", rc));
}
}
-
+
FreeXid(xid);
return rc;
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 3e87dad3367..f0ff12b3f39 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -986,7 +986,8 @@ mkdir_get_info:
* failed to get it from the server or was set bogus */
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
direntry->d_inode->i_nlink = 2;
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
+ if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
+ mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode,
@@ -1004,7 +1005,7 @@ mkdir_get_info:
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
}
- else {
+ } else {
/* BB to be implemented via Windows secrty descriptors
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
-1, -1, local_nls); */
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index e34c7db00f6..a414f1775ae 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -30,7 +30,7 @@
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
-int cifs_ioctl (struct inode * inode, struct file * filep,
+int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg)
{
int rc = -ENOTTY; /* strange error - but the precedent */
@@ -47,13 +47,13 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
xid = GetXid();
- cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg));
+ cFYI(1, ("ioctl file %p cmd %u arg %lu", filep, command, arg));
cifs_sb = CIFS_SB(inode->i_sb);
#ifdef CONFIG_CIFS_POSIX
tcon = cifs_sb->tcon;
- if(tcon)
+ if (tcon)
caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
else {
rc = -EIO;
@@ -62,24 +62,24 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
}
#endif /* CONFIG_CIFS_POSIX */
- switch(command) {
+ switch (command) {
case CIFS_IOC_CHECKUMOUNT:
- cFYI(1,("User unmount attempted"));
- if(cifs_sb->mnt_uid == current->uid)
+ cFYI(1, ("User unmount attempted"));
+ if (cifs_sb->mnt_uid == current->uid)
rc = 0;
else {
rc = -EACCES;
- cFYI(1,("uids do not match"));
+ cFYI(1, ("uids do not match"));
}
break;
#ifdef CONFIG_CIFS_POSIX
case FS_IOC_GETFLAGS:
- if(CIFS_UNIX_EXTATTR_CAP & caps) {
+ if (CIFS_UNIX_EXTATTR_CAP & caps) {
if (pSMBFile == NULL)
break;
rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
&ExtAttrBits, &ExtAttrMask);
- if(rc == 0)
+ if (rc == 0)
rc = put_user(ExtAttrBits &
FS_FL_USER_VISIBLE,
(int __user *)arg);
@@ -87,8 +87,8 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
break;
case FS_IOC_SETFLAGS:
- if(CIFS_UNIX_EXTATTR_CAP & caps) {
- if(get_user(ExtAttrBits,(int __user *)arg)) {
+ if (CIFS_UNIX_EXTATTR_CAP & caps) {
+ if (get_user(ExtAttrBits, (int __user *)arg)) {
rc = -EFAULT;
break;
}
@@ -96,16 +96,15 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
break;
/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
extAttrBits, &ExtAttrMask);*/
-
}
- cFYI(1,("set flags not implemented yet"));
+ cFYI(1, ("set flags not implemented yet"));
break;
#endif /* CONFIG_CIFS_POSIX */
default:
- cFYI(1,("unsupported ioctl"));
+ cFYI(1, ("unsupported ioctl"));
break;
}
FreeXid(xid);
return rc;
-}
+}
diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h
index aede606132a..8b69fcceb59 100644
--- a/fs/cifs/rfc1002pdu.h
+++ b/fs/cifs/rfc1002pdu.h
@@ -18,7 +18,7 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 9ddf5ed6216..898a86dde8f 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -470,7 +470,7 @@ int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
ret = -ENOENT;
if (!IS_DEADDIR(host_inode)) {
- ret = host_file->f_op->readdir(host_file, filldir, dirent);
+ ret = host_file->f_op->readdir(host_file, dirent, filldir);
file_accessed(host_file);
}
}
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 5ef2b609ec7..99dbe866816 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -47,8 +47,9 @@ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *p
}
static ssize_t
-coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
- read_actor_t actor, void *target)
+coda_file_splice_read(struct file *coda_file, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t count,
+ unsigned int flags)
{
struct coda_file_info *cfi;
struct file *host_file;
@@ -57,10 +58,10 @@ coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
- if (!host_file->f_op || !host_file->f_op->sendfile)
+ if (!host_file->f_op || !host_file->f_op->splice_read)
return -EINVAL;
- return host_file->f_op->sendfile(host_file, ppos, count, actor, target);
+ return host_file->f_op->splice_read(host_file, ppos, pipe, count,flags);
}
static ssize_t
@@ -295,6 +296,6 @@ const struct file_operations coda_file_operations = {
.flush = coda_flush,
.release = coda_release,
.fsync = coda_fsync,
- .sendfile = coda_file_sendfile,
+ .splice_read = coda_file_splice_read,
};
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index ec8896b264d..1d533a2ec3a 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -368,6 +368,69 @@ void debugfs_remove(struct dentry *dentry)
}
EXPORT_SYMBOL_GPL(debugfs_remove);
+/**
+ * debugfs_rename - rename a file/directory in the debugfs filesystem
+ * @old_dir: a pointer to the parent dentry for the renamed object. This
+ * should be a directory dentry.
+ * @old_dentry: dentry of an object to be renamed.
+ * @new_dir: a pointer to the parent dentry where the object should be
+ * moved. This should be a directory dentry.
+ * @new_name: a pointer to a string containing the target name.
+ *
+ * This function renames a file/directory in debugfs. The target must not
+ * exist for rename to succeed.
+ *
+ * This function will return a pointer to old_dentry (which is updated to
+ * reflect renaming) if it succeeds. If an error occurs, %NULL will be
+ * returned.
+ *
+ * If debugfs is not enabled in the kernel, the value -%ENODEV will be
+ * returned.
+ */
+struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+ struct dentry *new_dir, const char *new_name)
+{
+ int error;
+ struct dentry *dentry = NULL, *trap;
+ const char *old_name;
+
+ trap = lock_rename(new_dir, old_dir);
+ /* Source or destination directories don't exist? */
+ if (!old_dir->d_inode || !new_dir->d_inode)
+ goto exit;
+ /* Source does not exist, cyclic rename, or mountpoint? */
+ if (!old_dentry->d_inode || old_dentry == trap ||
+ d_mountpoint(old_dentry))
+ goto exit;
+ dentry = lookup_one_len(new_name, new_dir, strlen(new_name));
+ /* Lookup failed, cyclic rename or target exists? */
+ if (IS_ERR(dentry) || dentry == trap || dentry->d_inode)
+ goto exit;
+
+ old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+
+ error = simple_rename(old_dir->d_inode, old_dentry, new_dir->d_inode,
+ dentry);
+ if (error) {
+ fsnotify_oldname_free(old_name);
+ goto exit;
+ }
+ d_move(old_dentry, dentry);
+ fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name,
+ old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode),
+ NULL, old_dentry->d_inode);
+ fsnotify_oldname_free(old_name);
+ unlock_rename(new_dir, old_dir);
+ dput(dentry);
+ return old_dentry;
+exit:
+ if (dentry && !IS_ERR(dentry))
+ dput(dentry);
+ unlock_rename(new_dir, old_dir);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(debugfs_rename);
+
static decl_subsys(debug, NULL, NULL);
static int __init debugfs_init(void)
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 8593f3dfd29..52bb2638f7a 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1106,7 +1106,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
spin_lock_irqsave(&dio->bio_lock, flags);
ret2 = --dio->refcount;
spin_unlock_irqrestore(&dio->bio_lock, flags);
- BUG_ON(!dio->is_async && ret2 != 0);
+
if (ret2 == 0) {
ret = dio_complete(dio, offset, ret);
kfree(dio);
diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig
index 69a94690e49..54bcc00ec8d 100644
--- a/fs/dlm/Kconfig
+++ b/fs/dlm/Kconfig
@@ -3,7 +3,7 @@ menu "Distributed Lock Manager"
config DLM
tristate "Distributed Lock Manager (DLM)"
- depends on IPV6 || IPV6=n
+ depends on SYSFS && (IPV6 || IPV6=n)
select CONFIGFS_FS
select IP_SCTP
help
diff --git a/fs/dlm/Makefile b/fs/dlm/Makefile
index 604cf7dc5f3..d248e60951b 100644
--- a/fs/dlm/Makefile
+++ b/fs/dlm/Makefile
@@ -8,6 +8,7 @@ dlm-y := ast.o \
member.o \
memory.o \
midcomms.o \
+ netlink.o \
lowcomms.o \
rcom.o \
recover.o \
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 822abdcd143..5069b2cb5a1 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -90,6 +90,7 @@ struct cluster {
unsigned int cl_scan_secs;
unsigned int cl_log_debug;
unsigned int cl_protocol;
+ unsigned int cl_timewarn_cs;
};
enum {
@@ -103,6 +104,7 @@ enum {
CLUSTER_ATTR_SCAN_SECS,
CLUSTER_ATTR_LOG_DEBUG,
CLUSTER_ATTR_PROTOCOL,
+ CLUSTER_ATTR_TIMEWARN_CS,
};
struct cluster_attribute {
@@ -162,6 +164,7 @@ CLUSTER_ATTR(toss_secs, 1);
CLUSTER_ATTR(scan_secs, 1);
CLUSTER_ATTR(log_debug, 0);
CLUSTER_ATTR(protocol, 0);
+CLUSTER_ATTR(timewarn_cs, 1);
static struct configfs_attribute *cluster_attrs[] = {
[CLUSTER_ATTR_TCP_PORT] = &cluster_attr_tcp_port.attr,
@@ -174,6 +177,7 @@ static struct configfs_attribute *cluster_attrs[] = {
[CLUSTER_ATTR_SCAN_SECS] = &cluster_attr_scan_secs.attr,
[CLUSTER_ATTR_LOG_DEBUG] = &cluster_attr_log_debug.attr,
[CLUSTER_ATTR_PROTOCOL] = &cluster_attr_protocol.attr,
+ [CLUSTER_ATTR_TIMEWARN_CS] = &cluster_attr_timewarn_cs.attr,
NULL,
};
@@ -429,6 +433,8 @@ static struct config_group *make_cluster(struct config_group *g,
cl->cl_toss_secs = dlm_config.ci_toss_secs;
cl->cl_scan_secs = dlm_config.ci_scan_secs;
cl->cl_log_debug = dlm_config.ci_log_debug;
+ cl->cl_protocol = dlm_config.ci_protocol;
+ cl->cl_timewarn_cs = dlm_config.ci_timewarn_cs;
space_list = &sps->ss_group;
comm_list = &cms->cs_group;
@@ -748,9 +754,16 @@ static ssize_t node_weight_write(struct node *nd, const char *buf, size_t len)
static struct space *get_space(char *name)
{
+ struct config_item *i;
+
if (!space_list)
return NULL;
- return to_space(config_group_find_obj(space_list, name));
+
+ down(&space_list->cg_subsys->su_sem);
+ i = config_group_find_obj(space_list, name);
+ up(&space_list->cg_subsys->su_sem);
+
+ return to_space(i);
}
static void put_space(struct space *sp)
@@ -776,20 +789,20 @@ static struct comm *get_comm(int nodeid, struct sockaddr_storage *addr)
if (cm->nodeid != nodeid)
continue;
found = 1;
+ config_item_get(i);
break;
} else {
if (!cm->addr_count ||
memcmp(cm->addr[0], addr, sizeof(*addr)))
continue;
found = 1;
+ config_item_get(i);
break;
}
}
up(&clusters_root.subsys.su_sem);
- if (found)
- config_item_get(i);
- else
+ if (!found)
cm = NULL;
return cm;
}
@@ -909,6 +922,7 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
#define DEFAULT_SCAN_SECS 5
#define DEFAULT_LOG_DEBUG 0
#define DEFAULT_PROTOCOL 0
+#define DEFAULT_TIMEWARN_CS 500 /* 5 sec = 500 centiseconds */
struct dlm_config_info dlm_config = {
.ci_tcp_port = DEFAULT_TCP_PORT,
@@ -920,6 +934,7 @@ struct dlm_config_info dlm_config = {
.ci_toss_secs = DEFAULT_TOSS_SECS,
.ci_scan_secs = DEFAULT_SCAN_SECS,
.ci_log_debug = DEFAULT_LOG_DEBUG,
- .ci_protocol = DEFAULT_PROTOCOL
+ .ci_protocol = DEFAULT_PROTOCOL,
+ .ci_timewarn_cs = DEFAULT_TIMEWARN_CS
};
diff --git a/fs/dlm/config.h b/fs/dlm/config.h
index 967cc3d72e5..a3170fe2209 100644
--- a/fs/dlm/config.h
+++ b/fs/dlm/config.h
@@ -27,6 +27,7 @@ struct dlm_config_info {
int ci_scan_secs;
int ci_log_debug;
int ci_protocol;
+ int ci_timewarn_cs;
};
extern struct dlm_config_info dlm_config;
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 61ba670b9e0..12c3bfd5e66 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -17,6 +17,7 @@
#include <linux/debugfs.h>
#include "dlm_internal.h"
+#include "lock.h"
#define DLM_DEBUG_BUF_LEN 4096
static char debug_buf[DLM_DEBUG_BUF_LEN];
@@ -26,6 +27,8 @@ static struct dentry *dlm_root;
struct rsb_iter {
int entry;
+ int locks;
+ int header;
struct dlm_ls *ls;
struct list_head *next;
struct dlm_rsb *rsb;
@@ -57,8 +60,8 @@ static char *print_lockmode(int mode)
}
}
-static void print_lock(struct seq_file *s, struct dlm_lkb *lkb,
- struct dlm_rsb *res)
+static void print_resource_lock(struct seq_file *s, struct dlm_lkb *lkb,
+ struct dlm_rsb *res)
{
seq_printf(s, "%08x %s", lkb->lkb_id, print_lockmode(lkb->lkb_grmode));
@@ -85,6 +88,8 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
struct dlm_lkb *lkb;
int i, lvblen = res->res_ls->ls_lvblen, recover_list, root_list;
+ lock_rsb(res);
+
seq_printf(s, "\nResource %p Name (len=%d) \"", res, res->res_length);
for (i = 0; i < res->res_length; i++) {
if (isprint(res->res_name[i]))
@@ -129,15 +134,15 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
/* Print the locks attached to this resource */
seq_printf(s, "Granted Queue\n");
list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue)
- print_lock(s, lkb, res);
+ print_resource_lock(s, lkb, res);
seq_printf(s, "Conversion Queue\n");
list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue)
- print_lock(s, lkb, res);
+ print_resource_lock(s, lkb, res);
seq_printf(s, "Waiting Queue\n");
list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue)
- print_lock(s, lkb, res);
+ print_resource_lock(s, lkb, res);
if (list_empty(&res->res_lookup))
goto out;
@@ -151,6 +156,61 @@ static int print_resource(struct dlm_rsb *res, struct seq_file *s)
seq_printf(s, "\n");
}
out:
+ unlock_rsb(res);
+ return 0;
+}
+
+static void print_lock(struct seq_file *s, struct dlm_lkb *lkb, struct dlm_rsb *r)
+{
+ struct dlm_user_args *ua;
+ unsigned int waiting = 0;
+ uint64_t xid = 0;
+
+ if (lkb->lkb_flags & DLM_IFL_USER) {
+ ua = (struct dlm_user_args *) lkb->lkb_astparam;
+ if (ua)
+ xid = ua->xid;
+ }
+
+ if (lkb->lkb_timestamp)
+ waiting = jiffies_to_msecs(jiffies - lkb->lkb_timestamp);
+
+ /* id nodeid remid pid xid exflags flags sts grmode rqmode time_ms
+ r_nodeid r_len r_name */
+
+ seq_printf(s, "%x %d %x %u %llu %x %x %d %d %d %u %u %d \"%s\"\n",
+ lkb->lkb_id,
+ lkb->lkb_nodeid,
+ lkb->lkb_remid,
+ lkb->lkb_ownpid,
+ (unsigned long long)xid,
+ lkb->lkb_exflags,
+ lkb->lkb_flags,
+ lkb->lkb_status,
+ lkb->lkb_grmode,
+ lkb->lkb_rqmode,
+ waiting,
+ r->res_nodeid,
+ r->res_length,
+ r->res_name);
+}
+
+static int print_locks(struct dlm_rsb *r, struct seq_file *s)
+{
+ struct dlm_lkb *lkb;
+
+ lock_rsb(r);
+
+ list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue)
+ print_lock(s, lkb, r);
+
+ list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue)
+ print_lock(s, lkb, r);
+
+ list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue)
+ print_lock(s, lkb, r);
+
+ unlock_rsb(r);
return 0;
}
@@ -166,6 +226,9 @@ static int rsb_iter_next(struct rsb_iter *ri)
read_lock(&ls->ls_rsbtbl[i].lock);
if (!list_empty(&ls->ls_rsbtbl[i].list)) {
ri->next = ls->ls_rsbtbl[i].list.next;
+ ri->rsb = list_entry(ri->next, struct dlm_rsb,
+ res_hashchain);
+ dlm_hold_rsb(ri->rsb);
read_unlock(&ls->ls_rsbtbl[i].lock);
break;
}
@@ -176,6 +239,7 @@ static int rsb_iter_next(struct rsb_iter *ri)
if (ri->entry >= ls->ls_rsbtbl_size)
return 1;
} else {
+ struct dlm_rsb *old = ri->rsb;
i = ri->entry;
read_lock(&ls->ls_rsbtbl[i].lock);
ri->next = ri->next->next;
@@ -184,11 +248,14 @@ static int rsb_iter_next(struct rsb_iter *ri)
ri->next = NULL;
ri->entry++;
read_unlock(&ls->ls_rsbtbl[i].lock);
+ dlm_put_rsb(old);
goto top;
}
+ ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
+ dlm_hold_rsb(ri->rsb);
read_unlock(&ls->ls_rsbtbl[i].lock);
+ dlm_put_rsb(old);
}
- ri->rsb = list_entry(ri->next, struct dlm_rsb, res_hashchain);
return 0;
}
@@ -202,7 +269,7 @@ static struct rsb_iter *rsb_iter_init(struct dlm_ls *ls)
{
struct rsb_iter *ri;
- ri = kmalloc(sizeof *ri, GFP_KERNEL);
+ ri = kzalloc(sizeof *ri, GFP_KERNEL);
if (!ri)
return NULL;
@@ -260,7 +327,17 @@ static int rsb_seq_show(struct seq_file *file, void *iter_ptr)
{
struct rsb_iter *ri = iter_ptr;
- print_resource(ri->rsb, file);
+ if (ri->locks) {
+ if (ri->header) {
+ seq_printf(file, "id nodeid remid pid xid exflags flags "
+ "sts grmode rqmode time_ms r_nodeid "
+ "r_len r_name\n");
+ ri->header = 0;
+ }
+ print_locks(ri->rsb, file);
+ } else {
+ print_resource(ri->rsb, file);
+ }
return 0;
}
@@ -296,6 +373,83 @@ static const struct file_operations rsb_fops = {
};
/*
+ * Dump state in compact per-lock listing
+ */
+
+static struct rsb_iter *locks_iter_init(struct dlm_ls *ls, loff_t *pos)
+{
+ struct rsb_iter *ri;
+
+ ri = kzalloc(sizeof *ri, GFP_KERNEL);
+ if (!ri)
+ return NULL;
+
+ ri->ls = ls;
+ ri->entry = 0;
+ ri->next = NULL;
+ ri->locks = 1;
+
+ if (*pos == 0)
+ ri->header = 1;
+
+ if (rsb_iter_next(ri)) {
+ rsb_iter_free(ri);
+ return NULL;
+ }
+
+ return ri;
+}
+
+static void *locks_seq_start(struct seq_file *file, loff_t *pos)
+{
+ struct rsb_iter *ri;
+ loff_t n = *pos;
+
+ ri = locks_iter_init(file->private, pos);
+ if (!ri)
+ return NULL;
+
+ while (n--) {
+ if (rsb_iter_next(ri)) {
+ rsb_iter_free(ri);
+ return NULL;
+ }
+ }
+
+ return ri;
+}
+
+static struct seq_operations locks_seq_ops = {
+ .start = locks_seq_start,
+ .next = rsb_seq_next,
+ .stop = rsb_seq_stop,
+ .show = rsb_seq_show,
+};
+
+static int locks_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int ret;
+
+ ret = seq_open(file, &locks_seq_ops);
+ if (ret)
+ return ret;
+
+ seq = file->private_data;
+ seq->private = inode->i_private;
+
+ return 0;
+}
+
+static const struct file_operations locks_fops = {
+ .owner = THIS_MODULE,
+ .open = locks_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/*
* dump lkb's on the ls_waiters list
*/
@@ -362,6 +516,20 @@ int dlm_create_debug_file(struct dlm_ls *ls)
return -ENOMEM;
}
+ memset(name, 0, sizeof(name));
+ snprintf(name, DLM_LOCKSPACE_LEN+8, "%s_locks", ls->ls_name);
+
+ ls->ls_debug_locks_dentry = debugfs_create_file(name,
+ S_IFREG | S_IRUGO,
+ dlm_root,
+ ls,
+ &locks_fops);
+ if (!ls->ls_debug_locks_dentry) {
+ debugfs_remove(ls->ls_debug_waiters_dentry);
+ debugfs_remove(ls->ls_debug_rsb_dentry);
+ return -ENOMEM;
+ }
+
return 0;
}
@@ -371,6 +539,8 @@ void dlm_delete_debug_file(struct dlm_ls *ls)
debugfs_remove(ls->ls_debug_rsb_dentry);
if (ls->ls_debug_waiters_dentry)
debugfs_remove(ls->ls_debug_waiters_dentry);
+ if (ls->ls_debug_locks_dentry)
+ debugfs_remove(ls->ls_debug_locks_dentry);
}
int dlm_register_debugfs(void)
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 30994d68f6a..74901e981e1 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -151,6 +151,7 @@ struct dlm_args {
void *bastaddr;
int mode;
struct dlm_lksb *lksb;
+ unsigned long timeout;
};
@@ -213,6 +214,9 @@ struct dlm_args {
#define DLM_IFL_OVERLAP_UNLOCK 0x00080000
#define DLM_IFL_OVERLAP_CANCEL 0x00100000
#define DLM_IFL_ENDOFLIFE 0x00200000
+#define DLM_IFL_WATCH_TIMEWARN 0x00400000
+#define DLM_IFL_TIMEOUT_CANCEL 0x00800000
+#define DLM_IFL_DEADLOCK_CANCEL 0x01000000
#define DLM_IFL_USER 0x00000001
#define DLM_IFL_ORPHAN 0x00000002
@@ -243,6 +247,9 @@ struct dlm_lkb {
struct list_head lkb_wait_reply; /* waiting for remote reply */
struct list_head lkb_astqueue; /* need ast to be sent */
struct list_head lkb_ownqueue; /* list of locks for a process */
+ struct list_head lkb_time_list;
+ unsigned long lkb_timestamp;
+ unsigned long lkb_timeout_cs;
char *lkb_lvbptr;
struct dlm_lksb *lkb_lksb; /* caller's status block */
@@ -447,12 +454,16 @@ struct dlm_ls {
struct mutex ls_orphans_mutex;
struct list_head ls_orphans;
+ struct mutex ls_timeout_mutex;
+ struct list_head ls_timeout;
+
struct list_head ls_nodes; /* current nodes in ls */
struct list_head ls_nodes_gone; /* dead node list, recovery */
int ls_num_nodes; /* number of nodes in ls */
int ls_low_nodeid;
int ls_total_weight;
int *ls_node_array;
+ gfp_t ls_allocation;
struct dlm_rsb ls_stub_rsb; /* for returning errors */
struct dlm_lkb ls_stub_lkb; /* for returning errors */
@@ -460,9 +471,12 @@ struct dlm_ls {
struct dentry *ls_debug_rsb_dentry; /* debugfs */
struct dentry *ls_debug_waiters_dentry; /* debugfs */
+ struct dentry *ls_debug_locks_dentry; /* debugfs */
wait_queue_head_t ls_uevent_wait; /* user part of join/leave */
int ls_uevent_result;
+ struct completion ls_members_done;
+ int ls_members_result;
struct miscdevice ls_device;
@@ -472,6 +486,7 @@ struct dlm_ls {
struct task_struct *ls_recoverd_task;
struct mutex ls_recoverd_active;
spinlock_t ls_recover_lock;
+ unsigned long ls_recover_begin; /* jiffies timestamp */
uint32_t ls_recover_status; /* DLM_RS_ */
uint64_t ls_recover_seq;
struct dlm_recover *ls_recover_args;
@@ -501,6 +516,7 @@ struct dlm_ls {
#define LSFL_RCOM_READY 3
#define LSFL_RCOM_WAIT 4
#define LSFL_UEVENT_WAIT 5
+#define LSFL_TIMEWARN 6
/* much of this is just saving user space pointers associated with the
lock that we pass back to the user lib with an ast */
@@ -518,6 +534,7 @@ struct dlm_user_args {
void __user *castaddr;
void __user *bastparam;
void __user *bastaddr;
+ uint64_t xid;
};
#define DLM_PROC_FLAGS_CLOSING 1
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index d8d6e729f96..b455919c199 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -82,10 +82,13 @@ static int send_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int mode);
static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb);
static int send_remove(struct dlm_rsb *r);
static int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
+static int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb);
static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
struct dlm_message *ms);
static int receive_extralen(struct dlm_message *ms);
static void do_purge(struct dlm_ls *ls, int nodeid, int pid);
+static void del_timeout(struct dlm_lkb *lkb);
+void dlm_timeout_warn(struct dlm_lkb *lkb);
/*
* Lock compatibilty matrix - thanks Steve
@@ -194,17 +197,17 @@ void dlm_dump_rsb(struct dlm_rsb *r)
/* Threads cannot use the lockspace while it's being recovered */
-static inline void lock_recovery(struct dlm_ls *ls)
+static inline void dlm_lock_recovery(struct dlm_ls *ls)
{
down_read(&ls->ls_in_recovery);
}
-static inline void unlock_recovery(struct dlm_ls *ls)
+void dlm_unlock_recovery(struct dlm_ls *ls)
{
up_read(&ls->ls_in_recovery);
}
-static inline int lock_recovery_try(struct dlm_ls *ls)
+int dlm_lock_recovery_try(struct dlm_ls *ls)
{
return down_read_trylock(&ls->ls_in_recovery);
}
@@ -286,8 +289,22 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
if (is_master_copy(lkb))
return;
+ del_timeout(lkb);
+
DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb););
+ /* if the operation was a cancel, then return -DLM_ECANCEL, if a
+ timeout caused the cancel then return -ETIMEDOUT */
+ if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_TIMEOUT_CANCEL)) {
+ lkb->lkb_flags &= ~DLM_IFL_TIMEOUT_CANCEL;
+ rv = -ETIMEDOUT;
+ }
+
+ if (rv == -DLM_ECANCEL && (lkb->lkb_flags & DLM_IFL_DEADLOCK_CANCEL)) {
+ lkb->lkb_flags &= ~DLM_IFL_DEADLOCK_CANCEL;
+ rv = -EDEADLK;
+ }
+
lkb->lkb_lksb->sb_status = rv;
lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
@@ -581,6 +598,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
kref_init(&lkb->lkb_ref);
INIT_LIST_HEAD(&lkb->lkb_ownqueue);
INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
+ INIT_LIST_HEAD(&lkb->lkb_time_list);
get_random_bytes(&bucket, sizeof(bucket));
bucket &= (ls->ls_lkbtbl_size - 1);
@@ -985,15 +1003,136 @@ void dlm_scan_rsbs(struct dlm_ls *ls)
{
int i;
- if (dlm_locking_stopped(ls))
- return;
-
for (i = 0; i < ls->ls_rsbtbl_size; i++) {
shrink_bucket(ls, i);
+ if (dlm_locking_stopped(ls))
+ break;
cond_resched();
}
}
+static void add_timeout(struct dlm_lkb *lkb)
+{
+ struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+
+ if (is_master_copy(lkb)) {
+ lkb->lkb_timestamp = jiffies;
+ return;
+ }
+
+ if (test_bit(LSFL_TIMEWARN, &ls->ls_flags) &&
+ !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
+ lkb->lkb_flags |= DLM_IFL_WATCH_TIMEWARN;
+ goto add_it;
+ }
+ if (lkb->lkb_exflags & DLM_LKF_TIMEOUT)
+ goto add_it;
+ return;
+
+ add_it:
+ DLM_ASSERT(list_empty(&lkb->lkb_time_list), dlm_print_lkb(lkb););
+ mutex_lock(&ls->ls_timeout_mutex);
+ hold_lkb(lkb);
+ lkb->lkb_timestamp = jiffies;
+ list_add_tail(&lkb->lkb_time_list, &ls->ls_timeout);
+ mutex_unlock(&ls->ls_timeout_mutex);
+}
+
+static void del_timeout(struct dlm_lkb *lkb)
+{
+ struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+
+ mutex_lock(&ls->ls_timeout_mutex);
+ if (!list_empty(&lkb->lkb_time_list)) {
+ list_del_init(&lkb->lkb_time_list);
+ unhold_lkb(lkb);
+ }
+ mutex_unlock(&ls->ls_timeout_mutex);
+}
+
+/* FIXME: is it safe to look at lkb_exflags, lkb_flags, lkb_timestamp, and
+ lkb_lksb_timeout without lock_rsb? Note: we can't lock timeout_mutex
+ and then lock rsb because of lock ordering in add_timeout. We may need
+ to specify some special timeout-related bits in the lkb that are just to
+ be accessed under the timeout_mutex. */
+
+void dlm_scan_timeout(struct dlm_ls *ls)
+{
+ struct dlm_rsb *r;
+ struct dlm_lkb *lkb;
+ int do_cancel, do_warn;
+
+ for (;;) {
+ if (dlm_locking_stopped(ls))
+ break;
+
+ do_cancel = 0;
+ do_warn = 0;
+ mutex_lock(&ls->ls_timeout_mutex);
+ list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list) {
+
+ if ((lkb->lkb_exflags & DLM_LKF_TIMEOUT) &&
+ time_after_eq(jiffies, lkb->lkb_timestamp +
+ lkb->lkb_timeout_cs * HZ/100))
+ do_cancel = 1;
+
+ if ((lkb->lkb_flags & DLM_IFL_WATCH_TIMEWARN) &&
+ time_after_eq(jiffies, lkb->lkb_timestamp +
+ dlm_config.ci_timewarn_cs * HZ/100))
+ do_warn = 1;
+
+ if (!do_cancel && !do_warn)
+ continue;
+ hold_lkb(lkb);
+ break;
+ }
+ mutex_unlock(&ls->ls_timeout_mutex);
+
+ if (!do_cancel && !do_warn)
+ break;
+
+ r = lkb->lkb_resource;
+ hold_rsb(r);
+ lock_rsb(r);
+
+ if (do_warn) {
+ /* clear flag so we only warn once */
+ lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
+ if (!(lkb->lkb_exflags & DLM_LKF_TIMEOUT))
+ del_timeout(lkb);
+ dlm_timeout_warn(lkb);
+ }
+
+ if (do_cancel) {
+ log_debug(ls, "timeout cancel %x node %d %s",
+ lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+ lkb->lkb_flags &= ~DLM_IFL_WATCH_TIMEWARN;
+ lkb->lkb_flags |= DLM_IFL_TIMEOUT_CANCEL;
+ del_timeout(lkb);
+ _cancel_lock(r, lkb);
+ }
+
+ unlock_rsb(r);
+ unhold_rsb(r);
+ dlm_put_lkb(lkb);
+ }
+}
+
+/* This is only called by dlm_recoverd, and we rely on dlm_ls_stop() stopping
+ dlm_recoverd before checking/setting ls_recover_begin. */
+
+void dlm_adjust_timeouts(struct dlm_ls *ls)
+{
+ struct dlm_lkb *lkb;
+ long adj = jiffies - ls->ls_recover_begin;
+
+ ls->ls_recover_begin = 0;
+ mutex_lock(&ls->ls_timeout_mutex);
+ list_for_each_entry(lkb, &ls->ls_timeout, lkb_time_list)
+ lkb->lkb_timestamp += adj;
+ mutex_unlock(&ls->ls_timeout_mutex);
+}
+
/* lkb is master or local copy */
static void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -1275,10 +1414,8 @@ static int queue_conflict(struct list_head *head, struct dlm_lkb *lkb)
* queue for one resource. The granted mode of each lock blocks the requested
* mode of the other lock."
*
- * Part 2: if the granted mode of lkb is preventing the first lkb in the
- * convert queue from being granted, then demote lkb (set grmode to NL).
- * This second form requires that we check for conv-deadlk even when
- * now == 0 in _can_be_granted().
+ * Part 2: if the granted mode of lkb is preventing an earlier lkb in the
+ * convert queue from being granted, then deadlk/demote lkb.
*
* Example:
* Granted Queue: empty
@@ -1287,41 +1424,52 @@ static int queue_conflict(struct list_head *head, struct dlm_lkb *lkb)
*
* The first lock can't be granted because of the granted mode of the second
* lock and the second lock can't be granted because it's not first in the
- * list. We demote the granted mode of the second lock (the lkb passed to this
- * function).
+ * list. We either cancel lkb's conversion (PR->EX) and return EDEADLK, or we
+ * demote the granted mode of lkb (from PR to NL) if it has the CONVDEADLK
+ * flag set and return DEMOTED in the lksb flags.
+ *
+ * Originally, this function detected conv-deadlk in a more limited scope:
+ * - if !modes_compat(lkb1, lkb2) && !modes_compat(lkb2, lkb1), or
+ * - if lkb1 was the first entry in the queue (not just earlier), and was
+ * blocked by the granted mode of lkb2, and there was nothing on the
+ * granted queue preventing lkb1 from being granted immediately, i.e.
+ * lkb2 was the only thing preventing lkb1 from being granted.
+ *
+ * That second condition meant we'd only say there was conv-deadlk if
+ * resolving it (by demotion) would lead to the first lock on the convert
+ * queue being granted right away. It allowed conversion deadlocks to exist
+ * between locks on the convert queue while they couldn't be granted anyway.
*
- * After the resolution, the "grant pending" function needs to go back and try
- * to grant locks on the convert queue again since the first lock can now be
- * granted.
+ * Now, we detect and take action on conversion deadlocks immediately when
+ * they're created, even if they may not be immediately consequential. If
+ * lkb1 exists anywhere in the convert queue and lkb2 comes in with a granted
+ * mode that would prevent lkb1's conversion from being granted, we do a
+ * deadlk/demote on lkb2 right away and don't let it onto the convert queue.
+ * I think this means that the lkb_is_ahead condition below should always
+ * be zero, i.e. there will never be conv-deadlk between two locks that are
+ * both already on the convert queue.
*/
-static int conversion_deadlock_detect(struct dlm_rsb *rsb, struct dlm_lkb *lkb)
+static int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2)
{
- struct dlm_lkb *this, *first = NULL, *self = NULL;
+ struct dlm_lkb *lkb1;
+ int lkb_is_ahead = 0;
- list_for_each_entry(this, &rsb->res_convertqueue, lkb_statequeue) {
- if (!first)
- first = this;
- if (this == lkb) {
- self = lkb;
+ list_for_each_entry(lkb1, &r->res_convertqueue, lkb_statequeue) {
+ if (lkb1 == lkb2) {
+ lkb_is_ahead = 1;
continue;
}
- if (!modes_compat(this, lkb) && !modes_compat(lkb, this))
- return 1;
- }
-
- /* if lkb is on the convert queue and is preventing the first
- from being granted, then there's deadlock and we demote lkb.
- multiple converting locks may need to do this before the first
- converting lock can be granted. */
-
- if (self && self != first) {
- if (!modes_compat(lkb, first) &&
- !queue_conflict(&rsb->res_grantqueue, first))
- return 1;
+ if (!lkb_is_ahead) {
+ if (!modes_compat(lkb2, lkb1))
+ return 1;
+ } else {
+ if (!modes_compat(lkb2, lkb1) &&
+ !modes_compat(lkb1, lkb2))
+ return 1;
+ }
}
-
return 0;
}
@@ -1450,42 +1598,57 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
if (!now && !conv && list_empty(&r->res_convertqueue) &&
first_in_list(lkb, &r->res_waitqueue))
return 1;
-
out:
- /*
- * The following, enabled by CONVDEADLK, departs from VMS.
- */
-
- if (conv && (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) &&
- conversion_deadlock_detect(r, lkb)) {
- lkb->lkb_grmode = DLM_LOCK_NL;
- lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
- }
-
return 0;
}
-/*
- * The ALTPR and ALTCW flags aren't traditional lock manager flags, but are a
- * simple way to provide a big optimization to applications that can use them.
- */
-
-static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
+static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
+ int *err)
{
- uint32_t flags = lkb->lkb_exflags;
int rv;
int8_t alt = 0, rqmode = lkb->lkb_rqmode;
+ int8_t is_convert = (lkb->lkb_grmode != DLM_LOCK_IV);
+
+ if (err)
+ *err = 0;
rv = _can_be_granted(r, lkb, now);
if (rv)
goto out;
- if (lkb->lkb_sbflags & DLM_SBF_DEMOTED)
+ /*
+ * The CONVDEADLK flag is non-standard and tells the dlm to resolve
+ * conversion deadlocks by demoting grmode to NL, otherwise the dlm
+ * cancels one of the locks.
+ */
+
+ if (is_convert && can_be_queued(lkb) &&
+ conversion_deadlock_detect(r, lkb)) {
+ if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) {
+ lkb->lkb_grmode = DLM_LOCK_NL;
+ lkb->lkb_sbflags |= DLM_SBF_DEMOTED;
+ } else if (!(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) {
+ if (err)
+ *err = -EDEADLK;
+ else {
+ log_print("can_be_granted deadlock %x now %d",
+ lkb->lkb_id, now);
+ dlm_dump_rsb(r);
+ }
+ }
goto out;
+ }
- if (rqmode != DLM_LOCK_PR && flags & DLM_LKF_ALTPR)
+ /*
+ * The ALTPR and ALTCW flags are non-standard and tell the dlm to try
+ * to grant a request in a mode other than the normal rqmode. It's a
+ * simple way to provide a big optimization to applications that can
+ * use them.
+ */
+
+ if (rqmode != DLM_LOCK_PR && (lkb->lkb_exflags & DLM_LKF_ALTPR))
alt = DLM_LOCK_PR;
- else if (rqmode != DLM_LOCK_CW && flags & DLM_LKF_ALTCW)
+ else if (rqmode != DLM_LOCK_CW && (lkb->lkb_exflags & DLM_LKF_ALTCW))
alt = DLM_LOCK_CW;
if (alt) {
@@ -1500,10 +1663,20 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
return rv;
}
+/* FIXME: I don't think that can_be_granted() can/will demote or find deadlock
+ for locks pending on the convert list. Once verified (watch for these
+ log_prints), we should be able to just call _can_be_granted() and not
+ bother with the demote/deadlk cases here (and there's no easy way to deal
+ with a deadlk here, we'd have to generate something like grant_lock with
+ the deadlk error.) */
+
+/* returns the highest requested mode of all blocked conversions */
+
static int grant_pending_convert(struct dlm_rsb *r, int high)
{
struct dlm_lkb *lkb, *s;
int hi, demoted, quit, grant_restart, demote_restart;
+ int deadlk;
quit = 0;
restart:
@@ -1513,14 +1686,29 @@ static int grant_pending_convert(struct dlm_rsb *r, int high)
list_for_each_entry_safe(lkb, s, &r->res_convertqueue, lkb_statequeue) {
demoted = is_demoted(lkb);
- if (can_be_granted(r, lkb, 0)) {
+ deadlk = 0;
+
+ if (can_be_granted(r, lkb, 0, &deadlk)) {
grant_lock_pending(r, lkb);
grant_restart = 1;
- } else {
- hi = max_t(int, lkb->lkb_rqmode, hi);
- if (!demoted && is_demoted(lkb))
- demote_restart = 1;
+ continue;
}
+
+ if (!demoted && is_demoted(lkb)) {
+ log_print("WARN: pending demoted %x node %d %s",
+ lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+ demote_restart = 1;
+ continue;
+ }
+
+ if (deadlk) {
+ log_print("WARN: pending deadlock %x node %d %s",
+ lkb->lkb_id, lkb->lkb_nodeid, r->res_name);
+ dlm_dump_rsb(r);
+ continue;
+ }
+
+ hi = max_t(int, lkb->lkb_rqmode, hi);
}
if (grant_restart)
@@ -1538,7 +1726,7 @@ static int grant_pending_wait(struct dlm_rsb *r, int high)
struct dlm_lkb *lkb, *s;
list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
- if (can_be_granted(r, lkb, 0))
+ if (can_be_granted(r, lkb, 0, NULL))
grant_lock_pending(r, lkb);
else
high = max_t(int, lkb->lkb_rqmode, high);
@@ -1733,7 +1921,7 @@ static void confirm_master(struct dlm_rsb *r, int error)
}
static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
- int namelen, uint32_t parent_lkid, void *ast,
+ int namelen, unsigned long timeout_cs, void *ast,
void *astarg, void *bast, struct dlm_args *args)
{
int rv = -EINVAL;
@@ -1776,10 +1964,6 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr)
goto out;
- /* parent/child locks not yet supported */
- if (parent_lkid)
- goto out;
-
if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid)
goto out;
@@ -1791,6 +1975,7 @@ static int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags,
args->astaddr = ast;
args->astparam = (long) astarg;
args->bastaddr = bast;
+ args->timeout = timeout_cs;
args->mode = mode;
args->lksb = lksb;
rv = 0;
@@ -1845,6 +2030,7 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
lkb->lkb_lksb = args->lksb;
lkb->lkb_lvbptr = args->lksb->sb_lvbptr;
lkb->lkb_ownpid = (int) current->pid;
+ lkb->lkb_timeout_cs = args->timeout;
rv = 0;
out:
return rv;
@@ -1903,6 +2089,9 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
if (is_overlap(lkb))
goto out;
+ /* don't let scand try to do a cancel */
+ del_timeout(lkb);
+
if (lkb->lkb_flags & DLM_IFL_RESEND) {
lkb->lkb_flags |= DLM_IFL_OVERLAP_CANCEL;
rv = -EBUSY;
@@ -1934,6 +2123,9 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
if (is_overlap_unlock(lkb))
goto out;
+ /* don't let scand try to do a cancel */
+ del_timeout(lkb);
+
if (lkb->lkb_flags & DLM_IFL_RESEND) {
lkb->lkb_flags |= DLM_IFL_OVERLAP_UNLOCK;
rv = -EBUSY;
@@ -1984,7 +2176,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
{
int error = 0;
- if (can_be_granted(r, lkb, 1)) {
+ if (can_be_granted(r, lkb, 1, NULL)) {
grant_lock(r, lkb);
queue_cast(r, lkb, 0);
goto out;
@@ -1994,6 +2186,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
error = -EINPROGRESS;
add_lkb(r, lkb, DLM_LKSTS_WAITING);
send_blocking_asts(r, lkb);
+ add_timeout(lkb);
goto out;
}
@@ -2009,16 +2202,32 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
{
int error = 0;
+ int deadlk = 0;
/* changing an existing lock may allow others to be granted */
- if (can_be_granted(r, lkb, 1)) {
+ if (can_be_granted(r, lkb, 1, &deadlk)) {
grant_lock(r, lkb);
queue_cast(r, lkb, 0);
grant_pending_locks(r);
goto out;
}
+ /* can_be_granted() detected that this lock would block in a conversion
+ deadlock, so we leave it on the granted queue and return EDEADLK in
+ the ast for the convert. */
+
+ if (deadlk) {
+ /* it's left on the granted queue */
+ log_debug(r->res_ls, "deadlock %x node %d sts%d g%d r%d %s",
+ lkb->lkb_id, lkb->lkb_nodeid, lkb->lkb_status,
+ lkb->lkb_grmode, lkb->lkb_rqmode, r->res_name);
+ revert_lock(r, lkb);
+ queue_cast(r, lkb, -EDEADLK);
+ error = -EDEADLK;
+ goto out;
+ }
+
/* is_demoted() means the can_be_granted() above set the grmode
to NL, and left us on the granted queue. This auto-demotion
(due to CONVDEADLK) might mean other locks, and/or this lock, are
@@ -2041,6 +2250,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
del_lkb(r, lkb);
add_lkb(r, lkb, DLM_LKSTS_CONVERT);
send_blocking_asts(r, lkb);
+ add_timeout(lkb);
goto out;
}
@@ -2274,7 +2484,7 @@ int dlm_lock(dlm_lockspace_t *lockspace,
if (!ls)
return -EINVAL;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
if (convert)
error = find_lkb(ls, lksb->sb_lkid, &lkb);
@@ -2284,7 +2494,7 @@ int dlm_lock(dlm_lockspace_t *lockspace,
if (error)
goto out;
- error = set_lock_args(mode, lksb, flags, namelen, parent_lkid, ast,
+ error = set_lock_args(mode, lksb, flags, namelen, 0, ast,
astarg, bast, &args);
if (error)
goto out_put;
@@ -2299,10 +2509,10 @@ int dlm_lock(dlm_lockspace_t *lockspace,
out_put:
if (convert || error)
__put_lkb(ls, lkb);
- if (error == -EAGAIN)
+ if (error == -EAGAIN || error == -EDEADLK)
error = 0;
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
dlm_put_lockspace(ls);
return error;
}
@@ -2322,7 +2532,7 @@ int dlm_unlock(dlm_lockspace_t *lockspace,
if (!ls)
return -EINVAL;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = find_lkb(ls, lkid, &lkb);
if (error)
@@ -2344,7 +2554,7 @@ int dlm_unlock(dlm_lockspace_t *lockspace,
out_put:
dlm_put_lkb(lkb);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
dlm_put_lockspace(ls);
return error;
}
@@ -2384,7 +2594,7 @@ static int _create_message(struct dlm_ls *ls, int mb_len,
pass into lowcomms_commit and a message buffer (mb) that we
write our data into */
- mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb);
+ mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
if (!mh)
return -ENOBUFS;
@@ -3111,9 +3321,10 @@ static void receive_request_reply(struct dlm_ls *ls, struct dlm_message *ms)
lkb->lkb_remid = ms->m_lkid;
if (is_altmode(lkb))
munge_altmode(lkb, ms);
- if (result)
+ if (result) {
add_lkb(r, lkb, DLM_LKSTS_WAITING);
- else {
+ add_timeout(lkb);
+ } else {
grant_lock_pc(r, lkb, ms);
queue_cast(r, lkb, 0);
}
@@ -3172,6 +3383,12 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
queue_cast(r, lkb, -EAGAIN);
break;
+ case -EDEADLK:
+ receive_flags_reply(lkb, ms);
+ revert_lock_pc(r, lkb);
+ queue_cast(r, lkb, -EDEADLK);
+ break;
+
case -EINPROGRESS:
/* convert was queued on remote master */
receive_flags_reply(lkb, ms);
@@ -3179,6 +3396,7 @@ static void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb,
munge_demoted(lkb, ms);
del_lkb(r, lkb);
add_lkb(r, lkb, DLM_LKSTS_CONVERT);
+ add_timeout(lkb);
break;
case 0:
@@ -3298,8 +3516,7 @@ static void _receive_cancel_reply(struct dlm_lkb *lkb, struct dlm_message *ms)
case -DLM_ECANCEL:
receive_flags_reply(lkb, ms);
revert_lock_pc(r, lkb);
- if (ms->m_result)
- queue_cast(r, lkb, -DLM_ECANCEL);
+ queue_cast(r, lkb, -DLM_ECANCEL);
break;
case 0:
break;
@@ -3424,7 +3641,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery)
}
}
- if (lock_recovery_try(ls))
+ if (dlm_lock_recovery_try(ls))
break;
schedule();
}
@@ -3503,7 +3720,7 @@ int dlm_receive_message(struct dlm_header *hd, int nodeid, int recovery)
log_error(ls, "unknown message type %d", ms->m_type);
}
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
out:
dlm_put_lockspace(ls);
dlm_astd_wake();
@@ -4034,13 +4251,13 @@ int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc)
int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
int mode, uint32_t flags, void *name, unsigned int namelen,
- uint32_t parent_lkid)
+ unsigned long timeout_cs)
{
struct dlm_lkb *lkb;
struct dlm_args args;
int error;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = create_lkb(ls, &lkb);
if (error) {
@@ -4062,7 +4279,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
When DLM_IFL_USER is set, the dlm knows that this is a userspace
lock and that lkb_astparam is the dlm_user_args structure. */
- error = set_lock_args(mode, &ua->lksb, flags, namelen, parent_lkid,
+ error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
lkb->lkb_flags |= DLM_IFL_USER;
ua->old_mode = DLM_LOCK_IV;
@@ -4094,19 +4311,20 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks);
spin_unlock(&ua->proc->locks_spin);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
return error;
}
int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- int mode, uint32_t flags, uint32_t lkid, char *lvb_in)
+ int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+ unsigned long timeout_cs)
{
struct dlm_lkb *lkb;
struct dlm_args args;
struct dlm_user_args *ua;
int error;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = find_lkb(ls, lkid, &lkb);
if (error)
@@ -4127,6 +4345,7 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
if (lvb_in && ua->lksb.sb_lvbptr)
memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN);
+ ua->xid = ua_tmp->xid;
ua->castparam = ua_tmp->castparam;
ua->castaddr = ua_tmp->castaddr;
ua->bastparam = ua_tmp->bastparam;
@@ -4134,19 +4353,19 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
ua->user_lksb = ua_tmp->user_lksb;
ua->old_mode = lkb->lkb_grmode;
- error = set_lock_args(mode, &ua->lksb, flags, 0, 0, DLM_FAKE_USER_AST,
- ua, DLM_FAKE_USER_AST, &args);
+ error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs,
+ DLM_FAKE_USER_AST, ua, DLM_FAKE_USER_AST, &args);
if (error)
goto out_put;
error = convert_lock(ls, lkb, &args);
- if (error == -EINPROGRESS || error == -EAGAIN)
+ if (error == -EINPROGRESS || error == -EAGAIN || error == -EDEADLK)
error = 0;
out_put:
dlm_put_lkb(lkb);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
kfree(ua_tmp);
return error;
}
@@ -4159,7 +4378,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
struct dlm_user_args *ua;
int error;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = find_lkb(ls, lkid, &lkb);
if (error)
@@ -4194,7 +4413,7 @@ int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
out_put:
dlm_put_lkb(lkb);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
kfree(ua_tmp);
return error;
}
@@ -4207,7 +4426,7 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
struct dlm_user_args *ua;
int error;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
error = find_lkb(ls, lkid, &lkb);
if (error)
@@ -4231,11 +4450,59 @@ int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
out_put:
dlm_put_lkb(lkb);
out:
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
kfree(ua_tmp);
return error;
}
+int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid)
+{
+ struct dlm_lkb *lkb;
+ struct dlm_args args;
+ struct dlm_user_args *ua;
+ struct dlm_rsb *r;
+ int error;
+
+ dlm_lock_recovery(ls);
+
+ error = find_lkb(ls, lkid, &lkb);
+ if (error)
+ goto out;
+
+ ua = (struct dlm_user_args *)lkb->lkb_astparam;
+
+ error = set_unlock_args(flags, ua, &args);
+ if (error)
+ goto out_put;
+
+ /* same as cancel_lock(), but set DEADLOCK_CANCEL after lock_rsb */
+
+ r = lkb->lkb_resource;
+ hold_rsb(r);
+ lock_rsb(r);
+
+ error = validate_unlock_args(lkb, &args);
+ if (error)
+ goto out_r;
+ lkb->lkb_flags |= DLM_IFL_DEADLOCK_CANCEL;
+
+ error = _cancel_lock(r, lkb);
+ out_r:
+ unlock_rsb(r);
+ put_rsb(r);
+
+ if (error == -DLM_ECANCEL)
+ error = 0;
+ /* from validate_unlock_args() */
+ if (error == -EBUSY)
+ error = 0;
+ out_put:
+ dlm_put_lkb(lkb);
+ out:
+ dlm_unlock_recovery(ls);
+ return error;
+}
+
/* lkb's that are removed from the waiters list by revert are just left on the
orphans list with the granted orphan locks, to be freed by purge */
@@ -4314,12 +4581,13 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
{
struct dlm_lkb *lkb, *safe;
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
while (1) {
lkb = del_proc_lock(ls, proc);
if (!lkb)
break;
+ del_timeout(lkb);
if (lkb->lkb_exflags & DLM_LKF_PERSISTENT)
orphan_proc_lock(ls, lkb);
else
@@ -4347,7 +4615,7 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
}
mutex_unlock(&ls->ls_clear_proc_locks);
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
}
static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
@@ -4429,12 +4697,12 @@ int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
if (nodeid != dlm_our_nodeid()) {
error = send_purge(ls, nodeid, pid);
} else {
- lock_recovery(ls);
+ dlm_lock_recovery(ls);
if (pid == current->pid)
purge_proc_locks(ls, proc);
else
do_purge(ls, nodeid, pid);
- unlock_recovery(ls);
+ dlm_unlock_recovery(ls);
}
return error;
}
diff --git a/fs/dlm/lock.h b/fs/dlm/lock.h
index 64fc4ec4066..1720313c22d 100644
--- a/fs/dlm/lock.h
+++ b/fs/dlm/lock.h
@@ -1,7 +1,7 @@
/******************************************************************************
*******************************************************************************
**
-** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -24,6 +24,10 @@ void dlm_put_rsb(struct dlm_rsb *r);
void dlm_hold_rsb(struct dlm_rsb *r);
int dlm_put_lkb(struct dlm_lkb *lkb);
void dlm_scan_rsbs(struct dlm_ls *ls);
+int dlm_lock_recovery_try(struct dlm_ls *ls);
+void dlm_unlock_recovery(struct dlm_ls *ls);
+void dlm_scan_timeout(struct dlm_ls *ls);
+void dlm_adjust_timeouts(struct dlm_ls *ls);
int dlm_purge_locks(struct dlm_ls *ls);
void dlm_purge_mstcpy_locks(struct dlm_rsb *r);
@@ -34,15 +38,18 @@ int dlm_recover_master_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
int dlm_recover_process_copy(struct dlm_ls *ls, struct dlm_rcom *rc);
int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, int mode,
- uint32_t flags, void *name, unsigned int namelen, uint32_t parent_lkid);
+ uint32_t flags, void *name, unsigned int namelen,
+ unsigned long timeout_cs);
int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
- int mode, uint32_t flags, uint32_t lkid, char *lvb_in);
+ int mode, uint32_t flags, uint32_t lkid, char *lvb_in,
+ unsigned long timeout_cs);
int dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
uint32_t flags, uint32_t lkid, char *lvb_in);
int dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
uint32_t flags, uint32_t lkid);
int dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc,
int nodeid, int pid);
+int dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid);
void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc);
static inline int is_master(struct dlm_rsb *r)
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a677b2a5eed..1dc72105ab1 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -197,13 +197,24 @@ static int do_uevent(struct dlm_ls *ls, int in)
else
kobject_uevent(&ls->ls_kobj, KOBJ_OFFLINE);
+ log_debug(ls, "%s the lockspace group...", in ? "joining" : "leaving");
+
+ /* dlm_controld will see the uevent, do the necessary group management
+ and then write to sysfs to wake us */
+
error = wait_event_interruptible(ls->ls_uevent_wait,
test_and_clear_bit(LSFL_UEVENT_WAIT, &ls->ls_flags));
+
+ log_debug(ls, "group event done %d %d", error, ls->ls_uevent_result);
+
if (error)
goto out;
error = ls->ls_uevent_result;
out:
+ if (error)
+ log_error(ls, "group %s failed %d %d", in ? "join" : "leave",
+ error, ls->ls_uevent_result);
return error;
}
@@ -234,8 +245,13 @@ static int dlm_scand(void *data)
struct dlm_ls *ls;
while (!kthread_should_stop()) {
- list_for_each_entry(ls, &lslist, ls_list)
- dlm_scan_rsbs(ls);
+ list_for_each_entry(ls, &lslist, ls_list) {
+ if (dlm_lock_recovery_try(ls)) {
+ dlm_scan_rsbs(ls);
+ dlm_scan_timeout(ls);
+ dlm_unlock_recovery(ls);
+ }
+ }
schedule_timeout_interruptible(dlm_config.ci_scan_secs * HZ);
}
return 0;
@@ -395,6 +411,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
{
struct dlm_ls *ls;
int i, size, error = -ENOMEM;
+ int do_unreg = 0;
if (namelen > DLM_LOCKSPACE_LEN)
return -EINVAL;
@@ -417,11 +434,22 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
goto out;
memcpy(ls->ls_name, name, namelen);
ls->ls_namelen = namelen;
- ls->ls_exflags = flags;
ls->ls_lvblen = lvblen;
ls->ls_count = 0;
ls->ls_flags = 0;
+ if (flags & DLM_LSFL_TIMEWARN)
+ set_bit(LSFL_TIMEWARN, &ls->ls_flags);
+
+ if (flags & DLM_LSFL_FS)
+ ls->ls_allocation = GFP_NOFS;
+ else
+ ls->ls_allocation = GFP_KERNEL;
+
+ /* ls_exflags are forced to match among nodes, and we don't
+ need to require all nodes to have TIMEWARN or FS set */
+ ls->ls_exflags = (flags & ~(DLM_LSFL_TIMEWARN | DLM_LSFL_FS));
+
size = dlm_config.ci_rsbtbl_size;
ls->ls_rsbtbl_size = size;
@@ -461,6 +489,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
mutex_init(&ls->ls_waiters_mutex);
INIT_LIST_HEAD(&ls->ls_orphans);
mutex_init(&ls->ls_orphans_mutex);
+ INIT_LIST_HEAD(&ls->ls_timeout);
+ mutex_init(&ls->ls_timeout_mutex);
INIT_LIST_HEAD(&ls->ls_nodes);
INIT_LIST_HEAD(&ls->ls_nodes_gone);
@@ -477,6 +507,8 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
init_waitqueue_head(&ls->ls_uevent_wait);
ls->ls_uevent_result = 0;
+ init_completion(&ls->ls_members_done);
+ ls->ls_members_result = -1;
ls->ls_recoverd_task = NULL;
mutex_init(&ls->ls_recoverd_active);
@@ -513,32 +545,49 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
error = dlm_recoverd_start(ls);
if (error) {
log_error(ls, "can't start dlm_recoverd %d", error);
- goto out_rcomfree;
+ goto out_delist;
}
- dlm_create_debug_file(ls);
-
error = kobject_setup(ls);
if (error)
- goto out_del;
+ goto out_stop;
error = kobject_register(&ls->ls_kobj);
if (error)
- goto out_del;
+ goto out_stop;
+
+ /* let kobject handle freeing of ls if there's an error */
+ do_unreg = 1;
+
+ /* This uevent triggers dlm_controld in userspace to add us to the
+ group of nodes that are members of this lockspace (managed by the
+ cluster infrastructure.) Once it's done that, it tells us who the
+ current lockspace members are (via configfs) and then tells the
+ lockspace to start running (via sysfs) in dlm_ls_start(). */
error = do_uevent(ls, 1);
if (error)
- goto out_unreg;
+ goto out_stop;
+
+ wait_for_completion(&ls->ls_members_done);
+ error = ls->ls_members_result;
+ if (error)
+ goto out_members;
+
+ dlm_create_debug_file(ls);
+
+ log_debug(ls, "join complete");
*lockspace = ls;
return 0;
- out_unreg:
- kobject_unregister(&ls->ls_kobj);
- out_del:
- dlm_delete_debug_file(ls);
+ out_members:
+ do_uevent(ls, 0);
+ dlm_clear_members(ls);
+ kfree(ls->ls_node_array);
+ out_stop:
dlm_recoverd_stop(ls);
- out_rcomfree:
+ out_delist:
spin_lock(&lslist_lock);
list_del(&ls->ls_list);
spin_unlock(&lslist_lock);
@@ -550,7 +599,10 @@ static int new_lockspace(char *name, int namelen, void **lockspace,
out_rsbfree:
kfree(ls->ls_rsbtbl);
out_lsfree:
- kfree(ls);
+ if (do_unreg)
+ kobject_unregister(&ls->ls_kobj);
+ else
+ kfree(ls);
out:
module_put(THIS_MODULE);
return error;
@@ -570,6 +622,8 @@ int dlm_new_lockspace(char *name, int namelen, void **lockspace,
error = new_lockspace(name, namelen, lockspace, flags, lvblen);
if (!error)
ls_count++;
+ else if (!ls_count)
+ threads_stop();
out:
mutex_unlock(&ls_lock);
return error;
@@ -696,7 +750,7 @@ static int release_lockspace(struct dlm_ls *ls, int force)
dlm_clear_members_gone(ls);
kfree(ls->ls_node_array);
kobject_unregister(&ls->ls_kobj);
- /* The ls structure will be freed when the kobject is done with */
+ /* The ls structure will be freed when the kobject is done with */
mutex_lock(&ls_lock);
ls_count--;
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 27970a58d29..0553a6158dc 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -260,7 +260,7 @@ static int nodeid_to_addr(int nodeid, struct sockaddr *retaddr)
static void lowcomms_data_ready(struct sock *sk, int count_unused)
{
struct connection *con = sock2con(sk);
- if (!test_and_set_bit(CF_READ_PENDING, &con->flags))
+ if (con && !test_and_set_bit(CF_READ_PENDING, &con->flags))
queue_work(recv_workqueue, &con->rwork);
}
@@ -268,7 +268,7 @@ static void lowcomms_write_space(struct sock *sk)
{
struct connection *con = sock2con(sk);
- if (!test_and_set_bit(CF_WRITE_PENDING, &con->flags))
+ if (con && !test_and_set_bit(CF_WRITE_PENDING, &con->flags))
queue_work(send_workqueue, &con->swork);
}
@@ -720,11 +720,17 @@ static int tcp_accept_from_sock(struct connection *con)
INIT_WORK(&othercon->rwork, process_recv_sockets);
set_bit(CF_IS_OTHERCON, &othercon->flags);
newcon->othercon = othercon;
+ othercon->sock = newsock;
+ newsock->sk->sk_user_data = othercon;
+ add_sock(newsock, othercon);
+ addcon = othercon;
+ }
+ else {
+ printk("Extra connection from node %d attempted\n", nodeid);
+ result = -EAGAIN;
+ mutex_unlock(&newcon->sock_mutex);
+ goto accept_err;
}
- othercon->sock = newsock;
- newsock->sk->sk_user_data = othercon;
- add_sock(newsock, othercon);
- addcon = othercon;
}
else {
newsock->sk->sk_user_data = newcon;
@@ -1400,8 +1406,11 @@ void dlm_lowcomms_stop(void)
down(&connections_lock);
for (i = 0; i <= max_nodeid; i++) {
con = __nodeid2con(i, 0);
- if (con)
+ if (con) {
con->flags |= 0xFF;
+ if (con->sock)
+ con->sock->sk->sk_user_data = NULL;
+ }
}
up(&connections_lock);
diff --git a/fs/dlm/main.c b/fs/dlm/main.c
index 162fbae58fe..eca2907f238 100644
--- a/fs/dlm/main.c
+++ b/fs/dlm/main.c
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -25,6 +25,8 @@ void dlm_unregister_debugfs(void);
static inline int dlm_register_debugfs(void) { return 0; }
static inline void dlm_unregister_debugfs(void) { }
#endif
+int dlm_netlink_init(void);
+void dlm_netlink_exit(void);
static int __init init_dlm(void)
{
@@ -50,10 +52,16 @@ static int __init init_dlm(void)
if (error)
goto out_debug;
+ error = dlm_netlink_init();
+ if (error)
+ goto out_user;
+
printk("DLM (built %s %s) installed\n", __DATE__, __TIME__);
return 0;
+ out_user:
+ dlm_user_exit();
out_debug:
dlm_unregister_debugfs();
out_config:
@@ -68,6 +76,7 @@ static int __init init_dlm(void)
static void __exit exit_dlm(void)
{
+ dlm_netlink_exit();
dlm_user_exit();
dlm_config_exit();
dlm_memory_exit();
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 85e2897bd74..073599dced2 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -1,7 +1,7 @@
/******************************************************************************
*******************************************************************************
**
-** Copyright (C) 2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -233,6 +233,12 @@ int dlm_recover_members(struct dlm_ls *ls, struct dlm_recover *rv, int *neg_out)
*neg_out = neg;
error = ping_members(ls);
+ if (!error || error == -EPROTO) {
+ /* new_lockspace() may be waiting to know if the config
+ is good or bad */
+ ls->ls_members_result = error;
+ complete(&ls->ls_members_done);
+ }
if (error)
goto out;
@@ -284,6 +290,9 @@ int dlm_ls_stop(struct dlm_ls *ls)
dlm_recoverd_suspend(ls);
ls->ls_recover_status = 0;
dlm_recoverd_resume(ls);
+
+ if (!ls->ls_recover_begin)
+ ls->ls_recover_begin = jiffies;
return 0;
}
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
new file mode 100644
index 00000000000..863b87d0dc7
--- /dev/null
+++ b/fs/dlm/netlink.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#include <net/genetlink.h>
+#include <linux/dlm.h>
+#include <linux/dlm_netlink.h>
+
+#include "dlm_internal.h"
+
+static uint32_t dlm_nl_seqnum;
+static uint32_t listener_nlpid;
+
+static struct genl_family family = {
+ .id = GENL_ID_GENERATE,
+ .name = DLM_GENL_NAME,
+ .version = DLM_GENL_VERSION,
+};
+
+static int prepare_data(u8 cmd, struct sk_buff **skbp, size_t size)
+{
+ struct sk_buff *skb;
+ void *data;
+
+ skb = genlmsg_new(size, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ /* add the message headers */
+ data = genlmsg_put(skb, 0, dlm_nl_seqnum++, &family, 0, cmd);
+ if (!data) {
+ nlmsg_free(skb);
+ return -EINVAL;
+ }
+
+ *skbp = skb;
+ return 0;
+}
+
+static struct dlm_lock_data *mk_data(struct sk_buff *skb)
+{
+ struct nlattr *ret;
+
+ ret = nla_reserve(skb, DLM_TYPE_LOCK, sizeof(struct dlm_lock_data));
+ if (!ret)
+ return NULL;
+ return nla_data(ret);
+}
+
+static int send_data(struct sk_buff *skb)
+{
+ struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data);
+ void *data = genlmsg_data(genlhdr);
+ int rv;
+
+ rv = genlmsg_end(skb, data);
+ if (rv < 0) {
+ nlmsg_free(skb);
+ return rv;
+ }
+
+ return genlmsg_unicast(skb, listener_nlpid);
+}
+
+static int user_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+ listener_nlpid = info->snd_pid;
+ printk("user_cmd nlpid %u\n", listener_nlpid);
+ return 0;
+}
+
+static struct genl_ops dlm_nl_ops = {
+ .cmd = DLM_CMD_HELLO,
+ .doit = user_cmd,
+};
+
+int dlm_netlink_init(void)
+{
+ int rv;
+
+ rv = genl_register_family(&family);
+ if (rv)
+ return rv;
+
+ rv = genl_register_ops(&family, &dlm_nl_ops);
+ if (rv < 0)
+ goto err;
+ return 0;
+ err:
+ genl_unregister_family(&family);
+ return rv;
+}
+
+void dlm_netlink_exit(void)
+{
+ genl_unregister_ops(&family, &dlm_nl_ops);
+ genl_unregister_family(&family);
+}
+
+static void fill_data(struct dlm_lock_data *data, struct dlm_lkb *lkb)
+{
+ struct dlm_rsb *r = lkb->lkb_resource;
+ struct dlm_user_args *ua = (struct dlm_user_args *) lkb->lkb_astparam;
+
+ memset(data, 0, sizeof(struct dlm_lock_data));
+
+ data->version = DLM_LOCK_DATA_VERSION;
+ data->nodeid = lkb->lkb_nodeid;
+ data->ownpid = lkb->lkb_ownpid;
+ data->id = lkb->lkb_id;
+ data->remid = lkb->lkb_remid;
+ data->status = lkb->lkb_status;
+ data->grmode = lkb->lkb_grmode;
+ data->rqmode = lkb->lkb_rqmode;
+ data->timestamp = lkb->lkb_timestamp;
+ if (ua)
+ data->xid = ua->xid;
+ if (r) {
+ data->lockspace_id = r->res_ls->ls_global_id;
+ data->resource_namelen = r->res_length;
+ memcpy(data->resource_name, r->res_name, r->res_length);
+ }
+}
+
+void dlm_timeout_warn(struct dlm_lkb *lkb)
+{
+ struct dlm_lock_data *data;
+ struct sk_buff *send_skb;
+ size_t size;
+ int rv;
+
+ size = nla_total_size(sizeof(struct dlm_lock_data)) +
+ nla_total_size(0); /* why this? */
+
+ rv = prepare_data(DLM_CMD_TIMEOUT, &send_skb, size);
+ if (rv < 0)
+ return;
+
+ data = mk_data(send_skb);
+ if (!data) {
+ nlmsg_free(send_skb);
+ return;
+ }
+
+ fill_data(data, lkb);
+
+ send_data(send_skb);
+}
+
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 6bfbd615380..e3a1527cbdb 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -38,7 +38,7 @@ static int create_rcom(struct dlm_ls *ls, int to_nodeid, int type, int len,
char *mb;
int mb_len = sizeof(struct dlm_rcom) + len;
- mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, GFP_KERNEL, &mb);
+ mh = dlm_lowcomms_get_buffer(to_nodeid, mb_len, ls->ls_allocation, &mb);
if (!mh) {
log_print("create_rcom to %d type %d len %d ENOBUFS",
to_nodeid, type, len);
@@ -90,7 +90,7 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
log_error(ls, "version mismatch: %x nodeid %d: %x",
DLM_HEADER_MAJOR | DLM_HEADER_MINOR, nodeid,
rc->rc_header.h_version);
- return -EINVAL;
+ return -EPROTO;
}
if (rf->rf_lvblen != ls->ls_lvblen ||
@@ -98,7 +98,7 @@ static int check_config(struct dlm_ls *ls, struct dlm_rcom *rc, int nodeid)
log_error(ls, "config mismatch: %d,%x nodeid %d: %d,%x",
ls->ls_lvblen, ls->ls_exflags,
nodeid, rf->rf_lvblen, rf->rf_lsflags);
- return -EINVAL;
+ return -EPROTO;
}
return 0;
}
@@ -386,7 +386,8 @@ static void receive_rcom_lock_reply(struct dlm_ls *ls, struct dlm_rcom *rc_in)
dlm_recover_process_copy(ls, rc_in);
}
-static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
+static int send_ls_not_ready(struct dlm_ls *ls, int nodeid,
+ struct dlm_rcom *rc_in)
{
struct dlm_rcom *rc;
struct rcom_config *rf;
@@ -394,7 +395,7 @@ static int send_ls_not_ready(int nodeid, struct dlm_rcom *rc_in)
char *mb;
int mb_len = sizeof(struct dlm_rcom) + sizeof(struct rcom_config);
- mh = dlm_lowcomms_get_buffer(nodeid, mb_len, GFP_KERNEL, &mb);
+ mh = dlm_lowcomms_get_buffer(nodeid, mb_len, ls->ls_allocation, &mb);
if (!mh)
return -ENOBUFS;
memset(mb, 0, mb_len);
@@ -464,7 +465,7 @@ void dlm_receive_rcom(struct dlm_header *hd, int nodeid)
log_print("lockspace %x from %d type %x not found",
hd->h_lockspace, nodeid, rc->rc_type);
if (rc->rc_type == DLM_RCOM_STATUS)
- send_ls_not_ready(nodeid, rc);
+ send_ls_not_ready(ls, nodeid, rc);
return;
}
diff --git a/fs/dlm/recoverd.c b/fs/dlm/recoverd.c
index 3cb636d6024..66575997861 100644
--- a/fs/dlm/recoverd.c
+++ b/fs/dlm/recoverd.c
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -190,6 +190,8 @@ static int ls_recover(struct dlm_ls *ls, struct dlm_recover *rv)
dlm_clear_members_gone(ls);
+ dlm_adjust_timeouts(ls);
+
error = enable_locking(ls, rv->seq);
if (error) {
log_debug(ls, "enable_locking failed %d", error);
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index b0201ec325a..6438941ab1f 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -33,16 +33,17 @@ static const struct file_operations device_fops;
struct dlm_lock_params32 {
__u8 mode;
__u8 namelen;
- __u16 flags;
+ __u16 unused;
+ __u32 flags;
__u32 lkid;
__u32 parent;
-
+ __u64 xid;
+ __u64 timeout;
__u32 castparam;
__u32 castaddr;
__u32 bastparam;
__u32 bastaddr;
__u32 lksb;
-
char lvb[DLM_USER_LVB_LEN];
char name[0];
};
@@ -68,6 +69,7 @@ struct dlm_lksb32 {
};
struct dlm_lock_result32 {
+ __u32 version[3];
__u32 length;
__u32 user_astaddr;
__u32 user_astparam;
@@ -102,6 +104,8 @@ static void compat_input(struct dlm_write_request *kb,
kb->i.lock.flags = kb32->i.lock.flags;
kb->i.lock.lkid = kb32->i.lock.lkid;
kb->i.lock.parent = kb32->i.lock.parent;
+ kb->i.lock.xid = kb32->i.lock.xid;
+ kb->i.lock.timeout = kb32->i.lock.timeout;
kb->i.lock.castparam = (void *)(long)kb32->i.lock.castparam;
kb->i.lock.castaddr = (void *)(long)kb32->i.lock.castaddr;
kb->i.lock.bastparam = (void *)(long)kb32->i.lock.bastparam;
@@ -115,6 +119,10 @@ static void compat_input(struct dlm_write_request *kb,
static void compat_output(struct dlm_lock_result *res,
struct dlm_lock_result32 *res32)
{
+ res32->version[0] = res->version[0];
+ res32->version[1] = res->version[1];
+ res32->version[2] = res->version[2];
+
res32->user_astaddr = (__u32)(long)res->user_astaddr;
res32->user_astparam = (__u32)(long)res->user_astparam;
res32->user_lksb = (__u32)(long)res->user_lksb;
@@ -130,6 +138,36 @@ static void compat_output(struct dlm_lock_result *res,
}
#endif
+/* Figure out if this lock is at the end of its life and no longer
+ available for the application to use. The lkb still exists until
+ the final ast is read. A lock becomes EOL in three situations:
+ 1. a noqueue request fails with EAGAIN
+ 2. an unlock completes with EUNLOCK
+ 3. a cancel of a waiting request completes with ECANCEL/EDEADLK
+ An EOL lock needs to be removed from the process's list of locks.
+ And we can't allow any new operation on an EOL lock. This is
+ not related to the lifetime of the lkb struct which is managed
+ entirely by refcount. */
+
+static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
+{
+ switch (sb_status) {
+ case -DLM_EUNLOCK:
+ return 1;
+ case -DLM_ECANCEL:
+ case -ETIMEDOUT:
+ case -EDEADLK:
+ if (lkb->lkb_grmode == DLM_LOCK_IV)
+ return 1;
+ break;
+ case -EAGAIN:
+ if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
/* we could possibly check if the cancel of an orphan has resulted in the lkb
being removed and then remove that lkb from the orphans list and free it */
@@ -176,25 +214,7 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type)
log_debug(ls, "ast overlap %x status %x %x",
lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
- /* Figure out if this lock is at the end of its life and no longer
- available for the application to use. The lkb still exists until
- the final ast is read. A lock becomes EOL in three situations:
- 1. a noqueue request fails with EAGAIN
- 2. an unlock completes with EUNLOCK
- 3. a cancel of a waiting request completes with ECANCEL
- An EOL lock needs to be removed from the process's list of locks.
- And we can't allow any new operation on an EOL lock. This is
- not related to the lifetime of the lkb struct which is managed
- entirely by refcount. */
-
- if (type == AST_COMP &&
- lkb->lkb_grmode == DLM_LOCK_IV &&
- ua->lksb.sb_status == -EAGAIN)
- eol = 1;
- else if (ua->lksb.sb_status == -DLM_EUNLOCK ||
- (ua->lksb.sb_status == -DLM_ECANCEL &&
- lkb->lkb_grmode == DLM_LOCK_IV))
- eol = 1;
+ eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type);
if (eol) {
lkb->lkb_ast_type &= ~AST_BAST;
lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
@@ -252,16 +272,18 @@ static int device_user_lock(struct dlm_user_proc *proc,
ua->castaddr = params->castaddr;
ua->bastparam = params->bastparam;
ua->bastaddr = params->bastaddr;
+ ua->xid = params->xid;
if (params->flags & DLM_LKF_CONVERT)
error = dlm_user_convert(ls, ua,
params->mode, params->flags,
- params->lkid, params->lvb);
+ params->lkid, params->lvb,
+ (unsigned long) params->timeout);
else {
error = dlm_user_request(ls, ua,
params->mode, params->flags,
params->name, params->namelen,
- params->parent);
+ (unsigned long) params->timeout);
if (!error)
error = ua->lksb.sb_lkid;
}
@@ -299,6 +321,22 @@ static int device_user_unlock(struct dlm_user_proc *proc,
return error;
}
+static int device_user_deadlock(struct dlm_user_proc *proc,
+ struct dlm_lock_params *params)
+{
+ struct dlm_ls *ls;
+ int error;
+
+ ls = dlm_find_lockspace_local(proc->lockspace);
+ if (!ls)
+ return -ENOENT;
+
+ error = dlm_user_deadlock(ls, params->flags, params->lkid);
+
+ dlm_put_lockspace(ls);
+ return error;
+}
+
static int create_misc_device(struct dlm_ls *ls, char *name)
{
int error, len;
@@ -348,7 +386,7 @@ static int device_create_lockspace(struct dlm_lspace_params *params)
return -EPERM;
error = dlm_new_lockspace(params->name, strlen(params->name),
- &lockspace, 0, DLM_USER_LVB_LEN);
+ &lockspace, params->flags, DLM_USER_LVB_LEN);
if (error)
return error;
@@ -524,6 +562,14 @@ static ssize_t device_write(struct file *file, const char __user *buf,
error = device_user_unlock(proc, &kbuf->i.lock);
break;
+ case DLM_USER_DEADLOCK:
+ if (!proc) {
+ log_print("no locking on control device");
+ goto out_sig;
+ }
+ error = device_user_deadlock(proc, &kbuf->i.lock);
+ break;
+
case DLM_USER_CREATE_LOCKSPACE:
if (proc) {
log_print("create/remove only on control device");
@@ -641,6 +687,9 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
int struct_len;
memset(&result, 0, sizeof(struct dlm_lock_result));
+ result.version[0] = DLM_DEVICE_VERSION_MAJOR;
+ result.version[1] = DLM_DEVICE_VERSION_MINOR;
+ result.version[2] = DLM_DEVICE_VERSION_PATCH;
memcpy(&result.lksb, &ua->lksb, sizeof(struct dlm_lksb));
result.user_lksb = ua->user_lksb;
@@ -699,6 +748,20 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
return error;
}
+static int copy_version_to_user(char __user *buf, size_t count)
+{
+ struct dlm_device_version ver;
+
+ memset(&ver, 0, sizeof(struct dlm_device_version));
+ ver.version[0] = DLM_DEVICE_VERSION_MAJOR;
+ ver.version[1] = DLM_DEVICE_VERSION_MINOR;
+ ver.version[2] = DLM_DEVICE_VERSION_PATCH;
+
+ if (copy_to_user(buf, &ver, sizeof(struct dlm_device_version)))
+ return -EFAULT;
+ return sizeof(struct dlm_device_version);
+}
+
/* a read returns a single ast described in a struct dlm_lock_result */
static ssize_t device_read(struct file *file, char __user *buf, size_t count,
@@ -710,6 +773,16 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
DECLARE_WAITQUEUE(wait, current);
int error, type=0, bmode=0, removed = 0;
+ if (count == sizeof(struct dlm_device_version)) {
+ error = copy_version_to_user(buf, count);
+ return error;
+ }
+
+ if (!proc) {
+ log_print("non-version read from control device %zu", count);
+ return -EINVAL;
+ }
+
#ifdef CONFIG_COMPAT
if (count < sizeof(struct dlm_lock_result32))
#else
@@ -747,11 +820,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
}
}
- if (list_empty(&proc->asts)) {
- spin_unlock(&proc->asts_spin);
- return -EAGAIN;
- }
-
/* there may be both completion and blocking asts to return for
the lkb, don't remove lkb from asts list unless no asts remain */
@@ -823,6 +891,7 @@ static const struct file_operations device_fops = {
static const struct file_operations ctl_device_fops = {
.open = ctl_device_open,
.release = ctl_device_close,
+ .read = device_read,
.write = device_write,
.owner = THIS_MODULE,
};
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 403e3bad145..1b9dd9a96f1 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -580,5 +580,7 @@ void
ecryptfs_write_header_metadata(char *virt,
struct ecryptfs_crypt_stat *crypt_stat,
size_t *written);
+int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start,
+ int num_zeros);
#endif /* #ifndef ECRYPTFS_KERNEL_H */
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c
index 59288d81707..94f456fe4d9 100644
--- a/fs/ecryptfs/file.c
+++ b/fs/ecryptfs/file.c
@@ -338,16 +338,17 @@ static int ecryptfs_fasync(int fd, struct file *file, int flag)
return rc;
}
-static ssize_t ecryptfs_sendfile(struct file *file, loff_t * ppos,
- size_t count, read_actor_t actor, void *target)
+static ssize_t ecryptfs_splice_read(struct file *file, loff_t * ppos,
+ struct pipe_inode_info *pipe, size_t count,
+ unsigned int flags)
{
struct file *lower_file = NULL;
int rc = -EINVAL;
lower_file = ecryptfs_file_to_lower(file);
- if (lower_file->f_op && lower_file->f_op->sendfile)
- rc = lower_file->f_op->sendfile(lower_file, ppos, count,
- actor, target);
+ if (lower_file->f_op && lower_file->f_op->splice_read)
+ rc = lower_file->f_op->splice_read(lower_file, ppos, pipe,
+ count, flags);
return rc;
}
@@ -364,7 +365,7 @@ const struct file_operations ecryptfs_dir_fops = {
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
- .sendfile = ecryptfs_sendfile,
+ .splice_read = ecryptfs_splice_read,
};
const struct file_operations ecryptfs_main_fops = {
@@ -381,7 +382,7 @@ const struct file_operations ecryptfs_main_fops = {
.release = ecryptfs_release,
.fsync = ecryptfs_fsync,
.fasync = ecryptfs_fasync,
- .sendfile = ecryptfs_sendfile,
+ .splice_read = ecryptfs_splice_read,
};
static int
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 1548be26b5e..83e94fedd4e 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -800,6 +800,25 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
goto out_fput;
}
} else { /* new_length < i_size_read(inode) */
+ pgoff_t index = 0;
+ int end_pos_in_page = -1;
+
+ if (new_length != 0) {
+ index = ((new_length - 1) >> PAGE_CACHE_SHIFT);
+ end_pos_in_page = ((new_length - 1) & ~PAGE_CACHE_MASK);
+ }
+ if (end_pos_in_page != (PAGE_CACHE_SIZE - 1)) {
+ if ((rc = ecryptfs_write_zeros(&fake_ecryptfs_file,
+ index,
+ (end_pos_in_page + 1),
+ ((PAGE_CACHE_SIZE - 1)
+ - end_pos_in_page)))) {
+ printk(KERN_ERR "Error attempting to zero out "
+ "the remainder of the end page on "
+ "reducing truncate; rc = [%d]\n", rc);
+ goto out_fput;
+ }
+ }
vmtruncate(inode, new_length);
rc = ecryptfs_write_inode_size_to_metadata(
lower_file, lower_dentry->d_inode, inode, dentry,
@@ -875,9 +894,54 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
struct ecryptfs_crypt_stat *crypt_stat;
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
- lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
+ ecryptfs_init_crypt_stat(crypt_stat);
inode = dentry->d_inode;
lower_inode = ecryptfs_inode_to_lower(inode);
+ lower_dentry = ecryptfs_dentry_to_lower(dentry);
+ mutex_lock(&crypt_stat->cs_mutex);
+ if (S_ISDIR(dentry->d_inode->i_mode))
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+ else if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED)
+ || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
+ struct vfsmount *lower_mnt;
+ struct file *lower_file = NULL;
+ struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
+ int lower_flags;
+
+ lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+ lower_flags = O_RDONLY;
+ if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry,
+ lower_mnt, lower_flags))) {
+ printk(KERN_ERR
+ "Error opening lower file; rc = [%d]\n", rc);
+ mutex_unlock(&crypt_stat->cs_mutex);
+ goto out;
+ }
+ mount_crypt_stat = &ecryptfs_superblock_to_private(
+ dentry->d_sb)->mount_crypt_stat;
+ if ((rc = ecryptfs_read_metadata(dentry, lower_file))) {
+ if (!(mount_crypt_stat->flags
+ & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
+ rc = -EIO;
+ printk(KERN_WARNING "Attempt to read file that "
+ "is not in a valid eCryptfs format, "
+ "and plaintext passthrough mode is not "
+ "enabled; returning -EIO\n");
+
+ mutex_unlock(&crypt_stat->cs_mutex);
+ fput(lower_file);
+ goto out;
+ }
+ rc = 0;
+ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+ mutex_unlock(&crypt_stat->cs_mutex);
+ fput(lower_file);
+ goto out;
+ }
+ fput(lower_file);
+ }
+ mutex_unlock(&crypt_stat->cs_mutex);
if (ia->ia_valid & ATTR_SIZE) {
ecryptfs_printk(KERN_DEBUG,
"ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n",
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 606128f5c92..02ca6f1e55d 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -840,8 +840,6 @@ static int __init ecryptfs_init(void)
goto out;
}
kobj_set_kset_s(&ecryptfs_subsys, fs_subsys);
- sysfs_attr_version.attr.owner = THIS_MODULE;
- sysfs_attr_version_str.attr.owner = THIS_MODULE;
rc = do_sysfs_registration();
if (rc) {
printk(KERN_ERR "sysfs registration failed\n");
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 55cec98a84e..7d5a43cb0d5 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -56,9 +56,6 @@ static struct page *ecryptfs_get1page(struct file *file, int index)
return read_mapping_page(mapping, index, (void *)file);
}
-static
-int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros);
-
/**
* ecryptfs_fill_zeros
* @file: The ecryptfs file
@@ -101,10 +98,13 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length)
if (old_end_page_index == new_end_page_index) {
/* Start and end are in the same page; we just need to
* set a portion of the existing page to zero's */
- rc = write_zeros(file, index, (old_end_pos_in_page + 1),
- (new_end_pos_in_page - old_end_pos_in_page));
+ rc = ecryptfs_write_zeros(file, index,
+ (old_end_pos_in_page + 1),
+ (new_end_pos_in_page
+ - old_end_pos_in_page));
if (rc)
- ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], "
+ ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros("
+ "file=[%p], "
"index=[0x%.16x], "
"old_end_pos_in_page=[d], "
"(PAGE_CACHE_SIZE - new_end_pos_in_page"
@@ -117,10 +117,10 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length)
goto out;
}
/* Fill the remainder of the previous last page with zeros */
- rc = write_zeros(file, index, (old_end_pos_in_page + 1),
+ rc = ecryptfs_write_zeros(file, index, (old_end_pos_in_page + 1),
((PAGE_CACHE_SIZE - 1) - old_end_pos_in_page));
if (rc) {
- ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], "
+ ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(file=[%p], "
"index=[0x%.16x], old_end_pos_in_page=[d], "
"(PAGE_CACHE_SIZE - old_end_pos_in_page)=[d]) "
"returned [%d]\n", file, index,
@@ -131,9 +131,10 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length)
index++;
while (index < new_end_page_index) {
/* Fill all intermediate pages with zeros */
- rc = write_zeros(file, index, 0, PAGE_CACHE_SIZE);
+ rc = ecryptfs_write_zeros(file, index, 0, PAGE_CACHE_SIZE);
if (rc) {
- ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], "
+ ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros("
+ "file=[%p], "
"index=[0x%.16x], "
"old_end_pos_in_page=[d], "
"(PAGE_CACHE_SIZE - new_end_pos_in_page"
@@ -149,9 +150,9 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length)
}
/* Fill the portion at the beginning of the last new page with
* zero's */
- rc = write_zeros(file, index, 0, (new_end_pos_in_page + 1));
+ rc = ecryptfs_write_zeros(file, index, 0, (new_end_pos_in_page + 1));
if (rc) {
- ecryptfs_printk(KERN_ERR, "write_zeros(file="
+ ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(file="
"[%p], index=[0x%.16x], 0, "
"new_end_pos_in_page=[%d]"
"returned [%d]\n", file, index,
@@ -400,7 +401,6 @@ out:
static int ecryptfs_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
- loff_t pos;
int rc = 0;
if (from == 0 && to == PAGE_CACHE_SIZE)
@@ -408,15 +408,22 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
up to date. */
if (!PageUptodate(page))
rc = ecryptfs_do_readpage(file, page, page->index);
- pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
- if (pos > i_size_read(page->mapping->host)) {
- rc = ecryptfs_truncate(file->f_path.dentry, pos);
- if (rc) {
- printk(KERN_ERR "Error on attempt to "
- "truncate to (higher) offset [%lld];"
- " rc = [%d]\n", pos, rc);
- goto out;
+ if (page->index != 0) {
+ loff_t end_of_prev_pg_pos =
+ (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1);
+
+ if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) {
+ rc = ecryptfs_truncate(file->f_path.dentry,
+ end_of_prev_pg_pos);
+ if (rc) {
+ printk(KERN_ERR "Error on attempt to "
+ "truncate to (higher) offset [%lld];"
+ " rc = [%d]\n", end_of_prev_pg_pos, rc);
+ goto out;
+ }
}
+ if (end_of_prev_pg_pos + 1 > i_size_read(page->mapping->host))
+ zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
}
out:
return rc;
@@ -753,7 +760,7 @@ out:
}
/**
- * write_zeros
+ * ecryptfs_write_zeros
* @file: The ecryptfs file
* @index: The index in which we are writing
* @start: The position after the last block of data
@@ -763,8 +770,8 @@ out:
*
* (start + num_zeros) must be less than or equal to PAGE_CACHE_SIZE
*/
-static
-int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
+int
+ecryptfs_write_zeros(struct file *file, pgoff_t index, int start, int num_zeros)
{
int rc = 0;
struct page *tmp_page;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 566d4e2d385..04afeecaaef 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -53,7 +53,6 @@ const struct file_operations ext2_file_operations = {
.open = generic_file_open,
.release = ext2_release_file,
.fsync = ext2_sync_file,
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
@@ -71,7 +70,6 @@ const struct file_operations ext2_xip_file_operations = {
.open = generic_file_open,
.release = ext2_release_file,
.fsync = ext2_sync_file,
- .sendfile = xip_file_sendfile,
};
#endif
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 16337bff027..5de5061eb33 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -1038,6 +1038,15 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+ ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
+ EXT2_MOUNT_XIP if not */
+
+ if ((ext2_use_xip(sb)) && (sb->s_blocksize != PAGE_SIZE)) {
+ printk("XIP: Unsupported blocksize\n");
+ err = -EINVAL;
+ goto restore_opts;
+ }
+
es = sbi->s_es;
if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
(old_mount_opt & EXT2_MOUNT_XIP)) &&
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 1e6f1386453..acc4913d301 100644
--- a/fs/ext3/file.c
+++ b/fs/ext3/file.c
@@ -120,7 +120,6 @@ const struct file_operations ext3_file_operations = {
.open = generic_file_open,
.release = ext3_release_file,
.fsync = ext3_sync_file,
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index a6cb6171c3a..2a85ddee474 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2677,8 +2677,10 @@ void ext3_read_inode(struct inode * inode)
*/
ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
if (EXT3_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
- EXT3_INODE_SIZE(inode->i_sb))
+ EXT3_INODE_SIZE(inode->i_sb)) {
+ brelse (bh);
goto bad_inode;
+ }
if (ei->i_extra_isize == 0) {
/* The extra space is currently unused. Use it. */
ei->i_extra_isize = sizeof(struct ext3_inode) -
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 8a23483ca8d..3b64bb16c72 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -30,15 +30,15 @@
void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
unsigned long *blockgrpp, ext4_grpblk_t *offsetp)
{
- struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;
ext4_grpblk_t offset;
- blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
+ blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
if (offsetp)
*offsetp = offset;
if (blockgrpp)
- *blockgrpp = blocknr;
+ *blockgrpp = blocknr;
}
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index a0f0c04e79b..b9ce2412907 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -374,7 +374,7 @@ ext4_ext_binsearch_idx(struct inode *inode, struct ext4_ext_path *path, int bloc
le32_to_cpu(ix[-1].ei_block));
}
BUG_ON(k && le32_to_cpu(ix->ei_block)
- <= le32_to_cpu(ix[-1].ei_block));
+ <= le32_to_cpu(ix[-1].ei_block));
if (block < le32_to_cpu(ix->ei_block))
break;
chix = ix;
@@ -423,8 +423,8 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block)
path->p_ext = l - 1;
ext_debug(" -> %d:%llu:%d ",
- le32_to_cpu(path->p_ext->ee_block),
- ext_pblock(path->p_ext),
+ le32_to_cpu(path->p_ext->ee_block),
+ ext_pblock(path->p_ext),
le16_to_cpu(path->p_ext->ee_len));
#ifdef CHECK_BINSEARCH
@@ -435,7 +435,7 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block)
chex = ex = EXT_FIRST_EXTENT(eh);
for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ex++) {
BUG_ON(k && le32_to_cpu(ex->ee_block)
- <= le32_to_cpu(ex[-1].ee_block));
+ <= le32_to_cpu(ex[-1].ee_block));
if (block < le32_to_cpu(ex->ee_block))
break;
chex = ex;
@@ -577,7 +577,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode,
curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1);
BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries)
- > le16_to_cpu(curp->p_hdr->eh_max));
+ > le16_to_cpu(curp->p_hdr->eh_max));
BUG_ON(ix > EXT_LAST_INDEX(curp->p_hdr));
err = ext4_ext_dirty(handle, inode, curp);
@@ -621,12 +621,12 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
border = path[depth].p_ext[1].ee_block;
ext_debug("leaf will be split."
" next leaf starts at %d\n",
- le32_to_cpu(border));
+ le32_to_cpu(border));
} else {
border = newext->ee_block;
ext_debug("leaf will be added."
" next leaf starts at %d\n",
- le32_to_cpu(border));
+ le32_to_cpu(border));
}
/*
@@ -684,9 +684,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
while (path[depth].p_ext <=
EXT_MAX_EXTENT(path[depth].p_hdr)) {
ext_debug("move %d:%llu:%d in new leaf %llu\n",
- le32_to_cpu(path[depth].p_ext->ee_block),
- ext_pblock(path[depth].p_ext),
- le16_to_cpu(path[depth].p_ext->ee_len),
+ le32_to_cpu(path[depth].p_ext->ee_block),
+ ext_pblock(path[depth].p_ext),
+ le16_to_cpu(path[depth].p_ext->ee_len),
newblock);
/*memmove(ex++, path[depth].p_ext++,
sizeof(struct ext4_extent));
@@ -765,9 +765,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
EXT_LAST_INDEX(path[i].p_hdr));
while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) {
ext_debug("%d: move %d:%d in new index %llu\n", i,
- le32_to_cpu(path[i].p_idx->ei_block),
- idx_pblock(path[i].p_idx),
- newblock);
+ le32_to_cpu(path[i].p_idx->ei_block),
+ idx_pblock(path[i].p_idx),
+ newblock);
/*memmove(++fidx, path[i].p_idx++,
sizeof(struct ext4_extent_idx));
neh->eh_entries++;
@@ -1128,6 +1128,55 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
}
/*
+ * check if a portion of the "newext" extent overlaps with an
+ * existing extent.
+ *
+ * If there is an overlap discovered, it updates the length of the newext
+ * such that there will be no overlap, and then returns 1.
+ * If there is no overlap found, it returns 0.
+ */
+unsigned int ext4_ext_check_overlap(struct inode *inode,
+ struct ext4_extent *newext,
+ struct ext4_ext_path *path)
+{
+ unsigned long b1, b2;
+ unsigned int depth, len1;
+ unsigned int ret = 0;
+
+ b1 = le32_to_cpu(newext->ee_block);
+ len1 = le16_to_cpu(newext->ee_len);
+ depth = ext_depth(inode);
+ if (!path[depth].p_ext)
+ goto out;
+ b2 = le32_to_cpu(path[depth].p_ext->ee_block);
+
+ /*
+ * get the next allocated block if the extent in the path
+ * is before the requested block(s)
+ */
+ if (b2 < b1) {
+ b2 = ext4_ext_next_allocated_block(path);
+ if (b2 == EXT_MAX_BLOCK)
+ goto out;
+ }
+
+ /* check for wrap through zero */
+ if (b1 + len1 < b1) {
+ len1 = EXT_MAX_BLOCK - b1;
+ newext->ee_len = cpu_to_le16(len1);
+ ret = 1;
+ }
+
+ /* check for overlap */
+ if (b1 + len1 > b2) {
+ newext->ee_len = cpu_to_le16(b2 - b1);
+ ret = 1;
+ }
+out:
+ return ret;
+}
+
+/*
* ext4_ext_insert_extent:
* tries to merge requsted extent into the existing extent or
* inserts requested extent as new one into the tree,
@@ -1212,12 +1261,12 @@ has_space:
if (!nearex) {
/* there is no extent in this leaf, create first one */
ext_debug("first extent in the leaf: %d:%llu:%d\n",
- le32_to_cpu(newext->ee_block),
- ext_pblock(newext),
- le16_to_cpu(newext->ee_len));
+ le32_to_cpu(newext->ee_block),
+ ext_pblock(newext),
+ le16_to_cpu(newext->ee_len));
path[depth].p_ext = EXT_FIRST_EXTENT(eh);
} else if (le32_to_cpu(newext->ee_block)
- > le32_to_cpu(nearex->ee_block)) {
+ > le32_to_cpu(nearex->ee_block)) {
/* BUG_ON(newext->ee_block == nearex->ee_block); */
if (nearex != EXT_LAST_EXTENT(eh)) {
len = EXT_MAX_EXTENT(eh) - nearex;
@@ -1225,9 +1274,9 @@ has_space:
len = len < 0 ? 0 : len;
ext_debug("insert %d:%llu:%d after: nearest 0x%p, "
"move %d from 0x%p to 0x%p\n",
- le32_to_cpu(newext->ee_block),
- ext_pblock(newext),
- le16_to_cpu(newext->ee_len),
+ le32_to_cpu(newext->ee_block),
+ ext_pblock(newext),
+ le16_to_cpu(newext->ee_len),
nearex, len, nearex + 1, nearex + 2);
memmove(nearex + 2, nearex + 1, len);
}
@@ -1358,9 +1407,9 @@ int ext4_ext_walk_space(struct inode *inode, unsigned long block,
cbex.ec_start = 0;
cbex.ec_type = EXT4_EXT_CACHE_GAP;
} else {
- cbex.ec_block = le32_to_cpu(ex->ee_block);
- cbex.ec_len = le16_to_cpu(ex->ee_len);
- cbex.ec_start = ext_pblock(ex);
+ cbex.ec_block = le32_to_cpu(ex->ee_block);
+ cbex.ec_len = le16_to_cpu(ex->ee_len);
+ cbex.ec_start = ext_pblock(ex);
cbex.ec_type = EXT4_EXT_CACHE_EXTENT;
}
@@ -1431,16 +1480,16 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
len = le32_to_cpu(ex->ee_block) - block;
ext_debug("cache gap(before): %lu [%lu:%lu]",
(unsigned long) block,
- (unsigned long) le32_to_cpu(ex->ee_block),
- (unsigned long) le16_to_cpu(ex->ee_len));
+ (unsigned long) le32_to_cpu(ex->ee_block),
+ (unsigned long) le16_to_cpu(ex->ee_len));
} else if (block >= le32_to_cpu(ex->ee_block)
- + le16_to_cpu(ex->ee_len)) {
- lblock = le32_to_cpu(ex->ee_block)
- + le16_to_cpu(ex->ee_len);
+ + le16_to_cpu(ex->ee_len)) {
+ lblock = le32_to_cpu(ex->ee_block)
+ + le16_to_cpu(ex->ee_len);
len = ext4_ext_next_allocated_block(path);
ext_debug("cache gap(after): [%lu:%lu] %lu",
- (unsigned long) le32_to_cpu(ex->ee_block),
- (unsigned long) le16_to_cpu(ex->ee_len),
+ (unsigned long) le32_to_cpu(ex->ee_block),
+ (unsigned long) le16_to_cpu(ex->ee_len),
(unsigned long) block);
BUG_ON(len == lblock);
len = len - lblock;
@@ -1468,9 +1517,9 @@ ext4_ext_in_cache(struct inode *inode, unsigned long block,
BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
cex->ec_type != EXT4_EXT_CACHE_EXTENT);
if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) {
- ex->ee_block = cpu_to_le32(cex->ec_block);
+ ex->ee_block = cpu_to_le32(cex->ec_block);
ext4_ext_store_pblock(ex, cex->ec_start);
- ex->ee_len = cpu_to_le16(cex->ec_len);
+ ex->ee_len = cpu_to_le16(cex->ec_len);
ext_debug("%lu cached by %lu:%lu:%llu\n",
(unsigned long) block,
(unsigned long) cex->ec_block,
@@ -1956,9 +2005,9 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
/* we should allocate requested block */
} else if (goal == EXT4_EXT_CACHE_EXTENT) {
/* block is already allocated */
- newblock = iblock
- - le32_to_cpu(newex.ee_block)
- + ext_pblock(&newex);
+ newblock = iblock
+ - le32_to_cpu(newex.ee_block)
+ + ext_pblock(&newex);
/* number of remaining blocks in the extent */
allocated = le16_to_cpu(newex.ee_len) -
(iblock - le32_to_cpu(newex.ee_block));
@@ -1987,7 +2036,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
ex = path[depth].p_ext;
if (ex) {
- unsigned long ee_block = le32_to_cpu(ex->ee_block);
+ unsigned long ee_block = le32_to_cpu(ex->ee_block);
ext4_fsblk_t ee_start = ext_pblock(ex);
unsigned short ee_len = le16_to_cpu(ex->ee_len);
@@ -2000,7 +2049,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
if (ee_len > EXT_MAX_LEN)
goto out2;
/* if found extent covers block, simply return it */
- if (iblock >= ee_block && iblock < ee_block + ee_len) {
+ if (iblock >= ee_block && iblock < ee_block + ee_len) {
newblock = iblock - ee_block + ee_start;
/* number of remaining blocks in the extent */
allocated = ee_len - (iblock - ee_block);
@@ -2031,7 +2080,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
/* allocate new block */
goal = ext4_ext_find_goal(inode, path, iblock);
- allocated = max_blocks;
+
+ /* Check if we can really insert (iblock)::(iblock+max_blocks) extent */
+ newex.ee_block = cpu_to_le32(iblock);
+ newex.ee_len = cpu_to_le16(max_blocks);
+ err = ext4_ext_check_overlap(inode, &newex, path);
+ if (err)
+ allocated = le16_to_cpu(newex.ee_len);
+ else
+ allocated = max_blocks;
newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err);
if (!newblock)
goto out2;
@@ -2039,12 +2096,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
goal, newblock, allocated);
/* try to insert new extent into found leaf and return */
- newex.ee_block = cpu_to_le32(iblock);
ext4_ext_store_pblock(&newex, newblock);
newex.ee_len = cpu_to_le16(allocated);
err = ext4_ext_insert_extent(handle, inode, path, &newex);
- if (err)
+ if (err) {
+ /* free data blocks we just allocated */
+ ext4_free_blocks(handle, inode, ext_pblock(&newex),
+ le16_to_cpu(newex.ee_len));
goto out2;
+ }
if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize)
EXT4_I(inode)->i_disksize = inode->i_size;
@@ -2157,11 +2217,3 @@ int ext4_ext_writepage_trans_blocks(struct inode *inode, int num)
return needed;
}
-
-EXPORT_SYMBOL(ext4_mark_inode_dirty);
-EXPORT_SYMBOL(ext4_ext_invalidate_cache);
-EXPORT_SYMBOL(ext4_ext_insert_extent);
-EXPORT_SYMBOL(ext4_ext_walk_space);
-EXPORT_SYMBOL(ext4_ext_find_goal);
-EXPORT_SYMBOL(ext4_ext_calc_credits_for_insert);
-
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 3c6c1fd2be9..d4c8186aed6 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -120,7 +120,6 @@ const struct file_operations ext4_file_operations = {
.open = generic_file_open,
.release = ext4_release_file,
.fsync = ext4_sync_file,
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index b34182b6ee4..8416fa28c42 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -255,8 +255,8 @@ static int verify_chain(Indirect *from, Indirect *to)
* @inode: inode in question (we are only interested in its superblock)
* @i_block: block number to be parsed
* @offsets: array to store the offsets in
- * @boundary: set this non-zero if the referred-to block is likely to be
- * followed (on disk) by an indirect block.
+ * @boundary: set this non-zero if the referred-to block is likely to be
+ * followed (on disk) by an indirect block.
*
* To store the locations of file's data ext4 uses a data structure common
* for UNIX filesystems - tree of pointers anchored in the inode, with
@@ -2673,8 +2673,10 @@ void ext4_read_inode(struct inode * inode)
*/
ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
- EXT4_INODE_SIZE(inode->i_sb))
+ EXT4_INODE_SIZE(inode->i_sb)) {
+ brelse (bh);
goto bad_inode;
+ }
if (ei->i_extra_isize == 0) {
/* The extra space is currently unused. Use it. */
ei->i_extra_isize = sizeof(struct ext4_inode) -
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 4ec57be5baf..2811e5720ad 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -46,7 +46,7 @@
*/
#define NAMEI_RA_CHUNKS 2
#define NAMEI_RA_BLOCKS 4
-#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
+#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
static struct buffer_head *ext4_append(handle_t *handle,
@@ -241,7 +241,7 @@ static inline unsigned dx_node_limit (struct inode *dir)
static void dx_show_index (char * label, struct dx_entry *entries)
{
int i, n = dx_get_count (entries);
- printk("%s index ", label);
+ printk("%s index ", label);
for (i = 0; i < n; i++) {
printk("%x->%u ", i? dx_get_hash(entries + i) :
0, dx_get_block(entries + i));
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index cb9afdd0e26..175b68c6096 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1985,7 +1985,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb,
if (bd_claim(bdev, sb)) {
printk(KERN_ERR
- "EXT4: failed to claim external journal device.\n");
+ "EXT4: failed to claim external journal device.\n");
blkdev_put(bdev);
return NULL;
}
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 55d3c7461c5..69a83b59dce 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -134,7 +134,7 @@ const struct file_operations fat_file_operations = {
.release = fat_file_release,
.ioctl = fat_generic_ioctl,
.fsync = file_fsync,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
static int fat_cont_expand(struct inode *inode, loff_t size)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index adf7995232b..f79de7c8cdf 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -802,7 +802,7 @@ static const struct file_operations fuse_file_operations = {
.release = fuse_release,
.fsync = fuse_fsync,
.lock = fuse_file_lock,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
static const struct file_operations fuse_direct_io_file_operations = {
@@ -814,7 +814,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
.release = fuse_release,
.fsync = fuse_fsync,
.lock = fuse_file_lock,
- /* no mmap and sendfile */
+ /* no mmap and splice_read */
};
static const struct address_space_operations fuse_file_aops = {
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 9804c0cdcb4..cc5efc13496 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -655,10 +655,9 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type,
static struct file_system_type fuseblk_fs_type = {
.owner = THIS_MODULE,
.name = "fuseblk",
- .fs_flags = FS_HAS_SUBTYPE,
.get_sb = fuse_get_sb_blk,
.kill_sb = kill_block_super,
- .fs_flags = FS_REQUIRES_DEV,
+ .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE,
};
static inline int register_fuseblk(void)
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index e3f1ada643a..04ad0caebed 100644
--- a/fs/gfs2/Makefile
+++ b/fs/gfs2/Makefile
@@ -1,7 +1,7 @@
obj-$(CONFIG_GFS2_FS) += gfs2.o
gfs2-y := acl.o bmap.o daemon.o dir.o eaops.o eattr.o glock.o \
glops.o inode.o lm.o log.o lops.o locking.o main.o meta_io.o \
- mount.o ondisk.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
+ mount.o ops_address.o ops_dentry.o ops_export.o ops_file.o \
ops_fstype.o ops_inode.o ops_super.o ops_vm.o quota.o \
recovery.o rgrp.o super.o sys.o trans.o util.o
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index c53a5d2d059..cd805a66880 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -718,7 +718,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
for (x = 0; x < rlist.rl_rgrps; x++) {
struct gfs2_rgrpd *rgd;
rgd = rlist.rl_ghs[x].gh_gl->gl_object;
- rg_blocks += rgd->rd_ri.ri_length;
+ rg_blocks += rgd->rd_length;
}
error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
@@ -772,7 +772,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
gfs2_free_data(ip, bstart, blen);
}
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, dibh->b_data);
@@ -824,7 +824,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
goto out_gunlock_q;
error = gfs2_trans_begin(sdp,
- sdp->sd_max_height + al->al_rgd->rd_ri.ri_length +
+ sdp->sd_max_height + al->al_rgd->rd_length +
RES_JDATA + RES_DINODE + RES_STATFS + RES_QUOTA, 0);
if (error)
goto out_ipres;
@@ -847,7 +847,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
}
ip->i_di.di_size = size;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
error = gfs2_meta_inode_buffer(ip, &dibh);
if (error)
@@ -885,7 +885,6 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
unsigned blocksize, iblock, length, pos;
struct buffer_head *bh;
struct page *page;
- void *kaddr;
int err;
page = grab_cache_page(mapping, index);
@@ -928,15 +927,13 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
/* Uhhuh. Read error. Complain and punt. */
if (!buffer_uptodate(bh))
goto unlock;
+ err = 0;
}
if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
gfs2_trans_add_bh(ip->i_gl, bh, 0);
- kaddr = kmap_atomic(page, KM_USER0);
- memset(kaddr + offset, 0, length);
- flush_dcache_page(page);
- kunmap_atomic(kaddr, KM_USER0);
+ zero_user_page(page, offset, length, KM_USER0);
unlock:
unlock_page(page);
@@ -962,7 +959,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
if (gfs2_is_stuffed(ip)) {
ip->i_di.di_size = size;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
@@ -974,7 +971,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
if (!error) {
ip->i_di.di_size = size;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1044,10 +1041,10 @@ static int trunc_end(struct gfs2_inode *ip)
ip->i_di.di_height = 0;
ip->i_di.di_goal_meta =
ip->i_di.di_goal_data =
- ip->i_num.no_addr;
+ ip->i_no_addr;
gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
}
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
diff --git a/fs/gfs2/daemon.c b/fs/gfs2/daemon.c
index 683cb5bda87..3548d9f31e0 100644
--- a/fs/gfs2/daemon.c
+++ b/fs/gfs2/daemon.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/gfs2_ondisk.h>
#include <linux/lm_interface.h>
+#include <linux/freezer.h>
#include "gfs2.h"
#include "incore.h"
@@ -49,6 +50,8 @@ int gfs2_scand(void *data)
while (!kthread_should_stop()) {
gfs2_scand_internal(sdp);
t = gfs2_tune_get(sdp, gt_scand_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
schedule_timeout_interruptible(t);
}
@@ -74,6 +77,8 @@ int gfs2_glockd(void *data)
wait_event_interruptible(sdp->sd_reclaim_wq,
(atomic_read(&sdp->sd_reclaim_count) ||
kthread_should_stop()));
+ if (freezing(current))
+ refrigerator();
}
return 0;
@@ -93,6 +98,8 @@ int gfs2_recoverd(void *data)
while (!kthread_should_stop()) {
gfs2_check_journals(sdp);
t = gfs2_tune_get(sdp, gt_recoverd_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
schedule_timeout_interruptible(t);
}
@@ -141,6 +148,8 @@ int gfs2_logd(void *data)
}
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
schedule_timeout_interruptible(t);
}
@@ -191,6 +200,8 @@ int gfs2_quotad(void *data)
gfs2_quota_scan(sdp);
t = gfs2_tune_get(sdp, gt_quotad_secs) * HZ;
+ if (freezing(current))
+ refrigerator();
schedule_timeout_interruptible(t);
}
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index a96fa07b3f3..2beb2f401aa 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -130,7 +130,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
if (ip->i_di.di_size < offset + size)
ip->i_di.di_size = offset + size;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -228,7 +228,7 @@ out:
if (ip->i_di.di_size < offset + copied)
ip->i_di.di_size = offset + copied;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -1456,7 +1456,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
if (dip->i_di.di_entries != g.offset) {
fs_warn(sdp, "Number of entries corrupt in dir %llu, "
"ip->i_di.di_entries (%u) != g.offset (%u)\n",
- (unsigned long long)dip->i_num.no_addr,
+ (unsigned long long)dip->i_no_addr,
dip->i_di.di_entries,
g.offset);
error = -EIO;
@@ -1488,24 +1488,55 @@ out:
* Returns: errno
*/
-int gfs2_dir_search(struct inode *dir, const struct qstr *name,
- struct gfs2_inum_host *inum, unsigned int *type)
+struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
+ struct inode *inode;
+
+ dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
+ if (dent) {
+ if (IS_ERR(dent))
+ return ERR_PTR(PTR_ERR(dent));
+ inode = gfs2_inode_lookup(dir->i_sb,
+ be16_to_cpu(dent->de_type),
+ be64_to_cpu(dent->de_inum.no_addr),
+ be64_to_cpu(dent->de_inum.no_formal_ino));
+ brelse(bh);
+ return inode;
+ }
+ return ERR_PTR(-ENOENT);
+}
+
+int gfs2_dir_check(struct inode *dir, const struct qstr *name,
+ const struct gfs2_inode *ip)
+{
+ struct buffer_head *bh;
+ struct gfs2_dirent *dent;
+ int ret = -ENOENT;
dent = gfs2_dirent_search(dir, name, gfs2_dirent_find, &bh);
if (dent) {
if (IS_ERR(dent))
return PTR_ERR(dent);
- if (inum)
- gfs2_inum_in(inum, (char *)&dent->de_inum);
- if (type)
- *type = be16_to_cpu(dent->de_type);
+ if (ip) {
+ if (be64_to_cpu(dent->de_inum.no_addr) != ip->i_no_addr)
+ goto out;
+ if (be64_to_cpu(dent->de_inum.no_formal_ino) !=
+ ip->i_no_formal_ino)
+ goto out;
+ if (unlikely(IF2DT(ip->i_inode.i_mode) !=
+ be16_to_cpu(dent->de_type))) {
+ gfs2_consist_inode(GFS2_I(dir));
+ ret = -EIO;
+ goto out;
+ }
+ }
+ ret = 0;
+out:
brelse(bh);
- return 0;
}
- return -ENOENT;
+ return ret;
}
static int dir_new_leaf(struct inode *inode, const struct qstr *name)
@@ -1565,7 +1596,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name)
*/
int gfs2_dir_add(struct inode *inode, const struct qstr *name,
- const struct gfs2_inum_host *inum, unsigned type)
+ const struct gfs2_inode *nip, unsigned type)
{
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh;
@@ -1580,7 +1611,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
if (IS_ERR(dent))
return PTR_ERR(dent);
dent = gfs2_init_dirent(inode, dent, name, bh);
- gfs2_inum_out(inum, (char *)&dent->de_inum);
+ gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(type);
if (ip->i_di.di_flags & GFS2_DIF_EXHASH) {
leaf = (struct gfs2_leaf *)bh->b_data;
@@ -1592,7 +1623,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
break;
gfs2_trans_add_bh(ip->i_gl, bh, 1);
ip->i_di.di_entries++;
- ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(ip, bh->b_data);
brelse(bh);
error = 0;
@@ -1678,7 +1709,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
gfs2_consist_inode(dip);
gfs2_trans_add_bh(dip->i_gl, bh, 1);
dip->i_di.di_entries--;
- dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
mark_inode_dirty(&dip->i_inode);
@@ -1700,7 +1731,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
*/
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
- struct gfs2_inum_host *inum, unsigned int new_type)
+ const struct gfs2_inode *nip, unsigned int new_type)
{
struct buffer_head *bh;
struct gfs2_dirent *dent;
@@ -1715,7 +1746,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
return PTR_ERR(dent);
gfs2_trans_add_bh(dip->i_gl, bh, 1);
- gfs2_inum_out(inum, (char *)&dent->de_inum);
+ gfs2_inum_out(nip, dent);
dent->de_type = cpu_to_be16(new_type);
if (dip->i_di.di_flags & GFS2_DIF_EXHASH) {
@@ -1726,7 +1757,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
gfs2_trans_add_bh(dip->i_gl, bh, 1);
}
- dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
gfs2_dinode_out(dip, bh->b_data);
brelse(bh);
return 0;
@@ -1867,7 +1898,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
for (x = 0; x < rlist.rl_rgrps; x++) {
struct gfs2_rgrpd *rgd;
rgd = rlist.rl_ghs[x].gh_gl->gl_object;
- rg_blocks += rgd->rd_ri.ri_length;
+ rg_blocks += rgd->rd_length;
}
error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h
index 48fe89046bb..8a468cac932 100644
--- a/fs/gfs2/dir.h
+++ b/fs/gfs2/dir.h
@@ -16,15 +16,16 @@ struct inode;
struct gfs2_inode;
struct gfs2_inum;
-int gfs2_dir_search(struct inode *dir, const struct qstr *filename,
- struct gfs2_inum_host *inum, unsigned int *type);
+struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *filename);
+int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
+ const struct gfs2_inode *ip);
int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
- const struct gfs2_inum_host *inum, unsigned int type);
+ const struct gfs2_inode *ip, unsigned int type);
int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *filename);
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
filldir_t filldir);
int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
- struct gfs2_inum_host *new_inum, unsigned int new_type);
+ const struct gfs2_inode *nip, unsigned int new_type);
int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip);
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index 5b83ca6acab..2a7435b5c4d 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -254,7 +254,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
if (error)
return error;
- error = gfs2_trans_begin(sdp, rgd->rd_ri.ri_length + RES_DINODE +
+ error = gfs2_trans_begin(sdp, rgd->rd_length + RES_DINODE +
RES_EATTR + RES_STATFS + RES_QUOTA, blks);
if (error)
goto out_gunlock;
@@ -300,7 +300,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -700,7 +700,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
goto out_gunlock_q;
error = gfs2_trans_begin(GFS2_SB(&ip->i_inode),
- blks + al->al_rgd->rd_ri.ri_length +
+ blks + al->al_rgd->rd_length +
RES_DINODE + RES_STATFS + RES_QUOTA, 0);
if (error)
goto out_ipres;
@@ -717,7 +717,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
(er->er_mode & S_IFMT));
ip->i_inode.i_mode = er->er_mode;
}
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -852,7 +852,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
(ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));
ip->i_inode.i_mode = er->er_mode;
}
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -1133,7 +1133,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
error = gfs2_meta_inode_buffer(ip, &dibh);
if (!error) {
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -1352,7 +1352,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
for (x = 0; x < rlist.rl_rgrps; x++) {
struct gfs2_rgrpd *rgd;
rgd = rlist.rl_ghs[x].gh_gl->gl_object;
- rg_blocks += rgd->rd_ri.ri_length;
+ rg_blocks += rgd->rd_length;
}
error = gfs2_glock_nq_m(rlist.rl_rgrps, rlist.rl_ghs);
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 1815429a297..3f0974e1afe 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -422,11 +422,11 @@ void gfs2_holder_uninit(struct gfs2_holder *gh)
static void gfs2_holder_wake(struct gfs2_holder *gh)
{
clear_bit(HIF_WAIT, &gh->gh_iflags);
- smp_mb();
+ smp_mb__after_clear_bit();
wake_up_bit(&gh->gh_iflags, HIF_WAIT);
}
-static int holder_wait(void *word)
+static int just_schedule(void *word)
{
schedule();
return 0;
@@ -435,7 +435,20 @@ static int holder_wait(void *word)
static void wait_on_holder(struct gfs2_holder *gh)
{
might_sleep();
- wait_on_bit(&gh->gh_iflags, HIF_WAIT, holder_wait, TASK_UNINTERRUPTIBLE);
+ wait_on_bit(&gh->gh_iflags, HIF_WAIT, just_schedule, TASK_UNINTERRUPTIBLE);
+}
+
+static void gfs2_demote_wake(struct gfs2_glock *gl)
+{
+ clear_bit(GLF_DEMOTE, &gl->gl_flags);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&gl->gl_flags, GLF_DEMOTE);
+}
+
+static void wait_on_demote(struct gfs2_glock *gl)
+{
+ might_sleep();
+ wait_on_bit(&gl->gl_flags, GLF_DEMOTE, just_schedule, TASK_UNINTERRUPTIBLE);
}
/**
@@ -528,7 +541,7 @@ static int rq_demote(struct gfs2_glock *gl)
if (gl->gl_state == gl->gl_demote_state ||
gl->gl_state == LM_ST_UNLOCKED) {
- clear_bit(GLF_DEMOTE, &gl->gl_flags);
+ gfs2_demote_wake(gl);
return 0;
}
set_bit(GLF_LOCK, &gl->gl_flags);
@@ -666,12 +679,22 @@ static void gfs2_glmutex_unlock(struct gfs2_glock *gl)
* practise: LM_ST_SHARED and LM_ST_UNLOCKED
*/
-static void handle_callback(struct gfs2_glock *gl, unsigned int state)
+static void handle_callback(struct gfs2_glock *gl, unsigned int state, int remote)
{
spin_lock(&gl->gl_spin);
if (test_and_set_bit(GLF_DEMOTE, &gl->gl_flags) == 0) {
gl->gl_demote_state = state;
gl->gl_demote_time = jiffies;
+ if (remote && gl->gl_ops->go_type == LM_TYPE_IOPEN &&
+ gl->gl_object) {
+ struct inode *inode = igrab(gl->gl_object);
+ spin_unlock(&gl->gl_spin);
+ if (inode) {
+ d_prune_aliases(inode);
+ iput(inode);
+ }
+ return;
+ }
} else if (gl->gl_demote_state != LM_ST_UNLOCKED) {
gl->gl_demote_state = state;
}
@@ -740,7 +763,7 @@ static void xmote_bh(struct gfs2_glock *gl, unsigned int ret)
if (ret & LM_OUT_CANCELED)
op_done = 0;
else
- clear_bit(GLF_DEMOTE, &gl->gl_flags);
+ gfs2_demote_wake(gl);
} else {
spin_lock(&gl->gl_spin);
list_del_init(&gh->gh_list);
@@ -848,7 +871,7 @@ static void drop_bh(struct gfs2_glock *gl, unsigned int ret)
gfs2_assert_warn(sdp, !ret);
state_change(gl, LM_ST_UNLOCKED);
- clear_bit(GLF_DEMOTE, &gl->gl_flags);
+ gfs2_demote_wake(gl);
if (glops->go_inval)
glops->go_inval(gl, DIO_METADATA);
@@ -1174,7 +1197,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
const struct gfs2_glock_operations *glops = gl->gl_ops;
if (gh->gh_flags & GL_NOCACHE)
- handle_callback(gl, LM_ST_UNLOCKED);
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
gfs2_glmutex_lock(gl);
@@ -1196,6 +1219,13 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
spin_unlock(&gl->gl_spin);
}
+void gfs2_glock_dq_wait(struct gfs2_holder *gh)
+{
+ struct gfs2_glock *gl = gh->gh_gl;
+ gfs2_glock_dq(gh);
+ wait_on_demote(gl);
+}
+
/**
* gfs2_glock_dq_uninit - dequeue a holder from a glock and initialize it
* @gh: the holder structure
@@ -1297,10 +1327,6 @@ static int nq_m_sync(unsigned int num_gh, struct gfs2_holder *ghs,
* @num_gh: the number of structures
* @ghs: an array of struct gfs2_holder structures
*
- * Figure out how big an impact this function has. Either:
- * 1) Replace this code with code that calls gfs2_glock_prefetch()
- * 2) Forget async stuff and just call nq_m_sync()
- * 3) Leave it like it is
*
* Returns: 0 on success (all glocks acquired),
* errno on failure (no glocks acquired)
@@ -1308,62 +1334,28 @@ static int nq_m_sync(unsigned int num_gh, struct gfs2_holder *ghs,
int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs)
{
- int *e;
- unsigned int x;
- int borked = 0, serious = 0;
+ struct gfs2_holder *tmp[4];
+ struct gfs2_holder **pph = tmp;
int error = 0;
- if (!num_gh)
+ switch(num_gh) {
+ case 0:
return 0;
-
- if (num_gh == 1) {
+ case 1:
ghs->gh_flags &= ~(LM_FLAG_TRY | GL_ASYNC);
return gfs2_glock_nq(ghs);
- }
-
- e = kcalloc(num_gh, sizeof(struct gfs2_holder *), GFP_KERNEL);
- if (!e)
- return -ENOMEM;
-
- for (x = 0; x < num_gh; x++) {
- ghs[x].gh_flags |= LM_FLAG_TRY | GL_ASYNC;
- error = gfs2_glock_nq(&ghs[x]);
- if (error) {
- borked = 1;
- serious = error;
- num_gh = x;
+ default:
+ if (num_gh <= 4)
break;
- }
- }
-
- for (x = 0; x < num_gh; x++) {
- error = e[x] = glock_wait_internal(&ghs[x]);
- if (error) {
- borked = 1;
- if (error != GLR_TRYFAILED && error != GLR_CANCELED)
- serious = error;
- }
+ pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS);
+ if (!pph)
+ return -ENOMEM;
}
- if (!borked) {
- kfree(e);
- return 0;
- }
-
- for (x = 0; x < num_gh; x++)
- if (!e[x])
- gfs2_glock_dq(&ghs[x]);
-
- if (serious)
- error = serious;
- else {
- for (x = 0; x < num_gh; x++)
- gfs2_holder_reinit(ghs[x].gh_state, ghs[x].gh_flags,
- &ghs[x]);
- error = nq_m_sync(num_gh, ghs, (struct gfs2_holder **)e);
- }
+ error = nq_m_sync(num_gh, ghs, pph);
- kfree(e);
+ if (pph != tmp)
+ kfree(pph);
return error;
}
@@ -1456,7 +1448,7 @@ static void blocking_cb(struct gfs2_sbd *sdp, struct lm_lockname *name,
if (!gl)
return;
- handle_callback(gl, state);
+ handle_callback(gl, state, 1);
spin_lock(&gl->gl_spin);
run_queue(gl);
@@ -1596,7 +1588,7 @@ void gfs2_reclaim_glock(struct gfs2_sbd *sdp)
if (gfs2_glmutex_trylock(gl)) {
if (list_empty(&gl->gl_holders) &&
gl->gl_state != LM_ST_UNLOCKED && demote_ok(gl))
- handle_callback(gl, LM_ST_UNLOCKED);
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
gfs2_glmutex_unlock(gl);
}
@@ -1709,7 +1701,7 @@ static void clear_glock(struct gfs2_glock *gl)
if (gfs2_glmutex_trylock(gl)) {
if (list_empty(&gl->gl_holders) &&
gl->gl_state != LM_ST_UNLOCKED)
- handle_callback(gl, LM_ST_UNLOCKED);
+ handle_callback(gl, LM_ST_UNLOCKED, 0);
gfs2_glmutex_unlock(gl);
}
}
@@ -1823,7 +1815,8 @@ static int dump_inode(struct glock_iter *gi, struct gfs2_inode *ip)
print_dbg(gi, " Inode:\n");
print_dbg(gi, " num = %llu/%llu\n",
- ip->i_num.no_formal_ino, ip->i_num.no_addr);
+ (unsigned long long)ip->i_no_formal_ino,
+ (unsigned long long)ip->i_no_addr);
print_dbg(gi, " type = %u\n", IF2DT(ip->i_inode.i_mode));
print_dbg(gi, " i_flags =");
for (x = 0; x < 32; x++)
@@ -1909,8 +1902,8 @@ static int dump_glock(struct glock_iter *gi, struct gfs2_glock *gl)
}
if (test_bit(GLF_DEMOTE, &gl->gl_flags)) {
print_dbg(gi, " Demotion req to state %u (%llu uS ago)\n",
- gl->gl_demote_state,
- (u64)(jiffies - gl->gl_demote_time)*(1000000/HZ));
+ gl->gl_demote_state, (unsigned long long)
+ (jiffies - gl->gl_demote_time)*(1000000/HZ));
}
if (gl->gl_ops == &gfs2_inode_glops && gl->gl_object) {
if (!test_bit(GLF_LOCK, &gl->gl_flags) &&
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index b3e152db70c..7721ca3fff9 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -87,6 +87,7 @@ int gfs2_glock_nq(struct gfs2_holder *gh);
int gfs2_glock_poll(struct gfs2_holder *gh);
int gfs2_glock_wait(struct gfs2_holder *gh);
void gfs2_glock_dq(struct gfs2_holder *gh);
+void gfs2_glock_dq_wait(struct gfs2_holder *gh);
void gfs2_glock_dq_uninit(struct gfs2_holder *gh);
int gfs2_glock_nq_num(struct gfs2_sbd *sdp,
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 7b82657a991..777ca46010e 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -156,9 +156,9 @@ static void inode_go_sync(struct gfs2_glock *gl)
ip = NULL;
if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
- gfs2_log_flush(gl->gl_sbd, gl);
if (ip)
filemap_fdatawrite(ip->i_inode.i_mapping);
+ gfs2_log_flush(gl->gl_sbd, gl);
gfs2_meta_sync(gl);
if (ip) {
struct address_space *mapping = ip->i_inode.i_mapping;
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index d995441373a..170ba93829c 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -28,6 +28,14 @@ struct gfs2_sbd;
typedef void (*gfs2_glop_bh_t) (struct gfs2_glock *gl, unsigned int ret);
+struct gfs2_log_header_host {
+ u64 lh_sequence; /* Sequence number of this transaction */
+ u32 lh_flags; /* GFS2_LOG_HEAD_... */
+ u32 lh_tail; /* Block number of log tail */
+ u32 lh_blkno;
+ u32 lh_hash;
+};
+
/*
* Structure of operations that are associated with each
* type of element in the log.
@@ -60,12 +68,23 @@ struct gfs2_bitmap {
u32 bi_len;
};
+struct gfs2_rgrp_host {
+ u32 rg_flags;
+ u32 rg_free;
+ u32 rg_dinodes;
+ u64 rg_igeneration;
+};
+
struct gfs2_rgrpd {
struct list_head rd_list; /* Link with superblock */
struct list_head rd_list_mru;
struct list_head rd_recent; /* Recently used rgrps */
struct gfs2_glock *rd_gl; /* Glock for this rgrp */
- struct gfs2_rindex_host rd_ri;
+ u64 rd_addr; /* grp block disk address */
+ u64 rd_data0; /* first data location */
+ u32 rd_length; /* length of rgrp header in fs blocks */
+ u32 rd_data; /* num of data blocks in rgrp */
+ u32 rd_bitbytes; /* number of bytes in data bitmaps */
struct gfs2_rgrp_host rd_rg;
u64 rd_rg_vn;
struct gfs2_bitmap *rd_bits;
@@ -76,6 +95,8 @@ struct gfs2_rgrpd {
u32 rd_last_alloc_data;
u32 rd_last_alloc_meta;
struct gfs2_sbd *rd_sbd;
+ unsigned long rd_flags;
+#define GFS2_RDF_CHECK 0x0001 /* Need to check for unlinked inodes */
};
enum gfs2_state_bits {
@@ -211,10 +232,24 @@ enum {
GIF_SW_PAGED = 3,
};
+struct gfs2_dinode_host {
+ u64 di_size; /* number of bytes in file */
+ u64 di_blocks; /* number of blocks in file */
+ u64 di_goal_meta; /* rgrp to alloc from next */
+ u64 di_goal_data; /* data block goal */
+ u64 di_generation; /* generation number for NFS */
+ u32 di_flags; /* GFS2_DIF_... */
+ u16 di_height; /* height of metadata */
+ /* These only apply to directories */
+ u16 di_depth; /* Number of bits in the table */
+ u32 di_entries; /* The number of entries in the directory */
+ u64 di_eattr; /* extended attribute block number */
+};
+
struct gfs2_inode {
struct inode i_inode;
- struct gfs2_inum_host i_num;
-
+ u64 i_no_addr;
+ u64 i_no_formal_ino;
unsigned long i_flags; /* GIF_... */
struct gfs2_dinode_host i_di; /* To be replaced by ref to block */
@@ -275,14 +310,6 @@ enum {
QDF_LOCKED = 2,
};
-struct gfs2_quota_lvb {
- __be32 qb_magic;
- u32 __pad;
- __be64 qb_limit; /* Hard limit of # blocks to alloc */
- __be64 qb_warn; /* Warn user when alloc is above this # */
- __be64 qb_value; /* Current # blocks allocated */
-};
-
struct gfs2_quota_data {
struct list_head qd_list;
unsigned int qd_count;
@@ -327,7 +354,9 @@ struct gfs2_trans {
unsigned int tr_num_buf;
unsigned int tr_num_buf_new;
+ unsigned int tr_num_databuf_new;
unsigned int tr_num_buf_rm;
+ unsigned int tr_num_databuf_rm;
struct list_head tr_list_buf;
unsigned int tr_num_revoke;
@@ -354,6 +383,12 @@ struct gfs2_jdesc {
unsigned int jd_blocks;
};
+struct gfs2_statfs_change_host {
+ s64 sc_total;
+ s64 sc_free;
+ s64 sc_dinodes;
+};
+
#define GFS2_GLOCKD_DEFAULT 1
#define GFS2_GLOCKD_MAX 16
@@ -426,6 +461,28 @@ enum {
#define GFS2_FSNAME_LEN 256
+struct gfs2_inum_host {
+ u64 no_formal_ino;
+ u64 no_addr;
+};
+
+struct gfs2_sb_host {
+ u32 sb_magic;
+ u32 sb_type;
+ u32 sb_format;
+
+ u32 sb_fs_format;
+ u32 sb_multihost_format;
+ u32 sb_bsize;
+ u32 sb_bsize_shift;
+
+ struct gfs2_inum_host sb_master_dir;
+ struct gfs2_inum_host sb_root_dir;
+
+ char sb_lockproto[GFS2_LOCKNAME_LEN];
+ char sb_locktable[GFS2_LOCKNAME_LEN];
+};
+
struct gfs2_sbd {
struct super_block *sd_vfs;
struct super_block *sd_vfs_meta;
@@ -544,6 +601,7 @@ struct gfs2_sbd {
unsigned int sd_log_blks_reserved;
unsigned int sd_log_commited_buf;
+ unsigned int sd_log_commited_databuf;
unsigned int sd_log_commited_revoke;
unsigned int sd_log_num_gl;
@@ -552,7 +610,6 @@ struct gfs2_sbd {
unsigned int sd_log_num_rg;
unsigned int sd_log_num_databuf;
unsigned int sd_log_num_jdata;
- unsigned int sd_log_num_hdrs;
struct list_head sd_log_le_gl;
struct list_head sd_log_le_buf;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index df0b8b3018b..34f7bcdea1e 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -38,12 +38,17 @@
#include "trans.h"
#include "util.h"
+struct gfs2_inum_range_host {
+ u64 ir_start;
+ u64 ir_length;
+};
+
static int iget_test(struct inode *inode, void *opaque)
{
struct gfs2_inode *ip = GFS2_I(inode);
- struct gfs2_inum_host *inum = opaque;
+ u64 *no_addr = opaque;
- if (ip->i_num.no_addr == inum->no_addr &&
+ if (ip->i_no_addr == *no_addr &&
inode->i_private != NULL)
return 1;
@@ -53,37 +58,70 @@ static int iget_test(struct inode *inode, void *opaque)
static int iget_set(struct inode *inode, void *opaque)
{
struct gfs2_inode *ip = GFS2_I(inode);
- struct gfs2_inum_host *inum = opaque;
+ u64 *no_addr = opaque;
- ip->i_num = *inum;
- inode->i_ino = inum->no_addr;
+ inode->i_ino = (unsigned long)*no_addr;
+ ip->i_no_addr = *no_addr;
return 0;
}
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum)
+struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr)
+{
+ unsigned long hash = (unsigned long)no_addr;
+ return ilookup5(sb, hash, iget_test, &no_addr);
+}
+
+static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
{
- return ilookup5(sb, (unsigned long)inum->no_addr,
- iget_test, inum);
+ unsigned long hash = (unsigned long)no_addr;
+ return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
}
-static struct inode *gfs2_iget(struct super_block *sb, struct gfs2_inum_host *inum)
+/**
+ * GFS2 lookup code fills in vfs inode contents based on info obtained
+ * from directory entry inside gfs2_inode_lookup(). This has caused issues
+ * with NFS code path since its get_dentry routine doesn't have the relevant
+ * directory entry when gfs2_inode_lookup() is invoked. Part of the code
+ * segment inside gfs2_inode_lookup code needs to get moved around.
+ *
+ * Clean up I_LOCK and I_NEW as well.
+ **/
+
+void gfs2_set_iop(struct inode *inode)
{
- return iget5_locked(sb, (unsigned long)inum->no_addr,
- iget_test, iget_set, inum);
+ umode_t mode = inode->i_mode;
+
+ if (S_ISREG(mode)) {
+ inode->i_op = &gfs2_file_iops;
+ inode->i_fop = &gfs2_file_fops;
+ inode->i_mapping->a_ops = &gfs2_file_aops;
+ } else if (S_ISDIR(mode)) {
+ inode->i_op = &gfs2_dir_iops;
+ inode->i_fop = &gfs2_dir_fops;
+ } else if (S_ISLNK(mode)) {
+ inode->i_op = &gfs2_symlink_iops;
+ } else {
+ inode->i_op = &gfs2_dev_iops;
+ }
+
+ unlock_new_inode(inode);
}
/**
* gfs2_inode_lookup - Lookup an inode
* @sb: The super block
- * @inum: The inode number
+ * @no_addr: The inode number
* @type: The type of the inode
*
* Returns: A VFS inode, or an error
*/
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned int type)
+struct inode *gfs2_inode_lookup(struct super_block *sb,
+ unsigned int type,
+ u64 no_addr,
+ u64 no_formal_ino)
{
- struct inode *inode = gfs2_iget(sb, inum);
+ struct inode *inode = gfs2_iget(sb, no_addr);
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_glock *io_gl;
int error;
@@ -93,29 +131,15 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *i
if (inode->i_state & I_NEW) {
struct gfs2_sbd *sdp = GFS2_SB(inode);
- umode_t mode = DT2IF(type);
inode->i_private = ip;
- inode->i_mode = mode;
-
- if (S_ISREG(mode)) {
- inode->i_op = &gfs2_file_iops;
- inode->i_fop = &gfs2_file_fops;
- inode->i_mapping->a_ops = &gfs2_file_aops;
- } else if (S_ISDIR(mode)) {
- inode->i_op = &gfs2_dir_iops;
- inode->i_fop = &gfs2_dir_fops;
- } else if (S_ISLNK(mode)) {
- inode->i_op = &gfs2_symlink_iops;
- } else {
- inode->i_op = &gfs2_dev_iops;
- }
+ ip->i_no_formal_ino = no_formal_ino;
- error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
+ error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl);
if (unlikely(error))
goto fail;
ip->i_gl->gl_object = ip;
- error = gfs2_glock_get(sdp, inum->no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
+ error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl);
if (unlikely(error))
goto fail_put;
@@ -123,12 +147,38 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *i
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
if (unlikely(error))
goto fail_iopen;
+ ip->i_iopen_gh.gh_gl->gl_object = ip;
gfs2_glock_put(io_gl);
- unlock_new_inode(inode);
+
+ if ((type == DT_UNKNOWN) && (no_formal_ino == 0))
+ goto gfs2_nfsbypass;
+
+ inode->i_mode = DT2IF(type);
+
+ /*
+ * We must read the inode in order to work out its type in
+ * this case. Note that this doesn't happen often as we normally
+ * know the type beforehand. This code path only occurs during
+ * unlinked inode recovery (where it is safe to do this glock,
+ * which is not true in the general case).
+ */
+ if (type == DT_UNKNOWN) {
+ struct gfs2_holder gh;
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+ if (unlikely(error))
+ goto fail_glock;
+ /* Inode is now uptodate */
+ gfs2_glock_dq_uninit(&gh);
+ }
+
+ gfs2_set_iop(inode);
}
+gfs2_nfsbypass:
return inode;
+fail_glock:
+ gfs2_glock_dq(&ip->i_iopen_gh);
fail_iopen:
gfs2_glock_put(io_gl);
fail_put:
@@ -144,14 +194,12 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
struct gfs2_dinode_host *di = &ip->i_di;
const struct gfs2_dinode *str = buf;
- if (ip->i_num.no_addr != be64_to_cpu(str->di_num.no_addr)) {
+ if (ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)) {
if (gfs2_consist_inode(ip))
gfs2_dinode_print(ip);
return -EIO;
}
- if (ip->i_num.no_formal_ino != be64_to_cpu(str->di_num.no_formal_ino))
- return -ESTALE;
-
+ ip->i_no_formal_ino = be64_to_cpu(str->di_num.no_formal_ino);
ip->i_inode.i_mode = be32_to_cpu(str->di_mode);
ip->i_inode.i_rdev = 0;
switch (ip->i_inode.i_mode & S_IFMT) {
@@ -175,11 +223,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
di->di_blocks = be64_to_cpu(str->di_blocks);
gfs2_set_inode_blocks(&ip->i_inode);
ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
- ip->i_inode.i_atime.tv_nsec = 0;
+ ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
- ip->i_inode.i_mtime.tv_nsec = 0;
+ ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
- ip->i_inode.i_ctime.tv_nsec = 0;
+ ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
di->di_goal_data = be64_to_cpu(str->di_goal_data);
@@ -247,7 +295,7 @@ int gfs2_dinode_dealloc(struct gfs2_inode *ip)
if (error)
goto out_qs;
- rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+ rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
if (!rgd) {
gfs2_consist_inode(ip);
error = -EIO;
@@ -314,7 +362,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
else
drop_nlink(&ip->i_inode);
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
@@ -366,9 +414,7 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
struct super_block *sb = dir->i_sb;
struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_holder d_gh;
- struct gfs2_inum_host inum;
- unsigned int type;
- int error;
+ int error = 0;
struct inode *inode = NULL;
int unlock = 0;
@@ -395,12 +441,9 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name,
goto out;
}
- error = gfs2_dir_search(dir, name, &inum, &type);
- if (error)
- goto out;
-
- inode = gfs2_inode_lookup(sb, &inum, type);
-
+ inode = gfs2_dir_search(dir, name);
+ if (IS_ERR(inode))
+ error = PTR_ERR(inode);
out:
if (unlock)
gfs2_glock_dq_uninit(&d_gh);
@@ -409,6 +452,22 @@ out:
return inode ? inode : ERR_PTR(error);
}
+static void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
+{
+ const struct gfs2_inum_range *str = buf;
+
+ ir->ir_start = be64_to_cpu(str->ir_start);
+ ir->ir_length = be64_to_cpu(str->ir_length);
+}
+
+static void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
+{
+ struct gfs2_inum_range *str = buf;
+
+ str->ir_start = cpu_to_be64(ir->ir_start);
+ str->ir_length = cpu_to_be64(ir->ir_length);
+}
+
static int pick_formal_ino_1(struct gfs2_sbd *sdp, u64 *formal_ino)
{
struct gfs2_inode *ip = GFS2_I(sdp->sd_ir_inode);
@@ -548,7 +607,7 @@ static int create_ok(struct gfs2_inode *dip, const struct qstr *name,
if (!dip->i_inode.i_nlink)
return -EPERM;
- error = gfs2_dir_search(&dip->i_inode, name, NULL, NULL);
+ error = gfs2_dir_check(&dip->i_inode, name, NULL);
switch (error) {
case -ENOENT:
error = 0;
@@ -588,8 +647,7 @@ static void munge_mode_uid_gid(struct gfs2_inode *dip, unsigned int *mode,
*gid = current->fsgid;
}
-static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum,
- u64 *generation)
+static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
{
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
int error;
@@ -605,7 +663,7 @@ static int alloc_dinode(struct gfs2_inode *dip, struct gfs2_inum_host *inum,
if (error)
goto out_ipreserv;
- inum->no_addr = gfs2_alloc_di(dip, generation);
+ *no_addr = gfs2_alloc_di(dip, generation);
gfs2_trans_end(sdp);
@@ -635,6 +693,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
struct gfs2_dinode *di;
struct buffer_head *dibh;
+ struct timespec tv = CURRENT_TIME;
dibh = gfs2_meta_new(gl, inum->no_addr);
gfs2_trans_add_bh(gl, dibh, 1);
@@ -650,7 +709,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
di->di_nlink = 0;
di->di_size = 0;
di->di_blocks = cpu_to_be64(1);
- di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds());
+ di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
di->di_major = cpu_to_be32(MAJOR(dev));
di->di_minor = cpu_to_be32(MINOR(dev));
di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
@@ -680,6 +739,9 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
di->di_entries = 0;
memset(&di->__pad4, 0, sizeof(di->__pad4));
di->di_eattr = 0;
+ di->di_atime_nsec = cpu_to_be32(tv.tv_nsec);
+ di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
+ di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
memset(&di->di_reserved, 0, sizeof(di->di_reserved));
brelse(dibh);
@@ -749,7 +811,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
goto fail_quota_locks;
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
- al->al_rgd->rd_ri.ri_length +
+ al->al_rgd->rd_length +
2 * RES_DINODE +
RES_STATFS + RES_QUOTA, 0);
if (error)
@@ -760,7 +822,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,
goto fail_quota_locks;
}
- error = gfs2_dir_add(&dip->i_inode, name, &ip->i_num, IF2DT(ip->i_inode.i_mode));
+ error = gfs2_dir_add(&dip->i_inode, name, ip, IF2DT(ip->i_inode.i_mode));
if (error)
goto fail_end_trans;
@@ -840,11 +902,11 @@ static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip)
struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
unsigned int mode, dev_t dev)
{
- struct inode *inode;
+ struct inode *inode = NULL;
struct gfs2_inode *dip = ghs->gh_gl->gl_object;
struct inode *dir = &dip->i_inode;
struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
- struct gfs2_inum_host inum;
+ struct gfs2_inum_host inum = { .no_addr = 0, .no_formal_ino = 0 };
int error;
u64 generation;
@@ -864,7 +926,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock;
- error = alloc_dinode(dip, &inum, &generation);
+ error = alloc_dinode(dip, &inum.no_addr, &generation);
if (error)
goto fail_gunlock;
@@ -877,34 +939,36 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
if (error)
goto fail_gunlock2;
- inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode));
+ inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode),
+ inum.no_addr,
+ inum.no_formal_ino);
if (IS_ERR(inode))
goto fail_gunlock2;
error = gfs2_inode_refresh(GFS2_I(inode));
if (error)
- goto fail_iput;
+ goto fail_gunlock2;
error = gfs2_acl_create(dip, GFS2_I(inode));
if (error)
- goto fail_iput;
+ goto fail_gunlock2;
error = gfs2_security_init(dip, GFS2_I(inode));
if (error)
- goto fail_iput;
+ goto fail_gunlock2;
error = link_dinode(dip, name, GFS2_I(inode));
if (error)
- goto fail_iput;
+ goto fail_gunlock2;
if (!inode)
return ERR_PTR(-ENOMEM);
return inode;
-fail_iput:
- iput(inode);
fail_gunlock2:
gfs2_glock_dq_uninit(ghs + 1);
+ if (inode)
+ iput(inode);
fail_gunlock:
gfs2_glock_dq(ghs);
fail:
@@ -976,10 +1040,8 @@ int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
*/
int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
- struct gfs2_inode *ip)
+ const struct gfs2_inode *ip)
{
- struct gfs2_inum_host inum;
- unsigned int type;
int error;
if (IS_IMMUTABLE(&ip->i_inode) || IS_APPEND(&ip->i_inode))
@@ -997,18 +1059,10 @@ int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
if (error)
return error;
- error = gfs2_dir_search(&dip->i_inode, name, &inum, &type);
+ error = gfs2_dir_check(&dip->i_inode, name, ip);
if (error)
return error;
- if (!gfs2_inum_equal(&inum, &ip->i_num))
- return -ENOENT;
-
- if (IF2DT(ip->i_inode.i_mode) != type) {
- gfs2_consist_inode(dip);
- return -EIO;
- }
-
return 0;
}
@@ -1132,10 +1186,11 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
struct gfs2_glock *gl = gh->gh_gl;
struct gfs2_sbd *sdp = gl->gl_sbd;
struct gfs2_inode *ip = gl->gl_object;
- s64 curtime, quantum = gfs2_tune_get(sdp, gt_atime_quantum);
+ s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
unsigned int state;
int flags;
int error;
+ struct timespec tv = CURRENT_TIME;
if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
@@ -1153,8 +1208,7 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
(sdp->sd_vfs->s_flags & MS_RDONLY))
return 0;
- curtime = get_seconds();
- if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+ if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
gfs2_glock_dq(gh);
gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
gh);
@@ -1165,8 +1219,8 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
/* Verify that atime hasn't been updated while we were
trying to get exclusive lock. */
- curtime = get_seconds();
- if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+ tv = CURRENT_TIME;
+ if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
struct buffer_head *dibh;
struct gfs2_dinode *di;
@@ -1180,11 +1234,12 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
if (error)
goto fail_end_trans;
- ip->i_inode.i_atime.tv_sec = curtime;
+ ip->i_inode.i_atime = tv;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
di = (struct gfs2_dinode *)dibh->b_data;
di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+ di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
brelse(dibh);
gfs2_trans_end(sdp);
@@ -1252,3 +1307,66 @@ int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr)
return error;
}
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
+{
+ const struct gfs2_dinode_host *di = &ip->i_di;
+ struct gfs2_dinode *str = buf;
+
+ str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
+ str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
+ str->di_header.__pad0 = 0;
+ str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
+ str->di_header.__pad1 = 0;
+ str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);
+ str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+ str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
+ str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
+ str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
+ str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
+ str->di_size = cpu_to_be64(di->di_size);
+ str->di_blocks = cpu_to_be64(di->di_blocks);
+ str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+ str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
+ str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
+
+ str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
+ str->di_goal_data = cpu_to_be64(di->di_goal_data);
+ str->di_generation = cpu_to_be64(di->di_generation);
+
+ str->di_flags = cpu_to_be32(di->di_flags);
+ str->di_height = cpu_to_be16(di->di_height);
+ str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
+ !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
+ GFS2_FORMAT_DE : 0);
+ str->di_depth = cpu_to_be16(di->di_depth);
+ str->di_entries = cpu_to_be32(di->di_entries);
+
+ str->di_eattr = cpu_to_be64(di->di_eattr);
+ str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
+ str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec);
+ str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec);
+}
+
+void gfs2_dinode_print(const struct gfs2_inode *ip)
+{
+ const struct gfs2_dinode_host *di = &ip->i_di;
+
+ printk(KERN_INFO " no_formal_ino = %llu\n",
+ (unsigned long long)ip->i_no_formal_ino);
+ printk(KERN_INFO " no_addr = %llu\n",
+ (unsigned long long)ip->i_no_addr);
+ printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size);
+ printk(KERN_INFO " di_blocks = %llu\n",
+ (unsigned long long)di->di_blocks);
+ printk(KERN_INFO " di_goal_meta = %llu\n",
+ (unsigned long long)di->di_goal_meta);
+ printk(KERN_INFO " di_goal_data = %llu\n",
+ (unsigned long long)di->di_goal_data);
+ printk(KERN_INFO " di_flags = 0x%.8X\n", di->di_flags);
+ printk(KERN_INFO " di_height = %u\n", di->di_height);
+ printk(KERN_INFO " di_depth = %u\n", di->di_depth);
+ printk(KERN_INFO " di_entries = %u\n", di->di_entries);
+ printk(KERN_INFO " di_eattr = %llu\n",
+ (unsigned long long)di->di_eattr);
+}
+
diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h
index b57f448b15b..4517ac82c01 100644
--- a/fs/gfs2/inode.h
+++ b/fs/gfs2/inode.h
@@ -10,17 +10,17 @@
#ifndef __INODE_DOT_H__
#define __INODE_DOT_H__
-static inline int gfs2_is_stuffed(struct gfs2_inode *ip)
+static inline int gfs2_is_stuffed(const struct gfs2_inode *ip)
{
return !ip->i_di.di_height;
}
-static inline int gfs2_is_jdata(struct gfs2_inode *ip)
+static inline int gfs2_is_jdata(const struct gfs2_inode *ip)
{
return ip->i_di.di_flags & GFS2_DIF_JDATA;
}
-static inline int gfs2_is_dir(struct gfs2_inode *ip)
+static inline int gfs2_is_dir(const struct gfs2_inode *ip)
{
return S_ISDIR(ip->i_inode.i_mode);
}
@@ -32,9 +32,25 @@ static inline void gfs2_set_inode_blocks(struct inode *inode)
(GFS2_SB(inode)->sd_sb.sb_bsize_shift - GFS2_BASIC_BLOCK_SHIFT);
}
+static inline int gfs2_check_inum(const struct gfs2_inode *ip, u64 no_addr,
+ u64 no_formal_ino)
+{
+ return ip->i_no_addr == no_addr && ip->i_no_formal_ino == no_formal_ino;
+}
+
+static inline void gfs2_inum_out(const struct gfs2_inode *ip,
+ struct gfs2_dirent *dent)
+{
+ dent->de_inum.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);
+ dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr);
+}
+
+
void gfs2_inode_attr_in(struct gfs2_inode *ip);
-struct inode *gfs2_inode_lookup(struct super_block *sb, struct gfs2_inum_host *inum, unsigned type);
-struct inode *gfs2_ilookup(struct super_block *sb, struct gfs2_inum_host *inum);
+void gfs2_set_iop(struct inode *inode);
+struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type,
+ u64 no_addr, u64 no_formal_ino);
+struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
int gfs2_inode_refresh(struct gfs2_inode *ip);
@@ -47,12 +63,14 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
int gfs2_rmdiri(struct gfs2_inode *dip, const struct qstr *name,
struct gfs2_inode *ip);
int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name,
- struct gfs2_inode *ip);
+ const struct gfs2_inode *ip);
int gfs2_ok_to_move(struct gfs2_inode *this, struct gfs2_inode *to);
int gfs2_readlinki(struct gfs2_inode *ip, char **buf, unsigned int *len);
int gfs2_glock_nq_atime(struct gfs2_holder *gh);
int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr);
struct inode *gfs2_lookup_simple(struct inode *dip, const char *name);
+void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
+void gfs2_dinode_print(const struct gfs2_inode *ip);
#endif /* __INODE_DOT_H__ */
diff --git a/fs/gfs2/locking/dlm/lock.c b/fs/gfs2/locking/dlm/lock.c
index c305255bfe8..542a797ac89 100644
--- a/fs/gfs2/locking/dlm/lock.c
+++ b/fs/gfs2/locking/dlm/lock.c
@@ -174,7 +174,6 @@ static int gdlm_create_lp(struct gdlm_ls *ls, struct lm_lockname *name,
lp->cur = DLM_LOCK_IV;
lp->lvb = NULL;
lp->hold_null = NULL;
- init_completion(&lp->ast_wait);
INIT_LIST_HEAD(&lp->clist);
INIT_LIST_HEAD(&lp->blist);
INIT_LIST_HEAD(&lp->delay_list);
@@ -399,6 +398,12 @@ static void gdlm_del_lvb(struct gdlm_lock *lp)
lp->lksb.sb_lvbptr = NULL;
}
+static int gdlm_ast_wait(void *word)
+{
+ schedule();
+ return 0;
+}
+
/* This can do a synchronous dlm request (requiring a lock_dlm thread to get
the completion) because gfs won't call hold_lvb() during a callback (from
the context of a lock_dlm thread). */
@@ -424,10 +429,10 @@ static int hold_null_lock(struct gdlm_lock *lp)
lpn->lkf = DLM_LKF_VALBLK | DLM_LKF_EXPEDITE;
set_bit(LFL_NOBAST, &lpn->flags);
set_bit(LFL_INLOCK, &lpn->flags);
+ set_bit(LFL_AST_WAIT, &lpn->flags);
- init_completion(&lpn->ast_wait);
gdlm_do_lock(lpn);
- wait_for_completion(&lpn->ast_wait);
+ wait_on_bit(&lpn->flags, LFL_AST_WAIT, gdlm_ast_wait, TASK_UNINTERRUPTIBLE);
error = lpn->lksb.sb_status;
if (error) {
printk(KERN_INFO "lock_dlm: hold_null_lock dlm error %d\n",
diff --git a/fs/gfs2/locking/dlm/lock_dlm.h b/fs/gfs2/locking/dlm/lock_dlm.h
index d074c6e6f9b..24d70f73b65 100644
--- a/fs/gfs2/locking/dlm/lock_dlm.h
+++ b/fs/gfs2/locking/dlm/lock_dlm.h
@@ -101,6 +101,7 @@ enum {
LFL_NOBAST = 10,
LFL_HEADQUE = 11,
LFL_UNLOCK_DELETE = 12,
+ LFL_AST_WAIT = 13,
};
struct gdlm_lock {
@@ -117,7 +118,6 @@ struct gdlm_lock {
unsigned long flags; /* lock_dlm flags LFL_ */
int bast_mode; /* protected by async_lock */
- struct completion ast_wait;
struct list_head clist; /* complete */
struct list_head blist; /* blocking */
diff --git a/fs/gfs2/locking/dlm/mount.c b/fs/gfs2/locking/dlm/mount.c
index 1d8faa3da8a..41c5b04caab 100644
--- a/fs/gfs2/locking/dlm/mount.c
+++ b/fs/gfs2/locking/dlm/mount.c
@@ -147,7 +147,7 @@ static int gdlm_mount(char *table_name, char *host_data,
error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
&ls->dlm_lockspace,
- nodir ? DLM_LSFL_NODIR : 0,
+ DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
GDLM_LVB_SIZE);
if (error) {
log_error("dlm_new_lockspace error %d", error);
diff --git a/fs/gfs2/locking/dlm/plock.c b/fs/gfs2/locking/dlm/plock.c
index f82495e18c2..fba1f1d87e4 100644
--- a/fs/gfs2/locking/dlm/plock.c
+++ b/fs/gfs2/locking/dlm/plock.c
@@ -242,7 +242,7 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
op->info.number = name->ln_number;
op->info.start = fl->fl_start;
op->info.end = fl->fl_end;
-
+ op->info.owner = (__u64)(long) fl->fl_owner;
send_op(op);
wait_event(recv_wq, (op->done != 0));
@@ -254,16 +254,20 @@ int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
}
spin_unlock(&ops_lock);
+ /* info.rv from userspace is 1 for conflict, 0 for no-conflict,
+ -ENOENT if there are no locks on the file */
+
rv = op->info.rv;
fl->fl_type = F_UNLCK;
if (rv == -ENOENT)
rv = 0;
- else if (rv == 0 && op->info.pid != fl->fl_pid) {
+ else if (rv > 0) {
fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
fl->fl_pid = op->info.pid;
fl->fl_start = op->info.start;
fl->fl_end = op->info.end;
+ rv = 0;
}
kfree(op);
diff --git a/fs/gfs2/locking/dlm/thread.c b/fs/gfs2/locking/dlm/thread.c
index 9cf1f168eaf..1aca51e4509 100644
--- a/fs/gfs2/locking/dlm/thread.c
+++ b/fs/gfs2/locking/dlm/thread.c
@@ -44,6 +44,13 @@ static void process_blocking(struct gdlm_lock *lp, int bast_mode)
ls->fscb(ls->sdp, cb, &lp->lockname);
}
+static void wake_up_ast(struct gdlm_lock *lp)
+{
+ clear_bit(LFL_AST_WAIT, &lp->flags);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&lp->flags, LFL_AST_WAIT);
+}
+
static void process_complete(struct gdlm_lock *lp)
{
struct gdlm_ls *ls = lp->ls;
@@ -136,7 +143,7 @@ static void process_complete(struct gdlm_lock *lp)
*/
if (test_and_clear_bit(LFL_SYNC_LVB, &lp->flags)) {
- complete(&lp->ast_wait);
+ wake_up_ast(lp);
return;
}
@@ -214,7 +221,7 @@ out:
if (test_bit(LFL_INLOCK, &lp->flags)) {
clear_bit(LFL_NOBLOCK, &lp->flags);
lp->cur = lp->req;
- complete(&lp->ast_wait);
+ wake_up_ast(lp);
return;
}
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 291415ddfe5..f49a12e2408 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -83,6 +83,11 @@ static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
gfs2_assert(sdp, bd->bd_ail == ai);
+ if (!bh){
+ list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+ continue;
+ }
+
if (!buffer_busy(bh)) {
if (!buffer_uptodate(bh)) {
gfs2_log_unlock(sdp);
@@ -125,6 +130,11 @@ static int gfs2_ail1_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai, int fl
bd_ail_st_list) {
bh = bd->bd_bh;
+ if (!bh){
+ list_move(&bd->bd_ail_st_list, &ai->ai_ail2_list);
+ continue;
+ }
+
gfs2_assert(sdp, bd->bd_ail == ai);
if (buffer_busy(bh)) {
@@ -262,8 +272,8 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
* @sdp: The GFS2 superblock
* @blks: The number of blocks to reserve
*
- * Note that we never give out the last 6 blocks of the journal. Thats
- * due to the fact that there is are a small number of header blocks
+ * Note that we never give out the last few blocks of the journal. Thats
+ * due to the fact that there is a small number of header blocks
* associated with each log flush. The exact number can't be known until
* flush time, so we ensure that we have just enough free blocks at all
* times to avoid running out during a log flush.
@@ -274,6 +284,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
{
unsigned int try = 0;
+ unsigned reserved_blks = 6 * (4096 / sdp->sd_vfs->s_blocksize);
if (gfs2_assert_warn(sdp, blks) ||
gfs2_assert_warn(sdp, blks <= sdp->sd_jdesc->jd_blocks))
@@ -281,7 +292,7 @@ int gfs2_log_reserve(struct gfs2_sbd *sdp, unsigned int blks)
mutex_lock(&sdp->sd_log_reserve_mutex);
gfs2_log_lock(sdp);
- while(sdp->sd_log_blks_free <= (blks + 6)) {
+ while(sdp->sd_log_blks_free <= (blks + reserved_blks)) {
gfs2_log_unlock(sdp);
gfs2_ail1_empty(sdp, 0);
gfs2_log_flush(sdp, NULL);
@@ -357,6 +368,58 @@ static inline unsigned int log_distance(struct gfs2_sbd *sdp, unsigned int newer
return dist;
}
+/**
+ * calc_reserved - Calculate the number of blocks to reserve when
+ * refunding a transaction's unused buffers.
+ * @sdp: The GFS2 superblock
+ *
+ * This is complex. We need to reserve room for all our currently used
+ * metadata buffers (e.g. normal file I/O rewriting file time stamps) and
+ * all our journaled data buffers for journaled files (e.g. files in the
+ * meta_fs like rindex, or files for which chattr +j was done.)
+ * If we don't reserve enough space, gfs2_log_refund and gfs2_log_flush
+ * will count it as free space (sd_log_blks_free) and corruption will follow.
+ *
+ * We can have metadata bufs and jdata bufs in the same journal. So each
+ * type gets its own log header, for which we need to reserve a block.
+ * In fact, each type has the potential for needing more than one header
+ * in cases where we have more buffers than will fit on a journal page.
+ * Metadata journal entries take up half the space of journaled buffer entries.
+ * Thus, metadata entries have buf_limit (502) and journaled buffers have
+ * databuf_limit (251) before they cause a wrap around.
+ *
+ * Also, we need to reserve blocks for revoke journal entries and one for an
+ * overall header for the lot.
+ *
+ * Returns: the number of blocks reserved
+ */
+static unsigned int calc_reserved(struct gfs2_sbd *sdp)
+{
+ unsigned int reserved = 0;
+ unsigned int mbuf_limit, metabufhdrs_needed;
+ unsigned int dbuf_limit, databufhdrs_needed;
+ unsigned int revokes = 0;
+
+ mbuf_limit = buf_limit(sdp);
+ metabufhdrs_needed = (sdp->sd_log_commited_buf +
+ (mbuf_limit - 1)) / mbuf_limit;
+ dbuf_limit = databuf_limit(sdp);
+ databufhdrs_needed = (sdp->sd_log_commited_databuf +
+ (dbuf_limit - 1)) / dbuf_limit;
+
+ if (sdp->sd_log_commited_revoke)
+ revokes = gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
+ sizeof(u64));
+
+ reserved = sdp->sd_log_commited_buf + metabufhdrs_needed +
+ sdp->sd_log_commited_databuf + databufhdrs_needed +
+ revokes;
+ /* One for the overall header */
+ if (reserved)
+ reserved++;
+ return reserved;
+}
+
static unsigned int current_tail(struct gfs2_sbd *sdp)
{
struct gfs2_ail *ai;
@@ -447,14 +510,14 @@ struct buffer_head *gfs2_log_fake_buf(struct gfs2_sbd *sdp,
return bh;
}
-static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail, int pull)
+static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
{
unsigned int dist = log_distance(sdp, new_tail, sdp->sd_log_tail);
ail2_empty(sdp, new_tail);
gfs2_log_lock(sdp);
- sdp->sd_log_blks_free += dist - (pull ? 1 : 0);
+ sdp->sd_log_blks_free += dist;
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks);
gfs2_log_unlock(sdp);
@@ -504,7 +567,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
brelse(bh);
if (sdp->sd_log_tail != tail)
- log_pull_tail(sdp, tail, pull);
+ log_pull_tail(sdp, tail);
else
gfs2_assert_withdraw(sdp, !pull);
@@ -517,6 +580,7 @@ static void log_flush_commit(struct gfs2_sbd *sdp)
struct list_head *head = &sdp->sd_log_flush_list;
struct gfs2_log_buf *lb;
struct buffer_head *bh;
+ int flushcount = 0;
while (!list_empty(head)) {
lb = list_entry(head->next, struct gfs2_log_buf, lb_list);
@@ -533,9 +597,20 @@ static void log_flush_commit(struct gfs2_sbd *sdp)
} else
brelse(bh);
kfree(lb);
+ flushcount++;
}
- log_write_header(sdp, 0, 0);
+ /* If nothing was journaled, the header is unplanned and unwanted. */
+ if (flushcount) {
+ log_write_header(sdp, 0, 0);
+ } else {
+ unsigned int tail;
+ tail = current_tail(sdp);
+
+ gfs2_ail1_empty(sdp, 0);
+ if (sdp->sd_log_tail != tail)
+ log_pull_tail(sdp, tail);
+ }
}
/**
@@ -565,7 +640,10 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
INIT_LIST_HEAD(&ai->ai_ail1_list);
INIT_LIST_HEAD(&ai->ai_ail2_list);
- gfs2_assert_withdraw(sdp, sdp->sd_log_num_buf == sdp->sd_log_commited_buf);
+ gfs2_assert_withdraw(sdp,
+ sdp->sd_log_num_buf + sdp->sd_log_num_jdata ==
+ sdp->sd_log_commited_buf +
+ sdp->sd_log_commited_databuf);
gfs2_assert_withdraw(sdp,
sdp->sd_log_num_revoke == sdp->sd_log_commited_revoke);
@@ -576,16 +654,19 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
lops_before_commit(sdp);
if (!list_empty(&sdp->sd_log_flush_list))
log_flush_commit(sdp);
- else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle)
+ else if (sdp->sd_log_tail != current_tail(sdp) && !sdp->sd_log_idle){
+ gfs2_log_lock(sdp);
+ sdp->sd_log_blks_free--; /* Adjust for unreserved buffer */
+ gfs2_log_unlock(sdp);
log_write_header(sdp, 0, PULL);
+ }
lops_after_commit(sdp, ai);
gfs2_log_lock(sdp);
sdp->sd_log_head = sdp->sd_log_flush_head;
- sdp->sd_log_blks_free -= sdp->sd_log_num_hdrs;
sdp->sd_log_blks_reserved = 0;
sdp->sd_log_commited_buf = 0;
- sdp->sd_log_num_hdrs = 0;
+ sdp->sd_log_commited_databuf = 0;
sdp->sd_log_commited_revoke = 0;
if (!list_empty(&ai->ai_ail1_list)) {
@@ -602,32 +683,26 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
static void log_refund(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
{
- unsigned int reserved = 0;
+ unsigned int reserved;
unsigned int old;
gfs2_log_lock(sdp);
sdp->sd_log_commited_buf += tr->tr_num_buf_new - tr->tr_num_buf_rm;
- gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_buf) >= 0);
+ sdp->sd_log_commited_databuf += tr->tr_num_databuf_new -
+ tr->tr_num_databuf_rm;
+ gfs2_assert_withdraw(sdp, (((int)sdp->sd_log_commited_buf) >= 0) ||
+ (((int)sdp->sd_log_commited_databuf) >= 0));
sdp->sd_log_commited_revoke += tr->tr_num_revoke - tr->tr_num_revoke_rm;
gfs2_assert_withdraw(sdp, ((int)sdp->sd_log_commited_revoke) >= 0);
-
- if (sdp->sd_log_commited_buf)
- reserved += sdp->sd_log_commited_buf;
- if (sdp->sd_log_commited_revoke)
- reserved += gfs2_struct2blk(sdp, sdp->sd_log_commited_revoke,
- sizeof(u64));
- if (reserved)
- reserved++;
-
+ reserved = calc_reserved(sdp);
old = sdp->sd_log_blks_free;
sdp->sd_log_blks_free += tr->tr_reserved -
(reserved - sdp->sd_log_blks_reserved);
gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free >= old);
- gfs2_assert_withdraw(sdp,
- sdp->sd_log_blks_free <= sdp->sd_jdesc->jd_blocks +
- sdp->sd_log_num_hdrs);
+ gfs2_assert_withdraw(sdp, sdp->sd_log_blks_free <=
+ sdp->sd_jdesc->jd_blocks);
sdp->sd_log_blks_reserved = reserved;
@@ -673,13 +748,13 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_revoke);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_rg);
gfs2_assert_withdraw(sdp, !sdp->sd_log_num_databuf);
- gfs2_assert_withdraw(sdp, !sdp->sd_log_num_hdrs);
gfs2_assert_withdraw(sdp, list_empty(&sdp->sd_ail1_list));
sdp->sd_log_flush_head = sdp->sd_log_head;
sdp->sd_log_flush_wrapped = 0;
- log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT, 0);
+ log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT,
+ (sdp->sd_log_tail == current_tail(sdp)) ? 0 : PULL);
gfs2_assert_warn(sdp, sdp->sd_log_blks_free == sdp->sd_jdesc->jd_blocks);
gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index f82d84d05d2..aff70f0698f 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -17,6 +17,7 @@
#include "gfs2.h"
#include "incore.h"
+#include "inode.h"
#include "glock.h"
#include "log.h"
#include "lops.h"
@@ -117,15 +118,13 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
struct gfs2_log_descriptor *ld;
struct gfs2_bufdata *bd1 = NULL, *bd2;
unsigned int total = sdp->sd_log_num_buf;
- unsigned int offset = sizeof(struct gfs2_log_descriptor);
+ unsigned int offset = BUF_OFFSET;
unsigned int limit;
unsigned int num;
unsigned n;
__be64 *ptr;
- offset += sizeof(__be64) - 1;
- offset &= ~(sizeof(__be64) - 1);
- limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
+ limit = buf_limit(sdp);
/* for 4k blocks, limit = 503 */
bd1 = bd2 = list_prepare_entry(bd1, &sdp->sd_log_le_buf, bd_le.le_list);
@@ -134,7 +133,6 @@ static void buf_lo_before_commit(struct gfs2_sbd *sdp)
if (total > limit)
num = limit;
bh = gfs2_log_get_buf(sdp);
- sdp->sd_log_num_hdrs++;
ld = (struct gfs2_log_descriptor *)bh->b_data;
ptr = (__be64 *)(bh->b_data + offset);
ld->ld_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
@@ -469,25 +467,28 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)
struct gfs2_inode *ip = GFS2_I(mapping->host);
gfs2_log_lock(sdp);
+ if (!list_empty(&bd->bd_list_tr)) {
+ gfs2_log_unlock(sdp);
+ return;
+ }
tr->tr_touched = 1;
- if (list_empty(&bd->bd_list_tr) &&
- (ip->i_di.di_flags & GFS2_DIF_JDATA)) {
+ if (gfs2_is_jdata(ip)) {
tr->tr_num_buf++;
list_add(&bd->bd_list_tr, &tr->tr_list_buf);
- gfs2_log_unlock(sdp);
- gfs2_pin(sdp, bd->bd_bh);
- tr->tr_num_buf_new++;
- } else {
- gfs2_log_unlock(sdp);
}
+ gfs2_log_unlock(sdp);
+ if (!list_empty(&le->le_list))
+ return;
+
gfs2_trans_add_gl(bd->bd_gl);
- gfs2_log_lock(sdp);
- if (list_empty(&le->le_list)) {
- if (ip->i_di.di_flags & GFS2_DIF_JDATA)
- sdp->sd_log_num_jdata++;
- sdp->sd_log_num_databuf++;
- list_add(&le->le_list, &sdp->sd_log_le_databuf);
+ if (gfs2_is_jdata(ip)) {
+ sdp->sd_log_num_jdata++;
+ gfs2_pin(sdp, bd->bd_bh);
+ tr->tr_num_databuf_new++;
}
+ sdp->sd_log_num_databuf++;
+ gfs2_log_lock(sdp);
+ list_add(&le->le_list, &sdp->sd_log_le_databuf);
gfs2_log_unlock(sdp);
}
@@ -520,7 +521,6 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
LIST_HEAD(started);
struct gfs2_bufdata *bd1 = NULL, *bd2, *bdt;
struct buffer_head *bh = NULL,*bh1 = NULL;
- unsigned int offset = sizeof(struct gfs2_log_descriptor);
struct gfs2_log_descriptor *ld;
unsigned int limit;
unsigned int total_dbuf = sdp->sd_log_num_databuf;
@@ -528,9 +528,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
unsigned int num, n;
__be64 *ptr = NULL;
- offset += 2*sizeof(__be64) - 1;
- offset &= ~(2*sizeof(__be64) - 1);
- limit = (sdp->sd_sb.sb_bsize - offset)/sizeof(__be64);
+ limit = databuf_limit(sdp);
/*
* Start writing ordered buffers, write journaled buffers
@@ -581,10 +579,10 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
gfs2_log_unlock(sdp);
if (!bh) {
bh = gfs2_log_get_buf(sdp);
- sdp->sd_log_num_hdrs++;
ld = (struct gfs2_log_descriptor *)
bh->b_data;
- ptr = (__be64 *)(bh->b_data + offset);
+ ptr = (__be64 *)(bh->b_data +
+ DATABUF_OFFSET);
ld->ld_header.mh_magic =
cpu_to_be32(GFS2_MAGIC);
ld->ld_header.mh_type =
@@ -605,7 +603,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
if (unlikely(magic != 0))
set_buffer_escaped(bh1);
gfs2_log_lock(sdp);
- if (n++ > num)
+ if (++n >= num)
break;
} else if (!bh1) {
total_dbuf--;
@@ -622,6 +620,7 @@ static void databuf_lo_before_commit(struct gfs2_sbd *sdp)
}
gfs2_log_unlock(sdp);
if (bh) {
+ set_buffer_mapped(bh);
set_buffer_dirty(bh);
ll_rw_block(WRITE, 1, &bh);
bh = NULL;
diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h
index 965bc65c7c6..41a00df7558 100644
--- a/fs/gfs2/lops.h
+++ b/fs/gfs2/lops.h
@@ -13,6 +13,13 @@
#include <linux/list.h>
#include "incore.h"
+#define BUF_OFFSET \
+ ((sizeof(struct gfs2_log_descriptor) + sizeof(__be64) - 1) & \
+ ~(sizeof(__be64) - 1))
+#define DATABUF_OFFSET \
+ ((sizeof(struct gfs2_log_descriptor) + (2 * sizeof(__be64) - 1)) & \
+ ~(2 * sizeof(__be64) - 1))
+
extern const struct gfs2_log_operations gfs2_glock_lops;
extern const struct gfs2_log_operations gfs2_buf_lops;
extern const struct gfs2_log_operations gfs2_revoke_lops;
@@ -21,6 +28,22 @@ extern const struct gfs2_log_operations gfs2_databuf_lops;
extern const struct gfs2_log_operations *gfs2_log_ops[];
+static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
+{
+ unsigned int limit;
+
+ limit = (sdp->sd_sb.sb_bsize - BUF_OFFSET) / sizeof(__be64);
+ return limit;
+}
+
+static inline unsigned int databuf_limit(struct gfs2_sbd *sdp)
+{
+ unsigned int limit;
+
+ limit = (sdp->sd_sb.sb_bsize - DATABUF_OFFSET) / (2 * sizeof(__be64));
+ return limit;
+}
+
static inline void lops_init_le(struct gfs2_log_element *le,
const struct gfs2_log_operations *lops)
{
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index e62d4f620c5..8da343b34ae 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -387,12 +387,18 @@ void gfs2_meta_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen)
if (test_clear_buffer_pinned(bh)) {
struct gfs2_trans *tr = current->journal_info;
+ struct gfs2_inode *bh_ip =
+ GFS2_I(bh->b_page->mapping->host);
+
gfs2_log_lock(sdp);
list_del_init(&bd->bd_le.le_list);
gfs2_assert_warn(sdp, sdp->sd_log_num_buf);
sdp->sd_log_num_buf--;
gfs2_log_unlock(sdp);
- tr->tr_num_buf_rm++;
+ if (bh_ip->i_inode.i_private != NULL)
+ tr->tr_num_databuf_rm++;
+ else
+ tr->tr_num_buf_rm++;
brelse(bh);
}
if (bd) {
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index e037425bc04..527bf19d969 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -63,7 +63,7 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
struct buffer_head **bhp)
{
- return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp);
+ return gfs2_meta_indirect_buffer(ip, 0, ip->i_no_addr, 0, bhp);
}
struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
diff --git a/fs/gfs2/mount.c b/fs/gfs2/mount.c
index 4864659555d..6f006a804db 100644
--- a/fs/gfs2/mount.c
+++ b/fs/gfs2/mount.c
@@ -82,20 +82,19 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, char *data_arg, int remount)
char *options, *o, *v;
int error = 0;
- if (!remount) {
- /* If someone preloaded options, use those instead */
- spin_lock(&gfs2_sys_margs_lock);
- if (gfs2_sys_margs) {
- data = gfs2_sys_margs;
- gfs2_sys_margs = NULL;
- }
- spin_unlock(&gfs2_sys_margs_lock);
-
- /* Set some defaults */
- args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
- args->ar_quota = GFS2_QUOTA_DEFAULT;
- args->ar_data = GFS2_DATA_DEFAULT;
+ /* If someone preloaded options, use those instead */
+ spin_lock(&gfs2_sys_margs_lock);
+ if (!remount && gfs2_sys_margs) {
+ data = gfs2_sys_margs;
+ gfs2_sys_margs = NULL;
}
+ spin_unlock(&gfs2_sys_margs_lock);
+
+ /* Set some defaults */
+ memset(args, 0, sizeof(struct gfs2_args));
+ args->ar_num_glockd = GFS2_GLOCKD_DEFAULT;
+ args->ar_quota = GFS2_QUOTA_DEFAULT;
+ args->ar_data = GFS2_DATA_DEFAULT;
/* Split the options into tokens with the "," character and
process them */
diff --git a/fs/gfs2/ondisk.c b/fs/gfs2/ondisk.c
deleted file mode 100644
index d9ecfd23a49..00000000000
--- a/fs/gfs2/ondisk.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/buffer_head.h>
-
-#include "gfs2.h"
-#include <linux/gfs2_ondisk.h>
-#include <linux/lm_interface.h>
-#include "incore.h"
-
-#define pv(struct, member, fmt) printk(KERN_INFO " "#member" = "fmt"\n", \
- struct->member);
-
-/*
- * gfs2_xxx_in - read in an xxx struct
- * first arg: the cpu-order structure
- * buf: the disk-order buffer
- *
- * gfs2_xxx_out - write out an xxx struct
- * first arg: the cpu-order structure
- * buf: the disk-order buffer
- *
- * gfs2_xxx_print - print out an xxx struct
- * first arg: the cpu-order structure
- */
-
-void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf)
-{
- const struct gfs2_inum *str = buf;
-
- no->no_formal_ino = be64_to_cpu(str->no_formal_ino);
- no->no_addr = be64_to_cpu(str->no_addr);
-}
-
-void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf)
-{
- struct gfs2_inum *str = buf;
-
- str->no_formal_ino = cpu_to_be64(no->no_formal_ino);
- str->no_addr = cpu_to_be64(no->no_addr);
-}
-
-static void gfs2_inum_print(const struct gfs2_inum_host *no)
-{
- printk(KERN_INFO " no_formal_ino = %llu\n", (unsigned long long)no->no_formal_ino);
- printk(KERN_INFO " no_addr = %llu\n", (unsigned long long)no->no_addr);
-}
-
-static void gfs2_meta_header_in(struct gfs2_meta_header_host *mh, const void *buf)
-{
- const struct gfs2_meta_header *str = buf;
-
- mh->mh_magic = be32_to_cpu(str->mh_magic);
- mh->mh_type = be32_to_cpu(str->mh_type);
- mh->mh_format = be32_to_cpu(str->mh_format);
-}
-
-void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
-{
- const struct gfs2_sb *str = buf;
-
- gfs2_meta_header_in(&sb->sb_header, buf);
-
- sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
- sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
- sb->sb_bsize = be32_to_cpu(str->sb_bsize);
- sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
-
- gfs2_inum_in(&sb->sb_master_dir, (char *)&str->sb_master_dir);
- gfs2_inum_in(&sb->sb_root_dir, (char *)&str->sb_root_dir);
-
- memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
- memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
-}
-
-void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf)
-{
- const struct gfs2_rindex *str = buf;
-
- ri->ri_addr = be64_to_cpu(str->ri_addr);
- ri->ri_length = be32_to_cpu(str->ri_length);
- ri->ri_data0 = be64_to_cpu(str->ri_data0);
- ri->ri_data = be32_to_cpu(str->ri_data);
- ri->ri_bitbytes = be32_to_cpu(str->ri_bitbytes);
-
-}
-
-void gfs2_rindex_print(const struct gfs2_rindex_host *ri)
-{
- printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)ri->ri_addr);
- pv(ri, ri_length, "%u");
-
- printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)ri->ri_data0);
- pv(ri, ri_data, "%u");
-
- pv(ri, ri_bitbytes, "%u");
-}
-
-void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
-{
- const struct gfs2_rgrp *str = buf;
-
- rg->rg_flags = be32_to_cpu(str->rg_flags);
- rg->rg_free = be32_to_cpu(str->rg_free);
- rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
- rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
-}
-
-void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
-{
- struct gfs2_rgrp *str = buf;
-
- str->rg_flags = cpu_to_be32(rg->rg_flags);
- str->rg_free = cpu_to_be32(rg->rg_free);
- str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
- str->__pad = cpu_to_be32(0);
- str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
- memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
-}
-
-void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
-{
- const struct gfs2_quota *str = buf;
-
- qu->qu_limit = be64_to_cpu(str->qu_limit);
- qu->qu_warn = be64_to_cpu(str->qu_warn);
- qu->qu_value = be64_to_cpu(str->qu_value);
-}
-
-void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
-{
- const struct gfs2_dinode_host *di = &ip->i_di;
- struct gfs2_dinode *str = buf;
-
- str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
- str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI);
- str->di_header.__pad0 = 0;
- str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI);
- str->di_header.__pad1 = 0;
-
- gfs2_inum_out(&ip->i_num, &str->di_num);
-
- str->di_mode = cpu_to_be32(ip->i_inode.i_mode);
- str->di_uid = cpu_to_be32(ip->i_inode.i_uid);
- str->di_gid = cpu_to_be32(ip->i_inode.i_gid);
- str->di_nlink = cpu_to_be32(ip->i_inode.i_nlink);
- str->di_size = cpu_to_be64(di->di_size);
- str->di_blocks = cpu_to_be64(di->di_blocks);
- str->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
- str->di_mtime = cpu_to_be64(ip->i_inode.i_mtime.tv_sec);
- str->di_ctime = cpu_to_be64(ip->i_inode.i_ctime.tv_sec);
-
- str->di_goal_meta = cpu_to_be64(di->di_goal_meta);
- str->di_goal_data = cpu_to_be64(di->di_goal_data);
- str->di_generation = cpu_to_be64(di->di_generation);
-
- str->di_flags = cpu_to_be32(di->di_flags);
- str->di_height = cpu_to_be16(di->di_height);
- str->di_payload_format = cpu_to_be32(S_ISDIR(ip->i_inode.i_mode) &&
- !(ip->i_di.di_flags & GFS2_DIF_EXHASH) ?
- GFS2_FORMAT_DE : 0);
- str->di_depth = cpu_to_be16(di->di_depth);
- str->di_entries = cpu_to_be32(di->di_entries);
-
- str->di_eattr = cpu_to_be64(di->di_eattr);
-}
-
-void gfs2_dinode_print(const struct gfs2_inode *ip)
-{
- const struct gfs2_dinode_host *di = &ip->i_di;
-
- gfs2_inum_print(&ip->i_num);
-
- printk(KERN_INFO " di_size = %llu\n", (unsigned long long)di->di_size);
- printk(KERN_INFO " di_blocks = %llu\n", (unsigned long long)di->di_blocks);
- printk(KERN_INFO " di_goal_meta = %llu\n", (unsigned long long)di->di_goal_meta);
- printk(KERN_INFO " di_goal_data = %llu\n", (unsigned long long)di->di_goal_data);
-
- pv(di, di_flags, "0x%.8X");
- pv(di, di_height, "%u");
-
- pv(di, di_depth, "%u");
- pv(di, di_entries, "%u");
-
- printk(KERN_INFO " di_eattr = %llu\n", (unsigned long long)di->di_eattr);
-}
-
-void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
-{
- const struct gfs2_log_header *str = buf;
-
- gfs2_meta_header_in(&lh->lh_header, buf);
- lh->lh_sequence = be64_to_cpu(str->lh_sequence);
- lh->lh_flags = be32_to_cpu(str->lh_flags);
- lh->lh_tail = be32_to_cpu(str->lh_tail);
- lh->lh_blkno = be32_to_cpu(str->lh_blkno);
- lh->lh_hash = be32_to_cpu(str->lh_hash);
-}
-
-void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf)
-{
- const struct gfs2_inum_range *str = buf;
-
- ir->ir_start = be64_to_cpu(str->ir_start);
- ir->ir_length = be64_to_cpu(str->ir_length);
-}
-
-void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf)
-{
- struct gfs2_inum_range *str = buf;
-
- str->ir_start = cpu_to_be64(ir->ir_start);
- str->ir_length = cpu_to_be64(ir->ir_length);
-}
-
-void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
-{
- const struct gfs2_statfs_change *str = buf;
-
- sc->sc_total = be64_to_cpu(str->sc_total);
- sc->sc_free = be64_to_cpu(str->sc_free);
- sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
-}
-
-void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
-{
- struct gfs2_statfs_change *str = buf;
-
- str->sc_total = cpu_to_be64(sc->sc_total);
- str->sc_free = cpu_to_be64(sc->sc_free);
- str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
-}
-
-void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
-{
- const struct gfs2_quota_change *str = buf;
-
- qc->qc_change = be64_to_cpu(str->qc_change);
- qc->qc_flags = be32_to_cpu(str->qc_flags);
- qc->qc_id = be32_to_cpu(str->qc_id);
-}
-
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 30c15622174..26c888890c2 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
@@ -32,6 +32,7 @@
#include "trans.h"
#include "rgrp.h"
#include "ops_file.h"
+#include "super.h"
#include "util.h"
#include "glops.h"
@@ -49,6 +50,8 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
end = start + bsize;
if (end <= from || start >= to)
continue;
+ if (gfs2_is_jdata(ip))
+ set_buffer_uptodate(bh);
gfs2_trans_add_bh(ip->i_gl, bh, 0);
}
}
@@ -134,7 +137,9 @@ static int gfs2_writepage(struct page *page, struct writeback_control *wbc)
return 0; /* don't care */
}
- if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) {
+ if ((sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip)) &&
+ PageChecked(page)) {
+ ClearPageChecked(page);
error = gfs2_trans_begin(sdp, RES_DINODE + 1, 0);
if (error)
goto out_ignore;
@@ -203,11 +208,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
* so we need to supply one here. It doesn't happen often.
*/
if (unlikely(page->index)) {
- kaddr = kmap_atomic(page, KM_USER0);
- memset(kaddr, 0, PAGE_CACHE_SIZE);
- kunmap_atomic(kaddr, KM_USER0);
- flush_dcache_page(page);
- SetPageUptodate(page);
+ zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
return 0;
}
@@ -450,6 +451,31 @@ out_uninit:
}
/**
+ * adjust_fs_space - Adjusts the free space available due to gfs2_grow
+ * @inode: the rindex inode
+ */
+static void adjust_fs_space(struct inode *inode)
+{
+ struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+ struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+ struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+ u64 fs_total, new_free;
+
+ /* Total up the file system space, according to the latest rindex. */
+ fs_total = gfs2_ri_total(sdp);
+
+ spin_lock(&sdp->sd_statfs_spin);
+ if (fs_total > (m_sc->sc_total + l_sc->sc_total))
+ new_free = fs_total - (m_sc->sc_total + l_sc->sc_total);
+ else
+ new_free = 0;
+ spin_unlock(&sdp->sd_statfs_spin);
+ fs_warn(sdp, "File system extended by %llu blocks.\n",
+ (unsigned long long)new_free);
+ gfs2_statfs_change(sdp, new_free, new_free, 0);
+}
+
+/**
* gfs2_commit_write - Commit write to a file
* @file: The file to write to
* @page: The page containing the data
@@ -511,6 +537,9 @@ static int gfs2_commit_write(struct file *file, struct page *page,
di->di_size = cpu_to_be64(inode->i_size);
}
+ if (inode == sdp->sd_rindex)
+ adjust_fs_space(inode);
+
brelse(dibh);
gfs2_trans_end(sdp);
if (al->al_requested) {
@@ -543,6 +572,23 @@ fail_nounlock:
}
/**
+ * gfs2_set_page_dirty - Page dirtying function
+ * @page: The page to dirty
+ *
+ * Returns: 1 if it dirtyed the page, or 0 otherwise
+ */
+
+static int gfs2_set_page_dirty(struct page *page)
+{
+ struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+ struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host);
+
+ if (sdp->sd_args.ar_data == GFS2_DATA_ORDERED || gfs2_is_jdata(ip))
+ SetPageChecked(page);
+ return __set_page_dirty_buffers(page);
+}
+
+/**
* gfs2_bmap - Block map function
* @mapping: Address space info
* @lblock: The block to map
@@ -578,6 +624,8 @@ static void discard_buffer(struct gfs2_sbd *sdp, struct buffer_head *bh)
if (bd) {
bd->bd_bh = NULL;
bh->b_private = NULL;
+ if (!bd->bd_ail && list_empty(&bd->bd_le.le_list))
+ kmem_cache_free(gfs2_bufdata_cachep, bd);
}
gfs2_log_unlock(sdp);
@@ -598,6 +646,8 @@ static void gfs2_invalidatepage(struct page *page, unsigned long offset)
unsigned int curr_off = 0;
BUG_ON(!PageLocked(page));
+ if (offset == 0)
+ ClearPageChecked(page);
if (!page_has_buffers(page))
return;
@@ -728,8 +778,8 @@ static unsigned limit = 0;
return;
fs_warn(sdp, "ip = %llu %llu\n",
- (unsigned long long)ip->i_num.no_formal_ino,
- (unsigned long long)ip->i_num.no_addr);
+ (unsigned long long)ip->i_no_formal_ino,
+ (unsigned long long)ip->i_no_addr);
for (x = 0; x < GFS2_MAX_META_HEIGHT; x++)
fs_warn(sdp, "ip->i_cache[%u] = %s\n",
@@ -810,6 +860,7 @@ const struct address_space_operations gfs2_file_aops = {
.sync_page = block_sync_page,
.prepare_write = gfs2_prepare_write,
.commit_write = gfs2_commit_write,
+ .set_page_dirty = gfs2_set_page_dirty,
.bmap = gfs2_bmap,
.invalidatepage = gfs2_invalidatepage,
.releasepage = gfs2_releasepage,
diff --git a/fs/gfs2/ops_address.h b/fs/gfs2/ops_address.h
index 35aaee4aa7e..fa1b5b3d28b 100644
--- a/fs/gfs2/ops_address.h
+++ b/fs/gfs2/ops_address.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
diff --git a/fs/gfs2/ops_dentry.c b/fs/gfs2/ops_dentry.c
index a6fdc52f554..793e334d098 100644
--- a/fs/gfs2/ops_dentry.c
+++ b/fs/gfs2/ops_dentry.c
@@ -21,6 +21,7 @@
#include "glock.h"
#include "ops_dentry.h"
#include "util.h"
+#include "inode.h"
/**
* gfs2_drevalidate - Check directory lookup consistency
@@ -40,14 +41,15 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
struct gfs2_inode *dip = GFS2_I(parent->d_inode);
struct inode *inode = dentry->d_inode;
struct gfs2_holder d_gh;
- struct gfs2_inode *ip;
- struct gfs2_inum_host inum;
- unsigned int type;
+ struct gfs2_inode *ip = NULL;
int error;
int had_lock=0;
- if (inode && is_bad_inode(inode))
- goto invalid;
+ if (inode) {
+ if (is_bad_inode(inode))
+ goto invalid;
+ ip = GFS2_I(inode);
+ }
if (sdp->sd_args.ar_localcaching)
goto valid;
@@ -59,7 +61,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
goto fail;
}
- error = gfs2_dir_search(parent->d_inode, &dentry->d_name, &inum, &type);
+ error = gfs2_dir_check(parent->d_inode, &dentry->d_name, ip);
switch (error) {
case 0:
if (!inode)
@@ -73,16 +75,6 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
goto fail_gunlock;
}
- ip = GFS2_I(inode);
-
- if (!gfs2_inum_equal(&ip->i_num, &inum))
- goto invalid_gunlock;
-
- if (IF2DT(ip->i_inode.i_mode) != type) {
- gfs2_consist_inode(dip);
- goto fail_gunlock;
- }
-
valid_gunlock:
if (!had_lock)
gfs2_glock_dq_uninit(&d_gh);
diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c
index aad918337a4..99ea5659bc2 100644
--- a/fs/gfs2/ops_export.c
+++ b/fs/gfs2/ops_export.c
@@ -22,10 +22,14 @@
#include "glops.h"
#include "inode.h"
#include "ops_dentry.h"
-#include "ops_export.h"
+#include "ops_fstype.h"
#include "rgrp.h"
#include "util.h"
+#define GFS2_SMALL_FH_SIZE 4
+#define GFS2_LARGE_FH_SIZE 8
+#define GFS2_OLD_FH_SIZE 10
+
static struct dentry *gfs2_decode_fh(struct super_block *sb,
__u32 *p,
int fh_len,
@@ -35,31 +39,28 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb,
void *context)
{
__be32 *fh = (__force __be32 *)p;
- struct gfs2_fh_obj fh_obj;
- struct gfs2_inum_host *this, parent;
+ struct gfs2_inum_host inum, parent;
- this = &fh_obj.this;
- fh_obj.imode = DT_UNKNOWN;
memset(&parent, 0, sizeof(struct gfs2_inum));
switch (fh_len) {
case GFS2_LARGE_FH_SIZE:
+ case GFS2_OLD_FH_SIZE:
parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32;
parent.no_formal_ino |= be32_to_cpu(fh[5]);
parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
parent.no_addr |= be32_to_cpu(fh[7]);
- fh_obj.imode = be32_to_cpu(fh[8]);
case GFS2_SMALL_FH_SIZE:
- this->no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
- this->no_formal_ino |= be32_to_cpu(fh[1]);
- this->no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
- this->no_addr |= be32_to_cpu(fh[3]);
+ inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
+ inum.no_formal_ino |= be32_to_cpu(fh[1]);
+ inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
+ inum.no_addr |= be32_to_cpu(fh[3]);
break;
default:
return NULL;
}
- return gfs2_export_ops.find_exported_dentry(sb, &fh_obj, &parent,
+ return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent,
acceptable, context);
}
@@ -75,10 +76,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
(connectable && *len < GFS2_LARGE_FH_SIZE))
return 255;
- fh[0] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
- fh[1] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
- fh[2] = cpu_to_be32(ip->i_num.no_addr >> 32);
- fh[3] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
+ fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
+ fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+ fh[2] = cpu_to_be32(ip->i_no_addr >> 32);
+ fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
*len = GFS2_SMALL_FH_SIZE;
if (!connectable || inode == sb->s_root->d_inode)
@@ -90,13 +91,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
igrab(inode);
spin_unlock(&dentry->d_lock);
- fh[4] = cpu_to_be32(ip->i_num.no_formal_ino >> 32);
- fh[5] = cpu_to_be32(ip->i_num.no_formal_ino & 0xFFFFFFFF);
- fh[6] = cpu_to_be32(ip->i_num.no_addr >> 32);
- fh[7] = cpu_to_be32(ip->i_num.no_addr & 0xFFFFFFFF);
-
- fh[8] = cpu_to_be32(inode->i_mode);
- fh[9] = 0; /* pad to double word */
+ fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
+ fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
+ fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
+ fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
*len = GFS2_LARGE_FH_SIZE;
iput(inode);
@@ -144,7 +142,8 @@ static int gfs2_get_name(struct dentry *parent, char *name,
ip = GFS2_I(inode);
*name = 0;
- gnfd.inum = ip->i_num;
+ gnfd.inum.no_addr = ip->i_no_addr;
+ gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
gnfd.name = name;
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
@@ -192,8 +191,7 @@ static struct dentry *gfs2_get_parent(struct dentry *child)
static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
- struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj;
- struct gfs2_inum_host *inum = &fh_obj->this;
+ struct gfs2_inum_host *inum = inum_obj;
struct gfs2_holder i_gh, ri_gh, rgd_gh;
struct gfs2_rgrpd *rgd;
struct inode *inode;
@@ -202,9 +200,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
/* System files? */
- inode = gfs2_ilookup(sb, inum);
+ inode = gfs2_ilookup(sb, inum->no_addr);
if (inode) {
- if (GFS2_I(inode)->i_num.no_formal_ino != inum->no_formal_ino) {
+ if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
iput(inode);
return ERR_PTR(-ESTALE);
}
@@ -236,7 +234,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
gfs2_glock_dq_uninit(&rgd_gh);
gfs2_glock_dq_uninit(&ri_gh);
- inode = gfs2_inode_lookup(sb, inum, fh_obj->imode);
+ inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
+ inum->no_addr,
+ 0);
if (!inode)
goto fail;
if (IS_ERR(inode)) {
@@ -250,6 +250,15 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
goto fail;
}
+ /* Pick up the works we bypass in gfs2_inode_lookup */
+ if (inode->i_state & I_NEW)
+ gfs2_set_iop(inode);
+
+ if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
+ iput(inode);
+ goto fail;
+ }
+
error = -EIO;
if (GFS2_I(inode)->i_di.di_flags & GFS2_DIF_SYSTEM) {
iput(inode);
diff --git a/fs/gfs2/ops_export.h b/fs/gfs2/ops_export.h
deleted file mode 100644
index f925a955b3b..00000000000
--- a/fs/gfs2/ops_export.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
- *
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU General Public License version 2.
- */
-
-#ifndef __OPS_EXPORT_DOT_H__
-#define __OPS_EXPORT_DOT_H__
-
-#define GFS2_SMALL_FH_SIZE 4
-#define GFS2_LARGE_FH_SIZE 10
-
-extern struct export_operations gfs2_export_ops;
-struct gfs2_fh_obj {
- struct gfs2_inum_host this;
- __u32 imode;
-};
-
-#endif /* __OPS_EXPORT_DOT_H__ */
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 064df880458..196d83266e3 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -502,7 +502,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
struct lm_lockname name =
- { .ln_number = ip->i_num.no_addr,
+ { .ln_number = ip->i_no_addr,
.ln_type = LM_TYPE_PLOCK };
if (!(fl->fl_flags & FL_POSIX))
@@ -557,7 +557,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
gfs2_glock_dq_uninit(fl_gh);
} else {
error = gfs2_glock_get(GFS2_SB(&ip->i_inode),
- ip->i_num.no_addr, &gfs2_flock_glops,
+ ip->i_no_addr, &gfs2_flock_glops,
CREATE, &gl);
if (error)
goto out;
@@ -635,7 +635,6 @@ const struct file_operations gfs2_file_fops = {
.release = gfs2_close,
.fsync = gfs2_fsync,
.lock = gfs2_lock,
- .sendfile = generic_file_sendfile,
.flock = gfs2_flock,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 2c5f8e7def0..cf5aa505054 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -27,7 +27,6 @@
#include "inode.h"
#include "lm.h"
#include "mount.h"
-#include "ops_export.h"
#include "ops_fstype.h"
#include "ops_super.h"
#include "recovery.h"
@@ -105,6 +104,7 @@ static void init_vfs(struct super_block *sb, unsigned noatime)
sb->s_magic = GFS2_MAGIC;
sb->s_op = &gfs2_super_ops;
sb->s_export_op = &gfs2_export_ops;
+ sb->s_time_gran = 1;
sb->s_maxbytes = MAX_LFS_FILESIZE;
if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME))
@@ -116,7 +116,6 @@ static void init_vfs(struct super_block *sb, unsigned noatime)
static int init_names(struct gfs2_sbd *sdp, int silent)
{
- struct page *page;
char *proto, *table;
int error = 0;
@@ -126,14 +125,9 @@ static int init_names(struct gfs2_sbd *sdp, int silent)
/* Try to autodetect */
if (!proto[0] || !table[0]) {
- struct gfs2_sb *sb;
- page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
- if (!page)
- return -ENOBUFS;
- sb = kmap(page);
- gfs2_sb_in(&sdp->sd_sb, sb);
- kunmap(page);
- __free_page(page);
+ error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+ if (error)
+ return error;
error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
if (error)
@@ -151,6 +145,9 @@ static int init_names(struct gfs2_sbd *sdp, int silent)
snprintf(sdp->sd_proto_name, GFS2_FSNAME_LEN, "%s", proto);
snprintf(sdp->sd_table_name, GFS2_FSNAME_LEN, "%s", table);
+ while ((table = strchr(sdp->sd_table_name, '/')))
+ *table = '_';
+
out:
return error;
}
@@ -236,17 +233,17 @@ fail:
return error;
}
-static struct inode *gfs2_lookup_root(struct super_block *sb,
- struct gfs2_inum_host *inum)
+static inline struct inode *gfs2_lookup_root(struct super_block *sb,
+ u64 no_addr)
{
- return gfs2_inode_lookup(sb, inum, DT_DIR);
+ return gfs2_inode_lookup(sb, DT_DIR, no_addr, 0);
}
static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
{
struct super_block *sb = sdp->sd_vfs;
struct gfs2_holder sb_gh;
- struct gfs2_inum_host *inum;
+ u64 no_addr;
struct inode *inode;
int error = 0;
@@ -289,10 +286,10 @@ static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
sb_set_blocksize(sb, sdp->sd_sb.sb_bsize);
/* Get the root inode */
- inum = &sdp->sd_sb.sb_root_dir;
+ no_addr = sdp->sd_sb.sb_root_dir.no_addr;
if (sb->s_type == &gfs2meta_fs_type)
- inum = &sdp->sd_sb.sb_master_dir;
- inode = gfs2_lookup_root(sb, inum);
+ no_addr = sdp->sd_sb.sb_master_dir.no_addr;
+ inode = gfs2_lookup_root(sb, no_addr);
if (IS_ERR(inode)) {
error = PTR_ERR(inode);
fs_err(sdp, "can't read in root inode: %d\n", error);
@@ -449,7 +446,7 @@ static int init_inodes(struct gfs2_sbd *sdp, int undo)
if (undo)
goto fail_qinode;
- inode = gfs2_lookup_root(sdp->sd_vfs, &sdp->sd_sb.sb_master_dir);
+ inode = gfs2_lookup_root(sdp->sd_vfs, sdp->sd_sb.sb_master_dir.no_addr);
if (IS_ERR(inode)) {
error = PTR_ERR(inode);
fs_err(sdp, "can't read in master directory: %d\n", error);
diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h
index 7cc2c296271..407029b3b2b 100644
--- a/fs/gfs2/ops_fstype.h
+++ b/fs/gfs2/ops_fstype.h
@@ -14,5 +14,6 @@
extern struct file_system_type gfs2_fs_type;
extern struct file_system_type gfs2meta_fs_type;
+extern struct export_operations gfs2_export_ops;
#endif /* __OPS_FSTYPE_DOT_H__ */
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index d85f6e05cb9..911c115b5c6 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -157,7 +157,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
if (error)
goto out_gunlock;
- error = gfs2_dir_search(dir, &dentry->d_name, NULL, NULL);
+ error = gfs2_dir_check(dir, &dentry->d_name, NULL);
switch (error) {
case -ENOENT:
break;
@@ -206,7 +206,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
goto out_gunlock_q;
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
- al->al_rgd->rd_ri.ri_length +
+ al->al_rgd->rd_length +
2 * RES_DINODE + RES_STATFS +
RES_QUOTA, 0);
if (error)
@@ -217,8 +217,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
goto out_ipres;
}
- error = gfs2_dir_add(dir, &dentry->d_name, &ip->i_num,
- IF2DT(inode->i_mode));
+ error = gfs2_dir_add(dir, &dentry->d_name, ip, IF2DT(inode->i_mode));
if (error)
goto out_end_trans;
@@ -275,7 +274,7 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry)
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
- rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+ rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
@@ -420,7 +419,7 @@ static int gfs2_mkdir(struct inode *dir, struct dentry *dentry, int mode)
dent = (struct gfs2_dirent *)((char*)dent + GFS2_DIRENT_SIZE(1));
gfs2_qstr2dirent(&str, dibh->b_size - GFS2_DIRENT_SIZE(1) - sizeof(struct gfs2_dinode), dent);
- gfs2_inum_out(&dip->i_num, &dent->de_inum);
+ gfs2_inum_out(dip, dent);
dent->de_type = cpu_to_be16(DT_DIR);
gfs2_dinode_out(ip, di);
@@ -472,7 +471,7 @@ static int gfs2_rmdir(struct inode *dir, struct dentry *dentry)
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
- rgd = gfs2_blk2rgrpd(sdp, ip->i_num.no_addr);
+ rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr);
gfs2_holder_init(rgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + 2);
error = gfs2_glock_nq_m(3, ghs);
@@ -614,7 +613,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
* this is the case of the target file already existing
* so we unlink before doing the rename
*/
- nrgd = gfs2_blk2rgrpd(sdp, nip->i_num.no_addr);
+ nrgd = gfs2_blk2rgrpd(sdp, nip->i_no_addr);
if (nrgd)
gfs2_holder_init(nrgd->rd_gl, LM_ST_EXCLUSIVE, 0, ghs + num_gh++);
}
@@ -653,7 +652,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
if (error)
goto out_gunlock;
- error = gfs2_dir_search(ndir, &ndentry->d_name, NULL, NULL);
+ error = gfs2_dir_check(ndir, &ndentry->d_name, NULL);
switch (error) {
case -ENOENT:
error = 0;
@@ -712,7 +711,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
goto out_gunlock_q;
error = gfs2_trans_begin(sdp, sdp->sd_max_dirres +
- al->al_rgd->rd_ri.ri_length +
+ al->al_rgd->rd_length +
4 * RES_DINODE + 4 * RES_LEAF +
RES_STATFS + RES_QUOTA + 4, 0);
if (error)
@@ -750,7 +749,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
if (error)
goto out_end_trans;
- error = gfs2_dir_mvino(ip, &name, &ndip->i_num, DT_DIR);
+ error = gfs2_dir_mvino(ip, &name, ndip, DT_DIR);
if (error)
goto out_end_trans;
} else {
@@ -758,7 +757,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
error = gfs2_meta_inode_buffer(ip, &dibh);
if (error)
goto out_end_trans;
- ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+ ip->i_inode.i_ctime = CURRENT_TIME;
gfs2_trans_add_bh(ip->i_gl, dibh, 1);
gfs2_dinode_out(ip, dibh->b_data);
brelse(dibh);
@@ -768,8 +767,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
if (error)
goto out_end_trans;
- error = gfs2_dir_add(ndir, &ndentry->d_name, &ip->i_num,
- IF2DT(ip->i_inode.i_mode));
+ error = gfs2_dir_add(ndir, &ndentry->d_name, ip, IF2DT(ip->i_inode.i_mode));
if (error)
goto out_end_trans;
@@ -905,8 +903,8 @@ static int setattr_size(struct inode *inode, struct iattr *attr)
}
error = gfs2_truncatei(ip, attr->ia_size);
- if (error)
- return error;
+ if (error && (inode->i_size != ip->i_di.di_size))
+ i_size_write(inode, ip->i_di.di_size);
return error;
}
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c
index 485ce3d4992..603d940f115 100644
--- a/fs/gfs2/ops_super.c
+++ b/fs/gfs2/ops_super.c
@@ -326,8 +326,10 @@ static void gfs2_clear_inode(struct inode *inode)
gfs2_glock_schedule_for_reclaim(ip->i_gl);
gfs2_glock_put(ip->i_gl);
ip->i_gl = NULL;
- if (ip->i_iopen_gh.gh_gl)
+ if (ip->i_iopen_gh.gh_gl) {
+ ip->i_iopen_gh.gh_gl->gl_object = NULL;
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
+ }
}
}
@@ -422,13 +424,13 @@ static void gfs2_delete_inode(struct inode *inode)
if (!inode->i_private)
goto out;
- error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB, &gh);
+ error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
if (unlikely(error)) {
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
goto out;
}
- gfs2_glock_dq(&ip->i_iopen_gh);
+ gfs2_glock_dq_wait(&ip->i_iopen_gh);
gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
error = gfs2_glock_nq(&ip->i_iopen_gh);
if (error)
diff --git a/fs/gfs2/ops_vm.c b/fs/gfs2/ops_vm.c
index aa0dbd2aac1..404b7cc9f8c 100644
--- a/fs/gfs2/ops_vm.c
+++ b/fs/gfs2/ops_vm.c
@@ -66,7 +66,7 @@ static int alloc_page_backing(struct gfs2_inode *ip, struct page *page)
if (error)
goto out_gunlock_q;
- error = gfs2_trans_begin(sdp, al->al_rgd->rd_ri.ri_length +
+ error = gfs2_trans_begin(sdp, al->al_rgd->rd_length +
ind_blocks + RES_DINODE +
RES_STATFS + RES_QUOTA, 0);
if (error)
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c186857e48a..6e546ee8f3d 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -66,6 +66,18 @@
#define QUOTA_USER 1
#define QUOTA_GROUP 0
+struct gfs2_quota_host {
+ u64 qu_limit;
+ u64 qu_warn;
+ s64 qu_value;
+};
+
+struct gfs2_quota_change_host {
+ u64 qc_change;
+ u32 qc_flags; /* GFS2_QCF_... */
+ u32 qc_id;
+};
+
static u64 qd2offset(struct gfs2_quota_data *qd)
{
u64 offset;
@@ -561,6 +573,25 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
mutex_unlock(&sdp->sd_quota_mutex);
}
+static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf)
+{
+ const struct gfs2_quota *str = buf;
+
+ qu->qu_limit = be64_to_cpu(str->qu_limit);
+ qu->qu_warn = be64_to_cpu(str->qu_warn);
+ qu->qu_value = be64_to_cpu(str->qu_value);
+}
+
+static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf)
+{
+ struct gfs2_quota *str = buf;
+
+ str->qu_limit = cpu_to_be64(qu->qu_limit);
+ str->qu_warn = cpu_to_be64(qu->qu_warn);
+ str->qu_value = cpu_to_be64(qu->qu_value);
+ memset(&str->qu_reserved, 0, sizeof(str->qu_reserved));
+}
+
/**
* gfs2_adjust_quota
*
@@ -573,12 +604,13 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
struct inode *inode = &ip->i_inode;
struct address_space *mapping = inode->i_mapping;
unsigned long index = loc >> PAGE_CACHE_SHIFT;
- unsigned offset = loc & (PAGE_CACHE_SHIFT - 1);
+ unsigned offset = loc & (PAGE_CACHE_SIZE - 1);
unsigned blocksize, iblock, pos;
struct buffer_head *bh;
struct page *page;
void *kaddr;
- __be64 *ptr;
+ char *ptr;
+ struct gfs2_quota_host qp;
s64 value;
int err = -EIO;
@@ -620,13 +652,17 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
kaddr = kmap_atomic(page, KM_USER0);
ptr = kaddr + offset;
- value = (s64)be64_to_cpu(*ptr) + change;
- *ptr = cpu_to_be64(value);
+ gfs2_quota_in(&qp, ptr);
+ qp.qu_value += change;
+ value = qp.qu_value;
+ gfs2_quota_out(&qp, ptr);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
err = 0;
qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC);
qd->qd_qb.qb_value = cpu_to_be64(value);
+ ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC);
+ ((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value);
unlock:
unlock_page(page);
page_cache_release(page);
@@ -689,7 +725,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
goto out_alloc;
error = gfs2_trans_begin(sdp,
- al->al_rgd->rd_ri.ri_length +
+ al->al_rgd->rd_length +
num_qd * data_blocks +
nalloc * ind_blocks +
RES_DINODE + num_qd +
@@ -709,7 +745,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
offset = qd2offset(qd);
error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync,
(struct gfs2_quota_data *)
- qd->qd_gl->gl_lvb);
+ qd);
if (error)
goto out_end_trans;
@@ -1050,6 +1086,15 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
return error;
}
+static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf)
+{
+ const struct gfs2_quota_change *str = buf;
+
+ qc->qc_change = be64_to_cpu(str->qc_change);
+ qc->qc_flags = be32_to_cpu(str->qc_flags);
+ qc->qc_id = be32_to_cpu(str->qc_id);
+}
+
int gfs2_quota_init(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode);
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 8bc182c7e2e..5ada38c99a2 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -116,6 +116,22 @@ void gfs2_revoke_clean(struct gfs2_sbd *sdp)
}
}
+static int gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf)
+{
+ const struct gfs2_log_header *str = buf;
+
+ if (str->lh_header.mh_magic != cpu_to_be32(GFS2_MAGIC) ||
+ str->lh_header.mh_type != cpu_to_be32(GFS2_METATYPE_LH))
+ return 1;
+
+ lh->lh_sequence = be64_to_cpu(str->lh_sequence);
+ lh->lh_flags = be32_to_cpu(str->lh_flags);
+ lh->lh_tail = be32_to_cpu(str->lh_tail);
+ lh->lh_blkno = be32_to_cpu(str->lh_blkno);
+ lh->lh_hash = be32_to_cpu(str->lh_hash);
+ return 0;
+}
+
/**
* get_log_header - read the log header for a given segment
* @jd: the journal
@@ -147,12 +163,10 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
sizeof(u32));
hash = crc32_le(hash, (unsigned char const *)&nothing, sizeof(nothing));
hash ^= (u32)~0;
- gfs2_log_header_in(&lh, bh->b_data);
+ error = gfs2_log_header_in(&lh, bh->b_data);
brelse(bh);
- if (lh.lh_header.mh_magic != GFS2_MAGIC ||
- lh.lh_header.mh_type != GFS2_METATYPE_LH ||
- lh.lh_blkno != blk || lh.lh_hash != hash)
+ if (error || lh.lh_blkno != blk || lh.lh_hash != hash)
return 1;
*head = lh;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 1727f5012ef..e4e04062515 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
- * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
@@ -28,6 +28,7 @@
#include "ops_file.h"
#include "util.h"
#include "log.h"
+#include "inode.h"
#define BFITNOENT ((u32)~0)
@@ -50,6 +51,9 @@ static const char valid_change[16] = {
1, 0, 0, 0
};
+static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
+ unsigned char old_state, unsigned char new_state);
+
/**
* gfs2_setbit - Set a bit in the bitmaps
* @buffer: the buffer that holds the bitmaps
@@ -204,7 +208,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
struct gfs2_bitmap *bi = NULL;
- u32 length = rgd->rd_ri.ri_length;
+ u32 length = rgd->rd_length;
u32 count[4], tmp;
int buf, x;
@@ -227,7 +231,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
return;
}
- tmp = rgd->rd_ri.ri_data -
+ tmp = rgd->rd_data -
rgd->rd_rg.rg_free -
rgd->rd_rg.rg_dinodes;
if (count[1] + count[2] != tmp) {
@@ -253,10 +257,10 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
}
-static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block)
+static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
{
- u64 first = ri->ri_data0;
- u64 last = first + ri->ri_data;
+ u64 first = rgd->rd_data0;
+ u64 last = first + rgd->rd_data;
return first <= block && block < last;
}
@@ -275,7 +279,7 @@ struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk)
spin_lock(&sdp->sd_rindex_spin);
list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) {
- if (rgrp_contains_block(&rgd->rd_ri, blk)) {
+ if (rgrp_contains_block(rgd, blk)) {
list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
spin_unlock(&sdp->sd_rindex_spin);
return rgd;
@@ -354,6 +358,15 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
mutex_unlock(&sdp->sd_rindex_mutex);
}
+static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd)
+{
+ printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)rgd->rd_addr);
+ printk(KERN_INFO " ri_length = %u\n", rgd->rd_length);
+ printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0);
+ printk(KERN_INFO " ri_data = %u\n", rgd->rd_data);
+ printk(KERN_INFO " ri_bitbytes = %u\n", rgd->rd_bitbytes);
+}
+
/**
* gfs2_compute_bitstructs - Compute the bitmap sizes
* @rgd: The resource group descriptor
@@ -367,7 +380,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
struct gfs2_bitmap *bi;
- u32 length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */
+ u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */
u32 bytes_left, bytes;
int x;
@@ -378,7 +391,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
if (!rgd->rd_bits)
return -ENOMEM;
- bytes_left = rgd->rd_ri.ri_bitbytes;
+ bytes_left = rgd->rd_bitbytes;
for (x = 0; x < length; x++) {
bi = rgd->rd_bits + x;
@@ -399,14 +412,14 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
} else if (x + 1 == length) {
bytes = bytes_left;
bi->bi_offset = sizeof(struct gfs2_meta_header);
- bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
+ bi->bi_start = rgd->rd_bitbytes - bytes_left;
bi->bi_len = bytes;
/* other blocks */
} else {
bytes = sdp->sd_sb.sb_bsize -
sizeof(struct gfs2_meta_header);
bi->bi_offset = sizeof(struct gfs2_meta_header);
- bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left;
+ bi->bi_start = rgd->rd_bitbytes - bytes_left;
bi->bi_len = bytes;
}
@@ -418,9 +431,9 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
return -EIO;
}
bi = rgd->rd_bits + (length - 1);
- if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_ri.ri_data) {
+ if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_data) {
if (gfs2_consist_rgrpd(rgd)) {
- gfs2_rindex_print(&rgd->rd_ri);
+ gfs2_rindex_print(rgd);
fs_err(sdp, "start=%u len=%u offset=%u\n",
bi->bi_start, bi->bi_len, bi->bi_offset);
}
@@ -431,9 +444,104 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd)
}
/**
- * gfs2_ri_update - Pull in a new resource index from the disk
+ * gfs2_ri_total - Total up the file system space, according to the rindex.
+ *
+ */
+u64 gfs2_ri_total(struct gfs2_sbd *sdp)
+{
+ u64 total_data = 0;
+ struct inode *inode = sdp->sd_rindex;
+ struct gfs2_inode *ip = GFS2_I(inode);
+ char buf[sizeof(struct gfs2_rindex)];
+ struct file_ra_state ra_state;
+ int error, rgrps;
+
+ mutex_lock(&sdp->sd_rindex_mutex);
+ file_ra_state_init(&ra_state, inode->i_mapping);
+ for (rgrps = 0;; rgrps++) {
+ loff_t pos = rgrps * sizeof(struct gfs2_rindex);
+
+ if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size)
+ break;
+ error = gfs2_internal_read(ip, &ra_state, buf, &pos,
+ sizeof(struct gfs2_rindex));
+ if (error != sizeof(struct gfs2_rindex))
+ break;
+ total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data);
+ }
+ mutex_unlock(&sdp->sd_rindex_mutex);
+ return total_data;
+}
+
+static void gfs2_rindex_in(struct gfs2_rgrpd *rgd, const void *buf)
+{
+ const struct gfs2_rindex *str = buf;
+
+ rgd->rd_addr = be64_to_cpu(str->ri_addr);
+ rgd->rd_length = be32_to_cpu(str->ri_length);
+ rgd->rd_data0 = be64_to_cpu(str->ri_data0);
+ rgd->rd_data = be32_to_cpu(str->ri_data);
+ rgd->rd_bitbytes = be32_to_cpu(str->ri_bitbytes);
+}
+
+/**
+ * read_rindex_entry - Pull in a new resource index entry from the disk
* @gl: The glock covering the rindex inode
*
+ * Returns: 0 on success, error code otherwise
+ */
+
+static int read_rindex_entry(struct gfs2_inode *ip,
+ struct file_ra_state *ra_state)
+{
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
+ char buf[sizeof(struct gfs2_rindex)];
+ int error;
+ struct gfs2_rgrpd *rgd;
+
+ error = gfs2_internal_read(ip, ra_state, buf, &pos,
+ sizeof(struct gfs2_rindex));
+ if (!error)
+ return 0;
+ if (error != sizeof(struct gfs2_rindex)) {
+ if (error > 0)
+ error = -EIO;
+ return error;
+ }
+
+ rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
+ error = -ENOMEM;
+ if (!rgd)
+ return error;
+
+ mutex_init(&rgd->rd_mutex);
+ lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
+ rgd->rd_sbd = sdp;
+
+ list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
+ list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
+
+ gfs2_rindex_in(rgd, buf);
+ error = compute_bitstructs(rgd);
+ if (error)
+ return error;
+
+ error = gfs2_glock_get(sdp, rgd->rd_addr,
+ &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
+ if (error)
+ return error;
+
+ rgd->rd_gl->gl_object = rgd;
+ rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
+ rgd->rd_flags |= GFS2_RDF_CHECK;
+ return error;
+}
+
+/**
+ * gfs2_ri_update - Pull in a new resource index from the disk
+ * @ip: pointer to the rindex inode
+ *
* Returns: 0 on successful update, error code otherwise
*/
@@ -441,13 +549,11 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct inode *inode = &ip->i_inode;
- struct gfs2_rgrpd *rgd;
- char buf[sizeof(struct gfs2_rindex)];
struct file_ra_state ra_state;
- u64 junk = ip->i_di.di_size;
+ u64 rgrp_count = ip->i_di.di_size;
int error;
- if (do_div(junk, sizeof(struct gfs2_rindex))) {
+ if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) {
gfs2_consist_inode(ip);
return -EIO;
}
@@ -455,50 +561,50 @@ static int gfs2_ri_update(struct gfs2_inode *ip)
clear_rgrpdi(sdp);
file_ra_state_init(&ra_state, inode->i_mapping);
- for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
- loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex);
- error = gfs2_internal_read(ip, &ra_state, buf, &pos,
- sizeof(struct gfs2_rindex));
- if (!error)
- break;
- if (error != sizeof(struct gfs2_rindex)) {
- if (error > 0)
- error = -EIO;
- goto fail;
+ for (sdp->sd_rgrps = 0; sdp->sd_rgrps < rgrp_count; sdp->sd_rgrps++) {
+ error = read_rindex_entry(ip, &ra_state);
+ if (error) {
+ clear_rgrpdi(sdp);
+ return error;
}
+ }
- rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS);
- error = -ENOMEM;
- if (!rgd)
- goto fail;
-
- mutex_init(&rgd->rd_mutex);
- lops_init_le(&rgd->rd_le, &gfs2_rg_lops);
- rgd->rd_sbd = sdp;
-
- list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list);
- list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list);
-
- gfs2_rindex_in(&rgd->rd_ri, buf);
- error = compute_bitstructs(rgd);
- if (error)
- goto fail;
+ sdp->sd_rindex_vn = ip->i_gl->gl_vn;
+ return 0;
+}
- error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr,
- &gfs2_rgrp_glops, CREATE, &rgd->rd_gl);
- if (error)
- goto fail;
+/**
+ * gfs2_ri_update_special - Pull in a new resource index from the disk
+ *
+ * This is a special version that's safe to call from gfs2_inplace_reserve_i.
+ * In this case we know that we don't have any resource groups in memory yet.
+ *
+ * @ip: pointer to the rindex inode
+ *
+ * Returns: 0 on successful update, error code otherwise
+ */
+static int gfs2_ri_update_special(struct gfs2_inode *ip)
+{
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct inode *inode = &ip->i_inode;
+ struct file_ra_state ra_state;
+ int error;
- rgd->rd_gl->gl_object = rgd;
- rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1;
+ file_ra_state_init(&ra_state, inode->i_mapping);
+ for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) {
+ /* Ignore partials */
+ if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) >
+ ip->i_di.di_size)
+ break;
+ error = read_rindex_entry(ip, &ra_state);
+ if (error) {
+ clear_rgrpdi(sdp);
+ return error;
+ }
}
sdp->sd_rindex_vn = ip->i_gl->gl_vn;
return 0;
-
-fail:
- clear_rgrpdi(sdp);
- return error;
}
/**
@@ -543,6 +649,28 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh)
return error;
}
+static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf)
+{
+ const struct gfs2_rgrp *str = buf;
+
+ rg->rg_flags = be32_to_cpu(str->rg_flags);
+ rg->rg_free = be32_to_cpu(str->rg_free);
+ rg->rg_dinodes = be32_to_cpu(str->rg_dinodes);
+ rg->rg_igeneration = be64_to_cpu(str->rg_igeneration);
+}
+
+static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf)
+{
+ struct gfs2_rgrp *str = buf;
+
+ str->rg_flags = cpu_to_be32(rg->rg_flags);
+ str->rg_free = cpu_to_be32(rg->rg_free);
+ str->rg_dinodes = cpu_to_be32(rg->rg_dinodes);
+ str->__pad = cpu_to_be32(0);
+ str->rg_igeneration = cpu_to_be64(rg->rg_igeneration);
+ memset(&str->rg_reserved, 0, sizeof(str->rg_reserved));
+}
+
/**
* gfs2_rgrp_bh_get - Read in a RG's header and bitmaps
* @rgd: the struct gfs2_rgrpd describing the RG to read in
@@ -557,7 +685,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
struct gfs2_glock *gl = rgd->rd_gl;
- unsigned int length = rgd->rd_ri.ri_length;
+ unsigned int length = rgd->rd_length;
struct gfs2_bitmap *bi;
unsigned int x, y;
int error;
@@ -575,7 +703,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
for (x = 0; x < length; x++) {
bi = rgd->rd_bits + x;
- error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh);
+ error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh);
if (error)
goto fail;
}
@@ -637,7 +765,7 @@ void gfs2_rgrp_bh_hold(struct gfs2_rgrpd *rgd)
void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
- int x, length = rgd->rd_ri.ri_length;
+ int x, length = rgd->rd_length;
spin_lock(&sdp->sd_rindex_spin);
gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count);
@@ -660,7 +788,7 @@ void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd)
void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd)
{
struct gfs2_sbd *sdp = rgd->rd_sbd;
- unsigned int length = rgd->rd_ri.ri_length;
+ unsigned int length = rgd->rd_length;
unsigned int x;
for (x = 0; x < length; x++) {
@@ -722,6 +850,38 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
}
/**
+ * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes
+ * @rgd: The rgrp
+ *
+ * Returns: The inode, if one has been found
+ */
+
+static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+{
+ struct inode *inode;
+ u32 goal = 0;
+ u64 no_addr;
+
+ for(;;) {
+ goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED,
+ GFS2_BLKST_UNLINKED);
+ if (goal == 0)
+ return 0;
+ no_addr = goal + rgd->rd_data0;
+ if (no_addr <= *last_unlinked)
+ continue;
+ *last_unlinked = no_addr;
+ inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
+ no_addr, -1);
+ if (!IS_ERR(inode))
+ return inode;
+ }
+
+ rgd->rd_flags &= ~GFS2_RDF_CHECK;
+ return NULL;
+}
+
+/**
* recent_rgrp_first - get first RG from "recent" list
* @sdp: The GFS2 superblock
* @rglast: address of the rgrp used last
@@ -743,7 +903,7 @@ static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp,
goto first;
list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) {
- if (rgd->rd_ri.ri_addr == rglast)
+ if (rgd->rd_addr == rglast)
goto out;
}
@@ -882,8 +1042,9 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd)
* Returns: errno
*/
-static int get_local_rgrp(struct gfs2_inode *ip)
+static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
{
+ struct inode *inode = NULL;
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_rgrpd *rgd, *begin = NULL;
struct gfs2_alloc *al = &ip->i_alloc;
@@ -903,7 +1064,11 @@ static int get_local_rgrp(struct gfs2_inode *ip)
case 0:
if (try_rgrp_fit(rgd, al))
goto out;
+ if (rgd->rd_flags & GFS2_RDF_CHECK)
+ inode = try_rgrp_unlink(rgd, last_unlinked);
gfs2_glock_dq_uninit(&al->al_rgd_gh);
+ if (inode)
+ return inode;
rgd = recent_rgrp_next(rgd, 1);
break;
@@ -912,7 +1077,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
break;
default:
- return error;
+ return ERR_PTR(error);
}
}
@@ -927,7 +1092,11 @@ static int get_local_rgrp(struct gfs2_inode *ip)
case 0:
if (try_rgrp_fit(rgd, al))
goto out;
+ if (rgd->rd_flags & GFS2_RDF_CHECK)
+ inode = try_rgrp_unlink(rgd, last_unlinked);
gfs2_glock_dq_uninit(&al->al_rgd_gh);
+ if (inode)
+ return inode;
break;
case GLR_TRYFAILED:
@@ -935,7 +1104,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
break;
default:
- return error;
+ return ERR_PTR(error);
}
rgd = gfs2_rgrpd_get_next(rgd);
@@ -944,7 +1113,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
if (rgd == begin) {
if (++loops >= 3)
- return -ENOSPC;
+ return ERR_PTR(-ENOSPC);
if (!skipped)
loops++;
flags = 0;
@@ -954,7 +1123,7 @@ static int get_local_rgrp(struct gfs2_inode *ip)
}
out:
- ip->i_last_rg_alloc = rgd->rd_ri.ri_addr;
+ ip->i_last_rg_alloc = rgd->rd_addr;
if (begin) {
recent_rgrp_add(rgd);
@@ -964,7 +1133,7 @@ out:
forward_rgrp_set(sdp, rgd);
}
- return 0;
+ return NULL;
}
/**
@@ -978,19 +1147,33 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
struct gfs2_alloc *al = &ip->i_alloc;
- int error;
+ struct inode *inode;
+ int error = 0;
+ u64 last_unlinked = 0;
if (gfs2_assert_warn(sdp, al->al_requested))
return -EINVAL;
- error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+try_again:
+ /* We need to hold the rindex unless the inode we're using is
+ the rindex itself, in which case it's already held. */
+ if (ip != GFS2_I(sdp->sd_rindex))
+ error = gfs2_rindex_hold(sdp, &al->al_ri_gh);
+ else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */
+ error = gfs2_ri_update_special(ip);
+
if (error)
return error;
- error = get_local_rgrp(ip);
- if (error) {
- gfs2_glock_dq_uninit(&al->al_ri_gh);
- return error;
+ inode = get_local_rgrp(ip, &last_unlinked);
+ if (inode) {
+ if (ip != GFS2_I(sdp->sd_rindex))
+ gfs2_glock_dq_uninit(&al->al_ri_gh);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+ iput(inode);
+ gfs2_log_flush(sdp, NULL);
+ goto try_again;
}
al->al_file = file;
@@ -1019,7 +1202,8 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
al->al_rgd = NULL;
gfs2_glock_dq_uninit(&al->al_rgd_gh);
- gfs2_glock_dq_uninit(&al->al_ri_gh);
+ if (ip != GFS2_I(sdp->sd_rindex))
+ gfs2_glock_dq_uninit(&al->al_ri_gh);
}
/**
@@ -1037,8 +1221,8 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
unsigned int buf;
unsigned char type;
- length = rgd->rd_ri.ri_length;
- rgrp_block = block - rgd->rd_ri.ri_data0;
+ length = rgd->rd_length;
+ rgrp_block = block - rgd->rd_data0;
for (buf = 0; buf < length; buf++) {
bi = rgd->rd_bits + buf;
@@ -1077,10 +1261,10 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block)
*/
static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
- unsigned char old_state, unsigned char new_state)
+ unsigned char old_state, unsigned char new_state)
{
struct gfs2_bitmap *bi = NULL;
- u32 length = rgd->rd_ri.ri_length;
+ u32 length = rgd->rd_length;
u32 blk = 0;
unsigned int buf, x;
@@ -1118,17 +1302,18 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal,
goal = 0;
}
- if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length))
- blk = 0;
+ if (old_state != new_state) {
+ gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT);
- gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
- gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
- bi->bi_len, blk, new_state);
- if (bi->bi_clone)
- gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+ gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
+ gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
bi->bi_len, blk, new_state);
+ if (bi->bi_clone)
+ gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset,
+ bi->bi_len, blk, new_state);
+ }
- return bi->bi_start * GFS2_NBBY + blk;
+ return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk;
}
/**
@@ -1156,9 +1341,9 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
return NULL;
}
- length = rgd->rd_ri.ri_length;
+ length = rgd->rd_length;
- rgrp_blk = bstart - rgd->rd_ri.ri_data0;
+ rgrp_blk = bstart - rgd->rd_data0;
while (blen--) {
for (buf = 0; buf < length; buf++) {
@@ -1202,15 +1387,15 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip)
u32 goal, blk;
u64 block;
- if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_data))
- goal = ip->i_di.di_goal_data - rgd->rd_ri.ri_data0;
+ if (rgrp_contains_block(rgd, ip->i_di.di_goal_data))
+ goal = ip->i_di.di_goal_data - rgd->rd_data0;
else
goal = rgd->rd_last_alloc_data;
blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
rgd->rd_last_alloc_data = blk;
- block = rgd->rd_ri.ri_data0 + blk;
+ block = rgd->rd_data0 + blk;
ip->i_di.di_goal_data = block;
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
@@ -1246,15 +1431,15 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip)
u32 goal, blk;
u64 block;
- if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_meta))
- goal = ip->i_di.di_goal_meta - rgd->rd_ri.ri_data0;
+ if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta))
+ goal = ip->i_di.di_goal_meta - rgd->rd_data0;
else
goal = rgd->rd_last_alloc_meta;
blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED);
rgd->rd_last_alloc_meta = blk;
- block = rgd->rd_ri.ri_data0 + blk;
+ block = rgd->rd_data0 + blk;
ip->i_di.di_goal_meta = block;
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
@@ -1296,7 +1481,7 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
rgd->rd_last_alloc_meta = blk;
- block = rgd->rd_ri.ri_data0 + blk;
+ block = rgd->rd_data0 + blk;
gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free);
rgd->rd_rg.rg_free--;
@@ -1379,7 +1564,7 @@ void gfs2_unlink_di(struct inode *inode)
struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode);
struct gfs2_rgrpd *rgd;
- u64 blkno = ip->i_num.no_addr;
+ u64 blkno = ip->i_no_addr;
rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED);
if (!rgd)
@@ -1414,9 +1599,9 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno)
void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip)
{
- gfs2_free_uninit_di(rgd, ip->i_num.no_addr);
+ gfs2_free_uninit_di(rgd, ip->i_no_addr);
gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid);
- gfs2_meta_wipe(ip, ip->i_num.no_addr, 1);
+ gfs2_meta_wipe(ip, ip->i_no_addr, 1);
}
/**
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index b01e0cfc99b..b4c6adfc6f2 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -65,5 +65,6 @@ void gfs2_rlist_add(struct gfs2_sbd *sdp, struct gfs2_rgrp_list *rlist,
void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state,
int flags);
void gfs2_rlist_free(struct gfs2_rgrp_list *rlist);
+u64 gfs2_ri_total(struct gfs2_sbd *sdp);
#endif /* __RGRP_DOT_H__ */
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 4fdda974dc8..f916b9740c7 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -95,8 +95,8 @@ int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent)
{
unsigned int x;
- if (sb->sb_header.mh_magic != GFS2_MAGIC ||
- sb->sb_header.mh_type != GFS2_METATYPE_SB) {
+ if (sb->sb_magic != GFS2_MAGIC ||
+ sb->sb_type != GFS2_METATYPE_SB) {
if (!silent)
printk(KERN_WARNING "GFS2: not a GFS2 filesystem\n");
return -EINVAL;
@@ -174,10 +174,31 @@ static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error)
return 0;
}
+static void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf)
+{
+ const struct gfs2_sb *str = buf;
+
+ sb->sb_magic = be32_to_cpu(str->sb_header.mh_magic);
+ sb->sb_type = be32_to_cpu(str->sb_header.mh_type);
+ sb->sb_format = be32_to_cpu(str->sb_header.mh_format);
+ sb->sb_fs_format = be32_to_cpu(str->sb_fs_format);
+ sb->sb_multihost_format = be32_to_cpu(str->sb_multihost_format);
+ sb->sb_bsize = be32_to_cpu(str->sb_bsize);
+ sb->sb_bsize_shift = be32_to_cpu(str->sb_bsize_shift);
+ sb->sb_master_dir.no_addr = be64_to_cpu(str->sb_master_dir.no_addr);
+ sb->sb_master_dir.no_formal_ino = be64_to_cpu(str->sb_master_dir.no_formal_ino);
+ sb->sb_root_dir.no_addr = be64_to_cpu(str->sb_root_dir.no_addr);
+ sb->sb_root_dir.no_formal_ino = be64_to_cpu(str->sb_root_dir.no_formal_ino);
+
+ memcpy(sb->sb_lockproto, str->sb_lockproto, GFS2_LOCKNAME_LEN);
+ memcpy(sb->sb_locktable, str->sb_locktable, GFS2_LOCKNAME_LEN);
+}
+
/**
* gfs2_read_super - Read the gfs2 super block from disk
- * @sb: The VFS super block
+ * @sdp: The GFS2 super block
* @sector: The location of the super block
+ * @error: The error code to return
*
* This uses the bio functions to read the super block from disk
* because we want to be 100% sure that we never read cached data.
@@ -189,17 +210,19 @@ static int end_bio_io_page(struct bio *bio, unsigned int bytes_done, int error)
* the master directory (contains pointers to journals etc) and the
* root directory.
*
- * Returns: A page containing the sb or NULL
+ * Returns: 0 on success or error
*/
-struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
+int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector)
{
+ struct super_block *sb = sdp->sd_vfs;
+ struct gfs2_sb *p;
struct page *page;
struct bio *bio;
page = alloc_page(GFP_KERNEL);
if (unlikely(!page))
- return NULL;
+ return -ENOBUFS;
ClearPageUptodate(page);
ClearPageDirty(page);
@@ -208,7 +231,7 @@ struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
bio = bio_alloc(GFP_KERNEL, 1);
if (unlikely(!bio)) {
__free_page(page);
- return NULL;
+ return -ENOBUFS;
}
bio->bi_sector = sector * (sb->s_blocksize >> 9);
@@ -222,9 +245,13 @@ struct page *gfs2_read_super(struct super_block *sb, sector_t sector)
bio_put(bio);
if (!PageUptodate(page)) {
__free_page(page);
- return NULL;
+ return -EIO;
}
- return page;
+ p = kmap(page);
+ gfs2_sb_in(&sdp->sd_sb, p);
+ kunmap(page);
+ __free_page(page);
+ return 0;
}
/**
@@ -241,19 +268,13 @@ int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent)
u32 tmp_blocks;
unsigned int x;
int error;
- struct page *page;
- char *sb;
- page = gfs2_read_super(sdp->sd_vfs, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
- if (!page) {
+ error = gfs2_read_super(sdp, GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift);
+ if (error) {
if (!silent)
fs_err(sdp, "can't read superblock\n");
- return -EIO;
+ return error;
}
- sb = kmap(page);
- gfs2_sb_in(&sdp->sd_sb, sb);
- kunmap(page);
- __free_page(page);
error = gfs2_check_sb(sdp, &sdp->sd_sb, silent);
if (error)
@@ -360,7 +381,7 @@ int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh)
name.len = sprintf(buf, "journal%u", sdp->sd_journals);
name.hash = gfs2_disk_hash(name.name, name.len);
- error = gfs2_dir_search(sdp->sd_jindex, &name, NULL, NULL);
+ error = gfs2_dir_check(sdp->sd_jindex, &name, NULL);
if (error == -ENOENT) {
error = 0;
break;
@@ -593,6 +614,24 @@ int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
return error;
}
+static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
+{
+ const struct gfs2_statfs_change *str = buf;
+
+ sc->sc_total = be64_to_cpu(str->sc_total);
+ sc->sc_free = be64_to_cpu(str->sc_free);
+ sc->sc_dinodes = be64_to_cpu(str->sc_dinodes);
+}
+
+static void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf)
+{
+ struct gfs2_statfs_change *str = buf;
+
+ str->sc_total = cpu_to_be64(sc->sc_total);
+ str->sc_free = cpu_to_be64(sc->sc_free);
+ str->sc_dinodes = cpu_to_be64(sc->sc_dinodes);
+}
+
int gfs2_statfs_init(struct gfs2_sbd *sdp)
{
struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
@@ -772,7 +811,7 @@ static int statfs_slow_fill(struct gfs2_rgrpd *rgd,
struct gfs2_statfs_change_host *sc)
{
gfs2_rgrp_verify(rgd);
- sc->sc_total += rgd->rd_ri.ri_data;
+ sc->sc_total += rgd->rd_data;
sc->sc_free += rgd->rd_rg.rg_free;
sc->sc_dinodes += rgd->rd_rg.rg_dinodes;
return 0;
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h
index e590b2df11d..60a870e430b 100644
--- a/fs/gfs2/super.h
+++ b/fs/gfs2/super.h
@@ -16,7 +16,7 @@ void gfs2_tune_init(struct gfs2_tune *gt);
int gfs2_check_sb(struct gfs2_sbd *sdp, struct gfs2_sb_host *sb, int silent);
int gfs2_read_sb(struct gfs2_sbd *sdp, struct gfs2_glock *gl, int silent);
-struct page *gfs2_read_super(struct super_block *sb, sector_t sector);
+int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector);
static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)
{
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
index 601eaa1b9ed..424a0774eda 100644
--- a/fs/gfs2/util.c
+++ b/fs/gfs2/util.c
@@ -115,8 +115,8 @@ int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide,
"GFS2: fsid=%s: inode = %llu %llu\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n",
sdp->sd_fsname,
- sdp->sd_fsname, (unsigned long long)ip->i_num.no_formal_ino,
- (unsigned long long)ip->i_num.no_addr,
+ sdp->sd_fsname, (unsigned long long)ip->i_no_formal_ino,
+ (unsigned long long)ip->i_no_addr,
sdp->sd_fsname, function, file, line);
return rv;
}
@@ -137,7 +137,7 @@ int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide,
"GFS2: fsid=%s: RG = %llu\n"
"GFS2: fsid=%s: function = %s, file = %s, line = %u\n",
sdp->sd_fsname,
- sdp->sd_fsname, (unsigned long long)rgd->rd_ri.ri_addr,
+ sdp->sd_fsname, (unsigned long long)rgd->rd_addr,
sdp->sd_fsname, function, file, line);
return rv;
}
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 9a934db0bd8..bc835f272a6 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -607,7 +607,7 @@ static const struct file_operations hfs_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.fsync = file_fsync,
.open = hfs_file_open,
.release = hfs_file_release,
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 45dab5d6cc1..409ce5429c9 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -288,7 +288,7 @@ static const struct file_operations hfsplus_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.fsync = file_fsync,
.open = hfsplus_file_open,
.release = hfsplus_file_release,
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 8286491dbf3..c77862032e8 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -390,7 +390,7 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync)
static const struct file_operations hostfs_file_fops = {
.llseek = generic_file_llseek,
.read = do_sync_read,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.write = do_sync_write,
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index b4eafc0f1e5..5b53e5c5d8d 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -129,7 +129,7 @@ const struct file_operations hpfs_file_ops =
.mmap = generic_file_mmap,
.release = hpfs_file_release,
.fsync = hpfs_file_fsync,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations hpfs_file_iops =
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index aa083dd34e9..e6b46b3ac2f 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -736,15 +736,13 @@ static int can_do_hugetlb_shm(void)
can_do_mlock());
}
-struct file *hugetlb_zero_setup(size_t size)
+struct file *hugetlb_file_setup(const char *name, size_t size)
{
int error = -ENOMEM;
struct file *file;
struct inode *inode;
struct dentry *dentry, *root;
struct qstr quick_string;
- char buf[16];
- static atomic_t counter;
if (!hugetlbfs_vfsmount)
return ERR_PTR(-ENOENT);
@@ -756,8 +754,7 @@ struct file *hugetlb_zero_setup(size_t size)
return ERR_PTR(-ENOMEM);
root = hugetlbfs_vfsmount->mnt_root;
- snprintf(buf, 16, "%u", atomic_inc_return(&counter));
- quick_string.name = buf;
+ quick_string.name = name;
quick_string.len = strlen(quick_string.name);
quick_string.hash = 0;
dentry = d_alloc(root, &quick_string);
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 479c1038ed4..8c90cbc903f 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -12,6 +12,7 @@
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/module.h>
+#include <linux/kallsyms.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
@@ -20,6 +21,7 @@ static long do_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
int error = -ENOTTY;
+ void *f;
if (!filp->f_op)
goto out;
@@ -29,10 +31,16 @@ static long do_ioctl(struct file *filp, unsigned int cmd,
if (error == -ENOIOCTLCMD)
error = -EINVAL;
goto out;
- } else if (filp->f_op->ioctl) {
+ } else if ((f = filp->f_op->ioctl)) {
lock_kernel();
- error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
- filp, cmd, arg);
+ if (!filp->f_op->ioctl) {
+ printk("%s: ioctl %p disappeared\n", __FUNCTION__, f);
+ print_symbol("symbol: %s\n", (unsigned long)f);
+ dump_stack();
+ } else {
+ error = filp->f_op->ioctl(filp->f_path.dentry->d_inode,
+ filp, cmd, arg);
+ }
unlock_kernel();
}
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 99871279a1e..c2530197be0 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -47,7 +47,7 @@ const struct file_operations jffs2_file_operations =
.ioctl = jffs2_ioctl,
.mmap = generic_file_readonly_mmap,
.fsync = jffs2_fsync,
- .sendfile = generic_file_sendfile
+ .splice_read = generic_file_splice_read,
};
/* jffs2_file_inode_operations */
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 4884d5edfe6..7b363786c2d 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -210,8 +210,7 @@ static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *
* offset, and the one with the smallest length will come first in the
* ordering.
*
- * Returns 0 if the node was inserted
- * 1 if the node is obsolete (because we can't mark it so yet)
+ * Returns 0 if the node was handled (including marking it obsolete)
* < 0 an if error occurred
*/
static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
@@ -229,9 +228,16 @@ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
check anyway. */
if (!tn->fn->size) {
if (rii->mdata_tn) {
- /* We had a candidate mdata node already */
- dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
- jffs2_kill_tn(c, rii->mdata_tn);
+ if (rii->mdata_tn->version < tn->version) {
+ /* We had a candidate mdata node already */
+ dbg_readinode("kill old mdata with ver %d\n", rii->mdata_tn->version);
+ jffs2_kill_tn(c, rii->mdata_tn);
+ } else {
+ dbg_readinode("kill new mdata with ver %d (older than existing %d\n",
+ tn->version, rii->mdata_tn->version);
+ jffs2_kill_tn(c, tn);
+ return 0;
+ }
}
rii->mdata_tn = tn;
dbg_readinode("keep new mdata with ver %d\n", tn->version);
@@ -565,8 +571,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r
* Helper function for jffs2_get_inode_nodes().
* It is called every time an directory entry node is found.
*
- * Returns: 0 on succes;
- * 1 if the node should be marked obsolete;
+ * Returns: 0 on success;
* negative error code on failure.
*/
static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
@@ -673,8 +678,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r
* Helper function for jffs2_get_inode_nodes().
* It is called every time an inode node is found.
*
- * Returns: 0 on success;
- * 1 if the node should be marked obsolete;
+ * Returns: 0 on success (possibly after marking a bad node obsolete);
* negative error code on failure.
*/
static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref,
@@ -683,7 +687,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
{
struct jffs2_tmp_dnode_info *tn;
uint32_t len, csize;
- int ret = 1;
+ int ret = 0;
uint32_t crc;
/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
@@ -712,8 +716,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
/* Sanity checks */
if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) {
- JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
- jffs2_dbg_dump_node(c, ref_offset(ref));
+ JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref));
+ jffs2_dbg_dump_node(c, ref_offset(ref));
+ jffs2_mark_node_obsolete(c, ref);
goto free_out;
}
@@ -768,6 +773,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) {
JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n",
ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc));
+ jffs2_mark_node_obsolete(c, ref);
goto free_out;
}
@@ -847,7 +853,6 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
* It is called every time an unknown node is found.
*
* Returns: 0 on success;
- * 1 if the node should be marked obsolete;
* negative error code on failure.
*/
static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un)
@@ -1044,7 +1049,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
case JFFS2_NODETYPE_DIRENT:
- if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) {
+ if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent) &&
+ len < sizeof(struct jffs2_raw_dirent)) {
err = read_more(c, ref, sizeof(struct jffs2_raw_dirent), &len, buf);
if (unlikely(err))
goto free_out;
@@ -1058,7 +1064,8 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
case JFFS2_NODETYPE_INODE:
- if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) {
+ if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode) &&
+ len < sizeof(struct jffs2_raw_inode)) {
err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf);
if (unlikely(err))
goto free_out;
@@ -1071,17 +1078,15 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf
break;
default:
- if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node)) {
+ if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_unknown_node) &&
+ len < sizeof(struct jffs2_unknown_node)) {
err = read_more(c, ref, sizeof(struct jffs2_unknown_node), &len, buf);
if (unlikely(err))
goto free_out;
}
err = read_unknown(c, ref, &node->u);
- if (err == 1) {
- jffs2_mark_node_obsolete(c, ref);
- break;
- } else if (unlikely(err))
+ if (unlikely(err))
goto free_out;
}
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index 6488af43bc9..e220d3bd610 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -19,7 +19,7 @@
#include <linux/mount.h>
#include <linux/jffs2.h>
#include <linux/pagemap.h>
-#include <linux/mtd/mtd.h>
+#include <linux/mtd/super.h>
#include <linux/ctype.h>
#include <linux/namei.h>
#include "compr.h"
@@ -75,69 +75,27 @@ static const struct super_operations jffs2_super_operations =
.sync_fs = jffs2_sync_fs,
};
-static int jffs2_sb_compare(struct super_block *sb, void *data)
-{
- struct jffs2_sb_info *p = data;
- struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
-
- /* The superblocks are considered to be equivalent if the underlying MTD
- device is the same one */
- if (c->mtd == p->mtd) {
- D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name));
- return 1;
- } else {
- D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n",
- c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name));
- return 0;
- }
-}
-
-static int jffs2_sb_set(struct super_block *sb, void *data)
-{
- struct jffs2_sb_info *p = data;
-
- /* For persistence of NFS exports etc. we use the same s_dev
- each time we mount the device, don't just use an anonymous
- device */
- sb->s_fs_info = p;
- p->os_priv = sb;
- sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index);
-
- return 0;
-}
-
-static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
- int flags, const char *dev_name,
- void *data, struct mtd_info *mtd,
- struct vfsmount *mnt)
+/*
+ * fill in the superblock
+ */
+static int jffs2_fill_super(struct super_block *sb, void *data, int silent)
{
- struct super_block *sb;
struct jffs2_sb_info *c;
- int ret;
+
+ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd():"
+ " New superblock for device %d (\"%s\")\n",
+ sb->s_mtd->index, sb->s_mtd->name));
c = kzalloc(sizeof(*c), GFP_KERNEL);
if (!c)
return -ENOMEM;
- c->mtd = mtd;
-
- sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c);
-
- if (IS_ERR(sb))
- goto out_error;
-
- if (sb->s_root) {
- /* New mountpoint for JFFS2 which is already mounted */
- D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n",
- mtd->index, mtd->name));
- ret = simple_set_mnt(mnt, sb);
- goto out_put;
- }
- D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n",
- mtd->index, mtd->name));
+ c->mtd = sb->s_mtd;
+ c->os_priv = sb;
+ sb->s_fs_info = c;
- /* Initialize JFFS2 superblock locks, the further initialization will be
- * done later */
+ /* Initialize JFFS2 superblock locks, the further initialization will
+ * be done later */
init_MUTEX(&c->alloc_sem);
init_MUTEX(&c->erase_free_sem);
init_waitqueue_head(&c->erase_wait);
@@ -146,133 +104,20 @@ static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
spin_lock_init(&c->inocache_lock);
sb->s_op = &jffs2_super_operations;
- sb->s_flags = flags | MS_NOATIME;
+ sb->s_flags = sb->s_flags | MS_NOATIME;
sb->s_xattr = jffs2_xattr_handlers;
#ifdef CONFIG_JFFS2_FS_POSIX_ACL
sb->s_flags |= MS_POSIXACL;
#endif
- ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
-
- if (ret) {
- /* Failure case... */
- up_write(&sb->s_umount);
- deactivate_super(sb);
- return ret;
- }
-
- sb->s_flags |= MS_ACTIVE;
- return simple_set_mnt(mnt, sb);
-
-out_error:
- ret = PTR_ERR(sb);
- out_put:
- kfree(c);
- put_mtd_device(mtd);
-
- return ret;
-}
-
-static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
- int flags, const char *dev_name,
- void *data, int mtdnr,
- struct vfsmount *mnt)
-{
- struct mtd_info *mtd;
-
- mtd = get_mtd_device(NULL, mtdnr);
- if (IS_ERR(mtd)) {
- D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr));
- return PTR_ERR(mtd);
- }
-
- return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
+ return jffs2_do_fill_super(sb, data, silent);
}
static int jffs2_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data, struct vfsmount *mnt)
{
- int err;
- struct nameidata nd;
- int mtdnr;
-
- if (!dev_name)
- return -EINVAL;
-
- D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name));
-
- /* The preferred way of mounting in future; especially when
- CONFIG_BLK_DEV is implemented - we specify the underlying
- MTD device by number or by name, so that we don't require
- block device support to be present in the kernel. */
-
- /* FIXME: How to do the root fs this way? */
-
- if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') {
- /* Probably mounting without the blkdev crap */
- if (dev_name[3] == ':') {
- struct mtd_info *mtd;
-
- /* Mount by MTD device name */
- D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4));
- for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) {
- mtd = get_mtd_device(NULL, mtdnr);
- if (!IS_ERR(mtd)) {
- if (!strcmp(mtd->name, dev_name+4))
- return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
- put_mtd_device(mtd);
- }
- }
- printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4);
- } else if (isdigit(dev_name[3])) {
- /* Mount by MTD device number name */
- char *endptr;
-
- mtdnr = simple_strtoul(dev_name+3, &endptr, 0);
- if (!*endptr) {
- /* It was a valid number */
- D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr));
- return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
- }
- }
- }
-
- /* Try the old way - the hack where we allowed users to mount
- /dev/mtdblock$(n) but didn't actually _use_ the blkdev */
-
- err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
-
- D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n",
- err, nd.dentry->d_inode));
-
- if (err)
- return err;
-
- err = -EINVAL;
-
- if (!S_ISBLK(nd.dentry->d_inode->i_mode))
- goto out;
-
- if (nd.mnt->mnt_flags & MNT_NODEV) {
- err = -EACCES;
- goto out;
- }
-
- if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) {
- if (!(flags & MS_SILENT))
- printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n",
- dev_name);
- goto out;
- }
-
- mtdnr = iminor(nd.dentry->d_inode);
- path_release(&nd);
-
- return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
-
-out:
- path_release(&nd);
- return err;
+ return get_sb_mtd(fs_type, flags, dev_name, data, jffs2_fill_super,
+ mnt);
}
static void jffs2_put_super (struct super_block *sb)
@@ -307,8 +152,7 @@ static void jffs2_kill_sb(struct super_block *sb)
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
if (!(sb->s_flags & MS_RDONLY))
jffs2_stop_garbage_collect_thread(c);
- generic_shutdown_super(sb);
- put_mtd_device(c->mtd);
+ kill_mtd_super(sb);
kfree(c);
}
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
index 78fc08893a6..e48665984cb 100644
--- a/fs/jffs2/xattr.c
+++ b/fs/jffs2/xattr.c
@@ -754,6 +754,10 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
list_del(&xd->xindex);
jffs2_free_xattr_datum(xd);
}
+ list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
+ list_del(&xd->xindex);
+ jffs2_free_xattr_datum(xd);
+ }
}
#define XREF_TMPHASH_SIZE (128)
@@ -825,7 +829,7 @@ void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
ref->xd and ref->ic are not valid yet. */
xd = jffs2_find_xattr_datum(c, ref->xid);
ic = jffs2_get_ino_cache(c, ref->ino);
- if (!xd || !ic) {
+ if (!xd || !ic || !ic->nlink) {
dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
ref->ino, ref->xid, ref->xseqno);
ref->xseqno |= XREF_DELETE_MARKER;
diff --git a/fs/jfs/endian24.h b/fs/jfs/endian24.h
index 79494c4f2b1..fa92f7f1d0d 100644
--- a/fs/jfs/endian24.h
+++ b/fs/jfs/endian24.h
@@ -29,7 +29,7 @@
__u32 __x = (x); \
((__u32)( \
((__x & (__u32)0x000000ffUL) << 16) | \
- (__x & (__u32)0x0000ff00UL) | \
+ (__x & (__u32)0x0000ff00UL) | \
((__x & (__u32)0x00ff0000UL) >> 16) )); \
})
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index f7f8eff19b7..87eb93694af 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -108,7 +108,6 @@ const struct file_operations jfs_file_operations = {
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
.fsync = jfs_fsync,
diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
index 9c5d59632aa..887f5759e53 100644
--- a/fs/jfs/jfs_debug.c
+++ b/fs/jfs/jfs_debug.c
@@ -26,34 +26,6 @@
#include "jfs_filsys.h"
#include "jfs_debug.h"
-#ifdef CONFIG_JFS_DEBUG
-void dump_mem(char *label, void *data, int length)
-{
- int i, j;
- int *intptr = data;
- char *charptr = data;
- char buf[10], line[80];
-
- printk("%s: dump of %d bytes of data at 0x%p\n\n", label, length,
- data);
- for (i = 0; i < length; i += 16) {
- line[0] = 0;
- for (j = 0; (j < 4) && (i + j * 4 < length); j++) {
- sprintf(buf, " %08x", intptr[i / 4 + j]);
- strcat(line, buf);
- }
- buf[0] = ' ';
- buf[2] = 0;
- for (j = 0; (j < 16) && (i + j < length); j++) {
- buf[1] =
- isprint(charptr[i + j]) ? charptr[i + j] : '.';
- strcat(line, buf);
- }
- printk("%s\n", line);
- }
-}
-#endif
-
#ifdef PROC_FS_JFS /* see jfs_debug.h */
static struct proc_dir_entry *base;
diff --git a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
index 7378798f0b2..044c1e654cc 100644
--- a/fs/jfs/jfs_debug.h
+++ b/fs/jfs/jfs_debug.h
@@ -62,7 +62,6 @@ extern void jfs_proc_clean(void);
extern int jfsloglevel;
-extern void dump_mem(char *label, void *data, int length);
extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
/* information message: e.g., configuration, major event */
@@ -94,7 +93,6 @@ extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
* ---------
*/
#else /* CONFIG_JFS_DEBUG */
-#define dump_mem(label,data,length) do {} while (0)
#define ASSERT(p) do {} while (0)
#define jfs_info(fmt, arg...) do {} while (0)
#define jfs_debug(fmt, arg...) do {} while (0)
diff --git a/fs/jfs/jfs_dinode.h b/fs/jfs/jfs_dinode.h
index 40b20111383..c387540d342 100644
--- a/fs/jfs/jfs_dinode.h
+++ b/fs/jfs/jfs_dinode.h
@@ -19,23 +19,23 @@
#define _H_JFS_DINODE
/*
- * jfs_dinode.h: on-disk inode manager
+ * jfs_dinode.h: on-disk inode manager
*/
-#define INODESLOTSIZE 128
-#define L2INODESLOTSIZE 7
-#define log2INODESIZE 9 /* log2(bytes per dinode) */
+#define INODESLOTSIZE 128
+#define L2INODESLOTSIZE 7
+#define log2INODESIZE 9 /* log2(bytes per dinode) */
/*
- * on-disk inode : 512 bytes
+ * on-disk inode : 512 bytes
*
* note: align 64-bit fields on 8-byte boundary.
*/
struct dinode {
/*
- * I. base area (128 bytes)
- * ------------------------
+ * I. base area (128 bytes)
+ * ------------------------
*
* define generic/POSIX attributes
*/
@@ -70,16 +70,16 @@ struct dinode {
__le32 di_acltype; /* 4: Type of ACL */
/*
- * Extension Areas.
+ * Extension Areas.
*
- * Historically, the inode was partitioned into 4 128-byte areas,
- * the last 3 being defined as unions which could have multiple
- * uses. The first 96 bytes had been completely unused until
- * an index table was added to the directory. It is now more
- * useful to describe the last 3/4 of the inode as a single
- * union. We would probably be better off redesigning the
- * entire structure from scratch, but we don't want to break
- * commonality with OS/2's JFS at this time.
+ * Historically, the inode was partitioned into 4 128-byte areas,
+ * the last 3 being defined as unions which could have multiple
+ * uses. The first 96 bytes had been completely unused until
+ * an index table was added to the directory. It is now more
+ * useful to describe the last 3/4 of the inode as a single
+ * union. We would probably be better off redesigning the
+ * entire structure from scratch, but we don't want to break
+ * commonality with OS/2's JFS at this time.
*/
union {
struct {
@@ -95,7 +95,7 @@ struct dinode {
} _dir; /* (384) */
#define di_dirtable u._dir._table
#define di_dtroot u._dir._dtroot
-#define di_parent di_dtroot.header.idotdot
+#define di_parent di_dtroot.header.idotdot
#define di_DASD di_dtroot.header.DASD
struct {
@@ -127,14 +127,14 @@ struct dinode {
#define di_inlinedata u._file._u2._special._u
#define di_rdev u._file._u2._special._u._rdev
#define di_fastsymlink u._file._u2._special._u._fastsymlink
-#define di_inlineea u._file._u2._special._inlineea
+#define di_inlineea u._file._u2._special._inlineea
} u;
};
/* extended mode bits (on-disk inode di_mode) */
-#define IFJOURNAL 0x00010000 /* journalled file */
-#define ISPARSE 0x00020000 /* sparse file enabled */
-#define INLINEEA 0x00040000 /* inline EA area free */
+#define IFJOURNAL 0x00010000 /* journalled file */
+#define ISPARSE 0x00020000 /* sparse file enabled */
+#define INLINEEA 0x00040000 /* inline EA area free */
#define ISWAPFILE 0x00800000 /* file open for pager swap space */
/* more extended mode bits: attributes for OS/2 */
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index f3b1ebb2228..e1985066b1c 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -154,12 +154,12 @@ static const s8 budtab[256] = {
* the in-core descriptor is initialized from disk.
*
* PARAMETERS:
- * ipbmap - pointer to in-core inode for the block map.
+ * ipbmap - pointer to in-core inode for the block map.
*
* RETURN VALUES:
- * 0 - success
- * -ENOMEM - insufficient memory
- * -EIO - i/o error
+ * 0 - success
+ * -ENOMEM - insufficient memory
+ * -EIO - i/o error
*/
int dbMount(struct inode *ipbmap)
{
@@ -232,11 +232,11 @@ int dbMount(struct inode *ipbmap)
* the memory for this descriptor is freed.
*
* PARAMETERS:
- * ipbmap - pointer to in-core inode for the block map.
+ * ipbmap - pointer to in-core inode for the block map.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*/
int dbUnmount(struct inode *ipbmap, int mounterror)
{
@@ -320,13 +320,13 @@ int dbSync(struct inode *ipbmap)
* at a time.
*
* PARAMETERS:
- * ip - pointer to in-core inode;
- * blkno - starting block number to be freed.
- * nblocks - number of blocks to be freed.
+ * ip - pointer to in-core inode;
+ * blkno - starting block number to be freed.
+ * nblocks - number of blocks to be freed.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*/
int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
{
@@ -395,23 +395,23 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks)
/*
* NAME: dbUpdatePMap()
*
- * FUNCTION: update the allocation state (free or allocate) of the
+ * FUNCTION: update the allocation state (free or allocate) of the
* specified block range in the persistent block allocation map.
*
* the blocks will be updated in the persistent map one
* dmap at a time.
*
* PARAMETERS:
- * ipbmap - pointer to in-core inode for the block map.
- * free - 'true' if block range is to be freed from the persistent
- * map; 'false' if it is to be allocated.
- * blkno - starting block number of the range.
- * nblocks - number of contiguous blocks in the range.
- * tblk - transaction block;
+ * ipbmap - pointer to in-core inode for the block map.
+ * free - 'true' if block range is to be freed from the persistent
+ * map; 'false' if it is to be allocated.
+ * blkno - starting block number of the range.
+ * nblocks - number of contiguous blocks in the range.
+ * tblk - transaction block;
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*/
int
dbUpdatePMap(struct inode *ipbmap,
@@ -573,7 +573,7 @@ dbUpdatePMap(struct inode *ipbmap,
/*
* NAME: dbNextAG()
*
- * FUNCTION: find the preferred allocation group for new allocations.
+ * FUNCTION: find the preferred allocation group for new allocations.
*
* Within the allocation groups, we maintain a preferred
* allocation group which consists of a group with at least
@@ -589,10 +589,10 @@ dbUpdatePMap(struct inode *ipbmap,
* empty ags around for large allocations.
*
* PARAMETERS:
- * ipbmap - pointer to in-core inode for the block map.
+ * ipbmap - pointer to in-core inode for the block map.
*
* RETURN VALUES:
- * the preferred allocation group number.
+ * the preferred allocation group number.
*/
int dbNextAG(struct inode *ipbmap)
{
@@ -656,7 +656,7 @@ unlock:
/*
* NAME: dbAlloc()
*
- * FUNCTION: attempt to allocate a specified number of contiguous free
+ * FUNCTION: attempt to allocate a specified number of contiguous free
* blocks from the working allocation block map.
*
* the block allocation policy uses hints and a multi-step
@@ -680,16 +680,16 @@ unlock:
* size or requests that specify no hint value.
*
* PARAMETERS:
- * ip - pointer to in-core inode;
- * hint - allocation hint.
- * nblocks - number of contiguous blocks in the range.
- * results - on successful return, set to the starting block number
+ * ip - pointer to in-core inode;
+ * hint - allocation hint.
+ * nblocks - number of contiguous blocks in the range.
+ * results - on successful return, set to the starting block number
* of the newly allocated contiguous range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*/
int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
{
@@ -706,12 +706,6 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
/* assert that nblocks is valid */
assert(nblocks > 0);
-#ifdef _STILL_TO_PORT
- /* DASD limit check F226941 */
- if (OVER_LIMIT(ip, nblocks))
- return -ENOSPC;
-#endif /* _STILL_TO_PORT */
-
/* get the log2 number of blocks to be allocated.
* if the number of blocks is not a log2 multiple,
* it will be rounded up to the next log2 multiple.
@@ -720,7 +714,6 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
bmp = JFS_SBI(ip->i_sb)->bmap;
-//retry: /* serialize w.r.t.extendfs() */
mapSize = bmp->db_mapsize;
/* the hint should be within the map */
@@ -879,17 +872,17 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results)
/*
* NAME: dbAllocExact()
*
- * FUNCTION: try to allocate the requested extent;
+ * FUNCTION: try to allocate the requested extent;
*
* PARAMETERS:
- * ip - pointer to in-core inode;
- * blkno - extent address;
- * nblocks - extent length;
+ * ip - pointer to in-core inode;
+ * blkno - extent address;
+ * nblocks - extent length;
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*/
int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
{
@@ -946,7 +939,7 @@ int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
/*
* NAME: dbReAlloc()
*
- * FUNCTION: attempt to extend a current allocation by a specified
+ * FUNCTION: attempt to extend a current allocation by a specified
* number of blocks.
*
* this routine attempts to satisfy the allocation request
@@ -959,21 +952,21 @@ int dbAllocExact(struct inode *ip, s64 blkno, int nblocks)
* number of blocks required.
*
* PARAMETERS:
- * ip - pointer to in-core inode requiring allocation.
- * blkno - starting block of the current allocation.
- * nblocks - number of contiguous blocks within the current
+ * ip - pointer to in-core inode requiring allocation.
+ * blkno - starting block of the current allocation.
+ * nblocks - number of contiguous blocks within the current
* allocation.
- * addnblocks - number of blocks to add to the allocation.
- * results - on successful return, set to the starting block number
+ * addnblocks - number of blocks to add to the allocation.
+ * results - on successful return, set to the starting block number
* of the existing allocation if the existing allocation
* was extended in place or to a newly allocated contiguous
* range if the existing allocation could not be extended
* in place.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*/
int
dbReAlloc(struct inode *ip,
@@ -1004,7 +997,7 @@ dbReAlloc(struct inode *ip,
/*
* NAME: dbExtend()
*
- * FUNCTION: attempt to extend a current allocation by a specified
+ * FUNCTION: attempt to extend a current allocation by a specified
* number of blocks.
*
* this routine attempts to satisfy the allocation request
@@ -1013,16 +1006,16 @@ dbReAlloc(struct inode *ip,
* immediately following the current allocation.
*
* PARAMETERS:
- * ip - pointer to in-core inode requiring allocation.
- * blkno - starting block of the current allocation.
- * nblocks - number of contiguous blocks within the current
+ * ip - pointer to in-core inode requiring allocation.
+ * blkno - starting block of the current allocation.
+ * nblocks - number of contiguous blocks within the current
* allocation.
- * addnblocks - number of blocks to add to the allocation.
+ * addnblocks - number of blocks to add to the allocation.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*/
static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
{
@@ -1109,19 +1102,19 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks)
/*
* NAME: dbAllocNext()
*
- * FUNCTION: attempt to allocate the blocks of the specified block
+ * FUNCTION: attempt to allocate the blocks of the specified block
* range within a dmap.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap.
- * blkno - starting block number of the range.
- * nblocks - number of contiguous free blocks of the range.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap.
+ * blkno - starting block number of the range.
+ * nblocks - number of contiguous free blocks of the range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) held on entry/exit;
*/
@@ -1233,7 +1226,7 @@ static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno,
/*
* NAME: dbAllocNear()
*
- * FUNCTION: attempt to allocate a number of contiguous free blocks near
+ * FUNCTION: attempt to allocate a number of contiguous free blocks near
* a specified block (hint) within a dmap.
*
* starting with the dmap leaf that covers the hint, we'll
@@ -1242,18 +1235,18 @@ static int dbAllocNext(struct bmap * bmp, struct dmap * dp, s64 blkno,
* the desired free space.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap.
- * blkno - block number to allocate near.
- * nblocks - actual number of contiguous free blocks desired.
- * l2nb - log2 number of contiguous free blocks desired.
- * results - on successful return, set to the starting block number
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap.
+ * blkno - block number to allocate near.
+ * nblocks - actual number of contiguous free blocks desired.
+ * l2nb - log2 number of contiguous free blocks desired.
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) held on entry/exit;
*/
@@ -1316,7 +1309,7 @@ dbAllocNear(struct bmap * bmp,
/*
* NAME: dbAllocAG()
*
- * FUNCTION: attempt to allocate the specified number of contiguous
+ * FUNCTION: attempt to allocate the specified number of contiguous
* free blocks within the specified allocation group.
*
* unless the allocation group size is equal to the number
@@ -1353,17 +1346,17 @@ dbAllocNear(struct bmap * bmp,
* the allocation group.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
+ * bmp - pointer to bmap descriptor
* agno - allocation group number.
- * nblocks - actual number of contiguous free blocks desired.
- * l2nb - log2 number of contiguous free blocks desired.
- * results - on successful return, set to the starting block number
+ * nblocks - actual number of contiguous free blocks desired.
+ * l2nb - log2 number of contiguous free blocks desired.
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* note: IWRITE_LOCK(ipmap) held on entry/exit;
*/
@@ -1546,7 +1539,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
/*
* NAME: dbAllocAny()
*
- * FUNCTION: attempt to allocate the specified number of contiguous
+ * FUNCTION: attempt to allocate the specified number of contiguous
* free blocks anywhere in the file system.
*
* dbAllocAny() attempts to find the sufficient free space by
@@ -1556,16 +1549,16 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
* desired free space is allocated.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * nblocks - actual number of contiguous free blocks desired.
- * l2nb - log2 number of contiguous free blocks desired.
- * results - on successful return, set to the starting block number
+ * bmp - pointer to bmap descriptor
+ * nblocks - actual number of contiguous free blocks desired.
+ * l2nb - log2 number of contiguous free blocks desired.
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -1598,9 +1591,9 @@ static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results)
/*
* NAME: dbFindCtl()
*
- * FUNCTION: starting at a specified dmap control page level and block
+ * FUNCTION: starting at a specified dmap control page level and block
* number, search down the dmap control levels for a range of
- * contiguous free blocks large enough to satisfy an allocation
+ * contiguous free blocks large enough to satisfy an allocation
* request for the specified number of free blocks.
*
* if sufficient contiguous free blocks are found, this routine
@@ -1609,17 +1602,17 @@ static int dbAllocAny(struct bmap * bmp, s64 nblocks, int l2nb, s64 * results)
* is sufficient in size.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * level - starting dmap control page level.
- * l2nb - log2 number of contiguous free blocks desired.
- * *blkno - on entry, starting block number for conducting the search.
+ * bmp - pointer to bmap descriptor
+ * level - starting dmap control page level.
+ * l2nb - log2 number of contiguous free blocks desired.
+ * *blkno - on entry, starting block number for conducting the search.
* on successful return, the first block within a dmap page
* that contains or starts a range of contiguous free blocks.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -1699,7 +1692,7 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
/*
* NAME: dbAllocCtl()
*
- * FUNCTION: attempt to allocate a specified number of contiguous
+ * FUNCTION: attempt to allocate a specified number of contiguous
* blocks starting within a specific dmap.
*
* this routine is called by higher level routines that search
@@ -1726,18 +1719,18 @@ static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno)
* first dmap (i.e. blkno).
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * nblocks - actual number of contiguous free blocks to allocate.
- * l2nb - log2 number of contiguous free blocks to allocate.
- * blkno - starting block number of the dmap to start the allocation
+ * bmp - pointer to bmap descriptor
+ * nblocks - actual number of contiguous free blocks to allocate.
+ * l2nb - log2 number of contiguous free blocks to allocate.
+ * blkno - starting block number of the dmap to start the allocation
* from.
- * results - on successful return, set to the starting block number
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -1870,7 +1863,7 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
/*
* NAME: dbAllocDmapLev()
*
- * FUNCTION: attempt to allocate a specified number of contiguous blocks
+ * FUNCTION: attempt to allocate a specified number of contiguous blocks
* from a specified dmap.
*
* this routine checks if the contiguous blocks are available.
@@ -1878,17 +1871,17 @@ dbAllocCtl(struct bmap * bmp, s64 nblocks, int l2nb, s64 blkno, s64 * results)
* returned.
*
* PARAMETERS:
- * mp - pointer to bmap descriptor
- * dp - pointer to dmap to attempt to allocate blocks from.
- * l2nb - log2 number of contiguous block desired.
- * nblocks - actual number of contiguous block desired.
- * results - on successful return, set to the starting block number
+ * mp - pointer to bmap descriptor
+ * dp - pointer to dmap to attempt to allocate blocks from.
+ * l2nb - log2 number of contiguous block desired.
+ * nblocks - actual number of contiguous block desired.
+ * results - on successful return, set to the starting block number
* of the newly allocated range.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient disk resources
- * -EIO - i/o error
+ * 0 - success
+ * -ENOSPC - insufficient disk resources
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap), e.g., from dbAlloc(), or
* IWRITE_LOCK(ipbmap), e.g., dbAllocCtl(), held on entry/exit;
@@ -1933,7 +1926,7 @@ dbAllocDmapLev(struct bmap * bmp,
/*
* NAME: dbAllocDmap()
*
- * FUNCTION: adjust the disk allocation map to reflect the allocation
+ * FUNCTION: adjust the disk allocation map to reflect the allocation
* of a specified block range within a dmap.
*
* this routine allocates the specified blocks from the dmap
@@ -1946,14 +1939,14 @@ dbAllocDmapLev(struct bmap * bmp,
* covers this dmap.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap to allocate the block range from.
- * blkno - starting block number of the block to be allocated.
- * nblocks - number of blocks to be allocated.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap to allocate the block range from.
+ * blkno - starting block number of the block to be allocated.
+ * nblocks - number of blocks to be allocated.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -1989,7 +1982,7 @@ static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
/*
* NAME: dbFreeDmap()
*
- * FUNCTION: adjust the disk allocation map to reflect the allocation
+ * FUNCTION: adjust the disk allocation map to reflect the allocation
* of a specified block range within a dmap.
*
* this routine frees the specified blocks from the dmap through
@@ -1997,18 +1990,18 @@ static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
* causes the maximum string of free blocks within the dmap to
* change (i.e. the value of the root of the dmap's dmtree), this
* routine will cause this change to be reflected up through the
- * appropriate levels of the dmap control pages by a call to
+ * appropriate levels of the dmap control pages by a call to
* dbAdjCtl() for the L0 dmap control page that covers this dmap.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap to free the block range from.
- * blkno - starting block number of the block to be freed.
- * nblocks - number of blocks to be freed.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap to free the block range from.
+ * blkno - starting block number of the block to be freed.
+ * nblocks - number of blocks to be freed.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -2055,7 +2048,7 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
/*
* NAME: dbAllocBits()
*
- * FUNCTION: allocate a specified block range from a dmap.
+ * FUNCTION: allocate a specified block range from a dmap.
*
* this routine updates the dmap to reflect the working
* state allocation of the specified block range. it directly
@@ -2065,10 +2058,10 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno,
* dmap's dmtree, as a whole, to reflect the allocated range.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap to allocate bits from.
- * blkno - starting block number of the bits to be allocated.
- * nblocks - number of bits to be allocated.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap to allocate bits from.
+ * blkno - starting block number of the bits to be allocated.
+ * nblocks - number of bits to be allocated.
*
* RETURN VALUES: none
*
@@ -2149,7 +2142,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
* the allocated words.
*/
for (; nwords > 0; nwords -= nw) {
- if (leaf[word] < BUDMIN) {
+ if (leaf[word] < BUDMIN) {
jfs_error(bmp->db_ipbmap->i_sb,
"dbAllocBits: leaf page "
"corrupt");
@@ -2202,7 +2195,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
/*
* NAME: dbFreeBits()
*
- * FUNCTION: free a specified block range from a dmap.
+ * FUNCTION: free a specified block range from a dmap.
*
* this routine updates the dmap to reflect the working
* state allocation of the specified block range. it directly
@@ -2212,10 +2205,10 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
* dmtree, as a whole, to reflect the deallocated range.
*
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * dp - pointer to dmap to free bits from.
- * blkno - starting block number of the bits to be freed.
- * nblocks - number of bits to be freed.
+ * bmp - pointer to bmap descriptor
+ * dp - pointer to dmap to free bits from.
+ * blkno - starting block number of the bits to be freed.
+ * nblocks - number of bits to be freed.
*
* RETURN VALUES: 0 for success
*
@@ -2388,19 +2381,19 @@ static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno,
* the new root value and the next dmap control page level to
* be adjusted.
* PARAMETERS:
- * bmp - pointer to bmap descriptor
- * blkno - the first block of a block range within a dmap. it is
+ * bmp - pointer to bmap descriptor
+ * blkno - the first block of a block range within a dmap. it is
* the allocation or deallocation of this block range that
* requires the dmap control page to be adjusted.
- * newval - the new value of the lower level dmap or dmap control
+ * newval - the new value of the lower level dmap or dmap control
* page root.
- * alloc - 'true' if adjustment is due to an allocation.
- * level - current level of dmap control page (i.e. L0, L1, L2) to
+ * alloc - 'true' if adjustment is due to an allocation.
+ * level - current level of dmap control page (i.e. L0, L1, L2) to
* be adjusted.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*
* serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit;
*/
@@ -2544,16 +2537,16 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level)
/*
* NAME: dbSplit()
*
- * FUNCTION: update the leaf of a dmtree with a new value, splitting
+ * FUNCTION: update the leaf of a dmtree with a new value, splitting
* the leaf from the binary buddy system of the dmtree's
* leaves, as required.
*
* PARAMETERS:
- * tp - pointer to the tree containing the leaf.
- * leafno - the number of the leaf to be updated.
- * splitsz - the size the binary buddy system starting at the leaf
+ * tp - pointer to the tree containing the leaf.
+ * leafno - the number of the leaf to be updated.
+ * splitsz - the size the binary buddy system starting at the leaf
* must be split to, specified as the log2 number of blocks.
- * newval - the new value for the leaf.
+ * newval - the new value for the leaf.
*
* RETURN VALUES: none
*
@@ -2600,7 +2593,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
/*
* NAME: dbBackSplit()
*
- * FUNCTION: back split the binary buddy system of dmtree leaves
+ * FUNCTION: back split the binary buddy system of dmtree leaves
* that hold a specified leaf until the specified leaf
* starts its own binary buddy system.
*
@@ -2617,8 +2610,8 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval)
* in which a previous join operation must be backed out.
*
* PARAMETERS:
- * tp - pointer to the tree containing the leaf.
- * leafno - the number of the leaf to be updated.
+ * tp - pointer to the tree containing the leaf.
+ * leafno - the number of the leaf to be updated.
*
* RETURN VALUES: none
*
@@ -2692,14 +2685,14 @@ static int dbBackSplit(dmtree_t * tp, int leafno)
/*
* NAME: dbJoin()
*
- * FUNCTION: update the leaf of a dmtree with a new value, joining
+ * FUNCTION: update the leaf of a dmtree with a new value, joining
* the leaf with other leaves of the dmtree into a multi-leaf
* binary buddy system, as required.
*
* PARAMETERS:
- * tp - pointer to the tree containing the leaf.
- * leafno - the number of the leaf to be updated.
- * newval - the new value for the leaf.
+ * tp - pointer to the tree containing the leaf.
+ * leafno - the number of the leaf to be updated.
+ * newval - the new value for the leaf.
*
* RETURN VALUES: none
*/
@@ -2785,15 +2778,15 @@ static int dbJoin(dmtree_t * tp, int leafno, int newval)
/*
* NAME: dbAdjTree()
*
- * FUNCTION: update a leaf of a dmtree with a new value, adjusting
+ * FUNCTION: update a leaf of a dmtree with a new value, adjusting
* the dmtree, as required, to reflect the new leaf value.
* the combination of any buddies must already be done before
* this is called.
*
* PARAMETERS:
- * tp - pointer to the tree to be adjusted.
- * leafno - the number of the leaf to be updated.
- * newval - the new value for the leaf.
+ * tp - pointer to the tree to be adjusted.
+ * leafno - the number of the leaf to be updated.
+ * newval - the new value for the leaf.
*
* RETURN VALUES: none
*/
@@ -2852,7 +2845,7 @@ static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
/*
* NAME: dbFindLeaf()
*
- * FUNCTION: search a dmtree_t for sufficient free blocks, returning
+ * FUNCTION: search a dmtree_t for sufficient free blocks, returning
* the index of a leaf describing the free blocks if
* sufficient free blocks are found.
*
@@ -2861,15 +2854,15 @@ static void dbAdjTree(dmtree_t * tp, int leafno, int newval)
* free space.
*
* PARAMETERS:
- * tp - pointer to the tree to be searched.
- * l2nb - log2 number of free blocks to search for.
+ * tp - pointer to the tree to be searched.
+ * l2nb - log2 number of free blocks to search for.
* leafidx - return pointer to be set to the index of the leaf
* describing at least l2nb free blocks if sufficient
* free blocks are found.
*
* RETURN VALUES:
- * 0 - success
- * -ENOSPC - insufficient free blocks.
+ * 0 - success
+ * -ENOSPC - insufficient free blocks.
*/
static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
{
@@ -2916,18 +2909,18 @@ static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx)
/*
* NAME: dbFindBits()
*
- * FUNCTION: find a specified number of binary buddy free bits within a
+ * FUNCTION: find a specified number of binary buddy free bits within a
* dmap bitmap word value.
*
* this routine searches the bitmap value for (1 << l2nb) free
* bits at (1 << l2nb) alignments within the value.
*
* PARAMETERS:
- * word - dmap bitmap word value.
- * l2nb - number of free bits specified as a log2 number.
+ * word - dmap bitmap word value.
+ * l2nb - number of free bits specified as a log2 number.
*
* RETURN VALUES:
- * starting bit number of free bits.
+ * starting bit number of free bits.
*/
static int dbFindBits(u32 word, int l2nb)
{
@@ -2963,14 +2956,14 @@ static int dbFindBits(u32 word, int l2nb)
/*
* NAME: dbMaxBud(u8 *cp)
*
- * FUNCTION: determine the largest binary buddy string of free
+ * FUNCTION: determine the largest binary buddy string of free
* bits within 32-bits of the map.
*
* PARAMETERS:
- * cp - pointer to the 32-bit value.
+ * cp - pointer to the 32-bit value.
*
* RETURN VALUES:
- * largest binary buddy of free bits within a dmap word.
+ * largest binary buddy of free bits within a dmap word.
*/
static int dbMaxBud(u8 * cp)
{
@@ -3000,14 +2993,14 @@ static int dbMaxBud(u8 * cp)
/*
* NAME: cnttz(uint word)
*
- * FUNCTION: determine the number of trailing zeros within a 32-bit
+ * FUNCTION: determine the number of trailing zeros within a 32-bit
* value.
*
* PARAMETERS:
- * value - 32-bit value to be examined.
+ * value - 32-bit value to be examined.
*
* RETURN VALUES:
- * count of trailing zeros
+ * count of trailing zeros
*/
static int cnttz(u32 word)
{
@@ -3025,14 +3018,14 @@ static int cnttz(u32 word)
/*
* NAME: cntlz(u32 value)
*
- * FUNCTION: determine the number of leading zeros within a 32-bit
+ * FUNCTION: determine the number of leading zeros within a 32-bit
* value.
*
* PARAMETERS:
- * value - 32-bit value to be examined.
+ * value - 32-bit value to be examined.
*
* RETURN VALUES:
- * count of leading zeros
+ * count of leading zeros
*/
static int cntlz(u32 value)
{
@@ -3050,14 +3043,14 @@ static int cntlz(u32 value)
* NAME: blkstol2(s64 nb)
*
* FUNCTION: convert a block count to its log2 value. if the block
- * count is not a l2 multiple, it is rounded up to the next
+ * count is not a l2 multiple, it is rounded up to the next
* larger l2 multiple.
*
* PARAMETERS:
- * nb - number of blocks
+ * nb - number of blocks
*
* RETURN VALUES:
- * log2 number of blocks
+ * log2 number of blocks
*/
static int blkstol2(s64 nb)
{
@@ -3099,13 +3092,13 @@ static int blkstol2(s64 nb)
* at a time.
*
* PARAMETERS:
- * ip - pointer to in-core inode;
- * blkno - starting block number to be freed.
- * nblocks - number of blocks to be freed.
+ * ip - pointer to in-core inode;
+ * blkno - starting block number to be freed.
+ * nblocks - number of blocks to be freed.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error
+ * 0 - success
+ * -EIO - i/o error
*/
int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks)
{
@@ -3278,10 +3271,10 @@ static int dbAllocDmapBU(struct bmap * bmp, struct dmap * dp, s64 blkno,
* L2
* |
* L1---------------------------------L1
- * | |
- * L0---------L0---------L0 L0---------L0---------L0
- * | | | | | |
- * d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,.,dm;
+ * | |
+ * L0---------L0---------L0 L0---------L0---------L0
+ * | | | | | |
+ * d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,...,dn d0,.,dm;
* L2L1L0d0,...,dnL0d0,...,dnL0d0,...,dnL1L0d0,...,dnL0d0,...,dnL0d0,..dm
*
* <---old---><----------------------------extend----------------------->
@@ -3307,7 +3300,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
(long long) blkno, (long long) nblocks, (long long) newsize);
/*
- * initialize bmap control page.
+ * initialize bmap control page.
*
* all the data in bmap control page should exclude
* the mkfs hidden dmap page.
@@ -3330,7 +3323,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
bmp->db_numag += ((u32) newsize % (u32) bmp->db_agsize) ? 1 : 0;
/*
- * reconfigure db_agfree[]
+ * reconfigure db_agfree[]
* from old AG configuration to new AG configuration;
*
* coalesce contiguous k (newAGSize/oldAGSize) AGs;
@@ -3362,7 +3355,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
bmp->db_maxag = bmp->db_maxag / k;
/*
- * extend bmap
+ * extend bmap
*
* update bit maps and corresponding level control pages;
* global control page db_nfree, db_agfree[agno], db_maxfreebud;
@@ -3410,7 +3403,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
/* compute start L0 */
j = 0;
l1leaf = l1dcp->stree + CTLLEAFIND;
- p += nbperpage; /* 1st L0 of L1.k */
+ p += nbperpage; /* 1st L0 of L1.k */
}
/*
@@ -3548,7 +3541,7 @@ errout:
return -EIO;
/*
- * finalize bmap control page
+ * finalize bmap control page
*/
finalize:
@@ -3567,7 +3560,7 @@ void dbFinalizeBmap(struct inode *ipbmap)
int i, n;
/*
- * finalize bmap control page
+ * finalize bmap control page
*/
//finalize:
/*
@@ -3953,8 +3946,8 @@ static int dbGetL2AGSize(s64 nblocks)
* convert number of map pages to the zero origin top dmapctl level
*/
#define BMAPPGTOLEV(npages) \
- (((npages) <= 3 + MAXL0PAGES) ? 0 \
- : ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
+ (((npages) <= 3 + MAXL0PAGES) ? 0 : \
+ ((npages) <= 2 + MAXL1PAGES) ? 1 : 2)
s64 dbMapFileSizeToMapSize(struct inode * ipbmap)
{
@@ -3981,8 +3974,8 @@ s64 dbMapFileSizeToMapSize(struct inode * ipbmap)
factor =
(i == 2) ? MAXL1PAGES : ((i == 1) ? MAXL0PAGES : 1);
complete = (u32) npages / factor;
- ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL
- : ((i == 1) ? LPERCTL : 1));
+ ndmaps += complete * ((i == 2) ? LPERCTL * LPERCTL :
+ ((i == 1) ? LPERCTL : 1));
/* pages in last/incomplete child */
npages = (u32) npages % factor;
diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h
index 45ea454c74b..11e6d471b36 100644
--- a/fs/jfs/jfs_dmap.h
+++ b/fs/jfs/jfs_dmap.h
@@ -83,7 +83,7 @@ static __inline signed char TREEMAX(signed char *cp)
* - 1 is added to account for the control page of the map.
*/
#define BLKTODMAP(b,s) \
- ((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
+ ((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s))
/*
* convert disk block number to the logical block number of the LEVEL 0
@@ -98,7 +98,7 @@ static __inline signed char TREEMAX(signed char *cp)
* - 1 is added to account for the control page of the map.
*/
#define BLKTOL0(b,s) \
- (((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
+ (((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s))
/*
* convert disk block number to the logical block number of the LEVEL 1
@@ -120,7 +120,7 @@ static __inline signed char TREEMAX(signed char *cp)
* at the specified level which describes the disk block.
*/
#define BLKTOCTL(b,s,l) \
- (((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
+ (((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s)))
/*
* convert aggregate map size to the zero origin dmapctl level of the
@@ -145,27 +145,27 @@ static __inline signed char TREEMAX(signed char *cp)
* dmaptree must be consistent with dmapctl.
*/
struct dmaptree {
- __le32 nleafs; /* 4: number of tree leafs */
- __le32 l2nleafs; /* 4: l2 number of tree leafs */
- __le32 leafidx; /* 4: index of first tree leaf */
- __le32 height; /* 4: height of the tree */
+ __le32 nleafs; /* 4: number of tree leafs */
+ __le32 l2nleafs; /* 4: l2 number of tree leafs */
+ __le32 leafidx; /* 4: index of first tree leaf */
+ __le32 height; /* 4: height of the tree */
s8 budmin; /* 1: min l2 tree leaf value to combine */
- s8 stree[TREESIZE]; /* TREESIZE: tree */
- u8 pad[2]; /* 2: pad to word boundary */
-}; /* - 360 - */
+ s8 stree[TREESIZE]; /* TREESIZE: tree */
+ u8 pad[2]; /* 2: pad to word boundary */
+}; /* - 360 - */
/*
* dmap page per 8K blocks bitmap
*/
struct dmap {
- __le32 nblocks; /* 4: num blks covered by this dmap */
- __le32 nfree; /* 4: num of free blks in this dmap */
- __le64 start; /* 8: starting blkno for this dmap */
- struct dmaptree tree; /* 360: dmap tree */
- u8 pad[1672]; /* 1672: pad to 2048 bytes */
- __le32 wmap[LPERDMAP]; /* 1024: bits of the working map */
- __le32 pmap[LPERDMAP]; /* 1024: bits of the persistent map */
-}; /* - 4096 - */
+ __le32 nblocks; /* 4: num blks covered by this dmap */
+ __le32 nfree; /* 4: num of free blks in this dmap */
+ __le64 start; /* 8: starting blkno for this dmap */
+ struct dmaptree tree; /* 360: dmap tree */
+ u8 pad[1672]; /* 1672: pad to 2048 bytes */
+ __le32 wmap[LPERDMAP]; /* 1024: bits of the working map */
+ __le32 pmap[LPERDMAP]; /* 1024: bits of the persistent map */
+}; /* - 4096 - */
/*
* disk map control page per level.
@@ -173,14 +173,14 @@ struct dmap {
* dmapctl must be consistent with dmaptree.
*/
struct dmapctl {
- __le32 nleafs; /* 4: number of tree leafs */
- __le32 l2nleafs; /* 4: l2 number of tree leafs */
- __le32 leafidx; /* 4: index of the first tree leaf */
- __le32 height; /* 4: height of tree */
- s8 budmin; /* 1: minimum l2 tree leaf value */
- s8 stree[CTLTREESIZE]; /* CTLTREESIZE: dmapctl tree */
- u8 pad[2714]; /* 2714: pad to 4096 */
-}; /* - 4096 - */
+ __le32 nleafs; /* 4: number of tree leafs */
+ __le32 l2nleafs; /* 4: l2 number of tree leafs */
+ __le32 leafidx; /* 4: index of the first tree leaf */
+ __le32 height; /* 4: height of tree */
+ s8 budmin; /* 1: minimum l2 tree leaf value */
+ s8 stree[CTLTREESIZE]; /* CTLTREESIZE: dmapctl tree */
+ u8 pad[2714]; /* 2714: pad to 4096 */
+}; /* - 4096 - */
/*
* common definition for dmaptree within dmap and dmapctl
@@ -202,41 +202,41 @@ typedef union dmtree {
* on-disk aggregate disk allocation map descriptor.
*/
struct dbmap_disk {
- __le64 dn_mapsize; /* 8: number of blocks in aggregate */
- __le64 dn_nfree; /* 8: num free blks in aggregate map */
- __le32 dn_l2nbperpage; /* 4: number of blks per page */
- __le32 dn_numag; /* 4: total number of ags */
- __le32 dn_maxlevel; /* 4: number of active ags */
- __le32 dn_maxag; /* 4: max active alloc group number */
- __le32 dn_agpref; /* 4: preferred alloc group (hint) */
- __le32 dn_aglevel; /* 4: dmapctl level holding the AG */
- __le32 dn_agheigth; /* 4: height in dmapctl of the AG */
- __le32 dn_agwidth; /* 4: width in dmapctl of the AG */
- __le32 dn_agstart; /* 4: start tree index at AG height */
- __le32 dn_agl2size; /* 4: l2 num of blks per alloc group */
- __le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count */
- __le64 dn_agsize; /* 8: num of blks per alloc group */
- s8 dn_maxfreebud; /* 1: max free buddy system */
- u8 pad[3007]; /* 3007: pad to 4096 */
-}; /* - 4096 - */
+ __le64 dn_mapsize; /* 8: number of blocks in aggregate */
+ __le64 dn_nfree; /* 8: num free blks in aggregate map */
+ __le32 dn_l2nbperpage; /* 4: number of blks per page */
+ __le32 dn_numag; /* 4: total number of ags */
+ __le32 dn_maxlevel; /* 4: number of active ags */
+ __le32 dn_maxag; /* 4: max active alloc group number */
+ __le32 dn_agpref; /* 4: preferred alloc group (hint) */
+ __le32 dn_aglevel; /* 4: dmapctl level holding the AG */
+ __le32 dn_agheigth; /* 4: height in dmapctl of the AG */
+ __le32 dn_agwidth; /* 4: width in dmapctl of the AG */
+ __le32 dn_agstart; /* 4: start tree index at AG height */
+ __le32 dn_agl2size; /* 4: l2 num of blks per alloc group */
+ __le64 dn_agfree[MAXAG];/* 8*MAXAG: per AG free count */
+ __le64 dn_agsize; /* 8: num of blks per alloc group */
+ s8 dn_maxfreebud; /* 1: max free buddy system */
+ u8 pad[3007]; /* 3007: pad to 4096 */
+}; /* - 4096 - */
struct dbmap {
- s64 dn_mapsize; /* number of blocks in aggregate */
- s64 dn_nfree; /* num free blks in aggregate map */
- int dn_l2nbperpage; /* number of blks per page */
- int dn_numag; /* total number of ags */
- int dn_maxlevel; /* number of active ags */
- int dn_maxag; /* max active alloc group number */
- int dn_agpref; /* preferred alloc group (hint) */
- int dn_aglevel; /* dmapctl level holding the AG */
- int dn_agheigth; /* height in dmapctl of the AG */
- int dn_agwidth; /* width in dmapctl of the AG */
- int dn_agstart; /* start tree index at AG height */
- int dn_agl2size; /* l2 num of blks per alloc group */
- s64 dn_agfree[MAXAG]; /* per AG free count */
- s64 dn_agsize; /* num of blks per alloc group */
- signed char dn_maxfreebud; /* max free buddy system */
-}; /* - 4096 - */
+ s64 dn_mapsize; /* number of blocks in aggregate */
+ s64 dn_nfree; /* num free blks in aggregate map */
+ int dn_l2nbperpage; /* number of blks per page */
+ int dn_numag; /* total number of ags */
+ int dn_maxlevel; /* number of active ags */
+ int dn_maxag; /* max active alloc group number */
+ int dn_agpref; /* preferred alloc group (hint) */
+ int dn_aglevel; /* dmapctl level holding the AG */
+ int dn_agheigth; /* height in dmapctl of the AG */
+ int dn_agwidth; /* width in dmapctl of the AG */
+ int dn_agstart; /* start tree index at AG height */
+ int dn_agl2size; /* l2 num of blks per alloc group */
+ s64 dn_agfree[MAXAG]; /* per AG free count */
+ s64 dn_agsize; /* num of blks per alloc group */
+ signed char dn_maxfreebud; /* max free buddy system */
+}; /* - 4096 - */
/*
* in-memory aggregate disk allocation map descriptor.
*/
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 6d62f322289..c14ba3cfa81 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -315,8 +315,8 @@ static inline void lock_index(tid_t tid, struct inode *ip, struct metapage * mp,
lv = &llck->lv[llck->index];
/*
- * Linelock slot size is twice the size of directory table
- * slot size. 512 entries per page.
+ * Linelock slot size is twice the size of directory table
+ * slot size. 512 entries per page.
*/
lv->offset = ((index - 2) & 511) >> 1;
lv->length = 1;
@@ -615,7 +615,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
btstack->nsplit = 1;
/*
- * search down tree from root:
+ * search down tree from root:
*
* between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
* internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -659,7 +659,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
}
if (cmp == 0) {
/*
- * search hit
+ * search hit
*/
/* search hit - leaf page:
* return the entry found
@@ -723,7 +723,7 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
}
/*
- * search miss
+ * search miss
*
* base is the smallest index with key (Kj) greater than
* search key (K) and may be zero or (maxindex + 1) index.
@@ -834,7 +834,7 @@ int dtInsert(tid_t tid, struct inode *ip,
struct lv *lv;
/*
- * retrieve search result
+ * retrieve search result
*
* dtSearch() returns (leaf page pinned, index at which to insert).
* n.b. dtSearch() may return index of (maxindex + 1) of
@@ -843,7 +843,7 @@ int dtInsert(tid_t tid, struct inode *ip,
DT_GETSEARCH(ip, btstack->top, bn, mp, p, index);
/*
- * insert entry for new key
+ * insert entry for new key
*/
if (DO_INDEX(ip)) {
if (JFS_IP(ip)->next_index == DIREND) {
@@ -860,9 +860,9 @@ int dtInsert(tid_t tid, struct inode *ip,
data.leaf.ino = *fsn;
/*
- * leaf page does not have enough room for new entry:
+ * leaf page does not have enough room for new entry:
*
- * extend/split the leaf page;
+ * extend/split the leaf page;
*
* dtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -877,9 +877,9 @@ int dtInsert(tid_t tid, struct inode *ip,
}
/*
- * leaf page does have enough room for new entry:
+ * leaf page does have enough room for new entry:
*
- * insert the new data entry into the leaf page;
+ * insert the new data entry into the leaf page;
*/
BT_MARK_DIRTY(mp, ip);
/*
@@ -967,13 +967,13 @@ static int dtSplitUp(tid_t tid,
}
/*
- * split leaf page
+ * split leaf page
*
* The split routines insert the new entry, and
* acquire txLock as appropriate.
*/
/*
- * split root leaf page:
+ * split root leaf page:
*/
if (sp->header.flag & BT_ROOT) {
/*
@@ -1012,7 +1012,7 @@ static int dtSplitUp(tid_t tid,
}
/*
- * extend first leaf page
+ * extend first leaf page
*
* extend the 1st extent if less than buffer page size
* (dtExtendPage() reurns leaf page unpinned)
@@ -1068,7 +1068,7 @@ static int dtSplitUp(tid_t tid,
}
/*
- * split leaf page <sp> into <sp> and a new right page <rp>.
+ * split leaf page <sp> into <sp> and a new right page <rp>.
*
* return <rp> pinned and its extent descriptor <rpxd>
*/
@@ -1433,7 +1433,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
rp->header.freecnt = rp->header.maxslot - fsi;
/*
- * sequential append at tail: append without split
+ * sequential append at tail: append without split
*
* If splitting the last page on a level because of appending
* a entry to it (skip is maxentry), it's likely that the access is
@@ -1467,7 +1467,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
}
/*
- * non-sequential insert (at possibly middle page)
+ * non-sequential insert (at possibly middle page)
*/
/*
@@ -1508,7 +1508,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
left = 0;
/*
- * compute fill factor for split pages
+ * compute fill factor for split pages
*
* <nxt> traces the next entry to move to rp
* <off> traces the next entry to stay in sp
@@ -1551,7 +1551,7 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
/* <nxt> poins to the 1st entry to move */
/*
- * move entries to right page
+ * move entries to right page
*
* dtMoveEntry() initializes rp and reserves entry for insertion
*
@@ -1677,7 +1677,7 @@ static int dtExtendPage(tid_t tid,
return (rc);
/*
- * extend the extent
+ * extend the extent
*/
pxdlist = split->pxdlist;
pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1722,7 +1722,7 @@ static int dtExtendPage(tid_t tid,
}
/*
- * extend the page
+ * extend the page
*/
sp->header.self = *pxd;
@@ -1739,9 +1739,6 @@ static int dtExtendPage(tid_t tid,
/* update buffer extent descriptor of extended page */
xlen = lengthPXD(pxd);
xsize = xlen << JFS_SBI(sb)->l2bsize;
-#ifdef _STILL_TO_PORT
- bmSetXD(smp, xaddr, xsize);
-#endif /* _STILL_TO_PORT */
/*
* copy old stbl to new stbl at start of extended area
@@ -1836,7 +1833,7 @@ static int dtExtendPage(tid_t tid,
}
/*
- * update parent entry on the parent/root page
+ * update parent entry on the parent/root page
*/
/*
* acquire a transaction lock on the parent/root page
@@ -1904,7 +1901,7 @@ static int dtSplitRoot(tid_t tid,
sp = &JFS_IP(ip)->i_dtroot;
/*
- * allocate/initialize a single (right) child page
+ * allocate/initialize a single (right) child page
*
* N.B. at first split, a one (or two) block to fit new entry
* is allocated; at subsequent split, a full page is allocated;
@@ -1943,7 +1940,7 @@ static int dtSplitRoot(tid_t tid,
rp->header.prev = 0;
/*
- * move in-line root page into new right page extent
+ * move in-line root page into new right page extent
*/
/* linelock header + copied entries + new stbl (1st slot) in new page */
ASSERT(dtlck->index == 0);
@@ -2016,7 +2013,7 @@ static int dtSplitRoot(tid_t tid,
dtInsertEntry(rp, split->index, split->key, split->data, &dtlck);
/*
- * reset parent/root page
+ * reset parent/root page
*
* set the 1st entry offset to 0, which force the left-most key
* at any level of the tree to be less than any search key.
@@ -2102,7 +2099,7 @@ int dtDelete(tid_t tid,
dtpage_t *np;
/*
- * search for the entry to delete:
+ * search for the entry to delete:
*
* dtSearch() returns (leaf page pinned, index at which to delete).
*/
@@ -2253,7 +2250,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
int i;
/*
- * keep the root leaf page which has become empty
+ * keep the root leaf page which has become empty
*/
if (BT_IS_ROOT(fmp)) {
/*
@@ -2269,7 +2266,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
}
/*
- * free the non-root leaf page
+ * free the non-root leaf page
*/
/*
* acquire a transaction lock on the page
@@ -2299,7 +2296,7 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
discard_metapage(fmp);
/*
- * propagate page deletion up the directory tree
+ * propagate page deletion up the directory tree
*
* If the delete from the parent page makes it empty,
* continue all the way up the tree.
@@ -2440,10 +2437,10 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
#ifdef _NOTYET
/*
- * NAME: dtRelocate()
+ * NAME: dtRelocate()
*
- * FUNCTION: relocate dtpage (internal or leaf) of directory;
- * This function is mainly used by defragfs utility.
+ * FUNCTION: relocate dtpage (internal or leaf) of directory;
+ * This function is mainly used by defragfs utility.
*/
int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
s64 nxaddr)
@@ -2471,8 +2468,8 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
xlen);
/*
- * 1. get the internal parent dtpage covering
- * router entry for the tartget page to be relocated;
+ * 1. get the internal parent dtpage covering
+ * router entry for the tartget page to be relocated;
*/
rc = dtSearchNode(ip, lmxaddr, opxd, &btstack);
if (rc)
@@ -2483,7 +2480,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
jfs_info("dtRelocate: parent router entry validated.");
/*
- * 2. relocate the target dtpage
+ * 2. relocate the target dtpage
*/
/* read in the target page from src extent */
DT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
@@ -2581,9 +2578,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
/* update the buffer extent descriptor of the dtpage */
xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
-#ifdef _STILL_TO_PORT
- bmSetXD(mp, nxaddr, xsize);
-#endif /* _STILL_TO_PORT */
+
/* unpin the relocated page */
DT_PUTPAGE(mp);
jfs_info("dtRelocate: target dtpage relocated.");
@@ -2594,7 +2589,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
*/
/*
- * 3. acquire maplock for the source extent to be freed;
+ * 3. acquire maplock for the source extent to be freed;
*/
/* for dtpage relocation, write a LOG_NOREDOPAGE record
* for the source dtpage (logredo() will init NoRedoPage
@@ -2609,7 +2604,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
pxdlock->index = 1;
/*
- * 4. update the parent router entry for relocation;
+ * 4. update the parent router entry for relocation;
*
* acquire tlck for the parent entry covering the target dtpage;
* write LOG_REDOPAGE to apply after image only;
@@ -2637,7 +2632,7 @@ int dtRelocate(tid_t tid, struct inode *ip, s64 lmxaddr, pxd_t * opxd,
* NAME: dtSearchNode()
*
* FUNCTION: Search for an dtpage containing a specified address
- * This function is mainly used by defragfs utility.
+ * This function is mainly used by defragfs utility.
*
* NOTE: Search result on stack, the found page is pinned at exit.
* The result page must be an internal dtpage.
@@ -2660,7 +2655,7 @@ static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
BT_CLR(btstack); /* reset stack */
/*
- * descend tree to the level with specified leftmost page
+ * descend tree to the level with specified leftmost page
*
* by convention, root bn = 0.
*/
@@ -2699,7 +2694,7 @@ static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
}
/*
- * search each page at the current levevl
+ * search each page at the current levevl
*/
loop:
stbl = DT_GETSTBL(p);
@@ -3044,9 +3039,9 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (DO_INDEX(ip)) {
/*
* persistent index is stored in directory entries.
- * Special cases: 0 = .
- * 1 = ..
- * -1 = End of directory
+ * Special cases: 0 = .
+ * 1 = ..
+ * -1 = End of directory
*/
do_index = 1;
@@ -3128,10 +3123,10 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/*
* Legacy filesystem - OS/2 & Linux JFS < 0.3.6
*
- * pn = index = 0: First entry "."
- * pn = 0; index = 1: Second entry ".."
- * pn > 0: Real entries, pn=1 -> leftmost page
- * pn = index = -1: No more entries
+ * pn = index = 0: First entry "."
+ * pn = 0; index = 1: Second entry ".."
+ * pn > 0: Real entries, pn=1 -> leftmost page
+ * pn = index = -1: No more entries
*/
dtpos = filp->f_pos;
if (dtpos == 0) {
@@ -3351,7 +3346,7 @@ static int dtReadFirst(struct inode *ip, struct btstack * btstack)
BT_CLR(btstack); /* reset stack */
/*
- * descend leftmost path of the tree
+ * descend leftmost path of the tree
*
* by convention, root bn = 0.
*/
@@ -4531,7 +4526,7 @@ int dtModify(tid_t tid, struct inode *ip,
struct ldtentry *entry;
/*
- * search for the entry to modify:
+ * search for the entry to modify:
*
* dtSearch() returns (leaf page pinned, index at which to modify).
*/
diff --git a/fs/jfs/jfs_dtree.h b/fs/jfs/jfs_dtree.h
index af8513f7864..8561c6ecece 100644
--- a/fs/jfs/jfs_dtree.h
+++ b/fs/jfs/jfs_dtree.h
@@ -35,7 +35,7 @@ typedef union {
/*
- * entry segment/slot
+ * entry segment/slot
*
* an entry consists of type dependent head/only segment/slot and
* additional segments/slots linked vi next field;
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index a35bdca6a80..7ae1e3281de 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -34,8 +34,8 @@ static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *);
#endif
static s64 extRoundDown(s64 nb);
-#define DPD(a) (printk("(a): %d\n",(a)))
-#define DPC(a) (printk("(a): %c\n",(a)))
+#define DPD(a) (printk("(a): %d\n",(a)))
+#define DPC(a) (printk("(a): %c\n",(a)))
#define DPL1(a) \
{ \
if ((a) >> 32) \
@@ -51,19 +51,19 @@ static s64 extRoundDown(s64 nb);
printk("(a): %x\n",(a) << 32); \
}
-#define DPD1(a) (printk("(a): %d ",(a)))
-#define DPX(a) (printk("(a): %08x\n",(a)))
-#define DPX1(a) (printk("(a): %08x ",(a)))
-#define DPS(a) (printk("%s\n",(a)))
-#define DPE(a) (printk("\nENTERING: %s\n",(a)))
-#define DPE1(a) (printk("\nENTERING: %s",(a)))
-#define DPS1(a) (printk(" %s ",(a)))
+#define DPD1(a) (printk("(a): %d ",(a)))
+#define DPX(a) (printk("(a): %08x\n",(a)))
+#define DPX1(a) (printk("(a): %08x ",(a)))
+#define DPS(a) (printk("%s\n",(a)))
+#define DPE(a) (printk("\nENTERING: %s\n",(a)))
+#define DPE1(a) (printk("\nENTERING: %s",(a)))
+#define DPS1(a) (printk(" %s ",(a)))
/*
* NAME: extAlloc()
*
- * FUNCTION: allocate an extent for a specified page range within a
+ * FUNCTION: allocate an extent for a specified page range within a
* file.
*
* PARAMETERS:
@@ -78,9 +78,9 @@ static s64 extRoundDown(s64 nb);
* should be marked as allocated but not recorded.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
int
extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
@@ -192,9 +192,9 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
#ifdef _NOTYET
/*
- * NAME: extRealloc()
+ * NAME: extRealloc()
*
- * FUNCTION: extend the allocation of a file extent containing a
+ * FUNCTION: extend the allocation of a file extent containing a
* partial back last page.
*
* PARAMETERS:
@@ -207,9 +207,9 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)
* should be marked as allocated but not recorded.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, bool abnr)
{
@@ -345,9 +345,9 @@ exit:
/*
- * NAME: extHint()
+ * NAME: extHint()
*
- * FUNCTION: produce an extent allocation hint for a file offset.
+ * FUNCTION: produce an extent allocation hint for a file offset.
*
* PARAMETERS:
* ip - the inode of the file.
@@ -356,8 +356,8 @@ exit:
* the hint.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
+ * 0 - success
+ * -EIO - i/o error.
*/
int extHint(struct inode *ip, s64 offset, xad_t * xp)
{
@@ -387,7 +387,7 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp)
lxdl.nlxd = 1;
lxdl.lxd = &lxd;
LXDoffset(&lxd, prev)
- LXDlength(&lxd, nbperpage);
+ LXDlength(&lxd, nbperpage);
xadl.maxnxad = 1;
xadl.nxad = 0;
@@ -397,11 +397,11 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp)
if ((rc = xtLookupList(ip, &lxdl, &xadl, 0)))
return (rc);
- /* check if not extent exists for the previous page.
+ /* check if no extent exists for the previous page.
* this is possible for sparse files.
*/
if (xadl.nxad == 0) {
-// assert(ISSPARSE(ip));
+// assert(ISSPARSE(ip));
return (0);
}
@@ -410,28 +410,28 @@ int extHint(struct inode *ip, s64 offset, xad_t * xp)
*/
xp->flag &= XAD_NOTRECORDED;
- if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
+ if(xadl.nxad != 1 || lengthXAD(xp) != nbperpage) {
jfs_error(ip->i_sb, "extHint: corrupt xtree");
return -EIO;
- }
+ }
return (0);
}
/*
- * NAME: extRecord()
+ * NAME: extRecord()
*
- * FUNCTION: change a page with a file from not recorded to recorded.
+ * FUNCTION: change a page with a file from not recorded to recorded.
*
* PARAMETERS:
* ip - inode of the file.
* cp - cbuf of the file page.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
int extRecord(struct inode *ip, xad_t * xp)
{
@@ -451,9 +451,9 @@ int extRecord(struct inode *ip, xad_t * xp)
#ifdef _NOTYET
/*
- * NAME: extFill()
+ * NAME: extFill()
*
- * FUNCTION: allocate disk space for a file page that represents
+ * FUNCTION: allocate disk space for a file page that represents
* a file hole.
*
* PARAMETERS:
@@ -461,16 +461,16 @@ int extRecord(struct inode *ip, xad_t * xp)
* cp - cbuf of the file page represent the hole.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
int extFill(struct inode *ip, xad_t * xp)
{
int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
s64 blkno = offsetXAD(xp) >> ip->i_blkbits;
-// assert(ISSPARSE(ip));
+// assert(ISSPARSE(ip));
/* initialize the extent allocation hint */
XADaddress(xp, 0);
@@ -489,7 +489,7 @@ int extFill(struct inode *ip, xad_t * xp)
/*
* NAME: extBalloc()
*
- * FUNCTION: allocate disk blocks to form an extent.
+ * FUNCTION: allocate disk blocks to form an extent.
*
* initially, we will try to allocate disk blocks for the
* requested size (nblocks). if this fails (nblocks
@@ -513,9 +513,9 @@ int extFill(struct inode *ip, xad_t * xp)
* allocated block range.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
static int
extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
@@ -580,7 +580,7 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
/*
* NAME: extBrealloc()
*
- * FUNCTION: attempt to extend an extent's allocation.
+ * FUNCTION: attempt to extend an extent's allocation.
*
* Initially, we will try to extend the extent's allocation
* in place. If this fails, we'll try to move the extent
@@ -597,8 +597,8 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
*
* PARAMETERS:
* ip - the inode of the file.
- * blkno - starting block number of the extents current allocation.
- * nblks - number of blocks within the extents current allocation.
+ * blkno - starting block number of the extents current allocation.
+ * nblks - number of blocks within the extents current allocation.
* newnblks - pointer to a s64 value. on entry, this value is the
* the new desired extent size (number of blocks). on
* successful exit, this value is set to the extent's actual
@@ -606,9 +606,9 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno)
* newblkno - the starting block number of the extents new allocation.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOSPC - insufficient disk resources.
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOSPC - insufficient disk resources.
*/
static int
extBrealloc(struct inode *ip,
@@ -634,16 +634,16 @@ extBrealloc(struct inode *ip,
/*
- * NAME: extRoundDown()
+ * NAME: extRoundDown()
*
- * FUNCTION: round down a specified number of blocks to the next
+ * FUNCTION: round down a specified number of blocks to the next
* smallest power of 2 number.
*
* PARAMETERS:
* nb - the inode of the file.
*
* RETURN VALUES:
- * next smallest power of 2 number.
+ * next smallest power of 2 number.
*/
static s64 extRoundDown(s64 nb)
{
diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h
index 38f70ac03be..b3f5463fbe5 100644
--- a/fs/jfs/jfs_filsys.h
+++ b/fs/jfs/jfs_filsys.h
@@ -34,9 +34,9 @@
#define JFS_UNICODE 0x00000001 /* unicode name */
/* mount time flags for error handling */
-#define JFS_ERR_REMOUNT_RO 0x00000002 /* remount read-only */
-#define JFS_ERR_CONTINUE 0x00000004 /* continue */
-#define JFS_ERR_PANIC 0x00000008 /* panic */
+#define JFS_ERR_REMOUNT_RO 0x00000002 /* remount read-only */
+#define JFS_ERR_CONTINUE 0x00000004 /* continue */
+#define JFS_ERR_PANIC 0x00000008 /* panic */
/* Quota support */
#define JFS_USRQUOTA 0x00000010
@@ -83,7 +83,6 @@
/* case-insensitive name/directory support */
#define JFS_AIX 0x80000000 /* AIX support */
-/* POSIX name/directory support - Never implemented*/
/*
* buffer cache configuration
@@ -113,10 +112,10 @@
#define IDATASIZE 256 /* inode inline data size */
#define IXATTRSIZE 128 /* inode inline extended attribute size */
-#define XTPAGE_SIZE 4096
-#define log2_PAGESIZE 12
+#define XTPAGE_SIZE 4096
+#define log2_PAGESIZE 12
-#define IAG_SIZE 4096
+#define IAG_SIZE 4096
#define IAG_EXTENT_SIZE 4096
#define INOSPERIAG 4096 /* number of disk inodes per iag */
#define L2INOSPERIAG 12 /* l2 number of disk inodes per iag */
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index c6530227cda..3870ba8b908 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -93,21 +93,21 @@ static int copy_from_dinode(struct dinode *, struct inode *);
static void copy_to_dinode(struct dinode *, struct inode *);
/*
- * NAME: diMount()
+ * NAME: diMount()
*
- * FUNCTION: initialize the incore inode map control structures for
+ * FUNCTION: initialize the incore inode map control structures for
* a fileset or aggregate init time.
*
- * the inode map's control structure (dinomap) is
- * brought in from disk and placed in virtual memory.
+ * the inode map's control structure (dinomap) is
+ * brought in from disk and placed in virtual memory.
*
* PARAMETERS:
- * ipimap - pointer to inode map inode for the aggregate or fileset.
+ * ipimap - pointer to inode map inode for the aggregate or fileset.
*
* RETURN VALUES:
- * 0 - success
- * -ENOMEM - insufficient free virtual memory.
- * -EIO - i/o error.
+ * 0 - success
+ * -ENOMEM - insufficient free virtual memory.
+ * -EIO - i/o error.
*/
int diMount(struct inode *ipimap)
{
@@ -180,18 +180,18 @@ int diMount(struct inode *ipimap)
/*
- * NAME: diUnmount()
+ * NAME: diUnmount()
*
- * FUNCTION: write to disk the incore inode map control structures for
+ * FUNCTION: write to disk the incore inode map control structures for
* a fileset or aggregate at unmount time.
*
* PARAMETERS:
- * ipimap - pointer to inode map inode for the aggregate or fileset.
+ * ipimap - pointer to inode map inode for the aggregate or fileset.
*
* RETURN VALUES:
- * 0 - success
- * -ENOMEM - insufficient free virtual memory.
- * -EIO - i/o error.
+ * 0 - success
+ * -ENOMEM - insufficient free virtual memory.
+ * -EIO - i/o error.
*/
int diUnmount(struct inode *ipimap, int mounterror)
{
@@ -274,9 +274,9 @@ int diSync(struct inode *ipimap)
/*
- * NAME: diRead()
+ * NAME: diRead()
*
- * FUNCTION: initialize an incore inode from disk.
+ * FUNCTION: initialize an incore inode from disk.
*
* on entry, the specifed incore inode should itself
* specify the disk inode number corresponding to the
@@ -285,7 +285,7 @@ int diSync(struct inode *ipimap)
* this routine handles incore inode initialization for
* both "special" and "regular" inodes. special inodes
* are those required early in the mount process and
- * require special handling since much of the file system
+ * require special handling since much of the file system
* is not yet initialized. these "special" inodes are
* identified by a NULL inode map inode pointer and are
* actually initialized by a call to diReadSpecial().
@@ -298,12 +298,12 @@ int diSync(struct inode *ipimap)
* incore inode.
*
* PARAMETERS:
- * ip - pointer to incore inode to be initialized from disk.
+ * ip - pointer to incore inode to be initialized from disk.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
- * -ENOMEM - insufficient memory
+ * 0 - success
+ * -EIO - i/o error.
+ * -ENOMEM - insufficient memory
*
*/
int diRead(struct inode *ip)
@@ -410,26 +410,26 @@ int diRead(struct inode *ip)
/*
- * NAME: diReadSpecial()
+ * NAME: diReadSpecial()
*
- * FUNCTION: initialize a 'special' inode from disk.
+ * FUNCTION: initialize a 'special' inode from disk.
*
* this routines handles aggregate level inodes. The
* inode cache cannot differentiate between the
* aggregate inodes and the filesystem inodes, so we
* handle these here. We don't actually use the aggregate
- * inode map, since these inodes are at a fixed location
+ * inode map, since these inodes are at a fixed location
* and in some cases the aggregate inode map isn't initialized
* yet.
*
* PARAMETERS:
- * sb - filesystem superblock
+ * sb - filesystem superblock
* inum - aggregate inode number
* secondary - 1 if secondary aggregate inode table
*
* RETURN VALUES:
- * new inode - success
- * NULL - i/o error.
+ * new inode - success
+ * NULL - i/o error.
*/
struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
{
@@ -502,12 +502,12 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
}
/*
- * NAME: diWriteSpecial()
+ * NAME: diWriteSpecial()
*
- * FUNCTION: Write the special inode to disk
+ * FUNCTION: Write the special inode to disk
*
* PARAMETERS:
- * ip - special inode
+ * ip - special inode
* secondary - 1 if secondary aggregate inode table
*
* RETURN VALUES: none
@@ -554,9 +554,9 @@ void diWriteSpecial(struct inode *ip, int secondary)
}
/*
- * NAME: diFreeSpecial()
+ * NAME: diFreeSpecial()
*
- * FUNCTION: Free allocated space for special inode
+ * FUNCTION: Free allocated space for special inode
*/
void diFreeSpecial(struct inode *ip)
{
@@ -572,9 +572,9 @@ void diFreeSpecial(struct inode *ip)
/*
- * NAME: diWrite()
+ * NAME: diWrite()
*
- * FUNCTION: write the on-disk inode portion of the in-memory inode
+ * FUNCTION: write the on-disk inode portion of the in-memory inode
* to its corresponding on-disk inode.
*
* on entry, the specifed incore inode should itself
@@ -589,11 +589,11 @@ void diFreeSpecial(struct inode *ip)
*
* PARAMETERS:
* tid - transacation id
- * ip - pointer to incore inode to be written to the inode extent.
+ * ip - pointer to incore inode to be written to the inode extent.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
+ * 0 - success
+ * -EIO - i/o error.
*/
int diWrite(tid_t tid, struct inode *ip)
{
@@ -730,7 +730,7 @@ int diWrite(tid_t tid, struct inode *ip)
ilinelock = (struct linelock *) & tlck->lock;
/*
- * regular file: 16 byte (XAD slot) granularity
+ * regular file: 16 byte (XAD slot) granularity
*/
if (type & tlckXTREE) {
xtpage_t *p, *xp;
@@ -755,7 +755,7 @@ int diWrite(tid_t tid, struct inode *ip)
xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
}
/*
- * directory: 32 byte (directory entry slot) granularity
+ * directory: 32 byte (directory entry slot) granularity
*/
else if (type & tlckDTREE) {
dtpage_t *p, *xp;
@@ -800,9 +800,8 @@ int diWrite(tid_t tid, struct inode *ip)
}
/*
- * lock/copy inode base: 128 byte slot granularity
+ * lock/copy inode base: 128 byte slot granularity
*/
-// baseDinode:
lv = & dilinelock->lv[dilinelock->index];
lv->offset = dioffset >> L2INODESLOTSIZE;
copy_to_dinode(dp, ip);
@@ -813,17 +812,6 @@ int diWrite(tid_t tid, struct inode *ip)
lv->length = 1;
dilinelock->index++;
-#ifdef _JFS_FASTDASD
- /*
- * We aren't logging changes to the DASD used in directory inodes,
- * but we need to write them to disk. If we don't unmount cleanly,
- * mount will recalculate the DASD used.
- */
- if (S_ISDIR(ip->i_mode)
- && (ip->i_ipmnt->i_mntflag & JFS_DASD_ENABLED))
- memcpy(&dp->di_DASD, &ip->i_DASD, sizeof(struct dasd));
-#endif /* _JFS_FASTDASD */
-
/* release the buffer holding the updated on-disk inode.
* the buffer will be later written by commit processing.
*/
@@ -834,9 +822,9 @@ int diWrite(tid_t tid, struct inode *ip)
/*
- * NAME: diFree(ip)
+ * NAME: diFree(ip)
*
- * FUNCTION: free a specified inode from the inode working map
+ * FUNCTION: free a specified inode from the inode working map
* for a fileset or aggregate.
*
* if the inode to be freed represents the first (only)
@@ -865,11 +853,11 @@ int diWrite(tid_t tid, struct inode *ip)
* any updates and are held until all updates are complete.
*
* PARAMETERS:
- * ip - inode to be freed.
+ * ip - inode to be freed.
*
* RETURN VALUES:
- * 0 - success
- * -EIO - i/o error.
+ * 0 - success
+ * -EIO - i/o error.
*/
int diFree(struct inode *ip)
{
@@ -902,7 +890,8 @@ int diFree(struct inode *ip)
* the map.
*/
if (iagno >= imap->im_nextiag) {
- dump_mem("imap", imap, 32);
+ print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ imap, 32, 0);
jfs_error(ip->i_sb,
"diFree: inum = %d, iagno = %d, nextiag = %d",
(uint) inum, iagno, imap->im_nextiag);
@@ -964,8 +953,8 @@ int diFree(struct inode *ip)
return -EIO;
}
/*
- * inode extent still has some inodes or below low water mark:
- * keep the inode extent;
+ * inode extent still has some inodes or below low water mark:
+ * keep the inode extent;
*/
if (bitmap ||
imap->im_agctl[agno].numfree < 96 ||
@@ -1047,12 +1036,12 @@ int diFree(struct inode *ip)
/*
- * inode extent has become free and above low water mark:
- * free the inode extent;
+ * inode extent has become free and above low water mark:
+ * free the inode extent;
*/
/*
- * prepare to update iag list(s) (careful update step 1)
+ * prepare to update iag list(s) (careful update step 1)
*/
amp = bmp = cmp = dmp = NULL;
fwd = back = -1;
@@ -1152,7 +1141,7 @@ int diFree(struct inode *ip)
invalidate_pxd_metapages(ip, freepxd);
/*
- * update iag list(s) (careful update step 2)
+ * update iag list(s) (careful update step 2)
*/
/* add the iag to the ag extent free list if this is the
* first free extent for the iag.
@@ -1338,20 +1327,20 @@ diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
/*
- * NAME: diAlloc(pip,dir,ip)
+ * NAME: diAlloc(pip,dir,ip)
*
- * FUNCTION: allocate a disk inode from the inode working map
+ * FUNCTION: allocate a disk inode from the inode working map
* for a fileset or aggregate.
*
* PARAMETERS:
- * pip - pointer to incore inode for the parent inode.
- * dir - 'true' if the new disk inode is for a directory.
- * ip - pointer to a new inode
+ * pip - pointer to incore inode for the parent inode.
+ * dir - 'true' if the new disk inode is for a directory.
+ * ip - pointer to a new inode
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
int diAlloc(struct inode *pip, bool dir, struct inode *ip)
{
@@ -1433,7 +1422,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
addext = (imap->im_agctl[agno].numfree < 32 && iagp->nfreeexts);
/*
- * try to allocate from the IAG
+ * try to allocate from the IAG
*/
/* check if the inode may be allocated from the iag
* (i.e. the inode has free inodes or new extent can be added).
@@ -1633,9 +1622,9 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
/*
- * NAME: diAllocAG(imap,agno,dir,ip)
+ * NAME: diAllocAG(imap,agno,dir,ip)
*
- * FUNCTION: allocate a disk inode from the allocation group.
+ * FUNCTION: allocate a disk inode from the allocation group.
*
* this routine first determines if a new extent of free
* inodes should be added for the allocation group, with
@@ -1649,17 +1638,17 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
* PRE CONDITION: Already have the AG lock for this AG.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * agno - allocation group to allocate from.
- * dir - 'true' if the new disk inode is for a directory.
- * ip - pointer to the new inode to be filled in on successful return
+ * imap - pointer to inode map control structure.
+ * agno - allocation group to allocate from.
+ * dir - 'true' if the new disk inode is for a directory.
+ * ip - pointer to the new inode to be filled in on successful return
* with the disk inode number allocated, its extent address
* and the start of the ag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int
diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
@@ -1709,9 +1698,9 @@ diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
/*
- * NAME: diAllocAny(imap,agno,dir,iap)
+ * NAME: diAllocAny(imap,agno,dir,iap)
*
- * FUNCTION: allocate a disk inode from any other allocation group.
+ * FUNCTION: allocate a disk inode from any other allocation group.
*
* this routine is called when an allocation attempt within
* the primary allocation group has failed. if attempts to
@@ -1719,17 +1708,17 @@ diAllocAG(struct inomap * imap, int agno, bool dir, struct inode *ip)
* specified primary group.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * agno - primary allocation group (to avoid).
- * dir - 'true' if the new disk inode is for a directory.
- * ip - pointer to a new inode to be filled in on successful return
+ * imap - pointer to inode map control structure.
+ * agno - primary allocation group (to avoid).
+ * dir - 'true' if the new disk inode is for a directory.
+ * ip - pointer to a new inode to be filled in on successful return
* with the disk inode number allocated, its extent address
* and the start of the ag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int
diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
@@ -1772,9 +1761,9 @@ diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
/*
- * NAME: diAllocIno(imap,agno,ip)
+ * NAME: diAllocIno(imap,agno,ip)
*
- * FUNCTION: allocate a disk inode from the allocation group's free
+ * FUNCTION: allocate a disk inode from the allocation group's free
* inode list, returning an error if this free list is
* empty (i.e. no iags on the list).
*
@@ -1785,16 +1774,16 @@ diAllocAny(struct inomap * imap, int agno, bool dir, struct inode *ip)
* PRE CONDITION: Already have AG lock for this AG.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * agno - allocation group.
- * ip - pointer to new inode to be filled in on successful return
+ * imap - pointer to inode map control structure.
+ * agno - allocation group.
+ * ip - pointer to new inode to be filled in on successful return
* with the disk inode number allocated, its extent address
* and the start of the ag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
{
@@ -1890,7 +1879,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
/*
- * NAME: diAllocExt(imap,agno,ip)
+ * NAME: diAllocExt(imap,agno,ip)
*
* FUNCTION: add a new extent of free inodes to an iag, allocating
* an inode from this extent to satisfy the current allocation
@@ -1910,16 +1899,16 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
* for the purpose of satisfying this request.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * agno - allocation group number.
- * ip - pointer to new inode to be filled in on successful return
+ * imap - pointer to inode map control structure.
+ * agno - allocation group number.
+ * ip - pointer to new inode to be filled in on successful return
* with the disk inode number allocated, its extent address
* and the start of the ag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
{
@@ -2010,7 +1999,7 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
/*
- * NAME: diAllocBit(imap,iagp,ino)
+ * NAME: diAllocBit(imap,iagp,ino)
*
* FUNCTION: allocate a backed inode from an iag.
*
@@ -2030,14 +2019,14 @@ static int diAllocExt(struct inomap * imap, int agno, struct inode *ip)
* this AG. Must have read lock on imap inode.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * iagp - pointer to iag.
- * ino - inode number to be allocated within the iag.
+ * imap - pointer to inode map control structure.
+ * iagp - pointer to iag.
+ * ino - inode number to be allocated within the iag.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
{
@@ -2144,11 +2133,11 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
/*
- * NAME: diNewExt(imap,iagp,extno)
+ * NAME: diNewExt(imap,iagp,extno)
*
- * FUNCTION: initialize a new extent of inodes for an iag, allocating
- * the first inode of the extent for use for the current
- * allocation request.
+ * FUNCTION: initialize a new extent of inodes for an iag, allocating
+ * the first inode of the extent for use for the current
+ * allocation request.
*
* disk resources are allocated for the new extent of inodes
* and the inodes themselves are initialized to reflect their
@@ -2177,14 +2166,14 @@ static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino)
* this AG. Must have read lock on imap inode.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * iagp - pointer to iag.
- * extno - extent number.
+ * imap - pointer to inode map control structure.
+ * iagp - pointer to iag.
+ * extno - extent number.
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*/
static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
{
@@ -2430,7 +2419,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
/*
- * NAME: diNewIAG(imap,iagnop,agno)
+ * NAME: diNewIAG(imap,iagnop,agno)
*
* FUNCTION: allocate a new iag for an allocation group.
*
@@ -2443,16 +2432,16 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
* and returned to satisfy the request.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * iagnop - pointer to an iag number set with the number of the
+ * imap - pointer to inode map control structure.
+ * iagnop - pointer to an iag number set with the number of the
* newly allocated iag upon successful return.
- * agno - allocation group number.
+ * agno - allocation group number.
* bpp - Buffer pointer to be filled in with new IAG's buffer
*
* RETURN VALUES:
- * 0 - success.
- * -ENOSPC - insufficient disk resources.
- * -EIO - i/o error.
+ * 0 - success.
+ * -ENOSPC - insufficient disk resources.
+ * -EIO - i/o error.
*
* serialization:
* AG lock held on entry/exit;
@@ -2461,7 +2450,7 @@ static int diNewExt(struct inomap * imap, struct iag * iagp, int extno)
*
* note: new iag transaction:
* . synchronously write iag;
- * . write log of xtree and inode of imap;
+ * . write log of xtree and inode of imap;
* . commit;
* . synchronous write of xtree (right to left, bottom to top);
* . at start of logredo(): init in-memory imap with one additional iag page;
@@ -2481,9 +2470,6 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
s64 xaddr = 0;
s64 blkno;
tid_t tid;
-#ifdef _STILL_TO_PORT
- xad_t xad;
-#endif /* _STILL_TO_PORT */
struct inode *iplist[1];
/* pick up pointers to the inode map and mount inodes */
@@ -2674,15 +2660,15 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
}
/*
- * NAME: diIAGRead()
+ * NAME: diIAGRead()
*
- * FUNCTION: get the buffer for the specified iag within a fileset
+ * FUNCTION: get the buffer for the specified iag within a fileset
* or aggregate inode map.
*
* PARAMETERS:
- * imap - pointer to inode map control structure.
- * iagno - iag number.
- * bpp - point to buffer pointer to be filled in on successful
+ * imap - pointer to inode map control structure.
+ * iagno - iag number.
+ * bpp - point to buffer pointer to be filled in on successful
* exit.
*
* SERIALIZATION:
@@ -2691,8 +2677,8 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
* the read lock is unnecessary.)
*
* RETURN VALUES:
- * 0 - success.
- * -EIO - i/o error.
+ * 0 - success.
+ * -EIO - i/o error.
*/
static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
{
@@ -2712,17 +2698,17 @@ static int diIAGRead(struct inomap * imap, int iagno, struct metapage ** mpp)
}
/*
- * NAME: diFindFree()
+ * NAME: diFindFree()
*
- * FUNCTION: find the first free bit in a word starting at
+ * FUNCTION: find the first free bit in a word starting at
* the specified bit position.
*
* PARAMETERS:
- * word - word to be examined.
- * start - starting bit position.
+ * word - word to be examined.
+ * start - starting bit position.
*
* RETURN VALUES:
- * bit position of first free bit in the word or 32 if
+ * bit position of first free bit in the word or 32 if
* no free bits were found.
*/
static int diFindFree(u32 word, int start)
@@ -2897,7 +2883,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
atomic_read(&imap->im_numfree));
/*
- * reconstruct imap
+ * reconstruct imap
*
* coalesce contiguous k (newAGSize/oldAGSize) AGs;
* i.e., (AGi, ..., AGj) where i = k*n and j = k*(n+1) - 1 to AGn;
@@ -2913,7 +2899,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
}
/*
- * process each iag page of the map.
+ * process each iag page of the map.
*
* rebuild AG Free Inode List, AG Free Inode Extent List;
*/
@@ -2932,7 +2918,7 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
/* leave free iag in the free iag list */
if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {
- release_metapage(bp);
+ release_metapage(bp);
continue;
}
@@ -3063,13 +3049,13 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
}
/*
- * NAME: copy_from_dinode()
+ * NAME: copy_from_dinode()
*
- * FUNCTION: Copies inode info from disk inode to in-memory inode
+ * FUNCTION: Copies inode info from disk inode to in-memory inode
*
* RETURN VALUES:
- * 0 - success
- * -ENOMEM - insufficient memory
+ * 0 - success
+ * -ENOMEM - insufficient memory
*/
static int copy_from_dinode(struct dinode * dip, struct inode *ip)
{
@@ -3151,9 +3137,9 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
}
/*
- * NAME: copy_to_dinode()
+ * NAME: copy_to_dinode()
*
- * FUNCTION: Copies inode info from in-memory inode to disk inode
+ * FUNCTION: Copies inode info from in-memory inode to disk inode
*/
static void copy_to_dinode(struct dinode * dip, struct inode *ip)
{
diff --git a/fs/jfs/jfs_imap.h b/fs/jfs/jfs_imap.h
index 4f9c346ed49..610a0e9d894 100644
--- a/fs/jfs/jfs_imap.h
+++ b/fs/jfs/jfs_imap.h
@@ -24,17 +24,17 @@
* jfs_imap.h: disk inode manager
*/
-#define EXTSPERIAG 128 /* number of disk inode extent per iag */
-#define IMAPBLKNO 0 /* lblkno of dinomap within inode map */
-#define SMAPSZ 4 /* number of words per summary map */
+#define EXTSPERIAG 128 /* number of disk inode extent per iag */
+#define IMAPBLKNO 0 /* lblkno of dinomap within inode map */
+#define SMAPSZ 4 /* number of words per summary map */
#define EXTSPERSUM 32 /* number of extents per summary map entry */
#define L2EXTSPERSUM 5 /* l2 number of extents per summary map */
#define PGSPERIEXT 4 /* number of 4K pages per dinode extent */
-#define MAXIAGS ((1<<20)-1) /* maximum number of iags */
-#define MAXAG 128 /* maximum number of allocation groups */
+#define MAXIAGS ((1<<20)-1) /* maximum number of iags */
+#define MAXAG 128 /* maximum number of allocation groups */
-#define AMAPSIZE 512 /* bytes in the IAG allocation maps */
-#define SMAPSIZE 16 /* bytes in the IAG summary maps */
+#define AMAPSIZE 512 /* bytes in the IAG allocation maps */
+#define SMAPSIZE 16 /* bytes in the IAG summary maps */
/* convert inode number to iag number */
#define INOTOIAG(ino) ((ino) >> L2INOSPERIAG)
@@ -60,31 +60,31 @@
* inode allocation group page (per 4096 inodes of an AG)
*/
struct iag {
- __le64 agstart; /* 8: starting block of ag */
- __le32 iagnum; /* 4: inode allocation group number */
- __le32 inofreefwd; /* 4: ag inode free list forward */
- __le32 inofreeback; /* 4: ag inode free list back */
- __le32 extfreefwd; /* 4: ag inode extent free list forward */
- __le32 extfreeback; /* 4: ag inode extent free list back */
- __le32 iagfree; /* 4: iag free list */
+ __le64 agstart; /* 8: starting block of ag */
+ __le32 iagnum; /* 4: inode allocation group number */
+ __le32 inofreefwd; /* 4: ag inode free list forward */
+ __le32 inofreeback; /* 4: ag inode free list back */
+ __le32 extfreefwd; /* 4: ag inode extent free list forward */
+ __le32 extfreeback; /* 4: ag inode extent free list back */
+ __le32 iagfree; /* 4: iag free list */
/* summary map: 1 bit per inode extent */
__le32 inosmap[SMAPSZ]; /* 16: sum map of mapwords w/ free inodes;
- * note: this indicates free and backed
- * inodes, if the extent is not backed the
- * value will be 1. if the extent is
- * backed but all inodes are being used the
- * value will be 1. if the extent is
- * backed but at least one of the inodes is
- * free the value will be 0.
+ * note: this indicates free and backed
+ * inodes, if the extent is not backed the
+ * value will be 1. if the extent is
+ * backed but all inodes are being used the
+ * value will be 1. if the extent is
+ * backed but at least one of the inodes is
+ * free the value will be 0.
*/
__le32 extsmap[SMAPSZ]; /* 16: sum map of mapwords w/ free extents */
- __le32 nfreeinos; /* 4: number of free inodes */
- __le32 nfreeexts; /* 4: number of free extents */
+ __le32 nfreeinos; /* 4: number of free inodes */
+ __le32 nfreeexts; /* 4: number of free extents */
/* (72) */
u8 pad[1976]; /* 1976: pad to 2048 bytes */
/* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */
- __le32 wmap[EXTSPERIAG]; /* 512: working allocation map */
+ __le32 wmap[EXTSPERIAG]; /* 512: working allocation map */
__le32 pmap[EXTSPERIAG]; /* 512: persistent allocation map */
pxd_t inoext[EXTSPERIAG]; /* 1024: inode extent addresses */
}; /* (4096) */
@@ -93,44 +93,44 @@ struct iag {
* per AG control information (in inode map control page)
*/
struct iagctl_disk {
- __le32 inofree; /* 4: free inode list anchor */
- __le32 extfree; /* 4: free extent list anchor */
- __le32 numinos; /* 4: number of backed inodes */
- __le32 numfree; /* 4: number of free inodes */
+ __le32 inofree; /* 4: free inode list anchor */
+ __le32 extfree; /* 4: free extent list anchor */
+ __le32 numinos; /* 4: number of backed inodes */
+ __le32 numfree; /* 4: number of free inodes */
}; /* (16) */
struct iagctl {
- int inofree; /* free inode list anchor */
- int extfree; /* free extent list anchor */
- int numinos; /* number of backed inodes */
- int numfree; /* number of free inodes */
+ int inofree; /* free inode list anchor */
+ int extfree; /* free extent list anchor */
+ int numinos; /* number of backed inodes */
+ int numfree; /* number of free inodes */
};
/*
* per fileset/aggregate inode map control page
*/
struct dinomap_disk {
- __le32 in_freeiag; /* 4: free iag list anchor */
- __le32 in_nextiag; /* 4: next free iag number */
- __le32 in_numinos; /* 4: num of backed inodes */
+ __le32 in_freeiag; /* 4: free iag list anchor */
+ __le32 in_nextiag; /* 4: next free iag number */
+ __le32 in_numinos; /* 4: num of backed inodes */
__le32 in_numfree; /* 4: num of free backed inodes */
__le32 in_nbperiext; /* 4: num of blocks per inode extent */
- __le32 in_l2nbperiext; /* 4: l2 of in_nbperiext */
- __le32 in_diskblock; /* 4: for standalone test driver */
- __le32 in_maxag; /* 4: for standalone test driver */
- u8 pad[2016]; /* 2016: pad to 2048 */
+ __le32 in_l2nbperiext; /* 4: l2 of in_nbperiext */
+ __le32 in_diskblock; /* 4: for standalone test driver */
+ __le32 in_maxag; /* 4: for standalone test driver */
+ u8 pad[2016]; /* 2016: pad to 2048 */
struct iagctl_disk in_agctl[MAXAG]; /* 2048: AG control information */
}; /* (4096) */
struct dinomap {
- int in_freeiag; /* free iag list anchor */
- int in_nextiag; /* next free iag number */
- int in_numinos; /* num of backed inodes */
- int in_numfree; /* num of free backed inodes */
+ int in_freeiag; /* free iag list anchor */
+ int in_nextiag; /* next free iag number */
+ int in_numinos; /* num of backed inodes */
+ int in_numfree; /* num of free backed inodes */
int in_nbperiext; /* num of blocks per inode extent */
- int in_l2nbperiext; /* l2 of in_nbperiext */
- int in_diskblock; /* for standalone test driver */
- int in_maxag; /* for standalone test driver */
+ int in_l2nbperiext; /* l2 of in_nbperiext */
+ int in_diskblock; /* for standalone test driver */
+ int in_maxag; /* for standalone test driver */
struct iagctl in_agctl[MAXAG]; /* AG control information */
};
@@ -139,9 +139,9 @@ struct dinomap {
*/
struct inomap {
struct dinomap im_imap; /* 4096: inode allocation control */
- struct inode *im_ipimap; /* 4: ptr to inode for imap */
- struct mutex im_freelock; /* 4: iag free list lock */
- struct mutex im_aglock[MAXAG]; /* 512: per AG locks */
+ struct inode *im_ipimap; /* 4: ptr to inode for imap */
+ struct mutex im_freelock; /* 4: iag free list lock */
+ struct mutex im_aglock[MAXAG]; /* 512: per AG locks */
u32 *im_DBGdimap;
atomic_t im_numinos; /* num of backed inodes */
atomic_t im_numfree; /* num of free backed inodes */
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
index 8f453eff3c8..cb8f30985ad 100644
--- a/fs/jfs/jfs_incore.h
+++ b/fs/jfs/jfs_incore.h
@@ -40,7 +40,7 @@ struct jfs_inode_info {
uint mode2; /* jfs-specific mode */
uint saved_uid; /* saved for uid mount option */
uint saved_gid; /* saved for gid mount option */
- pxd_t ixpxd; /* inode extent descriptor */
+ pxd_t ixpxd; /* inode extent descriptor */
dxd_t acl; /* dxd describing acl */
dxd_t ea; /* dxd describing ea */
time_t otime; /* time created */
@@ -190,7 +190,7 @@ struct jfs_sb_info {
uint gengen; /* inode generation generator*/
uint inostamp; /* shows inode belongs to fileset*/
- /* Formerly in ipbmap */
+ /* Formerly in ipbmap */
struct bmap *bmap; /* incore bmap descriptor */
struct nls_table *nls_tab; /* current codepage */
struct inode *direct_inode; /* metadata inode */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 44a2f33cb98..de3e4a506db 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -244,7 +244,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
goto writeRecord;
/*
- * initialize/update page/transaction recovery lsn
+ * initialize/update page/transaction recovery lsn
*/
lsn = log->lsn;
@@ -263,7 +263,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * initialize/update lsn of tblock of the page
+ * initialize/update lsn of tblock of the page
*
* transaction inherits oldest lsn of pages associated
* with allocation/deallocation of resources (their
@@ -307,7 +307,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
LOGSYNC_UNLOCK(log, flags);
/*
- * write the log record
+ * write the log record
*/
writeRecord:
lsn = lmWriteRecord(log, tblk, lrd, tlck);
@@ -372,7 +372,7 @@ lmWriteRecord(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
goto moveLrd;
/*
- * move log record data
+ * move log record data
*/
/* retrieve source meta-data page to log */
if (tlck->flag & tlckPAGELOCK) {
@@ -465,7 +465,7 @@ lmWriteRecord(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * move log record descriptor
+ * move log record descriptor
*/
moveLrd:
lrd->length = cpu_to_le16(len);
@@ -574,7 +574,7 @@ static int lmNextPage(struct jfs_log * log)
LOGGC_LOCK(log);
/*
- * write or queue the full page at the tail of write queue
+ * write or queue the full page at the tail of write queue
*/
/* get the tail tblk on commit queue */
if (list_empty(&log->cqueue))
@@ -625,7 +625,7 @@ static int lmNextPage(struct jfs_log * log)
LOGGC_UNLOCK(log);
/*
- * allocate/initialize next page
+ * allocate/initialize next page
*/
/* if log wraps, the first data page of log is 2
* (0 never used, 1 is superblock).
@@ -953,7 +953,7 @@ static int lmLogSync(struct jfs_log * log, int hard_sync)
}
/*
- * forward syncpt
+ * forward syncpt
*/
/* if last sync is same as last syncpt,
* invoke sync point forward processing to update sync.
@@ -989,7 +989,7 @@ static int lmLogSync(struct jfs_log * log, int hard_sync)
lsn = log->lsn;
/*
- * setup next syncpt trigger (SWAG)
+ * setup next syncpt trigger (SWAG)
*/
logsize = log->logsize;
@@ -1000,11 +1000,11 @@ static int lmLogSync(struct jfs_log * log, int hard_sync)
if (more < 2 * LOGPSIZE) {
jfs_warn("\n ... Log Wrap ... Log Wrap ... Log Wrap ...\n");
/*
- * log wrapping
+ * log wrapping
*
* option 1 - panic ? No.!
* option 2 - shutdown file systems
- * associated with log ?
+ * associated with log ?
* option 3 - extend log ?
*/
/*
@@ -1062,7 +1062,7 @@ void jfs_syncpt(struct jfs_log *log, int hard_sync)
/*
* NAME: lmLogOpen()
*
- * FUNCTION: open the log on first open;
+ * FUNCTION: open the log on first open;
* insert filesystem in the active list of the log.
*
* PARAMETER: ipmnt - file system mount inode
@@ -1113,7 +1113,7 @@ int lmLogOpen(struct super_block *sb)
init_waitqueue_head(&log->syncwait);
/*
- * external log as separate logical volume
+ * external log as separate logical volume
*
* file systems to log may have n-to-1 relationship;
*/
@@ -1155,7 +1155,7 @@ journal_found:
return 0;
/*
- * unwind on error
+ * unwind on error
*/
shutdown: /* unwind lbmLogInit() */
list_del(&log->journal_list);
@@ -1427,7 +1427,7 @@ int lmLogInit(struct jfs_log * log)
return 0;
/*
- * unwind on error
+ * unwind on error
*/
errout30: /* release log page */
log->wqueue = NULL;
@@ -1480,7 +1480,7 @@ int lmLogClose(struct super_block *sb)
if (test_bit(log_INLINELOG, &log->flag)) {
/*
- * in-line log in host file system
+ * in-line log in host file system
*/
rc = lmLogShutdown(log);
kfree(log);
@@ -1504,7 +1504,7 @@ int lmLogClose(struct super_block *sb)
goto out;
/*
- * external log as separate logical volume
+ * external log as separate logical volume
*/
list_del(&log->journal_list);
bdev = log->bdev;
@@ -1622,20 +1622,26 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
if (!list_empty(&log->synclist)) {
struct logsyncblk *lp;
+ printk(KERN_ERR "jfs_flush_journal: synclist not empty\n");
list_for_each_entry(lp, &log->synclist, synclist) {
if (lp->xflag & COMMIT_PAGE) {
struct metapage *mp = (struct metapage *)lp;
- dump_mem("orphan metapage", lp,
- sizeof(struct metapage));
- dump_mem("page", mp->page, sizeof(struct page));
- }
- else
- dump_mem("orphan tblock", lp,
- sizeof(struct tblock));
+ print_hex_dump(KERN_ERR, "metapage: ",
+ DUMP_PREFIX_ADDRESS, 16, 4,
+ mp, sizeof(struct metapage), 0);
+ print_hex_dump(KERN_ERR, "page: ",
+ DUMP_PREFIX_ADDRESS, 16,
+ sizeof(long), mp->page,
+ sizeof(struct page), 0);
+ } else
+ print_hex_dump(KERN_ERR, "tblock:",
+ DUMP_PREFIX_ADDRESS, 16, 4,
+ lp, sizeof(struct tblock), 0);
}
}
+#else
+ WARN_ON(!list_empty(&log->synclist));
#endif
- //assert(list_empty(&log->synclist));
clear_bit(log_FLUSH, &log->flag);
}
@@ -1723,7 +1729,7 @@ int lmLogShutdown(struct jfs_log * log)
*
* PARAMETE: log - pointer to logs inode.
* fsdev - kdev_t of filesystem.
- * serial - pointer to returned log serial number
+ * serial - pointer to returned log serial number
* activate - insert/remove device from active list.
*
* RETURN: 0 - success
@@ -1963,7 +1969,7 @@ static void lbmfree(struct lbuf * bp)
* FUNCTION: add a log buffer to the log redrive list
*
* PARAMETER:
- * bp - log buffer
+ * bp - log buffer
*
* NOTES:
* Takes log_redrive_lock.
@@ -2054,7 +2060,7 @@ static void lbmWrite(struct jfs_log * log, struct lbuf * bp, int flag,
bp->l_flag = flag;
/*
- * insert bp at tail of write queue associated with log
+ * insert bp at tail of write queue associated with log
*
* (request is either for bp already/currently at head of queue
* or new bp to be inserted at tail)
@@ -2117,7 +2123,7 @@ static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag)
log->base + (bp->l_pn << (L2LOGPSIZE - log->l2bsize));
/*
- * initiate pageout of the page
+ * initiate pageout of the page
*/
lbmStartIO(bp);
}
@@ -2128,7 +2134,7 @@ static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag)
*
* FUNCTION: Interface to DD strategy routine
*
- * RETURN: none
+ * RETURN: none
*
* serialization: LCACHE_LOCK() is NOT held during log i/o;
*/
@@ -2222,7 +2228,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
bio_put(bio);
/*
- * pagein completion
+ * pagein completion
*/
if (bp->l_flag & lbmREAD) {
bp->l_flag &= ~lbmREAD;
@@ -2236,7 +2242,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
}
/*
- * pageout completion
+ * pageout completion
*
* the bp at the head of write queue has completed pageout.
*
@@ -2302,7 +2308,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
}
/*
- * synchronous pageout:
+ * synchronous pageout:
*
* buffer has not necessarily been removed from write queue
* (e.g., synchronous write of partial-page with COMMIT):
@@ -2316,7 +2322,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
}
/*
- * Group Commit pageout:
+ * Group Commit pageout:
*/
else if (bp->l_flag & lbmGC) {
LCACHE_UNLOCK(flags);
@@ -2324,7 +2330,7 @@ static int lbmIODone(struct bio *bio, unsigned int bytes_done, int error)
}
/*
- * asynchronous pageout:
+ * asynchronous pageout:
*
* buffer must have been removed from write queue:
* insert buffer at head of freelist where it can be recycled
@@ -2375,7 +2381,7 @@ int jfsIOWait(void *arg)
* FUNCTION: format file system log
*
* PARAMETERS:
- * log - volume log
+ * log - volume log
* logAddress - start address of log space in FS block
* logSize - length of log space in FS block;
*
@@ -2407,16 +2413,16 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
npages = logSize >> sbi->l2nbperpage;
/*
- * log space:
+ * log space:
*
* page 0 - reserved;
* page 1 - log superblock;
* page 2 - log data page: A SYNC log record is written
- * into this page at logform time;
+ * into this page at logform time;
* pages 3-N - log data page: set to empty log data pages;
*/
/*
- * init log superblock: log page 1
+ * init log superblock: log page 1
*/
logsuper = (struct logsuper *) bp->l_ldata;
@@ -2436,7 +2442,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
goto exit;
/*
- * init pages 2 to npages-1 as log data pages:
+ * init pages 2 to npages-1 as log data pages:
*
* log page sequence number (lpsn) initialization:
*
@@ -2479,7 +2485,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
goto exit;
/*
- * initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
+ * initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)
*/
for (lspn = 0; lspn < npages - 3; lspn++) {
lp->h.page = lp->t.page = cpu_to_le32(lspn);
@@ -2495,7 +2501,7 @@ int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize)
rc = 0;
exit:
/*
- * finalize log
+ * finalize log
*/
/* release the buffer */
lbmFree(bp);
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index a53fb17ea21..1f85ef0ec04 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -144,7 +144,7 @@ struct logpage {
*
* (this comment should be rewritten !)
* jfs uses only "after" log records (only a single writer is allowed
- * in a page, pages are written to temporary paging space if
+ * in a page, pages are written to temporary paging space if
* if they must be written to disk before commit, and i/o is
* scheduled for modified pages to their home location after
* the log records containing the after values and the commit
@@ -153,7 +153,7 @@ struct logpage {
*
* a log record consists of a data area of variable length followed by
* a descriptor of fixed size LOGRDSIZE bytes.
- * the data area is rounded up to an integral number of 4-bytes and
+ * the data area is rounded up to an integral number of 4-bytes and
* must be no longer than LOGPSIZE.
* the descriptor is of size of multiple of 4-bytes and aligned on a
* 4-byte boundary.
@@ -215,13 +215,13 @@ struct lrd {
union {
/*
- * COMMIT: commit
+ * COMMIT: commit
*
* transaction commit: no type-dependent information;
*/
/*
- * REDOPAGE: after-image
+ * REDOPAGE: after-image
*
* apply after-image;
*
@@ -236,7 +236,7 @@ struct lrd {
} redopage; /* (20) */
/*
- * NOREDOPAGE: the page is freed
+ * NOREDOPAGE: the page is freed
*
* do not apply after-image records which precede this record
* in the log with the same page block number to this page.
@@ -252,7 +252,7 @@ struct lrd {
} noredopage; /* (20) */
/*
- * UPDATEMAP: update block allocation map
+ * UPDATEMAP: update block allocation map
*
* either in-line PXD,
* or out-of-line XADLIST;
@@ -268,7 +268,7 @@ struct lrd {
} updatemap; /* (20) */
/*
- * NOREDOINOEXT: the inode extent is freed
+ * NOREDOINOEXT: the inode extent is freed
*
* do not apply after-image records which precede this
* record in the log with the any of the 4 page block
@@ -286,7 +286,7 @@ struct lrd {
} noredoinoext; /* (20) */
/*
- * SYNCPT: log sync point
+ * SYNCPT: log sync point
*
* replay log upto syncpt address specified;
*/
@@ -295,13 +295,13 @@ struct lrd {
} syncpt;
/*
- * MOUNT: file system mount
+ * MOUNT: file system mount
*
* file system mount: no type-dependent information;
*/
/*
- * ? FREEXTENT: free specified extent(s)
+ * ? FREEXTENT: free specified extent(s)
*
* free specified extent(s) from block allocation map
* N.B.: nextents should be length of data/sizeof(xad_t)
@@ -314,7 +314,7 @@ struct lrd {
} freextent;
/*
- * ? NOREDOFILE: this file is freed
+ * ? NOREDOFILE: this file is freed
*
* do not apply records which precede this record in the log
* with the same inode number.
@@ -330,7 +330,7 @@ struct lrd {
} noredofile;
/*
- * ? NEWPAGE:
+ * ? NEWPAGE:
*
* metadata type dependent
*/
@@ -342,7 +342,7 @@ struct lrd {
} newpage;
/*
- * ? DUMMY: filler
+ * ? DUMMY: filler
*
* no type-dependent information
*/
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 43d4f69afbe..77c7f1129dd 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -472,7 +472,8 @@ add_failed:
printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n");
goto skip;
dump_bio:
- dump_mem("bio", bio, sizeof(*bio));
+ print_hex_dump(KERN_ERR, "JFS: dump of bio: ", DUMP_PREFIX_ADDRESS, 16,
+ 4, bio, sizeof(*bio), 0);
skip:
bio_put(bio);
unlock_page(page);
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index 4dd47983489..644429acb8c 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -80,7 +80,7 @@ static int logMOUNT(struct super_block *sb);
*/
int jfs_mount(struct super_block *sb)
{
- int rc = 0; /* Return code */
+ int rc = 0; /* Return code */
struct jfs_sb_info *sbi = JFS_SBI(sb);
struct inode *ipaimap = NULL;
struct inode *ipaimap2 = NULL;
@@ -169,7 +169,7 @@ int jfs_mount(struct super_block *sb)
sbi->ipaimap2 = NULL;
/*
- * mount (the only/single) fileset
+ * mount (the only/single) fileset
*/
/*
* open fileset inode allocation map (aka fileset inode)
@@ -195,7 +195,7 @@ int jfs_mount(struct super_block *sb)
goto out;
/*
- * unwind on error
+ * unwind on error
*/
errout41: /* close fileset inode allocation map inode */
diFreeSpecial(ipimap);
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 25430d0b0d5..7aa1f7004ea 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -18,7 +18,7 @@
*/
/*
- * jfs_txnmgr.c: transaction manager
+ * jfs_txnmgr.c: transaction manager
*
* notes:
* transaction starts with txBegin() and ends with txCommit()
@@ -60,7 +60,7 @@
#include "jfs_debug.h"
/*
- * transaction management structures
+ * transaction management structures
*/
static struct {
int freetid; /* index of a free tid structure */
@@ -103,19 +103,19 @@ module_param(nTxLock, int, 0);
MODULE_PARM_DESC(nTxLock,
"Number of transaction locks (max:65536)");
-struct tblock *TxBlock; /* transaction block table */
-static int TxLockLWM; /* Low water mark for number of txLocks used */
-static int TxLockHWM; /* High water mark for number of txLocks used */
-static int TxLockVHWM; /* Very High water mark */
-struct tlock *TxLock; /* transaction lock table */
+struct tblock *TxBlock; /* transaction block table */
+static int TxLockLWM; /* Low water mark for number of txLocks used */
+static int TxLockHWM; /* High water mark for number of txLocks used */
+static int TxLockVHWM; /* Very High water mark */
+struct tlock *TxLock; /* transaction lock table */
/*
- * transaction management lock
+ * transaction management lock
*/
static DEFINE_SPINLOCK(jfsTxnLock);
-#define TXN_LOCK() spin_lock(&jfsTxnLock)
-#define TXN_UNLOCK() spin_unlock(&jfsTxnLock)
+#define TXN_LOCK() spin_lock(&jfsTxnLock)
+#define TXN_UNLOCK() spin_unlock(&jfsTxnLock)
#define LAZY_LOCK_INIT() spin_lock_init(&TxAnchor.LazyLock);
#define LAZY_LOCK(flags) spin_lock_irqsave(&TxAnchor.LazyLock, flags)
@@ -148,7 +148,7 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event)
#define TXN_WAKEUP(event) wake_up_all(event)
/*
- * statistics
+ * statistics
*/
static struct {
tid_t maxtid; /* 4: biggest tid ever used */
@@ -181,8 +181,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
static void LogSyncRelease(struct metapage * mp);
/*
- * transaction block/lock management
- * ---------------------------------
+ * transaction block/lock management
+ * ---------------------------------
*/
/*
@@ -227,9 +227,9 @@ static void txLockFree(lid_t lid)
}
/*
- * NAME: txInit()
+ * NAME: txInit()
*
- * FUNCTION: initialize transaction management structures
+ * FUNCTION: initialize transaction management structures
*
* RETURN:
*
@@ -333,9 +333,9 @@ int txInit(void)
}
/*
- * NAME: txExit()
+ * NAME: txExit()
*
- * FUNCTION: clean up when module is unloaded
+ * FUNCTION: clean up when module is unloaded
*/
void txExit(void)
{
@@ -346,12 +346,12 @@ void txExit(void)
}
/*
- * NAME: txBegin()
+ * NAME: txBegin()
*
- * FUNCTION: start a transaction.
+ * FUNCTION: start a transaction.
*
- * PARAMETER: sb - superblock
- * flag - force for nested tx;
+ * PARAMETER: sb - superblock
+ * flag - force for nested tx;
*
* RETURN: tid - transaction id
*
@@ -447,13 +447,13 @@ tid_t txBegin(struct super_block *sb, int flag)
}
/*
- * NAME: txBeginAnon()
+ * NAME: txBeginAnon()
*
- * FUNCTION: start an anonymous transaction.
+ * FUNCTION: start an anonymous transaction.
* Blocks if logsync or available tlocks are low to prevent
* anonymous tlocks from depleting supply.
*
- * PARAMETER: sb - superblock
+ * PARAMETER: sb - superblock
*
* RETURN: none
*/
@@ -489,11 +489,11 @@ void txBeginAnon(struct super_block *sb)
}
/*
- * txEnd()
+ * txEnd()
*
* function: free specified transaction block.
*
- * logsync barrier processing:
+ * logsync barrier processing:
*
* serialization:
*/
@@ -577,13 +577,13 @@ wakeup:
}
/*
- * txLock()
+ * txLock()
*
* function: acquire a transaction lock on the specified <mp>
*
* parameter:
*
- * return: transaction lock id
+ * return: transaction lock id
*
* serialization:
*/
@@ -829,12 +829,16 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
/* Only locks on ipimap or ipaimap should reach here */
/* assert(jfs_ip->fileset == AGGREGATE_I); */
if (jfs_ip->fileset != AGGREGATE_I) {
- jfs_err("txLock: trying to lock locked page!");
- dump_mem("ip", ip, sizeof(struct inode));
- dump_mem("mp", mp, sizeof(struct metapage));
- dump_mem("Locker's tblk", tid_to_tblock(tid),
- sizeof(struct tblock));
- dump_mem("Tlock", tlck, sizeof(struct tlock));
+ printk(KERN_ERR "txLock: trying to lock locked page!");
+ print_hex_dump(KERN_ERR, "ip: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ ip, sizeof(*ip), 0);
+ print_hex_dump(KERN_ERR, "mp: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ mp, sizeof(*mp), 0);
+ print_hex_dump(KERN_ERR, "Locker's tblock: ",
+ DUMP_PREFIX_ADDRESS, 16, 4, tid_to_tblock(tid),
+ sizeof(struct tblock), 0);
+ print_hex_dump(KERN_ERR, "Tlock: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ tlck, sizeof(*tlck), 0);
BUG();
}
INCREMENT(stattx.waitlock); /* statistics */
@@ -857,17 +861,17 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
}
/*
- * NAME: txRelease()
+ * NAME: txRelease()
*
- * FUNCTION: Release buffers associated with transaction locks, but don't
+ * FUNCTION: Release buffers associated with transaction locks, but don't
* mark homeok yet. The allows other transactions to modify
* buffers, but won't let them go to disk until commit record
* actually gets written.
*
* PARAMETER:
- * tblk -
+ * tblk -
*
- * RETURN: Errors from subroutines.
+ * RETURN: Errors from subroutines.
*/
static void txRelease(struct tblock * tblk)
{
@@ -896,10 +900,10 @@ static void txRelease(struct tblock * tblk)
}
/*
- * NAME: txUnlock()
+ * NAME: txUnlock()
*
- * FUNCTION: Initiates pageout of pages modified by tid in journalled
- * objects and frees their lockwords.
+ * FUNCTION: Initiates pageout of pages modified by tid in journalled
+ * objects and frees their lockwords.
*/
static void txUnlock(struct tblock * tblk)
{
@@ -983,10 +987,10 @@ static void txUnlock(struct tblock * tblk)
}
/*
- * txMaplock()
+ * txMaplock()
*
* function: allocate a transaction lock for freed page/entry;
- * for freed page, maplock is used as xtlock/dtlock type;
+ * for freed page, maplock is used as xtlock/dtlock type;
*/
struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
{
@@ -1057,7 +1061,7 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
}
/*
- * txLinelock()
+ * txLinelock()
*
* function: allocate a transaction lock for log vector list
*/
@@ -1092,39 +1096,39 @@ struct linelock *txLinelock(struct linelock * tlock)
}
/*
- * transaction commit management
- * -----------------------------
+ * transaction commit management
+ * -----------------------------
*/
/*
- * NAME: txCommit()
- *
- * FUNCTION: commit the changes to the objects specified in
- * clist. For journalled segments only the
- * changes of the caller are committed, ie by tid.
- * for non-journalled segments the data are flushed to
- * disk and then the change to the disk inode and indirect
- * blocks committed (so blocks newly allocated to the
- * segment will be made a part of the segment atomically).
- *
- * all of the segments specified in clist must be in
- * one file system. no more than 6 segments are needed
- * to handle all unix svcs.
- *
- * if the i_nlink field (i.e. disk inode link count)
- * is zero, and the type of inode is a regular file or
- * directory, or symbolic link , the inode is truncated
- * to zero length. the truncation is committed but the
- * VM resources are unaffected until it is closed (see
- * iput and iclose).
+ * NAME: txCommit()
+ *
+ * FUNCTION: commit the changes to the objects specified in
+ * clist. For journalled segments only the
+ * changes of the caller are committed, ie by tid.
+ * for non-journalled segments the data are flushed to
+ * disk and then the change to the disk inode and indirect
+ * blocks committed (so blocks newly allocated to the
+ * segment will be made a part of the segment atomically).
+ *
+ * all of the segments specified in clist must be in
+ * one file system. no more than 6 segments are needed
+ * to handle all unix svcs.
+ *
+ * if the i_nlink field (i.e. disk inode link count)
+ * is zero, and the type of inode is a regular file or
+ * directory, or symbolic link , the inode is truncated
+ * to zero length. the truncation is committed but the
+ * VM resources are unaffected until it is closed (see
+ * iput and iclose).
*
* PARAMETER:
*
* RETURN:
*
* serialization:
- * on entry the inode lock on each segment is assumed
- * to be held.
+ * on entry the inode lock on each segment is assumed
+ * to be held.
*
* i/o error:
*/
@@ -1175,7 +1179,7 @@ int txCommit(tid_t tid, /* transaction identifier */
if ((flag & (COMMIT_FORCE | COMMIT_SYNC)) == 0)
tblk->xflag |= COMMIT_LAZY;
/*
- * prepare non-journaled objects for commit
+ * prepare non-journaled objects for commit
*
* flush data pages of non-journaled file
* to prevent the file getting non-initialized disk blocks
@@ -1186,7 +1190,7 @@ int txCommit(tid_t tid, /* transaction identifier */
cd.nip = nip;
/*
- * acquire transaction lock on (on-disk) inodes
+ * acquire transaction lock on (on-disk) inodes
*
* update on-disk inode from in-memory inode
* acquiring transaction locks for AFTER records
@@ -1262,7 +1266,7 @@ int txCommit(tid_t tid, /* transaction identifier */
}
/*
- * write log records from transaction locks
+ * write log records from transaction locks
*
* txUpdateMap() resets XAD_NEW in XAD.
*/
@@ -1294,7 +1298,7 @@ int txCommit(tid_t tid, /* transaction identifier */
!test_cflag(COMMIT_Nolink, tblk->u.ip)));
/*
- * write COMMIT log record
+ * write COMMIT log record
*/
lrd->type = cpu_to_le16(LOG_COMMIT);
lrd->length = 0;
@@ -1303,7 +1307,7 @@ int txCommit(tid_t tid, /* transaction identifier */
lmGroupCommit(log, tblk);
/*
- * - transaction is now committed -
+ * - transaction is now committed -
*/
/*
@@ -1314,11 +1318,11 @@ int txCommit(tid_t tid, /* transaction identifier */
txForce(tblk);
/*
- * update allocation map.
+ * update allocation map.
*
* update inode allocation map and inode:
* free pager lock on memory object of inode if any.
- * update block allocation map.
+ * update block allocation map.
*
* txUpdateMap() resets XAD_NEW in XAD.
*/
@@ -1326,7 +1330,7 @@ int txCommit(tid_t tid, /* transaction identifier */
txUpdateMap(tblk);
/*
- * free transaction locks and pageout/free pages
+ * free transaction locks and pageout/free pages
*/
txRelease(tblk);
@@ -1335,7 +1339,7 @@ int txCommit(tid_t tid, /* transaction identifier */
/*
- * reset in-memory object state
+ * reset in-memory object state
*/
for (k = 0; k < cd.nip; k++) {
ip = cd.iplist[k];
@@ -1358,11 +1362,11 @@ int txCommit(tid_t tid, /* transaction identifier */
}
/*
- * NAME: txLog()
+ * NAME: txLog()
*
- * FUNCTION: Writes AFTER log records for all lines modified
- * by tid for segments specified by inodes in comdata.
- * Code assumes only WRITELOCKS are recorded in lockwords.
+ * FUNCTION: Writes AFTER log records for all lines modified
+ * by tid for segments specified by inodes in comdata.
+ * Code assumes only WRITELOCKS are recorded in lockwords.
*
* PARAMETERS:
*
@@ -1421,12 +1425,12 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd)
}
/*
- * diLog()
+ * diLog()
*
- * function: log inode tlock and format maplock to update bmap;
+ * function: log inode tlock and format maplock to update bmap;
*/
static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
- struct tlock * tlck, struct commit * cd)
+ struct tlock * tlck, struct commit * cd)
{
int rc = 0;
struct metapage *mp;
@@ -1442,7 +1446,7 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
pxd = &lrd->log.redopage.pxd;
/*
- * inode after image
+ * inode after image
*/
if (tlck->type & tlckENTRY) {
/* log after-image for logredo(): */
@@ -1456,7 +1460,7 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
tlck->flag |= tlckWRITEPAGE;
} else if (tlck->type & tlckFREE) {
/*
- * free inode extent
+ * free inode extent
*
* (pages of the freed inode extent have been invalidated and
* a maplock for free of the extent has been formatted at
@@ -1498,7 +1502,7 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
jfs_err("diLog: UFO type tlck:0x%p", tlck);
#ifdef _JFS_WIP
/*
- * alloc/free external EA extent
+ * alloc/free external EA extent
*
* a maplock for txUpdateMap() to update bPWMAP for alloc/free
* of the extent has been formatted at txLock() time;
@@ -1534,9 +1538,9 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * dataLog()
+ * dataLog()
*
- * function: log data tlock
+ * function: log data tlock
*/
static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct tlock * tlck)
@@ -1580,9 +1584,9 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * dtLog()
+ * dtLog()
*
- * function: log dtree tlock and format maplock to update bmap;
+ * function: log dtree tlock and format maplock to update bmap;
*/
static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct tlock * tlck)
@@ -1603,10 +1607,10 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
/*
- * page extension via relocation: entry insertion;
- * page extension in-place: entry insertion;
- * new right page from page split, reinitialized in-line
- * root from root page split: entry insertion;
+ * page extension via relocation: entry insertion;
+ * page extension in-place: entry insertion;
+ * new right page from page split, reinitialized in-line
+ * root from root page split: entry insertion;
*/
if (tlck->type & (tlckNEW | tlckEXTEND)) {
/* log after-image of the new page for logredo():
@@ -1641,8 +1645,8 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * entry insertion/deletion,
- * sibling page link update (old right page before split);
+ * entry insertion/deletion,
+ * sibling page link update (old right page before split);
*/
if (tlck->type & (tlckENTRY | tlckRELINK)) {
/* log after-image for logredo(): */
@@ -1658,11 +1662,11 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * page deletion: page has been invalidated
- * page relocation: source extent
+ * page deletion: page has been invalidated
+ * page relocation: source extent
*
- * a maplock for free of the page has been formatted
- * at txLock() time);
+ * a maplock for free of the page has been formatted
+ * at txLock() time);
*/
if (tlck->type & (tlckFREE | tlckRELOCATE)) {
/* log LOG_NOREDOPAGE of the deleted page for logredo()
@@ -1683,9 +1687,9 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * xtLog()
+ * xtLog()
*
- * function: log xtree tlock and format maplock to update bmap;
+ * function: log xtree tlock and format maplock to update bmap;
*/
static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct tlock * tlck)
@@ -1725,8 +1729,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
xadlock = (struct xdlistlock *) maplock;
/*
- * entry insertion/extension;
- * sibling page link update (old right page before split);
+ * entry insertion/extension;
+ * sibling page link update (old right page before split);
*/
if (tlck->type & (tlckNEW | tlckGROW | tlckRELINK)) {
/* log after-image for logredo():
@@ -1801,7 +1805,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * page deletion: file deletion/truncation (ref. xtTruncate())
+ * page deletion: file deletion/truncation (ref. xtTruncate())
*
* (page will be invalidated after log is written and bmap
* is updated from the page);
@@ -1908,13 +1912,13 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * page/entry truncation: file truncation (ref. xtTruncate())
+ * page/entry truncation: file truncation (ref. xtTruncate())
*
- * |----------+------+------+---------------|
- * | | |
- * | | hwm - hwm before truncation
- * | next - truncation point
- * lwm - lwm before truncation
+ * |----------+------+------+---------------|
+ * | | |
+ * | | hwm - hwm before truncation
+ * | next - truncation point
+ * lwm - lwm before truncation
* header ?
*/
if (tlck->type & tlckTRUNCATE) {
@@ -1937,7 +1941,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
twm = xtlck->twm.offset;
/*
- * write log records
+ * write log records
*/
/* log after-image for logredo():
*
@@ -1997,7 +2001,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * format maplock(s) for txUpdateMap() to update bmap
+ * format maplock(s) for txUpdateMap() to update bmap
*/
maplock->index = 0;
@@ -2069,9 +2073,9 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * mapLog()
+ * mapLog()
*
- * function: log from maplock of freed data extents;
+ * function: log from maplock of freed data extents;
*/
static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct tlock * tlck)
@@ -2081,7 +2085,7 @@ static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
pxd_t *pxd;
/*
- * page relocation: free the source page extent
+ * page relocation: free the source page extent
*
* a maplock for txUpdateMap() for free of the page
* has been formatted at txLock() time saving the src
@@ -2155,10 +2159,10 @@ static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
/*
- * txEA()
+ * txEA()
*
- * function: acquire maplock for EA/ACL extents or
- * set COMMIT_INLINE flag;
+ * function: acquire maplock for EA/ACL extents or
+ * set COMMIT_INLINE flag;
*/
void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
{
@@ -2207,10 +2211,10 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
}
/*
- * txForce()
+ * txForce()
*
* function: synchronously write pages locked by transaction
- * after txLog() but before txUpdateMap();
+ * after txLog() but before txUpdateMap();
*/
static void txForce(struct tblock * tblk)
{
@@ -2273,10 +2277,10 @@ static void txForce(struct tblock * tblk)
}
/*
- * txUpdateMap()
+ * txUpdateMap()
*
- * function: update persistent allocation map (and working map
- * if appropriate);
+ * function: update persistent allocation map (and working map
+ * if appropriate);
*
* parameter:
*/
@@ -2298,7 +2302,7 @@ static void txUpdateMap(struct tblock * tblk)
/*
- * update block allocation map
+ * update block allocation map
*
* update allocation state in pmap (and wmap) and
* update lsn of the pmap page;
@@ -2382,7 +2386,7 @@ static void txUpdateMap(struct tblock * tblk)
}
}
/*
- * update inode allocation map
+ * update inode allocation map
*
* update allocation state in pmap and
* update lsn of the pmap page;
@@ -2407,24 +2411,24 @@ static void txUpdateMap(struct tblock * tblk)
}
/*
- * txAllocPMap()
+ * txAllocPMap()
*
* function: allocate from persistent map;
*
* parameter:
- * ipbmap -
- * malock -
- * xad list:
- * pxd:
- *
- * maptype -
- * allocate from persistent map;
- * free from persistent map;
- * (e.g., tmp file - free from working map at releae
- * of last reference);
- * free from persistent and working map;
- *
- * lsn - log sequence number;
+ * ipbmap -
+ * malock -
+ * xad list:
+ * pxd:
+ *
+ * maptype -
+ * allocate from persistent map;
+ * free from persistent map;
+ * (e.g., tmp file - free from working map at releae
+ * of last reference);
+ * free from persistent and working map;
+ *
+ * lsn - log sequence number;
*/
static void txAllocPMap(struct inode *ip, struct maplock * maplock,
struct tblock * tblk)
@@ -2478,9 +2482,9 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock,
}
/*
- * txFreeMap()
+ * txFreeMap()
*
- * function: free from persistent and/or working map;
+ * function: free from persistent and/or working map;
*
* todo: optimization
*/
@@ -2579,9 +2583,9 @@ void txFreeMap(struct inode *ip,
}
/*
- * txFreelock()
+ * txFreelock()
*
- * function: remove tlock from inode anonymous locklist
+ * function: remove tlock from inode anonymous locklist
*/
void txFreelock(struct inode *ip)
{
@@ -2619,7 +2623,7 @@ void txFreelock(struct inode *ip)
}
/*
- * txAbort()
+ * txAbort()
*
* function: abort tx before commit;
*
@@ -2679,7 +2683,7 @@ void txAbort(tid_t tid, int dirty)
}
/*
- * txLazyCommit(void)
+ * txLazyCommit(void)
*
* All transactions except those changing ipimap (COMMIT_FORCE) are
* processed by this routine. This insures that the inode and block
@@ -2728,7 +2732,7 @@ static void txLazyCommit(struct tblock * tblk)
}
/*
- * jfs_lazycommit(void)
+ * jfs_lazycommit(void)
*
* To be run as a kernel daemon. If lbmIODone is called in an interrupt
* context, or where blocking is not wanted, this routine will process
@@ -2913,7 +2917,7 @@ void txResume(struct super_block *sb)
}
/*
- * jfs_sync(void)
+ * jfs_sync(void)
*
* To be run as a kernel daemon. This is awakened when tlocks run low.
* We write any inodes that have anonymous tlocks so they will become
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index 7863cf21afc..ab728893701 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -94,7 +94,7 @@ extern struct tblock *TxBlock; /* transaction block table */
*/
struct tlock {
lid_t next; /* 2: index next lockword on tid locklist
- * next lockword on freelist
+ * next lockword on freelist
*/
tid_t tid; /* 2: transaction id holding lock */
diff --git a/fs/jfs/jfs_types.h b/fs/jfs/jfs_types.h
index 09b25295868..649f9817acc 100644
--- a/fs/jfs/jfs_types.h
+++ b/fs/jfs/jfs_types.h
@@ -21,7 +21,7 @@
/*
* jfs_types.h:
*
- * basic type/utility definitions
+ * basic type/utility definitions
*
* note: this header file must be the 1st include file
* of JFS include list in all JFS .c file.
@@ -54,8 +54,8 @@ struct timestruc_t {
*/
#define LEFTMOSTONE 0x80000000
-#define HIGHORDER 0x80000000u /* high order bit on */
-#define ONES 0xffffffffu /* all bit on */
+#define HIGHORDER 0x80000000u /* high order bit on */
+#define ONES 0xffffffffu /* all bit on */
/*
* logical xd (lxd)
@@ -148,7 +148,7 @@ typedef struct {
#define sizeDXD(dxd) le32_to_cpu((dxd)->size)
/*
- * directory entry argument
+ * directory entry argument
*/
struct component_name {
int namlen;
@@ -160,14 +160,14 @@ struct component_name {
* DASD limit information - stored in directory inode
*/
struct dasd {
- u8 thresh; /* Alert Threshold (in percent) */
- u8 delta; /* Alert Threshold delta (in percent) */
+ u8 thresh; /* Alert Threshold (in percent) */
+ u8 delta; /* Alert Threshold delta (in percent) */
u8 rsrvd1;
- u8 limit_hi; /* DASD limit (in logical blocks) */
- __le32 limit_lo; /* DASD limit (in logical blocks) */
+ u8 limit_hi; /* DASD limit (in logical blocks) */
+ __le32 limit_lo; /* DASD limit (in logical blocks) */
u8 rsrvd2[3];
- u8 used_hi; /* DASD usage (in logical blocks) */
- __le32 used_lo; /* DASD usage (in logical blocks) */
+ u8 used_hi; /* DASD usage (in logical blocks) */
+ __le32 used_lo; /* DASD usage (in logical blocks) */
};
#define DASDLIMIT(dasdp) \
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index a386f48c73f..7971f37534a 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -60,7 +60,7 @@ int jfs_umount(struct super_block *sb)
jfs_info("UnMount JFS: sb:0x%p", sb);
/*
- * update superblock and close log
+ * update superblock and close log
*
* if mounted read-write and log based recovery was enabled
*/
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index acc97c46d8a..1543906a2e0 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
- * jfs_xtree.c: extent allocation descriptor B+-tree manager
+ * jfs_xtree.c: extent allocation descriptor B+-tree manager
*/
#include <linux/fs.h>
@@ -32,30 +32,30 @@
/*
* xtree local flag
*/
-#define XT_INSERT 0x00000001
+#define XT_INSERT 0x00000001
/*
- * xtree key/entry comparison: extent offset
+ * xtree key/entry comparison: extent offset
*
* return:
- * -1: k < start of extent
- * 0: start_of_extent <= k <= end_of_extent
- * 1: k > end_of_extent
+ * -1: k < start of extent
+ * 0: start_of_extent <= k <= end_of_extent
+ * 1: k > end_of_extent
*/
#define XT_CMP(CMP, K, X, OFFSET64)\
{\
- OFFSET64 = offsetXAD(X);\
- (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
- ((K) < OFFSET64) ? -1 : 0;\
+ OFFSET64 = offsetXAD(X);\
+ (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
+ ((K) < OFFSET64) ? -1 : 0;\
}
/* write a xad entry */
#define XT_PUTENTRY(XAD, FLAG, OFF, LEN, ADDR)\
{\
- (XAD)->flag = (FLAG);\
- XADoffset((XAD), (OFF));\
- XADlength((XAD), (LEN));\
- XADaddress((XAD), (ADDR));\
+ (XAD)->flag = (FLAG);\
+ XADoffset((XAD), (OFF));\
+ XADlength((XAD), (LEN));\
+ XADaddress((XAD), (ADDR));\
}
#define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)
@@ -76,13 +76,13 @@
MP = NULL;\
RC = -EIO;\
}\
- }\
+ }\
}
/* for consistency */
#define XT_PUTPAGE(MP) BT_PUTPAGE(MP)
-#define XT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
+#define XT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
BT_GETSEARCH(IP, LEAF, BN, MP, xtpage_t, P, INDEX, i_xtroot)
/* xtree entry parameter descriptor */
struct xtsplit {
@@ -97,7 +97,7 @@ struct xtsplit {
/*
- * statistics
+ * statistics
*/
#ifdef CONFIG_JFS_STATISTICS
static struct {
@@ -136,7 +136,7 @@ static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * fp);
#endif /* _STILL_TO_PORT */
/*
- * xtLookup()
+ * xtLookup()
*
* function: map a single page into a physical extent;
*/
@@ -179,7 +179,7 @@ int xtLookup(struct inode *ip, s64 lstart,
}
/*
- * compute the physical extent covering logical extent
+ * compute the physical extent covering logical extent
*
* N.B. search may have failed (e.g., hole in sparse file),
* and returned the index of the next entry.
@@ -220,27 +220,27 @@ int xtLookup(struct inode *ip, s64 lstart,
/*
- * xtLookupList()
+ * xtLookupList()
*
* function: map a single logical extent into a list of physical extent;
*
* parameter:
- * struct inode *ip,
- * struct lxdlist *lxdlist, lxd list (in)
- * struct xadlist *xadlist, xad list (in/out)
- * int flag)
+ * struct inode *ip,
+ * struct lxdlist *lxdlist, lxd list (in)
+ * struct xadlist *xadlist, xad list (in/out)
+ * int flag)
*
* coverage of lxd by xad under assumption of
* . lxd's are ordered and disjoint.
* . xad's are ordered and disjoint.
*
* return:
- * 0: success
+ * 0: success
*
* note: a page being written (even a single byte) is backed fully,
- * except the last page which is only backed with blocks
- * required to cover the last byte;
- * the extent backing a page is fully contained within an xad;
+ * except the last page which is only backed with blocks
+ * required to cover the last byte;
+ * the extent backing a page is fully contained within an xad;
*/
int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
struct xadlist * xadlist, int flag)
@@ -284,7 +284,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
return rc;
/*
- * compute the physical extent covering logical extent
+ * compute the physical extent covering logical extent
*
* N.B. search may have failed (e.g., hole in sparse file),
* and returned the index of the next entry.
@@ -343,7 +343,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
if (lstart >= size)
goto mapend;
- /* compare with the current xad */
+ /* compare with the current xad */
goto compare1;
}
/* lxd is covered by xad */
@@ -430,7 +430,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
/*
* lxd is partially covered by xad
*/
- else { /* (xend < lend) */
+ else { /* (xend < lend) */
/*
* get next xad
@@ -477,22 +477,22 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist,
/*
- * xtSearch()
+ * xtSearch()
*
- * function: search for the xad entry covering specified offset.
+ * function: search for the xad entry covering specified offset.
*
* parameters:
- * ip - file object;
- * xoff - extent offset;
- * nextp - address of next extent (if any) for search miss
- * cmpp - comparison result:
- * btstack - traverse stack;
- * flag - search process flag (XT_INSERT);
+ * ip - file object;
+ * xoff - extent offset;
+ * nextp - address of next extent (if any) for search miss
+ * cmpp - comparison result:
+ * btstack - traverse stack;
+ * flag - search process flag (XT_INSERT);
*
* returns:
- * btstack contains (bn, index) of search path traversed to the entry.
- * *cmpp is set to result of comparison with the entry returned.
- * the page containing the entry is pinned at exit.
+ * btstack contains (bn, index) of search path traversed to the entry.
+ * *cmpp is set to result of comparison with the entry returned.
+ * the page containing the entry is pinned at exit.
*/
static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
int *cmpp, struct btstack * btstack, int flag)
@@ -517,7 +517,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
btstack->nsplit = 0;
/*
- * search down tree from root:
+ * search down tree from root:
*
* between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
* internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -642,7 +642,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
XT_CMP(cmp, xoff, &p->xad[index], t64);
if (cmp == 0) {
/*
- * search hit
+ * search hit
*/
/* search hit - leaf page:
* return the entry found
@@ -692,7 +692,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
}
/*
- * search miss
+ * search miss
*
* base is the smallest index with key (Kj) greater than
* search key (K) and may be zero or maxentry index.
@@ -773,22 +773,22 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
}
/*
- * xtInsert()
+ * xtInsert()
*
* function:
*
* parameter:
- * tid - transaction id;
- * ip - file object;
- * xflag - extent flag (XAD_NOTRECORDED):
- * xoff - extent offset;
- * xlen - extent length;
- * xaddrp - extent address pointer (in/out):
- * if (*xaddrp)
- * caller allocated data extent at *xaddrp;
- * else
- * allocate data extent and return its xaddr;
- * flag -
+ * tid - transaction id;
+ * ip - file object;
+ * xflag - extent flag (XAD_NOTRECORDED):
+ * xoff - extent offset;
+ * xlen - extent length;
+ * xaddrp - extent address pointer (in/out):
+ * if (*xaddrp)
+ * caller allocated data extent at *xaddrp;
+ * else
+ * allocate data extent and return its xaddr;
+ * flag -
*
* return:
*/
@@ -813,7 +813,7 @@ int xtInsert(tid_t tid, /* transaction id */
jfs_info("xtInsert: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
/*
- * search for the entry location at which to insert:
+ * search for the entry location at which to insert:
*
* xtFastSearch() and xtSearch() both returns (leaf page
* pinned, index at which to insert).
@@ -853,13 +853,13 @@ int xtInsert(tid_t tid, /* transaction id */
}
/*
- * insert entry for new extent
+ * insert entry for new extent
*/
xflag |= XAD_NEW;
/*
- * if the leaf page is full, split the page and
- * propagate up the router entry for the new page from split
+ * if the leaf page is full, split the page and
+ * propagate up the router entry for the new page from split
*
* The xtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -886,7 +886,7 @@ int xtInsert(tid_t tid, /* transaction id */
}
/*
- * insert the new entry into the leaf page
+ * insert the new entry into the leaf page
*/
/*
* acquire a transaction lock on the leaf page;
@@ -930,16 +930,16 @@ int xtInsert(tid_t tid, /* transaction id */
/*
- * xtSplitUp()
+ * xtSplitUp()
*
* function:
- * split full pages as propagating insertion up the tree
+ * split full pages as propagating insertion up the tree
*
* parameter:
- * tid - transaction id;
- * ip - file object;
- * split - entry parameter descriptor;
- * btstack - traverse stack from xtSearch()
+ * tid - transaction id;
+ * ip - file object;
+ * split - entry parameter descriptor;
+ * btstack - traverse stack from xtSearch()
*
* return:
*/
@@ -1199,22 +1199,22 @@ xtSplitUp(tid_t tid,
/*
- * xtSplitPage()
+ * xtSplitPage()
*
* function:
- * split a full non-root page into
- * original/split/left page and new right page
- * i.e., the original/split page remains as left page.
+ * split a full non-root page into
+ * original/split/left page and new right page
+ * i.e., the original/split page remains as left page.
*
* parameter:
- * int tid,
- * struct inode *ip,
- * struct xtsplit *split,
- * struct metapage **rmpp,
- * u64 *rbnp,
+ * int tid,
+ * struct inode *ip,
+ * struct xtsplit *split,
+ * struct metapage **rmpp,
+ * u64 *rbnp,
*
* return:
- * Pointer to page in which to insert or NULL on error.
+ * Pointer to page in which to insert or NULL on error.
*/
static int
xtSplitPage(tid_t tid, struct inode *ip,
@@ -1248,9 +1248,9 @@ xtSplitPage(tid_t tid, struct inode *ip,
rbn = addressPXD(pxd);
/* Allocate blocks to quota. */
- if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
- rc = -EDQUOT;
- goto clean_up;
+ if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+ rc = -EDQUOT;
+ goto clean_up;
}
quota_allocation += lengthPXD(pxd);
@@ -1304,7 +1304,7 @@ xtSplitPage(tid_t tid, struct inode *ip,
skip = split->index;
/*
- * sequential append at tail (after last entry of last page)
+ * sequential append at tail (after last entry of last page)
*
* if splitting the last page on a level because of appending
* a entry to it (skip is maxentry), it's likely that the access is
@@ -1342,7 +1342,7 @@ xtSplitPage(tid_t tid, struct inode *ip,
}
/*
- * non-sequential insert (at possibly middle page)
+ * non-sequential insert (at possibly middle page)
*/
/*
@@ -1465,25 +1465,24 @@ xtSplitPage(tid_t tid, struct inode *ip,
/*
- * xtSplitRoot()
+ * xtSplitRoot()
*
* function:
- * split the full root page into
- * original/root/split page and new right page
- * i.e., root remains fixed in tree anchor (inode) and
- * the root is copied to a single new right child page
- * since root page << non-root page, and
- * the split root page contains a single entry for the
- * new right child page.
+ * split the full root page into original/root/split page and new
+ * right page
+ * i.e., root remains fixed in tree anchor (inode) and the root is
+ * copied to a single new right child page since root page <<
+ * non-root page, and the split root page contains a single entry
+ * for the new right child page.
*
* parameter:
- * int tid,
- * struct inode *ip,
- * struct xtsplit *split,
- * struct metapage **rmpp)
+ * int tid,
+ * struct inode *ip,
+ * struct xtsplit *split,
+ * struct metapage **rmpp)
*
* return:
- * Pointer to page in which to insert or NULL on error.
+ * Pointer to page in which to insert or NULL on error.
*/
static int
xtSplitRoot(tid_t tid,
@@ -1505,7 +1504,7 @@ xtSplitRoot(tid_t tid,
INCREMENT(xtStat.split);
/*
- * allocate a single (right) child page
+ * allocate a single (right) child page
*/
pxdlist = split->pxdlist;
pxd = &pxdlist->pxd[pxdlist->npxd];
@@ -1573,7 +1572,7 @@ xtSplitRoot(tid_t tid,
}
/*
- * reset the root
+ * reset the root
*
* init root with the single entry for the new right page
* set the 1st entry offset to 0, which force the left-most key
@@ -1610,7 +1609,7 @@ xtSplitRoot(tid_t tid,
/*
- * xtExtend()
+ * xtExtend()
*
* function: extend in-place;
*
@@ -1677,7 +1676,7 @@ int xtExtend(tid_t tid, /* transaction id */
goto extendOld;
/*
- * extent overflow: insert entry for new extent
+ * extent overflow: insert entry for new extent
*/
//insertNew:
xoff = offsetXAD(xad) + MAXXLEN;
@@ -1685,8 +1684,8 @@ int xtExtend(tid_t tid, /* transaction id */
nextindex = le16_to_cpu(p->header.nextindex);
/*
- * if the leaf page is full, insert the new entry and
- * propagate up the router entry for the new page from split
+ * if the leaf page is full, insert the new entry and
+ * propagate up the router entry for the new page from split
*
* The xtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -1731,7 +1730,7 @@ int xtExtend(tid_t tid, /* transaction id */
}
}
/*
- * insert the new entry into the leaf page
+ * insert the new entry into the leaf page
*/
else {
/* insert the new entry: mark the entry NEW */
@@ -1771,11 +1770,11 @@ int xtExtend(tid_t tid, /* transaction id */
#ifdef _NOTYET
/*
- * xtTailgate()
+ * xtTailgate()
*
* function: split existing 'tail' extent
- * (split offset >= start offset of tail extent), and
- * relocate and extend the split tail half;
+ * (split offset >= start offset of tail extent), and
+ * relocate and extend the split tail half;
*
* note: existing extent may or may not have been committed.
* caller is responsible for pager buffer cache update, and
@@ -1804,7 +1803,7 @@ int xtTailgate(tid_t tid, /* transaction id */
/*
printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
- (ulong)xoff, xlen, (ulong)xaddr);
+ (ulong)xoff, xlen, (ulong)xaddr);
*/
/* there must exist extent to be tailgated */
@@ -1842,18 +1841,18 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
xad = &p->xad[index];
/*
printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
- (ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
+ (ulong)offsetXAD(xad), lengthXAD(xad), (ulong)addressXAD(xad));
*/
if ((llen = xoff - offsetXAD(xad)) == 0)
goto updateOld;
/*
- * partially replace extent: insert entry for new extent
+ * partially replace extent: insert entry for new extent
*/
//insertNew:
/*
- * if the leaf page is full, insert the new entry and
- * propagate up the router entry for the new page from split
+ * if the leaf page is full, insert the new entry and
+ * propagate up the router entry for the new page from split
*
* The xtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -1898,7 +1897,7 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
}
}
/*
- * insert the new entry into the leaf page
+ * insert the new entry into the leaf page
*/
else {
/* insert the new entry: mark the entry NEW */
@@ -1955,17 +1954,17 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
#endif /* _NOTYET */
/*
- * xtUpdate()
+ * xtUpdate()
*
* function: update XAD;
*
- * update extent for allocated_but_not_recorded or
- * compressed extent;
+ * update extent for allocated_but_not_recorded or
+ * compressed extent;
*
* parameter:
- * nxad - new XAD;
- * logical extent of the specified XAD must be completely
- * contained by an existing XAD;
+ * nxad - new XAD;
+ * logical extent of the specified XAD must be completely
+ * contained by an existing XAD;
*/
int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
{ /* new XAD */
@@ -2416,19 +2415,19 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p);
/*
- * xtAppend()
+ * xtAppend()
*
* function: grow in append mode from contiguous region specified ;
*
* parameter:
- * tid - transaction id;
- * ip - file object;
- * xflag - extent flag:
- * xoff - extent offset;
- * maxblocks - max extent length;
- * xlen - extent length (in/out);
- * xaddrp - extent address pointer (in/out):
- * flag -
+ * tid - transaction id;
+ * ip - file object;
+ * xflag - extent flag:
+ * xoff - extent offset;
+ * maxblocks - max extent length;
+ * xlen - extent length (in/out);
+ * xaddrp - extent address pointer (in/out):
+ * flag -
*
* return:
*/
@@ -2460,7 +2459,7 @@ int xtAppend(tid_t tid, /* transaction id */
(ulong) xoff, maxblocks, xlen, (ulong) xaddr);
/*
- * search for the entry location at which to insert:
+ * search for the entry location at which to insert:
*
* xtFastSearch() and xtSearch() both returns (leaf page
* pinned, index at which to insert).
@@ -2482,13 +2481,13 @@ int xtAppend(tid_t tid, /* transaction id */
xlen = min(xlen, (int)(next - xoff));
//insert:
/*
- * insert entry for new extent
+ * insert entry for new extent
*/
xflag |= XAD_NEW;
/*
- * if the leaf page is full, split the page and
- * propagate up the router entry for the new page from split
+ * if the leaf page is full, split the page and
+ * propagate up the router entry for the new page from split
*
* The xtSplitUp() will insert the entry and unpin the leaf page.
*/
@@ -2545,7 +2544,7 @@ int xtAppend(tid_t tid, /* transaction id */
return 0;
/*
- * insert the new entry into the leaf page
+ * insert the new entry into the leaf page
*/
insertLeaf:
/*
@@ -2589,17 +2588,17 @@ int xtAppend(tid_t tid, /* transaction id */
/* - TBD for defragmentaion/reorganization -
*
- * xtDelete()
+ * xtDelete()
*
* function:
- * delete the entry with the specified key.
+ * delete the entry with the specified key.
*
- * N.B.: whole extent of the entry is assumed to be deleted.
+ * N.B.: whole extent of the entry is assumed to be deleted.
*
* parameter:
*
* return:
- * ENOENT: if the entry is not found.
+ * ENOENT: if the entry is not found.
*
* exception:
*/
@@ -2665,10 +2664,10 @@ int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag)
/* - TBD for defragmentaion/reorganization -
*
- * xtDeleteUp()
+ * xtDeleteUp()
*
* function:
- * free empty pages as propagating deletion up the tree
+ * free empty pages as propagating deletion up the tree
*
* parameter:
*
@@ -2815,15 +2814,15 @@ xtDeleteUp(tid_t tid, struct inode *ip,
/*
- * NAME: xtRelocate()
+ * NAME: xtRelocate()
*
- * FUNCTION: relocate xtpage or data extent of regular file;
- * This function is mainly used by defragfs utility.
+ * FUNCTION: relocate xtpage or data extent of regular file;
+ * This function is mainly used by defragfs utility.
*
- * NOTE: This routine does not have the logic to handle
- * uncommitted allocated extent. The caller should call
- * txCommit() to commit all the allocation before call
- * this routine.
+ * NOTE: This routine does not have the logic to handle
+ * uncommitted allocated extent. The caller should call
+ * txCommit() to commit all the allocation before call
+ * this routine.
*/
int
xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
@@ -2865,8 +2864,8 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
xtype, (ulong) xoff, xlen, (ulong) oxaddr, (ulong) nxaddr);
/*
- * 1. get and validate the parent xtpage/xad entry
- * covering the source extent to be relocated;
+ * 1. get and validate the parent xtpage/xad entry
+ * covering the source extent to be relocated;
*/
if (xtype == DATAEXT) {
/* search in leaf entry */
@@ -2910,7 +2909,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
jfs_info("xtRelocate: parent xad entry validated.");
/*
- * 2. relocate the extent
+ * 2. relocate the extent
*/
if (xtype == DATAEXT) {
/* if the extent is allocated-but-not-recorded
@@ -2923,7 +2922,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
XT_PUTPAGE(pmp);
/*
- * cmRelocate()
+ * cmRelocate()
*
* copy target data pages to be relocated;
*
@@ -2945,8 +2944,8 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
pno = offset >> CM_L2BSIZE;
npages = (nbytes + (CM_BSIZE - 1)) >> CM_L2BSIZE;
/*
- npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
- (offset >> CM_L2BSIZE) + 1;
+ npages = ((offset + nbytes - 1) >> CM_L2BSIZE) -
+ (offset >> CM_L2BSIZE) + 1;
*/
sxaddr = oxaddr;
dxaddr = nxaddr;
@@ -2981,7 +2980,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
jfs_info("xtRelocate: target data extent relocated.");
- } else { /* (xtype == XTPAGE) */
+ } else { /* (xtype == XTPAGE) */
/*
* read in the target xtpage from the source extent;
@@ -3026,16 +3025,14 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
*/
if (lmp) {
BT_MARK_DIRTY(lmp, ip);
- tlck =
- txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
+ tlck = txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
lp->header.next = cpu_to_le64(nxaddr);
XT_PUTPAGE(lmp);
}
if (rmp) {
BT_MARK_DIRTY(rmp, ip);
- tlck =
- txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
+ tlck = txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
rp->header.prev = cpu_to_le64(nxaddr);
XT_PUTPAGE(rmp);
}
@@ -3062,7 +3059,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
* scan may be skipped by commit() and logredo();
*/
BT_MARK_DIRTY(mp, ip);
- /* tlckNEW init xtlck->lwm.offset = XTENTRYSTART; */
+ /* tlckNEW init xtlck->lwm.offset = XTENTRYSTART; */
tlck = txLock(tid, ip, mp, tlckXTREE | tlckNEW);
xtlck = (struct xtlock *) & tlck->lock;
@@ -3084,7 +3081,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
}
/*
- * 3. acquire maplock for the source extent to be freed;
+ * 3. acquire maplock for the source extent to be freed;
*
* acquire a maplock saving the src relocated extent address;
* to free of the extent at commit time;
@@ -3105,7 +3102,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
* is no buffer associated with this lock since the buffer
* has been redirected to the target location.
*/
- else /* (xtype == XTPAGE) */
+ else /* (xtype == XTPAGE) */
tlck = txMaplock(tid, ip, tlckMAP | tlckRELOCATE);
pxdlock = (struct pxd_lock *) & tlck->lock;
@@ -3115,7 +3112,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
pxdlock->index = 1;
/*
- * 4. update the parent xad entry for relocation;
+ * 4. update the parent xad entry for relocation;
*
* acquire tlck for the parent entry with XAD_NEW as entry
* update which will write LOG_REDOPAGE and update bmap for
@@ -3143,22 +3140,22 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
/*
- * xtSearchNode()
+ * xtSearchNode()
*
- * function: search for the internal xad entry covering specified extent.
- * This function is mainly used by defragfs utility.
+ * function: search for the internal xad entry covering specified extent.
+ * This function is mainly used by defragfs utility.
*
* parameters:
- * ip - file object;
- * xad - extent to find;
- * cmpp - comparison result:
- * btstack - traverse stack;
- * flag - search process flag;
+ * ip - file object;
+ * xad - extent to find;
+ * cmpp - comparison result:
+ * btstack - traverse stack;
+ * flag - search process flag;
*
* returns:
- * btstack contains (bn, index) of search path traversed to the entry.
- * *cmpp is set to result of comparison with the entry returned.
- * the page containing the entry is pinned at exit.
+ * btstack contains (bn, index) of search path traversed to the entry.
+ * *cmpp is set to result of comparison with the entry returned.
+ * the page containing the entry is pinned at exit.
*/
static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
int *cmpp, struct btstack * btstack, int flag)
@@ -3181,7 +3178,7 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
xaddr = addressXAD(xad);
/*
- * search down tree from root:
+ * search down tree from root:
*
* between two consecutive entries of <Ki, Pi> and <Kj, Pj> of
* internal page, child page Pi contains entry with k, Ki <= K < Kj.
@@ -3217,7 +3214,7 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
XT_CMP(cmp, xoff, &p->xad[index], t64);
if (cmp == 0) {
/*
- * search hit
+ * search hit
*
* verify for exact match;
*/
@@ -3245,7 +3242,7 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
}
/*
- * search miss - non-leaf page:
+ * search miss - non-leaf page:
*
* base is the smallest index with key (Kj) greater than
* search key (K) and may be zero or maxentry index.
@@ -3268,15 +3265,15 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
/*
- * xtRelink()
+ * xtRelink()
*
* function:
- * link around a freed page.
+ * link around a freed page.
*
* Parameter:
- * int tid,
- * struct inode *ip,
- * xtpage_t *p)
+ * int tid,
+ * struct inode *ip,
+ * xtpage_t *p)
*
* returns:
*/
@@ -3338,7 +3335,7 @@ static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * p)
/*
- * xtInitRoot()
+ * xtInitRoot()
*
* initialize file root (inline in inode)
*/
@@ -3385,42 +3382,42 @@ void xtInitRoot(tid_t tid, struct inode *ip)
#define MAX_TRUNCATE_LEAVES 50
/*
- * xtTruncate()
+ * xtTruncate()
*
* function:
- * traverse for truncation logging backward bottom up;
- * terminate at the last extent entry at the current subtree
- * root page covering new down size.
- * truncation may occur within the last extent entry.
+ * traverse for truncation logging backward bottom up;
+ * terminate at the last extent entry at the current subtree
+ * root page covering new down size.
+ * truncation may occur within the last extent entry.
*
* parameter:
- * int tid,
- * struct inode *ip,
- * s64 newsize,
- * int type) {PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
+ * int tid,
+ * struct inode *ip,
+ * s64 newsize,
+ * int type) {PWMAP, PMAP, WMAP; DELETE, TRUNCATE}
*
* return:
*
* note:
- * PWMAP:
- * 1. truncate (non-COMMIT_NOLINK file)
- * by jfs_truncate() or jfs_open(O_TRUNC):
- * xtree is updated;
+ * PWMAP:
+ * 1. truncate (non-COMMIT_NOLINK file)
+ * by jfs_truncate() or jfs_open(O_TRUNC):
+ * xtree is updated;
* 2. truncate index table of directory when last entry removed
- * map update via tlock at commit time;
- * PMAP:
+ * map update via tlock at commit time;
+ * PMAP:
* Call xtTruncate_pmap instead
- * WMAP:
- * 1. remove (free zero link count) on last reference release
- * (pmap has been freed at commit zero link count);
- * 2. truncate (COMMIT_NOLINK file, i.e., tmp file):
- * xtree is updated;
- * map update directly at truncation time;
+ * WMAP:
+ * 1. remove (free zero link count) on last reference release
+ * (pmap has been freed at commit zero link count);
+ * 2. truncate (COMMIT_NOLINK file, i.e., tmp file):
+ * xtree is updated;
+ * map update directly at truncation time;
*
- * if (DELETE)
- * no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
- * else if (TRUNCATE)
- * must write LOG_NOREDOPAGE for deleted index page;
+ * if (DELETE)
+ * no LOG_NOREDOPAGE is required (NOREDOFILE is sufficient);
+ * else if (TRUNCATE)
+ * must write LOG_NOREDOPAGE for deleted index page;
*
* pages may already have been tlocked by anonymous transactions
* during file growth (i.e., write) before truncation;
@@ -3493,7 +3490,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
* retained in the new sized file.
* if type is PMAP, the data and index pages are NOT
* freed, and the data and index blocks are NOT freed
- * from working map.
+ * from working map.
* (this will allow continued access of data/index of
* temporary file (zerolink count file truncated to zero-length)).
*/
@@ -3542,7 +3539,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
goto getChild;
/*
- * leaf page
+ * leaf page
*/
freed = 0;
@@ -3916,7 +3913,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
}
/*
- * internal page: go down to child page of current entry
+ * internal page: go down to child page of current entry
*/
getChild:
/* save current parent entry for the child page */
@@ -3965,7 +3962,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
/*
- * xtTruncate_pmap()
+ * xtTruncate_pmap()
*
* function:
* Perform truncate to zero lenghth for deleted file, leaving the
@@ -3974,9 +3971,9 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
* is committed to disk.
*
* parameter:
- * tid_t tid,
- * struct inode *ip,
- * s64 committed_size)
+ * tid_t tid,
+ * struct inode *ip,
+ * s64 committed_size)
*
* return: new committed size
*
@@ -4050,7 +4047,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
}
/*
- * leaf page
+ * leaf page
*/
if (++locked_leaves > MAX_TRUNCATE_LEAVES) {
@@ -4062,7 +4059,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
xoff = offsetXAD(xad);
xlen = lengthXAD(xad);
XT_PUTPAGE(mp);
- return (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
+ return (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
}
tlck = txLock(tid, ip, mp, tlckXTREE);
tlck->type = tlckXTREE | tlckFREE;
@@ -4099,8 +4096,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
*/
tlck = txLock(tid, ip, mp, tlckXTREE);
xtlck = (struct xtlock *) & tlck->lock;
- xtlck->hwm.offset =
- le16_to_cpu(p->header.nextindex) - 1;
+ xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1;
tlck->type = tlckXTREE | tlckFREE;
XT_PUTPAGE(mp);
@@ -4118,7 +4114,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
else
index--;
/*
- * internal page: go down to child page of current entry
+ * internal page: go down to child page of current entry
*/
getChild:
/* save current parent entry for the child page */
diff --git a/fs/jfs/jfs_xtree.h b/fs/jfs/jfs_xtree.h
index 164f6f2b101..70815c8a3d6 100644
--- a/fs/jfs/jfs_xtree.h
+++ b/fs/jfs/jfs_xtree.h
@@ -19,14 +19,14 @@
#define _H_JFS_XTREE
/*
- * jfs_xtree.h: extent allocation descriptor B+-tree manager
+ * jfs_xtree.h: extent allocation descriptor B+-tree manager
*/
#include "jfs_btree.h"
/*
- * extent allocation descriptor (xad)
+ * extent allocation descriptor (xad)
*/
typedef struct xad {
unsigned flag:8; /* 1: flag */
@@ -38,30 +38,30 @@ typedef struct xad {
__le32 addr2; /* 4: address in unit of fsblksize */
} xad_t; /* (16) */
-#define MAXXLEN ((1 << 24) - 1)
+#define MAXXLEN ((1 << 24) - 1)
-#define XTSLOTSIZE 16
-#define L2XTSLOTSIZE 4
+#define XTSLOTSIZE 16
+#define L2XTSLOTSIZE 4
/* xad_t field construction */
#define XADoffset(xad, offset64)\
{\
- (xad)->off1 = ((u64)offset64) >> 32;\
- (xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\
+ (xad)->off1 = ((u64)offset64) >> 32;\
+ (xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\
}
#define XADaddress(xad, address64)\
{\
- (xad)->addr1 = ((u64)address64) >> 32;\
- (xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
+ (xad)->addr1 = ((u64)address64) >> 32;\
+ (xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\
}
-#define XADlength(xad, length32) (xad)->len = __cpu_to_le24(length32)
+#define XADlength(xad, length32) (xad)->len = __cpu_to_le24(length32)
/* xad_t field extraction */
#define offsetXAD(xad)\
- ( ((s64)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2))
+ ( ((s64)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2))
#define addressXAD(xad)\
- ( ((s64)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2))
-#define lengthXAD(xad) __le24_to_cpu((xad)->len)
+ ( ((s64)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2))
+#define lengthXAD(xad) __le24_to_cpu((xad)->len)
/* xad list */
struct xadlist {
@@ -71,22 +71,22 @@ struct xadlist {
};
/* xad_t flags */
-#define XAD_NEW 0x01 /* new */
-#define XAD_EXTENDED 0x02 /* extended */
-#define XAD_COMPRESSED 0x04 /* compressed with recorded length */
+#define XAD_NEW 0x01 /* new */
+#define XAD_EXTENDED 0x02 /* extended */
+#define XAD_COMPRESSED 0x04 /* compressed with recorded length */
#define XAD_NOTRECORDED 0x08 /* allocated but not recorded */
-#define XAD_COW 0x10 /* copy-on-write */
+#define XAD_COW 0x10 /* copy-on-write */
/* possible values for maxentry */
-#define XTROOTINITSLOT_DIR 6
-#define XTROOTINITSLOT 10
-#define XTROOTMAXSLOT 18
-#define XTPAGEMAXSLOT 256
-#define XTENTRYSTART 2
+#define XTROOTINITSLOT_DIR 6
+#define XTROOTINITSLOT 10
+#define XTROOTMAXSLOT 18
+#define XTPAGEMAXSLOT 256
+#define XTENTRYSTART 2
/*
- * xtree page:
+ * xtree page:
*/
typedef union {
struct xtheader {
@@ -106,7 +106,7 @@ typedef union {
} xtpage_t;
/*
- * external declaration
+ * external declaration
*/
extern int xtLookup(struct inode *ip, s64 lstart, s64 llen,
int *pflag, s64 * paddr, int *plen, int flag);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 41c20477126..25161c4121e 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -328,7 +328,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
* dentry - child directory dentry
*
* RETURN: -EINVAL - if name is . or ..
- * -EINVAL - if . or .. exist but are invalid.
+ * -EINVAL - if . or .. exist but are invalid.
* errors from subroutines
*
* note:
@@ -517,7 +517,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
inode_dec_link_count(ip);
/*
- * commit zero link count object
+ * commit zero link count object
*/
if (ip->i_nlink == 0) {
assert(!test_cflag(COMMIT_Nolink, ip));
@@ -596,7 +596,7 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
/*
* NAME: commitZeroLink()
*
- * FUNCTION: for non-directory, called by jfs_remove(),
+ * FUNCTION: for non-directory, called by jfs_remove(),
* truncate a regular file, directory or symbolic
* link to zero length. return 0 if type is not
* one of these.
@@ -676,7 +676,7 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
/*
* NAME: jfs_free_zero_link()
*
- * FUNCTION: for non-directory, called by iClose(),
+ * FUNCTION: for non-directory, called by iClose(),
* free resources of a file from cache and WORKING map
* for a file previously committed with zero link count
* while associated with a pager object,
@@ -855,12 +855,12 @@ static int jfs_link(struct dentry *old_dentry,
* NAME: jfs_symlink(dip, dentry, name)
*
* FUNCTION: creates a symbolic link to <symlink> by name <name>
- * in directory <dip>
+ * in directory <dip>
*
- * PARAMETER: dip - parent directory vnode
- * dentry - dentry of symbolic link
- * name - the path name of the existing object
- * that will be the source of the link
+ * PARAMETER: dip - parent directory vnode
+ * dentry - dentry of symbolic link
+ * name - the path name of the existing object
+ * that will be the source of the link
*
* RETURN: errors from subroutines
*
@@ -1052,9 +1052,9 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
/*
- * NAME: jfs_rename
+ * NAME: jfs_rename
*
- * FUNCTION: rename a file or directory
+ * FUNCTION: rename a file or directory
*/
static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
@@ -1331,9 +1331,9 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
/*
- * NAME: jfs_mknod
+ * NAME: jfs_mknod
*
- * FUNCTION: Create a special file (device)
+ * FUNCTION: Create a special file (device)
*/
static int jfs_mknod(struct inode *dir, struct dentry *dentry,
int mode, dev_t rdev)
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 79d625f3f73..71984ee9534 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -29,17 +29,17 @@
#include "jfs_txnmgr.h"
#include "jfs_debug.h"
-#define BITSPERPAGE (PSIZE << 3)
-#define L2MEGABYTE 20
-#define MEGABYTE (1 << L2MEGABYTE)
-#define MEGABYTE32 (MEGABYTE << 5)
+#define BITSPERPAGE (PSIZE << 3)
+#define L2MEGABYTE 20
+#define MEGABYTE (1 << L2MEGABYTE)
+#define MEGABYTE32 (MEGABYTE << 5)
/* convert block number to bmap file page number */
#define BLKTODMAPN(b)\
- (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)
+ (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1)
/*
- * jfs_extendfs()
+ * jfs_extendfs()
*
* function: extend file system;
*
@@ -48,9 +48,9 @@
* workspace space
*
* input:
- * new LVSize: in LV blocks (required)
- * new LogSize: in LV blocks (optional)
- * new FSSize: in LV blocks (optional)
+ * new LVSize: in LV blocks (required)
+ * new LogSize: in LV blocks (optional)
+ * new FSSize: in LV blocks (optional)
*
* new configuration:
* 1. set new LogSize as specified or default from new LVSize;
@@ -125,8 +125,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
}
/*
- * reconfigure LV spaces
- * ---------------------
+ * reconfigure LV spaces
+ * ---------------------
*
* validate new size, or, if not specified, determine new size
*/
@@ -198,7 +198,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
log_formatted = 1;
}
/*
- * quiesce file system
+ * quiesce file system
*
* (prepare to move the inline log and to prevent map update)
*
@@ -270,8 +270,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
}
/*
- * extend block allocation map
- * ---------------------------
+ * extend block allocation map
+ * ---------------------------
*
* extendfs() for new extension, retry after crash recovery;
*
@@ -283,7 +283,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
* s_size: aggregate size in physical blocks;
*/
/*
- * compute the new block allocation map configuration
+ * compute the new block allocation map configuration
*
* map dinode:
* di_size: map file size in byte;
@@ -301,7 +301,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
newNpages = BLKTODMAPN(t64) + 1;
/*
- * extend map from current map (WITHOUT growing mapfile)
+ * extend map from current map (WITHOUT growing mapfile)
*
* map new extension with unmapped part of the last partial
* dmap page, if applicable, and extra page(s) allocated
@@ -341,8 +341,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
XSize -= nblocks;
/*
- * grow map file to cover remaining extension
- * and/or one extra dmap page for next extendfs();
+ * grow map file to cover remaining extension
+ * and/or one extra dmap page for next extendfs();
*
* allocate new map pages and its backing blocks, and
* update map file xtree
@@ -422,8 +422,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
dbFinalizeBmap(ipbmap);
/*
- * update inode allocation map
- * ---------------------------
+ * update inode allocation map
+ * ---------------------------
*
* move iag lists from old to new iag;
* agstart field is not updated for logredo() to reconstruct
@@ -442,8 +442,8 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
}
/*
- * finalize
- * --------
+ * finalize
+ * --------
*
* extension is committed when on-disk super block is
* updated with new descriptors: logredo will recover
@@ -480,7 +480,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
diFreeSpecial(ipbmap2);
/*
- * update superblock
+ * update superblock
*/
if ((rc = readSuper(sb, &bh)))
goto error_out;
@@ -530,7 +530,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
resume:
/*
- * resume file system transactions
+ * resume file system transactions
*/
txResume(sb);
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index b753ba21645..b2375f0774b 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -63,9 +63,9 @@
*
* On-disk:
*
- * FEALISTs are stored on disk using blocks allocated by dbAlloc() and
- * written directly. An EA list may be in-lined in the inode if there is
- * sufficient room available.
+ * FEALISTs are stored on disk using blocks allocated by dbAlloc() and
+ * written directly. An EA list may be in-lined in the inode if there is
+ * sufficient room available.
*/
struct ea_buffer {
@@ -590,7 +590,8 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
size_check:
if (EALIST_SIZE(ea_buf->xattr) != ea_size) {
printk(KERN_ERR "ea_get: invalid extended attribute\n");
- dump_mem("xattr", ea_buf->xattr, ea_size);
+ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1,
+ ea_buf->xattr, ea_size, 1);
ea_release(inode, ea_buf);
rc = -EIO;
goto clean_up;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 96070bff93f..572601e98dc 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -44,9 +44,8 @@ static struct nsm_handle * nsm_find(const struct sockaddr_in *sin,
*/
static struct nlm_host *
nlm_lookup_host(int server, const struct sockaddr_in *sin,
- int proto, int version,
- const char *hostname,
- int hostname_len)
+ int proto, int version, const char *hostname,
+ int hostname_len, const struct sockaddr_in *ssin)
{
struct hlist_head *chain;
struct hlist_node *pos;
@@ -54,7 +53,9 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
struct nsm_handle *nsm = NULL;
int hash;
- dprintk("lockd: nlm_lookup_host(%u.%u.%u.%u, p=%d, v=%d, my role=%s, name=%.*s)\n",
+ dprintk("lockd: nlm_lookup_host("NIPQUAD_FMT"->"NIPQUAD_FMT
+ ", p=%d, v=%d, my role=%s, name=%.*s)\n",
+ NIPQUAD(ssin->sin_addr.s_addr),
NIPQUAD(sin->sin_addr.s_addr), proto, version,
server? "server" : "client",
hostname_len,
@@ -91,6 +92,8 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
continue;
if (host->h_server != server)
continue;
+ if (!nlm_cmp_addr(&host->h_saddr, ssin))
+ continue;
/* Move to head of hash chain. */
hlist_del(&host->h_hash);
@@ -118,6 +121,7 @@ nlm_lookup_host(int server, const struct sockaddr_in *sin,
host->h_name = nsm->sm_name;
host->h_addr = *sin;
host->h_addr.sin_port = 0; /* ouch! */
+ host->h_saddr = *ssin;
host->h_version = version;
host->h_proto = proto;
host->h_rpcclnt = NULL;
@@ -161,15 +165,9 @@ nlm_destroy_host(struct nlm_host *host)
*/
nsm_unmonitor(host);
- if ((clnt = host->h_rpcclnt) != NULL) {
- if (atomic_read(&clnt->cl_users)) {
- printk(KERN_WARNING
- "lockd: active RPC handle\n");
- clnt->cl_dead = 1;
- } else {
- rpc_destroy_client(host->h_rpcclnt);
- }
- }
+ clnt = host->h_rpcclnt;
+ if (clnt != NULL)
+ rpc_shutdown_client(clnt);
kfree(host);
}
@@ -180,8 +178,10 @@ struct nlm_host *
nlmclnt_lookup_host(const struct sockaddr_in *sin, int proto, int version,
const char *hostname, int hostname_len)
{
+ struct sockaddr_in ssin = {0};
+
return nlm_lookup_host(0, sin, proto, version,
- hostname, hostname_len);
+ hostname, hostname_len, &ssin);
}
/*
@@ -191,9 +191,12 @@ struct nlm_host *
nlmsvc_lookup_host(struct svc_rqst *rqstp,
const char *hostname, int hostname_len)
{
+ struct sockaddr_in ssin = {0};
+
+ ssin.sin_addr = rqstp->rq_daddr.addr;
return nlm_lookup_host(1, svc_addr_in(rqstp),
rqstp->rq_prot, rqstp->rq_vers,
- hostname, hostname_len);
+ hostname, hostname_len, &ssin);
}
/*
@@ -204,8 +207,9 @@ nlm_bind_host(struct nlm_host *host)
{
struct rpc_clnt *clnt;
- dprintk("lockd: nlm_bind_host(%08x)\n",
- (unsigned)ntohl(host->h_addr.sin_addr.s_addr));
+ dprintk("lockd: nlm_bind_host("NIPQUAD_FMT"->"NIPQUAD_FMT")\n",
+ NIPQUAD(host->h_saddr.sin_addr),
+ NIPQUAD(host->h_addr.sin_addr));
/* Lock host handle */
mutex_lock(&host->h_mutex);
@@ -232,6 +236,7 @@ nlm_bind_host(struct nlm_host *host)
.protocol = host->h_proto,
.address = (struct sockaddr *)&host->h_addr,
.addrsize = sizeof(host->h_addr),
+ .saddress = (struct sockaddr *)&host->h_saddr,
.timeout = &timeparms,
.servername = host->h_name,
.program = &nlm_program,
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 2102e2d0134..3353ed8421a 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -61,6 +61,7 @@ nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res)
status);
else
status = 0;
+ rpc_shutdown_client(clnt);
out:
return status;
}
@@ -138,7 +139,6 @@ nsm_create(void)
.program = &nsm_program,
.version = SM_VERSION,
.authflavor = RPC_AUTH_NULL,
- .flags = (RPC_CLNT_CREATE_ONESHOT),
};
return rpc_create(&args);
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 126b1bf02c0..26809325469 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -123,9 +123,6 @@ lockd(struct svc_rqst *rqstp)
/* Process request with signals blocked, but allow SIGKILL. */
allow_signal(SIGKILL);
- /* kick rpciod */
- rpciod_up();
-
dprintk("NFS locking service started (ver " LOCKD_VERSION ").\n");
if (!nlm_timeout)
@@ -202,9 +199,6 @@ lockd(struct svc_rqst *rqstp)
/* Exit the RPC thread */
svc_exit_thread(rqstp);
- /* release rpciod */
- rpciod_down();
-
/* Release module */
unlock_kernel();
module_put_and_exit(0);
diff --git a/fs/minix/file.c b/fs/minix/file.c
index f92baa1d757..17765f697e5 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -23,7 +23,7 @@ const struct file_operations minix_file_operations = {
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = minix_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations minix_file_inode_operations = {
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index f4580b44eef..b55cb236cf7 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -6,8 +6,8 @@ obj-$(CONFIG_NFS_FS) += nfs.o
nfs-y := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \
pagelist.o proc.o read.o symlink.o unlink.o \
- write.o namespace.o
-nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
+ write.o namespace.o mount_clnt.o
+nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 881fa490092..ccb455053ee 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -102,19 +102,10 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
int nfsversion)
{
struct nfs_client *clp;
- int error;
if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
goto error_0;
- error = rpciod_up();
- if (error < 0) {
- dprintk("%s: couldn't start rpciod! Error = %d\n",
- __FUNCTION__, error);
- goto error_1;
- }
- __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
-
if (nfsversion == 4) {
if (nfs_callback_up() < 0)
goto error_2;
@@ -139,8 +130,6 @@ static struct nfs_client *nfs_alloc_client(const char *hostname,
#ifdef CONFIG_NFS_V4
init_rwsem(&clp->cl_sem);
INIT_LIST_HEAD(&clp->cl_delegations);
- INIT_LIST_HEAD(&clp->cl_state_owners);
- INIT_LIST_HEAD(&clp->cl_unused);
spin_lock_init(&clp->cl_lock);
INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
@@ -154,9 +143,6 @@ error_3:
if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
nfs_callback_down();
error_2:
- rpciod_down();
- __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state);
-error_1:
kfree(clp);
error_0:
return NULL;
@@ -167,16 +153,7 @@ static void nfs4_shutdown_client(struct nfs_client *clp)
#ifdef CONFIG_NFS_V4
if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state))
nfs4_kill_renewd(clp);
- while (!list_empty(&clp->cl_unused)) {
- struct nfs4_state_owner *sp;
-
- sp = list_entry(clp->cl_unused.next,
- struct nfs4_state_owner,
- so_list);
- list_del(&sp->so_list);
- kfree(sp);
- }
- BUG_ON(!list_empty(&clp->cl_state_owners));
+ BUG_ON(!RB_EMPTY_ROOT(&clp->cl_state_owners));
if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state))
nfs_idmap_delete(clp);
#endif
@@ -198,9 +175,6 @@ static void nfs_free_client(struct nfs_client *clp)
if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
nfs_callback_down();
- if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state))
- rpciod_down();
-
kfree(clp->cl_hostname);
kfree(clp);
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 7f37d1bea83..20ac403469a 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -27,6 +27,13 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
kfree(delegation);
}
+static void nfs_free_delegation_callback(struct rcu_head *head)
+{
+ struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu);
+
+ nfs_free_delegation(delegation);
+}
+
static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_state *state)
{
struct inode *inode = state->inode;
@@ -57,7 +64,7 @@ out_err:
return status;
}
-static void nfs_delegation_claim_opens(struct inode *inode)
+static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
{
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_open_context *ctx;
@@ -72,9 +79,11 @@ again:
continue;
if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
continue;
+ if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
+ continue;
get_nfs_open_context(ctx);
spin_unlock(&inode->i_lock);
- err = nfs4_open_delegation_recall(ctx->dentry, state);
+ err = nfs4_open_delegation_recall(ctx, state, stateid);
if (err >= 0)
err = nfs_delegation_claim_locks(ctx, state);
put_nfs_open_context(ctx);
@@ -115,10 +124,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
struct nfs_delegation *delegation;
int status = 0;
- /* Ensure we first revalidate the attributes and page cache! */
- if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR)))
- __nfs_revalidate_inode(NFS_SERVER(inode), inode);
-
delegation = kmalloc(sizeof(*delegation), GFP_KERNEL);
if (delegation == NULL)
return -ENOMEM;
@@ -131,10 +136,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
delegation->inode = inode;
spin_lock(&clp->cl_lock);
- if (nfsi->delegation == NULL) {
- list_add(&delegation->super_list, &clp->cl_delegations);
- nfsi->delegation = delegation;
+ if (rcu_dereference(nfsi->delegation) == NULL) {
+ list_add_rcu(&delegation->super_list, &clp->cl_delegations);
nfsi->delegation_state = delegation->type;
+ rcu_assign_pointer(nfsi->delegation, delegation);
delegation = NULL;
} else {
if (memcmp(&delegation->stateid, &nfsi->delegation->stateid,
@@ -145,6 +150,12 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
status = -EIO;
}
}
+
+ /* Ensure we revalidate the attributes and page cache! */
+ spin_lock(&inode->i_lock);
+ nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
+ spin_unlock(&inode->i_lock);
+
spin_unlock(&clp->cl_lock);
kfree(delegation);
return status;
@@ -155,7 +166,7 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
int res = 0;
res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
- nfs_free_delegation(delegation);
+ call_rcu(&delegation->rcu, nfs_free_delegation_callback);
return res;
}
@@ -170,33 +181,55 @@ static void nfs_msync_inode(struct inode *inode)
/*
* Basic procedure for returning a delegation to the server
*/
-int __nfs_inode_return_delegation(struct inode *inode)
+static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
{
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
struct nfs_inode *nfsi = NFS_I(inode);
- struct nfs_delegation *delegation;
- int res = 0;
nfs_msync_inode(inode);
down_read(&clp->cl_sem);
/* Guard against new delegated open calls */
down_write(&nfsi->rwsem);
- spin_lock(&clp->cl_lock);
- delegation = nfsi->delegation;
- if (delegation != NULL) {
- list_del_init(&delegation->super_list);
- nfsi->delegation = NULL;
- nfsi->delegation_state = 0;
- }
- spin_unlock(&clp->cl_lock);
- nfs_delegation_claim_opens(inode);
+ nfs_delegation_claim_opens(inode, &delegation->stateid);
up_write(&nfsi->rwsem);
up_read(&clp->cl_sem);
nfs_msync_inode(inode);
- if (delegation != NULL)
- res = nfs_do_return_delegation(inode, delegation);
- return res;
+ return nfs_do_return_delegation(inode, delegation);
+}
+
+static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
+{
+ struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
+
+ if (delegation == NULL)
+ goto nomatch;
+ if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
+ sizeof(delegation->stateid.data)) != 0)
+ goto nomatch;
+ list_del_rcu(&delegation->super_list);
+ nfsi->delegation_state = 0;
+ rcu_assign_pointer(nfsi->delegation, NULL);
+ return delegation;
+nomatch:
+ return NULL;
+}
+
+int nfs_inode_return_delegation(struct inode *inode)
+{
+ struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+ struct nfs_inode *nfsi = NFS_I(inode);
+ struct nfs_delegation *delegation;
+ int err = 0;
+
+ if (rcu_dereference(nfsi->delegation) != NULL) {
+ spin_lock(&clp->cl_lock);
+ delegation = nfs_detach_delegation_locked(nfsi, NULL);
+ spin_unlock(&clp->cl_lock);
+ if (delegation != NULL)
+ err = __nfs_inode_return_delegation(inode, delegation);
+ }
+ return err;
}
/*
@@ -211,19 +244,23 @@ void nfs_return_all_delegations(struct super_block *sb)
if (clp == NULL)
return;
restart:
- spin_lock(&clp->cl_lock);
- list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
if (delegation->inode->i_sb != sb)
continue;
inode = igrab(delegation->inode);
if (inode == NULL)
continue;
+ spin_lock(&clp->cl_lock);
+ delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
spin_unlock(&clp->cl_lock);
- nfs_inode_return_delegation(inode);
+ rcu_read_unlock();
+ if (delegation != NULL)
+ __nfs_inode_return_delegation(inode, delegation);
iput(inode);
goto restart;
}
- spin_unlock(&clp->cl_lock);
+ rcu_read_unlock();
}
static int nfs_do_expire_all_delegations(void *ptr)
@@ -234,22 +271,26 @@ static int nfs_do_expire_all_delegations(void *ptr)
allow_signal(SIGKILL);
restart:
- spin_lock(&clp->cl_lock);
if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
goto out;
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
goto out;
- list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
inode = igrab(delegation->inode);
if (inode == NULL)
continue;
+ spin_lock(&clp->cl_lock);
+ delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
spin_unlock(&clp->cl_lock);
- nfs_inode_return_delegation(inode);
+ rcu_read_unlock();
+ if (delegation)
+ __nfs_inode_return_delegation(inode, delegation);
iput(inode);
goto restart;
}
+ rcu_read_unlock();
out:
- spin_unlock(&clp->cl_lock);
nfs_put_client(clp);
module_put_and_exit(0);
}
@@ -280,17 +321,21 @@ void nfs_handle_cb_pathdown(struct nfs_client *clp)
if (clp == NULL)
return;
restart:
- spin_lock(&clp->cl_lock);
- list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
inode = igrab(delegation->inode);
if (inode == NULL)
continue;
+ spin_lock(&clp->cl_lock);
+ delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
spin_unlock(&clp->cl_lock);
- nfs_inode_return_delegation(inode);
+ rcu_read_unlock();
+ if (delegation != NULL)
+ __nfs_inode_return_delegation(inode, delegation);
iput(inode);
goto restart;
}
- spin_unlock(&clp->cl_lock);
+ rcu_read_unlock();
}
struct recall_threadargs {
@@ -316,21 +361,14 @@ static int recall_thread(void *data)
down_read(&clp->cl_sem);
down_write(&nfsi->rwsem);
spin_lock(&clp->cl_lock);
- delegation = nfsi->delegation;
- if (delegation != NULL && memcmp(delegation->stateid.data,
- args->stateid->data,
- sizeof(delegation->stateid.data)) == 0) {
- list_del_init(&delegation->super_list);
- nfsi->delegation = NULL;
- nfsi->delegation_state = 0;
+ delegation = nfs_detach_delegation_locked(nfsi, args->stateid);
+ if (delegation != NULL)
args->result = 0;
- } else {
- delegation = NULL;
+ else
args->result = -ENOENT;
- }
spin_unlock(&clp->cl_lock);
complete(&args->started);
- nfs_delegation_claim_opens(inode);
+ nfs_delegation_claim_opens(inode, args->stateid);
up_write(&nfsi->rwsem);
up_read(&clp->cl_sem);
nfs_msync_inode(inode);
@@ -371,14 +409,14 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
{
struct nfs_delegation *delegation;
struct inode *res = NULL;
- spin_lock(&clp->cl_lock);
- list_for_each_entry(delegation, &clp->cl_delegations, super_list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
res = igrab(delegation->inode);
break;
}
}
- spin_unlock(&clp->cl_lock);
+ rcu_read_unlock();
return res;
}
@@ -388,10 +426,10 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
void nfs_delegation_mark_reclaim(struct nfs_client *clp)
{
struct nfs_delegation *delegation;
- spin_lock(&clp->cl_lock);
- list_for_each_entry(delegation, &clp->cl_delegations, super_list)
+ rcu_read_lock();
+ list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
delegation->flags |= NFS_DELEGATION_NEED_RECLAIM;
- spin_unlock(&clp->cl_lock);
+ rcu_read_unlock();
}
/*
@@ -399,39 +437,35 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
*/
void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
{
- struct nfs_delegation *delegation, *n;
- LIST_HEAD(head);
- spin_lock(&clp->cl_lock);
- list_for_each_entry_safe(delegation, n, &clp->cl_delegations, super_list) {
+ struct nfs_delegation *delegation;
+restart:
+ rcu_read_lock();
+ list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0)
continue;
- list_move(&delegation->super_list, &head);
- NFS_I(delegation->inode)->delegation = NULL;
- NFS_I(delegation->inode)->delegation_state = 0;
- }
- spin_unlock(&clp->cl_lock);
- while(!list_empty(&head)) {
- delegation = list_entry(head.next, struct nfs_delegation, super_list);
- list_del(&delegation->super_list);
- nfs_free_delegation(delegation);
+ spin_lock(&clp->cl_lock);
+ delegation = nfs_detach_delegation_locked(NFS_I(delegation->inode), NULL);
+ spin_unlock(&clp->cl_lock);
+ rcu_read_unlock();
+ if (delegation != NULL)
+ call_rcu(&delegation->rcu, nfs_free_delegation_callback);
+ goto restart;
}
+ rcu_read_unlock();
}
int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
{
- struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_delegation *delegation;
- int res = 0;
+ int ret = 0;
- if (nfsi->delegation_state == 0)
- return 0;
- spin_lock(&clp->cl_lock);
- delegation = nfsi->delegation;
+ rcu_read_lock();
+ delegation = rcu_dereference(nfsi->delegation);
if (delegation != NULL) {
memcpy(dst->data, delegation->stateid.data, sizeof(dst->data));
- res = 1;
+ ret = 1;
}
- spin_unlock(&clp->cl_lock);
- return res;
+ rcu_read_unlock();
+ return ret;
}
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 2cfd4b24c7f..5874ce7fdba 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -22,11 +22,12 @@ struct nfs_delegation {
long flags;
loff_t maxsize;
__u64 change_attr;
+ struct rcu_head rcu;
};
int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
-int __nfs_inode_return_delegation(struct inode *inode);
+int nfs_inode_return_delegation(struct inode *inode);
int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid);
struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
@@ -39,27 +40,24 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
/* NFSv4 delegation-related procedures */
int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid);
-int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state);
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid);
int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl);
int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode);
static inline int nfs_have_delegation(struct inode *inode, int flags)
{
+ struct nfs_delegation *delegation;
+ int ret = 0;
+
flags &= FMODE_READ|FMODE_WRITE;
- smp_rmb();
- if ((NFS_I(inode)->delegation_state & flags) == flags)
- return 1;
- return 0;
+ rcu_read_lock();
+ delegation = rcu_dereference(NFS_I(inode)->delegation);
+ if (delegation != NULL && (delegation->type & flags) == flags)
+ ret = 1;
+ rcu_read_unlock();
+ return ret;
}
-static inline int nfs_inode_return_delegation(struct inode *inode)
-{
- int err = 0;
-
- if (NFS_I(inode)->delegation != NULL)
- err = __nfs_inode_return_delegation(inode);
- return err;
-}
#else
static inline int nfs_have_delegation(struct inode *inode, int flags)
{
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index c27258b5d3e..322141f4ab4 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -897,14 +897,13 @@ int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
return (nd->intent.open.flags & O_EXCL) != 0;
}
-static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir,
- struct nfs_fh *fh, struct nfs_fattr *fattr)
+static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
{
struct nfs_server *server = NFS_SERVER(dir);
if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
- /* Revalidate fsid on root dir */
- return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode);
+ /* Revalidate fsid using the parent directory */
+ return __nfs_revalidate_inode(server, dir);
return 0;
}
@@ -946,7 +945,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
res = ERR_PTR(error);
goto out_unlock;
}
- error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr);
+ error = nfs_reval_fsid(dir, &fattr);
if (error < 0) {
res = ERR_PTR(error);
goto out_unlock;
@@ -1244,7 +1243,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
- if (nd && (nd->flags & LOOKUP_CREATE))
+ if ((nd->flags & LOOKUP_CREATE) != 0)
open_flags = nd->intent.open.flags;
lock_kernel();
@@ -1535,7 +1534,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
lock_kernel();
- page = alloc_page(GFP_KERNEL);
+ page = alloc_page(GFP_HIGHUSER);
if (!page) {
unlock_kernel();
return -ENOMEM;
@@ -1744,8 +1743,8 @@ int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
struct nfs_inode *nfsi;
struct nfs_access_entry *cache;
- spin_lock(&nfs_access_lru_lock);
restart:
+ spin_lock(&nfs_access_lru_lock);
list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
struct inode *inode;
@@ -1770,6 +1769,7 @@ remove_lru_entry:
clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags);
}
spin_unlock(&inode->i_lock);
+ spin_unlock(&nfs_access_lru_lock);
iput(inode);
goto restart;
}
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 00eee87510f..a5c82b6f3b4 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -266,7 +266,7 @@ static const struct rpc_call_ops nfs_read_direct_ops = {
static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos)
{
struct nfs_open_context *ctx = dreq->ctx;
- struct inode *inode = ctx->dentry->d_inode;
+ struct inode *inode = ctx->path.dentry->d_inode;
size_t rsize = NFS_SERVER(inode)->rsize;
unsigned int pgbase;
int result;
@@ -295,9 +295,14 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo
break;
}
if ((unsigned)result < data->npages) {
- nfs_direct_release_pages(data->pagevec, result);
- nfs_readdata_release(data);
- break;
+ bytes = result * PAGE_SIZE;
+ if (bytes <= pgbase) {
+ nfs_direct_release_pages(data->pagevec, result);
+ nfs_readdata_release(data);
+ break;
+ }
+ bytes -= pgbase;
+ data->npages = result;
}
get_dreq(dreq);
@@ -601,7 +606,7 @@ static const struct rpc_call_ops nfs_write_direct_ops = {
static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned long user_addr, size_t count, loff_t pos, int sync)
{
struct nfs_open_context *ctx = dreq->ctx;
- struct inode *inode = ctx->dentry->d_inode;
+ struct inode *inode = ctx->path.dentry->d_inode;
size_t wsize = NFS_SERVER(inode)->wsize;
unsigned int pgbase;
int result;
@@ -630,9 +635,14 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l
break;
}
if ((unsigned)result < data->npages) {
- nfs_direct_release_pages(data->pagevec, result);
- nfs_writedata_release(data);
- break;
+ bytes = result * PAGE_SIZE;
+ if (bytes <= pgbase) {
+ nfs_direct_release_pages(data->pagevec, result);
+ nfs_writedata_release(data);
+ break;
+ }
+ bytes -= pgbase;
+ data->npages = result;
}
get_dreq(dreq);
@@ -763,10 +773,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
(unsigned long) count, (long long) pos);
if (nr_segs != 1)
- return -EINVAL;
-
- if (count < 0)
goto out;
+
retval = -EFAULT;
if (!access_ok(VERIFY_WRITE, buf, count))
goto out;
@@ -814,7 +822,7 @@ out:
ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t pos)
{
- ssize_t retval;
+ ssize_t retval = -EINVAL;
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
/* XXX: temporary */
@@ -827,7 +835,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
(unsigned long) count, (long long) pos);
if (nr_segs != 1)
- return -EINVAL;
+ goto out;
retval = generic_write_checks(file, &pos, &count, 0);
if (retval)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 9eb8eb4e4a0..8689b736fdd 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -41,7 +41,9 @@ static int nfs_file_open(struct inode *, struct file *);
static int nfs_file_release(struct inode *, struct file *);
static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
static int nfs_file_mmap(struct file *, struct vm_area_struct *);
-static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
+static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t count, unsigned int flags);
static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
unsigned long nr_segs, loff_t pos);
static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
@@ -65,7 +67,7 @@ const struct file_operations nfs_file_operations = {
.fsync = nfs_fsync,
.lock = nfs_lock,
.flock = nfs_flock,
- .sendfile = nfs_file_sendfile,
+ .splice_read = nfs_file_splice_read,
.check_flags = nfs_check_flags,
};
@@ -224,20 +226,21 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov,
}
static ssize_t
-nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
- read_actor_t actor, void *target)
+nfs_file_splice_read(struct file *filp, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t count,
+ unsigned int flags)
{
struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = dentry->d_inode;
ssize_t res;
- dfprintk(VFS, "nfs: sendfile(%s/%s, %lu@%Lu)\n",
+ dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long long) *ppos);
res = nfs_revalidate_mapping(inode, filp->f_mapping);
if (!res)
- res = generic_file_sendfile(filp, ppos, count, actor, target);
+ res = generic_file_splice_read(filp, ppos, pipe, count, flags);
return res;
}
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index bd9f5a83659..3d9fccf4ef9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -461,14 +461,14 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
if (ctx != NULL) {
- atomic_set(&ctx->count, 1);
- ctx->dentry = dget(dentry);
- ctx->vfsmnt = mntget(mnt);
+ ctx->path.dentry = dget(dentry);
+ ctx->path.mnt = mntget(mnt);
ctx->cred = get_rpccred(cred);
ctx->state = NULL;
ctx->lockowner = current->files;
ctx->error = 0;
ctx->dir_cookie = 0;
+ kref_init(&ctx->kref);
}
return ctx;
}
@@ -476,27 +476,33 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
{
if (ctx != NULL)
- atomic_inc(&ctx->count);
+ kref_get(&ctx->kref);
return ctx;
}
-void put_nfs_open_context(struct nfs_open_context *ctx)
+static void nfs_free_open_context(struct kref *kref)
{
- if (atomic_dec_and_test(&ctx->count)) {
- if (!list_empty(&ctx->list)) {
- struct inode *inode = ctx->dentry->d_inode;
- spin_lock(&inode->i_lock);
- list_del(&ctx->list);
- spin_unlock(&inode->i_lock);
- }
- if (ctx->state != NULL)
- nfs4_close_state(ctx->state, ctx->mode);
- if (ctx->cred != NULL)
- put_rpccred(ctx->cred);
- dput(ctx->dentry);
- mntput(ctx->vfsmnt);
- kfree(ctx);
+ struct nfs_open_context *ctx = container_of(kref,
+ struct nfs_open_context, kref);
+
+ if (!list_empty(&ctx->list)) {
+ struct inode *inode = ctx->path.dentry->d_inode;
+ spin_lock(&inode->i_lock);
+ list_del(&ctx->list);
+ spin_unlock(&inode->i_lock);
}
+ if (ctx->state != NULL)
+ nfs4_close_state(&ctx->path, ctx->state, ctx->mode);
+ if (ctx->cred != NULL)
+ put_rpccred(ctx->cred);
+ dput(ctx->path.dentry);
+ mntput(ctx->path.mnt);
+ kfree(ctx);
+}
+
+void put_nfs_open_context(struct nfs_open_context *ctx)
+{
+ kref_put(&ctx->kref, nfs_free_open_context);
}
/*
@@ -961,8 +967,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
goto out_changed;
server = NFS_SERVER(inode);
- /* Update the fsid if and only if this is the root directory */
- if (inode == inode->i_sb->s_root->d_inode
+ /* Update the fsid? */
+ if (S_ISDIR(inode->i_mode)
&& !nfs_fsid_equal(&server->fsid, &fattr->fsid))
server->fsid = fattr->fsid;
@@ -1066,8 +1072,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
invalid &= ~NFS_INO_INVALID_DATA;
if (data_stable)
invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE);
- if (!nfs_have_delegation(inode, FMODE_READ))
+ if (!nfs_have_delegation(inode, FMODE_READ) ||
+ (nfsi->cache_validity & NFS_INO_REVAL_FORCED))
nfsi->cache_validity |= invalid;
+ nfsi->cache_validity &= ~NFS_INO_REVAL_FORCED;
return 0;
out_changed:
@@ -1103,27 +1111,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
*/
void nfs4_clear_inode(struct inode *inode)
{
- struct nfs_inode *nfsi = NFS_I(inode);
-
/* If we are holding a delegation, return it! */
nfs_inode_return_delegation(inode);
/* First call standard NFS clear_inode() code */
nfs_clear_inode(inode);
- /* Now clear out any remaining state */
- while (!list_empty(&nfsi->open_states)) {
- struct nfs4_state *state;
-
- state = list_entry(nfsi->open_states.next,
- struct nfs4_state,
- inode_states);
- dprintk("%s(%s/%Ld): found unclaimed NFSv4 state %p\n",
- __FUNCTION__,
- inode->i_sb->s_id,
- (long long)NFS_FILEID(inode),
- state);
- BUG_ON(atomic_read(&state->count) != 1);
- nfs4_close_state(state, state->state);
- }
}
#endif
@@ -1165,15 +1156,11 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag
struct nfs_inode *nfsi = (struct nfs_inode *) foo;
inode_init_once(&nfsi->vfs_inode);
- spin_lock_init(&nfsi->req_lock);
- INIT_LIST_HEAD(&nfsi->dirty);
- INIT_LIST_HEAD(&nfsi->commit);
INIT_LIST_HEAD(&nfsi->open_files);
INIT_LIST_HEAD(&nfsi->access_cache_entry_lru);
INIT_LIST_HEAD(&nfsi->access_cache_inode_lru);
INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
atomic_set(&nfsi->data_updates, 0);
- nfsi->ndirty = 0;
nfsi->ncommit = 0;
nfsi->npages = 0;
nfs4_init_once(nfsi);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index ad2b40db1e6..76cf55d5710 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -183,9 +183,9 @@ unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
/*
* Calculate the number of 512byte blocks used.
*/
-static inline unsigned long nfs_calc_block_size(u64 tsize)
+static inline blkcnt_t nfs_calc_block_size(u64 tsize)
{
- loff_t used = (tsize + 511) >> 9;
+ blkcnt_t used = (tsize + 511) >> 9;
return (used > ULONG_MAX) ? ULONG_MAX : used;
}
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index ca5a266a314..8afd9f7e7a9 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -1,7 +1,5 @@
/*
- * linux/fs/nfs/mount_clnt.c
- *
- * MOUNT client to support NFSroot.
+ * In-kernel MOUNT protocol client
*
* Copyright (C) 1997, Olaf Kirch <okir@monad.swb.de>
*/
@@ -18,33 +16,31 @@
#include <linux/nfs_fs.h>
#ifdef RPC_DEBUG
-# define NFSDBG_FACILITY NFSDBG_ROOT
+# define NFSDBG_FACILITY NFSDBG_MOUNT
#endif
-/*
-#define MOUNT_PROGRAM 100005
-#define MOUNT_VERSION 1
-#define MOUNT_MNT 1
-#define MOUNT_UMNT 3
- */
-
-static struct rpc_clnt * mnt_create(char *, struct sockaddr_in *,
- int, int);
static struct rpc_program mnt_program;
struct mnt_fhstatus {
- unsigned int status;
- struct nfs_fh * fh;
+ u32 status;
+ struct nfs_fh *fh;
};
-/*
- * Obtain an NFS file handle for the given host and path
+/**
+ * nfs_mount - Obtain an NFS file handle for the given host and path
+ * @addr: pointer to server's address
+ * @len: size of server's address
+ * @hostname: name of server host, or NULL
+ * @path: pointer to string containing export path to mount
+ * @version: mount version to use for this request
+ * @protocol: transport protocol to use for thie request
+ * @fh: pointer to location to place returned file handle
+ *
+ * Uses default timeout parameters specified by underlying transport.
*/
-int
-nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
- int version, int protocol)
+int nfs_mount(struct sockaddr *addr, size_t len, char *hostname, char *path,
+ int version, int protocol, struct nfs_fh *fh)
{
- struct rpc_clnt *mnt_clnt;
struct mnt_fhstatus result = {
.fh = fh
};
@@ -52,16 +48,25 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
.rpc_argp = path,
.rpc_resp = &result,
};
- char hostname[32];
+ struct rpc_create_args args = {
+ .protocol = protocol,
+ .address = addr,
+ .addrsize = len,
+ .servername = hostname,
+ .program = &mnt_program,
+ .version = version,
+ .authflavor = RPC_AUTH_UNIX,
+ .flags = RPC_CLNT_CREATE_INTR,
+ };
+ struct rpc_clnt *mnt_clnt;
int status;
- dprintk("NFS: nfs_mount(%08x:%s)\n",
- (unsigned)ntohl(addr->sin_addr.s_addr), path);
+ dprintk("NFS: sending MNT request for %s:%s\n",
+ (hostname ? hostname : "server"), path);
- sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr));
- mnt_clnt = mnt_create(hostname, addr, version, protocol);
+ mnt_clnt = rpc_create(&args);
if (IS_ERR(mnt_clnt))
- return PTR_ERR(mnt_clnt);
+ goto out_clnt_err;
if (version == NFS_MNT3_VERSION)
msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC3_MNT];
@@ -69,33 +74,39 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
msg.rpc_proc = &mnt_clnt->cl_procinfo[MNTPROC_MNT];
status = rpc_call_sync(mnt_clnt, &msg, 0);
- return status < 0? status : (result.status? -EACCES : 0);
-}
+ rpc_shutdown_client(mnt_clnt);
-static struct rpc_clnt *
-mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
- int protocol)
-{
- struct rpc_create_args args = {
- .protocol = protocol,
- .address = (struct sockaddr *)srvaddr,
- .addrsize = sizeof(*srvaddr),
- .servername = hostname,
- .program = &mnt_program,
- .version = version,
- .authflavor = RPC_AUTH_UNIX,
- .flags = (RPC_CLNT_CREATE_ONESHOT |
- RPC_CLNT_CREATE_INTR),
- };
+ if (status < 0)
+ goto out_call_err;
+ if (result.status != 0)
+ goto out_mnt_err;
+
+ dprintk("NFS: MNT request succeeded\n");
+ status = 0;
+
+out:
+ return status;
+
+out_clnt_err:
+ status = PTR_ERR(mnt_clnt);
+ dprintk("NFS: failed to create RPC client, status=%d\n", status);
+ goto out;
+
+out_call_err:
+ dprintk("NFS: failed to start MNT request, status=%d\n", status);
+ goto out;
- return rpc_create(&args);
+out_mnt_err:
+ dprintk("NFS: MNT server returned result %d\n", result.status);
+ status = -EACCES;
+ goto out;
}
/*
* XDR encode/decode functions for MOUNT
*/
-static int
-xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const char *path)
+static int xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p,
+ const char *path)
{
p = xdr_encode_string(p, path);
@@ -103,8 +114,8 @@ xdr_encode_dirpath(struct rpc_rqst *req, __be32 *p, const char *path)
return 0;
}
-static int
-xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
+static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p,
+ struct mnt_fhstatus *res)
{
struct nfs_fh *fh = res->fh;
@@ -115,8 +126,8 @@ xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
return 0;
}
-static int
-xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
+static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
+ struct mnt_fhstatus *res)
{
struct nfs_fh *fh = res->fh;
@@ -135,53 +146,53 @@ xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, struct mnt_fhstatus *res)
#define MNT_fhstatus_sz (1 + 8)
#define MNT_fhstatus3_sz (1 + 16)
-static struct rpc_procinfo mnt_procedures[] = {
-[MNTPROC_MNT] = {
- .p_proc = MNTPROC_MNT,
- .p_encode = (kxdrproc_t) xdr_encode_dirpath,
- .p_decode = (kxdrproc_t) xdr_decode_fhstatus,
- .p_arglen = MNT_dirpath_sz,
- .p_replen = MNT_fhstatus_sz,
- .p_statidx = MNTPROC_MNT,
- .p_name = "MOUNT",
+static struct rpc_procinfo mnt_procedures[] = {
+ [MNTPROC_MNT] = {
+ .p_proc = MNTPROC_MNT,
+ .p_encode = (kxdrproc_t) xdr_encode_dirpath,
+ .p_decode = (kxdrproc_t) xdr_decode_fhstatus,
+ .p_arglen = MNT_dirpath_sz,
+ .p_replen = MNT_fhstatus_sz,
+ .p_statidx = MNTPROC_MNT,
+ .p_name = "MOUNT",
},
};
static struct rpc_procinfo mnt3_procedures[] = {
-[MOUNTPROC3_MNT] = {
- .p_proc = MOUNTPROC3_MNT,
- .p_encode = (kxdrproc_t) xdr_encode_dirpath,
- .p_decode = (kxdrproc_t) xdr_decode_fhstatus3,
- .p_arglen = MNT_dirpath_sz,
- .p_replen = MNT_fhstatus3_sz,
- .p_statidx = MOUNTPROC3_MNT,
- .p_name = "MOUNT",
+ [MOUNTPROC3_MNT] = {
+ .p_proc = MOUNTPROC3_MNT,
+ .p_encode = (kxdrproc_t) xdr_encode_dirpath,
+ .p_decode = (kxdrproc_t) xdr_decode_fhstatus3,
+ .p_arglen = MNT_dirpath_sz,
+ .p_replen = MNT_fhstatus3_sz,
+ .p_statidx = MOUNTPROC3_MNT,
+ .p_name = "MOUNT",
},
};
-static struct rpc_version mnt_version1 = {
- .number = 1,
- .nrprocs = 2,
- .procs = mnt_procedures
+static struct rpc_version mnt_version1 = {
+ .number = 1,
+ .nrprocs = 2,
+ .procs = mnt_procedures,
};
-static struct rpc_version mnt_version3 = {
- .number = 3,
- .nrprocs = 2,
- .procs = mnt3_procedures
+static struct rpc_version mnt_version3 = {
+ .number = 3,
+ .nrprocs = 2,
+ .procs = mnt3_procedures,
};
-static struct rpc_version * mnt_version[] = {
+static struct rpc_version *mnt_version[] = {
NULL,
&mnt_version1,
NULL,
&mnt_version3,
};
-static struct rpc_stat mnt_stats;
+static struct rpc_stat mnt_stats;
-static struct rpc_program mnt_program = {
+static struct rpc_program mnt_program = {
.name = "mount",
.number = NFS_MNT_PROGRAM,
.nrvers = ARRAY_SIZE(mnt_version),
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index cd3ca7b5d3d..7fcc78f2aa7 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -223,7 +223,7 @@ nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
static int
nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
u32 offset = (u32)args->offset;
u32 count = args->count;
@@ -380,7 +380,7 @@ static int
nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args)
{
struct rpc_task *task = req->rq_task;
- struct rpc_auth *auth = task->tk_auth;
+ struct rpc_auth *auth = task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
u32 count = args->count;
@@ -541,7 +541,7 @@ nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
static int
nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
p = xdr_encode_fhandle(p, args->fh);
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 45268d6def2..814d886b6aa 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -335,9 +335,7 @@ again:
* not sure this buys us anything (and I'd have
* to revamp the NFSv3 XDR code) */
status = nfs3_proc_setattr(dentry, &fattr, sattr);
- if (status == 0)
- nfs_setattr_update_inode(dentry->d_inode, sattr);
- nfs_refresh_inode(dentry->d_inode, &fattr);
+ nfs_post_op_update_inode(dentry->d_inode, &fattr);
dprintk("NFS reply setattr (post-create): %d\n", status);
}
if (status != 0)
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index b51df8eb9f0..b4647a22f34 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -319,7 +319,7 @@ nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *arg
static int
nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
u32 count = args->count;
@@ -458,7 +458,7 @@ nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
static int
nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
u32 count = args->count;
@@ -643,7 +643,7 @@ static int
nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
struct nfs3_getaclargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
p = xdr_encode_fhandle(p, args->fh);
@@ -773,7 +773,7 @@ nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
static int
nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
p = xdr_encode_fhandle(p, args->fh);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index cf3a17eb5c0..6c028e734fe 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -70,19 +70,26 @@ static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status
seqid->flags |= NFS_SEQID_CONFIRMED;
}
+struct nfs_unique_id {
+ struct rb_node rb_node;
+ __u64 id;
+};
+
/*
* NFS4 state_owners and lock_owners are simply labels for ordered
* sequences of RPC calls. Their sole purpose is to provide once-only
* semantics by allowing the server to identify replayed requests.
*/
struct nfs4_state_owner {
- spinlock_t so_lock;
- struct list_head so_list; /* per-clientid list of state_owners */
+ struct nfs_unique_id so_owner_id;
struct nfs_client *so_client;
- u32 so_id; /* 32-bit identifier, unique */
- atomic_t so_count;
+ struct nfs_server *so_server;
+ struct rb_node so_client_node;
struct rpc_cred *so_cred; /* Associated cred */
+
+ spinlock_t so_lock;
+ atomic_t so_count;
struct list_head so_states;
struct list_head so_delegations;
struct nfs_seqid_counter so_seqid;
@@ -108,7 +115,7 @@ struct nfs4_lock_state {
#define NFS_LOCK_INITIALIZED 1
int ls_flags;
struct nfs_seqid_counter ls_seqid;
- u32 ls_id;
+ struct nfs_unique_id ls_id;
nfs4_stateid ls_stateid;
atomic_t ls_count;
};
@@ -116,7 +123,10 @@ struct nfs4_lock_state {
/* bits for nfs4_state->flags */
enum {
LK_STATE_IN_USE,
- NFS_DELEGATED_STATE,
+ NFS_DELEGATED_STATE, /* Current stateid is delegation */
+ NFS_O_RDONLY_STATE, /* OPEN stateid has read-only state */
+ NFS_O_WRONLY_STATE, /* OPEN stateid has write-only state */
+ NFS_O_RDWR_STATE, /* OPEN stateid has read/write state */
};
struct nfs4_state {
@@ -130,11 +140,14 @@ struct nfs4_state {
unsigned long flags; /* Do we hold any locks? */
spinlock_t state_lock; /* Protects the lock_states list */
- nfs4_stateid stateid;
+ seqlock_t seqlock; /* Protects the stateid/open_stateid */
+ nfs4_stateid stateid; /* Current stateid: may be delegation */
+ nfs4_stateid open_stateid; /* OPEN stateid */
- unsigned int n_rdonly;
- unsigned int n_wronly;
- unsigned int n_rdwr;
+ /* The following 3 fields are protected by owner->so_lock */
+ unsigned int n_rdonly; /* Number of read-only references */
+ unsigned int n_wronly; /* Number of write-only references */
+ unsigned int n_rdwr; /* Number of read/write references */
int state; /* State on the server (R,W, or RW) */
atomic_t count;
};
@@ -165,7 +178,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struc
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
-extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
+extern int nfs4_do_close(struct path *path, struct nfs4_state *state);
extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
@@ -189,14 +202,13 @@ extern void nfs4_renew_state(struct work_struct *);
/* nfs4state.c */
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
-extern u32 nfs4_alloc_lockowner_id(struct nfs_client *);
extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
extern void nfs4_put_state_owner(struct nfs4_state_owner *);
extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
extern void nfs4_put_open_state(struct nfs4_state *);
-extern void nfs4_close_state(struct nfs4_state *, mode_t);
+extern void nfs4_close_state(struct path *, struct nfs4_state *, mode_t);
extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t);
extern void nfs4_schedule_state_recovery(struct nfs_client *);
extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
@@ -222,7 +234,7 @@ extern struct svc_version nfs4_callback_version1;
#else
-#define nfs4_close_state(a, b) do { } while (0)
+#define nfs4_close_state(a, b, c) do { } while (0)
#endif /* CONFIG_NFS_V4 */
#endif /* __LINUX_FS_NFS_NFS4_FS.H */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 648e0ac0f90..fee2da856c9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -65,6 +65,7 @@ static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *)
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags);
/* Prevent leaks of NFSv4 errors into userland */
int nfs4_map_errors(int err)
@@ -214,27 +215,39 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
}
struct nfs4_opendata {
- atomic_t count;
+ struct kref kref;
struct nfs_openargs o_arg;
struct nfs_openres o_res;
struct nfs_open_confirmargs c_arg;
struct nfs_open_confirmres c_res;
struct nfs_fattr f_attr;
struct nfs_fattr dir_attr;
- struct dentry *dentry;
+ struct path path;
struct dentry *dir;
struct nfs4_state_owner *owner;
+ struct nfs4_state *state;
struct iattr attrs;
unsigned long timestamp;
+ unsigned int rpc_done : 1;
int rpc_status;
int cancelled;
};
-static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
+
+static void nfs4_init_opendata_res(struct nfs4_opendata *p)
+{
+ p->o_res.f_attr = &p->f_attr;
+ p->o_res.dir_attr = &p->dir_attr;
+ p->o_res.server = p->o_arg.server;
+ nfs_fattr_init(&p->f_attr);
+ nfs_fattr_init(&p->dir_attr);
+}
+
+static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
struct nfs4_state_owner *sp, int flags,
const struct iattr *attrs)
{
- struct dentry *parent = dget_parent(dentry);
+ struct dentry *parent = dget_parent(path->dentry);
struct inode *dir = parent->d_inode;
struct nfs_server *server = NFS_SERVER(dir);
struct nfs4_opendata *p;
@@ -245,24 +258,19 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid);
if (p->o_arg.seqid == NULL)
goto err_free;
- atomic_set(&p->count, 1);
- p->dentry = dget(dentry);
+ p->path.mnt = mntget(path->mnt);
+ p->path.dentry = dget(path->dentry);
p->dir = parent;
p->owner = sp;
atomic_inc(&sp->so_count);
p->o_arg.fh = NFS_FH(dir);
p->o_arg.open_flags = flags,
p->o_arg.clientid = server->nfs_client->cl_clientid;
- p->o_arg.id = sp->so_id;
- p->o_arg.name = &dentry->d_name;
+ p->o_arg.id = sp->so_owner_id.id;
+ p->o_arg.name = &p->path.dentry->d_name;
p->o_arg.server = server;
p->o_arg.bitmask = server->attr_bitmask;
p->o_arg.claim = NFS4_OPEN_CLAIM_NULL;
- p->o_res.f_attr = &p->f_attr;
- p->o_res.dir_attr = &p->dir_attr;
- p->o_res.server = server;
- nfs_fattr_init(&p->f_attr);
- nfs_fattr_init(&p->dir_attr);
if (flags & O_EXCL) {
u32 *s = (u32 *) p->o_arg.u.verifier.data;
s[0] = jiffies;
@@ -274,6 +282,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
p->c_arg.fh = &p->o_res.fh;
p->c_arg.stateid = &p->o_res.stateid;
p->c_arg.seqid = p->o_arg.seqid;
+ nfs4_init_opendata_res(p);
+ kref_init(&p->kref);
return p;
err_free:
kfree(p);
@@ -282,27 +292,25 @@ err:
return NULL;
}
-static void nfs4_opendata_free(struct nfs4_opendata *p)
+static void nfs4_opendata_free(struct kref *kref)
{
- if (p != NULL && atomic_dec_and_test(&p->count)) {
- nfs_free_seqid(p->o_arg.seqid);
- nfs4_put_state_owner(p->owner);
- dput(p->dir);
- dput(p->dentry);
- kfree(p);
- }
+ struct nfs4_opendata *p = container_of(kref,
+ struct nfs4_opendata, kref);
+
+ nfs_free_seqid(p->o_arg.seqid);
+ if (p->state != NULL)
+ nfs4_put_open_state(p->state);
+ nfs4_put_state_owner(p->owner);
+ dput(p->dir);
+ dput(p->path.dentry);
+ mntput(p->path.mnt);
+ kfree(p);
}
-/* Helper for asynchronous RPC calls */
-static int nfs4_call_async(struct rpc_clnt *clnt,
- const struct rpc_call_ops *tk_ops, void *calldata)
+static void nfs4_opendata_put(struct nfs4_opendata *p)
{
- struct rpc_task *task;
-
- if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata)))
- return -ENOMEM;
- rpc_execute(task);
- return 0;
+ if (p != NULL)
+ kref_put(&p->kref, nfs4_opendata_free);
}
static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
@@ -316,7 +324,34 @@ static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task)
return ret;
}
-static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
+static int can_open_cached(struct nfs4_state *state, int mode)
+{
+ int ret = 0;
+ switch (mode & (FMODE_READ|FMODE_WRITE|O_EXCL)) {
+ case FMODE_READ:
+ ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0;
+ ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+ break;
+ case FMODE_WRITE:
+ ret |= test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0;
+ ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+ break;
+ case FMODE_READ|FMODE_WRITE:
+ ret |= test_bit(NFS_O_RDWR_STATE, &state->flags) != 0;
+ }
+ return ret;
+}
+
+static int can_open_delegated(struct nfs_delegation *delegation, mode_t open_flags)
+{
+ if ((delegation->type & open_flags) != open_flags)
+ return 0;
+ if (delegation->flags & NFS_DELEGATION_NEED_RECLAIM)
+ return 0;
+ return 1;
+}
+
+static void update_open_stateflags(struct nfs4_state *state, mode_t open_flags)
{
switch (open_flags) {
case FMODE_WRITE:
@@ -328,41 +363,176 @@ static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_
case FMODE_READ|FMODE_WRITE:
state->n_rdwr++;
}
+ nfs4_state_set_mode_locked(state, state->state | open_flags);
}
-static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
{
- struct inode *inode = state->inode;
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
+ memcpy(state->stateid.data, stateid->data, sizeof(state->stateid.data));
+ memcpy(state->open_stateid.data, stateid->data, sizeof(state->open_stateid.data));
+ switch (open_flags) {
+ case FMODE_READ:
+ set_bit(NFS_O_RDONLY_STATE, &state->flags);
+ break;
+ case FMODE_WRITE:
+ set_bit(NFS_O_WRONLY_STATE, &state->flags);
+ break;
+ case FMODE_READ|FMODE_WRITE:
+ set_bit(NFS_O_RDWR_STATE, &state->flags);
+ }
+}
+
+static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+{
+ write_seqlock(&state->seqlock);
+ nfs_set_open_stateid_locked(state, stateid, open_flags);
+ write_sequnlock(&state->seqlock);
+}
+static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *deleg_stateid, int open_flags)
+{
open_flags &= (FMODE_READ|FMODE_WRITE);
- /* Protect against nfs4_find_state_byowner() */
+ /*
+ * Protect the call to nfs4_state_set_mode_locked and
+ * serialise the stateid update
+ */
+ write_seqlock(&state->seqlock);
+ if (deleg_stateid != NULL) {
+ memcpy(state->stateid.data, deleg_stateid->data, sizeof(state->stateid.data));
+ set_bit(NFS_DELEGATED_STATE, &state->flags);
+ }
+ if (open_stateid != NULL)
+ nfs_set_open_stateid_locked(state, open_stateid, open_flags);
+ write_sequnlock(&state->seqlock);
spin_lock(&state->owner->so_lock);
- spin_lock(&inode->i_lock);
- memcpy(&state->stateid, stateid, sizeof(state->stateid));
update_open_stateflags(state, open_flags);
- nfs4_state_set_mode_locked(state, state->state | open_flags);
- spin_unlock(&inode->i_lock);
spin_unlock(&state->owner->so_lock);
}
+static void nfs4_return_incompatible_delegation(struct inode *inode, mode_t open_flags)
+{
+ struct nfs_delegation *delegation;
+
+ rcu_read_lock();
+ delegation = rcu_dereference(NFS_I(inode)->delegation);
+ if (delegation == NULL || (delegation->type & open_flags) == open_flags) {
+ rcu_read_unlock();
+ return;
+ }
+ rcu_read_unlock();
+ nfs_inode_return_delegation(inode);
+}
+
+static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata)
+{
+ struct nfs4_state *state = opendata->state;
+ struct nfs_inode *nfsi = NFS_I(state->inode);
+ struct nfs_delegation *delegation;
+ int open_mode = opendata->o_arg.open_flags & (FMODE_READ|FMODE_WRITE|O_EXCL);
+ nfs4_stateid stateid;
+ int ret = -EAGAIN;
+
+ rcu_read_lock();
+ delegation = rcu_dereference(nfsi->delegation);
+ for (;;) {
+ if (can_open_cached(state, open_mode)) {
+ spin_lock(&state->owner->so_lock);
+ if (can_open_cached(state, open_mode)) {
+ update_open_stateflags(state, open_mode);
+ spin_unlock(&state->owner->so_lock);
+ rcu_read_unlock();
+ goto out_return_state;
+ }
+ spin_unlock(&state->owner->so_lock);
+ }
+ if (delegation == NULL)
+ break;
+ if (!can_open_delegated(delegation, open_mode))
+ break;
+ /* Save the delegation */
+ memcpy(stateid.data, delegation->stateid.data, sizeof(stateid.data));
+ rcu_read_unlock();
+ lock_kernel();
+ ret = _nfs4_do_access(state->inode, state->owner->so_cred, open_mode);
+ unlock_kernel();
+ if (ret != 0)
+ goto out;
+ ret = -EAGAIN;
+ rcu_read_lock();
+ delegation = rcu_dereference(nfsi->delegation);
+ /* If no delegation, try a cached open */
+ if (delegation == NULL)
+ continue;
+ /* Is the delegation still valid? */
+ if (memcmp(stateid.data, delegation->stateid.data, sizeof(stateid.data)) != 0)
+ continue;
+ rcu_read_unlock();
+ update_open_stateid(state, NULL, &stateid, open_mode);
+ goto out_return_state;
+ }
+ rcu_read_unlock();
+out:
+ return ERR_PTR(ret);
+out_return_state:
+ atomic_inc(&state->count);
+ return state;
+}
+
static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
{
struct inode *inode;
struct nfs4_state *state = NULL;
+ struct nfs_delegation *delegation;
+ nfs4_stateid *deleg_stateid = NULL;
+ int ret;
- if (!(data->f_attr.valid & NFS_ATTR_FATTR))
+ if (!data->rpc_done) {
+ state = nfs4_try_open_cached(data);
goto out;
+ }
+
+ ret = -EAGAIN;
+ if (!(data->f_attr.valid & NFS_ATTR_FATTR))
+ goto err;
inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr);
+ ret = PTR_ERR(inode);
if (IS_ERR(inode))
- goto out;
+ goto err;
+ ret = -ENOMEM;
state = nfs4_get_open_state(inode, data->owner);
if (state == NULL)
- goto put_inode;
- update_open_stateid(state, &data->o_res.stateid, data->o_arg.open_flags);
-put_inode:
+ goto err_put_inode;
+ if (data->o_res.delegation_type != 0) {
+ int delegation_flags = 0;
+
+ rcu_read_lock();
+ delegation = rcu_dereference(NFS_I(inode)->delegation);
+ if (delegation)
+ delegation_flags = delegation->flags;
+ rcu_read_unlock();
+ if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
+ nfs_inode_set_delegation(state->inode,
+ data->owner->so_cred,
+ &data->o_res);
+ else
+ nfs_inode_reclaim_delegation(state->inode,
+ data->owner->so_cred,
+ &data->o_res);
+ }
+ rcu_read_lock();
+ delegation = rcu_dereference(NFS_I(inode)->delegation);
+ if (delegation != NULL)
+ deleg_stateid = &delegation->stateid;
+ update_open_stateid(state, &data->o_res.stateid, deleg_stateid, data->o_arg.open_flags);
+ rcu_read_unlock();
iput(inode);
out:
return state;
+err_put_inode:
+ iput(inode);
+err:
+ return ERR_PTR(ret);
}
static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
@@ -382,79 +552,66 @@ static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *
return ERR_PTR(-ENOENT);
}
-static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, nfs4_stateid *stateid)
+static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, struct nfs4_state **res)
{
+ struct nfs4_state *newstate;
int ret;
opendata->o_arg.open_flags = openflags;
+ memset(&opendata->o_res, 0, sizeof(opendata->o_res));
+ memset(&opendata->c_res, 0, sizeof(opendata->c_res));
+ nfs4_init_opendata_res(opendata);
ret = _nfs4_proc_open(opendata);
if (ret != 0)
return ret;
- memcpy(stateid->data, opendata->o_res.stateid.data,
- sizeof(stateid->data));
+ newstate = nfs4_opendata_to_nfs4_state(opendata);
+ if (IS_ERR(newstate))
+ return PTR_ERR(newstate);
+ nfs4_close_state(&opendata->path, newstate, openflags);
+ *res = newstate;
return 0;
}
static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state)
{
- nfs4_stateid stateid;
struct nfs4_state *newstate;
- int mode = 0;
- int delegation = 0;
int ret;
/* memory barrier prior to reading state->n_* */
+ clear_bit(NFS_DELEGATED_STATE, &state->flags);
smp_rmb();
if (state->n_rdwr != 0) {
- ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &stateid);
+ ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
if (ret != 0)
return ret;
- mode |= FMODE_READ|FMODE_WRITE;
- if (opendata->o_res.delegation_type != 0)
- delegation = opendata->o_res.delegation_type;
- smp_rmb();
+ if (newstate != state)
+ return -ESTALE;
}
if (state->n_wronly != 0) {
- ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &stateid);
+ ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
if (ret != 0)
return ret;
- mode |= FMODE_WRITE;
- if (opendata->o_res.delegation_type != 0)
- delegation = opendata->o_res.delegation_type;
- smp_rmb();
+ if (newstate != state)
+ return -ESTALE;
}
if (state->n_rdonly != 0) {
- ret = nfs4_open_recover_helper(opendata, FMODE_READ, &stateid);
+ ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
if (ret != 0)
return ret;
- mode |= FMODE_READ;
+ if (newstate != state)
+ return -ESTALE;
}
- clear_bit(NFS_DELEGATED_STATE, &state->flags);
- if (mode == 0)
- return 0;
- if (opendata->o_res.delegation_type == 0)
- opendata->o_res.delegation_type = delegation;
- opendata->o_arg.open_flags |= mode;
- newstate = nfs4_opendata_to_nfs4_state(opendata);
- if (newstate != NULL) {
- if (opendata->o_res.delegation_type != 0) {
- struct nfs_inode *nfsi = NFS_I(newstate->inode);
- int delegation_flags = 0;
- if (nfsi->delegation)
- delegation_flags = nfsi->delegation->flags;
- if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM))
- nfs_inode_set_delegation(newstate->inode,
- opendata->owner->so_cred,
- &opendata->o_res);
- else
- nfs_inode_reclaim_delegation(newstate->inode,
- opendata->owner->so_cred,
- &opendata->o_res);
- }
- nfs4_close_state(newstate, opendata->o_arg.open_flags);
+ /*
+ * We may have performed cached opens for all three recoveries.
+ * Check if we need to update the current stateid.
+ */
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 &&
+ memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) {
+ write_seqlock(&state->seqlock);
+ if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
+ memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data));
+ write_sequnlock(&state->seqlock);
}
- if (newstate != state)
- return -ESTALE;
return 0;
}
@@ -462,41 +619,37 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
* OPEN_RECLAIM:
* reclaim state on the server after a reboot.
*/
-static int _nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int _nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
{
- struct nfs_delegation *delegation = NFS_I(state->inode)->delegation;
+ struct nfs_delegation *delegation;
struct nfs4_opendata *opendata;
int delegation_type = 0;
int status;
- if (delegation != NULL) {
- if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
- memcpy(&state->stateid, &delegation->stateid,
- sizeof(state->stateid));
- set_bit(NFS_DELEGATED_STATE, &state->flags);
- return 0;
- }
- delegation_type = delegation->type;
- }
- opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+ opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
if (opendata == NULL)
return -ENOMEM;
opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS;
opendata->o_arg.fh = NFS_FH(state->inode);
nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh);
+ rcu_read_lock();
+ delegation = rcu_dereference(NFS_I(state->inode)->delegation);
+ if (delegation != NULL && (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) != 0)
+ delegation_type = delegation->flags;
+ rcu_read_unlock();
opendata->o_arg.u.delegation_type = delegation_type;
status = nfs4_open_recover(opendata, state);
- nfs4_opendata_free(opendata);
+ nfs4_opendata_put(opendata);
return status;
}
-static int nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_exception exception = { };
int err;
do {
- err = _nfs4_do_open_reclaim(sp, state, dentry);
+ err = _nfs4_do_open_reclaim(ctx, state);
if (err != -NFS4ERR_DELAY)
break;
nfs4_handle_exception(server, err, &exception);
@@ -512,37 +665,35 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
ctx = nfs4_state_find_open_context(state);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
- ret = nfs4_do_open_reclaim(sp, state, ctx->dentry);
+ ret = nfs4_do_open_reclaim(ctx, state);
put_nfs_open_context(ctx);
return ret;
}
-static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+static int _nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
{
struct nfs4_state_owner *sp = state->owner;
struct nfs4_opendata *opendata;
int ret;
- if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
- return 0;
- opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL);
+ opendata = nfs4_opendata_alloc(&ctx->path, sp, 0, NULL);
if (opendata == NULL)
return -ENOMEM;
opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR;
- memcpy(opendata->o_arg.u.delegation.data, state->stateid.data,
+ memcpy(opendata->o_arg.u.delegation.data, stateid->data,
sizeof(opendata->o_arg.u.delegation.data));
ret = nfs4_open_recover(opendata, state);
- nfs4_opendata_free(opendata);
+ nfs4_opendata_put(opendata);
return ret;
}
-int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid)
{
struct nfs4_exception exception = { };
- struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+ struct nfs_server *server = NFS_SERVER(state->inode);
int err;
do {
- err = _nfs4_open_delegation_recall(dentry, state);
+ err = _nfs4_open_delegation_recall(ctx, state, stateid);
switch (err) {
case 0:
return err;
@@ -582,9 +733,10 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata)
memcpy(data->o_res.stateid.data, data->c_res.stateid.data,
sizeof(data->o_res.stateid.data));
renew_lease(data->o_res.server, data->timestamp);
+ data->rpc_done = 1;
}
- nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status);
+ nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid);
}
static void nfs4_open_confirm_release(void *calldata)
@@ -596,14 +748,14 @@ static void nfs4_open_confirm_release(void *calldata)
if (data->cancelled == 0)
goto out_free;
/* In case of error, no cleanup! */
- if (data->rpc_status != 0)
+ if (!data->rpc_done)
goto out_free;
nfs_confirm_seqid(&data->owner->so_seqid, 0);
state = nfs4_opendata_to_nfs4_state(data);
- if (state != NULL)
- nfs4_close_state(state, data->o_arg.open_flags);
+ if (!IS_ERR(state))
+ nfs4_close_state(&data->path, state, data->o_arg.open_flags);
out_free:
- nfs4_opendata_free(data);
+ nfs4_opendata_put(data);
}
static const struct rpc_call_ops nfs4_open_confirm_ops = {
@@ -621,12 +773,9 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
struct rpc_task *task;
int status;
- atomic_inc(&data->count);
- /*
- * If rpc_run_task() ends up calling ->rpc_release(), we
- * want to ensure that it takes the 'error' code path.
- */
- data->rpc_status = -ENOMEM;
+ kref_get(&data->kref);
+ data->rpc_done = 0;
+ data->rpc_status = 0;
task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -653,13 +802,35 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0)
return;
+ /*
+ * Check if we still need to send an OPEN call, or if we can use
+ * a delegation instead.
+ */
+ if (data->state != NULL) {
+ struct nfs_delegation *delegation;
+
+ if (can_open_cached(data->state, data->o_arg.open_flags & (FMODE_READ|FMODE_WRITE|O_EXCL)))
+ goto out_no_action;
+ rcu_read_lock();
+ delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
+ if (delegation != NULL &&
+ (delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0) {
+ rcu_read_unlock();
+ goto out_no_action;
+ }
+ rcu_read_unlock();
+ }
/* Update sequence id. */
- data->o_arg.id = sp->so_id;
+ data->o_arg.id = sp->so_owner_id.id;
data->o_arg.clientid = sp->so_client->cl_clientid;
if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
data->timestamp = jiffies;
rpc_call_setup(task, &msg, 0);
+ return;
+out_no_action:
+ task->tk_action = NULL;
+
}
static void nfs4_open_done(struct rpc_task *task, void *calldata)
@@ -683,8 +854,11 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)
data->rpc_status = -ENOTDIR;
}
renew_lease(data->o_res.server, data->timestamp);
+ if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM))
+ nfs_confirm_seqid(&data->owner->so_seqid, 0);
}
nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid);
+ data->rpc_done = 1;
}
static void nfs4_open_release(void *calldata)
@@ -696,17 +870,17 @@ static void nfs4_open_release(void *calldata)
if (data->cancelled == 0)
goto out_free;
/* In case of error, no cleanup! */
- if (data->rpc_status != 0)
+ if (data->rpc_status != 0 || !data->rpc_done)
goto out_free;
/* In case we need an open_confirm, no cleanup! */
if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
goto out_free;
nfs_confirm_seqid(&data->owner->so_seqid, 0);
state = nfs4_opendata_to_nfs4_state(data);
- if (state != NULL)
- nfs4_close_state(state, data->o_arg.open_flags);
+ if (!IS_ERR(state))
+ nfs4_close_state(&data->path, state, data->o_arg.open_flags);
out_free:
- nfs4_opendata_free(data);
+ nfs4_opendata_put(data);
}
static const struct rpc_call_ops nfs4_open_ops = {
@@ -727,12 +901,10 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
struct rpc_task *task;
int status;
- atomic_inc(&data->count);
- /*
- * If rpc_run_task() ends up calling ->rpc_release(), we
- * want to ensure that it takes the 'error' code path.
- */
- data->rpc_status = -ENOMEM;
+ kref_get(&data->kref);
+ data->rpc_done = 0;
+ data->rpc_status = 0;
+ data->cancelled = 0;
task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -743,7 +915,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
} else
status = data->rpc_status;
rpc_put_task(task);
- if (status != 0)
+ if (status != 0 || !data->rpc_done)
return status;
if (o_arg->open_flags & O_CREAT) {
@@ -756,7 +928,6 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
if (status != 0)
return status;
}
- nfs_confirm_seqid(&data->owner->so_seqid, 0);
if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
return 0;
@@ -772,6 +943,8 @@ static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openf
mask |= MAY_READ;
if (openflags & FMODE_WRITE)
mask |= MAY_WRITE;
+ if (openflags & FMODE_EXEC)
+ mask |= MAY_EXEC;
status = nfs_access_get_cached(inode, cred, &cache);
if (status == 0)
goto out;
@@ -811,43 +984,32 @@ static int nfs4_recover_expired_lease(struct nfs_server *server)
* reclaim state on the server after a network partition.
* Assumes caller holds the appropriate lock
*/
-static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
{
- struct inode *inode = state->inode;
- struct nfs_delegation *delegation = NFS_I(inode)->delegation;
struct nfs4_opendata *opendata;
- int openflags = state->state & (FMODE_READ|FMODE_WRITE);
int ret;
- if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
- ret = _nfs4_do_access(inode, sp->so_cred, openflags);
- if (ret < 0)
- return ret;
- memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
- set_bit(NFS_DELEGATED_STATE, &state->flags);
- return 0;
- }
- opendata = nfs4_opendata_alloc(dentry, sp, openflags, NULL);
+ opendata = nfs4_opendata_alloc(&ctx->path, state->owner, 0, NULL);
if (opendata == NULL)
return -ENOMEM;
ret = nfs4_open_recover(opendata, state);
if (ret == -ESTALE) {
/* Invalidate the state owner so we don't ever use it again */
- nfs4_drop_state_owner(sp);
- d_drop(dentry);
+ nfs4_drop_state_owner(state->owner);
+ d_drop(ctx->path.dentry);
}
- nfs4_opendata_free(opendata);
+ nfs4_opendata_put(opendata);
return ret;
}
-static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
{
- struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+ struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_exception exception = { };
int err;
do {
- err = _nfs4_open_expired(sp, state, dentry);
+ err = _nfs4_open_expired(ctx, state);
if (err == -NFS4ERR_DELAY)
nfs4_handle_exception(server, err, &exception);
} while (exception.retry);
@@ -862,107 +1024,38 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
ctx = nfs4_state_find_open_context(state);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
- ret = nfs4_do_open_expired(sp, state, ctx->dentry);
+ ret = nfs4_do_open_expired(ctx, state);
put_nfs_open_context(ctx);
return ret;
}
/*
- * Returns a referenced nfs4_state if there is an open delegation on the file
+ * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
+ * fields corresponding to attributes that were used to store the verifier.
+ * Make sure we clobber those fields in the later setattr call
*/
-static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
-{
- struct nfs_delegation *delegation;
- struct nfs_server *server = NFS_SERVER(inode);
- struct nfs_client *clp = server->nfs_client;
- struct nfs_inode *nfsi = NFS_I(inode);
- struct nfs4_state_owner *sp = NULL;
- struct nfs4_state *state = NULL;
- int open_flags = flags & (FMODE_READ|FMODE_WRITE);
- int err;
-
- err = -ENOMEM;
- if (!(sp = nfs4_get_state_owner(server, cred))) {
- dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
- return err;
- }
- err = nfs4_recover_expired_lease(server);
- if (err != 0)
- goto out_put_state_owner;
- /* Protect against reboot recovery - NOTE ORDER! */
- down_read(&clp->cl_sem);
- /* Protect against delegation recall */
- down_read(&nfsi->rwsem);
- delegation = NFS_I(inode)->delegation;
- err = -ENOENT;
- if (delegation == NULL || (delegation->type & open_flags) != open_flags)
- goto out_err;
- err = -ENOMEM;
- state = nfs4_get_open_state(inode, sp);
- if (state == NULL)
- goto out_err;
-
- err = -ENOENT;
- if ((state->state & open_flags) == open_flags) {
- spin_lock(&inode->i_lock);
- update_open_stateflags(state, open_flags);
- spin_unlock(&inode->i_lock);
- goto out_ok;
- } else if (state->state != 0)
- goto out_put_open_state;
-
- lock_kernel();
- err = _nfs4_do_access(inode, cred, open_flags);
- unlock_kernel();
- if (err != 0)
- goto out_put_open_state;
- set_bit(NFS_DELEGATED_STATE, &state->flags);
- update_open_stateid(state, &delegation->stateid, open_flags);
-out_ok:
- nfs4_put_state_owner(sp);
- up_read(&nfsi->rwsem);
- up_read(&clp->cl_sem);
- *res = state;
- return 0;
-out_put_open_state:
- nfs4_put_open_state(state);
-out_err:
- up_read(&nfsi->rwsem);
- up_read(&clp->cl_sem);
- if (err != -EACCES)
- nfs_inode_return_delegation(inode);
-out_put_state_owner:
- nfs4_put_state_owner(sp);
- return err;
-}
-
-static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred)
+static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct iattr *sattr)
{
- struct nfs4_exception exception = { };
- struct nfs4_state *res = ERR_PTR(-EIO);
- int err;
+ if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
+ !(sattr->ia_valid & ATTR_ATIME_SET))
+ sattr->ia_valid |= ATTR_ATIME;
- do {
- err = _nfs4_open_delegated(inode, flags, cred, &res);
- if (err == 0)
- break;
- res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(inode),
- err, &exception));
- } while (exception.retry);
- return res;
+ if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
+ !(sattr->ia_valid & ATTR_MTIME_SET))
+ sattr->ia_valid |= ATTR_MTIME;
}
/*
* Returns a referenced nfs4_state
*/
-static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
{
struct nfs4_state_owner *sp;
struct nfs4_state *state = NULL;
struct nfs_server *server = NFS_SERVER(dir);
struct nfs_client *clp = server->nfs_client;
struct nfs4_opendata *opendata;
- int status;
+ int status;
/* Protect against reboot recovery conflicts */
status = -ENOMEM;
@@ -973,29 +1066,35 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
status = nfs4_recover_expired_lease(server);
if (status != 0)
goto err_put_state_owner;
+ if (path->dentry->d_inode != NULL)
+ nfs4_return_incompatible_delegation(path->dentry->d_inode, flags & (FMODE_READ|FMODE_WRITE));
down_read(&clp->cl_sem);
status = -ENOMEM;
- opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr);
+ opendata = nfs4_opendata_alloc(path, sp, flags, sattr);
if (opendata == NULL)
goto err_release_rwsem;
+ if (path->dentry->d_inode != NULL)
+ opendata->state = nfs4_get_open_state(path->dentry->d_inode, sp);
+
status = _nfs4_proc_open(opendata);
if (status != 0)
- goto err_opendata_free;
+ goto err_opendata_put;
+
+ if (opendata->o_arg.open_flags & O_EXCL)
+ nfs4_exclusive_attrset(opendata, sattr);
- status = -ENOMEM;
state = nfs4_opendata_to_nfs4_state(opendata);
- if (state == NULL)
- goto err_opendata_free;
- if (opendata->o_res.delegation_type != 0)
- nfs_inode_set_delegation(state->inode, cred, &opendata->o_res);
- nfs4_opendata_free(opendata);
+ status = PTR_ERR(state);
+ if (IS_ERR(state))
+ goto err_opendata_put;
+ nfs4_opendata_put(opendata);
nfs4_put_state_owner(sp);
up_read(&clp->cl_sem);
*res = state;
return 0;
-err_opendata_free:
- nfs4_opendata_free(opendata);
+err_opendata_put:
+ nfs4_opendata_put(opendata);
err_release_rwsem:
up_read(&clp->cl_sem);
err_put_state_owner:
@@ -1006,14 +1105,14 @@ out_err:
}
-static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred)
{
struct nfs4_exception exception = { };
struct nfs4_state *res;
int status;
do {
- status = _nfs4_do_open(dir, dentry, flags, sattr, cred, &res);
+ status = _nfs4_do_open(dir, path, flags, sattr, cred, &res);
if (status == 0)
break;
/* NOTE: BAD_SEQID means the server and client disagree about the
@@ -1028,7 +1127,9 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry,
* the user though...
*/
if (status == -NFS4ERR_BAD_SEQID) {
- printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");
+ printk(KERN_WARNING "NFS: v4 server %s "
+ " returned a bad sequence-id error!\n",
+ NFS_SERVER(dir)->nfs_client->cl_hostname);
exception.retry = 1;
continue;
}
@@ -1042,6 +1143,11 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry,
exception.retry = 1;
continue;
}
+ if (status == -EAGAIN) {
+ /* We must have found a delegation */
+ exception.retry = 1;
+ continue;
+ }
res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
status, &exception));
} while (exception.retry);
@@ -1101,6 +1207,7 @@ static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
}
struct nfs4_closedata {
+ struct path path;
struct inode *inode;
struct nfs4_state *state;
struct nfs_closeargs arg;
@@ -1117,6 +1224,8 @@ static void nfs4_free_closedata(void *data)
nfs4_put_open_state(calldata->state);
nfs_free_seqid(calldata->arg.seqid);
nfs4_put_state_owner(sp);
+ dput(calldata->path.dentry);
+ mntput(calldata->path.mnt);
kfree(calldata);
}
@@ -1134,8 +1243,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid);
switch (task->tk_status) {
case 0:
- memcpy(&state->stateid, &calldata->res.stateid,
- sizeof(state->stateid));
+ nfs_set_open_stateid(state, &calldata->res.stateid, calldata->arg.open_flags);
renew_lease(server, calldata->timestamp);
break;
case -NFS4ERR_STALE_STATEID:
@@ -1160,26 +1268,30 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
.rpc_resp = &calldata->res,
.rpc_cred = state->owner->so_cred,
};
- int mode = 0, old_mode;
+ int clear_rd, clear_wr, clear_rdwr;
+ int mode;
if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
return;
- /* Recalculate the new open mode in case someone reopened the file
- * while we were waiting in line to be scheduled.
- */
+
+ mode = FMODE_READ|FMODE_WRITE;
+ clear_rd = clear_wr = clear_rdwr = 0;
spin_lock(&state->owner->so_lock);
- spin_lock(&calldata->inode->i_lock);
- mode = old_mode = state->state;
+ /* Calculate the change in open mode */
if (state->n_rdwr == 0) {
- if (state->n_rdonly == 0)
+ if (state->n_rdonly == 0) {
mode &= ~FMODE_READ;
- if (state->n_wronly == 0)
+ clear_rd |= test_and_clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+ clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
+ }
+ if (state->n_wronly == 0) {
mode &= ~FMODE_WRITE;
+ clear_wr |= test_and_clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+ clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
+ }
}
- nfs4_state_set_mode_locked(state, mode);
- spin_unlock(&calldata->inode->i_lock);
spin_unlock(&state->owner->so_lock);
- if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) {
+ if (!clear_rd && !clear_wr && !clear_rdwr) {
/* Note: exit _without_ calling nfs4_close_done */
task->tk_action = NULL;
return;
@@ -1209,19 +1321,21 @@ static const struct rpc_call_ops nfs4_close_ops = {
*
* NOTE: Caller must be holding the sp->so_owner semaphore!
*/
-int nfs4_do_close(struct inode *inode, struct nfs4_state *state)
+int nfs4_do_close(struct path *path, struct nfs4_state *state)
{
- struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_closedata *calldata;
+ struct nfs4_state_owner *sp = state->owner;
+ struct rpc_task *task;
int status = -ENOMEM;
calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
if (calldata == NULL)
goto out;
- calldata->inode = inode;
+ calldata->inode = state->inode;
calldata->state = state;
- calldata->arg.fh = NFS_FH(inode);
- calldata->arg.stateid = &state->stateid;
+ calldata->arg.fh = NFS_FH(state->inode);
+ calldata->arg.stateid = &state->open_stateid;
/* Serialization for the sequence id */
calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
if (calldata->arg.seqid == NULL)
@@ -1229,36 +1343,55 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state)
calldata->arg.bitmask = server->attr_bitmask;
calldata->res.fattr = &calldata->fattr;
calldata->res.server = server;
+ calldata->path.mnt = mntget(path->mnt);
+ calldata->path.dentry = dget(path->dentry);
- status = nfs4_call_async(server->client, &nfs4_close_ops, calldata);
- if (status == 0)
- goto out;
-
- nfs_free_seqid(calldata->arg.seqid);
+ task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_close_ops, calldata);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+ rpc_put_task(task);
+ return 0;
out_free_calldata:
kfree(calldata);
out:
+ nfs4_put_open_state(state);
+ nfs4_put_state_owner(sp);
return status;
}
-static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state)
{
struct file *filp;
+ int ret;
- filp = lookup_instantiate_filp(nd, dentry, NULL);
+ /* If the open_intent is for execute, we have an extra check to make */
+ if (nd->intent.open.flags & FMODE_EXEC) {
+ ret = _nfs4_do_access(state->inode,
+ state->owner->so_cred,
+ nd->intent.open.flags);
+ if (ret < 0)
+ goto out_close;
+ }
+ filp = lookup_instantiate_filp(nd, path->dentry, NULL);
if (!IS_ERR(filp)) {
struct nfs_open_context *ctx;
ctx = (struct nfs_open_context *)filp->private_data;
ctx->state = state;
return 0;
}
- nfs4_close_state(state, nd->intent.open.flags);
- return PTR_ERR(filp);
+ ret = PTR_ERR(filp);
+out_close:
+ nfs4_close_state(path, state, nd->intent.open.flags);
+ return ret;
}
struct dentry *
nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
+ struct path path = {
+ .mnt = nd->mnt,
+ .dentry = dentry,
+ };
struct iattr attr;
struct rpc_cred *cred;
struct nfs4_state *state;
@@ -1277,7 +1410,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
if (IS_ERR(cred))
return (struct dentry *)cred;
- state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
+ state = nfs4_do_open(dir, &path, nd->intent.open.flags, &attr, cred);
put_rpccred(cred);
if (IS_ERR(state)) {
if (PTR_ERR(state) == -ENOENT)
@@ -1287,22 +1420,24 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
res = d_add_unique(dentry, igrab(state->inode));
if (res != NULL)
dentry = res;
- nfs4_intent_set_file(nd, dentry, state);
+ nfs4_intent_set_file(nd, &path, state);
return res;
}
int
nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
{
+ struct path path = {
+ .mnt = nd->mnt,
+ .dentry = dentry,
+ };
struct rpc_cred *cred;
struct nfs4_state *state;
cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0);
if (IS_ERR(cred))
return PTR_ERR(cred);
- state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
- if (IS_ERR(state))
- state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
+ state = nfs4_do_open(dir, &path, openflags, NULL, cred);
put_rpccred(cred);
if (IS_ERR(state)) {
switch (PTR_ERR(state)) {
@@ -1318,10 +1453,10 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
}
}
if (state->inode == dentry->d_inode) {
- nfs4_intent_set_file(nd, dentry, state);
+ nfs4_intent_set_file(nd, &path, state);
return 1;
}
- nfs4_close_state(state, openflags);
+ nfs4_close_state(&path, state, openflags);
out_drop:
d_drop(dentry);
return 0;
@@ -1559,8 +1694,6 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
dprintk("NFS call lookupfh %s\n", name->name);
status = rpc_call_sync(server->client, &msg, 0);
dprintk("NFS reply lookupfh: %d\n", status);
- if (status == -NFS4ERR_MOVED)
- status = -EREMOTE;
return status;
}
@@ -1571,10 +1704,13 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
struct nfs4_exception exception = { };
int err;
do {
- err = nfs4_handle_exception(server,
- _nfs4_proc_lookupfh(server, dirfh, name,
- fhandle, fattr),
- &exception);
+ err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr);
+ /* FIXME: !!!! */
+ if (err == -NFS4ERR_MOVED) {
+ err = -EREMOTE;
+ break;
+ }
+ err = nfs4_handle_exception(server, err, &exception);
} while (exception.retry);
return err;
}
@@ -1582,28 +1718,10 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
- int status;
- struct nfs_server *server = NFS_SERVER(dir);
- struct nfs4_lookup_arg args = {
- .bitmask = server->attr_bitmask,
- .dir_fh = NFS_FH(dir),
- .name = name,
- };
- struct nfs4_lookup_res res = {
- .server = server,
- .fattr = fattr,
- .fh = fhandle,
- };
- struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
- .rpc_argp = &args,
- .rpc_resp = &res,
- };
-
- nfs_fattr_init(fattr);
+ int status;
dprintk("NFS call lookup %s\n", name->name);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr);
if (status == -NFS4ERR_MOVED)
status = nfs4_get_referral(dir, name, fattr, fhandle);
dprintk("NFS reply lookup: %d\n", status);
@@ -1752,6 +1870,10 @@ static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
int flags, struct nameidata *nd)
{
+ struct path path = {
+ .mnt = nd->mnt,
+ .dentry = dentry,
+ };
struct nfs4_state *state;
struct rpc_cred *cred;
int status = 0;
@@ -1761,7 +1883,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
status = PTR_ERR(cred);
goto out;
}
- state = nfs4_do_open(dir, dentry, flags, sattr, cred);
+ state = nfs4_do_open(dir, &path, flags, sattr, cred);
put_rpccred(cred);
if (IS_ERR(state)) {
status = PTR_ERR(state);
@@ -1773,11 +1895,12 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
if (status == 0)
nfs_setattr_update_inode(state->inode, sattr);
+ nfs_post_op_update_inode(state->inode, &fattr);
}
- if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
- status = nfs4_intent_set_file(nd, dentry, state);
+ if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
+ status = nfs4_intent_set_file(nd, &path, state);
else
- nfs4_close_state(state, flags);
+ nfs4_close_state(&path, state, flags);
out:
return status;
}
@@ -3008,7 +3131,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
if (status != 0)
goto out;
lsp = request->fl_u.nfs4_fl.owner;
- arg.lock_owner.id = lsp->ls_id;
+ arg.lock_owner.id = lsp->ls_id.id;
status = rpc_call_sync(server->client, &msg, 0);
switch (status) {
case 0:
@@ -3152,6 +3275,11 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
{
struct nfs4_unlockdata *data;
+ /* Ensure this is an unlock - when canceling a lock, the
+ * canceled lock is passed in, and it won't be an unlock.
+ */
+ fl->fl_type = F_UNLCK;
+
data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
if (data == NULL) {
nfs_free_seqid(seqid);
@@ -3222,7 +3350,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
goto out_free;
p->arg.lock_stateid = &lsp->ls_stateid;
p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
- p->arg.lock_owner.id = lsp->ls_id;
+ p->arg.lock_owner.id = lsp->ls_id.id;
p->lsp = lsp;
atomic_inc(&lsp->ls_count);
p->ctx = get_nfs_open_context(ctx);
@@ -3285,7 +3413,7 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
memcpy(data->lsp->ls_stateid.data, data->res.stateid.data,
sizeof(data->lsp->ls_stateid.data));
data->lsp->ls_flags |= NFS_LOCK_INITIALIZED;
- renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp);
+ renew_lease(NFS_SERVER(data->ctx->path.dentry->d_inode), data->timestamp);
}
nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid);
out:
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 8ed79d5c54f..e9662ba81d8 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -38,12 +38,14 @@
* subsequent patch.
*/
+#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
#include <linux/kthread.h>
#include <linux/module.h>
+#include <linux/random.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
@@ -69,33 +71,14 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
return status;
}
-u32
-nfs4_alloc_lockowner_id(struct nfs_client *clp)
-{
- return clp->cl_lockowner_id ++;
-}
-
-static struct nfs4_state_owner *
-nfs4_client_grab_unused(struct nfs_client *clp, struct rpc_cred *cred)
-{
- struct nfs4_state_owner *sp = NULL;
-
- if (!list_empty(&clp->cl_unused)) {
- sp = list_entry(clp->cl_unused.next, struct nfs4_state_owner, so_list);
- atomic_inc(&sp->so_count);
- sp->so_cred = cred;
- list_move(&sp->so_list, &clp->cl_state_owners);
- clp->cl_nunused--;
- }
- return sp;
-}
-
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
{
struct nfs4_state_owner *sp;
+ struct rb_node *pos;
struct rpc_cred *cred = NULL;
- list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+ for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+ sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
if (list_empty(&sp->so_states))
continue;
cred = get_rpccred(sp->so_cred);
@@ -107,32 +90,146 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
{
struct nfs4_state_owner *sp;
+ struct rb_node *pos;
- if (!list_empty(&clp->cl_state_owners)) {
- sp = list_entry(clp->cl_state_owners.next,
- struct nfs4_state_owner, so_list);
+ pos = rb_first(&clp->cl_state_owners);
+ if (pos != NULL) {
+ sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
return get_rpccred(sp->so_cred);
}
return NULL;
}
+static void nfs_alloc_unique_id(struct rb_root *root, struct nfs_unique_id *new,
+ __u64 minval, int maxbits)
+{
+ struct rb_node **p, *parent;
+ struct nfs_unique_id *pos;
+ __u64 mask = ~0ULL;
+
+ if (maxbits < 64)
+ mask = (1ULL << maxbits) - 1ULL;
+
+ /* Ensure distribution is more or less flat */
+ get_random_bytes(&new->id, sizeof(new->id));
+ new->id &= mask;
+ if (new->id < minval)
+ new->id += minval;
+retry:
+ p = &root->rb_node;
+ parent = NULL;
+
+ while (*p != NULL) {
+ parent = *p;
+ pos = rb_entry(parent, struct nfs_unique_id, rb_node);
+
+ if (new->id < pos->id)
+ p = &(*p)->rb_left;
+ else if (new->id > pos->id)
+ p = &(*p)->rb_right;
+ else
+ goto id_exists;
+ }
+ rb_link_node(&new->rb_node, parent, p);
+ rb_insert_color(&new->rb_node, root);
+ return;
+id_exists:
+ for (;;) {
+ new->id++;
+ if (new->id < minval || (new->id & mask) != new->id) {
+ new->id = minval;
+ break;
+ }
+ parent = rb_next(parent);
+ if (parent == NULL)
+ break;
+ pos = rb_entry(parent, struct nfs_unique_id, rb_node);
+ if (new->id < pos->id)
+ break;
+ }
+ goto retry;
+}
+
+static void nfs_free_unique_id(struct rb_root *root, struct nfs_unique_id *id)
+{
+ rb_erase(&id->rb_node, root);
+}
+
static struct nfs4_state_owner *
-nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred)
+nfs4_find_state_owner(struct nfs_server *server, struct rpc_cred *cred)
{
+ struct nfs_client *clp = server->nfs_client;
+ struct rb_node **p = &clp->cl_state_owners.rb_node,
+ *parent = NULL;
struct nfs4_state_owner *sp, *res = NULL;
- list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
- if (sp->so_cred != cred)
+ while (*p != NULL) {
+ parent = *p;
+ sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
+
+ if (server < sp->so_server) {
+ p = &parent->rb_left;
continue;
- atomic_inc(&sp->so_count);
- /* Move to the head of the list */
- list_move(&sp->so_list, &clp->cl_state_owners);
- res = sp;
- break;
+ }
+ if (server > sp->so_server) {
+ p = &parent->rb_right;
+ continue;
+ }
+ if (cred < sp->so_cred)
+ p = &parent->rb_left;
+ else if (cred > sp->so_cred)
+ p = &parent->rb_right;
+ else {
+ atomic_inc(&sp->so_count);
+ res = sp;
+ break;
+ }
}
return res;
}
+static struct nfs4_state_owner *
+nfs4_insert_state_owner(struct nfs_client *clp, struct nfs4_state_owner *new)
+{
+ struct rb_node **p = &clp->cl_state_owners.rb_node,
+ *parent = NULL;
+ struct nfs4_state_owner *sp;
+
+ while (*p != NULL) {
+ parent = *p;
+ sp = rb_entry(parent, struct nfs4_state_owner, so_client_node);
+
+ if (new->so_server < sp->so_server) {
+ p = &parent->rb_left;
+ continue;
+ }
+ if (new->so_server > sp->so_server) {
+ p = &parent->rb_right;
+ continue;
+ }
+ if (new->so_cred < sp->so_cred)
+ p = &parent->rb_left;
+ else if (new->so_cred > sp->so_cred)
+ p = &parent->rb_right;
+ else {
+ atomic_inc(&sp->so_count);
+ return sp;
+ }
+ }
+ nfs_alloc_unique_id(&clp->cl_openowner_id, &new->so_owner_id, 1, 64);
+ rb_link_node(&new->so_client_node, parent, p);
+ rb_insert_color(&new->so_client_node, &clp->cl_state_owners);
+ return new;
+}
+
+static void
+nfs4_remove_state_owner(struct nfs_client *clp, struct nfs4_state_owner *sp)
+{
+ if (!RB_EMPTY_NODE(&sp->so_client_node))
+ rb_erase(&sp->so_client_node, &clp->cl_state_owners);
+ nfs_free_unique_id(&clp->cl_openowner_id, &sp->so_owner_id);
+}
+
/*
* nfs4_alloc_state_owner(): this is called on the OPEN or CREATE path to
* create a new state_owner.
@@ -160,10 +257,14 @@ nfs4_alloc_state_owner(void)
void
nfs4_drop_state_owner(struct nfs4_state_owner *sp)
{
- struct nfs_client *clp = sp->so_client;
- spin_lock(&clp->cl_lock);
- list_del_init(&sp->so_list);
- spin_unlock(&clp->cl_lock);
+ if (!RB_EMPTY_NODE(&sp->so_client_node)) {
+ struct nfs_client *clp = sp->so_client;
+
+ spin_lock(&clp->cl_lock);
+ rb_erase(&sp->so_client_node, &clp->cl_state_owners);
+ RB_CLEAR_NODE(&sp->so_client_node);
+ spin_unlock(&clp->cl_lock);
+ }
}
/*
@@ -175,26 +276,25 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct
struct nfs_client *clp = server->nfs_client;
struct nfs4_state_owner *sp, *new;
- get_rpccred(cred);
- new = nfs4_alloc_state_owner();
spin_lock(&clp->cl_lock);
- sp = nfs4_find_state_owner(clp, cred);
- if (sp == NULL)
- sp = nfs4_client_grab_unused(clp, cred);
- if (sp == NULL && new != NULL) {
- list_add(&new->so_list, &clp->cl_state_owners);
- new->so_client = clp;
- new->so_id = nfs4_alloc_lockowner_id(clp);
- new->so_cred = cred;
- sp = new;
- new = NULL;
- }
+ sp = nfs4_find_state_owner(server, cred);
spin_unlock(&clp->cl_lock);
- kfree(new);
if (sp != NULL)
return sp;
- put_rpccred(cred);
- return NULL;
+ new = nfs4_alloc_state_owner();
+ if (new == NULL)
+ return NULL;
+ new->so_client = clp;
+ new->so_server = server;
+ new->so_cred = cred;
+ spin_lock(&clp->cl_lock);
+ sp = nfs4_insert_state_owner(clp, new);
+ spin_unlock(&clp->cl_lock);
+ if (sp == new)
+ get_rpccred(cred);
+ else
+ kfree(new);
+ return sp;
}
/*
@@ -208,18 +308,7 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock))
return;
- if (clp->cl_nunused >= OPENOWNER_POOL_SIZE)
- goto out_free;
- if (list_empty(&sp->so_list))
- goto out_free;
- list_move(&sp->so_list, &clp->cl_unused);
- clp->cl_nunused++;
- spin_unlock(&clp->cl_lock);
- put_rpccred(cred);
- cred = NULL;
- return;
-out_free:
- list_del(&sp->so_list);
+ nfs4_remove_state_owner(clp, sp);
spin_unlock(&clp->cl_lock);
put_rpccred(cred);
kfree(sp);
@@ -236,6 +325,7 @@ nfs4_alloc_open_state(void)
atomic_set(&state->count, 1);
INIT_LIST_HEAD(&state->lock_states);
spin_lock_init(&state->state_lock);
+ seqlock_init(&state->seqlock);
return state;
}
@@ -263,13 +353,10 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
struct nfs4_state *state;
list_for_each_entry(state, &nfsi->open_states, inode_states) {
- /* Is this in the process of being freed? */
- if (state->state == 0)
+ if (state->owner != owner)
continue;
- if (state->owner == owner) {
- atomic_inc(&state->count);
+ if (atomic_inc_not_zero(&state->count))
return state;
- }
}
return NULL;
}
@@ -341,16 +428,15 @@ void nfs4_put_open_state(struct nfs4_state *state)
/*
* Close the current file.
*/
-void nfs4_close_state(struct nfs4_state *state, mode_t mode)
+void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
{
- struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner;
- int oldstate, newstate = 0;
+ int call_close = 0;
+ int newstate;
atomic_inc(&owner->so_count);
/* Protect against nfs4_find_state() */
spin_lock(&owner->so_lock);
- spin_lock(&inode->i_lock);
switch (mode & (FMODE_READ | FMODE_WRITE)) {
case FMODE_READ:
state->n_rdonly--;
@@ -361,24 +447,29 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
case FMODE_READ|FMODE_WRITE:
state->n_rdwr--;
}
- oldstate = newstate = state->state;
+ newstate = FMODE_READ|FMODE_WRITE;
if (state->n_rdwr == 0) {
- if (state->n_rdonly == 0)
+ if (state->n_rdonly == 0) {
newstate &= ~FMODE_READ;
- if (state->n_wronly == 0)
+ call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags);
+ call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+ }
+ if (state->n_wronly == 0) {
newstate &= ~FMODE_WRITE;
+ call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags);
+ call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+ }
+ if (newstate == 0)
+ clear_bit(NFS_DELEGATED_STATE, &state->flags);
}
- if (test_bit(NFS_DELEGATED_STATE, &state->flags)) {
- nfs4_state_set_mode_locked(state, newstate);
- oldstate = newstate;
- }
- spin_unlock(&inode->i_lock);
+ nfs4_state_set_mode_locked(state, newstate);
spin_unlock(&owner->so_lock);
- if (oldstate != newstate && nfs4_do_close(inode, state) == 0)
- return;
- nfs4_put_open_state(state);
- nfs4_put_state_owner(owner);
+ if (!call_close) {
+ nfs4_put_open_state(state);
+ nfs4_put_state_owner(owner);
+ } else
+ nfs4_do_close(path, state);
}
/*
@@ -415,12 +506,22 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
atomic_set(&lsp->ls_count, 1);
lsp->ls_owner = fl_owner;
spin_lock(&clp->cl_lock);
- lsp->ls_id = nfs4_alloc_lockowner_id(clp);
+ nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
spin_unlock(&clp->cl_lock);
INIT_LIST_HEAD(&lsp->ls_locks);
return lsp;
}
+static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
+{
+ struct nfs_client *clp = lsp->ls_state->owner->so_client;
+
+ spin_lock(&clp->cl_lock);
+ nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id);
+ spin_unlock(&clp->cl_lock);
+ kfree(lsp);
+}
+
/*
* Return a compatible lock_state. If no initialized lock_state structure
* exists, return an uninitialized one.
@@ -450,7 +551,8 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
return NULL;
}
spin_unlock(&state->state_lock);
- kfree(new);
+ if (new != NULL)
+ nfs4_free_lock_state(new);
return lsp;
}
@@ -471,7 +573,7 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
if (list_empty(&state->lock_states))
clear_bit(LK_STATE_IN_USE, &state->flags);
spin_unlock(&state->state_lock);
- kfree(lsp);
+ nfs4_free_lock_state(lsp);
}
static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
@@ -513,8 +615,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
{
struct nfs4_lock_state *lsp;
+ int seq;
- memcpy(dst, &state->stateid, sizeof(*dst));
+ do {
+ seq = read_seqbegin(&state->seqlock);
+ memcpy(dst, &state->stateid, sizeof(*dst));
+ } while (read_seqretry(&state->seqlock, seq));
if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
return;
@@ -557,12 +663,18 @@ void nfs_free_seqid(struct nfs_seqid *seqid)
* failed with a seqid incrementing error -
* see comments nfs_fs.h:seqid_mutating_error()
*/
-static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
+static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
{
switch (status) {
case 0:
break;
case -NFS4ERR_BAD_SEQID:
+ if (seqid->sequence->flags & NFS_SEQID_CONFIRMED)
+ return;
+ printk(KERN_WARNING "NFS: v4 server returned a bad"
+ "sequence-id error on an"
+ "unconfirmed sequence %p!\n",
+ seqid->sequence);
case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_BAD_STATEID:
@@ -586,7 +698,7 @@ void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
struct nfs4_state_owner, so_seqid);
nfs4_drop_state_owner(sp);
}
- return nfs_increment_seqid(status, seqid);
+ nfs_increment_seqid(status, seqid);
}
/*
@@ -596,7 +708,7 @@ void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
*/
void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid)
{
- return nfs_increment_seqid(status, seqid);
+ nfs_increment_seqid(status, seqid);
}
int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task)
@@ -748,15 +860,21 @@ out_err:
static void nfs4_state_mark_reclaim(struct nfs_client *clp)
{
struct nfs4_state_owner *sp;
+ struct rb_node *pos;
struct nfs4_state *state;
struct nfs4_lock_state *lock;
/* Reset all sequence ids to zero */
- list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+ for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+ sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
sp->so_seqid.counter = 0;
sp->so_seqid.flags = 0;
spin_lock(&sp->so_lock);
list_for_each_entry(state, &sp->so_states, open_states) {
+ clear_bit(NFS_DELEGATED_STATE, &state->flags);
+ clear_bit(NFS_O_RDONLY_STATE, &state->flags);
+ clear_bit(NFS_O_WRONLY_STATE, &state->flags);
+ clear_bit(NFS_O_RDWR_STATE, &state->flags);
list_for_each_entry(lock, &state->lock_states, ls_locks) {
lock->ls_seqid.counter = 0;
lock->ls_seqid.flags = 0;
@@ -771,6 +889,7 @@ static int reclaimer(void *ptr)
{
struct nfs_client *clp = ptr;
struct nfs4_state_owner *sp;
+ struct rb_node *pos;
struct nfs4_state_recovery_ops *ops;
struct rpc_cred *cred;
int status = 0;
@@ -816,7 +935,8 @@ restart_loop:
/* Mark all delegations for reclaim */
nfs_delegation_mark_reclaim(clp);
/* Note: list is protected by exclusive lock on cl->cl_sem */
- list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
+ for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
+ sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
status = nfs4_reclaim_open_state(ops, sp);
if (status < 0) {
if (status == -NFS4ERR_NO_GRACE) {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 8003c91ccb9..c08738441f7 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -68,9 +68,10 @@ static int nfs4_stat_to_errno(int);
#endif
/* lock,open owner id:
- * we currently use size 1 (u32) out of (NFS4_OPAQUE_LIMIT >> 2)
+ * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2)
*/
-#define owner_id_maxsz (1 + 1)
+#define open_owner_id_maxsz (1 + 4)
+#define lock_owner_id_maxsz (1 + 4)
#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
#define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
#define op_encode_hdr_maxsz (1)
@@ -87,9 +88,11 @@ static int nfs4_stat_to_errno(int);
#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
+#define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
+#define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
/* This is based on getfattr, which uses the most attributes: */
#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
- 3 + 3 + 3 + 2 * nfs4_name_maxsz))
+ 3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz))
#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
nfs4_fattr_value_maxsz)
#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
@@ -116,8 +119,27 @@ static int nfs4_stat_to_errno(int);
3 + (NFS4_VERIFIER_SIZE >> 2))
#define decode_setclientid_confirm_maxsz \
(op_decode_hdr_maxsz)
-#define encode_lookup_maxsz (op_encode_hdr_maxsz + \
- 1 + ((3 + NFS4_FHSIZE) >> 2))
+#define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
+#define decode_lookup_maxsz (op_decode_hdr_maxsz)
+#define encode_share_access_maxsz \
+ (2)
+#define encode_createmode_maxsz (1 + nfs4_fattr_maxsz)
+#define encode_opentype_maxsz (1 + encode_createmode_maxsz)
+#define encode_claim_null_maxsz (1 + nfs4_name_maxsz)
+#define encode_open_maxsz (op_encode_hdr_maxsz + \
+ 2 + encode_share_access_maxsz + 2 + \
+ open_owner_id_maxsz + \
+ encode_opentype_maxsz + \
+ encode_claim_null_maxsz)
+#define decode_ace_maxsz (3 + nfs4_owner_maxsz)
+#define decode_delegation_maxsz (1 + XDR_QUADLEN(NFS4_STATEID_SIZE) + 1 + \
+ decode_ace_maxsz)
+#define decode_change_info_maxsz (5)
+#define decode_open_maxsz (op_decode_hdr_maxsz + \
+ XDR_QUADLEN(NFS4_STATEID_SIZE) + \
+ decode_change_info_maxsz + 1 + \
+ nfs4_fattr_bitmap_maxsz + \
+ decode_delegation_maxsz)
#define encode_remove_maxsz (op_encode_hdr_maxsz + \
nfs4_name_maxsz)
#define encode_rename_maxsz (op_encode_hdr_maxsz + \
@@ -134,9 +156,15 @@ static int nfs4_stat_to_errno(int);
#define encode_create_maxsz (op_encode_hdr_maxsz + \
2 + nfs4_name_maxsz + \
nfs4_fattr_maxsz)
-#define decode_create_maxsz (op_decode_hdr_maxsz + 8)
+#define decode_create_maxsz (op_decode_hdr_maxsz + \
+ decode_change_info_maxsz + \
+ nfs4_fattr_bitmap_maxsz)
#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
+#define encode_fs_locations_maxsz \
+ (encode_getattr_maxsz)
+#define decode_fs_locations_maxsz \
+ (0)
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
@@ -174,16 +202,21 @@ static int nfs4_stat_to_errno(int);
op_decode_hdr_maxsz + 2 + \
decode_getattr_maxsz)
#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
- encode_putfh_maxsz + \
- op_encode_hdr_maxsz + \
- 13 + 3 + 2 + 64 + \
- encode_getattr_maxsz + \
- encode_getfh_maxsz)
+ encode_putfh_maxsz + \
+ encode_savefh_maxsz + \
+ encode_open_maxsz + \
+ encode_getfh_maxsz + \
+ encode_getattr_maxsz + \
+ encode_restorefh_maxsz + \
+ encode_getattr_maxsz)
#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
- decode_putfh_maxsz + \
- op_decode_hdr_maxsz + 4 + 5 + 2 + 3 + \
- decode_getattr_maxsz + \
- decode_getfh_maxsz)
+ decode_putfh_maxsz + \
+ decode_savefh_maxsz + \
+ decode_open_maxsz + \
+ decode_getfh_maxsz + \
+ decode_getattr_maxsz + \
+ decode_restorefh_maxsz + \
+ decode_getattr_maxsz)
#define NFS4_enc_open_confirm_sz \
(compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
@@ -193,12 +226,12 @@ static int nfs4_stat_to_errno(int);
op_decode_hdr_maxsz + 4)
#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
- op_encode_hdr_maxsz + \
- 11)
+ encode_open_maxsz + \
+ encode_getattr_maxsz)
#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
- op_decode_hdr_maxsz + \
- 4 + 5 + 2 + 3)
+ decode_open_maxsz + \
+ decode_getattr_maxsz)
#define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
@@ -256,19 +289,19 @@ static int nfs4_stat_to_errno(int);
op_encode_hdr_maxsz + \
1 + 1 + 2 + 2 + \
1 + 4 + 1 + 2 + \
- owner_id_maxsz)
+ lock_owner_id_maxsz)
#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz + \
op_decode_hdr_maxsz + \
2 + 2 + 1 + 2 + \
- owner_id_maxsz)
+ lock_owner_id_maxsz)
#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz + \
op_encode_hdr_maxsz + \
1 + 2 + 2 + 2 + \
- owner_id_maxsz)
+ lock_owner_id_maxsz)
#define NFS4_dec_lockt_sz (NFS4_dec_lock_sz)
#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
@@ -298,7 +331,7 @@ static int nfs4_stat_to_errno(int);
encode_getfh_maxsz)
#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
- op_decode_hdr_maxsz + \
+ decode_lookup_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
@@ -417,12 +450,13 @@ static int nfs4_stat_to_errno(int);
#define NFS4_enc_fs_locations_sz \
(compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
- encode_getattr_maxsz)
+ encode_lookup_maxsz + \
+ encode_fs_locations_maxsz)
#define NFS4_dec_fs_locations_sz \
(compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
- op_decode_hdr_maxsz + \
- nfs4_fattr_bitmap_maxsz)
+ decode_lookup_maxsz + \
+ decode_fs_locations_maxsz)
static struct {
unsigned int mode;
@@ -793,13 +827,14 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)
WRITE64(nfs4_lock_length(args->fl));
WRITE32(args->new_lock_owner);
if (args->new_lock_owner){
- RESERVE_SPACE(4+NFS4_STATEID_SIZE+20);
+ RESERVE_SPACE(4+NFS4_STATEID_SIZE+32);
WRITE32(args->open_seqid->sequence->counter);
WRITEMEM(args->open_stateid->data, NFS4_STATEID_SIZE);
WRITE32(args->lock_seqid->sequence->counter);
WRITE64(args->lock_owner.clientid);
- WRITE32(4);
- WRITE32(args->lock_owner.id);
+ WRITE32(16);
+ WRITEMEM("lock id:", 8);
+ WRITE64(args->lock_owner.id);
}
else {
RESERVE_SPACE(NFS4_STATEID_SIZE+4);
@@ -814,14 +849,15 @@ static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *arg
{
__be32 *p;
- RESERVE_SPACE(40);
+ RESERVE_SPACE(52);
WRITE32(OP_LOCKT);
WRITE32(nfs4_lock_type(args->fl, 0));
WRITE64(args->fl->fl_start);
WRITE64(nfs4_lock_length(args->fl));
WRITE64(args->lock_owner.clientid);
- WRITE32(4);
- WRITE32(args->lock_owner.id);
+ WRITE32(16);
+ WRITEMEM("lock id:", 8);
+ WRITE64(args->lock_owner.id);
return 0;
}
@@ -886,10 +922,11 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
WRITE32(OP_OPEN);
WRITE32(arg->seqid->sequence->counter);
encode_share_access(xdr, arg->open_flags);
- RESERVE_SPACE(16);
+ RESERVE_SPACE(28);
WRITE64(arg->clientid);
- WRITE32(4);
- WRITE32(arg->id);
+ WRITE32(16);
+ WRITEMEM("open id:", 8);
+ WRITE64(arg->id);
}
static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
@@ -1071,7 +1108,7 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
uint32_t attrs[2] = {
FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
FATTR4_WORD1_MOUNTED_ON_FILEID,
@@ -1117,7 +1154,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
__be32 *p;
@@ -1735,7 +1772,7 @@ out:
*/
static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
{
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
@@ -1795,7 +1832,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
struct nfs_getaclargs *args)
{
struct xdr_stream xdr;
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
struct compound_hdr hdr = {
.nops = 2,
};
@@ -2030,7 +2067,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
struct compound_hdr hdr = {
.nops = 3,
};
- struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
int replen;
int status;
@@ -3269,7 +3306,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
{
__be32 *p;
- uint32_t bmlen;
+ uint32_t savewords, bmlen, i;
int status;
status = decode_op_hdr(xdr, OP_OPEN);
@@ -3287,7 +3324,12 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
goto xdr_error;
READ_BUF(bmlen << 2);
- p += bmlen;
+ savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
+ for (i = 0; i < savewords; ++i)
+ READ32(res->attrset[i]);
+ for (; i < NFS4_BITMAP_SIZE; i++)
+ res->attrset[i] = 0;
+
return decode_delegation(xdr, res);
xdr_error:
dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen);
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index 49d1008ce1d..3490322d114 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -428,7 +428,7 @@ static int __init root_nfs_getport(int program, int version, int proto)
printk(KERN_NOTICE "Looking up port of RPC %d/%d on %u.%u.%u.%u\n",
program, version, NIPQUAD(servaddr));
set_sockaddr(&sin, servaddr, 0);
- return rpcb_getport_external(&sin, program, version, proto);
+ return rpcb_getport_sync(&sin, program, version, proto);
}
@@ -496,7 +496,8 @@ static int __init root_nfs_get_handle(void)
NFS_MNT3_VERSION : NFS_MNT_VERSION;
set_sockaddr(&sin, servaddr, htons(mount_port));
- status = nfsroot_mount(&sin, nfs_path, &fh, version, protocol);
+ status = nfs_mount((struct sockaddr *) &sin, sizeof(sin), NULL,
+ nfs_path, version, protocol, &fh);
if (status < 0)
printk(KERN_ERR "Root-NFS: Server returned error %d "
"while mounting %s\n", status, nfs_path);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index c5bb51a29e8..f56dae5216f 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -85,9 +85,8 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
req->wb_offset = offset;
req->wb_pgbase = offset;
req->wb_bytes = count;
- atomic_set(&req->wb_count, 1);
req->wb_context = get_nfs_open_context(ctx);
-
+ kref_init(&req->wb_kref);
return req;
}
@@ -109,30 +108,31 @@ void nfs_unlock_request(struct nfs_page *req)
}
/**
- * nfs_set_page_writeback_locked - Lock a request for writeback
+ * nfs_set_page_tag_locked - Tag a request as locked
* @req:
*/
-int nfs_set_page_writeback_locked(struct nfs_page *req)
+static int nfs_set_page_tag_locked(struct nfs_page *req)
{
- struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+ struct nfs_inode *nfsi = NFS_I(req->wb_context->path.dentry->d_inode);
if (!nfs_lock_request(req))
return 0;
- radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+ radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
return 1;
}
/**
- * nfs_clear_page_writeback - Unlock request and wake up sleepers
+ * nfs_clear_page_tag_locked - Clear request tag and wake up sleepers
*/
-void nfs_clear_page_writeback(struct nfs_page *req)
+void nfs_clear_page_tag_locked(struct nfs_page *req)
{
- struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+ struct inode *inode = req->wb_context->path.dentry->d_inode;
+ struct nfs_inode *nfsi = NFS_I(inode);
if (req->wb_page != NULL) {
- spin_lock(&nfsi->req_lock);
- radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
- spin_unlock(&nfsi->req_lock);
+ spin_lock(&inode->i_lock);
+ radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
+ spin_unlock(&inode->i_lock);
}
nfs_unlock_request(req);
}
@@ -160,11 +160,9 @@ void nfs_clear_request(struct nfs_page *req)
*
* Note: Should never be called with the spinlock held!
*/
-void
-nfs_release_request(struct nfs_page *req)
+static void nfs_free_request(struct kref *kref)
{
- if (!atomic_dec_and_test(&req->wb_count))
- return;
+ struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
/* Release struct file or cached credential */
nfs_clear_request(req);
@@ -172,6 +170,11 @@ nfs_release_request(struct nfs_page *req)
nfs_page_free(req);
}
+void nfs_release_request(struct nfs_page *req)
+{
+ kref_put(&req->wb_kref, nfs_free_request);
+}
+
static int nfs_wait_bit_interruptible(void *word)
{
int ret = 0;
@@ -193,7 +196,7 @@ static int nfs_wait_bit_interruptible(void *word)
int
nfs_wait_on_request(struct nfs_page *req)
{
- struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->dentry->d_inode);
+ struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->path.dentry->d_inode);
sigset_t oldmask;
int ret = 0;
@@ -379,20 +382,20 @@ void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
/**
* nfs_scan_list - Scan a list for matching requests
* @nfsi: NFS inode
- * @head: One of the NFS inode request lists
* @dst: Destination list
* @idx_start: lower bound of page->index to scan
* @npages: idx_start + npages sets the upper bound to scan.
+ * @tag: tag to scan for
*
* Moves elements from one of the inode request lists.
* If the number of requests is set to 0, the entire address_space
* starting at index idx_start, is scanned.
* The requests are *not* checked to ensure that they form a contiguous set.
- * You must be holding the inode's req_lock when calling this function
+ * You must be holding the inode's i_lock when calling this function
*/
-int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
+int nfs_scan_list(struct nfs_inode *nfsi,
struct list_head *dst, pgoff_t idx_start,
- unsigned int npages)
+ unsigned int npages, int tag)
{
struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
struct nfs_page *req;
@@ -407,9 +410,9 @@ int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
idx_end = idx_start + npages - 1;
for (;;) {
- found = radix_tree_gang_lookup(&nfsi->nfs_page_tree,
+ found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
(void **)&pgvec[0], idx_start,
- NFS_SCAN_MAXENTRIES);
+ NFS_SCAN_MAXENTRIES, tag);
if (found <= 0)
break;
for (i = 0; i < found; i++) {
@@ -417,15 +420,18 @@ int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
if (req->wb_index > idx_end)
goto out;
idx_start = req->wb_index + 1;
- if (req->wb_list_head != head)
- continue;
- if (nfs_set_page_writeback_locked(req)) {
+ if (nfs_set_page_tag_locked(req)) {
nfs_list_remove_request(req);
+ radix_tree_tag_clear(&nfsi->nfs_page_tree,
+ req->wb_index, tag);
nfs_list_add_request(req, dst);
res++;
+ if (res == INT_MAX)
+ goto out;
}
}
-
+ /* for latency reduction */
+ cond_resched_lock(&nfsi->vfs_inode.i_lock);
}
out:
return res;
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 7bd7cb95c03..6ae2e58ed05 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -145,8 +145,8 @@ static void nfs_readpage_release(struct nfs_page *req)
unlock_page(req->wb_page);
dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
- req->wb_context->dentry->d_inode->i_sb->s_id,
- (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+ req->wb_context->path.dentry->d_inode->i_sb->s_id,
+ (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
req->wb_bytes,
(long long)req_offset(req));
nfs_clear_request(req);
@@ -164,7 +164,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
int flags;
data->req = req;
- data->inode = inode = req->wb_context->dentry->d_inode;
+ data->inode = inode = req->wb_context->path.dentry->d_inode;
data->cred = req->wb_context->cred;
data->args.fh = NFS_FH(inode);
@@ -483,17 +483,19 @@ int nfs_readpage(struct file *file, struct page *page)
*/
error = nfs_wb_page(inode, page);
if (error)
- goto out_error;
+ goto out_unlock;
+ if (PageUptodate(page))
+ goto out_unlock;
error = -ESTALE;
if (NFS_STALE(inode))
- goto out_error;
+ goto out_unlock;
if (file == NULL) {
error = -EBADF;
ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
if (ctx == NULL)
- goto out_error;
+ goto out_unlock;
} else
ctx = get_nfs_open_context((struct nfs_open_context *)
file->private_data);
@@ -502,8 +504,7 @@ int nfs_readpage(struct file *file, struct page *page)
put_nfs_open_context(ctx);
return error;
-
-out_error:
+out_unlock:
unlock_page(page);
return error;
}
@@ -520,21 +521,32 @@ readpage_async_filler(void *data, struct page *page)
struct inode *inode = page->mapping->host;
struct nfs_page *new;
unsigned int len;
+ int error;
+
+ error = nfs_wb_page(inode, page);
+ if (error)
+ goto out_unlock;
+ if (PageUptodate(page))
+ goto out_unlock;
- nfs_wb_page(inode, page);
len = nfs_page_length(page);
if (len == 0)
return nfs_return_empty_page(page);
+
new = nfs_create_request(desc->ctx, inode, page, 0, len);
- if (IS_ERR(new)) {
- SetPageError(page);
- unlock_page(page);
- return PTR_ERR(new);
- }
+ if (IS_ERR(new))
+ goto out_error;
+
if (len < PAGE_CACHE_SIZE)
zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0);
nfs_pageio_add_request(desc->pgio, new);
return 0;
+out_error:
+ error = PTR_ERR(new);
+ SetPageError(page);
+out_unlock:
+ unlock_page(page);
+ return error;
}
int nfs_readpages(struct file *filp, struct address_space *mapping,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ca20d3cc260..a2b1af89ca1 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -45,6 +45,7 @@
#include <linux/inet.h>
#include <linux/nfs_xdr.h>
#include <linux/magic.h>
+#include <linux/parser.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -57,6 +58,167 @@
#define NFSDBG_FACILITY NFSDBG_VFS
+
+struct nfs_parsed_mount_data {
+ int flags;
+ int rsize, wsize;
+ int timeo, retrans;
+ int acregmin, acregmax,
+ acdirmin, acdirmax;
+ int namlen;
+ unsigned int bsize;
+ unsigned int auth_flavor_len;
+ rpc_authflavor_t auth_flavors[1];
+ char *client_address;
+
+ struct {
+ struct sockaddr_in address;
+ unsigned int program;
+ unsigned int version;
+ unsigned short port;
+ int protocol;
+ } mount_server;
+
+ struct {
+ struct sockaddr_in address;
+ char *hostname;
+ char *export_path;
+ unsigned int program;
+ int protocol;
+ } nfs_server;
+};
+
+enum {
+ /* Mount options that take no arguments */
+ Opt_soft, Opt_hard,
+ Opt_intr, Opt_nointr,
+ Opt_posix, Opt_noposix,
+ Opt_cto, Opt_nocto,
+ Opt_ac, Opt_noac,
+ Opt_lock, Opt_nolock,
+ Opt_v2, Opt_v3,
+ Opt_udp, Opt_tcp,
+ Opt_acl, Opt_noacl,
+ Opt_rdirplus, Opt_nordirplus,
+ Opt_sharecache, Opt_nosharecache,
+
+ /* Mount options that take integer arguments */
+ Opt_port,
+ Opt_rsize, Opt_wsize, Opt_bsize,
+ Opt_timeo, Opt_retrans,
+ Opt_acregmin, Opt_acregmax,
+ Opt_acdirmin, Opt_acdirmax,
+ Opt_actimeo,
+ Opt_namelen,
+ Opt_mountport,
+ Opt_mountprog, Opt_mountvers,
+ Opt_nfsprog, Opt_nfsvers,
+
+ /* Mount options that take string arguments */
+ Opt_sec, Opt_proto, Opt_mountproto,
+ Opt_addr, Opt_mounthost, Opt_clientaddr,
+
+ /* Mount options that are ignored */
+ Opt_userspace, Opt_deprecated,
+
+ Opt_err
+};
+
+static match_table_t nfs_mount_option_tokens = {
+ { Opt_userspace, "bg" },
+ { Opt_userspace, "fg" },
+ { Opt_soft, "soft" },
+ { Opt_hard, "hard" },
+ { Opt_intr, "intr" },
+ { Opt_nointr, "nointr" },
+ { Opt_posix, "posix" },
+ { Opt_noposix, "noposix" },
+ { Opt_cto, "cto" },
+ { Opt_nocto, "nocto" },
+ { Opt_ac, "ac" },
+ { Opt_noac, "noac" },
+ { Opt_lock, "lock" },
+ { Opt_nolock, "nolock" },
+ { Opt_v2, "v2" },
+ { Opt_v3, "v3" },
+ { Opt_udp, "udp" },
+ { Opt_tcp, "tcp" },
+ { Opt_acl, "acl" },
+ { Opt_noacl, "noacl" },
+ { Opt_rdirplus, "rdirplus" },
+ { Opt_nordirplus, "nordirplus" },
+ { Opt_sharecache, "sharecache" },
+ { Opt_nosharecache, "nosharecache" },
+
+ { Opt_port, "port=%u" },
+ { Opt_rsize, "rsize=%u" },
+ { Opt_wsize, "wsize=%u" },
+ { Opt_bsize, "bsize=%u" },
+ { Opt_timeo, "timeo=%u" },
+ { Opt_retrans, "retrans=%u" },
+ { Opt_acregmin, "acregmin=%u" },
+ { Opt_acregmax, "acregmax=%u" },
+ { Opt_acdirmin, "acdirmin=%u" },
+ { Opt_acdirmax, "acdirmax=%u" },
+ { Opt_actimeo, "actimeo=%u" },
+ { Opt_userspace, "retry=%u" },
+ { Opt_namelen, "namlen=%u" },
+ { Opt_mountport, "mountport=%u" },
+ { Opt_mountprog, "mountprog=%u" },
+ { Opt_mountvers, "mountvers=%u" },
+ { Opt_nfsprog, "nfsprog=%u" },
+ { Opt_nfsvers, "nfsvers=%u" },
+ { Opt_nfsvers, "vers=%u" },
+
+ { Opt_sec, "sec=%s" },
+ { Opt_proto, "proto=%s" },
+ { Opt_mountproto, "mountproto=%s" },
+ { Opt_addr, "addr=%s" },
+ { Opt_clientaddr, "clientaddr=%s" },
+ { Opt_mounthost, "mounthost=%s" },
+
+ { Opt_err, NULL }
+};
+
+enum {
+ Opt_xprt_udp, Opt_xprt_tcp,
+
+ Opt_xprt_err
+};
+
+static match_table_t nfs_xprt_protocol_tokens = {
+ { Opt_xprt_udp, "udp" },
+ { Opt_xprt_tcp, "tcp" },
+
+ { Opt_xprt_err, NULL }
+};
+
+enum {
+ Opt_sec_none, Opt_sec_sys,
+ Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,
+ Opt_sec_lkey, Opt_sec_lkeyi, Opt_sec_lkeyp,
+ Opt_sec_spkm, Opt_sec_spkmi, Opt_sec_spkmp,
+
+ Opt_sec_err
+};
+
+static match_table_t nfs_secflavor_tokens = {
+ { Opt_sec_none, "none" },
+ { Opt_sec_none, "null" },
+ { Opt_sec_sys, "sys" },
+
+ { Opt_sec_krb5, "krb5" },
+ { Opt_sec_krb5i, "krb5i" },
+ { Opt_sec_krb5p, "krb5p" },
+
+ { Opt_sec_lkey, "lkey" },
+ { Opt_sec_lkeyi, "lkeyi" },
+ { Opt_sec_lkeyp, "lkeyp" },
+
+ { Opt_sec_err, NULL }
+};
+
+
static void nfs_umount_begin(struct vfsmount *, int);
static int nfs_statfs(struct dentry *, struct kstatfs *);
static int nfs_show_options(struct seq_file *, struct vfsmount *);
@@ -263,11 +425,11 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
{ RPC_AUTH_GSS_SPKM, "spkm" },
{ RPC_AUTH_GSS_SPKMI, "spkmi" },
{ RPC_AUTH_GSS_SPKMP, "spkmp" },
- { -1, "unknown" }
+ { UINT_MAX, "unknown" }
};
int i;
- for (i=0; sec_flavours[i].flavour != -1; i++) {
+ for (i = 0; sec_flavours[i].flavour != UINT_MAX; i++) {
if (sec_flavours[i].flavour == flavour)
break;
}
@@ -291,6 +453,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
{ NFS_MOUNT_NONLM, ",nolock", "" },
{ NFS_MOUNT_NOACL, ",noacl", "" },
{ NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },
+ { NFS_MOUNT_UNSHARED, ",nosharecache", ""},
{ 0, NULL, NULL }
};
const struct proc_nfs_info *nfs_infop;
@@ -430,87 +593,641 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
*/
static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
{
+ struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
+ struct rpc_clnt *rpc;
+
shrink_submounts(vfsmnt, &nfs_automount_list);
+
+ if (!(flags & MNT_FORCE))
+ return;
+ /* -EIO all pending I/O */
+ rpc = server->client_acl;
+ if (!IS_ERR(rpc))
+ rpc_killall_tasks(rpc);
+ rpc = server->client;
+ if (!IS_ERR(rpc))
+ rpc_killall_tasks(rpc);
}
/*
- * Validate the NFS2/NFS3 mount data
- * - fills in the mount root filehandle
+ * Sanity-check a server address provided by the mount command
*/
-static int nfs_validate_mount_data(struct nfs_mount_data *data,
- struct nfs_fh *mntfh)
+static int nfs_verify_server_address(struct sockaddr *addr)
{
- if (data == NULL) {
- dprintk("%s: missing data argument\n", __FUNCTION__);
- return -EINVAL;
+ switch (addr->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sa = (struct sockaddr_in *) addr;
+ if (sa->sin_addr.s_addr != INADDR_ANY)
+ return 1;
+ break;
+ }
}
- if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
- dprintk("%s: bad mount version\n", __FUNCTION__);
- return -EINVAL;
+ return 0;
+}
+
+/*
+ * Error-check and convert a string of mount options from user space into
+ * a data structure
+ */
+static int nfs_parse_mount_options(char *raw,
+ struct nfs_parsed_mount_data *mnt)
+{
+ char *p, *string;
+
+ if (!raw) {
+ dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
+ return 1;
}
+ dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
- switch (data->version) {
- case 1:
- data->namlen = 0;
- case 2:
- data->bsize = 0;
- case 3:
- if (data->flags & NFS_MOUNT_VER3) {
- dprintk("%s: mount structure version %d does not support NFSv3\n",
- __FUNCTION__,
- data->version);
- return -EINVAL;
+ while ((p = strsep(&raw, ",")) != NULL) {
+ substring_t args[MAX_OPT_ARGS];
+ int option, token;
+
+ if (!*p)
+ continue;
+
+ dfprintk(MOUNT, "NFS: parsing nfs mount option '%s'\n", p);
+
+ token = match_token(p, nfs_mount_option_tokens, args);
+ switch (token) {
+ case Opt_soft:
+ mnt->flags |= NFS_MOUNT_SOFT;
+ break;
+ case Opt_hard:
+ mnt->flags &= ~NFS_MOUNT_SOFT;
+ break;
+ case Opt_intr:
+ mnt->flags |= NFS_MOUNT_INTR;
+ break;
+ case Opt_nointr:
+ mnt->flags &= ~NFS_MOUNT_INTR;
+ break;
+ case Opt_posix:
+ mnt->flags |= NFS_MOUNT_POSIX;
+ break;
+ case Opt_noposix:
+ mnt->flags &= ~NFS_MOUNT_POSIX;
+ break;
+ case Opt_cto:
+ mnt->flags &= ~NFS_MOUNT_NOCTO;
+ break;
+ case Opt_nocto:
+ mnt->flags |= NFS_MOUNT_NOCTO;
+ break;
+ case Opt_ac:
+ mnt->flags &= ~NFS_MOUNT_NOAC;
+ break;
+ case Opt_noac:
+ mnt->flags |= NFS_MOUNT_NOAC;
+ break;
+ case Opt_lock:
+ mnt->flags &= ~NFS_MOUNT_NONLM;
+ break;
+ case Opt_nolock:
+ mnt->flags |= NFS_MOUNT_NONLM;
+ break;
+ case Opt_v2:
+ mnt->flags &= ~NFS_MOUNT_VER3;
+ break;
+ case Opt_v3:
+ mnt->flags |= NFS_MOUNT_VER3;
+ break;
+ case Opt_udp:
+ mnt->flags &= ~NFS_MOUNT_TCP;
+ mnt->nfs_server.protocol = IPPROTO_UDP;
+ mnt->timeo = 7;
+ mnt->retrans = 5;
+ break;
+ case Opt_tcp:
+ mnt->flags |= NFS_MOUNT_TCP;
+ mnt->nfs_server.protocol = IPPROTO_TCP;
+ mnt->timeo = 600;
+ mnt->retrans = 2;
+ break;
+ case Opt_acl:
+ mnt->flags &= ~NFS_MOUNT_NOACL;
+ break;
+ case Opt_noacl:
+ mnt->flags |= NFS_MOUNT_NOACL;
+ break;
+ case Opt_rdirplus:
+ mnt->flags &= ~NFS_MOUNT_NORDIRPLUS;
+ break;
+ case Opt_nordirplus:
+ mnt->flags |= NFS_MOUNT_NORDIRPLUS;
+ break;
+ case Opt_sharecache:
+ mnt->flags &= ~NFS_MOUNT_UNSHARED;
+ break;
+ case Opt_nosharecache:
+ mnt->flags |= NFS_MOUNT_UNSHARED;
+ break;
+
+ case Opt_port:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0 || option > 65535)
+ return 0;
+ mnt->nfs_server.address.sin_port = htonl(option);
+ break;
+ case Opt_rsize:
+ if (match_int(args, &mnt->rsize))
+ return 0;
+ break;
+ case Opt_wsize:
+ if (match_int(args, &mnt->wsize))
+ return 0;
+ break;
+ case Opt_bsize:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0)
+ return 0;
+ mnt->bsize = option;
+ break;
+ case Opt_timeo:
+ if (match_int(args, &mnt->timeo))
+ return 0;
+ break;
+ case Opt_retrans:
+ if (match_int(args, &mnt->retrans))
+ return 0;
+ break;
+ case Opt_acregmin:
+ if (match_int(args, &mnt->acregmin))
+ return 0;
+ break;
+ case Opt_acregmax:
+ if (match_int(args, &mnt->acregmax))
+ return 0;
+ break;
+ case Opt_acdirmin:
+ if (match_int(args, &mnt->acdirmin))
+ return 0;
+ break;
+ case Opt_acdirmax:
+ if (match_int(args, &mnt->acdirmax))
+ return 0;
+ break;
+ case Opt_actimeo:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0)
+ return 0;
+ mnt->acregmin =
+ mnt->acregmax =
+ mnt->acdirmin =
+ mnt->acdirmax = option;
+ break;
+ case Opt_namelen:
+ if (match_int(args, &mnt->namlen))
+ return 0;
+ break;
+ case Opt_mountport:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0 || option > 65535)
+ return 0;
+ mnt->mount_server.port = option;
+ break;
+ case Opt_mountprog:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0)
+ return 0;
+ mnt->mount_server.program = option;
+ break;
+ case Opt_mountvers:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0)
+ return 0;
+ mnt->mount_server.version = option;
+ break;
+ case Opt_nfsprog:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0)
+ return 0;
+ mnt->nfs_server.program = option;
+ break;
+ case Opt_nfsvers:
+ if (match_int(args, &option))
+ return 0;
+ switch (option) {
+ case 2:
+ mnt->flags &= ~NFS_MOUNT_VER3;
+ break;
+ case 3:
+ mnt->flags |= NFS_MOUNT_VER3;
+ break;
+ default:
+ goto out_unrec_vers;
}
- data->root.size = NFS2_FHSIZE;
- memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
- case 4:
- if (data->flags & NFS_MOUNT_SECFLAVOUR) {
- dprintk("%s: mount structure version %d does not support strong security\n",
- __FUNCTION__,
- data->version);
- return -EINVAL;
+ break;
+
+ case Opt_sec:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ token = match_token(string, nfs_secflavor_tokens, args);
+ kfree(string);
+
+ /*
+ * The flags setting is for v2/v3. The flavor_len
+ * setting is for v4. v2/v3 also need to know the
+ * difference between NULL and UNIX.
+ */
+ switch (token) {
+ case Opt_sec_none:
+ mnt->flags &= ~NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 0;
+ mnt->auth_flavors[0] = RPC_AUTH_NULL;
+ break;
+ case Opt_sec_sys:
+ mnt->flags &= ~NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 0;
+ mnt->auth_flavors[0] = RPC_AUTH_UNIX;
+ break;
+ case Opt_sec_krb5:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5;
+ break;
+ case Opt_sec_krb5i:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5I;
+ break;
+ case Opt_sec_krb5p:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5P;
+ break;
+ case Opt_sec_lkey:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEY;
+ break;
+ case Opt_sec_lkeyi:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYI;
+ break;
+ case Opt_sec_lkeyp:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYP;
+ break;
+ case Opt_sec_spkm:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKM;
+ break;
+ case Opt_sec_spkmi:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMI;
+ break;
+ case Opt_sec_spkmp:
+ mnt->flags |= NFS_MOUNT_SECFLAVOUR;
+ mnt->auth_flavor_len = 1;
+ mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMP;
+ break;
+ default:
+ goto out_unrec_sec;
}
- case 5:
- memset(data->context, 0, sizeof(data->context));
- }
+ break;
+ case Opt_proto:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ token = match_token(string,
+ nfs_xprt_protocol_tokens, args);
+ kfree(string);
+
+ switch (token) {
+ case Opt_udp:
+ mnt->flags &= ~NFS_MOUNT_TCP;
+ mnt->nfs_server.protocol = IPPROTO_UDP;
+ mnt->timeo = 7;
+ mnt->retrans = 5;
+ break;
+ case Opt_tcp:
+ mnt->flags |= NFS_MOUNT_TCP;
+ mnt->nfs_server.protocol = IPPROTO_TCP;
+ mnt->timeo = 600;
+ mnt->retrans = 2;
+ break;
+ default:
+ goto out_unrec_xprt;
+ }
+ break;
+ case Opt_mountproto:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ token = match_token(string,
+ nfs_xprt_protocol_tokens, args);
+ kfree(string);
+
+ switch (token) {
+ case Opt_udp:
+ mnt->mount_server.protocol = IPPROTO_UDP;
+ break;
+ case Opt_tcp:
+ mnt->mount_server.protocol = IPPROTO_TCP;
+ break;
+ default:
+ goto out_unrec_xprt;
+ }
+ break;
+ case Opt_addr:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ mnt->nfs_server.address.sin_family = AF_INET;
+ mnt->nfs_server.address.sin_addr.s_addr =
+ in_aton(string);
+ kfree(string);
+ break;
+ case Opt_clientaddr:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ mnt->client_address = string;
+ break;
+ case Opt_mounthost:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ mnt->mount_server.address.sin_family = AF_INET;
+ mnt->mount_server.address.sin_addr.s_addr =
+ in_aton(string);
+ kfree(string);
+ break;
- /* Set the pseudoflavor */
- if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
- data->pseudoflavor = RPC_AUTH_UNIX;
+ case Opt_userspace:
+ case Opt_deprecated:
+ break;
-#ifndef CONFIG_NFS_V3
- /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
- if (data->flags & NFS_MOUNT_VER3) {
- dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
- return -EPROTONOSUPPORT;
+ default:
+ goto out_unknown;
+ }
}
-#endif /* CONFIG_NFS_V3 */
- /* We now require that the mount process passes the remote address */
- if (data->addr.sin_addr.s_addr == INADDR_ANY) {
- dprintk("%s: mount program didn't pass remote address!\n",
- __FUNCTION__);
- return -EINVAL;
+ return 1;
+
+out_nomem:
+ printk(KERN_INFO "NFS: not enough memory to parse option\n");
+ return 0;
+
+out_unrec_vers:
+ printk(KERN_INFO "NFS: unrecognized NFS version number\n");
+ return 0;
+
+out_unrec_xprt:
+ printk(KERN_INFO "NFS: unrecognized transport protocol\n");
+ return 0;
+
+out_unrec_sec:
+ printk(KERN_INFO "NFS: unrecognized security flavor\n");
+ return 0;
+
+out_unknown:
+ printk(KERN_INFO "NFS: unknown mount option: %s\n", p);
+ return 0;
+}
+
+/*
+ * Use the remote server's MOUNT service to request the NFS file handle
+ * corresponding to the provided path.
+ */
+static int nfs_try_mount(struct nfs_parsed_mount_data *args,
+ struct nfs_fh *root_fh)
+{
+ struct sockaddr_in sin;
+ int status;
+
+ if (args->mount_server.version == 0) {
+ if (args->flags & NFS_MOUNT_VER3)
+ args->mount_server.version = NFS_MNT3_VERSION;
+ else
+ args->mount_server.version = NFS_MNT_VERSION;
}
- /* Prepare the root filehandle */
- if (data->flags & NFS_MOUNT_VER3)
- mntfh->size = data->root.size;
+ /*
+ * Construct the mount server's address.
+ */
+ if (args->mount_server.address.sin_addr.s_addr != INADDR_ANY)
+ sin = args->mount_server.address;
else
- mntfh->size = NFS2_FHSIZE;
+ sin = args->nfs_server.address;
+ if (args->mount_server.port == 0) {
+ status = rpcb_getport_sync(&sin,
+ args->mount_server.program,
+ args->mount_server.version,
+ args->mount_server.protocol);
+ if (status < 0)
+ goto out_err;
+ sin.sin_port = htons(status);
+ } else
+ sin.sin_port = htons(args->mount_server.port);
+
+ /*
+ * Now ask the mount server to map our export path
+ * to a file handle.
+ */
+ status = nfs_mount((struct sockaddr *) &sin,
+ sizeof(sin),
+ args->nfs_server.hostname,
+ args->nfs_server.export_path,
+ args->mount_server.version,
+ args->mount_server.protocol,
+ root_fh);
+ if (status < 0)
+ goto out_err;
+
+ return status;
- if (mntfh->size > sizeof(mntfh->data)) {
- dprintk("%s: invalid root filehandle\n", __FUNCTION__);
- return -EINVAL;
+out_err:
+ dfprintk(MOUNT, "NFS: unable to contact server on host "
+ NIPQUAD_FMT "\n", NIPQUAD(sin.sin_addr.s_addr));
+ return status;
+}
+
+/*
+ * Validate the NFS2/NFS3 mount data
+ * - fills in the mount root filehandle
+ *
+ * For option strings, user space handles the following behaviors:
+ *
+ * + DNS: mapping server host name to IP address ("addr=" option)
+ *
+ * + failure mode: how to behave if a mount request can't be handled
+ * immediately ("fg/bg" option)
+ *
+ * + retry: how often to retry a mount request ("retry=" option)
+ *
+ * + breaking back: trying proto=udp after proto=tcp, v2 after v3,
+ * mountproto=tcp after mountproto=udp, and so on
+ *
+ * XXX: as far as I can tell, changing the NFS program number is not
+ * supported in the NFS client.
+ */
+static int nfs_validate_mount_data(struct nfs_mount_data **options,
+ struct nfs_fh *mntfh,
+ const char *dev_name)
+{
+ struct nfs_mount_data *data = *options;
+
+ if (data == NULL)
+ goto out_no_data;
+
+ switch (data->version) {
+ case 1:
+ data->namlen = 0;
+ case 2:
+ data->bsize = 0;
+ case 3:
+ if (data->flags & NFS_MOUNT_VER3)
+ goto out_no_v3;
+ data->root.size = NFS2_FHSIZE;
+ memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
+ case 4:
+ if (data->flags & NFS_MOUNT_SECFLAVOUR)
+ goto out_no_sec;
+ case 5:
+ memset(data->context, 0, sizeof(data->context));
+ case 6:
+ if (data->flags & NFS_MOUNT_VER3)
+ mntfh->size = data->root.size;
+ else
+ mntfh->size = NFS2_FHSIZE;
+
+ if (mntfh->size > sizeof(mntfh->data))
+ goto out_invalid_fh;
+
+ memcpy(mntfh->data, data->root.data, mntfh->size);
+ if (mntfh->size < sizeof(mntfh->data))
+ memset(mntfh->data + mntfh->size, 0,
+ sizeof(mntfh->data) - mntfh->size);
+ break;
+ default: {
+ unsigned int len;
+ char *c;
+ int status;
+ struct nfs_parsed_mount_data args = {
+ .flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP),
+ .rsize = NFS_MAX_FILE_IO_SIZE,
+ .wsize = NFS_MAX_FILE_IO_SIZE,
+ .timeo = 600,
+ .retrans = 2,
+ .acregmin = 3,
+ .acregmax = 60,
+ .acdirmin = 30,
+ .acdirmax = 60,
+ .mount_server.protocol = IPPROTO_UDP,
+ .mount_server.program = NFS_MNT_PROGRAM,
+ .nfs_server.protocol = IPPROTO_TCP,
+ .nfs_server.program = NFS_PROGRAM,
+ };
+
+ if (nfs_parse_mount_options((char *) *options, &args) == 0)
+ return -EINVAL;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ /*
+ * NB: after this point, caller will free "data"
+ * if we return an error
+ */
+ *options = data;
+
+ c = strchr(dev_name, ':');
+ if (c == NULL)
+ return -EINVAL;
+ len = c - dev_name - 1;
+ if (len > sizeof(data->hostname))
+ return -EINVAL;
+ strncpy(data->hostname, dev_name, len);
+ args.nfs_server.hostname = data->hostname;
+
+ c++;
+ if (strlen(c) > NFS_MAXPATHLEN)
+ return -EINVAL;
+ args.nfs_server.export_path = c;
+
+ status = nfs_try_mount(&args, mntfh);
+ if (status)
+ return -EINVAL;
+
+ /*
+ * Translate to nfs_mount_data, which nfs_fill_super
+ * can deal with.
+ */
+ data->version = 6;
+ data->flags = args.flags;
+ data->rsize = args.rsize;
+ data->wsize = args.wsize;
+ data->timeo = args.timeo;
+ data->retrans = args.retrans;
+ data->acregmin = args.acregmin;
+ data->acregmax = args.acregmax;
+ data->acdirmin = args.acdirmin;
+ data->acdirmax = args.acdirmax;
+ data->addr = args.nfs_server.address;
+ data->namlen = args.namlen;
+ data->bsize = args.bsize;
+ data->pseudoflavor = args.auth_flavors[0];
+
+ break;
+ }
}
- memcpy(mntfh->data, data->root.data, mntfh->size);
- if (mntfh->size < sizeof(mntfh->data))
- memset(mntfh->data + mntfh->size, 0,
- sizeof(mntfh->data) - mntfh->size);
+ if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
+ data->pseudoflavor = RPC_AUTH_UNIX;
+
+#ifndef CONFIG_NFS_V3
+ if (data->flags & NFS_MOUNT_VER3)
+ goto out_v3_not_compiled;
+#endif /* !CONFIG_NFS_V3 */
+
+ if (!nfs_verify_server_address((struct sockaddr *) &data->addr))
+ goto out_no_address;
return 0;
+
+out_no_data:
+ dfprintk(MOUNT, "NFS: mount program didn't pass any mount data\n");
+ return -EINVAL;
+
+out_no_v3:
+ dfprintk(MOUNT, "NFS: nfs_mount_data version %d does not support v3\n",
+ data->version);
+ return -EINVAL;
+
+out_no_sec:
+ dfprintk(MOUNT, "NFS: nfs_mount_data version supports only AUTH_SYS\n");
+ return -EINVAL;
+
+#ifndef CONFIG_NFS_V3
+out_v3_not_compiled:
+ dfprintk(MOUNT, "NFS: NFSv3 is not compiled into kernel\n");
+ return -EPROTONOSUPPORT;
+#endif /* !CONFIG_NFS_V3 */
+
+out_no_address:
+ dfprintk(MOUNT, "NFS: mount program didn't pass remote address\n");
+ return -EINVAL;
+
+out_invalid_fh:
+ dfprintk(MOUNT, "NFS: invalid root filehandle\n");
+ return -EINVAL;
}
/*
@@ -600,13 +1317,51 @@ static int nfs_compare_super(struct super_block *sb, void *data)
{
struct nfs_server *server = data, *old = NFS_SB(sb);
- if (old->nfs_client != server->nfs_client)
+ if (memcmp(&old->nfs_client->cl_addr,
+ &server->nfs_client->cl_addr,
+ sizeof(old->nfs_client->cl_addr)) != 0)
+ return 0;
+ /* Note: NFS_MOUNT_UNSHARED == NFS4_MOUNT_UNSHARED */
+ if (old->flags & NFS_MOUNT_UNSHARED)
return 0;
if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0)
return 0;
return 1;
}
+#define NFS_MS_MASK (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_SYNCHRONOUS)
+
+static int nfs_compare_mount_options(const struct super_block *s, const struct nfs_server *b, int flags)
+{
+ const struct nfs_server *a = s->s_fs_info;
+ const struct rpc_clnt *clnt_a = a->client;
+ const struct rpc_clnt *clnt_b = b->client;
+
+ if ((s->s_flags & NFS_MS_MASK) != (flags & NFS_MS_MASK))
+ goto Ebusy;
+ if (a->nfs_client != b->nfs_client)
+ goto Ebusy;
+ if (a->flags != b->flags)
+ goto Ebusy;
+ if (a->wsize != b->wsize)
+ goto Ebusy;
+ if (a->rsize != b->rsize)
+ goto Ebusy;
+ if (a->acregmin != b->acregmin)
+ goto Ebusy;
+ if (a->acregmax != b->acregmax)
+ goto Ebusy;
+ if (a->acdirmin != b->acdirmin)
+ goto Ebusy;
+ if (a->acdirmax != b->acdirmax)
+ goto Ebusy;
+ if (clnt_a->cl_auth->au_flavor != clnt_b->cl_auth->au_flavor)
+ goto Ebusy;
+ return 0;
+Ebusy:
+ return -EBUSY;
+}
+
static int nfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
{
@@ -615,30 +1370,37 @@ static int nfs_get_sb(struct file_system_type *fs_type,
struct nfs_fh mntfh;
struct nfs_mount_data *data = raw_data;
struct dentry *mntroot;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
int error;
/* Validate the mount data */
- error = nfs_validate_mount_data(data, &mntfh);
+ error = nfs_validate_mount_data(&data, &mntfh, dev_name);
if (error < 0)
- return error;
+ goto out;
/* Get a volume representation */
server = nfs_create_server(data, &mntfh);
if (IS_ERR(server)) {
error = PTR_ERR(server);
- goto out_err_noserver;
+ goto out;
}
+ if (server->flags & NFS_MOUNT_UNSHARED)
+ compare_super = NULL;
+
/* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+ s = sget(fs_type, compare_super, nfs_set_super, server);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
}
if (s->s_fs_info != server) {
+ error = nfs_compare_mount_options(s, server, flags);
nfs_free_server(server);
server = NULL;
+ if (error < 0)
+ goto error_splat_super;
}
if (!s->s_root) {
@@ -656,17 +1418,21 @@ static int nfs_get_sb(struct file_system_type *fs_type,
s->s_flags |= MS_ACTIVE;
mnt->mnt_sb = s;
mnt->mnt_root = mntroot;
- return 0;
+ error = 0;
+
+out:
+ if (data != raw_data)
+ kfree(data);
+ return error;
out_err_nosb:
nfs_free_server(server);
-out_err_noserver:
- return error;
+ goto out;
error_splat_super:
up_write(&s->s_umount);
deactivate_super(s);
- return error;
+ goto out;
}
/*
@@ -691,6 +1457,7 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
struct super_block *s;
struct nfs_server *server;
struct dentry *mntroot;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
int error;
dprintk("--> nfs_xdev_get_sb()\n");
@@ -702,16 +1469,22 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
goto out_err_noserver;
}
+ if (server->flags & NFS_MOUNT_UNSHARED)
+ compare_super = NULL;
+
/* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+ s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
}
if (s->s_fs_info != server) {
+ error = nfs_compare_mount_options(s, server, flags);
nfs_free_server(server);
server = NULL;
+ if (error < 0)
+ goto error_splat_super;
}
if (!s->s_root) {
@@ -772,25 +1545,164 @@ static void nfs4_fill_super(struct super_block *sb)
nfs_initialise_sb(sb);
}
-static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
+/*
+ * Validate NFSv4 mount options
+ */
+static int nfs4_validate_mount_data(struct nfs4_mount_data **options,
+ const char *dev_name,
+ struct sockaddr_in *addr,
+ rpc_authflavor_t *authflavour,
+ char **hostname,
+ char **mntpath,
+ char **ip_addr)
{
- void *p = NULL;
-
- if (!src->len)
- return ERR_PTR(-EINVAL);
- if (src->len < maxlen)
- maxlen = src->len;
- if (dst == NULL) {
- p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
- if (p == NULL)
- return ERR_PTR(-ENOMEM);
- }
- if (copy_from_user(dst, src->data, maxlen)) {
- kfree(p);
- return ERR_PTR(-EFAULT);
+ struct nfs4_mount_data *data = *options;
+ char *c;
+
+ if (data == NULL)
+ goto out_no_data;
+
+ switch (data->version) {
+ case 1:
+ if (data->host_addrlen != sizeof(*addr))
+ goto out_no_address;
+ if (copy_from_user(addr, data->host_addr, sizeof(*addr)))
+ return -EFAULT;
+ if (addr->sin_port == 0)
+ addr->sin_port = htons(NFS_PORT);
+ if (!nfs_verify_server_address((struct sockaddr *) addr))
+ goto out_no_address;
+
+ switch (data->auth_flavourlen) {
+ case 0:
+ *authflavour = RPC_AUTH_UNIX;
+ break;
+ case 1:
+ if (copy_from_user(authflavour, data->auth_flavours,
+ sizeof(*authflavour)))
+ return -EFAULT;
+ break;
+ default:
+ goto out_inval_auth;
+ }
+
+ c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ *hostname = c;
+
+ c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ *mntpath = c;
+ dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath);
+
+ c = strndup_user(data->client_addr.data, 16);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+ *ip_addr = c;
+
+ break;
+ default: {
+ unsigned int len;
+ struct nfs_parsed_mount_data args = {
+ .rsize = NFS_MAX_FILE_IO_SIZE,
+ .wsize = NFS_MAX_FILE_IO_SIZE,
+ .timeo = 600,
+ .retrans = 2,
+ .acregmin = 3,
+ .acregmax = 60,
+ .acdirmin = 30,
+ .acdirmax = 60,
+ .nfs_server.protocol = IPPROTO_TCP,
+ };
+
+ if (nfs_parse_mount_options((char *) *options, &args) == 0)
+ return -EINVAL;
+
+ if (!nfs_verify_server_address((struct sockaddr *)
+ &args.nfs_server.address))
+ return -EINVAL;
+ *addr = args.nfs_server.address;
+
+ switch (args.auth_flavor_len) {
+ case 0:
+ *authflavour = RPC_AUTH_UNIX;
+ break;
+ case 1:
+ *authflavour = (rpc_authflavor_t) args.auth_flavors[0];
+ break;
+ default:
+ goto out_inval_auth;
+ }
+
+ /*
+ * Translate to nfs4_mount_data, which nfs4_fill_super
+ * can deal with.
+ */
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+ *options = data;
+
+ data->version = 1;
+ data->flags = args.flags & NFS4_MOUNT_FLAGMASK;
+ data->rsize = args.rsize;
+ data->wsize = args.wsize;
+ data->timeo = args.timeo;
+ data->retrans = args.retrans;
+ data->acregmin = args.acregmin;
+ data->acregmax = args.acregmax;
+ data->acdirmin = args.acdirmin;
+ data->acdirmax = args.acdirmax;
+ data->proto = args.nfs_server.protocol;
+
+ /*
+ * Split "dev_name" into "hostname:mntpath".
+ */
+ c = strchr(dev_name, ':');
+ if (c == NULL)
+ return -EINVAL;
+ /* while calculating len, pretend ':' is '\0' */
+ len = c - dev_name;
+ if (len > NFS4_MAXNAMLEN)
+ return -EINVAL;
+ *hostname = kzalloc(len, GFP_KERNEL);
+ if (*hostname == NULL)
+ return -ENOMEM;
+ strncpy(*hostname, dev_name, len - 1);
+
+ c++; /* step over the ':' */
+ len = strlen(c);
+ if (len > NFS4_MAXPATHLEN)
+ return -EINVAL;
+ *mntpath = kzalloc(len + 1, GFP_KERNEL);
+ if (*mntpath == NULL)
+ return -ENOMEM;
+ strncpy(*mntpath, c, len);
+
+ dprintk("MNTPATH: %s\n", *mntpath);
+
+ *ip_addr = args.client_address;
+
+ break;
+ }
}
- dst[maxlen] = '\0';
- return dst;
+
+ return 0;
+
+out_no_data:
+ dfprintk(MOUNT, "NFS4: mount program didn't pass any mount data\n");
+ return -EINVAL;
+
+out_inval_auth:
+ dfprintk(MOUNT, "NFS4: Invalid number of RPC auth flavours %d\n",
+ data->auth_flavourlen);
+ return -EINVAL;
+
+out_no_address:
+ dfprintk(MOUNT, "NFS4: mount program didn't pass remote address\n");
+ return -EINVAL;
}
/*
@@ -806,81 +1718,29 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
rpc_authflavor_t authflavour;
struct nfs_fh mntfh;
struct dentry *mntroot;
- char *mntpath = NULL, *hostname = NULL, ip_addr[16];
- void *p;
+ char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
int error;
- if (data == NULL) {
- dprintk("%s: missing data argument\n", __FUNCTION__);
- return -EINVAL;
- }
- if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
- dprintk("%s: bad mount version\n", __FUNCTION__);
- return -EINVAL;
- }
-
- /* We now require that the mount process passes the remote address */
- if (data->host_addrlen != sizeof(addr))
- return -EINVAL;
-
- if (copy_from_user(&addr, data->host_addr, sizeof(addr)))
- return -EFAULT;
-
- if (addr.sin_family != AF_INET ||
- addr.sin_addr.s_addr == INADDR_ANY
- ) {
- dprintk("%s: mount program didn't pass remote IP address!\n",
- __FUNCTION__);
- return -EINVAL;
- }
- /* RFC3530: The default port for NFS is 2049 */
- if (addr.sin_port == 0)
- addr.sin_port = htons(NFS_PORT);
-
- /* Grab the authentication type */
- authflavour = RPC_AUTH_UNIX;
- if (data->auth_flavourlen != 0) {
- if (data->auth_flavourlen != 1) {
- dprintk("%s: Invalid number of RPC auth flavours %d.\n",
- __FUNCTION__, data->auth_flavourlen);
- error = -EINVAL;
- goto out_err_noserver;
- }
-
- if (copy_from_user(&authflavour, data->auth_flavours,
- sizeof(authflavour))) {
- error = -EFAULT;
- goto out_err_noserver;
- }
- }
-
- p = nfs_copy_user_string(NULL, &data->hostname, 256);
- if (IS_ERR(p))
- goto out_err;
- hostname = p;
-
- p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
- if (IS_ERR(p))
- goto out_err;
- mntpath = p;
-
- dprintk("MNTPATH: %s\n", mntpath);
-
- p = nfs_copy_user_string(ip_addr, &data->client_addr,
- sizeof(ip_addr) - 1);
- if (IS_ERR(p))
- goto out_err;
+ /* Validate the mount data */
+ error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour,
+ &hostname, &mntpath, &ip_addr);
+ if (error < 0)
+ goto out;
/* Get a volume representation */
server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr,
authflavour, &mntfh);
if (IS_ERR(server)) {
error = PTR_ERR(server);
- goto out_err_noserver;
+ goto out;
}
+ if (server->flags & NFS4_MOUNT_UNSHARED)
+ compare_super = NULL;
+
/* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+ s = sget(fs_type, compare_super, nfs_set_super, server);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_free;
@@ -906,25 +1766,22 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
s->s_flags |= MS_ACTIVE;
mnt->mnt_sb = s;
mnt->mnt_root = mntroot;
+ error = 0;
+
+out:
+ kfree(ip_addr);
kfree(mntpath);
kfree(hostname);
- return 0;
-
-out_err:
- error = PTR_ERR(p);
- goto out_err_noserver;
+ return error;
out_free:
nfs_free_server(server);
-out_err_noserver:
- kfree(mntpath);
- kfree(hostname);
- return error;
+ goto out;
error_splat_super:
up_write(&s->s_umount);
deactivate_super(s);
- goto out_err_noserver;
+ goto out;
}
static void nfs4_kill_super(struct super_block *sb)
@@ -949,6 +1806,7 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
struct super_block *s;
struct nfs_server *server;
struct dentry *mntroot;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
int error;
dprintk("--> nfs4_xdev_get_sb()\n");
@@ -960,8 +1818,11 @@ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags,
goto out_err_noserver;
}
+ if (server->flags & NFS4_MOUNT_UNSHARED)
+ compare_super = NULL;
+
/* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+ s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
@@ -1016,6 +1877,7 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
struct nfs_server *server;
struct dentry *mntroot;
struct nfs_fh mntfh;
+ int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
int error;
dprintk("--> nfs4_referral_get_sb()\n");
@@ -1027,8 +1889,11 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags,
goto out_err_noserver;
}
+ if (server->flags & NFS4_MOUNT_UNSHARED)
+ compare_super = NULL;
+
/* Get a superblock - note that we may end up sharing one that already exists */
- s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+ s = sget(&nfs_fs_type, compare_super, nfs_set_super, server);
if (IS_ERR(s)) {
error = PTR_ERR(s);
goto out_err_nosb;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index af344a158e0..73ac992ece8 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -117,19 +117,19 @@ static struct nfs_page *nfs_page_find_request_locked(struct page *page)
if (PagePrivate(page)) {
req = (struct nfs_page *)page_private(page);
if (req != NULL)
- atomic_inc(&req->wb_count);
+ kref_get(&req->wb_kref);
}
return req;
}
static struct nfs_page *nfs_page_find_request(struct page *page)
{
+ struct inode *inode = page->mapping->host;
struct nfs_page *req = NULL;
- spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
- spin_lock(req_lock);
+ spin_lock(&inode->i_lock);
req = nfs_page_find_request_locked(page);
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
return req;
}
@@ -191,8 +191,6 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
}
/* Update file length */
nfs_grow_file(page, offset, count);
- /* Set the PG_uptodate flag? */
- nfs_mark_uptodate(page, offset, count);
nfs_unlock_request(req);
return 0;
}
@@ -253,16 +251,16 @@ static void nfs_end_page_writeback(struct page *page)
static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
struct page *page)
{
+ struct inode *inode = page->mapping->host;
+ struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_page *req;
- struct nfs_inode *nfsi = NFS_I(page->mapping->host);
- spinlock_t *req_lock = &nfsi->req_lock;
int ret;
- spin_lock(req_lock);
+ spin_lock(&inode->i_lock);
for(;;) {
req = nfs_page_find_request_locked(page);
if (req == NULL) {
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
return 1;
}
if (nfs_lock_request_dontget(req))
@@ -272,28 +270,28 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
* succeed provided that someone hasn't already marked the
* request as dirty (in which case we don't care).
*/
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
ret = nfs_wait_on_request(req);
nfs_release_request(req);
if (ret != 0)
return ret;
- spin_lock(req_lock);
+ spin_lock(&inode->i_lock);
}
if (test_bit(PG_NEED_COMMIT, &req->wb_flags)) {
/* This request is marked for commit */
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
nfs_unlock_request(req);
nfs_pageio_complete(pgio);
return 1;
}
if (nfs_set_page_writeback(page) != 0) {
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
BUG();
}
radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index,
- NFS_PAGE_TAG_WRITEBACK);
+ NFS_PAGE_TAG_LOCKED);
ret = test_bit(PG_NEED_FLUSH, &req->wb_flags);
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
nfs_pageio_add_request(pgio, req);
return ret;
}
@@ -400,7 +398,7 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
if (PageDirty(req->wb_page))
set_bit(PG_NEED_FLUSH, &req->wb_flags);
nfsi->npages++;
- atomic_inc(&req->wb_count);
+ kref_get(&req->wb_kref);
return 0;
}
@@ -409,12 +407,12 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
*/
static void nfs_inode_remove_request(struct nfs_page *req)
{
- struct inode *inode = req->wb_context->dentry->d_inode;
+ struct inode *inode = req->wb_context->path.dentry->d_inode;
struct nfs_inode *nfsi = NFS_I(inode);
BUG_ON (!NFS_WBACK_BUSY(req));
- spin_lock(&nfsi->req_lock);
+ spin_lock(&inode->i_lock);
set_page_private(req->wb_page, 0);
ClearPagePrivate(req->wb_page);
radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
@@ -422,11 +420,11 @@ static void nfs_inode_remove_request(struct nfs_page *req)
__set_page_dirty_nobuffers(req->wb_page);
nfsi->npages--;
if (!nfsi->npages) {
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
nfs_end_data_update(inode);
iput(inode);
} else
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
nfs_clear_request(req);
nfs_release_request(req);
}
@@ -457,14 +455,16 @@ nfs_dirty_request(struct nfs_page *req)
static void
nfs_mark_request_commit(struct nfs_page *req)
{
- struct inode *inode = req->wb_context->dentry->d_inode;
+ struct inode *inode = req->wb_context->path.dentry->d_inode;
struct nfs_inode *nfsi = NFS_I(inode);
- spin_lock(&nfsi->req_lock);
- nfs_list_add_request(req, &nfsi->commit);
+ spin_lock(&inode->i_lock);
nfsi->ncommit++;
set_bit(PG_NEED_COMMIT, &(req)->wb_flags);
- spin_unlock(&nfsi->req_lock);
+ radix_tree_tag_set(&nfsi->nfs_page_tree,
+ req->wb_index,
+ NFS_PAGE_TAG_COMMIT);
+ spin_unlock(&inode->i_lock);
inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
}
@@ -526,18 +526,18 @@ static int nfs_wait_on_requests_locked(struct inode *inode, pgoff_t idx_start, u
idx_end = idx_start + npages - 1;
next = idx_start;
- while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
+ while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_LOCKED)) {
if (req->wb_index > idx_end)
break;
next = req->wb_index + 1;
BUG_ON(!NFS_WBACK_BUSY(req));
- atomic_inc(&req->wb_count);
- spin_unlock(&nfsi->req_lock);
+ kref_get(&req->wb_kref);
+ spin_unlock(&inode->i_lock);
error = nfs_wait_on_request(req);
nfs_release_request(req);
- spin_lock(&nfsi->req_lock);
+ spin_lock(&inode->i_lock);
if (error < 0)
return error;
res++;
@@ -577,10 +577,9 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, u
int res = 0;
if (nfsi->ncommit != 0) {
- res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages);
+ res = nfs_scan_list(nfsi, dst, idx_start, npages,
+ NFS_PAGE_TAG_COMMIT);
nfsi->ncommit -= res;
- if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
- printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
}
return res;
}
@@ -603,7 +602,6 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
{
struct address_space *mapping = page->mapping;
struct inode *inode = mapping->host;
- struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_page *req, *new = NULL;
pgoff_t rqend, end;
@@ -613,13 +611,13 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
/* Loop over all inode entries and see if we find
* A request for the page we wish to update
*/
- spin_lock(&nfsi->req_lock);
+ spin_lock(&inode->i_lock);
req = nfs_page_find_request_locked(page);
if (req) {
if (!nfs_lock_request_dontget(req)) {
int error;
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
error = nfs_wait_on_request(req);
nfs_release_request(req);
if (error < 0) {
@@ -629,7 +627,7 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
}
continue;
}
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
if (new)
nfs_release_request(new);
break;
@@ -640,14 +638,14 @@ static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
nfs_lock_request_dontget(new);
error = nfs_inode_add_request(inode, new);
if (error) {
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
nfs_unlock_request(new);
return ERR_PTR(error);
}
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
return new;
}
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
new = nfs_create_request(ctx, inode, page, offset, bytes);
if (IS_ERR(new))
@@ -751,12 +749,17 @@ int nfs_updatepage(struct file *file, struct page *page,
static void nfs_writepage_release(struct nfs_page *req)
{
- if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) {
+ if (PageError(req->wb_page)) {
+ nfs_end_page_writeback(req->wb_page);
+ nfs_inode_remove_request(req);
+ } else if (!nfs_reschedule_unstable_write(req)) {
+ /* Set the PG_uptodate flag */
+ nfs_mark_uptodate(req->wb_page, req->wb_pgbase, req->wb_bytes);
nfs_end_page_writeback(req->wb_page);
nfs_inode_remove_request(req);
} else
nfs_end_page_writeback(req->wb_page);
- nfs_clear_page_writeback(req);
+ nfs_clear_page_tag_locked(req);
}
static inline int flush_task_priority(int how)
@@ -786,7 +789,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
* NB: take care not to mess about with data->commit et al. */
data->req = req;
- data->inode = inode = req->wb_context->dentry->d_inode;
+ data->inode = inode = req->wb_context->path.dentry->d_inode;
data->cred = req->wb_context->cred;
data->args.fh = NFS_FH(inode);
@@ -885,7 +888,7 @@ out_bad:
}
nfs_redirty_request(req);
nfs_end_page_writeback(req->wb_page);
- nfs_clear_page_writeback(req);
+ nfs_clear_page_tag_locked(req);
return -ENOMEM;
}
@@ -928,7 +931,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
nfs_list_remove_request(req);
nfs_redirty_request(req);
nfs_end_page_writeback(req->wb_page);
- nfs_clear_page_writeback(req);
+ nfs_clear_page_tag_locked(req);
}
return -ENOMEM;
}
@@ -954,8 +957,8 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
struct page *page = req->wb_page;
dprintk("NFS: write (%s/%Ld %d@%Ld)",
- req->wb_context->dentry->d_inode->i_sb->s_id,
- (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+ req->wb_context->path.dentry->d_inode->i_sb->s_id,
+ (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
req->wb_bytes,
(long long)req_offset(req));
@@ -970,9 +973,9 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
}
if (nfs_write_need_commit(data)) {
- spinlock_t *req_lock = &NFS_I(page->mapping->host)->req_lock;
+ struct inode *inode = page->mapping->host;
- spin_lock(req_lock);
+ spin_lock(&inode->i_lock);
if (test_bit(PG_NEED_RESCHED, &req->wb_flags)) {
/* Do nothing we need to resend the writes */
} else if (!test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags)) {
@@ -983,7 +986,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
clear_bit(PG_NEED_COMMIT, &req->wb_flags);
dprintk(" server reboot detected\n");
}
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
} else
dprintk(" OK\n");
@@ -1020,8 +1023,8 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
page = req->wb_page;
dprintk("NFS: write (%s/%Ld %d@%Ld)",
- req->wb_context->dentry->d_inode->i_sb->s_id,
- (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+ req->wb_context->path.dentry->d_inode->i_sb->s_id,
+ (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
req->wb_bytes,
(long long)req_offset(req));
@@ -1039,12 +1042,14 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
dprintk(" marked for commit\n");
goto next;
}
+ /* Set the PG_uptodate flag? */
+ nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
dprintk(" OK\n");
remove_request:
nfs_end_page_writeback(page);
nfs_inode_remove_request(req);
next:
- nfs_clear_page_writeback(req);
+ nfs_clear_page_tag_locked(req);
}
}
@@ -1157,7 +1162,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
list_splice_init(head, &data->pages);
first = nfs_list_entry(data->pages.next);
- inode = first->wb_context->dentry->d_inode;
+ inode = first->wb_context->path.dentry->d_inode;
data->inode = inode;
data->cred = first->wb_context->cred;
@@ -1207,7 +1212,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
nfs_list_remove_request(req);
nfs_mark_request_commit(req);
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
- nfs_clear_page_writeback(req);
+ nfs_clear_page_tag_locked(req);
}
return -ENOMEM;
}
@@ -1234,8 +1239,8 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS);
dprintk("NFS: commit (%s/%Ld %d@%Ld)",
- req->wb_context->dentry->d_inode->i_sb->s_id,
- (long long)NFS_FILEID(req->wb_context->dentry->d_inode),
+ req->wb_context->path.dentry->d_inode->i_sb->s_id,
+ (long long)NFS_FILEID(req->wb_context->path.dentry->d_inode),
req->wb_bytes,
(long long)req_offset(req));
if (task->tk_status < 0) {
@@ -1249,6 +1254,9 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
* returned by the server against all stored verfs. */
if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) {
/* We have a match */
+ /* Set the PG_uptodate flag */
+ nfs_mark_uptodate(req->wb_page, req->wb_pgbase,
+ req->wb_bytes);
nfs_inode_remove_request(req);
dprintk(" OK\n");
goto next;
@@ -1257,7 +1265,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
dprintk(" mismatch\n");
nfs_redirty_request(req);
next:
- nfs_clear_page_writeback(req);
+ nfs_clear_page_tag_locked(req);
}
}
@@ -1268,13 +1276,12 @@ static const struct rpc_call_ops nfs_commit_ops = {
int nfs_commit_inode(struct inode *inode, int how)
{
- struct nfs_inode *nfsi = NFS_I(inode);
LIST_HEAD(head);
int res;
- spin_lock(&nfsi->req_lock);
+ spin_lock(&inode->i_lock);
res = nfs_scan_commit(inode, &head, 0, 0);
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
if (res) {
int error = nfs_commit_list(inode, &head, how);
if (error < 0)
@@ -1292,7 +1299,6 @@ static inline int nfs_commit_list(struct inode *inode, struct list_head *head, i
long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_control *wbc, int how)
{
struct inode *inode = mapping->host;
- struct nfs_inode *nfsi = NFS_I(inode);
pgoff_t idx_start, idx_end;
unsigned int npages = 0;
LIST_HEAD(head);
@@ -1314,7 +1320,7 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr
}
}
how &= ~FLUSH_NOCOMMIT;
- spin_lock(&nfsi->req_lock);
+ spin_lock(&inode->i_lock);
do {
ret = nfs_wait_on_requests_locked(inode, idx_start, npages);
if (ret != 0)
@@ -1325,18 +1331,19 @@ long nfs_sync_mapping_wait(struct address_space *mapping, struct writeback_contr
if (pages == 0)
break;
if (how & FLUSH_INVALIDATE) {
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
nfs_cancel_commit_list(&head);
ret = pages;
- spin_lock(&nfsi->req_lock);
+ spin_lock(&inode->i_lock);
continue;
}
pages += nfs_scan_commit(inode, &head, 0, 0);
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
ret = nfs_commit_list(inode, &head, how);
- spin_lock(&nfsi->req_lock);
+ spin_lock(&inode->i_lock);
+
} while (ret >= 0);
- spin_unlock(&nfsi->req_lock);
+ spin_unlock(&inode->i_lock);
return ret;
}
@@ -1430,7 +1437,6 @@ int nfs_set_page_dirty(struct page *page)
{
struct address_space *mapping = page->mapping;
struct inode *inode;
- spinlock_t *req_lock;
struct nfs_page *req;
int ret;
@@ -1439,18 +1445,17 @@ int nfs_set_page_dirty(struct page *page)
inode = mapping->host;
if (!inode)
goto out_raced;
- req_lock = &NFS_I(inode)->req_lock;
- spin_lock(req_lock);
+ spin_lock(&inode->i_lock);
req = nfs_page_find_request_locked(page);
if (req != NULL) {
/* Mark any existing write requests for flushing */
ret = !test_and_set_bit(PG_NEED_FLUSH, &req->wb_flags);
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
nfs_release_request(req);
return ret;
}
ret = __set_page_dirty_nobuffers(page);
- spin_unlock(req_lock);
+ spin_unlock(&inode->i_lock);
return ret;
out_raced:
return !TestSetPageDirty(page);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 864090edc28..5443c52b57a 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -394,7 +394,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
.rpc_argp = clp,
};
- char clientname[16];
int status;
if (atomic_read(&cb->cb_set))
@@ -417,11 +416,6 @@ nfsd4_probe_callback(struct nfs4_client *clp)
memset(program->stats, 0, sizeof(cb->cb_stat));
program->stats->program = program;
- /* Just here to make some printk's more useful: */
- snprintf(clientname, sizeof(clientname),
- "%u.%u.%u.%u", NIPQUAD(addr.sin_addr));
- args.servername = clientname;
-
/* Create RPC client */
cb->cb_client = rpc_create(&args);
if (IS_ERR(cb->cb_client)) {
@@ -429,29 +423,23 @@ nfsd4_probe_callback(struct nfs4_client *clp)
goto out_err;
}
- /* Kick rpciod, put the call on the wire. */
- if (rpciod_up() != 0)
- goto out_clnt;
-
/* the task holds a reference to the nfs4_client struct */
atomic_inc(&clp->cl_count);
msg.rpc_cred = nfsd4_lookupcred(clp,0);
if (IS_ERR(msg.rpc_cred))
- goto out_rpciod;
+ goto out_release_clp;
status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL);
put_rpccred(msg.rpc_cred);
if (status != 0) {
dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
- goto out_rpciod;
+ goto out_release_clp;
}
return;
-out_rpciod:
+out_release_clp:
atomic_dec(&clp->cl_count);
- rpciod_down();
-out_clnt:
rpc_shutdown_client(cb->cb_client);
out_err:
cb->cb_client = NULL;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 3cc8ce422ab..8c52913d7cb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -378,7 +378,6 @@ shutdown_callback_client(struct nfs4_client *clp)
if (clnt) {
clp->cl_callback.cb_client = NULL;
rpc_shutdown_client(clnt);
- rpciod_down();
}
}
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7e6aa245b5d..945b1cedde2 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -23,7 +23,7 @@
#include <linux/file.h>
#include <linux/mount.h>
#include <linux/major.h>
-#include <linux/ext2_fs.h>
+#include <linux/splice.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
@@ -801,26 +801,32 @@ found:
}
/*
- * Grab and keep cached pages assosiated with a file in the svc_rqst
- * so that they can be passed to the netowork sendmsg/sendpage routines
- * directrly. They will be released after the sending has completed.
+ * Grab and keep cached pages associated with a file in the svc_rqst
+ * so that they can be passed to the network sendmsg/sendpage routines
+ * directly. They will be released after the sending has completed.
*/
static int
-nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset , unsigned long size)
+nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
{
- unsigned long count = desc->count;
- struct svc_rqst *rqstp = desc->arg.data;
+ struct svc_rqst *rqstp = sd->u.data;
struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
+ struct page *page = buf->page;
+ size_t size;
+ int ret;
+
+ ret = buf->ops->confirm(pipe, buf);
+ if (unlikely(ret))
+ return ret;
- if (size > count)
- size = count;
+ size = sd->len;
if (rqstp->rq_res.page_len == 0) {
get_page(page);
put_page(*pp);
*pp = page;
rqstp->rq_resused++;
- rqstp->rq_res.page_base = offset;
+ rqstp->rq_res.page_base = buf->offset;
rqstp->rq_res.page_len = size;
} else if (page != pp[-1]) {
get_page(page);
@@ -832,11 +838,15 @@ nfsd_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset
} else
rqstp->rq_res.page_len += size;
- desc->count = count - size;
- desc->written += size;
return size;
}
+static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
+ struct splice_desc *sd)
+{
+ return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
+}
+
static __be32
nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
@@ -861,10 +871,16 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
if (ra && ra->p_set)
file->f_ra = ra->p_ra;
- if (file->f_op->sendfile && rqstp->rq_sendfile_ok) {
+ if (file->f_op->splice_read && rqstp->rq_splice_ok) {
+ struct splice_desc sd = {
+ .len = 0,
+ .total_len = *count,
+ .pos = offset,
+ .u.data = rqstp,
+ };
+
rqstp->rq_resused = 1;
- host_err = file->f_op->sendfile(file, &offset, *count,
- nfsd_read_actor, rqstp);
+ host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
} else {
oldfs = get_fs();
set_fs(KERNEL_DS);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index 7ed56390b58..ffcc504a166 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -2276,7 +2276,7 @@ const struct file_operations ntfs_file_ops = {
mounted filesystem. */
.mmap = generic_file_mmap, /* Mmap file. */
.open = ntfs_file_open, /* Open file. */
- .sendfile = generic_file_sendfile, /* Zero-copy data send with
+ .splice_read = generic_file_splice_read /* Zero-copy data send with
the data source being on
the ntfs partition. We do
not need to care about the
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 074791ce4ab..b532a730cec 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -140,7 +140,7 @@ static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na)
if (!ni->name)
return -ENOMEM;
memcpy(ni->name, na->name, i);
- ni->name[i] = 0;
+ ni->name[na->name_len] = 0;
}
return 0;
}
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 0023b31e48a..a480b09c79b 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -798,6 +798,11 @@ int ocfs2_map_and_write_splice_data(struct inode *inode,
}
to = from + bytes;
+ BUG_ON(from > PAGE_CACHE_SIZE);
+ BUG_ON(to > PAGE_CACHE_SIZE);
+ BUG_ON(from < cluster_start);
+ BUG_ON(to > cluster_end);
+
if (wc->w_this_page_new)
ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
cluster_start, cluster_end, 1);
@@ -809,11 +814,6 @@ int ocfs2_map_and_write_splice_data(struct inode *inode,
goto out;
}
- BUG_ON(from > PAGE_CACHE_SIZE);
- BUG_ON(to > PAGE_CACHE_SIZE);
- BUG_ON(from > osb->s_clustersize);
- BUG_ON(to > osb->s_clustersize);
-
src = buf->ops->map(sp->s_pipe, buf, 1);
dst = kmap_atomic(wc->w_this_page, KM_USER1);
memcpy(dst + from, src + src_from, bytes);
@@ -890,6 +890,11 @@ int ocfs2_map_and_write_user_data(struct inode *inode,
to = from + bytes;
+ BUG_ON(from > PAGE_CACHE_SIZE);
+ BUG_ON(to > PAGE_CACHE_SIZE);
+ BUG_ON(from < cluster_start);
+ BUG_ON(to > cluster_end);
+
if (wc->w_this_page_new)
ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode,
cluster_start, cluster_end, 1);
@@ -901,11 +906,6 @@ int ocfs2_map_and_write_user_data(struct inode *inode,
goto out;
}
- BUG_ON(from > PAGE_CACHE_SIZE);
- BUG_ON(to > PAGE_CACHE_SIZE);
- BUG_ON(from > osb->s_clustersize);
- BUG_ON(to > osb->s_clustersize);
-
dst = kmap(wc->w_this_page);
memcpy(dst + from, bp->b_src_buf + src_from, bytes);
kunmap(wc->w_this_page);
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index a93620ce4ac..e9e042b93db 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -74,7 +74,6 @@ struct mlog_attribute {
#define define_mask(_name) { \
.attr = { \
.name = #_name, \
- .owner = THIS_MODULE, \
.mode = S_IRUGO | S_IWUSR, \
}, \
.mask = ML_##_name, \
@@ -144,8 +143,7 @@ static struct kobj_type mlog_ktype = {
};
static struct kset mlog_kset = {
- .kobj = {.name = "logmask"},
- .ktype = &mlog_ktype
+ .kobj = {.name = "logmask", .ktype = &mlog_ktype},
};
int mlog_sys_init(struct kset *o2cb_subsys)
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index ac6c96431bb..4979b667571 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -31,7 +31,7 @@
#include <linux/pagemap.h>
#include <linux/uio.h>
#include <linux/sched.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
#include <linux/mount.h>
#include <linux/writeback.h>
@@ -1583,7 +1583,7 @@ static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe,
ssize_t copied = 0;
struct ocfs2_splice_write_priv sp;
- ret = buf->ops->pin(pipe, buf);
+ ret = buf->ops->confirm(pipe, buf);
if (ret)
goto out;
@@ -1604,7 +1604,7 @@ static int ocfs2_splice_write_actor(struct pipe_inode_info *pipe,
* might enter ocfs2_buffered_write_cluster() more
* than once, so keep track of our progress here.
*/
- copied = ocfs2_buffered_write_cluster(sd->file,
+ copied = ocfs2_buffered_write_cluster(sd->u.file,
(loff_t)sd->pos + total,
count,
ocfs2_map_and_write_splice_data,
@@ -1636,9 +1636,14 @@ static ssize_t __ocfs2_file_splice_write(struct pipe_inode_info *pipe,
int ret, err;
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
-
- ret = __splice_from_pipe(pipe, out, ppos, len, flags,
- ocfs2_splice_write_actor);
+ struct splice_desc sd = {
+ .total_len = len,
+ .flags = flags,
+ .pos = *ppos,
+ .u.file = out,
+ };
+
+ ret = __splice_from_pipe(pipe, &sd, ocfs2_splice_write_actor);
if (ret > 0) {
*ppos += ret;
@@ -1817,7 +1822,6 @@ const struct inode_operations ocfs2_special_file_iops = {
const struct file_operations ocfs2_fops = {
.read = do_sync_read,
.write = do_sync_write,
- .sendfile = generic_file_sendfile,
.mmap = ocfs2_mmap,
.fsync = ocfs2_sync_file,
.release = ocfs2_file_release,
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 9a3a058f355..98e0b85a9bb 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -397,7 +397,6 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
static struct attribute addpartattr = {
.name = "whole_disk",
.mode = S_IRUSR | S_IRGRP | S_IROTH,
- .owner = THIS_MODULE,
};
sysfs_create_file(&p->kobj, &addpartattr);
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c
index 9f7ad4244f6..1e064c4a4f8 100644
--- a/fs/partitions/ibm.c
+++ b/fs/partitions/ibm.c
@@ -45,7 +45,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
{
int blocksize, offset, size,res;
loff_t i_size;
- dasd_information_t *info;
+ dasd_information2_t *info;
struct hd_geometry *geo;
char type[5] = {0,};
char name[7] = {0,};
@@ -64,14 +64,17 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
if (i_size == 0)
goto out_exit;
- if ((info = kmalloc(sizeof(dasd_information_t), GFP_KERNEL)) == NULL)
+ info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
+ if (info == NULL)
goto out_exit;
- if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL)
+ geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL);
+ if (geo == NULL)
goto out_nogeo;
- if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL)
+ label = kmalloc(sizeof(union label_t), GFP_KERNEL);
+ if (label == NULL)
goto out_nolab;
- if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 ||
+ if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 ||
ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
goto out_freeall;
@@ -96,84 +99,108 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev)
res = 1;
/*
- * Three different types: CMS1, VOL1 and LNX1/unlabeled
+ * Three different formats: LDL, CDL and unformated disk
+ *
+ * identified by info->format
+ *
+ * unformated disks we do not have to care about
*/
- if (strncmp(type, "CMS1", 4) == 0) {
- /*
- * VM style CMS1 labeled disk
- */
- if (label->cms.disk_offset != 0) {
- printk("CMS1/%8s(MDSK):", name);
- /* disk is reserved minidisk */
- blocksize = label->cms.block_size;
- offset = label->cms.disk_offset;
- size = (label->cms.block_count - 1) * (blocksize >> 9);
+ if (info->format == DASD_FORMAT_LDL) {
+ if (strncmp(type, "CMS1", 4) == 0) {
+ /*
+ * VM style CMS1 labeled disk
+ */
+ if (label->cms.disk_offset != 0) {
+ printk("CMS1/%8s(MDSK):", name);
+ /* disk is reserved minidisk */
+ blocksize = label->cms.block_size;
+ offset = label->cms.disk_offset;
+ size = (label->cms.block_count - 1)
+ * (blocksize >> 9);
+ } else {
+ printk("CMS1/%8s:", name);
+ offset = (info->label_block + 1);
+ size = i_size >> 9;
+ }
} else {
- printk("CMS1/%8s:", name);
+ /*
+ * Old style LNX1 or unlabeled disk
+ */
+ if (strncmp(type, "LNX1", 4) == 0)
+ printk ("LNX1/%8s:", name);
+ else
+ printk("(nonl)");
offset = (info->label_block + 1);
size = i_size >> 9;
}
put_partition(state, 1, offset*(blocksize >> 9),
- size-offset*(blocksize >> 9));
- } else if ((strncmp(type, "VOL1", 4) == 0) &&
- (!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
+ size-offset*(blocksize >> 9));
+ } else if (info->format == DASD_FORMAT_CDL) {
/*
- * New style VOL1 labeled disk
+ * New style CDL formatted disk
*/
unsigned int blk;
int counter;
- printk("VOL1/%8s:", name);
-
- /* get block number and read then go through format1 labels */
- blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
- counter = 0;
- while ((data = read_dev_sector(bdev, blk*(blocksize/512),
- &sect)) != NULL) {
- struct vtoc_format1_label f1;
-
- memcpy(&f1, data, sizeof(struct vtoc_format1_label));
- put_dev_sector(sect);
-
- /* skip FMT4 / FMT5 / FMT7 labels */
- if (f1.DS1FMTID == _ascebc['4']
- || f1.DS1FMTID == _ascebc['5']
- || f1.DS1FMTID == _ascebc['7']) {
- blk++;
- continue;
- }
-
- /* only FMT1 valid at this point */
- if (f1.DS1FMTID != _ascebc['1'])
- break;
-
- /* OK, we got valid partition data */
- offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
- size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
- offset + geo->sectors;
- if (counter >= state->limit)
- break;
- put_partition(state, counter + 1,
- offset * (blocksize >> 9),
- size * (blocksize >> 9));
- counter++;
- blk++;
- }
- if (!data)
- /* Are we not supposed to report this ? */
- goto out_readerr;
- } else {
/*
- * Old style LNX1 or unlabeled disk
+ * check if VOL1 label is available
+ * if not, something is wrong, skipping partition detection
*/
- if (strncmp(type, "LNX1", 4) == 0)
- printk ("LNX1/%8s:", name);
- else
- printk("(nonl)/%8s:", name);
- offset = (info->label_block + 1);
- size = i_size >> 9;
- put_partition(state, 1, offset*(blocksize >> 9),
- size-offset*(blocksize >> 9));
+ if (strncmp(type, "VOL1", 4) == 0) {
+ printk("VOL1/%8s:", name);
+ /*
+ * get block number and read then go through format1
+ * labels
+ */
+ blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
+ counter = 0;
+ data = read_dev_sector(bdev, blk * (blocksize/512),
+ &sect);
+ while (data != NULL) {
+ struct vtoc_format1_label f1;
+
+ memcpy(&f1, data,
+ sizeof(struct vtoc_format1_label));
+ put_dev_sector(sect);
+
+ /* skip FMT4 / FMT5 / FMT7 labels */
+ if (f1.DS1FMTID == _ascebc['4']
+ || f1.DS1FMTID == _ascebc['5']
+ || f1.DS1FMTID == _ascebc['7']) {
+ blk++;
+ data = read_dev_sector(bdev, blk *
+ (blocksize/512),
+ &sect);
+ continue;
+ }
+
+ /* only FMT1 valid at this point */
+ if (f1.DS1FMTID != _ascebc['1'])
+ break;
+
+ /* OK, we got valid partition data */
+ offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
+ size = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
+ offset + geo->sectors;
+ if (counter >= state->limit)
+ break;
+ put_partition(state, counter + 1,
+ offset * (blocksize >> 9),
+ size * (blocksize >> 9));
+ counter++;
+ blk++;
+ data = read_dev_sector(bdev,
+ blk * (blocksize/512),
+ &sect);
+ }
+
+ if (!data)
+ /* Are we not supposed to report this ? */
+ goto out_readerr;
+ } else
+ printk(KERN_WARNING "Warning, expected Label VOL1 not "
+ "found, treating as CDL formated Disk");
+
}
printk("\n");
diff --git a/fs/pipe.c b/fs/pipe.c
index 3a89592bdf5..d007830d9c8 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -164,6 +164,20 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe,
page_cache_release(page);
}
+/**
+ * generic_pipe_buf_map - virtually map a pipe buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer that should be mapped
+ * @atomic: whether to use an atomic map
+ *
+ * Description:
+ * This function returns a kernel virtual address mapping for the
+ * passed in @pipe_buffer. If @atomic is set, an atomic map is provided
+ * and the caller has to be careful not to fault before calling
+ * the unmap function.
+ *
+ * Note that this function occupies KM_USER0 if @atomic != 0.
+ */
void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
struct pipe_buffer *buf, int atomic)
{
@@ -175,6 +189,15 @@ void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
return kmap(buf->page);
}
+/**
+ * generic_pipe_buf_unmap - unmap a previously mapped pipe buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer that should be unmapped
+ * @map_data: the data that the mapping function returned
+ *
+ * Description:
+ * This function undoes the mapping that ->map() provided.
+ */
void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
struct pipe_buffer *buf, void *map_data)
{
@@ -185,11 +208,28 @@ void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
kunmap(buf->page);
}
+/**
+ * generic_pipe_buf_steal - attempt to take ownership of a @pipe_buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer to attempt to steal
+ *
+ * Description:
+ * This function attempts to steal the @struct page attached to
+ * @buf. If successful, this function returns 0 and returns with
+ * the page locked. The caller may then reuse the page for whatever
+ * he wishes, the typical use is insertion into a different file
+ * page cache.
+ */
int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
struct pipe_buffer *buf)
{
struct page *page = buf->page;
+ /*
+ * A reference of one is golden, that means that the owner of this
+ * page is the only one holding a reference to it. lock the page
+ * and return OK.
+ */
if (page_count(page) == 1) {
lock_page(page);
return 0;
@@ -198,12 +238,32 @@ int generic_pipe_buf_steal(struct pipe_inode_info *pipe,
return 1;
}
-void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/**
+ * generic_pipe_buf_get - get a reference to a @struct pipe_buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer to get a reference to
+ *
+ * Description:
+ * This function grabs an extra reference to @buf. It's used in
+ * in the tee() system call, when we duplicate the buffers in one
+ * pipe into another.
+ */
+void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
{
page_cache_get(buf->page);
}
-int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf)
+/**
+ * generic_pipe_buf_confirm - verify contents of the pipe buffer
+ * @pipe: the pipe that the buffer belongs to
+ * @buf: the buffer to confirm
+ *
+ * Description:
+ * This function does nothing, because the generic pipe code uses
+ * pages that are always good when inserted into the pipe.
+ */
+int generic_pipe_buf_confirm(struct pipe_inode_info *info,
+ struct pipe_buffer *buf)
{
return 0;
}
@@ -212,7 +272,7 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
.can_merge = 1,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
- .pin = generic_pipe_buf_pin,
+ .confirm = generic_pipe_buf_confirm,
.release = anon_pipe_buf_release,
.steal = generic_pipe_buf_steal,
.get = generic_pipe_buf_get,
@@ -252,7 +312,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
if (chars > total_len)
chars = total_len;
- error = ops->pin(pipe, buf);
+ error = ops->confirm(pipe, buf);
if (error) {
if (!ret)
error = ret;
@@ -373,7 +433,7 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
int error, atomic = 1;
void *addr;
- error = ops->pin(pipe, buf);
+ error = ops->confirm(pipe, buf);
if (error)
goto out;
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 74f30e0c038..98e78e2f18d 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -165,7 +165,6 @@ static inline char * task_state(struct task_struct *p, char *buffer)
rcu_read_lock();
buffer += sprintf(buffer,
"State:\t%s\n"
- "SleepAVG:\t%lu%%\n"
"Tgid:\t%d\n"
"Pid:\t%d\n"
"PPid:\t%d\n"
@@ -173,7 +172,6 @@ static inline char * task_state(struct task_struct *p, char *buffer)
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n",
get_task_state(p),
- (p->sleep_avg/1024)*100/(1020000000/1024),
p->tgid, p->pid,
pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0,
pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0,
@@ -312,6 +310,41 @@ int proc_pid_status(struct task_struct *task, char * buffer)
return buffer - orig;
}
+static clock_t task_utime(struct task_struct *p)
+{
+ clock_t utime = cputime_to_clock_t(p->utime),
+ total = utime + cputime_to_clock_t(p->stime);
+ u64 temp;
+
+ /*
+ * Use CFS's precise accounting:
+ */
+ temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime);
+
+ if (total) {
+ temp *= utime;
+ do_div(temp, total);
+ }
+ utime = (clock_t)temp;
+
+ return utime;
+}
+
+static clock_t task_stime(struct task_struct *p)
+{
+ clock_t stime = cputime_to_clock_t(p->stime);
+
+ /*
+ * Use CFS's precise accounting. (we subtract utime from
+ * the total, to make sure the total observed by userspace
+ * grows monotonically - apps rely on that):
+ */
+ stime = nsec_to_clock_t(p->se.sum_exec_runtime) - task_utime(p);
+
+ return stime;
+}
+
+
static int do_task_stat(struct task_struct *task, char * buffer, int whole)
{
unsigned long vsize, eip, esp, wchan = ~0UL;
@@ -326,7 +359,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
unsigned long long start_time;
unsigned long cmin_flt = 0, cmaj_flt = 0;
unsigned long min_flt = 0, maj_flt = 0;
- cputime_t cutime, cstime, utime, stime;
+ cputime_t cutime, cstime;
+ clock_t utime, stime;
unsigned long rsslim = 0;
char tcomm[sizeof(task->comm)];
unsigned long flags;
@@ -344,7 +378,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
sigemptyset(&sigign);
sigemptyset(&sigcatch);
- cutime = cstime = utime = stime = cputime_zero;
+ cutime = cstime = cputime_zero;
+ utime = stime = 0;
rcu_read_lock();
if (lock_task_sighand(task, &flags)) {
@@ -370,15 +405,15 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
do {
min_flt += t->min_flt;
maj_flt += t->maj_flt;
- utime = cputime_add(utime, t->utime);
- stime = cputime_add(stime, t->stime);
+ utime += task_utime(t);
+ stime += task_stime(t);
t = next_thread(t);
} while (t != task);
min_flt += sig->min_flt;
maj_flt += sig->maj_flt;
- utime = cputime_add(utime, sig->utime);
- stime = cputime_add(stime, sig->stime);
+ utime += cputime_to_clock_t(sig->utime);
+ stime += cputime_to_clock_t(sig->stime);
}
sid = signal_session(sig);
@@ -394,8 +429,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
if (!whole) {
min_flt = task->min_flt;
maj_flt = task->maj_flt;
- utime = task->utime;
- stime = task->stime;
+ utime = task_utime(task);
+ stime = task_stime(task);
}
/* scale priority and nice values from timeslices to -20..20 */
@@ -426,8 +461,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
cmin_flt,
maj_flt,
cmaj_flt,
- cputime_to_clock_t(utime),
- cputime_to_clock_t(stime),
+ utime,
+ stime,
cputime_to_clock_t(cutime),
cputime_to_clock_t(cstime),
priority,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a5fa1fdafc4..46ea5d56e1b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -296,7 +296,7 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
*/
static int proc_pid_schedstat(struct task_struct *task, char *buffer)
{
- return sprintf(buffer, "%lu %lu %lu\n",
+ return sprintf(buffer, "%llu %llu %lu\n",
task->sched_info.cpu_time,
task->sched_info.run_delay,
task->sched_info.pcnt);
@@ -929,6 +929,69 @@ static const struct file_operations proc_fault_inject_operations = {
};
#endif
+#ifdef CONFIG_SCHED_DEBUG
+/*
+ * Print out various scheduling related per-task fields:
+ */
+static int sched_show(struct seq_file *m, void *v)
+{
+ struct inode *inode = m->private;
+ struct task_struct *p;
+
+ WARN_ON(!inode);
+
+ p = get_proc_task(inode);
+ if (!p)
+ return -ESRCH;
+ proc_sched_show_task(p, m);
+
+ put_task_struct(p);
+
+ return 0;
+}
+
+static ssize_t
+sched_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct task_struct *p;
+
+ WARN_ON(!inode);
+
+ p = get_proc_task(inode);
+ if (!p)
+ return -ESRCH;
+ proc_sched_set_task(p);
+
+ put_task_struct(p);
+
+ return count;
+}
+
+static int sched_open(struct inode *inode, struct file *filp)
+{
+ int ret;
+
+ ret = single_open(filp, sched_show, NULL);
+ if (!ret) {
+ struct seq_file *m = filp->private_data;
+
+ m->private = inode;
+ }
+ return ret;
+}
+
+static const struct file_operations proc_pid_sched_operations = {
+ .open = sched_open,
+ .read = seq_read,
+ .write = sched_write,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+#endif
+
static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
@@ -1963,6 +2026,9 @@ static const struct pid_entry tgid_base_stuff[] = {
INF("environ", S_IRUSR, pid_environ),
INF("auxv", S_IRUSR, pid_auxv),
INF("status", S_IRUGO, pid_status),
+#ifdef CONFIG_SCHED_DEBUG
+ REG("sched", S_IRUGO|S_IWUSR, pid_sched),
+#endif
INF("cmdline", S_IRUGO, pid_cmdline),
INF("stat", S_IRUGO, tgid_stat),
INF("statm", S_IRUGO, pid_statm),
@@ -2247,6 +2313,9 @@ static const struct pid_entry tid_base_stuff[] = {
INF("environ", S_IRUSR, pid_environ),
INF("auxv", S_IRUSR, pid_auxv),
INF("status", S_IRUGO, pid_status),
+#ifdef CONFIG_SCHED_DEBUG
+ REG("sched", S_IRUGO|S_IWUSR, pid_sched),
+#endif
INF("cmdline", S_IRUGO, pid_cmdline),
INF("stat", S_IRUGO, tid_stat),
INF("statm", S_IRUGO, pid_statm),
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 44649981bbc..867f42b0203 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -25,7 +25,7 @@ const struct file_operations qnx4_file_operations =
.read = do_sync_read,
.aio_read = generic_file_aio_read,
.mmap = generic_file_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
#ifdef CONFIG_QNX4FS_RW
.write = do_sync_write,
.aio_write = generic_file_aio_write,
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 2f14774a124..97bdc0b2f9d 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -41,7 +41,7 @@ const struct file_operations ramfs_file_operations = {
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = simple_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.llseek = generic_file_llseek,
};
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index 9345a46ffb3..cad2b7ace63 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -42,7 +42,7 @@ const struct file_operations ramfs_file_operations = {
.write = do_sync_write,
.aio_write = generic_file_aio_write,
.fsync = simple_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
.llseek = generic_file_llseek,
};
@@ -195,6 +195,11 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia)
unsigned int old_ia_valid = ia->ia_valid;
int ret = 0;
+ /* POSIX UID/GID verification for setting inode attributes */
+ ret = inode_change_ok(inode, ia);
+ if (ret)
+ return ret;
+
/* by providing our own setattr() method, we skip this quotaism */
if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) ||
(old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid))
diff --git a/fs/read_write.c b/fs/read_write.c
index 4d03008f015..507ddff48a9 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/pagemap.h>
+#include <linux/splice.h>
#include "read_write.h"
#include <asm/uaccess.h>
@@ -25,7 +26,7 @@ const struct file_operations generic_ro_fops = {
.read = do_sync_read,
.aio_read = generic_file_aio_read,
.mmap = generic_file_readonly_mmap,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
EXPORT_SYMBOL(generic_ro_fops);
@@ -708,7 +709,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
struct inode * in_inode, * out_inode;
loff_t pos;
ssize_t retval;
- int fput_needed_in, fput_needed_out;
+ int fput_needed_in, fput_needed_out, fl;
/*
* Get input file, and verify that it is ok..
@@ -723,7 +724,7 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
in_inode = in_file->f_path.dentry->d_inode;
if (!in_inode)
goto fput_in;
- if (!in_file->f_op || !in_file->f_op->sendfile)
+ if (!in_file->f_op || !in_file->f_op->splice_read)
goto fput_in;
retval = -ESPIPE;
if (!ppos)
@@ -776,7 +777,18 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
count = max - pos;
}
- retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
+ fl = 0;
+#if 0
+ /*
+ * We need to debate whether we can enable this or not. The
+ * man page documents EAGAIN return for the output at least,
+ * and the application is arguably buggy if it doesn't expect
+ * EAGAIN on a non-blocking file descriptor.
+ */
+ if (in_file->f_flags & O_NONBLOCK)
+ fl = SPLICE_F_NONBLOCK;
+#endif
+ retval = do_splice_direct(in_file, ppos, out_file, count, fl);
if (retval > 0) {
add_rchar(current, retval);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 9e451a68580..30eebfb1b2d 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1531,7 +1531,6 @@ const struct file_operations reiserfs_file_operations = {
.open = generic_file_open,
.release = reiserfs_file_release,
.fsync = reiserfs_sync_file,
- .sendfile = generic_file_sendfile,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.splice_read = generic_file_splice_read,
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 0ac22af7afe..49194a4e6b9 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -447,3 +447,37 @@ int seq_puts(struct seq_file *m, const char *s)
return -1;
}
EXPORT_SYMBOL(seq_puts);
+
+struct list_head *seq_list_start(struct list_head *head, loff_t pos)
+{
+ struct list_head *lh;
+
+ list_for_each(lh, head)
+ if (pos-- == 0)
+ return lh;
+
+ return NULL;
+}
+
+EXPORT_SYMBOL(seq_list_start);
+
+struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
+{
+ if (!pos)
+ return head;
+
+ return seq_list_start(head, pos - 1);
+}
+
+EXPORT_SYMBOL(seq_list_start_head);
+
+struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
+{
+ struct list_head *lh;
+
+ lh = ((struct list_head *)v)->next;
+ ++*ppos;
+ return lh == head ? NULL : lh;
+}
+
+EXPORT_SYMBOL(seq_list_next);
diff --git a/fs/signalfd.c b/fs/signalfd.c
index f1da89203a9..3b07f26d984 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -133,7 +133,8 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait)
* the peer disconnects.
*/
if (signalfd_lock(ctx, &lk)) {
- if (next_signal(&lk.tsk->pending, &ctx->sigmask) > 0 ||
+ if ((lk.tsk == current &&
+ next_signal(&lk.tsk->pending, &ctx->sigmask) > 0) ||
next_signal(&lk.tsk->signal->shared_pending,
&ctx->sigmask) > 0)
events |= POLLIN;
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index aea3f8aa54c..c5d78a7e492 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -262,8 +262,9 @@ out:
}
static ssize_t
-smb_file_sendfile(struct file *file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
+smb_file_splice_read(struct file *file, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t count,
+ unsigned int flags)
{
struct dentry *dentry = file->f_path.dentry;
ssize_t status;
@@ -277,7 +278,7 @@ smb_file_sendfile(struct file *file, loff_t *ppos,
DENTRY_PATH(dentry), status);
goto out;
}
- status = generic_file_sendfile(file, ppos, count, actor, target);
+ status = generic_file_splice_read(file, ppos, pipe, count, flags);
out:
return status;
}
@@ -416,7 +417,7 @@ const struct file_operations smb_file_operations =
.open = smb_file_open,
.release = smb_file_release,
.fsync = smb_fsync,
- .sendfile = smb_file_sendfile,
+ .splice_read = smb_file_splice_read,
};
const struct inode_operations smb_file_inode_operations =
diff --git a/fs/splice.c b/fs/splice.c
index 12f28281d2b..6c9828651e6 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -20,7 +20,7 @@
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/pagemap.h>
-#include <linux/pipe_fs_i.h>
+#include <linux/splice.h>
#include <linux/mm_inline.h>
#include <linux/swap.h>
#include <linux/writeback.h>
@@ -28,22 +28,7 @@
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/uio.h>
-
-struct partial_page {
- unsigned int offset;
- unsigned int len;
-};
-
-/*
- * Passed to splice_to_pipe
- */
-struct splice_pipe_desc {
- struct page **pages; /* page map */
- struct partial_page *partial; /* pages[] may not be contig */
- int nr_pages; /* number of pages in map */
- unsigned int flags; /* splice flags */
- const struct pipe_buf_operations *ops;/* ops associated with output pipe */
-};
+#include <linux/security.h>
/*
* Attempt to steal a page from a pipe buffer. This should perhaps go into
@@ -101,8 +86,12 @@ static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,
buf->flags &= ~PIPE_BUF_FLAG_LRU;
}
-static int page_cache_pipe_buf_pin(struct pipe_inode_info *pipe,
- struct pipe_buffer *buf)
+/*
+ * Check whether the contents of buf is OK to access. Since the content
+ * is a page cache page, IO may be in flight.
+ */
+static int page_cache_pipe_buf_confirm(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
{
struct page *page = buf->page;
int err;
@@ -143,7 +132,7 @@ static const struct pipe_buf_operations page_cache_pipe_buf_ops = {
.can_merge = 0,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
- .pin = page_cache_pipe_buf_pin,
+ .confirm = page_cache_pipe_buf_confirm,
.release = page_cache_pipe_buf_release,
.steal = page_cache_pipe_buf_steal,
.get = generic_pipe_buf_get,
@@ -163,19 +152,27 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = {
.can_merge = 0,
.map = generic_pipe_buf_map,
.unmap = generic_pipe_buf_unmap,
- .pin = generic_pipe_buf_pin,
+ .confirm = generic_pipe_buf_confirm,
.release = page_cache_pipe_buf_release,
.steal = user_page_pipe_buf_steal,
.get = generic_pipe_buf_get,
};
-/*
- * Pipe output worker. This sets up our pipe format with the page cache
- * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
+/**
+ * splice_to_pipe - fill passed data into a pipe
+ * @pipe: pipe to fill
+ * @spd: data to fill
+ *
+ * Description:
+ * @spd contains a map of pages and len/offset tupples, a long with
+ * the struct pipe_buf_operations associated with these pages. This
+ * function will link that data to the pipe.
+ *
*/
-static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
- struct splice_pipe_desc *spd)
+ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
+ struct splice_pipe_desc *spd)
{
+ unsigned int spd_pages = spd->nr_pages;
int ret, do_wakeup, page_nr;
ret = 0;
@@ -200,6 +197,7 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
buf->page = spd->pages[page_nr];
buf->offset = spd->partial[page_nr].offset;
buf->len = spd->partial[page_nr].len;
+ buf->private = spd->partial[page_nr].private;
buf->ops = spd->ops;
if (spd->flags & SPLICE_F_GIFT)
buf->flags |= PIPE_BUF_FLAG_GIFT;
@@ -244,17 +242,18 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe,
pipe->waiting_writers--;
}
- if (pipe->inode)
+ if (pipe->inode) {
mutex_unlock(&pipe->inode->i_mutex);
- if (do_wakeup) {
- smp_mb();
- if (waitqueue_active(&pipe->wait))
- wake_up_interruptible(&pipe->wait);
- kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+ if (do_wakeup) {
+ smp_mb();
+ if (waitqueue_active(&pipe->wait))
+ wake_up_interruptible(&pipe->wait);
+ kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
+ }
}
- while (page_nr < spd->nr_pages)
+ while (page_nr < spd_pages)
page_cache_release(spd->pages[page_nr++]);
return ret;
@@ -272,7 +271,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
struct page *page;
pgoff_t index, end_index;
loff_t isize;
- size_t total_len;
int error, page_nr;
struct splice_pipe_desc spd = {
.pages = pages,
@@ -295,20 +293,15 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
page_cache_readahead(mapping, &in->f_ra, in, index, nr_pages);
/*
- * Now fill in the holes:
- */
- error = 0;
- total_len = 0;
-
- /*
* Lookup the (hopefully) full range of pages we need.
*/
spd.nr_pages = find_get_pages_contig(mapping, index, nr_pages, pages);
/*
* If find_get_pages_contig() returned fewer pages than we needed,
- * allocate the rest.
+ * allocate the rest and fill in the holes.
*/
+ error = 0;
index += spd.nr_pages;
while (spd.nr_pages < nr_pages) {
/*
@@ -415,43 +408,47 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
break;
}
+ }
+fill_it:
+ /*
+ * i_size must be checked after PageUptodate.
+ */
+ isize = i_size_read(mapping->host);
+ end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+ if (unlikely(!isize || index > end_index))
+ break;
+
+ /*
+ * if this is the last page, see if we need to shrink
+ * the length and stop
+ */
+ if (end_index == index) {
+ unsigned int plen;
/*
- * i_size must be checked after ->readpage().
+ * max good bytes in this page
*/
- isize = i_size_read(mapping->host);
- end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
- if (unlikely(!isize || index > end_index))
+ plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+ if (plen <= loff)
break;
/*
- * if this is the last page, see if we need to shrink
- * the length and stop
+ * force quit after adding this page
*/
- if (end_index == index) {
- loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
- if (total_len + loff > isize)
- break;
- /*
- * force quit after adding this page
- */
- len = this_len;
- this_len = min(this_len, loff);
- loff = 0;
- }
+ this_len = min(this_len, plen - loff);
+ len = this_len;
}
-fill_it:
+
partial[page_nr].offset = loff;
partial[page_nr].len = this_len;
len -= this_len;
- total_len += this_len;
loff = 0;
spd.nr_pages++;
index++;
}
/*
- * Release any pages at the end, if we quit early. 'i' is how far
+ * Release any pages at the end, if we quit early. 'page_nr' is how far
* we got, 'nr_pages' is how many pages are in the map.
*/
while (page_nr < nr_pages)
@@ -466,11 +463,16 @@ fill_it:
/**
* generic_file_splice_read - splice data from file to a pipe
* @in: file to splice from
+ * @ppos: position in @in
* @pipe: pipe to splice to
* @len: number of bytes to splice
* @flags: splice modifier flags
*
- * Will read pages from given file and fill them into a pipe.
+ * Description:
+ * Will read pages from given file and fill them into a pipe. Can be
+ * used as long as the address_space operations for the source implements
+ * a readpage() hook.
+ *
*/
ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
@@ -478,11 +480,19 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
{
ssize_t spliced;
int ret;
+ loff_t isize, left;
+
+ isize = i_size_read(in->f_mapping->host);
+ if (unlikely(*ppos >= isize))
+ return 0;
+
+ left = isize - *ppos;
+ if (unlikely(left < len))
+ len = left;
ret = 0;
spliced = 0;
-
- while (len) {
+ while (len && !spliced) {
ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
if (ret < 0)
@@ -516,11 +526,11 @@ EXPORT_SYMBOL(generic_file_splice_read);
static int pipe_to_sendpage(struct pipe_inode_info *pipe,
struct pipe_buffer *buf, struct splice_desc *sd)
{
- struct file *file = sd->file;
+ struct file *file = sd->u.file;
loff_t pos = sd->pos;
int ret, more;
- ret = buf->ops->pin(pipe, buf);
+ ret = buf->ops->confirm(pipe, buf);
if (!ret) {
more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
@@ -554,7 +564,7 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe,
static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
struct splice_desc *sd)
{
- struct file *file = sd->file;
+ struct file *file = sd->u.file;
struct address_space *mapping = file->f_mapping;
unsigned int offset, this_len;
struct page *page;
@@ -564,7 +574,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
/*
* make sure the data in this buffer is uptodate
*/
- ret = buf->ops->pin(pipe, buf);
+ ret = buf->ops->confirm(pipe, buf);
if (unlikely(ret))
return ret;
@@ -644,7 +654,6 @@ find_page:
* accessed, we are now done!
*/
mark_page_accessed(page);
- balance_dirty_pages_ratelimited(mapping);
out:
page_cache_release(page);
unlock_page(page);
@@ -652,36 +661,37 @@ out_ret:
return ret;
}
-/*
- * Pipe input worker. Most of this logic works like a regular pipe, the
- * key here is the 'actor' worker passed in that actually moves the data
- * to the wanted destination. See pipe_to_file/pipe_to_sendpage above.
+/**
+ * __splice_from_pipe - splice data from a pipe to given actor
+ * @pipe: pipe to splice from
+ * @sd: information to @actor
+ * @actor: handler that splices the data
+ *
+ * Description:
+ * This function does little more than loop over the pipe and call
+ * @actor to do the actual moving of a single struct pipe_buffer to
+ * the desired destination. See pipe_to_file, pipe_to_sendpage, or
+ * pipe_to_user.
+ *
*/
-ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
- struct file *out, loff_t *ppos, size_t len,
- unsigned int flags, splice_actor *actor)
+ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
+ splice_actor *actor)
{
int ret, do_wakeup, err;
- struct splice_desc sd;
ret = 0;
do_wakeup = 0;
- sd.total_len = len;
- sd.flags = flags;
- sd.file = out;
- sd.pos = *ppos;
-
for (;;) {
if (pipe->nrbufs) {
struct pipe_buffer *buf = pipe->bufs + pipe->curbuf;
const struct pipe_buf_operations *ops = buf->ops;
- sd.len = buf->len;
- if (sd.len > sd.total_len)
- sd.len = sd.total_len;
+ sd->len = buf->len;
+ if (sd->len > sd->total_len)
+ sd->len = sd->total_len;
- err = actor(pipe, buf, &sd);
+ err = actor(pipe, buf, sd);
if (err <= 0) {
if (!ret && err != -ENODATA)
ret = err;
@@ -693,10 +703,10 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
buf->offset += err;
buf->len -= err;
- sd.len -= err;
- sd.pos += err;
- sd.total_len -= err;
- if (sd.len)
+ sd->len -= err;
+ sd->pos += err;
+ sd->total_len -= err;
+ if (sd->len)
continue;
if (!buf->len) {
@@ -708,7 +718,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
do_wakeup = 1;
}
- if (!sd.total_len)
+ if (!sd->total_len)
break;
}
@@ -721,7 +731,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
break;
}
- if (flags & SPLICE_F_NONBLOCK) {
+ if (sd->flags & SPLICE_F_NONBLOCK) {
if (!ret)
ret = -EAGAIN;
break;
@@ -755,12 +765,32 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe,
}
EXPORT_SYMBOL(__splice_from_pipe);
+/**
+ * splice_from_pipe - splice data from a pipe to a file
+ * @pipe: pipe to splice from
+ * @out: file to splice to
+ * @ppos: position in @out
+ * @len: how many bytes to splice
+ * @flags: splice modifier flags
+ * @actor: handler that splices the data
+ *
+ * Description:
+ * See __splice_from_pipe. This function locks the input and output inodes,
+ * otherwise it's identical to __splice_from_pipe().
+ *
+ */
ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
loff_t *ppos, size_t len, unsigned int flags,
splice_actor *actor)
{
ssize_t ret;
struct inode *inode = out->f_mapping->host;
+ struct splice_desc sd = {
+ .total_len = len,
+ .flags = flags,
+ .pos = *ppos,
+ .u.file = out,
+ };
/*
* The actor worker might be calling ->prepare_write and
@@ -769,7 +799,7 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
* pipe->inode, we have to order lock acquiry here.
*/
inode_double_lock(inode, pipe->inode);
- ret = __splice_from_pipe(pipe, out, ppos, len, flags, actor);
+ ret = __splice_from_pipe(pipe, &sd, actor);
inode_double_unlock(inode, pipe->inode);
return ret;
@@ -779,12 +809,14 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out,
* generic_file_splice_write_nolock - generic_file_splice_write without mutexes
* @pipe: pipe info
* @out: file to write to
+ * @ppos: position in @out
* @len: number of bytes to splice
* @flags: splice modifier flags
*
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file. The caller is responsible
- * for acquiring i_mutex on both inodes.
+ * Description:
+ * Will either move or copy pages (determined by @flags options) from
+ * the given pipe inode to the given file. The caller is responsible
+ * for acquiring i_mutex on both inodes.
*
*/
ssize_t
@@ -793,6 +825,12 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
{
struct address_space *mapping = out->f_mapping;
struct inode *inode = mapping->host;
+ struct splice_desc sd = {
+ .total_len = len,
+ .flags = flags,
+ .pos = *ppos,
+ .u.file = out,
+ };
ssize_t ret;
int err;
@@ -800,9 +838,12 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
if (unlikely(err))
return err;
- ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
+ ret = __splice_from_pipe(pipe, &sd, pipe_to_file);
if (ret > 0) {
+ unsigned long nr_pages;
+
*ppos += ret;
+ nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
/*
* If file or inode is SYNC and we actually wrote some data,
@@ -815,6 +856,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
if (err)
ret = err;
}
+ balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
}
return ret;
@@ -826,11 +868,13 @@ EXPORT_SYMBOL(generic_file_splice_write_nolock);
* generic_file_splice_write - splice data from a pipe to a file
* @pipe: pipe info
* @out: file to write to
+ * @ppos: position in @out
* @len: number of bytes to splice
* @flags: splice modifier flags
*
- * Will either move or copy pages (determined by @flags options) from
- * the given pipe inode to the given file.
+ * Description:
+ * Will either move or copy pages (determined by @flags options) from
+ * the given pipe inode to the given file.
*
*/
ssize_t
@@ -853,7 +897,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
if (ret > 0) {
+ unsigned long nr_pages;
+
*ppos += ret;
+ nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
/*
* If file or inode is SYNC and we actually wrote some data,
@@ -868,6 +915,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
if (err)
ret = err;
}
+ balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
}
return ret;
@@ -877,13 +925,15 @@ EXPORT_SYMBOL(generic_file_splice_write);
/**
* generic_splice_sendpage - splice data from a pipe to a socket
- * @inode: pipe inode
+ * @pipe: pipe to splice from
* @out: socket to write to
+ * @ppos: position in @out
* @len: number of bytes to splice
* @flags: splice modifier flags
*
- * Will send @len bytes from the pipe to a network socket. No data copying
- * is involved.
+ * Description:
+ * Will send @len bytes from the pipe to a network socket. No data copying
+ * is involved.
*
*/
ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out,
@@ -912,6 +962,10 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
if (unlikely(ret < 0))
return ret;
+ ret = security_file_permission(out, MAY_WRITE);
+ if (unlikely(ret < 0))
+ return ret;
+
return out->f_op->splice_write(pipe, out, ppos, len, flags);
}
@@ -922,7 +976,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
- loff_t isize, left;
int ret;
if (unlikely(!in->f_op || !in->f_op->splice_read))
@@ -935,25 +988,34 @@ static long do_splice_to(struct file *in, loff_t *ppos,
if (unlikely(ret < 0))
return ret;
- isize = i_size_read(in->f_mapping->host);
- if (unlikely(*ppos >= isize))
- return 0;
-
- left = isize - *ppos;
- if (unlikely(left < len))
- len = left;
+ ret = security_file_permission(in, MAY_READ);
+ if (unlikely(ret < 0))
+ return ret;
return in->f_op->splice_read(in, ppos, pipe, len, flags);
}
-long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
- size_t len, unsigned int flags)
+/**
+ * splice_direct_to_actor - splices data directly between two non-pipes
+ * @in: file to splice from
+ * @sd: actor information on where to splice to
+ * @actor: handles the data splicing
+ *
+ * Description:
+ * This is a special case helper to splice directly between two
+ * points, without requiring an explicit pipe. Internally an allocated
+ * pipe is cached in the process, and reused during the life time of
+ * that process.
+ *
+ */
+ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+ splice_direct_actor *actor)
{
struct pipe_inode_info *pipe;
long ret, bytes;
- loff_t out_off;
umode_t i_mode;
- int i;
+ size_t len;
+ int i, flags;
/*
* We require the input being a regular file, as we don't want to
@@ -989,49 +1051,41 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
*/
ret = 0;
bytes = 0;
- out_off = 0;
+ len = sd->total_len;
+ flags = sd->flags;
- while (len) {
- size_t read_len, max_read_len;
+ /*
+ * Don't block on output, we have to drain the direct pipe.
+ */
+ sd->flags &= ~SPLICE_F_NONBLOCK;
- /*
- * Do at most PIPE_BUFFERS pages worth of transfer:
- */
- max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
+ while (len) {
+ size_t read_len;
- ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
- if (unlikely(ret < 0))
+ ret = do_splice_to(in, &sd->pos, pipe, len, flags);
+ if (unlikely(ret <= 0))
goto out_release;
read_len = ret;
+ sd->total_len = read_len;
/*
* NOTE: nonblocking mode only applies to the input. We
* must not do the output in nonblocking mode as then we
* could get stuck data in the internal pipe:
*/
- ret = do_splice_from(pipe, out, &out_off, read_len,
- flags & ~SPLICE_F_NONBLOCK);
- if (unlikely(ret < 0))
+ ret = actor(pipe, sd);
+ if (unlikely(ret <= 0))
goto out_release;
bytes += ret;
len -= ret;
- /*
- * In nonblocking mode, if we got back a short read then
- * that was due to either an IO error or due to the
- * pagecache entry not being there. In the IO error case
- * the _next_ splice attempt will produce a clean IO error
- * return value (not a short read), so in both cases it's
- * correct to break out of the loop here:
- */
- if ((flags & SPLICE_F_NONBLOCK) && (read_len < max_read_len))
- break;
+ if (ret < read_len)
+ goto out_release;
}
pipe->nrbufs = pipe->curbuf = 0;
-
return bytes;
out_release:
@@ -1056,9 +1110,51 @@ out_release:
return bytes;
return ret;
+
}
+EXPORT_SYMBOL(splice_direct_to_actor);
-EXPORT_SYMBOL(do_splice_direct);
+static int direct_splice_actor(struct pipe_inode_info *pipe,
+ struct splice_desc *sd)
+{
+ struct file *file = sd->u.file;
+
+ return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags);
+}
+
+/**
+ * do_splice_direct - splices data directly between two files
+ * @in: file to splice from
+ * @ppos: input file offset
+ * @out: file to splice to
+ * @len: number of bytes to splice
+ * @flags: splice modifier flags
+ *
+ * Description:
+ * For use by do_sendfile(). splice can easily emulate sendfile, but
+ * doing it in the application would incur an extra system call
+ * (splice in + splice out, as compared to just sendfile()). So this helper
+ * can splice directly through a process-private pipe.
+ *
+ */
+long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
+ size_t len, unsigned int flags)
+{
+ struct splice_desc sd = {
+ .len = len,
+ .total_len = len,
+ .flags = flags,
+ .pos = *ppos,
+ .u.file = out,
+ };
+ long ret;
+
+ ret = splice_direct_to_actor(in, &sd, direct_splice_actor);
+ if (ret > 0)
+ *ppos += ret;
+
+ return ret;
+}
/*
* After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
@@ -1240,28 +1336,131 @@ static int get_iovec_page_array(const struct iovec __user *iov,
return error;
}
+static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+ struct splice_desc *sd)
+{
+ char *src;
+ int ret;
+
+ ret = buf->ops->confirm(pipe, buf);
+ if (unlikely(ret))
+ return ret;
+
+ /*
+ * See if we can use the atomic maps, by prefaulting in the
+ * pages and doing an atomic copy
+ */
+ if (!fault_in_pages_writeable(sd->u.userptr, sd->len)) {
+ src = buf->ops->map(pipe, buf, 1);
+ ret = __copy_to_user_inatomic(sd->u.userptr, src + buf->offset,
+ sd->len);
+ buf->ops->unmap(pipe, buf, src);
+ if (!ret) {
+ ret = sd->len;
+ goto out;
+ }
+ }
+
+ /*
+ * No dice, use slow non-atomic map and copy
+ */
+ src = buf->ops->map(pipe, buf, 0);
+
+ ret = sd->len;
+ if (copy_to_user(sd->u.userptr, src + buf->offset, sd->len))
+ ret = -EFAULT;
+
+out:
+ if (ret > 0)
+ sd->u.userptr += ret;
+ buf->ops->unmap(pipe, buf, src);
+ return ret;
+}
+
+/*
+ * For lack of a better implementation, implement vmsplice() to userspace
+ * as a simple copy of the pipes pages to the user iov.
+ */
+static long vmsplice_to_user(struct file *file, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags)
+{
+ struct pipe_inode_info *pipe;
+ struct splice_desc sd;
+ ssize_t size;
+ int error;
+ long ret;
+
+ pipe = pipe_info(file->f_path.dentry->d_inode);
+ if (!pipe)
+ return -EBADF;
+
+ if (pipe->inode)
+ mutex_lock(&pipe->inode->i_mutex);
+
+ error = ret = 0;
+ while (nr_segs) {
+ void __user *base;
+ size_t len;
+
+ /*
+ * Get user address base and length for this iovec.
+ */
+ error = get_user(base, &iov->iov_base);
+ if (unlikely(error))
+ break;
+ error = get_user(len, &iov->iov_len);
+ if (unlikely(error))
+ break;
+
+ /*
+ * Sanity check this iovec. 0 read succeeds.
+ */
+ if (unlikely(!len))
+ break;
+ if (unlikely(!base)) {
+ error = -EFAULT;
+ break;
+ }
+
+ sd.len = 0;
+ sd.total_len = len;
+ sd.flags = flags;
+ sd.u.userptr = base;
+ sd.pos = 0;
+
+ size = __splice_from_pipe(pipe, &sd, pipe_to_user);
+ if (size < 0) {
+ if (!ret)
+ ret = size;
+
+ break;
+ }
+
+ ret += size;
+
+ if (size < len)
+ break;
+
+ nr_segs--;
+ iov++;
+ }
+
+ if (pipe->inode)
+ mutex_unlock(&pipe->inode->i_mutex);
+
+ if (!ret)
+ ret = error;
+
+ return ret;
+}
+
/*
* vmsplice splices a user address range into a pipe. It can be thought of
* as splice-from-memory, where the regular splice is splice-from-file (or
* to file). In both cases the output is a pipe, naturally.
- *
- * Note that vmsplice only supports splicing _from_ user memory to a pipe,
- * not the other way around. Splicing from user memory is a simple operation
- * that can be supported without any funky alignment restrictions or nasty
- * vm tricks. We simply map in the user memory and fill them into a pipe.
- * The reverse isn't quite as easy, though. There are two possible solutions
- * for that:
- *
- * - memcpy() the data internally, at which point we might as well just
- * do a regular read() on the buffer anyway.
- * - Lots of nasty vm tricks, that are neither fast nor flexible (it
- * has restriction limitations on both ends of the pipe).
- *
- * Alas, it isn't here.
- *
*/
-static long do_vmsplice(struct file *file, const struct iovec __user *iov,
- unsigned long nr_segs, unsigned int flags)
+static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov,
+ unsigned long nr_segs, unsigned int flags)
{
struct pipe_inode_info *pipe;
struct page *pages[PIPE_BUFFERS];
@@ -1276,10 +1475,6 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
pipe = pipe_info(file->f_path.dentry->d_inode);
if (!pipe)
return -EBADF;
- if (unlikely(nr_segs > UIO_MAXIOV))
- return -EINVAL;
- else if (unlikely(!nr_segs))
- return 0;
spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
flags & SPLICE_F_GIFT);
@@ -1289,6 +1484,22 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
return splice_to_pipe(pipe, &spd);
}
+/*
+ * Note that vmsplice only really supports true splicing _from_ user memory
+ * to a pipe, not the other way around. Splicing from user memory is a simple
+ * operation that can be supported without any funky alignment restrictions
+ * or nasty vm tricks. We simply map in the user memory and fill them into
+ * a pipe. The reverse isn't quite as easy, though. There are two possible
+ * solutions for that:
+ *
+ * - memcpy() the data internally, at which point we might as well just
+ * do a regular read() on the buffer anyway.
+ * - Lots of nasty vm tricks, that are neither fast nor flexible (it
+ * has restriction limitations on both ends of the pipe).
+ *
+ * Currently we punt and implement it as a normal copy, see pipe_to_user().
+ *
+ */
asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
unsigned long nr_segs, unsigned int flags)
{
@@ -1296,11 +1507,18 @@ asmlinkage long sys_vmsplice(int fd, const struct iovec __user *iov,
long error;
int fput;
+ if (unlikely(nr_segs > UIO_MAXIOV))
+ return -EINVAL;
+ else if (unlikely(!nr_segs))
+ return 0;
+
error = -EBADF;
file = fget_light(fd, &fput);
if (file) {
if (file->f_mode & FMODE_WRITE)
- error = do_vmsplice(file, iov, nr_segs, flags);
+ error = vmsplice_to_pipe(file, iov, nr_segs, flags);
+ else if (file->f_mode & FMODE_READ)
+ error = vmsplice_to_user(file, iov, nr_segs, flags);
fput_light(file, fput);
}
diff --git a/fs/sync.c b/fs/sync.c
index 2f97576355b..7cd005ea763 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -236,6 +236,14 @@ out:
return ret;
}
+/* It would be nice if people remember that not all the world's an i386
+ when they introduce new system calls */
+asmlinkage long sys_sync_file_range2(int fd, unsigned int flags,
+ loff_t offset, loff_t nbytes)
+{
+ return sys_sync_file_range(fd, offset, nbytes, flags);
+}
+
/*
* `endbyte' is inclusive
*/
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d3b9f5f07db..135353f8a29 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -20,29 +20,41 @@
#include "sysfs.h"
+struct bin_buffer {
+ struct mutex mutex;
+ void *buffer;
+ int mmapped;
+};
+
static int
fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
{
- struct bin_attribute * attr = to_bin_attr(dentry);
- struct kobject * kobj = to_kobj(dentry->d_parent);
+ struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+ struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+ struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ int rc;
+
+ /* need attr_sd for attr, its parent for kobj */
+ if (!sysfs_get_active_two(attr_sd))
+ return -ENODEV;
- if (!attr->read)
- return -EIO;
+ rc = -EIO;
+ if (attr->read)
+ rc = attr->read(kobj, attr, buffer, off, count);
- return attr->read(kobj, buffer, off, count);
+ sysfs_put_active_two(attr_sd);
+
+ return rc;
}
static ssize_t
-read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
+read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off)
{
- char *buffer = file->private_data;
+ struct bin_buffer *bb = file->private_data;
struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
- int ret;
-
- if (count > PAGE_SIZE)
- count = PAGE_SIZE;
+ int count = min_t(size_t, bytes, PAGE_SIZE);
if (size) {
if (offs > size)
@@ -51,43 +63,56 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
count = size - offs;
}
- ret = fill_read(dentry, buffer, offs, count);
- if (ret < 0)
- return ret;
- count = ret;
+ mutex_lock(&bb->mutex);
+
+ count = fill_read(dentry, bb->buffer, offs, count);
+ if (count < 0)
+ goto out_unlock;
- if (copy_to_user(userbuf, buffer, count))
- return -EFAULT;
+ if (copy_to_user(userbuf, bb->buffer, count)) {
+ count = -EFAULT;
+ goto out_unlock;
+ }
- pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
+ pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
*off = offs + count;
+ out_unlock:
+ mutex_unlock(&bb->mutex);
return count;
}
static int
flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
{
- struct bin_attribute *attr = to_bin_attr(dentry);
- struct kobject *kobj = to_kobj(dentry->d_parent);
+ struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+ struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+ struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ int rc;
+
+ /* need attr_sd for attr, its parent for kobj */
+ if (!sysfs_get_active_two(attr_sd))
+ return -ENODEV;
+
+ rc = -EIO;
+ if (attr->write)
+ rc = attr->write(kobj, attr, buffer, offset, count);
- if (!attr->write)
- return -EIO;
+ sysfs_put_active_two(attr_sd);
- return attr->write(kobj, buffer, offset, count);
+ return rc;
}
-static ssize_t write(struct file * file, const char __user * userbuf,
- size_t count, loff_t * off)
+static ssize_t write(struct file *file, const char __user *userbuf,
+ size_t bytes, loff_t *off)
{
- char *buffer = file->private_data;
+ struct bin_buffer *bb = file->private_data;
struct dentry *dentry = file->f_path.dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
+ int count = min_t(size_t, bytes, PAGE_SIZE);
- if (count > PAGE_SIZE)
- count = PAGE_SIZE;
if (size) {
if (offs > size)
return 0;
@@ -95,72 +120,100 @@ static ssize_t write(struct file * file, const char __user * userbuf,
count = size - offs;
}
- if (copy_from_user(buffer, userbuf, count))
- return -EFAULT;
+ mutex_lock(&bb->mutex);
- count = flush_write(dentry, buffer, offs, count);
+ if (copy_from_user(bb->buffer, userbuf, count)) {
+ count = -EFAULT;
+ goto out_unlock;
+ }
+
+ count = flush_write(dentry, bb->buffer, offs, count);
if (count > 0)
*off = offs + count;
+
+ out_unlock:
+ mutex_unlock(&bb->mutex);
return count;
}
static int mmap(struct file *file, struct vm_area_struct *vma)
{
- struct dentry *dentry = file->f_path.dentry;
- struct bin_attribute *attr = to_bin_attr(dentry);
- struct kobject *kobj = to_kobj(dentry->d_parent);
+ struct bin_buffer *bb = file->private_data;
+ struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+ struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+ struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+ int rc;
+
+ mutex_lock(&bb->mutex);
+
+ /* need attr_sd for attr, its parent for kobj */
+ if (!sysfs_get_active_two(attr_sd))
+ return -ENODEV;
- if (!attr->mmap)
- return -EINVAL;
+ rc = -EINVAL;
+ if (attr->mmap)
+ rc = attr->mmap(kobj, attr, vma);
- return attr->mmap(kobj, attr, vma);
+ if (rc == 0 && !bb->mmapped)
+ bb->mmapped = 1;
+ else
+ sysfs_put_active_two(attr_sd);
+
+ mutex_unlock(&bb->mutex);
+
+ return rc;
}
static int open(struct inode * inode, struct file * file)
{
- struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
- struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
- int error = -EINVAL;
-
- if (!kobj || !attr)
- goto Done;
+ struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+ struct bin_attribute *attr = attr_sd->s_elem.bin_attr.bin_attr;
+ struct bin_buffer *bb = NULL;
+ int error;
- /* Grab the module reference for this attribute if we have one */
- error = -ENODEV;
- if (!try_module_get(attr->attr.owner))
- goto Done;
+ /* need attr_sd for attr */
+ if (!sysfs_get_active(attr_sd))
+ return -ENODEV;
error = -EACCES;
if ((file->f_mode & FMODE_WRITE) && !(attr->write || attr->mmap))
- goto Error;
+ goto err_out;
if ((file->f_mode & FMODE_READ) && !(attr->read || attr->mmap))
- goto Error;
+ goto err_out;
error = -ENOMEM;
- file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!file->private_data)
- goto Error;
-
- error = 0;
- goto Done;
-
- Error:
- module_put(attr->attr.owner);
- Done:
- if (error)
- kobject_put(kobj);
+ bb = kzalloc(sizeof(*bb), GFP_KERNEL);
+ if (!bb)
+ goto err_out;
+
+ bb->buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!bb->buffer)
+ goto err_out;
+
+ mutex_init(&bb->mutex);
+ file->private_data = bb;
+
+ /* open succeeded, put active reference and pin attr_sd */
+ sysfs_put_active(attr_sd);
+ sysfs_get(attr_sd);
+ return 0;
+
+ err_out:
+ sysfs_put_active(attr_sd);
+ kfree(bb);
return error;
}
static int release(struct inode * inode, struct file * file)
{
- struct kobject * kobj = to_kobj(file->f_path.dentry->d_parent);
- struct bin_attribute * attr = to_bin_attr(file->f_path.dentry);
- u8 * buffer = file->private_data;
-
- kobject_put(kobj);
- module_put(attr->attr.owner);
- kfree(buffer);
+ struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+ struct bin_buffer *bb = file->private_data;
+
+ if (bb->mmapped)
+ sysfs_put_active_two(attr_sd);
+ sysfs_put(attr_sd);
+ kfree(bb->buffer);
+ kfree(bb);
return 0;
}
@@ -181,9 +234,9 @@ const struct file_operations bin_fops = {
int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
- BUG_ON(!kobj || !kobj->dentry || !attr);
+ BUG_ON(!kobj || !kobj->sd || !attr);
- return sysfs_add_file(kobj->dentry, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
+ return sysfs_add_file(kobj->sd, &attr->attr, SYSFS_KOBJ_BIN_ATTR);
}
@@ -195,7 +248,7 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
{
- if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) {
+ if (sysfs_hash_and_remove(kobj->sd, attr->attr.name) < 0) {
printk(KERN_ERR "%s: "
"bad dentry or inode or no such file: \"%s\"\n",
__FUNCTION__, attr->attr.name);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 85a668680f8..aee966c44aa 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -9,18 +9,346 @@
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/namei.h>
+#include <linux/idr.h>
+#include <linux/completion.h>
#include <asm/semaphore.h>
#include "sysfs.h"
-DECLARE_RWSEM(sysfs_rename_sem);
+DEFINE_MUTEX(sysfs_mutex);
+spinlock_t sysfs_assoc_lock = SPIN_LOCK_UNLOCKED;
+
+static spinlock_t sysfs_ino_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_IDA(sysfs_ino_ida);
+
+/**
+ * sysfs_link_sibling - link sysfs_dirent into sibling list
+ * @sd: sysfs_dirent of interest
+ *
+ * Link @sd into its sibling list which starts from
+ * sd->s_parent->s_children.
+ *
+ * Locking:
+ * mutex_lock(sysfs_mutex)
+ */
+void sysfs_link_sibling(struct sysfs_dirent *sd)
+{
+ struct sysfs_dirent *parent_sd = sd->s_parent;
+
+ BUG_ON(sd->s_sibling);
+ sd->s_sibling = parent_sd->s_children;
+ parent_sd->s_children = sd;
+}
+
+/**
+ * sysfs_unlink_sibling - unlink sysfs_dirent from sibling list
+ * @sd: sysfs_dirent of interest
+ *
+ * Unlink @sd from its sibling list which starts from
+ * sd->s_parent->s_children.
+ *
+ * Locking:
+ * mutex_lock(sysfs_mutex)
+ */
+void sysfs_unlink_sibling(struct sysfs_dirent *sd)
+{
+ struct sysfs_dirent **pos;
+
+ for (pos = &sd->s_parent->s_children; *pos; pos = &(*pos)->s_sibling) {
+ if (*pos == sd) {
+ *pos = sd->s_sibling;
+ sd->s_sibling = NULL;
+ break;
+ }
+ }
+}
+
+/**
+ * sysfs_get_dentry - get dentry for the given sysfs_dirent
+ * @sd: sysfs_dirent of interest
+ *
+ * Get dentry for @sd. Dentry is looked up if currently not
+ * present. This function climbs sysfs_dirent tree till it
+ * reaches a sysfs_dirent with valid dentry attached and descends
+ * down from there looking up dentry for each step.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * Pointer to found dentry on success, ERR_PTR() value on error.
+ */
+struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd)
+{
+ struct sysfs_dirent *cur;
+ struct dentry *parent_dentry, *dentry;
+ int i, depth;
+
+ /* Find the first parent which has valid s_dentry and get the
+ * dentry.
+ */
+ mutex_lock(&sysfs_mutex);
+ restart0:
+ spin_lock(&sysfs_assoc_lock);
+ restart1:
+ spin_lock(&dcache_lock);
+
+ dentry = NULL;
+ depth = 0;
+ cur = sd;
+ while (!cur->s_dentry || !cur->s_dentry->d_inode) {
+ if (cur->s_flags & SYSFS_FLAG_REMOVED) {
+ dentry = ERR_PTR(-ENOENT);
+ depth = 0;
+ break;
+ }
+ cur = cur->s_parent;
+ depth++;
+ }
+ if (!IS_ERR(dentry))
+ dentry = dget_locked(cur->s_dentry);
+
+ spin_unlock(&dcache_lock);
+ spin_unlock(&sysfs_assoc_lock);
+
+ /* from the found dentry, look up depth times */
+ while (depth--) {
+ /* find and get depth'th ancestor */
+ for (cur = sd, i = 0; cur && i < depth; i++)
+ cur = cur->s_parent;
+
+ /* This can happen if tree structure was modified due
+ * to move/rename. Restart.
+ */
+ if (i != depth) {
+ dput(dentry);
+ goto restart0;
+ }
+
+ sysfs_get(cur);
+
+ mutex_unlock(&sysfs_mutex);
+
+ /* look it up */
+ parent_dentry = dentry;
+ dentry = lookup_one_len_kern(cur->s_name, parent_dentry,
+ strlen(cur->s_name));
+ dput(parent_dentry);
+
+ if (IS_ERR(dentry)) {
+ sysfs_put(cur);
+ return dentry;
+ }
+
+ mutex_lock(&sysfs_mutex);
+ spin_lock(&sysfs_assoc_lock);
+
+ /* This, again, can happen if tree structure has
+ * changed and we looked up the wrong thing. Restart.
+ */
+ if (cur->s_dentry != dentry) {
+ dput(dentry);
+ sysfs_put(cur);
+ goto restart1;
+ }
+
+ spin_unlock(&sysfs_assoc_lock);
+
+ sysfs_put(cur);
+ }
+
+ mutex_unlock(&sysfs_mutex);
+ return dentry;
+}
+
+/**
+ * sysfs_get_active - get an active reference to sysfs_dirent
+ * @sd: sysfs_dirent to get an active reference to
+ *
+ * Get an active reference of @sd. This function is noop if @sd
+ * is NULL.
+ *
+ * RETURNS:
+ * Pointer to @sd on success, NULL on failure.
+ */
+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
+{
+ if (unlikely(!sd))
+ return NULL;
+
+ while (1) {
+ int v, t;
+
+ v = atomic_read(&sd->s_active);
+ if (unlikely(v < 0))
+ return NULL;
+
+ t = atomic_cmpxchg(&sd->s_active, v, v + 1);
+ if (likely(t == v))
+ return sd;
+ if (t < 0)
+ return NULL;
+
+ cpu_relax();
+ }
+}
+
+/**
+ * sysfs_put_active - put an active reference to sysfs_dirent
+ * @sd: sysfs_dirent to put an active reference to
+ *
+ * Put an active reference to @sd. This function is noop if @sd
+ * is NULL.
+ */
+void sysfs_put_active(struct sysfs_dirent *sd)
+{
+ struct completion *cmpl;
+ int v;
+
+ if (unlikely(!sd))
+ return;
+
+ v = atomic_dec_return(&sd->s_active);
+ if (likely(v != SD_DEACTIVATED_BIAS))
+ return;
+
+ /* atomic_dec_return() is a mb(), we'll always see the updated
+ * sd->s_sibling.
+ */
+ cmpl = (void *)sd->s_sibling;
+ complete(cmpl);
+}
+
+/**
+ * sysfs_get_active_two - get active references to sysfs_dirent and parent
+ * @sd: sysfs_dirent of interest
+ *
+ * Get active reference to @sd and its parent. Parent's active
+ * reference is grabbed first. This function is noop if @sd is
+ * NULL.
+ *
+ * RETURNS:
+ * Pointer to @sd on success, NULL on failure.
+ */
+struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
+{
+ if (sd) {
+ if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
+ return NULL;
+ if (unlikely(!sysfs_get_active(sd))) {
+ sysfs_put_active(sd->s_parent);
+ return NULL;
+ }
+ }
+ return sd;
+}
+
+/**
+ * sysfs_put_active_two - put active references to sysfs_dirent and parent
+ * @sd: sysfs_dirent of interest
+ *
+ * Put active references to @sd and its parent. This function is
+ * noop if @sd is NULL.
+ */
+void sysfs_put_active_two(struct sysfs_dirent *sd)
+{
+ if (sd) {
+ sysfs_put_active(sd);
+ sysfs_put_active(sd->s_parent);
+ }
+}
+
+/**
+ * sysfs_deactivate - deactivate sysfs_dirent
+ * @sd: sysfs_dirent to deactivate
+ *
+ * Deny new active references and drain existing ones.
+ */
+static void sysfs_deactivate(struct sysfs_dirent *sd)
+{
+ DECLARE_COMPLETION_ONSTACK(wait);
+ int v;
+
+ BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
+ sd->s_sibling = (void *)&wait;
+
+ /* atomic_add_return() is a mb(), put_active() will always see
+ * the updated sd->s_sibling.
+ */
+ v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
+
+ if (v != SD_DEACTIVATED_BIAS)
+ wait_for_completion(&wait);
+
+ sd->s_sibling = NULL;
+}
+
+static int sysfs_alloc_ino(ino_t *pino)
+{
+ int ino, rc;
+
+ retry:
+ spin_lock(&sysfs_ino_lock);
+ rc = ida_get_new_above(&sysfs_ino_ida, 2, &ino);
+ spin_unlock(&sysfs_ino_lock);
+
+ if (rc == -EAGAIN) {
+ if (ida_pre_get(&sysfs_ino_ida, GFP_KERNEL))
+ goto retry;
+ rc = -ENOMEM;
+ }
+
+ *pino = ino;
+ return rc;
+}
+
+static void sysfs_free_ino(ino_t ino)
+{
+ spin_lock(&sysfs_ino_lock);
+ ida_remove(&sysfs_ino_ida, ino);
+ spin_unlock(&sysfs_ino_lock);
+}
+
+void release_sysfs_dirent(struct sysfs_dirent * sd)
+{
+ struct sysfs_dirent *parent_sd;
+
+ repeat:
+ /* Moving/renaming is always done while holding reference.
+ * sd->s_parent won't change beneath us.
+ */
+ parent_sd = sd->s_parent;
+
+ if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
+ sysfs_put(sd->s_elem.symlink.target_sd);
+ if (sysfs_type(sd) & SYSFS_COPY_NAME)
+ kfree(sd->s_name);
+ kfree(sd->s_iattr);
+ sysfs_free_ino(sd->s_ino);
+ kmem_cache_free(sysfs_dir_cachep, sd);
+
+ sd = parent_sd;
+ if (sd && atomic_dec_and_test(&sd->s_count))
+ goto repeat;
+}
static void sysfs_d_iput(struct dentry * dentry, struct inode * inode)
{
struct sysfs_dirent * sd = dentry->d_fsdata;
if (sd) {
- BUG_ON(sd->s_dentry != dentry);
- sd->s_dentry = NULL;
+ /* sd->s_dentry is protected with sysfs_assoc_lock.
+ * This allows sysfs_drop_dentry() to dereference it.
+ */
+ spin_lock(&sysfs_assoc_lock);
+
+ /* The dentry might have been deleted or another
+ * lookup could have happened updating sd->s_dentry to
+ * point the new dentry. Ignore if it isn't pointing
+ * to this dentry.
+ */
+ if (sd->s_dentry == dentry)
+ sd->s_dentry = NULL;
+ spin_unlock(&sysfs_assoc_lock);
sysfs_put(sd);
}
iput(inode);
@@ -30,245 +358,402 @@ static struct dentry_operations sysfs_dentry_ops = {
.d_iput = sysfs_d_iput,
};
-/*
- * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent
- */
-static struct sysfs_dirent * __sysfs_new_dirent(void * element)
+struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
{
- struct sysfs_dirent * sd;
+ char *dup_name = NULL;
+ struct sysfs_dirent *sd = NULL;
+
+ if (type & SYSFS_COPY_NAME) {
+ name = dup_name = kstrdup(name, GFP_KERNEL);
+ if (!name)
+ goto err_out;
+ }
sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
if (!sd)
- return NULL;
+ goto err_out;
+
+ if (sysfs_alloc_ino(&sd->s_ino))
+ goto err_out;
atomic_set(&sd->s_count, 1);
+ atomic_set(&sd->s_active, 0);
atomic_set(&sd->s_event, 1);
- INIT_LIST_HEAD(&sd->s_children);
- INIT_LIST_HEAD(&sd->s_sibling);
- sd->s_element = element;
+
+ sd->s_name = name;
+ sd->s_mode = mode;
+ sd->s_flags = type;
return sd;
+
+ err_out:
+ kfree(dup_name);
+ kmem_cache_free(sysfs_dir_cachep, sd);
+ return NULL;
}
-static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd,
- struct sysfs_dirent *sd)
+/**
+ * sysfs_attach_dentry - associate sysfs_dirent with dentry
+ * @sd: target sysfs_dirent
+ * @dentry: dentry to associate
+ *
+ * Associate @sd with @dentry. This is protected by
+ * sysfs_assoc_lock to avoid race with sysfs_d_iput().
+ *
+ * LOCKING:
+ * mutex_lock(sysfs_mutex)
+ */
+static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry)
{
- if (sd)
- list_add(&sd->s_sibling, &parent_sd->s_children);
+ dentry->d_op = &sysfs_dentry_ops;
+ dentry->d_fsdata = sysfs_get(sd);
+
+ /* protect sd->s_dentry against sysfs_d_iput */
+ spin_lock(&sysfs_assoc_lock);
+ sd->s_dentry = dentry;
+ spin_unlock(&sysfs_assoc_lock);
+
+ d_rehash(dentry);
}
-static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd,
- void * element)
+static int sysfs_ilookup_test(struct inode *inode, void *arg)
{
- struct sysfs_dirent *sd;
- sd = __sysfs_new_dirent(element);
- __sysfs_list_dirent(parent_sd, sd);
- return sd;
+ struct sysfs_dirent *sd = arg;
+ return inode->i_ino == sd->s_ino;
}
-/*
+/**
+ * sysfs_addrm_start - prepare for sysfs_dirent add/remove
+ * @acxt: pointer to sysfs_addrm_cxt to be used
+ * @parent_sd: parent sysfs_dirent
*
- * Return -EEXIST if there is already a sysfs element with the same name for
- * the same parent.
+ * This function is called when the caller is about to add or
+ * remove sysfs_dirent under @parent_sd. This function acquires
+ * sysfs_mutex, grabs inode for @parent_sd if available and lock
+ * i_mutex of it. @acxt is used to keep and pass context to
+ * other addrm functions.
*
- * called with parent inode's i_mutex held
+ * LOCKING:
+ * Kernel thread context (may sleep). sysfs_mutex is locked on
+ * return. i_mutex of parent inode is locked on return if
+ * available.
*/
-int sysfs_dirent_exist(struct sysfs_dirent *parent_sd,
- const unsigned char *new)
+void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+ struct sysfs_dirent *parent_sd)
{
- struct sysfs_dirent * sd;
+ struct inode *inode;
- list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
- if (sd->s_element) {
- const unsigned char *existing = sysfs_get_name(sd);
- if (strcmp(existing, new))
- continue;
- else
- return -EEXIST;
- }
- }
+ memset(acxt, 0, sizeof(*acxt));
+ acxt->parent_sd = parent_sd;
- return 0;
+ /* Lookup parent inode. inode initialization and I_NEW
+ * clearing are protected by sysfs_mutex. By grabbing it and
+ * looking up with _nowait variant, inode state can be
+ * determined reliably.
+ */
+ mutex_lock(&sysfs_mutex);
+
+ inode = ilookup5_nowait(sysfs_sb, parent_sd->s_ino, sysfs_ilookup_test,
+ parent_sd);
+
+ if (inode && !(inode->i_state & I_NEW)) {
+ /* parent inode available */
+ acxt->parent_inode = inode;
+
+ /* sysfs_mutex is below i_mutex in lock hierarchy.
+ * First, trylock i_mutex. If fails, unlock
+ * sysfs_mutex and lock them in order.
+ */
+ if (!mutex_trylock(&inode->i_mutex)) {
+ mutex_unlock(&sysfs_mutex);
+ mutex_lock(&inode->i_mutex);
+ mutex_lock(&sysfs_mutex);
+ }
+ } else
+ iput(inode);
}
+/**
+ * sysfs_add_one - add sysfs_dirent to parent
+ * @acxt: addrm context to use
+ * @sd: sysfs_dirent to be added
+ *
+ * Get @acxt->parent_sd and set sd->s_parent to it and increment
+ * nlink of parent inode if @sd is a directory. @sd is NOT
+ * linked into the children list of the parent. The caller
+ * should invoke sysfs_link_sibling() after this function
+ * completes if @sd needs to be on the children list.
+ *
+ * This function should be called between calls to
+ * sysfs_addrm_start() and sysfs_addrm_finish() and should be
+ * passed the same @acxt as passed to sysfs_addrm_start().
+ *
+ * LOCKING:
+ * Determined by sysfs_addrm_start().
+ */
+void sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
+{
+ sd->s_parent = sysfs_get(acxt->parent_sd);
+
+ if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+ inc_nlink(acxt->parent_inode);
+
+ acxt->cnt++;
+}
-static struct sysfs_dirent *
-__sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type)
+/**
+ * sysfs_remove_one - remove sysfs_dirent from parent
+ * @acxt: addrm context to use
+ * @sd: sysfs_dirent to be added
+ *
+ * Mark @sd removed and drop nlink of parent inode if @sd is a
+ * directory. @sd is NOT unlinked from the children list of the
+ * parent. The caller is repsonsible for removing @sd from the
+ * children list before calling this function.
+ *
+ * This function should be called between calls to
+ * sysfs_addrm_start() and sysfs_addrm_finish() and should be
+ * passed the same @acxt as passed to sysfs_addrm_start().
+ *
+ * LOCKING:
+ * Determined by sysfs_addrm_start().
+ */
+void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
{
- struct sysfs_dirent * sd;
+ BUG_ON(sd->s_sibling || (sd->s_flags & SYSFS_FLAG_REMOVED));
- sd = __sysfs_new_dirent(element);
- if (!sd)
- goto out;
+ sd->s_flags |= SYSFS_FLAG_REMOVED;
+ sd->s_sibling = acxt->removed;
+ acxt->removed = sd;
- sd->s_mode = mode;
- sd->s_type = type;
- sd->s_dentry = dentry;
- if (dentry) {
- dentry->d_fsdata = sysfs_get(sd);
- dentry->d_op = &sysfs_dentry_ops;
- }
+ if (sysfs_type(sd) == SYSFS_DIR && acxt->parent_inode)
+ drop_nlink(acxt->parent_inode);
-out:
- return sd;
+ acxt->cnt++;
}
-int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry,
- void * element, umode_t mode, int type)
+/**
+ * sysfs_drop_dentry - drop dentry for the specified sysfs_dirent
+ * @sd: target sysfs_dirent
+ *
+ * Drop dentry for @sd. @sd must have been unlinked from its
+ * parent on entry to this function such that it can't be looked
+ * up anymore.
+ *
+ * @sd->s_dentry which is protected with sysfs_assoc_lock points
+ * to the currently associated dentry but we're not holding a
+ * reference to it and racing with dput(). Grab dcache_lock and
+ * verify dentry before dropping it. If @sd->s_dentry is NULL or
+ * dput() beats us, no need to bother.
+ */
+static void sysfs_drop_dentry(struct sysfs_dirent *sd)
{
- struct sysfs_dirent *sd;
+ struct dentry *dentry = NULL;
+ struct inode *inode;
+
+ /* We're not holding a reference to ->s_dentry dentry but the
+ * field will stay valid as long as sysfs_assoc_lock is held.
+ */
+ spin_lock(&sysfs_assoc_lock);
+ spin_lock(&dcache_lock);
+
+ /* drop dentry if it's there and dput() didn't kill it yet */
+ if (sd->s_dentry && sd->s_dentry->d_inode) {
+ dentry = dget_locked(sd->s_dentry);
+ spin_lock(&dentry->d_lock);
+ __d_drop(dentry);
+ spin_unlock(&dentry->d_lock);
+ }
- sd = __sysfs_make_dirent(dentry, element, mode, type);
- __sysfs_list_dirent(parent_sd, sd);
+ spin_unlock(&dcache_lock);
+ spin_unlock(&sysfs_assoc_lock);
- return sd ? 0 : -ENOMEM;
+ /* dentries for shadowed inodes are pinned, unpin */
+ if (dentry && sysfs_is_shadowed_inode(dentry->d_inode))
+ dput(dentry);
+ dput(dentry);
+
+ /* adjust nlink and update timestamp */
+ inode = ilookup(sysfs_sb, sd->s_ino);
+ if (inode) {
+ mutex_lock(&inode->i_mutex);
+
+ inode->i_ctime = CURRENT_TIME;
+ drop_nlink(inode);
+ if (sysfs_type(sd) == SYSFS_DIR)
+ drop_nlink(inode);
+
+ mutex_unlock(&inode->i_mutex);
+ iput(inode);
+ }
}
-static int init_dir(struct inode * inode)
+/**
+ * sysfs_addrm_finish - finish up sysfs_dirent add/remove
+ * @acxt: addrm context to finish up
+ *
+ * Finish up sysfs_dirent add/remove. Resources acquired by
+ * sysfs_addrm_start() are released and removed sysfs_dirents are
+ * cleaned up. Timestamps on the parent inode are updated.
+ *
+ * LOCKING:
+ * All mutexes acquired by sysfs_addrm_start() are released.
+ *
+ * RETURNS:
+ * Number of added/removed sysfs_dirents since sysfs_addrm_start().
+ */
+int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
{
- inode->i_op = &sysfs_dir_inode_operations;
- inode->i_fop = &sysfs_dir_operations;
+ /* release resources acquired by sysfs_addrm_start() */
+ mutex_unlock(&sysfs_mutex);
+ if (acxt->parent_inode) {
+ struct inode *inode = acxt->parent_inode;
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
- inc_nlink(inode);
- return 0;
+ /* if added/removed, update timestamps on the parent */
+ if (acxt->cnt)
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+ mutex_unlock(&inode->i_mutex);
+ iput(inode);
+ }
+
+ /* kill removed sysfs_dirents */
+ while (acxt->removed) {
+ struct sysfs_dirent *sd = acxt->removed;
+
+ acxt->removed = sd->s_sibling;
+ sd->s_sibling = NULL;
+
+ sysfs_drop_dentry(sd);
+ sysfs_deactivate(sd);
+ sysfs_put(sd);
+ }
+
+ return acxt->cnt;
}
-static int init_file(struct inode * inode)
+/**
+ * sysfs_find_dirent - find sysfs_dirent with the given name
+ * @parent_sd: sysfs_dirent to search under
+ * @name: name to look for
+ *
+ * Look for sysfs_dirent with name @name under @parent_sd.
+ *
+ * LOCKING:
+ * mutex_lock(sysfs_mutex)
+ *
+ * RETURNS:
+ * Pointer to sysfs_dirent if found, NULL if not.
+ */
+struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+ const unsigned char *name)
{
- inode->i_size = PAGE_SIZE;
- inode->i_fop = &sysfs_file_operations;
- return 0;
+ struct sysfs_dirent *sd;
+
+ for (sd = parent_sd->s_children; sd; sd = sd->s_sibling)
+ if (sysfs_type(sd) && !strcmp(sd->s_name, name))
+ return sd;
+ return NULL;
}
-static int init_symlink(struct inode * inode)
+/**
+ * sysfs_get_dirent - find and get sysfs_dirent with the given name
+ * @parent_sd: sysfs_dirent to search under
+ * @name: name to look for
+ *
+ * Look for sysfs_dirent with name @name under @parent_sd and get
+ * it if found.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep). Grabs sysfs_mutex.
+ *
+ * RETURNS:
+ * Pointer to sysfs_dirent if found, NULL if not.
+ */
+struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+ const unsigned char *name)
{
- inode->i_op = &sysfs_symlink_inode_operations;
- return 0;
+ struct sysfs_dirent *sd;
+
+ mutex_lock(&sysfs_mutex);
+ sd = sysfs_find_dirent(parent_sd, name);
+ sysfs_get(sd);
+ mutex_unlock(&sysfs_mutex);
+
+ return sd;
}
-static int create_dir(struct kobject * k, struct dentry * p,
- const char * n, struct dentry ** d)
+static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
+ const char *name, struct sysfs_dirent **p_sd)
{
- int error;
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
+ struct sysfs_addrm_cxt acxt;
+ struct sysfs_dirent *sd;
- mutex_lock(&p->d_inode->i_mutex);
- *d = lookup_one_len(n, p, strlen(n));
- if (!IS_ERR(*d)) {
- if (sysfs_dirent_exist(p->d_fsdata, n))
- error = -EEXIST;
- else
- error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
- SYSFS_DIR);
- if (!error) {
- error = sysfs_create(*d, mode, init_dir);
- if (!error) {
- inc_nlink(p->d_inode);
- (*d)->d_op = &sysfs_dentry_ops;
- d_rehash(*d);
- }
- }
- if (error && (error != -EEXIST)) {
- struct sysfs_dirent *sd = (*d)->d_fsdata;
- if (sd) {
- list_del_init(&sd->s_sibling);
- sysfs_put(sd);
- }
- d_drop(*d);
- }
- dput(*d);
- } else
- error = PTR_ERR(*d);
- mutex_unlock(&p->d_inode->i_mutex);
- return error;
-}
+ /* allocate */
+ sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
+ if (!sd)
+ return -ENOMEM;
+ sd->s_elem.dir.kobj = kobj;
+ /* link in */
+ sysfs_addrm_start(&acxt, parent_sd);
+ if (!sysfs_find_dirent(parent_sd, name)) {
+ sysfs_add_one(&acxt, sd);
+ sysfs_link_sibling(sd);
+ }
+ if (sysfs_addrm_finish(&acxt)) {
+ *p_sd = sd;
+ return 0;
+ }
-int sysfs_create_subdir(struct kobject * k, const char * n, struct dentry ** d)
+ sysfs_put(sd);
+ return -EEXIST;
+}
+
+int sysfs_create_subdir(struct kobject *kobj, const char *name,
+ struct sysfs_dirent **p_sd)
{
- return create_dir(k,k->dentry,n,d);
+ return create_dir(kobj, kobj->sd, name, p_sd);
}
/**
* sysfs_create_dir - create a directory for an object.
* @kobj: object we're creating directory for.
- * @shadow_parent: parent parent object.
+ * @shadow_parent: parent object.
*/
-
-int sysfs_create_dir(struct kobject * kobj, struct dentry *shadow_parent)
+int sysfs_create_dir(struct kobject *kobj,
+ struct sysfs_dirent *shadow_parent_sd)
{
- struct dentry * dentry = NULL;
- struct dentry * parent;
+ struct sysfs_dirent *parent_sd, *sd;
int error = 0;
BUG_ON(!kobj);
- if (shadow_parent)
- parent = shadow_parent;
+ if (shadow_parent_sd)
+ parent_sd = shadow_parent_sd;
else if (kobj->parent)
- parent = kobj->parent->dentry;
+ parent_sd = kobj->parent->sd;
else if (sysfs_mount && sysfs_mount->mnt_sb)
- parent = sysfs_mount->mnt_sb->s_root;
+ parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
else
return -EFAULT;
- error = create_dir(kobj,parent,kobject_name(kobj),&dentry);
+ error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);
if (!error)
- kobj->dentry = dentry;
+ kobj->sd = sd;
return error;
}
-/* attaches attribute's sysfs_dirent to the dentry corresponding to the
- * attribute file
- */
-static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
+static int sysfs_count_nlink(struct sysfs_dirent *sd)
{
- struct attribute * attr = NULL;
- struct bin_attribute * bin_attr = NULL;
- int (* init) (struct inode *) = NULL;
- int error = 0;
+ struct sysfs_dirent *child;
+ int nr = 0;
- if (sd->s_type & SYSFS_KOBJ_BIN_ATTR) {
- bin_attr = sd->s_element;
- attr = &bin_attr->attr;
- } else {
- attr = sd->s_element;
- init = init_file;
- }
-
- dentry->d_fsdata = sysfs_get(sd);
- sd->s_dentry = dentry;
- error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
- if (error) {
- sysfs_put(sd);
- return error;
- }
-
- if (bin_attr) {
- dentry->d_inode->i_size = bin_attr->size;
- dentry->d_inode->i_fop = &bin_fops;
- }
- dentry->d_op = &sysfs_dentry_ops;
- d_rehash(dentry);
-
- return 0;
-}
-
-static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
-{
- int err = 0;
-
- dentry->d_fsdata = sysfs_get(sd);
- sd->s_dentry = dentry;
- err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
- if (!err) {
- dentry->d_op = &sysfs_dentry_ops;
- d_rehash(dentry);
- } else
- sysfs_put(sd);
-
- return err;
+ for (child = sd->s_children; child; child = child->s_sibling)
+ if (sysfs_type(child) == SYSFS_DIR)
+ nr++;
+ return nr + 2;
}
static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
@@ -276,24 +761,60 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
{
struct sysfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
struct sysfs_dirent * sd;
- int err = 0;
+ struct bin_attribute *bin_attr;
+ struct inode *inode;
+ int found = 0;
- list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
- if (sd->s_type & SYSFS_NOT_PINNED) {
- const unsigned char * name = sysfs_get_name(sd);
+ for (sd = parent_sd->s_children; sd; sd = sd->s_sibling) {
+ if (sysfs_type(sd) &&
+ !strcmp(sd->s_name, dentry->d_name.name)) {
+ found = 1;
+ break;
+ }
+ }
+
+ /* no such entry */
+ if (!found)
+ return NULL;
- if (strcmp(name, dentry->d_name.name))
- continue;
+ /* attach dentry and inode */
+ inode = sysfs_get_inode(sd);
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
- if (sd->s_type & SYSFS_KOBJ_LINK)
- err = sysfs_attach_link(sd, dentry);
- else
- err = sysfs_attach_attr(sd, dentry);
+ mutex_lock(&sysfs_mutex);
+
+ if (inode->i_state & I_NEW) {
+ /* initialize inode according to type */
+ switch (sysfs_type(sd)) {
+ case SYSFS_DIR:
+ inode->i_op = &sysfs_dir_inode_operations;
+ inode->i_fop = &sysfs_dir_operations;
+ inode->i_nlink = sysfs_count_nlink(sd);
break;
+ case SYSFS_KOBJ_ATTR:
+ inode->i_size = PAGE_SIZE;
+ inode->i_fop = &sysfs_file_operations;
+ break;
+ case SYSFS_KOBJ_BIN_ATTR:
+ bin_attr = sd->s_elem.bin_attr.bin_attr;
+ inode->i_size = bin_attr->size;
+ inode->i_fop = &bin_fops;
+ break;
+ case SYSFS_KOBJ_LINK:
+ inode->i_op = &sysfs_symlink_inode_operations;
+ break;
+ default:
+ BUG();
}
}
- return ERR_PTR(err);
+ sysfs_instantiate(dentry, inode);
+ sysfs_attach_dentry(sd, dentry);
+
+ mutex_unlock(&sysfs_mutex);
+
+ return NULL;
}
const struct inode_operations sysfs_dir_inode_operations = {
@@ -301,58 +822,46 @@ const struct inode_operations sysfs_dir_inode_operations = {
.setattr = sysfs_setattr,
};
-static void remove_dir(struct dentry * d)
+static void remove_dir(struct sysfs_dirent *sd)
{
- struct dentry * parent = dget(d->d_parent);
- struct sysfs_dirent * sd;
-
- mutex_lock(&parent->d_inode->i_mutex);
- d_delete(d);
- sd = d->d_fsdata;
- list_del_init(&sd->s_sibling);
- sysfs_put(sd);
- if (d->d_inode)
- simple_rmdir(parent->d_inode,d);
+ struct sysfs_addrm_cxt acxt;
- pr_debug(" o %s removing done (%d)\n",d->d_name.name,
- atomic_read(&d->d_count));
-
- mutex_unlock(&parent->d_inode->i_mutex);
- dput(parent);
+ sysfs_addrm_start(&acxt, sd->s_parent);
+ sysfs_unlink_sibling(sd);
+ sysfs_remove_one(&acxt, sd);
+ sysfs_addrm_finish(&acxt);
}
-void sysfs_remove_subdir(struct dentry * d)
+void sysfs_remove_subdir(struct sysfs_dirent *sd)
{
- remove_dir(d);
+ remove_dir(sd);
}
-static void __sysfs_remove_dir(struct dentry *dentry)
+static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
{
- struct sysfs_dirent * parent_sd;
- struct sysfs_dirent * sd, * tmp;
+ struct sysfs_addrm_cxt acxt;
+ struct sysfs_dirent **pos;
- dget(dentry);
- if (!dentry)
+ if (!dir_sd)
return;
- pr_debug("sysfs %s: removing dir\n",dentry->d_name.name);
- mutex_lock(&dentry->d_inode->i_mutex);
- parent_sd = dentry->d_fsdata;
- list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
- if (!sd->s_element || !(sd->s_type & SYSFS_NOT_PINNED))
- continue;
- list_del_init(&sd->s_sibling);
- sysfs_drop_dentry(sd, dentry);
- sysfs_put(sd);
+ pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
+ sysfs_addrm_start(&acxt, dir_sd);
+ pos = &dir_sd->s_children;
+ while (*pos) {
+ struct sysfs_dirent *sd = *pos;
+
+ if (sysfs_type(sd) && sysfs_type(sd) != SYSFS_DIR) {
+ *pos = sd->s_sibling;
+ sd->s_sibling = NULL;
+ sysfs_remove_one(&acxt, sd);
+ } else
+ pos = &(*pos)->s_sibling;
}
- mutex_unlock(&dentry->d_inode->i_mutex);
+ sysfs_addrm_finish(&acxt);
- remove_dir(dentry);
- /**
- * Drop reference from dget() on entrance.
- */
- dput(dentry);
+ remove_dir(dir_sd);
}
/**
@@ -366,102 +875,166 @@ static void __sysfs_remove_dir(struct dentry *dentry)
void sysfs_remove_dir(struct kobject * kobj)
{
- __sysfs_remove_dir(kobj->dentry);
- kobj->dentry = NULL;
+ struct sysfs_dirent *sd = kobj->sd;
+
+ spin_lock(&sysfs_assoc_lock);
+ kobj->sd = NULL;
+ spin_unlock(&sysfs_assoc_lock);
+
+ __sysfs_remove_dir(sd);
}
-int sysfs_rename_dir(struct kobject * kobj, struct dentry *new_parent,
+int sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
const char *new_name)
{
- int error = 0;
- struct dentry * new_dentry;
+ struct sysfs_dirent *sd = kobj->sd;
+ struct dentry *new_parent = NULL;
+ struct dentry *old_dentry = NULL, *new_dentry = NULL;
+ const char *dup_name = NULL;
+ int error;
- if (!new_parent)
- return -EFAULT;
+ /* get dentries */
+ old_dentry = sysfs_get_dentry(sd);
+ if (IS_ERR(old_dentry)) {
+ error = PTR_ERR(old_dentry);
+ goto out_dput;
+ }
+
+ new_parent = sysfs_get_dentry(new_parent_sd);
+ if (IS_ERR(new_parent)) {
+ error = PTR_ERR(new_parent);
+ goto out_dput;
+ }
- down_write(&sysfs_rename_sem);
+ /* lock new_parent and get dentry for new name */
mutex_lock(&new_parent->d_inode->i_mutex);
new_dentry = lookup_one_len(new_name, new_parent, strlen(new_name));
- if (!IS_ERR(new_dentry)) {
- /* By allowing two different directories with the
- * same d_parent we allow this routine to move
- * between different shadows of the same directory
- */
- if (kobj->dentry->d_parent->d_inode != new_parent->d_inode)
- return -EINVAL;
- else if (new_dentry->d_parent->d_inode != new_parent->d_inode)
- error = -EINVAL;
- else if (new_dentry == kobj->dentry)
- error = -EINVAL;
- else if (!new_dentry->d_inode) {
- error = kobject_set_name(kobj, "%s", new_name);
- if (!error) {
- struct sysfs_dirent *sd, *parent_sd;
-
- d_add(new_dentry, NULL);
- d_move(kobj->dentry, new_dentry);
-
- sd = kobj->dentry->d_fsdata;
- parent_sd = new_parent->d_fsdata;
-
- list_del_init(&sd->s_sibling);
- list_add(&sd->s_sibling, &parent_sd->s_children);
- }
- else
- d_drop(new_dentry);
- } else
- error = -EEXIST;
- dput(new_dentry);
+ if (IS_ERR(new_dentry)) {
+ error = PTR_ERR(new_dentry);
+ goto out_unlock;
}
- mutex_unlock(&new_parent->d_inode->i_mutex);
- up_write(&sysfs_rename_sem);
+ /* By allowing two different directories with the same
+ * d_parent we allow this routine to move between different
+ * shadows of the same directory
+ */
+ error = -EINVAL;
+ if (old_dentry->d_parent->d_inode != new_parent->d_inode ||
+ new_dentry->d_parent->d_inode != new_parent->d_inode ||
+ old_dentry == new_dentry)
+ goto out_unlock;
+
+ error = -EEXIST;
+ if (new_dentry->d_inode)
+ goto out_unlock;
+
+ /* rename kobject and sysfs_dirent */
+ error = -ENOMEM;
+ new_name = dup_name = kstrdup(new_name, GFP_KERNEL);
+ if (!new_name)
+ goto out_drop;
+
+ error = kobject_set_name(kobj, "%s", new_name);
+ if (error)
+ goto out_drop;
+
+ dup_name = sd->s_name;
+ sd->s_name = new_name;
+
+ /* move under the new parent */
+ d_add(new_dentry, NULL);
+ d_move(sd->s_dentry, new_dentry);
+
+ mutex_lock(&sysfs_mutex);
+
+ sysfs_unlink_sibling(sd);
+ sysfs_get(new_parent_sd);
+ sysfs_put(sd->s_parent);
+ sd->s_parent = new_parent_sd;
+ sysfs_link_sibling(sd);
+
+ mutex_unlock(&sysfs_mutex);
+
+ error = 0;
+ goto out_unlock;
+
+ out_drop:
+ d_drop(new_dentry);
+ out_unlock:
+ mutex_unlock(&new_parent->d_inode->i_mutex);
+ out_dput:
+ kfree(dup_name);
+ dput(new_parent);
+ dput(old_dentry);
+ dput(new_dentry);
return error;
}
-int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
+int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent_kobj)
{
- struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
- struct sysfs_dirent *new_parent_sd, *sd;
+ struct sysfs_dirent *sd = kobj->sd;
+ struct sysfs_dirent *new_parent_sd;
+ struct dentry *old_parent, *new_parent = NULL;
+ struct dentry *old_dentry = NULL, *new_dentry = NULL;
int error;
- old_parent_dentry = kobj->parent ?
- kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
- new_parent_dentry = new_parent ?
- new_parent->dentry : sysfs_mount->mnt_sb->s_root;
+ BUG_ON(!sd->s_parent);
+ new_parent_sd = new_parent_kobj->sd ? new_parent_kobj->sd : &sysfs_root;
+
+ /* get dentries */
+ old_dentry = sysfs_get_dentry(sd);
+ if (IS_ERR(old_dentry)) {
+ error = PTR_ERR(old_dentry);
+ goto out_dput;
+ }
+ old_parent = sd->s_parent->s_dentry;
+
+ new_parent = sysfs_get_dentry(new_parent_sd);
+ if (IS_ERR(new_parent)) {
+ error = PTR_ERR(new_parent);
+ goto out_dput;
+ }
- if (old_parent_dentry->d_inode == new_parent_dentry->d_inode)
- return 0; /* nothing to move */
+ if (old_parent->d_inode == new_parent->d_inode) {
+ error = 0;
+ goto out_dput; /* nothing to move */
+ }
again:
- mutex_lock(&old_parent_dentry->d_inode->i_mutex);
- if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
- mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+ mutex_lock(&old_parent->d_inode->i_mutex);
+ if (!mutex_trylock(&new_parent->d_inode->i_mutex)) {
+ mutex_unlock(&old_parent->d_inode->i_mutex);
goto again;
}
- new_parent_sd = new_parent_dentry->d_fsdata;
- sd = kobj->dentry->d_fsdata;
-
- new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
- strlen(kobj->name));
+ new_dentry = lookup_one_len(kobj->name, new_parent, strlen(kobj->name));
if (IS_ERR(new_dentry)) {
error = PTR_ERR(new_dentry);
- goto out;
+ goto out_unlock;
} else
error = 0;
d_add(new_dentry, NULL);
- d_move(kobj->dentry, new_dentry);
+ d_move(sd->s_dentry, new_dentry);
dput(new_dentry);
/* Remove from old parent's list and insert into new parent's list. */
- list_del_init(&sd->s_sibling);
- list_add(&sd->s_sibling, &new_parent_sd->s_children);
+ mutex_lock(&sysfs_mutex);
-out:
- mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
- mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
+ sysfs_unlink_sibling(sd);
+ sysfs_get(new_parent_sd);
+ sysfs_put(sd->s_parent);
+ sd->s_parent = new_parent_sd;
+ sysfs_link_sibling(sd);
+ mutex_unlock(&sysfs_mutex);
+
+ out_unlock:
+ mutex_unlock(&new_parent->d_inode->i_mutex);
+ mutex_unlock(&old_parent->d_inode->i_mutex);
+ out_dput:
+ dput(new_parent);
+ dput(old_dentry);
+ dput(new_dentry);
return error;
}
@@ -469,23 +1042,27 @@ static int sysfs_dir_open(struct inode *inode, struct file *file)
{
struct dentry * dentry = file->f_path.dentry;
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
+ struct sysfs_dirent * sd;
- mutex_lock(&dentry->d_inode->i_mutex);
- file->private_data = sysfs_new_dirent(parent_sd, NULL);
- mutex_unlock(&dentry->d_inode->i_mutex);
-
- return file->private_data ? 0 : -ENOMEM;
+ sd = sysfs_new_dirent("_DIR_", 0, 0);
+ if (sd) {
+ mutex_lock(&sysfs_mutex);
+ sd->s_parent = sysfs_get(parent_sd);
+ sysfs_link_sibling(sd);
+ mutex_unlock(&sysfs_mutex);
+ }
+ file->private_data = sd;
+ return sd ? 0 : -ENOMEM;
}
static int sysfs_dir_close(struct inode *inode, struct file *file)
{
- struct dentry * dentry = file->f_path.dentry;
struct sysfs_dirent * cursor = file->private_data;
- mutex_lock(&dentry->d_inode->i_mutex);
- list_del_init(&cursor->s_sibling);
- mutex_unlock(&dentry->d_inode->i_mutex);
+ mutex_lock(&sysfs_mutex);
+ sysfs_unlink_sibling(cursor);
+ mutex_unlock(&sysfs_mutex);
release_sysfs_dirent(cursor);
@@ -503,54 +1080,65 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
struct dentry *dentry = filp->f_path.dentry;
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
struct sysfs_dirent *cursor = filp->private_data;
- struct list_head *p, *q = &cursor->s_sibling;
+ struct sysfs_dirent **pos;
ino_t ino;
int i = filp->f_pos;
switch (i) {
case 0:
- ino = dentry->d_inode->i_ino;
+ ino = parent_sd->s_ino;
if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
break;
filp->f_pos++;
i++;
/* fallthrough */
case 1:
- ino = parent_ino(dentry);
+ if (parent_sd->s_parent)
+ ino = parent_sd->s_parent->s_ino;
+ else
+ ino = parent_sd->s_ino;
if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
break;
filp->f_pos++;
i++;
/* fallthrough */
default:
+ mutex_lock(&sysfs_mutex);
+
+ pos = &parent_sd->s_children;
+ while (*pos != cursor)
+ pos = &(*pos)->s_sibling;
+
+ /* unlink cursor */
+ *pos = cursor->s_sibling;
+
if (filp->f_pos == 2)
- list_move(q, &parent_sd->s_children);
+ pos = &parent_sd->s_children;
- for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
- struct sysfs_dirent *next;
+ for ( ; *pos; pos = &(*pos)->s_sibling) {
+ struct sysfs_dirent *next = *pos;
const char * name;
int len;
- next = list_entry(p, struct sysfs_dirent,
- s_sibling);
- if (!next->s_element)
+ if (!sysfs_type(next))
continue;
- name = sysfs_get_name(next);
+ name = next->s_name;
len = strlen(name);
- if (next->s_dentry)
- ino = next->s_dentry->d_inode->i_ino;
- else
- ino = iunique(sysfs_sb, 2);
+ ino = next->s_ino;
if (filldir(dirent, name, len, filp->f_pos, ino,
dt_type(next)) < 0)
- return 0;
+ break;
- list_move(q, p);
- p = q;
filp->f_pos++;
}
+
+ /* put cursor back in */
+ cursor->s_sibling = *pos;
+ *pos = cursor;
+
+ mutex_unlock(&sysfs_mutex);
}
return 0;
}
@@ -559,7 +1147,6 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
{
struct dentry * dentry = file->f_path.dentry;
- mutex_lock(&dentry->d_inode->i_mutex);
switch (origin) {
case 1:
offset += file->f_pos;
@@ -567,31 +1154,35 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
if (offset >= 0)
break;
default:
- mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
return -EINVAL;
}
if (offset != file->f_pos) {
+ mutex_lock(&sysfs_mutex);
+
file->f_pos = offset;
if (file->f_pos >= 2) {
struct sysfs_dirent *sd = dentry->d_fsdata;
struct sysfs_dirent *cursor = file->private_data;
- struct list_head *p;
+ struct sysfs_dirent **pos;
loff_t n = file->f_pos - 2;
- list_del(&cursor->s_sibling);
- p = sd->s_children.next;
- while (n && p != &sd->s_children) {
- struct sysfs_dirent *next;
- next = list_entry(p, struct sysfs_dirent,
- s_sibling);
- if (next->s_element)
+ sysfs_unlink_sibling(cursor);
+
+ pos = &sd->s_children;
+ while (n && *pos) {
+ struct sysfs_dirent *next = *pos;
+ if (sysfs_type(next))
n--;
- p = p->next;
+ pos = &(*pos)->s_sibling;
}
- list_add_tail(&cursor->s_sibling, p);
+
+ cursor->s_sibling = *pos;
+ *pos = cursor;
}
+
+ mutex_unlock(&sysfs_mutex);
}
- mutex_unlock(&dentry->d_inode->i_mutex);
+
return offset;
}
@@ -604,12 +1195,20 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin)
int sysfs_make_shadowed_dir(struct kobject *kobj,
void * (*follow_link)(struct dentry *, struct nameidata *))
{
+ struct dentry *dentry;
struct inode *inode;
struct inode_operations *i_op;
- inode = kobj->dentry->d_inode;
- if (inode->i_op != &sysfs_dir_inode_operations)
+ /* get dentry for @kobj->sd, dentry of a shadowed dir is pinned */
+ dentry = sysfs_get_dentry(kobj->sd);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ inode = dentry->d_inode;
+ if (inode->i_op != &sysfs_dir_inode_operations) {
+ dput(dentry);
return -EINVAL;
+ }
i_op = kmalloc(sizeof(*i_op), GFP_KERNEL);
if (!i_op)
@@ -634,54 +1233,72 @@ int sysfs_make_shadowed_dir(struct kobject *kobj,
* directory.
*/
-struct dentry *sysfs_create_shadow_dir(struct kobject *kobj)
+struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj)
{
- struct sysfs_dirent *sd;
- struct dentry *parent, *dir, *shadow;
+ struct sysfs_dirent *parent_sd = kobj->sd->s_parent;
+ struct dentry *dir, *parent, *shadow;
struct inode *inode;
+ struct sysfs_dirent *sd;
+ struct sysfs_addrm_cxt acxt;
- dir = kobj->dentry;
- inode = dir->d_inode;
+ dir = sysfs_get_dentry(kobj->sd);
+ if (IS_ERR(dir)) {
+ sd = (void *)dir;
+ goto out;
+ }
parent = dir->d_parent;
- shadow = ERR_PTR(-EINVAL);
+
+ inode = dir->d_inode;
+ sd = ERR_PTR(-EINVAL);
if (!sysfs_is_shadowed_inode(inode))
- goto out;
+ goto out_dput;
shadow = d_alloc(parent, &dir->d_name);
if (!shadow)
goto nomem;
- sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR);
+ sd = sysfs_new_dirent("_SHADOW_", inode->i_mode, SYSFS_DIR);
if (!sd)
goto nomem;
+ sd->s_elem.dir.kobj = kobj;
+ sysfs_addrm_start(&acxt, parent_sd);
+
+ /* add but don't link into children list */
+ sysfs_add_one(&acxt, sd);
+
+ /* attach and instantiate dentry */
+ sysfs_attach_dentry(sd, shadow);
d_instantiate(shadow, igrab(inode));
- inc_nlink(inode);
- inc_nlink(parent->d_inode);
- shadow->d_op = &sysfs_dentry_ops;
+ inc_nlink(inode); /* tj: synchronization? */
+
+ sysfs_addrm_finish(&acxt);
dget(shadow); /* Extra count - pin the dentry in core */
-out:
- return shadow;
-nomem:
+ goto out_dput;
+
+ nomem:
dput(shadow);
- shadow = ERR_PTR(-ENOMEM);
- goto out;
+ sd = ERR_PTR(-ENOMEM);
+ out_dput:
+ dput(dir);
+ out:
+ return sd;
}
/**
* sysfs_remove_shadow_dir - remove an object's directory.
- * @shadow: dentry of shadow directory
+ * @shadow_sd: sysfs_dirent of shadow directory
*
* The only thing special about this is that we remove any files in
* the directory before we remove the directory, and we've inlined
* what used to be sysfs_rmdir() below, instead of calling separately.
*/
-void sysfs_remove_shadow_dir(struct dentry *shadow)
+void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd)
{
- __sysfs_remove_dir(shadow);
+ __sysfs_remove_dir(shadow_sd);
}
const struct file_operations sysfs_dir_operations = {
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index b502c7197ec..cc497994b2a 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -50,29 +50,15 @@ static struct sysfs_ops subsys_sysfs_ops = {
.store = subsys_attr_store,
};
-/**
- * add_to_collection - add buffer to a collection
- * @buffer: buffer to be added
- * @node: inode of set to add to
- */
-
-static inline void
-add_to_collection(struct sysfs_buffer *buffer, struct inode *node)
-{
- struct sysfs_buffer_collection *set = node->i_private;
-
- mutex_lock(&node->i_mutex);
- list_add(&buffer->associates, &set->associates);
- mutex_unlock(&node->i_mutex);
-}
-
-static inline void
-remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
-{
- mutex_lock(&node->i_mutex);
- list_del(&buffer->associates);
- mutex_unlock(&node->i_mutex);
-}
+struct sysfs_buffer {
+ size_t count;
+ loff_t pos;
+ char * page;
+ struct sysfs_ops * ops;
+ struct semaphore sem;
+ int needs_read_fill;
+ int event;
+};
/**
* fill_read_buffer - allocate and fill buffer from object.
@@ -87,9 +73,8 @@ remove_from_collection(struct sysfs_buffer *buffer, struct inode *node)
*/
static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
{
- struct sysfs_dirent * sd = dentry->d_fsdata;
- struct attribute * attr = to_attr(dentry);
- struct kobject * kobj = to_kobj(dentry->d_parent);
+ struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+ struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
struct sysfs_ops * ops = buffer->ops;
int ret = 0;
ssize_t count;
@@ -99,8 +84,15 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
if (!buffer->page)
return -ENOMEM;
- buffer->event = atomic_read(&sd->s_event);
- count = ops->show(kobj,attr,buffer->page);
+ /* need attr_sd for attr and ops, its parent for kobj */
+ if (!sysfs_get_active_two(attr_sd))
+ return -ENODEV;
+
+ buffer->event = atomic_read(&attr_sd->s_event);
+ count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page);
+
+ sysfs_put_active_two(attr_sd);
+
BUG_ON(count > (ssize_t)PAGE_SIZE);
if (count >= 0) {
buffer->needs_read_fill = 0;
@@ -138,10 +130,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
down(&buffer->sem);
if (buffer->needs_read_fill) {
- if (buffer->orphaned)
- retval = -ENODEV;
- else
- retval = fill_read_buffer(file->f_path.dentry,buffer);
+ retval = fill_read_buffer(file->f_path.dentry,buffer);
if (retval)
goto out;
}
@@ -196,14 +185,23 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
* passing the buffer that we acquired in fill_write_buffer().
*/
-static int
+static int
flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
{
- struct attribute * attr = to_attr(dentry);
- struct kobject * kobj = to_kobj(dentry->d_parent);
+ struct sysfs_dirent *attr_sd = dentry->d_fsdata;
+ struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
struct sysfs_ops * ops = buffer->ops;
+ int rc;
+
+ /* need attr_sd for attr and ops, its parent for kobj */
+ if (!sysfs_get_active_two(attr_sd))
+ return -ENODEV;
+
+ rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count);
- return ops->store(kobj,attr,buffer->page,count);
+ sysfs_put_active_two(attr_sd);
+
+ return rc;
}
@@ -231,37 +229,26 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
ssize_t len;
down(&buffer->sem);
- if (buffer->orphaned) {
- len = -ENODEV;
- goto out;
- }
len = fill_write_buffer(buffer, buf, count);
if (len > 0)
len = flush_write_buffer(file->f_path.dentry, buffer, len);
if (len > 0)
*ppos += len;
-out:
up(&buffer->sem);
return len;
}
static int sysfs_open_file(struct inode *inode, struct file *file)
{
- struct kobject *kobj = sysfs_get_kobject(file->f_path.dentry->d_parent);
- struct attribute * attr = to_attr(file->f_path.dentry);
- struct sysfs_buffer_collection *set;
+ struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
+ struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
struct sysfs_buffer * buffer;
struct sysfs_ops * ops = NULL;
- int error = 0;
-
- if (!kobj || !attr)
- goto Einval;
+ int error;
- /* Grab the module reference for this attribute if we have one */
- if (!try_module_get(attr->owner)) {
- error = -ENODEV;
- goto Done;
- }
+ /* need attr_sd for attr and ops, its parent for kobj */
+ if (!sysfs_get_active_two(attr_sd))
+ return -ENODEV;
/* if the kobject has no ktype, then we assume that it is a subsystem
* itself, and use ops for it.
@@ -273,33 +260,21 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
else
ops = &subsys_sysfs_ops;
+ error = -EACCES;
+
/* No sysfs operations, either from having no subsystem,
* or the subsystem have no operations.
*/
if (!ops)
- goto Eaccess;
-
- /* make sure we have a collection to add our buffers to */
- mutex_lock(&inode->i_mutex);
- if (!(set = inode->i_private)) {
- if (!(set = inode->i_private = kmalloc(sizeof(struct sysfs_buffer_collection), GFP_KERNEL))) {
- error = -ENOMEM;
- goto Done;
- } else {
- INIT_LIST_HEAD(&set->associates);
- }
- }
- mutex_unlock(&inode->i_mutex);
+ goto err_out;
/* File needs write support.
* The inode's perms must say it's ok,
* and we must have a store method.
*/
if (file->f_mode & FMODE_WRITE) {
-
if (!(inode->i_mode & S_IWUGO) || !ops->store)
- goto Eaccess;
-
+ goto err_out;
}
/* File needs read support.
@@ -308,48 +283,38 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
*/
if (file->f_mode & FMODE_READ) {
if (!(inode->i_mode & S_IRUGO) || !ops->show)
- goto Eaccess;
+ goto err_out;
}
/* No error? Great, allocate a buffer for the file, and store it
* it in file->private_data for easy access.
*/
+ error = -ENOMEM;
buffer = kzalloc(sizeof(struct sysfs_buffer), GFP_KERNEL);
- if (buffer) {
- INIT_LIST_HEAD(&buffer->associates);
- init_MUTEX(&buffer->sem);
- buffer->needs_read_fill = 1;
- buffer->ops = ops;
- add_to_collection(buffer, inode);
- file->private_data = buffer;
- } else
- error = -ENOMEM;
- goto Done;
-
- Einval:
- error = -EINVAL;
- goto Done;
- Eaccess:
- error = -EACCES;
- module_put(attr->owner);
- Done:
- if (error)
- kobject_put(kobj);
+ if (!buffer)
+ goto err_out;
+
+ init_MUTEX(&buffer->sem);
+ buffer->needs_read_fill = 1;
+ buffer->ops = ops;
+ file->private_data = buffer;
+
+ /* open succeeded, put active references and pin attr_sd */
+ sysfs_put_active_two(attr_sd);
+ sysfs_get(attr_sd);
+ return 0;
+
+ err_out:
+ sysfs_put_active_two(attr_sd);
return error;
}
static int sysfs_release(struct inode * inode, struct file * filp)
{
- struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
- struct attribute * attr = to_attr(filp->f_path.dentry);
- struct module * owner = attr->owner;
- struct sysfs_buffer * buffer = filp->private_data;
+ struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
+ struct sysfs_buffer *buffer = filp->private_data;
- if (buffer)
- remove_from_collection(buffer, inode);
- kobject_put(kobj);
- /* After this point, attr should not be accessed. */
- module_put(owner);
+ sysfs_put(attr_sd);
if (buffer) {
if (buffer->page)
@@ -376,57 +341,43 @@ static int sysfs_release(struct inode * inode, struct file * filp)
static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
{
struct sysfs_buffer * buffer = filp->private_data;
- struct kobject * kobj = to_kobj(filp->f_path.dentry->d_parent);
- struct sysfs_dirent * sd = filp->f_path.dentry->d_fsdata;
- int res = 0;
+ struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
+ struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj;
+
+ /* need parent for the kobj, grab both */
+ if (!sysfs_get_active_two(attr_sd))
+ goto trigger;
poll_wait(filp, &kobj->poll, wait);
- if (buffer->event != atomic_read(&sd->s_event)) {
- res = POLLERR|POLLPRI;
- buffer->needs_read_fill = 1;
- }
+ sysfs_put_active_two(attr_sd);
- return res;
-}
+ if (buffer->event != atomic_read(&attr_sd->s_event))
+ goto trigger;
+ return 0;
-static struct dentry *step_down(struct dentry *dir, const char * name)
-{
- struct dentry * de;
-
- if (dir == NULL || dir->d_inode == NULL)
- return NULL;
-
- mutex_lock(&dir->d_inode->i_mutex);
- de = lookup_one_len(name, dir, strlen(name));
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(dir);
- if (IS_ERR(de))
- return NULL;
- if (de->d_inode == NULL) {
- dput(de);
- return NULL;
- }
- return de;
+ trigger:
+ buffer->needs_read_fill = 1;
+ return POLLERR|POLLPRI;
}
-void sysfs_notify(struct kobject * k, char *dir, char *attr)
+void sysfs_notify(struct kobject *k, char *dir, char *attr)
{
- struct dentry *de = k->dentry;
- if (de)
- dget(de);
- if (de && dir)
- de = step_down(de, dir);
- if (de && attr)
- de = step_down(de, attr);
- if (de) {
- struct sysfs_dirent * sd = de->d_fsdata;
- if (sd)
- atomic_inc(&sd->s_event);
+ struct sysfs_dirent *sd = k->sd;
+
+ mutex_lock(&sysfs_mutex);
+
+ if (sd && dir)
+ sd = sysfs_find_dirent(sd, dir);
+ if (sd && attr)
+ sd = sysfs_find_dirent(sd, attr);
+ if (sd) {
+ atomic_inc(&sd->s_event);
wake_up_interruptible(&k->poll);
- dput(de);
}
+
+ mutex_unlock(&sysfs_mutex);
}
EXPORT_SYMBOL_GPL(sysfs_notify);
@@ -440,19 +391,30 @@ const struct file_operations sysfs_file_operations = {
};
-int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
+int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
+ int type)
{
- struct sysfs_dirent * parent_sd = dir->d_fsdata;
umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
- int error = -EEXIST;
+ struct sysfs_addrm_cxt acxt;
+ struct sysfs_dirent *sd;
- mutex_lock(&dir->d_inode->i_mutex);
- if (!sysfs_dirent_exist(parent_sd, attr->name))
- error = sysfs_make_dirent(parent_sd, NULL, (void *)attr,
- mode, type);
- mutex_unlock(&dir->d_inode->i_mutex);
+ sd = sysfs_new_dirent(attr->name, mode, type);
+ if (!sd)
+ return -ENOMEM;
+ sd->s_elem.attr.attr = (void *)attr;
- return error;
+ sysfs_addrm_start(&acxt, dir_sd);
+
+ if (!sysfs_find_dirent(dir_sd, attr->name)) {
+ sysfs_add_one(&acxt, sd);
+ sysfs_link_sibling(sd);
+ }
+
+ if (sysfs_addrm_finish(&acxt))
+ return 0;
+
+ sysfs_put(sd);
+ return -EEXIST;
}
@@ -464,9 +426,9 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type)
int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
{
- BUG_ON(!kobj || !kobj->dentry || !attr);
+ BUG_ON(!kobj || !kobj->sd || !attr);
- return sysfs_add_file(kobj->dentry, attr, SYSFS_KOBJ_ATTR);
+ return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
}
@@ -480,16 +442,16 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group)
{
- struct dentry *dir;
+ struct sysfs_dirent *dir_sd;
int error;
- dir = lookup_one_len(group, kobj->dentry, strlen(group));
- if (IS_ERR(dir))
- error = PTR_ERR(dir);
- else {
- error = sysfs_add_file(dir, attr, SYSFS_KOBJ_ATTR);
- dput(dir);
- }
+ dir_sd = sysfs_get_dirent(kobj->sd, group);
+ if (!dir_sd)
+ return -ENOENT;
+
+ error = sysfs_add_file(dir_sd, attr, SYSFS_KOBJ_ATTR);
+ sysfs_put(dir_sd);
+
return error;
}
EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
@@ -502,30 +464,31 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
*/
int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
{
- struct dentry * dir = kobj->dentry;
- struct dentry * victim;
- int res = -ENOENT;
-
- mutex_lock(&dir->d_inode->i_mutex);
- victim = lookup_one_len(attr->name, dir, strlen(attr->name));
- if (!IS_ERR(victim)) {
- /* make sure dentry is really there */
- if (victim->d_inode &&
- (victim->d_parent->d_inode == dir->d_inode)) {
- victim->d_inode->i_mtime = CURRENT_TIME;
- fsnotify_modify(victim);
- res = 0;
- } else
- d_drop(victim);
-
- /**
- * Drop the reference acquired from lookup_one_len() above.
- */
- dput(victim);
+ struct sysfs_dirent *victim_sd = NULL;
+ struct dentry *victim = NULL;
+ int rc;
+
+ rc = -ENOENT;
+ victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
+ if (!victim_sd)
+ goto out;
+
+ victim = sysfs_get_dentry(victim_sd);
+ if (IS_ERR(victim)) {
+ rc = PTR_ERR(victim);
+ victim = NULL;
+ goto out;
}
- mutex_unlock(&dir->d_inode->i_mutex);
- return res;
+ mutex_lock(&victim->d_inode->i_mutex);
+ victim->d_inode->i_mtime = CURRENT_TIME;
+ fsnotify_modify(victim);
+ mutex_unlock(&victim->d_inode->i_mutex);
+ rc = 0;
+ out:
+ dput(victim);
+ sysfs_put(victim_sd);
+ return rc;
}
@@ -538,30 +501,34 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
*/
int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
{
- struct dentry *dir = kobj->dentry;
- struct dentry *victim;
+ struct sysfs_dirent *victim_sd = NULL;
+ struct dentry *victim = NULL;
struct inode * inode;
struct iattr newattrs;
- int res = -ENOENT;
-
- mutex_lock(&dir->d_inode->i_mutex);
- victim = lookup_one_len(attr->name, dir, strlen(attr->name));
- if (!IS_ERR(victim)) {
- if (victim->d_inode &&
- (victim->d_parent->d_inode == dir->d_inode)) {
- inode = victim->d_inode;
- mutex_lock(&inode->i_mutex);
- newattrs.ia_mode = (mode & S_IALLUGO) |
- (inode->i_mode & ~S_IALLUGO);
- newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
- res = notify_change(victim, &newattrs);
- mutex_unlock(&inode->i_mutex);
- }
- dput(victim);
+ int rc;
+
+ rc = -ENOENT;
+ victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
+ if (!victim_sd)
+ goto out;
+
+ victim = sysfs_get_dentry(victim_sd);
+ if (IS_ERR(victim)) {
+ rc = PTR_ERR(victim);
+ victim = NULL;
+ goto out;
}
- mutex_unlock(&dir->d_inode->i_mutex);
- return res;
+ inode = victim->d_inode;
+ mutex_lock(&inode->i_mutex);
+ newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
+ rc = notify_change(victim, &newattrs);
+ mutex_unlock(&inode->i_mutex);
+ out:
+ dput(victim);
+ sysfs_put(victim_sd);
+ return rc;
}
EXPORT_SYMBOL_GPL(sysfs_chmod_file);
@@ -576,7 +543,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
{
- sysfs_hash_and_remove(kobj->dentry, attr->name);
+ sysfs_hash_and_remove(kobj->sd, attr->name);
}
@@ -589,12 +556,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
void sysfs_remove_file_from_group(struct kobject *kobj,
const struct attribute *attr, const char *group)
{
- struct dentry *dir;
+ struct sysfs_dirent *dir_sd;
- dir = lookup_one_len(group, kobj->dentry, strlen(group));
- if (!IS_ERR(dir)) {
- sysfs_hash_and_remove(dir, attr->name);
- dput(dir);
+ dir_sd = sysfs_get_dirent(kobj->sd, group);
+ if (dir_sd) {
+ sysfs_hash_and_remove(dir_sd, attr->name);
+ sysfs_put(dir_sd);
}
}
EXPORT_SYMBOL_GPL(sysfs_remove_file_from_group);
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 52eed2a7a5e..f318b73c790 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -18,26 +18,25 @@
#include "sysfs.h"
-static void remove_files(struct dentry * dir,
- const struct attribute_group * grp)
+static void remove_files(struct sysfs_dirent *dir_sd,
+ const struct attribute_group *grp)
{
struct attribute *const* attr;
for (attr = grp->attrs; *attr; attr++)
- sysfs_hash_and_remove(dir,(*attr)->name);
+ sysfs_hash_and_remove(dir_sd, (*attr)->name);
}
-static int create_files(struct dentry * dir,
- const struct attribute_group * grp)
+static int create_files(struct sysfs_dirent *dir_sd,
+ const struct attribute_group *grp)
{
struct attribute *const* attr;
int error = 0;
- for (attr = grp->attrs; *attr && !error; attr++) {
- error = sysfs_add_file(dir, *attr, SYSFS_KOBJ_ATTR);
- }
+ for (attr = grp->attrs; *attr && !error; attr++)
+ error = sysfs_add_file(dir_sd, *attr, SYSFS_KOBJ_ATTR);
if (error)
- remove_files(dir,grp);
+ remove_files(dir_sd, grp);
return error;
}
@@ -45,44 +44,44 @@ static int create_files(struct dentry * dir,
int sysfs_create_group(struct kobject * kobj,
const struct attribute_group * grp)
{
- struct dentry * dir;
+ struct sysfs_dirent *sd;
int error;
- BUG_ON(!kobj || !kobj->dentry);
+ BUG_ON(!kobj || !kobj->sd);
if (grp->name) {
- error = sysfs_create_subdir(kobj,grp->name,&dir);
+ error = sysfs_create_subdir(kobj, grp->name, &sd);
if (error)
return error;
} else
- dir = kobj->dentry;
- dir = dget(dir);
- if ((error = create_files(dir,grp))) {
+ sd = kobj->sd;
+ sysfs_get(sd);
+ error = create_files(sd, grp);
+ if (error) {
if (grp->name)
- sysfs_remove_subdir(dir);
+ sysfs_remove_subdir(sd);
}
- dput(dir);
+ sysfs_put(sd);
return error;
}
void sysfs_remove_group(struct kobject * kobj,
const struct attribute_group * grp)
{
- struct dentry * dir;
+ struct sysfs_dirent *dir_sd = kobj->sd;
+ struct sysfs_dirent *sd;
if (grp->name) {
- dir = lookup_one_len_kern(grp->name, kobj->dentry,
- strlen(grp->name));
- BUG_ON(IS_ERR(dir));
- }
- else
- dir = dget(kobj->dentry);
+ sd = sysfs_get_dirent(dir_sd, grp->name);
+ BUG_ON(!sd);
+ } else
+ sd = sysfs_get(dir_sd);
- remove_files(dir,grp);
+ remove_files(sd, grp);
if (grp->name)
- sysfs_remove_subdir(dir);
- /* release the ref. taken in this routine */
- dput(dir);
+ sysfs_remove_subdir(sd);
+
+ sysfs_put(sd);
}
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index bdd30e74de6..3756e152285 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -133,170 +133,94 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
*/
static struct lock_class_key sysfs_inode_imutex_key;
-struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
+void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
{
- struct inode * inode = new_inode(sysfs_sb);
- if (inode) {
- inode->i_blocks = 0;
- inode->i_mapping->a_ops = &sysfs_aops;
- inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
- inode->i_op = &sysfs_inode_operations;
- lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
-
- if (sd->s_iattr) {
- /* sysfs_dirent has non-default attributes
- * get them for the new inode from persistent copy
- * in sysfs_dirent
- */
- set_inode_attr(inode, sd->s_iattr);
- } else
- set_default_inode_attr(inode, mode);
- }
- return inode;
-}
-
-int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
-{
- int error = 0;
- struct inode * inode = NULL;
- if (dentry) {
- if (!dentry->d_inode) {
- struct sysfs_dirent * sd = dentry->d_fsdata;
- if ((inode = sysfs_new_inode(mode, sd))) {
- if (dentry->d_parent && dentry->d_parent->d_inode) {
- struct inode *p_inode = dentry->d_parent->d_inode;
- p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
- }
- goto Proceed;
- }
- else
- error = -ENOMEM;
- } else
- error = -EEXIST;
- } else
- error = -ENOENT;
- goto Done;
-
- Proceed:
- if (init)
- error = init(inode);
- if (!error) {
- d_instantiate(dentry, inode);
- if (S_ISDIR(mode))
- dget(dentry); /* pin only directory dentry in core */
+ inode->i_blocks = 0;
+ inode->i_mapping->a_ops = &sysfs_aops;
+ inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+ inode->i_op = &sysfs_inode_operations;
+ inode->i_ino = sd->s_ino;
+ lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
+
+ if (sd->s_iattr) {
+ /* sysfs_dirent has non-default attributes
+ * get them for the new inode from persistent copy
+ * in sysfs_dirent
+ */
+ set_inode_attr(inode, sd->s_iattr);
} else
- iput(inode);
- Done:
- return error;
+ set_default_inode_attr(inode, sd->s_mode);
}
-/*
- * Get the name for corresponding element represented by the given sysfs_dirent
+/**
+ * sysfs_get_inode - get inode for sysfs_dirent
+ * @sd: sysfs_dirent to allocate inode for
+ *
+ * Get inode for @sd. If such inode doesn't exist, a new inode
+ * is allocated and basics are initialized. New inode is
+ * returned locked.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * Pointer to allocated inode on success, NULL on failure.
*/
-const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
+struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
{
- struct attribute * attr;
- struct bin_attribute * bin_attr;
- struct sysfs_symlink * sl;
-
- BUG_ON(!sd || !sd->s_element);
-
- switch (sd->s_type) {
- case SYSFS_DIR:
- /* Always have a dentry so use that */
- return sd->s_dentry->d_name.name;
-
- case SYSFS_KOBJ_ATTR:
- attr = sd->s_element;
- return attr->name;
+ struct inode *inode;
- case SYSFS_KOBJ_BIN_ATTR:
- bin_attr = sd->s_element;
- return bin_attr->attr.name;
+ inode = iget_locked(sysfs_sb, sd->s_ino);
+ if (inode && (inode->i_state & I_NEW))
+ sysfs_init_inode(sd, inode);
- case SYSFS_KOBJ_LINK:
- sl = sd->s_element;
- return sl->link_name;
- }
- return NULL;
-}
-
-static inline void orphan_all_buffers(struct inode *node)
-{
- struct sysfs_buffer_collection *set;
- struct sysfs_buffer *buf;
-
- mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
- set = node->i_private;
- if (set) {
- list_for_each_entry(buf, &set->associates, associates) {
- down(&buf->sem);
- buf->orphaned = 1;
- up(&buf->sem);
- }
- }
- mutex_unlock(&node->i_mutex);
+ return inode;
}
-
-/*
- * Unhashes the dentry corresponding to given sysfs_dirent
- * Called with parent inode's i_mutex held.
+/**
+ * sysfs_instantiate - instantiate dentry
+ * @dentry: dentry to be instantiated
+ * @inode: inode associated with @sd
+ *
+ * Unlock @inode if locked and instantiate @dentry with @inode.
+ *
+ * LOCKING:
+ * None.
*/
-void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
+void sysfs_instantiate(struct dentry *dentry, struct inode *inode)
{
- struct dentry * dentry = sd->s_dentry;
- struct inode *inode;
+ BUG_ON(!dentry || dentry->d_inode);
- if (dentry) {
- spin_lock(&dcache_lock);
- spin_lock(&dentry->d_lock);
- if (!(d_unhashed(dentry) && dentry->d_inode)) {
- inode = dentry->d_inode;
- spin_lock(&inode->i_lock);
- __iget(inode);
- spin_unlock(&inode->i_lock);
- dget_locked(dentry);
- __d_drop(dentry);
- spin_unlock(&dentry->d_lock);
- spin_unlock(&dcache_lock);
- simple_unlink(parent->d_inode, dentry);
- orphan_all_buffers(inode);
- iput(inode);
- } else {
- spin_unlock(&dentry->d_lock);
- spin_unlock(&dcache_lock);
- }
- }
+ if (inode->i_state & I_NEW)
+ unlock_new_inode(inode);
+
+ d_instantiate(dentry, inode);
}
-int sysfs_hash_and_remove(struct dentry * dir, const char * name)
+int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name)
{
- struct sysfs_dirent * sd;
- struct sysfs_dirent * parent_sd;
- int found = 0;
+ struct sysfs_addrm_cxt acxt;
+ struct sysfs_dirent **pos, *sd;
- if (!dir)
+ if (!dir_sd)
return -ENOENT;
- if (dir->d_inode == NULL)
- /* no inode means this hasn't been made visible yet */
- return -ENOENT;
+ sysfs_addrm_start(&acxt, dir_sd);
+
+ for (pos = &dir_sd->s_children; *pos; pos = &(*pos)->s_sibling) {
+ sd = *pos;
- parent_sd = dir->d_fsdata;
- mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
- list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
- if (!sd->s_element)
+ if (!sysfs_type(sd))
continue;
- if (!strcmp(sysfs_get_name(sd), name)) {
- list_del_init(&sd->s_sibling);
- sysfs_drop_dentry(sd, dir);
- sysfs_put(sd);
- found = 1;
+ if (!strcmp(sd->s_name, name)) {
+ *pos = sd->s_sibling;
+ sd->s_sibling = NULL;
+ sysfs_remove_one(&acxt, sd);
break;
}
}
- mutex_unlock(&dir->d_inode->i_mutex);
- return found ? 0 : -ENOENT;
+ if (sysfs_addrm_finish(&acxt))
+ return 0;
+ return -ENOENT;
}
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 23a48a38e6a..402cc356203 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -19,27 +19,18 @@ struct vfsmount *sysfs_mount;
struct super_block * sysfs_sb = NULL;
struct kmem_cache *sysfs_dir_cachep;
-static void sysfs_clear_inode(struct inode *inode);
-
static const struct super_operations sysfs_ops = {
.statfs = simple_statfs,
.drop_inode = sysfs_delete_inode,
- .clear_inode = sysfs_clear_inode,
};
-static struct sysfs_dirent sysfs_root = {
- .s_sibling = LIST_HEAD_INIT(sysfs_root.s_sibling),
- .s_children = LIST_HEAD_INIT(sysfs_root.s_children),
- .s_element = NULL,
- .s_type = SYSFS_ROOT,
- .s_iattr = NULL,
+struct sysfs_dirent sysfs_root = {
+ .s_count = ATOMIC_INIT(1),
+ .s_flags = SYSFS_ROOT,
+ .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+ .s_ino = 1,
};
-static void sysfs_clear_inode(struct inode *inode)
-{
- kfree(inode->i_private);
-}
-
static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *inode;
@@ -52,24 +43,26 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_time_gran = 1;
sysfs_sb = sb;
- inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
- &sysfs_root);
- if (inode) {
- inode->i_op = &sysfs_dir_inode_operations;
- inode->i_fop = &sysfs_dir_operations;
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
- inc_nlink(inode);
- } else {
+ inode = new_inode(sysfs_sb);
+ if (!inode) {
pr_debug("sysfs: could not get root inode\n");
return -ENOMEM;
}
+ sysfs_init_inode(&sysfs_root, inode);
+
+ inode->i_op = &sysfs_dir_inode_operations;
+ inode->i_fop = &sysfs_dir_operations;
+ /* directory inodes start off with i_nlink == 2 (for "." entry) */
+ inc_nlink(inode);
+
root = d_alloc_root(inode);
if (!root) {
pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
iput(inode);
return -ENOMEM;
}
+ sysfs_root.s_dentry = root;
root->d_fsdata = &sysfs_root;
sb->s_root = root;
return 0;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 7b9c5bfde92..2f86e042229 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -11,71 +11,39 @@
#include "sysfs.h"
-static int object_depth(struct kobject * kobj)
+static int object_depth(struct sysfs_dirent *sd)
{
- struct kobject * p = kobj;
int depth = 0;
- do { depth++; } while ((p = p->parent));
+
+ for (; sd->s_parent; sd = sd->s_parent)
+ depth++;
+
return depth;
}
-static int object_path_length(struct kobject * kobj)
+static int object_path_length(struct sysfs_dirent * sd)
{
- struct kobject * p = kobj;
int length = 1;
- do {
- length += strlen(kobject_name(p)) + 1;
- p = p->parent;
- } while (p);
+
+ for (; sd->s_parent; sd = sd->s_parent)
+ length += strlen(sd->s_name) + 1;
+
return length;
}
-static void fill_object_path(struct kobject * kobj, char * buffer, int length)
+static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length)
{
- struct kobject * p;
-
--length;
- for (p = kobj; p; p = p->parent) {
- int cur = strlen(kobject_name(p));
+ for (; sd->s_parent; sd = sd->s_parent) {
+ int cur = strlen(sd->s_name);
/* back up enough to print this bus id with '/' */
length -= cur;
- strncpy(buffer + length,kobject_name(p),cur);
+ strncpy(buffer + length, sd->s_name, cur);
*(buffer + --length) = '/';
}
}
-static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
-{
- struct sysfs_dirent * parent_sd = parent->d_fsdata;
- struct sysfs_symlink * sl;
- int error = 0;
-
- error = -ENOMEM;
- sl = kmalloc(sizeof(*sl), GFP_KERNEL);
- if (!sl)
- goto exit1;
-
- sl->link_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
- if (!sl->link_name)
- goto exit2;
-
- strcpy(sl->link_name, name);
- sl->target_kobj = kobject_get(target);
-
- error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO,
- SYSFS_KOBJ_LINK);
- if (!error)
- return 0;
-
- kobject_put(target);
- kfree(sl->link_name);
-exit2:
- kfree(sl);
-exit1:
- return error;
-}
-
/**
* sysfs_create_link - create symlink between two objects.
* @kobj: object whose directory we're creating the link in.
@@ -84,24 +52,57 @@ exit1:
*/
int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
{
- struct dentry *dentry = NULL;
- int error = -EEXIST;
+ struct sysfs_dirent *parent_sd = NULL;
+ struct sysfs_dirent *target_sd = NULL;
+ struct sysfs_dirent *sd = NULL;
+ struct sysfs_addrm_cxt acxt;
+ int error;
BUG_ON(!name);
if (!kobj) {
if (sysfs_mount && sysfs_mount->mnt_sb)
- dentry = sysfs_mount->mnt_sb->s_root;
+ parent_sd = sysfs_mount->mnt_sb->s_root->d_fsdata;
} else
- dentry = kobj->dentry;
+ parent_sd = kobj->sd;
+
+ error = -EFAULT;
+ if (!parent_sd)
+ goto out_put;
+
+ /* target->sd can go away beneath us but is protected with
+ * sysfs_assoc_lock. Fetch target_sd from it.
+ */
+ spin_lock(&sysfs_assoc_lock);
+ if (target->sd)
+ target_sd = sysfs_get(target->sd);
+ spin_unlock(&sysfs_assoc_lock);
+
+ error = -ENOENT;
+ if (!target_sd)
+ goto out_put;
+
+ error = -ENOMEM;
+ sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
+ if (!sd)
+ goto out_put;
+ sd->s_elem.symlink.target_sd = target_sd;
- if (!dentry)
- return -EFAULT;
+ sysfs_addrm_start(&acxt, parent_sd);
- mutex_lock(&dentry->d_inode->i_mutex);
- if (!sysfs_dirent_exist(dentry->d_fsdata, name))
- error = sysfs_add_link(dentry, name, target);
- mutex_unlock(&dentry->d_inode->i_mutex);
+ if (!sysfs_find_dirent(parent_sd, name)) {
+ sysfs_add_one(&acxt, sd);
+ sysfs_link_sibling(sd);
+ }
+
+ if (sysfs_addrm_finish(&acxt))
+ return 0;
+
+ error = -EEXIST;
+ /* fall through */
+ out_put:
+ sysfs_put(target_sd);
+ sysfs_put(sd);
return error;
}
@@ -114,17 +115,17 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
void sysfs_remove_link(struct kobject * kobj, const char * name)
{
- sysfs_hash_and_remove(kobj->dentry,name);
+ sysfs_hash_and_remove(kobj->sd, name);
}
-static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
- char *path)
+static int sysfs_get_target_path(struct sysfs_dirent * parent_sd,
+ struct sysfs_dirent * target_sd, char *path)
{
char * s;
int depth, size;
- depth = object_depth(kobj);
- size = object_path_length(target) + depth * 3 - 1;
+ depth = object_depth(parent_sd);
+ size = object_path_length(target_sd) + depth * 3 - 1;
if (size > PATH_MAX)
return -ENAMETOOLONG;
@@ -133,7 +134,7 @@ static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
for (s = path; depth--; s += 3)
strcpy(s,"../");
- fill_object_path(target, path, size);
+ fill_object_path(target_sd, path, size);
pr_debug("%s: path = '%s'\n", __FUNCTION__, path);
return 0;
@@ -141,27 +142,16 @@ static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
static int sysfs_getlink(struct dentry *dentry, char * path)
{
- struct kobject *kobj, *target_kobj;
- int error = 0;
+ struct sysfs_dirent *sd = dentry->d_fsdata;
+ struct sysfs_dirent *parent_sd = sd->s_parent;
+ struct sysfs_dirent *target_sd = sd->s_elem.symlink.target_sd;
+ int error;
- kobj = sysfs_get_kobject(dentry->d_parent);
- if (!kobj)
- return -EINVAL;
+ mutex_lock(&sysfs_mutex);
+ error = sysfs_get_target_path(parent_sd, target_sd, path);
+ mutex_unlock(&sysfs_mutex);
- target_kobj = sysfs_get_kobject(dentry);
- if (!target_kobj) {
- kobject_put(kobj);
- return -EINVAL;
- }
-
- down_read(&sysfs_rename_sem);
- error = sysfs_get_target_path(kobj, target_kobj, path);
- up_read(&sysfs_rename_sem);
-
- kobject_put(kobj);
- kobject_put(target_kobj);
return error;
-
}
static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a77c57e5a6d..6a37f2386a8 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -1,38 +1,101 @@
+struct sysfs_elem_dir {
+ struct kobject * kobj;
+};
+
+struct sysfs_elem_symlink {
+ struct sysfs_dirent * target_sd;
+};
+
+struct sysfs_elem_attr {
+ struct attribute * attr;
+};
+
+struct sysfs_elem_bin_attr {
+ struct bin_attribute * bin_attr;
+};
+
+/*
+ * As long as s_count reference is held, the sysfs_dirent itself is
+ * accessible. Dereferencing s_elem or any other outer entity
+ * requires s_active reference.
+ */
struct sysfs_dirent {
atomic_t s_count;
- struct list_head s_sibling;
- struct list_head s_children;
- void * s_element;
- int s_type;
+ atomic_t s_active;
+ struct sysfs_dirent * s_parent;
+ struct sysfs_dirent * s_sibling;
+ struct sysfs_dirent * s_children;
+ const char * s_name;
+
+ union {
+ struct sysfs_elem_dir dir;
+ struct sysfs_elem_symlink symlink;
+ struct sysfs_elem_attr attr;
+ struct sysfs_elem_bin_attr bin_attr;
+ } s_elem;
+
+ unsigned int s_flags;
umode_t s_mode;
+ ino_t s_ino;
struct dentry * s_dentry;
struct iattr * s_iattr;
atomic_t s_event;
};
+#define SD_DEACTIVATED_BIAS INT_MIN
+
+struct sysfs_addrm_cxt {
+ struct sysfs_dirent *parent_sd;
+ struct inode *parent_inode;
+ struct sysfs_dirent *removed;
+ int cnt;
+};
+
extern struct vfsmount * sysfs_mount;
+extern struct sysfs_dirent sysfs_root;
extern struct kmem_cache *sysfs_dir_cachep;
-extern void sysfs_delete_inode(struct inode *inode);
-extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
-extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
+extern struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
+extern void sysfs_link_sibling(struct sysfs_dirent *sd);
+extern void sysfs_unlink_sibling(struct sysfs_dirent *sd);
+extern struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
+extern void sysfs_put_active(struct sysfs_dirent *sd);
+extern struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
+extern void sysfs_put_active_two(struct sysfs_dirent *sd);
+extern void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
+ struct sysfs_dirent *parent_sd);
+extern void sysfs_add_one(struct sysfs_addrm_cxt *acxt,
+ struct sysfs_dirent *sd);
+extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
+ struct sysfs_dirent *sd);
+extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
-extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *);
-extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
- umode_t, int);
-
-extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
-extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);
+extern void sysfs_delete_inode(struct inode *inode);
+extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
+extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
+extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
+
+extern void release_sysfs_dirent(struct sysfs_dirent * sd);
+extern struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
+ const unsigned char *name);
+extern struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
+ const unsigned char *name);
+extern struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode,
+ int type);
+
+extern int sysfs_add_file(struct sysfs_dirent *dir_sd,
+ const struct attribute *attr, int type);
+extern int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
-extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
-extern void sysfs_remove_subdir(struct dentry *);
+extern int sysfs_create_subdir(struct kobject *kobj, const char *name,
+ struct sysfs_dirent **p_sd);
+extern void sysfs_remove_subdir(struct sysfs_dirent *sd);
-extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
-extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
-extern struct rw_semaphore sysfs_rename_sem;
+extern spinlock_t sysfs_assoc_lock;
+extern struct mutex sysfs_mutex;
extern struct super_block * sysfs_sb;
extern const struct file_operations sysfs_dir_operations;
extern const struct file_operations sysfs_file_operations;
@@ -40,73 +103,9 @@ extern const struct file_operations bin_fops;
extern const struct inode_operations sysfs_dir_inode_operations;
extern const struct inode_operations sysfs_symlink_inode_operations;
-struct sysfs_symlink {
- char * link_name;
- struct kobject * target_kobj;
-};
-
-struct sysfs_buffer {
- struct list_head associates;
- size_t count;
- loff_t pos;
- char * page;
- struct sysfs_ops * ops;
- struct semaphore sem;
- int orphaned;
- int needs_read_fill;
- int event;
-};
-
-struct sysfs_buffer_collection {
- struct list_head associates;
-};
-
-static inline struct kobject * to_kobj(struct dentry * dentry)
-{
- struct sysfs_dirent * sd = dentry->d_fsdata;
- return ((struct kobject *) sd->s_element);
-}
-
-static inline struct attribute * to_attr(struct dentry * dentry)
+static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
{
- struct sysfs_dirent * sd = dentry->d_fsdata;
- return ((struct attribute *) sd->s_element);
-}
-
-static inline struct bin_attribute * to_bin_attr(struct dentry * dentry)
-{
- struct sysfs_dirent * sd = dentry->d_fsdata;
- return ((struct bin_attribute *) sd->s_element);
-}
-
-static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
-{
- struct kobject * kobj = NULL;
-
- spin_lock(&dcache_lock);
- if (!d_unhashed(dentry)) {
- struct sysfs_dirent * sd = dentry->d_fsdata;
- if (sd->s_type & SYSFS_KOBJ_LINK) {
- struct sysfs_symlink * sl = sd->s_element;
- kobj = kobject_get(sl->target_kobj);
- } else
- kobj = kobject_get(sd->s_element);
- }
- spin_unlock(&dcache_lock);
-
- return kobj;
-}
-
-static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
-{
- if (sd->s_type & SYSFS_KOBJ_LINK) {
- struct sysfs_symlink * sl = sd->s_element;
- kfree(sl->link_name);
- kobject_put(sl->target_kobj);
- kfree(sl);
- }
- kfree(sd->s_iattr);
- kmem_cache_free(sysfs_dir_cachep, sd);
+ return sd->s_flags & SYSFS_TYPE_MASK;
}
static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
@@ -120,7 +119,7 @@ static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd)
static inline void sysfs_put(struct sysfs_dirent * sd)
{
- if (atomic_dec_and_test(&sd->s_count))
+ if (sd && atomic_dec_and_test(&sd->s_count))
release_sysfs_dirent(sd);
}
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 0732ddb9020..589be21d884 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -27,7 +27,7 @@ const struct file_operations sysv_file_operations = {
.aio_write = generic_file_aio_write,
.mmap = generic_file_mmap,
.fsync = sysv_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations sysv_file_inode_operations = {
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 51b5764685e..df070bee8d4 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -261,7 +261,7 @@ const struct file_operations udf_file_operations = {
.aio_write = udf_file_aio_write,
.release = udf_release_file,
.fsync = udf_fsync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
const struct inode_operations udf_file_inode_operations = {
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index c8461551e10..bf7de0bdbab 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -100,14 +100,23 @@ no_delete:
clear_inode(inode);
}
+/*
+ * If we are going to release inode from memory, we discard preallocation and
+ * truncate last inode extent to proper length. We could use drop_inode() but
+ * it's called under inode_lock and thus we cannot mark inode dirty there. We
+ * use clear_inode() but we have to make sure to write inode as it's not written
+ * automatically.
+ */
void udf_clear_inode(struct inode *inode)
{
if (!(inode->i_sb->s_flags & MS_RDONLY)) {
lock_kernel();
+ /* Discard preallocation for directories, symlinks, etc. */
udf_discard_prealloc(inode);
+ udf_truncate_tail_extent(inode);
unlock_kernel();
+ write_inode_now(inode, 1);
}
-
kfree(UDF_I_DATA(inode));
UDF_I_DATA(inode) = NULL;
}
@@ -460,8 +469,8 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
kernel_long_ad laarr[EXTENT_MERGE_SIZE];
struct extent_position prev_epos, cur_epos, next_epos;
int count = 0, startnum = 0, endnum = 0;
- uint32_t elen = 0;
- kernel_lb_addr eloc;
+ uint32_t elen = 0, tmpelen;
+ kernel_lb_addr eloc, tmpeloc;
int c = 1;
loff_t lbcount = 0, b_off = 0;
uint32_t newblocknum, newblock;
@@ -520,8 +529,12 @@ static struct buffer_head * inode_getblk(struct inode * inode, sector_t block,
b_off -= lbcount;
offset = b_off >> inode->i_sb->s_blocksize_bits;
- /* Move into indirect extent if we are at a pointer to it */
- udf_next_aext(inode, &prev_epos, &eloc, &elen, 0);
+ /*
+ * Move prev_epos and cur_epos into indirect extent if we are at
+ * the pointer to it
+ */
+ udf_next_aext(inode, &prev_epos, &tmpeloc, &tmpelen, 0);
+ udf_next_aext(inode, &cur_epos, &tmpeloc, &tmpelen, 0);
/* if the extent is allocated and recorded, return the block
if the extent is not a multiple of the blocksize, round up */
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 3a743d854c1..6658afb41cc 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1351,7 +1351,7 @@ udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
for (i=0; i<UDF_SB_NUMPARTS(sb); i++)
{
- switch UDF_SB_PARTTYPE(sb, i)
+ switch (UDF_SB_PARTTYPE(sb, i))
{
case UDF_VIRTUAL_MAP15:
case UDF_VIRTUAL_MAP20:
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 77975ae291a..60d27764424 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -61,7 +61,11 @@ static void extent_trunc(struct inode * inode, struct extent_position *epos,
}
}
-void udf_discard_prealloc(struct inode * inode)
+/*
+ * Truncate the last extent to match i_size. This function assumes
+ * that preallocation extent is already truncated.
+ */
+void udf_truncate_tail_extent(struct inode *inode)
{
struct extent_position epos = { NULL, 0, {0, 0}};
kernel_lb_addr eloc;
@@ -71,7 +75,10 @@ void udf_discard_prealloc(struct inode * inode)
int adsize;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
- inode->i_size == UDF_I_LENEXTENTS(inode))
+ inode->i_size == UDF_I_LENEXTENTS(inode))
+ return;
+ /* Are we going to delete the file anyway? */
+ if (inode->i_nlink == 0)
return;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
@@ -79,36 +86,76 @@ void udf_discard_prealloc(struct inode * inode)
else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
adsize = sizeof(long_ad);
else
- adsize = 0;
-
- epos.block = UDF_I_LOCATION(inode);
+ BUG();
/* Find the last extent in the file */
while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1)
{
etype = netype;
lbcount += elen;
- if (lbcount > inode->i_size && lbcount - elen < inode->i_size)
- {
- WARN_ON(lbcount - inode->i_size >= inode->i_sb->s_blocksize);
+ if (lbcount > inode->i_size) {
+ if (lbcount - inode->i_size >= inode->i_sb->s_blocksize)
+ printk(KERN_WARNING
+ "udf_truncate_tail_extent(): Too long "
+ "extent after EOF in inode %u: i_size: "
+ "%Ld lbcount: %Ld extent %u+%u\n",
+ (unsigned)inode->i_ino,
+ (long long)inode->i_size,
+ (long long)lbcount,
+ (unsigned)eloc.logicalBlockNum,
+ (unsigned)elen);
nelen = elen - (lbcount - inode->i_size);
epos.offset -= adsize;
extent_trunc(inode, &epos, eloc, etype, elen, nelen);
epos.offset += adsize;
- lbcount = inode->i_size;
+ if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1)
+ printk(KERN_ERR "udf_truncate_tail_extent(): "
+ "Extent after EOF in inode %u.\n",
+ (unsigned)inode->i_ino);
+ break;
}
}
+ /* This inode entry is in-memory only and thus we don't have to mark
+ * the inode dirty */
+ UDF_I_LENEXTENTS(inode) = inode->i_size;
+ brelse(epos.bh);
+}
+
+void udf_discard_prealloc(struct inode *inode)
+{
+ struct extent_position epos = { NULL, 0, {0, 0}};
+ kernel_lb_addr eloc;
+ uint32_t elen;
+ uint64_t lbcount = 0;
+ int8_t etype = -1, netype;
+ int adsize;
+
+ if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ||
+ inode->i_size == UDF_I_LENEXTENTS(inode))
+ return;
+
+ if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
+ adsize = sizeof(short_ad);
+ else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
+ adsize = sizeof(long_ad);
+ else
+ adsize = 0;
+
+ epos.block = UDF_I_LOCATION(inode);
+
+ /* Find the last extent in the file */
+ while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {
+ etype = netype;
+ lbcount += elen;
+ }
if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) {
epos.offset -= adsize;
lbcount -= elen;
extent_trunc(inode, &epos, eloc, etype, elen, 0);
- if (!epos.bh)
- {
+ if (!epos.bh) {
UDF_I_LENALLOC(inode) = epos.offset - udf_file_entry_alloc_offset(inode);
mark_inode_dirty(inode);
- }
- else
- {
+ } else {
struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data);
aed->lengthAllocDescs = cpu_to_le32(epos.offset - sizeof(struct allocExtDesc));
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
@@ -118,9 +165,9 @@ void udf_discard_prealloc(struct inode * inode)
mark_buffer_dirty_inode(epos.bh, inode);
}
}
+ /* This inode entry is in-memory only and thus we don't have to mark
+ * the inode dirty */
UDF_I_LENEXTENTS(inode) = lbcount;
-
- WARN_ON(lbcount != inode->i_size);
brelse(epos.bh);
}
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 67ded289497..f581f2f69c0 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -146,6 +146,7 @@ extern void udf_free_inode(struct inode *);
extern struct inode * udf_new_inode (struct inode *, int, int *);
/* truncate.c */
+extern void udf_truncate_tail_extent(struct inode *);
extern void udf_discard_prealloc(struct inode *);
extern void udf_truncate_extents(struct inode *);
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 1e096323bad..6705d74c6d2 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -60,5 +60,5 @@ const struct file_operations ufs_file_operations = {
.mmap = generic_file_mmap,
.open = generic_file_open,
.fsync = ufs_sync_file,
- .sendfile = generic_file_sendfile,
+ .splice_read = generic_file_splice_read,
};
diff --git a/fs/utimes.c b/fs/utimes.c
index 480f7c8c29d..b3c88952465 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -106,9 +106,16 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags
if (IS_IMMUTABLE(inode))
goto dput_and_out;
- if (current->fsuid != inode->i_uid &&
- (error = vfs_permission(&nd, MAY_WRITE)) != 0)
- goto dput_and_out;
+ if (current->fsuid != inode->i_uid) {
+ if (f) {
+ if (!(f->f_mode & FMODE_WRITE))
+ goto dput_and_out;
+ } else {
+ error = vfs_permission(&nd, MAY_WRITE);
+ if (error)
+ goto dput_and_out;
+ }
+ }
}
mutex_lock(&inode->i_mutex);
error = notify_change(dentry, &newattrs);
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
index b49989bb89a..e7a9a83f008 100644
--- a/fs/xfs/Makefile-linux-2.6
+++ b/fs/xfs/Makefile-linux-2.6
@@ -64,6 +64,7 @@ xfs-y += xfs_alloc.o \
xfs_dir2_sf.o \
xfs_error.o \
xfs_extfree_item.o \
+ xfs_filestream.o \
xfs_fsops.o \
xfs_ialloc.o \
xfs_ialloc_btree.o \
@@ -77,6 +78,7 @@ xfs-y += xfs_alloc.o \
xfs_log.o \
xfs_log_recover.o \
xfs_mount.o \
+ xfs_mru_cache.o \
xfs_rename.o \
xfs_trans.o \
xfs_trans_ail.o \
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index 9ebabdf7829..4b6470cf87f 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -100,25 +100,6 @@ kmem_zone_destroy(kmem_zone_t *zone)
extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
-/*
- * Low memory cache shrinkers
- */
-
-typedef struct shrinker *kmem_shaker_t;
-typedef int (*kmem_shake_func_t)(int, gfp_t);
-
-static inline kmem_shaker_t
-kmem_shake_register(kmem_shake_func_t sfunc)
-{
- return set_shrinker(DEFAULT_SEEKS, sfunc);
-}
-
-static inline void
-kmem_shake_deregister(kmem_shaker_t shrinker)
-{
- remove_shrinker(shrinker);
-}
-
static inline int
kmem_shake_allow(gfp_t gfp_mask)
{
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 7361861e3aa..fd4105d662e 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -108,14 +108,19 @@ xfs_page_trace(
/*
* Schedule IO completion handling on a xfsdatad if this was
- * the final hold on this ioend.
+ * the final hold on this ioend. If we are asked to wait,
+ * flush the workqueue.
*/
STATIC void
xfs_finish_ioend(
- xfs_ioend_t *ioend)
+ xfs_ioend_t *ioend,
+ int wait)
{
- if (atomic_dec_and_test(&ioend->io_remaining))
+ if (atomic_dec_and_test(&ioend->io_remaining)) {
queue_work(xfsdatad_workqueue, &ioend->io_work);
+ if (wait)
+ flush_workqueue(xfsdatad_workqueue);
+ }
}
/*
@@ -156,6 +161,8 @@ xfs_setfilesize(
xfs_fsize_t bsize;
ip = xfs_vtoi(ioend->io_vnode);
+ if (!ip)
+ return;
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
ASSERT(ioend->io_type != IOMAP_READ);
@@ -334,7 +341,7 @@ xfs_end_bio(
bio->bi_end_io = NULL;
bio_put(bio);
- xfs_finish_ioend(ioend);
+ xfs_finish_ioend(ioend, 0);
return 0;
}
@@ -470,7 +477,7 @@ xfs_submit_ioend(
}
if (bio)
xfs_submit_ioend_bio(ioend, bio);
- xfs_finish_ioend(ioend);
+ xfs_finish_ioend(ioend, 0);
} while ((ioend = next) != NULL);
}
@@ -1003,6 +1010,8 @@ xfs_page_state_convert(
if (buffer_unwritten(bh) || buffer_delay(bh) ||
((buffer_uptodate(bh) || PageUptodate(page)) &&
!buffer_mapped(bh) && (unmapped || startio))) {
+ int new_ioend = 0;
+
/*
* Make sure we don't use a read-only iomap
*/
@@ -1021,6 +1030,15 @@ xfs_page_state_convert(
}
if (!iomap_valid) {
+ /*
+ * if we didn't have a valid mapping then we
+ * need to ensure that we put the new mapping
+ * in a new ioend structure. This needs to be
+ * done to ensure that the ioends correctly
+ * reflect the block mappings at io completion
+ * for unwritten extent conversion.
+ */
+ new_ioend = 1;
if (type == IOMAP_NEW) {
size = xfs_probe_cluster(inode,
page, bh, head, 0);
@@ -1040,7 +1058,7 @@ xfs_page_state_convert(
if (startio) {
xfs_add_to_ioend(inode, bh, offset,
type, &ioend,
- !iomap_valid);
+ new_ioend);
} else {
set_buffer_dirty(bh);
unlock_buffer(bh);
@@ -1416,6 +1434,13 @@ xfs_end_io_direct(
* This is not necessary for synchronous direct I/O, but we do
* it anyway to keep the code uniform and simpler.
*
+ * Well, if only it were that simple. Because synchronous direct I/O
+ * requires extent conversion to occur *before* we return to userspace,
+ * we have to wait for extent conversion to complete. Look at the
+ * iocb that has been passed to us to determine if this is AIO or
+ * not. If it is synchronous, tell xfs_finish_ioend() to kick the
+ * workqueue and wait for it to complete.
+ *
* The core direct I/O code might be changed to always call the
* completion handler in the future, in which case all this can
* go away.
@@ -1423,9 +1448,9 @@ xfs_end_io_direct(
ioend->io_offset = offset;
ioend->io_size = size;
if (ioend->io_type == IOMAP_READ) {
- xfs_finish_ioend(ioend);
+ xfs_finish_ioend(ioend, 0);
} else if (private && size > 0) {
- xfs_finish_ioend(ioend);
+ xfs_finish_ioend(ioend, is_sync_kiocb(iocb));
} else {
/*
* A direct I/O write ioend starts it's life in unwritten
@@ -1434,7 +1459,7 @@ xfs_end_io_direct(
* handler.
*/
INIT_WORK(&ioend->io_work, xfs_end_bio_written);
- xfs_finish_ioend(ioend);
+ xfs_finish_ioend(ioend, 0);
}
/*
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index fe4f66a5af1..2df63622354 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -35,7 +35,7 @@
#include <linux/freezer.h>
static kmem_zone_t *xfs_buf_zone;
-static kmem_shaker_t xfs_buf_shake;
+static struct shrinker *xfs_buf_shake;
STATIC int xfsbufd(void *);
STATIC int xfsbufd_wakeup(int, gfp_t);
STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int);
@@ -314,7 +314,7 @@ xfs_buf_free(
ASSERT(list_empty(&bp->b_hash_list));
- if (bp->b_flags & _XBF_PAGE_CACHE) {
+ if (bp->b_flags & (_XBF_PAGE_CACHE|_XBF_PAGES)) {
uint i;
if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
@@ -323,18 +323,11 @@ xfs_buf_free(
for (i = 0; i < bp->b_page_count; i++) {
struct page *page = bp->b_pages[i];
- ASSERT(!PagePrivate(page));
+ if (bp->b_flags & _XBF_PAGE_CACHE)
+ ASSERT(!PagePrivate(page));
page_cache_release(page);
}
_xfs_buf_free_pages(bp);
- } else if (bp->b_flags & _XBF_KMEM_ALLOC) {
- /*
- * XXX(hch): bp->b_count_desired might be incorrect (see
- * xfs_buf_associate_memory for details), but fortunately
- * the Linux version of kmem_free ignores the len argument..
- */
- kmem_free(bp->b_addr, bp->b_count_desired);
- _xfs_buf_free_pages(bp);
}
xfs_buf_deallocate(bp);
@@ -764,43 +757,44 @@ xfs_buf_get_noaddr(
size_t len,
xfs_buftarg_t *target)
{
- size_t malloc_len = len;
+ unsigned long page_count = PAGE_ALIGN(len) >> PAGE_SHIFT;
+ int error, i;
xfs_buf_t *bp;
- void *data;
- int error;
bp = xfs_buf_allocate(0);
if (unlikely(bp == NULL))
goto fail;
_xfs_buf_initialize(bp, target, 0, len, 0);
- try_again:
- data = kmem_alloc(malloc_len, KM_SLEEP | KM_MAYFAIL | KM_LARGE);
- if (unlikely(data == NULL))
+ error = _xfs_buf_get_pages(bp, page_count, 0);
+ if (error)
goto fail_free_buf;
- /* check whether alignment matches.. */
- if ((__psunsigned_t)data !=
- ((__psunsigned_t)data & ~target->bt_smask)) {
- /* .. else double the size and try again */
- kmem_free(data, malloc_len);
- malloc_len <<= 1;
- goto try_again;
+ for (i = 0; i < page_count; i++) {
+ bp->b_pages[i] = alloc_page(GFP_KERNEL);
+ if (!bp->b_pages[i])
+ goto fail_free_mem;
}
+ bp->b_flags |= _XBF_PAGES;
- error = xfs_buf_associate_memory(bp, data, len);
- if (error)
+ error = _xfs_buf_map_pages(bp, XBF_MAPPED);
+ if (unlikely(error)) {
+ printk(KERN_WARNING "%s: failed to map pages\n",
+ __FUNCTION__);
goto fail_free_mem;
- bp->b_flags |= _XBF_KMEM_ALLOC;
+ }
xfs_buf_unlock(bp);
- XB_TRACE(bp, "no_daddr", data);
+ XB_TRACE(bp, "no_daddr", len);
return bp;
+
fail_free_mem:
- kmem_free(data, malloc_len);
+ while (--i >= 0)
+ __free_page(bp->b_pages[i]);
+ _xfs_buf_free_pages(bp);
fail_free_buf:
- xfs_buf_free(bp);
+ xfs_buf_deallocate(bp);
fail:
return NULL;
}
@@ -1453,6 +1447,7 @@ xfs_free_buftarg(
int external)
{
xfs_flush_buftarg(btp, 1);
+ xfs_blkdev_issue_flush(btp);
if (external)
xfs_blkdev_put(btp->bt_bdev);
xfs_free_bufhash(btp);
@@ -1837,7 +1832,7 @@ xfs_buf_init(void)
if (!xfsdatad_workqueue)
goto out_destroy_xfslogd_workqueue;
- xfs_buf_shake = kmem_shake_register(xfsbufd_wakeup);
+ xfs_buf_shake = set_shrinker(DEFAULT_SEEKS, xfsbufd_wakeup);
if (!xfs_buf_shake)
goto out_destroy_xfsdatad_workqueue;
@@ -1859,7 +1854,7 @@ xfs_buf_init(void)
void
xfs_buf_terminate(void)
{
- kmem_shake_deregister(xfs_buf_shake);
+ remove_shrinker(xfs_buf_shake);
destroy_workqueue(xfsdatad_workqueue);
destroy_workqueue(xfslogd_workqueue);
kmem_zone_destroy(xfs_buf_zone);
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index b6241f6201a..b5908a34b15 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -63,7 +63,7 @@ typedef enum {
/* flags used only internally */
_XBF_PAGE_CACHE = (1 << 17),/* backed by pagecache */
- _XBF_KMEM_ALLOC = (1 << 18),/* backed by kmem_alloc() */
+ _XBF_PAGES = (1 << 18), /* backed by refcounted pages */
_XBF_RUN_QUEUES = (1 << 19),/* run block device task queue */
_XBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */
} xfs_buf_flags_t;
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index cb51dc96135..cbcd40c8c2a 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -124,30 +124,6 @@ xfs_file_aio_write_invis(
}
STATIC ssize_t
-xfs_file_sendfile(
- struct file *filp,
- loff_t *pos,
- size_t count,
- read_actor_t actor,
- void *target)
-{
- return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
- filp, pos, 0, count, actor, target, NULL);
-}
-
-STATIC ssize_t
-xfs_file_sendfile_invis(
- struct file *filp,
- loff_t *pos,
- size_t count,
- read_actor_t actor,
- void *target)
-{
- return bhv_vop_sendfile(vn_from_inode(filp->f_path.dentry->d_inode),
- filp, pos, IO_INVIS, count, actor, target, NULL);
-}
-
-STATIC ssize_t
xfs_file_splice_read(
struct file *infilp,
loff_t *ppos,
@@ -208,15 +184,6 @@ xfs_file_open(
}
STATIC int
-xfs_file_close(
- struct file *filp,
- fl_owner_t id)
-{
- return -bhv_vop_close(vn_from_inode(filp->f_path.dentry->d_inode), 0,
- file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
-}
-
-STATIC int
xfs_file_release(
struct inode *inode,
struct file *filp)
@@ -452,7 +419,6 @@ const struct file_operations xfs_file_operations = {
.write = do_sync_write,
.aio_read = xfs_file_aio_read,
.aio_write = xfs_file_aio_write,
- .sendfile = xfs_file_sendfile,
.splice_read = xfs_file_splice_read,
.splice_write = xfs_file_splice_write,
.unlocked_ioctl = xfs_file_ioctl,
@@ -461,7 +427,6 @@ const struct file_operations xfs_file_operations = {
#endif
.mmap = xfs_file_mmap,
.open = xfs_file_open,
- .flush = xfs_file_close,
.release = xfs_file_release,
.fsync = xfs_file_fsync,
#ifdef HAVE_FOP_OPEN_EXEC
@@ -475,7 +440,6 @@ const struct file_operations xfs_invis_file_operations = {
.write = do_sync_write,
.aio_read = xfs_file_aio_read_invis,
.aio_write = xfs_file_aio_write_invis,
- .sendfile = xfs_file_sendfile_invis,
.splice_read = xfs_file_splice_read_invis,
.splice_write = xfs_file_splice_write_invis,
.unlocked_ioctl = xfs_file_ioctl_invis,
@@ -484,7 +448,6 @@ const struct file_operations xfs_invis_file_operations = {
#endif
.mmap = xfs_file_mmap,
.open = xfs_file_open,
- .flush = xfs_file_close,
.release = xfs_file_release,
.fsync = xfs_file_fsync,
};
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index ed3a5e1b4b6..bb72c3d4141 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -46,6 +46,7 @@ xfs_param_t xfs_params = {
.inherit_nosym = { 0, 0, 1 },
.rotorstep = { 1, 1, 255 },
.inherit_nodfrg = { 0, 1, 1 },
+ .fstrm_timer = { 1, 50, 3600*100},
};
/*
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index ff5c41ff8d4..5917808abbd 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -1019,7 +1019,7 @@ xfs_ioc_bulkstat(
if (cmd == XFS_IOC_FSINUMBERS)
error = xfs_inumbers(mp, &inlast, &count,
- bulkreq.ubuffer);
+ bulkreq.ubuffer, xfs_inumbers_fmt);
else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE)
error = xfs_bulkstat_single(mp, &inlast,
bulkreq.ubuffer, &done);
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index b83cebc165f..141cf15067c 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -23,10 +23,25 @@
#include <linux/fs.h>
#include <asm/uaccess.h>
#include "xfs.h"
-#include "xfs_types.h"
#include "xfs_fs.h"
+#include "xfs_bit.h"
+#include "xfs_log.h"
+#include "xfs_inum.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_dir2.h"
+#include "xfs_dmapi.h"
+#include "xfs_mount.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dir2_sf.h"
#include "xfs_vfs.h"
#include "xfs_vnode.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_itable.h"
+#include "xfs_error.h"
#include "xfs_dfrag.h"
#define _NATIVE_IOC(cmd, type) \
@@ -34,6 +49,7 @@
#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
#define BROKEN_X86_ALIGNMENT
+#define _PACKED __attribute__((packed))
/* on ia32 l_start is on a 32-bit boundary */
typedef struct xfs_flock64_32 {
__s16 l_type;
@@ -75,35 +91,276 @@ xfs_ioctl32_flock(
return (unsigned long)p;
}
+typedef struct compat_xfs_fsop_geom_v1 {
+ __u32 blocksize; /* filesystem (data) block size */
+ __u32 rtextsize; /* realtime extent size */
+ __u32 agblocks; /* fsblocks in an AG */
+ __u32 agcount; /* number of allocation groups */
+ __u32 logblocks; /* fsblocks in the log */
+ __u32 sectsize; /* (data) sector size, bytes */
+ __u32 inodesize; /* inode size in bytes */
+ __u32 imaxpct; /* max allowed inode space(%) */
+ __u64 datablocks; /* fsblocks in data subvolume */
+ __u64 rtblocks; /* fsblocks in realtime subvol */
+ __u64 rtextents; /* rt extents in realtime subvol*/
+ __u64 logstart; /* starting fsblock of the log */
+ unsigned char uuid[16]; /* unique id of the filesystem */
+ __u32 sunit; /* stripe unit, fsblocks */
+ __u32 swidth; /* stripe width, fsblocks */
+ __s32 version; /* structure version */
+ __u32 flags; /* superblock version flags */
+ __u32 logsectsize; /* log sector size, bytes */
+ __u32 rtsectsize; /* realtime sector size, bytes */
+ __u32 dirblocksize; /* directory block size, bytes */
+} __attribute__((packed)) compat_xfs_fsop_geom_v1_t;
+
+#define XFS_IOC_FSGEOMETRY_V1_32 \
+ _IOR ('X', 100, struct compat_xfs_fsop_geom_v1)
+
+STATIC unsigned long xfs_ioctl32_geom_v1(unsigned long arg)
+{
+ compat_xfs_fsop_geom_v1_t __user *p32 = (void __user *)arg;
+ xfs_fsop_geom_v1_t __user *p = compat_alloc_user_space(sizeof(*p));
+
+ if (copy_in_user(p, p32, sizeof(*p32)))
+ return -EFAULT;
+ return (unsigned long)p;
+}
+
+typedef struct compat_xfs_inogrp {
+ __u64 xi_startino; /* starting inode number */
+ __s32 xi_alloccount; /* # bits set in allocmask */
+ __u64 xi_allocmask; /* mask of allocated inodes */
+} __attribute__((packed)) compat_xfs_inogrp_t;
+
+STATIC int xfs_inumbers_fmt_compat(
+ void __user *ubuffer,
+ const xfs_inogrp_t *buffer,
+ long count,
+ long *written)
+{
+ compat_xfs_inogrp_t *p32 = ubuffer;
+ long i;
+
+ for (i = 0; i < count; i++) {
+ if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) ||
+ put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) ||
+ put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask))
+ return -EFAULT;
+ }
+ *written = count * sizeof(*p32);
+ return 0;
+}
+
#else
-typedef struct xfs_fsop_bulkreq32 {
+#define xfs_inumbers_fmt_compat xfs_inumbers_fmt
+#define _PACKED
+
+#endif
+
+/* XFS_IOC_FSBULKSTAT and friends */
+
+typedef struct compat_xfs_bstime {
+ __s32 tv_sec; /* seconds */
+ __s32 tv_nsec; /* and nanoseconds */
+} compat_xfs_bstime_t;
+
+STATIC int xfs_bstime_store_compat(
+ compat_xfs_bstime_t __user *p32,
+ const xfs_bstime_t *p)
+{
+ __s32 sec32;
+
+ sec32 = p->tv_sec;
+ if (put_user(sec32, &p32->tv_sec) ||
+ put_user(p->tv_nsec, &p32->tv_nsec))
+ return -EFAULT;
+ return 0;
+}
+
+typedef struct compat_xfs_bstat {
+ __u64 bs_ino; /* inode number */
+ __u16 bs_mode; /* type and mode */
+ __u16 bs_nlink; /* number of links */
+ __u32 bs_uid; /* user id */
+ __u32 bs_gid; /* group id */
+ __u32 bs_rdev; /* device value */
+ __s32 bs_blksize; /* block size */
+ __s64 bs_size; /* file size */
+ compat_xfs_bstime_t bs_atime; /* access time */
+ compat_xfs_bstime_t bs_mtime; /* modify time */
+ compat_xfs_bstime_t bs_ctime; /* inode change time */
+ int64_t bs_blocks; /* number of blocks */
+ __u32 bs_xflags; /* extended flags */
+ __s32 bs_extsize; /* extent size */
+ __s32 bs_extents; /* number of extents */
+ __u32 bs_gen; /* generation count */
+ __u16 bs_projid; /* project id */
+ unsigned char bs_pad[14]; /* pad space, unused */
+ __u32 bs_dmevmask; /* DMIG event mask */
+ __u16 bs_dmstate; /* DMIG state info */
+ __u16 bs_aextents; /* attribute number of extents */
+} _PACKED compat_xfs_bstat_t;
+
+STATIC int xfs_bulkstat_one_fmt_compat(
+ void __user *ubuffer,
+ const xfs_bstat_t *buffer)
+{
+ compat_xfs_bstat_t __user *p32 = ubuffer;
+
+ if (put_user(buffer->bs_ino, &p32->bs_ino) ||
+ put_user(buffer->bs_mode, &p32->bs_mode) ||
+ put_user(buffer->bs_nlink, &p32->bs_nlink) ||
+ put_user(buffer->bs_uid, &p32->bs_uid) ||
+ put_user(buffer->bs_gid, &p32->bs_gid) ||
+ put_user(buffer->bs_rdev, &p32->bs_rdev) ||
+ put_user(buffer->bs_blksize, &p32->bs_blksize) ||
+ put_user(buffer->bs_size, &p32->bs_size) ||
+ xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) ||
+ xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) ||
+ xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) ||
+ put_user(buffer->bs_blocks, &p32->bs_blocks) ||
+ put_user(buffer->bs_xflags, &p32->bs_xflags) ||
+ put_user(buffer->bs_extsize, &p32->bs_extsize) ||
+ put_user(buffer->bs_extents, &p32->bs_extents) ||
+ put_user(buffer->bs_gen, &p32->bs_gen) ||
+ put_user(buffer->bs_projid, &p32->bs_projid) ||
+ put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) ||
+ put_user(buffer->bs_dmstate, &p32->bs_dmstate) ||
+ put_user(buffer->bs_aextents, &p32->bs_aextents))
+ return -EFAULT;
+ return sizeof(*p32);
+}
+
+
+
+typedef struct compat_xfs_fsop_bulkreq {
compat_uptr_t lastip; /* last inode # pointer */
__s32 icount; /* count of entries in buffer */
compat_uptr_t ubuffer; /* user buffer for inode desc. */
- __s32 ocount; /* output count pointer */
-} xfs_fsop_bulkreq32_t;
+ compat_uptr_t ocount; /* output count pointer */
+} compat_xfs_fsop_bulkreq_t;
-STATIC unsigned long
-xfs_ioctl32_bulkstat(
- unsigned long arg)
+#define XFS_IOC_FSBULKSTAT_32 \
+ _IOWR('X', 101, struct compat_xfs_fsop_bulkreq)
+#define XFS_IOC_FSBULKSTAT_SINGLE_32 \
+ _IOWR('X', 102, struct compat_xfs_fsop_bulkreq)
+#define XFS_IOC_FSINUMBERS_32 \
+ _IOWR('X', 103, struct compat_xfs_fsop_bulkreq)
+
+/* copied from xfs_ioctl.c */
+STATIC int
+xfs_ioc_bulkstat_compat(
+ xfs_mount_t *mp,
+ unsigned int cmd,
+ void __user *arg)
{
- xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg;
- xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p));
+ compat_xfs_fsop_bulkreq_t __user *p32 = (void __user *)arg;
u32 addr;
+ xfs_fsop_bulkreq_t bulkreq;
+ int count; /* # of records returned */
+ xfs_ino_t inlast; /* last inode number */
+ int done;
+ int error;
+
+ /* done = 1 if there are more stats to get and if bulkstat */
+ /* should be called again (unused here, but used in dmapi) */
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return -XFS_ERROR(EIO);
+
+ if (get_user(addr, &p32->lastip))
+ return -EFAULT;
+ bulkreq.lastip = compat_ptr(addr);
+ if (get_user(bulkreq.icount, &p32->icount) ||
+ get_user(addr, &p32->ubuffer))
+ return -EFAULT;
+ bulkreq.ubuffer = compat_ptr(addr);
+ if (get_user(addr, &p32->ocount))
+ return -EFAULT;
+ bulkreq.ocount = compat_ptr(addr);
+
+ if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
+ return -XFS_ERROR(EFAULT);
+
+ if ((count = bulkreq.icount) <= 0)
+ return -XFS_ERROR(EINVAL);
+
+ if (cmd == XFS_IOC_FSINUMBERS)
+ error = xfs_inumbers(mp, &inlast, &count,
+ bulkreq.ubuffer, xfs_inumbers_fmt_compat);
+ else {
+ /* declare a var to get a warning in case the type changes */
+ bulkstat_one_fmt_pf formatter = xfs_bulkstat_one_fmt_compat;
+ error = xfs_bulkstat(mp, &inlast, &count,
+ xfs_bulkstat_one, formatter,
+ sizeof(compat_xfs_bstat_t), bulkreq.ubuffer,
+ BULKSTAT_FG_QUICK, &done);
+ }
+ if (error)
+ return -error;
+
+ if (bulkreq.ocount != NULL) {
+ if (copy_to_user(bulkreq.lastip, &inlast,
+ sizeof(xfs_ino_t)))
+ return -XFS_ERROR(EFAULT);
+
+ if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
+ return -XFS_ERROR(EFAULT);
+ }
+
+ return 0;
+}
+
+
+
+typedef struct compat_xfs_fsop_handlereq {
+ __u32 fd; /* fd for FD_TO_HANDLE */
+ compat_uptr_t path; /* user pathname */
+ __u32 oflags; /* open flags */
+ compat_uptr_t ihandle; /* user supplied handle */
+ __u32 ihandlen; /* user supplied length */
+ compat_uptr_t ohandle; /* user buffer for handle */
+ compat_uptr_t ohandlen; /* user buffer length */
+} compat_xfs_fsop_handlereq_t;
+
+#define XFS_IOC_PATH_TO_FSHANDLE_32 \
+ _IOWR('X', 104, struct compat_xfs_fsop_handlereq)
+#define XFS_IOC_PATH_TO_HANDLE_32 \
+ _IOWR('X', 105, struct compat_xfs_fsop_handlereq)
+#define XFS_IOC_FD_TO_HANDLE_32 \
+ _IOWR('X', 106, struct compat_xfs_fsop_handlereq)
+#define XFS_IOC_OPEN_BY_HANDLE_32 \
+ _IOWR('X', 107, struct compat_xfs_fsop_handlereq)
+#define XFS_IOC_READLINK_BY_HANDLE_32 \
+ _IOWR('X', 108, struct compat_xfs_fsop_handlereq)
+
+STATIC unsigned long xfs_ioctl32_fshandle(unsigned long arg)
+{
+ compat_xfs_fsop_handlereq_t __user *p32 = (void __user *)arg;
+ xfs_fsop_handlereq_t __user *p = compat_alloc_user_space(sizeof(*p));
+ u32 addr;
- if (get_user(addr, &p32->lastip) ||
- put_user(compat_ptr(addr), &p->lastip) ||
- copy_in_user(&p->icount, &p32->icount, sizeof(s32)) ||
- get_user(addr, &p32->ubuffer) ||
- put_user(compat_ptr(addr), &p->ubuffer) ||
- get_user(addr, &p32->ocount) ||
- put_user(compat_ptr(addr), &p->ocount))
+ if (copy_in_user(&p->fd, &p32->fd, sizeof(__u32)) ||
+ get_user(addr, &p32->path) ||
+ put_user(compat_ptr(addr), &p->path) ||
+ copy_in_user(&p->oflags, &p32->oflags, sizeof(__u32)) ||
+ get_user(addr, &p32->ihandle) ||
+ put_user(compat_ptr(addr), &p->ihandle) ||
+ copy_in_user(&p->ihandlen, &p32->ihandlen, sizeof(__u32)) ||
+ get_user(addr, &p32->ohandle) ||
+ put_user(compat_ptr(addr), &p->ohandle) ||
+ get_user(addr, &p32->ohandlen) ||
+ put_user(compat_ptr(addr), &p->ohandlen))
return -EFAULT;
return (unsigned long)p;
}
-#endif
+
STATIC long
xfs_compat_ioctl(
@@ -118,7 +375,6 @@ xfs_compat_ioctl(
switch (cmd) {
case XFS_IOC_DIOINFO:
- case XFS_IOC_FSGEOMETRY_V1:
case XFS_IOC_FSGEOMETRY:
case XFS_IOC_GETVERSION:
case XFS_IOC_GETXFLAGS:
@@ -131,12 +387,7 @@ xfs_compat_ioctl(
case XFS_IOC_GETBMAPA:
case XFS_IOC_GETBMAPX:
/* not handled
- case XFS_IOC_FD_TO_HANDLE:
- case XFS_IOC_PATH_TO_HANDLE:
- case XFS_IOC_PATH_TO_FSHANDLE:
- case XFS_IOC_OPEN_BY_HANDLE:
case XFS_IOC_FSSETDM_BY_HANDLE:
- case XFS_IOC_READLINK_BY_HANDLE:
case XFS_IOC_ATTRLIST_BY_HANDLE:
case XFS_IOC_ATTRMULTI_BY_HANDLE:
*/
@@ -166,6 +417,10 @@ xfs_compat_ioctl(
arg = xfs_ioctl32_flock(arg);
cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
break;
+ case XFS_IOC_FSGEOMETRY_V1_32:
+ arg = xfs_ioctl32_geom_v1(arg);
+ cmd = _NATIVE_IOC(cmd, struct xfs_fsop_geom_v1);
+ break;
#else /* These are handled fine if no alignment issues */
case XFS_IOC_ALLOCSP:
@@ -176,18 +431,28 @@ xfs_compat_ioctl(
case XFS_IOC_FREESP64:
case XFS_IOC_RESVSP64:
case XFS_IOC_UNRESVSP64:
+ case XFS_IOC_FSGEOMETRY_V1:
break;
/* xfs_bstat_t still has wrong u32 vs u64 alignment */
case XFS_IOC_SWAPEXT:
break;
- case XFS_IOC_FSBULKSTAT_SINGLE:
- case XFS_IOC_FSBULKSTAT:
- case XFS_IOC_FSINUMBERS:
- arg = xfs_ioctl32_bulkstat(arg);
- break;
#endif
+ case XFS_IOC_FSBULKSTAT_32:
+ case XFS_IOC_FSBULKSTAT_SINGLE_32:
+ case XFS_IOC_FSINUMBERS_32:
+ cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq);
+ return xfs_ioc_bulkstat_compat(XFS_BHVTOI(VNHEAD(vp))->i_mount,
+ cmd, (void*)arg);
+ case XFS_IOC_FD_TO_HANDLE_32:
+ case XFS_IOC_PATH_TO_HANDLE_32:
+ case XFS_IOC_PATH_TO_FSHANDLE_32:
+ case XFS_IOC_OPEN_BY_HANDLE_32:
+ case XFS_IOC_READLINK_BY_HANDLE_32:
+ arg = xfs_ioctl32_fshandle(arg);
+ cmd = _NATIVE_IOC(cmd, struct xfs_fsop_handlereq);
+ break;
default:
return -ENOIOCTLCMD;
}
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 715adad7dd4..330c4ba9d40 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -101,7 +101,6 @@
* Feature macros (disable/enable)
*/
#undef HAVE_REFCACHE /* reference cache not needed for NFS in 2.6 */
-#define HAVE_SENDFILE /* sendfile(2) exists in 2.6, but not in 2.4 */
#define HAVE_SPLICE /* a splice(2) exists in 2.6, but not in 2.4 */
#ifdef CONFIG_SMP
#define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */
@@ -124,6 +123,7 @@
#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val
#define xfs_rotorstep xfs_params.rotorstep.val
#define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val
+#define xfs_fstrm_centisecs xfs_params.fstrm_timer.val
#define current_cpu() (raw_smp_processor_id())
#define current_pid() (current->pid)
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 86fb671a8bc..765ec16a6e3 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -159,7 +159,7 @@ xfs_iozero(
if (status)
goto unlock;
- memclear_highpage_flush(page, offset, bytes);
+ zero_user_page(page, offset, bytes, KM_USER0);
status = mapping->a_ops->commit_write(NULL, page, offset,
offset + bytes);
@@ -287,50 +287,6 @@ xfs_read(
}
ssize_t
-xfs_sendfile(
- bhv_desc_t *bdp,
- struct file *filp,
- loff_t *offset,
- int ioflags,
- size_t count,
- read_actor_t actor,
- void *target,
- cred_t *credp)
-{
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
- xfs_mount_t *mp = ip->i_mount;
- ssize_t ret;
-
- XFS_STATS_INC(xs_read_calls);
- if (XFS_FORCED_SHUTDOWN(mp))
- return -EIO;
-
- xfs_ilock(ip, XFS_IOLOCK_SHARED);
-
- if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
- (!(ioflags & IO_INVIS))) {
- bhv_vrwlock_t locktype = VRWLOCK_READ;
- int error;
-
- error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
- *offset, count,
- FILP_DELAY_FLAG(filp), &locktype);
- if (error) {
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return -error;
- }
- }
- xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
- (void *)(unsigned long)target, count, *offset, ioflags);
- ret = generic_file_sendfile(filp, offset, count, actor, target);
- if (ret > 0)
- XFS_STATS_ADD(xs_read_bytes, ret);
-
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return ret;
-}
-
-ssize_t
xfs_splice_read(
bhv_desc_t *bdp,
struct file *infilp,
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 7ac51b1d216..7c60a1eed88 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -90,9 +90,6 @@ extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
-extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *,
- loff_t *, int, size_t, read_actor_t,
- void *, struct cred *);
extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
struct pipe_inode_info *, size_t, int, int,
struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index bf9a9d5909b..06894cf00b1 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -547,7 +547,8 @@ vfs_sync_worker(
if (!(vfsp->vfs_flag & VFS_RDONLY))
error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
- SYNC_ATTR | SYNC_REFCACHE, NULL);
+ SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER,
+ NULL);
vfsp->vfs_sync_seq++;
wake_up(&vfsp->vfs_wait_single_sync_task);
}
@@ -663,7 +664,7 @@ xfs_fs_sync_super(
* occur here so don't bother flushing the buftarg (i.e
* SYNC_QUIESCE) because it'll just get dirty again.
*/
- flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_IOWAIT;
+ flags = SYNC_DATA_QUIESCE;
} else
flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index cd6eaa44aa2..bb997d75c05 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -210,6 +210,17 @@ static ctl_table xfs_table[] = {
.extra1 = &xfs_params.inherit_nodfrg.min,
.extra2 = &xfs_params.inherit_nodfrg.max
},
+ {
+ .ctl_name = XFS_FILESTREAM_TIMER,
+ .procname = "filestream_centisecs",
+ .data = &xfs_params.fstrm_timer.val,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &xfs_params.fstrm_timer.min,
+ .extra2 = &xfs_params.fstrm_timer.max,
+ },
/* please keep this the last entry */
#ifdef CONFIG_PROC_FS
{
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h
index a631fb8cc5a..98b97e399d6 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.h
+++ b/fs/xfs/linux-2.6/xfs_sysctl.h
@@ -47,6 +47,7 @@ typedef struct xfs_param {
xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */
xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */
xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
+ xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */
} xfs_param_t;
/*
@@ -86,6 +87,7 @@ enum {
XFS_INHERIT_NOSYM = 19,
XFS_ROTORSTEP = 20,
XFS_INHERIT_NODFRG = 21,
+ XFS_FILESTREAM_TIMER = 22,
};
extern xfs_param_t xfs_params;
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index e2c2ce98ab5..dca3481aaaf 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -92,6 +92,21 @@ typedef enum {
#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
#define SYNC_IOWAIT 0x0100 /* wait for all I/O to complete */
+#define SYNC_SUPER 0x0200 /* flush superblock to disk */
+
+/*
+ * When remounting a filesystem read-only or freezing the filesystem,
+ * we have two phases to execute. This first phase is syncing the data
+ * before we quiesce the fielsystem, and the second is flushing all the
+ * inodes out after we've waited for all the transactions created by
+ * the first phase to complete. The second phase uses SYNC_INODE_QUIESCE
+ * to ensure that the inodes are written to their location on disk
+ * rather than just existing in transactions in the log. This means
+ * after a quiesce there is no log replay required to write the inodes
+ * to disk (this is the main difference between a sync and a quiesce).
+ */
+#define SYNC_DATA_QUIESCE (SYNC_DELWRI|SYNC_FSDATA|SYNC_WAIT|SYNC_IOWAIT)
+#define SYNC_INODE_QUIESCE (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
#define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */
#define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index d1b2d01843d..5742d65f078 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -129,19 +129,13 @@ typedef enum bhv_vchange {
VCHANGE_FLAGS_IOEXCL_COUNT = 4
} bhv_vchange_t;
-typedef enum { L_FALSE, L_TRUE } lastclose_t;
-
typedef int (*vop_open_t)(bhv_desc_t *, struct cred *);
-typedef int (*vop_close_t)(bhv_desc_t *, int, lastclose_t, struct cred *);
typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
-typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
- loff_t *, int, size_t, read_actor_t,
- void *, struct cred *);
typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
struct pipe_inode_info *, size_t, int, int,
struct cred *);
@@ -203,10 +197,8 @@ typedef int (*vop_iflush_t)(bhv_desc_t *, int);
typedef struct bhv_vnodeops {
bhv_position_t vn_position; /* position within behavior chain */
vop_open_t vop_open;
- vop_close_t vop_close;
vop_read_t vop_read;
vop_write_t vop_write;
- vop_sendfile_t vop_sendfile;
vop_splice_read_t vop_splice_read;
vop_splice_write_t vop_splice_write;
vop_ioctl_t vop_ioctl;
@@ -249,13 +241,10 @@ typedef struct bhv_vnodeops {
#define VNHEAD(vp) ((vp)->v_bh.bh_first)
#define VOP(op, vp) (*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op)
#define bhv_vop_open(vp, cr) VOP(vop_open, vp)(VNHEAD(vp),cr)
-#define bhv_vop_close(vp, f,last,cr) VOP(vop_close, vp)(VNHEAD(vp),f,last,cr)
#define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr) \
VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \
VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
-#define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr) \
- VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr)
#define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \
VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
#define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 3e4a8ad8a34..7def4c69934 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -62,10 +62,9 @@ uint ndquot;
kmem_zone_t *qm_dqzone;
kmem_zone_t *qm_dqtrxzone;
-static kmem_shaker_t xfs_qm_shaker;
+static struct shrinker *xfs_qm_shaker;
static cred_t xfs_zerocr;
-static xfs_inode_t xfs_zeroino;
STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
@@ -150,7 +149,7 @@ xfs_Gqm_init(void)
} else
xqm->qm_dqzone = qm_dqzone;
- xfs_qm_shaker = kmem_shake_register(xfs_qm_shake);
+ xfs_qm_shaker = set_shrinker(DEFAULT_SEEKS, xfs_qm_shake);
/*
* The t_dqinfo portion of transactions.
@@ -182,7 +181,7 @@ xfs_qm_destroy(
ASSERT(xqm != NULL);
ASSERT(xqm->qm_nrefs == 0);
- kmem_shake_deregister(xfs_qm_shaker);
+ remove_shrinker(xfs_qm_shaker);
hsize = xqm->qm_dqhashmask + 1;
for (i = 0; i < hsize; i++) {
xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
@@ -1415,7 +1414,7 @@ xfs_qm_qino_alloc(
return error;
}
- if ((error = xfs_dir_ialloc(&tp, &xfs_zeroino, S_IFREG, 1, 0,
+ if ((error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
&xfs_zerocr, 0, 1, ip, &committed))) {
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
XFS_TRANS_ABORT);
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
index bf0a12040b1..b5a7d92c684 100644
--- a/fs/xfs/xfs.h
+++ b/fs/xfs/xfs.h
@@ -38,6 +38,7 @@
#define XFS_RW_TRACE 1
#define XFS_BUF_TRACE 1
#define XFS_VNODE_TRACE 1
+#define XFS_FILESTREAMS_TRACE 1
#endif
#include <linux-2.6/xfs_linux.h>
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 9ece7f87ec5..51c09c114a2 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -68,6 +68,7 @@ typedef struct xfs_agf {
__be32 agf_flcount; /* count of blocks in freelist */
__be32 agf_freeblks; /* total free blocks */
__be32 agf_longest; /* longest free space */
+ __be32 agf_btreeblks; /* # of blocks held in AGF btrees */
} xfs_agf_t;
#define XFS_AGF_MAGICNUM 0x00000001
@@ -81,7 +82,8 @@ typedef struct xfs_agf {
#define XFS_AGF_FLCOUNT 0x00000100
#define XFS_AGF_FREEBLKS 0x00000200
#define XFS_AGF_LONGEST 0x00000400
-#define XFS_AGF_NUM_BITS 11
+#define XFS_AGF_BTREEBLKS 0x00000800
+#define XFS_AGF_NUM_BITS 12
#define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1)
/* disk block (xfs_daddr_t) in the AG */
@@ -186,12 +188,15 @@ typedef struct xfs_perag
__uint32_t pagf_flcount; /* count of blocks in freelist */
xfs_extlen_t pagf_freeblks; /* total free blocks */
xfs_extlen_t pagf_longest; /* longest free space */
+ __uint32_t pagf_btreeblks; /* # of blocks held in AGF btrees */
xfs_agino_t pagi_freecount; /* number of free inodes */
+ xfs_agino_t pagi_count; /* number of allocated inodes */
+ int pagb_count; /* pagb slots in use */
#ifdef __KERNEL__
lock_t pagb_lock; /* lock for pagb_list */
#endif
- int pagb_count; /* pagb slots in use */
xfs_perag_busy_t *pagb_list; /* unstable blocks */
+ atomic_t pagf_fstrms; /* # of filestreams active in this AG */
} xfs_perag_t;
#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels)
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 8e9a40aa0cd..012a649a19c 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -55,17 +55,17 @@ xfs_alloc_search_busy(xfs_trans_t *tp,
ktrace_t *xfs_alloc_trace_buf;
#define TRACE_ALLOC(s,a) \
- xfs_alloc_trace_alloc(fname, s, a, __LINE__)
+ xfs_alloc_trace_alloc(__FUNCTION__, s, a, __LINE__)
#define TRACE_FREE(s,a,b,x,f) \
- xfs_alloc_trace_free(fname, s, mp, a, b, x, f, __LINE__)
+ xfs_alloc_trace_free(__FUNCTION__, s, mp, a, b, x, f, __LINE__)
#define TRACE_MODAGF(s,a,f) \
- xfs_alloc_trace_modagf(fname, s, mp, a, f, __LINE__)
-#define TRACE_BUSY(fname,s,ag,agb,l,sl,tp) \
- xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
-#define TRACE_UNBUSY(fname,s,ag,sl,tp) \
- xfs_alloc_trace_busy(fname, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
-#define TRACE_BUSYSEARCH(fname,s,ag,agb,l,sl,tp) \
- xfs_alloc_trace_busy(fname, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
+ xfs_alloc_trace_modagf(__FUNCTION__, s, mp, a, f, __LINE__)
+#define TRACE_BUSY(__FUNCTION__,s,ag,agb,l,sl,tp) \
+ xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSY, __LINE__)
+#define TRACE_UNBUSY(__FUNCTION__,s,ag,sl,tp) \
+ xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, -1, -1, sl, tp, XFS_ALLOC_KTRACE_UNBUSY, __LINE__)
+#define TRACE_BUSYSEARCH(__FUNCTION__,s,ag,agb,l,sl,tp) \
+ xfs_alloc_trace_busy(__FUNCTION__, s, mp, ag, agb, l, sl, tp, XFS_ALLOC_KTRACE_BUSYSEARCH, __LINE__)
#else
#define TRACE_ALLOC(s,a)
#define TRACE_FREE(s,a,b,x,f)
@@ -420,7 +420,7 @@ xfs_alloc_read_agfl(
*/
STATIC void
xfs_alloc_trace_alloc(
- char *name, /* function tag string */
+ const char *name, /* function tag string */
char *str, /* additional string */
xfs_alloc_arg_t *args, /* allocation argument structure */
int line) /* source line number */
@@ -453,7 +453,7 @@ xfs_alloc_trace_alloc(
*/
STATIC void
xfs_alloc_trace_free(
- char *name, /* function tag string */
+ const char *name, /* function tag string */
char *str, /* additional string */
xfs_mount_t *mp, /* file system mount point */
xfs_agnumber_t agno, /* allocation group number */
@@ -479,7 +479,7 @@ xfs_alloc_trace_free(
*/
STATIC void
xfs_alloc_trace_modagf(
- char *name, /* function tag string */
+ const char *name, /* function tag string */
char *str, /* additional string */
xfs_mount_t *mp, /* file system mount point */
xfs_agf_t *agf, /* new agf value */
@@ -507,7 +507,7 @@ xfs_alloc_trace_modagf(
STATIC void
xfs_alloc_trace_busy(
- char *name, /* function tag string */
+ const char *name, /* function tag string */
char *str, /* additional string */
xfs_mount_t *mp, /* file system mount point */
xfs_agnumber_t agno, /* allocation group number */
@@ -549,9 +549,6 @@ xfs_alloc_ag_vextent(
xfs_alloc_arg_t *args) /* argument structure for allocation */
{
int error=0;
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_alloc_ag_vextent";
-#endif
ASSERT(args->minlen > 0);
ASSERT(args->maxlen > 0);
@@ -635,9 +632,6 @@ xfs_alloc_ag_vextent_exact(
xfs_agblock_t fbno; /* start block of found extent */
xfs_agblock_t fend; /* end block of found extent */
xfs_extlen_t flen; /* length of found extent */
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_alloc_ag_vextent_exact";
-#endif
int i; /* success/failure of operation */
xfs_agblock_t maxend; /* end of maximal extent */
xfs_agblock_t minend; /* end of minimal extent */
@@ -737,9 +731,6 @@ xfs_alloc_ag_vextent_near(
xfs_btree_cur_t *bno_cur_gt; /* cursor for bno btree, right side */
xfs_btree_cur_t *bno_cur_lt; /* cursor for bno btree, left side */
xfs_btree_cur_t *cnt_cur; /* cursor for count btree */
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_alloc_ag_vextent_near";
-#endif
xfs_agblock_t gtbno; /* start bno of right side entry */
xfs_agblock_t gtbnoa; /* aligned ... */
xfs_extlen_t gtdiff; /* difference to right side entry */
@@ -1270,9 +1261,6 @@ xfs_alloc_ag_vextent_size(
int error; /* error result */
xfs_agblock_t fbno; /* start of found freespace */
xfs_extlen_t flen; /* length of found freespace */
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_alloc_ag_vextent_size";
-#endif
int i; /* temp status variable */
xfs_agblock_t rbno; /* returned block number */
xfs_extlen_t rlen; /* length of returned extent */
@@ -1427,9 +1415,6 @@ xfs_alloc_ag_vextent_small(
int error;
xfs_agblock_t fbno;
xfs_extlen_t flen;
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_alloc_ag_vextent_small";
-#endif
int i;
if ((error = xfs_alloc_decrement(ccur, 0, &i)))
@@ -1447,7 +1432,8 @@ xfs_alloc_ag_vextent_small(
else if (args->minlen == 1 && args->alignment == 1 && !args->isfl &&
(be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount)
> args->minleft)) {
- if ((error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno)))
+ error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0);
+ if (error)
goto error0;
if (fbno != NULLAGBLOCK) {
if (args->userdata) {
@@ -1515,9 +1501,6 @@ xfs_free_ag_extent(
xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */
xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */
int error; /* error return value */
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_free_ag_extent";
-#endif
xfs_agblock_t gtbno; /* start of right neighbor block */
xfs_extlen_t gtlen; /* length of right neighbor block */
int haveleft; /* have a left neighbor block */
@@ -1923,7 +1906,8 @@ xfs_alloc_fix_freelist(
while (be32_to_cpu(agf->agf_flcount) > need) {
xfs_buf_t *bp;
- if ((error = xfs_alloc_get_freelist(tp, agbp, &bno)))
+ error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
+ if (error)
return error;
if ((error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1)))
return error;
@@ -1973,8 +1957,9 @@ xfs_alloc_fix_freelist(
* Put each allocated block on the list.
*/
for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) {
- if ((error = xfs_alloc_put_freelist(tp, agbp, agflbp,
- bno)))
+ error = xfs_alloc_put_freelist(tp, agbp,
+ agflbp, bno, 0);
+ if (error)
return error;
}
}
@@ -1991,16 +1976,15 @@ int /* error */
xfs_alloc_get_freelist(
xfs_trans_t *tp, /* transaction pointer */
xfs_buf_t *agbp, /* buffer containing the agf structure */
- xfs_agblock_t *bnop) /* block address retrieved from freelist */
+ xfs_agblock_t *bnop, /* block address retrieved from freelist */
+ int btreeblk) /* destination is a AGF btree */
{
xfs_agf_t *agf; /* a.g. freespace structure */
xfs_agfl_t *agfl; /* a.g. freelist structure */
xfs_buf_t *agflbp;/* buffer for a.g. freelist structure */
xfs_agblock_t bno; /* block number returned */
int error;
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_alloc_get_freelist";
-#endif
+ int logflags;
xfs_mount_t *mp; /* mount structure */
xfs_perag_t *pag; /* per allocation group data */
@@ -2032,8 +2016,16 @@ xfs_alloc_get_freelist(
be32_add(&agf->agf_flcount, -1);
xfs_trans_agflist_delta(tp, -1);
pag->pagf_flcount--;
- TRACE_MODAGF(NULL, agf, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
- xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT);
+
+ logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
+ if (btreeblk) {
+ be32_add(&agf->agf_btreeblks, 1);
+ pag->pagf_btreeblks++;
+ logflags |= XFS_AGF_BTREEBLKS;
+ }
+
+ TRACE_MODAGF(NULL, agf, logflags);
+ xfs_alloc_log_agf(tp, agbp, logflags);
*bnop = bno;
/*
@@ -2071,6 +2063,7 @@ xfs_alloc_log_agf(
offsetof(xfs_agf_t, agf_flcount),
offsetof(xfs_agf_t, agf_freeblks),
offsetof(xfs_agf_t, agf_longest),
+ offsetof(xfs_agf_t, agf_btreeblks),
sizeof(xfs_agf_t)
};
@@ -2106,15 +2099,14 @@ xfs_alloc_put_freelist(
xfs_trans_t *tp, /* transaction pointer */
xfs_buf_t *agbp, /* buffer for a.g. freelist header */
xfs_buf_t *agflbp,/* buffer for a.g. free block array */
- xfs_agblock_t bno) /* block being freed */
+ xfs_agblock_t bno, /* block being freed */
+ int btreeblk) /* block came from a AGF btree */
{
xfs_agf_t *agf; /* a.g. freespace structure */
xfs_agfl_t *agfl; /* a.g. free block array */
__be32 *blockp;/* pointer to array entry */
int error;
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_alloc_put_freelist";
-#endif
+ int logflags;
xfs_mount_t *mp; /* mount structure */
xfs_perag_t *pag; /* per allocation group data */
@@ -2132,11 +2124,22 @@ xfs_alloc_put_freelist(
be32_add(&agf->agf_flcount, 1);
xfs_trans_agflist_delta(tp, 1);
pag->pagf_flcount++;
+
+ logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT;
+ if (btreeblk) {
+ be32_add(&agf->agf_btreeblks, -1);
+ pag->pagf_btreeblks--;
+ logflags |= XFS_AGF_BTREEBLKS;
+ }
+
+ TRACE_MODAGF(NULL, agf, logflags);
+ xfs_alloc_log_agf(tp, agbp, logflags);
+
ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
*blockp = cpu_to_be32(bno);
- TRACE_MODAGF(NULL, agf, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
- xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLLAST | XFS_AGF_FLCOUNT);
+ TRACE_MODAGF(NULL, agf, logflags);
+ xfs_alloc_log_agf(tp, agbp, logflags);
xfs_trans_log_buf(tp, agflbp,
(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
@@ -2196,6 +2199,7 @@ xfs_alloc_read_agf(
pag = &mp->m_perag[agno];
if (!pag->pagf_init) {
pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
+ pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks);
pag->pagf_flcount = be32_to_cpu(agf->agf_flcount);
pag->pagf_longest = be32_to_cpu(agf->agf_longest);
pag->pagf_levels[XFS_BTNUM_BNOi] =
@@ -2235,9 +2239,6 @@ xfs_alloc_vextent(
xfs_agblock_t agsize; /* allocation group size */
int error;
int flags; /* XFS_ALLOC_FLAG_... locking flags */
-#ifdef XFS_ALLOC_TRACE
- static char fname[] = "xfs_alloc_vextent";
-#endif
xfs_extlen_t minleft;/* minimum left value, temp copy */
xfs_mount_t *mp; /* mount structure pointer */
xfs_agnumber_t sagno; /* starting allocation group number */
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index 5a4256120cc..5aec15d0651 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -136,7 +136,8 @@ int /* error */
xfs_alloc_get_freelist(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* buffer containing the agf structure */
- xfs_agblock_t *bnop); /* block address retrieved from freelist */
+ xfs_agblock_t *bnop, /* block address retrieved from freelist */
+ int btreeblk); /* destination is a AGF btree */
/*
* Log the given fields from the agf structure.
@@ -165,7 +166,8 @@ xfs_alloc_put_freelist(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* buffer for a.g. freelist header */
struct xfs_buf *agflbp,/* buffer for a.g. free block array */
- xfs_agblock_t bno); /* block being freed */
+ xfs_agblock_t bno, /* block being freed */
+ int btreeblk); /* owner was a AGF btree */
/*
* Read in the allocation group header (free/alloc section).
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 74cadf95d4e..1603ce59585 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -226,8 +226,9 @@ xfs_alloc_delrec(
/*
* Put this buffer/block on the ag's freelist.
*/
- if ((error = xfs_alloc_put_freelist(cur->bc_tp,
- cur->bc_private.a.agbp, NULL, bno)))
+ error = xfs_alloc_put_freelist(cur->bc_tp,
+ cur->bc_private.a.agbp, NULL, bno, 1);
+ if (error)
return error;
/*
* Since blocks move to the free list without the
@@ -549,8 +550,9 @@ xfs_alloc_delrec(
/*
* Free the deleting block by putting it on the freelist.
*/
- if ((error = xfs_alloc_put_freelist(cur->bc_tp, cur->bc_private.a.agbp,
- NULL, rbno)))
+ error = xfs_alloc_put_freelist(cur->bc_tp,
+ cur->bc_private.a.agbp, NULL, rbno, 1);
+ if (error)
return error;
/*
* Since blocks move to the free list without the coordination
@@ -1320,8 +1322,9 @@ xfs_alloc_newroot(
/*
* Get a buffer from the freelist blocks, for the new root.
*/
- if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
- &nbno)))
+ error = xfs_alloc_get_freelist(cur->bc_tp,
+ cur->bc_private.a.agbp, &nbno, 1);
+ if (error)
return error;
/*
* None available, we fail.
@@ -1604,8 +1607,9 @@ xfs_alloc_split(
* Allocate the new block from the freelist.
* If we can't do it, we're toast. Give up.
*/
- if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
- &rbno)))
+ error = xfs_alloc_get_freelist(cur->bc_tp,
+ cur->bc_private.a.agbp, &rbno, 1);
+ if (error)
return error;
if (rbno == NULLAGBLOCK) {
*stat = 0;
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index 1afe07f67e3..fab0b6d5a41 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -66,44 +66,6 @@ static const char xfs_highbit[256] = {
#endif
/*
- * Count of bits set in byte, 0..8.
- */
-static const char xfs_countbit[256] = {
- 0, 1, 1, 2, 1, 2, 2, 3, /* 00 .. 07 */
- 1, 2, 2, 3, 2, 3, 3, 4, /* 08 .. 0f */
- 1, 2, 2, 3, 2, 3, 3, 4, /* 10 .. 17 */
- 2, 3, 3, 4, 3, 4, 4, 5, /* 18 .. 1f */
- 1, 2, 2, 3, 2, 3, 3, 4, /* 20 .. 27 */
- 2, 3, 3, 4, 3, 4, 4, 5, /* 28 .. 2f */
- 2, 3, 3, 4, 3, 4, 4, 5, /* 30 .. 37 */
- 3, 4, 4, 5, 4, 5, 5, 6, /* 38 .. 3f */
- 1, 2, 2, 3, 2, 3, 3, 4, /* 40 .. 47 */
- 2, 3, 3, 4, 3, 4, 4, 5, /* 48 .. 4f */
- 2, 3, 3, 4, 3, 4, 4, 5, /* 50 .. 57 */
- 3, 4, 4, 5, 4, 5, 5, 6, /* 58 .. 5f */
- 2, 3, 3, 4, 3, 4, 4, 5, /* 60 .. 67 */
- 3, 4, 4, 5, 4, 5, 5, 6, /* 68 .. 6f */
- 3, 4, 4, 5, 4, 5, 5, 6, /* 70 .. 77 */
- 4, 5, 5, 6, 5, 6, 6, 7, /* 78 .. 7f */
- 1, 2, 2, 3, 2, 3, 3, 4, /* 80 .. 87 */
- 2, 3, 3, 4, 3, 4, 4, 5, /* 88 .. 8f */
- 2, 3, 3, 4, 3, 4, 4, 5, /* 90 .. 97 */
- 3, 4, 4, 5, 4, 5, 5, 6, /* 98 .. 9f */
- 2, 3, 3, 4, 3, 4, 4, 5, /* a0 .. a7 */
- 3, 4, 4, 5, 4, 5, 5, 6, /* a8 .. af */
- 3, 4, 4, 5, 4, 5, 5, 6, /* b0 .. b7 */
- 4, 5, 5, 6, 5, 6, 6, 7, /* b8 .. bf */
- 2, 3, 3, 4, 3, 4, 4, 5, /* c0 .. c7 */
- 3, 4, 4, 5, 4, 5, 5, 6, /* c8 .. cf */
- 3, 4, 4, 5, 4, 5, 5, 6, /* d0 .. d7 */
- 4, 5, 5, 6, 5, 6, 6, 7, /* d8 .. df */
- 3, 4, 4, 5, 4, 5, 5, 6, /* e0 .. e7 */
- 4, 5, 5, 6, 5, 6, 6, 7, /* e8 .. ef */
- 4, 5, 5, 6, 5, 6, 6, 7, /* f0 .. f7 */
- 5, 6, 6, 7, 6, 7, 7, 8, /* f8 .. ff */
-};
-
-/*
* xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set.
*/
inline int
@@ -167,56 +129,21 @@ xfs_highbit64(
/*
- * Count the number of bits set in the bitmap starting with bit
- * start_bit. Size is the size of the bitmap in words.
- *
- * Do the counting by mapping a byte value to the number of set
- * bits for that value using the xfs_countbit array, i.e.
- * xfs_countbit[0] == 0, xfs_countbit[1] == 1, xfs_countbit[2] == 1,
- * xfs_countbit[3] == 2, etc.
+ * Return whether bitmap is empty.
+ * Size is number of words in the bitmap, which is padded to word boundary
+ * Returns 1 for empty, 0 for non-empty.
*/
int
-xfs_count_bits(uint *map, uint size, uint start_bit)
+xfs_bitmap_empty(uint *map, uint size)
{
- register int bits;
- register unsigned char *bytep;
- register unsigned char *end_map;
- int byte_bit;
-
- bits = 0;
- end_map = (char*)(map + size);
- bytep = (char*)(map + (start_bit & ~0x7));
- byte_bit = start_bit & 0x7;
-
- /*
- * If the caller fell off the end of the map, return 0.
- */
- if (bytep >= end_map) {
- return (0);
- }
-
- /*
- * If start_bit is not byte aligned, then process the
- * first byte separately.
- */
- if (byte_bit != 0) {
- /*
- * Shift off the bits we don't want to look at,
- * before indexing into xfs_countbit.
- */
- bits += xfs_countbit[(*bytep >> byte_bit)];
- bytep++;
- }
+ uint i;
+ uint ret = 0;
- /*
- * Count the bits in each byte until the end of the bitmap.
- */
- while (bytep < end_map) {
- bits += xfs_countbit[*bytep];
- bytep++;
+ for (i = 0; i < size; i++) {
+ ret |= map[i];
}
- return (bits);
+ return (ret == 0);
}
/*
diff --git a/fs/xfs/xfs_bit.h b/fs/xfs/xfs_bit.h
index 0bbe5681754..082641a9782 100644
--- a/fs/xfs/xfs_bit.h
+++ b/fs/xfs/xfs_bit.h
@@ -55,8 +55,8 @@ extern int xfs_lowbit64(__uint64_t v);
/* Get high bit set out of 64-bit argument, -1 if none set */
extern int xfs_highbit64(__uint64_t);
-/* Count set bits in map starting with start_bit */
-extern int xfs_count_bits(uint *map, uint size, uint start_bit);
+/* Return whether bitmap is empty (1 == empty) */
+extern int xfs_bitmap_empty(uint *map, uint size);
/* Count continuous one bits in map starting with start_bit */
extern int xfs_contig_bits(uint *map, uint size, uint start_bit);
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index b1ea26e40aa..94b5c5fe268 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -52,6 +52,7 @@
#include "xfs_quota.h"
#include "xfs_trans_space.h"
#include "xfs_buf_item.h"
+#include "xfs_filestream.h"
#ifdef DEBUG
@@ -277,7 +278,7 @@ xfs_bmap_isaeof(
STATIC void
xfs_bmap_trace_addentry(
int opcode, /* operation */
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(ies) */
@@ -291,7 +292,7 @@ xfs_bmap_trace_addentry(
*/
STATIC void
xfs_bmap_trace_delete(
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(entries) deleted */
@@ -304,7 +305,7 @@ xfs_bmap_trace_delete(
*/
STATIC void
xfs_bmap_trace_insert(
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(entries) inserted */
@@ -318,7 +319,7 @@ xfs_bmap_trace_insert(
*/
STATIC void
xfs_bmap_trace_post_update(
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry updated */
@@ -329,17 +330,25 @@ xfs_bmap_trace_post_update(
*/
STATIC void
xfs_bmap_trace_pre_update(
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry to be updated */
int whichfork); /* data or attr fork */
+#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w) \
+ xfs_bmap_trace_delete(__FUNCTION__,d,ip,i,c,w)
+#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w) \
+ xfs_bmap_trace_insert(__FUNCTION__,d,ip,i,c,r1,r2,w)
+#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w) \
+ xfs_bmap_trace_post_update(__FUNCTION__,d,ip,i,w)
+#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w) \
+ xfs_bmap_trace_pre_update(__FUNCTION__,d,ip,i,w)
#else
-#define xfs_bmap_trace_delete(f,d,ip,i,c,w)
-#define xfs_bmap_trace_insert(f,d,ip,i,c,r1,r2,w)
-#define xfs_bmap_trace_post_update(f,d,ip,i,w)
-#define xfs_bmap_trace_pre_update(f,d,ip,i,w)
+#define XFS_BMAP_TRACE_DELETE(d,ip,i,c,w)
+#define XFS_BMAP_TRACE_INSERT(d,ip,i,c,r1,r2,w)
+#define XFS_BMAP_TRACE_POST_UPDATE(d,ip,i,w)
+#define XFS_BMAP_TRACE_PRE_UPDATE(d,ip,i,w)
#endif /* XFS_BMAP_TRACE */
/*
@@ -531,9 +540,6 @@ xfs_bmap_add_extent(
xfs_filblks_t da_new; /* new count del alloc blocks used */
xfs_filblks_t da_old; /* old count del alloc blocks used */
int error; /* error return value */
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_bmap_add_extent";
-#endif
xfs_ifork_t *ifp; /* inode fork ptr */
int logflags; /* returned value */
xfs_extnum_t nextents; /* number of extents in file now */
@@ -551,8 +557,8 @@ xfs_bmap_add_extent(
* already extents in the list.
*/
if (nextents == 0) {
- xfs_bmap_trace_insert(fname, "insert empty", ip, 0, 1, new,
- NULL, whichfork);
+ XFS_BMAP_TRACE_INSERT("insert empty", ip, 0, 1, new, NULL,
+ whichfork);
xfs_iext_insert(ifp, 0, 1, new);
ASSERT(cur == NULL);
ifp->if_lastex = 0;
@@ -710,9 +716,6 @@ xfs_bmap_add_extent_delay_real(
int diff; /* temp value */
xfs_bmbt_rec_t *ep; /* extent entry for idx */
int error; /* error return value */
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_bmap_add_extent_delay_real";
-#endif
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_fileoff_t new_endoff; /* end offset of new entry */
@@ -808,15 +811,14 @@ xfs_bmap_add_extent_delay_real(
* Filling in all of a previously delayed allocation extent.
* The left and right neighbors are both contiguous with new.
*/
- xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
LEFT.br_blockcount + PREV.br_blockcount +
RIGHT.br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
- XFS_DATA_FORK);
- xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
+ XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
XFS_DATA_FORK);
+ XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
xfs_iext_remove(ifp, idx, 2);
ip->i_df.if_lastex = idx - 1;
ip->i_d.di_nextents--;
@@ -855,15 +857,14 @@ xfs_bmap_add_extent_delay_real(
* Filling in all of a previously delayed allocation extent.
* The left neighbor is contiguous, the right is not.
*/
- xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
LEFT.br_blockcount + PREV.br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
+ XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
XFS_DATA_FORK);
ip->i_df.if_lastex = idx - 1;
- xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
xfs_iext_remove(ifp, idx, 1);
if (cur == NULL)
rval = XFS_ILOG_DEXT;
@@ -892,16 +893,13 @@ xfs_bmap_add_extent_delay_real(
* Filling in all of a previously delayed allocation extent.
* The right neighbor is contiguous, the left is not.
*/
- xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
xfs_bmbt_set_startblock(ep, new->br_startblock);
xfs_bmbt_set_blockcount(ep,
PREV.br_blockcount + RIGHT.br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx, XFS_DATA_FORK);
ip->i_df.if_lastex = idx;
- xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
xfs_iext_remove(ifp, idx + 1, 1);
if (cur == NULL)
rval = XFS_ILOG_DEXT;
@@ -931,11 +929,9 @@ xfs_bmap_add_extent_delay_real(
* Neither the left nor right neighbors are contiguous with
* the new one.
*/
- xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
xfs_bmbt_set_startblock(ep, new->br_startblock);
- xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx, XFS_DATA_FORK);
ip->i_df.if_lastex = idx;
ip->i_d.di_nextents++;
if (cur == NULL)
@@ -963,17 +959,14 @@ xfs_bmap_add_extent_delay_real(
* Filling in the first part of a previous delayed allocation.
* The left neighbor is contiguous.
*/
- xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
LEFT.br_blockcount + new->br_blockcount);
xfs_bmbt_set_startoff(ep,
PREV.br_startoff + new->br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1, XFS_DATA_FORK);
temp = PREV.br_blockcount - new->br_blockcount;
- xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
xfs_bmbt_set_blockcount(ep, temp);
ip->i_df.if_lastex = idx - 1;
if (cur == NULL)
@@ -995,8 +988,7 @@ xfs_bmap_add_extent_delay_real(
temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
STARTBLOCKVAL(PREV.br_startblock));
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
- xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx, XFS_DATA_FORK);
*dnew = temp;
/* DELTA: The boundary between two in-core extents moved. */
temp = LEFT.br_startoff;
@@ -1009,11 +1001,11 @@ xfs_bmap_add_extent_delay_real(
* Filling in the first part of a previous delayed allocation.
* The left neighbor is not contiguous.
*/
- xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
xfs_bmbt_set_startoff(ep, new_endoff);
temp = PREV.br_blockcount - new->br_blockcount;
xfs_bmbt_set_blockcount(ep, temp);
- xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
+ XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
XFS_DATA_FORK);
xfs_iext_insert(ifp, idx, 1, new);
ip->i_df.if_lastex = idx;
@@ -1046,8 +1038,7 @@ xfs_bmap_add_extent_delay_real(
(cur ? cur->bc_private.b.allocated : 0));
ep = xfs_iext_get_ext(ifp, idx + 1);
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
- xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx + 1, XFS_DATA_FORK);
*dnew = temp;
/* DELTA: One in-core extent is split in two. */
temp = PREV.br_startoff;
@@ -1060,17 +1051,14 @@ xfs_bmap_add_extent_delay_real(
* The right neighbor is contiguous with the new allocation.
*/
temp = PREV.br_blockcount - new->br_blockcount;
- xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
- XFS_DATA_FORK);
- xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
xfs_bmbt_set_blockcount(ep, temp);
xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
new->br_startoff, new->br_startblock,
new->br_blockcount + RIGHT.br_blockcount,
RIGHT.br_state);
- xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1, XFS_DATA_FORK);
ip->i_df.if_lastex = idx + 1;
if (cur == NULL)
rval = XFS_ILOG_DEXT;
@@ -1091,8 +1079,7 @@ xfs_bmap_add_extent_delay_real(
temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
STARTBLOCKVAL(PREV.br_startblock));
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
- xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx, XFS_DATA_FORK);
*dnew = temp;
/* DELTA: The boundary between two in-core extents moved. */
temp = PREV.br_startoff;
@@ -1106,10 +1093,10 @@ xfs_bmap_add_extent_delay_real(
* The right neighbor is not contiguous.
*/
temp = PREV.br_blockcount - new->br_blockcount;
- xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
xfs_bmbt_set_blockcount(ep, temp);
- xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
- new, NULL, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
+ XFS_DATA_FORK);
xfs_iext_insert(ifp, idx + 1, 1, new);
ip->i_df.if_lastex = idx + 1;
ip->i_d.di_nextents++;
@@ -1141,7 +1128,7 @@ xfs_bmap_add_extent_delay_real(
(cur ? cur->bc_private.b.allocated : 0));
ep = xfs_iext_get_ext(ifp, idx);
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
- xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
*dnew = temp;
/* DELTA: One in-core extent is split in two. */
temp = PREV.br_startoff;
@@ -1155,7 +1142,7 @@ xfs_bmap_add_extent_delay_real(
* This case is avoided almost all the time.
*/
temp = new->br_startoff - PREV.br_startoff;
- xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
xfs_bmbt_set_blockcount(ep, temp);
r[0] = *new;
r[1].br_state = PREV.br_state;
@@ -1163,7 +1150,7 @@ xfs_bmap_add_extent_delay_real(
r[1].br_startoff = new_endoff;
temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff;
r[1].br_blockcount = temp2;
- xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
+ XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
XFS_DATA_FORK);
xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
ip->i_df.if_lastex = idx + 1;
@@ -1222,13 +1209,11 @@ xfs_bmap_add_extent_delay_real(
}
ep = xfs_iext_get_ext(ifp, idx);
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
- xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
- xfs_bmap_trace_pre_update(fname, "0", ip, idx + 2,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx + 2),
NULLSTARTBLOCK((int)temp2));
- xfs_bmap_trace_post_update(fname, "0", ip, idx + 2,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx + 2, XFS_DATA_FORK);
*dnew = temp + temp2;
/* DELTA: One in-core extent is split in three. */
temp = PREV.br_startoff;
@@ -1287,9 +1272,6 @@ xfs_bmap_add_extent_unwritten_real(
xfs_btree_cur_t *cur; /* btree cursor */
xfs_bmbt_rec_t *ep; /* extent entry for idx */
int error; /* error return value */
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_bmap_add_extent_unwritten_real";
-#endif
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_fileoff_t new_endoff; /* end offset of new entry */
@@ -1390,15 +1372,14 @@ xfs_bmap_add_extent_unwritten_real(
* Setting all of a previous oldext extent to newext.
* The left and right neighbors are both contiguous with new.
*/
- xfs_bmap_trace_pre_update(fname, "LF|RF|LC|RC", ip, idx - 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
LEFT.br_blockcount + PREV.br_blockcount +
RIGHT.br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF|RF|LC|RC", ip, idx - 1,
- XFS_DATA_FORK);
- xfs_bmap_trace_delete(fname, "LF|RF|LC|RC", ip, idx, 2,
+ XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,
XFS_DATA_FORK);
+ XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);
xfs_iext_remove(ifp, idx, 2);
ip->i_df.if_lastex = idx - 1;
ip->i_d.di_nextents -= 2;
@@ -1441,15 +1422,14 @@ xfs_bmap_add_extent_unwritten_real(
* Setting all of a previous oldext extent to newext.
* The left neighbor is contiguous, the right is not.
*/
- xfs_bmap_trace_pre_update(fname, "LF|RF|LC", ip, idx - 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
LEFT.br_blockcount + PREV.br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF|RF|LC", ip, idx - 1,
+ XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,
XFS_DATA_FORK);
ip->i_df.if_lastex = idx - 1;
- xfs_bmap_trace_delete(fname, "LF|RF|LC", ip, idx, 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);
xfs_iext_remove(ifp, idx, 1);
ip->i_d.di_nextents--;
if (cur == NULL)
@@ -1484,16 +1464,15 @@ xfs_bmap_add_extent_unwritten_real(
* Setting all of a previous oldext extent to newext.
* The right neighbor is contiguous, the left is not.
*/
- xfs_bmap_trace_pre_update(fname, "LF|RF|RC", ip, idx,
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(ep,
PREV.br_blockcount + RIGHT.br_blockcount);
xfs_bmbt_set_state(ep, newext);
- xfs_bmap_trace_post_update(fname, "LF|RF|RC", ip, idx,
+ XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx,
XFS_DATA_FORK);
ip->i_df.if_lastex = idx;
- xfs_bmap_trace_delete(fname, "LF|RF|RC", ip, idx + 1, 1,
- XFS_DATA_FORK);
+ XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);
xfs_iext_remove(ifp, idx + 1, 1);
ip->i_d.di_nextents--;
if (cur == NULL)
@@ -1529,10 +1508,10 @@ xfs_bmap_add_extent_unwritten_real(
* Neither the left nor right neighbors are contiguous with
* the new one.
*/
- xfs_bmap_trace_pre_update(fname, "LF|RF", ip, idx,
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx,
XFS_DATA_FORK);
xfs_bmbt_set_state(ep, newext);
- xfs_bmap_trace_post_update(fname, "LF|RF", ip, idx,
+ XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx,
XFS_DATA_FORK);
ip->i_df.if_lastex = idx;
if (cur == NULL)
@@ -1559,21 +1538,21 @@ xfs_bmap_add_extent_unwritten_real(
* Setting the first part of a previous oldext extent to newext.
* The left neighbor is contiguous.
*/
- xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx - 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
LEFT.br_blockcount + new->br_blockcount);
xfs_bmbt_set_startoff(ep,
PREV.br_startoff + new->br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx - 1,
+ XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1,
XFS_DATA_FORK);
- xfs_bmap_trace_pre_update(fname, "LF|LC", ip, idx,
+ XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx,
XFS_DATA_FORK);
xfs_bmbt_set_startblock(ep,
new->br_startblock + new->br_blockcount);
xfs_bmbt_set_blockcount(ep,
PREV.br_blockcount - new->br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
+ XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx,
XFS_DATA_FORK);
ip->i_df.if_lastex = idx - 1;
if (cur == NULL)
@@ -1610,15 +1589,15 @@ xfs_bmap_add_extent_unwritten_real(
* Setting the first part of a previous oldext extent to newext.
* The left neighbor is not contiguous.
*/
- xfs_bmap_trace_pre_update(fname, "LF", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);
ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);
xfs_bmbt_set_startoff(ep, new_endoff);
xfs_bmbt_set_blockcount(ep,
PREV.br_blockcount - new->br_blockcount);
xfs_bmbt_set_startblock(ep,
new->br_startblock + new->br_blockcount);
- xfs_bmap_trace_post_update(fname, "LF", ip, idx, XFS_DATA_FORK);
- xfs_bmap_trace_insert(fname, "LF", ip, idx, 1, new, NULL,
+ XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,
XFS_DATA_FORK);
xfs_iext_insert(ifp, idx, 1, new);
ip->i_df.if_lastex = idx;
@@ -1653,18 +1632,18 @@ xfs_bmap_add_extent_unwritten_real(
* Setting the last part of a previous oldext extent to newext.
* The right neighbor is contiguous with the new allocation.
*/
- xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx,
+ XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx,
XFS_DATA_FORK);
- xfs_bmap_trace_pre_update(fname, "RF|RC", ip, idx + 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(ep,
PREV.br_blockcount - new->br_blockcount);
- xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
+ XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx,
XFS_DATA_FORK);
xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),
new->br_startoff, new->br_startblock,
new->br_blockcount + RIGHT.br_blockcount, newext);
- xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx + 1,
+ XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1,
XFS_DATA_FORK);
ip->i_df.if_lastex = idx + 1;
if (cur == NULL)
@@ -1700,12 +1679,12 @@ xfs_bmap_add_extent_unwritten_real(
* Setting the last part of a previous oldext extent to newext.
* The right neighbor is not contiguous.
*/
- xfs_bmap_trace_pre_update(fname, "RF", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);
xfs_bmbt_set_blockcount(ep,
PREV.br_blockcount - new->br_blockcount);
- xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
- xfs_bmap_trace_insert(fname, "RF", ip, idx + 1, 1,
- new, NULL, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,
+ XFS_DATA_FORK);
xfs_iext_insert(ifp, idx + 1, 1, new);
ip->i_df.if_lastex = idx + 1;
ip->i_d.di_nextents++;
@@ -1744,17 +1723,17 @@ xfs_bmap_add_extent_unwritten_real(
* newext. Contiguity is impossible here.
* One extent becomes three extents.
*/
- xfs_bmap_trace_pre_update(fname, "0", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);
xfs_bmbt_set_blockcount(ep,
new->br_startoff - PREV.br_startoff);
- xfs_bmap_trace_post_update(fname, "0", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);
r[0] = *new;
r[1].br_startoff = new_endoff;
r[1].br_blockcount =
PREV.br_startoff + PREV.br_blockcount - new_endoff;
r[1].br_startblock = new->br_startblock + new->br_blockcount;
r[1].br_state = oldext;
- xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 2, &r[0], &r[1],
+ XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],
XFS_DATA_FORK);
xfs_iext_insert(ifp, idx + 1, 2, &r[0]);
ip->i_df.if_lastex = idx + 1;
@@ -1845,9 +1824,6 @@ xfs_bmap_add_extent_hole_delay(
int rsvd) /* OK to allocate reserved blocks */
{
xfs_bmbt_rec_t *ep; /* extent record for idx */
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_bmap_add_extent_hole_delay";
-#endif
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_irec_t left; /* left neighbor extent entry */
xfs_filblks_t newlen=0; /* new indirect size */
@@ -1919,7 +1895,7 @@ xfs_bmap_add_extent_hole_delay(
*/
temp = left.br_blockcount + new->br_blockcount +
right.br_blockcount;
- xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
oldlen = STARTBLOCKVAL(left.br_startblock) +
@@ -1928,10 +1904,9 @@ xfs_bmap_add_extent_hole_delay(
newlen = xfs_bmap_worst_indlen(ip, temp);
xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
NULLSTARTBLOCK((int)newlen));
- xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
- XFS_DATA_FORK);
- xfs_bmap_trace_delete(fname, "LC|RC", ip, idx, 1,
+ XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
XFS_DATA_FORK);
+ XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, XFS_DATA_FORK);
xfs_iext_remove(ifp, idx, 1);
ip->i_df.if_lastex = idx - 1;
/* DELTA: Two in-core extents were replaced by one. */
@@ -1946,7 +1921,7 @@ xfs_bmap_add_extent_hole_delay(
* Merge the new allocation with the left neighbor.
*/
temp = left.br_blockcount + new->br_blockcount;
- xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1,
XFS_DATA_FORK);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);
oldlen = STARTBLOCKVAL(left.br_startblock) +
@@ -1954,7 +1929,7 @@ xfs_bmap_add_extent_hole_delay(
newlen = xfs_bmap_worst_indlen(ip, temp);
xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),
NULLSTARTBLOCK((int)newlen));
- xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1,
+ XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1,
XFS_DATA_FORK);
ip->i_df.if_lastex = idx - 1;
/* DELTA: One in-core extent grew into a hole. */
@@ -1968,14 +1943,14 @@ xfs_bmap_add_extent_hole_delay(
* on the right.
* Merge the new allocation with the right neighbor.
*/
- xfs_bmap_trace_pre_update(fname, "RC", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, XFS_DATA_FORK);
temp = new->br_blockcount + right.br_blockcount;
oldlen = STARTBLOCKVAL(new->br_startblock) +
STARTBLOCKVAL(right.br_startblock);
newlen = xfs_bmap_worst_indlen(ip, temp);
xfs_bmbt_set_allf(ep, new->br_startoff,
NULLSTARTBLOCK((int)newlen), temp, right.br_state);
- xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK);
+ XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, XFS_DATA_FORK);
ip->i_df.if_lastex = idx;
/* DELTA: One in-core extent grew into a hole. */
temp2 = temp;
@@ -1989,7 +1964,7 @@ xfs_bmap_add_extent_hole_delay(
* Insert a new entry.
*/
oldlen = newlen = 0;
- xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
+ XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL,
XFS_DATA_FORK);
xfs_iext_insert(ifp, idx, 1, new);
ip->i_df.if_lastex = idx;
@@ -2039,9 +2014,6 @@ xfs_bmap_add_extent_hole_real(
{
xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */
int error; /* error return value */
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_bmap_add_extent_hole_real";
-#endif
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_irec_t left; /* left neighbor extent entry */
@@ -2118,15 +2090,14 @@ xfs_bmap_add_extent_hole_real(
* left and on the right.
* Merge all three into a single extent record.
*/
- xfs_bmap_trace_pre_update(fname, "LC|RC", ip, idx - 1,
+ XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,
whichfork);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
left.br_blockcount + new->br_blockcount +
right.br_blockcount);
- xfs_bmap_trace_post_update(fname, "LC|RC", ip, idx - 1,
+ XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,
whichfork);
- xfs_bmap_trace_delete(fname, "LC|RC", ip,
- idx, 1, whichfork);
+ XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, whichfork);
xfs_iext_remove(ifp, idx, 1);
ifp->if_lastex = idx - 1;
XFS_IFORK_NEXT_SET(ip, whichfork,
@@ -2168,10 +2139,10 @@ xfs_bmap_add_extent_hole_real(
* on the left.
* Merge the new allocation with the left neighbor.
*/
- xfs_bmap_trace_pre_update(fname, "LC", ip, idx - 1, whichfork);
+ XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1, whichfork);
xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),
left.br_blockcount + new->br_blockcount);
- xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork);
+ XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1, whichfork);
ifp->if_lastex = idx - 1;
if (cur == NULL) {
rval = XFS_ILOG_FEXT(whichfork);
@@ -2202,11 +2173,11 @@ xfs_bmap_add_extent_hole_real(
* on the right.
* Merge the new allocation with the right neighbor.
*/
- xfs_bmap_trace_pre_update(fname, "RC", ip, idx, whichfork);
+ XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, whichfork);
xfs_bmbt_set_allf(ep, new->br_startoff, new->br_startblock,
new->br_blockcount + right.br_blockcount,
right.br_state);
- xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork);
+ XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, whichfork);
ifp->if_lastex = idx;
if (cur == NULL) {
rval = XFS_ILOG_FEXT(whichfork);
@@ -2237,8 +2208,7 @@ xfs_bmap_add_extent_hole_real(
* real allocation.
* Insert a new entry.
*/
- xfs_bmap_trace_insert(fname, "0", ip, idx, 1, new, NULL,
- whichfork);
+ XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL, whichfork);
xfs_iext_insert(ifp, idx, 1, new);
ifp->if_lastex = idx;
XFS_IFORK_NEXT_SET(ip, whichfork,
@@ -2605,12 +2575,10 @@ xfs_bmap_rtalloc(
xfs_extlen_t prod = 0; /* product factor for allocators */
xfs_extlen_t ralen = 0; /* realtime allocation length */
xfs_extlen_t align; /* minimum allocation alignment */
- xfs_rtblock_t rtx; /* realtime extent number */
xfs_rtblock_t rtb;
mp = ap->ip->i_mount;
- align = ap->ip->i_d.di_extsize ?
- ap->ip->i_d.di_extsize : mp->m_sb.sb_rextsize;
+ align = xfs_get_extsz_hint(ap->ip);
prod = align / mp->m_sb.sb_rextsize;
error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
align, 1, ap->eof, 0,
@@ -2644,6 +2612,8 @@ xfs_bmap_rtalloc(
* pick an extent that will space things out in the rt area.
*/
if (ap->eof && ap->off == 0) {
+ xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */
+
error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
if (error)
return error;
@@ -2715,9 +2685,7 @@ xfs_bmap_btalloc(
int error;
mp = ap->ip->i_mount;
- align = (ap->userdata && ap->ip->i_d.di_extsize &&
- (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)) ?
- ap->ip->i_d.di_extsize : 0;
+ align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
if (unlikely(align)) {
error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp,
align, 0, ap->eof, 0, ap->conv,
@@ -2727,9 +2695,15 @@ xfs_bmap_btalloc(
}
nullfb = ap->firstblock == NULLFSBLOCK;
fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock);
- if (nullfb)
- ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
- else
+ if (nullfb) {
+ if (ap->userdata && xfs_inode_is_filestream(ap->ip)) {
+ ag = xfs_filestream_lookup_ag(ap->ip);
+ ag = (ag != NULLAGNUMBER) ? ag : 0;
+ ap->rval = XFS_AGB_TO_FSB(mp, ag, 0);
+ } else {
+ ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino);
+ }
+ } else
ap->rval = ap->firstblock;
xfs_bmap_adjacent(ap);
@@ -2753,13 +2727,22 @@ xfs_bmap_btalloc(
args.firstblock = ap->firstblock;
blen = 0;
if (nullfb) {
- args.type = XFS_ALLOCTYPE_START_BNO;
+ if (ap->userdata && xfs_inode_is_filestream(ap->ip))
+ args.type = XFS_ALLOCTYPE_NEAR_BNO;
+ else
+ args.type = XFS_ALLOCTYPE_START_BNO;
args.total = ap->total;
+
/*
- * Find the longest available space.
- * We're going to try for the whole allocation at once.
+ * Search for an allocation group with a single extent
+ * large enough for the request.
+ *
+ * If one isn't found, then adjust the minimum allocation
+ * size to the largest space found.
*/
startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
+ if (startag == NULLAGNUMBER)
+ startag = ag = 0;
notinit = 0;
down_read(&mp->m_peraglock);
while (blen < ap->alen) {
@@ -2785,6 +2768,35 @@ xfs_bmap_btalloc(
blen = longest;
} else
notinit = 1;
+
+ if (xfs_inode_is_filestream(ap->ip)) {
+ if (blen >= ap->alen)
+ break;
+
+ if (ap->userdata) {
+ /*
+ * If startag is an invalid AG, we've
+ * come here once before and
+ * xfs_filestream_new_ag picked the
+ * best currently available.
+ *
+ * Don't continue looping, since we
+ * could loop forever.
+ */
+ if (startag == NULLAGNUMBER)
+ break;
+
+ error = xfs_filestream_new_ag(ap, &ag);
+ if (error) {
+ up_read(&mp->m_peraglock);
+ return error;
+ }
+
+ /* loop again to set 'blen'*/
+ startag = NULLAGNUMBER;
+ continue;
+ }
+ }
if (++ag == mp->m_sb.sb_agcount)
ag = 0;
if (ag == startag)
@@ -2809,17 +2821,27 @@ xfs_bmap_btalloc(
*/
else
args.minlen = ap->alen;
+
+ /*
+ * set the failure fallback case to look in the selected
+ * AG as the stream may have moved.
+ */
+ if (xfs_inode_is_filestream(ap->ip))
+ ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
} else if (ap->low) {
- args.type = XFS_ALLOCTYPE_START_BNO;
+ if (xfs_inode_is_filestream(ap->ip))
+ args.type = XFS_ALLOCTYPE_FIRST_AG;
+ else
+ args.type = XFS_ALLOCTYPE_START_BNO;
args.total = args.minlen = ap->minlen;
} else {
args.type = XFS_ALLOCTYPE_NEAR_BNO;
args.total = ap->total;
args.minlen = ap->minlen;
}
- if (unlikely(ap->userdata && ap->ip->i_d.di_extsize &&
- (ap->ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE))) {
- args.prod = ap->ip->i_d.di_extsize;
+ /* apply extent size hints if obtained earlier */
+ if (unlikely(align)) {
+ args.prod = align;
if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
args.mod = (xfs_extlen_t)(args.prod - args.mod);
} else if (mp->m_sb.sb_blocksize >= NBPP) {
@@ -3051,9 +3073,6 @@ xfs_bmap_del_extent(
xfs_bmbt_rec_t *ep; /* current extent entry pointer */
int error; /* error return value */
int flags; /* inode logging flags */
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_bmap_del_extent";
-#endif
xfs_bmbt_irec_t got; /* current extent entry */
xfs_fileoff_t got_endoff; /* first offset past got */
int i; /* temp state */
@@ -3147,7 +3166,7 @@ xfs_bmap_del_extent(
/*
* Matches the whole extent. Delete the entry.
*/
- xfs_bmap_trace_delete(fname, "3", ip, idx, 1, whichfork);
+ XFS_BMAP_TRACE_DELETE("3", ip, idx, 1, whichfork);
xfs_iext_remove(ifp, idx, 1);
ifp->if_lastex = idx;
if (delay)
@@ -3168,7 +3187,7 @@ xfs_bmap_del_extent(
/*
* Deleting the first part of the extent.
*/
- xfs_bmap_trace_pre_update(fname, "2", ip, idx, whichfork);
+ XFS_BMAP_TRACE_PRE_UPDATE("2", ip, idx, whichfork);
xfs_bmbt_set_startoff(ep, del_endoff);
temp = got.br_blockcount - del->br_blockcount;
xfs_bmbt_set_blockcount(ep, temp);
@@ -3177,13 +3196,13 @@ xfs_bmap_del_extent(
temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
da_old);
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
- xfs_bmap_trace_post_update(fname, "2", ip, idx,
+ XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx,
whichfork);
da_new = temp;
break;
}
xfs_bmbt_set_startblock(ep, del_endblock);
- xfs_bmap_trace_post_update(fname, "2", ip, idx, whichfork);
+ XFS_BMAP_TRACE_POST_UPDATE("2", ip, idx, whichfork);
if (!cur) {
flags |= XFS_ILOG_FEXT(whichfork);
break;
@@ -3199,19 +3218,19 @@ xfs_bmap_del_extent(
* Deleting the last part of the extent.
*/
temp = got.br_blockcount - del->br_blockcount;
- xfs_bmap_trace_pre_update(fname, "1", ip, idx, whichfork);
+ XFS_BMAP_TRACE_PRE_UPDATE("1", ip, idx, whichfork);
xfs_bmbt_set_blockcount(ep, temp);
ifp->if_lastex = idx;
if (delay) {
temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
da_old);
xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
- xfs_bmap_trace_post_update(fname, "1", ip, idx,
+ XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx,
whichfork);
da_new = temp;
break;
}
- xfs_bmap_trace_post_update(fname, "1", ip, idx, whichfork);
+ XFS_BMAP_TRACE_POST_UPDATE("1", ip, idx, whichfork);
if (!cur) {
flags |= XFS_ILOG_FEXT(whichfork);
break;
@@ -3228,7 +3247,7 @@ xfs_bmap_del_extent(
* Deleting the middle of the extent.
*/
temp = del->br_startoff - got.br_startoff;
- xfs_bmap_trace_pre_update(fname, "0", ip, idx, whichfork);
+ XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, whichfork);
xfs_bmbt_set_blockcount(ep, temp);
new.br_startoff = del_endoff;
temp2 = got_endoff - del_endoff;
@@ -3315,8 +3334,8 @@ xfs_bmap_del_extent(
}
}
}
- xfs_bmap_trace_post_update(fname, "0", ip, idx, whichfork);
- xfs_bmap_trace_insert(fname, "0", ip, idx + 1, 1, &new, NULL,
+ XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, whichfork);
+ XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 1, &new, NULL,
whichfork);
xfs_iext_insert(ifp, idx + 1, 1, &new);
ifp->if_lastex = idx + 1;
@@ -3556,9 +3575,6 @@ xfs_bmap_local_to_extents(
{
int error; /* error return value */
int flags; /* logging flags returned */
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_bmap_local_to_extents";
-#endif
xfs_ifork_t *ifp; /* inode fork pointer */
/*
@@ -3613,7 +3629,7 @@ xfs_bmap_local_to_extents(
xfs_iext_add(ifp, 0, 1);
ep = xfs_iext_get_ext(ifp, 0);
xfs_bmbt_set_allf(ep, 0, args.fsbno, 1, XFS_EXT_NORM);
- xfs_bmap_trace_post_update(fname, "new", ip, 0, whichfork);
+ XFS_BMAP_TRACE_POST_UPDATE("new", ip, 0, whichfork);
XFS_IFORK_NEXT_SET(ip, whichfork, 1);
ip->i_d.di_nblocks = 1;
XFS_TRANS_MOD_DQUOT_BYINO(args.mp, tp, ip,
@@ -3736,7 +3752,7 @@ ktrace_t *xfs_bmap_trace_buf;
STATIC void
xfs_bmap_trace_addentry(
int opcode, /* operation */
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(ies) */
@@ -3795,7 +3811,7 @@ xfs_bmap_trace_addentry(
*/
STATIC void
xfs_bmap_trace_delete(
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(entries) deleted */
@@ -3817,7 +3833,7 @@ xfs_bmap_trace_delete(
*/
STATIC void
xfs_bmap_trace_insert(
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(entries) inserted */
@@ -3846,7 +3862,7 @@ xfs_bmap_trace_insert(
*/
STATIC void
xfs_bmap_trace_post_update(
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry updated */
@@ -3864,7 +3880,7 @@ xfs_bmap_trace_post_update(
*/
STATIC void
xfs_bmap_trace_pre_update(
- char *fname, /* function name */
+ const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry to be updated */
@@ -4481,9 +4497,6 @@ xfs_bmap_read_extents(
xfs_buf_t *bp; /* buffer for "block" */
int error; /* error return value */
xfs_exntfmt_t exntf; /* XFS_EXTFMT_NOSTATE, if checking */
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_bmap_read_extents";
-#endif
xfs_extnum_t i, j; /* index into the extents list */
xfs_ifork_t *ifp; /* fork structure */
int level; /* btree level, for checking */
@@ -4600,7 +4613,7 @@ xfs_bmap_read_extents(
}
ASSERT(i == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)));
ASSERT(i == XFS_IFORK_NEXTENTS(ip, whichfork));
- xfs_bmap_trace_exlist(fname, ip, i, whichfork);
+ XFS_BMAP_TRACE_EXLIST(ip, i, whichfork);
return 0;
error0:
xfs_trans_brelse(tp, bp);
@@ -4613,7 +4626,7 @@ error0:
*/
void
xfs_bmap_trace_exlist(
- char *fname, /* function name */
+ const char *fname, /* function name */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t cnt, /* count of entries in the list */
int whichfork) /* data or attr fork */
@@ -4628,7 +4641,7 @@ xfs_bmap_trace_exlist(
for (idx = 0; idx < cnt; idx++) {
ep = xfs_iext_get_ext(ifp, idx);
xfs_bmbt_get_all(ep, &s);
- xfs_bmap_trace_insert(fname, "exlist", ip, idx, 1, &s, NULL,
+ XFS_BMAP_TRACE_INSERT("exlist", ip, idx, 1, &s, NULL,
whichfork);
}
}
@@ -4868,12 +4881,7 @@ xfs_bmapi(
xfs_extlen_t extsz;
/* Figure out the extent size, adjust alen */
- if (rt) {
- if (!(extsz = ip->i_d.di_extsize))
- extsz = mp->m_sb.sb_rextsize;
- } else {
- extsz = ip->i_d.di_extsize;
- }
+ extsz = xfs_get_extsz_hint(ip);
if (extsz) {
error = xfs_bmap_extsize_align(mp,
&got, &prev, extsz,
@@ -5219,10 +5227,10 @@ xfs_bmapi(
* Else go on to the next record.
*/
ep = xfs_iext_get_ext(ifp, ++lastx);
- if (lastx >= nextents) {
+ prev = got;
+ if (lastx >= nextents)
eof = 1;
- prev = got;
- } else
+ else
xfs_bmbt_get_all(ep, &got);
}
ifp->if_lastex = lastx;
@@ -5813,8 +5821,7 @@ xfs_getbmap(
ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
return XFS_ERROR(EINVAL);
if (whichfork == XFS_DATA_FORK) {
- if ((ip->i_d.di_extsize && (ip->i_d.di_flags &
- (XFS_DIFLAG_REALTIME|XFS_DIFLAG_EXTSIZE))) ||
+ if (xfs_get_extsz_hint(ip) ||
ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
prealloced = 1;
fixlen = XFS_MAXIOFFSET(mp);
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 4f24c7e39b3..524b1c9d524 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -144,12 +144,14 @@ extern ktrace_t *xfs_bmap_trace_buf;
*/
void
xfs_bmap_trace_exlist(
- char *fname, /* function name */
+ const char *fname, /* function name */
struct xfs_inode *ip, /* incore inode pointer */
xfs_extnum_t cnt, /* count of entries in list */
int whichfork); /* data or attr fork */
+#define XFS_BMAP_TRACE_EXLIST(ip,c,w) \
+ xfs_bmap_trace_exlist(__FUNCTION__,ip,c,w)
#else
-#define xfs_bmap_trace_exlist(f,ip,c,w)
+#define XFS_BMAP_TRACE_EXLIST(ip,c,w)
#endif
/*
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 0bf192fea3e..89b891f51cf 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -76,7 +76,7 @@ static char EXIT[] = "exit";
*/
STATIC void
xfs_bmbt_trace_enter(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
char *s,
int type,
@@ -117,7 +117,7 @@ xfs_bmbt_trace_enter(
*/
STATIC void
xfs_bmbt_trace_argbi(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
xfs_buf_t *b,
int i,
@@ -134,7 +134,7 @@ xfs_bmbt_trace_argbi(
*/
STATIC void
xfs_bmbt_trace_argbii(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
xfs_buf_t *b,
int i0,
@@ -153,7 +153,7 @@ xfs_bmbt_trace_argbii(
*/
STATIC void
xfs_bmbt_trace_argfffi(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
xfs_dfiloff_t o,
xfs_dfsbno_t b,
@@ -172,7 +172,7 @@ xfs_bmbt_trace_argfffi(
*/
STATIC void
xfs_bmbt_trace_argi(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
int i,
int line)
@@ -188,7 +188,7 @@ xfs_bmbt_trace_argi(
*/
STATIC void
xfs_bmbt_trace_argifk(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
int i,
xfs_fsblock_t f,
@@ -206,7 +206,7 @@ xfs_bmbt_trace_argifk(
*/
STATIC void
xfs_bmbt_trace_argifr(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
int i,
xfs_fsblock_t f,
@@ -235,7 +235,7 @@ xfs_bmbt_trace_argifr(
*/
STATIC void
xfs_bmbt_trace_argik(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
int i,
xfs_bmbt_key_t *k,
@@ -255,7 +255,7 @@ xfs_bmbt_trace_argik(
*/
STATIC void
xfs_bmbt_trace_cursor(
- char *func,
+ const char *func,
xfs_btree_cur_t *cur,
char *s,
int line)
@@ -274,21 +274,21 @@ xfs_bmbt_trace_cursor(
}
#define XFS_BMBT_TRACE_ARGBI(c,b,i) \
- xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__)
+ xfs_bmbt_trace_argbi(__FUNCTION__, c, b, i, __LINE__)
#define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \
- xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__)
+ xfs_bmbt_trace_argbii(__FUNCTION__, c, b, i, j, __LINE__)
#define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \
- xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
+ xfs_bmbt_trace_argfffi(__FUNCTION__, c, o, b, i, j, __LINE__)
#define XFS_BMBT_TRACE_ARGI(c,i) \
- xfs_bmbt_trace_argi(fname, c, i, __LINE__)
+ xfs_bmbt_trace_argi(__FUNCTION__, c, i, __LINE__)
#define XFS_BMBT_TRACE_ARGIFK(c,i,f,s) \
- xfs_bmbt_trace_argifk(fname, c, i, f, s, __LINE__)
+ xfs_bmbt_trace_argifk(__FUNCTION__, c, i, f, s, __LINE__)
#define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \
- xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
+ xfs_bmbt_trace_argifr(__FUNCTION__, c, i, f, r, __LINE__)
#define XFS_BMBT_TRACE_ARGIK(c,i,k) \
- xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
+ xfs_bmbt_trace_argik(__FUNCTION__, c, i, k, __LINE__)
#define XFS_BMBT_TRACE_CURSOR(c,s) \
- xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
+ xfs_bmbt_trace_cursor(__FUNCTION__, c, s, __LINE__)
#else
#define XFS_BMBT_TRACE_ARGBI(c,b,i)
#define XFS_BMBT_TRACE_ARGBII(c,b,i,j)
@@ -318,9 +318,6 @@ xfs_bmbt_delrec(
xfs_fsblock_t bno; /* fs-relative block number */
xfs_buf_t *bp; /* buffer for block */
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_delrec";
-#endif
int i; /* loop counter */
int j; /* temp state */
xfs_bmbt_key_t key; /* bmap btree key */
@@ -694,9 +691,6 @@ xfs_bmbt_insrec(
xfs_bmbt_block_t *block; /* bmap btree block */
xfs_buf_t *bp; /* buffer for block */
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_insrec";
-#endif
int i; /* loop index */
xfs_bmbt_key_t key; /* bmap btree key */
xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */
@@ -881,9 +875,6 @@ xfs_bmbt_killroot(
#ifdef DEBUG
int error;
#endif
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_killroot";
-#endif
int i;
xfs_bmbt_key_t *kp;
xfs_inode_t *ip;
@@ -973,9 +964,6 @@ xfs_bmbt_log_keys(
int kfirst,
int klast)
{
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_log_keys";
-#endif
xfs_trans_t *tp;
XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
@@ -1012,9 +1000,6 @@ xfs_bmbt_log_ptrs(
int pfirst,
int plast)
{
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_log_ptrs";
-#endif
xfs_trans_t *tp;
XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
@@ -1055,9 +1040,6 @@ xfs_bmbt_lookup(
xfs_daddr_t d;
xfs_sfiloff_t diff;
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_lookup";
-#endif
xfs_fsblock_t fsbno=0;
int high;
int i;
@@ -1195,9 +1177,6 @@ xfs_bmbt_lshift(
int *stat) /* success/failure */
{
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_lshift";
-#endif
#ifdef DEBUG
int i; /* loop counter */
#endif
@@ -1331,9 +1310,6 @@ xfs_bmbt_rshift(
int *stat) /* success/failure */
{
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_rshift";
-#endif
int i; /* loop counter */
xfs_bmbt_key_t key; /* bmap btree key */
xfs_buf_t *lbp; /* left buffer pointer */
@@ -1492,9 +1468,6 @@ xfs_bmbt_split(
{
xfs_alloc_arg_t args; /* block allocation args */
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_split";
-#endif
int i; /* loop counter */
xfs_fsblock_t lbno; /* left sibling block number */
xfs_buf_t *lbp; /* left buffer pointer */
@@ -1641,9 +1614,6 @@ xfs_bmbt_updkey(
#ifdef DEBUG
int error;
#endif
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_updkey";
-#endif
xfs_bmbt_key_t *kp;
int ptr;
@@ -1712,9 +1682,6 @@ xfs_bmbt_decrement(
xfs_bmbt_block_t *block;
xfs_buf_t *bp;
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_decrement";
-#endif
xfs_fsblock_t fsbno;
int lev;
xfs_mount_t *mp;
@@ -1785,9 +1752,6 @@ xfs_bmbt_delete(
int *stat) /* success/failure */
{
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_delete";
-#endif
int i;
int level;
@@ -2000,9 +1964,6 @@ xfs_bmbt_increment(
xfs_bmbt_block_t *block;
xfs_buf_t *bp;
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_increment";
-#endif
xfs_fsblock_t fsbno;
int lev;
xfs_mount_t *mp;
@@ -2080,9 +2041,6 @@ xfs_bmbt_insert(
int *stat) /* success/failure */
{
int error; /* error return value */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_insert";
-#endif
int i;
int level;
xfs_fsblock_t nbno;
@@ -2142,9 +2100,6 @@ xfs_bmbt_log_block(
int fields)
{
int first;
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_log_block";
-#endif
int last;
xfs_trans_t *tp;
static const short offsets[] = {
@@ -2181,9 +2136,6 @@ xfs_bmbt_log_recs(
{
xfs_bmbt_block_t *block;
int first;
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_log_recs";
-#endif
int last;
xfs_bmbt_rec_t *rp;
xfs_trans_t *tp;
@@ -2245,9 +2197,6 @@ xfs_bmbt_newroot(
xfs_bmbt_key_t *ckp; /* child key pointer */
xfs_bmbt_ptr_t *cpp; /* child ptr pointer */
int error; /* error return code */
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_newroot";
-#endif
#ifdef DEBUG
int i; /* loop counter */
#endif
@@ -2630,9 +2579,6 @@ xfs_bmbt_update(
xfs_bmbt_block_t *block;
xfs_buf_t *bp;
int error;
-#ifdef XFS_BMBT_TRACE
- static char fname[] = "xfs_bmbt_update";
-#endif
xfs_bmbt_key_t key;
int ptr;
xfs_bmbt_rec_t *rp;
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 4e27d55a1e7..6e40a0a198f 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -444,30 +444,14 @@ xfs_btree_setbuf(
/*
* Min and max functions for extlen, agblock, fileoff, and filblks types.
*/
-#define XFS_EXTLEN_MIN(a,b) \
- ((xfs_extlen_t)(a) < (xfs_extlen_t)(b) ? \
- (xfs_extlen_t)(a) : (xfs_extlen_t)(b))
-#define XFS_EXTLEN_MAX(a,b) \
- ((xfs_extlen_t)(a) > (xfs_extlen_t)(b) ? \
- (xfs_extlen_t)(a) : (xfs_extlen_t)(b))
-#define XFS_AGBLOCK_MIN(a,b) \
- ((xfs_agblock_t)(a) < (xfs_agblock_t)(b) ? \
- (xfs_agblock_t)(a) : (xfs_agblock_t)(b))
-#define XFS_AGBLOCK_MAX(a,b) \
- ((xfs_agblock_t)(a) > (xfs_agblock_t)(b) ? \
- (xfs_agblock_t)(a) : (xfs_agblock_t)(b))
-#define XFS_FILEOFF_MIN(a,b) \
- ((xfs_fileoff_t)(a) < (xfs_fileoff_t)(b) ? \
- (xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
-#define XFS_FILEOFF_MAX(a,b) \
- ((xfs_fileoff_t)(a) > (xfs_fileoff_t)(b) ? \
- (xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
-#define XFS_FILBLKS_MIN(a,b) \
- ((xfs_filblks_t)(a) < (xfs_filblks_t)(b) ? \
- (xfs_filblks_t)(a) : (xfs_filblks_t)(b))
-#define XFS_FILBLKS_MAX(a,b) \
- ((xfs_filblks_t)(a) > (xfs_filblks_t)(b) ? \
- (xfs_filblks_t)(a) : (xfs_filblks_t)(b))
+#define XFS_EXTLEN_MIN(a,b) min_t(xfs_extlen_t, (a), (b))
+#define XFS_EXTLEN_MAX(a,b) max_t(xfs_extlen_t, (a), (b))
+#define XFS_AGBLOCK_MIN(a,b) min_t(xfs_agblock_t, (a), (b))
+#define XFS_AGBLOCK_MAX(a,b) max_t(xfs_agblock_t, (a), (b))
+#define XFS_FILEOFF_MIN(a,b) min_t(xfs_fileoff_t, (a), (b))
+#define XFS_FILEOFF_MAX(a,b) max_t(xfs_fileoff_t, (a), (b))
+#define XFS_FILBLKS_MIN(a,b) min_t(xfs_filblks_t, (a), (b))
+#define XFS_FILBLKS_MAX(a,b) max_t(xfs_filblks_t, (a), (b))
#define XFS_FSB_SANITY_CHECK(mp,fsb) \
(XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 6c1bddc04e3..b0667cb27d6 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -580,8 +580,8 @@ xfs_buf_item_unlock(
* If the buf item isn't tracking any data, free it.
* Otherwise, if XFS_BLI_HOLD is set clear it.
*/
- if (xfs_count_bits(bip->bli_format.blf_data_map,
- bip->bli_format.blf_map_size, 0) == 0) {
+ if (xfs_bitmap_empty(bip->bli_format.blf_data_map,
+ bip->bli_format.blf_map_size)) {
xfs_buf_item_relse(bp);
} else if (hold) {
bip->bli_flags &= ~XFS_BLI_HOLD;
diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h
index 5b7eb81453b..f89196cb08d 100644
--- a/fs/xfs/xfs_clnt.h
+++ b/fs/xfs/xfs_clnt.h
@@ -99,5 +99,7 @@ struct xfs_mount_args {
*/
#define XFSMNT2_COMPAT_IOSIZE 0x00000001 /* don't report large preferred
* I/O size in stat(2) */
+#define XFSMNT2_FILESTREAMS 0x00000002 /* enable the filestreams
+ * allocator */
#endif /* __XFS_CLNT_H__ */
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index b33826961c4..fefd0116bac 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -257,6 +257,7 @@ typedef enum xfs_dinode_fmt
#define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */
#define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */
#define XFS_DIFLAG_NODEFRAG_BIT 13 /* do not reorganize/defragment */
+#define XFS_DIFLAG_FILESTREAM_BIT 14 /* use filestream allocator */
#define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT)
#define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT)
#define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT)
@@ -271,12 +272,13 @@ typedef enum xfs_dinode_fmt
#define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT)
#define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
#define XFS_DIFLAG_NODEFRAG (1 << XFS_DIFLAG_NODEFRAG_BIT)
+#define XFS_DIFLAG_FILESTREAM (1 << XFS_DIFLAG_FILESTREAM_BIT)
#define XFS_DIFLAG_ANY \
(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
- XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG)
+ XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM)
#endif /* __XFS_DINODE_H__ */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 8e8e5279334..29e091914df 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -55,9 +55,9 @@ xfs_dir_mount(
XFS_MAX_BLOCKSIZE);
mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
- mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp));
- mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
- mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp));
+ mp->m_dirdatablk = xfs_dir2_db_to_da(mp, XFS_DIR2_DATA_FIRSTDB(mp));
+ mp->m_dirleafblk = xfs_dir2_db_to_da(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
+ mp->m_dirfreeblk = xfs_dir2_db_to_da(mp, XFS_DIR2_FREE_FIRSTDB(mp));
mp->m_attr_node_ents =
(mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) /
(uint)sizeof(xfs_da_node_entry_t);
@@ -554,7 +554,7 @@ xfs_dir2_grow_inode(
*/
if (mapp != &map)
kmem_free(mapp, sizeof(*mapp) * count);
- *dbp = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)bno);
+ *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
/*
* Update file's size if this is the data space and it grew.
*/
@@ -706,7 +706,7 @@ xfs_dir2_shrink_inode(
dp = args->dp;
mp = dp->i_mount;
tp = args->trans;
- da = XFS_DIR2_DB_TO_DA(mp, db);
+ da = xfs_dir2_db_to_da(mp, db);
/*
* Unmap the fsblock(s).
*/
@@ -742,7 +742,7 @@ xfs_dir2_shrink_inode(
/*
* If the block isn't the last one in the directory, we're done.
*/
- if (dp->i_d.di_size > XFS_DIR2_DB_OFF_TO_BYTE(mp, db + 1, 0))
+ if (dp->i_d.di_size > xfs_dir2_db_off_to_byte(mp, db + 1, 0))
return 0;
bno = da;
if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 3accc1dcd6c..e4df1aaae2a 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -115,13 +115,13 @@ xfs_dir2_block_addname(
xfs_da_brelse(tp, bp);
return XFS_ERROR(EFSCORRUPTED);
}
- len = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+ len = xfs_dir2_data_entsize(args->namelen);
/*
* Set up pointers to parts of the block.
*/
bf = block->hdr.bestfree;
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, block);
+ blp = xfs_dir2_block_leaf_p(btp);
/*
* No stale entries? Need space for entry and new leaf.
*/
@@ -396,7 +396,7 @@ xfs_dir2_block_addname(
* Fill in the leaf entry.
*/
blp[mid].hashval = cpu_to_be32(args->hashval);
- blp[mid].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
+ blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
(char *)dep - (char *)block));
xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
/*
@@ -411,7 +411,7 @@ xfs_dir2_block_addname(
dep->inumber = cpu_to_be64(args->inumber);
dep->namelen = args->namelen;
memcpy(dep->name, args->name, args->namelen);
- tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+ tagp = xfs_dir2_data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)block);
/*
* Clean up the bestfree array and log the header, tail, and entry.
@@ -455,7 +455,7 @@ xfs_dir2_block_getdents(
/*
* If the block number in the offset is out of range, we're done.
*/
- if (XFS_DIR2_DATAPTR_TO_DB(mp, uio->uio_offset) > mp->m_dirdatablk) {
+ if (xfs_dir2_dataptr_to_db(mp, uio->uio_offset) > mp->m_dirdatablk) {
*eofp = 1;
return 0;
}
@@ -471,15 +471,15 @@ xfs_dir2_block_getdents(
* Extract the byte offset we start at from the seek pointer.
* We'll skip entries before this.
*/
- wantoff = XFS_DIR2_DATAPTR_TO_OFF(mp, uio->uio_offset);
+ wantoff = xfs_dir2_dataptr_to_off(mp, uio->uio_offset);
block = bp->data;
xfs_dir2_data_check(dp, bp);
/*
* Set up values for the loop.
*/
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+ btp = xfs_dir2_block_tail_p(mp, block);
ptr = (char *)block->u;
- endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
+ endptr = (char *)xfs_dir2_block_leaf_p(btp);
p.dbp = dbp;
p.put = put;
p.uio = uio;
@@ -502,7 +502,7 @@ xfs_dir2_block_getdents(
/*
* Bump pointer for the next iteration.
*/
- ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+ ptr += xfs_dir2_data_entsize(dep->namelen);
/*
* The entry is before the desired starting point, skip it.
*/
@@ -513,7 +513,7 @@ xfs_dir2_block_getdents(
*/
p.namelen = dep->namelen;
- p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+ p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
ptr - (char *)block);
p.ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
@@ -531,7 +531,7 @@ xfs_dir2_block_getdents(
*/
if (!p.done) {
uio->uio_offset =
- XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+ xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
(char *)dep - (char *)block);
xfs_da_brelse(tp, bp);
return error;
@@ -545,7 +545,7 @@ xfs_dir2_block_getdents(
*eofp = 1;
uio->uio_offset =
- XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
+ xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
xfs_da_brelse(tp, bp);
@@ -569,8 +569,8 @@ xfs_dir2_block_log_leaf(
mp = tp->t_mountp;
block = bp->data;
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, block);
+ blp = xfs_dir2_block_leaf_p(btp);
xfs_da_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)block),
(uint)((char *)&blp[last + 1] - (char *)block - 1));
}
@@ -589,7 +589,7 @@ xfs_dir2_block_log_tail(
mp = tp->t_mountp;
block = bp->data;
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+ btp = xfs_dir2_block_tail_p(mp, block);
xfs_da_log_buf(tp, bp, (uint)((char *)btp - (char *)block),
(uint)((char *)(btp + 1) - (char *)block - 1));
}
@@ -623,13 +623,13 @@ xfs_dir2_block_lookup(
mp = dp->i_mount;
block = bp->data;
xfs_dir2_data_check(dp, bp);
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, block);
+ blp = xfs_dir2_block_leaf_p(btp);
/*
* Get the offset from the leaf entry, to point to the data.
*/
dep = (xfs_dir2_data_entry_t *)
- ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
+ ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
/*
* Fill in inode number, release the block.
*/
@@ -675,8 +675,8 @@ xfs_dir2_block_lookup_int(
ASSERT(bp != NULL);
block = bp->data;
xfs_dir2_data_check(dp, bp);
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, block);
+ blp = xfs_dir2_block_leaf_p(btp);
/*
* Loop doing a binary search for our hash value.
* Find our entry, ENOENT if it's not there.
@@ -713,7 +713,7 @@ xfs_dir2_block_lookup_int(
* Get pointer to the entry from the leaf.
*/
dep = (xfs_dir2_data_entry_t *)
- ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
+ ((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
/*
* Compare, if it's right give back buffer & entry number.
*/
@@ -768,20 +768,20 @@ xfs_dir2_block_removename(
tp = args->trans;
mp = dp->i_mount;
block = bp->data;
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, block);
+ blp = xfs_dir2_block_leaf_p(btp);
/*
* Point to the data entry using the leaf entry.
*/
dep = (xfs_dir2_data_entry_t *)
- ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
+ ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
/*
* Mark the data entry's space free.
*/
needlog = needscan = 0;
xfs_dir2_data_make_free(tp, bp,
(xfs_dir2_data_aoff_t)((char *)dep - (char *)block),
- XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
+ xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
/*
* Fix up the block tail.
*/
@@ -843,13 +843,13 @@ xfs_dir2_block_replace(
dp = args->dp;
mp = dp->i_mount;
block = bp->data;
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, block);
+ blp = xfs_dir2_block_leaf_p(btp);
/*
* Point to the data entry we need to change.
*/
dep = (xfs_dir2_data_entry_t *)
- ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
+ ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address)));
ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
/*
* Change the inode number to the new value.
@@ -912,7 +912,7 @@ xfs_dir2_leaf_to_block(
mp = dp->i_mount;
leaf = lbp->data;
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
/*
* If there are data blocks other than the first one, take this
* opportunity to remove trailing empty data blocks that may have
@@ -920,7 +920,7 @@ xfs_dir2_leaf_to_block(
* These will show up in the leaf bests table.
*/
while (dp->i_d.di_size > mp->m_dirblksize) {
- bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
+ bestsp = xfs_dir2_leaf_bests_p(ltp);
if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
mp->m_dirblksize - (uint)sizeof(block->hdr)) {
if ((error =
@@ -974,14 +974,14 @@ xfs_dir2_leaf_to_block(
/*
* Initialize the block tail.
*/
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+ btp = xfs_dir2_block_tail_p(mp, block);
btp->count = cpu_to_be32(be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale));
btp->stale = 0;
xfs_dir2_block_log_tail(tp, dbp);
/*
* Initialize the block leaf area. We compact out stale entries.
*/
- lep = XFS_DIR2_BLOCK_LEAF_P(btp);
+ lep = xfs_dir2_block_leaf_p(btp);
for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) {
if (be32_to_cpu(leaf->ents[from].address) == XFS_DIR2_NULL_DATAPTR)
continue;
@@ -1067,7 +1067,7 @@ xfs_dir2_sf_to_block(
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
ASSERT(dp->i_df.if_u1.if_data != NULL);
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+ ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
/*
* Copy the directory into the stack buffer.
* Then pitch the incore inode data so we can make extents.
@@ -1119,10 +1119,10 @@ xfs_dir2_sf_to_block(
/*
* Fill in the tail.
*/
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+ btp = xfs_dir2_block_tail_p(mp, block);
btp->count = cpu_to_be32(sfp->hdr.count + 2); /* ., .. */
btp->stale = 0;
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ blp = xfs_dir2_block_leaf_p(btp);
endoffset = (uint)((char *)blp - (char *)block);
/*
* Remove the freespace, we'll manage it.
@@ -1138,25 +1138,25 @@ xfs_dir2_sf_to_block(
dep->inumber = cpu_to_be64(dp->i_ino);
dep->namelen = 1;
dep->name[0] = '.';
- tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+ tagp = xfs_dir2_data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)block);
xfs_dir2_data_log_entry(tp, bp, dep);
blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
- blp[0].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
+ blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
(char *)dep - (char *)block));
/*
* Create entry for ..
*/
dep = (xfs_dir2_data_entry_t *)
((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET);
- dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
+ dep->inumber = cpu_to_be64(xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
dep->namelen = 2;
dep->name[0] = dep->name[1] = '.';
- tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+ tagp = xfs_dir2_data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)block);
xfs_dir2_data_log_entry(tp, bp, dep);
blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
- blp[1].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
+ blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
(char *)dep - (char *)block));
offset = XFS_DIR2_DATA_FIRST_OFFSET;
/*
@@ -1165,7 +1165,7 @@ xfs_dir2_sf_to_block(
if ((i = 0) == sfp->hdr.count)
sfep = NULL;
else
- sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+ sfep = xfs_dir2_sf_firstentry(sfp);
/*
* Need to preserve the existing offset values in the sf directory.
* Insert holes (unused entries) where necessary.
@@ -1177,7 +1177,7 @@ xfs_dir2_sf_to_block(
if (sfep == NULL)
newoffset = endoffset;
else
- newoffset = XFS_DIR2_SF_GET_OFFSET(sfep);
+ newoffset = xfs_dir2_sf_get_offset(sfep);
/*
* There should be a hole here, make one.
*/
@@ -1186,7 +1186,7 @@ xfs_dir2_sf_to_block(
((char *)block + offset);
dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
dup->length = cpu_to_be16(newoffset - offset);
- *XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16(
+ *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(
((char *)dup - (char *)block));
xfs_dir2_data_log_unused(tp, bp, dup);
(void)xfs_dir2_data_freeinsert((xfs_dir2_data_t *)block,
@@ -1198,22 +1198,22 @@ xfs_dir2_sf_to_block(
* Copy a real entry.
*/
dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset);
- dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp,
- XFS_DIR2_SF_INUMBERP(sfep)));
+ dep->inumber = cpu_to_be64(xfs_dir2_sf_get_inumber(sfp,
+ xfs_dir2_sf_inumberp(sfep)));
dep->namelen = sfep->namelen;
memcpy(dep->name, sfep->name, dep->namelen);
- tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+ tagp = xfs_dir2_data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)block);
xfs_dir2_data_log_entry(tp, bp, dep);
blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname(
(char *)sfep->name, sfep->namelen));
- blp[2 + i].address = cpu_to_be32(XFS_DIR2_BYTE_TO_DATAPTR(mp,
+ blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
(char *)dep - (char *)block));
offset = (int)((char *)(tagp + 1) - (char *)block);
if (++i == sfp->hdr.count)
sfep = NULL;
else
- sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+ sfep = xfs_dir2_sf_nextentry(sfp, sfep);
}
/* Done with the temporary buffer */
kmem_free(buf, buf_len);
diff --git a/fs/xfs/xfs_dir2_block.h b/fs/xfs/xfs_dir2_block.h
index 6722effd0b2..e7c2606161e 100644
--- a/fs/xfs/xfs_dir2_block.h
+++ b/fs/xfs/xfs_dir2_block.h
@@ -60,7 +60,6 @@ typedef struct xfs_dir2_block {
/*
* Pointer to the leaf header embedded in a data block (1-block format)
*/
-#define XFS_DIR2_BLOCK_TAIL_P(mp,block) xfs_dir2_block_tail_p(mp,block)
static inline xfs_dir2_block_tail_t *
xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block)
{
@@ -71,7 +70,6 @@ xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block)
/*
* Pointer to the leaf entries embedded in a data block (1-block format)
*/
-#define XFS_DIR2_BLOCK_LEAF_P(btp) xfs_dir2_block_leaf_p(btp)
static inline struct xfs_dir2_leaf_entry *
xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
{
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index c211c37ef67..7ebe295bd6d 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -72,8 +72,8 @@ xfs_dir2_data_check(
bf = d->hdr.bestfree;
p = (char *)d->u;
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
- lep = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+ lep = xfs_dir2_block_leaf_p(btp);
endp = (char *)lep;
} else
endp = (char *)d + mp->m_dirblksize;
@@ -107,7 +107,7 @@ xfs_dir2_data_check(
*/
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
ASSERT(lastfree == 0);
- ASSERT(be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)) ==
+ ASSERT(be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) ==
(char *)dup - (char *)d);
dfp = xfs_dir2_data_freefind(d, dup);
if (dfp) {
@@ -131,12 +131,12 @@ xfs_dir2_data_check(
dep = (xfs_dir2_data_entry_t *)p;
ASSERT(dep->namelen != 0);
ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0);
- ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) ==
+ ASSERT(be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) ==
(char *)dep - (char *)d);
count++;
lastfree = 0;
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
- addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+ addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
(xfs_dir2_data_aoff_t)
((char *)dep - (char *)d));
hash = xfs_da_hashname((char *)dep->name, dep->namelen);
@@ -147,7 +147,7 @@ xfs_dir2_data_check(
}
ASSERT(i < be32_to_cpu(btp->count));
}
- p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+ p += xfs_dir2_data_entsize(dep->namelen);
}
/*
* Need to have seen all the entries and all the bestfree slots.
@@ -346,8 +346,8 @@ xfs_dir2_data_freescan(
*/
p = (char *)d->u;
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
- endp = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+ endp = (char *)xfs_dir2_block_leaf_p(btp);
} else
endp = (char *)d + mp->m_dirblksize;
/*
@@ -360,7 +360,7 @@ xfs_dir2_data_freescan(
*/
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
ASSERT((char *)dup - (char *)d ==
- be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
+ be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
xfs_dir2_data_freeinsert(d, dup, loghead);
p += be16_to_cpu(dup->length);
}
@@ -370,8 +370,8 @@ xfs_dir2_data_freescan(
else {
dep = (xfs_dir2_data_entry_t *)p;
ASSERT((char *)dep - (char *)d ==
- be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)));
- p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+ be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)));
+ p += xfs_dir2_data_entsize(dep->namelen);
}
}
}
@@ -402,7 +402,7 @@ xfs_dir2_data_init(
/*
* Get the buffer set up for the block.
*/
- error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, blkno), -1, &bp,
+ error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, blkno), -1, &bp,
XFS_DATA_FORK);
if (error) {
return error;
@@ -427,7 +427,7 @@ xfs_dir2_data_init(
t=mp->m_dirblksize - (uint)sizeof(d->hdr);
d->hdr.bestfree[0].length = cpu_to_be16(t);
dup->length = cpu_to_be16(t);
- *XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16((char *)dup - (char *)d);
+ *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)d);
/*
* Log it and return it.
*/
@@ -452,7 +452,7 @@ xfs_dir2_data_log_entry(
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)d),
- (uint)((char *)(XFS_DIR2_DATA_ENTRY_TAG_P(dep) + 1) -
+ (uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -
(char *)d - 1));
}
@@ -497,8 +497,8 @@ xfs_dir2_data_log_unused(
* Log the end (tag) of the unused entry.
*/
xfs_da_log_buf(tp, bp,
- (uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d),
- (uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d +
+ (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d),
+ (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)d +
sizeof(xfs_dir2_data_off_t) - 1));
}
@@ -535,8 +535,8 @@ xfs_dir2_data_make_free(
xfs_dir2_block_tail_t *btp; /* block tail */
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
- endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, (xfs_dir2_block_t *)d);
+ endptr = (char *)xfs_dir2_block_leaf_p(btp);
}
/*
* If this isn't the start of the block, then back up to
@@ -587,7 +587,7 @@ xfs_dir2_data_make_free(
* Fix up the new big freespace.
*/
be16_add(&prevdup->length, len + be16_to_cpu(postdup->length));
- *XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
+ *xfs_dir2_data_unused_tag_p(prevdup) =
cpu_to_be16((char *)prevdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, prevdup);
if (!needscan) {
@@ -621,7 +621,7 @@ xfs_dir2_data_make_free(
else if (prevdup) {
dfp = xfs_dir2_data_freefind(d, prevdup);
be16_add(&prevdup->length, len);
- *XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
+ *xfs_dir2_data_unused_tag_p(prevdup) =
cpu_to_be16((char *)prevdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, prevdup);
/*
@@ -649,7 +649,7 @@ xfs_dir2_data_make_free(
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
- *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+ *xfs_dir2_data_unused_tag_p(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
@@ -676,7 +676,7 @@ xfs_dir2_data_make_free(
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
newdup->length = cpu_to_be16(len);
- *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+ *xfs_dir2_data_unused_tag_p(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
@@ -712,7 +712,7 @@ xfs_dir2_data_use_free(
ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
ASSERT(offset >= (char *)dup - (char *)d);
ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)d);
- ASSERT((char *)dup - (char *)d == be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
+ ASSERT((char *)dup - (char *)d == be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)));
/*
* Look up the entry in the bestfree table.
*/
@@ -745,7 +745,7 @@ xfs_dir2_data_use_free(
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
newdup->length = cpu_to_be16(oldlen - len);
- *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+ *xfs_dir2_data_unused_tag_p(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
@@ -772,7 +772,7 @@ xfs_dir2_data_use_free(
else if (matchback) {
newdup = dup;
newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
- *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+ *xfs_dir2_data_unused_tag_p(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
@@ -799,13 +799,13 @@ xfs_dir2_data_use_free(
else {
newdup = dup;
newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
- *XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
+ *xfs_dir2_data_unused_tag_p(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
- *XFS_DIR2_DATA_UNUSED_TAG_P(newdup2) =
+ *xfs_dir2_data_unused_tag_p(newdup2) =
cpu_to_be16((char *)newdup2 - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup2);
/*
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
index c94c9099cfb..b816e025273 100644
--- a/fs/xfs/xfs_dir2_data.h
+++ b/fs/xfs/xfs_dir2_data.h
@@ -44,7 +44,7 @@ struct xfs_trans;
#define XFS_DIR2_DATA_SPACE 0
#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
#define XFS_DIR2_DATA_FIRSTDB(mp) \
- XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATA_OFFSET)
+ xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET)
/*
* Offsets of . and .. in data space (always block 0)
@@ -52,9 +52,9 @@ struct xfs_trans;
#define XFS_DIR2_DATA_DOT_OFFSET \
((xfs_dir2_data_aoff_t)sizeof(xfs_dir2_data_hdr_t))
#define XFS_DIR2_DATA_DOTDOT_OFFSET \
- (XFS_DIR2_DATA_DOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(1))
+ (XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1))
#define XFS_DIR2_DATA_FIRST_OFFSET \
- (XFS_DIR2_DATA_DOTDOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(2))
+ (XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2))
/*
* Structures.
@@ -123,7 +123,6 @@ typedef struct xfs_dir2_data {
/*
* Size of a data entry.
*/
-#define XFS_DIR2_DATA_ENTSIZE(n) xfs_dir2_data_entsize(n)
static inline int xfs_dir2_data_entsize(int n)
{
return (int)roundup(offsetof(xfs_dir2_data_entry_t, name[0]) + (n) + \
@@ -133,19 +132,16 @@ static inline int xfs_dir2_data_entsize(int n)
/*
* Pointer to an entry's tag word.
*/
-#define XFS_DIR2_DATA_ENTRY_TAG_P(dep) xfs_dir2_data_entry_tag_p(dep)
static inline __be16 *
xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep)
{
return (__be16 *)((char *)dep +
- XFS_DIR2_DATA_ENTSIZE(dep->namelen) - sizeof(__be16));
+ xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
}
/*
* Pointer to a freespace's tag word.
*/
-#define XFS_DIR2_DATA_UNUSED_TAG_P(dup) \
- xfs_dir2_data_unused_tag_p(dup)
static inline __be16 *
xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup)
{
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index db14ea71459..1b73c9ad646 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -92,7 +92,7 @@ xfs_dir2_block_to_leaf(
if ((error = xfs_da_grow_inode(args, &blkno))) {
return error;
}
- ldb = XFS_DIR2_DA_TO_DB(mp, blkno);
+ ldb = xfs_dir2_da_to_db(mp, blkno);
ASSERT(ldb == XFS_DIR2_LEAF_FIRSTDB(mp));
/*
* Initialize the leaf block, get a buffer for it.
@@ -104,8 +104,8 @@ xfs_dir2_block_to_leaf(
leaf = lbp->data;
block = dbp->data;
xfs_dir2_data_check(dp, dbp);
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, block);
+ blp = xfs_dir2_block_leaf_p(btp);
/*
* Set the counts in the leaf header.
*/
@@ -137,9 +137,9 @@ xfs_dir2_block_to_leaf(
/*
* Set up leaf tail and bests table.
*/
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
ltp->bestcount = cpu_to_be32(1);
- bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
+ bestsp = xfs_dir2_leaf_bests_p(ltp);
bestsp[0] = block->hdr.bestfree[0].length;
/*
* Log the data header and leaf bests table.
@@ -209,9 +209,9 @@ xfs_dir2_leaf_addname(
*/
index = xfs_dir2_leaf_search_hash(args, lbp);
leaf = lbp->data;
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
- bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
- length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+ bestsp = xfs_dir2_leaf_bests_p(ltp);
+ length = xfs_dir2_data_entsize(args->namelen);
/*
* See if there are any entries with the same hash value
* and space in their block for the new entry.
@@ -223,7 +223,7 @@ xfs_dir2_leaf_addname(
index++, lep++) {
if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
continue;
- i = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+ i = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
ASSERT(i < be32_to_cpu(ltp->bestcount));
ASSERT(be16_to_cpu(bestsp[i]) != NULLDATAOFF);
if (be16_to_cpu(bestsp[i]) >= length) {
@@ -378,7 +378,7 @@ xfs_dir2_leaf_addname(
*/
else {
if ((error =
- xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, use_block),
+ xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, use_block),
-1, &dbp, XFS_DATA_FORK))) {
xfs_da_brelse(tp, lbp);
return error;
@@ -407,7 +407,7 @@ xfs_dir2_leaf_addname(
dep->inumber = cpu_to_be64(args->inumber);
dep->namelen = args->namelen;
memcpy(dep->name, args->name, dep->namelen);
- tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+ tagp = xfs_dir2_data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)data);
/*
* Need to scan fix up the bestfree table.
@@ -529,7 +529,7 @@ xfs_dir2_leaf_addname(
* Fill in the new leaf entry.
*/
lep->hashval = cpu_to_be32(args->hashval);
- lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp, use_block,
+ lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, use_block,
be16_to_cpu(*tagp)));
/*
* Log the leaf fields and give up the buffers.
@@ -567,13 +567,13 @@ xfs_dir2_leaf_check(
* Should factor in the size of the bests table as well.
* We can deduce a value for that from di_size.
*/
- ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp));
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+ ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
/*
* Leaves and bests don't overlap.
*/
ASSERT((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <=
- (char *)XFS_DIR2_LEAF_BESTS_P(ltp));
+ (char *)xfs_dir2_leaf_bests_p(ltp));
/*
* Check hash value order, count stale entries.
*/
@@ -815,12 +815,12 @@ xfs_dir2_leaf_getdents(
* Inside the loop we keep the main offset value as a byte offset
* in the directory file.
*/
- curoff = XFS_DIR2_DATAPTR_TO_BYTE(mp, uio->uio_offset);
+ curoff = xfs_dir2_dataptr_to_byte(mp, uio->uio_offset);
/*
* Force this conversion through db so we truncate the offset
* down to get the start of the data block.
*/
- map_off = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, curoff));
+ map_off = xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, curoff));
/*
* Loop over directory entries until we reach the end offset.
* Get more blocks and readahead as necessary.
@@ -870,7 +870,7 @@ xfs_dir2_leaf_getdents(
*/
if (1 + ra_want > map_blocks &&
map_off <
- XFS_DIR2_BYTE_TO_DA(mp, XFS_DIR2_LEAF_OFFSET)) {
+ xfs_dir2_byte_to_da(mp, XFS_DIR2_LEAF_OFFSET)) {
/*
* Get more bmaps, fill in after the ones
* we already have in the table.
@@ -878,7 +878,7 @@ xfs_dir2_leaf_getdents(
nmap = map_size - map_valid;
error = xfs_bmapi(tp, dp,
map_off,
- XFS_DIR2_BYTE_TO_DA(mp,
+ xfs_dir2_byte_to_da(mp,
XFS_DIR2_LEAF_OFFSET) - map_off,
XFS_BMAPI_METADATA, NULL, 0,
&map[map_valid], &nmap, NULL, NULL);
@@ -903,7 +903,7 @@ xfs_dir2_leaf_getdents(
map[map_valid + nmap - 1].br_blockcount;
else
map_off =
- XFS_DIR2_BYTE_TO_DA(mp,
+ xfs_dir2_byte_to_da(mp,
XFS_DIR2_LEAF_OFFSET);
/*
* Look for holes in the mapping, and
@@ -931,14 +931,14 @@ xfs_dir2_leaf_getdents(
* No valid mappings, so no more data blocks.
*/
if (!map_valid) {
- curoff = XFS_DIR2_DA_TO_BYTE(mp, map_off);
+ curoff = xfs_dir2_da_to_byte(mp, map_off);
break;
}
/*
* Read the directory block starting at the first
* mapping.
*/
- curdb = XFS_DIR2_DA_TO_DB(mp, map->br_startoff);
+ curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
error = xfs_da_read_buf(tp, dp, map->br_startoff,
map->br_blockcount >= mp->m_dirblkfsbs ?
XFS_FSB_TO_DADDR(mp, map->br_startblock) :
@@ -1014,7 +1014,7 @@ xfs_dir2_leaf_getdents(
/*
* Having done a read, we need to set a new offset.
*/
- newoff = XFS_DIR2_DB_OFF_TO_BYTE(mp, curdb, 0);
+ newoff = xfs_dir2_db_off_to_byte(mp, curdb, 0);
/*
* Start of the current block.
*/
@@ -1024,7 +1024,7 @@ xfs_dir2_leaf_getdents(
* Make sure we're in the right block.
*/
else if (curoff > newoff)
- ASSERT(XFS_DIR2_BYTE_TO_DB(mp, curoff) ==
+ ASSERT(xfs_dir2_byte_to_db(mp, curoff) ==
curdb);
data = bp->data;
xfs_dir2_data_check(dp, bp);
@@ -1032,7 +1032,7 @@ xfs_dir2_leaf_getdents(
* Find our position in the block.
*/
ptr = (char *)&data->u;
- byteoff = XFS_DIR2_BYTE_TO_OFF(mp, curoff);
+ byteoff = xfs_dir2_byte_to_off(mp, curoff);
/*
* Skip past the header.
*/
@@ -1054,15 +1054,15 @@ xfs_dir2_leaf_getdents(
}
dep = (xfs_dir2_data_entry_t *)ptr;
length =
- XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+ xfs_dir2_data_entsize(dep->namelen);
ptr += length;
}
/*
* Now set our real offset.
*/
curoff =
- XFS_DIR2_DB_OFF_TO_BYTE(mp,
- XFS_DIR2_BYTE_TO_DB(mp, curoff),
+ xfs_dir2_db_off_to_byte(mp,
+ xfs_dir2_byte_to_db(mp, curoff),
(char *)ptr - (char *)data);
if (ptr >= (char *)data + mp->m_dirblksize) {
continue;
@@ -1091,9 +1091,9 @@ xfs_dir2_leaf_getdents(
p->namelen = dep->namelen;
- length = XFS_DIR2_DATA_ENTSIZE(p->namelen);
+ length = xfs_dir2_data_entsize(p->namelen);
- p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length);
+ p->cook = xfs_dir2_byte_to_dataptr(mp, curoff + length);
p->ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
@@ -1121,10 +1121,10 @@ xfs_dir2_leaf_getdents(
* All done. Set output offset value to current offset.
*/
*eofp = eof;
- if (curoff > XFS_DIR2_DATAPTR_TO_BYTE(mp, XFS_DIR2_MAX_DATAPTR))
+ if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
uio->uio_offset = XFS_DIR2_MAX_DATAPTR;
else
- uio->uio_offset = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff);
+ uio->uio_offset = xfs_dir2_byte_to_dataptr(mp, curoff);
kmem_free(map, map_size * sizeof(*map));
kmem_free(p, sizeof(*p));
if (bp)
@@ -1159,7 +1159,7 @@ xfs_dir2_leaf_init(
/*
* Get the buffer for the block.
*/
- error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, bno), -1, &bp,
+ error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp,
XFS_DATA_FORK);
if (error) {
return error;
@@ -1181,7 +1181,7 @@ xfs_dir2_leaf_init(
* the block.
*/
if (magic == XFS_DIR2_LEAF1_MAGIC) {
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
ltp->bestcount = 0;
xfs_dir2_leaf_log_tail(tp, bp);
}
@@ -1206,9 +1206,9 @@ xfs_dir2_leaf_log_bests(
leaf = bp->data;
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
- ltp = XFS_DIR2_LEAF_TAIL_P(tp->t_mountp, leaf);
- firstb = XFS_DIR2_LEAF_BESTS_P(ltp) + first;
- lastb = XFS_DIR2_LEAF_BESTS_P(ltp) + last;
+ ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf);
+ firstb = xfs_dir2_leaf_bests_p(ltp) + first;
+ lastb = xfs_dir2_leaf_bests_p(ltp) + last;
xfs_da_log_buf(tp, bp, (uint)((char *)firstb - (char *)leaf),
(uint)((char *)lastb - (char *)leaf + sizeof(*lastb) - 1));
}
@@ -1268,7 +1268,7 @@ xfs_dir2_leaf_log_tail(
mp = tp->t_mountp;
leaf = bp->data;
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAF1_MAGIC);
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
xfs_da_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf),
(uint)(mp->m_dirblksize - 1));
}
@@ -1312,7 +1312,7 @@ xfs_dir2_leaf_lookup(
*/
dep = (xfs_dir2_data_entry_t *)
((char *)dbp->data +
- XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
+ xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
/*
* Return the found inode number.
*/
@@ -1381,7 +1381,7 @@ xfs_dir2_leaf_lookup_int(
/*
* Get the new data block number.
*/
- newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+ newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
/*
* If it's not the same as the old data block number,
* need to pitch the old one and read the new one.
@@ -1391,7 +1391,7 @@ xfs_dir2_leaf_lookup_int(
xfs_da_brelse(tp, dbp);
if ((error =
xfs_da_read_buf(tp, dp,
- XFS_DIR2_DB_TO_DA(mp, newdb), -1, &dbp,
+ xfs_dir2_db_to_da(mp, newdb), -1, &dbp,
XFS_DATA_FORK))) {
xfs_da_brelse(tp, lbp);
return error;
@@ -1404,7 +1404,7 @@ xfs_dir2_leaf_lookup_int(
*/
dep = (xfs_dir2_data_entry_t *)
((char *)dbp->data +
- XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
+ xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
/*
* If it matches then return it.
*/
@@ -1469,20 +1469,20 @@ xfs_dir2_leaf_removename(
* Point to the leaf entry, use that to point to the data entry.
*/
lep = &leaf->ents[index];
- db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+ db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
dep = (xfs_dir2_data_entry_t *)
- ((char *)data + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
+ ((char *)data + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
needscan = needlog = 0;
oldbest = be16_to_cpu(data->hdr.bestfree[0].length);
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
- bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
+ bestsp = xfs_dir2_leaf_bests_p(ltp);
ASSERT(be16_to_cpu(bestsp[db]) == oldbest);
/*
* Mark the former data entry unused.
*/
xfs_dir2_data_make_free(tp, dbp,
(xfs_dir2_data_aoff_t)((char *)dep - (char *)data),
- XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
+ xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
/*
* We just mark the leaf entry stale by putting a null in it.
*/
@@ -1602,7 +1602,7 @@ xfs_dir2_leaf_replace(
*/
dep = (xfs_dir2_data_entry_t *)
((char *)dbp->data +
- XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
+ xfs_dir2_dataptr_to_off(dp->i_mount, be32_to_cpu(lep->address)));
ASSERT(args->inumber != be64_to_cpu(dep->inumber));
/*
* Put the new inode number in, log it.
@@ -1698,7 +1698,7 @@ xfs_dir2_leaf_trim_data(
/*
* Read the offending data block. We need its buffer.
*/
- if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, db), -1, &dbp,
+ if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp,
XFS_DATA_FORK))) {
return error;
}
@@ -1712,7 +1712,7 @@ xfs_dir2_leaf_trim_data(
*/
leaf = lbp->data;
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
ASSERT(be16_to_cpu(data->hdr.bestfree[0].length) ==
mp->m_dirblksize - (uint)sizeof(data->hdr));
ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);
@@ -1727,7 +1727,7 @@ xfs_dir2_leaf_trim_data(
/*
* Eliminate the last bests entry from the table.
*/
- bestsp = XFS_DIR2_LEAF_BESTS_P(ltp);
+ bestsp = xfs_dir2_leaf_bests_p(ltp);
be32_add(&ltp->bestcount, -1);
memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp));
xfs_dir2_leaf_log_tail(tp, lbp);
@@ -1838,12 +1838,12 @@ xfs_dir2_node_to_leaf(
/*
* Set up the leaf tail from the freespace block.
*/
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
ltp->bestcount = free->hdr.nvalid;
/*
* Set up the leaf bests table.
*/
- memcpy(XFS_DIR2_LEAF_BESTS_P(ltp), free->bests,
+ memcpy(xfs_dir2_leaf_bests_p(ltp), free->bests,
be32_to_cpu(ltp->bestcount) * sizeof(leaf->bests[0]));
xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
xfs_dir2_leaf_log_tail(tp, lbp);
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index f57ca116241..70c97f3f815 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -32,7 +32,7 @@ struct xfs_trans;
#define XFS_DIR2_LEAF_SPACE 1
#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
#define XFS_DIR2_LEAF_FIRSTDB(mp) \
- XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_LEAF_OFFSET)
+ xfs_dir2_byte_to_db(mp, XFS_DIR2_LEAF_OFFSET)
/*
* Offset in data space of a data entry.
@@ -82,7 +82,6 @@ typedef struct xfs_dir2_leaf {
* DB blocks here are logical directory block numbers, not filesystem blocks.
*/
-#define XFS_DIR2_MAX_LEAF_ENTS(mp) xfs_dir2_max_leaf_ents(mp)
static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
{
return (int)(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_leaf_hdr_t)) /
@@ -92,7 +91,6 @@ static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
/*
* Get address of the bestcount field in the single-leaf block.
*/
-#define XFS_DIR2_LEAF_TAIL_P(mp,lp) xfs_dir2_leaf_tail_p(mp, lp)
static inline xfs_dir2_leaf_tail_t *
xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp)
{
@@ -104,7 +102,6 @@ xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp)
/*
* Get address of the bests array in the single-leaf block.
*/
-#define XFS_DIR2_LEAF_BESTS_P(ltp) xfs_dir2_leaf_bests_p(ltp)
static inline __be16 *
xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
{
@@ -114,7 +111,6 @@ xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
/*
* Convert dataptr to byte in file space
*/
-#define XFS_DIR2_DATAPTR_TO_BYTE(mp,dp) xfs_dir2_dataptr_to_byte(mp, dp)
static inline xfs_dir2_off_t
xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
{
@@ -124,7 +120,6 @@ xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
/*
* Convert byte in file space to dataptr. It had better be aligned.
*/
-#define XFS_DIR2_BYTE_TO_DATAPTR(mp,by) xfs_dir2_byte_to_dataptr(mp,by)
static inline xfs_dir2_dataptr_t
xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
{
@@ -134,7 +129,6 @@ xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
/*
* Convert byte in space to (DB) block
*/
-#define XFS_DIR2_BYTE_TO_DB(mp,by) xfs_dir2_byte_to_db(mp, by)
static inline xfs_dir2_db_t
xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
{
@@ -145,17 +139,15 @@ xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
/*
* Convert dataptr to a block number
*/
-#define XFS_DIR2_DATAPTR_TO_DB(mp,dp) xfs_dir2_dataptr_to_db(mp, dp)
static inline xfs_dir2_db_t
xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
{
- return XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
+ return xfs_dir2_byte_to_db(mp, xfs_dir2_dataptr_to_byte(mp, dp));
}
/*
* Convert byte in space to offset in a block
*/
-#define XFS_DIR2_BYTE_TO_OFF(mp,by) xfs_dir2_byte_to_off(mp, by)
static inline xfs_dir2_data_aoff_t
xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
{
@@ -166,18 +158,15 @@ xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
/*
* Convert dataptr to a byte offset in a block
*/
-#define XFS_DIR2_DATAPTR_TO_OFF(mp,dp) xfs_dir2_dataptr_to_off(mp, dp)
static inline xfs_dir2_data_aoff_t
xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
{
- return XFS_DIR2_BYTE_TO_OFF(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
+ return xfs_dir2_byte_to_off(mp, xfs_dir2_dataptr_to_byte(mp, dp));
}
/*
* Convert block and offset to byte in space
*/
-#define XFS_DIR2_DB_OFF_TO_BYTE(mp,db,o) \
- xfs_dir2_db_off_to_byte(mp, db, o)
static inline xfs_dir2_off_t
xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
xfs_dir2_data_aoff_t o)
@@ -189,7 +178,6 @@ xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
/*
* Convert block (DB) to block (dablk)
*/
-#define XFS_DIR2_DB_TO_DA(mp,db) xfs_dir2_db_to_da(mp, db)
static inline xfs_dablk_t
xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
{
@@ -199,29 +187,25 @@ xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
/*
* Convert byte in space to (DA) block
*/
-#define XFS_DIR2_BYTE_TO_DA(mp,by) xfs_dir2_byte_to_da(mp, by)
static inline xfs_dablk_t
xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
{
- return XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, by));
+ return xfs_dir2_db_to_da(mp, xfs_dir2_byte_to_db(mp, by));
}
/*
* Convert block and offset to dataptr
*/
-#define XFS_DIR2_DB_OFF_TO_DATAPTR(mp,db,o) \
- xfs_dir2_db_off_to_dataptr(mp, db, o)
static inline xfs_dir2_dataptr_t
xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
xfs_dir2_data_aoff_t o)
{
- return XFS_DIR2_BYTE_TO_DATAPTR(mp, XFS_DIR2_DB_OFF_TO_BYTE(mp, db, o));
+ return xfs_dir2_byte_to_dataptr(mp, xfs_dir2_db_off_to_byte(mp, db, o));
}
/*
* Convert block (dablk) to block (DB)
*/
-#define XFS_DIR2_DA_TO_DB(mp,da) xfs_dir2_da_to_db(mp, da)
static inline xfs_dir2_db_t
xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
{
@@ -231,11 +215,10 @@ xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
/*
* Convert block (dablk) to byte offset in space
*/
-#define XFS_DIR2_DA_TO_BYTE(mp,da) xfs_dir2_da_to_byte(mp, da)
static inline xfs_dir2_off_t
xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
{
- return XFS_DIR2_DB_OFF_TO_BYTE(mp, XFS_DIR2_DA_TO_DB(mp, da), 0);
+ return xfs_dir2_db_off_to_byte(mp, xfs_dir2_da_to_db(mp, da), 0);
}
/*
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index d083c381993..91c61d9632c 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -136,14 +136,14 @@ xfs_dir2_leaf_to_node(
/*
* Get the buffer for the new freespace block.
*/
- if ((error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fdb), -1, &fbp,
+ if ((error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp,
XFS_DATA_FORK))) {
return error;
}
ASSERT(fbp != NULL);
free = fbp->data;
leaf = lbp->data;
- ltp = XFS_DIR2_LEAF_TAIL_P(mp, leaf);
+ ltp = xfs_dir2_leaf_tail_p(mp, leaf);
/*
* Initialize the freespace block header.
*/
@@ -155,7 +155,7 @@ xfs_dir2_leaf_to_node(
* Copy freespace entries from the leaf block to the new block.
* Count active entries.
*/
- for (i = n = 0, from = XFS_DIR2_LEAF_BESTS_P(ltp), to = free->bests;
+ for (i = n = 0, from = xfs_dir2_leaf_bests_p(ltp), to = free->bests;
i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
n++;
@@ -215,7 +215,7 @@ xfs_dir2_leafn_add(
* a compact.
*/
- if (be16_to_cpu(leaf->hdr.count) == XFS_DIR2_MAX_LEAF_ENTS(mp)) {
+ if (be16_to_cpu(leaf->hdr.count) == xfs_dir2_max_leaf_ents(mp)) {
if (!leaf->hdr.stale)
return XFS_ERROR(ENOSPC);
compact = be16_to_cpu(leaf->hdr.stale) > 1;
@@ -327,7 +327,7 @@ xfs_dir2_leafn_add(
* Insert the new entry, log everything.
*/
lep->hashval = cpu_to_be32(args->hashval);
- lep->address = cpu_to_be32(XFS_DIR2_DB_OFF_TO_DATAPTR(mp,
+ lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp,
args->blkno, args->index));
xfs_dir2_leaf_log_header(tp, bp);
xfs_dir2_leaf_log_ents(tp, bp, lfloglow, lfloghigh);
@@ -352,7 +352,7 @@ xfs_dir2_leafn_check(
leaf = bp->data;
mp = dp->i_mount;
ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
- ASSERT(be16_to_cpu(leaf->hdr.count) <= XFS_DIR2_MAX_LEAF_ENTS(mp));
+ ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp));
for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) {
if (i + 1 < be16_to_cpu(leaf->hdr.count)) {
ASSERT(be32_to_cpu(leaf->ents[i].hashval) <=
@@ -440,7 +440,7 @@ xfs_dir2_leafn_lookup_int(
if (args->addname) {
curfdb = curbp ? state->extrablk.blkno : -1;
curdb = -1;
- length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+ length = xfs_dir2_data_entsize(args->namelen);
if ((free = (curbp ? curbp->data : NULL)))
ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
}
@@ -465,7 +465,7 @@ xfs_dir2_leafn_lookup_int(
/*
* Pull the data block number from the entry.
*/
- newdb = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+ newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
/*
* For addname, we're looking for a place to put the new entry.
* We want to use a data block with an entry of equal
@@ -482,7 +482,7 @@ xfs_dir2_leafn_lookup_int(
* Convert the data block to the free block
* holding its freespace information.
*/
- newfdb = XFS_DIR2_DB_TO_FDB(mp, newdb);
+ newfdb = xfs_dir2_db_to_fdb(mp, newdb);
/*
* If it's not the one we have in hand,
* read it in.
@@ -497,7 +497,7 @@ xfs_dir2_leafn_lookup_int(
* Read the free block.
*/
if ((error = xfs_da_read_buf(tp, dp,
- XFS_DIR2_DB_TO_DA(mp,
+ xfs_dir2_db_to_da(mp,
newfdb),
-1, &curbp,
XFS_DATA_FORK))) {
@@ -517,7 +517,7 @@ xfs_dir2_leafn_lookup_int(
/*
* Get the index for our entry.
*/
- fi = XFS_DIR2_DB_TO_FDINDEX(mp, curdb);
+ fi = xfs_dir2_db_to_fdindex(mp, curdb);
/*
* If it has room, return it.
*/
@@ -561,7 +561,7 @@ xfs_dir2_leafn_lookup_int(
*/
if ((error =
xfs_da_read_buf(tp, dp,
- XFS_DIR2_DB_TO_DA(mp, newdb), -1,
+ xfs_dir2_db_to_da(mp, newdb), -1,
&curbp, XFS_DATA_FORK))) {
return error;
}
@@ -573,7 +573,7 @@ xfs_dir2_leafn_lookup_int(
*/
dep = (xfs_dir2_data_entry_t *)
((char *)curbp->data +
- XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address)));
+ xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
/*
* Compare the entry, return it if it matches.
*/
@@ -876,9 +876,9 @@ xfs_dir2_leafn_remove(
/*
* Extract the data block and offset from the entry.
*/
- db = XFS_DIR2_DATAPTR_TO_DB(mp, be32_to_cpu(lep->address));
+ db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
ASSERT(dblk->blkno == db);
- off = XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(lep->address));
+ off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address));
ASSERT(dblk->index == off);
/*
* Kill the leaf entry by marking it stale.
@@ -898,7 +898,7 @@ xfs_dir2_leafn_remove(
longest = be16_to_cpu(data->hdr.bestfree[0].length);
needlog = needscan = 0;
xfs_dir2_data_make_free(tp, dbp, off,
- XFS_DIR2_DATA_ENTSIZE(dep->namelen), &needlog, &needscan);
+ xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
/*
* Rescan the data block freespaces for bestfree.
* Log the data block header if needed.
@@ -924,8 +924,8 @@ xfs_dir2_leafn_remove(
* Convert the data block number to a free block,
* read in the free block.
*/
- fdb = XFS_DIR2_DB_TO_FDB(mp, db);
- if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fdb),
+ fdb = xfs_dir2_db_to_fdb(mp, db);
+ if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb),
-1, &fbp, XFS_DATA_FORK))) {
return error;
}
@@ -937,7 +937,7 @@ xfs_dir2_leafn_remove(
/*
* Calculate which entry we need to fix.
*/
- findex = XFS_DIR2_DB_TO_FDINDEX(mp, db);
+ findex = xfs_dir2_db_to_fdindex(mp, db);
longest = be16_to_cpu(data->hdr.bestfree[0].length);
/*
* If the data block is now empty we can get rid of it
@@ -1073,7 +1073,7 @@ xfs_dir2_leafn_split(
/*
* Initialize the new leaf block.
*/
- error = xfs_dir2_leaf_init(args, XFS_DIR2_DA_TO_DB(mp, blkno),
+ error = xfs_dir2_leaf_init(args, xfs_dir2_da_to_db(mp, blkno),
&newblk->bp, XFS_DIR2_LEAFN_MAGIC);
if (error) {
return error;
@@ -1385,7 +1385,7 @@ xfs_dir2_node_addname_int(
dp = args->dp;
mp = dp->i_mount;
tp = args->trans;
- length = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+ length = xfs_dir2_data_entsize(args->namelen);
/*
* If we came in with a freespace block that means that lookup
* found an entry with our hash value. This is the freespace
@@ -1438,7 +1438,7 @@ xfs_dir2_node_addname_int(
if ((error = xfs_bmap_last_offset(tp, dp, &fo, XFS_DATA_FORK)))
return error;
- lastfbno = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)fo);
+ lastfbno = xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo);
fbno = ifbno;
}
/*
@@ -1474,7 +1474,7 @@ xfs_dir2_node_addname_int(
* to avoid it.
*/
if ((error = xfs_da_read_buf(tp, dp,
- XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
+ xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
XFS_DATA_FORK))) {
return error;
}
@@ -1550,9 +1550,9 @@ xfs_dir2_node_addname_int(
* Get the freespace block corresponding to the data block
* that was just allocated.
*/
- fbno = XFS_DIR2_DB_TO_FDB(mp, dbno);
+ fbno = xfs_dir2_db_to_fdb(mp, dbno);
if (unlikely(error = xfs_da_read_buf(tp, dp,
- XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp,
+ xfs_dir2_db_to_da(mp, fbno), -2, &fbp,
XFS_DATA_FORK))) {
xfs_da_buf_done(dbp);
return error;
@@ -1567,14 +1567,14 @@ xfs_dir2_node_addname_int(
return error;
}
- if (unlikely(XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno)) {
+ if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
cmn_err(CE_ALERT,
"xfs_dir2_node_addname_int: dir ino "
"%llu needed freesp block %lld for\n"
" data block %lld, got %lld\n"
" ifbno %llu lastfbno %d\n",
(unsigned long long)dp->i_ino,
- (long long)XFS_DIR2_DB_TO_FDB(mp, dbno),
+ (long long)xfs_dir2_db_to_fdb(mp, dbno),
(long long)dbno, (long long)fbno,
(unsigned long long)ifbno, lastfbno);
if (fblk) {
@@ -1598,7 +1598,7 @@ xfs_dir2_node_addname_int(
* Get a buffer for the new block.
*/
if ((error = xfs_da_get_buf(tp, dp,
- XFS_DIR2_DB_TO_DA(mp, fbno),
+ xfs_dir2_db_to_da(mp, fbno),
-1, &fbp, XFS_DATA_FORK))) {
return error;
}
@@ -1623,7 +1623,7 @@ xfs_dir2_node_addname_int(
/*
* Set the freespace block index from the data block number.
*/
- findex = XFS_DIR2_DB_TO_FDINDEX(mp, dbno);
+ findex = xfs_dir2_db_to_fdindex(mp, dbno);
/*
* If it's after the end of the current entries in the
* freespace block, extend that table.
@@ -1669,7 +1669,7 @@ xfs_dir2_node_addname_int(
* Read the data block in.
*/
if (unlikely(
- error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, dbno),
+ error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, dbno),
-1, &dbp, XFS_DATA_FORK))) {
if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL)
xfs_da_buf_done(fbp);
@@ -1698,7 +1698,7 @@ xfs_dir2_node_addname_int(
dep->inumber = cpu_to_be64(args->inumber);
dep->namelen = args->namelen;
memcpy(dep->name, args->name, dep->namelen);
- tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
+ tagp = xfs_dir2_data_entry_tag_p(dep);
*tagp = cpu_to_be16((char *)dep - (char *)data);
xfs_dir2_data_log_entry(tp, dbp, dep);
/*
@@ -1904,7 +1904,7 @@ xfs_dir2_node_replace(
ASSERT(be32_to_cpu(data->hdr.magic) == XFS_DIR2_DATA_MAGIC);
dep = (xfs_dir2_data_entry_t *)
((char *)data +
- XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address)));
+ xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address)));
ASSERT(inum != be64_to_cpu(dep->inumber));
/*
* Fill in the new inode number and log the entry.
@@ -1980,7 +1980,7 @@ xfs_dir2_node_trim_free(
* Blow the block away.
*/
if ((error =
- xfs_dir2_shrink_inode(args, XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)fo),
+ xfs_dir2_shrink_inode(args, xfs_dir2_da_to_db(mp, (xfs_dablk_t)fo),
bp))) {
/*
* Can't fail with ENOSPC since that only happens with no
diff --git a/fs/xfs/xfs_dir2_node.h b/fs/xfs/xfs_dir2_node.h
index c7c870ee785..dde72db3d69 100644
--- a/fs/xfs/xfs_dir2_node.h
+++ b/fs/xfs/xfs_dir2_node.h
@@ -36,7 +36,7 @@ struct xfs_trans;
#define XFS_DIR2_FREE_SPACE 2
#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
#define XFS_DIR2_FREE_FIRSTDB(mp) \
- XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_FREE_OFFSET)
+ xfs_dir2_byte_to_db(mp, XFS_DIR2_FREE_OFFSET)
#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F */
@@ -60,7 +60,6 @@ typedef struct xfs_dir2_free {
/*
* Convert data space db to the corresponding free db.
*/
-#define XFS_DIR2_DB_TO_FDB(mp,db) xfs_dir2_db_to_fdb(mp, db)
static inline xfs_dir2_db_t
xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
{
@@ -70,7 +69,6 @@ xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
/*
* Convert data space db to the corresponding index in a free db.
*/
-#define XFS_DIR2_DB_TO_FDINDEX(mp,db) xfs_dir2_db_to_fdindex(mp, db)
static inline int
xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
{
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 0cd77b17bf9..38fc4f22b76 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -89,8 +89,8 @@ xfs_dir2_block_sfsize(
mp = dp->i_mount;
count = i8count = namelen = 0;
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
- blp = XFS_DIR2_BLOCK_LEAF_P(btp);
+ btp = xfs_dir2_block_tail_p(mp, block);
+ blp = xfs_dir2_block_leaf_p(btp);
/*
* Iterate over the block's data entries by using the leaf pointers.
@@ -102,7 +102,7 @@ xfs_dir2_block_sfsize(
* Calculate the pointer to the entry at hand.
*/
dep = (xfs_dir2_data_entry_t *)
- ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
+ ((char *)block + xfs_dir2_dataptr_to_off(mp, addr));
/*
* Detect . and .., so we can special-case them.
* . is not included in sf directories.
@@ -124,7 +124,7 @@ xfs_dir2_block_sfsize(
/*
* Calculate the new size, see if we should give up yet.
*/
- size = XFS_DIR2_SF_HDR_SIZE(i8count) + /* header */
+ size = xfs_dir2_sf_hdr_size(i8count) + /* header */
count + /* namelen */
count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
namelen + /* name */
@@ -139,7 +139,7 @@ xfs_dir2_block_sfsize(
*/
sfhp->count = count;
sfhp->i8count = i8count;
- XFS_DIR2_SF_PUT_INUMBER((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
+ xfs_dir2_sf_put_inumber((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
return size;
}
@@ -199,15 +199,15 @@ xfs_dir2_block_to_sf(
* Copy the header into the newly allocate local space.
*/
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- memcpy(sfp, sfhp, XFS_DIR2_SF_HDR_SIZE(sfhp->i8count));
+ memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));
dp->i_d.di_size = size;
/*
* Set up to loop over the block's entries.
*/
- btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
+ btp = xfs_dir2_block_tail_p(mp, block);
ptr = (char *)block->u;
- endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
- sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+ endptr = (char *)xfs_dir2_block_leaf_p(btp);
+ sfep = xfs_dir2_sf_firstentry(sfp);
/*
* Loop over the active and unused entries.
* Stop when we reach the leaf/tail portion of the block.
@@ -233,22 +233,22 @@ xfs_dir2_block_to_sf(
else if (dep->namelen == 2 &&
dep->name[0] == '.' && dep->name[1] == '.')
ASSERT(be64_to_cpu(dep->inumber) ==
- XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
+ xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent));
/*
* Normal entry, copy it into shortform.
*/
else {
sfep->namelen = dep->namelen;
- XFS_DIR2_SF_PUT_OFFSET(sfep,
+ xfs_dir2_sf_put_offset(sfep,
(xfs_dir2_data_aoff_t)
((char *)dep - (char *)block));
memcpy(sfep->name, dep->name, dep->namelen);
temp = be64_to_cpu(dep->inumber);
- XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
- XFS_DIR2_SF_INUMBERP(sfep));
- sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+ xfs_dir2_sf_put_inumber(sfp, &temp,
+ xfs_dir2_sf_inumberp(sfep));
+ sfep = xfs_dir2_sf_nextentry(sfp, sfep);
}
- ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
+ ptr += xfs_dir2_data_entsize(dep->namelen);
}
ASSERT((char *)sfep - (char *)sfp == size);
xfs_dir2_sf_check(args);
@@ -294,11 +294,11 @@ xfs_dir2_sf_addname(
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
ASSERT(dp->i_df.if_u1.if_data != NULL);
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+ ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
/*
* Compute entry (and change in) size.
*/
- add_entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
+ add_entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
incr_isize = add_entsize;
objchange = 0;
#if XFS_BIG_INUMS
@@ -392,7 +392,7 @@ xfs_dir2_sf_addname_easy(
/*
* Grow the in-inode space.
*/
- xfs_idata_realloc(dp, XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen),
+ xfs_idata_realloc(dp, xfs_dir2_sf_entsize_byname(sfp, args->namelen),
XFS_DATA_FORK);
/*
* Need to set up again due to realloc of the inode data.
@@ -403,10 +403,10 @@ xfs_dir2_sf_addname_easy(
* Fill in the new entry.
*/
sfep->namelen = args->namelen;
- XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
+ xfs_dir2_sf_put_offset(sfep, offset);
memcpy(sfep->name, args->name, sfep->namelen);
- XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
- XFS_DIR2_SF_INUMBERP(sfep));
+ xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+ xfs_dir2_sf_inumberp(sfep));
/*
* Update the header and inode.
*/
@@ -463,14 +463,14 @@ xfs_dir2_sf_addname_hard(
* If it's going to end up at the end then oldsfep will point there.
*/
for (offset = XFS_DIR2_DATA_FIRST_OFFSET,
- oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp),
- add_datasize = XFS_DIR2_DATA_ENTSIZE(args->namelen),
+ oldsfep = xfs_dir2_sf_firstentry(oldsfp),
+ add_datasize = xfs_dir2_data_entsize(args->namelen),
eof = (char *)oldsfep == &buf[old_isize];
!eof;
- offset = new_offset + XFS_DIR2_DATA_ENTSIZE(oldsfep->namelen),
- oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep),
+ offset = new_offset + xfs_dir2_data_entsize(oldsfep->namelen),
+ oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep),
eof = (char *)oldsfep == &buf[old_isize]) {
- new_offset = XFS_DIR2_SF_GET_OFFSET(oldsfep);
+ new_offset = xfs_dir2_sf_get_offset(oldsfep);
if (offset + add_datasize <= new_offset)
break;
}
@@ -495,10 +495,10 @@ xfs_dir2_sf_addname_hard(
* Fill in the new entry, and update the header counts.
*/
sfep->namelen = args->namelen;
- XFS_DIR2_SF_PUT_OFFSET(sfep, offset);
+ xfs_dir2_sf_put_offset(sfep, offset);
memcpy(sfep->name, args->name, sfep->namelen);
- XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
- XFS_DIR2_SF_INUMBERP(sfep));
+ xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+ xfs_dir2_sf_inumberp(sfep));
sfp->hdr.count++;
#if XFS_BIG_INUMS
if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
@@ -508,7 +508,7 @@ xfs_dir2_sf_addname_hard(
* If there's more left to copy, do that.
*/
if (!eof) {
- sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+ sfep = xfs_dir2_sf_nextentry(sfp, sfep);
memcpy(sfep, oldsfep, old_isize - nbytes);
}
kmem_free(buf, old_isize);
@@ -544,9 +544,9 @@ xfs_dir2_sf_addname_pick(
mp = dp->i_mount;
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- size = XFS_DIR2_DATA_ENTSIZE(args->namelen);
+ size = xfs_dir2_data_entsize(args->namelen);
offset = XFS_DIR2_DATA_FIRST_OFFSET;
- sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+ sfep = xfs_dir2_sf_firstentry(sfp);
holefit = 0;
/*
* Loop over sf entries.
@@ -555,10 +555,10 @@ xfs_dir2_sf_addname_pick(
*/
for (i = 0; i < sfp->hdr.count; i++) {
if (!holefit)
- holefit = offset + size <= XFS_DIR2_SF_GET_OFFSET(sfep);
- offset = XFS_DIR2_SF_GET_OFFSET(sfep) +
- XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
- sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
+ holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
+ offset = xfs_dir2_sf_get_offset(sfep) +
+ xfs_dir2_data_entsize(sfep->namelen);
+ sfep = xfs_dir2_sf_nextentry(sfp, sfep);
}
/*
* Calculate data bytes used excluding the new entry, if this
@@ -617,18 +617,18 @@ xfs_dir2_sf_check(
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
offset = XFS_DIR2_DATA_FIRST_OFFSET;
- ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+ ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
- for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
i < sfp->hdr.count;
- i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
- ASSERT(XFS_DIR2_SF_GET_OFFSET(sfep) >= offset);
- ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
+ i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
+ ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
+ ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
offset =
- XFS_DIR2_SF_GET_OFFSET(sfep) +
- XFS_DIR2_DATA_ENTSIZE(sfep->namelen);
+ xfs_dir2_sf_get_offset(sfep) +
+ xfs_dir2_data_entsize(sfep->namelen);
}
ASSERT(i8count == sfp->hdr.i8count);
ASSERT(XFS_BIG_INUMS || i8count == 0);
@@ -671,7 +671,7 @@ xfs_dir2_sf_create(
ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
ASSERT(dp->i_df.if_bytes == 0);
i8count = pino > XFS_DIR2_MAX_SHORT_INUM;
- size = XFS_DIR2_SF_HDR_SIZE(i8count);
+ size = xfs_dir2_sf_hdr_size(i8count);
/*
* Make a buffer for the data.
*/
@@ -684,7 +684,7 @@ xfs_dir2_sf_create(
/*
* Now can put in the inode number, since i8count is set.
*/
- XFS_DIR2_SF_PUT_INUMBER(sfp, &pino, &sfp->hdr.parent);
+ xfs_dir2_sf_put_inumber(sfp, &pino, &sfp->hdr.parent);
sfp->hdr.count = 0;
dp->i_d.di_size = size;
xfs_dir2_sf_check(args);
@@ -727,12 +727,12 @@ xfs_dir2_sf_getdents(
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+ ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
/*
* If the block number in the offset is out of range, we're done.
*/
- if (XFS_DIR2_DATAPTR_TO_DB(mp, dir_offset) > mp->m_dirdatablk) {
+ if (xfs_dir2_dataptr_to_db(mp, dir_offset) > mp->m_dirdatablk) {
*eofp = 1;
return 0;
}
@@ -747,9 +747,9 @@ xfs_dir2_sf_getdents(
* Put . entry unless we're starting past it.
*/
if (dir_offset <=
- XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+ xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOT_OFFSET)) {
- p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, 0,
+ p.cook = xfs_dir2_db_off_to_dataptr(mp, 0,
XFS_DIR2_DATA_DOTDOT_OFFSET);
p.ino = dp->i_ino;
#if XFS_BIG_INUMS
@@ -762,7 +762,7 @@ xfs_dir2_sf_getdents(
if (!p.done) {
uio->uio_offset =
- XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+ xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOT_OFFSET);
return error;
}
@@ -772,11 +772,11 @@ xfs_dir2_sf_getdents(
* Put .. entry unless we're starting past it.
*/
if (dir_offset <=
- XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+ xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOTDOT_OFFSET)) {
- p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+ p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_FIRST_OFFSET);
- p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+ p.ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
#endif
@@ -787,7 +787,7 @@ xfs_dir2_sf_getdents(
if (!p.done) {
uio->uio_offset =
- XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
+ xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOTDOT_OFFSET);
return error;
}
@@ -796,23 +796,23 @@ xfs_dir2_sf_getdents(
/*
* Loop while there are more entries and put'ing works.
*/
- for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
i < sfp->hdr.count;
- i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
+ i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
- off = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
- XFS_DIR2_SF_GET_OFFSET(sfep));
+ off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+ xfs_dir2_sf_get_offset(sfep));
if (dir_offset > off)
continue;
p.namelen = sfep->namelen;
- p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
- XFS_DIR2_SF_GET_OFFSET(sfep) +
- XFS_DIR2_DATA_ENTSIZE(p.namelen));
+ p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
+ xfs_dir2_sf_get_offset(sfep) +
+ xfs_dir2_data_entsize(p.namelen));
- p.ino = XFS_DIR2_SF_GET_INUMBER(sfp, XFS_DIR2_SF_INUMBERP(sfep));
+ p.ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
#endif
@@ -832,7 +832,7 @@ xfs_dir2_sf_getdents(
*eofp = 1;
uio->uio_offset =
- XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk + 1, 0);
+ xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
return 0;
}
@@ -865,7 +865,7 @@ xfs_dir2_sf_lookup(
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
ASSERT(dp->i_df.if_u1.if_data != NULL);
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+ ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
/*
* Special case for .
*/
@@ -878,21 +878,21 @@ xfs_dir2_sf_lookup(
*/
if (args->namelen == 2 &&
args->name[0] == '.' && args->name[1] == '.') {
- args->inumber = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+ args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
return XFS_ERROR(EEXIST);
}
/*
* Loop over all the entries trying to match ours.
*/
- for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
i < sfp->hdr.count;
- i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
+ i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
if (sfep->namelen == args->namelen &&
sfep->name[0] == args->name[0] &&
memcmp(args->name, sfep->name, args->namelen) == 0) {
args->inumber =
- XFS_DIR2_SF_GET_INUMBER(sfp,
- XFS_DIR2_SF_INUMBERP(sfep));
+ xfs_dir2_sf_get_inumber(sfp,
+ xfs_dir2_sf_inumberp(sfep));
return XFS_ERROR(EEXIST);
}
}
@@ -934,19 +934,19 @@ xfs_dir2_sf_removename(
ASSERT(dp->i_df.if_bytes == oldsize);
ASSERT(dp->i_df.if_u1.if_data != NULL);
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- ASSERT(oldsize >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+ ASSERT(oldsize >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
/*
* Loop over the old directory entries.
* Find the one we're deleting.
*/
- for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
i < sfp->hdr.count;
- i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
+ i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
if (sfep->namelen == args->namelen &&
sfep->name[0] == args->name[0] &&
memcmp(sfep->name, args->name, args->namelen) == 0) {
- ASSERT(XFS_DIR2_SF_GET_INUMBER(sfp,
- XFS_DIR2_SF_INUMBERP(sfep)) ==
+ ASSERT(xfs_dir2_sf_get_inumber(sfp,
+ xfs_dir2_sf_inumberp(sfep)) ==
args->inumber);
break;
}
@@ -961,7 +961,7 @@ xfs_dir2_sf_removename(
* Calculate sizes.
*/
byteoff = (int)((char *)sfep - (char *)sfp);
- entsize = XFS_DIR2_SF_ENTSIZE_BYNAME(sfp, args->namelen);
+ entsize = xfs_dir2_sf_entsize_byname(sfp, args->namelen);
newsize = oldsize - entsize;
/*
* Copy the part if any after the removed entry, sliding it down.
@@ -1027,7 +1027,7 @@ xfs_dir2_sf_replace(
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
ASSERT(dp->i_df.if_u1.if_data != NULL);
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
- ASSERT(dp->i_d.di_size >= XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count));
+ ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(sfp->hdr.i8count));
#if XFS_BIG_INUMS
/*
* New inode number is large, and need to convert to 8-byte inodes.
@@ -1067,28 +1067,28 @@ xfs_dir2_sf_replace(
if (args->namelen == 2 &&
args->name[0] == '.' && args->name[1] == '.') {
#if XFS_BIG_INUMS || defined(DEBUG)
- ino = XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent);
+ ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
ASSERT(args->inumber != ino);
#endif
- XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber, &sfp->hdr.parent);
+ xfs_dir2_sf_put_inumber(sfp, &args->inumber, &sfp->hdr.parent);
}
/*
* Normal entry, look for the name.
*/
else {
- for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp);
+ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
i < sfp->hdr.count;
- i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep)) {
+ i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
if (sfep->namelen == args->namelen &&
sfep->name[0] == args->name[0] &&
memcmp(args->name, sfep->name, args->namelen) == 0) {
#if XFS_BIG_INUMS || defined(DEBUG)
- ino = XFS_DIR2_SF_GET_INUMBER(sfp,
- XFS_DIR2_SF_INUMBERP(sfep));
+ ino = xfs_dir2_sf_get_inumber(sfp,
+ xfs_dir2_sf_inumberp(sfep));
ASSERT(args->inumber != ino);
#endif
- XFS_DIR2_SF_PUT_INUMBER(sfp, &args->inumber,
- XFS_DIR2_SF_INUMBERP(sfep));
+ xfs_dir2_sf_put_inumber(sfp, &args->inumber,
+ xfs_dir2_sf_inumberp(sfep));
break;
}
}
@@ -1189,22 +1189,22 @@ xfs_dir2_sf_toino4(
*/
sfp->hdr.count = oldsfp->hdr.count;
sfp->hdr.i8count = 0;
- ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
- XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
+ ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
+ xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
/*
* Copy the entries field by field.
*/
- for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
- oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
+ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
+ oldsfep = xfs_dir2_sf_firstentry(oldsfp);
i < sfp->hdr.count;
- i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
- oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
+ i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
+ oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
sfep->namelen = oldsfep->namelen;
sfep->offset = oldsfep->offset;
memcpy(sfep->name, oldsfep->name, sfep->namelen);
- ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
- XFS_DIR2_SF_INUMBERP(oldsfep));
- XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
+ ino = xfs_dir2_sf_get_inumber(oldsfp,
+ xfs_dir2_sf_inumberp(oldsfep));
+ xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
}
/*
* Clean up the inode.
@@ -1266,22 +1266,22 @@ xfs_dir2_sf_toino8(
*/
sfp->hdr.count = oldsfp->hdr.count;
sfp->hdr.i8count = 1;
- ino = XFS_DIR2_SF_GET_INUMBER(oldsfp, &oldsfp->hdr.parent);
- XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, &sfp->hdr.parent);
+ ino = xfs_dir2_sf_get_inumber(oldsfp, &oldsfp->hdr.parent);
+ xfs_dir2_sf_put_inumber(sfp, &ino, &sfp->hdr.parent);
/*
* Copy the entries field by field.
*/
- for (i = 0, sfep = XFS_DIR2_SF_FIRSTENTRY(sfp),
- oldsfep = XFS_DIR2_SF_FIRSTENTRY(oldsfp);
+ for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
+ oldsfep = xfs_dir2_sf_firstentry(oldsfp);
i < sfp->hdr.count;
- i++, sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep),
- oldsfep = XFS_DIR2_SF_NEXTENTRY(oldsfp, oldsfep)) {
+ i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep),
+ oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) {
sfep->namelen = oldsfep->namelen;
sfep->offset = oldsfep->offset;
memcpy(sfep->name, oldsfep->name, sfep->namelen);
- ino = XFS_DIR2_SF_GET_INUMBER(oldsfp,
- XFS_DIR2_SF_INUMBERP(oldsfep));
- XFS_DIR2_SF_PUT_INUMBER(sfp, &ino, XFS_DIR2_SF_INUMBERP(sfep));
+ ino = xfs_dir2_sf_get_inumber(oldsfp,
+ xfs_dir2_sf_inumberp(oldsfep));
+ xfs_dir2_sf_put_inumber(sfp, &ino, xfs_dir2_sf_inumberp(sfep));
}
/*
* Clean up the inode.
diff --git a/fs/xfs/xfs_dir2_sf.h b/fs/xfs/xfs_dir2_sf.h
index 42f015b7001..11e503209af 100644
--- a/fs/xfs/xfs_dir2_sf.h
+++ b/fs/xfs/xfs_dir2_sf.h
@@ -90,7 +90,6 @@ typedef struct xfs_dir2_sf {
xfs_dir2_sf_entry_t list[1]; /* shortform entries */
} xfs_dir2_sf_t;
-#define XFS_DIR2_SF_HDR_SIZE(i8count) xfs_dir2_sf_hdr_size(i8count)
static inline int xfs_dir2_sf_hdr_size(int i8count)
{
return ((uint)sizeof(xfs_dir2_sf_hdr_t) - \
@@ -98,14 +97,11 @@ static inline int xfs_dir2_sf_hdr_size(int i8count)
((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
}
-#define XFS_DIR2_SF_INUMBERP(sfep) xfs_dir2_sf_inumberp(sfep)
static inline xfs_dir2_inou_t *xfs_dir2_sf_inumberp(xfs_dir2_sf_entry_t *sfep)
{
return (xfs_dir2_inou_t *)&(sfep)->name[(sfep)->namelen];
}
-#define XFS_DIR2_SF_GET_INUMBER(sfp, from) \
- xfs_dir2_sf_get_inumber(sfp, from)
static inline xfs_intino_t
xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from)
{
@@ -114,8 +110,6 @@ xfs_dir2_sf_get_inumber(xfs_dir2_sf_t *sfp, xfs_dir2_inou_t *from)
(xfs_intino_t)XFS_GET_DIR_INO8((from)->i8));
}
-#define XFS_DIR2_SF_PUT_INUMBER(sfp,from,to) \
- xfs_dir2_sf_put_inumber(sfp,from,to)
static inline void xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
xfs_dir2_inou_t *to)
{
@@ -125,24 +119,18 @@ static inline void xfs_dir2_sf_put_inumber(xfs_dir2_sf_t *sfp, xfs_ino_t *from,
XFS_PUT_DIR_INO8(*(from), (to)->i8);
}
-#define XFS_DIR2_SF_GET_OFFSET(sfep) \
- xfs_dir2_sf_get_offset(sfep)
static inline xfs_dir2_data_aoff_t
xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep)
{
return INT_GET_UNALIGNED_16_BE(&(sfep)->offset.i);
}
-#define XFS_DIR2_SF_PUT_OFFSET(sfep,off) \
- xfs_dir2_sf_put_offset(sfep,off)
static inline void
xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
{
INT_SET_UNALIGNED_16_BE(&(sfep)->offset.i, off);
}
-#define XFS_DIR2_SF_ENTSIZE_BYNAME(sfp,len) \
- xfs_dir2_sf_entsize_byname(sfp,len)
static inline int xfs_dir2_sf_entsize_byname(xfs_dir2_sf_t *sfp, int len)
{
return ((uint)sizeof(xfs_dir2_sf_entry_t) - 1 + (len) - \
@@ -150,8 +138,6 @@ static inline int xfs_dir2_sf_entsize_byname(xfs_dir2_sf_t *sfp, int len)
((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
}
-#define XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,sfep) \
- xfs_dir2_sf_entsize_byentry(sfp,sfep)
static inline int
xfs_dir2_sf_entsize_byentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
{
@@ -160,19 +146,17 @@ xfs_dir2_sf_entsize_byentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)));
}
-#define XFS_DIR2_SF_FIRSTENTRY(sfp) xfs_dir2_sf_firstentry(sfp)
static inline xfs_dir2_sf_entry_t *xfs_dir2_sf_firstentry(xfs_dir2_sf_t *sfp)
{
return ((xfs_dir2_sf_entry_t *) \
- ((char *)(sfp) + XFS_DIR2_SF_HDR_SIZE(sfp->hdr.i8count)));
+ ((char *)(sfp) + xfs_dir2_sf_hdr_size(sfp->hdr.i8count)));
}
-#define XFS_DIR2_SF_NEXTENTRY(sfp,sfep) xfs_dir2_sf_nextentry(sfp,sfep)
static inline xfs_dir2_sf_entry_t *
xfs_dir2_sf_nextentry(xfs_dir2_sf_t *sfp, xfs_dir2_sf_entry_t *sfep)
{
return ((xfs_dir2_sf_entry_t *) \
- ((char *)(sfep) + XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp,sfep)));
+ ((char *)(sfep) + xfs_dir2_sf_entsize_byentry(sfp,sfep)));
}
/*
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
new file mode 100644
index 00000000000..ce2278611bb
--- /dev/null
+++ b/fs/xfs/xfs_filestream.c
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2006-2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "xfs.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_inum.h"
+#include "xfs_dir2.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_ag.h"
+#include "xfs_dmapi.h"
+#include "xfs_log.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_bmap.h"
+#include "xfs_alloc.h"
+#include "xfs_utils.h"
+#include "xfs_mru_cache.h"
+#include "xfs_filestream.h"
+
+#ifdef XFS_FILESTREAMS_TRACE
+
+ktrace_t *xfs_filestreams_trace_buf;
+
+STATIC void
+xfs_filestreams_trace(
+ xfs_mount_t *mp, /* mount point */
+ int type, /* type of trace */
+ const char *func, /* source function */
+ int line, /* source line number */
+ __psunsigned_t arg0,
+ __psunsigned_t arg1,
+ __psunsigned_t arg2,
+ __psunsigned_t arg3,
+ __psunsigned_t arg4,
+ __psunsigned_t arg5)
+{
+ ktrace_enter(xfs_filestreams_trace_buf,
+ (void *)(__psint_t)(type | (line << 16)),
+ (void *)func,
+ (void *)(__psunsigned_t)current_pid(),
+ (void *)mp,
+ (void *)(__psunsigned_t)arg0,
+ (void *)(__psunsigned_t)arg1,
+ (void *)(__psunsigned_t)arg2,
+ (void *)(__psunsigned_t)arg3,
+ (void *)(__psunsigned_t)arg4,
+ (void *)(__psunsigned_t)arg5,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+}
+
+#define TRACE0(mp,t) TRACE6(mp,t,0,0,0,0,0,0)
+#define TRACE1(mp,t,a0) TRACE6(mp,t,a0,0,0,0,0,0)
+#define TRACE2(mp,t,a0,a1) TRACE6(mp,t,a0,a1,0,0,0,0)
+#define TRACE3(mp,t,a0,a1,a2) TRACE6(mp,t,a0,a1,a2,0,0,0)
+#define TRACE4(mp,t,a0,a1,a2,a3) TRACE6(mp,t,a0,a1,a2,a3,0,0)
+#define TRACE5(mp,t,a0,a1,a2,a3,a4) TRACE6(mp,t,a0,a1,a2,a3,a4,0)
+#define TRACE6(mp,t,a0,a1,a2,a3,a4,a5) \
+ xfs_filestreams_trace(mp, t, __FUNCTION__, __LINE__, \
+ (__psunsigned_t)a0, (__psunsigned_t)a1, \
+ (__psunsigned_t)a2, (__psunsigned_t)a3, \
+ (__psunsigned_t)a4, (__psunsigned_t)a5)
+
+#define TRACE_AG_SCAN(mp, ag, ag2) \
+ TRACE2(mp, XFS_FSTRM_KTRACE_AGSCAN, ag, ag2);
+#define TRACE_AG_PICK1(mp, max_ag, maxfree) \
+ TRACE2(mp, XFS_FSTRM_KTRACE_AGPICK1, max_ag, maxfree);
+#define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag) \
+ TRACE6(mp, XFS_FSTRM_KTRACE_AGPICK2, ag, ag2, \
+ cnt, free, scan, flag)
+#define TRACE_UPDATE(mp, ip, ag, cnt, ag2, cnt2) \
+ TRACE5(mp, XFS_FSTRM_KTRACE_UPDATE, ip, ag, cnt, ag2, cnt2)
+#define TRACE_FREE(mp, ip, pip, ag, cnt) \
+ TRACE4(mp, XFS_FSTRM_KTRACE_FREE, ip, pip, ag, cnt)
+#define TRACE_LOOKUP(mp, ip, pip, ag, cnt) \
+ TRACE4(mp, XFS_FSTRM_KTRACE_ITEM_LOOKUP, ip, pip, ag, cnt)
+#define TRACE_ASSOCIATE(mp, ip, pip, ag, cnt) \
+ TRACE4(mp, XFS_FSTRM_KTRACE_ASSOCIATE, ip, pip, ag, cnt)
+#define TRACE_MOVEAG(mp, ip, pip, oag, ocnt, nag, ncnt) \
+ TRACE6(mp, XFS_FSTRM_KTRACE_MOVEAG, ip, pip, oag, ocnt, nag, ncnt)
+#define TRACE_ORPHAN(mp, ip, ag) \
+ TRACE2(mp, XFS_FSTRM_KTRACE_ORPHAN, ip, ag);
+
+
+#else
+#define TRACE_AG_SCAN(mp, ag, ag2)
+#define TRACE_AG_PICK1(mp, max_ag, maxfree)
+#define TRACE_AG_PICK2(mp, ag, ag2, cnt, free, scan, flag)
+#define TRACE_UPDATE(mp, ip, ag, cnt, ag2, cnt2)
+#define TRACE_FREE(mp, ip, pip, ag, cnt)
+#define TRACE_LOOKUP(mp, ip, pip, ag, cnt)
+#define TRACE_ASSOCIATE(mp, ip, pip, ag, cnt)
+#define TRACE_MOVEAG(mp, ip, pip, oag, ocnt, nag, ncnt)
+#define TRACE_ORPHAN(mp, ip, ag)
+#endif
+
+static kmem_zone_t *item_zone;
+
+/*
+ * Structure for associating a file or a directory with an allocation group.
+ * The parent directory pointer is only needed for files, but since there will
+ * generally be vastly more files than directories in the cache, using the same
+ * data structure simplifies the code with very little memory overhead.
+ */
+typedef struct fstrm_item
+{
+ xfs_agnumber_t ag; /* AG currently in use for the file/directory. */
+ xfs_inode_t *ip; /* inode self-pointer. */
+ xfs_inode_t *pip; /* Parent directory inode pointer. */
+} fstrm_item_t;
+
+
+/*
+ * Scan the AGs starting at startag looking for an AG that isn't in use and has
+ * at least minlen blocks free.
+ */
+static int
+_xfs_filestream_pick_ag(
+ xfs_mount_t *mp,
+ xfs_agnumber_t startag,
+ xfs_agnumber_t *agp,
+ int flags,
+ xfs_extlen_t minlen)
+{
+ int err, trylock, nscan;
+ xfs_extlen_t delta, longest, need, free, minfree, maxfree = 0;
+ xfs_agnumber_t ag, max_ag = NULLAGNUMBER;
+ struct xfs_perag *pag;
+
+ /* 2% of an AG's blocks must be free for it to be chosen. */
+ minfree = mp->m_sb.sb_agblocks / 50;
+
+ ag = startag;
+ *agp = NULLAGNUMBER;
+
+ /* For the first pass, don't sleep trying to init the per-AG. */
+ trylock = XFS_ALLOC_FLAG_TRYLOCK;
+
+ for (nscan = 0; 1; nscan++) {
+
+ TRACE_AG_SCAN(mp, ag, xfs_filestream_peek_ag(mp, ag));
+
+ pag = mp->m_perag + ag;
+
+ if (!pag->pagf_init) {
+ err = xfs_alloc_pagf_init(mp, NULL, ag, trylock);
+ if (err && !trylock)
+ return err;
+ }
+
+ /* Might fail sometimes during the 1st pass with trylock set. */
+ if (!pag->pagf_init)
+ goto next_ag;
+
+ /* Keep track of the AG with the most free blocks. */
+ if (pag->pagf_freeblks > maxfree) {
+ maxfree = pag->pagf_freeblks;
+ max_ag = ag;
+ }
+
+ /*
+ * The AG reference count does two things: it enforces mutual
+ * exclusion when examining the suitability of an AG in this
+ * loop, and it guards against two filestreams being established
+ * in the same AG as each other.
+ */
+ if (xfs_filestream_get_ag(mp, ag) > 1) {
+ xfs_filestream_put_ag(mp, ag);
+ goto next_ag;
+ }
+
+ need = XFS_MIN_FREELIST_PAG(pag, mp);
+ delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0;
+ longest = (pag->pagf_longest > delta) ?
+ (pag->pagf_longest - delta) :
+ (pag->pagf_flcount > 0 || pag->pagf_longest > 0);
+
+ if (((minlen && longest >= minlen) ||
+ (!minlen && pag->pagf_freeblks >= minfree)) &&
+ (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) ||
+ (flags & XFS_PICK_LOWSPACE))) {
+
+ /* Break out, retaining the reference on the AG. */
+ free = pag->pagf_freeblks;
+ *agp = ag;
+ break;
+ }
+
+ /* Drop the reference on this AG, it's not usable. */
+ xfs_filestream_put_ag(mp, ag);
+next_ag:
+ /* Move to the next AG, wrapping to AG 0 if necessary. */
+ if (++ag >= mp->m_sb.sb_agcount)
+ ag = 0;
+
+ /* If a full pass of the AGs hasn't been done yet, continue. */
+ if (ag != startag)
+ continue;
+
+ /* Allow sleeping in xfs_alloc_pagf_init() on the 2nd pass. */
+ if (trylock != 0) {
+ trylock = 0;
+ continue;
+ }
+
+ /* Finally, if lowspace wasn't set, set it for the 3rd pass. */
+ if (!(flags & XFS_PICK_LOWSPACE)) {
+ flags |= XFS_PICK_LOWSPACE;
+ continue;
+ }
+
+ /*
+ * Take the AG with the most free space, regardless of whether
+ * it's already in use by another filestream.
+ */
+ if (max_ag != NULLAGNUMBER) {
+ xfs_filestream_get_ag(mp, max_ag);
+ TRACE_AG_PICK1(mp, max_ag, maxfree);
+ free = maxfree;
+ *agp = max_ag;
+ break;
+ }
+
+ /* take AG 0 if none matched */
+ TRACE_AG_PICK1(mp, max_ag, maxfree);
+ *agp = 0;
+ return 0;
+ }
+
+ TRACE_AG_PICK2(mp, startag, *agp, xfs_filestream_peek_ag(mp, *agp),
+ free, nscan, flags);
+
+ return 0;
+}
+
+/*
+ * Set the allocation group number for a file or a directory, updating inode
+ * references and per-AG references as appropriate. Must be called with the
+ * m_peraglock held in read mode.
+ */
+static int
+_xfs_filestream_update_ag(
+ xfs_inode_t *ip,
+ xfs_inode_t *pip,
+ xfs_agnumber_t ag)
+{
+ int err = 0;
+ xfs_mount_t *mp;
+ xfs_mru_cache_t *cache;
+ fstrm_item_t *item;
+ xfs_agnumber_t old_ag;
+ xfs_inode_t *old_pip;
+
+ /*
+ * Either ip is a regular file and pip is a directory, or ip is a
+ * directory and pip is NULL.
+ */
+ ASSERT(ip && (((ip->i_d.di_mode & S_IFREG) && pip &&
+ (pip->i_d.di_mode & S_IFDIR)) ||
+ ((ip->i_d.di_mode & S_IFDIR) && !pip)));
+
+ mp = ip->i_mount;
+ cache = mp->m_filestream;
+
+ item = xfs_mru_cache_lookup(cache, ip->i_ino);
+ if (item) {
+ ASSERT(item->ip == ip);
+ old_ag = item->ag;
+ item->ag = ag;
+ old_pip = item->pip;
+ item->pip = pip;
+ xfs_mru_cache_done(cache);
+
+ /*
+ * If the AG has changed, drop the old ref and take a new one,
+ * effectively transferring the reference from old to new AG.
+ */
+ if (ag != old_ag) {
+ xfs_filestream_put_ag(mp, old_ag);
+ xfs_filestream_get_ag(mp, ag);
+ }
+
+ /*
+ * If ip is a file and its pip has changed, drop the old ref and
+ * take a new one.
+ */
+ if (pip && pip != old_pip) {
+ IRELE(old_pip);
+ IHOLD(pip);
+ }
+
+ TRACE_UPDATE(mp, ip, old_ag, xfs_filestream_peek_ag(mp, old_ag),
+ ag, xfs_filestream_peek_ag(mp, ag));
+ return 0;
+ }
+
+ item = kmem_zone_zalloc(item_zone, KM_MAYFAIL);
+ if (!item)
+ return ENOMEM;
+
+ item->ag = ag;
+ item->ip = ip;
+ item->pip = pip;
+
+ err = xfs_mru_cache_insert(cache, ip->i_ino, item);
+ if (err) {
+ kmem_zone_free(item_zone, item);
+ return err;
+ }
+
+ /* Take a reference on the AG. */
+ xfs_filestream_get_ag(mp, ag);
+
+ /*
+ * Take a reference on the inode itself regardless of whether it's a
+ * regular file or a directory.
+ */
+ IHOLD(ip);
+
+ /*
+ * In the case of a regular file, take a reference on the parent inode
+ * as well to ensure it remains in-core.
+ */
+ if (pip)
+ IHOLD(pip);
+
+ TRACE_UPDATE(mp, ip, ag, xfs_filestream_peek_ag(mp, ag),
+ ag, xfs_filestream_peek_ag(mp, ag));
+
+ return 0;
+}
+
+/* xfs_fstrm_free_func(): callback for freeing cached stream items. */
+void
+xfs_fstrm_free_func(
+ xfs_ino_t ino,
+ fstrm_item_t *item)
+{
+ xfs_inode_t *ip = item->ip;
+ int ref;
+
+ ASSERT(ip->i_ino == ino);
+
+ xfs_iflags_clear(ip, XFS_IFILESTREAM);
+
+ /* Drop the reference taken on the AG when the item was added. */
+ ref = xfs_filestream_put_ag(ip->i_mount, item->ag);
+
+ ASSERT(ref >= 0);
+ TRACE_FREE(ip->i_mount, ip, item->pip, item->ag,
+ xfs_filestream_peek_ag(ip->i_mount, item->ag));
+
+ /*
+ * _xfs_filestream_update_ag() always takes a reference on the inode
+ * itself, whether it's a file or a directory. Release it here.
+ * This can result in the inode being freed and so we must
+ * not hold any inode locks when freeing filesstreams objects
+ * otherwise we can deadlock here.
+ */
+ IRELE(ip);
+
+ /*
+ * In the case of a regular file, _xfs_filestream_update_ag() also
+ * takes a ref on the parent inode to keep it in-core. Release that
+ * too.
+ */
+ if (item->pip)
+ IRELE(item->pip);
+
+ /* Finally, free the memory allocated for the item. */
+ kmem_zone_free(item_zone, item);
+}
+
+/*
+ * xfs_filestream_init() is called at xfs initialisation time to set up the
+ * memory zone that will be used for filestream data structure allocation.
+ */
+int
+xfs_filestream_init(void)
+{
+ item_zone = kmem_zone_init(sizeof(fstrm_item_t), "fstrm_item");
+#ifdef XFS_FILESTREAMS_TRACE
+ xfs_filestreams_trace_buf = ktrace_alloc(XFS_FSTRM_KTRACE_SIZE, KM_SLEEP);
+#endif
+ return item_zone ? 0 : -ENOMEM;
+}
+
+/*
+ * xfs_filestream_uninit() is called at xfs termination time to destroy the
+ * memory zone that was used for filestream data structure allocation.
+ */
+void
+xfs_filestream_uninit(void)
+{
+#ifdef XFS_FILESTREAMS_TRACE
+ ktrace_free(xfs_filestreams_trace_buf);
+#endif
+ kmem_zone_destroy(item_zone);
+}
+
+/*
+ * xfs_filestream_mount() is called when a file system is mounted with the
+ * filestream option. It is responsible for allocating the data structures
+ * needed to track the new file system's file streams.
+ */
+int
+xfs_filestream_mount(
+ xfs_mount_t *mp)
+{
+ int err;
+ unsigned int lifetime, grp_count;
+
+ /*
+ * The filestream timer tunable is currently fixed within the range of
+ * one second to four minutes, with five seconds being the default. The
+ * group count is somewhat arbitrary, but it'd be nice to adhere to the
+ * timer tunable to within about 10 percent. This requires at least 10
+ * groups.
+ */
+ lifetime = xfs_fstrm_centisecs * 10;
+ grp_count = 10;
+
+ err = xfs_mru_cache_create(&mp->m_filestream, lifetime, grp_count,
+ (xfs_mru_cache_free_func_t)xfs_fstrm_free_func);
+
+ return err;
+}
+
+/*
+ * xfs_filestream_unmount() is called when a file system that was mounted with
+ * the filestream option is unmounted. It drains the data structures created
+ * to track the file system's file streams and frees all the memory that was
+ * allocated.
+ */
+void
+xfs_filestream_unmount(
+ xfs_mount_t *mp)
+{
+ xfs_mru_cache_destroy(mp->m_filestream);
+}
+
+/*
+ * If the mount point's m_perag array is going to be reallocated, all
+ * outstanding cache entries must be flushed to avoid accessing reference count
+ * addresses that have been freed. The call to xfs_filestream_flush() must be
+ * made inside the block that holds the m_peraglock in write mode to do the
+ * reallocation.
+ */
+void
+xfs_filestream_flush(
+ xfs_mount_t *mp)
+{
+ /* point in time flush, so keep the reaper running */
+ xfs_mru_cache_flush(mp->m_filestream, 1);
+}
+
+/*
+ * Return the AG of the filestream the file or directory belongs to, or
+ * NULLAGNUMBER otherwise.
+ */
+xfs_agnumber_t
+xfs_filestream_lookup_ag(
+ xfs_inode_t *ip)
+{
+ xfs_mru_cache_t *cache;
+ fstrm_item_t *item;
+ xfs_agnumber_t ag;
+ int ref;
+
+ if (!(ip->i_d.di_mode & (S_IFREG | S_IFDIR))) {
+ ASSERT(0);
+ return NULLAGNUMBER;
+ }
+
+ cache = ip->i_mount->m_filestream;
+ item = xfs_mru_cache_lookup(cache, ip->i_ino);
+ if (!item) {
+ TRACE_LOOKUP(ip->i_mount, ip, NULL, NULLAGNUMBER, 0);
+ return NULLAGNUMBER;
+ }
+
+ ASSERT(ip == item->ip);
+ ag = item->ag;
+ ref = xfs_filestream_peek_ag(ip->i_mount, ag);
+ xfs_mru_cache_done(cache);
+
+ TRACE_LOOKUP(ip->i_mount, ip, item->pip, ag, ref);
+ return ag;
+}
+
+/*
+ * xfs_filestream_associate() should only be called to associate a regular file
+ * with its parent directory. Calling it with a child directory isn't
+ * appropriate because filestreams don't apply to entire directory hierarchies.
+ * Creating a file in a child directory of an existing filestream directory
+ * starts a new filestream with its own allocation group association.
+ *
+ * Returns < 0 on error, 0 if successful association occurred, > 0 if
+ * we failed to get an association because of locking issues.
+ */
+int
+xfs_filestream_associate(
+ xfs_inode_t *pip,
+ xfs_inode_t *ip)
+{
+ xfs_mount_t *mp;
+ xfs_mru_cache_t *cache;
+ fstrm_item_t *item;
+ xfs_agnumber_t ag, rotorstep, startag;
+ int err = 0;
+
+ ASSERT(pip->i_d.di_mode & S_IFDIR);
+ ASSERT(ip->i_d.di_mode & S_IFREG);
+ if (!(pip->i_d.di_mode & S_IFDIR) || !(ip->i_d.di_mode & S_IFREG))
+ return -EINVAL;
+
+ mp = pip->i_mount;
+ cache = mp->m_filestream;
+ down_read(&mp->m_peraglock);
+
+ /*
+ * We have a problem, Houston.
+ *
+ * Taking the iolock here violates inode locking order - we already
+ * hold the ilock. Hence if we block getting this lock we may never
+ * wake. Unfortunately, that means if we can't get the lock, we're
+ * screwed in terms of getting a stream association - we can't spin
+ * waiting for the lock because someone else is waiting on the lock we
+ * hold and we cannot drop that as we are in a transaction here.
+ *
+ * Lucky for us, this inversion is rarely a problem because it's a
+ * directory inode that we are trying to lock here and that means the
+ * only place that matters is xfs_sync_inodes() and SYNC_DELWRI is
+ * used. i.e. freeze, remount-ro, quotasync or unmount.
+ *
+ * So, if we can't get the iolock without sleeping then just give up
+ */
+ if (!xfs_ilock_nowait(pip, XFS_IOLOCK_EXCL)) {
+ up_read(&mp->m_peraglock);
+ return 1;
+ }
+
+ /* If the parent directory is already in the cache, use its AG. */
+ item = xfs_mru_cache_lookup(cache, pip->i_ino);
+ if (item) {
+ ASSERT(item->ip == pip);
+ ag = item->ag;
+ xfs_mru_cache_done(cache);
+
+ TRACE_LOOKUP(mp, pip, pip, ag, xfs_filestream_peek_ag(mp, ag));
+ err = _xfs_filestream_update_ag(ip, pip, ag);
+
+ goto exit;
+ }
+
+ /*
+ * Set the starting AG using the rotor for inode32, otherwise
+ * use the directory inode's AG.
+ */
+ if (mp->m_flags & XFS_MOUNT_32BITINODES) {
+ rotorstep = xfs_rotorstep;
+ startag = (mp->m_agfrotor / rotorstep) % mp->m_sb.sb_agcount;
+ mp->m_agfrotor = (mp->m_agfrotor + 1) %
+ (mp->m_sb.sb_agcount * rotorstep);
+ } else
+ startag = XFS_INO_TO_AGNO(mp, pip->i_ino);
+
+ /* Pick a new AG for the parent inode starting at startag. */
+ err = _xfs_filestream_pick_ag(mp, startag, &ag, 0, 0);
+ if (err || ag == NULLAGNUMBER)
+ goto exit_did_pick;
+
+ /* Associate the parent inode with the AG. */
+ err = _xfs_filestream_update_ag(pip, NULL, ag);
+ if (err)
+ goto exit_did_pick;
+
+ /* Associate the file inode with the AG. */
+ err = _xfs_filestream_update_ag(ip, pip, ag);
+ if (err)
+ goto exit_did_pick;
+
+ TRACE_ASSOCIATE(mp, ip, pip, ag, xfs_filestream_peek_ag(mp, ag));
+
+exit_did_pick:
+ /*
+ * If _xfs_filestream_pick_ag() returned a valid AG, remove the
+ * reference it took on it, since the file and directory will have taken
+ * their own now if they were successfully cached.
+ */
+ if (ag != NULLAGNUMBER)
+ xfs_filestream_put_ag(mp, ag);
+
+exit:
+ xfs_iunlock(pip, XFS_IOLOCK_EXCL);
+ up_read(&mp->m_peraglock);
+ return -err;
+}
+
+/*
+ * Pick a new allocation group for the current file and its file stream. This
+ * function is called by xfs_bmap_filestreams() with the mount point's per-ag
+ * lock held.
+ */
+int
+xfs_filestream_new_ag(
+ xfs_bmalloca_t *ap,
+ xfs_agnumber_t *agp)
+{
+ int flags, err;
+ xfs_inode_t *ip, *pip = NULL;
+ xfs_mount_t *mp;
+ xfs_mru_cache_t *cache;
+ xfs_extlen_t minlen;
+ fstrm_item_t *dir, *file;
+ xfs_agnumber_t ag = NULLAGNUMBER;
+
+ ip = ap->ip;
+ mp = ip->i_mount;
+ cache = mp->m_filestream;
+ minlen = ap->alen;
+ *agp = NULLAGNUMBER;
+
+ /*
+ * Look for the file in the cache, removing it if it's found. Doing
+ * this allows it to be held across the dir lookup that follows.
+ */
+ file = xfs_mru_cache_remove(cache, ip->i_ino);
+ if (file) {
+ ASSERT(ip == file->ip);
+
+ /* Save the file's parent inode and old AG number for later. */
+ pip = file->pip;
+ ag = file->ag;
+
+ /* Look for the file's directory in the cache. */
+ dir = xfs_mru_cache_lookup(cache, pip->i_ino);
+ if (dir) {
+ ASSERT(pip == dir->ip);
+
+ /*
+ * If the directory has already moved on to a new AG,
+ * use that AG as the new AG for the file. Don't
+ * forget to twiddle the AG refcounts to match the
+ * movement.
+ */
+ if (dir->ag != file->ag) {
+ xfs_filestream_put_ag(mp, file->ag);
+ xfs_filestream_get_ag(mp, dir->ag);
+ *agp = file->ag = dir->ag;
+ }
+
+ xfs_mru_cache_done(cache);
+ }
+
+ /*
+ * Put the file back in the cache. If this fails, the free
+ * function needs to be called to tidy up in the same way as if
+ * the item had simply expired from the cache.
+ */
+ err = xfs_mru_cache_insert(cache, ip->i_ino, file);
+ if (err) {
+ xfs_fstrm_free_func(ip->i_ino, file);
+ return err;
+ }
+
+ /*
+ * If the file's AG was moved to the directory's new AG, there's
+ * nothing more to be done.
+ */
+ if (*agp != NULLAGNUMBER) {
+ TRACE_MOVEAG(mp, ip, pip,
+ ag, xfs_filestream_peek_ag(mp, ag),
+ *agp, xfs_filestream_peek_ag(mp, *agp));
+ return 0;
+ }
+ }
+
+ /*
+ * If the file's parent directory is known, take its iolock in exclusive
+ * mode to prevent two sibling files from racing each other to migrate
+ * themselves and their parent to different AGs.
+ */
+ if (pip)
+ xfs_ilock(pip, XFS_IOLOCK_EXCL);
+
+ /*
+ * A new AG needs to be found for the file. If the file's parent
+ * directory is also known, it will be moved to the new AG as well to
+ * ensure that files created inside it in future use the new AG.
+ */
+ ag = (ag == NULLAGNUMBER) ? 0 : (ag + 1) % mp->m_sb.sb_agcount;
+ flags = (ap->userdata ? XFS_PICK_USERDATA : 0) |
+ (ap->low ? XFS_PICK_LOWSPACE : 0);
+
+ err = _xfs_filestream_pick_ag(mp, ag, agp, flags, minlen);
+ if (err || *agp == NULLAGNUMBER)
+ goto exit;
+
+ /*
+ * If the file wasn't found in the file cache, then its parent directory
+ * inode isn't known. For this to have happened, the file must either
+ * be pre-existing, or it was created long enough ago that its cache
+ * entry has expired. This isn't the sort of usage that the filestreams
+ * allocator is trying to optimise, so there's no point trying to track
+ * its new AG somehow in the filestream data structures.
+ */
+ if (!pip) {
+ TRACE_ORPHAN(mp, ip, *agp);
+ goto exit;
+ }
+
+ /* Associate the parent inode with the AG. */
+ err = _xfs_filestream_update_ag(pip, NULL, *agp);
+ if (err)
+ goto exit;
+
+ /* Associate the file inode with the AG. */
+ err = _xfs_filestream_update_ag(ip, pip, *agp);
+ if (err)
+ goto exit;
+
+ TRACE_MOVEAG(mp, ip, pip, NULLAGNUMBER, 0,
+ *agp, xfs_filestream_peek_ag(mp, *agp));
+
+exit:
+ /*
+ * If _xfs_filestream_pick_ag() returned a valid AG, remove the
+ * reference it took on it, since the file and directory will have taken
+ * their own now if they were successfully cached.
+ */
+ if (*agp != NULLAGNUMBER)
+ xfs_filestream_put_ag(mp, *agp);
+ else
+ *agp = 0;
+
+ if (pip)
+ xfs_iunlock(pip, XFS_IOLOCK_EXCL);
+
+ return err;
+}
+
+/*
+ * Remove an association between an inode and a filestream object.
+ * Typically this is done on last close of an unlinked file.
+ */
+void
+xfs_filestream_deassociate(
+ xfs_inode_t *ip)
+{
+ xfs_mru_cache_t *cache = ip->i_mount->m_filestream;
+
+ xfs_mru_cache_delete(cache, ip->i_ino);
+}
diff --git a/fs/xfs/xfs_filestream.h b/fs/xfs/xfs_filestream.h
new file mode 100644
index 00000000000..f655f7dc334
--- /dev/null
+++ b/fs/xfs/xfs_filestream.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2006-2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __XFS_FILESTREAM_H__
+#define __XFS_FILESTREAM_H__
+
+#ifdef __KERNEL__
+
+struct xfs_mount;
+struct xfs_inode;
+struct xfs_perag;
+struct xfs_bmalloca;
+
+#ifdef XFS_FILESTREAMS_TRACE
+#define XFS_FSTRM_KTRACE_INFO 1
+#define XFS_FSTRM_KTRACE_AGSCAN 2
+#define XFS_FSTRM_KTRACE_AGPICK1 3
+#define XFS_FSTRM_KTRACE_AGPICK2 4
+#define XFS_FSTRM_KTRACE_UPDATE 5
+#define XFS_FSTRM_KTRACE_FREE 6
+#define XFS_FSTRM_KTRACE_ITEM_LOOKUP 7
+#define XFS_FSTRM_KTRACE_ASSOCIATE 8
+#define XFS_FSTRM_KTRACE_MOVEAG 9
+#define XFS_FSTRM_KTRACE_ORPHAN 10
+
+#define XFS_FSTRM_KTRACE_SIZE 16384
+extern ktrace_t *xfs_filestreams_trace_buf;
+
+#endif
+
+/*
+ * Allocation group filestream associations are tracked with per-ag atomic
+ * counters. These counters allow _xfs_filestream_pick_ag() to tell whether a
+ * particular AG already has active filestreams associated with it. The mount
+ * point's m_peraglock is used to protect these counters from per-ag array
+ * re-allocation during a growfs operation. When xfs_growfs_data_private() is
+ * about to reallocate the array, it calls xfs_filestream_flush() with the
+ * m_peraglock held in write mode.
+ *
+ * Since xfs_mru_cache_flush() guarantees that all the free functions for all
+ * the cache elements have finished executing before it returns, it's safe for
+ * the free functions to use the atomic counters without m_peraglock protection.
+ * This allows the implementation of xfs_fstrm_free_func() to be agnostic about
+ * whether it was called with the m_peraglock held in read mode, write mode or
+ * not held at all. The race condition this addresses is the following:
+ *
+ * - The work queue scheduler fires and pulls a filestream directory cache
+ * element off the LRU end of the cache for deletion, then gets pre-empted.
+ * - A growfs operation grabs the m_peraglock in write mode, flushes all the
+ * remaining items from the cache and reallocates the mount point's per-ag
+ * array, resetting all the counters to zero.
+ * - The work queue thread resumes and calls the free function for the element
+ * it started cleaning up earlier. In the process it decrements the
+ * filestreams counter for an AG that now has no references.
+ *
+ * With a shrinkfs feature, the above scenario could panic the system.
+ *
+ * All other uses of the following macros should be protected by either the
+ * m_peraglock held in read mode, or the cache's internal locking exposed by the
+ * interval between a call to xfs_mru_cache_lookup() and a call to
+ * xfs_mru_cache_done(). In addition, the m_peraglock must be held in read mode
+ * when new elements are added to the cache.
+ *
+ * Combined, these locking rules ensure that no associations will ever exist in
+ * the cache that reference per-ag array elements that have since been
+ * reallocated.
+ */
+STATIC_INLINE int
+xfs_filestream_peek_ag(
+ xfs_mount_t *mp,
+ xfs_agnumber_t agno)
+{
+ return atomic_read(&mp->m_perag[agno].pagf_fstrms);
+}
+
+STATIC_INLINE int
+xfs_filestream_get_ag(
+ xfs_mount_t *mp,
+ xfs_agnumber_t agno)
+{
+ return atomic_inc_return(&mp->m_perag[agno].pagf_fstrms);
+}
+
+STATIC_INLINE int
+xfs_filestream_put_ag(
+ xfs_mount_t *mp,
+ xfs_agnumber_t agno)
+{
+ return atomic_dec_return(&mp->m_perag[agno].pagf_fstrms);
+}
+
+/* allocation selection flags */
+typedef enum xfs_fstrm_alloc {
+ XFS_PICK_USERDATA = 1,
+ XFS_PICK_LOWSPACE = 2,
+} xfs_fstrm_alloc_t;
+
+/* prototypes for filestream.c */
+int xfs_filestream_init(void);
+void xfs_filestream_uninit(void);
+int xfs_filestream_mount(struct xfs_mount *mp);
+void xfs_filestream_unmount(struct xfs_mount *mp);
+void xfs_filestream_flush(struct xfs_mount *mp);
+xfs_agnumber_t xfs_filestream_lookup_ag(struct xfs_inode *ip);
+int xfs_filestream_associate(struct xfs_inode *dip, struct xfs_inode *ip);
+void xfs_filestream_deassociate(struct xfs_inode *ip);
+int xfs_filestream_new_ag(struct xfs_bmalloca *ap, xfs_agnumber_t *agp);
+
+
+/* filestreams for the inode? */
+STATIC_INLINE int
+xfs_inode_is_filestream(
+ struct xfs_inode *ip)
+{
+ return (ip->i_mount->m_flags & XFS_MOUNT_FILESTREAMS) ||
+ xfs_iflags_test(ip, XFS_IFILESTREAM) ||
+ (ip->i_d.di_flags & XFS_DIFLAG_FILESTREAM);
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __XFS_FILESTREAM_H__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 1335449841c..ec3c9c27e0d 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -66,6 +66,7 @@ struct fsxattr {
#define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */
#define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */
#define XFS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */
+#define XFS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */
#define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */
/*
@@ -238,6 +239,7 @@ typedef struct xfs_fsop_resblks {
#define XFS_FSOP_GEOM_FLAGS_LOGV2 0x0100 /* log format version 2 */
#define XFS_FSOP_GEOM_FLAGS_SECTOR 0x0200 /* sector sizes >1BB */
#define XFS_FSOP_GEOM_FLAGS_ATTR2 0x0400 /* inline attributes rework */
+#define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */
/*
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index b599e6be9ec..432e82347ed 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -44,6 +44,7 @@
#include "xfs_trans_space.h"
#include "xfs_rtalloc.h"
#include "xfs_rw.h"
+#include "xfs_filestream.h"
/*
* File system operations
@@ -94,6 +95,8 @@ xfs_fs_geometry(
XFS_FSOP_GEOM_FLAGS_DIRV2 : 0) |
(XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
XFS_FSOP_GEOM_FLAGS_SECTOR : 0) |
+ (xfs_sb_version_haslazysbcount(&mp->m_sb) ?
+ XFS_FSOP_GEOM_FLAGS_LAZYSB : 0) |
(XFS_SB_VERSION_HASATTR2(&mp->m_sb) ?
XFS_FSOP_GEOM_FLAGS_ATTR2 : 0);
geo->logsectsize = XFS_SB_VERSION_HASSECTOR(&mp->m_sb) ?
@@ -140,6 +143,8 @@ xfs_growfs_data_private(
pct = in->imaxpct;
if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
return XFS_ERROR(EINVAL);
+ if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
+ return error;
dpct = pct - mp->m_sb.sb_imax_pct;
error = xfs_read_buf(mp, mp->m_ddev_targp,
XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
@@ -161,6 +166,7 @@ xfs_growfs_data_private(
new = nb - mp->m_sb.sb_dblocks;
oagcount = mp->m_sb.sb_agcount;
if (nagcount > oagcount) {
+ xfs_filestream_flush(mp);
down_write(&mp->m_peraglock);
mp->m_perag = kmem_realloc(mp->m_perag,
sizeof(xfs_perag_t) * nagcount,
@@ -173,6 +179,7 @@ xfs_growfs_data_private(
up_write(&mp->m_peraglock);
}
tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
+ tp->t_flags |= XFS_TRANS_RESERVE;
if ((error = xfs_trans_reserve(tp, XFS_GROWFS_SPACE_RES(mp),
XFS_GROWDATA_LOG_RES(mp), 0, 0, 0))) {
xfs_trans_cancel(tp, 0);
@@ -328,6 +335,7 @@ xfs_growfs_data_private(
be32_add(&agf->agf_length, new);
ASSERT(be32_to_cpu(agf->agf_length) ==
be32_to_cpu(agi->agi_length));
+ xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH);
/*
* Free the new space.
*/
@@ -494,8 +502,9 @@ xfs_reserve_blocks(
unsigned long s;
/* If inval is null, report current values and return */
-
if (inval == (__uint64_t *)NULL) {
+ if (!outval)
+ return EINVAL;
outval->resblks = mp->m_resblks;
outval->resblks_avail = mp->m_resblks_avail;
return 0;
@@ -558,8 +567,10 @@ retry:
}
}
out:
- outval->resblks = mp->m_resblks;
- outval->resblks_avail = mp->m_resblks_avail;
+ if (outval) {
+ outval->resblks = mp->m_resblks;
+ outval->resblks_avail = mp->m_resblks_avail;
+ }
XFS_SB_UNLOCK(mp, s);
if (fdblks_delta) {
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index b5feb3e7711..f943368c9b9 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -123,6 +123,7 @@ xfs_ialloc_ag_alloc(
int blks_per_cluster; /* fs blocks per inode cluster */
xfs_btree_cur_t *cur; /* inode btree cursor */
xfs_daddr_t d; /* disk addr of buffer */
+ xfs_agnumber_t agno;
int error;
xfs_buf_t *fbuf; /* new free inodes' buffer */
xfs_dinode_t *free; /* new free inode structure */
@@ -302,15 +303,15 @@ xfs_ialloc_ag_alloc(
}
be32_add(&agi->agi_count, newlen);
be32_add(&agi->agi_freecount, newlen);
+ agno = be32_to_cpu(agi->agi_seqno);
down_read(&args.mp->m_peraglock);
- args.mp->m_perag[be32_to_cpu(agi->agi_seqno)].pagi_freecount += newlen;
+ args.mp->m_perag[agno].pagi_freecount += newlen;
up_read(&args.mp->m_peraglock);
agi->agi_newino = cpu_to_be32(newino);
/*
* Insert records describing the new inode chunk into the btree.
*/
- cur = xfs_btree_init_cursor(args.mp, tp, agbp,
- be32_to_cpu(agi->agi_seqno),
+ cur = xfs_btree_init_cursor(args.mp, tp, agbp, agno,
XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
for (thisino = newino;
thisino < newino + newlen;
@@ -1387,6 +1388,7 @@ xfs_ialloc_read_agi(
pag = &mp->m_perag[agno];
if (!pag->pagi_init) {
pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
+ pag->pagi_count = be32_to_cpu(agi->agi_count);
pag->pagi_init = 1;
} else {
/*
@@ -1410,3 +1412,23 @@ xfs_ialloc_read_agi(
*bpp = bp;
return 0;
}
+
+/*
+ * Read in the agi to initialise the per-ag data in the mount structure
+ */
+int
+xfs_ialloc_pagi_init(
+ xfs_mount_t *mp, /* file system mount structure */
+ xfs_trans_t *tp, /* transaction pointer */
+ xfs_agnumber_t agno) /* allocation group number */
+{
+ xfs_buf_t *bp = NULL;
+ int error;
+
+ error = xfs_ialloc_read_agi(mp, tp, agno, &bp);
+ if (error)
+ return error;
+ if (bp)
+ xfs_trans_brelse(tp, bp);
+ return 0;
+}
diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h
index 7f5debe1acb..97f4040931c 100644
--- a/fs/xfs/xfs_ialloc.h
+++ b/fs/xfs/xfs_ialloc.h
@@ -149,6 +149,16 @@ xfs_ialloc_read_agi(
xfs_agnumber_t agno, /* allocation group number */
struct xfs_buf **bpp); /* allocation group hdr buf */
+/*
+ * Read in the allocation group header to initialise the per-ag data
+ * in the mount structure
+ */
+int
+xfs_ialloc_pagi_init(
+ struct xfs_mount *mp, /* file system mount structure */
+ struct xfs_trans *tp, /* transaction pointer */
+ xfs_agnumber_t agno); /* allocation group number */
+
#endif /* __KERNEL__ */
#endif /* __XFS_IALLOC_H__ */
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 3ca5d43b834..cdc4c28926d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -48,7 +48,9 @@
#include "xfs_dir2_trace.h"
#include "xfs_quota.h"
#include "xfs_acl.h"
+#include "xfs_filestream.h"
+#include <linux/log2.h>
kmem_zone_t *xfs_ifork_zone;
kmem_zone_t *xfs_inode_zone;
@@ -643,8 +645,7 @@ xfs_iformat_extents(
ep->l1 = INT_GET(get_unaligned((__uint64_t*)&dp->l1),
ARCH_CONVERT);
}
- xfs_bmap_trace_exlist("xfs_iformat_extents", ip, nex,
- whichfork);
+ XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
if (whichfork != XFS_DATA_FORK ||
XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE)
if (unlikely(xfs_check_nostate_extents(
@@ -817,6 +818,8 @@ _xfs_dic2xflags(
flags |= XFS_XFLAG_EXTSZINHERIT;
if (di_flags & XFS_DIFLAG_NODEFRAG)
flags |= XFS_XFLAG_NODEFRAG;
+ if (di_flags & XFS_DIFLAG_FILESTREAM)
+ flags |= XFS_XFLAG_FILESTREAM;
}
return flags;
@@ -1074,6 +1077,11 @@ xfs_iread_extents(
* also returns the [locked] bp pointing to the head of the freelist
* as ialloc_context. The caller should hold this buffer across
* the commit and pass it back into this routine on the second call.
+ *
+ * If we are allocating quota inodes, we do not have a parent inode
+ * to attach to or associate with (i.e. pip == NULL) because they
+ * are not linked into the directory structure - they are attached
+ * directly to the superblock - and so have no parent.
*/
int
xfs_ialloc(
@@ -1099,7 +1107,7 @@ xfs_ialloc(
* Call the space management code to pick
* the on-disk inode to be allocated.
*/
- error = xfs_dialloc(tp, pip->i_ino, mode, okalloc,
+ error = xfs_dialloc(tp, pip ? pip->i_ino : 0, mode, okalloc,
ialloc_context, call_again, &ino);
if (error != 0) {
return error;
@@ -1150,10 +1158,10 @@ xfs_ialloc(
/*
* Project ids won't be stored on disk if we are using a version 1 inode.
*/
- if ( (prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
+ if ((prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
xfs_bump_ino_vers2(tp, ip);
- if (XFS_INHERIT_GID(pip, vp->v_vfsp)) {
+ if (pip && XFS_INHERIT_GID(pip, vp->v_vfsp)) {
ip->i_d.di_gid = pip->i_d.di_gid;
if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
ip->i_d.di_mode |= S_ISGID;
@@ -1195,8 +1203,16 @@ xfs_ialloc(
flags |= XFS_ILOG_DEV;
break;
case S_IFREG:
+ if (pip && xfs_inode_is_filestream(pip)) {
+ error = xfs_filestream_associate(pip, ip);
+ if (error < 0)
+ return -error;
+ if (!error)
+ xfs_iflags_set(ip, XFS_IFILESTREAM);
+ }
+ /* fall through */
case S_IFDIR:
- if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
+ if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
uint di_flags = 0;
if ((mode & S_IFMT) == S_IFDIR) {
@@ -1233,6 +1249,8 @@ xfs_ialloc(
if ((pip->i_d.di_flags & XFS_DIFLAG_NODEFRAG) &&
xfs_inherit_nodefrag)
di_flags |= XFS_DIFLAG_NODEFRAG;
+ if (pip->i_d.di_flags & XFS_DIFLAG_FILESTREAM)
+ di_flags |= XFS_DIFLAG_FILESTREAM;
ip->i_d.di_flags |= di_flags;
}
/* FALLTHROUGH */
@@ -2875,9 +2893,6 @@ xfs_iextents_copy(
int copied;
xfs_bmbt_rec_t *dest_ep;
xfs_bmbt_rec_t *ep;
-#ifdef XFS_BMAP_TRACE
- static char fname[] = "xfs_iextents_copy";
-#endif
int i;
xfs_ifork_t *ifp;
int nrecs;
@@ -2888,7 +2903,7 @@ xfs_iextents_copy(
ASSERT(ifp->if_bytes > 0);
nrecs = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
- xfs_bmap_trace_exlist(fname, ip, nrecs, whichfork);
+ XFS_BMAP_TRACE_EXLIST(ip, nrecs, whichfork);
ASSERT(nrecs > 0);
/*
@@ -4184,7 +4199,7 @@ xfs_iext_realloc_direct(
ifp->if_bytes = new_size;
return;
}
- if ((new_size & (new_size - 1)) != 0) {
+ if (!is_power_of_2(new_size)){
rnew_size = xfs_iroundup(new_size);
}
if (rnew_size != ifp->if_real_bytes) {
@@ -4207,7 +4222,7 @@ xfs_iext_realloc_direct(
*/
else {
new_size += ifp->if_bytes;
- if ((new_size & (new_size - 1)) != 0) {
+ if (!is_power_of_2(new_size)) {
rnew_size = xfs_iroundup(new_size);
}
xfs_iext_inline_to_direct(ifp, rnew_size);
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index f75afecef8e..012dfd4a958 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -379,6 +379,7 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
#define XFS_ISTALE 0x0010 /* inode has been staled */
#define XFS_IRECLAIMABLE 0x0020 /* inode can be reclaimed */
#define XFS_INEW 0x0040
+#define XFS_IFILESTREAM 0x0080 /* inode is in a filestream directory */
/*
* Flags for inode locking.
@@ -414,19 +415,22 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
* gets a lockdep subclass of 1 and the second lock will have a lockdep
* subclass of 0.
*
- * XFS_I[O]LOCK_INUMORDER - for locking several inodes at the some time
+ * XFS_LOCK_INUMORDER - for locking several inodes at the some time
* with xfs_lock_inodes(). This flag is used as the starting subclass
* and each subsequent lock acquired will increment the subclass by one.
* So the first lock acquired will have a lockdep subclass of 2, the
- * second lock will have a lockdep subclass of 3, and so on.
+ * second lock will have a lockdep subclass of 3, and so on. It is
+ * the responsibility of the class builder to shift this to the correct
+ * portion of the lock_mode lockdep mask.
*/
+#define XFS_LOCK_PARENT 1
+#define XFS_LOCK_INUMORDER 2
+
#define XFS_IOLOCK_SHIFT 16
-#define XFS_IOLOCK_PARENT (1 << XFS_IOLOCK_SHIFT)
-#define XFS_IOLOCK_INUMORDER (2 << XFS_IOLOCK_SHIFT)
+#define XFS_IOLOCK_PARENT (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT)
#define XFS_ILOCK_SHIFT 24
-#define XFS_ILOCK_PARENT (1 << XFS_ILOCK_SHIFT)
-#define XFS_ILOCK_INUMORDER (2 << XFS_ILOCK_SHIFT)
+#define XFS_ILOCK_PARENT (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT)
#define XFS_IOLOCK_DEP_MASK 0x00ff0000
#define XFS_ILOCK_DEP_MASK 0xff000000
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 3f2b9f2a7b9..bf57b75acb9 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -451,19 +451,14 @@ xfs_iomap_write_direct(
return XFS_ERROR(error);
rt = XFS_IS_REALTIME_INODE(ip);
- if (unlikely(rt)) {
- if (!(extsz = ip->i_d.di_extsize))
- extsz = mp->m_sb.sb_rextsize;
- } else {
- extsz = ip->i_d.di_extsize;
- }
+ extsz = xfs_get_extsz_hint(ip);
isize = ip->i_size;
if (io->io_new_size > isize)
isize = io->io_new_size;
- offset_fsb = XFS_B_TO_FSBT(mp, offset);
- last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
+ offset_fsb = XFS_B_TO_FSBT(mp, offset);
+ last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count)));
if ((offset + count) > isize) {
error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz,
&last_fsb);
@@ -489,13 +484,13 @@ xfs_iomap_write_direct(
if (unlikely(rt)) {
resrtextents = qblocks = resaligned;
resrtextents /= mp->m_sb.sb_rextsize;
- resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
- quota_flag = XFS_QMOPT_RES_RTBLKS;
- } else {
- resrtextents = 0;
+ resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
+ quota_flag = XFS_QMOPT_RES_RTBLKS;
+ } else {
+ resrtextents = 0;
resblks = qblocks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
- quota_flag = XFS_QMOPT_RES_REGBLKS;
- }
+ quota_flag = XFS_QMOPT_RES_REGBLKS;
+ }
/*
* Allocate and setup the transaction
@@ -666,13 +661,7 @@ xfs_iomap_write_delay(
if (error)
return XFS_ERROR(error);
- if (XFS_IS_REALTIME_INODE(ip)) {
- if (!(extsz = ip->i_d.di_extsize))
- extsz = mp->m_sb.sb_rextsize;
- } else {
- extsz = ip->i_d.di_extsize;
- }
-
+ extsz = xfs_get_extsz_hint(ip);
offset_fsb = XFS_B_TO_FSBT(mp, offset);
retry:
@@ -788,18 +777,12 @@ xfs_iomap_write_allocate(
nimaps = 0;
while (nimaps == 0) {
tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
+ tp->t_flags |= XFS_TRANS_RESERVE;
nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
error = xfs_trans_reserve(tp, nres,
XFS_WRITE_LOG_RES(mp),
0, XFS_TRANS_PERM_LOG_RES,
XFS_WRITE_LOG_COUNT);
- if (error == ENOSPC) {
- error = xfs_trans_reserve(tp, 0,
- XFS_WRITE_LOG_RES(mp),
- 0,
- XFS_TRANS_PERM_LOG_RES,
- XFS_WRITE_LOG_COUNT);
- }
if (error) {
xfs_trans_cancel(tp, 0);
return XFS_ERROR(error);
@@ -917,8 +900,8 @@ xfs_iomap_write_unwritten(
* from unwritten to real. Do allocations in a loop until
* we have covered the range passed in.
*/
-
tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE);
+ tp->t_flags |= XFS_TRANS_RESERVE;
error = xfs_trans_reserve(tp, resblks,
XFS_WRITE_LOG_RES(mp), 0,
XFS_TRANS_PERM_LOG_RES,
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index e725ddd3de5..4c2454bcc71 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -202,6 +202,16 @@ xfs_bulkstat_one_dinode(
return 0;
}
+STATIC int
+xfs_bulkstat_one_fmt(
+ void __user *ubuffer,
+ const xfs_bstat_t *buffer)
+{
+ if (copy_to_user(ubuffer, buffer, sizeof(*buffer)))
+ return -EFAULT;
+ return sizeof(*buffer);
+}
+
/*
* Return stat information for one inode.
* Return 0 if ok, else errno.
@@ -221,6 +231,7 @@ xfs_bulkstat_one(
xfs_bstat_t *buf; /* return buffer */
int error = 0; /* error value */
xfs_dinode_t *dip; /* dinode inode pointer */
+ bulkstat_one_fmt_pf formatter = private_data ? : xfs_bulkstat_one_fmt;
dip = (xfs_dinode_t *)dibuff;
*stat = BULKSTAT_RV_NOTHING;
@@ -243,14 +254,15 @@ xfs_bulkstat_one(
xfs_bulkstat_one_dinode(mp, ino, dip, buf);
}
- if (copy_to_user(buffer, buf, sizeof(*buf))) {
+ error = formatter(buffer, buf);
+ if (error < 0) {
error = EFAULT;
goto out_free;
}
*stat = BULKSTAT_RV_DIDONE;
if (ubused)
- *ubused = sizeof(*buf);
+ *ubused = error;
out_free:
kmem_free(buf, sizeof(*buf));
@@ -748,6 +760,19 @@ xfs_bulkstat_single(
return 0;
}
+int
+xfs_inumbers_fmt(
+ void __user *ubuffer, /* buffer to write to */
+ const xfs_inogrp_t *buffer, /* buffer to read from */
+ long count, /* # of elements to read */
+ long *written) /* # of bytes written */
+{
+ if (copy_to_user(ubuffer, buffer, count * sizeof(*buffer)))
+ return -EFAULT;
+ *written = count * sizeof(*buffer);
+ return 0;
+}
+
/*
* Return inode number table for the filesystem.
*/
@@ -756,7 +781,8 @@ xfs_inumbers(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_ino_t *lastino, /* last inode returned */
int *count, /* size of buffer/count returned */
- xfs_inogrp_t __user *ubuffer)/* buffer with inode descriptions */
+ void __user *ubuffer,/* buffer with inode descriptions */
+ inumbers_fmt_pf formatter)
{
xfs_buf_t *agbp;
xfs_agino_t agino;
@@ -835,12 +861,12 @@ xfs_inumbers(
bufidx++;
left--;
if (bufidx == bcount) {
- if (copy_to_user(ubuffer, buffer,
- bufidx * sizeof(*buffer))) {
+ long written;
+ if (formatter(ubuffer, buffer, bufidx, &written)) {
error = XFS_ERROR(EFAULT);
break;
}
- ubuffer += bufidx;
+ ubuffer += written;
*count += bufidx;
bufidx = 0;
}
@@ -862,8 +888,8 @@ xfs_inumbers(
}
if (!error) {
if (bufidx) {
- if (copy_to_user(ubuffer, buffer,
- bufidx * sizeof(*buffer)))
+ long written;
+ if (formatter(ubuffer, buffer, bufidx, &written))
error = XFS_ERROR(EFAULT);
else
*count += bufidx;
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index f25a28862a1..a1f18fce9b7 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -69,6 +69,10 @@ xfs_bulkstat_single(
char __user *buffer,
int *done);
+typedef int (*bulkstat_one_fmt_pf)( /* used size in bytes or negative error */
+ void __user *ubuffer, /* buffer to write to */
+ const xfs_bstat_t *buffer); /* buffer to read from */
+
int
xfs_bulkstat_one(
xfs_mount_t *mp,
@@ -86,11 +90,25 @@ xfs_internal_inum(
xfs_mount_t *mp,
xfs_ino_t ino);
+typedef int (*inumbers_fmt_pf)(
+ void __user *ubuffer, /* buffer to write to */
+ const xfs_inogrp_t *buffer, /* buffer to read from */
+ long count, /* # of elements to read */
+ long *written); /* # of bytes written */
+
+int
+xfs_inumbers_fmt(
+ void __user *ubuffer, /* buffer to write to */
+ const xfs_inogrp_t *buffer, /* buffer to read from */
+ long count, /* # of elements to read */
+ long *written); /* # of bytes written */
+
int /* error status */
xfs_inumbers(
xfs_mount_t *mp, /* mount point for filesystem */
xfs_ino_t *last, /* last inode returned */
int *count, /* size of buffer/count returned */
- xfs_inogrp_t __user *buffer);/* buffer with inode info */
+ void __user *buffer, /* buffer with inode info */
+ inumbers_fmt_pf formatter);
#endif /* __XFS_ITABLE_H__ */
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index c48bf61f17b..9d4c4fbeb3e 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -817,10 +817,8 @@ xfs_log_need_covered(xfs_mount_t *mp)
SPLDECL(s);
int needed = 0, gen;
xlog_t *log = mp->m_log;
- bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
- if (vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
- (vfsp->vfs_flag & VFS_RDONLY))
+ if (!xfs_fs_writable(mp))
return 0;
s = LOG_LOCK(log);
@@ -967,14 +965,16 @@ xlog_iodone(xfs_buf_t *bp)
} else if (iclog->ic_state & XLOG_STATE_IOERROR) {
aborted = XFS_LI_ABORTED;
}
+
+ /* log I/O is always issued ASYNC */
+ ASSERT(XFS_BUF_ISASYNC(bp));
xlog_state_done_syncing(iclog, aborted);
- if (!(XFS_BUF_ISASYNC(bp))) {
- /*
- * Corresponding psema() will be done in bwrite(). If we don't
- * vsema() here, panic.
- */
- XFS_BUF_V_IODONESEMA(bp);
- }
+ /*
+ * do not reference the buffer (bp) here as we could race
+ * with it being freed after writing the unmount record to the
+ * log.
+ */
+
} /* xlog_iodone */
/*
@@ -1199,11 +1199,18 @@ xlog_alloc_log(xfs_mount_t *mp,
*iclogp = (xlog_in_core_t *)
kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
iclog = *iclogp;
- iclog->hic_data = (xlog_in_core_2_t *)
- kmem_zalloc(iclogsize, KM_SLEEP | KM_LARGE);
-
iclog->ic_prev = prev_iclog;
prev_iclog = iclog;
+
+ bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
+ if (!XFS_BUF_CPSEMA(bp))
+ ASSERT(0);
+ XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
+ XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
+ XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
+ iclog->ic_bp = bp;
+ iclog->hic_data = bp->b_addr;
+
log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
head = &iclog->ic_header;
@@ -1216,11 +1223,6 @@ xlog_alloc_log(xfs_mount_t *mp,
INT_SET(head->h_fmt, ARCH_CONVERT, XLOG_FMT);
memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
- bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
- XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
- XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
- XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
- iclog->ic_bp = bp;
iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
iclog->ic_state = XLOG_STATE_ACTIVE;
@@ -1432,7 +1434,7 @@ xlog_sync(xlog_t *log,
} else {
iclog->ic_bwritecnt = 1;
}
- XFS_BUF_SET_PTR(bp, (xfs_caddr_t) &(iclog->ic_header), count);
+ XFS_BUF_SET_COUNT(bp, count);
XFS_BUF_SET_FSPRIVATE(bp, iclog); /* save for later */
XFS_BUF_ZEROFLAGS(bp);
XFS_BUF_BUSY(bp);
@@ -1528,7 +1530,6 @@ xlog_dealloc_log(xlog_t *log)
}
#endif
next_iclog = iclog->ic_next;
- kmem_free(iclog->hic_data, log->l_iclog_size);
kmem_free(iclog, sizeof(xlog_in_core_t));
iclog = next_iclog;
}
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 080fabf61c9..fddbb091a86 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -927,6 +927,14 @@ xlog_find_tail(
ASSIGN_ANY_LSN_HOST(log->l_last_sync_lsn, log->l_curr_cycle,
after_umount_blk);
*tail_blk = after_umount_blk;
+
+ /*
+ * Note that the unmount was clean. If the unmount
+ * was not clean, we need to know this to rebuild the
+ * superblock counters from the perag headers if we
+ * have a filesystem using non-persistent counters.
+ */
+ log->l_mp->m_flags |= XFS_MOUNT_WAS_CLEAN;
}
}
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index a96bde6df96..a66b3980517 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -202,6 +202,27 @@ xfs_mount_free(
kmem_free(mp, sizeof(xfs_mount_t));
}
+/*
+ * Check size of device based on the (data/realtime) block count.
+ * Note: this check is used by the growfs code as well as mount.
+ */
+int
+xfs_sb_validate_fsb_count(
+ xfs_sb_t *sbp,
+ __uint64_t nblocks)
+{
+ ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
+ ASSERT(sbp->sb_blocklog >= BBSHIFT);
+
+#if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */
+ if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
+ return E2BIG;
+#else /* Limited by UINT_MAX of sectors */
+ if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)
+ return E2BIG;
+#endif
+ return 0;
+}
/*
* Check the validity of the SB found.
@@ -284,18 +305,8 @@ xfs_mount_validate_sb(
return XFS_ERROR(EFSCORRUPTED);
}
- ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
- ASSERT(sbp->sb_blocklog >= BBSHIFT);
-
-#if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */
- if (unlikely(
- (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX ||
- (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) {
-#else /* Limited by UINT_MAX of sectors */
- if (unlikely(
- (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
- (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
-#endif
+ if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
+ xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
xfs_fs_mount_cmn_err(flags,
"file system too large to be mounted on this system.");
return XFS_ERROR(E2BIG);
@@ -632,6 +643,64 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
sbp->sb_inopblock);
mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
}
+
+/*
+ * xfs_initialize_perag_data
+ *
+ * Read in each per-ag structure so we can count up the number of
+ * allocated inodes, free inodes and used filesystem blocks as this
+ * information is no longer persistent in the superblock. Once we have
+ * this information, write it into the in-core superblock structure.
+ */
+STATIC int
+xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
+{
+ xfs_agnumber_t index;
+ xfs_perag_t *pag;
+ xfs_sb_t *sbp = &mp->m_sb;
+ uint64_t ifree = 0;
+ uint64_t ialloc = 0;
+ uint64_t bfree = 0;
+ uint64_t bfreelst = 0;
+ uint64_t btree = 0;
+ int error;
+ int s;
+
+ for (index = 0; index < agcount; index++) {
+ /*
+ * read the agf, then the agi. This gets us
+ * all the inforamtion we need and populates the
+ * per-ag structures for us.
+ */
+ error = xfs_alloc_pagf_init(mp, NULL, index, 0);
+ if (error)
+ return error;
+
+ error = xfs_ialloc_pagi_init(mp, NULL, index);
+ if (error)
+ return error;
+ pag = &mp->m_perag[index];
+ ifree += pag->pagi_freecount;
+ ialloc += pag->pagi_count;
+ bfree += pag->pagf_freeblks;
+ bfreelst += pag->pagf_flcount;
+ btree += pag->pagf_btreeblks;
+ }
+ /*
+ * Overwrite incore superblock counters with just-read data
+ */
+ s = XFS_SB_LOCK(mp);
+ sbp->sb_ifree = ifree;
+ sbp->sb_icount = ialloc;
+ sbp->sb_fdblocks = bfree + bfreelst + btree;
+ XFS_SB_UNLOCK(mp, s);
+
+ /* Fixup the per-cpu counters as well. */
+ xfs_icsb_reinit_counters(mp);
+
+ return 0;
+}
+
/*
* xfs_mountfs
*
@@ -656,7 +725,7 @@ xfs_mountfs(
bhv_vnode_t *rvp = NULL;
int readio_log, writeio_log;
xfs_daddr_t d;
- __uint64_t ret64;
+ __uint64_t resblks;
__int64_t update_flags;
uint quotamount, quotaflags;
int agno;
@@ -773,6 +842,7 @@ xfs_mountfs(
*/
if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
(mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
+ __uint64_t ret64;
if (xfs_uuid_mount(mp)) {
error = XFS_ERROR(EINVAL);
goto error1;
@@ -976,6 +1046,34 @@ xfs_mountfs(
}
/*
+ * Now the log is mounted, we know if it was an unclean shutdown or
+ * not. If it was, with the first phase of recovery has completed, we
+ * have consistent AG blocks on disk. We have not recovered EFIs yet,
+ * but they are recovered transactionally in the second recovery phase
+ * later.
+ *
+ * Hence we can safely re-initialise incore superblock counters from
+ * the per-ag data. These may not be correct if the filesystem was not
+ * cleanly unmounted, so we need to wait for recovery to finish before
+ * doing this.
+ *
+ * If the filesystem was cleanly unmounted, then we can trust the
+ * values in the superblock to be correct and we don't need to do
+ * anything here.
+ *
+ * If we are currently making the filesystem, the initialisation will
+ * fail as the perag data is in an undefined state.
+ */
+
+ if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
+ !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
+ !mp->m_sb.sb_inprogress) {
+ error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
+ if (error) {
+ goto error2;
+ }
+ }
+ /*
* Get and sanity-check the root inode.
* Save the pointer to it in the mount structure.
*/
@@ -1044,6 +1142,23 @@ xfs_mountfs(
if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags)))
goto error4;
+ /*
+ * Now we are mounted, reserve a small amount of unused space for
+ * privileged transactions. This is needed so that transaction
+ * space required for critical operations can dip into this pool
+ * when at ENOSPC. This is needed for operations like create with
+ * attr, unwritten extent conversion at ENOSPC, etc. Data allocations
+ * are not allowed to use this reserved space.
+ *
+ * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
+ * This may drive us straight to ENOSPC on mount, but that implies
+ * we were already there on the last unmount.
+ */
+ resblks = mp->m_sb.sb_dblocks;
+ do_div(resblks, 20);
+ resblks = min_t(__uint64_t, resblks, 1024);
+ xfs_reserve_blocks(mp, &resblks, NULL);
+
return 0;
error4:
@@ -1083,7 +1198,19 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
int64_t fsid;
#endif
+ __uint64_t resblks;
+ /*
+ * We can potentially deadlock here if we have an inode cluster
+ * that has been freed has it's buffer still pinned in memory because
+ * the transaction is still sitting in a iclog. The stale inodes
+ * on that buffer will have their flush locks held until the
+ * transaction hits the disk and the callbacks run. the inode
+ * flush takes the flush lock unconditionally and with nothing to
+ * push out the iclog we will never get that unlocked. hence we
+ * need to force the log first.
+ */
+ xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
xfs_iflush_all(mp);
XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);
@@ -1100,10 +1227,26 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
xfs_binval(mp->m_rtdev_targp);
}
- xfs_unmountfs_writesb(mp);
+ /*
+ * Unreserve any blocks we have so that when we unmount we don't account
+ * the reserved free space as used. This is really only necessary for
+ * lazy superblock counting because it trusts the incore superblock
+ * counters to be aboslutely correct on clean unmount.
+ *
+ * We don't bother correcting this elsewhere for lazy superblock
+ * counting because on mount of an unclean filesystem we reconstruct the
+ * correct counter value and this is irrelevant.
+ *
+ * For non-lazy counter filesystems, this doesn't matter at all because
+ * we only every apply deltas to the superblock and hence the incore
+ * value does not matter....
+ */
+ resblks = 0;
+ xfs_reserve_blocks(mp, &resblks, NULL);
+ xfs_log_sbcount(mp, 1);
+ xfs_unmountfs_writesb(mp);
xfs_unmountfs_wait(mp); /* wait for async bufs */
-
xfs_log_unmount(mp); /* Done! No more fs ops. */
xfs_freesb(mp);
@@ -1150,6 +1293,62 @@ xfs_unmountfs_wait(xfs_mount_t *mp)
}
int
+xfs_fs_writable(xfs_mount_t *mp)
+{
+ bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
+
+ return !(vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
+ (vfsp->vfs_flag & VFS_RDONLY));
+}
+
+/*
+ * xfs_log_sbcount
+ *
+ * Called either periodically to keep the on disk superblock values
+ * roughly up to date or from unmount to make sure the values are
+ * correct on a clean unmount.
+ *
+ * Note this code can be called during the process of freezing, so
+ * we may need to use the transaction allocator which does not not
+ * block when the transaction subsystem is in its frozen state.
+ */
+int
+xfs_log_sbcount(
+ xfs_mount_t *mp,
+ uint sync)
+{
+ xfs_trans_t *tp;
+ int error;
+
+ if (!xfs_fs_writable(mp))
+ return 0;
+
+ xfs_icsb_sync_counters(mp);
+
+ /*
+ * we don't need to do this if we are updating the superblock
+ * counters on every modification.
+ */
+ if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
+ return 0;
+
+ tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT);
+ error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
+ XFS_DEFAULT_LOG_COUNT);
+ if (error) {
+ xfs_trans_cancel(tp, 0);
+ return error;
+ }
+
+ xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
+ if (sync)
+ xfs_trans_set_sync(tp);
+ xfs_trans_commit(tp, 0);
+
+ return 0;
+}
+
+int
xfs_unmountfs_writesb(xfs_mount_t *mp)
{
xfs_buf_t *sbp;
@@ -1160,16 +1359,15 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
* skip superblock write if fs is read-only, or
* if we are doing a forced umount.
*/
- sbp = xfs_getsb(mp, 0);
if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY ||
XFS_FORCED_SHUTDOWN(mp))) {
- xfs_icsb_sync_counters(mp);
+ sbp = xfs_getsb(mp, 0);
+ sb = XFS_BUF_TO_SBP(sbp);
/*
* mark shared-readonly if desired
*/
- sb = XFS_BUF_TO_SBP(sbp);
if (mp->m_mk_sharedro) {
if (!(sb->sb_flags & XFS_SBF_READONLY))
sb->sb_flags |= XFS_SBF_READONLY;
@@ -1178,6 +1376,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
xfs_fs_cmn_err(CE_NOTE, mp,
"Unmounting, marking shared read-only");
}
+
XFS_BUF_UNDONE(sbp);
XFS_BUF_UNREAD(sbp);
XFS_BUF_UNDELAYWRITE(sbp);
@@ -1192,8 +1391,8 @@ xfs_unmountfs_writesb(xfs_mount_t *mp)
mp, sbp, XFS_BUF_ADDR(sbp));
if (error && mp->m_mk_sharedro)
xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly");
+ xfs_buf_relse(sbp);
}
- xfs_buf_relse(sbp);
return error;
}
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 82304b94646..76ad7475869 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -66,6 +66,7 @@ struct xfs_bmbt_irec;
struct xfs_bmap_free;
struct xfs_extdelta;
struct xfs_swapext;
+struct xfs_mru_cache;
extern struct bhv_vfsops xfs_vfsops;
extern struct bhv_vnodeops xfs_vnodeops;
@@ -424,17 +425,18 @@ typedef struct xfs_mount {
struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */
struct mutex m_icsb_mutex; /* balancer sync lock */
#endif
+ struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
} xfs_mount_t;
/*
* Flags for m_flags.
*/
-#define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops
+#define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops
must be synchronous except
for space allocations */
-#define XFS_MOUNT_INO64 (1ULL << 1)
+#define XFS_MOUNT_INO64 (1ULL << 1)
/* (1ULL << 2) -- currently unused */
- /* (1ULL << 3) -- currently unused */
+#define XFS_MOUNT_WAS_CLEAN (1ULL << 3)
#define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem
operations, typically for
disk errors in metadata */
@@ -463,6 +465,8 @@ typedef struct xfs_mount {
* I/O size in stat() */
#define XFS_MOUNT_NO_PERCPU_SB (1ULL << 23) /* don't use per-cpu superblock
counters */
+#define XFS_MOUNT_FILESTREAMS (1ULL << 24) /* enable the filestreams
+ allocator */
/*
@@ -511,6 +515,8 @@ xfs_preferred_iosize(xfs_mount_t *mp)
#define XFS_MAXIOFFSET(mp) ((mp)->m_maxioffset)
+#define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \
+ ((mp)->m_flags & XFS_MOUNT_WAS_CLEAN)
#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
#define xfs_force_shutdown(m,f) \
bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
@@ -602,6 +608,7 @@ typedef struct xfs_mod_sb {
extern xfs_mount_t *xfs_mount_init(void);
extern void xfs_mod_sb(xfs_trans_t *, __int64_t);
+extern int xfs_log_sbcount(xfs_mount_t *, uint);
extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
extern int xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int);
extern void xfs_mountfs_check_barriers(xfs_mount_t *mp);
@@ -618,12 +625,14 @@ extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
extern int xfs_readsb(xfs_mount_t *, int);
extern void xfs_freesb(xfs_mount_t *);
+extern int xfs_fs_writable(xfs_mount_t *);
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
extern int xfs_syncsub(xfs_mount_t *, int, int *);
extern int xfs_sync_inodes(xfs_mount_t *, int, int *);
extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
xfs_agnumber_t);
extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
+extern int xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
extern struct xfs_dmops xfs_dmcore_stub;
extern struct xfs_qmops xfs_qmcore_stub;
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
new file mode 100644
index 00000000000..7deb9e3cbbd
--- /dev/null
+++ b/fs/xfs/xfs_mru_cache.c
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2006-2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "xfs.h"
+#include "xfs_mru_cache.h"
+
+/*
+ * The MRU Cache data structure consists of a data store, an array of lists and
+ * a lock to protect its internal state. At initialisation time, the client
+ * supplies an element lifetime in milliseconds and a group count, as well as a
+ * function pointer to call when deleting elements. A data structure for
+ * queueing up work in the form of timed callbacks is also included.
+ *
+ * The group count controls how many lists are created, and thereby how finely
+ * the elements are grouped in time. When reaping occurs, all the elements in
+ * all the lists whose time has expired are deleted.
+ *
+ * To give an example of how this works in practice, consider a client that
+ * initialises an MRU Cache with a lifetime of ten seconds and a group count of
+ * five. Five internal lists will be created, each representing a two second
+ * period in time. When the first element is added, time zero for the data
+ * structure is initialised to the current time.
+ *
+ * All the elements added in the first two seconds are appended to the first
+ * list. Elements added in the third second go into the second list, and so on.
+ * If an element is accessed at any point, it is removed from its list and
+ * inserted at the head of the current most-recently-used list.
+ *
+ * The reaper function will have nothing to do until at least twelve seconds
+ * have elapsed since the first element was added. The reason for this is that
+ * if it were called at t=11s, there could be elements in the first list that
+ * have only been inactive for nine seconds, so it still does nothing. If it is
+ * called anywhere between t=12 and t=14 seconds, it will delete all the
+ * elements that remain in the first list. It's therefore possible for elements
+ * to remain in the data store even after they've been inactive for up to
+ * (t + t/g) seconds, where t is the inactive element lifetime and g is the
+ * number of groups.
+ *
+ * The above example assumes that the reaper function gets called at least once
+ * every (t/g) seconds. If it is called less frequently, unused elements will
+ * accumulate in the reap list until the reaper function is eventually called.
+ * The current implementation uses work queue callbacks to carefully time the
+ * reaper function calls, so this should happen rarely, if at all.
+ *
+ * From a design perspective, the primary reason for the choice of a list array
+ * representing discrete time intervals is that it's only practical to reap
+ * expired elements in groups of some appreciable size. This automatically
+ * introduces a granularity to element lifetimes, so there's no point storing an
+ * individual timeout with each element that specifies a more precise reap time.
+ * The bonus is a saving of sizeof(long) bytes of memory per element stored.
+ *
+ * The elements could have been stored in just one list, but an array of
+ * counters or pointers would need to be maintained to allow them to be divided
+ * up into discrete time groups. More critically, the process of touching or
+ * removing an element would involve walking large portions of the entire list,
+ * which would have a detrimental effect on performance. The additional memory
+ * requirement for the array of list heads is minimal.
+ *
+ * When an element is touched or deleted, it needs to be removed from its
+ * current list. Doubly linked lists are used to make the list maintenance
+ * portion of these operations O(1). Since reaper timing can be imprecise,
+ * inserts and lookups can occur when there are no free lists available. When
+ * this happens, all the elements on the LRU list need to be migrated to the end
+ * of the reap list. To keep the list maintenance portion of these operations
+ * O(1) also, list tails need to be accessible without walking the entire list.
+ * This is the reason why doubly linked list heads are used.
+ */
+
+/*
+ * An MRU Cache is a dynamic data structure that stores its elements in a way
+ * that allows efficient lookups, but also groups them into discrete time
+ * intervals based on insertion time. This allows elements to be efficiently
+ * and automatically reaped after a fixed period of inactivity.
+ *
+ * When a client data pointer is stored in the MRU Cache it needs to be added to
+ * both the data store and to one of the lists. It must also be possible to
+ * access each of these entries via the other, i.e. to:
+ *
+ * a) Walk a list, removing the corresponding data store entry for each item.
+ * b) Look up a data store entry, then access its list entry directly.
+ *
+ * To achieve both of these goals, each entry must contain both a list entry and
+ * a key, in addition to the user's data pointer. Note that it's not a good
+ * idea to have the client embed one of these structures at the top of their own
+ * data structure, because inserting the same item more than once would most
+ * likely result in a loop in one of the lists. That's a sure-fire recipe for
+ * an infinite loop in the code.
+ */
+typedef struct xfs_mru_cache_elem
+{
+ struct list_head list_node;
+ unsigned long key;
+ void *value;
+} xfs_mru_cache_elem_t;
+
+static kmem_zone_t *xfs_mru_elem_zone;
+static struct workqueue_struct *xfs_mru_reap_wq;
+
+/*
+ * When inserting, destroying or reaping, it's first necessary to update the
+ * lists relative to a particular time. In the case of destroying, that time
+ * will be well in the future to ensure that all items are moved to the reap
+ * list. In all other cases though, the time will be the current time.
+ *
+ * This function enters a loop, moving the contents of the LRU list to the reap
+ * list again and again until either a) the lists are all empty, or b) time zero
+ * has been advanced sufficiently to be within the immediate element lifetime.
+ *
+ * Case a) above is detected by counting how many groups are migrated and
+ * stopping when they've all been moved. Case b) is detected by monitoring the
+ * time_zero field, which is updated as each group is migrated.
+ *
+ * The return value is the earliest time that more migration could be needed, or
+ * zero if there's no need to schedule more work because the lists are empty.
+ */
+STATIC unsigned long
+_xfs_mru_cache_migrate(
+ xfs_mru_cache_t *mru,
+ unsigned long now)
+{
+ unsigned int grp;
+ unsigned int migrated = 0;
+ struct list_head *lru_list;
+
+ /* Nothing to do if the data store is empty. */
+ if (!mru->time_zero)
+ return 0;
+
+ /* While time zero is older than the time spanned by all the lists. */
+ while (mru->time_zero <= now - mru->grp_count * mru->grp_time) {
+
+ /*
+ * If the LRU list isn't empty, migrate its elements to the tail
+ * of the reap list.
+ */
+ lru_list = mru->lists + mru->lru_grp;
+ if (!list_empty(lru_list))
+ list_splice_init(lru_list, mru->reap_list.prev);
+
+ /*
+ * Advance the LRU group number, freeing the old LRU list to
+ * become the new MRU list; advance time zero accordingly.
+ */
+ mru->lru_grp = (mru->lru_grp + 1) % mru->grp_count;
+ mru->time_zero += mru->grp_time;
+
+ /*
+ * If reaping is so far behind that all the elements on all the
+ * lists have been migrated to the reap list, it's now empty.
+ */
+ if (++migrated == mru->grp_count) {
+ mru->lru_grp = 0;
+ mru->time_zero = 0;
+ return 0;
+ }
+ }
+
+ /* Find the first non-empty list from the LRU end. */
+ for (grp = 0; grp < mru->grp_count; grp++) {
+
+ /* Check the grp'th list from the LRU end. */
+ lru_list = mru->lists + ((mru->lru_grp + grp) % mru->grp_count);
+ if (!list_empty(lru_list))
+ return mru->time_zero +
+ (mru->grp_count + grp) * mru->grp_time;
+ }
+
+ /* All the lists must be empty. */
+ mru->lru_grp = 0;
+ mru->time_zero = 0;
+ return 0;
+}
+
+/*
+ * When inserting or doing a lookup, an element needs to be inserted into the
+ * MRU list. The lists must be migrated first to ensure that they're
+ * up-to-date, otherwise the new element could be given a shorter lifetime in
+ * the cache than it should.
+ */
+STATIC void
+_xfs_mru_cache_list_insert(
+ xfs_mru_cache_t *mru,
+ xfs_mru_cache_elem_t *elem)
+{
+ unsigned int grp = 0;
+ unsigned long now = jiffies;
+
+ /*
+ * If the data store is empty, initialise time zero, leave grp set to
+ * zero and start the work queue timer if necessary. Otherwise, set grp
+ * to the number of group times that have elapsed since time zero.
+ */
+ if (!_xfs_mru_cache_migrate(mru, now)) {
+ mru->time_zero = now;
+ if (!mru->next_reap)
+ mru->next_reap = mru->grp_count * mru->grp_time;
+ } else {
+ grp = (now - mru->time_zero) / mru->grp_time;
+ grp = (mru->lru_grp + grp) % mru->grp_count;
+ }
+
+ /* Insert the element at the tail of the corresponding list. */
+ list_add_tail(&elem->list_node, mru->lists + grp);
+}
+
+/*
+ * When destroying or reaping, all the elements that were migrated to the reap
+ * list need to be deleted. For each element this involves removing it from the
+ * data store, removing it from the reap list, calling the client's free
+ * function and deleting the element from the element zone.
+ */
+STATIC void
+_xfs_mru_cache_clear_reap_list(
+ xfs_mru_cache_t *mru)
+{
+ xfs_mru_cache_elem_t *elem, *next;
+ struct list_head tmp;
+
+ INIT_LIST_HEAD(&tmp);
+ list_for_each_entry_safe(elem, next, &mru->reap_list, list_node) {
+
+ /* Remove the element from the data store. */
+ radix_tree_delete(&mru->store, elem->key);
+
+ /*
+ * remove to temp list so it can be freed without
+ * needing to hold the lock
+ */
+ list_move(&elem->list_node, &tmp);
+ }
+ mutex_spinunlock(&mru->lock, 0);
+
+ list_for_each_entry_safe(elem, next, &tmp, list_node) {
+
+ /* Remove the element from the reap list. */
+ list_del_init(&elem->list_node);
+
+ /* Call the client's free function with the key and value pointer. */
+ mru->free_func(elem->key, elem->value);
+
+ /* Free the element structure. */
+ kmem_zone_free(xfs_mru_elem_zone, elem);
+ }
+
+ mutex_spinlock(&mru->lock);
+}
+
+/*
+ * We fire the reap timer every group expiry interval so
+ * we always have a reaper ready to run. This makes shutdown
+ * and flushing of the reaper easy to do. Hence we need to
+ * keep when the next reap must occur so we can determine
+ * at each interval whether there is anything we need to do.
+ */
+STATIC void
+_xfs_mru_cache_reap(
+ struct work_struct *work)
+{
+ xfs_mru_cache_t *mru = container_of(work, xfs_mru_cache_t, work.work);
+ unsigned long now;
+
+ ASSERT(mru && mru->lists);
+ if (!mru || !mru->lists)
+ return;
+
+ mutex_spinlock(&mru->lock);
+ now = jiffies;
+ if (mru->reap_all ||
+ (mru->next_reap && time_after(now, mru->next_reap))) {
+ if (mru->reap_all)
+ now += mru->grp_count * mru->grp_time * 2;
+ mru->next_reap = _xfs_mru_cache_migrate(mru, now);
+ _xfs_mru_cache_clear_reap_list(mru);
+ }
+
+ /*
+ * the process that triggered the reap_all is responsible
+ * for restating the periodic reap if it is required.
+ */
+ if (!mru->reap_all)
+ queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
+ mru->reap_all = 0;
+ mutex_spinunlock(&mru->lock, 0);
+}
+
+int
+xfs_mru_cache_init(void)
+{
+ xfs_mru_elem_zone = kmem_zone_init(sizeof(xfs_mru_cache_elem_t),
+ "xfs_mru_cache_elem");
+ if (!xfs_mru_elem_zone)
+ return ENOMEM;
+
+ xfs_mru_reap_wq = create_singlethread_workqueue("xfs_mru_cache");
+ if (!xfs_mru_reap_wq) {
+ kmem_zone_destroy(xfs_mru_elem_zone);
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+void
+xfs_mru_cache_uninit(void)
+{
+ destroy_workqueue(xfs_mru_reap_wq);
+ kmem_zone_destroy(xfs_mru_elem_zone);
+}
+
+/*
+ * To initialise a struct xfs_mru_cache pointer, call xfs_mru_cache_create()
+ * with the address of the pointer, a lifetime value in milliseconds, a group
+ * count and a free function to use when deleting elements. This function
+ * returns 0 if the initialisation was successful.
+ */
+int
+xfs_mru_cache_create(
+ xfs_mru_cache_t **mrup,
+ unsigned int lifetime_ms,
+ unsigned int grp_count,
+ xfs_mru_cache_free_func_t free_func)
+{
+ xfs_mru_cache_t *mru = NULL;
+ int err = 0, grp;
+ unsigned int grp_time;
+
+ if (mrup)
+ *mrup = NULL;
+
+ if (!mrup || !grp_count || !lifetime_ms || !free_func)
+ return EINVAL;
+
+ if (!(grp_time = msecs_to_jiffies(lifetime_ms) / grp_count))
+ return EINVAL;
+
+ if (!(mru = kmem_zalloc(sizeof(*mru), KM_SLEEP)))
+ return ENOMEM;
+
+ /* An extra list is needed to avoid reaping up to a grp_time early. */
+ mru->grp_count = grp_count + 1;
+ mru->lists = kmem_alloc(mru->grp_count * sizeof(*mru->lists), KM_SLEEP);
+
+ if (!mru->lists) {
+ err = ENOMEM;
+ goto exit;
+ }
+
+ for (grp = 0; grp < mru->grp_count; grp++)
+ INIT_LIST_HEAD(mru->lists + grp);
+
+ /*
+ * We use GFP_KERNEL radix tree preload and do inserts under a
+ * spinlock so GFP_ATOMIC is appropriate for the radix tree itself.
+ */
+ INIT_RADIX_TREE(&mru->store, GFP_ATOMIC);
+ INIT_LIST_HEAD(&mru->reap_list);
+ spinlock_init(&mru->lock, "xfs_mru_cache");
+ INIT_DELAYED_WORK(&mru->work, _xfs_mru_cache_reap);
+
+ mru->grp_time = grp_time;
+ mru->free_func = free_func;
+
+ /* start up the reaper event */
+ mru->next_reap = 0;
+ mru->reap_all = 0;
+ queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
+
+ *mrup = mru;
+
+exit:
+ if (err && mru && mru->lists)
+ kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists));
+ if (err && mru)
+ kmem_free(mru, sizeof(*mru));
+
+ return err;
+}
+
+/*
+ * Call xfs_mru_cache_flush() to flush out all cached entries, calling their
+ * free functions as they're deleted. When this function returns, the caller is
+ * guaranteed that all the free functions for all the elements have finished
+ * executing.
+ *
+ * While we are flushing, we stop the periodic reaper event from triggering.
+ * Normally, we want to restart this periodic event, but if we are shutting
+ * down the cache we do not want it restarted. hence the restart parameter
+ * where 0 = do not restart reaper and 1 = restart reaper.
+ */
+void
+xfs_mru_cache_flush(
+ xfs_mru_cache_t *mru,
+ int restart)
+{
+ if (!mru || !mru->lists)
+ return;
+
+ cancel_rearming_delayed_workqueue(xfs_mru_reap_wq, &mru->work);
+
+ mutex_spinlock(&mru->lock);
+ mru->reap_all = 1;
+ mutex_spinunlock(&mru->lock, 0);
+
+ queue_work(xfs_mru_reap_wq, &mru->work.work);
+ flush_workqueue(xfs_mru_reap_wq);
+
+ mutex_spinlock(&mru->lock);
+ WARN_ON_ONCE(mru->reap_all != 0);
+ mru->reap_all = 0;
+ if (restart)
+ queue_delayed_work(xfs_mru_reap_wq, &mru->work, mru->grp_time);
+ mutex_spinunlock(&mru->lock, 0);
+}
+
+void
+xfs_mru_cache_destroy(
+ xfs_mru_cache_t *mru)
+{
+ if (!mru || !mru->lists)
+ return;
+
+ /* we don't want the reaper to restart here */
+ xfs_mru_cache_flush(mru, 0);
+
+ kmem_free(mru->lists, mru->grp_count * sizeof(*mru->lists));
+ kmem_free(mru, sizeof(*mru));
+}
+
+/*
+ * To insert an element, call xfs_mru_cache_insert() with the data store, the
+ * element's key and the client data pointer. This function returns 0 on
+ * success or ENOMEM if memory for the data element couldn't be allocated.
+ */
+int
+xfs_mru_cache_insert(
+ xfs_mru_cache_t *mru,
+ unsigned long key,
+ void *value)
+{
+ xfs_mru_cache_elem_t *elem;
+
+ ASSERT(mru && mru->lists);
+ if (!mru || !mru->lists)
+ return EINVAL;
+
+ elem = kmem_zone_zalloc(xfs_mru_elem_zone, KM_SLEEP);
+ if (!elem)
+ return ENOMEM;
+
+ if (radix_tree_preload(GFP_KERNEL)) {
+ kmem_zone_free(xfs_mru_elem_zone, elem);
+ return ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&elem->list_node);
+ elem->key = key;
+ elem->value = value;
+
+ mutex_spinlock(&mru->lock);
+
+ radix_tree_insert(&mru->store, key, elem);
+ radix_tree_preload_end();
+ _xfs_mru_cache_list_insert(mru, elem);
+
+ mutex_spinunlock(&mru->lock, 0);
+
+ return 0;
+}
+
+/*
+ * To remove an element without calling the free function, call
+ * xfs_mru_cache_remove() with the data store and the element's key. On success
+ * the client data pointer for the removed element is returned, otherwise this
+ * function will return a NULL pointer.
+ */
+void *
+xfs_mru_cache_remove(
+ xfs_mru_cache_t *mru,
+ unsigned long key)
+{
+ xfs_mru_cache_elem_t *elem;
+ void *value = NULL;
+
+ ASSERT(mru && mru->lists);
+ if (!mru || !mru->lists)
+ return NULL;
+
+ mutex_spinlock(&mru->lock);
+ elem = radix_tree_delete(&mru->store, key);
+ if (elem) {
+ value = elem->value;
+ list_del(&elem->list_node);
+ }
+
+ mutex_spinunlock(&mru->lock, 0);
+
+ if (elem)
+ kmem_zone_free(xfs_mru_elem_zone, elem);
+
+ return value;
+}
+
+/*
+ * To remove and element and call the free function, call xfs_mru_cache_delete()
+ * with the data store and the element's key.
+ */
+void
+xfs_mru_cache_delete(
+ xfs_mru_cache_t *mru,
+ unsigned long key)
+{
+ void *value = xfs_mru_cache_remove(mru, key);
+
+ if (value)
+ mru->free_func(key, value);
+}
+
+/*
+ * To look up an element using its key, call xfs_mru_cache_lookup() with the
+ * data store and the element's key. If found, the element will be moved to the
+ * head of the MRU list to indicate that it's been touched.
+ *
+ * The internal data structures are protected by a spinlock that is STILL HELD
+ * when this function returns. Call xfs_mru_cache_done() to release it. Note
+ * that it is not safe to call any function that might sleep in the interim.
+ *
+ * The implementation could have used reference counting to avoid this
+ * restriction, but since most clients simply want to get, set or test a member
+ * of the returned data structure, the extra per-element memory isn't warranted.
+ *
+ * If the element isn't found, this function returns NULL and the spinlock is
+ * released. xfs_mru_cache_done() should NOT be called when this occurs.
+ */
+void *
+xfs_mru_cache_lookup(
+ xfs_mru_cache_t *mru,
+ unsigned long key)
+{
+ xfs_mru_cache_elem_t *elem;
+
+ ASSERT(mru && mru->lists);
+ if (!mru || !mru->lists)
+ return NULL;
+
+ mutex_spinlock(&mru->lock);
+ elem = radix_tree_lookup(&mru->store, key);
+ if (elem) {
+ list_del(&elem->list_node);
+ _xfs_mru_cache_list_insert(mru, elem);
+ }
+ else
+ mutex_spinunlock(&mru->lock, 0);
+
+ return elem ? elem->value : NULL;
+}
+
+/*
+ * To look up an element using its key, but leave its location in the internal
+ * lists alone, call xfs_mru_cache_peek(). If the element isn't found, this
+ * function returns NULL.
+ *
+ * See the comments above the declaration of the xfs_mru_cache_lookup() function
+ * for important locking information pertaining to this call.
+ */
+void *
+xfs_mru_cache_peek(
+ xfs_mru_cache_t *mru,
+ unsigned long key)
+{
+ xfs_mru_cache_elem_t *elem;
+
+ ASSERT(mru && mru->lists);
+ if (!mru || !mru->lists)
+ return NULL;
+
+ mutex_spinlock(&mru->lock);
+ elem = radix_tree_lookup(&mru->store, key);
+ if (!elem)
+ mutex_spinunlock(&mru->lock, 0);
+
+ return elem ? elem->value : NULL;
+}
+
+/*
+ * To release the internal data structure spinlock after having performed an
+ * xfs_mru_cache_lookup() or an xfs_mru_cache_peek(), call xfs_mru_cache_done()
+ * with the data store pointer.
+ */
+void
+xfs_mru_cache_done(
+ xfs_mru_cache_t *mru)
+{
+ mutex_spinunlock(&mru->lock, 0);
+}
diff --git a/fs/xfs/xfs_mru_cache.h b/fs/xfs/xfs_mru_cache.h
new file mode 100644
index 00000000000..624fd10ee8e
--- /dev/null
+++ b/fs/xfs/xfs_mru_cache.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2006-2007 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __XFS_MRU_CACHE_H__
+#define __XFS_MRU_CACHE_H__
+
+
+/* Function pointer type for callback to free a client's data pointer. */
+typedef void (*xfs_mru_cache_free_func_t)(unsigned long, void*);
+
+typedef struct xfs_mru_cache
+{
+ struct radix_tree_root store; /* Core storage data structure. */
+ struct list_head *lists; /* Array of lists, one per grp. */
+ struct list_head reap_list; /* Elements overdue for reaping. */
+ spinlock_t lock; /* Lock to protect this struct. */
+ unsigned int grp_count; /* Number of discrete groups. */
+ unsigned int grp_time; /* Time period spanned by grps. */
+ unsigned int lru_grp; /* Group containing time zero. */
+ unsigned long time_zero; /* Time first element was added. */
+ unsigned long next_reap; /* Time that the reaper should
+ next do something. */
+ unsigned int reap_all; /* if set, reap all lists */
+ xfs_mru_cache_free_func_t free_func; /* Function pointer for freeing. */
+ struct delayed_work work; /* Workqueue data for reaping. */
+} xfs_mru_cache_t;
+
+int xfs_mru_cache_init(void);
+void xfs_mru_cache_uninit(void);
+int xfs_mru_cache_create(struct xfs_mru_cache **mrup, unsigned int lifetime_ms,
+ unsigned int grp_count,
+ xfs_mru_cache_free_func_t free_func);
+void xfs_mru_cache_flush(xfs_mru_cache_t *mru, int restart);
+void xfs_mru_cache_destroy(struct xfs_mru_cache *mru);
+int xfs_mru_cache_insert(struct xfs_mru_cache *mru, unsigned long key,
+ void *value);
+void * xfs_mru_cache_remove(struct xfs_mru_cache *mru, unsigned long key);
+void xfs_mru_cache_delete(struct xfs_mru_cache *mru, unsigned long key);
+void *xfs_mru_cache_lookup(struct xfs_mru_cache *mru, unsigned long key);
+void *xfs_mru_cache_peek(struct xfs_mru_cache *mru, unsigned long key);
+void xfs_mru_cache_done(struct xfs_mru_cache *mru);
+
+#endif /* __XFS_MRU_CACHE_H__ */
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index b3a5f07bd07..47082c01872 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1882,11 +1882,13 @@ xfs_growfs_rt(
(nrblocks = in->newblocks) <= sbp->sb_rblocks ||
(sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
return XFS_ERROR(EINVAL);
+ if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks)))
+ return error;
/*
* Read in the last block of the device, make sure it exists.
*/
error = xfs_read_buf(mp, mp->m_rtdev_targp,
- XFS_FSB_TO_BB(mp, in->newblocks - 1),
+ XFS_FSB_TO_BB(mp, nrblocks - 1),
XFS_FSB_TO_BB(mp, 1), 0, &bp);
if (error)
return error;
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h
index 188b296ff50..fcf28dbded7 100644
--- a/fs/xfs/xfs_rw.h
+++ b/fs/xfs/xfs_rw.h
@@ -72,6 +72,34 @@ xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb)
}
/*
+ * Flags for xfs_free_eofblocks
+ */
+#define XFS_FREE_EOF_LOCK (1<<0)
+#define XFS_FREE_EOF_NOLOCK (1<<1)
+
+
+/*
+ * helper function to extract extent size hint from inode
+ */
+STATIC_INLINE xfs_extlen_t
+xfs_get_extsz_hint(
+ xfs_inode_t *ip)
+{
+ xfs_extlen_t extsz;
+
+ if (unlikely(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
+ extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
+ ? ip->i_d.di_extsize
+ : ip->i_mount->m_sb.sb_rextsize;
+ ASSERT(extsz);
+ } else {
+ extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
+ ? ip->i_d.di_extsize : 0;
+ }
+ return extsz;
+}
+
+/*
* Prototypes for functions in xfs_rw.c.
*/
extern int xfs_write_clear_setuid(struct xfs_inode *ip);
@@ -91,10 +119,12 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp,
extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags,
- cred_t *credp);
+ cred_t *credp);
extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf,
- xfs_off_t offset, cred_t *credp, int flags);
+ xfs_off_t offset, cred_t *credp, int flags);
extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
- cred_t *credp);
+ cred_t *credp);
+extern int xfs_free_eofblocks(struct xfs_mount *mp, struct xfs_inode *ip,
+ int flags);
#endif /* __XFS_RW_H__ */
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 467854b45c8..ef42537a607 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -74,12 +74,13 @@ struct xfs_mount;
*/
#define XFS_SB_VERSION2_REALFBITS 0x00ffffff /* Mask: features */
#define XFS_SB_VERSION2_RESERVED1BIT 0x00000001
-#define XFS_SB_VERSION2_RESERVED2BIT 0x00000002
+#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */
#define XFS_SB_VERSION2_RESERVED4BIT 0x00000004
#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */
#define XFS_SB_VERSION2_OKREALFBITS \
- (XFS_SB_VERSION2_ATTR2BIT)
+ (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
+ XFS_SB_VERSION2_ATTR2BIT)
#define XFS_SB_VERSION2_OKSASHFBITS \
(0)
#define XFS_SB_VERSION2_OKREALBITS \
@@ -181,6 +182,9 @@ typedef enum {
#define XFS_SB_SHARED_VN XFS_SB_MVAL(SHARED_VN)
#define XFS_SB_UNIT XFS_SB_MVAL(UNIT)
#define XFS_SB_WIDTH XFS_SB_MVAL(WIDTH)
+#define XFS_SB_ICOUNT XFS_SB_MVAL(ICOUNT)
+#define XFS_SB_IFREE XFS_SB_MVAL(IFREE)
+#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)
#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)
#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT)
#define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1)
@@ -188,7 +192,7 @@ typedef enum {
(XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \
XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
- XFS_SB_FEATURES2)
+ XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2)
/*
@@ -414,6 +418,12 @@ static inline int xfs_sb_version_hasmorebits(xfs_sb_t *sbp)
* ((sbp)->sb_features2 & XFS_SB_VERSION2_FUNBIT)
*/
+static inline int xfs_sb_version_haslazysbcount(xfs_sb_t *sbp)
+{
+ return (XFS_SB_VERSION_HASMOREBITS(sbp) && \
+ ((sbp)->sb_features2 & XFS_SB_VERSION2_LAZYSBCOUNTBIT));
+}
+
#define XFS_SB_VERSION_HASATTR2(sbp) xfs_sb_version_hasattr2(sbp)
static inline int xfs_sb_version_hasattr2(xfs_sb_t *sbp)
{
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index cc2d60951e2..356d6627f58 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -427,6 +427,14 @@ undo_blocks:
*
* Mark the transaction structure to indicate that the superblock
* needs to be updated before committing.
+ *
+ * Because we may not be keeping track of allocated/free inodes and
+ * used filesystem blocks in the superblock, we do not mark the
+ * superblock dirty in this transaction if we modify these fields.
+ * We still need to update the transaction deltas so that they get
+ * applied to the incore superblock, but we don't want them to
+ * cause the superblock to get locked and logged if these are the
+ * only fields in the superblock that the transaction modifies.
*/
void
xfs_trans_mod_sb(
@@ -434,13 +442,19 @@ xfs_trans_mod_sb(
uint field,
int64_t delta)
{
+ uint32_t flags = (XFS_TRANS_DIRTY|XFS_TRANS_SB_DIRTY);
+ xfs_mount_t *mp = tp->t_mountp;
switch (field) {
case XFS_TRANS_SB_ICOUNT:
tp->t_icount_delta += delta;
+ if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ flags &= ~XFS_TRANS_SB_DIRTY;
break;
case XFS_TRANS_SB_IFREE:
tp->t_ifree_delta += delta;
+ if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ flags &= ~XFS_TRANS_SB_DIRTY;
break;
case XFS_TRANS_SB_FDBLOCKS:
/*
@@ -453,6 +467,8 @@ xfs_trans_mod_sb(
ASSERT(tp->t_blk_res_used <= tp->t_blk_res);
}
tp->t_fdblocks_delta += delta;
+ if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ flags &= ~XFS_TRANS_SB_DIRTY;
break;
case XFS_TRANS_SB_RES_FDBLOCKS:
/*
@@ -462,6 +478,8 @@ xfs_trans_mod_sb(
*/
ASSERT(delta < 0);
tp->t_res_fdblocks_delta += delta;
+ if (xfs_sb_version_haslazysbcount(&mp->m_sb))
+ flags &= ~XFS_TRANS_SB_DIRTY;
break;
case XFS_TRANS_SB_FREXTENTS:
/*
@@ -515,7 +533,7 @@ xfs_trans_mod_sb(
return;
}
- tp->t_flags |= (XFS_TRANS_SB_DIRTY | XFS_TRANS_DIRTY);
+ tp->t_flags |= flags;
}
/*
@@ -544,18 +562,23 @@ xfs_trans_apply_sb_deltas(
(tp->t_ag_freeblks_delta + tp->t_ag_flist_delta +
tp->t_ag_btree_delta));
- if (tp->t_icount_delta != 0) {
- INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
- }
- if (tp->t_ifree_delta != 0) {
- INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
- }
+ /*
+ * Only update the superblock counters if we are logging them
+ */
+ if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
+ if (tp->t_icount_delta != 0) {
+ INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
+ }
+ if (tp->t_ifree_delta != 0) {
+ INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
+ }
- if (tp->t_fdblocks_delta != 0) {
- INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
- }
- if (tp->t_res_fdblocks_delta != 0) {
- INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
+ if (tp->t_fdblocks_delta != 0) {
+ INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
+ }
+ if (tp->t_res_fdblocks_delta != 0) {
+ INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
+ }
}
if (tp->t_frextents_delta != 0) {
@@ -615,11 +638,23 @@ xfs_trans_apply_sb_deltas(
}
/*
- * xfs_trans_unreserve_and_mod_sb() is called to release unused
- * reservations and apply superblock counter changes to the in-core
- * superblock.
+ * xfs_trans_unreserve_and_mod_sb() is called to release unused reservations
+ * and apply superblock counter changes to the in-core superblock. The
+ * t_res_fdblocks_delta and t_res_frextents_delta fields are explicitly NOT
+ * applied to the in-core superblock. The idea is that that has already been
+ * done.
*
* This is done efficiently with a single call to xfs_mod_incore_sb_batch().
+ * However, we have to ensure that we only modify each superblock field only
+ * once because the application of the delta values may not be atomic. That can
+ * lead to ENOSPC races occurring if we have two separate modifcations of the
+ * free space counter to put back the entire reservation and then take away
+ * what we used.
+ *
+ * If we are not logging superblock counters, then the inode allocated/free and
+ * used block counts are not updated in the on disk superblock. In this case,
+ * XFS_TRANS_SB_DIRTY will not be set when the transaction is updated but we
+ * still need to update the incore superblock with the changes.
*/
STATIC void
xfs_trans_unreserve_and_mod_sb(
@@ -627,40 +662,49 @@ xfs_trans_unreserve_and_mod_sb(
{
xfs_mod_sb_t msb[14]; /* If you add cases, add entries */
xfs_mod_sb_t *msbp;
+ xfs_mount_t *mp = tp->t_mountp;
/* REFERENCED */
int error;
int rsvd;
+ int64_t blkdelta = 0;
+ int64_t rtxdelta = 0;
msbp = msb;
rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
- /*
- * Release any reserved blocks. Any that were allocated
- * will be taken back again by fdblocks_delta below.
- */
- if (tp->t_blk_res > 0) {
+ /* calculate free blocks delta */
+ if (tp->t_blk_res > 0)
+ blkdelta = tp->t_blk_res;
+
+ if ((tp->t_fdblocks_delta != 0) &&
+ (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
+ (tp->t_flags & XFS_TRANS_SB_DIRTY)))
+ blkdelta += tp->t_fdblocks_delta;
+
+ if (blkdelta != 0) {
msbp->msb_field = XFS_SBS_FDBLOCKS;
- msbp->msb_delta = tp->t_blk_res;
+ msbp->msb_delta = blkdelta;
msbp++;
}
- /*
- * Release any reserved real time extents . Any that were
- * allocated will be taken back again by frextents_delta below.
- */
- if (tp->t_rtx_res > 0) {
+ /* calculate free realtime extents delta */
+ if (tp->t_rtx_res > 0)
+ rtxdelta = tp->t_rtx_res;
+
+ if ((tp->t_frextents_delta != 0) &&
+ (tp->t_flags & XFS_TRANS_SB_DIRTY))
+ rtxdelta += tp->t_frextents_delta;
+
+ if (rtxdelta != 0) {
msbp->msb_field = XFS_SBS_FREXTENTS;
- msbp->msb_delta = tp->t_rtx_res;
+ msbp->msb_delta = rtxdelta;
msbp++;
}
- /*
- * Apply any superblock modifications to the in-core version.
- * The t_res_fdblocks_delta and t_res_frextents_delta fields are
- * explicitly NOT applied to the in-core superblock.
- * The idea is that that has already been done.
- */
- if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
+ /* apply remaining deltas */
+
+ if (xfs_sb_version_haslazysbcount(&mp->m_sb) ||
+ (tp->t_flags & XFS_TRANS_SB_DIRTY)) {
if (tp->t_icount_delta != 0) {
msbp->msb_field = XFS_SBS_ICOUNT;
msbp->msb_delta = tp->t_icount_delta;
@@ -671,16 +715,9 @@ xfs_trans_unreserve_and_mod_sb(
msbp->msb_delta = tp->t_ifree_delta;
msbp++;
}
- if (tp->t_fdblocks_delta != 0) {
- msbp->msb_field = XFS_SBS_FDBLOCKS;
- msbp->msb_delta = tp->t_fdblocks_delta;
- msbp++;
- }
- if (tp->t_frextents_delta != 0) {
- msbp->msb_field = XFS_SBS_FREXTENTS;
- msbp->msb_delta = tp->t_frextents_delta;
- msbp++;
- }
+ }
+
+ if (tp->t_flags & XFS_TRANS_SB_DIRTY) {
if (tp->t_dblocks_delta != 0) {
msbp->msb_field = XFS_SBS_DBLOCKS;
msbp->msb_delta = tp->t_dblocks_delta;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 7dfcc450366..0e26e729023 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -94,7 +94,8 @@ typedef struct xfs_trans_header {
#define XFS_TRANS_GROWFSRT_ZERO 38
#define XFS_TRANS_GROWFSRT_FREE 39
#define XFS_TRANS_SWAPEXT 40
-#define XFS_TRANS_TYPE_MAX 40
+#define XFS_TRANS_SB_COUNT 41
+#define XFS_TRANS_TYPE_MAX 41
/* new transaction types need to be reflected in xfs_logprint(8) */
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 65c561201cb..11f5ea29a03 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -51,6 +51,8 @@
#include "xfs_acl.h"
#include "xfs_attr.h"
#include "xfs_clnt.h"
+#include "xfs_mru_cache.h"
+#include "xfs_filestream.h"
#include "xfs_fsops.h"
STATIC int xfs_sync(bhv_desc_t *, int, cred_t *);
@@ -81,6 +83,8 @@ xfs_init(void)
xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
+ xfs_mru_cache_init();
+ xfs_filestream_init();
/*
* The size of the zone allocated buf log item is the maximum
@@ -164,6 +168,8 @@ xfs_cleanup(void)
xfs_cleanup_procfs();
xfs_sysctl_unregister();
xfs_refcache_destroy();
+ xfs_filestream_uninit();
+ xfs_mru_cache_uninit();
xfs_acl_zone_destroy(xfs_acl_zone);
#ifdef XFS_DIR2_TRACE
@@ -320,6 +326,9 @@ xfs_start_flags(
else
mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ if (ap->flags2 & XFSMNT2_FILESTREAMS)
+ mp->m_flags |= XFS_MOUNT_FILESTREAMS;
+
return 0;
}
@@ -518,6 +527,9 @@ xfs_mount(
if (mp->m_flags & XFS_MOUNT_BARRIER)
xfs_mountfs_check_barriers(mp);
+ if ((error = xfs_filestream_mount(mp)))
+ goto error2;
+
error = XFS_IOINIT(vfsp, args, flags);
if (error)
goto error2;
@@ -575,6 +587,13 @@ xfs_unmount(
*/
xfs_refcache_purge_mp(mp);
+ /*
+ * Blow away any referenced inode in the filestreams cache.
+ * This can and will cause log traffic as inodes go inactive
+ * here.
+ */
+ xfs_filestream_unmount(mp);
+
XFS_bflush(mp->m_ddev_targp);
error = xfs_unmount_flush(mp, 0);
if (error)
@@ -640,7 +659,7 @@ xfs_quiesce_fs(
* we can write the unmount record.
*/
do {
- xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, NULL);
+ xfs_syncsub(mp, SYNC_INODE_QUIESCE, NULL);
pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
if (!pincount) {
delay(50);
@@ -651,6 +670,30 @@ xfs_quiesce_fs(
return 0;
}
+/*
+ * Second stage of a quiesce. The data is already synced, now we have to take
+ * care of the metadata. New transactions are already blocked, so we need to
+ * wait for any remaining transactions to drain out before proceding.
+ */
+STATIC void
+xfs_attr_quiesce(
+ xfs_mount_t *mp)
+{
+ /* wait for all modifications to complete */
+ while (atomic_read(&mp->m_active_trans) > 0)
+ delay(100);
+
+ /* flush inodes and push all remaining buffers out to disk */
+ xfs_quiesce_fs(mp);
+
+ ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
+
+ /* Push the superblock and write an unmount record */
+ xfs_log_sbcount(mp, 1);
+ xfs_log_unmount_write(mp);
+ xfs_unmountfs_writesb(mp);
+}
+
STATIC int
xfs_mntupdate(
bhv_desc_t *bdp,
@@ -670,10 +713,9 @@ xfs_mntupdate(
mp->m_flags &= ~XFS_MOUNT_BARRIER;
}
} else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */
- bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL);
- xfs_quiesce_fs(mp);
- xfs_log_unmount_write(mp);
- xfs_unmountfs_writesb(mp);
+ xfs_filestream_flush(mp);
+ bhv_vfs_sync(vfsp, SYNC_DATA_QUIESCE, NULL);
+ xfs_attr_quiesce(mp);
vfsp->vfs_flag |= VFS_RDONLY;
}
return 0;
@@ -887,6 +929,9 @@ xfs_sync(
{
xfs_mount_t *mp = XFS_BHVTOM(bdp);
+ if (flags & SYNC_IOWAIT)
+ xfs_filestream_flush(mp);
+
return xfs_syncsub(mp, flags, NULL);
}
@@ -1128,58 +1173,41 @@ xfs_sync_inodes(
* in the inode list.
*/
- if ((flags & SYNC_CLOSE) && (vp != NULL)) {
- /*
- * This is the shutdown case. We just need to
- * flush and invalidate all the pages associated
- * with the inode. Drop the inode lock since
- * we can't hold it across calls to the buffer
- * cache.
- *
- * We don't set the VREMAPPING bit in the vnode
- * here, because we don't hold the vnode lock
- * exclusively. It doesn't really matter, though,
- * because we only come here when we're shutting
- * down anyway.
- */
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
- if (XFS_FORCED_SHUTDOWN(mp)) {
- bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
- } else {
- error = bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF);
+ /*
+ * If we have to flush data or wait for I/O completion
+ * we need to drop the ilock that we currently hold.
+ * If we need to drop the lock, insert a marker if we
+ * have not already done so.
+ */
+ if ((flags & (SYNC_CLOSE|SYNC_IOWAIT)) ||
+ ((flags & SYNC_DELWRI) && VN_DIRTY(vp))) {
+ if (mount_locked) {
+ IPOINTER_INSERT(ip, mp);
}
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
- xfs_ilock(ip, XFS_ILOCK_SHARED);
-
- } else if ((flags & SYNC_DELWRI) && (vp != NULL)) {
- if (VN_DIRTY(vp)) {
- /* We need to have dropped the lock here,
- * so insert a marker if we have not already
- * done so.
- */
- if (mount_locked) {
- IPOINTER_INSERT(ip, mp);
- }
-
- /*
- * Drop the inode lock since we can't hold it
- * across calls to the buffer cache.
- */
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ if (flags & SYNC_CLOSE) {
+ /* Shutdown case. Flush and invalidate. */
+ if (XFS_FORCED_SHUTDOWN(mp))
+ bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
+ else
+ error = bhv_vop_flushinval_pages(vp, 0,
+ -1, FI_REMAPF);
+ } else if ((flags & SYNC_DELWRI) && VN_DIRTY(vp)) {
error = bhv_vop_flush_pages(vp, (xfs_off_t)0,
-1, fflag, FI_NONE);
- xfs_ilock(ip, XFS_ILOCK_SHARED);
}
+ /*
+ * When freezing, we need to wait ensure all I/O (including direct
+ * I/O) is complete to ensure no further data modification can take
+ * place after this point
+ */
+ if (flags & SYNC_IOWAIT)
+ vn_iowait(vp);
+
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
}
- /*
- * When freezing, we need to wait ensure all I/O (including direct
- * I/O) is complete to ensure no further data modification can take
- * place after this point
- */
- if (flags & SYNC_IOWAIT)
- vn_iowait(vp);
if (flags & SYNC_BDFLUSH) {
if ((flags & SYNC_ATTR) &&
@@ -1514,6 +1542,15 @@ xfs_syncsub(
}
/*
+ * If asked, update the disk superblock with incore counter values if we
+ * are using non-persistent counters so that they don't get too far out
+ * of sync if we crash or get a forced shutdown. We don't want to force
+ * this to disk, just get a transaction into the iclogs....
+ */
+ if (flags & SYNC_SUPER)
+ xfs_log_sbcount(mp, 0);
+
+ /*
* Now check to see if the log needs a "dummy" transaction.
*/
@@ -1645,6 +1682,7 @@ xfs_vget(
* in stat(). */
#define MNTOPT_ATTR2 "attr2" /* do use attr2 attribute format */
#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */
+#define MNTOPT_FILESTREAM "filestreams" /* use filestreams allocator */
STATIC unsigned long
suffix_strtoul(char *s, char **endp, unsigned int base)
@@ -1831,6 +1869,8 @@ xfs_parseargs(
args->flags |= XFSMNT_ATTR2;
} else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
args->flags &= ~XFSMNT_ATTR2;
+ } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
+ args->flags2 |= XFSMNT2_FILESTREAMS;
} else if (!strcmp(this_char, "osyncisdsync")) {
/* no-op, this is now the default */
cmn_err(CE_WARN,
@@ -1959,9 +1999,9 @@ xfs_showargs(
}
/*
- * Second stage of a freeze. The data is already frozen, now we have to take
- * care of the metadata. New transactions are already blocked, so we need to
- * wait for any remaining transactions to drain out before proceding.
+ * Second stage of a freeze. The data is already frozen so we only
+ * need to take care of themetadata. Once that's done write a dummy
+ * record to dirty the log in case of a crash while frozen.
*/
STATIC void
xfs_freeze(
@@ -1969,18 +2009,7 @@ xfs_freeze(
{
xfs_mount_t *mp = XFS_BHVTOM(bdp);
- /* wait for all modifications to complete */
- while (atomic_read(&mp->m_active_trans) > 0)
- delay(100);
-
- /* flush inodes and push all remaining buffers out to disk */
- xfs_quiesce_fs(mp);
-
- ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
-
- /* Push the superblock and write an unmount record */
- xfs_log_unmount_write(mp);
- xfs_unmountfs_writesb(mp);
+ xfs_attr_quiesce(mp);
xfs_fs_log_dummy(mp);
}
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index de17aed578f..79b522779aa 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -51,6 +51,7 @@
#include "xfs_refcache.h"
#include "xfs_trans_space.h"
#include "xfs_log_priv.h"
+#include "xfs_filestream.h"
STATIC int
xfs_open(
@@ -77,36 +78,6 @@ xfs_open(
return 0;
}
-STATIC int
-xfs_close(
- bhv_desc_t *bdp,
- int flags,
- lastclose_t lastclose,
- cred_t *credp)
-{
- bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
- xfs_inode_t *ip = XFS_BHVTOI(bdp);
-
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
- return XFS_ERROR(EIO);
-
- if (lastclose != L_TRUE || !VN_ISREG(vp))
- return 0;
-
- /*
- * If we previously truncated this file and removed old data in
- * the process, we want to initiate "early" writeout on the last
- * close. This is an attempt to combat the notorious NULL files
- * problem which is particularly noticable from a truncate down,
- * buffered (re-)write (delalloc), followed by a crash. What we
- * are effectively doing here is significantly reducing the time
- * window where we'd otherwise be exposed to that problem.
- */
- if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
- return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
- return 0;
-}
-
/*
* xfs_getattr
*/
@@ -183,9 +154,8 @@ xfs_getattr(
* realtime extent size or the realtime volume's
* extent size.
*/
- vap->va_blocksize = ip->i_d.di_extsize ?
- (ip->i_d.di_extsize << mp->m_sb.sb_blocklog) :
- (mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog);
+ vap->va_blocksize =
+ xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog;
}
break;
}
@@ -814,6 +784,8 @@ xfs_setattr(
di_flags |= XFS_DIFLAG_PROJINHERIT;
if (vap->va_xflags & XFS_XFLAG_NODEFRAG)
di_flags |= XFS_DIFLAG_NODEFRAG;
+ if (vap->va_xflags & XFS_XFLAG_FILESTREAM)
+ di_flags |= XFS_DIFLAG_FILESTREAM;
if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
di_flags |= XFS_DIFLAG_RTINHERIT;
@@ -1201,13 +1173,15 @@ xfs_fsync(
}
/*
- * This is called by xfs_inactive to free any blocks beyond eof,
- * when the link count isn't zero.
+ * This is called by xfs_inactive to free any blocks beyond eof
+ * when the link count isn't zero and by xfs_dm_punch_hole() when
+ * punching a hole to EOF.
*/
-STATIC int
-xfs_inactive_free_eofblocks(
+int
+xfs_free_eofblocks(
xfs_mount_t *mp,
- xfs_inode_t *ip)
+ xfs_inode_t *ip,
+ int flags)
{
xfs_trans_t *tp;
int error;
@@ -1216,6 +1190,7 @@ xfs_inactive_free_eofblocks(
xfs_filblks_t map_len;
int nimaps;
xfs_bmbt_irec_t imap;
+ int use_iolock = (flags & XFS_FREE_EOF_LOCK);
/*
* Figure out if there are any blocks beyond the end
@@ -1256,11 +1231,14 @@ xfs_inactive_free_eofblocks(
* cache and we can't
* do that within a transaction.
*/
- xfs_ilock(ip, XFS_IOLOCK_EXCL);
+ if (use_iolock)
+ xfs_ilock(ip, XFS_IOLOCK_EXCL);
error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
ip->i_size);
if (error) {
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ xfs_trans_cancel(tp, 0);
+ if (use_iolock)
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return error;
}
@@ -1297,7 +1275,8 @@ xfs_inactive_free_eofblocks(
error = xfs_trans_commit(tp,
XFS_TRANS_RELEASE_LOG_RES);
}
- xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
+ xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)
+ : XFS_ILOCK_EXCL));
}
return error;
}
@@ -1560,6 +1539,31 @@ xfs_release(
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
return 0;
+ if (!XFS_FORCED_SHUTDOWN(mp)) {
+ /*
+ * If we are using filestreams, and we have an unlinked
+ * file that we are processing the last close on, then nothing
+ * will be able to reopen and write to this file. Purge this
+ * inode from the filestreams cache so that it doesn't delay
+ * teardown of the inode.
+ */
+ if ((ip->i_d.di_nlink == 0) && xfs_inode_is_filestream(ip))
+ xfs_filestream_deassociate(ip);
+
+ /*
+ * If we previously truncated this file and removed old data
+ * in the process, we want to initiate "early" writeout on
+ * the last close. This is an attempt to combat the notorious
+ * NULL files problem which is particularly noticable from a
+ * truncate down, buffered (re-)write (delalloc), followed by
+ * a crash. What we are effectively doing here is
+ * significantly reducing the time window where we'd otherwise
+ * be exposed to that problem.
+ */
+ if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
+ bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
+ }
+
#ifdef HAVE_REFCACHE
/* If we are in the NFS reference cache then don't do this now */
if (ip->i_refcache)
@@ -1573,7 +1577,8 @@ xfs_release(
(ip->i_df.if_flags & XFS_IFEXTENTS)) &&
(!(ip->i_d.di_flags &
(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
- if ((error = xfs_inactive_free_eofblocks(mp, ip)))
+ error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
+ if (error)
return error;
/* Update linux inode block count after free above */
vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
@@ -1654,7 +1659,8 @@ xfs_inactive(
(!(ip->i_d.di_flags &
(XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
(ip->i_delayed_blks != 0)))) {
- if ((error = xfs_inactive_free_eofblocks(mp, ip)))
+ error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
+ if (error)
return VN_INACTIVE_CACHE;
/* Update linux inode block count after free above */
vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
@@ -1680,6 +1686,7 @@ xfs_inactive(
error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, 0);
if (error) {
+ xfs_trans_cancel(tp, 0);
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return VN_INACTIVE_CACHE;
}
@@ -2217,9 +2224,9 @@ static inline int
xfs_lock_inumorder(int lock_mode, int subclass)
{
if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL))
- lock_mode |= (subclass + XFS_IOLOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
+ lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT;
if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))
- lock_mode |= (subclass + XFS_ILOCK_INUMORDER) << XFS_ILOCK_SHIFT;
+ lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT;
return lock_mode;
}
@@ -2546,6 +2553,15 @@ xfs_remove(
*/
xfs_refcache_purge_ip(ip);
+ /*
+ * If we are using filestreams, kill the stream association.
+ * If the file is still open it may get a new one but that
+ * will get killed on last close in xfs_close() so we don't
+ * have to worry about that.
+ */
+ if (link_zero && xfs_inode_is_filestream(ip))
+ xfs_filestream_deassociate(ip);
+
vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
/*
@@ -4047,22 +4063,16 @@ xfs_alloc_file_space(
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
- rt = XFS_IS_REALTIME_INODE(ip);
- if (unlikely(rt)) {
- if (!(extsz = ip->i_d.di_extsize))
- extsz = mp->m_sb.sb_rextsize;
- } else {
- extsz = ip->i_d.di_extsize;
- }
-
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
return error;
if (len <= 0)
return XFS_ERROR(EINVAL);
+ rt = XFS_IS_REALTIME_INODE(ip);
+ extsz = xfs_get_extsz_hint(ip);
+
count = len;
- error = 0;
imapp = &imaps[0];
nimaps = 1;
bmapi_flag = XFS_BMAPI_WRITE | (alloc_type ? XFS_BMAPI_PREALLOC : 0);
@@ -4678,11 +4688,7 @@ xfs_change_file_space(
bhv_vnodeops_t xfs_vnodeops = {
BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
.vop_open = xfs_open,
- .vop_close = xfs_close,
.vop_read = xfs_read,
-#ifdef HAVE_SENDFILE
- .vop_sendfile = xfs_sendfile,
-#endif
#ifdef HAVE_SPLICE
.vop_splice_read = xfs_splice_read,
.vop_splice_write = xfs_splice_write,
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
index b62cd36ff32..e2fcee2b340 100644
--- a/include/acpi/acpi_numa.h
+++ b/include/acpi/acpi_numa.h
@@ -13,7 +13,7 @@
extern int pxm_to_node(int);
extern int node_to_pxm(int);
-extern int __cpuinit acpi_map_pxm_to_node(int);
+extern int acpi_map_pxm_to_node(int);
extern void __cpuinit acpi_unmap_pxm_to_node(int);
#endif /* CONFIG_ACPI_NUMA */
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 5e07db0d46e..ca882b8e7d1 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -78,7 +78,7 @@ struct acpi_signal_fatal_info {
/*
* OSL Initialization and shutdown primitives
*/
-acpi_status acpi_os_initialize(void);
+acpi_status __initdata acpi_os_initialize(void);
acpi_status acpi_os_terminate(void);
@@ -236,6 +236,7 @@ acpi_os_derive_pci_id(acpi_handle rhandle,
* Miscellaneous
*/
acpi_status acpi_os_validate_interface(char *interface);
+acpi_status acpi_osi_invalidate(char* interface);
acpi_status
acpi_os_validate_address(u8 space_id,
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index e08f7df85a4..b5cca5daa34 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -55,7 +55,7 @@ acpi_status
acpi_initialize_tables(struct acpi_table_desc *initial_storage,
u32 initial_table_count, u8 allow_resize);
-acpi_status acpi_initialize_subsystem(void);
+acpi_status __init acpi_initialize_subsystem(void);
acpi_status acpi_enable_subsystem(u32 flags);
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index 15a838862cd..a87ef1c8d46 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -390,6 +390,8 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object);
u8 acpi_ut_valid_internal_object(void *object);
+union acpi_operand_object *acpi_ut_create_package_object(u32 count);
+
union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size);
union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);
diff --git a/include/asm-alpha/core_t2.h b/include/asm-alpha/core_t2.h
index 457c34b6eb0..90e6b5d6c21 100644
--- a/include/asm-alpha/core_t2.h
+++ b/include/asm-alpha/core_t2.h
@@ -437,9 +437,15 @@ static inline void t2_outl(u32 b, unsigned long addr)
static DEFINE_SPINLOCK(t2_hae_lock);
+/*
+ * NOTE: take T2_DENSE_MEM off in each readX/writeX routine, since
+ * they may be called directly, rather than through the
+ * ioreadNN/iowriteNN routines.
+ */
+
__EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long) xaddr;
+ unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
unsigned long result, msb;
unsigned long flags;
spin_lock_irqsave(&t2_hae_lock, flags);
@@ -453,7 +459,7 @@ __EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
__EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long) xaddr;
+ unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
unsigned long result, msb;
unsigned long flags;
spin_lock_irqsave(&t2_hae_lock, flags);
@@ -471,7 +477,7 @@ __EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
*/
__EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long) xaddr;
+ unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
unsigned long result, msb;
unsigned long flags;
spin_lock_irqsave(&t2_hae_lock, flags);
@@ -485,7 +491,7 @@ __EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr)
__EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long) xaddr;
+ unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
unsigned long r0, r1, work, msb;
unsigned long flags;
spin_lock_irqsave(&t2_hae_lock, flags);
@@ -501,7 +507,7 @@ __EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr)
__EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long) xaddr;
+ unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
unsigned long msb, w;
unsigned long flags;
spin_lock_irqsave(&t2_hae_lock, flags);
@@ -515,7 +521,7 @@ __EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr)
__EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long) xaddr;
+ unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
unsigned long msb, w;
unsigned long flags;
spin_lock_irqsave(&t2_hae_lock, flags);
@@ -533,7 +539,7 @@ __EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
*/
__EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long) xaddr;
+ unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
unsigned long msb;
unsigned long flags;
spin_lock_irqsave(&t2_hae_lock, flags);
@@ -546,7 +552,7 @@ __EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr)
__EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long) xaddr;
+ unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
unsigned long msb, work;
unsigned long flags;
spin_lock_irqsave(&t2_hae_lock, flags);
@@ -587,14 +593,14 @@ __EXTERN_INLINE int t2_is_mmio(const volatile void __iomem *addr)
__EXTERN_INLINE unsigned int t2_ioread##NS(void __iomem *xaddr) \
{ \
if (t2_is_mmio(xaddr)) \
- return t2_read##OS(xaddr - T2_DENSE_MEM); \
+ return t2_read##OS(xaddr); \
else \
return t2_in##OS((unsigned long)xaddr - T2_IO); \
} \
__EXTERN_INLINE void t2_iowrite##NS(u##NS b, void __iomem *xaddr) \
{ \
if (t2_is_mmio(xaddr)) \
- t2_write##OS(b, xaddr - T2_DENSE_MEM); \
+ t2_write##OS(b, xaddr); \
else \
t2_out##OS(b, (unsigned long)xaddr - T2_IO); \
}
diff --git a/include/asm-alpha/core_titan.h b/include/asm-alpha/core_titan.h
index a64ccbff7d9..a17f6f33b68 100644
--- a/include/asm-alpha/core_titan.h
+++ b/include/asm-alpha/core_titan.h
@@ -380,12 +380,7 @@ struct el_PRIVATEER_envdata_mcheck {
/*
* Memory functions. all accesses are done through linear space.
*/
-
-__EXTERN_INLINE void __iomem *titan_ioportmap(unsigned long addr)
-{
- return (void __iomem *)(addr + TITAN_IO_BIAS);
-}
-
+extern void __iomem *titan_ioportmap(unsigned long addr);
extern void __iomem *titan_ioremap(unsigned long addr, unsigned long size);
extern void titan_iounmap(volatile void __iomem *addr);
diff --git a/include/asm-alpha/core_tsunami.h b/include/asm-alpha/core_tsunami.h
index 44e635d2c57..58d4fe48742 100644
--- a/include/asm-alpha/core_tsunami.h
+++ b/include/asm-alpha/core_tsunami.h
@@ -2,6 +2,7 @@
#define __ALPHA_TSUNAMI__H__
#include <linux/types.h>
+#include <linux/pci.h>
#include <asm/compiler.h>
/*
@@ -302,18 +303,8 @@ struct el_TSUNAMI_sysdata_mcheck {
/*
* Memory functions. all accesses are done through linear space.
*/
-
-__EXTERN_INLINE void __iomem *tsunami_ioportmap(unsigned long addr)
-{
- return (void __iomem *)(addr + TSUNAMI_IO_BIAS);
-}
-
-__EXTERN_INLINE void __iomem *tsunami_ioremap(unsigned long addr,
- unsigned long size)
-{
- return (void __iomem *)(addr + TSUNAMI_MEM_BIAS);
-}
-
+extern void __iomem *tsunami_ioportmap(unsigned long addr);
+extern void __iomem *tsunami_ioremap(unsigned long addr, unsigned long size);
__EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
{
return addr >= TSUNAMI_BASE;
diff --git a/include/asm-alpha/core_wildfire.h b/include/asm-alpha/core_wildfire.h
index 12af803d445..cd562f544ba 100644
--- a/include/asm-alpha/core_wildfire.h
+++ b/include/asm-alpha/core_wildfire.h
@@ -295,7 +295,7 @@ __EXTERN_INLINE int wildfire_is_ioaddr(unsigned long addr)
__EXTERN_INLINE int wildfire_is_mmio(const volatile void __iomem *xaddr)
{
- unsigned long addr = (unsigned long)addr;
+ unsigned long addr = (unsigned long)xaddr;
return (addr & 0x100000000UL) == 0;
}
diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
index 85aa1127c90..30ee7669b19 100644
--- a/include/asm-alpha/pci.h
+++ b/include/asm-alpha/pci.h
@@ -199,30 +199,6 @@ pci_dma_sync_sg_for_device(struct pci_dev *dev, struct scatterlist *sg,
extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
-/* True if the machine supports DAC addressing, and DEV can
- make use of it given MASK. */
-extern int pci_dac_dma_supported(struct pci_dev *hwdev, u64 mask);
-
-/* Convert to/from DAC dma address and struct page. */
-extern dma64_addr_t pci_dac_page_to_dma(struct pci_dev *, struct page *,
- unsigned long, int);
-extern struct page *pci_dac_dma_to_page(struct pci_dev *, dma64_addr_t);
-extern unsigned long pci_dac_dma_to_offset(struct pci_dev *, dma64_addr_t);
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr,
- size_t len, int direction)
-{
- /* Nothing to do. */
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr,
- size_t len, int direction)
-{
- /* Nothing to do. */
-}
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
@@ -275,11 +251,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
return hose->need_domain_info;
}
-static inline void
-pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
struct pci_dev *alpha_gendev_to_pci(struct device *dev);
#endif /* __KERNEL__ */
diff --git a/include/asm-alpha/vga.h b/include/asm-alpha/vga.h
index ed06f59b544..e8df1e7aae6 100644
--- a/include/asm-alpha/vga.h
+++ b/include/asm-alpha/vga.h
@@ -46,6 +46,37 @@ extern void scr_memcpyw(u16 *d, const u16 *s, unsigned int count);
#define vga_readb(a) readb((u8 __iomem *)(a))
#define vga_writeb(v,a) writeb(v, (u8 __iomem *)(a))
+#ifdef CONFIG_VGA_HOSE
+#include <linux/ioport.h>
+#include <linux/pci.h>
+
+extern struct pci_controller *pci_vga_hose;
+
+# define __is_port_vga(a) \
+ (((a) >= 0x3b0) && ((a) < 0x3e0) && \
+ ((a) != 0x3b3) && ((a) != 0x3d3))
+
+# define __is_mem_vga(a) \
+ (((a) >= 0xa0000) && ((a) <= 0xc0000))
+
+# define FIXUP_IOADDR_VGA(a) do { \
+ if (pci_vga_hose && __is_port_vga(a)) \
+ (a) += pci_vga_hose->io_space->start; \
+ } while(0)
+
+# define FIXUP_MEMADDR_VGA(a) do { \
+ if (pci_vga_hose && __is_mem_vga(a)) \
+ (a) += pci_vga_hose->mem_space->start; \
+ } while(0)
+
+#else /* CONFIG_VGA_HOSE */
+# define pci_vga_hose 0
+# define __is_port_vga(a) 0
+# define __is_mem_vga(a) 0
+# define FIXUP_IOADDR_VGA(a)
+# define FIXUP_MEMADDR_VGA(a)
+#endif /* CONFIG_VGA_HOSE */
+
#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap(x, s))
#endif
diff --git a/include/asm-arm/Kbuild b/include/asm-arm/Kbuild
index c68e1680da0..73237bd130a 100644
--- a/include/asm-arm/Kbuild
+++ b/include/asm-arm/Kbuild
@@ -1 +1,3 @@
include include/asm-generic/Kbuild.asm
+
+unifdef-y += hwcap.h
diff --git a/include/asm-arm/arch-at91/at91_dbgu.h b/include/asm-arm/arch-at91/at91_dbgu.h
index b0369e176f7..8019ffd0ad3 100644
--- a/include/asm-arm/arch-at91/at91_dbgu.h
+++ b/include/asm-arm/arch-at91/at91_dbgu.h
@@ -16,6 +16,7 @@
#ifndef AT91_DBGU_H
#define AT91_DBGU_H
+#ifdef AT91_DBGU
#define AT91_DBGU_CR (AT91_DBGU + 0x00) /* Control Register */
#define AT91_DBGU_MR (AT91_DBGU + 0x04) /* Mode Register */
#define AT91_DBGU_IER (AT91_DBGU + 0x08) /* Interrupt Enable Register */
@@ -30,6 +31,15 @@
#define AT91_DBGU_CIDR (AT91_DBGU + 0x40) /* Chip ID Register */
#define AT91_DBGU_EXID (AT91_DBGU + 0x44) /* Chip ID Extension Register */
+#define AT91_DBGU_FNR (AT91_DBGU + 0x48) /* Force NTRST Register [SAM9 only] */
+#define AT91_DBGU_FNTRST (1 << 0) /* Force NTRST */
+
+#endif /* AT91_DBGU */
+
+/*
+ * Some AT91 parts that don't have full DEBUG units still support the ID
+ * and extensions register.
+ */
#define AT91_CIDR_VERSION (0x1f << 0) /* Version of the Device */
#define AT91_CIDR_EPROC (7 << 5) /* Embedded Processor */
#define AT91_CIDR_NVPSIZ (0xf << 8) /* Nonvolatile Program Memory Size */
@@ -53,7 +63,4 @@
#define AT91_CIDR_NVPTYP (7 << 28) /* Nonvolatile Program Memory Type */
#define AT91_CIDR_EXT (1 << 31) /* Extension Flag */
-#define AT91_DBGU_FNR (AT91_DBGU + 0x48) /* Force NTRST Register [SAM9 only] */
-#define AT91_DBGU_FNTRST (1 << 0) /* Force NTRST */
-
#endif
diff --git a/include/asm-arm/arch-at91/at91_shdwc.h b/include/asm-arm/arch-at91/at91_shdwc.h
index 795fcc26622..01b433de227 100644
--- a/include/asm-arm/arch-at91/at91_shdwc.h
+++ b/include/asm-arm/arch-at91/at91_shdwc.h
@@ -14,8 +14,8 @@
#define AT91_SHDWC_H
#define AT91_SHDW_CR (AT91_SHDWC + 0x00) /* Shut Down Control Register */
-#define AT91_SHDW_SHDW (1 << 0) /* Processor Reset */
-#define AT91_SHDW_KEY (0xff << 24) /* KEY Password */
+#define AT91_SHDW_SHDW (1 << 0) /* Shut Down command */
+#define AT91_SHDW_KEY (0xa5 << 24) /* KEY Password */
#define AT91_SHDW_MR (AT91_SHDWC + 0x04) /* Shut Down Mode Register */
#define AT91_SHDW_WKMODE0 (3 << 0) /* Wake-up 0 Mode Selection */
diff --git a/include/asm-arm/arch-at91/at91_wdt.h b/include/asm-arm/arch-at91/at91_wdt.h
index 7251a344c74..1014e9bf181 100644
--- a/include/asm-arm/arch-at91/at91_wdt.h
+++ b/include/asm-arm/arch-at91/at91_wdt.h
@@ -15,7 +15,7 @@
#define AT91_WDT_CR (AT91_WDT + 0x00) /* Watchdog Control Register */
#define AT91_WDT_WDRSTT (1 << 0) /* Restart */
-#define AT91_WDT_KEY (0xff << 24) /* KEY Password */
+#define AT91_WDT_KEY (0xa5 << 24) /* KEY Password */
#define AT91_WDT_MR (AT91_WDT + 0x04) /* Watchdog Mode Register */
#define AT91_WDT_WDV (0xfff << 0) /* Counter Value */
diff --git a/include/asm-arm/arch-at91/at91x40.h b/include/asm-arm/arch-at91/at91x40.h
new file mode 100644
index 00000000000..612203e0177
--- /dev/null
+++ b/include/asm-arm/arch-at91/at91x40.h
@@ -0,0 +1,55 @@
+/*
+ * include/asm-arm/arch-at91/at91x40.h
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91X40_H
+#define AT91X40_H
+
+/*
+ * IRQ list.
+ */
+#define AT91_ID_FIQ 0 /* FIQ */
+#define AT91_ID_SYS 1 /* System Peripheral */
+#define AT91X40_ID_USART0 2 /* USART port 0 */
+#define AT91X40_ID_USART1 3 /* USART port 1 */
+#define AT91X40_ID_TC0 4 /* Timer/Counter 0 */
+#define AT91X40_ID_TC1 5 /* Timer/Counter 1*/
+#define AT91X40_ID_TC2 6 /* Timer/Counter 2*/
+#define AT91X40_ID_WD 7 /* Watchdog? */
+#define AT91X40_ID_PIOA 8 /* Parallel IO Controller A */
+
+#define AT91X40_ID_IRQ0 16 /* External IRQ 0 */
+#define AT91X40_ID_IRQ1 17 /* External IRQ 1 */
+#define AT91X40_ID_IRQ2 18 /* External IRQ 2 */
+
+/*
+ * System Peripherals (offset from AT91_BASE_SYS)
+ */
+#define AT91_BASE_SYS 0xffc00000
+
+#define AT91_EBI (0xffe00000 - AT91_BASE_SYS) /* External Bus Interface */
+#define AT91_SF (0xfff00000 - AT91_BASE_SYS) /* Special Function */
+#define AT91_USART1 (0xfffcc000 - AT91_BASE_SYS) /* USART 1 */
+#define AT91_USART0 (0xfffd0000 - AT91_BASE_SYS) /* USART 0 */
+#define AT91_TC (0xfffe0000 - AT91_BASE_SYS) /* Timer Counter */
+#define AT91_PIOA (0xffff0000 - AT91_BASE_SYS) /* PIO Controller A */
+#define AT91_PS (0xffff4000 - AT91_BASE_SYS) /* Power Save */
+#define AT91_WD (0xffff8000 - AT91_BASE_SYS) /* Watchdog Timer */
+#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) /* Advanced Interrupt Controller */
+
+/*
+ * The AT91x40 series doesn't have a debug unit like the other AT91 parts.
+ * But it does have a chip identify register and extension ID, so define at
+ * least these here.
+ */
+#define AT91_DBGU_CIDR (AT91_SF + 0) /* CIDR in PS segment */
+#define AT91_DBGU_EXID (AT91_SF + 4) /* EXID in PS segment */
+
+#endif /* AT91X40_H */
diff --git a/include/asm-arm/arch-at91/cpu.h b/include/asm-arm/arch-at91/cpu.h
index ef93c30a9c5..080cbb401a8 100644
--- a/include/asm-arm/arch-at91/cpu.h
+++ b/include/asm-arm/arch-at91/cpu.h
@@ -28,6 +28,11 @@
#define ARCH_ID_AT91SAM9RL64 0x019b03a0
+#define ARCH_ID_AT91M40800 0x14080044
+#define ARCH_ID_AT91R40807 0x44080746
+#define ARCH_ID_AT91M40807 0x14080745
+#define ARCH_ID_AT91R40008 0x44000840
+
static inline unsigned long at91_cpu_identify(void)
{
return (at91_sys_read(AT91_DBGU_CIDR) & ~AT91_CIDR_VERSION);
diff --git a/include/asm-arm/arch-at91/hardware.h b/include/asm-arm/arch-at91/hardware.h
index 46835e945ae..8f1cdd38a96 100644
--- a/include/asm-arm/arch-at91/hardware.h
+++ b/include/asm-arm/arch-at91/hardware.h
@@ -26,18 +26,29 @@
#include <asm/arch/at91sam9263.h>
#elif defined(CONFIG_ARCH_AT91SAM9RL)
#include <asm/arch/at91sam9rl.h>
+#elif defined(CONFIG_ARCH_AT91X40)
+#include <asm/arch/at91x40.h>
#else
#error "Unsupported AT91 processor"
#endif
+#ifdef CONFIG_MMU
/*
* Remap the peripherals from address 0xFFF78000 .. 0xFFFFFFFF
* to 0xFEF78000 .. 0xFF000000. (544Kb)
*/
#define AT91_IO_PHYS_BASE 0xFFF78000
-#define AT91_IO_SIZE (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
#define AT91_IO_VIRT_BASE (0xFF000000 - AT91_IO_SIZE)
+#else
+/*
+ * Identity mapping for the non MMU case.
+ */
+#define AT91_IO_PHYS_BASE AT91_BASE_SYS
+#define AT91_IO_VIRT_BASE AT91_IO_PHYS_BASE
+#endif
+
+#define AT91_IO_SIZE (0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
/* Convert a physical IO address to virtual IO address */
#define AT91_IO_P2V(x) ((x) - AT91_IO_PHYS_BASE + AT91_IO_VIRT_BASE)
@@ -66,7 +77,11 @@
#define AT91_CHIPSELECT_7 0x80000000
/* SDRAM */
+#ifdef CONFIG_DRAM_BASE
+#define AT91_SDRAM_BASE CONFIG_DRAM_BASE
+#else
#define AT91_SDRAM_BASE AT91_CHIPSELECT_1
+#endif
/* Clocks */
#define AT91_SLOW_CLOCK 32768 /* slow clock */
diff --git a/include/asm-arm/arch-at91/timex.h b/include/asm-arm/arch-at91/timex.h
index 2df1ee12dfb..a310698fb4d 100644
--- a/include/asm-arm/arch-at91/timex.h
+++ b/include/asm-arm/arch-at91/timex.h
@@ -42,6 +42,11 @@
#define AT91SAM9_MASTER_CLOCK 100000000
#define CLOCK_TICK_RATE (AT91SAM9_MASTER_CLOCK/16)
+#elif defined(CONFIG_ARCH_AT91X40)
+
+#define AT91X40_MASTER_CLOCK 40000000
+#define CLOCK_TICK_RATE (AT91X40_MASTER_CLOCK)
+
#endif
#endif
diff --git a/include/asm-arm/arch-at91/uncompress.h b/include/asm-arm/arch-at91/uncompress.h
index 30ac587b3b4..272a7e0dc6c 100644
--- a/include/asm-arm/arch-at91/uncompress.h
+++ b/include/asm-arm/arch-at91/uncompress.h
@@ -33,20 +33,24 @@
*/
static void putc(int c)
{
+#ifdef AT91_DBGU
void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */
while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
barrier();
__raw_writel(c, sys + AT91_DBGU_THR);
+#endif
}
static inline void flush(void)
{
+#ifdef AT91_DBGU
void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */
/* wait for transmission to complete */
while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
barrier();
+#endif
}
#define arch_decomp_setup()
diff --git a/include/asm-arm/arch-davinci/clock.h b/include/asm-arm/arch-davinci/clock.h
new file mode 100644
index 00000000000..cc168b7a14f
--- /dev/null
+++ b/include/asm-arm/arch-davinci/clock.h
@@ -0,0 +1,22 @@
+/*
+ * include/asm-arm/arch-davinci/clock.h
+ *
+ * Clock control driver for DaVinci - header file
+ *
+ * Authors: Vladimir Barinov <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
+#define __ASM_ARCH_DAVINCI_CLOCK_H
+
+struct clk;
+
+extern int clk_register(struct clk *clk);
+extern void clk_unregister(struct clk *clk);
+extern int davinci_clk_init(void);
+
+#endif
diff --git a/include/asm-arm/arch-davinci/gpio.h b/include/asm-arm/arch-davinci/gpio.h
new file mode 100644
index 00000000000..ea24a0e0bfd
--- /dev/null
+++ b/include/asm-arm/arch-davinci/gpio.h
@@ -0,0 +1,156 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __DAVINCI_GPIO_H
+#define __DAVINCI_GPIO_H
+
+/*
+ * basic gpio routines
+ *
+ * board-specific init should be done by arch/.../.../board-XXX.c (maybe
+ * initializing banks together) rather than boot loaders; kexec() won't
+ * go through boot loaders.
+ *
+ * the gpio clock will be turned on when gpios are used, and you may also
+ * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
+ * used as gpios, not with other peripherals.
+ *
+ * GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, and maybe
+ * for later updates, code should write GPIO(N) or:
+ * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
+ * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
+ *
+ * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
+ * for now, that's != GPIO(N)
+ */
+#define GPIO(X) (X) /* 0 <= X <= 70 */
+#define GPIOV18(X) (X) /* 1.8V i/o; 0 <= X <= 53 */
+#define GPIOV33(X) ((X)+54) /* 3.3V i/o; 0 <= X <= 17 */
+
+struct gpio_controller {
+ u32 dir;
+ u32 out_data;
+ u32 set_data;
+ u32 clr_data;
+ u32 in_data;
+ u32 set_rising;
+ u32 clr_rising;
+ u32 set_falling;
+ u32 clr_falling;
+ u32 intstat;
+};
+
+/* The __gpio_to_controller() and __gpio_mask() functions inline to constants
+ * with constant parameters; or in outlined code they execute at runtime.
+ *
+ * You'd access the controller directly when reading or writing more than
+ * one gpio value at a time, and to support wired logic where the value
+ * being driven by the cpu need not match the value read back.
+ *
+ * These are NOT part of the cross-platform GPIO interface
+ */
+static inline struct gpio_controller *__iomem
+__gpio_to_controller(unsigned gpio)
+{
+ void *__iomem ptr;
+
+ if (gpio < 32)
+ ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
+ else if (gpio < 64)
+ ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
+ else if (gpio < DAVINCI_N_GPIO)
+ ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+ else
+ ptr = NULL;
+ return ptr;
+}
+
+static inline u32 __gpio_mask(unsigned gpio)
+{
+ return 1 << (gpio % 32);
+}
+
+/* The get/set/clear functions will inline when called with constant
+ * parameters, for low-overhead bitbanging. Illegal constant parameters
+ * cause link-time errors.
+ *
+ * Otherwise, calls with variable parameters use outlined functions.
+ */
+extern int __error_inval_gpio(void);
+
+extern void __gpio_set(unsigned gpio, int value);
+extern int __gpio_get(unsigned gpio);
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ if (__builtin_constant_p(value)) {
+ struct gpio_controller *__iomem g;
+ u32 mask;
+
+ if (gpio >= DAVINCI_N_GPIO)
+ __error_inval_gpio();
+
+ g = __gpio_to_controller(gpio);
+ mask = __gpio_mask(gpio);
+ if (value)
+ __raw_writel(mask, &g->set_data);
+ else
+ __raw_writel(mask, &g->clr_data);
+ return;
+ }
+
+ __gpio_set(gpio, value);
+}
+
+/* Returns zero or nonzero; works for gpios configured as inputs OR
+ * as outputs.
+ *
+ * NOTE: changes in reported values are synchronized to the GPIO clock.
+ * This is most easily seen after calling gpio_set_value() and then immediatly
+ * gpio_get_value(), where the gpio_get_value() would return the old value
+ * until the GPIO clock ticks and the new value gets latched.
+ */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ struct gpio_controller *__iomem g;
+
+ if (!__builtin_constant_p(gpio))
+ return __gpio_get(gpio);
+
+ if (gpio >= DAVINCI_N_GPIO)
+ return __error_inval_gpio();
+
+ g = __gpio_to_controller(gpio);
+ return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
+}
+
+/* powerup default direction is IN */
+extern int gpio_direction_input(unsigned gpio);
+extern int gpio_direction_output(unsigned gpio, int value);
+
+#include <asm-generic/gpio.h> /* cansleep wrappers */
+
+extern int gpio_request(unsigned gpio, const char *tag);
+extern void gpio_free(unsigned gpio);
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return DAVINCI_N_AINTC_IRQ + gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return irq - DAVINCI_N_AINTC_IRQ;
+}
+
+#endif /* __DAVINCI_GPIO_H */
diff --git a/include/asm-arm/arch-davinci/hardware.h b/include/asm-arm/arch-davinci/hardware.h
index 60362d80229..a2e8969afac 100644
--- a/include/asm-arm/arch-davinci/hardware.h
+++ b/include/asm-arm/arch-davinci/hardware.h
@@ -11,4 +11,42 @@
#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H
+/*
+ * Base register addresses
+ */
+#define DAVINCI_DMA_3PCC_BASE (0x01C00000)
+#define DAVINCI_DMA_3PTC0_BASE (0x01C10000)
+#define DAVINCI_DMA_3PTC1_BASE (0x01C10400)
+#define DAVINCI_I2C_BASE (0x01C21000)
+#define DAVINCI_PWM0_BASE (0x01C22000)
+#define DAVINCI_PWM1_BASE (0x01C22400)
+#define DAVINCI_PWM2_BASE (0x01C22800)
+#define DAVINCI_SYSTEM_MODULE_BASE (0x01C40000)
+#define DAVINCI_PLL_CNTRL0_BASE (0x01C40800)
+#define DAVINCI_PLL_CNTRL1_BASE (0x01C40C00)
+#define DAVINCI_PWR_SLEEP_CNTRL_BASE (0x01C41000)
+#define DAVINCI_SYSTEM_DFT_BASE (0x01C42000)
+#define DAVINCI_IEEE1394_BASE (0x01C60000)
+#define DAVINCI_USB_OTG_BASE (0x01C64000)
+#define DAVINCI_CFC_ATA_BASE (0x01C66000)
+#define DAVINCI_SPI_BASE (0x01C66800)
+#define DAVINCI_GPIO_BASE (0x01C67000)
+#define DAVINCI_UHPI_BASE (0x01C67800)
+#define DAVINCI_VPSS_REGS_BASE (0x01C70000)
+#define DAVINCI_EMAC_CNTRL_REGS_BASE (0x01C80000)
+#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE (0x01C81000)
+#define DAVINCI_EMAC_WRAPPER_RAM_BASE (0x01C82000)
+#define DAVINCI_MDIO_CNTRL_REGS_BASE (0x01C84000)
+#define DAVINCI_IMCOP_BASE (0x01CC0000)
+#define DAVINCI_ASYNC_EMIF_CNTRL_BASE (0x01E00000)
+#define DAVINCI_VLYNQ_BASE (0x01E01000)
+#define DAVINCI_MCBSP_BASE (0x01E02000)
+#define DAVINCI_MMC_SD_BASE (0x01E10000)
+#define DAVINCI_MS_BASE (0x01E20000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE (0x02000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE (0x04000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE (0x06000000)
+#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE (0x08000000)
+#define DAVINCI_VLYNQ_REMOTE_BASE (0x0C000000)
+
#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-davinci/mux.h b/include/asm-arm/arch-davinci/mux.h
new file mode 100644
index 00000000000..c24b6782804
--- /dev/null
+++ b/include/asm-arm/arch-davinci/mux.h
@@ -0,0 +1,55 @@
+/*
+ * DaVinci pin multiplexing defines
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_MUX_H
+#define __ASM_ARCH_MUX_H
+
+#define DAVINCI_MUX_AEAW0 0
+#define DAVINCI_MUX_AEAW1 1
+#define DAVINCI_MUX_AEAW2 2
+#define DAVINCI_MUX_AEAW3 3
+#define DAVINCI_MUX_AEAW4 4
+#define DAVINCI_MUX_AECS4 10
+#define DAVINCI_MUX_AECS5 11
+#define DAVINCI_MUX_VLYNQWD0 12
+#define DAVINCI_MUX_VLYNQWD1 13
+#define DAVINCI_MUX_VLSCREN 14
+#define DAVINCI_MUX_VLYNQEN 15
+#define DAVINCI_MUX_HDIREN 16
+#define DAVINCI_MUX_ATAEN 17
+#define DAVINCI_MUX_RGB666 22
+#define DAVINCI_MUX_RGB888 23
+#define DAVINCI_MUX_LOEEN 24
+#define DAVINCI_MUX_LFLDEN 25
+#define DAVINCI_MUX_CWEN 26
+#define DAVINCI_MUX_CFLDEN 27
+#define DAVINCI_MUX_HPIEN 29
+#define DAVINCI_MUX_1394EN 30
+#define DAVINCI_MUX_EMACEN 31
+
+#define DAVINCI_MUX_LEVEL2 32
+#define DAVINCI_MUX_UART0 (DAVINCI_MUX_LEVEL2 + 0)
+#define DAVINCI_MUX_UART1 (DAVINCI_MUX_LEVEL2 + 1)
+#define DAVINCI_MUX_UART2 (DAVINCI_MUX_LEVEL2 + 2)
+#define DAVINCI_MUX_U2FLO (DAVINCI_MUX_LEVEL2 + 3)
+#define DAVINCI_MUX_PWM0 (DAVINCI_MUX_LEVEL2 + 4)
+#define DAVINCI_MUX_PWM1 (DAVINCI_MUX_LEVEL2 + 5)
+#define DAVINCI_MUX_PWM2 (DAVINCI_MUX_LEVEL2 + 6)
+#define DAVINCI_MUX_I2C (DAVINCI_MUX_LEVEL2 + 7)
+#define DAVINCI_MUX_SPI (DAVINCI_MUX_LEVEL2 + 8)
+#define DAVINCI_MUX_MSTK (DAVINCI_MUX_LEVEL2 + 9)
+#define DAVINCI_MUX_ASP (DAVINCI_MUX_LEVEL2 + 10)
+#define DAVINCI_MUX_CLK0 (DAVINCI_MUX_LEVEL2 + 16)
+#define DAVINCI_MUX_CLK1 (DAVINCI_MUX_LEVEL2 + 17)
+#define DAVINCI_MUX_TIMIN (DAVINCI_MUX_LEVEL2 + 18)
+
+extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable);
+
+#endif /* __ASM_ARCH_MUX_H */
diff --git a/include/asm-arm/arch-imx/gpio.h b/include/asm-arm/arch-imx/gpio.h
new file mode 100644
index 00000000000..486023263f3
--- /dev/null
+++ b/include/asm-arm/arch-imx/gpio.h
@@ -0,0 +1,102 @@
+#ifndef _IMX_GPIO_H
+
+#include <asm/arch/imx-regs.h>
+
+#define IMX_GPIO_ALLOC_MODE_NORMAL 0
+#define IMX_GPIO_ALLOC_MODE_NO_ALLOC 1
+#define IMX_GPIO_ALLOC_MODE_TRY_ALLOC 2
+#define IMX_GPIO_ALLOC_MODE_ALLOC_ONLY 4
+#define IMX_GPIO_ALLOC_MODE_RELEASE 8
+
+extern int imx_gpio_request(unsigned gpio, const char *label);
+
+extern void imx_gpio_free(unsigned gpio);
+
+extern int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+ int alloc_mode, const char *label);
+
+extern int imx_gpio_direction_input(unsigned gpio);
+
+extern int imx_gpio_direction_output(unsigned gpio, int value);
+
+extern void __imx_gpio_set_value(unsigned gpio, int value);
+
+static inline int imx_gpio_get_value(unsigned gpio)
+{
+ return SSR(gpio >> GPIO_PORT_SHIFT) & (1 << (gpio & GPIO_PIN_MASK));
+}
+
+static inline void imx_gpio_set_value_inline(unsigned gpio, int value)
+{
+ unsigned long flags;
+
+ raw_local_irq_save(flags);
+ if(value)
+ DR(gpio >> GPIO_PORT_SHIFT) |= (1 << (gpio & GPIO_PIN_MASK));
+ else
+ DR(gpio >> GPIO_PORT_SHIFT) &= ~(1 << (gpio & GPIO_PIN_MASK));
+ raw_local_irq_restore(flags);
+}
+
+static inline void imx_gpio_set_value(unsigned gpio, int value)
+{
+ if(__builtin_constant_p(gpio))
+ imx_gpio_set_value_inline(gpio, value);
+ else
+ __imx_gpio_set_value(gpio, value);
+}
+
+extern int imx_gpio_to_irq(unsigned gpio);
+
+extern int imx_irq_to_gpio(unsigned irq);
+
+/*-------------------------------------------------------------------------*/
+
+/* Wrappers for "new style" GPIO calls. These calls i.MX specific versions
+ * to allow future extension of GPIO logic.
+ */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+ return imx_gpio_request(gpio, label);
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+ imx_gpio_free(gpio);
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ return imx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ return imx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return imx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ imx_gpio_set_value(gpio, value);
+}
+
+#include <asm-generic/gpio.h> /* cansleep wrappers */
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return imx_gpio_to_irq(gpio);
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return imx_irq_to_gpio(irq);
+}
+
+
+#endif
diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h
index 30de404c61f..fb9de273387 100644
--- a/include/asm-arm/arch-imx/imx-regs.h
+++ b/include/asm-arm/arch-imx/imx-regs.h
@@ -77,6 +77,8 @@
#define SWR(x) __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8)
#define PUEN(x) __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8)
+#define GPIO_PORT_MAX 3
+
#define GPIO_PIN_MASK 0x1f
#define GPIO_PORT_MASK (0x3 << 5)
diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
new file mode 100644
index 00000000000..04006c1c5fd
--- /dev/null
+++ b/include/asm-arm/arch-iop13xx/adma.h
@@ -0,0 +1,544 @@
+/*
+ * Copyright(c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * 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 _ADMA_H
+#define _ADMA_H
+#include <linux/types.h>
+#include <linux/io.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop_adma.h>
+
+#define ADMA_ACCR(chan) (chan->mmr_base + 0x0)
+#define ADMA_ACSR(chan) (chan->mmr_base + 0x4)
+#define ADMA_ADAR(chan) (chan->mmr_base + 0x8)
+#define ADMA_IIPCR(chan) (chan->mmr_base + 0x18)
+#define ADMA_IIPAR(chan) (chan->mmr_base + 0x1c)
+#define ADMA_IIPUAR(chan) (chan->mmr_base + 0x20)
+#define ADMA_ANDAR(chan) (chan->mmr_base + 0x24)
+#define ADMA_ADCR(chan) (chan->mmr_base + 0x28)
+#define ADMA_CARMD(chan) (chan->mmr_base + 0x2c)
+#define ADMA_ABCR(chan) (chan->mmr_base + 0x30)
+#define ADMA_DLADR(chan) (chan->mmr_base + 0x34)
+#define ADMA_DUADR(chan) (chan->mmr_base + 0x38)
+#define ADMA_SLAR(src, chan) (chan->mmr_base + (0x3c + (src << 3)))
+#define ADMA_SUAR(src, chan) (chan->mmr_base + (0x40 + (src << 3)))
+
+struct iop13xx_adma_src {
+ u32 src_addr;
+ union {
+ u32 upper_src_addr;
+ struct {
+ unsigned int pq_upper_src_addr:24;
+ unsigned int pq_dmlt:8;
+ };
+ };
+};
+
+struct iop13xx_adma_desc_ctrl {
+ unsigned int int_en:1;
+ unsigned int xfer_dir:2;
+ unsigned int src_select:4;
+ unsigned int zero_result:1;
+ unsigned int block_fill_en:1;
+ unsigned int crc_gen_en:1;
+ unsigned int crc_xfer_dis:1;
+ unsigned int crc_seed_fetch_dis:1;
+ unsigned int status_write_back_en:1;
+ unsigned int endian_swap_en:1;
+ unsigned int reserved0:2;
+ unsigned int pq_update_xfer_en:1;
+ unsigned int dual_xor_en:1;
+ unsigned int pq_xfer_en:1;
+ unsigned int p_xfer_dis:1;
+ unsigned int reserved1:10;
+ unsigned int relax_order_en:1;
+ unsigned int no_snoop_en:1;
+};
+
+struct iop13xx_adma_byte_count {
+ unsigned int byte_count:24;
+ unsigned int host_if:3;
+ unsigned int reserved:2;
+ unsigned int zero_result_err_q:1;
+ unsigned int zero_result_err:1;
+ unsigned int tx_complete:1;
+};
+
+struct iop13xx_adma_desc_hw {
+ u32 next_desc;
+ union {
+ u32 desc_ctrl;
+ struct iop13xx_adma_desc_ctrl desc_ctrl_field;
+ };
+ union {
+ u32 crc_addr;
+ u32 block_fill_data;
+ u32 q_dest_addr;
+ };
+ union {
+ u32 byte_count;
+ struct iop13xx_adma_byte_count byte_count_field;
+ };
+ union {
+ u32 dest_addr;
+ u32 p_dest_addr;
+ };
+ union {
+ u32 upper_dest_addr;
+ u32 pq_upper_dest_addr;
+ };
+ struct iop13xx_adma_src src[1];
+};
+
+struct iop13xx_adma_desc_dual_xor {
+ u32 next_desc;
+ u32 desc_ctrl;
+ u32 reserved;
+ u32 byte_count;
+ u32 h_dest_addr;
+ u32 h_upper_dest_addr;
+ u32 src0_addr;
+ u32 upper_src0_addr;
+ u32 src1_addr;
+ u32 upper_src1_addr;
+ u32 h_src_addr;
+ u32 h_upper_src_addr;
+ u32 d_src_addr;
+ u32 d_upper_src_addr;
+ u32 d_dest_addr;
+ u32 d_upper_dest_addr;
+};
+
+struct iop13xx_adma_desc_pq_update {
+ u32 next_desc;
+ u32 desc_ctrl;
+ u32 reserved;
+ u32 byte_count;
+ u32 p_dest_addr;
+ u32 p_upper_dest_addr;
+ u32 src0_addr;
+ u32 upper_src0_addr;
+ u32 src1_addr;
+ u32 upper_src1_addr;
+ u32 p_src_addr;
+ u32 p_upper_src_addr;
+ u32 q_src_addr;
+ struct {
+ unsigned int q_upper_src_addr:24;
+ unsigned int q_dmlt:8;
+ };
+ u32 q_dest_addr;
+ u32 q_upper_dest_addr;
+};
+
+static inline int iop_adma_get_max_xor(void)
+{
+ return 16;
+}
+
+static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
+{
+ return __raw_readl(ADMA_ADAR(chan));
+}
+
+static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
+ u32 next_desc_addr)
+{
+ __raw_writel(next_desc_addr, ADMA_ANDAR(chan));
+}
+
+#define ADMA_STATUS_BUSY (1 << 13)
+
+static inline char iop_chan_is_busy(struct iop_adma_chan *chan)
+{
+ if (__raw_readl(ADMA_ACSR(chan)) &
+ ADMA_STATUS_BUSY)
+ return 1;
+ else
+ return 0;
+}
+
+static inline int
+iop_chan_get_desc_align(struct iop_adma_chan *chan, int num_slots)
+{
+ return 1;
+}
+#define iop_desc_is_aligned(x, y) 1
+
+static inline int
+iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
+{
+ *slots_per_op = 1;
+ return 1;
+}
+
+#define iop_chan_interrupt_slot_count(s, c) iop_chan_memcpy_slot_count(0, s)
+
+static inline int
+iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+{
+ *slots_per_op = 1;
+ return 1;
+}
+
+static inline int
+iop_chan_xor_slot_count(size_t len, int src_cnt, int *slots_per_op)
+{
+ int num_slots;
+ /* slots_to_find = 1 for basic descriptor + 1 per 4 sources above 1
+ * (1 source => 8 bytes) (1 slot => 32 bytes)
+ */
+ num_slots = 1 + (((src_cnt - 1) << 3) >> 5);
+ if (((src_cnt - 1) << 3) & 0x1f)
+ num_slots++;
+
+ *slots_per_op = num_slots;
+
+ return num_slots;
+}
+
+#define ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
+#define IOP_ADMA_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define IOP_ADMA_XOR_MAX_BYTE_COUNT ADMA_MAX_BYTE_COUNT
+#define iop_chan_zero_sum_slot_count(l, s, o) iop_chan_xor_slot_count(l, s, o)
+
+static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ return hw_desc->dest_addr;
+}
+
+static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ return hw_desc->byte_count_field.byte_count;
+}
+
+static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan,
+ int src_idx)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ return hw_desc->src[src_idx].src_addr;
+}
+
+static inline u32 iop_desc_get_src_count(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ return hw_desc->desc_ctrl_field.src_select + 1;
+}
+
+static inline void
+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ union {
+ u32 value;
+ struct iop13xx_adma_desc_ctrl field;
+ } u_desc_ctrl;
+
+ u_desc_ctrl.value = 0;
+ u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+ u_desc_ctrl.field.int_en = int_en;
+ hw_desc->desc_ctrl = u_desc_ctrl.value;
+ hw_desc->crc_addr = 0;
+}
+
+static inline void
+iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ union {
+ u32 value;
+ struct iop13xx_adma_desc_ctrl field;
+ } u_desc_ctrl;
+
+ u_desc_ctrl.value = 0;
+ u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+ u_desc_ctrl.field.block_fill_en = 1;
+ u_desc_ctrl.field.int_en = int_en;
+ hw_desc->desc_ctrl = u_desc_ctrl.value;
+ hw_desc->crc_addr = 0;
+}
+
+/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
+static inline void
+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ union {
+ u32 value;
+ struct iop13xx_adma_desc_ctrl field;
+ } u_desc_ctrl;
+
+ u_desc_ctrl.value = 0;
+ u_desc_ctrl.field.src_select = src_cnt - 1;
+ u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+ u_desc_ctrl.field.int_en = int_en;
+ hw_desc->desc_ctrl = u_desc_ctrl.value;
+ hw_desc->crc_addr = 0;
+
+}
+#define iop_desc_init_null_xor(d, s, i) iop_desc_init_xor(d, s, i)
+
+/* to do: support buffers larger than ADMA_MAX_BYTE_COUNT */
+static inline int
+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ union {
+ u32 value;
+ struct iop13xx_adma_desc_ctrl field;
+ } u_desc_ctrl;
+
+ u_desc_ctrl.value = 0;
+ u_desc_ctrl.field.src_select = src_cnt - 1;
+ u_desc_ctrl.field.xfer_dir = 3; /* local to internal bus */
+ u_desc_ctrl.field.zero_result = 1;
+ u_desc_ctrl.field.status_write_back_en = 1;
+ u_desc_ctrl.field.int_en = int_en;
+ hw_desc->desc_ctrl = u_desc_ctrl.value;
+ hw_desc->crc_addr = 0;
+
+ return 1;
+}
+
+static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan,
+ u32 byte_count)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ hw_desc->byte_count = byte_count;
+}
+
+static inline void
+iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
+{
+ int slots_per_op = desc->slots_per_op;
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
+ int i = 0;
+
+ if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+ hw_desc->byte_count = len;
+ } else {
+ do {
+ iter = iop_hw_desc_slot_idx(hw_desc, i);
+ iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+ len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+ i += slots_per_op;
+ } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
+
+ if (len) {
+ iter = iop_hw_desc_slot_idx(hw_desc, i);
+ iter->byte_count = len;
+ }
+ }
+}
+
+
+static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan,
+ dma_addr_t addr)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ hw_desc->dest_addr = addr;
+ hw_desc->upper_dest_addr = 0;
+}
+
+static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
+ dma_addr_t addr)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ hw_desc->src[0].src_addr = addr;
+ hw_desc->src[0].upper_src_addr = 0;
+}
+
+static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
+ int src_idx, dma_addr_t addr)
+{
+ int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc, *iter;
+ int i = 0;
+
+ do {
+ iter = iop_hw_desc_slot_idx(hw_desc, i);
+ iter->src[src_idx].src_addr = addr;
+ iter->src[src_idx].upper_src_addr = 0;
+ slot_cnt -= slots_per_op;
+ if (slot_cnt) {
+ i += slots_per_op;
+ addr += IOP_ADMA_XOR_MAX_BYTE_COUNT;
+ }
+ } while (slot_cnt);
+}
+
+static inline void
+iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan)
+{
+ iop_desc_init_memcpy(desc, 1);
+ iop_desc_set_byte_count(desc, chan, 0);
+ iop_desc_set_dest_addr(desc, chan, 0);
+ iop_desc_set_memcpy_src_addr(desc, 0);
+}
+
+#define iop_desc_set_zero_sum_src_addr iop_desc_set_xor_src_addr
+
+static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
+ u32 next_desc_addr)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ BUG_ON(hw_desc->next_desc);
+ hw_desc->next_desc = next_desc_addr;
+}
+
+static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ return hw_desc->next_desc;
+}
+
+static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ hw_desc->next_desc = 0;
+}
+
+static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
+ u32 val)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ hw_desc->block_fill_data = val;
+}
+
+static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+{
+ struct iop13xx_adma_desc_hw *hw_desc = desc->hw_desc;
+ struct iop13xx_adma_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
+ struct iop13xx_adma_byte_count byte_count = hw_desc->byte_count_field;
+
+ BUG_ON(!(byte_count.tx_complete && desc_ctrl.zero_result));
+
+ if (desc_ctrl.pq_xfer_en)
+ return byte_count.zero_result_err_q;
+ else
+ return byte_count.zero_result_err;
+}
+
+static inline void iop_chan_append(struct iop_adma_chan *chan)
+{
+ u32 adma_accr;
+
+ adma_accr = __raw_readl(ADMA_ACCR(chan));
+ adma_accr |= 0x2;
+ __raw_writel(adma_accr, ADMA_ACCR(chan));
+}
+
+static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+{
+ do { } while (0);
+}
+
+static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+{
+ return __raw_readl(ADMA_ACSR(chan));
+}
+
+static inline void iop_chan_disable(struct iop_adma_chan *chan)
+{
+ u32 adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
+ adma_chan_ctrl &= ~0x1;
+ __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
+}
+
+static inline void iop_chan_enable(struct iop_adma_chan *chan)
+{
+ u32 adma_chan_ctrl;
+
+ adma_chan_ctrl = __raw_readl(ADMA_ACCR(chan));
+ adma_chan_ctrl |= 0x1;
+ __raw_writel(adma_chan_ctrl, ADMA_ACCR(chan));
+}
+
+static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
+{
+ u32 status = __raw_readl(ADMA_ACSR(chan));
+ status &= (1 << 12);
+ __raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
+{
+ u32 status = __raw_readl(ADMA_ACSR(chan));
+ status &= (1 << 11);
+ __raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+{
+ u32 status = __raw_readl(ADMA_ACSR(chan));
+ status &= (1 << 9) | (1 << 5) | (1 << 4) | (1 << 3);
+ __raw_writel(status, ADMA_ACSR(chan));
+}
+
+static inline int
+iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
+{
+ return test_bit(9, &status);
+}
+
+static inline int
+iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
+{
+ return test_bit(5, &status);
+}
+
+static inline int
+iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+ return test_bit(4, &status);
+}
+
+static inline int
+iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+ return test_bit(3, &status);
+}
+
+static inline int
+iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+ return 0;
+}
+
+static inline int
+iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+ return 0;
+}
+
+static inline int
+iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
+{
+ return 0;
+}
+
+#endif /* _ADMA_H */
diff --git a/include/asm-arm/arch-iop13xx/iop13xx.h b/include/asm-arm/arch-iop13xx/iop13xx.h
index e6736c3d1f7..d4e4f828577 100644
--- a/include/asm-arm/arch-iop13xx/iop13xx.h
+++ b/include/asm-arm/arch-iop13xx/iop13xx.h
@@ -166,12 +166,22 @@ static inline int iop13xx_cpu_id(void)
#define IOP13XX_INIT_I2C_1 (1 << 1)
#define IOP13XX_INIT_I2C_2 (1 << 2)
-#define IQ81340_NUM_UART 2
-#define IQ81340_NUM_I2C 3
-#define IQ81340_NUM_PHYS_MAP_FLASH 1
-#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART +\
- IQ81340_NUM_I2C +\
- IQ81340_NUM_PHYS_MAP_FLASH)
+/* ADMA selection flags */
+/* INIT_ADMA_DEFAULT = Rely on CONFIG_IOP13XX_ADMA* */
+#define IOP13XX_INIT_ADMA_DEFAULT (0)
+#define IOP13XX_INIT_ADMA_0 (1 << 0)
+#define IOP13XX_INIT_ADMA_1 (1 << 1)
+#define IOP13XX_INIT_ADMA_2 (1 << 2)
+
+/* Platform devices */
+#define IQ81340_NUM_UART 2
+#define IQ81340_NUM_I2C 3
+#define IQ81340_NUM_PHYS_MAP_FLASH 1
+#define IQ81340_NUM_ADMA 3
+#define IQ81340_MAX_PLAT_DEVICES (IQ81340_NUM_UART + \
+ IQ81340_NUM_I2C + \
+ IQ81340_NUM_PHYS_MAP_FLASH + \
+ IQ81340_NUM_ADMA)
/*========================== PMMR offsets for key registers ============*/
#define IOP13XX_ATU0_PMMR_OFFSET 0x00048000
@@ -444,22 +454,6 @@ static inline int iop13xx_cpu_id(void)
/*==============================ADMA UNITS===============================*/
#define IOP13XX_ADMA_PHYS_BASE(chan) IOP13XX_REG_ADDR32_PHYS((chan << 9))
#define IOP13XX_ADMA_UPPER_PA(chan) (IOP13XX_ADMA_PHYS_BASE(chan) + 0xc0)
-#define IOP13XX_ADMA_OFFSET(chan, ofs) IOP13XX_REG_ADDR32((chan << 9) + (ofs))
-
-#define IOP13XX_ADMA_ACCR(chan) IOP13XX_ADMA_OFFSET(chan, 0x0)
-#define IOP13XX_ADMA_ACSR(chan) IOP13XX_ADMA_OFFSET(chan, 0x4)
-#define IOP13XX_ADMA_ADAR(chan) IOP13XX_ADMA_OFFSET(chan, 0x8)
-#define IOP13XX_ADMA_IIPCR(chan) IOP13XX_ADMA_OFFSET(chan, 0x18)
-#define IOP13XX_ADMA_IIPAR(chan) IOP13XX_ADMA_OFFSET(chan, 0x1c)
-#define IOP13XX_ADMA_IIPUAR(chan) IOP13XX_ADMA_OFFSET(chan, 0x20)
-#define IOP13XX_ADMA_ANDAR(chan) IOP13XX_ADMA_OFFSET(chan, 0x24)
-#define IOP13XX_ADMA_ADCR(chan) IOP13XX_ADMA_OFFSET(chan, 0x28)
-#define IOP13XX_ADMA_CARMD(chan) IOP13XX_ADMA_OFFSET(chan, 0x2c)
-#define IOP13XX_ADMA_ABCR(chan) IOP13XX_ADMA_OFFSET(chan, 0x30)
-#define IOP13XX_ADMA_DLADR(chan) IOP13XX_ADMA_OFFSET(chan, 0x34)
-#define IOP13XX_ADMA_DUADR(chan) IOP13XX_ADMA_OFFSET(chan, 0x38)
-#define IOP13XX_ADMA_SLAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x3c + (src <<3))
-#define IOP13XX_ADMA_SUAR(src, chan) IOP13XX_ADMA_OFFSET(chan, 0x40 + (src <<3))
/*==============================XSI BRIDGE===============================*/
#define IOP13XX_XBG_BECSR IOP13XX_REG_ADDR32(0x178c)
diff --git a/include/asm-arm/arch-iop32x/adma.h b/include/asm-arm/arch-iop32x/adma.h
new file mode 100644
index 00000000000..5ed92037dd1
--- /dev/null
+++ b/include/asm-arm/arch-iop32x/adma.h
@@ -0,0 +1,5 @@
+#ifndef IOP32X_ADMA_H
+#define IOP32X_ADMA_H
+#include <asm/hardware/iop3xx-adma.h>
+#endif
+
diff --git a/include/asm-arm/arch-iop33x/adma.h b/include/asm-arm/arch-iop33x/adma.h
new file mode 100644
index 00000000000..4b92f795f90
--- /dev/null
+++ b/include/asm-arm/arch-iop33x/adma.h
@@ -0,0 +1,5 @@
+#ifndef IOP33X_ADMA_H
+#define IOP33X_ADMA_H
+#include <asm/hardware/iop3xx-adma.h>
+#endif
+
diff --git a/include/asm-arm/arch-ixp4xx/ixdp425.h b/include/asm-arm/arch-ixp4xx/ixdp425.h
index 3d3820d7ba0..e0791af3bfe 100644
--- a/include/asm-arm/arch-ixp4xx/ixdp425.h
+++ b/include/asm-arm/arch-ixp4xx/ixdp425.h
@@ -32,4 +32,8 @@
#define IXDP425_PCI_INTC_PIN 9
#define IXDP425_PCI_INTD_PIN 8
+/* NAND Flash pins */
+#define IXDP425_NAND_NCE_PIN 12
+#define IXDP425_NAND_CMD_BYTE 0x01
+#define IXDP425_NAND_ADDR_BYTE 0x02
diff --git a/include/asm-arm/arch-ixp4xx/udc.h b/include/asm-arm/arch-ixp4xx/udc.h
index 79b850a3be4..dbdec36ff0d 100644
--- a/include/asm-arm/arch-ixp4xx/udc.h
+++ b/include/asm-arm/arch-ixp4xx/udc.h
@@ -6,25 +6,3 @@
extern void ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info);
-static inline int udc_gpio_to_irq(unsigned gpio)
-{
- return 0;
-}
-
-static inline void udc_gpio_init_vbus(unsigned gpio)
-{
-}
-
-static inline void udc_gpio_init_pullup(unsigned gpio)
-{
-}
-
-static inline int udc_gpio_get(unsigned gpio)
-{
- return 0;
-}
-
-static inline void udc_gpio_set(unsigned gpio, int is_on)
-{
-}
-
diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h
index 09ae6c91be6..f7a35b78823 100644
--- a/include/asm-arm/arch-ixp4xx/uncompress.h
+++ b/include/asm-arm/arch-ixp4xx/uncompress.h
@@ -38,9 +38,10 @@ static void flush(void)
static __inline__ void __arch_decomp_setup(unsigned long arch_id)
{
/*
- * Coyote and gtwx5715 only have UART2 connected
+ * Some boards are using UART2 as console
*/
- if (machine_is_adi_coyote() || machine_is_gtwx5715())
+ if (machine_is_adi_coyote() || machine_is_gtwx5715() ||
+ machine_is_gateway7001() || machine_is_wg302v2())
uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS;
else
uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS;
diff --git a/include/asm-arm/arch-ks8695/gpio.h b/include/asm-arm/arch-ks8695/gpio.h
new file mode 100644
index 00000000000..65ceea28607
--- /dev/null
+++ b/include/asm-arm/arch-ks8695/gpio.h
@@ -0,0 +1,79 @@
+/*
+ * include/asm-arm/arch-ks8695/gpio.h
+ *
+ * Copyright (C) 2006 Andrew Victor
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_GPIO_H_
+#define __ASM_ARCH_GPIO_H_
+
+#define KS8695_GPIO_0 0
+#define KS8695_GPIO_1 1
+#define KS8695_GPIO_2 2
+#define KS8695_GPIO_3 3
+#define KS8695_GPIO_4 4
+#define KS8695_GPIO_5 5
+#define KS8695_GPIO_6 6
+#define KS8695_GPIO_7 7
+#define KS8695_GPIO_8 8
+#define KS8695_GPIO_9 9
+#define KS8695_GPIO_10 10
+#define KS8695_GPIO_11 11
+#define KS8695_GPIO_12 12
+#define KS8695_GPIO_13 13
+#define KS8695_GPIO_14 14
+#define KS8695_GPIO_15 15
+
+
+/*
+ * Configure GPIO pin as external interrupt source.
+ */
+int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type);
+
+/*
+ * Configure the GPIO line as an input.
+ */
+int __init_or_module gpio_direction_input(unsigned int pin);
+
+/*
+ * Configure the GPIO line as an output, with default state.
+ */
+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state);
+
+/*
+ * Set the state of an output GPIO line.
+ */
+void gpio_set_value(unsigned int pin, unsigned int state);
+
+/*
+ * Read the state of a GPIO line.
+ */
+int gpio_get_value(unsigned int pin);
+
+/*
+ * Map GPIO line to IRQ number.
+ */
+int gpio_to_irq(unsigned int pin);
+
+/*
+ * Map IRQ number to GPIO line.
+ */
+int irq_to_gpio(unsigned int irq);
+
+
+#include <asm-generic/gpio.h>
+
+static inline int gpio_request(unsigned int pin, const char *label)
+{
+ return 0;
+}
+
+static inline void gpio_free(unsigned int pin)
+{
+}
+
+#endif
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index bed042d71d6..3280ee2ddfa 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -30,30 +30,12 @@ typedef enum {
DMA_PRIO_LOW = 2
} pxa_dma_prio;
-#if defined(CONFIG_PXA27x)
-
-#define PXA_DMA_CHANNELS 32
-
-#define pxa_for_each_dma_prio(ch, prio) \
-for ( \
- ch = prio * 4; \
- ch != (4 << prio) + 16; \
- ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1) \
-)
-
-#elif defined(CONFIG_PXA25x)
-
-#define PXA_DMA_CHANNELS 16
-
-#define pxa_for_each_dma_prio(ch, prio) \
- for (ch = prio * 4; ch != (4 << prio); ch++)
-
-#endif
-
/*
* DMA registration
*/
+int __init pxa_init_dma(int num_ch);
+
int pxa_request_dma (char *name,
pxa_dma_prio prio,
void (*irq_handler)(int, void *),
diff --git a/include/asm-arm/arch-pxa/entry-macro.S b/include/asm-arm/arch-pxa/entry-macro.S
index 1d5fbb9b379..b7e73085146 100644
--- a/include/asm-arm/arch-pxa/entry-macro.S
+++ b/include/asm-arm/arch-pxa/entry-macro.S
@@ -20,20 +20,38 @@
.endm
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
-#ifdef CONFIG_PXA27x
- mrc p6, 0, \irqstat, c0, c0, 0 @ ICIP
- mrc p6, 0, \irqnr, c1, c0, 0 @ ICMR
-#else
+ mrc p15, 0, \tmp, c0, c0, 0 @ CPUID
+ mov \tmp, \tmp, lsr #13
+ and \tmp, \tmp, #0x7 @ Core G
+ cmp \tmp, #1
+ bhi 1004f
+
mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000
add \base, \base, #0x00d00000
ldr \irqstat, [\base, #0] @ ICIP
ldr \irqnr, [\base, #4] @ ICMR
-#endif
+ b 1002f
+
+1004:
+ mrc p6, 0, \irqstat, c6, c0, 0 @ ICIP2
+ mrc p6, 0, \irqnr, c7, c0, 0 @ ICMR2
+ ands \irqstat, \irqstat, \irqnr
+ beq 1003f
+ rsb \irqstat, \irqnr, #0
+ and \irqstat, \irqstat, \irqnr
+ clz \irqnr, \irqstat
+ rsb \irqnr, \irqnr, #31
+ add \irqnr, \irqnr, #32
+ b 1001f
+1003:
+ mrc p6, 0, \irqstat, c0, c0, 0 @ ICIP
+ mrc p6, 0, \irqnr, c1, c0, 0 @ ICMR
+1002:
ands \irqnr, \irqstat, \irqnr
beq 1001f
rsb \irqstat, \irqnr, #0
and \irqstat, \irqstat, \irqnr
clz \irqnr, \irqstat
- rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP)
+ rsb \irqnr, \irqnr, #31
1001:
.endm
diff --git a/include/asm-arm/arch-pxa/gpio.h b/include/asm-arm/arch-pxa/gpio.h
index aeba24347f8..9e99241f3ed 100644
--- a/include/asm-arm/arch-pxa/gpio.h
+++ b/include/asm-arm/arch-pxa/gpio.h
@@ -45,7 +45,8 @@ static inline int gpio_direction_input(unsigned gpio)
static inline int gpio_direction_output(unsigned gpio, int value)
{
- return pxa_gpio_mode(gpio | GPIO_OUT | (value ? 0 : GPIO_DFLT_LOW));
+ return pxa_gpio_mode(gpio | GPIO_OUT |
+ (value ? GPIO_DFLT_HIGH : GPIO_DFLT_LOW));
}
static inline int __gpio_get_value(unsigned gpio)
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index e2bdc2fbede..38612174641 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -62,6 +62,42 @@
#ifndef __ASSEMBLY__
+#define __cpu_is_pxa21x(id) \
+ ({ \
+ unsigned int _id = (id) >> 4 & 0xf3f; \
+ _id == 0x212; \
+ })
+
+#define __cpu_is_pxa25x(id) \
+ ({ \
+ unsigned int _id = (id) >> 4 & 0xfff; \
+ _id == 0x2d0 || _id == 0x290; \
+ })
+
+#define __cpu_is_pxa27x(id) \
+ ({ \
+ unsigned int _id = (id) >> 4 & 0xfff; \
+ _id == 0x411; \
+ })
+
+#define cpu_is_pxa21x() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa21x(id); \
+ })
+
+#define cpu_is_pxa25x() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa25x(id); \
+ })
+
+#define cpu_is_pxa27x() \
+ ({ \
+ unsigned int id = read_cpuid(CPUID_ID); \
+ __cpu_is_pxa27x(id); \
+ })
+
/*
* Handy routine to set GPIO alternate functions
*/
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index 67ed43674c6..a07fe0f928c 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -11,14 +11,9 @@
*/
-#ifdef CONFIG_PXA27x
-#define PXA_IRQ_SKIP 0
-#else
-#define PXA_IRQ_SKIP 7
-#endif
-
-#define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP)
+#define PXA_IRQ(x) (x)
+#ifdef CONFIG_PXA27x
#define IRQ_SSP3 PXA_IRQ(0) /* SSP3 service request */
#define IRQ_MSL PXA_IRQ(1) /* MSL Interface interrupt */
#define IRQ_USBH2 PXA_IRQ(2) /* USB Host interrupt 1 (OHCI) */
@@ -26,6 +21,8 @@
#define IRQ_KEYPAD PXA_IRQ(4) /* Key pad controller */
#define IRQ_MEMSTK PXA_IRQ(5) /* Memory Stick interrupt */
#define IRQ_PWRI2C PXA_IRQ(6) /* Power I2C interrupt */
+#endif
+
#define IRQ_HWUART PXA_IRQ(7) /* HWUART Transmit/Receive/Error (PXA26x) */
#define IRQ_OST_4_11 PXA_IRQ(7) /* OS timer 4-11 matches (PXA27x) */
#define IRQ_GPIO0 PXA_IRQ(8) /* GPIO0 Edge Detect */
@@ -58,18 +55,15 @@
#ifdef CONFIG_PXA27x
#define IRQ_TPM PXA_IRQ(32) /* TPM interrupt */
#define IRQ_CAMERA PXA_IRQ(33) /* Camera Interface */
-
-#define PXA_INTERNAL_IRQS 34
-#else
-#define PXA_INTERNAL_IRQS 32
#endif
-#define GPIO_2_x_TO_IRQ(x) \
- PXA_IRQ((x) - 2 + PXA_INTERNAL_IRQS)
+#define PXA_GPIO_IRQ_BASE (64)
+#define PXA_GPIO_IRQ_NUM (128)
+
+#define GPIO_2_x_TO_IRQ(x) (PXA_GPIO_IRQ_BASE + (x))
#define IRQ_GPIO(x) (((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
-#define IRQ_TO_GPIO_2_x(i) \
- ((i) - IRQ_GPIO(2) + 2)
+#define IRQ_TO_GPIO_2_x(i) ((i) - PXA_GPIO_IRQ_BASE)
#define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
#if defined(CONFIG_PXA25x)
@@ -84,7 +78,7 @@
* these. If you need more, increase IRQ_BOARD_END, but keep it
* within sensible limits.
*/
-#define IRQ_BOARD_START (IRQ_GPIO(PXA_LAST_GPIO) + 1)
+#define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM)
#define IRQ_BOARD_END (IRQ_BOARD_START + 16)
#define IRQ_SA1111_START (IRQ_BOARD_END)
diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h
index 7a8a1cdf430..52243a62c4e 100644
--- a/include/asm-arm/arch-pxa/pm.h
+++ b/include/asm-arm/arch-pxa/pm.h
@@ -9,4 +9,3 @@
extern int pxa_pm_prepare(suspend_state_t state);
extern int pxa_pm_enter(suspend_state_t state);
-extern int pxa_pm_finish(suspend_state_t state);
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index dbcc9298b0c..e68b593d69d 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1765,29 +1765,9 @@
#define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : NULL))
/*
- * MultiMediaCard (MMC) controller
+ * MultiMediaCard (MMC) controller - see drivers/mmc/host/pxamci.h
*/
-#define MMC_STRPCL __REG(0x41100000) /* Control to start and stop MMC clock */
-#define MMC_STAT __REG(0x41100004) /* MMC Status Register (read only) */
-#define MMC_CLKRT __REG(0x41100008) /* MMC clock rate */
-#define MMC_SPI __REG(0x4110000c) /* SPI mode control bits */
-#define MMC_CMDAT __REG(0x41100010) /* Command/response/data sequence control */
-#define MMC_RESTO __REG(0x41100014) /* Expected response time out */
-#define MMC_RDTO __REG(0x41100018) /* Expected data read time out */
-#define MMC_BLKLEN __REG(0x4110001c) /* Block length of data transaction */
-#define MMC_NOB __REG(0x41100020) /* Number of blocks, for block mode */
-#define MMC_PRTBUF __REG(0x41100024) /* Partial MMC_TXFIFO FIFO written */
-#define MMC_I_MASK __REG(0x41100028) /* Interrupt Mask */
-#define MMC_I_REG __REG(0x4110002c) /* Interrupt Register (read only) */
-#define MMC_CMD __REG(0x41100030) /* Index of current command */
-#define MMC_ARGH __REG(0x41100034) /* MSW part of the current command argument */
-#define MMC_ARGL __REG(0x41100038) /* LSW part of the current command argument */
-#define MMC_RES __REG(0x4110003c) /* Response FIFO (read only) */
-#define MMC_RXFIFO __REG(0x41100040) /* Receive FIFO (read only) */
-#define MMC_TXFIFO __REG(0x41100044) /* Transmit FIFO (write only) */
-
-
/*
* Core Clock
*/
diff --git a/include/asm-arm/arch-pxa/udc.h b/include/asm-arm/arch-pxa/udc.h
index 8bc6f9c3e3e..27aa3a91012 100644
--- a/include/asm-arm/arch-pxa/udc.h
+++ b/include/asm-arm/arch-pxa/udc.h
@@ -1,41 +1,8 @@
/*
* linux/include/asm-arm/arch-pxa/udc.h
*
- * This supports machine-specific differences in how the PXA2xx
- * USB Device Controller (UDC) is wired.
- *
*/
#include <asm/mach/udc_pxa2xx.h>
extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
-static inline int udc_gpio_to_irq(unsigned gpio)
-{
- return IRQ_GPIO(gpio & GPIO_MD_MASK_NR);
-}
-
-static inline void udc_gpio_init_vbus(unsigned gpio)
-{
- pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_IN);
-}
-
-static inline void udc_gpio_init_pullup(unsigned gpio)
-{
- pxa_gpio_mode((gpio & GPIO_MD_MASK_NR) | GPIO_OUT | GPIO_DFLT_LOW);
-}
-
-static inline int udc_gpio_get(unsigned gpio)
-{
- return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
-}
-
-static inline void udc_gpio_set(unsigned gpio, int is_on)
-{
- int mask = GPIO_bit(gpio);
-
- if (is_on)
- GPSR(gpio) = mask;
- else
- GPCR(gpio) = mask;
-}
-
diff --git a/include/asm-arm/arch-s3c2410/anubis-cpld.h b/include/asm-arm/arch-s3c2410/anubis-cpld.h
index dcebf6d6190..168b93fee52 100644
--- a/include/asm-arm/arch-s3c2410/anubis-cpld.h
+++ b/include/asm-arm/arch-s3c2410/anubis-cpld.h
@@ -18,4 +18,8 @@
#define ANUBIS_CTRL1_NANDSEL (0x3)
+/* IDREG - revision */
+
+#define ANUBIS_IDREG_REVMASK (0x7)
+
#endif /* __ASM_ARCH_ANUBISCPLD_H */
diff --git a/include/asm-arm/arch-s3c2410/anubis-map.h b/include/asm-arm/arch-s3c2410/anubis-map.h
index ab076de4a0d..830d114261d 100644
--- a/include/asm-arm/arch-s3c2410/anubis-map.h
+++ b/include/asm-arm/arch-s3c2410/anubis-map.h
@@ -27,14 +27,8 @@
#define ANUBIS_VA_CTRL1 ANUBIS_IOADDR(0x00000000) /* 0x01800000 */
#define ANUBIS_PA_CTRL1 (ANUBIS_PA_CPLD)
-#define ANUBIS_VA_CTRL2 ANUBIS_IOADDR(0x00100000) /* 0x01900000 */
-#define ANUBIS_PA_CTRL2 (ANUBIS_PA_CPLD)
-
-#define ANUBIS_VA_CTRL3 ANUBIS_IOADDR(0x00200000) /* 0x01A00000 */
-#define ANUBIS_PA_CTRL3 (ANUBIS_PA_CPLD)
-
-#define ANUBIS_VA_CTRL4 ANUBIS_IOADDR(0x00300000) /* 0x01B00000 */
-#define ANUBIS_PA_CTRL4 (ANUBIS_PA_CPLD)
+#define ANUBIS_VA_IDREG ANUBIS_IOADDR(0x00300000) /* 0x01B00000 */
+#define ANUBIS_PA_IDREG (ANUBIS_PA_CPLD + (3<<23))
#define ANUBIS_IDEPRI ANUBIS_IOADDR(0x01000000)
#define ANUBIS_IDEPRIAUX ANUBIS_IOADDR(0x01100000)
diff --git a/include/asm-arm/arch-s3c2410/osiris-cpld.h b/include/asm-arm/arch-s3c2410/osiris-cpld.h
index 3b6498468d6..229ab2351db 100644
--- a/include/asm-arm/arch-s3c2410/osiris-cpld.h
+++ b/include/asm-arm/arch-s3c2410/osiris-cpld.h
@@ -1,6 +1,6 @@
/* linux/include/asm-arm/arch-s3c2410/osiris-cpld.h
*
- * Copyright (c) 2005 Simtec Electronics
+ * Copyright 2005 Simtec Electronics
* http://www.simtec.co.uk/products/
* Ben Dooks <ben@simtec.co.uk>
*
@@ -14,12 +14,17 @@
#ifndef __ASM_ARCH_OSIRISCPLD_H
#define __ASM_ARCH_OSIRISCPLD_H
-/* CTRL1 - NAND WP control */
+/* CTRL0 - NAND WP control */
-#define OSIRIS_CTRL1_NANDSEL (0x3)
-#define OSIRIS_CTRL1_BOOT_INT (1<<3)
-#define OSIRIS_CTRL1_PCMCIA (1<<4)
-#define OSIRIS_CTRL1_PCMCIA_nWAIT (1<<6)
-#define OSIRIS_CTRL1_PCMCIA_nIOIS16 (1<<7)
+#define OSIRIS_CTRL0_NANDSEL (0x3)
+#define OSIRIS_CTRL0_BOOT_INT (1<<3)
+#define OSIRIS_CTRL0_PCMCIA (1<<4)
+#define OSIRIS_CTRL0_FIX8 (1<<5)
+#define OSIRIS_CTRL0_PCMCIA_nWAIT (1<<6)
+#define OSIRIS_CTRL0_PCMCIA_nIOIS16 (1<<7)
+
+#define OSIRIS_CTRL1_FIX8 (1<<0)
+
+#define OSIRIS_ID_REVMASK (0x7)
#endif /* __ASM_ARCH_OSIRISCPLD_H */
diff --git a/include/asm-arm/arch-s3c2410/osiris-map.h b/include/asm-arm/arch-s3c2410/osiris-map.h
index a14164dfa52..b5c74d2b9aa 100644
--- a/include/asm-arm/arch-s3c2410/osiris-map.h
+++ b/include/asm-arm/arch-s3c2410/osiris-map.h
@@ -24,16 +24,19 @@
/* we put the CPLD registers next, to get them out of the way */
-#define OSIRIS_VA_CTRL1 OSIRIS_IOADDR(0x00000000)
-#define OSIRIS_PA_CTRL1 (OSIRIS_PA_CPLD)
+#define OSIRIS_VA_CTRL0 OSIRIS_IOADDR(0x00000000)
+#define OSIRIS_PA_CTRL0 (OSIRIS_PA_CPLD)
-#define OSIRIS_VA_CTRL2 OSIRIS_IOADDR(0x00100000)
-#define OSIRIS_PA_CTRL2 (OSIRIS_PA_CPLD + (1<<23))
+#define OSIRIS_VA_CTRL1 OSIRIS_IOADDR(0x00100000)
+#define OSIRIS_PA_CTRL1 (OSIRIS_PA_CPLD + (1<<23))
-#define OSIRIS_VA_CTRL3 OSIRIS_IOADDR(0x00200000)
-#define OSIRIS_PA_CTRL3 (OSIRIS_PA_CPLD + (2<<23))
+#define OSIRIS_VA_CTRL2 OSIRIS_IOADDR(0x00200000)
+#define OSIRIS_PA_CTRL2 (OSIRIS_PA_CPLD + (2<<23))
-#define OSIRIS_VA_CTRL4 OSIRIS_IOADDR(0x00300000)
-#define OSIRIS_PA_CTRL4 (OSIRIS_PA_CPLD + (3<<23))
+#define OSIRIS_VA_CTRL3 OSIRIS_IOADDR(0x00300000)
+#define OSIRIS_PA_CTRL3 (OSIRIS_PA_CPLD + (2<<23))
+
+#define OSIRIS_VA_IDREG OSIRIS_IOADDR(0x00700000)
+#define OSIRIS_PA_IDREG (OSIRIS_PA_CPLD + (7<<23))
#endif /* __ASM_ARCH_OSIRISMAP_H */
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index 3679a8a8922..d7a777f0508 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -7,6 +7,7 @@
*/
#include <asm/ptrace.h>
#include <asm/user.h>
+#include <asm/hwcap.h>
typedef unsigned long elf_greg_t;
typedef unsigned long elf_freg_t[3];
@@ -39,31 +40,9 @@ typedef struct user_fp elf_fpregset_t;
#endif
#define ELF_ARCH EM_ARM
-/*
- * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
- */
-#define HWCAP_SWP 1
-#define HWCAP_HALF 2
-#define HWCAP_THUMB 4
-#define HWCAP_26BIT 8 /* Play it safe */
-#define HWCAP_FAST_MULT 16
-#define HWCAP_FPA 32
-#define HWCAP_VFP 64
-#define HWCAP_EDSP 128
-#define HWCAP_JAVA 256
-#define HWCAP_IWMMXT 512
-#define HWCAP_CRUNCH 1024
-
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
/*
- * This yields a mask that user programs can use to figure out what
- * instruction set this cpu supports.
- */
-#define ELF_HWCAP (elf_hwcap)
-extern unsigned int elf_hwcap;
-
-/*
* This yields a string that ld.so will use to load implementation
* specific libraries for optimization. This is more specific in
* intent than poking at uname or /proc/cpuinfo.
diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
new file mode 100644
index 00000000000..10834b54f68
--- /dev/null
+++ b/include/asm-arm/hardware/iop3xx-adma.h
@@ -0,0 +1,892 @@
+/*
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * 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 _ADMA_H
+#define _ADMA_H
+#include <linux/types.h>
+#include <linux/io.h>
+#include <asm/hardware.h>
+#include <asm/hardware/iop_adma.h>
+
+/* Memory copy units */
+#define DMA_CCR(chan) (chan->mmr_base + 0x0)
+#define DMA_CSR(chan) (chan->mmr_base + 0x4)
+#define DMA_DAR(chan) (chan->mmr_base + 0xc)
+#define DMA_NDAR(chan) (chan->mmr_base + 0x10)
+#define DMA_PADR(chan) (chan->mmr_base + 0x14)
+#define DMA_PUADR(chan) (chan->mmr_base + 0x18)
+#define DMA_LADR(chan) (chan->mmr_base + 0x1c)
+#define DMA_BCR(chan) (chan->mmr_base + 0x20)
+#define DMA_DCR(chan) (chan->mmr_base + 0x24)
+
+/* Application accelerator unit */
+#define AAU_ACR(chan) (chan->mmr_base + 0x0)
+#define AAU_ASR(chan) (chan->mmr_base + 0x4)
+#define AAU_ADAR(chan) (chan->mmr_base + 0x8)
+#define AAU_ANDAR(chan) (chan->mmr_base + 0xc)
+#define AAU_SAR(src, chan) (chan->mmr_base + (0x10 + ((src) << 2)))
+#define AAU_DAR(chan) (chan->mmr_base + 0x20)
+#define AAU_ABCR(chan) (chan->mmr_base + 0x24)
+#define AAU_ADCR(chan) (chan->mmr_base + 0x28)
+#define AAU_SAR_EDCR(src_edc) (chan->mmr_base + (0x02c + ((src_edc-4) << 2)))
+#define AAU_EDCR0_IDX 8
+#define AAU_EDCR1_IDX 17
+#define AAU_EDCR2_IDX 26
+
+#define DMA0_ID 0
+#define DMA1_ID 1
+#define AAU_ID 2
+
+struct iop3xx_aau_desc_ctrl {
+ unsigned int int_en:1;
+ unsigned int blk1_cmd_ctrl:3;
+ unsigned int blk2_cmd_ctrl:3;
+ unsigned int blk3_cmd_ctrl:3;
+ unsigned int blk4_cmd_ctrl:3;
+ unsigned int blk5_cmd_ctrl:3;
+ unsigned int blk6_cmd_ctrl:3;
+ unsigned int blk7_cmd_ctrl:3;
+ unsigned int blk8_cmd_ctrl:3;
+ unsigned int blk_ctrl:2;
+ unsigned int dual_xor_en:1;
+ unsigned int tx_complete:1;
+ unsigned int zero_result_err:1;
+ unsigned int zero_result_en:1;
+ unsigned int dest_write_en:1;
+};
+
+struct iop3xx_aau_e_desc_ctrl {
+ unsigned int reserved:1;
+ unsigned int blk1_cmd_ctrl:3;
+ unsigned int blk2_cmd_ctrl:3;
+ unsigned int blk3_cmd_ctrl:3;
+ unsigned int blk4_cmd_ctrl:3;
+ unsigned int blk5_cmd_ctrl:3;
+ unsigned int blk6_cmd_ctrl:3;
+ unsigned int blk7_cmd_ctrl:3;
+ unsigned int blk8_cmd_ctrl:3;
+ unsigned int reserved2:7;
+};
+
+struct iop3xx_dma_desc_ctrl {
+ unsigned int pci_transaction:4;
+ unsigned int int_en:1;
+ unsigned int dac_cycle_en:1;
+ unsigned int mem_to_mem_en:1;
+ unsigned int crc_data_tx_en:1;
+ unsigned int crc_gen_en:1;
+ unsigned int crc_seed_dis:1;
+ unsigned int reserved:21;
+ unsigned int crc_tx_complete:1;
+};
+
+struct iop3xx_desc_dma {
+ u32 next_desc;
+ union {
+ u32 pci_src_addr;
+ u32 pci_dest_addr;
+ u32 src_addr;
+ };
+ union {
+ u32 upper_pci_src_addr;
+ u32 upper_pci_dest_addr;
+ };
+ union {
+ u32 local_pci_src_addr;
+ u32 local_pci_dest_addr;
+ u32 dest_addr;
+ };
+ u32 byte_count;
+ union {
+ u32 desc_ctrl;
+ struct iop3xx_dma_desc_ctrl desc_ctrl_field;
+ };
+ u32 crc_addr;
+};
+
+struct iop3xx_desc_aau {
+ u32 next_desc;
+ u32 src[4];
+ u32 dest_addr;
+ u32 byte_count;
+ union {
+ u32 desc_ctrl;
+ struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+ };
+ union {
+ u32 src_addr;
+ u32 e_desc_ctrl;
+ struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
+ } src_edc[31];
+};
+
+struct iop3xx_aau_gfmr {
+ unsigned int gfmr1:8;
+ unsigned int gfmr2:8;
+ unsigned int gfmr3:8;
+ unsigned int gfmr4:8;
+};
+
+struct iop3xx_desc_pq_xor {
+ u32 next_desc;
+ u32 src[3];
+ union {
+ u32 data_mult1;
+ struct iop3xx_aau_gfmr data_mult1_field;
+ };
+ u32 dest_addr;
+ u32 byte_count;
+ union {
+ u32 desc_ctrl;
+ struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+ };
+ union {
+ u32 src_addr;
+ u32 e_desc_ctrl;
+ struct iop3xx_aau_e_desc_ctrl e_desc_ctrl_field;
+ u32 data_multiplier;
+ struct iop3xx_aau_gfmr data_mult_field;
+ u32 reserved;
+ } src_edc_gfmr[19];
+};
+
+struct iop3xx_desc_dual_xor {
+ u32 next_desc;
+ u32 src0_addr;
+ u32 src1_addr;
+ u32 h_src_addr;
+ u32 d_src_addr;
+ u32 h_dest_addr;
+ u32 byte_count;
+ union {
+ u32 desc_ctrl;
+ struct iop3xx_aau_desc_ctrl desc_ctrl_field;
+ };
+ u32 d_dest_addr;
+};
+
+union iop3xx_desc {
+ struct iop3xx_desc_aau *aau;
+ struct iop3xx_desc_dma *dma;
+ struct iop3xx_desc_pq_xor *pq_xor;
+ struct iop3xx_desc_dual_xor *dual_xor;
+ void *ptr;
+};
+
+static inline int iop_adma_get_max_xor(void)
+{
+ return 32;
+}
+
+static inline u32 iop_chan_get_current_descriptor(struct iop_adma_chan *chan)
+{
+ int id = chan->device->id;
+
+ switch (id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ return __raw_readl(DMA_DAR(chan));
+ case AAU_ID:
+ return __raw_readl(AAU_ADAR(chan));
+ default:
+ BUG();
+ }
+ return 0;
+}
+
+static inline void iop_chan_set_next_descriptor(struct iop_adma_chan *chan,
+ u32 next_desc_addr)
+{
+ int id = chan->device->id;
+
+ switch (id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ __raw_writel(next_desc_addr, DMA_NDAR(chan));
+ break;
+ case AAU_ID:
+ __raw_writel(next_desc_addr, AAU_ANDAR(chan));
+ break;
+ }
+
+}
+
+#define IOP_ADMA_STATUS_BUSY (1 << 10)
+#define IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT (1024)
+#define IOP_ADMA_XOR_MAX_BYTE_COUNT (16 * 1024 * 1024)
+#define IOP_ADMA_MAX_BYTE_COUNT (16 * 1024 * 1024)
+
+static inline int iop_chan_is_busy(struct iop_adma_chan *chan)
+{
+ u32 status = __raw_readl(DMA_CSR(chan));
+ return (status & IOP_ADMA_STATUS_BUSY) ? 1 : 0;
+}
+
+static inline int iop_desc_is_aligned(struct iop_adma_desc_slot *desc,
+ int num_slots)
+{
+ /* num_slots will only ever be 1, 2, 4, or 8 */
+ return (desc->idx & (num_slots - 1)) ? 0 : 1;
+}
+
+/* to do: support large (i.e. > hw max) buffer sizes */
+static inline int iop_chan_memcpy_slot_count(size_t len, int *slots_per_op)
+{
+ *slots_per_op = 1;
+ return 1;
+}
+
+/* to do: support large (i.e. > hw max) buffer sizes */
+static inline int iop_chan_memset_slot_count(size_t len, int *slots_per_op)
+{
+ *slots_per_op = 1;
+ return 1;
+}
+
+static inline int iop3xx_aau_xor_slot_count(size_t len, int src_cnt,
+ int *slots_per_op)
+{
+ const static int slot_count_table[] = { 0,
+ 1, 1, 1, 1, /* 01 - 04 */
+ 2, 2, 2, 2, /* 05 - 08 */
+ 4, 4, 4, 4, /* 09 - 12 */
+ 4, 4, 4, 4, /* 13 - 16 */
+ 8, 8, 8, 8, /* 17 - 20 */
+ 8, 8, 8, 8, /* 21 - 24 */
+ 8, 8, 8, 8, /* 25 - 28 */
+ 8, 8, 8, 8, /* 29 - 32 */
+ };
+ *slots_per_op = slot_count_table[src_cnt];
+ return *slots_per_op;
+}
+
+static inline int
+iop_chan_interrupt_slot_count(int *slots_per_op, struct iop_adma_chan *chan)
+{
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ return iop_chan_memcpy_slot_count(0, slots_per_op);
+ case AAU_ID:
+ return iop3xx_aau_xor_slot_count(0, 2, slots_per_op);
+ default:
+ BUG();
+ }
+ return 0;
+}
+
+static inline int iop_chan_xor_slot_count(size_t len, int src_cnt,
+ int *slots_per_op)
+{
+ int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
+
+ if (len <= IOP_ADMA_XOR_MAX_BYTE_COUNT)
+ return slot_cnt;
+
+ len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
+ while (len > IOP_ADMA_XOR_MAX_BYTE_COUNT) {
+ len -= IOP_ADMA_XOR_MAX_BYTE_COUNT;
+ slot_cnt += *slots_per_op;
+ }
+
+ if (len)
+ slot_cnt += *slots_per_op;
+
+ return slot_cnt;
+}
+
+/* zero sum on iop3xx is limited to 1k at a time so it requires multiple
+ * descriptors
+ */
+static inline int iop_chan_zero_sum_slot_count(size_t len, int src_cnt,
+ int *slots_per_op)
+{
+ int slot_cnt = iop3xx_aau_xor_slot_count(len, src_cnt, slots_per_op);
+
+ if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT)
+ return slot_cnt;
+
+ len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+ while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+ len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+ slot_cnt += *slots_per_op;
+ }
+
+ if (len)
+ slot_cnt += *slots_per_op;
+
+ return slot_cnt;
+}
+
+static inline u32 iop_desc_get_dest_addr(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan)
+{
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ return hw_desc.dma->dest_addr;
+ case AAU_ID:
+ return hw_desc.aau->dest_addr;
+ default:
+ BUG();
+ }
+ return 0;
+}
+
+static inline u32 iop_desc_get_byte_count(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan)
+{
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ return hw_desc.dma->byte_count;
+ case AAU_ID:
+ return hw_desc.aau->byte_count;
+ default:
+ BUG();
+ }
+ return 0;
+}
+
+/* translate the src_idx to a descriptor word index */
+static inline int __desc_idx(int src_idx)
+{
+ const static int desc_idx_table[] = { 0, 0, 0, 0,
+ 0, 1, 2, 3,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 14, 15, 16, 17,
+ 18, 19, 20, 21,
+ 23, 24, 25, 26,
+ 27, 28, 29, 30,
+ };
+
+ return desc_idx_table[src_idx];
+}
+
+static inline u32 iop_desc_get_src_addr(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan,
+ int src_idx)
+{
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ return hw_desc.dma->src_addr;
+ case AAU_ID:
+ break;
+ default:
+ BUG();
+ }
+
+ if (src_idx < 4)
+ return hw_desc.aau->src[src_idx];
+ else
+ return hw_desc.aau->src_edc[__desc_idx(src_idx)].src_addr;
+}
+
+static inline void iop3xx_aau_desc_set_src_addr(struct iop3xx_desc_aau *hw_desc,
+ int src_idx, dma_addr_t addr)
+{
+ if (src_idx < 4)
+ hw_desc->src[src_idx] = addr;
+ else
+ hw_desc->src_edc[__desc_idx(src_idx)].src_addr = addr;
+}
+
+static inline void
+iop_desc_init_memcpy(struct iop_adma_desc_slot *desc, int int_en)
+{
+ struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
+ union {
+ u32 value;
+ struct iop3xx_dma_desc_ctrl field;
+ } u_desc_ctrl;
+
+ u_desc_ctrl.value = 0;
+ u_desc_ctrl.field.mem_to_mem_en = 1;
+ u_desc_ctrl.field.pci_transaction = 0xe; /* memory read block */
+ u_desc_ctrl.field.int_en = int_en;
+ hw_desc->desc_ctrl = u_desc_ctrl.value;
+ hw_desc->upper_pci_src_addr = 0;
+ hw_desc->crc_addr = 0;
+}
+
+static inline void
+iop_desc_init_memset(struct iop_adma_desc_slot *desc, int int_en)
+{
+ struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+ union {
+ u32 value;
+ struct iop3xx_aau_desc_ctrl field;
+ } u_desc_ctrl;
+
+ u_desc_ctrl.value = 0;
+ u_desc_ctrl.field.blk1_cmd_ctrl = 0x2; /* memory block fill */
+ u_desc_ctrl.field.dest_write_en = 1;
+ u_desc_ctrl.field.int_en = int_en;
+ hw_desc->desc_ctrl = u_desc_ctrl.value;
+}
+
+static inline u32
+iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, int int_en)
+{
+ int i, shift;
+ u32 edcr;
+ union {
+ u32 value;
+ struct iop3xx_aau_desc_ctrl field;
+ } u_desc_ctrl;
+
+ u_desc_ctrl.value = 0;
+ switch (src_cnt) {
+ case 25 ... 32:
+ u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+ edcr = 0;
+ shift = 1;
+ for (i = 24; i < src_cnt; i++) {
+ edcr |= (1 << shift);
+ shift += 3;
+ }
+ hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr;
+ src_cnt = 24;
+ /* fall through */
+ case 17 ... 24:
+ if (!u_desc_ctrl.field.blk_ctrl) {
+ hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+ u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+ }
+ edcr = 0;
+ shift = 1;
+ for (i = 16; i < src_cnt; i++) {
+ edcr |= (1 << shift);
+ shift += 3;
+ }
+ hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr;
+ src_cnt = 16;
+ /* fall through */
+ case 9 ... 16:
+ if (!u_desc_ctrl.field.blk_ctrl)
+ u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
+ edcr = 0;
+ shift = 1;
+ for (i = 8; i < src_cnt; i++) {
+ edcr |= (1 << shift);
+ shift += 3;
+ }
+ hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr;
+ src_cnt = 8;
+ /* fall through */
+ case 2 ... 8:
+ shift = 1;
+ for (i = 0; i < src_cnt; i++) {
+ u_desc_ctrl.value |= (1 << shift);
+ shift += 3;
+ }
+
+ if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
+ u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
+ }
+
+ u_desc_ctrl.field.dest_write_en = 1;
+ u_desc_ctrl.field.blk1_cmd_ctrl = 0x7; /* direct fill */
+ u_desc_ctrl.field.int_en = int_en;
+ hw_desc->desc_ctrl = u_desc_ctrl.value;
+
+ return u_desc_ctrl.value;
+}
+
+static inline void
+iop_desc_init_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+ iop3xx_desc_init_xor(desc->hw_desc, src_cnt, int_en);
+}
+
+/* return the number of operations */
+static inline int
+iop_desc_init_zero_sum(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+ int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+ struct iop3xx_desc_aau *hw_desc, *prev_hw_desc, *iter;
+ union {
+ u32 value;
+ struct iop3xx_aau_desc_ctrl field;
+ } u_desc_ctrl;
+ int i, j;
+
+ hw_desc = desc->hw_desc;
+
+ for (i = 0, j = 0; (slot_cnt -= slots_per_op) >= 0;
+ i += slots_per_op, j++) {
+ iter = iop_hw_desc_slot_idx(hw_desc, i);
+ u_desc_ctrl.value = iop3xx_desc_init_xor(iter, src_cnt, int_en);
+ u_desc_ctrl.field.dest_write_en = 0;
+ u_desc_ctrl.field.zero_result_en = 1;
+ u_desc_ctrl.field.int_en = int_en;
+ iter->desc_ctrl = u_desc_ctrl.value;
+
+ /* for the subsequent descriptors preserve the store queue
+ * and chain them together
+ */
+ if (i) {
+ prev_hw_desc =
+ iop_hw_desc_slot_idx(hw_desc, i - slots_per_op);
+ prev_hw_desc->next_desc =
+ (u32) (desc->async_tx.phys + (i << 5));
+ }
+ }
+
+ return j;
+}
+
+static inline void
+iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, int int_en)
+{
+ struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+ union {
+ u32 value;
+ struct iop3xx_aau_desc_ctrl field;
+ } u_desc_ctrl;
+
+ u_desc_ctrl.value = 0;
+ switch (src_cnt) {
+ case 25 ... 32:
+ u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+ hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+ /* fall through */
+ case 17 ... 24:
+ if (!u_desc_ctrl.field.blk_ctrl) {
+ hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0;
+ u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */
+ }
+ hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0;
+ /* fall through */
+ case 9 ... 16:
+ if (!u_desc_ctrl.field.blk_ctrl)
+ u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */
+ hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0;
+ /* fall through */
+ case 1 ... 8:
+ if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4)
+ u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */
+ }
+
+ u_desc_ctrl.field.dest_write_en = 0;
+ u_desc_ctrl.field.int_en = int_en;
+ hw_desc->desc_ctrl = u_desc_ctrl.value;
+}
+
+static inline void iop_desc_set_byte_count(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan,
+ u32 byte_count)
+{
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ hw_desc.dma->byte_count = byte_count;
+ break;
+ case AAU_ID:
+ hw_desc.aau->byte_count = byte_count;
+ break;
+ default:
+ BUG();
+ }
+}
+
+static inline void
+iop_desc_init_interrupt(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan)
+{
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ iop_desc_init_memcpy(desc, 1);
+ hw_desc.dma->byte_count = 0;
+ hw_desc.dma->dest_addr = 0;
+ hw_desc.dma->src_addr = 0;
+ break;
+ case AAU_ID:
+ iop_desc_init_null_xor(desc, 2, 1);
+ hw_desc.aau->byte_count = 0;
+ hw_desc.aau->dest_addr = 0;
+ hw_desc.aau->src[0] = 0;
+ hw_desc.aau->src[1] = 0;
+ break;
+ default:
+ BUG();
+ }
+}
+
+static inline void
+iop_desc_set_zero_sum_byte_count(struct iop_adma_desc_slot *desc, u32 len)
+{
+ int slots_per_op = desc->slots_per_op;
+ struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+ int i = 0;
+
+ if (len <= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+ hw_desc->byte_count = len;
+ } else {
+ do {
+ iter = iop_hw_desc_slot_idx(hw_desc, i);
+ iter->byte_count = IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+ len -= IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT;
+ i += slots_per_op;
+ } while (len > IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT);
+
+ if (len) {
+ iter = iop_hw_desc_slot_idx(hw_desc, i);
+ iter->byte_count = len;
+ }
+ }
+}
+
+static inline void iop_desc_set_dest_addr(struct iop_adma_desc_slot *desc,
+ struct iop_adma_chan *chan,
+ dma_addr_t addr)
+{
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ hw_desc.dma->dest_addr = addr;
+ break;
+ case AAU_ID:
+ hw_desc.aau->dest_addr = addr;
+ break;
+ default:
+ BUG();
+ }
+}
+
+static inline void iop_desc_set_memcpy_src_addr(struct iop_adma_desc_slot *desc,
+ dma_addr_t addr)
+{
+ struct iop3xx_desc_dma *hw_desc = desc->hw_desc;
+ hw_desc->src_addr = addr;
+}
+
+static inline void
+iop_desc_set_zero_sum_src_addr(struct iop_adma_desc_slot *desc, int src_idx,
+ dma_addr_t addr)
+{
+
+ struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+ int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+ int i;
+
+ for (i = 0; (slot_cnt -= slots_per_op) >= 0;
+ i += slots_per_op, addr += IOP_ADMA_ZERO_SUM_MAX_BYTE_COUNT) {
+ iter = iop_hw_desc_slot_idx(hw_desc, i);
+ iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
+ }
+}
+
+static inline void iop_desc_set_xor_src_addr(struct iop_adma_desc_slot *desc,
+ int src_idx, dma_addr_t addr)
+{
+
+ struct iop3xx_desc_aau *hw_desc = desc->hw_desc, *iter;
+ int slot_cnt = desc->slot_cnt, slots_per_op = desc->slots_per_op;
+ int i;
+
+ for (i = 0; (slot_cnt -= slots_per_op) >= 0;
+ i += slots_per_op, addr += IOP_ADMA_XOR_MAX_BYTE_COUNT) {
+ iter = iop_hw_desc_slot_idx(hw_desc, i);
+ iop3xx_aau_desc_set_src_addr(iter, src_idx, addr);
+ }
+}
+
+static inline void iop_desc_set_next_desc(struct iop_adma_desc_slot *desc,
+ u32 next_desc_addr)
+{
+ /* hw_desc->next_desc is the same location for all channels */
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+ BUG_ON(hw_desc.dma->next_desc);
+ hw_desc.dma->next_desc = next_desc_addr;
+}
+
+static inline u32 iop_desc_get_next_desc(struct iop_adma_desc_slot *desc)
+{
+ /* hw_desc->next_desc is the same location for all channels */
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+ return hw_desc.dma->next_desc;
+}
+
+static inline void iop_desc_clear_next_desc(struct iop_adma_desc_slot *desc)
+{
+ /* hw_desc->next_desc is the same location for all channels */
+ union iop3xx_desc hw_desc = { .ptr = desc->hw_desc, };
+ hw_desc.dma->next_desc = 0;
+}
+
+static inline void iop_desc_set_block_fill_val(struct iop_adma_desc_slot *desc,
+ u32 val)
+{
+ struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+ hw_desc->src[0] = val;
+}
+
+static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
+{
+ struct iop3xx_desc_aau *hw_desc = desc->hw_desc;
+ struct iop3xx_aau_desc_ctrl desc_ctrl = hw_desc->desc_ctrl_field;
+
+ BUG_ON(!(desc_ctrl.tx_complete && desc_ctrl.zero_result_en));
+ return desc_ctrl.zero_result_err;
+}
+
+static inline void iop_chan_append(struct iop_adma_chan *chan)
+{
+ u32 dma_chan_ctrl;
+ /* workaround dropped interrupts on 3xx */
+ mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));
+
+ dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+ dma_chan_ctrl |= 0x2;
+ __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
+{
+ if (!busy)
+ del_timer(&chan->cleanup_watchdog);
+}
+
+static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
+{
+ return __raw_readl(DMA_CSR(chan));
+}
+
+static inline void iop_chan_disable(struct iop_adma_chan *chan)
+{
+ u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+ dma_chan_ctrl &= ~1;
+ __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_chan_enable(struct iop_adma_chan *chan)
+{
+ u32 dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
+
+ dma_chan_ctrl |= 1;
+ __raw_writel(dma_chan_ctrl, DMA_CCR(chan));
+}
+
+static inline void iop_adma_device_clear_eot_status(struct iop_adma_chan *chan)
+{
+ u32 status = __raw_readl(DMA_CSR(chan));
+ status &= (1 << 9);
+ __raw_writel(status, DMA_CSR(chan));
+}
+
+static inline void iop_adma_device_clear_eoc_status(struct iop_adma_chan *chan)
+{
+ u32 status = __raw_readl(DMA_CSR(chan));
+ status &= (1 << 8);
+ __raw_writel(status, DMA_CSR(chan));
+}
+
+static inline void iop_adma_device_clear_err_status(struct iop_adma_chan *chan)
+{
+ u32 status = __raw_readl(DMA_CSR(chan));
+
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ status &= (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1);
+ break;
+ case AAU_ID:
+ status &= (1 << 5);
+ break;
+ default:
+ BUG();
+ }
+
+ __raw_writel(status, DMA_CSR(chan));
+}
+
+static inline int
+iop_is_err_int_parity(unsigned long status, struct iop_adma_chan *chan)
+{
+ return 0;
+}
+
+static inline int
+iop_is_err_mcu_abort(unsigned long status, struct iop_adma_chan *chan)
+{
+ return 0;
+}
+
+static inline int
+iop_is_err_int_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+ return 0;
+}
+
+static inline int
+iop_is_err_int_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+ return test_bit(5, &status);
+}
+
+static inline int
+iop_is_err_pci_tabort(unsigned long status, struct iop_adma_chan *chan)
+{
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ return test_bit(2, &status);
+ default:
+ return 0;
+ }
+}
+
+static inline int
+iop_is_err_pci_mabort(unsigned long status, struct iop_adma_chan *chan)
+{
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ return test_bit(3, &status);
+ default:
+ return 0;
+ }
+}
+
+static inline int
+iop_is_err_split_tx(unsigned long status, struct iop_adma_chan *chan)
+{
+ switch (chan->device->id) {
+ case DMA0_ID:
+ case DMA1_ID:
+ return test_bit(1, &status);
+ default:
+ return 0;
+ }
+}
+#endif /* _ADMA_H */
diff --git a/include/asm-arm/hardware/iop3xx.h b/include/asm-arm/hardware/iop3xx.h
index 63feceb7ede..81ca5d3e2bf 100644
--- a/include/asm-arm/hardware/iop3xx.h
+++ b/include/asm-arm/hardware/iop3xx.h
@@ -144,24 +144,9 @@ extern int init_atu;
#define IOP3XX_IAR (volatile u32 *)IOP3XX_REG_ADDR(0x0380)
/* DMA Controller */
-#define IOP3XX_DMA0_CCR (volatile u32 *)IOP3XX_REG_ADDR(0x0400)
-#define IOP3XX_DMA0_CSR (volatile u32 *)IOP3XX_REG_ADDR(0x0404)
-#define IOP3XX_DMA0_DAR (volatile u32 *)IOP3XX_REG_ADDR(0x040c)
-#define IOP3XX_DMA0_NDAR (volatile u32 *)IOP3XX_REG_ADDR(0x0410)
-#define IOP3XX_DMA0_PADR (volatile u32 *)IOP3XX_REG_ADDR(0x0414)
-#define IOP3XX_DMA0_PUADR (volatile u32 *)IOP3XX_REG_ADDR(0x0418)
-#define IOP3XX_DMA0_LADR (volatile u32 *)IOP3XX_REG_ADDR(0x041c)
-#define IOP3XX_DMA0_BCR (volatile u32 *)IOP3XX_REG_ADDR(0x0420)
-#define IOP3XX_DMA0_DCR (volatile u32 *)IOP3XX_REG_ADDR(0x0424)
-#define IOP3XX_DMA1_CCR (volatile u32 *)IOP3XX_REG_ADDR(0x0440)
-#define IOP3XX_DMA1_CSR (volatile u32 *)IOP3XX_REG_ADDR(0x0444)
-#define IOP3XX_DMA1_DAR (volatile u32 *)IOP3XX_REG_ADDR(0x044c)
-#define IOP3XX_DMA1_NDAR (volatile u32 *)IOP3XX_REG_ADDR(0x0450)
-#define IOP3XX_DMA1_PADR (volatile u32 *)IOP3XX_REG_ADDR(0x0454)
-#define IOP3XX_DMA1_PUADR (volatile u32 *)IOP3XX_REG_ADDR(0x0458)
-#define IOP3XX_DMA1_LADR (volatile u32 *)IOP3XX_REG_ADDR(0x045c)
-#define IOP3XX_DMA1_BCR (volatile u32 *)IOP3XX_REG_ADDR(0x0460)
-#define IOP3XX_DMA1_DCR (volatile u32 *)IOP3XX_REG_ADDR(0x0464)
+#define IOP3XX_DMA_PHYS_BASE(chan) (IOP3XX_PERIPHERAL_PHYS_BASE + \
+ (0x400 + (chan << 6)))
+#define IOP3XX_DMA_UPPER_PA(chan) (IOP3XX_DMA_PHYS_BASE(chan) + 0x27)
/* Peripheral bus interface */
#define IOP3XX_PBCR (volatile u32 *)IOP3XX_REG_ADDR(0x0680)
@@ -210,48 +195,8 @@ extern int init_atu;
#define IOP_TMR_RATIO_1_1 0x00
/* Application accelerator unit */
-#define IOP3XX_AAU_ACR (volatile u32 *)IOP3XX_REG_ADDR(0x0800)
-#define IOP3XX_AAU_ASR (volatile u32 *)IOP3XX_REG_ADDR(0x0804)
-#define IOP3XX_AAU_ADAR (volatile u32 *)IOP3XX_REG_ADDR(0x0808)
-#define IOP3XX_AAU_ANDAR (volatile u32 *)IOP3XX_REG_ADDR(0x080c)
-#define IOP3XX_AAU_SAR1 (volatile u32 *)IOP3XX_REG_ADDR(0x0810)
-#define IOP3XX_AAU_SAR2 (volatile u32 *)IOP3XX_REG_ADDR(0x0814)
-#define IOP3XX_AAU_SAR3 (volatile u32 *)IOP3XX_REG_ADDR(0x0818)
-#define IOP3XX_AAU_SAR4 (volatile u32 *)IOP3XX_REG_ADDR(0x081c)
-#define IOP3XX_AAU_DAR (volatile u32 *)IOP3XX_REG_ADDR(0x0820)
-#define IOP3XX_AAU_ABCR (volatile u32 *)IOP3XX_REG_ADDR(0x0824)
-#define IOP3XX_AAU_ADCR (volatile u32 *)IOP3XX_REG_ADDR(0x0828)
-#define IOP3XX_AAU_SAR5 (volatile u32 *)IOP3XX_REG_ADDR(0x082c)
-#define IOP3XX_AAU_SAR6 (volatile u32 *)IOP3XX_REG_ADDR(0x0830)
-#define IOP3XX_AAU_SAR7 (volatile u32 *)IOP3XX_REG_ADDR(0x0834)
-#define IOP3XX_AAU_SAR8 (volatile u32 *)IOP3XX_REG_ADDR(0x0838)
-#define IOP3XX_AAU_EDCR0 (volatile u32 *)IOP3XX_REG_ADDR(0x083c)
-#define IOP3XX_AAU_SAR9 (volatile u32 *)IOP3XX_REG_ADDR(0x0840)
-#define IOP3XX_AAU_SAR10 (volatile u32 *)IOP3XX_REG_ADDR(0x0844)
-#define IOP3XX_AAU_SAR11 (volatile u32 *)IOP3XX_REG_ADDR(0x0848)
-#define IOP3XX_AAU_SAR12 (volatile u32 *)IOP3XX_REG_ADDR(0x084c)
-#define IOP3XX_AAU_SAR13 (volatile u32 *)IOP3XX_REG_ADDR(0x0850)
-#define IOP3XX_AAU_SAR14 (volatile u32 *)IOP3XX_REG_ADDR(0x0854)
-#define IOP3XX_AAU_SAR15 (volatile u32 *)IOP3XX_REG_ADDR(0x0858)
-#define IOP3XX_AAU_SAR16 (volatile u32 *)IOP3XX_REG_ADDR(0x085c)
-#define IOP3XX_AAU_EDCR1 (volatile u32 *)IOP3XX_REG_ADDR(0x0860)
-#define IOP3XX_AAU_SAR17 (volatile u32 *)IOP3XX_REG_ADDR(0x0864)
-#define IOP3XX_AAU_SAR18 (volatile u32 *)IOP3XX_REG_ADDR(0x0868)
-#define IOP3XX_AAU_SAR19 (volatile u32 *)IOP3XX_REG_ADDR(0x086c)
-#define IOP3XX_AAU_SAR20 (volatile u32 *)IOP3XX_REG_ADDR(0x0870)
-#define IOP3XX_AAU_SAR21 (volatile u32 *)IOP3XX_REG_ADDR(0x0874)
-#define IOP3XX_AAU_SAR22 (volatile u32 *)IOP3XX_REG_ADDR(0x0878)
-#define IOP3XX_AAU_SAR23 (volatile u32 *)IOP3XX_REG_ADDR(0x087c)
-#define IOP3XX_AAU_SAR24 (volatile u32 *)IOP3XX_REG_ADDR(0x0880)
-#define IOP3XX_AAU_EDCR2 (volatile u32 *)IOP3XX_REG_ADDR(0x0884)
-#define IOP3XX_AAU_SAR25 (volatile u32 *)IOP3XX_REG_ADDR(0x0888)
-#define IOP3XX_AAU_SAR26 (volatile u32 *)IOP3XX_REG_ADDR(0x088c)
-#define IOP3XX_AAU_SAR27 (volatile u32 *)IOP3XX_REG_ADDR(0x0890)
-#define IOP3XX_AAU_SAR28 (volatile u32 *)IOP3XX_REG_ADDR(0x0894)
-#define IOP3XX_AAU_SAR29 (volatile u32 *)IOP3XX_REG_ADDR(0x0898)
-#define IOP3XX_AAU_SAR30 (volatile u32 *)IOP3XX_REG_ADDR(0x089c)
-#define IOP3XX_AAU_SAR31 (volatile u32 *)IOP3XX_REG_ADDR(0x08a0)
-#define IOP3XX_AAU_SAR32 (volatile u32 *)IOP3XX_REG_ADDR(0x08a4)
+#define IOP3XX_AAU_PHYS_BASE (IOP3XX_PERIPHERAL_PHYS_BASE + 0x800)
+#define IOP3XX_AAU_UPPER_PA (IOP3XX_AAU_PHYS_BASE + 0xa7)
/* I2C bus interface unit */
#define IOP3XX_ICR0 (volatile u32 *)IOP3XX_REG_ADDR(0x1680)
@@ -329,6 +274,9 @@ static inline void write_tisr(u32 val)
asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (val));
}
+extern struct platform_device iop3xx_dma_0_channel;
+extern struct platform_device iop3xx_dma_1_channel;
+extern struct platform_device iop3xx_aau_channel;
extern struct platform_device iop3xx_i2c0_device;
extern struct platform_device iop3xx_i2c1_device;
diff --git a/include/asm-arm/hardware/iop_adma.h b/include/asm-arm/hardware/iop_adma.h
new file mode 100644
index 00000000000..ca8e71f4434
--- /dev/null
+++ b/include/asm-arm/hardware/iop_adma.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * 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 IOP_ADMA_H
+#define IOP_ADMA_H
+#include <linux/types.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+
+#define IOP_ADMA_SLOT_SIZE 32
+#define IOP_ADMA_THRESHOLD 4
+
+/**
+ * struct iop_adma_device - internal representation of an ADMA device
+ * @pdev: Platform device
+ * @id: HW ADMA Device selector
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @dma_desc_pool_virt: base of DMA descriptor region (CPU address)
+ * @common: embedded struct dma_device
+ */
+struct iop_adma_device {
+ struct platform_device *pdev;
+ int id;
+ dma_addr_t dma_desc_pool;
+ void *dma_desc_pool_virt;
+ struct dma_device common;
+};
+
+/**
+ * struct iop_adma_chan - internal representation of an ADMA device
+ * @pending: allows batching of hardware operations
+ * @completed_cookie: identifier for the most recently completed operation
+ * @lock: serializes enqueue/dequeue operations to the slot pool
+ * @mmr_base: memory mapped register base
+ * @chain: device chain view of the descriptors
+ * @device: parent device
+ * @common: common dmaengine channel object members
+ * @last_used: place holder for allocation to continue from where it left off
+ * @all_slots: complete domain of slots usable by the channel
+ * @cleanup_watchdog: workaround missed interrupts on iop3xx
+ * @slots_allocated: records the actual size of the descriptor slot pool
+ * @irq_tasklet: bottom half where iop_adma_slot_cleanup runs
+ */
+struct iop_adma_chan {
+ int pending;
+ dma_cookie_t completed_cookie;
+ spinlock_t lock; /* protects the descriptor slot pool */
+ void __iomem *mmr_base;
+ struct list_head chain;
+ struct iop_adma_device *device;
+ struct dma_chan common;
+ struct iop_adma_desc_slot *last_used;
+ struct list_head all_slots;
+ struct timer_list cleanup_watchdog;
+ int slots_allocated;
+ struct tasklet_struct irq_tasklet;
+};
+
+/**
+ * struct iop_adma_desc_slot - IOP-ADMA software descriptor
+ * @slot_node: node on the iop_adma_chan.all_slots list
+ * @chain_node: node on the op_adma_chan.chain list
+ * @hw_desc: virtual address of the hardware descriptor chain
+ * @phys: hardware address of the hardware descriptor chain
+ * @group_head: first operation in a transaction
+ * @slot_cnt: total slots used in an transaction (group of operations)
+ * @slots_per_op: number of slots per operation
+ * @idx: pool index
+ * @unmap_src_cnt: number of xor sources
+ * @unmap_len: transaction bytecount
+ * @async_tx: support for the async_tx api
+ * @group_list: list of slots that make up a multi-descriptor transaction
+ * for example transfer lengths larger than the supported hw max
+ * @xor_check_result: result of zero sum
+ * @crc32_result: result crc calculation
+ */
+struct iop_adma_desc_slot {
+ struct list_head slot_node;
+ struct list_head chain_node;
+ void *hw_desc;
+ struct iop_adma_desc_slot *group_head;
+ u16 slot_cnt;
+ u16 slots_per_op;
+ u16 idx;
+ u16 unmap_src_cnt;
+ size_t unmap_len;
+ struct dma_async_tx_descriptor async_tx;
+ union {
+ u32 *xor_check_result;
+ u32 *crc32_result;
+ };
+};
+
+struct iop_adma_platform_data {
+ int hw_id;
+ dma_cap_mask_t cap_mask;
+ size_t pool_size;
+};
+
+#define to_iop_sw_desc(addr_hw_desc) \
+ container_of(addr_hw_desc, struct iop_adma_desc_slot, hw_desc)
+#define iop_hw_desc_slot_idx(hw_desc, idx) \
+ ( (void *) (((unsigned long) hw_desc) + ((idx) << 5)) )
+#endif
diff --git a/include/asm-arm/hwcap.h b/include/asm-arm/hwcap.h
new file mode 100644
index 00000000000..01a1391d301
--- /dev/null
+++ b/include/asm-arm/hwcap.h
@@ -0,0 +1,28 @@
+#ifndef __ASMARM_HWCAP_H
+#define __ASMARM_HWCAP_H
+
+/*
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
+ */
+#define HWCAP_SWP 1
+#define HWCAP_HALF 2
+#define HWCAP_THUMB 4
+#define HWCAP_26BIT 8 /* Play it safe */
+#define HWCAP_FAST_MULT 16
+#define HWCAP_FPA 32
+#define HWCAP_VFP 64
+#define HWCAP_EDSP 128
+#define HWCAP_JAVA 256
+#define HWCAP_IWMMXT 512
+#define HWCAP_CRUNCH 1024
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP (elf_hwcap)
+extern unsigned int elf_hwcap;
+#endif
+
+#endif
diff --git a/include/asm-arm/linkage.h b/include/asm-arm/linkage.h
index dbe4b4e31a5..5a25632b1bc 100644
--- a/include/asm-arm/linkage.h
+++ b/include/asm-arm/linkage.h
@@ -4,4 +4,8 @@
#define __ALIGN .align 0
#define __ALIGN_STR ".align 0"
+#define ENDPROC(name) \
+ .type name, %function; \
+ END(name)
+
#endif
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index f21abd4ddac..ed3f898191f 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -26,11 +26,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
#define PCI_DMA_BUS_IS_PHYS (0)
/*
- * We don't support DAC DMA cycles.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
-/*
* Whether pci_unmap_{single,page} is a nop depends upon the
* configuration.
*/
@@ -76,10 +71,6 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
return root;
}
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index 2d0dad8c10a..7aaa206cb54 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -10,6 +10,8 @@
#ifndef __ASM_ARM_PTRACE_H
#define __ASM_ARM_PTRACE_H
+#include <asm/hwcap.h>
+
#define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14
@@ -45,6 +47,7 @@
#define PSR_T_BIT 0x00000020
#define PSR_F_BIT 0x00000040
#define PSR_I_BIT 0x00000080
+#define PSR_A_BIT 0x00000100
#define PSR_J_BIT 0x01000000
#define PSR_Q_BIT 0x08000000
#define PSR_V_BIT 0x10000000
@@ -103,6 +106,10 @@ struct pt_regs {
#define thumb_mode(regs) (0)
#endif
+#define isa_mode(regs) \
+ ((((regs)->ARM_cpsr & PSR_J_BIT) >> 23) | \
+ (((regs)->ARM_cpsr & PSR_T_BIT) >> 5))
+
#define processor_mode(regs) \
((regs)->ARM_cpsr & MODE_MASK)
@@ -112,22 +119,22 @@ struct pt_regs {
#define fast_interrupts_enabled(regs) \
(!((regs)->ARM_cpsr & PSR_F_BIT))
-#define condition_codes(regs) \
- ((regs)->ARM_cpsr & (PSR_V_BIT|PSR_C_BIT|PSR_Z_BIT|PSR_N_BIT))
-
/* Are the current registers suitable for user mode?
* (used to maintain security in signal handlers)
*/
static inline int valid_user_regs(struct pt_regs *regs)
{
- if (user_mode(regs) &&
- (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0)
+ if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) {
+ regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
return 1;
+ }
/*
* Force CPSR to something logical...
*/
- regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT;
+ regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT;
+ if (!(elf_hwcap & HWCAP_26BIT))
+ regs->ARM_cpsr |= USR_MODE;
return 0;
}
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 250d7f145ac..bfdbebebdc1 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -367,6 +367,7 @@
#define __NR_get_robust_list (__NR_SYSCALL_BASE+339)
#define __NR_splice (__NR_SYSCALL_BASE+340)
#define __NR_arm_sync_file_range (__NR_SYSCALL_BASE+341)
+#define __NR_sync_file_range2 __NR_arm_sync_file_range
#define __NR_tee (__NR_SYSCALL_BASE+342)
#define __NR_vmsplice (__NR_SYSCALL_BASE+343)
#define __NR_move_pages (__NR_SYSCALL_BASE+344)
diff --git a/include/asm-arm26/termbits.h b/include/asm-arm26/termbits.h
index a3f4fe1742d..f66b5180473 100644
--- a/include/asm-arm26/termbits.h
+++ b/include/asm-arm26/termbits.h
@@ -15,7 +15,7 @@ struct termios {
cc_t c_cc[NCCS]; /* control characters */
};
-struct ktermios {
+struct termios2 {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
@@ -26,6 +26,16 @@ struct ktermios {
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
diff --git a/include/asm-avr32/arch-at32ap/gpio.h b/include/asm-avr32/arch-at32ap/gpio.h
index 80a21aa9ae7..af7f9535bab 100644
--- a/include/asm-avr32/arch-at32ap/gpio.h
+++ b/include/asm-avr32/arch-at32ap/gpio.h
@@ -14,6 +14,8 @@ int gpio_direction_output(unsigned int gpio, int value);
int gpio_get_value(unsigned int gpio);
void gpio_set_value(unsigned int gpio, int value);
+#include <asm-generic/gpio.h> /* cansleep wrappers */
+
static inline int gpio_to_irq(unsigned int gpio)
{
return gpio + GPIO_IRQ_BASE;
diff --git a/include/asm-avr32/cache.h b/include/asm-avr32/cache.h
index dabb955f3c0..d3cf35ab11a 100644
--- a/include/asm-avr32/cache.h
+++ b/include/asm-avr32/cache.h
@@ -4,6 +4,15 @@
#define L1_CACHE_SHIFT 5
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
+/*
+ * Memory returned by kmalloc() may be used for DMA, so we must make
+ * sure that all such allocations are cache aligned. Otherwise,
+ * unrelated code may cause parts of the buffer to be read into the
+ * cache before the transfer is done, causing old data to be seen by
+ * the CPU.
+ */
+#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES
+
#ifndef __ASSEMBLER__
struct cache_info {
unsigned int ways;
diff --git a/include/asm-avr32/termbits.h b/include/asm-avr32/termbits.h
index c215fafdae4..db2daab31fd 100644
--- a/include/asm-avr32/termbits.h
+++ b/include/asm-avr32/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-blackfin/Kbuild b/include/asm-blackfin/Kbuild
index c68e1680da0..71f8fe78325 100644
--- a/include/asm-blackfin/Kbuild
+++ b/include/asm-blackfin/Kbuild
@@ -1 +1,3 @@
include include/asm-generic/Kbuild.asm
+
+header-y += fixed_code.h
diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h
index 57f37ccdcdf..c4d6cbbf96d 100644
--- a/include/asm-blackfin/bfin-global.h
+++ b/include/asm-blackfin/bfin-global.h
@@ -67,6 +67,18 @@ extern void evt14_softirq(void);
extern asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs);
extern void bfin_gpio_interrupt_setup(int irq, int irq_pfx, int type);
+extern asmlinkage void finish_atomic_sections (struct pt_regs *regs);
+extern char fixed_code_start;
+extern char fixed_code_end;
+extern int atomic_xchg32(void);
+extern int atomic_cas32(void);
+extern int atomic_add32(void);
+extern int atomic_sub32(void);
+extern int atomic_ior32(void);
+extern int atomic_and32(void);
+extern int atomic_xor32(void);
+extern void sigreturn_stub(void);
+
extern void *l1_data_A_sram_alloc(size_t);
extern void *l1_data_B_sram_alloc(size_t);
extern void *l1_inst_sram_alloc(size_t);
diff --git a/include/asm-blackfin/blackfin.h b/include/asm-blackfin/blackfin.h
index 14e58de7397..25b934b7f82 100644
--- a/include/asm-blackfin/blackfin.h
+++ b/include/asm-blackfin/blackfin.h
@@ -6,7 +6,11 @@
#ifndef _BLACKFIN_H_
#define _BLACKFIN_H_
-#include <asm/macros.h>
+#define LO(con32) ((con32) & 0xFFFF)
+#define lo(con32) ((con32) & 0xFFFF)
+#define HI(con32) (((con32) >> 16) & 0xFFFF)
+#define hi(con32) (((con32) >> 16) & 0xFFFF)
+
#include <asm/mach/blackfin.h>
#include <asm/bfin-global.h>
@@ -35,7 +39,9 @@ static inline void SSYNC (void)
#elif !defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
static inline void SSYNC (void)
{
- __builtin_bfin_ssync();
+ __asm__ __volatile__ ("nop; nop; nop;\n\t"
+ "ssync;\n\t"
+ ::);
}
#elif !defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
static inline void SSYNC (void)
@@ -67,7 +73,9 @@ static inline void CSYNC (void)
#elif !defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
static inline void CSYNC (void)
{
- __builtin_bfin_csync();
+ __asm__ __volatile__ ("nop; nop; nop;\n\t"
+ "ssync;\n\t"
+ ::);
}
#elif !defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
static inline void CSYNC (void)
@@ -76,6 +84,31 @@ static inline void CSYNC (void)
}
#endif
+#else /* __ASSEMBLY__ */
+
+/* SSYNC & CSYNC implementations for assembly files */
+
+#define ssync(x) SSYNC(x)
+#define csync(x) CSYNC(x)
+
+#if defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
+#define SSYNC(scratch) cli scratch; nop; nop; SSYNC; sti scratch;
+#define CSYNC(scratch) cli scratch; nop; nop; CSYNC; sti scratch;
+
+#elif defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
+#define SSYNC(scratch) cli scratch; nop; nop; SSYNC; sti scratch;
+#define CSYNC(scratch) cli scratch; nop; nop; CSYNC; sti scratch;
+
+#elif !defined(ANOMALY_05000312) && defined(ANOMALY_05000244)
+#define SSYNC(scratch) nop; nop; nop; SSYNC;
+#define CSYNC(scratch) nop; nop; nop; CSYNC;
+
+#elif !defined(ANOMALY_05000312) && !defined(ANOMALY_05000244)
+#define SSYNC(scratch) SSYNC;
+#define CSYNC(scratch) CSYNC;
+
+#endif /* ANOMALY_05000312 & ANOMALY_05000244 handling */
+
#endif /* __ASSEMBLY__ */
#endif /* _BLACKFIN_H_ */
diff --git a/include/asm-blackfin/cplbinit.h b/include/asm-blackfin/cplbinit.h
index 3bad2d1e6a8..bec6ecdf1bd 100644
--- a/include/asm-blackfin/cplbinit.h
+++ b/include/asm-blackfin/cplbinit.h
@@ -57,8 +57,8 @@ struct cplb_tab {
u16 size;
};
-u_long icplb_table[MAX_CPLBS+1];
-u_long dcplb_table[MAX_CPLBS+1];
+extern u_long icplb_table[MAX_CPLBS+1];
+extern u_long dcplb_table[MAX_CPLBS+1];
/* Till here we are discussing about the static memory management model.
* However, the operating envoronments commonly define more CPLB
@@ -70,134 +70,27 @@ u_long dcplb_table[MAX_CPLBS+1];
*/
#ifdef CONFIG_CPLB_SWITCH_TAB_L1
-u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
-u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
+extern u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
+extern u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
#ifdef CONFIG_CPLB_INFO
-u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
-u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
+extern u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
+extern u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
#endif /* CONFIG_CPLB_INFO */
#else
-u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
-u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
+extern u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
+extern u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
#ifdef CONFIG_CPLB_INFO
-u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
-u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
+extern u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
+extern u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
#endif /* CONFIG_CPLB_INFO */
#endif /*CONFIG_CPLB_SWITCH_TAB_L1*/
-struct s_cplb {
- struct cplb_tab init_i;
- struct cplb_tab init_d;
- struct cplb_tab switch_i;
- struct cplb_tab switch_d;
-};
+extern unsigned long reserved_mem_dcache_on;
+extern unsigned long reserved_mem_icache_on;
-#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
-static struct cplb_desc cplb_data[] = {
- {
- .start = 0,
- .end = SIZE_4K,
- .psize = SIZE_4K,
- .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
- .i_conf = SDRAM_OOPS,
- .d_conf = SDRAM_OOPS,
-#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
- .valid = 1,
-#else
- .valid = 0,
-#endif
- .name = "ZERO Pointer Saveguard",
- },
- {
- .start = L1_CODE_START,
- .end = L1_CODE_START + L1_CODE_LENGTH,
- .psize = SIZE_4M,
- .attr = INITIAL_T | SWITCH_T | I_CPLB,
- .i_conf = L1_IMEMORY,
- .d_conf = 0,
- .valid = 1,
- .name = "L1 I-Memory",
- },
- {
- .start = L1_DATA_A_START,
- .end = L1_DATA_B_START + L1_DATA_B_LENGTH,
- .psize = SIZE_4M,
- .attr = INITIAL_T | SWITCH_T | D_CPLB,
- .i_conf = 0,
- .d_conf = L1_DMEMORY,
-#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
- .valid = 1,
-#else
- .valid = 0,
-#endif
- .name = "L1 D-Memory",
- },
- {
- .start = 0,
- .end = 0, /* dynamic */
- .psize = 0,
- .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
- .i_conf = SDRAM_IGENERIC,
- .d_conf = SDRAM_DGENERIC,
- .valid = 1,
- .name = "SDRAM Kernel",
- },
- {
- .start = 0, /* dynamic */
- .end = 0, /* dynamic */
- .psize = 0,
- .attr = INITIAL_T | SWITCH_T | D_CPLB,
- .i_conf = SDRAM_IGENERIC,
- .d_conf = SDRAM_DNON_CHBL,
- .valid = 1,
- .name = "SDRAM RAM MTD",
- },
- {
- .start = 0, /* dynamic */
- .end = 0, /* dynamic */
- .psize = SIZE_1M,
- .attr = INITIAL_T | SWITCH_T | D_CPLB,
- .d_conf = SDRAM_DNON_CHBL,
- .valid = 1,//(DMA_UNCACHED_REGION > 0),
- .name = "SDRAM Uncached DMA ZONE",
- },
- {
- .start = 0, /* dynamic */
- .end = 0, /* dynamic */
- .psize = 0,
- .attr = SWITCH_T | D_CPLB,
- .i_conf = 0, /* dynamic */
- .d_conf = 0, /* dynamic */
- .valid = 1,
- .name = "SDRAM Reserved Memory",
- },
- {
- .start = ASYNC_BANK0_BASE,
- .end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
- .psize = 0,
- .attr = SWITCH_T | D_CPLB,
- .d_conf = SDRAM_EBIU,
- .valid = 1,
- .name = "ASYNC Memory",
- },
- {
-#if defined(CONFIG_BF561)
- .start = L2_SRAM,
- .end = L2_SRAM_END,
- .psize = SIZE_1M,
- .attr = SWITCH_T | D_CPLB,
- .i_conf = L2_MEMORY,
- .d_conf = L2_MEMORY,
- .valid = 1,
-#else
- .valid = 0,
-#endif
- .name = "L2 Memory",
- }
-};
-#endif
+extern void generate_cpl_tables(void);
diff --git a/include/asm-blackfin/dma-mapping.h b/include/asm-blackfin/dma-mapping.h
index 7a77d7fe3a3..282fabccf6a 100644
--- a/include/asm-blackfin/dma-mapping.h
+++ b/include/asm-blackfin/dma-mapping.h
@@ -15,6 +15,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_mapping_error
+
/*
* Map a single buffer of the indicated size for DMA in streaming mode.
* The 32-bit bus address to use is returned.
diff --git a/include/asm-blackfin/fixed_code.h b/include/asm-blackfin/fixed_code.h
new file mode 100644
index 00000000000..e6df84ee155
--- /dev/null
+++ b/include/asm-blackfin/fixed_code.h
@@ -0,0 +1,20 @@
+/* This file defines the fixed addresses where userspace programs can find
+ atomic code sequences. */
+
+#define FIXED_CODE_START 0x400
+
+#define SIGRETURN_STUB 0x400
+
+#define ATOMIC_SEQS_START 0x410
+
+#define ATOMIC_XCHG32 0x410
+#define ATOMIC_CAS32 0x420
+#define ATOMIC_ADD32 0x430
+#define ATOMIC_SUB32 0x440
+#define ATOMIC_IOR32 0x450
+#define ATOMIC_AND32 0x460
+#define ATOMIC_XOR32 0x470
+
+#define ATOMIC_SEQS_END 0x480
+
+#define FIXED_CODE_END 0x480
diff --git a/include/asm-blackfin/gpio.h b/include/asm-blackfin/gpio.h
index aa0d5503e23..7480cfa7e2d 100644
--- a/include/asm-blackfin/gpio.h
+++ b/include/asm-blackfin/gpio.h
@@ -204,8 +204,62 @@
#endif
+#ifdef BF548_FAMILY
+#include <asm-blackfin/mach-bf548/gpio.h>
+#endif
+
#ifdef BF561_FAMILY
#define MAX_BLACKFIN_GPIOS 48
+
+#define GPIO_PF0 0
+#define GPIO_PF1 1
+#define GPIO_PF2 2
+#define GPIO_PF3 3
+#define GPIO_PF4 4
+#define GPIO_PF5 5
+#define GPIO_PF6 6
+#define GPIO_PF7 7
+#define GPIO_PF8 8
+#define GPIO_PF9 9
+#define GPIO_PF10 10
+#define GPIO_PF11 11
+#define GPIO_PF12 12
+#define GPIO_PF13 13
+#define GPIO_PF14 14
+#define GPIO_PF15 15
+#define GPIO_PF16 16
+#define GPIO_PF17 17
+#define GPIO_PF18 18
+#define GPIO_PF19 19
+#define GPIO_PF20 20
+#define GPIO_PF21 21
+#define GPIO_PF22 22
+#define GPIO_PF23 23
+#define GPIO_PF24 24
+#define GPIO_PF25 25
+#define GPIO_PF26 26
+#define GPIO_PF27 27
+#define GPIO_PF28 28
+#define GPIO_PF29 29
+#define GPIO_PF30 30
+#define GPIO_PF31 31
+#define GPIO_PF32 32
+#define GPIO_PF33 33
+#define GPIO_PF34 34
+#define GPIO_PF35 35
+#define GPIO_PF36 36
+#define GPIO_PF37 37
+#define GPIO_PF38 38
+#define GPIO_PF39 39
+#define GPIO_PF40 40
+#define GPIO_PF41 41
+#define GPIO_PF42 42
+#define GPIO_PF43 43
+#define GPIO_PF44 44
+#define GPIO_PF45 45
+#define GPIO_PF46 46
+#define GPIO_PF47 47
+
#define PORT_FIO0 GPIO_0
#define PORT_FIO1 GPIO_16
#define PORT_FIO2 GPIO_32
@@ -230,6 +284,7 @@
* MODIFICATION HISTORY :
**************************************************************/
+#ifndef BF548_FAMILY
void set_gpio_dir(unsigned short, unsigned short);
void set_gpio_inen(unsigned short, unsigned short);
void set_gpio_polar(unsigned short, unsigned short);
@@ -299,6 +354,7 @@ struct gpio_port_t {
unsigned short dummy16;
unsigned short inen;
};
+#endif
#ifdef CONFIG_PM
#define PM_WAKE_RISING 0x1
@@ -332,6 +388,7 @@ struct gpio_port_s {
unsigned short inen;
unsigned short fer;
+ unsigned short reserved;
};
#endif /*CONFIG_PM*/
@@ -356,8 +413,10 @@ void gpio_free(unsigned short);
void gpio_set_value(unsigned short gpio, unsigned short arg);
unsigned short gpio_get_value(unsigned short gpio);
+#ifndef BF548_FAMILY
#define gpio_get_value(gpio) get_gpio_data(gpio)
#define gpio_set_value(gpio, value) set_gpio_data(gpio, value)
+#endif
void gpio_direction_input(unsigned short gpio);
void gpio_direction_output(unsigned short gpio);
diff --git a/include/asm-blackfin/hardirq.h b/include/asm-blackfin/hardirq.h
index 0cab0d35bad..b6b19f1b9da 100644
--- a/include/asm-blackfin/hardirq.h
+++ b/include/asm-blackfin/hardirq.h
@@ -28,7 +28,11 @@ typedef struct {
* SOFTIRQ_MASK: 0x00ff0000
*/
+#if NR_IRQS > 256
+#define HARDIRQ_BITS 9
+#else
#define HARDIRQ_BITS 8
+#endif
#ifdef NR_IRQS
# if (1 << HARDIRQ_BITS) < NR_IRQS
diff --git a/include/asm-blackfin/io.h b/include/asm-blackfin/io.h
index eac8bcaf64c..142cb333db2 100644
--- a/include/asm-blackfin/io.h
+++ b/include/asm-blackfin/io.h
@@ -20,7 +20,7 @@
*/
#ifndef __ASSEMBLY__
-static inline unsigned char readb(void __iomem *addr)
+static inline unsigned char readb(const volatile void __iomem *addr)
{
unsigned int val;
int tmp;
@@ -35,7 +35,7 @@ static inline unsigned char readb(void __iomem *addr)
return (unsigned char) val;
}
-static inline unsigned short readw(void __iomem *addr)
+static inline unsigned short readw(const volatile void __iomem *addr)
{
unsigned int val;
int tmp;
@@ -50,7 +50,7 @@ static inline unsigned short readw(void __iomem *addr)
return (unsigned short) val;
}
-static inline unsigned int readl(void __iomem *addr)
+static inline unsigned int readl(const volatile void __iomem *addr)
{
unsigned int val;
int tmp;
diff --git a/include/asm-blackfin/kgdb.h b/include/asm-blackfin/kgdb.h
new file mode 100644
index 00000000000..532bd905200
--- /dev/null
+++ b/include/asm-blackfin/kgdb.h
@@ -0,0 +1,183 @@
+/*
+ * File: include/asm-blackfin/kgdb.h
+ * Based on:
+ * Author: Sonic Zhang
+ *
+ * Created:
+ * Description:
+ *
+ * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
+ *
+ * Modified:
+ * Copyright 2005-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __ASM_BLACKFIN_KGDB_H__
+#define __ASM_BLACKFIN_KGDB_H__
+
+#include <linux/ptrace.h>
+
+/* gdb locks */
+#define KGDB_MAX_NO_CPUS 8
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+/* Longer buffer is needed to list all threads */
+#define BUFMAX 2048
+
+/*
+ * Note that this register image is different from
+ * the register image that Linux produces at interrupt time.
+ *
+ * Linux's register image is defined by struct pt_regs in ptrace.h.
+ */
+enum regnames {
+ /* Core Registers */
+ BFIN_R0 = 0,
+ BFIN_R1,
+ BFIN_R2,
+ BFIN_R3,
+ BFIN_R4,
+ BFIN_R5,
+ BFIN_R6,
+ BFIN_R7,
+ BFIN_P0,
+ BFIN_P1,
+ BFIN_P2,
+ BFIN_P3,
+ BFIN_P4,
+ BFIN_P5,
+ BFIN_SP,
+ BFIN_FP,
+ BFIN_I0,
+ BFIN_I1,
+ BFIN_I2,
+ BFIN_I3,
+ BFIN_M0,
+ BFIN_M1,
+ BFIN_M2,
+ BFIN_M3,
+ BFIN_B0,
+ BFIN_B1,
+ BFIN_B2,
+ BFIN_B3,
+ BFIN_L0,
+ BFIN_L1,
+ BFIN_L2,
+ BFIN_L3,
+ BFIN_A0_DOT_X,
+ BFIN_A0_DOT_W,
+ BFIN_A1_DOT_X,
+ BFIN_A1_DOT_W,
+ BFIN_ASTAT,
+ BFIN_RETS,
+ BFIN_LC0,
+ BFIN_LT0,
+ BFIN_LB0,
+ BFIN_LC1,
+ BFIN_LT1,
+ BFIN_LB1,
+ BFIN_CYCLES,
+ BFIN_CYCLES2,
+ BFIN_USP,
+ BFIN_SEQSTAT,
+ BFIN_SYSCFG,
+ BFIN_RETI,
+ BFIN_RETX,
+ BFIN_RETN,
+ BFIN_RETE,
+
+ /* Pseudo Registers */
+ BFIN_PC,
+ BFIN_CC,
+ BFIN_EXTRA1, /* Address of .text section. */
+ BFIN_EXTRA2, /* Address of .data section. */
+ BFIN_EXTRA3, /* Address of .bss section. */
+ BFIN_FDPIC_EXEC,
+ BFIN_FDPIC_INTERP,
+
+ /* MMRs */
+ BFIN_IPEND,
+
+ /* LAST ENTRY SHOULD NOT BE CHANGED. */
+ BFIN_NUM_REGS /* The number of all registers. */
+};
+
+/* Number of bytes of registers. */
+#define NUMREGBYTES BFIN_NUM_REGS*4
+
+#define BREAKPOINT() asm(" EXCPT 2;");
+#define BREAK_INSTR_SIZE 2
+#define HW_BREAKPOINT_NUM 6
+
+/* Instruction watchpoint address control register bits mask */
+#define WPPWR 0x1
+#define WPIREN01 0x2
+#define WPIRINV01 0x4
+#define WPIAEN0 0x8
+#define WPIAEN1 0x10
+#define WPICNTEN0 0x20
+#define WPICNTEN1 0x40
+#define EMUSW0 0x80
+#define EMUSW1 0x100
+#define WPIREN23 0x200
+#define WPIRINV23 0x400
+#define WPIAEN2 0x800
+#define WPIAEN3 0x1000
+#define WPICNTEN2 0x2000
+#define WPICNTEN3 0x4000
+#define EMUSW2 0x8000
+#define EMUSW3 0x10000
+#define WPIREN45 0x20000
+#define WPIRINV45 0x40000
+#define WPIAEN4 0x80000
+#define WPIAEN5 0x100000
+#define WPICNTEN4 0x200000
+#define WPICNTEN5 0x400000
+#define EMUSW4 0x800000
+#define EMUSW5 0x1000000
+#define WPAND 0x2000000
+
+/* Data watchpoint address control register bits mask */
+#define WPDREN01 0x1
+#define WPDRINV01 0x2
+#define WPDAEN0 0x4
+#define WPDAEN1 0x8
+#define WPDCNTEN0 0x10
+#define WPDCNTEN1 0x20
+#define WPDSRC0 0xc0
+#define WPDACC0 0x300
+#define WPDSRC1 0xc00
+#define WPDACC1 0x3000
+
+/* Watchpoint status register bits mask */
+#define STATIA0 0x1
+#define STATIA1 0x2
+#define STATIA2 0x4
+#define STATIA3 0x8
+#define STATIA4 0x10
+#define STATIA5 0x20
+#define STATDA0 0x40
+#define STATDA1 0x80
+
+extern void kgdb_print(const char *fmt, ...);
+
+#endif
diff --git a/include/asm-blackfin/mach-bf533/anomaly.h b/include/asm-blackfin/mach-bf533/anomaly.h
index a84d3909345..7302f290b93 100644
--- a/include/asm-blackfin/mach-bf533/anomaly.h
+++ b/include/asm-blackfin/mach-bf533/anomaly.h
@@ -43,7 +43,8 @@
#endif
/* Issues that are common to 0.5, 0.4, and 0.3 silicon */
-#if (defined(CONFIG_BF_REV_0_5) || defined(CONFIG_BF_REV_0_4) || defined(CONFIG_BF_REV_0_3))
+#if (defined(CONFIG_BF_REV_0_5) || defined(CONFIG_BF_REV_0_4) \
+ || defined(CONFIG_BF_REV_0_3))
#define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in
slot1 and store of a P register in slot 2 is not
supported */
@@ -76,11 +77,16 @@
control */
#define ANOMALY_05000283 /* A system MMR write is stalled indefinitely when
killed in a particular stage*/
+#define ANOMALY_05000311 /* Erroneous flag pin operations under specific
+ sequences */
#define ANOMALY_05000312 /* Errors when SSYNC, CSYNC, or loads to LT, LB and LC
registers are interrupted */
-#define ANOMALY_05000311 /* Erroneous flag pin operations under specific sequences*/
-
-#endif
+#define ANOMALY_05000313 /* PPI Is Level-Sensitive on First Transfer */
+#define ANOMALY_05000315 /* Killed System MMR Write Completes Erroneously On
+ * Next System MMR Access */
+#define ANOMALY_05000319 /* Internal Voltage Regulator Values of 1.05V, 1.10V
+ * and 1.15V Not Allowed for LQFP Packages */
+#endif /* Issues that are common to 0.5, 0.4, and 0.3 silicon */
/* These issues only occur on 0.3 or 0.4 BF533 */
#if (defined(CONFIG_BF_REV_0_4) || defined(CONFIG_BF_REV_0_3))
@@ -134,14 +140,14 @@
internal voltage regulator (VDDint) to increase. */
#define ANOMALY_05000270 /* High I/O activity causes the output voltage of the
internal voltage regulator (VDDint) to decrease */
-#endif
+#endif /* issues only occur on 0.3 or 0.4 BF533 */
/* These issues are only on 0.4 silicon */
#if (defined(CONFIG_BF_REV_0_4))
#define ANOMALY_05000234 /* Incorrect Revision Number in DSPID Register */
#define ANOMALY_05000250 /* Incorrect Bit-Shift of Data Word in Multichannel
(TDM) */
-#endif
+#endif /* issues are only on 0.4 silicon */
/* These issues are only on 0.3 silicon */
#if defined(CONFIG_BF_REV_0_3)
@@ -170,6 +176,72 @@
#define ANOMALY_05000233 /* PPI_FS3 is not driven in 2 or 3 internal Frame
Sync Transmit Mode */
#define ANOMALY_05000271 /* Spontaneous reset of Internal Voltage Regulator */
+#endif /* only on 0.3 silicon */
+
+#if defined(CONFIG_BF_REV_0_2)
+#define ANOMALY_05000067 /* Watchpoints (Hardware Breakpoints) are not
+ * supported */
+#define ANOMALY_05000109 /* Reserved bits in SYSCFG register not set at
+ * power on */
+#define ANOMALY_05000116 /* Trace Buffers may record discontinuities into
+ * emulation mode and/or exception, NMI, reset
+ * handlers */
+#define ANOMALY_05000123 /* DTEST_COMMAND initiated memory access may be
+ * incorrect if data cache or DMA is active */
+#define ANOMALY_05000124 /* DMA Lock-up at CCLK to SCLK ratios of 4:1, 2:1,
+ * or 1:1 */
+#define ANOMALY_05000125 /* Erroneous exception when enabling cache */
+#define ANOMALY_05000126 /* SPI clock polarity and phase bits incorrect
+ * during booting */
+#define ANOMALY_05000137 /* DMEM_CONTROL is not set on Reset */
+#define ANOMALY_05000138 /* SPI boot will not complete if there is a zero fill
+ * block in the loader file */
+#define ANOMALY_05000140 /* Allowing the SPORT RX FIFO to fill will cause an
+ * overflow */
+#define ANOMALY_05000141 /* An Infinite Stall occurs with a particular sequence
+ * of consecutive dual dag events */
+#define ANOMALY_05000142 /* Interrupts may be lost when a programmable input
+ * flag is configured to be edge sensitive */
+#define ANOMALY_05000143 /* A read from external memory may return a wrong
+ * value with data cache enabled */
+#define ANOMALY_05000144 /* DMA and TESTSET conflict when both are accessing
+ * external memory */
+#define ANOMALY_05000145 /* In PWM_OUT mode, you must enable the PPI block to
+ * generate a waveform from PPI_CLK */
+#define ANOMALY_05000146 /* MDMA may lose the first few words of a descriptor
+ * chain */
+#define ANOMALY_05000147 /* The source MDMA descriptor may stop with a DMA
+ * Error */
+#define ANOMALY_05000148 /* When booting from a 16-bit asynchronous memory
+ * device, the upper 8-bits of each word must be
+ * 0x00 */
+#define ANOMALY_05000153 /* Frame Delay in SPORT Multichannel Mode */
+#define ANOMALY_05000154 /* SPORT TFS signal is active in Multi-channel mode
+ * outside of valid channels */
+#define ANOMALY_05000155 /* Timer1 can not be used for PWMOUT mode when a
+ * certain PPI mode is in use */
+#define ANOMALY_05000157 /* A killed 32-bit System MMR write will lead to
+ * the next system MMR access thinking it should be
+ * 32-bit. */
+#define ANOMALY_05000163 /* SPORT transmit data is not gated by external frame
+ * sync in certain conditions */
+#define ANOMALY_05000168 /* SDRAM auto-refresh and subsequent Power Ups */
+#define ANOMALY_05000169 /* DATA CPLB page miss can result in lost
+ * write-through cache data writes */
+#define ANOMALY_05000173 /* DMA vs Core accesses to external memory */
+#define ANOMALY_05000174 /* Cache Fill Buffer Data lost */
+#define ANOMALY_05000175 /* Overlapping Sequencer and Memory Stalls */
+#define ANOMALY_05000176 /* Multiplication of (-1) by (-1) followed by an
+ * accumulator saturation */
+#define ANOMALY_05000181 /* Disabling the PPI resets the PPI configuration
+ * registers */
+#define ANOMALY_05000185 /* PPI TX Mode with 2 External Frame Syncs */
+#define ANOMALY_05000191 /* PPI does not invert the Driving PPICLK edge in
+ * Transmit Modes */
+#define ANOMALY_05000192 /* In PPI Transmit Modes with External Frame Syncs
+ * POLC */
+#define ANOMALY_05000206 /* Internal Voltage Regulator may not start up */
+
#endif
#endif /* _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
index 23bf76aa345..e043cafa3c4 100644
--- a/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf533/bfin_serial_5xx.h
@@ -78,6 +78,7 @@ struct bfin_serial_res {
};
struct bfin_serial_res bfin_serial_resource[] = {
+ {
0xFFC00400,
IRQ_UART_RX,
#ifdef CONFIG_SERIAL_BFIN_DMA
@@ -88,6 +89,7 @@ struct bfin_serial_res bfin_serial_resource[] = {
CONFIG_UART0_CTS_PIN,
CONFIG_UART0_RTS_PIN,
#endif
+ }
};
diff --git a/include/asm-blackfin/mach-bf533/dma.h b/include/asm-blackfin/mach-bf533/dma.h
index bd9d5e94307..16c672c01d8 100644
--- a/include/asm-blackfin/mach-bf533/dma.h
+++ b/include/asm-blackfin/mach-bf533/dma.h
@@ -51,4 +51,7 @@
#define CH_MEM_STREAM1_DEST 10 /* TX */
#define CH_MEM_STREAM1_SRC 11 /* RX */
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
#endif
diff --git a/include/asm-blackfin/mach-bf533/portmux.h b/include/asm-blackfin/mach-bf533/portmux.h
new file mode 100644
index 00000000000..b88d7a03ee3
--- /dev/null
+++ b/include/asm-blackfin/mach-bf533/portmux.h
@@ -0,0 +1,65 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_PPI0_CLK (P_DONTCARE)
+#define P_PPI0_FS1 (P_DONTCARE)
+#define P_PPI0_FS2 (P_DONTCARE)
+#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF8))
+#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF9))
+#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF10))
+#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF11))
+#define P_PPI0_D0 (P_DONTCARE)
+#define P_PPI0_D1 (P_DONTCARE)
+#define P_PPI0_D2 (P_DONTCARE)
+#define P_PPI0_D3 (P_DONTCARE)
+#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PF15))
+#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PF14))
+#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PF13))
+#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PF12))
+
+#define P_SPORT1_TSCLK (P_DONTCARE)
+#define P_SPORT1_RSCLK (P_DONTCARE)
+#define P_SPORT0_TSCLK (P_DONTCARE)
+#define P_SPORT0_RSCLK (P_DONTCARE)
+#define P_UART0_RX (P_DONTCARE)
+#define P_UART0_TX (P_DONTCARE)
+#define P_SPORT1_DRSEC (P_DONTCARE)
+#define P_SPORT1_RFS (P_DONTCARE)
+#define P_SPORT1_DTPRI (P_DONTCARE)
+#define P_SPORT1_DTSEC (P_DONTCARE)
+#define P_SPORT1_TFS (P_DONTCARE)
+#define P_SPORT1_DRPRI (P_DONTCARE)
+#define P_SPORT0_DRSEC (P_DONTCARE)
+#define P_SPORT0_RFS (P_DONTCARE)
+#define P_SPORT0_DTPRI (P_DONTCARE)
+#define P_SPORT0_DTSEC (P_DONTCARE)
+#define P_SPORT0_TFS (P_DONTCARE)
+#define P_SPORT0_DRPRI (P_DONTCARE)
+
+#define P_SPI0_MOSI (P_DONTCARE)
+#define P_SPI0_MIS0 (P_DONTCARE)
+#define P_SPI0_SCK (P_DONTCARE)
+#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF0))
+
+#define P_TMR2 (P_DONTCARE)
+#define P_TMR1 (P_DONTCARE)
+#define P_TMR0 (P_DONTCARE)
+#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF1))
+
+
+
+
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf537/anomaly.h b/include/asm-blackfin/mach-bf537/anomaly.h
index 7f040f5ba01..4453e614c3b 100644
--- a/include/asm-blackfin/mach-bf537/anomaly.h
+++ b/include/asm-blackfin/mach-bf537/anomaly.h
@@ -73,8 +73,13 @@
control */
#define ANOMALY_05000283 /* A system MMR write is stalled indefinitely when
killed in a particular stage*/
+#define ANOMALY_05000310 /* False hardware errors caused by fetches at the
+ * boundary of reserved memory */
#define ANOMALY_05000312 /* Errors when SSYNC, CSYNC, or loads to LT, LB and LC
registers are interrupted */
+#define ANOMALY_05000313 /* PPI is level sensitive on first transfer */
+#define ANOMALY_05000322 /* EMAC RMII mode at 10-Base-T speed: RX frames not
+ * received properly */
#endif
#if defined(CONFIG_BF_REV_0_2)
@@ -114,7 +119,21 @@
DMA system instability */
#define ANOMALY_05000280 /* SPI Master boot mode does not work well with
Atmel Dataflash devices */
-
+#define ANOMALY_05000281 /* False Hardware Error Exception when ISR context
+ * is not restored */
+#define ANOMALY_05000282 /* Memory DMA corruption with 32-bit data and traffic
+ * control */
+#define ANOMALY_05000283 /* System MMR Write Is Stalled Indefinitely When
+ * Killed in a Particular Stage */
+#define ANOMALY_05000285 /* New Feature: EMAC TX DMA Word Alignment
+ * (Not Available On Older Silicon) */
+#define ANOMALY_05000288 /* SPORTs may receive bad data if FIFOs fill up */
+#define ANOMALY_05000315 /* Killed System MMR Write Completes Erroneously
+ * On Next System MMR Access */
+#define ANOMALY_05000316 /* EMAC RMII mode: collisions occur in Full Duplex
+ * mode */
+#define ANOMALY_05000321 /* EMAC RMII mode: TX frames in half duplex fail with
+ * status No Carrier */
#endif /* CONFIG_BF_REV_0_2 */
#endif /* _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf537/dma.h b/include/asm-blackfin/mach-bf537/dma.h
index 7a964040870..021991984e6 100644
--- a/include/asm-blackfin/mach-bf537/dma.h
+++ b/include/asm-blackfin/mach-bf537/dma.h
@@ -52,4 +52,7 @@
#define CH_MEM_STREAM1_DEST 14 /* TX */
#define CH_MEM_STREAM1_SRC 15 /* RX */
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
#endif
diff --git a/include/asm-blackfin/mach-bf537/portmux.h b/include/asm-blackfin/mach-bf537/portmux.h
new file mode 100644
index 00000000000..23e13c5abc4
--- /dev/null
+++ b/include/asm-blackfin/mach-bf537/portmux.h
@@ -0,0 +1,109 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0))
+#define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0))
+#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0))
+#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0))
+#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0))
+#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0))
+#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0))
+#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0))
+#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0))
+#define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0))
+#define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0))
+#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
+#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
+#define P_PPI0_CLK (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
+#define P_DMAR0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_DMAR1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_TACLK0 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
+#define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_PPI0_D2 (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0))
+#define P_PPI0_D3 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
+#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
+#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0))
+#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(1))
+#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(1))
+#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(1))
+#define P_SPORT1_RFS (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_SPORT1_DRPRI (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1))
+#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1))
+#define P_SPORT1_TFS (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1))
+#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1))
+
+#define P_MII0_ETxD0 (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0))
+#define P_MII0_ETxD1 (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0))
+#define P_MII0_ETxD2 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0))
+#define P_MII0_ETxD3 (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0))
+#define P_MII0_ETxEN (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0))
+#define P_MII0_TxCLK (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0))
+#define P_MII0_PHYINT (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0))
+#define P_MII0_COL (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0))
+#define P_MII0_ERxD0 (P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(0))
+#define P_MII0_ERxD1 (P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(0))
+#define P_MII0_ERxD2 (P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(0))
+#define P_MII0_ERxD3 (P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(0))
+#define P_MII0_ERxDV (P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(0))
+#define P_MII0_ERxCLK (P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(0))
+#define P_MII0_ERxER (P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(0))
+#define P_MII0_CRS (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(0))
+#define P_RMII0_REF_CLK (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(1))
+#define P_RMII0_MDINT (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1))
+#define P_RMII0_CRS_DV (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(1))
+
+#define PORT_PJ0 (GPIO_PH15 + 1)
+#define PORT_PJ1 (GPIO_PH15 + 2)
+#define PORT_PJ2 (GPIO_PH15 + 3)
+#define PORT_PJ3 (GPIO_PH15 + 4)
+#define PORT_PJ4 (GPIO_PH15 + 5)
+#define PORT_PJ5 (GPIO_PH15 + 6)
+#define PORT_PJ6 (GPIO_PH15 + 7)
+#define PORT_PJ7 (GPIO_PH15 + 8)
+#define PORT_PJ8 (GPIO_PH15 + 9)
+#define PORT_PJ9 (GPIO_PH15 + 10)
+#define PORT_PJ10 (GPIO_PH15 + 11)
+#define PORT_PJ11 (GPIO_PH15 + 12)
+
+#define P_MDC (P_DEFINED | P_IDENT(PORT_PJ0) | P_FUNCT(0))
+#define P_MDIO (P_DEFINED | P_IDENT(PORT_PJ1) | P_FUNCT(0))
+#define P_TWI0_SCL (P_DEFINED | P_IDENT(PORT_PJ2) | P_FUNCT(0))
+#define P_TWI0_SDA (P_DEFINED | P_IDENT(PORT_PJ3) | P_FUNCT(0))
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(PORT_PJ4) | P_FUNCT(0))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(0))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(PORT_PJ6) | P_FUNCT(0))
+#define P_SPORT0_RFS (P_DEFINED | P_IDENT(PORT_PJ7) | P_FUNCT(0))
+#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(PORT_PJ8) | P_FUNCT(0))
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(PORT_PJ9) | P_FUNCT(0))
+#define P_SPORT0_TFS (P_DEFINED | P_IDENT(PORT_PJ10) | P_FUNCT(0))
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1))
+#define P_CAN0_RX (P_DEFINED | P_IDENT(PORT_PJ4) | P_FUNCT(1))
+#define P_CAN0_TX (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(1))
+#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(PORT_PJ10) | P_FUNCT(1))
+#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(PORT_PJ11) | P_FUNCT(1))
+#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(PORT_PJ5) | P_FUNCT(2))
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf548/anomaly.h b/include/asm-blackfin/mach-bf548/anomaly.h
new file mode 100644
index 00000000000..aca1d4ba145
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/anomaly.h
@@ -0,0 +1,74 @@
+
+/*
+ * File: include/asm-blackfin/mach-bf548/anomaly.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_ANOMALY_H_
+#define _MACH_ANOMALY_H_
+#define ANOMALY_05000074 /* A multi issue instruction with dsp32shiftimm in
+ slot1 and store of a P register in slot 2 is not
+ supported */
+#define ANOMALY_05000119 /* DMA_RUN bit is not valid after a Peripheral Receive
+ Channel DMA stops */
+#define ANOMALY_05000122 /* Rx.H can not be used to access 16-bit System MMR
+ registers. */
+#define ANOMALY_05000245 /* Spurious Hardware Error from an Access in the
+ Shadow of a Conditional Branch */
+#define ANOMALY_05000255 /* Entering Hibernate Mode with RTC Seconds event
+ interrupt not functional */
+#define ANOMALY_05000265 /* Sensitivity to noise with slow input edge rates on
+ SPORT external receive and transmit clocks. */
+#define ANOMALY_05000272 /* Certain data cache write through modes fail for
+ VDDint <=0.9V */
+#define ANOMALY_05000281 /* False Hardware Error Exception when ISR context is
+ not restored */
+#define ANOMALY_05000310 /* False Hardware Errors Caused by Fetches at the
+ Boundary of Reserved Memory */
+#define ANOMALY_05000312 /* Errors When SSYNC, CSYNC, or Loads to LT, LB and
+ LC Registers Are Interrupted */
+#define ANOMALY_05000324 /* TWI Slave Boot Mode Is Not Functional */
+#define ANOMALY_05000325 /* External FIFO Boot Mode Is Not Functional */
+#define ANOMALY_05000327 /* Data Lost When Core and DMA Accesses Are Made to
+ the USB FIFO Simultaneously */
+#define ANOMALY_05000328 /* Incorrect Access of OTP_STATUS During otp_write()
+ function */
+#define ANOMALY_05000329 /* Synchronous Burst Flash Boot Mode Is Not Functional
+ */
+#define ANOMALY_05000330 /* Host DMA Boot Mode Is Not Functional */
+#define ANOMALY_05000334 /* Inadequate Timing Margins on DDR DQS to DQ and DQM
+ Skew */
+#define ANOMALY_05000335 /* Inadequate Rotary Debounce Logic Duration */
+#define ANOMALY_05000336 /* Phantom Interrupt Occurs After First Configuration
+ of Host DMA Port */
+#define ANOMALY_05000337 /* Disallowed Configuration Prevents Subsequent
+ Allowed Configuration on Host DMA Port */
+#define ANOMALY_05000338 /* Slave-Mode SPI0 MISO Failure With CPHA = 0 */
+
+#endif /* _MACH_ANOMALY_H_ */
diff --git a/include/asm-blackfin/mach-bf548/bf548.h b/include/asm-blackfin/mach-bf548/bf548.h
new file mode 100644
index 00000000000..9498313a2cb
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/bf548.h
@@ -0,0 +1,271 @@
+/*
+ * File: include/asm-blackfin/mach-bf548/bf548.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: System MMR register and memory map for ADSP-BF548
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __MACH_BF548_H__
+#define __MACH_BF548_H__
+
+#define SUPPORTED_REVID 0
+
+#define OFFSET_(x) ((x) & 0x0000FFFF)
+
+/*some misc defines*/
+#define IMASK_IVG15 0x8000
+#define IMASK_IVG14 0x4000
+#define IMASK_IVG13 0x2000
+#define IMASK_IVG12 0x1000
+
+#define IMASK_IVG11 0x0800
+#define IMASK_IVG10 0x0400
+#define IMASK_IVG9 0x0200
+#define IMASK_IVG8 0x0100
+
+#define IMASK_IVG7 0x0080
+#define IMASK_IVGTMR 0x0040
+#define IMASK_IVGHW 0x0020
+
+/***************************/
+
+
+#define BLKFIN_DSUBBANKS 4
+#define BLKFIN_DWAYS 2
+#define BLKFIN_DLINES 64
+#define BLKFIN_ISUBBANKS 4
+#define BLKFIN_IWAYS 4
+#define BLKFIN_ILINES 32
+
+#define WAY0_L 0x1
+#define WAY1_L 0x2
+#define WAY01_L 0x3
+#define WAY2_L 0x4
+#define WAY02_L 0x5
+#define WAY12_L 0x6
+#define WAY012_L 0x7
+
+#define WAY3_L 0x8
+#define WAY03_L 0x9
+#define WAY13_L 0xA
+#define WAY013_L 0xB
+
+#define WAY32_L 0xC
+#define WAY320_L 0xD
+#define WAY321_L 0xE
+#define WAYALL_L 0xF
+
+#define DMC_ENABLE (2<<2) /*yes, 2, not 1 */
+
+/********************************* EBIU Settings ************************************/
+#define AMBCTL0VAL ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0)
+#define AMBCTL1VAL ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2)
+
+#ifdef CONFIG_C_AMBEN_ALL
+#define V_AMBEN AMBEN_ALL
+#endif
+#ifdef CONFIG_C_AMBEN
+#define V_AMBEN 0x0
+#endif
+#ifdef CONFIG_C_AMBEN_B0
+#define V_AMBEN AMBEN_B0
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1
+#define V_AMBEN AMBEN_B0_B1
+#endif
+#ifdef CONFIG_C_AMBEN_B0_B1_B2
+#define V_AMBEN AMBEN_B0_B1_B2
+#endif
+#ifdef CONFIG_C_AMCKEN
+#define V_AMCKEN AMCKEN
+#else
+#define V_AMCKEN 0x0
+#endif
+
+#define AMGCTLVAL (V_AMBEN | V_AMCKEN)
+
+#define MAX_VC 650000000
+#define MIN_VC 50000000
+
+/********************************PLL Settings **************************************/
+#ifdef CONFIG_BFIN_KERNEL_CLOCK
+#if (CONFIG_VCO_MULT < 0)
+#error "VCO Multiplier is less than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT == 0)
+#error "VCO Multiplier should be greater than 0. Please select a different value"
+#endif
+
+#if (CONFIG_VCO_MULT > 64)
+#error "VCO Multiplier is more than 64. Please select a different value"
+#endif
+
+#ifndef CONFIG_CLKIN_HALF
+#define CONFIG_VCO_HZ (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)
+#else
+#define CONFIG_VCO_HZ ((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT)/2)
+#endif
+
+#ifndef CONFIG_PLL_BYPASS
+#define CONFIG_CCLK_HZ (CONFIG_VCO_HZ/CONFIG_CCLK_DIV)
+#define CONFIG_SCLK_HZ (CONFIG_VCO_HZ/CONFIG_SCLK_DIV)
+#else
+#define CONFIG_CCLK_HZ CONFIG_CLKIN_HZ
+#define CONFIG_SCLK_HZ CONFIG_CLKIN_HZ
+#endif
+
+#if (CONFIG_SCLK_DIV < 1)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_SCLK_DIV > 15)
+#error "SCLK DIV cannot be less than 1 or more than 15. Please select a proper value"
+#endif
+
+#if (CONFIG_CCLK_DIV != 1)
+#if (CONFIG_CCLK_DIV != 2)
+#if (CONFIG_CCLK_DIV != 4)
+#if (CONFIG_CCLK_DIV != 8)
+#error "CCLK DIV can be 1,2,4 or 8 only. Please select a proper value"
+#endif
+#endif
+#endif
+#endif
+
+#if (CONFIG_VCO_HZ > MAX_VC)
+#error "VCO selected is more than maximum value. Please change the VCO multipler"
+#endif
+
+#if (CONFIG_SCLK_HZ > 133000000)
+#error "Sclk value selected is more than maximum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ < 27000000)
+#error "Sclk value selected is less than minimum. Please select a proper value for SCLK multiplier"
+#endif
+
+#if (CONFIG_SCLK_HZ >= CONFIG_CCLK_HZ)
+#if (CONFIG_SCLK_HZ != CONFIG_CLKIN_HZ)
+#if (CONFIG_CCLK_HZ != CONFIG_CLKIN_HZ)
+#error "Please select sclk less than cclk"
+#endif
+#endif
+#endif
+
+#if (CONFIG_CCLK_DIV == 1)
+#define CONFIG_CCLK_ACT_DIV CCLK_DIV1
+#endif
+#if (CONFIG_CCLK_DIV == 2)
+#define CONFIG_CCLK_ACT_DIV CCLK_DIV2
+#endif
+#if (CONFIG_CCLK_DIV == 4)
+#define CONFIG_CCLK_ACT_DIV CCLK_DIV4
+#endif
+#if (CONFIG_CCLK_DIV == 8)
+#define CONFIG_CCLK_ACT_DIV CCLK_DIV8
+#endif
+#ifndef CONFIG_CCLK_ACT_DIV
+#define CONFIG_CCLK_ACT_DIV CONFIG_CCLK_DIV_not_defined_properly
+#endif
+
+#endif /* CONFIG_BFIN_KERNEL_CLOCK */
+
+#ifdef CONFIG_BF542
+#define CPU "BF542"
+#define CPUID 0x027c8000
+#endif
+#ifdef CONFIG_BF544
+#define CPU "BF544"
+#define CPUID 0x027c8000
+#endif
+#ifdef CONFIG_BF548
+#define CPU "BF548"
+#define CPUID 0x027c6000
+#endif
+#ifdef CONFIG_BF549
+#define CPU "BF549"
+#endif
+#ifndef CPU
+#define CPU "UNKNOWN"
+#define CPUID 0x0
+#endif
+
+#if (CONFIG_MEM_SIZE % 4)
+#error "SDRAM mem size must be multible of 4MB"
+#endif
+
+#define SDRAM_IGENERIC (CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_PORTPRIO)
+#define SDRAM_IKERNEL (SDRAM_IGENERIC | CPLB_LOCK)
+#define L1_IMEMORY ( CPLB_USER_RD | CPLB_VALID | CPLB_LOCK)
+#define SDRAM_INON_CHBL ( CPLB_USER_RD | CPLB_VALID)
+
+/*Use the menuconfig cache policy here - CONFIG_BLKFIN_WT/CONFIG_BLKFIN_WB*/
+
+#define ANOMALY_05000158_WORKAROUND 0x200
+#ifdef CONFIG_BLKFIN_WB /*Write Back Policy */
+#define SDRAM_DGENERIC (CPLB_L1_CHBL | CPLB_DIRTY \
+ | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND)
+#else /*Write Through */
+#define SDRAM_DGENERIC (CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW \
+ | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#endif
+
+
+#define L1_DMEMORY (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY )
+#define SDRAM_DNON_CHBL (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#define SDRAM_EBIU (CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_DIRTY )
+#define SDRAM_OOPS (CPLB_VALID | ANOMALY_05000158_WORKAROUND | CPLB_LOCK | CPLB_DIRTY )
+
+#define SIZE_1K 0x00000400 /* 1K */
+#define SIZE_4K 0x00001000 /* 4K */
+#define SIZE_1M 0x00100000 /* 1M */
+#define SIZE_4M 0x00400000 /* 4M */
+
+#define MAX_CPLBS (16 * 2)
+
+/*
+* Number of required data CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 16 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Data Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+* 1 for ASYNC Memory
+*/
+
+
+#define MAX_SWITCH_D_CPLBS (((CONFIG_MEM_SIZE / 4) + 16 + 1 + 1 + 1) * 2)
+
+/*
+* Number of required instruction CPLB switchtable entries
+* MEMSIZE / 4 (we mostly install 4M page size CPLBs
+* approx 12 for smaller 1MB page size CPLBs for allignment purposes
+* 1 for L1 Instruction Memory
+* 1 for CONFIG_DEBUG_HUNT_FOR_ZERO
+*/
+
+#define MAX_SWITCH_I_CPLBS (((CONFIG_MEM_SIZE / 4) + 12 + 1 + 1) * 2)
+
+#endif /* __MACH_BF48_H__ */
diff --git a/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
new file mode 100644
index 00000000000..2f4afc90db1
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/bfin_serial_5xx.h
@@ -0,0 +1,193 @@
+#include <linux/serial.h>
+#include <asm/dma.h>
+
+#define NR_PORTS 4
+
+#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */
+#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */
+#define OFFSET_GCTL 0x08 /* Global Control Register */
+#define OFFSET_LCR 0x0C /* Line Control Register */
+#define OFFSET_MCR 0x10 /* Modem Control Register */
+#define OFFSET_LSR 0x14 /* Line Status Register */
+#define OFFSET_MSR 0x18 /* Modem Status Register */
+#define OFFSET_SCR 0x1C /* SCR Scratch Register */
+#define OFFSET_IER_SET 0x20 /* Set Interrupt Enable Register */
+#define OFFSET_IER_CLEAR 0x24 /* Clear Interrupt Enable Register */
+#define OFFSET_THR 0x28 /* Transmit Holding register */
+#define OFFSET_RBR 0x2C /* Receive Buffer register */
+
+#define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR))
+#define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL))
+#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH))
+#define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER_SET))
+#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR))
+#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR))
+#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL))
+
+#define UART_PUT_CHAR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_THR),v)
+#define UART_PUT_DLL(uart,v) bfin_write16(((uart)->port.membase + OFFSET_DLL),v)
+#define UART_SET_IER(uart,v) bfin_write16(((uart)->port.membase + OFFSET_IER_SET),v)
+#define UART_CLEAR_IER(uart,v) bfin_write16(((uart)->port.membase + OFFSET_IER_CLEAR),v)
+#define UART_PUT_DLH(uart,v) bfin_write16(((uart)->port.membase + OFFSET_DLH),v)
+#define UART_PUT_LSR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_LSR),v)
+#define UART_PUT_LCR(uart,v) bfin_write16(((uart)->port.membase + OFFSET_LCR),v)
+#define UART_PUT_GCTL(uart,v) bfin_write16(((uart)->port.membase + OFFSET_GCTL),v)
+
+#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS)
+# define CONFIG_SERIAL_BFIN_CTSRTS
+
+# ifndef CONFIG_UART0_CTS_PIN
+# define CONFIG_UART0_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART0_RTS_PIN
+# define CONFIG_UART0_RTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_CTS_PIN
+# define CONFIG_UART1_CTS_PIN -1
+# endif
+
+# ifndef CONFIG_UART1_RTS_PIN
+# define CONFIG_UART1_RTS_PIN -1
+# endif
+#endif
+/*
+ * The pin configuration is different from schematic
+ */
+struct bfin_serial_port {
+ struct uart_port port;
+ unsigned int old_status;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ int tx_done;
+ int tx_count;
+ struct circ_buf rx_dma_buf;
+ struct timer_list rx_dma_timer;
+ int rx_dma_nrows;
+ unsigned int tx_dma_channel;
+ unsigned int rx_dma_channel;
+ struct work_struct tx_dma_workqueue;
+#else
+ struct work_struct cts_workqueue;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ int cts_pin;
+ int rts_pin;
+#endif
+};
+
+struct bfin_serial_port bfin_serial_ports[NR_PORTS];
+struct bfin_serial_res {
+ unsigned long uart_base_addr;
+ int uart_irq;
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ unsigned int uart_tx_dma_channel;
+ unsigned int uart_rx_dma_channel;
+#endif
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ int uart_cts_pin;
+ int uart_rts_pin;
+#endif
+};
+
+struct bfin_serial_res bfin_serial_resource[] = {
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ {
+ 0xFFC00400,
+ IRQ_UART0_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART0_TX,
+ CH_UART0_RX,
+#endif
+#ifdef CONFIG_BFIN_UART0_CTSRTS
+ CONFIG_UART0_CTS_PIN,
+ CONFIG_UART0_RTS_PIN,
+#endif
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ {
+ 0xFFC02000,
+ IRQ_UART1_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART1_TX,
+ CH_UART1_RX,
+#endif
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART2
+ {
+ 0xFFC02100,
+ IRQ_UART2_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART2_TX,
+ CH_UART2_RX,
+#endif
+#ifdef CONFIG_BFIN_UART2_CTSRTS
+ CONFIG_UART2_CTS_PIN,
+ CONFIG_UART2_RTS_PIN,
+#endif
+ },
+#endif
+#ifdef CONFIG_SERIAL_BFIN_UART3
+ {
+ 0xFFC03100,
+ IRQ_UART3_RX,
+#ifdef CONFIG_SERIAL_BFIN_DMA
+ CH_UART3_TX,
+ CH_UART3_RX,
+#endif
+ },
+#endif
+};
+
+int nr_ports = ARRAY_SIZE(bfin_serial_resource);
+
+static void bfin_serial_hw_init(struct bfin_serial_port *uart)
+{
+#ifdef CONFIG_SERIAL_BFIN_UART0
+ /* Enable UART0 RX and TX on pin 7 & 8 of PORT E */
+ bfin_write_PORTE_FER(0x180 | bfin_read_PORTE_FER());
+ bfin_write_PORTE_MUX(0x3C000 | bfin_read_PORTE_MUX());
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART1
+ /* Enable UART1 RX and TX on pin 0 & 1 of PORT H */
+ bfin_write_PORTH_FER(0x3 | bfin_read_PORTH_FER());
+ bfin_write_PORTH_MUX(~0xF & bfin_read_PORTH_MUX());
+#ifdef CONFIG_BFIN_UART1_CTSRTS
+ /* Enable UART1 RTS and CTS on pin 9 & 10 of PORT E */
+ bfin_write_PORTE_FER(0x600 | bfin_read_PORTE_FER());
+ bfin_write_PORTE_MUX(~0x3C0000 & bfin_read_PORTE_MUX());
+#endif
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART2
+ /* Enable UART2 RX and TX on pin 4 & 5 of PORT B */
+ bfin_write_PORTB_FER(0x30 | bfin_read_PORTB_FER());
+ bfin_write_PORTB_MUX(~0xF00 & bfin_read_PORTB_MUX());
+#endif
+
+#ifdef CONFIG_SERIAL_BFIN_UART3
+ /* Enable UART3 RX and TX on pin 6 & 7 of PORT B */
+ bfin_write_PORTB_FER(0xC0 | bfin_read_PORTB_FER());
+ bfin_write_PORTB_MUX(~0xF000 | bfin_read_PORTB_MUX());
+#ifdef CONFIG_BFIN_UART3_CTSRTS
+ /* Enable UART3 RTS and CTS on pin 2 & 3 of PORT B */
+ bfin_write_PORTB_FER(0xC | bfin_read_PORTB_FER());
+ bfin_write_PORTB_MUX(~0xF0 | bfin_read_PORTB_MUX());
+#endif
+#endif
+ SSYNC();
+#ifdef CONFIG_SERIAL_BFIN_CTSRTS
+ if (uart->cts_pin >= 0) {
+ gpio_request(uart->cts_pin, NULL);
+ gpio_direction_input(uart->cts_pin);
+ }
+
+ if (uart->rts_pin >= 0) {
+ gpio_request(uart->rts_pin, NULL);
+ gpio_direction_output(uart->rts_pin);
+ }
+#endif
+}
diff --git a/include/asm-blackfin/mach-bf548/blackfin.h b/include/asm-blackfin/mach-bf548/blackfin.h
new file mode 100644
index 00000000000..791218fe7d9
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/blackfin.h
@@ -0,0 +1,168 @@
+/*
+ * File: include/asm-blackfin/mach-bf548/blackfin.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ *
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _MACH_BLACKFIN_H_
+#define _MACH_BLACKFIN_H_
+
+#define BF548_FAMILY
+
+#include "bf548.h"
+#include "mem_map.h"
+#include "anomaly.h"
+
+#ifdef CONFIG_BF542
+#include "defBF542.h"
+#endif
+
+#ifdef CONFIG_BF544
+#include "defBF544.h"
+#endif
+
+#ifdef CONFIG_BF548
+#include "defBF548.h"
+#endif
+
+#ifdef CONFIG_BF549
+#include "defBF549.h"
+#endif
+
+#if !(defined(__ASSEMBLY__) || defined(ASSEMBLY))
+#ifdef CONFIG_BF542
+#include "cdefBF542.h"
+#endif
+
+#ifdef CONFIG_BF544
+#include "cdefBF544.h"
+#endif
+#ifdef CONFIG_BF548
+#include "cdefBF548.h"
+#endif
+#ifdef CONFIG_BF549
+#include "cdefBF549.h"
+#endif
+
+/* UART 1*/
+#define bfin_read_UART_THR() bfin_read_UART1_THR()
+#define bfin_write_UART_THR(val) bfin_write_UART1_THR(val)
+#define bfin_read_UART_RBR() bfin_read_UART1_RBR()
+#define bfin_write_UART_RBR(val) bfin_write_UART1_RBR(val)
+#define bfin_read_UART_DLL() bfin_read_UART1_DLL()
+#define bfin_write_UART_DLL(val) bfin_write_UART1_DLL(val)
+#define bfin_read_UART_IER() bfin_read_UART1_IER()
+#define bfin_write_UART_IER(val) bfin_write_UART1_IER(val)
+#define bfin_read_UART_DLH() bfin_read_UART1_DLH()
+#define bfin_write_UART_DLH(val) bfin_write_UART1_DLH(val)
+#define bfin_read_UART_IIR() bfin_read_UART1_IIR()
+#define bfin_write_UART_IIR(val) bfin_write_UART1_IIR(val)
+#define bfin_read_UART_LCR() bfin_read_UART1_LCR()
+#define bfin_write_UART_LCR(val) bfin_write_UART1_LCR(val)
+#define bfin_read_UART_MCR() bfin_read_UART1_MCR()
+#define bfin_write_UART_MCR(val) bfin_write_UART1_MCR(val)
+#define bfin_read_UART_LSR() bfin_read_UART1_LSR()
+#define bfin_write_UART_LSR(val) bfin_write_UART1_LSR(val)
+#define bfin_read_UART_SCR() bfin_read_UART1_SCR()
+#define bfin_write_UART_SCR(val) bfin_write_UART1_SCR(val)
+#define bfin_read_UART_GCTL() bfin_read_UART1_GCTL()
+#define bfin_write_UART_GCTL(val) bfin_write_UART1_GCTL(val)
+
+#endif
+
+/* MAP used DEFINES from BF533 to BF54x - so we don't need to change
+ * them in the driver, kernel, etc. */
+
+/* UART_IIR Register */
+#define STATUS(x) ((x << 1) & 0x06)
+#define STATUS_P1 0x02
+#define STATUS_P0 0x01
+
+/* UART 0*/
+
+/* DMA Channnel */
+#define bfin_read_CH_UART_RX() bfin_read_CH_UART1_RX()
+#define bfin_write_CH_UART_RX(val) bfin_write_CH_UART1_RX(val)
+#define bfin_read_CH_UART_TX() bfin_read_CH_UART1_TX()
+#define bfin_write_CH_UART_TX(val) bfin_write_CH_UART1_TX(val)
+#define CH_UART_RX CH_UART1_RX
+#define CH_UART_TX CH_UART1_TX
+
+/* System Interrupt Controller */
+#define bfin_read_IRQ_UART_RX() bfin_read_IRQ_UART1_RX()
+#define bfin_write_IRQ_UART_RX(val) bfin_write_IRQ_UART1_RX(val)
+#define bfin_read_IRQ_UART_TX() bfin_read_IRQ_UART1_TX()
+#define bfin_write_IRQ_UART_TX(val) bfin_write_IRQ_UART1_TX(val)
+#define bfin_read_IRQ_UART_ERROR() bfin_read_IRQ_UART1_ERROR()
+#define bfin_write_IRQ_UART_ERROR(val) bfin_write_IRQ_UART1_ERROR(val)
+#define IRQ_UART_RX IRQ_UART1_RX
+#define IRQ_UART_TX IRQ_UART1_TX
+#define IRQ_UART_ERROR IRQ_UART1_ERROR
+
+/* MMR Registers*/
+#define bfin_read_UART_THR() bfin_read_UART1_THR()
+#define bfin_write_UART_THR(val) bfin_write_UART1_THR(val)
+#define bfin_read_UART_RBR() bfin_read_UART1_RBR()
+#define bfin_write_UART_RBR(val) bfin_write_UART1_RBR(val)
+#define bfin_read_UART_DLL() bfin_read_UART1_DLL()
+#define bfin_write_UART_DLL(val) bfin_write_UART1_DLL(val)
+#define bfin_read_UART_IER() bfin_read_UART1_IER()
+#define bfin_write_UART_IER(val) bfin_write_UART1_IER(val)
+#define bfin_read_UART_DLH() bfin_read_UART1_DLH()
+#define bfin_write_UART_DLH(val) bfin_write_UART1_DLH(val)
+#define bfin_read_UART_IIR() bfin_read_UART1_IIR()
+#define bfin_write_UART_IIR(val) bfin_write_UART1_IIR(val)
+#define bfin_read_UART_LCR() bfin_read_UART1_LCR()
+#define bfin_write_UART_LCR(val) bfin_write_UART1_LCR(val)
+#define bfin_read_UART_MCR() bfin_read_UART1_MCR()
+#define bfin_write_UART_MCR(val) bfin_write_UART1_MCR(val)
+#define bfin_read_UART_LSR() bfin_read_UART1_LSR()
+#define bfin_write_UART_LSR(val) bfin_write_UART1_LSR(val)
+#define bfin_read_UART_SCR() bfin_read_UART1_SCR()
+#define bfin_write_UART_SCR(val) bfin_write_UART1_SCR(val)
+#define bfin_read_UART_GCTL() bfin_read_UART1_GCTL()
+#define bfin_write_UART_GCTL(val) bfin_write_UART1_GCTL(val)
+#define UART_THR UART1_THR
+#define UART_RBR UART1_RBR
+#define UART_DLL UART1_DLL
+#define UART_IER UART1_IER
+#define UART_DLH UART1_DLH
+#define UART_IIR UART1_IIR
+#define UART_LCR UART1_LCR
+#define UART_MCR UART1_MCR
+#define UART_LSR UART1_LSR
+#define UART_SCR UART1_SCR
+#define UART_GCTL UART1_GCTL
+
+/* PLL_DIV Masks */
+#define CCLK_DIV1 CSEL_DIV1 /* CCLK = VCO / 1 */
+#define CCLK_DIV2 CSEL_DIV2 /* CCLK = VCO / 2 */
+#define CCLK_DIV4 CSEL_DIV4 /* CCLK = VCO / 4 */
+#define CCLK_DIV8 CSEL_DIV8 /* CCLK = VCO / 8 */
+
+#endif
diff --git a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
index 6bbcefeb362..98d35a92911 100644
--- a/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
+++ b/include/asm-blackfin/mach-bf548/cdefBF54x_base.h
@@ -31,7 +31,8 @@
#ifndef _CDEF_BF54X_H
#define _CDEF_BF54X_H
-#include <defBF54x_base.h>
+#include "defBF54x_base.h"
+#include <asm/system.h>
/* ************************************************************** */
/* SYSTEM & MMR ADDRESS DEFINITIONS COMMON TO ALL ADSP-BF54x */
@@ -44,7 +45,30 @@
#define bfin_read_PLL_DIV() bfin_read16(PLL_DIV)
#define bfin_write_PLL_DIV(val) bfin_write16(PLL_DIV, val)
#define bfin_read_VR_CTL() bfin_read16(VR_CTL)
-#define bfin_write_VR_CTL(val) bfin_write16(VR_CTL, val)
+/* Writing to VR_CTL initiates a PLL relock sequence. */
+static __inline__ void bfin_write_VR_CTL(unsigned int val)
+{
+ unsigned long flags, iwr0, iwr1, iwr2;
+
+ /* Enable the PLL Wakeup bit in SIC IWR */
+ iwr0 = bfin_read32(SIC_IWR0);
+ iwr1 = bfin_read32(SIC_IWR1);
+ iwr2 = bfin_read32(SIC_IWR2);
+ /* Only allow PPL Wakeup) */
+ bfin_write32(SIC_IWR0, IWR_ENABLE(0));
+ bfin_write32(SIC_IWR1, 0);
+ bfin_write32(SIC_IWR2, 0);
+
+ bfin_write16(VR_CTL, val);
+ __builtin_bfin_ssync();
+
+ local_irq_save(flags);
+ asm("IDLE;");
+ local_irq_restore(flags);
+ bfin_write32(SIC_IWR0, iwr0);
+ bfin_write32(SIC_IWR1, iwr1);
+ bfin_write32(SIC_IWR2, iwr2);
+}
#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val)
#define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT)
@@ -70,12 +94,18 @@
#define bfin_write_SIC_IMASK1(val) bfin_write32(SIC_IMASK1, val)
#define bfin_read_SIC_IMASK2() bfin_read32(SIC_IMASK2)
#define bfin_write_SIC_IMASK2(val) bfin_write32(SIC_IMASK2, val)
+#define bfin_read_SIC_IMASK(x) bfin_read32(SIC_IMASK0 + (x << 2))
+#define bfin_write_SIC_IMASK(x, val) bfin_write32((SIC_IMASK0 + (x << 2)), val)
+
#define bfin_read_SIC_ISR0() bfin_read32(SIC_ISR0)
#define bfin_write_SIC_ISR0(val) bfin_write32(SIC_ISR0, val)
#define bfin_read_SIC_ISR1() bfin_read32(SIC_ISR1)
#define bfin_write_SIC_ISR1(val) bfin_write32(SIC_ISR1, val)
#define bfin_read_SIC_ISR2() bfin_read32(SIC_ISR2)
#define bfin_write_SIC_ISR2(val) bfin_write32(SIC_ISR2, val)
+#define bfin_read_SIC_ISR(x) bfin_read32(SIC_ISR0 + (x << 2))
+#define bfin_write_SIC_ISR(x, val) bfin_write32((SIC_ISR0 + (x << 2)), val)
+
#define bfin_read_SIC_IWR0() bfin_read32(SIC_IWR0)
#define bfin_write_SIC_IWR0(val) bfin_write32(SIC_IWR0, val)
#define bfin_read_SIC_IWR1() bfin_read32(SIC_IWR1)
@@ -710,21 +740,21 @@
#define bfin_read_MDMA_D0_NEXT_DESC_PTR() bfin_read32(MDMA_D0_NEXT_DESC_PTR)
#define bfin_write_MDMA_D0_NEXT_DESC_PTR(val) bfin_write32(MDMA_D0_NEXT_DESC_PTR)
#define bfin_read_MDMA_D0_START_ADDR() bfin_read32(MDMA_D0_START_ADDR)
-#define bfin_write_MDMA_D0_START_ADDR(val) bfin_write32(MDMA_D0_START_ADDR)
+#define bfin_write_MDMA_D0_START_ADDR(val) bfin_write32(MDMA_D0_START_ADDR, val)
#define bfin_read_MDMA_D0_CONFIG() bfin_read16(MDMA_D0_CONFIG)
#define bfin_write_MDMA_D0_CONFIG(val) bfin_write16(MDMA_D0_CONFIG, val)
#define bfin_read_MDMA_D0_X_COUNT() bfin_read16(MDMA_D0_X_COUNT)
#define bfin_write_MDMA_D0_X_COUNT(val) bfin_write16(MDMA_D0_X_COUNT, val)
#define bfin_read_MDMA_D0_X_MODIFY() bfin_read16(MDMA_D0_X_MODIFY)
-#define bfin_write_MDMA_D0_X_MODIFY(val) bfin_write16(MDMA_D0_X_MODIFY)
+#define bfin_write_MDMA_D0_X_MODIFY(val) bfin_write16(MDMA_D0_X_MODIFY, val)
#define bfin_read_MDMA_D0_Y_COUNT() bfin_read16(MDMA_D0_Y_COUNT)
#define bfin_write_MDMA_D0_Y_COUNT(val) bfin_write16(MDMA_D0_Y_COUNT, val)
#define bfin_read_MDMA_D0_Y_MODIFY() bfin_read16(MDMA_D0_Y_MODIFY)
-#define bfin_write_MDMA_D0_Y_MODIFY(val) bfin_write16(MDMA_D0_Y_MODIFY)
+#define bfin_write_MDMA_D0_Y_MODIFY(val) bfin_write16(MDMA_D0_Y_MODIFY, val)
#define bfin_read_MDMA_D0_CURR_DESC_PTR() bfin_read32(MDMA_D0_CURR_DESC_PTR)
-#define bfin_write_MDMA_D0_CURR_DESC_PTR(val) bfin_write32(MDMA_D0_CURR_DESC_PTR)
+#define bfin_write_MDMA_D0_CURR_DESC_PTR(val) bfin_write32(MDMA_D0_CURR_DESC_PTR, val)
#define bfin_read_MDMA_D0_CURR_ADDR() bfin_read32(MDMA_D0_CURR_ADDR)
-#define bfin_write_MDMA_D0_CURR_ADDR(val) bfin_write32(MDMA_D0_CURR_ADDR)
+#define bfin_write_MDMA_D0_CURR_ADDR(val) bfin_write32(MDMA_D0_CURR_ADDR, val)
#define bfin_read_MDMA_D0_IRQ_STATUS() bfin_read16(MDMA_D0_IRQ_STATUS)
#define bfin_write_MDMA_D0_IRQ_STATUS(val) bfin_write16(MDMA_D0_IRQ_STATUS, val)
#define bfin_read_MDMA_D0_PERIPHERAL_MAP() bfin_read16(MDMA_D0_PERIPHERAL_MAP)
@@ -734,23 +764,23 @@
#define bfin_read_MDMA_D0_CURR_Y_COUNT() bfin_read16(MDMA_D0_CURR_Y_COUNT)
#define bfin_write_MDMA_D0_CURR_Y_COUNT(val) bfin_write16(MDMA_D0_CURR_Y_COUNT, val)
#define bfin_read_MDMA_S0_NEXT_DESC_PTR() bfin_read32(MDMA_S0_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA_S0_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S0_NEXT_DESC_PTR(val) bfin_write32(MDMA_S0_NEXT_DESC_PTR, val)
#define bfin_read_MDMA_S0_START_ADDR() bfin_read32(MDMA_S0_START_ADDR)
-#define bfin_write_MDMA_S0_START_ADDR(val) bfin_write32(MDMA_S0_START_ADDR)
+#define bfin_write_MDMA_S0_START_ADDR(val) bfin_write32(MDMA_S0_START_ADDR, val)
#define bfin_read_MDMA_S0_CONFIG() bfin_read16(MDMA_S0_CONFIG)
#define bfin_write_MDMA_S0_CONFIG(val) bfin_write16(MDMA_S0_CONFIG, val)
#define bfin_read_MDMA_S0_X_COUNT() bfin_read16(MDMA_S0_X_COUNT)
#define bfin_write_MDMA_S0_X_COUNT(val) bfin_write16(MDMA_S0_X_COUNT, val)
#define bfin_read_MDMA_S0_X_MODIFY() bfin_read16(MDMA_S0_X_MODIFY)
-#define bfin_write_MDMA_S0_X_MODIFY(val) bfin_write16(MDMA_S0_X_MODIFY)
+#define bfin_write_MDMA_S0_X_MODIFY(val) bfin_write16(MDMA_S0_X_MODIFY, val)
#define bfin_read_MDMA_S0_Y_COUNT() bfin_read16(MDMA_S0_Y_COUNT)
#define bfin_write_MDMA_S0_Y_COUNT(val) bfin_write16(MDMA_S0_Y_COUNT, val)
#define bfin_read_MDMA_S0_Y_MODIFY() bfin_read16(MDMA_S0_Y_MODIFY)
-#define bfin_write_MDMA_S0_Y_MODIFY(val) bfin_write16(MDMA_S0_Y_MODIFY)
+#define bfin_write_MDMA_S0_Y_MODIFY(val) bfin_write16(MDMA_S0_Y_MODIFY, val)
#define bfin_read_MDMA_S0_CURR_DESC_PTR() bfin_read32(MDMA_S0_CURR_DESC_PTR)
-#define bfin_write_MDMA_S0_CURR_DESC_PTR(val) bfin_write32(MDMA_S0_CURR_DESC_PTR)
+#define bfin_write_MDMA_S0_CURR_DESC_PTR(val) bfin_write32(MDMA_S0_CURR_DESC_PTR, val)
#define bfin_read_MDMA_S0_CURR_ADDR() bfin_read32(MDMA_S0_CURR_ADDR)
-#define bfin_write_MDMA_S0_CURR_ADDR(val) bfin_write32(MDMA_S0_CURR_ADDR)
+#define bfin_write_MDMA_S0_CURR_ADDR(val) bfin_write32(MDMA_S0_CURR_ADDR, val)
#define bfin_read_MDMA_S0_IRQ_STATUS() bfin_read16(MDMA_S0_IRQ_STATUS)
#define bfin_write_MDMA_S0_IRQ_STATUS(val) bfin_write16(MDMA_S0_IRQ_STATUS, val)
#define bfin_read_MDMA_S0_PERIPHERAL_MAP() bfin_read16(MDMA_S0_PERIPHERAL_MAP)
@@ -763,9 +793,9 @@
/* MDMA Stream 1 Registers */
#define bfin_read_MDMA_D1_NEXT_DESC_PTR() bfin_read32(MDMA_D1_NEXT_DESC_PTR)
-#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA_D1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_D1_NEXT_DESC_PTR(val) bfin_write32(MDMA_D1_NEXT_DESC_PTR, val)
#define bfin_read_MDMA_D1_START_ADDR() bfin_read32(MDMA_D1_START_ADDR)
-#define bfin_write_MDMA_D1_START_ADDR(val) bfin_write32(MDMA_D1_START_ADDR)
+#define bfin_write_MDMA_D1_START_ADDR(val) bfin_write32(MDMA_D1_START_ADDR, val)
#define bfin_read_MDMA_D1_CONFIG() bfin_read16(MDMA_D1_CONFIG)
#define bfin_write_MDMA_D1_CONFIG(val) bfin_write16(MDMA_D1_CONFIG, val)
#define bfin_read_MDMA_D1_X_COUNT() bfin_read16(MDMA_D1_X_COUNT)
@@ -777,9 +807,9 @@
#define bfin_read_MDMA_D1_Y_MODIFY() bfin_read16(MDMA_D1_Y_MODIFY)
#define bfin_write_MDMA_D1_Y_MODIFY(val) bfin_write16(MDMA_D1_Y_MODIFY)
#define bfin_read_MDMA_D1_CURR_DESC_PTR() bfin_read32(MDMA_D1_CURR_DESC_PTR)
-#define bfin_write_MDMA_D1_CURR_DESC_PTR(val) bfin_write32(MDMA_D1_CURR_DESC_PTR)
+#define bfin_write_MDMA_D1_CURR_DESC_PTR(val) bfin_write32(MDMA_D1_CURR_DESC_PTR, val)
#define bfin_read_MDMA_D1_CURR_ADDR() bfin_read32(MDMA_D1_CURR_ADDR)
-#define bfin_write_MDMA_D1_CURR_ADDR(val) bfin_write32(MDMA_D1_CURR_ADDR)
+#define bfin_write_MDMA_D1_CURR_ADDR(val) bfin_write32(MDMA_D1_CURR_ADDR, val)
#define bfin_read_MDMA_D1_IRQ_STATUS() bfin_read16(MDMA_D1_IRQ_STATUS)
#define bfin_write_MDMA_D1_IRQ_STATUS(val) bfin_write16(MDMA_D1_IRQ_STATUS, val)
#define bfin_read_MDMA_D1_PERIPHERAL_MAP() bfin_read16(MDMA_D1_PERIPHERAL_MAP)
@@ -789,9 +819,9 @@
#define bfin_read_MDMA_D1_CURR_Y_COUNT() bfin_read16(MDMA_D1_CURR_Y_COUNT)
#define bfin_write_MDMA_D1_CURR_Y_COUNT(val) bfin_write16(MDMA_D1_CURR_Y_COUNT, val)
#define bfin_read_MDMA_S1_NEXT_DESC_PTR() bfin_read32(MDMA_S1_NEXT_DESC_PTR)
-#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA_S1_NEXT_DESC_PTR)
+#define bfin_write_MDMA_S1_NEXT_DESC_PTR(val) bfin_write32(MDMA_S1_NEXT_DESC_PTR, val)
#define bfin_read_MDMA_S1_START_ADDR() bfin_read32(MDMA_S1_START_ADDR)
-#define bfin_write_MDMA_S1_START_ADDR(val) bfin_write32(MDMA_S1_START_ADDR)
+#define bfin_write_MDMA_S1_START_ADDR(val) bfin_write32(MDMA_S1_START_ADDR, val)
#define bfin_read_MDMA_S1_CONFIG() bfin_read16(MDMA_S1_CONFIG)
#define bfin_write_MDMA_S1_CONFIG(val) bfin_write16(MDMA_S1_CONFIG, val)
#define bfin_read_MDMA_S1_X_COUNT() bfin_read16(MDMA_S1_X_COUNT)
@@ -803,9 +833,9 @@
#define bfin_read_MDMA_S1_Y_MODIFY() bfin_read16(MDMA_S1_Y_MODIFY)
#define bfin_write_MDMA_S1_Y_MODIFY(val) bfin_write16(MDMA_S1_Y_MODIFY)
#define bfin_read_MDMA_S1_CURR_DESC_PTR() bfin_read32(MDMA_S1_CURR_DESC_PTR)
-#define bfin_write_MDMA_S1_CURR_DESC_PTR(val) bfin_write32(MDMA_S1_CURR_DESC_PTR)
+#define bfin_write_MDMA_S1_CURR_DESC_PTR(val) bfin_write32(MDMA_S1_CURR_DESC_PTR, val)
#define bfin_read_MDMA_S1_CURR_ADDR() bfin_read32(MDMA_S1_CURR_ADDR)
-#define bfin_write_MDMA_S1_CURR_ADDR(val) bfin_write32(MDMA_S1_CURR_ADDR)
+#define bfin_write_MDMA_S1_CURR_ADDR(val) bfin_write32(MDMA_S1_CURR_ADDR, val)
#define bfin_read_MDMA_S1_IRQ_STATUS() bfin_read16(MDMA_S1_IRQ_STATUS)
#define bfin_write_MDMA_S1_IRQ_STATUS(val) bfin_write16(MDMA_S1_IRQ_STATUS, val)
#define bfin_read_MDMA_S1_PERIPHERAL_MAP() bfin_read16(MDMA_S1_PERIPHERAL_MAP)
diff --git a/include/asm-blackfin/mach-bf548/defBF542.h b/include/asm-blackfin/mach-bf548/defBF542.h
index ac968fca5cc..32d07130200 100644
--- a/include/asm-blackfin/mach-bf548/defBF542.h
+++ b/include/asm-blackfin/mach-bf548/defBF542.h
@@ -362,7 +362,6 @@
/* Bit masks for KPAD_CTL */
#define KPAD_EN 0x1 /* Keypad Enable */
-#define nKPAD_EN 0x0
#define KPAD_IRQMODE 0x6 /* Key Press Interrupt Enable */
#define KPAD_ROWEN 0x1c00 /* Row Enable Width */
#define KPAD_COLEN 0xe000 /* Column Enable Width */
@@ -384,29 +383,21 @@
/* Bit masks for KPAD_STAT */
#define KPAD_IRQ 0x1 /* Keypad Interrupt Status */
-#define nKPAD_IRQ 0x0
#define KPAD_MROWCOL 0x6 /* Multiple Row/Column Keypress Status */
#define KPAD_PRESSED 0x8 /* Key press current status */
-#define nKPAD_PRESSED 0x0
/* Bit masks for KPAD_SOFTEVAL */
#define KPAD_SOFTEVAL_E 0x2 /* Software Programmable Force Evaluate */
-#define nKPAD_SOFTEVAL_E 0x0
/* Bit masks for SDH_COMMAND */
#define CMD_IDX 0x3f /* Command Index */
#define CMD_RSP 0x40 /* Response */
-#define nCMD_RSP 0x0
#define CMD_L_RSP 0x80 /* Long Response */
-#define nCMD_L_RSP 0x0
#define CMD_INT_E 0x100 /* Command Interrupt */
-#define nCMD_INT_E 0x0
#define CMD_PEND_E 0x200 /* Command Pending */
-#define nCMD_PEND_E 0x0
#define CMD_E 0x400 /* Command Enable */
-#define nCMD_E 0x0
/* Bit masks for SDH_PWR_CTL */
@@ -415,21 +406,15 @@
#define TBD 0x3c /* TBD */
#endif
#define SD_CMD_OD 0x40 /* Open Drain Output */
-#define nSD_CMD_OD 0x0
#define ROD_CTL 0x80 /* Rod Control */
-#define nROD_CTL 0x0
/* Bit masks for SDH_CLK_CTL */
#define CLKDIV 0xff /* MC_CLK Divisor */
#define CLK_E 0x100 /* MC_CLK Bus Clock Enable */
-#define nCLK_E 0x0
#define PWR_SV_E 0x200 /* Power Save Enable */
-#define nPWR_SV_E 0x0
#define CLKDIV_BYPASS 0x400 /* Bypass Divisor */
-#define nCLKDIV_BYPASS 0x0
#define WIDE_BUS 0x800 /* Wide Bus Mode Enable */
-#define nWIDE_BUS 0x0
/* Bit masks for SDH_RESP_CMD */
@@ -438,133 +423,74 @@
/* Bit masks for SDH_DATA_CTL */
#define DTX_E 0x1 /* Data Transfer Enable */
-#define nDTX_E 0x0
#define DTX_DIR 0x2 /* Data Transfer Direction */
-#define nDTX_DIR 0x0
#define DTX_MODE 0x4 /* Data Transfer Mode */
-#define nDTX_MODE 0x0
#define DTX_DMA_E 0x8 /* Data Transfer DMA Enable */
-#define nDTX_DMA_E 0x0
#define DTX_BLK_LGTH 0xf0 /* Data Transfer Block Length */
/* Bit masks for SDH_STATUS */
#define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */
-#define nCMD_CRC_FAIL 0x0
#define DAT_CRC_FAIL 0x2 /* Data CRC Fail */
-#define nDAT_CRC_FAIL 0x0
#define CMD_TIMEOUT 0x4 /* CMD Time Out */
-#define nCMD_TIMEOUT 0x0
#define DAT_TIMEOUT 0x8 /* Data Time Out */
-#define nDAT_TIMEOUT 0x0
#define TX_UNDERRUN 0x10 /* Transmit Underrun */
-#define nTX_UNDERRUN 0x0
#define RX_OVERRUN 0x20 /* Receive Overrun */
-#define nRX_OVERRUN 0x0
#define CMD_RESP_END 0x40 /* CMD Response End */
-#define nCMD_RESP_END 0x0
#define CMD_SENT 0x80 /* CMD Sent */
-#define nCMD_SENT 0x0
#define DAT_END 0x100 /* Data End */
-#define nDAT_END 0x0
#define START_BIT_ERR 0x200 /* Start Bit Error */
-#define nSTART_BIT_ERR 0x0
#define DAT_BLK_END 0x400 /* Data Block End */
-#define nDAT_BLK_END 0x0
#define CMD_ACT 0x800 /* CMD Active */
-#define nCMD_ACT 0x0
#define TX_ACT 0x1000 /* Transmit Active */
-#define nTX_ACT 0x0
#define RX_ACT 0x2000 /* Receive Active */
-#define nRX_ACT 0x0
#define TX_FIFO_STAT 0x4000 /* Transmit FIFO Status */
-#define nTX_FIFO_STAT 0x0
#define RX_FIFO_STAT 0x8000 /* Receive FIFO Status */
-#define nRX_FIFO_STAT 0x0
#define TX_FIFO_FULL 0x10000 /* Transmit FIFO Full */
-#define nTX_FIFO_FULL 0x0
#define RX_FIFO_FULL 0x20000 /* Receive FIFO Full */
-#define nRX_FIFO_FULL 0x0
#define TX_FIFO_ZERO 0x40000 /* Transmit FIFO Empty */
-#define nTX_FIFO_ZERO 0x0
#define RX_DAT_ZERO 0x80000 /* Receive FIFO Empty */
-#define nRX_DAT_ZERO 0x0
#define TX_DAT_RDY 0x100000 /* Transmit Data Available */
-#define nTX_DAT_RDY 0x0
#define RX_FIFO_RDY 0x200000 /* Receive Data Available */
-#define nRX_FIFO_RDY 0x0
/* Bit masks for SDH_STATUS_CLR */
#define CMD_CRC_FAIL_STAT 0x1 /* CMD CRC Fail Status */
-#define nCMD_CRC_FAIL_STAT 0x0
#define DAT_CRC_FAIL_STAT 0x2 /* Data CRC Fail Status */
-#define nDAT_CRC_FAIL_STAT 0x0
#define CMD_TIMEOUT_STAT 0x4 /* CMD Time Out Status */
-#define nCMD_TIMEOUT_STAT 0x0
#define DAT_TIMEOUT_STAT 0x8 /* Data Time Out status */
-#define nDAT_TIMEOUT_STAT 0x0
#define TX_UNDERRUN_STAT 0x10 /* Transmit Underrun Status */
-#define nTX_UNDERRUN_STAT 0x0
#define RX_OVERRUN_STAT 0x20 /* Receive Overrun Status */
-#define nRX_OVERRUN_STAT 0x0
#define CMD_RESP_END_STAT 0x40 /* CMD Response End Status */
-#define nCMD_RESP_END_STAT 0x0
#define CMD_SENT_STAT 0x80 /* CMD Sent Status */
-#define nCMD_SENT_STAT 0x0
#define DAT_END_STAT 0x100 /* Data End Status */
-#define nDAT_END_STAT 0x0
#define START_BIT_ERR_STAT 0x200 /* Start Bit Error Status */
-#define nSTART_BIT_ERR_STAT 0x0
#define DAT_BLK_END_STAT 0x400 /* Data Block End Status */
-#define nDAT_BLK_END_STAT 0x0
/* Bit masks for SDH_MASK0 */
#define CMD_CRC_FAIL_MASK 0x1 /* CMD CRC Fail Mask */
-#define nCMD_CRC_FAIL_MASK 0x0
#define DAT_CRC_FAIL_MASK 0x2 /* Data CRC Fail Mask */
-#define nDAT_CRC_FAIL_MASK 0x0
#define CMD_TIMEOUT_MASK 0x4 /* CMD Time Out Mask */
-#define nCMD_TIMEOUT_MASK 0x0
#define DAT_TIMEOUT_MASK 0x8 /* Data Time Out Mask */
-#define nDAT_TIMEOUT_MASK 0x0
#define TX_UNDERRUN_MASK 0x10 /* Transmit Underrun Mask */
-#define nTX_UNDERRUN_MASK 0x0
#define RX_OVERRUN_MASK 0x20 /* Receive Overrun Mask */
-#define nRX_OVERRUN_MASK 0x0
#define CMD_RESP_END_MASK 0x40 /* CMD Response End Mask */
-#define nCMD_RESP_END_MASK 0x0
#define CMD_SENT_MASK 0x80 /* CMD Sent Mask */
-#define nCMD_SENT_MASK 0x0
#define DAT_END_MASK 0x100 /* Data End Mask */
-#define nDAT_END_MASK 0x0
#define START_BIT_ERR_MASK 0x200 /* Start Bit Error Mask */
-#define nSTART_BIT_ERR_MASK 0x0
#define DAT_BLK_END_MASK 0x400 /* Data Block End Mask */
-#define nDAT_BLK_END_MASK 0x0
#define CMD_ACT_MASK 0x800 /* CMD Active Mask */
-#define nCMD_ACT_MASK 0x0
#define TX_ACT_MASK 0x1000 /* Transmit Active Mask */
-#define nTX_ACT_MASK 0x0
#define RX_ACT_MASK 0x2000 /* Receive Active Mask */
-#define nRX_ACT_MASK 0x0
#define TX_FIFO_STAT_MASK 0x4000 /* Transmit FIFO Status Mask */
-#define nTX_FIFO_STAT_MASK 0x0
#define RX_FIFO_STAT_MASK 0x8000 /* Receive FIFO Status Mask */
-#define nRX_FIFO_STAT_MASK 0x0
#define TX_FIFO_FULL_MASK 0x10000 /* Transmit FIFO Full Mask */
-#define nTX_FIFO_FULL_MASK 0x0
#define RX_FIFO_FULL_MASK 0x20000 /* Receive FIFO Full Mask */
-#define nRX_FIFO_FULL_MASK 0x0
#define TX_FIFO_ZERO_MASK 0x40000 /* Transmit FIFO Empty Mask */
-#define nTX_FIFO_ZERO_MASK 0x0
#define RX_DAT_ZERO_MASK 0x80000 /* Receive FIFO Empty Mask */
-#define nRX_DAT_ZERO_MASK 0x0
#define TX_DAT_RDY_MASK 0x100000 /* Transmit Data Available Mask */
-#define nTX_DAT_RDY_MASK 0x0
#define RX_FIFO_RDY_MASK 0x200000 /* Receive Data Available Mask */
-#define nRX_FIFO_RDY_MASK 0x0
/* Bit masks for SDH_FIFO_CNT */
@@ -573,73 +499,47 @@
/* Bit masks for SDH_E_STATUS */
#define SDIO_INT_DET 0x2 /* SDIO Int Detected */
-#define nSDIO_INT_DET 0x0
#define SD_CARD_DET 0x10 /* SD Card Detect */
-#define nSD_CARD_DET 0x0
/* Bit masks for SDH_E_MASK */
#define SDIO_MSK 0x2 /* Mask SDIO Int Detected */
-#define nSDIO_MSK 0x0
#define SCD_MSK 0x40 /* Mask Card Detect */
-#define nSCD_MSK 0x0
/* Bit masks for SDH_CFG */
#define CLKS_EN 0x1 /* Clocks Enable */
-#define nCLKS_EN 0x0
#define SD4E 0x4 /* SDIO 4-Bit Enable */
-#define nSD4E 0x0
#define MWE 0x8 /* Moving Window Enable */
-#define nMWE 0x0
#define SD_RST 0x10 /* SDMMC Reset */
-#define nSD_RST 0x0
#define PUP_SDDAT 0x20 /* Pull-up SD_DAT */
-#define nPUP_SDDAT 0x0
#define PUP_SDDAT3 0x40 /* Pull-up SD_DAT3 */
-#define nPUP_SDDAT3 0x0
#define PD_SDDAT3 0x80 /* Pull-down SD_DAT3 */
-#define nPD_SDDAT3 0x0
/* Bit masks for SDH_RD_WAIT_EN */
#define RWR 0x1 /* Read Wait Request */
-#define nRWR 0x0
/* Bit masks for ATAPI_CONTROL */
#define PIO_START 0x1 /* Start PIO/Reg Op */
-#define nPIO_START 0x0
#define MULTI_START 0x2 /* Start Multi-DMA Op */
-#define nMULTI_START 0x0
#define ULTRA_START 0x4 /* Start Ultra-DMA Op */
-#define nULTRA_START 0x0
#define XFER_DIR 0x8 /* Transfer Direction */
-#define nXFER_DIR 0x0
#define IORDY_EN 0x10 /* IORDY Enable */
-#define nIORDY_EN 0x0
#define FIFO_FLUSH 0x20 /* Flush FIFOs */
-#define nFIFO_FLUSH 0x0
#define SOFT_RST 0x40 /* Soft Reset */
-#define nSOFT_RST 0x0
#define DEV_RST 0x80 /* Device Reset */
-#define nDEV_RST 0x0
#define TFRCNT_RST 0x100 /* Trans Count Reset */
-#define nTFRCNT_RST 0x0
#define END_ON_TERM 0x200 /* End/Terminate Select */
-#define nEND_ON_TERM 0x0
#define PIO_USE_DMA 0x400 /* PIO-DMA Enable */
-#define nPIO_USE_DMA 0x0
#define UDMAIN_FIFO_THRS 0xf000 /* Ultra DMA-IN FIFO Threshold */
/* Bit masks for ATAPI_STATUS */
#define PIO_XFER_ON 0x1 /* PIO transfer in progress */
-#define nPIO_XFER_ON 0x0
#define MULTI_XFER_ON 0x2 /* Multi-word DMA transfer in progress */
-#define nMULTI_XFER_ON 0x0
#define ULTRA_XFER_ON 0x4 /* Ultra DMA transfer in progress */
-#define nULTRA_XFER_ON 0x0
#define ULTRA_IN_FL 0xf0 /* Ultra DMA Input FIFO Level */
/* Bit masks for ATAPI_DEV_ADDR */
@@ -649,66 +549,39 @@
/* Bit masks for ATAPI_INT_MASK */
#define ATAPI_DEV_INT_MASK 0x1 /* Device interrupt mask */
-#define nATAPI_DEV_INT_MASK 0x0
#define PIO_DONE_MASK 0x2 /* PIO transfer done interrupt mask */
-#define nPIO_DONE_MASK 0x0
#define MULTI_DONE_MASK 0x4 /* Multi-DMA transfer done interrupt mask */
-#define nMULTI_DONE_MASK 0x0
#define UDMAIN_DONE_MASK 0x8 /* Ultra-DMA in transfer done interrupt mask */
-#define nUDMAIN_DONE_MASK 0x0
#define UDMAOUT_DONE_MASK 0x10 /* Ultra-DMA out transfer done interrupt mask */
-#define nUDMAOUT_DONE_MASK 0x0
#define HOST_TERM_XFER_MASK 0x20 /* Host terminate current transfer interrupt mask */
-#define nHOST_TERM_XFER_MASK 0x0
#define MULTI_TERM_MASK 0x40 /* Device terminate Multi-DMA transfer interrupt mask */
-#define nMULTI_TERM_MASK 0x0
#define UDMAIN_TERM_MASK 0x80 /* Device terminate Ultra-DMA-in transfer interrupt mask */
-#define nUDMAIN_TERM_MASK 0x0
#define UDMAOUT_TERM_MASK 0x100 /* Device terminate Ultra-DMA-out transfer interrupt mask */
-#define nUDMAOUT_TERM_MASK 0x0
/* Bit masks for ATAPI_INT_STATUS */
#define ATAPI_DEV_INT 0x1 /* Device interrupt status */
-#define nATAPI_DEV_INT 0x0
#define PIO_DONE_INT 0x2 /* PIO transfer done interrupt status */
-#define nPIO_DONE_INT 0x0
#define MULTI_DONE_INT 0x4 /* Multi-DMA transfer done interrupt status */
-#define nMULTI_DONE_INT 0x0
#define UDMAIN_DONE_INT 0x8 /* Ultra-DMA in transfer done interrupt status */
-#define nUDMAIN_DONE_INT 0x0
#define UDMAOUT_DONE_INT 0x10 /* Ultra-DMA out transfer done interrupt status */
-#define nUDMAOUT_DONE_INT 0x0
#define HOST_TERM_XFER_INT 0x20 /* Host terminate current transfer interrupt status */
-#define nHOST_TERM_XFER_INT 0x0
#define MULTI_TERM_INT 0x40 /* Device terminate Multi-DMA transfer interrupt status */
-#define nMULTI_TERM_INT 0x0
#define UDMAIN_TERM_INT 0x80 /* Device terminate Ultra-DMA-in transfer interrupt status */
-#define nUDMAIN_TERM_INT 0x0
#define UDMAOUT_TERM_INT 0x100 /* Device terminate Ultra-DMA-out transfer interrupt status */
-#define nUDMAOUT_TERM_INT 0x0
/* Bit masks for ATAPI_LINE_STATUS */
#define ATAPI_INTR 0x1 /* Device interrupt to host line status */
-#define nATAPI_INTR 0x0
#define ATAPI_DASP 0x2 /* Device dasp to host line status */
-#define nATAPI_DASP 0x0
#define ATAPI_CS0N 0x4 /* ATAPI chip select 0 line status */
-#define nATAPI_CS0N 0x0
#define ATAPI_CS1N 0x8 /* ATAPI chip select 1 line status */
-#define nATAPI_CS1N 0x0
#define ATAPI_ADDR 0x70 /* ATAPI address line status */
#define ATAPI_DMAREQ 0x80 /* ATAPI DMA request line status */
-#define nATAPI_DMAREQ 0x0
#define ATAPI_DMAACKN 0x100 /* ATAPI DMA acknowledge line status */
-#define nATAPI_DMAACKN 0x0
#define ATAPI_DIOWN 0x200 /* ATAPI write line status */
-#define nATAPI_DIOWN 0x0
#define ATAPI_DIORN 0x400 /* ATAPI read line status */
-#define nATAPI_DIORN 0x0
#define ATAPI_IORDY 0x800 /* ATAPI IORDY line status */
-#define nATAPI_IORDY 0x0
/* Bit masks for ATAPI_SM_STATE */
@@ -720,7 +593,6 @@
/* Bit masks for ATAPI_TERMINATE */
#define ATAPI_HOST_TERM 0x1 /* Host terminationation */
-#define nATAPI_HOST_TERM 0x0
/* Bit masks for ATAPI_REG_TIM_0 */
@@ -779,131 +651,77 @@
/* Bit masks for USB_POWER */
#define ENABLE_SUSPENDM 0x1 /* enable SuspendM output */
-#define nENABLE_SUSPENDM 0x0
#define SUSPEND_MODE 0x2 /* Suspend Mode indicator */
-#define nSUSPEND_MODE 0x0
#define RESUME_MODE 0x4 /* DMA Mode */
-#define nRESUME_MODE 0x0
#define RESET 0x8 /* Reset indicator */
-#define nRESET 0x0
#define HS_MODE 0x10 /* High Speed mode indicator */
-#define nHS_MODE 0x0
#define HS_ENABLE 0x20 /* high Speed Enable */
-#define nHS_ENABLE 0x0
#define SOFT_CONN 0x40 /* Soft connect */
-#define nSOFT_CONN 0x0
#define ISO_UPDATE 0x80 /* Isochronous update */
-#define nISO_UPDATE 0x0
/* Bit masks for USB_INTRTX */
#define EP0_TX 0x1 /* Tx Endpoint 0 interrupt */
-#define nEP0_TX 0x0
#define EP1_TX 0x2 /* Tx Endpoint 1 interrupt */
-#define nEP1_TX 0x0
#define EP2_TX 0x4 /* Tx Endpoint 2 interrupt */
-#define nEP2_TX 0x0
#define EP3_TX 0x8 /* Tx Endpoint 3 interrupt */
-#define nEP3_TX 0x0
#define EP4_TX 0x10 /* Tx Endpoint 4 interrupt */
-#define nEP4_TX 0x0
#define EP5_TX 0x20 /* Tx Endpoint 5 interrupt */
-#define nEP5_TX 0x0
#define EP6_TX 0x40 /* Tx Endpoint 6 interrupt */
-#define nEP6_TX 0x0
#define EP7_TX 0x80 /* Tx Endpoint 7 interrupt */
-#define nEP7_TX 0x0
/* Bit masks for USB_INTRRX */
#define EP1_RX 0x2 /* Rx Endpoint 1 interrupt */
-#define nEP1_RX 0x0
#define EP2_RX 0x4 /* Rx Endpoint 2 interrupt */
-#define nEP2_RX 0x0
#define EP3_RX 0x8 /* Rx Endpoint 3 interrupt */
-#define nEP3_RX 0x0
#define EP4_RX 0x10 /* Rx Endpoint 4 interrupt */
-#define nEP4_RX 0x0
#define EP5_RX 0x20 /* Rx Endpoint 5 interrupt */
-#define nEP5_RX 0x0
#define EP6_RX 0x40 /* Rx Endpoint 6 interrupt */
-#define nEP6_RX 0x0
#define EP7_RX 0x80 /* Rx Endpoint 7 interrupt */
-#define nEP7_RX 0x0
/* Bit masks for USB_INTRTXE */
#define EP0_TX_E 0x1 /* Endpoint 0 interrupt Enable */
-#define nEP0_TX_E 0x0
#define EP1_TX_E 0x2 /* Tx Endpoint 1 interrupt Enable */
-#define nEP1_TX_E 0x0
#define EP2_TX_E 0x4 /* Tx Endpoint 2 interrupt Enable */
-#define nEP2_TX_E 0x0
#define EP3_TX_E 0x8 /* Tx Endpoint 3 interrupt Enable */
-#define nEP3_TX_E 0x0
#define EP4_TX_E 0x10 /* Tx Endpoint 4 interrupt Enable */
-#define nEP4_TX_E 0x0
#define EP5_TX_E 0x20 /* Tx Endpoint 5 interrupt Enable */
-#define nEP5_TX_E 0x0
#define EP6_TX_E 0x40 /* Tx Endpoint 6 interrupt Enable */
-#define nEP6_TX_E 0x0
#define EP7_TX_E 0x80 /* Tx Endpoint 7 interrupt Enable */
-#define nEP7_TX_E 0x0
/* Bit masks for USB_INTRRXE */
#define EP1_RX_E 0x2 /* Rx Endpoint 1 interrupt Enable */
-#define nEP1_RX_E 0x0
#define EP2_RX_E 0x4 /* Rx Endpoint 2 interrupt Enable */
-#define nEP2_RX_E 0x0
#define EP3_RX_E 0x8 /* Rx Endpoint 3 interrupt Enable */
-#define nEP3_RX_E 0x0
#define EP4_RX_E 0x10 /* Rx Endpoint 4 interrupt Enable */
-#define nEP4_RX_E 0x0
#define EP5_RX_E 0x20 /* Rx Endpoint 5 interrupt Enable */
-#define nEP5_RX_E 0x0
#define EP6_RX_E 0x40 /* Rx Endpoint 6 interrupt Enable */
-#define nEP6_RX_E 0x0
#define EP7_RX_E 0x80 /* Rx Endpoint 7 interrupt Enable */
-#define nEP7_RX_E 0x0
/* Bit masks for USB_INTRUSB */
#define SUSPEND_B 0x1 /* Suspend indicator */
-#define nSUSPEND_B 0x0
#define RESUME_B 0x2 /* Resume indicator */
-#define nRESUME_B 0x0
#define RESET_OR_BABLE_B 0x4 /* Reset/babble indicator */
-#define nRESET_OR_BABLE_B 0x0
#define SOF_B 0x8 /* Start of frame */
-#define nSOF_B 0x0
#define CONN_B 0x10 /* Connection indicator */
-#define nCONN_B 0x0
#define DISCON_B 0x20 /* Disconnect indicator */
-#define nDISCON_B 0x0
#define SESSION_REQ_B 0x40 /* Session Request */
-#define nSESSION_REQ_B 0x0
#define VBUS_ERROR_B 0x80 /* Vbus threshold indicator */
-#define nVBUS_ERROR_B 0x0
/* Bit masks for USB_INTRUSBE */
#define SUSPEND_BE 0x1 /* Suspend indicator int enable */
-#define nSUSPEND_BE 0x0
#define RESUME_BE 0x2 /* Resume indicator int enable */
-#define nRESUME_BE 0x0
#define RESET_OR_BABLE_BE 0x4 /* Reset/babble indicator int enable */
-#define nRESET_OR_BABLE_BE 0x0
#define SOF_BE 0x8 /* Start of frame int enable */
-#define nSOF_BE 0x0
#define CONN_BE 0x10 /* Connection indicator int enable */
-#define nCONN_BE 0x0
#define DISCON_BE 0x20 /* Disconnect indicator int enable */
-#define nDISCON_BE 0x0
#define SESSION_REQ_BE 0x40 /* Session Request int enable */
-#define nSESSION_REQ_BE 0x0
#define VBUS_ERROR_BE 0x80 /* Vbus threshold indicator int enable */
-#define nVBUS_ERROR_BE 0x0
/* Bit masks for USB_FRAME */
@@ -916,117 +734,67 @@
/* Bit masks for USB_GLOBAL_CTL */
#define GLOBAL_ENA 0x1 /* enables USB module */
-#define nGLOBAL_ENA 0x0
#define EP1_TX_ENA 0x2 /* Transmit endpoint 1 enable */
-#define nEP1_TX_ENA 0x0
#define EP2_TX_ENA 0x4 /* Transmit endpoint 2 enable */
-#define nEP2_TX_ENA 0x0
#define EP3_TX_ENA 0x8 /* Transmit endpoint 3 enable */
-#define nEP3_TX_ENA 0x0
#define EP4_TX_ENA 0x10 /* Transmit endpoint 4 enable */
-#define nEP4_TX_ENA 0x0
#define EP5_TX_ENA 0x20 /* Transmit endpoint 5 enable */
-#define nEP5_TX_ENA 0x0
#define EP6_TX_ENA 0x40 /* Transmit endpoint 6 enable */
-#define nEP6_TX_ENA 0x0
#define EP7_TX_ENA 0x80 /* Transmit endpoint 7 enable */
-#define nEP7_TX_ENA 0x0
#define EP1_RX_ENA 0x100 /* Receive endpoint 1 enable */
-#define nEP1_RX_ENA 0x0
#define EP2_RX_ENA 0x200 /* Receive endpoint 2 enable */
-#define nEP2_RX_ENA 0x0
#define EP3_RX_ENA 0x400 /* Receive endpoint 3 enable */
-#define nEP3_RX_ENA 0x0
#define EP4_RX_ENA 0x800 /* Receive endpoint 4 enable */
-#define nEP4_RX_ENA 0x0
#define EP5_RX_ENA 0x1000 /* Receive endpoint 5 enable */
-#define nEP5_RX_ENA 0x0
#define EP6_RX_ENA 0x2000 /* Receive endpoint 6 enable */
-#define nEP6_RX_ENA 0x0
#define EP7_RX_ENA 0x4000 /* Receive endpoint 7 enable */
-#define nEP7_RX_ENA 0x0
/* Bit masks for USB_OTG_DEV_CTL */
#define SESSION 0x1 /* session indicator */
-#define nSESSION 0x0
#define HOST_REQ 0x2 /* Host negotiation request */
-#define nHOST_REQ 0x0
#define HOST_MODE 0x4 /* indicates USBDRC is a host */
-#define nHOST_MODE 0x0
#define VBUS0 0x8 /* Vbus level indicator[0] */
-#define nVBUS0 0x0
#define VBUS1 0x10 /* Vbus level indicator[1] */
-#define nVBUS1 0x0
#define LSDEV 0x20 /* Low-speed indicator */
-#define nLSDEV 0x0
#define FSDEV 0x40 /* Full or High-speed indicator */
-#define nFSDEV 0x0
#define B_DEVICE 0x80 /* A' or 'B' device indicator */
-#define nB_DEVICE 0x0
/* Bit masks for USB_OTG_VBUS_IRQ */
#define DRIVE_VBUS_ON 0x1 /* indicator to drive VBUS control circuit */
-#define nDRIVE_VBUS_ON 0x0
#define DRIVE_VBUS_OFF 0x2 /* indicator to shut off charge pump */
-#define nDRIVE_VBUS_OFF 0x0
#define CHRG_VBUS_START 0x4 /* indicator for external circuit to start charging VBUS */
-#define nCHRG_VBUS_START 0x0
#define CHRG_VBUS_END 0x8 /* indicator for external circuit to end charging VBUS */
-#define nCHRG_VBUS_END 0x0
#define DISCHRG_VBUS_START 0x10 /* indicator to start discharging VBUS */
-#define nDISCHRG_VBUS_START 0x0
#define DISCHRG_VBUS_END 0x20 /* indicator to stop discharging VBUS */
-#define nDISCHRG_VBUS_END 0x0
/* Bit masks for USB_OTG_VBUS_MASK */
#define DRIVE_VBUS_ON_ENA 0x1 /* enable DRIVE_VBUS_ON interrupt */
-#define nDRIVE_VBUS_ON_ENA 0x0
#define DRIVE_VBUS_OFF_ENA 0x2 /* enable DRIVE_VBUS_OFF interrupt */
-#define nDRIVE_VBUS_OFF_ENA 0x0
#define CHRG_VBUS_START_ENA 0x4 /* enable CHRG_VBUS_START interrupt */
-#define nCHRG_VBUS_START_ENA 0x0
#define CHRG_VBUS_END_ENA 0x8 /* enable CHRG_VBUS_END interrupt */
-#define nCHRG_VBUS_END_ENA 0x0
#define DISCHRG_VBUS_START_ENA 0x10 /* enable DISCHRG_VBUS_START interrupt */
-#define nDISCHRG_VBUS_START_ENA 0x0
#define DISCHRG_VBUS_END_ENA 0x20 /* enable DISCHRG_VBUS_END interrupt */
-#define nDISCHRG_VBUS_END_ENA 0x0
/* Bit masks for USB_CSR0 */
#define RXPKTRDY 0x1 /* data packet receive indicator */
-#define nRXPKTRDY 0x0
#define TXPKTRDY 0x2 /* data packet in FIFO indicator */
-#define nTXPKTRDY 0x0
#define STALL_SENT 0x4 /* STALL handshake sent */
-#define nSTALL_SENT 0x0
#define DATAEND 0x8 /* Data end indicator */
-#define nDATAEND 0x0
#define SETUPEND 0x10 /* Setup end */
-#define nSETUPEND 0x0
#define SENDSTALL 0x20 /* Send STALL handshake */
-#define nSENDSTALL 0x0
#define SERVICED_RXPKTRDY 0x40 /* used to clear the RxPktRdy bit */
-#define nSERVICED_RXPKTRDY 0x0
#define SERVICED_SETUPEND 0x80 /* used to clear the SetupEnd bit */
-#define nSERVICED_SETUPEND 0x0
#define FLUSHFIFO 0x100 /* flush endpoint FIFO */
-#define nFLUSHFIFO 0x0
#define STALL_RECEIVED_H 0x4 /* STALL handshake received host mode */
-#define nSTALL_RECEIVED_H 0x0
#define SETUPPKT_H 0x8 /* send Setup token host mode */
-#define nSETUPPKT_H 0x0
#define ERROR_H 0x10 /* timeout error indicator host mode */
-#define nERROR_H 0x0
#define REQPKT_H 0x20 /* Request an IN transaction host mode */
-#define nREQPKT_H 0x0
#define STATUSPKT_H 0x40 /* Status stage transaction host mode */
-#define nSTATUSPKT_H 0x0
#define NAK_TIMEOUT_H 0x80 /* EP0 halted after a NAK host mode */
-#define nNAK_TIMEOUT_H 0x0
/* Bit masks for USB_COUNT0 */
@@ -1047,37 +815,21 @@
/* Bit masks for USB_TXCSR */
#define TXPKTRDY_T 0x1 /* data packet in FIFO indicator */
-#define nTXPKTRDY_T 0x0
#define FIFO_NOT_EMPTY_T 0x2 /* FIFO not empty */
-#define nFIFO_NOT_EMPTY_T 0x0
#define UNDERRUN_T 0x4 /* TxPktRdy not set for an IN token */
-#define nUNDERRUN_T 0x0
#define FLUSHFIFO_T 0x8 /* flush endpoint FIFO */
-#define nFLUSHFIFO_T 0x0
#define STALL_SEND_T 0x10 /* issue a Stall handshake */
-#define nSTALL_SEND_T 0x0
#define STALL_SENT_T 0x20 /* Stall handshake transmitted */
-#define nSTALL_SENT_T 0x0
#define CLEAR_DATATOGGLE_T 0x40 /* clear endpoint data toggle */
-#define nCLEAR_DATATOGGLE_T 0x0
#define INCOMPTX_T 0x80 /* indicates that a large packet is split */
-#define nINCOMPTX_T 0x0
#define DMAREQMODE_T 0x400 /* DMA mode (0 or 1) selection */
-#define nDMAREQMODE_T 0x0
#define FORCE_DATATOGGLE_T 0x800 /* Force data toggle */
-#define nFORCE_DATATOGGLE_T 0x0
#define DMAREQ_ENA_T 0x1000 /* Enable DMA request for Tx EP */
-#define nDMAREQ_ENA_T 0x0
#define ISO_T 0x4000 /* enable Isochronous transfers */
-#define nISO_T 0x0
#define AUTOSET_T 0x8000 /* allows TxPktRdy to be set automatically */
-#define nAUTOSET_T 0x0
#define ERROR_TH 0x4 /* error condition host mode */
-#define nERROR_TH 0x0
#define STALL_RECEIVED_TH 0x20 /* Stall handshake received host mode */
-#define nSTALL_RECEIVED_TH 0x0
#define NAK_TIMEOUT_TH 0x80 /* NAK timeout host mode */
-#define nNAK_TIMEOUT_TH 0x0
/* Bit masks for USB_TXCOUNT */
@@ -1086,45 +838,25 @@
/* Bit masks for USB_RXCSR */
#define RXPKTRDY_R 0x1 /* data packet in FIFO indicator */
-#define nRXPKTRDY_R 0x0
#define FIFO_FULL_R 0x2 /* FIFO not empty */
-#define nFIFO_FULL_R 0x0
#define OVERRUN_R 0x4 /* TxPktRdy not set for an IN token */
-#define nOVERRUN_R 0x0
#define DATAERROR_R 0x8 /* Out packet cannot be loaded into Rx FIFO */
-#define nDATAERROR_R 0x0
#define FLUSHFIFO_R 0x10 /* flush endpoint FIFO */
-#define nFLUSHFIFO_R 0x0
#define STALL_SEND_R 0x20 /* issue a Stall handshake */
-#define nSTALL_SEND_R 0x0
#define STALL_SENT_R 0x40 /* Stall handshake transmitted */
-#define nSTALL_SENT_R 0x0
#define CLEAR_DATATOGGLE_R 0x80 /* clear endpoint data toggle */
-#define nCLEAR_DATATOGGLE_R 0x0
#define INCOMPRX_R 0x100 /* indicates that a large packet is split */
-#define nINCOMPRX_R 0x0
#define DMAREQMODE_R 0x800 /* DMA mode (0 or 1) selection */
-#define nDMAREQMODE_R 0x0
#define DISNYET_R 0x1000 /* disable Nyet handshakes */
-#define nDISNYET_R 0x0
#define DMAREQ_ENA_R 0x2000 /* Enable DMA request for Tx EP */
-#define nDMAREQ_ENA_R 0x0
#define ISO_R 0x4000 /* enable Isochronous transfers */
-#define nISO_R 0x0
#define AUTOCLEAR_R 0x8000 /* allows TxPktRdy to be set automatically */
-#define nAUTOCLEAR_R 0x0
#define ERROR_RH 0x4 /* TxPktRdy not set for an IN token host mode */
-#define nERROR_RH 0x0
#define REQPKT_RH 0x20 /* request an IN transaction host mode */
-#define nREQPKT_RH 0x0
#define STALL_RECEIVED_RH 0x40 /* Stall handshake received host mode */
-#define nSTALL_RECEIVED_RH 0x0
#define INCOMPRX_RH 0x100 /* indicates that a large packet is split host mode */
-#define nINCOMPRX_RH 0x0
#define DMAREQMODE_RH 0x800 /* DMA mode (0 or 1) selection host mode */
-#define nDMAREQMODE_RH 0x0
#define AUTOREQ_RH 0x4000 /* sets ReqPkt automatically host mode */
-#define nAUTOREQ_RH 0x0
/* Bit masks for USB_RXCOUNT */
@@ -1151,35 +883,22 @@
/* Bit masks for USB_DMA_INTERRUPT */
#define DMA0_INT 0x1 /* DMA0 pending interrupt */
-#define nDMA0_INT 0x0
#define DMA1_INT 0x2 /* DMA1 pending interrupt */
-#define nDMA1_INT 0x0
#define DMA2_INT 0x4 /* DMA2 pending interrupt */
-#define nDMA2_INT 0x0
#define DMA3_INT 0x8 /* DMA3 pending interrupt */
-#define nDMA3_INT 0x0
#define DMA4_INT 0x10 /* DMA4 pending interrupt */
-#define nDMA4_INT 0x0
#define DMA5_INT 0x20 /* DMA5 pending interrupt */
-#define nDMA5_INT 0x0
#define DMA6_INT 0x40 /* DMA6 pending interrupt */
-#define nDMA6_INT 0x0
#define DMA7_INT 0x80 /* DMA7 pending interrupt */
-#define nDMA7_INT 0x0
/* Bit masks for USB_DMAxCONTROL */
#define DMA_ENA 0x1 /* DMA enable */
-#define nDMA_ENA 0x0
#define DIRECTION 0x2 /* direction of DMA transfer */
-#define nDIRECTION 0x0
#define MODE 0x4 /* DMA Bus error */
-#define nMODE 0x0
#define INT_ENA 0x8 /* Interrupt enable */
-#define nINT_ENA 0x0
#define EPNUM 0xf0 /* EP number */
#define BUSERROR 0x100 /* DMA Bus error */
-#define nBUSERROR 0x0
/* Bit masks for USB_DMAxADDRHIGH */
diff --git a/include/asm-blackfin/mach-bf548/defBF544.h b/include/asm-blackfin/mach-bf548/defBF544.h
index 8fc77ea12aa..dd955dcd39b 100644
--- a/include/asm-blackfin/mach-bf548/defBF544.h
+++ b/include/asm-blackfin/mach-bf548/defBF544.h
@@ -538,21 +538,13 @@
/* Bit masks for PIXC_CTL */
#define PIXC_EN 0x1 /* Pixel Compositor Enable */
-#define nPIXC_EN 0x0
#define OVR_A_EN 0x2 /* Overlay A Enable */
-#define nOVR_A_EN 0x0
#define OVR_B_EN 0x4 /* Overlay B Enable */
-#define nOVR_B_EN 0x0
#define IMG_FORM 0x8 /* Image Data Format */
-#define nIMG_FORM 0x0
#define OVR_FORM 0x10 /* Overlay Data Format */
-#define nOVR_FORM 0x0
#define OUT_FORM 0x20 /* Output Data Format */
-#define nOUT_FORM 0x0
#define UDS_MOD 0x40 /* Resampling Mode */
-#define nUDS_MOD 0x0
#define TC_EN 0x80 /* Transparent Color Enable */
-#define nTC_EN 0x0
#define IMG_STAT 0x300 /* Image FIFO Status */
#define OVR_STAT 0xc00 /* Overlay FIFO Status */
#define WM_LVL 0x3000 /* FIFO Watermark Level */
@@ -600,13 +592,9 @@
/* Bit masks for PIXC_INTRSTAT */
#define OVR_INT_EN 0x1 /* Interrupt at End of Last Valid Overlay */
-#define nOVR_INT_EN 0x0
#define FRM_INT_EN 0x2 /* Interrupt at End of Frame */
-#define nFRM_INT_EN 0x0
#define OVR_INT_STAT 0x4 /* Overlay Interrupt Status */
-#define nOVR_INT_STAT 0x0
#define FRM_INT_STAT 0x8 /* Frame Interrupt Status */
-#define nFRM_INT_STAT 0x0
/* Bit masks for PIXC_RYCON */
@@ -614,7 +602,6 @@
#define A12 0xffc00 /* A12 in the Coefficient Matrix */
#define A13 0x3ff00000 /* A13 in the Coefficient Matrix */
#define RY_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nRY_MULT4 0x0
/* Bit masks for PIXC_GUCON */
@@ -622,7 +609,6 @@
#define A22 0xffc00 /* A22 in the Coefficient Matrix */
#define A23 0x3ff00000 /* A23 in the Coefficient Matrix */
#define GU_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nGU_MULT4 0x0
/* Bit masks for PIXC_BVCON */
@@ -630,7 +616,6 @@
#define A32 0xffc00 /* A32 in the Coefficient Matrix */
#define A33 0x3ff00000 /* A33 in the Coefficient Matrix */
#define BV_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nBV_MULT4 0x0
/* Bit masks for PIXC_CCBIAS */
@@ -647,48 +632,28 @@
/* Bit masks for HOST_CONTROL */
#define HOST_EN 0x1 /* Host Enable */
-#define nHOST_EN 0x0
#define HOST_END 0x2 /* Host Endianess */
-#define nHOST_END 0x0
#define DATA_SIZE 0x4 /* Data Size */
-#define nDATA_SIZE 0x0
#define HOST_RST 0x8 /* Host Reset */
-#define nHOST_RST 0x0
#define HRDY_OVR 0x20 /* Host Ready Override */
-#define nHRDY_OVR 0x0
#define INT_MODE 0x40 /* Interrupt Mode */
-#define nINT_MODE 0x0
#define BT_EN 0x80 /* Bus Timeout Enable */
-#define nBT_EN 0x0
#define EHW 0x100 /* Enable Host Write */
-#define nEHW 0x0
#define EHR 0x200 /* Enable Host Read */
-#define nEHR 0x0
#define BDR 0x400 /* Burst DMA Requests */
-#define nBDR 0x0
/* Bit masks for HOST_STATUS */
#define READY 0x1 /* DMA Ready */
-#define nREADY 0x0
#define FIFOFULL 0x2 /* FIFO Full */
-#define nFIFOFULL 0x0
#define FIFOEMPTY 0x4 /* FIFO Empty */
-#define nFIFOEMPTY 0x0
#define COMPLETE 0x8 /* DMA Complete */
-#define nCOMPLETE 0x0
#define HSHK 0x10 /* Host Handshake */
-#define nHSHK 0x0
#define TIMEOUT 0x20 /* Host Timeout */
-#define nTIMEOUT 0x0
#define HIRQ 0x40 /* Host Interrupt Request */
-#define nHIRQ 0x0
#define ALLOW_CNFG 0x80 /* Allow New Configuration */
-#define nALLOW_CNFG 0x0
#define DMA_DIR 0x100 /* DMA Direction */
-#define nDMA_DIR 0x0
#define BTE 0x200 /* Bus Timeout Enabled */
-#define nBTE 0x0
/* Bit masks for HOST_TIMEOUT */
@@ -697,67 +662,42 @@
/* Bit masks for TIMER_ENABLE1 */
#define TIMEN8 0x1 /* Timer 8 Enable */
-#define nTIMEN8 0x0
#define TIMEN9 0x2 /* Timer 9 Enable */
-#define nTIMEN9 0x0
#define TIMEN10 0x4 /* Timer 10 Enable */
-#define nTIMEN10 0x0
/* Bit masks for TIMER_DISABLE1 */
#define TIMDIS8 0x1 /* Timer 8 Disable */
-#define nTIMDIS8 0x0
#define TIMDIS9 0x2 /* Timer 9 Disable */
-#define nTIMDIS9 0x0
#define TIMDIS10 0x4 /* Timer 10 Disable */
-#define nTIMDIS10 0x0
/* Bit masks for TIMER_STATUS1 */
#define TIMIL8 0x1 /* Timer 8 Interrupt */
-#define nTIMIL8 0x0
#define TIMIL9 0x2 /* Timer 9 Interrupt */
-#define nTIMIL9 0x0
#define TIMIL10 0x4 /* Timer 10 Interrupt */
-#define nTIMIL10 0x0
#define TOVF_ERR8 0x10 /* Timer 8 Counter Overflow */
-#define nTOVF_ERR8 0x0
#define TOVF_ERR9 0x20 /* Timer 9 Counter Overflow */
-#define nTOVF_ERR9 0x0
#define TOVF_ERR10 0x40 /* Timer 10 Counter Overflow */
-#define nTOVF_ERR10 0x0
#define TRUN8 0x1000 /* Timer 8 Slave Enable Status */
-#define nTRUN8 0x0
#define TRUN9 0x2000 /* Timer 9 Slave Enable Status */
-#define nTRUN9 0x0
#define TRUN10 0x4000 /* Timer 10 Slave Enable Status */
-#define nTRUN10 0x0
/* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
/* Bit masks for HMDMAx_CONTROL */
#define HMDMAEN 0x1 /* Handshake MDMA Enable */
-#define nHMDMAEN 0x0
#define REP 0x2 /* Handshake MDMA Request Polarity */
-#define nREP 0x0
#define UTE 0x8 /* Urgency Threshold Enable */
-#define nUTE 0x0
#define OIE 0x10 /* Overflow Interrupt Enable */
-#define nOIE 0x0
#define BDIE 0x20 /* Block Done Interrupt Enable */
-#define nBDIE 0x0
#define MBDI 0x40 /* Mask Block Done Interrupt */
-#define nMBDI 0x0
#define DRQ 0x300 /* Handshake MDMA Request Type */
#define RBC 0x1000 /* Force Reload of BCOUNT */
-#define nRBC 0x0
#define PS 0x2000 /* Pin Status */
-#define nPS 0x0
#define OI 0x4000 /* Overflow Interrupt Generated */
-#define nOI 0x0
#define BDI 0x8000 /* Block Done Interrupt Generated */
-#define nBDI 0x0
/* ******************************************* */
/* MULTI BIT MACRO ENUMERATIONS */
diff --git a/include/asm-blackfin/mach-bf548/defBF548.h b/include/asm-blackfin/mach-bf548/defBF548.h
index d9e3062a911..8d4214e0807 100644
--- a/include/asm-blackfin/mach-bf548/defBF548.h
+++ b/include/asm-blackfin/mach-bf548/defBF548.h
@@ -899,21 +899,13 @@
/* Bit masks for PIXC_CTL */
#define PIXC_EN 0x1 /* Pixel Compositor Enable */
-#define nPIXC_EN 0x0
#define OVR_A_EN 0x2 /* Overlay A Enable */
-#define nOVR_A_EN 0x0
#define OVR_B_EN 0x4 /* Overlay B Enable */
-#define nOVR_B_EN 0x0
#define IMG_FORM 0x8 /* Image Data Format */
-#define nIMG_FORM 0x0
#define OVR_FORM 0x10 /* Overlay Data Format */
-#define nOVR_FORM 0x0
#define OUT_FORM 0x20 /* Output Data Format */
-#define nOUT_FORM 0x0
#define UDS_MOD 0x40 /* Resampling Mode */
-#define nUDS_MOD 0x0
#define TC_EN 0x80 /* Transparent Color Enable */
-#define nTC_EN 0x0
#define IMG_STAT 0x300 /* Image FIFO Status */
#define OVR_STAT 0xc00 /* Overlay FIFO Status */
#define WM_LVL 0x3000 /* FIFO Watermark Level */
@@ -961,13 +953,9 @@
/* Bit masks for PIXC_INTRSTAT */
#define OVR_INT_EN 0x1 /* Interrupt at End of Last Valid Overlay */
-#define nOVR_INT_EN 0x0
#define FRM_INT_EN 0x2 /* Interrupt at End of Frame */
-#define nFRM_INT_EN 0x0
#define OVR_INT_STAT 0x4 /* Overlay Interrupt Status */
-#define nOVR_INT_STAT 0x0
#define FRM_INT_STAT 0x8 /* Frame Interrupt Status */
-#define nFRM_INT_STAT 0x0
/* Bit masks for PIXC_RYCON */
@@ -975,7 +963,6 @@
#define A12 0xffc00 /* A12 in the Coefficient Matrix */
#define A13 0x3ff00000 /* A13 in the Coefficient Matrix */
#define RY_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nRY_MULT4 0x0
/* Bit masks for PIXC_GUCON */
@@ -983,7 +970,6 @@
#define A22 0xffc00 /* A22 in the Coefficient Matrix */
#define A23 0x3ff00000 /* A23 in the Coefficient Matrix */
#define GU_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nGU_MULT4 0x0
/* Bit masks for PIXC_BVCON */
@@ -991,7 +977,6 @@
#define A32 0xffc00 /* A32 in the Coefficient Matrix */
#define A33 0x3ff00000 /* A33 in the Coefficient Matrix */
#define BV_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nBV_MULT4 0x0
/* Bit masks for PIXC_CCBIAS */
@@ -1008,48 +993,28 @@
/* Bit masks for HOST_CONTROL */
#define HOST_EN 0x1 /* Host Enable */
-#define nHOST_EN 0x0
#define HOST_END 0x2 /* Host Endianess */
-#define nHOST_END 0x0
#define DATA_SIZE 0x4 /* Data Size */
-#define nDATA_SIZE 0x0
#define HOST_RST 0x8 /* Host Reset */
-#define nHOST_RST 0x0
#define HRDY_OVR 0x20 /* Host Ready Override */
-#define nHRDY_OVR 0x0
#define INT_MODE 0x40 /* Interrupt Mode */
-#define nINT_MODE 0x0
#define BT_EN 0x80 /* Bus Timeout Enable */
-#define nBT_EN 0x0
#define EHW 0x100 /* Enable Host Write */
-#define nEHW 0x0
#define EHR 0x200 /* Enable Host Read */
-#define nEHR 0x0
#define BDR 0x400 /* Burst DMA Requests */
-#define nBDR 0x0
/* Bit masks for HOST_STATUS */
#define READY 0x1 /* DMA Ready */
-#define nREADY 0x0
#define FIFOFULL 0x2 /* FIFO Full */
-#define nFIFOFULL 0x0
#define FIFOEMPTY 0x4 /* FIFO Empty */
-#define nFIFOEMPTY 0x0
#define COMPLETE 0x8 /* DMA Complete */
-#define nCOMPLETE 0x0
#define HSHK 0x10 /* Host Handshake */
-#define nHSHK 0x0
#define TIMEOUT 0x20 /* Host Timeout */
-#define nTIMEOUT 0x0
#define HIRQ 0x40 /* Host Interrupt Request */
-#define nHIRQ 0x0
#define ALLOW_CNFG 0x80 /* Allow New Configuration */
-#define nALLOW_CNFG 0x0
#define DMA_DIR 0x100 /* DMA Direction */
-#define nDMA_DIR 0x0
#define BTE 0x200 /* Bus Timeout Enabled */
-#define nBTE 0x0
/* Bit masks for HOST_TIMEOUT */
@@ -1058,7 +1023,6 @@
/* Bit masks for KPAD_CTL */
#define KPAD_EN 0x1 /* Keypad Enable */
-#define nKPAD_EN 0x0
#define KPAD_IRQMODE 0x6 /* Key Press Interrupt Enable */
#define KPAD_ROWEN 0x1c00 /* Row Enable Width */
#define KPAD_COLEN 0xe000 /* Column Enable Width */
@@ -1080,29 +1044,21 @@
/* Bit masks for KPAD_STAT */
#define KPAD_IRQ 0x1 /* Keypad Interrupt Status */
-#define nKPAD_IRQ 0x0
#define KPAD_MROWCOL 0x6 /* Multiple Row/Column Keypress Status */
#define KPAD_PRESSED 0x8 /* Key press current status */
-#define nKPAD_PRESSED 0x0
/* Bit masks for KPAD_SOFTEVAL */
#define KPAD_SOFTEVAL_E 0x2 /* Software Programmable Force Evaluate */
-#define nKPAD_SOFTEVAL_E 0x0
/* Bit masks for SDH_COMMAND */
#define CMD_IDX 0x3f /* Command Index */
#define CMD_RSP 0x40 /* Response */
-#define nCMD_RSP 0x0
#define CMD_L_RSP 0x80 /* Long Response */
-#define nCMD_L_RSP 0x0
#define CMD_INT_E 0x100 /* Command Interrupt */
-#define nCMD_INT_E 0x0
#define CMD_PEND_E 0x200 /* Command Pending */
-#define nCMD_PEND_E 0x0
#define CMD_E 0x400 /* Command Enable */
-#define nCMD_E 0x0
/* Bit masks for SDH_PWR_CTL */
@@ -1111,21 +1067,15 @@
#define TBD 0x3c /* TBD */
#endif
#define SD_CMD_OD 0x40 /* Open Drain Output */
-#define nSD_CMD_OD 0x0
#define ROD_CTL 0x80 /* Rod Control */
-#define nROD_CTL 0x0
/* Bit masks for SDH_CLK_CTL */
#define CLKDIV 0xff /* MC_CLK Divisor */
#define CLK_E 0x100 /* MC_CLK Bus Clock Enable */
-#define nCLK_E 0x0
#define PWR_SV_E 0x200 /* Power Save Enable */
-#define nPWR_SV_E 0x0
#define CLKDIV_BYPASS 0x400 /* Bypass Divisor */
-#define nCLKDIV_BYPASS 0x0
#define WIDE_BUS 0x800 /* Wide Bus Mode Enable */
-#define nWIDE_BUS 0x0
/* Bit masks for SDH_RESP_CMD */
@@ -1134,133 +1084,74 @@
/* Bit masks for SDH_DATA_CTL */
#define DTX_E 0x1 /* Data Transfer Enable */
-#define nDTX_E 0x0
#define DTX_DIR 0x2 /* Data Transfer Direction */
-#define nDTX_DIR 0x0
#define DTX_MODE 0x4 /* Data Transfer Mode */
-#define nDTX_MODE 0x0
#define DTX_DMA_E 0x8 /* Data Transfer DMA Enable */
-#define nDTX_DMA_E 0x0
#define DTX_BLK_LGTH 0xf0 /* Data Transfer Block Length */
/* Bit masks for SDH_STATUS */
#define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */
-#define nCMD_CRC_FAIL 0x0
#define DAT_CRC_FAIL 0x2 /* Data CRC Fail */
-#define nDAT_CRC_FAIL 0x0
#define CMD_TIMEOUT 0x4 /* CMD Time Out */
-#define nCMD_TIMEOUT 0x0
#define DAT_TIMEOUT 0x8 /* Data Time Out */
-#define nDAT_TIMEOUT 0x0
#define TX_UNDERRUN 0x10 /* Transmit Underrun */
-#define nTX_UNDERRUN 0x0
#define RX_OVERRUN 0x20 /* Receive Overrun */
-#define nRX_OVERRUN 0x0
#define CMD_RESP_END 0x40 /* CMD Response End */
-#define nCMD_RESP_END 0x0
#define CMD_SENT 0x80 /* CMD Sent */
-#define nCMD_SENT 0x0
#define DAT_END 0x100 /* Data End */
-#define nDAT_END 0x0
#define START_BIT_ERR 0x200 /* Start Bit Error */
-#define nSTART_BIT_ERR 0x0
#define DAT_BLK_END 0x400 /* Data Block End */
-#define nDAT_BLK_END 0x0
#define CMD_ACT 0x800 /* CMD Active */
-#define nCMD_ACT 0x0
#define TX_ACT 0x1000 /* Transmit Active */
-#define nTX_ACT 0x0
#define RX_ACT 0x2000 /* Receive Active */
-#define nRX_ACT 0x0
#define TX_FIFO_STAT 0x4000 /* Transmit FIFO Status */
-#define nTX_FIFO_STAT 0x0
#define RX_FIFO_STAT 0x8000 /* Receive FIFO Status */
-#define nRX_FIFO_STAT 0x0
#define TX_FIFO_FULL 0x10000 /* Transmit FIFO Full */
-#define nTX_FIFO_FULL 0x0
#define RX_FIFO_FULL 0x20000 /* Receive FIFO Full */
-#define nRX_FIFO_FULL 0x0
#define TX_FIFO_ZERO 0x40000 /* Transmit FIFO Empty */
-#define nTX_FIFO_ZERO 0x0
#define RX_DAT_ZERO 0x80000 /* Receive FIFO Empty */
-#define nRX_DAT_ZERO 0x0
#define TX_DAT_RDY 0x100000 /* Transmit Data Available */
-#define nTX_DAT_RDY 0x0
#define RX_FIFO_RDY 0x200000 /* Receive Data Available */
-#define nRX_FIFO_RDY 0x0
/* Bit masks for SDH_STATUS_CLR */
#define CMD_CRC_FAIL_STAT 0x1 /* CMD CRC Fail Status */
-#define nCMD_CRC_FAIL_STAT 0x0
#define DAT_CRC_FAIL_STAT 0x2 /* Data CRC Fail Status */
-#define nDAT_CRC_FAIL_STAT 0x0
#define CMD_TIMEOUT_STAT 0x4 /* CMD Time Out Status */
-#define nCMD_TIMEOUT_STAT 0x0
#define DAT_TIMEOUT_STAT 0x8 /* Data Time Out status */
-#define nDAT_TIMEOUT_STAT 0x0
#define TX_UNDERRUN_STAT 0x10 /* Transmit Underrun Status */
-#define nTX_UNDERRUN_STAT 0x0
#define RX_OVERRUN_STAT 0x20 /* Receive Overrun Status */
-#define nRX_OVERRUN_STAT 0x0
#define CMD_RESP_END_STAT 0x40 /* CMD Response End Status */
-#define nCMD_RESP_END_STAT 0x0
#define CMD_SENT_STAT 0x80 /* CMD Sent Status */
-#define nCMD_SENT_STAT 0x0
#define DAT_END_STAT 0x100 /* Data End Status */
-#define nDAT_END_STAT 0x0
#define START_BIT_ERR_STAT 0x200 /* Start Bit Error Status */
-#define nSTART_BIT_ERR_STAT 0x0
#define DAT_BLK_END_STAT 0x400 /* Data Block End Status */
-#define nDAT_BLK_END_STAT 0x0
/* Bit masks for SDH_MASK0 */
#define CMD_CRC_FAIL_MASK 0x1 /* CMD CRC Fail Mask */
-#define nCMD_CRC_FAIL_MASK 0x0
#define DAT_CRC_FAIL_MASK 0x2 /* Data CRC Fail Mask */
-#define nDAT_CRC_FAIL_MASK 0x0
#define CMD_TIMEOUT_MASK 0x4 /* CMD Time Out Mask */
-#define nCMD_TIMEOUT_MASK 0x0
#define DAT_TIMEOUT_MASK 0x8 /* Data Time Out Mask */
-#define nDAT_TIMEOUT_MASK 0x0
#define TX_UNDERRUN_MASK 0x10 /* Transmit Underrun Mask */
-#define nTX_UNDERRUN_MASK 0x0
#define RX_OVERRUN_MASK 0x20 /* Receive Overrun Mask */
-#define nRX_OVERRUN_MASK 0x0
#define CMD_RESP_END_MASK 0x40 /* CMD Response End Mask */
-#define nCMD_RESP_END_MASK 0x0
#define CMD_SENT_MASK 0x80 /* CMD Sent Mask */
-#define nCMD_SENT_MASK 0x0
#define DAT_END_MASK 0x100 /* Data End Mask */
-#define nDAT_END_MASK 0x0
#define START_BIT_ERR_MASK 0x200 /* Start Bit Error Mask */
-#define nSTART_BIT_ERR_MASK 0x0
#define DAT_BLK_END_MASK 0x400 /* Data Block End Mask */
-#define nDAT_BLK_END_MASK 0x0
#define CMD_ACT_MASK 0x800 /* CMD Active Mask */
-#define nCMD_ACT_MASK 0x0
#define TX_ACT_MASK 0x1000 /* Transmit Active Mask */
-#define nTX_ACT_MASK 0x0
#define RX_ACT_MASK 0x2000 /* Receive Active Mask */
-#define nRX_ACT_MASK 0x0
#define TX_FIFO_STAT_MASK 0x4000 /* Transmit FIFO Status Mask */
-#define nTX_FIFO_STAT_MASK 0x0
#define RX_FIFO_STAT_MASK 0x8000 /* Receive FIFO Status Mask */
-#define nRX_FIFO_STAT_MASK 0x0
#define TX_FIFO_FULL_MASK 0x10000 /* Transmit FIFO Full Mask */
-#define nTX_FIFO_FULL_MASK 0x0
#define RX_FIFO_FULL_MASK 0x20000 /* Receive FIFO Full Mask */
-#define nRX_FIFO_FULL_MASK 0x0
#define TX_FIFO_ZERO_MASK 0x40000 /* Transmit FIFO Empty Mask */
-#define nTX_FIFO_ZERO_MASK 0x0
#define RX_DAT_ZERO_MASK 0x80000 /* Receive FIFO Empty Mask */
-#define nRX_DAT_ZERO_MASK 0x0
#define TX_DAT_RDY_MASK 0x100000 /* Transmit Data Available Mask */
-#define nTX_DAT_RDY_MASK 0x0
#define RX_FIFO_RDY_MASK 0x200000 /* Receive Data Available Mask */
-#define nRX_FIFO_RDY_MASK 0x0
/* Bit masks for SDH_FIFO_CNT */
@@ -1269,73 +1160,47 @@
/* Bit masks for SDH_E_STATUS */
#define SDIO_INT_DET 0x2 /* SDIO Int Detected */
-#define nSDIO_INT_DET 0x0
#define SD_CARD_DET 0x10 /* SD Card Detect */
-#define nSD_CARD_DET 0x0
/* Bit masks for SDH_E_MASK */
#define SDIO_MSK 0x2 /* Mask SDIO Int Detected */
-#define nSDIO_MSK 0x0
#define SCD_MSK 0x40 /* Mask Card Detect */
-#define nSCD_MSK 0x0
/* Bit masks for SDH_CFG */
#define CLKS_EN 0x1 /* Clocks Enable */
-#define nCLKS_EN 0x0
#define SD4E 0x4 /* SDIO 4-Bit Enable */
-#define nSD4E 0x0
#define MWE 0x8 /* Moving Window Enable */
-#define nMWE 0x0
#define SD_RST 0x10 /* SDMMC Reset */
-#define nSD_RST 0x0
#define PUP_SDDAT 0x20 /* Pull-up SD_DAT */
-#define nPUP_SDDAT 0x0
#define PUP_SDDAT3 0x40 /* Pull-up SD_DAT3 */
-#define nPUP_SDDAT3 0x0
#define PD_SDDAT3 0x80 /* Pull-down SD_DAT3 */
-#define nPD_SDDAT3 0x0
/* Bit masks for SDH_RD_WAIT_EN */
#define RWR 0x1 /* Read Wait Request */
-#define nRWR 0x0
/* Bit masks for ATAPI_CONTROL */
#define PIO_START 0x1 /* Start PIO/Reg Op */
-#define nPIO_START 0x0
#define MULTI_START 0x2 /* Start Multi-DMA Op */
-#define nMULTI_START 0x0
#define ULTRA_START 0x4 /* Start Ultra-DMA Op */
-#define nULTRA_START 0x0
#define XFER_DIR 0x8 /* Transfer Direction */
-#define nXFER_DIR 0x0
#define IORDY_EN 0x10 /* IORDY Enable */
-#define nIORDY_EN 0x0
#define FIFO_FLUSH 0x20 /* Flush FIFOs */
-#define nFIFO_FLUSH 0x0
#define SOFT_RST 0x40 /* Soft Reset */
-#define nSOFT_RST 0x0
#define DEV_RST 0x80 /* Device Reset */
-#define nDEV_RST 0x0
#define TFRCNT_RST 0x100 /* Trans Count Reset */
-#define nTFRCNT_RST 0x0
#define END_ON_TERM 0x200 /* End/Terminate Select */
-#define nEND_ON_TERM 0x0
#define PIO_USE_DMA 0x400 /* PIO-DMA Enable */
-#define nPIO_USE_DMA 0x0
#define UDMAIN_FIFO_THRS 0xf000 /* Ultra DMA-IN FIFO Threshold */
/* Bit masks for ATAPI_STATUS */
#define PIO_XFER_ON 0x1 /* PIO transfer in progress */
-#define nPIO_XFER_ON 0x0
#define MULTI_XFER_ON 0x2 /* Multi-word DMA transfer in progress */
-#define nMULTI_XFER_ON 0x0
#define ULTRA_XFER_ON 0x4 /* Ultra DMA transfer in progress */
-#define nULTRA_XFER_ON 0x0
#define ULTRA_IN_FL 0xf0 /* Ultra DMA Input FIFO Level */
/* Bit masks for ATAPI_DEV_ADDR */
@@ -1345,66 +1210,39 @@
/* Bit masks for ATAPI_INT_MASK */
#define ATAPI_DEV_INT_MASK 0x1 /* Device interrupt mask */
-#define nATAPI_DEV_INT_MASK 0x0
#define PIO_DONE_MASK 0x2 /* PIO transfer done interrupt mask */
-#define nPIO_DONE_MASK 0x0
#define MULTI_DONE_MASK 0x4 /* Multi-DMA transfer done interrupt mask */
-#define nMULTI_DONE_MASK 0x0
#define UDMAIN_DONE_MASK 0x8 /* Ultra-DMA in transfer done interrupt mask */
-#define nUDMAIN_DONE_MASK 0x0
#define UDMAOUT_DONE_MASK 0x10 /* Ultra-DMA out transfer done interrupt mask */
-#define nUDMAOUT_DONE_MASK 0x0
#define HOST_TERM_XFER_MASK 0x20 /* Host terminate current transfer interrupt mask */
-#define nHOST_TERM_XFER_MASK 0x0
#define MULTI_TERM_MASK 0x40 /* Device terminate Multi-DMA transfer interrupt mask */
-#define nMULTI_TERM_MASK 0x0
#define UDMAIN_TERM_MASK 0x80 /* Device terminate Ultra-DMA-in transfer interrupt mask */
-#define nUDMAIN_TERM_MASK 0x0
#define UDMAOUT_TERM_MASK 0x100 /* Device terminate Ultra-DMA-out transfer interrupt mask */
-#define nUDMAOUT_TERM_MASK 0x0
/* Bit masks for ATAPI_INT_STATUS */
#define ATAPI_DEV_INT 0x1 /* Device interrupt status */
-#define nATAPI_DEV_INT 0x0
#define PIO_DONE_INT 0x2 /* PIO transfer done interrupt status */
-#define nPIO_DONE_INT 0x0
#define MULTI_DONE_INT 0x4 /* Multi-DMA transfer done interrupt status */
-#define nMULTI_DONE_INT 0x0
#define UDMAIN_DONE_INT 0x8 /* Ultra-DMA in transfer done interrupt status */
-#define nUDMAIN_DONE_INT 0x0
#define UDMAOUT_DONE_INT 0x10 /* Ultra-DMA out transfer done interrupt status */
-#define nUDMAOUT_DONE_INT 0x0
#define HOST_TERM_XFER_INT 0x20 /* Host terminate current transfer interrupt status */
-#define nHOST_TERM_XFER_INT 0x0
#define MULTI_TERM_INT 0x40 /* Device terminate Multi-DMA transfer interrupt status */
-#define nMULTI_TERM_INT 0x0
#define UDMAIN_TERM_INT 0x80 /* Device terminate Ultra-DMA-in transfer interrupt status */
-#define nUDMAIN_TERM_INT 0x0
#define UDMAOUT_TERM_INT 0x100 /* Device terminate Ultra-DMA-out transfer interrupt status */
-#define nUDMAOUT_TERM_INT 0x0
/* Bit masks for ATAPI_LINE_STATUS */
#define ATAPI_INTR 0x1 /* Device interrupt to host line status */
-#define nATAPI_INTR 0x0
#define ATAPI_DASP 0x2 /* Device dasp to host line status */
-#define nATAPI_DASP 0x0
#define ATAPI_CS0N 0x4 /* ATAPI chip select 0 line status */
-#define nATAPI_CS0N 0x0
#define ATAPI_CS1N 0x8 /* ATAPI chip select 1 line status */
-#define nATAPI_CS1N 0x0
#define ATAPI_ADDR 0x70 /* ATAPI address line status */
#define ATAPI_DMAREQ 0x80 /* ATAPI DMA request line status */
-#define nATAPI_DMAREQ 0x0
#define ATAPI_DMAACKN 0x100 /* ATAPI DMA acknowledge line status */
-#define nATAPI_DMAACKN 0x0
#define ATAPI_DIOWN 0x200 /* ATAPI write line status */
-#define nATAPI_DIOWN 0x0
#define ATAPI_DIORN 0x400 /* ATAPI read line status */
-#define nATAPI_DIORN 0x0
#define ATAPI_IORDY 0x800 /* ATAPI IORDY line status */
-#define nATAPI_IORDY 0x0
/* Bit masks for ATAPI_SM_STATE */
@@ -1416,7 +1254,6 @@
/* Bit masks for ATAPI_TERMINATE */
#define ATAPI_HOST_TERM 0x1 /* Host terminationation */
-#define nATAPI_HOST_TERM 0x0
/* Bit masks for ATAPI_REG_TIM_0 */
@@ -1471,41 +1308,26 @@
/* Bit masks for TIMER_ENABLE1 */
#define TIMEN8 0x1 /* Timer 8 Enable */
-#define nTIMEN8 0x0
#define TIMEN9 0x2 /* Timer 9 Enable */
-#define nTIMEN9 0x0
#define TIMEN10 0x4 /* Timer 10 Enable */
-#define nTIMEN10 0x0
/* Bit masks for TIMER_DISABLE1 */
#define TIMDIS8 0x1 /* Timer 8 Disable */
-#define nTIMDIS8 0x0
#define TIMDIS9 0x2 /* Timer 9 Disable */
-#define nTIMDIS9 0x0
#define TIMDIS10 0x4 /* Timer 10 Disable */
-#define nTIMDIS10 0x0
/* Bit masks for TIMER_STATUS1 */
#define TIMIL8 0x1 /* Timer 8 Interrupt */
-#define nTIMIL8 0x0
#define TIMIL9 0x2 /* Timer 9 Interrupt */
-#define nTIMIL9 0x0
#define TIMIL10 0x4 /* Timer 10 Interrupt */
-#define nTIMIL10 0x0
#define TOVF_ERR8 0x10 /* Timer 8 Counter Overflow */
-#define nTOVF_ERR8 0x0
#define TOVF_ERR9 0x20 /* Timer 9 Counter Overflow */
-#define nTOVF_ERR9 0x0
#define TOVF_ERR10 0x40 /* Timer 10 Counter Overflow */
-#define nTOVF_ERR10 0x0
#define TRUN8 0x1000 /* Timer 8 Slave Enable Status */
-#define nTRUN8 0x0
#define TRUN9 0x2000 /* Timer 9 Slave Enable Status */
-#define nTRUN9 0x0
#define TRUN10 0x4000 /* Timer 10 Slave Enable Status */
-#define nTRUN10 0x0
/* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
@@ -1516,131 +1338,77 @@
/* Bit masks for USB_POWER */
#define ENABLE_SUSPENDM 0x1 /* enable SuspendM output */
-#define nENABLE_SUSPENDM 0x0
#define SUSPEND_MODE 0x2 /* Suspend Mode indicator */
-#define nSUSPEND_MODE 0x0
#define RESUME_MODE 0x4 /* DMA Mode */
-#define nRESUME_MODE 0x0
#define RESET 0x8 /* Reset indicator */
-#define nRESET 0x0
#define HS_MODE 0x10 /* High Speed mode indicator */
-#define nHS_MODE 0x0
#define HS_ENABLE 0x20 /* high Speed Enable */
-#define nHS_ENABLE 0x0
#define SOFT_CONN 0x40 /* Soft connect */
-#define nSOFT_CONN 0x0
#define ISO_UPDATE 0x80 /* Isochronous update */
-#define nISO_UPDATE 0x0
/* Bit masks for USB_INTRTX */
#define EP0_TX 0x1 /* Tx Endpoint 0 interrupt */
-#define nEP0_TX 0x0
#define EP1_TX 0x2 /* Tx Endpoint 1 interrupt */
-#define nEP1_TX 0x0
#define EP2_TX 0x4 /* Tx Endpoint 2 interrupt */
-#define nEP2_TX 0x0
#define EP3_TX 0x8 /* Tx Endpoint 3 interrupt */
-#define nEP3_TX 0x0
#define EP4_TX 0x10 /* Tx Endpoint 4 interrupt */
-#define nEP4_TX 0x0
#define EP5_TX 0x20 /* Tx Endpoint 5 interrupt */
-#define nEP5_TX 0x0
#define EP6_TX 0x40 /* Tx Endpoint 6 interrupt */
-#define nEP6_TX 0x0
#define EP7_TX 0x80 /* Tx Endpoint 7 interrupt */
-#define nEP7_TX 0x0
/* Bit masks for USB_INTRRX */
#define EP1_RX 0x2 /* Rx Endpoint 1 interrupt */
-#define nEP1_RX 0x0
#define EP2_RX 0x4 /* Rx Endpoint 2 interrupt */
-#define nEP2_RX 0x0
#define EP3_RX 0x8 /* Rx Endpoint 3 interrupt */
-#define nEP3_RX 0x0
#define EP4_RX 0x10 /* Rx Endpoint 4 interrupt */
-#define nEP4_RX 0x0
#define EP5_RX 0x20 /* Rx Endpoint 5 interrupt */
-#define nEP5_RX 0x0
#define EP6_RX 0x40 /* Rx Endpoint 6 interrupt */
-#define nEP6_RX 0x0
#define EP7_RX 0x80 /* Rx Endpoint 7 interrupt */
-#define nEP7_RX 0x0
/* Bit masks for USB_INTRTXE */
#define EP0_TX_E 0x1 /* Endpoint 0 interrupt Enable */
-#define nEP0_TX_E 0x0
#define EP1_TX_E 0x2 /* Tx Endpoint 1 interrupt Enable */
-#define nEP1_TX_E 0x0
#define EP2_TX_E 0x4 /* Tx Endpoint 2 interrupt Enable */
-#define nEP2_TX_E 0x0
#define EP3_TX_E 0x8 /* Tx Endpoint 3 interrupt Enable */
-#define nEP3_TX_E 0x0
#define EP4_TX_E 0x10 /* Tx Endpoint 4 interrupt Enable */
-#define nEP4_TX_E 0x0
#define EP5_TX_E 0x20 /* Tx Endpoint 5 interrupt Enable */
-#define nEP5_TX_E 0x0
#define EP6_TX_E 0x40 /* Tx Endpoint 6 interrupt Enable */
-#define nEP6_TX_E 0x0
#define EP7_TX_E 0x80 /* Tx Endpoint 7 interrupt Enable */
-#define nEP7_TX_E 0x0
/* Bit masks for USB_INTRRXE */
#define EP1_RX_E 0x2 /* Rx Endpoint 1 interrupt Enable */
-#define nEP1_RX_E 0x0
#define EP2_RX_E 0x4 /* Rx Endpoint 2 interrupt Enable */
-#define nEP2_RX_E 0x0
#define EP3_RX_E 0x8 /* Rx Endpoint 3 interrupt Enable */
-#define nEP3_RX_E 0x0
#define EP4_RX_E 0x10 /* Rx Endpoint 4 interrupt Enable */
-#define nEP4_RX_E 0x0
#define EP5_RX_E 0x20 /* Rx Endpoint 5 interrupt Enable */
-#define nEP5_RX_E 0x0
#define EP6_RX_E 0x40 /* Rx Endpoint 6 interrupt Enable */
-#define nEP6_RX_E 0x0
#define EP7_RX_E 0x80 /* Rx Endpoint 7 interrupt Enable */
-#define nEP7_RX_E 0x0
/* Bit masks for USB_INTRUSB */
#define SUSPEND_B 0x1 /* Suspend indicator */
-#define nSUSPEND_B 0x0
#define RESUME_B 0x2 /* Resume indicator */
-#define nRESUME_B 0x0
#define RESET_OR_BABLE_B 0x4 /* Reset/babble indicator */
-#define nRESET_OR_BABLE_B 0x0
#define SOF_B 0x8 /* Start of frame */
-#define nSOF_B 0x0
#define CONN_B 0x10 /* Connection indicator */
-#define nCONN_B 0x0
#define DISCON_B 0x20 /* Disconnect indicator */
-#define nDISCON_B 0x0
#define SESSION_REQ_B 0x40 /* Session Request */
-#define nSESSION_REQ_B 0x0
#define VBUS_ERROR_B 0x80 /* Vbus threshold indicator */
-#define nVBUS_ERROR_B 0x0
/* Bit masks for USB_INTRUSBE */
#define SUSPEND_BE 0x1 /* Suspend indicator int enable */
-#define nSUSPEND_BE 0x0
#define RESUME_BE 0x2 /* Resume indicator int enable */
-#define nRESUME_BE 0x0
#define RESET_OR_BABLE_BE 0x4 /* Reset/babble indicator int enable */
-#define nRESET_OR_BABLE_BE 0x0
#define SOF_BE 0x8 /* Start of frame int enable */
-#define nSOF_BE 0x0
#define CONN_BE 0x10 /* Connection indicator int enable */
-#define nCONN_BE 0x0
#define DISCON_BE 0x20 /* Disconnect indicator int enable */
-#define nDISCON_BE 0x0
#define SESSION_REQ_BE 0x40 /* Session Request int enable */
-#define nSESSION_REQ_BE 0x0
#define VBUS_ERROR_BE 0x80 /* Vbus threshold indicator int enable */
-#define nVBUS_ERROR_BE 0x0
/* Bit masks for USB_FRAME */
@@ -1653,117 +1421,67 @@
/* Bit masks for USB_GLOBAL_CTL */
#define GLOBAL_ENA 0x1 /* enables USB module */
-#define nGLOBAL_ENA 0x0
#define EP1_TX_ENA 0x2 /* Transmit endpoint 1 enable */
-#define nEP1_TX_ENA 0x0
#define EP2_TX_ENA 0x4 /* Transmit endpoint 2 enable */
-#define nEP2_TX_ENA 0x0
#define EP3_TX_ENA 0x8 /* Transmit endpoint 3 enable */
-#define nEP3_TX_ENA 0x0
#define EP4_TX_ENA 0x10 /* Transmit endpoint 4 enable */
-#define nEP4_TX_ENA 0x0
#define EP5_TX_ENA 0x20 /* Transmit endpoint 5 enable */
-#define nEP5_TX_ENA 0x0
#define EP6_TX_ENA 0x40 /* Transmit endpoint 6 enable */
-#define nEP6_TX_ENA 0x0
#define EP7_TX_ENA 0x80 /* Transmit endpoint 7 enable */
-#define nEP7_TX_ENA 0x0
#define EP1_RX_ENA 0x100 /* Receive endpoint 1 enable */
-#define nEP1_RX_ENA 0x0
#define EP2_RX_ENA 0x200 /* Receive endpoint 2 enable */
-#define nEP2_RX_ENA 0x0
#define EP3_RX_ENA 0x400 /* Receive endpoint 3 enable */
-#define nEP3_RX_ENA 0x0
#define EP4_RX_ENA 0x800 /* Receive endpoint 4 enable */
-#define nEP4_RX_ENA 0x0
#define EP5_RX_ENA 0x1000 /* Receive endpoint 5 enable */
-#define nEP5_RX_ENA 0x0
#define EP6_RX_ENA 0x2000 /* Receive endpoint 6 enable */
-#define nEP6_RX_ENA 0x0
#define EP7_RX_ENA 0x4000 /* Receive endpoint 7 enable */
-#define nEP7_RX_ENA 0x0
/* Bit masks for USB_OTG_DEV_CTL */
#define SESSION 0x1 /* session indicator */
-#define nSESSION 0x0
#define HOST_REQ 0x2 /* Host negotiation request */
-#define nHOST_REQ 0x0
#define HOST_MODE 0x4 /* indicates USBDRC is a host */
-#define nHOST_MODE 0x0
#define VBUS0 0x8 /* Vbus level indicator[0] */
-#define nVBUS0 0x0
#define VBUS1 0x10 /* Vbus level indicator[1] */
-#define nVBUS1 0x0
#define LSDEV 0x20 /* Low-speed indicator */
-#define nLSDEV 0x0
#define FSDEV 0x40 /* Full or High-speed indicator */
-#define nFSDEV 0x0
#define B_DEVICE 0x80 /* A' or 'B' device indicator */
-#define nB_DEVICE 0x0
/* Bit masks for USB_OTG_VBUS_IRQ */
#define DRIVE_VBUS_ON 0x1 /* indicator to drive VBUS control circuit */
-#define nDRIVE_VBUS_ON 0x0
#define DRIVE_VBUS_OFF 0x2 /* indicator to shut off charge pump */
-#define nDRIVE_VBUS_OFF 0x0
#define CHRG_VBUS_START 0x4 /* indicator for external circuit to start charging VBUS */
-#define nCHRG_VBUS_START 0x0
#define CHRG_VBUS_END 0x8 /* indicator for external circuit to end charging VBUS */
-#define nCHRG_VBUS_END 0x0
#define DISCHRG_VBUS_START 0x10 /* indicator to start discharging VBUS */
-#define nDISCHRG_VBUS_START 0x0
#define DISCHRG_VBUS_END 0x20 /* indicator to stop discharging VBUS */
-#define nDISCHRG_VBUS_END 0x0
/* Bit masks for USB_OTG_VBUS_MASK */
#define DRIVE_VBUS_ON_ENA 0x1 /* enable DRIVE_VBUS_ON interrupt */
-#define nDRIVE_VBUS_ON_ENA 0x0
#define DRIVE_VBUS_OFF_ENA 0x2 /* enable DRIVE_VBUS_OFF interrupt */
-#define nDRIVE_VBUS_OFF_ENA 0x0
#define CHRG_VBUS_START_ENA 0x4 /* enable CHRG_VBUS_START interrupt */
-#define nCHRG_VBUS_START_ENA 0x0
#define CHRG_VBUS_END_ENA 0x8 /* enable CHRG_VBUS_END interrupt */
-#define nCHRG_VBUS_END_ENA 0x0
#define DISCHRG_VBUS_START_ENA 0x10 /* enable DISCHRG_VBUS_START interrupt */
-#define nDISCHRG_VBUS_START_ENA 0x0
#define DISCHRG_VBUS_END_ENA 0x20 /* enable DISCHRG_VBUS_END interrupt */
-#define nDISCHRG_VBUS_END_ENA 0x0
/* Bit masks for USB_CSR0 */
#define RXPKTRDY 0x1 /* data packet receive indicator */
-#define nRXPKTRDY 0x0
#define TXPKTRDY 0x2 /* data packet in FIFO indicator */
-#define nTXPKTRDY 0x0
#define STALL_SENT 0x4 /* STALL handshake sent */
-#define nSTALL_SENT 0x0
#define DATAEND 0x8 /* Data end indicator */
-#define nDATAEND 0x0
#define SETUPEND 0x10 /* Setup end */
-#define nSETUPEND 0x0
#define SENDSTALL 0x20 /* Send STALL handshake */
-#define nSENDSTALL 0x0
#define SERVICED_RXPKTRDY 0x40 /* used to clear the RxPktRdy bit */
-#define nSERVICED_RXPKTRDY 0x0
#define SERVICED_SETUPEND 0x80 /* used to clear the SetupEnd bit */
-#define nSERVICED_SETUPEND 0x0
#define FLUSHFIFO 0x100 /* flush endpoint FIFO */
-#define nFLUSHFIFO 0x0
#define STALL_RECEIVED_H 0x4 /* STALL handshake received host mode */
-#define nSTALL_RECEIVED_H 0x0
#define SETUPPKT_H 0x8 /* send Setup token host mode */
-#define nSETUPPKT_H 0x0
#define ERROR_H 0x10 /* timeout error indicator host mode */
-#define nERROR_H 0x0
#define REQPKT_H 0x20 /* Request an IN transaction host mode */
-#define nREQPKT_H 0x0
#define STATUSPKT_H 0x40 /* Status stage transaction host mode */
-#define nSTATUSPKT_H 0x0
#define NAK_TIMEOUT_H 0x80 /* EP0 halted after a NAK host mode */
-#define nNAK_TIMEOUT_H 0x0
/* Bit masks for USB_COUNT0 */
@@ -1784,37 +1502,21 @@
/* Bit masks for USB_TXCSR */
#define TXPKTRDY_T 0x1 /* data packet in FIFO indicator */
-#define nTXPKTRDY_T 0x0
#define FIFO_NOT_EMPTY_T 0x2 /* FIFO not empty */
-#define nFIFO_NOT_EMPTY_T 0x0
#define UNDERRUN_T 0x4 /* TxPktRdy not set for an IN token */
-#define nUNDERRUN_T 0x0
#define FLUSHFIFO_T 0x8 /* flush endpoint FIFO */
-#define nFLUSHFIFO_T 0x0
#define STALL_SEND_T 0x10 /* issue a Stall handshake */
-#define nSTALL_SEND_T 0x0
#define STALL_SENT_T 0x20 /* Stall handshake transmitted */
-#define nSTALL_SENT_T 0x0
#define CLEAR_DATATOGGLE_T 0x40 /* clear endpoint data toggle */
-#define nCLEAR_DATATOGGLE_T 0x0
#define INCOMPTX_T 0x80 /* indicates that a large packet is split */
-#define nINCOMPTX_T 0x0
#define DMAREQMODE_T 0x400 /* DMA mode (0 or 1) selection */
-#define nDMAREQMODE_T 0x0
#define FORCE_DATATOGGLE_T 0x800 /* Force data toggle */
-#define nFORCE_DATATOGGLE_T 0x0
#define DMAREQ_ENA_T 0x1000 /* Enable DMA request for Tx EP */
-#define nDMAREQ_ENA_T 0x0
#define ISO_T 0x4000 /* enable Isochronous transfers */
-#define nISO_T 0x0
#define AUTOSET_T 0x8000 /* allows TxPktRdy to be set automatically */
-#define nAUTOSET_T 0x0
#define ERROR_TH 0x4 /* error condition host mode */
-#define nERROR_TH 0x0
#define STALL_RECEIVED_TH 0x20 /* Stall handshake received host mode */
-#define nSTALL_RECEIVED_TH 0x0
#define NAK_TIMEOUT_TH 0x80 /* NAK timeout host mode */
-#define nNAK_TIMEOUT_TH 0x0
/* Bit masks for USB_TXCOUNT */
@@ -1823,45 +1525,25 @@
/* Bit masks for USB_RXCSR */
#define RXPKTRDY_R 0x1 /* data packet in FIFO indicator */
-#define nRXPKTRDY_R 0x0
#define FIFO_FULL_R 0x2 /* FIFO not empty */
-#define nFIFO_FULL_R 0x0
#define OVERRUN_R 0x4 /* TxPktRdy not set for an IN token */
-#define nOVERRUN_R 0x0
#define DATAERROR_R 0x8 /* Out packet cannot be loaded into Rx FIFO */
-#define nDATAERROR_R 0x0
#define FLUSHFIFO_R 0x10 /* flush endpoint FIFO */
-#define nFLUSHFIFO_R 0x0
#define STALL_SEND_R 0x20 /* issue a Stall handshake */
-#define nSTALL_SEND_R 0x0
#define STALL_SENT_R 0x40 /* Stall handshake transmitted */
-#define nSTALL_SENT_R 0x0
#define CLEAR_DATATOGGLE_R 0x80 /* clear endpoint data toggle */
-#define nCLEAR_DATATOGGLE_R 0x0
#define INCOMPRX_R 0x100 /* indicates that a large packet is split */
-#define nINCOMPRX_R 0x0
#define DMAREQMODE_R 0x800 /* DMA mode (0 or 1) selection */
-#define nDMAREQMODE_R 0x0
#define DISNYET_R 0x1000 /* disable Nyet handshakes */
-#define nDISNYET_R 0x0
#define DMAREQ_ENA_R 0x2000 /* Enable DMA request for Tx EP */
-#define nDMAREQ_ENA_R 0x0
#define ISO_R 0x4000 /* enable Isochronous transfers */
-#define nISO_R 0x0
#define AUTOCLEAR_R 0x8000 /* allows TxPktRdy to be set automatically */
-#define nAUTOCLEAR_R 0x0
#define ERROR_RH 0x4 /* TxPktRdy not set for an IN token host mode */
-#define nERROR_RH 0x0
#define REQPKT_RH 0x20 /* request an IN transaction host mode */
-#define nREQPKT_RH 0x0
#define STALL_RECEIVED_RH 0x40 /* Stall handshake received host mode */
-#define nSTALL_RECEIVED_RH 0x0
#define INCOMPRX_RH 0x100 /* indicates that a large packet is split host mode */
-#define nINCOMPRX_RH 0x0
#define DMAREQMODE_RH 0x800 /* DMA mode (0 or 1) selection host mode */
-#define nDMAREQMODE_RH 0x0
#define AUTOREQ_RH 0x4000 /* sets ReqPkt automatically host mode */
-#define nAUTOREQ_RH 0x0
/* Bit masks for USB_RXCOUNT */
@@ -1888,35 +1570,22 @@
/* Bit masks for USB_DMA_INTERRUPT */
#define DMA0_INT 0x1 /* DMA0 pending interrupt */
-#define nDMA0_INT 0x0
#define DMA1_INT 0x2 /* DMA1 pending interrupt */
-#define nDMA1_INT 0x0
#define DMA2_INT 0x4 /* DMA2 pending interrupt */
-#define nDMA2_INT 0x0
#define DMA3_INT 0x8 /* DMA3 pending interrupt */
-#define nDMA3_INT 0x0
#define DMA4_INT 0x10 /* DMA4 pending interrupt */
-#define nDMA4_INT 0x0
#define DMA5_INT 0x20 /* DMA5 pending interrupt */
-#define nDMA5_INT 0x0
#define DMA6_INT 0x40 /* DMA6 pending interrupt */
-#define nDMA6_INT 0x0
#define DMA7_INT 0x80 /* DMA7 pending interrupt */
-#define nDMA7_INT 0x0
/* Bit masks for USB_DMAxCONTROL */
#define DMA_ENA 0x1 /* DMA enable */
-#define nDMA_ENA 0x0
#define DIRECTION 0x2 /* direction of DMA transfer */
-#define nDIRECTION 0x0
#define MODE 0x4 /* DMA Bus error */
-#define nMODE 0x0
#define INT_ENA 0x8 /* Interrupt enable */
-#define nINT_ENA 0x0
#define EPNUM 0xf0 /* EP number */
#define BUSERROR 0x100 /* DMA Bus error */
-#define nBUSERROR 0x0
/* Bit masks for USB_DMAxADDRHIGH */
@@ -1937,26 +1606,16 @@
/* Bit masks for HMDMAx_CONTROL */
#define HMDMAEN 0x1 /* Handshake MDMA Enable */
-#define nHMDMAEN 0x0
#define REP 0x2 /* Handshake MDMA Request Polarity */
-#define nREP 0x0
#define UTE 0x8 /* Urgency Threshold Enable */
-#define nUTE 0x0
#define OIE 0x10 /* Overflow Interrupt Enable */
-#define nOIE 0x0
#define BDIE 0x20 /* Block Done Interrupt Enable */
-#define nBDIE 0x0
#define MBDI 0x40 /* Mask Block Done Interrupt */
-#define nMBDI 0x0
#define DRQ 0x300 /* Handshake MDMA Request Type */
#define RBC 0x1000 /* Force Reload of BCOUNT */
-#define nRBC 0x0
#define PS 0x2000 /* Pin Status */
-#define nPS 0x0
#define OI 0x4000 /* Overflow Interrupt Generated */
-#define nOI 0x0
#define BDI 0x8000 /* Block Done Interrupt Generated */
-#define nBDI 0x0
/* ******************************************* */
/* MULTI BIT MACRO ENUMERATIONS */
diff --git a/include/asm-blackfin/mach-bf548/defBF549.h b/include/asm-blackfin/mach-bf548/defBF549.h
index b1cc1c073b4..c2f4734da48 100644
--- a/include/asm-blackfin/mach-bf548/defBF549.h
+++ b/include/asm-blackfin/mach-bf548/defBF549.h
@@ -1070,21 +1070,13 @@
/* Bit masks for PIXC_CTL */
#define PIXC_EN 0x1 /* Pixel Compositor Enable */
-#define nPIXC_EN 0x0
#define OVR_A_EN 0x2 /* Overlay A Enable */
-#define nOVR_A_EN 0x0
#define OVR_B_EN 0x4 /* Overlay B Enable */
-#define nOVR_B_EN 0x0
#define IMG_FORM 0x8 /* Image Data Format */
-#define nIMG_FORM 0x0
#define OVR_FORM 0x10 /* Overlay Data Format */
-#define nOVR_FORM 0x0
#define OUT_FORM 0x20 /* Output Data Format */
-#define nOUT_FORM 0x0
#define UDS_MOD 0x40 /* Resampling Mode */
-#define nUDS_MOD 0x0
#define TC_EN 0x80 /* Transparent Color Enable */
-#define nTC_EN 0x0
#define IMG_STAT 0x300 /* Image FIFO Status */
#define OVR_STAT 0xc00 /* Overlay FIFO Status */
#define WM_LVL 0x3000 /* FIFO Watermark Level */
@@ -1132,13 +1124,9 @@
/* Bit masks for PIXC_INTRSTAT */
#define OVR_INT_EN 0x1 /* Interrupt at End of Last Valid Overlay */
-#define nOVR_INT_EN 0x0
#define FRM_INT_EN 0x2 /* Interrupt at End of Frame */
-#define nFRM_INT_EN 0x0
#define OVR_INT_STAT 0x4 /* Overlay Interrupt Status */
-#define nOVR_INT_STAT 0x0
#define FRM_INT_STAT 0x8 /* Frame Interrupt Status */
-#define nFRM_INT_STAT 0x0
/* Bit masks for PIXC_RYCON */
@@ -1146,7 +1134,6 @@
#define A12 0xffc00 /* A12 in the Coefficient Matrix */
#define A13 0x3ff00000 /* A13 in the Coefficient Matrix */
#define RY_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nRY_MULT4 0x0
/* Bit masks for PIXC_GUCON */
@@ -1154,7 +1141,6 @@
#define A22 0xffc00 /* A22 in the Coefficient Matrix */
#define A23 0x3ff00000 /* A23 in the Coefficient Matrix */
#define GU_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nGU_MULT4 0x0
/* Bit masks for PIXC_BVCON */
@@ -1162,7 +1148,6 @@
#define A32 0xffc00 /* A32 in the Coefficient Matrix */
#define A33 0x3ff00000 /* A33 in the Coefficient Matrix */
#define BV_MULT4 0x40000000 /* Multiply Row by 4 */
-#define nBV_MULT4 0x0
/* Bit masks for PIXC_CCBIAS */
@@ -1179,48 +1164,28 @@
/* Bit masks for HOST_CONTROL */
#define HOST_EN 0x1 /* Host Enable */
-#define nHOST_EN 0x0
#define HOST_END 0x2 /* Host Endianess */
-#define nHOST_END 0x0
#define DATA_SIZE 0x4 /* Data Size */
-#define nDATA_SIZE 0x0
#define HOST_RST 0x8 /* Host Reset */
-#define nHOST_RST 0x0
#define HRDY_OVR 0x20 /* Host Ready Override */
-#define nHRDY_OVR 0x0
#define INT_MODE 0x40 /* Interrupt Mode */
-#define nINT_MODE 0x0
#define BT_EN 0x80 /* Bus Timeout Enable */
-#define nBT_EN 0x0
#define EHW 0x100 /* Enable Host Write */
-#define nEHW 0x0
#define EHR 0x200 /* Enable Host Read */
-#define nEHR 0x0
#define BDR 0x400 /* Burst DMA Requests */
-#define nBDR 0x0
/* Bit masks for HOST_STATUS */
#define READY 0x1 /* DMA Ready */
-#define nREADY 0x0
#define FIFOFULL 0x2 /* FIFO Full */
-#define nFIFOFULL 0x0
#define FIFOEMPTY 0x4 /* FIFO Empty */
-#define nFIFOEMPTY 0x0
-#define COMPLETE 0x8 /* DMA Complete */
-#define nCOMPLETE 0x0
+#define DMA_COMPLETE 0x8 /* DMA Complete */
#define HSHK 0x10 /* Host Handshake */
-#define nHSHK 0x0
#define TIMEOUT 0x20 /* Host Timeout */
-#define nTIMEOUT 0x0
#define HIRQ 0x40 /* Host Interrupt Request */
-#define nHIRQ 0x0
#define ALLOW_CNFG 0x80 /* Allow New Configuration */
-#define nALLOW_CNFG 0x0
#define DMA_DIR 0x100 /* DMA Direction */
-#define nDMA_DIR 0x0
#define BTE 0x200 /* Bus Timeout Enabled */
-#define nBTE 0x0
/* Bit masks for HOST_TIMEOUT */
@@ -1229,71 +1194,41 @@
/* Bit masks for MXVR_CONFIG */
#define MXVREN 0x1 /* MXVR Enable */
-#define nMXVREN 0x0
#define MMSM 0x2 /* MXVR Master/Slave Mode Select */
-#define nMMSM 0x0
#define ACTIVE 0x4 /* Active Mode */
-#define nACTIVE 0x0
#define SDELAY 0x8 /* Synchronous Data Delay */
-#define nSDELAY 0x0
#define NCMRXEN 0x10 /* Normal Control Message Receive Enable */
-#define nNCMRXEN 0x0
#define RWRRXEN 0x20 /* Remote Write Receive Enable */
-#define nRWRRXEN 0x0
#define MTXEN 0x40 /* MXVR Transmit Data Enable */
-#define nMTXEN 0x0
#define MTXONB 0x80 /* MXVR Phy Transmitter On */
-#define nMTXONB 0x0
#define EPARITY 0x100 /* Even Parity Select */
-#define nEPARITY 0x0
#define MSB 0x1e00 /* Master Synchronous Boundary */
#define APRXEN 0x2000 /* Asynchronous Packet Receive Enable */
-#define nAPRXEN 0x0
#define WAKEUP 0x4000 /* Wake-Up */
-#define nWAKEUP 0x0
#define LMECH 0x8000 /* Lock Mechanism Select */
-#define nLMECH 0x0
/* Bit masks for MXVR_STATE_0 */
#define NACT 0x1 /* Network Activity */
-#define nNACT 0x0
#define SBLOCK 0x2 /* Super Block Lock */
-#define nSBLOCK 0x0
#define FMPLLST 0xc /* Frequency Multiply PLL SM State */
#define CDRPLLST 0xe0 /* Clock/Data Recovery PLL SM State */
#define APBSY 0x100 /* Asynchronous Packet Transmit Buffer Busy */
-#define nAPBSY 0x0
#define APARB 0x200 /* Asynchronous Packet Arbitrating */
-#define nAPARB 0x0
#define APTX 0x400 /* Asynchronous Packet Transmitting */
-#define nAPTX 0x0
#define APRX 0x800 /* Receiving Asynchronous Packet */
-#define nAPRX 0x0
#define CMBSY 0x1000 /* Control Message Transmit Buffer Busy */
-#define nCMBSY 0x0
#define CMARB 0x2000 /* Control Message Arbitrating */
-#define nCMARB 0x0
#define CMTX 0x4000 /* Control Message Transmitting */
-#define nCMTX 0x0
#define CMRX 0x8000 /* Receiving Control Message */
-#define nCMRX 0x0
#define MRXONB 0x10000 /* MRXONB Pin State */
-#define nMRXONB 0x0
#define RGSIP 0x20000 /* Remote Get Source In Progress */
-#define nRGSIP 0x0
#define DALIP 0x40000 /* Resource Deallocate In Progress */
-#define nDALIP 0x0
#define ALIP 0x80000 /* Resource Allocate In Progress */
-#define nALIP 0x0
#define RRDIP 0x100000 /* Remote Read In Progress */
-#define nRRDIP 0x0
#define RWRIP 0x200000 /* Remote Write In Progress */
-#define nRWRIP 0x0
#define FLOCK 0x400000 /* Frame Lock */
-#define nFLOCK 0x0
#define BLOCK 0x800000 /* Block Lock */
-#define nBLOCK 0x0
#define RSB 0xf000000 /* Received Synchronous Boundary */
#define DERRNUM 0xf0000000 /* DMA Error Channel Number */
@@ -1302,535 +1237,343 @@
#define SRXNUMB 0xf /* Synchronous Receive FIFO Number of Bytes */
#define STXNUMB 0xf0 /* Synchronous Transmit FIFO Number of Bytes */
#define APCONT 0x100 /* Asynchronous Packet Continuation */
-#define nAPCONT 0x0
#define OBERRNUM 0xe00 /* DMA Out of Bounds Error Channel Number */
#define DMAACTIVE0 0x10000 /* DMA0 Active */
-#define nDMAACTIVE0 0x0
#define DMAACTIVE1 0x20000 /* DMA1 Active */
-#define nDMAACTIVE1 0x0
#define DMAACTIVE2 0x40000 /* DMA2 Active */
-#define nDMAACTIVE2 0x0
#define DMAACTIVE3 0x80000 /* DMA3 Active */
-#define nDMAACTIVE3 0x0
#define DMAACTIVE4 0x100000 /* DMA4 Active */
-#define nDMAACTIVE4 0x0
#define DMAACTIVE5 0x200000 /* DMA5 Active */
-#define nDMAACTIVE5 0x0
#define DMAACTIVE6 0x400000 /* DMA6 Active */
-#define nDMAACTIVE6 0x0
#define DMAACTIVE7 0x800000 /* DMA7 Active */
-#define nDMAACTIVE7 0x0
#define DMAPMEN0 0x1000000 /* DMA0 Pattern Matching Enabled */
-#define nDMAPMEN0 0x0
#define DMAPMEN1 0x2000000 /* DMA1 Pattern Matching Enabled */
-#define nDMAPMEN1 0x0
#define DMAPMEN2 0x4000000 /* DMA2 Pattern Matching Enabled */
-#define nDMAPMEN2 0x0
#define DMAPMEN3 0x8000000 /* DMA3 Pattern Matching Enabled */
-#define nDMAPMEN3 0x0
#define DMAPMEN4 0x10000000 /* DMA4 Pattern Matching Enabled */
-#define nDMAPMEN4 0x0
#define DMAPMEN5 0x20000000 /* DMA5 Pattern Matching Enabled */
-#define nDMAPMEN5 0x0
#define DMAPMEN6 0x40000000 /* DMA6 Pattern Matching Enabled */
-#define nDMAPMEN6 0x0
#define DMAPMEN7 0x80000000 /* DMA7 Pattern Matching Enabled */
-#define nDMAPMEN7 0x0
/* Bit masks for MXVR_INT_STAT_0 */
#define NI2A 0x1 /* Network Inactive to Active */
-#define nNI2A 0x0
#define NA2I 0x2 /* Network Active to Inactive */
-#define nNA2I 0x0
#define SBU2L 0x4 /* Super Block Unlock to Lock */
-#define nSBU2L 0x0
#define SBL2U 0x8 /* Super Block Lock to Unlock */
-#define nSBL2U 0x0
#define PRU 0x10 /* Position Register Updated */
-#define nPRU 0x0
#define MPRU 0x20 /* Maximum Position Register Updated */
-#define nMPRU 0x0
#define DRU 0x40 /* Delay Register Updated */
-#define nDRU 0x0
#define MDRU 0x80 /* Maximum Delay Register Updated */
-#define nMDRU 0x0
#define SBU 0x100 /* Synchronous Boundary Updated */
-#define nSBU 0x0
#define ATU 0x200 /* Allocation Table Updated */
-#define nATU 0x0
#define FCZ0 0x400 /* Frame Counter 0 Zero */
-#define nFCZ0 0x0
#define FCZ1 0x800 /* Frame Counter 1 Zero */
-#define nFCZ1 0x0
#define PERR 0x1000 /* Parity Error */
-#define nPERR 0x0
#define MH2L 0x2000 /* MRXONB High to Low */
-#define nMH2L 0x0
#define ML2H 0x4000 /* MRXONB Low to High */
-#define nML2H 0x0
#define WUP 0x8000 /* Wake-Up Preamble Received */
-#define nWUP 0x0
#define FU2L 0x10000 /* Frame Unlock to Lock */
-#define nFU2L 0x0
#define FL2U 0x20000 /* Frame Lock to Unlock */
-#define nFL2U 0x0
#define BU2L 0x40000 /* Block Unlock to Lock */
-#define nBU2L 0x0
#define BL2U 0x80000 /* Block Lock to Unlock */
-#define nBL2U 0x0
#define OBERR 0x100000 /* DMA Out of Bounds Error */
-#define nOBERR 0x0
#define PFL 0x200000 /* PLL Frequency Locked */
-#define nPFL 0x0
#define SCZ 0x400000 /* System Clock Counter Zero */
-#define nSCZ 0x0
#define FERR 0x800000 /* FIFO Error */
-#define nFERR 0x0
#define CMR 0x1000000 /* Control Message Received */
-#define nCMR 0x0
#define CMROF 0x2000000 /* Control Message Receive Buffer Overflow */
-#define nCMROF 0x0
#define CMTS 0x4000000 /* Control Message Transmit Buffer Successfully Sent */
-#define nCMTS 0x0
#define CMTC 0x8000000 /* Control Message Transmit Buffer Successfully Cancelled */
-#define nCMTC 0x0
#define RWRC 0x10000000 /* Remote Write Control Message Completed */
-#define nRWRC 0x0
#define BCZ 0x20000000 /* Block Counter Zero */
-#define nBCZ 0x0
#define BMERR 0x40000000 /* Biphase Mark Coding Error */
-#define nBMERR 0x0
#define DERR 0x80000000 /* DMA Error */
-#define nDERR 0x0
/* Bit masks for MXVR_INT_STAT_1 */
#define HDONE0 0x1 /* DMA0 Half Done */
-#define nHDONE0 0x0
#define DONE0 0x2 /* DMA0 Done */
-#define nDONE0 0x0
#define APR 0x4 /* Asynchronous Packet Received */
-#define nAPR 0x0
#define APROF 0x8 /* Asynchronous Packet Receive Buffer Overflow */
-#define nAPROF 0x0
#define HDONE1 0x10 /* DMA1 Half Done */
-#define nHDONE1 0x0
#define DONE1 0x20 /* DMA1 Done */
-#define nDONE1 0x0
#define APTS 0x40 /* Asynchronous Packet Transmit Buffer Successfully Sent */
-#define nAPTS 0x0
#define APTC 0x80 /* Asynchronous Packet Transmit Buffer Successfully Cancelled */
-#define nAPTC 0x0
#define HDONE2 0x100 /* DMA2 Half Done */
-#define nHDONE2 0x0
#define DONE2 0x200 /* DMA2 Done */
-#define nDONE2 0x0
#define APRCE 0x400 /* Asynchronous Packet Receive CRC Error */
-#define nAPRCE 0x0
#define APRPE 0x800 /* Asynchronous Packet Receive Packet Error */
-#define nAPRPE 0x0
#define HDONE3 0x1000 /* DMA3 Half Done */
-#define nHDONE3 0x0
#define DONE3 0x2000 /* DMA3 Done */
-#define nDONE3 0x0
#define HDONE4 0x10000 /* DMA4 Half Done */
-#define nHDONE4 0x0
#define DONE4 0x20000 /* DMA4 Done */
-#define nDONE4 0x0
#define HDONE5 0x100000 /* DMA5 Half Done */
-#define nHDONE5 0x0
#define DONE5 0x200000 /* DMA5 Done */
-#define nDONE5 0x0
#define HDONE6 0x1000000 /* DMA6 Half Done */
-#define nHDONE6 0x0
#define DONE6 0x2000000 /* DMA6 Done */
-#define nDONE6 0x0
#define HDONE7 0x10000000 /* DMA7 Half Done */
-#define nHDONE7 0x0
#define DONE7 0x20000000 /* DMA7 Done */
-#define nDONE7 0x0
/* Bit masks for MXVR_INT_EN_0 */
#define NI2AEN 0x1 /* Network Inactive to Active Interrupt Enable */
-#define nNI2AEN 0x0
#define NA2IEN 0x2 /* Network Active to Inactive Interrupt Enable */
-#define nNA2IEN 0x0
#define SBU2LEN 0x4 /* Super Block Unlock to Lock Interrupt Enable */
-#define nSBU2LEN 0x0
#define SBL2UEN 0x8 /* Super Block Lock to Unlock Interrupt Enable */
-#define nSBL2UEN 0x0
#define PRUEN 0x10 /* Position Register Updated Interrupt Enable */
-#define nPRUEN 0x0
#define MPRUEN 0x20 /* Maximum Position Register Updated Interrupt Enable */
-#define nMPRUEN 0x0
#define DRUEN 0x40 /* Delay Register Updated Interrupt Enable */
-#define nDRUEN 0x0
#define MDRUEN 0x80 /* Maximum Delay Register Updated Interrupt Enable */
-#define nMDRUEN 0x0
#define SBUEN 0x100 /* Synchronous Boundary Updated Interrupt Enable */
-#define nSBUEN 0x0
#define ATUEN 0x200 /* Allocation Table Updated Interrupt Enable */
-#define nATUEN 0x0
#define FCZ0EN 0x400 /* Frame Counter 0 Zero Interrupt Enable */
-#define nFCZ0EN 0x0
#define FCZ1EN 0x800 /* Frame Counter 1 Zero Interrupt Enable */
-#define nFCZ1EN 0x0
#define PERREN 0x1000 /* Parity Error Interrupt Enable */
-#define nPERREN 0x0
#define MH2LEN 0x2000 /* MRXONB High to Low Interrupt Enable */
-#define nMH2LEN 0x0
#define ML2HEN 0x4000 /* MRXONB Low to High Interrupt Enable */
-#define nML2HEN 0x0
#define WUPEN 0x8000 /* Wake-Up Preamble Received Interrupt Enable */
-#define nWUPEN 0x0
#define FU2LEN 0x10000 /* Frame Unlock to Lock Interrupt Enable */
-#define nFU2LEN 0x0
#define FL2UEN 0x20000 /* Frame Lock to Unlock Interrupt Enable */
-#define nFL2UEN 0x0
#define BU2LEN 0x40000 /* Block Unlock to Lock Interrupt Enable */
-#define nBU2LEN 0x0
#define BL2UEN 0x80000 /* Block Lock to Unlock Interrupt Enable */
-#define nBL2UEN 0x0
#define OBERREN 0x100000 /* DMA Out of Bounds Error Interrupt Enable */
-#define nOBERREN 0x0
#define PFLEN 0x200000 /* PLL Frequency Locked Interrupt Enable */
-#define nPFLEN 0x0
#define SCZEN 0x400000 /* System Clock Counter Zero Interrupt Enable */
-#define nSCZEN 0x0
#define FERREN 0x800000 /* FIFO Error Interrupt Enable */
-#define nFERREN 0x0
#define CMREN 0x1000000 /* Control Message Received Interrupt Enable */
-#define nCMREN 0x0
#define CMROFEN 0x2000000 /* Control Message Receive Buffer Overflow Interrupt Enable */
-#define nCMROFEN 0x0
#define CMTSEN 0x4000000 /* Control Message Transmit Buffer Successfully Sent Interrupt Enable */
-#define nCMTSEN 0x0
#define CMTCEN 0x8000000 /* Control Message Transmit Buffer Successfully Cancelled Interrupt Enable */
-#define nCMTCEN 0x0
#define RWRCEN 0x10000000 /* Remote Write Control Message Completed Interrupt Enable */
-#define nRWRCEN 0x0
#define BCZEN 0x20000000 /* Block Counter Zero Interrupt Enable */
-#define nBCZEN 0x0
#define BMERREN 0x40000000 /* Biphase Mark Coding Error Interrupt Enable */
-#define nBMERREN 0x0
#define DERREN 0x80000000 /* DMA Error Interrupt Enable */
-#define nDERREN 0x0
/* Bit masks for MXVR_INT_EN_1 */
#define HDONEEN0 0x1 /* DMA0 Half Done Interrupt Enable */
-#define nHDONEEN0 0x0
#define DONEEN0 0x2 /* DMA0 Done Interrupt Enable */
-#define nDONEEN0 0x0
#define APREN 0x4 /* Asynchronous Packet Received Interrupt Enable */
-#define nAPREN 0x0
#define APROFEN 0x8 /* Asynchronous Packet Receive Buffer Overflow Interrupt Enable */
-#define nAPROFEN 0x0
#define HDONEEN1 0x10 /* DMA1 Half Done Interrupt Enable */
-#define nHDONEEN1 0x0
#define DONEEN1 0x20 /* DMA1 Done Interrupt Enable */
-#define nDONEEN1 0x0
#define APTSEN 0x40 /* Asynchronous Packet Transmit Buffer Successfully Sent Interrupt Enable */
-#define nAPTSEN 0x0
#define APTCEN 0x80 /* Asynchronous Packet Transmit Buffer Successfully Cancelled Interrupt Enable */
-#define nAPTCEN 0x0
#define HDONEEN2 0x100 /* DMA2 Half Done Interrupt Enable */
-#define nHDONEEN2 0x0
#define DONEEN2 0x200 /* DMA2 Done Interrupt Enable */
-#define nDONEEN2 0x0
#define APRCEEN 0x400 /* Asynchronous Packet Receive CRC Error Interrupt Enable */
-#define nAPRCEEN 0x0
#define APRPEEN 0x800 /* Asynchronous Packet Receive Packet Error Interrupt Enable */
-#define nAPRPEEN 0x0
#define HDONEEN3 0x1000 /* DMA3 Half Done Interrupt Enable */
-#define nHDONEEN3 0x0
#define DONEEN3 0x2000 /* DMA3 Done Interrupt Enable */
-#define nDONEEN3 0x0
#define HDONEEN4 0x10000 /* DMA4 Half Done Interrupt Enable */
-#define nHDONEEN4 0x0
#define DONEEN4 0x20000 /* DMA4 Done Interrupt Enable */
-#define nDONEEN4 0x0
#define HDONEEN5 0x100000 /* DMA5 Half Done Interrupt Enable */
-#define nHDONEEN5 0x0
#define DONEEN5 0x200000 /* DMA5 Done Interrupt Enable */
-#define nDONEEN5 0x0
#define HDONEEN6 0x1000000 /* DMA6 Half Done Interrupt Enable */
-#define nHDONEEN6 0x0
#define DONEEN6 0x2000000 /* DMA6 Done Interrupt Enable */
-#define nDONEEN6 0x0
#define HDONEEN7 0x10000000 /* DMA7 Half Done Interrupt Enable */
-#define nHDONEEN7 0x0
#define DONEEN7 0x20000000 /* DMA7 Done Interrupt Enable */
-#define nDONEEN7 0x0
/* Bit masks for MXVR_POSITION */
#define POSITION 0x3f /* Node Position */
#define PVALID 0x8000 /* Node Position Valid */
-#define nPVALID 0x0
/* Bit masks for MXVR_MAX_POSITION */
#define MPOSITION 0x3f /* Maximum Node Position */
#define MPVALID 0x8000 /* Maximum Node Position Valid */
-#define nMPVALID 0x0
/* Bit masks for MXVR_DELAY */
#define DELAY 0x3f /* Node Frame Delay */
#define DVALID 0x8000 /* Node Frame Delay Valid */
-#define nDVALID 0x0
/* Bit masks for MXVR_MAX_DELAY */
#define MDELAY 0x3f /* Maximum Node Frame Delay */
#define MDVALID 0x8000 /* Maximum Node Frame Delay Valid */
-#define nMDVALID 0x0
/* Bit masks for MXVR_LADDR */
#define LADDR 0xffff /* Logical Address */
#define LVALID 0x80000000 /* Logical Address Valid */
-#define nLVALID 0x0
/* Bit masks for MXVR_GADDR */
#define GADDRL 0xff /* Group Address Lower Byte */
#define GVALID 0x8000 /* Group Address Valid */
-#define nGVALID 0x0
/* Bit masks for MXVR_AADDR */
#define AADDR 0xffff /* Alternate Address */
#define AVALID 0x80000000 /* Alternate Address Valid */
-#define nAVALID 0x0
/* Bit masks for MXVR_ALLOC_0 */
#define CL0 0x7f /* Channel 0 Connection Label */
#define CIU0 0x80 /* Channel 0 In Use */
-#define nCIU0 0x0
#define CL1 0x7f00 /* Channel 0 Connection Label */
#define CIU1 0x8000 /* Channel 0 In Use */
-#define nCIU1 0x0
#define CL2 0x7f0000 /* Channel 0 Connection Label */
#define CIU2 0x800000 /* Channel 0 In Use */
-#define nCIU2 0x0
#define CL3 0x7f000000 /* Channel 0 Connection Label */
#define CIU3 0x80000000 /* Channel 0 In Use */
-#define nCIU3 0x0
/* Bit masks for MXVR_ALLOC_1 */
#define CL4 0x7f /* Channel 4 Connection Label */
#define CIU4 0x80 /* Channel 4 In Use */
-#define nCIU4 0x0
#define CL5 0x7f00 /* Channel 5 Connection Label */
#define CIU5 0x8000 /* Channel 5 In Use */
-#define nCIU5 0x0
#define CL6 0x7f0000 /* Channel 6 Connection Label */
#define CIU6 0x800000 /* Channel 6 In Use */
-#define nCIU6 0x0
#define CL7 0x7f000000 /* Channel 7 Connection Label */
#define CIU7 0x80000000 /* Channel 7 In Use */
-#define nCIU7 0x0
/* Bit masks for MXVR_ALLOC_2 */
#define CL8 0x7f /* Channel 8 Connection Label */
#define CIU8 0x80 /* Channel 8 In Use */
-#define nCIU8 0x0
#define CL9 0x7f00 /* Channel 9 Connection Label */
#define CIU9 0x8000 /* Channel 9 In Use */
-#define nCIU9 0x0
#define CL10 0x7f0000 /* Channel 10 Connection Label */
#define CIU10 0x800000 /* Channel 10 In Use */
-#define nCIU10 0x0
#define CL11 0x7f000000 /* Channel 11 Connection Label */
#define CIU11 0x80000000 /* Channel 11 In Use */
-#define nCIU11 0x0
/* Bit masks for MXVR_ALLOC_3 */
#define CL12 0x7f /* Channel 12 Connection Label */
#define CIU12 0x80 /* Channel 12 In Use */
-#define nCIU12 0x0
#define CL13 0x7f00 /* Channel 13 Connection Label */
#define CIU13 0x8000 /* Channel 13 In Use */
-#define nCIU13 0x0
#define CL14 0x7f0000 /* Channel 14 Connection Label */
#define CIU14 0x800000 /* Channel 14 In Use */
-#define nCIU14 0x0
#define CL15 0x7f000000 /* Channel 15 Connection Label */
#define CIU15 0x80000000 /* Channel 15 In Use */
-#define nCIU15 0x0
/* Bit masks for MXVR_ALLOC_4 */
#define CL16 0x7f /* Channel 16 Connection Label */
#define CIU16 0x80 /* Channel 16 In Use */
-#define nCIU16 0x0
#define CL17 0x7f00 /* Channel 17 Connection Label */
#define CIU17 0x8000 /* Channel 17 In Use */
-#define nCIU17 0x0
#define CL18 0x7f0000 /* Channel 18 Connection Label */
#define CIU18 0x800000 /* Channel 18 In Use */
-#define nCIU18 0x0
#define CL19 0x7f000000 /* Channel 19 Connection Label */
#define CIU19 0x80000000 /* Channel 19 In Use */
-#define nCIU19 0x0
/* Bit masks for MXVR_ALLOC_5 */
#define CL20 0x7f /* Channel 20 Connection Label */
#define CIU20 0x80 /* Channel 20 In Use */
-#define nCIU20 0x0
#define CL21 0x7f00 /* Channel 21 Connection Label */
#define CIU21 0x8000 /* Channel 21 In Use */
-#define nCIU21 0x0
#define CL22 0x7f0000 /* Channel 22 Connection Label */
#define CIU22 0x800000 /* Channel 22 In Use */
-#define nCIU22 0x0
#define CL23 0x7f000000 /* Channel 23 Connection Label */
#define CIU23 0x80000000 /* Channel 23 In Use */
-#define nCIU23 0x0
/* Bit masks for MXVR_ALLOC_6 */
#define CL24 0x7f /* Channel 24 Connection Label */
#define CIU24 0x80 /* Channel 24 In Use */
-#define nCIU24 0x0
#define CL25 0x7f00 /* Channel 25 Connection Label */
#define CIU25 0x8000 /* Channel 25 In Use */
-#define nCIU25 0x0
#define CL26 0x7f0000 /* Channel 26 Connection Label */
#define CIU26 0x800000 /* Channel 26 In Use */
-#define nCIU26 0x0
#define CL27 0x7f000000 /* Channel 27 Connection Label */
#define CIU27 0x80000000 /* Channel 27 In Use */
-#define nCIU27 0x0
/* Bit masks for MXVR_ALLOC_7 */
#define CL28 0x7f /* Channel 28 Connection Label */
#define CIU28 0x80 /* Channel 28 In Use */
-#define nCIU28 0x0
#define CL29 0x7f00 /* Channel 29 Connection Label */
#define CIU29 0x8000 /* Channel 29 In Use */
-#define nCIU29 0x0
#define CL30 0x7f0000 /* Channel 30 Connection Label */
#define CIU30 0x800000 /* Channel 30 In Use */
-#define nCIU30 0x0
#define CL31 0x7f000000 /* Channel 31 Connection Label */
#define CIU31 0x80000000 /* Channel 31 In Use */
-#define nCIU31 0x0
/* Bit masks for MXVR_ALLOC_8 */
#define CL32 0x7f /* Channel 32 Connection Label */
#define CIU32 0x80 /* Channel 32 In Use */
-#define nCIU32 0x0
#define CL33 0x7f00 /* Channel 33 Connection Label */
#define CIU33 0x8000 /* Channel 33 In Use */
-#define nCIU33 0x0
#define CL34 0x7f0000 /* Channel 34 Connection Label */
#define CIU34 0x800000 /* Channel 34 In Use */
-#define nCIU34 0x0
#define CL35 0x7f000000 /* Channel 35 Connection Label */
#define CIU35 0x80000000 /* Channel 35 In Use */
-#define nCIU35 0x0
/* Bit masks for MXVR_ALLOC_9 */
#define CL36 0x7f /* Channel 36 Connection Label */
#define CIU36 0x80 /* Channel 36 In Use */
-#define nCIU36 0x0
#define CL37 0x7f00 /* Channel 37 Connection Label */
#define CIU37 0x8000 /* Channel 37 In Use */
-#define nCIU37 0x0
#define CL38 0x7f0000 /* Channel 38 Connection Label */
#define CIU38 0x800000 /* Channel 38 In Use */
-#define nCIU38 0x0
#define CL39 0x7f000000 /* Channel 39 Connection Label */
#define CIU39 0x80000000 /* Channel 39 In Use */
-#define nCIU39 0x0
/* Bit masks for MXVR_ALLOC_10 */
#define CL40 0x7f /* Channel 40 Connection Label */
#define CIU40 0x80 /* Channel 40 In Use */
-#define nCIU40 0x0
#define CL41 0x7f00 /* Channel 41 Connection Label */
#define CIU41 0x8000 /* Channel 41 In Use */
-#define nCIU41 0x0
#define CL42 0x7f0000 /* Channel 42 Connection Label */
#define CIU42 0x800000 /* Channel 42 In Use */
-#define nCIU42 0x0
#define CL43 0x7f000000 /* Channel 43 Connection Label */
#define CIU43 0x80000000 /* Channel 43 In Use */
-#define nCIU43 0x0
/* Bit masks for MXVR_ALLOC_11 */
#define CL44 0x7f /* Channel 44 Connection Label */
#define CIU44 0x80 /* Channel 44 In Use */
-#define nCIU44 0x0
#define CL45 0x7f00 /* Channel 45 Connection Label */
#define CIU45 0x8000 /* Channel 45 In Use */
-#define nCIU45 0x0
#define CL46 0x7f0000 /* Channel 46 Connection Label */
#define CIU46 0x800000 /* Channel 46 In Use */
-#define nCIU46 0x0
#define CL47 0x7f000000 /* Channel 47 Connection Label */
#define CIU47 0x80000000 /* Channel 47 In Use */
-#define nCIU47 0x0
/* Bit masks for MXVR_ALLOC_12 */
#define CL48 0x7f /* Channel 48 Connection Label */
#define CIU48 0x80 /* Channel 48 In Use */
-#define nCIU48 0x0
#define CL49 0x7f00 /* Channel 49 Connection Label */
#define CIU49 0x8000 /* Channel 49 In Use */
-#define nCIU49 0x0
#define CL50 0x7f0000 /* Channel 50 Connection Label */
#define CIU50 0x800000 /* Channel 50 In Use */
-#define nCIU50 0x0
#define CL51 0x7f000000 /* Channel 51 Connection Label */
#define CIU51 0x80000000 /* Channel 51 In Use */
-#define nCIU51 0x0
/* Bit masks for MXVR_ALLOC_13 */
#define CL52 0x7f /* Channel 52 Connection Label */
#define CIU52 0x80 /* Channel 52 In Use */
-#define nCIU52 0x0
#define CL53 0x7f00 /* Channel 53 Connection Label */
#define CIU53 0x8000 /* Channel 53 In Use */
-#define nCIU53 0x0
#define CL54 0x7f0000 /* Channel 54 Connection Label */
#define CIU54 0x800000 /* Channel 54 In Use */
-#define nCIU54 0x0
#define CL55 0x7f000000 /* Channel 55 Connection Label */
#define CIU55 0x80000000 /* Channel 55 In Use */
-#define nCIU55 0x0
/* Bit masks for MXVR_ALLOC_14 */
#define CL56 0x7f /* Channel 56 Connection Label */
#define CIU56 0x80 /* Channel 56 In Use */
-#define nCIU56 0x0
#define CL57 0x7f00 /* Channel 57 Connection Label */
#define CIU57 0x8000 /* Channel 57 In Use */
-#define nCIU57 0x0
#define CL58 0x7f0000 /* Channel 58 Connection Label */
#define CIU58 0x800000 /* Channel 58 In Use */
-#define nCIU58 0x0
#define CL59 0x7f000000 /* Channel 59 Connection Label */
#define CIU59 0x80000000 /* Channel 59 In Use */
-#define nCIU59 0x0
/* MXVR_SYNC_LCHAN_0 Masks */
@@ -1926,19 +1669,13 @@
/* Bit masks for MXVR_DMAx_CONFIG */
#define MDMAEN 0x1 /* DMA Channel Enable */
-#define nMDMAEN 0x0
#define DD 0x2 /* DMA Channel Direction */
-#define nDD 0x0
#define BY4SWAPEN 0x20 /* DMA Channel Four Byte Swap Enable */
-#define nBY4SWAPEN 0x0
#define LCHAN 0x3c0 /* DMA Channel Logical Channel */
#define BITSWAPEN 0x400 /* DMA Channel Bit Swap Enable */
-#define nBITSWAPEN 0x0
#define BY2SWAPEN 0x800 /* DMA Channel Two Byte Swap Enable */
-#define nBY2SWAPEN 0x0
#define MFLOW 0x7000 /* DMA Channel Operation Flow */
#define FIXEDPM 0x80000 /* DMA Channel Fixed Pattern Matching Select */
-#define nFIXEDPM 0x0
#define STARTPAT 0x300000 /* DMA Channel Start Pattern Select */
#define STOPPAT 0xc00000 /* DMA Channel Stop Pattern Select */
#define COUNTPOS 0x1c000000 /* DMA Channel Count Position */
@@ -1946,94 +1683,71 @@
/* Bit masks for MXVR_AP_CTL */
#define STARTAP 0x1 /* Start Asynchronous Packet Transmission */
-#define nSTARTAP 0x0
#define CANCELAP 0x2 /* Cancel Asynchronous Packet Transmission */
-#define nCANCELAP 0x0
#define RESETAP 0x4 /* Reset Asynchronous Packet Arbitration */
-#define nRESETAP 0x0
#define APRBE0 0x4000 /* Asynchronous Packet Receive Buffer Entry 0 */
-#define nAPRBE0 0x0
#define APRBE1 0x8000 /* Asynchronous Packet Receive Buffer Entry 1 */
-#define nAPRBE1 0x0
/* Bit masks for MXVR_APRB_START_ADDR */
-#define MXVR_APRB_START_ADDR 0x1fffffe /* Asynchronous Packet Receive Buffer Start Address */
+#define MXVR_APRB_START_ADDR_MASK 0x1fffffe /* Asynchronous Packet Receive Buffer Start Address */
/* Bit masks for MXVR_APRB_CURR_ADDR */
-#define MXVR_APRB_CURR_ADDR 0xffffffff /* Asynchronous Packet Receive Buffer Current Address */
+#define MXVR_APRB_CURR_ADDR_MASK 0xffffffff /* Asynchronous Packet Receive Buffer Current Address */
/* Bit masks for MXVR_APTB_START_ADDR */
-#define MXVR_APTB_START_ADDR 0x1fffffe /* Asynchronous Packet Transmit Buffer Start Address */
+#define MXVR_APTB_START_ADDR_MASK 0x1fffffe /* Asynchronous Packet Transmit Buffer Start Address */
/* Bit masks for MXVR_APTB_CURR_ADDR */
-#define MXVR_APTB_CURR_ADDR 0xffffffff /* Asynchronous Packet Transmit Buffer Current Address */
+#define MXVR_APTB_CURR_ADDR_MASK 0xffffffff /* Asynchronous Packet Transmit Buffer Current Address */
/* Bit masks for MXVR_CM_CTL */
#define STARTCM 0x1 /* Start Control Message Transmission */
-#define nSTARTCM 0x0
#define CANCELCM 0x2 /* Cancel Control Message Transmission */
-#define nCANCELCM 0x0
#define CMRBE0 0x10000 /* Control Message Receive Buffer Entry 0 */
-#define nCMRBE0 0x0
#define CMRBE1 0x20000 /* Control Message Receive Buffer Entry 1 */
-#define nCMRBE1 0x0
#define CMRBE2 0x40000 /* Control Message Receive Buffer Entry 2 */
-#define nCMRBE2 0x0
#define CMRBE3 0x80000 /* Control Message Receive Buffer Entry 3 */
-#define nCMRBE3 0x0
#define CMRBE4 0x100000 /* Control Message Receive Buffer Entry 4 */
-#define nCMRBE4 0x0
#define CMRBE5 0x200000 /* Control Message Receive Buffer Entry 5 */
-#define nCMRBE5 0x0
#define CMRBE6 0x400000 /* Control Message Receive Buffer Entry 6 */
-#define nCMRBE6 0x0
#define CMRBE7 0x800000 /* Control Message Receive Buffer Entry 7 */
-#define nCMRBE7 0x0
#define CMRBE8 0x1000000 /* Control Message Receive Buffer Entry 8 */
-#define nCMRBE8 0x0
#define CMRBE9 0x2000000 /* Control Message Receive Buffer Entry 9 */
-#define nCMRBE9 0x0
#define CMRBE10 0x4000000 /* Control Message Receive Buffer Entry 10 */
-#define nCMRBE10 0x0
#define CMRBE11 0x8000000 /* Control Message Receive Buffer Entry 11 */
-#define nCMRBE11 0x0
#define CMRBE12 0x10000000 /* Control Message Receive Buffer Entry 12 */
-#define nCMRBE12 0x0
#define CMRBE13 0x20000000 /* Control Message Receive Buffer Entry 13 */
-#define nCMRBE13 0x0
#define CMRBE14 0x40000000 /* Control Message Receive Buffer Entry 14 */
-#define nCMRBE14 0x0
#define CMRBE15 0x80000000 /* Control Message Receive Buffer Entry 15 */
-#define nCMRBE15 0x0
/* Bit masks for MXVR_CMRB_START_ADDR */
-#define MXVR_CMRB_START_ADDR 0x1fffffe /* Control Message Receive Buffer Start Address */
+#define MXVR_CMRB_START_ADDR_MASK 0x1fffffe /* Control Message Receive Buffer Start Address */
/* Bit masks for MXVR_CMRB_CURR_ADDR */
-#define MXVR_CMRB_CURR_ADDR 0xffffffff /* Control Message Receive Buffer Current Address */
+#define MXVR_CMRB_CURR_ADDR_MASK 0xffffffff /* Control Message Receive Buffer Current Address */
/* Bit masks for MXVR_CMTB_START_ADDR */
-#define MXVR_CMTB_START_ADDR 0x1fffffe /* Control Message Transmit Buffer Start Address */
+#define MXVR_CMTB_START_ADDR_MASK 0x1fffffe /* Control Message Transmit Buffer Start Address */
/* Bit masks for MXVR_CMTB_CURR_ADDR */
-#define MXVR_CMTB_CURR_ADDR 0xffffffff /* Control Message Transmit Buffer Current Address */
+#define MXVR_CMTB_CURR_ADDR_MASK 0xffffffff /* Control Message Transmit Buffer Current Address */
/* Bit masks for MXVR_RRDB_START_ADDR */
-#define MXVR_RRDB_START_ADDR 0x1fffffe /* Remote Read Buffer Start Address */
+#define MXVR_RRDB_START_ADDR_MASK 0x1fffffe /* Remote Read Buffer Start Address */
/* Bit masks for MXVR_RRDB_CURR_ADDR */
-#define MXVR_RRDB_CURR_ADDR 0xffffffff /* Remote Read Buffer Current Address */
+#define MXVR_RRDB_CURR_ADDR_MASK 0xffffffff /* Remote Read Buffer Current Address */
/* Bit masks for MXVR_PAT_DATAx */
@@ -2045,136 +1759,72 @@
/* Bit masks for MXVR_PAT_EN_0 */
#define MATCH_EN_0_0 0x1 /* Pattern Match Enable Byte 0 Bit 0 */
-#define nMATCH_EN_0_0 0x0
#define MATCH_EN_0_1 0x2 /* Pattern Match Enable Byte 0 Bit 1 */
-#define nMATCH_EN_0_1 0x0
#define MATCH_EN_0_2 0x4 /* Pattern Match Enable Byte 0 Bit 2 */
-#define nMATCH_EN_0_2 0x0
#define MATCH_EN_0_3 0x8 /* Pattern Match Enable Byte 0 Bit 3 */
-#define nMATCH_EN_0_3 0x0
#define MATCH_EN_0_4 0x10 /* Pattern Match Enable Byte 0 Bit 4 */
-#define nMATCH_EN_0_4 0x0
#define MATCH_EN_0_5 0x20 /* Pattern Match Enable Byte 0 Bit 5 */
-#define nMATCH_EN_0_5 0x0
#define MATCH_EN_0_6 0x40 /* Pattern Match Enable Byte 0 Bit 6 */
-#define nMATCH_EN_0_6 0x0
#define MATCH_EN_0_7 0x80 /* Pattern Match Enable Byte 0 Bit 7 */
-#define nMATCH_EN_0_7 0x0
#define MATCH_EN_1_0 0x100 /* Pattern Match Enable Byte 1 Bit 0 */
-#define nMATCH_EN_1_0 0x0
#define MATCH_EN_1_1 0x200 /* Pattern Match Enable Byte 1 Bit 1 */
-#define nMATCH_EN_1_1 0x0
#define MATCH_EN_1_2 0x400 /* Pattern Match Enable Byte 1 Bit 2 */
-#define nMATCH_EN_1_2 0x0
#define MATCH_EN_1_3 0x800 /* Pattern Match Enable Byte 1 Bit 3 */
-#define nMATCH_EN_1_3 0x0
#define MATCH_EN_1_4 0x1000 /* Pattern Match Enable Byte 1 Bit 4 */
-#define nMATCH_EN_1_4 0x0
#define MATCH_EN_1_5 0x2000 /* Pattern Match Enable Byte 1 Bit 5 */
-#define nMATCH_EN_1_5 0x0
#define MATCH_EN_1_6 0x4000 /* Pattern Match Enable Byte 1 Bit 6 */
-#define nMATCH_EN_1_6 0x0
#define MATCH_EN_1_7 0x8000 /* Pattern Match Enable Byte 1 Bit 7 */
-#define nMATCH_EN_1_7 0x0
#define MATCH_EN_2_0 0x10000 /* Pattern Match Enable Byte 2 Bit 0 */
-#define nMATCH_EN_2_0 0x0
#define MATCH_EN_2_1 0x20000 /* Pattern Match Enable Byte 2 Bit 1 */
-#define nMATCH_EN_2_1 0x0
#define MATCH_EN_2_2 0x40000 /* Pattern Match Enable Byte 2 Bit 2 */
-#define nMATCH_EN_2_2 0x0
#define MATCH_EN_2_3 0x80000 /* Pattern Match Enable Byte 2 Bit 3 */
-#define nMATCH_EN_2_3 0x0
#define MATCH_EN_2_4 0x100000 /* Pattern Match Enable Byte 2 Bit 4 */
-#define nMATCH_EN_2_4 0x0
#define MATCH_EN_2_5 0x200000 /* Pattern Match Enable Byte 2 Bit 5 */
-#define nMATCH_EN_2_5 0x0
#define MATCH_EN_2_6 0x400000 /* Pattern Match Enable Byte 2 Bit 6 */
-#define nMATCH_EN_2_6 0x0
#define MATCH_EN_2_7 0x800000 /* Pattern Match Enable Byte 2 Bit 7 */
-#define nMATCH_EN_2_7 0x0
#define MATCH_EN_3_0 0x1000000 /* Pattern Match Enable Byte 3 Bit 0 */
-#define nMATCH_EN_3_0 0x0
#define MATCH_EN_3_1 0x2000000 /* Pattern Match Enable Byte 3 Bit 1 */
-#define nMATCH_EN_3_1 0x0
#define MATCH_EN_3_2 0x4000000 /* Pattern Match Enable Byte 3 Bit 2 */
-#define nMATCH_EN_3_2 0x0
#define MATCH_EN_3_3 0x8000000 /* Pattern Match Enable Byte 3 Bit 3 */
-#define nMATCH_EN_3_3 0x0
#define MATCH_EN_3_4 0x10000000 /* Pattern Match Enable Byte 3 Bit 4 */
-#define nMATCH_EN_3_4 0x0
#define MATCH_EN_3_5 0x20000000 /* Pattern Match Enable Byte 3 Bit 5 */
-#define nMATCH_EN_3_5 0x0
#define MATCH_EN_3_6 0x40000000 /* Pattern Match Enable Byte 3 Bit 6 */
-#define nMATCH_EN_3_6 0x0
#define MATCH_EN_3_7 0x80000000 /* Pattern Match Enable Byte 3 Bit 7 */
-#define nMATCH_EN_3_7 0x0
/* Bit masks for MXVR_PAT_EN_1 */
#define MATCH_EN_0_0 0x1 /* Pattern Match Enable Byte 0 Bit 0 */
-#define nMATCH_EN_0_0 0x0
#define MATCH_EN_0_1 0x2 /* Pattern Match Enable Byte 0 Bit 1 */
-#define nMATCH_EN_0_1 0x0
#define MATCH_EN_0_2 0x4 /* Pattern Match Enable Byte 0 Bit 2 */
-#define nMATCH_EN_0_2 0x0
#define MATCH_EN_0_3 0x8 /* Pattern Match Enable Byte 0 Bit 3 */
-#define nMATCH_EN_0_3 0x0
#define MATCH_EN_0_4 0x10 /* Pattern Match Enable Byte 0 Bit 4 */
-#define nMATCH_EN_0_4 0x0
#define MATCH_EN_0_5 0x20 /* Pattern Match Enable Byte 0 Bit 5 */
-#define nMATCH_EN_0_5 0x0
#define MATCH_EN_0_6 0x40 /* Pattern Match Enable Byte 0 Bit 6 */
-#define nMATCH_EN_0_6 0x0
#define MATCH_EN_0_7 0x80 /* Pattern Match Enable Byte 0 Bit 7 */
-#define nMATCH_EN_0_7 0x0
#define MATCH_EN_1_0 0x100 /* Pattern Match Enable Byte 1 Bit 0 */
-#define nMATCH_EN_1_0 0x0
#define MATCH_EN_1_1 0x200 /* Pattern Match Enable Byte 1 Bit 1 */
-#define nMATCH_EN_1_1 0x0
#define MATCH_EN_1_2 0x400 /* Pattern Match Enable Byte 1 Bit 2 */
-#define nMATCH_EN_1_2 0x0
#define MATCH_EN_1_3 0x800 /* Pattern Match Enable Byte 1 Bit 3 */
-#define nMATCH_EN_1_3 0x0
#define MATCH_EN_1_4 0x1000 /* Pattern Match Enable Byte 1 Bit 4 */
-#define nMATCH_EN_1_4 0x0
#define MATCH_EN_1_5 0x2000 /* Pattern Match Enable Byte 1 Bit 5 */
-#define nMATCH_EN_1_5 0x0
#define MATCH_EN_1_6 0x4000 /* Pattern Match Enable Byte 1 Bit 6 */
-#define nMATCH_EN_1_6 0x0
#define MATCH_EN_1_7 0x8000 /* Pattern Match Enable Byte 1 Bit 7 */
-#define nMATCH_EN_1_7 0x0
#define MATCH_EN_2_0 0x10000 /* Pattern Match Enable Byte 2 Bit 0 */
-#define nMATCH_EN_2_0 0x0
#define MATCH_EN_2_1 0x20000 /* Pattern Match Enable Byte 2 Bit 1 */
-#define nMATCH_EN_2_1 0x0
#define MATCH_EN_2_2 0x40000 /* Pattern Match Enable Byte 2 Bit 2 */
-#define nMATCH_EN_2_2 0x0
#define MATCH_EN_2_3 0x80000 /* Pattern Match Enable Byte 2 Bit 3 */
-#define nMATCH_EN_2_3 0x0
#define MATCH_EN_2_4 0x100000 /* Pattern Match Enable Byte 2 Bit 4 */
-#define nMATCH_EN_2_4 0x0
#define MATCH_EN_2_5 0x200000 /* Pattern Match Enable Byte 2 Bit 5 */
-#define nMATCH_EN_2_5 0x0
#define MATCH_EN_2_6 0x400000 /* Pattern Match Enable Byte 2 Bit 6 */
-#define nMATCH_EN_2_6 0x0
#define MATCH_EN_2_7 0x800000 /* Pattern Match Enable Byte 2 Bit 7 */
-#define nMATCH_EN_2_7 0x0
#define MATCH_EN_3_0 0x1000000 /* Pattern Match Enable Byte 3 Bit 0 */
-#define nMATCH_EN_3_0 0x0
#define MATCH_EN_3_1 0x2000000 /* Pattern Match Enable Byte 3 Bit 1 */
-#define nMATCH_EN_3_1 0x0
#define MATCH_EN_3_2 0x4000000 /* Pattern Match Enable Byte 3 Bit 2 */
-#define nMATCH_EN_3_2 0x0
#define MATCH_EN_3_3 0x8000000 /* Pattern Match Enable Byte 3 Bit 3 */
-#define nMATCH_EN_3_3 0x0
#define MATCH_EN_3_4 0x10000000 /* Pattern Match Enable Byte 3 Bit 4 */
-#define nMATCH_EN_3_4 0x0
#define MATCH_EN_3_5 0x20000000 /* Pattern Match Enable Byte 3 Bit 5 */
-#define nMATCH_EN_3_5 0x0
#define MATCH_EN_3_6 0x40000000 /* Pattern Match Enable Byte 3 Bit 6 */
-#define nMATCH_EN_3_6 0x0
#define MATCH_EN_3_7 0x80000000 /* Pattern Match Enable Byte 3 Bit 7 */
-#define nMATCH_EN_3_7 0x0
/* Bit masks for MXVR_FRAME_CNT_0 */
@@ -2188,226 +1838,166 @@
#define TX_CH0 0x3f /* Transmit Channel 0 */
#define MUTE_CH0 0x80 /* Mute Channel 0 */
-#define nMUTE_CH0 0x0
#define TX_CH1 0x3f00 /* Transmit Channel 0 */
#define MUTE_CH1 0x8000 /* Mute Channel 0 */
-#define nMUTE_CH1 0x0
#define TX_CH2 0x3f0000 /* Transmit Channel 0 */
#define MUTE_CH2 0x800000 /* Mute Channel 0 */
-#define nMUTE_CH2 0x0
#define TX_CH3 0x3f000000 /* Transmit Channel 0 */
#define MUTE_CH3 0x80000000 /* Mute Channel 0 */
-#define nMUTE_CH3 0x0
/* Bit masks for MXVR_ROUTING_1 */
#define TX_CH4 0x3f /* Transmit Channel 4 */
#define MUTE_CH4 0x80 /* Mute Channel 4 */
-#define nMUTE_CH4 0x0
#define TX_CH5 0x3f00 /* Transmit Channel 5 */
#define MUTE_CH5 0x8000 /* Mute Channel 5 */
-#define nMUTE_CH5 0x0
#define TX_CH6 0x3f0000 /* Transmit Channel 6 */
#define MUTE_CH6 0x800000 /* Mute Channel 6 */
-#define nMUTE_CH6 0x0
#define TX_CH7 0x3f000000 /* Transmit Channel 7 */
#define MUTE_CH7 0x80000000 /* Mute Channel 7 */
-#define nMUTE_CH7 0x0
/* Bit masks for MXVR_ROUTING_2 */
#define TX_CH8 0x3f /* Transmit Channel 8 */
#define MUTE_CH8 0x80 /* Mute Channel 8 */
-#define nMUTE_CH8 0x0
#define TX_CH9 0x3f00 /* Transmit Channel 9 */
#define MUTE_CH9 0x8000 /* Mute Channel 9 */
-#define nMUTE_CH9 0x0
#define TX_CH10 0x3f0000 /* Transmit Channel 10 */
#define MUTE_CH10 0x800000 /* Mute Channel 10 */
-#define nMUTE_CH10 0x0
#define TX_CH11 0x3f000000 /* Transmit Channel 11 */
#define MUTE_CH11 0x80000000 /* Mute Channel 11 */
-#define nMUTE_CH11 0x0
/* Bit masks for MXVR_ROUTING_3 */
#define TX_CH12 0x3f /* Transmit Channel 12 */
#define MUTE_CH12 0x80 /* Mute Channel 12 */
-#define nMUTE_CH12 0x0
#define TX_CH13 0x3f00 /* Transmit Channel 13 */
#define MUTE_CH13 0x8000 /* Mute Channel 13 */
-#define nMUTE_CH13 0x0
#define TX_CH14 0x3f0000 /* Transmit Channel 14 */
#define MUTE_CH14 0x800000 /* Mute Channel 14 */
-#define nMUTE_CH14 0x0
#define TX_CH15 0x3f000000 /* Transmit Channel 15 */
#define MUTE_CH15 0x80000000 /* Mute Channel 15 */
-#define nMUTE_CH15 0x0
/* Bit masks for MXVR_ROUTING_4 */
#define TX_CH16 0x3f /* Transmit Channel 16 */
#define MUTE_CH16 0x80 /* Mute Channel 16 */
-#define nMUTE_CH16 0x0
#define TX_CH17 0x3f00 /* Transmit Channel 17 */
#define MUTE_CH17 0x8000 /* Mute Channel 17 */
-#define nMUTE_CH17 0x0
#define TX_CH18 0x3f0000 /* Transmit Channel 18 */
#define MUTE_CH18 0x800000 /* Mute Channel 18 */
-#define nMUTE_CH18 0x0
#define TX_CH19 0x3f000000 /* Transmit Channel 19 */
#define MUTE_CH19 0x80000000 /* Mute Channel 19 */
-#define nMUTE_CH19 0x0
/* Bit masks for MXVR_ROUTING_5 */
#define TX_CH20 0x3f /* Transmit Channel 20 */
#define MUTE_CH20 0x80 /* Mute Channel 20 */
-#define nMUTE_CH20 0x0
#define TX_CH21 0x3f00 /* Transmit Channel 21 */
#define MUTE_CH21 0x8000 /* Mute Channel 21 */
-#define nMUTE_CH21 0x0
#define TX_CH22 0x3f0000 /* Transmit Channel 22 */
#define MUTE_CH22 0x800000 /* Mute Channel 22 */
-#define nMUTE_CH22 0x0
#define TX_CH23 0x3f000000 /* Transmit Channel 23 */
#define MUTE_CH23 0x80000000 /* Mute Channel 23 */
-#define nMUTE_CH23 0x0
/* Bit masks for MXVR_ROUTING_6 */
#define TX_CH24 0x3f /* Transmit Channel 24 */
#define MUTE_CH24 0x80 /* Mute Channel 24 */
-#define nMUTE_CH24 0x0
#define TX_CH25 0x3f00 /* Transmit Channel 25 */
#define MUTE_CH25 0x8000 /* Mute Channel 25 */
-#define nMUTE_CH25 0x0
#define TX_CH26 0x3f0000 /* Transmit Channel 26 */
#define MUTE_CH26 0x800000 /* Mute Channel 26 */
-#define nMUTE_CH26 0x0
#define TX_CH27 0x3f000000 /* Transmit Channel 27 */
#define MUTE_CH27 0x80000000 /* Mute Channel 27 */
-#define nMUTE_CH27 0x0
/* Bit masks for MXVR_ROUTING_7 */
#define TX_CH28 0x3f /* Transmit Channel 28 */
#define MUTE_CH28 0x80 /* Mute Channel 28 */
-#define nMUTE_CH28 0x0
#define TX_CH29 0x3f00 /* Transmit Channel 29 */
#define MUTE_CH29 0x8000 /* Mute Channel 29 */
-#define nMUTE_CH29 0x0
#define TX_CH30 0x3f0000 /* Transmit Channel 30 */
#define MUTE_CH30 0x800000 /* Mute Channel 30 */
-#define nMUTE_CH30 0x0
#define TX_CH31 0x3f000000 /* Transmit Channel 31 */
#define MUTE_CH31 0x80000000 /* Mute Channel 31 */
-#define nMUTE_CH31 0x0
/* Bit masks for MXVR_ROUTING_8 */
#define TX_CH32 0x3f /* Transmit Channel 32 */
#define MUTE_CH32 0x80 /* Mute Channel 32 */
-#define nMUTE_CH32 0x0
#define TX_CH33 0x3f00 /* Transmit Channel 33 */
#define MUTE_CH33 0x8000 /* Mute Channel 33 */
-#define nMUTE_CH33 0x0
#define TX_CH34 0x3f0000 /* Transmit Channel 34 */
#define MUTE_CH34 0x800000 /* Mute Channel 34 */
-#define nMUTE_CH34 0x0
#define TX_CH35 0x3f000000 /* Transmit Channel 35 */
#define MUTE_CH35 0x80000000 /* Mute Channel 35 */
-#define nMUTE_CH35 0x0
/* Bit masks for MXVR_ROUTING_9 */
#define TX_CH36 0x3f /* Transmit Channel 36 */
#define MUTE_CH36 0x80 /* Mute Channel 36 */
-#define nMUTE_CH36 0x0
#define TX_CH37 0x3f00 /* Transmit Channel 37 */
#define MUTE_CH37 0x8000 /* Mute Channel 37 */
-#define nMUTE_CH37 0x0
#define TX_CH38 0x3f0000 /* Transmit Channel 38 */
#define MUTE_CH38 0x800000 /* Mute Channel 38 */
-#define nMUTE_CH38 0x0
#define TX_CH39 0x3f000000 /* Transmit Channel 39 */
#define MUTE_CH39 0x80000000 /* Mute Channel 39 */
-#define nMUTE_CH39 0x0
/* Bit masks for MXVR_ROUTING_10 */
#define TX_CH40 0x3f /* Transmit Channel 40 */
#define MUTE_CH40 0x80 /* Mute Channel 40 */
-#define nMUTE_CH40 0x0
#define TX_CH41 0x3f00 /* Transmit Channel 41 */
#define MUTE_CH41 0x8000 /* Mute Channel 41 */
-#define nMUTE_CH41 0x0
#define TX_CH42 0x3f0000 /* Transmit Channel 42 */
#define MUTE_CH42 0x800000 /* Mute Channel 42 */
-#define nMUTE_CH42 0x0
#define TX_CH43 0x3f000000 /* Transmit Channel 43 */
#define MUTE_CH43 0x80000000 /* Mute Channel 43 */
-#define nMUTE_CH43 0x0
/* Bit masks for MXVR_ROUTING_11 */
#define TX_CH44 0x3f /* Transmit Channel 44 */
#define MUTE_CH44 0x80 /* Mute Channel 44 */
-#define nMUTE_CH44 0x0
#define TX_CH45 0x3f00 /* Transmit Channel 45 */
#define MUTE_CH45 0x8000 /* Mute Channel 45 */
-#define nMUTE_CH45 0x0
#define TX_CH46 0x3f0000 /* Transmit Channel 46 */
#define MUTE_CH46 0x800000 /* Mute Channel 46 */
-#define nMUTE_CH46 0x0
#define TX_CH47 0x3f000000 /* Transmit Channel 47 */
#define MUTE_CH47 0x80000000 /* Mute Channel 47 */
-#define nMUTE_CH47 0x0
/* Bit masks for MXVR_ROUTING_12 */
#define TX_CH48 0x3f /* Transmit Channel 48 */
#define MUTE_CH48 0x80 /* Mute Channel 48 */
-#define nMUTE_CH48 0x0
#define TX_CH49 0x3f00 /* Transmit Channel 49 */
#define MUTE_CH49 0x8000 /* Mute Channel 49 */
-#define nMUTE_CH49 0x0
#define TX_CH50 0x3f0000 /* Transmit Channel 50 */
#define MUTE_CH50 0x800000 /* Mute Channel 50 */
-#define nMUTE_CH50 0x0
#define TX_CH51 0x3f000000 /* Transmit Channel 51 */
#define MUTE_CH51 0x80000000 /* Mute Channel 51 */
-#define nMUTE_CH51 0x0
/* Bit masks for MXVR_ROUTING_13 */
#define TX_CH52 0x3f /* Transmit Channel 52 */
#define MUTE_CH52 0x80 /* Mute Channel 52 */
-#define nMUTE_CH52 0x0
#define TX_CH53 0x3f00 /* Transmit Channel 53 */
#define MUTE_CH53 0x8000 /* Mute Channel 53 */
-#define nMUTE_CH53 0x0
#define TX_CH54 0x3f0000 /* Transmit Channel 54 */
#define MUTE_CH54 0x800000 /* Mute Channel 54 */
-#define nMUTE_CH54 0x0
#define TX_CH55 0x3f000000 /* Transmit Channel 55 */
#define MUTE_CH55 0x80000000 /* Mute Channel 55 */
-#define nMUTE_CH55 0x0
/* Bit masks for MXVR_ROUTING_14 */
#define TX_CH56 0x3f /* Transmit Channel 56 */
#define MUTE_CH56 0x80 /* Mute Channel 56 */
-#define nMUTE_CH56 0x0
#define TX_CH57 0x3f00 /* Transmit Channel 57 */
#define MUTE_CH57 0x8000 /* Mute Channel 57 */
-#define nMUTE_CH57 0x0
#define TX_CH58 0x3f0000 /* Transmit Channel 58 */
#define MUTE_CH58 0x800000 /* Mute Channel 58 */
-#define nMUTE_CH58 0x0
#define TX_CH59 0x3f000000 /* Transmit Channel 59 */
#define MUTE_CH59 0x80000000 /* Mute Channel 59 */
-#define nMUTE_CH59 0x0
/* Bit masks for MXVR_BLOCK_CNT */
@@ -2416,53 +2006,37 @@
/* Bit masks for MXVR_CLK_CTL */
#define MXTALCEN 0x1 /* MXVR Crystal Oscillator Clock Enable */
-#define nMXTALCEN 0x0
#define MXTALFEN 0x2 /* MXVR Crystal Oscillator Feedback Enable */
-#define nMXTALFEN 0x0
#define MXTALMUL 0x30 /* MXVR Crystal Multiplier */
#define CLKX3SEL 0x80 /* Clock Generation Source Select */
-#define nCLKX3SEL 0x0
#define MMCLKEN 0x100 /* Master Clock Enable */
-#define nMMCLKEN 0x0
#define MMCLKMUL 0x1e00 /* Master Clock Multiplication Factor */
#define PLLSMPS 0xe000 /* MXVR PLL State Machine Prescaler */
#define MBCLKEN 0x10000 /* Bit Clock Enable */
-#define nMBCLKEN 0x0
#define MBCLKDIV 0x1e0000 /* Bit Clock Divide Factor */
#define INVRX 0x800000 /* Invert Receive Data */
-#define nINVRX 0x0
#define MFSEN 0x1000000 /* Frame Sync Enable */
-#define nMFSEN 0x0
#define MFSDIV 0x1e000000 /* Frame Sync Divide Factor */
#define MFSSEL 0x60000000 /* Frame Sync Select */
#define MFSSYNC 0x80000000 /* Frame Sync Synchronization Select */
-#define nMFSSYNC 0x0
/* Bit masks for MXVR_CDRPLL_CTL */
#define CDRSMEN 0x1 /* MXVR CDRPLL State Machine Enable */
-#define nCDRSMEN 0x0
#define CDRRSTB 0x2 /* MXVR CDRPLL Reset */
-#define nCDRRSTB 0x0
#define CDRSVCO 0x4 /* MXVR CDRPLL Start VCO */
-#define nCDRSVCO 0x0
#define CDRMODE 0x8 /* MXVR CDRPLL CDR Mode Select */
-#define nCDRMODE 0x0
#define CDRSCNT 0x3f0 /* MXVR CDRPLL Start Counter */
#define CDRLCNT 0xfc00 /* MXVR CDRPLL Lock Counter */
#define CDRSHPSEL 0x3f0000 /* MXVR CDRPLL Shaper Select */
#define CDRSHPEN 0x800000 /* MXVR CDRPLL Shaper Enable */
-#define nCDRSHPEN 0x0
#define CDRCPSEL 0xff000000 /* MXVR CDRPLL Charge Pump Current Select */
/* Bit masks for MXVR_FMPLL_CTL */
#define FMSMEN 0x1 /* MXVR FMPLL State Machine Enable */
-#define nFMSMEN 0x0
#define FMRSTB 0x2 /* MXVR FMPLL Reset */
-#define nFMRSTB 0x0
#define FMSVCO 0x4 /* MXVR FMPLL Start VCO */
-#define nFMSVCO 0x0
#define FMSCNT 0x3f0 /* MXVR FMPLL Start Counter */
#define FMLCNT 0xfc00 /* MXVR FMPLL Lock Counter */
#define FMCPSEL 0xff000000 /* MXVR FMPLL Charge Pump Current Select */
@@ -2470,15 +2044,10 @@
/* Bit masks for MXVR_PIN_CTL */
#define MTXONBOD 0x1 /* MTXONB Open Drain Select */
-#define nMTXONBOD 0x0
#define MTXONBG 0x2 /* MTXONB Gates MTX Select */
-#define nMTXONBG 0x0
#define MFSOE 0x10 /* MFS Output Enable */
-#define nMFSOE 0x0
#define MFSGPSEL 0x20 /* MFS General Purpose Output Select */
-#define nMFSGPSEL 0x0
#define MFSGPDAT 0x40 /* MFS General Purpose Output Data */
-#define nMFSGPDAT 0x0
/* Bit masks for MXVR_SCLK_CNT */
@@ -2487,7 +2056,6 @@
/* Bit masks for KPAD_CTL */
#define KPAD_EN 0x1 /* Keypad Enable */
-#define nKPAD_EN 0x0
#define KPAD_IRQMODE 0x6 /* Key Press Interrupt Enable */
#define KPAD_ROWEN 0x1c00 /* Row Enable Width */
#define KPAD_COLEN 0xe000 /* Column Enable Width */
@@ -2509,29 +2077,21 @@
/* Bit masks for KPAD_STAT */
#define KPAD_IRQ 0x1 /* Keypad Interrupt Status */
-#define nKPAD_IRQ 0x0
#define KPAD_MROWCOL 0x6 /* Multiple Row/Column Keypress Status */
#define KPAD_PRESSED 0x8 /* Key press current status */
-#define nKPAD_PRESSED 0x0
/* Bit masks for KPAD_SOFTEVAL */
#define KPAD_SOFTEVAL_E 0x2 /* Software Programmable Force Evaluate */
-#define nKPAD_SOFTEVAL_E 0x0
/* Bit masks for SDH_COMMAND */
#define CMD_IDX 0x3f /* Command Index */
#define CMD_RSP 0x40 /* Response */
-#define nCMD_RSP 0x0
#define CMD_L_RSP 0x80 /* Long Response */
-#define nCMD_L_RSP 0x0
#define CMD_INT_E 0x100 /* Command Interrupt */
-#define nCMD_INT_E 0x0
#define CMD_PEND_E 0x200 /* Command Pending */
-#define nCMD_PEND_E 0x0
#define CMD_E 0x400 /* Command Enable */
-#define nCMD_E 0x0
/* Bit masks for SDH_PWR_CTL */
@@ -2540,21 +2100,15 @@
#define TBD 0x3c /* TBD */
#endif
#define SD_CMD_OD 0x40 /* Open Drain Output */
-#define nSD_CMD_OD 0x0
#define ROD_CTL 0x80 /* Rod Control */
-#define nROD_CTL 0x0
/* Bit masks for SDH_CLK_CTL */
#define CLKDIV 0xff /* MC_CLK Divisor */
#define CLK_E 0x100 /* MC_CLK Bus Clock Enable */
-#define nCLK_E 0x0
#define PWR_SV_E 0x200 /* Power Save Enable */
-#define nPWR_SV_E 0x0
#define CLKDIV_BYPASS 0x400 /* Bypass Divisor */
-#define nCLKDIV_BYPASS 0x0
#define WIDE_BUS 0x800 /* Wide Bus Mode Enable */
-#define nWIDE_BUS 0x0
/* Bit masks for SDH_RESP_CMD */
@@ -2563,133 +2117,74 @@
/* Bit masks for SDH_DATA_CTL */
#define DTX_E 0x1 /* Data Transfer Enable */
-#define nDTX_E 0x0
#define DTX_DIR 0x2 /* Data Transfer Direction */
-#define nDTX_DIR 0x0
#define DTX_MODE 0x4 /* Data Transfer Mode */
-#define nDTX_MODE 0x0
#define DTX_DMA_E 0x8 /* Data Transfer DMA Enable */
-#define nDTX_DMA_E 0x0
#define DTX_BLK_LGTH 0xf0 /* Data Transfer Block Length */
/* Bit masks for SDH_STATUS */
#define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */
-#define nCMD_CRC_FAIL 0x0
#define DAT_CRC_FAIL 0x2 /* Data CRC Fail */
-#define nDAT_CRC_FAIL 0x0
-#define CMD_TIMEOUT 0x4 /* CMD Time Out */
-#define nCMD_TIMEOUT 0x0
-#define DAT_TIMEOUT 0x8 /* Data Time Out */
-#define nDAT_TIMEOUT 0x0
+#define CMD_TIME_OUT 0x4 /* CMD Time Out */
+#define DAT_TIME_OUT 0x8 /* Data Time Out */
#define TX_UNDERRUN 0x10 /* Transmit Underrun */
-#define nTX_UNDERRUN 0x0
#define RX_OVERRUN 0x20 /* Receive Overrun */
-#define nRX_OVERRUN 0x0
#define CMD_RESP_END 0x40 /* CMD Response End */
-#define nCMD_RESP_END 0x0
#define CMD_SENT 0x80 /* CMD Sent */
-#define nCMD_SENT 0x0
#define DAT_END 0x100 /* Data End */
-#define nDAT_END 0x0
#define START_BIT_ERR 0x200 /* Start Bit Error */
-#define nSTART_BIT_ERR 0x0
#define DAT_BLK_END 0x400 /* Data Block End */
-#define nDAT_BLK_END 0x0
#define CMD_ACT 0x800 /* CMD Active */
-#define nCMD_ACT 0x0
#define TX_ACT 0x1000 /* Transmit Active */
-#define nTX_ACT 0x0
#define RX_ACT 0x2000 /* Receive Active */
-#define nRX_ACT 0x0
#define TX_FIFO_STAT 0x4000 /* Transmit FIFO Status */
-#define nTX_FIFO_STAT 0x0
#define RX_FIFO_STAT 0x8000 /* Receive FIFO Status */
-#define nRX_FIFO_STAT 0x0
#define TX_FIFO_FULL 0x10000 /* Transmit FIFO Full */
-#define nTX_FIFO_FULL 0x0
#define RX_FIFO_FULL 0x20000 /* Receive FIFO Full */
-#define nRX_FIFO_FULL 0x0
#define TX_FIFO_ZERO 0x40000 /* Transmit FIFO Empty */
-#define nTX_FIFO_ZERO 0x0
#define RX_DAT_ZERO 0x80000 /* Receive FIFO Empty */
-#define nRX_DAT_ZERO 0x0
#define TX_DAT_RDY 0x100000 /* Transmit Data Available */
-#define nTX_DAT_RDY 0x0
#define RX_FIFO_RDY 0x200000 /* Receive Data Available */
-#define nRX_FIFO_RDY 0x0
/* Bit masks for SDH_STATUS_CLR */
#define CMD_CRC_FAIL_STAT 0x1 /* CMD CRC Fail Status */
-#define nCMD_CRC_FAIL_STAT 0x0
#define DAT_CRC_FAIL_STAT 0x2 /* Data CRC Fail Status */
-#define nDAT_CRC_FAIL_STAT 0x0
#define CMD_TIMEOUT_STAT 0x4 /* CMD Time Out Status */
-#define nCMD_TIMEOUT_STAT 0x0
#define DAT_TIMEOUT_STAT 0x8 /* Data Time Out status */
-#define nDAT_TIMEOUT_STAT 0x0
#define TX_UNDERRUN_STAT 0x10 /* Transmit Underrun Status */
-#define nTX_UNDERRUN_STAT 0x0
#define RX_OVERRUN_STAT 0x20 /* Receive Overrun Status */
-#define nRX_OVERRUN_STAT 0x0
#define CMD_RESP_END_STAT 0x40 /* CMD Response End Status */
-#define nCMD_RESP_END_STAT 0x0
#define CMD_SENT_STAT 0x80 /* CMD Sent Status */
-#define nCMD_SENT_STAT 0x0
#define DAT_END_STAT 0x100 /* Data End Status */
-#define nDAT_END_STAT 0x0
#define START_BIT_ERR_STAT 0x200 /* Start Bit Error Status */
-#define nSTART_BIT_ERR_STAT 0x0
#define DAT_BLK_END_STAT 0x400 /* Data Block End Status */
-#define nDAT_BLK_END_STAT 0x0
/* Bit masks for SDH_MASK0 */
#define CMD_CRC_FAIL_MASK 0x1 /* CMD CRC Fail Mask */
-#define nCMD_CRC_FAIL_MASK 0x0
#define DAT_CRC_FAIL_MASK 0x2 /* Data CRC Fail Mask */
-#define nDAT_CRC_FAIL_MASK 0x0
#define CMD_TIMEOUT_MASK 0x4 /* CMD Time Out Mask */
-#define nCMD_TIMEOUT_MASK 0x0
#define DAT_TIMEOUT_MASK 0x8 /* Data Time Out Mask */
-#define nDAT_TIMEOUT_MASK 0x0
#define TX_UNDERRUN_MASK 0x10 /* Transmit Underrun Mask */
-#define nTX_UNDERRUN_MASK 0x0
#define RX_OVERRUN_MASK 0x20 /* Receive Overrun Mask */
-#define nRX_OVERRUN_MASK 0x0
#define CMD_RESP_END_MASK 0x40 /* CMD Response End Mask */
-#define nCMD_RESP_END_MASK 0x0
#define CMD_SENT_MASK 0x80 /* CMD Sent Mask */
-#define nCMD_SENT_MASK 0x0
#define DAT_END_MASK 0x100 /* Data End Mask */
-#define nDAT_END_MASK 0x0
#define START_BIT_ERR_MASK 0x200 /* Start Bit Error Mask */
-#define nSTART_BIT_ERR_MASK 0x0
#define DAT_BLK_END_MASK 0x400 /* Data Block End Mask */
-#define nDAT_BLK_END_MASK 0x0
#define CMD_ACT_MASK 0x800 /* CMD Active Mask */
-#define nCMD_ACT_MASK 0x0
#define TX_ACT_MASK 0x1000 /* Transmit Active Mask */
-#define nTX_ACT_MASK 0x0
#define RX_ACT_MASK 0x2000 /* Receive Active Mask */
-#define nRX_ACT_MASK 0x0
#define TX_FIFO_STAT_MASK 0x4000 /* Transmit FIFO Status Mask */
-#define nTX_FIFO_STAT_MASK 0x0
#define RX_FIFO_STAT_MASK 0x8000 /* Receive FIFO Status Mask */
-#define nRX_FIFO_STAT_MASK 0x0
#define TX_FIFO_FULL_MASK 0x10000 /* Transmit FIFO Full Mask */
-#define nTX_FIFO_FULL_MASK 0x0
#define RX_FIFO_FULL_MASK 0x20000 /* Receive FIFO Full Mask */
-#define nRX_FIFO_FULL_MASK 0x0
#define TX_FIFO_ZERO_MASK 0x40000 /* Transmit FIFO Empty Mask */
-#define nTX_FIFO_ZERO_MASK 0x0
#define RX_DAT_ZERO_MASK 0x80000 /* Receive FIFO Empty Mask */
-#define nRX_DAT_ZERO_MASK 0x0
#define TX_DAT_RDY_MASK 0x100000 /* Transmit Data Available Mask */
-#define nTX_DAT_RDY_MASK 0x0
#define RX_FIFO_RDY_MASK 0x200000 /* Receive Data Available Mask */
-#define nRX_FIFO_RDY_MASK 0x0
/* Bit masks for SDH_FIFO_CNT */
@@ -2698,73 +2193,47 @@
/* Bit masks for SDH_E_STATUS */
#define SDIO_INT_DET 0x2 /* SDIO Int Detected */
-#define nSDIO_INT_DET 0x0
#define SD_CARD_DET 0x10 /* SD Card Detect */
-#define nSD_CARD_DET 0x0
/* Bit masks for SDH_E_MASK */
#define SDIO_MSK 0x2 /* Mask SDIO Int Detected */
-#define nSDIO_MSK 0x0
#define SCD_MSK 0x40 /* Mask Card Detect */
-#define nSCD_MSK 0x0
/* Bit masks for SDH_CFG */
#define CLKS_EN 0x1 /* Clocks Enable */
-#define nCLKS_EN 0x0
#define SD4E 0x4 /* SDIO 4-Bit Enable */
-#define nSD4E 0x0
#define MWE 0x8 /* Moving Window Enable */
-#define nMWE 0x0
#define SD_RST 0x10 /* SDMMC Reset */
-#define nSD_RST 0x0
#define PUP_SDDAT 0x20 /* Pull-up SD_DAT */
-#define nPUP_SDDAT 0x0
#define PUP_SDDAT3 0x40 /* Pull-up SD_DAT3 */
-#define nPUP_SDDAT3 0x0
#define PD_SDDAT3 0x80 /* Pull-down SD_DAT3 */
-#define nPD_SDDAT3 0x0
/* Bit masks for SDH_RD_WAIT_EN */
#define RWR 0x1 /* Read Wait Request */
-#define nRWR 0x0
/* Bit masks for ATAPI_CONTROL */
#define PIO_START 0x1 /* Start PIO/Reg Op */
-#define nPIO_START 0x0
#define MULTI_START 0x2 /* Start Multi-DMA Op */
-#define nMULTI_START 0x0
#define ULTRA_START 0x4 /* Start Ultra-DMA Op */
-#define nULTRA_START 0x0
#define XFER_DIR 0x8 /* Transfer Direction */
-#define nXFER_DIR 0x0
#define IORDY_EN 0x10 /* IORDY Enable */
-#define nIORDY_EN 0x0
#define FIFO_FLUSH 0x20 /* Flush FIFOs */
-#define nFIFO_FLUSH 0x0
#define SOFT_RST 0x40 /* Soft Reset */
-#define nSOFT_RST 0x0
#define DEV_RST 0x80 /* Device Reset */
-#define nDEV_RST 0x0
#define TFRCNT_RST 0x100 /* Trans Count Reset */
-#define nTFRCNT_RST 0x0
#define END_ON_TERM 0x200 /* End/Terminate Select */
-#define nEND_ON_TERM 0x0
#define PIO_USE_DMA 0x400 /* PIO-DMA Enable */
-#define nPIO_USE_DMA 0x0
#define UDMAIN_FIFO_THRS 0xf000 /* Ultra DMA-IN FIFO Threshold */
/* Bit masks for ATAPI_STATUS */
#define PIO_XFER_ON 0x1 /* PIO transfer in progress */
-#define nPIO_XFER_ON 0x0
#define MULTI_XFER_ON 0x2 /* Multi-word DMA transfer in progress */
-#define nMULTI_XFER_ON 0x0
#define ULTRA_XFER_ON 0x4 /* Ultra DMA transfer in progress */
-#define nULTRA_XFER_ON 0x0
#define ULTRA_IN_FL 0xf0 /* Ultra DMA Input FIFO Level */
/* Bit masks for ATAPI_DEV_ADDR */
@@ -2774,66 +2243,39 @@
/* Bit masks for ATAPI_INT_MASK */
#define ATAPI_DEV_INT_MASK 0x1 /* Device interrupt mask */
-#define nATAPI_DEV_INT_MASK 0x0
#define PIO_DONE_MASK 0x2 /* PIO transfer done interrupt mask */
-#define nPIO_DONE_MASK 0x0
#define MULTI_DONE_MASK 0x4 /* Multi-DMA transfer done interrupt mask */
-#define nMULTI_DONE_MASK 0x0
#define UDMAIN_DONE_MASK 0x8 /* Ultra-DMA in transfer done interrupt mask */
-#define nUDMAIN_DONE_MASK 0x0
#define UDMAOUT_DONE_MASK 0x10 /* Ultra-DMA out transfer done interrupt mask */
-#define nUDMAOUT_DONE_MASK 0x0
#define HOST_TERM_XFER_MASK 0x20 /* Host terminate current transfer interrupt mask */
-#define nHOST_TERM_XFER_MASK 0x0
#define MULTI_TERM_MASK 0x40 /* Device terminate Multi-DMA transfer interrupt mask */
-#define nMULTI_TERM_MASK 0x0
#define UDMAIN_TERM_MASK 0x80 /* Device terminate Ultra-DMA-in transfer interrupt mask */
-#define nUDMAIN_TERM_MASK 0x0
#define UDMAOUT_TERM_MASK 0x100 /* Device terminate Ultra-DMA-out transfer interrupt mask */
-#define nUDMAOUT_TERM_MASK 0x0
/* Bit masks for ATAPI_INT_STATUS */
#define ATAPI_DEV_INT 0x1 /* Device interrupt status */
-#define nATAPI_DEV_INT 0x0
#define PIO_DONE_INT 0x2 /* PIO transfer done interrupt status */
-#define nPIO_DONE_INT 0x0
#define MULTI_DONE_INT 0x4 /* Multi-DMA transfer done interrupt status */
-#define nMULTI_DONE_INT 0x0
#define UDMAIN_DONE_INT 0x8 /* Ultra-DMA in transfer done interrupt status */
-#define nUDMAIN_DONE_INT 0x0
#define UDMAOUT_DONE_INT 0x10 /* Ultra-DMA out transfer done interrupt status */
-#define nUDMAOUT_DONE_INT 0x0
#define HOST_TERM_XFER_INT 0x20 /* Host terminate current transfer interrupt status */
-#define nHOST_TERM_XFER_INT 0x0
#define MULTI_TERM_INT 0x40 /* Device terminate Multi-DMA transfer interrupt status */
-#define nMULTI_TERM_INT 0x0
#define UDMAIN_TERM_INT 0x80 /* Device terminate Ultra-DMA-in transfer interrupt status */
-#define nUDMAIN_TERM_INT 0x0
#define UDMAOUT_TERM_INT 0x100 /* Device terminate Ultra-DMA-out transfer interrupt status */
-#define nUDMAOUT_TERM_INT 0x0
/* Bit masks for ATAPI_LINE_STATUS */
#define ATAPI_INTR 0x1 /* Device interrupt to host line status */
-#define nATAPI_INTR 0x0
#define ATAPI_DASP 0x2 /* Device dasp to host line status */
-#define nATAPI_DASP 0x0
#define ATAPI_CS0N 0x4 /* ATAPI chip select 0 line status */
-#define nATAPI_CS0N 0x0
#define ATAPI_CS1N 0x8 /* ATAPI chip select 1 line status */
-#define nATAPI_CS1N 0x0
#define ATAPI_ADDR 0x70 /* ATAPI address line status */
#define ATAPI_DMAREQ 0x80 /* ATAPI DMA request line status */
-#define nATAPI_DMAREQ 0x0
#define ATAPI_DMAACKN 0x100 /* ATAPI DMA acknowledge line status */
-#define nATAPI_DMAACKN 0x0
#define ATAPI_DIOWN 0x200 /* ATAPI write line status */
-#define nATAPI_DIOWN 0x0
#define ATAPI_DIORN 0x400 /* ATAPI read line status */
-#define nATAPI_DIORN 0x0
#define ATAPI_IORDY 0x800 /* ATAPI IORDY line status */
-#define nATAPI_IORDY 0x0
/* Bit masks for ATAPI_SM_STATE */
@@ -2845,7 +2287,6 @@
/* Bit masks for ATAPI_TERMINATE */
#define ATAPI_HOST_TERM 0x1 /* Host terminationation */
-#define nATAPI_HOST_TERM 0x0
/* Bit masks for ATAPI_REG_TIM_0 */
@@ -2900,41 +2341,26 @@
/* Bit masks for TIMER_ENABLE1 */
#define TIMEN8 0x1 /* Timer 8 Enable */
-#define nTIMEN8 0x0
#define TIMEN9 0x2 /* Timer 9 Enable */
-#define nTIMEN9 0x0
#define TIMEN10 0x4 /* Timer 10 Enable */
-#define nTIMEN10 0x0
/* Bit masks for TIMER_DISABLE1 */
#define TIMDIS8 0x1 /* Timer 8 Disable */
-#define nTIMDIS8 0x0
#define TIMDIS9 0x2 /* Timer 9 Disable */
-#define nTIMDIS9 0x0
#define TIMDIS10 0x4 /* Timer 10 Disable */
-#define nTIMDIS10 0x0
/* Bit masks for TIMER_STATUS1 */
#define TIMIL8 0x1 /* Timer 8 Interrupt */
-#define nTIMIL8 0x0
#define TIMIL9 0x2 /* Timer 9 Interrupt */
-#define nTIMIL9 0x0
#define TIMIL10 0x4 /* Timer 10 Interrupt */
-#define nTIMIL10 0x0
#define TOVF_ERR8 0x10 /* Timer 8 Counter Overflow */
-#define nTOVF_ERR8 0x0
#define TOVF_ERR9 0x20 /* Timer 9 Counter Overflow */
-#define nTOVF_ERR9 0x0
#define TOVF_ERR10 0x40 /* Timer 10 Counter Overflow */
-#define nTOVF_ERR10 0x0
#define TRUN8 0x1000 /* Timer 8 Slave Enable Status */
-#define nTRUN8 0x0
#define TRUN9 0x2000 /* Timer 9 Slave Enable Status */
-#define nTRUN9 0x0
#define TRUN10 0x4000 /* Timer 10 Slave Enable Status */
-#define nTRUN10 0x0
/* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
@@ -2945,131 +2371,77 @@
/* Bit masks for USB_POWER */
#define ENABLE_SUSPENDM 0x1 /* enable SuspendM output */
-#define nENABLE_SUSPENDM 0x0
#define SUSPEND_MODE 0x2 /* Suspend Mode indicator */
-#define nSUSPEND_MODE 0x0
#define RESUME_MODE 0x4 /* DMA Mode */
-#define nRESUME_MODE 0x0
#define RESET 0x8 /* Reset indicator */
-#define nRESET 0x0
#define HS_MODE 0x10 /* High Speed mode indicator */
-#define nHS_MODE 0x0
#define HS_ENABLE 0x20 /* high Speed Enable */
-#define nHS_ENABLE 0x0
#define SOFT_CONN 0x40 /* Soft connect */
-#define nSOFT_CONN 0x0
#define ISO_UPDATE 0x80 /* Isochronous update */
-#define nISO_UPDATE 0x0
/* Bit masks for USB_INTRTX */
#define EP0_TX 0x1 /* Tx Endpoint 0 interrupt */
-#define nEP0_TX 0x0
#define EP1_TX 0x2 /* Tx Endpoint 1 interrupt */
-#define nEP1_TX 0x0
#define EP2_TX 0x4 /* Tx Endpoint 2 interrupt */
-#define nEP2_TX 0x0
#define EP3_TX 0x8 /* Tx Endpoint 3 interrupt */
-#define nEP3_TX 0x0
#define EP4_TX 0x10 /* Tx Endpoint 4 interrupt */
-#define nEP4_TX 0x0
#define EP5_TX 0x20 /* Tx Endpoint 5 interrupt */
-#define nEP5_TX 0x0
#define EP6_TX 0x40 /* Tx Endpoint 6 interrupt */
-#define nEP6_TX 0x0
#define EP7_TX 0x80 /* Tx Endpoint 7 interrupt */
-#define nEP7_TX 0x0
/* Bit masks for USB_INTRRX */
#define EP1_RX 0x2 /* Rx Endpoint 1 interrupt */
-#define nEP1_RX 0x0
#define EP2_RX 0x4 /* Rx Endpoint 2 interrupt */
-#define nEP2_RX 0x0
#define EP3_RX 0x8 /* Rx Endpoint 3 interrupt */
-#define nEP3_RX 0x0
#define EP4_RX 0x10 /* Rx Endpoint 4 interrupt */
-#define nEP4_RX 0x0
#define EP5_RX 0x20 /* Rx Endpoint 5 interrupt */
-#define nEP5_RX 0x0
#define EP6_RX 0x40 /* Rx Endpoint 6 interrupt */
-#define nEP6_RX 0x0
#define EP7_RX 0x80 /* Rx Endpoint 7 interrupt */
-#define nEP7_RX 0x0
/* Bit masks for USB_INTRTXE */
#define EP0_TX_E 0x1 /* Endpoint 0 interrupt Enable */
-#define nEP0_TX_E 0x0
#define EP1_TX_E 0x2 /* Tx Endpoint 1 interrupt Enable */
-#define nEP1_TX_E 0x0
#define EP2_TX_E 0x4 /* Tx Endpoint 2 interrupt Enable */
-#define nEP2_TX_E 0x0
#define EP3_TX_E 0x8 /* Tx Endpoint 3 interrupt Enable */
-#define nEP3_TX_E 0x0
#define EP4_TX_E 0x10 /* Tx Endpoint 4 interrupt Enable */
-#define nEP4_TX_E 0x0
#define EP5_TX_E 0x20 /* Tx Endpoint 5 interrupt Enable */
-#define nEP5_TX_E 0x0
#define EP6_TX_E 0x40 /* Tx Endpoint 6 interrupt Enable */
-#define nEP6_TX_E 0x0
#define EP7_TX_E 0x80 /* Tx Endpoint 7 interrupt Enable */
-#define nEP7_TX_E 0x0
/* Bit masks for USB_INTRRXE */
#define EP1_RX_E 0x2 /* Rx Endpoint 1 interrupt Enable */
-#define nEP1_RX_E 0x0
#define EP2_RX_E 0x4 /* Rx Endpoint 2 interrupt Enable */
-#define nEP2_RX_E 0x0
#define EP3_RX_E 0x8 /* Rx Endpoint 3 interrupt Enable */
-#define nEP3_RX_E 0x0
#define EP4_RX_E 0x10 /* Rx Endpoint 4 interrupt Enable */
-#define nEP4_RX_E 0x0
#define EP5_RX_E 0x20 /* Rx Endpoint 5 interrupt Enable */
-#define nEP5_RX_E 0x0
#define EP6_RX_E 0x40 /* Rx Endpoint 6 interrupt Enable */
-#define nEP6_RX_E 0x0
#define EP7_RX_E 0x80 /* Rx Endpoint 7 interrupt Enable */
-#define nEP7_RX_E 0x0
/* Bit masks for USB_INTRUSB */
#define SUSPEND_B 0x1 /* Suspend indicator */
-#define nSUSPEND_B 0x0
#define RESUME_B 0x2 /* Resume indicator */
-#define nRESUME_B 0x0
#define RESET_OR_BABLE_B 0x4 /* Reset/babble indicator */
-#define nRESET_OR_BABLE_B 0x0
#define SOF_B 0x8 /* Start of frame */
-#define nSOF_B 0x0
#define CONN_B 0x10 /* Connection indicator */
-#define nCONN_B 0x0
#define DISCON_B 0x20 /* Disconnect indicator */
-#define nDISCON_B 0x0
#define SESSION_REQ_B 0x40 /* Session Request */
-#define nSESSION_REQ_B 0x0
#define VBUS_ERROR_B 0x80 /* Vbus threshold indicator */
-#define nVBUS_ERROR_B 0x0
/* Bit masks for USB_INTRUSBE */
#define SUSPEND_BE 0x1 /* Suspend indicator int enable */
-#define nSUSPEND_BE 0x0
#define RESUME_BE 0x2 /* Resume indicator int enable */
-#define nRESUME_BE 0x0
#define RESET_OR_BABLE_BE 0x4 /* Reset/babble indicator int enable */
-#define nRESET_OR_BABLE_BE 0x0
#define SOF_BE 0x8 /* Start of frame int enable */
-#define nSOF_BE 0x0
#define CONN_BE 0x10 /* Connection indicator int enable */
-#define nCONN_BE 0x0
#define DISCON_BE 0x20 /* Disconnect indicator int enable */
-#define nDISCON_BE 0x0
#define SESSION_REQ_BE 0x40 /* Session Request int enable */
-#define nSESSION_REQ_BE 0x0
#define VBUS_ERROR_BE 0x80 /* Vbus threshold indicator int enable */
-#define nVBUS_ERROR_BE 0x0
/* Bit masks for USB_FRAME */
@@ -3082,117 +2454,67 @@
/* Bit masks for USB_GLOBAL_CTL */
#define GLOBAL_ENA 0x1 /* enables USB module */
-#define nGLOBAL_ENA 0x0
#define EP1_TX_ENA 0x2 /* Transmit endpoint 1 enable */
-#define nEP1_TX_ENA 0x0
#define EP2_TX_ENA 0x4 /* Transmit endpoint 2 enable */
-#define nEP2_TX_ENA 0x0
#define EP3_TX_ENA 0x8 /* Transmit endpoint 3 enable */
-#define nEP3_TX_ENA 0x0
#define EP4_TX_ENA 0x10 /* Transmit endpoint 4 enable */
-#define nEP4_TX_ENA 0x0
#define EP5_TX_ENA 0x20 /* Transmit endpoint 5 enable */
-#define nEP5_TX_ENA 0x0
#define EP6_TX_ENA 0x40 /* Transmit endpoint 6 enable */
-#define nEP6_TX_ENA 0x0
#define EP7_TX_ENA 0x80 /* Transmit endpoint 7 enable */
-#define nEP7_TX_ENA 0x0
#define EP1_RX_ENA 0x100 /* Receive endpoint 1 enable */
-#define nEP1_RX_ENA 0x0
#define EP2_RX_ENA 0x200 /* Receive endpoint 2 enable */
-#define nEP2_RX_ENA 0x0
#define EP3_RX_ENA 0x400 /* Receive endpoint 3 enable */
-#define nEP3_RX_ENA 0x0
#define EP4_RX_ENA 0x800 /* Receive endpoint 4 enable */
-#define nEP4_RX_ENA 0x0
#define EP5_RX_ENA 0x1000 /* Receive endpoint 5 enable */
-#define nEP5_RX_ENA 0x0
#define EP6_RX_ENA 0x2000 /* Receive endpoint 6 enable */
-#define nEP6_RX_ENA 0x0
#define EP7_RX_ENA 0x4000 /* Receive endpoint 7 enable */
-#define nEP7_RX_ENA 0x0
/* Bit masks for USB_OTG_DEV_CTL */
#define SESSION 0x1 /* session indicator */
-#define nSESSION 0x0
#define HOST_REQ 0x2 /* Host negotiation request */
-#define nHOST_REQ 0x0
#define HOST_MODE 0x4 /* indicates USBDRC is a host */
-#define nHOST_MODE 0x0
#define VBUS0 0x8 /* Vbus level indicator[0] */
-#define nVBUS0 0x0
#define VBUS1 0x10 /* Vbus level indicator[1] */
-#define nVBUS1 0x0
#define LSDEV 0x20 /* Low-speed indicator */
-#define nLSDEV 0x0
#define FSDEV 0x40 /* Full or High-speed indicator */
-#define nFSDEV 0x0
#define B_DEVICE 0x80 /* A' or 'B' device indicator */
-#define nB_DEVICE 0x0
/* Bit masks for USB_OTG_VBUS_IRQ */
#define DRIVE_VBUS_ON 0x1 /* indicator to drive VBUS control circuit */
-#define nDRIVE_VBUS_ON 0x0
#define DRIVE_VBUS_OFF 0x2 /* indicator to shut off charge pump */
-#define nDRIVE_VBUS_OFF 0x0
#define CHRG_VBUS_START 0x4 /* indicator for external circuit to start charging VBUS */
-#define nCHRG_VBUS_START 0x0
#define CHRG_VBUS_END 0x8 /* indicator for external circuit to end charging VBUS */
-#define nCHRG_VBUS_END 0x0
#define DISCHRG_VBUS_START 0x10 /* indicator to start discharging VBUS */
-#define nDISCHRG_VBUS_START 0x0
#define DISCHRG_VBUS_END 0x20 /* indicator to stop discharging VBUS */
-#define nDISCHRG_VBUS_END 0x0
/* Bit masks for USB_OTG_VBUS_MASK */
#define DRIVE_VBUS_ON_ENA 0x1 /* enable DRIVE_VBUS_ON interrupt */
-#define nDRIVE_VBUS_ON_ENA 0x0
#define DRIVE_VBUS_OFF_ENA 0x2 /* enable DRIVE_VBUS_OFF interrupt */
-#define nDRIVE_VBUS_OFF_ENA 0x0
#define CHRG_VBUS_START_ENA 0x4 /* enable CHRG_VBUS_START interrupt */
-#define nCHRG_VBUS_START_ENA 0x0
#define CHRG_VBUS_END_ENA 0x8 /* enable CHRG_VBUS_END interrupt */
-#define nCHRG_VBUS_END_ENA 0x0
#define DISCHRG_VBUS_START_ENA 0x10 /* enable DISCHRG_VBUS_START interrupt */
-#define nDISCHRG_VBUS_START_ENA 0x0
#define DISCHRG_VBUS_END_ENA 0x20 /* enable DISCHRG_VBUS_END interrupt */
-#define nDISCHRG_VBUS_END_ENA 0x0
/* Bit masks for USB_CSR0 */
#define RXPKTRDY 0x1 /* data packet receive indicator */
-#define nRXPKTRDY 0x0
#define TXPKTRDY 0x2 /* data packet in FIFO indicator */
-#define nTXPKTRDY 0x0
#define STALL_SENT 0x4 /* STALL handshake sent */
-#define nSTALL_SENT 0x0
#define DATAEND 0x8 /* Data end indicator */
-#define nDATAEND 0x0
#define SETUPEND 0x10 /* Setup end */
-#define nSETUPEND 0x0
#define SENDSTALL 0x20 /* Send STALL handshake */
-#define nSENDSTALL 0x0
#define SERVICED_RXPKTRDY 0x40 /* used to clear the RxPktRdy bit */
-#define nSERVICED_RXPKTRDY 0x0
#define SERVICED_SETUPEND 0x80 /* used to clear the SetupEnd bit */
-#define nSERVICED_SETUPEND 0x0
#define FLUSHFIFO 0x100 /* flush endpoint FIFO */
-#define nFLUSHFIFO 0x0
#define STALL_RECEIVED_H 0x4 /* STALL handshake received host mode */
-#define nSTALL_RECEIVED_H 0x0
#define SETUPPKT_H 0x8 /* send Setup token host mode */
-#define nSETUPPKT_H 0x0
#define ERROR_H 0x10 /* timeout error indicator host mode */
-#define nERROR_H 0x0
#define REQPKT_H 0x20 /* Request an IN transaction host mode */
-#define nREQPKT_H 0x0
#define STATUSPKT_H 0x40 /* Status stage transaction host mode */
-#define nSTATUSPKT_H 0x0
#define NAK_TIMEOUT_H 0x80 /* EP0 halted after a NAK host mode */
-#define nNAK_TIMEOUT_H 0x0
/* Bit masks for USB_COUNT0 */
@@ -3213,37 +2535,21 @@
/* Bit masks for USB_TXCSR */
#define TXPKTRDY_T 0x1 /* data packet in FIFO indicator */
-#define nTXPKTRDY_T 0x0
#define FIFO_NOT_EMPTY_T 0x2 /* FIFO not empty */
-#define nFIFO_NOT_EMPTY_T 0x0
#define UNDERRUN_T 0x4 /* TxPktRdy not set for an IN token */
-#define nUNDERRUN_T 0x0
#define FLUSHFIFO_T 0x8 /* flush endpoint FIFO */
-#define nFLUSHFIFO_T 0x0
#define STALL_SEND_T 0x10 /* issue a Stall handshake */
-#define nSTALL_SEND_T 0x0
#define STALL_SENT_T 0x20 /* Stall handshake transmitted */
-#define nSTALL_SENT_T 0x0
#define CLEAR_DATATOGGLE_T 0x40 /* clear endpoint data toggle */
-#define nCLEAR_DATATOGGLE_T 0x0
#define INCOMPTX_T 0x80 /* indicates that a large packet is split */
-#define nINCOMPTX_T 0x0
#define DMAREQMODE_T 0x400 /* DMA mode (0 or 1) selection */
-#define nDMAREQMODE_T 0x0
#define FORCE_DATATOGGLE_T 0x800 /* Force data toggle */
-#define nFORCE_DATATOGGLE_T 0x0
#define DMAREQ_ENA_T 0x1000 /* Enable DMA request for Tx EP */
-#define nDMAREQ_ENA_T 0x0
#define ISO_T 0x4000 /* enable Isochronous transfers */
-#define nISO_T 0x0
#define AUTOSET_T 0x8000 /* allows TxPktRdy to be set automatically */
-#define nAUTOSET_T 0x0
#define ERROR_TH 0x4 /* error condition host mode */
-#define nERROR_TH 0x0
#define STALL_RECEIVED_TH 0x20 /* Stall handshake received host mode */
-#define nSTALL_RECEIVED_TH 0x0
#define NAK_TIMEOUT_TH 0x80 /* NAK timeout host mode */
-#define nNAK_TIMEOUT_TH 0x0
/* Bit masks for USB_TXCOUNT */
@@ -3252,45 +2558,25 @@
/* Bit masks for USB_RXCSR */
#define RXPKTRDY_R 0x1 /* data packet in FIFO indicator */
-#define nRXPKTRDY_R 0x0
#define FIFO_FULL_R 0x2 /* FIFO not empty */
-#define nFIFO_FULL_R 0x0
#define OVERRUN_R 0x4 /* TxPktRdy not set for an IN token */
-#define nOVERRUN_R 0x0
#define DATAERROR_R 0x8 /* Out packet cannot be loaded into Rx FIFO */
-#define nDATAERROR_R 0x0
#define FLUSHFIFO_R 0x10 /* flush endpoint FIFO */
-#define nFLUSHFIFO_R 0x0
#define STALL_SEND_R 0x20 /* issue a Stall handshake */
-#define nSTALL_SEND_R 0x0
#define STALL_SENT_R 0x40 /* Stall handshake transmitted */
-#define nSTALL_SENT_R 0x0
#define CLEAR_DATATOGGLE_R 0x80 /* clear endpoint data toggle */
-#define nCLEAR_DATATOGGLE_R 0x0
#define INCOMPRX_R 0x100 /* indicates that a large packet is split */
-#define nINCOMPRX_R 0x0
#define DMAREQMODE_R 0x800 /* DMA mode (0 or 1) selection */
-#define nDMAREQMODE_R 0x0
#define DISNYET_R 0x1000 /* disable Nyet handshakes */
-#define nDISNYET_R 0x0
#define DMAREQ_ENA_R 0x2000 /* Enable DMA request for Tx EP */
-#define nDMAREQ_ENA_R 0x0
#define ISO_R 0x4000 /* enable Isochronous transfers */
-#define nISO_R 0x0
#define AUTOCLEAR_R 0x8000 /* allows TxPktRdy to be set automatically */
-#define nAUTOCLEAR_R 0x0
#define ERROR_RH 0x4 /* TxPktRdy not set for an IN token host mode */
-#define nERROR_RH 0x0
#define REQPKT_RH 0x20 /* request an IN transaction host mode */
-#define nREQPKT_RH 0x0
#define STALL_RECEIVED_RH 0x40 /* Stall handshake received host mode */
-#define nSTALL_RECEIVED_RH 0x0
#define INCOMPRX_RH 0x100 /* indicates that a large packet is split host mode */
-#define nINCOMPRX_RH 0x0
#define DMAREQMODE_RH 0x800 /* DMA mode (0 or 1) selection host mode */
-#define nDMAREQMODE_RH 0x0
#define AUTOREQ_RH 0x4000 /* sets ReqPkt automatically host mode */
-#define nAUTOREQ_RH 0x0
/* Bit masks for USB_RXCOUNT */
@@ -3317,35 +2603,22 @@
/* Bit masks for USB_DMA_INTERRUPT */
#define DMA0_INT 0x1 /* DMA0 pending interrupt */
-#define nDMA0_INT 0x0
#define DMA1_INT 0x2 /* DMA1 pending interrupt */
-#define nDMA1_INT 0x0
#define DMA2_INT 0x4 /* DMA2 pending interrupt */
-#define nDMA2_INT 0x0
#define DMA3_INT 0x8 /* DMA3 pending interrupt */
-#define nDMA3_INT 0x0
#define DMA4_INT 0x10 /* DMA4 pending interrupt */
-#define nDMA4_INT 0x0
#define DMA5_INT 0x20 /* DMA5 pending interrupt */
-#define nDMA5_INT 0x0
#define DMA6_INT 0x40 /* DMA6 pending interrupt */
-#define nDMA6_INT 0x0
#define DMA7_INT 0x80 /* DMA7 pending interrupt */
-#define nDMA7_INT 0x0
/* Bit masks for USB_DMAxCONTROL */
#define DMA_ENA 0x1 /* DMA enable */
-#define nDMA_ENA 0x0
#define DIRECTION 0x2 /* direction of DMA transfer */
-#define nDIRECTION 0x0
#define MODE 0x4 /* DMA Bus error */
-#define nMODE 0x0
#define INT_ENA 0x8 /* Interrupt enable */
-#define nINT_ENA 0x0
#define EPNUM 0xf0 /* EP number */
#define BUSERROR 0x100 /* DMA Bus error */
-#define nBUSERROR 0x0
/* Bit masks for USB_DMAxADDRHIGH */
@@ -3366,26 +2639,16 @@
/* Bit masks for HMDMAx_CONTROL */
#define HMDMAEN 0x1 /* Handshake MDMA Enable */
-#define nHMDMAEN 0x0
#define REP 0x2 /* Handshake MDMA Request Polarity */
-#define nREP 0x0
#define UTE 0x8 /* Urgency Threshold Enable */
-#define nUTE 0x0
#define OIE 0x10 /* Overflow Interrupt Enable */
-#define nOIE 0x0
#define BDIE 0x20 /* Block Done Interrupt Enable */
-#define nBDIE 0x0
#define MBDI 0x40 /* Mask Block Done Interrupt */
-#define nMBDI 0x0
#define DRQ 0x300 /* Handshake MDMA Request Type */
#define RBC 0x1000 /* Force Reload of BCOUNT */
-#define nRBC 0x0
#define PS 0x2000 /* Pin Status */
-#define nPS 0x0
#define OI 0x4000 /* Overflow Interrupt Generated */
-#define nOI 0x0
#define BDI 0x8000 /* Block Done Interrupt Generated */
-#define nBDI 0x0
/* ******************************************* */
/* MULTI BIT MACRO ENUMERATIONS */
diff --git a/include/asm-blackfin/mach-bf548/defBF54x_base.h b/include/asm-blackfin/mach-bf548/defBF54x_base.h
index a1b200fe6a1..895ddd40a83 100644
--- a/include/asm-blackfin/mach-bf548/defBF54x_base.h
+++ b/include/asm-blackfin/mach-bf548/defBF54x_base.h
@@ -46,7 +46,7 @@
/* Debug/MP/Emulation Registers (0xFFC00014 - 0xFFC00014) */
-#define CHIPID 0xffc00014
+#define CHIPID 0xffc00014
/* System Reset and Interrupt Controller (0xFFC00100 - 0xFFC00104) */
@@ -1512,231 +1512,144 @@
/* and MULTI BIT READ MACROS */
/* ********************************************************** */
+/* SIC_IMASK Masks */
+#define SIC_UNMASK_ALL 0x00000000 /* Unmask all peripheral interrupts */
+#define SIC_MASK_ALL 0xFFFFFFFF /* Mask all peripheral interrupts */
+#define SIC_MASK(x) (1 << (x)) /* Mask Peripheral #x interrupt */
+#define SIC_UNMASK(x) (0xFFFFFFFF ^ (1 << (x))) /* Unmask Peripheral #x interrupt */
+
+/* SIC_IWR Masks */
+#define IWR_DISABLE_ALL 0x00000000 /* Wakeup Disable all peripherals */
+#define IWR_ENABLE_ALL 0xFFFFFFFF /* Wakeup Enable all peripherals */
+#define IWR_ENABLE(x) (1 << (x)) /* Wakeup Enable Peripheral #x */
+#define IWR_DISABLE(x) (0xFFFFFFFF ^ (1 << (x))) /* Wakeup Disable Peripheral #x */
+
/* Bit masks for SIC_IAR0 */
-#define IRQ_PLL_WAKEUP 0x1 /* PLL Wakeup */
-#define nIRQ_PLL_WAKEUP 0x0
+#define PLL_WAKEUP 0x1 /* PLL Wakeup */
/* Bit masks for SIC_IWR0, SIC_IMASK0, SIC_ISR0 */
-#define IRQ_DMA0_ERR 0x2 /* DMA Controller 0 Error */
-#define nIRQ_DMA0_ERR 0x0
-#define IRQ_EPPI0_ERR 0x4 /* EPPI0 Error */
-#define nIRQ_EPPI0_ERR 0x0
-#define IRQ_SPORT0_ERR 0x8 /* SPORT0 Error */
-#define nIRQ_SPORT0_ERR 0x0
-#define IRQ_SPORT1_ERR 0x10 /* SPORT1 Error */
-#define nIRQ_SPORT1_ERR 0x0
-#define IRQ_SPI0_ERR 0x20 /* SPI0 Error */
-#define nIRQ_SPI0_ERR 0x0
-#define IRQ_UART0_ERR 0x40 /* UART0 Error */
-#define nIRQ_UART0_ERR 0x0
-#define IRQ_RTC 0x80 /* Real-Time Clock */
-#define nIRQ_RTC 0x0
-#define IRQ_DMA12 0x100 /* DMA Channel 12 */
-#define nIRQ_DMA12 0x0
-#define IRQ_DMA0 0x200 /* DMA Channel 0 */
-#define nIRQ_DMA0 0x0
-#define IRQ_DMA1 0x400 /* DMA Channel 1 */
-#define nIRQ_DMA1 0x0
-#define IRQ_DMA2 0x800 /* DMA Channel 2 */
-#define nIRQ_DMA2 0x0
-#define IRQ_DMA3 0x1000 /* DMA Channel 3 */
-#define nIRQ_DMA3 0x0
-#define IRQ_DMA4 0x2000 /* DMA Channel 4 */
-#define nIRQ_DMA4 0x0
-#define IRQ_DMA6 0x4000 /* DMA Channel 6 */
-#define nIRQ_DMA6 0x0
-#define IRQ_DMA7 0x8000 /* DMA Channel 7 */
-#define nIRQ_DMA7 0x0
-#define IRQ_PINT0 0x80000 /* Pin Interrupt 0 */
-#define nIRQ_PINT0 0x0
-#define IRQ_PINT1 0x100000 /* Pin Interrupt 1 */
-#define nIRQ_PINT1 0x0
-#define IRQ_MDMA0 0x200000 /* Memory DMA Stream 0 */
-#define nIRQ_MDMA0 0x0
-#define IRQ_MDMA1 0x400000 /* Memory DMA Stream 1 */
-#define nIRQ_MDMA1 0x0
-#define IRQ_WDOG 0x800000 /* Watchdog Timer */
-#define nIRQ_WDOG 0x0
-#define IRQ_DMA1_ERR 0x1000000 /* DMA Controller 1 Error */
-#define nIRQ_DMA1_ERR 0x0
-#define IRQ_SPORT2_ERR 0x2000000 /* SPORT2 Error */
-#define nIRQ_SPORT2_ERR 0x0
-#define IRQ_SPORT3_ERR 0x4000000 /* SPORT3 Error */
-#define nIRQ_SPORT3_ERR 0x0
-#define IRQ_MXVR_SD 0x8000000 /* MXVR Synchronous Data */
-#define nIRQ_MXVR_SD 0x0
-#define IRQ_SPI1_ERR 0x10000000 /* SPI1 Error */
-#define nIRQ_SPI1_ERR 0x0
-#define IRQ_SPI2_ERR 0x20000000 /* SPI2 Error */
-#define nIRQ_SPI2_ERR 0x0
-#define IRQ_UART1_ERR 0x40000000 /* UART1 Error */
-#define nIRQ_UART1_ERR 0x0
-#define IRQ_UART2_ERR 0x80000000 /* UART2 Error */
-#define nIRQ_UART2_ERR 0x0
+#define DMA0_ERR 0x2 /* DMA Controller 0 Error */
+#define EPPI0_ERR 0x4 /* EPPI0 Error */
+#define SPORT0_ERR 0x8 /* SPORT0 Error */
+#define SPORT1_ERR 0x10 /* SPORT1 Error */
+#define SPI0_ERR 0x20 /* SPI0 Error */
+#define UART0_ERR 0x40 /* UART0 Error */
+#define RTC 0x80 /* Real-Time Clock */
+#define DMA12 0x100 /* DMA Channel 12 */
+#define DMA0 0x200 /* DMA Channel 0 */
+#define DMA1 0x400 /* DMA Channel 1 */
+#define DMA2 0x800 /* DMA Channel 2 */
+#define DMA3 0x1000 /* DMA Channel 3 */
+#define DMA4 0x2000 /* DMA Channel 4 */
+#define DMA6 0x4000 /* DMA Channel 6 */
+#define DMA7 0x8000 /* DMA Channel 7 */
+#define PINT0 0x80000 /* Pin Interrupt 0 */
+#define PINT1 0x100000 /* Pin Interrupt 1 */
+#define MDMA0 0x200000 /* Memory DMA Stream 0 */
+#define MDMA1 0x400000 /* Memory DMA Stream 1 */
+#define WDOG 0x800000 /* Watchdog Timer */
+#define DMA1_ERR 0x1000000 /* DMA Controller 1 Error */
+#define SPORT2_ERR 0x2000000 /* SPORT2 Error */
+#define SPORT3_ERR 0x4000000 /* SPORT3 Error */
+#define MXVR_SD 0x8000000 /* MXVR Synchronous Data */
+#define SPI1_ERR 0x10000000 /* SPI1 Error */
+#define SPI2_ERR 0x20000000 /* SPI2 Error */
+#define UART1_ERR 0x40000000 /* UART1 Error */
+#define UART2_ERR 0x80000000 /* UART2 Error */
/* Bit masks for SIC_IWR1, SIC_IMASK1, SIC_ISR1 */
-#define IRQ_CAN0_ERR 0x1 /* CAN0 Error */
-#define nIRQ_CAN0_ERR 0x0
-#define IRQ_DMA18 0x2 /* DMA Channel 18 */
-#define nIRQ_DMA18 0x0
-#define IRQ_DMA19 0x4 /* DMA Channel 19 */
-#define nIRQ_DMA19 0x0
-#define IRQ_DMA20 0x8 /* DMA Channel 20 */
-#define nIRQ_DMA20 0x0
-#define IRQ_DMA21 0x10 /* DMA Channel 21 */
-#define nIRQ_DMA21 0x0
-#define IRQ_DMA13 0x20 /* DMA Channel 13 */
-#define nIRQ_DMA13 0x0
-#define IRQ_DMA14 0x40 /* DMA Channel 14 */
-#define nIRQ_DMA14 0x0
-#define IRQ_DMA5 0x80 /* DMA Channel 5 */
-#define nIRQ_DMA5 0x0
-#define IRQ_DMA23 0x100 /* DMA Channel 23 */
-#define nIRQ_DMA23 0x0
-#define IRQ_DMA8 0x200 /* DMA Channel 8 */
-#define nIRQ_DMA8 0x0
-#define IRQ_DMA9 0x400 /* DMA Channel 9 */
-#define nIRQ_DMA9 0x0
-#define IRQ_DMA10 0x800 /* DMA Channel 10 */
-#define nIRQ_DMA10 0x0
-#define IRQ_DMA11 0x1000 /* DMA Channel 11 */
-#define nIRQ_DMA11 0x0
-#define IRQ_TWI0 0x2000 /* TWI0 */
-#define nIRQ_TWI0 0x0
-#define IRQ_TWI1 0x4000 /* TWI1 */
-#define nIRQ_TWI1 0x0
-#define IRQ_CAN0_RX 0x8000 /* CAN0 Receive */
-#define nIRQ_CAN0_RX 0x0
-#define IRQ_CAN0_TX 0x10000 /* CAN0 Transmit */
-#define nIRQ_CAN0_TX 0x0
-#define IRQ_MDMA2 0x20000 /* Memory DMA Stream 0 */
-#define nIRQ_MDMA2 0x0
-#define IRQ_MDMA3 0x40000 /* Memory DMA Stream 1 */
-#define nIRQ_MDMA3 0x0
-#define IRQ_MXVR_STAT 0x80000 /* MXVR Status */
-#define nIRQ_MXVR_STAT 0x0
-#define IRQ_MXVR_CM 0x100000 /* MXVR Control Message */
-#define nIRQ_MXVR_CM 0x0
-#define IRQ_MXVR_AP 0x200000 /* MXVR Asynchronous Packet */
-#define nIRQ_MXVR_AP 0x0
-#define IRQ_EPPI1_ERR 0x400000 /* EPPI1 Error */
-#define nIRQ_EPPI1_ERR 0x0
-#define IRQ_EPPI2_ERR 0x800000 /* EPPI2 Error */
-#define nIRQ_EPPI2_ERR 0x0
-#define IRQ_UART3_ERR 0x1000000 /* UART3 Error */
-#define nIRQ_UART3_ERR 0x0
-#define IRQ_HOST_ERR 0x2000000 /* Host DMA Port Error */
-#define nIRQ_HOST_ERR 0x0
-#define IRQ_USB_ERR 0x4000000 /* USB Error */
-#define nIRQ_USB_ERR 0x0
-#define IRQ_PIXC_ERR 0x8000000 /* Pixel Compositor Error */
-#define nIRQ_PIXC_ERR 0x0
-#define IRQ_NFC_ERR 0x10000000 /* Nand Flash Controller Error */
-#define nIRQ_NFC_ERR 0x0
-#define IRQ_ATAPI_ERR 0x20000000 /* ATAPI Error */
-#define nIRQ_ATAPI_ERR 0x0
-#define IRQ_CAN1_ERR 0x40000000 /* CAN1 Error */
-#define nIRQ_CAN1_ERR 0x0
-#define IRQ_DMAR0_ERR 0x80000000 /* DMAR0 Overflow Error */
-#define nIRQ_DMAR0_ERR 0x0
-#define IRQ_DMAR1_ERR 0x80000000 /* DMAR1 Overflow Error */
-#define nIRQ_DMAR1_ERR 0x0
-#define IRQ_DMAR0 0x80000000 /* DMAR0 Block */
-#define nIRQ_DMAR0 0x0
-#define IRQ_DMAR1 0x80000000 /* DMAR1 Block */
-#define nIRQ_DMAR1 0x0
+#define CAN0_ERR 0x1 /* CAN0 Error */
+#define DMA18 0x2 /* DMA Channel 18 */
+#define DMA19 0x4 /* DMA Channel 19 */
+#define DMA20 0x8 /* DMA Channel 20 */
+#define DMA21 0x10 /* DMA Channel 21 */
+#define DMA13 0x20 /* DMA Channel 13 */
+#define DMA14 0x40 /* DMA Channel 14 */
+#define DMA5 0x80 /* DMA Channel 5 */
+#define DMA23 0x100 /* DMA Channel 23 */
+#define DMA8 0x200 /* DMA Channel 8 */
+#define DMA9 0x400 /* DMA Channel 9 */
+#define DMA10 0x800 /* DMA Channel 10 */
+#define DMA11 0x1000 /* DMA Channel 11 */
+#define TWI0 0x2000 /* TWI0 */
+#define TWI1 0x4000 /* TWI1 */
+#define CAN0_RX 0x8000 /* CAN0 Receive */
+#define CAN0_TX 0x10000 /* CAN0 Transmit */
+#define MDMA2 0x20000 /* Memory DMA Stream 0 */
+#define MDMA3 0x40000 /* Memory DMA Stream 1 */
+#define MXVR_STAT 0x80000 /* MXVR Status */
+#define MXVR_CM 0x100000 /* MXVR Control Message */
+#define MXVR_AP 0x200000 /* MXVR Asynchronous Packet */
+#define EPPI1_ERR 0x400000 /* EPPI1 Error */
+#define EPPI2_ERR 0x800000 /* EPPI2 Error */
+#define UART3_ERR 0x1000000 /* UART3 Error */
+#define HOST_ERR 0x2000000 /* Host DMA Port Error */
+#define USB_ERR 0x4000000 /* USB Error */
+#define PIXC_ERR 0x8000000 /* Pixel Compositor Error */
+#define NFC_ERR 0x10000000 /* Nand Flash Controller Error */
+#define ATAPI_ERR 0x20000000 /* ATAPI Error */
+#define CAN1_ERR 0x40000000 /* CAN1 Error */
+#define DMAR0_ERR 0x80000000 /* DMAR0 Overflow Error */
+#define DMAR1_ERR 0x80000000 /* DMAR1 Overflow Error */
+#define DMAR0 0x80000000 /* DMAR0 Block */
+#define DMAR1 0x80000000 /* DMAR1 Block */
/* Bit masks for SIC_IWR2, SIC_IMASK2, SIC_ISR2 */
-#define IRQ_DMA15 0x1 /* DMA Channel 15 */
-#define nIRQ_DMA15 0x0
-#define IRQ_DMA16 0x2 /* DMA Channel 16 */
-#define nIRQ_DMA16 0x0
-#define IRQ_DMA17 0x4 /* DMA Channel 17 */
-#define nIRQ_DMA17 0x0
-#define IRQ_DMA22 0x8 /* DMA Channel 22 */
-#define nIRQ_DMA22 0x0
-#define IRQ_CNT 0x10 /* Counter */
-#define nIRQ_CNT 0x0
-#define IRQ_KEY 0x20 /* Keypad */
-#define nIRQ_KEY 0x0
-#define IRQ_CAN1_RX 0x40 /* CAN1 Receive */
-#define nIRQ_CAN1_RX 0x0
-#define IRQ_CAN1_TX 0x80 /* CAN1 Transmit */
-#define nIRQ_CAN1_TX 0x0
-#define IRQ_SDH_MASK0 0x100 /* SDH Mask 0 */
-#define nIRQ_SDH_MASK0 0x0
-#define IRQ_SDH_MASK1 0x200 /* SDH Mask 1 */
-#define nIRQ_SDH_MASK1 0x0
-#define IRQ_USB_EINT 0x400 /* USB Exception */
-#define nIRQ_USB_EINT 0x0
-#define IRQ_USB_INT0 0x800 /* USB Interrupt 0 */
-#define nIRQ_USB_INT0 0x0
-#define IRQ_USB_INT1 0x1000 /* USB Interrupt 1 */
-#define nIRQ_USB_INT1 0x0
-#define IRQ_USB_INT2 0x2000 /* USB Interrupt 2 */
-#define nIRQ_USB_INT2 0x0
-#define IRQ_USB_DMAINT 0x4000 /* USB DMA */
-#define nIRQ_USB_DMAINT 0x0
-#define IRQ_OTPSEC 0x8000 /* OTP Access Complete */
-#define nIRQ_OTPSEC 0x0
-#define IRQ_TIMER0 0x400000 /* Timer 0 */
-#define nIRQ_TIMER0 0x0
-#define IRQ_TIMER1 0x800000 /* Timer 1 */
-#define nIRQ_TIMER1 0x0
-#define IRQ_TIMER2 0x1000000 /* Timer 2 */
-#define nIRQ_TIMER2 0x0
-#define IRQ_TIMER3 0x2000000 /* Timer 3 */
-#define nIRQ_TIMER3 0x0
-#define IRQ_TIMER4 0x4000000 /* Timer 4 */
-#define nIRQ_TIMER4 0x0
-#define IRQ_TIMER5 0x8000000 /* Timer 5 */
-#define nIRQ_TIMER5 0x0
-#define IRQ_TIMER6 0x10000000 /* Timer 6 */
-#define nIRQ_TIMER6 0x0
-#define IRQ_TIMER7 0x20000000 /* Timer 7 */
-#define nIRQ_TIMER7 0x0
-#define IRQ_PINT2 0x40000000 /* Pin Interrupt 2 */
-#define nIRQ_PINT2 0x0
-#define IRQ_PINT3 0x80000000 /* Pin Interrupt 3 */
-#define nIRQ_PINT3 0x0
+#define DMA15 0x1 /* DMA Channel 15 */
+#define DMA16 0x2 /* DMA Channel 16 */
+#define DMA17 0x4 /* DMA Channel 17 */
+#define DMA22 0x8 /* DMA Channel 22 */
+#define CNT 0x10 /* Counter */
+#define KEY 0x20 /* Keypad */
+#define CAN1_RX 0x40 /* CAN1 Receive */
+#define CAN1_TX 0x80 /* CAN1 Transmit */
+#define SDH_INT_MASK0 0x100 /* SDH Mask 0 */
+#define SDH_INT_MASK1 0x200 /* SDH Mask 1 */
+#define USB_EINT 0x400 /* USB Exception */
+#define USB_INT0 0x800 /* USB Interrupt 0 */
+#define USB_INT1 0x1000 /* USB Interrupt 1 */
+#define USB_INT2 0x2000 /* USB Interrupt 2 */
+#define USB_DMAINT 0x4000 /* USB DMA */
+#define OTPSEC 0x8000 /* OTP Access Complete */
+#define TIMER0 0x400000 /* Timer 0 */
+#define TIMER1 0x800000 /* Timer 1 */
+#define TIMER2 0x1000000 /* Timer 2 */
+#define TIMER3 0x2000000 /* Timer 3 */
+#define TIMER4 0x4000000 /* Timer 4 */
+#define TIMER5 0x8000000 /* Timer 5 */
+#define TIMER6 0x10000000 /* Timer 6 */
+#define TIMER7 0x20000000 /* Timer 7 */
+#define PINT2 0x40000000 /* Pin Interrupt 2 */
+#define PINT3 0x80000000 /* Pin Interrupt 3 */
/* Bit masks for DMAx_CONFIG, MDMA_Sx_CONFIG, MDMA_Dx_CONFIG */
#define DMAEN 0x1 /* DMA Channel Enable */
-#define nDMAEN 0x0
#define WNR 0x2 /* DMA Direction */
-#define nWNR 0x0
-#define WDSIZE 0xc /* Transfer Word Size */
+#define WDSIZE_8 0x0 /* Transfer Word Size = 8 */
+#define WDSIZE_16 0x4 /* Transfer Word Size = 16 */
+#define WDSIZE_32 0x8 /* Transfer Word Size = 32 */
#define DMA2D 0x10 /* DMA Mode */
-#define nDMA2D 0x0
#define RESTART 0x20 /* Work Unit Transitions */
-#define nRESTART 0x0
#define DI_SEL 0x40 /* Data Interrupt Timing Select */
-#define nDI_SEL 0x0
#define DI_EN 0x80 /* Data Interrupt Enable */
-#define nDI_EN 0x0
#define NDSIZE 0xf00 /* Flex Descriptor Size */
#define DMAFLOW 0xf000 /* Next Operation */
/* Bit masks for DMAx_IRQ_STATUS, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */
#define DMA_DONE 0x1 /* DMA Completion Interrupt Status */
-#define nDMA_DONE 0x0
#define DMA_ERR 0x2 /* DMA Error Interrupt Status */
-#define nDMA_ERR 0x0
#define DFETCH 0x4 /* DMA Descriptor Fetch */
-#define nDFETCH 0x0
#define DMA_RUN 0x8 /* DMA Channel Running */
-#define nDMA_RUN 0x0
/* Bit masks for DMAx_PERIPHERAL_MAP, MDMA_Sx_IRQ_STATUS, MDMA_Dx_IRQ_STATUS */
#define CTYPE 0x40 /* DMA Channel Type */
-#define nCTYPE 0x0
#define PMAP 0xf000 /* Peripheral Mapped To This Channel */
/* Bit masks for DMACx_TCPER */
@@ -1756,29 +1669,28 @@
/* Bit masks for DMAC1_PERIMUX */
#define PMUXSDH 0x1 /* Peripheral Select for DMA22 channel */
-#define nPMUXSDH 0x0
-/* Bit masks for EBIU_AMGCTL */
+/* ********************* ASYNCHRONOUS MEMORY CONTROLLER MASKS *************************/
+/* EBIU_AMGCTL Masks */
+#define AMCKEN 0x0001 /* Enable CLKOUT */
+#define AMBEN_NONE 0x0000 /* All Banks Disabled */
+#define AMBEN_B0 0x0002 /* Enable Async Memory Bank 0 only */
+#define AMBEN_B0_B1 0x0004 /* Enable Async Memory Banks 0 & 1 only */
+#define AMBEN_B0_B1_B2 0x0006 /* Enable Async Memory Banks 0, 1, and 2 */
+#define AMBEN_ALL 0x0008 /* Enable Async Memory Banks (all) 0, 1, 2, and 3 */
-#define AMCKEN 0x1 /* Async Memory Enable */
-#define nAMCKEN 0x0
-#define AMBEN 0xe /* Async bank enable */
/* Bit masks for EBIU_AMBCTL0 */
#define B0RDYEN 0x1 /* Bank 0 ARDY Enable */
-#define nB0RDYEN 0x0
#define B0RDYPOL 0x2 /* Bank 0 ARDY Polarity */
-#define nB0RDYPOL 0x0
#define B0TT 0xc /* Bank 0 transition time */
#define B0ST 0x30 /* Bank 0 Setup time */
#define B0HT 0xc0 /* Bank 0 Hold time */
#define B0RAT 0xf00 /* Bank 0 Read access time */
#define B0WAT 0xf000 /* Bank 0 write access time */
#define B1RDYEN 0x10000 /* Bank 1 ARDY Enable */
-#define nB1RDYEN 0x0
#define B1RDYPOL 0x20000 /* Bank 1 ARDY Polarity */
-#define nB1RDYPOL 0x0
#define B1TT 0xc0000 /* Bank 1 transition time */
#define B1ST 0x300000 /* Bank 1 Setup time */
#define B1HT 0xc00000 /* Bank 1 Hold time */
@@ -1788,18 +1700,14 @@
/* Bit masks for EBIU_AMBCTL1 */
#define B2RDYEN 0x1 /* Bank 2 ARDY Enable */
-#define nB2RDYEN 0x0
#define B2RDYPOL 0x2 /* Bank 2 ARDY Polarity */
-#define nB2RDYPOL 0x0
#define B2TT 0xc /* Bank 2 transition time */
#define B2ST 0x30 /* Bank 2 Setup time */
#define B2HT 0xc0 /* Bank 2 Hold time */
#define B2RAT 0xf00 /* Bank 2 Read access time */
#define B2WAT 0xf000 /* Bank 2 write access time */
#define B3RDYEN 0x10000 /* Bank 3 ARDY Enable */
-#define nB3RDYEN 0x0
#define B3RDYPOL 0x20000 /* Bank 3 ARDY Polarity */
-#define nB3RDYPOL 0x0
#define B3TT 0xc0000 /* Bank 3 transition time */
#define B3ST 0x300000 /* Bank 3 Setup time */
#define B3HT 0xc00000 /* Bank 3 Hold time */
@@ -1823,19 +1731,15 @@
/* Bit masks for EBIU_FCTL */
#define TESTSETLOCK 0x1 /* Test set lock */
-#define nTESTSETLOCK 0x0
#define BCLK 0x6 /* Burst clock frequency */
#define PGWS 0x38 /* Page wait states */
#define PGSZ 0x40 /* Page size */
-#define nPGSZ 0x0
#define RDDL 0x380 /* Read data delay */
/* Bit masks for EBIU_ARBSTAT */
#define ARBSTAT 0x1 /* Arbitration status */
-#define nARBSTAT 0x0
#define BGSTAT 0x2 /* Bus grant status */
-#define nBGSTAT 0x0
/* Bit masks for EBIU_DDRCTL0 */
@@ -1861,9 +1765,7 @@
#define BURSTLENGTH 0x7 /* Burst length */
#define CASLATENCY 0x70 /* CAS latency */
#define DLLRESET 0x100 /* DLL Reset */
-#define nDLLRESET 0x0
#define REGE 0x1000 /* Register mode enable */
-#define nREGE 0x0
/* Bit masks for EBIU_DDRCTL3 */
@@ -1876,30 +1778,19 @@
#define DEB3_PFLEN 0x30 /* Pre fetch length for DEB3 accesses */
#define DEB_ARB_PRIORITY 0x700 /* Arbitration between DEB busses */
#define DEB1_URGENT 0x1000 /* DEB1 Urgent */
-#define nDEB1_URGENT 0x0
#define DEB2_URGENT 0x2000 /* DEB2 Urgent */
-#define nDEB2_URGENT 0x0
#define DEB3_URGENT 0x4000 /* DEB3 Urgent */
-#define nDEB3_URGENT 0x0
/* Bit masks for EBIU_ERRMST */
#define DEB1_ERROR 0x1 /* DEB1 Error */
-#define nDEB1_ERROR 0x0
#define DEB2_ERROR 0x2 /* DEB2 Error */
-#define nDEB2_ERROR 0x0
#define DEB3_ERROR 0x4 /* DEB3 Error */
-#define nDEB3_ERROR 0x0
#define CORE_ERROR 0x8 /* Core error */
-#define nCORE_ERROR 0x0
#define DEB_MERROR 0x10 /* DEB1 Error (2nd) */
-#define nDEB_MERROR 0x0
#define DEB2_MERROR 0x20 /* DEB2 Error (2nd) */
-#define nDEB2_MERROR 0x0
#define DEB3_MERROR 0x40 /* DEB3 Error (2nd) */
-#define nDEB3_MERROR 0x0
#define CORE_MERROR 0x80 /* Core Error (2nd) */
-#define nCORE_MERROR 0x0
/* Bit masks for EBIU_ERRADD */
@@ -1908,15 +1799,10 @@
/* Bit masks for EBIU_RSTCTL */
#define DDRSRESET 0x1 /* DDR soft reset */
-#define nDDRSRESET 0x0
#define PFTCHSRESET 0x4 /* DDR prefetch reset */
-#define nPFTCHSRESET 0x0
#define SRREQ 0x8 /* Self-refresh request */
-#define nSRREQ 0x0
#define SRACK 0x10 /* Self-refresh acknowledge */
-#define nSRACK 0x0
#define MDDRENABLE 0x20 /* Mobile DDR enable */
-#define nMDDRENABLE 0x0
/* Bit masks for EBIU_DDRBRC0 */
@@ -2013,136 +1899,74 @@
/* Bit masks for EBIU_DDRMCEN */
#define B0WCENABLE 0x1 /* Bank 0 write count enable */
-#define nB0WCENABLE 0x0
#define B1WCENABLE 0x2 /* Bank 1 write count enable */
-#define nB1WCENABLE 0x0
#define B2WCENABLE 0x4 /* Bank 2 write count enable */
-#define nB2WCENABLE 0x0
#define B3WCENABLE 0x8 /* Bank 3 write count enable */
-#define nB3WCENABLE 0x0
#define B4WCENABLE 0x10 /* Bank 4 write count enable */
-#define nB4WCENABLE 0x0
#define B5WCENABLE 0x20 /* Bank 5 write count enable */
-#define nB5WCENABLE 0x0
#define B6WCENABLE 0x40 /* Bank 6 write count enable */
-#define nB6WCENABLE 0x0
#define B7WCENABLE 0x80 /* Bank 7 write count enable */
-#define nB7WCENABLE 0x0
#define B0RCENABLE 0x100 /* Bank 0 read count enable */
-#define nB0RCENABLE 0x0
#define B1RCENABLE 0x200 /* Bank 1 read count enable */
-#define nB1RCENABLE 0x0
#define B2RCENABLE 0x400 /* Bank 2 read count enable */
-#define nB2RCENABLE 0x0
#define B3RCENABLE 0x800 /* Bank 3 read count enable */
-#define nB3RCENABLE 0x0
#define B4RCENABLE 0x1000 /* Bank 4 read count enable */
-#define nB4RCENABLE 0x0
#define B5RCENABLE 0x2000 /* Bank 5 read count enable */
-#define nB5RCENABLE 0x0
#define B6RCENABLE 0x4000 /* Bank 6 read count enable */
-#define nB6RCENABLE 0x0
#define B7RCENABLE 0x8000 /* Bank 7 read count enable */
-#define nB7RCENABLE 0x0
#define ROWACTCENABLE 0x10000 /* DDR Row activate count enable */
-#define nROWACTCENABLE 0x0
#define RWTCENABLE 0x20000 /* DDR R/W Turn around count enable */
-#define nRWTCENABLE 0x0
#define ARCENABLE 0x40000 /* DDR Auto-refresh count enable */
-#define nARCENABLE 0x0
#define GC0ENABLE 0x100000 /* DDR Grant count 0 enable */
-#define nGC0ENABLE 0x0
#define GC1ENABLE 0x200000 /* DDR Grant count 1 enable */
-#define nGC1ENABLE 0x0
#define GC2ENABLE 0x400000 /* DDR Grant count 2 enable */
-#define nGC2ENABLE 0x0
#define GC3ENABLE 0x800000 /* DDR Grant count 3 enable */
-#define nGC3ENABLE 0x0
#define GCCONTROL 0x3000000 /* DDR Grant Count Control */
/* Bit masks for EBIU_DDRMCCL */
#define CB0WCOUNT 0x1 /* Clear write count 0 */
-#define nCB0WCOUNT 0x0
#define CB1WCOUNT 0x2 /* Clear write count 1 */
-#define nCB1WCOUNT 0x0
#define CB2WCOUNT 0x4 /* Clear write count 2 */
-#define nCB2WCOUNT 0x0
#define CB3WCOUNT 0x8 /* Clear write count 3 */
-#define nCB3WCOUNT 0x0
#define CB4WCOUNT 0x10 /* Clear write count 4 */
-#define nCB4WCOUNT 0x0
#define CB5WCOUNT 0x20 /* Clear write count 5 */
-#define nCB5WCOUNT 0x0
#define CB6WCOUNT 0x40 /* Clear write count 6 */
-#define nCB6WCOUNT 0x0
#define CB7WCOUNT 0x80 /* Clear write count 7 */
-#define nCB7WCOUNT 0x0
#define CBRCOUNT 0x100 /* Clear read count 0 */
-#define nCBRCOUNT 0x0
#define CB1RCOUNT 0x200 /* Clear read count 1 */
-#define nCB1RCOUNT 0x0
#define CB2RCOUNT 0x400 /* Clear read count 2 */
-#define nCB2RCOUNT 0x0
#define CB3RCOUNT 0x800 /* Clear read count 3 */
-#define nCB3RCOUNT 0x0
#define CB4RCOUNT 0x1000 /* Clear read count 4 */
-#define nCB4RCOUNT 0x0
#define CB5RCOUNT 0x2000 /* Clear read count 5 */
-#define nCB5RCOUNT 0x0
#define CB6RCOUNT 0x4000 /* Clear read count 6 */
-#define nCB6RCOUNT 0x0
#define CB7RCOUNT 0x8000 /* Clear read count 7 */
-#define nCB7RCOUNT 0x0
#define CRACOUNT 0x10000 /* Clear row activation count */
-#define nCRACOUNT 0x0
#define CRWTACOUNT 0x20000 /* Clear R/W turn-around count */
-#define nCRWTACOUNT 0x0
#define CARCOUNT 0x40000 /* Clear auto-refresh count */
-#define nCARCOUNT 0x0
#define CG0COUNT 0x100000 /* Clear grant count 0 */
-#define nCG0COUNT 0x0
#define CG1COUNT 0x200000 /* Clear grant count 1 */
-#define nCG1COUNT 0x0
#define CG2COUNT 0x400000 /* Clear grant count 2 */
-#define nCG2COUNT 0x0
#define CG3COUNT 0x800000 /* Clear grant count 3 */
-#define nCG3COUNT 0x0
/* Bit masks for (PORTx is PORTA - PORTJ) includes PORTx_FER, PORTx_SET, PORTx_CLEAR, PORTx_DIR_SET, PORTx_DIR_CLEAR, PORTx_INEN */
#define Px0 0x1 /* GPIO 0 */
-#define nPx0 0x0
#define Px1 0x2 /* GPIO 1 */
-#define nPx1 0x0
#define Px2 0x4 /* GPIO 2 */
-#define nPx2 0x0
#define Px3 0x8 /* GPIO 3 */
-#define nPx3 0x0
#define Px4 0x10 /* GPIO 4 */
-#define nPx4 0x0
#define Px5 0x20 /* GPIO 5 */
-#define nPx5 0x0
#define Px6 0x40 /* GPIO 6 */
-#define nPx6 0x0
#define Px7 0x80 /* GPIO 7 */
-#define nPx7 0x0
#define Px8 0x100 /* GPIO 8 */
-#define nPx8 0x0
#define Px9 0x200 /* GPIO 9 */
-#define nPx9 0x0
#define Px10 0x400 /* GPIO 10 */
-#define nPx10 0x0
#define Px11 0x800 /* GPIO 11 */
-#define nPx11 0x0
#define Px12 0x1000 /* GPIO 12 */
-#define nPx12 0x0
#define Px13 0x2000 /* GPIO 13 */
-#define nPx13 0x0
#define Px14 0x4000 /* GPIO 14 */
-#define nPx14 0x0
#define Px15 0x8000 /* GPIO 15 */
-#define nPx15 0x0
/* Bit masks for PORTA_MUX - PORTJ_MUX */
@@ -2167,223 +1991,129 @@
/* Bit masks for PINTx_MASK_SET/CLEAR, PINTx_REQUEST, PINTx_LATCH, PINTx_EDGE_SET/CLEAR, PINTx_INVERT_SET/CLEAR, PINTx_PINTSTATE */
#define IB0 0x1 /* Interrupt Bit 0 */
-#define nIB0 0x0
#define IB1 0x2 /* Interrupt Bit 1 */
-#define nIB1 0x0
#define IB2 0x4 /* Interrupt Bit 2 */
-#define nIB2 0x0
#define IB3 0x8 /* Interrupt Bit 3 */
-#define nIB3 0x0
#define IB4 0x10 /* Interrupt Bit 4 */
-#define nIB4 0x0
#define IB5 0x20 /* Interrupt Bit 5 */
-#define nIB5 0x0
#define IB6 0x40 /* Interrupt Bit 6 */
-#define nIB6 0x0
#define IB7 0x80 /* Interrupt Bit 7 */
-#define nIB7 0x0
#define IB8 0x100 /* Interrupt Bit 8 */
-#define nIB8 0x0
#define IB9 0x200 /* Interrupt Bit 9 */
-#define nIB9 0x0
#define IB10 0x400 /* Interrupt Bit 10 */
-#define nIB10 0x0
#define IB11 0x800 /* Interrupt Bit 11 */
-#define nIB11 0x0
#define IB12 0x1000 /* Interrupt Bit 12 */
-#define nIB12 0x0
#define IB13 0x2000 /* Interrupt Bit 13 */
-#define nIB13 0x0
#define IB14 0x4000 /* Interrupt Bit 14 */
-#define nIB14 0x0
#define IB15 0x8000 /* Interrupt Bit 15 */
-#define nIB15 0x0
/* Bit masks for TIMERx_CONFIG */
#define TMODE 0x3 /* Timer Mode */
#define PULSE_HI 0x4 /* Pulse Polarity */
-#define nPULSE_HI 0x0
#define PERIOD_CNT 0x8 /* Period Count */
-#define nPERIOD_CNT 0x0
#define IRQ_ENA 0x10 /* Interrupt Request Enable */
-#define nIRQ_ENA 0x0
#define TIN_SEL 0x20 /* Timer Input Select */
-#define nTIN_SEL 0x0
#define OUT_DIS 0x40 /* Output Pad Disable */
-#define nOUT_DIS 0x0
#define CLK_SEL 0x80 /* Timer Clock Select */
-#define nCLK_SEL 0x0
#define TOGGLE_HI 0x100 /* Toggle Mode */
-#define nTOGGLE_HI 0x0
#define EMU_RUN 0x200 /* Emulation Behavior Select */
-#define nEMU_RUN 0x0
#define ERR_TYP 0xc000 /* Error Type */
/* Bit masks for TIMER_ENABLE0 */
#define TIMEN0 0x1 /* Timer 0 Enable */
-#define nTIMEN0 0x0
#define TIMEN1 0x2 /* Timer 1 Enable */
-#define nTIMEN1 0x0
#define TIMEN2 0x4 /* Timer 2 Enable */
-#define nTIMEN2 0x0
#define TIMEN3 0x8 /* Timer 3 Enable */
-#define nTIMEN3 0x0
#define TIMEN4 0x10 /* Timer 4 Enable */
-#define nTIMEN4 0x0
#define TIMEN5 0x20 /* Timer 5 Enable */
-#define nTIMEN5 0x0
#define TIMEN6 0x40 /* Timer 6 Enable */
-#define nTIMEN6 0x0
#define TIMEN7 0x80 /* Timer 7 Enable */
-#define nTIMEN7 0x0
/* Bit masks for TIMER_DISABLE0 */
#define TIMDIS0 0x1 /* Timer 0 Disable */
-#define nTIMDIS0 0x0
#define TIMDIS1 0x2 /* Timer 1 Disable */
-#define nTIMDIS1 0x0
#define TIMDIS2 0x4 /* Timer 2 Disable */
-#define nTIMDIS2 0x0
#define TIMDIS3 0x8 /* Timer 3 Disable */
-#define nTIMDIS3 0x0
#define TIMDIS4 0x10 /* Timer 4 Disable */
-#define nTIMDIS4 0x0
#define TIMDIS5 0x20 /* Timer 5 Disable */
-#define nTIMDIS5 0x0
#define TIMDIS6 0x40 /* Timer 6 Disable */
-#define nTIMDIS6 0x0
#define TIMDIS7 0x80 /* Timer 7 Disable */
-#define nTIMDIS7 0x0
/* Bit masks for TIMER_STATUS0 */
#define TIMIL0 0x1 /* Timer 0 Interrupt */
-#define nTIMIL0 0x0
#define TIMIL1 0x2 /* Timer 1 Interrupt */
-#define nTIMIL1 0x0
#define TIMIL2 0x4 /* Timer 2 Interrupt */
-#define nTIMIL2 0x0
#define TIMIL3 0x8 /* Timer 3 Interrupt */
-#define nTIMIL3 0x0
#define TOVF_ERR0 0x10 /* Timer 0 Counter Overflow */
-#define nTOVF_ERR0 0x0
#define TOVF_ERR1 0x20 /* Timer 1 Counter Overflow */
-#define nTOVF_ERR1 0x0
#define TOVF_ERR2 0x40 /* Timer 2 Counter Overflow */
-#define nTOVF_ERR2 0x0
#define TOVF_ERR3 0x80 /* Timer 3 Counter Overflow */
-#define nTOVF_ERR3 0x0
#define TRUN0 0x1000 /* Timer 0 Slave Enable Status */
-#define nTRUN0 0x0
#define TRUN1 0x2000 /* Timer 1 Slave Enable Status */
-#define nTRUN1 0x0
#define TRUN2 0x4000 /* Timer 2 Slave Enable Status */
-#define nTRUN2 0x0
#define TRUN3 0x8000 /* Timer 3 Slave Enable Status */
-#define nTRUN3 0x0
#define TIMIL4 0x10000 /* Timer 4 Interrupt */
-#define nTIMIL4 0x0
#define TIMIL5 0x20000 /* Timer 5 Interrupt */
-#define nTIMIL5 0x0
#define TIMIL6 0x40000 /* Timer 6 Interrupt */
-#define nTIMIL6 0x0
#define TIMIL7 0x80000 /* Timer 7 Interrupt */
-#define nTIMIL7 0x0
#define TOVF_ERR4 0x100000 /* Timer 4 Counter Overflow */
-#define nTOVF_ERR4 0x0
#define TOVF_ERR5 0x200000 /* Timer 5 Counter Overflow */
-#define nTOVF_ERR5 0x0
#define TOVF_ERR6 0x400000 /* Timer 6 Counter Overflow */
-#define nTOVF_ERR6 0x0
#define TOVF_ERR7 0x800000 /* Timer 7 Counter Overflow */
-#define nTOVF_ERR7 0x0
#define TRUN4 0x10000000 /* Timer 4 Slave Enable Status */
-#define nTRUN4 0x0
#define TRUN5 0x20000000 /* Timer 5 Slave Enable Status */
-#define nTRUN5 0x0
#define TRUN6 0x40000000 /* Timer 6 Slave Enable Status */
-#define nTRUN6 0x0
#define TRUN7 0x80000000 /* Timer 7 Slave Enable Status */
-#define nTRUN7 0x0
/* Bit masks for WDOG_CTL */
#define WDEV 0x6 /* Watchdog Event */
#define WDEN 0xff0 /* Watchdog Enable */
#define WDRO 0x8000 /* Watchdog Rolled Over */
-#define nWDRO 0x0
/* Bit masks for CNT_CONFIG */
#define CNTE 0x1 /* Counter Enable */
-#define nCNTE 0x0
#define DEBE 0x2 /* Debounce Enable */
-#define nDEBE 0x0
#define CDGINV 0x10 /* CDG Pin Polarity Invert */
-#define nCDGINV 0x0
#define CUDINV 0x20 /* CUD Pin Polarity Invert */
-#define nCUDINV 0x0
#define CZMINV 0x40 /* CZM Pin Polarity Invert */
-#define nCZMINV 0x0
#define CNTMODE 0x700 /* Counter Operating Mode */
#define ZMZC 0x800 /* CZM Zeroes Counter Enable */
-#define nZMZC 0x0
#define BNDMODE 0x3000 /* Boundary register Mode */
#define INPDIS 0x8000 /* CUG and CDG Input Disable */
-#define nINPDIS 0x0
/* Bit masks for CNT_IMASK */
#define ICIE 0x1 /* Illegal Gray/Binary Code Interrupt Enable */
-#define nICIE 0x0
#define UCIE 0x2 /* Up count Interrupt Enable */
-#define nUCIE 0x0
#define DCIE 0x4 /* Down count Interrupt Enable */
-#define nDCIE 0x0
#define MINCIE 0x8 /* Min Count Interrupt Enable */
-#define nMINCIE 0x0
#define MAXCIE 0x10 /* Max Count Interrupt Enable */
-#define nMAXCIE 0x0
#define COV31IE 0x20 /* Bit 31 Overflow Interrupt Enable */
-#define nCOV31IE 0x0
#define COV15IE 0x40 /* Bit 15 Overflow Interrupt Enable */
-#define nCOV15IE 0x0
#define CZEROIE 0x80 /* Count to Zero Interrupt Enable */
-#define nCZEROIE 0x0
#define CZMIE 0x100 /* CZM Pin Interrupt Enable */
-#define nCZMIE 0x0
#define CZMEIE 0x200 /* CZM Error Interrupt Enable */
-#define nCZMEIE 0x0
#define CZMZIE 0x400 /* CZM Zeroes Counter Interrupt Enable */
-#define nCZMZIE 0x0
/* Bit masks for CNT_STATUS */
#define ICII 0x1 /* Illegal Gray/Binary Code Interrupt Identifier */
-#define nICII 0x0
#define UCII 0x2 /* Up count Interrupt Identifier */
-#define nUCII 0x0
#define DCII 0x4 /* Down count Interrupt Identifier */
-#define nDCII 0x0
#define MINCII 0x8 /* Min Count Interrupt Identifier */
-#define nMINCII 0x0
#define MAXCII 0x10 /* Max Count Interrupt Identifier */
-#define nMAXCII 0x0
#define COV31II 0x20 /* Bit 31 Overflow Interrupt Identifier */
-#define nCOV31II 0x0
#define COV15II 0x40 /* Bit 15 Overflow Interrupt Identifier */
-#define nCOV15II 0x0
#define CZEROII 0x80 /* Count to Zero Interrupt Identifier */
-#define nCZEROII 0x0
#define CZMII 0x100 /* CZM Pin Interrupt Identifier */
-#define nCZMII 0x0
#define CZMEII 0x200 /* CZM Error Interrupt Identifier */
-#define nCZMEII 0x0
#define CZMZII 0x400 /* CZM Zeroes Counter Interrupt Identifier */
-#define nCZMZII 0x0
/* Bit masks for CNT_COMMAND */
@@ -2391,7 +2121,6 @@
#define W1LMIN 0xf0 /* Load Min Register */
#define W1LMAX 0xf00 /* Load Max Register */
#define W1ZMONCE 0x1000 /* Enable CZM Clear Counter Once */
-#define nW1ZMONCE 0x0
/* Bit masks for CNT_DEBOUNCE */
@@ -2407,42 +2136,25 @@
/* Bit masks for RTC_ICTL */
#define STOPWATCH_INTERRUPT_ENABLE 0x1 /* Stopwatch Interrupt Enable */
-#define nSTOPWATCH_INTERRUPT_ENABLE 0x0
#define ALARM_INTERRUPT_ENABLE 0x2 /* Alarm Interrupt Enable */
-#define nALARM_INTERRUPT_ENABLE 0x0
#define SECONDS_INTERRUPT_ENABLE 0x4 /* Seconds Interrupt Enable */
-#define nSECONDS_INTERRUPT_ENABLE 0x0
#define MINUTES_INTERRUPT_ENABLE 0x8 /* Minutes Interrupt Enable */
-#define nMINUTES_INTERRUPT_ENABLE 0x0
#define HOURS_INTERRUPT_ENABLE 0x10 /* Hours Interrupt Enable */
-#define nHOURS_INTERRUPT_ENABLE 0x0
#define TWENTY_FOUR_HOURS_INTERRUPT_ENABLE 0x20 /* 24 Hours Interrupt Enable */
-#define nTWENTY_FOUR_HOURS_INTERRUPT_ENABLE 0x0
#define DAY_ALARM_INTERRUPT_ENABLE 0x40 /* Day Alarm Interrupt Enable */
-#define nDAY_ALARM_INTERRUPT_ENABLE 0x0
#define WRITE_COMPLETE_INTERRUPT_ENABLE 0x8000 /* Write Complete Interrupt Enable */
-#define nWRITE_COMPLETE_INTERRUPT_ENABLE 0x0
/* Bit masks for RTC_ISTAT */
#define STOPWATCH_EVENT_FLAG 0x1 /* Stopwatch Event Flag */
-#define nSTOPWATCH_EVENT_FLAG 0x0
#define ALARM_EVENT_FLAG 0x2 /* Alarm Event Flag */
-#define nALARM_EVENT_FLAG 0x0
#define SECONDS_EVENT_FLAG 0x4 /* Seconds Event Flag */
-#define nSECONDS_EVENT_FLAG 0x0
#define MINUTES_EVENT_FLAG 0x8 /* Minutes Event Flag */
-#define nMINUTES_EVENT_FLAG 0x0
#define HOURS_EVENT_FLAG 0x10 /* Hours Event Flag */
-#define nHOURS_EVENT_FLAG 0x0
#define TWENTY_FOUR_HOURS_EVENT_FLAG 0x20 /* 24 Hours Event Flag */
-#define nTWENTY_FOUR_HOURS_EVENT_FLAG 0x0
#define DAY_ALARM_EVENT_FLAG 0x40 /* Day Alarm Event Flag */
-#define nDAY_ALARM_EVENT_FLAG 0x0
#define WRITE_PENDING__STATUS 0x4000 /* Write Pending Status */
-#define nWRITE_PENDING__STATUS 0x0
#define WRITE_COMPLETE 0x8000 /* Write Complete */
-#define nWRITE_COMPLETE 0x0
/* Bit masks for RTC_SWCNT */
@@ -2458,21 +2170,15 @@
/* Bit masks for RTC_PREN */
#define PREN 0x1 /* Prescaler Enable */
-#define nPREN 0x0
/* Bit masks for OTP_CONTROL */
#define FUSE_FADDR 0x1ff /* OTP/Fuse Address */
#define FIEN 0x800 /* OTP/Fuse Interrupt Enable */
-#define nFIEN 0x0
#define FTESTDEC 0x1000 /* OTP/Fuse Test Decoder */
-#define nFTESTDEC 0x0
#define FWRTEST 0x2000 /* OTP/Fuse Write Test */
-#define nFWRTEST 0x0
#define FRDEN 0x4000 /* OTP/Fuse Read Enable */
-#define nFRDEN 0x0
#define FWREN 0x8000 /* OTP/Fuse Write Enable */
-#define nFWREN 0x0
/* Bit masks for OTP_BEN */
@@ -2481,15 +2187,10 @@
/* Bit masks for OTP_STATUS */
#define FCOMP 0x1 /* OTP/Fuse Access Complete */
-#define nFCOMP 0x0
#define FERROR 0x2 /* OTP/Fuse Access Error */
-#define nFERROR 0x0
#define MMRGLOAD 0x10 /* Memory Mapped Register Gasket Load */
-#define nMMRGLOAD 0x0
#define MMRGLOCK 0x20 /* Memory Mapped Register Gasket Lock */
-#define nMMRGLOCK 0x0
#define FPGMEN 0x40 /* OTP/Fuse Program Enable */
-#define nFPGMEN 0x0
/* Bit masks for OTP_TIMING */
@@ -2503,42 +2204,29 @@
/* Bit masks for SECURE_SYSSWT */
#define EMUDABL 0x1 /* Emulation Disable. */
-#define nEMUDABL 0x0
#define RSTDABL 0x2 /* Reset Disable */
-#define nRSTDABL 0x0
#define L1IDABL 0x1c /* L1 Instruction Memory Disable. */
#define L1DADABL 0xe0 /* L1 Data Bank A Memory Disable. */
#define L1DBDABL 0x700 /* L1 Data Bank B Memory Disable. */
#define DMA0OVR 0x800 /* DMA0 Memory Access Override */
-#define nDMA0OVR 0x0
#define DMA1OVR 0x1000 /* DMA1 Memory Access Override */
-#define nDMA1OVR 0x0
#define EMUOVR 0x4000 /* Emulation Override */
-#define nEMUOVR 0x0
#define OTPSEN 0x8000 /* OTP Secrets Enable. */
-#define nOTPSEN 0x0
#define L2DABL 0x70000 /* L2 Memory Disable. */
/* Bit masks for SECURE_CONTROL */
#define SECURE0 0x1 /* SECURE 0 */
-#define nSECURE0 0x0
#define SECURE1 0x2 /* SECURE 1 */
-#define nSECURE1 0x0
#define SECURE2 0x4 /* SECURE 2 */
-#define nSECURE2 0x0
#define SECURE3 0x8 /* SECURE 3 */
-#define nSECURE3 0x0
/* Bit masks for SECURE_STATUS */
#define SECMODE 0x3 /* Secured Mode Control State */
#define NMI 0x4 /* Non Maskable Interrupt */
-#define nNMI 0x0
#define AFVALID 0x8 /* Authentication Firmware Valid */
-#define nAFVALID 0x0
#define AFEXIT 0x10 /* Authentication Firmware Exit */
-#define nAFEXIT 0x0
#define SECSTAT 0xe0 /* Secure Status */
/* Bit masks for PLL_DIV */
@@ -2550,42 +2238,25 @@
#define MSEL 0x7e00 /* Multiplier Select */
#define BYPASS 0x100 /* PLL Bypass Enable */
-#define nBYPASS 0x0
#define OUTPUT_DELAY 0x80 /* External Memory Output Delay Enable */
-#define nOUTPUT_DELAY 0x0
#define INPUT_DELAY 0x40 /* External Memory Input Delay Enable */
-#define nINPUT_DELAY 0x0
#define PDWN 0x20 /* Power Down */
-#define nPDWN 0x0
#define STOPCK 0x8 /* Stop Clock */
-#define nSTOPCK 0x0
#define PLL_OFF 0x2 /* Disable PLL */
-#define nPLL_OFF 0x0
#define DF 0x1 /* Divide Frequency */
-#define nDF 0x0
/* Bit masks for PLL_STAT */
#define PLL_LOCKED 0x20 /* PLL Locked Status */
-#define nPLL_LOCKED 0x0
#define ACTIVE_PLLDISABLED 0x4 /* Active Mode With PLL Disabled */
-#define nACTIVE_PLLDISABLED 0x0
#define FULL_ON 0x2 /* Full-On Mode */
-#define nFULL_ON 0x0
#define ACTIVE_PLLENABLED 0x1 /* Active Mode With PLL Enabled */
-#define nACTIVE_PLLENABLED 0x0
#define RTCWS 0x400 /* RTC/Reset Wake-Up Status */
-#define nRTCWS 0x0
#define CANWS 0x800 /* CAN Wake-Up Status */
-#define nCANWS 0x0
#define USBWS 0x2000 /* USB Wake-Up Status */
-#define nUSBWS 0x0
#define KPADWS 0x4000 /* Keypad Wake-Up Status */
-#define nKPADWS 0x0
#define ROTWS 0x8000 /* Rotary Wake-Up Status */
-#define nROTWS 0x0
#define GPWS 0x1000 /* General-Purpose Wake-Up Status */
-#define nGPWS 0x0
/* Bit masks for VR_CTL */
@@ -2593,79 +2264,52 @@
#define GAIN 0xc /* Voltage Output Level Gain */
#define VLEV 0xf0 /* Internal Voltage Level */
#define SCKELOW 0x8000 /* Drive SCKE Low During Reset Enable */
-#define nSCKELOW 0x0
#define WAKE 0x100 /* RTC/Reset Wake-Up Enable */
-#define nWAKE 0x0
#define CANWE 0x200 /* CAN0/1 Wake-Up Enable */
-#define nCANWE 0x0
#define GPWE 0x400 /* General-Purpose Wake-Up Enable */
-#define nGPWE 0x0
#define USBWE 0x800 /* USB Wake-Up Enable */
-#define nUSBWE 0x0
#define KPADWE 0x1000 /* Keypad Wake-Up Enable */
-#define nKPADWE 0x0
#define ROTWE 0x2000 /* Rotary Wake-Up Enable */
-#define nROTWE 0x0
/* Bit masks for NFC_CTL */
#define WR_DLY 0xf /* Write Strobe Delay */
#define RD_DLY 0xf0 /* Read Strobe Delay */
#define NWIDTH 0x100 /* NAND Data Width */
-#define nNWIDTH 0x0
#define PG_SIZE 0x200 /* Page Size */
-#define nPG_SIZE 0x0
/* Bit masks for NFC_STAT */
#define NBUSY 0x1 /* Not Busy */
-#define nNBUSY 0x0
#define WB_FULL 0x2 /* Write Buffer Full */
-#define nWB_FULL 0x0
#define PG_WR_STAT 0x4 /* Page Write Pending */
-#define nPG_WR_STAT 0x0
#define PG_RD_STAT 0x8 /* Page Read Pending */
-#define nPG_RD_STAT 0x0
#define WB_EMPTY 0x10 /* Write Buffer Empty */
-#define nWB_EMPTY 0x0
/* Bit masks for NFC_IRQSTAT */
#define NBUSYIRQ 0x1 /* Not Busy IRQ */
-#define nNBUSYIRQ 0x0
#define WB_OVF 0x2 /* Write Buffer Overflow */
-#define nWB_OVF 0x0
#define WB_EDGE 0x4 /* Write Buffer Edge Detect */
-#define nWB_EDGE 0x0
#define RD_RDY 0x8 /* Read Data Ready */
-#define nRD_RDY 0x0
#define WR_DONE 0x10 /* Page Write Done */
-#define nWR_DONE 0x0
/* Bit masks for NFC_IRQMASK */
#define MASK_BUSYIRQ 0x1 /* Mask Not Busy IRQ */
-#define nMASK_BUSYIRQ 0x0
#define MASK_WBOVF 0x2 /* Mask Write Buffer Overflow */
-#define nMASK_WBOVF 0x0
#define MASK_WBEMPTY 0x4 /* Mask Write Buffer Empty */
-#define nMASK_WBEMPTY 0x0
#define MASK_RDRDY 0x8 /* Mask Read Data Ready */
-#define nMASK_RDRDY 0x0
#define MASK_WRDONE 0x10 /* Mask Write Done */
-#define nMASK_WRDONE 0x0
/* Bit masks for NFC_RST */
#define ECC_RST 0x1 /* ECC (and NFC counters) Reset */
-#define nECC_RST 0x0
/* Bit masks for NFC_PGCTL */
#define PG_RD_START 0x1 /* Page Read Start */
-#define nPG_RD_START 0x0
#define PG_WR_START 0x2 /* Page Write Start */
-#define nPG_WR_START 0x0
/* Bit masks for NFC_ECC0 */
@@ -2690,56 +2334,34 @@
/* Bit masks for CAN0_CONTROL */
#define SRS 0x1 /* Software Reset */
-#define nSRS 0x0
#define DNM 0x2 /* DeviceNet Mode */
-#define nDNM 0x0
#define ABO 0x4 /* Auto Bus On */
-#define nABO 0x0
#define WBA 0x10 /* Wakeup On CAN Bus Activity */
-#define nWBA 0x0
#define SMR 0x20 /* Sleep Mode Request */
-#define nSMR 0x0
#define CSR 0x40 /* CAN Suspend Mode Request */
-#define nCSR 0x0
#define CCR 0x80 /* CAN Configuration Mode Request */
-#define nCCR 0x0
/* Bit masks for CAN0_STATUS */
#define WT 0x1 /* CAN Transmit Warning Flag */
-#define nWT 0x0
#define WR 0x2 /* CAN Receive Warning Flag */
-#define nWR 0x0
#define EP 0x4 /* CAN Error Passive Mode */
-#define nEP 0x0
#define EBO 0x8 /* CAN Error Bus Off Mode */
-#define nEBO 0x0
#define CSA 0x40 /* CAN Suspend Mode Acknowledge */
-#define nCSA 0x0
#define CCA 0x80 /* CAN Configuration Mode Acknowledge */
-#define nCCA 0x0
#define MBPTR 0x1f00 /* Mailbox Pointer */
#define TRM 0x4000 /* Transmit Mode Status */
-#define nTRM 0x0
#define REC 0x8000 /* Receive Mode Status */
-#define nREC 0x0
/* Bit masks for CAN0_DEBUG */
#define DEC 0x1 /* Disable Transmit/Receive Error Counters */
-#define nDEC 0x0
#define DRI 0x2 /* Disable CANRX Input Pin */
-#define nDRI 0x0
#define DTO 0x4 /* Disable CANTX Output Pin */
-#define nDTO 0x0
#define DIL 0x8 /* Disable Internal Loop */
-#define nDIL 0x0
#define MAA 0x10 /* Mode Auto-Acknowledge */
-#define nMAA 0x0
#define MRB 0x20 /* Mode Read Back */
-#define nMRB 0x0
#define CDE 0x8000 /* CAN Debug Mode Enable */
-#define nCDE 0x0
/* Bit masks for CAN0_CLOCK */
@@ -2749,111 +2371,69 @@
#define SJW 0x300 /* Synchronization Jump Width */
#define SAM 0x80 /* Sampling */
-#define nSAM 0x0
#define TSEG2 0x70 /* Time Segment 2 */
#define TSEG1 0xf /* Time Segment 1 */
/* Bit masks for CAN0_INTR */
#define CANRX 0x80 /* Serial Input From Transceiver */
-#define nCANRX 0x0
#define CANTX 0x40 /* Serial Output To Transceiver */
-#define nCANTX 0x0
#define SMACK 0x8 /* Sleep Mode Acknowledge */
-#define nSMACK 0x0
#define GIRQ 0x4 /* Global Interrupt Request Status */
-#define nGIRQ 0x0
#define MBTIRQ 0x2 /* Mailbox Transmit Interrupt Request */
-#define nMBTIRQ 0x0
#define MBRIRQ 0x1 /* Mailbox Receive Interrupt Request */
-#define nMBRIRQ 0x0
/* Bit masks for CAN0_GIM */
#define EWTIM 0x1 /* Error Warning Transmit Interrupt Mask */
-#define nEWTIM 0x0
#define EWRIM 0x2 /* Error Warning Receive Interrupt Mask */
-#define nEWRIM 0x0
#define EPIM 0x4 /* Error Passive Interrupt Mask */
-#define nEPIM 0x0
#define BOIM 0x8 /* Bus Off Interrupt Mask */
-#define nBOIM 0x0
#define WUIM 0x10 /* Wakeup Interrupt Mask */
-#define nWUIM 0x0
#define UIAIM 0x20 /* Unimplemented Address Interrupt Mask */
-#define nUIAIM 0x0
#define AAIM 0x40 /* Abort Acknowledge Interrupt Mask */
-#define nAAIM 0x0
#define RMLIM 0x80 /* Receive Message Lost Interrupt Mask */
-#define nRMLIM 0x0
#define UCEIM 0x100 /* Universal Counter Exceeded Interrupt Mask */
-#define nUCEIM 0x0
#define ADIM 0x400 /* Access Denied Interrupt Mask */
-#define nADIM 0x0
/* Bit masks for CAN0_GIS */
#define EWTIS 0x1 /* Error Warning Transmit Interrupt Status */
-#define nEWTIS 0x0
#define EWRIS 0x2 /* Error Warning Receive Interrupt Status */
-#define nEWRIS 0x0
#define EPIS 0x4 /* Error Passive Interrupt Status */
-#define nEPIS 0x0
#define BOIS 0x8 /* Bus Off Interrupt Status */
-#define nBOIS 0x0
#define WUIS 0x10 /* Wakeup Interrupt Status */
-#define nWUIS 0x0
#define UIAIS 0x20 /* Unimplemented Address Interrupt Status */
-#define nUIAIS 0x0
#define AAIS 0x40 /* Abort Acknowledge Interrupt Status */
-#define nAAIS 0x0
#define RMLIS 0x80 /* Receive Message Lost Interrupt Status */
-#define nRMLIS 0x0
#define UCEIS 0x100 /* Universal Counter Exceeded Interrupt Status */
-#define nUCEIS 0x0
#define ADIS 0x400 /* Access Denied Interrupt Status */
-#define nADIS 0x0
/* Bit masks for CAN0_GIF */
#define EWTIF 0x1 /* Error Warning Transmit Interrupt Flag */
-#define nEWTIF 0x0
#define EWRIF 0x2 /* Error Warning Receive Interrupt Flag */
-#define nEWRIF 0x0
#define EPIF 0x4 /* Error Passive Interrupt Flag */
-#define nEPIF 0x0
#define BOIF 0x8 /* Bus Off Interrupt Flag */
-#define nBOIF 0x0
#define WUIF 0x10 /* Wakeup Interrupt Flag */
-#define nWUIF 0x0
#define UIAIF 0x20 /* Unimplemented Address Interrupt Flag */
-#define nUIAIF 0x0
#define AAIF 0x40 /* Abort Acknowledge Interrupt Flag */
-#define nAAIF 0x0
#define RMLIF 0x80 /* Receive Message Lost Interrupt Flag */
-#define nRMLIF 0x0
#define UCEIF 0x100 /* Universal Counter Exceeded Interrupt Flag */
-#define nUCEIF 0x0
#define ADIF 0x400 /* Access Denied Interrupt Flag */
-#define nADIF 0x0
/* Bit masks for CAN0_MBTD */
#define TDR 0x80 /* Temporary Disable Request */
-#define nTDR 0x0
#define TDA 0x40 /* Temporary Disable Acknowledge */
-#define nTDA 0x0
#define TDPTR 0x1f /* Temporary Disable Pointer */
/* Bit masks for CAN0_UCCNF */
#define UCCNF 0xf /* Universal Counter Configuration */
#define UCRC 0x20 /* Universal Counter Reload/Clear */
-#define nUCRC 0x0
#define UCCT 0x40 /* Universal Counter CAN Trigger */
-#define nUCCT 0x0
#define UCE 0x80 /* Universal Counter Enable */
-#define nUCE 0x0
/* Bit masks for CAN0_UCCNT */
@@ -2871,17 +2451,11 @@
/* Bit masks for CAN0_ESR */
#define FER 0x80 /* Form Error */
-#define nFER 0x0
#define BEF 0x40 /* Bit Error Flag */
-#define nBEF 0x0
#define SA0 0x20 /* Stuck At Dominant */
-#define nSA0 0x0
#define CRCE 0x10 /* CRC Error */
-#define nCRCE 0x0
#define SER 0x8 /* Stuff Bit Error */
-#define nSER 0x0
#define ACKE 0x4 /* Acknowledge Error */
-#define nACKE 0x0
/* Bit masks for CAN0_EWR */
@@ -2891,11 +2465,8 @@
/* Bit masks for CAN0_AMxx_H */
#define FDF 0x8000 /* Filter On Data Field */
-#define nFDF 0x0
#define FMD 0x4000 /* Full Mask Data */
-#define nFMD 0x0
#define AMIDE 0x2000 /* Acceptance Mask Identifier Extension */
-#define nAMIDE 0x0
#define BASEID 0x1ffc /* Base Identifier */
#define EXTID_HI 0x3 /* Extended Identifier High Bits */
@@ -2907,11 +2478,8 @@
/* Bit masks for CAN0_MBxx_ID1 */
#define AME 0x8000 /* Acceptance Mask Enable */
-#define nAME 0x0
#define RTR 0x4000 /* Remote Transmission Request */
-#define nRTR 0x0
#define IDE 0x2000 /* Identifier Extension */
-#define nIDE 0x0
#define BASEID 0x1ffc /* Base Identifier */
#define EXTID_HI 0x3 /* Extended Identifier High Bits */
@@ -2951,980 +2519,546 @@
/* Bit masks for CAN0_MC1 */
#define MC0 0x1 /* Mailbox 0 Enable */
-#define nMC0 0x0
#define MC1 0x2 /* Mailbox 1 Enable */
-#define nMC1 0x0
#define MC2 0x4 /* Mailbox 2 Enable */
-#define nMC2 0x0
#define MC3 0x8 /* Mailbox 3 Enable */
-#define nMC3 0x0
#define MC4 0x10 /* Mailbox 4 Enable */
-#define nMC4 0x0
#define MC5 0x20 /* Mailbox 5 Enable */
-#define nMC5 0x0
#define MC6 0x40 /* Mailbox 6 Enable */
-#define nMC6 0x0
#define MC7 0x80 /* Mailbox 7 Enable */
-#define nMC7 0x0
#define MC8 0x100 /* Mailbox 8 Enable */
-#define nMC8 0x0
#define MC9 0x200 /* Mailbox 9 Enable */
-#define nMC9 0x0
#define MC10 0x400 /* Mailbox 10 Enable */
-#define nMC10 0x0
#define MC11 0x800 /* Mailbox 11 Enable */
-#define nMC11 0x0
#define MC12 0x1000 /* Mailbox 12 Enable */
-#define nMC12 0x0
#define MC13 0x2000 /* Mailbox 13 Enable */
-#define nMC13 0x0
#define MC14 0x4000 /* Mailbox 14 Enable */
-#define nMC14 0x0
#define MC15 0x8000 /* Mailbox 15 Enable */
-#define nMC15 0x0
/* Bit masks for CAN0_MC2 */
#define MC16 0x1 /* Mailbox 16 Enable */
-#define nMC16 0x0
#define MC17 0x2 /* Mailbox 17 Enable */
-#define nMC17 0x0
#define MC18 0x4 /* Mailbox 18 Enable */
-#define nMC18 0x0
#define MC19 0x8 /* Mailbox 19 Enable */
-#define nMC19 0x0
#define MC20 0x10 /* Mailbox 20 Enable */
-#define nMC20 0x0
#define MC21 0x20 /* Mailbox 21 Enable */
-#define nMC21 0x0
#define MC22 0x40 /* Mailbox 22 Enable */
-#define nMC22 0x0
#define MC23 0x80 /* Mailbox 23 Enable */
-#define nMC23 0x0
#define MC24 0x100 /* Mailbox 24 Enable */
-#define nMC24 0x0
#define MC25 0x200 /* Mailbox 25 Enable */
-#define nMC25 0x0
#define MC26 0x400 /* Mailbox 26 Enable */
-#define nMC26 0x0
#define MC27 0x800 /* Mailbox 27 Enable */
-#define nMC27 0x0
#define MC28 0x1000 /* Mailbox 28 Enable */
-#define nMC28 0x0
#define MC29 0x2000 /* Mailbox 29 Enable */
-#define nMC29 0x0
#define MC30 0x4000 /* Mailbox 30 Enable */
-#define nMC30 0x0
#define MC31 0x8000 /* Mailbox 31 Enable */
-#define nMC31 0x0
/* Bit masks for CAN0_MD1 */
#define MD0 0x1 /* Mailbox 0 Receive Enable */
-#define nMD0 0x0
#define MD1 0x2 /* Mailbox 1 Receive Enable */
-#define nMD1 0x0
#define MD2 0x4 /* Mailbox 2 Receive Enable */
-#define nMD2 0x0
#define MD3 0x8 /* Mailbox 3 Receive Enable */
-#define nMD3 0x0
#define MD4 0x10 /* Mailbox 4 Receive Enable */
-#define nMD4 0x0
#define MD5 0x20 /* Mailbox 5 Receive Enable */
-#define nMD5 0x0
#define MD6 0x40 /* Mailbox 6 Receive Enable */
-#define nMD6 0x0
#define MD7 0x80 /* Mailbox 7 Receive Enable */
-#define nMD7 0x0
#define MD8 0x100 /* Mailbox 8 Receive Enable */
-#define nMD8 0x0
#define MD9 0x200 /* Mailbox 9 Receive Enable */
-#define nMD9 0x0
#define MD10 0x400 /* Mailbox 10 Receive Enable */
-#define nMD10 0x0
#define MD11 0x800 /* Mailbox 11 Receive Enable */
-#define nMD11 0x0
#define MD12 0x1000 /* Mailbox 12 Receive Enable */
-#define nMD12 0x0
#define MD13 0x2000 /* Mailbox 13 Receive Enable */
-#define nMD13 0x0
#define MD14 0x4000 /* Mailbox 14 Receive Enable */
-#define nMD14 0x0
#define MD15 0x8000 /* Mailbox 15 Receive Enable */
-#define nMD15 0x0
/* Bit masks for CAN0_MD2 */
#define MD16 0x1 /* Mailbox 16 Receive Enable */
-#define nMD16 0x0
#define MD17 0x2 /* Mailbox 17 Receive Enable */
-#define nMD17 0x0
#define MD18 0x4 /* Mailbox 18 Receive Enable */
-#define nMD18 0x0
#define MD19 0x8 /* Mailbox 19 Receive Enable */
-#define nMD19 0x0
#define MD20 0x10 /* Mailbox 20 Receive Enable */
-#define nMD20 0x0
#define MD21 0x20 /* Mailbox 21 Receive Enable */
-#define nMD21 0x0
#define MD22 0x40 /* Mailbox 22 Receive Enable */
-#define nMD22 0x0
#define MD23 0x80 /* Mailbox 23 Receive Enable */
-#define nMD23 0x0
#define MD24 0x100 /* Mailbox 24 Receive Enable */
-#define nMD24 0x0
#define MD25 0x200 /* Mailbox 25 Receive Enable */
-#define nMD25 0x0
#define MD26 0x400 /* Mailbox 26 Receive Enable */
-#define nMD26 0x0
#define MD27 0x800 /* Mailbox 27 Receive Enable */
-#define nMD27 0x0
#define MD28 0x1000 /* Mailbox 28 Receive Enable */
-#define nMD28 0x0
#define MD29 0x2000 /* Mailbox 29 Receive Enable */
-#define nMD29 0x0
#define MD30 0x4000 /* Mailbox 30 Receive Enable */
-#define nMD30 0x0
#define MD31 0x8000 /* Mailbox 31 Receive Enable */
-#define nMD31 0x0
/* Bit masks for CAN0_RMP1 */
#define RMP0 0x1 /* Mailbox 0 Receive Message Pending */
-#define nRMP0 0x0
#define RMP1 0x2 /* Mailbox 1 Receive Message Pending */
-#define nRMP1 0x0
#define RMP2 0x4 /* Mailbox 2 Receive Message Pending */
-#define nRMP2 0x0
#define RMP3 0x8 /* Mailbox 3 Receive Message Pending */
-#define nRMP3 0x0
#define RMP4 0x10 /* Mailbox 4 Receive Message Pending */
-#define nRMP4 0x0
#define RMP5 0x20 /* Mailbox 5 Receive Message Pending */
-#define nRMP5 0x0
#define RMP6 0x40 /* Mailbox 6 Receive Message Pending */
-#define nRMP6 0x0
#define RMP7 0x80 /* Mailbox 7 Receive Message Pending */
-#define nRMP7 0x0
#define RMP8 0x100 /* Mailbox 8 Receive Message Pending */
-#define nRMP8 0x0
#define RMP9 0x200 /* Mailbox 9 Receive Message Pending */
-#define nRMP9 0x0
#define RMP10 0x400 /* Mailbox 10 Receive Message Pending */
-#define nRMP10 0x0
#define RMP11 0x800 /* Mailbox 11 Receive Message Pending */
-#define nRMP11 0x0
#define RMP12 0x1000 /* Mailbox 12 Receive Message Pending */
-#define nRMP12 0x0
#define RMP13 0x2000 /* Mailbox 13 Receive Message Pending */
-#define nRMP13 0x0
#define RMP14 0x4000 /* Mailbox 14 Receive Message Pending */
-#define nRMP14 0x0
#define RMP15 0x8000 /* Mailbox 15 Receive Message Pending */
-#define nRMP15 0x0
/* Bit masks for CAN0_RMP2 */
#define RMP16 0x1 /* Mailbox 16 Receive Message Pending */
-#define nRMP16 0x0
#define RMP17 0x2 /* Mailbox 17 Receive Message Pending */
-#define nRMP17 0x0
#define RMP18 0x4 /* Mailbox 18 Receive Message Pending */
-#define nRMP18 0x0
#define RMP19 0x8 /* Mailbox 19 Receive Message Pending */
-#define nRMP19 0x0
#define RMP20 0x10 /* Mailbox 20 Receive Message Pending */
-#define nRMP20 0x0
#define RMP21 0x20 /* Mailbox 21 Receive Message Pending */
-#define nRMP21 0x0
#define RMP22 0x40 /* Mailbox 22 Receive Message Pending */
-#define nRMP22 0x0
#define RMP23 0x80 /* Mailbox 23 Receive Message Pending */
-#define nRMP23 0x0
#define RMP24 0x100 /* Mailbox 24 Receive Message Pending */
-#define nRMP24 0x0
#define RMP25 0x200 /* Mailbox 25 Receive Message Pending */
-#define nRMP25 0x0
#define RMP26 0x400 /* Mailbox 26 Receive Message Pending */
-#define nRMP26 0x0
#define RMP27 0x800 /* Mailbox 27 Receive Message Pending */
-#define nRMP27 0x0
#define RMP28 0x1000 /* Mailbox 28 Receive Message Pending */
-#define nRMP28 0x0
#define RMP29 0x2000 /* Mailbox 29 Receive Message Pending */
-#define nRMP29 0x0
#define RMP30 0x4000 /* Mailbox 30 Receive Message Pending */
-#define nRMP30 0x0
#define RMP31 0x8000 /* Mailbox 31 Receive Message Pending */
-#define nRMP31 0x0
/* Bit masks for CAN0_RML1 */
#define RML0 0x1 /* Mailbox 0 Receive Message Lost */
-#define nRML0 0x0
#define RML1 0x2 /* Mailbox 1 Receive Message Lost */
-#define nRML1 0x0
#define RML2 0x4 /* Mailbox 2 Receive Message Lost */
-#define nRML2 0x0
#define RML3 0x8 /* Mailbox 3 Receive Message Lost */
-#define nRML3 0x0
#define RML4 0x10 /* Mailbox 4 Receive Message Lost */
-#define nRML4 0x0
#define RML5 0x20 /* Mailbox 5 Receive Message Lost */
-#define nRML5 0x0
#define RML6 0x40 /* Mailbox 6 Receive Message Lost */
-#define nRML6 0x0
#define RML7 0x80 /* Mailbox 7 Receive Message Lost */
-#define nRML7 0x0
#define RML8 0x100 /* Mailbox 8 Receive Message Lost */
-#define nRML8 0x0
#define RML9 0x200 /* Mailbox 9 Receive Message Lost */
-#define nRML9 0x0
#define RML10 0x400 /* Mailbox 10 Receive Message Lost */
-#define nRML10 0x0
#define RML11 0x800 /* Mailbox 11 Receive Message Lost */
-#define nRML11 0x0
#define RML12 0x1000 /* Mailbox 12 Receive Message Lost */
-#define nRML12 0x0
#define RML13 0x2000 /* Mailbox 13 Receive Message Lost */
-#define nRML13 0x0
#define RML14 0x4000 /* Mailbox 14 Receive Message Lost */
-#define nRML14 0x0
#define RML15 0x8000 /* Mailbox 15 Receive Message Lost */
-#define nRML15 0x0
/* Bit masks for CAN0_RML2 */
#define RML16 0x1 /* Mailbox 16 Receive Message Lost */
-#define nRML16 0x0
#define RML17 0x2 /* Mailbox 17 Receive Message Lost */
-#define nRML17 0x0
#define RML18 0x4 /* Mailbox 18 Receive Message Lost */
-#define nRML18 0x0
#define RML19 0x8 /* Mailbox 19 Receive Message Lost */
-#define nRML19 0x0
#define RML20 0x10 /* Mailbox 20 Receive Message Lost */
-#define nRML20 0x0
#define RML21 0x20 /* Mailbox 21 Receive Message Lost */
-#define nRML21 0x0
#define RML22 0x40 /* Mailbox 22 Receive Message Lost */
-#define nRML22 0x0
#define RML23 0x80 /* Mailbox 23 Receive Message Lost */
-#define nRML23 0x0
#define RML24 0x100 /* Mailbox 24 Receive Message Lost */
-#define nRML24 0x0
#define RML25 0x200 /* Mailbox 25 Receive Message Lost */
-#define nRML25 0x0
#define RML26 0x400 /* Mailbox 26 Receive Message Lost */
-#define nRML26 0x0
#define RML27 0x800 /* Mailbox 27 Receive Message Lost */
-#define nRML27 0x0
#define RML28 0x1000 /* Mailbox 28 Receive Message Lost */
-#define nRML28 0x0
#define RML29 0x2000 /* Mailbox 29 Receive Message Lost */
-#define nRML29 0x0
#define RML30 0x4000 /* Mailbox 30 Receive Message Lost */
-#define nRML30 0x0
#define RML31 0x8000 /* Mailbox 31 Receive Message Lost */
-#define nRML31 0x0
/* Bit masks for CAN0_OPSS1 */
#define OPSS0 0x1 /* Mailbox 0 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS0 0x0
#define OPSS1 0x2 /* Mailbox 1 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS1 0x0
#define OPSS2 0x4 /* Mailbox 2 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS2 0x0
#define OPSS3 0x8 /* Mailbox 3 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS3 0x0
#define OPSS4 0x10 /* Mailbox 4 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS4 0x0
#define OPSS5 0x20 /* Mailbox 5 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS5 0x0
#define OPSS6 0x40 /* Mailbox 6 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS6 0x0
#define OPSS7 0x80 /* Mailbox 7 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS7 0x0
#define OPSS8 0x100 /* Mailbox 8 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS8 0x0
#define OPSS9 0x200 /* Mailbox 9 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS9 0x0
#define OPSS10 0x400 /* Mailbox 10 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS10 0x0
#define OPSS11 0x800 /* Mailbox 11 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS11 0x0
#define OPSS12 0x1000 /* Mailbox 12 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS12 0x0
#define OPSS13 0x2000 /* Mailbox 13 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS13 0x0
#define OPSS14 0x4000 /* Mailbox 14 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS14 0x0
#define OPSS15 0x8000 /* Mailbox 15 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS15 0x0
/* Bit masks for CAN0_OPSS2 */
#define OPSS16 0x1 /* Mailbox 16 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS16 0x0
#define OPSS17 0x2 /* Mailbox 17 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS17 0x0
#define OPSS18 0x4 /* Mailbox 18 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS18 0x0
#define OPSS19 0x8 /* Mailbox 19 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS19 0x0
#define OPSS20 0x10 /* Mailbox 20 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS20 0x0
#define OPSS21 0x20 /* Mailbox 21 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS21 0x0
#define OPSS22 0x40 /* Mailbox 22 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS22 0x0
#define OPSS23 0x80 /* Mailbox 23 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS23 0x0
#define OPSS24 0x100 /* Mailbox 24 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS24 0x0
#define OPSS25 0x200 /* Mailbox 25 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS25 0x0
#define OPSS26 0x400 /* Mailbox 26 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS26 0x0
#define OPSS27 0x800 /* Mailbox 27 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS27 0x0
#define OPSS28 0x1000 /* Mailbox 28 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS28 0x0
#define OPSS29 0x2000 /* Mailbox 29 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS29 0x0
#define OPSS30 0x4000 /* Mailbox 30 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS30 0x0
#define OPSS31 0x8000 /* Mailbox 31 Overwrite Protection/Single-Shot Transmission Enable */
-#define nOPSS31 0x0
/* Bit masks for CAN0_TRS1 */
#define TRS0 0x1 /* Mailbox 0 Transmit Request Set */
-#define nTRS0 0x0
#define TRS1 0x2 /* Mailbox 1 Transmit Request Set */
-#define nTRS1 0x0
#define TRS2 0x4 /* Mailbox 2 Transmit Request Set */
-#define nTRS2 0x0
#define TRS3 0x8 /* Mailbox 3 Transmit Request Set */
-#define nTRS3 0x0
#define TRS4 0x10 /* Mailbox 4 Transmit Request Set */
-#define nTRS4 0x0
#define TRS5 0x20 /* Mailbox 5 Transmit Request Set */
-#define nTRS5 0x0
#define TRS6 0x40 /* Mailbox 6 Transmit Request Set */
-#define nTRS6 0x0
#define TRS7 0x80 /* Mailbox 7 Transmit Request Set */
-#define nTRS7 0x0
#define TRS8 0x100 /* Mailbox 8 Transmit Request Set */
-#define nTRS8 0x0
#define TRS9 0x200 /* Mailbox 9 Transmit Request Set */
-#define nTRS9 0x0
#define TRS10 0x400 /* Mailbox 10 Transmit Request Set */
-#define nTRS10 0x0
#define TRS11 0x800 /* Mailbox 11 Transmit Request Set */
-#define nTRS11 0x0
#define TRS12 0x1000 /* Mailbox 12 Transmit Request Set */
-#define nTRS12 0x0
#define TRS13 0x2000 /* Mailbox 13 Transmit Request Set */
-#define nTRS13 0x0
#define TRS14 0x4000 /* Mailbox 14 Transmit Request Set */
-#define nTRS14 0x0
#define TRS15 0x8000 /* Mailbox 15 Transmit Request Set */
-#define nTRS15 0x0
/* Bit masks for CAN0_TRS2 */
#define TRS16 0x1 /* Mailbox 16 Transmit Request Set */
-#define nTRS16 0x0
#define TRS17 0x2 /* Mailbox 17 Transmit Request Set */
-#define nTRS17 0x0
#define TRS18 0x4 /* Mailbox 18 Transmit Request Set */
-#define nTRS18 0x0
#define TRS19 0x8 /* Mailbox 19 Transmit Request Set */
-#define nTRS19 0x0
#define TRS20 0x10 /* Mailbox 20 Transmit Request Set */
-#define nTRS20 0x0
#define TRS21 0x20 /* Mailbox 21 Transmit Request Set */
-#define nTRS21 0x0
#define TRS22 0x40 /* Mailbox 22 Transmit Request Set */
-#define nTRS22 0x0
#define TRS23 0x80 /* Mailbox 23 Transmit Request Set */
-#define nTRS23 0x0
#define TRS24 0x100 /* Mailbox 24 Transmit Request Set */
-#define nTRS24 0x0
#define TRS25 0x200 /* Mailbox 25 Transmit Request Set */
-#define nTRS25 0x0
#define TRS26 0x400 /* Mailbox 26 Transmit Request Set */
-#define nTRS26 0x0
#define TRS27 0x800 /* Mailbox 27 Transmit Request Set */
-#define nTRS27 0x0
#define TRS28 0x1000 /* Mailbox 28 Transmit Request Set */
-#define nTRS28 0x0
#define TRS29 0x2000 /* Mailbox 29 Transmit Request Set */
-#define nTRS29 0x0
#define TRS30 0x4000 /* Mailbox 30 Transmit Request Set */
-#define nTRS30 0x0
#define TRS31 0x8000 /* Mailbox 31 Transmit Request Set */
-#define nTRS31 0x0
/* Bit masks for CAN0_TRR1 */
#define TRR0 0x1 /* Mailbox 0 Transmit Request Reset */
-#define nTRR0 0x0
#define TRR1 0x2 /* Mailbox 1 Transmit Request Reset */
-#define nTRR1 0x0
#define TRR2 0x4 /* Mailbox 2 Transmit Request Reset */
-#define nTRR2 0x0
#define TRR3 0x8 /* Mailbox 3 Transmit Request Reset */
-#define nTRR3 0x0
#define TRR4 0x10 /* Mailbox 4 Transmit Request Reset */
-#define nTRR4 0x0
#define TRR5 0x20 /* Mailbox 5 Transmit Request Reset */
-#define nTRR5 0x0
#define TRR6 0x40 /* Mailbox 6 Transmit Request Reset */
-#define nTRR6 0x0
#define TRR7 0x80 /* Mailbox 7 Transmit Request Reset */
-#define nTRR7 0x0
#define TRR8 0x100 /* Mailbox 8 Transmit Request Reset */
-#define nTRR8 0x0
#define TRR9 0x200 /* Mailbox 9 Transmit Request Reset */
-#define nTRR9 0x0
#define TRR10 0x400 /* Mailbox 10 Transmit Request Reset */
-#define nTRR10 0x0
#define TRR11 0x800 /* Mailbox 11 Transmit Request Reset */
-#define nTRR11 0x0
#define TRR12 0x1000 /* Mailbox 12 Transmit Request Reset */
-#define nTRR12 0x0
#define TRR13 0x2000 /* Mailbox 13 Transmit Request Reset */
-#define nTRR13 0x0
#define TRR14 0x4000 /* Mailbox 14 Transmit Request Reset */
-#define nTRR14 0x0
#define TRR15 0x8000 /* Mailbox 15 Transmit Request Reset */
-#define nTRR15 0x0
/* Bit masks for CAN0_TRR2 */
#define TRR16 0x1 /* Mailbox 16 Transmit Request Reset */
-#define nTRR16 0x0
#define TRR17 0x2 /* Mailbox 17 Transmit Request Reset */
-#define nTRR17 0x0
#define TRR18 0x4 /* Mailbox 18 Transmit Request Reset */
-#define nTRR18 0x0
#define TRR19 0x8 /* Mailbox 19 Transmit Request Reset */
-#define nTRR19 0x0
#define TRR20 0x10 /* Mailbox 20 Transmit Request Reset */
-#define nTRR20 0x0
#define TRR21 0x20 /* Mailbox 21 Transmit Request Reset */
-#define nTRR21 0x0
#define TRR22 0x40 /* Mailbox 22 Transmit Request Reset */
-#define nTRR22 0x0
#define TRR23 0x80 /* Mailbox 23 Transmit Request Reset */
-#define nTRR23 0x0
#define TRR24 0x100 /* Mailbox 24 Transmit Request Reset */
-#define nTRR24 0x0
#define TRR25 0x200 /* Mailbox 25 Transmit Request Reset */
-#define nTRR25 0x0
#define TRR26 0x400 /* Mailbox 26 Transmit Request Reset */
-#define nTRR26 0x0
#define TRR27 0x800 /* Mailbox 27 Transmit Request Reset */
-#define nTRR27 0x0
#define TRR28 0x1000 /* Mailbox 28 Transmit Request Reset */
-#define nTRR28 0x0
#define TRR29 0x2000 /* Mailbox 29 Transmit Request Reset */
-#define nTRR29 0x0
#define TRR30 0x4000 /* Mailbox 30 Transmit Request Reset */
-#define nTRR30 0x0
#define TRR31 0x8000 /* Mailbox 31 Transmit Request Reset */
-#define nTRR31 0x0
/* Bit masks for CAN0_AA1 */
#define AA0 0x1 /* Mailbox 0 Abort Acknowledge */
-#define nAA0 0x0
#define AA1 0x2 /* Mailbox 1 Abort Acknowledge */
-#define nAA1 0x0
#define AA2 0x4 /* Mailbox 2 Abort Acknowledge */
-#define nAA2 0x0
#define AA3 0x8 /* Mailbox 3 Abort Acknowledge */
-#define nAA3 0x0
#define AA4 0x10 /* Mailbox 4 Abort Acknowledge */
-#define nAA4 0x0
#define AA5 0x20 /* Mailbox 5 Abort Acknowledge */
-#define nAA5 0x0
#define AA6 0x40 /* Mailbox 6 Abort Acknowledge */
-#define nAA6 0x0
#define AA7 0x80 /* Mailbox 7 Abort Acknowledge */
-#define nAA7 0x0
#define AA8 0x100 /* Mailbox 8 Abort Acknowledge */
-#define nAA8 0x0
#define AA9 0x200 /* Mailbox 9 Abort Acknowledge */
-#define nAA9 0x0
#define AA10 0x400 /* Mailbox 10 Abort Acknowledge */
-#define nAA10 0x0
#define AA11 0x800 /* Mailbox 11 Abort Acknowledge */
-#define nAA11 0x0
#define AA12 0x1000 /* Mailbox 12 Abort Acknowledge */
-#define nAA12 0x0
#define AA13 0x2000 /* Mailbox 13 Abort Acknowledge */
-#define nAA13 0x0
#define AA14 0x4000 /* Mailbox 14 Abort Acknowledge */
-#define nAA14 0x0
#define AA15 0x8000 /* Mailbox 15 Abort Acknowledge */
-#define nAA15 0x0
/* Bit masks for CAN0_AA2 */
#define AA16 0x1 /* Mailbox 16 Abort Acknowledge */
-#define nAA16 0x0
#define AA17 0x2 /* Mailbox 17 Abort Acknowledge */
-#define nAA17 0x0
#define AA18 0x4 /* Mailbox 18 Abort Acknowledge */
-#define nAA18 0x0
#define AA19 0x8 /* Mailbox 19 Abort Acknowledge */
-#define nAA19 0x0
#define AA20 0x10 /* Mailbox 20 Abort Acknowledge */
-#define nAA20 0x0
#define AA21 0x20 /* Mailbox 21 Abort Acknowledge */
-#define nAA21 0x0
#define AA22 0x40 /* Mailbox 22 Abort Acknowledge */
-#define nAA22 0x0
#define AA23 0x80 /* Mailbox 23 Abort Acknowledge */
-#define nAA23 0x0
#define AA24 0x100 /* Mailbox 24 Abort Acknowledge */
-#define nAA24 0x0
#define AA25 0x200 /* Mailbox 25 Abort Acknowledge */
-#define nAA25 0x0
#define AA26 0x400 /* Mailbox 26 Abort Acknowledge */
-#define nAA26 0x0
#define AA27 0x800 /* Mailbox 27 Abort Acknowledge */
-#define nAA27 0x0
#define AA28 0x1000 /* Mailbox 28 Abort Acknowledge */
-#define nAA28 0x0
#define AA29 0x2000 /* Mailbox 29 Abort Acknowledge */
-#define nAA29 0x0
#define AA30 0x4000 /* Mailbox 30 Abort Acknowledge */
-#define nAA30 0x0
#define AA31 0x8000 /* Mailbox 31 Abort Acknowledge */
-#define nAA31 0x0
/* Bit masks for CAN0_TA1 */
#define TA0 0x1 /* Mailbox 0 Transmit Acknowledge */
-#define nTA0 0x0
#define TA1 0x2 /* Mailbox 1 Transmit Acknowledge */
-#define nTA1 0x0
#define TA2 0x4 /* Mailbox 2 Transmit Acknowledge */
-#define nTA2 0x0
#define TA3 0x8 /* Mailbox 3 Transmit Acknowledge */
-#define nTA3 0x0
#define TA4 0x10 /* Mailbox 4 Transmit Acknowledge */
-#define nTA4 0x0
#define TA5 0x20 /* Mailbox 5 Transmit Acknowledge */
-#define nTA5 0x0
#define TA6 0x40 /* Mailbox 6 Transmit Acknowledge */
-#define nTA6 0x0
#define TA7 0x80 /* Mailbox 7 Transmit Acknowledge */
-#define nTA7 0x0
#define TA8 0x100 /* Mailbox 8 Transmit Acknowledge */
-#define nTA8 0x0
#define TA9 0x200 /* Mailbox 9 Transmit Acknowledge */
-#define nTA9 0x0
#define TA10 0x400 /* Mailbox 10 Transmit Acknowledge */
-#define nTA10 0x0
#define TA11 0x800 /* Mailbox 11 Transmit Acknowledge */
-#define nTA11 0x0
#define TA12 0x1000 /* Mailbox 12 Transmit Acknowledge */
-#define nTA12 0x0
#define TA13 0x2000 /* Mailbox 13 Transmit Acknowledge */
-#define nTA13 0x0
#define TA14 0x4000 /* Mailbox 14 Transmit Acknowledge */
-#define nTA14 0x0
#define TA15 0x8000 /* Mailbox 15 Transmit Acknowledge */
-#define nTA15 0x0
/* Bit masks for CAN0_TA2 */
#define TA16 0x1 /* Mailbox 16 Transmit Acknowledge */
-#define nTA16 0x0
#define TA17 0x2 /* Mailbox 17 Transmit Acknowledge */
-#define nTA17 0x0
#define TA18 0x4 /* Mailbox 18 Transmit Acknowledge */
-#define nTA18 0x0
#define TA19 0x8 /* Mailbox 19 Transmit Acknowledge */
-#define nTA19 0x0
#define TA20 0x10 /* Mailbox 20 Transmit Acknowledge */
-#define nTA20 0x0
#define TA21 0x20 /* Mailbox 21 Transmit Acknowledge */
-#define nTA21 0x0
#define TA22 0x40 /* Mailbox 22 Transmit Acknowledge */
-#define nTA22 0x0
#define TA23 0x80 /* Mailbox 23 Transmit Acknowledge */
-#define nTA23 0x0
#define TA24 0x100 /* Mailbox 24 Transmit Acknowledge */
-#define nTA24 0x0
#define TA25 0x200 /* Mailbox 25 Transmit Acknowledge */
-#define nTA25 0x0
#define TA26 0x400 /* Mailbox 26 Transmit Acknowledge */
-#define nTA26 0x0
#define TA27 0x800 /* Mailbox 27 Transmit Acknowledge */
-#define nTA27 0x0
#define TA28 0x1000 /* Mailbox 28 Transmit Acknowledge */
-#define nTA28 0x0
#define TA29 0x2000 /* Mailbox 29 Transmit Acknowledge */
-#define nTA29 0x0
#define TA30 0x4000 /* Mailbox 30 Transmit Acknowledge */
-#define nTA30 0x0
#define TA31 0x8000 /* Mailbox 31 Transmit Acknowledge */
-#define nTA31 0x0
/* Bit masks for CAN0_RFH1 */
#define RFH0 0x1 /* Mailbox 0 Remote Frame Handling Enable */
-#define nRFH0 0x0
#define RFH1 0x2 /* Mailbox 1 Remote Frame Handling Enable */
-#define nRFH1 0x0
#define RFH2 0x4 /* Mailbox 2 Remote Frame Handling Enable */
-#define nRFH2 0x0
#define RFH3 0x8 /* Mailbox 3 Remote Frame Handling Enable */
-#define nRFH3 0x0
#define RFH4 0x10 /* Mailbox 4 Remote Frame Handling Enable */
-#define nRFH4 0x0
#define RFH5 0x20 /* Mailbox 5 Remote Frame Handling Enable */
-#define nRFH5 0x0
#define RFH6 0x40 /* Mailbox 6 Remote Frame Handling Enable */
-#define nRFH6 0x0
#define RFH7 0x80 /* Mailbox 7 Remote Frame Handling Enable */
-#define nRFH7 0x0
#define RFH8 0x100 /* Mailbox 8 Remote Frame Handling Enable */
-#define nRFH8 0x0
#define RFH9 0x200 /* Mailbox 9 Remote Frame Handling Enable */
-#define nRFH9 0x0
#define RFH10 0x400 /* Mailbox 10 Remote Frame Handling Enable */
-#define nRFH10 0x0
#define RFH11 0x800 /* Mailbox 11 Remote Frame Handling Enable */
-#define nRFH11 0x0
#define RFH12 0x1000 /* Mailbox 12 Remote Frame Handling Enable */
-#define nRFH12 0x0
#define RFH13 0x2000 /* Mailbox 13 Remote Frame Handling Enable */
-#define nRFH13 0x0
#define RFH14 0x4000 /* Mailbox 14 Remote Frame Handling Enable */
-#define nRFH14 0x0
#define RFH15 0x8000 /* Mailbox 15 Remote Frame Handling Enable */
-#define nRFH15 0x0
/* Bit masks for CAN0_RFH2 */
#define RFH16 0x1 /* Mailbox 16 Remote Frame Handling Enable */
-#define nRFH16 0x0
#define RFH17 0x2 /* Mailbox 17 Remote Frame Handling Enable */
-#define nRFH17 0x0
#define RFH18 0x4 /* Mailbox 18 Remote Frame Handling Enable */
-#define nRFH18 0x0
#define RFH19 0x8 /* Mailbox 19 Remote Frame Handling Enable */
-#define nRFH19 0x0
#define RFH20 0x10 /* Mailbox 20 Remote Frame Handling Enable */
-#define nRFH20 0x0
#define RFH21 0x20 /* Mailbox 21 Remote Frame Handling Enable */
-#define nRFH21 0x0
#define RFH22 0x40 /* Mailbox 22 Remote Frame Handling Enable */
-#define nRFH22 0x0
#define RFH23 0x80 /* Mailbox 23 Remote Frame Handling Enable */
-#define nRFH23 0x0
#define RFH24 0x100 /* Mailbox 24 Remote Frame Handling Enable */
-#define nRFH24 0x0
#define RFH25 0x200 /* Mailbox 25 Remote Frame Handling Enable */
-#define nRFH25 0x0
#define RFH26 0x400 /* Mailbox 26 Remote Frame Handling Enable */
-#define nRFH26 0x0
#define RFH27 0x800 /* Mailbox 27 Remote Frame Handling Enable */
-#define nRFH27 0x0
#define RFH28 0x1000 /* Mailbox 28 Remote Frame Handling Enable */
-#define nRFH28 0x0
#define RFH29 0x2000 /* Mailbox 29 Remote Frame Handling Enable */
-#define nRFH29 0x0
#define RFH30 0x4000 /* Mailbox 30 Remote Frame Handling Enable */
-#define nRFH30 0x0
#define RFH31 0x8000 /* Mailbox 31 Remote Frame Handling Enable */
-#define nRFH31 0x0
/* Bit masks for CAN0_MBIM1 */
#define MBIM0 0x1 /* Mailbox 0 Mailbox Interrupt Mask */
-#define nMBIM0 0x0
#define MBIM1 0x2 /* Mailbox 1 Mailbox Interrupt Mask */
-#define nMBIM1 0x0
#define MBIM2 0x4 /* Mailbox 2 Mailbox Interrupt Mask */
-#define nMBIM2 0x0
#define MBIM3 0x8 /* Mailbox 3 Mailbox Interrupt Mask */
-#define nMBIM3 0x0
#define MBIM4 0x10 /* Mailbox 4 Mailbox Interrupt Mask */
-#define nMBIM4 0x0
#define MBIM5 0x20 /* Mailbox 5 Mailbox Interrupt Mask */
-#define nMBIM5 0x0
#define MBIM6 0x40 /* Mailbox 6 Mailbox Interrupt Mask */
-#define nMBIM6 0x0
#define MBIM7 0x80 /* Mailbox 7 Mailbox Interrupt Mask */
-#define nMBIM7 0x0
#define MBIM8 0x100 /* Mailbox 8 Mailbox Interrupt Mask */
-#define nMBIM8 0x0
#define MBIM9 0x200 /* Mailbox 9 Mailbox Interrupt Mask */
-#define nMBIM9 0x0
#define MBIM10 0x400 /* Mailbox 10 Mailbox Interrupt Mask */
-#define nMBIM10 0x0
#define MBIM11 0x800 /* Mailbox 11 Mailbox Interrupt Mask */
-#define nMBIM11 0x0
#define MBIM12 0x1000 /* Mailbox 12 Mailbox Interrupt Mask */
-#define nMBIM12 0x0
#define MBIM13 0x2000 /* Mailbox 13 Mailbox Interrupt Mask */
-#define nMBIM13 0x0
#define MBIM14 0x4000 /* Mailbox 14 Mailbox Interrupt Mask */
-#define nMBIM14 0x0
#define MBIM15 0x8000 /* Mailbox 15 Mailbox Interrupt Mask */
-#define nMBIM15 0x0
/* Bit masks for CAN0_MBIM2 */
#define MBIM16 0x1 /* Mailbox 16 Mailbox Interrupt Mask */
-#define nMBIM16 0x0
#define MBIM17 0x2 /* Mailbox 17 Mailbox Interrupt Mask */
-#define nMBIM17 0x0
#define MBIM18 0x4 /* Mailbox 18 Mailbox Interrupt Mask */
-#define nMBIM18 0x0
#define MBIM19 0x8 /* Mailbox 19 Mailbox Interrupt Mask */
-#define nMBIM19 0x0
#define MBIM20 0x10 /* Mailbox 20 Mailbox Interrupt Mask */
-#define nMBIM20 0x0
#define MBIM21 0x20 /* Mailbox 21 Mailbox Interrupt Mask */
-#define nMBIM21 0x0
#define MBIM22 0x40 /* Mailbox 22 Mailbox Interrupt Mask */
-#define nMBIM22 0x0
#define MBIM23 0x80 /* Mailbox 23 Mailbox Interrupt Mask */
-#define nMBIM23 0x0
#define MBIM24 0x100 /* Mailbox 24 Mailbox Interrupt Mask */
-#define nMBIM24 0x0
#define MBIM25 0x200 /* Mailbox 25 Mailbox Interrupt Mask */
-#define nMBIM25 0x0
#define MBIM26 0x400 /* Mailbox 26 Mailbox Interrupt Mask */
-#define nMBIM26 0x0
#define MBIM27 0x800 /* Mailbox 27 Mailbox Interrupt Mask */
-#define nMBIM27 0x0
#define MBIM28 0x1000 /* Mailbox 28 Mailbox Interrupt Mask */
-#define nMBIM28 0x0
#define MBIM29 0x2000 /* Mailbox 29 Mailbox Interrupt Mask */
-#define nMBIM29 0x0
#define MBIM30 0x4000 /* Mailbox 30 Mailbox Interrupt Mask */
-#define nMBIM30 0x0
#define MBIM31 0x8000 /* Mailbox 31 Mailbox Interrupt Mask */
-#define nMBIM31 0x0
/* Bit masks for CAN0_MBTIF1 */
#define MBTIF0 0x1 /* Mailbox 0 Mailbox Transmit Interrupt Flag */
-#define nMBTIF0 0x0
#define MBTIF1 0x2 /* Mailbox 1 Mailbox Transmit Interrupt Flag */
-#define nMBTIF1 0x0
#define MBTIF2 0x4 /* Mailbox 2 Mailbox Transmit Interrupt Flag */
-#define nMBTIF2 0x0
#define MBTIF3 0x8 /* Mailbox 3 Mailbox Transmit Interrupt Flag */
-#define nMBTIF3 0x0
#define MBTIF4 0x10 /* Mailbox 4 Mailbox Transmit Interrupt Flag */
-#define nMBTIF4 0x0
#define MBTIF5 0x20 /* Mailbox 5 Mailbox Transmit Interrupt Flag */
-#define nMBTIF5 0x0
#define MBTIF6 0x40 /* Mailbox 6 Mailbox Transmit Interrupt Flag */
-#define nMBTIF6 0x0
#define MBTIF7 0x80 /* Mailbox 7 Mailbox Transmit Interrupt Flag */
-#define nMBTIF7 0x0
#define MBTIF8 0x100 /* Mailbox 8 Mailbox Transmit Interrupt Flag */
-#define nMBTIF8 0x0
#define MBTIF9 0x200 /* Mailbox 9 Mailbox Transmit Interrupt Flag */
-#define nMBTIF9 0x0
#define MBTIF10 0x400 /* Mailbox 10 Mailbox Transmit Interrupt Flag */
-#define nMBTIF10 0x0
#define MBTIF11 0x800 /* Mailbox 11 Mailbox Transmit Interrupt Flag */
-#define nMBTIF11 0x0
#define MBTIF12 0x1000 /* Mailbox 12 Mailbox Transmit Interrupt Flag */
-#define nMBTIF12 0x0
#define MBTIF13 0x2000 /* Mailbox 13 Mailbox Transmit Interrupt Flag */
-#define nMBTIF13 0x0
#define MBTIF14 0x4000 /* Mailbox 14 Mailbox Transmit Interrupt Flag */
-#define nMBTIF14 0x0
#define MBTIF15 0x8000 /* Mailbox 15 Mailbox Transmit Interrupt Flag */
-#define nMBTIF15 0x0
/* Bit masks for CAN0_MBTIF2 */
#define MBTIF16 0x1 /* Mailbox 16 Mailbox Transmit Interrupt Flag */
-#define nMBTIF16 0x0
#define MBTIF17 0x2 /* Mailbox 17 Mailbox Transmit Interrupt Flag */
-#define nMBTIF17 0x0
#define MBTIF18 0x4 /* Mailbox 18 Mailbox Transmit Interrupt Flag */
-#define nMBTIF18 0x0
#define MBTIF19 0x8 /* Mailbox 19 Mailbox Transmit Interrupt Flag */
-#define nMBTIF19 0x0
#define MBTIF20 0x10 /* Mailbox 20 Mailbox Transmit Interrupt Flag */
-#define nMBTIF20 0x0
#define MBTIF21 0x20 /* Mailbox 21 Mailbox Transmit Interrupt Flag */
-#define nMBTIF21 0x0
#define MBTIF22 0x40 /* Mailbox 22 Mailbox Transmit Interrupt Flag */
-#define nMBTIF22 0x0
#define MBTIF23 0x80 /* Mailbox 23 Mailbox Transmit Interrupt Flag */
-#define nMBTIF23 0x0
#define MBTIF24 0x100 /* Mailbox 24 Mailbox Transmit Interrupt Flag */
-#define nMBTIF24 0x0
#define MBTIF25 0x200 /* Mailbox 25 Mailbox Transmit Interrupt Flag */
-#define nMBTIF25 0x0
#define MBTIF26 0x400 /* Mailbox 26 Mailbox Transmit Interrupt Flag */
-#define nMBTIF26 0x0
#define MBTIF27 0x800 /* Mailbox 27 Mailbox Transmit Interrupt Flag */
-#define nMBTIF27 0x0
#define MBTIF28 0x1000 /* Mailbox 28 Mailbox Transmit Interrupt Flag */
-#define nMBTIF28 0x0
#define MBTIF29 0x2000 /* Mailbox 29 Mailbox Transmit Interrupt Flag */
-#define nMBTIF29 0x0
#define MBTIF30 0x4000 /* Mailbox 30 Mailbox Transmit Interrupt Flag */
-#define nMBTIF30 0x0
#define MBTIF31 0x8000 /* Mailbox 31 Mailbox Transmit Interrupt Flag */
-#define nMBTIF31 0x0
/* Bit masks for CAN0_MBRIF1 */
#define MBRIF0 0x1 /* Mailbox 0 Mailbox Receive Interrupt Flag */
-#define nMBRIF0 0x0
#define MBRIF1 0x2 /* Mailbox 1 Mailbox Receive Interrupt Flag */
-#define nMBRIF1 0x0
#define MBRIF2 0x4 /* Mailbox 2 Mailbox Receive Interrupt Flag */
-#define nMBRIF2 0x0
#define MBRIF3 0x8 /* Mailbox 3 Mailbox Receive Interrupt Flag */
-#define nMBRIF3 0x0
#define MBRIF4 0x10 /* Mailbox 4 Mailbox Receive Interrupt Flag */
-#define nMBRIF4 0x0
#define MBRIF5 0x20 /* Mailbox 5 Mailbox Receive Interrupt Flag */
-#define nMBRIF5 0x0
#define MBRIF6 0x40 /* Mailbox 6 Mailbox Receive Interrupt Flag */
-#define nMBRIF6 0x0
#define MBRIF7 0x80 /* Mailbox 7 Mailbox Receive Interrupt Flag */
-#define nMBRIF7 0x0
#define MBRIF8 0x100 /* Mailbox 8 Mailbox Receive Interrupt Flag */
-#define nMBRIF8 0x0
#define MBRIF9 0x200 /* Mailbox 9 Mailbox Receive Interrupt Flag */
-#define nMBRIF9 0x0
#define MBRIF10 0x400 /* Mailbox 10 Mailbox Receive Interrupt Flag */
-#define nMBRIF10 0x0
#define MBRIF11 0x800 /* Mailbox 11 Mailbox Receive Interrupt Flag */
-#define nMBRIF11 0x0
#define MBRIF12 0x1000 /* Mailbox 12 Mailbox Receive Interrupt Flag */
-#define nMBRIF12 0x0
#define MBRIF13 0x2000 /* Mailbox 13 Mailbox Receive Interrupt Flag */
-#define nMBRIF13 0x0
#define MBRIF14 0x4000 /* Mailbox 14 Mailbox Receive Interrupt Flag */
-#define nMBRIF14 0x0
#define MBRIF15 0x8000 /* Mailbox 15 Mailbox Receive Interrupt Flag */
-#define nMBRIF15 0x0
/* Bit masks for CAN0_MBRIF2 */
#define MBRIF16 0x1 /* Mailbox 16 Mailbox Receive Interrupt Flag */
-#define nMBRIF16 0x0
#define MBRIF17 0x2 /* Mailbox 17 Mailbox Receive Interrupt Flag */
-#define nMBRIF17 0x0
#define MBRIF18 0x4 /* Mailbox 18 Mailbox Receive Interrupt Flag */
-#define nMBRIF18 0x0
#define MBRIF19 0x8 /* Mailbox 19 Mailbox Receive Interrupt Flag */
-#define nMBRIF19 0x0
#define MBRIF20 0x10 /* Mailbox 20 Mailbox Receive Interrupt Flag */
-#define nMBRIF20 0x0
#define MBRIF21 0x20 /* Mailbox 21 Mailbox Receive Interrupt Flag */
-#define nMBRIF21 0x0
#define MBRIF22 0x40 /* Mailbox 22 Mailbox Receive Interrupt Flag */
-#define nMBRIF22 0x0
#define MBRIF23 0x80 /* Mailbox 23 Mailbox Receive Interrupt Flag */
-#define nMBRIF23 0x0
#define MBRIF24 0x100 /* Mailbox 24 Mailbox Receive Interrupt Flag */
-#define nMBRIF24 0x0
#define MBRIF25 0x200 /* Mailbox 25 Mailbox Receive Interrupt Flag */
-#define nMBRIF25 0x0
#define MBRIF26 0x400 /* Mailbox 26 Mailbox Receive Interrupt Flag */
-#define nMBRIF26 0x0
#define MBRIF27 0x800 /* Mailbox 27 Mailbox Receive Interrupt Flag */
-#define nMBRIF27 0x0
#define MBRIF28 0x1000 /* Mailbox 28 Mailbox Receive Interrupt Flag */
-#define nMBRIF28 0x0
#define MBRIF29 0x2000 /* Mailbox 29 Mailbox Receive Interrupt Flag */
-#define nMBRIF29 0x0
#define MBRIF30 0x4000 /* Mailbox 30 Mailbox Receive Interrupt Flag */
-#define nMBRIF30 0x0
#define MBRIF31 0x8000 /* Mailbox 31 Mailbox Receive Interrupt Flag */
-#define nMBRIF31 0x0
/* Bit masks for EPPIx_STATUS */
#define CFIFO_ERR 0x1 /* Chroma FIFO Error */
-#define nCFIFO_ERR 0x0
#define YFIFO_ERR 0x2 /* Luma FIFO Error */
-#define nYFIFO_ERR 0x0
#define LTERR_OVR 0x4 /* Line Track Overflow */
-#define nLTERR_OVR 0x0
#define LTERR_UNDR 0x8 /* Line Track Underflow */
-#define nLTERR_UNDR 0x0
#define FTERR_OVR 0x10 /* Frame Track Overflow */
-#define nFTERR_OVR 0x0
#define FTERR_UNDR 0x20 /* Frame Track Underflow */
-#define nFTERR_UNDR 0x0
#define ERR_NCOR 0x40 /* Preamble Error Not Corrected */
-#define nERR_NCOR 0x0
#define DMA1URQ 0x80 /* DMA1 Urgent Request */
-#define nDMA1URQ 0x0
#define DMA0URQ 0x100 /* DMA0 Urgent Request */
-#define nDMA0URQ 0x0
#define ERR_DET 0x4000 /* Preamble Error Detected */
-#define nERR_DET 0x0
#define FLD 0x8000 /* Field */
-#define nFLD 0x0
/* Bit masks for EPPIx_CONTROL */
#define EPPI_EN 0x1 /* Enable */
-#define nEPPI_EN 0x0
#define EPPI_DIR 0x2 /* Direction */
-#define nEPPI_DIR 0x0
#define XFR_TYPE 0xc /* Operating Mode */
#define FS_CFG 0x30 /* Frame Sync Configuration */
#define FLD_SEL 0x40 /* Field Select/Trigger */
-#define nFLD_SEL 0x0
#define ITU_TYPE 0x80 /* ITU Interlaced or Progressive */
-#define nITU_TYPE 0x0
#define BLANKGEN 0x100 /* ITU Output Mode with Internal Blanking Generation */
-#define nBLANKGEN 0x0
#define ICLKGEN 0x200 /* Internal Clock Generation */
-#define nICLKGEN 0x0
#define IFSGEN 0x400 /* Internal Frame Sync Generation */
-#define nIFSGEN 0x0
#define POLC 0x1800 /* Frame Sync and Data Driving/Sampling Edges */
#define POLS 0x6000 /* Frame Sync Polarity */
#define DLENGTH 0x38000 /* Data Length */
#define SKIP_EN 0x40000 /* Skip Enable */
-#define nSKIP_EN 0x0
#define SKIP_EO 0x80000 /* Skip Even or Odd */
-#define nSKIP_EO 0x0
#define PACKEN 0x100000 /* Packing/Unpacking Enable */
-#define nPACKEN 0x0
#define SWAPEN 0x200000 /* Swap Enable */
-#define nSWAPEN 0x0
#define SIGN_EXT 0x400000 /* Sign Extension or Zero-filled / Data Split Format */
-#define nSIGN_EXT 0x0
#define SPLT_EVEN_ODD 0x800000 /* Split Even and Odd Data Samples */
-#define nSPLT_EVEN_ODD 0x0
#define SUBSPLT_ODD 0x1000000 /* Sub-split Odd Samples */
-#define nSUBSPLT_ODD 0x0
#define DMACFG 0x2000000 /* One or Two DMA Channels Mode */
-#define nDMACFG 0x0
#define RGB_FMT_EN 0x4000000 /* RGB Formatting Enable */
-#define nRGB_FMT_EN 0x0
#define FIFO_RWM 0x18000000 /* FIFO Regular Watermarks */
#define FIFO_UWM 0x60000000 /* FIFO Urgent Watermarks */
+#define DLEN_8 (0 << 15) /* 000 - 8 bits */
+#define DLEN_10 (1 << 15) /* 001 - 10 bits */
+#define DLEN_12 (2 << 15) /* 010 - 12 bits */
+#define DLEN_14 (3 << 15) /* 011 - 14 bits */
+#define DLEN_16 (4 << 15) /* 100 - 16 bits */
+#define DLEN_18 (5 << 15) /* 101 - 18 bits */
+#define DLEN_24 (6 << 15) /* 110 - 24 bits */
+
+
/* Bit masks for EPPIx_FS2W_LVB */
#define F1VB_BD 0xff /* Vertical Blanking before Field 1 Active Data */
@@ -3951,60 +3085,36 @@
/* Bit masks for SPIx_CTL */
#define SPE 0x4000 /* SPI Enable */
-#define nSPE 0x0
#define WOM 0x2000 /* Write Open Drain Master */
-#define nWOM 0x0
#define MSTR 0x1000 /* Master Mode */
-#define nMSTR 0x0
#define CPOL 0x800 /* Clock Polarity */
-#define nCPOL 0x0
#define CPHA 0x400 /* Clock Phase */
-#define nCPHA 0x0
#define LSBF 0x200 /* LSB First */
-#define nLSBF 0x0
#define SIZE 0x100 /* Size of Words */
-#define nSIZE 0x0
#define EMISO 0x20 /* Enable MISO Output */
-#define nEMISO 0x0
#define PSSE 0x10 /* Slave-Select Enable */
-#define nPSSE 0x0
#define GM 0x8 /* Get More Data */
-#define nGM 0x0
#define SZ 0x4 /* Send Zero */
-#define nSZ 0x0
#define TIMOD 0x3 /* Transfer Initiation Mode */
/* Bit masks for SPIx_FLG */
#define FLS1 0x2 /* Slave Select Enable 1 */
-#define nFLS1 0x0
#define FLS2 0x4 /* Slave Select Enable 2 */
-#define nFLS2 0x0
#define FLS3 0x8 /* Slave Select Enable 3 */
-#define nFLS3 0x0
#define FLG1 0x200 /* Slave Select Value 1 */
-#define nFLG1 0x0
#define FLG2 0x400 /* Slave Select Value 2 */
-#define nFLG2 0x0
#define FLG3 0x800 /* Slave Select Value 3 */
-#define nFLG3 0x0
/* Bit masks for SPIx_STAT */
#define TXCOL 0x40 /* Transmit Collision Error */
-#define nTXCOL 0x0
#define RXS 0x20 /* RDBR Data Buffer Status */
-#define nRXS 0x0
#define RBSY 0x10 /* Receive Error */
-#define nRBSY 0x0
#define TXS 0x8 /* TDBR Data Buffer Status */
-#define nTXS 0x0
#define TXE 0x4 /* Transmission Error */
-#define nTXE 0x0
#define MODF 0x2 /* Mode Fault Error */
-#define nMODF 0x0
#define SPIF 0x1 /* SPI Finished */
-#define nSPIF 0x0
/* Bit masks for SPIx_TDBR */
@@ -4028,9 +3138,7 @@
#define PRESCALE 0x7f /* Prescale Value */
#define TWI_ENA 0x80 /* TWI Enable */
-#define nTWI_ENA 0x0
#define SCCB 0x200 /* Serial Camera Control Bus */
-#define nSCCB 0x0
/* Bit maskes for TWIx_CLKDIV */
@@ -4040,13 +3148,9 @@
/* Bit maskes for TWIx_SLAVE_CTL */
#define SEN 0x1 /* Slave Enable */
-#define nSEN 0x0
#define STDVAL 0x4 /* Slave Transmit Data Valid */
-#define nSTDVAL 0x0
#define NAK 0x8 /* Not Acknowledge */
-#define nNAK 0x0
#define GEN 0x10 /* General Call Enable */
-#define nGEN 0x0
/* Bit maskes for TWIx_SLAVE_ADDR */
@@ -4055,27 +3159,18 @@
/* Bit maskes for TWIx_SLAVE_STAT */
#define SDIR 0x1 /* Slave Transfer Direction */
-#define nSDIR 0x0
#define GCALL 0x2 /* General Call */
-#define nGCALL 0x0
/* Bit maskes for TWIx_MASTER_CTL */
#define MEN 0x1 /* Master Mode Enable */
-#define nMEN 0x0
#define MDIR 0x4 /* Master Transfer Direction */
-#define nMDIR 0x0
#define FAST 0x8 /* Fast Mode */
-#define nFAST 0x0
#define STOP 0x10 /* Issue Stop Condition */
-#define nSTOP 0x0
#define RSTART 0x20 /* Repeat Start */
-#define nRSTART 0x0
#define DCNT 0x3fc0 /* Data Transfer Count */
#define SDAOVR 0x4000 /* Serial Data Override */
-#define nSDAOVR 0x0
#define SCLOVR 0x8000 /* Serial Clock Override */
-#define nSCLOVR 0x0
/* Bit maskes for TWIx_MASTER_ADDR */
@@ -4084,34 +3179,21 @@
/* Bit maskes for TWIx_MASTER_STAT */
#define MPROG 0x1 /* Master Transfer in Progress */
-#define nMPROG 0x0
#define LOSTARB 0x2 /* Lost Arbitration */
-#define nLOSTARB 0x0
#define ANAK 0x4 /* Address Not Acknowledged */
-#define nANAK 0x0
#define DNAK 0x8 /* Data Not Acknowledged */
-#define nDNAK 0x0
#define BUFRDERR 0x10 /* Buffer Read Error */
-#define nBUFRDERR 0x0
#define BUFWRERR 0x20 /* Buffer Write Error */
-#define nBUFWRERR 0x0
#define SDASEN 0x40 /* Serial Data Sense */
-#define nSDASEN 0x0
#define SCLSEN 0x80 /* Serial Clock Sense */
-#define nSCLSEN 0x0
#define BUSBUSY 0x100 /* Bus Busy */
-#define nBUSBUSY 0x0
/* Bit maskes for TWIx_FIFO_CTL */
#define XMTFLUSH 0x1 /* Transmit Buffer Flush */
-#define nXMTFLUSH 0x0
#define RCVFLUSH 0x2 /* Receive Buffer Flush */
-#define nRCVFLUSH 0x0
#define XMTINTLEN 0x4 /* Transmit Buffer Interrupt Length */
-#define nXMTINTLEN 0x0
#define RCVINTLEN 0x8 /* Receive Buffer Interrupt Length */
-#define nRCVINTLEN 0x0
/* Bit maskes for TWIx_FIFO_STAT */
@@ -4121,40 +3203,24 @@
/* Bit maskes for TWIx_INT_MASK */
#define SINITM 0x1 /* Slave Transfer Initiated Interrupt Mask */
-#define nSINITM 0x0
#define SCOMPM 0x2 /* Slave Transfer Complete Interrupt Mask */
-#define nSCOMPM 0x0
#define SERRM 0x4 /* Slave Transfer Error Interrupt Mask */
-#define nSERRM 0x0
#define SOVFM 0x8 /* Slave Overflow Interrupt Mask */
-#define nSOVFM 0x0
#define MCOMPM 0x10 /* Master Transfer Complete Interrupt Mask */
-#define nMCOMPM 0x0
#define MERRM 0x20 /* Master Transfer Error Interrupt Mask */
-#define nMERRM 0x0
#define XMTSERVM 0x40 /* Transmit FIFO Service Interrupt Mask */
-#define nXMTSERVM 0x0
#define RCVSERVM 0x80 /* Receive FIFO Service Interrupt Mask */
-#define nRCVSERVM 0x0
/* Bit maskes for TWIx_INT_STAT */
#define SINIT 0x1 /* Slave Transfer Initiated */
-#define nSINIT 0x0
#define SCOMP 0x2 /* Slave Transfer Complete */
-#define nSCOMP 0x0
#define SERR 0x4 /* Slave Transfer Error */
-#define nSERR 0x0
#define SOVF 0x8 /* Slave Overflow */
-#define nSOVF 0x0
#define MCOMP 0x10 /* Master Transfer Complete */
-#define nMCOMP 0x0
#define MERR 0x20 /* Master Transfer Error */
-#define nMERR 0x0
#define XMTSERV 0x40 /* Transmit FIFO Service */
-#define nXMTSERV 0x0
#define RCVSERV 0x80 /* Receive FIFO Service */
-#define nRCVSERV 0x0
/* Bit maskes for TWIx_XMT_DATA8 */
@@ -4175,81 +3241,51 @@
/* Bit masks for SPORTx_TCR1 */
#define TCKFE 0x4000 /* Clock Falling Edge Select */
-#define nTCKFE 0x0
#define LATFS 0x2000 /* Late Transmit Frame Sync */
-#define nLATFS 0x0
#define LTFS 0x1000 /* Low Transmit Frame Sync Select */
-#define nLTFS 0x0
#define DITFS 0x800 /* Data-Independent Transmit Frame Sync Select */
-#define nDITFS 0x0
#define TFSR 0x400 /* Transmit Frame Sync Required Select */
-#define nTFSR 0x0
#define ITFS 0x200 /* Internal Transmit Frame Sync Select */
-#define nITFS 0x0
#define TLSBIT 0x10 /* Transmit Bit Order */
-#define nTLSBIT 0x0
#define TDTYPE 0xc /* Data Formatting Type Select */
#define ITCLK 0x2 /* Internal Transmit Clock Select */
-#define nITCLK 0x0
#define TSPEN 0x1 /* Transmit Enable */
-#define nTSPEN 0x0
/* Bit masks for SPORTx_TCR2 */
#define TRFST 0x400 /* Left/Right Order */
-#define nTRFST 0x0
#define TSFSE 0x200 /* Transmit Stereo Frame Sync Enable */
-#define nTSFSE 0x0
#define TXSE 0x100 /* TxSEC Enable */
-#define nTXSE 0x0
#define SLEN_T 0x1f /* SPORT Word Length */
/* Bit masks for SPORTx_RCR1 */
#define RCKFE 0x4000 /* Clock Falling Edge Select */
-#define nRCKFE 0x0
#define LARFS 0x2000 /* Late Receive Frame Sync */
-#define nLARFS 0x0
#define LRFS 0x1000 /* Low Receive Frame Sync Select */
-#define nLRFS 0x0
#define RFSR 0x400 /* Receive Frame Sync Required Select */
-#define nRFSR 0x0
#define IRFS 0x200 /* Internal Receive Frame Sync Select */
-#define nIRFS 0x0
#define RLSBIT 0x10 /* Receive Bit Order */
-#define nRLSBIT 0x0
#define RDTYPE 0xc /* Data Formatting Type Select */
#define IRCLK 0x2 /* Internal Receive Clock Select */
-#define nIRCLK 0x0
#define RSPEN 0x1 /* Receive Enable */
-#define nRSPEN 0x0
/* Bit masks for SPORTx_RCR2 */
#define RRFST 0x400 /* Left/Right Order */
-#define nRRFST 0x0
#define RSFSE 0x200 /* Receive Stereo Frame Sync Enable */
-#define nRSFSE 0x0
#define RXSE 0x100 /* RxSEC Enable */
-#define nRXSE 0x0
#define SLEN_R 0x1f /* SPORT Word Length */
/* Bit masks for SPORTx_STAT */
#define TXHRE 0x40 /* Transmit Hold Register Empty */
-#define nTXHRE 0x0
#define TOVF 0x20 /* Sticky Transmit Overflow Status */
-#define nTOVF 0x0
#define TUVF 0x10 /* Sticky Transmit Underflow Status */
-#define nTUVF 0x0
#define TXF 0x8 /* Transmit FIFO Full Status */
-#define nTXF 0x0
#define ROVF 0x4 /* Sticky Receive Overflow Status */
-#define nROVF 0x0
#define RUVF 0x2 /* Sticky Receive Underflow Status */
-#define nRUVF 0x0
#define RXNE 0x1 /* Receive FIFO Not Empty Status */
-#define nRXNE 0x0
/* Bit masks for SPORTx_MCMC1 */
@@ -4260,13 +3296,9 @@
#define MFD 0xf000 /* Multi channel Frame Delay */
#define FSDR 0x80 /* Frame Sync to Data Relationship */
-#define nFSDR 0x0
#define MCMEM 0x10 /* Multi channel Frame Mode Enable */
-#define nMCMEM 0x0
#define MCDRXPE 0x8 /* Multi channel DMA Receive Packing */
-#define nMCDRXPE 0x0
#define MCDTXPE 0x4 /* Multi channel DMA Transmit Packing */
-#define nMCDTXPE 0x0
#define MCCRM 0x3 /* 2X Clock Recovery Mode */
/* Bit masks for SPORTx_CHNL */
@@ -4280,115 +3312,59 @@
#define WLS 0x3 /* Word Length Select */
#endif
#define STB 0x4 /* Stop Bits */
-#define nSTB 0x0
#define PEN 0x8 /* Parity Enable */
-#define nPEN 0x0
#define EPS 0x10 /* Even Parity Select */
-#define nEPS 0x0
#define STP 0x20 /* Sticky Parity */
-#define nSTP 0x0
#define SB 0x40 /* Set Break */
-#define nSB 0x0
/* Bit masks for UARTx_MCR */
#define XOFF 0x1 /* Transmitter Off */
-#define nXOFF 0x0
#define MRTS 0x2 /* Manual Request To Send */
-#define nMRTS 0x0
#define RFIT 0x4 /* Receive FIFO IRQ Threshold */
-#define nRFIT 0x0
#define RFRT 0x8 /* Receive FIFO RTS Threshold */
-#define nRFRT 0x0
#define LOOP_ENA 0x10 /* Loopback Mode Enable */
-#define nLOOP_ENA 0x0
#define FCPOL 0x20 /* Flow Control Pin Polarity */
-#define nFCPOL 0x0
#define ARTS 0x40 /* Automatic Request To Send */
-#define nARTS 0x0
#define ACTS 0x80 /* Automatic Clear To Send */
-#define nACTS 0x0
/* Bit masks for UARTx_LSR */
#define DR 0x1 /* Data Ready */
-#define nDR 0x0
#define OE 0x2 /* Overrun Error */
-#define nOE 0x0
#define PE 0x4 /* Parity Error */
-#define nPE 0x0
#define FE 0x8 /* Framing Error */
-#define nFE 0x0
#define BI 0x10 /* Break Interrupt */
-#define nBI 0x0
#define THRE 0x20 /* THR Empty */
-#define nTHRE 0x0
#define TEMT 0x40 /* Transmitter Empty */
-#define nTEMT 0x0
#define TFI 0x80 /* Transmission Finished Indicator */
-#define nTFI 0x0
/* Bit masks for UARTx_MSR */
#define SCTS 0x1 /* Sticky CTS */
-#define nSCTS 0x0
#define CTS 0x10 /* Clear To Send */
-#define nCTS 0x0
#define RFCS 0x20 /* Receive FIFO Count Status */
-#define nRFCS 0x0
-
-/* Bit masks for UARTx_IER_SET */
-
-#define ERBFI_S 0x1 /* Enable Receive Buffer Full Interrupt */
-#define nERBFI_S 0x0
-#define ETBEI_S 0x2 /* Enable Transmit Buffer Empty Interrupt */
-#define nETBEI_S 0x0
-#define ELSI_S 0x4 /* Enable Receive Status Interrupt */
-#define nELSI_S 0x0
-#define EDSSI_S 0x8 /* Enable Modem Status Interrupt */
-#define nEDSSI_S 0x0
-#define EDTPTI_S 0x10 /* Enable DMA Transmit PIRQ Interrupt */
-#define nEDTPTI_S 0x0
-#define ETFI_S 0x20 /* Enable Transmission Finished Interrupt */
-#define nETFI_S 0x0
-#define ERFCI_S 0x40 /* Enable Receive FIFO Count Interrupt */
-#define nERFCI_S 0x0
-
-/* Bit masks for UARTx_IER_CLEAR */
-
-#define ERBFI_C 0x1 /* Enable Receive Buffer Full Interrupt */
-#define nERBFI_C 0x0
-#define ETBEI_C 0x2 /* Enable Transmit Buffer Empty Interrupt */
-#define nETBEI_C 0x0
-#define ELSI_C 0x4 /* Enable Receive Status Interrupt */
-#define nELSI_C 0x0
-#define EDSSI_C 0x8 /* Enable Modem Status Interrupt */
-#define nEDSSI_C 0x0
-#define EDTPTI_C 0x10 /* Enable DMA Transmit PIRQ Interrupt */
-#define nEDTPTI_C 0x0
-#define ETFI_C 0x20 /* Enable Transmission Finished Interrupt */
-#define nETFI_C 0x0
-#define ERFCI_C 0x40 /* Enable Receive FIFO Count Interrupt */
-#define nERFCI_C 0x0
+
+/* Bit masks for UARTx_IER_SET & UARTx_IER_CLEAR */
+
+#define ERBFI 0x1 /* Enable Receive Buffer Full Interrupt */
+#define ETBEI 0x2 /* Enable Transmit Buffer Empty Interrupt */
+#define ELSI 0x4 /* Enable Receive Status Interrupt */
+#define EDSSI 0x8 /* Enable Modem Status Interrupt */
+#define EDTPTI 0x10 /* Enable DMA Transmit PIRQ Interrupt */
+#define ETFI 0x20 /* Enable Transmission Finished Interrupt */
+#define ERFCI 0x40 /* Enable Receive FIFO Count Interrupt */
/* Bit masks for UARTx_GCTL */
#define UCEN 0x1 /* UART Enable */
-#define nUCEN 0x0
#define IREN 0x2 /* IrDA Mode Enable */
-#define nIREN 0x0
#define TPOLC 0x4 /* IrDA TX Polarity Change */
-#define nTPOLC 0x0
#define RPOLC 0x8 /* IrDA RX Polarity Change */
-#define nRPOLC 0x0
#define FPE 0x10 /* Force Parity Error */
-#define nFPE 0x0
#define FFE 0x20 /* Force Framing Error */
-#define nFFE 0x0
#define EDBO 0x40 /* Enable Divide-by-One */
-#define nEDBO 0x0
#define EGLSI 0x80 /* Enable Global LS Interrupt */
-#define nEGLSI 0x0
/* ******************************************* */
@@ -4398,32 +3374,32 @@
/* BCODE bit field options (SYSCFG register) */
#define BCODE_WAKEUP 0x0000 /* boot according to wake-up condition */
-#define BCODE_FULLBOOT 0x0010 /* always perform full boot */
+#define BCODE_FULLBOOT 0x0010 /* always perform full boot */
#define BCODE_QUICKBOOT 0x0020 /* always perform quick boot */
#define BCODE_NOBOOT 0x0030 /* always perform full boot */
/* CNT_COMMAND bit field options */
-
+
#define W1LCNT_ZERO 0x0001 /* write 1 to load CNT_COUNTER with zero */
#define W1LCNT_MIN 0x0004 /* write 1 to load CNT_COUNTER from CNT_MIN */
#define W1LCNT_MAX 0x0008 /* write 1 to load CNT_COUNTER from CNT_MAX */
-
+
#define W1LMIN_ZERO 0x0010 /* write 1 to load CNT_MIN with zero */
#define W1LMIN_CNT 0x0020 /* write 1 to load CNT_MIN from CNT_COUNTER */
#define W1LMIN_MAX 0x0080 /* write 1 to load CNT_MIN from CNT_MAX */
-
+
#define W1LMAX_ZERO 0x0100 /* write 1 to load CNT_MAX with zero */
#define W1LMAX_CNT 0x0200 /* write 1 to load CNT_MAX from CNT_COUNTER */
#define W1LMAX_MIN 0x0400 /* write 1 to load CNT_MAX from CNT_MIN */
-
+
/* CNT_CONFIG bit field options */
-
+
#define CNTMODE_QUADENC 0x0000 /* quadrature encoder mode */
#define CNTMODE_BINENC 0x0100 /* binary encoder mode */
#define CNTMODE_UDCNT 0x0200 /* up/down counter mode */
#define CNTMODE_DIRCNT 0x0400 /* direction counter mode */
#define CNTMODE_DIRTMR 0x0500 /* direction timer mode */
-
+
#define BNDMODE_COMP 0x0000 /* boundary compare mode */
#define BNDMODE_ZERO 0x1000 /* boundary compare and zero mode */
#define BNDMODE_CAPT 0x2000 /* boundary capture mode */
@@ -4436,7 +3412,7 @@
#define EXT_CLK 0x0003
/* UARTx_LCR bit field options */
-
+
#define WLS_5 0x0000 /* 5 data bits */
#define WLS_6 0x0001 /* 6 data bits */
#define WLS_7 0x0002 /* 7 data bits */
@@ -4484,7 +3460,7 @@
#define PIQ30 0x40000000
#define PIQ31 0x80000000
-/* PORT A Bit Definitions for the registers
+/* PORT A Bit Definitions for the registers
PORTA, PORTA_SET, PORTA_CLEAR,
PORTA_DIR_SET, PORTA_DIR_CLEAR, PORTA_INEN,
PORTA_FER registers
@@ -4507,7 +3483,7 @@ PORTA_FER registers
#define PA14 0x4000
#define PA15 0x8000
-/* PORT B Bit Definitions for the registers
+/* PORT B Bit Definitions for the registers
PORTB, PORTB_SET, PORTB_CLEAR,
PORTB_DIR_SET, PORTB_DIR_CLEAR, PORTB_INEN,
PORTB_FER registers
@@ -4530,7 +3506,7 @@ PORTB_FER registers
#define PB14 0x4000
-/* PORT C Bit Definitions for the registers
+/* PORT C Bit Definitions for the registers
PORTC, PORTC_SET, PORTC_CLEAR,
PORTC_DIR_SET, PORTC_DIR_CLEAR, PORTC_INEN,
PORTC_FER registers
@@ -4553,7 +3529,7 @@ PORTC_FER registers
#define PC13 0x2000
-/* PORT D Bit Definitions for the registers
+/* PORT D Bit Definitions for the registers
PORTD, PORTD_SET, PORTD_CLEAR,
PORTD_DIR_SET, PORTD_DIR_CLEAR, PORTD_INEN,
PORTD_FER registers
@@ -4576,7 +3552,7 @@ PORTD_FER registers
#define PD14 0x4000
#define PD15 0x8000
-/* PORT E Bit Definitions for the registers
+/* PORT E Bit Definitions for the registers
PORTE, PORTE_SET, PORTE_CLEAR,
PORTE_DIR_SET, PORTE_DIR_CLEAR, PORTE_INEN,
PORTE_FER registers
@@ -4600,7 +3576,7 @@ PORTE_FER registers
#define PE14 0x4000
#define PE15 0x8000
-/* PORT F Bit Definitions for the registers
+/* PORT F Bit Definitions for the registers
PORTF, PORTF_SET, PORTF_CLEAR,
PORTF_DIR_SET, PORTF_DIR_CLEAR, PORTF_INEN,
PORTF_FER registers
@@ -4624,7 +3600,7 @@ PORTF_FER registers
#define PF14 0x4000
#define PF15 0x8000
-/* PORT G Bit Definitions for the registers
+/* PORT G Bit Definitions for the registers
PORTG, PORTG_SET, PORTG_CLEAR,
PORTG_DIR_SET, PORTG_DIR_CLEAR, PORTG_INEN,
PORTG_FER registers
@@ -4648,7 +3624,7 @@ PORTG_FER registers
#define PG14 0x4000
#define PG15 0x8000
-/* PORT H Bit Definitions for the registers
+/* PORT H Bit Definitions for the registers
PORTH, PORTH_SET, PORTH_CLEAR,
PORTH_DIR_SET, PORTH_DIR_CLEAR, PORTH_INEN,
PORTH_FER registers
@@ -4671,7 +3647,7 @@ PORTH_FER registers
#define PH13 0x2000
-/* PORT I Bit Definitions for the registers
+/* PORT I Bit Definitions for the registers
PORTI, PORTI_SET, PORTI_CLEAR,
PORTI_DIR_SET, PORTI_DIR_CLEAR, PORTI_INEN,
PORTI_FER registers
@@ -4695,7 +3671,7 @@ PORTI_FER registers
#define PI14 0x4000
#define PI15 0x8000
-/* PORT J Bit Definitions for the registers
+/* PORT J Bit Definitions for the registers
PORTJ, PORTJ_SET, PORTJ_CLEAR,
PORTJ_DIR_SET, PORTJ_DIR_CLEAR, PORTJ_INEN,
PORTJ_FER registers
@@ -4716,7 +3692,7 @@ PORTJ_FER registers
#define PJ11 0x0800
#define PJ12 0x1000
#define PJ13 0x2000
-
+
/* Port Muxing Bit Fields for PORTx_MUX Registers */
@@ -4860,7 +3836,7 @@ PORTJ_FER registers
#define B0MAP_PIL 0x00000006 /* Map Port I Low to Byte 0 */
#define B0MAP_PJL 0x00000007 /* Map Port J Low to Byte 0 */
-#define B1MAP_PCH 0x00000000 /* Map Port C High to Byte 1 */
+#define B1MAP_PCH 0x00000000 /* Map Port C High to Byte 1 */
#define B1MAP_PDH 0x00000100 /* Map Port D High to Byte 1 */
#define B1MAP_PEH 0x00000200 /* Map Port E High to Byte 1 */
#define B1MAP_PFH 0x00000300 /* Map Port F High to Byte 1 */
@@ -4869,27 +3845,27 @@ PORTJ_FER registers
#define B1MAP_PIH 0x00000600 /* Map Port I High to Byte 1 */
#define B1MAP_PJH 0x00000700 /* Map Port J High to Byte 1 */
-#define B2MAP_PCL 0x00000000 /* Map Port C Low to Byte 2 */
-#define B2MAP_PDL 0x00010000 /* Map Port D Low to Byte 2 */
-#define B2MAP_PEL 0x00020000 /* Map Port E Low to Byte 2 */
-#define B2MAP_PFL 0x00030000 /* Map Port F Low to Byte 2 */
-#define B2MAP_PGL 0x00040000 /* Map Port G Low to Byte 2 */
-#define B2MAP_PHL 0x00050000 /* Map Port H Low to Byte 2 */
-#define B2MAP_PIL 0x00060000 /* Map Port I Low to Byte 2 */
-#define B2MAP_PJL 0x00070000 /* Map Port J Low to Byte 2 */
-
-#define B3MAP_PCH 0x00000000 /* Map Port C High to Byte 3 */
-#define B3MAP_PDH 0x01000000 /* Map Port D High to Byte 3 */
-#define B3MAP_PEH 0x02000000 /* Map Port E High to Byte 3 */
-#define B3MAP_PFH 0x03000000 /* Map Port F High to Byte 3 */
-#define B3MAP_PGH 0x04000000 /* Map Port G High to Byte 3 */
-#define B3MAP_PHH 0x05000000 /* Map Port H High to Byte 3 */
-#define B3MAP_PIH 0x06000000 /* Map Port I High to Byte 3 */
-#define B3MAP_PJH 0x07000000 /* Map Port J High to Byte 3 */
+#define B2MAP_PCL 0x00000000 /* Map Port C Low to Byte 2 */
+#define B2MAP_PDL 0x00010000 /* Map Port D Low to Byte 2 */
+#define B2MAP_PEL 0x00020000 /* Map Port E Low to Byte 2 */
+#define B2MAP_PFL 0x00030000 /* Map Port F Low to Byte 2 */
+#define B2MAP_PGL 0x00040000 /* Map Port G Low to Byte 2 */
+#define B2MAP_PHL 0x00050000 /* Map Port H Low to Byte 2 */
+#define B2MAP_PIL 0x00060000 /* Map Port I Low to Byte 2 */
+#define B2MAP_PJL 0x00070000 /* Map Port J Low to Byte 2 */
+
+#define B3MAP_PCH 0x00000000 /* Map Port C High to Byte 3 */
+#define B3MAP_PDH 0x01000000 /* Map Port D High to Byte 3 */
+#define B3MAP_PEH 0x02000000 /* Map Port E High to Byte 3 */
+#define B3MAP_PFH 0x03000000 /* Map Port F High to Byte 3 */
+#define B3MAP_PGH 0x04000000 /* Map Port G High to Byte 3 */
+#define B3MAP_PHH 0x05000000 /* Map Port H High to Byte 3 */
+#define B3MAP_PIH 0x06000000 /* Map Port I High to Byte 3 */
+#define B3MAP_PJH 0x07000000 /* Map Port J High to Byte 3 */
/* for legacy compatibility */
-
+
#define WLS(x) (((x)-5) & 0x03) /* Word Length Select */
#define W1LMAX_MAX W1LMAX_MIN
#define EBIU_AMCBCTL0 EBIU_AMBCTL0
diff --git a/include/asm-blackfin/mach-bf548/dma.h b/include/asm-blackfin/mach-bf548/dma.h
new file mode 100644
index 00000000000..fcc8b4c34c6
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/dma.h
@@ -0,0 +1,73 @@
+/*
+ * file: include/asm-blackfin/mach-bf548/dma.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ * system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.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, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose. see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MACH_DMA_H_
+#define _MACH_DMA_H_
+
+#define CH_SPORT0_RX 0
+#define CH_SPORT0_TX 1
+#define CH_SPORT1_RX 2
+#define CH_SPORT1_TX 3
+#define CH_SPI0 4
+#define CH_SPI1 5
+#define CH_UART0_RX 6
+#define CH_UART0_TX 7
+#define CH_UART1_RX 8
+#define CH_UART1_TX 9
+#define CH_ATAPI_RX 10
+#define CH_ATAPI_TX 11
+#define CH_EPPI0 12
+#define CH_EPPI1 13
+#define CH_EPPI2 14
+#define CH_PIXC_IMAGE 15
+#define CH_PIXC_OVERLAY 16
+#define CH_PIXC_OUTPUT 17
+#define CH_SPORT2_RX 18
+#define CH_SPORT2_TX 19
+#define CH_SPORT3_RX 20
+#define CH_SPORT3_TX 21
+#define CH_SDH 22
+#define CH_SPI2 23
+
+#define CH_MEM_STREAM0_DEST 24
+#define CH_MEM_STREAM0_SRC 25
+#define CH_MEM_STREAM1_DEST 26
+#define CH_MEM_STREAM1_SRC 27
+#define CH_MEM_STREAM2_DEST 28
+#define CH_MEM_STREAM2_SRC 29
+#define CH_MEM_STREAM3_DEST 30
+#define CH_MEM_STREAM3_SRC 31
+
+#define MAX_BLACKFIN_DMA_CHANNEL 32
+
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+#endif
diff --git a/include/asm-blackfin/mach-bf548/gpio.h b/include/asm-blackfin/mach-bf548/gpio.h
new file mode 100644
index 00000000000..dbf66bcabe3
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/gpio.h
@@ -0,0 +1,216 @@
+/*
+ * File: include/asm-blackfin/mach-bf548/gpio.h
+ * Based on:
+ * Author: Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2004-2007 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+
+#define GPIO_PA0 0
+#define GPIO_PA1 1
+#define GPIO_PA2 2
+#define GPIO_PA3 3
+#define GPIO_PA4 4
+#define GPIO_PA5 5
+#define GPIO_PA6 6
+#define GPIO_PA7 7
+#define GPIO_PA8 8
+#define GPIO_PA9 9
+#define GPIO_PA10 10
+#define GPIO_PA11 11
+#define GPIO_PA12 12
+#define GPIO_PA13 13
+#define GPIO_PA14 14
+#define GPIO_PA15 15
+#define GPIO_PB0 16
+#define GPIO_PB1 17
+#define GPIO_PB2 18
+#define GPIO_PB3 19
+#define GPIO_PB4 20
+#define GPIO_PB5 21
+#define GPIO_PB6 22
+#define GPIO_PB7 23
+#define GPIO_PB8 24
+#define GPIO_PB9 25
+#define GPIO_PB10 26
+#define GPIO_PB11 27
+#define GPIO_PB12 28
+#define GPIO_PB13 29
+#define GPIO_PB14 30
+#define GPIO_PB15 31 /* N/A */
+#define GPIO_PC0 32
+#define GPIO_PC1 33
+#define GPIO_PC2 34
+#define GPIO_PC3 35
+#define GPIO_PC4 36
+#define GPIO_PC5 37
+#define GPIO_PC6 38
+#define GPIO_PC7 39
+#define GPIO_PC8 40
+#define GPIO_PC9 41
+#define GPIO_PC10 42
+#define GPIO_PC11 43
+#define GPIO_PC12 44
+#define GPIO_PC13 45
+#define GPIO_PC14 46 /* N/A */
+#define GPIO_PC15 47 /* N/A */
+#define GPIO_PD0 48
+#define GPIO_PD1 49
+#define GPIO_PD2 50
+#define GPIO_PD3 51
+#define GPIO_PD4 52
+#define GPIO_PD5 53
+#define GPIO_PD6 54
+#define GPIO_PD7 55
+#define GPIO_PD8 56
+#define GPIO_PD9 57
+#define GPIO_PD10 58
+#define GPIO_PD11 59
+#define GPIO_PD12 60
+#define GPIO_PD13 61
+#define GPIO_PD14 62
+#define GPIO_PD15 63
+#define GPIO_PE0 64
+#define GPIO_PE1 65
+#define GPIO_PE2 66
+#define GPIO_PE3 67
+#define GPIO_PE4 68
+#define GPIO_PE5 69
+#define GPIO_PE6 70
+#define GPIO_PE7 71
+#define GPIO_PE8 72
+#define GPIO_PE9 73
+#define GPIO_PE10 74
+#define GPIO_PE11 75
+#define GPIO_PE12 76
+#define GPIO_PE13 77
+#define GPIO_PE14 78
+#define GPIO_PE15 79
+#define GPIO_PF0 80
+#define GPIO_PF1 81
+#define GPIO_PF2 82
+#define GPIO_PF3 83
+#define GPIO_PF4 84
+#define GPIO_PF5 85
+#define GPIO_PF6 86
+#define GPIO_PF7 87
+#define GPIO_PF8 88
+#define GPIO_PF9 89
+#define GPIO_PF10 90
+#define GPIO_PF11 91
+#define GPIO_PF12 92
+#define GPIO_PF13 93
+#define GPIO_PF14 94
+#define GPIO_PF15 95
+#define GPIO_PG0 96
+#define GPIO_PG1 97
+#define GPIO_PG2 98
+#define GPIO_PG3 99
+#define GPIO_PG4 100
+#define GPIO_PG5 101
+#define GPIO_PG6 102
+#define GPIO_PG7 103
+#define GPIO_PG8 104
+#define GPIO_PG9 105
+#define GPIO_PG10 106
+#define GPIO_PG11 107
+#define GPIO_PG12 108
+#define GPIO_PG13 109
+#define GPIO_PG14 110
+#define GPIO_PG15 111
+#define GPIO_PH0 112
+#define GPIO_PH1 113
+#define GPIO_PH2 114
+#define GPIO_PH3 115
+#define GPIO_PH4 116
+#define GPIO_PH5 117
+#define GPIO_PH6 118
+#define GPIO_PH7 119
+#define GPIO_PH8 120
+#define GPIO_PH9 121
+#define GPIO_PH10 122
+#define GPIO_PH11 123
+#define GPIO_PH12 124
+#define GPIO_PH13 125
+#define GPIO_PH14 126 /* N/A */
+#define GPIO_PH15 127 /* N/A */
+#define GPIO_PI0 128
+#define GPIO_PI1 129
+#define GPIO_PI2 130
+#define GPIO_PI3 131
+#define GPIO_PI4 132
+#define GPIO_PI5 133
+#define GPIO_PI6 134
+#define GPIO_PI7 135
+#define GPIO_PI8 136
+#define GPIO_PI9 137
+#define GPIO_PI10 138
+#define GPIO_PI11 139
+#define GPIO_PI12 140
+#define GPIO_PI13 141
+#define GPIO_PI14 142
+#define GPIO_PI15 143
+#define GPIO_PJ0 144
+#define GPIO_PJ1 145
+#define GPIO_PJ2 146
+#define GPIO_PJ3 147
+#define GPIO_PJ4 148
+#define GPIO_PJ5 149
+#define GPIO_PJ6 150
+#define GPIO_PJ7 151
+#define GPIO_PJ8 152
+#define GPIO_PJ9 153
+#define GPIO_PJ10 154
+#define GPIO_PJ11 155
+#define GPIO_PJ12 156
+#define GPIO_PJ13 157
+#define GPIO_PJ14 158 /* N/A */
+#define GPIO_PJ15 159 /* N/A */
+
+#define MAX_BLACKFIN_GPIOS 160
+
+struct gpio_port_t {
+ unsigned short port_fer;
+ unsigned short dummy1;
+ unsigned short port_data;
+ unsigned short dummy2;
+ unsigned short port_set;
+ unsigned short dummy3;
+ unsigned short port_clear;
+ unsigned short dummy4;
+ unsigned short port_dir_set;
+ unsigned short dummy5;
+ unsigned short port_dir_clear;
+ unsigned short dummy6;
+ unsigned short port_inen;
+ unsigned short dummy7;
+ unsigned int port_mux;
+};
+
+int gpio_request(unsigned short gpio, const char *label);
+void peripheral_free(unsigned short per);
+int peripheral_request_list(unsigned short per[], const char *label);
+void peripheral_free_list(unsigned short per[]);
diff --git a/include/asm-blackfin/mach-bf548/irq.h b/include/asm-blackfin/mach-bf548/irq.h
new file mode 100644
index 00000000000..0b3325bb1ff
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/irq.h
@@ -0,0 +1,467 @@
+/*
+ * file: include/asm-blackfin/mach-bf548/irq.h
+ * based on: include/asm-blackfin/mach-bf537/irq.h
+ * author: Roy Huang (roy.huang@analog.com)
+ *
+ * created:
+ * description:
+ * system mmr register map
+ * rev:
+ *
+ * modified:
+ *
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.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, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose. see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _BF548_IRQ_H_
+#define _BF548_IRQ_H_
+
+/*
+ * Interrupt source definitions
+ Event Source Core Event Name
+Core Emulation **
+Events (highest priority) EMU 0
+ Reset RST 1
+ NMI NMI 2
+ Exception EVX 3
+ Reserved -- 4
+ Hardware Error IVHW 5
+ Core Timer IVTMR 6 *
+
+.....
+
+ Software Interrupt 1 IVG14 31
+ Software Interrupt 2 --
+ (lowest priority) IVG15 32 *
+ */
+
+#define NR_PERI_INTS (32 * 3)
+
+/* The ABSTRACT IRQ definitions */
+/** the first seven of the following are fixed, the rest you change if you need to **/
+#define IRQ_EMU 0 /* Emulation */
+#define IRQ_RST 1 /* reset */
+#define IRQ_NMI 2 /* Non Maskable */
+#define IRQ_EVX 3 /* Exception */
+#define IRQ_UNUSED 4 /* - unused interrupt*/
+#define IRQ_HWERR 5 /* Hardware Error */
+#define IRQ_CORETMR 6 /* Core timer */
+
+#define BFIN_IRQ(x) ((x) + 7)
+
+#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */
+#define IRQ_DMAC0_ERR BFIN_IRQ(1) /* DMAC0 Status Interrupt */
+#define IRQ_EPPI0_ERR BFIN_IRQ(2) /* EPPI0 Error Interrupt */
+#define IRQ_SPORT0_ERR BFIN_IRQ(3) /* SPORT0 Error Interrupt */
+#define IRQ_SPORT1_ERR BFIN_IRQ(4) /* SPORT1 Error Interrupt */
+#define IRQ_SPI0_ERR BFIN_IRQ(5) /* SPI0 Status(Error) Interrupt */
+#define IRQ_UART0_ERR BFIN_IRQ(6) /* UART0 Status(Error) Interrupt */
+#define IRQ_RTC BFIN_IRQ(7) /* RTC Interrupt */
+#define IRQ_EPPI0 BFIN_IRQ(8) /* EPPI0 Interrupt (DMA12) */
+#define IRQ_SPORT0_RX BFIN_IRQ(9) /* SPORT0 RX Interrupt (DMA0) */
+#define IRQ_SPORT0_TX BFIN_IRQ(10) /* SPORT0 TX Interrupt (DMA1) */
+#define IRQ_SPORT1_RX BFIN_IRQ(11) /* SPORT1 RX Interrupt (DMA2) */
+#define IRQ_SPORT1_TX BFIN_IRQ(12) /* SPORT1 TX Interrupt (DMA3) */
+#define IRQ_SPI0 BFIN_IRQ(13) /* SPI0 Interrupt (DMA4) */
+#define IRQ_UART0_RX BFIN_IRQ(14) /* UART0 RX Interrupt (DMA6) */
+#define IRQ_UART0_TX BFIN_IRQ(15) /* UART0 TX Interrupt (DMA7) */
+#define IRQ_TIMER8 BFIN_IRQ(16) /* TIMER 8 Interrupt */
+#define IRQ_TIMER9 BFIN_IRQ(17) /* TIMER 9 Interrupt */
+#define IRQ_TIMER10 BFIN_IRQ(18) /* TIMER 10 Interrupt */
+#define IRQ_PINT0 BFIN_IRQ(19) /* PINT0 Interrupt */
+#define IRQ_PINT1 BFIN_IRQ(20) /* PINT1 Interrupt */
+#define IRQ_MDMAS0 BFIN_IRQ(21) /* MDMA Stream 0 Interrupt */
+#define IRQ_MDMAS1 BFIN_IRQ(22) /* MDMA Stream 1 Interrupt */
+#define IRQ_WATCHDOG BFIN_IRQ(23) /* Watchdog Interrupt */
+#define IRQ_DMAC1_ERR BFIN_IRQ(24) /* DMAC1 Status (Error) Interrupt */
+#define IRQ_SPORT2_ERR BFIN_IRQ(25) /* SPORT2 Error Interrupt */
+#define IRQ_SPORT3_ERR BFIN_IRQ(26) /* SPORT3 Error Interrupt */
+#define IRQ_MXVR_DATA BFIN_IRQ(27) /* MXVR Data Interrupt */
+#define IRQ_SPI1_ERR BFIN_IRQ(28) /* SPI1 Status (Error) Interrupt */
+#define IRQ_SPI2_ERR BFIN_IRQ(29) /* SPI2 Status (Error) Interrupt */
+#define IRQ_UART1_ERR BFIN_IRQ(30) /* UART1 Status (Error) Interrupt */
+#define IRQ_UART2_ERR BFIN_IRQ(31) /* UART2 Status (Error) Interrupt */
+#define IRQ_CAN0_ERR BFIN_IRQ(32) /* CAN0 Status (Error) Interrupt */
+#define IRQ_SPORT2_RX BFIN_IRQ(33) /* SPORT2 RX (DMA18) Interrupt */
+#define IRQ_SPORT2_TX BFIN_IRQ(34) /* SPORT2 TX (DMA19) Interrupt */
+#define IRQ_SPORT3_RX BFIN_IRQ(35) /* SPORT3 RX (DMA20) Interrupt */
+#define IRQ_SPORT3_TX BFIN_IRQ(36) /* SPORT3 TX (DMA21) Interrupt */
+#define IRQ_EPPI1 BFIN_IRQ(37) /* EPP1 (DMA13) Interrupt */
+#define IRQ_EPPI2 BFIN_IRQ(38) /* EPP2 (DMA14) Interrupt */
+#define IRQ_SPI1 BFIN_IRQ(39) /* SPI1 (DMA5) Interrupt */
+#define IRQ_SPI2 BFIN_IRQ(40) /* SPI2 (DMA23) Interrupt */
+#define IRQ_UART1_RX BFIN_IRQ(41) /* UART1 RX (DMA8) Interrupt */
+#define IRQ_UART1_TX BFIN_IRQ(42) /* UART1 TX (DMA9) Interrupt */
+#define IRQ_ATAPI_RX BFIN_IRQ(43) /* ATAPI RX (DMA10) Interrupt */
+#define IRQ_ATAPI_TX BFIN_IRQ(44) /* ATAPI TX (DMA11) Interrupt */
+#define IRQ_TWI0 BFIN_IRQ(45) /* TWI0 Interrupt */
+#define IRQ_TWI1 BFIN_IRQ(46) /* TWI1 Interrupt */
+#define IRQ_CAN0_RX BFIN_IRQ(47) /* CAN0 Receive Interrupt */
+#define IRQ_CAN0_TX BFIN_IRQ(48) /* CAN0 Transmit Interrupt */
+#define IRQ_MDMAS2 BFIN_IRQ(49) /* MDMA Stream 2 Interrupt */
+#define IRQ_MDMAS3 BFIN_IRQ(50) /* MDMA Stream 3 Interrupt */
+#define IRQ_MXVR_ERR BFIN_IRQ(51) /* MXVR Status (Error) Interrupt */
+#define IRQ_MXVR_MSG BFIN_IRQ(52) /* MXVR Message Interrupt */
+#define IRQ_MXVR_PKT BFIN_IRQ(53) /* MXVR Packet Interrupt */
+#define IRQ_EPP1_ERR BFIN_IRQ(54) /* EPPI1 Error Interrupt */
+#define IRQ_EPP2_ERR BFIN_IRQ(55) /* EPPI2 Error Interrupt */
+#define IRQ_UART3_ERR BFIN_IRQ(56) /* UART3 Status (Error) Interrupt */
+#define IRQ_HOST_ERR BFIN_IRQ(57) /* HOST Status (Error) Interrupt */
+#define IRQ_PIXC_ERR BFIN_IRQ(59) /* PIXC Status (Error) Interrupt */
+#define IRQ_NFC_ERR BFIN_IRQ(60) /* NFC Error Interrupt */
+#define IRQ_ATAPI_ERR BFIN_IRQ(61) /* ATAPI Error Interrupt */
+#define IRQ_CAN1_ERR BFIN_IRQ(62) /* CAN1 Status (Error) Interrupt */
+#define IRQ_HS_DMA_ERR BFIN_IRQ(63) /* Handshake DMA Status Interrupt */
+#define IRQ_PIXC_IN0 BFIN_IRQ(64) /* PIXC IN0 (DMA15) Interrupt */
+#define IRQ_PIXC_IN1 BFIN_IRQ(65) /* PIXC IN1 (DMA16) Interrupt */
+#define IRQ_PIXC_OUT BFIN_IRQ(66) /* PIXC OUT (DMA17) Interrupt */
+#define IRQ_SDH BFIN_IRQ(67) /* SDH/NFC (DMA22) Interrupt */
+#define IRQ_CNT BFIN_IRQ(68) /* CNT Interrupt */
+#define IRQ_KEY BFIN_IRQ(69) /* KEY Interrupt */
+#define IRQ_CAN1_RX BFIN_IRQ(70) /* CAN1 RX Interrupt */
+#define IRQ_CAN1_TX BFIN_IRQ(71) /* CAN1 TX Interrupt */
+#define IRQ_SDH_MASK0 BFIN_IRQ(72) /* SDH Mask 0 Interrupt */
+#define IRQ_SDH_MASK1 BFIN_IRQ(73) /* SDH Mask 1 Interrupt */
+#define IRQ_USB_INT0 BFIN_IRQ(75) /* USB INT0 Interrupt */
+#define IRQ_USB_INT1 BFIN_IRQ(76) /* USB INT1 Interrupt */
+#define IRQ_USB_INT2 BFIN_IRQ(77) /* USB INT2 Interrupt */
+#define IRQ_USB_DMA BFIN_IRQ(78) /* USB DMA Interrupt */
+#define IRQ_OPTSEC BFIN_IRQ(79) /* OTPSEC Interrupt */
+#define IRQ_TIMER0 BFIN_IRQ(86) /* Timer 0 Interrupt */
+#define IRQ_TIMER1 BFIN_IRQ(87) /* Timer 1 Interrupt */
+#define IRQ_TIMER2 BFIN_IRQ(88) /* Timer 2 Interrupt */
+#define IRQ_TIMER3 BFIN_IRQ(89) /* Timer 3 Interrupt */
+#define IRQ_TIMER4 BFIN_IRQ(90) /* Timer 4 Interrupt */
+#define IRQ_TIMER5 BFIN_IRQ(91) /* Timer 5 Interrupt */
+#define IRQ_TIMER6 BFIN_IRQ(92) /* Timer 6 Interrupt */
+#define IRQ_TIMER7 BFIN_IRQ(93) /* Timer 7 Interrupt */
+#define IRQ_PINT2 BFIN_IRQ(94) /* PINT2 Interrupt */
+#define IRQ_PINT3 BFIN_IRQ(95) /* PINT3 Interrupt */
+
+#define SYS_IRQS IRQ_PINT3
+
+#define BFIN_PA_IRQ(x) ((x) + SYS_IRQS + 1)
+#define IRQ_PA0 BFIN_PA_IRQ(0)
+#define IRQ_PA1 BFIN_PA_IRQ(1)
+#define IRQ_PA2 BFIN_PA_IRQ(2)
+#define IRQ_PA3 BFIN_PA_IRQ(3)
+#define IRQ_PA4 BFIN_PA_IRQ(4)
+#define IRQ_PA5 BFIN_PA_IRQ(5)
+#define IRQ_PA6 BFIN_PA_IRQ(6)
+#define IRQ_PA7 BFIN_PA_IRQ(7)
+#define IRQ_PA8 BFIN_PA_IRQ(8)
+#define IRQ_PA9 BFIN_PA_IRQ(9)
+#define IRQ_PA10 BFIN_PA_IRQ(10)
+#define IRQ_PA11 BFIN_PA_IRQ(11)
+#define IRQ_PA12 BFIN_PA_IRQ(12)
+#define IRQ_PA13 BFIN_PA_IRQ(13)
+#define IRQ_PA14 BFIN_PA_IRQ(14)
+#define IRQ_PA15 BFIN_PA_IRQ(15)
+
+#define BFIN_PB_IRQ(x) ((x) + IRQ_PA15 + 1)
+#define IRQ_PB0 BFIN_PB_IRQ(0)
+#define IRQ_PB1 BFIN_PB_IRQ(1)
+#define IRQ_PB2 BFIN_PB_IRQ(2)
+#define IRQ_PB3 BFIN_PB_IRQ(3)
+#define IRQ_PB4 BFIN_PB_IRQ(4)
+#define IRQ_PB5 BFIN_PB_IRQ(5)
+#define IRQ_PB6 BFIN_PB_IRQ(6)
+#define IRQ_PB7 BFIN_PB_IRQ(7)
+#define IRQ_PB8 BFIN_PB_IRQ(8)
+#define IRQ_PB9 BFIN_PB_IRQ(9)
+#define IRQ_PB10 BFIN_PB_IRQ(10)
+#define IRQ_PB11 BFIN_PB_IRQ(11)
+#define IRQ_PB12 BFIN_PB_IRQ(12)
+#define IRQ_PB13 BFIN_PB_IRQ(13)
+#define IRQ_PB14 BFIN_PB_IRQ(14)
+#define IRQ_PB15 BFIN_PB_IRQ(15) /* N/A */
+
+#define BFIN_PC_IRQ(x) ((x) + IRQ_PB15 + 1)
+#define IRQ_PC0 BFIN_PC_IRQ(0)
+#define IRQ_PC1 BFIN_PC_IRQ(1)
+#define IRQ_PC2 BFIN_PC_IRQ(2)
+#define IRQ_PC3 BFIN_PC_IRQ(3)
+#define IRQ_PC4 BFIN_PC_IRQ(4)
+#define IRQ_PC5 BFIN_PC_IRQ(5)
+#define IRQ_PC6 BFIN_PC_IRQ(6)
+#define IRQ_PC7 BFIN_PC_IRQ(7)
+#define IRQ_PC8 BFIN_PC_IRQ(8)
+#define IRQ_PC9 BFIN_PC_IRQ(9)
+#define IRQ_PC10 BFIN_PC_IRQ(10)
+#define IRQ_PC11 BFIN_PC_IRQ(11)
+#define IRQ_PC12 BFIN_PC_IRQ(12)
+#define IRQ_PC13 BFIN_PC_IRQ(13)
+#define IRQ_PC14 BFIN_PC_IRQ(14) /* N/A */
+#define IRQ_PC15 BFIN_PC_IRQ(15) /* N/A */
+
+#define BFIN_PD_IRQ(x) ((x) + IRQ_PC15 + 1)
+#define IRQ_PD0 BFIN_PD_IRQ(0)
+#define IRQ_PD1 BFIN_PD_IRQ(1)
+#define IRQ_PD2 BFIN_PD_IRQ(2)
+#define IRQ_PD3 BFIN_PD_IRQ(3)
+#define IRQ_PD4 BFIN_PD_IRQ(4)
+#define IRQ_PD5 BFIN_PD_IRQ(5)
+#define IRQ_PD6 BFIN_PD_IRQ(6)
+#define IRQ_PD7 BFIN_PD_IRQ(7)
+#define IRQ_PD8 BFIN_PD_IRQ(8)
+#define IRQ_PD9 BFIN_PD_IRQ(9)
+#define IRQ_PD10 BFIN_PD_IRQ(10)
+#define IRQ_PD11 BFIN_PD_IRQ(11)
+#define IRQ_PD12 BFIN_PD_IRQ(12)
+#define IRQ_PD13 BFIN_PD_IRQ(13)
+#define IRQ_PD14 BFIN_PD_IRQ(14)
+#define IRQ_PD15 BFIN_PD_IRQ(15)
+
+#define BFIN_PE_IRQ(x) ((x) + IRQ_PD15 + 1)
+#define IRQ_PE0 BFIN_PE_IRQ(0)
+#define IRQ_PE1 BFIN_PE_IRQ(1)
+#define IRQ_PE2 BFIN_PE_IRQ(2)
+#define IRQ_PE3 BFIN_PE_IRQ(3)
+#define IRQ_PE4 BFIN_PE_IRQ(4)
+#define IRQ_PE5 BFIN_PE_IRQ(5)
+#define IRQ_PE6 BFIN_PE_IRQ(6)
+#define IRQ_PE7 BFIN_PE_IRQ(7)
+#define IRQ_PE8 BFIN_PE_IRQ(8)
+#define IRQ_PE9 BFIN_PE_IRQ(9)
+#define IRQ_PE10 BFIN_PE_IRQ(10)
+#define IRQ_PE11 BFIN_PE_IRQ(11)
+#define IRQ_PE12 BFIN_PE_IRQ(12)
+#define IRQ_PE13 BFIN_PE_IRQ(13)
+#define IRQ_PE14 BFIN_PE_IRQ(14)
+#define IRQ_PE15 BFIN_PE_IRQ(15)
+
+#define BFIN_PF_IRQ(x) ((x) + IRQ_PE15 + 1)
+#define IRQ_PF0 BFIN_PF_IRQ(0)
+#define IRQ_PF1 BFIN_PF_IRQ(1)
+#define IRQ_PF2 BFIN_PF_IRQ(2)
+#define IRQ_PF3 BFIN_PF_IRQ(3)
+#define IRQ_PF4 BFIN_PF_IRQ(4)
+#define IRQ_PF5 BFIN_PF_IRQ(5)
+#define IRQ_PF6 BFIN_PF_IRQ(6)
+#define IRQ_PF7 BFIN_PF_IRQ(7)
+#define IRQ_PF8 BFIN_PF_IRQ(8)
+#define IRQ_PF9 BFIN_PF_IRQ(9)
+#define IRQ_PF10 BFIN_PF_IRQ(10)
+#define IRQ_PF11 BFIN_PF_IRQ(11)
+#define IRQ_PF12 BFIN_PF_IRQ(12)
+#define IRQ_PF13 BFIN_PF_IRQ(13)
+#define IRQ_PF14 BFIN_PF_IRQ(14)
+#define IRQ_PF15 BFIN_PF_IRQ(15)
+
+#define BFIN_PG_IRQ(x) ((x) + IRQ_PF15 + 1)
+#define IRQ_PG0 BFIN_PG_IRQ(0)
+#define IRQ_PG1 BFIN_PG_IRQ(1)
+#define IRQ_PG2 BFIN_PG_IRQ(2)
+#define IRQ_PG3 BFIN_PG_IRQ(3)
+#define IRQ_PG4 BFIN_PG_IRQ(4)
+#define IRQ_PG5 BFIN_PG_IRQ(5)
+#define IRQ_PG6 BFIN_PG_IRQ(6)
+#define IRQ_PG7 BFIN_PG_IRQ(7)
+#define IRQ_PG8 BFIN_PG_IRQ(8)
+#define IRQ_PG9 BFIN_PG_IRQ(9)
+#define IRQ_PG10 BFIN_PG_IRQ(10)
+#define IRQ_PG11 BFIN_PG_IRQ(11)
+#define IRQ_PG12 BFIN_PG_IRQ(12)
+#define IRQ_PG13 BFIN_PG_IRQ(13)
+#define IRQ_PG14 BFIN_PG_IRQ(14)
+#define IRQ_PG15 BFIN_PG_IRQ(15)
+
+#define BFIN_PH_IRQ(x) ((x) + IRQ_PG15 + 1)
+#define IRQ_PH0 BFIN_PH_IRQ(0)
+#define IRQ_PH1 BFIN_PH_IRQ(1)
+#define IRQ_PH2 BFIN_PH_IRQ(2)
+#define IRQ_PH3 BFIN_PH_IRQ(3)
+#define IRQ_PH4 BFIN_PH_IRQ(4)
+#define IRQ_PH5 BFIN_PH_IRQ(5)
+#define IRQ_PH6 BFIN_PH_IRQ(6)
+#define IRQ_PH7 BFIN_PH_IRQ(7)
+#define IRQ_PH8 BFIN_PH_IRQ(8)
+#define IRQ_PH9 BFIN_PH_IRQ(9)
+#define IRQ_PH10 BFIN_PH_IRQ(10)
+#define IRQ_PH11 BFIN_PH_IRQ(11)
+#define IRQ_PH12 BFIN_PH_IRQ(12)
+#define IRQ_PH13 BFIN_PH_IRQ(13)
+#define IRQ_PH14 BFIN_PH_IRQ(14) /* N/A */
+#define IRQ_PH15 BFIN_PH_IRQ(15) /* N/A */
+
+#define BFIN_PI_IRQ(x) ((x) + IRQ_PH15 + 1)
+#define IRQ_PI0 BFIN_PI_IRQ(0)
+#define IRQ_PI1 BFIN_PI_IRQ(1)
+#define IRQ_PI2 BFIN_PI_IRQ(2)
+#define IRQ_PI3 BFIN_PI_IRQ(3)
+#define IRQ_PI4 BFIN_PI_IRQ(4)
+#define IRQ_PI5 BFIN_PI_IRQ(5)
+#define IRQ_PI6 BFIN_PI_IRQ(6)
+#define IRQ_PI7 BFIN_PI_IRQ(7)
+#define IRQ_PI8 BFIN_PI_IRQ(8)
+#define IRQ_PI9 BFIN_PI_IRQ(9)
+#define IRQ_PI10 BFIN_PI_IRQ(10)
+#define IRQ_PI11 BFIN_PI_IRQ(11)
+#define IRQ_PI12 BFIN_PI_IRQ(12)
+#define IRQ_PI13 BFIN_PI_IRQ(13)
+#define IRQ_PI14 BFIN_PI_IRQ(14)
+#define IRQ_PI15 BFIN_PI_IRQ(15)
+
+#define BFIN_PJ_IRQ(x) ((x) + IRQ_PI15 + 1)
+#define IRQ_PJ0 BFIN_PJ_IRQ(0)
+#define IRQ_PJ1 BFIN_PJ_IRQ(1)
+#define IRQ_PJ2 BFIN_PJ_IRQ(2)
+#define IRQ_PJ3 BFIN_PJ_IRQ(3)
+#define IRQ_PJ4 BFIN_PJ_IRQ(4)
+#define IRQ_PJ5 BFIN_PJ_IRQ(5)
+#define IRQ_PJ6 BFIN_PJ_IRQ(6)
+#define IRQ_PJ7 BFIN_PJ_IRQ(7)
+#define IRQ_PJ8 BFIN_PJ_IRQ(8)
+#define IRQ_PJ9 BFIN_PJ_IRQ(9)
+#define IRQ_PJ10 BFIN_PJ_IRQ(10)
+#define IRQ_PJ11 BFIN_PJ_IRQ(11)
+#define IRQ_PJ12 BFIN_PJ_IRQ(12)
+#define IRQ_PJ13 BFIN_PJ_IRQ(13)
+#define IRQ_PJ14 BFIN_PJ_IRQ(14) /* N/A */
+#define IRQ_PJ15 BFIN_PJ_IRQ(15) /* N/A */
+
+#ifdef CONFIG_IRQCHIP_DEMUX_GPIO
+#define NR_IRQS (IRQ_PJ15+1)
+#else
+#define NR_IRQS (SYS_IRQS+1)
+#endif
+
+#define IVG7 7
+#define IVG8 8
+#define IVG9 9
+#define IVG10 10
+#define IVG11 11
+#define IVG12 12
+#define IVG13 13
+#define IVG14 14
+#define IVG15 15
+
+/* IAR0 BIT FIELDS */
+#define IRQ_PLL_WAKEUP_POS 0
+#define IRQ_DMAC0_ERR_POS 4
+#define IRQ_EPPI0_ERR_POS 8
+#define IRQ_SPORT0_ERR_POS 12
+#define IRQ_SPORT1_ERR_POS 16
+#define IRQ_SPI0_ERR_POS 20
+#define IRQ_UART0_ERR_POS 24
+#define IRQ_RTC_POS 28
+
+/* IAR1 BIT FIELDS */
+#define IRQ_EPPI0_POS 0
+#define IRQ_SPORT0_RX_POS 4
+#define IRQ_SPORT0_TX_POS 8
+#define IRQ_SPORT1_RX_POS 12
+#define IRQ_SPORT1_TX_POS 16
+#define IRQ_SPI0_POS 20
+#define IRQ_UART0_RX_POS 24
+#define IRQ_UART0_TX_POS 28
+
+/* IAR2 BIT FIELDS */
+#define IRQ_TIMER8_POS 0
+#define IRQ_TIMER9_POS 4
+#define IRQ_TIMER10_POS 8
+#define IRQ_PINT0_POS 12
+#define IRQ_PINT1_POS 16
+#define IRQ_MDMAS0_POS 20
+#define IRQ_MDMAS1_POS 24
+#define IRQ_WATCHDOG_POS 28
+
+/* IAR3 BIT FIELDS */
+#define IRQ_DMAC1_ERR_POS 0
+#define IRQ_SPORT2_ERR_POS 4
+#define IRQ_SPORT3_ERR_POS 8
+#define IRQ_MXVR_DATA_POS 12
+#define IRQ_SPI1_ERR_POS 16
+#define IRQ_SPI2_ERR_POS 20
+#define IRQ_UART1_ERR_POS 24
+#define IRQ_UART2_ERR_POS 28
+
+/* IAR4 BIT FILEDS */
+#define IRQ_CAN0_ERR_POS 0
+#define IRQ_SPORT2_RX_POS 4
+#define IRQ_SPORT2_TX_POS 8
+#define IRQ_SPORT3_RX_POS 12
+#define IRQ_SPORT3_TX_POS 16
+#define IRQ_EPPI1_POS 20
+#define IRQ_EPPI2_POS 24
+#define IRQ_SPI1_POS 28
+
+/* IAR5 BIT FIELDS */
+#define IRQ_SPI2_POS 0
+#define IRQ_UART1_RX_POS 4
+#define IRQ_UART1_TX_POS 8
+#define IRQ_ATAPI_RX_POS 12
+#define IRQ_ATAPI_TX_POS 16
+#define IRQ_TWI0_POS 20
+#define IRQ_TWI1_POS 24
+#define IRQ_CAN0_RX_POS 28
+
+/* IAR6 BIT FIELDS */
+#define IRQ_CAN0_TX_POS 0
+#define IRQ_MDMAS2_POS 4
+#define IRQ_MDMAS3_POS 8
+#define IRQ_MXVR_ERR_POS 12
+#define IRQ_MXVR_MSG_POS 16
+#define IRQ_MXVR_PKT_POS 20
+#define IRQ_EPPI1_ERR_POS 24
+#define IRQ_EPPI2_ERR_POS 28
+
+/* IAR7 BIT FIELDS */
+#define IRQ_UART3_ERR_POS 0
+#define IRQ_HOST_ERR_POS 4
+#define IRQ_PIXC_ERR_POS 12
+#define IRQ_NFC_ERR_POS 16
+#define IRQ_ATAPI_ERR_POS 20
+#define IRQ_CAN1_ERR_POS 24
+#define IRQ_HS_DMA_ERR_POS 28
+
+/* IAR8 BIT FIELDS */
+#define IRQ_PIXC_IN0_POS 0
+#define IRQ_PIXC_IN1_POS 4
+#define IRQ_PIXC_OUT_POS 8
+#define IRQ_SDH_POS 12
+#define IRQ_CNT_POS 16
+#define IRQ_KEY_POS 20
+#define IRQ_CAN1_RX_POS 24
+#define IRQ_CAN1_TX_POS 28
+
+/* IAR9 BIT FIELDS */
+#define IRQ_SDH_MASK0_POS 0
+#define IRQ_SDH_MASK1_POS 4
+#define IRQ_USB_INT0_POS 12
+#define IRQ_USB_INT1_POS 16
+#define IRQ_USB_INT2_POS 20
+#define IRQ_USB_DMA_POS 24
+#define IRQ_OTPSEC_POS 28
+
+/* IAR10 BIT FIELDS */
+#define IRQ_TIMER0_POS 24
+#define IRQ_TIMER1_POS 28
+
+/* IAR11 BIT FIELDS */
+#define IRQ_TIMER2_POS 0
+#define IRQ_TIMER3_POS 4
+#define IRQ_TIMER4_POS 8
+#define IRQ_TIMER5_POS 12
+#define IRQ_TIMER6_POS 16
+#define IRQ_TIMER7_POS 20
+#define IRQ_PINT2_POS 24
+#define IRQ_PINT3_POS 28
+
+#endif /* _BF548_IRQ_H_ */
diff --git a/include/asm-blackfin/mach-bf548/mem_init.h b/include/asm-blackfin/mach-bf548/mem_init.h
new file mode 100644
index 00000000000..0cb279e973d
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/mem_init.h
@@ -0,0 +1,189 @@
+/*
+ * File: include/asm-blackfin/mach-bf548/mem_init.h
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Rev:
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.
+ * If not, write to the Free Software Foundation,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#if (CONFIG_MEM_MT46V32M16)
+
+#if defined CONFIG_CLKIN_HALF
+#define CLKIN_HALF 1
+#else
+#define CLKIN_HALF 0
+#endif
+
+#if defined CONFIG_PLL_BYPASS
+#define PLL_BYPASS 1
+#else
+#define PLL_BYPASS 0
+#endif
+
+/***************************************Currently Not Being Used *********************************/
+#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ))
+#define flash_EBIU_AMBCTL_ST ((CONFIG_FLASH_SPEED_BST * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+#define flash_EBIU_AMBCTL_TT ((CONFIG_FLASH_SPEED_BTT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1
+
+#if (flash_EBIU_AMBCTL_TT > 3)
+#define flash_EBIU_AMBCTL0_TT B0TT_4
+#endif
+#if (flash_EBIU_AMBCTL_TT == 3)
+#define flash_EBIU_AMBCTL0_TT B0TT_3
+#endif
+#if (flash_EBIU_AMBCTL_TT == 2)
+#define flash_EBIU_AMBCTL0_TT B0TT_2
+#endif
+#if (flash_EBIU_AMBCTL_TT < 2)
+#define flash_EBIU_AMBCTL0_TT B0TT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_ST > 3)
+#define flash_EBIU_AMBCTL0_ST B0ST_4
+#endif
+#if (flash_EBIU_AMBCTL_ST == 3)
+#define flash_EBIU_AMBCTL0_ST B0ST_3
+#endif
+#if (flash_EBIU_AMBCTL_ST == 2)
+#define flash_EBIU_AMBCTL0_ST B0ST_2
+#endif
+#if (flash_EBIU_AMBCTL_ST < 2)
+#define flash_EBIU_AMBCTL0_ST B0ST_1
+#endif
+
+#if (flash_EBIU_AMBCTL_HT > 2)
+#define flash_EBIU_AMBCTL0_HT B0HT_3
+#endif
+#if (flash_EBIU_AMBCTL_HT == 2)
+#define flash_EBIU_AMBCTL0_HT B0HT_2
+#endif
+#if (flash_EBIU_AMBCTL_HT == 1)
+#define flash_EBIU_AMBCTL0_HT B0HT_1
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0)
+#define flash_EBIU_AMBCTL0_HT B0HT_0
+#endif
+#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0)
+#define flash_EBIU_AMBCTL0_HT B0HT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_WAT > 14)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_15
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 14)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_14
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 13)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_13
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 12)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_12
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 11)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_11
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 10)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_10
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 9)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_9
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 8)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_8
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 7)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_7
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 6)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_6
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 5)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_5
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 4)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_4
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 3)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_3
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 2)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_2
+#endif
+#if (flash_EBIU_AMBCTL_WAT == 1)
+#define flash_EBIU_AMBCTL0_WAT B0WAT_1
+#endif
+
+#if (flash_EBIU_AMBCTL_RAT > 14)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_15
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 14)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_14
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 13)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_13
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 12)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_12
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 11)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_11
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 10)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_10
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 9)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_9
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 8)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_8
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 7)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_7
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 6)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_6
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 5)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_5
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 4)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_4
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 3)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_3
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 2)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_2
+#endif
+#if (flash_EBIU_AMBCTL_RAT == 1)
+#define flash_EBIU_AMBCTL0_RAT B0RAT_1
+#endif
+
+#define flash_EBIU_AMBCTL0 \
+ (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \
+ flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN)
diff --git a/include/asm-blackfin/mach-bf548/mem_map.h b/include/asm-blackfin/mach-bf548/mem_map.h
new file mode 100644
index 00000000000..72d80e8a6e8
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/mem_map.h
@@ -0,0 +1,97 @@
+/*
+ * file: include/asm-blackfin/mach-bf548/mem_map.h
+ * based on:
+ * author:
+ *
+ * created:
+ * description:
+ * Memory MAP Common header file for blackfin BF537/6/4 of processors.
+ * rev:
+ *
+ * modified:
+ *
+ * bugs: enter bugs at http://blackfin.uclinux.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, or (at your option)
+ * any later version.
+ *
+ * this program is distributed in the hope that it will be useful,
+ * but without any warranty; without even the implied warranty of
+ * merchantability or fitness for a particular purpose. see the
+ * gnu general public license for more details.
+ *
+ * you should have received a copy of the gnu general public license
+ * along with this program; see the file copying.
+ * if not, write to the free software foundation,
+ * 59 temple place - suite 330, boston, ma 02111-1307, usa.
+ */
+
+#ifndef _MEM_MAP_548_H_
+#define _MEM_MAP_548_H_
+
+#define COREMMR_BASE 0xFFE00000 /* Core MMRs */
+#define SYSMMR_BASE 0xFFC00000 /* System MMRs */
+
+/* Async Memory Banks */
+#define ASYNC_BANK3_BASE 0x2C000000 /* Async Bank 3 */
+#define ASYNC_BANK3_SIZE 0x04000000 /* 64M */
+#define ASYNC_BANK2_BASE 0x28000000 /* Async Bank 2 */
+#define ASYNC_BANK2_SIZE 0x04000000 /* 64M */
+#define ASYNC_BANK1_BASE 0x24000000 /* Async Bank 1 */
+#define ASYNC_BANK1_SIZE 0x04000000 /* 64M */
+#define ASYNC_BANK0_BASE 0x20000000 /* Async Bank 0 */
+#define ASYNC_BANK0_SIZE 0x04000000 /* 64M */
+
+/* Boot ROM Memory */
+
+#define BOOT_ROM_START 0xEF000000
+
+/* Level 1 Memory */
+
+/* Memory Map for ADSP-BF548 processors */
+#ifdef CONFIG_BLKFIN_ICACHE
+#define BLKFIN_ICACHESIZE (16*1024)
+#else
+#define BLKFIN_ICACHESIZE (0*1024)
+#endif
+
+#define L1_CODE_START 0xFFA00000
+#define L1_DATA_A_START 0xFF800000
+#define L1_DATA_B_START 0xFF900000
+
+#define L1_CODE_LENGTH 0xC000
+
+#ifdef CONFIG_BLKFIN_DCACHE
+
+#ifdef CONFIG_BLKFIN_DCACHE_BANKA
+#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH 0x8000
+#define BLKFIN_DCACHESIZE (16*1024)
+#define BLKFIN_DSUPBANKS 1
+#else
+#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
+#define L1_DATA_B_LENGTH (0x8000 - 0x4000)
+#define BLKFIN_DCACHESIZE (32*1024)
+#define BLKFIN_DSUPBANKS 2
+#endif
+
+#else
+#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0)
+#define L1_DATA_A_LENGTH 0x8000
+#define L1_DATA_B_LENGTH 0x8000
+#define BLKFIN_DCACHESIZE (0*1024)
+#define BLKFIN_DSUPBANKS 0
+#endif /*CONFIG_BLKFIN_DCACHE*/
+
+/* Scratch Pad Memory */
+
+#if defined(CONFIG_BF54x)
+#define L1_SCRATCH_START 0xFFB00000
+#define L1_SCRATCH_LENGTH 0x1000
+#endif
+
+#endif/* _MEM_MAP_548_H_ */
diff --git a/include/asm-blackfin/mach-bf548/portmux.h b/include/asm-blackfin/mach-bf548/portmux.h
new file mode 100644
index 00000000000..b382deb501a
--- /dev/null
+++ b/include/asm-blackfin/mach-bf548/portmux.h
@@ -0,0 +1,270 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_SPORT2_TFS (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(0))
+#define P_SPORT2_DTSEC (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(0))
+#define P_SPORT2_DTPRI (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(0))
+#define P_SPORT2_TSCLK (P_DEFINED | P_IDENT(GPIO_PA3) | P_FUNCT(0))
+#define P_SPORT2_RFS (P_DEFINED | P_IDENT(GPIO_PA4) | P_FUNCT(0))
+#define P_SPORT2_DRSEC (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(0))
+#define P_SPORT2_DRPRI (P_DEFINED | P_IDENT(GPIO_PA6) | P_FUNCT(0))
+#define P_SPORT2_RSCLK (P_DEFINED | P_IDENT(GPIO_PA7) | P_FUNCT(0))
+#define P_SPORT3_TFS (P_DEFINED | P_IDENT(GPIO_PA8) | P_FUNCT(0))
+#define P_SPORT3_DTSEC (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(0))
+#define P_SPORT3_DTPRI (P_DEFINED | P_IDENT(GPIO_PA10) | P_FUNCT(0))
+#define P_SPORT3_TSCLK (P_DEFINED | P_IDENT(GPIO_PA11) | P_FUNCT(0))
+#define P_SPORT3_RFS (P_DEFINED | P_IDENT(GPIO_PA12) | P_FUNCT(0))
+#define P_SPORT3_DRSEC (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(0))
+#define P_SPORT3_DRPRI (P_DEFINED | P_IDENT(GPIO_PA14) | P_FUNCT(0))
+#define P_SPORT3_RSCLK (P_DEFINED | P_IDENT(GPIO_PA15) | P_FUNCT(0))
+#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(1))
+#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(1))
+#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(1))
+#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(1))
+
+#define P_TWI1_SCL (P_DEFINED | P_IDENT(GPIO_PB0) | P_FUNCT(0))
+#define P_TWI1_SDA (P_DEFINED | P_IDENT(GPIO_PB1) | P_FUNCT(0))
+#define P_UART3_RTS (P_DEFINED | P_IDENT(GPIO_PB2) | P_FUNCT(0))
+#define P_UART3_CTS (P_DEFINED | P_IDENT(GPIO_PB3) | P_FUNCT(0))
+#define P_UART2_TX (P_DEFINED | P_IDENT(GPIO_PB4) | P_FUNCT(0))
+#define P_UART2_RX (P_DEFINED | P_IDENT(GPIO_PB5) | P_FUNCT(0))
+#define P_UART3_TX (P_DEFINED | P_IDENT(GPIO_PB6) | P_FUNCT(0))
+#define P_UART3_RX (P_DEFINED | P_IDENT(GPIO_PB7) | P_FUNCT(0))
+#define P_SPI2_SS (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(0))
+#define P_SPI2_SSEL1 (P_DEFINED | P_IDENT(GPIO_PB9) | P_FUNCT(0))
+#define P_SPI2_SSEL2 (P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(0))
+#define P_SPI2_SSEL3 (P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(0))
+#define P_SPI2_SCK (P_DEFINED | P_IDENT(GPIO_PB12) | P_FUNCT(0))
+#define P_SPI2_MOSI (P_DEFINED | P_IDENT(GPIO_PB13) | P_FUNCT(0))
+#define P_SPI2_MISO (P_DEFINED | P_IDENT(GPIO_PB14) | P_FUNCT(0))
+#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(1))
+#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PB9) | P_FUNCT(1))
+#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(1))
+#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(1))
+
+#define P_SPORT0_TFS (P_DEFINED | P_IDENT(GPIO_PC0) | P_FUNCT(0))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(0))
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PC2) | P_FUNCT(0))
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PC3) | P_FUNCT(0))
+#define P_SPORT0_RFS (P_DEFINED | P_IDENT(GPIO_PC4) | P_FUNCT(0))
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(0))
+#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(0))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(0))
+#define P_SD_D0 (P_DEFINED | P_IDENT(GPIO_PC8) | P_FUNCT(0))
+#define P_SD_D1 (P_DEFINED | P_IDENT(GPIO_PC9) | P_FUNCT(0))
+#define P_SD_D2 (P_DEFINED | P_IDENT(GPIO_PC10) | P_FUNCT(0))
+#define P_SD_D3 (P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(0))
+#define P_SD_CLK (P_DEFINED | P_IDENT(GPIO_PC12) | P_FUNCT(0))
+#define P_SD_CMD (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(0))
+#define P_MMCLK (P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(1))
+#define P_MBCLK (P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(1))
+
+#define P_PPI1_D0 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(0))
+#define P_PPI1_D1 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(0))
+#define P_PPI1_D2 (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(0))
+#define P_PPI1_D3 (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(0))
+#define P_PPI1_D4 (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(0))
+#define P_PPI1_D5 (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(0))
+#define P_PPI1_D6 (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(0))
+#define P_PPI1_D7 (P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(0))
+#define P_PPI1_D8 (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(0))
+#define P_PPI1_D9 (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(0))
+#define P_PPI1_D10 (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(0))
+#define P_PPI1_D11 (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(0))
+#define P_PPI1_D12 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(0))
+#define P_PPI1_D13 (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(0))
+#define P_PPI1_D14 (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(0))
+#define P_PPI1_D15 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(0))
+
+#define P_HOST_D8 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(1))
+#define P_HOST_D9 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(1))
+#define P_HOST_D10 (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(1))
+#define P_HOST_D11 (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(1))
+#define P_HOST_D12 (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(1))
+#define P_HOST_D13 (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(1))
+#define P_HOST_D14 (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(1))
+#define P_HOST_D15 (P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(1))
+#define P_HOST_D0 (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(1))
+#define P_HOST_D1 (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(1))
+#define P_HOST_D2 (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(1))
+#define P_HOST_D3 (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(1))
+#define P_HOST_D4 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(1))
+#define P_HOST_D5 (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(1))
+#define P_HOST_D6 (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(1))
+#define P_HOST_D7 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(1))
+#define P_SPORT1_TFS (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(2))
+#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(2))
+#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(2))
+#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(2))
+#define P_SPORT1_RFS (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(2))
+#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(2))
+#define P_SPORT1_DRPRI (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(2))
+#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(2))
+#define P_PPI2_D0 (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(2))
+#define P_PPI2_D1 (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(2))
+#define P_PPI2_D2 (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(2))
+#define P_PPI2_D3 (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(2))
+#define P_PPI2_D4 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(2))
+#define P_PPI2_D5 (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(2))
+#define P_PPI2_D6 (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(2))
+#define P_PPI2_D7 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(2))
+#define P_PPI0_D18 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(3))
+#define P_PPI0_D19 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(3))
+#define P_PPI0_D20 (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(3))
+#define P_PPI0_D21 (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(3))
+#define P_PPI0_D22 (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(3))
+#define P_PPI0_D23 (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(3))
+#define P_KEY_ROW0 (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(3))
+#define P_KEY_ROW1 (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(3))
+#define P_KEY_ROW2 (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(3))
+#define P_KEY_ROW3 (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(3))
+#define P_KEY_COL0 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(3))
+#define P_KEY_COL1 (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(3))
+#define P_KEY_COL2 (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(3))
+#define P_KEY_COL3 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(3))
+
+#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0))
+#define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0))
+#define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0))
+#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(0))
+#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(0))
+#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(0))
+#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(0))
+#define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(0))
+#define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PE8) | P_FUNCT(0))
+#define P_UART1_RTS (P_DEFINED | P_IDENT(GPIO_PE9) | P_FUNCT(0))
+#define P_UART1_CTS (P_DEFINED | P_IDENT(GPIO_PE10) | P_FUNCT(0))
+#define P_PPI1_CLK (P_DEFINED | P_IDENT(GPIO_PE11) | P_FUNCT(0))
+#define P_PPI1_FS1 (P_DEFINED | P_IDENT(GPIO_PE12) | P_FUNCT(0))
+#define P_PPI1_FS2 (P_DEFINED | P_IDENT(GPIO_PE13) | P_FUNCT(0))
+#define P_TWI0_SCL (P_DEFINED | P_IDENT(GPIO_PE14) | P_FUNCT(0))
+#define P_TWI0_SDA (P_DEFINED | P_IDENT(GPIO_PE15) | P_FUNCT(0))
+#define P_KEY_COL7 (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(1))
+#define P_KEY_ROW6 (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(1))
+#define P_KEY_COL6 (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(1))
+#define P_KEY_ROW5 (P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(1))
+#define P_KEY_COL5 (P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(1))
+#define P_KEY_ROW4 (P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(1))
+#define P_KEY_COL4 (P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(1))
+#define P_KEY_ROW7 (P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(1))
+
+#define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0))
+#define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0))
+#define P_PPI0_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0))
+#define P_PPI0_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0))
+#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0))
+#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0))
+#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0))
+#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0))
+#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0))
+#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0))
+#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0))
+#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0))
+#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0))
+#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0))
+#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0))
+#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0))
+#define P_ATAPI_D0A (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1))
+#define P_ATAPI_D1A (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1))
+#define P_ATAPI_D2A (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1))
+#define P_ATAPI_D3A (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1))
+#define P_ATAPI_D4A (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1))
+#define P_ATAPI_D5A (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1))
+#define P_ATAPI_D6A (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1))
+#define P_ATAPI_D7A (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1))
+#define P_ATAPI_D8A (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1))
+#define P_ATAPI_D9A (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1))
+#define P_ATAPI_D10A (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1))
+#define P_ATAPI_D11A (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1))
+#define P_ATAPI_D12A (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1))
+#define P_ATAPI_D13A (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1))
+#define P_ATAPI_D14A (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1))
+#define P_ATAPI_D15A (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1))
+
+#define P_PPI0_CLK (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0))
+#define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0))
+#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0))
+#define P_PPI0_D16 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0))
+#define P_PPI0_D17 (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0))
+#define P_SPI1_SSEL1 (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0))
+#define P_SPI1_SSEL2 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0))
+#define P_SPI1_SSEL3 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0))
+#define P_SPI1_SCK (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0))
+#define P_SPI1_MISO (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0))
+#define P_SPI1_MOSI (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0))
+#define P_SPI1_SS (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0))
+#define P_CAN0_TX (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0))
+#define P_CAN0_RX (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0))
+#define P_CAN1_TX (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0))
+#define P_CAN1_RX (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0))
+#define P_ATAPI_A0A (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(1))
+#define P_ATAPI_A1A (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1))
+#define P_ATAPI_A2A (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1))
+#define P_HOST_CE (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1))
+#define P_HOST_RD (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1))
+#define P_HOST_WR (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1))
+#define P_MTXONB (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1))
+#define P_PPI2_FS2 (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(2))
+#define P_PPI2_FS1 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2))
+#define P_PPI2_CLK (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(2))
+#define P_CNT_CZM (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(3))
+
+#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0))
+#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0))
+#define P_ATAPI_RESET (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0))
+#define P_HOST_ADDR (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0))
+#define P_HOST_ACK (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0))
+#define P_MTX (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0))
+#define P_MRX (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0))
+#define P_MRXONB (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0))
+#define P_A4 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(0))
+#define P_A5 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(0))
+#define P_A6 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(0))
+#define P_A7 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(0))
+#define P_A8 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(0))
+#define P_A9 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(0))
+#define P_PPI1_FS3 (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(1))
+#define P_PPI2_FS3 (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(1))
+#define P_TMR8 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(1))
+#define P_TMR9 (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(1))
+#define P_TMR10 (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(1))
+#define P_DMAR0 (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(1))
+#define P_DMAR1 (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1))
+#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(2))
+#define P_CNT_CDG (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(2))
+#define P_CNT_CUD (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(2))
+
+#define P_A10 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI0) | P_FUNCT(0))
+#define P_A11 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI1) | P_FUNCT(0))
+#define P_A12 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI2) | P_FUNCT(0))
+#define P_A13 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI3) | P_FUNCT(0))
+#define P_A14 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI4) | P_FUNCT(0))
+#define P_A15 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI5) | P_FUNCT(0))
+#define P_A16 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI6) | P_FUNCT(0))
+#define P_A17 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI7) | P_FUNCT(0))
+#define P_A18 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI8) | P_FUNCT(0))
+#define P_A19 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI9) | P_FUNCT(0))
+#define P_A20 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI10) | P_FUNCT(0))
+#define P_A21 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI11) | P_FUNCT(0))
+#define P_A22 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI12) | P_FUNCT(0))
+#define P_A23 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI13) | P_FUNCT(0))
+#define P_A24 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI14) | P_FUNCT(0))
+#define P_A25 (P_MAYSHARE | P_DEFINED | P_IDENT(GPIO_PI15) | P_FUNCT(0))
+#define P_NOR_CLK (P_DEFINED | P_IDENT(GPIO_PI15) | P_FUNCT(1))
+
+#define P_AMC_ARDY_NOR_WAIT (P_DEFINED | P_IDENT(GPIO_PJ0) | P_FUNCT(0))
+#define P_NAND_CE (P_DEFINED | P_IDENT(GPIO_PJ1) | P_FUNCT(0))
+#define P_NAND_RB (P_DEFINED | P_IDENT(GPIO_PJ2) | P_FUNCT(0))
+#define P_ATAPI_DIOR (P_DEFINED | P_IDENT(GPIO_PJ3) | P_FUNCT(0))
+#define P_ATAPI_DIOW (P_DEFINED | P_IDENT(GPIO_PJ4) | P_FUNCT(0))
+#define P_ATAPI_CS0 (P_DEFINED | P_IDENT(GPIO_PJ5) | P_FUNCT(0))
+#define P_ATAPI_CS1 (P_DEFINED | P_IDENT(GPIO_PJ6) | P_FUNCT(0))
+#define P_ATAPI_DMACK (P_DEFINED | P_IDENT(GPIO_PJ7) | P_FUNCT(0))
+#define P_ATAPI_DMARQ (P_DEFINED | P_IDENT(GPIO_PJ8) | P_FUNCT(0))
+#define P_ATAPI_INTRQ (P_DEFINED | P_IDENT(GPIO_PJ9) | P_FUNCT(0))
+#define P_ATAPI_IORDY (P_DEFINED | P_IDENT(GPIO_PJ10) | P_FUNCT(0))
+#define P_AMC_BR (P_DEFINED | P_IDENT(GPIO_PJ11) | P_FUNCT(0))
+#define P_AMC_BG (P_DEFINED | P_IDENT(GPIO_PJ12) | P_FUNCT(0))
+#define P_AMC_BGH (P_DEFINED | P_IDENT(GPIO_PJ13) | P_FUNCT(0))
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
index 23bf76aa345..e043cafa3c4 100644
--- a/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
+++ b/include/asm-blackfin/mach-bf561/bfin_serial_5xx.h
@@ -78,6 +78,7 @@ struct bfin_serial_res {
};
struct bfin_serial_res bfin_serial_resource[] = {
+ {
0xFFC00400,
IRQ_UART_RX,
#ifdef CONFIG_SERIAL_BFIN_DMA
@@ -88,6 +89,7 @@ struct bfin_serial_res bfin_serial_resource[] = {
CONFIG_UART0_CTS_PIN,
CONFIG_UART0_RTS_PIN,
#endif
+ }
};
diff --git a/include/asm-blackfin/mach-bf561/cdefBF561.h b/include/asm-blackfin/mach-bf561/cdefBF561.h
index b14f872e570..1a8ec9e4692 100644
--- a/include/asm-blackfin/mach-bf561/cdefBF561.h
+++ b/include/asm-blackfin/mach-bf561/cdefBF561.h
@@ -57,12 +57,14 @@
/* Writing to VR_CTL initiates a PLL relock sequence. */
static __inline__ void bfin_write_VR_CTL(unsigned int val)
{
- unsigned long flags, iwr;
+ unsigned long flags, iwr0, iwr1;
/* Enable the PLL Wakeup bit in SIC IWR */
- iwr = bfin_read32(SICA_IWR0);
+ iwr0 = bfin_read32(SICA_IWR0);
+ iwr1 = bfin_read32(SICA_IWR1);
/* Only allow PPL Wakeup) */
bfin_write32(SICA_IWR0, IWR_ENABLE(0));
+ bfin_write32(SICA_IWR1, 0);
bfin_write16(VR_CTL, val);
__builtin_bfin_ssync();
@@ -70,7 +72,8 @@ static __inline__ void bfin_write_VR_CTL(unsigned int val)
local_irq_save(flags);
asm("IDLE;");
local_irq_restore(flags);
- bfin_write32(SICA_IWR0, iwr);
+ bfin_write32(SICA_IWR0, iwr0);
+ bfin_write32(SICA_IWR1, iwr1);
}
#define bfin_read_PLL_STAT() bfin_read16(PLL_STAT)
#define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT,val)
diff --git a/include/asm-blackfin/mach-bf561/dma.h b/include/asm-blackfin/mach-bf561/dma.h
index 21d982003e7..766334b7d8a 100644
--- a/include/asm-blackfin/mach-bf561/dma.h
+++ b/include/asm-blackfin/mach-bf561/dma.h
@@ -32,4 +32,7 @@
#define CH_IMEM_STREAM1_SRC 34
#define CH_IMEM_STREAM1_DEST 35
+extern int channel2irq(unsigned int channel);
+extern struct dma_register *base_addr[];
+
#endif
diff --git a/include/asm-blackfin/mach-bf561/portmux.h b/include/asm-blackfin/mach-bf561/portmux.h
new file mode 100644
index 00000000000..10d11d5ffe2
--- /dev/null
+++ b/include/asm-blackfin/mach-bf561/portmux.h
@@ -0,0 +1,87 @@
+#ifndef _MACH_PORTMUX_H_
+#define _MACH_PORTMUX_H_
+
+#define P_PPI0_CLK (P_DONTCARE)
+#define P_PPI0_FS1 (P_DONTCARE)
+#define P_PPI0_FS2 (P_DONTCARE)
+#define P_PPI0_FS3 (P_DONTCARE)
+#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF47))
+#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF46))
+#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF45))
+#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF44))
+#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF43))
+#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF42))
+#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF41))
+#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF40))
+#define P_PPI0_D0 (P_DONTCARE)
+#define P_PPI0_D1 (P_DONTCARE)
+#define P_PPI0_D2 (P_DONTCARE)
+#define P_PPI0_D3 (P_DONTCARE)
+#define P_PPI0_D4 (P_DONTCARE)
+#define P_PPI0_D5 (P_DONTCARE)
+#define P_PPI0_D6 (P_DONTCARE)
+#define P_PPI0_D7 (P_DONTCARE)
+#define P_PPI1_CLK (P_DONTCARE)
+#define P_PPI1_FS1 (P_DONTCARE)
+#define P_PPI1_FS2 (P_DONTCARE)
+#define P_PPI1_FS3 (P_DONTCARE)
+#define P_PPI1_D15 (P_DEFINED | P_IDENT(GPIO_PF39))
+#define P_PPI1_D14 (P_DEFINED | P_IDENT(GPIO_PF38))
+#define P_PPI1_D13 (P_DEFINED | P_IDENT(GPIO_PF37))
+#define P_PPI1_D12 (P_DEFINED | P_IDENT(GPIO_PF36))
+#define P_PPI1_D11 (P_DEFINED | P_IDENT(GPIO_PF35))
+#define P_PPI1_D10 (P_DEFINED | P_IDENT(GPIO_PF34))
+#define P_PPI1_D9 (P_DEFINED | P_IDENT(GPIO_PF33))
+#define P_PPI1_D8 (P_DEFINED | P_IDENT(GPIO_PF32))
+#define P_PPI1_D0 (P_DONTCARE)
+#define P_PPI1_D1 (P_DONTCARE)
+#define P_PPI1_D2 (P_DONTCARE)
+#define P_PPI1_D3 (P_DONTCARE)
+#define P_PPI1_D4 (P_DONTCARE)
+#define P_PPI1_D5 (P_DONTCARE)
+#define P_PPI1_D6 (P_DONTCARE)
+#define P_PPI1_D7 (P_DONTCARE)
+#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PF31))
+#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PF30))
+#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PF29))
+#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PF28))
+#define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PF27))
+#define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PF26))
+#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PF25))
+#define P_SPORT1_RFS (P_DEFINED | P_IDENT(GPIO_PF24))
+#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PF23))
+#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PF22))
+#define P_SPORT1_TFS (P_DEFINED | P_IDENT(GPIO_PF21))
+#define P_SPORT1_DRPRI (P_DONTCARE)
+#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PF20))
+#define P_SPORT0_RFS (P_DEFINED | P_IDENT(GPIO_PF19))
+#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PF18))
+#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PF17))
+#define P_SPORT0_TFS (P_DEFINED | P_IDENT(GPIO_PF16))
+#define P_SPORT0_DRPRI (P_DONTCARE)
+#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF15))
+#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_TMR11 (P_DONTCARE)
+#define P_TMR10 (P_DONTCARE)
+#define P_TMR9 (P_DONTCARE)
+#define P_TMR8 (P_DONTCARE)
+#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PF7))
+#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PF6))
+#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PF5))
+#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PF4))
+#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PF3))
+#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PF2))
+#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PF1))
+#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PF0))
+#define P_SPI0_MOSI (P_DONTCARE)
+#define P_SPI0_MIS0 (P_DONTCARE)
+#define P_SPI0_SCK (P_DONTCARE)
+
+#endif /* _MACH_PORTMUX_H_ */
diff --git a/include/asm-blackfin/mach-common/cdef_LPBlackfin.h b/include/asm-blackfin/mach-common/cdef_LPBlackfin.h
index d39c396f850..94ed381e560 100644
--- a/include/asm-blackfin/mach-common/cdef_LPBlackfin.h
+++ b/include/asm-blackfin/mach-common/cdef_LPBlackfin.h
@@ -39,7 +39,11 @@
#define bfin_read_SRAM_BASE_ADDRESS() bfin_read32(SRAM_BASE_ADDRESS)
#define bfin_write_SRAM_BASE_ADDRESS(val) bfin_write32(SRAM_BASE_ADDRESS,val)
#define bfin_read_DMEM_CONTROL() bfin_read32(DMEM_CONTROL)
+#ifdef ANOMALY_05000125
+extern void bfin_write_DMEM_CONTROL(unsigned int val);
+#else
#define bfin_write_DMEM_CONTROL(val) bfin_write32(DMEM_CONTROL,val)
+#endif
#define bfin_read_DCPLB_STATUS() bfin_read32(DCPLB_STATUS)
#define bfin_write_DCPLB_STATUS(val) bfin_write32(DCPLB_STATUS,val)
#define bfin_read_DCPLB_FAULT_ADDR() bfin_read32(DCPLB_FAULT_ADDR)
@@ -125,7 +129,11 @@
#define DTEST_DATA3 0xFFE0040C
*/
#define bfin_read_IMEM_CONTROL() bfin_read32(IMEM_CONTROL)
+#ifdef ANOMALY_05000125
+extern void bfin_write_IMEM_CONTROL(unsigned int val);
+#else
#define bfin_write_IMEM_CONTROL(val) bfin_write32(IMEM_CONTROL,val)
+#endif
#define bfin_read_ICPLB_STATUS() bfin_read32(ICPLB_STATUS)
#define bfin_write_ICPLB_STATUS(val) bfin_write32(ICPLB_STATUS,val)
#define bfin_read_ICPLB_FAULT_ADDR() bfin_read32(ICPLB_FAULT_ADDR)
diff --git a/include/asm-blackfin/mach-common/def_LPBlackfin.h b/include/asm-blackfin/mach-common/def_LPBlackfin.h
index 76103526aec..be1ece8c0c2 100644
--- a/include/asm-blackfin/mach-common/def_LPBlackfin.h
+++ b/include/asm-blackfin/mach-common/def_LPBlackfin.h
@@ -42,6 +42,12 @@
#if defined(ANOMALY_05000198)
+#define bfin_read8(addr) ({ unsigned char __v; \
+ __asm__ __volatile__ ("NOP;\n\t" \
+ "%0 = b[%1] (z);\n\t" \
+ : "=d"(__v) : "a"(addr)); \
+ __v; })
+
#define bfin_read16(addr) ({ unsigned __v; \
__asm__ __volatile__ ("NOP;\n\t"\
"%0 = w[%1] (z);\n\t"\
@@ -52,6 +58,11 @@
"%0 = [%1];\n\t"\
: "=d"(__v) : "a"(addr)); __v; })
+#define bfin_write8(addr, val) ({ \
+ __asm__ __volatile__ ("NOP;\n\t" \
+ "b[%0] = %1;\n\t" \
+ : : "a"(addr), "d"(val) : "memory");})
+
#define bfin_write16(addr,val) ({\
__asm__ __volatile__ ("NOP;\n\t"\
"w[%0] = %1;\n\t"\
@@ -64,6 +75,12 @@
#else
+#define bfin_read8(addr) ({ unsigned char __v; \
+ __asm__ __volatile__ ( \
+ "%0 = b[%1] (z);\n\t" \
+ :"=d"(__v) : "a"(addr)); \
+ __v; })
+
#define bfin_read16(addr) ({ unsigned __v; \
__asm__ __volatile__ (\
"%0 = w[%1] (z);\n\t"\
@@ -74,6 +91,11 @@
"%0 = [%1];\n\t"\
: "=d"(__v) : "a"(addr)); __v; })
+#define bfin_write8(addr, val) ({ \
+ __asm__ __volatile__ ( \
+ "b[%0] = %1; \n\t" \
+ ::"a"(addr), "d"(val) : "memory");})
+
#define bfin_write16(addr,val) ({\
__asm__ __volatile__ (\
"w[%0] = %1;\n\t"\
diff --git a/include/asm-blackfin/macros.h b/include/asm-blackfin/macros.h
deleted file mode 100644
index c0c04a2f2dd..00000000000
--- a/include/asm-blackfin/macros.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/************************************************************************
- *
- * macros.h
- *
- * (c) Copyright 2001-2003 Analog Devices, Inc. All rights reserved.
- *
- ************************************************************************/
-
-/* Defines various assembly macros. */
-
-#ifndef _MACROS_H
-#define _MACROS_H
-
-#define LO(con32) ((con32) & 0xFFFF)
-#define lo(con32) ((con32) & 0xFFFF)
-#define HI(con32) (((con32) >> 16) & 0xFFFF)
-#define hi(con32) (((con32) >> 16) & 0xFFFF)
-
-/*
- * Set the corresponding bits in a System Register (SR);
- * All bits set in "mask" will be set in the system register
- * specified by "sys_reg" bitset_SR(sys_reg, mask), where
- * sys_reg is the system register and mask are the bits to be set.
- */
-#define bitset_SR(sys_reg, mask)\
- [--SP] = (R7:6);\
- r7 = sys_reg;\
- r6.l = (mask) & 0xffff;\
- r6.h = (mask) >> 16;\
- r7 = r7 | r6;\
- sys_reg = r7;\
- csync;\
- (R7:6) = [SP++]
-
-/*
- * Clear the corresponding bits in a System Register (SR);
- * All bits set in "mask" will be cleared in the SR
- * specified by "sys_reg" bitclr_SR(sys_reg, mask), where
- * sys_reg is the SR and mask are the bits to be cleared.
- */
-#define bitclr_SR(sys_reg, mask)\
- [--SP] = (R7:6);\
- r7 = sys_reg;\
- r7 =~ r7;\
- r6.l = (mask) & 0xffff;\
- r6.h = (mask) >> 16;\
- r7 = r7 | r6;\
- r7 =~ r7;\
- sys_reg = r7;\
- csync;\
- (R7:6) = [SP++]
-
-/*
- * Set the corresponding bits in a Memory Mapped Register (MMR);
- * All bits set in "mask" will be set in the MMR specified by "mmr_reg"
- * bitset_MMR(mmr_reg, mask), where mmr_reg is the MMR and mask are
- * the bits to be set.
- */
-#define bitset_MMR(mmr_reg, mask)\
- [--SP] = (R7:6);\
- [--SP] = P5;\
- p5.l = mmr_reg & 0xffff;\
- p5.h = mmr_reg >> 16;\
- r7 = [p5];\
- r6.l = (mask) & 0xffff;\
- r6.h = (mask) >> 16;\
- r7 = r7 | r6;\
- [p5] = r7;\
- csync;\
- p5 = [SP++];\
- (R7:6) = [SP++]
-
-/*
- * Clear the corresponding bits in a Memory Mapped Register (MMR);
- * All bits set in "mask" will be cleared in the MMR specified by "mmr_reg"
- * bitclr_MMRreg(mmr_reg, mask), where sys_reg is the MMR and mask are
- * the bits to be cleared.
- */
-#define bitclr_MMR(mmr_reg, mask)\
- [--SP] = (R7:6);\
- [--SP] = P5;\
- p5.l = mmr_reg & 0xffff;\
- p5.h = mmr_reg >> 16;\
- r7 = [p5];\
- r7 =~ r7;\
- r6.l = (mask) & 0xffff;\
- r6.h = (mask) >> 16;\
- r7 = r7 | r6;\
- r7 =~ r7;\
- [p5] = r7;\
- csync;\
- p5 = [SP++];\
- (R7:6) = [SP++]
-
-#endif /* _MACROS_H */
diff --git a/include/asm-blackfin/mman.h b/include/asm-blackfin/mman.h
index 4d504f908c0..b58f5ad3f02 100644
--- a/include/asm-blackfin/mman.h
+++ b/include/asm-blackfin/mman.h
@@ -22,8 +22,6 @@
#define MAP_NORESERVE 0x4000 /* don't check for reservations */
#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
-#define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could
- be uninitialized. */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_INVALIDATE 2 /* invalidate the caches */
diff --git a/include/asm-blackfin/page.h b/include/asm-blackfin/page.h
index ffad947f1b2..8bc86717021 100644
--- a/include/asm-blackfin/page.h
+++ b/include/asm-blackfin/page.h
@@ -4,7 +4,11 @@
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#else
#define PAGE_SIZE (1UL << PAGE_SHIFT)
+#endif
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifdef __KERNEL__
diff --git a/include/asm-blackfin/portmux.h b/include/asm-blackfin/portmux.h
new file mode 100644
index 00000000000..9d3681e4211
--- /dev/null
+++ b/include/asm-blackfin/portmux.h
@@ -0,0 +1,1133 @@
+/*
+ * Common header file for blackfin family of processors.
+ *
+ */
+
+#ifndef _PORTMUX_H_
+#define _PORTMUX_H_
+
+#define P_IDENT(x) ((x) & 0x1FF)
+#define P_FUNCT(x) (((x) & 0x3) << 9)
+#define P_FUNCT2MUX(x) (((x) >> 9) & 0x3)
+#define P_DEFINED 0x8000
+#define P_UNDEF 0x4000
+#define P_MAYSHARE 0x2000
+#define P_DONTCARE 0x1000
+
+#include <asm/gpio.h>
+#include <asm/mach/portmux.h>
+
+#ifndef P_SPORT2_TFS
+#define P_SPORT2_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DTSEC
+#define P_SPORT2_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DTPRI
+#define P_SPORT2_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT2_TSCLK
+#define P_SPORT2_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT2_RFS
+#define P_SPORT2_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DRSEC
+#define P_SPORT2_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT2_DRPRI
+#define P_SPORT2_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT2_RSCLK
+#define P_SPORT2_RSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT3_TFS
+#define P_SPORT3_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DTSEC
+#define P_SPORT3_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DTPRI
+#define P_SPORT3_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT3_TSCLK
+#define P_SPORT3_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT3_RFS
+#define P_SPORT3_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DRSEC
+#define P_SPORT3_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT3_DRPRI
+#define P_SPORT3_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT3_RSCLK
+#define P_SPORT3_RSCLK P_UNDEF
+#endif
+
+#ifndef P_TMR4
+#define P_TMR4 P_UNDEF
+#endif
+
+#ifndef P_TMR5
+#define P_TMR5 P_UNDEF
+#endif
+
+#ifndef P_TMR6
+#define P_TMR6 P_UNDEF
+#endif
+
+#ifndef P_TMR7
+#define P_TMR7 P_UNDEF
+#endif
+
+#ifndef P_TWI1_SCL
+#define P_TWI1_SCL P_UNDEF
+#endif
+
+#ifndef P_TWI1_SDA
+#define P_TWI1_SDA P_UNDEF
+#endif
+
+#ifndef P_UART3_RTS
+#define P_UART3_RTS P_UNDEF
+#endif
+
+#ifndef P_UART3_CTS
+#define P_UART3_CTS P_UNDEF
+#endif
+
+#ifndef P_UART2_TX
+#define P_UART2_TX P_UNDEF
+#endif
+
+#ifndef P_UART2_RX
+#define P_UART2_RX P_UNDEF
+#endif
+
+#ifndef P_UART3_TX
+#define P_UART3_TX P_UNDEF
+#endif
+
+#ifndef P_UART3_RX
+#define P_UART3_RX P_UNDEF
+#endif
+
+#ifndef P_SPI2_SS
+#define P_SPI2_SS P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL1
+#define P_SPI2_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL2
+#define P_SPI2_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SSEL3
+#define P_SPI2_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_SPI2_SCK
+#define P_SPI2_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI2_MOSI
+#define P_SPI2_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI2_MISO
+#define P_SPI2_MISO P_UNDEF
+#endif
+
+#ifndef P_TMR0
+#define P_TMR0 P_UNDEF
+#endif
+
+#ifndef P_TMR1
+#define P_TMR1 P_UNDEF
+#endif
+
+#ifndef P_TMR2
+#define P_TMR2 P_UNDEF
+#endif
+
+#ifndef P_TMR3
+#define P_TMR3 P_UNDEF
+#endif
+
+#ifndef P_SPORT0_TFS
+#define P_SPORT0_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DTSEC
+#define P_SPORT0_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DTPRI
+#define P_SPORT0_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT0_TSCLK
+#define P_SPORT0_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT0_RFS
+#define P_SPORT0_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DRSEC
+#define P_SPORT0_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT0_DRPRI
+#define P_SPORT0_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT0_RSCLK
+#define P_SPORT0_RSCLK P_UNDEF
+#endif
+
+#ifndef P_SD_D0
+#define P_SD_D0 P_UNDEF
+#endif
+
+#ifndef P_SD_D1
+#define P_SD_D1 P_UNDEF
+#endif
+
+#ifndef P_SD_D2
+#define P_SD_D2 P_UNDEF
+#endif
+
+#ifndef P_SD_D3
+#define P_SD_D3 P_UNDEF
+#endif
+
+#ifndef P_SD_CLK
+#define P_SD_CLK P_UNDEF
+#endif
+
+#ifndef P_SD_CMD
+#define P_SD_CMD P_UNDEF
+#endif
+
+#ifndef P_MMCLK
+#define P_MMCLK P_UNDEF
+#endif
+
+#ifndef P_MBCLK
+#define P_MBCLK P_UNDEF
+#endif
+
+#ifndef P_PPI1_D0
+#define P_PPI1_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D1
+#define P_PPI1_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D2
+#define P_PPI1_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D3
+#define P_PPI1_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D4
+#define P_PPI1_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D5
+#define P_PPI1_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D6
+#define P_PPI1_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D7
+#define P_PPI1_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D8
+#define P_PPI1_D8 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D9
+#define P_PPI1_D9 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D10
+#define P_PPI1_D10 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D11
+#define P_PPI1_D11 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D12
+#define P_PPI1_D12 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D13
+#define P_PPI1_D13 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D14
+#define P_PPI1_D14 P_UNDEF
+#endif
+
+#ifndef P_PPI1_D15
+#define P_PPI1_D15 P_UNDEF
+#endif
+
+#ifndef P_HOST_D8
+#define P_HOST_D8 P_UNDEF
+#endif
+
+#ifndef P_HOST_D9
+#define P_HOST_D9 P_UNDEF
+#endif
+
+#ifndef P_HOST_D10
+#define P_HOST_D10 P_UNDEF
+#endif
+
+#ifndef P_HOST_D11
+#define P_HOST_D11 P_UNDEF
+#endif
+
+#ifndef P_HOST_D12
+#define P_HOST_D12 P_UNDEF
+#endif
+
+#ifndef P_HOST_D13
+#define P_HOST_D13 P_UNDEF
+#endif
+
+#ifndef P_HOST_D14
+#define P_HOST_D14 P_UNDEF
+#endif
+
+#ifndef P_HOST_D15
+#define P_HOST_D15 P_UNDEF
+#endif
+
+#ifndef P_HOST_D0
+#define P_HOST_D0 P_UNDEF
+#endif
+
+#ifndef P_HOST_D1
+#define P_HOST_D1 P_UNDEF
+#endif
+
+#ifndef P_HOST_D2
+#define P_HOST_D2 P_UNDEF
+#endif
+
+#ifndef P_HOST_D3
+#define P_HOST_D3 P_UNDEF
+#endif
+
+#ifndef P_HOST_D4
+#define P_HOST_D4 P_UNDEF
+#endif
+
+#ifndef P_HOST_D5
+#define P_HOST_D5 P_UNDEF
+#endif
+
+#ifndef P_HOST_D6
+#define P_HOST_D6 P_UNDEF
+#endif
+
+#ifndef P_HOST_D7
+#define P_HOST_D7 P_UNDEF
+#endif
+
+#ifndef P_SPORT1_TFS
+#define P_SPORT1_TFS P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DTSEC
+#define P_SPORT1_DTSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DTPRI
+#define P_SPORT1_DTPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT1_TSCLK
+#define P_SPORT1_TSCLK P_UNDEF
+#endif
+
+#ifndef P_SPORT1_RFS
+#define P_SPORT1_RFS P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DRSEC
+#define P_SPORT1_DRSEC P_UNDEF
+#endif
+
+#ifndef P_SPORT1_DRPRI
+#define P_SPORT1_DRPRI P_UNDEF
+#endif
+
+#ifndef P_SPORT1_RSCLK
+#define P_SPORT1_RSCLK P_UNDEF
+#endif
+
+#ifndef P_PPI2_D0
+#define P_PPI2_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D1
+#define P_PPI2_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D2
+#define P_PPI2_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D3
+#define P_PPI2_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D4
+#define P_PPI2_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D5
+#define P_PPI2_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D6
+#define P_PPI2_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI2_D7
+#define P_PPI2_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D18
+#define P_PPI0_D18 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D19
+#define P_PPI0_D19 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D20
+#define P_PPI0_D20 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D21
+#define P_PPI0_D21 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D22
+#define P_PPI0_D22 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D23
+#define P_PPI0_D23 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW0
+#define P_KEY_ROW0 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW1
+#define P_KEY_ROW1 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW2
+#define P_KEY_ROW2 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW3
+#define P_KEY_ROW3 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL0
+#define P_KEY_COL0 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL1
+#define P_KEY_COL1 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL2
+#define P_KEY_COL2 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL3
+#define P_KEY_COL3 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SCK
+#define P_SPI0_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI0_MISO
+#define P_SPI0_MISO P_UNDEF
+#endif
+
+#ifndef P_SPI0_MOSI
+#define P_SPI0_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI0_SS
+#define P_SPI0_SS P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL1
+#define P_SPI0_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL2
+#define P_SPI0_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI0_SSEL3
+#define P_SPI0_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_UART0_TX
+#define P_UART0_TX P_UNDEF
+#endif
+
+#ifndef P_UART0_RX
+#define P_UART0_RX P_UNDEF
+#endif
+
+#ifndef P_UART1_RTS
+#define P_UART1_RTS P_UNDEF
+#endif
+
+#ifndef P_UART1_CTS
+#define P_UART1_CTS P_UNDEF
+#endif
+
+#ifndef P_PPI1_CLK
+#define P_PPI1_CLK P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS1
+#define P_PPI1_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS2
+#define P_PPI1_FS2 P_UNDEF
+#endif
+
+#ifndef P_TWI0_SCL
+#define P_TWI0_SCL P_UNDEF
+#endif
+
+#ifndef P_TWI0_SDA
+#define P_TWI0_SDA P_UNDEF
+#endif
+
+#ifndef P_KEY_COL7
+#define P_KEY_COL7 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW6
+#define P_KEY_ROW6 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL6
+#define P_KEY_COL6 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW5
+#define P_KEY_ROW5 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL5
+#define P_KEY_COL5 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW4
+#define P_KEY_ROW4 P_UNDEF
+#endif
+
+#ifndef P_KEY_COL4
+#define P_KEY_COL4 P_UNDEF
+#endif
+
+#ifndef P_KEY_ROW7
+#define P_KEY_ROW7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D0
+#define P_PPI0_D0 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D1
+#define P_PPI0_D1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D2
+#define P_PPI0_D2 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D3
+#define P_PPI0_D3 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D4
+#define P_PPI0_D4 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D5
+#define P_PPI0_D5 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D6
+#define P_PPI0_D6 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D7
+#define P_PPI0_D7 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D8
+#define P_PPI0_D8 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D9
+#define P_PPI0_D9 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D10
+#define P_PPI0_D10 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D11
+#define P_PPI0_D11 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D12
+#define P_PPI0_D12 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D13
+#define P_PPI0_D13 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D14
+#define P_PPI0_D14 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D15
+#define P_PPI0_D15 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D0A
+#define P_ATAPI_D0A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D1A
+#define P_ATAPI_D1A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D2A
+#define P_ATAPI_D2A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D3A
+#define P_ATAPI_D3A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D4A
+#define P_ATAPI_D4A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D5A
+#define P_ATAPI_D5A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D6A
+#define P_ATAPI_D6A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D7A
+#define P_ATAPI_D7A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D8A
+#define P_ATAPI_D8A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D9A
+#define P_ATAPI_D9A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D10A
+#define P_ATAPI_D10A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D11A
+#define P_ATAPI_D11A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D12A
+#define P_ATAPI_D12A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D13A
+#define P_ATAPI_D13A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D14A
+#define P_ATAPI_D14A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_D15A
+#define P_ATAPI_D15A P_UNDEF
+#endif
+
+#ifndef P_PPI0_CLK
+#define P_PPI0_CLK P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS1
+#define P_PPI0_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS2
+#define P_PPI0_FS2 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D16
+#define P_PPI0_D16 P_UNDEF
+#endif
+
+#ifndef P_PPI0_D17
+#define P_PPI0_D17 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL1
+#define P_SPI1_SSEL1 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL2
+#define P_SPI1_SSEL2 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SSEL3
+#define P_SPI1_SSEL3 P_UNDEF
+#endif
+
+#ifndef P_SPI1_SCK
+#define P_SPI1_SCK P_UNDEF
+#endif
+
+#ifndef P_SPI1_MISO
+#define P_SPI1_MISO P_UNDEF
+#endif
+
+#ifndef P_SPI1_MOSI
+#define P_SPI1_MOSI P_UNDEF
+#endif
+
+#ifndef P_SPI1_SS
+#define P_SPI1_SS P_UNDEF
+#endif
+
+#ifndef P_CAN0_TX
+#define P_CAN0_TX P_UNDEF
+#endif
+
+#ifndef P_CAN0_RX
+#define P_CAN0_RX P_UNDEF
+#endif
+
+#ifndef P_CAN1_TX
+#define P_CAN1_TX P_UNDEF
+#endif
+
+#ifndef P_CAN1_RX
+#define P_CAN1_RX P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A0A
+#define P_ATAPI_A0A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A1A
+#define P_ATAPI_A1A P_UNDEF
+#endif
+
+#ifndef P_ATAPI_A2A
+#define P_ATAPI_A2A P_UNDEF
+#endif
+
+#ifndef P_HOST_CE
+#define P_HOST_CE P_UNDEF
+#endif
+
+#ifndef P_HOST_RD
+#define P_HOST_RD P_UNDEF
+#endif
+
+#ifndef P_HOST_WR
+#define P_HOST_WR P_UNDEF
+#endif
+
+#ifndef P_MTXONB
+#define P_MTXONB P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS2
+#define P_PPI2_FS2 P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS1
+#define P_PPI2_FS1 P_UNDEF
+#endif
+
+#ifndef P_PPI2_CLK
+#define P_PPI2_CLK P_UNDEF
+#endif
+
+#ifndef P_CNT_CZM
+#define P_CNT_CZM P_UNDEF
+#endif
+
+#ifndef P_UART1_TX
+#define P_UART1_TX P_UNDEF
+#endif
+
+#ifndef P_UART1_RX
+#define P_UART1_RX P_UNDEF
+#endif
+
+#ifndef P_ATAPI_RESET
+#define P_ATAPI_RESET P_UNDEF
+#endif
+
+#ifndef P_HOST_ADDR
+#define P_HOST_ADDR P_UNDEF
+#endif
+
+#ifndef P_HOST_ACK
+#define P_HOST_ACK P_UNDEF
+#endif
+
+#ifndef P_MTX
+#define P_MTX P_UNDEF
+#endif
+
+#ifndef P_MRX
+#define P_MRX P_UNDEF
+#endif
+
+#ifndef P_MRXONB
+#define P_MRXONB P_UNDEF
+#endif
+
+#ifndef P_A4
+#define P_A4 P_UNDEF
+#endif
+
+#ifndef P_A5
+#define P_A5 P_UNDEF
+#endif
+
+#ifndef P_A6
+#define P_A6 P_UNDEF
+#endif
+
+#ifndef P_A7
+#define P_A7 P_UNDEF
+#endif
+
+#ifndef P_A8
+#define P_A8 P_UNDEF
+#endif
+
+#ifndef P_A9
+#define P_A9 P_UNDEF
+#endif
+
+#ifndef P_PPI1_FS3
+#define P_PPI1_FS3 P_UNDEF
+#endif
+
+#ifndef P_PPI2_FS3
+#define P_PPI2_FS3 P_UNDEF
+#endif
+
+#ifndef P_TMR8
+#define P_TMR8 P_UNDEF
+#endif
+
+#ifndef P_TMR9
+#define P_TMR9 P_UNDEF
+#endif
+
+#ifndef P_TMR10
+#define P_TMR10 P_UNDEF
+#endif
+#ifndef P_TMR11
+#define P_TMR11 P_UNDEF
+#endif
+
+#ifndef P_DMAR0
+#define P_DMAR0 P_UNDEF
+#endif
+
+#ifndef P_DMAR1
+#define P_DMAR1 P_UNDEF
+#endif
+
+#ifndef P_PPI0_FS3
+#define P_PPI0_FS3 P_UNDEF
+#endif
+
+#ifndef P_CNT_CDG
+#define P_CNT_CDG P_UNDEF
+#endif
+
+#ifndef P_CNT_CUD
+#define P_CNT_CUD P_UNDEF
+#endif
+
+#ifndef P_A10
+#define P_A10 P_UNDEF
+#endif
+
+#ifndef P_A11
+#define P_A11 P_UNDEF
+#endif
+
+#ifndef P_A12
+#define P_A12 P_UNDEF
+#endif
+
+#ifndef P_A13
+#define P_A13 P_UNDEF
+#endif
+
+#ifndef P_A14
+#define P_A14 P_UNDEF
+#endif
+
+#ifndef P_A15
+#define P_A15 P_UNDEF
+#endif
+
+#ifndef P_A16
+#define P_A16 P_UNDEF
+#endif
+
+#ifndef P_A17
+#define P_A17 P_UNDEF
+#endif
+
+#ifndef P_A18
+#define P_A18 P_UNDEF
+#endif
+
+#ifndef P_A19
+#define P_A19 P_UNDEF
+#endif
+
+#ifndef P_A20
+#define P_A20 P_UNDEF
+#endif
+
+#ifndef P_A21
+#define P_A21 P_UNDEF
+#endif
+
+#ifndef P_A22
+#define P_A22 P_UNDEF
+#endif
+
+#ifndef P_A23
+#define P_A23 P_UNDEF
+#endif
+
+#ifndef P_A24
+#define P_A24 P_UNDEF
+#endif
+
+#ifndef P_A25
+#define P_A25 P_UNDEF
+#endif
+
+#ifndef P_NOR_CLK
+#define P_NOR_CLK P_UNDEF
+#endif
+
+#ifndef P_TMRCLK
+#define P_TMRCLK P_UNDEF
+#endif
+
+#ifndef P_AMC_ARDY_NOR_WAIT
+#define P_AMC_ARDY_NOR_WAIT P_UNDEF
+#endif
+
+#ifndef P_NAND_CE
+#define P_NAND_CE P_UNDEF
+#endif
+
+#ifndef P_NAND_RB
+#define P_NAND_RB P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DIOR
+#define P_ATAPI_DIOR P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DIOW
+#define P_ATAPI_DIOW P_UNDEF
+#endif
+
+#ifndef P_ATAPI_CS0
+#define P_ATAPI_CS0 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_CS1
+#define P_ATAPI_CS1 P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DMACK
+#define P_ATAPI_DMACK P_UNDEF
+#endif
+
+#ifndef P_ATAPI_DMARQ
+#define P_ATAPI_DMARQ P_UNDEF
+#endif
+
+#ifndef P_ATAPI_INTRQ
+#define P_ATAPI_INTRQ P_UNDEF
+#endif
+
+#ifndef P_ATAPI_IORDY
+#define P_ATAPI_IORDY P_UNDEF
+#endif
+
+#ifndef P_AMC_BR
+#define P_AMC_BR P_UNDEF
+#endif
+
+#ifndef P_AMC_BG
+#define P_AMC_BG P_UNDEF
+#endif
+
+#ifndef P_AMC_BGH
+#define P_AMC_BGH P_UNDEF
+#endif
+
+/* EMAC */
+
+#ifndef P_MII0_ETxD0
+#define P_MII0_ETxD0 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD1
+#define P_MII0_ETxD1 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD2
+#define P_MII0_ETxD2 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxD3
+#define P_MII0_ETxD3 P_UNDEF
+#endif
+
+#ifndef P_MII0_ETxEN
+#define P_MII0_ETxEN P_UNDEF
+#endif
+
+#ifndef P_MII0_TxCLK
+#define P_MII0_TxCLK P_UNDEF
+#endif
+
+#ifndef P_MII0_PHYINT
+#define P_MII0_PHYINT P_UNDEF
+#endif
+
+#ifndef P_MII0_COL
+#define P_MII0_COL P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD0
+#define P_MII0_ERxD0 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD1
+#define P_MII0_ERxD1 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD2
+#define P_MII0_ERxD2 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxD3
+#define P_MII0_ERxD3 P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxDV
+#define P_MII0_ERxDV P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxCLK
+#define P_MII0_ERxCLK P_UNDEF
+#endif
+
+#ifndef P_MII0_ERxER
+#define P_MII0_ERxER P_UNDEF
+#endif
+
+#ifndef P_MII0_CRS
+#define P_MII0_CRS P_UNDEF
+#endif
+
+#ifndef P_RMII0_REF_CLK
+#define P_RMII0_REF_CLK P_UNDEF
+#endif
+
+#ifndef P_RMII0_MDINT
+#define P_RMII0_MDINT P_UNDEF
+#endif
+
+#ifndef P_RMII0_CRS_DV
+#define P_RMII0_CRS_DV P_UNDEF
+#endif
+
+#ifndef P_MDC
+#define P_MDC P_UNDEF
+#endif
+
+#ifndef P_MDIO
+#define P_MDIO P_UNDEF
+#endif
+
+#endif /* _PORTMUX_H_ */
diff --git a/include/asm-blackfin/processor.h b/include/asm-blackfin/processor.h
index aba2b30a8ed..6bb3e0d4705 100644
--- a/include/asm-blackfin/processor.h
+++ b/include/asm-blackfin/processor.h
@@ -124,6 +124,10 @@ static inline __attribute_pure__ uint32_t bfin_compiled_revid(void)
return 4;
#elif defined(CONFIG_BF_REV_0_5)
return 5;
+#elif defined(CONFIG_BF_REV_ANY)
+ return 0xffff;
+#else
+ return -1;
#endif
}
diff --git a/include/asm-blackfin/termbits.h b/include/asm-blackfin/termbits.h
index 2fd9dabdba7..4eac38de8ce 100644
--- a/include/asm-blackfin/termbits.h
+++ b/include/asm-blackfin/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-blackfin/trace.h b/include/asm-blackfin/trace.h
new file mode 100644
index 00000000000..9c2474c9a58
--- /dev/null
+++ b/include/asm-blackfin/trace.h
@@ -0,0 +1,52 @@
+/*
+ * Common header file for blackfin family of processors.
+ *
+ */
+
+#ifndef _BLACKFIN_TRACE_
+#define _BLACKFIN_TRACE_
+
+#ifndef __ASSEMBLY__
+/* Trace Macros for C files */
+
+#define trace_buffer_save(x) \
+ do { \
+ (x) = bfin_read_TBUFCTL(); \
+ bfin_write_TBUFCTL((x) & ~TBUFEN); \
+ } while (0)
+
+#define trace_buffer_restore(x) \
+ do { \
+ bfin_write_TBUFCTL((x)); \
+ } while (0)
+
+#else
+/* Trace Macros for Assembly files */
+
+#define TRACE_BUFFER_START(preg, dreg) trace_buffer_start(preg, dreg)
+#define TRACE_BUFFER_STOP(preg, dreg) trace_buffer_stop(preg, dreg)
+
+#define trace_buffer_stop(preg, dreg) \
+ preg.L = LO(TBUFCTL); \
+ preg.H = HI(TBUFCTL); \
+ dreg = 0x1; \
+ [preg] = dreg;
+
+#define trace_buffer_start(preg, dreg) \
+ preg.L = LO(TBUFCTL); \
+ preg.H = HI(TBUFCTL); \
+ dreg = 0x13; \
+ [preg] = dreg;
+
+#ifdef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
+# define DEBUG_START_HWTRACE(preg, dreg) trace_buffer_start(preg, dreg)
+# define DEBUG_STOP_HWTRACE(preg, dreg) trace_buffer_stop(preg, dreg)
+
+#else
+# define DEBUG_START_HWTRACE(preg, dreg)
+# define DEBUG_STOP_HWTRACE(preg, dreg)
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _BLACKFIN_TRACE_ */
diff --git a/include/asm-blackfin/unistd.h b/include/asm-blackfin/unistd.h
index 4df8790a67d..0df9f2d322a 100644
--- a/include/asm-blackfin/unistd.h
+++ b/include/asm-blackfin/unistd.h
@@ -369,7 +369,6 @@
#define __ARCH_WANT_SYS_NICE
#define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#endif
/*
* "Conditional" syscalls
@@ -379,4 +378,6 @@
*/
#define cond_syscall(x) asm(".weak\t_" #x "\n\t.set\t_" #x ",_sys_ni_syscall");
+#endif /* __KERNEL__ */
+
#endif /* __ASM_BFIN_UNISTD_H */
diff --git a/include/asm-cris/pci.h b/include/asm-cris/pci.h
index b2ac8a331da..730ce40fdd0 100644
--- a/include/asm-cris/pci.h
+++ b/include/asm-cris/pci.h
@@ -52,47 +52,11 @@ struct pci_dev;
#define pci_unmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask) (1)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
- return ((dma64_addr_t) page_to_phys(page) +
- (dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- return pfn_to_page(dma_addr >> PAGE_SHIFT);
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
#define HAVE_PCI_MMAP
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* __KERNEL__ */
/* implement the pci_ DMA API in terms of the generic device dma_ one */
diff --git a/include/asm-cris/termbits.h b/include/asm-cris/termbits.h
index 8d8cec225fe..6cc2e2736f7 100644
--- a/include/asm-cris/termbits.h
+++ b/include/asm-cris/termbits.h
@@ -19,6 +19,17 @@ struct termios {
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 */
diff --git a/include/asm-frv/pci.h b/include/asm-frv/pci.h
index f35a4511e7b..585d9b49949 100644
--- a/include/asm-frv/pci.h
+++ b/include/asm-frv/pci.h
@@ -22,10 +22,6 @@ struct pci_dev;
#define pcibios_assign_all_busses() 0
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
extern void pcibios_set_master(struct pci_dev *dev);
extern void pcibios_penalize_isa_irq(int irq);
@@ -44,9 +40,6 @@ extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle);
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask) (1)
-
/* Return the index of the PCI controller for device PDEV. */
#define pci_controller_num(PDEV) (0)
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index 2687c771512..114aefae270 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -25,7 +25,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/spinlock.h>
-struct mm_struct;
+#include <linux/sched.h>
struct vm_area_struct;
#endif
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index be303b3eef4..6931af525da 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -12,6 +12,7 @@
#ifndef _ASM_SYSTEM_H
#define _ASM_SYSTEM_H
+#include <linux/types.h>
#include <linux/linkage.h>
struct thread_struct;
diff --git a/include/asm-frv/termbits.h b/include/asm-frv/termbits.h
index 2d6d389cff4..74851b424d4 100644
--- a/include/asm-frv/termbits.h
+++ b/include/asm-frv/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-frv/uaccess.h b/include/asm-frv/uaccess.h
index 3d90e1018ee..53650c958f4 100644
--- a/include/asm-frv/uaccess.h
+++ b/include/asm-frv/uaccess.h
@@ -277,6 +277,8 @@ extern long __memcpy_user(void *dst, const void *src, unsigned long count);
#endif
+#define __clear_user clear_user
+
static inline unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n)
{
diff --git a/include/asm-generic/bitops/sched.h b/include/asm-generic/bitops/sched.h
index 815bb014806..604fab7031a 100644
--- a/include/asm-generic/bitops/sched.h
+++ b/include/asm-generic/bitops/sched.h
@@ -6,28 +6,23 @@
/*
* Every architecture must define this function. It's the fastest
- * way of searching a 140-bit bitmap where the first 100 bits are
- * unlikely to be set. It's guaranteed that at least one of the 140
- * bits is cleared.
+ * way of searching a 100-bit bitmap. It's guaranteed that at least
+ * one of the 100 bits is cleared.
*/
static inline int sched_find_first_bit(const unsigned long *b)
{
#if BITS_PER_LONG == 64
- if (unlikely(b[0]))
+ if (b[0])
return __ffs(b[0]);
- if (likely(b[1]))
- return __ffs(b[1]) + 64;
- return __ffs(b[2]) + 128;
+ return __ffs(b[1]) + 64;
#elif BITS_PER_LONG == 32
- if (unlikely(b[0]))
+ if (b[0])
return __ffs(b[0]);
- if (unlikely(b[1]))
+ if (b[1])
return __ffs(b[1]) + 32;
- if (unlikely(b[2]))
+ if (b[2])
return __ffs(b[2]) + 64;
- if (b[3])
- return __ffs(b[3]) + 96;
- return __ffs(b[4]) + 128;
+ return __ffs(b[3]) + 96;
#else
#error BITS_PER_LONG not defined
#endif
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index dc8f99ee305..7d7bcf990e9 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -27,13 +27,20 @@ do { \
* Largely same as above, but only sets the access flags (dirty,
* accessed, and writable). Furthermore, we know it always gets set
* to a "more permissive" setting, which allows most architectures
- * to optimize this.
+ * to optimize this. We return whether the PTE actually changed, which
+ * in turn instructs the caller to do things like update__mmu_cache.
+ * This used to be done in the caller, but sparc needs minor faults to
+ * force that call on sun4c so we changed this macro slightly
*/
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-do { \
- set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
- flush_tlb_page(__vma, __address); \
-} while (0)
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) { \
+ set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+ flush_tlb_page(__vma, __address); \
+ } \
+ __changed; \
+})
#endif
#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8307b1bb337..84155eb67f1 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -14,8 +14,8 @@
*(.data) \
*(.data.init.refok)
-#define RODATA \
- . = ALIGN(4096); \
+#define RO_DATA(align) \
+ . = ALIGN((align)); \
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_rodata) = .; \
*(.rodata) *(.rodata.*) \
@@ -135,7 +135,11 @@
VMLINUX_SYMBOL(__end_rodata) = .; \
} \
\
- . = ALIGN(4096);
+ . = ALIGN((align));
+
+/* RODATA provided for backward compatibility.
+ * All archs are supposed to use RO_DATA() */
+#define RODATA RO_DATA(4096)
#define SECURITY_INIT \
.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
diff --git a/include/asm-h8300/pci.h b/include/asm-h8300/pci.h
index 0c771b05fdd..97389b35aa3 100644
--- a/include/asm-h8300/pci.h
+++ b/include/asm-h8300/pci.h
@@ -22,8 +22,4 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
#define PCI_DMA_BUS_IS_PHYS (1)
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* _ASM_H8300_PCI_H */
diff --git a/include/asm-h8300/processor.h b/include/asm-h8300/processor.h
index 99b664aa208..49fc886a623 100644
--- a/include/asm-h8300/processor.h
+++ b/include/asm-h8300/processor.h
@@ -78,7 +78,7 @@ struct thread_struct {
do { \
set_fs(USER_DS); /* reads from user space */ \
(_regs)->pc = (_pc); \
- (_regs)->ccr &= 0x00; /* clear kernel flag */ \
+ (_regs)->ccr = 0x00; /* clear all flags */ \
(_regs)->er5 = current->mm->start_data; /* GOT base */ \
wrusp((unsigned long)(_usp) - sizeof(unsigned long)*3); \
} while(0)
diff --git a/include/asm-h8300/termbits.h b/include/asm-h8300/termbits.h
index 6a1f4d3807b..e877b40ac5b 100644
--- a/include/asm-h8300/termbits.h
+++ b/include/asm-h8300/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-i386/boot.h b/include/asm-i386/boot.h
index bd024ab4fe5..ed8affbf96c 100644
--- a/include/asm-i386/boot.h
+++ b/include/asm-i386/boot.h
@@ -1,5 +1,5 @@
-#ifndef _LINUX_BOOT_H
-#define _LINUX_BOOT_H
+#ifndef _ASM_BOOT_H
+#define _ASM_BOOT_H
/* Don't touch these, unless you really know what you're doing. */
#define DEF_INITSEG 0x9000
@@ -17,4 +17,4 @@
+ (CONFIG_PHYSICAL_ALIGN - 1)) \
& ~(CONFIG_PHYSICAL_ALIGN - 1))
-#endif /* _LINUX_BOOT_H */
+#endif /* _ASM_BOOT_H */
diff --git a/include/asm-i386/bootparam.h b/include/asm-i386/bootparam.h
new file mode 100644
index 00000000000..427d8652bfd
--- /dev/null
+++ b/include/asm-i386/bootparam.h
@@ -0,0 +1,85 @@
+#ifndef _ASM_BOOTPARAM_H
+#define _ASM_BOOTPARAM_H
+
+#include <linux/types.h>
+#include <linux/screen_info.h>
+#include <linux/apm_bios.h>
+#include <asm/e820.h>
+#include <linux/edd.h>
+#include <video/edid.h>
+
+struct setup_header {
+ u8 setup_sects;
+ u16 root_flags;
+ u32 syssize;
+ u16 ram_size;
+ u16 vid_mode;
+ u16 root_dev;
+ u16 boot_flag;
+ u16 jump;
+ u32 header;
+ u16 version;
+ u32 realmode_swtch;
+ u16 start_sys;
+ u16 kernel_version;
+ u8 type_of_loader;
+ u8 loadflags;
+#define LOADED_HIGH 0x01
+#define CAN_USE_HEAP 0x80
+ u16 setup_move_size;
+ u32 code32_start;
+ u32 ramdisk_image;
+ u32 ramdisk_size;
+ u32 bootsect_kludge;
+ u16 heap_end_ptr;
+ u16 _pad1;
+ u32 cmd_line_ptr;
+ u32 initrd_addr_max;
+ u32 kernel_alignment;
+ u8 relocatable_kernel;
+} __attribute__((packed));
+
+struct sys_desc_table {
+ u16 length;
+ u8 table[14];
+};
+
+struct efi_info {
+ u32 _pad1;
+ u32 efi_systab;
+ u32 efi_memdesc_size;
+ u32 efi_memdec_version;
+ u32 efi_memmap;
+ u32 fi_memmap_size;
+ u32 _pad2[2];
+};
+
+/* The so-called "zeropage" */
+struct boot_params {
+ struct screen_info screen_info; /* 0x000 */
+ struct apm_bios_info apm_bios_info; /* 0x040 */
+ u8 _pad2[12]; /* 0x054 */
+ u32 speedstep_info[4]; /* 0x060 */
+ u8 _pad3[16]; /* 0x070 */
+ u8 hd0_info[16]; /* obsolete! */ /* 0x080 */
+ u8 hd1_info[16]; /* obsolete! */ /* 0x090 */
+ struct sys_desc_table sys_desc_table; /* 0x0a0 */
+ u8 _pad4[144]; /* 0x0b0 */
+ struct edid_info edid_info; /* 0x140 */
+ struct efi_info efi_info; /* 0x1c0 */
+ u32 alt_mem_k; /* 0x1e0 */
+ u32 scratch; /* Scratch field! */ /* 0x1e4 */
+ u8 e820_entries; /* 0x1e8 */
+ u8 eddbuf_entries; /* 0x1e9 */
+ u8 edd_mbr_sig_buf_entries; /* 0x1ea */
+ u8 _pad6[6]; /* 0x1eb */
+ struct setup_header hdr; /* setup header */ /* 0x1f1 */
+ u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
+ u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */
+ struct e820entry e820_map[E820MAX]; /* 0x2d0 */
+ u8 _pad8[48]; /* 0xcd0 */
+ struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */
+ u8 _pad9[276]; /* 0xeec */
+} __attribute__((packed));
+
+#endif /* _ASM_BOOTPARAM_H */
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index f514e906643..c961c03cf1e 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -12,7 +12,7 @@
#endif
#include <asm/required-features.h>
-#define NCAPINTS 7 /* N 32-bit words worth of info */
+#define NCAPINTS 8 /* N 32-bit words worth of info */
/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */
@@ -81,6 +81,7 @@
#define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */
#define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14) /* lapic timer broken in C1 */
#define X86_FEATURE_SYNC_RDTSC (3*32+15) /* RDTSC synchronizes the CPU */
+#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
@@ -108,11 +109,24 @@
#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */
#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */
-#define cpu_has(c, bit) \
- ((__builtin_constant_p(bit) && (bit) < 32 && \
- (1UL << (bit)) & REQUIRED_MASK1) ? \
- 1 : \
- test_bit(bit, (c)->x86_capability))
+/*
+ * Auxiliary flags: Linux defined - For features scattered in various
+ * CPUID levels like 0x6, 0xA etc
+ */
+#define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */
+
+#define cpu_has(c, bit) \
+ (__builtin_constant_p(bit) && \
+ ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) || \
+ (((bit)>>5)==1 && (1UL<<((bit)&31) & REQUIRED_MASK1)) || \
+ (((bit)>>5)==2 && (1UL<<((bit)&31) & REQUIRED_MASK2)) || \
+ (((bit)>>5)==3 && (1UL<<((bit)&31) & REQUIRED_MASK3)) || \
+ (((bit)>>5)==4 && (1UL<<((bit)&31) & REQUIRED_MASK4)) || \
+ (((bit)>>5)==5 && (1UL<<((bit)&31) & REQUIRED_MASK5)) || \
+ (((bit)>>5)==6 && (1UL<<((bit)&31) & REQUIRED_MASK6)) || \
+ (((bit)>>5)==7 && (1UL<<((bit)&31) & REQUIRED_MASK7)) ) \
+ ? 1 : \
+ test_bit(bit, (c)->x86_capability))
#define boot_cpu_has(bit) cpu_has(&boot_cpu_data, bit)
#define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU)
diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h
index 183eebeebbd..f1d72d177f6 100644
--- a/include/asm-i386/dma-mapping.h
+++ b/include/asm-i386/dma-mapping.h
@@ -123,6 +123,8 @@ dma_mapping_error(dma_addr_t dma_addr)
return 0;
}
+extern int forbid_dac;
+
static inline int
dma_supported(struct device *dev, u64 mask)
{
@@ -134,6 +136,10 @@ dma_supported(struct device *dev, u64 mask)
if(mask < 0x00ffffff)
return 0;
+ /* Work around chipset bugs */
+ if (forbid_dac > 0 && mask > 0xffffffffULL)
+ return 0;
+
return 1;
}
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h
index 096a2a8eb1d..c03290ccecb 100644
--- a/include/asm-i386/e820.h
+++ b/include/asm-i386/e820.h
@@ -25,13 +25,15 @@
#ifndef __ASSEMBLY__
+struct e820entry {
+ u64 addr; /* start of memory segment */
+ u64 size; /* size of memory segment */
+ u32 type; /* type of memory segment */
+} __attribute__((packed));
+
struct e820map {
- int nr_map;
- struct e820entry {
- unsigned long long addr; /* start of memory segment */
- unsigned long long size; /* size of memory segment */
- unsigned long type; /* type of memory segment */
- } map[E820MAX];
+ u32 nr_map;
+ struct e820entry map[E820MAX];
};
extern struct e820map e820;
diff --git a/include/asm-i386/mach-es7000/mach_apic.h b/include/asm-i386/mach-es7000/mach_apic.h
index 2d978928a39..caec64be516 100644
--- a/include/asm-i386/mach-es7000/mach_apic.h
+++ b/include/asm-i386/mach-es7000/mach_apic.h
@@ -73,6 +73,10 @@ static inline void init_apic_ldr(void)
apic_write_around(APIC_LDR, val);
}
+#ifndef CONFIG_X86_GENERICARCH
+extern void enable_apic_mode(void);
+#endif
+
extern int apic_version [MAX_APICS];
static inline void setup_apic_routing(void)
{
diff --git a/include/asm-i386/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h
index b9fb784e1fd..8aa10547b4b 100644
--- a/include/asm-i386/mach-es7000/mach_mpparse.h
+++ b/include/asm-i386/mach-es7000/mach_mpparse.h
@@ -18,6 +18,12 @@ extern int parse_unisys_oem (char *oemptr);
extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
extern void setup_unisys(void);
+#ifndef CONFIG_X86_GENERICARCH
+extern int acpi_madt_oem_check(char *oem_id, char *oem_table_id);
+extern int mps_oem_check(struct mp_config_table *mpc, char *oem,
+ char *productid);
+#endif
+
#ifdef CONFIG_ACPI
static inline int es7000_check_dsdt(void)
diff --git a/include/asm-i386/paravirt.h b/include/asm-i386/paravirt.h
index d7a0512f88e..7f846a7d6bc 100644
--- a/include/asm-i386/paravirt.h
+++ b/include/asm-i386/paravirt.h
@@ -539,7 +539,7 @@ static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
val = paravirt_read_msr(msr, &_err); \
} while(0)
-#define wrmsrl(msr,val) ((void)paravirt_write_msr(msr, val, 0))
+#define wrmsrl(msr,val) wrmsr(msr, (u32)((u64)(val)), ((u64)(val))>>32)
#define wrmsr_safe(msr,a,b) paravirt_write_msr(msr, a, b)
/* rdmsr with exception handling */
diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h
index 64b6d0baedb..392d3fe5d45 100644
--- a/include/asm-i386/pci.h
+++ b/include/asm-i386/pci.h
@@ -56,48 +56,11 @@ struct pci_dev;
#define pci_unmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask) (1)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
- return ((dma64_addr_t) page_to_phys(page) +
- (dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- return pfn_to_page(dma_addr >> PAGE_SHIFT);
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
- flush_write_buffers();
-}
-
#define HAVE_PCI_MMAP
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 2394589786b..628fa7747d0 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -285,32 +285,36 @@ static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
*/
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define ptep_set_access_flags(vma, address, ptep, entry, dirty) \
-do { \
- if (dirty) { \
+({ \
+ int __changed = !pte_same(*(ptep), entry); \
+ if (__changed && dirty) { \
(ptep)->pte_low = (entry).pte_low; \
pte_update_defer((vma)->vm_mm, (address), (ptep)); \
flush_tlb_page(vma, address); \
} \
-} while (0)
+ __changed; \
+})
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
#define ptep_test_and_clear_dirty(vma, addr, ptep) ({ \
- int ret = 0; \
- if (pte_dirty(*ptep)) \
- ret = test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); \
- if (ret) \
- pte_update_defer(vma->vm_mm, addr, ptep); \
- ret; \
+ int __ret = 0; \
+ if (pte_dirty(*(ptep))) \
+ __ret = test_and_clear_bit(_PAGE_BIT_DIRTY, \
+ &(ptep)->pte_low); \
+ if (__ret) \
+ pte_update((vma)->vm_mm, addr, ptep); \
+ __ret; \
})
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define ptep_test_and_clear_young(vma, addr, ptep) ({ \
- int ret = 0; \
- if (pte_young(*ptep)) \
- ret = test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); \
- if (ret) \
- pte_update_defer(vma->vm_mm, addr, ptep); \
- ret; \
+ int __ret = 0; \
+ if (pte_young(*(ptep))) \
+ __ret = test_and_clear_bit(_PAGE_BIT_ACCESSED, \
+ &(ptep)->pte_low); \
+ if (__ret) \
+ pte_update((vma)->vm_mm, addr, ptep); \
+ __ret; \
})
/*
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 338668bfb0a..94e0c147c16 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -119,6 +119,7 @@ void __init cpu_detect(struct cpuinfo_x86 *c);
extern void identify_boot_cpu(void);
extern void identify_secondary_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
+extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
extern unsigned short num_cache_leaves;
diff --git a/include/asm-i386/required-features.h b/include/asm-i386/required-features.h
index 9db866c1e64..65848a00705 100644
--- a/include/asm-i386/required-features.h
+++ b/include/asm-i386/required-features.h
@@ -3,32 +3,53 @@
/* Define minimum CPUID feature set for kernel These bits are checked
really early to actually display a visible error message before the
- kernel dies. Only add word 0 bits here
+ kernel dies. Make sure to assign features to the proper mask!
Some requirements that are not in CPUID yet are also in the
- CONFIG_X86_MINIMUM_CPU mode which is checked too.
+ CONFIG_X86_MINIMUM_CPU_FAMILY which is checked too.
The real information is in arch/i386/Kconfig.cpu, this just converts
the CONFIGs into a bitmask */
+#ifndef CONFIG_MATH_EMULATION
+# define NEED_FPU (1<<(X86_FEATURE_FPU & 31))
+#else
+# define NEED_FPU 0
+#endif
+
#ifdef CONFIG_X86_PAE
-#define NEED_PAE (1<<X86_FEATURE_PAE)
+# define NEED_PAE (1<<(X86_FEATURE_PAE & 31))
#else
-#define NEED_PAE 0
+# define NEED_PAE 0
#endif
#ifdef CONFIG_X86_CMOV
-#define NEED_CMOV (1<<X86_FEATURE_CMOV)
+# define NEED_CMOV (1<<(X86_FEATURE_CMOV & 31))
#else
-#define NEED_CMOV 0
+# define NEED_CMOV 0
#endif
#ifdef CONFIG_X86_CMPXCHG64
-#define NEED_CMPXCHG64 (1<<X86_FEATURE_CX8)
+# define NEED_CX8 (1<<(X86_FEATURE_CX8 & 31))
+#else
+# define NEED_CX8 0
+#endif
+
+#define REQUIRED_MASK0 (NEED_FPU|NEED_PAE|NEED_CMOV|NEED_CX8)
+
+#ifdef CONFIG_X86_USE_3DNOW
+# define NEED_3DNOW (1<<(X86_FEATURE_3DNOW & 31))
#else
-#define NEED_CMPXCHG64 0
+# define NEED_3DNOW 0
#endif
-#define REQUIRED_MASK1 (NEED_PAE|NEED_CMOV|NEED_CMPXCHG64)
+#define REQUIRED_MASK1 (NEED_3DNOW)
+
+#define REQUIRED_MASK2 0
+#define REQUIRED_MASK3 0
+#define REQUIRED_MASK4 0
+#define REQUIRED_MASK5 0
+#define REQUIRED_MASK6 0
+#define REQUIRED_MASK7 0
#endif
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 0e8077cbfda..0d5bff9dc4a 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -26,12 +26,15 @@
#define NEW_CL_POINTER 0x228 /* Relative to real mode data */
#ifndef __ASSEMBLY__
+
+#include <asm/bootparam.h>
+
/*
* This is set up by the setup-routine at boot-time
*/
-extern unsigned char boot_params[PARAM_SIZE];
+extern struct boot_params boot_params;
-#define PARAM (boot_params)
+#define PARAM ((char *)&boot_params)
#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
#define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
@@ -39,8 +42,7 @@ extern unsigned char boot_params[PARAM_SIZE];
#define E820_MAP ((struct e820entry *) (PARAM+E820MAP))
#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
#define IST_INFO (*(struct ist_info *) (PARAM+0x60))
-#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
-#define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
+#define SYS_DESC_TABLE (*(struct sys_desc_table *)(PARAM+0xa0))
#define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
#define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
#define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index 41098f45968..edd5d01028d 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -48,6 +48,7 @@ enum {
IA64_MCA_RENDEZ_CHECKIN_NOTDONE = 0x0,
IA64_MCA_RENDEZ_CHECKIN_DONE = 0x1,
IA64_MCA_RENDEZ_CHECKIN_INIT = 0x2,
+ IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA = 0x3,
};
/* Information maintained by the MC infrastructure */
diff --git a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
index 5a5d1c2ce39..0149097b736 100644
--- a/include/asm-ia64/pci.h
+++ b/include/asm-ia64/pci.h
@@ -71,14 +71,6 @@ pcibios_penalize_isa_irq (int irq, int active)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
-/* The ia64 platform always supports 64-bit addressing. */
-#define pci_dac_dma_supported(pci_dev, mask) (1)
-#define pci_dac_page_to_dma(dev,pg,off,dir) ((dma_addr_t) page_to_bus(pg) + (off))
-#define pci_dac_dma_to_page(dev,dma_addr) (virt_to_page(bus_to_virt(dma_addr)))
-#define pci_dac_dma_to_offset(dev,dma_addr) offset_in_page(dma_addr)
-#define pci_dac_dma_sync_single_for_cpu(dev,dma_addr,len,dir) do { } while (0)
-#define pci_dac_dma_sync_single_for_device(dev,dma_addr,len,dir) do { mb(); } while (0)
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
@@ -104,10 +96,12 @@ extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
#define HAVE_PCI_LEGACY
extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
struct vm_area_struct *vma);
-extern ssize_t pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off,
- size_t count);
-extern ssize_t pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off,
- size_t count);
+extern ssize_t pci_read_legacy_io(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count);
+extern ssize_t pci_write_legacy_io(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count);
extern int pci_mmap_legacy_mem(struct kobject *kobj,
struct bin_attribute *attr,
struct vm_area_struct *vma);
@@ -143,10 +137,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
return (pci_domain_nr(bus) != 0);
}
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
extern void pcibios_resource_to_bus(struct pci_dev *dev,
struct pci_bus_region *region, struct resource *res);
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 670b706411b..6580f31b313 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -533,16 +533,23 @@ extern void lazy_mmu_prot_update (pte_t pte);
* daccess_bit in ivt.S).
*/
#ifdef CONFIG_SMP
-# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
-do { \
- if (__safely_writable) { \
- set_pte(__ptep, __entry); \
- flush_tlb_page(__vma, __addr); \
- } \
-} while (0)
+# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed && __safely_writable) { \
+ set_pte(__ptep, __entry); \
+ flush_tlb_page(__vma, __addr); \
+ } \
+ __changed; \
+})
#else
-# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
- ptep_establish(__vma, __addr, __ptep, __entry)
+# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) \
+ ptep_establish(__vma, __addr, __ptep, __entry); \
+ __changed; \
+})
#endif
# ifdef CONFIG_VIRTUAL_MEM_MAP
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 291e8ceed6e..676b31a08c6 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -32,6 +32,7 @@
#define SN_SAL_NO_FAULT_ZONE_VIRTUAL 0x02000010
#define SN_SAL_NO_FAULT_ZONE_PHYSICAL 0x02000011
#define SN_SAL_PRINT_ERROR 0x02000012
+#define SN_SAL_REGISTER_PMI_HANDLER 0x02000014
#define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant
#define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant
#define SN_SAL_GET_SAPIC_INFO 0x0200001d
@@ -680,6 +681,25 @@ sn_register_nofault_code(u64 start_addr, u64 end_addr, u64 return_addr,
}
/*
+ * Register or unregister a function to handle a PMI received by a CPU.
+ * Before calling the registered handler, SAL sets r1 to the value that
+ * was passed in as the global_pointer.
+ *
+ * If the handler pointer is NULL, then the currently registered handler
+ * will be unregistered.
+ *
+ * Returns 0 on success, or a negative value if an error occurred.
+ */
+static inline int
+sn_register_pmi_handler(u64 handler, u64 global_pointer)
+{
+ struct ia64_sal_retval ret_stuff;
+ ia64_sal_oemcall(&ret_stuff, SN_SAL_REGISTER_PMI_HANDLER, handler,
+ global_pointer, 0, 0, 0, 0, 0);
+ return ret_stuff.status;
+}
+
+/*
* Change or query the coherence domain for this partition. Each cpu-based
* nasid is represented by a bit in an array of 64-bit words:
* 0 = not in this partition's coherency domain
@@ -696,8 +716,8 @@ static inline int
sn_change_coherence(u64 *new_domain, u64 *old_domain)
{
struct ia64_sal_retval ret_stuff;
- ia64_sal_oemcall(&ret_stuff, SN_SAL_COHERENCE, (u64)new_domain,
- (u64)old_domain, 0, 0, 0, 0, 0);
+ ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_COHERENCE, (u64)new_domain,
+ (u64)old_domain, 0, 0, 0, 0, 0);
return ret_stuff.status;
}
diff --git a/include/asm-ia64/termbits.h b/include/asm-ia64/termbits.h
index 4531a511bde..7fae3109ef4 100644
--- a/include/asm-ia64/termbits.h
+++ b/include/asm-ia64/termbits.h
@@ -26,6 +26,17 @@ struct termios {
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 */
diff --git a/include/asm-m32r/termbits.h b/include/asm-m32r/termbits.h
index e402641dfba..6be3b8a3984 100644
--- a/include/asm-m32r/termbits.h
+++ b/include/asm-m32r/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-m68k/mmzone.h b/include/asm-m68k/mmzone.h
new file mode 100644
index 00000000000..e1f1ec7b700
--- /dev/null
+++ b/include/asm-m68k/mmzone.h
@@ -0,0 +1,9 @@
+#ifndef _ASM_M68K_MMZONE_H_
+#define _ASM_M68K_MMZONE_H_
+
+extern pg_data_t pg_data_map[];
+
+#define NODE_DATA(nid) (&pg_data_map[nid])
+#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map)
+
+#endif /* _ASM_M68K_MMZONE_H_ */
diff --git a/include/asm-m68k/module.h b/include/asm-m68k/module.h
index c6d75af2d8d..382d20a6fc1 100644
--- a/include/asm-m68k/module.h
+++ b/include/asm-m68k/module.h
@@ -1,7 +1,39 @@
#ifndef _ASM_M68K_MODULE_H
#define _ASM_M68K_MODULE_H
-struct mod_arch_specific { };
+
+struct mod_arch_specific {
+ struct m68k_fixup_info *fixup_start, *fixup_end;
+};
+
+#define MODULE_ARCH_INIT { \
+ .fixup_start = __start_fixup, \
+ .fixup_end = __stop_fixup, \
+}
+
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Ehdr Elf32_Ehdr
+
+
+enum m68k_fixup_type {
+ m68k_fixup_memoffset,
+ m68k_fixup_vnode_shift,
+};
+
+struct m68k_fixup_info {
+ enum m68k_fixup_type type;
+ void *addr;
+};
+
+#define m68k_fixup(type, addr) \
+ " .section \".m68k_fixup\",\"aw\"\n" \
+ " .long " #type "," #addr "\n" \
+ " .previous\n"
+
+extern struct m68k_fixup_info __start_fixup[], __stop_fixup[];
+
+struct module;
+extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+ struct m68k_fixup_info *end);
+
#endif /* _ASM_M68K_MODULE_H */
diff --git a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
index 61e4406ed96..b5b78c01eb6 100644
--- a/include/asm-m68k/motorola_pgtable.h
+++ b/include/asm-m68k/motorola_pgtable.h
@@ -130,7 +130,7 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
#define pte_present(pte) (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE))
#define pte_clear(mm,addr,ptep) ({ pte_val(*(ptep)) = 0; })
-#define pte_page(pte) (mem_map + ((unsigned long)(__va(pte_val(pte)) - PAGE_OFFSET) >> PAGE_SHIFT))
+#define pte_page(pte) virt_to_page(__va(pte_val(pte)))
#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
@@ -143,7 +143,7 @@ static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp)
while (--__i >= 0) \
*__ptr++ = 0; \
})
-#define pmd_page(pmd) (mem_map + ((unsigned long)(__va(pmd_val(pmd)) - PAGE_OFFSET) >> PAGE_SHIFT))
+#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd)))
#define pgd_none(pgd) (!pgd_val(pgd))
@@ -223,10 +223,10 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmdp, unsigned long address)
return (pte_t *)__pmd_page(*pmdp) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
}
-#define pte_offset_map(pmdp,address) ((pte_t *)kmap(pmd_page(*pmdp)) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+#define pte_offset_map(pmdp,address) ((pte_t *)__pmd_page(*pmdp) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
#define pte_offset_map_nested(pmdp, address) pte_offset_map(pmdp, address)
-#define pte_unmap(pte) kunmap(pte)
-#define pte_unmap_nested(pte) kunmap(pte)
+#define pte_unmap(pte) ((void)0)
+#define pte_unmap_nested(pte) ((void)0)
/*
* Allocate and free page tables. The xxx_kernel() versions are
diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h
index fcc165ddd09..9e6d0d6debd 100644
--- a/include/asm-m68k/page.h
+++ b/include/asm-m68k/page.h
@@ -27,6 +27,8 @@
#ifndef __ASSEMBLY__
+#include <asm/module.h>
+
#define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
#define free_user_page(page, addr) free_page(addr)
@@ -114,18 +116,33 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#ifndef __ASSEMBLY__
+extern unsigned long m68k_memoffset;
+
#ifndef CONFIG_SUN3
#define WANT_PAGE_VIRTUAL
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
-extern unsigned long m68k_memoffset;
-#define __pa(vaddr) ((unsigned long)(vaddr)+m68k_memoffset)
-#define __va(paddr) ((void *)((unsigned long)(paddr)-m68k_memoffset))
-#else
-#define __pa(vaddr) virt_to_phys((void *)(vaddr))
-#define __va(paddr) phys_to_virt((unsigned long)(paddr))
-#endif
+static inline unsigned long ___pa(void *vaddr)
+{
+ unsigned long paddr;
+ asm (
+ "1: addl #0,%0\n"
+ m68k_fixup(%c2, 1b+2)
+ : "=r" (paddr)
+ : "0" (vaddr), "i" (m68k_fixup_memoffset));
+ return paddr;
+}
+#define __pa(vaddr) ___pa((void *)(vaddr))
+static inline void *__va(unsigned long paddr)
+{
+ void *vaddr;
+ asm (
+ "1: subl #0,%0\n"
+ m68k_fixup(%c2, 1b+2)
+ : "=r" (vaddr)
+ : "0" (paddr), "i" (m68k_fixup_memoffset));
+ return vaddr;
+}
#else /* !CONFIG_SUN3 */
/* This #define is a horrible hack to suppress lots of warnings. --m */
@@ -161,11 +178,47 @@ static inline void *__va(unsigned long x)
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
-#define virt_to_page(kaddr) (mem_map + (((unsigned long)(kaddr)-PAGE_OFFSET) >> PAGE_SHIFT))
-#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
+extern int m68k_virt_to_node_shift;
+
+#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+#define __virt_to_node(addr) (&pg_data_map[0])
+#else
+extern struct pglist_data *pg_data_table[];
+
+static inline __attribute_const__ int __virt_to_node_shift(void)
+{
+ int shift;
+
+ asm (
+ "1: moveq #0,%0\n"
+ m68k_fixup(%c1, 1b)
+ : "=d" (shift)
+ : "i" (m68k_fixup_vnode_shift));
+ return shift;
+}
+
+#define __virt_to_node(addr) (pg_data_table[(unsigned long)(addr) >> __virt_to_node_shift()])
+#endif
-#define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn))
-#define page_to_pfn(page) virt_to_pfn(page_to_virt(page))
+#define virt_to_page(addr) ({ \
+ pfn_to_page(virt_to_pfn(addr)); \
+})
+#define page_to_virt(page) ({ \
+ pfn_to_virt(page_to_pfn(page)); \
+})
+
+#define pfn_to_page(pfn) ({ \
+ unsigned long __pfn = (pfn); \
+ struct pglist_data *pgdat; \
+ pgdat = __virt_to_node((unsigned long)pfn_to_virt(__pfn)); \
+ pgdat->node_mem_map + (__pfn - pgdat->node_start_pfn); \
+})
+#define page_to_pfn(_page) ({ \
+ struct page *__p = (_page); \
+ struct pglist_data *pgdat; \
+ pgdat = &pg_data_map[page_to_nid(__p)]; \
+ ((__p) - pgdat->node_mem_map) + pgdat->node_start_pfn; \
+})
#define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && (void *)(kaddr) < high_memory)
#define pfn_valid(pfn) virt_addr_valid(pfn_to_virt(pfn))
diff --git a/include/asm-m68k/pci.h b/include/asm-m68k/pci.h
index 9d2c07abe44..678cb0b5231 100644
--- a/include/asm-m68k/pci.h
+++ b/include/asm-m68k/pci.h
@@ -54,8 +54,4 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
*/
#define PCI_DMA_BUS_IS_PHYS (1)
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* _ASM_M68K_PCI_H */
diff --git a/include/asm-m68k/pgalloc.h b/include/asm-m68k/pgalloc.h
index a9cfb4b99d8..4cb1a57ab76 100644
--- a/include/asm-m68k/pgalloc.h
+++ b/include/asm-m68k/pgalloc.h
@@ -8,11 +8,12 @@
#include <asm/virtconvert.h>
-
#ifdef CONFIG_SUN3
#include <asm/sun3_pgalloc.h>
#else
#include <asm/motorola_pgalloc.h>
#endif
+extern void m68k_setup_node(int node);
+
#endif /* M68K_PGALLOC_H */
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index 555b87a1f7e..778a4c538eb 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -107,22 +107,7 @@ extern void *empty_zero_page;
/* 64-bit machines, beware! SRB. */
#define SIZEOF_PTR_LOG2 2
-/*
- * Check if the addr/len goes up to the end of a physical
- * memory chunk. Used for DMA functions.
- */
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
-/*
- * It makes no sense to consider whether we cross a memory boundary if
- * we support just one physical chunk of memory.
- */
-static inline int mm_end_of_chunk(unsigned long addr, int len)
-{
- return 0;
-}
-#else
-int mm_end_of_chunk (unsigned long addr, int len);
-#endif
+#define mm_end_of_chunk(addr, len) 0
extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);
diff --git a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
index 5156a28a18d..b9e62c1e7ae 100644
--- a/include/asm-m68k/sun3_pgtable.h
+++ b/include/asm-m68k/sun3_pgtable.h
@@ -132,8 +132,8 @@ static inline void pte_clear (struct mm_struct *mm, unsigned long addr, pte_t *p
#define pfn_pte(pfn, pgprot) \
({ pte_t __pte; pte_val(__pte) = pfn | pgprot_val(pgprot); __pte; })
-#define pte_page(pte) (mem_map+((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT))
-#define pmd_page(pmd) (mem_map+((__pmd_page(pmd) - PAGE_OFFSET) >> PAGE_SHIFT))
+#define pte_page(pte) virt_to_page(__pte_page(pte))
+#define pmd_page(pmd) virt_to_page(__pmd_page(pmd))
static inline int pmd_none2 (pmd_t *pmd) { return !pmd_val (*pmd); }
diff --git a/include/asm-m68k/termbits.h b/include/asm-m68k/termbits.h
index a194092240f..0e520f328f5 100644
--- a/include/asm-m68k/termbits.h
+++ b/include/asm-m68k/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-m68k/virtconvert.h b/include/asm-m68k/virtconvert.h
index 83a87c9b1a1..dea32fbc7e5 100644
--- a/include/asm-m68k/virtconvert.h
+++ b/include/asm-m68k/virtconvert.h
@@ -8,56 +8,35 @@
#ifdef __KERNEL__
#include <linux/compiler.h>
+#include <linux/mmzone.h>
#include <asm/setup.h>
#include <asm/page.h>
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#endif
-
/*
* Change virtual addresses to physical addresses and vv.
*/
-#ifndef CONFIG_SUN3
-extern unsigned long mm_vtop(unsigned long addr) __attribute_const__;
-extern unsigned long mm_ptov(unsigned long addr) __attribute_const__;
-#else
-static inline unsigned long mm_vtop(unsigned long vaddr)
-{
- return __pa(vaddr);
-}
-
-static inline unsigned long mm_ptov(unsigned long paddr)
-{
- return (unsigned long)__va(paddr);
-}
-#endif
-
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
-static inline unsigned long virt_to_phys(void *vaddr)
-{
- return (unsigned long)vaddr - PAGE_OFFSET + m68k_memory[0].addr;
-}
-
-static inline void * phys_to_virt(unsigned long paddr)
-{
- return (void *)(paddr - m68k_memory[0].addr + PAGE_OFFSET);
-}
-#else
static inline unsigned long virt_to_phys(void *address)
{
- return mm_vtop((unsigned long)address);
+ return __pa(address);
}
static inline void *phys_to_virt(unsigned long address)
{
- return (void *) mm_ptov(address);
+ return __va(address);
}
-#endif
/* Permanent address of a page. */
-#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
-#define page_to_phys(page) virt_to_phys((void *)__page_address(page))
+#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+#define page_to_phys(page) \
+ __pa(PAGE_OFFSET + (((page) - pg_data_map[0].node_mem_map) << PAGE_SHIFT))
+#else
+#define page_to_phys(_page) ({ \
+ struct page *__page = _page; \
+ struct pglist_data *pgdat; \
+ pgdat = pg_data_table[page_to_nid(__page)]; \
+ page_to_pfn(__page) << PAGE_SHIFT; \
+})
+#endif
/*
* IO bus memory addresses are 1:1 with the physical address,
diff --git a/include/asm-m68knommu/pci.h b/include/asm-m68knommu/pci.h
index e04c77e1184..a13f3cc8745 100644
--- a/include/asm-m68knommu/pci.h
+++ b/include/asm-m68knommu/pci.h
@@ -24,16 +24,6 @@ static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
return 1;
}
-/*
- * Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function. Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* CONFIG_COMEMPCI */
#endif /* M68KNOMMU_PCI_H */
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index c6275088cf6..0b3ff9c4840 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -129,28 +129,12 @@
#define PHYS_TO_XKPHYS(cm,a) (_CONST64_(0x8000000000000000) | \
((cm)<<59) | (a))
-#if defined (CONFIG_CPU_R4300) \
- || defined (CONFIG_CPU_R4X00) \
- || defined (CONFIG_CPU_R5000) \
- || defined (CONFIG_CPU_RM7000) \
- || defined (CONFIG_CPU_NEVADA) \
- || defined (CONFIG_CPU_TX49XX) \
- || defined (CONFIG_CPU_MIPS64)
-#define TO_PHYS_MASK _CONST64_(0x0000000fffffffff) /* 2^^36 - 1 */
-#endif
-
-#if defined (CONFIG_CPU_R8000)
-/* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */
-#define TO_PHYS_MASK _CONST64_(0x000000ffffffffff) /* 2^^40 - 1 */
-#endif
-
-#if defined (CONFIG_CPU_R10000)
-#define TO_PHYS_MASK _CONST64_(0x000000ffffffffff) /* 2^^40 - 1 */
-#endif
-
-#if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A)
-#define TO_PHYS_MASK _CONST64_(0x00000fffffffffff) /* 2^^44 - 1 */
-#endif
+/*
+ * The ultimate limited of the 64-bit MIPS architecture: 2 bits for selecting
+ * the region, 3 bits for the CCA mode. This leaves 59 bits of which the
+ * R8000 implements most with its 48-bit physical address space.
+ */
+#define TO_PHYS_MASK _CONST64_(0x07ffffffffffffff) /* 2^^59 - 1 */
#ifndef CONFIG_CPU_R8000
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index 92e62ef711e..c5f20df780e 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -52,21 +52,6 @@
.endm
#endif /* CONFIG_MIPS_MT_SMTC */
-#ifdef CONFIG_CPU_SB1
- .macro fpu_enable_hazard
- .set push
- .set noreorder
- .set mips2
- SSNOP
- bnezl $0, .+4
- SSNOP
- .set pop
- .endm
-#else
- .macro fpu_enable_hazard
- .endm
-#endif
-
/*
* Temporary until all gas have MT ASE support
*/
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index d995413e11f..d9e81af53f7 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -238,10 +238,11 @@ static inline int test_and_set_bit(unsigned long nr,
volatile unsigned long *addr)
{
unsigned short bit = nr & SZLONG_MASK;
+ unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -254,11 +255,9 @@ static inline int test_and_set_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set push \n"
@@ -277,25 +276,22 @@ static inline int test_and_set_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else {
volatile unsigned long *a = addr;
unsigned long mask;
- int retval;
unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << bit;
raw_local_irq_save(flags);
- retval = (mask & *a) != 0;
+ res = (mask & *a);
*a |= mask;
raw_local_irq_restore(flags);
-
- return retval;
}
smp_mb();
+
+ return res != 0;
}
/*
@@ -310,10 +306,11 @@ static inline int test_and_clear_bit(unsigned long nr,
volatile unsigned long *addr)
{
unsigned short bit = nr & SZLONG_MASK;
+ unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -327,12 +324,10 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
#ifdef CONFIG_CPU_MIPSR2
} else if (__builtin_constant_p(nr)) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
"1: " __LL "%0, %1 # test_and_clear_bit \n"
@@ -346,12 +341,10 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "ri" (bit), "m" (*m)
: "memory");
-
- return res;
#endif
} else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set push \n"
@@ -371,25 +364,22 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else {
volatile unsigned long *a = addr;
unsigned long mask;
- int retval;
unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << bit;
raw_local_irq_save(flags);
- retval = (mask & *a) != 0;
+ res = (mask & *a);
*a &= ~mask;
raw_local_irq_restore(flags);
-
- return retval;
}
smp_mb();
+
+ return res != 0;
}
/*
@@ -404,10 +394,11 @@ static inline int test_and_change_bit(unsigned long nr,
volatile unsigned long *addr)
{
unsigned short bit = nr & SZLONG_MASK;
+ unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set mips3 \n"
@@ -420,11 +411,9 @@ static inline int test_and_change_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
- unsigned long temp, res;
+ unsigned long temp;
__asm__ __volatile__(
" .set push \n"
@@ -443,24 +432,22 @@ static inline int test_and_change_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m)
: "memory");
-
- return res != 0;
} else {
volatile unsigned long *a = addr;
- unsigned long mask, retval;
+ unsigned long mask;
unsigned long flags;
a += nr >> SZLONG_LOG;
mask = 1UL << bit;
raw_local_irq_save(flags);
- retval = (mask & *a) != 0;
+ res = (mask & *a);
*a ^= mask;
raw_local_irq_restore(flags);
-
- return retval;
}
smp_mb();
+
+ return res != 0;
}
#include <asm-generic/bitops/non-atomic.h>
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index b0c329783ac..087126a5faf 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -109,18 +109,12 @@
#define MACH_COSINE_ORION 0
/*
- * Valid machtype for group GALILEO
- */
-#define MACH_GROUP_GALILEO 11 /* Galileo Eval Boards */
-#define MACH_EV64120A 0 /* EV64120A */
-
-/*
* Valid machtype for group MOMENCO
*/
#define MACH_GROUP_MOMENCO 12 /* Momentum Boards */
#define MACH_MOMENCO_OCELOT 0
#define MACH_MOMENCO_OCELOT_G 1 /* no more supported (may 2007) */
-#define MACH_MOMENCO_OCELOT_C 2
+#define MACH_MOMENCO_OCELOT_C 2 /* no more supported (jun 2007) */
#define MACH_MOMENCO_JAGUAR_ATX 3 /* no more supported (may 2007) */
#define MACH_MOMENCO_OCELOT_3 4
@@ -194,13 +188,6 @@
#define MACH_HP_LASERJET 1
/*
- * Valid machtype for group LASAT
- */
-#define MACH_GROUP_LASAT 21
-#define MACH_LASAT_100 0 /* Masquerade II/SP100/SP50/SP25 */
-#define MACH_LASAT_200 1 /* Masquerade PRO/SP200 */
-
-/*
* Valid machtype for group TITAN
*/
#define MACH_GROUP_TITAN 22 /* PMC-Sierra Titan */
@@ -213,6 +200,27 @@
#define MACH_GROUP_NEC_EMMA2RH 25 /* NEC EMMA2RH (was 23) */
#define MACH_NEC_MARKEINS 0 /* NEC EMMA2RH Mark-eins */
+/*
+ * Valid machtype for group LEMOTE
+ */
+#define MACH_GROUP_LEMOTE 27
+#define MACH_LEMOTE_FULONG 0
+
+/*
+ * Valid machtype for group PMC-MSP
+ */
+#define MACH_GROUP_MSP 26 /* PMC-Sierra MSP boards/CPUs */
+#define MACH_MSP4200_EVAL 0 /* PMC-Sierra MSP4200 Evaluation */
+#define MACH_MSP4200_GW 1 /* PMC-Sierra MSP4200 Gateway demo */
+#define MACH_MSP4200_FPGA 2 /* PMC-Sierra MSP4200 Emulation */
+#define MACH_MSP7120_EVAL 3 /* PMC-Sierra MSP7120 Evaluation */
+#define MACH_MSP7120_GW 4 /* PMC-Sierra MSP7120 Residential GW */
+#define MACH_MSP7120_FPGA 5 /* PMC-Sierra MSP7120 Emulation */
+#define MACH_MSP_OTHER 255 /* PMC-Sierra unknown board type */
+
+#define MACH_GROUP_WINDRIVER 28 /* Windriver boards */
+#define MACH_WRPPMC 1
+
#define CL_SIZE COMMAND_LINE_SIZE
const char *get_system_type(void);
diff --git a/include/asm-mips/cacheops.h b/include/asm-mips/cacheops.h
index c4a1ec31ff6..df7f2deb3b5 100644
--- a/include/asm-mips/cacheops.h
+++ b/include/asm-mips/cacheops.h
@@ -20,7 +20,11 @@
#define Index_Load_Tag_D 0x05
#define Index_Store_Tag_I 0x08
#define Index_Store_Tag_D 0x09
+#if defined(CONFIG_CPU_LOONGSON2)
+#define Hit_Invalidate_I 0x00
+#else
#define Hit_Invalidate_I 0x10
+#endif
#define Hit_Invalidate_D 0x11
#define Hit_Writeback_Inv_D 0x15
diff --git a/include/asm-mips/compat-signal.h b/include/asm-mips/compat-signal.h
index 6599a901b63..368a99e5c3e 100644
--- a/include/asm-mips/compat-signal.h
+++ b/include/asm-mips/compat-signal.h
@@ -10,6 +10,68 @@
#include <asm/uaccess.h>
+#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct compat_siginfo {
+ int si_signo;
+ int si_code;
+ int si_errno;
+
+ union {
+ int _pad[SI_PAD_SIZE32];
+
+ /* kill() */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ compat_uid_t _uid; /* sender's uid */
+ } _kill;
+
+ /* SIGCHLD */
+ struct {
+ compat_pid_t _pid; /* which child */
+ compat_uid_t _uid; /* sender's uid */
+ int _status; /* exit code */
+ compat_clock_t _utime;
+ compat_clock_t _stime;
+ } _sigchld;
+
+ /* IRIX SIGCHLD */
+ struct {
+ compat_pid_t _pid; /* which child */
+ compat_clock_t _utime;
+ int _status; /* exit code */
+ compat_clock_t _stime;
+ } _irix_sigchld;
+
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+ struct {
+ s32 _addr; /* faulting insn/memory ref. */
+ } _sigfault;
+
+ /* SIGPOLL, SIGXFSZ (To do ...) */
+ struct {
+ int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+ int _fd;
+ } _sigpoll;
+
+ /* POSIX.1b timers */
+ struct {
+ timer_t _tid; /* timer id */
+ int _overrun; /* overrun count */
+ compat_sigval_t _sigval;/* same as below */
+ int _sys_private; /* not to be passed to user */
+ } _timer;
+
+ /* POSIX.1b signals */
+ struct {
+ compat_pid_t _pid; /* sender's pid */
+ compat_uid_t _uid; /* sender's uid */
+ compat_sigval_t _sigval;
+ } _rt;
+
+ } _sifields;
+} compat_siginfo_t;
+
static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
const sigset_t *s)
{
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 432653d7ae0..67c3f8ec030 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -132,7 +132,8 @@ typedef u32 compat_uptr_t;
static inline void __user *compat_ptr(compat_uptr_t uptr)
{
- return (void __user *)(long)uptr;
+ /* cast to a __user pointer via "unsigned long" makes sparse happy */
+ return (void __user *)(unsigned long)(long)uptr;
}
static inline compat_uptr_t ptr_to_compat(void __user *uptr)
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 5e4bed123b4..d95a83e3e1d 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -150,6 +150,10 @@
#define cpu_has_mipsmt (cpu_data[0].ases & MIPS_ASE_MIPSMT)
#endif
+#ifndef cpu_has_userlocal
+#define cpu_has_userlocal (cpu_data[0].options & MIPS_CPU_ULRI)
+#endif
+
#ifdef CONFIG_32BIT
# ifndef cpu_has_nofpuex
# define cpu_has_nofpuex (cpu_data[0].options & MIPS_CPU_NOFPUEX)
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h
index d38fdbf845b..3857358fb6d 100644
--- a/include/asm-mips/cpu.h
+++ b/include/asm-mips/cpu.h
@@ -89,6 +89,8 @@
#define PRID_IMP_34K 0x9500
#define PRID_IMP_24KE 0x9600
#define PRID_IMP_74K 0x9700
+#define PRID_IMP_LOONGSON1 0x4200
+#define PRID_IMP_LOONGSON2 0x6300
/*
* These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -107,6 +109,7 @@
* Definitions for 7:0 on legacy processors
*/
+#define PRID_REV_MASK 0x00ff
#define PRID_REV_TX4927 0x0022
#define PRID_REV_TX4937 0x0030
@@ -123,6 +126,18 @@
#define PRID_REV_VR4122 0x0070
#define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */
#define PRID_REV_VR4130 0x0080
+#define PRID_REV_34K_V1_0_2 0x0022
+
+/*
+ * Older processors used to encode processor version and revision in two
+ * 4-bit bitfields, the 4K seems to simply count up and even newer MTI cores
+ * have switched to use the 8-bits as 3:3:2 bitfield with the last field as
+ * the patch number. *ARGH*
+ */
+#define PRID_REV_ENCODE_44(ver, rev) \
+ ((ver) << 4 | (rev))
+#define PRID_REV_ENCODE_332(ver, rev, patch) \
+ ((ver) << 5 | (rev) << 2 | (patch))
/*
* FPU implementation/revision register (CP1 control register 0).
@@ -200,7 +215,10 @@
#define CPU_SB1A 62
#define CPU_74K 63
#define CPU_R14000 64
-#define CPU_LAST 64
+#define CPU_LOONGSON1 65
+#define CPU_LOONGSON2 66
+
+#define CPU_LAST 66
/*
* ISA Level encodings
@@ -246,6 +264,7 @@
#define MIPS_CPU_PREFETCH 0x00080000 /* CPU has usable prefetch */
#define MIPS_CPU_VINT 0x00100000 /* CPU supports MIPSR2 vectored interrupts */
#define MIPS_CPU_VEIC 0x00200000 /* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI 0x00400000 /* CPU has ULRI feature */
/*
* CPU ASE encodings
diff --git a/include/asm-mips/div64.h b/include/asm-mips/div64.h
index 66189f5f639..716371bd098 100644
--- a/include/asm-mips/div64.h
+++ b/include/asm-mips/div64.h
@@ -20,7 +20,7 @@
*/
#define do_div64_32(res, high, low, base) ({ \
- unsigned long __quot, __mod; \
+ unsigned long __quot32, __mod32; \
unsigned long __cf, __tmp, __tmp2, __i; \
\
__asm__(".set push\n\t" \
@@ -48,12 +48,13 @@
"bnez %4, 0b\n\t" \
" srl %5, %1, 0x1f\n\t" \
".set pop" \
- : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
+ : "=&r" (__mod32), "=&r" (__tmp), \
+ "=&r" (__quot32), "=&r" (__cf), \
"=&r" (__i), "=&r" (__tmp2) \
: "Jr" (base), "0" (high), "1" (low)); \
\
- (res) = __quot; \
- __mod; })
+ (res) = __quot32; \
+ __mod32; })
#define do_div(n, base) ({ \
unsigned long long __quot; \
diff --git a/include/asm-mips/gpio.h b/include/asm-mips/gpio.h
new file mode 100644
index 00000000000..06e46faf862
--- /dev/null
+++ b/include/asm-mips/gpio.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_MIPS_GPIO_H
+#define __ASM_MIPS_GPIO_H
+
+#include <gpio.h>
+
+#endif /* __ASM_MIPS_GPIO_H */
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 92ec2618560..7ba92890ea1 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -178,6 +178,11 @@ extern void __iounmap(const volatile void __iomem *addr);
static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
unsigned long flags)
{
+ void __iomem *addr = plat_ioremap(offset, size, flags);
+
+ if (addr)
+ return addr;
+
#define __IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
if (cpu_has_64bit_addresses) {
@@ -207,7 +212,8 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
*/
if (__IS_LOW512(phys_addr) && __IS_LOW512(last_addr) &&
flags == _CACHE_UNCACHED)
- return (void __iomem *)CKSEG1ADDR(phys_addr);
+ return (void __iomem *)
+ (unsigned long)CKSEG1ADDR(phys_addr);
}
return __ioremap(offset, size, flags);
@@ -282,6 +288,9 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
static inline void iounmap(const volatile void __iomem *addr)
{
+ if (plat_iounmap(addr))
+ return;
+
#define __IS_KSEG1(addr) (((unsigned long)(addr) & ~0x1fffffffUL) == CKSEG1)
if (cpu_has_64bit_addresses ||
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index 91803ba30ff..97102ebc54b 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -24,7 +24,7 @@ static inline int irq_canonicalize(int irq)
#define irq_canonicalize(irq) (irq) /* Sane hardware, sane code ... */
#endif
-#ifdef CONFIG_MIPS_MT_SMTC
+#ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
/*
* Clear interrupt mask handling "backstop" if irq_hwmask
* entry so indicates. This implies that the ack() or end()
@@ -72,4 +72,13 @@ extern int allocate_irqno(void);
extern void alloc_legacy_irqno(void);
extern void free_irqno(unsigned int irq);
+/*
+ * Before R2 the timer and performance counter interrupts were both fixed to
+ * IE7. Since R2 their number has to be read from the c0_intctl register.
+ */
+#define CP0_LEGACY_COMPARE_IRQ 7
+
+extern int cp0_compare_irq;
+extern int cp0_perfcount_irq;
+
#endif /* _ASM_IRQ_H */
diff --git a/include/asm-mips/lasat/ds1603.h b/include/asm-mips/lasat/ds1603.h
deleted file mode 100644
index edcd7544b35..00000000000
--- a/include/asm-mips/lasat/ds1603.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <asm/addrspace.h>
-
-/* Lasat 100 */
-#define DS1603_REG_100 (KSEG1ADDR(0x1c810000))
-#define DS1603_RST_100 (1 << 2)
-#define DS1603_CLK_100 (1 << 0)
-#define DS1603_DATA_SHIFT_100 1
-#define DS1603_DATA_100 (1 << DS1603_DATA_SHIFT_100)
-
-/* Lasat 200 */
-#define DS1603_REG_200 (KSEG1ADDR(0x11000000))
-#define DS1603_RST_200 (1 << 3)
-#define DS1603_CLK_200 (1 << 4)
-#define DS1603_DATA_200 (1 << 5)
-
-#define DS1603_DATA_REG_200 (DS1603_REG_200 + 0x10000)
-#define DS1603_DATA_READ_SHIFT_200 9
-#define DS1603_DATA_READ_200 (1 << DS1603_DATA_READ_SHIFT_200)
diff --git a/include/asm-mips/lasat/eeprom.h b/include/asm-mips/lasat/eeprom.h
deleted file mode 100644
index 7b53edd5cd5..00000000000
--- a/include/asm-mips/lasat/eeprom.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <asm/addrspace.h>
-
-/* lasat 100 */
-#define AT93C_REG_100 KSEG1ADDR(0x1c810000)
-#define AT93C_RDATA_REG_100 AT93C_REG_100
-#define AT93C_RDATA_SHIFT_100 4
-#define AT93C_WDATA_SHIFT_100 4
-#define AT93C_CS_M_100 ( 1 << 5 )
-#define AT93C_CLK_M_100 ( 1 << 3 )
-
-/* lasat 200 */
-#define AT93C_REG_200 KSEG1ADDR(0x11000000)
-#define AT93C_RDATA_REG_200 (AT93C_REG_200+0x10000)
-#define AT93C_RDATA_SHIFT_200 8
-#define AT93C_WDATA_SHIFT_200 2
-#define AT93C_CS_M_200 ( 1 << 0 )
-#define AT93C_CLK_M_200 ( 1 << 1 )
diff --git a/include/asm-mips/lasat/head.h b/include/asm-mips/lasat/head.h
deleted file mode 100644
index f5589f31a19..00000000000
--- a/include/asm-mips/lasat/head.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Image header stuff
- */
-#ifndef _HEAD_H
-#define _HEAD_H
-
-#define LASAT_K_MAGIC0_VAL 0xfedeabba
-#define LASAT_K_MAGIC1_VAL 0x00bedead
-
-#ifndef _LANGUAGE_ASSEMBLY
-#include <linux/types.h>
-struct bootloader_header {
- u32 magic[2];
- u32 version;
- u32 image_start;
- u32 image_size;
- u32 kernel_start;
- u32 kernel_entry;
-};
-#endif
-
-#endif /* _HEAD_H */
diff --git a/include/asm-mips/lasat/lasat.h b/include/asm-mips/lasat/lasat.h
deleted file mode 100644
index 42077e367a5..00000000000
--- a/include/asm-mips/lasat/lasat.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * lasat.h
- *
- * Thomas Horsten <thh@lasat.com>
- * Copyright (C) 2000 LASAT Networks A/S.
- *
- * This program is free software; you can distribute 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 it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You 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.
- *
- * Configuration for LASAT boards, loads the appropriate include files.
- */
-#ifndef _LASAT_H
-#define _LASAT_H
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-extern struct lasat_misc {
- volatile u32 *reset_reg;
- volatile u32 *flash_wp_reg;
- u32 flash_wp_bit;
-} *lasat_misc;
-
-enum lasat_mtdparts {
- LASAT_MTD_BOOTLOADER,
- LASAT_MTD_SERVICE,
- LASAT_MTD_NORMAL,
- LASAT_MTD_CONFIG,
- LASAT_MTD_FS,
- LASAT_MTD_LAST
-};
-
-/*
- * The format of the data record in the EEPROM.
- * See Documentation/LASAT/eeprom.txt for a detailed description
- * of the fields in this struct, and the LASAT Hardware Configuration
- * field specification for a detailed description of the config
- * field.
- */
-#include <linux/types.h>
-
-#define LASAT_EEPROM_VERSION 7
-struct lasat_eeprom_struct {
- unsigned int version;
- unsigned int cfg[3];
- unsigned char hwaddr[6];
- unsigned char print_partno[12];
- unsigned char term0;
- unsigned char print_serial[14];
- unsigned char term1;
- unsigned char prod_partno[12];
- unsigned char term2;
- unsigned char prod_serial[14];
- unsigned char term3;
- unsigned char passwd_hash[16];
- unsigned char pwdnull;
- unsigned char vendid;
- unsigned char ts_ref;
- unsigned char ts_signoff;
- unsigned char reserved[11];
- unsigned char debugaccess;
- unsigned short prid;
- unsigned int serviceflag;
- unsigned int ipaddr;
- unsigned int netmask;
- unsigned int crc32;
-};
-
-struct lasat_eeprom_struct_pre7 {
- unsigned int version;
- unsigned int flags[3];
- unsigned char hwaddr0[6];
- unsigned char hwaddr1[6];
- unsigned char print_partno[9];
- unsigned char term0;
- unsigned char print_serial[14];
- unsigned char term1;
- unsigned char prod_partno[9];
- unsigned char term2;
- unsigned char prod_serial[14];
- unsigned char term3;
- unsigned char passwd_hash[24];
- unsigned char pwdnull;
- unsigned char vendor;
- unsigned char ts_ref;
- unsigned char ts_signoff;
- unsigned char reserved[6];
- unsigned int writecount;
- unsigned int ipaddr;
- unsigned int netmask;
- unsigned int crc32;
-};
-
-/* Configuration descriptor encoding - see the doc for details */
-
-#define LASAT_W0_DSCTYPE(v) ( ( (v) ) & 0xf )
-#define LASAT_W0_BMID(v) ( ( (v) >> 0x04 ) & 0xf )
-#define LASAT_W0_CPUTYPE(v) ( ( (v) >> 0x08 ) & 0xf )
-#define LASAT_W0_BUSSPEED(v) ( ( (v) >> 0x0c ) & 0xf )
-#define LASAT_W0_CPUCLK(v) ( ( (v) >> 0x10 ) & 0xf )
-#define LASAT_W0_SDRAMBANKSZ(v) ( ( (v) >> 0x14 ) & 0xf )
-#define LASAT_W0_SDRAMBANKS(v) ( ( (v) >> 0x18 ) & 0xf )
-#define LASAT_W0_L2CACHE(v) ( ( (v) >> 0x1c ) & 0xf )
-
-#define LASAT_W1_EDHAC(v) ( ( (v) ) & 0xf )
-#define LASAT_W1_HIFN(v) ( ( (v) >> 0x04 ) & 0x1 )
-#define LASAT_W1_ISDN(v) ( ( (v) >> 0x05 ) & 0x1 )
-#define LASAT_W1_IDE(v) ( ( (v) >> 0x06 ) & 0x1 )
-#define LASAT_W1_HDLC(v) ( ( (v) >> 0x07 ) & 0x1 )
-#define LASAT_W1_USVERSION(v) ( ( (v) >> 0x08 ) & 0x1 )
-#define LASAT_W1_4MACS(v) ( ( (v) >> 0x09 ) & 0x1 )
-#define LASAT_W1_EXTSERIAL(v) ( ( (v) >> 0x0a ) & 0x1 )
-#define LASAT_W1_FLASHSIZE(v) ( ( (v) >> 0x0c ) & 0xf )
-#define LASAT_W1_PCISLOTS(v) ( ( (v) >> 0x10 ) & 0xf )
-#define LASAT_W1_PCI1OPT(v) ( ( (v) >> 0x14 ) & 0xf )
-#define LASAT_W1_PCI2OPT(v) ( ( (v) >> 0x18 ) & 0xf )
-#define LASAT_W1_PCI3OPT(v) ( ( (v) >> 0x1c ) & 0xf )
-
-/* Routines specific to LASAT boards */
-
-#define LASAT_BMID_MASQUERADE2 0
-#define LASAT_BMID_MASQUERADEPRO 1
-#define LASAT_BMID_SAFEPIPE25 2
-#define LASAT_BMID_SAFEPIPE50 3
-#define LASAT_BMID_SAFEPIPE100 4
-#define LASAT_BMID_SAFEPIPE5000 5
-#define LASAT_BMID_SAFEPIPE7000 6
-#define LASAT_BMID_SAFEPIPE1000 7
-//#define LASAT_BMID_SAFEPIPE30 7
-//#define LASAT_BMID_SAFEPIPE5100 8
-//#define LASAT_BMID_SAFEPIPE7100 9
-#define LASAT_BMID_UNKNOWN 0xf
-#define LASAT_MAX_BMID_NAMES 9 // no larger than 15!
-
-#define LASAT_HAS_EDHAC ( 1 << 0 )
-#define LASAT_EDHAC_FAST ( 1 << 1 )
-#define LASAT_HAS_EADI ( 1 << 2 )
-#define LASAT_HAS_HIFN ( 1 << 3 )
-#define LASAT_HAS_ISDN ( 1 << 4 )
-#define LASAT_HAS_LEASEDLINE_IF ( 1 << 5 )
-#define LASAT_HAS_HDC ( 1 << 6 )
-
-#define LASAT_PRID_MASQUERADE2 0
-#define LASAT_PRID_MASQUERADEPRO 1
-#define LASAT_PRID_SAFEPIPE25 2
-#define LASAT_PRID_SAFEPIPE50 3
-#define LASAT_PRID_SAFEPIPE100 4
-#define LASAT_PRID_SAFEPIPE5000 5
-#define LASAT_PRID_SAFEPIPE7000 6
-#define LASAT_PRID_SAFEPIPE30 7
-#define LASAT_PRID_SAFEPIPE5100 8
-#define LASAT_PRID_SAFEPIPE7100 9
-
-#define LASAT_PRID_SAFEPIPE1110 10
-#define LASAT_PRID_SAFEPIPE3020 11
-#define LASAT_PRID_SAFEPIPE3030 12
-#define LASAT_PRID_SAFEPIPE5020 13
-#define LASAT_PRID_SAFEPIPE5030 14
-#define LASAT_PRID_SAFEPIPE1120 15
-#define LASAT_PRID_SAFEPIPE1130 16
-#define LASAT_PRID_SAFEPIPE6010 17
-#define LASAT_PRID_SAFEPIPE6110 18
-#define LASAT_PRID_SAFEPIPE6210 19
-#define LASAT_PRID_SAFEPIPE1020 20
-#define LASAT_PRID_SAFEPIPE1040 21
-#define LASAT_PRID_SAFEPIPE1060 22
-
-struct lasat_info {
- unsigned int li_cpu_hz;
- unsigned int li_bus_hz;
- unsigned int li_bmid;
- unsigned int li_memsize;
- unsigned int li_flash_size;
- unsigned int li_prid;
- unsigned char li_bmstr[16];
- unsigned char li_namestr[32];
- unsigned char li_typestr[16];
- /* Info on the Flash layout */
- unsigned int li_flash_base;
- unsigned long li_flashpart_base[LASAT_MTD_LAST];
- unsigned long li_flashpart_size[LASAT_MTD_LAST];
- struct lasat_eeprom_struct li_eeprom_info;
- unsigned int li_eeprom_upgrade_version;
- unsigned int li_debugaccess;
-};
-
-extern struct lasat_info lasat_board_info;
-
-static inline unsigned long lasat_flash_partition_start(int partno)
-{
- if (partno < 0 || partno >= LASAT_MTD_LAST)
- return 0;
-
- return lasat_board_info.li_flashpart_base[partno];
-}
-
-static inline unsigned long lasat_flash_partition_size(int partno)
-{
- if (partno < 0 || partno >= LASAT_MTD_LAST)
- return 0;
-
- return lasat_board_info.li_flashpart_size[partno];
-}
-
-/* Called from setup() to initialize the global board_info struct */
-extern int lasat_init_board_info(void);
-
-/* Write the modified EEPROM info struct */
-extern void lasat_write_eeprom_info(void);
-
-#define N_MACHTYPES 2
-/* for calibration of delays */
-
-/* the lasat_ndelay function is necessary because it is used at an
- * early stage of the boot process where ndelay is not calibrated.
- * It is used for the bit-banging rtc and eeprom drivers */
-
-#include <asm/delay.h>
-/* calculating with the slowest board with 100 MHz clock */
-#define LASAT_100_DIVIDER 20
-/* All 200's run at 250 MHz clock */
-#define LASAT_200_DIVIDER 8
-
-extern unsigned int lasat_ndelay_divider;
-
-static inline void lasat_ndelay(unsigned int ns)
-{
- __delay(ns / lasat_ndelay_divider);
-}
-
-#endif /* !defined (_LANGUAGE_ASSEMBLY) */
-
-#define LASAT_SERVICEMODE_MAGIC_1 0xdeadbeef
-#define LASAT_SERVICEMODE_MAGIC_2 0xfedeabba
-
-/* Lasat 100 boards */
-#define LASAT_GT_BASE (KSEG1ADDR(0x14000000))
-
-/* Lasat 200 boards */
-#define Vrc5074_PHYS_BASE 0x1fa00000
-#define Vrc5074_BASE (KSEG1ADDR(Vrc5074_PHYS_BASE))
-#define PCI_WINDOW1 0x1a000000
-
-#endif /* _LASAT_H */
diff --git a/include/asm-mips/lasat/lasatint.h b/include/asm-mips/lasat/lasatint.h
deleted file mode 100644
index 065474feecc..00000000000
--- a/include/asm-mips/lasat/lasatint.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#define LASATINT_END 16
-
-/* lasat 100 */
-#define LASAT_INT_STATUS_REG_100 (KSEG1ADDR(0x1c880000))
-#define LASAT_INT_MASK_REG_100 (KSEG1ADDR(0x1c890000))
-#define LASATINT_MASK_SHIFT_100 0
-
-/* lasat 200 */
-#define LASAT_INT_STATUS_REG_200 (KSEG1ADDR(0x1104003c))
-#define LASAT_INT_MASK_REG_200 (KSEG1ADDR(0x1104003c))
-#define LASATINT_MASK_SHIFT_200 16
-
diff --git a/include/asm-mips/lasat/picvue.h b/include/asm-mips/lasat/picvue.h
deleted file mode 100644
index 42a492edc40..00000000000
--- a/include/asm-mips/lasat/picvue.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Lasat 100 */
-#define PVC_REG_100 KSEG1ADDR(0x1c820000)
-#define PVC_DATA_SHIFT_100 0
-#define PVC_DATA_M_100 0xFF
-#define PVC_E_100 (1 << 8)
-#define PVC_RW_100 (1 << 9)
-#define PVC_RS_100 (1 << 10)
-
-/* Lasat 200 */
-#define PVC_REG_200 KSEG1ADDR(0x11000000)
-#define PVC_DATA_SHIFT_200 24
-#define PVC_DATA_M_200 (0xFF << PVC_DATA_SHIFT_200)
-#define PVC_E_200 (1 << 16)
-#define PVC_RW_200 (1 << 17)
-#define PVC_RS_200 (1 << 18)
diff --git a/include/asm-mips/lasat/serial.h b/include/asm-mips/lasat/serial.h
deleted file mode 100644
index 9e88c7669c7..00000000000
--- a/include/asm-mips/lasat/serial.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <asm/lasat/lasat.h>
-
-/* Lasat 100 boards serial configuration */
-#define LASAT_BASE_BAUD_100 ( 7372800 / 16 )
-#define LASAT_UART_REGS_BASE_100 0x1c8b0000
-#define LASAT_UART_REGS_SHIFT_100 2
-#define LASATINT_UART_100 8
-
-/* * LASAT 200 boards serial configuration */
-#define LASAT_BASE_BAUD_200 (100000000 / 16 / 12)
-#define LASAT_UART_REGS_BASE_200 (Vrc5074_PHYS_BASE + 0x0300)
-#define LASAT_UART_REGS_SHIFT_200 3
-#define LASATINT_UART_200 13
diff --git a/include/asm-mips/mach-au1x00/au1xxx_gpio.h b/include/asm-mips/mach-au1x00/au1xxx_gpio.h
deleted file mode 100644
index 27911e054ff..00000000000
--- a/include/asm-mips/mach-au1x00/au1xxx_gpio.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __AU1XXX_GPIO_H
-#define __AU1XXX_GPIO_H
-
-void au1xxx_gpio1_set_inputs(void);
-void au1xxx_gpio_tristate(int signal);
-void au1xxx_gpio_write(int signal, int value);
-int au1xxx_gpio_read(int signal);
-
-typedef volatile struct
-{
- u32 dir;
- u32 reserved;
- u32 output;
- u32 pinstate;
- u32 inten;
- u32 enable;
-
-} AU1X00_GPIO2;
-
-#endif //__AU1XXX_GPIO_H
diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
index 8fcae21adbd..4663e8b415c 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_ide.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
@@ -88,26 +88,26 @@ static const struct drive_list_entry dma_white_list [] = {
/*
* Hitachi
*/
- { "HITACHI_DK14FA-20" , "ALL" },
- { "HTS726060M9AT00" , "ALL" },
+ { "HITACHI_DK14FA-20" , NULL },
+ { "HTS726060M9AT00" , NULL },
/*
* Maxtor
*/
- { "Maxtor 6E040L0" , "ALL" },
- { "Maxtor 6Y080P0" , "ALL" },
- { "Maxtor 6Y160P0" , "ALL" },
+ { "Maxtor 6E040L0" , NULL },
+ { "Maxtor 6Y080P0" , NULL },
+ { "Maxtor 6Y160P0" , NULL },
/*
* Seagate
*/
- { "ST3120026A" , "ALL" },
- { "ST320014A" , "ALL" },
- { "ST94011A" , "ALL" },
- { "ST340016A" , "ALL" },
+ { "ST3120026A" , NULL },
+ { "ST320014A" , NULL },
+ { "ST94011A" , NULL },
+ { "ST340016A" , NULL },
/*
* Western Digital
*/
- { "WDC WD400UE-00HCT0" , "ALL" },
- { "WDC WD400JB-00JJC0" , "ALL" },
+ { "WDC WD400UE-00HCT0" , NULL },
+ { "WDC WD400JB-00JJC0" , NULL },
{ NULL , NULL }
};
@@ -116,9 +116,9 @@ static const struct drive_list_entry dma_black_list [] = {
/*
* Western Digital
*/
- { "WDC WD100EB-00CGH0" , "ALL" },
- { "WDC WD200BB-00AUA1" , "ALL" },
- { "WDC AC24300L" , "ALL" },
+ { "WDC WD100EB-00CGH0" , NULL },
+ { "WDC WD200BB-00AUA1" , NULL },
+ { "WDC AC24300L" , NULL },
{ NULL , NULL }
};
#endif
diff --git a/include/asm-mips/mach-au1x00/gpio.h b/include/asm-mips/mach-au1x00/gpio.h
new file mode 100644
index 00000000000..2dc61e009a0
--- /dev/null
+++ b/include/asm-mips/mach-au1x00/gpio.h
@@ -0,0 +1,69 @@
+#ifndef _AU1XXX_GPIO_H_
+#define _AU1XXX_GPIO_H_
+
+#include <linux/types.h>
+
+#define AU1XXX_GPIO_BASE 200
+
+struct au1x00_gpio2 {
+ u32 dir;
+ u32 reserved;
+ u32 output;
+ u32 pinstate;
+ u32 inten;
+ u32 enable;
+};
+
+extern int au1xxx_gpio_get_value(unsigned gpio);
+extern void au1xxx_gpio_set_value(unsigned gpio, int value);
+extern int au1xxx_gpio_direction_input(unsigned gpio);
+extern int au1xxx_gpio_direction_output(unsigned gpio, int value);
+
+
+/* Wrappers for the arch-neutral GPIO API */
+
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+ /* Not yet implemented */
+ return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+ /* Not yet implemented */
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ return au1xxx_gpio_direction_input(gpio);
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ return au1xxx_gpio_direction_output(gpio, value);
+}
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return au1xxx_gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ au1xxx_gpio_set_value(gpio, value);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+ return gpio;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+ return irq;
+}
+
+/* For cansleep */
+#include <asm-generic/gpio.h>
+
+#endif /* _AU1XXX_GPIO_H_ */
diff --git a/include/asm-mips/mach-au1x00/ioremap.h b/include/asm-mips/mach-au1x00/ioremap.h
index 098fca4289b..364cea2dc71 100644
--- a/include/asm-mips/mach-au1x00/ioremap.h
+++ b/include/asm-mips/mach-au1x00/ioremap.h
@@ -28,4 +28,15 @@ static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
return __fixup_bigphys_addr(phys_addr, size);
}
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+ unsigned long flags)
+{
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return 0;
+}
+
#endif /* __ASM_MACH_AU1X00_IOREMAP_H */
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
index 684a501c04c..9c9d2b998ca 100644
--- a/include/asm-mips/mach-cobalt/cobalt.h
+++ b/include/asm-mips/mach-cobalt/cobalt.h
@@ -30,7 +30,6 @@
#define COBALT_CPU_IRQ MIPS_CPU_IRQ_BASE
#define COBALT_GALILEO_IRQ (COBALT_CPU_IRQ + 2)
-#define COBALT_SCC_IRQ (COBALT_CPU_IRQ + 3) /* pre-production has 85C30 */
#define COBALT_RAQ_SCSI_IRQ (COBALT_CPU_IRQ + 3)
#define COBALT_ETH0_IRQ (COBALT_CPU_IRQ + 3)
#define COBALT_QUBE1_ETH0_IRQ (COBALT_CPU_IRQ + 4)
@@ -71,10 +70,6 @@
extern int cobalt_board_id;
-#define PCI_CFG_SET(devfn,where) \
- GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) | \
- (PCI_FUNC (devfn) << 8) | (where)))
-
#define COBALT_LED_PORT (*(volatile unsigned char *) CKSEG1ADDR(0x1c000000))
# define COBALT_LED_BAR_LEFT (1 << 0) /* Qube */
# define COBALT_LED_BAR_RIGHT (1 << 1) /* Qube */
diff --git a/include/asm-mips/mach-ev64120/mach-gt64120.h b/include/asm-mips/mach-ev64120/mach-gt64120.h
deleted file mode 100644
index 7e272ce57ea..00000000000
--- a/include/asm-mips/mach-ev64120/mach-gt64120.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This is a direct copy of the ev96100.h file, with a global
- * search and replace. The numbers are the same.
- *
- * The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef __ASM_GALILEO_BOARDS_MIPS_EV64120_H
-#define __ASM_GALILEO_BOARDS_MIPS_EV64120_H
-
-/*
- * GT64120 config space base address
- */
-extern unsigned long gt64120_base;
-
-#define GT64120_BASE (gt64120_base)
-
-/*
- * PCI Bus allocation
- */
-#define GT_PCI_MEM_BASE 0x12000000UL
-#define GT_PCI_MEM_SIZE 0x02000000UL
-#define GT_PCI_IO_BASE 0x10000000UL
-#define GT_PCI_IO_SIZE 0x02000000UL
-#define GT_ISA_IO_BASE PCI_IO_BASE
-
-/*
- * Duart I/O ports.
- */
-#define EV64120_COM1_BASE_ADDR (0x1d000000 + 0x20)
-#define EV64120_COM2_BASE_ADDR (0x1d000000 + 0x00)
-
-
-/*
- * EV64120 interrupt controller register base.
- */
-#define EV64120_ICTRL_REGS_BASE (KSEG1ADDR(0x1f000000))
-
-/*
- * EV64120 UART register base.
- */
-#define EV64120_UART0_REGS_BASE (KSEG1ADDR(EV64120_COM1_BASE_ADDR))
-#define EV64120_UART1_REGS_BASE (KSEG1ADDR(EV64120_COM2_BASE_ADDR))
-#define EV64120_BASE_BAUD ( 3686400 / 16 )
-#define EV64120_UART_IRQ 6
-
-/*
- * PCI interrupts will come in on either the INTA or INTD interrups lines,
- * which are mapped to the #2 and #5 interrupt pins of the MIPS. On our
- * boards, they all either come in on IntD or they all come in on IntA, they
- * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
- * "requested" interrupt numbers and go through the list whenever we get an
- * IntA/D.
- *
- * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and
- * INTD is 11.
- */
-#define GT_TIMER 4
-#define GT_INTA 2
-#define GT_INTD 5
-
-#endif /* __ASM_GALILEO_BOARDS_MIPS_EV64120_H */
diff --git a/include/asm-mips/mach-generic/gpio.h b/include/asm-mips/mach-generic/gpio.h
new file mode 100644
index 00000000000..6eaf5efedf3
--- /dev/null
+++ b/include/asm-mips/mach-generic/gpio.h
@@ -0,0 +1,15 @@
+#ifndef __ASM_MACH_GENERIC_GPIO_H
+#define __ASM_MACH_GENERIC_GPIO_H
+
+int gpio_request(unsigned gpio, const char *label);
+void gpio_free(unsigned gpio);
+int gpio_direction_input(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+int gpio_to_irq(unsigned gpio);
+int irq_to_gpio(unsigned irq);
+
+#include <asm-generic/gpio.h> /* cansleep wrappers */
+
+#endif /* __ASM_MACH_GENERIC_GPIO_H */
diff --git a/include/asm-mips/mach-generic/ioremap.h b/include/asm-mips/mach-generic/ioremap.h
index 9b64ff6e485..b379938d47f 100644
--- a/include/asm-mips/mach-generic/ioremap.h
+++ b/include/asm-mips/mach-generic/ioremap.h
@@ -20,4 +20,15 @@ static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
return phys_addr;
}
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+ unsigned long flags)
+{
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return 0;
+}
+
#endif /* __ASM_MACH_GENERIC_IOREMAP_H */
diff --git a/include/asm-mips/mach-generic/spaces.h b/include/asm-mips/mach-generic/spaces.h
index 0ae9997bc9a..c9fa4b14968 100644
--- a/include/asm-mips/mach-generic/spaces.h
+++ b/include/asm-mips/mach-generic/spaces.h
@@ -10,38 +10,54 @@
#ifndef _ASM_MACH_GENERIC_SPACES_H
#define _ASM_MACH_GENERIC_SPACES_H
+#include <linux/const.h>
+
+/*
+ * This gives the physical RAM offset.
+ */
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET _AC(0, UL)
+#endif
#ifdef CONFIG_32BIT
-#define CAC_BASE 0x80000000
-#define IO_BASE 0xa0000000
-#define UNCAC_BASE 0xa0000000
-#define MAP_BASE 0xc0000000
+#define CAC_BASE _AC(0x80000000, UL)
+#define IO_BASE _AC(0xa0000000, UL)
+#define UNCAC_BASE _AC(0xa0000000, UL)
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET 0x80000000UL
+#ifndef MAP_BASE
+#define MAP_BASE _AC(0xc0000000, UL)
+#endif
/*
* Memory above this physical address will be considered highmem.
*/
#ifndef HIGHMEM_START
-#define HIGHMEM_START 0x20000000UL
+#define HIGHMEM_START _AC(0x20000000, UL)
#endif
#endif /* CONFIG_32BIT */
#ifdef CONFIG_64BIT
-/*
- * This handles the memory map.
- */
+#ifndef CAC_BASE
#ifdef CONFIG_DMA_NONCOHERENT
-#define PAGE_OFFSET 0x9800000000000000UL
+#define CAC_BASE _AC(0x9800000000000000, UL)
#else
-#define PAGE_OFFSET 0xa800000000000000UL
+#define CAC_BASE _AC(0xa800000000000000, UL)
+#endif
+#endif
+
+#ifndef IO_BASE
+#define IO_BASE _AC(0x9000000000000000, UL)
+#endif
+
+#ifndef UNCAC_BASE
+#define UNCAC_BASE _AC(0x9000000000000000, UL)
+#endif
+
+#ifndef MAP_BASE
+#define MAP_BASE _AC(0xc000000000000000, UL)
#endif
/*
@@ -50,22 +66,20 @@
* in the distant future. Nobody will care for a few years :-)
*/
#ifndef HIGHMEM_START
-#define HIGHMEM_START (1UL << 59UL)
+#define HIGHMEM_START (_AC(1, UL) << _AC(59, UL))
#endif
-#ifdef CONFIG_DMA_NONCOHERENT
-#define CAC_BASE 0x9800000000000000UL
-#else
-#define CAC_BASE 0xa800000000000000UL
-#endif
-#define IO_BASE 0x9000000000000000UL
-#define UNCAC_BASE 0x9000000000000000UL
-#define MAP_BASE 0xc000000000000000UL
-
#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
#endif /* CONFIG_64BIT */
+/*
+ * This handles the memory map.
+ */
+#ifndef PAGE_OFFSET
+#define PAGE_OFFSET (CAC_BASE + PHYS_OFFSET)
+#endif
+
#endif /* __ASM_MACH_GENERIC_SPACES_H */
diff --git a/include/asm-mips/mach-ip22/spaces.h b/include/asm-mips/mach-ip22/spaces.h
index ab20c026fd1..7f9fa6f6605 100644
--- a/include/asm-mips/mach-ip22/spaces.h
+++ b/include/asm-mips/mach-ip22/spaces.h
@@ -11,44 +11,17 @@
#define _ASM_MACH_IP22_SPACES_H
-#ifdef CONFIG_32BIT
-
-#define CAC_BASE 0x80000000
-#define IO_BASE 0xa0000000
-#define UNCAC_BASE 0xa0000000
-#define MAP_BASE 0xc0000000
-
-/*
- * This handles the memory map.
- * We handle pages at KSEG0 for kernels with 32 bit address space.
- */
-#define PAGE_OFFSET 0x80000000UL
-
-/*
- * Memory above this physical address will be considered highmem.
- */
-#ifndef HIGHMEM_START
-#define HIGHMEM_START 0x20000000UL
-#endif
-
-#endif /* CONFIG_32BIT */
-
#ifdef CONFIG_64BIT
-#define PAGE_OFFSET 0xffffffff80000000UL
-#ifndef HIGHMEM_START
-#define HIGHMEM_START (1UL << 59UL)
-#endif
+#define PAGE_OFFSET 0xffffffff80000000UL
#define CAC_BASE 0xffffffff80000000
#define IO_BASE 0xffffffffa0000000
#define UNCAC_BASE 0xffffffffa0000000
#define MAP_BASE 0xc000000000000000
-#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
-#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
-
#endif /* CONFIG_64BIT */
+#include <asm/mach-generic/spaces.h>
+
#endif /* __ASM_MACH_IP22_SPACES_H */
diff --git a/include/asm-mips/mach-ip27/spaces.h b/include/asm-mips/mach-ip27/spaces.h
index 45e61785ef4..b18802a0b17 100644
--- a/include/asm-mips/mach-ip27/spaces.h
+++ b/include/asm-mips/mach-ip27/spaces.h
@@ -14,22 +14,17 @@
* IP27 uses the R10000's uncached attribute feature. Attribute 3 selects
* uncached memory addressing.
*/
-#define CAC_BASE 0xa800000000000000
#define HSPEC_BASE 0x9000000000000000
#define IO_BASE 0x9200000000000000
#define MSPEC_BASE 0x9400000000000000
#define UNCAC_BASE 0x9600000000000000
-#define MAP_BASE 0xc000000000000000
-#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
-#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
#define TO_MSPEC(x) (MSPEC_BASE | ((x) & TO_PHYS_MASK))
#define TO_HSPEC(x) (HSPEC_BASE | ((x) & TO_PHYS_MASK))
-#define PAGE_OFFSET CAC_BASE
-
#define HIGHMEM_START (~0UL)
+#include <asm/mach-generic/spaces.h>
+
#endif /* _ASM_MACH_IP27_SPACES_H */
diff --git a/include/asm-mips/mach-ip32/dma-coherence.h b/include/asm-mips/mach-ip32/dma-coherence.h
index c3f9a6a20eb..a5511ebb2d5 100644
--- a/include/asm-mips/mach-ip32/dma-coherence.h
+++ b/include/asm-mips/mach-ip32/dma-coherence.h
@@ -6,8 +6,8 @@
* Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org>
*
*/
-#ifndef __ASM_MACH_IP35_DMA_COHERENCE_H
-#define __ASM_MACH_IP35_DMA_COHERENCE_H
+#ifndef __ASM_MACH_IP32_DMA_COHERENCE_H
+#define __ASM_MACH_IP32_DMA_COHERENCE_H
#include <asm/ip32/crime.h>
@@ -69,4 +69,4 @@ static inline int plat_device_is_coherent(struct device *dev)
return 0; /* IP32 is non-cohernet */
}
-#endif /* __ASM_MACH_IP35_DMA_COHERENCE_H */
+#endif /* __ASM_MACH_IP32_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-ip32/spaces.h b/include/asm-mips/mach-ip32/spaces.h
deleted file mode 100644
index 44abe5c0238..00000000000
--- a/include/asm-mips/mach-ip32/spaces.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1999, 2000, 03, 04, 05 Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2000, 2002 Maciej W. Rozycki
- * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef _ASM_MACH_IP32_SPACES_H
-#define _ASM_MACH_IP32_SPACES_H
-
-/*
- * Memory above this physical address will be considered highmem.
- * Fixme: 59 bits is a fictive number and makes assumptions about processors
- * in the distant future. Nobody will care for a few years :-)
- */
-#ifndef HIGHMEM_START
-#define HIGHMEM_START (1UL << 59UL)
-#endif
-
-#define CAC_BASE 0x9800000000000000UL
-#define IO_BASE 0x9000000000000000UL
-#define UNCAC_BASE 0x9000000000000000UL
-#define MAP_BASE 0xc000000000000000UL
-
-#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))
-#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))
-#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))
-
-/*
- * This handles the memory map.
- */
-#define PAGE_OFFSET CAC_BASE
-
-#endif /* __ASM_MACH_IP32_SPACES_H */
diff --git a/include/asm-mips/mach-jmr3927/ioremap.h b/include/asm-mips/mach-jmr3927/ioremap.h
new file mode 100644
index 00000000000..aa131ad7f71
--- /dev/null
+++ b/include/asm-mips/mach-jmr3927/ioremap.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-mips/mach-jmr3927/ioremap.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_JMR3927_IOREMAP_H
+#define __ASM_MACH_JMR3927_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+ return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+ unsigned long flags)
+{
+#define TXX9_DIRECTMAP_BASE 0xff000000ul
+ if (offset >= TXX9_DIRECTMAP_BASE &&
+ offset < TXX9_DIRECTMAP_BASE + 0xf0000)
+ return (void __iomem *)offset;
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return (unsigned long)addr >= TXX9_DIRECTMAP_BASE;
+}
+
+#endif /* __ASM_MACH_JMR3927_IOREMAP_H */
diff --git a/include/asm-mips/mach-lasat/mach-gt64120.h b/include/asm-mips/mach-lasat/mach-gt64120.h
deleted file mode 100644
index 1a9ad45cc13..00000000000
--- a/include/asm-mips/mach-lasat/mach-gt64120.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This is a direct copy of the ev96100.h file, with a global
- * search and replace. The numbers are the same.
- *
- * The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef _ASM_GT64120_LASAT_GT64120_DEP_H
-#define _ASM_GT64120_LASAT_GT64120_DEP_H
-
-/*
- * GT64120 config space base address on Lasat 100
- */
-#define GT64120_BASE (KSEG1ADDR(0x14000000))
-
-/*
- * PCI Bus allocation
- *
- * (Guessing ...)
- */
-#define GT_PCI_MEM_BASE 0x12000000UL
-#define GT_PCI_MEM_SIZE 0x02000000UL
-#define GT_PCI_IO_BASE 0x10000000UL
-#define GT_PCI_IO_SIZE 0x02000000UL
-#define GT_ISA_IO_BASE PCI_IO_BASE
-
-#endif /* _ASM_GT64120_LASAT_GT64120_DEP_H */
diff --git a/include/asm-mips/mach-lemote/dma-coherence.h b/include/asm-mips/mach-lemote/dma-coherence.h
new file mode 100644
index 00000000000..7e914777ebc
--- /dev/null
+++ b/include/asm-mips/mach-lemote/dma-coherence.h
@@ -0,0 +1,42 @@
+/*
+ * 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) 2006, 07 Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
+ * Author: Fuxin Zhang, zhangfx@lemote.com
+ *
+ */
+#ifndef __ASM_MACH_LEMOTE_DMA_COHERENCE_H
+#define __ASM_MACH_LEMOTE_DMA_COHERENCE_H
+
+struct device;
+
+static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
+ size_t size)
+{
+ return virt_to_phys(addr) | 0x80000000;
+}
+
+static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
+ struct page *page)
+{
+ return page_to_phys(page) | 0x80000000;
+}
+
+static inline unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr)
+{
+ return dma_addr & 0x7fffffff;
+}
+
+static inline void plat_unmap_dma_mem(dma_addr_t dma_addr)
+{
+}
+
+static inline int plat_device_is_coherent(struct device *dev)
+{
+ return 0;
+}
+
+#endif /* __ASM_MACH_LEMOTE_DMA_COHERENCE_H */
diff --git a/include/asm-mips/mach-lemote/mc146818rtc.h b/include/asm-mips/mach-lemote/mc146818rtc.h
new file mode 100644
index 00000000000..ed5147e1108
--- /dev/null
+++ b/include/asm-mips/mach-lemote/mc146818rtc.h
@@ -0,0 +1,36 @@
+/*
+ * 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) 1998, 2001, 03, 07 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * RTC routines for PC style attached Dallas chip.
+ */
+#ifndef __ASM_MACH_LEMOTE_MC146818RTC_H
+#define __ASM_MACH_LEMOTE_MC146818RTC_H
+
+#include <linux/io.h>
+
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_IRQ 8
+
+static inline unsigned char CMOS_READ(unsigned long addr)
+{
+ outb_p(addr, RTC_PORT(0));
+ return inb_p(RTC_PORT(1));
+}
+
+static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
+{
+ outb_p(addr, RTC_PORT(0));
+ outb_p(data, RTC_PORT(1));
+}
+
+#define RTC_ALWAYS_BCD 0
+
+#ifndef mc146818_decode_year
+#define mc146818_decode_year(year) ((year) < 70 ? (year) + 2000 : (year) + 1970)
+#endif
+
+#endif /* __ASM_MACH_LEMOTE_MC146818RTC_H */
diff --git a/include/asm-mips/mach-mips/kernel-entry-init.h b/include/asm-mips/mach-mips/kernel-entry-init.h
new file mode 100644
index 00000000000..0b793e7bf67
--- /dev/null
+++ b/include/asm-mips/mach-mips/kernel-entry-init.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ * Chris Dearman (chris@mips.com)
+ * Copyright (C) 2007 Mips Technologies, Inc.
+ */
+#ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
+
+ .macro kernel_entry_setup
+#ifdef CONFIG_MIPS_MT_SMTC
+ mfc0 t0, CP0_CONFIG
+ bgez t0, 9f
+ mfc0 t0, CP0_CONFIG, 1
+ bgez t0, 9f
+ mfc0 t0, CP0_CONFIG, 2
+ bgez t0, 9f
+ mfc0 t0, CP0_CONFIG, 3
+ and t0, 1<<2
+ bnez t0, 0f
+9:
+ /* Assume we came from YAMON... */
+ PTR_LA v0, 0x9fc00534 /* YAMON print */
+ lw v0, (v0)
+ move a0, zero
+ PTR_LA a1, nonmt_processor
+ jal v0
+
+ PTR_LA v0, 0x9fc00520 /* YAMON exit */
+ lw v0, (v0)
+ li a0, 1
+ jal v0
+
+1: b 1b
+
+ __INITDATA
+nonmt_processor:
+ .asciz "SMTC kernel requires the MT ASE to run\n"
+ __FINIT
+0:
+#endif
+ .endm
+
+/*
+ * Do SMP slave processor setup necessary before we can safely execute C code.
+ */
+ .macro smp_slave_setup
+ .endm
+
+#endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */
diff --git a/include/asm-mips/mach-sim/cpu-feature-overrides.h b/include/asm-mips/mach-mipssim/cpu-feature-overrides.h
index 779b0220573..779b0220573 100644
--- a/include/asm-mips/mach-sim/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-mipssim/cpu-feature-overrides.h
diff --git a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h b/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
deleted file mode 100644
index 57a12ded061..00000000000
--- a/include/asm-mips/mach-ocelot3/cpu-feature-overrides.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- * Copyright (C) 2004 Ralf Baechle
- */
-#ifndef __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Momentum Ocelot-3 is based on Rm7900 processor which
- * is based on the E9000 core.
- */
-#define cpu_has_watch 1
-#define cpu_has_mips16 0
-#define cpu_has_divec 0
-#define cpu_has_vce 0
-#define cpu_has_cache_cdex_p 0
-#define cpu_has_cache_cdex_s 0
-#define cpu_has_prefetch 1
-#define cpu_has_mcheck 0
-#define cpu_has_ejtag 0
-
-#define cpu_has_llsc 1
-#define cpu_has_vtag_icache 0
-#define cpu_has_dc_aliases 0
-#define cpu_has_ic_fills_f_dc 0
-#define cpu_has_dsp 0
-#define cpu_icache_snoops_remote_store 0
-
-#define cpu_has_nofpuex 0
-#define cpu_has_64bits 1
-
-#define cpu_has_inclusive_pcaches 0
-
-#define cpu_dcache_line_size() 32
-#define cpu_icache_line_size() 32
-#define cpu_scache_line_size() 32
-
-#define cpu_has_mips32r1 0
-#define cpu_has_mips32r2 0
-#define cpu_has_mips64r1 0
-#define cpu_has_mips64r2 0
-
-#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-tx49xx/ioremap.h b/include/asm-mips/mach-tx49xx/ioremap.h
new file mode 100644
index 00000000000..1e7beae7222
--- /dev/null
+++ b/include/asm-mips/mach-tx49xx/ioremap.h
@@ -0,0 +1,43 @@
+/*
+ * include/asm-mips/mach-tx49xx/ioremap.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef __ASM_MACH_TX49XX_IOREMAP_H
+#define __ASM_MACH_TX49XX_IOREMAP_H
+
+#include <linux/types.h>
+
+/*
+ * Allow physical addresses to be fixed up to help peripherals located
+ * outside the low 32-bit range -- generic pass-through version.
+ */
+static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+ return phys_addr;
+}
+
+static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
+ unsigned long flags)
+{
+#ifdef CONFIG_64BIT
+#define TXX9_DIRECTMAP_BASE 0xfff000000ul
+#else
+#define TXX9_DIRECTMAP_BASE 0xff000000ul
+#endif
+ if (offset >= TXX9_DIRECTMAP_BASE &&
+ offset < TXX9_DIRECTMAP_BASE + 0x400000)
+ return (void __iomem *)(unsigned long)(int)offset;
+ return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+ return (unsigned long)addr >=
+ (unsigned long)(int)(TXX9_DIRECTMAP_BASE & 0xffffffff);
+}
+
+#endif /* __ASM_MACH_TX49XX_IOREMAP_H */
diff --git a/include/asm-mips/mips-boards/atlasint.h b/include/asm-mips/mips-boards/atlasint.h
index 76add42e486..93ba1c1b2a4 100644
--- a/include/asm-mips/mips-boards/atlasint.h
+++ b/include/asm-mips/mips-boards/atlasint.h
@@ -28,11 +28,6 @@
#include <irq.h>
-/*
- * Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode)
- */
-#define MIPSCPU_INT_BASE MIPS_CPU_IRQ_BASE
-
/* CPU interrupt offsets */
#define MIPSCPU_INT_SW0 0
#define MIPSCPU_INT_SW1 1
@@ -42,7 +37,6 @@
#define MIPSCPU_INT_MB2 4
#define MIPSCPU_INT_MB3 5
#define MIPSCPU_INT_MB4 6
-#define MIPSCPU_INT_CPUCTR 7
/*
* Interrupts 8..39 are used for Atlas interrupt controller interrupts
diff --git a/include/asm-mips/mips-boards/bonito64.h b/include/asm-mips/mips-boards/bonito64.h
index cd712561010..dc3fc32eedd 100644
--- a/include/asm-mips/mips-boards/bonito64.h
+++ b/include/asm-mips/mips-boards/bonito64.h
@@ -26,7 +26,12 @@
/* offsets from base register */
#define BONITO(x) (x)
-#else /* !__ASSEMBLY__ */
+#elif defined(CONFIG_LEMOTE_FULONG)
+
+#define BONITO(x) (*(volatile u32 *)((char *)CKSEG1ADDR(BONITO_REG_BASE) + (x)))
+#define BONITO_IRQ_BASE 32
+
+#else
/*
* Algorithmics Bonito64 system controller register base.
diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
index b98f1658cfd..c8ebcc3e126 100644
--- a/include/asm-mips/mips-boards/generic.h
+++ b/include/asm-mips/mips-boards/generic.h
@@ -73,12 +73,28 @@
* CoreEMUL with Bonito System Controller is treated like a Core20K
* CoreEMUL with SOC-it 101 System Controller is treated like a CoreMSC
*/
-#define MIPS_REVISION_CORID_CORE_EMUL_BON 0x63
-#define MIPS_REVISION_CORID_CORE_EMUL_MSC 0x65
+#define MIPS_REVISION_CORID_CORE_EMUL_BON -1
+#define MIPS_REVISION_CORID_CORE_EMUL_MSC -2
#define MIPS_REVISION_CORID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 10) & 0x3f)
-extern unsigned int mips_revision_corid;
+extern int mips_revision_corid;
+
+#define MIPS_REVISION_SCON_OTHER 0
+#define MIPS_REVISION_SCON_SOCITSC 1
+#define MIPS_REVISION_SCON_SOCITSCP 2
+
+/* Artificial SCON defines for MIPS_REVISION_SCON_OTHER */
+#define MIPS_REVISION_SCON_UNKNOWN -1
+#define MIPS_REVISION_SCON_GT64120 -2
+#define MIPS_REVISION_SCON_BONITO -3
+#define MIPS_REVISION_SCON_BRTL -4
+#define MIPS_REVISION_SCON_SOCIT -5
+#define MIPS_REVISION_SCON_ROCIT -6
+
+#define MIPS_REVISION_SCONID (((*(volatile u32 *)ioremap(MIPS_REVISION_REG, 4)) >> 24) & 0xff)
+
+extern int mips_revision_sconid;
#ifdef CONFIG_PCI
extern void mips_pcibios_init(void);
diff --git a/include/asm-mips/mips-boards/maltaint.h b/include/asm-mips/mips-boards/maltaint.h
index 9180d646611..7461318f1cd 100644
--- a/include/asm-mips/mips-boards/maltaint.h
+++ b/include/asm-mips/mips-boards/maltaint.h
@@ -32,11 +32,6 @@
*/
#define MALTA_INT_BASE 0
-/*
- * Interrupts 16..23 are used for Malta CPU interrupts (nonEIC mode)
- */
-#define MIPSCPU_INT_BASE MIPS_CPU_IRQ_BASE
-
/* CPU interrupt offsets */
#define MIPSCPU_INT_SW0 0
#define MIPSCPU_INT_SW1 1
@@ -49,7 +44,6 @@
#define MIPSCPU_INT_COREHI MIPSCPU_INT_MB3
#define MIPSCPU_INT_MB4 6
#define MIPSCPU_INT_CORELO MIPSCPU_INT_MB4
-#define MIPSCPU_INT_CPUCTR 7
/*
* Interrupts 64..127 are used for Soc-it Classic interrupts
diff --git a/include/asm-mips/mips-boards/msc01_pci.h b/include/asm-mips/mips-boards/msc01_pci.h
index 8eaefb837b9..e036b7dd6de 100644
--- a/include/asm-mips/mips-boards/msc01_pci.h
+++ b/include/asm-mips/mips-boards/msc01_pci.h
@@ -208,6 +208,7 @@
* latter, they should be moved elsewhere.
*/
#define MIPS_MSC01_PCI_REG_BASE 0x1bd00000
+#define MIPS_SOCITSC_PCI_REG_BASE 0x1ff10000
extern unsigned long _pcictrl_msc;
diff --git a/include/asm-mips/mips-boards/prom.h b/include/asm-mips/mips-boards/prom.h
index daaf9f98fc6..a9db576a976 100644
--- a/include/asm-mips/mips-boards/prom.h
+++ b/include/asm-mips/mips-boards/prom.h
@@ -33,6 +33,7 @@ extern void prom_meminit(void);
extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
extern void mips_display_message(const char *str);
extern void mips_display_word(unsigned int num);
+extern void mips_scroll_message(void);
extern int get_ethernet_addr(char *ethernet_addr);
/* Memory descriptor management. */
diff --git a/include/asm-mips/mips-boards/seadint.h b/include/asm-mips/mips-boards/seadint.h
index 4f6a3933699..e710bae0734 100644
--- a/include/asm-mips/mips-boards/seadint.h
+++ b/include/asm-mips/mips-boards/seadint.h
@@ -22,14 +22,7 @@
#include <irq.h>
-/*
- * Interrupts 0..7 are used for SEAD CPU interrupts
- */
-#define MIPSCPU_INT_BASE MIPS_CPU_IRQ_BASE
-
#define MIPSCPU_INT_UART0 2
#define MIPSCPU_INT_UART1 3
-#define MIPSCPU_INT_CPUCTR 7
-
#endif /* !(_MIPS_SEADINT_H) */
diff --git a/include/asm-mips/mips-boards/simint.h b/include/asm-mips/mips-boards/simint.h
index 54f2fe621d6..8ef6db76d5c 100644
--- a/include/asm-mips/mips-boards/simint.h
+++ b/include/asm-mips/mips-boards/simint.h
@@ -21,15 +21,11 @@
#define SIM_INT_BASE 0
#define MIPSCPU_INT_MB0 2
-#define MIPSCPU_INT_BASE MIPS_CPU_IRQ_BASE
#define MIPS_CPU_TIMER_IRQ 7
-#define MIPSCPU_INT_CPUCTR 7
-
#define MSC01E_INT_BASE 64
-#define MIPSCPU_INT_CPUCTR 7
#define MSC01E_INT_CPUCTR 11
#endif
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 9985cb7c16e..18f47f1e8cd 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -7,7 +7,7 @@
* Copyright (C) 2000 Silicon Graphics, Inc.
* Modified for further R[236]000 support by Paul M. Antoine, 1996.
* Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2000, 07 MIPS Technologies, Inc.
* Copyright (C) 2003, 2004 Maciej W. Rozycki
*/
#ifndef _ASM_MIPSREGS_H
@@ -15,6 +15,7 @@
#include <linux/linkage.h>
#include <asm/hazards.h>
+#include <asm/war.h>
/*
* The following macros are especially useful for __asm__
@@ -533,6 +534,12 @@
#define MIPS_CONF3_VEIC (_ULCAST_(1) << 6)
#define MIPS_CONF3_LPA (_ULCAST_(1) << 7)
#define MIPS_CONF3_DSP (_ULCAST_(1) << 10)
+#define MIPS_CONF3_ULRI (_ULCAST_(1) << 13)
+
+#define MIPS_CONF7_WII (_ULCAST_(1) << 31)
+
+#define MIPS_CONF7_RPS (_ULCAST_(1) << 2)
+
/*
* Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
@@ -700,10 +707,10 @@ do { \
*/
#define __read_64bit_c0_split(source, sel) \
({ \
- unsigned long long val; \
- unsigned long flags; \
+ unsigned long long __val; \
+ unsigned long __flags; \
\
- local_irq_save(flags); \
+ local_irq_save(__flags); \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
@@ -712,7 +719,7 @@ do { \
"dsrl\t%M0, %M0, 32\n\t" \
"dsrl\t%L0, %L0, 32\n\t" \
".set\tmips0" \
- : "=r" (val)); \
+ : "=r" (__val)); \
else \
__asm__ __volatile__( \
".set\tmips64\n\t" \
@@ -721,17 +728,17 @@ do { \
"dsrl\t%M0, %M0, 32\n\t" \
"dsrl\t%L0, %L0, 32\n\t" \
".set\tmips0" \
- : "=r" (val)); \
- local_irq_restore(flags); \
+ : "=r" (__val)); \
+ local_irq_restore(__flags); \
\
- val; \
+ __val; \
})
#define __write_64bit_c0_split(source, sel, val) \
do { \
- unsigned long flags; \
+ unsigned long __flags; \
\
- local_irq_save(flags); \
+ local_irq_save(__flags); \
if (sel == 0) \
__asm__ __volatile__( \
".set\tmips64\n\t" \
@@ -752,7 +759,7 @@ do { \
"dmtc0\t%L0, " #source ", " #sel "\n\t" \
".set\tmips0" \
: : "r" (val)); \
- local_irq_restore(flags); \
+ local_irq_restore(__flags); \
} while (0)
#define read_c0_index() __read_32bit_c0_register($0, 0)
@@ -770,6 +777,9 @@ do { \
#define read_c0_context() __read_ulong_c0_register($4, 0)
#define write_c0_context(val) __write_ulong_c0_register($4, 0, val)
+#define read_c0_userlocal() __read_ulong_c0_register($4, 2)
+#define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val)
+
#define read_c0_pagemask() __read_32bit_c0_register($5, 0)
#define write_c0_pagemask(val) __write_32bit_c0_register($5, 0, val)
@@ -1292,10 +1302,39 @@ static inline void tlb_probe(void)
static inline void tlb_read(void)
{
+#if MIPS34K_MISSED_ITLB_WAR
+ int res = 0;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " .set noat \n"
+ " .set mips32r2 \n"
+ " .word 0x41610001 # dvpe $1 \n"
+ " move %0, $1 \n"
+ " ehb \n"
+ " .set pop \n"
+ : "=r" (res));
+
+ instruction_hazard();
+#endif
+
__asm__ __volatile__(
".set noreorder\n\t"
"tlbr\n\t"
".set reorder");
+
+#if MIPS34K_MISSED_ITLB_WAR
+ if ((res & _ULCAST_(1)))
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " .set noat \n"
+ " .set mips32r2 \n"
+ " .word 0x41600021 # evpe \n"
+ " ehb \n"
+ " .set pop \n");
+#endif
}
static inline void tlb_write_indexed(void)
diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h
index 399d03f1c4f..de6d09ebbd8 100644
--- a/include/asm-mips/module.h
+++ b/include/asm-mips/module.h
@@ -112,6 +112,8 @@ search_module_dbetables(unsigned long addr)
#define MODULE_PROC_FAMILY "RM9000 "
#elif defined CONFIG_CPU_SB1
#define MODULE_PROC_FAMILY "SB1 "
+#elif defined CONFIG_CPU_LOONGSON2
+#define MODULE_PROC_FAMILY "LOONGSON2 "
#else
#error MODULE_PROC_FAMILY undefined for your processor configuration
#endif
@@ -122,6 +124,13 @@ search_module_dbetables(unsigned long addr)
#define MODULE_KERNEL_TYPE "64BIT "
#endif
-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_KERNEL_TYPE
+#ifdef CONFIG_MIPS_MT_SMTC
+#define MODULE_KERNEL_SMTC "MT_SMTC "
+#else
+#define MODULE_KERNEL_SMTC ""
+#endif
+
+#define MODULE_ARCH_VERMAGIC \
+ MODULE_PROC_FAMILY MODULE_KERNEL_TYPE MODULE_KERNEL_SMTC
#endif /* _ASM_MODULE_H */
diff --git a/include/asm-mips/nile4.h b/include/asm-mips/nile4.h
deleted file mode 100644
index c3ca959aa4d..00000000000
--- a/include/asm-mips/nile4.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions
- *
- * Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- * Sony Software Development Center Europe (SDCE), Brussels
- *
- * This file is based on the following documentation:
- *
- * NEC Vrc 5074 System Controller Data Sheet, June 1998
- */
-
-#ifndef _ASM_NILE4_H
-#define _ASM_NILE4_H
-
-#define NILE4_BASE 0xbfa00000
-#define NILE4_SIZE 0x00200000 /* 2 MB */
-
-
- /*
- * Physical Device Address Registers (PDARs)
- */
-
-#define NILE4_SDRAM0 0x0000 /* SDRAM Bank 0 [R/W] */
-#define NILE4_SDRAM1 0x0008 /* SDRAM Bank 1 [R/W] */
-#define NILE4_DCS2 0x0010 /* Device Chip-Select 2 [R/W] */
-#define NILE4_DCS3 0x0018 /* Device Chip-Select 3 [R/W] */
-#define NILE4_DCS4 0x0020 /* Device Chip-Select 4 [R/W] */
-#define NILE4_DCS5 0x0028 /* Device Chip-Select 5 [R/W] */
-#define NILE4_DCS6 0x0030 /* Device Chip-Select 6 [R/W] */
-#define NILE4_DCS7 0x0038 /* Device Chip-Select 7 [R/W] */
-#define NILE4_DCS8 0x0040 /* Device Chip-Select 8 [R/W] */
-#define NILE4_PCIW0 0x0060 /* PCI Address Window 0 [R/W] */
-#define NILE4_PCIW1 0x0068 /* PCI Address Window 1 [R/W] */
-#define NILE4_INTCS 0x0070 /* Controller Internal Registers and Devices */
- /* [R/W] */
-#define NILE4_BOOTCS 0x0078 /* Boot ROM Chip-Select [R/W] */
-
-
- /*
- * CPU Interface Registers
- */
-
-#define NILE4_CPUSTAT 0x0080 /* CPU Status [R/W] */
-#define NILE4_INTCTRL 0x0088 /* Interrupt Control [R/W] */
-#define NILE4_INTSTAT0 0x0090 /* Interrupt Status 0 [R] */
-#define NILE4_INTSTAT1 0x0098 /* Interrupt Status 1 and CPU Interrupt */
- /* Enable [R/W] */
-#define NILE4_INTCLR 0x00A0 /* Interrupt Clear [R/W] */
-#define NILE4_INTPPES 0x00A8 /* PCI Interrupt Control [R/W] */
-
-
- /*
- * Memory-Interface Registers
- */
-
-#define NILE4_MEMCTRL 0x00C0 /* Memory Control */
-#define NILE4_ACSTIME 0x00C8 /* Memory Access Timing [R/W] */
-#define NILE4_CHKERR 0x00D0 /* Memory Check Error Status [R] */
-
-
- /*
- * PCI-Bus Registers
- */
-
-#define NILE4_PCICTRL 0x00E0 /* PCI Control [R/W] */
-#define NILE4_PCIARB 0x00E8 /* PCI Arbiter [R/W] */
-#define NILE4_PCIINIT0 0x00F0 /* PCI Master (Initiator) 0 [R/W] */
-#define NILE4_PCIINIT1 0x00F8 /* PCI Master (Initiator) 1 [R/W] */
-#define NILE4_PCIERR 0x00B8 /* PCI Error [R/W] */
-
-
- /*
- * Local-Bus Registers
- */
-
-#define NILE4_LCNFG 0x0100 /* Local Bus Configuration [R/W] */
-#define NILE4_LCST2 0x0110 /* Local Bus Chip-Select Timing 2 [R/W] */
-#define NILE4_LCST3 0x0118 /* Local Bus Chip-Select Timing 3 [R/W] */
-#define NILE4_LCST4 0x0120 /* Local Bus Chip-Select Timing 4 [R/W] */
-#define NILE4_LCST5 0x0128 /* Local Bus Chip-Select Timing 5 [R/W] */
-#define NILE4_LCST6 0x0130 /* Local Bus Chip-Select Timing 6 [R/W] */
-#define NILE4_LCST7 0x0138 /* Local Bus Chip-Select Timing 7 [R/W] */
-#define NILE4_LCST8 0x0140 /* Local Bus Chip-Select Timing 8 [R/W] */
-#define NILE4_DCSFN 0x0150 /* Device Chip-Select Muxing and Output */
- /* Enables [R/W] */
-#define NILE4_DCSIO 0x0158 /* Device Chip-Selects As I/O Bits [R/W] */
-#define NILE4_BCST 0x0178 /* Local Boot Chip-Select Timing [R/W] */
-
-
- /*
- * DMA Registers
- */
-
-#define NILE4_DMACTRL0 0x0180 /* DMA Control 0 [R/W] */
-#define NILE4_DMASRCA0 0x0188 /* DMA Source Address 0 [R/W] */
-#define NILE4_DMADESA0 0x0190 /* DMA Destination Address 0 [R/W] */
-#define NILE4_DMACTRL1 0x0198 /* DMA Control 1 [R/W] */
-#define NILE4_DMASRCA1 0x01A0 /* DMA Source Address 1 [R/W] */
-#define NILE4_DMADESA1 0x01A8 /* DMA Destination Address 1 [R/W] */
-
-
- /*
- * Timer Registers
- */
-
-#define NILE4_T0CTRL 0x01C0 /* SDRAM Refresh Control [R/W] */
-#define NILE4_T0CNTR 0x01C8 /* SDRAM Refresh Counter [R/W] */
-#define NILE4_T1CTRL 0x01D0 /* CPU-Bus Read Time-Out Control [R/W] */
-#define NILE4_T1CNTR 0x01D8 /* CPU-Bus Read Time-Out Counter [R/W] */
-#define NILE4_T2CTRL 0x01E0 /* General-Purpose Timer Control [R/W] */
-#define NILE4_T2CNTR 0x01E8 /* General-Purpose Timer Counter [R/W] */
-#define NILE4_T3CTRL 0x01F0 /* Watchdog Timer Control [R/W] */
-#define NILE4_T3CNTR 0x01F8 /* Watchdog Timer Counter [R/W] */
-
-
- /*
- * PCI Configuration Space Registers
- */
-
-#define NILE4_PCI_BASE 0x0200
-
-#define NILE4_VID 0x0200 /* PCI Vendor ID [R] */
-#define NILE4_DID 0x0202 /* PCI Device ID [R] */
-#define NILE4_PCICMD 0x0204 /* PCI Command [R/W] */
-#define NILE4_PCISTS 0x0206 /* PCI Status [R/W] */
-#define NILE4_REVID 0x0208 /* PCI Revision ID [R] */
-#define NILE4_CLASS 0x0209 /* PCI Class Code [R] */
-#define NILE4_CLSIZ 0x020C /* PCI Cache Line Size [R/W] */
-#define NILE4_MLTIM 0x020D /* PCI Latency Timer [R/W] */
-#define NILE4_HTYPE 0x020E /* PCI Header Type [R] */
-#define NILE4_BIST 0x020F /* BIST [R] (unimplemented) */
-#define NILE4_BARC 0x0210 /* PCI Base Address Register Control [R/W] */
-#define NILE4_BAR0 0x0218 /* PCI Base Address Register 0 [R/W] */
-#define NILE4_BAR1 0x0220 /* PCI Base Address Register 1 [R/W] */
-#define NILE4_CIS 0x0228 /* PCI Cardbus CIS Pointer [R] */
- /* (unimplemented) */
-#define NILE4_SSVID 0x022C /* PCI Sub-System Vendor ID [R/W] */
-#define NILE4_SSID 0x022E /* PCI Sub-System ID [R/W] */
-#define NILE4_ROM 0x0230 /* Expansion ROM Base Address [R] */
- /* (unimplemented) */
-#define NILE4_INTLIN 0x023C /* PCI Interrupt Line [R/W] */
-#define NILE4_INTPIN 0x023D /* PCI Interrupt Pin [R] */
-#define NILE4_MINGNT 0x023E /* PCI Min_Gnt [R] (unimplemented) */
-#define NILE4_MAXLAT 0x023F /* PCI Max_Lat [R] (unimplemented) */
-#define NILE4_BAR2 0x0240 /* PCI Base Address Register 2 [R/W] */
-#define NILE4_BAR3 0x0248 /* PCI Base Address Register 3 [R/W] */
-#define NILE4_BAR4 0x0250 /* PCI Base Address Register 4 [R/W] */
-#define NILE4_BAR5 0x0258 /* PCI Base Address Register 5 [R/W] */
-#define NILE4_BAR6 0x0260 /* PCI Base Address Register 6 [R/W] */
-#define NILE4_BAR7 0x0268 /* PCI Base Address Register 7 [R/W] */
-#define NILE4_BAR8 0x0270 /* PCI Base Address Register 8 [R/W] */
-#define NILE4_BARB 0x0278 /* PCI Base Address Register BOOT [R/W] */
-
-
- /*
- * Serial-Port Registers
- */
-
-#define NILE4_UART_BASE 0x0300
-
-#define NILE4_UARTRBR 0x0300 /* UART Receiver Data Buffer [R] */
-#define NILE4_UARTTHR 0x0300 /* UART Transmitter Data Holding [W] */
-#define NILE4_UARTIER 0x0308 /* UART Interrupt Enable [R/W] */
-#define NILE4_UARTDLL 0x0300 /* UART Divisor Latch LSB [R/W] */
-#define NILE4_UARTDLM 0x0308 /* UART Divisor Latch MSB [R/W] */
-#define NILE4_UARTIIR 0x0310 /* UART Interrupt ID [R] */
-#define NILE4_UARTFCR 0x0310 /* UART FIFO Control [W] */
-#define NILE4_UARTLCR 0x0318 /* UART Line Control [R/W] */
-#define NILE4_UARTMCR 0x0320 /* UART Modem Control [R/W] */
-#define NILE4_UARTLSR 0x0328 /* UART Line Status [R/W] */
-#define NILE4_UARTMSR 0x0330 /* UART Modem Status [R/W] */
-#define NILE4_UARTSCR 0x0338 /* UART Scratch [R/W] */
-
-#define NILE4_UART_BASE_BAUD 520833 /* 100 MHz / 12 / 16 */
-
-
- /*
- * Interrupt Lines
- */
-
-#define NILE4_INT_CPCE 0 /* CPU-Interface Parity-Error Interrupt */
-#define NILE4_INT_CNTD 1 /* CPU No-Target Decode Interrupt */
-#define NILE4_INT_MCE 2 /* Memory-Check Error Interrupt */
-#define NILE4_INT_DMA 3 /* DMA Controller Interrupt */
-#define NILE4_INT_UART 4 /* UART Interrupt */
-#define NILE4_INT_WDOG 5 /* Watchdog Timer Interrupt */
-#define NILE4_INT_GPT 6 /* General-Purpose Timer Interrupt */
-#define NILE4_INT_LBRTD 7 /* Local-Bus Ready Timer Interrupt */
-#define NILE4_INT_INTA 8 /* PCI Interrupt Signal INTA# */
-#define NILE4_INT_INTB 9 /* PCI Interrupt Signal INTB# */
-#define NILE4_INT_INTC 10 /* PCI Interrupt Signal INTC# */
-#define NILE4_INT_INTD 11 /* PCI Interrupt Signal INTD# */
-#define NILE4_INT_INTE 12 /* PCI Interrupt Signal INTE# (ISA cascade) */
-#define NILE4_INT_RESV 13 /* Reserved */
-#define NILE4_INT_PCIS 14 /* PCI SERR# Interrupt */
-#define NILE4_INT_PCIE 15 /* PCI Internal Error Interrupt */
-
-
- /*
- * Nile 4 Register Access
- */
-
-static inline void nile4_sync(void)
-{
- volatile u32 *p = (volatile u32 *)0xbfc00000;
- (void)(*p);
-}
-
-static inline void nile4_out32(u32 offset, u32 val)
-{
- *(volatile u32 *)(NILE4_BASE+offset) = val;
- nile4_sync();
-}
-
-static inline u32 nile4_in32(u32 offset)
-{
- u32 val = *(volatile u32 *)(NILE4_BASE+offset);
- nile4_sync();
- return val;
-}
-
-static inline void nile4_out16(u32 offset, u16 val)
-{
- *(volatile u16 *)(NILE4_BASE+offset) = val;
- nile4_sync();
-}
-
-static inline u16 nile4_in16(u32 offset)
-{
- u16 val = *(volatile u16 *)(NILE4_BASE+offset);
- nile4_sync();
- return val;
-}
-
-static inline void nile4_out8(u32 offset, u8 val)
-{
- *(volatile u8 *)(NILE4_BASE+offset) = val;
- nile4_sync();
-}
-
-static inline u8 nile4_in8(u32 offset)
-{
- u8 val = *(volatile u8 *)(NILE4_BASE+offset);
- nile4_sync();
- return val;
-}
-
-
- /*
- * Physical Device Address Registers
- */
-
-extern void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
- int on_memory_bus, int visible);
-
-
- /*
- * PCI Master Registers
- */
-
-#define NILE4_PCICMD_IACK 0 /* PCI Interrupt Acknowledge */
-#define NILE4_PCICMD_IO 1 /* PCI I/O Space */
-#define NILE4_PCICMD_MEM 3 /* PCI Memory Space */
-#define NILE4_PCICMD_CFG 5 /* PCI Configuration Space */
-
-
- /*
- * PCI Address Spaces
- *
- * Note that these are multiplexed using PCIINIT[01]!
- */
-
-#define NILE4_PCI_IO_BASE 0xa6000000
-#define NILE4_PCI_MEM_BASE 0xa8000000
-#define NILE4_PCI_CFG_BASE NILE4_PCI_MEM_BASE
-#define NILE4_PCI_IACK_BASE NILE4_PCI_IO_BASE
-
-
-extern void nile4_set_pmr(u32 pmr, u32 type, u32 addr);
-
-
- /*
- * Interrupt Programming
- */
-
-#define NUM_I8259_INTERRUPTS 16
-#define NUM_NILE4_INTERRUPTS 16
-
-#define IRQ_I8259_CASCADE NILE4_INT_INTE
-#define is_i8259_irq(irq) ((irq) < NUM_I8259_INTERRUPTS)
-#define nile4_to_irq(n) ((n)+NUM_I8259_INTERRUPTS)
-#define irq_to_nile4(n) ((n)-NUM_I8259_INTERRUPTS)
-
-extern void nile4_map_irq(int nile4_irq, int cpu_irq);
-extern void nile4_map_irq_all(int cpu_irq);
-extern void nile4_enable_irq(unsigned int nile4_irq);
-extern void nile4_disable_irq(unsigned int nile4_irq);
-extern void nile4_disable_irq_all(void);
-extern u16 nile4_get_irq_stat(int cpu_irq);
-extern void nile4_enable_irq_output(int cpu_irq);
-extern void nile4_disable_irq_output(int cpu_irq);
-extern void nile4_set_pci_irq_polarity(int pci_irq, int high);
-extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level);
-extern void nile4_clear_irq(int nile4_irq);
-extern void nile4_clear_irq_mask(u32 mask);
-extern u8 nile4_i8259_iack(void);
-extern void nile4_dump_irq_status(void); /* Debug */
-
-#endif
-
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 5c3239dad0f..b92dd8c760d 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -34,12 +34,8 @@
#ifndef __ASSEMBLY__
-/*
- * This gives the physical RAM offset.
- */
-#ifndef PHYS_OFFSET
-#define PHYS_OFFSET 0UL
-#endif
+#include <linux/pfn.h>
+#include <asm/io.h>
/*
* It's normally defined only for FLATMEM config but it's
@@ -48,9 +44,6 @@
*/
#define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET)
-#include <linux/pfn.h>
-#include <asm/io.h>
-
extern void clear_page(void * page);
extern void copy_page(void * to, void * from);
@@ -150,11 +143,15 @@ typedef struct { unsigned long pgprot; } pgprot_t;
* __pa()/__va() should be used only during mem init.
*/
#if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
-#define __pa_page_offset(x) ((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0)
+#define __pa(x) \
+({ \
+ unsigned long __x = (unsigned long)(x); \
+ __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x); \
+})
#else
-#define __pa_page_offset(x) PAGE_OFFSET
+#define __pa(x) \
+ ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
#endif
-#define __pa(x) ((unsigned long)(x) - __pa_page_offset(x) + PHYS_OFFSET)
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x),0))
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 3eea3ba0fca..4fcc185cb2d 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -56,7 +56,7 @@ extern void register_pci_controller(struct pci_controller *hose);
/*
* board supplied pci irq fixup routine
*/
-extern int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
+extern int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
/* Can be used to override the logic in pci_scan_bus for skipping
@@ -121,20 +121,6 @@ extern unsigned int PCI_DMA_BUS_IS_PHYS;
#endif /* CONFIG_DMA_NEED_PCI_MAP_STATE */
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask) (1)
-
-extern dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev,
- struct page *page, unsigned long offset, int direction);
-extern struct page *pci_dac_dma_to_page(struct pci_dev *pdev,
- dma64_addr_t dma_addr);
-extern unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev,
- dma64_addr_t dma_addr);
-extern void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction);
-extern void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
- dma64_addr_t dma_addr, size_t len, int direction);
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
@@ -181,10 +167,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
/* implement the pci_ DMA API in terms of the generic device dma_ one */
#include <asm-generic/pci-dma-compat.h>
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
/* Do platform specific device initialization at pci_enable_device() time */
extern int pcibios_plat_dev_init(struct pci_dev *dev);
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h
new file mode 100644
index 00000000000..c84bcf9570b
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_cic_int.h
@@ -0,0 +1,151 @@
+/*
+ * Defines for the MSP interrupt controller.
+ *
+ * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You 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 _MSP_CIC_INT_H
+#define _MSP_CIC_INT_H
+
+/*
+ * The PMC-Sierra CIC interrupts are all centrally managed by the
+ * CIC sub-system.
+ * We attempt to keep the interrupt numbers as consistent as possible
+ * across all of the MSP devices, but some differences will creep in ...
+ * The interrupts which are directly forwarded to the MIPS core interrupts
+ * are assigned interrupts in the range 0-7, interrupts cascaded through
+ * the CIC are assigned interrupts 8-39. The cascade occurs on C_IRQ4
+ * (MSP_INT_CIC). Currently we don't really distinguish between VPE1
+ * and VPE0 (or thread contexts for that matter). Will have to fix.
+ * The PER interrupts are assigned interrupts in the range 40-71.
+*/
+
+
+/*
+ * IRQs directly forwarded to the CPU
+ */
+#define MSP_MIPS_INTBASE 0
+#define MSP_INT_SW0 0 /* IRQ for swint0, C_SW0 */
+#define MSP_INT_SW1 1 /* IRQ for swint1, C_SW1 */
+#define MSP_INT_MAC0 2 /* IRQ for MAC 0, C_IRQ0 */
+#define MSP_INT_MAC1 3 /* IRQ for MAC 1, C_IRQ1 */
+#define MSP_INT_USB 4 /* IRQ for USB, C_IRQ2 */
+#define MSP_INT_SAR 5 /* IRQ for ADSL2+ SAR, C_IRQ3 */
+#define MSP_INT_CIC 6 /* IRQ for CIC block, C_IRQ4 */
+#define MSP_INT_SEC 7 /* IRQ for Sec engine, C_IRQ5 */
+
+/*
+ * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4)
+ * These defines should be tied to the register definitions for the CIC
+ * interrupt routine. For now, just use hard-coded values.
+ */
+#define MSP_CIC_INTBASE (MSP_MIPS_INTBASE + 8)
+#define MSP_INT_EXT0 (MSP_CIC_INTBASE + 0)
+ /* External interrupt 0 */
+#define MSP_INT_EXT1 (MSP_CIC_INTBASE + 1)
+ /* External interrupt 1 */
+#define MSP_INT_EXT2 (MSP_CIC_INTBASE + 2)
+ /* External interrupt 2 */
+#define MSP_INT_EXT3 (MSP_CIC_INTBASE + 3)
+ /* External interrupt 3 */
+#define MSP_INT_CPUIF (MSP_CIC_INTBASE + 4)
+ /* CPU interface interrupt */
+#define MSP_INT_EXT4 (MSP_CIC_INTBASE + 5)
+ /* External interrupt 4 */
+#define MSP_INT_CIC_USB (MSP_CIC_INTBASE + 6)
+ /* Cascaded IRQ for USB */
+#define MSP_INT_MBOX (MSP_CIC_INTBASE + 7)
+ /* Sec engine mailbox IRQ */
+#define MSP_INT_EXT5 (MSP_CIC_INTBASE + 8)
+ /* External interrupt 5 */
+#define MSP_INT_TDM (MSP_CIC_INTBASE + 9)
+ /* TDM interrupt */
+#define MSP_INT_CIC_MAC0 (MSP_CIC_INTBASE + 10)
+ /* Cascaded IRQ for MAC 0 */
+#define MSP_INT_CIC_MAC1 (MSP_CIC_INTBASE + 11)
+ /* Cascaded IRQ for MAC 1 */
+#define MSP_INT_CIC_SEC (MSP_CIC_INTBASE + 12)
+ /* Cascaded IRQ for sec engine */
+#define MSP_INT_PER (MSP_CIC_INTBASE + 13)
+ /* Peripheral interrupt */
+#define MSP_INT_TIMER0 (MSP_CIC_INTBASE + 14)
+ /* SLP timer 0 */
+#define MSP_INT_TIMER1 (MSP_CIC_INTBASE + 15)
+ /* SLP timer 1 */
+#define MSP_INT_TIMER2 (MSP_CIC_INTBASE + 16)
+ /* SLP timer 2 */
+#define MSP_INT_VPE0_TIMER (MSP_CIC_INTBASE + 17)
+ /* VPE0 MIPS timer */
+#define MSP_INT_BLKCP (MSP_CIC_INTBASE + 18)
+ /* Block Copy */
+#define MSP_INT_UART0 (MSP_CIC_INTBASE + 19)
+ /* UART 0 */
+#define MSP_INT_PCI (MSP_CIC_INTBASE + 20)
+ /* PCI subsystem */
+#define MSP_INT_EXT6 (MSP_CIC_INTBASE + 21)
+ /* External interrupt 5 */
+#define MSP_INT_PCI_MSI (MSP_CIC_INTBASE + 22)
+ /* PCI Message Signal */
+#define MSP_INT_CIC_SAR (MSP_CIC_INTBASE + 23)
+ /* Cascaded ADSL2+ SAR IRQ */
+#define MSP_INT_DSL (MSP_CIC_INTBASE + 24)
+ /* ADSL2+ IRQ */
+#define MSP_INT_CIC_ERR (MSP_CIC_INTBASE + 25)
+ /* SLP error condition */
+#define MSP_INT_VPE1_TIMER (MSP_CIC_INTBASE + 26)
+ /* VPE1 MIPS timer */
+#define MSP_INT_VPE0_PC (MSP_CIC_INTBASE + 27)
+ /* VPE0 Performance counter */
+#define MSP_INT_VPE1_PC (MSP_CIC_INTBASE + 28)
+ /* VPE1 Performance counter */
+#define MSP_INT_EXT7 (MSP_CIC_INTBASE + 29)
+ /* External interrupt 5 */
+#define MSP_INT_VPE0_SW (MSP_CIC_INTBASE + 30)
+ /* VPE0 Software interrupt */
+#define MSP_INT_VPE1_SW (MSP_CIC_INTBASE + 31)
+ /* VPE0 Software interrupt */
+
+/*
+ * IRQs cascaded on CIC PER interrupt (MSP_INT_PER)
+ */
+#define MSP_PER_INTBASE (MSP_CIC_INTBASE + 32)
+/* Reserved 0-1 */
+#define MSP_INT_UART1 (MSP_PER_INTBASE + 2)
+ /* UART 1 */
+/* Reserved 3-5 */
+#define MSP_INT_2WIRE (MSP_PER_INTBASE + 6)
+ /* 2-wire */
+#define MSP_INT_TM0 (MSP_PER_INTBASE + 7)
+ /* Peripheral timer block out 0 */
+#define MSP_INT_TM1 (MSP_PER_INTBASE + 8)
+ /* Peripheral timer block out 1 */
+/* Reserved 9 */
+#define MSP_INT_SPRX (MSP_PER_INTBASE + 10)
+ /* SPI RX complete */
+#define MSP_INT_SPTX (MSP_PER_INTBASE + 11)
+ /* SPI TX complete */
+#define MSP_INT_GPIO (MSP_PER_INTBASE + 12)
+ /* GPIO */
+#define MSP_INT_PER_ERR (MSP_PER_INTBASE + 13)
+ /* Peripheral error */
+/* Reserved 14-31 */
+
+#endif /* !_MSP_CIC_INT_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_int.h
new file mode 100644
index 00000000000..1d9f0547482
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_int.h
@@ -0,0 +1,43 @@
+/*
+ * Defines for the MSP interrupt handlers.
+ *
+ * Copyright (C) 2005, PMC-Sierra, Inc. All rights reserved.
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You 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 _MSP_INT_H
+#define _MSP_INT_H
+
+/*
+ * The PMC-Sierra MSP product line has at least two different interrupt
+ * controllers, the SLP register based scheme and the CIC interrupt
+ * controller block mechanism. This file distinguishes between them
+ * so that devices see a uniform interface.
+ */
+
+#if defined(CONFIG_IRQ_MSP_SLP)
+ #include "msp_slp_int.h"
+#elif defined(CONFIG_IRQ_MSP_CIC)
+ #include "msp_cic_int.h"
+#else
+ #error "What sort of interrupt controller does *your* MSP have?"
+#endif
+
+#endif /* !_MSP_INT_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h b/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h
new file mode 100644
index 00000000000..41560690361
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_pci.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2000-2006 PMC-Sierra INC.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ *
+ * PMC-SIERRA INC. DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _MSP_PCI_H_
+#define _MSP_PCI_H_
+
+#define MSP_HAS_PCI(ID) (((u32)(ID) <= 0x4236) && ((u32)(ID) >= 0x4220))
+
+/*
+ * It is convenient to program the OATRAN register so that
+ * Athena virtual address space and PCI address space are
+ * the same. This is not a requirement, just a convenience.
+ *
+ * The only hard restrictions on the value of OATRAN is that
+ * OATRAN must not be programmed to allow translated memory
+ * addresses to fall within the lowest 512MB of
+ * PCI address space. This region is hardcoded
+ * for use as Athena PCI Host Controller target
+ * access memory space to the Athena's SDRAM.
+ *
+ * Note that OATRAN applies only to memory accesses, not
+ * to I/O accesses.
+ *
+ * To program OATRAN to make Athena virtual address space
+ * and PCI address space have the same values, OATRAN
+ * is to be programmed to 0xB8000000. The top seven
+ * bits of the value mimic the seven bits clipped off
+ * by the PCI Host controller.
+ *
+ * With OATRAN at the said value, when the CPU does
+ * an access to its virtual address at, say 0xB900_5000,
+ * the address appearing on the PCI bus will be
+ * 0xB900_5000.
+ * - Michael Penner
+ */
+#define MSP_PCI_OATRAN 0xB8000000UL
+
+#define MSP_PCI_SPACE_BASE (MSP_PCI_OATRAN + 0x1002000UL)
+#define MSP_PCI_SPACE_SIZE (0x3000000UL - 0x2000)
+#define MSP_PCI_SPACE_END \
+ (MSP_PCI_SPACE_BASE + MSP_PCI_SPACE_SIZE - 1)
+#define MSP_PCI_IOSPACE_BASE (MSP_PCI_OATRAN + 0x1001000UL)
+#define MSP_PCI_IOSPACE_SIZE 0x1000
+#define MSP_PCI_IOSPACE_END \
+ (MSP_PCI_IOSPACE_BASE + MSP_PCI_IOSPACE_SIZE - 1)
+
+/* IRQ for PCI status interrupts */
+#define PCI_STAT_IRQ 20
+
+#define QFLUSH_REG_1 0xB7F40000
+
+typedef volatile unsigned int pcireg;
+typedef void * volatile ppcireg;
+
+struct pci_block_copy
+{
+ pcireg unused1; /* +0x00 */
+ pcireg unused2; /* +0x04 */
+ ppcireg unused3; /* +0x08 */
+ ppcireg unused4; /* +0x0C */
+ pcireg unused5; /* +0x10 */
+ pcireg unused6; /* +0x14 */
+ pcireg unused7; /* +0x18 */
+ ppcireg unused8; /* +0x1C */
+ ppcireg unused9; /* +0x20 */
+ pcireg unusedA; /* +0x24 */
+ ppcireg unusedB; /* +0x28 */
+ ppcireg unusedC; /* +0x2C */
+};
+
+enum
+{
+ config_device_vendor, /* 0 */
+ config_status_command, /* 1 */
+ config_class_revision, /* 2 */
+ config_BIST_header_latency_cache, /* 3 */
+ config_BAR0, /* 4 */
+ config_BAR1, /* 5 */
+ config_BAR2, /* 6 */
+ config_not_used7, /* 7 */
+ config_not_used8, /* 8 */
+ config_not_used9, /* 9 */
+ config_CIS, /* 10 */
+ config_subsystem, /* 11 */
+ config_not_used12, /* 12 */
+ config_capabilities, /* 13 */
+ config_not_used14, /* 14 */
+ config_lat_grant_irq, /* 15 */
+ config_message_control,/* 16 */
+ config_message_addr, /* 17 */
+ config_message_data, /* 18 */
+ config_VPD_addr, /* 19 */
+ config_VPD_data, /* 20 */
+ config_maxregs /* 21 - number of registers */
+};
+
+struct msp_pci_regs
+{
+ pcireg hop_unused_00; /* +0x00 */
+ pcireg hop_unused_04; /* +0x04 */
+ pcireg hop_unused_08; /* +0x08 */
+ pcireg hop_unused_0C; /* +0x0C */
+ pcireg hop_unused_10; /* +0x10 */
+ pcireg hop_unused_14; /* +0x14 */
+ pcireg hop_unused_18; /* +0x18 */
+ pcireg hop_unused_1C; /* +0x1C */
+ pcireg hop_unused_20; /* +0x20 */
+ pcireg hop_unused_24; /* +0x24 */
+ pcireg hop_unused_28; /* +0x28 */
+ pcireg hop_unused_2C; /* +0x2C */
+ pcireg hop_unused_30; /* +0x30 */
+ pcireg hop_unused_34; /* +0x34 */
+ pcireg if_control; /* +0x38 */
+ pcireg oatran; /* +0x3C */
+ pcireg reset_ctl; /* +0x40 */
+ pcireg config_addr; /* +0x44 */
+ pcireg hop_unused_48; /* +0x48 */
+ pcireg msg_signaled_int_status; /* +0x4C */
+ pcireg msg_signaled_int_mask; /* +0x50 */
+ pcireg if_status; /* +0x54 */
+ pcireg if_mask; /* +0x58 */
+ pcireg hop_unused_5C; /* +0x5C */
+ pcireg hop_unused_60; /* +0x60 */
+ pcireg hop_unused_64; /* +0x64 */
+ pcireg hop_unused_68; /* +0x68 */
+ pcireg hop_unused_6C; /* +0x6C */
+ pcireg hop_unused_70; /* +0x70 */
+
+ struct pci_block_copy pci_bc[2] __attribute__((aligned(64)));
+
+ pcireg error_hdr1; /* +0xE0 */
+ pcireg error_hdr2; /* +0xE4 */
+
+ pcireg config[config_maxregs] __attribute__((aligned(256)));
+
+};
+
+#define BPCI_CFGADDR_BUSNUM_SHF 16
+#define BPCI_CFGADDR_FUNCTNUM_SHF 8
+#define BPCI_CFGADDR_REGNUM_SHF 2
+#define BPCI_CFGADDR_ENABLE (1<<31)
+
+#define BPCI_IFCONTROL_RTO (1<<20) /* Retry timeout */
+#define BPCI_IFCONTROL_HCE (1<<16) /* Host configuration enable */
+#define BPCI_IFCONTROL_CTO_SHF 12 /* Shift count for CTO bits */
+#define BPCI_IFCONTROL_SE (1<<5) /* Enable exceptions on errors */
+#define BPCI_IFCONTROL_BIST (1<<4) /* Use BIST in per. mode */
+#define BPCI_IFCONTROL_CAP (1<<3) /* Enable capabilities */
+#define BPCI_IFCONTROL_MMC_SHF 0 /* Shift count for MMC bits */
+
+#define BPCI_IFSTATUS_MGT (1<<8) /* Master Grant timeout */
+#define BPCI_IFSTATUS_MTT (1<<9) /* Master TRDY timeout */
+#define BPCI_IFSTATUS_MRT (1<<10) /* Master retry timeout */
+#define BPCI_IFSTATUS_BC0F (1<<13) /* Block copy 0 fault */
+#define BPCI_IFSTATUS_BC1F (1<<14) /* Block copy 1 fault */
+#define BPCI_IFSTATUS_PCIU (1<<15) /* PCI unable to respond */
+#define BPCI_IFSTATUS_BSIZ (1<<16) /* PCI access with illegal size */
+#define BPCI_IFSTATUS_BADD (1<<17) /* PCI access with illegal addr */
+#define BPCI_IFSTATUS_RTO (1<<18) /* Retry time out */
+#define BPCI_IFSTATUS_SER (1<<19) /* System error */
+#define BPCI_IFSTATUS_PER (1<<20) /* Parity error */
+#define BPCI_IFSTATUS_LCA (1<<21) /* Local CPU abort */
+#define BPCI_IFSTATUS_MEM (1<<22) /* Memory prot. violation */
+#define BPCI_IFSTATUS_ARB (1<<23) /* Arbiter timed out */
+#define BPCI_IFSTATUS_STA (1<<27) /* Signaled target abort */
+#define BPCI_IFSTATUS_TA (1<<28) /* Target abort */
+#define BPCI_IFSTATUS_MA (1<<29) /* Master abort */
+#define BPCI_IFSTATUS_PEI (1<<30) /* Parity error as initiator */
+#define BPCI_IFSTATUS_PET (1<<31) /* Parity error as target */
+
+#define BPCI_RESETCTL_PR (1<<0) /* True if reset asserted */
+#define BPCI_RESETCTL_RT (1<<4) /* Release time */
+#define BPCI_RESETCTL_CT (1<<8) /* Config time */
+#define BPCI_RESETCTL_PE (1<<12) /* PCI enabled */
+#define BPCI_RESETCTL_HM (1<<13) /* PCI host mode */
+#define BPCI_RESETCTL_RI (1<<14) /* PCI reset in */
+
+extern struct msp_pci_regs msp_pci_regs
+ __attribute__((section(".register")));
+extern unsigned long msp_pci_config_space
+ __attribute__((section(".register")));
+
+#endif /* !_MSP_PCI_H_ */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h b/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h
new file mode 100644
index 00000000000..14ca7dc382a
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_prom.h
@@ -0,0 +1,176 @@
+/*
+ * MIPS boards bootprom interface for the Linux kernel.
+ *
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You 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_MSP_PROM_H
+#define _ASM_MSP_PROM_H
+
+#include <linux/types.h>
+
+#define DEVICEID "deviceid"
+#define FEATURES "features"
+#define PROM_ENV "prom_env"
+#define PROM_ENV_FILE "/proc/"PROM_ENV
+#define PROM_ENV_SIZE 256
+
+#define CPU_DEVID_FAMILY 0x0000ff00
+#define CPU_DEVID_REVISION 0x000000ff
+
+#define FPGA_IS_POLO(revision) \
+ (((revision >= 0xb0) && (revision < 0xd0)))
+#define FPGA_IS_5000(revision) \
+ ((revision >= 0x80) && (revision <= 0x90))
+#define FPGA_IS_ZEUS(revision) ((revision < 0x7f))
+#define FPGA_IS_DUET(revision) \
+ (((revision >= 0xa0) && (revision < 0xb0)))
+#define FPGA_IS_MSP4200(revision) ((revision >= 0xd0))
+#define FPGA_IS_MSP7100(revision) ((revision >= 0xd0))
+
+#define MACHINE_TYPE_POLO "POLO"
+#define MACHINE_TYPE_DUET "DUET"
+#define MACHINE_TYPE_ZEUS "ZEUS"
+#define MACHINE_TYPE_MSP2000REVB "MSP2000REVB"
+#define MACHINE_TYPE_MSP5000 "MSP5000"
+#define MACHINE_TYPE_MSP4200 "MSP4200"
+#define MACHINE_TYPE_MSP7120 "MSP7120"
+#define MACHINE_TYPE_MSP7130 "MSP7130"
+#define MACHINE_TYPE_OTHER "OTHER"
+
+#define MACHINE_TYPE_POLO_FPGA "POLO-FPGA"
+#define MACHINE_TYPE_DUET_FPGA "DUET-FPGA"
+#define MACHINE_TYPE_ZEUS_FPGA "ZEUS_FPGA"
+#define MACHINE_TYPE_MSP2000REVB_FPGA "MSP2000REVB-FPGA"
+#define MACHINE_TYPE_MSP5000_FPGA "MSP5000-FPGA"
+#define MACHINE_TYPE_MSP4200_FPGA "MSP4200-FPGA"
+#define MACHINE_TYPE_MSP7100_FPGA "MSP7100-FPGA"
+#define MACHINE_TYPE_OTHER_FPGA "OTHER-FPGA"
+
+/* Device Family definitions */
+#define FAMILY_FPGA 0x0000
+#define FAMILY_ZEUS 0x1000
+#define FAMILY_POLO 0x2000
+#define FAMILY_DUET 0x4000
+#define FAMILY_TRIAD 0x5000
+#define FAMILY_MSP4200 0x4200
+#define FAMILY_MSP4200_FPGA 0x4f00
+#define FAMILY_MSP7100 0x7100
+#define FAMILY_MSP7100_FPGA 0x7f00
+
+/* Device Type definitions */
+#define TYPE_MSP7120 0x7120
+#define TYPE_MSP7130 0x7130
+
+#define ENET_KEY 'E'
+#define ENETTXD_KEY 'e'
+#define PCI_KEY 'P'
+#define PCIMUX_KEY 'p'
+#define SEC_KEY 'S'
+#define SPAD_KEY 'D'
+#define TDM_KEY 'T'
+#define ZSP_KEY 'Z'
+
+#define FEATURE_NOEXIST '-'
+#define FEATURE_EXIST '+'
+
+#define ENET_MII 'M'
+#define ENET_RMII 'R'
+
+#define ENETTXD_FALLING 'F'
+#define ENETTXD_RISING 'R'
+
+#define PCI_HOST 'H'
+#define PCI_PERIPHERAL 'P'
+
+#define PCIMUX_FULL 'F'
+#define PCIMUX_SINGLE 'S'
+
+#define SEC_DUET 'D'
+#define SEC_POLO 'P'
+#define SEC_SLOW 'S'
+#define SEC_TRIAD 'T'
+
+#define SPAD_POLO 'P'
+
+#define TDM_DUET 'D' /* DUET TDMs might exist */
+#define TDM_POLO 'P' /* POLO TDMs might exist */
+#define TDM_TRIAD 'T' /* TRIAD TDMs might exist */
+
+#define ZSP_DUET 'D' /* one DUET zsp engine */
+#define ZSP_TRIAD 'T' /* two TRIAD zsp engines */
+
+extern char *prom_getcmdline(void);
+extern char *prom_getenv(char *name);
+extern void prom_init_cmdline(void);
+extern void prom_meminit(void);
+extern void prom_fixup_mem_map(unsigned long start_mem,
+ unsigned long end_mem);
+
+#ifdef CONFIG_MTD_PMC_MSP_RAMROOT
+extern bool get_ramroot(void **start, unsigned long *size);
+#endif
+
+extern int get_ethernet_addr(char *ethaddr_name, char *ethernet_addr);
+extern unsigned long get_deviceid(void);
+extern char identify_enet(unsigned long interface_num);
+extern char identify_enetTxD(unsigned long interface_num);
+extern char identify_pci(void);
+extern char identify_sec(void);
+extern char identify_spad(void);
+extern char identify_sec(void);
+extern char identify_tdm(void);
+extern char identify_zsp(void);
+extern unsigned long identify_family(void);
+extern unsigned long identify_revision(void);
+
+/*
+ * The following macro calls prom_printf and puts the format string
+ * into an init section so it can be reclaimed.
+ */
+#define ppfinit(f, x...) \
+ do { \
+ static char _f[] __initdata = KERN_INFO f; \
+ printk(_f, ## x); \
+ } while (0)
+
+/* Memory descriptor management. */
+#define PROM_MAX_PMEMBLOCKS 7 /* 6 used */
+
+enum yamon_memtypes {
+ yamon_dontuse,
+ yamon_prom,
+ yamon_free,
+};
+
+struct prom_pmemblock {
+ unsigned long base; /* Within KSEG0. */
+ unsigned int size; /* In bytes. */
+ unsigned int type; /* free or prom memory */
+};
+
+extern int prom_argc;
+extern char **prom_argv;
+extern char **prom_envp;
+extern int *prom_vec;
+extern struct prom_pmemblock *prom_getmdesc(void);
+
+#endif /* !_ASM_MSP_PROM_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h
new file mode 100644
index 00000000000..60a5a38dd5b
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regops.h
@@ -0,0 +1,236 @@
+/*
+ * SMP/VPE-safe functions to access "registers" (see note).
+ *
+ * NOTES:
+* - These macros use ll/sc instructions, so it is your responsibility to
+ * ensure these are available on your platform before including this file.
+ * - The MIPS32 spec states that ll/sc results are undefined for uncached
+ * accesses. This means they can't be used on HW registers accessed
+ * through kseg1. Code which requires these macros for this purpose must
+ * front-end the registers with cached memory "registers" and have a single
+ * thread update the actual HW registers.
+ * - A maximum of 2k of code can be inserted between ll and sc. Every
+ * memory accesses between the instructions will increase the chance of
+ * sc failing and having to loop.
+ * - When using custom_read_reg32/custom_write_reg32 only perform the
+ * necessary logical operations on the register value in between these
+ * two calls. All other logic should be performed before the first call.
+ * - There is a bug on the R10000 chips which has a workaround. If you
+ * are affected by this bug, make sure to define the symbol 'R10000_LLSC_WAR'
+ * to be non-zero. If you are using this header from within linux, you may
+ * include <asm/war.h> before including this file to have this defined
+ * appropriately for you.
+ *
+ * Copyright 2005-2007 PMC-Sierra, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 675
+ * Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_REGOPS_H__
+#define __ASM_REGOPS_H__
+
+#include <linux/types.h>
+
+#include <asm/war.h>
+
+#ifndef R10000_LLSC_WAR
+#define R10000_LLSC_WAR 0
+#endif
+
+#if R10000_LLSC_WAR == 1
+#define __beqz "beqzl "
+#else
+#define __beqz "beqz "
+#endif
+
+#ifndef _LINUX_TYPES_H
+typedef unsigned int u32;
+#endif
+
+/*
+ * Sets all the masked bits to the corresponding value bits
+ */
+static inline void set_value_reg32(volatile u32 *const addr,
+ u32 const mask,
+ u32 const value)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips3 \n"
+ "1: ll %0, %1 # set_value_reg32 \n"
+ " and %0, %2 \n"
+ " or %0, %3 \n"
+ " sc %0, %1 \n"
+ " "__beqz"%0, 1b \n"
+ " nop \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*addr)
+ : "ir" (~mask), "ir" (value), "m" (*addr));
+}
+
+/*
+ * Sets all the masked bits to '1'
+ */
+static inline void set_reg32(volatile u32 *const addr,
+ u32 const mask)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips3 \n"
+ "1: ll %0, %1 # set_reg32 \n"
+ " or %0, %2 \n"
+ " sc %0, %1 \n"
+ " "__beqz"%0, 1b \n"
+ " nop \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*addr)
+ : "ir" (mask), "m" (*addr));
+}
+
+/*
+ * Sets all the masked bits to '0'
+ */
+static inline void clear_reg32(volatile u32 *const addr,
+ u32 const mask)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips3 \n"
+ "1: ll %0, %1 # clear_reg32 \n"
+ " and %0, %2 \n"
+ " sc %0, %1 \n"
+ " "__beqz"%0, 1b \n"
+ " nop \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*addr)
+ : "ir" (~mask), "m" (*addr));
+}
+
+/*
+ * Toggles all masked bits from '0' to '1' and '1' to '0'
+ */
+static inline void toggle_reg32(volatile u32 *const addr,
+ u32 const mask)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set mips3 \n"
+ "1: ll %0, %1 # toggle_reg32 \n"
+ " xor %0, %2 \n"
+ " sc %0, %1 \n"
+ " "__beqz"%0, 1b \n"
+ " nop \n"
+ " .set pop \n"
+ : "=&r" (temp), "=m" (*addr)
+ : "ir" (mask), "m" (*addr));
+}
+
+/*
+ * Read all masked bits others are returned as '0'
+ */
+static inline u32 read_reg32(volatile u32 *const addr,
+ u32 const mask)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " lw %0, %1 # read \n"
+ " and %0, %2 # mask \n"
+ " .set pop \n"
+ : "=&r" (temp)
+ : "m" (*addr), "ir" (mask));
+
+ return temp;
+}
+
+/*
+ * blocking_read_reg32 - Read address with blocking load
+ *
+ * Uncached writes need to be read back to ensure they reach RAM.
+ * The returned value must be 'used' to prevent from becoming a
+ * non-blocking load.
+ */
+static inline u32 blocking_read_reg32(volatile u32 *const addr)
+{
+ u32 temp;
+
+ __asm__ __volatile__(
+ " .set push \n"
+ " .set noreorder \n"
+ " lw %0, %1 # read \n"
+ " move %0, %0 # block \n"
+ " .set pop \n"
+ : "=&r" (temp)
+ : "m" (*addr));
+
+ return temp;
+}
+
+/*
+ * For special strange cases only:
+ *
+ * If you need custom processing within a ll/sc loop, use the following macros
+ * VERY CAREFULLY:
+ *
+ * u32 tmp; <-- Define a variable to hold the data
+ *
+ * custom_read_reg32(address, tmp); <-- Reads the address and put the value
+ * in the 'tmp' variable given
+ *
+ * From here on out, you are (basicly) atomic, so don't do anything too
+ * fancy!
+ * Also, this code may loop if the end of this block fails to write
+ * everything back safely due do the other CPU, so do NOT do anything
+ * with side-effects!
+ *
+ * custom_write_reg32(address, tmp); <-- Writes back 'tmp' safely.
+ */
+#define custom_read_reg32(address, tmp) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set mips3 \n" \
+ "1: ll %0, %1 #custom_read_reg32 \n" \
+ " .set pop \n" \
+ : "=r" (tmp), "=m" (*address) \
+ : "m" (*address))
+
+#define custom_write_reg32(address, tmp) \
+ __asm__ __volatile__( \
+ " .set push \n" \
+ " .set mips3 \n" \
+ " sc %0, %1 #custom_write_reg32 \n" \
+ " "__beqz"%0, 1b \n" \
+ " nop \n" \
+ " .set pop \n" \
+ : "=&r" (tmp), "=m" (*address) \
+ : "0" (tmp), "m" (*address))
+
+#endif /* __ASM_REGOPS_H__ */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
new file mode 100644
index 00000000000..0b56f55206c
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
@@ -0,0 +1,667 @@
+/*
+ * Defines for the address space, registers and register configuration
+ * (bit masks, access macros etc) for the PMC-Sierra line of MSP products.
+ * This file contains addess maps for all the devices in the line of
+ * products but only has register definitions and configuration masks for
+ * registers which aren't definitely associated with any device. Things
+ * like clock settings, reset access, the ELB etc. Individual device
+ * drivers will reference the appropriate XXX_BASE value defined here
+ * and have individual registers offset from that.
+ *
+ * Copyright (C) 2005-2007 PMC-Sierra, Inc. All rights reserved.
+ * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+#include <asm/addrspace.h>
+#include <linux/types.h>
+
+#ifndef _ASM_MSP_REGS_H
+#define _ASM_MSP_REGS_H
+
+/*
+ ########################################################################
+ # Address space and device base definitions #
+ ########################################################################
+ */
+
+/*
+ ***************************************************************************
+ * System Logic and Peripherals (ELB, UART0, etc) device address space *
+ ***************************************************************************
+ */
+#define MSP_SLP_BASE 0x1c000000
+ /* System Logic and Peripherals */
+#define MSP_RST_BASE (MSP_SLP_BASE + 0x10)
+ /* System reset register base */
+#define MSP_RST_SIZE 0x0C /* System reset register space */
+
+#define MSP_WTIMER_BASE (MSP_SLP_BASE + 0x04C)
+ /* watchdog timer base */
+#define MSP_ITIMER_BASE (MSP_SLP_BASE + 0x054)
+ /* internal timer base */
+#define MSP_UART0_BASE (MSP_SLP_BASE + 0x100)
+ /* UART0 controller base */
+#define MSP_BCPY_CTRL_BASE (MSP_SLP_BASE + 0x120)
+ /* Block Copy controller base */
+#define MSP_BCPY_DESC_BASE (MSP_SLP_BASE + 0x160)
+ /* Block Copy descriptor base */
+
+/*
+ ***************************************************************************
+ * PCI address space *
+ ***************************************************************************
+ */
+#define MSP_PCI_BASE 0x19000000
+
+/*
+ ***************************************************************************
+ * MSbus device address space *
+ ***************************************************************************
+ */
+#define MSP_MSB_BASE 0x18000000
+ /* MSbus address start */
+#define MSP_PER_BASE (MSP_MSB_BASE + 0x400000)
+ /* Peripheral device registers */
+#define MSP_MAC0_BASE (MSP_MSB_BASE + 0x600000)
+ /* MAC A device registers */
+#define MSP_MAC1_BASE (MSP_MSB_BASE + 0x700000)
+ /* MAC B device registers */
+#define MSP_MAC_SIZE 0xE0 /* MAC register space */
+
+#define MSP_SEC_BASE (MSP_MSB_BASE + 0x800000)
+ /* Security Engine registers */
+#define MSP_MAC2_BASE (MSP_MSB_BASE + 0x900000)
+ /* MAC C device registers */
+#define MSP_ADSL2_BASE (MSP_MSB_BASE + 0xA80000)
+ /* ADSL2 device registers */
+#define MSP_USB_BASE (MSP_MSB_BASE + 0xB40000)
+ /* USB device registers */
+#define MSP_USB_BASE_START (MSP_MSB_BASE + 0xB40100)
+ /* USB device registers */
+#define MSP_USB_BASE_END (MSP_MSB_BASE + 0xB401FF)
+ /* USB device registers */
+#define MSP_CPUIF_BASE (MSP_MSB_BASE + 0xC00000)
+ /* CPU interface registers */
+
+/* Devices within the MSbus peripheral block */
+#define MSP_UART1_BASE (MSP_PER_BASE + 0x030)
+ /* UART1 controller base */
+#define MSP_SPI_BASE (MSP_PER_BASE + 0x058)
+ /* SPI/MPI control registers */
+#define MSP_TWI_BASE (MSP_PER_BASE + 0x090)
+ /* Two-wire control registers */
+#define MSP_PTIMER_BASE (MSP_PER_BASE + 0x0F0)
+ /* Programmable timer control */
+
+/*
+ ***************************************************************************
+ * Physical Memory configuration address space *
+ ***************************************************************************
+ */
+#define MSP_MEM_CFG_BASE 0x17f00000
+
+#define MSP_MEM_INDIRECT_CTL_10 0x10
+
+/*
+ * Notes:
+ * 1) The SPI registers are split into two blocks, one offset from the
+ * MSP_SPI_BASE by 0x00 and the other offset from the MSP_SPI_BASE by
+ * 0x68. The SPI driver definitions for the register must be aware
+ * of this.
+ * 2) The block copy engine register are divided into two regions, one
+ * for the control/configuration of the engine proper and one for the
+ * values of the descriptors used in the copy process. These have
+ * different base defines (CTRL_BASE vs DESC_BASE)
+ * 3) These constants are for physical addresses which means that they
+ * work correctly with "ioremap" and friends. This means that device
+ * drivers will need to remap these addresses using ioremap and perhaps
+ * the readw/writew macros. Or they could use the regptr() macro
+ * defined below, but the readw/writew calls are the correct thing.
+ * 4) The UARTs have an additional status register offset from the base
+ * address. This register isn't used in the standard 8250 driver but
+ * may be used in other software. Consult the hardware datasheet for
+ * offset details.
+ * 5) For some unknown reason the security engine (MSP_SEC_BASE) registers
+ * start at an offset of 0x84 from the base address but the block of
+ * registers before this is reserved for the security engine. The
+ * driver will have to be aware of this but it makes the register
+ * definitions line up better with the documentation.
+ */
+
+/*
+ ########################################################################
+ # System register definitions. Not associated with a specific device #
+ ########################################################################
+ */
+
+/*
+ * This macro maps the physical register number into uncached space
+ * and (for C code) casts it into a u32 pointer so it can be dereferenced
+ * Normally these would be accessed with ioremap and readX/writeX, but
+ * these are convenient for a lot of internal kernel code.
+ */
+#ifdef __ASSEMBLER__
+ #define regptr(addr) (KSEG1ADDR(addr))
+#else
+ #define regptr(addr) ((volatile u32 *const)(KSEG1ADDR(addr)))
+#endif
+
+/*
+ ***************************************************************************
+ * System Logic and Peripherals (RESET, ELB, etc) registers *
+ ***************************************************************************
+ */
+
+/* System Control register definitions */
+#define DEV_ID_REG regptr(MSP_SLP_BASE + 0x00)
+ /* Device-ID RO */
+#define FWR_ID_REG regptr(MSP_SLP_BASE + 0x04)
+ /* Firmware-ID Register RW */
+#define SYS_ID_REG0 regptr(MSP_SLP_BASE + 0x08)
+ /* System-ID Register-0 RW */
+#define SYS_ID_REG1 regptr(MSP_SLP_BASE + 0x0C)
+ /* System-ID Register-1 RW */
+
+/* System Reset register definitions */
+#define RST_STS_REG regptr(MSP_SLP_BASE + 0x10)
+ /* System Reset Status RO */
+#define RST_SET_REG regptr(MSP_SLP_BASE + 0x14)
+ /* System Set Reset WO */
+#define RST_CLR_REG regptr(MSP_SLP_BASE + 0x18)
+ /* System Clear Reset WO */
+
+/* System Clock Registers */
+#define PCI_SLP_REG regptr(MSP_SLP_BASE + 0x1C)
+ /* PCI clock generator RW */
+#define URT_SLP_REG regptr(MSP_SLP_BASE + 0x20)
+ /* UART clock generator RW */
+/* reserved (MSP_SLP_BASE + 0x24) */
+/* reserved (MSP_SLP_BASE + 0x28) */
+#define PLL1_SLP_REG regptr(MSP_SLP_BASE + 0x2C)
+ /* PLL1 clock generator RW */
+#define PLL0_SLP_REG regptr(MSP_SLP_BASE + 0x30)
+ /* PLL0 clock generator RW */
+#define MIPS_SLP_REG regptr(MSP_SLP_BASE + 0x34)
+ /* MIPS clock generator RW */
+#define VE_SLP_REG regptr(MSP_SLP_BASE + 0x38)
+ /* Voice Eng clock generator RW */
+/* reserved (MSP_SLP_BASE + 0x3C) */
+#define MSB_SLP_REG regptr(MSP_SLP_BASE + 0x40)
+ /* MS-Bus clock generator RW */
+#define SMAC_SLP_REG regptr(MSP_SLP_BASE + 0x44)
+ /* Sec & MAC clock generator RW */
+#define PERF_SLP_REG regptr(MSP_SLP_BASE + 0x48)
+ /* Per & TDM clock generator RW */
+
+/* Interrupt Controller Registers */
+#define SLP_INT_STS_REG regptr(MSP_SLP_BASE + 0x70)
+ /* Interrupt status register RW */
+#define SLP_INT_MSK_REG regptr(MSP_SLP_BASE + 0x74)
+ /* Interrupt enable/mask RW */
+#define SE_MBOX_REG regptr(MSP_SLP_BASE + 0x78)
+ /* Security Engine mailbox RW */
+#define VE_MBOX_REG regptr(MSP_SLP_BASE + 0x7C)
+ /* Voice Engine mailbox RW */
+
+/* ELB Controller Registers */
+#define CS0_CNFG_REG regptr(MSP_SLP_BASE + 0x80)
+ /* ELB CS0 Configuration Reg */
+#define CS0_ADDR_REG regptr(MSP_SLP_BASE + 0x84)
+ /* ELB CS0 Base Address Reg */
+#define CS0_MASK_REG regptr(MSP_SLP_BASE + 0x88)
+ /* ELB CS0 Mask Register */
+#define CS0_ACCESS_REG regptr(MSP_SLP_BASE + 0x8C)
+ /* ELB CS0 access register */
+
+#define CS1_CNFG_REG regptr(MSP_SLP_BASE + 0x90)
+ /* ELB CS1 Configuration Reg */
+#define CS1_ADDR_REG regptr(MSP_SLP_BASE + 0x94)
+ /* ELB CS1 Base Address Reg */
+#define CS1_MASK_REG regptr(MSP_SLP_BASE + 0x98)
+ /* ELB CS1 Mask Register */
+#define CS1_ACCESS_REG regptr(MSP_SLP_BASE + 0x9C)
+ /* ELB CS1 access register */
+
+#define CS2_CNFG_REG regptr(MSP_SLP_BASE + 0xA0)
+ /* ELB CS2 Configuration Reg */
+#define CS2_ADDR_REG regptr(MSP_SLP_BASE + 0xA4)
+ /* ELB CS2 Base Address Reg */
+#define CS2_MASK_REG regptr(MSP_SLP_BASE + 0xA8)
+ /* ELB CS2 Mask Register */
+#define CS2_ACCESS_REG regptr(MSP_SLP_BASE + 0xAC)
+ /* ELB CS2 access register */
+
+#define CS3_CNFG_REG regptr(MSP_SLP_BASE + 0xB0)
+ /* ELB CS3 Configuration Reg */
+#define CS3_ADDR_REG regptr(MSP_SLP_BASE + 0xB4)
+ /* ELB CS3 Base Address Reg */
+#define CS3_MASK_REG regptr(MSP_SLP_BASE + 0xB8)
+ /* ELB CS3 Mask Register */
+#define CS3_ACCESS_REG regptr(MSP_SLP_BASE + 0xBC)
+ /* ELB CS3 access register */
+
+#define CS4_CNFG_REG regptr(MSP_SLP_BASE + 0xC0)
+ /* ELB CS4 Configuration Reg */
+#define CS4_ADDR_REG regptr(MSP_SLP_BASE + 0xC4)
+ /* ELB CS4 Base Address Reg */
+#define CS4_MASK_REG regptr(MSP_SLP_BASE + 0xC8)
+ /* ELB CS4 Mask Register */
+#define CS4_ACCESS_REG regptr(MSP_SLP_BASE + 0xCC)
+ /* ELB CS4 access register */
+
+#define CS5_CNFG_REG regptr(MSP_SLP_BASE + 0xD0)
+ /* ELB CS5 Configuration Reg */
+#define CS5_ADDR_REG regptr(MSP_SLP_BASE + 0xD4)
+ /* ELB CS5 Base Address Reg */
+#define CS5_MASK_REG regptr(MSP_SLP_BASE + 0xD8)
+ /* ELB CS5 Mask Register */
+#define CS5_ACCESS_REG regptr(MSP_SLP_BASE + 0xDC)
+ /* ELB CS5 access register */
+
+/* reserved 0xE0 - 0xE8 */
+#define ELB_1PC_EN_REG regptr(MSP_SLP_BASE + 0xEC)
+ /* ELB single PC card detect */
+
+/* reserved 0xF0 - 0xF8 */
+#define ELB_CLK_CFG_REG regptr(MSP_SLP_BASE + 0xFC)
+ /* SDRAM read/ELB timing Reg */
+
+/* Extended UART status registers */
+#define UART0_STATUS_REG regptr(MSP_UART0_BASE + 0x0c0)
+ /* UART Status Register 0 */
+#define UART1_STATUS_REG regptr(MSP_UART1_BASE + 0x170)
+ /* UART Status Register 1 */
+
+/* Performance monitoring registers */
+#define PERF_MON_CTRL_REG regptr(MSP_SLP_BASE + 0x140)
+ /* Performance monitor control */
+#define PERF_MON_CLR_REG regptr(MSP_SLP_BASE + 0x144)
+ /* Performance monitor clear */
+#define PERF_MON_CNTH_REG regptr(MSP_SLP_BASE + 0x148)
+ /* Perf monitor counter high */
+#define PERF_MON_CNTL_REG regptr(MSP_SLP_BASE + 0x14C)
+ /* Perf monitor counter low */
+
+/* System control registers */
+#define SYS_CTRL_REG regptr(MSP_SLP_BASE + 0x150)
+ /* System control register */
+#define SYS_ERR1_REG regptr(MSP_SLP_BASE + 0x154)
+ /* System Error status 1 */
+#define SYS_ERR2_REG regptr(MSP_SLP_BASE + 0x158)
+ /* System Error status 2 */
+#define SYS_INT_CFG_REG regptr(MSP_SLP_BASE + 0x15C)
+ /* System Interrupt config */
+
+/* Voice Engine Memory configuration */
+#define VE_MEM_REG regptr(MSP_SLP_BASE + 0x17C)
+ /* Voice engine memory config */
+
+/* CPU/SLP Error Status registers */
+#define CPU_ERR1_REG regptr(MSP_SLP_BASE + 0x180)
+ /* CPU/SLP Error status 1 */
+#define CPU_ERR2_REG regptr(MSP_SLP_BASE + 0x184)
+ /* CPU/SLP Error status 1 */
+
+#define EXTENDED_GPIO_REG regptr(MSP_SLP_BASE + 0x188)
+ /* Extended GPIO register */
+
+/* System Error registers */
+#define SLP_ERR_STS_REG regptr(MSP_SLP_BASE + 0x190)
+ /* Int status for SLP errors */
+#define SLP_ERR_MSK_REG regptr(MSP_SLP_BASE + 0x194)
+ /* Int mask for SLP errors */
+#define SLP_ELB_ERST_REG regptr(MSP_SLP_BASE + 0x198)
+ /* External ELB reset */
+#define SLP_BOOT_STS_REG regptr(MSP_SLP_BASE + 0x19C)
+ /* Boot Status */
+
+/* Extended ELB addressing */
+#define CS0_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A0)
+ /* CS0 Extended address */
+#define CS1_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A4)
+ /* CS1 Extended address */
+#define CS2_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1A8)
+ /* CS2 Extended address */
+#define CS3_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1AC)
+ /* CS3 Extended address */
+/* reserved 0x1B0 */
+#define CS5_EXT_ADDR_REG regptr(MSP_SLP_BASE + 0x1B4)
+ /* CS5 Extended address */
+
+/* PLL Adjustment registers */
+#define PLL_LOCK_REG regptr(MSP_SLP_BASE + 0x200)
+ /* PLL0 lock status */
+#define PLL_ARST_REG regptr(MSP_SLP_BASE + 0x204)
+ /* PLL Analog reset status */
+#define PLL0_ADJ_REG regptr(MSP_SLP_BASE + 0x208)
+ /* PLL0 Adjustment value */
+#define PLL1_ADJ_REG regptr(MSP_SLP_BASE + 0x20C)
+ /* PLL1 Adjustment value */
+
+/*
+ ***************************************************************************
+ * Peripheral Register definitions *
+ ***************************************************************************
+ */
+
+/* Peripheral status */
+#define PER_CTRL_REG regptr(MSP_PER_BASE + 0x50)
+ /* Peripheral control register */
+#define PER_STS_REG regptr(MSP_PER_BASE + 0x54)
+ /* Peripheral status register */
+
+/* SPI/MPI Registers */
+#define SMPI_TX_SZ_REG regptr(MSP_PER_BASE + 0x58)
+ /* SPI/MPI Tx Size register */
+#define SMPI_RX_SZ_REG regptr(MSP_PER_BASE + 0x5C)
+ /* SPI/MPI Rx Size register */
+#define SMPI_CTL_REG regptr(MSP_PER_BASE + 0x60)
+ /* SPI/MPI Control register */
+#define SMPI_MS_REG regptr(MSP_PER_BASE + 0x64)
+ /* SPI/MPI Chip Select reg */
+#define SMPI_CORE_DATA_REG regptr(MSP_PER_BASE + 0xC0)
+ /* SPI/MPI Core Data reg */
+#define SMPI_CORE_CTRL_REG regptr(MSP_PER_BASE + 0xC4)
+ /* SPI/MPI Core Control reg */
+#define SMPI_CORE_STAT_REG regptr(MSP_PER_BASE + 0xC8)
+ /* SPI/MPI Core Status reg */
+#define SMPI_CORE_SSEL_REG regptr(MSP_PER_BASE + 0xCC)
+ /* SPI/MPI Core Ssel reg */
+#define SMPI_FIFO_REG regptr(MSP_PER_BASE + 0xD0)
+ /* SPI/MPI Data FIFO reg */
+
+/* Peripheral Block Error Registers */
+#define PER_ERR_STS_REG regptr(MSP_PER_BASE + 0x70)
+ /* Error Bit Status Register */
+#define PER_ERR_MSK_REG regptr(MSP_PER_BASE + 0x74)
+ /* Error Bit Mask Register */
+#define PER_HDR1_REG regptr(MSP_PER_BASE + 0x78)
+ /* Error Header 1 Register */
+#define PER_HDR2_REG regptr(MSP_PER_BASE + 0x7C)
+ /* Error Header 2 Register */
+
+/* Peripheral Block Interrupt Registers */
+#define PER_INT_STS_REG regptr(MSP_PER_BASE + 0x80)
+ /* Interrupt status register */
+#define PER_INT_MSK_REG regptr(MSP_PER_BASE + 0x84)
+ /* Interrupt Mask Register */
+#define GPIO_INT_STS_REG regptr(MSP_PER_BASE + 0x88)
+ /* GPIO interrupt status reg */
+#define GPIO_INT_MSK_REG regptr(MSP_PER_BASE + 0x8C)
+ /* GPIO interrupt MASK Reg */
+
+/* POLO GPIO registers */
+#define POLO_GPIO_DAT1_REG regptr(MSP_PER_BASE + 0x0E0)
+ /* Polo GPIO[8:0] data reg */
+#define POLO_GPIO_CFG1_REG regptr(MSP_PER_BASE + 0x0E4)
+ /* Polo GPIO[7:0] config reg */
+#define POLO_GPIO_CFG2_REG regptr(MSP_PER_BASE + 0x0E8)
+ /* Polo GPIO[15:8] config reg */
+#define POLO_GPIO_OD1_REG regptr(MSP_PER_BASE + 0x0EC)
+ /* Polo GPIO[31:0] output drive */
+#define POLO_GPIO_CFG3_REG regptr(MSP_PER_BASE + 0x170)
+ /* Polo GPIO[23:16] config reg */
+#define POLO_GPIO_DAT2_REG regptr(MSP_PER_BASE + 0x174)
+ /* Polo GPIO[15:9] data reg */
+#define POLO_GPIO_DAT3_REG regptr(MSP_PER_BASE + 0x178)
+ /* Polo GPIO[23:16] data reg */
+#define POLO_GPIO_DAT4_REG regptr(MSP_PER_BASE + 0x17C)
+ /* Polo GPIO[31:24] data reg */
+#define POLO_GPIO_DAT5_REG regptr(MSP_PER_BASE + 0x180)
+ /* Polo GPIO[39:32] data reg */
+#define POLO_GPIO_DAT6_REG regptr(MSP_PER_BASE + 0x184)
+ /* Polo GPIO[47:40] data reg */
+#define POLO_GPIO_DAT7_REG regptr(MSP_PER_BASE + 0x188)
+ /* Polo GPIO[54:48] data reg */
+#define POLO_GPIO_CFG4_REG regptr(MSP_PER_BASE + 0x18C)
+ /* Polo GPIO[31:24] config reg */
+#define POLO_GPIO_CFG5_REG regptr(MSP_PER_BASE + 0x190)
+ /* Polo GPIO[39:32] config reg */
+#define POLO_GPIO_CFG6_REG regptr(MSP_PER_BASE + 0x194)
+ /* Polo GPIO[47:40] config reg */
+#define POLO_GPIO_CFG7_REG regptr(MSP_PER_BASE + 0x198)
+ /* Polo GPIO[54:48] config reg */
+#define POLO_GPIO_OD2_REG regptr(MSP_PER_BASE + 0x19C)
+ /* Polo GPIO[54:32] output drive */
+
+/* Generic GPIO registers */
+#define GPIO_DATA1_REG regptr(MSP_PER_BASE + 0x170)
+ /* GPIO[1:0] data register */
+#define GPIO_DATA2_REG regptr(MSP_PER_BASE + 0x174)
+ /* GPIO[5:2] data register */
+#define GPIO_DATA3_REG regptr(MSP_PER_BASE + 0x178)
+ /* GPIO[9:6] data register */
+#define GPIO_DATA4_REG regptr(MSP_PER_BASE + 0x17C)
+ /* GPIO[15:10] data register */
+#define GPIO_CFG1_REG regptr(MSP_PER_BASE + 0x180)
+ /* GPIO[1:0] config register */
+#define GPIO_CFG2_REG regptr(MSP_PER_BASE + 0x184)
+ /* GPIO[5:2] config register */
+#define GPIO_CFG3_REG regptr(MSP_PER_BASE + 0x188)
+ /* GPIO[9:6] config register */
+#define GPIO_CFG4_REG regptr(MSP_PER_BASE + 0x18C)
+ /* GPIO[15:10] config register */
+#define GPIO_OD_REG regptr(MSP_PER_BASE + 0x190)
+ /* GPIO[15:0] output drive */
+
+/*
+ ***************************************************************************
+ * CPU Interface register definitions *
+ ***************************************************************************
+ */
+#define PCI_FLUSH_REG regptr(MSP_CPUIF_BASE + 0x00)
+ /* PCI-SDRAM queue flush trigger */
+#define OCP_ERR1_REG regptr(MSP_CPUIF_BASE + 0x04)
+ /* OCP Error Attribute 1 */
+#define OCP_ERR2_REG regptr(MSP_CPUIF_BASE + 0x08)
+ /* OCP Error Attribute 2 */
+#define OCP_STS_REG regptr(MSP_CPUIF_BASE + 0x0C)
+ /* OCP Error Status */
+#define CPUIF_PM_REG regptr(MSP_CPUIF_BASE + 0x10)
+ /* CPU policy configuration */
+#define CPUIF_CFG_REG regptr(MSP_CPUIF_BASE + 0x10)
+ /* Misc configuration options */
+
+/* Central Interrupt Controller Registers */
+#define MSP_CIC_BASE (MSP_CPUIF_BASE + 0x8000)
+ /* Central Interrupt registers */
+#define CIC_EXT_CFG_REG regptr(MSP_CIC_BASE + 0x00)
+ /* External interrupt config */
+#define CIC_STS_REG regptr(MSP_CIC_BASE + 0x04)
+ /* CIC Interrupt Status */
+#define CIC_VPE0_MSK_REG regptr(MSP_CIC_BASE + 0x08)
+ /* VPE0 Interrupt Mask */
+#define CIC_VPE1_MSK_REG regptr(MSP_CIC_BASE + 0x0C)
+ /* VPE1 Interrupt Mask */
+#define CIC_TC0_MSK_REG regptr(MSP_CIC_BASE + 0x10)
+ /* Thread Context 0 Int Mask */
+#define CIC_TC1_MSK_REG regptr(MSP_CIC_BASE + 0x14)
+ /* Thread Context 1 Int Mask */
+#define CIC_TC2_MSK_REG regptr(MSP_CIC_BASE + 0x18)
+ /* Thread Context 2 Int Mask */
+#define CIC_TC3_MSK_REG regptr(MSP_CIC_BASE + 0x18)
+ /* Thread Context 3 Int Mask */
+#define CIC_TC4_MSK_REG regptr(MSP_CIC_BASE + 0x18)
+ /* Thread Context 4 Int Mask */
+#define CIC_PCIMSI_STS_REG regptr(MSP_CIC_BASE + 0x18)
+#define CIC_PCIMSI_MSK_REG regptr(MSP_CIC_BASE + 0x18)
+#define CIC_PCIFLSH_REG regptr(MSP_CIC_BASE + 0x18)
+#define CIC_VPE0_SWINT_REG regptr(MSP_CIC_BASE + 0x08)
+
+
+/*
+ ***************************************************************************
+ * Memory controller registers *
+ ***************************************************************************
+ */
+#define MEM_CFG1_REG regptr(MSP_MEM_CFG_BASE + 0x00)
+#define MEM_SS_ADDR regptr(MSP_MEM_CFG_BASE + 0x00)
+#define MEM_SS_DATA regptr(MSP_MEM_CFG_BASE + 0x04)
+#define MEM_SS_WRITE regptr(MSP_MEM_CFG_BASE + 0x08)
+
+/*
+ ***************************************************************************
+ * PCI controller registers *
+ ***************************************************************************
+ */
+#define PCI_BASE_REG regptr(MSP_PCI_BASE + 0x00)
+#define PCI_CONFIG_SPACE_REG regptr(MSP_PCI_BASE + 0x800)
+#define PCI_JTAG_DEVID_REG regptr(MSP_SLP_BASE + 0x13c)
+
+/*
+ ########################################################################
+ # Register content & macro definitions #
+ ########################################################################
+ */
+
+/*
+ ***************************************************************************
+ * DEV_ID defines *
+ ***************************************************************************
+ */
+#define DEV_ID_PCI_DIS (1 << 26) /* Set if PCI disabled */
+#define DEV_ID_PCI_HOST (1 << 20) /* Set if PCI host */
+#define DEV_ID_SINGLE_PC (1 << 19) /* Set if single PC Card */
+#define DEV_ID_FAMILY (0xff << 8) /* family ID code */
+#define POLO_ZEUS_SUB_FAMILY (0x7 << 16) /* sub family for Polo/Zeus */
+
+#define MSPFPGA_ID (0x00 << 8) /* you are on your own here */
+#define MSP5000_ID (0x50 << 8)
+#define MSP4F00_ID (0x4f << 8) /* FPGA version of MSP4200 */
+#define MSP4E00_ID (0x4f << 8) /* FPGA version of MSP7120 */
+#define MSP4200_ID (0x42 << 8)
+#define MSP4000_ID (0x40 << 8)
+#define MSP2XXX_ID (0x20 << 8)
+#define MSPZEUS_ID (0x10 << 8)
+
+#define MSP2004_SUB_ID (0x0 << 16)
+#define MSP2005_SUB_ID (0x1 << 16)
+#define MSP2006_SUB_ID (0x1 << 16)
+#define MSP2007_SUB_ID (0x2 << 16)
+#define MSP2010_SUB_ID (0x3 << 16)
+#define MSP2015_SUB_ID (0x4 << 16)
+#define MSP2020_SUB_ID (0x5 << 16)
+#define MSP2100_SUB_ID (0x6 << 16)
+
+/*
+ ***************************************************************************
+ * RESET defines *
+ ***************************************************************************
+ */
+#define MSP_GR_RST (0x01 << 0) /* Global reset bit */
+#define MSP_MR_RST (0x01 << 1) /* MIPS reset bit */
+#define MSP_PD_RST (0x01 << 2) /* PVC DMA reset bit */
+#define MSP_PP_RST (0x01 << 3) /* PVC reset bit */
+/* reserved */
+#define MSP_EA_RST (0x01 << 6) /* Mac A reset bit */
+#define MSP_EB_RST (0x01 << 7) /* Mac B reset bit */
+#define MSP_SE_RST (0x01 << 8) /* Security Eng reset bit */
+#define MSP_PB_RST (0x01 << 9) /* Per block reset bit */
+#define MSP_EC_RST (0x01 << 10) /* Mac C reset bit */
+#define MSP_TW_RST (0x01 << 11) /* TWI reset bit */
+#define MSP_SPI_RST (0x01 << 12) /* SPI/MPI reset bit */
+#define MSP_U1_RST (0x01 << 13) /* UART1 reset bit */
+#define MSP_U0_RST (0x01 << 14) /* UART0 reset bit */
+
+/*
+ ***************************************************************************
+ * UART defines *
+ ***************************************************************************
+ */
+#ifndef CONFIG_MSP_FPGA
+#define MSP_BASE_BAUD 25000000
+#else
+#define MSP_BASE_BAUD 6000000
+#endif
+#define MSP_UART_REG_LEN 0x20
+
+/*
+ ***************************************************************************
+ * ELB defines *
+ ***************************************************************************
+ */
+#define PCCARD_32 0x02 /* Set if is PCCARD 32 (Cardbus) */
+#define SINGLE_PCCARD 0x01 /* Set to enable single PC card */
+
+/*
+ ***************************************************************************
+ * CIC defines *
+ ***************************************************************************
+ */
+
+/* CIC_EXT_CFG_REG */
+#define EXT_INT_POL(eirq) (1 << (eirq + 8))
+#define EXT_INT_EDGE(eirq) (1 << eirq)
+
+#define CIC_EXT_SET_TRIGGER_LEVEL(reg, eirq) (reg &= ~EXT_INT_EDGE(eirq))
+#define CIC_EXT_SET_TRIGGER_EDGE(reg, eirq) (reg |= EXT_INT_EDGE(eirq))
+#define CIC_EXT_SET_ACTIVE_HI(reg, eirq) (reg |= EXT_INT_POL(eirq))
+#define CIC_EXT_SET_ACTIVE_LO(reg, eirq) (reg &= ~EXT_INT_POL(eirq))
+#define CIC_EXT_SET_ACTIVE_RISING CIC_EXT_SET_ACTIVE_HI
+#define CIC_EXT_SET_ACTIVE_FALLING CIC_EXT_SET_ACTIVE_LO
+
+#define CIC_EXT_IS_TRIGGER_LEVEL(reg, eirq) \
+ ((reg & EXT_INT_EDGE(eirq)) == 0)
+#define CIC_EXT_IS_TRIGGER_EDGE(reg, eirq) (reg & EXT_INT_EDGE(eirq))
+#define CIC_EXT_IS_ACTIVE_HI(reg, eirq) (reg & EXT_INT_POL(eirq))
+#define CIC_EXT_IS_ACTIVE_LO(reg, eirq) \
+ ((reg & EXT_INT_POL(eirq)) == 0)
+#define CIC_EXT_IS_ACTIVE_RISING CIC_EXT_IS_ACTIVE_HI
+#define CIC_EXT_IS_ACTIVE_FALLING CIC_EXT_IS_ACTIVE_LO
+
+/*
+ ***************************************************************************
+ * Memory Controller defines *
+ ***************************************************************************
+ */
+
+/* Indirect memory controller registers */
+#define DDRC_CFG(n) (n)
+#define DDRC_DEBUG(n) (0x04 + n)
+#define DDRC_CTL(n) (0x40 + n)
+
+/* Macro to perform DDRC indirect write */
+#define DDRC_INDIRECT_WRITE(reg, mask, value) \
+({ \
+ *MEM_SS_ADDR = (((mask) & 0xf) << 8) | ((reg) & 0xff); \
+ *MEM_SS_DATA = (value); \
+ *MEM_SS_WRITE = 1; \
+})
+
+/*
+ ***************************************************************************
+ * SPI/MPI Mode *
+ ***************************************************************************
+ */
+#define SPI_MPI_RX_BUSY 0x00008000 /* SPI/MPI Receive Busy */
+#define SPI_MPI_FIFO_EMPTY 0x00004000 /* SPI/MPI Fifo Empty */
+#define SPI_MPI_TX_BUSY 0x00002000 /* SPI/MPI Transmit Busy */
+#define SPI_MPI_FIFO_FULL 0x00001000 /* SPI/MPU FIFO full */
+
+/*
+ ***************************************************************************
+ * SPI/MPI Control Register *
+ ***************************************************************************
+ */
+#define SPI_MPI_RX_START 0x00000004 /* Start receive command */
+#define SPI_MPI_FLUSH_Q 0x00000002 /* Flush SPI/MPI Queue */
+#define SPI_MPI_TX_START 0x00000001 /* Start Transmit Command */
+
+#endif /* !_ASM_MSP_REGS_H */
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h b/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h
new file mode 100644
index 00000000000..96d4c8ce8c8
--- /dev/null
+++ b/include/asm-mips/pmc-sierra/msp71xx/msp_slp_int.h
@@ -0,0 +1,141 @@
+/*
+ * Defines for the MSP interrupt controller.
+ *
+ * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved.
+ * Author: Carsten Langgaard, carstenl@mips.com
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute 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 it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You 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 _MSP_SLP_INT_H
+#define _MSP_SLP_INT_H
+
+/*
+ * The PMC-Sierra SLP interrupts are arranged in a 3 level cascaded
+ * hierarchical system. The first level are the direct MIPS interrupts
+ * and are assigned the interrupt range 0-7. The second level is the SLM
+ * interrupt controller and is assigned the range 8-39. The third level
+ * comprises the Peripherial block, the PCI block, the PCI MSI block and
+ * the SLP. The PCI interrupts and the SLP errors are handled by the
+ * relevant subsystems so the core interrupt code needs only concern
+ * itself with the Peripheral block. These are assigned interrupts in
+ * the range 40-71.
+ */
+
+/*
+ * IRQs directly connected to CPU
+ */
+#define MSP_MIPS_INTBASE 0
+#define MSP_INT_SW0 0 /* IRQ for swint0, C_SW0 */
+#define MSP_INT_SW1 1 /* IRQ for swint1, C_SW1 */
+#define MSP_INT_MAC0 2 /* IRQ for MAC 0, C_IRQ0 */
+#define MSP_INT_MAC1 3 /* IRQ for MAC 1, C_IRQ1 */
+#define MSP_INT_C_IRQ2 4 /* Wired off, C_IRQ2 */
+#define MSP_INT_VE 5 /* IRQ for Voice Engine, C_IRQ3 */
+#define MSP_INT_SLP 6 /* IRQ for SLM block, C_IRQ4 */
+#define MSP_INT_TIMER 7 /* IRQ for the MIPS timer, C_IRQ5 */
+
+/*
+ * IRQs cascaded on CPU interrupt 4 (CAUSE bit 12, C_IRQ4)
+ * These defines should be tied to the register definition for the SLM
+ * interrupt routine. For now, just use hard-coded values.
+ */
+#define MSP_SLP_INTBASE (MSP_MIPS_INTBASE + 8)
+#define MSP_INT_EXT0 (MSP_SLP_INTBASE + 0)
+ /* External interrupt 0 */
+#define MSP_INT_EXT1 (MSP_SLP_INTBASE + 1)
+ /* External interrupt 1 */
+#define MSP_INT_EXT2 (MSP_SLP_INTBASE + 2)
+ /* External interrupt 2 */
+#define MSP_INT_EXT3 (MSP_SLP_INTBASE + 3)
+ /* External interrupt 3 */
+/* Reserved 4-7 */
+
+/*
+ *************************************************************************
+ * DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER/DANGER *
+ * Some MSP produces have this interrupt labelled as Voice and some are *
+ * SEC mbox ... *
+ *************************************************************************
+ */
+#define MSP_INT_SLP_VE (MSP_SLP_INTBASE + 8)
+ /* Cascaded IRQ for Voice Engine*/
+#define MSP_INT_SLP_TDM (MSP_SLP_INTBASE + 9)
+ /* TDM interrupt */
+#define MSP_INT_SLP_MAC0 (MSP_SLP_INTBASE + 10)
+ /* Cascaded IRQ for MAC 0 */
+#define MSP_INT_SLP_MAC1 (MSP_SLP_INTBASE + 11)
+ /* Cascaded IRQ for MAC 1 */
+#define MSP_INT_SEC (MSP_SLP_INTBASE + 12)
+ /* IRQ for security engine */
+#define MSP_INT_PER (MSP_SLP_INTBASE + 13)
+ /* Peripheral interrupt */
+#define MSP_INT_TIMER0 (MSP_SLP_INTBASE + 14)
+ /* SLP timer 0 */
+#define MSP_INT_TIMER1 (MSP_SLP_INTBASE + 15)
+ /* SLP timer 1 */
+#define MSP_INT_TIMER2 (MSP_SLP_INTBASE + 16)
+ /* SLP timer 2 */
+#define MSP_INT_SLP_TIMER (MSP_SLP_INTBASE + 17)
+ /* Cascaded MIPS timer */
+#define MSP_INT_BLKCP (MSP_SLP_INTBASE + 18)
+ /* Block Copy */
+#define MSP_INT_UART0 (MSP_SLP_INTBASE + 19)
+ /* UART 0 */
+#define MSP_INT_PCI (MSP_SLP_INTBASE + 20)
+ /* PCI subsystem */
+#define MSP_INT_PCI_DBELL (MSP_SLP_INTBASE + 21)
+ /* PCI doorbell */
+#define MSP_INT_PCI_MSI (MSP_SLP_INTBASE + 22)
+ /* PCI Message Signal */
+#define MSP_INT_PCI_BC0 (MSP_SLP_INTBASE + 23)
+ /* PCI Block Copy 0 */
+#define MSP_INT_PCI_BC1 (MSP_SLP_INTBASE + 24)
+ /* PCI Block Copy 1 */
+#define MSP_INT_SLP_ERR (MSP_SLP_INTBASE + 25)
+ /* SLP error condition */
+#define MSP_INT_MAC2 (MSP_SLP_INTBASE + 26)
+ /* IRQ for MAC2 */
+/* Reserved 26-31 */
+
+/*
+ * IRQs cascaded on SLP PER interrupt (MSP_INT_PER)
+ */
+#define MSP_PER_INTBASE (MSP_SLP_INTBASE + 32)
+/* Reserved 0-1 */
+#define MSP_INT_UART1 (MSP_PER_INTBASE + 2)
+ /* UART 1 */
+/* Reserved 3-5 */
+#define MSP_INT_2WIRE (MSP_PER_INTBASE + 6)
+ /* 2-wire */
+#define MSP_INT_TM0 (MSP_PER_INTBASE + 7)
+ /* Peripheral timer block out 0 */
+#define MSP_INT_TM1 (MSP_PER_INTBASE + 8)
+ /* Peripheral timer block out 1 */
+/* Reserved 9 */
+#define MSP_INT_SPRX (MSP_PER_INTBASE + 10)
+ /* SPI RX complete */
+#define MSP_INT_SPTX (MSP_PER_INTBASE + 11)
+ /* SPI TX complete */
+#define MSP_INT_GPIO (MSP_PER_INTBASE + 12)
+ /* GPIO */
+#define MSP_INT_PER_ERR (MSP_PER_INTBASE + 13)
+ /* Peripheral error */
+/* Reserved 14-31 */
+
+#endif /* !_MSP_SLP_INT_H */
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 5f80ba71ab9..1d8b9a8ae32 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -82,10 +82,6 @@ struct mips_fpu_struct {
unsigned int fcr31;
};
-#define INIT_FPU { \
- {0,} \
-}
-
#define NUM_DSP_REGS 6
typedef __u32 dspreg_t;
@@ -95,8 +91,6 @@ struct mips_dsp_state {
unsigned int dspcontrol;
};
-#define INIT_DSP {{0,},}
-
#define INIT_CPUMASK { \
{0,} \
}
@@ -155,41 +149,63 @@ struct thread_struct {
#define MF_N64 0
#ifdef CONFIG_MIPS_MT_FPAFF
-#define FPAFF_INIT 0, INIT_CPUMASK,
+#define FPAFF_INIT \
+ .emulated_fp = 0, \
+ .user_cpus_allowed = INIT_CPUMASK,
#else
#define FPAFF_INIT
#endif /* CONFIG_MIPS_MT_FPAFF */
-#define INIT_THREAD { \
- /* \
- * saved main processor registers \
- */ \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, \
- /* \
- * saved cp0 stuff \
- */ \
- 0, \
- /* \
- * saved fpu/fpu emulator stuff \
- */ \
- INIT_FPU, \
- /* \
- * fpu affinity state (null if not FPAFF) \
- */ \
- FPAFF_INIT \
- /* \
- * saved dsp/dsp emulator stuff \
- */ \
- INIT_DSP, \
- /* \
- * Other stuff associated with the process \
- */ \
- 0, 0, 0, 0, \
- /* \
- * For now the default is to fix address errors \
- */ \
- MF_FIXADE, 0, 0 \
+#define INIT_THREAD { \
+ /* \
+ * Saved main processor registers \
+ */ \
+ .reg16 = 0, \
+ .reg17 = 0, \
+ .reg18 = 0, \
+ .reg19 = 0, \
+ .reg20 = 0, \
+ .reg21 = 0, \
+ .reg22 = 0, \
+ .reg23 = 0, \
+ .reg29 = 0, \
+ .reg30 = 0, \
+ .reg31 = 0, \
+ /* \
+ * Saved cp0 stuff \
+ */ \
+ .cp0_status = 0, \
+ /* \
+ * Saved FPU/FPU emulator stuff \
+ */ \
+ .fpu = { \
+ .fpr = {0,}, \
+ .fcr31 = 0, \
+ }, \
+ /* \
+ * FPU affinity state (null if not FPAFF) \
+ */ \
+ FPAFF_INIT \
+ /* \
+ * Saved DSP stuff \
+ */ \
+ .dsp = { \
+ .dspr = {0, }, \
+ .dspcontrol = 0, \
+ }, \
+ /* \
+ * Other stuff associated with the process \
+ */ \
+ .cp0_badvaddr = 0, \
+ .cp0_baduaddr = 0, \
+ .error_code = 0, \
+ .trap_no = 0, \
+ /* \
+ * For now the default is to fix address errors \
+ */ \
+ .mflags = MF_FIXADE, \
+ .irix_trampoline = 0, \
+ .irix_oldctx = 0, \
}
struct task_struct;
@@ -237,7 +253,7 @@ unsigned long get_wchan(struct task_struct *p);
#define ARCH_HAS_PREFETCH
-extern inline void prefetch(const void *addr)
+static inline void prefetch(const void *addr)
{
__asm__ __volatile__(
" .set mips4 \n"
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 1906938285c..85b44366343 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -86,7 +86,7 @@ struct pt_regs {
extern asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit);
-extern NORET_TYPE void die(const char *, struct pt_regs *);
+extern NORET_TYPE void die(const char *, struct pt_regs *) ATTRIB_NORET;
static inline void die_if_kernel(const char *str, struct pt_regs *regs)
{
diff --git a/include/asm-mips/rtc.h b/include/asm-mips/rtc.h
deleted file mode 100644
index 82ad401c7dc..00000000000
--- a/include/asm-mips/rtc.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * include/asm-mips/rtc.h
- *
- * (Really an interface for drivers/char/genrtc.c)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * Please read the COPYING file for all license details.
- */
-
-#ifndef _MIPS_RTC_H
-#define _MIPS_RTC_H
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-#include <asm/time.h>
-
-#define RTC_PIE 0x40 /* periodic interrupt enable */
-#define RTC_AIE 0x20 /* alarm interrupt enable */
-#define RTC_UIE 0x10 /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100 /* battery bad */
-#define RTC_SQWE 0x08 /* enable square-wave output */
-#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
-#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
-
-static inline unsigned int get_rtc_time(struct rtc_time *time)
-{
- unsigned long nowtime;
-
- nowtime = rtc_mips_get_time();
- to_tm(nowtime, time);
- time->tm_year -= 1900;
-
- return RTC_24H;
-}
-
-static inline int set_rtc_time(struct rtc_time *time)
-{
- unsigned long nowtime;
- int ret;
-
- nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
- time->tm_mday, time->tm_hour, time->tm_min,
- time->tm_sec);
- ret = rtc_mips_set_time(nowtime);
-
- return ret;
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
- struct rtc_time h;
-
- get_rtc_time(&h);
- return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
- return -EINVAL;
-}
-
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
- return -EINVAL;
-}
-#endif
-#endif
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index ce51213d84f..c07ebd8eb9e 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -19,159 +19,4 @@
*/
#define BASE_BAUD (1843200 / 16)
-/* Standard COM flags (except for COM4, because of the 8514 problem) */
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
-#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
-#endif
-
-#ifdef CONFIG_MACH_JAZZ
-#include <asm/jazz.h>
-
-#ifndef CONFIG_OLIVETTI_M700
- /* Some Jazz machines seem to have an 8MHz crystal clock but I don't know
- exactly which ones ... XXX */
-#define JAZZ_BASE_BAUD ( 8000000 / 16 ) /* ( 3072000 / 16) */
-#else
-/* but the M700 isn't such a strange beast */
-#define JAZZ_BASE_BAUD BASE_BAUD
-#endif
-
-#define _JAZZ_SERIAL_INIT(int, base) \
- { .baud_base = JAZZ_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS, \
- .iomem_base = (u8 *) base, .iomem_reg_shift = 0, \
- .io_type = SERIAL_IO_MEM }
-#define JAZZ_SERIAL_PORT_DEFNS \
- _JAZZ_SERIAL_INIT(JAZZ_SERIAL1_IRQ, JAZZ_SERIAL1_BASE), \
- _JAZZ_SERIAL_INIT(JAZZ_SERIAL2_IRQ, JAZZ_SERIAL2_BASE),
-#else
-#define JAZZ_SERIAL_PORT_DEFNS
-#endif
-
-/*
- * Galileo EV64120 evaluation board
- */
-#ifdef CONFIG_MIPS_EV64120
-#include <mach-gt64120.h>
-#define EV64120_SERIAL_PORT_DEFNS \
- { .baud_base = EV64120_BASE_BAUD, .irq = EV64120_UART_IRQ, \
- .flags = STD_COM_FLAGS, \
- .iomem_base = EV64120_UART0_REGS_BASE, .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM }, \
- { .baud_base = EV64120_BASE_BAUD, .irq = EV64120_UART_IRQ, \
- .flags = STD_COM_FLAGS, \
- .iomem_base = EV64120_UART1_REGS_BASE, .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM },
-#else
-#define EV64120_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT
-#define STD_SERIAL_PORT_DEFNS \
- /* UART CLK PORT IRQ FLAGS */ \
- { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
- { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
- { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
-
-#else /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-#define STD_SERIAL_PORT_DEFNS
-#endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
-
-#ifdef CONFIG_MOMENCO_OCELOT_3
-#define OCELOT_3_BASE_BAUD ( 20000000 / 16 )
-#define OCELOT_3_SERIAL_IRQ 6
-#define OCELOT_3_SERIAL_BASE (signed)0xfd000020
-
-#define _OCELOT_3_SERIAL_INIT(int, base) \
- { .baud_base = OCELOT_3_BASE_BAUD, irq: int, \
- .flags = STD_COM_FLAGS, \
- .iomem_base = (u8 *) base, iomem_reg_shift: 2, \
- io_type: SERIAL_IO_MEM }
-
-#define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \
- _OCELOT_3_SERIAL_INIT(OCELOT_3_SERIAL_IRQ, OCELOT_3_SERIAL_BASE)
-#else
-#define MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MOMENCO_OCELOT
-/* Ordinary NS16552 duart with a 20MHz crystal. */
-#define OCELOT_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_SERIAL1_IRQ 4
-#define OCELOT_SERIAL1_BASE 0xe0001020
-
-#define _OCELOT_SERIAL_INIT(int, base) \
- { .baud_base = OCELOT_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS, \
- .iomem_base = (u8 *) base, .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM }
-#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
- _OCELOT_SERIAL_INIT(OCELOT_SERIAL1_IRQ, OCELOT_SERIAL1_BASE)
-#else
-#define MOMENCO_OCELOT_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_MOMENCO_OCELOT_C
-/* Ordinary NS16552 duart with a 20MHz crystal. */
-#define OCELOT_C_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_C_SERIAL1_IRQ 80
-#define OCELOT_C_SERIAL1_BASE 0xfd000020
-
-#define OCELOT_C_SERIAL2_IRQ 81
-#define OCELOT_C_SERIAL2_BASE 0xfd000000
-
-#define _OCELOT_C_SERIAL_INIT(int, base) \
- { .baud_base = OCELOT_C_BASE_BAUD, \
- .irq = (int), \
- .flags = STD_COM_FLAGS, \
- .iomem_base = (u8 *) base, \
- .iomem_reg_shift = 2, \
- .io_type = SERIAL_IO_MEM \
- }
-#define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \
- _OCELOT_C_SERIAL_INIT(OCELOT_C_SERIAL1_IRQ, OCELOT_C_SERIAL1_BASE), \
- _OCELOT_C_SERIAL_INIT(OCELOT_C_SERIAL2_IRQ, OCELOT_C_SERIAL2_BASE)
-#else
-#define MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_DDB5477
-#include <asm/ddb5xxx/ddb5477.h>
-#define DDB5477_SERIAL_PORT_DEFNS \
- { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART0, \
- .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04200, \
- .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM}, \
- { .baud_base = BASE_BAUD, .irq = VRC5477_IRQ_UART1, \
- .flags = STD_COM_FLAGS, .iomem_base = (u8*)0xbfa04240, \
- .iomem_reg_shift = 3, .io_type = SERIAL_IO_MEM},
-#else
-#define DDB5477_SERIAL_PORT_DEFNS
-#endif
-
-#ifdef CONFIG_SGI_IP32
-/*
- * The IP32 (SGI O2) has standard serial ports (UART 16550A) mapped in memory
- * They are initialized in ip32_setup
- */
-#define IP32_SERIAL_PORT_DEFNS \
- {},{},
-#else
-#define IP32_SERIAL_PORT_DEFNS
-#endif /* CONFIG_SGI_IP32 */
-
-#define SERIAL_PORT_DFNS \
- DDB5477_SERIAL_PORT_DEFNS \
- EV64120_SERIAL_PORT_DEFNS \
- IP32_SERIAL_PORT_DEFNS \
- JAZZ_SERIAL_PORT_DEFNS \
- STD_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_SERIAL_PORT_DEFNS \
- MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
-
#endif /* _ASM_SERIAL_H */
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index 1608fd71d6f..13aef6af422 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -49,13 +49,6 @@ extern struct call_data_struct *call_data;
extern cpumask_t phys_cpu_present_map;
#define cpu_possible_map phys_cpu_present_map
-extern cpumask_t cpu_callout_map;
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
-static inline int num_booting_cpus(void)
-{
- return cpus_weight(cpu_callout_map);
-}
-
/*
* These are defined by the board-specific code.
*/
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
index f257509b914..ddaf36a1e38 100644
--- a/include/asm-mips/sni.h
+++ b/include/asm-mips/sni.h
@@ -146,9 +146,6 @@ extern unsigned int sni_brd_type;
#define SNI_A20R_IRQ_BASE MIPS_CPU_IRQ_BASE
#define SNI_A20R_IRQ_TIMER (SNI_A20R_IRQ_BASE+5)
-#define SNI_DS1216_A20R_BASE 0xbc081ffc
-#define SNI_DS1216_RM200_BASE 0xbcd41ffc
-
#define SNI_PCIT_INT_REG 0xbfff000c
#define SNI_PCIT_INT_START 24
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index 7afa1fdf70c..ed33366b85b 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -17,6 +17,18 @@
#include <asm/mipsregs.h>
#include <asm/asm-offsets.h>
+/*
+ * For SMTC kernel, global IE should be left set, and interrupts
+ * controlled exclusively via IXMT.
+ */
+#ifdef CONFIG_MIPS_MT_SMTC
+#define STATMASK 0x1e
+#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+#define STATMASK 0x3f
+#else
+#define STATMASK 0x1f
+#endif
+
#ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h>
#endif /* CONFIG_MIPS_MT_SMTC */
@@ -236,10 +248,10 @@
.set reorder
.set noat
mfc0 a0, CP0_STATUS
- ori a0, 0x1f
- xori a0, 0x1f
- mtc0 a0, CP0_STATUS
li v1, 0xff00
+ ori a0, STATMASK
+ xori a0, STATMASK
+ mtc0 a0, CP0_STATUS
and a0, v1
LONG_L v0, PT_STATUS(sp)
nor v1, $0, v1
@@ -249,10 +261,6 @@
LONG_L $31, PT_R31(sp)
LONG_L $28, PT_R28(sp)
LONG_L $25, PT_R25(sp)
-#ifdef CONFIG_64BIT
- LONG_L $8, PT_R8(sp)
- LONG_L $9, PT_R9(sp)
-#endif
LONG_L $7, PT_R7(sp)
LONG_L $6, PT_R6(sp)
LONG_L $5, PT_R5(sp)
@@ -273,16 +281,6 @@
.endm
#else
-/*
- * For SMTC kernel, global IE should be left set, and interrupts
- * controlled exclusively via IXMT.
- */
-
-#ifdef CONFIG_MIPS_MT_SMTC
-#define STATMASK 0x1e
-#else
-#define STATMASK 0x1f
-#endif
.macro RESTORE_SOME
.set push
.set reorder
@@ -385,9 +383,9 @@
.macro CLI
#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | 0x1f
+ li t1, ST0_CU0 | STATMASK
or t0, t1
- xori t0, 0x1f
+ xori t0, STATMASK
mtc0 t0, CP0_STATUS
#else /* CONFIG_MIPS_MT_SMTC */
/*
@@ -420,9 +418,9 @@
.macro STI
#if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | 0x1f
+ li t1, ST0_CU0 | STATMASK
or t0, t1
- xori t0, 0x1e
+ xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
#else /* CONFIG_MIPS_MT_SMTC */
/*
@@ -451,7 +449,8 @@
.endm
/*
- * Just move to kernel mode and leave interrupts as they are.
+ * Just move to kernel mode and leave interrupts as they are. Note
+ * for the R3000 this means copying the previous enable from IEp.
* Set cp0 enable bit as sign that we're running on the kernel stack
*/
.macro KMODE
@@ -482,9 +481,14 @@
move ra, t0
#endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS
- li t1, ST0_CU0 | 0x1e
+ li t1, ST0_CU0 | (STATMASK & ~1)
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+ andi t2, t0, ST0_IEP
+ srl t2, 2
+ or t0, t2
+#endif
or t0, t1
- xori t0, 0x1e
+ xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS
#ifdef CONFIG_MIPS_MT_SMTC
_ehb
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index bb0b289dbc9..46bdb3f566f 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -44,7 +44,7 @@ struct task_struct;
* different thread.
*/
-#define switch_to(prev,next,last) \
+#define __mips_mt_fpaff_switch_to(prev) \
do { \
if (cpu_has_fpu && \
(prev->thread.mflags & MF_FPUBOUND) && \
@@ -52,24 +52,24 @@ do { \
prev->thread.mflags &= ~MF_FPUBOUND; \
prev->cpus_allowed = prev->thread.user_cpus_allowed; \
} \
- if (cpu_has_dsp) \
- __save_dsp(prev); \
next->thread.emulated_fp = 0; \
- (last) = resume(prev, next, task_thread_info(next)); \
- if (cpu_has_dsp) \
- __restore_dsp(current); \
} while(0)
#else
+#define __mips_mt_fpaff_switch_to(prev) do { (void) (prev); } while (0)
+#endif
+
#define switch_to(prev,next,last) \
do { \
+ __mips_mt_fpaff_switch_to(prev); \
if (cpu_has_dsp) \
__save_dsp(prev); \
(last) = resume(prev, next, task_thread_info(next)); \
if (cpu_has_dsp) \
__restore_dsp(current); \
+ if (cpu_has_userlocal) \
+ write_c0_userlocal(task_thread_info(current)->tp_value);\
} while(0)
-#endif
/*
* On SMP systems, when the scheduler does migration-cost autodetection,
diff --git a/include/asm-mips/termbits.h b/include/asm-mips/termbits.h
index 0bbe07b42a0..5bfdc3b6451 100644
--- a/include/asm-mips/termbits.h
+++ b/include/asm-mips/termbits.h
@@ -30,6 +30,17 @@ struct termios {
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 */
diff --git a/include/asm-mips/tlbdebug.h b/include/asm-mips/tlbdebug.h
index fff7a73e22d..bb8f5c29c3d 100644
--- a/include/asm-mips/tlbdebug.h
+++ b/include/asm-mips/tlbdebug.h
@@ -11,10 +11,6 @@
/*
* TLB debugging functions:
*/
-extern void dump_tlb(int first, int last);
extern void dump_tlb_all(void);
-extern void dump_tlb_wired(void);
-extern void dump_tlb_addr(unsigned long addr);
-extern void dump_tlb_nonwired(void);
#endif /* __ASM_TLBDEBUG_H */
diff --git a/include/asm-mips/tx4938/rbtx4938.h b/include/asm-mips/tx4938/rbtx4938.h
index 0fbedafdcea..74e7d8061e5 100644
--- a/include/asm-mips/tx4938/rbtx4938.h
+++ b/include/asm-mips/tx4938/rbtx4938.h
@@ -105,12 +105,6 @@
#define rbtx4938_pcireset_ptr \
((volatile unsigned char *)RBTX4938_PCIRESET_ADDR)
-/* SPI */
-#define RBTX4938_SEEPROM1_CHIPID 0
-#define RBTX4938_SEEPROM2_CHIPID 1
-#define RBTX4938_SEEPROM3_CHIPID 2
-#define RBTX4938_SRTC_CHIPID 3
-
/*
* IRQ mappings
*/
diff --git a/include/asm-mips/tx4938/spi.h b/include/asm-mips/tx4938/spi.h
index 0dbbab820a5..6a60c83e152 100644
--- a/include/asm-mips/tx4938/spi.h
+++ b/include/asm-mips/tx4938/spi.h
@@ -14,61 +14,7 @@
#ifndef __ASM_TX_BOARDS_TX4938_SPI_H
#define __ASM_TX_BOARDS_TX4938_SPI_H
-/* SPI */
-struct spi_dev_desc {
- unsigned int baud;
- unsigned short tcss, tcsh, tcsr; /* CS setup/hold/recovery time */
- unsigned int byteorder:1; /* 0:LSB-First, 1:MSB-First */
- unsigned int polarity:1; /* 0:High-Active */
- unsigned int phase:1; /* 0:Sample-Then-Shift */
-};
-
-extern void txx9_spi_init(unsigned long base, int (*cs_func)(int chipid, int on)) __init;
-extern void txx9_spi_irqinit(int irc_irq) __init;
-extern int txx9_spi_io(int chipid, struct spi_dev_desc *desc,
- unsigned char **inbufs, unsigned int *incounts,
- unsigned char **outbufs, unsigned int *outcounts,
- int cansleep);
-extern int spi_eeprom_write_enable(int chipid, int enable);
-extern int spi_eeprom_read_status(int chipid);
+extern int spi_eeprom_register(int chipid);
extern int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len);
-extern int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len);
-extern void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid) __init;
-
-#define TXX9_IMCLK (txx9_gbus_clock / 2)
-
-/*
-* SPI
-*/
-
-/* SPMCR : SPI Master Control */
-#define TXx9_SPMCR_OPMODE 0xc0
-#define TXx9_SPMCR_CONFIG 0x40
-#define TXx9_SPMCR_ACTIVE 0x80
-#define TXx9_SPMCR_SPSTP 0x02
-#define TXx9_SPMCR_BCLR 0x01
-
-/* SPCR0 : SPI Status */
-#define TXx9_SPCR0_TXIFL_MASK 0xc000
-#define TXx9_SPCR0_RXIFL_MASK 0x3000
-#define TXx9_SPCR0_SIDIE 0x0800
-#define TXx9_SPCR0_SOEIE 0x0400
-#define TXx9_SPCR0_RBSIE 0x0200
-#define TXx9_SPCR0_TBSIE 0x0100
-#define TXx9_SPCR0_IFSPSE 0x0010
-#define TXx9_SPCR0_SBOS 0x0004
-#define TXx9_SPCR0_SPHA 0x0002
-#define TXx9_SPCR0_SPOL 0x0001
-
-/* SPSR : SPI Status */
-#define TXx9_SPSR_TBSI 0x8000
-#define TXx9_SPSR_RBSI 0x4000
-#define TXx9_SPSR_TBS_MASK 0x3800
-#define TXx9_SPSR_RBS_MASK 0x0700
-#define TXx9_SPSR_SPOE 0x0080
-#define TXx9_SPSR_IFSD 0x0008
-#define TXx9_SPSR_SIDLE 0x0004
-#define TXx9_SPSR_STRDY 0x0002
-#define TXx9_SPSR_SRRDY 0x0001
#endif /* __ASM_TX_BOARDS_TX4938_SPI_H */
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 2f1087b3a20..ed16de0a639 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -336,16 +336,20 @@
#define __NR_epoll_pwait (__NR_Linux + 313)
#define __NR_ioprio_set (__NR_Linux + 314)
#define __NR_ioprio_get (__NR_Linux + 315)
+#define __NR_utimensat (__NR_Linux + 316)
+#define __NR_signalfd (__NR_Linux + 317)
+#define __NR_timerfd (__NR_Linux + 318)
+#define __NR_eventfd (__NR_Linux + 319)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 315
+#define __NR_Linux_syscalls 319
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 315
+#define __NR_O32_Linux_syscalls 319
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -628,16 +632,20 @@
#define __NR_epoll_pwait (__NR_Linux + 272)
#define __NR_ioprio_set (__NR_Linux + 273)
#define __NR_ioprio_get (__NR_Linux + 274)
+#define __NR_utimensat (__NR_Linux + 275)
+#define __NR_signalfd (__NR_Linux + 276)
+#define __NR_timerfd (__NR_Linux + 277)
+#define __NR_eventfd (__NR_Linux + 278)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 274
+#define __NR_Linux_syscalls 278
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 274
+#define __NR_64_Linux_syscalls 278
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -924,16 +932,20 @@
#define __NR_epoll_pwait (__NR_Linux + 276)
#define __NR_ioprio_set (__NR_Linux + 277)
#define __NR_ioprio_get (__NR_Linux + 278)
+#define __NR_utimensat (__NR_Linux + 279)
+#define __NR_signalfd (__NR_Linux + 280)
+#define __NR_timerfd (__NR_Linux + 281)
+#define __NR_eventfd (__NR_Linux + 282)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 278
+#define __NR_Linux_syscalls 282
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 278
+#define __NR_N32_Linux_syscalls 282
#ifdef __KERNEL__
@@ -949,7 +961,6 @@
#define __ARCH_WANT_SYS_UTIME
#define __ARCH_WANT_SYS_WAITPID
#define __ARCH_WANT_SYS_SOCKETCALL
-#define __ARCH_WANT_SYS_FADVISE64
#define __ARCH_WANT_SYS_GETPGRP
#define __ARCH_WANT_SYS_LLSEEK
#define __ARCH_WANT_SYS_NICE
@@ -966,6 +977,22 @@
# define __ARCH_WANT_COMPAT_SYS_TIME
# endif
+/* whitelists for checksyscalls */
+#define __IGNORE_select
+#define __IGNORE_vfork
+#define __IGNORE_time
+#define __IGNORE_uselib
+#define __IGNORE_fadvise64_64
+#define __IGNORE_getdents64
+#if _MIPS_SIM == _MIPS_SIM_NABI32
+#define __IGNORE_truncate64
+#define __IGNORE_ftruncate64
+#define __IGNORE_stat64
+#define __IGNORE_lstat64
+#define __IGNORE_fstat64
+#define __IGNORE_fstatat64
+#endif
+
#endif /* !__ASSEMBLY__ */
/*
diff --git a/include/asm-mips/vr41xx/giu.h b/include/asm-mips/vr41xx/giu.h
index 8109cda557d..0bcdd3a5c25 100644
--- a/include/asm-mips/vr41xx/giu.h
+++ b/include/asm-mips/vr41xx/giu.h
@@ -20,6 +20,15 @@
#ifndef __NEC_VR41XX_GIU_H
#define __NEC_VR41XX_GIU_H
+/*
+ * NEC VR4100 series GIU platform device IDs.
+ */
+enum {
+ GPIO_50PINS_PULLUPDOWN,
+ GPIO_36PINS,
+ GPIO_48PINS_EDGE_SELECT,
+};
+
typedef enum {
IRQ_TRIGGER_LEVEL,
IRQ_TRIGGER_EDGE,
diff --git a/include/asm-mips/vr41xx/siu.h b/include/asm-mips/vr41xx/siu.h
index 1fcf6e8082b..98cdb409648 100644
--- a/include/asm-mips/vr41xx/siu.h
+++ b/include/asm-mips/vr41xx/siu.h
@@ -20,6 +20,8 @@
#ifndef __NEC_VR41XX_SIU_H
#define __NEC_VR41XX_SIU_H
+#define SIU_PORTS_MAX 2
+
typedef enum {
SIU_INTERFACE_RS232C,
SIU_INTERFACE_IRDA,
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index 13a3502eef4..9de52a5b0f3 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -169,26 +169,28 @@
/*
* On the RM9000 there is a problem which makes the CreateDirtyExclusive
- * cache operation unusable on SMP systems.
+ * eache operation unusable on SMP systems.
*/
-#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE) || \
- defined(CONFIG_BASLER_EXCITE)
+#if defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE)
#define RM9000_CDEX_SMP_WAR 1
#endif
/*
- * The RM9000 has a bug (though PMC-Sierra opposes it being called that)
- * where invalid instructions in the same I-cache line worth of instructions
- * being fetched may case spurious exceptions.
+ * The RM7000 processors and the E9000 cores have a bug (though PMC-Sierra
+ * opposes it being called that) where invalid instructions in the same
+ * I-cache line worth of instructions being fetched may case spurious
+ * exceptions.
*/
-#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
- defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE)
+#if defined(CONFIG_BASLER_EXCITE) || defined(CONFIG_MIPS_ATLAS) || \
+ defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MOMENCO_OCELOT) || \
+ defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_SGI_IP32) || \
+ defined(CONFIG_WR_PPMC)
#define ICACHE_REFILLS_WORKAROUND_WAR 1
#endif
/*
- * ON the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
+ * On the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
* may cause ll / sc and lld / scd sequences to execute non-atomically.
*/
#ifdef CONFIG_SGI_IP27
@@ -196,6 +198,14 @@
#endif
/*
+ * 34K core erratum: "Problems Executing the TLBR Instruction"
+ */
+#if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \
+ defined(CONFIG_PMC_MSP7120_FPGA)
+#define MIPS34K_MISSED_ITLB_WAR 1
+#endif
+
+/*
* Workarounds default to off
*/
#ifndef ICACHE_REFILLS_WORKAROUND_WAR
@@ -234,5 +244,8 @@
#ifndef R10000_LLSC_WAR
#define R10000_LLSC_WAR 0
#endif
+#ifndef MIPS34K_MISSED_ITLB_WAR
+#define MIPS34K_MISSED_ITLB_WAR 0
+#endif
#endif /* _ASM_WAR_H */
diff --git a/include/asm-mips/watch.h b/include/asm-mips/watch.h
deleted file mode 100644
index 6aa90cae111..00000000000
--- a/include/asm-mips/watch.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997, 1998, 2000, 2001 by Ralf Baechle
- */
-#ifndef _ASM_WATCH_H
-#define _ASM_WATCH_H
-
-#include <linux/linkage.h>
-
-/*
- * Types of reference for watch_set()
- */
-enum wref_type {
- wr_save = 1,
- wr_load = 2
-};
-
-extern asmlinkage void __watch_set(unsigned long addr, enum wref_type ref);
-extern asmlinkage void __watch_clear(void);
-extern asmlinkage void __watch_reenable(void);
-
-#define watch_set(addr, ref) \
- if (cpu_has_watch) \
- __watch_set(addr, ref)
-#define watch_clear() \
- if (cpu_has_watch) \
- __watch_clear()
-#define watch_reenable() \
- if (cpu_has_watch) \
- __watch_reenable()
-
-#endif /* _ASM_WATCH_H */
diff --git a/include/asm-parisc/hardware.h b/include/asm-parisc/hardware.h
index 76d880dc4ba..4e9626836ba 100644
--- a/include/asm-parisc/hardware.h
+++ b/include/asm-parisc/hardware.h
@@ -31,10 +31,11 @@ enum cpu_type {
pcxw = 8, /* pa8500 pa 2.0 */
pcxw_ = 9, /* pa8600 (w+) pa 2.0 */
pcxw2 = 10, /* pa8700 pa 2.0 */
- mako = 11 /* pa8800 pa 2.0 */
+ mako = 11, /* pa8800 pa 2.0 */
+ mako2 = 12 /* pa8900 pa 2.0 */
};
-extern char *cpu_name_version[][2]; /* mapping from enum cpu_type to strings */
+extern const char * const cpu_name_version[][2]; /* mapping from enum cpu_type to strings */
struct parisc_driver;
diff --git a/include/asm-parisc/linkage.h b/include/asm-parisc/linkage.h
index 7a09d911b53..ad8cd0d069e 100644
--- a/include/asm-parisc/linkage.h
+++ b/include/asm-parisc/linkage.h
@@ -8,8 +8,10 @@
/*
* In parisc assembly a semicolon marks a comment while a
- * exclamation mark is used to seperate independend lines.
+ * exclamation mark is used to seperate independent lines.
*/
+#ifdef __ASSEMBLY__
+
#define ENTRY(name) \
.export name !\
ALIGN !\
@@ -24,5 +26,6 @@ name:
END(name)
#endif
+#endif /* __ASSEMBLY__ */
#endif /* __ASM_PARISC_LINKAGE_H */
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index 7b3be9ac0dd..61fbd57a832 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -238,9 +238,6 @@ extern inline void pcibios_register_hba(struct pci_hba_data *x)
#define PCIBIOS_MIN_IO 0x10
#define PCIBIOS_MIN_MEM 0x1000 /* NBPG - but pci/setup-res.c dies */
-/* Don't support DAC yet. */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
/* export the pci_ DMA API in terms of the dma_ one */
#include <asm-generic/pci-dma-compat.h>
@@ -284,10 +281,6 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
return root;
}
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
static inline void pcibios_penalize_isa_irq(int irq, int active)
{
/* We don't need to penalize isa irq's */
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
index d2f396721d3..6b294fb07a2 100644
--- a/include/asm-parisc/processor.h
+++ b/include/asm-parisc/processor.h
@@ -69,8 +69,8 @@ struct system_cpuinfo_parisc {
char sys_model_name[81]; /* PDC-ROM returnes this model name */
} pdc;
- char *cpu_name; /* e.g. "PA7300LC (PCX-L2)" */
- char *family_name; /* e.g. "1.1e" */
+ const char *cpu_name; /* e.g. "PA7300LC (PCX-L2)" */
+ const char *family_name; /* e.g. "1.1e" */
};
@@ -334,8 +334,8 @@ extern unsigned long get_wchan(struct task_struct *p);
static inline int parisc_requires_coherency(void)
{
#ifdef CONFIG_PA8X00
- /* FIXME: also pa8900 - when we see one */
- return boot_cpu_data.cpu_type == mako;
+ return (boot_cpu_data.cpu_type == mako) ||
+ (boot_cpu_data.cpu_type == mako2);
#else
return 0;
#endif
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h
index 7e9afa720d4..21fbfc5afd0 100644
--- a/include/asm-parisc/system.h
+++ b/include/asm-parisc/system.h
@@ -188,7 +188,6 @@ static inline void set_eiem(unsigned long val)
# define __lock_aligned __attribute__((__section__(".data.lock_aligned")))
#endif
-#define KERNEL_START (0x10100000 - 0x1000)
#define arch_align_stack(x) (x)
#endif
diff --git a/include/asm-parisc/termbits.h b/include/asm-parisc/termbits.h
index a46e299a939..e847fe97968 100644
--- a/include/asm-parisc/termbits.h
+++ b/include/asm-parisc/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index 2f7c40861c9..f74099bdca3 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -792,8 +792,19 @@
#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_Linux_syscalls (__NR_eventfd + 1)
+
+
+#define __IGNORE_select /* newselect */
+#define __IGNORE_fadvise64 /* fadvise64_64 */
+#define __IGNORE_utimes /* utime */
-#define __NR_Linux_syscalls (__NR_fstatfs64 + 1)
#define HPUX_GATEWAY_ADDR 0xC0000004
#define LINUX_GATEWAY_ADDR 0x100
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index a19a6f1a1cf..f6bd804d909 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -61,7 +61,6 @@ struct dma_mapping_ops {
void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction);
int (*dma_supported)(struct device *dev, u64 mask);
- int (*dac_dma_supported)(struct device *dev, u64 mask);
int (*set_dma_mask)(struct device *dev, u64 dma_mask);
};
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 4734cc178db..05dd5a3eb3a 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -138,10 +138,7 @@ struct irq_map_entry {
extern struct irq_map_entry irq_map[NR_IRQS];
-static inline irq_hw_number_t virq_to_hw(unsigned int virq)
-{
- return irq_map[virq].hwirq;
-}
+extern irq_hw_number_t virq_to_hw(unsigned int virq);
/**
* irq_alloc_host - Allocate a new irq_host data structure
diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h
index ce0f13e8eb1..e16e7bc9ab5 100644
--- a/include/asm-powerpc/pci.h
+++ b/include/asm-powerpc/pci.h
@@ -74,18 +74,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops);
extern struct dma_mapping_ops *get_pci_dma_ops(void);
-/* For DAC DMA, we currently don't support it by default, but
- * we let 64-bit platforms override this.
- */
-static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask)
-{
- struct dma_mapping_ops *d = get_pci_dma_ops();
-
- if (d && d->dac_dma_supported)
- return d->dac_dma_supported(&hwdev->dev, mask);
- return 0;
-}
-
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
unsigned long *strategy_parameter)
@@ -124,12 +112,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
-/*
- * At present there are very few 32-bit PPC machines that can have
- * memory above the 4GB point, and we don't support that.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
/* Return the index of the PCI controller for device PDEV. */
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
@@ -243,8 +225,6 @@ extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
extern int pci_read_irq_line(struct pci_dev *dev);
-extern void pcibios_add_platform_entries(struct pci_dev *dev);
-
struct file;
extern pgprot_t pci_phys_mem_access_prot(struct file *file,
unsigned long pfn,
diff --git a/include/asm-powerpc/pgalloc-64.h b/include/asm-powerpc/pgalloc-64.h
index d9a3a8ca58a..94d0294341d 100644
--- a/include/asm-powerpc/pgalloc-64.h
+++ b/include/asm-powerpc/pgalloc-64.h
@@ -90,7 +90,8 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
static inline struct page *pte_alloc_one(struct mm_struct *mm,
unsigned long address)
{
- return virt_to_page(pte_alloc_one_kernel(mm, address));
+ pte_t *pte = pte_alloc_one_kernel(mm, address);
+ return pte ? virt_to_page(pte) : NULL;
}
static inline void pte_free_kernel(pte_t *pte)
diff --git a/include/asm-powerpc/pgtable-ppc32.h b/include/asm-powerpc/pgtable-ppc32.h
index c863bdb2889..7fb730c62f8 100644
--- a/include/asm-powerpc/pgtable-ppc32.h
+++ b/include/asm-powerpc/pgtable-ppc32.h
@@ -673,10 +673,14 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
}
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- do { \
- __ptep_set_access_flags(__ptep, __entry, __dirty); \
- flush_tlb_page_nohash(__vma, __address); \
- } while(0)
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) { \
+ __ptep_set_access_flags(__ptep, __entry, __dirty); \
+ flush_tlb_page_nohash(__vma, __address); \
+ } \
+ __changed; \
+})
/*
* Macro to mark a page protection value as "uncacheable".
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h
index 704c4e669fe..3cfd98f44bf 100644
--- a/include/asm-powerpc/pgtable-ppc64.h
+++ b/include/asm-powerpc/pgtable-ppc64.h
@@ -413,10 +413,14 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
:"cc");
}
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- do { \
- __ptep_set_access_flags(__ptep, __entry, __dirty); \
- flush_tlb_page_nohash(__vma, __address); \
- } while(0)
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) { \
+ __ptep_set_access_flags(__ptep, __entry, __dirty); \
+ flush_tlb_page_nohash(__vma, __address); \
+ } \
+ __changed; \
+})
/*
* Macro to mark a page protection value as "uncacheable".
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
index 700ca592874..1cc3f9cb6f4 100644
--- a/include/asm-powerpc/systbl.h
+++ b/include/asm-powerpc/systbl.h
@@ -311,3 +311,4 @@ COMPAT_SYS_SPU(utimensat)
COMPAT_SYS_SPU(signalfd)
COMPAT_SYS_SPU(timerfd)
SYSCALL_SPU(eventfd)
+COMPAT_SYS_SPU(sync_file_range2)
diff --git a/include/asm-powerpc/tlb.h b/include/asm-powerpc/tlb.h
index 0a17682663d..66714042e43 100644
--- a/include/asm-powerpc/tlb.h
+++ b/include/asm-powerpc/tlb.h
@@ -38,6 +38,15 @@ extern void pte_free_finish(void);
static inline void tlb_flush(struct mmu_gather *tlb)
{
+ struct ppc64_tlb_batch *tlbbatch = &__get_cpu_var(ppc64_tlb_batch);
+
+ /* If there's a TLB batch pending, then we must flush it because the
+ * pages are going to be freed and we really don't want to have a CPU
+ * access a freed page because it has a stale TLB
+ */
+ if (tlbbatch->index)
+ __flush_tlb_pending(tlbbatch);
+
pte_free_finish();
}
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index e3c28dc31ab..f71c6061f1e 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -330,10 +330,11 @@
#define __NR_signalfd 305
#define __NR_timerfd 306
#define __NR_eventfd 307
+#define __NR_sync_file_range2 308
#ifdef __KERNEL__
-#define __NR_syscalls 308
+#define __NR_syscalls 309
#define __NR__exit __NR_exit
#define NR_syscalls __NR_syscalls
diff --git a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
index 9d162028dab..d2442cd72a5 100644
--- a/include/asm-ppc/pci.h
+++ b/include/asm-ppc/pci.h
@@ -102,12 +102,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
-/*
- * At present there are very few 32-bit PPC machines that can have
- * memory above the 4GB point, and we don't support that.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
/* Return the index of the PCI controller for device PDEV. */
#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
@@ -145,8 +139,6 @@ pcibios_select_root(struct pci_dev *pdev, struct resource *res)
return root;
}
-extern void pcibios_add_platform_entries(struct pci_dev *dev);
-
struct file;
extern pgprot_t pci_phys_mem_access_prot(struct file *file,
unsigned long pfn,
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index bed452d4a5f..9d0ce9ff584 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -694,10 +694,14 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
}
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- do { \
- __ptep_set_access_flags(__ptep, __entry, __dirty); \
- flush_tlb_page_nohash(__vma, __address); \
- } while(0)
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) { \
+ __ptep_set_access_flags(__ptep, __entry, __dirty); \
+ flush_tlb_page_nohash(__vma, __address); \
+ } \
+ __changed; \
+})
/*
* Macro to mark a page protection value as "uncacheable".
diff --git a/include/asm-s390/atomic.h b/include/asm-s390/atomic.h
index c17bdbf2206..ea486952f77 100644
--- a/include/asm-s390/atomic.h
+++ b/include/asm-s390/atomic.h
@@ -24,7 +24,7 @@
*/
typedef struct {
- volatile int counter;
+ int counter;
} __attribute__ ((aligned (4))) atomic_t;
#define ATOMIC_INIT(i) { (i) }
@@ -141,7 +141,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
#ifdef __s390x__
typedef struct {
- volatile long long counter;
+ long long counter;
} __attribute__ ((aligned (8))) atomic64_t;
#define ATOMIC64_INIT(i) { (i) }
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h
index 241756f80df..021e7c3223e 100644
--- a/include/asm-s390/cmb.h
+++ b/include/asm-s390/cmb.h
@@ -88,7 +88,6 @@ extern u64 cmf_read(struct ccw_device *cdev, int index);
* any
**/
extern int cmf_readall(struct ccw_device *cdev, struct cmbdata*data);
-extern void cmf_reset(struct ccw_device *cdev);
#endif /* __KERNEL__ */
#endif /* S390_CMB_H */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 8fe8d42e64c..0a307bb2f35 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -744,7 +744,12 @@ ptep_establish(struct vm_area_struct *vma,
}
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- ptep_establish(__vma, __address, __ptep, __entry)
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) \
+ ptep_establish(__vma, __address, __ptep, __entry); \
+ __changed; \
+})
/*
* Test and clear dirty bit in storage key.
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index e0fcea8c64c..3b972d4c6b2 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -216,6 +216,11 @@ static inline void cpu_relax(void)
barrier();
}
+static inline void psw_set_key(unsigned int key)
+{
+ asm volatile("spka 0(%0)" : : "d" (key));
+}
+
/*
* Set PSW to specified value.
*/
@@ -352,8 +357,8 @@ extern void (*s390_base_ext_handler_fn)(void);
/*
* CPU idle notifier chain.
*/
-#define CPU_IDLE 0
-#define CPU_NOT_IDLE 1
+#define S390_CPU_IDLE 0
+#define S390_CPU_NOT_IDLE 1
struct notifier_block;
int register_idle_notifier(struct notifier_block *nb);
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index fa6ca87080e..332ee73688f 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -470,14 +470,7 @@ struct user_regs_struct
#define regs_return_value(regs)((regs)->gprs[2])
#define profile_pc(regs) instruction_pointer(regs)
extern void show_regs(struct pt_regs * regs);
-#endif
-
-static inline void
-psw_set_key(unsigned int key)
-{
- asm volatile("spka 0(%0)" : : "d" (key));
-}
-
+#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
#endif /* _S390_PTRACE_H */
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h
index 21ed6477321..cb9faf1ea5c 100644
--- a/include/asm-s390/sclp.h
+++ b/include/asm-s390/sclp.h
@@ -11,29 +11,6 @@
#include <linux/types.h>
#include <asm/chpid.h>
-struct sccb_header {
- u16 length;
- u8 function_code;
- u8 control_mask[3];
- u16 response_code;
-} __attribute__((packed));
-
-#define LOADPARM_LEN 8
-
-struct sclp_readinfo_sccb {
- struct sccb_header header; /* 0-7 */
- u16 rnmax; /* 8-9 */
- u8 rnsize; /* 10 */
- u8 _reserved0[24 - 11]; /* 11-23 */
- u8 loadparm[LOADPARM_LEN]; /* 24-31 */
- u8 _reserved1[91 - 32]; /* 32-90 */
- u8 flags; /* 91 */
- u8 _reserved2[100 - 92]; /* 92-99 */
- u32 rnsize2; /* 100-103 */
- u64 rnmax2; /* 104-111 */
- u8 _reserved3[4096 - 112]; /* 112-4095 */
-} __attribute__((packed, aligned(4096)));
-
#define SCLP_CHP_INFO_MASK_SIZE 32
struct sclp_chp_info {
@@ -42,12 +19,22 @@ struct sclp_chp_info {
u8 configured[SCLP_CHP_INFO_MASK_SIZE];
};
-extern struct sclp_readinfo_sccb s390_readinfo_sccb;
-extern void sclp_readinfo_early(void);
-extern int sclp_sdias_blk_count(void);
-extern int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
-extern int sclp_chp_configure(struct chp_id chpid);
-extern int sclp_chp_deconfigure(struct chp_id chpid);
-extern int sclp_chp_read_info(struct sclp_chp_info *info);
+#define LOADPARM_LEN 8
+
+struct sclp_ipl_info {
+ int is_valid;
+ int has_dump;
+ char loadparm[LOADPARM_LEN];
+};
+
+void sclp_readinfo_early(void);
+void sclp_facilities_detect(void);
+unsigned long long sclp_memory_detect(void);
+int sclp_sdias_blk_count(void);
+int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);
+int sclp_chp_configure(struct chp_id chpid);
+int sclp_chp_deconfigure(struct chp_id chpid);
+int sclp_chp_read_info(struct sclp_chp_info *info);
+void sclp_get_ipl_info(struct sclp_ipl_info *info);
#endif /* _ASM_S390_SCLP_H */
diff --git a/include/asm-s390/sfp-machine.h b/include/asm-s390/sfp-machine.h
index 8ca8c77b2d0..4e16aede4b0 100644
--- a/include/asm-s390/sfp-machine.h
+++ b/include/asm-s390/sfp-machine.h
@@ -27,9 +27,9 @@
#define _FP_W_TYPE_SIZE 32
-#define _FP_W_TYPE unsigned long
-#define _FP_WS_TYPE signed long
-#define _FP_I_TYPE long
+#define _FP_W_TYPE unsigned int
+#define _FP_WS_TYPE signed int
+#define _FP_I_TYPE int
#define _FP_MUL_MEAT_S(R,X,Y) \
_FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
diff --git a/include/asm-s390/sfp-util.h b/include/asm-s390/sfp-util.h
index 8cabcd23d97..0addc6466d9 100644
--- a/include/asm-s390/sfp-util.h
+++ b/include/asm-s390/sfp-util.h
@@ -51,6 +51,16 @@
wl = __wl; \
})
+#ifdef __s390x__
+#define udiv_qrnnd(q, r, n1, n0, d) \
+ do { unsigned long __n; \
+ unsigned int __r, __d; \
+ __n = ((unsigned long)(n1) << 32) + n0; \
+ __d = (d); \
+ (q) = __n / __d; \
+ (r) = __n % __d; \
+ } while (0)
+#else
#define udiv_qrnnd(q, r, n1, n0, d) \
do { unsigned int __r; \
(q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
@@ -58,6 +68,7 @@
} while (0)
extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
unsigned int , unsigned int);
+#endif
#define UDIV_NEEDS_NORMALIZATION 0
diff --git a/include/asm-s390/termbits.h b/include/asm-s390/termbits.h
index 585c78a6e40..811b9a9cdc0 100644
--- a/include/asm-s390/termbits.h
+++ b/include/asm-s390/termbits.h
@@ -25,6 +25,17 @@ struct termios {
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 */
diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h
index 86564e7a26a..39f41fcd509 100644
--- a/include/asm-sh/cpu-sh4/freq.h
+++ b/include/asm-sh/cpu-sh4/freq.h
@@ -24,6 +24,9 @@
#define FRQMR1 0xffc80014
#else
#define FRQCR 0xffc00000
+#define FRQCR_PSTBY 0x0200
+#define FRQCR_PLLEN 0x0400
+#define FRQCR_CKOEN 0x0800
#endif
#define MIN_DIVISOR_NR 0
#define MAX_DIVISOR_NR 3
diff --git a/include/asm-sh/dma.h b/include/asm-sh/dma.h
index faf3051cd42..6034d4a29e7 100644
--- a/include/asm-sh/dma.h
+++ b/include/asm-sh/dma.h
@@ -13,6 +13,7 @@
#include <linux/spinlock.h>
#include <linux/wait.h>
+#include <linux/sched.h>
#include <linux/sysdev.h>
#include <asm/cpu/dma.h>
diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h
index a0e55b09e4f..aa80930ce8e 100644
--- a/include/asm-sh/io.h
+++ b/include/asm-sh/io.h
@@ -116,13 +116,13 @@ void __raw_readsl(unsigned long addr, void *data, int longlen);
* redefined by userlevel programs.
*/
#ifdef __readb
-# define readb(a) ({ unsigned long r_ = __raw_readb(a); mb(); r_; })
+# define readb(a) ({ unsigned int r_ = __raw_readb(a); mb(); r_; })
#endif
#ifdef __raw_readw
-# define readw(a) ({ unsigned long r_ = __raw_readw(a); mb(); r_; })
+# define readw(a) ({ unsigned int r_ = __raw_readw(a); mb(); r_; })
#endif
#ifdef __raw_readl
-# define readl(a) ({ unsigned long r_ = __raw_readl(a); mb(); r_; })
+# define readl(a) ({ unsigned int r_ = __raw_readl(a); mb(); r_; })
#endif
#ifdef __raw_writeb
diff --git a/include/asm-sh/pci.h b/include/asm-sh/pci.h
index b1f9a9e0231..2757ce096ff 100644
--- a/include/asm-sh/pci.h
+++ b/include/asm-sh/pci.h
@@ -110,11 +110,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
#endif
-/* Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function. Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
@@ -134,10 +129,6 @@ int pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
int pciauto_assign_resources(int busno, struct pci_channel *hose);
#endif
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* __KERNEL__ */
/* generic pci stuff */
diff --git a/include/asm-sh/se73180.h b/include/asm-sh/se73180.h
index 3a4acb3e38a..907c062b4c9 100644
--- a/include/asm-sh/se73180.h
+++ b/include/asm-sh/se73180.h
@@ -1,9 +1,7 @@
-#ifndef __ASM_SH_HITACHI_SE73180_H
-#define __ASM_SH_HITACHI_SE73180_H
+#ifndef __ASM_SH_SE73180_H
+#define __ASM_SH_SE73180_H
/*
- * include/asm-sh/se/se73180.h
- *
* Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
*
* SH-Mobile SolutionEngine 73180 support
@@ -62,4 +60,7 @@
#define __IO_PREFIX sh73180se
#include <asm/io_generic.h>
-#endif /* __ASM_SH_HITACHI_SE73180_H */
+/* arch/sh/boards/se/73180/irq.c */
+int shmse_irq_demux(int irq);
+
+#endif /* __ASM_SH_SE73180_H */
diff --git a/include/asm-sh/smp.h b/include/asm-sh/smp.h
index 71ecddf70db..caa7b93f1bc 100644
--- a/include/asm-sh/smp.h
+++ b/include/asm-sh/smp.h
@@ -15,7 +15,7 @@
#ifdef CONFIG_SMP
-#include <asm/spinlock.h>
+#include <linux/spinlock.h>
#include <asm/atomic.h>
#include <asm/current.h>
diff --git a/include/asm-sh/spinlock.h b/include/asm-sh/spinlock.h
index 2586eef07d5..92f6e2008b2 100644
--- a/include/asm-sh/spinlock.h
+++ b/include/asm-sh/spinlock.h
@@ -11,6 +11,7 @@
#define __ASM_SH_SPINLOCK_H
#include <asm/atomic.h>
+#include <asm/spinlock_types.h>
/*
* Your basic SMP spinlocks, allowing only a single CPU anywhere
@@ -42,7 +43,7 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock)
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
- assert_spin_locked(lock);
+ //assert_spin_locked(lock);
lock->lock = 0;
}
@@ -88,6 +89,11 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
__raw_spin_unlock(&rw->lock);
}
+static inline int __raw_write_can_lock(raw_rwlock_t *rw)
+{
+ return (atomic_read(&rw->counter) == RW_LOCK_BIAS);
+}
+
static inline int __raw_read_trylock(raw_rwlock_t *lock)
{
atomic_t *count = (atomic_t*)lock;
diff --git a/include/asm-sh/spinlock_types.h b/include/asm-sh/spinlock_types.h
index 8c41b6c3aac..5c58134f2c4 100644
--- a/include/asm-sh/spinlock_types.h
+++ b/include/asm-sh/spinlock_types.h
@@ -9,7 +9,9 @@ typedef struct {
volatile unsigned long lock;
} raw_spinlock_t;
-#define __SPIN_LOCK_UNLOCKED { 0 }
+#define __RAW_SPIN_LOCK_UNLOCKED { 1 }
+
+#include <asm/atomic.h>
typedef struct {
raw_spinlock_t lock;
diff --git a/include/asm-sh/termbits.h b/include/asm-sh/termbits.h
index f1b7b46f4e9..7ee1b42eeab 100644
--- a/include/asm-sh/termbits.h
+++ b/include/asm-sh/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-sh64/pci.h b/include/asm-sh64/pci.h
index aa8043089bb..57a67cf7a5c 100644
--- a/include/asm-sh64/pci.h
+++ b/include/asm-sh64/pci.h
@@ -72,11 +72,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
#endif
-/* Not supporting more than 32-bit PCI bus addresses now, but
- * must satisfy references to this function. Change if needed.
- */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
/* These macros should be used after a pci_map_sg call has been done
* to get bus addresses of each of the SG entries and their lengths.
* You should only work with the number of sg entries pci_map_sg
@@ -104,10 +99,6 @@ extern void pcibios_fixup_irqs(void);
extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
#endif
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* __KERNEL__ */
/* generic pci stuff */
diff --git a/include/asm-sparc/pci.h b/include/asm-sparc/pci.h
index a750c688408..b93b6c79e08 100644
--- a/include/asm-sparc/pci.h
+++ b/include/asm-sparc/pci.h
@@ -142,8 +142,6 @@ static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
return 1;
}
-#define pci_dac_dma_supported(dev, mask) (0)
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
@@ -154,10 +152,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#define PCI_DMA_ERROR_CODE (~(dma_addr_t)0x0)
static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index 4f0a5ba0d6a..59229aeba27 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -446,6 +446,17 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma,
#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
#define GET_PFN(pfn) (pfn & 0x0fffffffUL)
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) { \
+ set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+ flush_tlb_page(__vma, __address); \
+ } \
+ (sparc_cpu_model == sun4c) || __changed; \
+})
+
#include <asm-generic/pgtable.h>
#endif /* !(__ASSEMBLY__) */
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
index 03c385de761..445026fbec3 100644
--- a/include/asm-sparc64/cpudata.h
+++ b/include/asm-sparc64/cpudata.h
@@ -31,7 +31,7 @@ typedef struct {
unsigned int ecache_size;
unsigned int ecache_line_size;
int core_id;
- unsigned int __pad3;
+ int proc_id;
} cpuinfo_sparc;
DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h
index 9329429fb7f..c58ec1661df 100644
--- a/include/asm-sparc64/dma-mapping.h
+++ b/include/asm-sparc64/dma-mapping.h
@@ -15,8 +15,7 @@
static inline int
dma_supported(struct device *dev, u64 mask)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
return pci_dma_supported(to_pci_dev(dev), mask);
}
@@ -24,8 +23,7 @@ dma_supported(struct device *dev, u64 mask)
static inline int
dma_set_mask(struct device *dev, u64 dma_mask)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
}
@@ -34,8 +32,7 @@ static inline void *
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
return pci_iommu_ops->alloc_consistent(to_pci_dev(dev), size, dma_handle, flag);
}
@@ -44,8 +41,7 @@ static inline void
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_handle)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
}
@@ -54,8 +50,7 @@ static inline dma_addr_t
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
}
@@ -64,8 +59,7 @@ static inline void
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
}
@@ -75,8 +69,7 @@ dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
}
@@ -85,8 +78,7 @@ static inline void
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
}
@@ -95,8 +87,7 @@ static inline int
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
}
@@ -105,8 +96,7 @@ static inline void
dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
}
@@ -115,8 +105,7 @@ static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
size, (int)direction);
@@ -126,8 +115,7 @@ static inline void
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
size, (int)direction);
@@ -137,8 +125,7 @@ static inline void
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
}
@@ -147,8 +134,7 @@ static inline void
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
enum dma_data_direction direction)
{
- BUG_ON(dev->bus != &pci_bus_type &&
- dev->bus != &ebus_bus_type);
+ BUG_ON(dev->bus != &pci_bus_type);
pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
}
@@ -162,6 +148,22 @@ dma_mapping_error(dma_addr_t dma_addr)
#else
struct device;
+struct page;
+struct scatterlist;
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+ BUG();
+ return 0;
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+ BUG();
+ return 0;
+}
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
@@ -176,6 +178,52 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
BUG();
}
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return 0;
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return 0;
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return 0;
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
static inline void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
@@ -190,6 +238,27 @@ dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t siz
BUG();
}
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline int
+dma_mapping_error(dma_addr_t dma_addr)
+{
+ BUG();
+ return 0;
+}
+
#endif /* PCI */
diff --git a/include/asm-sparc64/hypervisor.h b/include/asm-sparc64/hypervisor.h
index 5cdb1ff0483..db2130a95d6 100644
--- a/include/asm-sparc64/hypervisor.h
+++ b/include/asm-sparc64/hypervisor.h
@@ -1097,6 +1097,80 @@ extern unsigned long sun4v_mach_set_soft_state(unsigned long soft_state,
*/
#define HV_FAST_MACH_GET_SOFT_STATE 0x71
+/* svc_send()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_SEND
+ * ARG0: service ID
+ * ARG1: buffer real address
+ * ARG2: buffer size
+ * RET0: STATUS
+ * RET1: sent_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_SEND 0x80
+
+/* svc_recv()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_RECV
+ * ARG0: service ID
+ * ARG1: buffer real address
+ * ARG2: buffer size
+ * RET0: STATUS
+ * RET1: recv_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_RECV 0x81
+
+/* svc_getstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_GETSTATUS
+ * ARG0: service ID
+ * RET0: STATUS
+ * RET1: status bits
+ */
+#define HV_FAST_SVC_GETSTATUS 0x82
+
+/* svc_setstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_SETSTATUS
+ * ARG0: service ID
+ * ARG1: bits to set
+ * RET0: STATUS
+ */
+#define HV_FAST_SVC_SETSTATUS 0x83
+
+/* svc_clrstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_CLRSTATUS
+ * ARG0: service ID
+ * ARG1: bits to clear
+ * RET0: STATUS
+ */
+#define HV_FAST_SVC_CLRSTATUS 0x84
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_svc_send(unsigned long svc_id,
+ unsigned long buffer,
+ unsigned long buffer_size,
+ unsigned long *sent_bytes);
+extern unsigned long sun4v_svc_recv(unsigned long svc_id,
+ unsigned long buffer,
+ unsigned long buffer_size,
+ unsigned long *recv_bytes);
+extern unsigned long sun4v_svc_getstatus(unsigned long svc_id,
+ unsigned long *status_bits);
+extern unsigned long sun4v_svc_setstatus(unsigned long svc_id,
+ unsigned long status_bits);
+extern unsigned long sun4v_svc_clrstatus(unsigned long svc_id,
+ unsigned long status_bits);
+#endif
+
/* Trap trace services.
*
* The hypervisor provides a trap tracing capability for privileged
@@ -2541,8 +2615,9 @@ struct ldc_mtable_entry {
/* ldc_revoke()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_LDC_REVOKE
- * ARG0: cookie
- * ARG1: ldc_mtable_entry cookie
+ * ARG0: channel ID
+ * ARG1: cookie
+ * ARG2: ldc_mtable_entry cookie
* RET0: status
*/
#define HV_FAST_LDC_REVOKE 0xef
@@ -2589,7 +2664,8 @@ extern unsigned long sun4v_ldc_mapin(unsigned long channel,
unsigned long *ra,
unsigned long *perm);
extern unsigned long sun4v_ldc_unmap(unsigned long ra);
-extern unsigned long sun4v_ldc_revoke(unsigned long cookie,
+extern unsigned long sun4v_ldc_revoke(unsigned long channel,
+ unsigned long cookie,
unsigned long mte_cookie);
#endif
@@ -2724,6 +2800,105 @@ struct hv_mmu_statistics {
*/
#define HV_FAST_MMUSTAT_INFO 0x103
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_mmustat_conf(unsigned long ra, unsigned long *orig_ra);
+extern unsigned long sun4v_mmustat_info(unsigned long *ra);
+#endif
+
+/* NCS crypto services */
+
+/* ncs_request() sub-function numbers */
+#define HV_NCS_QCONF 0x01
+#define HV_NCS_QTAIL_UPDATE 0x02
+
+#ifndef __ASSEMBLY__
+struct hv_ncs_queue_entry {
+ /* MAU Control Register */
+ unsigned long mau_control;
+#define MAU_CONTROL_INV_PARITY 0x0000000000002000
+#define MAU_CONTROL_STRAND 0x0000000000001800
+#define MAU_CONTROL_BUSY 0x0000000000000400
+#define MAU_CONTROL_INT 0x0000000000000200
+#define MAU_CONTROL_OP 0x00000000000001c0
+#define MAU_CONTROL_OP_SHIFT 6
+#define MAU_OP_LOAD_MA_MEMORY 0x0
+#define MAU_OP_STORE_MA_MEMORY 0x1
+#define MAU_OP_MODULAR_MULT 0x2
+#define MAU_OP_MODULAR_REDUCE 0x3
+#define MAU_OP_MODULAR_EXP_LOOP 0x4
+#define MAU_CONTROL_LEN 0x000000000000003f
+#define MAU_CONTROL_LEN_SHIFT 0
+
+ /* Real address of bytes to load or store bytes
+ * into/out-of the MAU.
+ */
+ unsigned long mau_mpa;
+
+ /* Modular Arithmetic MA Offset Register. */
+ unsigned long mau_ma;
+
+ /* Modular Arithmetic N Prime Register. */
+ unsigned long mau_np;
+};
+
+struct hv_ncs_qconf_arg {
+ unsigned long mid; /* MAU ID, 1 per core on Niagara */
+ unsigned long base; /* Real address base of queue */
+ unsigned long end; /* Real address end of queue */
+ unsigned long num_ents; /* Number of entries in queue */
+};
+
+struct hv_ncs_qtail_update_arg {
+ unsigned long mid; /* MAU ID, 1 per core on Niagara */
+ unsigned long tail; /* New tail index to use */
+ unsigned long syncflag; /* only SYNCFLAG_SYNC is implemented */
+#define HV_NCS_SYNCFLAG_SYNC 0x00
+#define HV_NCS_SYNCFLAG_ASYNC 0x01
+};
+#endif
+
+/* ncs_request()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_NCS_REQUEST
+ * ARG0: NCS sub-function
+ * ARG1: sub-function argument real address
+ * ARG2: size in bytes of sub-function argument
+ * RET0: status
+ *
+ * The MAU chip of the Niagara processor is not directly accessible
+ * to privileged code, instead it is programmed indirectly via this
+ * hypervisor API.
+ *
+ * The interfaces defines a queue of MAU operations to perform.
+ * Privileged code registers a queue with the hypervisor by invoking
+ * this HVAPI with the HV_NCS_QCONF sub-function, which defines the
+ * base, end, and number of entries of the queue. Each queue entry
+ * contains a MAU register struct block.
+ *
+ * The privileged code then proceeds to add entries to the queue and
+ * then invoke the HV_NCS_QTAIL_UPDATE sub-function. Since only
+ * synchronous operations are supported by the current hypervisor,
+ * HV_NCS_QTAIL_UPDATE will run all the pending queue entries to
+ * completion and return HV_EOK, or return an error code.
+ *
+ * The real address of the sub-function argument must be aligned on at
+ * least an 8-byte boundary.
+ *
+ * The tail argument of HV_NCS_QTAIL_UPDATE is an index, not a byte
+ * offset, into the queue and must be less than or equal the 'num_ents'
+ * argument given in the HV_NCS_QCONF call.
+ */
+#define HV_FAST_NCS_REQUEST 0x110
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_ncs_request(unsigned long request,
+ unsigned long arg_ra,
+ unsigned long arg_size);
+#endif
+
+#define HV_FAST_FIRE_GET_PERFREG 0x120
+#define HV_FAST_FIRE_SET_PERFREG 0x121
+
/* Function numbers for HV_CORE_TRAP. */
#define HV_CORE_SET_VER 0x00
#define HV_CORE_PUTCHAR 0x01
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index 5d233b42fe1..90781e34a95 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -46,6 +46,7 @@ extern void irq_install_pre_handler(int virt_irq,
#define irq_canonicalize(irq) (irq)
extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
+extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino);
extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
unsigned int msi_devino_start,
unsigned int msi_devino_end);
diff --git a/include/asm-sparc64/mdesc.h b/include/asm-sparc64/mdesc.h
index 124eb8ca237..c6383982b53 100644
--- a/include/asm-sparc64/mdesc.h
+++ b/include/asm-sparc64/mdesc.h
@@ -15,6 +15,7 @@ struct mdesc_node {
u64 node;
unsigned int unique_id;
unsigned int num_arcs;
+ unsigned int irqs[2];
struct property *properties;
struct mdesc_node *hash_next;
struct mdesc_node *allnodes_next;
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
index 6340a5253a3..23cc63f049a 100644
--- a/include/asm-sparc64/parport.h
+++ b/include/asm-sparc64/parport.h
@@ -145,7 +145,7 @@ static int parport_isa_probe(int count)
*/
if (parport_pc_probe_port(base, base + 0x400,
child->irq, PARPORT_DMA_NOFIFO,
- child->bus->self))
+ &child->bus->self->dev))
count++;
}
}
@@ -199,7 +199,8 @@ static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
if (parport_pc_probe_port(base, base + 0x400,
edev->irqs[0],
- count, ebus->self))
+ count,
+ &ebus->self->dev))
count++;
}
}
diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
index 47cea16e1ba..e11ac100f04 100644
--- a/include/asm-sparc64/pci.h
+++ b/include/asm-sparc64/pci.h
@@ -206,49 +206,6 @@ extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
#define PCI64_REQUIRED_MASK (~(dma64_addr_t)0)
#define PCI64_ADDR_BASE 0xfffc000000000000UL
-/* Usage of the pci_dac_foo interfaces is only valid if this
- * test passes.
- */
-#define pci_dac_dma_supported(pci_dev, mask) \
- ((((mask) & PCI64_REQUIRED_MASK) == PCI64_REQUIRED_MASK) ? 1 : 0)
-
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
- return (PCI64_ADDR_BASE +
- __pa(page_address(page)) + offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- unsigned long paddr = (dma_addr & PAGE_MASK) - PCI64_ADDR_BASE;
-
- return virt_to_page(__va(paddr));
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
- /* DAC cycle addressing does not make use of the
- * PCI controller's streaming cache, so nothing to do.
- */
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
- /* DAC cycle addressing does not make use of the
- * PCI controller's streaming cache, so nothing to do.
- */
-}
-
#define PCI_DMA_ERROR_CODE (~(dma_addr_t)0x0)
static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
@@ -303,10 +260,6 @@ pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
extern struct resource *pcibios_select_root(struct pci_dev *, struct resource *);
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
{
return PCI_IRQ_NONE;
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index f76e1492add..4fb8c4bfb84 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -33,6 +33,8 @@ extern cpumask_t phys_cpu_present_map;
#define cpu_possible_map phys_cpu_present_map
extern cpumask_t cpu_sibling_map[NR_CPUS];
+extern cpumask_t cpu_core_map[NR_CPUS];
+extern int sparc64_multi_core;
/*
* General functions that each host system must provide.
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
index 7af1e1109c4..349d1d3e9c2 100644
--- a/include/asm-sparc64/tlb.h
+++ b/include/asm-sparc64/tlb.h
@@ -2,6 +2,7 @@
#define _SPARC64_TLB_H
#include <linux/swap.h>
+#include <linux/pagemap.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
index e0d450d600e..290ac75f385 100644
--- a/include/asm-sparc64/topology.h
+++ b/include/asm-sparc64/topology.h
@@ -1,12 +1,17 @@
#ifndef _ASM_SPARC64_TOPOLOGY_H
#define _ASM_SPARC64_TOPOLOGY_H
-#include <asm/spitfire.h>
-#define smt_capable() (tlb_type == hypervisor)
+#ifdef CONFIG_SMP
+#define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
+#define topology_core_id(cpu) (cpu_data(cpu).core_id)
+#define topology_core_siblings(cpu) (cpu_core_map[cpu])
+#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu])
+#define mc_capable() (sparc64_multi_core)
+#define smt_capable() (sparc64_multi_core)
+#endif /* CONFIG_SMP */
#include <asm-generic/topology.h>
-#define topology_core_id(cpu) (cpu_data(cpu).core_id)
-#define topology_thread_siblings(cpu) (cpu_sibling_map[cpu])
+#define cpu_coregroup_map(cpu) (cpu_core_map[cpu])
#endif /* _ASM_SPARC64_TOPOLOGY_H */
diff --git a/include/asm-um/a.out.h b/include/asm-um/a.out.h
index 50cee7b296f..7016b893ac9 100644
--- a/include/asm-um/a.out.h
+++ b/include/asm-um/a.out.h
@@ -5,6 +5,7 @@
#include "choose-mode.h"
#undef STACK_TOP
+#undef STACK_TOP_MAX
extern unsigned long stacksizelim;
diff --git a/include/asm-um/bug.h b/include/asm-um/bug.h
index 3357c5e2468..9e33b864c35 100644
--- a/include/asm-um/bug.h
+++ b/include/asm-um/bug.h
@@ -1,6 +1,6 @@
#ifndef __UM_BUG_H
#define __UM_BUG_H
-#include <asm/arch/bug.h>
+#include <asm-generic/bug.h>
#endif
diff --git a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S
index f5de80c31e8..e3f010bd12b 100644
--- a/include/asm-um/common.lds.S
+++ b/include/asm-um/common.lds.S
@@ -20,6 +20,8 @@
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
+ BUG_TABLE
+
__uml_setup_start = .;
.uml.setup.init : { *(.uml.setup.init) }
__uml_setup_end = .;
diff --git a/include/asm-um/paravirt.h b/include/asm-um/paravirt.h
new file mode 100644
index 00000000000..9d6aaad80b5
--- /dev/null
+++ b/include/asm-um/paravirt.h
@@ -0,0 +1,6 @@
+#ifndef __UM_PARAVIRT_H
+#define __UM_PARAVIRT_H
+
+#include "asm/arch/paravirt.h"
+
+#endif
diff --git a/include/asm-v850/pci.h b/include/asm-v850/pci.h
index 4581826e1ca..de2a7d0a81c 100644
--- a/include/asm-v850/pci.h
+++ b/include/asm-v850/pci.h
@@ -116,8 +116,4 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
extern void pci_iounmap (struct pci_dev *dev, void __iomem *addr);
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* __V850_PCI_H__ */
diff --git a/include/asm-v850/rte_cb.h b/include/asm-v850/rte_cb.h
index 9f7f02cb039..e85d261b79b 100644
--- a/include/asm-v850/rte_cb.h
+++ b/include/asm-v850/rte_cb.h
@@ -64,7 +64,6 @@
/* As we don't really support PCI DMA to cpu memory, and use bounce-buffers
instead, perversely enough, this becomes always true! */
# define pci_dma_supported(dev, mask) 1
-# define pci_dac_dma_supported(dev, mask) 0
# define pcibios_assign_all_busses() 1
#endif /* CONFIG_RTE_MB_A_PCI */
diff --git a/include/asm-v850/termbits.h b/include/asm-v850/termbits.h
index f3b43303208..35412f7f3ee 100644
--- a/include/asm-v850/termbits.h
+++ b/include/asm-v850/termbits.h
@@ -17,6 +17,17 @@ struct termios {
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 */
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h
index a0942764076..eea7aecfac7 100644
--- a/include/asm-x86_64/alternative.h
+++ b/include/asm-x86_64/alternative.h
@@ -5,6 +5,41 @@
#include <linux/types.h>
#include <linux/stddef.h>
+
+/*
+ * Alternative inline assembly for SMP.
+ *
+ * The LOCK_PREFIX macro defined here replaces the LOCK and
+ * LOCK_PREFIX macros used everywhere in the source tree.
+ *
+ * SMP alternatives use the same data structures as the other
+ * alternatives and the X86_FEATURE_UP flag to indicate the case of a
+ * UP system running a SMP kernel. The existing apply_alternatives()
+ * works fine for patching a SMP kernel for UP.
+ *
+ * The SMP alternative tables can be kept after boot and contain both
+ * UP and SMP versions of the instructions to allow switching back to
+ * SMP at runtime, when hotplugging in a new CPU, which is especially
+ * useful in virtualized environments.
+ *
+ * The very common lock prefix is handled as special case in a
+ * separate table which is a pure address list without replacement ptr
+ * and size information. That keeps the table sizes small.
+ */
+
+#ifdef CONFIG_SMP
+#define LOCK_PREFIX \
+ ".section .smp_locks,\"a\"\n" \
+ " .align 8\n" \
+ " .quad 661f\n" /* address */ \
+ ".previous\n" \
+ "661:\n\tlock; "
+
+#else /* ! CONFIG_SMP */
+#define LOCK_PREFIX ""
+#endif
+
+/* This must be included *after* the definition of LOCK_PREFIX */
#include <asm/cpufeature.h>
struct alt_instr {
@@ -108,39 +143,6 @@ static inline void alternatives_smp_switch(int smp) {}
*/
#define ASM_OUTPUT2(a, b) a, b
-/*
- * Alternative inline assembly for SMP.
- *
- * The LOCK_PREFIX macro defined here replaces the LOCK and
- * LOCK_PREFIX macros used everywhere in the source tree.
- *
- * SMP alternatives use the same data structures as the other
- * alternatives and the X86_FEATURE_UP flag to indicate the case of a
- * UP system running a SMP kernel. The existing apply_alternatives()
- * works fine for patching a SMP kernel for UP.
- *
- * The SMP alternative tables can be kept after boot and contain both
- * UP and SMP versions of the instructions to allow switching back to
- * SMP at runtime, when hotplugging in a new CPU, which is especially
- * useful in virtualized environments.
- *
- * The very common lock prefix is handled as special case in a
- * separate table which is a pure address list without replacement ptr
- * and size information. That keeps the table sizes small.
- */
-
-#ifdef CONFIG_SMP
-#define LOCK_PREFIX \
- ".section .smp_locks,\"a\"\n" \
- " .align 8\n" \
- " .quad 661f\n" /* address */ \
- ".previous\n" \
- "661:\n\tlock; "
-
-#else /* ! CONFIG_SMP */
-#define LOCK_PREFIX ""
-#endif
-
struct paravirt_patch;
#ifdef CONFIG_PARAVIRT
void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
diff --git a/include/asm-x86_64/boot.h b/include/asm-x86_64/boot.h
index 96b228e6e79..3c46cea8db7 100644
--- a/include/asm-x86_64/boot.h
+++ b/include/asm-x86_64/boot.h
@@ -1,15 +1 @@
-#ifndef _LINUX_BOOT_H
-#define _LINUX_BOOT_H
-
-/* Don't touch these, unless you really know what you're doing. */
-#define DEF_INITSEG 0x9000
-#define DEF_SYSSEG 0x1000
-#define DEF_SETUPSEG 0x9020
-#define DEF_SYSSIZE 0x7F00
-
-/* Internal svga startup constants */
-#define NORMAL_VGA 0xffff /* 80x25 mode */
-#define EXTENDED_VGA 0xfffe /* 80x50 mode */
-#define ASK_VGA 0xfffd /* ask for it at bootup */
-
-#endif
+#include <asm-i386/boot.h>
diff --git a/include/asm-x86_64/bootparam.h b/include/asm-x86_64/bootparam.h
new file mode 100644
index 00000000000..aa82e5238d8
--- /dev/null
+++ b/include/asm-x86_64/bootparam.h
@@ -0,0 +1 @@
+#include <asm-i386/bootparam.h>
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index 0b3c686139f..8baefc3beb2 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -7,115 +7,24 @@
#ifndef __ASM_X8664_CPUFEATURE_H
#define __ASM_X8664_CPUFEATURE_H
-#define NCAPINTS 7 /* N 32-bit words worth of info */
+#include <asm-i386/cpufeature.h>
-/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
-#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */
-#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */
-#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */
-#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */
-#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */
-#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */
-#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
-#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */
-#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */
-#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */
-#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */
-#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */
-#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */
-#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */
-#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
-#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */
-#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */
-#define X86_FEATURE_PN (0*32+18) /* Processor serial number */
-#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */
-#define X86_FEATURE_DS (0*32+21) /* Debug Store */
-#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */
-#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */
-#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
- /* of FPU context), and CR4.OSFXSR available */
-#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */
-#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */
-#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */
-#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */
-#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */
-#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */
-
-/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
-/* Don't duplicate feature flags which are redundant with Intel! */
-#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */
-#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */
-#define X86_FEATURE_FXSR_OPT (1*32+25) /* FXSR optimizations */
-#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */
-#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */
-#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */
-#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */
-
-/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
-#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */
-#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */
-#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */
-
-/* Other features, Linux-defined mapping, word 3 */
-/* This range is used for feature bits which conflict or are synthesized */
-#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */
-#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */
-#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */
-#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */
-#define X86_FEATURE_REP_GOOD (3*32+ 4) /* rep microcode works well on this CPU */
-#define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
-#define X86_FEATURE_SYNC_RDTSC (3*32+6) /* RDTSC syncs CPU core */
-#define X86_FEATURE_FXSAVE_LEAK (3*32+7) /* FIP/FOP/FDP leaks through FXSAVE */
-#define X86_FEATURE_UP (3*32+8) /* SMP kernel running on UP */
-#define X86_FEATURE_ARCH_PERFMON (3*32+9) /* Intel Architectural PerfMon */
-#define X86_FEATURE_PEBS (3*32+10) /* Precise-Event Based Sampling */
-#define X86_FEATURE_BTS (3*32+11) /* Branch Trace Store */
-
-/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
-#define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */
-#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */
-#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */
-#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */
-#define X86_FEATURE_CID (4*32+10) /* Context ID */
-#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */
-#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */
-
-/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
-#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */
-#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */
-#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */
-#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */
-
-/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
-#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */
-#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */
-
-#define cpu_has(c, bit) test_bit(bit, (c)->x86_capability)
-#define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability)
-
-#define cpu_has_fpu 1
+#undef cpu_has_vme
#define cpu_has_vme 0
-#define cpu_has_de 1
-#define cpu_has_pse 1
-#define cpu_has_tsc 1
+
+#undef cpu_has_pae
#define cpu_has_pae ___BUG___
-#define cpu_has_pge 1
-#define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC)
-#define cpu_has_mtrr 1
-#define cpu_has_mmx 1
-#define cpu_has_fxsr 1
-#define cpu_has_xmm 1
-#define cpu_has_xmm2 1
-#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3)
-#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT)
+
+#undef cpu_has_mp
#define cpu_has_mp 1 /* XXX */
+
+#undef cpu_has_k6_mtrr
#define cpu_has_k6_mtrr 0
+
+#undef cpu_has_cyrix_arr
#define cpu_has_cyrix_arr 0
+
+#undef cpu_has_centaur_mcr
#define cpu_has_centaur_mcr 0
-#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH)
-#define cpu_has_ds boot_cpu_has(X86_FEATURE_DS)
-#define cpu_has_pebs boot_cpu_has(X86_FEATURE_PEBS)
-#define cpu_has_bts boot_cpu_has(X86_FEATURE_BTS)
#endif /* __ASM_X8664_CPUFEATURE_H */
diff --git a/include/asm-x86_64/e820.h b/include/asm-x86_64/e820.h
index 6216fa3f280..3486e701bd8 100644
--- a/include/asm-x86_64/e820.h
+++ b/include/asm-x86_64/e820.h
@@ -11,8 +11,6 @@
#ifndef __E820_HEADER
#define __E820_HEADER
-#include <linux/mmzone.h>
-
#define E820MAP 0x2d0 /* our map */
#define E820MAX 128 /* number of entries in E820MAP */
#define E820NR 0x1e8 /* # entries in E820MAP */
@@ -30,7 +28,7 @@ struct e820entry {
} __attribute__((packed));
struct e820map {
- int nr_map;
+ u32 nr_map;
struct e820entry map[E820MAX];
};
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index 49c5e928059..bda94fd5176 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -54,14 +54,6 @@ extern int iommu_setup(char *opt);
#if defined(CONFIG_IOMMU) || defined(CONFIG_CALGARY_IOMMU)
-/*
- * x86-64 always supports DAC, but sometimes it is useful to force
- * devices through the IOMMU to get automatic sg list merging.
- * Optional right now.
- */
-extern int iommu_sac_force;
-#define pci_dac_dma_supported(pci_dev, mask) (!iommu_sac_force)
-
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
@@ -78,8 +70,6 @@ extern int iommu_sac_force;
#else
/* No IOMMU */
-#define pci_dac_dma_supported(pci_dev, mask) 1
-
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
#define pci_unmap_addr(PTR, ADDR_NAME) (0)
@@ -91,36 +81,6 @@ extern int iommu_sac_force;
#include <asm-generic/pci-dma-compat.h>
-static inline dma64_addr_t
-pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
-{
- return ((dma64_addr_t) page_to_phys(page) +
- (dma64_addr_t) offset);
-}
-
-static inline struct page *
-pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- return virt_to_page(__va(dma_addr));
-}
-
-static inline unsigned long
-pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
-{
- return (dma_addr & ~PAGE_MASK);
-}
-
-static inline void
-pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
-}
-
-static inline void
-pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction)
-{
- flush_write_buffers();
-}
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
@@ -135,10 +95,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* __KERNEL__ */
/* generic pci stuff */
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 08b9831f2e1..0a71e0b9a61 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -395,12 +395,14 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* bit at the same time. */
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- do { \
- if (__dirty) { \
- set_pte(__ptep, __entry); \
- flush_tlb_page(__vma, __address); \
- } \
- } while (0)
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed && __dirty) { \
+ set_pte(__ptep, __entry); \
+ flush_tlb_page(__vma, __address); \
+ } \
+ __changed; \
+})
/* Encode and de-code a swap entry */
#define __swp_type(x) (((x).val >> 1) & 0x3f)
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 461ffe4c1fc..efc87a5aff7 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -100,6 +100,7 @@ extern char ignore_irq13;
extern void identify_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
+extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
extern unsigned short num_cache_leaves;
@@ -368,8 +369,6 @@ static inline void sync_core(void)
asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
}
-#define cpu_has_fpu 1
-
#define ARCH_HAS_PREFETCH
static inline void prefetch(void *x)
{
diff --git a/include/asm-x86_64/required-features.h b/include/asm-x86_64/required-features.h
new file mode 100644
index 00000000000..e80d5761b00
--- /dev/null
+++ b/include/asm-x86_64/required-features.h
@@ -0,0 +1,46 @@
+#ifndef _ASM_REQUIRED_FEATURES_H
+#define _ASM_REQUIRED_FEATURES_H 1
+
+/* Define minimum CPUID feature set for kernel These bits are checked
+ really early to actually display a visible error message before the
+ kernel dies. Make sure to assign features to the proper mask!
+
+ The real information is in arch/x86_64/Kconfig.cpu, this just converts
+ the CONFIGs into a bitmask */
+
+/* x86-64 baseline features */
+#define NEED_FPU (1<<(X86_FEATURE_FPU & 31))
+#define NEED_PSE (1<<(X86_FEATURE_PSE & 31))
+#define NEED_MSR (1<<(X86_FEATURE_MSR & 31))
+#define NEED_PAE (1<<(X86_FEATURE_PAE & 31))
+#define NEED_CX8 (1<<(X86_FEATURE_CX8 & 31))
+#define NEED_PGE (1<<(X86_FEATURE_PGE & 31))
+#define NEED_FXSR (1<<(X86_FEATURE_FXSR & 31))
+#define NEED_CMOV (1<<(X86_FEATURE_CMOV & 31))
+#define NEED_XMM (1<<(X86_FEATURE_XMM & 31))
+#define NEED_XMM2 (1<<(X86_FEATURE_XMM2 & 31))
+
+#define REQUIRED_MASK0 (NEED_FPU|NEED_PSE|NEED_MSR|NEED_PAE|\
+ NEED_CX8|NEED_PGE|NEED_FXSR|NEED_CMOV|\
+ NEED_XMM|NEED_XMM2)
+#define SSE_MASK (NEED_XMM|NEED_XMM2)
+
+/* x86-64 baseline features */
+#define NEED_LM (1<<(X86_FEATURE_LM & 31))
+
+#ifdef CONFIG_X86_USE_3DNOW
+# define NEED_3DNOW (1<<(X86_FEATURE_3DNOW & 31))
+#else
+# define NEED_3DNOW 0
+#endif
+
+#define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW)
+
+#define REQUIRED_MASK2 0
+#define REQUIRED_MASK3 0
+#define REQUIRED_MASK4 0
+#define REQUIRED_MASK5 0
+#define REQUIRED_MASK6 0
+#define REQUIRED_MASK7 0
+
+#endif
diff --git a/include/asm-x86_64/segment.h b/include/asm-x86_64/segment.h
index adf2bf1e187..04b8ab21328 100644
--- a/include/asm-x86_64/segment.h
+++ b/include/asm-x86_64/segment.h
@@ -3,6 +3,14 @@
#include <asm/cache.h>
+/* Simple and small GDT entries for booting only */
+
+#define GDT_ENTRY_BOOT_CS 2
+#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
+
+#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
+#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
+
#define __KERNEL_CS 0x10
#define __KERNEL_DS 0x18
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index ae1ed05f281..8696f8ad401 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -626,9 +626,9 @@ __SYSCALL(__NR_utimensat, sys_utimensat)
__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
#define __NR_signalfd 282
__SYSCALL(__NR_signalfd, sys_signalfd)
-#define __NR_timerfd 282
+#define __NR_timerfd 283
__SYSCALL(__NR_timerfd, sys_timerfd)
-#define __NR_eventfd 283
+#define __NR_eventfd 284
__SYSCALL(__NR_eventfd, sys_eventfd)
#ifndef __NO_STUBS
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
index d815649617a..1c1e0d933ee 100644
--- a/include/asm-xtensa/bitops.h
+++ b/include/asm-xtensa/bitops.h
@@ -7,7 +7,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 - 2007 Tensilica Inc.
*/
#ifndef _XTENSA_BITOPS_H
@@ -31,53 +31,30 @@
#if XCHAL_HAVE_NSA
-static __inline__ int __cntlz (unsigned long x)
+static inline unsigned long __cntlz (unsigned long x)
{
int lz;
asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
- return 31 - lz;
+ return lz;
}
-#else
-
-static __inline__ int __cntlz (unsigned long x)
-{
- unsigned long sum, x1, x2, x4, x8, x16;
- x1 = x & 0xAAAAAAAA;
- x2 = x & 0xCCCCCCCC;
- x4 = x & 0xF0F0F0F0;
- x8 = x & 0xFF00FF00;
- x16 = x & 0xFFFF0000;
- sum = x2 ? 2 : 0;
- sum += (x16 != 0) * 16;
- sum += (x8 != 0) * 8;
- sum += (x4 != 0) * 4;
- sum += (x1 != 0);
-
- return sum;
-}
-
-#endif
-
/*
* ffz: Find first zero in word. Undefined if no zero exists.
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
*/
-static __inline__ int ffz(unsigned long x)
+static inline int ffz(unsigned long x)
{
- if ((x = ~x) == 0)
- return 32;
- return __cntlz(x & -x);
+ return 31 - __cntlz(~x & -~x);
}
/*
* __ffs: Find first bit set in word. Return 0 for bit 0
*/
-static __inline__ int __ffs(unsigned long x)
+static inline int __ffs(unsigned long x)
{
- return __cntlz(x & -x);
+ return 31 - __cntlz(x & -x);
}
/*
@@ -86,9 +63,9 @@ static __inline__ int __ffs(unsigned long x)
* differs in spirit from the above ffz (man ffs).
*/
-static __inline__ int ffs(unsigned long x)
+static inline int ffs(unsigned long x)
{
- return __cntlz(x & -x) + 1;
+ return 32 - __cntlz(x & -x);
}
/*
@@ -96,20 +73,36 @@ static __inline__ int ffs(unsigned long x)
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
-static __inline__ int fls (unsigned int x)
+static inline int fls (unsigned int x)
{
- return __cntlz(x);
+ return 32 - __cntlz(x);
}
+
+#else
+
+/* Use the generic implementation if we don't have the nsa/nsau instructions. */
+
+# include <asm-generic/bitops/ffs.h>
+# include <asm-generic/bitops/__ffs.h>
+# include <asm-generic/bitops/ffz.h>
+# include <asm-generic/bitops/fls.h>
+
+#endif
+
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/find.h>
#include <asm-generic/bitops/ext2-non-atomic.h>
#ifdef __XTENSA_EL__
-# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr),(addr))
-# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr),(addr))
+# define ext2_set_bit_atomic(lock,nr,addr) \
+ test_and_set_bit((nr), (unsigned long*)(addr))
+# define ext2_clear_bit_atomic(lock,nr,addr) \
+ test_and_clear_bit((nr), (unsigned long*)(addr))
#elif defined(__XTENSA_EB__)
-# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr) ^ 0x18, (addr))
-# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr)^0x18,(addr))
+# define ext2_set_bit_atomic(lock,nr,addr) \
+ test_and_set_bit((nr) ^ 0x18, (unsigned long*)(addr))
+# define ext2_clear_bit_atomic(lock,nr,addr) \
+ test_and_clear_bit((nr) ^ 0x18, (unsigned long*)(addr))
#else
# error processor byte order undefined!
#endif
diff --git a/include/asm-xtensa/byteorder.h b/include/asm-xtensa/byteorder.h
index 0f540a5f4c0..765edf17a9a 100644
--- a/include/asm-xtensa/byteorder.h
+++ b/include/asm-xtensa/byteorder.h
@@ -12,6 +12,7 @@
#define _XTENSA_BYTEORDER_H
#include <asm/types.h>
+#include <linux/compiler.h>
static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{
@@ -78,4 +79,4 @@ static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
# error processor byte order undefined!
#endif
-#endif /* __ASM_XTENSA_BYTEORDER_H */
+#endif /* _XTENSA_BYTEORDER_H */
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h
index bd09ec02d57..aa212103455 100644
--- a/include/asm-xtensa/coprocessor.h
+++ b/include/asm-xtensa/coprocessor.h
@@ -64,6 +64,7 @@ typedef struct {
# define COPROCESSOR_INFO_SIZE 8
# endif
#endif
+#endif /* XCHAL_HAVE_CP */
#ifndef __ASSEMBLY__
@@ -74,8 +75,11 @@ extern void save_coprocessor_registers(void*, int);
# else
# define release_coprocessors(task)
# endif
-#endif
-#endif
+typedef unsigned char cp_state_t[XTENSA_CP_EXTRA_SIZE]
+ __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
+
+#endif /* !__ASSEMBLY__ */
+
#endif /* _XTENSA_COPROCESSOR_H */
diff --git a/include/asm-xtensa/div64.h b/include/asm-xtensa/div64.h
index 20965e3af1d..f35678cb0a9 100644
--- a/include/asm-xtensa/div64.h
+++ b/include/asm-xtensa/div64.h
@@ -5,21 +5,12 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
*/
#ifndef _XTENSA_DIV64_H
#define _XTENSA_DIV64_H
-#include <linux/types.h>
+#include <asm-generic/div64.h>
-#define do_div(n,base) ({ \
- int __res = n % ((unsigned int) base); \
- n /= (unsigned int) base; \
- __res; })
-
-static inline uint64_t div64_64(uint64_t dividend, uint64_t divisor)
-{
- return dividend / divisor;
-}
-#endif
+#endif /* _XTENSA_DIV64_H */
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index f0f9fd8560a..1569b53cec9 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -13,7 +13,6 @@
#ifndef _XTENSA_ELF_H
#define _XTENSA_ELF_H
-#include <asm/variant/core.h>
#include <asm/ptrace.h>
/* Xtensa processor ELF architecture-magic number */
@@ -49,7 +48,7 @@ typedef struct {
elf_greg_t lcount;
elf_greg_t sar;
elf_greg_t syscall;
- elf_greg_t ar[XCHAL_NUM_AREGS];
+ elf_greg_t ar[64];
} xtensa_gregset_t;
#define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h
index 0609fc691b7..46ab12db573 100644
--- a/include/asm-xtensa/fcntl.h
+++ b/include/asm-xtensa/fcntl.h
@@ -1,99 +1 @@
-/*
- * include/asm-xtensa/fcntl.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) 1995, 1996, 1997, 1998 by Ralf Baechle
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_FCNTL_H
-#define _XTENSA_FCNTL_H
-
-/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
- located on an ext2 file system */
-#define O_ACCMODE 0003
-#define O_RDONLY 00
-#define O_WRONLY 01
-#define O_RDWR 02
-#define O_CREAT 0100 /* not fcntl */
-#define O_EXCL 0200 /* not fcntl */
-#define O_NOCTTY 0400 /* not fcntl */
-#define O_TRUNC 01000 /* not fcntl */
-#define O_APPEND 02000
-#define O_NONBLOCK 04000
-#define O_NDELAY O_NONBLOCK
-#define O_SYNC 010000
-#define FASYNC 020000 /* fcntl, for BSD compatibility */
-#define O_DIRECT 040000 /* direct disk access hint */
-#define O_LARGEFILE 0100000
-#define O_DIRECTORY 0200000 /* must be a directory */
-#define O_NOFOLLOW 0400000 /* don't follow links */
-#define O_NOATIME 01000000
-
-#define F_DUPFD 0 /* dup */
-#define F_GETFD 1 /* get close_on_exec */
-#define F_SETFD 2 /* set/clear close_on_exec */
-#define F_GETFL 3 /* get file->f_flags */
-#define F_SETFL 4 /* set file->f_flags */
-#define F_GETLK 5
-#define F_SETLK 6
-#define F_SETLKW 7
-
-#define F_SETOWN 8 /* for sockets. */
-#define F_GETOWN 9 /* for sockets. */
-#define F_SETSIG 10 /* for sockets. */
-#define F_GETSIG 11 /* for sockets. */
-
-#define F_GETLK64 12 /* using 'struct flock64' */
-#define F_SETLK64 13
-#define F_SETLKW64 14
-
-/* for F_[GET|SET]FL */
-#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK 0
-#define F_WRLCK 1
-#define F_UNLCK 2
-
-/* for old implementation of bsd flock () */
-#define F_EXLCK 4 /* or 3 */
-#define F_SHLCK 8 /* or 4 */
-
-/* for leases */
-#define F_INPROGRESS 16
-
-/* operations for bsd flock(), also used by the kernel implementation */
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* or'd with one of the above to prevent
- blocking */
-#define LOCK_UN 8 /* remove lock */
-
-#define LOCK_MAND 32 /* This is a mandatory flock */
-#define LOCK_READ 64 /* ... Which allows concurrent read operations */
-#define LOCK_WRITE 128 /* ... Which allows concurrent write operations */
-#define LOCK_RW 192 /* ... Which allows concurrent read & write ops */
-
-struct flock {
- short l_type;
- short l_whence;
- off_t l_start;
- off_t l_len;
- pid_t l_pid;
-};
-
-struct flock64 {
- short l_type;
- short l_whence;
- loff_t l_start;
- loff_t l_len;
- pid_t l_pid;
-};
-
-#define F_LINUX_SPECIFIC_BASE 1024
-
-#endif /* _XTENSA_FCNTL_H */
+#include <asm-generic/fcntl.h>
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
index 92f948392eb..c0fd8e5b451 100644
--- a/include/asm-xtensa/mmu_context.h
+++ b/include/asm-xtensa/mmu_context.h
@@ -14,6 +14,7 @@
#define _XTENSA_MMU_CONTEXT_H
#include <linux/stringify.h>
+#include <linux/sched.h>
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index c631d006194..1213cde7543 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -131,6 +131,6 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
-#endif /* __KERNEL__ */
#include <asm-generic/memory_model.h>
+#endif /* __KERNEL__ */
#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h
index 6f281392e3f..ce3a336cad0 100644
--- a/include/asm-xtensa/param.h
+++ b/include/asm-xtensa/param.h
@@ -11,15 +11,13 @@
#ifndef _XTENSA_PARAM_H
#define _XTENSA_PARAM_H
-#include <asm/variant/core.h>
-
#ifdef __KERNEL__
# define HZ 100 /* internal timer frequency */
# define USER_HZ 100 /* for user interfaces in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* frequnzy at which times() counts */
#endif
-#define EXEC_PAGESIZE (1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE)
+#define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
diff --git a/include/asm-xtensa/pci.h b/include/asm-xtensa/pci.h
index 24eb7fc25da..66410acf18b 100644
--- a/include/asm-xtensa/pci.h
+++ b/include/asm-xtensa/pci.h
@@ -64,9 +64,6 @@ struct pci_dev;
#define pci_ubnmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-/* We cannot access memory above 4GB */
-#define pci_dac_dma_supported(pci_dev, mask) (0)
-
/* Map a range of PCI memory or I/O space for a device into user space */
int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
@@ -74,10 +71,6 @@ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
#define HAVE_PCI_MMAP 1
-static inline void pcibios_add_platform_entries(struct pci_dev *dev)
-{
-}
-
#endif /* __KERNEL__ */
/* Implement the pci_ DMA API in terms of the generic device dma_ one */
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
index 1b7fe363fad..77ff02d307b 100644
--- a/include/asm-xtensa/ptrace.h
+++ b/include/asm-xtensa/ptrace.h
@@ -11,8 +11,6 @@
#ifndef _XTENSA_PTRACE_H
#define _XTENSA_PTRACE_H
-#include <asm/variant/core.h>
-
/*
* Kernel stack
*
@@ -101,7 +99,8 @@ struct pt_regs {
unsigned long windowbase; /* 48 */
unsigned long windowstart; /* 52 */
unsigned long syscall; /* 56 */
- int reserved[2]; /* 64 */
+ unsigned long icountlevel; /* 60 */
+ int reserved[1]; /* 64 */
/* Make sure the areg field is 16 bytes aligned. */
int align[0] __attribute__ ((aligned(16)));
@@ -113,6 +112,9 @@ struct pt_regs {
};
#ifdef __KERNEL__
+
+#include <asm/variant/core.h>
+
# define task_pt_regs(tsk) ((struct pt_regs*) \
(task_stack_page(tsk) + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4) - 1)
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
diff --git a/include/asm-xtensa/shmparam.h b/include/asm-xtensa/shmparam.h
index d3b65bfa71c..c8cc16c3da9 100644
--- a/include/asm-xtensa/shmparam.h
+++ b/include/asm-xtensa/shmparam.h
@@ -9,8 +9,6 @@
#ifndef _XTENSA_SHMPARAM_H
#define _XTENSA_SHMPARAM_H
-#include <asm/processor.h>
-
/*
* Xtensa can have variable size caches, and if
* the size of single way is larger than the page size,
diff --git a/include/asm-xtensa/sigcontext.h b/include/asm-xtensa/sigcontext.h
index a7517729141..e3381cee505 100644
--- a/include/asm-xtensa/sigcontext.h
+++ b/include/asm-xtensa/sigcontext.h
@@ -5,21 +5,12 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2001 - 2003 Tensilica Inc.
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
*/
#ifndef _XTENSA_SIGCONTEXT_H
#define _XTENSA_SIGCONTEXT_H
-#define _ASMLANGUAGE
-#include <asm/processor.h>
-#include <asm/coprocessor.h>
-
-
-struct _cpstate {
- unsigned char _cpstate[XTENSA_CP_EXTRA_SIZE];
-} __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
-
struct sigcontext {
unsigned long oldmask;
@@ -27,18 +18,13 @@ struct sigcontext {
/* CPU registers */
unsigned long sc_pc;
unsigned long sc_ps;
- unsigned long sc_wmask;
- unsigned long sc_windowbase;
- unsigned long sc_windowstart;
unsigned long sc_lbeg;
unsigned long sc_lend;
unsigned long sc_lcount;
unsigned long sc_sar;
- unsigned long sc_depc;
- unsigned long sc_dareg0;
- unsigned long sc_treg[4];
- unsigned long sc_areg[XCHAL_NUM_AREGS];
- struct _cpstate *sc_cpstate;
+ unsigned long sc_acclo;
+ unsigned long sc_acchi;
+ unsigned long sc_a[16];
};
-#endif /* __ASM_XTENSA_SIGCONTEXT_H */
+#endif /* _XTENSA_SIGCONTEXT_H */
diff --git a/include/asm-xtensa/termbits.h b/include/asm-xtensa/termbits.h
index 057b9a3d8f8..9972c25ec86 100644
--- a/include/asm-xtensa/termbits.h
+++ b/include/asm-xtensa/termbits.h
@@ -30,6 +30,17 @@ struct termios {
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 */
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h
index 5ae34ab7159..3fa29799b43 100644
--- a/include/asm-xtensa/thread_info.h
+++ b/include/asm-xtensa/thread_info.h
@@ -116,6 +116,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
#define TIF_IRET 5 /* return with iret */
#define TIF_MEMDIE 6
+#define TIF_RESTORE_SIGMASK 7 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
@@ -125,6 +126,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_IRET (1<<TIF_IRET)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h
index 8a7fb6964ce..9bd34024431 100644
--- a/include/asm-xtensa/unistd.h
+++ b/include/asm-xtensa/unistd.h
@@ -485,8 +485,8 @@ __SYSCALL(217, sys_sched_get_priority_min, 1)
__SYSCALL(218, sys_sched_rr_get_interval, 2)
#define __NR_sched_yield 219
__SYSCALL(219, sys_sched_yield, 0)
-#define __NR_sigreturn 222
-__SYSCALL(222, xtensa_sigreturn, 0)
+#define __NR_available222 222
+__SYSCALL(222, sys_ni_syscall, 0)
/* Signal Handling */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index e1013156c25..127d2d192b5 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -49,6 +49,7 @@ header-y += consolemap.h
header-y += const.h
header-y += cycx_cfm.h
header-y += dlm_device.h
+header-y += dlm_netlink.h
header-y += dm-ioctl.h
header-y += dn.h
header-y += dqblk_v1.h
@@ -62,6 +63,8 @@ header-y += fadvise.h
header-y += fd.h
header-y += fdreg.h
header-y += fib_rules.h
+header-y += firewire-cdev.h
+header-y += firewire-constants.h
header-y += fuse.h
header-y += genetlink.h
header-y += gen_stats.h
@@ -88,7 +91,6 @@ header-y += in6.h
header-y += in_route.h
header-y += ioctl.h
header-y += ipmi_msgdefs.h
-header-y += ip_mp_alg.h
header-y += ipsec.h
header-y += ipx.h
header-y += irda.h
@@ -223,6 +225,7 @@ unifdef-y += if_fddi.h
unifdef-y += if_frad.h
unifdef-y += if_ltalk.h
unifdef-y += if_link.h
+unifdef-y += if_pppol2tp.h
unifdef-y += if_pppox.h
unifdef-y += if_shaper.h
unifdef-y += if_tr.h
diff --git a/include/linux/aer.h b/include/linux/aer.h
index 402e178b38e..509656286e5 100644
--- a/include/linux/aer.h
+++ b/include/linux/aer.h
@@ -13,11 +13,13 @@ extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
extern int pci_find_aer_capability(struct pci_dev *dev);
extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+extern int pci_cleanup_aer_correct_error_status(struct pci_dev *dev);
#else
-#define pci_enable_pcie_error_reporting(dev) do { } while (0)
-#define pci_find_aer_capability(dev) do { } while (0)
-#define pci_disable_pcie_error_reporting(dev) do { } while (0)
-#define pci_cleanup_aer_uncorrect_error_status(dev) do { } while (0)
+#define pci_enable_pcie_error_reporting(dev) (-EINVAL)
+#define pci_find_aer_capability(dev) (0)
+#define pci_disable_pcie_error_reporting(dev) (-EINVAL)
+#define pci_cleanup_aer_uncorrect_error_status(dev) (-EINVAL)
+#define pci_cleanup_aer_correct_error_status(dev) (-EINVAL)
#endif
#endif //_AER_H_
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h
new file mode 100644
index 00000000000..ff1255079fa
--- /dev/null
+++ b/include/linux/async_tx.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright © 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * 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 _ASYNC_TX_H_
+#define _ASYNC_TX_H_
+#include <linux/dmaengine.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+/**
+ * dma_chan_ref - object used to manage dma channels received from the
+ * dmaengine core.
+ * @chan - the channel being tracked
+ * @node - node for the channel to be placed on async_tx_master_list
+ * @rcu - for list_del_rcu
+ * @count - number of times this channel is listed in the pool
+ * (for channels with multiple capabiities)
+ */
+struct dma_chan_ref {
+ struct dma_chan *chan;
+ struct list_head node;
+ struct rcu_head rcu;
+ atomic_t count;
+};
+
+/**
+ * async_tx_flags - modifiers for the async_* calls
+ * @ASYNC_TX_XOR_ZERO_DST: this flag must be used for xor operations where the
+ * the destination address is not a source. The asynchronous case handles this
+ * implicitly, the synchronous case needs to zero the destination block.
+ * @ASYNC_TX_XOR_DROP_DST: this flag must be used if the destination address is
+ * also one of the source addresses. In the synchronous case the destination
+ * address is an implied source, whereas the asynchronous case it must be listed
+ * as a source. The destination address must be the first address in the source
+ * array.
+ * @ASYNC_TX_ASSUME_COHERENT: skip cache maintenance operations
+ * @ASYNC_TX_ACK: immediately ack the descriptor, precludes setting up a
+ * dependency chain
+ * @ASYNC_TX_DEP_ACK: ack the dependency descriptor. Useful for chaining.
+ * @ASYNC_TX_KMAP_SRC: if the transaction is to be performed synchronously
+ * take an atomic mapping (KM_USER0) on the source page(s)
+ * @ASYNC_TX_KMAP_DST: if the transaction is to be performed synchronously
+ * take an atomic mapping (KM_USER0) on the dest page(s)
+ */
+enum async_tx_flags {
+ ASYNC_TX_XOR_ZERO_DST = (1 << 0),
+ ASYNC_TX_XOR_DROP_DST = (1 << 1),
+ ASYNC_TX_ASSUME_COHERENT = (1 << 2),
+ ASYNC_TX_ACK = (1 << 3),
+ ASYNC_TX_DEP_ACK = (1 << 4),
+ ASYNC_TX_KMAP_SRC = (1 << 5),
+ ASYNC_TX_KMAP_DST = (1 << 6),
+};
+
+#ifdef CONFIG_DMA_ENGINE
+void async_tx_issue_pending_all(void);
+enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
+void async_tx_run_dependencies(struct dma_async_tx_descriptor *tx);
+struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+ enum dma_transaction_type tx_type);
+#else
+static inline void async_tx_issue_pending_all(void)
+{
+ do { } while (0);
+}
+
+static inline enum dma_status
+dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
+{
+ return DMA_SUCCESS;
+}
+
+static inline void
+async_tx_run_dependencies(struct dma_async_tx_descriptor *tx,
+ struct dma_chan *host_chan)
+{
+ do { } while (0);
+}
+
+static inline struct dma_chan *
+async_tx_find_channel(struct dma_async_tx_descriptor *depend_tx,
+ enum dma_transaction_type tx_type)
+{
+ return NULL;
+}
+#endif
+
+/**
+ * async_tx_sync_epilog - actions to take if an operation is run synchronously
+ * @flags: async_tx flags
+ * @depend_tx: transaction depends on depend_tx
+ * @cb_fn: function to call when the transaction completes
+ * @cb_fn_param: parameter to pass to the callback routine
+ */
+static inline void
+async_tx_sync_epilog(unsigned long flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_fn_param)
+{
+ if (cb_fn)
+ cb_fn(cb_fn_param);
+
+ if (depend_tx && (flags & ASYNC_TX_DEP_ACK))
+ async_tx_ack(depend_tx);
+}
+
+void
+async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
+ enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_xor(struct page *dest, struct page **src_list, unsigned int offset,
+ int src_cnt, size_t len, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_xor_zero_sum(struct page *dest, struct page **src_list,
+ unsigned int offset, int src_cnt, size_t len,
+ u32 *result, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
+ unsigned int src_offset, size_t len, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_memset(struct page *dest, int val, unsigned int offset,
+ size_t len, enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_fn_param);
+
+struct dma_async_tx_descriptor *
+async_trigger_callback(enum async_tx_flags flags,
+ struct dma_async_tx_descriptor *depend_tx,
+ dma_async_tx_callback cb_fn, void *cb_fn_param);
+#endif /* _ASYNC_TX_H_ */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index edb31bfff68..b5a20162af3 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -126,6 +126,7 @@ enum {
ATA_REG_IRQ = ATA_REG_NSECT,
/* ATA device commands */
+ ATA_CMD_DEV_RESET = 0x08, /* ATAPI device reset */
ATA_CMD_CHK_POWER = 0xE5, /* check power mode */
ATA_CMD_STANDBY = 0xE2, /* place in standby power mode */
ATA_CMD_IDLE = 0xE3, /* place in idle power mode */
@@ -151,6 +152,7 @@ enum {
ATA_CMD_WRITE_MULTI_EXT = 0x39,
ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
ATA_CMD_SET_FEATURES = 0xEF,
+ ATA_CMD_SET_MULTI = 0xC6,
ATA_CMD_PACKET = 0xA0,
ATA_CMD_VERIFY = 0x40,
ATA_CMD_VERIFY_EXT = 0x42,
@@ -162,6 +164,8 @@ enum {
ATA_CMD_SET_MAX = 0xF9,
ATA_CMD_SET_MAX_EXT = 0x37,
ATA_CMD_READ_LOG_EXT = 0x2f,
+ ATA_CMD_PMP_READ = 0xE4,
+ ATA_CMD_PMP_WRITE = 0xE8,
/* READ_LOG_EXT pages */
ATA_LOG_SATA_NCQ = 0x10,
@@ -210,6 +214,28 @@ enum {
0=to device, 1=to host */
ATAPI_CDB_LEN = 16,
+ /* PMP stuff */
+ SATA_PMP_MAX_PORTS = 15,
+ SATA_PMP_CTRL_PORT = 15,
+
+ SATA_PMP_GSCR_DWORDS = 128,
+ SATA_PMP_GSCR_PROD_ID = 0,
+ SATA_PMP_GSCR_REV = 1,
+ SATA_PMP_GSCR_PORT_INFO = 2,
+ SATA_PMP_GSCR_ERROR = 32,
+ SATA_PMP_GSCR_ERROR_EN = 33,
+ SATA_PMP_GSCR_FEAT = 64,
+ SATA_PMP_GSCR_FEAT_EN = 96,
+
+ SATA_PMP_PSCR_STATUS = 0,
+ SATA_PMP_PSCR_ERROR = 1,
+ SATA_PMP_PSCR_CONTROL = 2,
+
+ SATA_PMP_FEAT_BIST = (1 << 0),
+ SATA_PMP_FEAT_PMREQ = (1 << 1),
+ SATA_PMP_FEAT_DYNSSC = (1 << 2),
+ SATA_PMP_FEAT_NOTIFY = (1 << 3),
+
/* cable types */
ATA_CBL_NONE = 0,
ATA_CBL_PATA40 = 1,
@@ -249,7 +275,7 @@ enum ata_tf_protocols {
/* ATA taskfile protocols */
ATA_PROT_UNKNOWN, /* unknown/invalid */
ATA_PROT_NODATA, /* no data */
- ATA_PROT_PIO, /* PIO single sector */
+ ATA_PROT_PIO, /* PIO data xfer */
ATA_PROT_DMA, /* DMA */
ATA_PROT_NCQ, /* NCQ */
ATA_PROT_ATAPI, /* packet command, PIO data xfer*/
@@ -416,4 +442,9 @@ static inline int lba_48_ok(u64 block, u32 n_block)
return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
}
+#define sata_pmp_gscr_vendor(gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] & 0xffff)
+#define sata_pmp_gscr_devid(gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] >> 16)
+#define sata_pmp_gscr_rev(gscr) (((gscr)[SATA_PMP_GSCR_REV] >> 8) & 0xff)
+#define sata_pmp_gscr_ports(gscr) ((gscr)[SATA_PMP_GSCR_PORT_INFO] & 0xf)
+
#endif /* __LINUX_ATA_H__ */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index db5b00a792f..fae138bd220 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -868,11 +868,6 @@ void kblockd_flush_work(struct work_struct *work);
*/
#define buffer_heads_over_limit 0
-static inline long blk_congestion_wait(int rw, long timeout)
-{
- return io_schedule_timeout(timeout);
-}
-
static inline long nr_blockdev_pages(void)
{
return 0;
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 0365ec9fc0c..c83534ee1e7 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -59,6 +59,7 @@ extern void *__alloc_bootmem_core(struct bootmem_data *bdata,
unsigned long align,
unsigned long goal,
unsigned long limit);
+extern void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size);
#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE
extern void reserve_bootmem(unsigned long addr, unsigned long size);
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h
index a461f76fb00..dc77fed7b28 100644
--- a/include/linux/console_struct.h
+++ b/include/linux/console_struct.h
@@ -9,6 +9,9 @@
* to achieve effects such as fast scrolling by changing the origin.
*/
+#ifndef _LINUX_CONSOLE_STRUCT_H
+#define _LINUX_CONSOLE_STRUCT_H
+
#include <linux/wait.h>
#include <linux/vt.h>
#include <linux/workqueue.h>
@@ -130,3 +133,5 @@ extern void vc_SAK(struct work_struct *work);
#define CUR_DEFAULT CUR_UNDERLINE
#define CON_IS_VISIBLE(conp) (*conp->vc_display_fg == conp)
+
+#endif /* _LINUX_CONSOLE_STRUCT_H */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 0de7e2ace82..357e8cfedc3 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -295,28 +295,8 @@ struct blkcipher_tfm {
};
struct cipher_tfm {
- void *cit_iv;
- unsigned int cit_ivsize;
- u32 cit_mode;
int (*cit_setkey)(struct crypto_tfm *tfm,
const u8 *key, unsigned int keylen);
- int (*cit_encrypt)(struct crypto_tfm *tfm,
- struct scatterlist *dst,
- struct scatterlist *src,
- unsigned int nbytes);
- int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
- struct scatterlist *dst,
- struct scatterlist *src,
- unsigned int nbytes, u8 *iv);
- int (*cit_decrypt)(struct crypto_tfm *tfm,
- struct scatterlist *dst,
- struct scatterlist *src,
- unsigned int nbytes);
- int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
- struct scatterlist *dst,
- struct scatterlist *src,
- unsigned int nbytes, u8 *iv);
- void (*cit_xor_block)(u8 *dst, const u8 *src);
void (*cit_encrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
};
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index 5a9c49534d0..104e51e20e1 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -38,6 +38,9 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
void debugfs_remove(struct dentry *dentry);
+struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+ struct dentry *new_dir, const char *new_name);
+
struct dentry *debugfs_create_u8(const char *name, mode_t mode,
struct dentry *parent, u8 *value);
struct dentry *debugfs_create_u16(const char *name, mode_t mode,
@@ -85,6 +88,12 @@ static inline struct dentry *debugfs_create_symlink(const char *name,
static inline void debugfs_remove(struct dentry *dentry)
{ }
+static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
+ struct dentry *new_dir, char *new_name)
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline struct dentry *debugfs_create_u8(const char *name, mode_t mode,
struct dentry *parent,
u8 *value)
diff --git a/include/linux/device.h b/include/linux/device.h
index 2e1a2988b7e..be2debed70d 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -238,7 +238,6 @@ extern int __must_check class_device_create_file(struct class_device *,
* @devt: for internal use by the driver core only.
* @node: for internal use by the driver core only.
* @kobj: for internal use by the driver core only.
- * @devt_attr: for internal use by the driver core only.
* @groups: optional additional groups to be created
* @dev: if set, a symlink to the struct device is created in the sysfs
* directory for this struct class device.
@@ -263,8 +262,6 @@ struct class_device {
struct kobject kobj;
struct class * class; /* required */
dev_t devt; /* dev_t, creates the sysfs "dev" */
- struct class_device_attribute *devt_attr;
- struct class_device_attribute uevent_attr;
struct device * dev; /* not necessary, but nice to have */
void * class_data; /* class-specific data */
struct class_device *parent; /* parent of this child device, if there is one */
@@ -419,8 +416,6 @@ struct device {
struct device_type *type;
unsigned is_registered:1;
unsigned uevent_suppress:1;
- struct device_attribute uevent_attr;
- struct device_attribute *devt_attr;
struct semaphore sem; /* semaphore to synchronize calls to
* its driver.
diff --git a/include/linux/dlm.h b/include/linux/dlm.h
index 1b1dcb9a40b..be9d278761e 100644
--- a/include/linux/dlm.h
+++ b/include/linux/dlm.h
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -85,7 +85,11 @@
* Only relevant to locks originating in userspace. A persistent lock will not
* be removed if the process holding the lock exits.
*
- * DLM_LKF_NODLKWT
+ * DLM_LKF_NODLCKWT
+ *
+ * Do not cancel the lock if it gets into conversion deadlock.
+ * Exclude this lock from being monitored due to DLM_LSFL_TIMEWARN.
+ *
* DLM_LKF_NODLCKBLK
*
* net yet implemented
@@ -149,6 +153,7 @@
#define DLM_LKF_ALTPR 0x00008000
#define DLM_LKF_ALTCW 0x00010000
#define DLM_LKF_FORCEUNLOCK 0x00020000
+#define DLM_LKF_TIMEOUT 0x00040000
/*
* Some return codes that are not in errno.h
@@ -199,11 +204,12 @@ struct dlm_lksb {
char * sb_lvbptr;
};
+#define DLM_LSFL_NODIR 0x00000001
+#define DLM_LSFL_TIMEWARN 0x00000002
+#define DLM_LSFL_FS 0x00000004
#ifdef __KERNEL__
-#define DLM_LSFL_NODIR 0x00000001
-
/*
* dlm_new_lockspace
*
diff --git a/include/linux/dlm_device.h b/include/linux/dlm_device.h
index c2735cab2eb..9642277a152 100644
--- a/include/linux/dlm_device.h
+++ b/include/linux/dlm_device.h
@@ -2,7 +2,7 @@
*******************************************************************************
**
** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-** Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+** Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
**
** This copyrighted material is made available to anyone wishing to use,
** modify, copy, or redistribute it subject to the terms and conditions
@@ -18,21 +18,24 @@
#define DLM_USER_LVB_LEN 32
/* Version of the device interface */
-#define DLM_DEVICE_VERSION_MAJOR 5
-#define DLM_DEVICE_VERSION_MINOR 1
+#define DLM_DEVICE_VERSION_MAJOR 6
+#define DLM_DEVICE_VERSION_MINOR 0
#define DLM_DEVICE_VERSION_PATCH 0
/* struct passed to the lock write */
struct dlm_lock_params {
__u8 mode;
__u8 namelen;
- __u16 flags;
+ __u16 unused;
+ __u32 flags;
__u32 lkid;
__u32 parent;
- void __user *castparam;
+ __u64 xid;
+ __u64 timeout;
+ void __user *castparam;
void __user *castaddr;
void __user *bastparam;
- void __user *bastaddr;
+ void __user *bastaddr;
struct dlm_lksb __user *lksb;
char lvb[DLM_USER_LVB_LEN];
char name[0];
@@ -62,9 +65,15 @@ struct dlm_write_request {
} i;
};
+struct dlm_device_version {
+ __u32 version[3];
+};
+
/* struct read from the "device" fd,
consists mainly of userspace pointers for the library to use */
+
struct dlm_lock_result {
+ __u32 version[3];
__u32 length;
void __user * user_astaddr;
void __user * user_astparam;
@@ -83,6 +92,7 @@ struct dlm_lock_result {
#define DLM_USER_CREATE_LOCKSPACE 4
#define DLM_USER_REMOVE_LOCKSPACE 5
#define DLM_USER_PURGE 6
+#define DLM_USER_DEADLOCK 7
/* Arbitrary length restriction */
#define MAX_LS_NAME_LEN 64
diff --git a/include/linux/dlm_netlink.h b/include/linux/dlm_netlink.h
new file mode 100644
index 00000000000..19276332707
--- /dev/null
+++ b/include/linux/dlm_netlink.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ */
+
+#ifndef _DLM_NETLINK_H
+#define _DLM_NETLINK_H
+
+enum {
+ DLM_STATUS_WAITING = 1,
+ DLM_STATUS_GRANTED = 2,
+ DLM_STATUS_CONVERT = 3,
+};
+
+#define DLM_LOCK_DATA_VERSION 1
+
+struct dlm_lock_data {
+ uint16_t version;
+ uint32_t lockspace_id;
+ int nodeid;
+ int ownpid;
+ uint32_t id;
+ uint32_t remid;
+ uint64_t xid;
+ int8_t status;
+ int8_t grmode;
+ int8_t rqmode;
+ unsigned long timestamp;
+ int resource_namelen;
+ char resource_name[DLM_RESNAME_MAXLEN];
+};
+
+enum {
+ DLM_CMD_UNSPEC = 0,
+ DLM_CMD_HELLO, /* user->kernel */
+ DLM_CMD_TIMEOUT, /* kernel->user */
+ __DLM_CMD_MAX,
+};
+
+#define DLM_CMD_MAX (__DLM_CMD_MAX - 1)
+
+enum {
+ DLM_TYPE_UNSPEC = 0,
+ DLM_TYPE_LOCK,
+ __DLM_TYPE_MAX,
+};
+
+#define DLM_TYPE_MAX (__DLM_TYPE_MAX - 1)
+
+#define DLM_GENL_VERSION 0x1
+#define DLM_GENL_NAME "DLM"
+
+#endif /* _DLM_NETLINK_H */
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index c94d8f1d62e..a3b6035b6c8 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -21,29 +21,40 @@
#ifndef DMAENGINE_H
#define DMAENGINE_H
-#ifdef CONFIG_DMA_ENGINE
-
#include <linux/device.h>
#include <linux/uio.h>
#include <linux/kref.h>
#include <linux/completion.h>
#include <linux/rcupdate.h>
+#include <linux/dma-mapping.h>
/**
- * enum dma_event - resource PNP/power managment events
+ * enum dma_state - resource PNP/power managment state
* @DMA_RESOURCE_SUSPEND: DMA device going into low power state
* @DMA_RESOURCE_RESUME: DMA device returning to full power
- * @DMA_RESOURCE_ADDED: DMA device added to the system
+ * @DMA_RESOURCE_AVAILABLE: DMA device available to the system
* @DMA_RESOURCE_REMOVED: DMA device removed from the system
*/
-enum dma_event {
+enum dma_state {
DMA_RESOURCE_SUSPEND,
DMA_RESOURCE_RESUME,
- DMA_RESOURCE_ADDED,
+ DMA_RESOURCE_AVAILABLE,
DMA_RESOURCE_REMOVED,
};
/**
+ * enum dma_state_client - state of the channel in the client
+ * @DMA_ACK: client would like to use, or was using this channel
+ * @DMA_DUP: client has already seen this channel, or is not using this channel
+ * @DMA_NAK: client does not want to see any more channels
+ */
+enum dma_state_client {
+ DMA_ACK,
+ DMA_DUP,
+ DMA_NAK,
+};
+
+/**
* typedef dma_cookie_t - an opaque DMA cookie
*
* if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
@@ -65,6 +76,31 @@ enum dma_status {
};
/**
+ * enum dma_transaction_type - DMA transaction types/indexes
+ */
+enum dma_transaction_type {
+ DMA_MEMCPY,
+ DMA_XOR,
+ DMA_PQ_XOR,
+ DMA_DUAL_XOR,
+ DMA_PQ_UPDATE,
+ DMA_ZERO_SUM,
+ DMA_PQ_ZERO_SUM,
+ DMA_MEMSET,
+ DMA_MEMCPY_CRC32C,
+ DMA_INTERRUPT,
+};
+
+/* last transaction type for creation of the capabilities mask */
+#define DMA_TX_TYPE_END (DMA_INTERRUPT + 1)
+
+/**
+ * dma_cap_mask_t - capabilities bitmap modeled after cpumask_t.
+ * See linux/cpumask.h
+ */
+typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
+
+/**
* struct dma_chan_percpu - the per-CPU part of struct dma_chan
* @refcount: local_t used for open-coded "bigref" counting
* @memcpy_count: transaction counter
@@ -80,7 +116,6 @@ struct dma_chan_percpu {
/**
* struct dma_chan - devices supply DMA channels, clients use them
- * @client: ptr to the client user of this chan, will be %NULL when unused
* @device: ptr to the dma device who supplies this channel, always !%NULL
* @cookie: last cookie value returned to client
* @chan_id: channel ID for sysfs
@@ -88,12 +123,10 @@ struct dma_chan_percpu {
* @refcount: kref, used in "bigref" slow-mode
* @slow_ref: indicates that the DMA channel is free
* @rcu: the DMA channel's RCU head
- * @client_node: used to add this to the client chan list
* @device_node: used to add this to the device chan list
* @local: per-cpu pointer to a struct dma_chan_percpu
*/
struct dma_chan {
- struct dma_client *client;
struct dma_device *device;
dma_cookie_t cookie;
@@ -105,11 +138,11 @@ struct dma_chan {
int slow_ref;
struct rcu_head rcu;
- struct list_head client_node;
struct list_head device_node;
struct dma_chan_percpu *local;
};
+
void dma_chan_cleanup(struct kref *kref);
static inline void dma_chan_get(struct dma_chan *chan)
@@ -134,169 +167,206 @@ static inline void dma_chan_put(struct dma_chan *chan)
/*
* typedef dma_event_callback - function pointer to a DMA event callback
+ * For each channel added to the system this routine is called for each client.
+ * If the client would like to use the channel it returns '1' to signal (ack)
+ * the dmaengine core to take out a reference on the channel and its
+ * corresponding device. A client must not 'ack' an available channel more
+ * than once. When a channel is removed all clients are notified. If a client
+ * is using the channel it must 'ack' the removal. A client must not 'ack' a
+ * removed channel more than once.
+ * @client - 'this' pointer for the client context
+ * @chan - channel to be acted upon
+ * @state - available or removed
*/
-typedef void (*dma_event_callback) (struct dma_client *client,
- struct dma_chan *chan, enum dma_event event);
+struct dma_client;
+typedef enum dma_state_client (*dma_event_callback) (struct dma_client *client,
+ struct dma_chan *chan, enum dma_state state);
/**
* struct dma_client - info on the entity making use of DMA services
* @event_callback: func ptr to call when something happens
- * @chan_count: number of chans allocated
- * @chans_desired: number of chans requested. Can be +/- chan_count
- * @lock: protects access to the channels list
- * @channels: the list of DMA channels allocated
+ * @cap_mask: only return channels that satisfy the requested capabilities
+ * a value of zero corresponds to any capability
* @global_node: list_head for global dma_client_list
*/
struct dma_client {
dma_event_callback event_callback;
- unsigned int chan_count;
- unsigned int chans_desired;
-
- spinlock_t lock;
- struct list_head channels;
+ dma_cap_mask_t cap_mask;
struct list_head global_node;
};
+typedef void (*dma_async_tx_callback)(void *dma_async_param);
+/**
+ * struct dma_async_tx_descriptor - async transaction descriptor
+ * ---dma generic offload fields---
+ * @cookie: tracking cookie for this transaction, set to -EBUSY if
+ * this tx is sitting on a dependency list
+ * @ack: the descriptor can not be reused until the client acknowledges
+ * receipt, i.e. has has a chance to establish any dependency chains
+ * @phys: physical address of the descriptor
+ * @tx_list: driver common field for operations that require multiple
+ * descriptors
+ * @chan: target channel for this operation
+ * @tx_submit: set the prepared descriptor(s) to be executed by the engine
+ * @tx_set_dest: set a destination address in a hardware descriptor
+ * @tx_set_src: set a source address in a hardware descriptor
+ * @callback: routine to call after this operation is complete
+ * @callback_param: general parameter to pass to the callback routine
+ * ---async_tx api specific fields---
+ * @depend_list: at completion this list of transactions are submitted
+ * @depend_node: allow this transaction to be executed after another
+ * transaction has completed, possibly on another channel
+ * @parent: pointer to the next level up in the dependency chain
+ * @lock: protect the dependency list
+ */
+struct dma_async_tx_descriptor {
+ dma_cookie_t cookie;
+ int ack;
+ dma_addr_t phys;
+ struct list_head tx_list;
+ struct dma_chan *chan;
+ dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
+ void (*tx_set_dest)(dma_addr_t addr,
+ struct dma_async_tx_descriptor *tx, int index);
+ void (*tx_set_src)(dma_addr_t addr,
+ struct dma_async_tx_descriptor *tx, int index);
+ dma_async_tx_callback callback;
+ void *callback_param;
+ struct list_head depend_list;
+ struct list_head depend_node;
+ struct dma_async_tx_descriptor *parent;
+ spinlock_t lock;
+};
+
/**
* struct dma_device - info on the entity supplying DMA services
* @chancnt: how many DMA channels are supported
* @channels: the list of struct dma_chan
* @global_node: list_head for global dma_device_list
+ * @cap_mask: one or more dma_capability flags
+ * @max_xor: maximum number of xor sources, 0 if no capability
* @refcount: reference count
* @done: IO completion struct
* @dev_id: unique device ID
+ * @dev: struct device reference for dma mapping api
* @device_alloc_chan_resources: allocate resources and return the
* number of allocated descriptors
* @device_free_chan_resources: release DMA channel's resources
- * @device_memcpy_buf_to_buf: memcpy buf pointer to buf pointer
- * @device_memcpy_buf_to_pg: memcpy buf pointer to struct page
- * @device_memcpy_pg_to_pg: memcpy struct page/offset to struct page/offset
- * @device_memcpy_complete: poll the status of an IOAT DMA transaction
- * @device_memcpy_issue_pending: push appended descriptors to hardware
+ * @device_prep_dma_memcpy: prepares a memcpy operation
+ * @device_prep_dma_xor: prepares a xor operation
+ * @device_prep_dma_zero_sum: prepares a zero_sum operation
+ * @device_prep_dma_memset: prepares a memset operation
+ * @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+ * @device_dependency_added: async_tx notifies the channel about new deps
+ * @device_issue_pending: push pending transactions to hardware
*/
struct dma_device {
unsigned int chancnt;
struct list_head channels;
struct list_head global_node;
+ dma_cap_mask_t cap_mask;
+ int max_xor;
struct kref refcount;
struct completion done;
int dev_id;
+ struct device *dev;
int (*device_alloc_chan_resources)(struct dma_chan *chan);
void (*device_free_chan_resources)(struct dma_chan *chan);
- dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
- void *dest, void *src, size_t len);
- dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
- struct page *page, unsigned int offset, void *kdata,
- size_t len);
- dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
- struct page *dest_pg, unsigned int dest_off,
- struct page *src_pg, unsigned int src_off, size_t len);
- enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
+
+ struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
+ struct dma_chan *chan, size_t len, int int_en);
+ struct dma_async_tx_descriptor *(*device_prep_dma_xor)(
+ struct dma_chan *chan, unsigned int src_cnt, size_t len,
+ int int_en);
+ struct dma_async_tx_descriptor *(*device_prep_dma_zero_sum)(
+ struct dma_chan *chan, unsigned int src_cnt, size_t len,
+ u32 *result, int int_en);
+ struct dma_async_tx_descriptor *(*device_prep_dma_memset)(
+ struct dma_chan *chan, int value, size_t len, int int_en);
+ struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
+ struct dma_chan *chan);
+
+ void (*device_dependency_added)(struct dma_chan *chan);
+ enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
dma_cookie_t cookie, dma_cookie_t *last,
dma_cookie_t *used);
- void (*device_memcpy_issue_pending)(struct dma_chan *chan);
+ void (*device_issue_pending)(struct dma_chan *chan);
};
/* --- public DMA engine API --- */
-struct dma_client *dma_async_client_register(dma_event_callback event_callback);
+void dma_async_client_register(struct dma_client *client);
void dma_async_client_unregister(struct dma_client *client);
-void dma_async_client_chan_request(struct dma_client *client,
- unsigned int number);
+void dma_async_client_chan_request(struct dma_client *client);
+dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
+ void *dest, void *src, size_t len);
+dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
+ struct page *page, unsigned int offset, void *kdata, size_t len);
+dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
+ struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
+ unsigned int src_off, size_t len);
+void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
+ struct dma_chan *chan);
-/**
- * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
- * @chan: DMA channel to offload copy to
- * @dest: destination address (virtual)
- * @src: source address (virtual)
- * @len: length
- *
- * Both @dest and @src must be mappable to a bus address according to the
- * DMA mapping API rules for streaming mappings.
- * Both @dest and @src must stay memory resident (kernel memory or locked
- * user space pages).
- */
-static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
- void *dest, void *src, size_t len)
+static inline void
+async_tx_ack(struct dma_async_tx_descriptor *tx)
{
- int cpu = get_cpu();
- per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
- per_cpu_ptr(chan->local, cpu)->memcpy_count++;
- put_cpu();
-
- return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
+ tx->ack = 1;
}
-/**
- * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
- * @chan: DMA channel to offload copy to
- * @page: destination page
- * @offset: offset in page to copy to
- * @kdata: source address (virtual)
- * @len: length
- *
- * Both @page/@offset and @kdata must be mappable to a bus address according
- * to the DMA mapping API rules for streaming mappings.
- * Both @page/@offset and @kdata must stay memory resident (kernel memory or
- * locked user space pages)
- */
-static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
- struct page *page, unsigned int offset, void *kdata, size_t len)
+#define first_dma_cap(mask) __first_dma_cap(&(mask))
+static inline int __first_dma_cap(const dma_cap_mask_t *srcp)
{
- int cpu = get_cpu();
- per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
- per_cpu_ptr(chan->local, cpu)->memcpy_count++;
- put_cpu();
+ return min_t(int, DMA_TX_TYPE_END,
+ find_first_bit(srcp->bits, DMA_TX_TYPE_END));
+}
- return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
- kdata, len);
+#define next_dma_cap(n, mask) __next_dma_cap((n), &(mask))
+static inline int __next_dma_cap(int n, const dma_cap_mask_t *srcp)
+{
+ return min_t(int, DMA_TX_TYPE_END,
+ find_next_bit(srcp->bits, DMA_TX_TYPE_END, n+1));
}
-/**
- * dma_async_memcpy_pg_to_pg - offloaded copy from page to page
- * @chan: DMA channel to offload copy to
- * @dest_pg: destination page
- * @dest_off: offset in page to copy to
- * @src_pg: source page
- * @src_off: offset in page to copy from
- * @len: length
- *
- * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
- * address according to the DMA mapping API rules for streaming mappings.
- * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
- * (kernel memory or locked user space pages).
- */
-static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
- struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
- unsigned int src_off, size_t len)
+#define dma_cap_set(tx, mask) __dma_cap_set((tx), &(mask))
+static inline void
+__dma_cap_set(enum dma_transaction_type tx_type, dma_cap_mask_t *dstp)
{
- int cpu = get_cpu();
- per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
- per_cpu_ptr(chan->local, cpu)->memcpy_count++;
- put_cpu();
+ set_bit(tx_type, dstp->bits);
+}
- return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
- src_pg, src_off, len);
+#define dma_has_cap(tx, mask) __dma_has_cap((tx), &(mask))
+static inline int
+__dma_has_cap(enum dma_transaction_type tx_type, dma_cap_mask_t *srcp)
+{
+ return test_bit(tx_type, srcp->bits);
}
+#define for_each_dma_cap_mask(cap, mask) \
+ for ((cap) = first_dma_cap(mask); \
+ (cap) < DMA_TX_TYPE_END; \
+ (cap) = next_dma_cap((cap), (mask)))
+
/**
- * dma_async_memcpy_issue_pending - flush pending copies to HW
+ * dma_async_issue_pending - flush pending transactions to HW
* @chan: target DMA channel
*
* This allows drivers to push copies to HW in batches,
* reducing MMIO writes where possible.
*/
-static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
+static inline void dma_async_issue_pending(struct dma_chan *chan)
{
- return chan->device->device_memcpy_issue_pending(chan);
+ return chan->device->device_issue_pending(chan);
}
+#define dma_async_memcpy_issue_pending(chan) dma_async_issue_pending(chan)
+
/**
- * dma_async_memcpy_complete - poll for transaction completion
+ * dma_async_is_tx_complete - poll for transaction completion
* @chan: DMA channel
* @cookie: transaction identifier to check status of
* @last: returns last completed cookie, can be NULL
@@ -306,12 +376,15 @@ static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
* internal state and can be used with dma_async_is_complete() to check
* the status of multiple cookies without re-checking hardware state.
*/
-static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
+static inline enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
{
- return chan->device->device_memcpy_complete(chan, cookie, last, used);
+ return chan->device->device_is_tx_complete(chan, cookie, last, used);
}
+#define dma_async_memcpy_complete(chan, cookie, last, used)\
+ dma_async_is_tx_complete(chan, cookie, last, used)
+
/**
* dma_async_is_complete - test a cookie against chan state
* @cookie: transaction identifier to test status of
@@ -334,6 +407,7 @@ static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie,
return DMA_IN_PROGRESS;
}
+enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
/* --- DMA device --- */
@@ -362,5 +436,4 @@ dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
struct dma_pinned_list *pinned_list, struct page *page,
unsigned int offset, size_t len);
-#endif /* CONFIG_DMA_ENGINE */
#endif /* DMAENGINE_H */
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 904bf3d2d90..b8ac7b01c45 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -12,9 +12,17 @@ enum dmi_field {
DMI_PRODUCT_NAME,
DMI_PRODUCT_VERSION,
DMI_PRODUCT_SERIAL,
+ DMI_PRODUCT_UUID,
DMI_BOARD_VENDOR,
DMI_BOARD_NAME,
DMI_BOARD_VERSION,
+ DMI_BOARD_SERIAL,
+ DMI_BOARD_ASSET_TAG,
+ DMI_CHASSIS_VENDOR,
+ DMI_CHASSIS_TYPE,
+ DMI_CHASSIS_VERSION,
+ DMI_CHASSIS_SERIAL,
+ DMI_CHASSIS_ASSET_TAG,
DMI_STRING_MAX,
};
diff --git a/include/linux/edd.h b/include/linux/edd.h
index b2b3e68aa51..7b647822d6d 100644
--- a/include/linux/edd.h
+++ b/include/linux/edd.h
@@ -49,10 +49,6 @@
#define EDD_MBR_SIG_MAX 16 /* max number of signatures to store */
#define EDD_MBR_SIG_NR_BUF 0x1ea /* addr of number of MBR signtaures at EDD_MBR_SIG_BUF
in boot_params - treat this as 1 byte */
-#define EDD_CL_EQUALS 0x3d646465 /* "edd=" */
-#define EDD_CL_OFF 0x666f /* "of" for off */
-#define EDD_CL_SKIP 0x6b73 /* "sk" for skipmbr */
-#define EDD_CL_ON 0x6e6f /* "on" for on */
#ifndef __ASSEMBLY__
diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
new file mode 100644
index 00000000000..d774b7778c9
--- /dev/null
+++ b/include/linux/eeprom_93cx6.h
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Module: eeprom_93cx6
+ Abstract: EEPROM reader datastructures for 93cx6 chipsets.
+ Supported chipsets: 93c46 & 93c66.
+ */
+
+/*
+ * EEPROM operation defines.
+ */
+#define PCI_EEPROM_WIDTH_93C46 6
+#define PCI_EEPROM_WIDTH_93C66 8
+#define PCI_EEPROM_WIDTH_OPCODE 3
+#define PCI_EEPROM_WRITE_OPCODE 0x05
+#define PCI_EEPROM_READ_OPCODE 0x06
+#define PCI_EEPROM_EWDS_OPCODE 0x10
+#define PCI_EEPROM_EWEN_OPCODE 0x13
+
+/**
+ * struct eeprom_93cx6 - control structure for setting the commands
+ * for reading the eeprom data.
+ * @data: private pointer for the driver.
+ * @register_read(struct eeprom_93cx6 *eeprom): handler to
+ * read the eeprom register, this function should set all reg_* fields.
+ * @register_write(struct eeprom_93cx6 *eeprom): handler to
+ * write to the eeprom register by using all reg_* fields.
+ * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
+ * @reg_data_in: register field to indicate data input
+ * @reg_data_out: register field to indicate data output
+ * @reg_data_clock: register field to set the data clock
+ * @reg_chip_select: register field to set the chip select
+ *
+ * This structure is used for the communication between the driver
+ * and the eeprom_93cx6 handlers for reading the eeprom.
+ */
+struct eeprom_93cx6 {
+ void *data;
+
+ void (*register_read)(struct eeprom_93cx6 *eeprom);
+ void (*register_write)(struct eeprom_93cx6 *eeprom);
+
+ int width;
+
+ char reg_data_in;
+ char reg_data_out;
+ char reg_data_clock;
+ char reg_chip_select;
+};
+
+extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
+ const u8 word, u16 *data);
+extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
+ const u8 word, __le16 *data, const u16 words);
diff --git a/include/linux/errno.h b/include/linux/errno.h
index d90b80f9b28..46685832ed9 100644
--- a/include/linux/errno.h
+++ b/include/linux/errno.h
@@ -5,7 +5,12 @@
#ifdef __KERNEL__
-/* Should never be seen by user programs */
+/*
+ * These should never be seen by user programs. To return one of ERESTART*
+ * codes, signal_pending() MUST be set. Note that ptrace can observe these
+ * at syscall exit tracing, but they will never be left for the debugged user
+ * process to see.
+ */
#define ERESTARTSYS 512
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514 /* restart if no handler.. */
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 071c67abed8..6cdb97365e4 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -39,13 +39,8 @@ extern void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev
extern int eth_header_cache(struct neighbour *neigh,
struct hh_cache *hh);
-extern struct net_device *alloc_etherdev(int sizeof_priv);
-static inline void eth_copy_and_sum (struct sk_buff *dest,
- const unsigned char *src,
- int len, int base)
-{
- memcpy (dest->data, src, len);
-}
+extern struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count);
+#define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
/**
* is_zero_ether_addr - Determine if give Ethernet address is all zeros.
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index f2d248f8cc9..3a632244f31 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -265,6 +265,7 @@ u32 ethtool_op_get_link(struct net_device *dev);
u32 ethtool_op_get_tx_csum(struct net_device *dev);
int ethtool_op_set_tx_csum(struct net_device *dev, u32 data);
int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data);
+int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data);
u32 ethtool_op_get_sg(struct net_device *dev);
int ethtool_op_set_sg(struct net_device *dev, u32 data);
u32 ethtool_op_get_tso(struct net_device *dev);
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
index 0d6ecc60b94..b489fc6d0b6 100644
--- a/include/linux/eventfd.h
+++ b/include/linux/eventfd.h
@@ -19,7 +19,8 @@ int eventfd_signal(struct file *file, int n);
#else /* CONFIG_EVENTFD */
#define eventfd_fget(fd) ERR_PTR(-ENOSYS)
-#define eventfd_signal(f, n) 0
+static inline int eventfd_signal(struct file *file, int n)
+{ return 0; }
#endif /* CONFIG_EVENTFD */
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
index 54c576d414c..de1f9f78625 100644
--- a/include/linux/ext4_fs.h
+++ b/include/linux/ext4_fs.h
@@ -32,9 +32,9 @@
/*
* Define EXT4_RESERVATION to reserve data blocks for expanding files
*/
-#define EXT4_DEFAULT_RESERVE_BLOCKS 8
+#define EXT4_DEFAULT_RESERVE_BLOCKS 8
/*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
-#define EXT4_MAX_RESERVE_BLOCKS 1027
+#define EXT4_MAX_RESERVE_BLOCKS 1027
#define EXT4_RESERVE_WINDOW_NOT_ALLOCATED 0
/*
* Always enable hashed directories
@@ -204,12 +204,12 @@ struct ext4_group_desc
/* Used to pass group descriptor data when online resize is done */
struct ext4_new_group_input {
- __u32 group; /* Group number for this data */
- __u64 block_bitmap; /* Absolute block number of block bitmap */
- __u64 inode_bitmap; /* Absolute block number of inode bitmap */
- __u64 inode_table; /* Absolute block number of inode table start */
- __u32 blocks_count; /* Total number of blocks in this group */
- __u16 reserved_blocks; /* Number of reserved blocks in this group */
+ __u32 group; /* Group number for this data */
+ __u64 block_bitmap; /* Absolute block number of block bitmap */
+ __u64 inode_bitmap; /* Absolute block number of inode bitmap */
+ __u64 inode_table; /* Absolute block number of inode table start */
+ __u32 blocks_count; /* Total number of blocks in this group */
+ __u16 reserved_blocks; /* Number of reserved blocks in this group */
__u16 unused;
};
@@ -310,7 +310,7 @@ struct ext4_inode {
__u8 l_i_frag; /* Fragment number */
__u8 l_i_fsize; /* Fragment size */
__le16 l_i_file_acl_high;
- __le16 l_i_uid_high; /* these 2 fields */
+ __le16 l_i_uid_high; /* these 2 fields */
__le16 l_i_gid_high; /* were reserved2[0] */
__u32 l_i_reserved2;
} linux2;
@@ -513,7 +513,14 @@ struct ext4_super_block {
/*150*/ __le32 s_blocks_count_hi; /* Blocks count */
__le32 s_r_blocks_count_hi; /* Reserved blocks count */
__le32 s_free_blocks_count_hi; /* Free blocks count */
- __u32 s_reserved[169]; /* Padding to the end of the block */
+ __u16 s_min_extra_isize; /* All inodes have at least # bytes */
+ __u16 s_want_extra_isize; /* New inodes should reserve # bytes */
+ __u32 s_flags; /* Miscellaneous flags */
+ __u16 s_raid_stride; /* RAID stride */
+ __u16 s_mmp_interval; /* # seconds to wait in MMP checking */
+ __u64 s_mmp_block; /* Block for multi-mount protection */
+ __u32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/
+ __u32 s_reserved[163]; /* Padding to the end of the block */
};
#ifdef __KERNEL__
@@ -780,9 +787,9 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
* Ok, these declarations are also in <linux/kernel.h> but none of the
* ext4 source programs needs to include it so they are duplicated here.
*/
-# define NORET_TYPE /**/
-# define ATTRIB_NORET __attribute__((noreturn))
-# define NORET_AND noreturn,
+# define NORET_TYPE /**/
+# define ATTRIB_NORET __attribute__((noreturn))
+# define NORET_AND noreturn,
/* balloc.c */
extern unsigned int ext4_block_group(struct super_block *sb,
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h
index 7eb1d73fc5d..acfe59740b0 100644
--- a/include/linux/ext4_fs_extents.h
+++ b/include/linux/ext4_fs_extents.h
@@ -151,8 +151,8 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
sizeof(struct ext4_extent_header)))
#define EXT_HAS_FREE_INDEX(__path__) \
- (le16_to_cpu((__path__)->p_hdr->eh_entries) \
- < le16_to_cpu((__path__)->p_hdr->eh_max))
+ (le16_to_cpu((__path__)->p_hdr->eh_entries) \
+ < le16_to_cpu((__path__)->p_hdr->eh_max))
#define EXT_LAST_EXTENT(__hdr__) \
(EXT_FIRST_EXTENT((__hdr__)) + le16_to_cpu((__hdr__)->eh_entries) - 1)
#define EXT_LAST_INDEX(__hdr__) \
@@ -190,6 +190,7 @@ ext4_ext_invalidate_cache(struct inode *inode)
extern int ext4_extent_tree_init(handle_t *, struct inode *);
extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
+extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *);
extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *);
diff --git a/include/linux/ext4_fs_i.h b/include/linux/ext4_fs_i.h
index d5b177e5b39..9de49440699 100644
--- a/include/linux/ext4_fs_i.h
+++ b/include/linux/ext4_fs_i.h
@@ -41,14 +41,14 @@ struct ext4_reserve_window_node {
struct ext4_block_alloc_info {
/* information about reservation window */
- struct ext4_reserve_window_node rsv_window_node;
+ struct ext4_reserve_window_node rsv_window_node;
/*
* was i_next_alloc_block in ext4_inode_info
* is the logical (file-relative) number of the
* most-recently-allocated block in this file.
* We use this for detecting linearly ascending allocation requests.
*/
- __u32 last_alloc_logical_block;
+ __u32 last_alloc_logical_block;
/*
* Was i_next_alloc_goal in ext4_inode_info
* is the *physical* companion to i_next_alloc_block.
@@ -56,7 +56,7 @@ struct ext4_block_alloc_info {
* allocated to this file. This give us the goal (target) for the next
* allocation when we detect linearly ascending requests.
*/
- ext4_fsblk_t last_alloc_physical_block;
+ ext4_fsblk_t last_alloc_physical_block;
};
#define rsv_start rsv_window._rsv_start
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c654d0e9ce3..66226824ab6 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -942,6 +942,7 @@ extern int fb_new_modelist(struct fb_info *info);
extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
+extern struct class *fb_class;
static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
u8 *src, u32 s_pitch, u32 height)
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index d4455eb2ae3..1a45d6f41b0 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -30,16 +30,38 @@
#define FW_CDEV_EVENT_REQUEST 0x02
#define FW_CDEV_EVENT_ISO_INTERRUPT 0x03
-/* The 'closure' fields are for user space to use. Data passed in the
- * 'closure' field for a request will be returned in the corresponding
- * event. It's a 64-bit type so that it's a fixed size type big
- * enough to hold a pointer on all platforms. */
-
+/**
+ * struct fw_cdev_event_common - Common part of all fw_cdev_event_ types
+ * @closure: For arbitrary use by userspace
+ * @type: Discriminates the fw_cdev_event_ types
+ *
+ * This struct may be used to access generic members of all fw_cdev_event_
+ * types regardless of the specific type.
+ *
+ * Data passed in the @closure field for a request will be returned in the
+ * corresponding event. It is big enough to hold a pointer on all platforms.
+ * The ioctl used to set @closure depends on the @type of event.
+ */
struct fw_cdev_event_common {
__u64 closure;
__u32 type;
};
+/**
+ * struct fw_cdev_event_bus_reset - Sent when a bus reset occurred
+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_GET_INFO ioctl
+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_BUS_RESET
+ * @node_id: New node ID of this node
+ * @local_node_id: Node ID of the local node, i.e. of the controller
+ * @bm_node_id: Node ID of the bus manager
+ * @irm_node_id: Node ID of the iso resource manager
+ * @root_node_id: Node ID of the root node
+ * @generation: New bus generation
+ *
+ * This event is sent when the bus the device belongs to goes through a bus
+ * reset. It provides information about the new bus configuration, such as
+ * new node ID for this device, new root ID, and others.
+ */
struct fw_cdev_event_bus_reset {
__u64 closure;
__u32 type;
@@ -51,6 +73,20 @@ struct fw_cdev_event_bus_reset {
__u32 generation;
};
+/**
+ * struct fw_cdev_event_response - Sent when a response packet was received
+ * @closure: See &fw_cdev_event_common;
+ * set by %FW_CDEV_IOC_SEND_REQUEST ioctl
+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_RESPONSE
+ * @rcode: Response code returned by the remote node
+ * @length: Data length, i.e. the response's payload size in bytes
+ * @data: Payload data, if any
+ *
+ * This event is sent when the stack receives a response to an outgoing request
+ * sent by %FW_CDEV_IOC_SEND_REQUEST ioctl. The payload data for responses
+ * carrying data (read and lock responses) follows immediately and can be
+ * accessed through the @data field.
+ */
struct fw_cdev_event_response {
__u64 closure;
__u32 type;
@@ -59,6 +95,25 @@ struct fw_cdev_event_response {
__u32 data[0];
};
+/**
+ * struct fw_cdev_event_request - Sent on incoming request to an address region
+ * @closure: See &fw_cdev_event_common; set by %FW_CDEV_IOC_ALLOCATE ioctl
+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_REQUEST
+ * @tcode: Transaction code of the incoming request
+ * @offset: The offset into the 48-bit per-node address space
+ * @handle: Reference to the kernel-side pending request
+ * @length: Data length, i.e. the request's payload size in bytes
+ * @data: Incoming data, if any
+ *
+ * This event is sent when the stack receives an incoming request to an address
+ * region registered using the %FW_CDEV_IOC_ALLOCATE ioctl. The request is
+ * guaranteed to be completely contained in the specified region. Userspace is
+ * responsible for sending the response by %FW_CDEV_IOC_SEND_RESPONSE ioctl,
+ * using the same @handle.
+ *
+ * The payload data for requests carrying data (write and lock requests)
+ * follows immediately and can be accessed through the @data field.
+ */
struct fw_cdev_event_request {
__u64 closure;
__u32 type;
@@ -69,14 +124,39 @@ struct fw_cdev_event_request {
__u32 data[0];
};
+/**
+ * struct fw_cdev_event_iso_interrupt - Sent when an iso packet was completed
+ * @closure: See &fw_cdev_event_common;
+ * set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl
+ * @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_ISO_INTERRUPT
+ * @cycle: Cycle counter of the interrupt packet
+ * @header_length: Total length of following headers, in bytes
+ * @header: Stripped headers, if any
+ *
+ * This event is sent when the controller has completed an &fw_cdev_iso_packet
+ * with the %FW_CDEV_ISO_INTERRUPT bit set. In the receive case, the headers
+ * stripped of all packets up until and including the interrupt packet are
+ * returned in the @header field.
+ */
struct fw_cdev_event_iso_interrupt {
__u64 closure;
__u32 type;
__u32 cycle;
- __u32 header_length; /* Length in bytes of following headers. */
+ __u32 header_length;
__u32 header[0];
};
+/**
+ * union fw_cdev_event - Convenience union of fw_cdev_event_ types
+ * @common: Valid for all types
+ * @bus_reset: Valid if @common.type == %FW_CDEV_EVENT_BUS_RESET
+ * @response: Valid if @common.type == %FW_CDEV_EVENT_RESPONSE
+ * @request: Valid if @common.type == %FW_CDEV_EVENT_REQUEST
+ * @iso_interrupt: Valid if @common.type == %FW_CDEV_EVENT_ISO_INTERRUPT
+ *
+ * Convenience union for userspace use. Events could be read(2) into a char
+ * buffer and then cast to this union for further processing.
+ */
union fw_cdev_event {
struct fw_cdev_event_common common;
struct fw_cdev_event_bus_reset bus_reset;
@@ -105,35 +185,47 @@ union fw_cdev_event {
*/
#define FW_CDEV_VERSION 1
+/**
+ * struct fw_cdev_get_info - General purpose information ioctl
+ * @version: The version field is just a running serial number.
+ * We never break backwards compatibility, but may add more
+ * structs and ioctls in later revisions.
+ * @rom_length: If @rom is non-zero, at most rom_length bytes of configuration
+ * ROM will be copied into that user space address. In either
+ * case, @rom_length is updated with the actual length of the
+ * configuration ROM.
+ * @rom: If non-zero, address of a buffer to be filled by a copy of the
+ * local node's configuration ROM
+ * @bus_reset: If non-zero, address of a buffer to be filled by a
+ * &struct fw_cdev_event_bus_reset with the current state
+ * of the bus. This does not cause a bus reset to happen.
+ * @bus_reset_closure: Value of &closure in this and subsequent bus reset events
+ * @card: The index of the card this device belongs to
+ */
struct fw_cdev_get_info {
- /* The version field is just a running serial number. We
- * never break backwards compatibility. Userspace passes in
- * the version it expects and the kernel passes back the
- * highest version it can provide. Even if the structs in
- * this interface are extended in a later version, the kernel
- * will not copy back more data than what was present in the
- * interface version userspace expects. */
__u32 version;
-
- /* If non-zero, at most rom_length bytes of config rom will be
- * copied into that user space address. In either case,
- * rom_length is updated with the actual length of the config
- * rom. */
__u32 rom_length;
__u64 rom;
-
- /* If non-zero, a fw_cdev_event_bus_reset struct will be
- * copied here with the current state of the bus. This does
- * not cause a bus reset to happen. The value of closure in
- * this and sub-sequent bus reset events is set to
- * bus_reset_closure. */
__u64 bus_reset;
__u64 bus_reset_closure;
-
- /* The index of the card this devices belongs to. */
__u32 card;
};
+/**
+ * struct fw_cdev_send_request - Send an asynchronous request packet
+ * @tcode: Transaction code of the request
+ * @length: Length of outgoing payload, in bytes
+ * @offset: 48-bit offset at destination node
+ * @closure: Passed back to userspace in the response event
+ * @data: Userspace pointer to payload
+ * @generation: The bus generation where packet is valid
+ *
+ * Send a request to the device. This ioctl implements all outgoing requests.
+ * Both quadlet and block request specify the payload as a pointer to the data
+ * in the @data field. Once the transaction completes, the kernel writes an
+ * &fw_cdev_event_request event back. The @closure field is passed back to
+ * user space in the response event.
+ */
struct fw_cdev_send_request {
__u32 tcode;
__u32 length;
@@ -143,6 +235,19 @@ struct fw_cdev_send_request {
__u32 generation;
};
+/**
+ * struct fw_cdev_send_response - Send an asynchronous response packet
+ * @rcode: Response code as determined by the userspace handler
+ * @length: Length of outgoing payload, in bytes
+ * @data: Userspace pointer to payload
+ * @handle: The handle from the &fw_cdev_event_request
+ *
+ * Send a response to an incoming request. By setting up an address range using
+ * the %FW_CDEV_IOC_ALLOCATE ioctl, userspace can listen for incoming requests. An
+ * incoming request will generate an %FW_CDEV_EVENT_REQUEST, and userspace must
+ * send a reply using this ioctl. The event has a handle to the kernel-side
+ * pending transaction, which should be used with this ioctl.
+ */
struct fw_cdev_send_response {
__u32 rcode;
__u32 length;
@@ -150,6 +255,21 @@ struct fw_cdev_send_response {
__u32 handle;
};
+/**
+ * struct fw_cdev_allocate - Allocate a CSR address range
+ * @offset: Start offset of the address range
+ * @closure: To be passed back to userspace in request events
+ * @length: Length of the address range, in bytes
+ * @handle: Handle to the allocation, written by the kernel
+ *
+ * Allocate an address range in the 48-bit address space on the local node
+ * (the controller). This allows userspace to listen for requests with an
+ * offset within that address range. When the kernel receives a request
+ * within the range, an &fw_cdev_event_request event will be written back.
+ * The @closure field is passed back to userspace in the response event.
+ * The @handle field is an out parameter, returning a handle to the allocated
+ * range to be used for later deallocation of the range.
+ */
struct fw_cdev_allocate {
__u64 offset;
__u64 closure;
@@ -157,6 +277,11 @@ struct fw_cdev_allocate {
__u32 handle;
};
+/**
+ * struct fw_cdev_deallocate - Free an address range allocation
+ * @handle: Handle to the address range, as returned by the kernel when the
+ * range was allocated
+ */
struct fw_cdev_deallocate {
__u32 handle;
};
@@ -164,10 +289,41 @@ struct fw_cdev_deallocate {
#define FW_CDEV_LONG_RESET 0
#define FW_CDEV_SHORT_RESET 1
+/**
+ * struct fw_cdev_initiate_bus_reset - Initiate a bus reset
+ * @type: %FW_CDEV_SHORT_RESET or %FW_CDEV_LONG_RESET
+ *
+ * Initiate a bus reset for the bus this device is on. The bus reset can be
+ * either the original (long) bus reset or the arbitrated (short) bus reset
+ * introduced in 1394a-2000.
+ */
struct fw_cdev_initiate_bus_reset {
- __u32 type;
+ __u32 type; /* FW_CDEV_SHORT_RESET or FW_CDEV_LONG_RESET */
};
+/**
+ * struct fw_cdev_add_descriptor - Add contents to the local node's config ROM
+ * @immediate: If non-zero, immediate key to insert before pointer
+ * @key: Upper 8 bits of root directory pointer
+ * @data: Userspace pointer to contents of descriptor block
+ * @length: Length of descriptor block data, in bytes
+ * @handle: Handle to the descriptor, written by the kernel
+ *
+ * Add a descriptor block and optionally a preceding immediate key to the local
+ * node's configuration ROM.
+ *
+ * The @key field specifies the upper 8 bits of the descriptor root directory
+ * pointer and the @data and @length fields specify the contents. The @key
+ * should be of the form 0xXX000000. The offset part of the root directory entry
+ * will be filled in by the kernel.
+ *
+ * If not 0, the @immediate field specifies an immediate key which will be
+ * inserted before the root directory pointer.
+ *
+ * If successful, the kernel adds the descriptor and writes back a handle to the
+ * kernel-side object to be used for later removal of the descriptor block and
+ * immediate key.
+ */
struct fw_cdev_add_descriptor {
__u32 immediate;
__u32 key;
@@ -176,6 +332,14 @@ struct fw_cdev_add_descriptor {
__u32 handle;
};
+/**
+ * struct fw_cdev_remove_descriptor - Remove contents from the configuration ROM
+ * @handle: Handle to the descriptor, as returned by the kernel when the
+ * descriptor was added
+ *
+ * Remove a descriptor block and accompanying immediate key from the local
+ * node's configuration ROM.
+ */
struct fw_cdev_remove_descriptor {
__u32 handle;
};
@@ -183,12 +347,24 @@ struct fw_cdev_remove_descriptor {
#define FW_CDEV_ISO_CONTEXT_TRANSMIT 0
#define FW_CDEV_ISO_CONTEXT_RECEIVE 1
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4
-#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8
-#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15
-
+/**
+ * struct fw_cdev_create_iso_context - Create a context for isochronous IO
+ * @type: %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE
+ * @header_size: Header size to strip for receive contexts
+ * @channel: Channel to bind to
+ * @speed: Speed to transmit at
+ * @closure: To be returned in &fw_cdev_event_iso_interrupt
+ * @handle: Handle to context, written back by kernel
+ *
+ * Prior to sending or receiving isochronous I/O, a context must be created.
+ * The context records information about the transmit or receive configuration
+ * and typically maps to an underlying hardware resource. A context is set up
+ * for either sending or receiving. It is bound to a specific isochronous
+ * channel.
+ *
+ * If a context was successfully created, the kernel writes back a handle to the
+ * context, which must be passed in for subsequent operations on that context.
+ */
struct fw_cdev_create_iso_context {
__u32 type;
__u32 header_size;
@@ -198,16 +374,52 @@ struct fw_cdev_create_iso_context {
__u32 handle;
};
+#define FW_CDEV_ISO_PAYLOAD_LENGTH(v) (v)
+#define FW_CDEV_ISO_INTERRUPT (1 << 16)
+#define FW_CDEV_ISO_SKIP (1 << 17)
+#define FW_CDEV_ISO_SYNC (1 << 17)
+#define FW_CDEV_ISO_TAG(v) ((v) << 18)
+#define FW_CDEV_ISO_SY(v) ((v) << 20)
+#define FW_CDEV_ISO_HEADER_LENGTH(v) ((v) << 24)
+
+/**
+ * struct fw_cdev_iso_packet - Isochronous packet
+ * @control: Contains the header length (8 uppermost bits), the sy field
+ * (4 bits), the tag field (2 bits), a sync flag (1 bit),
+ * a skip flag (1 bit), an interrupt flag (1 bit), and the
+ * payload length (16 lowermost bits)
+ * @header: Header and payload
+ *
+ * &struct fw_cdev_iso_packet is used to describe isochronous packet queues.
+ *
+ * Use the FW_CDEV_ISO_ macros to fill in @control. The sy and tag fields are
+ * specified by IEEE 1394a and IEC 61883.
+ *
+ * FIXME - finish this documentation
+ */
struct fw_cdev_iso_packet {
- __u16 payload_length; /* Length of indirect payload. */
- __u32 interrupt : 1; /* Generate interrupt on this packet */
- __u32 skip : 1; /* Set to not send packet at all. */
- __u32 tag : 2;
- __u32 sy : 4;
- __u32 header_length : 8; /* Length of immediate header. */
+ __u32 control;
__u32 header[0];
};
+/**
+ * struct fw_cdev_queue_iso - Queue isochronous packets for I/O
+ * @packets: Userspace pointer to packet data
+ * @data: Pointer into mmap()'ed payload buffer
+ * @size: Size of packet data in bytes
+ * @handle: Isochronous context handle
+ *
+ * Queue a number of isochronous packets for reception or transmission.
+ * This ioctl takes a pointer to an array of &fw_cdev_iso_packet structs,
+ * which describe how to transmit from or receive into a contiguous region
+ * of a mmap()'ed payload buffer. As part of the packet descriptors,
+ * a series of headers can be supplied, which will be prepended to the
+ * payload during DMA.
+ *
+ * The kernel may or may not queue all packets, but will write back updated
+ * values of the @packets, @data and @size fields, so the ioctl can be
+ * resubmitted easily.
+ */
struct fw_cdev_queue_iso {
__u64 packets;
__u64 data;
@@ -215,6 +427,23 @@ struct fw_cdev_queue_iso {
__u32 handle;
};
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8
+#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15
+
+/**
+ * struct fw_cdev_start_iso - Start an isochronous transmission or reception
+ * @cycle: Cycle in which to start I/O. If @cycle is greater than or
+ * equal to 0, the I/O will start on that cycle.
+ * @sync: Determines the value to wait for for receive packets that have
+ * the %FW_CDEV_ISO_SYNC bit set
+ * @tags: Tag filter bit mask. Only valid for isochronous reception.
+ * Determines the tag values for which packets will be accepted.
+ * Use FW_CDEV_ISO_CONTEXT_MATCH_ macros to set @tags.
+ * @handle: Isochronous context handle within which to transmit or receive
+ */
struct fw_cdev_start_iso {
__s32 cycle;
__u32 sync;
@@ -222,6 +451,10 @@ struct fw_cdev_start_iso {
__u32 handle;
};
+/**
+ * struct fw_cdev_stop_iso - Stop an isochronous transmission or reception
+ * @handle: Handle of isochronous context to stop
+ */
struct fw_cdev_stop_iso {
__u32 handle;
};
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7cf0c54a46a..4f0b3bf5983 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -938,6 +938,7 @@ struct super_block {
struct list_head s_files;
struct block_device *s_bdev;
+ struct mtd_info *s_mtd;
struct list_head s_instances;
struct quota_info s_dquot; /* Diskquota specific options */
@@ -1053,7 +1054,7 @@ struct block_device_operations {
};
/*
- * "descriptor" for what we're up to with a read for sendfile().
+ * "descriptor" for what we're up to with a read.
* This allows us to use the same read code yet
* have multiple different users of the data that
* we read from a file.
@@ -1104,7 +1105,6 @@ struct file_operations {
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
- ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
@@ -1210,6 +1210,14 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
__mark_inode_dirty(inode, I_DIRTY_SYNC);
}
+/**
+ * inc_nlink - directly increment an inode's link count
+ * @inode: inode
+ *
+ * This is a low-level filesystem helper to replace any
+ * direct filesystem manipulation of i_nlink. Currently,
+ * it is only here for parity with dec_nlink().
+ */
static inline void inc_nlink(struct inode *inode)
{
inode->i_nlink++;
@@ -1221,11 +1229,30 @@ static inline void inode_inc_link_count(struct inode *inode)
mark_inode_dirty(inode);
}
+/**
+ * drop_nlink - directly drop an inode's link count
+ * @inode: inode
+ *
+ * This is a low-level filesystem helper to replace any
+ * direct filesystem manipulation of i_nlink. In cases
+ * where we are attempting to track writes to the
+ * filesystem, a decrement to zero means an imminent
+ * write when the file is truncated and actually unlinked
+ * on the filesystem.
+ */
static inline void drop_nlink(struct inode *inode)
{
inode->i_nlink--;
}
+/**
+ * clear_nlink - directly zero an inode's link count
+ * @inode: inode
+ *
+ * This is a low-level filesystem helper to replace any
+ * direct filesystem manipulation of i_nlink. See
+ * drop_nlink() for why we care about i_nlink hitting zero.
+ */
static inline void clear_nlink(struct inode *inode)
{
inode->i_nlink = 0;
@@ -1734,7 +1761,6 @@ extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
unsigned long, loff_t, loff_t *, size_t, ssize_t);
extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
-extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
extern void do_generic_mapping_read(struct address_space *mapping,
struct file_ra_state *, struct file *,
loff_t *, read_descriptor_t *, read_actor_t);
@@ -1764,9 +1790,6 @@ extern int nonseekable_open(struct inode * inode, struct file * filp);
#ifdef CONFIG_FS_XIP
extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
loff_t *ppos);
-extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor,
- void *target);
extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma);
extern ssize_t xip_file_write(struct file *filp, const char __user *buf,
size_t len, loff_t *ppos);
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 899fc7f20ed..99650353adf 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -17,7 +17,6 @@ union ktime;
#define FUTEX_LOCK_PI 6
#define FUTEX_UNLOCK_PI 7
#define FUTEX_TRYLOCK_PI 8
-#define FUTEX_CMP_REQUEUE_PI 9
#define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CMD_MASK ~FUTEX_PRIVATE_FLAG
@@ -98,14 +97,9 @@ struct robust_list_head {
#define FUTEX_OWNER_DIED 0x40000000
/*
- * Some processes have been requeued on this PI-futex
- */
-#define FUTEX_WAITER_REQUEUED 0x20000000
-
-/*
* The rest of the robust-futex field is for the TID:
*/
-#define FUTEX_TID_MASK 0x0fffffff
+#define FUTEX_TID_MASK 0x3fffffff
/*
* This limit protects against a deliberately circular list.
@@ -139,7 +133,6 @@ handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi);
#define FUT_OFF_MMSHARED 2 /* We set bit 1 if key has a reference on mm */
union futex_key {
- u32 __user *uaddr;
struct {
unsigned long pgoff;
struct inode *inode;
diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h
index 8b7e4c1e32a..a44a6a078f0 100644
--- a/include/linux/gfs2_ondisk.h
+++ b/include/linux/gfs2_ondisk.h
@@ -54,18 +54,6 @@ struct gfs2_inum {
__be64 no_addr;
};
-struct gfs2_inum_host {
- __u64 no_formal_ino;
- __u64 no_addr;
-};
-
-static inline int gfs2_inum_equal(const struct gfs2_inum_host *ino1,
- const struct gfs2_inum_host *ino2)
-{
- return ino1->no_formal_ino == ino2->no_formal_ino &&
- ino1->no_addr == ino2->no_addr;
-}
-
/*
* Generic metadata head structure
* Every inplace buffer logged in the journal must start with this.
@@ -94,12 +82,6 @@ struct gfs2_meta_header {
__be32 __pad1; /* Was incarnation number in gfs1 */
};
-struct gfs2_meta_header_host {
- __u32 mh_magic;
- __u32 mh_type;
- __u32 mh_format;
-};
-
/*
* super-block structure
*
@@ -139,23 +121,6 @@ struct gfs2_sb {
/* In gfs1, quota and license dinodes followed */
};
-struct gfs2_sb_host {
- struct gfs2_meta_header_host sb_header;
-
- __u32 sb_fs_format;
- __u32 sb_multihost_format;
-
- __u32 sb_bsize;
- __u32 sb_bsize_shift;
-
- struct gfs2_inum_host sb_master_dir; /* Was jindex dinode in gfs1 */
- struct gfs2_inum_host sb_root_dir;
-
- char sb_lockproto[GFS2_LOCKNAME_LEN];
- char sb_locktable[GFS2_LOCKNAME_LEN];
- /* In gfs1, quota and license dinodes followed */
-};
-
/*
* resource index structure
*/
@@ -173,14 +138,6 @@ struct gfs2_rindex {
__u8 ri_reserved[64];
};
-struct gfs2_rindex_host {
- __u64 ri_addr; /* grp block disk address */
- __u64 ri_data0; /* first data location */
- __u32 ri_length; /* length of rgrp header in fs blocks */
- __u32 ri_data; /* num of data blocks in rgrp */
- __u32 ri_bitbytes; /* number of bytes in data bitmaps */
-};
-
/*
* resource group header structure
*/
@@ -212,13 +169,6 @@ struct gfs2_rgrp {
__u8 rg_reserved[80]; /* Several fields from gfs1 now reserved */
};
-struct gfs2_rgrp_host {
- __u32 rg_flags;
- __u32 rg_free;
- __u32 rg_dinodes;
- __u64 rg_igeneration;
-};
-
/*
* quota structure
*/
@@ -230,12 +180,6 @@ struct gfs2_quota {
__u8 qu_reserved[64];
};
-struct gfs2_quota_host {
- __u64 qu_limit;
- __u64 qu_warn;
- __u64 qu_value;
-};
-
/*
* dinode structure
*/
@@ -315,29 +259,11 @@ struct gfs2_dinode {
struct gfs2_inum __pad4; /* Unused even in current gfs1 */
__be64 di_eattr; /* extended attribute block number */
+ __be32 di_atime_nsec; /* nsec portion of atime */
+ __be32 di_mtime_nsec; /* nsec portion of mtime */
+ __be32 di_ctime_nsec; /* nsec portion of ctime */
- __u8 di_reserved[56];
-};
-
-struct gfs2_dinode_host {
- __u64 di_size; /* number of bytes in file */
- __u64 di_blocks; /* number of blocks in file */
-
- /* This section varies from gfs1. Padding added to align with
- * remainder of dinode
- */
- __u64 di_goal_meta; /* rgrp to alloc from next */
- __u64 di_goal_data; /* data block goal */
- __u64 di_generation; /* generation number for NFS */
-
- __u32 di_flags; /* GFS2_DIF_... */
- __u16 di_height; /* height of metadata */
-
- /* These only apply to directories */
- __u16 di_depth; /* Number of bits in the table */
- __u32 di_entries; /* The number of entries in the directory */
-
- __u64 di_eattr; /* extended attribute block number */
+ __u8 di_reserved[44];
};
/*
@@ -414,16 +340,6 @@ struct gfs2_log_header {
__be32 lh_hash;
};
-struct gfs2_log_header_host {
- struct gfs2_meta_header_host lh_header;
-
- __u64 lh_sequence; /* Sequence number of this transaction */
- __u32 lh_flags; /* GFS2_LOG_HEAD_... */
- __u32 lh_tail; /* Block number of log tail */
- __u32 lh_blkno;
- __u32 lh_hash;
-};
-
/*
* Log type descriptor
*/
@@ -464,11 +380,6 @@ struct gfs2_inum_range {
__be64 ir_length;
};
-struct gfs2_inum_range_host {
- __u64 ir_start;
- __u64 ir_length;
-};
-
/*
* Statfs change
* Describes an change to the pool of free and allocated
@@ -481,12 +392,6 @@ struct gfs2_statfs_change {
__be64 sc_dinodes;
};
-struct gfs2_statfs_change_host {
- __u64 sc_total;
- __u64 sc_free;
- __u64 sc_dinodes;
-};
-
/*
* Quota change
* Describes an allocation change for a particular
@@ -501,39 +406,12 @@ struct gfs2_quota_change {
__be32 qc_id;
};
-struct gfs2_quota_change_host {
- __u64 qc_change;
- __u32 qc_flags; /* GFS2_QCF_... */
- __u32 qc_id;
+struct gfs2_quota_lvb {
+ __be32 qb_magic;
+ __u32 __pad;
+ __be64 qb_limit; /* Hard limit of # blocks to alloc */
+ __be64 qb_warn; /* Warn user when alloc is above this # */
+ __be64 qb_value; /* Current # blocks allocated */
};
-#ifdef __KERNEL__
-/* Translation functions */
-
-extern void gfs2_inum_in(struct gfs2_inum_host *no, const void *buf);
-extern void gfs2_inum_out(const struct gfs2_inum_host *no, void *buf);
-extern void gfs2_sb_in(struct gfs2_sb_host *sb, const void *buf);
-extern void gfs2_rindex_in(struct gfs2_rindex_host *ri, const void *buf);
-extern void gfs2_rindex_out(const struct gfs2_rindex_host *ri, void *buf);
-extern void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf);
-extern void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf);
-extern void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf);
-struct gfs2_inode;
-extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf);
-extern void gfs2_ea_header_in(struct gfs2_ea_header *ea, const void *buf);
-extern void gfs2_ea_header_out(const struct gfs2_ea_header *ea, void *buf);
-extern void gfs2_log_header_in(struct gfs2_log_header_host *lh, const void *buf);
-extern void gfs2_inum_range_in(struct gfs2_inum_range_host *ir, const void *buf);
-extern void gfs2_inum_range_out(const struct gfs2_inum_range_host *ir, void *buf);
-extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf);
-extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf);
-extern void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void *buf);
-
-/* Printing functions */
-
-extern void gfs2_rindex_print(const struct gfs2_rindex_host *ri);
-extern void gfs2_dinode_print(const struct gfs2_inode *ip);
-
-#endif /* __KERNEL__ */
-
#endif /* __GFS2_ONDISK_DOT_H__ */
diff --git a/include/linux/gpio_mouse.h b/include/linux/gpio_mouse.h
new file mode 100644
index 00000000000..44ed7aa14d8
--- /dev/null
+++ b/include/linux/gpio_mouse.h
@@ -0,0 +1,61 @@
+/*
+ * Driver for simulating a mouse on GPIO lines.
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _GPIO_MOUSE_H
+#define _GPIO_MOUSE_H
+
+#define GPIO_MOUSE_POLARITY_ACT_HIGH 0x00
+#define GPIO_MOUSE_POLARITY_ACT_LOW 0x01
+
+#define GPIO_MOUSE_PIN_UP 0
+#define GPIO_MOUSE_PIN_DOWN 1
+#define GPIO_MOUSE_PIN_LEFT 2
+#define GPIO_MOUSE_PIN_RIGHT 3
+#define GPIO_MOUSE_PIN_BLEFT 4
+#define GPIO_MOUSE_PIN_BMIDDLE 5
+#define GPIO_MOUSE_PIN_BRIGHT 6
+#define GPIO_MOUSE_PIN_MAX 7
+
+/**
+ * struct gpio_mouse_platform_data
+ * @scan_ms: integer in ms specifying the scan periode.
+ * @polarity: Pin polarity, active high or low.
+ * @up: GPIO line for up value.
+ * @down: GPIO line for down value.
+ * @left: GPIO line for left value.
+ * @right: GPIO line for right value.
+ * @bleft: GPIO line for left button.
+ * @bmiddle: GPIO line for middle button.
+ * @bright: GPIO line for right button.
+ *
+ * This struct must be added to the platform_device in the board code.
+ * It is used by the gpio_mouse driver to setup GPIO lines and to
+ * calculate mouse movement.
+ */
+struct gpio_mouse_platform_data {
+ int scan_ms;
+ int polarity;
+
+ union {
+ struct {
+ int up;
+ int down;
+ int left;
+ int right;
+
+ int bleft;
+ int bmiddle;
+ int bright;
+ };
+ int pins[GPIO_MOUSE_PIN_MAX];
+ };
+};
+
+#endif /* _GPIO_MOUSE_H */
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 7803014f3a1..8d302298a16 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -79,6 +79,19 @@
#endif
#ifdef CONFIG_PREEMPT
+# define PREEMPT_CHECK_OFFSET 1
+#else
+# define PREEMPT_CHECK_OFFSET 0
+#endif
+
+/*
+ * Check whether we were atomic before we did preempt_disable():
+ * (used by the scheduler)
+ */
+#define in_atomic_preempt_off() \
+ ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
+
+#ifdef CONFIG_PREEMPT
# define preemptible() (preempt_count() == 0 && !irqs_disabled())
# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
#else
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 827ee748fd4..898103b401f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -263,19 +263,28 @@ struct hid_item {
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
#define HID_QUIRK_MIGHTYMOUSE 0x00000400
-#define HID_QUIRK_CYMOTION 0x00000800
-#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
-#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
-#define HID_QUIRK_INVERT_HWHEEL 0x00004000
-#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000
-#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000
-#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000
-#define HID_QUIRK_IGNORE_MOUSE 0x00040000
-#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000
-#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
-#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
-#define HID_QUIRK_RESET_LEDS 0x00400000
-#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000
+#define HID_QUIRK_POWERBOOK_HAS_FN 0x00000800
+#define HID_QUIRK_POWERBOOK_FN_ON 0x00001000
+#define HID_QUIRK_INVERT_HWHEEL 0x00002000
+#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00004000
+#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00008000
+#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
+#define HID_QUIRK_IGNORE_MOUSE 0x00020000
+#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000
+#define HID_QUIRK_DUPLICATE_USAGES 0x00080000
+#define HID_QUIRK_RESET_LEDS 0x00100000
+#define HID_QUIRK_HIDINPUT 0x00200000
+#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL 0x00400000
+#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000
+
+/*
+ * Separate quirks for runtime report descriptor fixup
+ */
+
+#define HID_QUIRK_RDESC_CYMOTION 0x00000001
+#define HID_QUIRK_RDESC_LOGITECH 0x00000002
+#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
+#define HID_QUIRK_RDESC_PETALYNX 0x00000008
/*
* This is the global environment of the parser. This information is
@@ -488,6 +497,11 @@ struct hid_descriptor {
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
/* HID core API */
+
+#ifdef CONFIG_HID_DEBUG
+extern int hid_debug;
+#endif
+
extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
extern int hidinput_connect(struct hid_device *);
@@ -506,6 +520,7 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct, const u32 quirks);
int usbhid_quirks_init(char **quirks_param);
void usbhid_quirks_exit(void);
+void usbhid_fixup_report_descriptor(const u16, const u16, char *, unsigned, char **);
#ifdef CONFIG_HID_FF
int hid_ff_init(struct hid_device *hid);
@@ -523,14 +538,19 @@ static inline int hid_pidff_init(struct hid_device *hid) { return -ENODEV; }
#else
static inline int hid_ff_init(struct hid_device *hid) { return -1; }
#endif
-#ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , \
- __FILE__ , ## arg)
+
+#ifdef CONFIG_HID_DEBUG
+#define dbg_hid(format, arg...) if (hid_debug) \
+ printk(KERN_DEBUG "%s: " format ,\
+ __FILE__ , ## arg)
+#define dbg_hid_line(format, arg...) if (hid_debug) \
+ printk(format, ## arg)
#else
-#define dbg(format, arg...) do {} while (0)
+#define dbg_hid(format, arg...) do {} while (0)
+#define dbg_hid_line dbg_hid
#endif
-#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
+#define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \
__FILE__ , ## arg)
#endif
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index b4570b62ab8..2c13715e9dd 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -163,7 +163,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
extern const struct file_operations hugetlbfs_file_operations;
extern struct vm_operations_struct hugetlb_vm_ops;
-struct file *hugetlb_zero_setup(size_t);
+struct file *hugetlb_file_setup(const char *name, size_t);
int hugetlb_get_quota(struct address_space *mapping);
void hugetlb_put_quota(struct address_space *mapping);
@@ -185,7 +185,7 @@ static inline void set_file_hugepages(struct file *file)
#define is_file_hugepages(file) 0
#define set_file_hugepages(file) BUG()
-#define hugetlb_zero_setup(size) ERR_PTR(-ENOSYS)
+#define hugetlb_file_setup(name,size) ERR_PTR(-ENOSYS)
#endif /* !CONFIG_HUGETLBFS */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index cae7d618030..2eaba21b9b1 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -90,7 +90,7 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
const u8 *values);
/* Returns the number of read bytes */
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
- u8 command, u8 *values);
+ u8 command, u8 length, u8 *values);
extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
u8 command, u8 length,
const u8 *values);
@@ -150,15 +150,20 @@ struct i2c_driver {
/**
* struct i2c_client - represent an I2C slave device
+ * @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
+ * I2C_CLIENT_PEC indicates it uses SMBus Packet Error Checking
* @addr: Address used on the I2C bus connected to the parent adapter.
* @name: Indicates the type of the device, usually a chip name that's
* generic enough to hide second-sourcing and compatible revisions.
+ * @adapter: manages the bus segment hosting this I2C device
* @dev: Driver model device node for the slave.
+ * @irq: indicates the IRQ generated by this device (if any)
* @driver_name: Identifies new-style driver used with this device; also
* used as the module name for hotplug/coldplug modprobe support.
*
* An i2c_client identifies a single device (i.e. chip) connected to an
- * i2c bus. The behaviour is defined by the routines of the driver.
+ * i2c bus. The behaviour exposed to Linux is defined by the driver
+ * managing the device.
*/
struct i2c_client {
unsigned short flags; /* div., see below */
@@ -180,7 +185,8 @@ struct i2c_client {
static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
{
- return to_i2c_client(container_of(kobj, struct device, kobj));
+ struct device * const dev = container_of(kobj, struct device, kobj);
+ return to_i2c_client(dev);
}
static inline void *i2c_get_clientdata (struct i2c_client *dev)
@@ -201,7 +207,7 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
* @addr: stored in i2c_client.addr
* @platform_data: stored in i2c_client.dev.platform_data
* @irq: stored in i2c_client.irq
-
+ *
* I2C doesn't actually support hardware probing, although controllers and
* devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
* a device at a given address. Drivers commonly need more information than
@@ -210,7 +216,7 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
* i2c_board_info is used to build tables of information listing I2C devices
* that are present. This information is used to grow the driver model tree
* for "new style" I2C drivers. For mainboards this is done statically using
- * i2c_register_board_info(), where @bus_num represents an adapter that isn't
+ * i2c_register_board_info(); bus numbers identify adapters that aren't
* yet available. For add-on boards, i2c_new_device() does this dynamically
* with the adapter already known.
*/
@@ -518,8 +524,9 @@ union i2c_smbus_data {
#define I2C_SMBUS_WORD_DATA 3
#define I2C_SMBUS_PROC_CALL 4
#define I2C_SMBUS_BLOCK_DATA 5
-#define I2C_SMBUS_I2C_BLOCK_DATA 6
+#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
/* ----- commands for the ioctl like i2c_command call:
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 07aba87d369..19ab2580405 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -25,6 +25,7 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/semaphore.h>
+#include <asm/mutex.h>
/******************************************************************************
* IDE driver configuration options (play with these as desired):
@@ -685,6 +686,8 @@ typedef struct hwif_s {
u8 mwdma_mask;
u8 swdma_mask;
+ u8 cbl; /* cable type */
+
hwif_chipset_t chipset; /* sub-module for tuning.. */
struct pci_dev *pci_dev; /* for pci chipsets */
@@ -735,8 +738,8 @@ typedef struct hwif_s {
void (*ide_dma_clear_irq)(ide_drive_t *drive);
void (*dma_host_on)(ide_drive_t *drive);
void (*dma_host_off)(ide_drive_t *drive);
- int (*ide_dma_lostirq)(ide_drive_t *drive);
- int (*ide_dma_timeout)(ide_drive_t *drive);
+ void (*dma_lost_irq)(ide_drive_t *drive);
+ void (*dma_timeout)(ide_drive_t *drive);
void (*OUTB)(u8 addr, unsigned long port);
void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
@@ -791,7 +794,6 @@ typedef struct hwif_s {
unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */
unsigned reset : 1; /* reset after probe */
unsigned autodma : 1; /* auto-attempt using DMA at boot */
- unsigned udma_four : 1; /* 1=ATA-66 capable, 0=default */
unsigned no_lba48 : 1; /* 1 = cannot do LBA48 */
unsigned no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
unsigned auto_poll : 1; /* supports nop auto-poll */
@@ -863,7 +865,7 @@ typedef struct hwgroup_s {
typedef struct ide_driver_s ide_driver_t;
-extern struct semaphore ide_setting_sem;
+extern struct mutex ide_setting_mtx;
int set_io_32bit(ide_drive_t *, int);
int set_pio_mode(ide_drive_t *, int);
@@ -1001,6 +1003,7 @@ struct ide_driver_s {
struct device_driver gen_driver;
int (*probe)(ide_drive_t *);
void (*remove)(ide_drive_t *);
+ void (*resume)(ide_drive_t *);
void (*shutdown)(ide_drive_t *);
#ifdef CONFIG_IDE_PROC_FS
ide_proc_entry_t *proc;
@@ -1303,8 +1306,8 @@ extern int __ide_dma_check(ide_drive_t *);
extern int ide_dma_setup(ide_drive_t *);
extern void ide_dma_start(ide_drive_t *);
extern int __ide_dma_end(ide_drive_t *);
-extern int __ide_dma_lostirq(ide_drive_t *);
-extern int __ide_dma_timeout(ide_drive_t *);
+extern void ide_dma_lost_irq(ide_drive_t *);
+extern void ide_dma_timeout(ide_drive_t *);
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
#else
@@ -1381,11 +1384,11 @@ extern const ide_pio_timings_t ide_pio_timings[6];
extern spinlock_t ide_lock;
-extern struct semaphore ide_cfg_sem;
+extern struct mutex ide_cfg_mtx;
/*
* Structure locking:
*
- * ide_cfg_sem and ide_lock together protect changes to
+ * ide_cfg_mtx and ide_lock together protect changes to
* ide_hwif_t->{next,hwgroup}
* ide_drive_t->next
*
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 826803449db..915572fa030 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -83,4 +83,33 @@ void idr_remove(struct idr *idp, int id);
void idr_destroy(struct idr *idp);
void idr_init(struct idr *idp);
+
+/*
+ * IDA - IDR based id allocator, use when translation from id to
+ * pointer isn't necessary.
+ */
+#define IDA_CHUNK_SIZE 128 /* 128 bytes per chunk */
+#define IDA_BITMAP_LONGS (128 / sizeof(long) - 1)
+#define IDA_BITMAP_BITS (IDA_BITMAP_LONGS * sizeof(long) * 8)
+
+struct ida_bitmap {
+ long nr_busy;
+ unsigned long bitmap[IDA_BITMAP_LONGS];
+};
+
+struct ida {
+ struct idr idr;
+ struct ida_bitmap *free_bitmap;
+};
+
+#define IDA_INIT(name) { .idr = IDR_INIT(name), .free_bitmap = NULL, }
+#define DEFINE_IDA(name) struct ida name = IDA_INIT(name)
+
+int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
+int ida_get_new(struct ida *ida, int *p_id);
+void ida_remove(struct ida *ida, int id);
+void ida_destroy(struct ida *ida);
+void ida_init(struct ida *ida);
+
#endif /* __IDR_H__ */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index ecd61e8438a..272f8c8c90d 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -227,6 +227,17 @@ struct ieee80211_cts {
#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
+/* 802.11g ERP information element */
+#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
+#define WLAN_ERP_USE_PROTECTION (1<<1)
+#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
+
+/* WLAN_ERP_BARKER_PREAMBLE values */
+enum {
+ WLAN_ERP_PREAMBLE_SHORT = 0,
+ WLAN_ERP_PREAMBLE_LONG = 1,
+};
+
/* Status codes */
enum ieee80211_statuscode {
WLAN_STATUS_SUCCESS = 0,
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 604c2434f71..422084d18ce 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -76,6 +76,8 @@ enum
#define IFLA_WEIGHT IFLA_WEIGHT
IFLA_OPERSTATE,
IFLA_LINKMODE,
+ IFLA_LINKINFO,
+#define IFLA_LINKINFO IFLA_LINKINFO
__IFLA_MAX
};
@@ -140,4 +142,49 @@ struct ifla_cacheinfo
__u32 retrans_time;
};
+enum
+{
+ IFLA_INFO_UNSPEC,
+ IFLA_INFO_KIND,
+ IFLA_INFO_DATA,
+ IFLA_INFO_XSTATS,
+ __IFLA_INFO_MAX,
+};
+
+#define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1)
+
+/* VLAN section */
+
+enum
+{
+ IFLA_VLAN_UNSPEC,
+ IFLA_VLAN_ID,
+ IFLA_VLAN_FLAGS,
+ IFLA_VLAN_EGRESS_QOS,
+ IFLA_VLAN_INGRESS_QOS,
+ __IFLA_VLAN_MAX,
+};
+
+#define IFLA_VLAN_MAX (__IFLA_VLAN_MAX - 1)
+
+struct ifla_vlan_flags {
+ __u32 flags;
+ __u32 mask;
+};
+
+enum
+{
+ IFLA_VLAN_QOS_UNSPEC,
+ IFLA_VLAN_QOS_MAPPING,
+ __IFLA_VLAN_QOS_MAX
+};
+
+#define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1)
+
+struct ifla_vlan_qos_mapping
+{
+ __u32 from;
+ __u32 to;
+};
+
#endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
new file mode 100644
index 00000000000..0d9d7ea2c1c
--- /dev/null
+++ b/include/linux/if_macvlan.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_IF_MACVLAN_H
+#define _LINUX_IF_MACVLAN_H
+
+#ifdef __KERNEL__
+
+extern struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *);
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_IF_MACVLAN_H */
diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h
index 768372f07ca..0f2f70d4e48 100644
--- a/include/linux/if_ppp.h
+++ b/include/linux/if_ppp.h
@@ -110,6 +110,21 @@ struct ifpppcstatsreq {
struct ppp_comp_stats stats;
};
+/* For PPPIOCGL2TPSTATS */
+struct pppol2tp_ioc_stats {
+ __u16 tunnel_id; /* redundant */
+ __u16 session_id; /* if zero, get tunnel stats */
+ __u32 using_ipsec:1; /* valid only for session_id == 0 */
+ aligned_u64 tx_packets;
+ aligned_u64 tx_bytes;
+ aligned_u64 tx_errors;
+ aligned_u64 rx_packets;
+ aligned_u64 rx_bytes;
+ aligned_u64 rx_seq_discards;
+ aligned_u64 rx_oos_packets;
+ aligned_u64 rx_errors;
+};
+
#define ifr__name b.ifr_ifrn.ifrn_name
#define stats_ptr b.ifr_ifru.ifru_data
@@ -146,6 +161,7 @@ struct ifpppcstatsreq {
#define PPPIOCDISCONN _IO('t', 57) /* disconnect channel */
#define PPPIOCATTCHAN _IOW('t', 56, int) /* attach to ppp channel */
#define PPPIOCGCHAN _IOR('t', 55, int) /* get ppp channel number */
+#define PPPIOCGL2TPSTATS _IOR('t', 54, struct pppol2tp_ioc_stats)
#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0)
#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */
diff --git a/include/linux/if_pppol2tp.h b/include/linux/if_pppol2tp.h
new file mode 100644
index 00000000000..516203b6fde
--- /dev/null
+++ b/include/linux/if_pppol2tp.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Linux PPP over L2TP (PPPoL2TP) Socket Implementation (RFC 2661)
+ *
+ * This file supplies definitions required by the PPP over L2TP driver
+ * (pppol2tp.c). All version information wrt this file is located in pppol2tp.c
+ *
+ * License:
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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_IF_PPPOL2TP_H
+#define __LINUX_IF_PPPOL2TP_H
+
+#include <asm/types.h>
+
+#ifdef __KERNEL__
+#include <linux/in.h>
+#endif
+
+/* Structure used to connect() the socket to a particular tunnel UDP
+ * socket.
+ */
+struct pppol2tp_addr
+{
+ pid_t pid; /* pid that owns the fd.
+ * 0 => current */
+ int fd; /* FD of UDP socket to use */
+
+ struct sockaddr_in addr; /* IP address and port to send to */
+
+ __be16 s_tunnel, s_session; /* For matching incoming packets */
+ __be16 d_tunnel, d_session; /* For sending outgoing packets */
+};
+
+/* Socket options:
+ * DEBUG - bitmask of debug message categories
+ * SENDSEQ - 0 => don't send packets with sequence numbers
+ * 1 => send packets with sequence numbers
+ * RECVSEQ - 0 => receive packet sequence numbers are optional
+ * 1 => drop receive packets without sequence numbers
+ * LNSMODE - 0 => act as LAC.
+ * 1 => act as LNS.
+ * REORDERTO - reorder timeout (in millisecs). If 0, don't try to reorder.
+ */
+enum {
+ PPPOL2TP_SO_DEBUG = 1,
+ PPPOL2TP_SO_RECVSEQ = 2,
+ PPPOL2TP_SO_SENDSEQ = 3,
+ PPPOL2TP_SO_LNSMODE = 4,
+ PPPOL2TP_SO_REORDERTO = 5,
+};
+
+/* Debug message categories for the DEBUG socket option */
+enum {
+ PPPOL2TP_MSG_DEBUG = (1 << 0), /* verbose debug (if
+ * compiled in) */
+ PPPOL2TP_MSG_CONTROL = (1 << 1), /* userspace - kernel
+ * interface */
+ PPPOL2TP_MSG_SEQ = (1 << 2), /* sequence numbers */
+ PPPOL2TP_MSG_DATA = (1 << 3), /* data packets */
+};
+
+
+
+#endif
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 6f987be60fe..25652545ba6 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -27,6 +27,7 @@
#include <asm/semaphore.h>
#include <linux/ppp_channel.h>
#endif /* __KERNEL__ */
+#include <linux/if_pppol2tp.h>
/* For user-space programs to pick up these definitions
* which they wouldn't get otherwise without defining __KERNEL__
@@ -50,8 +51,9 @@ struct pppoe_addr{
* Protocols supported by AF_PPPOX
*/
#define PX_PROTO_OE 0 /* Currently just PPPoE */
-#define PX_MAX_PROTO 1
-
+#define PX_PROTO_OL2TP 1 /* Now L2TP also */
+#define PX_MAX_PROTO 2
+
struct sockaddr_pppox {
sa_family_t sa_family; /* address family, AF_PPPOX */
unsigned int sa_protocol; /* protocol identifier */
@@ -60,6 +62,16 @@ struct sockaddr_pppox {
}sa_addr;
}__attribute__ ((packed));
+/* The use of the above union isn't viable because the size of this
+ * struct must stay fixed over time -- applications use sizeof(struct
+ * sockaddr_pppox) to fill it. We use a protocol specific sockaddr
+ * type instead.
+ */
+struct sockaddr_pppol2tp {
+ sa_family_t sa_family; /* address family, AF_PPPOX */
+ unsigned int sa_protocol; /* protocol identifier */
+ struct pppol2tp_addr pppol2tp;
+}__attribute__ ((packed));
/*********************************************************************
*
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 88aef7b86ef..42eb6945b93 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -36,6 +36,7 @@ struct tun_struct {
unsigned long flags;
int attached;
uid_t owner;
+ gid_t group;
wait_queue_head_t read_wait;
struct sk_buff_head readq;
@@ -78,6 +79,7 @@ struct tun_struct {
#define TUNSETPERSIST _IOW('T', 203, int)
#define TUNSETOWNER _IOW('T', 204, int)
#define TUNSETLINK _IOW('T', 205, int)
+#define TUNSETGROUP _IOW('T', 206, int)
/* TUNSETIFF ifr flags */
#define IFF_TUN 0x0001
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 81e9bc93569..f8443fdb124 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -99,7 +99,7 @@ static inline void vlan_group_set_device(struct vlan_group *vg, int vlan_id,
}
struct vlan_priority_tci_mapping {
- unsigned long priority;
+ u32 priority;
unsigned short vlan_qos; /* This should be shifted when first set, so we only do it
* at provisioning time.
* ((skb->priority << 13) & 0xE000)
@@ -112,7 +112,10 @@ struct vlan_dev_info {
/** This will be the mapping that correlates skb->priority to
* 3 bits of VLAN QOS tags...
*/
- unsigned long ingress_priority_map[8];
+ unsigned int nr_ingress_mappings;
+ u32 ingress_priority_map[8];
+
+ unsigned int nr_egress_mappings;
struct vlan_priority_tci_mapping *egress_priority_map[16]; /* hash table */
unsigned short vlan_id; /* The VLAN Identifier for this interface. */
@@ -124,14 +127,8 @@ struct vlan_dev_info {
* like DHCP that use packet-filtering and don't understand
* 802.1Q
*/
- struct dev_mc_list *old_mc_list; /* old multi-cast list for the VLAN interface..
- * we save this so we can tell what changes were
- * made, in order to feed the right changes down
- * to the real hardware...
- */
- int old_allmulti; /* similar to above. */
- int old_promiscuity; /* similar to above. */
struct net_device *real_dev; /* the underlying device/interface */
+ unsigned char real_dev_addr[ETH_ALEN];
struct proc_dir_entry *dent; /* Holds the proc data */
unsigned long cnt_inc_headroom_on_tx; /* How many times did we have to grow the skb on TX. */
unsigned long cnt_encap_on_xmit; /* How many times did we have to encapsulate the skb on TX. */
@@ -395,6 +392,10 @@ enum vlan_ioctl_cmds {
GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
};
+enum vlan_flags {
+ VLAN_FLAG_REORDER_HDR = 0x1,
+};
+
enum vlan_name_types {
VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */
VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index c0f7aec331c..d83fee2dc64 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -3,35 +3,18 @@
#ifdef __KERNEL__
+#include <linux/bitmap.h>
#include <linux/if.h>
#include <linux/netdevice.h>
#include <linux/rcupdate.h>
#include <linux/timer.h>
+#include <linux/sysctl.h>
struct ipv4_devconf
{
- int accept_redirects;
- int send_redirects;
- int secure_redirects;
- int shared_media;
- int accept_source_route;
- int rp_filter;
- int proxy_arp;
- int bootp_relay;
- int log_martians;
- int forwarding;
- int mc_forwarding;
- int tag;
- int arp_filter;
- int arp_announce;
- int arp_ignore;
- int arp_accept;
- int medium_id;
- int no_xfrm;
- int no_policy;
- int force_igmp_version;
- int promote_secondaries;
void *sysctl;
+ int data[__NET_IPV4_CONF_MAX - 1];
+ DECLARE_BITMAP(state, __NET_IPV4_CONF_MAX - 1);
};
extern struct ipv4_devconf ipv4_devconf;
@@ -60,30 +43,70 @@ struct in_device
struct rcu_head rcu_head;
};
-#define IN_DEV_FORWARD(in_dev) ((in_dev)->cnf.forwarding)
-#define IN_DEV_MFORWARD(in_dev) (ipv4_devconf.mc_forwarding && (in_dev)->cnf.mc_forwarding)
-#define IN_DEV_RPFILTER(in_dev) (ipv4_devconf.rp_filter && (in_dev)->cnf.rp_filter)
-#define IN_DEV_SOURCE_ROUTE(in_dev) (ipv4_devconf.accept_source_route && (in_dev)->cnf.accept_source_route)
-#define IN_DEV_BOOTP_RELAY(in_dev) (ipv4_devconf.bootp_relay && (in_dev)->cnf.bootp_relay)
-
-#define IN_DEV_LOG_MARTIANS(in_dev) (ipv4_devconf.log_martians || (in_dev)->cnf.log_martians)
-#define IN_DEV_PROXY_ARP(in_dev) (ipv4_devconf.proxy_arp || (in_dev)->cnf.proxy_arp)
-#define IN_DEV_SHARED_MEDIA(in_dev) (ipv4_devconf.shared_media || (in_dev)->cnf.shared_media)
-#define IN_DEV_TX_REDIRECTS(in_dev) (ipv4_devconf.send_redirects || (in_dev)->cnf.send_redirects)
-#define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
-#define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag)
-#define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id)
-#define IN_DEV_PROMOTE_SECONDARIES(in_dev) (ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries)
+#define IPV4_DEVCONF(cnf, attr) ((cnf).data[NET_IPV4_CONF_ ## attr - 1])
+#define IPV4_DEVCONF_ALL(attr) IPV4_DEVCONF(ipv4_devconf, attr)
+
+static inline int ipv4_devconf_get(struct in_device *in_dev, int index)
+{
+ index--;
+ return in_dev->cnf.data[index];
+}
+
+static inline void ipv4_devconf_set(struct in_device *in_dev, int index,
+ int val)
+{
+ index--;
+ set_bit(index, in_dev->cnf.state);
+ in_dev->cnf.data[index] = val;
+}
+
+static inline void ipv4_devconf_setall(struct in_device *in_dev)
+{
+ bitmap_fill(in_dev->cnf.state, __NET_IPV4_CONF_MAX - 1);
+}
+
+#define IN_DEV_CONF_GET(in_dev, attr) \
+ ipv4_devconf_get((in_dev), NET_IPV4_CONF_ ## attr)
+#define IN_DEV_CONF_SET(in_dev, attr, val) \
+ ipv4_devconf_set((in_dev), NET_IPV4_CONF_ ## attr, (val))
+
+#define IN_DEV_ANDCONF(in_dev, attr) \
+ (IPV4_DEVCONF_ALL(attr) && IN_DEV_CONF_GET((in_dev), attr))
+#define IN_DEV_ORCONF(in_dev, attr) \
+ (IPV4_DEVCONF_ALL(attr) || IN_DEV_CONF_GET((in_dev), attr))
+#define IN_DEV_MAXCONF(in_dev, attr) \
+ (max(IPV4_DEVCONF_ALL(attr), IN_DEV_CONF_GET((in_dev), attr)))
+
+#define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING)
+#define IN_DEV_MFORWARD(in_dev) (IPV4_DEVCONF_ALL(MC_FORWARDING) && \
+ IPV4_DEVCONF((in_dev)->cnf, \
+ MC_FORWARDING))
+#define IN_DEV_RPFILTER(in_dev) IN_DEV_ANDCONF((in_dev), RP_FILTER)
+#define IN_DEV_SOURCE_ROUTE(in_dev) IN_DEV_ANDCONF((in_dev), \
+ ACCEPT_SOURCE_ROUTE)
+#define IN_DEV_BOOTP_RELAY(in_dev) IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
+
+#define IN_DEV_LOG_MARTIANS(in_dev) IN_DEV_ORCONF((in_dev), LOG_MARTIANS)
+#define IN_DEV_PROXY_ARP(in_dev) IN_DEV_ORCONF((in_dev), PROXY_ARP)
+#define IN_DEV_SHARED_MEDIA(in_dev) IN_DEV_ORCONF((in_dev), SHARED_MEDIA)
+#define IN_DEV_TX_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), SEND_REDIRECTS)
+#define IN_DEV_SEC_REDIRECTS(in_dev) IN_DEV_ORCONF((in_dev), \
+ SECURE_REDIRECTS)
+#define IN_DEV_IDTAG(in_dev) IN_DEV_CONF_GET(in_dev, TAG)
+#define IN_DEV_MEDIUM_ID(in_dev) IN_DEV_CONF_GET(in_dev, MEDIUM_ID)
+#define IN_DEV_PROMOTE_SECONDARIES(in_dev) \
+ IN_DEV_ORCONF((in_dev), \
+ PROMOTE_SECONDARIES)
#define IN_DEV_RX_REDIRECTS(in_dev) \
((IN_DEV_FORWARD(in_dev) && \
- (ipv4_devconf.accept_redirects && (in_dev)->cnf.accept_redirects)) \
+ IN_DEV_ANDCONF((in_dev), ACCEPT_REDIRECTS)) \
|| (!IN_DEV_FORWARD(in_dev) && \
- (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
+ IN_DEV_ORCONF((in_dev), ACCEPT_REDIRECTS)))
-#define IN_DEV_ARPFILTER(in_dev) (ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
-#define IN_DEV_ARP_ANNOUNCE(in_dev) (max(ipv4_devconf.arp_announce, (in_dev)->cnf.arp_announce))
-#define IN_DEV_ARP_IGNORE(in_dev) (max(ipv4_devconf.arp_ignore, (in_dev)->cnf.arp_ignore))
+#define IN_DEV_ARPFILTER(in_dev) IN_DEV_ORCONF((in_dev), ARPFILTER)
+#define IN_DEV_ARP_ANNOUNCE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
+#define IN_DEV_ARP_IGNORE(in_dev) IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
struct in_ifaddr
{
@@ -108,7 +131,6 @@ extern struct net_device *ip_dev_find(__be32 addr);
extern int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b);
extern int devinet_ioctl(unsigned int cmd, void __user *);
extern void devinet_init(void);
-extern struct in_device *inetdev_init(struct net_device *dev);
extern struct in_device *inetdev_by_index(int);
extern __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope);
extern __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope);
diff --git a/include/linux/input.h b/include/linux/input.h
index be2bf3a2b03..18c98b54303 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -108,6 +108,13 @@ struct input_absinfo {
/*
* Keys and buttons
+ *
+ * Most of the keys/buttons are modeled after USB HUT 1.12
+ * (see http://www.usb.org/developers/hidpage).
+ * Abbreviations in the comments:
+ * AC - Application Control
+ * AL - Application Launch Button
+ * SC - System Control
*/
#define KEY_RESERVED 0
@@ -226,7 +233,7 @@ struct input_absinfo {
#define KEY_MUTE 113
#define KEY_VOLUMEDOWN 114
#define KEY_VOLUMEUP 115
-#define KEY_POWER 116
+#define KEY_POWER 116 /* SC System Power Down */
#define KEY_KPEQUAL 117
#define KEY_KPPLUSMINUS 118
#define KEY_PAUSE 119
@@ -240,38 +247,39 @@ struct input_absinfo {
#define KEY_RIGHTMETA 126
#define KEY_COMPOSE 127
-#define KEY_STOP 128
+#define KEY_STOP 128 /* AC Stop */
#define KEY_AGAIN 129
-#define KEY_PROPS 130
-#define KEY_UNDO 131
+#define KEY_PROPS 130 /* AC Properties */
+#define KEY_UNDO 131 /* AC Undo */
#define KEY_FRONT 132
-#define KEY_COPY 133
-#define KEY_OPEN 134
-#define KEY_PASTE 135
-#define KEY_FIND 136
-#define KEY_CUT 137
-#define KEY_HELP 138
-#define KEY_MENU 139
-#define KEY_CALC 140
+#define KEY_COPY 133 /* AC Copy */
+#define KEY_OPEN 134 /* AC Open */
+#define KEY_PASTE 135 /* AC Paste */
+#define KEY_FIND 136 /* AC Search */
+#define KEY_CUT 137 /* AC Cut */
+#define KEY_HELP 138 /* AL Integrated Help Center */
+#define KEY_MENU 139 /* Menu (show menu) */
+#define KEY_CALC 140 /* AL Calculator */
#define KEY_SETUP 141
-#define KEY_SLEEP 142
-#define KEY_WAKEUP 143
-#define KEY_FILE 144
+#define KEY_SLEEP 142 /* SC System Sleep */
+#define KEY_WAKEUP 143 /* System Wake Up */
+#define KEY_FILE 144 /* AL Local Machine Browser */
#define KEY_SENDFILE 145
#define KEY_DELETEFILE 146
#define KEY_XFER 147
#define KEY_PROG1 148
#define KEY_PROG2 149
-#define KEY_WWW 150
+#define KEY_WWW 150 /* AL Internet Browser */
#define KEY_MSDOS 151
-#define KEY_COFFEE 152
+#define KEY_COFFEE 152 /* AL Terminal Lock/Screensaver */
+#define KEY_SCREENLOCK KEY_COFFEE
#define KEY_DIRECTION 153
#define KEY_CYCLEWINDOWS 154
#define KEY_MAIL 155
-#define KEY_BOOKMARKS 156
+#define KEY_BOOKMARKS 156 /* AC Bookmarks */
#define KEY_COMPUTER 157
-#define KEY_BACK 158
-#define KEY_FORWARD 159
+#define KEY_BACK 158 /* AC Back */
+#define KEY_FORWARD 159 /* AC Forward */
#define KEY_CLOSECD 160
#define KEY_EJECTCD 161
#define KEY_EJECTCLOSECD 162
@@ -281,20 +289,20 @@ struct input_absinfo {
#define KEY_STOPCD 166
#define KEY_RECORD 167
#define KEY_REWIND 168
-#define KEY_PHONE 169
+#define KEY_PHONE 169 /* Media Select Telephone */
#define KEY_ISO 170
-#define KEY_CONFIG 171
-#define KEY_HOMEPAGE 172
-#define KEY_REFRESH 173
-#define KEY_EXIT 174
+#define KEY_CONFIG 171 /* AL Consumer Control Configuration */
+#define KEY_HOMEPAGE 172 /* AC Home */
+#define KEY_REFRESH 173 /* AC Refresh */
+#define KEY_EXIT 174 /* AC Exit */
#define KEY_MOVE 175
#define KEY_EDIT 176
#define KEY_SCROLLUP 177
#define KEY_SCROLLDOWN 178
#define KEY_KPLEFTPAREN 179
#define KEY_KPRIGHTPAREN 180
-#define KEY_NEW 181
-#define KEY_REDO 182
+#define KEY_NEW 181 /* AC New */
+#define KEY_REDO 182 /* AC Redo/Repeat */
#define KEY_F13 183
#define KEY_F14 184
@@ -314,11 +322,11 @@ struct input_absinfo {
#define KEY_PROG3 202
#define KEY_PROG4 203
#define KEY_SUSPEND 205
-#define KEY_CLOSE 206
+#define KEY_CLOSE 206 /* AC Close */
#define KEY_PLAY 207
#define KEY_FASTFORWARD 208
#define KEY_BASSBOOST 209
-#define KEY_PRINT 210
+#define KEY_PRINT 210 /* AC Print */
#define KEY_HP 211
#define KEY_CAMERA 212
#define KEY_SOUND 213
@@ -327,11 +335,11 @@ struct input_absinfo {
#define KEY_CHAT 216
#define KEY_SEARCH 217
#define KEY_CONNECT 218
-#define KEY_FINANCE 219
+#define KEY_FINANCE 219 /* AL Checkbook/Finance */
#define KEY_SPORT 220
#define KEY_SHOP 221
#define KEY_ALTERASE 222
-#define KEY_CANCEL 223
+#define KEY_CANCEL 223 /* AC Cancel */
#define KEY_BRIGHTNESSDOWN 224
#define KEY_BRIGHTNESSUP 225
#define KEY_MEDIA 226
@@ -341,10 +349,10 @@ struct input_absinfo {
#define KEY_KBDILLUMDOWN 229
#define KEY_KBDILLUMUP 230
-#define KEY_SEND 231
-#define KEY_REPLY 232
-#define KEY_FORWARDMAIL 233
-#define KEY_SAVE 234
+#define KEY_SEND 231 /* AC Send */
+#define KEY_REPLY 232 /* AC Reply */
+#define KEY_FORWARDMAIL 233 /* AC Forward Msg */
+#define KEY_SAVE 234 /* AC Save */
#define KEY_DOCUMENTS 235
#define KEY_BATTERY 236
@@ -433,15 +441,15 @@ struct input_absinfo {
#define KEY_CLEAR 0x163
#define KEY_POWER2 0x164
#define KEY_OPTION 0x165
-#define KEY_INFO 0x166
+#define KEY_INFO 0x166 /* AL OEM Features/Tips/Tutorial */
#define KEY_TIME 0x167
#define KEY_VENDOR 0x168
#define KEY_ARCHIVE 0x169
-#define KEY_PROGRAM 0x16a
+#define KEY_PROGRAM 0x16a /* Media Select Program Guide */
#define KEY_CHANNEL 0x16b
#define KEY_FAVORITES 0x16c
#define KEY_EPG 0x16d
-#define KEY_PVR 0x16e
+#define KEY_PVR 0x16e /* Media Select Home */
#define KEY_MHP 0x16f
#define KEY_LANGUAGE 0x170
#define KEY_TITLE 0x171
@@ -451,36 +459,36 @@ struct input_absinfo {
#define KEY_MODE 0x175
#define KEY_KEYBOARD 0x176
#define KEY_SCREEN 0x177
-#define KEY_PC 0x178
-#define KEY_TV 0x179
-#define KEY_TV2 0x17a
-#define KEY_VCR 0x17b
-#define KEY_VCR2 0x17c
-#define KEY_SAT 0x17d
+#define KEY_PC 0x178 /* Media Select Computer */
+#define KEY_TV 0x179 /* Media Select TV */
+#define KEY_TV2 0x17a /* Media Select Cable */
+#define KEY_VCR 0x17b /* Media Select VCR */
+#define KEY_VCR2 0x17c /* VCR Plus */
+#define KEY_SAT 0x17d /* Media Select Satellite */
#define KEY_SAT2 0x17e
-#define KEY_CD 0x17f
-#define KEY_TAPE 0x180
+#define KEY_CD 0x17f /* Media Select CD */
+#define KEY_TAPE 0x180 /* Media Select Tape */
#define KEY_RADIO 0x181
-#define KEY_TUNER 0x182
+#define KEY_TUNER 0x182 /* Media Select Tuner */
#define KEY_PLAYER 0x183
#define KEY_TEXT 0x184
-#define KEY_DVD 0x185
+#define KEY_DVD 0x185 /* Media Select DVD */
#define KEY_AUX 0x186
#define KEY_MP3 0x187
#define KEY_AUDIO 0x188
#define KEY_VIDEO 0x189
#define KEY_DIRECTORY 0x18a
#define KEY_LIST 0x18b
-#define KEY_MEMO 0x18c
+#define KEY_MEMO 0x18c /* Media Select Messages */
#define KEY_CALENDAR 0x18d
#define KEY_RED 0x18e
#define KEY_GREEN 0x18f
#define KEY_YELLOW 0x190
#define KEY_BLUE 0x191
-#define KEY_CHANNELUP 0x192
-#define KEY_CHANNELDOWN 0x193
+#define KEY_CHANNELUP 0x192 /* Channel Increment */
+#define KEY_CHANNELDOWN 0x193 /* Channel Decrement */
#define KEY_FIRST 0x194
-#define KEY_LAST 0x195
+#define KEY_LAST 0x195 /* Recall Last */
#define KEY_AB 0x196
#define KEY_NEXT 0x197
#define KEY_RESTART 0x198
@@ -491,21 +499,21 @@ struct input_absinfo {
#define KEY_DIGITS 0x19d
#define KEY_TEEN 0x19e
#define KEY_TWEN 0x19f
-#define KEY_VIDEOPHONE 0x1a0
-#define KEY_GAMES 0x1a1
-#define KEY_ZOOMIN 0x1a2
-#define KEY_ZOOMOUT 0x1a3
-#define KEY_ZOOMRESET 0x1a4
-#define KEY_WORDPROCESSOR 0x1a5
-#define KEY_EDITOR 0x1a6
-#define KEY_SPREADSHEET 0x1a7
-#define KEY_GRAPHICSEDITOR 0x1a8
-#define KEY_PRESENTATION 0x1a9
-#define KEY_DATABASE 0x1aa
-#define KEY_NEWS 0x1ab
-#define KEY_VOICEMAIL 0x1ac
-#define KEY_ADDRESSBOOK 0x1ad
-#define KEY_MESSENGER 0x1ae
+#define KEY_VIDEOPHONE 0x1a0 /* Media Select Video Phone */
+#define KEY_GAMES 0x1a1 /* Media Select Games */
+#define KEY_ZOOMIN 0x1a2 /* AC Zoom In */
+#define KEY_ZOOMOUT 0x1a3 /* AC Zoom Out */
+#define KEY_ZOOMRESET 0x1a4 /* AC Zoom */
+#define KEY_WORDPROCESSOR 0x1a5 /* AL Word Processor */
+#define KEY_EDITOR 0x1a6 /* AL Text Editor */
+#define KEY_SPREADSHEET 0x1a7 /* AL Spreadsheet */
+#define KEY_GRAPHICSEDITOR 0x1a8 /* AL Graphics Editor */
+#define KEY_PRESENTATION 0x1a9 /* AL Presentation App */
+#define KEY_DATABASE 0x1aa /* AL Database App */
+#define KEY_NEWS 0x1ab /* AL Newsreader */
+#define KEY_VOICEMAIL 0x1ac /* AL Voicemail */
+#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */
+#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */
#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */
#define KEY_DEL_EOL 0x1c0
@@ -603,6 +611,7 @@ struct input_absinfo {
#define SW_LID 0x00 /* set = lid shut */
#define SW_TABLET_MODE 0x01 /* set = tablet mode */
#define SW_HEADPHONE_INSERT 0x02 /* set = inserted */
+#define SW_RADIO 0x03 /* set = radio enabled */
#define SW_MAX 0x0f
/*
@@ -972,15 +981,15 @@ struct input_dev {
struct mutex mutex; /* serializes open and close operations */
unsigned int users;
- struct class_device cdev;
+ struct device dev;
union { /* temporarily so while we switching to struct device */
- struct device *parent;
- } dev;
+ struct device *dev;
+ } cdev;
struct list_head h_list;
struct list_head node;
};
-#define to_input_dev(d) container_of(d, struct input_dev, cdev)
+#define to_input_dev(d) container_of(d, struct input_dev, dev)
/*
* Verify that we are in sync with input_device_id mod_devicetable.h #defines
@@ -1087,22 +1096,22 @@ struct input_handle {
struct list_head h_node;
};
-#define to_dev(n) container_of(n,struct input_dev,node)
-#define to_handler(n) container_of(n,struct input_handler,node)
-#define to_handle(n) container_of(n,struct input_handle,d_node)
-#define to_handle_h(n) container_of(n,struct input_handle,h_node)
+#define to_dev(n) container_of(n, struct input_dev, node)
+#define to_handler(n) container_of(n, struct input_handler, node)
+#define to_handle(n) container_of(n, struct input_handle, d_node)
+#define to_handle_h(n) container_of(n, struct input_handle, h_node)
struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev);
static inline struct input_dev *input_get_device(struct input_dev *dev)
{
- return to_input_dev(class_device_get(&dev->cdev));
+ return to_input_dev(get_device(&dev->dev));
}
static inline void input_put_device(struct input_dev *dev)
{
- class_device_put(&dev->cdev);
+ put_device(&dev->dev);
}
static inline void *input_get_drvdata(struct input_dev *dev)
diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h
index 8e2042b9d47..2eaa142cd06 100644
--- a/include/linux/ioprio.h
+++ b/include/linux/ioprio.h
@@ -47,8 +47,10 @@ enum {
#define IOPRIO_NORM (4)
static inline int task_ioprio(struct task_struct *task)
{
- WARN_ON(!ioprio_valid(task->ioprio));
- return IOPRIO_PRIO_DATA(task->ioprio);
+ if (ioprio_valid(task->ioprio))
+ return IOPRIO_PRIO_DATA(task->ioprio);
+
+ return IOPRIO_NORM;
}
static inline int task_nice_ioprio(struct task_struct *task)
diff --git a/include/linux/ip_mp_alg.h b/include/linux/ip_mp_alg.h
deleted file mode 100644
index e234e2008f5..00000000000
--- a/include/linux/ip_mp_alg.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* ip_mp_alg.h: IPV4 multipath algorithm support, user-visible values.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#ifndef _LINUX_IP_MP_ALG_H
-#define _LINUX_IP_MP_ALG_H
-
-enum ip_mp_alg {
- IP_MP_ALG_NONE,
- IP_MP_ALG_RR,
- IP_MP_ALG_DRR,
- IP_MP_ALG_RANDOM,
- IP_MP_ALG_WRANDOM,
- __IP_MP_ALG_MAX
-};
-
-#define IP_MP_ALG_MAX (__IP_MP_ALG_MAX - 1)
-
-#endif /* _LINUX_IP_MP_ALG_H */
-
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 09ea01a8a99..97983dc9df1 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -27,8 +27,8 @@ struct in6_ifreq {
int ifr6_ifindex;
};
-#define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */
-#define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */
+#define IPV6_SRCRT_STRICT 0x01 /* Deprecated; will be removed */
+#define IPV6_SRCRT_TYPE_0 0 /* Deprecated; will be removed */
#define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */
/*
@@ -209,9 +209,8 @@ enum {
DEVCONF_RTR_PROBE_INTERVAL,
DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN,
DEVCONF_PROXY_NDP,
- __DEVCONF_OPTIMISTIC_DAD,
- DEVCONF_ACCEPT_SOURCE_ROUTE,
DEVCONF_OPTIMISTIC_DAD,
+ DEVCONF_ACCEPT_SOURCE_ROUTE,
DEVCONF_MAX
};
@@ -248,7 +247,7 @@ struct inet6_skb_parm {
__u16 lastopt;
__u32 nhoff;
__u16 flags;
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
__u16 dsthao;
#endif
@@ -300,8 +299,8 @@ struct ipv6_pinfo {
/* pktoption flags */
union {
struct {
- __u16 srcrt:2,
- osrcrt:2,
+ __u16 srcrt:1,
+ osrcrt:1,
rxinfo:1,
rxoinfo:1,
rxhlim:1,
diff --git a/include/linux/irda.h b/include/linux/irda.h
index 945ba311087..8e3735714c1 100644
--- a/include/linux/irda.h
+++ b/include/linux/irda.h
@@ -216,6 +216,34 @@ struct if_irda_req {
#define ifr_dtr ifr_ifru.ifru_line.dtr
#define ifr_rts ifr_ifru.ifru_line.rts
+
+/* IrDA netlink definitions */
+#define IRDA_NL_NAME "irda"
+#define IRDA_NL_VERSION 1
+
+enum irda_nl_commands {
+ IRDA_NL_CMD_UNSPEC,
+ IRDA_NL_CMD_SET_MODE,
+ IRDA_NL_CMD_GET_MODE,
+
+ __IRDA_NL_CMD_AFTER_LAST
+};
+#define IRDA_NL_CMD_MAX (__IRDA_NL_CMD_AFTER_LAST - 1)
+
+enum nl80211_attrs {
+ IRDA_NL_ATTR_UNSPEC,
+ IRDA_NL_ATTR_IFNAME,
+ IRDA_NL_ATTR_MODE,
+
+ __IRDA_NL_ATTR_AFTER_LAST
+};
+#define IRDA_NL_ATTR_MAX (__IRDA_NL_ATTR_AFTER_LAST - 1)
+
+/* IrDA modes */
+#define IRDA_MODE_PRIMARY 0x1
+#define IRDA_MODE_SECONDARY 0x2
+#define IRDA_MODE_MONITOR 0x4
+
#endif /* KERNEL_IRDA_H */
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 12178d2c882..5f06527dca2 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -5,6 +5,7 @@
#ifndef _LINUX_KALLSYMS_H
#define _LINUX_KALLSYMS_H
+#include <linux/errno.h>
#define KSYM_NAME_LEN 127
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN + \
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 45353d757cd..7a485250591 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -218,10 +218,14 @@ enum {
DUMP_PREFIX_ADDRESS,
DUMP_PREFIX_OFFSET
};
-extern void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
- size_t linebuflen);
-extern void print_hex_dump(const char *level, int prefix_type,
- void *buf, size_t len);
+extern void hex_dump_to_buffer(const void *buf, size_t len,
+ int rowsize, int groupsize,
+ char *linebuf, size_t linebuflen, bool ascii);
+extern void print_hex_dump(const char *level, const char *prefix_str,
+ int prefix_type, int rowsize, int groupsize,
+ void *buf, size_t len, bool ascii);
+extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ void *buf, size_t len);
#define hex_asc(x) "0123456789abcdef"[x]
#ifdef DEBUG
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index c288e41ba33..06cbf41d32d 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -55,7 +55,7 @@ struct kobject {
struct kobject * parent;
struct kset * kset;
struct kobj_type * ktype;
- struct dentry * dentry;
+ struct sysfs_dirent * sd;
wait_queue_head_t poll;
};
@@ -71,13 +71,14 @@ extern void kobject_init(struct kobject *);
extern void kobject_cleanup(struct kobject *);
extern int __must_check kobject_add(struct kobject *);
-extern int __must_check kobject_shadow_add(struct kobject *, struct dentry *);
+extern int __must_check kobject_shadow_add(struct kobject *kobj,
+ struct sysfs_dirent *shadow_parent);
extern void kobject_del(struct kobject *);
extern int __must_check kobject_rename(struct kobject *, const char *new_name);
extern int __must_check kobject_shadow_rename(struct kobject *kobj,
- struct dentry *new_parent,
- const char *new_name);
+ struct sysfs_dirent *new_parent,
+ const char *new_name);
extern int __must_check kobject_move(struct kobject *, struct kobject *);
extern int __must_check kobject_register(struct kobject *);
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index c762954bda1..dae7143644f 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -261,12 +261,34 @@ static inline s64 ktime_to_ns(const ktime_t kt)
#endif
+/**
+ * ktime_equal - Compares two ktime_t variables to see if they are equal
+ * @cmp1: comparable1
+ * @cmp2: comparable2
+ *
+ * Compare two ktime_t variables, returns 1 if equal
+ */
+static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
+{
+ return cmp1.tv64 == cmp2.tv64;
+}
+
static inline s64 ktime_to_us(const ktime_t kt)
{
struct timeval tv = ktime_to_timeval(kt);
return (s64) tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
}
+static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier)
+{
+ return ktime_to_us(ktime_sub(later, earlier));
+}
+
+static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec)
+{
+ return ktime_add_ns(kt, usec * 1000);
+}
+
/*
* The resolution of the clocks. The resolution value is returned in
* the clock_getres() system call to give application programmers an
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 85f7b1bd148..47cd2a1c554 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -116,6 +116,7 @@ static inline struct device *pci_dev_to_dev(struct pci_dev *pdev)
enum {
/* various global constants */
LIBATA_MAX_PRD = ATA_MAX_PRD / 2,
+ LIBATA_DUMB_MAX_PRD = ATA_MAX_PRD / 4, /* Worst case */
ATA_MAX_PORTS = 8,
ATA_DEF_QUEUE = 1,
/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
@@ -136,6 +137,8 @@ enum {
ATA_DFLAG_CDB_INTR = (1 << 2), /* device asserts INTRQ when ready for CDB */
ATA_DFLAG_NCQ = (1 << 3), /* device supports NCQ */
ATA_DFLAG_FLUSH_EXT = (1 << 4), /* do FLUSH_EXT instead of FLUSH */
+ ATA_DFLAG_ACPI_PENDING = (1 << 5), /* ACPI resume action pending */
+ ATA_DFLAG_ACPI_FAILED = (1 << 6), /* ACPI on devcfg has failed */
ATA_DFLAG_CFG_MASK = (1 << 8) - 1,
ATA_DFLAG_PIO = (1 << 8), /* device limited to PIO mode */
@@ -171,7 +174,6 @@ enum {
ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H
* Register FIS clearing BSY */
ATA_FLAG_DEBUGMSG = (1 << 13),
- ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */
ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
@@ -194,9 +196,9 @@ enum {
ATA_PFLAG_SCSI_HOTPLUG = (1 << 6), /* SCSI hotplug scheduled */
ATA_PFLAG_INITIALIZING = (1 << 7), /* being initialized, don't touch */
- ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */
ATA_PFLAG_SUSPENDED = (1 << 17), /* port is suspended (power) */
ATA_PFLAG_PM_PENDING = (1 << 18), /* PM operation pending */
+ ATA_PFLAG_GTM_VALID = (1 << 19), /* acpi_gtm data valid */
/* struct ata_queued_cmd flags */
ATA_QCFLAG_ACTIVE = (1 << 0), /* cmd not yet ack'd to scsi lyer */
@@ -299,7 +301,6 @@ enum {
ATA_HORKAGE_NODMA = (1 << 1), /* DMA problems */
ATA_HORKAGE_NONCQ = (1 << 2), /* Don't use NCQ */
ATA_HORKAGE_MAX_SEC_128 = (1 << 3), /* Limit max sects to 128 */
- ATA_HORKAGE_DMA_RW_ONLY = (1 << 4), /* ATAPI DMA for RW only */
};
enum hsm_task_states {
@@ -365,6 +366,9 @@ struct ata_host {
void *private_data;
const struct ata_port_operations *ops;
unsigned long flags;
+#ifdef CONFIG_ATA_ACPI
+ acpi_handle acpi_handle;
+#endif
struct ata_port *simplex_claimed; /* channel owning the DMA */
struct ata_port *ports[0];
};
@@ -430,7 +434,11 @@ struct ata_device {
struct ata_port *ap;
unsigned int devno; /* 0 or 1 */
unsigned long flags; /* ATA_DFLAG_xxx */
+ unsigned int horkage; /* List of broken features */
struct scsi_device *sdev; /* attached SCSI device */
+#ifdef CONFIG_ATA_ACPI
+ acpi_handle acpi_handle;
+#endif
/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
u64 n_sectors; /* size of device, if ATA */
unsigned int class; /* ATA_DEV_xxx */
@@ -458,11 +466,6 @@ struct ata_device {
/* error history */
struct ata_ering ering;
int spdn_cnt;
- unsigned int horkage; /* List of broken features */
-#ifdef CONFIG_ATA_ACPI
- /* ACPI objects info */
- acpi_handle obj_handle;
-#endif
};
/* Offset into struct ata_device. Fields above it are maintained
@@ -491,6 +494,17 @@ struct ata_eh_context {
unsigned int did_probe_mask;
};
+struct ata_acpi_drive
+{
+ u32 pio;
+ u32 dma;
+} __packed;
+
+struct ata_acpi_gtm {
+ struct ata_acpi_drive drive[2];
+ u32 flags;
+} __packed;
+
struct ata_port {
struct Scsi_Host *scsi_host; /* our co-allocated scsi host */
const struct ata_port_operations *ops;
@@ -551,6 +565,10 @@ struct ata_port {
void *private_data;
+#ifdef CONFIG_ATA_ACPI
+ acpi_handle acpi_handle;
+ struct ata_acpi_gtm acpi_gtm;
+#endif
u8 sector_buf[ATA_SECT_SIZE]; /* owned by EH */
};
@@ -754,11 +772,13 @@ extern u8 ata_check_status(struct ata_port *ap);
extern u8 ata_altstatus(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap);
+extern int ata_sff_port_start (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data);
extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data);
+extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -773,7 +793,6 @@ extern void ata_id_string(const u16 *id, unsigned char *s,
extern void ata_id_c_string(const u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len);
extern void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown);
-extern unsigned long ata_device_blacklisted(const struct ata_device *dev);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
@@ -850,11 +869,11 @@ struct pci_bits {
unsigned long val;
};
-extern int ata_pci_init_native_host(struct ata_host *host);
+extern int ata_pci_init_sff_host(struct ata_host *host);
extern int ata_pci_init_bmdma(struct ata_host *host);
-extern int ata_pci_prepare_native_host(struct pci_dev *pdev,
- const struct ata_port_info * const * ppi,
- struct ata_host **r_host);
+extern int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ const struct ata_port_info * const * ppi,
+ struct ata_host **r_host);
extern int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits);
extern unsigned long ata_pci_default_filter(struct ata_device *, unsigned long);
#endif /* CONFIG_PCI */
@@ -1088,11 +1107,9 @@ static inline u8 ata_wait_idle(struct ata_port *ap)
{
u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
- if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) {
- if (ata_msg_warn(ap))
- printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%p\n",
- status, ap->ioaddr.status_addr);
- }
+ if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ)))
+ DPRINTK("ATA: abnormal status 0x%X on port 0x%p\n",
+ status, ap->ioaddr.status_addr);
return status;
}
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 05707e2fcca..e2d1ce36b36 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -39,6 +39,7 @@
struct nlm_host {
struct hlist_node h_hash; /* doubly linked list */
struct sockaddr_in h_addr; /* peer address */
+ struct sockaddr_in h_saddr; /* our address (optional) */
struct rpc_clnt * h_rpcclnt; /* RPC client to talk to peer */
char * h_name; /* remote hostname */
u32 h_version; /* interface version */
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
new file mode 100644
index 00000000000..582d8b711a1
--- /dev/null
+++ b/include/linux/lzo.h
@@ -0,0 +1,44 @@
+#ifndef __LZO_H__
+#define __LZO_H__
+/*
+ * LZO Public Kernel Interface
+ * A mini subset of the LZO real-time data compression library
+ *
+ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *))
+#define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS
+
+#define lzo1x_worst_compress(x) (x + (x / 64) + 16 + 3)
+
+/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
+int lzo1x_1_compress(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len, void *wrkmem);
+
+/* safe decompression with overrun testing */
+int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
+ unsigned char *dst, size_t *dst_len);
+
+/*
+ * Return values (< 0 = Error)
+ */
+#define LZO_E_OK 0
+#define LZO_E_ERROR (-1)
+#define LZO_E_OUT_OF_MEMORY (-2)
+#define LZO_E_NOT_COMPRESSIBLE (-3)
+#define LZO_E_INPUT_OVERRUN (-4)
+#define LZO_E_OUTPUT_OVERRUN (-5)
+#define LZO_E_LOOKBEHIND_OVERRUN (-6)
+#define LZO_E_EOF_NOT_FOUND (-7)
+#define LZO_E_INPUT_NOT_CONSUMED (-8)
+#define LZO_E_NOT_YET_IMPLEMENTED (-9)
+
+#endif
diff --git a/include/linux/mlx4/cmd.h b/include/linux/mlx4/cmd.h
index 4fb552d12f7..7d1eaa97de1 100644
--- a/include/linux/mlx4/cmd.h
+++ b/include/linux/mlx4/cmd.h
@@ -54,6 +54,7 @@ enum {
MLX4_CMD_INIT_PORT = 0x9,
MLX4_CMD_CLOSE_PORT = 0xa,
MLX4_CMD_QUERY_HCA = 0xb,
+ MLX4_CMD_QUERY_PORT = 0x43,
MLX4_CMD_SET_PORT = 0xc,
MLX4_CMD_ACCESS_DDR = 0x2e,
MLX4_CMD_MAP_ICM = 0xffa,
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 8c5f8fd8684..cfb78fb2c04 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -41,6 +41,7 @@
enum {
MLX4_FLAG_MSI_X = 1 << 0,
+ MLX4_FLAG_OLD_PORT_CMDS = 1 << 1,
};
enum {
@@ -131,10 +132,10 @@ enum {
struct mlx4_caps {
u64 fw_ver;
int num_ports;
- int vl_cap;
- int mtu_cap;
- int gid_table_len;
- int pkey_table_len;
+ int vl_cap[MLX4_MAX_PORTS + 1];
+ int mtu_cap[MLX4_MAX_PORTS + 1];
+ int gid_table_len[MLX4_MAX_PORTS + 1];
+ int pkey_table_len[MLX4_MAX_PORTS + 1];
int local_ca_ack_delay;
int num_uars;
int bf_reg_size;
@@ -171,10 +172,11 @@ struct mlx4_caps {
int num_pds;
int reserved_pds;
int mtt_entry_sz;
+ u32 max_msg_sz;
u32 page_size_cap;
u32 flags;
u16 stat_rate_support;
- u8 port_width_cap;
+ u8 port_width_cap[MLX4_MAX_PORTS + 1];
};
struct mlx4_buf_list {
@@ -321,8 +323,9 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,
u64 db_rec, struct mlx4_srq *srq);
void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq);
int mlx4_srq_arm(struct mlx4_dev *dev, struct mlx4_srq *srq, int limit_watermark);
+int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_watermark);
-int mlx4_INIT_PORT(struct mlx4_dev *dev, struct mlx4_init_port_param *param, int port);
+int mlx4_INIT_PORT(struct mlx4_dev *dev, int port);
int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port);
int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]);
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h
index 9eeb61adf6a..3968b943259 100644
--- a/include/linux/mlx4/qp.h
+++ b/include/linux/mlx4/qp.h
@@ -269,6 +269,10 @@ struct mlx4_wqe_data_seg {
__be64 addr;
};
+enum {
+ MLX4_INLINE_ALIGN = 64,
+};
+
struct mlx4_wqe_inline_seg {
__be32 byte_count;
};
@@ -278,6 +282,9 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar,
int sqd_event, struct mlx4_qp *qp);
+int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp,
+ struct mlx4_qp_context *context);
+
static inline struct mlx4_qp *__mlx4_qp_lookup(struct mlx4_dev *dev, u32 qpn)
{
return radix_tree_lookup(&dev->qp_table_tree, qpn & (dev->caps.num_qps - 1));
diff --git a/include/linux/mm.h b/include/linux/mm.h
index e4183c6c7de..1c1207472bb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -603,6 +603,10 @@ static inline struct address_space *page_mapping(struct page *page)
if (unlikely(PageSwapCache(page)))
mapping = &swapper_space;
+#ifdef CONFIG_SLUB
+ else if (unlikely(PageSlab(page)))
+ mapping = NULL;
+#endif
else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
mapping = NULL;
return mapping;
diff --git a/include/linux/mtd/super.h b/include/linux/mtd/super.h
new file mode 100644
index 00000000000..4016dd6fe33
--- /dev/null
+++ b/include/linux/mtd/super.h
@@ -0,0 +1,30 @@
+/* MTD-based superblock handling
+ *
+ * Copyright © 2006 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 __MTD_SUPER_H__
+#define __MTD_SUPER_H__
+
+#ifdef __KERNEL__
+
+#include <linux/mtd/mtd.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+
+extern int get_sb_mtd(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data,
+ int (*fill_super)(struct super_block *, void *, int),
+ struct vfsmount *mnt);
+extern void kill_mtd_super(struct super_block *sb);
+
+
+#endif /* __KERNEL__ */
+
+#endif /* __MTD_SUPER_H__ */
diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h
index c6d4ab86b83..b021b3a2b65 100644
--- a/include/linux/mv643xx.h
+++ b/include/linux/mv643xx.h
@@ -13,10 +13,6 @@
#ifndef __ASM_MV643XX_H
#define __ASM_MV643XX_H
-#ifdef __mips__
-#include <asm/addrspace.h>
-#include <asm/marvell.h>
-#endif
#include <asm/types.h>
/****************************************/
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f671cd2f133..322b5eae57d 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -108,6 +108,14 @@ struct wireless_dev;
#define MAX_HEADER (LL_MAX_HEADER + 48)
#endif
+struct net_device_subqueue
+{
+ /* Give a control state for each queue. This struct may contain
+ * per-queue locks in the future.
+ */
+ unsigned long state;
+};
+
/*
* Network device statistics. Akin to the 2.0 ether stats but
* with byte counters.
@@ -177,19 +185,25 @@ struct netif_rx_stats
DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat);
+struct dev_addr_list
+{
+ struct dev_addr_list *next;
+ u8 da_addr[MAX_ADDR_LEN];
+ u8 da_addrlen;
+ u8 da_synced;
+ int da_users;
+ int da_gusers;
+};
/*
* We tag multicasts with these structures.
*/
-
-struct dev_mc_list
-{
- struct dev_mc_list *next;
- __u8 dmi_addr[MAX_ADDR_LEN];
- unsigned char dmi_addrlen;
- int dmi_users;
- int dmi_gusers;
-};
+
+#define dev_mc_list dev_addr_list
+#define dmi_addr da_addr
+#define dmi_addrlen da_addrlen
+#define dmi_users da_users
+#define dmi_gusers da_gusers
struct hh_cache
{
@@ -248,6 +262,8 @@ enum netdev_state_t
__LINK_STATE_LINKWATCH_PENDING,
__LINK_STATE_DORMANT,
__LINK_STATE_QDISC_RUNNING,
+ /* Set by the netpoll NAPI code */
+ __LINK_STATE_POLL_LIST_FROZEN,
};
@@ -314,9 +330,10 @@ struct net_device
/* Net device features */
unsigned long features;
#define NETIF_F_SG 1 /* Scatter/gather IO. */
-#define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */
+#define NETIF_F_IP_CSUM 2 /* Can checksum TCP/UDP over IPv4. */
#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
#define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */
+#define NETIF_F_IPV6_CSUM 16 /* Can checksum TCP/UDP over IPV6 */
#define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */
#define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */
#define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */
@@ -325,6 +342,7 @@ struct net_device
#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
#define NETIF_F_GSO 2048 /* Enable software GSO. */
#define NETIF_F_LLTX 4096 /* LockLess TX */
+#define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */
/* Segmentation offload features */
#define NETIF_F_GSO_SHIFT 16
@@ -338,8 +356,11 @@ struct net_device
/* List of features with software fallbacks. */
#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
+
#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
-#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
+#define NETIF_F_V4_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IP_CSUM)
+#define NETIF_F_V6_CSUM (NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
+#define NETIF_F_ALL_CSUM (NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
struct net_device *next_sched;
@@ -388,7 +409,10 @@ struct net_device
unsigned char addr_len; /* hardware address length */
unsigned short dev_id; /* for shared network cards */
- struct dev_mc_list *mc_list; /* Multicast mac addresses */
+ struct dev_addr_list *uc_list; /* Secondary unicast mac addresses */
+ int uc_count; /* Number of installed ucasts */
+ int uc_promisc;
+ struct dev_addr_list *mc_list; /* Multicast mac addresses */
int mc_count; /* Number of installed mcasts */
int promiscuity;
int allmulti;
@@ -493,6 +517,11 @@ struct net_device
void *saddr,
unsigned len);
int (*rebuild_header)(struct sk_buff *skb);
+#define HAVE_CHANGE_RX_FLAGS
+ void (*change_rx_flags)(struct net_device *dev,
+ int flags);
+#define HAVE_SET_RX_MODE
+ void (*set_rx_mode)(struct net_device *dev);
#define HAVE_MULTICAST
void (*set_multicast_list)(struct net_device *dev);
#define HAVE_SET_MAC_ADDR
@@ -535,22 +564,29 @@ struct net_device
/* bridge stuff */
struct net_bridge_port *br_port;
+ /* macvlan */
+ struct macvlan_port *macvlan_port;
/* class/net/name entry */
struct device dev;
/* space for optional statistics and wireless sysfs groups */
struct attribute_group *sysfs_groups[3];
+
+ /* rtnetlink link ops */
+ const struct rtnl_link_ops *rtnl_link_ops;
+
+ /* The TX queue control structures */
+ unsigned int egress_subqueue_count;
+ struct net_device_subqueue egress_subqueue[0];
};
#define to_net_dev(d) container_of(d, struct net_device, dev)
#define NETDEV_ALIGN 32
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)
-static inline void *netdev_priv(struct net_device *dev)
+static inline void *netdev_priv(const struct net_device *dev)
{
- return (char *)dev + ((sizeof(struct net_device)
- + NETDEV_ALIGN_CONST)
- & ~NETDEV_ALIGN_CONST);
+ return dev->priv;
}
#define SET_MODULE_OWNER(dev) do { } while (0)
@@ -702,6 +738,62 @@ static inline int netif_running(const struct net_device *dev)
return test_bit(__LINK_STATE_START, &dev->state);
}
+/*
+ * Routines to manage the subqueues on a device. We only need start
+ * stop, and a check if it's stopped. All other device management is
+ * done at the overall netdevice level.
+ * Also test the device if we're multiqueue.
+ */
+static inline void netif_start_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ clear_bit(__LINK_STATE_XOFF, &dev->egress_subqueue[queue_index].state);
+#endif
+}
+
+static inline void netif_stop_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+#ifdef CONFIG_NETPOLL_TRAP
+ if (netpoll_trap())
+ return;
+#endif
+ set_bit(__LINK_STATE_XOFF, &dev->egress_subqueue[queue_index].state);
+#endif
+}
+
+static inline int netif_subqueue_stopped(const struct net_device *dev,
+ u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ return test_bit(__LINK_STATE_XOFF,
+ &dev->egress_subqueue[queue_index].state);
+#else
+ return 0;
+#endif
+}
+
+static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+#ifdef CONFIG_NETPOLL_TRAP
+ if (netpoll_trap())
+ return;
+#endif
+ if (test_and_clear_bit(__LINK_STATE_XOFF,
+ &dev->egress_subqueue[queue_index].state))
+ __netif_schedule(dev);
+#endif
+}
+
+static inline int netif_is_multiqueue(const struct net_device *dev)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ return (!!(NETIF_F_MULTI_QUEUE & dev->features));
+#else
+ return 0;
+#endif
+}
/* Use this variant when it is known for sure that it
* is executing from interrupt context.
@@ -910,6 +1002,17 @@ static inline int netif_rx_reschedule(struct net_device *dev, int undo)
return 0;
}
+/* same as netif_rx_complete, except that local_irq_save(flags)
+ * has already been issued
+ */
+static inline void __netif_rx_complete(struct net_device *dev)
+{
+ BUG_ON(!test_bit(__LINK_STATE_RX_SCHED, &dev->state));
+ list_del(&dev->poll_list);
+ smp_mb__before_clear_bit();
+ clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
+}
+
/* Remove interface from poll list: it must be in the poll list
* on current cpu. This primitive is called by dev->poll(), when
* it completes the work. The device cannot be out of poll list at this
@@ -919,11 +1022,16 @@ static inline void netif_rx_complete(struct net_device *dev)
{
unsigned long flags;
+#ifdef CONFIG_NETPOLL
+ /* Prevent race with netpoll - yes, this is a kludge.
+ * But at least it doesn't penalize the non-netpoll
+ * code path. */
+ if (test_bit(__LINK_STATE_POLL_LIST_FROZEN, &dev->state))
+ return;
+#endif
+
local_irq_save(flags);
- BUG_ON(!test_bit(__LINK_STATE_RX_SCHED, &dev->state));
- list_del(&dev->poll_list);
- smp_mb__before_clear_bit();
- clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
+ __netif_rx_complete(dev);
local_irq_restore(flags);
}
@@ -940,17 +1048,6 @@ static inline void netif_poll_enable(struct net_device *dev)
clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
}
-/* same as netif_rx_complete, except that local_irq_save(flags)
- * has already been issued
- */
-static inline void __netif_rx_complete(struct net_device *dev)
-{
- BUG_ON(!test_bit(__LINK_STATE_RX_SCHED, &dev->state));
- list_del(&dev->poll_list);
- smp_mb__before_clear_bit();
- clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
-}
-
static inline void netif_tx_lock(struct net_device *dev)
{
spin_lock(&dev->_xmit_lock);
@@ -995,15 +1092,26 @@ static inline void netif_tx_disable(struct net_device *dev)
extern void ether_setup(struct net_device *dev);
/* Support for loadable net-drivers */
-extern struct net_device *alloc_netdev(int sizeof_priv, const char *name,
- void (*setup)(struct net_device *));
+extern struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+ void (*setup)(struct net_device *),
+ unsigned int queue_count);
+#define alloc_netdev(sizeof_priv, name, setup) \
+ alloc_netdev_mq(sizeof_priv, name, setup, 1)
extern int register_netdev(struct net_device *dev);
extern void unregister_netdev(struct net_device *dev);
-/* Functions used for multicast support */
-extern void dev_mc_upload(struct net_device *dev);
+/* Functions used for secondary unicast and multicast support */
+extern void dev_set_rx_mode(struct net_device *dev);
+extern void __dev_set_rx_mode(struct net_device *dev);
+extern int dev_unicast_delete(struct net_device *dev, void *addr, int alen);
+extern int dev_unicast_add(struct net_device *dev, void *addr, int alen);
extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
+extern int dev_mc_sync(struct net_device *to, struct net_device *from);
+extern void dev_mc_unsync(struct net_device *to, struct net_device *from);
extern void dev_mc_discard(struct net_device *dev);
+extern int __dev_addr_delete(struct dev_addr_list **list, int *count, void *addr, int alen, int all);
+extern int __dev_addr_add(struct dev_addr_list **list, int *count, void *addr, int alen, int newonly);
+extern void __dev_addr_discard(struct dev_addr_list **list);
extern void dev_set_promiscuity(struct net_device *dev, int inc);
extern void dev_set_allmulti(struct net_device *dev, int inc);
extern void netdev_state_change(struct net_device *dev);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 10b5c627570..0eed0b7ab2d 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -275,7 +275,8 @@ struct nf_queue_handler {
};
extern int nf_register_queue_handler(int pf,
struct nf_queue_handler *qh);
-extern int nf_unregister_queue_handler(int pf);
+extern int nf_unregister_queue_handler(int pf,
+ struct nf_queue_handler *qh);
extern void nf_unregister_queue_handlers(struct nf_queue_handler *qh);
extern void nf_reinject(struct sk_buff *skb,
struct nf_info *info,
diff --git a/include/linux/netfilter/nf_conntrack_pptp.h b/include/linux/netfilter/nf_conntrack_pptp.h
index 9d8144a488c..c93061f3314 100644
--- a/include/linux/netfilter/nf_conntrack_pptp.h
+++ b/include/linux/netfilter/nf_conntrack_pptp.h
@@ -4,6 +4,8 @@
#include <linux/netfilter/nf_conntrack_common.h>
+extern const char *pptp_msg_name[];
+
/* state of the control session */
enum pptp_ctrlsess_state {
PPTP_SESSION_NONE, /* no session present */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 7e733a6ba4f..64f425a855b 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -141,22 +141,22 @@ struct xt_match
/* Arguments changed since 2.6.9, as this must now handle
non-linear skb, using skb_header_pointer and
skb_ip_make_writable. */
- int (*match)(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop);
+ bool (*match)(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ bool *hotdrop);
/* Called when user tries to insert an entry of this type. */
/* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask);
+ bool (*checkentry)(const char *tablename,
+ const void *ip,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask);
/* Called when entry of this type deleted. */
void (*destroy)(const struct xt_match *match, void *matchinfo);
@@ -202,11 +202,11 @@ struct xt_target
hook_mask is a bitmask of hooks from which it can be
called. */
/* Should return true or false. */
- int (*checkentry)(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask);
+ bool (*checkentry)(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask);
/* Called when entry of this type deleted. */
void (*destroy)(const struct xt_target *target, void *targinfo);
diff --git a/include/linux/netfilter/xt_connlimit.h b/include/linux/netfilter/xt_connlimit.h
new file mode 100644
index 00000000000..90ae8b474cb
--- /dev/null
+++ b/include/linux/netfilter/xt_connlimit.h
@@ -0,0 +1,17 @@
+#ifndef _XT_CONNLIMIT_H
+#define _XT_CONNLIMIT_H
+
+struct xt_connlimit_data;
+
+struct xt_connlimit_info {
+ union {
+ u_int32_t v4_mask;
+ u_int32_t v6_mask[4];
+ };
+ unsigned int limit, inverse;
+
+ /* this needs to be at the end */
+ struct xt_connlimit_data *data __attribute__((aligned(8)));
+};
+
+#endif /* _XT_CONNLIMIT_H */
diff --git a/include/linux/netfilter/xt_u32.h b/include/linux/netfilter/xt_u32.h
new file mode 100644
index 00000000000..9947f56cdbd
--- /dev/null
+++ b/include/linux/netfilter/xt_u32.h
@@ -0,0 +1,40 @@
+#ifndef _XT_U32_H
+#define _XT_U32_H 1
+
+enum xt_u32_ops {
+ XT_U32_AND,
+ XT_U32_LEFTSH,
+ XT_U32_RIGHTSH,
+ XT_U32_AT,
+};
+
+struct xt_u32_location_element {
+ u_int32_t number;
+ u_int8_t nextop;
+};
+
+struct xt_u32_value_element {
+ u_int32_t min;
+ u_int32_t max;
+};
+
+/*
+ * Any way to allow for an arbitrary number of elements?
+ * For now, I settle with a limit of 10 each.
+ */
+#define XT_U32_MAXSIZE 10
+
+struct xt_u32_test {
+ struct xt_u32_location_element location[XT_U32_MAXSIZE+1];
+ struct xt_u32_value_element value[XT_U32_MAXSIZE+1];
+ u_int8_t nnums;
+ u_int8_t nvalues;
+};
+
+struct xt_u32 {
+ struct xt_u32_test tests[XT_U32_MAXSIZE+1];
+ u_int8_t ntests;
+ u_int8_t invert;
+};
+
+#endif /* _XT_U32_H */
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 2f46dd728ee..e992cd6b28f 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -264,6 +264,26 @@ ipt_get_target(struct ipt_entry *e)
__ret; \
})
+/* fn returns 0 to continue iteration */
+#define IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
+({ \
+ unsigned int __i, __n; \
+ int __ret = 0; \
+ struct ipt_entry *__entry; \
+ \
+ for (__i = 0, __n = 0; __i < (size); \
+ __i += __entry->next_offset, __n++) { \
+ __entry = (void *)(entries) + __i; \
+ if (__n < n) \
+ continue; \
+ \
+ __ret = fn(__entry , ## args); \
+ if (__ret != 0) \
+ break; \
+ } \
+ __ret; \
+})
+
/*
* Main firewall chains definitions and global var's definitions.
*/
diff --git a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
index d9bceedfb3d..daf50be22c9 100644
--- a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+++ b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
@@ -18,13 +18,13 @@ struct clusterip_config;
struct ipt_clusterip_tgt_info {
u_int32_t flags;
-
+
/* only relevant for new ones */
u_int8_t clustermac[6];
u_int16_t num_total_nodes;
u_int16_t num_local_nodes;
u_int16_t local_nodes[CLUSTERIP_MAX_NODES];
- enum clusterip_hashmode hash_mode;
+ u_int32_t hash_mode;
u_int32_t hash_initval;
struct clusterip_config *config;
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 4686f8342cb..9a720f05888 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -44,8 +44,14 @@ struct ip6t_ip6 {
char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
- /* ARGH, HopByHop uses 0, so can't do 0 = ANY,
- instead IP6T_F_NOPROTO must be set */
+ /* Upper protocol number
+ * - The allowed value is 0 (any) or protocol number of last parsable
+ * header, which is 50 (ESP), 59 (No Next Header), 135 (MH), or
+ * the non IPv6 extension headers.
+ * - The protocol numbers of IPv6 extension headers except of ESP and
+ * MH do not match any packets.
+ * - You also need to set IP6T_FLAGS_PROTO to "flags" to check protocol.
+ */
u_int16_t proto;
/* TOS to match iff flags & IP6T_F_TOS */
u_int8_t tos;
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 7e7f33a38fc..8726491de15 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -15,6 +15,7 @@
#include <linux/types.h>
+#define NFS4_BITMAP_SIZE 2
#define NFS4_VERIFIER_SIZE 8
#define NFS4_STATEID_SIZE 16
#define NFS4_FHSIZE 128
diff --git a/include/linux/nfs4_mount.h b/include/linux/nfs4_mount.h
index 26b4c83f831..a0dcf665565 100644
--- a/include/linux/nfs4_mount.h
+++ b/include/linux/nfs4_mount.h
@@ -65,6 +65,7 @@ struct nfs4_mount_data {
#define NFS4_MOUNT_NOCTO 0x0010 /* 1 */
#define NFS4_MOUNT_NOAC 0x0020 /* 1 */
#define NFS4_MOUNT_STRICTLOCK 0x1000 /* 1 */
-#define NFS4_MOUNT_FLAGMASK 0xFFFF
+#define NFS4_MOUNT_UNSHARED 0x8000 /* 1 */
+#define NFS4_MOUNT_FLAGMASK 0x9033
#endif
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 0543439a97a..c098ae194f7 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -30,7 +30,9 @@
#ifdef __KERNEL__
#include <linux/in.h>
+#include <linux/kref.h>
#include <linux/mm.h>
+#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/rbtree.h>
#include <linux/rwsem.h>
@@ -69,9 +71,8 @@ struct nfs_access_entry {
struct nfs4_state;
struct nfs_open_context {
- atomic_t count;
- struct vfsmount *vfsmnt;
- struct dentry *dentry;
+ struct kref kref;
+ struct path path;
struct rpc_cred *cred;
struct nfs4_state *state;
fl_owner_t lockowner;
@@ -155,13 +156,9 @@ struct nfs_inode {
/*
* This is the list of dirty unwritten pages.
*/
- spinlock_t req_lock;
- struct list_head dirty;
- struct list_head commit;
struct radix_tree_root nfs_page_tree;
- unsigned int ndirty,
- ncommit,
+ unsigned long ncommit,
npages;
/* Open contexts for shared mmap writes */
@@ -187,6 +184,7 @@ struct nfs_inode {
#define NFS_INO_INVALID_ACCESS 0x0008 /* cached access cred invalid */
#define NFS_INO_INVALID_ACL 0x0010 /* cached acls are invalid */
#define NFS_INO_REVAL_PAGECACHE 0x0020 /* must revalidate pagecache */
+#define NFS_INO_REVAL_FORCED 0x0040 /* force revalidation ignoring a delegation */
/*
* Bit offsets in flags field
@@ -496,21 +494,18 @@ static inline void nfs3_forget_cached_acls(struct inode *inode)
/*
* linux/fs/mount_clnt.c
- * (Used only by nfsroot module)
*/
-extern int nfsroot_mount(struct sockaddr_in *, char *, struct nfs_fh *,
- int, int);
+extern int nfs_mount(struct sockaddr *, size_t, char *, char *,
+ int, int, struct nfs_fh *);
/*
* inline functions
*/
-static inline loff_t
-nfs_size_to_loff_t(__u64 size)
+static inline loff_t nfs_size_to_loff_t(__u64 size)
{
- loff_t maxsz = (((loff_t) ULONG_MAX) << PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE - 1;
- if (size > maxsz)
- return maxsz;
+ if (size > (__u64) OFFSET_MAX - 1)
+ return OFFSET_MAX - 1;
return (loff_t) size;
}
@@ -557,6 +552,7 @@ extern void * nfs_root_data(void);
#define NFSDBG_ROOT 0x0080
#define NFSDBG_CALLBACK 0x0100
#define NFSDBG_CLIENT 0x0200
+#define NFSDBG_MOUNT 0x0400
#define NFSDBG_ALL 0xFFFF
#ifdef __KERNEL__
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 52b4378311c..0cac49bc095 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -16,7 +16,6 @@ struct nfs_client {
#define NFS_CS_INITING 1 /* busy initialising */
int cl_nfsversion; /* NFS protocol version */
unsigned long cl_res_state; /* NFS resources state */
-#define NFS_CS_RPCIOD 0 /* - rpciod started */
#define NFS_CS_CALLBACK 1 /* - callback started */
#define NFS_CS_IDMAP 2 /* - idmap started */
#define NFS_CS_RENEWD 3 /* - renewd started */
@@ -35,7 +34,8 @@ struct nfs_client {
nfs4_verifier cl_confirm;
unsigned long cl_state;
- u32 cl_lockowner_id;
+ struct rb_root cl_openowner_id;
+ struct rb_root cl_lockowner_id;
/*
* The following rwsem ensures exclusive access to the server
@@ -44,9 +44,7 @@ struct nfs_client {
struct rw_semaphore cl_sem;
struct list_head cl_delegations;
- struct list_head cl_state_owners;
- struct list_head cl_unused;
- int cl_nunused;
+ struct rb_root cl_state_owners;
spinlock_t cl_lock;
unsigned long cl_lease_time;
diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
index cc8b9c59acb..a3ade89a64d 100644
--- a/include/linux/nfs_mount.h
+++ b/include/linux/nfs_mount.h
@@ -37,7 +37,7 @@ struct nfs_mount_data {
int acdirmin; /* 1 */
int acdirmax; /* 1 */
struct sockaddr_in addr; /* 1 */
- char hostname[256]; /* 1 */
+ char hostname[NFS_MAXNAMLEN + 1]; /* 1 */
int namlen; /* 2 */
unsigned int bsize; /* 3 */
struct nfs3_fh root; /* 4 */
@@ -62,6 +62,7 @@ struct nfs_mount_data {
#define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */
#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */
#define NFS_MOUNT_NORDIRPLUS 0x4000 /* 5 */
+#define NFS_MOUNT_UNSHARED 0x8000 /* 5 */
#define NFS_MOUNT_FLAGMASK 0xFFFF
#endif
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index bd193af8016..78e60798d10 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -16,12 +16,13 @@
#include <linux/sunrpc/auth.h>
#include <linux/nfs_xdr.h>
-#include <asm/atomic.h>
+#include <linux/kref.h>
/*
* Valid flags for the radix tree
*/
-#define NFS_PAGE_TAG_WRITEBACK 0
+#define NFS_PAGE_TAG_LOCKED 0
+#define NFS_PAGE_TAG_COMMIT 1
/*
* Valid flags for a dirty buffer
@@ -33,8 +34,7 @@
struct nfs_inode;
struct nfs_page {
- struct list_head wb_list, /* Defines state of page: */
- *wb_list_head; /* read/write/commit */
+ struct list_head wb_list; /* Defines state of page: */
struct page *wb_page; /* page to read in/write out */
struct nfs_open_context *wb_context; /* File state context info */
atomic_t wb_complete; /* i/os we're waiting for */
@@ -42,7 +42,7 @@ struct nfs_page {
unsigned int wb_offset, /* Offset & ~PAGE_CACHE_MASK */
wb_pgbase, /* Start of page data */
wb_bytes; /* Length of request */
- atomic_t wb_count; /* reference count */
+ struct kref wb_kref; /* reference count */
unsigned long wb_flags;
struct nfs_writeverf wb_verf; /* Commit cookie */
};
@@ -71,8 +71,8 @@ extern void nfs_clear_request(struct nfs_page *req);
extern void nfs_release_request(struct nfs_page *req);
-extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
- pgoff_t idx_start, unsigned int npages);
+extern int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst,
+ pgoff_t idx_start, unsigned int npages, int tag);
extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
struct inode *inode,
int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
@@ -84,12 +84,11 @@ extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t);
extern int nfs_wait_on_request(struct nfs_page *);
extern void nfs_unlock_request(struct nfs_page *req);
-extern int nfs_set_page_writeback_locked(struct nfs_page *req);
-extern void nfs_clear_page_writeback(struct nfs_page *req);
+extern void nfs_clear_page_tag_locked(struct nfs_page *req);
/*
- * Lock the page of an asynchronous request without incrementing the wb_count
+ * Lock the page of an asynchronous request without getting a new reference
*/
static inline int
nfs_lock_request_dontget(struct nfs_page *req)
@@ -98,14 +97,14 @@ nfs_lock_request_dontget(struct nfs_page *req)
}
/*
- * Lock the page of an asynchronous request
+ * Lock the page of an asynchronous request and take a reference
*/
static inline int
nfs_lock_request(struct nfs_page *req)
{
if (test_and_set_bit(PG_BUSY, &req->wb_flags))
return 0;
- atomic_inc(&req->wb_count);
+ kref_get(&req->wb_kref);
return 1;
}
@@ -118,7 +117,6 @@ static inline void
nfs_list_add_request(struct nfs_page *req, struct list_head *head)
{
list_add_tail(&req->wb_list, head);
- req->wb_list_head = head;
}
@@ -132,7 +130,6 @@ nfs_list_remove_request(struct nfs_page *req)
if (list_empty(&req->wb_list))
return;
list_del_init(&req->wb_list);
- req->wb_list_head = NULL;
}
static inline struct nfs_page *
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 10c26ed0db7..38d77681cf2 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -119,7 +119,7 @@ struct nfs_openargs {
struct nfs_seqid * seqid;
int open_flags;
__u64 clientid;
- __u32 id;
+ __u64 id;
union {
struct iattr * attrs; /* UNCHECKED, GUARDED */
nfs4_verifier verifier; /* EXCLUSIVE */
@@ -144,6 +144,7 @@ struct nfs_openres {
nfs4_stateid delegation;
__u32 do_recall;
__u64 maxsize;
+ __u32 attrset[NFS4_BITMAP_SIZE];
};
/*
@@ -180,7 +181,7 @@ struct nfs_closeres {
* */
struct nfs_lowner {
__u64 clientid;
- u32 id;
+ __u64 id;
};
struct nfs_lock_args {
diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h
index 2d5fd647e0e..5799e8d5062 100644
--- a/include/linux/pata_platform.h
+++ b/include/linux/pata_platform.h
@@ -8,6 +8,11 @@ struct pata_platform_info {
* spacing used by ata_std_ports().
*/
unsigned int ioport_shift;
+ /*
+ * Indicate platform specific irq types and initial
+ * IRQ flags when call request_irq()
+ */
+ unsigned int irq_flags;
};
#endif /* __LINUX_PATA_PLATFORM_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index fbf3766dac1..37a71580ad8 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -111,7 +111,8 @@ enum pcie_reset_state {
typedef unsigned short __bitwise pci_bus_flags_t;
enum pci_bus_flags {
- PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
+ PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
+ PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
};
struct pci_cap_saved_state {
@@ -138,6 +139,7 @@ struct pci_dev {
unsigned short subsystem_vendor;
unsigned short subsystem_device;
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
+ u8 revision; /* PCI revision, low byte of class word */
u8 hdr_type; /* PCI header type (`multi' flag masked out) */
u8 rom_base_reg; /* which config register controls the ROM */
u8 pin; /* which interrupt pin this device uses */
@@ -313,7 +315,7 @@ struct pci_dynids {
/* ---------------------------------------------------------------- */
/** PCI Error Recovery System (PCI-ERS). If a PCI device driver provides
- * a set fof callbacks in struct pci_error_handlers, then that device driver
+ * a set of callbacks in struct pci_error_handlers, then that device driver
* will be notified of PCI bus errors, and will be driven to recovery
* when an error occurs.
*/
@@ -370,7 +372,6 @@ struct pci_driver {
int (*suspend_late) (struct pci_dev *dev, pm_message_t state);
int (*resume_early) (struct pci_dev *dev);
int (*resume) (struct pci_dev *dev); /* Device woken up */
- int (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable); /* Enable wake event */
void (*shutdown) (struct pci_dev *dev);
struct pci_error_handlers *err_handler;
@@ -475,7 +476,7 @@ extern void pci_sort_breadthfirst(void);
/* Generic PCI functions exported to card drivers */
struct pci_dev __deprecated *pci_find_device (unsigned int vendor, unsigned int device, const struct pci_dev *from);
-struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
+struct pci_dev __deprecated *pci_find_slot (unsigned int bus, unsigned int devfn);
int pci_find_capability (struct pci_dev *dev, int cap);
int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
int pci_find_ext_capability (struct pci_dev *dev, int cap);
@@ -544,11 +545,16 @@ void pci_set_master(struct pci_dev *dev);
int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
#define HAVE_PCI_SET_MWI
int __must_check pci_set_mwi(struct pci_dev *dev);
+int pci_try_set_mwi(struct pci_dev *dev);
void pci_clear_mwi(struct pci_dev *dev);
void pci_intx(struct pci_dev *dev, int enable);
void pci_msi_off(struct pci_dev *dev);
int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
+int pcix_get_max_mmrbc(struct pci_dev *dev);
+int pcix_get_mmrbc(struct pci_dev *dev);
+int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
+int pcie_set_readrq(struct pci_dev *dev, int rq);
void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
int __must_check pci_assign_resource(struct pci_dev *dev, int i);
int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
@@ -560,6 +566,7 @@ void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
void __iomem __must_check *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
void pci_remove_rom(struct pci_dev *pdev);
+size_t pci_get_rom_size(void __iomem *rom, size_t size);
/* Power management related routines */
int pci_save_state(struct pci_dev *dev);
@@ -748,6 +755,17 @@ static inline void pci_release_regions(struct pci_dev *dev) { }
static inline void pci_block_user_cfg_access(struct pci_dev *dev) { }
static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) { }
+static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
+{ return NULL; }
+
+static inline struct pci_dev *pci_get_slot(struct pci_bus *bus,
+ unsigned int devfn)
+{ return NULL; }
+
+static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
+ unsigned int devfn)
+{ return NULL; }
+
#endif /* CONFIG_PCI */
/* Include architecture-dependent settings and functions */
@@ -865,5 +883,7 @@ extern int pci_pci_problems;
extern unsigned long pci_cardbus_io_size;
extern unsigned long pci_cardbus_mem_size;
+extern int pcibios_add_platform_entries(struct pci_dev *dev);
+
#endif /* __KERNEL__ */
#endif /* LINUX_PCI_H */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 4712e269d8d..2c7add16953 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -133,6 +133,9 @@
/* Vendors and devices. Sort key: vendor first, device next. */
+#define PCI_VENDOR_ID_TTTECH 0x0357
+#define PCI_DEVICE_ID_TTTECH_MC322 0x000a
+
#define PCI_VENDOR_ID_DYNALINK 0x0675
#define PCI_DEVICE_ID_DYNALINK_IS64PH 0x1702
@@ -371,6 +374,7 @@
#define PCI_DEVICE_ID_ATI_IXP600_SMBUS 0x4385
#define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c
#define PCI_DEVICE_ID_ATI_IXP700_SATA 0x4390
+#define PCI_DEVICE_ID_ATI_IXP700_SMBUS 0x4395
#define PCI_DEVICE_ID_ATI_IXP700_IDE 0x439c
#define PCI_VENDOR_ID_VLSI 0x1004
@@ -475,6 +479,9 @@
#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
+#define PCI_VENDOR_ID_UNISYS 0x1018
+#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C
+
#define PCI_VENDOR_ID_COMPEX2 0x101a /* pci.ids says "AT&T GIS (NCR)" */
#define PCI_DEVICE_ID_COMPEX2_100VG 0x0005
@@ -661,6 +668,7 @@
#define PCI_DEVICE_ID_SI_965 0x0965
#define PCI_DEVICE_ID_SI_966 0x0966
#define PCI_DEVICE_ID_SI_968 0x0968
+#define PCI_DEVICE_ID_SI_1180 0x1180
#define PCI_DEVICE_ID_SI_5511 0x5511
#define PCI_DEVICE_ID_SI_5513 0x5513
#define PCI_DEVICE_ID_SI_5517 0x5517
@@ -731,7 +739,6 @@
#define PCI_DEVICE_ID_ELSA_MICROLINK 0x1000
#define PCI_DEVICE_ID_ELSA_QS3000 0x3000
-
#define PCI_VENDOR_ID_BUSLOGIC 0x104B
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040
@@ -777,7 +784,6 @@
#define PCI_VENDOR_ID_SONY 0x104d
-
/* Winbond have two vendor IDs! See 0x10ad as well */
#define PCI_VENDOR_ID_WINBOND2 0x1050
#define PCI_DEVICE_ID_WINBOND2_89C940F 0x5a5a
@@ -815,7 +821,6 @@
#define PCI_DEVICE_ID_PROMISE_20276 0x5275
#define PCI_DEVICE_ID_PROMISE_20277 0x7275
-
#define PCI_VENDOR_ID_UMC 0x1060
#define PCI_DEVICE_ID_UMC_UM8673F 0x0101
#define PCI_DEVICE_ID_UMC_UM8886BF 0x673a
@@ -831,7 +836,6 @@
#define PCI_DEVICE_ID_MYLEX_DAC960_BA 0xBA56
#define PCI_DEVICE_ID_MYLEX_DAC960_GEM 0xB166
-
#define PCI_VENDOR_ID_APPLE 0x106b
#define PCI_DEVICE_ID_APPLE_BANDIT 0x0001
#define PCI_DEVICE_ID_APPLE_HYDRA 0x000e
@@ -867,7 +871,6 @@
#define PCI_DEVICE_ID_YAMAHA_744 0x0010
#define PCI_DEVICE_ID_YAMAHA_754 0x0012
-
#define PCI_VENDOR_ID_QLOGIC 0x1077
#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016
#define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020
@@ -898,12 +901,9 @@
#define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103
#define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104
-
-
#define PCI_VENDOR_ID_CONTAQ 0x1080
#define PCI_DEVICE_ID_CONTAQ_82C693 0xc693
-
#define PCI_VENDOR_ID_OLICOM 0x108d
#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012
#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013
@@ -935,23 +935,19 @@
#define PCI_DEVICE_ID_SII_3112 0x3112
#define PCI_DEVICE_ID_SII_1210SA 0x0240
-
#define PCI_VENDOR_ID_BROOKTREE 0x109e
#define PCI_DEVICE_ID_BROOKTREE_878 0x0878
#define PCI_DEVICE_ID_BROOKTREE_879 0x0879
-
#define PCI_VENDOR_ID_SGI 0x10a9
#define PCI_DEVICE_ID_SGI_IOC3 0x0003
+#define PCI_DEVICE_ID_SGI_LITHIUM 0x1002
#define PCI_DEVICE_ID_SGI_IOC4 0x100a
-#define PCI_VENDOR_ID_SGI_LITHIUM 0x1002
-
#define PCI_VENDOR_ID_WINBOND 0x10ad
#define PCI_DEVICE_ID_WINBOND_82C105 0x0105
#define PCI_DEVICE_ID_WINBOND_83C553 0x0565
-
#define PCI_VENDOR_ID_PLX 0x10b5
#define PCI_DEVICE_ID_PLX_R685 0x1030
#define PCI_DEVICE_ID_PLX_ROMULUS 0x106a
@@ -985,7 +981,6 @@
#define PCI_DEVICE_ID_3COM_3CR990SVR97 0x9909
#define PCI_DEVICE_ID_3COM_3CR990SVR 0x990a
-
#define PCI_VENDOR_ID_AL 0x10b9
#define PCI_DEVICE_ID_AL_M1533 0x1533
#define PCI_DEVICE_ID_AL_M1535 0x1535
@@ -1008,18 +1003,14 @@
#define PCI_DEVICE_ID_AL_M5451 0x5451
#define PCI_DEVICE_ID_AL_M7101 0x7101
-
-
#define PCI_VENDOR_ID_NEOMAGIC 0x10c8
#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
-
#define PCI_VENDOR_ID_TCONRAD 0x10da
#define PCI_DEVICE_ID_TCONRAD_TOKENRING 0x0508
-
#define PCI_VENDOR_ID_NVIDIA 0x10de
#define PCI_DEVICE_ID_NVIDIA_TNT 0x0020
#define PCI_DEVICE_ID_NVIDIA_TNT2 0x0028
@@ -1233,14 +1224,13 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E
#define PCI_DEVICE_ID_NVIDIA_NVENET_27 0x054F
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759
#define PCI_VENDOR_ID_IMS 0x10e0
#define PCI_DEVICE_ID_IMS_TT128 0x9128
#define PCI_DEVICE_ID_IMS_TT3D 0x9135
-
-
-
#define PCI_VENDOR_ID_INTERG 0x10ea
#define PCI_DEVICE_ID_INTERG_1682 0x1682
#define PCI_DEVICE_ID_INTERG_2000 0x2000
@@ -1259,7 +1249,6 @@
#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
-
#define PCI_VENDOR_ID_INIT 0x1101
#define PCI_VENDOR_ID_CREATIVE 0x1102 /* duplicate: ECTIVA */
@@ -1292,6 +1281,7 @@
#define PCI_DEVICE_ID_VIA_P4M890 0x0327
#define PCI_DEVICE_ID_VIA_VT3324 0x0324
#define PCI_DEVICE_ID_VIA_VT3336 0x0336
+#define PCI_DEVICE_ID_VIA_VT3351 0x0351
#define PCI_DEVICE_ID_VIA_8371_0 0x0391
#define PCI_DEVICE_ID_VIA_8501_0 0x0501
#define PCI_DEVICE_ID_VIA_82C561 0x0561
@@ -1353,7 +1343,6 @@
#define PCI_VENDOR_ID_SIEMENS 0x110A
#define PCI_DEVICE_ID_SIEMENS_DSCC4 0x2102
-
#define PCI_VENDOR_ID_VORTEX 0x1119
#define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000
#define PCI_DEVICE_ID_VORTEX_GDT6000B 0x0001
@@ -1379,8 +1368,8 @@
#define PCI_VENDOR_ID_EF 0x111a
#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000
#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002
-#define PCI_VENDOR_ID_EF_ATM_LANAI2 0x0003
-#define PCI_VENDOR_ID_EF_ATM_LANAIHB 0x0005
+#define PCI_DEVICE_ID_EF_ATM_LANAI2 0x0003
+#define PCI_DEVICE_ID_EF_ATM_LANAIHB 0x0005
#define PCI_VENDOR_ID_IDT 0x111d
#define PCI_DEVICE_ID_IDT_IDT77201 0x0001
@@ -1388,7 +1377,6 @@
#define PCI_VENDOR_ID_FORE 0x1127
#define PCI_DEVICE_ID_FORE_PCA200E 0x0300
-
#define PCI_VENDOR_ID_PHILIPS 0x1131
#define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146
#define PCI_DEVICE_ID_PHILIPS_SAA9730 0x9730
@@ -1407,7 +1395,6 @@
#define PCI_DEVICE_ID_ZIATECH_5550_HC 0x5550
-
#define PCI_VENDOR_ID_SYSKONNECT 0x1148
#define PCI_DEVICE_ID_SYSKONNECT_TR 0x4200
#define PCI_DEVICE_ID_SYSKONNECT_GE 0x4300
@@ -1415,7 +1402,6 @@
#define PCI_DEVICE_ID_SYSKONNECT_9DXX 0x4400
#define PCI_DEVICE_ID_SYSKONNECT_9MXX 0x4500
-
#define PCI_VENDOR_ID_DIGI 0x114f
#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070
#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071
@@ -1426,17 +1412,16 @@
#define PCI_DEVICE_ID_NEO_2RJ45 0x00CA
#define PCI_DEVICE_ID_NEO_2RJ45PRI 0x00CB
-
#define PCI_VENDOR_ID_XIRCOM 0x115d
#define PCI_DEVICE_ID_XIRCOM_RBM56G 0x0101
#define PCI_DEVICE_ID_XIRCOM_X3201_MDM 0x0103
-
#define PCI_VENDOR_ID_SERVERWORKS 0x1166
#define PCI_DEVICE_ID_SERVERWORKS_HE 0x0008
#define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009
#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
#define PCI_DEVICE_ID_SERVERWORKS_EPB 0x0103
+#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX 0x0104
#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132
#define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200
#define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201
@@ -1499,7 +1484,6 @@
#define PCI_DEVICE_ID_ZEITNET_1221 0x0001
#define PCI_DEVICE_ID_ZEITNET_1225 0x0002
-
#define PCI_VENDOR_ID_FUJITSU_ME 0x119e
#define PCI_DEVICE_ID_FUJITSU_FS155 0x0001
#define PCI_DEVICE_ID_FUJITSU_FS50 0x0003
@@ -1517,28 +1501,23 @@
#define PCI_DEVICE_ID_V3_V960 0x0001
#define PCI_DEVICE_ID_V3_V351 0x0002
-
#define PCI_VENDOR_ID_ATT 0x11c1
#define PCI_DEVICE_ID_ATT_VENUS_MODEM 0x480
-
#define PCI_VENDOR_ID_SPECIALIX 0x11cb
#define PCI_DEVICE_ID_SPECIALIX_IO8 0x2000
#define PCI_DEVICE_ID_SPECIALIX_RIO 0x8000
#define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004
-
#define PCI_VENDOR_ID_ANALOG_DEVICES 0x11d4
#define PCI_DEVICE_ID_AD1889JS 0x1889
-
#define PCI_DEVICE_ID_SEGA_BBA 0x1234
#define PCI_VENDOR_ID_ZORAN 0x11de
#define PCI_DEVICE_ID_ZORAN_36057 0x6057
#define PCI_DEVICE_ID_ZORAN_36120 0x6120
-
#define PCI_VENDOR_ID_COMPEX 0x11f6
#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112
@@ -1597,8 +1576,6 @@
#define PCI_DEVICE_ID_3DFX_VOODOO3 0x0005
#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
-
-
#define PCI_VENDOR_ID_AVM 0x1244
#define PCI_DEVICE_ID_AVM_B1 0x0700
#define PCI_DEVICE_ID_AVM_C4 0x0800
@@ -1607,7 +1584,6 @@
#define PCI_DEVICE_ID_AVM_C2 0x1100
#define PCI_DEVICE_ID_AVM_T1 0x1200
-
#define PCI_VENDOR_ID_STALLION 0x124d
/* Allied Telesyn */
@@ -1630,7 +1606,6 @@
#define PCI_VENDOR_ID_SATSAGEM 0x1267
#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016
-
#define PCI_VENDOR_ID_ENSONIQ 0x1274
#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
#define PCI_DEVICE_ID_ENSONIQ_ES1370 0x5000
@@ -1653,7 +1628,6 @@
#define PCI_VENDOR_ID_ALTEON 0x12ae
-
#define PCI_SUBVENDOR_ID_CONNECT_TECH 0x12c4
#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232 0x0001
#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232 0x0002
@@ -1684,7 +1658,6 @@
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485 0x0331
#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485 0x0332
-
#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
@@ -1794,7 +1767,6 @@
#define PCI_DEVICE_ID_LMC_SSI 0x0005
#define PCI_DEVICE_ID_LMC_T1 0x0006
-
#define PCI_VENDOR_ID_NETGEAR 0x1385
#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a
@@ -1897,6 +1869,8 @@
#define PCI_DEVICE_ID_OXSEMI_16PCI952 0x9521
#define PCI_DEVICE_ID_OXSEMI_16PCI952PP 0x9523
+#define PCI_VENDOR_ID_CHELSIO 0x1425
+
#define PCI_VENDOR_ID_SAMSUNG 0x144d
#define PCI_VENDOR_ID_MYRICOM 0x14c1
@@ -1995,6 +1969,7 @@
#define PCI_VENDOR_ID_ENE 0x1524
#define PCI_DEVICE_ID_ENE_CB712_SD 0x0550
+#define PCI_DEVICE_ID_ENE_CB712_SD_2 0x0551
#define PCI_DEVICE_ID_ENE_1211 0x1211
#define PCI_DEVICE_ID_ENE_1225 0x1225
#define PCI_DEVICE_ID_ENE_1410 0x1410
@@ -2004,13 +1979,10 @@
#define PCI_DEVICE_ID_ENE_720 0x1421
#define PCI_DEVICE_ID_ENE_722 0x1422
-#define PCI_VENDOR_ID_CHELSIO 0x1425
-
#define PCI_SUBVENDOR_ID_PERLE 0x155f
#define PCI_SUBDEVICE_ID_PCI_RAS4 0xf001
#define PCI_SUBDEVICE_ID_PCI_RAS8 0xf010
-
#define PCI_VENDOR_ID_SYBA 0x1592
#define PCI_DEVICE_ID_SYBA_2P_EPP 0x0782
#define PCI_DEVICE_ID_SYBA_1P_ECP 0x0783
@@ -2029,8 +2001,10 @@
#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
#define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274
-#define PCI_VENDOR_ID_PDC 0x15e9
+#define PCI_VENDOR_ID_QUICKNET 0x15e2
+#define PCI_DEVICE_ID_QUICKNET_XJ 0x0500
+#define PCI_VENDOR_ID_PDC 0x15e9
#define PCI_VENDOR_ID_FARSITE 0x1619
#define PCI_DEVICE_ID_FARSITE_T2P 0x0400
@@ -2047,6 +2021,8 @@
#define PCI_DEVICE_ID_BCM1250_PCI 0x0001
#define PCI_DEVICE_ID_BCM1250_HT 0x0002
+#define PCI_VENDOR_ID_ATHEROS 0x168c
+
#define PCI_VENDOR_ID_NETCELL 0x169c
#define PCI_DEVICE_ID_REVOLUTION 0x0044
@@ -2085,7 +2061,6 @@
#define PCI_DEVICE_ID_HERC_WIN 0x5732
#define PCI_DEVICE_ID_HERC_UNI 0x5832
-
#define PCI_VENDOR_ID_SITECOM 0x182d
#define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069
@@ -2121,12 +2096,9 @@
#define PCI_DEVICE_ID_3DLABS_PERMEDIA2 0x0007
#define PCI_DEVICE_ID_3DLABS_PERMEDIA2V 0x0009
-
#define PCI_VENDOR_ID_AKS 0x416c
#define PCI_DEVICE_ID_AKS_ALADDINCARD 0x0100
-
-
#define PCI_VENDOR_ID_S3 0x5333
#define PCI_DEVICE_ID_S3_TRIO 0x8811
#define PCI_DEVICE_ID_S3_868 0x8880
@@ -2138,7 +2110,6 @@
#define PCI_VENDOR_ID_DUNORD 0x5544
#define PCI_DEVICE_ID_DUNORD_I3000 0x0001
-
#define PCI_VENDOR_ID_DCI 0x6666
#define PCI_DEVICE_ID_DCI_PCCOM4 0x0001
#define PCI_DEVICE_ID_DCI_PCCOM8 0x0002
@@ -2267,11 +2238,11 @@
#define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e
#define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850
#define PCI_DEVICE_ID_INTEL_ICH9_0 0x2910
-#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2911
+#define PCI_DEVICE_ID_INTEL_ICH9_1 0x2917
#define PCI_DEVICE_ID_INTEL_ICH9_2 0x2912
#define PCI_DEVICE_ID_INTEL_ICH9_3 0x2913
#define PCI_DEVICE_ID_INTEL_ICH9_4 0x2914
-#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2915
+#define PCI_DEVICE_ID_INTEL_ICH9_5 0x2919
#define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930
#define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340
#define PCI_DEVICE_ID_INTEL_82830_HB 0x3575
@@ -2382,7 +2353,6 @@
#define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN 0x0500
#define PCI_DEVICE_ID_ADAPTEC2_SCAMP 0x0503
-
#define PCI_VENDOR_ID_HOLTEK 0x9412
#define PCI_DEVICE_ID_HOLTEK_6565 0x6565
@@ -2398,6 +2368,8 @@
#define PCI_DEVICE_ID_NETMOS_9845 0x9845
#define PCI_DEVICE_ID_NETMOS_9855 0x9855
+#define PCI_VENDOR_ID_3COM_2 0xa727
+
#define PCI_SUBVENDOR_ID_EXSYS 0xd84d
#define PCI_SUBDEVICE_ID_EXSYS_4014 0x4014
#define PCI_SUBDEVICE_ID_EXSYS_4055 0x4055
@@ -2406,13 +2378,7 @@
#define PCI_DEVICE_ID_TIGERJET_300 0x0001
#define PCI_DEVICE_ID_TIGERJET_100 0x0002
-#define PCI_VENDOR_ID_TTTECH 0x0357
-#define PCI_DEVICE_ID_TTTECH_MC322 0x000A
-
#define PCI_VENDOR_ID_XILINX_RME 0xea60
#define PCI_DEVICE_ID_RME_DIGI32 0x9896
#define PCI_DEVICE_ID_RME_DIGI32_PRO 0x9897
#define PCI_DEVICE_ID_RME_DIGI32_8 0x9898
-
-#define PCI_VENDOR_ID_QUICKNET 0x15E2
-#define PCI_DEVICE_ID_QUICKNET_XJ 0x0500
diff --git a/include/linux/pda_power.h b/include/linux/pda_power.h
new file mode 100644
index 00000000000..1375f15797e
--- /dev/null
+++ b/include/linux/pda_power.h
@@ -0,0 +1,31 @@
+/*
+ * Common power driver for PDAs and phones with one or two external
+ * power supplies (AC/USB) connected to main and backup batteries,
+ * and optional builtin charger.
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ *
+ * 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 __PDA_POWER_H__
+#define __PDA_POWER_H__
+
+#define PDA_POWER_CHARGE_AC (1 << 0)
+#define PDA_POWER_CHARGE_USB (1 << 1)
+
+struct pda_power_pdata {
+ int (*is_ac_online)(void);
+ int (*is_usb_online)(void);
+ void (*set_charge)(int flags);
+
+ char **supplied_to;
+ size_t num_supplicants;
+
+ unsigned int wait_for_status; /* msecs, default is 500 */
+ unsigned int wait_for_charger; /* msecs, default is 500 */
+};
+
+#endif /* __PDA_POWER_H__ */
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 8bcbc54e1b4..8e4120285f7 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -9,48 +9,125 @@
#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
+/**
+ * struct pipe_buffer - a linux kernel pipe buffer
+ * @page: the page containing the data for the pipe buffer
+ * @offset: offset of data inside the @page
+ * @len: length of data inside the @page
+ * @ops: operations associated with this buffer. See @pipe_buf_operations.
+ * @flags: pipe buffer flags. See above.
+ * @private: private data owned by the ops.
+ **/
struct pipe_buffer {
struct page *page;
unsigned int offset, len;
const struct pipe_buf_operations *ops;
unsigned int flags;
+ unsigned long private;
+};
+
+/**
+ * struct pipe_inode_info - a linux kernel pipe
+ * @wait: reader/writer wait point in case of empty/full pipe
+ * @nrbufs: the number of non-empty pipe buffers in this pipe
+ * @curbuf: the current pipe buffer entry
+ * @tmp_page: cached released page
+ * @readers: number of current readers of this pipe
+ * @writers: number of current writers of this pipe
+ * @waiting_writers: number of writers blocked waiting for room
+ * @r_counter: reader counter
+ * @w_counter: writer counter
+ * @fasync_readers: reader side fasync
+ * @fasync_writers: writer side fasync
+ * @inode: inode this pipe is attached to
+ * @bufs: the circular array of pipe buffers
+ **/
+struct pipe_inode_info {
+ wait_queue_head_t wait;
+ unsigned int nrbufs, curbuf;
+ struct page *tmp_page;
+ unsigned int readers;
+ unsigned int writers;
+ unsigned int waiting_writers;
+ unsigned int r_counter;
+ unsigned int w_counter;
+ struct fasync_struct *fasync_readers;
+ struct fasync_struct *fasync_writers;
+ struct inode *inode;
+ struct pipe_buffer bufs[PIPE_BUFFERS];
};
/*
* Note on the nesting of these functions:
*
- * ->pin()
+ * ->confirm()
* ->steal()
* ...
* ->map()
* ...
* ->unmap()
*
- * That is, ->map() must be called on a pinned buffer, same goes for ->steal().
+ * That is, ->map() must be called on a confirmed buffer,
+ * same goes for ->steal(). See below for the meaning of each
+ * operation. Also see kerneldoc in fs/pipe.c for the pipe
+ * and generic variants of these hooks.
*/
struct pipe_buf_operations {
+ /*
+ * This is set to 1, if the generic pipe read/write may coalesce
+ * data into an existing buffer. If this is set to 0, a new pipe
+ * page segment is always used for new data.
+ */
int can_merge;
+
+ /*
+ * ->map() returns a virtual address mapping of the pipe buffer.
+ * The last integer flag reflects whether this should be an atomic
+ * mapping or not. The atomic map is faster, however you can't take
+ * page faults before calling ->unmap() again. So if you need to eg
+ * access user data through copy_to/from_user(), then you must get
+ * a non-atomic map. ->map() uses the KM_USER0 atomic slot for
+ * atomic maps, so you can't map more than one pipe_buffer at once
+ * and you have to be careful if mapping another page as source
+ * or destination for a copy (IOW, it has to use something else
+ * than KM_USER0).
+ */
void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int);
+
+ /*
+ * Undoes ->map(), finishes the virtual mapping of the pipe buffer.
+ */
void (*unmap)(struct pipe_inode_info *, struct pipe_buffer *, void *);
- int (*pin)(struct pipe_inode_info *, struct pipe_buffer *);
+
+ /*
+ * ->confirm() verifies that the data in the pipe buffer is there
+ * and that the contents are good. If the pages in the pipe belong
+ * to a file system, we may need to wait for IO completion in this
+ * hook. Returns 0 for good, or a negative error value in case of
+ * error.
+ */
+ int (*confirm)(struct pipe_inode_info *, struct pipe_buffer *);
+
+ /*
+ * When the contents of this pipe buffer has been completely
+ * consumed by a reader, ->release() is called.
+ */
void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
+
+ /*
+ * Attempt to take ownership of the pipe buffer and its contents.
+ * ->steal() returns 0 for success, in which case the contents
+ * of the pipe (the buf->page) is locked and now completely owned
+ * by the caller. The page may then be transferred to a different
+ * mapping, the most often used case is insertion into different
+ * file address space cache.
+ */
int (*steal)(struct pipe_inode_info *, struct pipe_buffer *);
- void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
-};
-struct pipe_inode_info {
- wait_queue_head_t wait;
- unsigned int nrbufs, curbuf;
- struct page *tmp_page;
- unsigned int readers;
- unsigned int writers;
- unsigned int waiting_writers;
- unsigned int r_counter;
- unsigned int w_counter;
- struct fasync_struct *fasync_readers;
- struct fasync_struct *fasync_writers;
- struct inode *inode;
- struct pipe_buffer bufs[PIPE_BUFFERS];
+ /*
+ * Get a reference to the pipe buffer.
+ */
+ void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
};
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
@@ -68,39 +145,7 @@ void __free_pipe_info(struct pipe_inode_info *);
void *generic_pipe_buf_map(struct pipe_inode_info *, struct pipe_buffer *, int);
void generic_pipe_buf_unmap(struct pipe_inode_info *, struct pipe_buffer *, void *);
void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *);
-int generic_pipe_buf_pin(struct pipe_inode_info *, struct pipe_buffer *);
+int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *);
int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *);
-/*
- * splice is tied to pipes as a transport (at least for now), so we'll just
- * add the splice flags here.
- */
-#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */
-#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
- /* we may still block on the fd we splice */
- /* from/to, of course */
-#define SPLICE_F_MORE (0x04) /* expect more data */
-#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */
-
-/*
- * Passed to the actors
- */
-struct splice_desc {
- unsigned int len, total_len; /* current and remaining length */
- unsigned int flags; /* splice flags */
- struct file *file; /* file to read/write */
- loff_t pos; /* file position */
-};
-
-typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
- struct splice_desc *);
-
-extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
- loff_t *, size_t, unsigned int,
- splice_actor *);
-
-extern ssize_t __splice_from_pipe(struct pipe_inode_info *, struct file *,
- loff_t *, size_t, unsigned int,
- splice_actor *);
-
#endif
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index c3f01b3085a..30b8571e6b3 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -403,16 +403,13 @@ enum
* 1..32767 Reserved for ematches inside kernel tree
* 32768..65535 Free to use, not reliable
*/
-enum
-{
- TCF_EM_CONTAINER,
- TCF_EM_CMP,
- TCF_EM_NBYTE,
- TCF_EM_U32,
- TCF_EM_META,
- TCF_EM_TEXT,
- __TCF_EM_MAX
-};
+#define TCF_EM_CONTAINER 0
+#define TCF_EM_CMP 1
+#define TCF_EM_NBYTE 2
+#define TCF_EM_U32 3
+#define TCF_EM_META 4
+#define TCF_EM_TEXT 5
+#define TCF_EM_MAX 5
enum
{
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index d10f3533850..268c51599eb 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -101,6 +101,15 @@ struct tc_prio_qopt
__u8 priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
};
+enum
+{
+ TCA_PRIO_UNSPEC,
+ TCA_PRIO_MQ,
+ __TCA_PRIO_MAX
+};
+
+#define TCA_PRIO_MAX (__TCA_PRIO_MAX - 1)
+
/* TBF section */
struct tc_tbf_qopt
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 87545e0f0b5..273781c82e4 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -110,37 +110,67 @@ typedef int __bitwise suspend_state_t;
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4)
/**
- * struct pm_ops - Callbacks for managing platform dependent suspend states.
- * @valid: Callback to determine whether the given state can be entered.
- * Valid states are advertised in /sys/power/state but can still
- * be rejected by prepare or enter if the conditions aren't right.
- * There is a %pm_valid_only_mem function available that can be assigned
- * to this if you only implement mem sleep.
+ * struct pm_ops - Callbacks for managing platform dependent system sleep
+ * states.
*
- * @prepare: Prepare the platform for the given suspend state. Can return a
- * negative error code if necessary.
+ * @valid: Callback to determine if given system sleep state is supported by
+ * the platform.
+ * Valid (ie. supported) states are advertised in /sys/power/state. Note
+ * that it still may be impossible to enter given system sleep state if the
+ * conditions aren't right.
+ * There is the %pm_valid_only_mem function available that can be assigned
+ * to this if the platform only supports mem sleep.
*
- * @enter: Enter the given suspend state, must be assigned. Can return a
- * negative error code if necessary.
+ * @set_target: Tell the platform which system sleep state is going to be
+ * entered.
+ * @set_target() is executed right prior to suspending devices. The
+ * information conveyed to the platform code by @set_target() should be
+ * disregarded by the platform as soon as @finish() is executed and if
+ * @prepare() fails. If @set_target() fails (ie. returns nonzero),
+ * @prepare(), @enter() and @finish() will not be called by the PM core.
+ * This callback is optional. However, if it is implemented, the argument
+ * passed to @prepare(), @enter() and @finish() is meaningless and should
+ * be ignored.
*
- * @finish: Called when the system has left the given state and all devices
- * are resumed. The return value is ignored.
+ * @prepare: Prepare the platform for entering the system sleep state indicated
+ * by @set_target() or represented by the argument if @set_target() is not
+ * implemented.
+ * @prepare() is called right after devices have been suspended (ie. the
+ * appropriate .suspend() method has been executed for each device) and
+ * before the nonboot CPUs are disabled (it is executed with IRQs enabled).
+ * This callback is optional. It returns 0 on success or a negative
+ * error code otherwise, in which case the system cannot enter the desired
+ * sleep state (@enter() and @finish() will not be called in that case).
+ *
+ * @enter: Enter the system sleep state indicated by @set_target() or
+ * represented by the argument if @set_target() is not implemented.
+ * This callback is mandatory. It returns 0 on success or a negative
+ * error code otherwise, in which case the system cannot enter the desired
+ * sleep state.
+ *
+ * @finish: Called when the system has just left a sleep state, right after
+ * the nonboot CPUs have been enabled and before devices are resumed (it is
+ * executed with IRQs enabled). If @set_target() is not implemented, the
+ * argument represents the sleep state being left.
+ * This callback is optional, but should be implemented by the platforms
+ * that implement @prepare(). If implemented, it is always called after
+ * @enter() (even if @enter() fails).
*/
struct pm_ops {
int (*valid)(suspend_state_t state);
+ int (*set_target)(suspend_state_t state);
int (*prepare)(suspend_state_t state);
int (*enter)(suspend_state_t state);
int (*finish)(suspend_state_t state);
};
+extern struct pm_ops *pm_ops;
+
/**
* pm_set_ops - set platform dependent power management ops
* @pm_ops: The new power management operations to set.
*/
extern void pm_set_ops(struct pm_ops *pm_ops);
-extern struct pm_ops *pm_ops;
-extern int pm_suspend(suspend_state_t state);
-
extern int pm_valid_only_mem(suspend_state_t state);
/**
@@ -161,6 +191,8 @@ extern void arch_suspend_disable_irqs(void);
*/
extern void arch_suspend_enable_irqs(void);
+extern int pm_suspend(suspend_state_t state);
+
/*
* Device power management
*/
@@ -235,15 +267,10 @@ struct dev_pm_info {
unsigned can_wakeup:1;
#ifdef CONFIG_PM
unsigned should_wakeup:1;
- pm_message_t prev_state;
- void * saved_state;
- struct device * pm_parent;
struct list_head entry;
#endif
};
-extern void device_pm_set_parent(struct device * dev, struct device * parent);
-
extern int device_power_down(pm_message_t state);
extern void device_power_up(void);
extern void device_resume(void);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
new file mode 100644
index 00000000000..606c0957997
--- /dev/null
+++ b/include/linux/power_supply.h
@@ -0,0 +1,180 @@
+/*
+ * Universal power supply monitor class
+ *
+ * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
+ * Copyright © 2004 Szabolcs Gyurko
+ * Copyright © 2003 Ian Molton <spyro@f2s.com>
+ *
+ * Modified: 2004, Oct Szabolcs Gyurko
+ *
+ * You may use this code as per GPL version 2
+ */
+
+#ifndef __LINUX_POWER_SUPPLY_H__
+#define __LINUX_POWER_SUPPLY_H__
+
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/leds.h>
+
+/*
+ * All voltages, currents, charges, energies, time and temperatures in uV,
+ * µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise
+ * stated. It's driver's job to convert its raw values to units in which
+ * this class operates.
+ */
+
+/*
+ * For systems where the charger determines the maximum battery capacity
+ * the min and max fields should be used to present these values to user
+ * space. Unused/unknown fields will not appear in sysfs.
+ */
+
+enum {
+ POWER_SUPPLY_STATUS_UNKNOWN = 0,
+ POWER_SUPPLY_STATUS_CHARGING,
+ POWER_SUPPLY_STATUS_DISCHARGING,
+ POWER_SUPPLY_STATUS_NOT_CHARGING,
+ POWER_SUPPLY_STATUS_FULL,
+};
+
+enum {
+ POWER_SUPPLY_HEALTH_UNKNOWN = 0,
+ POWER_SUPPLY_HEALTH_GOOD,
+ POWER_SUPPLY_HEALTH_OVERHEAT,
+ POWER_SUPPLY_HEALTH_DEAD,
+ POWER_SUPPLY_HEALTH_OVERVOLTAGE,
+ POWER_SUPPLY_HEALTH_UNSPEC_FAILURE,
+};
+
+enum {
+ POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0,
+ POWER_SUPPLY_TECHNOLOGY_NiMH,
+ POWER_SUPPLY_TECHNOLOGY_LION,
+ POWER_SUPPLY_TECHNOLOGY_LIPO,
+ POWER_SUPPLY_TECHNOLOGY_LiFe,
+ POWER_SUPPLY_TECHNOLOGY_NiCd,
+};
+
+enum {
+ POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0,
+ POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL,
+ POWER_SUPPLY_CAPACITY_LEVEL_LOW,
+ POWER_SUPPLY_CAPACITY_LEVEL_NORMAL,
+ POWER_SUPPLY_CAPACITY_LEVEL_HIGH,
+ POWER_SUPPLY_CAPACITY_LEVEL_FULL,
+};
+
+enum power_supply_property {
+ /* Properties of type `int' */
+ POWER_SUPPLY_PROP_STATUS = 0,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_EMPTY,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ POWER_SUPPLY_PROP_CHARGE_AVG,
+ POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN,
+ POWER_SUPPLY_PROP_ENERGY_FULL,
+ POWER_SUPPLY_PROP_ENERGY_EMPTY,
+ POWER_SUPPLY_PROP_ENERGY_NOW,
+ POWER_SUPPLY_PROP_ENERGY_AVG,
+ POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+ POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+ /* Properties of type `const char *' */
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+enum power_supply_type {
+ POWER_SUPPLY_TYPE_BATTERY = 0,
+ POWER_SUPPLY_TYPE_UPS,
+ POWER_SUPPLY_TYPE_MAINS,
+ POWER_SUPPLY_TYPE_USB,
+};
+
+union power_supply_propval {
+ int intval;
+ const char *strval;
+};
+
+struct power_supply {
+ const char *name;
+ enum power_supply_type type;
+ enum power_supply_property *properties;
+ size_t num_properties;
+
+ char **supplied_to;
+ size_t num_supplicants;
+
+ int (*get_property)(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val);
+ void (*external_power_changed)(struct power_supply *psy);
+
+ /* For APM emulation, think legacy userspace. */
+ int use_for_apm;
+
+ /* private */
+ struct device *dev;
+ struct work_struct changed_work;
+
+#ifdef CONFIG_LEDS_TRIGGERS
+ struct led_trigger *charging_full_trig;
+ char *charging_full_trig_name;
+ struct led_trigger *charging_trig;
+ char *charging_trig_name;
+ struct led_trigger *full_trig;
+ char *full_trig_name;
+ struct led_trigger *online_trig;
+ char *online_trig_name;
+#endif
+};
+
+/*
+ * This is recommended structure to specify static power supply parameters.
+ * Generic one, parametrizable for different power supplies. Power supply
+ * class itself does not use it, but that's what implementing most platform
+ * drivers, should try reuse for consistency.
+ */
+
+struct power_supply_info {
+ const char *name;
+ int technology;
+ int voltage_max_design;
+ int voltage_min_design;
+ int charge_full_design;
+ int charge_empty_design;
+ int energy_full_design;
+ int energy_empty_design;
+ int use_for_apm;
+};
+
+extern void power_supply_changed(struct power_supply *psy);
+extern int power_supply_am_i_supplied(struct power_supply *psy);
+
+extern int power_supply_register(struct device *parent,
+ struct power_supply *psy);
+extern void power_supply_unregister(struct power_supply *psy);
+
+/* For APM emulation, think legacy userspace. */
+extern struct class *power_supply_class;
+
+#endif /* __LINUX_POWER_SUPPLY_H__ */
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index d8286db60b9..93678f57ccb 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -116,13 +116,46 @@
* attach a request to an active stripe (add_stripe_bh())
* lockdev attach-buffer unlockdev
* handle a stripe (handle_stripe())
- * lockstripe clrSTRIPE_HANDLE ... (lockdev check-buffers unlockdev) .. change-state .. record io needed unlockstripe schedule io
+ * lockstripe clrSTRIPE_HANDLE ...
+ * (lockdev check-buffers unlockdev) ..
+ * change-state ..
+ * record io/ops needed unlockstripe schedule io/ops
* release an active stripe (release_stripe())
* lockdev if (!--cnt) { if STRIPE_HANDLE, add to handle_list else add to inactive-list } unlockdev
*
* The refcount counts each thread that have activated the stripe,
* plus raid5d if it is handling it, plus one for each active request
- * on a cached buffer.
+ * on a cached buffer, and plus one if the stripe is undergoing stripe
+ * operations.
+ *
+ * Stripe operations are performed outside the stripe lock,
+ * the stripe operations are:
+ * -copying data between the stripe cache and user application buffers
+ * -computing blocks to save a disk access, or to recover a missing block
+ * -updating the parity on a write operation (reconstruct write and
+ * read-modify-write)
+ * -checking parity correctness
+ * -running i/o to disk
+ * These operations are carried out by raid5_run_ops which uses the async_tx
+ * api to (optionally) offload operations to dedicated hardware engines.
+ * When requesting an operation handle_stripe sets the pending bit for the
+ * operation and increments the count. raid5_run_ops is then run whenever
+ * the count is non-zero.
+ * There are some critical dependencies between the operations that prevent some
+ * from being requested while another is in flight.
+ * 1/ Parity check operations destroy the in cache version of the parity block,
+ * so we prevent parity dependent operations like writes and compute_blocks
+ * from starting while a check is in progress. Some dma engines can perform
+ * the check without damaging the parity block, in these cases the parity
+ * block is re-marked up to date (assuming the check was successful) and is
+ * not re-read from disk.
+ * 2/ When a write operation is requested we immediately lock the affected
+ * blocks, and mark them as not up to date. This causes new read requests
+ * to be held off, as well as parity checks and compute block operations.
+ * 3/ Once a compute block operation has been requested handle_stripe treats
+ * that block as if it is up to date. raid5_run_ops guaruntees that any
+ * operation that is dependent on the compute block result is initiated after
+ * the compute block completes.
*/
struct stripe_head {
@@ -136,15 +169,46 @@ struct stripe_head {
spinlock_t lock;
int bm_seq; /* sequence number for bitmap flushes */
int disks; /* disks in stripe */
+ /* stripe_operations
+ * @pending - pending ops flags (set for request->issue->complete)
+ * @ack - submitted ops flags (set for issue->complete)
+ * @complete - completed ops flags (set for complete)
+ * @target - STRIPE_OP_COMPUTE_BLK target
+ * @count - raid5_runs_ops is set to run when this is non-zero
+ */
+ struct stripe_operations {
+ unsigned long pending;
+ unsigned long ack;
+ unsigned long complete;
+ int target;
+ int count;
+ u32 zero_sum_result;
+ } ops;
struct r5dev {
struct bio req;
struct bio_vec vec;
struct page *page;
- struct bio *toread, *towrite, *written;
+ struct bio *toread, *read, *towrite, *written;
sector_t sector; /* sector of this page */
unsigned long flags;
} dev[1]; /* allocated with extra space depending of RAID geometry */
};
+
+/* stripe_head_state - collects and tracks the dynamic state of a stripe_head
+ * for handle_stripe. It is only valid under spin_lock(sh->lock);
+ */
+struct stripe_head_state {
+ int syncing, expanding, expanded;
+ int locked, uptodate, to_read, to_write, failed, written;
+ int to_fill, compute, req_compute, non_overwrite;
+ int failed_num;
+};
+
+/* r6_state - extra state data only relevant to r6 */
+struct r6_state {
+ int p_failed, q_failed, qd_idx, failed_num[2];
+};
+
/* Flags */
#define R5_UPTODATE 0 /* page contains current data */
#define R5_LOCKED 1 /* IO has been submitted on "req" */
@@ -158,6 +222,15 @@ struct stripe_head {
#define R5_ReWrite 9 /* have tried to over-write the readerror */
#define R5_Expanded 10 /* This block now has post-expand data */
+#define R5_Wantcompute 11 /* compute_block in progress treat as
+ * uptodate
+ */
+#define R5_Wantfill 12 /* dev->toread contains a bio that needs
+ * filling
+ */
+#define R5_Wantprexor 13 /* distinguish blocks ready for rmw from
+ * other "towrites"
+ */
/*
* Write method
*/
@@ -180,6 +253,24 @@ struct stripe_head {
#define STRIPE_EXPAND_SOURCE 10
#define STRIPE_EXPAND_READY 11
/*
+ * Operations flags (in issue order)
+ */
+#define STRIPE_OP_BIOFILL 0
+#define STRIPE_OP_COMPUTE_BLK 1
+#define STRIPE_OP_PREXOR 2
+#define STRIPE_OP_BIODRAIN 3
+#define STRIPE_OP_POSTXOR 4
+#define STRIPE_OP_CHECK 5
+#define STRIPE_OP_IO 6
+
+/* modifiers to the base operations
+ * STRIPE_OP_MOD_REPAIR_PD - compute the parity block and write it back
+ * STRIPE_OP_MOD_DMA_CHECK - parity is not corrupted by the check
+ */
+#define STRIPE_OP_MOD_REPAIR_PD 7
+#define STRIPE_OP_MOD_DMA_CHECK 8
+
+/*
* Plugging:
*
* To improve write throughput, we need to delay the handling of some
diff --git a/include/linux/raid/xor.h b/include/linux/raid/xor.h
index f0d67cbdea4..3e120587ead 100644
--- a/include/linux/raid/xor.h
+++ b/include/linux/raid/xor.h
@@ -3,9 +3,10 @@
#include <linux/raid/md.h>
-#define MAX_XOR_BLOCKS 5
+#define MAX_XOR_BLOCKS 4
-extern void xor_block(unsigned int count, unsigned int bytes, void **ptr);
+extern void xor_blocks(unsigned int count, unsigned int bytes,
+ void *dest, void **srcs);
struct xor_block_template {
struct xor_block_template *next;
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 7c1ffbab786..a8a6ea809da 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -63,7 +63,7 @@ enum rfkill_state {
* This structure represents a RF switch located on a network device.
*/
struct rfkill {
- char *name;
+ const char *name;
enum rfkill_type type;
enum rfkill_state state;
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 1fae30af91f..c91476ce314 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -261,7 +261,7 @@ enum rtattr_type_t
RTA_FLOW,
RTA_CACHEINFO,
RTA_SESSION,
- RTA_MP_ALGO,
+ RTA_MP_ALGO, /* no longer used */
RTA_TABLE,
__RTA_MAX
};
@@ -570,10 +570,16 @@ static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
}
extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
+extern int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+ struct rtattr *rta, int len);
#define rtattr_parse_nested(tb, max, rta) \
rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
+#define rtattr_parse_nested_compat(tb, max, rta, data, len) \
+({ data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
+ __rtattr_parse_nested_compat(tb, max, rta, len); })
+
extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
extern int rtnl_unicast(struct sk_buff *skb, u32 pid);
extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
@@ -638,6 +644,18 @@ extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const voi
({ (start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
(skb)->len; })
+#define RTA_NEST_COMPAT(skb, type, attrlen, data) \
+({ struct rtattr *__start = (struct rtattr *)skb_tail_pointer(skb); \
+ RTA_PUT(skb, type, attrlen, data); \
+ RTA_NEST(skb, type); \
+ __start; })
+
+#define RTA_NEST_COMPAT_END(skb, start) \
+({ struct rtattr *__nest = (void *)(start) + NLMSG_ALIGN((start)->rta_len); \
+ (start)->rta_len = skb_tail_pointer(skb) - (unsigned char *)(start); \
+ RTA_NEST_END(skb, __nest); \
+ (skb)->len; })
+
#define RTA_NEST_CANCEL(skb, start) \
({ if (start) \
skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d58e74b9836..cfb680585ab 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -34,6 +34,8 @@
#define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3
+/* SCHED_ISO: reserved but not implemented yet */
+#define SCHED_IDLE 5
#ifdef __KERNEL__
@@ -130,6 +132,26 @@ extern unsigned long nr_active(void);
extern unsigned long nr_iowait(void);
extern unsigned long weighted_cpuload(const int cpu);
+struct seq_file;
+struct cfs_rq;
+#ifdef CONFIG_SCHED_DEBUG
+extern void proc_sched_show_task(struct task_struct *p, struct seq_file *m);
+extern void proc_sched_set_task(struct task_struct *p);
+extern void
+print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now);
+#else
+static inline void
+proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+{
+}
+static inline void proc_sched_set_task(struct task_struct *p)
+{
+}
+static inline void
+print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now)
+{
+}
+#endif
/*
* Task state bitmask. NOTE! These bits are also
@@ -193,6 +215,7 @@ struct task_struct;
extern void sched_init(void);
extern void sched_init_smp(void);
extern void init_idle(struct task_struct *idle, int cpu);
+extern void init_idle_bootup_task(struct task_struct *idle);
extern cpumask_t nohz_cpu_mask;
#if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ)
@@ -479,7 +502,7 @@ struct signal_struct {
* from jiffies_to_ns(utime + stime) if sched_clock uses something
* other than jiffies.)
*/
- unsigned long long sched_time;
+ unsigned long long sum_sched_runtime;
/*
* We don't bother to synchronize most readers of this at all,
@@ -521,31 +544,6 @@ struct signal_struct {
#define SIGNAL_STOP_CONTINUED 0x00000004 /* SIGCONT since WCONTINUED reap */
#define SIGNAL_GROUP_EXIT 0x00000008 /* group exit in progress */
-
-/*
- * Priority of a process goes from 0..MAX_PRIO-1, valid RT
- * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
- * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
- * values are inverted: lower p->prio value means higher priority.
- *
- * The MAX_USER_RT_PRIO value allows the actual maximum
- * RT priority to be separate from the value exported to
- * user-space. This allows kernel threads to set their
- * priority to a value higher than any user task. Note:
- * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
- */
-
-#define MAX_USER_RT_PRIO 100
-#define MAX_RT_PRIO MAX_USER_RT_PRIO
-
-#define MAX_PRIO (MAX_RT_PRIO + 40)
-
-#define rt_prio(prio) unlikely((prio) < MAX_RT_PRIO)
-#define rt_task(p) rt_prio((p)->prio)
-#define batch_task(p) (unlikely((p)->policy == SCHED_BATCH))
-#define is_rt_policy(p) ((p) != SCHED_NORMAL && (p) != SCHED_BATCH)
-#define has_rt_policy(p) unlikely(is_rt_policy((p)->policy))
-
/*
* Some day this will be a full-fledged user tracking system..
*/
@@ -583,13 +581,13 @@ struct reclaim_state;
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
struct sched_info {
/* cumulative counters */
- unsigned long cpu_time, /* time spent on the cpu */
- run_delay, /* time spent waiting on a runqueue */
- pcnt; /* # of timeslices run on this cpu */
+ unsigned long pcnt; /* # of times run on this cpu */
+ unsigned long long cpu_time, /* time spent on the cpu */
+ run_delay; /* time spent waiting on a runqueue */
/* timestamps */
- unsigned long last_arrival, /* when we last ran on a cpu */
- last_queued; /* when we were last queued to run */
+ unsigned long long last_arrival,/* when we last ran on a cpu */
+ last_queued; /* when we were last queued to run */
};
#endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */
@@ -639,18 +637,24 @@ static inline int sched_info_on(void)
#endif
}
-enum idle_type
-{
- SCHED_IDLE,
- NOT_IDLE,
- NEWLY_IDLE,
- MAX_IDLE_TYPES
+enum cpu_idle_type {
+ CPU_IDLE,
+ CPU_NOT_IDLE,
+ CPU_NEWLY_IDLE,
+ CPU_MAX_IDLE_TYPES
};
/*
* sched-domains (multiprocessor balancing) declarations:
*/
-#define SCHED_LOAD_SCALE 128UL /* increase resolution of load */
+
+/*
+ * Increase resolution of nice-level calculations:
+ */
+#define SCHED_LOAD_SHIFT 10
+#define SCHED_LOAD_SCALE (1L << SCHED_LOAD_SHIFT)
+
+#define SCHED_LOAD_SCALE_FUZZ (SCHED_LOAD_SCALE >> 5)
#ifdef CONFIG_SMP
#define SD_LOAD_BALANCE 1 /* Do load balancing on this domain. */
@@ -719,14 +723,14 @@ struct sched_domain {
#ifdef CONFIG_SCHEDSTATS
/* load_balance() stats */
- unsigned long lb_cnt[MAX_IDLE_TYPES];
- unsigned long lb_failed[MAX_IDLE_TYPES];
- unsigned long lb_balanced[MAX_IDLE_TYPES];
- unsigned long lb_imbalance[MAX_IDLE_TYPES];
- unsigned long lb_gained[MAX_IDLE_TYPES];
- unsigned long lb_hot_gained[MAX_IDLE_TYPES];
- unsigned long lb_nobusyg[MAX_IDLE_TYPES];
- unsigned long lb_nobusyq[MAX_IDLE_TYPES];
+ unsigned long lb_cnt[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_failed[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_balanced[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_imbalance[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_gained[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_hot_gained[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_nobusyg[CPU_MAX_IDLE_TYPES];
+ unsigned long lb_nobusyq[CPU_MAX_IDLE_TYPES];
/* Active load balancing */
unsigned long alb_cnt;
@@ -753,12 +757,6 @@ struct sched_domain {
extern int partition_sched_domains(cpumask_t *partition1,
cpumask_t *partition2);
-/*
- * Maximum cache size the migration-costs auto-tuning code will
- * search from:
- */
-extern unsigned int max_cache_size;
-
#endif /* CONFIG_SMP */
@@ -809,14 +807,86 @@ struct mempolicy;
struct pipe_inode_info;
struct uts_namespace;
-enum sleep_type {
- SLEEP_NORMAL,
- SLEEP_NONINTERACTIVE,
- SLEEP_INTERACTIVE,
- SLEEP_INTERRUPTED,
+struct rq;
+struct sched_domain;
+
+struct sched_class {
+ struct sched_class *next;
+
+ void (*enqueue_task) (struct rq *rq, struct task_struct *p,
+ int wakeup, u64 now);
+ void (*dequeue_task) (struct rq *rq, struct task_struct *p,
+ int sleep, u64 now);
+ void (*yield_task) (struct rq *rq, struct task_struct *p);
+
+ void (*check_preempt_curr) (struct rq *rq, struct task_struct *p);
+
+ struct task_struct * (*pick_next_task) (struct rq *rq, u64 now);
+ void (*put_prev_task) (struct rq *rq, struct task_struct *p, u64 now);
+
+ int (*load_balance) (struct rq *this_rq, int this_cpu,
+ struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *total_load_moved);
+
+ void (*set_curr_task) (struct rq *rq);
+ void (*task_tick) (struct rq *rq, struct task_struct *p);
+ void (*task_new) (struct rq *rq, struct task_struct *p);
};
-struct prio_array;
+struct load_weight {
+ unsigned long weight, inv_weight;
+};
+
+/*
+ * CFS stats for a schedulable entity (task, task-group etc)
+ *
+ * Current field usage histogram:
+ *
+ * 4 se->block_start
+ * 4 se->run_node
+ * 4 se->sleep_start
+ * 4 se->sleep_start_fair
+ * 6 se->load.weight
+ * 7 se->delta_fair
+ * 15 se->wait_runtime
+ */
+struct sched_entity {
+ long wait_runtime;
+ unsigned long delta_fair_run;
+ unsigned long delta_fair_sleep;
+ unsigned long delta_exec;
+ s64 fair_key;
+ struct load_weight load; /* for load-balancing */
+ struct rb_node run_node;
+ unsigned int on_rq;
+
+ u64 wait_start_fair;
+ u64 wait_start;
+ u64 exec_start;
+ u64 sleep_start;
+ u64 sleep_start_fair;
+ u64 block_start;
+ u64 sleep_max;
+ u64 block_max;
+ u64 exec_max;
+ u64 wait_max;
+ u64 last_ran;
+
+ u64 sum_exec_runtime;
+ s64 sum_wait_runtime;
+ s64 sum_sleep_runtime;
+ unsigned long wait_runtime_overruns;
+ unsigned long wait_runtime_underruns;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ struct sched_entity *parent;
+ /* rq on which this entity is (to be) queued: */
+ struct cfs_rq *cfs_rq;
+ /* rq "owned" by this entity/group: */
+ struct cfs_rq *my_q;
+#endif
+};
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
@@ -832,23 +902,20 @@ struct task_struct {
int oncpu;
#endif
#endif
- int load_weight; /* for niceness load balancing purposes */
+
int prio, static_prio, normal_prio;
struct list_head run_list;
- struct prio_array *array;
+ struct sched_class *sched_class;
+ struct sched_entity se;
unsigned short ioprio;
#ifdef CONFIG_BLK_DEV_IO_TRACE
unsigned int btrace_seq;
#endif
- unsigned long sleep_avg;
- unsigned long long timestamp, last_ran;
- unsigned long long sched_time; /* sched_clock time spent running */
- enum sleep_type sleep_type;
unsigned int policy;
cpumask_t cpus_allowed;
- unsigned int time_slice, first_time_slice;
+ unsigned int time_slice;
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
struct sched_info sched_info;
@@ -1078,6 +1145,37 @@ struct task_struct {
#endif
};
+/*
+ * Priority of a process goes from 0..MAX_PRIO-1, valid RT
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
+ * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
+ * values are inverted: lower p->prio value means higher priority.
+ *
+ * The MAX_USER_RT_PRIO value allows the actual maximum
+ * RT priority to be separate from the value exported to
+ * user-space. This allows kernel threads to set their
+ * priority to a value higher than any user task. Note:
+ * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
+ */
+
+#define MAX_USER_RT_PRIO 100
+#define MAX_RT_PRIO MAX_USER_RT_PRIO
+
+#define MAX_PRIO (MAX_RT_PRIO + 40)
+#define DEFAULT_PRIO (MAX_RT_PRIO + 20)
+
+static inline int rt_prio(int prio)
+{
+ if (unlikely(prio < MAX_RT_PRIO))
+ return 1;
+ return 0;
+}
+
+static inline int rt_task(struct task_struct *p)
+{
+ return rt_prio(p->prio);
+}
+
static inline pid_t process_group(struct task_struct *tsk)
{
return tsk->signal->pgrp;
@@ -1162,6 +1260,7 @@ static inline void put_task_struct(struct task_struct *t)
/* Not implemented yet, only for 486*/
#define PF_STARTING 0x00000002 /* being created */
#define PF_EXITING 0x00000004 /* getting shut down */
+#define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */
#define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */
#define PF_SUPERPRIV 0x00000100 /* used super-user privileges */
#define PF_DUMPCORE 0x00000200 /* dumped core */
@@ -1222,7 +1321,7 @@ static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
extern unsigned long long sched_clock(void);
extern unsigned long long
-current_sched_time(const struct task_struct *current_task);
+task_sched_runtime(struct task_struct *task);
/* sched_exec is called by processes performing an exec */
#ifdef CONFIG_SMP
@@ -1231,6 +1330,8 @@ extern void sched_exec(void);
#define sched_exec() {}
#endif
+extern void sched_clock_unstable_event(void);
+
#ifdef CONFIG_HOTPLUG_CPU
extern void idle_task_exit(void);
#else
@@ -1239,6 +1340,14 @@ static inline void idle_task_exit(void) {}
extern void sched_idle_next(void);
+extern unsigned int sysctl_sched_granularity;
+extern unsigned int sysctl_sched_wakeup_granularity;
+extern unsigned int sysctl_sched_batch_wakeup_granularity;
+extern unsigned int sysctl_sched_stat_granularity;
+extern unsigned int sysctl_sched_runtime_limit;
+extern unsigned int sysctl_sched_child_runs_first;
+extern unsigned int sysctl_sched_features;
+
#ifdef CONFIG_RT_MUTEXES
extern int rt_mutex_getprio(struct task_struct *p);
extern void rt_mutex_setprio(struct task_struct *p, int prio);
@@ -1316,8 +1425,8 @@ extern void FASTCALL(wake_up_new_task(struct task_struct * tsk,
#else
static inline void kick_process(struct task_struct *tsk) { }
#endif
-extern void FASTCALL(sched_fork(struct task_struct * p, int clone_flags));
-extern void FASTCALL(sched_exit(struct task_struct * p));
+extern void sched_fork(struct task_struct *p, int clone_flags);
+extern void sched_dead(struct task_struct *p);
extern int in_group_p(gid_t);
extern int in_egroup_p(gid_t);
@@ -1405,7 +1514,7 @@ extern struct mm_struct * mm_alloc(void);
extern void FASTCALL(__mmdrop(struct mm_struct *));
static inline void mmdrop(struct mm_struct * mm)
{
- if (atomic_dec_and_test(&mm->mm_count))
+ if (unlikely(atomic_dec_and_test(&mm->mm_count)))
__mmdrop(mm);
}
@@ -1637,10 +1746,7 @@ static inline unsigned int task_cpu(const struct task_struct *p)
return task_thread_info(p)->cpu;
}
-static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
-{
- task_thread_info(p)->cpu = cpu;
-}
+extern void set_task_cpu(struct task_struct *p, unsigned int cpu);
#else
diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
index b02308ee766..3ee412bc00e 100644
--- a/include/linux/screen_info.h
+++ b/include/linux/screen_info.h
@@ -10,7 +10,7 @@
struct screen_info {
u8 orig_x; /* 0x00 */
u8 orig_y; /* 0x01 */
- u16 dontuse1; /* 0x02 -- EXT_MEM_K sits here */
+ u16 ext_mem_k; /* 0x02 */
u16 orig_video_page; /* 0x04 */
u8 orig_video_mode; /* 0x06 */
u8 orig_video_cols; /* 0x07 */
@@ -27,7 +27,7 @@ struct screen_info {
u16 lfb_depth; /* 0x16 */
u32 lfb_base; /* 0x18 */
u32 lfb_size; /* 0x1c */
- u16 dontuse2, dontuse3; /* 0x20 -- CL_MAGIC and CL_OFFSET here */
+ u16 cl_magic, cl_offset; /* 0x20 */
u16 lfb_linelength; /* 0x24 */
u8 red_size; /* 0x26 */
u8 red_pos; /* 0x27 */
@@ -42,9 +42,8 @@ struct screen_info {
u16 pages; /* 0x32 */
u16 vesa_attributes; /* 0x34 */
u32 capabilities; /* 0x36 */
- /* 0x3a -- 0x3b reserved for future expansion */
- /* 0x3c -- 0x3f micro stack for relocatable kernels */
-};
+ u8 _reserved[6]; /* 0x3a */
+} __attribute__((packed));
extern struct screen_info screen_info;
diff --git a/include/linux/security.h b/include/linux/security.h
index 9eb9e0fe033..c11dc8aa035 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -71,6 +71,7 @@ struct xfrm_user_sec_ctx;
extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
extern int cap_netlink_recv(struct sk_buff *skb, int cap);
+extern unsigned long mmap_min_addr;
/*
* Values used in the task_security_ops calls
*/
@@ -1241,8 +1242,9 @@ struct security_operations {
int (*file_ioctl) (struct file * file, unsigned int cmd,
unsigned long arg);
int (*file_mmap) (struct file * file,
- unsigned long reqprot,
- unsigned long prot, unsigned long flags);
+ unsigned long reqprot, unsigned long prot,
+ unsigned long flags, unsigned long addr,
+ unsigned long addr_only);
int (*file_mprotect) (struct vm_area_struct * vma,
unsigned long reqprot,
unsigned long prot);
@@ -1814,9 +1816,12 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
static inline int security_file_mmap (struct file *file, unsigned long reqprot,
unsigned long prot,
- unsigned long flags)
+ unsigned long flags,
+ unsigned long addr,
+ unsigned long addr_only)
{
- return security_ops->file_mmap (file, reqprot, prot, flags);
+ return security_ops->file_mmap (file, reqprot, prot, flags, addr,
+ addr_only);
}
static inline int security_file_mprotect (struct vm_area_struct *vma,
@@ -2489,7 +2494,9 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
static inline int security_file_mmap (struct file *file, unsigned long reqprot,
unsigned long prot,
- unsigned long flags)
+ unsigned long flags,
+ unsigned long addr,
+ unsigned long addr_only)
{
return 0;
}
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 3e3cccbb1ca..83783ab0f55 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -50,5 +50,16 @@ int seq_release_private(struct inode *, struct file *);
#define SEQ_START_TOKEN ((void *)1)
+/*
+ * Helpers for iteration over list_head-s in seq_files
+ */
+
+extern struct list_head *seq_list_start(struct list_head *head,
+ loff_t pos);
+extern struct list_head *seq_list_start_head(struct list_head *head,
+ loff_t pos);
+extern struct list_head *seq_list_next(void *v, struct list_head *head,
+ loff_t *ppos);
+
#endif
#endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index a3ac4c89683..7f2c99d66e9 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -152,6 +152,7 @@
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/mutex.h>
+#include <linux/sysrq.h>
struct uart_port;
struct uart_info;
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 1ebf0455e22..d9377ce9ffd 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -209,5 +209,6 @@ static inline void serio_unpin_driver(struct serio *serio)
#define SERIO_PENMOUNT 0x31
#define SERIO_TOUCHRIGHT 0x32
#define SERIO_TOUCHWIN 0x33
+#define SERIO_TAOSEVM 0x34
#endif
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e7367c74e1b..ce256438e61 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -65,13 +65,20 @@
* is able to produce some skb->csum, it MUST use COMPLETE,
* not UNNECESSARY.
*
+ * PARTIAL: identical to the case for output below. This may occur
+ * on a packet received directly from another Linux OS, e.g.,
+ * a virtualised Linux kernel on the same host. The packet can
+ * be treated in the same way as UNNECESSARY except that on
+ * output (i.e., forwarding) the checksum must be filled in
+ * by the OS or the hardware.
+ *
* B. Checksumming on output.
*
* NONE: skb is checksummed by protocol or csum is not required.
*
* PARTIAL: device is required to csum packet as seen by hard_start_xmit
- * from skb->transport_header to the end and to record the checksum
- * at skb->transport_header + skb->csum.
+ * from skb->csum_start to the end and to record the checksum
+ * at skb->csum_start + skb->csum_offset.
*
* Device must show its capabilities in dev->features, set
* at device setup time.
@@ -82,6 +89,7 @@
* TCP/UDP over IPv4. Sigh. Vendors like this
* way by an unknown reason. Though, see comment above
* about CHECKSUM_UNNECESSARY. 8)
+ * NETIF_F_IPV6_CSUM about as dumb as the last one but does IPv6 instead.
*
* Any questions? No questions, good. --ANK
*/
@@ -147,8 +155,8 @@ struct skb_shared_info {
/* We divide dataref into two halves. The higher 16 bits hold references
* to the payload part of skb->data. The lower 16 bits hold references to
- * the entire skb->data. It is up to the users of the skb to agree on
- * where the payload starts.
+ * the entire skb->data. A clone of a headerless skb holds the length of
+ * the header in skb->hdr_len.
*
* All users must obey the rule that the skb->data reference count must be
* greater than or equal to the payload reference count.
@@ -196,7 +204,6 @@ typedef unsigned char *sk_buff_data_t;
* @sk: Socket we are owned by
* @tstamp: Time we arrived
* @dev: Device we arrived on/are leaving by
- * @iif: ifindex of device we arrived on
* @transport_header: Transport layer header
* @network_header: Network layer header
* @mac_header: Link layer header
@@ -206,6 +213,7 @@ typedef unsigned char *sk_buff_data_t;
* @len: Length of actual data
* @data_len: Data length
* @mac_len: Length of link layer header
+ * @hdr_len: writable header length of cloned skb
* @csum: Checksum (must include start/offset pair)
* @csum_start: Offset from skb->head where checksumming should start
* @csum_offset: Offset from csum_start where checksum should be stored
@@ -227,9 +235,12 @@ typedef unsigned char *sk_buff_data_t;
* @mark: Generic packet mark
* @nfct: Associated connection, if any
* @ipvs_property: skbuff is owned by ipvs
+ * @nf_trace: netfilter packet trace flag
* @nfctinfo: Relationship of this skb to the connection
* @nfct_reasm: netfilter conntrack re-assembly pointer
* @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
+ * @iif: ifindex of device we arrived on
+ * @queue_mapping: Queue mapping for multiqueue devices
* @tc_index: Traffic control index
* @tc_verd: traffic control verdict
* @dma_cookie: a cookie to one of several possible DMA operations
@@ -245,8 +256,6 @@ struct sk_buff {
struct sock *sk;
ktime_t tstamp;
struct net_device *dev;
- int iif;
- /* 4 byte hole on 64 bit*/
struct dst_entry *dst;
struct sec_path *sp;
@@ -260,8 +269,9 @@ struct sk_buff {
char cb[48];
unsigned int len,
- data_len,
- mac_len;
+ data_len;
+ __u16 mac_len,
+ hdr_len;
union {
__wsum csum;
struct {
@@ -277,7 +287,8 @@ struct sk_buff {
nfctinfo:3;
__u8 pkt_type:3,
fclone:2,
- ipvs_property:1;
+ ipvs_property:1,
+ nf_trace:1;
__be16 protocol;
void (*destructor)(struct sk_buff *skb);
@@ -288,12 +299,18 @@ struct sk_buff {
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
+
+ int iif;
+ __u16 queue_mapping;
+
#ifdef CONFIG_NET_SCHED
__u16 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
__u16 tc_verd; /* traffic control verdict */
#endif
#endif
+ /* 2 byte hole */
+
#ifdef CONFIG_NET_DMA
dma_cookie_t dma_cookie;
#endif
@@ -1322,6 +1339,20 @@ static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev,
}
/**
+ * skb_clone_writable - is the header of a clone writable
+ * @skb: buffer to check
+ * @len: length up to which to write
+ *
+ * Returns true if modifying the header part of the cloned buffer
+ * does not requires the data to be copied.
+ */
+static inline int skb_clone_writable(struct sk_buff *skb, int len)
+{
+ return !skb_header_cloned(skb) &&
+ skb_headroom(skb) + len <= skb->hdr_len;
+}
+
+/**
* skb_cow - copy header of skb when it is required
* @skb: buffer to cow
* @headroom: needed headroom
@@ -1579,6 +1610,10 @@ static inline ktime_t net_timedelta(ktime_t t)
return ktime_sub(ktime_get_real(), t);
}
+static inline ktime_t net_invalid_timestamp(void)
+{
+ return ktime_set(0, 0);
+}
extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
@@ -1604,7 +1639,7 @@ static inline int skb_csum_unnecessary(const struct sk_buff *skb)
* if skb->ip_summed is CHECKSUM_UNNECESSARY which indicates that the
* hardware has already verified the correctness of the checksum.
*/
-static inline unsigned int skb_checksum_complete(struct sk_buff *skb)
+static inline __sum16 skb_checksum_complete(struct sk_buff *skb)
{
return skb_csum_unnecessary(skb) ?
0 : __skb_checksum_complete(skb);
@@ -1705,6 +1740,20 @@ static inline void skb_init_secmark(struct sk_buff *skb)
{ }
#endif
+static inline void skb_set_queue_mapping(struct sk_buff *skb, u16 queue_mapping)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ skb->queue_mapping = queue_mapping;
+#endif
+}
+
+static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_buff *from)
+{
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+ to->queue_mapping = from->queue_mapping;
+#endif
+}
+
static inline int skb_is_gso(const struct sk_buff *skb)
{
return skb_shinfo(skb)->gso_size;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index a015236cc57..cebcd3833c7 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -82,8 +82,8 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep,
* to do various tricks to work around compiler limitations in order to
* ensure proper constant folding.
*/
-#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT) <= 25 ? \
- (MAX_ORDER + PAGE_SHIFT) : 25)
+#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
+ (MAX_ORDER + PAGE_SHIFT - 1) : 25)
#define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_HIGH)
#define KMALLOC_MAX_ORDER (KMALLOC_SHIFT_HIGH - PAGE_SHIFT)
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 0764c829d96..6207a3d8da7 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -28,7 +28,7 @@ struct kmem_cache {
int size; /* The size of an object including meta data */
int objsize; /* The size of an object without meta data */
int offset; /* Free pointer offset. */
- unsigned int order;
+ int order;
/*
* Avoid an extra cache line for UP, SMP and for the node local to
@@ -56,7 +56,13 @@ struct kmem_cache {
/*
* Kmalloc subsystem.
*/
-#define KMALLOC_SHIFT_LOW 3
+#if defined(ARCH_KMALLOC_MINALIGN) && ARCH_KMALLOC_MINALIGN > 8
+#define KMALLOC_MIN_SIZE ARCH_KMALLOC_MINALIGN
+#else
+#define KMALLOC_MIN_SIZE 8
+#endif
+
+#define KMALLOC_SHIFT_LOW ilog2(KMALLOC_MIN_SIZE)
/*
* We keep the general caches in an array of slab caches that are used for
@@ -70,15 +76,15 @@ extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
*/
static inline int kmalloc_index(size_t size)
{
- /*
- * We should return 0 if size == 0 but we use the smallest object
- * here for SLAB legacy reasons.
- */
- WARN_ON_ONCE(size == 0);
+ if (!size)
+ return 0;
if (size > KMALLOC_MAX_SIZE)
return -1;
+ if (size <= KMALLOC_MIN_SIZE)
+ return KMALLOC_SHIFT_LOW;
+
if (size > 64 && size <= 96)
return 1;
if (size > 128 && size <= 192)
@@ -153,13 +159,25 @@ static inline struct kmem_cache *kmalloc_slab(size_t size)
#define SLUB_DMA 0
#endif
+
+/*
+ * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
+ *
+ * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
+ *
+ * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can.
+ * Both make kfree a no-op.
+ */
+#define ZERO_SIZE_PTR ((void *)16)
+
+
static inline void *kmalloc(size_t size, gfp_t flags)
{
if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_alloc(s, flags);
} else
@@ -172,7 +190,7 @@ static inline void *kzalloc(size_t size, gfp_t flags)
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_zalloc(s, flags);
} else
@@ -188,7 +206,7 @@ static inline void *kmalloc_node(size_t size, gfp_t flags, int node)
struct kmem_cache *s = kmalloc_slab(size);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return kmem_cache_alloc_node(s, flags, node);
} else
diff --git a/include/linux/sm501-regs.h b/include/linux/sm501-regs.h
index cc9be4a1186..014e73b31fc 100644
--- a/include/linux/sm501-regs.h
+++ b/include/linux/sm501-regs.h
@@ -64,6 +64,11 @@
#define SM501_DEBUG_CONTROL (0x000034)
/* power management */
+#define SM501_POWERMODE_P2X_SRC (1<<29)
+#define SM501_POWERMODE_V2X_SRC (1<<20)
+#define SM501_POWERMODE_M_SRC (1<<12)
+#define SM501_POWERMODE_M1_SRC (1<<4)
+
#define SM501_CURRENT_GATE (0x000038)
#define SM501_CURRENT_CLOCK (0x00003C)
#define SM501_POWER_MODE_0_GATE (0x000040)
@@ -104,6 +109,9 @@
#define SM501_DEVICEID (0x000060)
/* 0x050100A0 */
+#define SM501_DEVICEID_SM501 (0x05010000)
+#define SM501_DEVICEID_IDMASK (0xffff0000)
+
#define SM501_PLLCLOCK_COUNT (0x000064)
#define SM501_MISC_TIMING (0x000068)
#define SM501_CURRENT_SDRAM_CLOCK (0x00006C)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 6e7c9483a6a..fe195c97a89 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -287,6 +287,7 @@ struct ucred {
#define SOL_NETLINK 270
#define SOL_TIPC 271
#define SOL_RXRPC 272
+#define SOL_PPPOL2TP 273
/* IPX options */
#define IPX_TYPE 1
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index b6bedc3ee95..1be5ea05947 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -341,9 +341,14 @@ extern struct spi_master *spi_busnum_to_master(u16 busnum);
* chip transactions together.
*
* (ii) When the transfer is the last one in the message, the chip may
- * stay selected until the next transfer. This is purely a performance
- * hint; the controller driver may need to select a different device
- * for the next message.
+ * stay selected until the next transfer. On multi-device SPI busses
+ * with nothing blocking messages going to other devices, this is just
+ * a performance hint; starting a message to another device deselects
+ * this one. But in other cases, this can be used to ensure correctness.
+ * Some devices need protocol transactions to be built from a series of
+ * spi_message submissions, where the content of one message is determined
+ * by the results of previous messages and where the whole transaction
+ * ends when the chipselect goes intactive.
*
* The code that submits an spi_message (and its spi_transfers)
* to the lower layers is responsible for managing its memory.
@@ -480,14 +485,15 @@ static inline void spi_message_free(struct spi_message *m)
/**
* spi_setup - setup SPI mode and clock rate
* @spi: the device whose settings are being modified
- * Context: can sleep
+ * Context: can sleep, and no requests are queued to the device
*
* SPI protocol drivers may need to update the transfer mode if the
- * device doesn't work with the mode 0 default. They may likewise need
+ * device doesn't work with its default. They may likewise need
* to update clock rates or word sizes from initial values. This function
* changes those settings, and must be called from a context that can sleep.
- * The changes take effect the next time the device is selected and data
- * is transferred to or from it.
+ * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
+ * effect the next time the device is selected and data is transferred to
+ * or from it. When this function returns, the spi device is deselected.
*
* Note that this call will fail if the protocol driver specifies an option
* that the underlying controller or its driver does not support. For
diff --git a/include/linux/splice.h b/include/linux/splice.h
new file mode 100644
index 00000000000..33e447f98a5
--- /dev/null
+++ b/include/linux/splice.h
@@ -0,0 +1,73 @@
+/*
+ * Function declerations and data structures related to the splice
+ * implementation.
+ *
+ * Copyright (C) 2007 Jens Axboe <jens.axboe@oracle.com>
+ *
+ */
+#ifndef SPLICE_H
+#define SPLICE_H
+
+#include <linux/pipe_fs_i.h>
+
+/*
+ * splice is tied to pipes as a transport (at least for now), so we'll just
+ * add the splice flags here.
+ */
+#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */
+#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */
+ /* we may still block on the fd we splice */
+ /* from/to, of course */
+#define SPLICE_F_MORE (0x04) /* expect more data */
+#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */
+
+/*
+ * Passed to the actors
+ */
+struct splice_desc {
+ unsigned int len, total_len; /* current and remaining length */
+ unsigned int flags; /* splice flags */
+ /*
+ * actor() private data
+ */
+ union {
+ void __user *userptr; /* memory to write to */
+ struct file *file; /* file to read/write */
+ void *data; /* cookie */
+ } u;
+ loff_t pos; /* file position */
+};
+
+struct partial_page {
+ unsigned int offset;
+ unsigned int len;
+ unsigned long private;
+};
+
+/*
+ * Passed to splice_to_pipe
+ */
+struct splice_pipe_desc {
+ struct page **pages; /* page map */
+ struct partial_page *partial; /* pages[] may not be contig */
+ int nr_pages; /* number of pages in map */
+ unsigned int flags; /* splice flags */
+ const struct pipe_buf_operations *ops;/* ops associated with output pipe */
+};
+
+typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *,
+ struct splice_desc *);
+typedef int (splice_direct_actor)(struct pipe_inode_info *,
+ struct splice_desc *);
+
+extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *,
+ loff_t *, size_t, unsigned int,
+ splice_actor *);
+extern ssize_t __splice_from_pipe(struct pipe_inode_info *,
+ struct splice_desc *, splice_actor *);
+extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ struct splice_pipe_desc *);
+extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+ splice_direct_actor *);
+
+#endif
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 534cdc7be58..7a69ca3beba 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -16,6 +16,7 @@
#include <linux/sunrpc/xdr.h>
#include <asm/atomic.h>
+#include <linux/rcupdate.h>
/* size of the nodename buffer */
#define UNX_MAXNODENAME 32
@@ -30,22 +31,28 @@ struct auth_cred {
/*
* Client user credentials
*/
+struct rpc_auth;
+struct rpc_credops;
struct rpc_cred {
struct hlist_node cr_hash; /* hash chain */
- struct rpc_credops * cr_ops;
- unsigned long cr_expire; /* when to gc */
- atomic_t cr_count; /* ref count */
- unsigned short cr_flags; /* various flags */
+ struct list_head cr_lru; /* lru garbage collection */
+ struct rcu_head cr_rcu;
+ struct rpc_auth * cr_auth;
+ const struct rpc_credops *cr_ops;
#ifdef RPC_DEBUG
unsigned long cr_magic; /* 0x0f4aa4f0 */
#endif
+ unsigned long cr_expire; /* when to gc */
+ unsigned long cr_flags; /* various flags */
+ atomic_t cr_count; /* ref count */
uid_t cr_uid;
/* per-flavor data */
};
-#define RPCAUTH_CRED_NEW 0x0001
-#define RPCAUTH_CRED_UPTODATE 0x0002
+#define RPCAUTH_CRED_NEW 0
+#define RPCAUTH_CRED_UPTODATE 1
+#define RPCAUTH_CRED_HASHED 2
#define RPCAUTH_CRED_MAGIC 0x0f4aa4f0
@@ -56,10 +63,10 @@ struct rpc_cred {
#define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1)
struct rpc_cred_cache {
struct hlist_head hashtable[RPC_CREDCACHE_NR];
- unsigned long nextgc; /* next garbage collection */
- unsigned long expire; /* cache expiry interval */
+ spinlock_t lock;
};
+struct rpc_authops;
struct rpc_auth {
unsigned int au_cslack; /* call cred size estimate */
/* guess at number of u32's auth adds before
@@ -69,7 +76,7 @@ struct rpc_auth {
unsigned int au_verfsize;
unsigned int au_flags; /* various flags */
- struct rpc_authops * au_ops; /* operations */
+ const struct rpc_authops *au_ops; /* operations */
rpc_authflavor_t au_flavor; /* pseudoflavor (note may
* differ from the flavor in
* au_ops->au_flavor in gss
@@ -115,17 +122,19 @@ struct rpc_credops {
void *, __be32 *, void *);
};
-extern struct rpc_authops authunix_ops;
-extern struct rpc_authops authnull_ops;
-#ifdef CONFIG_SUNRPC_SECURE
-extern struct rpc_authops authdes_ops;
-#endif
+extern const struct rpc_authops authunix_ops;
+extern const struct rpc_authops authnull_ops;
+
+void __init rpc_init_authunix(void);
+void __init rpcauth_init_module(void);
+void __exit rpcauth_remove_module(void);
-int rpcauth_register(struct rpc_authops *);
-int rpcauth_unregister(struct rpc_authops *);
+int rpcauth_register(const struct rpc_authops *);
+int rpcauth_unregister(const struct rpc_authops *);
struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
-void rpcauth_destroy(struct rpc_auth *);
+void rpcauth_release(struct rpc_auth *);
struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
+void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
struct rpc_cred * rpcauth_bindcred(struct rpc_task *);
void rpcauth_holdcred(struct rpc_task *);
@@ -138,8 +147,9 @@ int rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
int rpcauth_refreshcred(struct rpc_task *);
void rpcauth_invalcred(struct rpc_task *);
int rpcauth_uptodatecred(struct rpc_task *);
-int rpcauth_init_credcache(struct rpc_auth *, unsigned long);
-void rpcauth_free_credcache(struct rpc_auth *);
+int rpcauth_init_credcache(struct rpc_auth *);
+void rpcauth_destroy_credcache(struct rpc_auth *);
+void rpcauth_clear_credcache(struct rpc_cred_cache *);
static inline
struct rpc_cred * get_rpccred(struct rpc_cred *cred)
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 2db2fbf3494..67658e17a37 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -75,6 +75,7 @@ struct gss_cl_ctx {
struct xdr_netobj gc_wire_ctx;
u32 gc_win;
unsigned long gc_expiry;
+ struct rcu_head gc_rcu;
};
struct gss_upcall_msg;
@@ -85,11 +86,6 @@ struct gss_cred {
struct gss_upcall_msg *gc_upcall;
};
-#define gc_uid gc_base.cr_uid
-#define gc_count gc_base.cr_count
-#define gc_flags gc_base.cr_flags
-#define gc_expire gc_base.cr_expire
-
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_AUTH_GSS_H */
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 66611423c8e..c0d9d14983b 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -24,8 +24,10 @@ struct rpc_inode;
* The high-level client handle
*/
struct rpc_clnt {
- atomic_t cl_count; /* Number of clones */
- atomic_t cl_users; /* number of references */
+ struct kref cl_kref; /* Number of references */
+ struct list_head cl_clients; /* Global list of clients */
+ struct list_head cl_tasks; /* List of tasks */
+ spinlock_t cl_lock; /* spinlock */
struct rpc_xprt * cl_xprt; /* transport */
struct rpc_procinfo * cl_procinfo; /* procedure info */
u32 cl_prog, /* RPC program number */
@@ -41,9 +43,7 @@ struct rpc_clnt {
unsigned int cl_softrtry : 1,/* soft timeouts */
cl_intr : 1,/* interruptible */
cl_discrtry : 1,/* disconnect before retry */
- cl_autobind : 1,/* use getport() */
- cl_oneshot : 1,/* dispose after use */
- cl_dead : 1;/* abandoned */
+ cl_autobind : 1;/* use getport() */
struct rpc_rtt * cl_rtt; /* RTO estimator data */
@@ -98,6 +98,7 @@ struct rpc_create_args {
int protocol;
struct sockaddr *address;
size_t addrsize;
+ struct sockaddr *saddress;
struct rpc_timeout *timeout;
char *servername;
struct rpc_program *program;
@@ -110,20 +111,20 @@ struct rpc_create_args {
#define RPC_CLNT_CREATE_HARDRTRY (1UL << 0)
#define RPC_CLNT_CREATE_INTR (1UL << 1)
#define RPC_CLNT_CREATE_AUTOBIND (1UL << 2)
-#define RPC_CLNT_CREATE_ONESHOT (1UL << 3)
-#define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 4)
-#define RPC_CLNT_CREATE_NOPING (1UL << 5)
-#define RPC_CLNT_CREATE_DISCRTRY (1UL << 6)
+#define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 3)
+#define RPC_CLNT_CREATE_NOPING (1UL << 4)
+#define RPC_CLNT_CREATE_DISCRTRY (1UL << 5)
struct rpc_clnt *rpc_create(struct rpc_create_args *args);
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
struct rpc_program *, int);
struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
-int rpc_shutdown_client(struct rpc_clnt *);
-int rpc_destroy_client(struct rpc_clnt *);
+void rpc_shutdown_client(struct rpc_clnt *);
void rpc_release_client(struct rpc_clnt *);
+
int rpcb_register(u32, u32, int, unsigned short, int *);
-void rpcb_getport(struct rpc_task *);
+int rpcb_getport_sync(struct sockaddr_in *, __u32, __u32, int);
+void rpcb_getport_async(struct rpc_task *);
void rpc_call_setup(struct rpc_task *, struct rpc_message *, int);
@@ -132,20 +133,16 @@ int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg,
void *calldata);
int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg,
int flags);
+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
+ int flags);
void rpc_restart_call(struct rpc_task *);
void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
size_t rpc_max_payload(struct rpc_clnt *);
void rpc_force_rebind(struct rpc_clnt *);
-int rpc_ping(struct rpc_clnt *clnt, int flags);
size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t);
char * rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
-/*
- * Helper function for NFSroot support
- */
-int rpcb_getport_external(struct sockaddr_in *, __u32, __u32, int);
-
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_CLNT_H */
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 5eca9e44205..bbac101ac37 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -77,7 +77,7 @@ struct gss_api_mech {
struct module *gm_owner;
struct xdr_netobj gm_oid;
char *gm_name;
- struct gss_api_ops *gm_ops;
+ const struct gss_api_ops *gm_ops;
/* pseudoflavors supported by this mechanism: */
int gm_pf_num;
struct pf_desc * gm_pfs;
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index ad293760f6e..51b977a4ca2 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -23,9 +23,11 @@ struct rpc_inode {
void *private;
struct list_head pipe;
struct list_head in_upcall;
+ struct list_head in_downcall;
int pipelen;
int nreaders;
int nwriters;
+ int nkern_readwriters;
wait_queue_head_t waitq;
#define RPC_PIPE_WAIT_FOR_OPEN 1
int flags;
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 2047fb202a1..8ea077db009 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -98,7 +98,6 @@ struct rpc_task {
unsigned short tk_pid; /* debugging aid */
#endif
};
-#define tk_auth tk_client->cl_auth
#define tk_xprt tk_client->cl_xprt
/* support walking a list of tasks on a wait queue */
@@ -110,11 +109,6 @@ struct rpc_task {
if (!list_empty(head) && \
((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1))
-/* .. and walking list of all tasks */
-#define alltask_for_each(task, pos, head) \
- list_for_each(pos, head) \
- if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
-
typedef void (*rpc_action)(struct rpc_task *);
struct rpc_call_ops {
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 4a7ae8ab6eb..129d50f2225 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -253,7 +253,7 @@ struct svc_rqst {
* determine what device number
* to report (real or virtual)
*/
- int rq_sendfile_ok; /* turned off in gss privacy
+ int rq_splice_ok; /* turned off in gss privacy
* to prevent encrypting page
* cache pages */
wait_queue_head_t rq_wait; /* synchronization */
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index e21dd93ac4b..a53e0fa855d 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -59,6 +59,7 @@ struct svc_sock {
/* cache of various info for TCP sockets */
void *sk_info_authunix;
+ struct sockaddr_storage sk_local; /* local address */
struct sockaddr_storage sk_remote; /* remote peer's address */
int sk_remotelen; /* length of address */
};
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 34f7590506f..d11cedd14f0 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -17,6 +17,8 @@
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/msg_prot.h>
+#ifdef __KERNEL__
+
extern unsigned int xprt_udp_slot_table_entries;
extern unsigned int xprt_tcp_slot_table_entries;
@@ -194,7 +196,13 @@ struct rpc_xprt {
char * address_strings[RPC_DISPLAY_MAX];
};
-#ifdef __KERNEL__
+struct rpc_xprtsock_create {
+ int proto; /* IPPROTO_UDP or IPPROTO_TCP */
+ struct sockaddr * srcaddr; /* optional local address */
+ struct sockaddr * dstaddr; /* remote peer address */
+ size_t addrlen;
+ struct rpc_timeout * timeout; /* optional timeout parameters */
+};
/*
* Transport operations used by ULPs
@@ -204,7 +212,7 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long
/*
* Generic internal transport functions
*/
-struct rpc_xprt * xprt_create_transport(int proto, struct sockaddr *addr, size_t size, struct rpc_timeout *toparms);
+struct rpc_xprt * xprt_create_transport(struct rpc_xprtsock_create *args);
void xprt_connect(struct rpc_task *task);
void xprt_reserve(struct rpc_task *task);
int xprt_reserve_xprt(struct rpc_task *task);
@@ -242,8 +250,8 @@ void xprt_disconnect(struct rpc_xprt *xprt);
/*
* Socket transport setup operations
*/
-struct rpc_xprt * xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
-struct rpc_xprt * xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to);
+struct rpc_xprt * xs_setup_udp(struct rpc_xprtsock_create *args);
+struct rpc_xprt * xs_setup_tcp(struct rpc_xprtsock_create *args);
int init_socket_xprt(void);
void cleanup_socket_xprt(void);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index b02070eac42..83d0ec11235 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -598,6 +598,8 @@ asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags);
asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
unsigned int flags);
+asmlinkage long sys_sync_file_range2(int fd, unsigned int flags,
+ loff_t offset, loff_t nbytes);
asmlinkage long sys_get_robust_list(int pid,
struct robust_list_head __user * __user *head_ptr,
size_t __user *len_ptr);
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index e699ab279c2..e285746588d 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -101,8 +101,7 @@ struct sysdev_attribute {
#define _SYSDEV_ATTR(_name,_mode,_show,_store) \
{ \
- .attr = { .name = __stringify(_name), .mode = _mode, \
- .owner = THIS_MODULE }, \
+ .attr = { .name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 7d5d1ec95c2..be8228e50a2 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -19,10 +19,15 @@ struct kobject;
struct module;
struct nameidata;
struct dentry;
+struct sysfs_dirent;
+/* FIXME
+ * The *owner field is no longer used, but leave around
+ * until the tree gets cleaned up fully.
+ */
struct attribute {
const char * name;
- struct module * owner;
+ struct module * owner;
mode_t mode;
};
@@ -39,14 +44,14 @@ struct attribute_group {
*/
#define __ATTR(_name,_mode,_show,_store) { \
- .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}
#define __ATTR_RO(_name) { \
- .attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \
- .show = _name##_show, \
+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
+ .show = _name##_show, \
}
#define __ATTR_NULL { .attr = { .name = NULL } }
@@ -59,8 +64,10 @@ struct bin_attribute {
struct attribute attr;
size_t size;
void *private;
- ssize_t (*read)(struct kobject *, char *, loff_t, size_t);
- ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
+ ssize_t (*read)(struct kobject *, struct bin_attribute *,
+ char *, loff_t, size_t);
+ ssize_t (*write)(struct kobject *, struct bin_attribute *,
+ char *, loff_t, size_t);
int (*mmap)(struct kobject *, struct bin_attribute *attr,
struct vm_area_struct *vma);
};
@@ -70,12 +77,16 @@ struct sysfs_ops {
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
};
+#define SYSFS_TYPE_MASK 0x00ff
#define SYSFS_ROOT 0x0001
#define SYSFS_DIR 0x0002
#define SYSFS_KOBJ_ATTR 0x0004
#define SYSFS_KOBJ_BIN_ATTR 0x0008
#define SYSFS_KOBJ_LINK 0x0020
-#define SYSFS_NOT_PINNED (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR | SYSFS_KOBJ_LINK)
+#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
+
+#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
+#define SYSFS_FLAG_REMOVED 0x0100
#ifdef CONFIG_SYSFS
@@ -83,13 +94,14 @@ extern int sysfs_schedule_callback(struct kobject *kobj,
void (*func)(void *), void *data, struct module *owner);
extern int __must_check
-sysfs_create_dir(struct kobject *, struct dentry *);
+sysfs_create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent_sd);
extern void
sysfs_remove_dir(struct kobject *);
extern int __must_check
-sysfs_rename_dir(struct kobject *, struct dentry *, const char *new_name);
+sysfs_rename_dir(struct kobject *kobj, struct sysfs_dirent *new_parent_sd,
+ const char *new_name);
extern int __must_check
sysfs_move_dir(struct kobject *, struct kobject *);
@@ -129,8 +141,8 @@ void sysfs_notify(struct kobject * k, char *dir, char *attr);
extern int sysfs_make_shadowed_dir(struct kobject *kobj,
void * (*follow_link)(struct dentry *, struct nameidata *));
-extern struct dentry *sysfs_create_shadow_dir(struct kobject *kobj);
-extern void sysfs_remove_shadow_dir(struct dentry *dir);
+extern struct sysfs_dirent *sysfs_create_shadow_dir(struct kobject *kobj);
+extern void sysfs_remove_shadow_dir(struct sysfs_dirent *shadow_sd);
extern int __must_check sysfs_init(void);
@@ -142,7 +154,8 @@ static inline int sysfs_schedule_callback(struct kobject *kobj,
return -ENOSYS;
}
-static inline int sysfs_create_dir(struct kobject * k, struct dentry *shadow)
+static inline int sysfs_create_dir(struct kobject *kobj,
+ struct sysfs_dirent *shadow_parent_sd)
{
return 0;
}
@@ -152,9 +165,9 @@ static inline void sysfs_remove_dir(struct kobject * k)
;
}
-static inline int sysfs_rename_dir(struct kobject * k,
- struct dentry *new_parent,
- const char *new_name)
+static inline int sysfs_rename_dir(struct kobject *kobj,
+ struct sysfs_dirent *new_parent_sd,
+ const char *new_name)
{
return 0;
}
diff --git a/include/linux/topology.h b/include/linux/topology.h
index a9d1f049cc1..d0890a7e5ba 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -50,10 +50,10 @@
for_each_online_node(node) \
if (nr_cpus_node(node))
-#ifndef node_distance
/* Conform to ACPI 2.0 SLIT distance definitions */
#define LOCAL_DISTANCE 10
#define REMOTE_DISTANCE 20
+#ifndef node_distance
#define node_distance(from,to) ((from) == (to) ? LOCAL_DISTANCE : REMOTE_DISTANCE)
#endif
#ifndef RECLAIM_DISTANCE
@@ -98,7 +98,7 @@
.cache_nice_tries = 0, \
.busy_idx = 0, \
.idle_idx = 0, \
- .newidle_idx = 1, \
+ .newidle_idx = 0, \
.wake_idx = 0, \
.forkexec_idx = 0, \
.flags = SD_LOAD_BALANCE \
@@ -128,14 +128,15 @@
.imbalance_pct = 125, \
.cache_nice_tries = 1, \
.busy_idx = 2, \
- .idle_idx = 1, \
- .newidle_idx = 2, \
+ .idle_idx = 0, \
+ .newidle_idx = 0, \
.wake_idx = 1, \
.forkexec_idx = 1, \
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_NEWIDLE \
| SD_BALANCE_EXEC \
| SD_WAKE_AFFINE \
+ | SD_WAKE_IDLE \
| SD_SHARE_PKG_RESOURCES\
| BALANCE_FOR_MC_POWER, \
.last_balance = jiffies, \
@@ -158,14 +159,15 @@
.imbalance_pct = 125, \
.cache_nice_tries = 1, \
.busy_idx = 2, \
- .idle_idx = 1, \
- .newidle_idx = 2, \
+ .idle_idx = 0, \
+ .newidle_idx = 0, \
.wake_idx = 1, \
.forkexec_idx = 1, \
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_NEWIDLE \
| SD_BALANCE_EXEC \
| SD_WAKE_AFFINE \
+ | SD_WAKE_IDLE \
| BALANCE_FOR_PKG_POWER,\
.last_balance = jiffies, \
.balance_interval = 1, \
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 6de445c31a6..8ec703f462d 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -42,6 +42,7 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
/* UDP encapsulation types */
#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */
+#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
#ifdef __KERNEL__
#include <linux/types.h>
@@ -70,6 +71,11 @@ struct udp_sock {
#define UDPLITE_SEND_CC 0x2 /* set via udplite setsockopt */
#define UDPLITE_RECV_CC 0x4 /* set via udplite setsocktopt */
__u8 pcflag; /* marks socket as UDP-Lite if > 0 */
+ __u8 unused[3];
+ /*
+ * For encapsulation sockets.
+ */
+ int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
};
static inline struct udp_sock *udp_sk(const struct sock *sk)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 94bd38a6d94..7a60946df3b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -146,6 +146,10 @@ struct usb_interface {
* active alternate setting */
unsigned num_altsetting; /* number of alternate settings */
+ /* If there is an interface association descriptor then it will list
+ * the associated interfaces */
+ struct usb_interface_assoc_descriptor *intf_assoc;
+
int minor; /* minor number this interface is
* bound to */
enum usb_interface_condition condition; /* state of binding */
@@ -175,6 +179,7 @@ void usb_put_intf(struct usb_interface *intf);
/* this maximum is arbitrary */
#define USB_MAXINTERFACES 32
+#define USB_MAXIADS USB_MAXINTERFACES/2
/**
* struct usb_interface_cache - long-term representation of a device interface
@@ -245,6 +250,11 @@ struct usb_host_config {
struct usb_config_descriptor desc;
char *string; /* iConfiguration string, if present */
+
+ /* List of any Interface Association Descriptors in this
+ * configuration. */
+ struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
+
/* the interfaces associated with this configuration,
* stored in no particular order */
struct usb_interface *interface[USB_MAXINTERFACES];
@@ -403,6 +413,8 @@ struct usb_device {
unsigned auto_pm:1; /* autosuspend/resume in progress */
unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */
+ unsigned reset_resume:1; /* needs reset instead of resume */
+ unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */
unsigned autosuspend_disabled:1; /* autosuspend and autoresume */
unsigned autoresume_disabled:1; /* disabled by the user */
#endif
@@ -729,6 +741,22 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
.bcdDevice_lo = (lo), .bcdDevice_hi = (hi)
/**
+ * USB_DEVICE_INTERFACE_PROTOCOL - macro used to describe a usb
+ * device with a specific interface protocol
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific interface protocol of devices.
+ */
+#define USB_DEVICE_INTERFACE_PROTOCOL(vend,prod,pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_PROTOCOL, \
+ .idVendor = (vend), \
+ .idProduct = (prod), \
+ .bInterfaceProtocol = (pr)
+
+/**
* USB_DEVICE_INFO - macro used to describe a class of usb devices
* @cl: bDeviceClass value
* @sc: bDeviceSubClass value
@@ -754,6 +782,28 @@ static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO, .bInterfaceClass = (cl), \
.bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+/**
+ * USB_DEVICE_AND_INTERFACE_INFO - macro used to describe a specific usb device
+ * with a class of usb interfaces
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @cl: bInterfaceClass value
+ * @sc: bInterfaceSubClass value
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific device with a specific class of interfaces.
+ *
+ * This is especially useful when explicitly matching devices that have
+ * vendor specific bDeviceClass values, but standards-compliant interfaces.
+ */
+#define USB_DEVICE_AND_INTERFACE_INFO(vend,prod,cl,sc,pr) \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+ | USB_DEVICE_ID_MATCH_DEVICE, \
+ .idVendor = (vend), .idProduct = (prod), \
+ .bInterfaceClass = (cl), \
+ .bInterfaceSubClass = (sc), .bInterfaceProtocol = (pr)
+
/* ----------------------------------------------------------------------- */
/* Stuff for dynamic usb ids */
@@ -800,10 +850,15 @@ struct usbdrv_wrap {
* do (or don't) show up otherwise in the filesystem.
* @suspend: Called when the device is going to be suspended by the system.
* @resume: Called when the device is being resumed by the system.
+ * @reset_resume: Called when the suspended device has been reset instead
+ * of being resumed.
* @pre_reset: Called by usb_reset_composite_device() when the device
* is about to be reset.
* @post_reset: Called by usb_reset_composite_device() after the device
- * has been reset.
+ * has been reset, or in lieu of @resume following a reset-resume
+ * (i.e., the device is reset instead of being resumed, as might
+ * happen if power was lost). The second argument tells which is
+ * the reason.
* @id_table: USB drivers use ID table to support hotplugging.
* Export this with MODULE_DEVICE_TABLE(usb,...). This must be set
* or your driver's probe function will never get called.
@@ -843,9 +898,10 @@ struct usb_driver {
int (*suspend) (struct usb_interface *intf, pm_message_t message);
int (*resume) (struct usb_interface *intf);
+ int (*reset_resume)(struct usb_interface *intf);
- void (*pre_reset) (struct usb_interface *intf);
- void (*post_reset) (struct usb_interface *intf);
+ int (*pre_reset)(struct usb_interface *intf);
+ int (*post_reset)(struct usb_interface *intf);
const struct usb_device_id *id_table;
@@ -948,6 +1004,7 @@ extern int usb_disabled(void);
#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
#define URB_NO_INTERRUPT 0x0080 /* HINT: no non-error interrupt
* needed */
+#define URB_FREE_BUFFER 0x0100 /* Free transfer buffer with the URB */
struct usb_iso_packet_descriptor {
unsigned int offset;
@@ -958,11 +1015,26 @@ struct usb_iso_packet_descriptor {
struct urb;
+struct usb_anchor {
+ struct list_head urb_list;
+ wait_queue_head_t wait;
+ spinlock_t lock;
+};
+
+static inline void init_usb_anchor(struct usb_anchor *anchor)
+{
+ INIT_LIST_HEAD(&anchor->urb_list);
+ init_waitqueue_head(&anchor->wait);
+ spin_lock_init(&anchor->lock);
+}
+
typedef void (*usb_complete_t)(struct urb *);
/**
* struct urb - USB Request Block
* @urb_list: For use by current owner of the URB.
+ * @anchor_list: membership in the list of an anchor
+ * @anchor: to anchor URBs to a common mooring
* @pipe: Holds endpoint number, direction, type, and more.
* Create these values with the eight macros available;
* usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
@@ -1135,6 +1207,8 @@ struct urb
/* public: documented fields in the urb that can be used by drivers */
struct list_head urb_list; /* list head for use by the urb's
* current owner */
+ struct list_head anchor_list; /* the URB may be anchored by the driver */
+ struct usb_anchor *anchor;
struct usb_device *dev; /* (in) pointer to associated device */
unsigned int pipe; /* (in) pipe information */
int status; /* (return) non-ISO status */
@@ -1270,6 +1344,11 @@ extern struct urb *usb_get_urb(struct urb *urb);
extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
extern int usb_unlink_urb(struct urb *urb);
extern void usb_kill_urb(struct urb *urb);
+extern void usb_kill_anchored_urbs(struct usb_anchor *anchor);
+extern void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor);
+extern void usb_unanchor_urb(struct urb *urb);
+extern int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor,
+ unsigned int timeout);
void *usb_buffer_alloc (struct usb_device *dev, size_t size,
gfp_t mem_flags, dma_addr_t *dma);
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index 43f160cfe00..6ce42bf9f74 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -1,5 +1,6 @@
unifdef-y += audio.h
unifdef-y += cdc.h
unifdef-y += ch9.h
+unifdef-y += gadgetfs.h
unifdef-y += midi.h
diff --git a/include/linux/usb_gadgetfs.h b/include/linux/usb/gadgetfs.h
index 8086d5a9b94..e8654c33872 100644
--- a/include/linux/usb_gadgetfs.h
+++ b/include/linux/usb/gadgetfs.h
@@ -1,3 +1,5 @@
+#ifndef __LINUX_USB_GADGETFS_H
+#define __LINUX_USB_GADGETFS_H
#include <asm/types.h>
#include <asm/ioctl.h>
@@ -7,11 +9,12 @@
/*
* Filesystem based user-mode API to USB Gadget controller hardware
*
- * Almost everything can be done with only read and write operations,
+ * 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.
+ * 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
@@ -21,9 +24,9 @@
*/
/*
- * Events are delivered on the ep0 file descriptor, if the user mode driver
+ * 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, if you write that kind of driver.
+ * stop polling this descriptor.
*/
enum usb_gadgetfs_event_type {
@@ -36,8 +39,10 @@ enum usb_gadgetfs_event_type {
// 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 {
- enum usb_gadgetfs_event_type type;
union {
// NOP, DISCONNECT, SUSPEND: nothing
// ... some hardware can't report disconnection
@@ -46,19 +51,20 @@ struct usb_gadgetfs_event {
enum usb_device_speed speed;
// SETUP: packet; DATA phase i/o precedes next event
- // (setup.bmRequestType & USB_DIR_IN) flags direction
+ // (setup.bmRequestType & USB_DIR_IN) flags direction
// ... includes SET_CONFIGURATION, SET_INTERFACE
struct usb_ctrlrequest setup;
} u;
+ enum usb_gadgetfs_event_type type;
};
/* endpoint ioctls */
/* IN transfers may be reported to the gadget driver as complete
- * when the fifo is loaded, before the host reads the data;
+ * 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.
+ * 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)
*/
@@ -72,4 +78,4 @@ struct usb_gadgetfs_event {
*/
#define GADGETFS_CLEAR_HALT _IO('g',3)
-
+#endif /* __LINUX_USB_GADGETFS_H */
diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
index 6bac8faacbc..8da374caf58 100644
--- a/include/linux/usb/quirks.h
+++ b/include/linux/usb/quirks.h
@@ -9,3 +9,6 @@
/* string descriptors must not be fetched using a 255-byte read */
#define USB_QUIRK_STRING_FETCH_255 0x00000002
+
+/* device can't resume correctly so reset it instead */
+#define USB_QUIRK_RESET_RESUME 0x00000004
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 32acbae28d2..e8b8928232c 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -221,6 +221,9 @@ struct usb_serial_driver {
int (*port_probe) (struct usb_serial_port *port);
int (*port_remove) (struct usb_serial_port *port);
+ int (*suspend) (struct usb_serial *serial, pm_message_t message);
+ int (*resume) (struct usb_serial *serial);
+
/* serial function calls */
int (*open) (struct usb_serial_port *port, struct file * filp);
void (*close) (struct usb_serial_port *port, struct file * filp);
@@ -249,6 +252,9 @@ extern void usb_serial_port_softint(struct usb_serial_port *port);
extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
extern void usb_serial_disconnect(struct usb_interface *iface);
+extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
+extern int usb_serial_resume(struct usb_interface *intf);
+
extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest);
extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
@@ -269,6 +275,7 @@ extern void usb_serial_put(struct usb_serial *serial);
extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
+extern int usb_serial_generic_resume (struct usb_serial *serial);
extern int usb_serial_generic_write_room (struct usb_serial_port *port);
extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port);
extern void usb_serial_generic_read_bulk_callback (struct urb *urb);
diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h
index e17186dbcdc..4f59b2aa8a9 100644
--- a/include/linux/usb_gadget.h
+++ b/include/linux/usb_gadget.h
@@ -110,13 +110,6 @@ struct usb_ep_ops {
gfp_t gfp_flags);
void (*free_request) (struct usb_ep *ep, struct usb_request *req);
- void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
- dma_addr_t *dma, gfp_t gfp_flags);
- void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
- unsigned bytes);
- // NOTE: on 2.6, drivers may also use dma_map() and
- // dma_sync_single_*() to directly manage dma overhead.
-
int (*queue) (struct usb_ep *ep, struct usb_request *req,
gfp_t gfp_flags);
int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
@@ -235,47 +228,6 @@ usb_ep_free_request (struct usb_ep *ep, struct usb_request *req)
}
/**
- * usb_ep_alloc_buffer - allocate an I/O buffer
- * @ep:the endpoint associated with the buffer
- * @len:length of the desired buffer
- * @dma:pointer to the buffer's DMA address; must be valid
- * @gfp_flags:GFP_* flags to use
- *
- * Returns a new buffer, or null if one could not be allocated.
- * The buffer is suitably aligned for dma, if that endpoint uses DMA,
- * and the caller won't have to care about dma-inconsistency
- * or any hidden "bounce buffer" mechanism. No additional per-request
- * DMA mapping will be required for such buffers.
- * Free it later with usb_ep_free_buffer().
- *
- * You don't need to use this call to allocate I/O buffers unless you
- * want to make sure drivers don't incur costs for such "bounce buffer"
- * copies or per-request DMA mappings.
- */
-static inline void *
-usb_ep_alloc_buffer (struct usb_ep *ep, unsigned len, dma_addr_t *dma,
- gfp_t gfp_flags)
-{
- return ep->ops->alloc_buffer (ep, len, dma, gfp_flags);
-}
-
-/**
- * usb_ep_free_buffer - frees an i/o buffer
- * @ep:the endpoint associated with the buffer
- * @buf:CPU view address of the buffer
- * @dma:the buffer's DMA address
- * @len:length of the buffer
- *
- * reverses the effect of usb_ep_alloc_buffer().
- * caller guarantees the buffer will no longer be accessed
- */
-static inline void
-usb_ep_free_buffer (struct usb_ep *ep, void *buf, dma_addr_t dma, unsigned len)
-{
- ep->ops->free_buffer (ep, buf, dma, len);
-}
-
-/**
* usb_ep_queue - queues (submits) an I/O request to an endpoint.
* @ep:the endpoint associated with the request
* @req:the request being submitted
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index e7560389079..d16a2b57dc8 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -243,8 +243,7 @@ struct v4l2_capability
#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */
#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */
#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
-#define V4L2_CAP_VIDEO_OUTPUT_POS 0x00000200 /* Video output can have x,y coords */
-#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000400 /* Can do video output overlay */
+#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
@@ -616,12 +615,16 @@ struct v4l2_framebuffer
#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008
#define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010
#define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020
+#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040
+#define V4L2_FBUF_CAP_GLOBAL_INV_ALPHA 0x0080
/* Flags for the 'flags' field. */
#define V4L2_FBUF_FLAG_PRIMARY 0x0001
#define V4L2_FBUF_FLAG_OVERLAY 0x0002
#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004
#define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008
#define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010
+#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020
+#define V4L2_FBUF_FLAG_GLOBAL_INV_ALPHA 0x0040
struct v4l2_clip
{
diff --git a/include/linux/wait.h b/include/linux/wait.h
index e820d00e138..0e686280450 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -366,15 +366,15 @@ static inline void remove_wait_queue_locked(wait_queue_head_t *q,
/*
* These are the old interfaces to sleep waiting for an event.
- * They are racy. DO NOT use them, use the wait_event* interfaces above.
- * We plan to remove these interfaces during 2.7.
+ * They are racy. DO NOT use them, use the wait_event* interfaces above.
+ * We plan to remove these interfaces.
*/
-extern void FASTCALL(sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
- signed long timeout));
-extern void FASTCALL(interruptible_sleep_on(wait_queue_head_t *q));
-extern long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t *q,
- signed long timeout));
+extern void sleep_on(wait_queue_head_t *q);
+extern long sleep_on_timeout(wait_queue_head_t *q,
+ signed long timeout);
+extern void interruptible_sleep_on(wait_queue_head_t *q);
+extern long interruptible_sleep_on_timeout(wait_queue_head_t *q,
+ signed long timeout);
/*
* Waitqueues which are removed from the waitqueue_head at wakeup time
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
new file mode 100644
index 00000000000..88884d39f28
--- /dev/null
+++ b/include/net/9p/9p.h
@@ -0,0 +1,417 @@
+/*
+ * include/net/9p/9p.h
+ *
+ * 9P protocol definitions.
+ *
+ * Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#ifndef NET_9P_H
+#define NET_9P_H
+
+#ifdef CONFIG_NET_9P_DEBUG
+
+#define P9_DEBUG_ERROR (1<<0)
+#define P9_DEBUG_9P (1<<2)
+#define P9_DEBUG_VFS (1<<3)
+#define P9_DEBUG_CONV (1<<4)
+#define P9_DEBUG_MUX (1<<5)
+#define P9_DEBUG_TRANS (1<<6)
+#define P9_DEBUG_SLABS (1<<7)
+#define P9_DEBUG_FCALL (1<<8)
+
+extern unsigned int p9_debug_level;
+
+#define P9_DPRINTK(level, format, arg...) \
+do { \
+ if ((p9_debug_level & level) == level) \
+ printk(KERN_NOTICE "-- %s (%d): " \
+ format , __FUNCTION__, current->pid , ## arg); \
+} while (0)
+
+#define PRINT_FCALL_ERROR(s, fcall) P9_DPRINTK(P9_DEBUG_ERROR, \
+ "%s: %.*s\n", s, fcall?fcall->params.rerror.error.len:0, \
+ fcall?fcall->params.rerror.error.str:"");
+
+#else
+#define P9_DPRINTK(level, format, arg...) do { } while (0)
+#define PRINT_FCALL_ERROR(s, fcall) do { } while (0)
+#endif
+
+#define P9_EPRINTK(level, format, arg...) \
+do { \
+ printk(level "9p: %s (%d): " \
+ format , __FUNCTION__, current->pid , ## arg); \
+} while (0)
+
+
+/* Message Types */
+enum {
+ P9_TVERSION = 100,
+ P9_RVERSION,
+ P9_TAUTH = 102,
+ P9_RAUTH,
+ P9_TATTACH = 104,
+ P9_RATTACH,
+ P9_TERROR = 106,
+ P9_RERROR,
+ P9_TFLUSH = 108,
+ P9_RFLUSH,
+ P9_TWALK = 110,
+ P9_RWALK,
+ P9_TOPEN = 112,
+ P9_ROPEN,
+ P9_TCREATE = 114,
+ P9_RCREATE,
+ P9_TREAD = 116,
+ P9_RREAD,
+ P9_TWRITE = 118,
+ P9_RWRITE,
+ P9_TCLUNK = 120,
+ P9_RCLUNK,
+ P9_TREMOVE = 122,
+ P9_RREMOVE,
+ P9_TSTAT = 124,
+ P9_RSTAT,
+ P9_TWSTAT = 126,
+ P9_RWSTAT,
+};
+
+/* open modes */
+enum {
+ P9_OREAD = 0x00,
+ P9_OWRITE = 0x01,
+ P9_ORDWR = 0x02,
+ P9_OEXEC = 0x03,
+ P9_OEXCL = 0x04,
+ P9_OTRUNC = 0x10,
+ P9_OREXEC = 0x20,
+ P9_ORCLOSE = 0x40,
+ P9_OAPPEND = 0x80,
+};
+
+/* permissions */
+enum {
+ P9_DMDIR = 0x80000000,
+ P9_DMAPPEND = 0x40000000,
+ P9_DMEXCL = 0x20000000,
+ P9_DMMOUNT = 0x10000000,
+ P9_DMAUTH = 0x08000000,
+ P9_DMTMP = 0x04000000,
+ P9_DMSYMLINK = 0x02000000,
+ P9_DMLINK = 0x01000000,
+ /* 9P2000.u extensions */
+ P9_DMDEVICE = 0x00800000,
+ P9_DMNAMEDPIPE = 0x00200000,
+ P9_DMSOCKET = 0x00100000,
+ P9_DMSETUID = 0x00080000,
+ P9_DMSETGID = 0x00040000,
+};
+
+/* qid.types */
+enum {
+ P9_QTDIR = 0x80,
+ P9_QTAPPEND = 0x40,
+ P9_QTEXCL = 0x20,
+ P9_QTMOUNT = 0x10,
+ P9_QTAUTH = 0x08,
+ P9_QTTMP = 0x04,
+ P9_QTSYMLINK = 0x02,
+ P9_QTLINK = 0x01,
+ P9_QTFILE = 0x00,
+};
+
+#define P9_NOTAG (u16)(~0)
+#define P9_NOFID (u32)(~0)
+#define P9_MAXWELEM 16
+
+/* ample room for Twrite/Rread header */
+#define P9_IOHDRSZ 24
+
+struct p9_str {
+ u16 len;
+ char *str;
+};
+
+/* qids are the unique ID for a file (like an inode */
+struct p9_qid {
+ u8 type;
+ u32 version;
+ u64 path;
+};
+
+/* Plan 9 file metadata (stat) structure */
+struct p9_stat {
+ u16 size;
+ u16 type;
+ u32 dev;
+ struct p9_qid qid;
+ u32 mode;
+ u32 atime;
+ u32 mtime;
+ u64 length;
+ struct p9_str name;
+ struct p9_str uid;
+ struct p9_str gid;
+ struct p9_str muid;
+ struct p9_str extension; /* 9p2000.u extensions */
+ u32 n_uid; /* 9p2000.u extensions */
+ u32 n_gid; /* 9p2000.u extensions */
+ u32 n_muid; /* 9p2000.u extensions */
+};
+
+/* file metadata (stat) structure used to create Twstat message
+ The is similar to p9_stat, but the strings don't point to
+ the same memory block and should be freed separately
+*/
+struct p9_wstat {
+ u16 size;
+ u16 type;
+ u32 dev;
+ struct p9_qid qid;
+ u32 mode;
+ u32 atime;
+ u32 mtime;
+ u64 length;
+ char *name;
+ char *uid;
+ char *gid;
+ char *muid;
+ char *extension; /* 9p2000.u extensions */
+ u32 n_uid; /* 9p2000.u extensions */
+ u32 n_gid; /* 9p2000.u extensions */
+ u32 n_muid; /* 9p2000.u extensions */
+};
+
+/* Structures for Protocol Operations */
+struct p9_tversion {
+ u32 msize;
+ struct p9_str version;
+};
+
+struct p9_rversion {
+ u32 msize;
+ struct p9_str version;
+};
+
+struct p9_tauth {
+ u32 afid;
+ struct p9_str uname;
+ struct p9_str aname;
+};
+
+struct p9_rauth {
+ struct p9_qid qid;
+};
+
+struct p9_rerror {
+ struct p9_str error;
+ u32 errno; /* 9p2000.u extension */
+};
+
+struct p9_tflush {
+ u16 oldtag;
+};
+
+struct p9_rflush {
+};
+
+struct p9_tattach {
+ u32 fid;
+ u32 afid;
+ struct p9_str uname;
+ struct p9_str aname;
+};
+
+struct p9_rattach {
+ struct p9_qid qid;
+};
+
+struct p9_twalk {
+ u32 fid;
+ u32 newfid;
+ u16 nwname;
+ struct p9_str wnames[16];
+};
+
+struct p9_rwalk {
+ u16 nwqid;
+ struct p9_qid wqids[16];
+};
+
+struct p9_topen {
+ u32 fid;
+ u8 mode;
+};
+
+struct p9_ropen {
+ struct p9_qid qid;
+ u32 iounit;
+};
+
+struct p9_tcreate {
+ u32 fid;
+ struct p9_str name;
+ u32 perm;
+ u8 mode;
+ struct p9_str extension;
+};
+
+struct p9_rcreate {
+ struct p9_qid qid;
+ u32 iounit;
+};
+
+struct p9_tread {
+ u32 fid;
+ u64 offset;
+ u32 count;
+};
+
+struct p9_rread {
+ u32 count;
+ u8 *data;
+};
+
+struct p9_twrite {
+ u32 fid;
+ u64 offset;
+ u32 count;
+ u8 *data;
+};
+
+struct p9_rwrite {
+ u32 count;
+};
+
+struct p9_tclunk {
+ u32 fid;
+};
+
+struct p9_rclunk {
+};
+
+struct p9_tremove {
+ u32 fid;
+};
+
+struct p9_rremove {
+};
+
+struct p9_tstat {
+ u32 fid;
+};
+
+struct p9_rstat {
+ struct p9_stat stat;
+};
+
+struct p9_twstat {
+ u32 fid;
+ struct p9_stat stat;
+};
+
+struct p9_rwstat {
+};
+
+/*
+ * fcall is the primary packet structure
+ *
+ */
+
+struct p9_fcall {
+ u32 size;
+ u8 id;
+ u16 tag;
+ void *sdata;
+
+ union {
+ struct p9_tversion tversion;
+ struct p9_rversion rversion;
+ struct p9_tauth tauth;
+ struct p9_rauth rauth;
+ struct p9_rerror rerror;
+ struct p9_tflush tflush;
+ struct p9_rflush rflush;
+ struct p9_tattach tattach;
+ struct p9_rattach rattach;
+ struct p9_twalk twalk;
+ struct p9_rwalk rwalk;
+ struct p9_topen topen;
+ struct p9_ropen ropen;
+ struct p9_tcreate tcreate;
+ struct p9_rcreate rcreate;
+ struct p9_tread tread;
+ struct p9_rread rread;
+ struct p9_twrite twrite;
+ struct p9_rwrite rwrite;
+ struct p9_tclunk tclunk;
+ struct p9_rclunk rclunk;
+ struct p9_tremove tremove;
+ struct p9_rremove rremove;
+ struct p9_tstat tstat;
+ struct p9_rstat rstat;
+ struct p9_twstat twstat;
+ struct p9_rwstat rwstat;
+ } params;
+};
+
+struct p9_idpool;
+
+int p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,
+ int dotu);
+int p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *fc, int dotu);
+void p9_set_tag(struct p9_fcall *fc, u16 tag);
+struct p9_fcall *p9_create_tversion(u32 msize, char *version);
+struct p9_fcall *p9_create_tattach(u32 fid, u32 afid, char *uname,
+ char *aname);
+struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname);
+struct p9_fcall *p9_create_tflush(u16 oldtag);
+struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
+ char **wnames);
+struct p9_fcall *p9_create_topen(u32 fid, u8 mode);
+struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
+ char *extension, int dotu);
+struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count);
+struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count,
+ const char *data);
+struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count,
+ const char __user *data);
+struct p9_fcall *p9_create_tclunk(u32 fid);
+struct p9_fcall *p9_create_tremove(u32 fid);
+struct p9_fcall *p9_create_tstat(u32 fid);
+struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat,
+ int dotu);
+
+int p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int dotu);
+int p9_errstr2errno(char *errstr, int len);
+
+struct p9_idpool *p9_idpool_create(void);
+void p9_idpool_destroy(struct p9_idpool *);
+int p9_idpool_get(struct p9_idpool *p);
+void p9_idpool_put(int id, struct p9_idpool *p);
+int p9_idpool_check(int id, struct p9_idpool *p);
+
+int p9_error_init(void);
+int p9_errstr2errno(char *, int);
+int __init p9_sysctl_register(void);
+void __exit p9_sysctl_unregister(void);
+#endif /* NET_9P_H */
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
new file mode 100644
index 00000000000..d65ed7c6906
--- /dev/null
+++ b/include/net/9p/client.h
@@ -0,0 +1,80 @@
+/*
+ * include/net/9p/client.h
+ *
+ * 9P Client Definitions
+ *
+ * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ * 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#ifndef NET_9P_CLIENT_H
+#define NET_9P_CLIENT_H
+
+struct p9_client {
+ spinlock_t lock; /* protect client structure */
+ int msize;
+ unsigned char dotu;
+ struct p9_transport *trans;
+ struct p9_conn *conn;
+
+ struct p9_idpool *fidpool;
+ struct list_head fidlist;
+};
+
+struct p9_fid {
+ struct p9_client *clnt;
+ u32 fid;
+ int mode;
+ struct p9_qid qid;
+ u32 iounit;
+ uid_t uid;
+ void *aux;
+
+ int rdir_fpos;
+ int rdir_pos;
+ struct p9_fcall *rdir_fcall;
+ struct list_head flist;
+ struct list_head dlist; /* list of all fids attached to a dentry */
+};
+
+struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
+ int dotu);
+void p9_client_destroy(struct p9_client *clnt);
+void p9_client_disconnect(struct p9_client *clnt);
+struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
+ char *uname, char *aname);
+struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname);
+struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
+ int clone);
+int p9_client_open(struct p9_fid *fid, int mode);
+int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
+ char *extension);
+int p9_client_clunk(struct p9_fid *fid);
+int p9_client_remove(struct p9_fid *fid);
+int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count);
+int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count);
+int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count);
+int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset,
+ u32 count);
+int p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
+ u32 count);
+struct p9_stat *p9_client_stat(struct p9_fid *fid);
+int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
+struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset);
+
+#endif /* NET_9P_CLIENT_H */
diff --git a/fs/9p/mux.h b/include/net/9p/conn.h
index fb10c50186a..583b6a2cb3d 100644
--- a/fs/9p/mux.h
+++ b/include/net/9p/conn.h
@@ -1,7 +1,7 @@
/*
- * linux/fs/9p/mux.h
+ * include/net/9p/conn.h
*
- * Multiplexer Definitions
+ * Connection Definitions
*
* Copyright (C) 2005 by Latchesar Ionkov <lucho@ionkov.net>
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
@@ -23,33 +23,35 @@
*
*/
-struct v9fs_mux_data;
-struct v9fs_req;
+#ifndef NET_9P_CONN_H
+#define NET_9P_CONN_H
+
+#undef P9_NONBLOCK
+
+struct p9_conn;
+struct p9_req;
/**
- * v9fs_mux_req_callback - callback function that is called when the
+ * p9_mux_req_callback - callback function that is called when the
* response of a request is received. The callback is called from
* a workqueue and shouldn't block.
*
+ * @req - request
* @a - the pointer that was specified when the request was send to be
* passed to the callback
- * @tc - request call
- * @rc - response call
- * @err - error code (non-zero if error occured)
*/
-typedef void (*v9fs_mux_req_callback)(struct v9fs_req *req, void *a);
+typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a);
-int v9fs_mux_global_init(void);
-void v9fs_mux_global_exit(void);
+struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
+ unsigned char *dotu);
+void p9_conn_destroy(struct p9_conn *);
+int p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc, struct p9_fcall **rc);
-struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
- unsigned char *extended);
-void v9fs_mux_destroy(struct v9fs_mux_data *);
+#ifdef P9_NONBLOCK
+int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
+ p9_conn_req_callback cb, void *a);
+#endif /* P9_NONBLOCK */
-int v9fs_mux_send(struct v9fs_mux_data *m, struct v9fs_fcall *tc);
-struct v9fs_fcall *v9fs_mux_recv(struct v9fs_mux_data *m);
-int v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc, struct v9fs_fcall **rc);
+void p9_conn_cancel(struct p9_conn *m, int err);
-void v9fs_mux_flush(struct v9fs_mux_data *m, int sendflush);
-void v9fs_mux_cancel(struct v9fs_mux_data *m, int err);
-int v9fs_errstr2errno(char *errstr, int len);
+#endif /* NET_9P_CONN_H */
diff --git a/fs/9p/transport.h b/include/net/9p/transport.h
index b38a4b8a41c..462d42279fb 100644
--- a/fs/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -1,5 +1,5 @@
/*
- * linux/fs/9p/transport.h
+ * include/net/9p/transport.h
*
* Transport Definition
*
@@ -23,23 +23,27 @@
*
*/
-enum v9fs_transport_status {
+#ifndef NET_9P_TRANSPORT_H
+#define NET_9P_TRANSPORT_H
+
+enum p9_transport_status {
Connected,
Disconnected,
Hung,
};
-struct v9fs_transport {
- enum v9fs_transport_status status;
+struct p9_transport {
+ enum p9_transport_status status;
void *priv;
- int (*init) (struct v9fs_session_info *, const char *, char *);
- int (*write) (struct v9fs_transport *, void *, int);
- int (*read) (struct v9fs_transport *, void *, int);
- void (*close) (struct v9fs_transport *);
- unsigned int (*poll)(struct v9fs_transport *, struct poll_table_struct *);
+ int (*write) (struct p9_transport *, void *, int);
+ int (*read) (struct p9_transport *, void *, int);
+ void (*close) (struct p9_transport *);
+ unsigned int (*poll)(struct p9_transport *, struct poll_table_struct *);
};
-extern struct v9fs_transport v9fs_trans_tcp;
-extern struct v9fs_transport v9fs_trans_unix;
-extern struct v9fs_transport v9fs_trans_fd;
+struct p9_transport *p9_trans_create_tcp(const char *addr, int port);
+struct p9_transport *p9_trans_create_unix(const char *addr);
+struct p9_transport *p9_trans_create_fd(int rfd, int wfd);
+
+#endif /* NET_9P_TRANSPORT_H */
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 8b06c2f3657..68b4eaf7719 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -19,7 +19,6 @@ struct tcf_common {
struct gnet_stats_basic tcfc_bstats;
struct gnet_stats_queue tcfc_qstats;
struct gnet_stats_rate_est tcfc_rate_est;
- spinlock_t *tcfc_stats_lock;
spinlock_t tcfc_lock;
};
#define tcf_next common.tcfc_next
@@ -32,7 +31,6 @@ struct tcf_common {
#define tcf_bstats common.tcfc_bstats
#define tcf_qstats common.tcfc_qstats
#define tcf_rate_est common.tcfc_rate_est
-#define tcf_stats_lock common.tcfc_stats_lock
#define tcf_lock common.tcfc_lock
struct tcf_police {
@@ -123,34 +121,4 @@ extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, in
extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
extern int tcf_action_copy_stats (struct sk_buff *,struct tc_action *, int);
#endif /* CONFIG_NET_CLS_ACT */
-
-extern int tcf_police(struct sk_buff *skb, struct tcf_police *p);
-extern void tcf_police_destroy(struct tcf_police *p);
-extern struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est);
-extern int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p);
-extern int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p);
-
-static inline int
-tcf_police_release(struct tcf_police *p, int bind)
-{
- int ret = 0;
-#ifdef CONFIG_NET_CLS_ACT
- if (p) {
- if (bind)
- p->tcf_bindcnt--;
-
- p->tcf_refcnt--;
- if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) {
- tcf_police_destroy(p);
- ret = 1;
- }
- }
-#else
- if (p && --p->tcf_refcnt == 0)
- tcf_police_destroy(p);
-
-#endif /* CONFIG_NET_CLS_ACT */
- return ret;
-}
-
#endif
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index f3531d0bcd0..33b593e1744 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -61,7 +61,7 @@ extern int addrconf_set_dstaddr(void __user *arg);
extern int ipv6_chk_addr(struct in6_addr *addr,
struct net_device *dev,
int strict);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
extern int ipv6_chk_home_addr(struct in6_addr *addr);
#endif
extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index c0398f5a8cb..6de1e9e35c7 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -62,13 +62,11 @@ struct unix_skb_parms {
#define UNIXCREDS(skb) (&UNIXCB((skb)).creds)
#define UNIXSID(skb) (&UNIXCB((skb)).secid)
-#define unix_state_rlock(s) spin_lock(&unix_sk(s)->lock)
-#define unix_state_runlock(s) spin_unlock(&unix_sk(s)->lock)
-#define unix_state_wlock(s) spin_lock(&unix_sk(s)->lock)
-#define unix_state_wlock_nested(s) \
+#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
+#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
+#define unix_state_lock_nested(s) \
spin_lock_nested(&unix_sk(s)->lock, \
SINGLE_DEPTH_NESTING)
-#define unix_state_wunlock(s) spin_unlock(&unix_sk(s)->lock)
#ifdef __KERNEL__
/* The AF_UNIX socket */
@@ -81,9 +79,10 @@ struct unix_sock {
struct mutex readlock;
struct sock *peer;
struct sock *other;
- struct sock *gc_tree;
+ struct list_head link;
atomic_t inflight;
spinlock_t lock;
+ unsigned int gc_candidate : 1;
wait_queue_head_t peer_wait;
};
#define unix_sk(__sk) ((struct unix_sock *)__sk)
diff --git a/include/net/ax88796.h b/include/net/ax88796.h
new file mode 100644
index 00000000000..ee786a043b3
--- /dev/null
+++ b/include/net/ax88796.h
@@ -0,0 +1,27 @@
+/* include/net/ax88796.h
+ *
+ * Copyright 2005 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#ifndef __NET_AX88796_PLAT_H
+#define __NET_AX88796_PLAT_H
+
+#define AXFLG_HAS_EEPROM (1<<0)
+#define AXFLG_MAC_FROMDEV (1<<1) /* device already has MAC */
+
+struct ax_plat_data {
+ unsigned int flags;
+ unsigned char wordlength; /* 1 or 2 */
+ unsigned char dcr_val; /* default value for DCR */
+ unsigned char rcr_val; /* default value for RCR */
+ unsigned char gpoc_val; /* default value for GPOC */
+ u32 *reg_offsets; /* register offsets */
+};
+
+#endif /* __NET_AX88796_PLAT_H */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 93ce272a5d2..ebfb96b4110 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -107,14 +107,14 @@ enum {
#define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */
#define HCI_INIT_TIMEOUT (10000) /* 10 seconds */
-/* HCI Packet types */
+/* HCI data types */
#define HCI_COMMAND_PKT 0x01
#define HCI_ACLDATA_PKT 0x02
#define HCI_SCODATA_PKT 0x03
#define HCI_EVENT_PKT 0x04
#define HCI_VENDOR_PKT 0xff
-/* HCI Packet types */
+/* HCI packet types */
#define HCI_DM1 0x0008
#define HCI_DM3 0x0400
#define HCI_DM5 0x4000
@@ -129,6 +129,14 @@ enum {
#define SCO_PTYPE_MASK (HCI_HV1 | HCI_HV2 | HCI_HV3)
#define ACL_PTYPE_MASK (~SCO_PTYPE_MASK)
+/* eSCO packet types */
+#define ESCO_HV1 0x0001
+#define ESCO_HV2 0x0002
+#define ESCO_HV3 0x0004
+#define ESCO_EV3 0x0008
+#define ESCO_EV4 0x0010
+#define ESCO_EV5 0x0020
+
/* ACL flags */
#define ACL_CONT 0x01
#define ACL_START 0x02
@@ -138,6 +146,7 @@ enum {
/* Baseband links */
#define SCO_LINK 0x00
#define ACL_LINK 0x01
+#define ESCO_LINK 0x02
/* LMP features */
#define LMP_3SLOT 0x01
@@ -162,6 +171,11 @@ enum {
#define LMP_PSCHEME 0x02
#define LMP_PCONTROL 0x04
+#define LMP_ESCO 0x80
+
+#define LMP_EV4 0x01
+#define LMP_EV5 0x02
+
#define LMP_SNIFF_SUBR 0x02
/* Connection modes */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index c0fc39620f3..8f67c8a7169 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -78,6 +78,7 @@ struct hci_dev {
__u16 voice_setting;
__u16 pkt_type;
+ __u16 esco_type;
__u16 link_policy;
__u16 link_mode;
@@ -109,6 +110,7 @@ struct hci_dev {
struct sk_buff_head cmd_q;
struct sk_buff *sent_cmd;
+ struct sk_buff *reassembly[3];
struct semaphore req_lock;
wait_queue_head_t req_wait_q;
@@ -437,6 +439,8 @@ static inline int hci_recv_frame(struct sk_buff *skb)
return 0;
}
+int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
+
int hci_register_sysfs(struct hci_dev *hdev);
void hci_unregister_sysfs(struct hci_dev *hdev);
void hci_conn_add_sysfs(struct hci_conn *conn);
@@ -449,6 +453,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
/* ----- HCI protocols ----- */
struct hci_proto {
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 3c563f02907..25aa575db80 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc
#define RFCOMM_RELEASE_ONHUP 1
#define RFCOMM_HANGUP_NOW 2
#define RFCOMM_TTY_ATTACHED 3
+#define RFCOMM_TTY_RELEASED 4
struct rfcomm_dev_req {
s16 dev_id;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 88171f8ce58..7edaef6b29d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -11,6 +11,44 @@
* Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
*/
+
+/* Radiotap header iteration
+ * implemented in net/wireless/radiotap.c
+ * docs in Documentation/networking/radiotap-headers.txt
+ */
+/**
+ * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
+ * @rtheader: pointer to the radiotap header we are walking through
+ * @max_length: length of radiotap header in cpu byte ordering
+ * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg
+ * @this_arg: pointer to current radiotap arg
+ * @arg_index: internal next argument index
+ * @arg: internal next argument pointer
+ * @next_bitmap: internal pointer to next present u32
+ * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
+ */
+
+struct ieee80211_radiotap_iterator {
+ struct ieee80211_radiotap_header *rtheader;
+ int max_length;
+ int this_arg_index;
+ u8 *this_arg;
+
+ int arg_index;
+ u8 *arg;
+ __le32 *next_bitmap;
+ u32 bitmap_shifter;
+};
+
+extern int ieee80211_radiotap_iterator_init(
+ struct ieee80211_radiotap_iterator *iterator,
+ struct ieee80211_radiotap_header *radiotap_header,
+ int max_length);
+
+extern int ieee80211_radiotap_iterator_next(
+ struct ieee80211_radiotap_iterator *iterator);
+
+
/* from net/wireless.h */
struct wiphy;
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index 4f90f5554fa..a6bb94530cf 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -203,12 +203,10 @@ static inline int cipso_v4_cache_add(const struct sk_buff *skb,
#ifdef CONFIG_NETLABEL
void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
-int cipso_v4_socket_setattr(const struct socket *sock,
- const struct cipso_v4_doi *doi_def,
- const struct netlbl_lsm_secattr *secattr);
+int cipso_v4_sock_setattr(struct sock *sk,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr);
int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
-int cipso_v4_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr);
int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr);
int cipso_v4_validate(unsigned char **option);
@@ -220,9 +218,9 @@ static inline void cipso_v4_error(struct sk_buff *skb,
return;
}
-static inline int cipso_v4_socket_setattr(const struct socket *sock,
- const struct cipso_v4_doi *doi_def,
- const struct netlbl_lsm_secattr *secattr)
+static inline int cipso_v4_sock_setattr(struct sock *sk,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
}
@@ -233,12 +231,6 @@ static inline int cipso_v4_sock_getattr(struct sock *sk,
return -ENOSYS;
}
-static inline int cipso_v4_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
-{
- return -ENOSYS;
-}
-
static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr)
{
diff --git a/include/net/dn.h b/include/net/dn.h
index ac4ce909174..627778384c8 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -3,7 +3,6 @@
#include <linux/dn.h>
#include <net/sock.h>
-#include <net/tcp.h>
#include <asm/byteorder.h>
#define dn_ntohs(x) le16_to_cpu(x)
diff --git a/include/net/dst.h b/include/net/dst.h
index 82270f9332d..e9ff4a4caef 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -47,7 +47,6 @@ struct dst_entry
#define DST_NOXFRM 2
#define DST_NOPOLICY 4
#define DST_NOHASH 8
-#define DST_BALANCED 0x10
unsigned long expires;
unsigned short header_len; /* more space at head required */
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index ed3a8872c6c..83e41dd15cc 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -64,7 +64,7 @@ struct fib_rules_ops
void (*flush_cache)(void);
int nlgroup;
- struct nla_policy *policy;
+ const struct nla_policy *policy;
struct list_head *rules_list;
struct module *owner;
};
diff --git a/include/net/flow.h b/include/net/flow.h
index f3cc1f81261..af59fa5cc1f 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -67,20 +67,16 @@ struct flowi {
__be32 spi;
-#ifdef CONFIG_IPV6_MIP6
struct {
__u8 type;
} mht;
-#endif
} uli_u;
#define fl_ip_sport uli_u.ports.sport
#define fl_ip_dport uli_u.ports.dport
#define fl_icmp_type uli_u.icmpt.type
#define fl_icmp_code uli_u.icmpt.code
#define fl_ipsec_spi uli_u.spi
-#ifdef CONFIG_IPV6_MIP6
#define fl_mh_type uli_u.mht.type
-#endif
__u32 secid; /* used by xfrm; see secid.txt */
} __attribute__((__aligned__(BITS_PER_LONG/8)));
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index adff4c898d5..b6eaca122db 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -60,7 +60,7 @@ struct genl_ops
{
u8 cmd;
unsigned int flags;
- struct nla_policy *policy;
+ const struct nla_policy *policy;
int (*doit)(struct sk_buff *skb,
struct genl_info *info);
int (*dumpit)(struct sk_buff *skb,
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 09a2532699b..47d52b2414d 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -209,9 +209,6 @@ static inline void inet_twsk_put(struct inet_timewait_sock *tw)
extern struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
const int state);
-extern void __inet_twsk_kill(struct inet_timewait_sock *tw,
- struct inet_hashinfo *hashinfo);
-
extern void __inet_twsk_hashdance(struct inet_timewait_sock *tw,
struct sock *sk,
struct inet_hashinfo *hashinfo);
diff --git a/include/net/ip.h b/include/net/ip.h
index bb207db0367..abf2820a112 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -143,6 +143,7 @@ struct ip_reply_arg {
__wsum csum;
int csumoffset; /* u16 offset of csum in iov[0].iov_base */
/* -1 if not needed */
+ int bound_dev_if;
};
void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 5a4a0366c24..8cadc77c7df 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -39,7 +39,6 @@ struct fib_config {
int fc_mx_len;
int fc_mp_len;
u32 fc_flow;
- u32 fc_mp_alg;
u32 fc_nlflags;
struct nl_info fc_nlinfo;
};
@@ -86,9 +85,6 @@ struct fib_info {
#ifdef CONFIG_IP_ROUTE_MULTIPATH
int fib_power;
#endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- u32 fib_mp_alg;
-#endif
struct fib_nh fib_nh[0];
#define fib_dev fib_nh[0].nh_dev
};
@@ -103,10 +99,6 @@ struct fib_result {
unsigned char nh_sel;
unsigned char type;
unsigned char scope;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- __be32 network;
- __be32 netmask;
-#endif
struct fib_info *fi;
#ifdef CONFIG_IP_MULTIPLE_TABLES
struct fib_rule *r;
@@ -145,14 +137,6 @@ struct fib_result_nl {
#define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
#define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif)
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-#define FIB_RES_NETWORK(res) ((res).network)
-#define FIB_RES_NETMASK(res) ((res).netmask)
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-#define FIB_RES_NETWORK(res) (0)
-#define FIB_RES_NETMASK(res) (0)
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */
-
struct fib_table {
struct hlist_node tb_hlist;
u32 tb_id;
@@ -213,7 +197,7 @@ extern void fib_select_default(const struct flowi *flp, struct fib_result *res);
#endif /* CONFIG_IP_MULTIPLE_TABLES */
/* Exported by fib_frontend.c */
-extern struct nla_policy rtm_ipv4_policy[];
+extern const struct nla_policy rtm_ipv4_policy[];
extern void ip_fib_init(void);
extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
struct net_device *dev, __be32 *spec_dst, u32 *itag);
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
deleted file mode 100644
index 25b56571e54..00000000000
--- a/include/net/ip_mp_alg.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* ip_mp_alg.h: IPV4 multipath algorithm support.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#ifndef _NET_IP_MP_ALG_H
-#define _NET_IP_MP_ALG_H
-
-#include <linux/ip_mp_alg.h>
-#include <net/flow.h>
-#include <net/route.h>
-
-struct fib_nh;
-
-struct ip_mp_alg_ops {
- void (*mp_alg_select_route)(const struct flowi *flp,
- struct rtable *rth, struct rtable **rp);
- void (*mp_alg_flush)(void);
- void (*mp_alg_set_nhinfo)(__be32 network, __be32 netmask,
- unsigned char prefixlen,
- const struct fib_nh *nh);
- void (*mp_alg_remove)(struct rtable *rth);
-};
-
-extern int multipath_alg_register(struct ip_mp_alg_ops *, enum ip_mp_alg);
-extern void multipath_alg_unregister(struct ip_mp_alg_ops *, enum ip_mp_alg);
-
-extern struct ip_mp_alg_ops *ip_mp_alg_table[];
-
-static inline int multipath_select_route(const struct flowi *flp,
- struct rtable *rth,
- struct rtable **rp)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
- /* mp_alg_select_route _MUST_ be implemented */
- if (ops && (rth->u.dst.flags & DST_BALANCED)) {
- ops->mp_alg_select_route(flp, rth, rp);
- return 1;
- }
-#endif
- return 0;
-}
-
-static inline void multipath_flush(void)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- int i;
-
- for (i = IP_MP_ALG_NONE; i <= IP_MP_ALG_MAX; i++) {
- struct ip_mp_alg_ops *ops = ip_mp_alg_table[i];
-
- if (ops && ops->mp_alg_flush)
- ops->mp_alg_flush();
- }
-#endif
-}
-
-static inline void multipath_set_nhinfo(struct rtable *rth,
- __be32 network, __be32 netmask,
- unsigned char prefixlen,
- const struct fib_nh *nh)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
- if (ops && ops->mp_alg_set_nhinfo)
- ops->mp_alg_set_nhinfo(network, netmask, prefixlen, nh);
-#endif
-}
-
-static inline void multipath_remove(struct rtable *rth)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- struct ip_mp_alg_ops *ops = ip_mp_alg_table[rth->rt_multipath_alg];
-
- if (ops && ops->mp_alg_remove &&
- (rth->u.dst.flags & DST_BALANCED))
- ops->mp_alg_remove(rth);
-#endif
-}
-
-static inline int multipath_comparekeys(const struct flowi *flp1,
- const struct flowi *flp2)
-{
- return flp1->fl4_dst == flp2->fl4_dst &&
- flp1->fl4_src == flp2->fl4_src &&
- flp1->oif == flp2->oif &&
- flp1->mark == flp2->mark &&
- !((flp1->fl4_tos ^ flp2->fl4_tos) &
- (IPTOS_RT_MASK | RTO_ONLINK));
-}
-
-#endif /* _NET_IP_MP_ALG_H */
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 78a0d06d98d..46b9dce82f6 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -512,10 +512,6 @@ extern int ipv6_ext_hdr(u8 nexthdr);
extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
-extern struct ipv6_txoptions * ipv6_invert_rthdr(struct sock *sk,
- struct ipv6_rt_hdr *hdr);
-
-
/*
* socket options (ipv6_sockglue.c)
*/
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 36bee441aa5..08387553b57 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -125,6 +125,9 @@ extern void irda_sysctl_unregister(void);
extern int irsock_init(void);
extern void irsock_cleanup(void);
+extern int irda_nl_register(void);
+extern void irda_nl_unregister(void);
+
extern int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype,
struct net_device *orig_dev);
diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h
index f0248fb8e19..9d0c78ea92f 100644
--- a/include/net/irda/irlap.h
+++ b/include/net/irda/irlap.h
@@ -208,6 +208,8 @@ struct irlap_cb {
int xbofs_delay; /* Nr of XBOF's used to MTT */
int bofs_count; /* Negotiated extra BOFs */
int next_bofs; /* Negotiated extra BOFs after next frame */
+
+ int mode; /* IrLAP mode (primary, secondary or monitor) */
};
/*
@@ -289,4 +291,21 @@ static inline void irlap_clear_disconnect(struct irlap_cb *self)
self->disconnect_pending = FALSE;
}
+/*
+ * Function irlap_next_state (self, state)
+ *
+ * Switches state and provides debug information
+ *
+ */
+static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state)
+{
+ /*
+ if (!self || self->magic != LAP_MAGIC)
+ return;
+
+ IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]);
+ */
+ self->state = state;
+}
+
#endif
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h
index f9bd11be189..b6c468cd7f5 100644
--- a/include/net/iucv/af_iucv.h
+++ b/include/net/iucv/af_iucv.h
@@ -60,6 +60,7 @@ struct iucv_sock {
char dst_user_id[8];
char dst_name[8];
struct list_head accept_q;
+ spinlock_t accept_q_lock;
struct sock *parent;
struct iucv_path *path;
struct sk_buff_head send_skb_q;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a7f122b7994..c34fd9a6160 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -347,9 +347,16 @@ enum ieee80211_if_types {
* @mac_addr: pointer to MAC address of the interface. This pointer is valid
* until the interface is removed (i.e. it cannot be used after
* remove_interface() callback was called for this interface).
+ * This pointer will be %NULL for monitor interfaces, be careful.
*
* This structure is used in add_interface() and remove_interface()
* callbacks of &struct ieee80211_hw.
+ *
+ * When you allow multiple interfaces to be added to your PHY, take care
+ * that the hardware can actually handle multiple MAC addresses. However,
+ * also take care that when there's no interface left with mac_addr != %NULL
+ * you remove the MAC address from the device to avoid acknowledging packets
+ * in pure monitor mode.
*/
struct ieee80211_if_init_conf {
int if_id;
@@ -574,10 +581,11 @@ struct ieee80211_ops {
* to returning zero. By returning non-zero addition of the interface
* is inhibited. Unless monitor_during_oper is set, it is guaranteed
* that monitor interfaces and normal interfaces are mutually
- * exclusive. The open() handler is called after add_interface()
- * if this is the first device added. At least one of the open()
- * open() and add_interface() callbacks has to be assigned. If
- * add_interface() is NULL, one STA interface is permitted only. */
+ * exclusive. If assigned, the open() handler is called after
+ * add_interface() if this is the first device added. The
+ * add_interface() callback has to be assigned because it is the only
+ * way to obtain the requested MAC address for any interface.
+ */
int (*add_interface)(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf);
@@ -921,12 +929,6 @@ struct sk_buff *
ieee80211_get_buffered_bc(struct ieee80211_hw *hw, int if_id,
struct ieee80211_tx_control *control);
-/* Low level drivers that have their own MLME and MAC indicate
- * the aid for an associating station with this call */
-int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw,
- u8 *peer_address, u16 aid);
-
-
/* Given an sk_buff with a raw 802.11 header at the data pointer this function
* returns the 802.11 header length in bytes (not including encryption
* headers). If the data in the sk_buff is too short to contain a valid 802.11
diff --git a/include/net/mip6.h b/include/net/mip6.h
index 68263c6d999..63272610a24 100644
--- a/include/net/mip6.h
+++ b/include/net/mip6.h
@@ -54,8 +54,4 @@ struct ip6_mh {
#define IP6_MH_TYPE_BERROR 7 /* Binding Error */
#define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR
-extern int mip6_init(void);
-extern void mip6_fini(void);
-extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb);
-
#endif
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 1401ccc051c..7a671603fca 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -9,29 +9,10 @@
#ifndef _NF_CONNTRACK_IPV4_H
#define _NF_CONNTRACK_IPV4_H
-#ifdef CONFIG_NF_NAT_NEEDED
-#include <net/netfilter/nf_nat.h>
-#include <linux/netfilter/nf_conntrack_pptp.h>
-
-/* per conntrack: nat application helper private data */
-union nf_conntrack_nat_help {
- /* insert nat helper private data here */
- struct nf_nat_pptp nat_pptp_info;
-};
-
-struct nf_conn_nat {
- struct nf_nat_info info;
- union nf_conntrack_nat_help help;
-#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
- defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
- int masq_index;
-#endif
-};
-#endif /* CONFIG_NF_NAT_NEEDED */
-
/* Returns new sk_buff, or NULL */
-struct sk_buff *
-nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
+struct sk_buff *nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
+
+extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
diff --git a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
index b4b6049e01f..5a896590437 100644
--- a/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_conntrack_ipv6.h
@@ -7,7 +7,7 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
-extern int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start,
+extern int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start,
u8 *nexthdrp, int len);
extern int nf_ct_frag6_init(void);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 4732432f8eb..810020ec345 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -82,6 +82,8 @@ struct nf_conn_help {
union nf_conntrack_help help;
+ struct hlist_head expectations;
+
/* Current number of expected connections */
unsigned int expecting;
};
@@ -117,9 +119,6 @@ struct nf_conn
/* Unique ID that identifies this conntrack*/
unsigned int id;
- /* features - nat, helper, ... used by allocating system */
- u_int32_t features;
-
#if defined(CONFIG_NF_CONNTRACK_MARK)
u_int32_t mark;
#endif
@@ -131,8 +130,8 @@ struct nf_conn
/* Storage reserved for other modules: */
union nf_conntrack_proto proto;
- /* features dynamically at the end: helper, nat (both optional) */
- char data[0];
+ /* Extensions */
+ struct nf_ct_ext *ext;
};
static inline struct nf_conn *
@@ -175,6 +174,10 @@ static inline void nf_ct_put(struct nf_conn *ct)
extern int nf_ct_l3proto_try_module_get(unsigned short l3proto);
extern void nf_ct_l3proto_module_put(unsigned short l3proto);
+extern struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced);
+extern void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced,
+ int size);
+
extern struct nf_conntrack_tuple_hash *
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack);
@@ -183,6 +186,10 @@ extern void nf_conntrack_hash_insert(struct nf_conn *ct);
extern void nf_conntrack_flush(void);
+extern int nf_ct_get_tuplepr(const struct sk_buff *skb,
+ unsigned int nhoff,
+ u_int16_t l3num,
+ struct nf_conntrack_tuple *tuple);
extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
@@ -216,9 +223,6 @@ extern void nf_conntrack_tcp_update(struct sk_buff *skb,
struct nf_conn *conntrack,
int dir);
-/* Call me when a conntrack is destroyed. */
-extern void (*nf_conntrack_destroyed)(struct nf_conn *conntrack);
-
/* Fake conntrack entry for untracked connections */
extern struct nf_conn nf_conntrack_untracked;
@@ -262,60 +266,10 @@ do { \
local_bh_enable(); \
} while (0)
-/* no helper, no nat */
-#define NF_CT_F_BASIC 0
-/* for helper */
-#define NF_CT_F_HELP 1
-/* for nat. */
-#define NF_CT_F_NAT 2
-#define NF_CT_F_NUM 4
-
extern int
nf_conntrack_register_cache(u_int32_t features, const char *name, size_t size);
extern void
nf_conntrack_unregister_cache(u_int32_t features);
-/* valid combinations:
- * basic: nf_conn, nf_conn .. nf_conn_help
- * nat: nf_conn .. nf_conn_nat, nf_conn .. nf_conn_nat .. nf_conn help
- */
-#ifdef CONFIG_NF_NAT_NEEDED
-static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
-{
- unsigned int offset = sizeof(struct nf_conn);
-
- if (!(ct->features & NF_CT_F_NAT))
- return NULL;
-
- offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
- return (struct nf_conn_nat *) ((void *)ct + offset);
-}
-
-static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
-{
- unsigned int offset = sizeof(struct nf_conn);
-
- if (!(ct->features & NF_CT_F_HELP))
- return NULL;
- if (ct->features & NF_CT_F_NAT) {
- offset = ALIGN(offset, __alignof__(struct nf_conn_nat));
- offset += sizeof(struct nf_conn_nat);
- }
-
- offset = ALIGN(offset, __alignof__(struct nf_conn_help));
- return (struct nf_conn_help *) ((void *)ct + offset);
-}
-#else /* No NAT */
-static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
-{
- unsigned int offset = sizeof(struct nf_conn);
-
- if (!(ct->features & NF_CT_F_HELP))
- return NULL;
-
- offset = ALIGN(offset, __alignof__(struct nf_conn_help));
- return (struct nf_conn_help *) ((void *)ct + offset);
-}
-#endif /* CONFIG_NF_NAT_NEEDED */
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_H */
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index 9fb906688ff..4056f5f08da 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -30,6 +30,9 @@ extern void nf_conntrack_cleanup(void);
extern int nf_conntrack_proto_init(void);
extern void nf_conntrack_proto_fini(void);
+extern int nf_conntrack_helper_init(void);
+extern void nf_conntrack_helper_fini(void);
+
struct nf_conntrack_l3proto;
extern struct nf_conntrack_l3proto *nf_ct_find_l3proto(u_int16_t pf);
/* Like above, but you already have conntrack read lock. */
@@ -55,8 +58,7 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
/* Find a connection corresponding to a tuple. */
extern struct nf_conntrack_tuple_hash *
-nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
- const struct nf_conn *ignored_conntrack);
+nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple);
extern int __nf_conntrack_confirm(struct sk_buff **pskb);
@@ -81,9 +83,8 @@ print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
struct nf_conntrack_l3proto *l3proto,
struct nf_conntrack_l4proto *proto);
-extern struct list_head *nf_conntrack_hash;
-extern struct list_head nf_conntrack_expect_list;
+extern struct hlist_head *nf_conntrack_hash;
extern rwlock_t nf_conntrack_lock ;
-extern struct list_head unconfirmed;
+extern struct hlist_head unconfirmed;
#endif /* _NF_CONNTRACK_CORE_H */
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 811c9073c53..f0b9078235c 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -49,15 +49,15 @@ static inline void nf_conntrack_event(enum ip_conntrack_events event,
atomic_notifier_call_chain(&nf_conntrack_chain, event, ct);
}
-extern struct atomic_notifier_head nf_conntrack_expect_chain;
-extern int nf_conntrack_expect_register_notifier(struct notifier_block *nb);
-extern int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb);
+extern struct atomic_notifier_head nf_ct_expect_chain;
+extern int nf_ct_expect_register_notifier(struct notifier_block *nb);
+extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb);
static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
- struct nf_conntrack_expect *exp)
+nf_ct_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp)
{
- atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp);
+ atomic_notifier_call_chain(&nf_ct_expect_chain, event, exp);
}
#else /* CONFIG_NF_CONNTRACK_EVENTS */
@@ -67,9 +67,8 @@ static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
static inline void nf_conntrack_event(enum ip_conntrack_events event,
struct nf_conn *ct) {}
static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
-static inline void
-nf_conntrack_expect_event(enum ip_conntrack_expect_events event,
- struct nf_conntrack_expect *exp) {}
+static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
+ struct nf_conntrack_expect *exp) {}
static inline void nf_ct_event_cache_flush(void) {}
#endif /* CONFIG_NF_CONNTRACK_EVENTS */
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 173c7c1eff2..cae1a0dce36 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -6,17 +6,21 @@
#define _NF_CONNTRACK_EXPECT_H
#include <net/netfilter/nf_conntrack.h>
-extern struct list_head nf_conntrack_expect_list;
-extern struct kmem_cache *nf_conntrack_expect_cachep;
-extern const struct file_operations exp_file_ops;
+extern struct hlist_head *nf_ct_expect_hash;
+extern unsigned int nf_ct_expect_hsize;
+extern unsigned int nf_ct_expect_max;
struct nf_conntrack_expect
{
- /* Internal linked list (global expectation list) */
- struct list_head list;
+ /* Conntrack expectation list member */
+ struct hlist_node lnode;
+
+ /* Hash member */
+ struct hlist_node hnode;
/* We expect this tuple, with the following mask */
- struct nf_conntrack_tuple tuple, mask;
+ struct nf_conntrack_tuple tuple;
+ struct nf_conntrack_tuple_mask mask;
/* Function to call after setup and insertion */
void (*expectfn)(struct nf_conn *new,
@@ -52,29 +56,31 @@ struct nf_conntrack_expect
#define NF_CT_EXPECT_PERMANENT 0x1
+int nf_conntrack_expect_init(void);
+void nf_conntrack_expect_fini(void);
struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple);
struct nf_conntrack_expect *
-nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple);
+nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple);
struct nf_conntrack_expect *
-find_expectation(const struct nf_conntrack_tuple *tuple);
+nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple);
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
void nf_ct_remove_expectations(struct nf_conn *ct);
-void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
+void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
/* Allocate space for an expectation: this is mandatory before calling
- nf_conntrack_expect_related. You will have to call put afterwards. */
-struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me);
-void nf_conntrack_expect_init(struct nf_conntrack_expect *, int,
- union nf_conntrack_address *,
- union nf_conntrack_address *,
- u_int8_t, __be16 *, __be16 *);
-void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
-int nf_conntrack_expect_related(struct nf_conntrack_expect *expect);
+ nf_ct_expect_related. You will have to call put afterwards. */
+struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
+void nf_ct_expect_init(struct nf_conntrack_expect *, int,
+ union nf_conntrack_address *,
+ union nf_conntrack_address *,
+ u_int8_t, __be16 *, __be16 *);
+void nf_ct_expect_put(struct nf_conntrack_expect *exp);
+int nf_ct_expect_related(struct nf_conntrack_expect *expect);
#endif /*_NF_CONNTRACK_EXPECT_H*/
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
new file mode 100644
index 00000000000..73b5711faf3
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -0,0 +1,85 @@
+#ifndef _NF_CONNTRACK_EXTEND_H
+#define _NF_CONNTRACK_EXTEND_H
+
+#include <net/netfilter/nf_conntrack.h>
+
+enum nf_ct_ext_id
+{
+ NF_CT_EXT_HELPER,
+ NF_CT_EXT_NAT,
+ NF_CT_EXT_NUM,
+};
+
+#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
+#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
+
+/* Extensions: optional stuff which isn't permanently in struct. */
+struct nf_ct_ext {
+ u8 offset[NF_CT_EXT_NUM];
+ u8 len;
+ u8 real_len;
+ char data[0];
+};
+
+static inline int nf_ct_ext_exist(const struct nf_conn *ct, u8 id)
+{
+ return (ct->ext && ct->ext->offset[id]);
+}
+
+static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id)
+{
+ if (!nf_ct_ext_exist(ct, id))
+ return NULL;
+
+ return (void *)ct->ext + ct->ext->offset[id];
+}
+#define nf_ct_ext_find(ext, id) \
+ ((id##_TYPE *)__nf_ct_ext_find((ext), (id)))
+
+/* Destroy all relationships */
+extern void __nf_ct_ext_destroy(struct nf_conn *ct);
+static inline void nf_ct_ext_destroy(struct nf_conn *ct)
+{
+ if (ct->ext)
+ __nf_ct_ext_destroy(ct);
+}
+
+/* Free operation. If you want to free a object referred from private area,
+ * please implement __nf_ct_ext_free() and call it.
+ */
+static inline void nf_ct_ext_free(struct nf_conn *ct)
+{
+ if (ct->ext)
+ kfree(ct->ext);
+}
+
+/* Add this type, returns pointer to data or NULL. */
+void *
+__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
+#define nf_ct_ext_add(ct, id, gfp) \
+ ((id##_TYPE *)__nf_ct_ext_add((ct), (id), (gfp)))
+
+#define NF_CT_EXT_F_PREALLOC 0x0001
+
+struct nf_ct_ext_type
+{
+ /* Destroys relationships (can be NULL). */
+ void (*destroy)(struct nf_conn *ct);
+ /* Called when realloacted (can be NULL).
+ Contents has already been moved. */
+ void (*move)(struct nf_conn *ct, void *old);
+
+ enum nf_ct_ext_id id;
+
+ unsigned int flags;
+
+ /* Length and min alignment. */
+ u8 len;
+ u8 align;
+ /* initial size of nf_ct_ext. */
+ u8 alloc_size;
+};
+
+int nf_ct_extend_register(struct nf_ct_ext_type *type);
+void nf_ct_extend_unregister(struct nf_ct_ext_type *type);
+#endif /* _NF_CONNTRACK_EXTEND_H */
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 8c72ac9f0ab..d04f99964d9 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -10,12 +10,13 @@
#ifndef _NF_CONNTRACK_HELPER_H
#define _NF_CONNTRACK_HELPER_H
#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
struct module;
struct nf_conntrack_helper
-{
- struct list_head list; /* Internal use. */
+{
+ struct hlist_node hnode; /* Internal use. */
const char *name; /* name of the module */
struct module *me; /* pointer to self */
@@ -23,10 +24,9 @@ struct nf_conntrack_helper
* expected connections */
unsigned int timeout; /* timeout for expecteds */
- /* Mask of things we will help (compared against server response) */
+ /* Tuple of things we will help (compared against server response) */
struct nf_conntrack_tuple tuple;
- struct nf_conntrack_tuple mask;
-
+
/* Function to call when data passes; return verdict, or -1 to
invalidate. */
int (*help)(struct sk_buff **pskb,
@@ -52,4 +52,10 @@ extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
+extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
+
+static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
+{
+ return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+}
#endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 96a58d8e1d3..3c58a2c4df2 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -58,13 +58,11 @@ struct nf_conntrack_l3proto
/*
* Called before tracking.
- * *dataoff: offset of protocol header (TCP, UDP,...) in *pskb
+ * *dataoff: offset of protocol header (TCP, UDP,...) in skb
* *protonum: protocol number
*/
- int (*prepare)(struct sk_buff **pskb, unsigned int hooknum,
- unsigned int *dataoff, u_int8_t *protonum);
-
- u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
+ int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff,
+ unsigned int *dataoff, u_int8_t *protonum);
int (*tuple_to_nfattr)(struct sk_buff *skb,
const struct nf_conntrack_tuple *t);
@@ -91,8 +89,6 @@ extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
/* Existing built-in protocols */
-extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
-extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
static inline struct nf_conntrack_l3proto *
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 5d72b16e876..040dae5f0c9 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -100,6 +100,14 @@ struct nf_conntrack_tuple
} dst;
};
+struct nf_conntrack_tuple_mask
+{
+ struct {
+ union nf_conntrack_address u3;
+ union nf_conntrack_man_proto u;
+ } src;
+};
+
/* This is optimized opposed to a memset of the whole structure. Everything we
* really care about is the source/destination unions */
#define NF_CT_TUPLE_U_BLANK(tuple) \
@@ -112,11 +120,11 @@ struct nf_conntrack_tuple
#ifdef __KERNEL__
-#define NF_CT_DUMP_TUPLE(tp) \
-DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \
- (tp), (tp)->src.l3num, (tp)->dst.protonum, \
- NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
- NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
+#define NF_CT_DUMP_TUPLE(tp) \
+pr_debug("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \
+ (tp), (tp)->src.l3num, (tp)->dst.protonum, \
+ NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
+ NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
/* If we're the first tuple, it's the original dir. */
#define NF_CT_DIRECTION(h) \
@@ -125,8 +133,7 @@ DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \
/* Connections have two entries in the hash table: one for each way */
struct nf_conntrack_tuple_hash
{
- struct list_head list;
-
+ struct hlist_node hnode;
struct nf_conntrack_tuple tuple;
};
@@ -162,31 +169,44 @@ static inline int nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
return nf_ct_tuple_src_equal(t1, t2) && nf_ct_tuple_dst_equal(t1, t2);
}
+static inline int nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
+ const struct nf_conntrack_tuple_mask *m2)
+{
+ return (m1->src.u3.all[0] == m2->src.u3.all[0] &&
+ m1->src.u3.all[1] == m2->src.u3.all[1] &&
+ m1->src.u3.all[2] == m2->src.u3.all[2] &&
+ m1->src.u3.all[3] == m2->src.u3.all[3] &&
+ m1->src.u.all == m2->src.u.all);
+}
+
+static inline int nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
+ const struct nf_conntrack_tuple *t2,
+ const struct nf_conntrack_tuple_mask *mask)
+{
+ int count;
+
+ for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
+ if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
+ mask->src.u3.all[count])
+ return 0;
+ }
+
+ if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
+ return 0;
+
+ if (t1->src.l3num != t2->src.l3num ||
+ t1->dst.protonum != t2->dst.protonum)
+ return 0;
+
+ return 1;
+}
+
static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *mask)
+ const struct nf_conntrack_tuple_mask *mask)
{
- int count = 0;
-
- for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
- if ((t->src.u3.all[count] ^ tuple->src.u3.all[count]) &
- mask->src.u3.all[count])
- return 0;
- }
-
- for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
- if ((t->dst.u3.all[count] ^ tuple->dst.u3.all[count]) &
- mask->dst.u3.all[count])
- return 0;
- }
-
- if ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all ||
- (t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all ||
- (t->src.l3num ^ tuple->src.l3num) & mask->src.l3num ||
- (t->dst.protonum ^ tuple->dst.protonum) & mask->dst.protonum)
- return 0;
-
- return 1;
+ return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
+ nf_ct_tuple_dst_equal(t, tuple);
}
#endif /* _NF_CONNTRACK_TUPLE_H */
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index bc57dd7b9b5..6ae52f7c9f5 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -51,16 +51,31 @@ struct nf_nat_multi_range_compat
#ifdef __KERNEL__
#include <linux/list.h>
+#include <linux/netfilter/nf_conntrack_pptp.h>
+#include <net/netfilter/nf_conntrack_extend.h>
-/* The structure embedded in the conntrack structure. */
-struct nf_nat_info
+/* per conntrack: nat application helper private data */
+union nf_conntrack_nat_help
{
- struct list_head bysource;
- struct nf_nat_seq seq[IP_CT_DIR_MAX];
+ /* insert nat helper private data here */
+ struct nf_nat_pptp nat_pptp_info;
};
struct nf_conn;
+/* The structure embedded in the conntrack structure. */
+struct nf_conn_nat
+{
+ struct hlist_node bysource;
+ struct nf_nat_seq seq[IP_CT_DIR_MAX];
+ struct nf_conn *ct;
+ union nf_conntrack_nat_help help;
+#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+ defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
+ int masq_index;
+#endif
+};
+
/* Set up the info structure to map into this range. */
extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
const struct nf_nat_range *range,
@@ -70,7 +85,10 @@ extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack);
-extern int nf_nat_module_is_loaded;
+static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
+{
+ return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+}
#else /* !__KERNEL__: iptables wants this to compile. */
#define nf_nat_multi_range nf_nat_multi_range_compat
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
index 9778ffa9344..c3cd127ba4b 100644
--- a/include/net/netfilter/nf_nat_core.h
+++ b/include/net/netfilter/nf_nat_core.h
@@ -2,6 +2,7 @@
#define _NF_NAT_CORE_H
#include <linux/list.h>
#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat.h>
/* This header used to share core functionality between the standalone
NAT module, and the compatibility layer's use of NAT for masquerading. */
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 83da7e1f0d3..9b7d6f2ac9a 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -332,17 +332,15 @@ static inline int netlbl_secattr_catmap_setrng(
*/
#ifdef CONFIG_NETLABEL
-int netlbl_socket_setattr(const struct socket *sock,
- const struct netlbl_lsm_secattr *secattr);
+int netlbl_sock_setattr(struct sock *sk,
+ const struct netlbl_lsm_secattr *secattr);
int netlbl_sock_getattr(struct sock *sk,
struct netlbl_lsm_secattr *secattr);
-int netlbl_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr);
int netlbl_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr);
void netlbl_skbuff_err(struct sk_buff *skb, int error);
#else
-static inline int netlbl_socket_setattr(const struct socket *sock,
+static inline int netlbl_sock_setattr(struct sock *sk,
const struct netlbl_lsm_secattr *secattr)
{
return -ENOSYS;
@@ -354,12 +352,6 @@ static inline int netlbl_sock_getattr(struct sock *sk,
return -ENOSYS;
}
-static inline int netlbl_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
-{
- return -ENOSYS;
-}
-
static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
struct netlbl_lsm_secattr *secattr)
{
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 0bf325c29af..d7b824be542 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -118,6 +118,9 @@
* Nested Attributes Construction:
* nla_nest_start(skb, type) start a nested attribute
* nla_nest_end(skb, nla) finalize a nested attribute
+ * nla_nest_compat_start(skb, type, start a nested compat attribute
+ * len, data)
+ * nla_nest_compat_end(skb, type) finalize a nested compat attribute
* nla_nest_cancel(skb, nla) cancel nested attribute construction
*
* Attribute Length Calculations:
@@ -152,6 +155,7 @@
* nla_find_nested() find attribute in nested attributes
* nla_parse() parse and validate stream of attrs
* nla_parse_nested() parse nested attribuets
+ * nla_parse_nested_compat() parse nested compat attributes
* nla_for_each_attr() loop over all attributes
* nla_for_each_nested() loop over the nested attributes
*=========================================================================
@@ -170,6 +174,7 @@ enum {
NLA_FLAG,
NLA_MSECS,
NLA_NESTED,
+ NLA_NESTED_COMPAT,
NLA_NUL_STRING,
NLA_BINARY,
__NLA_TYPE_MAX,
@@ -190,6 +195,7 @@ enum {
* NLA_NUL_STRING Maximum length of string (excluding NUL)
* NLA_FLAG Unused
* NLA_BINARY Maximum length of attribute payload
+ * NLA_NESTED_COMPAT Exact length of structure payload
* All other Exact length of attribute payload
*
* Example:
@@ -222,10 +228,10 @@ extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb,
gfp_t flags);
extern int nla_validate(struct nlattr *head, int len, int maxtype,
- struct nla_policy *policy);
+ const struct nla_policy *policy);
extern int nla_parse(struct nlattr *tb[], int maxtype,
struct nlattr *head, int len,
- struct nla_policy *policy);
+ const struct nla_policy *policy);
extern struct nlattr * nla_find(struct nlattr *head, int len, int attrtype);
extern size_t nla_strlcpy(char *dst, const struct nlattr *nla,
size_t dstsize);
@@ -360,7 +366,7 @@ static inline struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
*/
static inline int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen,
struct nlattr *tb[], int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
return -EINVAL;
@@ -392,7 +398,7 @@ static inline struct nlattr *nlmsg_find_attr(struct nlmsghdr *nlh,
* @policy: validation policy
*/
static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
return -EINVAL;
@@ -729,10 +735,43 @@ static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype)
*/
static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
struct nlattr *nla,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy);
}
+
+/**
+ * nla_parse_nested_compat - parse nested compat attributes
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @nla: attribute containing the nested attributes
+ * @data: pointer to point to contained structure
+ * @len: length of contained structure
+ * @policy: validation policy
+ *
+ * Parse a nested compat attribute. The compat attribute contains a structure
+ * and optionally a set of nested attributes. On success the data pointer
+ * points to the nested data and tb contains the parsed attributes
+ * (see nla_parse).
+ */
+static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype,
+ struct nlattr *nla,
+ const struct nla_policy *policy,
+ int len)
+{
+ if (nla_len(nla) < len)
+ return -1;
+ if (nla_len(nla) >= NLA_ALIGN(len) + sizeof(struct nlattr))
+ return nla_parse_nested(tb, maxtype,
+ nla_data(nla) + NLA_ALIGN(len),
+ policy);
+ memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
+ return 0;
+}
+
+#define nla_parse_nested_compat(tb, maxtype, nla, policy, data, len) \
+({ data = nla_len(nla) >= len ? nla_data(nla) : NULL; \
+ __nla_parse_nested_compat(tb, maxtype, nla, policy, len); })
/**
* nla_put_u8 - Add a u16 netlink attribute to a socket buffer
* @skb: socket buffer to add attribute to
@@ -965,6 +1004,51 @@ static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start)
}
/**
+ * nla_nest_compat_start - Start a new level of nested compat attributes
+ * @skb: socket buffer to add attributes to
+ * @attrtype: attribute type of container
+ * @attrlen: length of structure
+ * @data: pointer to structure
+ *
+ * Start a nested compat attribute that contains both a structure and
+ * a set of nested attributes.
+ *
+ * Returns the container attribute
+ */
+static inline struct nlattr *nla_nest_compat_start(struct sk_buff *skb,
+ int attrtype, int attrlen,
+ const void *data)
+{
+ struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
+
+ if (nla_put(skb, attrtype, attrlen, data) < 0)
+ return NULL;
+ if (nla_nest_start(skb, attrtype) == NULL) {
+ nlmsg_trim(skb, start);
+ return NULL;
+ }
+ return start;
+}
+
+/**
+ * nla_nest_compat_end - Finalize nesting of compat attributes
+ * @skb: socket buffer the attribtues are stored in
+ * @start: container attribute
+ *
+ * Corrects the container attribute header to include the all
+ * appeneded attributes.
+ *
+ * Returns the total data length of the skb.
+ */
+static inline int nla_nest_compat_end(struct sk_buff *skb, struct nlattr *start)
+{
+ struct nlattr *nest = (void *)start + NLMSG_ALIGN(start->nla_len);
+
+ start->nla_len = skb_tail_pointer(skb) - (unsigned char *)start;
+ return nla_nest_end(skb, nest);
+}
+
+/**
* nla_nest_cancel - Cancel nesting of attributes
* @skb: socket buffer the message is stored in
* @start: container attribute
@@ -990,7 +1074,7 @@ static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
* Returns 0 on success or a negative error code.
*/
static inline int nla_validate_nested(struct nlattr *start, int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
return nla_validate(nla_data(start), nla_len(start), maxtype, policy);
}
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 4129df70807..7968b1d6636 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -65,8 +65,6 @@ struct tcf_exts
{
#ifdef CONFIG_NET_CLS_ACT
struct tc_action *action;
-#elif defined CONFIG_NET_CLS_POLICE
- struct tcf_police *police;
#endif
};
@@ -91,8 +89,6 @@ tcf_exts_is_predicative(struct tcf_exts *exts)
{
#ifdef CONFIG_NET_CLS_ACT
return !!exts->action;
-#elif defined CONFIG_NET_CLS_POLICE
- return !!exts->police;
#else
return 0;
#endif
@@ -129,11 +125,7 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
#ifdef CONFIG_NET_CLS_ACT
if (exts->action)
return tcf_action_exec(skb, exts->action, res);
-#elif defined CONFIG_NET_CLS_POLICE
- if (exts->police)
- return tcf_police(skb, exts->police);
#endif
-
return 0;
}
@@ -306,6 +298,8 @@ static inline int tcf_em_tree_match(struct sk_buff *skb,
return 1;
}
+#define MODULE_ALIAS_TCF_EMATCH(kind) MODULE_ALIAS("ematch-kind-" __stringify(kind))
+
#else /* CONFIG_NET_EMATCH */
struct tcf_ematch_tree
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 5754d53d9ef..9e22526e80e 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -89,8 +89,10 @@ static inline void qdisc_run(struct net_device *dev)
__qdisc_run(dev);
}
+extern int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
+ struct tcf_result *res);
extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
- struct tcf_result *res);
+ struct tcf_result *res);
/* Calculate maximal size of packet seen by hard_start_xmit
routine of this device.
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index af8960878ef..a5819891d52 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -3,6 +3,8 @@
#ifdef __KERNEL__
+#include <net/protocol.h>
+
#define RAWV6_HTABLE_SIZE MAX_INET_PROTOS
extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
extern rwlock_t raw_v6_lock;
@@ -23,6 +25,13 @@ extern void rawv6_err(struct sock *sk,
int type, int code,
int offset, __be32 info);
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+ struct sk_buff *skb));
+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+ struct sk_buff *skb));
+#endif
+
#endif
#endif
diff --git a/include/net/route.h b/include/net/route.h
index 749e4dfe5ff..f7ce6259f86 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -62,7 +62,6 @@ struct rtable
unsigned rt_flags;
__u16 rt_type;
- __u16 rt_multipath_alg;
__be32 rt_dst; /* Path destination */
__be32 rt_src; /* Path source */
@@ -136,7 +135,7 @@ static inline void ip_rt_put(struct rtable * rt)
#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3)
-extern __u8 ip_tos2prio[16];
+extern const __u8 ip_tos2prio[16];
static inline char rt_tos2priority(u8 tos)
{
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 3b3d4745618..3861c05cdf0 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -22,4 +22,62 @@ static inline int rtnl_msg_family(struct nlmsghdr *nlh)
return AF_UNSPEC;
}
+/**
+ * struct rtnl_link_ops - rtnetlink link operations
+ *
+ * @list: Used internally
+ * @kind: Identifier
+ * @maxtype: Highest device specific netlink attribute number
+ * @policy: Netlink policy for device specific attribute validation
+ * @validate: Optional validation function for netlink/changelink parameters
+ * @priv_size: sizeof net_device private space
+ * @setup: net_device setup function
+ * @newlink: Function for configuring and registering a new device
+ * @changelink: Function for changing parameters of an existing device
+ * @dellink: Function to remove a device
+ * @get_size: Function to calculate required room for dumping device
+ * specific netlink attributes
+ * @fill_info: Function to dump device specific netlink attributes
+ * @get_xstats_size: Function to calculate required room for dumping devic
+ * specific statistics
+ * @fill_xstats: Function to dump device specific statistics
+ */
+struct rtnl_link_ops {
+ struct list_head list;
+
+ const char *kind;
+
+ size_t priv_size;
+ void (*setup)(struct net_device *dev);
+
+ int maxtype;
+ const struct nla_policy *policy;
+ int (*validate)(struct nlattr *tb[],
+ struct nlattr *data[]);
+
+ int (*newlink)(struct net_device *dev,
+ struct nlattr *tb[],
+ struct nlattr *data[]);
+ int (*changelink)(struct net_device *dev,
+ struct nlattr *tb[],
+ struct nlattr *data[]);
+ void (*dellink)(struct net_device *dev);
+
+ size_t (*get_size)(const struct net_device *dev);
+ int (*fill_info)(struct sk_buff *skb,
+ const struct net_device *dev);
+
+ size_t (*get_xstats_size)(const struct net_device *dev);
+ int (*fill_xstats)(struct sk_buff *skb,
+ const struct net_device *dev);
+};
+
+extern int __rtnl_link_register(struct rtnl_link_ops *ops);
+extern void __rtnl_link_unregister(struct rtnl_link_ops *ops);
+
+extern int rtnl_link_register(struct rtnl_link_ops *ops);
+extern void rtnl_link_unregister(struct rtnl_link_ops *ops);
+
+#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
+
#endif
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 1b8e35197eb..8a67f24cbe0 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -290,7 +290,7 @@ static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch)
{
sch->qstats.drops++;
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
goto drop;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index dda72bf5b9b..16baef4dab7 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -503,6 +503,13 @@ static inline int sctp_frag_point(const struct sctp_sock *sp, int pmtu)
return frag;
}
+static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc)
+{
+
+ sctp_assoc_sync_pmtu(asoc);
+ asoc->pmtu_pending = 0;
+}
+
/* Walk through a list of TLV parameters. Don't trust the
* individual parameter lengths and instead depend on
* the chunk length to indicate when to stop. Make sure
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 5e81984b847..ee4559b1130 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -912,6 +912,9 @@ struct sctp_transport {
*/
__u16 pathmaxrxt;
+ /* is the Path MTU update pending on this tranport */
+ __u8 pmtu_pending;
+
/* PMTU : The current known path MTU. */
__u32 pathmtu;
@@ -1006,6 +1009,7 @@ void sctp_transport_raise_cwnd(struct sctp_transport *, __u32, __u32);
void sctp_transport_lower_cwnd(struct sctp_transport *, sctp_lower_cwnd_t);
unsigned long sctp_transport_timeout(struct sctp_transport *);
void sctp_transport_reset(struct sctp_transport *);
+void sctp_transport_update_pmtu(struct sctp_transport *, u32);
/* This is the structure we use to queue packets as they come into
@@ -1565,6 +1569,9 @@ struct sctp_association {
*/
__u16 pathmaxrxt;
+ /* Flag that path mtu update is pending */
+ __u8 pmtu_pending;
+
/* Association : The smallest PMTU discovered for all of the
* PMTU : peer's transport addresses.
*/
diff --git a/include/net/sock.h b/include/net/sock.h
index 689b886038d..dfeb8b13024 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -218,13 +218,13 @@ struct sock {
atomic_t sk_rmem_alloc;
atomic_t sk_wmem_alloc;
atomic_t sk_omem_alloc;
+ int sk_sndbuf;
struct sk_buff_head sk_receive_queue;
struct sk_buff_head sk_write_queue;
struct sk_buff_head sk_async_wait_queue;
int sk_wmem_queued;
int sk_forward_alloc;
gfp_t sk_allocation;
- int sk_sndbuf;
int sk_route_caps;
int sk_gso_type;
int sk_rcvlowat;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e22b4f0305a..a8af9ae0017 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -254,6 +254,12 @@ static inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
return seq3 - seq2 >= seq1 - seq2;
}
+static inline int tcp_too_many_orphans(struct sock *sk, int num)
+{
+ return (num > sysctl_tcp_max_orphans) ||
+ (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
+ atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]);
+}
extern struct proto tcp_prot;
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h
index 333bba6dc52..cfc4ba46de8 100644
--- a/include/net/tipc/tipc_port.h
+++ b/include/net/tipc/tipc_port.h
@@ -1,8 +1,8 @@
/*
* include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports
*
- * Copyright (c) 1994-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 1994-2007, Ericsson AB
+ * Copyright (c) 2005-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,6 +55,7 @@
* @conn_unacked: number of unacknowledged messages received from peer port
* @published: non-zero if port has one or more associated names
* @congested: non-zero if cannot send because of link or port congestion
+ * @max_pkt: maximum packet size "hint" used when building messages sent by port
* @ref: unique reference to port in TIPC object registry
* @phdr: preformatted message header used when sending messages
*/
@@ -68,6 +69,7 @@ struct tipc_port {
u32 conn_unacked;
int published;
u32 congested;
+ u32 max_pkt;
u32 ref;
struct tipc_msg phdr;
};
diff --git a/include/net/udp.h b/include/net/udp.h
index 496f89d45c8..98755ebaf16 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -119,16 +119,9 @@ static inline void udp_lib_close(struct sock *sk, long timeout)
}
-struct udp_get_port_ops {
- int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2);
- int (*saddr_any)(const struct sock *sk);
- unsigned int (*hash_port_and_rcv_saddr)(__u16 port,
- const struct sock *sk);
-};
-
/* net/ipv4/udp.c */
extern int udp_get_port(struct sock *sk, unsigned short snum,
- const struct udp_get_port_ops *ops);
+ int (*saddr_cmp)(const struct sock *, const struct sock *));
extern void udp_err(struct sk_buff *, u32);
extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 50b4b424d1c..635b0eafca9 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -120,5 +120,5 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
extern void udplite4_register(void);
extern int udplite_get_port(struct sock *sk, unsigned short snum,
- const struct udp_get_port_ops *ops);
+ int (*scmp)(const struct sock *, const struct sock *));
#endif /* _UDPLITE_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 39ef925d39d..ae959e95017 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -19,9 +19,19 @@
#include <net/ipv6.h>
#include <net/ip6_fib.h>
+#define XFRM_PROTO_ESP 50
+#define XFRM_PROTO_AH 51
+#define XFRM_PROTO_COMP 108
+#define XFRM_PROTO_IPIP 4
+#define XFRM_PROTO_IPV6 41
+#define XFRM_PROTO_ROUTING IPPROTO_ROUTING
+#define XFRM_PROTO_DSTOPTS IPPROTO_DSTOPTS
+
#define XFRM_ALIGN8(len) (((len) + 7) & ~7)
#define MODULE_ALIAS_XFRM_MODE(family, encap) \
MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
+#define MODULE_ALIAS_XFRM_TYPE(family, proto) \
+ MODULE_ALIAS("xfrm-type-" __stringify(family) "-" __stringify(proto))
extern struct sock *xfrm_nl;
extern u32 sysctl_xfrm_aevent_etime;
@@ -237,7 +247,6 @@ extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
-#define XFRM_ACQ_EXPIRES 30
struct xfrm_tmpl;
extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
@@ -510,11 +519,9 @@ __be16 xfrm_flowi_sport(struct flowi *fl)
case IPPROTO_ICMPV6:
port = htons(fl->fl_icmp_type);
break;
-#ifdef CONFIG_IPV6_MIP6
case IPPROTO_MH:
port = htons(fl->fl_mh_type);
break;
-#endif
default:
port = 0; /*XXX*/
}
@@ -921,6 +928,10 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t
struct flowi *fl, struct xfrm_tmpl *tmpl,
struct xfrm_policy *pol, int *err,
unsigned short family);
+extern struct xfrm_state * xfrm_stateonly_find(xfrm_address_t *daddr,
+ xfrm_address_t *saddr,
+ unsigned short family,
+ u8 mode, u8 proto, u32 reqid);
extern int xfrm_state_check_expire(struct xfrm_state *x);
extern void xfrm_state_insert(struct xfrm_state *x);
extern int xfrm_state_add(struct xfrm_state *x);
@@ -965,7 +976,7 @@ struct xfrmk_spdinfo {
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
-extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
+extern int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si);
extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si);
extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
@@ -992,7 +1003,7 @@ extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
u8 **prevhdr);
#ifdef CONFIG_XFRM
-extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
+extern int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb);
extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen);
extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family);
#else
@@ -1001,12 +1012,13 @@ static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optv
return -ENOPROTOOPT;
}
-static inline int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
+static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
{
/* should not happen */
kfree_skb(skb);
return 0;
}
+
static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family)
{
return -EINVAL;
@@ -1021,13 +1033,13 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
struct xfrm_sec_ctx *ctx, int delete,
int *err);
struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err);
-void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
xfrm_address_t *daddr, xfrm_address_t *saddr,
int create, unsigned short family);
-extern void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
+extern int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
struct flowi *fl, int family, int strict);
diff --git a/include/pcmcia/ciscode.h b/include/pcmcia/ciscode.h
index eae7e2e8449..ad6e278ba7f 100644
--- a/include/pcmcia/ciscode.h
+++ b/include/pcmcia/ciscode.h
@@ -126,4 +126,6 @@
#define MANFID_POSSIO 0x030c
#define PRODID_POSSIO_GCC 0x0003
+#define MANFID_NEC 0x0010
+
#endif /* _LINUX_CISCODE_H */
diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h
index 5c070176d9a..12243e80c70 100644
--- a/include/rdma/ib_cm.h
+++ b/include/rdma/ib_cm.h
@@ -385,7 +385,6 @@ struct ib_cm_rep_param {
u8 private_data_len;
u8 responder_resources;
u8 initiator_depth;
- u8 target_ack_delay;
u8 failover_accepted;
u8 flow_control;
u8 rnr_retry_count;
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
index 739fa4d0e53..30712ddd8a5 100644
--- a/include/rdma/ib_mad.h
+++ b/include/rdma/ib_mad.h
@@ -111,6 +111,9 @@
#define IB_QP1_QKEY 0x80010000
#define IB_QP_SET_QKEY 0x80000000
+#define IB_DEFAULT_PKEY_PARTIAL 0x7FFF
+#define IB_DEFAULT_PKEY_FULL 0xFFFF
+
enum {
IB_MGMT_MAD_HDR = 24,
IB_MGMT_MAD_DATA = 232,
diff --git a/include/sound/version.h b/include/sound/version.h
index 50ee4fd420f..8e5b2f0f594 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by alsa/ksync script. */
-#define CONFIG_SND_VERSION "1.0.14rc4"
-#define CONFIG_SND_DATE " (Wed May 16 09:45:46 2007 UTC)"
+#define CONFIG_SND_VERSION "1.0.14"
+#define CONFIG_SND_DATE " (Thu May 31 09:03:25 2007 UTC)"
diff --git a/init/Kconfig b/init/Kconfig
index a9e99f8328f..d9d878a3bb4 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -686,6 +686,4 @@ config STOP_MACHINE
Need stop_machine() primitive.
endmenu
-menu "Block layer"
source "block/Kconfig"
-endmenu
diff --git a/init/main.c b/init/main.c
index eb8bdbae4fc..0eb1c7463fe 100644
--- a/init/main.c
+++ b/init/main.c
@@ -436,15 +436,16 @@ static void noinline __init_refok rest_init(void)
/*
* The boot idle thread must execute schedule()
- * at least one to get things moving:
+ * at least once to get things moving:
*/
+ init_idle_bootup_task(current);
preempt_enable_no_resched();
schedule();
preempt_disable();
/* Call into cpu_idle with preempt disabled */
cpu_idle();
-}
+}
/* Check for early params. */
static int __init do_early_param(char *param, char *val)
diff --git a/ipc/compat.c b/ipc/compat.c
index 8b44aa9a7c9..ab76fb0ef84 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -225,7 +225,7 @@ static inline int put_compat_semid_ds(struct semid64_ds *s,
int err;
if (!access_ok (VERIFY_WRITE, up, sizeof(*up)))
- err = -EFAULT;
+ return -EFAULT;
err = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm);
err |= __put_user(s->sem_otime, &up->sem_otime);
err |= __put_user(s->sem_ctime, &up->sem_ctime);
diff --git a/ipc/shm.c b/ipc/shm.c
index 4fefbad7096..0852f206d89 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -254,8 +254,10 @@ struct mempolicy *shm_get_policy(struct vm_area_struct *vma, unsigned long addr)
if (sfd->vm_ops->get_policy)
pol = sfd->vm_ops->get_policy(vma, addr);
- else
+ else if (vma->vm_policy)
pol = vma->vm_policy;
+ else
+ pol = current->mempolicy;
return pol;
}
#endif
@@ -364,9 +366,10 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
return error;
}
+ sprintf (name, "SYSV%08x", key);
if (shmflg & SHM_HUGETLB) {
- /* hugetlb_zero_setup takes care of mlock user accounting */
- file = hugetlb_zero_setup(size);
+ /* hugetlb_file_setup takes care of mlock user accounting */
+ file = hugetlb_file_setup(name, size);
shp->mlock_user = current->user;
} else {
int acctflag = VM_ACCOUNT;
@@ -377,7 +380,6 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
if ((shmflg & SHM_NORESERVE) &&
sysctl_overcommit_memory != OVERCOMMIT_NEVER)
acctflag = 0;
- sprintf (name, "SYSV%08x", key);
file = shmem_file_setup(name, size, acctflag);
}
error = PTR_ERR(file);
@@ -397,6 +399,11 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
shp->shm_nattch = 0;
shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
shp->shm_file = file;
+ /*
+ * shmid gets reported as "inode#" in /proc/pid/maps.
+ * proc-ps tools use this. Changing this will break them.
+ */
+ file->f_dentry->d_inode->i_ino = shp->id;
ns->shm_tot += numpages;
shm_unlock(shp);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 74cc0fc6bb8..ce61f423542 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -947,7 +947,7 @@ static void audit_update_watch(struct audit_parent *parent,
/* If the update involves invalidating rules, do the inode-based
* filtering now, so we don't omit records. */
- if (invalidating &&
+ if (invalidating && current->audit_context &&
audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT)
audit_set_auditable(current->audit_context);
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index f57854b0892..4c49188cc49 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1682,9 +1682,9 @@ static int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
do_each_thread(g, p) {
if (p->cpuset == cs) {
- pidarray[n++] = p->pid;
if (unlikely(n == npids))
goto array_full;
+ pidarray[n++] = p->pid;
}
} while_each_thread(g, p);
diff --git a/kernel/delayacct.c b/kernel/delayacct.c
index c0148ae992c..81e69782963 100644
--- a/kernel/delayacct.c
+++ b/kernel/delayacct.c
@@ -99,9 +99,10 @@ void __delayacct_blkio_end(void)
int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
{
s64 tmp;
- struct timespec ts;
- unsigned long t1,t2,t3;
+ unsigned long t1;
+ unsigned long long t2, t3;
unsigned long flags;
+ struct timespec ts;
/* Though tsk->delays accessed later, early exit avoids
* unnecessary returning of other data
@@ -124,11 +125,10 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
d->cpu_count += t1;
- jiffies_to_timespec(t2, &ts);
- tmp = (s64)d->cpu_delay_total + timespec_to_ns(&ts);
+ tmp = (s64)d->cpu_delay_total + t2;
d->cpu_delay_total = (tmp < (s64)d->cpu_delay_total) ? 0 : tmp;
- tmp = (s64)d->cpu_run_virtual_total + (s64)jiffies_to_usecs(t3) * 1000;
+ tmp = (s64)d->cpu_run_virtual_total + t3;
d->cpu_run_virtual_total =
(tmp < (s64)d->cpu_run_virtual_total) ? 0 : tmp;
diff --git a/kernel/exit.c b/kernel/exit.c
index 5b888c24e43..ca6a11b7302 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -122,9 +122,9 @@ static void __exit_signal(struct task_struct *tsk)
sig->maj_flt += tsk->maj_flt;
sig->nvcsw += tsk->nvcsw;
sig->nivcsw += tsk->nivcsw;
- sig->sched_time += tsk->sched_time;
sig->inblock += task_io_get_inblock(tsk);
sig->oublock += task_io_get_oublock(tsk);
+ sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
sig = NULL; /* Marker for below. */
}
@@ -182,7 +182,6 @@ repeat:
zap_leader = (leader->exit_signal == -1);
}
- sched_exit(p);
write_unlock_irq(&tasklist_lock);
proc_flush_task(p);
release_thread(p);
@@ -291,7 +290,7 @@ static void reparent_to_kthreadd(void)
/* Set the exit signal to SIGCHLD so we signal init on exit */
current->exit_signal = SIGCHLD;
- if (!has_rt_policy(current) && (task_nice(current) < 0))
+ if (task_nice(current) < 0)
set_user_nice(current, 0);
/* cpus_allowed? */
/* rt_priority? */
@@ -892,13 +891,29 @@ fastcall NORET_TYPE void do_exit(long code)
if (unlikely(tsk->flags & PF_EXITING)) {
printk(KERN_ALERT
"Fixing recursive fault but reboot is needed!\n");
+ /*
+ * We can do this unlocked here. The futex code uses
+ * this flag just to verify whether the pi state
+ * cleanup has been done or not. In the worst case it
+ * loops once more. We pretend that the cleanup was
+ * done as there is no way to return. Either the
+ * OWNER_DIED bit is set by now or we push the blocked
+ * task into the wait for ever nirwana as well.
+ */
+ tsk->flags |= PF_EXITPIDONE;
if (tsk->io_context)
exit_io_context();
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
}
+ /*
+ * tsk->flags are checked in the futex code to protect against
+ * an exiting task cleaning up the robust pi futexes.
+ */
+ spin_lock_irq(&tsk->pi_lock);
tsk->flags |= PF_EXITING;
+ spin_unlock_irq(&tsk->pi_lock);
if (unlikely(in_atomic()))
printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
@@ -912,7 +927,7 @@ fastcall NORET_TYPE void do_exit(long code)
}
group_dead = atomic_dec_and_test(&tsk->signal->live);
if (group_dead) {
- hrtimer_cancel(&tsk->signal->real_timer);
+ hrtimer_cancel(&tsk->signal->real_timer);
exit_itimers(tsk->signal);
}
acct_collect(code, group_dead);
@@ -965,6 +980,12 @@ fastcall NORET_TYPE void do_exit(long code)
* Make sure we are holding no locks:
*/
debug_check_no_locks_held(tsk);
+ /*
+ * We can do this unlocked here. The futex code uses this flag
+ * just to verify whether the pi state cleanup has been done
+ * or not. In the worst case it loops once more.
+ */
+ tsk->flags |= PF_EXITPIDONE;
if (tsk->io_context)
exit_io_context();
diff --git a/kernel/fork.c b/kernel/fork.c
index 73ad5cda1bc..da3a155bba0 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -877,7 +877,7 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
- sig->sched_time = 0;
+ sig->sum_sched_runtime = 0;
INIT_LIST_HEAD(&sig->cpu_timers[0]);
INIT_LIST_HEAD(&sig->cpu_timers[1]);
INIT_LIST_HEAD(&sig->cpu_timers[2]);
@@ -1040,7 +1040,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->utime = cputime_zero;
p->stime = cputime_zero;
- p->sched_time = 0;
+
#ifdef CONFIG_TASK_XACCT
p->rchar = 0; /* I/O counter: bytes read */
p->wchar = 0; /* I/O counter: bytes written */
diff --git a/kernel/futex.c b/kernel/futex.c
index b7ce15c67e3..45490bec583 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -56,12 +56,6 @@
#include "rtmutex_common.h"
-#ifdef CONFIG_DEBUG_RT_MUTEXES
-# include "rtmutex-debug.h"
-#else
-# include "rtmutex.h"
-#endif
-
#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
/*
@@ -111,12 +105,6 @@ struct futex_q {
/* Optional priority inheritance state: */
struct futex_pi_state *pi_state;
struct task_struct *task;
-
- /*
- * This waiter is used in case of requeue from a
- * normal futex to a PI-futex
- */
- struct rt_mutex_waiter waiter;
};
/*
@@ -216,9 +204,6 @@ int get_futex_key(u32 __user *uaddr, struct rw_semaphore *fshared,
if (unlikely((vma->vm_flags & (VM_IO|VM_READ)) != VM_READ))
return (vma->vm_flags & VM_IO) ? -EPERM : -EACCES;
- /* Save the user address in the ley */
- key->uaddr = uaddr;
-
/*
* Private mappings are handled in a simple way.
*
@@ -424,18 +409,12 @@ static struct task_struct * futex_find_get_task(pid_t pid)
rcu_read_lock();
p = find_task_by_pid(pid);
- if (!p)
- goto out_unlock;
- if ((current->euid != p->euid) && (current->euid != p->uid)) {
- p = NULL;
- goto out_unlock;
- }
- if (p->exit_state != 0) {
- p = NULL;
- goto out_unlock;
- }
- get_task_struct(p);
-out_unlock:
+
+ if (!p || ((current->euid != p->euid) && (current->euid != p->uid)))
+ p = ERR_PTR(-ESRCH);
+ else
+ get_task_struct(p);
+
rcu_read_unlock();
return p;
@@ -502,7 +481,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
struct futex_q *this, *next;
struct plist_head *head;
struct task_struct *p;
- pid_t pid;
+ pid_t pid = uval & FUTEX_TID_MASK;
head = &hb->chain;
@@ -520,6 +499,8 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
return -EINVAL;
WARN_ON(!atomic_read(&pi_state->refcount));
+ WARN_ON(pid && pi_state->owner &&
+ pi_state->owner->pid != pid);
atomic_inc(&pi_state->refcount);
*ps = pi_state;
@@ -530,15 +511,33 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
/*
* We are the first waiter - try to look up the real owner and attach
- * the new pi_state to it, but bail out when the owner died bit is set
- * and TID = 0:
+ * the new pi_state to it, but bail out when TID = 0
*/
- pid = uval & FUTEX_TID_MASK;
- if (!pid && (uval & FUTEX_OWNER_DIED))
+ if (!pid)
return -ESRCH;
p = futex_find_get_task(pid);
- if (!p)
- return -ESRCH;
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ /*
+ * We need to look at the task state flags to figure out,
+ * whether the task is exiting. To protect against the do_exit
+ * change of the task flags, we do this protected by
+ * p->pi_lock:
+ */
+ spin_lock_irq(&p->pi_lock);
+ if (unlikely(p->flags & PF_EXITING)) {
+ /*
+ * The task is on the way out. When PF_EXITPIDONE is
+ * set, we know that the task has finished the
+ * cleanup:
+ */
+ int ret = (p->flags & PF_EXITPIDONE) ? -ESRCH : -EAGAIN;
+
+ spin_unlock_irq(&p->pi_lock);
+ put_task_struct(p);
+ return ret;
+ }
pi_state = alloc_pi_state();
@@ -551,7 +550,6 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
/* Store the key for possible exit cleanups: */
pi_state->key = *key;
- spin_lock_irq(&p->pi_lock);
WARN_ON(!list_empty(&pi_state->list));
list_add(&pi_state->list, &p->pi_state_list);
pi_state->owner = p;
@@ -618,17 +616,22 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
* preserve the owner died bit.)
*/
if (!(uval & FUTEX_OWNER_DIED)) {
+ int ret = 0;
+
newval = FUTEX_WAITERS | new_owner->pid;
- /* Keep the FUTEX_WAITER_REQUEUED flag if it was set */
- newval |= (uval & FUTEX_WAITER_REQUEUED);
pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
pagefault_enable();
+
if (curval == -EFAULT)
- return -EFAULT;
+ ret = -EFAULT;
if (curval != uval)
- return -EINVAL;
+ ret = -EINVAL;
+ if (ret) {
+ spin_unlock(&pi_state->pi_mutex.wait_lock);
+ return ret;
+ }
}
spin_lock_irq(&pi_state->owner->pi_lock);
@@ -728,259 +731,6 @@ out:
}
/*
- * Called from futex_requeue_pi.
- * Set FUTEX_WAITERS and FUTEX_WAITER_REQUEUED flags on the
- * PI-futex value; search its associated pi_state if an owner exist
- * or create a new one without owner.
- */
-static inline int
-lookup_pi_state_for_requeue(u32 __user *uaddr, struct futex_hash_bucket *hb,
- union futex_key *key,
- struct futex_pi_state **pi_state)
-{
- u32 curval, uval, newval;
-
-retry:
- /*
- * We can't handle a fault cleanly because we can't
- * release the locks here. Simply return the fault.
- */
- if (get_futex_value_locked(&curval, uaddr))
- return -EFAULT;
-
- /* set the flags FUTEX_WAITERS and FUTEX_WAITER_REQUEUED */
- if ((curval & (FUTEX_WAITERS | FUTEX_WAITER_REQUEUED))
- != (FUTEX_WAITERS | FUTEX_WAITER_REQUEUED)) {
- /*
- * No waiters yet, we prepare the futex to have some waiters.
- */
-
- uval = curval;
- newval = uval | FUTEX_WAITERS | FUTEX_WAITER_REQUEUED;
-
- pagefault_disable();
- curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
- pagefault_enable();
-
- if (unlikely(curval == -EFAULT))
- return -EFAULT;
- if (unlikely(curval != uval))
- goto retry;
- }
-
- if (!(curval & FUTEX_TID_MASK)
- || lookup_pi_state(curval, hb, key, pi_state)) {
- /* the futex has no owner (yet) or the lookup failed:
- allocate one pi_state without owner */
-
- *pi_state = alloc_pi_state();
-
- /* Already stores the key: */
- (*pi_state)->key = *key;
-
- /* init the mutex without owner */
- __rt_mutex_init(&(*pi_state)->pi_mutex, NULL);
- }
-
- return 0;
-}
-
-/*
- * Keep the first nr_wake waiter from futex1, wake up one,
- * and requeue the next nr_requeue waiters following hashed on
- * one physical page to another physical page (PI-futex uaddr2)
- */
-static int futex_requeue_pi(u32 __user *uaddr1,
- struct rw_semaphore *fshared,
- u32 __user *uaddr2,
- int nr_wake, int nr_requeue, u32 *cmpval)
-{
- union futex_key key1, key2;
- struct futex_hash_bucket *hb1, *hb2;
- struct plist_head *head1;
- struct futex_q *this, *next;
- struct futex_pi_state *pi_state2 = NULL;
- struct rt_mutex_waiter *waiter, *top_waiter = NULL;
- struct rt_mutex *lock2 = NULL;
- int ret, drop_count = 0;
-
- if (refill_pi_state_cache())
- return -ENOMEM;
-
-retry:
- /*
- * First take all the futex related locks:
- */
- if (fshared)
- down_read(fshared);
-
- ret = get_futex_key(uaddr1, fshared, &key1);
- if (unlikely(ret != 0))
- goto out;
- ret = get_futex_key(uaddr2, fshared, &key2);
- if (unlikely(ret != 0))
- goto out;
-
- hb1 = hash_futex(&key1);
- hb2 = hash_futex(&key2);
-
- double_lock_hb(hb1, hb2);
-
- if (likely(cmpval != NULL)) {
- u32 curval;
-
- ret = get_futex_value_locked(&curval, uaddr1);
-
- if (unlikely(ret)) {
- spin_unlock(&hb1->lock);
- if (hb1 != hb2)
- spin_unlock(&hb2->lock);
-
- /*
- * If we would have faulted, release mmap_sem, fault
- * it in and start all over again.
- */
- if (fshared)
- up_read(fshared);
-
- ret = get_user(curval, uaddr1);
-
- if (!ret)
- goto retry;
-
- return ret;
- }
- if (curval != *cmpval) {
- ret = -EAGAIN;
- goto out_unlock;
- }
- }
-
- head1 = &hb1->chain;
- plist_for_each_entry_safe(this, next, head1, list) {
- if (!match_futex (&this->key, &key1))
- continue;
- if (++ret <= nr_wake) {
- wake_futex(this);
- } else {
- /*
- * FIRST: get and set the pi_state
- */
- if (!pi_state2) {
- int s;
- /* do this only the first time we requeue someone */
- s = lookup_pi_state_for_requeue(uaddr2, hb2,
- &key2, &pi_state2);
- if (s) {
- ret = s;
- goto out_unlock;
- }
-
- lock2 = &pi_state2->pi_mutex;
- spin_lock(&lock2->wait_lock);
-
- /* Save the top waiter of the wait_list */
- if (rt_mutex_has_waiters(lock2))
- top_waiter = rt_mutex_top_waiter(lock2);
- } else
- atomic_inc(&pi_state2->refcount);
-
-
- this->pi_state = pi_state2;
-
- /*
- * SECOND: requeue futex_q to the correct hashbucket
- */
-
- /*
- * If key1 and key2 hash to the same bucket, no need to
- * requeue.
- */
- if (likely(head1 != &hb2->chain)) {
- plist_del(&this->list, &hb1->chain);
- plist_add(&this->list, &hb2->chain);
- this->lock_ptr = &hb2->lock;
-#ifdef CONFIG_DEBUG_PI_LIST
- this->list.plist.lock = &hb2->lock;
-#endif
- }
- this->key = key2;
- get_futex_key_refs(&key2);
- drop_count++;
-
-
- /*
- * THIRD: queue it to lock2
- */
- spin_lock_irq(&this->task->pi_lock);
- waiter = &this->waiter;
- waiter->task = this->task;
- waiter->lock = lock2;
- plist_node_init(&waiter->list_entry, this->task->prio);
- plist_node_init(&waiter->pi_list_entry, this->task->prio);
- plist_add(&waiter->list_entry, &lock2->wait_list);
- this->task->pi_blocked_on = waiter;
- spin_unlock_irq(&this->task->pi_lock);
-
- if (ret - nr_wake >= nr_requeue)
- break;
- }
- }
-
- /* If we've requeued some tasks and the top_waiter of the rt_mutex
- has changed, we must adjust the priority of the owner, if any */
- if (drop_count) {
- struct task_struct *owner = rt_mutex_owner(lock2);
- if (owner &&
- (top_waiter != (waiter = rt_mutex_top_waiter(lock2)))) {
- int chain_walk = 0;
-
- spin_lock_irq(&owner->pi_lock);
- if (top_waiter)
- plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters);
- else
- /*
- * There was no waiters before the requeue,
- * the flag must be updated
- */
- mark_rt_mutex_waiters(lock2);
-
- plist_add(&waiter->pi_list_entry, &owner->pi_waiters);
- __rt_mutex_adjust_prio(owner);
- if (owner->pi_blocked_on) {
- chain_walk = 1;
- get_task_struct(owner);
- }
-
- spin_unlock_irq(&owner->pi_lock);
- spin_unlock(&lock2->wait_lock);
-
- if (chain_walk)
- rt_mutex_adjust_prio_chain(owner, 0, lock2, NULL,
- current);
- } else {
- /* No owner or the top_waiter does not change */
- mark_rt_mutex_waiters(lock2);
- spin_unlock(&lock2->wait_lock);
- }
- }
-
-out_unlock:
- spin_unlock(&hb1->lock);
- if (hb1 != hb2)
- spin_unlock(&hb2->lock);
-
- /* drop_futex_key_refs() must be called outside the spinlocks. */
- while (--drop_count >= 0)
- drop_futex_key_refs(&key1);
-
-out:
- if (fshared)
- up_read(fshared);
- return ret;
-}
-
-/*
* Wake up all waiters hashed on the physical page that is mapped
* to this virtual address:
*/
@@ -1174,7 +924,7 @@ static int futex_requeue(u32 __user *uaddr1, struct rw_semaphore *fshared,
#ifdef CONFIG_DEBUG_PI_LIST
this->list.plist.lock = &hb2->lock;
#endif
- }
+ }
this->key = key2;
get_futex_key_refs(&key2);
drop_count++;
@@ -1326,12 +1076,10 @@ static void unqueue_me_pi(struct futex_q *q)
/*
* Fixup the pi_state owner with current.
*
- * The cur->mm semaphore must be held, it is released at return of this
- * function.
+ * Must be called with hash bucket lock held and mm->sem held for non
+ * private futexes.
*/
-static int fixup_pi_state_owner(u32 __user *uaddr, struct rw_semaphore *fshared,
- struct futex_q *q,
- struct futex_hash_bucket *hb,
+static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
struct task_struct *curr)
{
u32 newtid = curr->pid | FUTEX_WAITERS;
@@ -1355,23 +1103,23 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct rw_semaphore *fshared,
list_add(&pi_state->list, &curr->pi_state_list);
spin_unlock_irq(&curr->pi_lock);
- /* Unqueue and drop the lock */
- unqueue_me_pi(q);
- if (fshared)
- up_read(fshared);
/*
* We own it, so we have to replace the pending owner
* TID. This must be atomic as we have preserve the
* owner died bit here.
*/
- ret = get_user(uval, uaddr);
+ ret = get_futex_value_locked(&uval, uaddr);
+
while (!ret) {
newval = (uval & FUTEX_OWNER_DIED) | newtid;
- newval |= (uval & FUTEX_WAITER_REQUEUED);
+
+ pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr,
uval, newval);
+ pagefault_enable();
+
if (curval == -EFAULT)
- ret = -EFAULT;
+ ret = -EFAULT;
if (curval == uval)
break;
uval = curval;
@@ -1395,7 +1143,7 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
struct futex_q q;
u32 uval;
int ret;
- struct hrtimer_sleeper t, *to = NULL;
+ struct hrtimer_sleeper t;
int rem = 0;
q.pi_state = NULL;
@@ -1451,14 +1199,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
if (uval != val)
goto out_unlock_release_sem;
- /*
- * This rt_mutex_waiter structure is prepared here and will
- * be used only if this task is requeued from a normal futex to
- * a PI-futex with futex_requeue_pi.
- */
- debug_rt_mutex_init_waiter(&q.waiter);
- q.waiter.task = NULL;
-
/* Only actually queue if *uaddr contained val. */
__queue_me(&q, hb);
@@ -1489,7 +1229,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
if (!abs_time)
schedule();
else {
- to = &t;
hrtimer_init(&t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
hrtimer_init_sleeper(&t, current);
t.timer.expires = *abs_time;
@@ -1517,69 +1256,6 @@ static int futex_wait(u32 __user *uaddr, struct rw_semaphore *fshared,
* we are the only user of it.
*/
- if (q.pi_state) {
- /*
- * We were woken but have been requeued on a PI-futex.
- * We have to complete the lock acquisition by taking
- * the rtmutex.
- */
-
- struct rt_mutex *lock = &q.pi_state->pi_mutex;
-
- spin_lock(&lock->wait_lock);
- if (unlikely(q.waiter.task)) {
- remove_waiter(lock, &q.waiter);
- }
- spin_unlock(&lock->wait_lock);
-
- if (rem)
- ret = -ETIMEDOUT;
- else
- ret = rt_mutex_timed_lock(lock, to, 1);
-
- if (fshared)
- down_read(fshared);
- spin_lock(q.lock_ptr);
-
- /*
- * Got the lock. We might not be the anticipated owner if we
- * did a lock-steal - fix up the PI-state in that case.
- */
- if (!ret && q.pi_state->owner != curr) {
- /*
- * We MUST play with the futex we were requeued on,
- * NOT the current futex.
- * We can retrieve it from the key of the pi_state
- */
- uaddr = q.pi_state->key.uaddr;
-
- /* mmap_sem and hash_bucket lock are unlocked at
- return of this function */
- ret = fixup_pi_state_owner(uaddr, fshared,
- &q, hb, curr);
- } else {
- /*
- * Catch the rare case, where the lock was released
- * when we were on the way back before we locked
- * the hash bucket.
- */
- if (ret && q.pi_state->owner == curr) {
- if (rt_mutex_trylock(&q.pi_state->pi_mutex))
- ret = 0;
- }
- /* Unqueue and drop the lock */
- unqueue_me_pi(&q);
- if (fshared)
- up_read(fshared);
- }
-
- debug_rt_mutex_free_waiter(&q.waiter);
-
- return ret;
- }
-
- debug_rt_mutex_free_waiter(&q.waiter);
-
/* If we were woken (and unqueued), we succeeded, whatever. */
if (!unqueue_me(&q))
return 0;
@@ -1629,51 +1305,6 @@ static long futex_wait_restart(struct restart_block *restart)
}
-static void set_pi_futex_owner(struct futex_hash_bucket *hb,
- union futex_key *key, struct task_struct *p)
-{
- struct plist_head *head;
- struct futex_q *this, *next;
- struct futex_pi_state *pi_state = NULL;
- struct rt_mutex *lock;
-
- /* Search a waiter that should already exists */
-
- head = &hb->chain;
-
- plist_for_each_entry_safe(this, next, head, list) {
- if (match_futex (&this->key, key)) {
- pi_state = this->pi_state;
- break;
- }
- }
-
- BUG_ON(!pi_state);
-
- /* set p as pi_state's owner */
- lock = &pi_state->pi_mutex;
-
- spin_lock(&lock->wait_lock);
- spin_lock_irq(&p->pi_lock);
-
- list_add(&pi_state->list, &p->pi_state_list);
- pi_state->owner = p;
-
-
- /* set p as pi_mutex's owner */
- debug_rt_mutex_proxy_lock(lock, p);
- WARN_ON(rt_mutex_owner(lock));
- rt_mutex_set_owner(lock, p, 0);
- rt_mutex_deadlock_account_lock(lock, p);
-
- plist_add(&rt_mutex_top_waiter(lock)->pi_list_entry,
- &p->pi_waiters);
- __rt_mutex_adjust_prio(p);
-
- spin_unlock_irq(&p->pi_lock);
- spin_unlock(&lock->wait_lock);
-}
-
/*
* Userspace tried a 0 -> TID atomic transition of the futex value
* and failed. The kernel side here does the whole locking operation:
@@ -1688,7 +1319,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
struct futex_hash_bucket *hb;
u32 uval, newval, curval;
struct futex_q q;
- int ret, lock_held, attempt = 0;
+ int ret, lock_taken, ownerdied = 0, attempt = 0;
if (refill_pi_state_cache())
return -ENOMEM;
@@ -1709,10 +1340,11 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
if (unlikely(ret != 0))
goto out_release_sem;
+ retry_unlocked:
hb = queue_lock(&q, -1, NULL);
retry_locked:
- lock_held = 0;
+ ret = lock_taken = 0;
/*
* To avoid races, we attempt to take the lock here again
@@ -1728,43 +1360,43 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
if (unlikely(curval == -EFAULT))
goto uaddr_faulted;
- /* We own the lock already */
+ /*
+ * Detect deadlocks. In case of REQUEUE_PI this is a valid
+ * situation and we return success to user space.
+ */
if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) {
- if (!detect && 0)
- force_sig(SIGKILL, current);
- /*
- * Normally, this check is done in user space.
- * In case of requeue, the owner may attempt to lock this futex,
- * even if the ownership has already been given by the previous
- * waker.
- * In the usual case, this is a case of deadlock, but not in case
- * of REQUEUE_PI.
- */
- if (!(curval & FUTEX_WAITER_REQUEUED))
- ret = -EDEADLK;
+ ret = -EDEADLK;
goto out_unlock_release_sem;
}
/*
- * Surprise - we got the lock. Just return
- * to userspace:
+ * Surprise - we got the lock. Just return to userspace:
*/
if (unlikely(!curval))
goto out_unlock_release_sem;
uval = curval;
+
/*
- * In case of a requeue, check if there already is an owner
- * If not, just take the futex.
+ * Set the WAITERS flag, so the owner will know it has someone
+ * to wake at next unlock
*/
- if ((curval & FUTEX_WAITER_REQUEUED) && !(curval & FUTEX_TID_MASK)) {
- /* set current as futex owner */
- newval = curval | current->pid;
- lock_held = 1;
- } else
- /* Set the WAITERS flag, so the owner will know it has someone
- to wake at next unlock */
- newval = curval | FUTEX_WAITERS;
+ 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 !
+ */
+ if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
+ /* Keep the OWNER_DIED bit */
+ newval = (curval & ~FUTEX_TID_MASK) | current->pid;
+ ownerdied = 0;
+ lock_taken = 1;
+ }
pagefault_disable();
curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
@@ -1775,10 +1407,11 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
if (unlikely(curval != uval))
goto retry_locked;
- if (lock_held) {
- set_pi_futex_owner(hb, &q.key, curr);
+ /*
+ * We took the lock due to owner died take over.
+ */
+ if (unlikely(lock_taken))
goto out_unlock_release_sem;
- }
/*
* We dont have the lock. Look up the PI state (or create it if
@@ -1787,34 +1420,40 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
ret = lookup_pi_state(uval, hb, &q.key, &q.pi_state);
if (unlikely(ret)) {
- /*
- * There were no waiters and the owner task lookup
- * failed. When the OWNER_DIED bit is set, then we
- * know that this is a robust futex and we actually
- * take the lock. This is safe as we are protected by
- * the hash bucket lock. We also set the waiters bit
- * unconditionally here, to simplify glibc handling of
- * multiple tasks racing to acquire the lock and
- * cleanup the problems which were left by the dead
- * owner.
- */
- if (curval & FUTEX_OWNER_DIED) {
- uval = newval;
- newval = current->pid |
- FUTEX_OWNER_DIED | FUTEX_WAITERS;
+ switch (ret) {
- pagefault_disable();
- curval = futex_atomic_cmpxchg_inatomic(uaddr,
- uval, newval);
- pagefault_enable();
+ case -EAGAIN:
+ /*
+ * Task is exiting and we just wait for the
+ * exit to complete.
+ */
+ queue_unlock(&q, hb);
+ if (fshared)
+ up_read(fshared);
+ cond_resched();
+ goto retry;
- if (unlikely(curval == -EFAULT))
+ 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.
+ */
+ if (get_futex_value_locked(&curval, uaddr))
goto uaddr_faulted;
- if (unlikely(curval != uval))
+
+ /*
+ * We simply start over in case of a robust
+ * futex. The code above will take the futex
+ * and return happy.
+ */
+ if (curval & FUTEX_OWNER_DIED) {
+ ownerdied = 1;
goto retry_locked;
- ret = 0;
+ }
+ default:
+ goto out_unlock_release_sem;
}
- goto out_unlock_release_sem;
}
/*
@@ -1845,31 +1484,42 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
down_read(fshared);
spin_lock(q.lock_ptr);
- /*
- * Got the lock. We might not be the anticipated owner if we
- * did a lock-steal - fix up the PI-state in that case.
- */
- if (!ret && q.pi_state->owner != curr)
- /* mmap_sem is unlocked at return of this function */
- ret = fixup_pi_state_owner(uaddr, fshared, &q, hb, curr);
- else {
+ if (!ret) {
+ /*
+ * Got the lock. We might not be the anticipated owner
+ * if we did a lock-steal - fix up the PI-state in
+ * that case:
+ */
+ if (q.pi_state->owner != curr)
+ ret = fixup_pi_state_owner(uaddr, &q, curr);
+ } else {
/*
* Catch the rare case, where the lock was released
- * when we were on the way back before we locked
- * the hash bucket.
+ * when we were on the way back before we locked the
+ * hash bucket.
*/
- if (ret && q.pi_state->owner == curr) {
- if (rt_mutex_trylock(&q.pi_state->pi_mutex))
- ret = 0;
+ if (q.pi_state->owner == curr &&
+ rt_mutex_trylock(&q.pi_state->pi_mutex)) {
+ ret = 0;
+ } else {
+ /*
+ * Paranoia check. If we did not take the lock
+ * in the trylock above, then we should not be
+ * the owner of the rtmutex, neither the real
+ * nor the pending one:
+ */
+ if (rt_mutex_owner(&q.pi_state->pi_mutex) == curr)
+ printk(KERN_ERR "futex_lock_pi: ret = %d "
+ "pi-mutex: %p pi-state %p\n", ret,
+ q.pi_state->pi_mutex.owner,
+ q.pi_state->owner);
}
- /* Unqueue and drop the lock */
- unqueue_me_pi(&q);
- if (fshared)
- up_read(fshared);
}
- if (!detect && ret == -EDEADLK && 0)
- force_sig(SIGKILL, current);
+ /* Unqueue and drop the lock */
+ unqueue_me_pi(&q);
+ if (fshared)
+ up_read(fshared);
return ret != -EINTR ? ret : -ERESTARTNOINTR;
@@ -1887,16 +1537,19 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
* non-atomically. Therefore, if get_user below is not
* enough, we need to handle the fault ourselves, while
* still holding the mmap_sem.
+ *
+ * ... and hb->lock. :-) --ANK
*/
+ queue_unlock(&q, hb);
+
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr, fshared,
attempt);
if (ret)
- goto out_unlock_release_sem;
- goto retry_locked;
+ goto out_release_sem;
+ goto retry_unlocked;
}
- queue_unlock(&q, hb);
if (fshared)
up_read(fshared);
@@ -1940,9 +1593,9 @@ retry:
goto out;
hb = hash_futex(&key);
+retry_unlocked:
spin_lock(&hb->lock);
-retry_locked:
/*
* To avoid races, try to do the TID -> 0 atomic transition
* again. If it succeeds then we can return without waking
@@ -2005,16 +1658,19 @@ pi_faulted:
* non-atomically. Therefore, if get_user below is not
* enough, we need to handle the fault ourselves, while
* still holding the mmap_sem.
+ *
+ * ... and hb->lock. --ANK
*/
+ spin_unlock(&hb->lock);
+
if (attempt++) {
ret = futex_handle_fault((unsigned long)uaddr, fshared,
attempt);
if (ret)
- goto out_unlock;
- goto retry_locked;
+ goto out;
+ goto retry_unlocked;
}
- spin_unlock(&hb->lock);
if (fshared)
up_read(fshared);
@@ -2240,8 +1896,6 @@ retry:
* userspace.
*/
mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
- /* Also keep the FUTEX_WAITER_REQUEUED flag if set */
- mval |= (uval & FUTEX_WAITER_REQUEUED);
nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
if (nval == -EFAULT)
@@ -2378,9 +2032,6 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
case FUTEX_TRYLOCK_PI:
ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
break;
- case FUTEX_CMP_REQUEUE_PI:
- ret = futex_requeue_pi(uaddr, fshared, uaddr2, val, val2, &val3);
- break;
default:
ret = -ENOSYS;
}
@@ -2411,8 +2062,7 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
/*
* requeue parameter in 'utime' if cmd == FUTEX_REQUEUE.
*/
- if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE
- || cmd == FUTEX_CMP_REQUEUE_PI)
+ if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE)
val2 = (u32) (unsigned long) utime;
return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index 338a9b489fb..f7921360efa 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -144,20 +144,20 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
struct timespec ts;
ktime_t t, *tp = NULL;
int val2 = 0;
+ int cmd = op & FUTEX_CMD_MASK;
- if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
+ if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI)) {
if (get_compat_timespec(&ts, utime))
return -EFAULT;
if (!timespec_valid(&ts))
return -EINVAL;
t = timespec_to_ktime(ts);
- if (op == FUTEX_WAIT)
+ if (cmd == FUTEX_WAIT)
t = ktime_add(ktime_get(), t);
tp = &t;
}
- if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE
- || op == FUTEX_CMP_REQUEUE_PI)
+ if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE)
val2 = (int) (unsigned long) utime;
return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
diff --git a/kernel/module.c b/kernel/module.c
index 9bd93de01f4..015d60cfd90 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -488,8 +488,7 @@ static void free_modinfo_##field(struct module *mod) \
mod->field = NULL; \
} \
static struct module_attribute modinfo_##field = { \
- .attr = { .name = __stringify(field), .mode = 0444, \
- .owner = THIS_MODULE }, \
+ .attr = { .name = __stringify(field), .mode = 0444 }, \
.show = show_modinfo_##field, \
.setup = setup_modinfo_##field, \
.test = modinfo_##field##_exists, \
@@ -793,7 +792,7 @@ static ssize_t show_refcnt(struct module_attribute *mattr,
}
static struct module_attribute refcnt = {
- .attr = { .name = "refcnt", .mode = 0444, .owner = THIS_MODULE },
+ .attr = { .name = "refcnt", .mode = 0444 },
.show = show_refcnt,
};
@@ -851,7 +850,7 @@ static ssize_t show_initstate(struct module_attribute *mattr,
}
static struct module_attribute initstate = {
- .attr = { .name = "initstate", .mode = 0444, .owner = THIS_MODULE },
+ .attr = { .name = "initstate", .mode = 0444 },
.show = show_initstate,
};
@@ -1032,7 +1031,6 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
sattr->mattr.show = module_sect_show;
sattr->mattr.store = NULL;
sattr->mattr.attr.name = sattr->name;
- sattr->mattr.attr.owner = mod;
sattr->mattr.attr.mode = S_IRUGO;
*(gattr++) = &(sattr++)->mattr.attr;
}
@@ -1090,7 +1088,6 @@ int module_add_modinfo_attrs(struct module *mod)
if (!attr->test ||
(attr->test && attr->test(mod))) {
memcpy(temp_attr, attr, sizeof(*temp_attr));
- temp_attr->attr.owner = mod;
error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
++temp_attr;
}
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index 1bc4b55241a..9e83b589f75 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -145,13 +145,11 @@ void free_nsproxy(struct nsproxy *ns)
/*
* Called from unshare. Unshare all the namespaces part of nsproxy.
- * On sucess, returns the new nsproxy and a reference to old nsproxy
- * to make sure it stays around.
+ * On success, returns the new nsproxy.
*/
int unshare_nsproxy_namespaces(unsigned long unshare_flags,
struct nsproxy **new_nsp, struct fs_struct *new_fs)
{
- struct nsproxy *old_ns = current->nsproxy;
int err = 0;
if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC)))
@@ -170,13 +168,9 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- get_nsproxy(old_ns);
-
*new_nsp = create_new_namespaces(unshare_flags, current,
new_fs ? new_fs : current->fs);
- if (IS_ERR(*new_nsp)) {
+ if (IS_ERR(*new_nsp))
err = PTR_ERR(*new_nsp);
- put_nsproxy(old_ns);
- }
return err;
}
diff --git a/kernel/params.c b/kernel/params.c
index e61c46c97ce..effbaaedd7f 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -491,7 +491,6 @@ param_sysfs_setup(struct module_kobject *mk,
pattr->mattr.show = param_attr_show;
pattr->mattr.store = param_attr_store;
pattr->mattr.attr.name = (char *)&kp->name[name_skip];
- pattr->mattr.attr.owner = mk->mod;
pattr->mattr.attr.mode = kp->perm;
*(gattr++) = &(pattr++)->mattr.attr;
}
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 1de710e1837..b53c8fcd9d8 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -161,7 +161,7 @@ static inline cputime_t virt_ticks(struct task_struct *p)
}
static inline unsigned long long sched_ns(struct task_struct *p)
{
- return (p == current) ? current_sched_time(p) : p->sched_time;
+ return task_sched_runtime(p);
}
int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
@@ -246,10 +246,10 @@ static int cpu_clock_sample_group_locked(unsigned int clock_idx,
} while (t != p);
break;
case CPUCLOCK_SCHED:
- cpu->sched = p->signal->sched_time;
+ cpu->sched = p->signal->sum_sched_runtime;
/* Add in each other live thread. */
while ((t = next_thread(t)) != p) {
- cpu->sched += t->sched_time;
+ cpu->sched += t->se.sum_exec_runtime;
}
cpu->sched += sched_ns(p);
break;
@@ -422,7 +422,7 @@ int posix_cpu_timer_del(struct k_itimer *timer)
*/
static void cleanup_timers(struct list_head *head,
cputime_t utime, cputime_t stime,
- unsigned long long sched_time)
+ unsigned long long sum_exec_runtime)
{
struct cpu_timer_list *timer, *next;
cputime_t ptime = cputime_add(utime, stime);
@@ -451,10 +451,10 @@ static void cleanup_timers(struct list_head *head,
++head;
list_for_each_entry_safe(timer, next, head, entry) {
list_del_init(&timer->entry);
- if (timer->expires.sched < sched_time) {
+ if (timer->expires.sched < sum_exec_runtime) {
timer->expires.sched = 0;
} else {
- timer->expires.sched -= sched_time;
+ timer->expires.sched -= sum_exec_runtime;
}
}
}
@@ -467,7 +467,7 @@ static void cleanup_timers(struct list_head *head,
void posix_cpu_timers_exit(struct task_struct *tsk)
{
cleanup_timers(tsk->cpu_timers,
- tsk->utime, tsk->stime, tsk->sched_time);
+ tsk->utime, tsk->stime, tsk->se.sum_exec_runtime);
}
void posix_cpu_timers_exit_group(struct task_struct *tsk)
@@ -475,7 +475,7 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
cleanup_timers(tsk->signal->cpu_timers,
cputime_add(tsk->utime, tsk->signal->utime),
cputime_add(tsk->stime, tsk->signal->stime),
- tsk->sched_time + tsk->signal->sched_time);
+ tsk->se.sum_exec_runtime + tsk->signal->sum_sched_runtime);
}
@@ -536,7 +536,7 @@ static void process_timer_rebalance(struct task_struct *p,
nsleft = max_t(unsigned long long, nsleft, 1);
do {
if (likely(!(t->flags & PF_EXITING))) {
- ns = t->sched_time + nsleft;
+ ns = t->se.sum_exec_runtime + nsleft;
if (t->it_sched_expires == 0 ||
t->it_sched_expires > ns) {
t->it_sched_expires = ns;
@@ -1004,7 +1004,7 @@ static void check_thread_timers(struct task_struct *tsk,
struct cpu_timer_list *t = list_first_entry(timers,
struct cpu_timer_list,
entry);
- if (!--maxfire || tsk->sched_time < t->expires.sched) {
+ if (!--maxfire || tsk->se.sum_exec_runtime < t->expires.sched) {
tsk->it_sched_expires = t->expires.sched;
break;
}
@@ -1024,7 +1024,7 @@ static void check_process_timers(struct task_struct *tsk,
int maxfire;
struct signal_struct *const sig = tsk->signal;
cputime_t utime, stime, ptime, virt_expires, prof_expires;
- unsigned long long sched_time, sched_expires;
+ unsigned long long sum_sched_runtime, sched_expires;
struct task_struct *t;
struct list_head *timers = sig->cpu_timers;
@@ -1044,12 +1044,12 @@ static void check_process_timers(struct task_struct *tsk,
*/
utime = sig->utime;
stime = sig->stime;
- sched_time = sig->sched_time;
+ sum_sched_runtime = sig->sum_sched_runtime;
t = tsk;
do {
utime = cputime_add(utime, t->utime);
stime = cputime_add(stime, t->stime);
- sched_time += t->sched_time;
+ sum_sched_runtime += t->se.sum_exec_runtime;
t = next_thread(t);
} while (t != tsk);
ptime = cputime_add(utime, stime);
@@ -1090,7 +1090,7 @@ static void check_process_timers(struct task_struct *tsk,
struct cpu_timer_list *t = list_first_entry(timers,
struct cpu_timer_list,
entry);
- if (!--maxfire || sched_time < t->expires.sched) {
+ if (!--maxfire || sum_sched_runtime < t->expires.sched) {
sched_expires = t->expires.sched;
break;
}
@@ -1182,7 +1182,7 @@ static void check_process_timers(struct task_struct *tsk,
virt_left = cputime_sub(virt_expires, utime);
virt_left = cputime_div_non_zero(virt_left, nthreads);
if (sched_expires) {
- sched_left = sched_expires - sched_time;
+ sched_left = sched_expires - sum_sched_runtime;
do_div(sched_left, nthreads);
sched_left = max_t(unsigned long long, sched_left, 1);
} else {
@@ -1208,7 +1208,7 @@ static void check_process_timers(struct task_struct *tsk,
t->it_virt_expires = ticks;
}
- sched = t->sched_time + sched_left;
+ sched = t->se.sum_exec_runtime + sched_left;
if (sched_expires && (t->it_sched_expires == 0 ||
t->it_sched_expires > sched)) {
t->it_sched_expires = sched;
@@ -1300,7 +1300,7 @@ void run_posix_cpu_timers(struct task_struct *tsk)
if (UNEXPIRED(prof) && UNEXPIRED(virt) &&
(tsk->it_sched_expires == 0 ||
- tsk->sched_time < tsk->it_sched_expires))
+ tsk->se.sum_exec_runtime < tsk->it_sched_expires))
return;
#undef UNEXPIRED
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 588c99da030..329ce017207 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -353,9 +353,40 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
* it should be restarted.
*/
if (timr->it.real.interval.tv64 != 0) {
+ ktime_t now = hrtimer_cb_get_time(timer);
+
+ /*
+ * FIXME: What we really want, is to stop this
+ * timer completely and restart it in case the
+ * SIG_IGN is removed. This is a non trivial
+ * change which involves sighand locking
+ * (sigh !), which we don't want to do late in
+ * the release cycle.
+ *
+ * For now we just let timers with an interval
+ * less than a jiffie expire every jiffie to
+ * avoid softirq starvation in case of SIG_IGN
+ * and a very small interval, which would put
+ * the timer right back on the softirq pending
+ * list. By moving now ahead of time we trick
+ * hrtimer_forward() to expire the timer
+ * later, while we still maintain the overrun
+ * accuracy, but have some inconsistency in
+ * the timer_gettime() case. This is at least
+ * better than a starved softirq. A more
+ * complex fix which solves also another related
+ * inconsistency is already in the pipeline.
+ */
+#ifdef CONFIG_HIGH_RES_TIMERS
+ {
+ ktime_t kj = ktime_set(0, NSEC_PER_SEC / HZ);
+
+ if (timr->it.real.interval.tv64 < kj.tv64)
+ now = ktime_add(now, kj);
+ }
+#endif
timr->it_overrun +=
- hrtimer_forward(timer,
- hrtimer_cb_get_time(timer),
+ hrtimer_forward(timer, now,
timr->it.real.interval);
ret = HRTIMER_RESTART;
++timr->it_requeue_pending;
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 8812985f302..fc45ed22620 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -15,7 +15,6 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/pm.h>
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/resume-trace.h>
@@ -97,6 +96,11 @@ static int suspend_prepare(suspend_state_t state)
}
}
+ if (pm_ops->set_target) {
+ error = pm_ops->set_target(state);
+ if (error)
+ goto Thaw;
+ }
suspend_console();
error = device_suspend(PMSG_SUSPEND);
if (error) {
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 24d7d78e6f4..d65305b515b 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -99,6 +99,8 @@ static ssize_t snapshot_read(struct file *filp, char __user *buf,
ssize_t res;
data = filp->private_data;
+ if (!data->ready)
+ return -ENODATA;
res = snapshot_read_next(&data->handle, count);
if (res > 0) {
if (copy_to_user(buf, data_of(data->handle), res))
@@ -245,7 +247,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
break;
case SNAPSHOT_UNFREEZE:
- if (!data->frozen)
+ if (!data->frozen || data->ready)
break;
mutex_lock(&pm_mutex);
thaw_processes();
diff --git a/kernel/relay.c b/kernel/relay.c
index 4311101b0ca..a615a8f513f 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -21,6 +21,7 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/cpu.h>
+#include <linux/splice.h>
/* list of open channels, for cpu hotplug */
static DEFINE_MUTEX(relay_channels_mutex);
@@ -121,6 +122,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size)
buf->page_array[i] = alloc_page(GFP_KERNEL);
if (unlikely(!buf->page_array[i]))
goto depopulate;
+ set_page_private(buf->page_array[i], (unsigned long)buf);
}
mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL);
if (!mem)
@@ -812,7 +814,10 @@ static void relay_file_read_consume(struct rchan_buf *buf,
}
buf->bytes_consumed += bytes_consumed;
- read_subbuf = read_pos / buf->chan->subbuf_size;
+ if (!read_pos)
+ read_subbuf = buf->subbufs_consumed % n_subbufs;
+ else
+ read_subbuf = read_pos / buf->chan->subbuf_size;
if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) {
if ((read_subbuf == buf->subbufs_produced % n_subbufs) &&
(buf->offset == subbuf_size))
@@ -841,8 +846,9 @@ static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
}
if (unlikely(produced - consumed >= n_subbufs)) {
- consumed = (produced / n_subbufs) * n_subbufs;
+ consumed = produced - n_subbufs + 1;
buf->subbufs_consumed = consumed;
+ buf->bytes_consumed = 0;
}
produced = (produced % n_subbufs) * subbuf_size + buf->offset;
@@ -899,7 +905,10 @@ static size_t relay_file_read_start_pos(size_t read_pos,
size_t read_subbuf, padding, padding_start, padding_end;
size_t subbuf_size = buf->chan->subbuf_size;
size_t n_subbufs = buf->chan->n_subbufs;
+ size_t consumed = buf->subbufs_consumed % n_subbufs;
+ if (!read_pos)
+ read_pos = consumed * subbuf_size + buf->bytes_consumed;
read_subbuf = read_pos / subbuf_size;
padding = buf->padding[read_subbuf];
padding_start = (read_subbuf + 1) * subbuf_size - padding;
@@ -963,43 +972,6 @@ static int subbuf_read_actor(size_t read_start,
return ret;
}
-/*
- * subbuf_send_actor - send up to one subbuf's worth of data
- */
-static int subbuf_send_actor(size_t read_start,
- struct rchan_buf *buf,
- size_t avail,
- read_descriptor_t *desc,
- read_actor_t actor)
-{
- unsigned long pidx, poff;
- unsigned int subbuf_pages;
- int ret = 0;
-
- subbuf_pages = buf->chan->alloc_size >> PAGE_SHIFT;
- pidx = (read_start / PAGE_SIZE) % subbuf_pages;
- poff = read_start & ~PAGE_MASK;
- while (avail) {
- struct page *p = buf->page_array[pidx];
- unsigned int len;
-
- len = PAGE_SIZE - poff;
- if (len > avail)
- len = avail;
-
- len = actor(desc, p, poff, len);
- if (desc->error)
- break;
-
- avail -= len;
- ret += len;
- poff = 0;
- pidx = (pidx + 1) % subbuf_pages;
- }
-
- return ret;
-}
-
typedef int (*subbuf_actor_t) (size_t read_start,
struct rchan_buf *buf,
size_t avail,
@@ -1060,19 +1032,161 @@ static ssize_t relay_file_read(struct file *filp,
NULL, &desc);
}
-static ssize_t relay_file_sendfile(struct file *filp,
- loff_t *ppos,
- size_t count,
- read_actor_t actor,
- void *target)
+static void relay_consume_bytes(struct rchan_buf *rbuf, int bytes_consumed)
{
- read_descriptor_t desc;
- desc.written = 0;
- desc.count = count;
- desc.arg.data = target;
- desc.error = 0;
- return relay_file_read_subbufs(filp, ppos, subbuf_send_actor,
- actor, &desc);
+ rbuf->bytes_consumed += bytes_consumed;
+
+ if (rbuf->bytes_consumed >= rbuf->chan->subbuf_size) {
+ relay_subbufs_consumed(rbuf->chan, rbuf->cpu, 1);
+ rbuf->bytes_consumed %= rbuf->chan->subbuf_size;
+ }
+}
+
+static void relay_pipe_buf_release(struct pipe_inode_info *pipe,
+ struct pipe_buffer *buf)
+{
+ struct rchan_buf *rbuf;
+
+ rbuf = (struct rchan_buf *)page_private(buf->page);
+ relay_consume_bytes(rbuf, buf->private);
+}
+
+static struct pipe_buf_operations relay_pipe_buf_ops = {
+ .can_merge = 0,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .confirm = generic_pipe_buf_confirm,
+ .release = relay_pipe_buf_release,
+ .steal = generic_pipe_buf_steal,
+ .get = generic_pipe_buf_get,
+};
+
+/*
+ * subbuf_splice_actor - splice up to one subbuf's worth of data
+ */
+static int subbuf_splice_actor(struct file *in,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags,
+ int *nonpad_ret)
+{
+ unsigned int pidx, poff, total_len, subbuf_pages, ret;
+ struct rchan_buf *rbuf = in->private_data;
+ unsigned int subbuf_size = rbuf->chan->subbuf_size;
+ uint64_t pos = (uint64_t) *ppos;
+ uint32_t alloc_size = (uint32_t) rbuf->chan->alloc_size;
+ size_t read_start = (size_t) do_div(pos, alloc_size);
+ size_t read_subbuf = read_start / subbuf_size;
+ size_t padding = rbuf->padding[read_subbuf];
+ size_t nonpad_end = read_subbuf * subbuf_size + subbuf_size - padding;
+ struct page *pages[PIPE_BUFFERS];
+ struct partial_page partial[PIPE_BUFFERS];
+ struct splice_pipe_desc spd = {
+ .pages = pages,
+ .nr_pages = 0,
+ .partial = partial,
+ .flags = flags,
+ .ops = &relay_pipe_buf_ops,
+ };
+
+ if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
+ return 0;
+
+ /*
+ * Adjust read len, if longer than what is available
+ */
+ if (len > (subbuf_size - read_start % subbuf_size))
+ len = subbuf_size - read_start % subbuf_size;
+
+ subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT;
+ pidx = (read_start / PAGE_SIZE) % subbuf_pages;
+ poff = read_start & ~PAGE_MASK;
+
+ for (total_len = 0; spd.nr_pages < subbuf_pages; spd.nr_pages++) {
+ unsigned int this_len, this_end, private;
+ unsigned int cur_pos = read_start + total_len;
+
+ if (!len)
+ break;
+
+ this_len = min_t(unsigned long, len, PAGE_SIZE - poff);
+ private = this_len;
+
+ spd.pages[spd.nr_pages] = rbuf->page_array[pidx];
+ spd.partial[spd.nr_pages].offset = poff;
+
+ this_end = cur_pos + this_len;
+ if (this_end >= nonpad_end) {
+ this_len = nonpad_end - cur_pos;
+ private = this_len + padding;
+ }
+ spd.partial[spd.nr_pages].len = this_len;
+ spd.partial[spd.nr_pages].private = private;
+
+ len -= this_len;
+ total_len += this_len;
+ poff = 0;
+ pidx = (pidx + 1) % subbuf_pages;
+
+ if (this_end >= nonpad_end) {
+ spd.nr_pages++;
+ break;
+ }
+ }
+
+ if (!spd.nr_pages)
+ return 0;
+
+ ret = *nonpad_ret = splice_to_pipe(pipe, &spd);
+ if (ret < 0 || ret < total_len)
+ return ret;
+
+ if (read_start + ret == nonpad_end)
+ ret += padding;
+
+ return ret;
+}
+
+static ssize_t relay_file_splice_read(struct file *in,
+ loff_t *ppos,
+ struct pipe_inode_info *pipe,
+ size_t len,
+ unsigned int flags)
+{
+ ssize_t spliced;
+ int ret;
+ int nonpad_ret = 0;
+
+ ret = 0;
+ spliced = 0;
+
+ while (len) {
+ ret = subbuf_splice_actor(in, ppos, pipe, len, flags, &nonpad_ret);
+ if (ret < 0)
+ break;
+ else if (!ret) {
+ if (spliced)
+ break;
+ if (flags & SPLICE_F_NONBLOCK) {
+ ret = -EAGAIN;
+ break;
+ }
+ }
+
+ *ppos += ret;
+ if (ret > len)
+ len = 0;
+ else
+ len -= ret;
+ spliced += nonpad_ret;
+ nonpad_ret = 0;
+ }
+
+ if (spliced)
+ return spliced;
+
+ return ret;
}
const struct file_operations relay_file_operations = {
@@ -1082,7 +1196,7 @@ const struct file_operations relay_file_operations = {
.read = relay_file_read,
.llseek = no_llseek,
.release = relay_file_release,
- .sendfile = relay_file_sendfile,
+ .splice_read = relay_file_splice_read,
};
EXPORT_SYMBOL_GPL(relay_file_operations);
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 12879f6c1ec..17d28ce2030 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -56,7 +56,7 @@
* state.
*/
-void
+static void
rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
unsigned long mask)
{
@@ -81,6 +81,29 @@ static void fixup_rt_mutex_waiters(struct rt_mutex *lock)
}
/*
+ * We can speed up the acquire/release, if the architecture
+ * supports cmpxchg and if there's no debugging state to be set up
+ */
+#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES)
+# define rt_mutex_cmpxchg(l,c,n) (cmpxchg(&l->owner, c, n) == c)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+ unsigned long owner, *p = (unsigned long *) &lock->owner;
+
+ do {
+ owner = *p;
+ } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner);
+}
+#else
+# define rt_mutex_cmpxchg(l,c,n) (0)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+ lock->owner = (struct task_struct *)
+ ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS);
+}
+#endif
+
+/*
* Calculate task priority from the waiter list priority
*
* Return task->normal_prio when the waiter list is empty or when
@@ -100,7 +123,7 @@ int rt_mutex_getprio(struct task_struct *task)
*
* This can be both boosting and unboosting. task->pi_lock must be held.
*/
-void __rt_mutex_adjust_prio(struct task_struct *task)
+static void __rt_mutex_adjust_prio(struct task_struct *task)
{
int prio = rt_mutex_getprio(task);
@@ -136,11 +159,11 @@ int max_lock_depth = 1024;
* Decreases task's usage by one - may thus free the task.
* Returns 0 or -EDEADLK.
*/
-int rt_mutex_adjust_prio_chain(struct task_struct *task,
- int deadlock_detect,
- struct rt_mutex *orig_lock,
- struct rt_mutex_waiter *orig_waiter,
- struct task_struct *top_task)
+static int rt_mutex_adjust_prio_chain(struct task_struct *task,
+ int deadlock_detect,
+ struct rt_mutex *orig_lock,
+ struct rt_mutex_waiter *orig_waiter,
+ struct task_struct *top_task)
{
struct rt_mutex *lock;
struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter;
@@ -189,6 +212,19 @@ int rt_mutex_adjust_prio_chain(struct task_struct *task,
if (!waiter || !waiter->task)
goto out_unlock_pi;
+ /*
+ * Check the orig_waiter state. After we dropped the locks,
+ * the previous owner of the lock might have released the lock
+ * and made us the pending owner:
+ */
+ if (orig_waiter && !orig_waiter->task)
+ goto out_unlock_pi;
+
+ /*
+ * Drop out, when the task has no waiters. Note,
+ * top_waiter can be NULL, when we are in the deboosting
+ * mode!
+ */
if (top_waiter && (!task_has_pi_waiters(task) ||
top_waiter != task_top_pi_waiter(task)))
goto out_unlock_pi;
@@ -501,8 +537,8 @@ static void wakeup_next_waiter(struct rt_mutex *lock)
*
* Must be called with lock->wait_lock held
*/
-void remove_waiter(struct rt_mutex *lock,
- struct rt_mutex_waiter *waiter)
+static void remove_waiter(struct rt_mutex *lock,
+ struct rt_mutex_waiter *waiter)
{
int first = (waiter == rt_mutex_top_waiter(lock));
struct task_struct *owner = rt_mutex_owner(lock);
@@ -636,9 +672,16 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
* all over without going into schedule to try
* to get the lock now:
*/
- if (unlikely(!waiter.task))
+ if (unlikely(!waiter.task)) {
+ /*
+ * Reset the return value. We might
+ * have returned with -EDEADLK and the
+ * owner released the lock while we
+ * were walking the pi chain.
+ */
+ ret = 0;
continue;
-
+ }
if (unlikely(ret))
break;
}
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
index 242ec7ee740..9c75856e791 100644
--- a/kernel/rtmutex_common.h
+++ b/kernel/rtmutex_common.h
@@ -113,29 +113,6 @@ static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock)
}
/*
- * We can speed up the acquire/release, if the architecture
- * supports cmpxchg and if there's no debugging state to be set up
- */
-#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES)
-# define rt_mutex_cmpxchg(l,c,n) (cmpxchg(&l->owner, c, n) == c)
-static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
-{
- unsigned long owner, *p = (unsigned long *) &lock->owner;
-
- do {
- owner = *p;
- } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner);
-}
-#else
-# define rt_mutex_cmpxchg(l,c,n) (0)
-static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
-{
- lock->owner = (struct task_struct *)
- ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS);
-}
-#endif
-
-/*
* PI-futex support (proxy locking functions, etc.):
*/
extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock);
@@ -143,15 +120,4 @@ extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
struct task_struct *proxy_owner);
extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
struct task_struct *proxy_owner);
-
-extern void rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
- unsigned long mask);
-extern void __rt_mutex_adjust_prio(struct task_struct *task);
-extern int rt_mutex_adjust_prio_chain(struct task_struct *task,
- int deadlock_detect,
- struct rt_mutex *orig_lock,
- struct rt_mutex_waiter *orig_waiter,
- struct task_struct *top_task);
-extern void remove_waiter(struct rt_mutex *lock,
- struct rt_mutex_waiter *waiter);
#endif
diff --git a/kernel/sched.c b/kernel/sched.c
index 13cdab3b4c4..3332bbb5d5c 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -16,13 +16,19 @@
* by Davide Libenzi, preemptible kernel bits by Robert Love.
* 2003-09-03 Interactivity tuning by Con Kolivas.
* 2004-04-02 Scheduler domains code by Nick Piggin
+ * 2007-04-15 Work begun on replacing all interactivity tuning with a
+ * fair scheduling design by Con Kolivas.
+ * 2007-05-05 Load balancing (smp-nice) and other improvements
+ * by Peter Williams
+ * 2007-05-06 Interactivity improvements to CFS by Mike Galbraith
+ * 2007-07-01 Group scheduling enhancements by Srivatsa Vaddagiri
*/
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/nmi.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
#include <linux/highmem.h>
#include <linux/smp_lock.h>
#include <asm/mmu_context.h>
@@ -53,9 +59,9 @@
#include <linux/kprobes.h>
#include <linux/delayacct.h>
#include <linux/reciprocal_div.h>
+#include <linux/unistd.h>
#include <asm/tlb.h>
-#include <asm/unistd.h>
/*
* Scheduler clock - returns current time in nanosec units.
@@ -91,6 +97,9 @@ unsigned long long __attribute__((weak)) sched_clock(void)
#define NS_TO_JIFFIES(TIME) ((TIME) / (1000000000 / HZ))
#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ))
+#define NICE_0_LOAD SCHED_LOAD_SCALE
+#define NICE_0_SHIFT SCHED_LOAD_SHIFT
+
/*
* These are the 'tuning knobs' of the scheduler:
*
@@ -100,87 +109,6 @@ unsigned long long __attribute__((weak)) sched_clock(void)
*/
#define MIN_TIMESLICE max(5 * HZ / 1000, 1)
#define DEF_TIMESLICE (100 * HZ / 1000)
-#define ON_RUNQUEUE_WEIGHT 30
-#define CHILD_PENALTY 95
-#define PARENT_PENALTY 100
-#define EXIT_WEIGHT 3
-#define PRIO_BONUS_RATIO 25
-#define MAX_BONUS (MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
-#define INTERACTIVE_DELTA 2
-#define MAX_SLEEP_AVG (DEF_TIMESLICE * MAX_BONUS)
-#define STARVATION_LIMIT (MAX_SLEEP_AVG)
-#define NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(MAX_SLEEP_AVG))
-
-/*
- * If a task is 'interactive' then we reinsert it in the active
- * array after it has expired its current timeslice. (it will not
- * continue to run immediately, it will still roundrobin with
- * other interactive tasks.)
- *
- * This part scales the interactivity limit depending on niceness.
- *
- * We scale it linearly, offset by the INTERACTIVE_DELTA delta.
- * Here are a few examples of different nice levels:
- *
- * TASK_INTERACTIVE(-20): [1,1,1,1,1,1,1,1,1,0,0]
- * TASK_INTERACTIVE(-10): [1,1,1,1,1,1,1,0,0,0,0]
- * TASK_INTERACTIVE( 0): [1,1,1,1,0,0,0,0,0,0,0]
- * TASK_INTERACTIVE( 10): [1,1,0,0,0,0,0,0,0,0,0]
- * TASK_INTERACTIVE( 19): [0,0,0,0,0,0,0,0,0,0,0]
- *
- * (the X axis represents the possible -5 ... 0 ... +5 dynamic
- * priority range a task can explore, a value of '1' means the
- * task is rated interactive.)
- *
- * Ie. nice +19 tasks can never get 'interactive' enough to be
- * reinserted into the active array. And only heavily CPU-hog nice -20
- * tasks will be expired. Default nice 0 tasks are somewhere between,
- * it takes some effort for them to get interactive, but it's not
- * too hard.
- */
-
-#define CURRENT_BONUS(p) \
- (NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
- MAX_SLEEP_AVG)
-
-#define GRANULARITY (10 * HZ / 1000 ? : 1)
-
-#ifdef CONFIG_SMP
-#define TIMESLICE_GRANULARITY(p) (GRANULARITY * \
- (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \
- num_online_cpus())
-#else
-#define TIMESLICE_GRANULARITY(p) (GRANULARITY * \
- (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)))
-#endif
-
-#define SCALE(v1,v1_max,v2_max) \
- (v1) * (v2_max) / (v1_max)
-
-#define DELTA(p) \
- (SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \
- INTERACTIVE_DELTA)
-
-#define TASK_INTERACTIVE(p) \
- ((p)->prio <= (p)->static_prio - DELTA(p))
-
-#define INTERACTIVE_SLEEP(p) \
- (JIFFIES_TO_NS(MAX_SLEEP_AVG * \
- (MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1))
-
-#define TASK_PREEMPTS_CURR(p, rq) \
- ((p)->prio < (rq)->curr->prio)
-
-#define SCALE_PRIO(x, prio) \
- max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
-
-static unsigned int static_prio_timeslice(int static_prio)
-{
- if (static_prio < NICE_TO_PRIO(0))
- return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
- else
- return SCALE_PRIO(DEF_TIMESLICE, static_prio);
-}
#ifdef CONFIG_SMP
/*
@@ -203,28 +131,87 @@ static inline void sg_inc_cpu_power(struct sched_group *sg, u32 val)
}
#endif
+#define SCALE_PRIO(x, prio) \
+ max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
+
/*
- * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
+ * static_prio_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
* to time slice values: [800ms ... 100ms ... 5ms]
- *
- * The higher a thread's priority, the bigger timeslices
- * it gets during one round of execution. But even the lowest
- * priority thread gets MIN_TIMESLICE worth of execution time.
*/
+static unsigned int static_prio_timeslice(int static_prio)
+{
+ if (static_prio == NICE_TO_PRIO(19))
+ return 1;
-static inline unsigned int task_timeslice(struct task_struct *p)
+ if (static_prio < NICE_TO_PRIO(0))
+ return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
+ else
+ return SCALE_PRIO(DEF_TIMESLICE, static_prio);
+}
+
+static inline int rt_policy(int policy)
+{
+ if (unlikely(policy == SCHED_FIFO) || unlikely(policy == SCHED_RR))
+ return 1;
+ return 0;
+}
+
+static inline int task_has_rt_policy(struct task_struct *p)
{
- return static_prio_timeslice(p->static_prio);
+ return rt_policy(p->policy);
}
/*
- * These are the runqueue data structures:
+ * This is the priority-queue data structure of the RT scheduling class:
*/
+struct rt_prio_array {
+ DECLARE_BITMAP(bitmap, MAX_RT_PRIO+1); /* include 1 bit for delimiter */
+ struct list_head queue[MAX_RT_PRIO];
+};
-struct prio_array {
- unsigned int nr_active;
- DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
- struct list_head queue[MAX_PRIO];
+struct load_stat {
+ struct load_weight load;
+ u64 load_update_start, load_update_last;
+ unsigned long delta_fair, delta_exec, delta_stat;
+};
+
+/* CFS-related fields in a runqueue */
+struct cfs_rq {
+ struct load_weight load;
+ unsigned long nr_running;
+
+ s64 fair_clock;
+ u64 exec_clock;
+ s64 wait_runtime;
+ u64 sleeper_bonus;
+ unsigned long wait_runtime_overruns, wait_runtime_underruns;
+
+ struct rb_root tasks_timeline;
+ struct rb_node *rb_leftmost;
+ struct rb_node *rb_load_balance_curr;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ /* 'curr' points to currently running entity on this cfs_rq.
+ * It is set to NULL otherwise (i.e when none are currently running).
+ */
+ struct sched_entity *curr;
+ struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */
+
+ /* leaf cfs_rqs are those that hold tasks (lowest schedulable entity in
+ * a hierarchy). Non-leaf lrqs hold other higher schedulable entities
+ * (like users, containers etc.)
+ *
+ * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This
+ * list is used during load balance.
+ */
+ struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */
+#endif
+};
+
+/* Real-Time classes' related field in a runqueue: */
+struct rt_rq {
+ struct rt_prio_array active;
+ int rt_load_balance_idx;
+ struct list_head *rt_load_balance_head, *rt_load_balance_curr;
};
/*
@@ -235,22 +222,28 @@ struct prio_array {
* acquire operations must be ordered by ascending &runqueue.
*/
struct rq {
- spinlock_t lock;
+ spinlock_t lock; /* runqueue lock */
/*
* nr_running and cpu_load should be in the same cacheline because
* remote CPUs use both these fields when doing load calculation.
*/
unsigned long nr_running;
- unsigned long raw_weighted_load;
-#ifdef CONFIG_SMP
- unsigned long cpu_load[3];
+ #define CPU_LOAD_IDX_MAX 5
+ unsigned long cpu_load[CPU_LOAD_IDX_MAX];
unsigned char idle_at_tick;
#ifdef CONFIG_NO_HZ
unsigned char in_nohz_recently;
#endif
+ struct load_stat ls; /* capture load from *all* tasks on this cpu */
+ unsigned long nr_load_updates;
+ u64 nr_switches;
+
+ struct cfs_rq cfs;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ struct list_head leaf_cfs_rq_list; /* list of leaf cfs_rq on this cpu */
#endif
- unsigned long long nr_switches;
+ struct rt_rq rt;
/*
* This is part of a global counter where only the total sum
@@ -260,14 +253,18 @@ struct rq {
*/
unsigned long nr_uninterruptible;
- unsigned long expired_timestamp;
- /* Cached timestamp set by update_cpu_clock() */
- unsigned long long most_recent_timestamp;
struct task_struct *curr, *idle;
unsigned long next_balance;
struct mm_struct *prev_mm;
- struct prio_array *active, *expired, arrays[2];
- int best_expired_prio;
+
+ u64 clock, prev_clock_raw;
+ s64 clock_max_delta;
+
+ unsigned int clock_warps, clock_overflows;
+ unsigned int clock_unstable_events;
+
+ struct sched_class *load_balance_class;
+
atomic_t nr_iowait;
#ifdef CONFIG_SMP
@@ -307,6 +304,11 @@ struct rq {
static DEFINE_PER_CPU(struct rq, runqueues) ____cacheline_aligned_in_smp;
static DEFINE_MUTEX(sched_hotcpu_mutex);
+static inline void check_preempt_curr(struct rq *rq, struct task_struct *p)
+{
+ rq->curr->sched_class->check_preempt_curr(rq, p);
+}
+
static inline int cpu_of(struct rq *rq)
{
#ifdef CONFIG_SMP
@@ -317,6 +319,52 @@ static inline int cpu_of(struct rq *rq)
}
/*
+ * Per-runqueue clock, as finegrained as the platform can give us:
+ */
+static unsigned long long __rq_clock(struct rq *rq)
+{
+ u64 prev_raw = rq->prev_clock_raw;
+ u64 now = sched_clock();
+ s64 delta = now - prev_raw;
+ u64 clock = rq->clock;
+
+ /*
+ * Protect against sched_clock() occasionally going backwards:
+ */
+ if (unlikely(delta < 0)) {
+ clock++;
+ rq->clock_warps++;
+ } else {
+ /*
+ * Catch too large forward jumps too:
+ */
+ if (unlikely(delta > 2*TICK_NSEC)) {
+ clock++;
+ rq->clock_overflows++;
+ } else {
+ if (unlikely(delta > rq->clock_max_delta))
+ rq->clock_max_delta = delta;
+ clock += delta;
+ }
+ }
+
+ rq->prev_clock_raw = now;
+ rq->clock = clock;
+
+ return clock;
+}
+
+static inline unsigned long long rq_clock(struct rq *rq)
+{
+ int this_cpu = smp_processor_id();
+
+ if (this_cpu == cpu_of(rq))
+ return __rq_clock(rq);
+
+ return rq->clock;
+}
+
+/*
* The domain tree (rq->sd) is protected by RCU's quiescent state transition.
* See detach_destroy_domains: synchronize_sched for details.
*
@@ -331,6 +379,18 @@ static inline int cpu_of(struct rq *rq)
#define task_rq(p) cpu_rq(task_cpu(p))
#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/* Change a task's ->cfs_rq if it moves across CPUs */
+static inline void set_task_cfs_rq(struct task_struct *p)
+{
+ p->se.cfs_rq = &task_rq(p)->cfs;
+}
+#else
+static inline void set_task_cfs_rq(struct task_struct *p)
+{
+}
+#endif
+
#ifndef prepare_arch_switch
# define prepare_arch_switch(next) do { } while (0)
#endif
@@ -460,134 +520,6 @@ static inline void task_rq_unlock(struct rq *rq, unsigned long *flags)
spin_unlock_irqrestore(&rq->lock, *flags);
}
-#ifdef CONFIG_SCHEDSTATS
-/*
- * bump this up when changing the output format or the meaning of an existing
- * format, so that tools can adapt (or abort)
- */
-#define SCHEDSTAT_VERSION 14
-
-static int show_schedstat(struct seq_file *seq, void *v)
-{
- int cpu;
-
- seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
- seq_printf(seq, "timestamp %lu\n", jiffies);
- for_each_online_cpu(cpu) {
- struct rq *rq = cpu_rq(cpu);
-#ifdef CONFIG_SMP
- struct sched_domain *sd;
- int dcnt = 0;
-#endif
-
- /* runqueue-specific stats */
- seq_printf(seq,
- "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
- cpu, rq->yld_both_empty,
- rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
- rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
- rq->ttwu_cnt, rq->ttwu_local,
- rq->rq_sched_info.cpu_time,
- rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
-
- seq_printf(seq, "\n");
-
-#ifdef CONFIG_SMP
- /* domain-specific stats */
- preempt_disable();
- for_each_domain(cpu, sd) {
- enum idle_type itype;
- char mask_str[NR_CPUS];
-
- cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
- seq_printf(seq, "domain%d %s", dcnt++, mask_str);
- for (itype = SCHED_IDLE; itype < MAX_IDLE_TYPES;
- itype++) {
- seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
- "%lu",
- sd->lb_cnt[itype],
- sd->lb_balanced[itype],
- sd->lb_failed[itype],
- sd->lb_imbalance[itype],
- sd->lb_gained[itype],
- sd->lb_hot_gained[itype],
- sd->lb_nobusyq[itype],
- sd->lb_nobusyg[itype]);
- }
- seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
- " %lu %lu %lu\n",
- sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
- sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
- sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
- sd->ttwu_wake_remote, sd->ttwu_move_affine,
- sd->ttwu_move_balance);
- }
- preempt_enable();
-#endif
- }
- return 0;
-}
-
-static int schedstat_open(struct inode *inode, struct file *file)
-{
- unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
- char *buf = kmalloc(size, GFP_KERNEL);
- struct seq_file *m;
- int res;
-
- if (!buf)
- return -ENOMEM;
- res = single_open(file, show_schedstat, NULL);
- if (!res) {
- m = file->private_data;
- m->buf = buf;
- m->size = size;
- } else
- kfree(buf);
- return res;
-}
-
-const struct file_operations proc_schedstat_operations = {
- .open = schedstat_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/*
- * Expects runqueue lock to be held for atomicity of update
- */
-static inline void
-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
-{
- if (rq) {
- rq->rq_sched_info.run_delay += delta_jiffies;
- rq->rq_sched_info.pcnt++;
- }
-}
-
-/*
- * Expects runqueue lock to be held for atomicity of update
- */
-static inline void
-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
-{
- if (rq)
- rq->rq_sched_info.cpu_time += delta_jiffies;
-}
-# define schedstat_inc(rq, field) do { (rq)->field++; } while (0)
-# define schedstat_add(rq, field, amt) do { (rq)->field += (amt); } while (0)
-#else /* !CONFIG_SCHEDSTATS */
-static inline void
-rq_sched_info_arrive(struct rq *rq, unsigned long delta_jiffies)
-{}
-static inline void
-rq_sched_info_depart(struct rq *rq, unsigned long delta_jiffies)
-{}
-# define schedstat_inc(rq, field) do { } while (0)
-# define schedstat_add(rq, field, amt) do { } while (0)
-#endif
-
/*
* this_rq_lock - lock this runqueue and disable interrupts.
*/
@@ -603,177 +535,172 @@ static inline struct rq *this_rq_lock(void)
return rq;
}
-#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
/*
- * Called when a process is dequeued from the active array and given
- * the cpu. We should note that with the exception of interactive
- * tasks, the expired queue will become the active queue after the active
- * queue is empty, without explicitly dequeuing and requeuing tasks in the
- * expired queue. (Interactive tasks may be requeued directly to the
- * active queue, thus delaying tasks in the expired queue from running;
- * see scheduler_tick()).
- *
- * This function is only called from sched_info_arrive(), rather than
- * dequeue_task(). Even though a task may be queued and dequeued multiple
- * times as it is shuffled about, we're really interested in knowing how
- * long it was from the *first* time it was queued to the time that it
- * finally hit a cpu.
+ * CPU frequency is/was unstable - start new by setting prev_clock_raw:
*/
-static inline void sched_info_dequeued(struct task_struct *t)
+void sched_clock_unstable_event(void)
{
- t->sched_info.last_queued = 0;
+ unsigned long flags;
+ struct rq *rq;
+
+ rq = task_rq_lock(current, &flags);
+ rq->prev_clock_raw = sched_clock();
+ rq->clock_unstable_events++;
+ task_rq_unlock(rq, &flags);
}
/*
- * Called when a task finally hits the cpu. We can now calculate how
- * long it was waiting to run. We also note when it began so that we
- * can keep stats on how long its timeslice is.
+ * resched_task - mark a task 'to be rescheduled now'.
+ *
+ * On UP this means the setting of the need_resched flag, on SMP it
+ * might also involve a cross-CPU call to trigger the scheduler on
+ * the target CPU.
*/
-static void sched_info_arrive(struct task_struct *t)
+#ifdef CONFIG_SMP
+
+#ifndef tsk_is_polling
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+#endif
+
+static void resched_task(struct task_struct *p)
{
- unsigned long now = jiffies, delta_jiffies = 0;
+ int cpu;
- if (t->sched_info.last_queued)
- delta_jiffies = now - t->sched_info.last_queued;
- sched_info_dequeued(t);
- t->sched_info.run_delay += delta_jiffies;
- t->sched_info.last_arrival = now;
- t->sched_info.pcnt++;
+ assert_spin_locked(&task_rq(p)->lock);
+
+ if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED)))
+ return;
- rq_sched_info_arrive(task_rq(t), delta_jiffies);
+ set_tsk_thread_flag(p, TIF_NEED_RESCHED);
+
+ cpu = task_cpu(p);
+ if (cpu == smp_processor_id())
+ return;
+
+ /* NEED_RESCHED must be visible before we test polling */
+ smp_mb();
+ if (!tsk_is_polling(p))
+ smp_send_reschedule(cpu);
}
-/*
- * Called when a process is queued into either the active or expired
- * array. The time is noted and later used to determine how long we
- * had to wait for us to reach the cpu. Since the expired queue will
- * become the active queue after active queue is empty, without dequeuing
- * and requeuing any tasks, we are interested in queuing to either. It
- * is unusual but not impossible for tasks to be dequeued and immediately
- * requeued in the same or another array: this can happen in sched_yield(),
- * set_user_nice(), and even load_balance() as it moves tasks from runqueue
- * to runqueue.
- *
- * This function is only called from enqueue_task(), but also only updates
- * the timestamp if it is already not set. It's assumed that
- * sched_info_dequeued() will clear that stamp when appropriate.
- */
-static inline void sched_info_queued(struct task_struct *t)
+static void resched_cpu(int cpu)
{
- if (unlikely(sched_info_on()))
- if (!t->sched_info.last_queued)
- t->sched_info.last_queued = jiffies;
+ struct rq *rq = cpu_rq(cpu);
+ unsigned long flags;
+
+ if (!spin_trylock_irqsave(&rq->lock, flags))
+ return;
+ resched_task(cpu_curr(cpu));
+ spin_unlock_irqrestore(&rq->lock, flags);
+}
+#else
+static inline void resched_task(struct task_struct *p)
+{
+ assert_spin_locked(&task_rq(p)->lock);
+ set_tsk_need_resched(p);
}
+#endif
-/*
- * Called when a process ceases being the active-running process, either
- * voluntarily or involuntarily. Now we can calculate how long we ran.
- */
-static inline void sched_info_depart(struct task_struct *t)
+static u64 div64_likely32(u64 divident, unsigned long divisor)
{
- unsigned long delta_jiffies = jiffies - t->sched_info.last_arrival;
+#if BITS_PER_LONG == 32
+ if (likely(divident <= 0xffffffffULL))
+ return (u32)divident / divisor;
+ do_div(divident, divisor);
- t->sched_info.cpu_time += delta_jiffies;
- rq_sched_info_depart(task_rq(t), delta_jiffies);
+ return divident;
+#else
+ return divident / divisor;
+#endif
}
-/*
- * Called when tasks are switched involuntarily due, typically, to expiring
- * their time slice. (This may also be called when switching to or from
- * the idle task.) We are only called when prev != next.
- */
-static inline void
-__sched_info_switch(struct task_struct *prev, struct task_struct *next)
+#if BITS_PER_LONG == 32
+# define WMULT_CONST (~0UL)
+#else
+# define WMULT_CONST (1UL << 32)
+#endif
+
+#define WMULT_SHIFT 32
+
+static inline unsigned long
+calc_delta_mine(unsigned long delta_exec, unsigned long weight,
+ struct load_weight *lw)
{
- struct rq *rq = task_rq(prev);
+ u64 tmp;
+
+ if (unlikely(!lw->inv_weight))
+ lw->inv_weight = WMULT_CONST / lw->weight;
+ tmp = (u64)delta_exec * weight;
/*
- * prev now departs the cpu. It's not interesting to record
- * stats about how efficient we were at scheduling the idle
- * process, however.
+ * Check whether we'd overflow the 64-bit multiplication:
*/
- if (prev != rq->idle)
- sched_info_depart(prev);
+ if (unlikely(tmp > WMULT_CONST)) {
+ tmp = ((tmp >> WMULT_SHIFT/2) * lw->inv_weight)
+ >> (WMULT_SHIFT/2);
+ } else {
+ tmp = (tmp * lw->inv_weight) >> WMULT_SHIFT;
+ }
- if (next != rq->idle)
- sched_info_arrive(next);
+ return (unsigned long)min(tmp, (u64)sysctl_sched_runtime_limit);
}
-static inline void
-sched_info_switch(struct task_struct *prev, struct task_struct *next)
-{
- if (unlikely(sched_info_on()))
- __sched_info_switch(prev, next);
-}
-#else
-#define sched_info_queued(t) do { } while (0)
-#define sched_info_switch(t, next) do { } while (0)
-#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
-/*
- * Adding/removing a task to/from a priority array:
- */
-static void dequeue_task(struct task_struct *p, struct prio_array *array)
+static inline unsigned long
+calc_delta_fair(unsigned long delta_exec, struct load_weight *lw)
{
- array->nr_active--;
- list_del(&p->run_list);
- if (list_empty(array->queue + p->prio))
- __clear_bit(p->prio, array->bitmap);
+ return calc_delta_mine(delta_exec, NICE_0_LOAD, lw);
}
-static void enqueue_task(struct task_struct *p, struct prio_array *array)
+static void update_load_add(struct load_weight *lw, unsigned long inc)
{
- sched_info_queued(p);
- list_add_tail(&p->run_list, array->queue + p->prio);
- __set_bit(p->prio, array->bitmap);
- array->nr_active++;
- p->array = array;
+ lw->weight += inc;
+ lw->inv_weight = 0;
}
-/*
- * Put task to the end of the run list without the overhead of dequeue
- * followed by enqueue.
- */
-static void requeue_task(struct task_struct *p, struct prio_array *array)
+static void update_load_sub(struct load_weight *lw, unsigned long dec)
{
- list_move_tail(&p->run_list, array->queue + p->prio);
+ lw->weight -= dec;
+ lw->inv_weight = 0;
}
-static inline void
-enqueue_task_head(struct task_struct *p, struct prio_array *array)
+static void __update_curr_load(struct rq *rq, struct load_stat *ls)
{
- list_add(&p->run_list, array->queue + p->prio);
- __set_bit(p->prio, array->bitmap);
- array->nr_active++;
- p->array = array;
+ if (rq->curr != rq->idle && ls->load.weight) {
+ ls->delta_exec += ls->delta_stat;
+ ls->delta_fair += calc_delta_fair(ls->delta_stat, &ls->load);
+ ls->delta_stat = 0;
+ }
}
/*
- * __normal_prio - return the priority that is based on the static
- * priority but is modified by bonuses/penalties.
- *
- * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
- * into the -5 ... 0 ... +5 bonus/penalty range.
+ * Update delta_exec, delta_fair fields for rq.
*
- * We use 25% of the full 0...39 priority range so that:
+ * delta_fair clock advances at a rate inversely proportional to
+ * total load (rq->ls.load.weight) on the runqueue, while
+ * delta_exec advances at the same rate as wall-clock (provided
+ * cpu is not idle).
*
- * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
- * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
+ * delta_exec / delta_fair is a measure of the (smoothened) load on this
+ * runqueue over any given interval. This (smoothened) load is used
+ * during load balance.
*
- * Both properties are important to certain workloads.
+ * This function is called /before/ updating rq->ls.load
+ * and when switching tasks.
*/
-
-static inline int __normal_prio(struct task_struct *p)
+static void update_curr_load(struct rq *rq, u64 now)
{
- int bonus, prio;
+ struct load_stat *ls = &rq->ls;
+ u64 start;
- bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
-
- prio = p->static_prio - bonus;
- if (prio < MAX_RT_PRIO)
- prio = MAX_RT_PRIO;
- if (prio > MAX_PRIO-1)
- prio = MAX_PRIO-1;
- return prio;
+ start = ls->load_update_start;
+ ls->load_update_start = now;
+ ls->delta_stat += now - start;
+ /*
+ * Stagger updates to ls->delta_fair. Very frequent updates
+ * can be expensive.
+ */
+ if (ls->delta_stat >= sysctl_sched_stat_granularity)
+ __update_curr_load(rq, ls);
}
/*
@@ -791,53 +718,146 @@ static inline int __normal_prio(struct task_struct *p)
* this code will need modification
*/
#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
-#define LOAD_WEIGHT(lp) \
+#define load_weight(lp) \
(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
#define PRIO_TO_LOAD_WEIGHT(prio) \
- LOAD_WEIGHT(static_prio_timeslice(prio))
+ load_weight(static_prio_timeslice(prio))
#define RTPRIO_TO_LOAD_WEIGHT(rp) \
- (PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))
+ (PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + load_weight(rp))
-static void set_load_weight(struct task_struct *p)
-{
- if (has_rt_policy(p)) {
-#ifdef CONFIG_SMP
- if (p == task_rq(p)->migration_thread)
- /*
- * The migration thread does the actual balancing.
- * Giving its load any weight will skew balancing
- * adversely.
- */
- p->load_weight = 0;
- else
-#endif
- p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
- } else
- p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
-}
+#define WEIGHT_IDLEPRIO 2
+#define WMULT_IDLEPRIO (1 << 31)
+
+/*
+ * Nice levels are multiplicative, with a gentle 10% change for every
+ * nice level changed. I.e. when a CPU-bound task goes from nice 0 to
+ * nice 1, it will get ~10% less CPU time than another CPU-bound task
+ * that remained on nice 0.
+ *
+ * The "10% effect" is relative and cumulative: from _any_ nice level,
+ * if you go up 1 level, it's -10% CPU usage, if you go down 1 level
+ * it's +10% CPU usage.
+ */
+static const int prio_to_weight[40] = {
+/* -20 */ 88818, 71054, 56843, 45475, 36380, 29104, 23283, 18626, 14901, 11921,
+/* -10 */ 9537, 7629, 6103, 4883, 3906, 3125, 2500, 2000, 1600, 1280,
+/* 0 */ NICE_0_LOAD /* 1024 */,
+/* 1 */ 819, 655, 524, 419, 336, 268, 215, 172, 137,
+/* 10 */ 110, 87, 70, 56, 45, 36, 29, 23, 18, 15,
+};
+
+static const u32 prio_to_wmult[40] = {
+ 48356, 60446, 75558, 94446, 118058, 147573,
+ 184467, 230589, 288233, 360285, 450347,
+ 562979, 703746, 879575, 1099582, 1374389,
+ 1717986, 2147483, 2684354, 3355443, 4194304,
+ 5244160, 6557201, 8196502, 10250518, 12782640,
+ 16025997, 19976592, 24970740, 31350126, 39045157,
+ 49367440, 61356675, 76695844, 95443717, 119304647,
+ 148102320, 186737708, 238609294, 286331153,
+};
static inline void
-inc_raw_weighted_load(struct rq *rq, const struct task_struct *p)
+inc_load(struct rq *rq, const struct task_struct *p, u64 now)
{
- rq->raw_weighted_load += p->load_weight;
+ update_curr_load(rq, now);
+ update_load_add(&rq->ls.load, p->se.load.weight);
}
static inline void
-dec_raw_weighted_load(struct rq *rq, const struct task_struct *p)
+dec_load(struct rq *rq, const struct task_struct *p, u64 now)
{
- rq->raw_weighted_load -= p->load_weight;
+ update_curr_load(rq, now);
+ update_load_sub(&rq->ls.load, p->se.load.weight);
}
-static inline void inc_nr_running(struct task_struct *p, struct rq *rq)
+static inline void inc_nr_running(struct task_struct *p, struct rq *rq, u64 now)
{
rq->nr_running++;
- inc_raw_weighted_load(rq, p);
+ inc_load(rq, p, now);
}
-static inline void dec_nr_running(struct task_struct *p, struct rq *rq)
+static inline void dec_nr_running(struct task_struct *p, struct rq *rq, u64 now)
{
rq->nr_running--;
- dec_raw_weighted_load(rq, p);
+ dec_load(rq, p, now);
+}
+
+static void activate_task(struct rq *rq, struct task_struct *p, int wakeup);
+
+/*
+ * runqueue iterator, to support SMP load-balancing between different
+ * scheduling classes, without having to expose their internal data
+ * structures to the load-balancing proper:
+ */
+struct rq_iterator {
+ void *arg;
+ struct task_struct *(*start)(void *);
+ struct task_struct *(*next)(void *);
+};
+
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *load_moved,
+ int this_best_prio, int best_prio, int best_prio_seen,
+ struct rq_iterator *iterator);
+
+#include "sched_stats.h"
+#include "sched_rt.c"
+#include "sched_fair.c"
+#include "sched_idletask.c"
+#ifdef CONFIG_SCHED_DEBUG
+# include "sched_debug.c"
+#endif
+
+#define sched_class_highest (&rt_sched_class)
+
+static void set_load_weight(struct task_struct *p)
+{
+ task_rq(p)->cfs.wait_runtime -= p->se.wait_runtime;
+ p->se.wait_runtime = 0;
+
+ if (task_has_rt_policy(p)) {
+ p->se.load.weight = prio_to_weight[0] * 2;
+ p->se.load.inv_weight = prio_to_wmult[0] >> 1;
+ return;
+ }
+
+ /*
+ * SCHED_IDLE tasks get minimal weight:
+ */
+ if (p->policy == SCHED_IDLE) {
+ p->se.load.weight = WEIGHT_IDLEPRIO;
+ p->se.load.inv_weight = WMULT_IDLEPRIO;
+ return;
+ }
+
+ p->se.load.weight = prio_to_weight[p->static_prio - MAX_RT_PRIO];
+ p->se.load.inv_weight = prio_to_wmult[p->static_prio - MAX_RT_PRIO];
+}
+
+static void
+enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+ sched_info_queued(p);
+ p->sched_class->enqueue_task(rq, p, wakeup, now);
+ p->se.on_rq = 1;
+}
+
+static void
+dequeue_task(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+ p->sched_class->dequeue_task(rq, p, sleep, now);
+ p->se.on_rq = 0;
+}
+
+/*
+ * __normal_prio - return the priority that is based on the static prio
+ */
+static inline int __normal_prio(struct task_struct *p)
+{
+ return p->static_prio;
}
/*
@@ -851,7 +871,7 @@ static inline int normal_prio(struct task_struct *p)
{
int prio;
- if (has_rt_policy(p))
+ if (task_has_rt_policy(p))
prio = MAX_RT_PRIO-1 - p->rt_priority;
else
prio = __normal_prio(p);
@@ -879,221 +899,46 @@ static int effective_prio(struct task_struct *p)
}
/*
- * __activate_task - move a task to the runqueue.
- */
-static void __activate_task(struct task_struct *p, struct rq *rq)
-{
- struct prio_array *target = rq->active;
-
- if (batch_task(p))
- target = rq->expired;
- enqueue_task(p, target);
- inc_nr_running(p, rq);
-}
-
-/*
- * __activate_idle_task - move idle task to the _front_ of runqueue.
+ * activate_task - move a task to the runqueue.
*/
-static inline void __activate_idle_task(struct task_struct *p, struct rq *rq)
+static void activate_task(struct rq *rq, struct task_struct *p, int wakeup)
{
- enqueue_task_head(p, rq->active);
- inc_nr_running(p, rq);
-}
+ u64 now = rq_clock(rq);
-/*
- * Recalculate p->normal_prio and p->prio after having slept,
- * updating the sleep-average too:
- */
-static int recalc_task_prio(struct task_struct *p, unsigned long long now)
-{
- /* Caller must always ensure 'now >= p->timestamp' */
- unsigned long sleep_time = now - p->timestamp;
-
- if (batch_task(p))
- sleep_time = 0;
-
- if (likely(sleep_time > 0)) {
- /*
- * This ceiling is set to the lowest priority that would allow
- * a task to be reinserted into the active array on timeslice
- * completion.
- */
- unsigned long ceiling = INTERACTIVE_SLEEP(p);
-
- if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
- /*
- * Prevents user tasks from achieving best priority
- * with one single large enough sleep.
- */
- p->sleep_avg = ceiling;
- /*
- * Using INTERACTIVE_SLEEP() as a ceiling places a
- * nice(0) task 1ms sleep away from promotion, and
- * gives it 700ms to round-robin with no chance of
- * being demoted. This is more than generous, so
- * mark this sleep as non-interactive to prevent the
- * on-runqueue bonus logic from intervening should
- * this task not receive cpu immediately.
- */
- p->sleep_type = SLEEP_NONINTERACTIVE;
- } else {
- /*
- * Tasks waking from uninterruptible sleep are
- * limited in their sleep_avg rise as they
- * are likely to be waiting on I/O
- */
- if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
- if (p->sleep_avg >= ceiling)
- sleep_time = 0;
- else if (p->sleep_avg + sleep_time >=
- ceiling) {
- p->sleep_avg = ceiling;
- sleep_time = 0;
- }
- }
-
- /*
- * This code gives a bonus to interactive tasks.
- *
- * The boost works by updating the 'average sleep time'
- * value here, based on ->timestamp. The more time a
- * task spends sleeping, the higher the average gets -
- * and the higher the priority boost gets as well.
- */
- p->sleep_avg += sleep_time;
-
- }
- if (p->sleep_avg > NS_MAX_SLEEP_AVG)
- p->sleep_avg = NS_MAX_SLEEP_AVG;
- }
+ if (p->state == TASK_UNINTERRUPTIBLE)
+ rq->nr_uninterruptible--;
- return effective_prio(p);
+ enqueue_task(rq, p, wakeup, now);
+ inc_nr_running(p, rq, now);
}
/*
- * activate_task - move a task to the runqueue and do priority recalculation
- *
- * Update all the scheduling statistics stuff. (sleep average
- * calculation, priority modifiers, etc.)
+ * activate_idle_task - move idle task to the _front_ of runqueue.
*/
-static void activate_task(struct task_struct *p, struct rq *rq, int local)
+static inline void activate_idle_task(struct task_struct *p, struct rq *rq)
{
- unsigned long long now;
-
- if (rt_task(p))
- goto out;
-
- now = sched_clock();
-#ifdef CONFIG_SMP
- if (!local) {
- /* Compensate for drifting sched_clock */
- struct rq *this_rq = this_rq();
- now = (now - this_rq->most_recent_timestamp)
- + rq->most_recent_timestamp;
- }
-#endif
+ u64 now = rq_clock(rq);
- /*
- * Sleep time is in units of nanosecs, so shift by 20 to get a
- * milliseconds-range estimation of the amount of time that the task
- * spent sleeping:
- */
- if (unlikely(prof_on == SLEEP_PROFILING)) {
- if (p->state == TASK_UNINTERRUPTIBLE)
- profile_hits(SLEEP_PROFILING, (void *)get_wchan(p),
- (now - p->timestamp) >> 20);
- }
-
- p->prio = recalc_task_prio(p, now);
+ if (p->state == TASK_UNINTERRUPTIBLE)
+ rq->nr_uninterruptible--;
- /*
- * This checks to make sure it's not an uninterruptible task
- * that is now waking up.
- */
- if (p->sleep_type == SLEEP_NORMAL) {
- /*
- * Tasks which were woken up by interrupts (ie. hw events)
- * are most likely of interactive nature. So we give them
- * the credit of extending their sleep time to the period
- * of time they spend on the runqueue, waiting for execution
- * on a CPU, first time around:
- */
- if (in_interrupt())
- p->sleep_type = SLEEP_INTERRUPTED;
- else {
- /*
- * Normal first-time wakeups get a credit too for
- * on-runqueue time, but it will be weighted down:
- */
- p->sleep_type = SLEEP_INTERACTIVE;
- }
- }
- p->timestamp = now;
-out:
- __activate_task(p, rq);
+ enqueue_task(rq, p, 0, now);
+ inc_nr_running(p, rq, now);
}
/*
* deactivate_task - remove a task from the runqueue.
*/
-static void deactivate_task(struct task_struct *p, struct rq *rq)
+static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep)
{
- dec_nr_running(p, rq);
- dequeue_task(p, p->array);
- p->array = NULL;
-}
+ u64 now = rq_clock(rq);
-/*
- * resched_task - mark a task 'to be rescheduled now'.
- *
- * On UP this means the setting of the need_resched flag, on SMP it
- * might also involve a cross-CPU call to trigger the scheduler on
- * the target CPU.
- */
-#ifdef CONFIG_SMP
-
-#ifndef tsk_is_polling
-#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
-#endif
-
-static void resched_task(struct task_struct *p)
-{
- int cpu;
-
- assert_spin_locked(&task_rq(p)->lock);
-
- if (unlikely(test_tsk_thread_flag(p, TIF_NEED_RESCHED)))
- return;
-
- set_tsk_thread_flag(p, TIF_NEED_RESCHED);
-
- cpu = task_cpu(p);
- if (cpu == smp_processor_id())
- return;
-
- /* NEED_RESCHED must be visible before we test polling */
- smp_mb();
- if (!tsk_is_polling(p))
- smp_send_reschedule(cpu);
-}
-
-static void resched_cpu(int cpu)
-{
- struct rq *rq = cpu_rq(cpu);
- unsigned long flags;
+ if (p->state == TASK_UNINTERRUPTIBLE)
+ rq->nr_uninterruptible++;
- if (!spin_trylock_irqsave(&rq->lock, flags))
- return;
- resched_task(cpu_curr(cpu));
- spin_unlock_irqrestore(&rq->lock, flags);
+ dequeue_task(rq, p, sleep, now);
+ dec_nr_running(p, rq, now);
}
-#else
-static inline void resched_task(struct task_struct *p)
-{
- assert_spin_locked(&task_rq(p)->lock);
- set_tsk_need_resched(p);
-}
-#endif
/**
* task_curr - is this task currently executing on a CPU?
@@ -1107,10 +952,42 @@ inline int task_curr(const struct task_struct *p)
/* Used instead of source_load when we know the type == 0 */
unsigned long weighted_cpuload(const int cpu)
{
- return cpu_rq(cpu)->raw_weighted_load;
+ return cpu_rq(cpu)->ls.load.weight;
}
+static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
+{
#ifdef CONFIG_SMP
+ task_thread_info(p)->cpu = cpu;
+ set_task_cfs_rq(p);
+#endif
+}
+
+#ifdef CONFIG_SMP
+
+void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
+{
+ int old_cpu = task_cpu(p);
+ struct rq *old_rq = cpu_rq(old_cpu), *new_rq = cpu_rq(new_cpu);
+ u64 clock_offset, fair_clock_offset;
+
+ clock_offset = old_rq->clock - new_rq->clock;
+ fair_clock_offset = old_rq->cfs.fair_clock -
+ new_rq->cfs.fair_clock;
+ if (p->se.wait_start)
+ p->se.wait_start -= clock_offset;
+ if (p->se.wait_start_fair)
+ p->se.wait_start_fair -= fair_clock_offset;
+ if (p->se.sleep_start)
+ p->se.sleep_start -= clock_offset;
+ if (p->se.block_start)
+ p->se.block_start -= clock_offset;
+ if (p->se.sleep_start_fair)
+ p->se.sleep_start_fair -= fair_clock_offset;
+
+ __set_task_cpu(p, new_cpu);
+}
+
struct migration_req {
struct list_head list;
@@ -1133,7 +1010,7 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
* If the task is not on a runqueue (and not running), then
* it is sufficient to simply update the task's cpu field.
*/
- if (!p->array && !task_running(rq, p)) {
+ if (!p->se.on_rq && !task_running(rq, p)) {
set_task_cpu(p, dest_cpu);
return 0;
}
@@ -1158,22 +1035,72 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
void wait_task_inactive(struct task_struct *p)
{
unsigned long flags;
+ int running, on_rq;
struct rq *rq;
- int preempted;
repeat:
+ /*
+ * We do the initial early heuristics without holding
+ * any task-queue locks at all. We'll only try to get
+ * the runqueue lock when things look like they will
+ * work out!
+ */
+ rq = task_rq(p);
+
+ /*
+ * If the task is actively running on another CPU
+ * still, just relax and busy-wait without holding
+ * any locks.
+ *
+ * NOTE! Since we don't hold any locks, it's not
+ * even sure that "rq" stays as the right runqueue!
+ * But we don't care, since "task_running()" will
+ * return false if the runqueue has changed and p
+ * is actually now running somewhere else!
+ */
+ while (task_running(rq, p))
+ cpu_relax();
+
+ /*
+ * Ok, time to look more closely! We need the rq
+ * lock now, to be *sure*. If we're wrong, we'll
+ * just go back and repeat.
+ */
rq = task_rq_lock(p, &flags);
- /* Must be off runqueue entirely, not preempted. */
- if (unlikely(p->array || task_running(rq, p))) {
- /* If it's preempted, we yield. It could be a while. */
- preempted = !task_running(rq, p);
- task_rq_unlock(rq, &flags);
+ running = task_running(rq, p);
+ on_rq = p->se.on_rq;
+ task_rq_unlock(rq, &flags);
+
+ /*
+ * Was it really running after all now that we
+ * checked with the proper locks actually held?
+ *
+ * Oops. Go back and try again..
+ */
+ if (unlikely(running)) {
cpu_relax();
- if (preempted)
- yield();
goto repeat;
}
- task_rq_unlock(rq, &flags);
+
+ /*
+ * It's not enough that it's not actively running,
+ * it must be off the runqueue _entirely_, and not
+ * preempted!
+ *
+ * So if it wa still runnable (but just not actively
+ * running right now), it's preempted, and we should
+ * yield - it could be a while.
+ */
+ if (unlikely(on_rq)) {
+ yield();
+ goto repeat;
+ }
+
+ /*
+ * Ahh, all good. It wasn't running, and it wasn't
+ * runnable, which means that it will never become
+ * running in the future either. We're all done!
+ */
}
/***
@@ -1210,11 +1137,12 @@ void kick_process(struct task_struct *p)
static inline unsigned long source_load(int cpu, int type)
{
struct rq *rq = cpu_rq(cpu);
+ unsigned long total = weighted_cpuload(cpu);
if (type == 0)
- return rq->raw_weighted_load;
+ return total;
- return min(rq->cpu_load[type-1], rq->raw_weighted_load);
+ return min(rq->cpu_load[type-1], total);
}
/*
@@ -1224,11 +1152,12 @@ static inline unsigned long source_load(int cpu, int type)
static inline unsigned long target_load(int cpu, int type)
{
struct rq *rq = cpu_rq(cpu);
+ unsigned long total = weighted_cpuload(cpu);
if (type == 0)
- return rq->raw_weighted_load;
+ return total;
- return max(rq->cpu_load[type-1], rq->raw_weighted_load);
+ return max(rq->cpu_load[type-1], total);
}
/*
@@ -1237,9 +1166,10 @@ static inline unsigned long target_load(int cpu, int type)
static inline unsigned long cpu_avg_load_per_task(int cpu)
{
struct rq *rq = cpu_rq(cpu);
+ unsigned long total = weighted_cpuload(cpu);
unsigned long n = rq->nr_running;
- return n ? rq->raw_weighted_load / n : SCHED_LOAD_SCALE;
+ return n ? total / n : SCHED_LOAD_SCALE;
}
/*
@@ -1341,9 +1271,9 @@ static int sched_balance_self(int cpu, int flag)
struct sched_domain *tmp, *sd = NULL;
for_each_domain(cpu, tmp) {
- /*
- * If power savings logic is enabled for a domain, stop there.
- */
+ /*
+ * If power savings logic is enabled for a domain, stop there.
+ */
if (tmp->flags & SD_POWERSAVINGS_BALANCE)
break;
if (tmp->flags & flag)
@@ -1426,9 +1356,9 @@ static int wake_idle(int cpu, struct task_struct *p)
if (idle_cpu(i))
return i;
}
- }
- else
+ } else {
break;
+ }
}
return cpu;
}
@@ -1470,7 +1400,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
if (!(old_state & state))
goto out;
- if (p->array)
+ if (p->se.on_rq)
goto out_running;
cpu = task_cpu(p);
@@ -1525,11 +1455,11 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync)
* of the current CPU:
*/
if (sync)
- tl -= current->load_weight;
+ tl -= current->se.load.weight;
if ((tl <= load &&
tl + target_load(cpu, idx) <= tl_per_task) ||
- 100*(tl + p->load_weight) <= imbalance*load) {
+ 100*(tl + p->se.load.weight) <= imbalance*load) {
/*
* This domain has SD_WAKE_AFFINE and
* p is cache cold in this domain, and
@@ -1563,7 +1493,7 @@ out_set_cpu:
old_state = p->state;
if (!(old_state & state))
goto out;
- if (p->array)
+ if (p->se.on_rq)
goto out_running;
this_cpu = smp_processor_id();
@@ -1572,25 +1502,7 @@ out_set_cpu:
out_activate:
#endif /* CONFIG_SMP */
- if (old_state == TASK_UNINTERRUPTIBLE) {
- rq->nr_uninterruptible--;
- /*
- * Tasks on involuntary sleep don't earn
- * sleep_avg beyond just interactive state.
- */
- p->sleep_type = SLEEP_NONINTERACTIVE;
- } else
-
- /*
- * Tasks that have marked their sleep as noninteractive get
- * woken up with their sleep average not weighted in an
- * interactive way.
- */
- if (old_state & TASK_NONINTERACTIVE)
- p->sleep_type = SLEEP_NONINTERACTIVE;
-
-
- activate_task(p, rq, cpu == this_cpu);
+ activate_task(rq, p, 1);
/*
* Sync wakeups (i.e. those types of wakeups where the waker
* has indicated that it will leave the CPU in short order)
@@ -1599,10 +1511,8 @@ out_activate:
* the waker guarantees that the freshly woken up task is going
* to be considered on this CPU.)
*/
- if (!sync || cpu != this_cpu) {
- if (TASK_PREEMPTS_CURR(p, rq))
- resched_task(rq->curr);
- }
+ if (!sync || cpu != this_cpu)
+ check_preempt_curr(rq, p);
success = 1;
out_running:
@@ -1625,19 +1535,36 @@ int fastcall wake_up_state(struct task_struct *p, unsigned int state)
return try_to_wake_up(p, state, 0);
}
-static void task_running_tick(struct rq *rq, struct task_struct *p);
/*
* Perform scheduler related setup for a newly forked process p.
* p is forked by current.
- */
-void fastcall sched_fork(struct task_struct *p, int clone_flags)
-{
- int cpu = get_cpu();
+ *
+ * __sched_fork() is basic setup used by init_idle() too:
+ */
+static void __sched_fork(struct task_struct *p)
+{
+ p->se.wait_start_fair = 0;
+ p->se.wait_start = 0;
+ p->se.exec_start = 0;
+ p->se.sum_exec_runtime = 0;
+ p->se.delta_exec = 0;
+ p->se.delta_fair_run = 0;
+ p->se.delta_fair_sleep = 0;
+ p->se.wait_runtime = 0;
+ p->se.sum_wait_runtime = 0;
+ p->se.sum_sleep_runtime = 0;
+ p->se.sleep_start = 0;
+ p->se.sleep_start_fair = 0;
+ p->se.block_start = 0;
+ p->se.sleep_max = 0;
+ p->se.block_max = 0;
+ p->se.exec_max = 0;
+ p->se.wait_max = 0;
+ p->se.wait_runtime_overruns = 0;
+ p->se.wait_runtime_underruns = 0;
-#ifdef CONFIG_SMP
- cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
-#endif
- set_task_cpu(p, cpu);
+ INIT_LIST_HEAD(&p->run_list);
+ p->se.on_rq = 0;
/*
* We mark the process as running here, but have not actually
@@ -1646,16 +1573,29 @@ void fastcall sched_fork(struct task_struct *p, int clone_flags)
* event cannot wake it up and insert it on the runqueue either.
*/
p->state = TASK_RUNNING;
+}
+
+/*
+ * fork()/clone()-time setup:
+ */
+void sched_fork(struct task_struct *p, int clone_flags)
+{
+ int cpu = get_cpu();
+
+ __sched_fork(p);
+
+#ifdef CONFIG_SMP
+ cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
+#endif
+ __set_task_cpu(p, cpu);
/*
* Make sure we do not leak PI boosting priority to the child:
*/
p->prio = current->normal_prio;
- INIT_LIST_HEAD(&p->run_list);
- p->array = NULL;
#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
- if (unlikely(sched_info_on()))
+ if (likely(sched_info_on()))
memset(&p->sched_info, 0, sizeof(p->sched_info));
#endif
#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
@@ -1665,34 +1605,16 @@ void fastcall sched_fork(struct task_struct *p, int clone_flags)
/* Want to start with kernel preemption disabled. */
task_thread_info(p)->preempt_count = 1;
#endif
- /*
- * Share the timeslice between parent and child, thus the
- * total amount of pending timeslices in the system doesn't change,
- * resulting in more scheduling fairness.
- */
- local_irq_disable();
- p->time_slice = (current->time_slice + 1) >> 1;
- /*
- * The remainder of the first timeslice might be recovered by
- * the parent if the child exits early enough.
- */
- p->first_time_slice = 1;
- current->time_slice >>= 1;
- p->timestamp = sched_clock();
- if (unlikely(!current->time_slice)) {
- /*
- * This case is rare, it happens when the parent has only
- * a single jiffy left from its timeslice. Taking the
- * runqueue lock is not a problem.
- */
- current->time_slice = 1;
- task_running_tick(cpu_rq(cpu), current);
- }
- local_irq_enable();
put_cpu();
}
/*
+ * After fork, child runs first. (default) If set to 0 then
+ * parent will (try to) run first.
+ */
+unsigned int __read_mostly sysctl_sched_child_runs_first = 1;
+
+/*
* wake_up_new_task - wake up a newly created task for the first time.
*
* This function will do some initial scheduler statistics housekeeping
@@ -1701,107 +1623,27 @@ void fastcall sched_fork(struct task_struct *p, int clone_flags)
*/
void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags)
{
- struct rq *rq, *this_rq;
unsigned long flags;
- int this_cpu, cpu;
+ struct rq *rq;
+ int this_cpu;
rq = task_rq_lock(p, &flags);
BUG_ON(p->state != TASK_RUNNING);
- this_cpu = smp_processor_id();
- cpu = task_cpu(p);
-
- /*
- * We decrease the sleep average of forking parents
- * and children as well, to keep max-interactive tasks
- * from forking tasks that are max-interactive. The parent
- * (current) is done further down, under its lock.
- */
- p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
- CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
+ this_cpu = smp_processor_id(); /* parent's CPU */
p->prio = effective_prio(p);
- if (likely(cpu == this_cpu)) {
- if (!(clone_flags & CLONE_VM)) {
- /*
- * The VM isn't cloned, so we're in a good position to
- * do child-runs-first in anticipation of an exec. This
- * usually avoids a lot of COW overhead.
- */
- if (unlikely(!current->array))
- __activate_task(p, rq);
- else {
- p->prio = current->prio;
- p->normal_prio = current->normal_prio;
- list_add_tail(&p->run_list, &current->run_list);
- p->array = current->array;
- p->array->nr_active++;
- inc_nr_running(p, rq);
- }
- set_need_resched();
- } else
- /* Run child last */
- __activate_task(p, rq);
- /*
- * We skip the following code due to cpu == this_cpu
- *
- * task_rq_unlock(rq, &flags);
- * this_rq = task_rq_lock(current, &flags);
- */
- this_rq = rq;
+ if (!sysctl_sched_child_runs_first || (clone_flags & CLONE_VM) ||
+ task_cpu(p) != this_cpu || !current->se.on_rq) {
+ activate_task(rq, p, 0);
} else {
- this_rq = cpu_rq(this_cpu);
-
/*
- * Not the local CPU - must adjust timestamp. This should
- * get optimised away in the !CONFIG_SMP case.
+ * Let the scheduling class do new task startup
+ * management (if any):
*/
- p->timestamp = (p->timestamp - this_rq->most_recent_timestamp)
- + rq->most_recent_timestamp;
- __activate_task(p, rq);
- if (TASK_PREEMPTS_CURR(p, rq))
- resched_task(rq->curr);
-
- /*
- * Parent and child are on different CPUs, now get the
- * parent runqueue to update the parent's ->sleep_avg:
- */
- task_rq_unlock(rq, &flags);
- this_rq = task_rq_lock(current, &flags);
- }
- current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
- PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
- task_rq_unlock(this_rq, &flags);
-}
-
-/*
- * Potentially available exiting-child timeslices are
- * retrieved here - this way the parent does not get
- * penalized for creating too many threads.
- *
- * (this cannot be used to 'generate' timeslices
- * artificially, because any timeslice recovered here
- * was given away by the parent in the first place.)
- */
-void fastcall sched_exit(struct task_struct *p)
-{
- unsigned long flags;
- struct rq *rq;
-
- /*
- * If the child was a (relative-) CPU hog then decrease
- * the sleep_avg of the parent as well.
- */
- rq = task_rq_lock(p->parent, &flags);
- if (p->first_time_slice && task_cpu(p) == task_cpu(p->parent)) {
- p->parent->time_slice += p->time_slice;
- if (unlikely(p->parent->time_slice > task_timeslice(p)))
- p->parent->time_slice = task_timeslice(p);
+ p->sched_class->task_new(rq, p);
}
- if (p->sleep_avg < p->parent->sleep_avg)
- p->parent->sleep_avg = p->parent->sleep_avg /
- (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
- (EXIT_WEIGHT + 1);
+ check_preempt_curr(rq, p);
task_rq_unlock(rq, &flags);
}
@@ -1866,7 +1708,7 @@ static inline void finish_task_switch(struct rq *rq, struct task_struct *prev)
/*
* Remove function-return probe instances associated with this
* task and put them back on the free list.
- */
+ */
kprobe_flush_task(prev);
put_task_struct(prev);
}
@@ -1894,13 +1736,15 @@ asmlinkage void schedule_tail(struct task_struct *prev)
* context_switch - switch to the new MM and the new
* thread's register state.
*/
-static inline struct task_struct *
+static inline void
context_switch(struct rq *rq, struct task_struct *prev,
struct task_struct *next)
{
- struct mm_struct *mm = next->mm;
- struct mm_struct *oldmm = prev->active_mm;
+ struct mm_struct *mm, *oldmm;
+ prepare_task_switch(rq, next);
+ mm = next->mm;
+ oldmm = prev->active_mm;
/*
* For paravirt, this is coupled with an exit in switch_to to
* combine the page table reload and the switch backend into
@@ -1908,16 +1752,15 @@ context_switch(struct rq *rq, struct task_struct *prev,
*/
arch_enter_lazy_cpu_mode();
- if (!mm) {
+ if (unlikely(!mm)) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);
- if (!prev->mm) {
+ if (unlikely(!prev->mm)) {
prev->active_mm = NULL;
- WARN_ON(rq->prev_mm);
rq->prev_mm = oldmm;
}
/*
@@ -1933,7 +1776,13 @@ context_switch(struct rq *rq, struct task_struct *prev,
/* Here we just switch the register state and the stack. */
switch_to(prev, next, prev);
- return prev;
+ barrier();
+ /*
+ * this_rq must be evaluated again because prev may have moved
+ * CPUs since it called schedule(), thus the 'rq' on its stack
+ * frame will be invalid.
+ */
+ finish_task_switch(this_rq(), prev);
}
/*
@@ -2006,17 +1855,65 @@ unsigned long nr_active(void)
return running + uninterruptible;
}
-#ifdef CONFIG_SMP
-
/*
- * Is this task likely cache-hot:
+ * Update rq->cpu_load[] statistics. This function is usually called every
+ * scheduler tick (TICK_NSEC).
*/
-static inline int
-task_hot(struct task_struct *p, unsigned long long now, struct sched_domain *sd)
+static void update_cpu_load(struct rq *this_rq)
{
- return (long long)(now - p->last_ran) < (long long)sd->cache_hot_time;
+ u64 fair_delta64, exec_delta64, idle_delta64, sample_interval64, tmp64;
+ unsigned long total_load = this_rq->ls.load.weight;
+ unsigned long this_load = total_load;
+ struct load_stat *ls = &this_rq->ls;
+ u64 now = __rq_clock(this_rq);
+ int i, scale;
+
+ this_rq->nr_load_updates++;
+ if (unlikely(!(sysctl_sched_features & SCHED_FEAT_PRECISE_CPU_LOAD)))
+ goto do_avg;
+
+ /* Update delta_fair/delta_exec fields first */
+ update_curr_load(this_rq, now);
+
+ fair_delta64 = ls->delta_fair + 1;
+ ls->delta_fair = 0;
+
+ exec_delta64 = ls->delta_exec + 1;
+ ls->delta_exec = 0;
+
+ sample_interval64 = now - ls->load_update_last;
+ ls->load_update_last = now;
+
+ if ((s64)sample_interval64 < (s64)TICK_NSEC)
+ sample_interval64 = TICK_NSEC;
+
+ if (exec_delta64 > sample_interval64)
+ exec_delta64 = sample_interval64;
+
+ idle_delta64 = sample_interval64 - exec_delta64;
+
+ tmp64 = div64_64(SCHED_LOAD_SCALE * exec_delta64, fair_delta64);
+ tmp64 = div64_64(tmp64 * exec_delta64, sample_interval64);
+
+ this_load = (unsigned long)tmp64;
+
+do_avg:
+
+ /* Update our load: */
+ for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
+ unsigned long old_load, new_load;
+
+ /* scale is effectively 1 << i now, and >> i divides by scale */
+
+ old_load = this_rq->cpu_load[i];
+ new_load = this_load;
+
+ this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
+ }
}
+#ifdef CONFIG_SMP
+
/*
* double_rq_lock - safely lock two runqueues
*
@@ -2133,23 +2030,17 @@ void sched_exec(void)
* pull_task - move a task from a remote runqueue to the local runqueue.
* Both runqueues must be locked.
*/
-static void pull_task(struct rq *src_rq, struct prio_array *src_array,
- struct task_struct *p, struct rq *this_rq,
- struct prio_array *this_array, int this_cpu)
+static void pull_task(struct rq *src_rq, struct task_struct *p,
+ struct rq *this_rq, int this_cpu)
{
- dequeue_task(p, src_array);
- dec_nr_running(p, src_rq);
+ deactivate_task(src_rq, p, 0);
set_task_cpu(p, this_cpu);
- inc_nr_running(p, this_rq);
- enqueue_task(p, this_array);
- p->timestamp = (p->timestamp - src_rq->most_recent_timestamp)
- + this_rq->most_recent_timestamp;
+ activate_task(this_rq, p, 0);
/*
* Note that idle threads have a prio of MAX_PRIO, for this test
* to be always true for them.
*/
- if (TASK_PREEMPTS_CURR(p, this_rq))
- resched_task(this_rq->curr);
+ check_preempt_curr(this_rq, p);
}
/*
@@ -2157,7 +2048,7 @@ static void pull_task(struct rq *src_rq, struct prio_array *src_array,
*/
static
int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
- struct sched_domain *sd, enum idle_type idle,
+ struct sched_domain *sd, enum cpu_idle_type idle,
int *all_pinned)
{
/*
@@ -2174,132 +2065,67 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu,
return 0;
/*
- * Aggressive migration if:
- * 1) task is cache cold, or
- * 2) too many balance attempts have failed.
+ * Aggressive migration if too many balance attempts have failed:
*/
-
- if (sd->nr_balance_failed > sd->cache_nice_tries) {
-#ifdef CONFIG_SCHEDSTATS
- if (task_hot(p, rq->most_recent_timestamp, sd))
- schedstat_inc(sd, lb_hot_gained[idle]);
-#endif
+ if (sd->nr_balance_failed > sd->cache_nice_tries)
return 1;
- }
- if (task_hot(p, rq->most_recent_timestamp, sd))
- return 0;
return 1;
}
-#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio)
-
-/*
- * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
- * load from busiest to this_rq, as part of a balancing operation within
- * "domain". Returns the number of tasks moved.
- *
- * Called with both runqueues locked.
- */
-static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
unsigned long max_nr_move, unsigned long max_load_move,
- struct sched_domain *sd, enum idle_type idle,
- int *all_pinned)
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *load_moved,
+ int this_best_prio, int best_prio, int best_prio_seen,
+ struct rq_iterator *iterator)
{
- int idx, pulled = 0, pinned = 0, this_best_prio, best_prio,
- best_prio_seen, skip_for_load;
- struct prio_array *array, *dst_array;
- struct list_head *head, *curr;
- struct task_struct *tmp;
- long rem_load_move;
+ int pulled = 0, pinned = 0, skip_for_load;
+ struct task_struct *p;
+ long rem_load_move = max_load_move;
if (max_nr_move == 0 || max_load_move == 0)
goto out;
- rem_load_move = max_load_move;
pinned = 1;
- this_best_prio = rq_best_prio(this_rq);
- best_prio = rq_best_prio(busiest);
- /*
- * Enable handling of the case where there is more than one task
- * with the best priority. If the current running task is one
- * of those with prio==best_prio we know it won't be moved
- * and therefore it's safe to override the skip (based on load) of
- * any task we find with that prio.
- */
- best_prio_seen = best_prio == busiest->curr->prio;
/*
- * We first consider expired tasks. Those will likely not be
- * executed in the near future, and they are most likely to
- * be cache-cold, thus switching CPUs has the least effect
- * on them.
+ * Start the load-balancing iterator:
*/
- if (busiest->expired->nr_active) {
- array = busiest->expired;
- dst_array = this_rq->expired;
- } else {
- array = busiest->active;
- dst_array = this_rq->active;
- }
-
-new_array:
- /* Start searching at priority 0: */
- idx = 0;
-skip_bitmap:
- if (!idx)
- idx = sched_find_first_bit(array->bitmap);
- else
- idx = find_next_bit(array->bitmap, MAX_PRIO, idx);
- if (idx >= MAX_PRIO) {
- if (array == busiest->expired && busiest->active->nr_active) {
- array = busiest->active;
- dst_array = this_rq->active;
- goto new_array;
- }
+ p = iterator->start(iterator->arg);
+next:
+ if (!p)
goto out;
- }
-
- head = array->queue + idx;
- curr = head->prev;
-skip_queue:
- tmp = list_entry(curr, struct task_struct, run_list);
-
- curr = curr->prev;
-
/*
* To help distribute high priority tasks accross CPUs we don't
* skip a task if it will be the highest priority task (i.e. smallest
* prio value) on its new queue regardless of its load weight
*/
- skip_for_load = tmp->load_weight > rem_load_move;
- if (skip_for_load && idx < this_best_prio)
- skip_for_load = !best_prio_seen && idx == best_prio;
+ skip_for_load = (p->se.load.weight >> 1) > rem_load_move +
+ SCHED_LOAD_SCALE_FUZZ;
+ if (skip_for_load && p->prio < this_best_prio)
+ skip_for_load = !best_prio_seen && p->prio == best_prio;
if (skip_for_load ||
- !can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
+ !can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned)) {
- best_prio_seen |= idx == best_prio;
- if (curr != head)
- goto skip_queue;
- idx++;
- goto skip_bitmap;
+ best_prio_seen |= p->prio == best_prio;
+ p = iterator->next(iterator->arg);
+ goto next;
}
- pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
+ pull_task(busiest, p, this_rq, this_cpu);
pulled++;
- rem_load_move -= tmp->load_weight;
+ rem_load_move -= p->se.load.weight;
/*
* We only want to steal up to the prescribed number of tasks
* and the prescribed amount of weighted load.
*/
if (pulled < max_nr_move && rem_load_move > 0) {
- if (idx < this_best_prio)
- this_best_prio = idx;
- if (curr != head)
- goto skip_queue;
- idx++;
- goto skip_bitmap;
+ if (p->prio < this_best_prio)
+ this_best_prio = p->prio;
+ p = iterator->next(iterator->arg);
+ goto next;
}
out:
/*
@@ -2311,18 +2137,48 @@ out:
if (all_pinned)
*all_pinned = pinned;
+ *load_moved = max_load_move - rem_load_move;
return pulled;
}
/*
+ * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
+ * load from busiest to this_rq, as part of a balancing operation within
+ * "domain". Returns the number of tasks moved.
+ *
+ * Called with both runqueues locked.
+ */
+static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned)
+{
+ struct sched_class *class = sched_class_highest;
+ unsigned long load_moved, total_nr_moved = 0, nr_moved;
+ long rem_load_move = max_load_move;
+
+ do {
+ nr_moved = class->load_balance(this_rq, this_cpu, busiest,
+ max_nr_move, (unsigned long)rem_load_move,
+ sd, idle, all_pinned, &load_moved);
+ total_nr_moved += nr_moved;
+ max_nr_move -= nr_moved;
+ rem_load_move -= load_moved;
+ class = class->next;
+ } while (class && max_nr_move && rem_load_move > 0);
+
+ return total_nr_moved;
+}
+
+/*
* find_busiest_group finds and returns the busiest CPU group within the
* domain. It calculates and returns the amount of weighted load which
* should be moved to restore balance via the imbalance parameter.
*/
static struct sched_group *
find_busiest_group(struct sched_domain *sd, int this_cpu,
- unsigned long *imbalance, enum idle_type idle, int *sd_idle,
- cpumask_t *cpus, int *balance)
+ unsigned long *imbalance, enum cpu_idle_type idle,
+ int *sd_idle, cpumask_t *cpus, int *balance)
{
struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
unsigned long max_load, avg_load, total_load, this_load, total_pwr;
@@ -2340,9 +2196,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
max_load = this_load = total_load = total_pwr = 0;
busiest_load_per_task = busiest_nr_running = 0;
this_load_per_task = this_nr_running = 0;
- if (idle == NOT_IDLE)
+ if (idle == CPU_NOT_IDLE)
load_idx = sd->busy_idx;
- else if (idle == NEWLY_IDLE)
+ else if (idle == CPU_NEWLY_IDLE)
load_idx = sd->newidle_idx;
else
load_idx = sd->idle_idx;
@@ -2386,7 +2242,7 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
avg_load += load;
sum_nr_running += rq->nr_running;
- sum_weighted_load += rq->raw_weighted_load;
+ sum_weighted_load += weighted_cpuload(i);
}
/*
@@ -2426,8 +2282,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
* Busy processors will not participate in power savings
* balance.
*/
- if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
- goto group_next;
+ if (idle == CPU_NOT_IDLE ||
+ !(sd->flags & SD_POWERSAVINGS_BALANCE))
+ goto group_next;
/*
* If the local group is idle or completely loaded
@@ -2437,42 +2294,42 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
!this_nr_running))
power_savings_balance = 0;
- /*
+ /*
* If a group is already running at full capacity or idle,
* don't include that group in power savings calculations
- */
- if (!power_savings_balance || sum_nr_running >= group_capacity
+ */
+ if (!power_savings_balance || sum_nr_running >= group_capacity
|| !sum_nr_running)
- goto group_next;
+ goto group_next;
- /*
+ /*
* Calculate the group which has the least non-idle load.
- * This is the group from where we need to pick up the load
- * for saving power
- */
- if ((sum_nr_running < min_nr_running) ||
- (sum_nr_running == min_nr_running &&
+ * This is the group from where we need to pick up the load
+ * for saving power
+ */
+ if ((sum_nr_running < min_nr_running) ||
+ (sum_nr_running == min_nr_running &&
first_cpu(group->cpumask) <
first_cpu(group_min->cpumask))) {
- group_min = group;
- min_nr_running = sum_nr_running;
+ group_min = group;
+ min_nr_running = sum_nr_running;
min_load_per_task = sum_weighted_load /
sum_nr_running;
- }
+ }
- /*
+ /*
* Calculate the group which is almost near its
- * capacity but still has some space to pick up some load
- * from other group and save more power
- */
- if (sum_nr_running <= group_capacity - 1) {
- if (sum_nr_running > leader_nr_running ||
- (sum_nr_running == leader_nr_running &&
- first_cpu(group->cpumask) >
- first_cpu(group_leader->cpumask))) {
- group_leader = group;
- leader_nr_running = sum_nr_running;
- }
+ * capacity but still has some space to pick up some load
+ * from other group and save more power
+ */
+ if (sum_nr_running <= group_capacity - 1) {
+ if (sum_nr_running > leader_nr_running ||
+ (sum_nr_running == leader_nr_running &&
+ first_cpu(group->cpumask) >
+ first_cpu(group_leader->cpumask))) {
+ group_leader = group;
+ leader_nr_running = sum_nr_running;
+ }
}
group_next:
#endif
@@ -2527,7 +2384,7 @@ group_next:
* a think about bumping its value to force at least one task to be
* moved
*/
- if (*imbalance < busiest_load_per_task) {
+ if (*imbalance + SCHED_LOAD_SCALE_FUZZ < busiest_load_per_task/2) {
unsigned long tmp, pwr_now, pwr_move;
unsigned int imbn;
@@ -2541,7 +2398,8 @@ small_imbalance:
} else
this_load_per_task = SCHED_LOAD_SCALE;
- if (max_load - this_load >= busiest_load_per_task * imbn) {
+ if (max_load - this_load + SCHED_LOAD_SCALE_FUZZ >=
+ busiest_load_per_task * imbn) {
*imbalance = busiest_load_per_task;
return busiest;
}
@@ -2588,7 +2446,7 @@ small_imbalance:
out_balanced:
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
- if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
+ if (idle == CPU_NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
goto ret;
if (this == group_leader && group_leader != group_min) {
@@ -2605,7 +2463,7 @@ ret:
* find_busiest_queue - find the busiest runqueue among the cpus in group.
*/
static struct rq *
-find_busiest_queue(struct sched_group *group, enum idle_type idle,
+find_busiest_queue(struct sched_group *group, enum cpu_idle_type idle,
unsigned long imbalance, cpumask_t *cpus)
{
struct rq *busiest = NULL, *rq;
@@ -2613,17 +2471,19 @@ find_busiest_queue(struct sched_group *group, enum idle_type idle,
int i;
for_each_cpu_mask(i, group->cpumask) {
+ unsigned long wl;
if (!cpu_isset(i, *cpus))
continue;
rq = cpu_rq(i);
+ wl = weighted_cpuload(i);
- if (rq->nr_running == 1 && rq->raw_weighted_load > imbalance)
+ if (rq->nr_running == 1 && wl > imbalance)
continue;
- if (rq->raw_weighted_load > max_load) {
- max_load = rq->raw_weighted_load;
+ if (wl > max_load) {
+ max_load = wl;
busiest = rq;
}
}
@@ -2647,7 +2507,7 @@ static inline unsigned long minus_1_or_zero(unsigned long n)
* tasks if there is an imbalance.
*/
static int load_balance(int this_cpu, struct rq *this_rq,
- struct sched_domain *sd, enum idle_type idle,
+ struct sched_domain *sd, enum cpu_idle_type idle,
int *balance)
{
int nr_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
@@ -2660,10 +2520,10 @@ static int load_balance(int this_cpu, struct rq *this_rq,
/*
* When power savings policy is enabled for the parent domain, idle
* sibling can pick up load irrespective of busy siblings. In this case,
- * let the state of idle sibling percolate up as IDLE, instead of
- * portraying it as NOT_IDLE.
+ * let the state of idle sibling percolate up as CPU_IDLE, instead of
+ * portraying it as CPU_NOT_IDLE.
*/
- if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
+ if (idle != CPU_NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
!test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
sd_idle = 1;
@@ -2797,7 +2657,7 @@ out_one_pinned:
* Check this_cpu to ensure it is balanced within domain. Attempt to move
* tasks if there is an imbalance.
*
- * Called from schedule when this_rq is about to become idle (NEWLY_IDLE).
+ * Called from schedule when this_rq is about to become idle (CPU_NEWLY_IDLE).
* this_rq is locked.
*/
static int
@@ -2814,31 +2674,31 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd)
* When power savings policy is enabled for the parent domain, idle
* sibling can pick up load irrespective of busy siblings. In this case,
* let the state of idle sibling percolate up as IDLE, instead of
- * portraying it as NOT_IDLE.
+ * portraying it as CPU_NOT_IDLE.
*/
if (sd->flags & SD_SHARE_CPUPOWER &&
!test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
sd_idle = 1;
- schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_cnt[CPU_NEWLY_IDLE]);
redo:
- group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE,
+ group = find_busiest_group(sd, this_cpu, &imbalance, CPU_NEWLY_IDLE,
&sd_idle, &cpus, NULL);
if (!group) {
- schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_nobusyg[CPU_NEWLY_IDLE]);
goto out_balanced;
}
- busiest = find_busiest_queue(group, NEWLY_IDLE, imbalance,
+ busiest = find_busiest_queue(group, CPU_NEWLY_IDLE, imbalance,
&cpus);
if (!busiest) {
- schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_nobusyq[CPU_NEWLY_IDLE]);
goto out_balanced;
}
BUG_ON(busiest == this_rq);
- schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
+ schedstat_add(sd, lb_imbalance[CPU_NEWLY_IDLE], imbalance);
nr_moved = 0;
if (busiest->nr_running > 1) {
@@ -2846,7 +2706,7 @@ redo:
double_lock_balance(this_rq, busiest);
nr_moved = move_tasks(this_rq, this_cpu, busiest,
minus_1_or_zero(busiest->nr_running),
- imbalance, sd, NEWLY_IDLE, NULL);
+ imbalance, sd, CPU_NEWLY_IDLE, NULL);
spin_unlock(&busiest->lock);
if (!nr_moved) {
@@ -2857,7 +2717,7 @@ redo:
}
if (!nr_moved) {
- schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_failed[CPU_NEWLY_IDLE]);
if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
!test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
return -1;
@@ -2867,7 +2727,7 @@ redo:
return nr_moved;
out_balanced:
- schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+ schedstat_inc(sd, lb_balanced[CPU_NEWLY_IDLE]);
if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
!test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
return -1;
@@ -2883,28 +2743,33 @@ out_balanced:
static void idle_balance(int this_cpu, struct rq *this_rq)
{
struct sched_domain *sd;
- int pulled_task = 0;
- unsigned long next_balance = jiffies + 60 * HZ;
+ int pulled_task = -1;
+ unsigned long next_balance = jiffies + HZ;
for_each_domain(this_cpu, sd) {
- if (sd->flags & SD_BALANCE_NEWIDLE) {
+ unsigned long interval;
+
+ if (!(sd->flags & SD_LOAD_BALANCE))
+ continue;
+
+ if (sd->flags & SD_BALANCE_NEWIDLE)
/* If we've pulled tasks over stop searching: */
pulled_task = load_balance_newidle(this_cpu,
- this_rq, sd);
- if (time_after(next_balance,
- sd->last_balance + sd->balance_interval))
- next_balance = sd->last_balance
- + sd->balance_interval;
- if (pulled_task)
- break;
- }
+ this_rq, sd);
+
+ interval = msecs_to_jiffies(sd->balance_interval);
+ if (time_after(next_balance, sd->last_balance + interval))
+ next_balance = sd->last_balance + interval;
+ if (pulled_task)
+ break;
}
- if (!pulled_task)
+ if (pulled_task || time_after(jiffies, this_rq->next_balance)) {
/*
* We are going idle. next_balance may be set based on
* a busy processor. So reset next_balance.
*/
this_rq->next_balance = next_balance;
+ }
}
/*
@@ -2948,7 +2813,7 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu)
schedstat_inc(sd, alb_cnt);
if (move_tasks(target_rq, target_cpu, busiest_rq, 1,
- RTPRIO_TO_LOAD_WEIGHT(100), sd, SCHED_IDLE,
+ RTPRIO_TO_LOAD_WEIGHT(100), sd, CPU_IDLE,
NULL))
schedstat_inc(sd, alb_pushed);
else
@@ -2957,32 +2822,6 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu)
spin_unlock(&target_rq->lock);
}
-static void update_load(struct rq *this_rq)
-{
- unsigned long this_load;
- unsigned int i, scale;
-
- this_load = this_rq->raw_weighted_load;
-
- /* Update our load: */
- for (i = 0, scale = 1; i < 3; i++, scale += scale) {
- unsigned long old_load, new_load;
-
- /* scale is effectively 1 << i now, and >> i divides by scale */
-
- old_load = this_rq->cpu_load[i];
- new_load = this_load;
- /*
- * Round up the averaging division if load is increasing. This
- * prevents us from getting stuck on 9 if the load is 10, for
- * example.
- */
- if (new_load > old_load)
- new_load += scale-1;
- this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
- }
-}
-
#ifdef CONFIG_NO_HZ
static struct {
atomic_t load_balancer;
@@ -3065,7 +2904,7 @@ static DEFINE_SPINLOCK(balancing);
*
* Balancing parameters are set up in arch_init_sched_domains.
*/
-static inline void rebalance_domains(int cpu, enum idle_type idle)
+static inline void rebalance_domains(int cpu, enum cpu_idle_type idle)
{
int balance = 1;
struct rq *rq = cpu_rq(cpu);
@@ -3079,13 +2918,16 @@ static inline void rebalance_domains(int cpu, enum idle_type idle)
continue;
interval = sd->balance_interval;
- if (idle != SCHED_IDLE)
+ if (idle != CPU_IDLE)
interval *= sd->busy_factor;
/* scale ms to jiffies */
interval = msecs_to_jiffies(interval);
if (unlikely(!interval))
interval = 1;
+ if (interval > HZ*NR_CPUS/10)
+ interval = HZ*NR_CPUS/10;
+
if (sd->flags & SD_SERIALIZE) {
if (!spin_trylock(&balancing))
@@ -3099,7 +2941,7 @@ static inline void rebalance_domains(int cpu, enum idle_type idle)
* longer idle, or one of our SMT siblings is
* not idle.
*/
- idle = NOT_IDLE;
+ idle = CPU_NOT_IDLE;
}
sd->last_balance = jiffies;
}
@@ -3127,11 +2969,12 @@ out:
*/
static void run_rebalance_domains(struct softirq_action *h)
{
- int local_cpu = smp_processor_id();
- struct rq *local_rq = cpu_rq(local_cpu);
- enum idle_type idle = local_rq->idle_at_tick ? SCHED_IDLE : NOT_IDLE;
+ int this_cpu = smp_processor_id();
+ struct rq *this_rq = cpu_rq(this_cpu);
+ enum cpu_idle_type idle = this_rq->idle_at_tick ?
+ CPU_IDLE : CPU_NOT_IDLE;
- rebalance_domains(local_cpu, idle);
+ rebalance_domains(this_cpu, idle);
#ifdef CONFIG_NO_HZ
/*
@@ -3139,13 +2982,13 @@ static void run_rebalance_domains(struct softirq_action *h)
* balancing on behalf of the other idle cpus whose ticks are
* stopped.
*/
- if (local_rq->idle_at_tick &&
- atomic_read(&nohz.load_balancer) == local_cpu) {
+ if (this_rq->idle_at_tick &&
+ atomic_read(&nohz.load_balancer) == this_cpu) {
cpumask_t cpus = nohz.cpu_mask;
struct rq *rq;
int balance_cpu;
- cpu_clear(local_cpu, cpus);
+ cpu_clear(this_cpu, cpus);
for_each_cpu_mask(balance_cpu, cpus) {
/*
* If this cpu gets work to do, stop the load balancing
@@ -3158,8 +3001,8 @@ static void run_rebalance_domains(struct softirq_action *h)
rebalance_domains(balance_cpu, SCHED_IDLE);
rq = cpu_rq(balance_cpu);
- if (time_after(local_rq->next_balance, rq->next_balance))
- local_rq->next_balance = rq->next_balance;
+ if (time_after(this_rq->next_balance, rq->next_balance))
+ this_rq->next_balance = rq->next_balance;
}
}
#endif
@@ -3172,9 +3015,8 @@ static void run_rebalance_domains(struct softirq_action *h)
* idle load balancing owner or decide to stop the periodic load balancing,
* if the whole system is idle.
*/
-static inline void trigger_load_balance(int cpu)
+static inline void trigger_load_balance(struct rq *rq, int cpu)
{
- struct rq *rq = cpu_rq(cpu);
#ifdef CONFIG_NO_HZ
/*
* If we were in the nohz mode recently and busy at the current
@@ -3226,13 +3068,29 @@ static inline void trigger_load_balance(int cpu)
if (time_after_eq(jiffies, rq->next_balance))
raise_softirq(SCHED_SOFTIRQ);
}
-#else
+
+#else /* CONFIG_SMP */
+
/*
* on UP we do not need to balance between CPUs:
*/
static inline void idle_balance(int cpu, struct rq *rq)
{
}
+
+/* Avoid "used but not defined" warning on UP */
+static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *load_moved,
+ int this_best_prio, int best_prio, int best_prio_seen,
+ struct rq_iterator *iterator)
+{
+ *load_moved = 0;
+
+ return 0;
+}
+
#endif
DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -3240,54 +3098,28 @@ DEFINE_PER_CPU(struct kernel_stat, kstat);
EXPORT_PER_CPU_SYMBOL(kstat);
/*
- * This is called on clock ticks and on context switches.
- * Bank in p->sched_time the ns elapsed since the last tick or switch.
+ * Return p->sum_exec_runtime plus any more ns on the sched_clock
+ * that have not yet been banked in case the task is currently running.
*/
-static inline void
-update_cpu_clock(struct task_struct *p, struct rq *rq, unsigned long long now)
-{
- p->sched_time += now - p->last_ran;
- p->last_ran = rq->most_recent_timestamp = now;
-}
-
-/*
- * Return current->sched_time plus any more ns on the sched_clock
- * that have not yet been banked.
- */
-unsigned long long current_sched_time(const struct task_struct *p)
+unsigned long long task_sched_runtime(struct task_struct *p)
{
- unsigned long long ns;
unsigned long flags;
+ u64 ns, delta_exec;
+ struct rq *rq;
- local_irq_save(flags);
- ns = p->sched_time + sched_clock() - p->last_ran;
- local_irq_restore(flags);
+ rq = task_rq_lock(p, &flags);
+ ns = p->se.sum_exec_runtime;
+ if (rq->curr == p) {
+ delta_exec = rq_clock(rq) - p->se.exec_start;
+ if ((s64)delta_exec > 0)
+ ns += delta_exec;
+ }
+ task_rq_unlock(rq, &flags);
return ns;
}
/*
- * We place interactive tasks back into the active array, if possible.
- *
- * To guarantee that this does not starve expired tasks we ignore the
- * interactivity of a task if the first expired task had to wait more
- * than a 'reasonable' amount of time. This deadline timeout is
- * load-dependent, as the frequency of array switched decreases with
- * increasing number of running tasks. We also ignore the interactivity
- * if a better static_prio task has expired:
- */
-static inline int expired_starving(struct rq *rq)
-{
- if (rq->curr->static_prio > rq->best_expired_prio)
- return 1;
- if (!STARVATION_LIMIT || !rq->expired_timestamp)
- return 0;
- if (jiffies - rq->expired_timestamp > STARVATION_LIMIT * rq->nr_running)
- return 1;
- return 0;
-}
-
-/*
* Account user cpu time to a process.
* @p: the process that the cpu time gets accounted to
* @hardirq_offset: the offset to subtract from hardirq_count()
@@ -3360,81 +3192,6 @@ void account_steal_time(struct task_struct *p, cputime_t steal)
cpustat->steal = cputime64_add(cpustat->steal, tmp);
}
-static void task_running_tick(struct rq *rq, struct task_struct *p)
-{
- if (p->array != rq->active) {
- /* Task has expired but was not scheduled yet */
- set_tsk_need_resched(p);
- return;
- }
- spin_lock(&rq->lock);
- /*
- * The task was running during this tick - update the
- * time slice counter. Note: we do not update a thread's
- * priority until it either goes to sleep or uses up its
- * timeslice. This makes it possible for interactive tasks
- * to use up their timeslices at their highest priority levels.
- */
- if (rt_task(p)) {
- /*
- * RR tasks need a special form of timeslice management.
- * FIFO tasks have no timeslices.
- */
- if ((p->policy == SCHED_RR) && !--p->time_slice) {
- p->time_slice = task_timeslice(p);
- p->first_time_slice = 0;
- set_tsk_need_resched(p);
-
- /* put it at the end of the queue: */
- requeue_task(p, rq->active);
- }
- goto out_unlock;
- }
- if (!--p->time_slice) {
- dequeue_task(p, rq->active);
- set_tsk_need_resched(p);
- p->prio = effective_prio(p);
- p->time_slice = task_timeslice(p);
- p->first_time_slice = 0;
-
- if (!rq->expired_timestamp)
- rq->expired_timestamp = jiffies;
- if (!TASK_INTERACTIVE(p) || expired_starving(rq)) {
- enqueue_task(p, rq->expired);
- if (p->static_prio < rq->best_expired_prio)
- rq->best_expired_prio = p->static_prio;
- } else
- enqueue_task(p, rq->active);
- } else {
- /*
- * Prevent a too long timeslice allowing a task to monopolize
- * the CPU. We do this by splitting up the timeslice into
- * smaller pieces.
- *
- * Note: this does not mean the task's timeslices expire or
- * get lost in any way, they just might be preempted by
- * another task of equal priority. (one with higher
- * priority would have preempted this task already.) We
- * requeue this task to the end of the list on this priority
- * level, which is in essence a round-robin of tasks with
- * equal priority.
- *
- * This only applies to tasks in the interactive
- * delta range with at least TIMESLICE_GRANULARITY to requeue.
- */
- if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
- p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
- (p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
- (p->array == rq->active)) {
-
- requeue_task(p, rq->active);
- set_tsk_need_resched(p);
- }
- }
-out_unlock:
- spin_unlock(&rq->lock);
-}
-
/*
* This function gets called by the timer code, with HZ frequency.
* We call it with interrupts disabled.
@@ -3444,20 +3201,19 @@ out_unlock:
*/
void scheduler_tick(void)
{
- unsigned long long now = sched_clock();
- struct task_struct *p = current;
int cpu = smp_processor_id();
- int idle_at_tick = idle_cpu(cpu);
struct rq *rq = cpu_rq(cpu);
+ struct task_struct *curr = rq->curr;
- update_cpu_clock(p, rq, now);
+ spin_lock(&rq->lock);
+ if (curr != rq->idle) /* FIXME: needed? */
+ curr->sched_class->task_tick(rq, curr);
+ update_cpu_load(rq);
+ spin_unlock(&rq->lock);
- if (!idle_at_tick)
- task_running_tick(rq, p);
#ifdef CONFIG_SMP
- update_load(rq);
- rq->idle_at_tick = idle_at_tick;
- trigger_load_balance(cpu);
+ rq->idle_at_tick = idle_cpu(cpu);
+ trigger_load_balance(rq, cpu);
#endif
}
@@ -3499,170 +3255,129 @@ EXPORT_SYMBOL(sub_preempt_count);
#endif
-static inline int interactive_sleep(enum sleep_type sleep_type)
+/*
+ * Print scheduling while atomic bug:
+ */
+static noinline void __schedule_bug(struct task_struct *prev)
{
- return (sleep_type == SLEEP_INTERACTIVE ||
- sleep_type == SLEEP_INTERRUPTED);
+ printk(KERN_ERR "BUG: scheduling while atomic: %s/0x%08x/%d\n",
+ prev->comm, preempt_count(), prev->pid);
+ debug_show_held_locks(prev);
+ if (irqs_disabled())
+ print_irqtrace_events(prev);
+ dump_stack();
}
/*
- * schedule() is the main scheduler function.
+ * Various schedule()-time debugging checks and statistics:
*/
-asmlinkage void __sched schedule(void)
+static inline void schedule_debug(struct task_struct *prev)
{
- struct task_struct *prev, *next;
- struct prio_array *array;
- struct list_head *queue;
- unsigned long long now;
- unsigned long run_time;
- int cpu, idx, new_prio;
- long *switch_count;
- struct rq *rq;
-
/*
* Test if we are atomic. Since do_exit() needs to call into
* schedule() atomically, we ignore that path for now.
* Otherwise, whine if we are scheduling when we should not be.
*/
- if (unlikely(in_atomic() && !current->exit_state)) {
- printk(KERN_ERR "BUG: scheduling while atomic: "
- "%s/0x%08x/%d\n",
- current->comm, preempt_count(), current->pid);
- debug_show_held_locks(current);
- if (irqs_disabled())
- print_irqtrace_events(current);
- dump_stack();
- }
- profile_hit(SCHED_PROFILING, __builtin_return_address(0));
+ if (unlikely(in_atomic_preempt_off()) && unlikely(!prev->exit_state))
+ __schedule_bug(prev);
-need_resched:
- preempt_disable();
- prev = current;
- release_kernel_lock(prev);
-need_resched_nonpreemptible:
- rq = this_rq();
+ profile_hit(SCHED_PROFILING, __builtin_return_address(0));
- /*
- * The idle thread is not allowed to schedule!
- * Remove this check after it has been exercised a bit.
- */
- if (unlikely(prev == rq->idle) && prev->state != TASK_RUNNING) {
- printk(KERN_ERR "bad: scheduling from the idle thread!\n");
- dump_stack();
- }
+ schedstat_inc(this_rq(), sched_cnt);
+}
- schedstat_inc(rq, sched_cnt);
- now = sched_clock();
- if (likely((long long)(now - prev->timestamp) < NS_MAX_SLEEP_AVG)) {
- run_time = now - prev->timestamp;
- if (unlikely((long long)(now - prev->timestamp) < 0))
- run_time = 0;
- } else
- run_time = NS_MAX_SLEEP_AVG;
+/*
+ * Pick up the highest-prio task:
+ */
+static inline struct task_struct *
+pick_next_task(struct rq *rq, struct task_struct *prev, u64 now)
+{
+ struct sched_class *class;
+ struct task_struct *p;
/*
- * Tasks charged proportionately less run_time at high sleep_avg to
- * delay them losing their interactive status
+ * Optimization: we know that if all tasks are in
+ * the fair class we can call that function directly:
*/
- run_time /= (CURRENT_BONUS(prev) ? : 1);
-
- spin_lock_irq(&rq->lock);
-
- switch_count = &prev->nivcsw;
- if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
- switch_count = &prev->nvcsw;
- if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
- unlikely(signal_pending(prev))))
- prev->state = TASK_RUNNING;
- else {
- if (prev->state == TASK_UNINTERRUPTIBLE)
- rq->nr_uninterruptible++;
- deactivate_task(prev, rq);
- }
+ if (likely(rq->nr_running == rq->cfs.nr_running)) {
+ p = fair_sched_class.pick_next_task(rq, now);
+ if (likely(p))
+ return p;
}
- cpu = smp_processor_id();
- if (unlikely(!rq->nr_running)) {
- idle_balance(cpu, rq);
- if (!rq->nr_running) {
- next = rq->idle;
- rq->expired_timestamp = 0;
- goto switch_tasks;
- }
- }
-
- array = rq->active;
- if (unlikely(!array->nr_active)) {
+ class = sched_class_highest;
+ for ( ; ; ) {
+ p = class->pick_next_task(rq, now);
+ if (p)
+ return p;
/*
- * Switch the active and expired arrays.
+ * Will never be NULL as the idle class always
+ * returns a non-NULL p:
*/
- schedstat_inc(rq, sched_switch);
- rq->active = rq->expired;
- rq->expired = array;
- array = rq->active;
- rq->expired_timestamp = 0;
- rq->best_expired_prio = MAX_PRIO;
+ class = class->next;
}
+}
+
+/*
+ * schedule() is the main scheduler function.
+ */
+asmlinkage void __sched schedule(void)
+{
+ struct task_struct *prev, *next;
+ long *switch_count;
+ struct rq *rq;
+ u64 now;
+ int cpu;
- idx = sched_find_first_bit(array->bitmap);
- queue = array->queue + idx;
- next = list_entry(queue->next, struct task_struct, run_list);
+need_resched:
+ preempt_disable();
+ cpu = smp_processor_id();
+ rq = cpu_rq(cpu);
+ rcu_qsctr_inc(cpu);
+ prev = rq->curr;
+ switch_count = &prev->nivcsw;
- if (!rt_task(next) && interactive_sleep(next->sleep_type)) {
- unsigned long long delta = now - next->timestamp;
- if (unlikely((long long)(now - next->timestamp) < 0))
- delta = 0;
+ release_kernel_lock(prev);
+need_resched_nonpreemptible:
- if (next->sleep_type == SLEEP_INTERACTIVE)
- delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
+ schedule_debug(prev);
- array = next->array;
- new_prio = recalc_task_prio(next, next->timestamp + delta);
+ spin_lock_irq(&rq->lock);
+ clear_tsk_need_resched(prev);
- if (unlikely(next->prio != new_prio)) {
- dequeue_task(next, array);
- next->prio = new_prio;
- enqueue_task(next, array);
+ if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
+ if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
+ unlikely(signal_pending(prev)))) {
+ prev->state = TASK_RUNNING;
+ } else {
+ deactivate_task(rq, prev, 1);
}
+ switch_count = &prev->nvcsw;
}
- next->sleep_type = SLEEP_NORMAL;
-switch_tasks:
- if (next == rq->idle)
- schedstat_inc(rq, sched_goidle);
- prefetch(next);
- prefetch_stack(next);
- clear_tsk_need_resched(prev);
- rcu_qsctr_inc(task_cpu(prev));
- update_cpu_clock(prev, rq, now);
+ if (unlikely(!rq->nr_running))
+ idle_balance(cpu, rq);
- prev->sleep_avg -= run_time;
- if ((long)prev->sleep_avg <= 0)
- prev->sleep_avg = 0;
- prev->timestamp = prev->last_ran = now;
+ now = __rq_clock(rq);
+ prev->sched_class->put_prev_task(rq, prev, now);
+ next = pick_next_task(rq, prev, now);
sched_info_switch(prev, next);
+
if (likely(prev != next)) {
- next->timestamp = next->last_ran = now;
rq->nr_switches++;
rq->curr = next;
++*switch_count;
- prepare_task_switch(rq, next);
- prev = context_switch(rq, prev, next);
- barrier();
- /*
- * this_rq must be evaluated again because prev may have moved
- * CPUs since it called schedule(), thus the 'rq' on its stack
- * frame will be invalid.
- */
- finish_task_switch(this_rq(), prev);
+ context_switch(rq, prev, next); /* unlocks the rq */
} else
spin_unlock_irq(&rq->lock);
- prev = current;
- if (unlikely(reacquire_kernel_lock(prev) < 0))
+ if (unlikely(reacquire_kernel_lock(current) < 0)) {
+ cpu = smp_processor_id();
+ rq = cpu_rq(cpu);
goto need_resched_nonpreemptible;
+ }
preempt_enable_no_resched();
if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
goto need_resched;
@@ -3990,74 +3705,85 @@ out:
}
EXPORT_SYMBOL(wait_for_completion_interruptible_timeout);
-
-#define SLEEP_ON_VAR \
- unsigned long flags; \
- wait_queue_t wait; \
- init_waitqueue_entry(&wait, current);
-
-#define SLEEP_ON_HEAD \
- spin_lock_irqsave(&q->lock,flags); \
- __add_wait_queue(q, &wait); \
+static inline void
+sleep_on_head(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags)
+{
+ spin_lock_irqsave(&q->lock, *flags);
+ __add_wait_queue(q, wait);
spin_unlock(&q->lock);
+}
-#define SLEEP_ON_TAIL \
- spin_lock_irq(&q->lock); \
- __remove_wait_queue(q, &wait); \
- spin_unlock_irqrestore(&q->lock, flags);
+static inline void
+sleep_on_tail(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags)
+{
+ spin_lock_irq(&q->lock);
+ __remove_wait_queue(q, wait);
+ spin_unlock_irqrestore(&q->lock, *flags);
+}
-void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
+void __sched interruptible_sleep_on(wait_queue_head_t *q)
{
- SLEEP_ON_VAR
+ unsigned long flags;
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
current->state = TASK_INTERRUPTIBLE;
- SLEEP_ON_HEAD
+ sleep_on_head(q, &wait, &flags);
schedule();
- SLEEP_ON_TAIL
+ sleep_on_tail(q, &wait, &flags);
}
EXPORT_SYMBOL(interruptible_sleep_on);
-long fastcall __sched
+long __sched
interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
{
- SLEEP_ON_VAR
+ unsigned long flags;
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
current->state = TASK_INTERRUPTIBLE;
- SLEEP_ON_HEAD
+ sleep_on_head(q, &wait, &flags);
timeout = schedule_timeout(timeout);
- SLEEP_ON_TAIL
+ sleep_on_tail(q, &wait, &flags);
return timeout;
}
EXPORT_SYMBOL(interruptible_sleep_on_timeout);
-void fastcall __sched sleep_on(wait_queue_head_t *q)
+void __sched sleep_on(wait_queue_head_t *q)
{
- SLEEP_ON_VAR
+ unsigned long flags;
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
current->state = TASK_UNINTERRUPTIBLE;
- SLEEP_ON_HEAD
+ sleep_on_head(q, &wait, &flags);
schedule();
- SLEEP_ON_TAIL
+ sleep_on_tail(q, &wait, &flags);
}
EXPORT_SYMBOL(sleep_on);
-long fastcall __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
{
- SLEEP_ON_VAR
+ unsigned long flags;
+ wait_queue_t wait;
+
+ init_waitqueue_entry(&wait, current);
current->state = TASK_UNINTERRUPTIBLE;
- SLEEP_ON_HEAD
+ sleep_on_head(q, &wait, &flags);
timeout = schedule_timeout(timeout);
- SLEEP_ON_TAIL
+ sleep_on_tail(q, &wait, &flags);
return timeout;
}
-
EXPORT_SYMBOL(sleep_on_timeout);
#ifdef CONFIG_RT_MUTEXES
@@ -4074,29 +3800,30 @@ EXPORT_SYMBOL(sleep_on_timeout);
*/
void rt_mutex_setprio(struct task_struct *p, int prio)
{
- struct prio_array *array;
unsigned long flags;
+ int oldprio, on_rq;
struct rq *rq;
- int oldprio;
+ u64 now;
BUG_ON(prio < 0 || prio > MAX_PRIO);
rq = task_rq_lock(p, &flags);
+ now = rq_clock(rq);
oldprio = p->prio;
- array = p->array;
- if (array)
- dequeue_task(p, array);
+ on_rq = p->se.on_rq;
+ if (on_rq)
+ dequeue_task(rq, p, 0, now);
+
+ if (rt_prio(prio))
+ p->sched_class = &rt_sched_class;
+ else
+ p->sched_class = &fair_sched_class;
+
p->prio = prio;
- if (array) {
- /*
- * If changing to an RT priority then queue it
- * in the active array!
- */
- if (rt_task(p))
- array = rq->active;
- enqueue_task(p, array);
+ if (on_rq) {
+ enqueue_task(rq, p, 0, now);
/*
* Reschedule if we are currently running on this runqueue and
* our priority decreased, or if we are not currently running on
@@ -4105,8 +3832,9 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
if (task_running(rq, p)) {
if (p->prio > oldprio)
resched_task(rq->curr);
- } else if (TASK_PREEMPTS_CURR(p, rq))
- resched_task(rq->curr);
+ } else {
+ check_preempt_curr(rq, p);
+ }
}
task_rq_unlock(rq, &flags);
}
@@ -4115,10 +3843,10 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
void set_user_nice(struct task_struct *p, long nice)
{
- struct prio_array *array;
- int old_prio, delta;
+ int old_prio, delta, on_rq;
unsigned long flags;
struct rq *rq;
+ u64 now;
if (TASK_NICE(p) == nice || nice < -20 || nice > 19)
return;
@@ -4127,20 +3855,21 @@ void set_user_nice(struct task_struct *p, long nice)
* the task might be in the middle of scheduling on another CPU.
*/
rq = task_rq_lock(p, &flags);
+ now = rq_clock(rq);
/*
* The RT priorities are set via sched_setscheduler(), but we still
* allow the 'normal' nice value to be set - but as expected
* it wont have any effect on scheduling until the task is
- * not SCHED_NORMAL/SCHED_BATCH:
+ * SCHED_FIFO/SCHED_RR:
*/
- if (has_rt_policy(p)) {
+ if (task_has_rt_policy(p)) {
p->static_prio = NICE_TO_PRIO(nice);
goto out_unlock;
}
- array = p->array;
- if (array) {
- dequeue_task(p, array);
- dec_raw_weighted_load(rq, p);
+ on_rq = p->se.on_rq;
+ if (on_rq) {
+ dequeue_task(rq, p, 0, now);
+ dec_load(rq, p, now);
}
p->static_prio = NICE_TO_PRIO(nice);
@@ -4149,9 +3878,9 @@ void set_user_nice(struct task_struct *p, long nice)
p->prio = effective_prio(p);
delta = p->prio - old_prio;
- if (array) {
- enqueue_task(p, array);
- inc_raw_weighted_load(rq, p);
+ if (on_rq) {
+ enqueue_task(rq, p, 0, now);
+ inc_load(rq, p, now);
/*
* If the task increased its priority or is running and
* lowered its priority, then reschedule its CPU:
@@ -4271,20 +4000,28 @@ static inline struct task_struct *find_process_by_pid(pid_t pid)
}
/* Actually do priority change: must hold rq lock. */
-static void __setscheduler(struct task_struct *p, int policy, int prio)
+static void
+__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
{
- BUG_ON(p->array);
+ BUG_ON(p->se.on_rq);
p->policy = policy;
+ switch (p->policy) {
+ case SCHED_NORMAL:
+ case SCHED_BATCH:
+ case SCHED_IDLE:
+ p->sched_class = &fair_sched_class;
+ break;
+ case SCHED_FIFO:
+ case SCHED_RR:
+ p->sched_class = &rt_sched_class;
+ break;
+ }
+
p->rt_priority = prio;
p->normal_prio = normal_prio(p);
/* we are holding p->pi_lock already */
p->prio = rt_mutex_getprio(p);
- /*
- * SCHED_BATCH tasks are treated as perpetual CPU hogs:
- */
- if (policy == SCHED_BATCH)
- p->sleep_avg = 0;
set_load_weight(p);
}
@@ -4299,8 +4036,7 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
int sched_setscheduler(struct task_struct *p, int policy,
struct sched_param *param)
{
- int retval, oldprio, oldpolicy = -1;
- struct prio_array *array;
+ int retval, oldprio, oldpolicy = -1, on_rq;
unsigned long flags;
struct rq *rq;
@@ -4311,27 +4047,27 @@ recheck:
if (policy < 0)
policy = oldpolicy = p->policy;
else if (policy != SCHED_FIFO && policy != SCHED_RR &&
- policy != SCHED_NORMAL && policy != SCHED_BATCH)
+ policy != SCHED_NORMAL && policy != SCHED_BATCH &&
+ policy != SCHED_IDLE)
return -EINVAL;
/*
* Valid priorities for SCHED_FIFO and SCHED_RR are
- * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and
- * SCHED_BATCH is 0.
+ * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL,
+ * SCHED_BATCH and SCHED_IDLE is 0.
*/
if (param->sched_priority < 0 ||
(p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) ||
(!p->mm && param->sched_priority > MAX_RT_PRIO-1))
return -EINVAL;
- if (is_rt_policy(policy) != (param->sched_priority != 0))
+ if (rt_policy(policy) != (param->sched_priority != 0))
return -EINVAL;
/*
* Allow unprivileged RT tasks to decrease priority:
*/
if (!capable(CAP_SYS_NICE)) {
- if (is_rt_policy(policy)) {
+ if (rt_policy(policy)) {
unsigned long rlim_rtprio;
- unsigned long flags;
if (!lock_task_sighand(p, &flags))
return -ESRCH;
@@ -4347,6 +4083,12 @@ recheck:
param->sched_priority > rlim_rtprio)
return -EPERM;
}
+ /*
+ * Like positive nice levels, dont allow tasks to
+ * move out of SCHED_IDLE either:
+ */
+ if (p->policy == SCHED_IDLE && policy != SCHED_IDLE)
+ return -EPERM;
/* can't change other user's priorities */
if ((current->euid != p->euid) &&
@@ -4374,13 +4116,13 @@ recheck:
spin_unlock_irqrestore(&p->pi_lock, flags);
goto recheck;
}
- array = p->array;
- if (array)
- deactivate_task(p, rq);
+ on_rq = p->se.on_rq;
+ if (on_rq)
+ deactivate_task(rq, p, 0);
oldprio = p->prio;
- __setscheduler(p, policy, param->sched_priority);
- if (array) {
- __activate_task(p, rq);
+ __setscheduler(rq, p, policy, param->sched_priority);
+ if (on_rq) {
+ activate_task(rq, p, 0);
/*
* Reschedule if we are currently running on this runqueue and
* our priority decreased, or if we are not currently running on
@@ -4389,8 +4131,9 @@ recheck:
if (task_running(rq, p)) {
if (p->prio > oldprio)
resched_task(rq->curr);
- } else if (TASK_PREEMPTS_CURR(p, rq))
- resched_task(rq->curr);
+ } else {
+ check_preempt_curr(rq, p);
+ }
}
__task_rq_unlock(rq);
spin_unlock_irqrestore(&p->pi_lock, flags);
@@ -4662,41 +4405,18 @@ asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
/**
* sys_sched_yield - yield the current processor to other threads.
*
- * This function yields the current CPU by moving the calling thread
- * to the expired array. If there are no other threads running on this
- * CPU then this function will return.
+ * This function yields the current CPU to other tasks. If there are no
+ * other threads running on this CPU then this function will return.
*/
asmlinkage long sys_sched_yield(void)
{
struct rq *rq = this_rq_lock();
- struct prio_array *array = current->array, *target = rq->expired;
schedstat_inc(rq, yld_cnt);
- /*
- * We implement yielding by moving the task into the expired
- * queue.
- *
- * (special rule: RT tasks will just roundrobin in the active
- * array.)
- */
- if (rt_task(current))
- target = rq->active;
-
- if (array->nr_active == 1) {
+ if (unlikely(rq->nr_running == 1))
schedstat_inc(rq, yld_act_empty);
- if (!rq->expired->nr_active)
- schedstat_inc(rq, yld_both_empty);
- } else if (!rq->expired->nr_active)
- schedstat_inc(rq, yld_exp_empty);
-
- if (array != target) {
- dequeue_task(current, array);
- enqueue_task(current, target);
- } else
- /*
- * requeue_task is cheaper so perform that if possible.
- */
- requeue_task(current, array);
+ else
+ current->sched_class->yield_task(rq, current);
/*
* Since we are going to call schedule() anyway, there's
@@ -4847,6 +4567,7 @@ asmlinkage long sys_sched_get_priority_max(int policy)
break;
case SCHED_NORMAL:
case SCHED_BATCH:
+ case SCHED_IDLE:
ret = 0;
break;
}
@@ -4871,6 +4592,7 @@ asmlinkage long sys_sched_get_priority_min(int policy)
break;
case SCHED_NORMAL:
case SCHED_BATCH:
+ case SCHED_IDLE:
ret = 0;
}
return ret;
@@ -4905,7 +4627,7 @@ long sys_sched_rr_get_interval(pid_t pid, struct timespec __user *interval)
goto out_unlock;
jiffies_to_timespec(p->policy == SCHED_FIFO ?
- 0 : task_timeslice(p), &t);
+ 0 : static_prio_timeslice(p->static_prio), &t);
read_unlock(&tasklist_lock);
retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
out_nounlock:
@@ -4925,14 +4647,14 @@ static void show_task(struct task_struct *p)
state = p->state ? __ffs(p->state) + 1 : 0;
printk("%-13.13s %c", p->comm,
state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?');
-#if (BITS_PER_LONG == 32)
+#if BITS_PER_LONG == 32
if (state == TASK_RUNNING)
- printk(" running ");
+ printk(" running ");
else
- printk(" %08lX ", thread_saved_pc(p));
+ printk(" %08lx ", thread_saved_pc(p));
#else
if (state == TASK_RUNNING)
- printk(" running task ");
+ printk(" running task ");
else
printk(" %016lx ", thread_saved_pc(p));
#endif
@@ -4944,11 +4666,7 @@ static void show_task(struct task_struct *p)
free = (unsigned long)n - (unsigned long)end_of_stack(p);
}
#endif
- printk("%5lu %5d %6d", free, p->pid, p->parent->pid);
- if (!p->mm)
- printk(" (L-TLB)\n");
- else
- printk(" (NOTLB)\n");
+ printk("%5lu %5d %6d\n", free, p->pid, p->parent->pid);
if (state != TASK_RUNNING)
show_stack(p, NULL);
@@ -4958,14 +4676,12 @@ void show_state_filter(unsigned long state_filter)
{
struct task_struct *g, *p;
-#if (BITS_PER_LONG == 32)
- printk("\n"
- " free sibling\n");
- printk(" task PC stack pid father child younger older\n");
+#if BITS_PER_LONG == 32
+ printk(KERN_INFO
+ " task PC stack pid father\n");
#else
- printk("\n"
- " free sibling\n");
- printk(" task PC stack pid father child younger older\n");
+ printk(KERN_INFO
+ " task PC stack pid father\n");
#endif
read_lock(&tasklist_lock);
do_each_thread(g, p) {
@@ -4980,6 +4696,9 @@ void show_state_filter(unsigned long state_filter)
touch_all_softlockup_watchdogs();
+#ifdef CONFIG_SCHED_DEBUG
+ sysrq_sched_debug_show();
+#endif
read_unlock(&tasklist_lock);
/*
* Only show locks if all tasks are dumped:
@@ -4988,6 +4707,11 @@ void show_state_filter(unsigned long state_filter)
debug_show_all_locks();
}
+void __cpuinit init_idle_bootup_task(struct task_struct *idle)
+{
+ idle->sched_class = &idle_sched_class;
+}
+
/**
* init_idle - set up an idle thread for a given CPU
* @idle: task in question
@@ -5001,13 +4725,12 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
struct rq *rq = cpu_rq(cpu);
unsigned long flags;
- idle->timestamp = sched_clock();
- idle->sleep_avg = 0;
- idle->array = NULL;
+ __sched_fork(idle);
+ idle->se.exec_start = sched_clock();
+
idle->prio = idle->normal_prio = MAX_PRIO;
- idle->state = TASK_RUNNING;
idle->cpus_allowed = cpumask_of_cpu(cpu);
- set_task_cpu(idle, cpu);
+ __set_task_cpu(idle, cpu);
spin_lock_irqsave(&rq->lock, flags);
rq->curr = rq->idle = idle;
@@ -5022,6 +4745,10 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
#else
task_thread_info(idle)->preempt_count = 0;
#endif
+ /*
+ * The idle tasks have their own, simple scheduling class:
+ */
+ idle->sched_class = &idle_sched_class;
}
/*
@@ -5033,6 +4760,28 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
*/
cpumask_t nohz_cpu_mask = CPU_MASK_NONE;
+/*
+ * Increase the granularity value when there are more CPUs,
+ * because with more CPUs the 'effective latency' as visible
+ * to users decreases. But the relationship is not linear,
+ * so pick a second-best guess by going with the log2 of the
+ * number of CPUs.
+ *
+ * This idea comes from the SD scheduler of Con Kolivas:
+ */
+static inline void sched_init_granularity(void)
+{
+ unsigned int factor = 1 + ilog2(num_online_cpus());
+ const unsigned long gran_limit = 100000000;
+
+ sysctl_sched_granularity *= factor;
+ if (sysctl_sched_granularity > gran_limit)
+ sysctl_sched_granularity = gran_limit;
+
+ sysctl_sched_runtime_limit = sysctl_sched_granularity * 4;
+ sysctl_sched_wakeup_granularity = sysctl_sched_granularity / 2;
+}
+
#ifdef CONFIG_SMP
/*
* This is how migration works:
@@ -5106,7 +4855,7 @@ EXPORT_SYMBOL_GPL(set_cpus_allowed);
static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
{
struct rq *rq_dest, *rq_src;
- int ret = 0;
+ int ret = 0, on_rq;
if (unlikely(cpu_is_offline(dest_cpu)))
return ret;
@@ -5122,20 +4871,13 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
if (!cpu_isset(dest_cpu, p->cpus_allowed))
goto out;
+ on_rq = p->se.on_rq;
+ if (on_rq)
+ deactivate_task(rq_src, p, 0);
set_task_cpu(p, dest_cpu);
- if (p->array) {
- /*
- * Sync timestamp with rq_dest's before activating.
- * The same thing could be achieved by doing this step
- * afterwards, and pretending it was a local activate.
- * This way is cleaner and logically correct.
- */
- p->timestamp = p->timestamp - rq_src->most_recent_timestamp
- + rq_dest->most_recent_timestamp;
- deactivate_task(p, rq_src);
- __activate_task(p, rq_dest);
- if (TASK_PREEMPTS_CURR(p, rq_dest))
- resched_task(rq_dest->curr);
+ if (on_rq) {
+ activate_task(rq_dest, p, 0);
+ check_preempt_curr(rq_dest, p);
}
ret = 1;
out:
@@ -5287,7 +5029,8 @@ static void migrate_live_tasks(int src_cpu)
write_unlock_irq(&tasklist_lock);
}
-/* Schedules idle task to be the next runnable task on current CPU.
+/*
+ * Schedules idle task to be the next runnable task on current CPU.
* It does so by boosting its priority to highest possible and adding it to
* the _front_ of the runqueue. Used by CPU offline code.
*/
@@ -5307,10 +5050,10 @@ void sched_idle_next(void)
*/
spin_lock_irqsave(&rq->lock, flags);
- __setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
+ __setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
/* Add idle task to the _front_ of its priority queue: */
- __activate_idle_task(p, rq);
+ activate_idle_task(p, rq);
spin_unlock_irqrestore(&rq->lock, flags);
}
@@ -5360,16 +5103,15 @@ static void migrate_dead(unsigned int dead_cpu, struct task_struct *p)
static void migrate_dead_tasks(unsigned int dead_cpu)
{
struct rq *rq = cpu_rq(dead_cpu);
- unsigned int arr, i;
+ struct task_struct *next;
- for (arr = 0; arr < 2; arr++) {
- for (i = 0; i < MAX_PRIO; i++) {
- struct list_head *list = &rq->arrays[arr].queue[i];
-
- while (!list_empty(list))
- migrate_dead(dead_cpu, list_entry(list->next,
- struct task_struct, run_list));
- }
+ for ( ; ; ) {
+ if (!rq->nr_running)
+ break;
+ next = pick_next_task(rq, rq->curr, rq_clock(rq));
+ if (!next)
+ break;
+ migrate_dead(dead_cpu, next);
}
}
#endif /* CONFIG_HOTPLUG_CPU */
@@ -5393,14 +5135,14 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
- p = kthread_create(migration_thread, hcpu, "migration/%d",cpu);
+ p = kthread_create(migration_thread, hcpu, "migration/%d", cpu);
if (IS_ERR(p))
return NOTIFY_BAD;
p->flags |= PF_NOFREEZE;
kthread_bind(p, cpu);
/* Must be high prio: stop_machine expects to yield to it. */
rq = task_rq_lock(p, &flags);
- __setscheduler(p, SCHED_FIFO, MAX_RT_PRIO-1);
+ __setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1);
task_rq_unlock(rq, &flags);
cpu_rq(cpu)->migration_thread = p;
break;
@@ -5431,9 +5173,10 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
rq->migration_thread = NULL;
/* Idle task back to normal (off runqueue, low prio) */
rq = task_rq_lock(rq->idle, &flags);
- deactivate_task(rq->idle, rq);
+ deactivate_task(rq, rq->idle, 0);
rq->idle->static_prio = MAX_PRIO;
- __setscheduler(rq->idle, SCHED_NORMAL, 0);
+ __setscheduler(rq, rq->idle, SCHED_NORMAL, 0);
+ rq->idle->sched_class = &idle_sched_class;
migrate_dead_tasks(cpu);
task_rq_unlock(rq, &flags);
migrate_nr_uninterruptible(rq);
@@ -5742,483 +5485,6 @@ init_sched_build_groups(cpumask_t span, const cpumask_t *cpu_map,
#define SD_NODES_PER_DOMAIN 16
-/*
- * Self-tuning task migration cost measurement between source and target CPUs.
- *
- * This is done by measuring the cost of manipulating buffers of varying
- * sizes. For a given buffer-size here are the steps that are taken:
- *
- * 1) the source CPU reads+dirties a shared buffer
- * 2) the target CPU reads+dirties the same shared buffer
- *
- * We measure how long they take, in the following 4 scenarios:
- *
- * - source: CPU1, target: CPU2 | cost1
- * - source: CPU2, target: CPU1 | cost2
- * - source: CPU1, target: CPU1 | cost3
- * - source: CPU2, target: CPU2 | cost4
- *
- * We then calculate the cost3+cost4-cost1-cost2 difference - this is
- * the cost of migration.
- *
- * We then start off from a small buffer-size and iterate up to larger
- * buffer sizes, in 5% steps - measuring each buffer-size separately, and
- * doing a maximum search for the cost. (The maximum cost for a migration
- * normally occurs when the working set size is around the effective cache
- * size.)
- */
-#define SEARCH_SCOPE 2
-#define MIN_CACHE_SIZE (64*1024U)
-#define DEFAULT_CACHE_SIZE (5*1024*1024U)
-#define ITERATIONS 1
-#define SIZE_THRESH 130
-#define COST_THRESH 130
-
-/*
- * The migration cost is a function of 'domain distance'. Domain
- * distance is the number of steps a CPU has to iterate down its
- * domain tree to share a domain with the other CPU. The farther
- * two CPUs are from each other, the larger the distance gets.
- *
- * Note that we use the distance only to cache measurement results,
- * the distance value is not used numerically otherwise. When two
- * CPUs have the same distance it is assumed that the migration
- * cost is the same. (this is a simplification but quite practical)
- */
-#define MAX_DOMAIN_DISTANCE 32
-
-static unsigned long long migration_cost[MAX_DOMAIN_DISTANCE] =
- { [ 0 ... MAX_DOMAIN_DISTANCE-1 ] =
-/*
- * Architectures may override the migration cost and thus avoid
- * boot-time calibration. Unit is nanoseconds. Mostly useful for
- * virtualized hardware:
- */
-#ifdef CONFIG_DEFAULT_MIGRATION_COST
- CONFIG_DEFAULT_MIGRATION_COST
-#else
- -1LL
-#endif
-};
-
-/*
- * Allow override of migration cost - in units of microseconds.
- * E.g. migration_cost=1000,2000,3000 will set up a level-1 cost
- * of 1 msec, level-2 cost of 2 msecs and level3 cost of 3 msecs:
- */
-static int __init migration_cost_setup(char *str)
-{
- int ints[MAX_DOMAIN_DISTANCE+1], i;
-
- str = get_options(str, ARRAY_SIZE(ints), ints);
-
- printk("#ints: %d\n", ints[0]);
- for (i = 1; i <= ints[0]; i++) {
- migration_cost[i-1] = (unsigned long long)ints[i]*1000;
- printk("migration_cost[%d]: %Ld\n", i-1, migration_cost[i-1]);
- }
- return 1;
-}
-
-__setup ("migration_cost=", migration_cost_setup);
-
-/*
- * Global multiplier (divisor) for migration-cutoff values,
- * in percentiles. E.g. use a value of 150 to get 1.5 times
- * longer cache-hot cutoff times.
- *
- * (We scale it from 100 to 128 to long long handling easier.)
- */
-
-#define MIGRATION_FACTOR_SCALE 128
-
-static unsigned int migration_factor = MIGRATION_FACTOR_SCALE;
-
-static int __init setup_migration_factor(char *str)
-{
- get_option(&str, &migration_factor);
- migration_factor = migration_factor * MIGRATION_FACTOR_SCALE / 100;
- return 1;
-}
-
-__setup("migration_factor=", setup_migration_factor);
-
-/*
- * Estimated distance of two CPUs, measured via the number of domains
- * we have to pass for the two CPUs to be in the same span:
- */
-static unsigned long domain_distance(int cpu1, int cpu2)
-{
- unsigned long distance = 0;
- struct sched_domain *sd;
-
- for_each_domain(cpu1, sd) {
- WARN_ON(!cpu_isset(cpu1, sd->span));
- if (cpu_isset(cpu2, sd->span))
- return distance;
- distance++;
- }
- if (distance >= MAX_DOMAIN_DISTANCE) {
- WARN_ON(1);
- distance = MAX_DOMAIN_DISTANCE-1;
- }
-
- return distance;
-}
-
-static unsigned int migration_debug;
-
-static int __init setup_migration_debug(char *str)
-{
- get_option(&str, &migration_debug);
- return 1;
-}
-
-__setup("migration_debug=", setup_migration_debug);
-
-/*
- * Maximum cache-size that the scheduler should try to measure.
- * Architectures with larger caches should tune this up during
- * bootup. Gets used in the domain-setup code (i.e. during SMP
- * bootup).
- */
-unsigned int max_cache_size;
-
-static int __init setup_max_cache_size(char *str)
-{
- get_option(&str, &max_cache_size);
- return 1;
-}
-
-__setup("max_cache_size=", setup_max_cache_size);
-
-/*
- * Dirty a big buffer in a hard-to-predict (for the L2 cache) way. This
- * is the operation that is timed, so we try to generate unpredictable
- * cachemisses that still end up filling the L2 cache:
- */
-static void touch_cache(void *__cache, unsigned long __size)
-{
- unsigned long size = __size / sizeof(long);
- unsigned long chunk1 = size / 3;
- unsigned long chunk2 = 2 * size / 3;
- unsigned long *cache = __cache;
- int i;
-
- for (i = 0; i < size/6; i += 8) {
- switch (i % 6) {
- case 0: cache[i]++;
- case 1: cache[size-1-i]++;
- case 2: cache[chunk1-i]++;
- case 3: cache[chunk1+i]++;
- case 4: cache[chunk2-i]++;
- case 5: cache[chunk2+i]++;
- }
- }
-}
-
-/*
- * Measure the cache-cost of one task migration. Returns in units of nsec.
- */
-static unsigned long long
-measure_one(void *cache, unsigned long size, int source, int target)
-{
- cpumask_t mask, saved_mask;
- unsigned long long t0, t1, t2, t3, cost;
-
- saved_mask = current->cpus_allowed;
-
- /*
- * Flush source caches to RAM and invalidate them:
- */
- sched_cacheflush();
-
- /*
- * Migrate to the source CPU:
- */
- mask = cpumask_of_cpu(source);
- set_cpus_allowed(current, mask);
- WARN_ON(smp_processor_id() != source);
-
- /*
- * Dirty the working set:
- */
- t0 = sched_clock();
- touch_cache(cache, size);
- t1 = sched_clock();
-
- /*
- * Migrate to the target CPU, dirty the L2 cache and access
- * the shared buffer. (which represents the working set
- * of a migrated task.)
- */
- mask = cpumask_of_cpu(target);
- set_cpus_allowed(current, mask);
- WARN_ON(smp_processor_id() != target);
-
- t2 = sched_clock();
- touch_cache(cache, size);
- t3 = sched_clock();
-
- cost = t1-t0 + t3-t2;
-
- if (migration_debug >= 2)
- printk("[%d->%d]: %8Ld %8Ld %8Ld => %10Ld.\n",
- source, target, t1-t0, t1-t0, t3-t2, cost);
- /*
- * Flush target caches to RAM and invalidate them:
- */
- sched_cacheflush();
-
- set_cpus_allowed(current, saved_mask);
-
- return cost;
-}
-
-/*
- * Measure a series of task migrations and return the average
- * result. Since this code runs early during bootup the system
- * is 'undisturbed' and the average latency makes sense.
- *
- * The algorithm in essence auto-detects the relevant cache-size,
- * so it will properly detect different cachesizes for different
- * cache-hierarchies, depending on how the CPUs are connected.
- *
- * Architectures can prime the upper limit of the search range via
- * max_cache_size, otherwise the search range defaults to 20MB...64K.
- */
-static unsigned long long
-measure_cost(int cpu1, int cpu2, void *cache, unsigned int size)
-{
- unsigned long long cost1, cost2;
- int i;
-
- /*
- * Measure the migration cost of 'size' bytes, over an
- * average of 10 runs:
- *
- * (We perturb the cache size by a small (0..4k)
- * value to compensate size/alignment related artifacts.
- * We also subtract the cost of the operation done on
- * the same CPU.)
- */
- cost1 = 0;
-
- /*
- * dry run, to make sure we start off cache-cold on cpu1,
- * and to get any vmalloc pagefaults in advance:
- */
- measure_one(cache, size, cpu1, cpu2);
- for (i = 0; i < ITERATIONS; i++)
- cost1 += measure_one(cache, size - i * 1024, cpu1, cpu2);
-
- measure_one(cache, size, cpu2, cpu1);
- for (i = 0; i < ITERATIONS; i++)
- cost1 += measure_one(cache, size - i * 1024, cpu2, cpu1);
-
- /*
- * (We measure the non-migrating [cached] cost on both
- * cpu1 and cpu2, to handle CPUs with different speeds)
- */
- cost2 = 0;
-
- measure_one(cache, size, cpu1, cpu1);
- for (i = 0; i < ITERATIONS; i++)
- cost2 += measure_one(cache, size - i * 1024, cpu1, cpu1);
-
- measure_one(cache, size, cpu2, cpu2);
- for (i = 0; i < ITERATIONS; i++)
- cost2 += measure_one(cache, size - i * 1024, cpu2, cpu2);
-
- /*
- * Get the per-iteration migration cost:
- */
- do_div(cost1, 2 * ITERATIONS);
- do_div(cost2, 2 * ITERATIONS);
-
- return cost1 - cost2;
-}
-
-static unsigned long long measure_migration_cost(int cpu1, int cpu2)
-{
- unsigned long long max_cost = 0, fluct = 0, avg_fluct = 0;
- unsigned int max_size, size, size_found = 0;
- long long cost = 0, prev_cost;
- void *cache;
-
- /*
- * Search from max_cache_size*5 down to 64K - the real relevant
- * cachesize has to lie somewhere inbetween.
- */
- if (max_cache_size) {
- max_size = max(max_cache_size * SEARCH_SCOPE, MIN_CACHE_SIZE);
- size = max(max_cache_size / SEARCH_SCOPE, MIN_CACHE_SIZE);
- } else {
- /*
- * Since we have no estimation about the relevant
- * search range
- */
- max_size = DEFAULT_CACHE_SIZE * SEARCH_SCOPE;
- size = MIN_CACHE_SIZE;
- }
-
- if (!cpu_online(cpu1) || !cpu_online(cpu2)) {
- printk("cpu %d and %d not both online!\n", cpu1, cpu2);
- return 0;
- }
-
- /*
- * Allocate the working set:
- */
- cache = vmalloc(max_size);
- if (!cache) {
- printk("could not vmalloc %d bytes for cache!\n", 2 * max_size);
- return 1000000; /* return 1 msec on very small boxen */
- }
-
- while (size <= max_size) {
- prev_cost = cost;
- cost = measure_cost(cpu1, cpu2, cache, size);
-
- /*
- * Update the max:
- */
- if (cost > 0) {
- if (max_cost < cost) {
- max_cost = cost;
- size_found = size;
- }
- }
- /*
- * Calculate average fluctuation, we use this to prevent
- * noise from triggering an early break out of the loop:
- */
- fluct = abs(cost - prev_cost);
- avg_fluct = (avg_fluct + fluct)/2;
-
- if (migration_debug)
- printk("-> [%d][%d][%7d] %3ld.%ld [%3ld.%ld] (%ld): "
- "(%8Ld %8Ld)\n",
- cpu1, cpu2, size,
- (long)cost / 1000000,
- ((long)cost / 100000) % 10,
- (long)max_cost / 1000000,
- ((long)max_cost / 100000) % 10,
- domain_distance(cpu1, cpu2),
- cost, avg_fluct);
-
- /*
- * If we iterated at least 20% past the previous maximum,
- * and the cost has dropped by more than 20% already,
- * (taking fluctuations into account) then we assume to
- * have found the maximum and break out of the loop early:
- */
- if (size_found && (size*100 > size_found*SIZE_THRESH))
- if (cost+avg_fluct <= 0 ||
- max_cost*100 > (cost+avg_fluct)*COST_THRESH) {
-
- if (migration_debug)
- printk("-> found max.\n");
- break;
- }
- /*
- * Increase the cachesize in 10% steps:
- */
- size = size * 10 / 9;
- }
-
- if (migration_debug)
- printk("[%d][%d] working set size found: %d, cost: %Ld\n",
- cpu1, cpu2, size_found, max_cost);
-
- vfree(cache);
-
- /*
- * A task is considered 'cache cold' if at least 2 times
- * the worst-case cost of migration has passed.
- *
- * (this limit is only listened to if the load-balancing
- * situation is 'nice' - if there is a large imbalance we
- * ignore it for the sake of CPU utilization and
- * processing fairness.)
- */
- return 2 * max_cost * migration_factor / MIGRATION_FACTOR_SCALE;
-}
-
-static void calibrate_migration_costs(const cpumask_t *cpu_map)
-{
- int cpu1 = -1, cpu2 = -1, cpu, orig_cpu = raw_smp_processor_id();
- unsigned long j0, j1, distance, max_distance = 0;
- struct sched_domain *sd;
-
- j0 = jiffies;
-
- /*
- * First pass - calculate the cacheflush times:
- */
- for_each_cpu_mask(cpu1, *cpu_map) {
- for_each_cpu_mask(cpu2, *cpu_map) {
- if (cpu1 == cpu2)
- continue;
- distance = domain_distance(cpu1, cpu2);
- max_distance = max(max_distance, distance);
- /*
- * No result cached yet?
- */
- if (migration_cost[distance] == -1LL)
- migration_cost[distance] =
- measure_migration_cost(cpu1, cpu2);
- }
- }
- /*
- * Second pass - update the sched domain hierarchy with
- * the new cache-hot-time estimations:
- */
- for_each_cpu_mask(cpu, *cpu_map) {
- distance = 0;
- for_each_domain(cpu, sd) {
- sd->cache_hot_time = migration_cost[distance];
- distance++;
- }
- }
- /*
- * Print the matrix:
- */
- if (migration_debug)
- printk("migration: max_cache_size: %d, cpu: %d MHz:\n",
- max_cache_size,
-#ifdef CONFIG_X86
- cpu_khz/1000
-#else
- -1
-#endif
- );
- if (system_state == SYSTEM_BOOTING && num_online_cpus() > 1) {
- printk("migration_cost=");
- for (distance = 0; distance <= max_distance; distance++) {
- if (distance)
- printk(",");
- printk("%ld", (long)migration_cost[distance] / 1000);
- }
- printk("\n");
- }
- j1 = jiffies;
- if (migration_debug)
- printk("migration: %ld seconds\n", (j1-j0) / HZ);
-
- /*
- * Move back to the original CPU. NUMA-Q gets confused
- * if we migrate to another quad during bootup.
- */
- if (raw_smp_processor_id() != orig_cpu) {
- cpumask_t mask = cpumask_of_cpu(orig_cpu),
- saved_mask = current->cpus_allowed;
-
- set_cpus_allowed(current, mask);
- set_cpus_allowed(current, saved_mask);
- }
-}
-
#ifdef CONFIG_NUMA
/**
@@ -6519,7 +5785,6 @@ static void init_sched_groups_power(int cpu, struct sched_domain *sd)
static int build_sched_domains(const cpumask_t *cpu_map)
{
int i;
- struct sched_domain *sd;
#ifdef CONFIG_NUMA
struct sched_group **sched_group_nodes = NULL;
int sd_allnodes = 0;
@@ -6527,7 +5792,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
/*
* Allocate the per-node list of sched groups
*/
- sched_group_nodes = kzalloc(sizeof(struct sched_group*)*MAX_NUMNODES,
+ sched_group_nodes = kzalloc(sizeof(struct sched_group *)*MAX_NUMNODES,
GFP_KERNEL);
if (!sched_group_nodes) {
printk(KERN_WARNING "Can not alloc sched group node list\n");
@@ -6546,8 +5811,8 @@ static int build_sched_domains(const cpumask_t *cpu_map)
cpus_and(nodemask, nodemask, *cpu_map);
#ifdef CONFIG_NUMA
- if (cpus_weight(*cpu_map)
- > SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
+ if (cpus_weight(*cpu_map) >
+ SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
sd = &per_cpu(allnodes_domains, i);
*sd = SD_ALLNODES_INIT;
sd->span = *cpu_map;
@@ -6606,7 +5871,8 @@ static int build_sched_domains(const cpumask_t *cpu_map)
if (i != first_cpu(this_sibling_map))
continue;
- init_sched_build_groups(this_sibling_map, cpu_map, &cpu_to_cpu_group);
+ init_sched_build_groups(this_sibling_map, cpu_map,
+ &cpu_to_cpu_group);
}
#endif
@@ -6617,11 +5883,11 @@ static int build_sched_domains(const cpumask_t *cpu_map)
cpus_and(this_core_map, this_core_map, *cpu_map);
if (i != first_cpu(this_core_map))
continue;
- init_sched_build_groups(this_core_map, cpu_map, &cpu_to_core_group);
+ init_sched_build_groups(this_core_map, cpu_map,
+ &cpu_to_core_group);
}
#endif
-
/* Set up physical groups */
for (i = 0; i < MAX_NUMNODES; i++) {
cpumask_t nodemask = node_to_cpumask(i);
@@ -6636,7 +5902,8 @@ static int build_sched_domains(const cpumask_t *cpu_map)
#ifdef CONFIG_NUMA
/* Set up node groups */
if (sd_allnodes)
- init_sched_build_groups(*cpu_map, cpu_map, &cpu_to_allnodes_group);
+ init_sched_build_groups(*cpu_map, cpu_map,
+ &cpu_to_allnodes_group);
for (i = 0; i < MAX_NUMNODES; i++) {
/* Set up node groups */
@@ -6664,6 +5931,7 @@ static int build_sched_domains(const cpumask_t *cpu_map)
sched_group_nodes[i] = sg;
for_each_cpu_mask(j, nodemask) {
struct sched_domain *sd;
+
sd = &per_cpu(node_domains, j);
sd->groups = sg;
}
@@ -6708,19 +5976,22 @@ static int build_sched_domains(const cpumask_t *cpu_map)
/* Calculate CPU power for physical packages and nodes */
#ifdef CONFIG_SCHED_SMT
for_each_cpu_mask(i, *cpu_map) {
- sd = &per_cpu(cpu_domains, i);
+ struct sched_domain *sd = &per_cpu(cpu_domains, i);
+
init_sched_groups_power(i, sd);
}
#endif
#ifdef CONFIG_SCHED_MC
for_each_cpu_mask(i, *cpu_map) {
- sd = &per_cpu(core_domains, i);
+ struct sched_domain *sd = &per_cpu(core_domains, i);
+
init_sched_groups_power(i, sd);
}
#endif
for_each_cpu_mask(i, *cpu_map) {
- sd = &per_cpu(phys_domains, i);
+ struct sched_domain *sd = &per_cpu(phys_domains, i);
+
init_sched_groups_power(i, sd);
}
@@ -6748,10 +6019,6 @@ static int build_sched_domains(const cpumask_t *cpu_map)
#endif
cpu_attach_domain(sd, i);
}
- /*
- * Tune cache-hot values:
- */
- calibrate_migration_costs(cpu_map);
return 0;
@@ -6958,10 +6225,12 @@ void __init sched_init_smp(void)
/* Move init over to a non-isolated CPU */
if (set_cpus_allowed(current, non_isolated_cpus) < 0)
BUG();
+ sched_init_granularity();
}
#else
void __init sched_init_smp(void)
{
+ sched_init_granularity();
}
#endif /* CONFIG_SMP */
@@ -6975,28 +6244,51 @@ int in_sched_functions(unsigned long addr)
&& addr < (unsigned long)__sched_text_end);
}
+static inline void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
+{
+ cfs_rq->tasks_timeline = RB_ROOT;
+ cfs_rq->fair_clock = 1;
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ cfs_rq->rq = rq;
+#endif
+}
+
void __init sched_init(void)
{
- int i, j, k;
+ u64 now = sched_clock();
int highest_cpu = 0;
+ int i, j;
+
+ /*
+ * Link up the scheduling class hierarchy:
+ */
+ rt_sched_class.next = &fair_sched_class;
+ fair_sched_class.next = &idle_sched_class;
+ idle_sched_class.next = NULL;
for_each_possible_cpu(i) {
- struct prio_array *array;
+ struct rt_prio_array *array;
struct rq *rq;
rq = cpu_rq(i);
spin_lock_init(&rq->lock);
lockdep_set_class(&rq->lock, &rq->rq_lock_key);
rq->nr_running = 0;
- rq->active = rq->arrays;
- rq->expired = rq->arrays + 1;
- rq->best_expired_prio = MAX_PRIO;
+ rq->clock = 1;
+ init_cfs_rq(&rq->cfs, rq);
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);
+ list_add(&rq->cfs.leaf_cfs_rq_list, &rq->leaf_cfs_rq_list);
+#endif
+ rq->ls.load_update_last = now;
+ rq->ls.load_update_start = now;
+ for (j = 0; j < CPU_LOAD_IDX_MAX; j++)
+ rq->cpu_load[j] = 0;
#ifdef CONFIG_SMP
rq->sd = NULL;
- for (j = 1; j < 3; j++)
- rq->cpu_load[j] = 0;
rq->active_balance = 0;
+ rq->next_balance = jiffies;
rq->push_cpu = 0;
rq->cpu = i;
rq->migration_thread = NULL;
@@ -7004,16 +6296,14 @@ void __init sched_init(void)
#endif
atomic_set(&rq->nr_iowait, 0);
- for (j = 0; j < 2; j++) {
- array = rq->arrays + j;
- for (k = 0; k < MAX_PRIO; k++) {
- INIT_LIST_HEAD(array->queue + k);
- __clear_bit(k, array->bitmap);
- }
- // delimiter for bitsearch
- __set_bit(MAX_PRIO, array->bitmap);
+ array = &rq->rt.active;
+ for (j = 0; j < MAX_RT_PRIO; j++) {
+ INIT_LIST_HEAD(array->queue + j);
+ __clear_bit(j, array->bitmap);
}
highest_cpu = i;
+ /* delimiter for bitsearch: */
+ __set_bit(MAX_RT_PRIO, array->bitmap);
}
set_load_weight(&init_task);
@@ -7040,6 +6330,10 @@ void __init sched_init(void)
* when this runqueue becomes "idle".
*/
init_idle(current, smp_processor_id());
+ /*
+ * During early bootup we pretend to be a normal task:
+ */
+ current->sched_class = &fair_sched_class;
}
#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
@@ -7070,31 +6364,59 @@ EXPORT_SYMBOL(__might_sleep);
#ifdef CONFIG_MAGIC_SYSRQ
void normalize_rt_tasks(void)
{
- struct prio_array *array;
- struct task_struct *p;
+ struct task_struct *g, *p;
unsigned long flags;
struct rq *rq;
+ int on_rq;
read_lock_irq(&tasklist_lock);
- for_each_process(p) {
- if (!rt_task(p))
+ do_each_thread(g, p) {
+ p->se.fair_key = 0;
+ p->se.wait_runtime = 0;
+ p->se.wait_start_fair = 0;
+ p->se.wait_start = 0;
+ p->se.exec_start = 0;
+ p->se.sleep_start = 0;
+ p->se.sleep_start_fair = 0;
+ p->se.block_start = 0;
+ task_rq(p)->cfs.fair_clock = 0;
+ task_rq(p)->clock = 0;
+
+ if (!rt_task(p)) {
+ /*
+ * Renice negative nice level userspace
+ * tasks back to 0:
+ */
+ if (TASK_NICE(p) < 0 && p->mm)
+ set_user_nice(p, 0);
continue;
+ }
spin_lock_irqsave(&p->pi_lock, flags);
rq = __task_rq_lock(p);
+#ifdef CONFIG_SMP
+ /*
+ * Do not touch the migration thread:
+ */
+ if (p == rq->migration_thread)
+ goto out_unlock;
+#endif
- array = p->array;
- if (array)
- deactivate_task(p, task_rq(p));
- __setscheduler(p, SCHED_NORMAL, 0);
- if (array) {
- __activate_task(p, task_rq(p));
+ on_rq = p->se.on_rq;
+ if (on_rq)
+ deactivate_task(task_rq(p), p, 0);
+ __setscheduler(rq, p, SCHED_NORMAL, 0);
+ if (on_rq) {
+ activate_task(task_rq(p), p, 0);
resched_task(rq->curr);
}
-
+#ifdef CONFIG_SMP
+ out_unlock:
+#endif
__task_rq_unlock(rq);
spin_unlock_irqrestore(&p->pi_lock, flags);
- }
+ } while_each_thread(g, p);
+
read_unlock_irq(&tasklist_lock);
}
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
new file mode 100644
index 00000000000..29f2c21e7da
--- /dev/null
+++ b/kernel/sched_debug.c
@@ -0,0 +1,275 @@
+/*
+ * kernel/time/sched_debug.c
+ *
+ * Print the CFS rbtree
+ *
+ * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
+ *
+ * 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/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/utsname.h>
+
+/*
+ * This allows printing both to /proc/sched_debug and
+ * to the console
+ */
+#define SEQ_printf(m, x...) \
+ do { \
+ if (m) \
+ seq_printf(m, x); \
+ else \
+ printk(x); \
+ } while (0)
+
+static void
+print_task(struct seq_file *m, struct rq *rq, struct task_struct *p, u64 now)
+{
+ if (rq->curr == p)
+ SEQ_printf(m, "R");
+ else
+ SEQ_printf(m, " ");
+
+ SEQ_printf(m, "%15s %5d %15Ld %13Ld %13Ld %9Ld %5d "
+ "%15Ld %15Ld %15Ld %15Ld %15Ld\n",
+ p->comm, p->pid,
+ (long long)p->se.fair_key,
+ (long long)(p->se.fair_key - rq->cfs.fair_clock),
+ (long long)p->se.wait_runtime,
+ (long long)(p->nvcsw + p->nivcsw),
+ p->prio,
+ (long long)p->se.sum_exec_runtime,
+ (long long)p->se.sum_wait_runtime,
+ (long long)p->se.sum_sleep_runtime,
+ (long long)p->se.wait_runtime_overruns,
+ (long long)p->se.wait_runtime_underruns);
+}
+
+static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu, u64 now)
+{
+ struct task_struct *g, *p;
+
+ SEQ_printf(m,
+ "\nrunnable tasks:\n"
+ " task PID tree-key delta waiting"
+ " switches prio"
+ " sum-exec sum-wait sum-sleep"
+ " wait-overrun wait-underrun\n"
+ "------------------------------------------------------------------"
+ "----------------"
+ "------------------------------------------------"
+ "--------------------------------\n");
+
+ read_lock_irq(&tasklist_lock);
+
+ do_each_thread(g, p) {
+ if (!p->se.on_rq || task_cpu(p) != rq_cpu)
+ continue;
+
+ print_task(m, rq, p, now);
+ } while_each_thread(g, p);
+
+ read_unlock_irq(&tasklist_lock);
+}
+
+static void
+print_cfs_rq_runtime_sum(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
+{
+ s64 wait_runtime_rq_sum = 0;
+ struct task_struct *p;
+ struct rb_node *curr;
+ unsigned long flags;
+ struct rq *rq = &per_cpu(runqueues, cpu);
+
+ spin_lock_irqsave(&rq->lock, flags);
+ curr = first_fair(cfs_rq);
+ while (curr) {
+ p = rb_entry(curr, struct task_struct, se.run_node);
+ wait_runtime_rq_sum += p->se.wait_runtime;
+
+ curr = rb_next(curr);
+ }
+ spin_unlock_irqrestore(&rq->lock, flags);
+
+ SEQ_printf(m, " .%-30s: %Ld\n", "wait_runtime_rq_sum",
+ (long long)wait_runtime_rq_sum);
+}
+
+void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq, u64 now)
+{
+ SEQ_printf(m, "\ncfs_rq %p\n", cfs_rq);
+
+#define P(x) \
+ SEQ_printf(m, " .%-30s: %Ld\n", #x, (long long)(cfs_rq->x))
+
+ P(fair_clock);
+ P(exec_clock);
+ P(wait_runtime);
+ P(wait_runtime_overruns);
+ P(wait_runtime_underruns);
+ P(sleeper_bonus);
+#undef P
+
+ print_cfs_rq_runtime_sum(m, cpu, cfs_rq);
+}
+
+static void print_cpu(struct seq_file *m, int cpu, u64 now)
+{
+ struct rq *rq = &per_cpu(runqueues, cpu);
+
+#ifdef CONFIG_X86
+ {
+ unsigned int freq = cpu_khz ? : 1;
+
+ SEQ_printf(m, "\ncpu#%d, %u.%03u MHz\n",
+ cpu, freq / 1000, (freq % 1000));
+ }
+#else
+ SEQ_printf(m, "\ncpu#%d\n", cpu);
+#endif
+
+#define P(x) \
+ SEQ_printf(m, " .%-30s: %Ld\n", #x, (long long)(rq->x))
+
+ P(nr_running);
+ SEQ_printf(m, " .%-30s: %lu\n", "load",
+ rq->ls.load.weight);
+ P(ls.delta_fair);
+ P(ls.delta_exec);
+ P(nr_switches);
+ P(nr_load_updates);
+ P(nr_uninterruptible);
+ SEQ_printf(m, " .%-30s: %lu\n", "jiffies", jiffies);
+ P(next_balance);
+ P(curr->pid);
+ P(clock);
+ P(prev_clock_raw);
+ P(clock_warps);
+ P(clock_overflows);
+ P(clock_unstable_events);
+ P(clock_max_delta);
+ P(cpu_load[0]);
+ P(cpu_load[1]);
+ P(cpu_load[2]);
+ P(cpu_load[3]);
+ P(cpu_load[4]);
+#undef P
+
+ print_cfs_stats(m, cpu, now);
+
+ print_rq(m, rq, cpu, now);
+}
+
+static int sched_debug_show(struct seq_file *m, void *v)
+{
+ u64 now = ktime_to_ns(ktime_get());
+ int cpu;
+
+ SEQ_printf(m, "Sched Debug Version: v0.05, %s %.*s\n",
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+
+ SEQ_printf(m, "now at %Lu nsecs\n", (unsigned long long)now);
+
+ for_each_online_cpu(cpu)
+ print_cpu(m, cpu, now);
+
+ SEQ_printf(m, "\n");
+
+ return 0;
+}
+
+void sysrq_sched_debug_show(void)
+{
+ sched_debug_show(NULL, NULL);
+}
+
+static int sched_debug_open(struct inode *inode, struct file *filp)
+{
+ return single_open(filp, sched_debug_show, NULL);
+}
+
+static struct file_operations sched_debug_fops = {
+ .open = sched_debug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int __init init_sched_debug_procfs(void)
+{
+ struct proc_dir_entry *pe;
+
+ pe = create_proc_entry("sched_debug", 0644, NULL);
+ if (!pe)
+ return -ENOMEM;
+
+ pe->proc_fops = &sched_debug_fops;
+
+ return 0;
+}
+
+__initcall(init_sched_debug_procfs);
+
+void proc_sched_show_task(struct task_struct *p, struct seq_file *m)
+{
+ unsigned long flags;
+ int num_threads = 1;
+
+ rcu_read_lock();
+ if (lock_task_sighand(p, &flags)) {
+ num_threads = atomic_read(&p->signal->count);
+ unlock_task_sighand(p, &flags);
+ }
+ rcu_read_unlock();
+
+ SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid, num_threads);
+ SEQ_printf(m, "----------------------------------------------\n");
+#define P(F) \
+ SEQ_printf(m, "%-25s:%20Ld\n", #F, (long long)p->F)
+
+ P(se.wait_start);
+ P(se.wait_start_fair);
+ P(se.exec_start);
+ P(se.sleep_start);
+ P(se.sleep_start_fair);
+ P(se.block_start);
+ P(se.sleep_max);
+ P(se.block_max);
+ P(se.exec_max);
+ P(se.wait_max);
+ P(se.wait_runtime);
+ P(se.wait_runtime_overruns);
+ P(se.wait_runtime_underruns);
+ P(se.sum_wait_runtime);
+ P(se.sum_exec_runtime);
+ SEQ_printf(m, "%-25s:%20Ld\n",
+ "nr_switches", (long long)(p->nvcsw + p->nivcsw));
+ P(se.load.weight);
+ P(policy);
+ P(prio);
+#undef P
+
+ {
+ u64 t0, t1;
+
+ t0 = sched_clock();
+ t1 = sched_clock();
+ SEQ_printf(m, "%-25s:%20Ld\n",
+ "clock-delta", (long long)(t1-t0));
+ }
+}
+
+void proc_sched_set_task(struct task_struct *p)
+{
+ p->se.sleep_max = p->se.block_max = p->se.exec_max = p->se.wait_max = 0;
+ p->se.wait_runtime_overruns = p->se.wait_runtime_underruns = 0;
+ p->se.sum_exec_runtime = 0;
+}
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
new file mode 100644
index 00000000000..6971db0a716
--- /dev/null
+++ b/kernel/sched_fair.c
@@ -0,0 +1,1131 @@
+/*
+ * Completely Fair Scheduling (CFS) Class (SCHED_NORMAL/SCHED_BATCH)
+ *
+ * Copyright (C) 2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *
+ * Interactivity improvements by Mike Galbraith
+ * (C) 2007 Mike Galbraith <efault@gmx.de>
+ *
+ * Various enhancements by Dmitry Adamushko.
+ * (C) 2007 Dmitry Adamushko <dmitry.adamushko@gmail.com>
+ *
+ * Group scheduling enhancements by Srivatsa Vaddagiri
+ * Copyright IBM Corporation, 2007
+ * Author: Srivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
+ *
+ * Scaled math optimizations by Thomas Gleixner
+ * Copyright (C) 2007, Thomas Gleixner <tglx@linutronix.de>
+ */
+
+/*
+ * Preemption granularity:
+ * (default: 2 msec, units: nanoseconds)
+ *
+ * NOTE: this granularity value is not the same as the concept of
+ * 'timeslice length' - timeslices in CFS will typically be somewhat
+ * larger than this value. (to see the precise effective timeslice
+ * length of your workload, run vmstat and monitor the context-switches
+ * field)
+ *
+ * On SMP systems the value of this is multiplied by the log2 of the
+ * number of CPUs. (i.e. factor 2x on 2-way systems, 3x on 4-way
+ * systems, 4x on 8-way systems, 5x on 16-way systems, etc.)
+ */
+unsigned int sysctl_sched_granularity __read_mostly = 2000000000ULL/HZ;
+
+/*
+ * SCHED_BATCH wake-up granularity.
+ * (default: 10 msec, units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+unsigned int sysctl_sched_batch_wakeup_granularity __read_mostly =
+ 10000000000ULL/HZ;
+
+/*
+ * SCHED_OTHER wake-up granularity.
+ * (default: 1 msec, units: nanoseconds)
+ *
+ * This option delays the preemption effects of decoupled workloads
+ * and reduces their over-scheduling. Synchronous workloads will still
+ * have immediate wakeup/sleep latencies.
+ */
+unsigned int sysctl_sched_wakeup_granularity __read_mostly = 1000000000ULL/HZ;
+
+unsigned int sysctl_sched_stat_granularity __read_mostly;
+
+/*
+ * Initialized in sched_init_granularity():
+ */
+unsigned int sysctl_sched_runtime_limit __read_mostly;
+
+/*
+ * Debugging: various feature bits
+ */
+enum {
+ SCHED_FEAT_FAIR_SLEEPERS = 1,
+ SCHED_FEAT_SLEEPER_AVG = 2,
+ SCHED_FEAT_SLEEPER_LOAD_AVG = 4,
+ SCHED_FEAT_PRECISE_CPU_LOAD = 8,
+ SCHED_FEAT_START_DEBIT = 16,
+ SCHED_FEAT_SKIP_INITIAL = 32,
+};
+
+unsigned int sysctl_sched_features __read_mostly =
+ SCHED_FEAT_FAIR_SLEEPERS *1 |
+ SCHED_FEAT_SLEEPER_AVG *1 |
+ SCHED_FEAT_SLEEPER_LOAD_AVG *1 |
+ SCHED_FEAT_PRECISE_CPU_LOAD *1 |
+ SCHED_FEAT_START_DEBIT *1 |
+ SCHED_FEAT_SKIP_INITIAL *0;
+
+extern struct sched_class fair_sched_class;
+
+/**************************************************************
+ * CFS operations on generic schedulable entities:
+ */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+/* cpu runqueue to which this cfs_rq is attached */
+static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+{
+ return cfs_rq->rq;
+}
+
+/* currently running entity (if any) on this cfs_rq */
+static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq)
+{
+ return cfs_rq->curr;
+}
+
+/* An entity is a task if it doesn't "own" a runqueue */
+#define entity_is_task(se) (!se->my_q)
+
+static inline void
+set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ cfs_rq->curr = se;
+}
+
+#else /* CONFIG_FAIR_GROUP_SCHED */
+
+static inline struct rq *rq_of(struct cfs_rq *cfs_rq)
+{
+ return container_of(cfs_rq, struct rq, cfs);
+}
+
+static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq)
+{
+ struct rq *rq = rq_of(cfs_rq);
+
+ if (unlikely(rq->curr->sched_class != &fair_sched_class))
+ return NULL;
+
+ return &rq->curr->se;
+}
+
+#define entity_is_task(se) 1
+
+static inline void
+set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se) { }
+
+#endif /* CONFIG_FAIR_GROUP_SCHED */
+
+static inline struct task_struct *task_of(struct sched_entity *se)
+{
+ return container_of(se, struct task_struct, se);
+}
+
+
+/**************************************************************
+ * Scheduling class tree data structure manipulation methods:
+ */
+
+/*
+ * Enqueue an entity into the rb-tree:
+ */
+static inline void
+__enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ struct rb_node **link = &cfs_rq->tasks_timeline.rb_node;
+ struct rb_node *parent = NULL;
+ struct sched_entity *entry;
+ s64 key = se->fair_key;
+ int leftmost = 1;
+
+ /*
+ * Find the right place in the rbtree:
+ */
+ while (*link) {
+ parent = *link;
+ entry = rb_entry(parent, struct sched_entity, run_node);
+ /*
+ * We dont care about collisions. Nodes with
+ * the same key stay together.
+ */
+ if (key - entry->fair_key < 0) {
+ link = &parent->rb_left;
+ } else {
+ link = &parent->rb_right;
+ leftmost = 0;
+ }
+ }
+
+ /*
+ * Maintain a cache of leftmost tree entries (it is frequently
+ * used):
+ */
+ if (leftmost)
+ cfs_rq->rb_leftmost = &se->run_node;
+
+ rb_link_node(&se->run_node, parent, link);
+ rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline);
+ update_load_add(&cfs_rq->load, se->load.weight);
+ cfs_rq->nr_running++;
+ se->on_rq = 1;
+}
+
+static inline void
+__dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ if (cfs_rq->rb_leftmost == &se->run_node)
+ cfs_rq->rb_leftmost = rb_next(&se->run_node);
+ rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
+ update_load_sub(&cfs_rq->load, se->load.weight);
+ cfs_rq->nr_running--;
+ se->on_rq = 0;
+}
+
+static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq)
+{
+ return cfs_rq->rb_leftmost;
+}
+
+static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq)
+{
+ return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node);
+}
+
+/**************************************************************
+ * Scheduling class statistics methods:
+ */
+
+/*
+ * We rescale the rescheduling granularity of tasks according to their
+ * nice level, but only linearly, not exponentially:
+ */
+static long
+niced_granularity(struct sched_entity *curr, unsigned long granularity)
+{
+ u64 tmp;
+
+ /*
+ * Negative nice levels get the same granularity as nice-0:
+ */
+ if (likely(curr->load.weight >= NICE_0_LOAD))
+ return granularity;
+ /*
+ * Positive nice level tasks get linearly finer
+ * granularity:
+ */
+ tmp = curr->load.weight * (u64)granularity;
+
+ /*
+ * It will always fit into 'long':
+ */
+ return (long) (tmp >> NICE_0_SHIFT);
+}
+
+static inline void
+limit_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se)
+{
+ long limit = sysctl_sched_runtime_limit;
+
+ /*
+ * Niced tasks have the same history dynamic range as
+ * non-niced tasks:
+ */
+ if (unlikely(se->wait_runtime > limit)) {
+ se->wait_runtime = limit;
+ schedstat_inc(se, wait_runtime_overruns);
+ schedstat_inc(cfs_rq, wait_runtime_overruns);
+ }
+ if (unlikely(se->wait_runtime < -limit)) {
+ se->wait_runtime = -limit;
+ schedstat_inc(se, wait_runtime_underruns);
+ schedstat_inc(cfs_rq, wait_runtime_underruns);
+ }
+}
+
+static inline void
+__add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta)
+{
+ se->wait_runtime += delta;
+ schedstat_add(se, sum_wait_runtime, delta);
+ limit_wait_runtime(cfs_rq, se);
+}
+
+static void
+add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta)
+{
+ schedstat_add(cfs_rq, wait_runtime, -se->wait_runtime);
+ __add_wait_runtime(cfs_rq, se, delta);
+ schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
+}
+
+/*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+ */
+static inline void
+__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr, u64 now)
+{
+ unsigned long delta, delta_exec, delta_fair;
+ long delta_mine;
+ struct load_weight *lw = &cfs_rq->load;
+ unsigned long load = lw->weight;
+
+ if (unlikely(!load))
+ return;
+
+ delta_exec = curr->delta_exec;
+#ifdef CONFIG_SCHEDSTATS
+ if (unlikely(delta_exec > curr->exec_max))
+ curr->exec_max = delta_exec;
+#endif
+
+ curr->sum_exec_runtime += delta_exec;
+ cfs_rq->exec_clock += delta_exec;
+
+ delta_fair = calc_delta_fair(delta_exec, lw);
+ delta_mine = calc_delta_mine(delta_exec, curr->load.weight, lw);
+
+ if (cfs_rq->sleeper_bonus > sysctl_sched_stat_granularity) {
+ delta = calc_delta_mine(cfs_rq->sleeper_bonus,
+ curr->load.weight, lw);
+ if (unlikely(delta > cfs_rq->sleeper_bonus))
+ delta = cfs_rq->sleeper_bonus;
+
+ cfs_rq->sleeper_bonus -= delta;
+ delta_mine -= delta;
+ }
+
+ cfs_rq->fair_clock += delta_fair;
+ /*
+ * We executed delta_exec amount of time on the CPU,
+ * but we were only entitled to delta_mine amount of
+ * time during that period (if nr_running == 1 then
+ * the two values are equal)
+ * [Note: delta_mine - delta_exec is negative]:
+ */
+ add_wait_runtime(cfs_rq, curr, delta_mine - delta_exec);
+}
+
+static void update_curr(struct cfs_rq *cfs_rq, u64 now)
+{
+ struct sched_entity *curr = cfs_rq_curr(cfs_rq);
+ unsigned long delta_exec;
+
+ if (unlikely(!curr))
+ return;
+
+ /*
+ * Get the amount of time the current task was running
+ * since the last time we changed load (this cannot
+ * overflow on 32 bits):
+ */
+ delta_exec = (unsigned long)(now - curr->exec_start);
+
+ curr->delta_exec += delta_exec;
+
+ if (unlikely(curr->delta_exec > sysctl_sched_stat_granularity)) {
+ __update_curr(cfs_rq, curr, now);
+ curr->delta_exec = 0;
+ }
+ curr->exec_start = now;
+}
+
+static inline void
+update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ se->wait_start_fair = cfs_rq->fair_clock;
+ se->wait_start = now;
+}
+
+/*
+ * We calculate fair deltas here, so protect against the random effects
+ * of a multiplication overflow by capping it to the runtime limit:
+ */
+#if BITS_PER_LONG == 32
+static inline unsigned long
+calc_weighted(unsigned long delta, unsigned long weight, int shift)
+{
+ u64 tmp = (u64)delta * weight >> shift;
+
+ if (unlikely(tmp > sysctl_sched_runtime_limit*2))
+ return sysctl_sched_runtime_limit*2;
+ return tmp;
+}
+#else
+static inline unsigned long
+calc_weighted(unsigned long delta, unsigned long weight, int shift)
+{
+ return delta * weight >> shift;
+}
+#endif
+
+/*
+ * Task is being enqueued - update stats:
+ */
+static void
+update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ s64 key;
+
+ /*
+ * Are we enqueueing a waiting task? (for current tasks
+ * a dequeue/enqueue event is a NOP)
+ */
+ if (se != cfs_rq_curr(cfs_rq))
+ update_stats_wait_start(cfs_rq, se, now);
+ /*
+ * Update the key:
+ */
+ key = cfs_rq->fair_clock;
+
+ /*
+ * Optimize the common nice 0 case:
+ */
+ if (likely(se->load.weight == NICE_0_LOAD)) {
+ key -= se->wait_runtime;
+ } else {
+ u64 tmp;
+
+ if (se->wait_runtime < 0) {
+ tmp = -se->wait_runtime;
+ key += (tmp * se->load.inv_weight) >>
+ (WMULT_SHIFT - NICE_0_SHIFT);
+ } else {
+ tmp = se->wait_runtime;
+ key -= (tmp * se->load.weight) >> NICE_0_SHIFT;
+ }
+ }
+
+ se->fair_key = key;
+}
+
+/*
+ * Note: must be called with a freshly updated rq->fair_clock.
+ */
+static inline void
+__update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ unsigned long delta_fair = se->delta_fair_run;
+
+#ifdef CONFIG_SCHEDSTATS
+ {
+ s64 delta_wait = now - se->wait_start;
+ if (unlikely(delta_wait > se->wait_max))
+ se->wait_max = delta_wait;
+ }
+#endif
+
+ if (unlikely(se->load.weight != NICE_0_LOAD))
+ delta_fair = calc_weighted(delta_fair, se->load.weight,
+ NICE_0_SHIFT);
+
+ add_wait_runtime(cfs_rq, se, delta_fair);
+}
+
+static void
+update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ unsigned long delta_fair;
+
+ delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit),
+ (u64)(cfs_rq->fair_clock - se->wait_start_fair));
+
+ se->delta_fair_run += delta_fair;
+ if (unlikely(abs(se->delta_fair_run) >=
+ sysctl_sched_stat_granularity)) {
+ __update_stats_wait_end(cfs_rq, se, now);
+ se->delta_fair_run = 0;
+ }
+
+ se->wait_start_fair = 0;
+ se->wait_start = 0;
+}
+
+static inline void
+update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ update_curr(cfs_rq, now);
+ /*
+ * Mark the end of the wait period if dequeueing a
+ * waiting task:
+ */
+ if (se != cfs_rq_curr(cfs_rq))
+ update_stats_wait_end(cfs_rq, se, now);
+}
+
+/*
+ * We are picking a new current task - update its stats:
+ */
+static inline void
+update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ /*
+ * We are starting a new run period:
+ */
+ se->exec_start = now;
+}
+
+/*
+ * We are descheduling a task - update its stats:
+ */
+static inline void
+update_stats_curr_end(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ se->exec_start = 0;
+}
+
+/**************************************************
+ * Scheduling class queueing methods:
+ */
+
+static void
+__enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ unsigned long load = cfs_rq->load.weight, delta_fair;
+ long prev_runtime;
+
+ if (sysctl_sched_features & SCHED_FEAT_SLEEPER_LOAD_AVG)
+ load = rq_of(cfs_rq)->cpu_load[2];
+
+ delta_fair = se->delta_fair_sleep;
+
+ /*
+ * Fix up delta_fair with the effect of us running
+ * during the whole sleep period:
+ */
+ if (sysctl_sched_features & SCHED_FEAT_SLEEPER_AVG)
+ delta_fair = div64_likely32((u64)delta_fair * load,
+ load + se->load.weight);
+
+ if (unlikely(se->load.weight != NICE_0_LOAD))
+ delta_fair = calc_weighted(delta_fair, se->load.weight,
+ NICE_0_SHIFT);
+
+ prev_runtime = se->wait_runtime;
+ __add_wait_runtime(cfs_rq, se, delta_fair);
+ delta_fair = se->wait_runtime - prev_runtime;
+
+ /*
+ * Track the amount of bonus we've given to sleepers:
+ */
+ cfs_rq->sleeper_bonus += delta_fair;
+
+ schedstat_add(cfs_rq, wait_runtime, se->wait_runtime);
+}
+
+static void
+enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ struct task_struct *tsk = task_of(se);
+ unsigned long delta_fair;
+
+ if ((entity_is_task(se) && tsk->policy == SCHED_BATCH) ||
+ !(sysctl_sched_features & SCHED_FEAT_FAIR_SLEEPERS))
+ return;
+
+ delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit),
+ (u64)(cfs_rq->fair_clock - se->sleep_start_fair));
+
+ se->delta_fair_sleep += delta_fair;
+ if (unlikely(abs(se->delta_fair_sleep) >=
+ sysctl_sched_stat_granularity)) {
+ __enqueue_sleeper(cfs_rq, se, now);
+ se->delta_fair_sleep = 0;
+ }
+
+ se->sleep_start_fair = 0;
+
+#ifdef CONFIG_SCHEDSTATS
+ if (se->sleep_start) {
+ u64 delta = now - se->sleep_start;
+
+ if ((s64)delta < 0)
+ delta = 0;
+
+ if (unlikely(delta > se->sleep_max))
+ se->sleep_max = delta;
+
+ se->sleep_start = 0;
+ se->sum_sleep_runtime += delta;
+ }
+ if (se->block_start) {
+ u64 delta = now - se->block_start;
+
+ if ((s64)delta < 0)
+ delta = 0;
+
+ if (unlikely(delta > se->block_max))
+ se->block_max = delta;
+
+ se->block_start = 0;
+ se->sum_sleep_runtime += delta;
+ }
+#endif
+}
+
+static void
+enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+ int wakeup, u64 now)
+{
+ /*
+ * Update the fair clock.
+ */
+ update_curr(cfs_rq, now);
+
+ if (wakeup)
+ enqueue_sleeper(cfs_rq, se, now);
+
+ update_stats_enqueue(cfs_rq, se, now);
+ __enqueue_entity(cfs_rq, se);
+}
+
+static void
+dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+ int sleep, u64 now)
+{
+ update_stats_dequeue(cfs_rq, se, now);
+ if (sleep) {
+ se->sleep_start_fair = cfs_rq->fair_clock;
+#ifdef CONFIG_SCHEDSTATS
+ if (entity_is_task(se)) {
+ struct task_struct *tsk = task_of(se);
+
+ if (tsk->state & TASK_INTERRUPTIBLE)
+ se->sleep_start = now;
+ if (tsk->state & TASK_UNINTERRUPTIBLE)
+ se->block_start = now;
+ }
+ cfs_rq->wait_runtime -= se->wait_runtime;
+#endif
+ }
+ __dequeue_entity(cfs_rq, se);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void
+__check_preempt_curr_fair(struct cfs_rq *cfs_rq, struct sched_entity *se,
+ struct sched_entity *curr, unsigned long granularity)
+{
+ s64 __delta = curr->fair_key - se->fair_key;
+
+ /*
+ * Take scheduling granularity into account - do not
+ * preempt the current task unless the best task has
+ * a larger than sched_granularity fairness advantage:
+ */
+ if (__delta > niced_granularity(curr, granularity))
+ resched_task(rq_of(cfs_rq)->curr);
+}
+
+static inline void
+set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, u64 now)
+{
+ /*
+ * Any task has to be enqueued before it get to execute on
+ * a CPU. So account for the time it spent waiting on the
+ * runqueue. (note, here we rely on pick_next_task() having
+ * done a put_prev_task_fair() shortly before this, which
+ * updated rq->fair_clock - used by update_stats_wait_end())
+ */
+ update_stats_wait_end(cfs_rq, se, now);
+ update_stats_curr_start(cfs_rq, se, now);
+ set_cfs_rq_curr(cfs_rq, se);
+}
+
+static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq, u64 now)
+{
+ struct sched_entity *se = __pick_next_entity(cfs_rq);
+
+ set_next_entity(cfs_rq, se, now);
+
+ return se;
+}
+
+static void
+put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev, u64 now)
+{
+ /*
+ * If still on the runqueue then deactivate_task()
+ * was not called and update_curr() has to be done:
+ */
+ if (prev->on_rq)
+ update_curr(cfs_rq, now);
+
+ update_stats_curr_end(cfs_rq, prev, now);
+
+ if (prev->on_rq)
+ update_stats_wait_start(cfs_rq, prev, now);
+ set_cfs_rq_curr(cfs_rq, NULL);
+}
+
+static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
+{
+ struct rq *rq = rq_of(cfs_rq);
+ struct sched_entity *next;
+ u64 now = __rq_clock(rq);
+
+ /*
+ * Dequeue and enqueue the task to update its
+ * position within the tree:
+ */
+ dequeue_entity(cfs_rq, curr, 0, now);
+ enqueue_entity(cfs_rq, curr, 0, now);
+
+ /*
+ * Reschedule if another task tops the current one.
+ */
+ next = __pick_next_entity(cfs_rq);
+ if (next == curr)
+ return;
+
+ __check_preempt_curr_fair(cfs_rq, next, curr, sysctl_sched_granularity);
+}
+
+/**************************************************
+ * CFS operations on tasks:
+ */
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+
+/* Walk up scheduling entities hierarchy */
+#define for_each_sched_entity(se) \
+ for (; se; se = se->parent)
+
+static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+{
+ return p->se.cfs_rq;
+}
+
+/* runqueue on which this entity is (to be) queued */
+static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+{
+ return se->cfs_rq;
+}
+
+/* runqueue "owned" by this group */
+static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+{
+ return grp->my_q;
+}
+
+/* Given a group's cfs_rq on one cpu, return its corresponding cfs_rq on
+ * another cpu ('this_cpu')
+ */
+static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+{
+ /* A later patch will take group into account */
+ return &cpu_rq(this_cpu)->cfs;
+}
+
+/* Iterate thr' all leaf cfs_rq's on a runqueue */
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+ list_for_each_entry(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list)
+
+/* Do the two (enqueued) tasks belong to the same group ? */
+static inline int is_same_group(struct task_struct *curr, struct task_struct *p)
+{
+ if (curr->se.cfs_rq == p->se.cfs_rq)
+ return 1;
+
+ return 0;
+}
+
+#else /* CONFIG_FAIR_GROUP_SCHED */
+
+#define for_each_sched_entity(se) \
+ for (; se; se = NULL)
+
+static inline struct cfs_rq *task_cfs_rq(struct task_struct *p)
+{
+ return &task_rq(p)->cfs;
+}
+
+static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
+{
+ struct task_struct *p = task_of(se);
+ struct rq *rq = task_rq(p);
+
+ return &rq->cfs;
+}
+
+/* runqueue "owned" by this group */
+static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp)
+{
+ return NULL;
+}
+
+static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu)
+{
+ return &cpu_rq(this_cpu)->cfs;
+}
+
+#define for_each_leaf_cfs_rq(rq, cfs_rq) \
+ for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL)
+
+static inline int is_same_group(struct task_struct *curr, struct task_struct *p)
+{
+ return 1;
+}
+
+#endif /* CONFIG_FAIR_GROUP_SCHED */
+
+/*
+ * The enqueue_task method is called before nr_running is
+ * increased. Here we update the fair scheduling stats and
+ * then put the task into the rbtree:
+ */
+static void
+enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+ struct cfs_rq *cfs_rq;
+ struct sched_entity *se = &p->se;
+
+ for_each_sched_entity(se) {
+ if (se->on_rq)
+ break;
+ cfs_rq = cfs_rq_of(se);
+ enqueue_entity(cfs_rq, se, wakeup, now);
+ }
+}
+
+/*
+ * The dequeue_task method is called before nr_running is
+ * decreased. We remove the task from the rbtree and
+ * update the fair scheduling stats:
+ */
+static void
+dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+ struct cfs_rq *cfs_rq;
+ struct sched_entity *se = &p->se;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+ dequeue_entity(cfs_rq, se, sleep, now);
+ /* Don't dequeue parent if it has other entities besides us */
+ if (cfs_rq->load.weight)
+ break;
+ }
+}
+
+/*
+ * sched_yield() support is very simple - we dequeue and enqueue
+ */
+static void yield_task_fair(struct rq *rq, struct task_struct *p)
+{
+ struct cfs_rq *cfs_rq = task_cfs_rq(p);
+ u64 now = __rq_clock(rq);
+
+ /*
+ * Dequeue and enqueue the task to update its
+ * position within the tree:
+ */
+ dequeue_entity(cfs_rq, &p->se, 0, now);
+ enqueue_entity(cfs_rq, &p->se, 0, now);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void check_preempt_curr_fair(struct rq *rq, struct task_struct *p)
+{
+ struct task_struct *curr = rq->curr;
+ struct cfs_rq *cfs_rq = task_cfs_rq(curr);
+ unsigned long gran;
+
+ if (unlikely(rt_prio(p->prio))) {
+ update_curr(cfs_rq, rq_clock(rq));
+ resched_task(curr);
+ return;
+ }
+
+ gran = sysctl_sched_wakeup_granularity;
+ /*
+ * Batch tasks prefer throughput over latency:
+ */
+ if (unlikely(p->policy == SCHED_BATCH))
+ gran = sysctl_sched_batch_wakeup_granularity;
+
+ if (is_same_group(curr, p))
+ __check_preempt_curr_fair(cfs_rq, &p->se, &curr->se, gran);
+}
+
+static struct task_struct *pick_next_task_fair(struct rq *rq, u64 now)
+{
+ struct cfs_rq *cfs_rq = &rq->cfs;
+ struct sched_entity *se;
+
+ if (unlikely(!cfs_rq->nr_running))
+ return NULL;
+
+ do {
+ se = pick_next_entity(cfs_rq, now);
+ cfs_rq = group_cfs_rq(se);
+ } while (cfs_rq);
+
+ return task_of(se);
+}
+
+/*
+ * Account for a descheduled task:
+ */
+static void put_prev_task_fair(struct rq *rq, struct task_struct *prev, u64 now)
+{
+ struct sched_entity *se = &prev->se;
+ struct cfs_rq *cfs_rq;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+ put_prev_entity(cfs_rq, se, now);
+ }
+}
+
+/**************************************************
+ * Fair scheduling class load-balancing methods:
+ */
+
+/*
+ * Load-balancing iterator. Note: while the runqueue stays locked
+ * during the whole iteration, the current task might be
+ * dequeued so the iterator has to be dequeue-safe. Here we
+ * achieve that by always pre-iterating before returning
+ * the current task:
+ */
+static inline struct task_struct *
+__load_balance_iterator(struct cfs_rq *cfs_rq, struct rb_node *curr)
+{
+ struct task_struct *p;
+
+ if (!curr)
+ return NULL;
+
+ p = rb_entry(curr, struct task_struct, se.run_node);
+ cfs_rq->rb_load_balance_curr = rb_next(curr);
+
+ return p;
+}
+
+static struct task_struct *load_balance_start_fair(void *arg)
+{
+ struct cfs_rq *cfs_rq = arg;
+
+ return __load_balance_iterator(cfs_rq, first_fair(cfs_rq));
+}
+
+static struct task_struct *load_balance_next_fair(void *arg)
+{
+ struct cfs_rq *cfs_rq = arg;
+
+ return __load_balance_iterator(cfs_rq, cfs_rq->rb_load_balance_curr);
+}
+
+static int cfs_rq_best_prio(struct cfs_rq *cfs_rq)
+{
+ struct sched_entity *curr;
+ struct task_struct *p;
+
+ if (!cfs_rq->nr_running)
+ return MAX_PRIO;
+
+ curr = __pick_next_entity(cfs_rq);
+ p = task_of(curr);
+
+ return p->prio;
+}
+
+static int
+load_balance_fair(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *total_load_moved)
+{
+ struct cfs_rq *busy_cfs_rq;
+ unsigned long load_moved, total_nr_moved = 0, nr_moved;
+ long rem_load_move = max_load_move;
+ struct rq_iterator cfs_rq_iterator;
+
+ cfs_rq_iterator.start = load_balance_start_fair;
+ cfs_rq_iterator.next = load_balance_next_fair;
+
+ for_each_leaf_cfs_rq(busiest, busy_cfs_rq) {
+ struct cfs_rq *this_cfs_rq;
+ long imbalance;
+ unsigned long maxload;
+ int this_best_prio, best_prio, best_prio_seen = 0;
+
+ this_cfs_rq = cpu_cfs_rq(busy_cfs_rq, this_cpu);
+
+ imbalance = busy_cfs_rq->load.weight -
+ this_cfs_rq->load.weight;
+ /* Don't pull if this_cfs_rq has more load than busy_cfs_rq */
+ if (imbalance <= 0)
+ continue;
+
+ /* Don't pull more than imbalance/2 */
+ imbalance /= 2;
+ maxload = min(rem_load_move, imbalance);
+
+ this_best_prio = cfs_rq_best_prio(this_cfs_rq);
+ best_prio = cfs_rq_best_prio(busy_cfs_rq);
+
+ /*
+ * Enable handling of the case where there is more than one task
+ * with the best priority. If the current running task is one
+ * of those with prio==best_prio we know it won't be moved
+ * and therefore it's safe to override the skip (based on load)
+ * of any task we find with that prio.
+ */
+ if (cfs_rq_curr(busy_cfs_rq) == &busiest->curr->se)
+ best_prio_seen = 1;
+
+ /* pass busy_cfs_rq argument into
+ * load_balance_[start|next]_fair iterators
+ */
+ cfs_rq_iterator.arg = busy_cfs_rq;
+ nr_moved = balance_tasks(this_rq, this_cpu, busiest,
+ max_nr_move, maxload, sd, idle, all_pinned,
+ &load_moved, this_best_prio, best_prio,
+ best_prio_seen, &cfs_rq_iterator);
+
+ total_nr_moved += nr_moved;
+ max_nr_move -= nr_moved;
+ rem_load_move -= load_moved;
+
+ if (max_nr_move <= 0 || rem_load_move <= 0)
+ break;
+ }
+
+ *total_load_moved = max_load_move - rem_load_move;
+
+ return total_nr_moved;
+}
+
+/*
+ * scheduler tick hitting a task of our scheduling class:
+ */
+static void task_tick_fair(struct rq *rq, struct task_struct *curr)
+{
+ struct cfs_rq *cfs_rq;
+ struct sched_entity *se = &curr->se;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+ entity_tick(cfs_rq, se);
+ }
+}
+
+/*
+ * Share the fairness runtime between parent and child, thus the
+ * total amount of pressure for CPU stays equal - new tasks
+ * get a chance to run but frequent forkers are not allowed to
+ * monopolize the CPU. Note: the parent runqueue is locked,
+ * the child is not running yet.
+ */
+static void task_new_fair(struct rq *rq, struct task_struct *p)
+{
+ struct cfs_rq *cfs_rq = task_cfs_rq(p);
+ struct sched_entity *se = &p->se;
+ u64 now = rq_clock(rq);
+
+ sched_info_queued(p);
+
+ update_stats_enqueue(cfs_rq, se, now);
+ /*
+ * Child runs first: we let it run before the parent
+ * until it reschedules once. We set up the key so that
+ * it will preempt the parent:
+ */
+ p->se.fair_key = current->se.fair_key -
+ niced_granularity(&rq->curr->se, sysctl_sched_granularity) - 1;
+ /*
+ * The first wait is dominated by the child-runs-first logic,
+ * so do not credit it with that waiting time yet:
+ */
+ if (sysctl_sched_features & SCHED_FEAT_SKIP_INITIAL)
+ p->se.wait_start_fair = 0;
+
+ /*
+ * The statistical average of wait_runtime is about
+ * -granularity/2, so initialize the task with that:
+ */
+ if (sysctl_sched_features & SCHED_FEAT_START_DEBIT)
+ p->se.wait_runtime = -(sysctl_sched_granularity / 2);
+
+ __enqueue_entity(cfs_rq, se);
+ inc_nr_running(p, rq, now);
+}
+
+#ifdef CONFIG_FAIR_GROUP_SCHED
+/* Account for a task changing its policy or group.
+ *
+ * This routine is mostly called to set cfs_rq->curr field when a task
+ * migrates between groups/classes.
+ */
+static void set_curr_task_fair(struct rq *rq)
+{
+ struct task_struct *curr = rq->curr;
+ struct sched_entity *se = &curr->se;
+ u64 now = rq_clock(rq);
+ struct cfs_rq *cfs_rq;
+
+ for_each_sched_entity(se) {
+ cfs_rq = cfs_rq_of(se);
+ set_next_entity(cfs_rq, se, now);
+ }
+}
+#else
+static void set_curr_task_fair(struct rq *rq)
+{
+}
+#endif
+
+/*
+ * All the scheduling class methods:
+ */
+struct sched_class fair_sched_class __read_mostly = {
+ .enqueue_task = enqueue_task_fair,
+ .dequeue_task = dequeue_task_fair,
+ .yield_task = yield_task_fair,
+
+ .check_preempt_curr = check_preempt_curr_fair,
+
+ .pick_next_task = pick_next_task_fair,
+ .put_prev_task = put_prev_task_fair,
+
+ .load_balance = load_balance_fair,
+
+ .set_curr_task = set_curr_task_fair,
+ .task_tick = task_tick_fair,
+ .task_new = task_new_fair,
+};
+
+#ifdef CONFIG_SCHED_DEBUG
+void print_cfs_stats(struct seq_file *m, int cpu, u64 now)
+{
+ struct rq *rq = cpu_rq(cpu);
+ struct cfs_rq *cfs_rq;
+
+ for_each_leaf_cfs_rq(rq, cfs_rq)
+ print_cfs_rq(m, cpu, cfs_rq, now);
+}
+#endif
diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c
new file mode 100644
index 00000000000..41841e741c4
--- /dev/null
+++ b/kernel/sched_idletask.c
@@ -0,0 +1,71 @@
+/*
+ * idle-task scheduling class.
+ *
+ * (NOTE: these are not related to SCHED_IDLE tasks which are
+ * handled in sched_fair.c)
+ */
+
+/*
+ * Idle tasks are unconditionally rescheduled:
+ */
+static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p)
+{
+ resched_task(rq->idle);
+}
+
+static struct task_struct *pick_next_task_idle(struct rq *rq, u64 now)
+{
+ schedstat_inc(rq, sched_goidle);
+
+ return rq->idle;
+}
+
+/*
+ * It is not legal to sleep in the idle task - print a warning
+ * message if some code attempts to do it:
+ */
+static void
+dequeue_task_idle(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+ spin_unlock_irq(&rq->lock);
+ printk(KERN_ERR "bad: scheduling from the idle thread!\n");
+ dump_stack();
+ spin_lock_irq(&rq->lock);
+}
+
+static void put_prev_task_idle(struct rq *rq, struct task_struct *prev, u64 now)
+{
+}
+
+static int
+load_balance_idle(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *total_load_moved)
+{
+ return 0;
+}
+
+static void task_tick_idle(struct rq *rq, struct task_struct *curr)
+{
+}
+
+/*
+ * Simple, special scheduling class for the per-CPU idle tasks:
+ */
+static struct sched_class idle_sched_class __read_mostly = {
+ /* no enqueue/yield_task for idle tasks */
+
+ /* dequeue is not valid, we print a debug message there: */
+ .dequeue_task = dequeue_task_idle,
+
+ .check_preempt_curr = check_preempt_curr_idle,
+
+ .pick_next_task = pick_next_task_idle,
+ .put_prev_task = put_prev_task_idle,
+
+ .load_balance = load_balance_idle,
+
+ .task_tick = task_tick_idle,
+ /* no .task_new for idle tasks */
+};
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
new file mode 100644
index 00000000000..1192a2741b9
--- /dev/null
+++ b/kernel/sched_rt.c
@@ -0,0 +1,255 @@
+/*
+ * Real-Time Scheduling Class (mapped to the SCHED_FIFO and SCHED_RR
+ * policies)
+ */
+
+/*
+ * Update the current task's runtime statistics. Skip current tasks that
+ * are not in our scheduling class.
+ */
+static inline void update_curr_rt(struct rq *rq, u64 now)
+{
+ struct task_struct *curr = rq->curr;
+ u64 delta_exec;
+
+ if (!task_has_rt_policy(curr))
+ return;
+
+ delta_exec = now - curr->se.exec_start;
+ if (unlikely((s64)delta_exec < 0))
+ delta_exec = 0;
+ if (unlikely(delta_exec > curr->se.exec_max))
+ curr->se.exec_max = delta_exec;
+
+ curr->se.sum_exec_runtime += delta_exec;
+ curr->se.exec_start = now;
+}
+
+static void
+enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup, u64 now)
+{
+ struct rt_prio_array *array = &rq->rt.active;
+
+ list_add_tail(&p->run_list, array->queue + p->prio);
+ __set_bit(p->prio, array->bitmap);
+}
+
+/*
+ * Adding/removing a task to/from a priority array:
+ */
+static void
+dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep, u64 now)
+{
+ struct rt_prio_array *array = &rq->rt.active;
+
+ update_curr_rt(rq, now);
+
+ list_del(&p->run_list);
+ if (list_empty(array->queue + p->prio))
+ __clear_bit(p->prio, array->bitmap);
+}
+
+/*
+ * Put task to the end of the run list without the overhead of dequeue
+ * followed by enqueue.
+ */
+static void requeue_task_rt(struct rq *rq, struct task_struct *p)
+{
+ struct rt_prio_array *array = &rq->rt.active;
+
+ list_move_tail(&p->run_list, array->queue + p->prio);
+}
+
+static void
+yield_task_rt(struct rq *rq, struct task_struct *p)
+{
+ requeue_task_rt(rq, p);
+}
+
+/*
+ * Preempt the current task with a newly woken task if needed:
+ */
+static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p)
+{
+ if (p->prio < rq->curr->prio)
+ resched_task(rq->curr);
+}
+
+static struct task_struct *pick_next_task_rt(struct rq *rq, u64 now)
+{
+ struct rt_prio_array *array = &rq->rt.active;
+ struct task_struct *next;
+ struct list_head *queue;
+ int idx;
+
+ idx = sched_find_first_bit(array->bitmap);
+ if (idx >= MAX_RT_PRIO)
+ return NULL;
+
+ queue = array->queue + idx;
+ next = list_entry(queue->next, struct task_struct, run_list);
+
+ next->se.exec_start = now;
+
+ return next;
+}
+
+static void put_prev_task_rt(struct rq *rq, struct task_struct *p, u64 now)
+{
+ update_curr_rt(rq, now);
+ p->se.exec_start = 0;
+}
+
+/*
+ * Load-balancing iterator. Note: while the runqueue stays locked
+ * during the whole iteration, the current task might be
+ * dequeued so the iterator has to be dequeue-safe. Here we
+ * achieve that by always pre-iterating before returning
+ * the current task:
+ */
+static struct task_struct *load_balance_start_rt(void *arg)
+{
+ struct rq *rq = arg;
+ struct rt_prio_array *array = &rq->rt.active;
+ struct list_head *head, *curr;
+ struct task_struct *p;
+ int idx;
+
+ idx = sched_find_first_bit(array->bitmap);
+ if (idx >= MAX_RT_PRIO)
+ return NULL;
+
+ head = array->queue + idx;
+ curr = head->prev;
+
+ p = list_entry(curr, struct task_struct, run_list);
+
+ curr = curr->prev;
+
+ rq->rt.rt_load_balance_idx = idx;
+ rq->rt.rt_load_balance_head = head;
+ rq->rt.rt_load_balance_curr = curr;
+
+ return p;
+}
+
+static struct task_struct *load_balance_next_rt(void *arg)
+{
+ struct rq *rq = arg;
+ struct rt_prio_array *array = &rq->rt.active;
+ struct list_head *head, *curr;
+ struct task_struct *p;
+ int idx;
+
+ idx = rq->rt.rt_load_balance_idx;
+ head = rq->rt.rt_load_balance_head;
+ curr = rq->rt.rt_load_balance_curr;
+
+ /*
+ * If we arrived back to the head again then
+ * iterate to the next queue (if any):
+ */
+ if (unlikely(head == curr)) {
+ int next_idx = find_next_bit(array->bitmap, MAX_RT_PRIO, idx+1);
+
+ if (next_idx >= MAX_RT_PRIO)
+ return NULL;
+
+ idx = next_idx;
+ head = array->queue + idx;
+ curr = head->prev;
+
+ rq->rt.rt_load_balance_idx = idx;
+ rq->rt.rt_load_balance_head = head;
+ }
+
+ p = list_entry(curr, struct task_struct, run_list);
+
+ curr = curr->prev;
+
+ rq->rt.rt_load_balance_curr = curr;
+
+ return p;
+}
+
+static int
+load_balance_rt(struct rq *this_rq, int this_cpu, struct rq *busiest,
+ unsigned long max_nr_move, unsigned long max_load_move,
+ struct sched_domain *sd, enum cpu_idle_type idle,
+ int *all_pinned, unsigned long *load_moved)
+{
+ int this_best_prio, best_prio, best_prio_seen = 0;
+ int nr_moved;
+ struct rq_iterator rt_rq_iterator;
+
+ best_prio = sched_find_first_bit(busiest->rt.active.bitmap);
+ this_best_prio = sched_find_first_bit(this_rq->rt.active.bitmap);
+
+ /*
+ * Enable handling of the case where there is more than one task
+ * with the best priority. If the current running task is one
+ * of those with prio==best_prio we know it won't be moved
+ * and therefore it's safe to override the skip (based on load)
+ * of any task we find with that prio.
+ */
+ if (busiest->curr->prio == best_prio)
+ best_prio_seen = 1;
+
+ rt_rq_iterator.start = load_balance_start_rt;
+ rt_rq_iterator.next = load_balance_next_rt;
+ /* pass 'busiest' rq argument into
+ * load_balance_[start|next]_rt iterators
+ */
+ rt_rq_iterator.arg = busiest;
+
+ nr_moved = balance_tasks(this_rq, this_cpu, busiest, max_nr_move,
+ max_load_move, sd, idle, all_pinned, load_moved,
+ this_best_prio, best_prio, best_prio_seen,
+ &rt_rq_iterator);
+
+ return nr_moved;
+}
+
+static void task_tick_rt(struct rq *rq, struct task_struct *p)
+{
+ /*
+ * RR tasks need a special form of timeslice management.
+ * FIFO tasks have no timeslices.
+ */
+ if (p->policy != SCHED_RR)
+ return;
+
+ if (--p->time_slice)
+ return;
+
+ p->time_slice = static_prio_timeslice(p->static_prio);
+ set_tsk_need_resched(p);
+
+ /* put it at the end of the queue: */
+ requeue_task_rt(rq, p);
+}
+
+/*
+ * No parent/child timeslice management necessary for RT tasks,
+ * just activate them:
+ */
+static void task_new_rt(struct rq *rq, struct task_struct *p)
+{
+ activate_task(rq, p, 1);
+}
+
+static struct sched_class rt_sched_class __read_mostly = {
+ .enqueue_task = enqueue_task_rt,
+ .dequeue_task = dequeue_task_rt,
+ .yield_task = yield_task_rt,
+
+ .check_preempt_curr = check_preempt_curr_rt,
+
+ .pick_next_task = pick_next_task_rt,
+ .put_prev_task = put_prev_task_rt,
+
+ .load_balance = load_balance_rt,
+
+ .task_tick = task_tick_rt,
+ .task_new = task_new_rt,
+};
diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h
new file mode 100644
index 00000000000..c63c38f6fa6
--- /dev/null
+++ b/kernel/sched_stats.h
@@ -0,0 +1,235 @@
+
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * bump this up when changing the output format or the meaning of an existing
+ * format, so that tools can adapt (or abort)
+ */
+#define SCHEDSTAT_VERSION 14
+
+static int show_schedstat(struct seq_file *seq, void *v)
+{
+ int cpu;
+
+ seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+ seq_printf(seq, "timestamp %lu\n", jiffies);
+ for_each_online_cpu(cpu) {
+ struct rq *rq = cpu_rq(cpu);
+#ifdef CONFIG_SMP
+ struct sched_domain *sd;
+ int dcnt = 0;
+#endif
+
+ /* runqueue-specific stats */
+ seq_printf(seq,
+ "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %llu %llu %lu",
+ cpu, rq->yld_both_empty,
+ rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt,
+ rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
+ rq->ttwu_cnt, rq->ttwu_local,
+ rq->rq_sched_info.cpu_time,
+ rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
+
+ seq_printf(seq, "\n");
+
+#ifdef CONFIG_SMP
+ /* domain-specific stats */
+ preempt_disable();
+ for_each_domain(cpu, sd) {
+ enum cpu_idle_type itype;
+ char mask_str[NR_CPUS];
+
+ cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
+ seq_printf(seq, "domain%d %s", dcnt++, mask_str);
+ for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES;
+ itype++) {
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu "
+ "%lu",
+ sd->lb_cnt[itype],
+ sd->lb_balanced[itype],
+ sd->lb_failed[itype],
+ sd->lb_imbalance[itype],
+ sd->lb_gained[itype],
+ sd->lb_hot_gained[itype],
+ sd->lb_nobusyq[itype],
+ sd->lb_nobusyg[itype]);
+ }
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu"
+ " %lu %lu %lu\n",
+ sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
+ sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
+ sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
+ sd->ttwu_wake_remote, sd->ttwu_move_affine,
+ sd->ttwu_move_balance);
+ }
+ preempt_enable();
+#endif
+ }
+ return 0;
+}
+
+static int schedstat_open(struct inode *inode, struct file *file)
+{
+ unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
+ char *buf = kmalloc(size, GFP_KERNEL);
+ struct seq_file *m;
+ int res;
+
+ if (!buf)
+ return -ENOMEM;
+ res = single_open(file, show_schedstat, NULL);
+ if (!res) {
+ m = file->private_data;
+ m->buf = buf;
+ m->size = size;
+ } else
+ kfree(buf);
+ return res;
+}
+
+const struct file_operations proc_schedstat_operations = {
+ .open = schedstat_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+/*
+ * Expects runqueue lock to be held for atomicity of update
+ */
+static inline void
+rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
+{
+ if (rq) {
+ rq->rq_sched_info.run_delay += delta;
+ rq->rq_sched_info.pcnt++;
+ }
+}
+
+/*
+ * Expects runqueue lock to be held for atomicity of update
+ */
+static inline void
+rq_sched_info_depart(struct rq *rq, unsigned long long delta)
+{
+ if (rq)
+ rq->rq_sched_info.cpu_time += delta;
+}
+# define schedstat_inc(rq, field) do { (rq)->field++; } while (0)
+# define schedstat_add(rq, field, amt) do { (rq)->field += (amt); } while (0)
+#else /* !CONFIG_SCHEDSTATS */
+static inline void
+rq_sched_info_arrive(struct rq *rq, unsigned long long delta)
+{}
+static inline void
+rq_sched_info_depart(struct rq *rq, unsigned long long delta)
+{}
+# define schedstat_inc(rq, field) do { } while (0)
+# define schedstat_add(rq, field, amt) do { } while (0)
+#endif
+
+#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
+/*
+ * Called when a process is dequeued from the active array and given
+ * the cpu. We should note that with the exception of interactive
+ * tasks, the expired queue will become the active queue after the active
+ * queue is empty, without explicitly dequeuing and requeuing tasks in the
+ * expired queue. (Interactive tasks may be requeued directly to the
+ * active queue, thus delaying tasks in the expired queue from running;
+ * see scheduler_tick()).
+ *
+ * This function is only called from sched_info_arrive(), rather than
+ * dequeue_task(). Even though a task may be queued and dequeued multiple
+ * times as it is shuffled about, we're really interested in knowing how
+ * long it was from the *first* time it was queued to the time that it
+ * finally hit a cpu.
+ */
+static inline void sched_info_dequeued(struct task_struct *t)
+{
+ t->sched_info.last_queued = 0;
+}
+
+/*
+ * Called when a task finally hits the cpu. We can now calculate how
+ * long it was waiting to run. We also note when it began so that we
+ * can keep stats on how long its timeslice is.
+ */
+static void sched_info_arrive(struct task_struct *t)
+{
+ unsigned long long now = sched_clock(), delta = 0;
+
+ if (t->sched_info.last_queued)
+ delta = now - t->sched_info.last_queued;
+ sched_info_dequeued(t);
+ t->sched_info.run_delay += delta;
+ t->sched_info.last_arrival = now;
+ t->sched_info.pcnt++;
+
+ rq_sched_info_arrive(task_rq(t), delta);
+}
+
+/*
+ * Called when a process is queued into either the active or expired
+ * array. The time is noted and later used to determine how long we
+ * had to wait for us to reach the cpu. Since the expired queue will
+ * become the active queue after active queue is empty, without dequeuing
+ * and requeuing any tasks, we are interested in queuing to either. It
+ * is unusual but not impossible for tasks to be dequeued and immediately
+ * requeued in the same or another array: this can happen in sched_yield(),
+ * set_user_nice(), and even load_balance() as it moves tasks from runqueue
+ * to runqueue.
+ *
+ * This function is only called from enqueue_task(), but also only updates
+ * the timestamp if it is already not set. It's assumed that
+ * sched_info_dequeued() will clear that stamp when appropriate.
+ */
+static inline void sched_info_queued(struct task_struct *t)
+{
+ if (unlikely(sched_info_on()))
+ if (!t->sched_info.last_queued)
+ t->sched_info.last_queued = sched_clock();
+}
+
+/*
+ * Called when a process ceases being the active-running process, either
+ * voluntarily or involuntarily. Now we can calculate how long we ran.
+ */
+static inline void sched_info_depart(struct task_struct *t)
+{
+ unsigned long long delta = sched_clock() - t->sched_info.last_arrival;
+
+ t->sched_info.cpu_time += delta;
+ rq_sched_info_depart(task_rq(t), delta);
+}
+
+/*
+ * Called when tasks are switched involuntarily due, typically, to expiring
+ * their time slice. (This may also be called when switching to or from
+ * the idle task.) We are only called when prev != next.
+ */
+static inline void
+__sched_info_switch(struct task_struct *prev, struct task_struct *next)
+{
+ struct rq *rq = task_rq(prev);
+
+ /*
+ * prev now departs the cpu. It's not interesting to record
+ * stats about how efficient we were at scheduling the idle
+ * process, however.
+ */
+ if (prev != rq->idle)
+ sched_info_depart(prev);
+
+ if (next != rq->idle)
+ sched_info_arrive(next);
+}
+static inline void
+sched_info_switch(struct task_struct *prev, struct task_struct *next)
+{
+ if (unlikely(sched_info_on()))
+ __sched_info_switch(prev, next);
+}
+#else
+#define sched_info_queued(t) do { } while (0)
+#define sched_info_switch(t, next) do { } while (0)
+#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */
+
diff --git a/kernel/signal.c b/kernel/signal.c
index acdfc0549c6..f9405609774 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -105,7 +105,11 @@ static int recalc_sigpending_tsk(struct task_struct *t)
set_tsk_thread_flag(t, TIF_SIGPENDING);
return 1;
}
- clear_tsk_thread_flag(t, TIF_SIGPENDING);
+ /*
+ * We must never clear the flag in another thread, or in current
+ * when it's possible the current syscall is returning -ERESTART*.
+ * So we don't clear it here, and only callers who know they should do.
+ */
return 0;
}
@@ -121,7 +125,9 @@ void recalc_sigpending_and_wake(struct task_struct *t)
void recalc_sigpending(void)
{
- recalc_sigpending_tsk(current);
+ if (!recalc_sigpending_tsk(current))
+ clear_thread_flag(TIF_SIGPENDING);
+
}
/* Given the mask, find the first available signal that should be serviced. */
@@ -357,7 +363,13 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
*/
int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
{
- int signr = __dequeue_signal(&tsk->pending, mask, info);
+ int signr = 0;
+
+ /* We only dequeue private signals from ourselves, we don't let
+ * signalfd steal them
+ */
+ if (tsk == current)
+ signr = __dequeue_signal(&tsk->pending, mask, info);
if (!signr) {
signr = __dequeue_signal(&tsk->signal->shared_pending,
mask, info);
@@ -385,7 +397,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
}
}
}
- recalc_sigpending_tsk(tsk);
+ if (likely(tsk == current))
+ recalc_sigpending();
if (signr && unlikely(sig_kernel_stop(signr))) {
/*
* Set a marker that we have dequeued a stop signal. Our
@@ -1580,8 +1593,9 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info)
/*
* Queued signals ignored us while we were stopped for tracing.
* So check for any that we should take before resuming user mode.
+ * This sets TIF_SIGPENDING, but never clears it.
*/
- recalc_sigpending();
+ recalc_sigpending_tsk(current);
}
void ptrace_notify(int exit_code)
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 0b9886a00e7..73217a9e287 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -488,7 +488,6 @@ void __init softirq_init(void)
static int ksoftirqd(void * __bind_cpu)
{
- set_user_nice(current, 19);
current->flags |= PF_NOFREEZE;
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 30ee462ee79..d93e13d93f2 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -206,7 +206,87 @@ static ctl_table root_table[] = {
{ .ctl_name = 0 }
};
+#ifdef CONFIG_SCHED_DEBUG
+static unsigned long min_sched_granularity_ns = 100000; /* 100 usecs */
+static unsigned long max_sched_granularity_ns = 1000000000; /* 1 second */
+static unsigned long min_wakeup_granularity_ns; /* 0 usecs */
+static unsigned long max_wakeup_granularity_ns = 1000000000; /* 1 second */
+#endif
+
static ctl_table kern_table[] = {
+#ifdef CONFIG_SCHED_DEBUG
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_granularity_ns",
+ .data = &sysctl_sched_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_sched_granularity_ns,
+ .extra2 = &max_sched_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_wakeup_granularity_ns",
+ .data = &sysctl_sched_wakeup_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_wakeup_granularity_ns,
+ .extra2 = &max_wakeup_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_batch_wakeup_granularity_ns",
+ .data = &sysctl_sched_batch_wakeup_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_wakeup_granularity_ns,
+ .extra2 = &max_wakeup_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_stat_granularity_ns",
+ .data = &sysctl_sched_stat_granularity,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_wakeup_granularity_ns,
+ .extra2 = &max_wakeup_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_runtime_limit_ns",
+ .data = &sysctl_sched_runtime_limit,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_minmax,
+ .strategy = &sysctl_intvec,
+ .extra1 = &min_sched_granularity_ns,
+ .extra2 = &max_sched_granularity_ns,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_child_runs_first",
+ .data = &sysctl_sched_child_runs_first,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "sched_features",
+ .data = &sysctl_sched_features,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+#endif
{
.ctl_name = KERN_PANIC,
.procname = "panic",
@@ -869,6 +949,16 @@ static ctl_table vm_table[] = {
.strategy = &sysctl_jiffies,
},
#endif
+#ifdef CONFIG_SECURITY
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "mmap_min_addr",
+ .data = &mmap_min_addr,
+ .maxlen = sizeof(unsigned long),
+ .mode = 0644,
+ .proc_handler = &proc_doulongvec_minmax,
+ },
+#endif
#if defined(CONFIG_X86_32) || \
(defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
{
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 87aa5ff931e..cf53bb5814c 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -122,7 +122,6 @@ void second_overflow(void)
*/
time_interpolator_update(-NSEC_PER_SEC);
time_state = TIME_OOP;
- clock_was_set();
printk(KERN_NOTICE "Clock: inserting leap second "
"23:59:60 UTC\n");
}
@@ -137,7 +136,6 @@ void second_overflow(void)
*/
time_interpolator_update(NSEC_PER_SEC);
time_state = TIME_WAIT;
- clock_was_set();
printk(KERN_NOTICE "Clock: deleting leap second "
"23:59:59 UTC\n");
}
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
index 868f1bceb07..321693724ad 100644
--- a/kernel/time/timer_stats.c
+++ b/kernel/time/timer_stats.c
@@ -117,21 +117,6 @@ static struct entry entries[MAX_ENTRIES];
static atomic_t overflow_count;
-static void reset_entries(void)
-{
- nr_entries = 0;
- memset(entries, 0, sizeof(entries));
- atomic_set(&overflow_count, 0);
-}
-
-static struct entry *alloc_entry(void)
-{
- if (nr_entries >= MAX_ENTRIES)
- return NULL;
-
- return entries + nr_entries++;
-}
-
/*
* The entries are in a hash-table, for fast lookup:
*/
@@ -149,6 +134,22 @@ static struct entry *alloc_entry(void)
static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly;
+static void reset_entries(void)
+{
+ nr_entries = 0;
+ memset(entries, 0, sizeof(entries));
+ memset(tstat_hash_table, 0, sizeof(tstat_hash_table));
+ atomic_set(&overflow_count, 0);
+}
+
+static struct entry *alloc_entry(void)
+{
+ if (nr_entries >= MAX_ENTRIES)
+ return NULL;
+
+ return entries + nr_entries++;
+}
+
static int match_entries(struct entry *entry1, struct entry *entry2)
{
return entry1->timer == entry2->timer &&
@@ -202,12 +203,15 @@ static struct entry *tstat_lookup(struct entry *entry, char *comm)
if (curr) {
*curr = *entry;
curr->count = 0;
+ curr->next = NULL;
memcpy(curr->comm, comm, TASK_COMM_LEN);
+
+ smp_mb(); /* Ensure that curr is initialized before insert */
+
if (prev)
prev->next = curr;
else
*head = curr;
- curr->next = NULL;
}
out_unlock:
spin_unlock(&table_lock);
@@ -232,10 +236,15 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
/*
* It doesnt matter which lock we take:
*/
- spinlock_t *lock = &per_cpu(lookup_lock, raw_smp_processor_id());
+ spinlock_t *lock;
struct entry *entry, input;
unsigned long flags;
+ if (likely(!active))
+ return;
+
+ lock = &per_cpu(lookup_lock, raw_smp_processor_id());
+
input.timer = timer;
input.start_func = startf;
input.expire_func = timerf;
@@ -360,6 +369,7 @@ static ssize_t tstats_write(struct file *file, const char __user *buf,
if (!active) {
reset_entries();
time_start = ktime_get();
+ smp_mb();
active = 1;
}
break;
diff --git a/lib/Kconfig b/lib/Kconfig
index 2e7ae6b9215..3eb29d5dc4f 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -64,6 +64,12 @@ config ZLIB_INFLATE
config ZLIB_DEFLATE
tristate
+config LZO_COMPRESS
+ tristate
+
+config LZO_DECOMPRESS
+ tristate
+
#
# Generic allocator support is selected if needed
#
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1ba77ca7d16..fab32a28637 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -105,6 +105,15 @@ config DETECT_SOFTLOCKUP
can be detected via the NMI-watchdog, on platforms that
support it.)
+config SCHED_DEBUG
+ bool "Collect scheduler debugging info"
+ depends on DEBUG_KERNEL && PROC_FS
+ default y
+ help
+ If you say Y here, the /proc/sched_debug file will be provided
+ that can help debug the scheduler. The runtime overhead of this
+ option is minimal.
+
config SCHEDSTATS
bool "Collect scheduler statistics"
depends on DEBUG_KERNEL && PROC_FS
@@ -126,7 +135,10 @@ config TIMER_STATS
reprogrammed. The statistics can be read from /proc/timer_stats.
The statistics collection is started by writing 1 to /proc/timer_stats,
writing 0 stops it. This feature is useful to collect information
- about timer usage patterns in kernel and userspace.
+ about timer usage patterns in kernel and userspace. This feature
+ is lightweight if enabled in the kernel config but not activated
+ (it defaults to deactivated on bootup and will only be activated
+ if some application like powertop activates it explicitly).
config DEBUG_SLAB
bool "Debug slab memory allocations"
diff --git a/lib/Makefile b/lib/Makefile
index c8c8e20784c..d1b366bdf86 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -49,6 +49,8 @@ obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
+obj-$(CONFIG_LZO_COMPRESS) += lzo/
+obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
obj-$(CONFIG_TEXTSEARCH) += textsearch.o
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
diff --git a/lib/hexdump.c b/lib/hexdump.c
index e6da5b7fc29..473f5aed6ca 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -16,42 +16,98 @@
* hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
* @buf: data blob to dump
* @len: number of bytes in the @buf
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @linebuf: where to put the converted data
* @linebuflen: total size of @linebuf, including space for terminating NUL
+ * @ascii: include ASCII after the hex output
*
* hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
- * 16 bytes of input data converted to hex + ASCII output.
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
*
* Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
* to a hex + ASCII dump at the supplied memory location.
* The converted output is always NUL-terminated.
*
* E.g.:
- * hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf));
+ * hex_dump_to_buffer(frame->data, frame->len, 16, 1,
+ * linebuf, sizeof(linebuf), 1);
*
* example output buffer:
- * 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
+ * 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
*/
-void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
- size_t linebuflen)
+void hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
+ int groupsize, char *linebuf, size_t linebuflen,
+ bool ascii)
{
const u8 *ptr = buf;
u8 ch;
int j, lx = 0;
+ int ascii_column;
- for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) {
- if (j && !(j % 4))
+ if (rowsize != 16 && rowsize != 32)
+ rowsize = 16;
+
+ if (!len)
+ goto nil;
+ if (len > rowsize) /* limit to one line at a time */
+ len = rowsize;
+ if ((len % groupsize) != 0) /* no mixed size output */
+ groupsize = 1;
+
+ switch (groupsize) {
+ case 8: {
+ const u64 *ptr8 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%16.16llx ", (unsigned long long)*(ptr8 + j));
+ ascii_column = 17 * ngroups + 2;
+ break;
+ }
+
+ case 4: {
+ const u32 *ptr4 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%8.8x ", *(ptr4 + j));
+ ascii_column = 9 * ngroups + 2;
+ break;
+ }
+
+ case 2: {
+ const u16 *ptr2 = buf;
+ int ngroups = len / groupsize;
+
+ for (j = 0; j < ngroups; j++)
+ lx += scnprintf(linebuf + lx, linebuflen - lx,
+ "%4.4x ", *(ptr2 + j));
+ ascii_column = 5 * ngroups + 2;
+ break;
+ }
+
+ default:
+ for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen;
+ j++) {
+ ch = ptr[j];
+ linebuf[lx++] = hex_asc(ch >> 4);
+ linebuf[lx++] = hex_asc(ch & 0x0f);
linebuf[lx++] = ' ';
- ch = ptr[j];
- linebuf[lx++] = hex_asc(ch >> 4);
- linebuf[lx++] = hex_asc(ch & 0x0f);
+ }
+ ascii_column = 3 * rowsize + 2;
+ break;
}
- if ((lx + 2) < linebuflen) {
- linebuf[lx++] = ' ';
+ if (!ascii)
+ goto nil;
+
+ while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
linebuf[lx++] = ' ';
- }
- for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++)
+ for (j = 0; (j < rowsize) && (j < len) && (lx + 2) < linebuflen; j++)
linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
+nil:
linebuf[lx++] = '\0';
}
EXPORT_SYMBOL(hex_dump_to_buffer);
@@ -59,46 +115,83 @@ EXPORT_SYMBOL(hex_dump_to_buffer);
/**
* print_hex_dump - print a text hex dump to syslog for a binary blob of data
* @level: kernel log level (e.g. KERN_DEBUG)
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
* @prefix_type: controls whether prefix of an offset, address, or none
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @rowsize: number of bytes to print per line; must be 16 or 32
+ * @groupsize: number of bytes to print at a time (1, 2, 4, 8; default = 1)
* @buf: data blob to dump
* @len: number of bytes in the @buf
+ * @ascii: include ASCII after the hex output
*
* Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
* to the kernel log at the specified kernel log level, with an optional
* leading prefix.
*
+ * print_hex_dump() works on one "line" of output at a time, i.e.,
+ * 16 or 32 bytes of input data converted to hex + ASCII output.
+ * print_hex_dump() iterates over the entire input @buf, breaking it into
+ * "line size" chunks to format and print.
+ *
* E.g.:
- * print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
+ * print_hex_dump(KERN_DEBUG, "raw data: ", DUMP_PREFIX_ADDRESS,
+ * 16, 1, frame->data, frame->len, 1);
*
- * Example output using %DUMP_PREFIX_OFFSET:
- * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f @ABCDEFGHIJKLMNO
- * Example output using %DUMP_PREFIX_ADDRESS:
- * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f pqrstuvwxyz{|}~.
+ * Example output using %DUMP_PREFIX_OFFSET and 1-byte mode:
+ * 0009ab42: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS and 4-byte mode:
+ * ffffffff88089af0: 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.
*/
-void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len)
+void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
+ int rowsize, int groupsize,
+ void *buf, size_t len, bool ascii)
{
u8 *ptr = buf;
int i, linelen, remaining = len;
- unsigned char linebuf[100];
+ unsigned char linebuf[200];
- for (i = 0; i < len; i += 16) {
- linelen = min(remaining, 16);
- remaining -= 16;
- hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf));
+ if (rowsize != 16 && rowsize != 32)
+ rowsize = 16;
+
+ for (i = 0; i < len; i += rowsize) {
+ linelen = min(remaining, rowsize);
+ remaining -= rowsize;
+ hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
+ linebuf, sizeof(linebuf), ascii);
switch (prefix_type) {
case DUMP_PREFIX_ADDRESS:
- printk("%s%*p: %s\n", level,
+ printk("%s%s%*p: %s\n", level, prefix_str,
(int)(2 * sizeof(void *)), ptr + i, linebuf);
break;
case DUMP_PREFIX_OFFSET:
- printk("%s%.8x: %s\n", level, i, linebuf);
+ printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
break;
default:
- printk("%s%s\n", level, linebuf);
+ printk("%s%s%s\n", level, prefix_str, linebuf);
break;
}
}
}
EXPORT_SYMBOL(print_hex_dump);
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), with log level of KERN_DEBUG,
+ * rowsize of 16, groupsize of 1, and ASCII output included.
+ */
+void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
+ void *buf, size_t len)
+{
+ print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
+ buf, len, 1);
+}
+EXPORT_SYMBOL(print_hex_dump_bytes);
diff --git a/lib/idr.c b/lib/idr.c
index 305117ca2d4..b98f01a2eb9 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -70,6 +70,26 @@ static void free_layer(struct idr *idp, struct idr_layer *p)
spin_unlock_irqrestore(&idp->lock, flags);
}
+static void idr_mark_full(struct idr_layer **pa, int id)
+{
+ struct idr_layer *p = pa[0];
+ int l = 0;
+
+ __set_bit(id & IDR_MASK, &p->bitmap);
+ /*
+ * If this layer is full mark the bit in the layer above to
+ * show that this part of the radix tree is full. This may
+ * complete the layer above and require walking up the radix
+ * tree.
+ */
+ while (p->bitmap == IDR_FULL) {
+ if (!(p = pa[++l]))
+ break;
+ id = id >> IDR_BITS;
+ __set_bit((id & IDR_MASK), &p->bitmap);
+ }
+}
+
/**
* idr_pre_get - reserver resources for idr allocation
* @idp: idr handle
@@ -95,15 +115,15 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
}
EXPORT_SYMBOL(idr_pre_get);
-static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
+static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
{
int n, m, sh;
struct idr_layer *p, *new;
- struct idr_layer *pa[MAX_LEVEL];
- int l, id;
+ int l, id, oid;
long bm;
id = *starting_id;
+ restart:
p = idp->top;
l = idp->layers;
pa[l--] = NULL;
@@ -117,12 +137,23 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
if (m == IDR_SIZE) {
/* no space available go back to previous layer. */
l++;
+ oid = id;
id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
+
+ /* if already at the top layer, we need to grow */
if (!(p = pa[l])) {
*starting_id = id;
return -2;
}
- continue;
+
+ /* If we need to go up one layer, continue the
+ * loop; otherwise, restart from the top.
+ */
+ sh = IDR_BITS * (l + 1);
+ if (oid >> sh == id >> sh)
+ continue;
+ else
+ goto restart;
}
if (m != n) {
sh = IDR_BITS*l;
@@ -144,30 +175,13 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
pa[l--] = p;
p = p->ary[m];
}
- /*
- * We have reached the leaf node, plant the
- * users pointer and return the raw id.
- */
- p->ary[m] = (struct idr_layer *)ptr;
- __set_bit(m, &p->bitmap);
- p->count++;
- /*
- * If this layer is full mark the bit in the layer above
- * to show that this part of the radix tree is full.
- * This may complete the layer above and require walking
- * up the radix tree.
- */
- n = id;
- while (p->bitmap == IDR_FULL) {
- if (!(p = pa[++l]))
- break;
- n = n >> IDR_BITS;
- __set_bit((n & IDR_MASK), &p->bitmap);
- }
- return(id);
+
+ pa[l] = p;
+ return id;
}
-static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+static int idr_get_empty_slot(struct idr *idp, int starting_id,
+ struct idr_layer **pa)
{
struct idr_layer *p, *new;
int layers, v, id;
@@ -213,12 +227,31 @@ build_up:
}
idp->top = p;
idp->layers = layers;
- v = sub_alloc(idp, ptr, &id);
+ v = sub_alloc(idp, &id, pa);
if (v == -2)
goto build_up;
return(v);
}
+static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
+{
+ struct idr_layer *pa[MAX_LEVEL];
+ int id;
+
+ id = idr_get_empty_slot(idp, starting_id, pa);
+ if (id >= 0) {
+ /*
+ * Successfully found an empty slot. Install the user
+ * pointer and mark the slot full.
+ */
+ pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
+ pa[0]->count++;
+ idr_mark_full(pa, id);
+ }
+
+ return id;
+}
+
/**
* idr_get_new_above - allocate new idr entry above or equal to a start id
* @idp: idr handle
@@ -473,3 +506,248 @@ void idr_init(struct idr *idp)
spin_lock_init(&idp->lock);
}
EXPORT_SYMBOL(idr_init);
+
+
+/*
+ * IDA - IDR based ID allocator
+ *
+ * this is id allocator without id -> pointer translation. Memory
+ * usage is much lower than full blown idr because each id only
+ * occupies a bit. ida uses a custom leaf node which contains
+ * IDA_BITMAP_BITS slots.
+ *
+ * 2007-04-25 written by Tejun Heo <htejun@gmail.com>
+ */
+
+static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
+{
+ unsigned long flags;
+
+ if (!ida->free_bitmap) {
+ spin_lock_irqsave(&ida->idr.lock, flags);
+ if (!ida->free_bitmap) {
+ ida->free_bitmap = bitmap;
+ bitmap = NULL;
+ }
+ spin_unlock_irqrestore(&ida->idr.lock, flags);
+ }
+
+ kfree(bitmap);
+}
+
+/**
+ * ida_pre_get - reserve resources for ida allocation
+ * @ida: ida handle
+ * @gfp_mask: memory allocation flag
+ *
+ * This function should be called prior to locking and calling the
+ * following function. It preallocates enough memory to satisfy the
+ * worst possible allocation.
+ *
+ * If the system is REALLY out of memory this function returns 0,
+ * otherwise 1.
+ */
+int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
+{
+ /* allocate idr_layers */
+ if (!idr_pre_get(&ida->idr, gfp_mask))
+ return 0;
+
+ /* allocate free_bitmap */
+ if (!ida->free_bitmap) {
+ struct ida_bitmap *bitmap;
+
+ bitmap = kmalloc(sizeof(struct ida_bitmap), gfp_mask);
+ if (!bitmap)
+ return 0;
+
+ free_bitmap(ida, bitmap);
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL(ida_pre_get);
+
+/**
+ * ida_get_new_above - allocate new ID above or equal to a start id
+ * @ida: ida handle
+ * @staring_id: id to start search at
+ * @p_id: pointer to the allocated handle
+ *
+ * Allocate new ID above or equal to @ida. It should be called with
+ * any required locks.
+ *
+ * If memory is required, it will return -EAGAIN, you should unlock
+ * and go back to the ida_pre_get() call. If the ida is full, it will
+ * return -ENOSPC.
+ *
+ * @p_id returns a value in the range 0 ... 0x7fffffff.
+ */
+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
+{
+ struct idr_layer *pa[MAX_LEVEL];
+ struct ida_bitmap *bitmap;
+ unsigned long flags;
+ int idr_id = starting_id / IDA_BITMAP_BITS;
+ int offset = starting_id % IDA_BITMAP_BITS;
+ int t, id;
+
+ restart:
+ /* get vacant slot */
+ t = idr_get_empty_slot(&ida->idr, idr_id, pa);
+ if (t < 0) {
+ if (t == -1)
+ return -EAGAIN;
+ else /* will be -3 */
+ return -ENOSPC;
+ }
+
+ if (t * IDA_BITMAP_BITS >= MAX_ID_BIT)
+ return -ENOSPC;
+
+ if (t != idr_id)
+ offset = 0;
+ idr_id = t;
+
+ /* if bitmap isn't there, create a new one */
+ bitmap = (void *)pa[0]->ary[idr_id & IDR_MASK];
+ if (!bitmap) {
+ spin_lock_irqsave(&ida->idr.lock, flags);
+ bitmap = ida->free_bitmap;
+ ida->free_bitmap = NULL;
+ spin_unlock_irqrestore(&ida->idr.lock, flags);
+
+ if (!bitmap)
+ return -EAGAIN;
+
+ memset(bitmap, 0, sizeof(struct ida_bitmap));
+ pa[0]->ary[idr_id & IDR_MASK] = (void *)bitmap;
+ pa[0]->count++;
+ }
+
+ /* lookup for empty slot */
+ t = find_next_zero_bit(bitmap->bitmap, IDA_BITMAP_BITS, offset);
+ if (t == IDA_BITMAP_BITS) {
+ /* no empty slot after offset, continue to the next chunk */
+ idr_id++;
+ offset = 0;
+ goto restart;
+ }
+
+ id = idr_id * IDA_BITMAP_BITS + t;
+ if (id >= MAX_ID_BIT)
+ return -ENOSPC;
+
+ __set_bit(t, bitmap->bitmap);
+ if (++bitmap->nr_busy == IDA_BITMAP_BITS)
+ idr_mark_full(pa, idr_id);
+
+ *p_id = id;
+
+ /* Each leaf node can handle nearly a thousand slots and the
+ * whole idea of ida is to have small memory foot print.
+ * Throw away extra resources one by one after each successful
+ * allocation.
+ */
+ if (ida->idr.id_free_cnt || ida->free_bitmap) {
+ struct idr_layer *p = alloc_layer(&ida->idr);
+ if (p)
+ kmem_cache_free(idr_layer_cache, p);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(ida_get_new_above);
+
+/**
+ * ida_get_new - allocate new ID
+ * @ida: idr handle
+ * @p_id: pointer to the allocated handle
+ *
+ * Allocate new ID. It should be called with any required locks.
+ *
+ * If memory is required, it will return -EAGAIN, you should unlock
+ * and go back to the idr_pre_get() call. If the idr is full, it will
+ * return -ENOSPC.
+ *
+ * @id returns a value in the range 0 ... 0x7fffffff.
+ */
+int ida_get_new(struct ida *ida, int *p_id)
+{
+ return ida_get_new_above(ida, 0, p_id);
+}
+EXPORT_SYMBOL(ida_get_new);
+
+/**
+ * ida_remove - remove the given ID
+ * @ida: ida handle
+ * @id: ID to free
+ */
+void ida_remove(struct ida *ida, int id)
+{
+ struct idr_layer *p = ida->idr.top;
+ int shift = (ida->idr.layers - 1) * IDR_BITS;
+ int idr_id = id / IDA_BITMAP_BITS;
+ int offset = id % IDA_BITMAP_BITS;
+ int n;
+ struct ida_bitmap *bitmap;
+
+ /* clear full bits while looking up the leaf idr_layer */
+ while ((shift > 0) && p) {
+ n = (idr_id >> shift) & IDR_MASK;
+ __clear_bit(n, &p->bitmap);
+ p = p->ary[n];
+ shift -= IDR_BITS;
+ }
+
+ if (p == NULL)
+ goto err;
+
+ n = idr_id & IDR_MASK;
+ __clear_bit(n, &p->bitmap);
+
+ bitmap = (void *)p->ary[n];
+ if (!test_bit(offset, bitmap->bitmap))
+ goto err;
+
+ /* update bitmap and remove it if empty */
+ __clear_bit(offset, bitmap->bitmap);
+ if (--bitmap->nr_busy == 0) {
+ __set_bit(n, &p->bitmap); /* to please idr_remove() */
+ idr_remove(&ida->idr, idr_id);
+ free_bitmap(ida, bitmap);
+ }
+
+ return;
+
+ err:
+ printk(KERN_WARNING
+ "ida_remove called for id=%d which is not allocated.\n", id);
+}
+EXPORT_SYMBOL(ida_remove);
+
+/**
+ * ida_destroy - release all cached layers within an ida tree
+ * ida: ida handle
+ */
+void ida_destroy(struct ida *ida)
+{
+ idr_destroy(&ida->idr);
+ kfree(ida->free_bitmap);
+}
+EXPORT_SYMBOL(ida_destroy);
+
+/**
+ * ida_init - initialize ida handle
+ * @ida: ida handle
+ *
+ * This function is use to set up the handle (@ida) that you will pass
+ * to the rest of the functions.
+ */
+void ida_init(struct ida *ida)
+{
+ memset(ida, 0, sizeof(struct ida));
+ idr_init(&ida->idr);
+
+}
+EXPORT_SYMBOL(ida_init);
diff --git a/lib/kobject.c b/lib/kobject.c
index fc5f3f6e732..4b08e0ff95c 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -44,7 +44,7 @@ static int populate_dir(struct kobject * kobj)
return error;
}
-static int create_dir(struct kobject * kobj, struct dentry *shadow_parent)
+static int create_dir(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
{
int error = 0;
if (kobject_name(kobj)) {
@@ -162,7 +162,7 @@ static void unlink(struct kobject * kobj)
* @shadow_parent: sysfs directory to add to.
*/
-int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
+int kobject_shadow_add(struct kobject *kobj, struct sysfs_dirent *shadow_parent)
{
int error = 0;
struct kobject * parent;
@@ -202,14 +202,14 @@ int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent)
/* be noisy on error issues */
if (error == -EEXIST)
- printk("kobject_add failed for %s with -EEXIST, "
- "don't try to register things with the "
- "same name in the same directory.\n",
+ printk(KERN_ERR "kobject_add failed for %s with "
+ "-EEXIST, don't try to register things with "
+ "the same name in the same directory.\n",
kobject_name(kobj));
else
- printk("kobject_add failed for %s (%d)\n",
+ printk(KERN_ERR "kobject_add failed for %s (%d)\n",
kobject_name(kobj), error);
- dump_stack();
+ dump_stack();
}
return error;
@@ -338,7 +338,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
/* Note : if we want to send the new name alone, not the full path,
* we could probably use kobject_name(kobj); */
- error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name);
+ error = sysfs_rename_dir(kobj, kobj->parent->sd, new_name);
/* This function is mostly/only used for network interface.
* Some hotplug package track interfaces by their name and
@@ -361,8 +361,8 @@ out:
* @new_name: object's new name
*/
-int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent,
- const char *new_name)
+int kobject_shadow_rename(struct kobject *kobj,
+ struct sysfs_dirent *new_parent, const char *new_name)
{
int error = 0;
@@ -597,10 +597,17 @@ int kset_add(struct kset * k)
int kset_register(struct kset * k)
{
+ int err;
+
if (!k)
return -EINVAL;
+
kset_init(k);
- return kset_add(k);
+ err = kset_add(k);
+ if (err)
+ return err;
+ kobject_uevent(&k->kobj, KOBJ_ADD);
+ return 0;
}
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
new file mode 100644
index 00000000000..e764116ea12
--- /dev/null
+++ b/lib/lzo/Makefile
@@ -0,0 +1,5 @@
+lzo_compress-objs := lzo1x_compress.o
+lzo_decompress-objs := lzo1x_decompress.o
+
+obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
+obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
new file mode 100644
index 00000000000..c935f00073e
--- /dev/null
+++ b/lib/lzo/lzo1x_compress.c
@@ -0,0 +1,226 @@
+/*
+ * LZO1X Compressor from MiniLZO
+ *
+ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lzo.h>
+#include <asm/unaligned.h>
+#include "lzodefs.h"
+
+static noinline size_t
+_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len, void *wrkmem)
+{
+ const unsigned char * const in_end = in + in_len;
+ const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
+ const unsigned char ** const dict = wrkmem;
+ const unsigned char *ip = in, *ii = ip;
+ const unsigned char *end, *m, *m_pos;
+ size_t m_off, m_len, dindex;
+ unsigned char *op = out;
+
+ ip += 4;
+
+ for (;;) {
+ dindex = ((0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
+ m_pos = dict[dindex];
+
+ if (m_pos < in)
+ goto literal;
+
+ if (ip == m_pos || (ip - m_pos) > M4_MAX_OFFSET)
+ goto literal;
+
+ m_off = ip - m_pos;
+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+ goto try_match;
+
+ dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
+ m_pos = dict[dindex];
+
+ if (m_pos < in)
+ goto literal;
+
+ if (ip == m_pos || (ip - m_pos) > M4_MAX_OFFSET)
+ goto literal;
+
+ m_off = ip - m_pos;
+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
+ goto try_match;
+
+ goto literal;
+
+try_match:
+ if (get_unaligned((const unsigned short *)m_pos)
+ == get_unaligned((const unsigned short *)ip)) {
+ if (likely(m_pos[2] == ip[2]))
+ goto match;
+ }
+
+literal:
+ dict[dindex] = ip;
+ ++ip;
+ if (unlikely(ip >= ip_end))
+ break;
+ continue;
+
+match:
+ dict[dindex] = ip;
+ if (ip != ii) {
+ size_t t = ip - ii;
+
+ if (t <= 3) {
+ op[-2] |= t;
+ } else if (t <= 18) {
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255) {
+ tt -= 255;
+ *op++ = 0;
+ }
+ *op++ = tt;
+ }
+ do {
+ *op++ = *ii++;
+ } while (--t > 0);
+ }
+
+ ip += 3;
+ if (m_pos[3] != *ip++ || m_pos[4] != *ip++
+ || m_pos[5] != *ip++ || m_pos[6] != *ip++
+ || m_pos[7] != *ip++ || m_pos[8] != *ip++) {
+ --ip;
+ m_len = ip - ii;
+
+ if (m_off <= M2_MAX_OFFSET) {
+ m_off -= 1;
+ *op++ = (((m_len - 1) << 5)
+ | ((m_off & 7) << 2));
+ *op++ = (m_off >> 3);
+ } else if (m_off <= M3_MAX_OFFSET) {
+ m_off -= 1;
+ *op++ = (M3_MARKER | (m_len - 2));
+ goto m3_m4_offset;
+ } else {
+ m_off -= 0x4000;
+
+ *op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
+ | (m_len - 2));
+ goto m3_m4_offset;
+ }
+ } else {
+ end = in_end;
+ m = m_pos + M2_MAX_LEN + 1;
+
+ while (ip < end && *m == *ip) {
+ m++;
+ ip++;
+ }
+ m_len = ip - ii;
+
+ if (m_off <= M3_MAX_OFFSET) {
+ m_off -= 1;
+ if (m_len <= 33) {
+ *op++ = (M3_MARKER | (m_len - 2));
+ } else {
+ m_len -= 33;
+ *op++ = M3_MARKER | 0;
+ goto m3_m4_len;
+ }
+ } else {
+ m_off -= 0x4000;
+ if (m_len <= M4_MAX_LEN) {
+ *op++ = (M4_MARKER
+ | ((m_off & 0x4000) >> 11)
+ | (m_len - 2));
+ } else {
+ m_len -= M4_MAX_LEN;
+ *op++ = (M4_MARKER
+ | ((m_off & 0x4000) >> 11));
+m3_m4_len:
+ while (m_len > 255) {
+ m_len -= 255;
+ *op++ = 0;
+ }
+
+ *op++ = (m_len);
+ }
+ }
+m3_m4_offset:
+ *op++ = ((m_off & 63) << 2);
+ *op++ = (m_off >> 6);
+ }
+
+ ii = ip;
+ if (unlikely(ip >= ip_end))
+ break;
+ }
+
+ *out_len = op - out;
+ return in_end - ii;
+}
+
+int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
+ size_t *out_len, void *wrkmem)
+{
+ const unsigned char *ii;
+ unsigned char *op = out;
+ size_t t;
+
+ if (unlikely(in_len <= M2_MAX_LEN + 5)) {
+ t = in_len;
+ } else {
+ t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
+ op += *out_len;
+ }
+
+ if (t > 0) {
+ ii = in + in_len - t;
+
+ if (op == out && t <= 238) {
+ *op++ = (17 + t);
+ } else if (t <= 3) {
+ op[-2] |= t;
+ } else if (t <= 18) {
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
+
+ *op++ = 0;
+ while (tt > 255) {
+ tt -= 255;
+ *op++ = 0;
+ }
+
+ *op++ = tt;
+ }
+ do {
+ *op++ = *ii++;
+ } while (--t > 0);
+ }
+
+ *op++ = M4_MARKER | 1;
+ *op++ = 0;
+ *op++ = 0;
+
+ *out_len = op - out;
+ return LZO_E_OK;
+}
+EXPORT_SYMBOL_GPL(lzo1x_1_compress);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X-1 Compressor");
+
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
new file mode 100644
index 00000000000..9dc7056e552
--- /dev/null
+++ b/lib/lzo/lzo1x_decompress.c
@@ -0,0 +1,254 @@
+/*
+ * LZO1X Decompressor from MiniLZO
+ *
+ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lzo.h>
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include "lzodefs.h"
+
+#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
+#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
+#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
+
+#define COPY4(dst, src) \
+ put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len)
+{
+ const unsigned char * const ip_end = in + in_len;
+ unsigned char * const op_end = out + *out_len;
+ const unsigned char *ip = in, *m_pos;
+ unsigned char *op = out;
+ size_t t;
+
+ *out_len = 0;
+
+ if (*ip > 17) {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ if (HAVE_OP(t, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 1, ip_end, ip))
+ goto input_overrun;
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while ((ip < ip_end)) {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 15 + *ip++;
+ }
+ if (HAVE_OP(t + 3, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 4, ip_end, ip))
+ goto input_overrun;
+
+ COPY4(op, ip);
+ op += 4;
+ ip += 4;
+ if (--t > 0) {
+ if (t >= 4) {
+ do {
+ COPY4(op, ip);
+ op += 4;
+ ip += 4;
+ t -= 4;
+ } while (t >= 4);
+ if (t > 0) {
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ } else {
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ }
+
+first_literal_run:
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+
+ if (HAVE_OP(3, op_end, op))
+ goto output_overrun;
+ *op++ = *m_pos++;
+ *op++ = *m_pos++;
+ *op++ = *m_pos;
+
+ goto match_done;
+
+ do {
+match:
+ if (t >= 64) {
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(t + 3 - 1, op_end, op))
+ goto output_overrun;
+ goto copy_match;
+ } else if (t >= 32) {
+ t &= 31;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 31 + *ip++;
+ }
+ m_pos = op - 1;
+ m_pos -= le16_to_cpu(get_unaligned(
+ (const unsigned short *)ip)) >> 2;
+ ip += 2;
+ } else if (t >= 16) {
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+
+ t &= 7;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 7 + *ip++;
+ }
+ m_pos -= le16_to_cpu(get_unaligned(
+ (const unsigned short *)ip) >> 2);
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+ } else {
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(2, op_end, op))
+ goto output_overrun;
+
+ *op++ = *m_pos++;
+ *op++ = *m_pos;
+ goto match_done;
+ }
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(t + 3 - 1, op_end, op))
+ goto output_overrun;
+
+ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
+ COPY4(op, m_pos);
+ op += 4;
+ m_pos += 4;
+ t -= 4 - (3 - 1);
+ do {
+ COPY4(op, m_pos);
+ op += 4;
+ m_pos += 4;
+ t -= 4;
+ } while (t >= 4);
+ if (t > 0)
+ do {
+ *op++ = *m_pos++;
+ } while (--t > 0);
+ } else {
+copy_match:
+ *op++ = *m_pos++;
+ *op++ = *m_pos++;
+ do {
+ *op++ = *m_pos++;
+ } while (--t > 0);
+ }
+match_done:
+ t = ip[-2] & 3;
+ if (t == 0)
+ break;
+match_next:
+ if (HAVE_OP(t, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 1, ip_end, ip))
+ goto input_overrun;
+
+ *op++ = *ip++;
+ if (t > 1) {
+ *op++ = *ip++;
+ if (t > 2)
+ *op++ = *ip++;
+ }
+
+ t = *ip++;
+ } while (ip < ip_end);
+ }
+
+ *out_len = op - out;
+ return LZO_E_EOF_NOT_FOUND;
+
+eof_found:
+ *out_len = op - out;
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+input_overrun:
+ *out_len = op - out;
+ return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+}
+
+EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X Decompressor");
+
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
new file mode 100644
index 00000000000..b6d482c492e
--- /dev/null
+++ b/lib/lzo/lzodefs.h
@@ -0,0 +1,43 @@
+/*
+ * lzodefs.h -- architecture, OS and compiler specific defines
+ *
+ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#define LZO_VERSION 0x2020
+#define LZO_VERSION_STRING "2.02"
+#define LZO_VERSION_DATE "Oct 17 2005"
+
+#define M1_MAX_OFFSET 0x0400
+#define M2_MAX_OFFSET 0x0800
+#define M3_MAX_OFFSET 0x4000
+#define M4_MAX_OFFSET 0xbfff
+
+#define M1_MIN_LEN 2
+#define M1_MAX_LEN 2
+#define M2_MIN_LEN 3
+#define M2_MAX_LEN 8
+#define M3_MIN_LEN 3
+#define M3_MAX_LEN 33
+#define M4_MIN_LEN 3
+#define M4_MAX_LEN 9
+
+#define M1_MARKER 0
+#define M2_MARKER 64
+#define M3_MARKER 32
+#define M4_MARKER 16
+
+#define D_BITS 14
+#define D_MASK ((1u << D_BITS) - 1)
+#define D_HIGH ((D_MASK >> 1) + 1)
+
+#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
+ << (s1)) ^ (p)[0])
+#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 402eb4eb6b2..9927cca14cb 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -151,6 +151,7 @@ int radix_tree_preload(gfp_t gfp_mask)
out:
return ret;
}
+EXPORT_SYMBOL(radix_tree_preload);
static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
int offset)
diff --git a/mm/filemap.c b/mm/filemap.c
index edb1b0b5cc8..c6ebd9f912a 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1245,26 +1245,6 @@ int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long o
return written;
}
-ssize_t generic_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
-{
- read_descriptor_t desc;
-
- if (!count)
- return 0;
-
- desc.written = 0;
- desc.count = count;
- desc.arg.data = target;
- desc.error = 0;
-
- do_generic_file_read(in_file, ppos, &desc, actor);
- if (desc.written)
- return desc.written;
- return desc.error;
-}
-EXPORT_SYMBOL(generic_file_sendfile);
-
static ssize_t
do_readahead(struct address_space *mapping, struct file *filp,
unsigned long index, unsigned long nr)
@@ -1786,7 +1766,6 @@ retry:
page = __read_cache_page(mapping, index, filler, data);
if (IS_ERR(page))
return page;
- mark_page_accessed(page);
if (PageUptodate(page))
goto out;
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index fa360e566d8..65ffc321f0c 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -159,28 +159,6 @@ xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
}
EXPORT_SYMBOL_GPL(xip_file_read);
-ssize_t
-xip_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
-{
- read_descriptor_t desc;
-
- if (!count)
- return 0;
-
- desc.written = 0;
- desc.count = count;
- desc.arg.data = target;
- desc.error = 0;
-
- do_xip_mapping_read(in_file->f_mapping, &in_file->f_ra, in_file,
- ppos, &desc, actor);
- if (desc.written)
- return desc.written;
- return desc.error;
-}
-EXPORT_SYMBOL_GPL(xip_file_sendfile);
-
/*
* __xip_unmap is invoked from xip_unmap and
* xip_write
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index eb7180db303..a45d1f0691c 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -326,9 +326,10 @@ static void set_huge_ptep_writable(struct vm_area_struct *vma,
pte_t entry;
entry = pte_mkwrite(pte_mkdirty(*ptep));
- ptep_set_access_flags(vma, address, ptep, entry, 1);
- update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
+ if (ptep_set_access_flags(vma, address, ptep, entry, 1)) {
+ update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
+ }
}
diff --git a/mm/memory.c b/mm/memory.c
index cb94488ab96..f64cbf9baa3 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1691,9 +1691,10 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
flush_cache_page(vma, address, pte_pfn(orig_pte));
entry = pte_mkyoung(orig_pte);
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
- ptep_set_access_flags(vma, address, page_table, entry, 1);
- update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
+ if (ptep_set_access_flags(vma, address, page_table, entry,1)) {
+ update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
+ }
ret |= VM_FAULT_WRITE;
goto unlock;
}
@@ -2525,10 +2526,9 @@ static inline int handle_pte_fault(struct mm_struct *mm,
pte_t *pte, pmd_t *pmd, int write_access)
{
pte_t entry;
- pte_t old_entry;
spinlock_t *ptl;
- old_entry = entry = *pte;
+ entry = *pte;
if (!pte_present(entry)) {
if (pte_none(entry)) {
if (vma->vm_ops) {
@@ -2561,8 +2561,7 @@ static inline int handle_pte_fault(struct mm_struct *mm,
entry = pte_mkdirty(entry);
}
entry = pte_mkyoung(entry);
- if (!pte_same(old_entry, entry)) {
- ptep_set_access_flags(vma, address, pte, entry, write_access);
+ if (ptep_set_access_flags(vma, address, pte, entry, write_access)) {
update_mmu_cache(vma, address, entry);
lazy_mmu_prot_update(entry);
} else {
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 84279127fcd..df9d554bea3 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -65,7 +65,7 @@ static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
int zone_type;
zone_type = zone - pgdat->node_zones;
- if (!populated_zone(zone)) {
+ if (!zone->wait_table) {
int ret = 0;
ret = init_currently_empty_zone(zone, phys_start_pfn,
nr_pages, MEMMAP_HOTPLUG);
diff --git a/mm/mmap.c b/mm/mmap.c
index 68b9ad2ef1d..9f70c8e8c87 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1023,10 +1023,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
}
}
- error = security_file_mmap(file, reqprot, prot, flags);
+ error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
if (error)
return error;
-
+
/* Clear old maps */
error = -ENOMEM;
munmap_back:
@@ -1536,9 +1536,14 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
* vma->vm_start/vm_end cannot change under us because the caller
* is required to hold the mmap_sem in read mode. We need the
* anon_vma lock to serialize against concurrent expand_stacks.
+ * Also guard against wrapping around to address 0.
*/
- address += 4 + PAGE_SIZE - 1;
- address &= PAGE_MASK;
+ if (address < PAGE_ALIGN(address+4))
+ address = PAGE_ALIGN(address+4);
+ else {
+ anon_vma_unlock(vma);
+ return -ENOMEM;
+ }
error = 0;
/* Somebody else might have raced and expanded it already */
diff --git a/mm/mremap.c b/mm/mremap.c
index 5d4bd4f95b8..bc7c52efc71 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -291,6 +291,10 @@ unsigned long do_mremap(unsigned long addr,
if ((addr <= new_addr) && (addr+old_len) > new_addr)
goto out;
+ ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+ if (ret)
+ goto out;
+
ret = do_munmap(mm, new_addr, new_len);
if (ret)
goto out;
@@ -390,8 +394,13 @@ unsigned long do_mremap(unsigned long addr,
new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
vma->vm_pgoff, map_flags);
- ret = new_addr;
- if (new_addr & ~PAGE_MASK)
+ if (new_addr & ~PAGE_MASK) {
+ ret = new_addr;
+ goto out;
+ }
+
+ ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+ if (ret)
goto out;
}
ret = move_vma(vma, addr, old_len, new_len, new_addr);
diff --git a/mm/nommu.c b/mm/nommu.c
index 2b16b00a5b1..989e2e9af5c 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -639,7 +639,7 @@ static int validate_mmap_request(struct file *file,
}
/* allow the security API to have its say */
- ret = security_file_mmap(file, reqprot, prot, flags);
+ ret = security_file_mmap(file, reqprot, prot, flags, addr, 0);
if (ret < 0)
return ret;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d8970623c56..05ace44852e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1968,7 +1968,7 @@ void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY)
#endif
-static int __cpuinit zone_batchsize(struct zone *zone)
+static int __devinit zone_batchsize(struct zone *zone)
{
int batch;
@@ -2689,7 +2689,7 @@ static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
map = alloc_bootmem_node(pgdat, size);
pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);
}
-#ifdef CONFIG_FLATMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
/*
* With no DISCONTIG, the global mem_map is just set as node 0's
*/
diff --git a/mm/rmap.c b/mm/rmap.c
index 850165d32b7..61e492597a0 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -53,24 +53,6 @@
struct kmem_cache *anon_vma_cachep;
-static inline void validate_anon_vma(struct vm_area_struct *find_vma)
-{
-#ifdef CONFIG_DEBUG_VM
- struct anon_vma *anon_vma = find_vma->anon_vma;
- struct vm_area_struct *vma;
- unsigned int mapcount = 0;
- int found = 0;
-
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
- mapcount++;
- BUG_ON(mapcount > 100000);
- if (vma == find_vma)
- found = 1;
- }
- BUG_ON(!found);
-#endif
-}
-
/* This must be called under the mmap_sem. */
int anon_vma_prepare(struct vm_area_struct *vma)
{
@@ -121,10 +103,8 @@ void __anon_vma_link(struct vm_area_struct *vma)
{
struct anon_vma *anon_vma = vma->anon_vma;
- if (anon_vma) {
+ if (anon_vma)
list_add_tail(&vma->anon_vma_node, &anon_vma->head);
- validate_anon_vma(vma);
- }
}
void anon_vma_link(struct vm_area_struct *vma)
@@ -134,7 +114,6 @@ void anon_vma_link(struct vm_area_struct *vma)
if (anon_vma) {
spin_lock(&anon_vma->lock);
list_add_tail(&vma->anon_vma_node, &anon_vma->head);
- validate_anon_vma(vma);
spin_unlock(&anon_vma->lock);
}
}
@@ -148,7 +127,6 @@ void anon_vma_unlink(struct vm_area_struct *vma)
return;
spin_lock(&anon_vma->lock);
- validate_anon_vma(vma);
list_del(&vma->anon_vma_node);
/* We must garbage collect the anon_vma if it's empty */
diff --git a/mm/shmem.c b/mm/shmem.c
index e537317bec4..0493e4d0bca 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -967,6 +967,8 @@ static inline int shmem_parse_mpol(char *value, int *policy, nodemask_t *policy_
*nodelist++ = '\0';
if (nodelist_parse(nodelist, *policy_nodes))
goto out;
+ if (!nodes_subset(*policy_nodes, node_online_map))
+ goto out;
}
if (!strcmp(value, "default")) {
*policy = MPOL_DEFAULT;
@@ -1098,9 +1100,9 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
* Normally, filepage is NULL on entry, and either found
* uptodate immediately, or allocated and zeroed, or read
* in under swappage, which is then assigned to filepage.
- * But shmem_prepare_write passes in a locked filepage,
- * which may be found not uptodate by other callers too,
- * and may need to be copied from the swappage read in.
+ * But shmem_readpage and shmem_prepare_write pass in a locked
+ * filepage, which may be found not uptodate by other callers
+ * too, and may need to be copied from the swappage read in.
*/
repeat:
if (!filepage)
@@ -1483,9 +1485,18 @@ static const struct inode_operations shmem_symlink_inode_operations;
static const struct inode_operations shmem_symlink_inline_operations;
/*
- * Normally tmpfs makes no use of shmem_prepare_write, but it
- * lets a tmpfs file be used read-write below the loop driver.
+ * Normally tmpfs avoids the use of shmem_readpage and shmem_prepare_write;
+ * but providing them allows a tmpfs file to be used for splice, sendfile, and
+ * below the loop driver, in the generic fashion that many filesystems support.
*/
+static int shmem_readpage(struct file *file, struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ int error = shmem_getpage(inode, page->index, &page, SGP_CACHE, NULL);
+ unlock_page(page);
+ return error;
+}
+
static int
shmem_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
@@ -1709,25 +1720,6 @@ static ssize_t shmem_file_read(struct file *filp, char __user *buf, size_t count
return desc.error;
}
-static ssize_t shmem_file_sendfile(struct file *in_file, loff_t *ppos,
- size_t count, read_actor_t actor, void *target)
-{
- read_descriptor_t desc;
-
- if (!count)
- return 0;
-
- desc.written = 0;
- desc.count = count;
- desc.arg.data = target;
- desc.error = 0;
-
- do_shmem_file_read(in_file, ppos, &desc, actor);
- if (desc.written)
- return desc.written;
- return desc.error;
-}
-
static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
@@ -2384,6 +2376,7 @@ static const struct address_space_operations shmem_aops = {
.writepage = shmem_writepage,
.set_page_dirty = __set_page_dirty_no_writeback,
#ifdef CONFIG_TMPFS
+ .readpage = shmem_readpage,
.prepare_write = shmem_prepare_write,
.commit_write = simple_commit_write,
#endif
@@ -2397,7 +2390,8 @@ static const struct file_operations shmem_file_operations = {
.read = shmem_file_read,
.write = shmem_file_write,
.fsync = simple_sync_file,
- .sendfile = shmem_file_sendfile,
+ .splice_read = generic_file_splice_read,
+ .splice_write = generic_file_splice_write,
#endif
};
diff --git a/mm/slab.c b/mm/slab.c
index 2e71a328aa0..b344e670712 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -137,6 +137,7 @@
/* Shouldn't this be in a header file somewhere? */
#define BYTES_PER_WORD sizeof(void *)
+#define REDZONE_ALIGN max(BYTES_PER_WORD, __alignof__(unsigned long long))
#ifndef cache_line_size
#define cache_line_size() L1_CACHE_BYTES
@@ -547,7 +548,7 @@ static unsigned long long *dbg_redzone2(struct kmem_cache *cachep, void *objp)
if (cachep->flags & SLAB_STORE_USER)
return (unsigned long long *)(objp + cachep->buffer_size -
sizeof(unsigned long long) -
- BYTES_PER_WORD);
+ REDZONE_ALIGN);
return (unsigned long long *) (objp + cachep->buffer_size -
sizeof(unsigned long long));
}
@@ -774,7 +775,6 @@ static inline struct kmem_cache *__find_general_cachep(size_t size,
*/
BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
#endif
- WARN_ON_ONCE(size == 0);
while (size > csizep->cs_size)
csizep++;
@@ -2179,7 +2179,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
* above the next power of two: caches with object sizes just above a
* power of two have a significant amount of internal fragmentation.
*/
- if (size < 4096 || fls(size - 1) == fls(size-1 + 3 * BYTES_PER_WORD))
+ if (size < 4096 || fls(size - 1) == fls(size-1 + REDZONE_ALIGN +
+ 2 * sizeof(unsigned long long)))
flags |= SLAB_RED_ZONE | SLAB_STORE_USER;
if (!(flags & SLAB_DESTROY_BY_RCU))
flags |= SLAB_POISON;
@@ -2220,12 +2221,20 @@ kmem_cache_create (const char *name, size_t size, size_t align,
}
/*
- * Redzoning and user store require word alignment. Note this will be
- * overridden by architecture or caller mandated alignment if either
- * is greater than BYTES_PER_WORD.
+ * Redzoning and user store require word alignment or possibly larger.
+ * Note this will be overridden by architecture or caller mandated
+ * alignment if either is greater than BYTES_PER_WORD.
*/
- if (flags & SLAB_RED_ZONE || flags & SLAB_STORE_USER)
- ralign = __alignof__(unsigned long long);
+ if (flags & SLAB_STORE_USER)
+ ralign = BYTES_PER_WORD;
+
+ if (flags & SLAB_RED_ZONE) {
+ ralign = REDZONE_ALIGN;
+ /* If redzoning, ensure that the second redzone is suitably
+ * aligned, by adjusting the object size accordingly. */
+ size += REDZONE_ALIGN - 1;
+ size &= ~(REDZONE_ALIGN - 1);
+ }
/* 2) arch mandated alignment */
if (ralign < ARCH_SLAB_MINALIGN) {
@@ -2262,9 +2271,13 @@ kmem_cache_create (const char *name, size_t size, size_t align,
}
if (flags & SLAB_STORE_USER) {
/* user store requires one word storage behind the end of
- * the real object.
+ * the real object. But if the second red zone needs to be
+ * aligned to 64 bits, we must allow that much space.
*/
- size += BYTES_PER_WORD;
+ if (flags & SLAB_RED_ZONE)
+ size += REDZONE_ALIGN;
+ else
+ size += BYTES_PER_WORD;
}
#if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC)
if (size >= malloc_sizes[INDEX_L3 + 1].cs_size
@@ -3539,7 +3552,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp)
check_irq_off();
objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
- if (use_alien_caches && cache_free_alien(cachep, objp))
+ if (cache_free_alien(cachep, objp))
return;
if (likely(ac->avail < ac->limit)) {
diff --git a/mm/slub.c b/mm/slub.c
index 3e5aefcb407..e0cf6213abc 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1798,8 +1798,6 @@ static struct kmem_cache_node * __init early_kmem_cache_node_alloc(gfp_t gfpflag
BUG_ON(kmalloc_caches->size < sizeof(struct kmem_cache_node));
page = new_slab(kmalloc_caches, gfpflags | GFP_THISNODE, node);
- /* new_slab() disables interupts */
- local_irq_enable();
BUG_ON(!page);
n = page->freelist;
@@ -1811,6 +1809,12 @@ static struct kmem_cache_node * __init early_kmem_cache_node_alloc(gfp_t gfpflag
init_kmem_cache_node(n);
atomic_long_inc(&n->nr_slabs);
add_partial(n, page);
+
+ /*
+ * new_slab() disables interupts. If we do not reenable interrupts here
+ * then bootup would continue with interrupts disabled.
+ */
+ local_irq_enable();
return n;
}
@@ -2016,7 +2020,6 @@ error:
s->offset, flags);
return 0;
}
-EXPORT_SYMBOL(kmem_cache_open);
/*
* Check if a given pointer is valid
@@ -2241,7 +2244,7 @@ void *__kmalloc(size_t size, gfp_t flags)
if (s)
return slab_alloc(s, flags, -1, __builtin_return_address(0));
- return NULL;
+ return ZERO_SIZE_PTR;
}
EXPORT_SYMBOL(__kmalloc);
@@ -2252,16 +2255,20 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
if (s)
return slab_alloc(s, flags, node, __builtin_return_address(0));
- return NULL;
+ return ZERO_SIZE_PTR;
}
EXPORT_SYMBOL(__kmalloc_node);
#endif
size_t ksize(const void *object)
{
- struct page *page = get_object_page(object);
+ struct page *page;
struct kmem_cache *s;
+ if (object == ZERO_SIZE_PTR)
+ return 0;
+
+ page = get_object_page(object);
BUG_ON(!page);
s = page->slab;
BUG_ON(!s);
@@ -2293,7 +2300,13 @@ void kfree(const void *x)
struct kmem_cache *s;
struct page *page;
- if (!x)
+ /*
+ * This has to be an unsigned comparison. According to Linus
+ * some gcc version treat a pointer as a signed entity. Then
+ * this comparison would be true for all "negative" pointers
+ * (which would cover the whole upper half of the address space).
+ */
+ if ((unsigned long)x <= (unsigned long)ZERO_SIZE_PTR)
return;
page = virt_to_head_page(x);
@@ -2398,12 +2411,12 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
void *ret;
size_t ks;
- if (unlikely(!p))
+ if (unlikely(!p || p == ZERO_SIZE_PTR))
return kmalloc(new_size, flags);
if (unlikely(!new_size)) {
kfree(p);
- return NULL;
+ return ZERO_SIZE_PTR;
}
ks = ksize(p);
@@ -2426,6 +2439,7 @@ EXPORT_SYMBOL(krealloc);
void __init kmem_cache_init(void)
{
int i;
+ int caches = 0;
#ifdef CONFIG_NUMA
/*
@@ -2435,20 +2449,30 @@ void __init kmem_cache_init(void)
*/
create_kmalloc_cache(&kmalloc_caches[0], "kmem_cache_node",
sizeof(struct kmem_cache_node), GFP_KERNEL);
+ kmalloc_caches[0].refcount = -1;
+ caches++;
#endif
/* Able to allocate the per node structures */
slab_state = PARTIAL;
/* Caches that are not of the two-to-the-power-of size */
- create_kmalloc_cache(&kmalloc_caches[1],
+ if (KMALLOC_MIN_SIZE <= 64) {
+ create_kmalloc_cache(&kmalloc_caches[1],
"kmalloc-96", 96, GFP_KERNEL);
- create_kmalloc_cache(&kmalloc_caches[2],
+ caches++;
+ }
+ if (KMALLOC_MIN_SIZE <= 128) {
+ create_kmalloc_cache(&kmalloc_caches[2],
"kmalloc-192", 192, GFP_KERNEL);
+ caches++;
+ }
- for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++)
+ for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) {
create_kmalloc_cache(&kmalloc_caches[i],
"kmalloc", 1 << i, GFP_KERNEL);
+ caches++;
+ }
slab_state = UP;
@@ -2465,8 +2489,8 @@ void __init kmem_cache_init(void)
nr_cpu_ids * sizeof(struct page *);
printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
- " Processors=%d, Nodes=%d\n",
- KMALLOC_SHIFT_HIGH, cache_line_size(),
+ " CPUs=%d, Nodes=%d\n",
+ caches, cache_line_size(),
slub_min_order, slub_max_order, slub_min_objects,
nr_cpu_ids, nr_node_ids);
}
@@ -2482,6 +2506,12 @@ static int slab_unmergeable(struct kmem_cache *s)
if (s->ctor)
return 1;
+ /*
+ * We may have set a slab to be unmergeable during bootstrap.
+ */
+ if (s->refcount < 0)
+ return 1;
+
return 0;
}
@@ -2601,6 +2631,19 @@ static void for_all_slabs(void (*func)(struct kmem_cache *, int), int cpu)
}
/*
+ * Version of __flush_cpu_slab for the case that interrupts
+ * are enabled.
+ */
+static void cpu_slab_flush(struct kmem_cache *s, int cpu)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ __flush_cpu_slab(s, cpu);
+ local_irq_restore(flags);
+}
+
+/*
* Use the cpu notifier to insure that the cpu slabs are flushed when
* necessary.
*/
@@ -2614,7 +2657,7 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
case CPU_UP_CANCELED_FROZEN:
case CPU_DEAD:
case CPU_DEAD_FROZEN:
- for_all_slabs(__flush_cpu_slab, cpu);
+ for_all_slabs(cpu_slab_flush, cpu);
break;
default:
break;
@@ -2632,7 +2675,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, void *caller)
struct kmem_cache *s = get_slab(size, gfpflags);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return slab_alloc(s, gfpflags, -1, caller);
}
@@ -2643,7 +2686,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
struct kmem_cache *s = get_slab(size, gfpflags);
if (!s)
- return NULL;
+ return ZERO_SIZE_PTR;
return slab_alloc(s, gfpflags, node, caller);
}
@@ -2837,7 +2880,7 @@ static int alloc_loc_track(struct loc_track *t, unsigned long max)
order = get_order(sizeof(struct location) * max);
- l = (void *)__get_free_pages(GFP_KERNEL, order);
+ l = (void *)__get_free_pages(GFP_ATOMIC, order);
if (!l)
return 0;
@@ -3002,13 +3045,15 @@ static int list_locations(struct kmem_cache *s, char *buf,
n += sprintf(buf + n, " pid=%ld",
l->min_pid);
- if (num_online_cpus() > 1 && !cpus_empty(l->cpus)) {
+ if (num_online_cpus() > 1 && !cpus_empty(l->cpus) &&
+ n < PAGE_SIZE - 60) {
n += sprintf(buf + n, " cpus=");
n += cpulist_scnprintf(buf + n, PAGE_SIZE - n - 50,
l->cpus);
}
- if (num_online_nodes() > 1 && !nodes_empty(l->nodes)) {
+ if (num_online_nodes() > 1 && !nodes_empty(l->nodes) &&
+ n < PAGE_SIZE - 60) {
n += sprintf(buf + n, " nodes=");
n += nodelist_scnprintf(buf + n, PAGE_SIZE - n - 50,
l->nodes);
diff --git a/mm/sparse.c b/mm/sparse.c
index 1302f8348d5..e03b39f3540 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -209,6 +209,12 @@ static int __meminit sparse_init_one_section(struct mem_section *ms,
return 1;
}
+__attribute__((weak))
+void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size)
+{
+ return NULL;
+}
+
static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
{
struct page *map;
@@ -219,6 +225,11 @@ static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
if (map)
return map;
+ map = alloc_bootmem_high_node(NODE_DATA(nid),
+ sizeof(struct page) * PAGES_PER_SECTION);
+ if (map)
+ return map;
+
map = alloc_bootmem_node(NODE_DATA(nid),
sizeof(struct page) * PAGES_PER_SECTION);
if (map)
@@ -229,6 +240,27 @@ static struct page __init *sparse_early_mem_map_alloc(unsigned long pnum)
return NULL;
}
+/*
+ * Allocate the accumulated non-linear sections, allocate a mem_map
+ * for each and record the physical to section mapping.
+ */
+void __init sparse_init(void)
+{
+ unsigned long pnum;
+ struct page *map;
+
+ for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+ if (!valid_section_nr(pnum))
+ continue;
+
+ map = sparse_early_mem_map_alloc(pnum);
+ if (!map)
+ continue;
+ sparse_init_one_section(__nr_to_section(pnum), pnum, map);
+ }
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
static struct page *__kmalloc_section_memmap(unsigned long nr_pages)
{
struct page *page, *ret;
@@ -269,27 +301,6 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
}
/*
- * Allocate the accumulated non-linear sections, allocate a mem_map
- * for each and record the physical to section mapping.
- */
-void __init sparse_init(void)
-{
- unsigned long pnum;
- struct page *map;
-
- for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
- if (!valid_section_nr(pnum))
- continue;
-
- map = sparse_early_mem_map_alloc(pnum);
- if (!map)
- continue;
- sparse_init_one_section(__nr_to_section(pnum), pnum, map);
- }
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-/*
* returns the number of sections whose mem_maps were properly
* set. If this is <=0, then that means that the passed-in
* map was not consumed and must be freed.
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 38254297a49..eceaf496210 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -477,8 +477,8 @@ const struct seq_operations fragmentation_op = {
static const char * const vmstat_text[] = {
/* Zoned VM counters */
"nr_free_pages",
- "nr_active",
"nr_inactive",
+ "nr_active",
"nr_anon_pages",
"nr_mapped",
"nr_file_pages",
diff --git a/net/802/tr.c b/net/802/tr.c
index 0ba1946211c..e56e61a7f54 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -567,7 +567,7 @@ static int rif_seq_show(struct seq_file *seq, void *v)
}
-static struct seq_operations rif_seq_ops = {
+static const struct seq_operations rif_seq_ops = {
.start = rif_seq_start,
.next = rif_seq_next,
.stop = rif_seq_stop,
diff --git a/net/8021q/Makefile b/net/8021q/Makefile
index 97feb44dbdc..10ca7f486c3 100644
--- a/net/8021q/Makefile
+++ b/net/8021q/Makefile
@@ -4,7 +4,7 @@
obj-$(CONFIG_VLAN_8021Q) += 8021q.o
-8021q-objs := vlan.o vlan_dev.o
+8021q-objs := vlan.o vlan_dev.o vlan_netlink.o
ifeq ($(CONFIG_PROC_FS),y)
8021q-objs += vlanproc.o
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index bd93c45778d..cda936b77d2 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -97,35 +97,22 @@ static int __init vlan_proto_init(void)
/* Register us to receive netdevice events */
err = register_netdevice_notifier(&vlan_notifier_block);
- if (err < 0) {
- dev_remove_pack(&vlan_packet_type);
- vlan_proc_cleanup();
- return err;
- }
+ if (err < 0)
+ goto err1;
- vlan_ioctl_set(vlan_ioctl_handler);
+ err = vlan_netlink_init();
+ if (err < 0)
+ goto err2;
+ vlan_ioctl_set(vlan_ioctl_handler);
return 0;
-}
-
-/* Cleanup all vlan devices
- * Note: devices that have been registered that but not
- * brought up will exist but have no module ref count.
- */
-static void __exit vlan_cleanup_devices(void)
-{
- struct net_device *dev, *nxt;
-
- rtnl_lock();
- for_each_netdev_safe(dev, nxt) {
- if (dev->priv_flags & IFF_802_1Q_VLAN) {
- unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
- VLAN_DEV_INFO(dev)->vlan_id);
- unregister_netdevice(dev);
- }
- }
- rtnl_unlock();
+err2:
+ unregister_netdevice_notifier(&vlan_notifier_block);
+err1:
+ vlan_proc_cleanup();
+ dev_remove_pack(&vlan_packet_type);
+ return err;
}
/*
@@ -136,13 +123,13 @@ static void __exit vlan_cleanup_module(void)
{
int i;
+ vlan_netlink_fini();
vlan_ioctl_set(NULL);
/* Un-register us from receiving netdevice events */
unregister_netdevice_notifier(&vlan_notifier_block);
dev_remove_pack(&vlan_packet_type);
- vlan_cleanup_devices();
/* This table must be empty if there are no module
* references left.
@@ -197,6 +184,34 @@ static void vlan_group_free(struct vlan_group *grp)
kfree(grp);
}
+static struct vlan_group *vlan_group_alloc(int ifindex)
+{
+ struct vlan_group *grp;
+ unsigned int size;
+ unsigned int i;
+
+ grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
+ if (!grp)
+ return NULL;
+
+ size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
+
+ for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
+ grp->vlan_devices_arrays[i] = kzalloc(size, GFP_KERNEL);
+ if (!grp->vlan_devices_arrays[i])
+ goto err;
+ }
+
+ grp->real_dev_ifindex = ifindex;
+ hlist_add_head_rcu(&grp->hlist,
+ &vlan_group_hash[vlan_grp_hashfn(ifindex)]);
+ return grp;
+
+err:
+ vlan_group_free(grp);
+ return NULL;
+}
+
static void vlan_rcu_free(struct rcu_head *rcu)
{
vlan_group_free(container_of(rcu, struct vlan_group, rcu));
@@ -240,10 +255,8 @@ static int unregister_vlan_dev(struct net_device *real_dev,
* interlock with HW accelerating devices or SW vlan
* input packet processing.
*/
- if (real_dev->features &
- (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER)) {
+ if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
real_dev->vlan_rx_kill_vid(real_dev, vlan_id);
- }
vlan_group_set_device(grp, vlan_id, NULL);
synchronize_net();
@@ -280,50 +293,66 @@ static int unregister_vlan_dev(struct net_device *real_dev,
return ret;
}
-static int unregister_vlan_device(const char *vlan_IF_name)
+int unregister_vlan_device(struct net_device *dev)
{
- struct net_device *dev = NULL;
int ret;
+ ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
+ VLAN_DEV_INFO(dev)->vlan_id);
+ unregister_netdevice(dev);
- dev = dev_get_by_name(vlan_IF_name);
- ret = -EINVAL;
- if (dev) {
- if (dev->priv_flags & IFF_802_1Q_VLAN) {
- rtnl_lock();
+ if (ret == 1)
+ ret = 0;
+ return ret;
+}
- ret = unregister_vlan_dev(VLAN_DEV_INFO(dev)->real_dev,
- VLAN_DEV_INFO(dev)->vlan_id);
+/*
+ * vlan 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 vlan_netdev_xmit_lock_key;
- dev_put(dev);
- unregister_netdevice(dev);
+static int vlan_dev_init(struct net_device *dev)
+{
+ struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
- rtnl_unlock();
+ /* IFF_BROADCAST|IFF_MULTICAST; ??? */
+ dev->flags = real_dev->flags & ~IFF_UP;
+ dev->iflink = real_dev->ifindex;
+ dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
+ (1<<__LINK_STATE_DORMANT))) |
+ (1<<__LINK_STATE_PRESENT);
- if (ret == 1)
- ret = 0;
- } else {
- printk(VLAN_ERR
- "%s: ERROR: Tried to remove a non-vlan device "
- "with VLAN code, name: %s priv_flags: %hX\n",
- __FUNCTION__, dev->name, dev->priv_flags);
- dev_put(dev);
- ret = -EPERM;
- }
+ if (is_zero_ether_addr(dev->dev_addr))
+ memcpy(dev->dev_addr, real_dev->dev_addr, dev->addr_len);
+ if (is_zero_ether_addr(dev->broadcast))
+ memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
+
+ if (real_dev->features & NETIF_F_HW_VLAN_TX) {
+ dev->hard_header = real_dev->hard_header;
+ dev->hard_header_len = real_dev->hard_header_len;
+ dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
+ dev->rebuild_header = real_dev->rebuild_header;
} else {
-#ifdef VLAN_DEBUG
- printk(VLAN_DBG "%s: WARNING: Could not find dev.\n", __FUNCTION__);
-#endif
- ret = -EINVAL;
+ dev->hard_header = vlan_dev_hard_header;
+ dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
+ dev->hard_start_xmit = vlan_dev_hard_start_xmit;
+ dev->rebuild_header = vlan_dev_rebuild_header;
}
+ dev->hard_header_parse = real_dev->hard_header_parse;
+ dev->hard_header_cache = NULL;
- return ret;
+ lockdep_set_class(&dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
+ return 0;
}
-static void vlan_setup(struct net_device *new_dev)
+void vlan_setup(struct net_device *new_dev)
{
SET_MODULE_OWNER(new_dev);
+ ether_setup(new_dev);
+
/* new_dev->ifindex = 0; it will be set when added to
* the global list.
* iflink is set as well.
@@ -340,12 +369,15 @@ static void vlan_setup(struct net_device *new_dev)
/* set up method calls */
new_dev->change_mtu = vlan_dev_change_mtu;
+ new_dev->init = vlan_dev_init;
new_dev->open = vlan_dev_open;
new_dev->stop = vlan_dev_stop;
- new_dev->set_mac_address = vlan_dev_set_mac_address;
new_dev->set_multicast_list = vlan_dev_set_multicast_list;
+ new_dev->change_rx_flags = vlan_change_rx_flags;
new_dev->destructor = free_netdev;
new_dev->do_ioctl = vlan_dev_ioctl;
+
+ memset(new_dev->broadcast, 0, ETH_ALEN);
}
static void vlan_transfer_operstate(const struct net_device *dev, struct net_device *vlandev)
@@ -368,79 +400,110 @@ static void vlan_transfer_operstate(const struct net_device *dev, struct net_dev
}
}
-/*
- * vlan 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 vlan_netdev_xmit_lock_key;
-
-
-/* Attach a VLAN device to a mac address (ie Ethernet Card).
- * Returns the device that was created, or NULL if there was
- * an error of some kind.
- */
-static struct net_device *register_vlan_device(const char *eth_IF_name,
- unsigned short VLAN_ID)
+int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id)
{
- struct vlan_group *grp;
- struct net_device *new_dev;
- struct net_device *real_dev; /* the ethernet device */
- char name[IFNAMSIZ];
- int i;
-
-#ifdef VLAN_DEBUG
- printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n",
- __FUNCTION__, eth_IF_name, VLAN_ID);
-#endif
-
- if (VLAN_ID >= VLAN_VID_MASK)
- goto out_ret_null;
-
- /* find the device relating to eth_IF_name. */
- real_dev = dev_get_by_name(eth_IF_name);
- if (!real_dev)
- goto out_ret_null;
-
if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
printk(VLAN_DBG "%s: VLANs not supported on %s.\n",
__FUNCTION__, real_dev->name);
- goto out_put_dev;
+ return -EOPNOTSUPP;
}
if ((real_dev->features & NETIF_F_HW_VLAN_RX) &&
- (real_dev->vlan_rx_register == NULL ||
- real_dev->vlan_rx_kill_vid == NULL)) {
+ !real_dev->vlan_rx_register) {
printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
__FUNCTION__, real_dev->name);
- goto out_put_dev;
+ return -EOPNOTSUPP;
}
if ((real_dev->features & NETIF_F_HW_VLAN_FILTER) &&
- (real_dev->vlan_rx_add_vid == NULL ||
- real_dev->vlan_rx_kill_vid == NULL)) {
+ (!real_dev->vlan_rx_add_vid || !real_dev->vlan_rx_kill_vid)) {
printk(VLAN_DBG "%s: Device %s has buggy VLAN hw accel.\n",
__FUNCTION__, real_dev->name);
- goto out_put_dev;
+ return -EOPNOTSUPP;
}
- /* From this point on, all the data structures must remain
- * consistent.
- */
- rtnl_lock();
-
/* The real device must be up and operating in order to
* assosciate a VLAN device with it.
*/
if (!(real_dev->flags & IFF_UP))
- goto out_unlock;
+ return -ENETDOWN;
- if (__find_vlan_dev(real_dev, VLAN_ID) != NULL) {
+ if (__find_vlan_dev(real_dev, vlan_id) != NULL) {
/* was already registered. */
printk(VLAN_DBG "%s: ALREADY had VLAN registered\n", __FUNCTION__);
- goto out_unlock;
+ return -EEXIST;
}
+ return 0;
+}
+
+int register_vlan_dev(struct net_device *dev)
+{
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+ struct net_device *real_dev = vlan->real_dev;
+ unsigned short vlan_id = vlan->vlan_id;
+ struct vlan_group *grp, *ngrp = NULL;
+ int err;
+
+ grp = __vlan_find_group(real_dev->ifindex);
+ if (!grp) {
+ ngrp = grp = vlan_group_alloc(real_dev->ifindex);
+ if (!grp)
+ return -ENOBUFS;
+ }
+
+ err = register_netdevice(dev);
+ if (err < 0)
+ goto out_free_group;
+
+ /* Account for reference in struct vlan_dev_info */
+ dev_hold(real_dev);
+
+ vlan_transfer_operstate(real_dev, dev);
+ linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */
+
+ /* So, got the sucker initialized, now lets place
+ * it into our local structure.
+ */
+ vlan_group_set_device(grp, vlan_id, dev);
+ if (ngrp && real_dev->features & NETIF_F_HW_VLAN_RX)
+ real_dev->vlan_rx_register(real_dev, ngrp);
+ if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
+ real_dev->vlan_rx_add_vid(real_dev, vlan_id);
+
+ if (vlan_proc_add_dev(dev) < 0)
+ printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
+ dev->name);
+ return 0;
+
+out_free_group:
+ if (ngrp)
+ vlan_group_free(ngrp);
+ return err;
+}
+
+/* Attach a VLAN device to a mac address (ie Ethernet Card).
+ * Returns 0 if the device was created or a negative error code otherwise.
+ */
+static int register_vlan_device(struct net_device *real_dev,
+ unsigned short VLAN_ID)
+{
+ struct net_device *new_dev;
+ char name[IFNAMSIZ];
+ int err;
+
+#ifdef VLAN_DEBUG
+ printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n",
+ __FUNCTION__, eth_IF_name, VLAN_ID);
+#endif
+
+ if (VLAN_ID >= VLAN_VID_MASK)
+ return -ERANGE;
+
+ err = vlan_check_real_dev(real_dev, VLAN_ID);
+ if (err < 0)
+ return err;
+
/* Gotta set up the fields for the device. */
#ifdef VLAN_DEBUG
printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n",
@@ -475,138 +538,64 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
vlan_setup);
if (new_dev == NULL)
- goto out_unlock;
-
-#ifdef VLAN_DEBUG
- printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
-#endif
- /* IFF_BROADCAST|IFF_MULTICAST; ??? */
- new_dev->flags = real_dev->flags;
- new_dev->flags &= ~IFF_UP;
-
- new_dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
- (1<<__LINK_STATE_DORMANT))) |
- (1<<__LINK_STATE_PRESENT);
+ return -ENOBUFS;
/* need 4 bytes for extra VLAN header info,
* hope the underlying device can handle it.
*/
new_dev->mtu = real_dev->mtu;
- /* TODO: maybe just assign it to be ETHERNET? */
- new_dev->type = real_dev->type;
-
- new_dev->hard_header_len = real_dev->hard_header_len;
- if (!(real_dev->features & NETIF_F_HW_VLAN_TX)) {
- /* Regular ethernet + 4 bytes (18 total). */
- new_dev->hard_header_len += VLAN_HLEN;
- }
-
+#ifdef VLAN_DEBUG
+ printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n",
new_dev->priv,
sizeof(struct vlan_dev_info));
-
- memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
- memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
- new_dev->addr_len = real_dev->addr_len;
-
- if (real_dev->features & NETIF_F_HW_VLAN_TX) {
- new_dev->hard_header = real_dev->hard_header;
- new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
- new_dev->rebuild_header = real_dev->rebuild_header;
- } else {
- new_dev->hard_header = vlan_dev_hard_header;
- new_dev->hard_start_xmit = vlan_dev_hard_start_xmit;
- new_dev->rebuild_header = vlan_dev_rebuild_header;
- }
- new_dev->hard_header_parse = real_dev->hard_header_parse;
+#endif
VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
VLAN_DEV_INFO(new_dev)->dent = NULL;
- VLAN_DEV_INFO(new_dev)->flags = 1;
+ VLAN_DEV_INFO(new_dev)->flags = VLAN_FLAG_REORDER_HDR;
-#ifdef VLAN_DEBUG
- printk(VLAN_DBG "About to go find the group for idx: %i\n",
- real_dev->ifindex);
-#endif
-
- if (register_netdevice(new_dev))
+ new_dev->rtnl_link_ops = &vlan_link_ops;
+ err = register_vlan_dev(new_dev);
+ if (err < 0)
goto out_free_newdev;
- lockdep_set_class(&new_dev->_xmit_lock, &vlan_netdev_xmit_lock_key);
-
- new_dev->iflink = real_dev->ifindex;
- vlan_transfer_operstate(real_dev, new_dev);
- linkwatch_fire_event(new_dev); /* _MUST_ call rfc2863_policy() */
-
- /* So, got the sucker initialized, now lets place
- * it into our local structure.
- */
- grp = __vlan_find_group(real_dev->ifindex);
-
- /* Note, we are running under the RTNL semaphore
- * so it cannot "appear" on us.
- */
- if (!grp) { /* need to add a new group */
- grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL);
- if (!grp)
- goto out_free_unregister;
-
- for (i=0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) {
- grp->vlan_devices_arrays[i] = kzalloc(
- sizeof(struct net_device *)*VLAN_GROUP_ARRAY_PART_LEN,
- GFP_KERNEL);
-
- if (!grp->vlan_devices_arrays[i])
- goto out_free_arrays;
- }
-
- /* printk(KERN_ALERT "VLAN REGISTER: Allocated new group.\n"); */
- grp->real_dev_ifindex = real_dev->ifindex;
-
- hlist_add_head_rcu(&grp->hlist,
- &vlan_group_hash[vlan_grp_hashfn(real_dev->ifindex)]);
-
- if (real_dev->features & NETIF_F_HW_VLAN_RX)
- real_dev->vlan_rx_register(real_dev, grp);
- }
-
- vlan_group_set_device(grp, VLAN_ID, new_dev);
-
- if (vlan_proc_add_dev(new_dev)<0)/* create it's proc entry */
- printk(KERN_WARNING "VLAN: failed to add proc entry for %s\n",
- new_dev->name);
-
- if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
- real_dev->vlan_rx_add_vid(real_dev, VLAN_ID);
-
- rtnl_unlock();
-
-
+ /* Account for reference in struct vlan_dev_info */
+ dev_hold(real_dev);
#ifdef VLAN_DEBUG
printk(VLAN_DBG "Allocated new device successfully, returning.\n");
#endif
- return new_dev;
-
-out_free_arrays:
- vlan_group_free(grp);
-
-out_free_unregister:
- unregister_netdev(new_dev);
- goto out_unlock;
+ return 0;
out_free_newdev:
free_netdev(new_dev);
+ return err;
+}
-out_unlock:
- rtnl_unlock();
+static void vlan_sync_address(struct net_device *dev,
+ struct net_device *vlandev)
+{
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(vlandev);
-out_put_dev:
- dev_put(real_dev);
+ /* May be called without an actual change */
+ if (!compare_ether_addr(vlan->real_dev_addr, dev->dev_addr))
+ return;
-out_ret_null:
- return NULL;
+ /* vlan address was different from the old address and is equal to
+ * the new address */
+ if (compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
+ !compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
+ dev_unicast_delete(dev, vlandev->dev_addr, ETH_ALEN);
+
+ /* vlan address was equal to the old address and is different from
+ * the new address */
+ if (!compare_ether_addr(vlandev->dev_addr, vlan->real_dev_addr) &&
+ compare_ether_addr(vlandev->dev_addr, dev->dev_addr))
+ dev_unicast_add(dev, vlandev->dev_addr, ETH_ALEN);
+
+ memcpy(vlan->real_dev_addr, dev->dev_addr, ETH_ALEN);
}
static int vlan_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
@@ -635,6 +624,17 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
}
break;
+ case NETDEV_CHANGEADDR:
+ /* Adjust unicast filters on underlying device */
+ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
+ vlandev = vlan_group_get_device(grp, i);
+ if (!vlandev)
+ continue;
+
+ vlan_sync_address(dev, vlandev);
+ }
+ break;
+
case NETDEV_DOWN:
/* Put all VLANs for this dev in the down state too. */
for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
@@ -697,9 +697,10 @@ out:
*/
static int vlan_ioctl_handler(void __user *arg)
{
- int err = 0;
+ int err;
unsigned short vid = 0;
struct vlan_ioctl_args args;
+ struct net_device *dev = NULL;
if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
return -EFAULT;
@@ -712,32 +713,57 @@ static int vlan_ioctl_handler(void __user *arg)
printk(VLAN_DBG "%s: args.cmd: %x\n", __FUNCTION__, args.cmd);
#endif
+ rtnl_lock();
+
+ switch (args.cmd) {
+ case SET_VLAN_INGRESS_PRIORITY_CMD:
+ case SET_VLAN_EGRESS_PRIORITY_CMD:
+ case SET_VLAN_FLAG_CMD:
+ case ADD_VLAN_CMD:
+ case DEL_VLAN_CMD:
+ case GET_VLAN_REALDEV_NAME_CMD:
+ case GET_VLAN_VID_CMD:
+ err = -ENODEV;
+ dev = __dev_get_by_name(args.device1);
+ if (!dev)
+ goto out;
+
+ err = -EINVAL;
+ if (args.cmd != ADD_VLAN_CMD &&
+ !(dev->priv_flags & IFF_802_1Q_VLAN))
+ goto out;
+ }
+
switch (args.cmd) {
case SET_VLAN_INGRESS_PRIORITY_CMD:
+ err = -EPERM;
if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- err = vlan_dev_set_ingress_priority(args.device1,
- args.u.skb_priority,
- args.vlan_qos);
+ break;
+ vlan_dev_set_ingress_priority(dev,
+ args.u.skb_priority,
+ args.vlan_qos);
break;
case SET_VLAN_EGRESS_PRIORITY_CMD:
+ err = -EPERM;
if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- err = vlan_dev_set_egress_priority(args.device1,
+ break;
+ err = vlan_dev_set_egress_priority(dev,
args.u.skb_priority,
args.vlan_qos);
break;
case SET_VLAN_FLAG_CMD:
+ err = -EPERM;
if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- err = vlan_dev_set_vlan_flag(args.device1,
+ break;
+ err = vlan_dev_set_vlan_flag(dev,
args.u.flag,
args.vlan_qos);
break;
case SET_VLAN_NAME_TYPE_CMD:
+ err = -EPERM;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if ((args.u.name_type >= 0) &&
@@ -750,26 +776,17 @@ static int vlan_ioctl_handler(void __user *arg)
break;
case ADD_VLAN_CMD:
+ err = -EPERM;
if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- /* we have been given the name of the Ethernet Device we want to
- * talk to: args.dev1 We also have the
- * VLAN ID: args.u.VID
- */
- if (register_vlan_device(args.device1, args.u.VID)) {
- err = 0;
- } else {
- err = -EINVAL;
- }
+ break;
+ err = register_vlan_device(dev, args.u.VID);
break;
case DEL_VLAN_CMD:
+ err = -EPERM;
if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- /* Here, the args.dev1 is the actual VLAN we want
- * to get rid of.
- */
- err = unregister_vlan_device(args.device1);
+ break;
+ err = unregister_vlan_device(dev);
break;
case GET_VLAN_INGRESS_PRIORITY_CMD:
@@ -793,9 +810,7 @@ static int vlan_ioctl_handler(void __user *arg)
err = -EINVAL;
break;
case GET_VLAN_REALDEV_NAME_CMD:
- err = vlan_dev_get_realdev_name(args.device1, args.u.device2);
- if (err)
- goto out;
+ vlan_dev_get_realdev_name(dev, args.u.device2);
if (copy_to_user(arg, &args,
sizeof(struct vlan_ioctl_args))) {
err = -EFAULT;
@@ -803,9 +818,7 @@ static int vlan_ioctl_handler(void __user *arg)
break;
case GET_VLAN_VID_CMD:
- err = vlan_dev_get_vid(args.device1, &vid);
- if (err)
- goto out;
+ vlan_dev_get_vid(dev, &vid);
args.u.VID = vid;
if (copy_to_user(arg, &args,
sizeof(struct vlan_ioctl_args))) {
@@ -817,9 +830,11 @@ static int vlan_ioctl_handler(void __user *arg)
/* pass on to underlying device instead?? */
printk(VLAN_DBG "%s: Unknown VLAN CMD: %x \n",
__FUNCTION__, args.cmd);
- return -EINVAL;
+ err = -EINVAL;
+ break;
}
out:
+ rtnl_unlock();
return err;
}
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 1976cdba8f7..7df5b293557 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -58,15 +58,28 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
int vlan_dev_change_mtu(struct net_device *dev, int new_mtu);
-int vlan_dev_set_mac_address(struct net_device *dev, void* addr);
int vlan_dev_open(struct net_device* dev);
int vlan_dev_stop(struct net_device* dev);
int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd);
-int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
-int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
-int vlan_dev_get_realdev_name(const char* dev_name, char* result);
-int vlan_dev_get_vid(const char* dev_name, unsigned short* result);
+void vlan_dev_set_ingress_priority(const struct net_device *dev,
+ u32 skb_prio, short vlan_prio);
+int vlan_dev_set_egress_priority(const struct net_device *dev,
+ u32 skb_prio, short vlan_prio);
+int vlan_dev_set_vlan_flag(const struct net_device *dev,
+ u32 flag, short flag_val);
+void vlan_dev_get_realdev_name(const struct net_device *dev, char *result);
+void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result);
+void vlan_change_rx_flags(struct net_device *dev, int change);
void vlan_dev_set_multicast_list(struct net_device *vlan_dev);
+int vlan_check_real_dev(struct net_device *real_dev, unsigned short vlan_id);
+void vlan_setup(struct net_device *dev);
+int register_vlan_dev(struct net_device *dev);
+int unregister_vlan_device(struct net_device *dev);
+
+int vlan_netlink_init(void);
+void vlan_netlink_fini(void);
+
+extern struct rtnl_link_ops vlan_link_ops;
+
#endif /* !(__BEN_VLAN_802_1Q_INC__) */
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index ec46084f44b..4d2aa4dd42a 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -73,7 +73,7 @@ int vlan_dev_rebuild_header(struct sk_buff *skb)
static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
{
- if (VLAN_DEV_INFO(skb->dev)->flags & 1) {
+ if (VLAN_DEV_INFO(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) {
if (skb_shared(skb) || skb_cloned(skb)) {
struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
kfree_skb(skb);
@@ -350,7 +350,8 @@ int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev,
* header shuffling in the hard_start_xmit. Users can turn off this
* REORDER behaviour with the vconfig tool.
*/
- build_vlan_header = ((VLAN_DEV_INFO(dev)->flags & 1) == 0);
+ if (!(VLAN_DEV_INFO(dev)->flags & VLAN_FLAG_REORDER_HDR))
+ build_vlan_header = 1;
if (build_vlan_header) {
vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN);
@@ -534,272 +535,123 @@ int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-int vlan_dev_set_ingress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
+void vlan_dev_set_ingress_priority(const struct net_device *dev,
+ u32 skb_prio, short vlan_prio)
{
- struct net_device *dev = dev_get_by_name(dev_name);
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
- if (dev) {
- if (dev->priv_flags & IFF_802_1Q_VLAN) {
- /* see if a priority mapping exists.. */
- VLAN_DEV_INFO(dev)->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
- dev_put(dev);
- return 0;
- }
+ if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio)
+ vlan->nr_ingress_mappings--;
+ else if (!vlan->ingress_priority_map[vlan_prio & 0x7] && skb_prio)
+ vlan->nr_ingress_mappings++;
- dev_put(dev);
- }
- return -EINVAL;
+ vlan->ingress_priority_map[vlan_prio & 0x7] = skb_prio;
}
-int vlan_dev_set_egress_priority(char *dev_name, __u32 skb_prio, short vlan_prio)
+int vlan_dev_set_egress_priority(const struct net_device *dev,
+ u32 skb_prio, short vlan_prio)
{
- struct net_device *dev = dev_get_by_name(dev_name);
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
struct vlan_priority_tci_mapping *mp = NULL;
struct vlan_priority_tci_mapping *np;
+ u32 vlan_qos = (vlan_prio << 13) & 0xE000;
- if (dev) {
- if (dev->priv_flags & IFF_802_1Q_VLAN) {
- /* See if a priority mapping exists.. */
- mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
- while (mp) {
- if (mp->priority == skb_prio) {
- mp->vlan_qos = ((vlan_prio << 13) & 0xE000);
- dev_put(dev);
- return 0;
- }
- mp = mp->next;
- }
-
- /* Create a new mapping then. */
- mp = VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF];
- np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
- if (np) {
- np->next = mp;
- np->priority = skb_prio;
- np->vlan_qos = ((vlan_prio << 13) & 0xE000);
- VLAN_DEV_INFO(dev)->egress_priority_map[skb_prio & 0xF] = np;
- dev_put(dev);
- return 0;
- } else {
- dev_put(dev);
- return -ENOBUFS;
- }
- }
- dev_put(dev);
- }
- return -EINVAL;
-}
-
-/* Flags are defined in the vlan_dev_info class in include/linux/if_vlan.h file. */
-int vlan_dev_set_vlan_flag(char *dev_name, __u32 flag, short flag_val)
-{
- struct net_device *dev = dev_get_by_name(dev_name);
-
- if (dev) {
- if (dev->priv_flags & IFF_802_1Q_VLAN) {
- /* verify flag is supported */
- if (flag == 1) {
- if (flag_val) {
- VLAN_DEV_INFO(dev)->flags |= 1;
- } else {
- VLAN_DEV_INFO(dev)->flags &= ~1;
- }
- dev_put(dev);
- return 0;
- } else {
- printk(KERN_ERR "%s: flag %i is not valid.\n",
- __FUNCTION__, (int)(flag));
- dev_put(dev);
- return -EINVAL;
- }
- } else {
- printk(KERN_ERR
- "%s: %s is not a vlan device, priv_flags: %hX.\n",
- __FUNCTION__, dev->name, dev->priv_flags);
- dev_put(dev);
+ /* See if a priority mapping exists.. */
+ mp = vlan->egress_priority_map[skb_prio & 0xF];
+ while (mp) {
+ if (mp->priority == skb_prio) {
+ if (mp->vlan_qos && !vlan_qos)
+ vlan->nr_egress_mappings--;
+ else if (!mp->vlan_qos && vlan_qos)
+ vlan->nr_egress_mappings++;
+ mp->vlan_qos = vlan_qos;
+ return 0;
}
- } else {
- printk(KERN_ERR "%s: Could not find device: %s\n",
- __FUNCTION__, dev_name);
+ mp = mp->next;
}
- return -EINVAL;
-}
-
-
-int vlan_dev_get_realdev_name(const char *dev_name, char* result)
-{
- struct net_device *dev = dev_get_by_name(dev_name);
- int rv = 0;
- if (dev) {
- if (dev->priv_flags & IFF_802_1Q_VLAN) {
- strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
- rv = 0;
- } else {
- rv = -EINVAL;
- }
- dev_put(dev);
- } else {
- rv = -ENODEV;
- }
- return rv;
+ /* Create a new mapping then. */
+ mp = vlan->egress_priority_map[skb_prio & 0xF];
+ np = kmalloc(sizeof(struct vlan_priority_tci_mapping), GFP_KERNEL);
+ if (!np)
+ return -ENOBUFS;
+
+ np->next = mp;
+ np->priority = skb_prio;
+ np->vlan_qos = vlan_qos;
+ vlan->egress_priority_map[skb_prio & 0xF] = np;
+ if (vlan_qos)
+ vlan->nr_egress_mappings++;
+ return 0;
}
-int vlan_dev_get_vid(const char *dev_name, unsigned short* result)
+/* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */
+int vlan_dev_set_vlan_flag(const struct net_device *dev,
+ u32 flag, short flag_val)
{
- struct net_device *dev = dev_get_by_name(dev_name);
- int rv = 0;
- if (dev) {
- if (dev->priv_flags & IFF_802_1Q_VLAN) {
- *result = VLAN_DEV_INFO(dev)->vlan_id;
- rv = 0;
+ /* verify flag is supported */
+ if (flag == VLAN_FLAG_REORDER_HDR) {
+ if (flag_val) {
+ VLAN_DEV_INFO(dev)->flags |= VLAN_FLAG_REORDER_HDR;
} else {
- rv = -EINVAL;
+ VLAN_DEV_INFO(dev)->flags &= ~VLAN_FLAG_REORDER_HDR;
}
- dev_put(dev);
- } else {
- rv = -ENODEV;
+ return 0;
}
- return rv;
+ printk(KERN_ERR "%s: flag %i is not valid.\n", __FUNCTION__, flag);
+ return -EINVAL;
}
-
-int vlan_dev_set_mac_address(struct net_device *dev, void *addr_struct_p)
+void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
{
- struct sockaddr *addr = (struct sockaddr *)(addr_struct_p);
- int i;
-
- if (netif_running(dev))
- return -EBUSY;
-
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
- printk("%s: Setting MAC address to ", dev->name);
- for (i = 0; i < 6; i++)
- printk(" %2.2x", dev->dev_addr[i]);
- printk(".\n");
-
- if (memcmp(VLAN_DEV_INFO(dev)->real_dev->dev_addr,
- dev->dev_addr,
- dev->addr_len) != 0) {
- if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_PROMISC)) {
- int flgs = VLAN_DEV_INFO(dev)->real_dev->flags;
-
- /* Increment our in-use promiscuity counter */
- dev_set_promiscuity(VLAN_DEV_INFO(dev)->real_dev, 1);
-
- /* Make PROMISC visible to the user. */
- flgs |= IFF_PROMISC;
- printk("VLAN (%s): Setting underlying device (%s) to promiscious mode.\n",
- dev->name, VLAN_DEV_INFO(dev)->real_dev->name);
- dev_change_flags(VLAN_DEV_INFO(dev)->real_dev, flgs);
- }
- } else {
- printk("VLAN (%s): Underlying device (%s) has same MAC, not checking promiscious mode.\n",
- dev->name, VLAN_DEV_INFO(dev)->real_dev->name);
- }
-
- return 0;
+ strncpy(result, VLAN_DEV_INFO(dev)->real_dev->name, 23);
}
-static inline int vlan_dmi_equals(struct dev_mc_list *dmi1,
- struct dev_mc_list *dmi2)
+void vlan_dev_get_vid(const struct net_device *dev, unsigned short *result)
{
- return ((dmi1->dmi_addrlen == dmi2->dmi_addrlen) &&
- (memcmp(dmi1->dmi_addr, dmi2->dmi_addr, dmi1->dmi_addrlen) == 0));
+ *result = VLAN_DEV_INFO(dev)->vlan_id;
}
-/** dmi is a single entry into a dev_mc_list, a single node. mc_list is
- * an entire list, and we'll iterate through it.
- */
-static int vlan_should_add_mc(struct dev_mc_list *dmi, struct dev_mc_list *mc_list)
+int vlan_dev_open(struct net_device *dev)
{
- struct dev_mc_list *idmi;
-
- for (idmi = mc_list; idmi != NULL; ) {
- if (vlan_dmi_equals(dmi, idmi)) {
- if (dmi->dmi_users > idmi->dmi_users)
- return 1;
- else
- return 0;
- } else {
- idmi = idmi->next;
- }
- }
-
- return 1;
-}
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+ struct net_device *real_dev = vlan->real_dev;
+ int err;
-static inline void vlan_destroy_mc_list(struct dev_mc_list *mc_list)
-{
- struct dev_mc_list *dmi = mc_list;
- struct dev_mc_list *next;
+ if (!(real_dev->flags & IFF_UP))
+ return -ENETDOWN;
- while(dmi) {
- next = dmi->next;
- kfree(dmi);
- dmi = next;
+ if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) {
+ err = dev_unicast_add(real_dev, dev->dev_addr, ETH_ALEN);
+ if (err < 0)
+ return err;
}
-}
-
-static void vlan_copy_mc_list(struct dev_mc_list *mc_list, struct vlan_dev_info *vlan_info)
-{
- struct dev_mc_list *dmi, *new_dmi;
+ memcpy(vlan->real_dev_addr, real_dev->dev_addr, ETH_ALEN);
- vlan_destroy_mc_list(vlan_info->old_mc_list);
- vlan_info->old_mc_list = NULL;
+ if (dev->flags & IFF_ALLMULTI)
+ dev_set_allmulti(real_dev, 1);
+ if (dev->flags & IFF_PROMISC)
+ dev_set_promiscuity(real_dev, 1);
- for (dmi = mc_list; dmi != NULL; dmi = dmi->next) {
- new_dmi = kmalloc(sizeof(*new_dmi), GFP_ATOMIC);
- if (new_dmi == NULL) {
- printk(KERN_ERR "vlan: cannot allocate memory. "
- "Multicast may not work properly from now.\n");
- return;
- }
-
- /* Copy whole structure, then make new 'next' pointer */
- *new_dmi = *dmi;
- new_dmi->next = vlan_info->old_mc_list;
- vlan_info->old_mc_list = new_dmi;
- }
+ return 0;
}
-static void vlan_flush_mc_list(struct net_device *dev)
+int vlan_dev_stop(struct net_device *dev)
{
- struct dev_mc_list *dmi = dev->mc_list;
-
- while (dmi) {
- printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from vlan interface\n",
- dev->name,
- dmi->dmi_addr[0],
- dmi->dmi_addr[1],
- dmi->dmi_addr[2],
- dmi->dmi_addr[3],
- dmi->dmi_addr[4],
- dmi->dmi_addr[5]);
- dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
- dmi = dev->mc_list;
- }
+ struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
- /* dev->mc_list is NULL by the time we get here. */
- vlan_destroy_mc_list(VLAN_DEV_INFO(dev)->old_mc_list);
- VLAN_DEV_INFO(dev)->old_mc_list = NULL;
-}
+ dev_mc_unsync(real_dev, dev);
+ if (dev->flags & IFF_ALLMULTI)
+ dev_set_allmulti(real_dev, -1);
+ if (dev->flags & IFF_PROMISC)
+ dev_set_promiscuity(real_dev, -1);
-int vlan_dev_open(struct net_device *dev)
-{
- if (!(VLAN_DEV_INFO(dev)->real_dev->flags & IFF_UP))
- return -ENETDOWN;
+ if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr))
+ dev_unicast_delete(real_dev, dev->dev_addr, dev->addr_len);
return 0;
}
-int vlan_dev_stop(struct net_device *dev)
-{
- vlan_flush_mc_list(dev);
- return 0;
-}
-
int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
@@ -827,68 +679,18 @@ int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return err;
}
-/** Taken from Gleb + Lennert's VLAN code, and modified... */
-void vlan_dev_set_multicast_list(struct net_device *vlan_dev)
+void vlan_change_rx_flags(struct net_device *dev, int change)
{
- struct dev_mc_list *dmi;
- struct net_device *real_dev;
- int inc;
-
- if (vlan_dev && (vlan_dev->priv_flags & IFF_802_1Q_VLAN)) {
- /* Then it's a real vlan device, as far as we can tell.. */
- real_dev = VLAN_DEV_INFO(vlan_dev)->real_dev;
-
- /* compare the current promiscuity to the last promisc we had.. */
- inc = vlan_dev->promiscuity - VLAN_DEV_INFO(vlan_dev)->old_promiscuity;
- if (inc) {
- printk(KERN_INFO "%s: dev_set_promiscuity(master, %d)\n",
- vlan_dev->name, inc);
- dev_set_promiscuity(real_dev, inc); /* found in dev.c */
- VLAN_DEV_INFO(vlan_dev)->old_promiscuity = vlan_dev->promiscuity;
- }
-
- inc = vlan_dev->allmulti - VLAN_DEV_INFO(vlan_dev)->old_allmulti;
- if (inc) {
- printk(KERN_INFO "%s: dev_set_allmulti(master, %d)\n",
- vlan_dev->name, inc);
- dev_set_allmulti(real_dev, inc); /* dev.c */
- VLAN_DEV_INFO(vlan_dev)->old_allmulti = vlan_dev->allmulti;
- }
-
- /* looking for addresses to add to master's list */
- for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) {
- if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) {
- dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
- printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n",
- vlan_dev->name,
- dmi->dmi_addr[0],
- dmi->dmi_addr[1],
- dmi->dmi_addr[2],
- dmi->dmi_addr[3],
- dmi->dmi_addr[4],
- dmi->dmi_addr[5]);
- }
- }
+ struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev;
- /* looking for addresses to delete from master's list */
- for (dmi = VLAN_DEV_INFO(vlan_dev)->old_mc_list; dmi != NULL; dmi = dmi->next) {
- if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) {
- /* if we think we should add it to the new list, then we should really
- * delete it from the real list on the underlying device.
- */
- dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
- printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n",
- vlan_dev->name,
- dmi->dmi_addr[0],
- dmi->dmi_addr[1],
- dmi->dmi_addr[2],
- dmi->dmi_addr[3],
- dmi->dmi_addr[4],
- dmi->dmi_addr[5]);
- }
- }
+ if (change & IFF_ALLMULTI)
+ dev_set_allmulti(real_dev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+ if (change & IFF_PROMISC)
+ dev_set_promiscuity(real_dev, dev->flags & IFF_PROMISC ? 1 : -1);
+}
- /* save multicast list */
- vlan_copy_mc_list(vlan_dev->mc_list, VLAN_DEV_INFO(vlan_dev));
- }
+/** Taken from Gleb + Lennert's VLAN code, and modified... */
+void vlan_dev_set_multicast_list(struct net_device *vlan_dev)
+{
+ dev_mc_sync(VLAN_DEV_INFO(vlan_dev)->real_dev, vlan_dev);
}
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
new file mode 100644
index 00000000000..6cdd1e015e2
--- /dev/null
+++ b/net/8021q/vlan_netlink.c
@@ -0,0 +1,243 @@
+/*
+ * VLAN netlink control interface
+ *
+ * Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/netlink.h>
+#include <net/rtnetlink.h>
+#include "vlan.h"
+
+
+static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
+ [IFLA_VLAN_ID] = { .type = NLA_U16 },
+ [IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) },
+ [IFLA_VLAN_EGRESS_QOS] = { .type = NLA_NESTED },
+ [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = {
+ [IFLA_VLAN_QOS_MAPPING] = { .len = sizeof(struct ifla_vlan_qos_mapping) },
+};
+
+
+static inline int vlan_validate_qos_map(struct nlattr *attr)
+{
+ if (!attr)
+ return 0;
+ return nla_validate_nested(attr, IFLA_VLAN_QOS_MAX, vlan_map_policy);
+}
+
+static int vlan_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+ struct ifla_vlan_flags *flags;
+ u16 id;
+ int err;
+
+ if (tb[IFLA_ADDRESS]) {
+ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+ return -EINVAL;
+ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+ return -EADDRNOTAVAIL;
+ }
+
+ if (!data)
+ return -EINVAL;
+
+ if (data[IFLA_VLAN_ID]) {
+ id = nla_get_u16(data[IFLA_VLAN_ID]);
+ if (id >= VLAN_VID_MASK)
+ return -ERANGE;
+ }
+ if (data[IFLA_VLAN_FLAGS]) {
+ flags = nla_data(data[IFLA_VLAN_FLAGS]);
+ if ((flags->flags & flags->mask) & ~VLAN_FLAG_REORDER_HDR)
+ return -EINVAL;
+ }
+
+ err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
+ if (err < 0)
+ return err;
+ err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+static int vlan_changelink(struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+ struct ifla_vlan_flags *flags;
+ struct ifla_vlan_qos_mapping *m;
+ struct nlattr *attr;
+ int rem;
+
+ if (data[IFLA_VLAN_FLAGS]) {
+ flags = nla_data(data[IFLA_VLAN_FLAGS]);
+ vlan->flags = (vlan->flags & ~flags->mask) |
+ (flags->flags & flags->mask);
+ }
+ if (data[IFLA_VLAN_INGRESS_QOS]) {
+ nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
+ m = nla_data(attr);
+ vlan_dev_set_ingress_priority(dev, m->to, m->from);
+ }
+ }
+ if (data[IFLA_VLAN_EGRESS_QOS]) {
+ nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
+ m = nla_data(attr);
+ vlan_dev_set_egress_priority(dev, m->from, m->to);
+ }
+ }
+ return 0;
+}
+
+static int vlan_newlink(struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+ struct net_device *real_dev;
+ int err;
+
+ if (!data[IFLA_VLAN_ID])
+ return -EINVAL;
+
+ if (!tb[IFLA_LINK])
+ return -EINVAL;
+ real_dev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK]));
+ if (!real_dev)
+ return -ENODEV;
+
+ vlan->vlan_id = nla_get_u16(data[IFLA_VLAN_ID]);
+ vlan->real_dev = real_dev;
+ vlan->flags = VLAN_FLAG_REORDER_HDR;
+
+ err = vlan_check_real_dev(real_dev, vlan->vlan_id);
+ if (err < 0)
+ return err;
+
+ if (!tb[IFLA_MTU])
+ dev->mtu = real_dev->mtu;
+ else if (dev->mtu > real_dev->mtu)
+ return -EINVAL;
+
+ err = vlan_changelink(dev, tb, data);
+ if (err < 0)
+ return err;
+
+ return register_vlan_dev(dev);
+}
+
+static void vlan_dellink(struct net_device *dev)
+{
+ unregister_vlan_device(dev);
+}
+
+static inline size_t vlan_qos_map_size(unsigned int n)
+{
+ if (n == 0)
+ return 0;
+ /* IFLA_VLAN_{EGRESS,INGRESS}_QOS + n * IFLA_VLAN_QOS_MAPPING */
+ return nla_total_size(sizeof(struct nlattr)) +
+ nla_total_size(sizeof(struct ifla_vlan_qos_mapping)) * n;
+}
+
+static size_t vlan_get_size(const struct net_device *dev)
+{
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+
+ return nla_total_size(2) + /* IFLA_VLAN_ID */
+ vlan_qos_map_size(vlan->nr_ingress_mappings) +
+ vlan_qos_map_size(vlan->nr_egress_mappings);
+}
+
+static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+ struct vlan_dev_info *vlan = VLAN_DEV_INFO(dev);
+ struct vlan_priority_tci_mapping *pm;
+ struct ifla_vlan_flags f;
+ struct ifla_vlan_qos_mapping m;
+ struct nlattr *nest;
+ unsigned int i;
+
+ NLA_PUT_U16(skb, IFLA_VLAN_ID, VLAN_DEV_INFO(dev)->vlan_id);
+ if (vlan->flags) {
+ f.flags = vlan->flags;
+ f.mask = ~0;
+ NLA_PUT(skb, IFLA_VLAN_FLAGS, sizeof(f), &f);
+ }
+ if (vlan->nr_ingress_mappings) {
+ nest = nla_nest_start(skb, IFLA_VLAN_INGRESS_QOS);
+ if (nest == NULL)
+ goto nla_put_failure;
+
+ for (i = 0; i < ARRAY_SIZE(vlan->ingress_priority_map); i++) {
+ if (!vlan->ingress_priority_map[i])
+ continue;
+
+ m.from = i;
+ m.to = vlan->ingress_priority_map[i];
+ NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
+ sizeof(m), &m);
+ }
+ nla_nest_end(skb, nest);
+ }
+
+ if (vlan->nr_egress_mappings) {
+ nest = nla_nest_start(skb, IFLA_VLAN_EGRESS_QOS);
+ if (nest == NULL)
+ goto nla_put_failure;
+
+ for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
+ for (pm = vlan->egress_priority_map[i]; pm;
+ pm = pm->next) {
+ if (!pm->vlan_qos)
+ continue;
+
+ m.from = pm->priority;
+ m.to = (pm->vlan_qos >> 13) & 0x7;
+ NLA_PUT(skb, IFLA_VLAN_QOS_MAPPING,
+ sizeof(m), &m);
+ }
+ }
+ nla_nest_end(skb, nest);
+ }
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+struct rtnl_link_ops vlan_link_ops __read_mostly = {
+ .kind = "vlan",
+ .maxtype = IFLA_VLAN_MAX,
+ .policy = vlan_policy,
+ .priv_size = sizeof(struct vlan_dev_info),
+ .setup = vlan_setup,
+ .validate = vlan_validate,
+ .newlink = vlan_newlink,
+ .changelink = vlan_changelink,
+ .dellink = vlan_dellink,
+ .get_size = vlan_get_size,
+ .fill_info = vlan_fill_info,
+};
+
+int __init vlan_netlink_init(void)
+{
+ return rtnl_link_register(&vlan_link_ops);
+}
+
+void __exit vlan_netlink_fini(void)
+{
+ rtnl_link_unregister(&vlan_link_ops);
+}
+
+MODULE_ALIAS_RTNL_LINK("vlan");
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index d216a64421c..c0040c9064a 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -69,7 +69,7 @@ static const char name_conf[] = "config";
* Generic /proc/net/vlan/<file> file and inode operations
*/
-static struct seq_operations vlan_seq_ops = {
+static const struct seq_operations vlan_seq_ops = {
.start = vlan_seq_start,
.next = vlan_seq_next,
.stop = vlan_seq_stop,
@@ -342,7 +342,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset)
seq_printf(seq, "Device: %s", dev_info->real_dev->name);
/* now show all PRIORITY mappings relating to this VLAN */
seq_printf(seq,
- "\nINGRESS priority mappings: 0:%lu 1:%lu 2:%lu 3:%lu 4:%lu 5:%lu 6:%lu 7:%lu\n",
+ "\nINGRESS priority mappings: 0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u\n",
dev_info->ingress_priority_map[0],
dev_info->ingress_priority_map[1],
dev_info->ingress_priority_map[2],
@@ -357,7 +357,7 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset)
const struct vlan_priority_tci_mapping *mp
= dev_info->egress_priority_map[i];
while (mp) {
- seq_printf(seq, "%lu:%hu ",
+ seq_printf(seq, "%u:%hu ",
mp->priority, ((mp->vlan_qos >> 13) & 0x7));
mp = mp->next;
}
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
new file mode 100644
index 00000000000..66821cd64a7
--- /dev/null
+++ b/net/9p/Kconfig
@@ -0,0 +1,21 @@
+#
+# 9P protocol configuration
+#
+
+menuconfig NET_9P
+ depends on NET && EXPERIMENTAL
+ tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)"
+ help
+ If you say Y here, you will get experimental support for
+ Plan 9 resource sharing via the 9P2000 protocol.
+
+ See <http://v9fs.sf.net> for more information.
+
+ If unsure, say N.
+
+config NET_9P_DEBUG
+ bool "Debug information"
+ depends on NET_9P
+ help
+ Say Y if you want the 9P subsistem to log debug information.
+
diff --git a/net/9p/Makefile b/net/9p/Makefile
new file mode 100644
index 00000000000..85b3a7838ac
--- /dev/null
+++ b/net/9p/Makefile
@@ -0,0 +1,13 @@
+obj-$(CONFIG_NET_9P) := 9pnet.o
+
+9pnet-objs := \
+ mod.o \
+ trans_fd.o \
+ mux.o \
+ client.o \
+ conv.o \
+ error.o \
+ fcprint.o \
+ util.o \
+
+9pnet-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/9p/client.c b/net/9p/client.c
new file mode 100644
index 00000000000..cb170750337
--- /dev/null
+++ b/net/9p/client.c
@@ -0,0 +1,965 @@
+/*
+ * net/9p/clnt.c
+ *
+ * 9P Client
+ *
+ * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ * 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <net/9p/9p.h>
+#include <net/9p/transport.h>
+#include <net/9p/conn.h>
+#include <net/9p/client.h>
+
+static struct p9_fid *p9_fid_create(struct p9_client *clnt);
+static void p9_fid_destroy(struct p9_fid *fid);
+static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu);
+
+struct p9_client *p9_client_create(struct p9_transport *trans, int msize,
+ int dotu)
+{
+ int err, n;
+ struct p9_client *clnt;
+ struct p9_fcall *tc, *rc;
+ struct p9_str *version;
+
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL);
+ if (!clnt)
+ return ERR_PTR(-ENOMEM);
+
+ P9_DPRINTK(P9_DEBUG_9P, "clnt %p trans %p msize %d dotu %d\n",
+ clnt, trans, msize, dotu);
+ spin_lock_init(&clnt->lock);
+ clnt->trans = trans;
+ clnt->msize = msize;
+ clnt->dotu = dotu;
+ INIT_LIST_HEAD(&clnt->fidlist);
+ clnt->fidpool = p9_idpool_create();
+ if (!clnt->fidpool) {
+ err = PTR_ERR(clnt->fidpool);
+ clnt->fidpool = NULL;
+ goto error;
+ }
+
+ clnt->conn = p9_conn_create(clnt->trans, clnt->msize, &clnt->dotu);
+ if (IS_ERR(clnt->conn)) {
+ err = PTR_ERR(clnt->conn);
+ clnt->conn = NULL;
+ goto error;
+ }
+
+ tc = p9_create_tversion(clnt->msize, clnt->dotu?"9P2000.u":"9P2000");
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ version = &rc->params.rversion.version;
+ if (version->len == 8 && !memcmp(version->str, "9P2000.u", 8))
+ clnt->dotu = 1;
+ else if (version->len == 6 && !memcmp(version->str, "9P2000", 6))
+ clnt->dotu = 0;
+ else {
+ err = -EREMOTEIO;
+ goto error;
+ }
+
+ n = rc->params.rversion.msize;
+ if (n < clnt->msize)
+ clnt->msize = n;
+
+ kfree(tc);
+ kfree(rc);
+ return clnt;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ p9_client_destroy(clnt);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_create);
+
+void p9_client_destroy(struct p9_client *clnt)
+{
+ struct p9_fid *fid, *fidptr;
+
+ P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
+ if (clnt->conn) {
+ p9_conn_destroy(clnt->conn);
+ clnt->conn = NULL;
+ }
+
+ if (clnt->trans) {
+ clnt->trans->close(clnt->trans);
+ kfree(clnt->trans);
+ clnt->trans = NULL;
+ }
+
+ list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist)
+ p9_fid_destroy(fid);
+
+ if (clnt->fidpool)
+ p9_idpool_destroy(clnt->fidpool);
+
+ kfree(clnt);
+}
+EXPORT_SYMBOL(p9_client_destroy);
+
+void p9_client_disconnect(struct p9_client *clnt)
+{
+ P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
+ clnt->trans->status = Disconnected;
+ p9_conn_cancel(clnt->conn, -EIO);
+}
+EXPORT_SYMBOL(p9_client_disconnect);
+
+struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
+ char *uname, char *aname)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_fid *fid;
+
+ P9_DPRINTK(P9_DEBUG_9P, "clnt %p afid %d uname %s aname %s\n",
+ clnt, afid?afid->fid:-1, uname, aname);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+
+ fid = p9_fid_create(clnt);
+ if (IS_ERR(fid)) {
+ err = PTR_ERR(fid);
+ fid = NULL;
+ goto error;
+ }
+
+ tc = p9_create_tattach(fid->fid, afid?afid->fid:P9_NOFID, uname, aname);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ memmove(&fid->qid, &rc->params.rattach.qid, sizeof(struct p9_qid));
+ kfree(tc);
+ kfree(rc);
+ return fid;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ if (fid)
+ p9_fid_destroy(fid);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_attach);
+
+struct p9_fid *p9_client_auth(struct p9_client *clnt, char *uname, char *aname)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_fid *fid;
+
+ P9_DPRINTK(P9_DEBUG_9P, "clnt %p uname %s aname %s\n", clnt, uname,
+ aname);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+
+ fid = p9_fid_create(clnt);
+ if (IS_ERR(fid)) {
+ err = PTR_ERR(fid);
+ fid = NULL;
+ goto error;
+ }
+
+ tc = p9_create_tauth(fid->fid, uname, aname);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ memmove(&fid->qid, &rc->params.rauth.qid, sizeof(struct p9_qid));
+ kfree(tc);
+ kfree(rc);
+ return fid;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ if (fid)
+ p9_fid_destroy(fid);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_auth);
+
+struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
+ int clone)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+ struct p9_fid *fid;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d nwname %d wname[0] %s\n",
+ oldfid->fid, nwname, wnames?wnames[0]:NULL);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = oldfid->clnt;
+ if (clone) {
+ fid = p9_fid_create(clnt);
+ if (IS_ERR(fid)) {
+ err = PTR_ERR(fid);
+ fid = NULL;
+ goto error;
+ }
+
+ fid->uid = oldfid->uid;
+ } else
+ fid = oldfid;
+
+ tc = p9_create_twalk(oldfid->fid, fid->fid, nwname, wnames);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err) {
+ if (rc && rc->id == P9_RWALK)
+ goto clunk_fid;
+ else
+ goto error;
+ }
+
+ if (rc->params.rwalk.nwqid != nwname) {
+ err = -ENOENT;
+ goto clunk_fid;
+ }
+
+ if (nwname)
+ memmove(&fid->qid,
+ &rc->params.rwalk.wqids[rc->params.rwalk.nwqid - 1],
+ sizeof(struct p9_qid));
+ else
+ fid->qid = oldfid->qid;
+
+ kfree(tc);
+ kfree(rc);
+ return fid;
+
+clunk_fid:
+ kfree(tc);
+ kfree(rc);
+ rc = NULL;
+ tc = p9_create_tclunk(fid->fid);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ p9_conn_rpc(clnt->conn, tc, &rc);
+
+error:
+ kfree(tc);
+ kfree(rc);
+ if (fid && (fid != oldfid))
+ p9_fid_destroy(fid);
+
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_walk);
+
+int p9_client_open(struct p9_fid *fid, int mode)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d mode %d\n", fid->fid, mode);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+
+ if (fid->mode != -1)
+ return -EINVAL;
+
+ tc = p9_create_topen(fid->fid, mode);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto done;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto done;
+
+ fid->mode = mode;
+ fid->iounit = rc->params.ropen.iounit;
+
+done:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_open);
+
+int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
+ char *extension)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d name %s perm %d mode %d\n", fid->fid,
+ name, perm, mode);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+
+ if (fid->mode != -1)
+ return -EINVAL;
+
+ tc = p9_create_tcreate(fid->fid, name, perm, mode, extension,
+ clnt->dotu);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto done;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto done;
+
+ fid->mode = mode;
+ fid->iounit = rc->params.ropen.iounit;
+
+done:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_fcreate);
+
+int p9_client_clunk(struct p9_fid *fid)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+
+ tc = p9_create_tclunk(fid->fid);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto done;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto done;
+
+ p9_fid_destroy(fid);
+
+done:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_clunk);
+
+int p9_client_remove(struct p9_fid *fid)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+
+ tc = p9_create_tremove(fid->fid);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto done;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto done;
+
+ p9_fid_destroy(fid);
+
+done:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_remove);
+
+int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count)
+{
+ int err, n, rsize, total;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu %d\n", fid->fid,
+ (long long unsigned) offset, count);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+ total = 0;
+
+ rsize = fid->iounit;
+ if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+ rsize = clnt->msize - P9_IOHDRSZ;
+
+ do {
+ if (count < rsize)
+ rsize = count;
+
+ tc = p9_create_tread(fid->fid, offset, rsize);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ n = rc->params.rread.count;
+ if (n > count)
+ n = count;
+
+ memmove(data, rc->params.rread.data, n);
+ count -= n;
+ data += n;
+ offset += n;
+ total += n;
+ kfree(tc);
+ tc = NULL;
+ kfree(rc);
+ rc = NULL;
+ } while (count > 0 && n == rsize);
+
+ return total;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_read);
+
+int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count)
+{
+ int err, n, rsize, total;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+ (long long unsigned) offset, count);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+ total = 0;
+
+ rsize = fid->iounit;
+ if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+ rsize = clnt->msize - P9_IOHDRSZ;
+
+ do {
+ if (count < rsize)
+ rsize = count;
+
+ tc = p9_create_twrite(fid->fid, offset, rsize, data);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ n = rc->params.rread.count;
+ count -= n;
+ data += n;
+ offset += n;
+ total += n;
+ kfree(tc);
+ tc = NULL;
+ kfree(rc);
+ rc = NULL;
+ } while (count > 0);
+
+ return total;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_write);
+
+int
+p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset, u32 count)
+{
+ int err, n, rsize, total;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+ (long long unsigned) offset, count);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+ total = 0;
+
+ rsize = fid->iounit;
+ if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+ rsize = clnt->msize - P9_IOHDRSZ;
+
+ do {
+ if (count < rsize)
+ rsize = count;
+
+ tc = p9_create_tread(fid->fid, offset, rsize);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ n = rc->params.rread.count;
+ if (n > count)
+ n = count;
+
+ err = copy_to_user(data, rc->params.rread.data, n);
+ if (err) {
+ err = -EFAULT;
+ goto error;
+ }
+
+ count -= n;
+ data += n;
+ offset += n;
+ total += n;
+ kfree(tc);
+ tc = NULL;
+ kfree(rc);
+ rc = NULL;
+ } while (count > 0 && n == rsize);
+
+ return total;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_uread);
+
+int
+p9_client_uwrite(struct p9_fid *fid, const char __user *data, u64 offset,
+ u32 count)
+{
+ int err, n, rsize, total;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+ (long long unsigned) offset, count);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+ total = 0;
+
+ rsize = fid->iounit;
+ if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
+ rsize = clnt->msize - P9_IOHDRSZ;
+
+ do {
+ if (count < rsize)
+ rsize = count;
+
+ tc = p9_create_twrite_u(fid->fid, offset, rsize, data);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ n = rc->params.rread.count;
+ count -= n;
+ data += n;
+ offset += n;
+ total += n;
+ kfree(tc);
+ tc = NULL;
+ kfree(rc);
+ rc = NULL;
+ } while (count > 0);
+
+ return total;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_uwrite);
+
+int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count)
+{
+ int n, total;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu count %d\n", fid->fid,
+ (long long unsigned) offset, count);
+ n = 0;
+ total = 0;
+ while (count) {
+ n = p9_client_read(fid, data, offset, count);
+ if (n <= 0)
+ break;
+
+ data += n;
+ offset += n;
+ count -= n;
+ total += n;
+ }
+
+ if (n < 0)
+ total = n;
+
+ return total;
+}
+EXPORT_SYMBOL(p9_client_readn);
+
+struct p9_stat *p9_client_stat(struct p9_fid *fid)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+ struct p9_stat *ret;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ ret = NULL;
+ clnt = fid->clnt;
+
+ tc = p9_create_tstat(fid->fid);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ ret = p9_clone_stat(&rc->params.rstat.stat, clnt->dotu);
+ if (IS_ERR(ret)) {
+ err = PTR_ERR(ret);
+ ret = NULL;
+ goto error;
+ }
+
+ kfree(tc);
+ kfree(rc);
+ return ret;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ kfree(ret);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_stat);
+
+int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
+{
+ int err;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ clnt = fid->clnt;
+
+ tc = p9_create_twstat(fid->fid, wst, clnt->dotu);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto done;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+
+done:
+ kfree(tc);
+ kfree(rc);
+ return err;
+}
+EXPORT_SYMBOL(p9_client_wstat);
+
+struct p9_stat *p9_client_dirread(struct p9_fid *fid, u64 offset)
+{
+ int err, n, m;
+ struct p9_fcall *tc, *rc;
+ struct p9_client *clnt;
+ struct p9_stat st, *ret;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d offset %llu\n", fid->fid,
+ (long long unsigned) offset);
+ err = 0;
+ tc = NULL;
+ rc = NULL;
+ ret = NULL;
+ clnt = fid->clnt;
+
+ /* if the offset is below or above the current response, free it */
+ if (offset < fid->rdir_fpos || (fid->rdir_fcall &&
+ offset >= fid->rdir_fpos+fid->rdir_fcall->params.rread.count)) {
+ fid->rdir_pos = 0;
+ if (fid->rdir_fcall)
+ fid->rdir_fpos += fid->rdir_fcall->params.rread.count;
+
+ kfree(fid->rdir_fcall);
+ fid->rdir_fcall = NULL;
+ if (offset < fid->rdir_fpos)
+ fid->rdir_fpos = 0;
+ }
+
+ if (!fid->rdir_fcall) {
+ n = fid->iounit;
+ if (!n || n > clnt->msize-P9_IOHDRSZ)
+ n = clnt->msize - P9_IOHDRSZ;
+
+ while (1) {
+ if (fid->rdir_fcall) {
+ fid->rdir_fpos +=
+ fid->rdir_fcall->params.rread.count;
+ kfree(fid->rdir_fcall);
+ fid->rdir_fcall = NULL;
+ }
+
+ tc = p9_create_tread(fid->fid, fid->rdir_fpos, n);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ tc = NULL;
+ goto error;
+ }
+
+ err = p9_conn_rpc(clnt->conn, tc, &rc);
+ if (err)
+ goto error;
+
+ n = rc->params.rread.count;
+ if (n == 0)
+ goto done;
+
+ fid->rdir_fcall = rc;
+ rc = NULL;
+ if (offset >= fid->rdir_fpos &&
+ offset < fid->rdir_fpos+n)
+ break;
+ }
+
+ fid->rdir_pos = 0;
+ }
+
+ m = offset - fid->rdir_fpos;
+ if (m < 0)
+ goto done;
+
+ n = p9_deserialize_stat(fid->rdir_fcall->params.rread.data + m,
+ fid->rdir_fcall->params.rread.count - m, &st, clnt->dotu);
+
+ if (!n) {
+ err = -EIO;
+ goto error;
+ }
+
+ fid->rdir_pos += n;
+ st.size = n;
+ ret = p9_clone_stat(&st, clnt->dotu);
+ if (IS_ERR(ret)) {
+ err = PTR_ERR(ret);
+ ret = NULL;
+ goto error;
+ }
+
+done:
+ kfree(tc);
+ kfree(rc);
+ return ret;
+
+error:
+ kfree(tc);
+ kfree(rc);
+ kfree(ret);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_client_dirread);
+
+static struct p9_stat *p9_clone_stat(struct p9_stat *st, int dotu)
+{
+ int n;
+ char *p;
+ struct p9_stat *ret;
+
+ n = sizeof(struct p9_stat) + st->name.len + st->uid.len + st->gid.len +
+ st->muid.len;
+
+ if (dotu)
+ n += st->extension.len;
+
+ ret = kmalloc(n, GFP_KERNEL);
+ if (!ret)
+ return ERR_PTR(-ENOMEM);
+
+ memmove(ret, st, sizeof(struct p9_stat));
+ p = ((char *) ret) + sizeof(struct p9_stat);
+ memmove(p, st->name.str, st->name.len);
+ p += st->name.len;
+ memmove(p, st->uid.str, st->uid.len);
+ p += st->uid.len;
+ memmove(p, st->gid.str, st->gid.len);
+ p += st->gid.len;
+ memmove(p, st->muid.str, st->muid.len);
+ p += st->muid.len;
+
+ if (dotu) {
+ memmove(p, st->extension.str, st->extension.len);
+ p += st->extension.len;
+ }
+
+ return ret;
+}
+
+static struct p9_fid *p9_fid_create(struct p9_client *clnt)
+{
+ int err;
+ struct p9_fid *fid;
+
+ P9_DPRINTK(P9_DEBUG_9P, "clnt %p\n", clnt);
+ fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL);
+ if (!fid)
+ return ERR_PTR(-ENOMEM);
+
+ fid->fid = p9_idpool_get(clnt->fidpool);
+ if (fid->fid < 0) {
+ err = -ENOSPC;
+ goto error;
+ }
+
+ memset(&fid->qid, 0, sizeof(struct p9_qid));
+ fid->mode = -1;
+ fid->rdir_fpos = 0;
+ fid->rdir_pos = 0;
+ fid->rdir_fcall = NULL;
+ fid->uid = current->fsuid;
+ fid->clnt = clnt;
+ fid->aux = NULL;
+
+ spin_lock(&clnt->lock);
+ list_add(&fid->flist, &clnt->fidlist);
+ spin_unlock(&clnt->lock);
+
+ return fid;
+
+error:
+ kfree(fid);
+ return ERR_PTR(err);
+}
+
+static void p9_fid_destroy(struct p9_fid *fid)
+{
+ struct p9_client *clnt;
+
+ P9_DPRINTK(P9_DEBUG_9P, "fid %d\n", fid->fid);
+ clnt = fid->clnt;
+ p9_idpool_put(fid->fid, clnt->fidpool);
+ spin_lock(&clnt->lock);
+ list_del(&fid->flist);
+ spin_unlock(&clnt->lock);
+ kfree(fid->rdir_fcall);
+ kfree(fid);
+}
diff --git a/fs/9p/conv.c b/net/9p/conv.c
index a3ed571eee3..37451178e76 100644
--- a/fs/9p/conv.c
+++ b/net/9p/conv.c
@@ -1,5 +1,5 @@
/*
- * linux/fs/9p/conv.c
+ * net/9p/conv.c
*
* 9P protocol conversion functions
*
@@ -29,11 +29,8 @@
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/idr.h>
-#include <asm/uaccess.h>
-#include "debug.h"
-#include "v9fs.h"
-#include "9p.h"
-#include "conv.h"
+#include <linux/uaccess.h>
+#include <net/9p/9p.h>
/*
* Buffer to help with string parsing
@@ -59,8 +56,9 @@ static int buf_check_size(struct cbuf *buf, int len)
{
if (buf->p + len > buf->ep) {
if (buf->p < buf->ep) {
- eprintk(KERN_ERR, "buffer overflow: want %d has %d\n",
- len, (int)(buf->ep - buf->p));
+ P9_EPRINTK(KERN_ERR,
+ "buffer overflow: want %d has %d\n", len,
+ (int)(buf->ep - buf->p));
dump_stack();
buf->p = buf->ep + 1;
}
@@ -183,7 +181,7 @@ static u64 buf_get_int64(struct cbuf *buf)
return ret;
}
-static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
+static void buf_get_str(struct cbuf *buf, struct p9_str *vstr)
{
vstr->len = buf_get_int16(buf);
if (!buf_check_overflow(buf) && buf_check_size(buf, vstr->len)) {
@@ -195,7 +193,7 @@ static void buf_get_str(struct cbuf *buf, struct v9fs_str *vstr)
}
}
-static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid)
+static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid)
{
qid->type = buf_get_int8(bufp);
qid->version = buf_get_int32(bufp);
@@ -203,18 +201,18 @@ static void buf_get_qid(struct cbuf *bufp, struct v9fs_qid *qid)
}
/**
- * v9fs_size_wstat - calculate the size of a variable length stat struct
+ * p9_size_wstat - calculate the size of a variable length stat struct
* @stat: metadata (stat) structure
- * @extended: non-zero if 9P2000.u
+ * @dotu: non-zero if 9P2000.u
*
*/
-static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
+static int p9_size_wstat(struct p9_wstat *wstat, int dotu)
{
int size = 0;
if (wstat == NULL) {
- eprintk(KERN_ERR, "v9fs_size_stat: got a NULL stat pointer\n");
+ P9_EPRINTK(KERN_ERR, "p9_size_stat: got a NULL stat pointer\n");
return 0;
}
@@ -239,7 +237,7 @@ static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
if (wstat->muid)
size += strlen(wstat->muid);
- if (extended) {
+ if (dotu) {
size += 4 + /* n_uid[4] */
4 + /* n_gid[4] */
4 + /* n_muid[4] */
@@ -255,12 +253,12 @@ static int v9fs_size_wstat(struct v9fs_wstat *wstat, int extended)
* buf_get_stat - safely decode a recieved metadata (stat) structure
* @bufp: buffer to deserialize
* @stat: metadata (stat) structure
- * @extended: non-zero if 9P2000.u
+ * @dotu: non-zero if 9P2000.u
*
*/
static void
-buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
+buf_get_stat(struct cbuf *bufp, struct p9_stat *stat, int dotu)
{
stat->size = buf_get_int16(bufp);
stat->type = buf_get_int16(bufp);
@@ -277,7 +275,7 @@ buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
buf_get_str(bufp, &stat->gid);
buf_get_str(bufp, &stat->muid);
- if (extended) {
+ if (dotu) {
buf_get_str(bufp, &stat->extension);
stat->n_uid = buf_get_int32(bufp);
stat->n_gid = buf_get_int32(bufp);
@@ -286,18 +284,18 @@ buf_get_stat(struct cbuf *bufp, struct v9fs_stat *stat, int extended)
}
/**
- * v9fs_deserialize_stat - decode a received metadata structure
+ * p9_deserialize_stat - decode a received metadata structure
* @buf: buffer to deserialize
* @buflen: length of received buffer
* @stat: metadata structure to decode into
- * @extended: non-zero if 9P2000.u
+ * @dotu: non-zero if 9P2000.u
*
* Note: stat will point to the buf region.
*/
int
-v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
- int extended)
+p9_deserialize_stat(void *buf, u32 buflen, struct p9_stat *stat,
+ int dotu)
{
struct cbuf buffer;
struct cbuf *bufp = &buffer;
@@ -305,13 +303,14 @@ v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
buf_init(bufp, buf, buflen);
p = bufp->p;
- buf_get_stat(bufp, stat, extended);
+ buf_get_stat(bufp, stat, dotu);
if (buf_check_overflow(bufp))
return 0;
else
return bufp->p - p;
}
+EXPORT_SYMBOL(p9_deserialize_stat);
/**
* deserialize_fcall - unmarshal a response
@@ -319,13 +318,13 @@ v9fs_deserialize_stat(void *buf, u32 buflen, struct v9fs_stat *stat,
* @buflen: length of received buffer
* @rcall: fcall structure to populate
* @rcalllen: length of fcall structure to populate
- * @extended: non-zero if 9P2000.u
+ * @dotu: non-zero if 9P2000.u
*
*/
int
-v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
- int extended)
+p9_deserialize_fcall(void *buf, u32 buflen, struct p9_fcall *rcall,
+ int dotu)
{
struct cbuf buffer;
@@ -338,102 +337,104 @@ v9fs_deserialize_fcall(void *buf, u32 buflen, struct v9fs_fcall *rcall,
rcall->id = buf_get_int8(bufp);
rcall->tag = buf_get_int16(bufp);
- dprintk(DEBUG_CONV, "size %d id %d tag %d\n", rcall->size, rcall->id,
- rcall->tag);
+ P9_DPRINTK(P9_DEBUG_CONV, "size %d id %d tag %d\n", rcall->size,
+ rcall->id, rcall->tag);
switch (rcall->id) {
default:
- eprintk(KERN_ERR, "unknown message type: %d\n", rcall->id);
+ P9_EPRINTK(KERN_ERR, "unknown message type: %d\n", rcall->id);
return -EPROTO;
- case RVERSION:
+ case P9_RVERSION:
rcall->params.rversion.msize = buf_get_int32(bufp);
buf_get_str(bufp, &rcall->params.rversion.version);
break;
- case RFLUSH:
+ case P9_RFLUSH:
break;
- case RATTACH:
+ case P9_RATTACH:
rcall->params.rattach.qid.type = buf_get_int8(bufp);
rcall->params.rattach.qid.version = buf_get_int32(bufp);
rcall->params.rattach.qid.path = buf_get_int64(bufp);
break;
- case RWALK:
+ case P9_RWALK:
rcall->params.rwalk.nwqid = buf_get_int16(bufp);
- if (rcall->params.rwalk.nwqid > V9FS_MAXWELEM) {
- eprintk(KERN_ERR, "Rwalk with more than %d qids: %d\n",
- V9FS_MAXWELEM, rcall->params.rwalk.nwqid);
+ if (rcall->params.rwalk.nwqid > P9_MAXWELEM) {
+ P9_EPRINTK(KERN_ERR,
+ "Rwalk with more than %d qids: %d\n",
+ P9_MAXWELEM, rcall->params.rwalk.nwqid);
return -EPROTO;
}
for (i = 0; i < rcall->params.rwalk.nwqid; i++)
buf_get_qid(bufp, &rcall->params.rwalk.wqids[i]);
break;
- case ROPEN:
+ case P9_ROPEN:
buf_get_qid(bufp, &rcall->params.ropen.qid);
rcall->params.ropen.iounit = buf_get_int32(bufp);
break;
- case RCREATE:
+ case P9_RCREATE:
buf_get_qid(bufp, &rcall->params.rcreate.qid);
rcall->params.rcreate.iounit = buf_get_int32(bufp);
break;
- case RREAD:
+ case P9_RREAD:
rcall->params.rread.count = buf_get_int32(bufp);
rcall->params.rread.data = bufp->p;
buf_check_size(bufp, rcall->params.rread.count);
break;
- case RWRITE:
+ case P9_RWRITE:
rcall->params.rwrite.count = buf_get_int32(bufp);
break;
- case RCLUNK:
+ case P9_RCLUNK:
break;
- case RREMOVE:
+ case P9_RREMOVE:
break;
- case RSTAT:
+ case P9_RSTAT:
buf_get_int16(bufp);
- buf_get_stat(bufp, &rcall->params.rstat.stat, extended);
+ buf_get_stat(bufp, &rcall->params.rstat.stat, dotu);
break;
- case RWSTAT:
+ case P9_RWSTAT:
break;
- case RERROR:
+ case P9_RERROR:
buf_get_str(bufp, &rcall->params.rerror.error);
- if (extended)
+ if (dotu)
rcall->params.rerror.errno = buf_get_int16(bufp);
break;
}
if (buf_check_overflow(bufp)) {
- dprintk(DEBUG_ERROR, "buffer overflow\n");
+ P9_DPRINTK(P9_DEBUG_ERROR, "buffer overflow\n");
return -EIO;
}
return bufp->p - bufp->sp;
}
+EXPORT_SYMBOL(p9_deserialize_fcall);
-static inline void v9fs_put_int8(struct cbuf *bufp, u8 val, u8 * p)
+static inline void p9_put_int8(struct cbuf *bufp, u8 val, u8 * p)
{
*p = val;
buf_put_int8(bufp, val);
}
-static inline void v9fs_put_int16(struct cbuf *bufp, u16 val, u16 * p)
+static inline void p9_put_int16(struct cbuf *bufp, u16 val, u16 * p)
{
*p = val;
buf_put_int16(bufp, val);
}
-static inline void v9fs_put_int32(struct cbuf *bufp, u32 val, u32 * p)
+static inline void p9_put_int32(struct cbuf *bufp, u32 val, u32 * p)
{
*p = val;
buf_put_int32(bufp, val);
}
-static inline void v9fs_put_int64(struct cbuf *bufp, u64 val, u64 * p)
+static inline void p9_put_int64(struct cbuf *bufp, u64 val, u64 * p)
{
*p = val;
buf_put_int64(bufp, val);
}
static void
-v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
+p9_put_str(struct cbuf *bufp, char *data, struct p9_str *str)
{
int len;
char *s;
@@ -451,7 +452,16 @@ v9fs_put_str(struct cbuf *bufp, char *data, struct v9fs_str *str)
}
static int
-v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count,
+p9_put_data(struct cbuf *bufp, const char *data, int count,
+ unsigned char **pdata)
+{
+ *pdata = buf_alloc(bufp, count);
+ memmove(*pdata, data, count);
+ return count;
+}
+
+static int
+p9_put_user_data(struct cbuf *bufp, const char __user *data, int count,
unsigned char **pdata)
{
*pdata = buf_alloc(bufp, count);
@@ -459,162 +469,167 @@ v9fs_put_user_data(struct cbuf *bufp, const char __user * data, int count,
}
static void
-v9fs_put_wstat(struct cbuf *bufp, struct v9fs_wstat *wstat,
- struct v9fs_stat *stat, int statsz, int extended)
+p9_put_wstat(struct cbuf *bufp, struct p9_wstat *wstat,
+ struct p9_stat *stat, int statsz, int dotu)
{
- v9fs_put_int16(bufp, statsz, &stat->size);
- v9fs_put_int16(bufp, wstat->type, &stat->type);
- v9fs_put_int32(bufp, wstat->dev, &stat->dev);
- v9fs_put_int8(bufp, wstat->qid.type, &stat->qid.type);
- v9fs_put_int32(bufp, wstat->qid.version, &stat->qid.version);
- v9fs_put_int64(bufp, wstat->qid.path, &stat->qid.path);
- v9fs_put_int32(bufp, wstat->mode, &stat->mode);
- v9fs_put_int32(bufp, wstat->atime, &stat->atime);
- v9fs_put_int32(bufp, wstat->mtime, &stat->mtime);
- v9fs_put_int64(bufp, wstat->length, &stat->length);
+ p9_put_int16(bufp, statsz, &stat->size);
+ p9_put_int16(bufp, wstat->type, &stat->type);
+ p9_put_int32(bufp, wstat->dev, &stat->dev);
+ p9_put_int8(bufp, wstat->qid.type, &stat->qid.type);
+ p9_put_int32(bufp, wstat->qid.version, &stat->qid.version);
+ p9_put_int64(bufp, wstat->qid.path, &stat->qid.path);
+ p9_put_int32(bufp, wstat->mode, &stat->mode);
+ p9_put_int32(bufp, wstat->atime, &stat->atime);
+ p9_put_int32(bufp, wstat->mtime, &stat->mtime);
+ p9_put_int64(bufp, wstat->length, &stat->length);
- v9fs_put_str(bufp, wstat->name, &stat->name);
- v9fs_put_str(bufp, wstat->uid, &stat->uid);
- v9fs_put_str(bufp, wstat->gid, &stat->gid);
- v9fs_put_str(bufp, wstat->muid, &stat->muid);
+ p9_put_str(bufp, wstat->name, &stat->name);
+ p9_put_str(bufp, wstat->uid, &stat->uid);
+ p9_put_str(bufp, wstat->gid, &stat->gid);
+ p9_put_str(bufp, wstat->muid, &stat->muid);
- if (extended) {
- v9fs_put_str(bufp, wstat->extension, &stat->extension);
- v9fs_put_int32(bufp, wstat->n_uid, &stat->n_uid);
- v9fs_put_int32(bufp, wstat->n_gid, &stat->n_gid);
- v9fs_put_int32(bufp, wstat->n_muid, &stat->n_muid);
+ if (dotu) {
+ p9_put_str(bufp, wstat->extension, &stat->extension);
+ p9_put_int32(bufp, wstat->n_uid, &stat->n_uid);
+ p9_put_int32(bufp, wstat->n_gid, &stat->n_gid);
+ p9_put_int32(bufp, wstat->n_muid, &stat->n_muid);
}
}
-static struct v9fs_fcall *
-v9fs_create_common(struct cbuf *bufp, u32 size, u8 id)
+static struct p9_fcall *
+p9_create_common(struct cbuf *bufp, u32 size, u8 id)
{
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
size += 4 + 1 + 2; /* size[4] id[1] tag[2] */
- fc = kmalloc(sizeof(struct v9fs_fcall) + size, GFP_KERNEL);
+ fc = kmalloc(sizeof(struct p9_fcall) + size, GFP_KERNEL);
if (!fc)
return ERR_PTR(-ENOMEM);
fc->sdata = (char *)fc + sizeof(*fc);
buf_init(bufp, (char *)fc->sdata, size);
- v9fs_put_int32(bufp, size, &fc->size);
- v9fs_put_int8(bufp, id, &fc->id);
- v9fs_put_int16(bufp, V9FS_NOTAG, &fc->tag);
+ p9_put_int32(bufp, size, &fc->size);
+ p9_put_int8(bufp, id, &fc->id);
+ p9_put_int16(bufp, P9_NOTAG, &fc->tag);
return fc;
}
-void v9fs_set_tag(struct v9fs_fcall *fc, u16 tag)
+void p9_set_tag(struct p9_fcall *fc, u16 tag)
{
fc->tag = tag;
*(__le16 *) (fc->sdata + 5) = cpu_to_le16(tag);
}
+EXPORT_SYMBOL(p9_set_tag);
-struct v9fs_fcall *v9fs_create_tversion(u32 msize, char *version)
+struct p9_fcall *p9_create_tversion(u32 msize, char *version)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
size = 4 + 2 + strlen(version); /* msize[4] version[s] */
- fc = v9fs_create_common(bufp, size, TVERSION);
+ fc = p9_create_common(bufp, size, P9_TVERSION);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, msize, &fc->params.tversion.msize);
- v9fs_put_str(bufp, version, &fc->params.tversion.version);
+ p9_put_int32(bufp, msize, &fc->params.tversion.msize);
+ p9_put_str(bufp, version, &fc->params.tversion.version);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_tversion);
-#if 0
-struct v9fs_fcall *v9fs_create_tauth(u32 afid, char *uname, char *aname)
+struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
- size = 4 + 2 + strlen(uname) + 2 + strlen(aname); /* afid[4] uname[s] aname[s] */
- fc = v9fs_create_common(bufp, size, TAUTH);
+ /* afid[4] uname[s] aname[s] */
+ size = 4 + 2 + strlen(uname) + 2 + strlen(aname);
+ fc = p9_create_common(bufp, size, P9_TAUTH);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, afid, &fc->params.tauth.afid);
- v9fs_put_str(bufp, uname, &fc->params.tauth.uname);
- v9fs_put_str(bufp, aname, &fc->params.tauth.aname);
+ p9_put_int32(bufp, afid, &fc->params.tauth.afid);
+ p9_put_str(bufp, uname, &fc->params.tauth.uname);
+ p9_put_str(bufp, aname, &fc->params.tauth.aname);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
-#endif /* 0 */
+EXPORT_SYMBOL(p9_create_tauth);
-struct v9fs_fcall *
-v9fs_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
+struct p9_fcall *
+p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
- size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname); /* fid[4] afid[4] uname[s] aname[s] */
- fc = v9fs_create_common(bufp, size, TATTACH);
+ /* fid[4] afid[4] uname[s] aname[s] */
+ size = 4 + 4 + 2 + strlen(uname) + 2 + strlen(aname);
+ fc = p9_create_common(bufp, size, P9_TATTACH);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.tattach.fid);
- v9fs_put_int32(bufp, afid, &fc->params.tattach.afid);
- v9fs_put_str(bufp, uname, &fc->params.tattach.uname);
- v9fs_put_str(bufp, aname, &fc->params.tattach.aname);
+ p9_put_int32(bufp, fid, &fc->params.tattach.fid);
+ p9_put_int32(bufp, afid, &fc->params.tattach.afid);
+ p9_put_str(bufp, uname, &fc->params.tattach.uname);
+ p9_put_str(bufp, aname, &fc->params.tattach.aname);
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_tattach);
-struct v9fs_fcall *v9fs_create_tflush(u16 oldtag)
+struct p9_fcall *p9_create_tflush(u16 oldtag)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
size = 2; /* oldtag[2] */
- fc = v9fs_create_common(bufp, size, TFLUSH);
+ fc = p9_create_common(bufp, size, P9_TFLUSH);
if (IS_ERR(fc))
goto error;
- v9fs_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
+ p9_put_int16(bufp, oldtag, &fc->params.tflush.oldtag);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_tflush);
-struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
+struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname,
char **wnames)
{
int i, size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
- if (nwname > V9FS_MAXWELEM) {
- dprintk(DEBUG_ERROR, "nwname > %d\n", V9FS_MAXWELEM);
+ if (nwname > P9_MAXWELEM) {
+ P9_DPRINTK(P9_DEBUG_ERROR, "nwname > %d\n", P9_MAXWELEM);
return NULL;
}
@@ -623,122 +638,160 @@ struct v9fs_fcall *v9fs_create_twalk(u32 fid, u32 newfid, u16 nwname,
size += 2 + strlen(wnames[i]); /* wname[s] */
}
- fc = v9fs_create_common(bufp, size, TWALK);
+ fc = p9_create_common(bufp, size, P9_TWALK);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.twalk.fid);
- v9fs_put_int32(bufp, newfid, &fc->params.twalk.newfid);
- v9fs_put_int16(bufp, nwname, &fc->params.twalk.nwname);
+ p9_put_int32(bufp, fid, &fc->params.twalk.fid);
+ p9_put_int32(bufp, newfid, &fc->params.twalk.newfid);
+ p9_put_int16(bufp, nwname, &fc->params.twalk.nwname);
for (i = 0; i < nwname; i++) {
- v9fs_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
+ p9_put_str(bufp, wnames[i], &fc->params.twalk.wnames[i]);
}
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_twalk);
-struct v9fs_fcall *v9fs_create_topen(u32 fid, u8 mode)
+struct p9_fcall *p9_create_topen(u32 fid, u8 mode)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
size = 4 + 1; /* fid[4] mode[1] */
- fc = v9fs_create_common(bufp, size, TOPEN);
+ fc = p9_create_common(bufp, size, P9_TOPEN);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.topen.fid);
- v9fs_put_int8(bufp, mode, &fc->params.topen.mode);
+ p9_put_int32(bufp, fid, &fc->params.topen.fid);
+ p9_put_int8(bufp, mode, &fc->params.topen.mode);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_topen);
-struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
- char *extension, int extended)
+struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode,
+ char *extension, int dotu)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
- size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */
- if (extended) {
+ /* fid[4] name[s] perm[4] mode[1] */
+ size = 4 + 2 + strlen(name) + 4 + 1;
+ if (dotu) {
size += 2 + /* extension[s] */
(extension == NULL ? 0 : strlen(extension));
}
- fc = v9fs_create_common(bufp, size, TCREATE);
+ fc = p9_create_common(bufp, size, P9_TCREATE);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.tcreate.fid);
- v9fs_put_str(bufp, name, &fc->params.tcreate.name);
- v9fs_put_int32(bufp, perm, &fc->params.tcreate.perm);
- v9fs_put_int8(bufp, mode, &fc->params.tcreate.mode);
- if (extended)
- v9fs_put_str(bufp, extension, &fc->params.tcreate.extension);
+ p9_put_int32(bufp, fid, &fc->params.tcreate.fid);
+ p9_put_str(bufp, name, &fc->params.tcreate.name);
+ p9_put_int32(bufp, perm, &fc->params.tcreate.perm);
+ p9_put_int8(bufp, mode, &fc->params.tcreate.mode);
+ if (dotu)
+ p9_put_str(bufp, extension, &fc->params.tcreate.extension);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_tcreate);
-struct v9fs_fcall *v9fs_create_tread(u32 fid, u64 offset, u32 count)
+struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
size = 4 + 8 + 4; /* fid[4] offset[8] count[4] */
- fc = v9fs_create_common(bufp, size, TREAD);
+ fc = p9_create_common(bufp, size, P9_TREAD);
+ if (IS_ERR(fc))
+ goto error;
+
+ p9_put_int32(bufp, fid, &fc->params.tread.fid);
+ p9_put_int64(bufp, offset, &fc->params.tread.offset);
+ p9_put_int32(bufp, count, &fc->params.tread.count);
+
+ if (buf_check_overflow(bufp)) {
+ kfree(fc);
+ fc = ERR_PTR(-ENOMEM);
+ }
+error:
+ return fc;
+}
+EXPORT_SYMBOL(p9_create_tread);
+
+struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count,
+ const char *data)
+{
+ int size, err;
+ struct p9_fcall *fc;
+ struct cbuf buffer;
+ struct cbuf *bufp = &buffer;
+
+ /* fid[4] offset[8] count[4] data[count] */
+ size = 4 + 8 + 4 + count;
+ fc = p9_create_common(bufp, size, P9_TWRITE);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.tread.fid);
- v9fs_put_int64(bufp, offset, &fc->params.tread.offset);
- v9fs_put_int32(bufp, count, &fc->params.tread.count);
+ p9_put_int32(bufp, fid, &fc->params.twrite.fid);
+ p9_put_int64(bufp, offset, &fc->params.twrite.offset);
+ p9_put_int32(bufp, count, &fc->params.twrite.count);
+ err = p9_put_data(bufp, data, count, &fc->params.twrite.data);
+ if (err) {
+ kfree(fc);
+ fc = ERR_PTR(err);
+ }
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_twrite);
-struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
- const char __user * data)
+struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count,
+ const char __user *data)
{
int size, err;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
- size = 4 + 8 + 4 + count; /* fid[4] offset[8] count[4] data[count] */
- fc = v9fs_create_common(bufp, size, TWRITE);
+ /* fid[4] offset[8] count[4] data[count] */
+ size = 4 + 8 + 4 + count;
+ fc = p9_create_common(bufp, size, P9_TWRITE);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.twrite.fid);
- v9fs_put_int64(bufp, offset, &fc->params.twrite.offset);
- v9fs_put_int32(bufp, count, &fc->params.twrite.count);
- err = v9fs_put_user_data(bufp, data, count, &fc->params.twrite.data);
+ p9_put_int32(bufp, fid, &fc->params.twrite.fid);
+ p9_put_int64(bufp, offset, &fc->params.twrite.offset);
+ p9_put_int32(bufp, count, &fc->params.twrite.count);
+ err = p9_put_user_data(bufp, data, count, &fc->params.twrite.data);
if (err) {
kfree(fc);
fc = ERR_PTR(err);
@@ -748,98 +801,103 @@ struct v9fs_fcall *v9fs_create_twrite(u32 fid, u64 offset, u32 count,
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_twrite_u);
-struct v9fs_fcall *v9fs_create_tclunk(u32 fid)
+struct p9_fcall *p9_create_tclunk(u32 fid)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
size = 4; /* fid[4] */
- fc = v9fs_create_common(bufp, size, TCLUNK);
+ fc = p9_create_common(bufp, size, P9_TCLUNK);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.tclunk.fid);
+ p9_put_int32(bufp, fid, &fc->params.tclunk.fid);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_tclunk);
-struct v9fs_fcall *v9fs_create_tremove(u32 fid)
+struct p9_fcall *p9_create_tremove(u32 fid)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
size = 4; /* fid[4] */
- fc = v9fs_create_common(bufp, size, TREMOVE);
+ fc = p9_create_common(bufp, size, P9_TREMOVE);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.tremove.fid);
+ p9_put_int32(bufp, fid, &fc->params.tremove.fid);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_tremove);
-struct v9fs_fcall *v9fs_create_tstat(u32 fid)
+struct p9_fcall *p9_create_tstat(u32 fid)
{
int size;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
size = 4; /* fid[4] */
- fc = v9fs_create_common(bufp, size, TSTAT);
+ fc = p9_create_common(bufp, size, P9_TSTAT);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.tstat.fid);
+ p9_put_int32(bufp, fid, &fc->params.tstat.fid);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_tstat);
-struct v9fs_fcall *v9fs_create_twstat(u32 fid, struct v9fs_wstat *wstat,
- int extended)
+struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat,
+ int dotu)
{
int size, statsz;
- struct v9fs_fcall *fc;
+ struct p9_fcall *fc;
struct cbuf buffer;
struct cbuf *bufp = &buffer;
- statsz = v9fs_size_wstat(wstat, extended);
+ statsz = p9_size_wstat(wstat, dotu);
size = 4 + 2 + 2 + statsz; /* fid[4] stat[n] */
- fc = v9fs_create_common(bufp, size, TWSTAT);
+ fc = p9_create_common(bufp, size, P9_TWSTAT);
if (IS_ERR(fc))
goto error;
- v9fs_put_int32(bufp, fid, &fc->params.twstat.fid);
+ p9_put_int32(bufp, fid, &fc->params.twstat.fid);
buf_put_int16(bufp, statsz + 2);
- v9fs_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, extended);
+ p9_put_wstat(bufp, wstat, &fc->params.twstat.stat, statsz, dotu);
if (buf_check_overflow(bufp)) {
kfree(fc);
fc = ERR_PTR(-ENOMEM);
}
- error:
+error:
return fc;
}
+EXPORT_SYMBOL(p9_create_twstat);
diff --git a/fs/9p/error.h b/net/9p/error.c
index 5f3ca522b31..ab2458b6c90 100644
--- a/fs/9p/error.h
+++ b/net/9p/error.c
@@ -1,12 +1,11 @@
/*
- * linux/fs/9p/error.h
+ * linux/fs/9p/error.c
*
- * Huge Nasty Error Table
+ * Error string handling
*
- * Plan 9 uses error strings, Unix uses error numbers. This table tries to
- * match UNIX strings and Plan 9 strings to unix error numbers. It is used
- * to preload the dynamic error table which can also track user-specific error
- * strings.
+ * Plan 9 uses error strings, Unix uses error numbers. These functions
+ * try to help manage that and provide for dynamically adding error
+ * mappings.
*
* Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
* Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
@@ -28,8 +27,11 @@
*
*/
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/jhash.h>
#include <linux/errno.h>
-#include <asm/errno.h>
+#include <net/9p/9p.h>
struct errormap {
char *name;
@@ -174,4 +176,65 @@ static struct errormap errmap[] = {
{NULL, -1}
};
-extern int v9fs_error_init(void);
+/**
+ * p9_error_init - preload
+ * @errstr: error string
+ *
+ */
+
+int p9_error_init(void)
+{
+ struct errormap *c;
+ int bucket;
+
+ /* initialize hash table */
+ for (bucket = 0; bucket < ERRHASHSZ; bucket++)
+ INIT_HLIST_HEAD(&hash_errmap[bucket]);
+
+ /* load initial error map into hash table */
+ for (c = errmap; c->name != NULL; c++) {
+ c->namelen = strlen(c->name);
+ bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ;
+ INIT_HLIST_NODE(&c->list);
+ hlist_add_head(&c->list, &hash_errmap[bucket]);
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL(p9_error_init);
+
+/**
+ * errstr2errno - convert error string to error number
+ * @errstr: error string
+ *
+ */
+
+int p9_errstr2errno(char *errstr, int len)
+{
+ int errno;
+ struct hlist_node *p;
+ struct errormap *c;
+ int bucket;
+
+ errno = 0;
+ p = NULL;
+ c = NULL;
+ bucket = jhash(errstr, len, 0) % ERRHASHSZ;
+ hlist_for_each_entry(c, p, &hash_errmap[bucket], list) {
+ if (c->namelen == len && !memcmp(c->name, errstr, len)) {
+ errno = c->val;
+ break;
+ }
+ }
+
+ if (errno == 0) {
+ /* TODO: if error isn't found, add it dynamically */
+ errstr[len] = 0;
+ printk(KERN_ERR "%s: errstr :%s: not found\n", __FUNCTION__,
+ errstr);
+ errno = 1;
+ }
+
+ return -errno;
+}
+EXPORT_SYMBOL(p9_errstr2errno);
diff --git a/fs/9p/fcprint.c b/net/9p/fcprint.c
index 34b96114a28..b1ae8ec57d5 100644
--- a/fs/9p/fcprint.c
+++ b/net/9p/fcprint.c
@@ -1,5 +1,5 @@
/*
- * linux/fs/9p/fcprint.c
+ * net/9p/fcprint.c
*
* Print 9P call.
*
@@ -25,61 +25,59 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/idr.h>
+#include <net/9p/9p.h>
-#include "debug.h"
-#include "v9fs.h"
-#include "9p.h"
-#include "mux.h"
+#ifdef CONFIG_NET_9P_DEBUG
static int
-v9fs_printqid(char *buf, int buflen, struct v9fs_qid *q)
+p9_printqid(char *buf, int buflen, struct p9_qid *q)
{
int n;
char b[10];
n = 0;
- if (q->type & V9FS_QTDIR)
+ if (q->type & P9_QTDIR)
b[n++] = 'd';
- if (q->type & V9FS_QTAPPEND)
+ if (q->type & P9_QTAPPEND)
b[n++] = 'a';
- if (q->type & V9FS_QTAUTH)
+ if (q->type & P9_QTAUTH)
b[n++] = 'A';
- if (q->type & V9FS_QTEXCL)
+ if (q->type & P9_QTEXCL)
b[n++] = 'l';
- if (q->type & V9FS_QTTMP)
+ if (q->type & P9_QTTMP)
b[n++] = 't';
- if (q->type & V9FS_QTSYMLINK)
+ if (q->type & P9_QTSYMLINK)
b[n++] = 'L';
b[n] = '\0';
- return scnprintf(buf, buflen, "(%.16llx %x %s)", (long long int) q->path,
- q->version, b);
+ return scnprintf(buf, buflen, "(%.16llx %x %s)",
+ (long long int) q->path, q->version, b);
}
static int
-v9fs_printperm(char *buf, int buflen, int perm)
+p9_printperm(char *buf, int buflen, int perm)
{
int n;
char b[15];
n = 0;
- if (perm & V9FS_DMDIR)
+ if (perm & P9_DMDIR)
b[n++] = 'd';
- if (perm & V9FS_DMAPPEND)
+ if (perm & P9_DMAPPEND)
b[n++] = 'a';
- if (perm & V9FS_DMAUTH)
+ if (perm & P9_DMAUTH)
b[n++] = 'A';
- if (perm & V9FS_DMEXCL)
+ if (perm & P9_DMEXCL)
b[n++] = 'l';
- if (perm & V9FS_DMTMP)
+ if (perm & P9_DMTMP)
b[n++] = 't';
- if (perm & V9FS_DMDEVICE)
+ if (perm & P9_DMDEVICE)
b[n++] = 'D';
- if (perm & V9FS_DMSOCKET)
+ if (perm & P9_DMSOCKET)
b[n++] = 'S';
- if (perm & V9FS_DMNAMEDPIPE)
+ if (perm & P9_DMNAMEDPIPE)
b[n++] = 'P';
- if (perm & V9FS_DMSYMLINK)
+ if (perm & P9_DMSYMLINK)
b[n++] = 'L';
b[n] = '\0';
@@ -87,7 +85,7 @@ v9fs_printperm(char *buf, int buflen, int perm)
}
static int
-v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended)
+p9_printstat(char *buf, int buflen, struct p9_stat *st, int extended)
{
int n;
@@ -105,9 +103,9 @@ v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended)
n += scnprintf(buf+n, buflen-n, "(%d)", st->n_muid);
n += scnprintf(buf+n, buflen-n, " q ");
- n += v9fs_printqid(buf+n, buflen-n, &st->qid);
+ n += p9_printqid(buf+n, buflen-n, &st->qid);
n += scnprintf(buf+n, buflen-n, " m ");
- n += v9fs_printperm(buf+n, buflen-n, st->mode);
+ n += p9_printperm(buf+n, buflen-n, st->mode);
n += scnprintf(buf+n, buflen-n, " at %d mt %d l %lld",
st->atime, st->mtime, (long long int) st->length);
@@ -119,7 +117,7 @@ v9fs_printstat(char *buf, int buflen, struct v9fs_stat *st, int extended)
}
static int
-v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen)
+p9_dumpdata(char *buf, int buflen, u8 *data, int datalen)
{
int i, n;
@@ -139,13 +137,13 @@ v9fs_dumpdata(char *buf, int buflen, u8 *data, int datalen)
}
static int
-v9fs_printdata(char *buf, int buflen, u8 *data, int datalen)
+p9_printdata(char *buf, int buflen, u8 *data, int datalen)
{
- return v9fs_dumpdata(buf, buflen, data, datalen<16?datalen:16);
+ return p9_dumpdata(buf, buflen, data, datalen < 16?datalen:16);
}
int
-v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
+p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended)
{
int i, ret, type, tag;
@@ -157,21 +155,23 @@ v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
ret = 0;
switch (type) {
- case TVERSION:
+ case P9_TVERSION:
ret += scnprintf(buf+ret, buflen-ret,
- "Tversion tag %u msize %u version '%.*s'", tag,
- fc->params.tversion.msize, fc->params.tversion.version.len,
- fc->params.tversion.version.str);
+ "Tversion tag %u msize %u version '%.*s'", tag,
+ fc->params.tversion.msize,
+ fc->params.tversion.version.len,
+ fc->params.tversion.version.str);
break;
- case RVERSION:
+ case P9_RVERSION:
ret += scnprintf(buf+ret, buflen-ret,
- "Rversion tag %u msize %u version '%.*s'", tag,
- fc->params.rversion.msize, fc->params.rversion.version.len,
- fc->params.rversion.version.str);
+ "Rversion tag %u msize %u version '%.*s'", tag,
+ fc->params.rversion.msize,
+ fc->params.rversion.version.len,
+ fc->params.rversion.version.str);
break;
- case TAUTH:
+ case P9_TAUTH:
ret += scnprintf(buf+ret, buflen-ret,
"Tauth tag %u afid %d uname '%.*s' aname '%.*s'", tag,
fc->params.tauth.afid, fc->params.tauth.uname.len,
@@ -179,93 +179,97 @@ v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
fc->params.tauth.aname.str);
break;
- case RAUTH:
+ case P9_RAUTH:
ret += scnprintf(buf+ret, buflen-ret, "Rauth tag %u qid ", tag);
- v9fs_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid);
+ p9_printqid(buf+ret, buflen-ret, &fc->params.rauth.qid);
break;
- case TATTACH:
+ case P9_TATTACH:
ret += scnprintf(buf+ret, buflen-ret,
- "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'",
- tag, fc->params.tattach.fid, fc->params.tattach.afid,
- fc->params.tattach.uname.len, fc->params.tattach.uname.str,
- fc->params.tattach.aname.len, fc->params.tattach.aname.str);
+ "Tattach tag %u fid %d afid %d uname '%.*s' aname '%.*s'", tag,
+ fc->params.tattach.fid, fc->params.tattach.afid,
+ fc->params.tattach.uname.len, fc->params.tattach.uname.str,
+ fc->params.tattach.aname.len, fc->params.tattach.aname.str);
break;
- case RATTACH:
- ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ", tag);
- v9fs_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid);
+ case P9_RATTACH:
+ ret += scnprintf(buf+ret, buflen-ret, "Rattach tag %u qid ",
+ tag);
+ p9_printqid(buf+ret, buflen-ret, &fc->params.rattach.qid);
break;
- case RERROR:
- ret += scnprintf(buf+ret, buflen-ret, "Rerror tag %u ename '%.*s'",
- tag, fc->params.rerror.error.len,
- fc->params.rerror.error.str);
+ case P9_RERROR:
+ ret += scnprintf(buf+ret, buflen-ret,
+ "Rerror tag %u ename '%.*s'", tag,
+ fc->params.rerror.error.len,
+ fc->params.rerror.error.str);
if (extended)
ret += scnprintf(buf+ret, buflen-ret, " ecode %d\n",
fc->params.rerror.errno);
break;
- case TFLUSH:
+ case P9_TFLUSH:
ret += scnprintf(buf+ret, buflen-ret, "Tflush tag %u oldtag %u",
tag, fc->params.tflush.oldtag);
break;
- case RFLUSH:
+ case P9_RFLUSH:
ret += scnprintf(buf+ret, buflen-ret, "Rflush tag %u", tag);
break;
- case TWALK:
+ case P9_TWALK:
ret += scnprintf(buf+ret, buflen-ret,
"Twalk tag %u fid %d newfid %d nwname %d", tag,
fc->params.twalk.fid, fc->params.twalk.newfid,
fc->params.twalk.nwname);
- for(i = 0; i < fc->params.twalk.nwname; i++)
- ret += scnprintf(buf+ret, buflen-ret," '%.*s'",
+ for (i = 0; i < fc->params.twalk.nwname; i++)
+ ret += scnprintf(buf+ret, buflen-ret, " '%.*s'",
fc->params.twalk.wnames[i].len,
fc->params.twalk.wnames[i].str);
break;
- case RWALK:
+ case P9_RWALK:
ret += scnprintf(buf+ret, buflen-ret, "Rwalk tag %u nwqid %d",
tag, fc->params.rwalk.nwqid);
- for(i = 0; i < fc->params.rwalk.nwqid; i++)
- ret += v9fs_printqid(buf+ret, buflen-ret,
+ for (i = 0; i < fc->params.rwalk.nwqid; i++)
+ ret += p9_printqid(buf+ret, buflen-ret,
&fc->params.rwalk.wqids[i]);
break;
- case TOPEN:
+ case P9_TOPEN:
ret += scnprintf(buf+ret, buflen-ret,
"Topen tag %u fid %d mode %d", tag,
fc->params.topen.fid, fc->params.topen.mode);
break;
- case ROPEN:
+ case P9_ROPEN:
ret += scnprintf(buf+ret, buflen-ret, "Ropen tag %u", tag);
- ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid);
- ret += scnprintf(buf+ret, buflen-ret," iounit %d",
+ ret += p9_printqid(buf+ret, buflen-ret, &fc->params.ropen.qid);
+ ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
fc->params.ropen.iounit);
break;
- case TCREATE:
+ case P9_TCREATE:
ret += scnprintf(buf+ret, buflen-ret,
"Tcreate tag %u fid %d name '%.*s' perm ", tag,
fc->params.tcreate.fid, fc->params.tcreate.name.len,
fc->params.tcreate.name.str);
- ret += v9fs_printperm(buf+ret, buflen-ret, fc->params.tcreate.perm);
+ ret += p9_printperm(buf+ret, buflen-ret,
+ fc->params.tcreate.perm);
ret += scnprintf(buf+ret, buflen-ret, " mode %d",
fc->params.tcreate.mode);
break;
- case RCREATE:
+ case P9_RCREATE:
ret += scnprintf(buf+ret, buflen-ret, "Rcreate tag %u", tag);
- ret += v9fs_printqid(buf+ret, buflen-ret, &fc->params.rcreate.qid);
+ ret += p9_printqid(buf+ret, buflen-ret,
+ &fc->params.rcreate.qid);
ret += scnprintf(buf+ret, buflen-ret, " iounit %d",
fc->params.rcreate.iounit);
break;
- case TREAD:
+ case P9_TREAD:
ret += scnprintf(buf+ret, buflen-ret,
"Tread tag %u fid %d offset %lld count %u", tag,
fc->params.tread.fid,
@@ -273,66 +277,66 @@ v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
fc->params.tread.count);
break;
- case RREAD:
+ case P9_RREAD:
ret += scnprintf(buf+ret, buflen-ret,
"Rread tag %u count %u data ", tag,
fc->params.rread.count);
- ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.rread.data,
+ ret += p9_printdata(buf+ret, buflen-ret, fc->params.rread.data,
fc->params.rread.count);
break;
- case TWRITE:
+ case P9_TWRITE:
ret += scnprintf(buf+ret, buflen-ret,
"Twrite tag %u fid %d offset %lld count %u data ",
tag, fc->params.twrite.fid,
(long long int) fc->params.twrite.offset,
fc->params.twrite.count);
- ret += v9fs_printdata(buf+ret, buflen-ret, fc->params.twrite.data,
+ ret += p9_printdata(buf+ret, buflen-ret, fc->params.twrite.data,
fc->params.twrite.count);
break;
- case RWRITE:
+ case P9_RWRITE:
ret += scnprintf(buf+ret, buflen-ret, "Rwrite tag %u count %u",
tag, fc->params.rwrite.count);
break;
- case TCLUNK:
+ case P9_TCLUNK:
ret += scnprintf(buf+ret, buflen-ret, "Tclunk tag %u fid %d",
tag, fc->params.tclunk.fid);
break;
- case RCLUNK:
+ case P9_RCLUNK:
ret += scnprintf(buf+ret, buflen-ret, "Rclunk tag %u", tag);
break;
- case TREMOVE:
+ case P9_TREMOVE:
ret += scnprintf(buf+ret, buflen-ret, "Tremove tag %u fid %d",
tag, fc->params.tremove.fid);
break;
- case RREMOVE:
+ case P9_RREMOVE:
ret += scnprintf(buf+ret, buflen-ret, "Rremove tag %u", tag);
break;
- case TSTAT:
+ case P9_TSTAT:
ret += scnprintf(buf+ret, buflen-ret, "Tstat tag %u fid %d",
tag, fc->params.tstat.fid);
break;
- case RSTAT:
+ case P9_RSTAT:
ret += scnprintf(buf+ret, buflen-ret, "Rstat tag %u ", tag);
- ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat,
+ ret += p9_printstat(buf+ret, buflen-ret, &fc->params.rstat.stat,
extended);
break;
- case TWSTAT:
+ case P9_TWSTAT:
ret += scnprintf(buf+ret, buflen-ret, "Twstat tag %u fid %d ",
tag, fc->params.twstat.fid);
- ret += v9fs_printstat(buf+ret, buflen-ret, &fc->params.twstat.stat,
- extended);
+ ret += p9_printstat(buf+ret, buflen-ret,
+ &fc->params.twstat.stat, extended);
break;
- case RWSTAT:
+ case P9_RWSTAT:
ret += scnprintf(buf+ret, buflen-ret, "Rwstat tag %u", tag);
break;
@@ -343,3 +347,12 @@ v9fs_printfcall(char *buf, int buflen, struct v9fs_fcall *fc, int extended)
return ret;
}
+
+#else
+int
+p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended)
+{
+ return 0;
+}
+EXPORT_SYMBOL(p9_printfcall);
+#endif /* CONFIG_NET_9P_DEBUG */
diff --git a/net/9p/mod.c b/net/9p/mod.c
new file mode 100644
index 00000000000..4f9e1d2ac25
--- /dev/null
+++ b/net/9p/mod.c
@@ -0,0 +1,85 @@
+/*
+ * net/9p/9p.c
+ *
+ * 9P entry point
+ *
+ * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <net/9p/9p.h>
+
+#ifdef CONFIG_NET_9P_DEBUG
+unsigned int p9_debug_level = 0; /* feature-rific global debug level */
+EXPORT_SYMBOL(p9_debug_level);
+module_param_named(debug, p9_debug_level, uint, 0);
+MODULE_PARM_DESC(debug, "9P debugging level");
+#endif
+
+extern int p9_mux_global_init(void);
+extern void p9_mux_global_exit(void);
+extern int p9_sysctl_register(void);
+extern void p9_sysctl_unregister(void);
+
+/**
+ * v9fs_init - Initialize module
+ *
+ */
+static int __init init_p9(void)
+{
+ int ret;
+
+ p9_error_init();
+ printk(KERN_INFO "Installing 9P2000 support\n");
+ ret = p9_mux_global_init();
+ if (ret) {
+ printk(KERN_WARNING "9p: starting mux failed\n");
+ return ret;
+ }
+
+ ret = p9_sysctl_register();
+ if (ret) {
+ printk(KERN_WARNING "9p: registering sysctl failed\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * v9fs_init - shutdown module
+ *
+ */
+
+static void __exit exit_p9(void)
+{
+ p9_sysctl_unregister();
+ p9_mux_global_exit();
+}
+
+module_init(init_p9)
+module_exit(exit_p9)
+
+MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
+MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
+MODULE_AUTHOR("Ron Minnich <rminnich@lanl.gov>");
+MODULE_LICENSE("GPL");
diff --git a/fs/9p/mux.c b/net/9p/mux.c
index c783874a9ca..acb038810f3 100644
--- a/fs/9p/mux.c
+++ b/net/9p/mux.c
@@ -1,5 +1,5 @@
/*
- * linux/fs/9p/mux.c
+ * net/9p/mux.c
*
* Protocol Multiplexer
*
@@ -30,13 +30,9 @@
#include <linux/kthread.h>
#include <linux/idr.h>
#include <linux/mutex.h>
-
-#include "debug.h"
-#include "v9fs.h"
-#include "9p.h"
-#include "conv.h"
-#include "transport.h"
-#include "mux.h"
+#include <net/9p/9p.h>
+#include <net/9p/transport.h>
+#include <net/9p/conn.h>
#define ERREQFLUSH 1
#define SCHED_TIMEOUT 10
@@ -55,33 +51,33 @@ enum {
Flushed,
};
-struct v9fs_mux_poll_task;
+struct p9_mux_poll_task;
-struct v9fs_req {
- spinlock_t lock;
+struct p9_req {
+ spinlock_t lock; /* protect request structure */
int tag;
- struct v9fs_fcall *tcall;
- struct v9fs_fcall *rcall;
+ struct p9_fcall *tcall;
+ struct p9_fcall *rcall;
int err;
- v9fs_mux_req_callback cb;
+ p9_conn_req_callback cb;
void *cba;
int flush;
struct list_head req_list;
};
-struct v9fs_mux_data {
- spinlock_t lock;
+struct p9_conn {
+ spinlock_t lock; /* protect lock structure */
struct list_head mux_list;
- struct v9fs_mux_poll_task *poll_task;
+ struct p9_mux_poll_task *poll_task;
int msize;
unsigned char *extended;
- struct v9fs_transport *trans;
- struct v9fs_idpool tagpool;
+ struct p9_transport *trans;
+ struct p9_idpool *tagpool;
int err;
wait_queue_head_t equeue;
struct list_head req_list;
struct list_head unsent_req_list;
- struct v9fs_fcall *rcall;
+ struct p9_fcall *rcall;
int rpos;
char *rbuf;
int wpos;
@@ -95,44 +91,44 @@ struct v9fs_mux_data {
unsigned long wsched;
};
-struct v9fs_mux_poll_task {
+struct p9_mux_poll_task {
struct task_struct *task;
struct list_head mux_list;
int muxnum;
};
-struct v9fs_mux_rpc {
- struct v9fs_mux_data *m;
+struct p9_mux_rpc {
+ struct p9_conn *m;
int err;
- struct v9fs_fcall *tcall;
- struct v9fs_fcall *rcall;
+ struct p9_fcall *tcall;
+ struct p9_fcall *rcall;
wait_queue_head_t wqueue;
};
-static int v9fs_poll_proc(void *);
-static void v9fs_read_work(struct work_struct *work);
-static void v9fs_write_work(struct work_struct *work);
-static void v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
+static int p9_poll_proc(void *);
+static void p9_read_work(struct work_struct *work);
+static void p9_write_work(struct work_struct *work);
+static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address,
poll_table * p);
-static u16 v9fs_mux_get_tag(struct v9fs_mux_data *);
-static void v9fs_mux_put_tag(struct v9fs_mux_data *, u16);
+static u16 p9_mux_get_tag(struct p9_conn *);
+static void p9_mux_put_tag(struct p9_conn *, u16);
-static DEFINE_MUTEX(v9fs_mux_task_lock);
-static struct workqueue_struct *v9fs_mux_wq;
+static DEFINE_MUTEX(p9_mux_task_lock);
+static struct workqueue_struct *p9_mux_wq;
-static int v9fs_mux_num;
-static int v9fs_mux_poll_task_num;
-static struct v9fs_mux_poll_task v9fs_mux_poll_tasks[100];
+static int p9_mux_num;
+static int p9_mux_poll_task_num;
+static struct p9_mux_poll_task p9_mux_poll_tasks[100];
-int v9fs_mux_global_init(void)
+int p9_mux_global_init(void)
{
int i;
- for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++)
- v9fs_mux_poll_tasks[i].task = NULL;
+ for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++)
+ p9_mux_poll_tasks[i].task = NULL;
- v9fs_mux_wq = create_workqueue("v9fs");
- if (!v9fs_mux_wq) {
+ p9_mux_wq = create_workqueue("v9fs");
+ if (!p9_mux_wq) {
printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n");
return -ENOMEM;
}
@@ -140,114 +136,117 @@ int v9fs_mux_global_init(void)
return 0;
}
-void v9fs_mux_global_exit(void)
+void p9_mux_global_exit(void)
{
- destroy_workqueue(v9fs_mux_wq);
+ destroy_workqueue(p9_mux_wq);
}
/**
- * v9fs_mux_calc_poll_procs - calculates the number of polling procs
+ * p9_mux_calc_poll_procs - calculates the number of polling procs
* based on the number of mounted v9fs filesystems.
*
* The current implementation returns sqrt of the number of mounts.
*/
-static int v9fs_mux_calc_poll_procs(int muxnum)
+static int p9_mux_calc_poll_procs(int muxnum)
{
int n;
- if (v9fs_mux_poll_task_num)
- n = muxnum / v9fs_mux_poll_task_num +
- (muxnum % v9fs_mux_poll_task_num ? 1 : 0);
+ if (p9_mux_poll_task_num)
+ n = muxnum / p9_mux_poll_task_num +
+ (muxnum % p9_mux_poll_task_num ? 1 : 0);
else
n = 1;
- if (n > ARRAY_SIZE(v9fs_mux_poll_tasks))
- n = ARRAY_SIZE(v9fs_mux_poll_tasks);
+ if (n > ARRAY_SIZE(p9_mux_poll_tasks))
+ n = ARRAY_SIZE(p9_mux_poll_tasks);
return n;
}
-static int v9fs_mux_poll_start(struct v9fs_mux_data *m)
+static int p9_mux_poll_start(struct p9_conn *m)
{
int i, n;
- struct v9fs_mux_poll_task *vpt, *vptlast;
+ struct p9_mux_poll_task *vpt, *vptlast;
struct task_struct *pproc;
- dprintk(DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, v9fs_mux_num,
- v9fs_mux_poll_task_num);
- mutex_lock(&v9fs_mux_task_lock);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p muxnum %d procnum %d\n", m, p9_mux_num,
+ p9_mux_poll_task_num);
+ mutex_lock(&p9_mux_task_lock);
- n = v9fs_mux_calc_poll_procs(v9fs_mux_num + 1);
- if (n > v9fs_mux_poll_task_num) {
- for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) {
- if (v9fs_mux_poll_tasks[i].task == NULL) {
- vpt = &v9fs_mux_poll_tasks[i];
- dprintk(DEBUG_MUX, "create proc %p\n", vpt);
- pproc = kthread_create(v9fs_poll_proc, vpt,
- "v9fs-poll");
+ n = p9_mux_calc_poll_procs(p9_mux_num + 1);
+ if (n > p9_mux_poll_task_num) {
+ for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) {
+ if (p9_mux_poll_tasks[i].task == NULL) {
+ vpt = &p9_mux_poll_tasks[i];
+ P9_DPRINTK(P9_DEBUG_MUX, "create proc %p\n",
+ vpt);
+ pproc = kthread_create(p9_poll_proc, vpt,
+ "v9fs-poll");
if (!IS_ERR(pproc)) {
vpt->task = pproc;
INIT_LIST_HEAD(&vpt->mux_list);
vpt->muxnum = 0;
- v9fs_mux_poll_task_num++;
+ p9_mux_poll_task_num++;
wake_up_process(vpt->task);
}
break;
}
}
- if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks))
- dprintk(DEBUG_ERROR, "warning: no free poll slots\n");
+ if (i >= ARRAY_SIZE(p9_mux_poll_tasks))
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "warning: no free poll slots\n");
}
- n = (v9fs_mux_num + 1) / v9fs_mux_poll_task_num +
- ((v9fs_mux_num + 1) % v9fs_mux_poll_task_num ? 1 : 0);
+ n = (p9_mux_num + 1) / p9_mux_poll_task_num +
+ ((p9_mux_num + 1) % p9_mux_poll_task_num ? 1 : 0);
vptlast = NULL;
- for (i = 0; i < ARRAY_SIZE(v9fs_mux_poll_tasks); i++) {
- vpt = &v9fs_mux_poll_tasks[i];
+ for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) {
+ vpt = &p9_mux_poll_tasks[i];
if (vpt->task != NULL) {
vptlast = vpt;
if (vpt->muxnum < n) {
- dprintk(DEBUG_MUX, "put in proc %d\n", i);
+ P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i);
list_add(&m->mux_list, &vpt->mux_list);
vpt->muxnum++;
m->poll_task = vpt;
- memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
- init_poll_funcptr(&m->pt, v9fs_pollwait);
+ memset(&m->poll_waddr, 0,
+ sizeof(m->poll_waddr));
+ init_poll_funcptr(&m->pt, p9_pollwait);
break;
}
}
}
- if (i >= ARRAY_SIZE(v9fs_mux_poll_tasks)) {
+ if (i >= ARRAY_SIZE(p9_mux_poll_tasks)) {
if (vptlast == NULL)
return -ENOMEM;
- dprintk(DEBUG_MUX, "put in proc %d\n", i);
+ P9_DPRINTK(P9_DEBUG_MUX, "put in proc %d\n", i);
list_add(&m->mux_list, &vptlast->mux_list);
vptlast->muxnum++;
m->poll_task = vptlast;
memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
- init_poll_funcptr(&m->pt, v9fs_pollwait);
+ init_poll_funcptr(&m->pt, p9_pollwait);
}
- v9fs_mux_num++;
- mutex_unlock(&v9fs_mux_task_lock);
+ p9_mux_num++;
+ mutex_unlock(&p9_mux_task_lock);
return 0;
}
-static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
+static void p9_mux_poll_stop(struct p9_conn *m)
{
int i;
- struct v9fs_mux_poll_task *vpt;
+ struct p9_mux_poll_task *vpt;
- mutex_lock(&v9fs_mux_task_lock);
+ mutex_lock(&p9_mux_task_lock);
vpt = m->poll_task;
list_del(&m->mux_list);
- for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
+ for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
if (m->poll_waddr[i] != NULL) {
remove_wait_queue(m->poll_waddr[i], &m->poll_wait[i]);
m->poll_waddr[i] = NULL;
@@ -255,31 +254,31 @@ static void v9fs_mux_poll_stop(struct v9fs_mux_data *m)
}
vpt->muxnum--;
if (!vpt->muxnum) {
- dprintk(DEBUG_MUX, "destroy proc %p\n", vpt);
+ P9_DPRINTK(P9_DEBUG_MUX, "destroy proc %p\n", vpt);
kthread_stop(vpt->task);
vpt->task = NULL;
- v9fs_mux_poll_task_num--;
+ p9_mux_poll_task_num--;
}
- v9fs_mux_num--;
- mutex_unlock(&v9fs_mux_task_lock);
+ p9_mux_num--;
+ mutex_unlock(&p9_mux_task_lock);
}
/**
- * v9fs_mux_init - allocate and initialize the per-session mux data
+ * p9_conn_create - allocate and initialize the per-session mux data
* Creates the polling task if this is the first session.
*
* @trans - transport structure
* @msize - maximum message size
* @extended - pointer to the extended flag
*/
-struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
+struct p9_conn *p9_conn_create(struct p9_transport *trans, int msize,
unsigned char *extended)
{
int i, n;
- struct v9fs_mux_data *m, *mtmp;
+ struct p9_conn *m, *mtmp;
- dprintk(DEBUG_MUX, "transport %p msize %d\n", trans, msize);
- m = kmalloc(sizeof(struct v9fs_mux_data), GFP_KERNEL);
+ P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, msize);
+ m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL);
if (!m)
return ERR_PTR(-ENOMEM);
@@ -288,8 +287,12 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
m->msize = msize;
m->extended = extended;
m->trans = trans;
- idr_init(&m->tagpool.pool);
- init_MUTEX(&m->tagpool.lock);
+ m->tagpool = p9_idpool_create();
+ if (!m->tagpool) {
+ kfree(m);
+ return ERR_PTR(PTR_ERR(m->tagpool));
+ }
+
m->err = 0;
init_waitqueue_head(&m->equeue);
INIT_LIST_HEAD(&m->req_list);
@@ -299,29 +302,29 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
m->rbuf = NULL;
m->wpos = m->wsize = 0;
m->wbuf = NULL;
- INIT_WORK(&m->rq, v9fs_read_work);
- INIT_WORK(&m->wq, v9fs_write_work);
+ INIT_WORK(&m->rq, p9_read_work);
+ INIT_WORK(&m->wq, p9_write_work);
m->wsched = 0;
memset(&m->poll_waddr, 0, sizeof(m->poll_waddr));
m->poll_task = NULL;
- n = v9fs_mux_poll_start(m);
+ n = p9_mux_poll_start(m);
if (n)
return ERR_PTR(n);
n = trans->poll(trans, &m->pt);
if (n & POLLIN) {
- dprintk(DEBUG_MUX, "mux %p can read\n", m);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
set_bit(Rpending, &m->wsched);
}
if (n & POLLOUT) {
- dprintk(DEBUG_MUX, "mux %p can write\n", m);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
set_bit(Wpending, &m->wsched);
}
- for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
+ for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) {
if (IS_ERR(m->poll_waddr[i])) {
- v9fs_mux_poll_stop(m);
+ p9_mux_poll_stop(m);
mtmp = (void *)m->poll_waddr; /* the error code */
kfree(m);
m = mtmp;
@@ -331,56 +334,58 @@ struct v9fs_mux_data *v9fs_mux_init(struct v9fs_transport *trans, int msize,
return m;
}
+EXPORT_SYMBOL(p9_conn_create);
/**
- * v9fs_mux_destroy - cancels all pending requests and frees mux resources
+ * p9_mux_destroy - cancels all pending requests and frees mux resources
*/
-void v9fs_mux_destroy(struct v9fs_mux_data *m)
+void p9_conn_destroy(struct p9_conn *m)
{
- dprintk(DEBUG_MUX, "mux %p prev %p next %p\n", m,
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m,
m->mux_list.prev, m->mux_list.next);
- v9fs_mux_cancel(m, -ECONNRESET);
+ p9_conn_cancel(m, -ECONNRESET);
if (!list_empty(&m->req_list)) {
/* wait until all processes waiting on this session exit */
- dprintk(DEBUG_MUX, "mux %p waiting for empty request queue\n",
- m);
+ P9_DPRINTK(P9_DEBUG_MUX,
+ "mux %p waiting for empty request queue\n", m);
wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000);
- dprintk(DEBUG_MUX, "mux %p request queue empty: %d\n", m,
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m,
list_empty(&m->req_list));
}
- v9fs_mux_poll_stop(m);
+ p9_mux_poll_stop(m);
m->trans = NULL;
-
+ p9_idpool_destroy(m->tagpool);
kfree(m);
}
+EXPORT_SYMBOL(p9_conn_destroy);
/**
- * v9fs_pollwait - called by files poll operation to add v9fs-poll task
+ * p9_pollwait - called by files poll operation to add v9fs-poll task
* to files wait queue
*/
static void
-v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
+p9_pollwait(struct file *filp, wait_queue_head_t *wait_address,
poll_table * p)
{
int i;
- struct v9fs_mux_data *m;
+ struct p9_conn *m;
- m = container_of(p, struct v9fs_mux_data, pt);
- for(i = 0; i < ARRAY_SIZE(m->poll_waddr); i++)
+ m = container_of(p, struct p9_conn, pt);
+ for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++)
if (m->poll_waddr[i] == NULL)
break;
if (i >= ARRAY_SIZE(m->poll_waddr)) {
- dprintk(DEBUG_ERROR, "not enough wait_address slots\n");
+ P9_DPRINTK(P9_DEBUG_ERROR, "not enough wait_address slots\n");
return;
}
m->poll_waddr[i] = wait_address;
if (!wait_address) {
- dprintk(DEBUG_ERROR, "no wait_address\n");
+ P9_DPRINTK(P9_DEBUG_ERROR, "no wait_address\n");
m->poll_waddr[i] = ERR_PTR(-EIO);
return;
}
@@ -390,9 +395,9 @@ v9fs_pollwait(struct file *filp, wait_queue_head_t * wait_address,
}
/**
- * v9fs_poll_mux - polls a mux and schedules read or write works if necessary
+ * p9_poll_mux - polls a mux and schedules read or write works if necessary
*/
-static void v9fs_poll_mux(struct v9fs_mux_data *m)
+static void p9_poll_mux(struct p9_conn *m)
{
int n;
@@ -401,69 +406,69 @@ static void v9fs_poll_mux(struct v9fs_mux_data *m)
n = m->trans->poll(m->trans, NULL);
if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) {
- dprintk(DEBUG_MUX, "error mux %p err %d\n", m, n);
+ P9_DPRINTK(P9_DEBUG_MUX, "error mux %p err %d\n", m, n);
if (n >= 0)
n = -ECONNRESET;
- v9fs_mux_cancel(m, n);
+ p9_conn_cancel(m, n);
}
if (n & POLLIN) {
set_bit(Rpending, &m->wsched);
- dprintk(DEBUG_MUX, "mux %p can read\n", m);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p can read\n", m);
if (!test_and_set_bit(Rworksched, &m->wsched)) {
- dprintk(DEBUG_MUX, "schedule read work mux %p\n", m);
- queue_work(v9fs_mux_wq, &m->rq);
+ P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
+ queue_work(p9_mux_wq, &m->rq);
}
}
if (n & POLLOUT) {
set_bit(Wpending, &m->wsched);
- dprintk(DEBUG_MUX, "mux %p can write\n", m);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p can write\n", m);
if ((m->wsize || !list_empty(&m->unsent_req_list))
&& !test_and_set_bit(Wworksched, &m->wsched)) {
- dprintk(DEBUG_MUX, "schedule write work mux %p\n", m);
- queue_work(v9fs_mux_wq, &m->wq);
+ P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
+ queue_work(p9_mux_wq, &m->wq);
}
}
}
/**
- * v9fs_poll_proc - polls all v9fs transports for new events and queues
+ * p9_poll_proc - polls all v9fs transports for new events and queues
* the appropriate work to the work queue
*/
-static int v9fs_poll_proc(void *a)
+static int p9_poll_proc(void *a)
{
- struct v9fs_mux_data *m, *mtmp;
- struct v9fs_mux_poll_task *vpt;
+ struct p9_conn *m, *mtmp;
+ struct p9_mux_poll_task *vpt;
vpt = a;
- dprintk(DEBUG_MUX, "start %p %p\n", current, vpt);
+ P9_DPRINTK(P9_DEBUG_MUX, "start %p %p\n", current, vpt);
while (!kthread_should_stop()) {
set_current_state(TASK_INTERRUPTIBLE);
list_for_each_entry_safe(m, mtmp, &vpt->mux_list, mux_list) {
- v9fs_poll_mux(m);
+ p9_poll_mux(m);
}
- dprintk(DEBUG_MUX, "sleeping...\n");
+ P9_DPRINTK(P9_DEBUG_MUX, "sleeping...\n");
schedule_timeout(SCHED_TIMEOUT * HZ);
}
__set_current_state(TASK_RUNNING);
- dprintk(DEBUG_MUX, "finish\n");
+ P9_DPRINTK(P9_DEBUG_MUX, "finish\n");
return 0;
}
/**
- * v9fs_write_work - called when a transport can send some data
+ * p9_write_work - called when a transport can send some data
*/
-static void v9fs_write_work(struct work_struct *work)
+static void p9_write_work(struct work_struct *work)
{
int n, err;
- struct v9fs_mux_data *m;
- struct v9fs_req *req;
+ struct p9_conn *m;
+ struct p9_req *req;
- m = container_of(work, struct v9fs_mux_data, wq);
+ m = container_of(work, struct p9_conn, wq);
if (m->err < 0) {
clear_bit(Wworksched, &m->wsched);
@@ -478,7 +483,7 @@ static void v9fs_write_work(struct work_struct *work)
spin_lock(&m->lock);
again:
- req = list_entry(m->unsent_req_list.next, struct v9fs_req,
+ req = list_entry(m->unsent_req_list.next, struct p9_req,
req_list);
list_move_tail(&req->req_list, &m->req_list);
if (req->err == ERREQFLUSH)
@@ -487,21 +492,25 @@ again:
m->wbuf = req->tcall->sdata;
m->wsize = req->tcall->size;
m->wpos = 0;
- dump_data(m->wbuf, m->wsize);
spin_unlock(&m->lock);
}
- dprintk(DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos, m->wsize);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p pos %d size %d\n", m, m->wpos,
+ m->wsize);
clear_bit(Wpending, &m->wsched);
err = m->trans->write(m->trans, m->wbuf + m->wpos, m->wsize - m->wpos);
- dprintk(DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p sent %d bytes\n", m, err);
if (err == -EAGAIN) {
clear_bit(Wworksched, &m->wsched);
return;
}
- if (err <= 0)
+ if (err < 0)
+ goto error;
+ else if (err == 0) {
+ err = -EREMOTEIO;
goto error;
+ }
m->wpos += err;
if (m->wpos == m->wsize)
@@ -514,8 +523,8 @@ again:
n = m->trans->poll(m->trans, NULL);
if (n & POLLOUT) {
- dprintk(DEBUG_MUX, "schedule write work mux %p\n", m);
- queue_work(v9fs_mux_wq, &m->wq);
+ P9_DPRINTK(P9_DEBUG_MUX, "schedule write work %p\n", m);
+ queue_work(p9_mux_wq, &m->wq);
} else
clear_bit(Wworksched, &m->wsched);
} else
@@ -523,27 +532,28 @@ again:
return;
- error:
- v9fs_mux_cancel(m, err);
+error:
+ p9_conn_cancel(m, err);
clear_bit(Wworksched, &m->wsched);
}
-static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
+static void process_request(struct p9_conn *m, struct p9_req *req)
{
int ecode;
- struct v9fs_str *ename;
+ struct p9_str *ename;
- if (!req->err && req->rcall->id == RERROR) {
+ if (!req->err && req->rcall->id == P9_RERROR) {
ecode = req->rcall->params.rerror.errno;
ename = &req->rcall->params.rerror.error;
- dprintk(DEBUG_MUX, "Rerror %.*s\n", ename->len, ename->str);
+ P9_DPRINTK(P9_DEBUG_MUX, "Rerror %.*s\n", ename->len,
+ ename->str);
if (*m->extended)
req->err = -ecode;
if (!req->err) {
- req->err = v9fs_errstr2errno(ename->str, ename->len);
+ req->err = p9_errstr2errno(ename->str, ename->len);
if (!req->err) { /* string match failed */
PRINT_FCALL_ERROR("unknown error", req->rcall);
@@ -553,47 +563,48 @@ static void process_request(struct v9fs_mux_data *m, struct v9fs_req *req)
req->err = -ESERVERFAULT;
}
} else if (req->tcall && req->rcall->id != req->tcall->id + 1) {
- dprintk(DEBUG_ERROR, "fcall mismatch: expected %d, got %d\n",
- req->tcall->id + 1, req->rcall->id);
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "fcall mismatch: expected %d, got %d\n",
+ req->tcall->id + 1, req->rcall->id);
if (!req->err)
req->err = -EIO;
}
}
/**
- * v9fs_read_work - called when there is some data to be read from a transport
+ * p9_read_work - called when there is some data to be read from a transport
*/
-static void v9fs_read_work(struct work_struct *work)
+static void p9_read_work(struct work_struct *work)
{
int n, err;
- struct v9fs_mux_data *m;
- struct v9fs_req *req, *rptr, *rreq;
- struct v9fs_fcall *rcall;
+ struct p9_conn *m;
+ struct p9_req *req, *rptr, *rreq;
+ struct p9_fcall *rcall;
char *rbuf;
- m = container_of(work, struct v9fs_mux_data, rq);
+ m = container_of(work, struct p9_conn, rq);
if (m->err < 0)
return;
rcall = NULL;
- dprintk(DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
+ P9_DPRINTK(P9_DEBUG_MUX, "start mux %p pos %d\n", m, m->rpos);
if (!m->rcall) {
m->rcall =
- kmalloc(sizeof(struct v9fs_fcall) + m->msize, GFP_KERNEL);
+ kmalloc(sizeof(struct p9_fcall) + m->msize, GFP_KERNEL);
if (!m->rcall) {
err = -ENOMEM;
goto error;
}
- m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall);
+ m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
m->rpos = 0;
}
clear_bit(Rpending, &m->wsched);
err = m->trans->read(m->trans, m->rbuf + m->rpos, m->msize - m->rpos);
- dprintk(DEBUG_MUX, "mux %p got %d bytes\n", m, err);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p got %d bytes\n", m, err);
if (err == -EAGAIN) {
clear_bit(Rworksched, &m->wsched);
return;
@@ -606,7 +617,7 @@ static void v9fs_read_work(struct work_struct *work)
while (m->rpos > 4) {
n = le32_to_cpu(*(__le32 *) m->rbuf);
if (n >= m->msize) {
- dprintk(DEBUG_ERROR,
+ P9_DPRINTK(P9_DEBUG_ERROR,
"requested packet size too big: %d\n", n);
err = -EIO;
goto error;
@@ -615,32 +626,33 @@ static void v9fs_read_work(struct work_struct *work)
if (m->rpos < n)
break;
- dump_data(m->rbuf, n);
err =
- v9fs_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended);
+ p9_deserialize_fcall(m->rbuf, n, m->rcall, *m->extended);
if (err < 0) {
goto error;
}
- if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
+#ifdef CONFIG_NET_9P_DEBUG
+ if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
char buf[150];
- v9fs_printfcall(buf, sizeof(buf), m->rcall,
+ p9_printfcall(buf, sizeof(buf), m->rcall,
*m->extended);
printk(KERN_NOTICE ">>> %p %s\n", m, buf);
}
+#endif
rcall = m->rcall;
rbuf = m->rbuf;
if (m->rpos > n) {
- m->rcall = kmalloc(sizeof(struct v9fs_fcall) + m->msize,
+ m->rcall = kmalloc(sizeof(struct p9_fcall) + m->msize,
GFP_KERNEL);
if (!m->rcall) {
err = -ENOMEM;
goto error;
}
- m->rbuf = (char *)m->rcall + sizeof(struct v9fs_fcall);
+ m->rbuf = (char *)m->rcall + sizeof(struct p9_fcall);
memmove(m->rbuf, rbuf + n, m->rpos - n);
m->rpos -= n;
} else {
@@ -649,8 +661,8 @@ static void v9fs_read_work(struct work_struct *work)
m->rpos = 0;
}
- dprintk(DEBUG_MUX, "mux %p fcall id %d tag %d\n", m, rcall->id,
- rcall->tag);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p fcall id %d tag %d\n", m,
+ rcall->id, rcall->tag);
req = NULL;
spin_lock(&m->lock);
@@ -677,10 +689,10 @@ static void v9fs_read_work(struct work_struct *work)
wake_up(&m->equeue);
}
} else {
- if (err >= 0 && rcall->id != RFLUSH)
- dprintk(DEBUG_ERROR,
- "unexpected response mux %p id %d tag %d\n",
- m, rcall->id, rcall->tag);
+ if (err >= 0 && rcall->id != P9_RFLUSH)
+ P9_DPRINTK(P9_DEBUG_ERROR,
+ "unexpected response mux %p id %d tag %d\n",
+ m, rcall->id, rcall->tag);
kfree(rcall);
}
}
@@ -692,8 +704,8 @@ static void v9fs_read_work(struct work_struct *work)
n = m->trans->poll(m->trans, NULL);
if (n & POLLIN) {
- dprintk(DEBUG_MUX, "schedule read work mux %p\n", m);
- queue_work(v9fs_mux_wq, &m->rq);
+ P9_DPRINTK(P9_DEBUG_MUX, "schedule read work %p\n", m);
+ queue_work(p9_mux_wq, &m->rq);
} else
clear_bit(Rworksched, &m->wsched);
} else
@@ -701,13 +713,13 @@ static void v9fs_read_work(struct work_struct *work)
return;
- error:
- v9fs_mux_cancel(m, err);
+error:
+ p9_conn_cancel(m, err);
clear_bit(Rworksched, &m->wsched);
}
/**
- * v9fs_send_request - send 9P request
+ * p9_send_request - send 9P request
* The function can sleep until the request is scheduled for sending.
* The function can be interrupted. Return from the function is not
* a guarantee that the request is sent successfully. Can return errors
@@ -718,37 +730,40 @@ static void v9fs_read_work(struct work_struct *work)
* @cb: callback function to call when response is received
* @cba: parameter to pass to the callback function
*/
-static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
- struct v9fs_fcall *tc,
- v9fs_mux_req_callback cb, void *cba)
+static struct p9_req *p9_send_request(struct p9_conn *m,
+ struct p9_fcall *tc,
+ p9_conn_req_callback cb, void *cba)
{
int n;
- struct v9fs_req *req;
+ struct p9_req *req;
- dprintk(DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p task %p tcall %p id %d\n", m, current,
tc, tc->id);
if (m->err < 0)
return ERR_PTR(m->err);
- req = kmalloc(sizeof(struct v9fs_req), GFP_KERNEL);
+ req = kmalloc(sizeof(struct p9_req), GFP_KERNEL);
if (!req)
return ERR_PTR(-ENOMEM);
- if (tc->id == TVERSION)
- n = V9FS_NOTAG;
+ if (tc->id == P9_TVERSION)
+ n = P9_NOTAG;
else
- n = v9fs_mux_get_tag(m);
+ n = p9_mux_get_tag(m);
if (n < 0)
return ERR_PTR(-ENOMEM);
- v9fs_set_tag(tc, n);
- if ((v9fs_debug_level&DEBUG_FCALL) == DEBUG_FCALL) {
+ p9_set_tag(tc, n);
+
+#ifdef CONFIG_NET_9P_DEBUG
+ if ((p9_debug_level&P9_DEBUG_FCALL) == P9_DEBUG_FCALL) {
char buf[150];
- v9fs_printfcall(buf, sizeof(buf), tc, *m->extended);
+ p9_printfcall(buf, sizeof(buf), tc, *m->extended);
printk(KERN_NOTICE "<<< %p %s\n", m, buf);
}
+#endif
spin_lock_init(&req->lock);
req->tag = n;
@@ -769,26 +784,26 @@ static struct v9fs_req *v9fs_send_request(struct v9fs_mux_data *m,
n = m->trans->poll(m->trans, NULL);
if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
- queue_work(v9fs_mux_wq, &m->wq);
+ queue_work(p9_mux_wq, &m->wq);
return req;
}
-static void v9fs_mux_free_request(struct v9fs_mux_data *m, struct v9fs_req *req)
+static void p9_mux_free_request(struct p9_conn *m, struct p9_req *req)
{
- v9fs_mux_put_tag(m, req->tag);
+ p9_mux_put_tag(m, req->tag);
kfree(req);
}
-static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a)
+static void p9_mux_flush_cb(struct p9_req *freq, void *a)
{
- v9fs_mux_req_callback cb;
+ p9_conn_req_callback cb;
int tag;
- struct v9fs_mux_data *m;
- struct v9fs_req *req, *rreq, *rptr;
+ struct p9_conn *m;
+ struct p9_req *req, *rreq, *rptr;
m = a;
- dprintk(DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p rc %p err %d oldtag %d\n", m,
freq->tcall, freq->rcall, freq->err,
freq->tcall->params.tflush.oldtag);
@@ -820,22 +835,23 @@ static void v9fs_mux_flush_cb(struct v9fs_req *freq, void *a)
kfree(freq->tcall);
kfree(freq->rcall);
- v9fs_mux_free_request(m, freq);
+ p9_mux_free_request(m, freq);
}
static int
-v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
+p9_mux_flush_request(struct p9_conn *m, struct p9_req *req)
{
- struct v9fs_fcall *fc;
- struct v9fs_req *rreq, *rptr;
+ struct p9_fcall *fc;
+ struct p9_req *rreq, *rptr;
- dprintk(DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p req %p tag %d\n", m, req, req->tag);
/* if a response was received for a request, do nothing */
spin_lock(&req->lock);
if (req->rcall || req->err) {
spin_unlock(&req->lock);
- dprintk(DEBUG_MUX, "mux %p req %p response already received\n", m, req);
+ P9_DPRINTK(P9_DEBUG_MUX,
+ "mux %p req %p response already received\n", m, req);
return 0;
}
@@ -846,7 +862,8 @@ v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
/* if the request is not sent yet, just remove it from the list */
list_for_each_entry_safe(rreq, rptr, &m->unsent_req_list, req_list) {
if (rreq->tag == req->tag) {
- dprintk(DEBUG_MUX, "mux %p req %p request is not sent yet\n", m, req);
+ P9_DPRINTK(P9_DEBUG_MUX,
+ "mux %p req %p request is not sent yet\n", m, req);
list_del(&rreq->req_list);
req->flush = Flushed;
spin_unlock(&m->lock);
@@ -858,42 +875,42 @@ v9fs_mux_flush_request(struct v9fs_mux_data *m, struct v9fs_req *req)
spin_unlock(&m->lock);
clear_thread_flag(TIF_SIGPENDING);
- fc = v9fs_create_tflush(req->tag);
- v9fs_send_request(m, fc, v9fs_mux_flush_cb, m);
+ fc = p9_create_tflush(req->tag);
+ p9_send_request(m, fc, p9_mux_flush_cb, m);
return 1;
}
static void
-v9fs_mux_rpc_cb(struct v9fs_req *req, void *a)
+p9_conn_rpc_cb(struct p9_req *req, void *a)
{
- struct v9fs_mux_rpc *r;
+ struct p9_mux_rpc *r;
- dprintk(DEBUG_MUX, "req %p r %p\n", req, a);
+ P9_DPRINTK(P9_DEBUG_MUX, "req %p r %p\n", req, a);
r = a;
r->rcall = req->rcall;
r->err = req->err;
- if (req->flush!=None && !req->err)
+ if (req->flush != None && !req->err)
r->err = -ERESTARTSYS;
wake_up(&r->wqueue);
}
/**
- * v9fs_mux_rpc - sends 9P request and waits until a response is available.
+ * p9_mux_rpc - sends 9P request and waits until a response is available.
* The function can be interrupted.
* @m: mux data
* @tc: request to be sent
* @rc: pointer where a pointer to the response is stored
*/
int
-v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
- struct v9fs_fcall **rc)
+p9_conn_rpc(struct p9_conn *m, struct p9_fcall *tc,
+ struct p9_fcall **rc)
{
int err, sigpending;
unsigned long flags;
- struct v9fs_req *req;
- struct v9fs_mux_rpc r;
+ struct p9_req *req;
+ struct p9_mux_rpc r;
r.err = 0;
r.tcall = tc;
@@ -910,10 +927,10 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
clear_thread_flag(TIF_SIGPENDING);
}
- req = v9fs_send_request(m, tc, v9fs_mux_rpc_cb, &r);
+ req = p9_send_request(m, tc, p9_conn_rpc_cb, &r);
if (IS_ERR(req)) {
err = PTR_ERR(req);
- dprintk(DEBUG_MUX, "error %d\n", err);
+ P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err);
return err;
}
@@ -921,15 +938,16 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
if (r.err < 0)
err = r.err;
- if (err == -ERESTARTSYS && m->trans->status == Connected && m->err == 0) {
- if (v9fs_mux_flush_request(m, req)) {
+ if (err == -ERESTARTSYS && m->trans->status == Connected
+ && m->err == 0) {
+ if (p9_mux_flush_request(m, req)) {
/* wait until we get response of the flush message */
do {
clear_thread_flag(TIF_SIGPENDING);
err = wait_event_interruptible(r.wqueue,
r.rcall || r.err);
- } while (!r.rcall && !r.err && err==-ERESTARTSYS &&
- m->trans->status==Connected && !m->err);
+ } while (!r.rcall && !r.err && err == -ERESTARTSYS &&
+ m->trans->status == Connected && !m->err);
err = -ERESTARTSYS;
}
@@ -947,50 +965,52 @@ v9fs_mux_rpc(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
else
kfree(r.rcall);
- v9fs_mux_free_request(m, req);
+ p9_mux_free_request(m, req);
if (err > 0)
err = -EIO;
return err;
}
+EXPORT_SYMBOL(p9_conn_rpc);
-#if 0
+#ifdef P9_NONBLOCK
/**
- * v9fs_mux_rpcnb - sends 9P request without waiting for response.
+ * p9_conn_rpcnb - sends 9P request without waiting for response.
* @m: mux data
* @tc: request to be sent
* @cb: callback function to be called when response arrives
* @cba: value to pass to the callback function
*/
-int v9fs_mux_rpcnb(struct v9fs_mux_data *m, struct v9fs_fcall *tc,
- v9fs_mux_req_callback cb, void *a)
+int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc,
+ p9_conn_req_callback cb, void *a)
{
int err;
- struct v9fs_req *req;
+ struct p9_req *req;
- req = v9fs_send_request(m, tc, cb, a);
+ req = p9_send_request(m, tc, cb, a);
if (IS_ERR(req)) {
err = PTR_ERR(req);
- dprintk(DEBUG_MUX, "error %d\n", err);
+ P9_DPRINTK(P9_DEBUG_MUX, "error %d\n", err);
return PTR_ERR(req);
}
- dprintk(DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag);
+ P9_DPRINTK(P9_DEBUG_MUX, "mux %p tc %p tag %d\n", m, tc, req->tag);
return 0;
}
-#endif /* 0 */
+EXPORT_SYMBOL(p9_conn_rpcnb);
+#endif /* P9_NONBLOCK */
/**
- * v9fs_mux_cancel - cancel all pending requests with error
+ * p9_conn_cancel - cancel all pending requests with error
* @m: mux data
* @err: error code
*/
-void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
+void p9_conn_cancel(struct p9_conn *m, int err)
{
- struct v9fs_req *req, *rtmp;
+ struct p9_req *req, *rtmp;
LIST_HEAD(cancel_list);
- dprintk(DEBUG_ERROR, "mux %p err %d\n", m, err);
+ P9_DPRINTK(P9_DEBUG_ERROR, "mux %p err %d\n", m, err);
m->err = err;
spin_lock(&m->lock);
list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
@@ -1014,20 +1034,21 @@ void v9fs_mux_cancel(struct v9fs_mux_data *m, int err)
wake_up(&m->equeue);
}
+EXPORT_SYMBOL(p9_conn_cancel);
-static u16 v9fs_mux_get_tag(struct v9fs_mux_data *m)
+static u16 p9_mux_get_tag(struct p9_conn *m)
{
int tag;
- tag = v9fs_get_idpool(&m->tagpool);
+ tag = p9_idpool_get(m->tagpool);
if (tag < 0)
- return V9FS_NOTAG;
+ return P9_NOTAG;
else
return (u16) tag;
}
-static void v9fs_mux_put_tag(struct v9fs_mux_data *m, u16 tag)
+static void p9_mux_put_tag(struct p9_conn *m, u16 tag)
{
- if (tag != V9FS_NOTAG && v9fs_check_idpool(tag, &m->tagpool))
- v9fs_put_idpool(tag, &m->tagpool);
+ if (tag != P9_NOTAG && p9_idpool_check(tag, m->tagpool))
+ p9_idpool_put(tag, m->tagpool);
}
diff --git a/net/9p/sysctl.c b/net/9p/sysctl.c
new file mode 100644
index 00000000000..e7fe706ab95
--- /dev/null
+++ b/net/9p/sysctl.c
@@ -0,0 +1,86 @@
+/*
+ * net/9p/sysctl.c
+ *
+ * 9P sysctl interface
+ *
+ * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ *
+ * 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+#include <linux/init.h>
+#include <net/9p/9p.h>
+
+enum {
+ P9_SYSCTL_NET = 487,
+ P9_SYSCTL_DEBUG = 1,
+};
+
+static ctl_table p9_table[] = {
+#ifdef CONFIG_NET_9P_DEBUG
+ {
+ .ctl_name = P9_SYSCTL_DEBUG,
+ .procname = "debug",
+ .data = &p9_debug_level,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
+#endif
+ { .ctl_name = 0 },
+};
+
+static ctl_table p9_net_table[] = {
+ {
+ .ctl_name = P9_SYSCTL_NET,
+ .procname = "9p",
+ .maxlen = 0,
+ .mode = 0555,
+ .child = p9_table,
+ },
+ { .ctl_name = 0 },
+};
+
+static ctl_table p9_ctl_table[] = {
+ {
+ .ctl_name = CTL_NET,
+ .procname = "net",
+ .maxlen = 0,
+ .mode = 0555,
+ .child = p9_net_table,
+ },
+ { .ctl_name = 0 },
+};
+
+static struct ctl_table_header *p9_table_header;
+
+int __init p9_sysctl_register(void)
+{
+ p9_table_header = register_sysctl_table(p9_ctl_table);
+ if (!p9_table_header)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void __exit p9_sysctl_unregister(void)
+{
+ unregister_sysctl_table(p9_table_header);
+}
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
new file mode 100644
index 00000000000..fd636e94358
--- /dev/null
+++ b/net/9p/trans_fd.c
@@ -0,0 +1,363 @@
+/*
+ * linux/fs/9p/trans_fd.c
+ *
+ * Fd transport layer. Includes deprecated socket layer.
+ *
+ * Copyright (C) 2006 by Russ Cox <rsc@swtch.com>
+ * Copyright (C) 2004-2005 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004-2005 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 1997-2002 by Ron Minnich <rminnich@sarnoff.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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/in.h>
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/ipv6.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/un.h>
+#include <linux/uaccess.h>
+#include <linux/inet.h>
+#include <linux/idr.h>
+#include <linux/file.h>
+#include <net/9p/9p.h>
+#include <net/9p/transport.h>
+
+#define P9_PORT 564
+
+struct p9_trans_fd {
+ struct file *rd;
+ struct file *wr;
+};
+
+static int p9_socket_open(struct p9_transport *trans, struct socket *csocket);
+static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd);
+static int p9_fd_read(struct p9_transport *trans, void *v, int len);
+static int p9_fd_write(struct p9_transport *trans, void *v, int len);
+static unsigned int p9_fd_poll(struct p9_transport *trans,
+ struct poll_table_struct *pt);
+static void p9_fd_close(struct p9_transport *trans);
+
+struct p9_transport *p9_trans_create_tcp(const char *addr, int port)
+{
+ int err;
+ struct p9_transport *trans;
+ struct socket *csocket;
+ struct sockaddr_in sin_server;
+
+ csocket = NULL;
+ trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
+ if (!trans)
+ return ERR_PTR(-ENOMEM);
+
+ trans->write = p9_fd_write;
+ trans->read = p9_fd_read;
+ trans->close = p9_fd_close;
+ trans->poll = p9_fd_poll;
+
+ sin_server.sin_family = AF_INET;
+ sin_server.sin_addr.s_addr = in_aton(addr);
+ sin_server.sin_port = htons(port);
+ sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &csocket);
+
+ if (!csocket) {
+ P9_EPRINTK(KERN_ERR, "p9_trans_tcp: problem creating socket\n");
+ err = -EIO;
+ goto error;
+ }
+
+ err = csocket->ops->connect(csocket,
+ (struct sockaddr *)&sin_server,
+ sizeof(struct sockaddr_in), 0);
+ if (err < 0) {
+ P9_EPRINTK(KERN_ERR,
+ "p9_trans_tcp: problem connecting socket to %s\n",
+ addr);
+ goto error;
+ }
+
+ err = p9_socket_open(trans, csocket);
+ if (err < 0)
+ goto error;
+
+ return trans;
+
+error:
+ if (csocket)
+ sock_release(csocket);
+
+ kfree(trans);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_trans_create_tcp);
+
+struct p9_transport *p9_trans_create_unix(const char *addr)
+{
+ int err;
+ struct socket *csocket;
+ struct sockaddr_un sun_server;
+ struct p9_transport *trans;
+
+ csocket = NULL;
+ trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
+ if (!trans)
+ return ERR_PTR(-ENOMEM);
+
+ trans->write = p9_fd_write;
+ trans->read = p9_fd_read;
+ trans->close = p9_fd_close;
+ trans->poll = p9_fd_poll;
+
+ if (strlen(addr) > UNIX_PATH_MAX) {
+ P9_EPRINTK(KERN_ERR, "p9_trans_unix: address too long: %s\n",
+ addr);
+ err = -ENAMETOOLONG;
+ goto error;
+ }
+
+ sun_server.sun_family = PF_UNIX;
+ strcpy(sun_server.sun_path, addr);
+ sock_create_kern(PF_UNIX, SOCK_STREAM, 0, &csocket);
+ err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server,
+ sizeof(struct sockaddr_un) - 1, 0);
+ if (err < 0) {
+ P9_EPRINTK(KERN_ERR,
+ "p9_trans_unix: problem connecting socket: %s: %d\n",
+ addr, err);
+ goto error;
+ }
+
+ err = p9_socket_open(trans, csocket);
+ if (err < 0)
+ goto error;
+
+ return trans;
+
+error:
+ if (csocket)
+ sock_release(csocket);
+
+ kfree(trans);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_trans_create_unix);
+
+struct p9_transport *p9_trans_create_fd(int rfd, int wfd)
+{
+ int err;
+ struct p9_transport *trans;
+
+ if (rfd == ~0 || wfd == ~0) {
+ printk(KERN_ERR "v9fs: Insufficient options for proto=fd\n");
+ return ERR_PTR(-ENOPROTOOPT);
+ }
+
+ trans = kmalloc(sizeof(struct p9_transport), GFP_KERNEL);
+ if (!trans)
+ return ERR_PTR(-ENOMEM);
+
+ trans->write = p9_fd_write;
+ trans->read = p9_fd_read;
+ trans->close = p9_fd_close;
+ trans->poll = p9_fd_poll;
+
+ err = p9_fd_open(trans, rfd, wfd);
+ if (err < 0)
+ goto error;
+
+ return trans;
+
+error:
+ kfree(trans);
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL(p9_trans_create_fd);
+
+static int p9_socket_open(struct p9_transport *trans, struct socket *csocket)
+{
+ int fd, ret;
+
+ csocket->sk->sk_allocation = GFP_NOIO;
+ fd = sock_map_fd(csocket);
+ if (fd < 0) {
+ P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to map fd\n");
+ return fd;
+ }
+
+ ret = p9_fd_open(trans, fd, fd);
+ if (ret < 0) {
+ P9_EPRINTK(KERN_ERR, "p9_socket_open: failed to open fd\n");
+ sockfd_put(csocket);
+ return ret;
+ }
+
+ ((struct p9_trans_fd *)trans->priv)->rd->f_flags |= O_NONBLOCK;
+
+ return 0;
+}
+
+static int p9_fd_open(struct p9_transport *trans, int rfd, int wfd)
+{
+ struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd),
+ GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->rd = fget(rfd);
+ ts->wr = fget(wfd);
+ if (!ts->rd || !ts->wr) {
+ if (ts->rd)
+ fput(ts->rd);
+ if (ts->wr)
+ fput(ts->wr);
+ kfree(ts);
+ return -EIO;
+ }
+
+ trans->priv = ts;
+ trans->status = Connected;
+
+ return 0;
+}
+
+/**
+ * p9_fd_read- read from a fd
+ * @v9ses: session information
+ * @v: buffer to receive data into
+ * @len: size of receive buffer
+ *
+ */
+static int p9_fd_read(struct p9_transport *trans, void *v, int len)
+{
+ int ret;
+ struct p9_trans_fd *ts = NULL;
+
+ if (trans && trans->status != Disconnected)
+ ts = trans->priv;
+
+ if (!ts)
+ return -EREMOTEIO;
+
+ if (!(ts->rd->f_flags & O_NONBLOCK))
+ P9_DPRINTK(P9_DEBUG_ERROR, "blocking read ...\n");
+
+ ret = kernel_read(ts->rd, ts->rd->f_pos, v, len);
+ if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
+ trans->status = Disconnected;
+ return ret;
+}
+
+/**
+ * p9_fd_write - write to a socket
+ * @v9ses: session information
+ * @v: buffer to send data from
+ * @len: size of send buffer
+ *
+ */
+static int p9_fd_write(struct p9_transport *trans, void *v, int len)
+{
+ int ret;
+ mm_segment_t oldfs;
+ struct p9_trans_fd *ts = NULL;
+
+ if (trans && trans->status != Disconnected)
+ ts = trans->priv;
+
+ if (!ts)
+ return -EREMOTEIO;
+
+ if (!(ts->wr->f_flags & O_NONBLOCK))
+ P9_DPRINTK(P9_DEBUG_ERROR, "blocking write ...\n");
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+ /* The cast to a user pointer is valid due to the set_fs() */
+ ret = vfs_write(ts->wr, (void __user *)v, len, &ts->wr->f_pos);
+ set_fs(oldfs);
+
+ if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN)
+ trans->status = Disconnected;
+ return ret;
+}
+
+static unsigned int
+p9_fd_poll(struct p9_transport *trans, struct poll_table_struct *pt)
+{
+ int ret, n;
+ struct p9_trans_fd *ts = NULL;
+ mm_segment_t oldfs;
+
+ if (trans && trans->status == Connected)
+ ts = trans->priv;
+
+ if (!ts)
+ return -EREMOTEIO;
+
+ if (!ts->rd->f_op || !ts->rd->f_op->poll)
+ return -EIO;
+
+ if (!ts->wr->f_op || !ts->wr->f_op->poll)
+ return -EIO;
+
+ oldfs = get_fs();
+ set_fs(get_ds());
+
+ ret = ts->rd->f_op->poll(ts->rd, pt);
+ if (ret < 0)
+ goto end;
+
+ if (ts->rd != ts->wr) {
+ n = ts->wr->f_op->poll(ts->wr, pt);
+ if (n < 0) {
+ ret = n;
+ goto end;
+ }
+ ret = (ret & ~POLLOUT) | (n & ~POLLIN);
+ }
+
+end:
+ set_fs(oldfs);
+ return ret;
+}
+
+/**
+ * p9_sock_close - shutdown socket
+ * @trans: private socket structure
+ *
+ */
+static void p9_fd_close(struct p9_transport *trans)
+{
+ struct p9_trans_fd *ts;
+
+ if (!trans)
+ return;
+
+ ts = xchg(&trans->priv, NULL);
+
+ if (!ts)
+ return;
+
+ trans->status = Disconnected;
+ if (ts->rd)
+ fput(ts->rd);
+ if (ts->wr)
+ fput(ts->wr);
+ kfree(ts);
+}
+
diff --git a/net/9p/util.c b/net/9p/util.c
new file mode 100644
index 00000000000..22077b79395
--- /dev/null
+++ b/net/9p/util.c
@@ -0,0 +1,125 @@
+/*
+ * net/9p/util.c
+ *
+ * This file contains some helper functions
+ *
+ * Copyright (C) 2007 by Latchesar Ionkov <lucho@ionkov.net>
+ * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com>
+ * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
+ *
+ * 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:
+ * Free Software Foundation
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02111-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/parser.h>
+#include <linux/idr.h>
+#include <net/9p/9p.h>
+
+struct p9_idpool {
+ struct semaphore lock;
+ struct idr pool;
+};
+
+struct p9_idpool *p9_idpool_create(void)
+{
+ struct p9_idpool *p;
+
+ p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL);
+ if (!p)
+ return ERR_PTR(-ENOMEM);
+
+ init_MUTEX(&p->lock);
+ idr_init(&p->pool);
+
+ return p;
+}
+EXPORT_SYMBOL(p9_idpool_create);
+
+void p9_idpool_destroy(struct p9_idpool *p)
+{
+ idr_destroy(&p->pool);
+ kfree(p);
+}
+EXPORT_SYMBOL(p9_idpool_destroy);
+
+/**
+ * p9_idpool_get - allocate numeric id from pool
+ * @p - pool to allocate from
+ *
+ * XXX - This seems to be an awful generic function, should it be in idr.c with
+ * the lock included in struct idr?
+ */
+
+int p9_idpool_get(struct p9_idpool *p)
+{
+ int i = 0;
+ int error;
+
+retry:
+ if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
+ return 0;
+
+ if (down_interruptible(&p->lock) == -EINTR) {
+ P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n");
+ return -1;
+ }
+
+ /* no need to store exactly p, we just need something non-null */
+ error = idr_get_new(&p->pool, p, &i);
+ up(&p->lock);
+
+ if (error == -EAGAIN)
+ goto retry;
+ else if (error)
+ return -1;
+
+ return i;
+}
+EXPORT_SYMBOL(p9_idpool_get);
+
+/**
+ * p9_idpool_put - release numeric id from pool
+ * @p - pool to allocate from
+ *
+ * XXX - This seems to be an awful generic function, should it be in idr.c with
+ * the lock included in struct idr?
+ */
+
+void p9_idpool_put(int id, struct p9_idpool *p)
+{
+ if (down_interruptible(&p->lock) == -EINTR) {
+ P9_EPRINTK(KERN_WARNING, "Interrupted while locking\n");
+ return;
+ }
+ idr_remove(&p->pool, id);
+ up(&p->lock);
+}
+EXPORT_SYMBOL(p9_idpool_put);
+
+/**
+ * p9_idpool_check - check if the specified id is available
+ * @id - id to check
+ * @p - pool
+ */
+int p9_idpool_check(int id, struct p9_idpool *p)
+{
+ return idr_find(&p->pool, id) != NULL;
+}
+EXPORT_SYMBOL(p9_idpool_check);
diff --git a/net/Kconfig b/net/Kconfig
index f3de72978ab..cdba08ca2ef 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -227,6 +227,7 @@ source "net/ieee80211/Kconfig"
endmenu
source "net/rfkill/Kconfig"
+source "net/9p/Kconfig"
endif # if NET
endmenu # Networking
diff --git a/net/Makefile b/net/Makefile
index 34e5b2d7f87..bbe7d2a4148 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -37,7 +37,6 @@ obj-$(CONFIG_AX25) += ax25/
obj-$(CONFIG_IRDA) += irda/
obj-$(CONFIG_BT) += bluetooth/
obj-$(CONFIG_SUNRPC) += sunrpc/
-obj-$(CONFIG_RXRPC) += rxrpc/
obj-$(CONFIG_AF_RXRPC) += rxrpc/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_DECNET) += decnet/
@@ -52,6 +51,7 @@ obj-$(CONFIG_TIPC) += tipc/
obj-$(CONFIG_NETLABEL) += netlabel/
obj-$(CONFIG_IUCV) += iucv/
obj-$(CONFIG_RFKILL) += rfkill/
+obj-$(CONFIG_NET_9P) += 9p/
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 5ef6a238bdb..3d1655f9838 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -1024,7 +1024,7 @@ static int aarp_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations aarp_seq_ops = {
+static const struct seq_operations aarp_seq_ops = {
.start = aarp_seq_start,
.next = aarp_seq_next,
.stop = aarp_seq_stop,
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index 57ff8122b5c..87a582cc811 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -204,21 +204,21 @@ out:
return 0;
}
-static struct seq_operations atalk_seq_interface_ops = {
+static const struct seq_operations atalk_seq_interface_ops = {
.start = atalk_seq_interface_start,
.next = atalk_seq_interface_next,
.stop = atalk_seq_interface_stop,
.show = atalk_seq_interface_show,
};
-static struct seq_operations atalk_seq_route_ops = {
+static const struct seq_operations atalk_seq_route_ops = {
.start = atalk_seq_route_start,
.next = atalk_seq_route_next,
.stop = atalk_seq_route_stop,
.show = atalk_seq_route_show,
};
-static struct seq_operations atalk_seq_socket_ops = {
+static const struct seq_operations atalk_seq_socket_ops = {
.start = atalk_seq_socket_start,
.next = atalk_seq_socket_next,
.stop = atalk_seq_socket_stop,
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 0e9f00c5c89..faa6aaf6756 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -699,28 +699,13 @@ static struct atm_ioctl br2684_ioctl_ops = {
#ifdef CONFIG_PROC_FS
static void *br2684_seq_start(struct seq_file *seq, loff_t *pos)
{
- loff_t offs = 0;
- struct br2684_dev *brd;
-
read_lock(&devs_lock);
-
- list_for_each_entry(brd, &br2684_devs, br2684_devs) {
- if (offs == *pos)
- return brd;
- ++offs;
- }
- return NULL;
+ return seq_list_start(&br2684_devs, *pos);
}
static void *br2684_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct br2684_dev *brd = v;
-
- ++*pos;
-
- brd = list_entry(brd->br2684_devs.next,
- struct br2684_dev, br2684_devs);
- return (&brd->br2684_devs != &br2684_devs) ? brd : NULL;
+ return seq_list_next(v, &br2684_devs, pos);
}
static void br2684_seq_stop(struct seq_file *seq, void *v)
@@ -730,7 +715,8 @@ static void br2684_seq_stop(struct seq_file *seq, void *v)
static int br2684_seq_show(struct seq_file *seq, void *v)
{
- const struct br2684_dev *brdev = v;
+ const struct br2684_dev *brdev = list_entry(v, struct br2684_dev,
+ br2684_devs);
const struct net_device *net_dev = brdev->net_dev;
const struct br2684_vcc *brvcc;
@@ -772,7 +758,7 @@ static int br2684_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations br2684_seq_ops = {
+static const struct seq_operations br2684_seq_ops = {
.start = br2684_seq_start,
.next = br2684_seq_next,
.stop = br2684_seq_stop,
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 876b77f1474..ecf0f79b94a 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -928,7 +928,7 @@ static int clip_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations arp_seq_ops = {
+static const struct seq_operations arp_seq_ops = {
.start = clip_seq_start,
.next = neigh_seq_next,
.stop = neigh_seq_stop,
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 4dc5f2b8c43..2770fb451ae 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -1174,7 +1174,7 @@ static int lec_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations lec_seq_ops = {
+static const struct seq_operations lec_seq_ops = {
.start = lec_seq_start,
.next = lec_seq_next,
.stop = lec_seq_stop,
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
index 4b05cbec7a5..91f3ffc90db 100644
--- a/net/atm/mpoa_proc.c
+++ b/net/atm/mpoa_proc.c
@@ -177,7 +177,7 @@ static int mpc_show(struct seq_file *m, void *v)
return 0;
}
-static struct seq_operations mpc_op = {
+static const struct seq_operations mpc_op = {
.start = mpc_start,
.next = mpc_next,
.stop = mpc_stop,
diff --git a/net/atm/proc.c b/net/atm/proc.c
index 9e61e512f66..99fc1fe950e 100644
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -110,7 +110,7 @@ static inline void *vcc_walk(struct vcc_state *state, loff_t l)
}
static int __vcc_seq_open(struct inode *inode, struct file *file,
- int family, struct seq_operations *ops)
+ int family, const struct seq_operations *ops)
{
struct vcc_state *state;
struct seq_file *seq;
@@ -260,7 +260,7 @@ static int atm_dev_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations atm_dev_seq_ops = {
+static const struct seq_operations atm_dev_seq_ops = {
.start = atm_dev_seq_start,
.next = atm_dev_seq_next,
.stop = atm_dev_seq_stop,
@@ -295,7 +295,7 @@ static int pvc_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations pvc_seq_ops = {
+static const struct seq_operations pvc_seq_ops = {
.start = vcc_seq_start,
.next = vcc_seq_next,
.stop = vcc_seq_stop,
@@ -329,7 +329,7 @@ static int vcc_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations vcc_seq_ops = {
+static const struct seq_operations vcc_seq_ops = {
.start = vcc_seq_start,
.next = vcc_seq_next,
.stop = vcc_seq_stop,
@@ -364,7 +364,7 @@ static int svc_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations svc_seq_ops = {
+static const struct seq_operations svc_seq_ops = {
.start = vcc_seq_start,
.next = vcc_seq_next,
.stop = vcc_seq_stop,
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 429e13a6c6a..c83cf843297 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1924,7 +1924,7 @@ static int ax25_info_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ax25_info_seqops = {
+static const struct seq_operations ax25_info_seqops = {
.start = ax25_info_start,
.next = ax25_info_next,
.stop = ax25_info_stop,
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index d65b8e22868..9ecf6f1df86 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -320,7 +320,7 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ax25_rt_seqops = {
+static const struct seq_operations ax25_rt_seqops = {
.start = ax25_rt_seq_start,
.next = ax25_rt_seq_next,
.stop = ax25_rt_seq_stop,
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 75c76647b2c..ce0b13d4438 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -185,7 +185,7 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ax25_uid_seqops = {
+static const struct seq_operations ax25_uid_seqops = {
.start = ax25_uid_seq_start,
.next = ax25_uid_seq_next,
.stop = ax25_uid_seq_stop,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 63980bd6b5f..5fdfc9a67d3 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -123,8 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
conn->state = BT_CONNECT;
conn->out = 1;
- cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
cp.handle = cpu_to_le16(handle);
+ cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
}
@@ -220,19 +220,19 @@ int hci_conn_del(struct hci_conn *conn)
del_timer(&conn->disc_timer);
- if (conn->type == SCO_LINK) {
- struct hci_conn *acl = conn->link;
- if (acl) {
- acl->link = NULL;
- hci_conn_put(acl);
- }
- } else {
+ if (conn->type == ACL_LINK) {
struct hci_conn *sco = conn->link;
if (sco)
sco->link = NULL;
/* Unacked frames */
hdev->acl_cnt += conn->sent;
+ } else {
+ struct hci_conn *acl = conn->link;
+ if (acl) {
+ acl->link = NULL;
+ hci_conn_put(acl);
+ }
}
tasklet_disable(&hdev->tx_task);
@@ -297,9 +297,10 @@ EXPORT_SYMBOL(hci_get_route);
/* Create SCO or ACL connection.
* Device _must_ be locked */
-struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
{
struct hci_conn *acl;
+ struct hci_conn *sco;
BT_DBG("%s dst %s", hdev->name, batostr(dst));
@@ -313,28 +314,26 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
hci_acl_connect(acl);
- if (type == SCO_LINK) {
- struct hci_conn *sco;
+ if (type == ACL_LINK)
+ return acl;
- if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) {
- if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) {
- hci_conn_put(acl);
- return NULL;
- }
+ if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) {
+ if (!(sco = hci_conn_add(hdev, type, dst))) {
+ hci_conn_put(acl);
+ return NULL;
}
- acl->link = sco;
- sco->link = acl;
+ }
- hci_conn_hold(sco);
+ acl->link = sco;
+ sco->link = acl;
- if (acl->state == BT_CONNECTED &&
- (sco->state == BT_OPEN || sco->state == BT_CLOSED))
- hci_add_sco(sco, acl->handle);
+ hci_conn_hold(sco);
- return sco;
- } else {
- return acl;
- }
+ if (acl->state == BT_CONNECTED &&
+ (sco->state == BT_OPEN || sco->state == BT_CLOSED))
+ hci_add_sco(sco, acl->handle);
+
+ return sco;
}
EXPORT_SYMBOL(hci_connect);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index aa4b56a8c3e..f6d867e0179 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -826,7 +826,7 @@ EXPORT_SYMBOL(hci_free_dev);
int hci_register_dev(struct hci_dev *hdev)
{
struct list_head *head = &hci_dev_list, *p;
- int id = 0;
+ int i, id = 0;
BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner);
@@ -851,6 +851,7 @@ int hci_register_dev(struct hci_dev *hdev)
hdev->flags = 0;
hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1);
+ hdev->esco_type = (ESCO_HV1);
hdev->link_mode = (HCI_LM_ACCEPT);
hdev->idle_timeout = 0;
@@ -865,6 +866,9 @@ int hci_register_dev(struct hci_dev *hdev)
skb_queue_head_init(&hdev->cmd_q);
skb_queue_head_init(&hdev->raw_q);
+ for (i = 0; i < 3; i++)
+ hdev->reassembly[i] = NULL;
+
init_waitqueue_head(&hdev->req_wait_q);
init_MUTEX(&hdev->req_lock);
@@ -889,6 +893,8 @@ EXPORT_SYMBOL(hci_register_dev);
/* Unregister HCI device */
int hci_unregister_dev(struct hci_dev *hdev)
{
+ int i;
+
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
hci_unregister_sysfs(hdev);
@@ -899,9 +905,13 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_dev_do_close(hdev);
+ for (i = 0; i < 3; i++)
+ kfree_skb(hdev->reassembly[i]);
+
hci_notify(hdev, HCI_DEV_UNREG);
__hci_dev_put(hdev);
+
return 0;
}
EXPORT_SYMBOL(hci_unregister_dev);
@@ -922,6 +932,90 @@ int hci_resume_dev(struct hci_dev *hdev)
}
EXPORT_SYMBOL(hci_resume_dev);
+/* Receive packet type fragment */
+#define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 2])
+
+int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
+{
+ if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT)
+ return -EILSEQ;
+
+ while (count) {
+ struct sk_buff *skb = __reassembly(hdev, type);
+ struct { int expect; } *scb;
+ int len = 0;
+
+ if (!skb) {
+ /* Start of the frame */
+
+ switch (type) {
+ case HCI_EVENT_PKT:
+ if (count >= HCI_EVENT_HDR_SIZE) {
+ struct hci_event_hdr *h = data;
+ len = HCI_EVENT_HDR_SIZE + h->plen;
+ } else
+ return -EILSEQ;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ if (count >= HCI_ACL_HDR_SIZE) {
+ struct hci_acl_hdr *h = data;
+ len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen);
+ } else
+ return -EILSEQ;
+ break;
+
+ case HCI_SCODATA_PKT:
+ if (count >= HCI_SCO_HDR_SIZE) {
+ struct hci_sco_hdr *h = data;
+ len = HCI_SCO_HDR_SIZE + h->dlen;
+ } else
+ return -EILSEQ;
+ break;
+ }
+
+ skb = bt_skb_alloc(len, GFP_ATOMIC);
+ if (!skb) {
+ BT_ERR("%s no memory for packet", hdev->name);
+ return -ENOMEM;
+ }
+
+ skb->dev = (void *) hdev;
+ bt_cb(skb)->pkt_type = type;
+
+ __reassembly(hdev, type) = skb;
+
+ scb = (void *) skb->cb;
+ scb->expect = len;
+ } else {
+ /* Continuation */
+
+ scb = (void *) skb->cb;
+ len = scb->expect;
+ }
+
+ len = min(len, count);
+
+ memcpy(skb_put(skb, len), data, len);
+
+ scb->expect -= len;
+
+ if (scb->expect == 0) {
+ /* Complete frame */
+
+ __reassembly(hdev, type) = NULL;
+
+ bt_cb(skb)->pkt_type = type;
+ hci_recv_frame(skb);
+ }
+
+ count -= len; data += len;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(hci_recv_fragment);
+
/* ---- Interface to upper protocols ---- */
/* Register/Unregister protocols.
@@ -1029,7 +1123,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p
skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!skb) {
- BT_ERR("%s Can't allocate memory for HCI command", hdev->name);
+ BT_ERR("%s no memory for command", hdev->name);
return -ENOMEM;
}
@@ -1161,7 +1255,7 @@ EXPORT_SYMBOL(hci_send_sco);
static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- struct hci_conn *conn = NULL;
+ struct hci_conn *conn = NULL;
int num = 0, min = ~0;
struct list_head *p;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 447ba713122..4baea1e3865 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -350,11 +350,24 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s
if (hdev->features[0] & LMP_5SLOT)
hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
- if (hdev->features[1] & LMP_HV2)
- hdev->pkt_type |= (HCI_HV2);
+ if (hdev->features[1] & LMP_HV2) {
+ hdev->pkt_type |= (HCI_HV2);
+ hdev->esco_type |= (ESCO_HV2);
+ }
+
+ if (hdev->features[1] & LMP_HV3) {
+ hdev->pkt_type |= (HCI_HV3);
+ hdev->esco_type |= (ESCO_HV3);
+ }
- if (hdev->features[1] & LMP_HV3)
- hdev->pkt_type |= (HCI_HV3);
+ if (hdev->features[3] & LMP_ESCO)
+ hdev->esco_type |= (ESCO_EV3);
+
+ if (hdev->features[4] & LMP_EV4)
+ hdev->esco_type |= (ESCO_EV4);
+
+ if (hdev->features[4] & LMP_EV5)
+ hdev->esco_type |= (ESCO_EV5);
BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
lf->features[0], lf->features[1], lf->features[2]);
@@ -881,12 +894,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
if (conn) {
conn->sent -= count;
- if (conn->type == SCO_LINK) {
- if ((hdev->sco_cnt += count) > hdev->sco_pkts)
- hdev->sco_cnt = hdev->sco_pkts;
- } else {
+ if (conn->type == ACL_LINK) {
if ((hdev->acl_cnt += count) > hdev->acl_pkts)
hdev->acl_cnt = hdev->acl_pkts;
+ } else {
+ if ((hdev->sco_cnt += count) > hdev->sco_pkts)
+ hdev->sco_cnt = hdev->sco_pkts;
}
}
}
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index ceadfcf457c..450eb0244bb 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -581,15 +581,6 @@ static int hidp_session(void *arg)
hidp_del_timer(session);
- fput(session->intr_sock->file);
-
- wait_event_timeout(*(ctrl_sk->sk_sleep),
- (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
-
- fput(session->ctrl_sock->file);
-
- __hidp_unlink_session(session);
-
if (session->input) {
input_unregister_device(session->input);
session->input = NULL;
@@ -601,6 +592,15 @@ static int hidp_session(void *arg)
hid_free_device(session->hid);
}
+ fput(session->intr_sock->file);
+
+ wait_event_timeout(*(ctrl_sk->sk_sleep),
+ (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
+
+ fput(session->ctrl_sock->file);
+
+ __hidp_unlink_session(session);
+
up_write(&hidp_session_sem);
kfree(session);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index b2b1cceb102..23ba61a13bd 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev)
BT_DBG("dev %p dlc %p", dev, dlc);
+ write_lock_bh(&rfcomm_dev_lock);
+ list_del_init(&dev->list);
+ write_unlock_bh(&rfcomm_dev_lock);
+
rfcomm_dlc_lock(dlc);
/* Detach DLC if it's owned by this dev */
if (dlc->owner == dev)
@@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
read_lock(&rfcomm_dev_lock);
dev = __rfcomm_dev_get(id);
- if (dev)
- rfcomm_dev_hold(dev);
+
+ if (dev) {
+ if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+ dev = NULL;
+ else
+ rfcomm_dev_hold(dev);
+ }
read_unlock(&rfcomm_dev_lock);
@@ -265,6 +274,12 @@ out:
dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);
+ if (IS_ERR(dev->tty_dev)) {
+ list_del(&dev->list);
+ kfree(dev);
+ return PTR_ERR(dev->tty_dev);
+ }
+
return dev->id;
}
@@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
{
BT_DBG("dev %p", dev);
- write_lock_bh(&rfcomm_dev_lock);
- list_del_init(&dev->list);
- write_unlock_bh(&rfcomm_dev_lock);
-
+ set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
rfcomm_dev_put(dev);
}
@@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg)
if (copy_from_user(&req, arg, sizeof(req)))
return -EFAULT;
- BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags);
+ BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags);
if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
return -EPERM;
@@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg)
if (copy_from_user(&req, arg, sizeof(req)))
return -EFAULT;
- BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags);
+ BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);
if (!(dev = rfcomm_dev_get(req.dev_id)))
return -ENODEV;
@@ -383,6 +395,10 @@ static int rfcomm_release_dev(void __user *arg)
if (req.flags & (1 << RFCOMM_HANGUP_NOW))
rfcomm_dlc_close(dev->dlc, 0);
+ /* Shut down TTY synchronously before freeing rfcomm_dev */
+ if (dev->tty)
+ tty_vhangup(dev->tty);
+
rfcomm_dev_del(dev);
rfcomm_dev_put(dev);
return 0;
@@ -415,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg)
list_for_each(p, &rfcomm_dev_list) {
struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list);
+ if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+ continue;
(di + n)->id = dev->id;
(di + n)->flags = dev->flags;
(di + n)->state = dev->dlc->state;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 91b017016d5..3fc69729381 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -121,6 +121,7 @@ void br_fdb_cleanup(unsigned long _data)
{
struct net_bridge *br = (struct net_bridge *)_data;
unsigned long delay = hold_time(br);
+ unsigned long next_timer = jiffies + br->forward_delay;
int i;
spin_lock_bh(&br->hash_lock);
@@ -129,14 +130,21 @@ void br_fdb_cleanup(unsigned long _data)
struct hlist_node *h, *n;
hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) {
- if (!f->is_static &&
- time_before_eq(f->ageing_timer + delay, jiffies))
+ unsigned long this_timer;
+ if (f->is_static)
+ continue;
+ this_timer = f->ageing_timer + delay;
+ if (time_before_eq(this_timer, jiffies))
fdb_delete(f);
+ else if (this_timer < next_timer)
+ next_timer = this_timer;
}
}
spin_unlock_bh(&br->hash_lock);
- mod_timer(&br->gc_timer, jiffies + HZ/10);
+ /* Add HZ/4 to ensure we round the jiffies upwards to be after the next
+ * timer, otherwise we might round down and will have no-op run. */
+ mod_timer(&br->gc_timer, round_jiffies(next_timer + HZ/4));
}
/* Completely flush all dynamic entries in forwarding database.*/
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 849deaf1410..7b4ce9113be 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -368,10 +368,18 @@ void br_features_recompute(struct net_bridge *br)
list_for_each_entry(p, &br->port_list, list) {
unsigned long feature = p->dev->features;
+ /* if device needs checksumming, downgrade to hw checksumming */
if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
+
+ /* if device can't do all checksum, downgrade to ipv4/ipv6 */
if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
- checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
+ checksum ^= NETIF_F_HW_CSUM
+ | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+ if (checksum & NETIF_F_IPV6_CSUM && !(feature & NETIF_F_IPV6_CSUM))
+ checksum &= ~NETIF_F_IPV6_CSUM;
+
if (!(feature & NETIF_F_IP_CSUM))
checksum = 0;
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 0e035d6162c..e38034aa56f 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -178,7 +178,8 @@ void br_transmit_config(struct net_bridge_port *p)
br_send_config_bpdu(p, &bpdu);
p->topology_change_ack = 0;
p->config_pending = 0;
- mod_timer(&p->hold_timer, jiffies + BR_HOLD_TIME);
+ mod_timer(&p->hold_timer,
+ round_jiffies(jiffies + BR_HOLD_TIME));
}
}
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 24e0ca4a313..77f5255e691 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -42,7 +42,7 @@ static void br_hello_timer_expired(unsigned long arg)
if (br->dev->flags & IFF_UP) {
br_config_bpdu_generation(br);
- mod_timer(&br->hello_timer, jiffies + br->hello_time);
+ mod_timer(&br->hello_timer, round_jiffies(jiffies + br->hello_time));
}
spin_unlock(&br->lock);
}
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 33c6c4a7c68..4f42263e0a8 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -360,8 +360,9 @@ static struct attribute_group bridge_group = {
*
* Returns the number of bytes read.
*/
-static ssize_t brforward_read(struct kobject *kobj, char *buf,
- loff_t off, size_t count)
+static ssize_t brforward_read(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj);
struct net_bridge *br = to_bridge(dev);
@@ -383,8 +384,7 @@ static ssize_t brforward_read(struct kobject *kobj, char *buf,
static struct bin_attribute bridge_forward = {
.attr = { .name = SYSFS_BRIDGE_FDB,
- .mode = S_IRUGO,
- .owner = THIS_MODULE, },
+ .mode = S_IRUGO, },
.read = brforward_read,
};
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 2da22927d8d..79db51fcb47 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -29,8 +29,7 @@ struct brport_attribute {
#define BRPORT_ATTR(_name,_mode,_show,_store) \
struct brport_attribute brport_attr_##_name = { \
.attr = {.name = __stringify(_name), \
- .mode = _mode, \
- .owner = THIS_MODULE, }, \
+ .mode = _mode }, \
.show = _show, \
.store = _store, \
};
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index ac9984f98e5..4169a2a89a3 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1525,14 +1525,14 @@ static int __init ebtables_init(void)
if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
return ret;
- printk(KERN_NOTICE "Ebtables v2.0 registered\n");
+ printk(KERN_INFO "Ebtables v2.0 registered\n");
return 0;
}
static void __exit ebtables_fini(void)
{
nf_unregister_sockopt(&ebt_sockopts);
- printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
+ printk(KERN_INFO "Ebtables v2.0 unregistered\n");
}
EXPORT_SYMBOL(ebt_register_table);
diff --git a/net/core/dev.c b/net/core/dev.c
index 5a7f20f7857..13a0d9f6da5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -98,6 +98,7 @@
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/if_bridge.h>
+#include <linux/if_macvlan.h>
#include <net/dst.h>
#include <net/pkt_sched.h>
#include <net/checksum.h>
@@ -151,9 +152,22 @@ static struct list_head ptype_base[16] __read_mostly; /* 16 way hashed list */
static struct list_head ptype_all __read_mostly; /* Taps */
#ifdef CONFIG_NET_DMA
-static struct dma_client *net_dma_client;
-static unsigned int net_dma_count;
-static spinlock_t net_dma_event_lock;
+struct net_dma {
+ struct dma_client client;
+ spinlock_t lock;
+ cpumask_t channel_mask;
+ struct dma_chan *channels[NR_CPUS];
+};
+
+static enum dma_state_client
+netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+ enum dma_state state);
+
+static struct net_dma net_dma = {
+ .client = {
+ .event_callback = netdev_dma_event,
+ },
+};
#endif
/*
@@ -942,7 +956,7 @@ int dev_open(struct net_device *dev)
/*
* Initialize multicasting status
*/
- dev_mc_upload(dev);
+ dev_set_rx_mode(dev);
/*
* Wakeup transmit queue engine
@@ -1429,7 +1443,9 @@ gso:
skb->next = nskb;
return rc;
}
- if (unlikely(netif_queue_stopped(dev) && skb->next))
+ if (unlikely((netif_queue_stopped(dev) ||
+ netif_subqueue_stopped(dev, skb->queue_mapping)) &&
+ skb->next))
return NETDEV_TX_BUSY;
} while (skb->next);
@@ -1510,8 +1526,10 @@ int dev_queue_xmit(struct sk_buff *skb)
skb_headroom(skb));
if (!(dev->features & NETIF_F_GEN_CSUM) &&
- (!(dev->features & NETIF_F_IP_CSUM) ||
- skb->protocol != htons(ETH_P_IP)))
+ !((dev->features & NETIF_F_IP_CSUM) &&
+ skb->protocol == htons(ETH_P_IP)) &&
+ !((dev->features & NETIF_F_IPV6_CSUM) &&
+ skb->protocol == htons(ETH_P_IPV6)))
if (skb_checksum_help(skb))
goto out_kfree_skb;
}
@@ -1545,6 +1563,8 @@ gso:
spin_lock(&dev->queue_lock);
q = dev->qdisc;
if (q->enqueue) {
+ /* reset queue_mapping to zero */
+ skb->queue_mapping = 0;
rc = q->enqueue(skb, q);
qdisc_run(dev);
spin_unlock(&dev->queue_lock);
@@ -1574,7 +1594,8 @@ gso:
HARD_TX_LOCK(dev, cpu);
- if (!netif_queue_stopped(dev)) {
+ if (!netif_queue_stopped(dev) &&
+ !netif_subqueue_stopped(dev, skb->queue_mapping)) {
rc = 0;
if (!dev_hard_start_xmit(skb, dev)) {
HARD_TX_UNLOCK(dev);
@@ -1793,6 +1814,28 @@ static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
#define handle_bridge(skb, pt_prev, ret, orig_dev) (skb)
#endif
+#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
+struct sk_buff *(*macvlan_handle_frame_hook)(struct sk_buff *skb) __read_mostly;
+EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook);
+
+static inline struct sk_buff *handle_macvlan(struct sk_buff *skb,
+ struct packet_type **pt_prev,
+ int *ret,
+ struct net_device *orig_dev)
+{
+ if (skb->dev->macvlan_port == NULL)
+ return skb;
+
+ if (*pt_prev) {
+ *ret = deliver_skb(skb, *pt_prev, orig_dev);
+ *pt_prev = NULL;
+ }
+ return macvlan_handle_frame_hook(skb);
+}
+#else
+#define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb)
+#endif
+
#ifdef CONFIG_NET_CLS_ACT
/* TODO: Maybe we should just force sch_ingress to be compiled in
* when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
@@ -1900,6 +1943,9 @@ ncls:
skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
if (!skb)
goto out;
+ skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev);
+ if (!skb)
+ goto out;
type = skb->protocol;
list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
@@ -2009,20 +2055,21 @@ static void net_rx_action(struct softirq_action *h)
}
}
out:
+ local_irq_enable();
#ifdef CONFIG_NET_DMA
/*
* There may not be any more sk_buffs coming right now, so push
* any pending DMA copies to hardware
*/
- if (net_dma_client) {
- struct dma_chan *chan;
- rcu_read_lock();
- list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node)
- dma_async_memcpy_issue_pending(chan);
- rcu_read_unlock();
+ if (!cpus_empty(net_dma.channel_mask)) {
+ int chan_idx;
+ for_each_cpu_mask(chan_idx, net_dma.channel_mask) {
+ struct dma_chan *chan = net_dma.channels[chan_idx];
+ if (chan)
+ dma_async_memcpy_issue_pending(chan);
+ }
}
#endif
- local_irq_enable();
return;
softnet_break:
@@ -2496,26 +2543,17 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
return 0;
}
-/**
- * dev_set_promiscuity - update promiscuity count on a device
- * @dev: device
- * @inc: modifier
- *
- * Add or remove promiscuity from a device. While the count in the device
- * remains above zero the interface remains promiscuous. Once it hits zero
- * the device reverts back to normal filtering operation. A negative inc
- * value is used to drop promiscuity on the device.
- */
-void dev_set_promiscuity(struct net_device *dev, int inc)
+static void __dev_set_promiscuity(struct net_device *dev, int inc)
{
unsigned short old_flags = dev->flags;
+ ASSERT_RTNL();
+
if ((dev->promiscuity += inc) == 0)
dev->flags &= ~IFF_PROMISC;
else
dev->flags |= IFF_PROMISC;
if (dev->flags != old_flags) {
- dev_mc_upload(dev);
printk(KERN_INFO "device %s %s promiscuous mode\n",
dev->name, (dev->flags & IFF_PROMISC) ? "entered" :
"left");
@@ -2525,10 +2563,32 @@ void dev_set_promiscuity(struct net_device *dev, int inc)
dev->name, (dev->flags & IFF_PROMISC),
(old_flags & IFF_PROMISC),
audit_get_loginuid(current->audit_context));
+
+ if (dev->change_rx_flags)
+ dev->change_rx_flags(dev, IFF_PROMISC);
}
}
/**
+ * dev_set_promiscuity - update promiscuity count on a device
+ * @dev: device
+ * @inc: modifier
+ *
+ * Add or remove promiscuity from a device. While the count in the device
+ * remains above zero the interface remains promiscuous. Once it hits zero
+ * the device reverts back to normal filtering operation. A negative inc
+ * value is used to drop promiscuity on the device.
+ */
+void dev_set_promiscuity(struct net_device *dev, int inc)
+{
+ unsigned short old_flags = dev->flags;
+
+ __dev_set_promiscuity(dev, inc);
+ if (dev->flags != old_flags)
+ dev_set_rx_mode(dev);
+}
+
+/**
* dev_set_allmulti - update allmulti count on a device
* @dev: device
* @inc: modifier
@@ -2544,11 +2604,185 @@ void dev_set_allmulti(struct net_device *dev, int inc)
{
unsigned short old_flags = dev->flags;
+ ASSERT_RTNL();
+
dev->flags |= IFF_ALLMULTI;
if ((dev->allmulti += inc) == 0)
dev->flags &= ~IFF_ALLMULTI;
- if (dev->flags ^ old_flags)
- dev_mc_upload(dev);
+ if (dev->flags ^ old_flags) {
+ if (dev->change_rx_flags)
+ dev->change_rx_flags(dev, IFF_ALLMULTI);
+ dev_set_rx_mode(dev);
+ }
+}
+
+/*
+ * Upload unicast and multicast address lists to device and
+ * configure RX filtering. When the device doesn't support unicast
+ * filtering it is put in promiscous mode while unicast addresses
+ * are present.
+ */
+void __dev_set_rx_mode(struct net_device *dev)
+{
+ /* dev_open will call this function so the list will stay sane. */
+ if (!(dev->flags&IFF_UP))
+ return;
+
+ if (!netif_device_present(dev))
+ return;
+
+ if (dev->set_rx_mode)
+ dev->set_rx_mode(dev);
+ else {
+ /* Unicast addresses changes may only happen under the rtnl,
+ * therefore calling __dev_set_promiscuity here is safe.
+ */
+ if (dev->uc_count > 0 && !dev->uc_promisc) {
+ __dev_set_promiscuity(dev, 1);
+ dev->uc_promisc = 1;
+ } else if (dev->uc_count == 0 && dev->uc_promisc) {
+ __dev_set_promiscuity(dev, -1);
+ dev->uc_promisc = 0;
+ }
+
+ if (dev->set_multicast_list)
+ dev->set_multicast_list(dev);
+ }
+}
+
+void dev_set_rx_mode(struct net_device *dev)
+{
+ netif_tx_lock_bh(dev);
+ __dev_set_rx_mode(dev);
+ netif_tx_unlock_bh(dev);
+}
+
+int __dev_addr_delete(struct dev_addr_list **list, int *count,
+ void *addr, int alen, int glbl)
+{
+ struct dev_addr_list *da;
+
+ for (; (da = *list) != NULL; list = &da->next) {
+ if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
+ alen == da->da_addrlen) {
+ if (glbl) {
+ int old_glbl = da->da_gusers;
+ da->da_gusers = 0;
+ if (old_glbl == 0)
+ break;
+ }
+ if (--da->da_users)
+ return 0;
+
+ *list = da->next;
+ kfree(da);
+ (*count)--;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+int __dev_addr_add(struct dev_addr_list **list, int *count,
+ void *addr, int alen, int glbl)
+{
+ struct dev_addr_list *da;
+
+ for (da = *list; da != NULL; da = da->next) {
+ if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
+ da->da_addrlen == alen) {
+ if (glbl) {
+ int old_glbl = da->da_gusers;
+ da->da_gusers = 1;
+ if (old_glbl)
+ return 0;
+ }
+ da->da_users++;
+ return 0;
+ }
+ }
+
+ da = kmalloc(sizeof(*da), GFP_ATOMIC);
+ if (da == NULL)
+ return -ENOMEM;
+ memcpy(da->da_addr, addr, alen);
+ da->da_addrlen = alen;
+ da->da_users = 1;
+ da->da_gusers = glbl ? 1 : 0;
+ da->next = *list;
+ *list = da;
+ (*count)++;
+ return 0;
+}
+
+void __dev_addr_discard(struct dev_addr_list **list)
+{
+ struct dev_addr_list *tmp;
+
+ while (*list != NULL) {
+ tmp = *list;
+ *list = tmp->next;
+ if (tmp->da_users > tmp->da_gusers)
+ printk("__dev_addr_discard: address leakage! "
+ "da_users=%d\n", tmp->da_users);
+ kfree(tmp);
+ }
+}
+
+/**
+ * dev_unicast_delete - Release secondary unicast address.
+ * @dev: device
+ *
+ * Release reference to a secondary unicast address and remove it
+ * from the device if the reference count drop to zero.
+ *
+ * The caller must hold the rtnl_mutex.
+ */
+int dev_unicast_delete(struct net_device *dev, void *addr, int alen)
+{
+ int err;
+
+ ASSERT_RTNL();
+
+ netif_tx_lock_bh(dev);
+ err = __dev_addr_delete(&dev->uc_list, &dev->uc_count, addr, alen, 0);
+ if (!err)
+ __dev_set_rx_mode(dev);
+ netif_tx_unlock_bh(dev);
+ return err;
+}
+EXPORT_SYMBOL(dev_unicast_delete);
+
+/**
+ * dev_unicast_add - add a secondary unicast address
+ * @dev: device
+ *
+ * Add a secondary unicast address to the device or increase
+ * the reference count if it already exists.
+ *
+ * The caller must hold the rtnl_mutex.
+ */
+int dev_unicast_add(struct net_device *dev, void *addr, int alen)
+{
+ int err;
+
+ ASSERT_RTNL();
+
+ netif_tx_lock_bh(dev);
+ err = __dev_addr_add(&dev->uc_list, &dev->uc_count, addr, alen, 0);
+ if (!err)
+ __dev_set_rx_mode(dev);
+ netif_tx_unlock_bh(dev);
+ return err;
+}
+EXPORT_SYMBOL(dev_unicast_add);
+
+static void dev_unicast_discard(struct net_device *dev)
+{
+ netif_tx_lock_bh(dev);
+ __dev_addr_discard(&dev->uc_list);
+ dev->uc_count = 0;
+ netif_tx_unlock_bh(dev);
}
unsigned dev_get_flags(const struct net_device *dev)
@@ -2577,9 +2811,11 @@ unsigned dev_get_flags(const struct net_device *dev)
int dev_change_flags(struct net_device *dev, unsigned flags)
{
- int ret;
+ int ret, changes;
int old_flags = dev->flags;
+ ASSERT_RTNL();
+
/*
* Set the flags on our device.
*/
@@ -2594,7 +2830,10 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
* Load in the correct multicast list now the flags have changed.
*/
- dev_mc_upload(dev);
+ if (dev->change_rx_flags && (dev->flags ^ flags) & IFF_MULTICAST)
+ dev->change_rx_flags(dev, IFF_MULTICAST);
+
+ dev_set_rx_mode(dev);
/*
* Have we downed the interface. We handle IFF_UP ourselves
@@ -2607,7 +2846,7 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
ret = ((old_flags & IFF_UP) ? dev_close : dev_open)(dev);
if (!ret)
- dev_mc_upload(dev);
+ dev_set_rx_mode(dev);
}
if (dev->flags & IFF_UP &&
@@ -2632,8 +2871,10 @@ int dev_change_flags(struct net_device *dev, unsigned flags)
dev_set_allmulti(dev, inc);
}
- if (old_flags ^ dev->flags)
- rtmsg_ifinfo(RTM_NEWLINK, dev, old_flags ^ dev->flags);
+ /* Exclude state transition flags, already notified */
+ changes = (old_flags ^ dev->flags) & ~(IFF_UP | IFF_RUNNING);
+ if (changes)
+ rtmsg_ifinfo(RTM_NEWLINK, dev, changes);
return ret;
}
@@ -3105,6 +3346,22 @@ int register_netdevice(struct net_device *dev)
}
}
+ /* Fix illegal checksum combinations */
+ if ((dev->features & NETIF_F_HW_CSUM) &&
+ (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+ printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n",
+ dev->name);
+ dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
+ }
+
+ if ((dev->features & NETIF_F_NO_CSUM) &&
+ (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+ printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n",
+ dev->name);
+ dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
+ }
+
+
/* Fix illegal SG+CSUM combinations. */
if ((dev->features & NETIF_F_SG) &&
!(dev->features & NETIF_F_ALL_CSUM)) {
@@ -3341,16 +3598,18 @@ static struct net_device_stats *internal_stats(struct net_device *dev)
}
/**
- * alloc_netdev - allocate network device
+ * alloc_netdev_mq - allocate network device
* @sizeof_priv: size of private data to allocate space for
* @name: device name format string
* @setup: callback to initialize device
+ * @queue_count: the number of subqueues to allocate
*
* Allocates a struct net_device with private data area for driver use
- * and performs basic initialization.
+ * and performs basic initialization. Also allocates subquue structs
+ * for each queue on the device at the end of the netdevice.
*/
-struct net_device *alloc_netdev(int sizeof_priv, const char *name,
- void (*setup)(struct net_device *))
+struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
+ void (*setup)(struct net_device *), unsigned int queue_count)
{
void *p;
struct net_device *dev;
@@ -3359,7 +3618,9 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name,
BUG_ON(strlen(name) >= sizeof(dev->name));
/* ensure 32-byte alignment of both the device and private area */
- alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST;
+ alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST +
+ (sizeof(struct net_device_subqueue) * queue_count)) &
+ ~NETDEV_ALIGN_CONST;
alloc_size += sizeof_priv + NETDEV_ALIGN_CONST;
p = kzalloc(alloc_size, GFP_KERNEL);
@@ -3372,15 +3633,22 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name,
(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
dev->padded = (char *)dev - (char *)p;
- if (sizeof_priv)
- dev->priv = netdev_priv(dev);
+ if (sizeof_priv) {
+ dev->priv = ((char *)dev +
+ ((sizeof(struct net_device) +
+ (sizeof(struct net_device_subqueue) *
+ queue_count) + NETDEV_ALIGN_CONST)
+ & ~NETDEV_ALIGN_CONST));
+ }
+
+ dev->egress_subqueue_count = queue_count;
dev->get_stats = internal_stats;
setup(dev);
strcpy(dev->name, name);
return dev;
}
-EXPORT_SYMBOL(alloc_netdev);
+EXPORT_SYMBOL(alloc_netdev_mq);
/**
* free_netdev - free network device
@@ -3469,8 +3737,9 @@ void unregister_netdevice(struct net_device *dev)
raw_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
/*
- * Flush the multicast chain
+ * Flush the unicast and multicast chains
*/
+ dev_unicast_discard(dev);
dev_mc_discard(dev);
if (dev->uninit)
@@ -3561,12 +3830,13 @@ static int dev_cpu_callback(struct notifier_block *nfb,
* This is called when the number of channels allocated to the net_dma_client
* changes. The net_dma_client tries to have one DMA channel per CPU.
*/
-static void net_dma_rebalance(void)
+
+static void net_dma_rebalance(struct net_dma *net_dma)
{
- unsigned int cpu, i, n;
+ unsigned int cpu, i, n, chan_idx;
struct dma_chan *chan;
- if (net_dma_count == 0) {
+ if (cpus_empty(net_dma->channel_mask)) {
for_each_online_cpu(cpu)
rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL);
return;
@@ -3575,10 +3845,12 @@ static void net_dma_rebalance(void)
i = 0;
cpu = first_cpu(cpu_online_map);
- rcu_read_lock();
- list_for_each_entry(chan, &net_dma_client->channels, client_node) {
- n = ((num_online_cpus() / net_dma_count)
- + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
+ for_each_cpu_mask(chan_idx, net_dma->channel_mask) {
+ chan = net_dma->channels[chan_idx];
+
+ n = ((num_online_cpus() / cpus_weight(net_dma->channel_mask))
+ + (i < (num_online_cpus() %
+ cpus_weight(net_dma->channel_mask)) ? 1 : 0));
while(n) {
per_cpu(softnet_data, cpu).net_dma = chan;
@@ -3587,7 +3859,6 @@ static void net_dma_rebalance(void)
}
i++;
}
- rcu_read_unlock();
}
/**
@@ -3596,23 +3867,53 @@ static void net_dma_rebalance(void)
* @chan: DMA channel for the event
* @event: event type
*/
-static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
- enum dma_event event)
-{
- spin_lock(&net_dma_event_lock);
- switch (event) {
- case DMA_RESOURCE_ADDED:
- net_dma_count++;
- net_dma_rebalance();
+static enum dma_state_client
+netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+ enum dma_state state)
+{
+ int i, found = 0, pos = -1;
+ struct net_dma *net_dma =
+ container_of(client, struct net_dma, client);
+ enum dma_state_client ack = DMA_DUP; /* default: take no action */
+
+ spin_lock(&net_dma->lock);
+ switch (state) {
+ case DMA_RESOURCE_AVAILABLE:
+ for (i = 0; i < NR_CPUS; i++)
+ if (net_dma->channels[i] == chan) {
+ found = 1;
+ break;
+ } else if (net_dma->channels[i] == NULL && pos < 0)
+ pos = i;
+
+ if (!found && pos >= 0) {
+ ack = DMA_ACK;
+ net_dma->channels[pos] = chan;
+ cpu_set(pos, net_dma->channel_mask);
+ net_dma_rebalance(net_dma);
+ }
break;
case DMA_RESOURCE_REMOVED:
- net_dma_count--;
- net_dma_rebalance();
+ for (i = 0; i < NR_CPUS; i++)
+ if (net_dma->channels[i] == chan) {
+ found = 1;
+ pos = i;
+ break;
+ }
+
+ if (found) {
+ ack = DMA_ACK;
+ cpu_clear(pos, net_dma->channel_mask);
+ net_dma->channels[i] = NULL;
+ net_dma_rebalance(net_dma);
+ }
break;
default:
break;
}
- spin_unlock(&net_dma_event_lock);
+ spin_unlock(&net_dma->lock);
+
+ return ack;
}
/**
@@ -3620,12 +3921,10 @@ static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
*/
static int __init netdev_dma_register(void)
{
- spin_lock_init(&net_dma_event_lock);
- net_dma_client = dma_async_client_register(netdev_dma_event);
- if (net_dma_client == NULL)
- return -ENOMEM;
-
- dma_async_client_chan_request(net_dma_client, num_online_cpus());
+ spin_lock_init(&net_dma.lock);
+ dma_cap_set(DMA_MEMCPY, net_dma.client.cap_mask);
+ dma_async_client_register(&net_dma.client);
+ dma_async_client_chan_request(&net_dma.client);
return 0;
}
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 5a54053386c..235a2a8a0d0 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -64,85 +64,24 @@
*/
/*
- * Update the multicast list into the physical NIC controller.
- */
-
-static void __dev_mc_upload(struct net_device *dev)
-{
- /* Don't do anything till we up the interface
- * [dev_open will call this function so the list will
- * stay sane]
- */
-
- if (!(dev->flags&IFF_UP))
- return;
-
- /*
- * Devices with no set multicast or which have been
- * detached don't get set.
- */
-
- if (dev->set_multicast_list == NULL ||
- !netif_device_present(dev))
- return;
-
- dev->set_multicast_list(dev);
-}
-
-void dev_mc_upload(struct net_device *dev)
-{
- netif_tx_lock_bh(dev);
- __dev_mc_upload(dev);
- netif_tx_unlock_bh(dev);
-}
-
-/*
* Delete a device level multicast
*/
int dev_mc_delete(struct net_device *dev, void *addr, int alen, int glbl)
{
- int err = 0;
- struct dev_mc_list *dmi, **dmip;
+ int err;
netif_tx_lock_bh(dev);
-
- for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
+ err = __dev_addr_delete(&dev->mc_list, &dev->mc_count,
+ addr, alen, glbl);
+ if (!err) {
/*
- * Find the entry we want to delete. The device could
- * have variable length entries so check these too.
+ * We have altered the list, so the card
+ * loaded filter is now wrong. Fix it
*/
- if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
- alen == dmi->dmi_addrlen) {
- if (glbl) {
- int old_glbl = dmi->dmi_gusers;
- dmi->dmi_gusers = 0;
- if (old_glbl == 0)
- break;
- }
- if (--dmi->dmi_users)
- goto done;
-
- /*
- * Last user. So delete the entry.
- */
- *dmip = dmi->next;
- dev->mc_count--;
-
- kfree(dmi);
-
- /*
- * We have altered the list, so the card
- * loaded filter is now wrong. Fix it
- */
- __dev_mc_upload(dev);
-
- netif_tx_unlock_bh(dev);
- return 0;
- }
+
+ __dev_set_rx_mode(dev);
}
- err = -ENOENT;
-done:
netif_tx_unlock_bh(dev);
return err;
}
@@ -153,48 +92,90 @@ done:
int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl)
{
- int err = 0;
- struct dev_mc_list *dmi, *dmi1;
-
- dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
+ int err;
netif_tx_lock_bh(dev);
- for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
- if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
- dmi->dmi_addrlen == alen) {
- if (glbl) {
- int old_glbl = dmi->dmi_gusers;
- dmi->dmi_gusers = 1;
- if (old_glbl)
- goto done;
- }
- dmi->dmi_users++;
- goto done;
+ err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl);
+ if (!err)
+ __dev_set_rx_mode(dev);
+ netif_tx_unlock_bh(dev);
+ return err;
+}
+
+/**
+ * dev_mc_sync - Synchronize device's multicast list to another device
+ * @to: destination device
+ * @from: source device
+ *
+ * Add newly added addresses to the destination device and release
+ * addresses that have no users left. The source device must be
+ * locked by netif_tx_lock_bh.
+ *
+ * This function is intended to be called from the dev->set_multicast_list
+ * function of layered software devices.
+ */
+int dev_mc_sync(struct net_device *to, struct net_device *from)
+{
+ struct dev_addr_list *da;
+ int err = 0;
+
+ netif_tx_lock_bh(to);
+ for (da = from->mc_list; da != NULL; da = da->next) {
+ if (!da->da_synced) {
+ err = __dev_addr_add(&to->mc_list, &to->mc_count,
+ da->da_addr, da->da_addrlen, 0);
+ if (err < 0)
+ break;
+ da->da_synced = 1;
+ da->da_users++;
+ } else if (da->da_users == 1) {
+ __dev_addr_delete(&to->mc_list, &to->mc_count,
+ da->da_addr, da->da_addrlen, 0);
+ __dev_addr_delete(&from->mc_list, &from->mc_count,
+ da->da_addr, da->da_addrlen, 0);
}
}
+ if (!err)
+ __dev_set_rx_mode(to);
+ netif_tx_unlock_bh(to);
- if ((dmi = dmi1) == NULL) {
- netif_tx_unlock_bh(dev);
- return -ENOMEM;
- }
- memcpy(dmi->dmi_addr, addr, alen);
- dmi->dmi_addrlen = alen;
- dmi->next = dev->mc_list;
- dmi->dmi_users = 1;
- dmi->dmi_gusers = glbl ? 1 : 0;
- dev->mc_list = dmi;
- dev->mc_count++;
+ return err;
+}
+EXPORT_SYMBOL(dev_mc_sync);
- __dev_mc_upload(dev);
- netif_tx_unlock_bh(dev);
- return 0;
+/**
+ * dev_mc_unsync - Remove synchronized addresses from the destination
+ * device
+ * @to: destination device
+ * @from: source device
+ *
+ * Remove all addresses that were added to the destination device by
+ * dev_mc_sync(). This function is intended to be called from the
+ * dev->stop function of layered software devices.
+ */
+void dev_mc_unsync(struct net_device *to, struct net_device *from)
+{
+ struct dev_addr_list *da;
+
+ netif_tx_lock_bh(from);
+ netif_tx_lock_bh(to);
+
+ for (da = from->mc_list; da != NULL; da = da->next) {
+ if (!da->da_synced)
+ continue;
+ __dev_addr_delete(&to->mc_list, &to->mc_count,
+ da->da_addr, da->da_addrlen, 0);
+ da->da_synced = 0;
+ __dev_addr_delete(&from->mc_list, &from->mc_count,
+ da->da_addr, da->da_addrlen, 0);
+ }
+ __dev_set_rx_mode(to);
-done:
- netif_tx_unlock_bh(dev);
- kfree(dmi1);
- return err;
+ netif_tx_unlock_bh(to);
+ netif_tx_unlock_bh(from);
}
+EXPORT_SYMBOL(dev_mc_unsync);
/*
* Discard multicast list when a device is downed
@@ -203,16 +184,8 @@ done:
void dev_mc_discard(struct net_device *dev)
{
netif_tx_lock_bh(dev);
-
- while (dev->mc_list != NULL) {
- struct dev_mc_list *tmp = dev->mc_list;
- dev->mc_list = tmp->next;
- if (tmp->dmi_users > tmp->dmi_gusers)
- printk("dev_mc_discard: multicast leakage! dmi_users=%d\n", tmp->dmi_users);
- kfree(tmp);
- }
+ __dev_addr_discard(&dev->mc_list);
dev->mc_count = 0;
-
netif_tx_unlock_bh(dev);
}
@@ -244,7 +217,7 @@ static void dev_mc_seq_stop(struct seq_file *seq, void *v)
static int dev_mc_seq_show(struct seq_file *seq, void *v)
{
- struct dev_mc_list *m;
+ struct dev_addr_list *m;
struct net_device *dev = v;
netif_tx_lock_bh(dev);
@@ -292,4 +265,3 @@ void __init dev_mcast_init(void)
EXPORT_SYMBOL(dev_mc_add);
EXPORT_SYMBOL(dev_mc_delete);
-EXPORT_SYMBOL(dev_mc_upload);
diff --git a/net/core/dst.c b/net/core/dst.c
index 764bccb3d99..c6a05879d58 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -111,13 +111,7 @@ out:
spin_unlock(&dst_lock);
}
-static int dst_discard_in(struct sk_buff *skb)
-{
- kfree_skb(skb);
- return 0;
-}
-
-static int dst_discard_out(struct sk_buff *skb)
+static int dst_discard(struct sk_buff *skb)
{
kfree_skb(skb);
return 0;
@@ -138,8 +132,7 @@ void * dst_alloc(struct dst_ops * ops)
dst->ops = ops;
dst->lastuse = jiffies;
dst->path = dst;
- dst->input = dst_discard_in;
- dst->output = dst_discard_out;
+ dst->input = dst->output = dst_discard;
#if RT_CACHE_DEBUG >= 2
atomic_inc(&dst_total);
#endif
@@ -153,8 +146,7 @@ static void ___dst_free(struct dst_entry * dst)
protocol module is unloaded.
*/
if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) {
- dst->input = dst_discard_in;
- dst->output = dst_discard_out;
+ dst->input = dst->output = dst_discard;
}
dst->obsolete = 2;
}
@@ -242,8 +234,7 @@ static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
return;
if (!unregister) {
- dst->input = dst_discard_in;
- dst->output = dst_discard_out;
+ dst->input = dst->output = dst_discard;
} else {
dst->dev = &loopback_dev;
dev_hold(&loopback_dev);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 8d5e5a09b57..0b531e98ec3 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -52,6 +52,17 @@ int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data)
return 0;
}
+
+int ethtool_op_set_tx_ipv6_csum(struct net_device *dev, u32 data)
+{
+ if (data)
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ else
+ dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
+
+ return 0;
+}
+
u32 ethtool_op_get_sg(struct net_device *dev)
{
return (dev->features & NETIF_F_SG) != 0;
@@ -980,5 +991,6 @@ EXPORT_SYMBOL(ethtool_op_set_sg);
EXPORT_SYMBOL(ethtool_op_set_tso);
EXPORT_SYMBOL(ethtool_op_set_tx_csum);
EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
+EXPORT_SYMBOL(ethtool_op_set_tx_ipv6_csum);
EXPORT_SYMBOL(ethtool_op_set_ufo);
EXPORT_SYMBOL(ethtool_op_get_ufo);
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
index 17daf4c9f79..cc84d8d8a3c 100644
--- a/net/core/gen_estimator.c
+++ b/net/core/gen_estimator.c
@@ -128,7 +128,8 @@ static void est_timer(unsigned long arg)
spin_unlock(e->stats_lock);
}
- mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
+ if (elist[idx].list != NULL)
+ mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
read_unlock(&est_lock);
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 6f3bb73053c..9df26a07f06 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1761,7 +1761,7 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
return NULL;
}
-static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = {
+static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
[NDTA_NAME] = { .type = NLA_STRING },
[NDTA_THRESH1] = { .type = NLA_U32 },
[NDTA_THRESH2] = { .type = NLA_U32 },
@@ -1770,7 +1770,7 @@ static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = {
[NDTA_PARMS] = { .type = NLA_NESTED },
};
-static struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] __read_mostly = {
+static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
[NDTPA_IFINDEX] = { .type = NLA_U32 },
[NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
[NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
diff --git a/net/core/netevent.c b/net/core/netevent.c
index 35d02c38554..95f81de8750 100644
--- a/net/core/netevent.c
+++ b/net/core/netevent.c
@@ -15,6 +15,7 @@
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
+#include <net/netevent.h>
static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 758dafe284c..d1264e9a50a 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -66,8 +66,9 @@ static void queue_process(struct work_struct *work)
local_irq_save(flags);
netif_tx_lock(dev);
- if (netif_queue_stopped(dev) ||
- dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
+ if ((netif_queue_stopped(dev) ||
+ netif_subqueue_stopped(dev, skb->queue_mapping)) ||
+ dev->hard_start_xmit(skb, dev) != NETDEV_TX_OK) {
skb_queue_head(&npinfo->txq, skb);
netif_tx_unlock(dev);
local_irq_restore(flags);
@@ -123,6 +124,13 @@ static void poll_napi(struct netpoll *np)
if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
npinfo->poll_owner != smp_processor_id() &&
spin_trylock(&npinfo->poll_lock)) {
+ /* When calling dev->poll from poll_napi, we may end up in
+ * netif_rx_complete. However, only the CPU to which the
+ * device was queued is allowed to remove it from poll_list.
+ * Setting POLL_LIST_FROZEN tells netif_rx_complete
+ * to leave the NAPI state alone.
+ */
+ set_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
npinfo->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped);
@@ -130,6 +138,7 @@ static void poll_napi(struct netpoll *np)
atomic_dec(&trapped);
npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+ clear_bit(__LINK_STATE_POLL_LIST_FROZEN, &np->dev->state);
spin_unlock(&npinfo->poll_lock);
}
}
@@ -250,22 +259,24 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
unsigned long flags;
local_irq_save(flags);
- if (netif_tx_trylock(dev)) {
- /* try until next clock tick */
- for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
- tries > 0; --tries) {
- if (!netif_queue_stopped(dev))
+ /* try until next clock tick */
+ for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
+ tries > 0; --tries) {
+ if (netif_tx_trylock(dev)) {
+ if (!netif_queue_stopped(dev) &&
+ !netif_subqueue_stopped(dev, skb->queue_mapping))
status = dev->hard_start_xmit(skb, dev);
+ netif_tx_unlock(dev);
if (status == NETDEV_TX_OK)
break;
- /* tickle device maybe there is some cleanup */
- netpoll_poll(np);
-
- udelay(USEC_PER_POLL);
}
- netif_tx_unlock(dev);
+
+ /* tickle device maybe there is some cleanup */
+ netpoll_poll(np);
+
+ udelay(USEC_PER_POLL);
}
local_irq_restore(flags);
}
@@ -780,14 +791,19 @@ void netpoll_cleanup(struct netpoll *np)
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
}
- np->dev->npinfo = NULL;
if (atomic_dec_and_test(&npinfo->refcnt)) {
skb_queue_purge(&npinfo->arp_tx);
skb_queue_purge(&npinfo->txq);
cancel_rearming_delayed_work(&npinfo->tx_work);
- flush_scheduled_work();
+ /* clean after last, unfinished work */
+ if (!skb_queue_empty(&npinfo->txq)) {
+ struct sk_buff *skb;
+ skb = __skb_dequeue(&npinfo->txq);
+ kfree_skb(skb);
+ }
kfree(npinfo);
+ np->dev->npinfo = NULL;
}
}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 9cd3a1cb60e..75215331b04 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -152,6 +152,9 @@
#include <net/checksum.h>
#include <net/ipv6.h>
#include <net/addrconf.h>
+#ifdef CONFIG_XFRM
+#include <net/xfrm.h>
+#endif
#include <asm/byteorder.h>
#include <linux/rcupdate.h>
#include <asm/bitops.h>
@@ -181,6 +184,8 @@
#define F_MPLS_RND (1<<8) /* Random MPLS labels */
#define F_VID_RND (1<<9) /* Random VLAN ID */
#define F_SVID_RND (1<<10) /* Random SVLAN ID */
+#define F_FLOW_SEQ (1<<11) /* Sequential flows */
+#define F_IPSEC_ON (1<<12) /* ipsec on for flows */
/* Thread control flag bits */
#define T_TERMINATE (1<<0)
@@ -207,8 +212,15 @@ static struct proc_dir_entry *pg_proc_dir = NULL;
struct flow_state {
__be32 cur_daddr;
int count;
+#ifdef CONFIG_XFRM
+ struct xfrm_state *x;
+#endif
+ __u32 flags;
};
+/* flow flag bits */
+#define F_INIT (1<<0) /* flow has been initialized */
+
struct pktgen_dev {
/*
* Try to keep frequent/infrequent used vars. separated.
@@ -228,6 +240,7 @@ struct pktgen_dev {
int min_pkt_size; /* = ETH_ZLEN; */
int max_pkt_size; /* = ETH_ZLEN; */
+ int pkt_overhead; /* overhead for MPLS, VLANs, IPSEC etc */
int nfrags;
__u32 delay_us; /* Default delay */
__u32 delay_ns;
@@ -341,7 +354,11 @@ struct pktgen_dev {
unsigned cflows; /* Concurrent flows (config) */
unsigned lflow; /* Flow length (config) */
unsigned nflows; /* accumulated flows (stats) */
-
+ unsigned curfl; /* current sequenced flow (state)*/
+#ifdef CONFIG_XFRM
+ __u8 ipsmode; /* IPSEC mode (config) */
+ __u8 ipsproto; /* IPSEC type (config) */
+#endif
char result[512];
};
@@ -690,6 +707,18 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
if (pkt_dev->flags & F_MPLS_RND)
seq_printf(seq, "MPLS_RND ");
+ if (pkt_dev->cflows) {
+ if (pkt_dev->flags & F_FLOW_SEQ)
+ seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/
+ else
+ seq_printf(seq, "FLOW_RND ");
+ }
+
+#ifdef CONFIG_XFRM
+ if (pkt_dev->flags & F_IPSEC_ON)
+ seq_printf(seq, "IPSEC ");
+#endif
+
if (pkt_dev->flags & F_MACSRC_RND)
seq_printf(seq, "MACSRC_RND ");
@@ -1181,6 +1210,14 @@ static ssize_t pktgen_if_write(struct file *file,
else if (strcmp(f, "!SVID_RND") == 0)
pkt_dev->flags &= ~F_SVID_RND;
+ else if (strcmp(f, "FLOW_SEQ") == 0)
+ pkt_dev->flags |= F_FLOW_SEQ;
+
+#ifdef CONFIG_XFRM
+ else if (strcmp(f, "IPSEC") == 0)
+ pkt_dev->flags |= F_IPSEC_ON;
+#endif
+
else if (strcmp(f, "!IPV6") == 0)
pkt_dev->flags &= ~F_IPV6;
@@ -1189,7 +1226,7 @@ static ssize_t pktgen_if_write(struct file *file,
"Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s",
f,
"IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, "
- "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND\n");
+ "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n");
return count;
}
sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags);
@@ -2075,6 +2112,70 @@ static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us)
pkt_dev->idle_acc += now - start;
}
+static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev)
+{
+ pkt_dev->pkt_overhead = 0;
+ pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32);
+ pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev);
+ pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev);
+}
+
+static inline int f_seen(struct pktgen_dev *pkt_dev, int flow)
+{
+
+ if (pkt_dev->flows[flow].flags & F_INIT)
+ return 1;
+ else
+ return 0;
+}
+
+static inline int f_pick(struct pktgen_dev *pkt_dev)
+{
+ int flow = pkt_dev->curfl;
+
+ if (pkt_dev->flags & F_FLOW_SEQ) {
+ if (pkt_dev->flows[flow].count >= pkt_dev->lflow) {
+ /* reset time */
+ pkt_dev->flows[flow].count = 0;
+ pkt_dev->curfl += 1;
+ if (pkt_dev->curfl >= pkt_dev->cflows)
+ pkt_dev->curfl = 0; /*reset */
+ }
+ } else {
+ flow = random32() % pkt_dev->cflows;
+
+ if (pkt_dev->flows[flow].count > pkt_dev->lflow)
+ pkt_dev->flows[flow].count = 0;
+ }
+
+ return pkt_dev->curfl;
+}
+
+
+#ifdef CONFIG_XFRM
+/* If there was already an IPSEC SA, we keep it as is, else
+ * we go look for it ...
+*/
+inline
+void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
+{
+ struct xfrm_state *x = pkt_dev->flows[flow].x;
+ if (!x) {
+ /*slow path: we dont already have xfrm_state*/
+ x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr,
+ (xfrm_address_t *)&pkt_dev->cur_saddr,
+ AF_INET,
+ pkt_dev->ipsmode,
+ pkt_dev->ipsproto, 0);
+ if (x) {
+ pkt_dev->flows[flow].x = x;
+ set_pkt_overhead(pkt_dev);
+ pkt_dev->pkt_overhead+=x->props.header_len;
+ }
+
+ }
+}
+#endif
/* Increment/randomize headers according to flags and current values
* for IP src/dest, UDP src/dst port, MAC-Addr src/dst
*/
@@ -2084,12 +2185,8 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
__u32 imx;
int flow = 0;
- if (pkt_dev->cflows) {
- flow = random32() % pkt_dev->cflows;
-
- if (pkt_dev->flows[flow].count > pkt_dev->lflow)
- pkt_dev->flows[flow].count = 0;
- }
+ if (pkt_dev->cflows)
+ flow = f_pick(pkt_dev);
/* Deal with source MAC */
if (pkt_dev->src_mac_count > 1) {
@@ -2205,7 +2302,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
pkt_dev->cur_saddr = htonl(t);
}
- if (pkt_dev->cflows && pkt_dev->flows[flow].count != 0) {
+ if (pkt_dev->cflows && f_seen(pkt_dev, flow)) {
pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr;
} else {
imn = ntohl(pkt_dev->daddr_min);
@@ -2235,8 +2332,13 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
}
}
if (pkt_dev->cflows) {
+ pkt_dev->flows[flow].flags |= F_INIT;
pkt_dev->flows[flow].cur_daddr =
pkt_dev->cur_daddr;
+#ifdef CONFIG_XFRM
+ if (pkt_dev->flags & F_IPSEC_ON)
+ get_ipsec_sa(pkt_dev, flow);
+#endif
pkt_dev->nflows++;
}
}
@@ -2277,6 +2379,91 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
pkt_dev->flows[flow].count++;
}
+
+#ifdef CONFIG_XFRM
+static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
+{
+ struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
+ int err = 0;
+ struct iphdr *iph;
+
+ if (!x)
+ return 0;
+ /* XXX: we dont support tunnel mode for now until
+ * we resolve the dst issue */
+ if (x->props.mode != XFRM_MODE_TRANSPORT)
+ return 0;
+
+ spin_lock(&x->lock);
+ iph = ip_hdr(skb);
+
+ err = x->mode->output(x, skb);
+ if (err)
+ goto error;
+ err = x->type->output(x, skb);
+ if (err)
+ goto error;
+
+ x->curlft.bytes +=skb->len;
+ x->curlft.packets++;
+ spin_unlock(&x->lock);
+
+error:
+ spin_unlock(&x->lock);
+ return err;
+}
+
+static inline void free_SAs(struct pktgen_dev *pkt_dev)
+{
+ if (pkt_dev->cflows) {
+ /* let go of the SAs if we have them */
+ int i = 0;
+ for (; i < pkt_dev->nflows; i++){
+ struct xfrm_state *x = pkt_dev->flows[i].x;
+ if (x) {
+ xfrm_state_put(x);
+ pkt_dev->flows[i].x = NULL;
+ }
+ }
+ }
+}
+
+static inline int process_ipsec(struct pktgen_dev *pkt_dev,
+ struct sk_buff *skb, __be16 protocol)
+{
+ if (pkt_dev->flags & F_IPSEC_ON) {
+ struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x;
+ int nhead = 0;
+ if (x) {
+ int ret;
+ __u8 *eth;
+ nhead = x->props.header_len - skb_headroom(skb);
+ if (nhead >0) {
+ ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
+ if (ret < 0) {
+ printk("Error expanding ipsec packet %d\n",ret);
+ return 0;
+ }
+ }
+
+ /* ipsec is not expecting ll header */
+ skb_pull(skb, ETH_HLEN);
+ ret = pktgen_output_ipsec(skb, pkt_dev);
+ if (ret) {
+ printk("Error creating ipsec packet %d\n",ret);
+ kfree_skb(skb);
+ return 0;
+ }
+ /* restore ll */
+ eth = (__u8 *) skb_push(skb, ETH_HLEN);
+ memcpy(eth, pkt_dev->hh, 12);
+ *(u16 *) & eth[12] = protocol;
+ }
+ }
+ return 1;
+}
+#endif
+
static void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev)
{
unsigned i;
@@ -2323,9 +2510,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
datalen = (odev->hard_header_len + 16) & ~0xf;
skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen +
- pkt_dev->nr_labels*sizeof(u32) +
- VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
- GFP_ATOMIC);
+ pkt_dev->pkt_overhead, GFP_ATOMIC);
if (!skb) {
sprintf(pkt_dev->result, "No memory");
return NULL;
@@ -2368,7 +2553,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
/* Eth + IPh + UDPh + mpls */
datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
- pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
+ pkt_dev->pkt_overhead;
if (datalen < sizeof(struct pktgen_hdr))
datalen = sizeof(struct pktgen_hdr);
@@ -2391,8 +2576,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
iph->check = ip_fast_csum((void *)iph, iph->ihl);
skb->protocol = protocol;
skb->mac_header = (skb->network_header - ETH_HLEN -
- pkt_dev->nr_labels * sizeof(u32) -
- VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev));
+ pkt_dev->pkt_overhead);
skb->dev = odev;
skb->pkt_type = PACKET_HOST;
@@ -2463,6 +2647,11 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
pgh->tv_usec = htonl(timestamp.tv_usec);
}
+#ifdef CONFIG_XFRM
+ if (!process_ipsec(pkt_dev, skb, protocol))
+ return NULL;
+#endif
+
return skb;
}
@@ -2662,9 +2851,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
mod_cur_headers(pkt_dev);
skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16 +
- pkt_dev->nr_labels*sizeof(u32) +
- VLAN_TAG_SIZE(pkt_dev) + SVLAN_TAG_SIZE(pkt_dev),
- GFP_ATOMIC);
+ pkt_dev->pkt_overhead, GFP_ATOMIC);
if (!skb) {
sprintf(pkt_dev->result, "No memory");
return NULL;
@@ -2708,7 +2895,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
/* Eth + IPh + UDPh + mpls */
datalen = pkt_dev->cur_pkt_size - 14 -
sizeof(struct ipv6hdr) - sizeof(struct udphdr) -
- pkt_dev->nr_labels*sizeof(u32) - VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev);
+ pkt_dev->pkt_overhead;
if (datalen < sizeof(struct pktgen_hdr)) {
datalen = sizeof(struct pktgen_hdr);
@@ -2738,8 +2925,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
ipv6_addr_copy(&iph->saddr, &pkt_dev->cur_in6_saddr);
skb->mac_header = (skb->network_header - ETH_HLEN -
- pkt_dev->nr_labels * sizeof(u32) -
- VLAN_TAG_SIZE(pkt_dev) - SVLAN_TAG_SIZE(pkt_dev));
+ pkt_dev->pkt_overhead);
skb->protocol = protocol;
skb->dev = odev;
skb->pkt_type = PACKET_HOST;
@@ -2857,6 +3043,7 @@ static void pktgen_run(struct pktgen_thread *t)
pkt_dev->started_at = getCurUs();
pkt_dev->next_tx_us = getCurUs(); /* Transmit immediately */
pkt_dev->next_tx_ns = 0;
+ set_pkt_overhead(pkt_dev);
strcpy(pkt_dev->result, "Starting");
started++;
@@ -3139,7 +3326,9 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
}
}
- if (netif_queue_stopped(odev) || need_resched()) {
+ if ((netif_queue_stopped(odev) ||
+ netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) ||
+ need_resched()) {
idle_start = getCurUs();
if (!netif_running(odev)) {
@@ -3154,7 +3343,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
pkt_dev->idle_acc += getCurUs() - idle_start;
- if (netif_queue_stopped(odev)) {
+ if (netif_queue_stopped(odev) ||
+ netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) {
pkt_dev->next_tx_us = getCurUs(); /* TODO */
pkt_dev->next_tx_ns = 0;
goto out; /* Try the next interface */
@@ -3181,7 +3371,8 @@ static __inline__ void pktgen_xmit(struct pktgen_dev *pkt_dev)
}
netif_tx_lock_bh(odev);
- if (!netif_queue_stopped(odev)) {
+ if (!netif_queue_stopped(odev) &&
+ !netif_subqueue_stopped(odev, pkt_dev->skb->queue_mapping)) {
atomic_inc(&(pkt_dev->skb->users));
retry_now:
@@ -3446,11 +3637,18 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
}
pkt_dev->entry->proc_fops = &pktgen_if_fops;
pkt_dev->entry->data = pkt_dev;
+#ifdef CONFIG_XFRM
+ pkt_dev->ipsmode = XFRM_MODE_TRANSPORT;
+ pkt_dev->ipsproto = IPPROTO_ESP;
+#endif
return add_dev_to_thread(t, pkt_dev);
out2:
dev_put(pkt_dev->odev);
out1:
+#ifdef CONFIG_XFRM
+ free_SAs(pkt_dev);
+#endif
if (pkt_dev->flows)
vfree(pkt_dev->flows);
kfree(pkt_dev);
@@ -3545,6 +3743,9 @@ static int pktgen_remove_device(struct pktgen_thread *t,
if (pkt_dev->entry)
remove_proc_entry(pkt_dev->entry->name, pg_proc_dir);
+#ifdef CONFIG_XFRM
+ free_SAs(pkt_dev);
+#endif
if (pkt_dev->flows)
vfree(pkt_dev->flows);
kfree(pkt_dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 27da9cdec6a..864cbdf31ed 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -97,6 +97,19 @@ int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
return 0;
}
+int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+ struct rtattr *rta, int len)
+{
+ if (RTA_PAYLOAD(rta) < len)
+ return -1;
+ if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
+ rta = RTA_DATA(rta) + RTA_ALIGN(len);
+ return rtattr_parse_nested(tb, maxattr, rta);
+ }
+ memset(tb, 0, sizeof(struct rtattr *) * maxattr);
+ return 0;
+}
+
static struct rtnl_link *rtnl_msg_handlers[NPROTO];
static inline int rtm_msgindex(int msgtype)
@@ -243,6 +256,150 @@ void rtnl_unregister_all(int protocol)
EXPORT_SYMBOL_GPL(rtnl_unregister_all);
+static LIST_HEAD(link_ops);
+
+/**
+ * __rtnl_link_register - Register rtnl_link_ops with rtnetlink.
+ * @ops: struct rtnl_link_ops * to register
+ *
+ * The caller must hold the rtnl_mutex. This function should be used
+ * by drivers that create devices during module initialization. It
+ * must be called before registering the devices.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int __rtnl_link_register(struct rtnl_link_ops *ops)
+{
+ if (!ops->dellink)
+ ops->dellink = unregister_netdevice;
+
+ list_add_tail(&ops->list, &link_ops);
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(__rtnl_link_register);
+
+/**
+ * rtnl_link_register - Register rtnl_link_ops with rtnetlink.
+ * @ops: struct rtnl_link_ops * to register
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int rtnl_link_register(struct rtnl_link_ops *ops)
+{
+ int err;
+
+ rtnl_lock();
+ err = __rtnl_link_register(ops);
+ rtnl_unlock();
+ return err;
+}
+
+EXPORT_SYMBOL_GPL(rtnl_link_register);
+
+/**
+ * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+ * @ops: struct rtnl_link_ops * to unregister
+ *
+ * The caller must hold the rtnl_mutex.
+ */
+void __rtnl_link_unregister(struct rtnl_link_ops *ops)
+{
+ struct net_device *dev, *n;
+
+ for_each_netdev_safe(dev, n) {
+ if (dev->rtnl_link_ops == ops)
+ ops->dellink(dev);
+ }
+ list_del(&ops->list);
+}
+
+EXPORT_SYMBOL_GPL(__rtnl_link_unregister);
+
+/**
+ * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
+ * @ops: struct rtnl_link_ops * to unregister
+ */
+void rtnl_link_unregister(struct rtnl_link_ops *ops)
+{
+ rtnl_lock();
+ __rtnl_link_unregister(ops);
+ rtnl_unlock();
+}
+
+EXPORT_SYMBOL_GPL(rtnl_link_unregister);
+
+static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind)
+{
+ const struct rtnl_link_ops *ops;
+
+ list_for_each_entry(ops, &link_ops, list) {
+ if (!strcmp(ops->kind, kind))
+ return ops;
+ }
+ return NULL;
+}
+
+static size_t rtnl_link_get_size(const struct net_device *dev)
+{
+ const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+ size_t size;
+
+ if (!ops)
+ return 0;
+
+ size = nlmsg_total_size(sizeof(struct nlattr)) + /* IFLA_LINKINFO */
+ nlmsg_total_size(strlen(ops->kind) + 1); /* IFLA_INFO_KIND */
+
+ if (ops->get_size)
+ /* IFLA_INFO_DATA + nested data */
+ size += nlmsg_total_size(sizeof(struct nlattr)) +
+ ops->get_size(dev);
+
+ if (ops->get_xstats_size)
+ size += ops->get_xstats_size(dev); /* IFLA_INFO_XSTATS */
+
+ return size;
+}
+
+static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
+{
+ const struct rtnl_link_ops *ops = dev->rtnl_link_ops;
+ struct nlattr *linkinfo, *data;
+ int err = -EMSGSIZE;
+
+ linkinfo = nla_nest_start(skb, IFLA_LINKINFO);
+ if (linkinfo == NULL)
+ goto out;
+
+ if (nla_put_string(skb, IFLA_INFO_KIND, ops->kind) < 0)
+ goto err_cancel_link;
+ if (ops->fill_xstats) {
+ err = ops->fill_xstats(skb, dev);
+ if (err < 0)
+ goto err_cancel_link;
+ }
+ if (ops->fill_info) {
+ data = nla_nest_start(skb, IFLA_INFO_DATA);
+ if (data == NULL)
+ goto err_cancel_link;
+ err = ops->fill_info(skb, dev);
+ if (err < 0)
+ goto err_cancel_data;
+ nla_nest_end(skb, data);
+ }
+
+ nla_nest_end(skb, linkinfo);
+ return 0;
+
+err_cancel_data:
+ nla_nest_cancel(skb, data);
+err_cancel_link:
+ nla_nest_cancel(skb, linkinfo);
+out:
+ return err;
+}
+
static const int rtm_min[RTM_NR_FAMILIES] =
{
[RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
@@ -437,7 +594,7 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
a->tx_compressed = b->tx_compressed;
};
-static inline size_t if_nlmsg_size(void)
+static inline size_t if_nlmsg_size(const struct net_device *dev)
{
return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+ nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
@@ -452,7 +609,8 @@ static inline size_t if_nlmsg_size(void)
+ nla_total_size(4) /* IFLA_LINK */
+ nla_total_size(4) /* IFLA_MASTER */
+ nla_total_size(1) /* IFLA_OPERSTATE */
- + nla_total_size(1); /* IFLA_LINKMODE */
+ + nla_total_size(1) /* IFLA_LINKMODE */
+ + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
}
static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
@@ -522,6 +680,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
}
}
+ if (dev->rtnl_link_ops) {
+ if (rtnl_link_fill(skb, dev) < 0)
+ goto nla_put_failure;
+ }
+
return nlmsg_end(skb, nlh);
nla_put_failure:
@@ -551,8 +714,10 @@ cont:
return skb->len;
}
-static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = {
+static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
+ [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
+ [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
[IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
[IFLA_MTU] = { .type = NLA_U32 },
[IFLA_TXQLEN] = { .type = NLA_U32 },
@@ -561,44 +726,16 @@ static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = {
[IFLA_LINKMODE] = { .type = NLA_U8 },
};
-static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
-{
- struct ifinfomsg *ifm;
- struct net_device *dev;
- int err, send_addr_notify = 0, modified = 0;
- struct nlattr *tb[IFLA_MAX+1];
- char ifname[IFNAMSIZ];
-
- err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
- if (err < 0)
- goto errout;
-
- if (tb[IFLA_IFNAME])
- nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
- else
- ifname[0] = '\0';
-
- err = -EINVAL;
- ifm = nlmsg_data(nlh);
- if (ifm->ifi_index >= 0)
- dev = dev_get_by_index(ifm->ifi_index);
- else if (tb[IFLA_IFNAME])
- dev = dev_get_by_name(ifname);
- else
- goto errout;
-
- if (dev == NULL) {
- err = -ENODEV;
- goto errout;
- }
-
- if (tb[IFLA_ADDRESS] &&
- nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
- goto errout_dev;
+static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
+ [IFLA_INFO_KIND] = { .type = NLA_STRING },
+ [IFLA_INFO_DATA] = { .type = NLA_NESTED },
+};
- if (tb[IFLA_BROADCAST] &&
- nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
- goto errout_dev;
+static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
+ struct nlattr **tb, char *ifname, int modified)
+{
+ int send_addr_notify = 0;
+ int err;
if (tb[IFLA_MAP]) {
struct rtnl_link_ifmap *u_map;
@@ -606,12 +743,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (!dev->set_config) {
err = -EOPNOTSUPP;
- goto errout_dev;
+ goto errout;
}
if (!netif_device_present(dev)) {
err = -ENODEV;
- goto errout_dev;
+ goto errout;
}
u_map = nla_data(tb[IFLA_MAP]);
@@ -624,7 +761,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = dev->set_config(dev, &k_map);
if (err < 0)
- goto errout_dev;
+ goto errout;
modified = 1;
}
@@ -635,19 +772,19 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (!dev->set_mac_address) {
err = -EOPNOTSUPP;
- goto errout_dev;
+ goto errout;
}
if (!netif_device_present(dev)) {
err = -ENODEV;
- goto errout_dev;
+ goto errout;
}
len = sizeof(sa_family_t) + dev->addr_len;
sa = kmalloc(len, GFP_KERNEL);
if (!sa) {
err = -ENOMEM;
- goto errout_dev;
+ goto errout;
}
sa->sa_family = dev->type;
memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
@@ -655,7 +792,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = dev->set_mac_address(dev, sa);
kfree(sa);
if (err)
- goto errout_dev;
+ goto errout;
send_addr_notify = 1;
modified = 1;
}
@@ -663,7 +800,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (tb[IFLA_MTU]) {
err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
if (err < 0)
- goto errout_dev;
+ goto errout;
modified = 1;
}
@@ -672,10 +809,10 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
* name provided implies that a name change has been
* requested.
*/
- if (ifm->ifi_index >= 0 && ifname[0]) {
+ if (ifm->ifi_index > 0 && ifname[0]) {
err = dev_change_name(dev, ifname);
if (err < 0)
- goto errout_dev;
+ goto errout;
modified = 1;
}
@@ -684,7 +821,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
send_addr_notify = 1;
}
-
if (ifm->ifi_flags || ifm->ifi_change) {
unsigned int flags = ifm->ifi_flags;
@@ -712,7 +848,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = 0;
-errout_dev:
+errout:
if (err < 0 && modified && net_ratelimit())
printk(KERN_WARNING "A link change request failed with "
"some changes comitted already. Interface %s may "
@@ -721,12 +857,239 @@ errout_dev:
if (send_addr_notify)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+ return err;
+}
+
+static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct ifinfomsg *ifm;
+ struct net_device *dev;
+ int err;
+ struct nlattr *tb[IFLA_MAX+1];
+ char ifname[IFNAMSIZ];
+
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+ if (err < 0)
+ goto errout;
+
+ if (tb[IFLA_IFNAME])
+ nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+ else
+ ifname[0] = '\0';
+
+ err = -EINVAL;
+ ifm = nlmsg_data(nlh);
+ if (ifm->ifi_index > 0)
+ dev = dev_get_by_index(ifm->ifi_index);
+ else if (tb[IFLA_IFNAME])
+ dev = dev_get_by_name(ifname);
+ else
+ goto errout;
+
+ if (dev == NULL) {
+ err = -ENODEV;
+ goto errout;
+ }
+ if (tb[IFLA_ADDRESS] &&
+ nla_len(tb[IFLA_ADDRESS]) < dev->addr_len)
+ goto errout_dev;
+
+ if (tb[IFLA_BROADCAST] &&
+ nla_len(tb[IFLA_BROADCAST]) < dev->addr_len)
+ goto errout_dev;
+
+ err = do_setlink(dev, ifm, tb, ifname, 0);
+errout_dev:
dev_put(dev);
errout:
return err;
}
+static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ const struct rtnl_link_ops *ops;
+ struct net_device *dev;
+ struct ifinfomsg *ifm;
+ char ifname[IFNAMSIZ];
+ struct nlattr *tb[IFLA_MAX+1];
+ int err;
+
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[IFLA_IFNAME])
+ nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+
+ ifm = nlmsg_data(nlh);
+ if (ifm->ifi_index > 0)
+ dev = __dev_get_by_index(ifm->ifi_index);
+ else if (tb[IFLA_IFNAME])
+ dev = __dev_get_by_name(ifname);
+ else
+ return -EINVAL;
+
+ if (!dev)
+ return -ENODEV;
+
+ ops = dev->rtnl_link_ops;
+ if (!ops)
+ return -EOPNOTSUPP;
+
+ ops->dellink(dev);
+ return 0;
+}
+
+static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ const struct rtnl_link_ops *ops;
+ struct net_device *dev;
+ struct ifinfomsg *ifm;
+ char kind[MODULE_NAME_LEN];
+ char ifname[IFNAMSIZ];
+ struct nlattr *tb[IFLA_MAX+1];
+ struct nlattr *linkinfo[IFLA_INFO_MAX+1];
+ int err;
+
+replay:
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[IFLA_IFNAME])
+ nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
+ else
+ ifname[0] = '\0';
+
+ ifm = nlmsg_data(nlh);
+ if (ifm->ifi_index > 0)
+ dev = __dev_get_by_index(ifm->ifi_index);
+ else if (ifname[0])
+ dev = __dev_get_by_name(ifname);
+ else
+ dev = NULL;
+
+ if (tb[IFLA_LINKINFO]) {
+ err = nla_parse_nested(linkinfo, IFLA_INFO_MAX,
+ tb[IFLA_LINKINFO], ifla_info_policy);
+ if (err < 0)
+ return err;
+ } else
+ memset(linkinfo, 0, sizeof(linkinfo));
+
+ if (linkinfo[IFLA_INFO_KIND]) {
+ nla_strlcpy(kind, linkinfo[IFLA_INFO_KIND], sizeof(kind));
+ ops = rtnl_link_ops_get(kind);
+ } else {
+ kind[0] = '\0';
+ ops = NULL;
+ }
+
+ if (1) {
+ struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL;
+
+ if (ops) {
+ if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) {
+ err = nla_parse_nested(attr, ops->maxtype,
+ linkinfo[IFLA_INFO_DATA],
+ ops->policy);
+ if (err < 0)
+ return err;
+ data = attr;
+ }
+ if (ops->validate) {
+ err = ops->validate(tb, data);
+ if (err < 0)
+ return err;
+ }
+ }
+
+ if (dev) {
+ int modified = 0;
+
+ if (nlh->nlmsg_flags & NLM_F_EXCL)
+ return -EEXIST;
+ if (nlh->nlmsg_flags & NLM_F_REPLACE)
+ return -EOPNOTSUPP;
+
+ if (linkinfo[IFLA_INFO_DATA]) {
+ if (!ops || ops != dev->rtnl_link_ops ||
+ !ops->changelink)
+ return -EOPNOTSUPP;
+
+ err = ops->changelink(dev, tb, data);
+ if (err < 0)
+ return err;
+ modified = 1;
+ }
+
+ return do_setlink(dev, ifm, tb, ifname, modified);
+ }
+
+ if (!(nlh->nlmsg_flags & NLM_F_CREATE))
+ return -ENODEV;
+
+ if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change)
+ return -EOPNOTSUPP;
+ if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO])
+ return -EOPNOTSUPP;
+
+ if (!ops) {
+#ifdef CONFIG_KMOD
+ if (kind[0]) {
+ __rtnl_unlock();
+ request_module("rtnl-link-%s", kind);
+ rtnl_lock();
+ ops = rtnl_link_ops_get(kind);
+ if (ops)
+ goto replay;
+ }
+#endif
+ return -EOPNOTSUPP;
+ }
+
+ if (!ifname[0])
+ snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
+ dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
+ if (!dev)
+ return -ENOMEM;
+
+ if (strchr(dev->name, '%')) {
+ err = dev_alloc_name(dev, dev->name);
+ if (err < 0)
+ goto err_free;
+ }
+ dev->rtnl_link_ops = ops;
+
+ if (tb[IFLA_MTU])
+ dev->mtu = nla_get_u32(tb[IFLA_MTU]);
+ if (tb[IFLA_ADDRESS])
+ memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]),
+ nla_len(tb[IFLA_ADDRESS]));
+ if (tb[IFLA_BROADCAST])
+ memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]),
+ nla_len(tb[IFLA_BROADCAST]));
+ if (tb[IFLA_TXQLEN])
+ dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+ if (tb[IFLA_WEIGHT])
+ dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
+ if (tb[IFLA_OPERSTATE])
+ set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+ if (tb[IFLA_LINKMODE])
+ dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+
+ if (ops->newlink)
+ err = ops->newlink(dev, tb, data);
+ else
+ err = register_netdevice(dev);
+err_free:
+ if (err < 0)
+ free_netdev(dev);
+ return err;
+ }
+}
+
static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct ifinfomsg *ifm;
@@ -740,14 +1103,14 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
return err;
ifm = nlmsg_data(nlh);
- if (ifm->ifi_index >= 0) {
+ if (ifm->ifi_index > 0) {
dev = dev_get_by_index(ifm->ifi_index);
if (dev == NULL)
return -ENODEV;
} else
return -EINVAL;
- nskb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL);
+ nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
if (nskb == NULL) {
err = -ENOBUFS;
goto errout;
@@ -797,7 +1160,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
struct sk_buff *skb;
int err = -ENOBUFS;
- skb = nlmsg_new(if_nlmsg_size(), GFP_KERNEL);
+ skb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL);
if (skb == NULL)
goto errout;
@@ -952,6 +1315,8 @@ void __init rtnetlink_init(void)
rtnl_register(PF_UNSPEC, RTM_GETLINK, rtnl_getlink, rtnl_dump_ifinfo);
rtnl_register(PF_UNSPEC, RTM_SETLINK, rtnl_setlink, NULL);
+ rtnl_register(PF_UNSPEC, RTM_NEWLINK, rtnl_newlink, NULL);
+ rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL);
rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all);
rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all);
@@ -960,6 +1325,7 @@ void __init rtnetlink_init(void)
EXPORT_SYMBOL(__rta_fill);
EXPORT_SYMBOL(rtattr_strlcpy);
EXPORT_SYMBOL(rtattr_parse);
+EXPORT_SYMBOL(__rtattr_parse_nested_compat);
EXPORT_SYMBOL(rtnetlink_put_metrics);
EXPORT_SYMBOL(rtnl_lock);
EXPORT_SYMBOL(rtnl_trylock);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 7c6a34e21ee..0583e8498f1 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -415,9 +415,11 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
C(csum);
C(local_df);
n->cloned = 1;
+ n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
n->nohdr = 0;
C(pkt_type);
C(ip_summed);
+ skb_copy_queue_mapping(n, skb);
C(priority);
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
C(ipvs_property);
@@ -426,6 +428,10 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
n->destructor = NULL;
C(mark);
__nf_copy(n, skb);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+ C(nf_trace);
+#endif
#ifdef CONFIG_NET_SCHED
C(tc_index);
#ifdef CONFIG_NET_CLS_ACT
@@ -434,8 +440,8 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
C(iif);
#endif
- skb_copy_secmark(n, skb);
#endif
+ skb_copy_secmark(n, skb);
C(truesize);
atomic_set(&n->users, 1);
C(head);
@@ -459,6 +465,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
#endif
new->sk = NULL;
new->dev = old->dev;
+ skb_copy_queue_mapping(new, old);
new->priority = old->priority;
new->protocol = old->protocol;
new->dst = dst_clone(old->dst);
@@ -482,6 +489,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->destructor = NULL;
new->mark = old->mark;
__nf_copy(new, old);
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+ new->nf_trace = old->nf_trace;
+#endif
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
new->ipvs_property = old->ipvs_property;
#endif
@@ -676,6 +687,7 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
skb->network_header += off;
skb->mac_header += off;
skb->cloned = 0;
+ skb->hdr_len = 0;
skb->nohdr = 0;
atomic_set(&skb_shinfo(skb)->dataref, 1);
return 0;
@@ -1706,6 +1718,11 @@ next_skb:
st->stepped_offset += frag->size;
}
+ if (st->frag_data) {
+ kunmap_skb_frag(st->frag_data);
+ st->frag_data = NULL;
+ }
+
if (st->cur_skb->next) {
st->cur_skb = st->cur_skb->next;
st->frag_idx = 0;
@@ -1925,6 +1942,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
tail = nskb;
nskb->dev = skb->dev;
+ skb_copy_queue_mapping(nskb, skb);
nskb->priority = skb->priority;
nskb->protocol = skb->protocol;
nskb->dst = dst_clone(skb->dst);
@@ -2206,7 +2224,6 @@ EXPORT_SYMBOL(pskb_copy);
EXPORT_SYMBOL(pskb_expand_head);
EXPORT_SYMBOL(skb_checksum);
EXPORT_SYMBOL(skb_clone);
-EXPORT_SYMBOL(skb_clone_fraglist);
EXPORT_SYMBOL(skb_copy);
EXPORT_SYMBOL(skb_copy_and_csum_bits);
EXPORT_SYMBOL(skb_copy_and_csum_dev);
diff --git a/net/core/sock.c b/net/core/sock.c
index 7e51d3a5e4f..091032a250c 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -210,7 +210,8 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
return -EDOM;
if (tv.tv_sec < 0) {
- static int warned = 0;
+ static int warned __read_mostly;
+
*timeo_p = 0;
if (warned < 10 && net_ratelimit())
warned++;
@@ -998,7 +999,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
__sk_dst_set(sk, dst);
sk->sk_route_caps = dst->dev->features;
if (sk->sk_route_caps & NETIF_F_GSO)
- sk->sk_route_caps |= NETIF_F_GSO_MASK;
+ sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE;
if (sk_can_gso(sk)) {
if (dst->header_len)
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
@@ -1851,46 +1852,15 @@ void proto_unregister(struct proto *prot)
EXPORT_SYMBOL(proto_unregister);
#ifdef CONFIG_PROC_FS
-static inline struct proto *__proto_head(void)
-{
- return list_entry(proto_list.next, struct proto, node);
-}
-
-static inline struct proto *proto_head(void)
-{
- return list_empty(&proto_list) ? NULL : __proto_head();
-}
-
-static inline struct proto *proto_next(struct proto *proto)
-{
- return proto->node.next == &proto_list ? NULL :
- list_entry(proto->node.next, struct proto, node);
-}
-
-static inline struct proto *proto_get_idx(loff_t pos)
-{
- struct proto *proto;
- loff_t i = 0;
-
- list_for_each_entry(proto, &proto_list, node)
- if (i++ == pos)
- goto out;
-
- proto = NULL;
-out:
- return proto;
-}
-
static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
{
read_lock(&proto_list_lock);
- return *pos ? proto_get_idx(*pos - 1) : SEQ_START_TOKEN;
+ return seq_list_start_head(&proto_list, *pos);
}
static void *proto_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- ++*pos;
- return v == SEQ_START_TOKEN ? proto_head() : proto_next(v);
+ return seq_list_next(v, &proto_list, pos);
}
static void proto_seq_stop(struct seq_file *seq, void *v)
@@ -1938,7 +1908,7 @@ static void proto_seq_printf(struct seq_file *seq, struct proto *proto)
static int proto_seq_show(struct seq_file *seq, void *v)
{
- if (v == SEQ_START_TOKEN)
+ if (v == &proto_list)
seq_printf(seq, "%-9s %-4s %-8s %-6s %-5s %-7s %-4s %-10s %s",
"protocol",
"size",
@@ -1950,7 +1920,7 @@ static int proto_seq_show(struct seq_file *seq, void *v)
"module",
"cl co di ac io in de sh ss gs se re sp bi br ha uh gp em\n");
else
- proto_seq_printf(seq, v);
+ proto_seq_printf(seq, list_entry(v, struct proto, node));
return 0;
}
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index f34aca041a2..6d5ea976204 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -25,6 +25,7 @@ extern int sysctl_core_destroy_delay;
extern u32 sysctl_xfrm_aevent_etime;
extern u32 sysctl_xfrm_aevent_rseqth;
extern int sysctl_xfrm_larval_drop;
+extern u32 sysctl_xfrm_acq_expires;
#endif
ctl_table core_table[] = {
@@ -127,6 +128,14 @@ ctl_table core_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec
},
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "xfrm_acq_expires",
+ .data = &sysctl_xfrm_acq_expires,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
#endif /* CONFIG_XFRM */
#endif /* CONFIG_NET */
{
diff --git a/net/core/utils.c b/net/core/utils.c
index adecfd281ae..2030bb8c2d3 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -139,16 +139,16 @@ int in4_pton(const char *src, int srclen,
while(1) {
int c;
c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
- if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM))) {
+ if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK))) {
goto out;
}
- if (c & (IN6PTON_DOT | IN6PTON_DELIM)) {
+ if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
if (w == 0)
goto out;
*d++ = w & 0xff;
w = 0;
i++;
- if (c & IN6PTON_DELIM) {
+ if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
if (i != 4)
goto out;
break;
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index ec7fa4d67f0..e91c2b9dc27 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1,8 +1,8 @@
/*
* net/dccp/ccids/ccid3.c
*
- * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
*
* An implementation of the DCCP protocol
*
@@ -49,7 +49,6 @@ static int ccid3_debug;
static struct dccp_tx_hist *ccid3_tx_hist;
static struct dccp_rx_hist *ccid3_rx_hist;
-static struct dccp_li_hist *ccid3_li_hist;
/*
* Transmitter Half-Connection Routines
@@ -194,25 +193,20 @@ static inline void ccid3_hc_tx_update_s(struct ccid3_hc_tx_sock *hctx, int len)
* The algorithm is not applicable if RTT < 4 microseconds.
*/
static inline void ccid3_hc_tx_update_win_count(struct ccid3_hc_tx_sock *hctx,
- struct timeval *now)
+ ktime_t now)
{
- suseconds_t delta;
u32 quarter_rtts;
if (unlikely(hctx->ccid3hctx_rtt < 4)) /* avoid divide-by-zero */
return;
- delta = timeval_delta(now, &hctx->ccid3hctx_t_last_win_count);
- DCCP_BUG_ON(delta < 0);
-
- quarter_rtts = (u32)delta / (hctx->ccid3hctx_rtt / 4);
+ quarter_rtts = ktime_us_delta(now, hctx->ccid3hctx_t_last_win_count);
+ quarter_rtts /= hctx->ccid3hctx_rtt / 4;
if (quarter_rtts > 0) {
- hctx->ccid3hctx_t_last_win_count = *now;
+ hctx->ccid3hctx_t_last_win_count = now;
hctx->ccid3hctx_last_win_count += min_t(u32, quarter_rtts, 5);
hctx->ccid3hctx_last_win_count &= 0xF; /* mod 16 */
-
- ccid3_pr_debug("now at %#X\n", hctx->ccid3hctx_last_win_count);
}
}
@@ -312,8 +306,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
{
struct dccp_sock *dp = dccp_sk(sk);
struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
- struct timeval now;
- suseconds_t delay;
+ ktime_t now = ktime_get_real();
+ s64 delay;
BUG_ON(hctx == NULL);
@@ -325,8 +319,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
if (unlikely(skb->len == 0))
return -EBADMSG;
- dccp_timestamp(sk, &now);
-
switch (hctx->ccid3hctx_state) {
case TFRC_SSTATE_NO_SENT:
sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
@@ -349,7 +341,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
ccid3_pr_debug("SYN RTT = %uus\n", dp->dccps_syn_rtt);
hctx->ccid3hctx_rtt = dp->dccps_syn_rtt;
hctx->ccid3hctx_x = rfc3390_initial_rate(sk);
- hctx->ccid3hctx_t_ld = now;
+ hctx->ccid3hctx_t_ld = ktime_to_timeval(now);
} else {
/* Sender does not have RTT sample: X = MSS/second */
hctx->ccid3hctx_x = dp->dccps_mss_cache;
@@ -361,7 +353,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
break;
case TFRC_SSTATE_NO_FBACK:
case TFRC_SSTATE_FBACK:
- delay = timeval_delta(&hctx->ccid3hctx_t_nom, &now);
+ delay = ktime_us_delta(hctx->ccid3hctx_t_nom, now);
ccid3_pr_debug("delay=%ld\n", (long)delay);
/*
* Scheduling of packet transmissions [RFC 3448, 4.6]
@@ -371,10 +363,10 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
* else
* // send the packet in (t_nom - t_now) milliseconds.
*/
- if (delay - (suseconds_t)hctx->ccid3hctx_delta >= 0)
- return delay / 1000L;
+ if (delay - (s64)hctx->ccid3hctx_delta >= 1000)
+ return (u32)delay / 1000L;
- ccid3_hc_tx_update_win_count(hctx, &now);
+ ccid3_hc_tx_update_win_count(hctx, now);
break;
case TFRC_SSTATE_TERM:
DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk);
@@ -387,8 +379,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
hctx->ccid3hctx_idle = 0;
/* set the nominal send time for the next following packet */
- timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi);
-
+ hctx->ccid3hctx_t_nom = ktime_add_us(hctx->ccid3hctx_t_nom,
+ hctx->ccid3hctx_t_ipi);
return 0;
}
@@ -819,154 +811,6 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
return 0;
}
-/* calculate first loss interval
- *
- * returns estimated loss interval in usecs */
-
-static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
-{
- struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
- struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
- u32 x_recv, p;
- suseconds_t rtt, delta;
- struct timeval tstamp = { 0, };
- int interval = 0;
- int win_count = 0;
- int step = 0;
- u64 fval;
-
- list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
- dccphrx_node) {
- if (dccp_rx_hist_entry_data_packet(entry)) {
- tail = entry;
-
- switch (step) {
- case 0:
- tstamp = entry->dccphrx_tstamp;
- win_count = entry->dccphrx_ccval;
- step = 1;
- break;
- case 1:
- interval = win_count - entry->dccphrx_ccval;
- if (interval < 0)
- interval += TFRC_WIN_COUNT_LIMIT;
- if (interval > 4)
- goto found;
- break;
- }
- }
- }
-
- if (unlikely(step == 0)) {
- DCCP_WARN("%s(%p), packet history has no data packets!\n",
- dccp_role(sk), sk);
- return ~0;
- }
-
- if (unlikely(interval == 0)) {
- DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
- "Defaulting to 1\n", dccp_role(sk), sk);
- interval = 1;
- }
-found:
- if (!tail) {
- DCCP_CRIT("tail is null\n");
- return ~0;
- }
-
- delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
- DCCP_BUG_ON(delta < 0);
-
- rtt = delta * 4 / interval;
- ccid3_pr_debug("%s(%p), approximated RTT to %dus\n",
- dccp_role(sk), sk, (int)rtt);
-
- /*
- * Determine the length of the first loss interval via inverse lookup.
- * Assume that X_recv can be computed by the throughput equation
- * s
- * X_recv = --------
- * R * fval
- * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
- */
- if (rtt == 0) { /* would result in divide-by-zero */
- DCCP_WARN("RTT==0\n");
- return ~0;
- }
-
- dccp_timestamp(sk, &tstamp);
- delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback);
- DCCP_BUG_ON(delta <= 0);
-
- x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
- if (x_recv == 0) { /* would also trigger divide-by-zero */
- DCCP_WARN("X_recv==0\n");
- if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
- DCCP_BUG("stored value of X_recv is zero");
- return ~0;
- }
- }
-
- fval = scaled_div(hcrx->ccid3hcrx_s, rtt);
- fval = scaled_div32(fval, x_recv);
- p = tfrc_calc_x_reverse_lookup(fval);
-
- ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
- "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
-
- if (p == 0)
- return ~0;
- else
- return 1000000 / p;
-}
-
-static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
-{
- struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
- struct dccp_li_hist_entry *head;
- u64 seq_temp;
-
- if (list_empty(&hcrx->ccid3hcrx_li_hist)) {
- if (!dccp_li_hist_interval_new(ccid3_li_hist,
- &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss))
- return;
-
- head = list_entry(hcrx->ccid3hcrx_li_hist.next,
- struct dccp_li_hist_entry, dccplih_node);
- head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk);
- } else {
- struct dccp_li_hist_entry *entry;
- struct list_head *tail;
-
- head = list_entry(hcrx->ccid3hcrx_li_hist.next,
- struct dccp_li_hist_entry, dccplih_node);
- /* FIXME win count check removed as was wrong */
- /* should make this check with receive history */
- /* and compare there as per section 10.2 of RFC4342 */
-
- /* new loss event detected */
- /* calculate last interval length */
- seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
- entry = dccp_li_hist_entry_new(ccid3_li_hist, GFP_ATOMIC);
-
- if (entry == NULL) {
- DCCP_BUG("out of memory - can not allocate entry");
- return;
- }
-
- list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist);
-
- tail = hcrx->ccid3hcrx_li_hist.prev;
- list_del(tail);
- kmem_cache_free(ccid3_li_hist->dccplih_slab, tail);
-
- /* Create the newest interval */
- entry->dccplih_seqno = seq_loss;
- entry->dccplih_interval = seq_temp;
- entry->dccplih_win_count = win_loss;
- }
-}
-
static int ccid3_hc_rx_detect_loss(struct sock *sk,
struct dccp_rx_hist_entry *packet)
{
@@ -992,8 +836,15 @@ static int ccid3_hc_rx_detect_loss(struct sock *sk,
while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno)
> TFRC_RECV_NUM_LATE_LOSS) {
loss = 1;
- ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss,
- hcrx->ccid3hcrx_ccval_nonloss);
+ dccp_li_update_li(sk,
+ &hcrx->ccid3hcrx_li_hist,
+ &hcrx->ccid3hcrx_hist,
+ &hcrx->ccid3hcrx_tstamp_last_feedback,
+ hcrx->ccid3hcrx_s,
+ hcrx->ccid3hcrx_bytes_recv,
+ hcrx->ccid3hcrx_x_recv,
+ hcrx->ccid3hcrx_seqno_nonloss,
+ hcrx->ccid3hcrx_ccval_nonloss);
tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss;
dccp_inc_seqno(&tmp_seqno);
hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno;
@@ -1152,7 +1003,7 @@ static void ccid3_hc_rx_exit(struct sock *sk)
dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
/* Empty loss interval history */
- dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist);
+ dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
}
static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
@@ -1236,19 +1087,12 @@ static __init int ccid3_module_init(void)
if (ccid3_tx_hist == NULL)
goto out_free_rx;
- ccid3_li_hist = dccp_li_hist_new("ccid3");
- if (ccid3_li_hist == NULL)
- goto out_free_tx;
-
rc = ccid_register(&ccid3);
if (rc != 0)
- goto out_free_loss_interval_history;
+ goto out_free_tx;
out:
return rc;
-out_free_loss_interval_history:
- dccp_li_hist_delete(ccid3_li_hist);
- ccid3_li_hist = NULL;
out_free_tx:
dccp_tx_hist_delete(ccid3_tx_hist);
ccid3_tx_hist = NULL;
@@ -1271,10 +1115,6 @@ static __exit void ccid3_module_exit(void)
dccp_rx_hist_delete(ccid3_rx_hist);
ccid3_rx_hist = NULL;
}
- if (ccid3_li_hist != NULL) {
- dccp_li_hist_delete(ccid3_li_hist);
- ccid3_li_hist = NULL;
- }
}
module_exit(ccid3_module_exit);
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 8d31b389c19..51d4b804e33 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -36,6 +36,7 @@
#ifndef _DCCP_CCID3_H_
#define _DCCP_CCID3_H_
+#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/time.h>
#include <linux/types.h>
@@ -108,10 +109,10 @@ struct ccid3_hc_tx_sock {
enum ccid3_hc_tx_states ccid3hctx_state:8;
u8 ccid3hctx_last_win_count;
u8 ccid3hctx_idle;
- struct timeval ccid3hctx_t_last_win_count;
+ ktime_t ccid3hctx_t_last_win_count;
struct timer_list ccid3hctx_no_feedback_timer;
struct timeval ccid3hctx_t_ld;
- struct timeval ccid3hctx_t_nom;
+ ktime_t ccid3hctx_t_nom;
u32 ccid3hctx_delta;
struct list_head ccid3hctx_hist;
struct ccid3_options_received ccid3hctx_options_received;
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 372d7e75cdd..515225f3a46 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -1,8 +1,8 @@
/*
* net/dccp/ccids/lib/loss_interval.c
*
- * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* This program is free software; you can redistribute it and/or modify
@@ -15,58 +15,38 @@
#include <net/sock.h>
#include "../../dccp.h"
#include "loss_interval.h"
+#include "packet_history.h"
+#include "tfrc.h"
-struct dccp_li_hist *dccp_li_hist_new(const char *name)
-{
- struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
- static const char dccp_li_hist_mask[] = "li_hist_%s";
- char *slab_name;
-
- if (hist == NULL)
- goto out;
-
- slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1,
- GFP_ATOMIC);
- if (slab_name == NULL)
- goto out_free_hist;
-
- sprintf(slab_name, dccp_li_hist_mask, name);
- hist->dccplih_slab = kmem_cache_create(slab_name,
- sizeof(struct dccp_li_hist_entry),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (hist->dccplih_slab == NULL)
- goto out_free_slab_name;
-out:
- return hist;
-out_free_slab_name:
- kfree(slab_name);
-out_free_hist:
- kfree(hist);
- hist = NULL;
- goto out;
-}
+#define DCCP_LI_HIST_IVAL_F_LENGTH 8
-EXPORT_SYMBOL_GPL(dccp_li_hist_new);
+struct dccp_li_hist_entry {
+ struct list_head dccplih_node;
+ u64 dccplih_seqno:48,
+ dccplih_win_count:4;
+ u32 dccplih_interval;
+};
-void dccp_li_hist_delete(struct dccp_li_hist *hist)
-{
- const char* name = kmem_cache_name(hist->dccplih_slab);
+static struct kmem_cache *dccp_li_cachep __read_mostly;
- kmem_cache_destroy(hist->dccplih_slab);
- kfree(name);
- kfree(hist);
+static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
+{
+ return kmem_cache_alloc(dccp_li_cachep, prio);
}
-EXPORT_SYMBOL_GPL(dccp_li_hist_delete);
+static inline void dccp_li_hist_entry_delete(struct dccp_li_hist_entry *entry)
+{
+ if (entry != NULL)
+ kmem_cache_free(dccp_li_cachep, entry);
+}
-void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list)
+void dccp_li_hist_purge(struct list_head *list)
{
struct dccp_li_hist_entry *entry, *next;
list_for_each_entry_safe(entry, next, list, dccplih_node) {
list_del_init(&entry->dccplih_node);
- kmem_cache_free(hist->dccplih_slab, entry);
+ kmem_cache_free(dccp_li_cachep, entry);
}
}
@@ -118,16 +98,16 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list)
EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
-int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
- struct list_head *list, const u64 seq_loss, const u8 win_loss)
+static int dccp_li_hist_interval_new(struct list_head *list,
+ const u64 seq_loss, const u8 win_loss)
{
struct dccp_li_hist_entry *entry;
int i;
for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
- entry = dccp_li_hist_entry_new(hist, GFP_ATOMIC);
+ entry = dccp_li_hist_entry_new(GFP_ATOMIC);
if (entry == NULL) {
- dccp_li_hist_purge(hist, list);
+ dccp_li_hist_purge(list);
DCCP_BUG("loss interval list entry is NULL");
return 0;
}
@@ -140,4 +120,176 @@ int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
return 1;
}
-EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
+/* calculate first loss interval
+ *
+ * returns estimated loss interval in usecs */
+static u32 dccp_li_calc_first_li(struct sock *sk,
+ struct list_head *hist_list,
+ struct timeval *last_feedback,
+ u16 s, u32 bytes_recv,
+ u32 previous_x_recv)
+{
+ struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
+ u32 x_recv, p;
+ suseconds_t rtt, delta;
+ struct timeval tstamp = { 0, 0 };
+ int interval = 0;
+ int win_count = 0;
+ int step = 0;
+ u64 fval;
+
+ list_for_each_entry_safe(entry, next, hist_list, dccphrx_node) {
+ if (dccp_rx_hist_entry_data_packet(entry)) {
+ tail = entry;
+
+ switch (step) {
+ case 0:
+ tstamp = entry->dccphrx_tstamp;
+ win_count = entry->dccphrx_ccval;
+ step = 1;
+ break;
+ case 1:
+ interval = win_count - entry->dccphrx_ccval;
+ if (interval < 0)
+ interval += TFRC_WIN_COUNT_LIMIT;
+ if (interval > 4)
+ goto found;
+ break;
+ }
+ }
+ }
+
+ if (unlikely(step == 0)) {
+ DCCP_WARN("%s(%p), packet history has no data packets!\n",
+ dccp_role(sk), sk);
+ return ~0;
+ }
+
+ if (unlikely(interval == 0)) {
+ DCCP_WARN("%s(%p), Could not find a win_count interval > 0."
+ "Defaulting to 1\n", dccp_role(sk), sk);
+ interval = 1;
+ }
+found:
+ if (!tail) {
+ DCCP_CRIT("tail is null\n");
+ return ~0;
+ }
+
+ delta = timeval_delta(&tstamp, &tail->dccphrx_tstamp);
+ DCCP_BUG_ON(delta < 0);
+
+ rtt = delta * 4 / interval;
+ dccp_pr_debug("%s(%p), approximated RTT to %dus\n",
+ dccp_role(sk), sk, (int)rtt);
+
+ /*
+ * Determine the length of the first loss interval via inverse lookup.
+ * Assume that X_recv can be computed by the throughput equation
+ * s
+ * X_recv = --------
+ * R * fval
+ * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1].
+ */
+ if (rtt == 0) { /* would result in divide-by-zero */
+ DCCP_WARN("RTT==0\n");
+ return ~0;
+ }
+
+ dccp_timestamp(sk, &tstamp);
+ delta = timeval_delta(&tstamp, last_feedback);
+ DCCP_BUG_ON(delta <= 0);
+
+ x_recv = scaled_div32(bytes_recv, delta);
+ if (x_recv == 0) { /* would also trigger divide-by-zero */
+ DCCP_WARN("X_recv==0\n");
+ if (previous_x_recv == 0) {
+ DCCP_BUG("stored value of X_recv is zero");
+ return ~0;
+ }
+ x_recv = previous_x_recv;
+ }
+
+ fval = scaled_div(s, rtt);
+ fval = scaled_div32(fval, x_recv);
+ p = tfrc_calc_x_reverse_lookup(fval);
+
+ dccp_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
+ "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
+
+ if (p == 0)
+ return ~0;
+ else
+ return 1000000 / p;
+}
+
+void dccp_li_update_li(struct sock *sk,
+ struct list_head *li_hist_list,
+ struct list_head *hist_list,
+ struct timeval *last_feedback, u16 s, u32 bytes_recv,
+ u32 previous_x_recv, u64 seq_loss, u8 win_loss)
+{
+ struct dccp_li_hist_entry *head;
+ u64 seq_temp;
+
+ if (list_empty(li_hist_list)) {
+ if (!dccp_li_hist_interval_new(li_hist_list, seq_loss,
+ win_loss))
+ return;
+
+ head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
+ dccplih_node);
+ head->dccplih_interval = dccp_li_calc_first_li(sk, hist_list,
+ last_feedback,
+ s, bytes_recv,
+ previous_x_recv);
+ } else {
+ struct dccp_li_hist_entry *entry;
+ struct list_head *tail;
+
+ head = list_entry(li_hist_list->next, struct dccp_li_hist_entry,
+ dccplih_node);
+ /* FIXME win count check removed as was wrong */
+ /* should make this check with receive history */
+ /* and compare there as per section 10.2 of RFC4342 */
+
+ /* new loss event detected */
+ /* calculate last interval length */
+ seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss);
+ entry = dccp_li_hist_entry_new(GFP_ATOMIC);
+
+ if (entry == NULL) {
+ DCCP_BUG("out of memory - can not allocate entry");
+ return;
+ }
+
+ list_add(&entry->dccplih_node, li_hist_list);
+
+ tail = li_hist_list->prev;
+ list_del(tail);
+ kmem_cache_free(dccp_li_cachep, tail);
+
+ /* Create the newest interval */
+ entry->dccplih_seqno = seq_loss;
+ entry->dccplih_interval = seq_temp;
+ entry->dccplih_win_count = win_loss;
+ }
+}
+
+EXPORT_SYMBOL_GPL(dccp_li_update_li);
+
+static __init int dccp_li_init(void)
+{
+ dccp_li_cachep = kmem_cache_create("dccp_li_hist",
+ sizeof(struct dccp_li_hist_entry),
+ 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+ return dccp_li_cachep == NULL ? -ENOBUFS : 0;
+}
+
+static __exit void dccp_li_exit(void)
+{
+ kmem_cache_destroy(dccp_li_cachep);
+}
+
+module_init(dccp_li_init);
+module_exit(dccp_li_exit);
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index eb257014dd7..906c806d6d9 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -3,8 +3,8 @@
/*
* net/dccp/ccids/lib/loss_interval.h
*
- * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
- * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
+ * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
+ * Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
* Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,44 +14,16 @@
*/
#include <linux/list.h>
-#include <linux/slab.h>
#include <linux/time.h>
-#define DCCP_LI_HIST_IVAL_F_LENGTH 8
-
-struct dccp_li_hist {
- struct kmem_cache *dccplih_slab;
-};
-
-extern struct dccp_li_hist *dccp_li_hist_new(const char *name);
-extern void dccp_li_hist_delete(struct dccp_li_hist *hist);
-
-struct dccp_li_hist_entry {
- struct list_head dccplih_node;
- u64 dccplih_seqno:48,
- dccplih_win_count:4;
- u32 dccplih_interval;
-};
-
-static inline struct dccp_li_hist_entry *
- dccp_li_hist_entry_new(struct dccp_li_hist *hist,
- const gfp_t prio)
-{
- return kmem_cache_alloc(hist->dccplih_slab, prio);
-}
-
-static inline void dccp_li_hist_entry_delete(struct dccp_li_hist *hist,
- struct dccp_li_hist_entry *entry)
-{
- if (entry != NULL)
- kmem_cache_free(hist->dccplih_slab, entry);
-}
-
-extern void dccp_li_hist_purge(struct dccp_li_hist *hist,
- struct list_head *list);
+extern void dccp_li_hist_purge(struct list_head *list);
extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
-extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
- struct list_head *list, const u64 seq_loss, const u8 win_loss);
+extern void dccp_li_update_li(struct sock *sk,
+ struct list_head *li_hist_list,
+ struct list_head *hist_list,
+ struct timeval *last_feedback, u16 s,
+ u32 bytes_recv, u32 previous_x_recv,
+ u64 seq_loss, u8 win_loss);
#endif /* _DCCP_LI_HIST_ */
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index d8ad27bfe01..e2d74cd7eee 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -184,7 +184,7 @@ DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics);
/*
* Checksumming routines
*/
-static inline int dccp_csum_coverage(const struct sk_buff *skb)
+static inline unsigned int dccp_csum_coverage(const struct sk_buff *skb)
{
const struct dccp_hdr* dh = dccp_hdr(skb);
@@ -195,7 +195,7 @@ static inline int dccp_csum_coverage(const struct sk_buff *skb)
static inline void dccp_csum_outgoing(struct sk_buff *skb)
{
- int cov = dccp_csum_coverage(skb);
+ unsigned int cov = dccp_csum_coverage(skb);
if (cov >= skb->len)
dccp_hdr(skb)->dccph_cscov = 0;
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 31737cdf156..b158c661867 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -253,17 +253,6 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
if (dst == NULL) {
opt = np->opt;
- if (opt == NULL &&
- np->rxopt.bits.osrcrt == 2 &&
- ireq6->pktopts) {
- struct sk_buff *pktopts = ireq6->pktopts;
- struct inet6_skb_parm *rxopt = IP6CB(pktopts);
-
- if (rxopt->srcrt)
- opt = ipv6_invert_rthdr(sk,
- (struct ipv6_rt_hdr *)(skb_network_header(pktopts) +
- rxopt->srcrt));
- }
if (opt != NULL && opt->srcrt != NULL) {
const struct rt0_hdr *rt0 = (struct rt0_hdr *)opt->srcrt;
@@ -570,15 +559,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
if (sk_acceptq_is_full(sk))
goto out_overflow;
- if (np->rxopt.bits.osrcrt == 2 && opt == NULL && ireq6->pktopts) {
- const struct inet6_skb_parm *rxopt = IP6CB(ireq6->pktopts);
-
- if (rxopt->srcrt)
- opt = ipv6_invert_rthdr(sk,
- (struct ipv6_rt_hdr *)(skb_network_header(ireq6->pktopts) +
- rxopt->srcrt));
- }
-
if (dst == NULL) {
struct in6_addr *final_p = NULL, final;
struct flowi fl;
diff --git a/net/dccp/probe.c b/net/dccp/probe.c
index 1f5e3ba6206..43a3adb027e 100644
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -128,7 +128,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf,
int error = 0, cnt = 0;
unsigned char *tbuf;
- if (!buf || len < 0)
+ if (!buf)
return -EINVAL;
if (len == 0)
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index bfa910b6ad2..ed76d4aab4a 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -2304,7 +2304,7 @@ static int dn_socket_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations dn_socket_seq_ops = {
+static const struct seq_operations dn_socket_seq_ops = {
.start = dn_socket_seq_start,
.next = dn_socket_seq_next,
.stop = dn_socket_seq_stop,
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 764a56a13e3..fa6604fcf0e 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -461,7 +461,6 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) {
dn_dn2eth(mac_addr, ifa->ifa_local);
dev_mc_add(dev, mac_addr, ETH_ALEN, 0);
- dev_mc_upload(dev);
}
}
@@ -638,7 +637,7 @@ static struct dn_dev *dn_dev_by_index(int ifindex)
return dn_dev;
}
-static struct nla_policy dn_ifa_policy[IFA_MAX+1] __read_mostly = {
+static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
[IFA_ADDRESS] = { .type = NLA_U16 },
[IFA_LOCAL] = { .type = NLA_U16 },
[IFA_LABEL] = { .type = NLA_STRING,
@@ -1064,8 +1063,6 @@ static int dn_eth_up(struct net_device *dev)
else
dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);
- dev_mc_upload(dev);
-
dn_db->use_long = 1;
return 0;
@@ -1419,7 +1416,7 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations dn_dev_seq_ops = {
+static const struct seq_operations dn_dev_seq_ops = {
.start = dn_dev_seq_start,
.next = dn_dev_seq_next,
.stop = dn_dev_seq_stop,
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 4bf066c416e..174d8a7a6da 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -569,7 +569,7 @@ static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
NEIGH_SEQ_NEIGH_ONLY);
}
-static struct seq_operations dn_neigh_seq_ops = {
+static const struct seq_operations dn_neigh_seq_ops = {
.start = dn_neigh_seq_start,
.next = neigh_seq_next,
.stop = neigh_seq_stop,
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index a8bf106b7a6..82622fb6f68 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1726,7 +1726,7 @@ static int dn_rt_cache_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations dn_rt_cache_seq_ops = {
+static const struct seq_operations dn_rt_cache_seq_ops = {
.start = dn_rt_cache_seq_start,
.next = dn_rt_cache_seq_next,
.stop = dn_rt_cache_seq_stop,
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 17a1932216d..84ff3dd3707 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -108,7 +108,7 @@ errout:
return err;
}
-static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy dn_fib_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY,
};
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 0ac2524f3b6..12c765715ac 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -266,8 +266,11 @@ void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev,
static int eth_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
+
if (netif_running(dev))
return -EBUSY;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
return 0;
}
@@ -316,9 +319,10 @@ void ether_setup(struct net_device *dev)
EXPORT_SYMBOL(ether_setup);
/**
- * alloc_etherdev - Allocates and sets up an Ethernet device
+ * alloc_etherdev_mq - Allocates and sets up an Ethernet device
* @sizeof_priv: Size of additional driver-private structure to be allocated
* for this Ethernet device
+ * @queue_count: The number of queues this device has.
*
* Fill in the fields of the device structure with Ethernet-generic
* values. Basically does everything except registering the device.
@@ -328,8 +332,8 @@ EXPORT_SYMBOL(ether_setup);
* this private data area.
*/
-struct net_device *alloc_etherdev(int sizeof_priv)
+struct net_device *alloc_etherdev_mq(int sizeof_priv, unsigned int queue_count)
{
- return alloc_netdev(sizeof_priv, "eth%d", ether_setup);
+ return alloc_netdev_mq(sizeof_priv, "eth%d", ether_setup, queue_count);
}
-EXPORT_SYMBOL(alloc_etherdev);
+EXPORT_SYMBOL(alloc_etherdev_mq);
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index c308756c2f9..6398e6e6749 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -456,18 +456,13 @@ void
ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac,
struct ieee80211softmac_network *add_net)
{
- struct list_head *list_ptr;
- struct ieee80211softmac_network *softmac_net = NULL;
+ struct ieee80211softmac_network *softmac_net;
- list_for_each(list_ptr, &mac->network_list) {
- softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+ list_for_each_entry(softmac_net, &mac->network_list, list) {
if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN))
- break;
- else
- softmac_net = NULL;
+ return;
}
- if(softmac_net == NULL)
- list_add(&(add_net->list), &mac->network_list);
+ list_add(&(add_net->list), &mac->network_list);
}
/* Add a network to the list, with locking */
@@ -506,16 +501,13 @@ struct ieee80211softmac_network *
ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac,
u8 *bssid)
{
- struct list_head *list_ptr;
- struct ieee80211softmac_network *softmac_net = NULL;
- list_for_each(list_ptr, &mac->network_list) {
- softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+ struct ieee80211softmac_network *softmac_net;
+
+ list_for_each_entry(softmac_net, &mac->network_list, list) {
if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN))
- break;
- else
- softmac_net = NULL;
+ return softmac_net;
}
- return softmac_net;
+ return NULL;
}
/* Get a network from the list by BSSID with locking */
@@ -537,11 +529,9 @@ struct ieee80211softmac_network *
ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac,
struct ieee80211softmac_essid *essid)
{
- struct list_head *list_ptr;
- struct ieee80211softmac_network *softmac_net = NULL;
+ struct ieee80211softmac_network *softmac_net;
- list_for_each(list_ptr, &mac->network_list) {
- softmac_net = list_entry(list_ptr, struct ieee80211softmac_network, list);
+ list_for_each_entry(softmac_net, &mac->network_list, list) {
if (softmac_net->essid.len == essid->len &&
!memcmp(softmac_net->essid.data, essid->data, essid->len))
return softmac_net;
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 010fbb2d45e..fb790977425 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -116,48 +116,6 @@ config IP_ROUTE_MULTIPATH
equal "cost" and chooses one of them in a non-deterministic fashion
if a matching packet arrives.
-config IP_ROUTE_MULTIPATH_CACHED
- bool "IP: equal cost multipath with caching support (EXPERIMENTAL)"
- depends on IP_ROUTE_MULTIPATH
- help
- Normally, equal cost multipath routing is not supported by the
- routing cache. If you say Y here, alternative routes are cached
- and on cache lookup a route is chosen in a configurable fashion.
-
- If unsure, say N.
-
-config IP_ROUTE_MULTIPATH_RR
- tristate "MULTIPATH: round robin algorithm"
- depends on IP_ROUTE_MULTIPATH_CACHED
- help
- Multipath routes are chosen according to Round Robin
-
-config IP_ROUTE_MULTIPATH_RANDOM
- tristate "MULTIPATH: random algorithm"
- depends on IP_ROUTE_MULTIPATH_CACHED
- help
- Multipath routes are chosen in a random fashion. Actually,
- there is no weight for a route. The advantage of this policy
- is that it is implemented stateless and therefore introduces only
- a very small delay.
-
-config IP_ROUTE_MULTIPATH_WRANDOM
- tristate "MULTIPATH: weighted random algorithm"
- depends on IP_ROUTE_MULTIPATH_CACHED
- help
- Multipath routes are chosen in a weighted random fashion.
- The per route weights are the weights visible via ip route 2. As the
- corresponding state management introduces some overhead routing delay
- is increased.
-
-config IP_ROUTE_MULTIPATH_DRR
- tristate "MULTIPATH: interface round robin algorithm"
- depends on IP_ROUTE_MULTIPATH_CACHED
- help
- Connections are distributed in a round robin fashion over the
- available interfaces. This policy makes sense if the connections
- should be primarily distributed on interfaces and not on routes.
-
config IP_ROUTE_VERBOSE
bool "IP: verbose route monitoring"
depends on IP_ADVANCED_ROUTER
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 4ff6c151d7f..fbf1674e0c2 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -29,14 +29,9 @@ obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/
obj-$(CONFIG_IP_VS) += ipvs/
obj-$(CONFIG_INET_DIAG) += inet_diag.o
-obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 041fba3fa0a..06c08e5740f 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1170,6 +1170,9 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
int ihl;
int id;
+ if (!(features & NETIF_F_V4_CSUM))
+ features &= ~NETIF_F_SG;
+
if (unlikely(skb_shinfo(skb)->gso_type &
~(SKB_GSO_TCPV4 |
SKB_GSO_UDP |
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 6da8ff597ad..7a23e59c374 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -339,3 +339,4 @@ static void __exit ah4_fini(void)
module_init(ah4_init);
module_exit(ah4_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_AH);
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 7110779a024..9ab9d534fba 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -877,7 +877,7 @@ static int arp_process(struct sk_buff *skb)
n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
- if (ipv4_devconf.arp_accept) {
+ if (IPV4_DEVCONF_ALL(ARP_ACCEPT)) {
/* Unsolicited ARP is not accepted by default.
It is possible, that this option should be enabled for some
devices (strip is candidate)
@@ -885,7 +885,7 @@ static int arp_process(struct sk_buff *skb)
if (n == NULL &&
arp->ar_op == htons(ARPOP_REPLY) &&
inet_addr_type(sip) == RTN_UNICAST)
- n = __neigh_lookup(&arp_tbl, &sip, dev, -1);
+ n = __neigh_lookup(&arp_tbl, &sip, dev, 1);
}
if (n) {
@@ -987,11 +987,11 @@ static int arp_req_set(struct arpreq *r, struct net_device * dev)
return 0;
}
if (dev == NULL) {
- ipv4_devconf.proxy_arp = 1;
+ IPV4_DEVCONF_ALL(PROXY_ARP) = 1;
return 0;
}
if (__in_dev_get_rtnl(dev)) {
- __in_dev_get_rtnl(dev)->cnf.proxy_arp = 1;
+ IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 1);
return 0;
}
return -ENXIO;
@@ -1093,11 +1093,12 @@ static int arp_req_delete(struct arpreq *r, struct net_device * dev)
return pneigh_delete(&arp_tbl, &ip, dev);
if (mask == 0) {
if (dev == NULL) {
- ipv4_devconf.proxy_arp = 0;
+ IPV4_DEVCONF_ALL(PROXY_ARP) = 0;
return 0;
}
if (__in_dev_get_rtnl(dev)) {
- __in_dev_get_rtnl(dev)->cnf.proxy_arp = 0;
+ IN_DEV_CONF_SET(__in_dev_get_rtnl(dev),
+ PROXY_ARP, 0);
return 0;
}
return -ENXIO;
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 86a2b52aad3..ab56a052ce3 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -45,6 +45,7 @@
#include <net/cipso_ipv4.h>
#include <asm/atomic.h>
#include <asm/bug.h>
+#include <asm/unaligned.h>
struct cipso_v4_domhsh_entry {
char *domain;
@@ -1000,7 +1001,7 @@ static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def,
return -EFAULT;
for (iter = 0; iter < enumcat_len; iter += 2) {
- cat = ntohs(*((__be16 *)&enumcat[iter]));
+ cat = ntohs(get_unaligned((__be16 *)&enumcat[iter]));
if (cat <= cat_prev)
return -EFAULT;
cat_prev = cat;
@@ -1068,8 +1069,8 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
for (iter = 0; iter < net_cat_len; iter += 2) {
ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
- ntohs(*((__be16 *)&net_cat[iter])),
- GFP_ATOMIC);
+ ntohs(get_unaligned((__be16 *)&net_cat[iter])),
+ GFP_ATOMIC);
if (ret_val != 0)
return ret_val;
}
@@ -1102,9 +1103,10 @@ static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def,
return -EFAULT;
for (iter = 0; iter < rngcat_len; iter += 4) {
- cat_high = ntohs(*((__be16 *)&rngcat[iter]));
+ cat_high = ntohs(get_unaligned((__be16 *)&rngcat[iter]));
if ((iter + 4) <= rngcat_len)
- cat_low = ntohs(*((__be16 *)&rngcat[iter + 2]));
+ cat_low = ntohs(
+ get_unaligned((__be16 *)&rngcat[iter + 2]));
else
cat_low = 0;
@@ -1201,9 +1203,10 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
u16 cat_high;
for (net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
- cat_high = ntohs(*((__be16 *)&net_cat[net_iter]));
+ cat_high = ntohs(get_unaligned((__be16 *)&net_cat[net_iter]));
if ((net_iter + 4) <= net_cat_len)
- cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2]));
+ cat_low = ntohs(
+ get_unaligned((__be16 *)&net_cat[net_iter + 2]));
else
cat_low = 0;
@@ -1565,7 +1568,7 @@ int cipso_v4_validate(unsigned char **option)
}
rcu_read_lock();
- doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2])));
+ doi_def = cipso_v4_doi_search(ntohl(get_unaligned((__be32 *)&opt[2])));
if (doi_def == NULL) {
err_offset = 2;
goto validate_return_locked;
@@ -1709,22 +1712,22 @@ void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway)
}
/**
- * cipso_v4_socket_setattr - Add a CIPSO option to a socket
- * @sock: the socket
+ * cipso_v4_sock_setattr - Add a CIPSO option to a socket
+ * @sk: the socket
* @doi_def: the CIPSO DOI to use
* @secattr: the specific security attributes of the socket
*
* Description:
* Set the CIPSO option on the given socket using the DOI definition and
* security attributes passed to the function. This function requires
- * exclusive access to @sock->sk, which means it either needs to be in the
- * process of being created or locked via lock_sock(sock->sk). Returns zero on
- * success and negative values on failure.
+ * exclusive access to @sk, which means it either needs to be in the
+ * process of being created or locked. Returns zero on success and negative
+ * values on failure.
*
*/
-int cipso_v4_socket_setattr(const struct socket *sock,
- const struct cipso_v4_doi *doi_def,
- const struct netlbl_lsm_secattr *secattr)
+int cipso_v4_sock_setattr(struct sock *sk,
+ const struct cipso_v4_doi *doi_def,
+ const struct netlbl_lsm_secattr *secattr)
{
int ret_val = -EPERM;
u32 iter;
@@ -1732,7 +1735,6 @@ int cipso_v4_socket_setattr(const struct socket *sock,
u32 buf_len = 0;
u32 opt_len;
struct ip_options *opt = NULL;
- struct sock *sk;
struct inet_sock *sk_inet;
struct inet_connection_sock *sk_conn;
@@ -1740,7 +1742,6 @@ int cipso_v4_socket_setattr(const struct socket *sock,
* defined yet but it is not a problem as the only users of these
* "lite" PF_INET sockets are functions which do an accept() call
* afterwards so we will label the socket as part of the accept(). */
- sk = sock->sk;
if (sk == NULL)
return 0;
@@ -1858,7 +1859,7 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
if (ret_val == 0)
return ret_val;
- doi = ntohl(*(__be32 *)&cipso_ptr[2]);
+ doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2]));
rcu_read_lock();
doi_def = cipso_v4_doi_search(doi);
if (doi_def == NULL) {
@@ -1892,29 +1893,6 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
}
/**
- * cipso_v4_socket_getattr - Get the security attributes from a socket
- * @sock: the socket
- * @secattr: the security attributes
- *
- * Description:
- * Query @sock to see if there is a CIPSO option attached to the socket and if
- * there is return the CIPSO security attributes in @secattr. Returns zero on
- * success and negative values on failure.
- *
- */
-int cipso_v4_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
-{
- int ret_val;
-
- lock_sock(sock->sk);
- ret_val = cipso_v4_sock_getattr(sock->sk, secattr);
- release_sock(sock->sk);
-
- return ret_val;
-}
-
-/**
* cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
* @skb: the packet
* @secattr: the security attributes
@@ -1936,7 +1914,7 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
return 0;
- doi = ntohl(*(__be32 *)&cipso_ptr[2]);
+ doi = ntohl(get_unaligned((__be32 *)&cipso_ptr[2]));
rcu_read_lock();
doi_def = cipso_v4_doi_search(doi);
if (doi_def == NULL)
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index dd02a45d0f6..0301dd468cf 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -50,8 +50,12 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
RT_CONN_FLAGS(sk), oif,
sk->sk_protocol,
inet->sport, usin->sin_port, sk, 1);
- if (err)
+ if (err) {
+ if (err == -ENETUNREACH)
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
return err;
+ }
+
if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
ip_rt_put(rt);
return -EACCES;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7f95e6e9bee..abf6352f990 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -64,21 +64,27 @@
#include <net/rtnetlink.h>
struct ipv4_devconf ipv4_devconf = {
- .accept_redirects = 1,
- .send_redirects = 1,
- .secure_redirects = 1,
- .shared_media = 1,
+ .data = {
+ [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
+ },
};
static struct ipv4_devconf ipv4_devconf_dflt = {
- .accept_redirects = 1,
- .send_redirects = 1,
- .secure_redirects = 1,
- .shared_media = 1,
- .accept_source_route = 1,
+ .data = {
+ [NET_IPV4_CONF_ACCEPT_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SEND_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SECURE_REDIRECTS - 1] = 1,
+ [NET_IPV4_CONF_SHARED_MEDIA - 1] = 1,
+ [NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE - 1] = 1,
+ },
};
-static struct nla_policy ifa_ipv4_policy[IFA_MAX+1] __read_mostly = {
+#define IPV4_DEVCONF_DFLT(attr) IPV4_DEVCONF(ipv4_devconf_dflt, attr)
+
+static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
[IFA_LOCAL] = { .type = NLA_U32 },
[IFA_ADDRESS] = { .type = NLA_U32 },
[IFA_BROADCAST] = { .type = NLA_U32 },
@@ -141,7 +147,7 @@ void in_dev_finish_destroy(struct in_device *idev)
}
}
-struct in_device *inetdev_init(struct net_device *dev)
+static struct in_device *inetdev_init(struct net_device *dev)
{
struct in_device *in_dev;
@@ -321,12 +327,8 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
}
}
- if (destroy) {
+ if (destroy)
inet_free_ifa(ifa1);
-
- if (!in_dev->ifa_list)
- inetdev_destroy(in_dev);
- }
}
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
@@ -399,12 +401,10 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
ASSERT_RTNL();
if (!in_dev) {
- in_dev = inetdev_init(dev);
- if (!in_dev) {
- inet_free_ifa(ifa);
- return -ENOBUFS;
- }
+ inet_free_ifa(ifa);
+ return -ENOBUFS;
}
+ ipv4_devconf_setall(in_dev);
if (ifa->ifa_dev != in_dev) {
BUG_TRAP(!ifa->ifa_dev);
in_dev_hold(in_dev);
@@ -514,13 +514,12 @@ static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)
in_dev = __in_dev_get_rtnl(dev);
if (in_dev == NULL) {
- in_dev = inetdev_init(dev);
- if (in_dev == NULL) {
- err = -ENOBUFS;
- goto errout;
- }
+ err = -ENOBUFS;
+ goto errout;
}
+ ipv4_devconf_setall(in_dev);
+
ifa = inet_alloc_ifa();
if (ifa == NULL) {
/*
@@ -1057,11 +1056,12 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
if (!in_dev) {
if (event == NETDEV_REGISTER) {
in_dev = inetdev_init(dev);
- if (!in_dev)
- panic("devinet: Failed to create loopback\n");
if (dev == &loopback_dev) {
- in_dev->cnf.no_xfrm = 1;
- in_dev->cnf.no_policy = 1;
+ if (!in_dev)
+ panic("devinet: "
+ "Failed to create loopback\n");
+ IN_DEV_CONF_SET(in_dev, NOXFRM, 1);
+ IN_DEV_CONF_SET(in_dev, NOPOLICY, 1);
}
}
goto out;
@@ -1237,13 +1237,98 @@ errout:
#ifdef CONFIG_SYSCTL
+static void devinet_copy_dflt_conf(int i)
+{
+ struct net_device *dev;
+
+ read_lock(&dev_base_lock);
+ for_each_netdev(dev) {
+ struct in_device *in_dev;
+ rcu_read_lock();
+ in_dev = __in_dev_get_rcu(dev);
+ if (in_dev && !test_bit(i, in_dev->cnf.state))
+ in_dev->cnf.data[i] = ipv4_devconf_dflt.data[i];
+ rcu_read_unlock();
+ }
+ read_unlock(&dev_base_lock);
+}
+
+static int devinet_conf_proc(ctl_table *ctl, int write,
+ struct file* filp, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+
+ if (write) {
+ struct ipv4_devconf *cnf = ctl->extra1;
+ int i = (int *)ctl->data - cnf->data;
+
+ set_bit(i, cnf->state);
+
+ if (cnf == &ipv4_devconf_dflt)
+ devinet_copy_dflt_conf(i);
+ }
+
+ return ret;
+}
+
+static int devinet_conf_sysctl(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
+{
+ struct ipv4_devconf *cnf;
+ int *valp = table->data;
+ int new;
+ int i;
+
+ if (!newval || !newlen)
+ return 0;
+
+ if (newlen != sizeof(int))
+ return -EINVAL;
+
+ if (get_user(new, (int __user *)newval))
+ return -EFAULT;
+
+ if (new == *valp)
+ return 0;
+
+ if (oldval && oldlenp) {
+ size_t len;
+
+ if (get_user(len, oldlenp))
+ return -EFAULT;
+
+ if (len) {
+ if (len > table->maxlen)
+ len = table->maxlen;
+ if (copy_to_user(oldval, valp, len))
+ return -EFAULT;
+ if (put_user(len, oldlenp))
+ return -EFAULT;
+ }
+ }
+
+ *valp = new;
+
+ cnf = table->extra1;
+ i = (int *)table->data - cnf->data;
+
+ set_bit(i, cnf->state);
+
+ if (cnf == &ipv4_devconf_dflt)
+ devinet_copy_dflt_conf(i);
+
+ return 1;
+}
+
void inet_forward_change(void)
{
struct net_device *dev;
- int on = ipv4_devconf.forwarding;
+ int on = IPV4_DEVCONF_ALL(FORWARDING);
- ipv4_devconf.accept_redirects = !on;
- ipv4_devconf_dflt.forwarding = on;
+ IPV4_DEVCONF_ALL(ACCEPT_REDIRECTS) = !on;
+ IPV4_DEVCONF_DFLT(FORWARDING) = on;
read_lock(&dev_base_lock);
for_each_netdev(dev) {
@@ -1251,7 +1336,7 @@ void inet_forward_change(void)
rcu_read_lock();
in_dev = __in_dev_get_rcu(dev);
if (in_dev)
- in_dev->cnf.forwarding = on;
+ IN_DEV_CONF_SET(in_dev, FORWARDING, on);
rcu_read_unlock();
}
read_unlock(&dev_base_lock);
@@ -1268,9 +1353,9 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
if (write && *valp != val) {
- if (valp == &ipv4_devconf.forwarding)
+ if (valp == &IPV4_DEVCONF_ALL(FORWARDING))
inet_forward_change();
- else if (valp != &ipv4_devconf_dflt.forwarding)
+ else if (valp != &IPV4_DEVCONF_DFLT(FORWARDING))
rt_cache_flush(0);
}
@@ -1295,42 +1380,43 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
void __user *oldval, size_t __user *oldlenp,
void __user *newval, size_t newlen)
{
- int *valp = table->data;
- int new;
+ int ret = devinet_conf_sysctl(table, name, nlen, oldval, oldlenp,
+ newval, newlen);
- if (!newval || !newlen)
- return 0;
+ if (ret == 1)
+ rt_cache_flush(0);
- if (newlen != sizeof(int))
- return -EINVAL;
+ return ret;
+}
- if (get_user(new, (int __user *)newval))
- return -EFAULT;
- if (new == *valp)
- return 0;
+#define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc, sysctl) \
+ { \
+ .ctl_name = NET_IPV4_CONF_ ## attr, \
+ .procname = name, \
+ .data = ipv4_devconf.data + \
+ NET_IPV4_CONF_ ## attr - 1, \
+ .maxlen = sizeof(int), \
+ .mode = mval, \
+ .proc_handler = proc, \
+ .strategy = sysctl, \
+ .extra1 = &ipv4_devconf, \
+ }
- if (oldval && oldlenp) {
- size_t len;
+#define DEVINET_SYSCTL_RW_ENTRY(attr, name) \
+ DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc, \
+ devinet_conf_sysctl)
- if (get_user(len, oldlenp))
- return -EFAULT;
+#define DEVINET_SYSCTL_RO_ENTRY(attr, name) \
+ DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc, \
+ devinet_conf_sysctl)
- if (len) {
- if (len > table->maxlen)
- len = table->maxlen;
- if (copy_to_user(oldval, valp, len))
- return -EFAULT;
- if (put_user(len, oldlenp))
- return -EFAULT;
- }
- }
-
- *valp = new;
- rt_cache_flush(0);
- return 1;
-}
+#define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc, sysctl) \
+ DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc, sysctl)
+#define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \
+ DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush, \
+ ipv4_doint_and_flush_strategy)
static struct devinet_sysctl_table {
struct ctl_table_header *sysctl_header;
@@ -1341,178 +1427,34 @@ static struct devinet_sysctl_table {
ctl_table devinet_root_dir[2];
} devinet_sysctl = {
.devinet_vars = {
- {
- .ctl_name = NET_IPV4_CONF_FORWARDING,
- .procname = "forwarding",
- .data = &ipv4_devconf.forwarding,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &devinet_sysctl_forward,
- },
- {
- .ctl_name = NET_IPV4_CONF_MC_FORWARDING,
- .procname = "mc_forwarding",
- .data = &ipv4_devconf.mc_forwarding,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ACCEPT_REDIRECTS,
- .procname = "accept_redirects",
- .data = &ipv4_devconf.accept_redirects,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_SECURE_REDIRECTS,
- .procname = "secure_redirects",
- .data = &ipv4_devconf.secure_redirects,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_SHARED_MEDIA,
- .procname = "shared_media",
- .data = &ipv4_devconf.shared_media,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_RP_FILTER,
- .procname = "rp_filter",
- .data = &ipv4_devconf.rp_filter,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_SEND_REDIRECTS,
- .procname = "send_redirects",
- .data = &ipv4_devconf.send_redirects,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE,
- .procname = "accept_source_route",
- .data = &ipv4_devconf.accept_source_route,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_PROXY_ARP,
- .procname = "proxy_arp",
- .data = &ipv4_devconf.proxy_arp,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_MEDIUM_ID,
- .procname = "medium_id",
- .data = &ipv4_devconf.medium_id,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_BOOTP_RELAY,
- .procname = "bootp_relay",
- .data = &ipv4_devconf.bootp_relay,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_LOG_MARTIANS,
- .procname = "log_martians",
- .data = &ipv4_devconf.log_martians,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_TAG,
- .procname = "tag",
- .data = &ipv4_devconf.tag,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ARPFILTER,
- .procname = "arp_filter",
- .data = &ipv4_devconf.arp_filter,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ARP_ANNOUNCE,
- .procname = "arp_announce",
- .data = &ipv4_devconf.arp_announce,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ARP_IGNORE,
- .procname = "arp_ignore",
- .data = &ipv4_devconf.arp_ignore,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_ARP_ACCEPT,
- .procname = "arp_accept",
- .data = &ipv4_devconf.arp_accept,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_IPV4_CONF_NOXFRM,
- .procname = "disable_xfrm",
- .data = &ipv4_devconf.no_xfrm,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &ipv4_doint_and_flush,
- .strategy = &ipv4_doint_and_flush_strategy,
- },
- {
- .ctl_name = NET_IPV4_CONF_NOPOLICY,
- .procname = "disable_policy",
- .data = &ipv4_devconf.no_policy,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &ipv4_doint_and_flush,
- .strategy = &ipv4_doint_and_flush_strategy,
- },
- {
- .ctl_name = NET_IPV4_CONF_FORCE_IGMP_VERSION,
- .procname = "force_igmp_version",
- .data = &ipv4_devconf.force_igmp_version,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &ipv4_doint_and_flush,
- .strategy = &ipv4_doint_and_flush_strategy,
- },
- {
- .ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES,
- .procname = "promote_secondaries",
- .data = &ipv4_devconf.promote_secondaries,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &ipv4_doint_and_flush,
- .strategy = &ipv4_doint_and_flush_strategy,
- },
+ DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding",
+ devinet_sysctl_forward,
+ devinet_conf_sysctl),
+ DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"),
+
+ DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"),
+ DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
+ DEVINET_SYSCTL_RW_ENTRY(SHARED_MEDIA, "shared_media"),
+ DEVINET_SYSCTL_RW_ENTRY(RP_FILTER, "rp_filter"),
+ DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"),
+ DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE,
+ "accept_source_route"),
+ DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"),
+ DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"),
+ DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"),
+ DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
+ DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
+ DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
+ DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
+ DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
+ DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
+
+ DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"),
+ DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"),
+ DEVINET_SYSCTL_FLUSHING_ENTRY(FORCE_IGMP_VERSION,
+ "force_igmp_version"),
+ DEVINET_SYSCTL_FLUSHING_ENTRY(PROMOTE_SECONDARIES,
+ "promote_secondaries"),
},
.devinet_dev = {
{
@@ -1561,6 +1503,7 @@ static void devinet_sysctl_register(struct in_device *in_dev,
return;
for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
+ t->devinet_vars[i].extra1 = p;
}
if (dev) {
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 47c95e8ef04..98767a4f118 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -481,3 +481,4 @@ static void __exit esp4_fini(void)
module_init(esp4_init);
module_exit(esp4_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_ESP);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 837f2957fa8..2eb909be804 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -250,8 +250,6 @@ e_inval:
return -EINVAL;
}
-#ifndef CONFIG_IP_NOSIOCRT
-
static inline __be32 sk_extract_addr(struct sockaddr *addr)
{
return ((struct sockaddr_in *) addr)->sin_addr.s_addr;
@@ -443,16 +441,7 @@ int ip_rt_ioctl(unsigned int cmd, void __user *arg)
return -EINVAL;
}
-#else
-
-int ip_rt_ioctl(unsigned int cmd, void *arg)
-{
- return -EINVAL;
-}
-
-#endif
-
-struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = {
+const struct nla_policy rtm_ipv4_policy[RTA_MAX+1] = {
[RTA_DST] = { .type = NLA_U32 },
[RTA_SRC] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 },
@@ -464,7 +453,6 @@ struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = {
[RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
[RTA_PROTOINFO] = { .type = NLA_U32 },
[RTA_FLOW] = { .type = NLA_U32 },
- [RTA_MP_ALGO] = { .type = NLA_U32 },
};
static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -526,9 +514,6 @@ static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh,
case RTA_FLOW:
cfg->fc_flow = nla_get_u32(attr);
break;
- case RTA_MP_ALGO:
- cfg->fc_mp_alg = nla_get_u32(attr);
- break;
case RTA_TABLE:
cfg->fc_table = nla_get_u32(attr);
break;
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 33083ad52e9..2a947840210 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -169,7 +169,7 @@ static struct fib_table *fib_empty_table(void)
return NULL;
}
-static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY,
[FRA_FLOW] = { .type = NLA_U32 },
};
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index bb94550d95c..c434119deb5 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -42,7 +42,6 @@
#include <net/tcp.h>
#include <net/sock.h>
#include <net/ip_fib.h>
-#include <net/ip_mp_alg.h>
#include <net/netlink.h>
#include <net/nexthop.h>
@@ -697,13 +696,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
goto err_inval;
}
#endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- if (cfg->fc_mp_alg) {
- if (cfg->fc_mp_alg < IP_MP_ALG_NONE ||
- cfg->fc_mp_alg > IP_MP_ALG_MAX)
- goto err_inval;
- }
-#endif
err = -ENOBUFS;
if (fib_info_cnt >= fib_hash_size) {
@@ -791,10 +783,6 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
#endif
}
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- fi->fib_mp_alg = cfg->fc_mp_alg;
-#endif
-
if (fib_props[cfg->fc_type].error) {
if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
goto err_inval;
@@ -940,10 +928,6 @@ out_fill_res:
res->type = fa->fa_type;
res->scope = fa->fa_scope;
res->fi = fa->fa_info;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- res->netmask = mask;
- res->network = zone & inet_make_mask(prefixlen);
-#endif
atomic_inc(&res->fi->fib_clntref);
return 0;
}
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index e238b17f554..02a899bec19 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -514,12 +514,15 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
saddr = iph->daddr;
if (!(rt->rt_flags & RTCF_LOCAL)) {
- /* This is broken, skb_in->dev points to the outgoing device
- * after the packet passes through ip_output().
- */
- if (skb_in->dev && sysctl_icmp_errors_use_inbound_ifaddr)
- saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK);
- else
+ struct net_device *dev = NULL;
+
+ if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr)
+ dev = dev_get_by_index(rt->fl.iif);
+
+ if (dev) {
+ saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK);
+ dev_put(dev);
+ } else
saddr = 0;
}
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index f4dd4745310..a646409c2d0 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -128,14 +128,16 @@
* contradict to specs provided this delay is small enough.
*/
-#define IGMP_V1_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 1 || \
- (in_dev)->cnf.force_igmp_version == 1 || \
- ((in_dev)->mr_v1_seen && \
- time_before(jiffies, (in_dev)->mr_v1_seen)))
-#define IGMP_V2_SEEN(in_dev) (ipv4_devconf.force_igmp_version == 2 || \
- (in_dev)->cnf.force_igmp_version == 2 || \
- ((in_dev)->mr_v2_seen && \
- time_before(jiffies, (in_dev)->mr_v2_seen)))
+#define IGMP_V1_SEEN(in_dev) \
+ (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 1 || \
+ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
+ ((in_dev)->mr_v1_seen && \
+ time_before(jiffies, (in_dev)->mr_v1_seen)))
+#define IGMP_V2_SEEN(in_dev) \
+ (IPV4_DEVCONF_ALL(FORCE_IGMP_VERSION) == 2 || \
+ IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 2 || \
+ ((in_dev)->mr_v2_seen && \
+ time_before(jiffies, (in_dev)->mr_v2_seen)))
static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 43fb1600f1f..fbe7714f21d 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -31,10 +31,8 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg);
/*
* This array holds the first and last local port number.
- * For high-usage systems, use sysctl to change this to
- * 32768-61000
*/
-int sysctl_local_port_range[2] = { 1024, 4999 };
+int sysctl_local_port_range[2] = { 32768, 61000 };
int inet_csk_bind_conflict(const struct sock *sk,
const struct inet_bind_bucket *tb)
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index a73cf93cee3..2586df09b9b 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -14,7 +14,8 @@
#include <net/ip.h>
/* Must be called with locally disabled BHs. */
-void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashinfo)
+static void __inet_twsk_kill(struct inet_timewait_sock *tw,
+ struct inet_hashinfo *hashinfo)
{
struct inet_bind_hashbucket *bhead;
struct inet_bind_bucket *tb;
@@ -47,8 +48,6 @@ void __inet_twsk_kill(struct inet_timewait_sock *tw, struct inet_hashinfo *hashi
inet_twsk_put(tw);
}
-EXPORT_SYMBOL_GPL(__inet_twsk_kill);
-
/*
* Enter the time wait state. This is called with locally disabled BH.
* Essentially we whip up a timewait bucket, copy the relevant info into it
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 63282934725..5c14ed63e56 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -809,7 +809,8 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen;
- if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+ if (skb_headroom(skb) < max_headroom || skb_shared(skb)||
+ (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
if (!new_skb) {
ip_rt_put(rt);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index d6427d91851..c9e2b5e6305 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -399,6 +399,10 @@ static void ip_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)
+ to->nf_trace = from->nf_trace;
+#endif
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
to->ipvs_property = from->ipvs_property;
#endif
@@ -837,7 +841,7 @@ int ip_append_data(struct sock *sk,
*/
if (transhdrlen &&
length + fragheaderlen <= mtu &&
- rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
+ rt->u.dst.dev->features & NETIF_F_V4_CSUM &&
!exthdrlen)
csummode = CHECKSUM_PARTIAL;
@@ -1352,7 +1356,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
}
{
- struct flowi fl = { .nl_u = { .ip4_u =
+ struct flowi fl = { .oif = arg->bound_dev_if,
+ .nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = rt->rt_spec_dst,
.tos = RT_TOS(ip_hdr(skb)->tos) } },
@@ -1376,6 +1381,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
inet->tos = ip_hdr(skb)->tos;
sk->sk_priority = skb->priority;
sk->sk_protocol = ip_hdr(skb)->protocol;
+ sk->sk_bound_dev_if = arg->bound_dev_if;
ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0,
&ipc, rt, MSG_DONTWAIT);
if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index ab86137c71d..e787044a851 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -485,3 +485,4 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) - RFC3173");
MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_COMP);
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index ebd2f2d532f..396437242a1 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -595,7 +595,8 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
*/
max_headroom = (LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr));
- if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+ if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+ (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
if (!new_skb) {
ip_rt_put(rt);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 0ebae413ae8..d96582acdf6 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -152,9 +152,11 @@ struct net_device *ipmr_new_tunnel(struct vifctl *v)
dev->flags |= IFF_MULTICAST;
in_dev = __in_dev_get_rtnl(dev);
- if (in_dev == NULL && (in_dev = inetdev_init(dev)) == NULL)
+ if (in_dev == NULL)
goto failure;
- in_dev->cnf.rp_filter = 0;
+
+ ipv4_devconf_setall(in_dev);
+ IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
if (dev_open(dev))
goto failure;
@@ -218,10 +220,15 @@ static struct net_device *ipmr_reg_vif(void)
}
dev->iflink = 0;
- if ((in_dev = inetdev_init(dev)) == NULL)
+ rcu_read_lock();
+ if ((in_dev = __in_dev_get_rcu(dev)) == NULL) {
+ rcu_read_unlock();
goto failure;
+ }
- in_dev->cnf.rp_filter = 0;
+ ipv4_devconf_setall(in_dev);
+ IPV4_DEVCONF(in_dev->cnf, RP_FILTER) = 0;
+ rcu_read_unlock();
if (dev_open(dev))
goto failure;
@@ -281,7 +288,7 @@ static int vif_delete(int vifi)
dev_set_allmulti(dev, -1);
if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) {
- in_dev->cnf.mc_forwarding--;
+ IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
ip_rt_multicast_event(in_dev);
}
@@ -426,7 +433,7 @@ static int vif_add(struct vifctl *vifc, int mrtsock)
if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
return -EADDRNOTAVAIL;
- in_dev->cnf.mc_forwarding++;
+ IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
dev_set_allmulti(dev, +1);
ip_rt_multicast_event(in_dev);
@@ -841,7 +848,7 @@ static void mrtsock_destruct(struct sock *sk)
{
rtnl_lock();
if (sk == mroute_socket) {
- ipv4_devconf.mc_forwarding--;
+ IPV4_DEVCONF_ALL(MC_FORWARDING)--;
write_lock_bh(&mrt_lock);
mroute_socket=NULL;
@@ -890,7 +897,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char __user *optval,int opt
mroute_socket=sk;
write_unlock_bh(&mrt_lock);
- ipv4_devconf.mc_forwarding++;
+ IPV4_DEVCONF_ALL(MC_FORWARDING)++;
}
rtnl_unlock();
return ret;
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index 15ad5dd2d98..8d6901d4e94 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -549,7 +549,7 @@ static int ip_vs_app_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ip_vs_app_seq_ops = {
+static const struct seq_operations ip_vs_app_seq_ops = {
.start = ip_vs_app_seq_start,
.next = ip_vs_app_seq_next,
.stop = ip_vs_app_seq_stop,
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c
index 7018f97c75d..3b446b1a6b9 100644
--- a/net/ipv4/ipvs/ip_vs_conn.c
+++ b/net/ipv4/ipvs/ip_vs_conn.c
@@ -745,7 +745,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ip_vs_conn_seq_ops = {
+static const struct seq_operations ip_vs_conn_seq_ops = {
.start = ip_vs_conn_seq_start,
.next = ip_vs_conn_seq_next,
.stop = ip_vs_conn_seq_stop,
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 68fe1d4d021..e1052bcf4ed 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -1783,7 +1783,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ip_vs_info_seq_ops = {
+static const struct seq_operations ip_vs_info_seq_ops = {
.start = ip_vs_info_seq_start,
.next = ip_vs_info_seq_next,
.stop = ip_vs_info_seq_stop,
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 7ea2d981a93..356f067484e 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -67,6 +67,11 @@ struct ip_vs_sync_conn_options {
struct ip_vs_seq out_seq; /* outgoing seq. struct */
};
+struct ip_vs_sync_thread_data {
+ struct completion *startup;
+ int state;
+};
+
#define IP_VS_SYNC_CONN_TIMEOUT (3*60*HZ)
#define SIMPLE_CONN_SIZE (sizeof(struct ip_vs_sync_conn))
#define FULL_CONN_SIZE \
@@ -751,6 +756,7 @@ static int sync_thread(void *startup)
mm_segment_t oldmm;
int state;
const char *name;
+ struct ip_vs_sync_thread_data *tinfo = startup;
/* increase the module use count */
ip_vs_use_count_inc();
@@ -789,7 +795,14 @@ static int sync_thread(void *startup)
add_wait_queue(&sync_wait, &wait);
set_sync_pid(state, current->pid);
- complete((struct completion *)startup);
+ complete(tinfo->startup);
+
+ /*
+ * once we call the completion queue above, we should
+ * null out that reference, since its allocated on the
+ * stack of the creating kernel thread
+ */
+ tinfo->startup = NULL;
/* processing master/backup loop here */
if (state == IP_VS_STATE_MASTER)
@@ -801,6 +814,14 @@ static int sync_thread(void *startup)
remove_wait_queue(&sync_wait, &wait);
/* thread exits */
+
+ /*
+ * If we weren't explicitly stopped, then we
+ * exited in error, and should undo our state
+ */
+ if ((!stop_master_sync) && (!stop_backup_sync))
+ ip_vs_sync_state -= tinfo->state;
+
set_sync_pid(state, 0);
IP_VS_INFO("sync thread stopped!\n");
@@ -812,6 +833,11 @@ static int sync_thread(void *startup)
set_stop_sync(state, 0);
wake_up(&stop_sync_wait);
+ /*
+ * we need to free the structure that was allocated
+ * for us in start_sync_thread
+ */
+ kfree(tinfo);
return 0;
}
@@ -838,11 +864,19 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
{
DECLARE_COMPLETION_ONSTACK(startup);
pid_t pid;
+ struct ip_vs_sync_thread_data *tinfo;
if ((state == IP_VS_STATE_MASTER && sync_master_pid) ||
(state == IP_VS_STATE_BACKUP && sync_backup_pid))
return -EEXIST;
+ /*
+ * Note that tinfo will be freed in sync_thread on exit
+ */
+ tinfo = kmalloc(sizeof(struct ip_vs_sync_thread_data), GFP_KERNEL);
+ if (!tinfo)
+ return -ENOMEM;
+
IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %Zd bytes\n",
sizeof(struct ip_vs_sync_conn));
@@ -858,8 +892,11 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
ip_vs_backup_syncid = syncid;
}
+ tinfo->state = state;
+ tinfo->startup = &startup;
+
repeat:
- if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
+ if ((pid = kernel_thread(fork_sync_thread, tinfo, 0)) < 0) {
IP_VS_ERR("could not create fork_sync_thread due to %d... "
"retrying.\n", pid);
msleep_interruptible(1000);
diff --git a/net/ipv4/multipath.c b/net/ipv4/multipath.c
deleted file mode 100644
index 4e9ca7c7640..00000000000
--- a/net/ipv4/multipath.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* multipath.c: IPV4 multipath algorithm support.
- *
- * Copyright (C) 2004, 2005 Einar Lueck <elueck@de.ibm.com>
- * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-
-#include <net/ip_mp_alg.h>
-
-static DEFINE_SPINLOCK(alg_table_lock);
-struct ip_mp_alg_ops *ip_mp_alg_table[IP_MP_ALG_MAX + 1];
-
-int multipath_alg_register(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
-{
- struct ip_mp_alg_ops **slot;
- int err;
-
- if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX ||
- !ops->mp_alg_select_route)
- return -EINVAL;
-
- spin_lock(&alg_table_lock);
- slot = &ip_mp_alg_table[n];
- if (*slot != NULL) {
- err = -EBUSY;
- } else {
- *slot = ops;
- err = 0;
- }
- spin_unlock(&alg_table_lock);
-
- return err;
-}
-EXPORT_SYMBOL(multipath_alg_register);
-
-void multipath_alg_unregister(struct ip_mp_alg_ops *ops, enum ip_mp_alg n)
-{
- struct ip_mp_alg_ops **slot;
-
- if (n < IP_MP_ALG_NONE || n > IP_MP_ALG_MAX)
- return;
-
- spin_lock(&alg_table_lock);
- slot = &ip_mp_alg_table[n];
- if (*slot == ops)
- *slot = NULL;
- spin_unlock(&alg_table_lock);
-
- synchronize_net();
-}
-EXPORT_SYMBOL(multipath_alg_unregister);
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c
deleted file mode 100644
index b03c5ca2c82..00000000000
--- a/net/ipv4/multipath_drr.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Device round robin policy for multipath.
- *
- *
- * Version: $Id: multipath_drr.c,v 1.1.2.1 2004/09/16 07:42:34 elueck Exp $
- *
- * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-struct multipath_device {
- int ifi; /* interface index of device */
- atomic_t usecount;
- int allocated;
-};
-
-#define MULTIPATH_MAX_DEVICECANDIDATES 10
-
-static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES];
-static DEFINE_SPINLOCK(state_lock);
-
-static int inline __multipath_findslot(void)
-{
- int i;
-
- for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
- if (state[i].allocated == 0)
- return i;
- }
- return -1;
-}
-
-static int inline __multipath_finddev(int ifindex)
-{
- int i;
-
- for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++) {
- if (state[i].allocated != 0 &&
- state[i].ifi == ifindex)
- return i;
- }
- return -1;
-}
-
-static int drr_dev_event(struct notifier_block *this,
- unsigned long event, void *ptr)
-{
- struct net_device *dev = ptr;
- int devidx;
-
- switch (event) {
- case NETDEV_UNREGISTER:
- case NETDEV_DOWN:
- spin_lock_bh(&state_lock);
-
- devidx = __multipath_finddev(dev->ifindex);
- if (devidx != -1) {
- state[devidx].allocated = 0;
- state[devidx].ifi = 0;
- atomic_set(&state[devidx].usecount, 0);
- }
-
- spin_unlock_bh(&state_lock);
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block drr_dev_notifier = {
- .notifier_call = drr_dev_event,
-};
-
-
-static void drr_safe_inc(atomic_t *usecount)
-{
- int n;
-
- atomic_inc(usecount);
-
- n = atomic_read(usecount);
- if (n <= 0) {
- int i;
-
- spin_lock_bh(&state_lock);
-
- for (i = 0; i < MULTIPATH_MAX_DEVICECANDIDATES; i++)
- atomic_set(&state[i].usecount, 0);
-
- spin_unlock_bh(&state_lock);
- }
-}
-
-static void drr_select_route(const struct flowi *flp,
- struct rtable *first, struct rtable **rp)
-{
- struct rtable *nh, *result, *cur_min;
- int min_usecount = -1;
- int devidx = -1;
- int cur_min_devidx = -1;
-
- /* 1. make sure all alt. nexthops have the same GC related data */
- /* 2. determine the new candidate to be returned */
- result = NULL;
- cur_min = NULL;
- for (nh = rcu_dereference(first); nh;
- nh = rcu_dereference(nh->u.dst.rt_next)) {
- if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
- multipath_comparekeys(&nh->fl, flp)) {
- int nh_ifidx = nh->u.dst.dev->ifindex;
-
- nh->u.dst.lastuse = jiffies;
- nh->u.dst.__use++;
- if (result != NULL)
- continue;
-
- /* search for the output interface */
-
- /* this is not SMP safe, only add/remove are
- * SMP safe as wrong usecount updates have no big
- * impact
- */
- devidx = __multipath_finddev(nh_ifidx);
- if (devidx == -1) {
- /* add the interface to the array
- * SMP safe
- */
- spin_lock_bh(&state_lock);
-
- /* due to SMP: search again */
- devidx = __multipath_finddev(nh_ifidx);
- if (devidx == -1) {
- /* add entry for device */
- devidx = __multipath_findslot();
- if (devidx == -1) {
- /* unlikely but possible */
- continue;
- }
-
- state[devidx].allocated = 1;
- state[devidx].ifi = nh_ifidx;
- atomic_set(&state[devidx].usecount, 0);
- min_usecount = 0;
- }
-
- spin_unlock_bh(&state_lock);
- }
-
- if (min_usecount == 0) {
- /* if the device has not been used it is
- * the primary target
- */
- drr_safe_inc(&state[devidx].usecount);
- result = nh;
- } else {
- int count =
- atomic_read(&state[devidx].usecount);
-
- if (min_usecount == -1 ||
- count < min_usecount) {
- cur_min = nh;
- cur_min_devidx = devidx;
- min_usecount = count;
- }
- }
- }
- }
-
- if (!result) {
- if (cur_min) {
- drr_safe_inc(&state[cur_min_devidx].usecount);
- result = cur_min;
- } else {
- result = first;
- }
- }
-
- *rp = result;
-}
-
-static struct ip_mp_alg_ops drr_ops = {
- .mp_alg_select_route = drr_select_route,
-};
-
-static int __init drr_init(void)
-{
- int err = register_netdevice_notifier(&drr_dev_notifier);
-
- if (err)
- return err;
-
- err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR);
- if (err)
- goto fail;
-
- return 0;
-
-fail:
- unregister_netdevice_notifier(&drr_dev_notifier);
- return err;
-}
-
-static void __exit drr_exit(void)
-{
- unregister_netdevice_notifier(&drr_dev_notifier);
- multipath_alg_unregister(&drr_ops, IP_MP_ALG_DRR);
-}
-
-module_init(drr_init);
-module_exit(drr_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c
deleted file mode 100644
index c312785d14d..00000000000
--- a/net/ipv4/multipath_random.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Random policy for multipath.
- *
- *
- * Version: $Id: multipath_random.c,v 1.1.2.3 2004/09/21 08:42:11 elueck Exp $
- *
- * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-#define MULTIPATH_MAX_CANDIDATES 40
-
-static void random_select_route(const struct flowi *flp,
- struct rtable *first,
- struct rtable **rp)
-{
- struct rtable *rt;
- struct rtable *decision;
- unsigned char candidate_count = 0;
-
- /* count all candidate */
- for (rt = rcu_dereference(first); rt;
- rt = rcu_dereference(rt->u.dst.rt_next)) {
- if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
- multipath_comparekeys(&rt->fl, flp))
- ++candidate_count;
- }
-
- /* choose a random candidate */
- decision = first;
- if (candidate_count > 1) {
- unsigned char i = 0;
- unsigned char candidate_no = (unsigned char)
- (random32() % candidate_count);
-
- /* find chosen candidate and adjust GC data for all candidates
- * to ensure they stay in cache
- */
- for (rt = first; rt; rt = rt->u.dst.rt_next) {
- if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
- multipath_comparekeys(&rt->fl, flp)) {
- rt->u.dst.lastuse = jiffies;
-
- if (i == candidate_no)
- decision = rt;
-
- if (i >= candidate_count)
- break;
-
- i++;
- }
- }
- }
-
- decision->u.dst.__use++;
- *rp = decision;
-}
-
-static struct ip_mp_alg_ops random_ops = {
- .mp_alg_select_route = random_select_route,
-};
-
-static int __init random_init(void)
-{
- return multipath_alg_register(&random_ops, IP_MP_ALG_RANDOM);
-}
-
-static void __exit random_exit(void)
-{
- multipath_alg_unregister(&random_ops, IP_MP_ALG_RANDOM);
-}
-
-module_init(random_init);
-module_exit(random_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c
deleted file mode 100644
index 0ad22524f45..00000000000
--- a/net/ipv4/multipath_rr.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Round robin policy for multipath.
- *
- *
- * Version: $Id: multipath_rr.c,v 1.1.2.2 2004/09/16 07:42:34 elueck Exp $
- *
- * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_mp_alg.h>
-
-static void rr_select_route(const struct flowi *flp,
- struct rtable *first, struct rtable **rp)
-{
- struct rtable *nh, *result, *min_use_cand = NULL;
- int min_use = -1;
-
- /* 1. make sure all alt. nexthops have the same GC related data
- * 2. determine the new candidate to be returned
- */
- result = NULL;
- for (nh = rcu_dereference(first); nh;
- nh = rcu_dereference(nh->u.dst.rt_next)) {
- if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
- multipath_comparekeys(&nh->fl, flp)) {
- nh->u.dst.lastuse = jiffies;
-
- if (min_use == -1 || nh->u.dst.__use < min_use) {
- min_use = nh->u.dst.__use;
- min_use_cand = nh;
- }
- }
- }
- result = min_use_cand;
- if (!result)
- result = first;
-
- result->u.dst.__use++;
- *rp = result;
-}
-
-static struct ip_mp_alg_ops rr_ops = {
- .mp_alg_select_route = rr_select_route,
-};
-
-static int __init rr_init(void)
-{
- return multipath_alg_register(&rr_ops, IP_MP_ALG_RR);
-}
-
-static void __exit rr_exit(void)
-{
- multipath_alg_unregister(&rr_ops, IP_MP_ALG_RR);
-}
-
-module_init(rr_init);
-module_exit(rr_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
deleted file mode 100644
index 57c50369453..00000000000
--- a/net/ipv4/multipath_wrandom.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Weighted random policy for multipath.
- *
- *
- * Version: $Id: multipath_wrandom.c,v 1.1.2.3 2004/09/22 07:51:40 elueck Exp $
- *
- * Authors: Einar Lueck <elueck@de.ibm.com><lkml@einar-lueck.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/igmp.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/mroute.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/icmp.h>
-#include <net/udp.h>
-#include <net/raw.h>
-#include <linux/notifier.h>
-#include <linux/if_arp.h>
-#include <linux/netfilter_ipv4.h>
-#include <net/ipip.h>
-#include <net/checksum.h>
-#include <net/ip_fib.h>
-#include <net/ip_mp_alg.h>
-
-#define MULTIPATH_STATE_SIZE 15
-
-struct multipath_candidate {
- struct multipath_candidate *next;
- int power;
- struct rtable *rt;
-};
-
-struct multipath_dest {
- struct list_head list;
-
- const struct fib_nh *nh_info;
- __be32 netmask;
- __be32 network;
- unsigned char prefixlen;
-
- struct rcu_head rcu;
-};
-
-struct multipath_bucket {
- struct list_head head;
- spinlock_t lock;
-};
-
-struct multipath_route {
- struct list_head list;
-
- int oif;
- __be32 gw;
- struct list_head dests;
-
- struct rcu_head rcu;
-};
-
-/* state: primarily weight per route information */
-static struct multipath_bucket state[MULTIPATH_STATE_SIZE];
-
-static unsigned char __multipath_lookup_weight(const struct flowi *fl,
- const struct rtable *rt)
-{
- const int state_idx = rt->idev->dev->ifindex % MULTIPATH_STATE_SIZE;
- struct multipath_route *r;
- struct multipath_route *target_route = NULL;
- struct multipath_dest *d;
- int weight = 1;
-
- /* lookup the weight information for a certain route */
- rcu_read_lock();
-
- /* find state entry for gateway or add one if necessary */
- list_for_each_entry_rcu(r, &state[state_idx].head, list) {
- if (r->gw == rt->rt_gateway &&
- r->oif == rt->idev->dev->ifindex) {
- target_route = r;
- break;
- }
- }
-
- if (!target_route) {
- /* this should not happen... but we are prepared */
- printk( KERN_CRIT"%s: missing state for gateway: %u and " \
- "device %d\n", __FUNCTION__, rt->rt_gateway,
- rt->idev->dev->ifindex);
- goto out;
- }
-
- /* find state entry for destination */
- list_for_each_entry_rcu(d, &target_route->dests, list) {
- __be32 targetnetwork = fl->fl4_dst &
- inet_make_mask(d->prefixlen);
-
- if ((targetnetwork & d->netmask) == d->network) {
- weight = d->nh_info->nh_weight;
- goto out;
- }
- }
-
-out:
- rcu_read_unlock();
- return weight;
-}
-
-static void wrandom_init_state(void)
-{
- int i;
-
- for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
- INIT_LIST_HEAD(&state[i].head);
- spin_lock_init(&state[i].lock);
- }
-}
-
-static void wrandom_select_route(const struct flowi *flp,
- struct rtable *first,
- struct rtable **rp)
-{
- struct rtable *rt;
- struct rtable *decision;
- struct multipath_candidate *first_mpc = NULL;
- struct multipath_candidate *mpc, *last_mpc = NULL;
- int power = 0;
- int last_power;
- int selector;
- const size_t size_mpc = sizeof(struct multipath_candidate);
-
- /* collect all candidates and identify their weights */
- for (rt = rcu_dereference(first); rt;
- rt = rcu_dereference(rt->u.dst.rt_next)) {
- if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
- multipath_comparekeys(&rt->fl, flp)) {
- struct multipath_candidate* mpc =
- (struct multipath_candidate*)
- kmalloc(size_mpc, GFP_ATOMIC);
-
- if (!mpc)
- return;
-
- power += __multipath_lookup_weight(flp, rt) * 10000;
-
- mpc->power = power;
- mpc->rt = rt;
- mpc->next = NULL;
-
- if (!first_mpc)
- first_mpc = mpc;
- else
- last_mpc->next = mpc;
-
- last_mpc = mpc;
- }
- }
-
- /* choose a weighted random candidate */
- decision = first;
- selector = random32() % power;
- last_power = 0;
-
- /* select candidate, adjust GC data and cleanup local state */
- decision = first;
- last_mpc = NULL;
- for (mpc = first_mpc; mpc; mpc = mpc->next) {
- mpc->rt->u.dst.lastuse = jiffies;
- if (last_power <= selector && selector < mpc->power)
- decision = mpc->rt;
-
- last_power = mpc->power;
- kfree(last_mpc);
- last_mpc = mpc;
- }
-
- /* concurrent __multipath_flush may lead to !last_mpc */
- kfree(last_mpc);
-
- decision->u.dst.__use++;
- *rp = decision;
-}
-
-static void wrandom_set_nhinfo(__be32 network,
- __be32 netmask,
- unsigned char prefixlen,
- const struct fib_nh *nh)
-{
- const int state_idx = nh->nh_oif % MULTIPATH_STATE_SIZE;
- struct multipath_route *r, *target_route = NULL;
- struct multipath_dest *d, *target_dest = NULL;
-
- /* store the weight information for a certain route */
- spin_lock_bh(&state[state_idx].lock);
-
- /* find state entry for gateway or add one if necessary */
- list_for_each_entry_rcu(r, &state[state_idx].head, list) {
- if (r->gw == nh->nh_gw && r->oif == nh->nh_oif) {
- target_route = r;
- break;
- }
- }
-
- if (!target_route) {
- const size_t size_rt = sizeof(struct multipath_route);
- target_route = (struct multipath_route *)
- kmalloc(size_rt, GFP_ATOMIC);
-
- target_route->gw = nh->nh_gw;
- target_route->oif = nh->nh_oif;
- memset(&target_route->rcu, 0, sizeof(struct rcu_head));
- INIT_LIST_HEAD(&target_route->dests);
-
- list_add_rcu(&target_route->list, &state[state_idx].head);
- }
-
- /* find state entry for destination or add one if necessary */
- list_for_each_entry_rcu(d, &target_route->dests, list) {
- if (d->nh_info == nh) {
- target_dest = d;
- break;
- }
- }
-
- if (!target_dest) {
- const size_t size_dst = sizeof(struct multipath_dest);
- target_dest = (struct multipath_dest*)
- kmalloc(size_dst, GFP_ATOMIC);
-
- target_dest->nh_info = nh;
- target_dest->network = network;
- target_dest->netmask = netmask;
- target_dest->prefixlen = prefixlen;
- memset(&target_dest->rcu, 0, sizeof(struct rcu_head));
-
- list_add_rcu(&target_dest->list, &target_route->dests);
- }
- /* else: we already stored this info for another destination =>
- * we are finished
- */
-
- spin_unlock_bh(&state[state_idx].lock);
-}
-
-static void __multipath_free(struct rcu_head *head)
-{
- struct multipath_route *rt = container_of(head, struct multipath_route,
- rcu);
- kfree(rt);
-}
-
-static void __multipath_free_dst(struct rcu_head *head)
-{
- struct multipath_dest *dst = container_of(head,
- struct multipath_dest,
- rcu);
- kfree(dst);
-}
-
-static void wrandom_flush(void)
-{
- int i;
-
- /* defere delete to all entries */
- for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) {
- struct multipath_route *r;
-
- spin_lock_bh(&state[i].lock);
- list_for_each_entry_rcu(r, &state[i].head, list) {
- struct multipath_dest *d;
- list_for_each_entry_rcu(d, &r->dests, list) {
- list_del_rcu(&d->list);
- call_rcu(&d->rcu,
- __multipath_free_dst);
- }
- list_del_rcu(&r->list);
- call_rcu(&r->rcu,
- __multipath_free);
- }
-
- spin_unlock_bh(&state[i].lock);
- }
-}
-
-static struct ip_mp_alg_ops wrandom_ops = {
- .mp_alg_select_route = wrandom_select_route,
- .mp_alg_flush = wrandom_flush,
- .mp_alg_set_nhinfo = wrandom_set_nhinfo,
-};
-
-static int __init wrandom_init(void)
-{
- wrandom_init_state();
-
- return multipath_alg_register(&wrandom_ops, IP_MP_ALG_WRANDOM);
-}
-
-static void __exit wrandom_exit(void)
-{
- multipath_alg_unregister(&wrandom_ops, IP_MP_ALG_WRANDOM);
-}
-
-module_init(wrandom_init);
-module_exit(wrandom_exit);
-MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 46509fae9fd..fa97947c6ae 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -230,7 +230,7 @@ config IP_NF_TARGET_NETMAP
To compile it as a module, choose M here. If unsure, say N.
config IP_NF_TARGET_SAME
- tristate "SAME target support"
+ tristate "SAME target support (OBSOLETE)"
depends on NF_NAT
help
This option adds a `SAME' target, which works like the standard SNAT
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index cae41215e3c..d1149aba935 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -224,7 +224,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
static const char nulldevname[IFNAMSIZ];
unsigned int verdict = NF_DROP;
struct arphdr *arp;
- int hotdrop = 0;
+ bool hotdrop = false;
struct arpt_entry *e, *back;
const char *indev, *outdev;
void *table_base;
@@ -1140,13 +1140,13 @@ void arpt_unregister_table(struct arpt_table *table)
}
/* The built-in targets: standard (NULL) and error. */
-static struct arpt_target arpt_standard_target = {
+static struct arpt_target arpt_standard_target __read_mostly = {
.name = ARPT_STANDARD_TARGET,
.targetsize = sizeof(int),
.family = NF_ARP,
};
-static struct arpt_target arpt_error_target = {
+static struct arpt_target arpt_error_target __read_mostly = {
.name = ARPT_ERROR_TARGET,
.target = arpt_error,
.targetsize = ARPT_FUNCTION_MAXNAMELEN,
@@ -1184,7 +1184,7 @@ static int __init arp_tables_init(void)
if (ret < 0)
goto err4;
- printk("arp_tables: (C) 2002 David S. Miller\n");
+ printk(KERN_INFO "arp_tables: (C) 2002 David S. Miller\n");
return 0;
err4:
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 6298d404e7c..c4bdab47597 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -65,7 +65,7 @@ target(struct sk_buff **pskb,
return mangle->target;
}
-static int
+static bool
checkentry(const char *tablename, const void *e, const struct xt_target *target,
void *targinfo, unsigned int hook_mask)
{
@@ -73,15 +73,15 @@ checkentry(const char *tablename, const void *e, const struct xt_target *target,
if (mangle->flags & ~ARPT_MANGLE_MASK ||
!(mangle->flags & ARPT_MANGLE_MASK))
- return 0;
+ return false;
if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
mangle->target != ARPT_CONTINUE)
- return 0;
- return 1;
+ return false;
+ return true;
}
-static struct arpt_target arpt_mangle_reg = {
+static struct arpt_target arpt_mangle_reg __read_mostly = {
.name = "mangle",
.target = target,
.targetsize = sizeof(struct arpt_mangle),
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index e3f83bf160d..e1b402c6b85 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -152,20 +152,20 @@ ip_packet_match(const struct iphdr *ip,
return 1;
}
-static inline int
+static inline bool
ip_checkentry(const struct ipt_ip *ip)
{
if (ip->flags & ~IPT_F_MASK) {
duprintf("Unknown flag bits set: %08X\n",
ip->flags & ~IPT_F_MASK);
- return 0;
+ return false;
}
if (ip->invflags & ~IPT_INV_MASK) {
duprintf("Unknown invflag bits set: %08X\n",
ip->invflags & ~IPT_INV_MASK);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static unsigned int
@@ -183,19 +183,19 @@ ipt_error(struct sk_buff **pskb,
}
static inline
-int do_match(struct ipt_entry_match *m,
- const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int offset,
- int *hotdrop)
+bool do_match(struct ipt_entry_match *m,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int offset,
+ bool *hotdrop)
{
/* Stop iteration if it doesn't match */
if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
offset, ip_hdrlen(skb), hotdrop))
- return 1;
+ return true;
else
- return 0;
+ return false;
}
static inline struct ipt_entry *
@@ -204,6 +204,112 @@ get_entry(void *base, unsigned int offset)
return (struct ipt_entry *)(base + offset);
}
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ipt_ip *ip)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
+ if (((__u32 *)ip)[i])
+ return 0;
+
+ return 1;
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+static const char *hooknames[] = {
+ [NF_IP_PRE_ROUTING] = "PREROUTING",
+ [NF_IP_LOCAL_IN] = "INPUT",
+ [NF_IP_FORWARD] = "FORWARD",
+ [NF_IP_LOCAL_OUT] = "OUTPUT",
+ [NF_IP_POST_ROUTING] = "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+ NF_IP_TRACE_COMMENT_RULE,
+ NF_IP_TRACE_COMMENT_RETURN,
+ NF_IP_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+ [NF_IP_TRACE_COMMENT_RULE] = "rule",
+ [NF_IP_TRACE_COMMENT_RETURN] = "return",
+ [NF_IP_TRACE_COMMENT_POLICY] = "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+ .type = NF_LOG_TYPE_LOG,
+ .u = {
+ .log = {
+ .level = 4,
+ .logflags = NF_LOG_MASK,
+ },
+ },
+};
+
+static inline int
+get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
+ char *hookname, char **chainname,
+ char **comment, unsigned int *rulenum)
+{
+ struct ipt_standard_target *t = (void *)ipt_get_target(s);
+
+ if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
+ /* Head of user chain: ERROR target with chainname */
+ *chainname = t->target.data;
+ (*rulenum) = 0;
+ } else if (s == e) {
+ (*rulenum)++;
+
+ if (s->target_offset == sizeof(struct ipt_entry)
+ && strcmp(t->target.u.kernel.target->name,
+ IPT_STANDARD_TARGET) == 0
+ && t->verdict < 0
+ && unconditional(&s->ip)) {
+ /* Tail of chains: STANDARD target (return/policy) */
+ *comment = *chainname == hookname
+ ? (char *)comments[NF_IP_TRACE_COMMENT_POLICY]
+ : (char *)comments[NF_IP_TRACE_COMMENT_RETURN];
+ }
+ return 1;
+ } else
+ (*rulenum)++;
+
+ return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+ unsigned int hook,
+ const struct net_device *in,
+ const struct net_device *out,
+ char *tablename,
+ struct xt_table_info *private,
+ struct ipt_entry *e)
+{
+ void *table_base;
+ struct ipt_entry *root;
+ char *hookname, *chainname, *comment;
+ unsigned int rulenum = 0;
+
+ table_base = (void *)private->entries[smp_processor_id()];
+ root = get_entry(table_base, private->hook_entry[hook]);
+
+ hookname = chainname = (char *)hooknames[hook];
+ comment = (char *)comments[NF_IP_TRACE_COMMENT_RULE];
+
+ IPT_ENTRY_ITERATE(root,
+ private->size - private->hook_entry[hook],
+ get_chainname_rulenum,
+ e, hookname, &chainname, &comment, &rulenum);
+
+ nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
+ "TRACE: %s:%s:%s:%u ",
+ tablename, chainname, comment, rulenum);
+}
+#endif
+
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
ipt_do_table(struct sk_buff **pskb,
@@ -216,7 +322,7 @@ ipt_do_table(struct sk_buff **pskb,
u_int16_t offset;
struct iphdr *ip;
u_int16_t datalen;
- int hotdrop = 0;
+ bool hotdrop = false;
/* Initializing verdict to NF_DROP keeps gcc happy. */
unsigned int verdict = NF_DROP;
const char *indev, *outdev;
@@ -261,6 +367,14 @@ ipt_do_table(struct sk_buff **pskb,
t = ipt_get_target(e);
IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+ /* The packet is traced: log it */
+ if (unlikely((*pskb)->nf_trace))
+ trace_packet(*pskb, hook, in, out,
+ table->name, private, e);
+#endif
/* Standard target? */
if (!t->u.kernel.target->target) {
int v;
@@ -341,19 +455,6 @@ ipt_do_table(struct sk_buff **pskb,
#endif
}
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ipt_ip *ip)
-{
- unsigned int i;
-
- for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
- if (((__u32 *)ip)[i])
- return 0;
-
- return 1;
-}
-
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
@@ -499,7 +600,8 @@ check_entry(struct ipt_entry *e, const char *name)
}
static inline int check_match(struct ipt_entry_match *m, const char *name,
- const struct ipt_ip *ip, unsigned int hookmask)
+ const struct ipt_ip *ip, unsigned int hookmask,
+ unsigned int *i)
{
struct xt_match *match;
int ret;
@@ -515,6 +617,8 @@ static inline int check_match(struct ipt_entry_match *m, const char *name,
m->u.kernel.match->name);
ret = -EINVAL;
}
+ if (!ret)
+ (*i)++;
return ret;
}
@@ -537,11 +641,10 @@ find_check_match(struct ipt_entry_match *m,
}
m->u.kernel.match = match;
- ret = check_match(m, name, ip, hookmask);
+ ret = check_match(m, name, ip, hookmask, i);
if (ret)
goto err;
- (*i)++;
return 0;
err:
module_put(m->u.kernel.match->me);
@@ -1425,7 +1528,7 @@ out:
}
static inline int
-compat_check_calc_match(struct ipt_entry_match *m,
+compat_find_calc_match(struct ipt_entry_match *m,
const char *name,
const struct ipt_ip *ip,
unsigned int hookmask,
@@ -1449,6 +1552,31 @@ compat_check_calc_match(struct ipt_entry_match *m,
}
static inline int
+compat_release_match(struct ipt_entry_match *m, unsigned int *i)
+{
+ if (i && (*i)-- == 0)
+ return 1;
+
+ module_put(m->u.kernel.match->me);
+ return 0;
+}
+
+static inline int
+compat_release_entry(struct ipt_entry *e, unsigned int *i)
+{
+ struct ipt_entry_target *t;
+
+ if (i && (*i)-- == 0)
+ return 1;
+
+ /* Cleanup all matches */
+ IPT_MATCH_ITERATE(e, compat_release_match, NULL);
+ t = ipt_get_target(e);
+ module_put(t->u.kernel.target->me);
+ return 0;
+}
+
+static inline int
check_compat_entry_size_and_hooks(struct ipt_entry *e,
struct xt_table_info *newinfo,
unsigned int *size,
@@ -1485,10 +1613,10 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
off = 0;
entry_offset = (void *)e - (void *)base;
j = 0;
- ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip,
+ ret = IPT_MATCH_ITERATE(e, compat_find_calc_match, name, &e->ip,
e->comefrom, &off, &j);
if (ret != 0)
- goto cleanup_matches;
+ goto release_matches;
t = ipt_get_target(e);
target = try_then_request_module(xt_find_target(AF_INET,
@@ -1499,7 +1627,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
duprintf("check_compat_entry_size_and_hooks: `%s' not found\n",
t->u.user.name);
ret = target ? PTR_ERR(target) : -ENOENT;
- goto cleanup_matches;
+ goto release_matches;
}
t->u.kernel.target = target;
@@ -1526,8 +1654,8 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
out:
module_put(t->u.kernel.target->me);
-cleanup_matches:
- IPT_MATCH_ITERATE(e, cleanup_match, &j);
+release_matches:
+ IPT_MATCH_ITERATE(e, compat_release_match, &j);
return ret;
}
@@ -1574,15 +1702,26 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
return ret;
}
-static inline int compat_check_entry(struct ipt_entry *e, const char *name)
+static inline int compat_check_entry(struct ipt_entry *e, const char *name,
+ unsigned int *i)
{
- int ret;
+ int j, ret;
- ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom);
+ j = 0;
+ ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
if (ret)
- return ret;
+ goto cleanup_matches;
+
+ ret = check_target(e, name);
+ if (ret)
+ goto cleanup_matches;
+
+ (*i)++;
+ return 0;
- return check_target(e, name);
+ cleanup_matches:
+ IPT_MATCH_ITERATE(e, cleanup_match, &j);
+ return ret;
}
static int
@@ -1673,10 +1812,17 @@ translate_compat_table(const char *name,
if (!mark_source_chains(newinfo, valid_hooks, entry1))
goto free_newinfo;
+ i = 0;
ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
- name);
- if (ret)
- goto free_newinfo;
+ name, &i);
+ if (ret) {
+ j -= i;
+ IPT_ENTRY_ITERATE_CONTINUE(entry1, newinfo->size, i,
+ compat_release_entry, &j);
+ IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);
+ xt_free_table_info(newinfo);
+ return ret;
+ }
/* And one copy for every other CPU */
for_each_possible_cpu(i)
@@ -1691,7 +1837,7 @@ translate_compat_table(const char *name,
free_newinfo:
xt_free_table_info(newinfo);
out:
- IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j);
+ IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);
return ret;
out_unlock:
compat_flush_offsets();
@@ -2060,16 +2206,16 @@ void ipt_unregister_table(struct xt_table *table)
}
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
-static inline int
+static inline bool
icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
u_int8_t type, u_int8_t code,
- int invert)
+ bool invert)
{
return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
^ invert;
}
-static int
+static bool
icmp_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -2077,14 +2223,14 @@ icmp_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
struct icmphdr _icmph, *ic;
const struct ipt_icmp *icmpinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
- return 0;
+ return false;
ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph);
if (ic == NULL) {
@@ -2092,8 +2238,8 @@ icmp_match(const struct sk_buff *skb,
* can't. Hence, no choice but to drop.
*/
duprintf("Dropping evil ICMP tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
return icmp_type_code_match(icmpinfo->type,
@@ -2104,7 +2250,7 @@ icmp_match(const struct sk_buff *skb,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
icmp_checkentry(const char *tablename,
const void *info,
const struct xt_match *match,
@@ -2118,7 +2264,7 @@ icmp_checkentry(const char *tablename,
}
/* The built-in targets: standard (NULL) and error. */
-static struct xt_target ipt_standard_target = {
+static struct xt_target ipt_standard_target __read_mostly = {
.name = IPT_STANDARD_TARGET,
.targetsize = sizeof(int),
.family = AF_INET,
@@ -2129,7 +2275,7 @@ static struct xt_target ipt_standard_target = {
#endif
};
-static struct xt_target ipt_error_target = {
+static struct xt_target ipt_error_target __read_mostly = {
.name = IPT_ERROR_TARGET,
.target = ipt_error,
.targetsize = IPT_FUNCTION_MAXNAMELEN,
@@ -2152,7 +2298,7 @@ static struct nf_sockopt_ops ipt_sockopts = {
#endif
};
-static struct xt_match icmp_matchstruct = {
+static struct xt_match icmp_matchstruct __read_mostly = {
.name = "icmp",
.match = icmp_match,
.matchsize = sizeof(struct ipt_icmp),
@@ -2185,7 +2331,7 @@ static int __init ip_tables_init(void)
if (ret < 0)
goto err5;
- printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n");
+ printk(KERN_INFO "ip_tables: (C) 2000-2006 Netfilter Core Team\n");
return 0;
err5:
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 40e27342139..dcc12b18347 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -30,14 +30,6 @@
#define CLUSTERIP_VERSION "0.8"
-#define DEBUG_CLUSTERIP
-
-#ifdef DEBUG_CLUSTERIP
-#define DEBUGP printk
-#else
-#define DEBUGP
-#endif
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -122,9 +114,8 @@ __clusterip_config_find(__be32 clusterip)
list_for_each(pos, &clusterip_configs) {
struct clusterip_config *c = list_entry(pos,
struct clusterip_config, list);
- if (c->clusterip == clusterip) {
+ if (c->clusterip == clusterip)
return c;
- }
}
return NULL;
@@ -155,9 +146,8 @@ clusterip_config_init_nodelist(struct clusterip_config *c,
{
int n;
- for (n = 0; n < i->num_local_nodes; n++) {
+ for (n = 0; n < i->num_local_nodes; n++)
set_bit(i->local_nodes[n] - 1, &c->local_nodes);
- }
}
static struct clusterip_config *
@@ -220,27 +210,28 @@ clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
return 0;
}
-static int
+static bool
clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
{
if (nodenum == 0 ||
nodenum > c->num_total_nodes)
- return 1;
+ return true;
if (test_and_clear_bit(nodenum - 1, &c->local_nodes))
- return 0;
+ return false;
- return 1;
+ return true;
}
#endif
static inline u_int32_t
-clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
+clusterip_hashfn(const struct sk_buff *skb,
+ const struct clusterip_config *config)
{
- struct iphdr *iph = ip_hdr(skb);
+ const struct iphdr *iph = ip_hdr(skb);
unsigned long hashval;
u_int16_t sport, dport;
- u_int16_t *ports;
+ const u_int16_t *ports;
switch (iph->protocol) {
case IPPROTO_TCP:
@@ -249,15 +240,14 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
case IPPROTO_SCTP:
case IPPROTO_DCCP:
case IPPROTO_ICMP:
- ports = (void *)iph+iph->ihl*4;
+ ports = (const void *)iph+iph->ihl*4;
sport = ports[0];
dport = ports[1];
break;
default:
- if (net_ratelimit()) {
+ if (net_ratelimit())
printk(KERN_NOTICE "CLUSTERIP: unknown protocol `%u'\n",
iph->protocol);
- }
sport = dport = 0;
}
@@ -285,11 +275,11 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
}
/* node numbers are 1..n, not 0..n */
- return ((hashval % config->num_total_nodes)+1);
+ return (hashval % config->num_total_nodes) + 1;
}
static inline int
-clusterip_responsible(struct clusterip_config *config, u_int32_t hash)
+clusterip_responsible(const struct clusterip_config *config, u_int32_t hash)
{
return test_bit(hash - 1, &config->local_nodes);
}
@@ -353,15 +343,15 @@ target(struct sk_buff **pskb,
break;
}
-#ifdef DEBUG_CLUSTERP
+#ifdef DEBUG
DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
#endif
- DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark);
+ pr_debug("hash=%u ct_hash=%u ", hash, ct->mark);
if (!clusterip_responsible(cipinfo->config, hash)) {
- DEBUGP("not responsible\n");
+ pr_debug("not responsible\n");
return NF_DROP;
}
- DEBUGP("responsible\n");
+ pr_debug("responsible\n");
/* despite being received via linklayer multicast, this is
* actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
@@ -370,7 +360,7 @@ target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int
+static bool
checkentry(const char *tablename,
const void *e_void,
const struct xt_target *target,
@@ -387,50 +377,34 @@ checkentry(const char *tablename,
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
printk(KERN_WARNING "CLUSTERIP: unknown mode `%u'\n",
cipinfo->hash_mode);
- return 0;
+ return false;
}
if (e->ip.dmsk.s_addr != htonl(0xffffffff)
|| e->ip.dst.s_addr == 0) {
printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n");
- return 0;
+ return false;
}
/* FIXME: further sanity checks */
config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
- if (config) {
- if (cipinfo->config != NULL) {
- /* Case A: This is an entry that gets reloaded, since
- * it still has a cipinfo->config pointer. Simply
- * increase the entry refcount and return */
- if (cipinfo->config != config) {
- printk(KERN_ERR "CLUSTERIP: Reloaded entry "
- "has invalid config pointer!\n");
- return 0;
- }
- } else {
- /* Case B: This is a new rule referring to an existing
- * clusterip config. */
- cipinfo->config = config;
- }
- } else {
- /* Case C: This is a completely new clusterip config */
+ if (!config) {
if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr));
- return 0;
+ return false;
} else {
struct net_device *dev;
if (e->ip.iniface[0] == '\0') {
printk(KERN_WARNING "CLUSTERIP: Please specify an interface name\n");
- return 0;
+ return false;
}
dev = dev_get_by_name(e->ip.iniface);
if (!dev) {
printk(KERN_WARNING "CLUSTERIP: no such interface %s\n", e->ip.iniface);
- return 0;
+ return false;
}
config = clusterip_config_init(cipinfo,
@@ -438,20 +412,20 @@ checkentry(const char *tablename,
if (!config) {
printk(KERN_WARNING "CLUSTERIP: cannot allocate config\n");
dev_put(dev);
- return 0;
+ return false;
}
dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0);
}
- cipinfo->config = config;
}
+ cipinfo->config = config;
if (nf_ct_l3proto_try_module_get(target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", target->family);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* drop reference count of cluster config when rule is deleted */
@@ -468,13 +442,30 @@ static void destroy(const struct xt_target *target, void *targinfo)
nf_ct_l3proto_module_put(target->family);
}
-static struct xt_target clusterip_tgt = {
+#ifdef CONFIG_COMPAT
+struct compat_ipt_clusterip_tgt_info
+{
+ u_int32_t flags;
+ u_int8_t clustermac[6];
+ u_int16_t num_total_nodes;
+ u_int16_t num_local_nodes;
+ u_int16_t local_nodes[CLUSTERIP_MAX_NODES];
+ u_int32_t hash_mode;
+ u_int32_t hash_initval;
+ compat_uptr_t config;
+};
+#endif /* CONFIG_COMPAT */
+
+static struct xt_target clusterip_tgt __read_mostly = {
.name = "CLUSTERIP",
.family = AF_INET,
.target = target,
- .targetsize = sizeof(struct ipt_clusterip_tgt_info),
.checkentry = checkentry,
.destroy = destroy,
+ .targetsize = sizeof(struct ipt_clusterip_tgt_info),
+#ifdef CONFIG_COMPAT
+ .compatsize = sizeof(struct compat_ipt_clusterip_tgt_info),
+#endif /* CONFIG_COMPAT */
.me = THIS_MODULE
};
@@ -491,7 +482,7 @@ struct arp_payload {
__be32 dst_ip;
} __attribute__ ((packed));
-#ifdef CLUSTERIP_DEBUG
+#ifdef DEBUG
static void arp_print(struct arp_payload *payload)
{
#define HBUFFERLEN 30
@@ -547,8 +538,9 @@ arp_mangle(unsigned int hook,
* this wouldn't work, since we didn't subscribe the mcast group on
* other interfaces */
if (c->dev != out) {
- DEBUGP("CLUSTERIP: not mangling arp reply on different "
- "interface: cip'%s'-skb'%s'\n", c->dev->name, out->name);
+ pr_debug("CLUSTERIP: not mangling arp reply on different "
+ "interface: cip'%s'-skb'%s'\n",
+ c->dev->name, out->name);
clusterip_config_put(c);
return NF_ACCEPT;
}
@@ -556,8 +548,8 @@ arp_mangle(unsigned int hook,
/* mangle reply hardware address */
memcpy(payload->src_hw, c->clustermac, arp->ar_hln);
-#ifdef CLUSTERIP_DEBUG
- DEBUGP(KERN_DEBUG "CLUSTERIP mangled arp reply: ");
+#ifdef DEBUG
+ pr_debug(KERN_DEBUG "CLUSTERIP mangled arp reply: ");
arp_print(payload);
#endif
@@ -647,7 +639,7 @@ static int clusterip_seq_show(struct seq_file *s, void *v)
return 0;
}
-static struct seq_operations clusterip_seq_ops = {
+static const struct seq_operations clusterip_seq_ops = {
.start = clusterip_seq_start,
.next = clusterip_seq_next,
.stop = clusterip_seq_stop,
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 918ca92e534..f1253bd3837 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -24,8 +24,8 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables ECN modification module");
/* set ECT codepoint from IP header.
- * return 0 if there was an error. */
-static inline int
+ * return false if there was an error. */
+static inline bool
set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
{
struct iphdr *iph = ip_hdr(*pskb);
@@ -33,18 +33,18 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
__u8 oldtos;
if (!skb_make_writable(pskb, sizeof(struct iphdr)))
- return 0;
+ return false;
iph = ip_hdr(*pskb);
oldtos = iph->tos;
iph->tos &= ~IPT_ECN_IP_MASK;
iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
}
- return 1;
+ return true;
}
-/* Return 0 if there was an error. */
-static inline int
+/* Return false if there was an error. */
+static inline bool
set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
{
struct tcphdr _tcph, *tcph;
@@ -54,16 +54,16 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb),
sizeof(_tcph), &_tcph);
if (!tcph)
- return 0;
+ return false;
if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) ||
tcph->ece == einfo->proto.tcp.ece) &&
- ((!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
- tcph->cwr == einfo->proto.tcp.cwr)))
- return 1;
+ (!(einfo->operation & IPT_ECN_OP_SET_CWR) ||
+ tcph->cwr == einfo->proto.tcp.cwr))
+ return true;
if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
- return 0;
+ return false;
tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb);
oldval = ((__be16 *)tcph)[6];
@@ -74,7 +74,7 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
nf_proto_csum_replace2(&tcph->check, *pskb,
oldval, ((__be16 *)tcph)[6], 0);
- return 1;
+ return true;
}
static unsigned int
@@ -99,7 +99,7 @@ target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int
+static bool
checkentry(const char *tablename,
const void *e_void,
const struct xt_target *target,
@@ -112,23 +112,23 @@ checkentry(const char *tablename,
if (einfo->operation & IPT_ECN_OP_MASK) {
printk(KERN_WARNING "ECN: unsupported ECN operation %x\n",
einfo->operation);
- return 0;
+ return false;
}
if (einfo->ip_ect & ~IPT_ECN_IP_MASK) {
printk(KERN_WARNING "ECN: new ECT codepoint %x out of mask\n",
einfo->ip_ect);
- return 0;
+ return false;
}
if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
&& (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) {
printk(KERN_WARNING "ECN: cannot use TCP operations on a "
"non-tcp rule\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_target ipt_ecn_reg = {
+static struct xt_target ipt_ecn_reg __read_mostly = {
.name = "ECN",
.family = AF_INET,
.target = target,
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index a42c5cd968b..5937ad150b9 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -27,12 +27,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables syslog logging module");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Use lock to serialize, so printks don't overlap */
static DEFINE_SPINLOCK(log_lock);
@@ -41,7 +35,8 @@ static void dump_packet(const struct nf_loginfo *info,
const struct sk_buff *skb,
unsigned int iphoff)
{
- struct iphdr _iph, *ih;
+ struct iphdr _iph;
+ const struct iphdr *ih;
unsigned int logflags;
if (info->type == NF_LOG_TYPE_LOG)
@@ -100,7 +95,8 @@ static void dump_packet(const struct nf_loginfo *info,
switch (ih->protocol) {
case IPPROTO_TCP: {
- struct tcphdr _tcph, *th;
+ struct tcphdr _tcph;
+ const struct tcphdr *th;
/* Max length: 10 "PROTO=TCP " */
printk("PROTO=TCP ");
@@ -151,7 +147,7 @@ static void dump_packet(const struct nf_loginfo *info,
if ((logflags & IPT_LOG_TCPOPT)
&& th->doff * 4 > sizeof(struct tcphdr)) {
unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
- unsigned char *op;
+ const unsigned char *op;
unsigned int i, optsize;
optsize = th->doff * 4 - sizeof(struct tcphdr);
@@ -173,7 +169,8 @@ static void dump_packet(const struct nf_loginfo *info,
}
case IPPROTO_UDP:
case IPPROTO_UDPLITE: {
- struct udphdr _udph, *uh;
+ struct udphdr _udph;
+ const struct udphdr *uh;
if (ih->protocol == IPPROTO_UDP)
/* Max length: 10 "PROTO=UDP " */
@@ -200,7 +197,8 @@ static void dump_packet(const struct nf_loginfo *info,
break;
}
case IPPROTO_ICMP: {
- struct icmphdr _icmph, *ich;
+ struct icmphdr _icmph;
+ const struct icmphdr *ich;
static const size_t required_len[NR_ICMP_TYPES+1]
= { [ICMP_ECHOREPLY] = 4,
[ICMP_DEST_UNREACH]
@@ -285,7 +283,8 @@ static void dump_packet(const struct nf_loginfo *info,
}
/* Max Length */
case IPPROTO_AH: {
- struct ip_auth_hdr _ahdr, *ah;
+ struct ip_auth_hdr _ahdr;
+ const struct ip_auth_hdr *ah;
if (ntohs(ih->frag_off) & IP_OFFSET)
break;
@@ -307,7 +306,8 @@ static void dump_packet(const struct nf_loginfo *info,
break;
}
case IPPROTO_ESP: {
- struct ip_esp_hdr _esph, *eh;
+ struct ip_esp_hdr _esph;
+ const struct ip_esp_hdr *eh;
/* Max length: 10 "PROTO=ESP " */
printk("PROTO=ESP ");
@@ -385,11 +385,13 @@ ipt_log_packet(unsigned int pf,
out ? out->name : "");
#ifdef CONFIG_BRIDGE_NETFILTER
if (skb->nf_bridge) {
- struct net_device *physindev = skb->nf_bridge->physindev;
- struct net_device *physoutdev = skb->nf_bridge->physoutdev;
+ const struct net_device *physindev;
+ const struct net_device *physoutdev;
+ physindev = skb->nf_bridge->physindev;
if (physindev && in != physindev)
printk("PHYSIN=%s ", physindev->name);
+ physoutdev = skb->nf_bridge->physoutdev;
if (physoutdev && out != physoutdev)
printk("PHYSOUT=%s ", physoutdev->name);
}
@@ -435,27 +437,27 @@ ipt_log_target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int ipt_log_checkentry(const char *tablename,
- const void *e,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool ipt_log_checkentry(const char *tablename,
+ const void *e,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
{
const struct ipt_log_info *loginfo = targinfo;
if (loginfo->level >= 8) {
- DEBUGP("LOG: level %u >= 8\n", loginfo->level);
- return 0;
+ pr_debug("LOG: level %u >= 8\n", loginfo->level);
+ return false;
}
if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
- DEBUGP("LOG: prefix term %i\n",
- loginfo->prefix[sizeof(loginfo->prefix)-1]);
- return 0;
+ pr_debug("LOG: prefix term %i\n",
+ loginfo->prefix[sizeof(loginfo->prefix)-1]);
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_target ipt_log_reg = {
+static struct xt_target ipt_log_reg __read_mostly = {
.name = "LOG",
.family = AF_INET,
.target = ipt_log_target,
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index d4f2d777533..7c4e4be7c8b 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -27,17 +27,11 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables MASQUERADE target module");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Lock protects masq region inside conntrack */
static DEFINE_RWLOCK(masq_lock);
/* FIXME: Multiple targets. --RR */
-static int
+static bool
masquerade_check(const char *tablename,
const void *e,
const struct xt_target *target,
@@ -47,14 +41,14 @@ masquerade_check(const char *tablename,
const struct nf_nat_multi_range_compat *mr = targinfo;
if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
- DEBUGP("masquerade_check: bad MAP_IPS.\n");
- return 0;
+ pr_debug("masquerade_check: bad MAP_IPS.\n");
+ return false;
}
if (mr->rangesize != 1) {
- DEBUGP("masquerade_check: bad rangesize %u.\n", mr->rangesize);
- return 0;
+ pr_debug("masquerade_check: bad rangesize %u\n", mr->rangesize);
+ return false;
}
- return 1;
+ return true;
}
static unsigned int
@@ -70,7 +64,7 @@ masquerade_target(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo;
struct nf_nat_range newrange;
const struct nf_nat_multi_range_compat *mr;
- struct rtable *rt;
+ const struct rtable *rt;
__be32 newsrc;
NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
@@ -109,10 +103,10 @@ masquerade_target(struct sk_buff **pskb,
return nf_nat_setup_info(ct, &newrange, hooknum);
}
-static inline int
+static int
device_cmp(struct nf_conn *i, void *ifindex)
{
- struct nf_conn_nat *nat = nfct_nat(i);
+ const struct nf_conn_nat *nat = nfct_nat(i);
int ret;
if (!nat)
@@ -129,7 +123,7 @@ static int masq_device_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{
- struct net_device *dev = ptr;
+ const struct net_device *dev = ptr;
if (event == NETDEV_DOWN) {
/* Device was downed. Search entire table for
@@ -147,7 +141,7 @@ static int masq_inet_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{
- struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
+ const struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
if (event == NETDEV_DOWN) {
/* IP address was deleted. Search entire table for
@@ -169,7 +163,7 @@ static struct notifier_block masq_inet_notifier = {
.notifier_call = masq_inet_event,
};
-static struct xt_target masquerade = {
+static struct xt_target masquerade __read_mostly = {
.name = "MASQUERADE",
.family = AF_INET,
.target = masquerade_target,
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 068c69bce30..41a011d5a06 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -18,18 +18,11 @@
#include <linux/netfilter/x_tables.h>
#include <net/netfilter/nf_nat_rule.h>
-#define MODULENAME "NETMAP"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
check(const char *tablename,
const void *e,
const struct xt_target *target,
@@ -39,14 +32,14 @@ check(const char *tablename,
const struct nf_nat_multi_range_compat *mr = targinfo;
if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
- DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
- return 0;
+ pr_debug("NETMAP:check: bad MAP_IPS.\n");
+ return false;
}
if (mr->rangesize != 1) {
- DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize);
- return 0;
+ pr_debug("NETMAP:check: bad rangesize %u.\n", mr->rangesize);
+ return false;
}
- return 1;
+ return true;
}
static unsigned int
@@ -85,8 +78,8 @@ target(struct sk_buff **pskb,
return nf_nat_setup_info(ct, &newrange, hooknum);
}
-static struct xt_target target_module = {
- .name = MODULENAME,
+static struct xt_target target_module __read_mostly = {
+ .name = "NETMAP",
.family = AF_INET,
.target = target,
.targetsize = sizeof(struct nf_nat_multi_range_compat),
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 68cc76a198e..6ac7a237331 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -25,14 +25,8 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables REDIRECT target module");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* FIXME: Take multiple ranges --RR */
-static int
+static bool
redirect_check(const char *tablename,
const void *e,
const struct xt_target *target,
@@ -42,14 +36,14 @@ redirect_check(const char *tablename,
const struct nf_nat_multi_range_compat *mr = targinfo;
if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) {
- DEBUGP("redirect_check: bad MAP_IPS.\n");
- return 0;
+ pr_debug("redirect_check: bad MAP_IPS.\n");
+ return false;
}
if (mr->rangesize != 1) {
- DEBUGP("redirect_check: bad rangesize %u.\n", mr->rangesize);
- return 0;
+ pr_debug("redirect_check: bad rangesize %u.\n", mr->rangesize);
+ return false;
}
- return 1;
+ return true;
}
static unsigned int
@@ -101,7 +95,7 @@ redirect_target(struct sk_buff **pskb,
return nf_nat_setup_info(ct, &newrange, hooknum);
}
-static struct xt_target redirect_reg = {
+static struct xt_target redirect_reg __read_mostly = {
.name = "REDIRECT",
.family = AF_INET,
.target = redirect_target,
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 9041e0741f6..cb038c8fbc9 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -31,12 +31,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables REJECT target module");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Send RST reply */
static void send_reset(struct sk_buff *oldskb, int hook)
{
@@ -122,7 +116,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
tcph->check = 0;
tcph->check = tcp_v4_check(sizeof(struct tcphdr),
niph->saddr, niph->daddr,
- csum_partial((char *)tcph,
+ csum_partial(tcph,
sizeof(struct tcphdr), 0));
/* Set DF, id = 0 */
@@ -217,30 +211,30 @@ static unsigned int reject(struct sk_buff **pskb,
return NF_DROP;
}
-static int check(const char *tablename,
- const void *e_void,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool check(const char *tablename,
+ const void *e_void,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
{
const struct ipt_reject_info *rejinfo = targinfo;
const struct ipt_entry *e = e_void;
if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
- printk("REJECT: ECHOREPLY no longer supported.\n");
- return 0;
+ printk("ipt_REJECT: ECHOREPLY no longer supported.\n");
+ return false;
} else if (rejinfo->with == IPT_TCP_RESET) {
/* Must specify that it's a TCP packet */
if (e->ip.proto != IPPROTO_TCP
|| (e->ip.invflags & XT_INV_PROTO)) {
- DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
- return 0;
+ printk("ipt_REJECT: TCP_RESET invalid for non-tcp\n");
+ return false;
}
}
- return 1;
+ return true;
}
-static struct xt_target ipt_reject_reg = {
+static struct xt_target ipt_reject_reg __read_mostly = {
.name = "REJECT",
.family = AF_INET,
.target = reject,
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 511e5ff8493..97641f1a97f 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -27,13 +27,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Martin Josefsson <gandalf@wlug.westbo.se>");
MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
same_check(const char *tablename,
const void *e,
const struct xt_target *target,
@@ -46,58 +40,56 @@ same_check(const char *tablename,
mr->ipnum = 0;
if (mr->rangesize < 1) {
- DEBUGP("same_check: need at least one dest range.\n");
- return 0;
+ pr_debug("same_check: need at least one dest range.\n");
+ return false;
}
if (mr->rangesize > IPT_SAME_MAX_RANGE) {
- DEBUGP("same_check: too many ranges specified, maximum "
- "is %u ranges\n",
- IPT_SAME_MAX_RANGE);
- return 0;
+ pr_debug("same_check: too many ranges specified, maximum "
+ "is %u ranges\n", IPT_SAME_MAX_RANGE);
+ return false;
}
for (count = 0; count < mr->rangesize; count++) {
if (ntohl(mr->range[count].min_ip) >
ntohl(mr->range[count].max_ip)) {
- DEBUGP("same_check: min_ip is larger than max_ip in "
- "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n",
- NIPQUAD(mr->range[count].min_ip),
- NIPQUAD(mr->range[count].max_ip));
- return 0;
+ pr_debug("same_check: min_ip is larger than max_ip in "
+ "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n",
+ NIPQUAD(mr->range[count].min_ip),
+ NIPQUAD(mr->range[count].max_ip));
+ return false;
}
if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) {
- DEBUGP("same_check: bad MAP_IPS.\n");
- return 0;
+ pr_debug("same_check: bad MAP_IPS.\n");
+ return false;
}
rangeip = (ntohl(mr->range[count].max_ip) -
ntohl(mr->range[count].min_ip) + 1);
mr->ipnum += rangeip;
- DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip);
+ pr_debug("same_check: range %u, ipnum = %u\n", count, rangeip);
}
- DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum);
+ pr_debug("same_check: total ipaddresses = %u\n", mr->ipnum);
mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL);
if (!mr->iparray) {
- DEBUGP("same_check: Couldn't allocate %u bytes "
- "for %u ipaddresses!\n",
- (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
- return 0;
+ pr_debug("same_check: Couldn't allocate %Zu bytes "
+ "for %u ipaddresses!\n",
+ (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+ return false;
}
- DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n",
- (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+ pr_debug("same_check: Allocated %Zu bytes for %u ipaddresses.\n",
+ (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
for (count = 0; count < mr->rangesize; count++) {
for (countess = ntohl(mr->range[count].min_ip);
countess <= ntohl(mr->range[count].max_ip);
countess++) {
mr->iparray[index] = countess;
- DEBUGP("same_check: Added ipaddress `%u.%u.%u.%u' "
- "in index %u.\n",
- HIPQUAD(countess), index);
+ pr_debug("same_check: Added ipaddress `%u.%u.%u.%u' "
+ "in index %u.\n", HIPQUAD(countess), index);
index++;
}
}
- return 1;
+ return true;
}
static void
@@ -107,8 +99,8 @@ same_destroy(const struct xt_target *target, void *targinfo)
kfree(mr->iparray);
- DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n",
- (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
+ pr_debug("same_destroy: Deallocated %Zu bytes for %u ipaddresses.\n",
+ (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
}
static unsigned int
@@ -146,10 +138,9 @@ same_target(struct sk_buff **pskb,
new_ip = htonl(same->iparray[aindex]);
- DEBUGP("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, "
- "new src=%u.%u.%u.%u\n",
- NIPQUAD(t->src.ip), NIPQUAD(t->dst.ip),
- NIPQUAD(new_ip));
+ pr_debug("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, "
+ "new src=%u.%u.%u.%u\n",
+ NIPQUAD(t->src.u3.ip), NIPQUAD(t->dst.u3.ip), NIPQUAD(new_ip));
/* Transfer from original range. */
newrange = ((struct nf_nat_range)
@@ -161,7 +152,7 @@ same_target(struct sk_buff **pskb,
return nf_nat_setup_info(ct, &newrange, hooknum);
}
-static struct xt_target same_reg = {
+static struct xt_target same_reg __read_mostly = {
.name = "SAME",
.family = AF_INET,
.target = same_target,
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 0ad02f24983..25f5d0b3906 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -43,7 +43,7 @@ target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int
+static bool
checkentry(const char *tablename,
const void *e_void,
const struct xt_target *target,
@@ -58,12 +58,12 @@ checkentry(const char *tablename,
&& tos != IPTOS_MINCOST
&& tos != IPTOS_NORMALSVC) {
printk(KERN_WARNING "TOS: bad tos value %#x\n", tos);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_target ipt_tos_reg = {
+static struct xt_target ipt_tos_reg __read_mostly = {
.name = "TOS",
.family = AF_INET,
.target = target,
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index a991ec7bd4e..2b54e7b0cfe 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -62,25 +62,25 @@ ipt_ttl_target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int ipt_ttl_checkentry(const char *tablename,
+static bool ipt_ttl_checkentry(const char *tablename,
const void *e,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask)
{
- struct ipt_TTL_info *info = targinfo;
+ const struct ipt_TTL_info *info = targinfo;
if (info->mode > IPT_TTL_MAXMODE) {
printk(KERN_WARNING "ipt_TTL: invalid or unknown Mode %u\n",
info->mode);
- return 0;
+ return false;
}
- if ((info->mode != IPT_TTL_SET) && (info->ttl == 0))
- return 0;
- return 1;
+ if (info->mode != IPT_TTL_SET && info->ttl == 0)
+ return false;
+ return true;
}
-static struct xt_target ipt_TTL = {
+static struct xt_target ipt_TTL __read_mostly = {
.name = "TTL",
.family = AF_INET,
.target = ipt_ttl_target,
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 23b607b33b3..6ca43e4ca7e 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -55,13 +55,6 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG);
#define ULOG_NL_EVENT 111 /* Harald's favorite number */
#define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */
-#if 0
-#define DEBUGP(format, args...) printk("%s:%s:" format, \
- __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
static unsigned int nlbufsiz = NLMSG_GOODSIZE;
@@ -96,12 +89,12 @@ static void ulog_send(unsigned int nlgroupnum)
ulog_buff_t *ub = &ulog_buffers[nlgroupnum];
if (timer_pending(&ub->timer)) {
- DEBUGP("ipt_ULOG: ulog_send: timer was pending, deleting\n");
+ pr_debug("ipt_ULOG: ulog_send: timer was pending, deleting\n");
del_timer(&ub->timer);
}
if (!ub->skb) {
- DEBUGP("ipt_ULOG: ulog_send: nothing to send\n");
+ pr_debug("ipt_ULOG: ulog_send: nothing to send\n");
return;
}
@@ -110,8 +103,8 @@ static void ulog_send(unsigned int nlgroupnum)
ub->lastnlh->nlmsg_type = NLMSG_DONE;
NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1;
- DEBUGP("ipt_ULOG: throwing %d packets to netlink group %u\n",
- ub->qlen, nlgroupnum + 1);
+ pr_debug("ipt_ULOG: throwing %d packets to netlink group %u\n",
+ ub->qlen, nlgroupnum + 1);
netlink_broadcast(nflognl, ub->skb, 0, nlgroupnum + 1, GFP_ATOMIC);
ub->qlen = 0;
@@ -123,7 +116,7 @@ static void ulog_send(unsigned int nlgroupnum)
/* timer function to flush queue in flushtimeout time */
static void ulog_timer(unsigned long data)
{
- DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n");
+ pr_debug("ipt_ULOG: timer function called, calling ulog_send\n");
/* lock to protect against somebody modifying our structure
* from ipt_ulog_target at the same time */
@@ -179,12 +172,10 @@ static void ipt_ulog_packet(unsigned int hooknum,
unsigned int groupnum = ffs(loginfo->nl_group) - 1;
/* calculate the size of the skb needed */
- if ((loginfo->copy_range == 0) ||
- (loginfo->copy_range > skb->len)) {
+ if (loginfo->copy_range == 0 || loginfo->copy_range > skb->len)
copy_len = skb->len;
- } else {
+ else
copy_len = loginfo->copy_range;
- }
size = NLMSG_SPACE(sizeof(*pm) + copy_len);
@@ -206,8 +197,8 @@ static void ipt_ulog_packet(unsigned int hooknum,
goto alloc_failure;
}
- DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen,
- loginfo->qthreshold);
+ pr_debug("ipt_ULOG: qlen %d, qthreshold %Zu\n", ub->qlen,
+ loginfo->qthreshold);
/* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT,
@@ -257,9 +248,8 @@ static void ipt_ulog_packet(unsigned int hooknum,
BUG();
/* check if we are building multi-part messages */
- if (ub->qlen > 1) {
+ if (ub->qlen > 1)
ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
- }
ub->lastnlh = nlh;
@@ -328,25 +318,25 @@ static void ipt_logfn(unsigned int pf,
ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
}
-static int ipt_ulog_checkentry(const char *tablename,
- const void *e,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hookmask)
+static bool ipt_ulog_checkentry(const char *tablename,
+ const void *e,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hookmask)
{
- struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
+ const struct ipt_ulog_info *loginfo = targinfo;
if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') {
- DEBUGP("ipt_ULOG: prefix term %i\n",
- loginfo->prefix[sizeof(loginfo->prefix) - 1]);
- return 0;
+ pr_debug("ipt_ULOG: prefix term %i\n",
+ loginfo->prefix[sizeof(loginfo->prefix) - 1]);
+ return false;
}
if (loginfo->qthreshold > ULOG_MAX_QLEN) {
- DEBUGP("ipt_ULOG: queue threshold %i > MAX_QLEN\n",
- loginfo->qthreshold);
- return 0;
+ pr_debug("ipt_ULOG: queue threshold %Zu > MAX_QLEN\n",
+ loginfo->qthreshold);
+ return false;
}
- return 1;
+ return true;
}
#ifdef CONFIG_COMPAT
@@ -359,7 +349,7 @@ struct compat_ipt_ulog_info {
static void compat_from_user(void *dst, void *src)
{
- struct compat_ipt_ulog_info *cl = src;
+ const struct compat_ipt_ulog_info *cl = src;
struct ipt_ulog_info l = {
.nl_group = cl->nl_group,
.copy_range = cl->copy_range,
@@ -372,7 +362,7 @@ static void compat_from_user(void *dst, void *src)
static int compat_to_user(void __user *dst, void *src)
{
- struct ipt_ulog_info *l = src;
+ const struct ipt_ulog_info *l = src;
struct compat_ipt_ulog_info cl = {
.nl_group = l->nl_group,
.copy_range = l->copy_range,
@@ -384,7 +374,7 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_target ipt_ulog_reg = {
+static struct xt_target ipt_ulog_reg __read_mostly = {
.name = "ULOG",
.family = AF_INET,
.target = ipt_ulog_target,
@@ -408,7 +398,7 @@ static int __init ipt_ulog_init(void)
{
int ret, i;
- DEBUGP("ipt_ULOG: init module\n");
+ pr_debug("ipt_ULOG: init module\n");
if (nlbufsiz > 128*1024) {
printk("Netlink buffer has to be <= 128kB\n");
@@ -440,7 +430,7 @@ static void __exit ipt_ulog_fini(void)
ulog_buff_t *ub;
int i;
- DEBUGP("ipt_ULOG: cleanup_module\n");
+ pr_debug("ipt_ULOG: cleanup_module\n");
if (nflog)
nf_log_unregister(&ipt_ulog_logger);
@@ -451,7 +441,7 @@ static void __exit ipt_ulog_fini(void)
for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
ub = &ulog_buffers[i];
if (timer_pending(&ub->timer)) {
- DEBUGP("timer was pending, deleting\n");
+ pr_debug("timer was pending, deleting\n");
del_timer(&ub->timer);
}
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index a652a145155..59f01f7ba6b 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -22,19 +22,19 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_DESCRIPTION("iptables addrtype match");
-static inline int match_type(__be32 addr, u_int16_t mask)
+static inline bool match_type(__be32 addr, u_int16_t mask)
{
return !!(mask & (1 << inet_addr_type(addr)));
}
-static int match(const struct sk_buff *skb,
- const struct net_device *in, const struct net_device *out,
- const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ const struct xt_match *match, const void *matchinfo,
+ int offset, unsigned int protoff, bool *hotdrop)
{
const struct ipt_addrtype_info *info = matchinfo;
const struct iphdr *iph = ip_hdr(skb);
- int ret = 1;
+ bool ret = true;
if (info->source)
ret &= match_type(iph->saddr, info->source)^info->invert_source;
@@ -44,7 +44,7 @@ static int match(const struct sk_buff *skb,
return ret;
}
-static struct xt_match addrtype_match = {
+static struct xt_match addrtype_match __read_mostly = {
.name = "addrtype",
.family = AF_INET,
.match = match,
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 18a16782cf4..61b017fd743 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -25,10 +25,10 @@ MODULE_DESCRIPTION("iptables AH SPI match module");
#endif
/* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
{
- int r=0;
+ bool r;
duprintf("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
min,spi,max);
r=(spi >= min && spi <= max) ^ invert;
@@ -36,7 +36,7 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
return r;
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -44,14 +44,15 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
- struct ip_auth_hdr _ahdr, *ah;
+ struct ip_auth_hdr _ahdr;
+ const struct ip_auth_hdr *ah;
const struct ipt_ah *ahinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
- return 0;
+ return false;
ah = skb_header_pointer(skb, protoff,
sizeof(_ahdr), &_ahdr);
@@ -60,7 +61,7 @@ match(const struct sk_buff *skb,
* can't. Hence, no choice but to drop.
*/
duprintf("Dropping evil AH tinygram.\n");
- *hotdrop = 1;
+ *hotdrop = true;
return 0;
}
@@ -70,7 +71,7 @@ match(const struct sk_buff *skb,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
checkentry(const char *tablename,
const void *ip_void,
const struct xt_match *match,
@@ -82,12 +83,12 @@ checkentry(const char *tablename,
/* Must specify no unknown invflags */
if (ahinfo->invflags & ~IPT_AH_INV_MASK) {
duprintf("ipt_ah: unknown flags %X\n", ahinfo->invflags);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match ah_match = {
+static struct xt_match ah_match __read_mostly = {
.name = "ah",
.family = AF_INET,
.match = match,
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index 26218122f86..d6925c67406 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -22,95 +22,96 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables ECN matching module");
MODULE_LICENSE("GPL");
-static inline int match_ip(const struct sk_buff *skb,
- const struct ipt_ecn_info *einfo)
+static inline bool match_ip(const struct sk_buff *skb,
+ const struct ipt_ecn_info *einfo)
{
return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect;
}
-static inline int match_tcp(const struct sk_buff *skb,
- const struct ipt_ecn_info *einfo,
- int *hotdrop)
+static inline bool match_tcp(const struct sk_buff *skb,
+ const struct ipt_ecn_info *einfo,
+ bool *hotdrop)
{
- struct tcphdr _tcph, *th;
+ struct tcphdr _tcph;
+ const struct tcphdr *th;
/* In practice, TCP match does this, so can't fail. But let's
* be good citizens.
*/
th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_tcph), &_tcph);
if (th == NULL) {
- *hotdrop = 0;
- return 0;
+ *hotdrop = false;
+ return false;
}
if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
if (einfo->invert & IPT_ECN_OP_MATCH_ECE) {
if (th->ece == 1)
- return 0;
+ return false;
} else {
if (th->ece == 0)
- return 0;
+ return false;
}
}
if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
if (einfo->invert & IPT_ECN_OP_MATCH_CWR) {
if (th->cwr == 1)
- return 0;
+ return false;
} else {
if (th->cwr == 0)
- return 0;
+ return false;
}
}
- return 1;
+ return true;
}
-static int match(const struct sk_buff *skb,
- const struct net_device *in, const struct net_device *out,
- const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ const struct xt_match *match, const void *matchinfo,
+ int offset, unsigned int protoff, bool *hotdrop)
{
const struct ipt_ecn_info *info = matchinfo;
if (info->operation & IPT_ECN_OP_MATCH_IP)
if (!match_ip(skb, info))
- return 0;
+ return false;
if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
if (ip_hdr(skb)->protocol != IPPROTO_TCP)
- return 0;
+ return false;
if (!match_tcp(skb, info, hotdrop))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int checkentry(const char *tablename, const void *ip_void,
- const struct xt_match *match,
- void *matchinfo, unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *ip_void,
+ const struct xt_match *match,
+ void *matchinfo, unsigned int hook_mask)
{
const struct ipt_ecn_info *info = matchinfo;
const struct ipt_ip *ip = ip_void;
if (info->operation & IPT_ECN_OP_MATCH_MASK)
- return 0;
+ return false;
if (info->invert & IPT_ECN_OP_MATCH_MASK)
- return 0;
+ return false;
if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)
&& ip->proto != IPPROTO_TCP) {
printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for"
" non-tcp packets\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match ecn_match = {
+static struct xt_match ecn_match __read_mostly = {
.name = "ecn",
.family = AF_INET,
.match = match,
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index 33af9e94088..0106dc955a6 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -17,53 +17,47 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
MODULE_DESCRIPTION("iptables arbitrary IP range match module");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct xt_match *match,
const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+ int offset, unsigned int protoff, bool *hotdrop)
{
const struct ipt_iprange_info *info = matchinfo;
const struct iphdr *iph = ip_hdr(skb);
if (info->flags & IPRANGE_SRC) {
- if (((ntohl(iph->saddr) < ntohl(info->src.min_ip))
- || (ntohl(iph->saddr) > ntohl(info->src.max_ip)))
+ if ((ntohl(iph->saddr) < ntohl(info->src.min_ip)
+ || ntohl(iph->saddr) > ntohl(info->src.max_ip))
^ !!(info->flags & IPRANGE_SRC_INV)) {
- DEBUGP("src IP %u.%u.%u.%u NOT in range %s"
- "%u.%u.%u.%u-%u.%u.%u.%u\n",
- NIPQUAD(iph->saddr),
- info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
- NIPQUAD(info->src.min_ip),
- NIPQUAD(info->src.max_ip));
- return 0;
+ pr_debug("src IP %u.%u.%u.%u NOT in range %s"
+ "%u.%u.%u.%u-%u.%u.%u.%u\n",
+ NIPQUAD(iph->saddr),
+ info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
+ NIPQUAD(info->src.min_ip),
+ NIPQUAD(info->src.max_ip));
+ return false;
}
}
if (info->flags & IPRANGE_DST) {
- if (((ntohl(iph->daddr) < ntohl(info->dst.min_ip))
- || (ntohl(iph->daddr) > ntohl(info->dst.max_ip)))
+ if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip)
+ || ntohl(iph->daddr) > ntohl(info->dst.max_ip))
^ !!(info->flags & IPRANGE_DST_INV)) {
- DEBUGP("dst IP %u.%u.%u.%u NOT in range %s"
- "%u.%u.%u.%u-%u.%u.%u.%u\n",
- NIPQUAD(iph->daddr),
- info->flags & IPRANGE_DST_INV ? "(INV) " : "",
- NIPQUAD(info->dst.min_ip),
- NIPQUAD(info->dst.max_ip));
- return 0;
+ pr_debug("dst IP %u.%u.%u.%u NOT in range %s"
+ "%u.%u.%u.%u-%u.%u.%u.%u\n",
+ NIPQUAD(iph->daddr),
+ info->flags & IPRANGE_DST_INV ? "(INV) " : "",
+ NIPQUAD(info->dst.min_ip),
+ NIPQUAD(info->dst.max_ip));
+ return false;
}
}
- return 1;
+ return true;
}
-static struct xt_match iprange_match = {
+static struct xt_match iprange_match __read_mostly = {
.name = "iprange",
.family = AF_INET,
.match = match,
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 7fae9aa8944..b14e77da7a3 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables owner match");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -29,29 +29,29 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct ipt_owner_info *info = matchinfo;
if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
- return 0;
+ return false;
if(info->match & IPT_OWNER_UID) {
if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
!!(info->invert & IPT_OWNER_UID))
- return 0;
+ return false;
}
if(info->match & IPT_OWNER_GID) {
if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
!!(info->invert & IPT_OWNER_GID))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int
+static bool
checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
@@ -63,12 +63,12 @@ checkentry(const char *tablename,
if (info->match & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)) {
printk("ipt_owner: pid, sid and command matching "
"not supported anymore\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match owner_match = {
+static struct xt_match owner_match __read_mostly = {
.name = "owner",
.family = AF_INET,
.match = match,
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 15a9e8bbb7c..32180431565 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -163,24 +163,23 @@ static void recent_table_flush(struct recent_table *t)
struct recent_entry *e, *next;
unsigned int i;
- for (i = 0; i < ip_list_hash_size; i++) {
+ for (i = 0; i < ip_list_hash_size; i++)
list_for_each_entry_safe(e, next, &t->iphash[i], list)
recent_entry_remove(t, e);
- }
}
-static int
+static bool
ipt_recent_match(const struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+ int offset, unsigned int protoff, bool *hotdrop)
{
const struct ipt_recent_info *info = matchinfo;
struct recent_table *t;
struct recent_entry *e;
__be32 addr;
u_int8_t ttl;
- int ret = info->invert;
+ bool ret = info->invert;
if (info->side == IPT_RECENT_DEST)
addr = ip_hdr(skb)->daddr;
@@ -201,16 +200,16 @@ ipt_recent_match(const struct sk_buff *skb,
goto out;
e = recent_entry_init(t, addr, ttl);
if (e == NULL)
- *hotdrop = 1;
- ret ^= 1;
+ *hotdrop = true;
+ ret = !ret;
goto out;
}
if (info->check_set & IPT_RECENT_SET)
- ret ^= 1;
+ ret = !ret;
else if (info->check_set & IPT_RECENT_REMOVE) {
recent_entry_remove(t, e);
- ret ^= 1;
+ ret = !ret;
} else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) {
unsigned long t = jiffies - info->seconds * HZ;
unsigned int i, hits = 0;
@@ -219,7 +218,7 @@ ipt_recent_match(const struct sk_buff *skb,
if (info->seconds && time_after(t, e->stamps[i]))
continue;
if (++hits >= info->hit_count) {
- ret ^= 1;
+ ret = !ret;
break;
}
}
@@ -235,7 +234,7 @@ out:
return ret;
}
-static int
+static bool
ipt_recent_checkentry(const char *tablename, const void *ip,
const struct xt_match *match, void *matchinfo,
unsigned int hook_mask)
@@ -243,24 +242,24 @@ ipt_recent_checkentry(const char *tablename, const void *ip,
const struct ipt_recent_info *info = matchinfo;
struct recent_table *t;
unsigned i;
- int ret = 0;
+ bool ret = false;
if (hweight8(info->check_set &
(IPT_RECENT_SET | IPT_RECENT_REMOVE |
IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1)
- return 0;
+ return false;
if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) &&
(info->seconds || info->hit_count))
- return 0;
+ return false;
if (info->name[0] == '\0' ||
strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
- return 0;
+ return false;
mutex_lock(&recent_mutex);
t = recent_table_lookup(info->name);
if (t != NULL) {
t->refcnt++;
- ret = 1;
+ ret = true;
goto out;
}
@@ -287,7 +286,7 @@ ipt_recent_checkentry(const char *tablename, const void *ip,
spin_lock_bh(&recent_lock);
list_add_tail(&t->list, &tables);
spin_unlock_bh(&recent_lock);
- ret = 1;
+ ret = true;
out:
mutex_unlock(&recent_mutex);
return ret;
@@ -323,18 +322,16 @@ struct recent_iter_state {
static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
{
struct recent_iter_state *st = seq->private;
- struct recent_table *t = st->table;
+ const struct recent_table *t = st->table;
struct recent_entry *e;
loff_t p = *pos;
spin_lock_bh(&recent_lock);
- for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++) {
- list_for_each_entry(e, &t->iphash[st->bucket], list) {
+ for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++)
+ list_for_each_entry(e, &t->iphash[st->bucket], list)
if (p-- == 0)
return e;
- }
- }
return NULL;
}
@@ -373,7 +370,7 @@ static int recent_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations recent_seq_ops = {
+static const struct seq_operations recent_seq_ops = {
.start = recent_seq_start,
.next = recent_seq_next,
.stop = recent_seq_stop,
@@ -463,7 +460,7 @@ static const struct file_operations recent_fops = {
};
#endif /* CONFIG_PROC_FS */
-static struct xt_match recent_match = {
+static struct xt_match recent_match __read_mostly = {
.name = "recent",
.family = AF_INET,
.match = ipt_recent_match,
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index d314844af12..e740441c973 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -18,7 +18,7 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("iptables TOS match module");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -26,14 +26,14 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct ipt_tos_info *info = matchinfo;
return (ip_hdr(skb)->tos == info->tos) ^ info->invert;
}
-static struct xt_match tos_match = {
+static struct xt_match tos_match __read_mostly = {
.name = "tos",
.family = AF_INET,
.match = match,
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index ab02d9e3139..a439900a4ba 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -18,37 +18,33 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("IP tables TTL matching module");
MODULE_LICENSE("GPL");
-static int match(const struct sk_buff *skb,
- const struct net_device *in, const struct net_device *out,
- const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ const struct xt_match *match, const void *matchinfo,
+ int offset, unsigned int protoff, bool *hotdrop)
{
const struct ipt_ttl_info *info = matchinfo;
const u8 ttl = ip_hdr(skb)->ttl;
switch (info->mode) {
case IPT_TTL_EQ:
- return (ttl == info->ttl);
- break;
+ return ttl == info->ttl;
case IPT_TTL_NE:
- return (!(ttl == info->ttl));
- break;
+ return ttl != info->ttl;
case IPT_TTL_LT:
- return (ttl < info->ttl);
- break;
+ return ttl < info->ttl;
case IPT_TTL_GT:
- return (ttl > info->ttl);
- break;
+ return ttl > info->ttl;
default:
printk(KERN_WARNING "ipt_ttl: unknown mode %d\n",
info->mode);
- return 0;
+ return false;
}
- return 0;
+ return false;
}
-static struct xt_match ttl_match = {
+static struct xt_match ttl_match __read_mostly = {
.name = "ttl",
.family = AF_INET,
.match = match,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index fd62a41d69c..64552afd01c 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -24,12 +24,6 @@
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
@@ -84,36 +78,30 @@ nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
return skb;
}
-static int
-ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
- u_int8_t *protonum)
+static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
+ unsigned int *dataoff, u_int8_t *protonum)
{
+ struct iphdr _iph, *iph;
+
+ iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+ if (iph == NULL)
+ return -NF_DROP;
+
/* Never happen */
- if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) {
+ if (iph->frag_off & htons(IP_OFFSET)) {
if (net_ratelimit()) {
- printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n",
- ip_hdr(*pskb)->protocol, hooknum);
+ printk(KERN_ERR "ipv4_get_l4proto: Frag of proto %u\n",
+ iph->protocol);
}
return -NF_DROP;
}
- *dataoff = skb_network_offset(*pskb) + ip_hdrlen(*pskb);
- *protonum = ip_hdr(*pskb)->protocol;
+ *dataoff = nhoff + (iph->ihl << 2);
+ *protonum = iph->protocol;
return NF_ACCEPT;
}
-int nf_nat_module_is_loaded = 0;
-EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded);
-
-static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple)
-{
- if (nf_nat_module_is_loaded)
- return NF_CT_F_NAT;
-
- return NF_CT_F_BASIC;
-}
-
static unsigned int ipv4_confirm(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
@@ -133,6 +121,7 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
struct nf_conn_help *help;
+ struct nf_conntrack_helper *helper;
/* This is where we call the helper: as the packet goes out. */
ct = nf_ct_get(*pskb, &ctinfo);
@@ -140,12 +129,14 @@ static unsigned int ipv4_conntrack_help(unsigned int hooknum,
return NF_ACCEPT;
help = nfct_help(ct);
- if (!help || !help->helper)
+ if (!help)
return NF_ACCEPT;
-
- return help->helper->help(pskb,
- skb_network_offset(*pskb) + ip_hdrlen(*pskb),
- ct, ctinfo);
+ /* rcu_read_lock()ed by nf_hook_slow */
+ helper = rcu_dereference(help->helper);
+ if (!helper)
+ return NF_ACCEPT;
+ return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb),
+ ct, ctinfo);
}
static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
@@ -332,17 +323,17 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
/* We only do TCP at the moment: is there a better way? */
if (strcmp(sk->sk_prot->name, "TCP")) {
- DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n");
+ pr_debug("SO_ORIGINAL_DST: Not a TCP socket\n");
return -ENOPROTOOPT;
}
if ((unsigned int) *len < sizeof(struct sockaddr_in)) {
- DEBUGP("SO_ORIGINAL_DST: len %u not %u\n",
- *len, sizeof(struct sockaddr_in));
+ pr_debug("SO_ORIGINAL_DST: len %d not %Zu\n",
+ *len, sizeof(struct sockaddr_in));
return -EINVAL;
}
- h = nf_conntrack_find_get(&tuple, NULL);
+ h = nf_conntrack_find_get(&tuple);
if (h) {
struct sockaddr_in sin;
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
@@ -354,17 +345,17 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
.tuple.dst.u3.ip;
memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
- DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
- NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ pr_debug("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n",
+ NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
nf_ct_put(ct);
if (copy_to_user(user, &sin, sizeof(sin)) != 0)
return -EFAULT;
else
return 0;
}
- DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
- NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
- NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
+ pr_debug("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n",
+ NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
+ NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
return -ENOENT;
}
@@ -414,15 +405,14 @@ static struct nf_sockopt_ops so_getorigdst = {
.get = &getorigdst,
};
-struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
+struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = {
.l3proto = PF_INET,
.name = "ipv4",
.pkt_to_tuple = ipv4_pkt_to_tuple,
.invert_tuple = ipv4_invert_tuple,
.print_tuple = ipv4_print_tuple,
.print_conntrack = ipv4_print_conntrack,
- .prepare = ipv4_prepare,
- .get_features = ipv4_get_features,
+ .get_l4proto = ipv4_get_l4proto,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = ipv4_tuple_to_nfattr,
.nfattr_to_tuple = ipv4_nfattr_to_tuple,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 89f933e8103..3da9d73d1b5 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -18,12 +18,6 @@
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_expect.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
#ifdef CONFIG_NF_CT_ACCT
static unsigned int
seq_print_counters(struct seq_file *s,
@@ -41,35 +35,36 @@ struct ct_iter_state {
unsigned int bucket;
};
-static struct list_head *ct_get_first(struct seq_file *seq)
+static struct hlist_node *ct_get_first(struct seq_file *seq)
{
struct ct_iter_state *st = seq->private;
for (st->bucket = 0;
st->bucket < nf_conntrack_htable_size;
st->bucket++) {
- if (!list_empty(&nf_conntrack_hash[st->bucket]))
- return nf_conntrack_hash[st->bucket].next;
+ if (!hlist_empty(&nf_conntrack_hash[st->bucket]))
+ return nf_conntrack_hash[st->bucket].first;
}
return NULL;
}
-static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+static struct hlist_node *ct_get_next(struct seq_file *seq,
+ struct hlist_node *head)
{
struct ct_iter_state *st = seq->private;
head = head->next;
- while (head == &nf_conntrack_hash[st->bucket]) {
+ while (head == NULL) {
if (++st->bucket >= nf_conntrack_htable_size)
return NULL;
- head = nf_conntrack_hash[st->bucket].next;
+ head = nf_conntrack_hash[st->bucket].first;
}
return head;
}
-static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos)
{
- struct list_head *head = ct_get_first(seq);
+ struct hlist_node *head = ct_get_first(seq);
if (head)
while (pos && (head = ct_get_next(seq, head)))
@@ -169,7 +164,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
return 0;
}
-static struct seq_operations ct_seq_ops = {
+static const struct seq_operations ct_seq_ops = {
.start = ct_seq_start,
.next = ct_seq_next,
.stop = ct_seq_stop,
@@ -206,47 +201,68 @@ static const struct file_operations ct_file_ops = {
};
/* expects */
-static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_expect_iter_state {
+ unsigned int bucket;
+};
+
+static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
{
- struct list_head *e = &nf_conntrack_expect_list;
- loff_t i;
+ struct ct_expect_iter_state *st = seq->private;
- /* strange seq_file api calls stop even if we fail,
- * thus we need to grab lock since stop unlocks */
- read_lock_bh(&nf_conntrack_lock);
+ for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
+ if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
+ return nf_ct_expect_hash[st->bucket].first;
+ }
+ return NULL;
+}
- if (list_empty(e))
- return NULL;
+static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
+ struct hlist_node *head)
+{
+ struct ct_expect_iter_state *st = seq->private;
- for (i = 0; i <= *pos; i++) {
- e = e->next;
- if (e == &nf_conntrack_expect_list)
+ head = head->next;
+ while (head == NULL) {
+ if (++st->bucket >= nf_ct_expect_hsize)
return NULL;
+ head = nf_ct_expect_hash[st->bucket].first;
}
- return e;
+ return head;
}
-static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
{
- struct list_head *e = v;
+ struct hlist_node *head = ct_expect_get_first(seq);
- ++*pos;
- e = e->next;
+ if (head)
+ while (pos && (head = ct_expect_get_next(seq, head)))
+ pos--;
+ return pos ? NULL : head;
+}
- if (e == &nf_conntrack_expect_list)
- return NULL;
+static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ read_lock_bh(&nf_conntrack_lock);
+ return ct_expect_get_idx(seq, *pos);
+}
- return e;
+static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return ct_expect_get_next(seq, v);
}
-static void exp_seq_stop(struct seq_file *s, void *v)
+static void exp_seq_stop(struct seq_file *seq, void *v)
{
read_unlock_bh(&nf_conntrack_lock);
}
static int exp_seq_show(struct seq_file *s, void *v)
{
- struct nf_conntrack_expect *exp = v;
+ struct nf_conntrack_expect *exp;
+ struct hlist_node *n = v;
+
+ exp = hlist_entry(n, struct nf_conntrack_expect, hnode);
if (exp->tuple.src.l3num != AF_INET)
return 0;
@@ -266,7 +282,7 @@ static int exp_seq_show(struct seq_file *s, void *v)
return seq_putc(s, '\n');
}
-static struct seq_operations exp_seq_ops = {
+static const struct seq_operations exp_seq_ops = {
.start = exp_seq_start,
.next = exp_seq_next,
.stop = exp_seq_stop,
@@ -275,7 +291,23 @@ static struct seq_operations exp_seq_ops = {
static int exp_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &exp_seq_ops);
+ struct seq_file *seq;
+ struct ct_expect_iter_state *st;
+ int ret;
+
+ st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
+ if (st == NULL)
+ return -ENOMEM;
+ ret = seq_open(file, &exp_seq_ops);
+ if (ret)
+ goto out_free;
+ seq = file->private_data;
+ seq->private = st;
+ memset(st, 0, sizeof(struct ct_expect_iter_state));
+ return ret;
+out_free:
+ kfree(st);
+ return ret;
}
static const struct file_operations ip_exp_file_ops = {
@@ -283,7 +315,7 @@ static const struct file_operations ip_exp_file_ops = {
.open = exp_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release
+ .release = seq_release_private,
};
static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
@@ -354,7 +386,7 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ct_cpu_seq_ops = {
+static const struct seq_operations ct_cpu_seq_ops = {
.start = ct_cpu_seq_start,
.next = ct_cpu_seq_next,
.stop = ct_cpu_seq_stop,
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index f4fc657c198..6593fd2c5b1 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -21,12 +21,6 @@
static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
static int icmp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
@@ -125,8 +119,8 @@ static int icmp_new(struct nf_conn *conntrack,
if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
|| !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
/* Can't create a new ICMP `conn' with this. */
- DEBUGP("icmp: can't create new conn with type %u\n",
- conntrack->tuplehash[0].tuple.dst.u.icmp.type);
+ pr_debug("icmp: can't create new conn with type %u\n",
+ conntrack->tuplehash[0].tuple.dst.u.icmp.type);
NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
return 0;
}
@@ -142,72 +136,42 @@ icmp_error_message(struct sk_buff *skb,
unsigned int hooknum)
{
struct nf_conntrack_tuple innertuple, origtuple;
- struct {
- struct icmphdr icmp;
- struct iphdr ip;
- } _in, *inside;
struct nf_conntrack_l4proto *innerproto;
struct nf_conntrack_tuple_hash *h;
- int dataoff;
NF_CT_ASSERT(skb->nfct == NULL);
- /* Not enough header? */
- inside = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_in), &_in);
- if (inside == NULL)
- return -NF_ACCEPT;
-
- /* Ignore ICMP's containing fragments (shouldn't happen) */
- if (inside->ip.frag_off & htons(IP_OFFSET)) {
- DEBUGP("icmp_error_message: fragment of proto %u\n",
- inside->ip.protocol);
+ /* Are they talking about one of our connections? */
+ if (!nf_ct_get_tuplepr(skb,
+ skb_network_offset(skb) + ip_hdrlen(skb)
+ + sizeof(struct icmphdr),
+ PF_INET, &origtuple)) {
+ pr_debug("icmp_error_message: failed to get tuple\n");
return -NF_ACCEPT;
}
/* rcu_read_lock()ed by nf_hook_slow */
- innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
-
- dataoff = ip_hdrlen(skb) + sizeof(inside->icmp);
- /* Are they talking about one of our connections? */
- if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
- inside->ip.protocol, &origtuple,
- &nf_conntrack_l3proto_ipv4, innerproto)) {
- DEBUGP("icmp_error_message: ! get_tuple p=%u",
- inside->ip.protocol);
- return -NF_ACCEPT;
- }
+ innerproto = __nf_ct_l4proto_find(PF_INET, origtuple.dst.protonum);
/* Ordinarily, we'd expect the inverted tupleproto, but it's
been preserved inside the ICMP. */
if (!nf_ct_invert_tuple(&innertuple, &origtuple,
&nf_conntrack_l3proto_ipv4, innerproto)) {
- DEBUGP("icmp_error_message: no match\n");
+ pr_debug("icmp_error_message: no match\n");
return -NF_ACCEPT;
}
*ctinfo = IP_CT_RELATED;
- h = nf_conntrack_find_get(&innertuple, NULL);
+ h = nf_conntrack_find_get(&innertuple);
if (!h) {
- /* Locally generated ICMPs will match inverted if they
- haven't been SNAT'ed yet */
- /* FIXME: NAT code has to handle half-done double NAT --RR */
- if (hooknum == NF_IP_LOCAL_OUT)
- h = nf_conntrack_find_get(&origtuple, NULL);
-
- if (!h) {
- DEBUGP("icmp_error_message: no match\n");
- return -NF_ACCEPT;
- }
-
- /* Reverse direction from that found */
- if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
- *ctinfo += IP_CT_IS_REPLY;
- } else {
- if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
- *ctinfo += IP_CT_IS_REPLY;
+ pr_debug("icmp_error_message: no match\n");
+ return -NF_ACCEPT;
}
+ if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
+ *ctinfo += IP_CT_IS_REPLY;
+
/* Update skb to refer to this connection */
skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
skb->nfctinfo = *ctinfo;
@@ -348,7 +312,7 @@ static struct ctl_table icmp_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif /* CONFIG_SYSCTL */
-struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
{
.l3proto = PF_INET,
.l4proto = IPPROTO_ICMP,
@@ -374,4 +338,3 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
#endif
#endif
};
-EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_icmp);
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c
index 0f17098917b..bd93a1d7105 100644
--- a/net/ipv4/netfilter/nf_nat_amanda.c
+++ b/net/ipv4/netfilter/nf_nat_amanda.c
@@ -45,7 +45,7 @@ static unsigned int help(struct sk_buff **pskb,
/* Try to get same port: if not, try to change it. */
for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
exp->tuple.dst.u.tcp.port = htons(port);
- if (nf_conntrack_expect_related(exp) == 0)
+ if (nf_ct_expect_related(exp) == 0)
break;
}
@@ -57,7 +57,7 @@ static unsigned int help(struct sk_buff **pskb,
matchoff, matchlen,
buffer, strlen(buffer));
if (ret != NF_ACCEPT)
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
return ret;
}
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index ea02f00d2da..e848d8d6292 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -12,7 +12,6 @@
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/skbuff.h>
-#include <linux/vmalloc.h>
#include <net/checksum.h>
#include <net/icmp.h>
#include <net/ip.h>
@@ -32,20 +31,15 @@
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
static DEFINE_RWLOCK(nf_nat_lock);
static struct nf_conntrack_l3proto *l3proto = NULL;
/* Calculated at init based on memory size */
static unsigned int nf_nat_htable_size;
+static int nf_nat_vmalloced;
-static struct list_head *bysource;
+static struct hlist_head *bysource;
#define MAX_IP_NAT_PROTO 256
static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO];
@@ -87,19 +81,6 @@ hash_by_src(const struct nf_conntrack_tuple *tuple)
tuple->dst.protonum, 0) % nf_nat_htable_size;
}
-/* Noone using conntrack by the time this called. */
-static void nf_nat_cleanup_conntrack(struct nf_conn *conn)
-{
- struct nf_conn_nat *nat;
- if (!(conn->status & IPS_NAT_DONE_MASK))
- return;
-
- nat = nfct_nat(conn);
- write_lock_bh(&nf_nat_lock);
- list_del(&nat->info.bysource);
- write_unlock_bh(&nf_nat_lock);
-}
-
/* Is this tuple already taken? (not by us) */
int
nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
@@ -166,10 +147,11 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple,
unsigned int h = hash_by_src(tuple);
struct nf_conn_nat *nat;
struct nf_conn *ct;
+ struct hlist_node *n;
read_lock_bh(&nf_nat_lock);
- list_for_each_entry(nat, &bysource[h], info.bysource) {
- ct = (struct nf_conn *)((char *)nat - offsetof(struct nf_conn, data));
+ hlist_for_each_entry(nat, n, &bysource[h], bysource) {
+ ct = nat->ct;
if (same_src(ct, tuple)) {
/* Copy source part from reply tuple. */
nf_ct_invert_tuplepr(result,
@@ -254,7 +236,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
manips not an issue. */
if (maniptype == IP_NAT_MANIP_SRC) {
if (find_appropriate_src(orig_tuple, tuple, range)) {
- DEBUGP("get_unique_tuple: Found current src map\n");
+ pr_debug("get_unique_tuple: Found current src map\n");
if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
if (!nf_nat_used_tuple(tuple, ct))
return;
@@ -296,11 +278,20 @@ nf_nat_setup_info(struct nf_conn *ct,
unsigned int hooknum)
{
struct nf_conntrack_tuple curr_tuple, new_tuple;
- struct nf_conn_nat *nat = nfct_nat(ct);
- struct nf_nat_info *info = &nat->info;
+ struct nf_conn_nat *nat;
int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
+ /* nat helper or nfctnetlink also setup binding */
+ nat = nfct_nat(ct);
+ if (!nat) {
+ nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+ if (nat == NULL) {
+ pr_debug("failed to add NAT extension\n");
+ return NF_ACCEPT;
+ }
+ }
+
NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
hooknum == NF_IP_POST_ROUTING ||
hooknum == NF_IP_LOCAL_IN ||
@@ -337,7 +328,10 @@ nf_nat_setup_info(struct nf_conn *ct,
srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
write_lock_bh(&nf_nat_lock);
- list_add(&info->bysource, &bysource[srchash]);
+ /* nf_conntrack_alter_reply might re-allocate exntension aera */
+ nat = nfct_nat(ct);
+ nat->ct = ct;
+ hlist_add_head(&nat->bysource, &bysource[srchash]);
write_unlock_bh(&nf_nat_lock);
}
@@ -462,8 +456,9 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
return 0;
}
- DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",
- *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
+ pr_debug("icmp_reply_translation: translating error %p manip %u "
+ "dir %s\n", *pskb, manip,
+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
/* rcu_read_lock()ed by nf_hook_slow */
l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
@@ -590,17 +585,69 @@ nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range)
EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr);
#endif
+/* Noone using conntrack by the time this called. */
+static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
+{
+ struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+
+ if (nat == NULL || nat->ct == NULL)
+ return;
+
+ NF_CT_ASSERT(nat->ct->status & IPS_NAT_DONE_MASK);
+
+ write_lock_bh(&nf_nat_lock);
+ hlist_del(&nat->bysource);
+ nat->ct = NULL;
+ write_unlock_bh(&nf_nat_lock);
+}
+
+static void nf_nat_move_storage(struct nf_conn *conntrack, void *old)
+{
+ struct nf_conn_nat *new_nat = nf_ct_ext_find(conntrack, NF_CT_EXT_NAT);
+ struct nf_conn_nat *old_nat = (struct nf_conn_nat *)old;
+ struct nf_conn *ct = old_nat->ct;
+ unsigned int srchash;
+
+ if (!(ct->status & IPS_NAT_DONE_MASK))
+ return;
+
+ srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+
+ write_lock_bh(&nf_nat_lock);
+ hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource);
+ new_nat->ct = ct;
+ write_unlock_bh(&nf_nat_lock);
+}
+
+static struct nf_ct_ext_type nat_extend __read_mostly = {
+ .len = sizeof(struct nf_conn_nat),
+ .align = __alignof__(struct nf_conn_nat),
+ .destroy = nf_nat_cleanup_conntrack,
+ .move = nf_nat_move_storage,
+ .id = NF_CT_EXT_NAT,
+ .flags = NF_CT_EXT_F_PREALLOC,
+};
+
static int __init nf_nat_init(void)
{
size_t i;
+ int ret;
+
+ ret = nf_ct_extend_register(&nat_extend);
+ if (ret < 0) {
+ printk(KERN_ERR "nf_nat_core: Unable to register extension\n");
+ return ret;
+ }
/* Leave them the same for the moment. */
nf_nat_htable_size = nf_conntrack_htable_size;
- /* One vmalloc for both hash tables */
- bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size);
- if (!bysource)
- return -ENOMEM;
+ bysource = nf_ct_alloc_hashtable(&nf_nat_htable_size,
+ &nf_nat_vmalloced);
+ if (!bysource) {
+ ret = -ENOMEM;
+ goto cleanup_extend;
+ }
/* Sew in builtin protocols. */
write_lock_bh(&nf_nat_lock);
@@ -612,18 +659,18 @@ static int __init nf_nat_init(void)
write_unlock_bh(&nf_nat_lock);
for (i = 0; i < nf_nat_htable_size; i++) {
- INIT_LIST_HEAD(&bysource[i]);
+ INIT_HLIST_HEAD(&bysource[i]);
}
- /* FIXME: Man, this is a hack. <SIGH> */
- NF_CT_ASSERT(rcu_dereference(nf_conntrack_destroyed) == NULL);
- rcu_assign_pointer(nf_conntrack_destroyed, nf_nat_cleanup_conntrack);
-
/* Initialize fake conntrack so that NAT will skip it */
nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
return 0;
+
+ cleanup_extend:
+ nf_ct_extend_unregister(&nat_extend);
+ return ret;
}
/* Clear NAT section of all conntracks, in case we're loaded again. */
@@ -641,10 +688,10 @@ static int clean_nat(struct nf_conn *i, void *data)
static void __exit nf_nat_cleanup(void)
{
nf_ct_iterate_cleanup(&clean_nat, NULL);
- rcu_assign_pointer(nf_conntrack_destroyed, NULL);
synchronize_rcu();
- vfree(bysource);
+ nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
nf_ct_l3proto_put(l3proto);
+ nf_ct_extend_unregister(&nat_extend);
}
MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c
index e6bc8e5a72f..3663bd879c3 100644
--- a/net/ipv4/netfilter/nf_nat_ftp.c
+++ b/net/ipv4/netfilter/nf_nat_ftp.c
@@ -25,12 +25,6 @@ MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
MODULE_DESCRIPTION("ftp NAT helper");
MODULE_ALIAS("ip_nat_ftp");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* FIXME: Time out? --RR */
static int
@@ -47,7 +41,7 @@ mangle_rfc959_packet(struct sk_buff **pskb,
sprintf(buffer, "%u,%u,%u,%u,%u,%u",
NIPQUAD(newip), port>>8, port&0xFF);
- DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+ pr_debug("calling nf_nat_mangle_tcp_packet\n");
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer));
@@ -67,7 +61,7 @@ mangle_eprt_packet(struct sk_buff **pskb,
sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
- DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+ pr_debug("calling nf_nat_mangle_tcp_packet\n");
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer));
@@ -87,7 +81,7 @@ mangle_epsv_packet(struct sk_buff **pskb,
sprintf(buffer, "|||%u|", port);
- DEBUGP("calling nf_nat_mangle_tcp_packet\n");
+ pr_debug("calling nf_nat_mangle_tcp_packet\n");
return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
matchlen, buffer, strlen(buffer));
@@ -117,7 +111,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb,
int dir = CTINFO2DIR(ctinfo);
struct nf_conn *ct = exp->master;
- DEBUGP("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
+ pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
/* Connection will come from wherever this packet goes, hence !dir */
newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
@@ -131,7 +125,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb,
/* Try to get same port: if not, try to change it. */
for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
exp->tuple.dst.u.tcp.port = htons(port);
- if (nf_conntrack_expect_related(exp) == 0)
+ if (nf_ct_expect_related(exp) == 0)
break;
}
@@ -139,7 +133,7 @@ static unsigned int nf_nat_ftp(struct sk_buff **pskb,
return NF_DROP;
if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo)) {
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
return NF_DROP;
}
return NF_ACCEPT;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index c5d2a2d690b..c1b059a7370 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -21,12 +21,6 @@
#include <net/netfilter/nf_conntrack_expect.h>
#include <linux/netfilter/nf_conntrack_h323.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/****************************************************************************/
static int set_addr(struct sk_buff **pskb,
unsigned char **data, int dataoff,
@@ -126,12 +120,11 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
(ntohl(addr.ip) & 0xff000000) == 0x7f000000)
i = 0;
- DEBUGP
- ("nf_nat_ras: set signal address "
- "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(ip), port,
- NIPQUAD(ct->tuplehash[!dir].tuple.dst.
- ip), info->sig_port[!dir]);
+ pr_debug("nf_nat_ras: set signal address "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(addr.ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+ info->sig_port[!dir]);
return set_h225_addr(pskb, data, 0, &taddr[i],
&ct->tuplehash[!dir].
tuple.dst.u3,
@@ -139,12 +132,11 @@ static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
} else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
port == info->sig_port[dir]) {
/* GK->GW */
- DEBUGP
- ("nf_nat_ras: set signal address "
- "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(ip), port,
- NIPQUAD(ct->tuplehash[!dir].tuple.src.
- ip), info->sig_port[!dir]);
+ pr_debug("nf_nat_ras: set signal address "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(addr.ip), port,
+ NIPQUAD(ct->tuplehash[!dir].tuple.src.u3.ip),
+ info->sig_port[!dir]);
return set_h225_addr(pskb, data, 0, &taddr[i],
&ct->tuplehash[!dir].
tuple.src.u3,
@@ -171,12 +163,11 @@ static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
port == ct->tuplehash[dir].tuple.src.u.udp.port) {
- DEBUGP("nf_nat_ras: set rasAddress "
- "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(ip), ntohs(port),
- NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
- ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
- port));
+ pr_debug("nf_nat_ras: set rasAddress "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(addr.ip), ntohs(port),
+ NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
+ ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
return set_h225_addr(pskb, data, 0, &taddr[i],
&ct->tuplehash[!dir].tuple.dst.u3,
ct->tuplehash[!dir].tuple.
@@ -237,12 +228,12 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
nated_port != 0; nated_port += 2) {
rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
- if (nf_conntrack_expect_related(rtp_exp) == 0) {
+ if (nf_ct_expect_related(rtp_exp) == 0) {
rtcp_exp->tuple.dst.u.udp.port =
htons(nated_port + 1);
- if (nf_conntrack_expect_related(rtcp_exp) == 0)
+ if (nf_ct_expect_related(rtcp_exp) == 0)
break;
- nf_conntrack_unexpect_related(rtp_exp);
+ nf_ct_unexpect_related(rtp_exp);
}
}
@@ -261,22 +252,22 @@ static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
info->rtp_port[i][dir] = rtp_port;
info->rtp_port[i][!dir] = htons(nated_port);
} else {
- nf_conntrack_unexpect_related(rtp_exp);
- nf_conntrack_unexpect_related(rtcp_exp);
+ nf_ct_unexpect_related(rtp_exp);
+ nf_ct_unexpect_related(rtcp_exp);
return -1;
}
/* Success */
- DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(rtp_exp->tuple.src.ip),
- ntohs(rtp_exp->tuple.src.u.udp.port),
- NIPQUAD(rtp_exp->tuple.dst.ip),
- ntohs(rtp_exp->tuple.dst.u.udp.port));
- DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(rtcp_exp->tuple.src.ip),
- ntohs(rtcp_exp->tuple.src.u.udp.port),
- NIPQUAD(rtcp_exp->tuple.dst.ip),
- ntohs(rtcp_exp->tuple.dst.u.udp.port));
+ pr_debug("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(rtp_exp->tuple.src.u3.ip),
+ ntohs(rtp_exp->tuple.src.u.udp.port),
+ NIPQUAD(rtp_exp->tuple.dst.u3.ip),
+ ntohs(rtp_exp->tuple.dst.u.udp.port));
+ pr_debug("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(rtcp_exp->tuple.src.u3.ip),
+ ntohs(rtcp_exp->tuple.src.u.udp.port),
+ NIPQUAD(rtcp_exp->tuple.dst.u3.ip),
+ ntohs(rtcp_exp->tuple.dst.u.udp.port));
return 0;
}
@@ -299,7 +290,7 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
/* Try to get same port: if not, try to change it. */
for (; nated_port != 0; nated_port++) {
exp->tuple.dst.u.tcp.port = htons(nated_port);
- if (nf_conntrack_expect_related(exp) == 0)
+ if (nf_ct_expect_related(exp) == 0)
break;
}
@@ -313,13 +304,15 @@ static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
if (set_h245_addr(pskb, data, dataoff, taddr,
&ct->tuplehash[!dir].tuple.dst.u3,
htons(nated_port)) < 0) {
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
return -1;
}
- DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
- NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+ pr_debug("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.u3.ip),
+ ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.u3.ip),
+ ntohs(exp->tuple.dst.u.tcp.port));
return 0;
}
@@ -347,7 +340,7 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
/* Try to get same port: if not, try to change it. */
for (; nated_port != 0; nated_port++) {
exp->tuple.dst.u.tcp.port = htons(nated_port);
- if (nf_conntrack_expect_related(exp) == 0)
+ if (nf_ct_expect_related(exp) == 0)
break;
}
@@ -365,13 +358,15 @@ static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
info->sig_port[dir] = port;
info->sig_port[!dir] = htons(nated_port);
} else {
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
return -1;
}
- DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
- NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+ pr_debug("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.u3.ip),
+ ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.u3.ip),
+ ntohs(exp->tuple.dst.u.tcp.port));
return 0;
}
@@ -433,7 +428,7 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
/* Try to get same port: if not, try to change it. */
for (; nated_port != 0; nated_port++) {
exp->tuple.dst.u.tcp.port = htons(nated_port);
- if (nf_conntrack_expect_related(exp) == 0)
+ if (nf_ct_expect_related(exp) == 0)
break;
}
@@ -460,14 +455,16 @@ static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
info->sig_port[!dir]);
}
} else {
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
return -1;
}
/* Success */
- DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
- NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+ pr_debug("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.u3.ip),
+ ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.u3.ip),
+ ntohs(exp->tuple.dst.u.tcp.port));
return 0;
}
@@ -517,7 +514,7 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
/* Try to get same port: if not, try to change it. */
for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
exp->tuple.dst.u.tcp.port = htons(nated_port);
- if (nf_conntrack_expect_related(exp) == 0)
+ if (nf_ct_expect_related(exp) == 0)
break;
}
@@ -531,15 +528,17 @@ static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
if (!set_h225_addr(pskb, data, dataoff, taddr,
&ct->tuplehash[!dir].tuple.dst.u3,
htons(nated_port)) == 0) {
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
return -1;
}
/* Success */
- DEBUGP("nf_nat_q931: expect Call Forwarding "
- "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
- NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
- NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+ pr_debug("nf_nat_q931: expect Call Forwarding "
+ "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+ NIPQUAD(exp->tuple.src.u3.ip),
+ ntohs(exp->tuple.src.u.tcp.port),
+ NIPQUAD(exp->tuple.dst.u3.ip),
+ ntohs(exp->tuple.dst.u.tcp.port));
return 0;
}
@@ -566,8 +565,6 @@ static int __init init(void)
rcu_assign_pointer(nat_h245_hook, nat_h245);
rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
rcu_assign_pointer(nat_q931_hook, nat_q931);
-
- DEBUGP("nf_nat_h323: init success\n");
return 0;
}
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 15b6e5ce3a0..93d8a0a8f03 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -26,13 +26,9 @@
#include <net/netfilter/nf_nat_core.h>
#include <net/netfilter/nf_nat_helper.h>
-#if 0
-#define DEBUGP printk
-#define DUMP_OFFSET(x) printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
-#else
-#define DEBUGP(format, args...)
-#define DUMP_OFFSET(x)
-#endif
+#define DUMP_OFFSET(x) \
+ pr_debug("offset_before=%d, offset_after=%d, correction_pos=%u\n", \
+ x->offset_before, x->offset_after, x->correction_pos);
static DEFINE_SPINLOCK(nf_nat_seqofs_lock);
@@ -47,15 +43,15 @@ adjust_tcp_sequence(u32 seq,
struct nf_nat_seq *this_way, *other_way;
struct nf_conn_nat *nat = nfct_nat(ct);
- DEBUGP("nf_nat_resize_packet: old_size = %u, new_size = %u\n",
- (*skb)->len, new_size);
+ pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n",
+ ntohl(seq), seq);
dir = CTINFO2DIR(ctinfo);
- this_way = &nat->info.seq[dir];
- other_way = &nat->info.seq[!dir];
+ this_way = &nat->seq[dir];
+ other_way = &nat->seq[!dir];
- DEBUGP("nf_nat_resize_packet: Seq_offset before: ");
+ pr_debug("nf_nat_resize_packet: Seq_offset before: ");
DUMP_OFFSET(this_way);
spin_lock_bh(&nf_nat_seqofs_lock);
@@ -72,7 +68,7 @@ adjust_tcp_sequence(u32 seq,
}
spin_unlock_bh(&nf_nat_seqofs_lock);
- DEBUGP("nf_nat_resize_packet: Seq_offset after: ");
+ pr_debug("nf_nat_resize_packet: Seq_offset after: ");
DUMP_OFFSET(this_way);
}
@@ -100,14 +96,12 @@ static void mangle_contents(struct sk_buff *skb,
/* update skb info */
if (rep_len > match_len) {
- DEBUGP("nf_nat_mangle_packet: Extending packet by "
- "%u from %u bytes\n", rep_len - match_len,
- skb->len);
+ pr_debug("nf_nat_mangle_packet: Extending packet by "
+ "%u from %u bytes\n", rep_len - match_len, skb->len);
skb_put(skb, rep_len - match_len);
} else {
- DEBUGP("nf_nat_mangle_packet: Shrinking packet from "
- "%u from %u bytes\n", match_len - rep_len,
- skb->len);
+ pr_debug("nf_nat_mangle_packet: Shrinking packet from "
+ "%u from %u bytes\n", match_len - rep_len, skb->len);
__skb_trim(skb, skb->len + rep_len - match_len);
}
@@ -178,7 +172,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
datalen = (*pskb)->len - iph->ihl*4;
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
if (!(rt->rt_flags & RTCF_LOCAL) &&
- (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
+ (*pskb)->dev->features & NETIF_F_V4_CSUM) {
(*pskb)->ip_summed = CHECKSUM_PARTIAL;
(*pskb)->csum_start = skb_headroom(*pskb) +
skb_network_offset(*pskb) +
@@ -190,7 +184,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
tcph->check = 0;
tcph->check = tcp_v4_check(datalen,
iph->saddr, iph->daddr,
- csum_partial((char *)tcph,
+ csum_partial(tcph,
datalen, 0));
}
} else
@@ -265,7 +259,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
if (!(rt->rt_flags & RTCF_LOCAL) &&
- (*pskb)->dev->features & NETIF_F_ALL_CSUM) {
+ (*pskb)->dev->features & NETIF_F_V4_CSUM) {
(*pskb)->ip_summed = CHECKSUM_PARTIAL;
(*pskb)->csum_start = skb_headroom(*pskb) +
skb_network_offset(*pskb) +
@@ -278,7 +272,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
udph->check = 0;
udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
datalen, IPPROTO_UDP,
- csum_partial((char *)udph,
+ csum_partial(udph,
datalen, 0));
if (!udph->check)
udph->check = CSUM_MANGLED_0;
@@ -320,9 +314,9 @@ sack_adjust(struct sk_buff *skb,
new_end_seq = htonl(ntohl(sack->end_seq)
- natseq->offset_before);
- DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
- ntohl(sack->start_seq), new_start_seq,
- ntohl(sack->end_seq), new_end_seq);
+ pr_debug("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
+ ntohl(sack->start_seq), new_start_seq,
+ ntohl(sack->end_seq), new_end_seq);
nf_proto_csum_replace4(&tcph->check, skb,
sack->start_seq, new_start_seq, 0);
@@ -372,8 +366,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb,
op[1] >= 2+TCPOLEN_SACK_PERBLOCK &&
((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
sack_adjust(*pskb, tcph, optoff+2,
- optoff+op[1],
- &nat->info.seq[!dir]);
+ optoff+op[1], &nat->seq[!dir]);
optoff += op[1];
}
}
@@ -394,8 +387,8 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
dir = CTINFO2DIR(ctinfo);
- this_way = &nat->info.seq[dir];
- other_way = &nat->info.seq[!dir];
+ this_way = &nat->seq[dir];
+ other_way = &nat->seq[!dir];
if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
return 0;
@@ -415,9 +408,9 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
- DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
- ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
- ntohl(newack));
+ pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n",
+ ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
+ ntohl(newack));
tcph->seq = newseq;
tcph->ack_seq = newack;
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c
index 9b8c0daea74..bcf274bba60 100644
--- a/net/ipv4/netfilter/nf_nat_irc.c
+++ b/net/ipv4/netfilter/nf_nat_irc.c
@@ -22,12 +22,6 @@
#include <net/netfilter/nf_conntrack_expect.h>
#include <linux/netfilter/nf_conntrack_irc.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("IRC (DCC) NAT helper");
MODULE_LICENSE("GPL");
@@ -44,9 +38,6 @@ static unsigned int help(struct sk_buff **pskb,
u_int16_t port;
unsigned int ret;
- DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
- expect->seq, exp_irc_info->len, ntohl(tcph->seq));
-
/* Reply comes from server. */
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
exp->dir = IP_CT_DIR_REPLY;
@@ -55,7 +46,7 @@ static unsigned int help(struct sk_buff **pskb,
/* Try to get same port: if not, try to change it. */
for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
exp->tuple.dst.u.tcp.port = htons(port);
- if (nf_conntrack_expect_related(exp) == 0)
+ if (nf_ct_expect_related(exp) == 0)
break;
}
@@ -64,14 +55,14 @@ static unsigned int help(struct sk_buff **pskb,
ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
sprintf(buffer, "%u %u", ip, port);
- DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
- buffer, NIPQUAD(ip), port);
+ pr_debug("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
+ buffer, NIPQUAD(ip), port);
ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
matchoff, matchlen, buffer,
strlen(buffer));
if (ret != NF_ACCEPT)
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
return ret;
}
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index a66888749ce..984ec8308b2 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -37,14 +37,6 @@ MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
MODULE_ALIAS("ip_nat_pptp");
-#if 0
-extern const char *pptp_msg_name[];
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
- __FUNCTION__, ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
static void pptp_nat_expected(struct nf_conn *ct,
struct nf_conntrack_expect *exp)
{
@@ -60,7 +52,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
/* And here goes the grand finale of corrosion... */
if (exp->dir == IP_CT_DIR_ORIGINAL) {
- DEBUGP("we are PNS->PAC\n");
+ pr_debug("we are PNS->PAC\n");
/* therefore, build tuple for PAC->PNS */
t.src.l3num = AF_INET;
t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
@@ -69,7 +61,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
t.dst.u.gre.key = ct_pptp_info->pns_call_id;
t.dst.protonum = IPPROTO_GRE;
} else {
- DEBUGP("we are PAC->PNS\n");
+ pr_debug("we are PAC->PNS\n");
/* build tuple for PNS->PAC */
t.src.l3num = AF_INET;
t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
@@ -79,15 +71,15 @@ static void pptp_nat_expected(struct nf_conn *ct,
t.dst.protonum = IPPROTO_GRE;
}
- DEBUGP("trying to unexpect other dir: ");
+ pr_debug("trying to unexpect other dir: ");
NF_CT_DUMP_TUPLE(&t);
- other_exp = nf_conntrack_expect_find_get(&t);
+ other_exp = nf_ct_expect_find_get(&t);
if (other_exp) {
- nf_conntrack_unexpect_related(other_exp);
- nf_conntrack_expect_put(other_exp);
- DEBUGP("success\n");
+ nf_ct_unexpect_related(other_exp);
+ nf_ct_expect_put(other_exp);
+ pr_debug("success\n");
} else {
- DEBUGP("not found!\n");
+ pr_debug("not found!\n");
}
/* This must be a fresh one. */
@@ -161,9 +153,9 @@ pptp_outbound_pkt(struct sk_buff **pskb,
cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
break;
default:
- DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
- (msg <= PPTP_MSG_MAX)?
- pptp_msg_name[msg]:pptp_msg_name[0]);
+ pr_debug("unknown outbound packet 0x%04x:%s\n", msg,
+ msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] :
+ pptp_msg_name[0]);
/* fall through */
case PPTP_SET_LINK_INFO:
/* only need to NAT in case PAC is behind NAT box */
@@ -179,8 +171,8 @@ pptp_outbound_pkt(struct sk_buff **pskb,
/* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
* down to here */
- DEBUGP("altering call id from 0x%04x to 0x%04x\n",
- ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
+ pr_debug("altering call id from 0x%04x to 0x%04x\n",
+ ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
/* mangle packet */
if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
@@ -255,8 +247,9 @@ pptp_inbound_pkt(struct sk_buff **pskb,
pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
break;
default:
- DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)?
- pptp_msg_name[msg]:pptp_msg_name[0]);
+ pr_debug("unknown inbound packet %s\n",
+ msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] :
+ pptp_msg_name[0]);
/* fall through */
case PPTP_START_SESSION_REQUEST:
case PPTP_START_SESSION_REPLY:
@@ -272,8 +265,8 @@ pptp_inbound_pkt(struct sk_buff **pskb,
* WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
/* mangle packet */
- DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
- ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
+ pr_debug("altering peer call id from 0x%04x to 0x%04x\n",
+ ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
pcid_off + sizeof(struct pptp_pkt_hdr) +
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
index c3908bc5a70..2e40cc83526 100644
--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -36,13 +36,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
-#if 0
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
- __FUNCTION__, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
/* is key in given range between min and max */
static int
gre_in_range(const struct nf_conntrack_tuple *tuple,
@@ -83,7 +76,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
keyptr = &tuple->dst.u.gre.key;
if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
- DEBUGP("%p: NATing GRE PPTP\n", conntrack);
+ pr_debug("%p: NATing GRE PPTP\n", conntrack);
min = 1;
range_size = 0xffff;
} else {
@@ -91,7 +84,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
range_size = ntohs(range->max.gre.key) - min + 1;
}
- DEBUGP("min = %u, range_size = %u\n", min, range_size);
+ pr_debug("min = %u, range_size = %u\n", min, range_size);
for (i = 0; i < range_size; i++, key++) {
*keyptr = htons(min + key % range_size);
@@ -99,7 +92,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
return 1;
}
- DEBUGP("%p: no NAT mapping\n", conntrack);
+ pr_debug("%p: no NAT mapping\n", conntrack);
return 0;
}
@@ -132,11 +125,11 @@ gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff,
* Try to behave like "nf_nat_proto_unknown" */
break;
case GRE_VERSION_PPTP:
- DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
+ pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
pgreh->call_id = tuple->dst.u.gre.key;
break;
default:
- DEBUGP("can't nat unknown GRE version\n");
+ pr_debug("can't nat unknown GRE version\n");
return 0;
}
return 1;
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 6740736c5e7..0f45427e5fd 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -24,12 +24,6 @@
#include <net/netfilter/nf_nat_core.h>
#include <net/netfilter/nf_nat_rule.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
#define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
static struct
@@ -140,39 +134,39 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
return nf_nat_setup_info(ct, &mr->range[0], hooknum);
}
-static int ipt_snat_checkentry(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool ipt_snat_checkentry(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
{
struct nf_nat_multi_range_compat *mr = targinfo;
/* Must be a valid range */
if (mr->rangesize != 1) {
printk("SNAT: multiple ranges no longer supported\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int ipt_dnat_checkentry(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool ipt_dnat_checkentry(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
{
struct nf_nat_multi_range_compat *mr = targinfo;
/* Must be a valid range */
if (mr->rangesize != 1) {
printk("DNAT: multiple ranges no longer supported\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-inline unsigned int
+unsigned int
alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
{
/* Force range to this IP; let proto decide mapping for
@@ -186,8 +180,8 @@ alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
struct nf_nat_range range
= { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
- DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
- ct, NIPQUAD(ip));
+ pr_debug("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
+ ct, NIPQUAD(ip));
return nf_nat_setup_info(ct, &range, hooknum);
}
@@ -205,8 +199,8 @@ alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
struct nf_nat_range range
= { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
- DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
- ct, NIPQUAD(ip));
+ pr_debug("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
+ ct, NIPQUAD(ip));
return nf_nat_setup_info(ct, &range, hooknum);
}
@@ -228,7 +222,7 @@ int nf_nat_rule_find(struct sk_buff **pskb,
return ret;
}
-static struct xt_target ipt_snat_reg = {
+static struct xt_target ipt_snat_reg __read_mostly = {
.name = "SNAT",
.target = ipt_snat_target,
.targetsize = sizeof(struct nf_nat_multi_range_compat),
@@ -238,7 +232,7 @@ static struct xt_target ipt_snat_reg = {
.family = AF_INET,
};
-static struct xt_target ipt_dnat_reg = {
+static struct xt_target ipt_dnat_reg __read_mostly = {
.name = "DNAT",
.target = ipt_dnat_target,
.targetsize = sizeof(struct nf_nat_multi_range_compat),
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index fac97cf51ae..a889ec3ec83 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -26,12 +26,6 @@ MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
MODULE_DESCRIPTION("SIP NAT helper");
MODULE_ALIAS("ip_nat_sip");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
struct addr_map {
struct {
char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
@@ -257,10 +251,12 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb,
__be32 newip;
u_int16_t port;
- DEBUGP("ip_nat_sdp():\n");
-
/* Connection will come from reply */
- newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
+ if (ct->tuplehash[dir].tuple.src.u3.ip ==
+ ct->tuplehash[!dir].tuple.dst.u3.ip)
+ newip = exp->tuple.dst.u3.ip;
+ else
+ newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
exp->saved_ip = exp->tuple.dst.u3.ip;
exp->tuple.dst.u3.ip = newip;
@@ -274,7 +270,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb,
/* Try to get same port: if not, try to change it. */
for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
exp->tuple.dst.u.udp.port = htons(port);
- if (nf_conntrack_expect_related(exp) == 0)
+ if (nf_ct_expect_related(exp) == 0)
break;
}
@@ -282,7 +278,7 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb,
return NF_DROP;
if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
return NF_DROP;
}
return NF_ACCEPT;
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 6e88505d616..6bfcd3a90f0 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -1276,9 +1276,6 @@ static struct nf_conntrack_helper snmp_helper __read_mostly = {
.tuple.src.l3num = AF_INET,
.tuple.src.u.udp.port = __constant_htons(SNMP_PORT),
.tuple.dst.protonum = IPPROTO_UDP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.udp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
};
static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
@@ -1290,9 +1287,6 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
.tuple.src.l3num = AF_INET,
.tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT),
.tuple.dst.protonum = IPPROTO_UDP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.udp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
};
/*****************************************************************************
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 55dac36dbc8..332814dac50 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -19,6 +19,7 @@
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_nat.h>
#include <net/netfilter/nf_nat_rule.h>
#include <net/netfilter/nf_nat_protocol.h>
@@ -26,12 +27,6 @@
#include <net/netfilter/nf_nat_helper.h>
#include <linux/netfilter_ipv4/ip_tables.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
#ifdef CONFIG_XFRM
static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
{
@@ -113,8 +108,13 @@ nf_nat_fn(unsigned int hooknum,
return NF_ACCEPT;
nat = nfct_nat(ct);
- if (!nat)
- return NF_ACCEPT;
+ if (!nat) {
+ nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
+ if (nat == NULL) {
+ pr_debug("failed to add NAT extension\n");
+ return NF_ACCEPT;
+ }
+ }
switch (ctinfo) {
case IP_CT_RELATED:
@@ -148,9 +148,9 @@ nf_nat_fn(unsigned int hooknum,
return ret;
}
} else
- DEBUGP("Already setup manip %s for ct %p\n",
- maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
- ct);
+ pr_debug("Already setup manip %s for ct %p\n",
+ maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
+ ct);
break;
default:
@@ -264,7 +264,7 @@ nf_nat_adjust(unsigned int hooknum,
ct = nf_ct_get(*pskb, &ctinfo);
if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
- DEBUGP("nf_nat_standalone: adjusting sequence number\n");
+ pr_debug("nf_nat_standalone: adjusting sequence number\n");
if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
return NF_DROP;
}
@@ -326,26 +326,10 @@ static struct nf_hook_ops nf_nat_ops[] = {
static int __init nf_nat_standalone_init(void)
{
- int size, ret = 0;
+ int ret = 0;
need_conntrack();
- size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
- sizeof(struct nf_conn_nat);
- ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
- if (ret < 0) {
- printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
- return ret;
- }
-
- size = ALIGN(size, __alignof__(struct nf_conn_help)) +
- sizeof(struct nf_conn_help);
- ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP,
- "nf_nat:help", size);
- if (ret < 0) {
- printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
- goto cleanup_register_cache;
- }
#ifdef CONFIG_XFRM
BUG_ON(ip_nat_decode_session != NULL);
ip_nat_decode_session = nat_decode_session;
@@ -360,7 +344,6 @@ static int __init nf_nat_standalone_init(void)
printk("nf_nat_init: can't register hooks.\n");
goto cleanup_rule_init;
}
- nf_nat_module_is_loaded = 1;
return ret;
cleanup_rule_init:
@@ -370,9 +353,6 @@ static int __init nf_nat_standalone_init(void)
ip_nat_decode_session = NULL;
synchronize_net();
#endif
- nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP);
- cleanup_register_cache:
- nf_conntrack_unregister_cache(NF_CT_F_NAT);
return ret;
}
@@ -380,7 +360,6 @@ static void __exit nf_nat_standalone_fini(void)
{
nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
nf_nat_rule_cleanup();
- nf_nat_module_is_loaded = 0;
#ifdef CONFIG_XFRM
ip_nat_decode_session = NULL;
synchronize_net();
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c
index 2566b79de22..04dfeaefec0 100644
--- a/net/ipv4/netfilter/nf_nat_tftp.c
+++ b/net/ipv4/netfilter/nf_nat_tftp.c
@@ -30,7 +30,7 @@ static unsigned int help(struct sk_buff **pskb,
= ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
exp->dir = IP_CT_DIR_REPLY;
exp->expectfn = nf_nat_follow_master;
- if (nf_conntrack_expect_related(exp) != 0)
+ if (nf_ct_expect_related(exp) != 0)
return NF_DROP;
return NF_ACCEPT;
}
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index cdbc6c13584..3b690cf2a4e 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -260,7 +260,7 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
seq_printf(seq, "\nIp: %d %d",
- ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
+ IPV4_DEVCONF_ALL(FORWARDING) ? 1 : 2, sysctl_ip_default_ttl);
for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
seq_printf(seq, " %lu",
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 8603cfb271f..88fa648d7ba 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -101,7 +101,6 @@
#include <net/tcp.h>
#include <net/icmp.h>
#include <net/xfrm.h>
-#include <net/ip_mp_alg.h>
#include <net/netevent.h>
#include <net/rtnetlink.h>
#ifdef CONFIG_SYSCTL
@@ -168,7 +167,7 @@ static struct dst_ops ipv4_dst_ops = {
#define ECN_OR_COST(class) TC_PRIO_##class
-__u8 ip_tos2prio[16] = {
+const __u8 ip_tos2prio[16] = {
TC_PRIO_BESTEFFORT,
ECN_OR_COST(FILLER),
TC_PRIO_BESTEFFORT,
@@ -495,13 +494,11 @@ static const struct file_operations rt_cpu_seq_fops = {
static __inline__ void rt_free(struct rtable *rt)
{
- multipath_remove(rt);
call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
}
static __inline__ void rt_drop(struct rtable *rt)
{
- multipath_remove(rt);
ip_rt_put(rt);
call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
}
@@ -574,52 +571,6 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
(fl1->iif ^ fl2->iif)) == 0;
}
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-static struct rtable **rt_remove_balanced_route(struct rtable **chain_head,
- struct rtable *expentry,
- int *removed_count)
-{
- int passedexpired = 0;
- struct rtable **nextstep = NULL;
- struct rtable **rthp = chain_head;
- struct rtable *rth;
-
- if (removed_count)
- *removed_count = 0;
-
- while ((rth = *rthp) != NULL) {
- if (rth == expentry)
- passedexpired = 1;
-
- if (((*rthp)->u.dst.flags & DST_BALANCED) != 0 &&
- compare_keys(&(*rthp)->fl, &expentry->fl)) {
- if (*rthp == expentry) {
- *rthp = rth->u.dst.rt_next;
- continue;
- } else {
- *rthp = rth->u.dst.rt_next;
- rt_free(rth);
- if (removed_count)
- ++(*removed_count);
- }
- } else {
- if (!((*rthp)->u.dst.flags & DST_BALANCED) &&
- passedexpired && !nextstep)
- nextstep = &rth->u.dst.rt_next;
-
- rthp = &rth->u.dst.rt_next;
- }
- }
-
- rt_free(expentry);
- if (removed_count)
- ++(*removed_count);
-
- return nextstep;
-}
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-
-
/* This runs via a timer and thus is always in BH context. */
static void rt_check_expire(unsigned long dummy)
{
@@ -658,22 +609,8 @@ static void rt_check_expire(unsigned long dummy)
}
/* Cleanup aged off entries. */
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- /* remove all related balanced entries if necessary */
- if (rth->u.dst.flags & DST_BALANCED) {
- rthp = rt_remove_balanced_route(
- &rt_hash_table[i].chain,
- rth, NULL);
- if (!rthp)
- break;
- } else {
- *rthp = rth->u.dst.rt_next;
- rt_free(rth);
- }
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
*rthp = rth->u.dst.rt_next;
rt_free(rth);
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
}
spin_unlock(rt_hash_lock_addr(i));
@@ -721,9 +658,6 @@ void rt_cache_flush(int delay)
if (delay < 0)
delay = ip_rt_min_delay;
- /* flush existing multipath state*/
- multipath_flush();
-
spin_lock_bh(&rt_flush_lock);
if (del_timer(&rt_flush_timer) && delay > 0 && rt_deadline) {
@@ -842,30 +776,9 @@ static int rt_garbage_collect(void)
rthp = &rth->u.dst.rt_next;
continue;
}
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- /* remove all related balanced entries
- * if necessary
- */
- if (rth->u.dst.flags & DST_BALANCED) {
- int r;
-
- rthp = rt_remove_balanced_route(
- &rt_hash_table[k].chain,
- rth,
- &r);
- goal -= r;
- if (!rthp)
- break;
- } else {
- *rthp = rth->u.dst.rt_next;
- rt_free(rth);
- goal--;
- }
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
*rthp = rth->u.dst.rt_next;
rt_free(rth);
goal--;
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
}
spin_unlock_bh(rt_hash_lock_addr(k));
if (goal <= 0)
@@ -939,12 +852,7 @@ restart:
spin_lock_bh(rt_hash_lock_addr(hash));
while ((rth = *rthp) != NULL) {
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- if (!(rth->u.dst.flags & DST_BALANCED) &&
- compare_keys(&rth->fl, &rt->fl)) {
-#else
if (compare_keys(&rth->fl, &rt->fl)) {
-#endif
/* Put it first */
*rthp = rth->u.dst.rt_next;
/*
@@ -1636,7 +1544,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST;
- if (in_dev->cnf.no_policy)
+ if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
@@ -1774,13 +1682,9 @@ static inline int __mkroute_input(struct sk_buff *skb,
atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- if (res->fi->fib_nhs > 1)
- rth->u.dst.flags |= DST_BALANCED;
-#endif
- if (in_dev->cnf.no_policy)
+ if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY;
- if (out_dev->cnf.no_xfrm)
+ if (IN_DEV_CONF_GET(out_dev, NOXFRM))
rth->u.dst.flags |= DST_NOXFRM;
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
@@ -1812,11 +1716,11 @@ static inline int __mkroute_input(struct sk_buff *skb,
return err;
}
-static inline int ip_mkroute_input_def(struct sk_buff *skb,
- struct fib_result* res,
- const struct flowi *fl,
- struct in_device *in_dev,
- __be32 daddr, __be32 saddr, u32 tos)
+static inline int ip_mkroute_input(struct sk_buff *skb,
+ struct fib_result* res,
+ const struct flowi *fl,
+ struct in_device *in_dev,
+ __be32 daddr, __be32 saddr, u32 tos)
{
struct rtable* rth = NULL;
int err;
@@ -1837,63 +1741,6 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb,
return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
}
-static inline int ip_mkroute_input(struct sk_buff *skb,
- struct fib_result* res,
- const struct flowi *fl,
- struct in_device *in_dev,
- __be32 daddr, __be32 saddr, u32 tos)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- struct rtable* rth = NULL, *rtres;
- unsigned char hop, hopcount;
- int err = -EINVAL;
- unsigned int hash;
-
- if (res->fi)
- hopcount = res->fi->fib_nhs;
- else
- hopcount = 1;
-
- /* distinguish between multipath and singlepath */
- if (hopcount < 2)
- return ip_mkroute_input_def(skb, res, fl, in_dev, daddr,
- saddr, tos);
-
- /* add all alternatives to the routing cache */
- for (hop = 0; hop < hopcount; hop++) {
- res->nh_sel = hop;
-
- /* put reference to previous result */
- if (hop)
- ip_rt_put(rtres);
-
- /* create a routing cache entry */
- err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos,
- &rth);
- if (err)
- return err;
-
- /* put it into the cache */
- hash = rt_hash(daddr, saddr, fl->iif);
- err = rt_intern_hash(hash, rth, &rtres);
- if (err)
- return err;
-
- /* forward hop information to multipath impl. */
- multipath_set_nhinfo(rth,
- FIB_RES_NETWORK(*res),
- FIB_RES_NETMASK(*res),
- res->prefixlen,
- &FIB_RES_NH(*res));
- }
- skb->dst = &rtres->u.dst;
- return err;
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
- return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
-#endif /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
-}
-
-
/*
* NOTE. We drop all the packets that has local source
* addresses, because every properly looped back packet
@@ -2021,7 +1868,7 @@ local_input:
atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST;
- if (in_dev->cnf.no_policy)
+ if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = daddr;
rth->rt_dst = daddr;
@@ -2211,16 +2058,9 @@ static inline int __mkroute_output(struct rtable **result,
atomic_set(&rth->u.dst.__refcnt, 1);
rth->u.dst.flags= DST_HOST;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- if (res->fi) {
- rth->rt_multipath_alg = res->fi->fib_mp_alg;
- if (res->fi->fib_nhs > 1)
- rth->u.dst.flags |= DST_BALANCED;
- }
-#endif
- if (in_dev->cnf.no_xfrm)
+ if (IN_DEV_CONF_GET(in_dev, NOXFRM))
rth->u.dst.flags |= DST_NOXFRM;
- if (in_dev->cnf.no_policy)
+ if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
rth->u.dst.flags |= DST_NOPOLICY;
rth->fl.fl4_dst = oldflp->fl4_dst;
@@ -2277,12 +2117,12 @@ static inline int __mkroute_output(struct rtable **result,
return err;
}
-static inline int ip_mkroute_output_def(struct rtable **rp,
- struct fib_result* res,
- const struct flowi *fl,
- const struct flowi *oldflp,
- struct net_device *dev_out,
- unsigned flags)
+static inline int ip_mkroute_output(struct rtable **rp,
+ struct fib_result* res,
+ const struct flowi *fl,
+ const struct flowi *oldflp,
+ struct net_device *dev_out,
+ unsigned flags)
{
struct rtable *rth = NULL;
int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
@@ -2295,68 +2135,6 @@ static inline int ip_mkroute_output_def(struct rtable **rp,
return err;
}
-static inline int ip_mkroute_output(struct rtable** rp,
- struct fib_result* res,
- const struct flowi *fl,
- const struct flowi *oldflp,
- struct net_device *dev_out,
- unsigned flags)
-{
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- unsigned char hop;
- unsigned hash;
- int err = -EINVAL;
- struct rtable *rth = NULL;
-
- if (res->fi && res->fi->fib_nhs > 1) {
- unsigned char hopcount = res->fi->fib_nhs;
-
- for (hop = 0; hop < hopcount; hop++) {
- struct net_device *dev2nexthop;
-
- res->nh_sel = hop;
-
- /* hold a work reference to the output device */
- dev2nexthop = FIB_RES_DEV(*res);
- dev_hold(dev2nexthop);
-
- /* put reference to previous result */
- if (hop)
- ip_rt_put(*rp);
-
- err = __mkroute_output(&rth, res, fl, oldflp,
- dev2nexthop, flags);
-
- if (err != 0)
- goto cleanup;
-
- hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src,
- oldflp->oif);
- err = rt_intern_hash(hash, rth, rp);
-
- /* forward hop information to multipath impl. */
- multipath_set_nhinfo(rth,
- FIB_RES_NETWORK(*res),
- FIB_RES_NETMASK(*res),
- res->prefixlen,
- &FIB_RES_NH(*res));
- cleanup:
- /* release work reference to output device */
- dev_put(dev2nexthop);
-
- if (err != 0)
- return err;
- }
- return err;
- } else {
- return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out,
- flags);
- }
-#else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */
- return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);
-#endif
-}
-
/*
* Major route resolver routine.
*/
@@ -2570,17 +2348,6 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
rth->fl.mark == flp->mark &&
!((rth->fl.fl4_tos ^ flp->fl4_tos) &
(IPTOS_RT_MASK | RTO_ONLINK))) {
-
- /* check for multipath routes and choose one if
- * necessary
- */
- if (multipath_select_route(flp, rth, rp)) {
- dst_hold(&(*rp)->u.dst);
- RT_CACHE_STAT_INC(out_hit);
- rcu_read_unlock_bh();
- return 0;
- }
-
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
@@ -2729,10 +2496,6 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
if (rt->u.dst.tclassid)
NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid);
#endif
-#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- if (rt->rt_multipath_alg != IP_MP_ALG_NONE)
- NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg);
-#endif
if (rt->fl.iif)
NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
else if (rt->rt_src != rt->fl.fl4_src)
@@ -2759,7 +2522,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
__be32 dst = rt->rt_dst;
if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
- ipv4_devconf.mc_forwarding) {
+ IPV4_DEVCONF_ALL(MC_FORWARDING)) {
int err = ipmr_get_route(skb, r, nowait);
if (err <= 0) {
if (!nowait) {
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 6817d6485df..53ef0f4bbda 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -37,12 +37,12 @@ static
int ipv4_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- int val = ipv4_devconf.forwarding;
+ int val = IPV4_DEVCONF_ALL(FORWARDING);
int ret;
ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
- if (write && ipv4_devconf.forwarding != val)
+ if (write && IPV4_DEVCONF_ALL(FORWARDING) != val)
inet_forward_change();
return ret;
@@ -222,7 +222,7 @@ ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_FORWARD,
.procname = "ip_forward",
- .data = &ipv4_devconf.forwarding,
+ .data = &IPV4_DEVCONF_ALL(FORWARDING),
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &ipv4_sysctl_forward,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index bd4c295f5d7..987b94403be 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1064,7 +1064,11 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
break;
}
used = recv_actor(desc, skb, offset, len);
- if (used <= len) {
+ if (used < 0) {
+ if (!copied)
+ copied = used;
+ break;
+ } else if (used <= len) {
seq += used;
copied += used;
offset += used;
@@ -1086,7 +1090,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
tcp_rcv_space_adjust(sk);
/* Clean up data we have read: This will do ACK frames. */
- if (copied)
+ if (copied > 0)
tcp_cleanup_rbuf(sk, copied);
return copied;
}
@@ -1112,6 +1116,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
long timeo;
struct task_struct *user_recv = NULL;
int copied_early = 0;
+ struct sk_buff *skb;
lock_sock(sk);
@@ -1138,16 +1143,26 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
#ifdef CONFIG_NET_DMA
tp->ucopy.dma_chan = NULL;
preempt_disable();
- if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
- !sysctl_tcp_low_latency && __get_cpu_var(softnet_data).net_dma) {
- preempt_enable_no_resched();
- tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len);
- } else
- preempt_enable_no_resched();
+ skb = skb_peek_tail(&sk->sk_receive_queue);
+ {
+ int available = 0;
+
+ if (skb)
+ available = TCP_SKB_CB(skb)->seq + skb->len - (*seq);
+ if ((available < target) &&
+ (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
+ !sysctl_tcp_low_latency &&
+ __get_cpu_var(softnet_data).net_dma) {
+ preempt_enable_no_resched();
+ tp->ucopy.pinned_list =
+ dma_pin_iovec_pages(msg->msg_iov, len);
+ } else {
+ preempt_enable_no_resched();
+ }
+ }
#endif
do {
- struct sk_buff *skb;
u32 offset;
/* Are we at urgent data? Stop if we have read anything or have SIGURG pending. */
@@ -1435,7 +1450,6 @@ skip_copy:
#ifdef CONFIG_NET_DMA
if (tp->ucopy.dma_chan) {
- struct sk_buff *skb;
dma_cookie_t done, used;
dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
@@ -1674,9 +1688,8 @@ adjudge_to_death:
}
if (sk->sk_state != TCP_CLOSE) {
sk_stream_mem_reclaim(sk);
- if (atomic_read(sk->sk_prot->orphan_count) > sysctl_tcp_max_orphans ||
- (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
- atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+ if (tcp_too_many_orphans(sk,
+ atomic_read(sk->sk_prot->orphan_count))) {
if (net_ratelimit())
printk(KERN_INFO "TCP: too many of orphaned "
"sockets\n");
@@ -2465,13 +2478,10 @@ void __init tcp_init(void)
order++)
;
if (order >= 4) {
- sysctl_local_port_range[0] = 32768;
- sysctl_local_port_range[1] = 61000;
tcp_death_row.sysctl_max_tw_buckets = 180000;
sysctl_tcp_max_orphans = 4096 << (order - 4);
sysctl_max_syn_backlog = 1024;
} else if (order < 3) {
- sysctl_local_port_range[0] = 1024 * (3 - order);
tcp_death_row.sysctl_max_tw_buckets >>= (3 - order);
sysctl_tcp_max_orphans >>= (3 - order);
sysctl_max_syn_backlog = 128;
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index 281c9f91325..dd9ef65ad3f 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -29,7 +29,7 @@ static int fast_convergence = 1;
static int max_increment = 16;
static int low_window = 14;
static int beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
-static int initial_ssthresh = 100;
+static int initial_ssthresh;
static int smooth_part = 20;
module_param(fast_convergence, int, 0644);
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 14224487b16..ebfaac2f9f4 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -29,7 +29,7 @@
static int fast_convergence __read_mostly = 1;
static int max_increment __read_mostly = 16;
static int beta __read_mostly = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
-static int initial_ssthresh __read_mostly = 100;
+static int initial_ssthresh __read_mostly;
static int bic_scale __read_mostly = 41;
static int tcp_friendliness __read_mostly = 1;
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c
index 4adc47c5535..b2b2256d3b8 100644
--- a/net/ipv4/tcp_illinois.c
+++ b/net/ipv4/tcp_illinois.c
@@ -90,6 +90,9 @@ static void tcp_illinois_acked(struct sock *sk, u32 pkts_acked, ktime_t last)
ca->acked = pkts_acked;
+ if (ktime_equal(last, net_invalid_timestamp()))
+ return;
+
rtt = ktime_to_us(net_timedelta(last));
/* ignore bogus values, this prevents wraparound in alpha math */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 38cb25b48bf..4e5884ac8f2 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -953,7 +953,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
int prior_fackets;
u32 lost_retrans = 0;
int flag = 0;
- int dup_sack = 0;
+ int found_dup_sack = 0;
int cached_fack_count;
int i;
int first_sack_index;
@@ -964,20 +964,20 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
/* Check for D-SACK. */
if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) {
- dup_sack = 1;
+ found_dup_sack = 1;
tp->rx_opt.sack_ok |= 4;
NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV);
} else if (num_sacks > 1 &&
!after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) &&
!before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) {
- dup_sack = 1;
+ found_dup_sack = 1;
tp->rx_opt.sack_ok |= 4;
NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV);
}
/* D-SACK for already forgotten data...
* Do dumb counting. */
- if (dup_sack &&
+ if (found_dup_sack &&
!after(ntohl(sp[0].end_seq), prior_snd_una) &&
after(ntohl(sp[0].end_seq), tp->undo_marker))
tp->undo_retrans--;
@@ -1058,6 +1058,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
__u32 start_seq = ntohl(sp->start_seq);
__u32 end_seq = ntohl(sp->end_seq);
int fack_count;
+ int dup_sack = (found_dup_sack && (i == first_sack_index));
skb = cached_skb;
fack_count = cached_fack_count;
@@ -1397,7 +1398,9 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag)
* waiting for the first ACK and did not get it)...
*/
if ((tp->frto_counter == 1) && !(flag&FLAG_DATA_ACKED)) {
- tp->retrans_out += tcp_skb_pcount(skb);
+ /* For some reason this R-bit might get cleared? */
+ if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
+ tp->retrans_out += tcp_skb_pcount(skb);
/* ...enter this if branch just for the first segment */
flag |= FLAG_DATA_ACKED;
} else {
@@ -2037,7 +2040,7 @@ static void tcp_try_to_open(struct sock *sk, int flag)
{
struct tcp_sock *tp = tcp_sk(sk);
- tp->left_out = tp->sacked_out;
+ tcp_sync_left_out(tp);
if (tp->retrans_out == 0)
tp->retrans_stamp = 0;
@@ -2407,9 +2410,9 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
struct sk_buff *skb;
__u32 now = tcp_time_stamp;
int acked = 0;
+ int prior_packets = tp->packets_out;
__s32 seq_rtt = -1;
- u32 pkts_acked = 0;
- ktime_t last_ackt = ktime_set(0,0);
+ ktime_t last_ackt = net_invalid_timestamp();
while ((skb = tcp_write_queue_head(sk)) &&
skb != tcp_send_head(sk)) {
@@ -2437,7 +2440,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
*/
if (!(scb->flags & TCPCB_FLAG_SYN)) {
acked |= FLAG_DATA_ACKED;
- ++pkts_acked;
} else {
acked |= FLAG_SYN_ACKED;
tp->retrans_stamp = 0;
@@ -2481,12 +2483,17 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
}
if (acked&FLAG_ACKED) {
+ u32 pkts_acked = prior_packets - tp->packets_out;
const struct tcp_congestion_ops *ca_ops
= inet_csk(sk)->icsk_ca_ops;
tcp_ack_update_rtt(sk, acked, seq_rtt);
tcp_ack_packets_out(sk);
+ /* Is the ACK triggering packet unambiguous? */
+ if (acked & FLAG_RETRANS_DATA_ACKED)
+ last_ackt = net_invalid_timestamp();
+
if (ca_ops->pkts_acked)
ca_ops->pkts_acked(sk, pkts_acked, last_ackt);
}
@@ -2932,6 +2939,7 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
opt_rx->sack_ok) {
TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th;
}
+ break;
#ifdef CONFIG_TCP_MD5SIG
case TCPOPT_MD5SIG:
/*
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 5a3e7f839fc..3f5f7423b95 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -192,8 +192,11 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
IPPROTO_TCP,
inet->sport, usin->sin_port, sk, 1);
- if (tmp < 0)
+ if (tmp < 0) {
+ if (tmp == -ENETUNREACH)
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
return tmp;
+ }
if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
ip_rt_put(rt);
@@ -702,6 +705,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
ip_hdr(skb)->saddr, /* XXX */
arg.iov[0].iov_len, IPPROTO_TCP, 0);
arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+ if (twsk)
+ arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
@@ -873,6 +878,7 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
kfree(newkey);
return -ENOMEM;
}
+ sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
}
if (tcp_alloc_md5sig_pool() == NULL) {
kfree(newkey);
@@ -1002,7 +1008,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
return -EINVAL;
tp->md5sig_info = p;
-
+ sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
}
newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
@@ -2039,10 +2045,7 @@ static void *established_get_first(struct seq_file *seq)
struct hlist_node *node;
struct inet_timewait_sock *tw;
- /* We can reschedule _before_ having picked the target: */
- cond_resched_softirq();
-
- read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
if (sk->sk_family != st->family) {
continue;
@@ -2059,7 +2062,7 @@ static void *established_get_first(struct seq_file *seq)
rc = tw;
goto out;
}
- read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
st->state = TCP_SEQ_STATE_ESTABLISHED;
}
out:
@@ -2086,14 +2089,11 @@ get_tw:
cur = tw;
goto out;
}
- read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
st->state = TCP_SEQ_STATE_ESTABLISHED;
- /* We can reschedule between buckets: */
- cond_resched_softirq();
-
if (++st->bucket < tcp_hashinfo.ehash_size) {
- read_lock(&tcp_hashinfo.ehash[st->bucket].lock);
+ read_lock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
} else {
cur = NULL;
@@ -2138,7 +2138,6 @@ static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
if (!rc) {
inet_listen_unlock(&tcp_hashinfo);
- local_bh_disable();
st->state = TCP_SEQ_STATE_ESTABLISHED;
rc = established_get_idx(seq, pos);
}
@@ -2171,7 +2170,6 @@ static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
rc = listening_get_next(seq, v);
if (!rc) {
inet_listen_unlock(&tcp_hashinfo);
- local_bh_disable();
st->state = TCP_SEQ_STATE_ESTABLISHED;
rc = established_get_first(seq);
}
@@ -2203,8 +2201,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
case TCP_SEQ_STATE_TIME_WAIT:
case TCP_SEQ_STATE_ESTABLISHED:
if (v)
- read_unlock(&tcp_hashinfo.ehash[st->bucket].lock);
- local_bh_enable();
+ read_unlock_bh(&tcp_hashinfo.ehash[st->bucket].lock);
break;
}
}
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
index 43294ad9f63..e49836ce012 100644
--- a/net/ipv4/tcp_lp.c
+++ b/net/ipv4/tcp_lp.c
@@ -266,7 +266,8 @@ static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, ktime_t last)
struct tcp_sock *tp = tcp_sk(sk);
struct lp *lp = inet_csk_ca(sk);
- tcp_lp_rtt_sample(sk, ktime_to_us(net_timedelta(last)));
+ if (!ktime_equal(last, net_invalid_timestamp()))
+ tcp_lp_rtt_sample(sk, ktime_to_us(net_timedelta(last)));
/* calc inference */
if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 53232dd6fb4..20aea1595c4 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -699,6 +699,14 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
tp->fackets_out -= diff;
if ((int)tp->fackets_out < 0)
tp->fackets_out = 0;
+ /* SACK fastpath might overwrite it unless dealt with */
+ if (tp->fastpath_skb_hint != NULL &&
+ after(TCP_SKB_CB(tp->fastpath_skb_hint)->seq,
+ TCP_SKB_CB(skb)->seq)) {
+ tp->fastpath_cnt_hint -= diff;
+ if ((int)tp->fastpath_cnt_hint < 0)
+ tp->fastpath_cnt_hint = 0;
+ }
}
}
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 3938d5dbdf2..f37d5928921 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -6,8 +6,7 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,23 +24,22 @@
#include <linux/tcp.h>
#include <linux/proc_fs.h>
#include <linux/module.h>
-#include <linux/kfifo.h>
#include <linux/ktime.h>
#include <linux/time.h>
-#include <linux/vmalloc.h>
#include <net/tcp.h>
MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>");
MODULE_DESCRIPTION("TCP cwnd snooper");
MODULE_LICENSE("GPL");
+MODULE_VERSION("1.1");
static int port __read_mostly = 0;
MODULE_PARM_DESC(port, "Port to match (0=all)");
module_param(port, int, 0);
-static int bufsize __read_mostly = 64*1024;
-MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
+static int bufsize __read_mostly = 4096;
+MODULE_PARM_DESC(bufsize, "Log buffer size in packets (4096)");
module_param(bufsize, int, 0);
static int full __read_mostly;
@@ -50,36 +48,38 @@ module_param(full, int, 0);
static const char procname[] = "tcpprobe";
-struct {
- struct kfifo *fifo;
+struct tcp_log {
+ ktime_t tstamp;
+ __be32 saddr, daddr;
+ __be16 sport, dport;
+ u16 length;
+ u32 snd_nxt;
+ u32 snd_una;
+ u32 snd_wnd;
+ u32 snd_cwnd;
+ u32 ssthresh;
+ u32 srtt;
+};
+
+static struct {
spinlock_t lock;
wait_queue_head_t wait;
ktime_t start;
u32 lastcwnd;
-} tcpw;
-/*
- * Print to log with timestamps.
- * FIXME: causes an extra copy
- */
-static void printl(const char *fmt, ...)
+ unsigned long head, tail;
+ struct tcp_log *log;
+} tcp_probe;
+
+
+static inline int tcp_probe_used(void)
{
- va_list args;
- int len;
- struct timespec tv;
- char tbuf[256];
-
- va_start(args, fmt);
- /* want monotonic time since start of tcp_probe */
- tv = ktime_to_timespec(ktime_sub(ktime_get(), tcpw.start));
-
- len = sprintf(tbuf, "%lu.%09lu ",
- (unsigned long) tv.tv_sec, (unsigned long) tv.tv_nsec);
- len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
- va_end(args);
-
- kfifo_put(tcpw.fifo, tbuf, len);
- wake_up(&tcpw.wait);
+ return (tcp_probe.head - tcp_probe.tail) % bufsize;
+}
+
+static inline int tcp_probe_avail(void)
+{
+ return bufsize - tcp_probe_used();
}
/*
@@ -94,63 +94,118 @@ static int jtcp_rcv_established(struct sock *sk, struct sk_buff *skb,
/* Only update if port matches */
if ((port == 0 || ntohs(inet->dport) == port || ntohs(inet->sport) == port)
- && (full || tp->snd_cwnd != tcpw.lastcwnd)) {
- printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u\n",
- NIPQUAD(inet->saddr), ntohs(inet->sport),
- NIPQUAD(inet->daddr), ntohs(inet->dport),
- skb->len, tp->snd_nxt, tp->snd_una,
- tp->snd_cwnd, tcp_current_ssthresh(sk),
- tp->snd_wnd, tp->srtt >> 3);
- tcpw.lastcwnd = tp->snd_cwnd;
+ && (full || tp->snd_cwnd != tcp_probe.lastcwnd)) {
+
+ spin_lock(&tcp_probe.lock);
+ /* If log fills, just silently drop */
+ if (tcp_probe_avail() > 1) {
+ struct tcp_log *p = tcp_probe.log + tcp_probe.head;
+
+ p->tstamp = ktime_get();
+ p->saddr = inet->saddr;
+ p->sport = inet->sport;
+ p->daddr = inet->daddr;
+ p->dport = inet->dport;
+ p->length = skb->len;
+ p->snd_nxt = tp->snd_nxt;
+ p->snd_una = tp->snd_una;
+ p->snd_cwnd = tp->snd_cwnd;
+ p->snd_wnd = tp->snd_wnd;
+ p->ssthresh = tcp_current_ssthresh(sk);
+ p->srtt = tp->srtt >> 3;
+
+ tcp_probe.head = (tcp_probe.head + 1) % bufsize;
+ }
+ tcp_probe.lastcwnd = tp->snd_cwnd;
+ spin_unlock(&tcp_probe.lock);
+
+ wake_up(&tcp_probe.wait);
}
jprobe_return();
return 0;
}
-static struct jprobe tcp_probe = {
+static struct jprobe tcp_jprobe = {
.kp = {
.symbol_name = "tcp_rcv_established",
},
.entry = JPROBE_ENTRY(jtcp_rcv_established),
};
-
static int tcpprobe_open(struct inode * inode, struct file * file)
{
- kfifo_reset(tcpw.fifo);
- tcpw.start = ktime_get();
+ /* Reset (empty) log */
+ spin_lock_bh(&tcp_probe.lock);
+ tcp_probe.head = tcp_probe.tail = 0;
+ tcp_probe.start = ktime_get();
+ spin_unlock_bh(&tcp_probe.lock);
+
return 0;
}
+static int tcpprobe_sprint(char *tbuf, int n)
+{
+ const struct tcp_log *p
+ = tcp_probe.log + tcp_probe.tail % bufsize;
+ struct timespec tv
+ = ktime_to_timespec(ktime_sub(p->tstamp, tcp_probe.start));
+
+ return snprintf(tbuf, n,
+ "%lu.%09lu %d.%d.%d.%d:%u %d.%d.%d.%d:%u"
+ " %d %#x %#x %u %u %u %u\n",
+ (unsigned long) tv.tv_sec,
+ (unsigned long) tv.tv_nsec,
+ NIPQUAD(p->saddr), ntohs(p->sport),
+ NIPQUAD(p->daddr), ntohs(p->dport),
+ p->length, p->snd_nxt, p->snd_una,
+ p->snd_cwnd, p->ssthresh, p->snd_wnd, p->srtt);
+}
+
static ssize_t tcpprobe_read(struct file *file, char __user *buf,
size_t len, loff_t *ppos)
{
int error = 0, cnt = 0;
- unsigned char *tbuf;
if (!buf || len < 0)
return -EINVAL;
- if (len == 0)
- return 0;
+ while (cnt < len) {
+ char tbuf[128];
+ int width;
+
+ /* Wait for data in buffer */
+ error = wait_event_interruptible(tcp_probe.wait,
+ tcp_probe_used() > 0);
+ if (error)
+ break;
- tbuf = vmalloc(len);
- if (!tbuf)
- return -ENOMEM;
+ spin_lock_bh(&tcp_probe.lock);
+ if (tcp_probe.head == tcp_probe.tail) {
+ /* multiple readers race? */
+ spin_unlock_bh(&tcp_probe.lock);
+ continue;
+ }
- error = wait_event_interruptible(tcpw.wait,
- __kfifo_len(tcpw.fifo) != 0);
- if (error)
- goto out_free;
+ width = tcpprobe_sprint(tbuf, sizeof(tbuf));
- cnt = kfifo_get(tcpw.fifo, tbuf, len);
- error = copy_to_user(buf, tbuf, cnt);
+ if (width < len)
+ tcp_probe.tail = (tcp_probe.tail + 1) % bufsize;
-out_free:
- vfree(tbuf);
+ spin_unlock_bh(&tcp_probe.lock);
+
+ /* if record greater than space available
+ return partial buffer (so far) */
+ if (width >= len)
+ break;
+
+ error = copy_to_user(buf + cnt, tbuf, width);
+ if (error)
+ break;
+ cnt += width;
+ }
- return error ? error : cnt;
+ return cnt == 0 ? error : cnt;
}
static const struct file_operations tcpprobe_fops = {
@@ -163,34 +218,37 @@ static __init int tcpprobe_init(void)
{
int ret = -ENOMEM;
- init_waitqueue_head(&tcpw.wait);
- spin_lock_init(&tcpw.lock);
- tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock);
- if (IS_ERR(tcpw.fifo))
- return PTR_ERR(tcpw.fifo);
+ init_waitqueue_head(&tcp_probe.wait);
+ spin_lock_init(&tcp_probe.lock);
+
+ if (bufsize < 0)
+ return -EINVAL;
+
+ tcp_probe.log = kcalloc(sizeof(struct tcp_log), bufsize, GFP_KERNEL);
+ if (!tcp_probe.log)
+ goto err0;
if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
goto err0;
- ret = register_jprobe(&tcp_probe);
+ ret = register_jprobe(&tcp_jprobe);
if (ret)
goto err1;
- pr_info("TCP watch registered (port=%d)\n", port);
+ pr_info("TCP probe registered (port=%d)\n", port);
return 0;
err1:
proc_net_remove(procname);
err0:
- kfifo_free(tcpw.fifo);
+ kfree(tcp_probe.log);
return ret;
}
module_init(tcpprobe_init);
static __exit void tcpprobe_exit(void)
{
- kfifo_free(tcpw.fifo);
proc_net_remove(procname);
- unregister_jprobe(&tcp_probe);
-
+ unregister_jprobe(&tcp_jprobe);
+ kfree(tcp_probe.log);
}
module_exit(tcpprobe_exit);
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 2ca97b20929..e9b151b3a59 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -78,9 +78,7 @@ static int tcp_out_of_resources(struct sock *sk, int do_reset)
if (sk->sk_err_soft)
orphans <<= 1;
- if (orphans >= sysctl_tcp_max_orphans ||
- (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
- atomic_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])) {
+ if (tcp_too_many_orphans(sk, orphans)) {
if (net_ratelimit())
printk(KERN_INFO "Out of socket memory\n");
@@ -294,9 +292,9 @@ static void tcp_retransmit_timer(struct sock *sk)
* we cannot allow such beasts to hang infinitely.
*/
#ifdef TCP_DEBUG
- if (net_ratelimit()) {
+ if (1) {
struct inet_sock *inet = inet_sk(sk);
- printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
+ LIMIT_NETDEBUG(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
NIPQUAD(inet->daddr), ntohs(inet->dport),
inet->num, tp->snd_una, tp->snd_nxt);
}
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index 73e19cf7df2..e218a51cece 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -117,6 +117,9 @@ void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
struct vegas *vegas = inet_csk_ca(sk);
u32 vrtt;
+ if (ktime_equal(last, net_invalid_timestamp()))
+ return;
+
/* Never allow zero rtt or baseRTT */
vrtt = ktime_to_us(net_timedelta(last)) + 1;
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
index 9edb340f2f9..ec854cc5fad 100644
--- a/net/ipv4/tcp_veno.c
+++ b/net/ipv4/tcp_veno.c
@@ -74,6 +74,9 @@ static void tcp_veno_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
struct veno *veno = inet_csk_ca(sk);
u32 vrtt;
+ if (ktime_equal(last, net_invalid_timestamp()))
+ return;
+
/* Never allow zero rtt or baseRTT */
vrtt = ktime_to_us(net_timedelta(last)) + 1;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 4c7e95fa090..28355350fb6 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -70,6 +70,7 @@
* Alexey Kuznetsov: allow both IPv4 and IPv6 sockets to bind
* a single port at the same time.
* Derek Atkins <derek@ihtfp.com>: Add Encapulation Support
+ * James Chapman : Add L2TP encapsulation type.
*
*
* This program is free software; you can redistribute it and/or
@@ -114,36 +115,14 @@ DEFINE_RWLOCK(udp_hash_lock);
static int udp_port_rover;
-/*
- * Note about this hash function :
- * Typical use is probably daddr = 0, only dport is going to vary hash
- */
-static inline unsigned int udp_hash_port(__u16 port)
-{
- return port;
-}
-
-static inline int __udp_lib_port_inuse(unsigned int hash, int port,
- const struct sock *this_sk,
- struct hlist_head udptable[],
- const struct udp_get_port_ops *ops)
+static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
{
struct sock *sk;
struct hlist_node *node;
- struct inet_sock *inet;
- sk_for_each(sk, node, &udptable[hash & (UDP_HTABLE_SIZE - 1)]) {
- if (sk->sk_hash != hash)
- continue;
- inet = inet_sk(sk);
- if (inet->num != port)
- continue;
- if (this_sk) {
- if (ops->saddr_cmp(sk, this_sk))
- return 1;
- } else if (ops->saddr_any(sk))
+ sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
+ if (sk->sk_hash == num)
return 1;
- }
return 0;
}
@@ -154,16 +133,16 @@ static inline int __udp_lib_port_inuse(unsigned int hash, int port,
* @snum: port number to look up
* @udptable: hash list table, must be of UDP_HTABLE_SIZE
* @port_rover: pointer to record of last unallocated port
- * @ops: AF-dependent address operations
+ * @saddr_comp: AF-dependent comparison of bound local IP addresses
*/
int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover,
- const struct udp_get_port_ops *ops)
+ int (*saddr_comp)(const struct sock *sk1,
+ const struct sock *sk2 ) )
{
struct hlist_node *node;
struct hlist_head *head;
struct sock *sk2;
- unsigned int hash;
int error = 1;
write_lock_bh(&udp_hash_lock);
@@ -178,8 +157,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
int size;
- hash = ops->hash_port_and_rcv_saddr(result, sk);
- head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
if (hlist_empty(head)) {
if (result > sysctl_local_port_range[1])
result = sysctl_local_port_range[0] +
@@ -204,16 +182,7 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
result = sysctl_local_port_range[0]
+ ((result - sysctl_local_port_range[0]) &
(UDP_HTABLE_SIZE - 1));
- hash = udp_hash_port(result);
- if (__udp_lib_port_inuse(hash, result,
- NULL, udptable, ops))
- continue;
- if (ops->saddr_any(sk))
- break;
-
- hash = ops->hash_port_and_rcv_saddr(result, sk);
- if (! __udp_lib_port_inuse(hash, result,
- sk, udptable, ops))
+ if (! __udp_lib_lport_inuse(result, udptable))
break;
}
if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@@ -221,40 +190,21 @@ int __udp_lib_get_port(struct sock *sk, unsigned short snum,
gotit:
*port_rover = snum = result;
} else {
- hash = udp_hash_port(snum);
- head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
sk_for_each(sk2, node, head)
- if (sk2->sk_hash == hash &&
- sk2 != sk &&
- inet_sk(sk2)->num == snum &&
- (!sk2->sk_reuse || !sk->sk_reuse) &&
- (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
- sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
- ops->saddr_cmp(sk, sk2))
+ if (sk2->sk_hash == snum &&
+ sk2 != sk &&
+ (!sk2->sk_reuse || !sk->sk_reuse) &&
+ (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
+ || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
+ (*saddr_comp)(sk, sk2) )
goto fail;
-
- if (!ops->saddr_any(sk)) {
- hash = ops->hash_port_and_rcv_saddr(snum, sk);
- head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
-
- sk_for_each(sk2, node, head)
- if (sk2->sk_hash == hash &&
- sk2 != sk &&
- inet_sk(sk2)->num == snum &&
- (!sk2->sk_reuse || !sk->sk_reuse) &&
- (!sk2->sk_bound_dev_if ||
- !sk->sk_bound_dev_if ||
- sk2->sk_bound_dev_if ==
- sk->sk_bound_dev_if) &&
- ops->saddr_cmp(sk, sk2))
- goto fail;
- }
}
inet_sk(sk)->num = snum;
- sk->sk_hash = hash;
+ sk->sk_hash = snum;
if (sk_unhashed(sk)) {
- head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
+ head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
sk_add_node(sk, head);
sock_prot_inc_use(sk->sk_prot);
}
@@ -265,12 +215,12 @@ fail:
}
int udp_get_port(struct sock *sk, unsigned short snum,
- const struct udp_get_port_ops *ops)
+ int (*scmp)(const struct sock *, const struct sock *))
{
- return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops);
+ return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
}
-static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
{
struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
@@ -279,33 +229,9 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
inet1->rcv_saddr == inet2->rcv_saddr ));
}
-static int ipv4_rcv_saddr_any(const struct sock *sk)
-{
- return !inet_sk(sk)->rcv_saddr;
-}
-
-static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr)
-{
- addr ^= addr >> 16;
- addr ^= addr >> 8;
- return port ^ addr;
-}
-
-static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port,
- const struct sock *sk)
-{
- return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr);
-}
-
-const struct udp_get_port_ops udp_ipv4_ops = {
- .saddr_cmp = ipv4_rcv_saddr_equal,
- .saddr_any = ipv4_rcv_saddr_any,
- .hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr,
-};
-
static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
{
- return udp_get_port(sk, snum, &udp_ipv4_ops);
+ return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
}
/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
@@ -317,77 +243,63 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
{
struct sock *sk, *result = NULL;
struct hlist_node *node;
- unsigned int hash, hashwild;
- int score, best = -1, hport = ntohs(dport);
-
- hash = ipv4_hash_port_and_addr(hport, daddr);
- hashwild = udp_hash_port(hport);
+ unsigned short hnum = ntohs(dport);
+ int badness = -1;
read_lock(&udp_hash_lock);
-
-lookup:
-
- sk_for_each(sk, node, &udptable[hash & (UDP_HTABLE_SIZE - 1)]) {
+ sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
struct inet_sock *inet = inet_sk(sk);
- if (sk->sk_hash != hash || ipv6_only_sock(sk) ||
- inet->num != hport)
- continue;
-
- score = (sk->sk_family == PF_INET ? 1 : 0);
- if (inet->rcv_saddr) {
- if (inet->rcv_saddr != daddr)
- continue;
- score+=2;
- }
- if (inet->daddr) {
- if (inet->daddr != saddr)
- continue;
- score+=2;
- }
- if (inet->dport) {
- if (inet->dport != sport)
- continue;
- score+=2;
- }
- if (sk->sk_bound_dev_if) {
- if (sk->sk_bound_dev_if != dif)
- continue;
- score+=2;
- }
- if (score == 9) {
- result = sk;
- goto found;
- } else if (score > best) {
- result = sk;
- best = score;
+ if (sk->sk_hash == hnum && !ipv6_only_sock(sk)) {
+ int score = (sk->sk_family == PF_INET ? 1 : 0);
+ if (inet->rcv_saddr) {
+ if (inet->rcv_saddr != daddr)
+ continue;
+ score+=2;
+ }
+ if (inet->daddr) {
+ if (inet->daddr != saddr)
+ continue;
+ score+=2;
+ }
+ if (inet->dport) {
+ if (inet->dport != sport)
+ continue;
+ score+=2;
+ }
+ if (sk->sk_bound_dev_if) {
+ if (sk->sk_bound_dev_if != dif)
+ continue;
+ score+=2;
+ }
+ if (score == 9) {
+ result = sk;
+ break;
+ } else if (score > badness) {
+ result = sk;
+ badness = score;
+ }
}
}
-
- if (hash != hashwild) {
- hash = hashwild;
- goto lookup;
- }
-found:
if (result)
sock_hold(result);
read_unlock(&udp_hash_lock);
return result;
}
-static inline struct sock *udp_v4_mcast_next(struct sock *sk, unsigned int hnum,
- int hport, __be32 loc_addr,
+static inline struct sock *udp_v4_mcast_next(struct sock *sk,
+ __be16 loc_port, __be32 loc_addr,
__be16 rmt_port, __be32 rmt_addr,
int dif)
{
struct hlist_node *node;
struct sock *s = sk;
+ unsigned short hnum = ntohs(loc_port);
sk_for_each_from(s, node) {
struct inet_sock *inet = inet_sk(s);
if (s->sk_hash != hnum ||
- inet->num != hport ||
(inet->daddr && inet->daddr != rmt_addr) ||
(inet->dport != rmt_port && inet->dport) ||
(inet->rcv_saddr && inet->rcv_saddr != loc_addr) ||
@@ -722,8 +634,11 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
.dport = dport } } };
security_sk_classify_flow(sk, &fl);
err = ip_route_output_flow(&rt, &fl, sk, 1);
- if (err)
+ if (err) {
+ if (err == -ENETUNREACH)
+ IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
goto out;
+ }
err = -EACCES;
if ((rt->rt_flags & RTCF_BROADCAST) &&
@@ -1005,104 +920,6 @@ int udp_disconnect(struct sock *sk, int flags)
return 0;
}
-/* return:
- * 1 if the UDP system should process it
- * 0 if we should drop this packet
- * -1 if it should get processed by xfrm4_rcv_encap
- */
-static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
-{
-#ifndef CONFIG_XFRM
- return 1;
-#else
- struct udp_sock *up = udp_sk(sk);
- struct udphdr *uh;
- struct iphdr *iph;
- int iphlen, len;
-
- __u8 *udpdata;
- __be32 *udpdata32;
- __u16 encap_type = up->encap_type;
-
- /* if we're overly short, let UDP handle it */
- len = skb->len - sizeof(struct udphdr);
- if (len <= 0)
- return 1;
-
- /* if this is not encapsulated socket, then just return now */
- if (!encap_type)
- return 1;
-
- /* If this is a paged skb, make sure we pull up
- * whatever data we need to look at. */
- if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
- return 1;
-
- /* Now we can get the pointers */
- uh = udp_hdr(skb);
- udpdata = (__u8 *)uh + sizeof(struct udphdr);
- udpdata32 = (__be32 *)udpdata;
-
- switch (encap_type) {
- default:
- case UDP_ENCAP_ESPINUDP:
- /* Check if this is a keepalive packet. If so, eat it. */
- if (len == 1 && udpdata[0] == 0xff) {
- return 0;
- } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
- /* ESP Packet without Non-ESP header */
- len = sizeof(struct udphdr);
- } else
- /* Must be an IKE packet.. pass it through */
- return 1;
- break;
- case UDP_ENCAP_ESPINUDP_NON_IKE:
- /* Check if this is a keepalive packet. If so, eat it. */
- if (len == 1 && udpdata[0] == 0xff) {
- return 0;
- } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
- udpdata32[0] == 0 && udpdata32[1] == 0) {
-
- /* ESP Packet with Non-IKE marker */
- len = sizeof(struct udphdr) + 2 * sizeof(u32);
- } else
- /* Must be an IKE packet.. pass it through */
- return 1;
- break;
- }
-
- /* At this point we are sure that this is an ESPinUDP packet,
- * so we need to remove 'len' bytes from the packet (the UDP
- * header and optional ESP marker bytes) and then modify the
- * protocol to ESP, and then call into the transform receiver.
- */
- if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
- return 0;
-
- /* Now we can update and verify the packet length... */
- iph = ip_hdr(skb);
- iphlen = iph->ihl << 2;
- iph->tot_len = htons(ntohs(iph->tot_len) - len);
- if (skb->len < iphlen + len) {
- /* packet is too small!?! */
- return 0;
- }
-
- /* pull the data buffer up to the ESP header and set the
- * transport header to point to ESP. Keep UDP on the stack
- * for later.
- */
- __skb_pull(skb, len);
- skb_reset_transport_header(skb);
-
- /* modify the protocol (it's ESP!) */
- iph->protocol = IPPROTO_ESP;
-
- /* and let the caller know to send this into the ESP processor... */
- return -1;
-#endif
-}
-
/* returns:
* -1: error
* 0: success
@@ -1125,28 +942,28 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
if (up->encap_type) {
/*
- * This is an encapsulation socket, so let's see if this is
- * an encapsulated packet.
- * If it's a keepalive packet, then just eat it.
- * If it's an encapsulateed packet, then pass it to the
- * IPsec xfrm input and return the response
- * appropriately. Otherwise, just fall through and
- * pass this up the UDP socket.
+ * This is an encapsulation socket so pass the skb to
+ * the socket's udp_encap_rcv() hook. Otherwise, just
+ * fall through and pass this up the UDP socket.
+ * up->encap_rcv() returns the following value:
+ * =0 if skb was successfully passed to the encap
+ * handler or was discarded by it.
+ * >0 if skb should be passed on to UDP.
+ * <0 if skb should be resubmitted as proto -N
*/
- int ret;
- ret = udp_encap_rcv(sk, skb);
- if (ret == 0) {
- /* Eat the packet .. */
- kfree_skb(skb);
- return 0;
- }
- if (ret < 0) {
- /* process the ESP packet */
- ret = xfrm4_rcv_encap(skb, up->encap_type);
- UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
- return -ret;
+ /* if we're overly short, let UDP handle it */
+ if (skb->len > sizeof(struct udphdr) &&
+ up->encap_rcv != NULL) {
+ int ret;
+
+ ret = (*up->encap_rcv)(sk, skb);
+ if (ret <= 0) {
+ UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
+ return -ret;
+ }
}
+
/* FALLTHROUGH -- it's a UDP Packet */
}
@@ -1218,45 +1035,29 @@ static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
__be32 saddr, __be32 daddr,
struct hlist_head udptable[])
{
- struct sock *sk, *skw, *sknext;
+ struct sock *sk;
int dif;
- int hport = ntohs(uh->dest);
- unsigned int hash = ipv4_hash_port_and_addr(hport, daddr);
- unsigned int hashwild = udp_hash_port(hport);
-
- dif = skb->dev->ifindex;
read_lock(&udp_hash_lock);
-
- sk = sk_head(&udptable[hash & (UDP_HTABLE_SIZE - 1)]);
- skw = sk_head(&udptable[hashwild & (UDP_HTABLE_SIZE - 1)]);
-
- sk = udp_v4_mcast_next(sk, hash, hport, daddr, uh->source, saddr, dif);
- if (!sk) {
- hash = hashwild;
- sk = udp_v4_mcast_next(skw, hash, hport, daddr, uh->source,
- saddr, dif);
- }
+ sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
+ dif = skb->dev->ifindex;
+ sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
if (sk) {
+ struct sock *sknext = NULL;
+
do {
struct sk_buff *skb1 = skb;
- sknext = udp_v4_mcast_next(sk_next(sk), hash, hport,
- daddr, uh->source, saddr, dif);
- if (!sknext && hash != hashwild) {
- hash = hashwild;
- sknext = udp_v4_mcast_next(skw, hash, hport,
- daddr, uh->source, saddr, dif);
- }
+
+ sknext = udp_v4_mcast_next(sk_next(sk), uh->dest, daddr,
+ uh->source, saddr, dif);
if (sknext)
skb1 = skb_clone(skb, GFP_ATOMIC);
if (skb1) {
int ret = udp_queue_rcv_skb(sk, skb1);
if (ret > 0)
- /*
- * we should probably re-process
- * instead of dropping packets here.
- */
+ /* we should probably re-process instead
+ * of dropping packets here. */
kfree_skb(skb1);
}
sk = sknext;
@@ -1343,7 +1144,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
- skb->dev->ifindex, udptable);
+ skb->dev->ifindex, udptable );
if (sk != NULL) {
int ret = udp_queue_rcv_skb(sk, skb);
@@ -1451,6 +1252,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
case 0:
case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE:
+ up->encap_rcv = xfrm4_udp_encap_rcv;
+ /* FALLTHROUGH */
+ case UDP_ENCAP_L2TPINUDP:
up->encap_type = val;
break;
default:
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index 06d94195e64..820a477cfaa 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -5,14 +5,14 @@
#include <net/protocol.h>
#include <net/inet_common.h>
-extern const struct udp_get_port_ops udp_ipv4_ops;
-
extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
struct hlist_head udptable[], int *port_rover,
- const struct udp_get_port_ops *ops);
+ int (*)(const struct sock*,const struct sock*));
+extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
+
extern int udp_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, int optlen);
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index 3653b32dce2..f34fd686a8f 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -19,15 +19,14 @@ struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
static int udplite_port_rover;
int udplite_get_port(struct sock *sk, unsigned short p,
- const struct udp_get_port_ops *ops)
+ int (*c)(const struct sock *, const struct sock *))
{
- return __udp_lib_get_port(sk, p, udplite_hash,
- &udplite_port_rover, ops);
+ return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
}
static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
{
- return udplite_get_port(sk, snum, &udp_ipv4_ops);
+ return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
}
static int udplite_rcv(struct sk_buff *skb)
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 5ceca951d73..2fa10824541 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -16,13 +16,6 @@
#include <net/ip.h>
#include <net/xfrm.h>
-int xfrm4_rcv(struct sk_buff *skb)
-{
- return xfrm4_rcv_encap(skb, 0);
-}
-
-EXPORT_SYMBOL(xfrm4_rcv);
-
static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
{
switch (nexthdr) {
@@ -53,7 +46,7 @@ drop:
}
#endif
-int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
+static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
{
__be32 spi, seq;
struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH];
@@ -139,10 +132,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
nf_reset(skb);
if (decaps) {
- if (!(skb->dev->flags&IFF_LOOPBACK)) {
- dst_release(skb->dst);
- skb->dst = NULL;
- }
+ dst_release(skb->dst);
+ skb->dst = NULL;
netif_rx(skb);
return 0;
} else {
@@ -169,3 +160,108 @@ drop:
kfree_skb(skb);
return 0;
}
+
+/* If it's a keepalive packet, then just eat it.
+ * If it's an encapsulated packet, then pass it to the
+ * IPsec xfrm input.
+ * Returns 0 if skb passed to xfrm or was dropped.
+ * Returns >0 if skb should be passed to UDP.
+ * Returns <0 if skb should be resubmitted (-ret is protocol)
+ */
+int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ struct udp_sock *up = udp_sk(sk);
+ struct udphdr *uh;
+ struct iphdr *iph;
+ int iphlen, len;
+ int ret;
+
+ __u8 *udpdata;
+ __be32 *udpdata32;
+ __u16 encap_type = up->encap_type;
+
+ /* if this is not encapsulated socket, then just return now */
+ if (!encap_type)
+ return 1;
+
+ /* If this is a paged skb, make sure we pull up
+ * whatever data we need to look at. */
+ len = skb->len - sizeof(struct udphdr);
+ if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
+ return 1;
+
+ /* Now we can get the pointers */
+ uh = udp_hdr(skb);
+ udpdata = (__u8 *)uh + sizeof(struct udphdr);
+ udpdata32 = (__be32 *)udpdata;
+
+ switch (encap_type) {
+ default:
+ case UDP_ENCAP_ESPINUDP:
+ /* Check if this is a keepalive packet. If so, eat it. */
+ if (len == 1 && udpdata[0] == 0xff) {
+ goto drop;
+ } else if (len > sizeof(struct ip_esp_hdr) && udpdata32[0] != 0) {
+ /* ESP Packet without Non-ESP header */
+ len = sizeof(struct udphdr);
+ } else
+ /* Must be an IKE packet.. pass it through */
+ return 1;
+ break;
+ case UDP_ENCAP_ESPINUDP_NON_IKE:
+ /* Check if this is a keepalive packet. If so, eat it. */
+ if (len == 1 && udpdata[0] == 0xff) {
+ goto drop;
+ } else if (len > 2 * sizeof(u32) + sizeof(struct ip_esp_hdr) &&
+ udpdata32[0] == 0 && udpdata32[1] == 0) {
+
+ /* ESP Packet with Non-IKE marker */
+ len = sizeof(struct udphdr) + 2 * sizeof(u32);
+ } else
+ /* Must be an IKE packet.. pass it through */
+ return 1;
+ break;
+ }
+
+ /* At this point we are sure that this is an ESPinUDP packet,
+ * so we need to remove 'len' bytes from the packet (the UDP
+ * header and optional ESP marker bytes) and then modify the
+ * protocol to ESP, and then call into the transform receiver.
+ */
+ if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ goto drop;
+
+ /* Now we can update and verify the packet length... */
+ iph = ip_hdr(skb);
+ iphlen = iph->ihl << 2;
+ iph->tot_len = htons(ntohs(iph->tot_len) - len);
+ if (skb->len < iphlen + len) {
+ /* packet is too small!?! */
+ goto drop;
+ }
+
+ /* pull the data buffer up to the ESP header and set the
+ * transport header to point to ESP. Keep UDP on the stack
+ * for later.
+ */
+ __skb_pull(skb, len);
+ skb_reset_transport_header(skb);
+
+ /* modify the protocol (it's ESP!) */
+ iph->protocol = IPPROTO_ESP;
+
+ /* process ESP */
+ ret = xfrm4_rcv_encap(skb, encap_type);
+ return ret;
+
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+
+int xfrm4_rcv(struct sk_buff *skb)
+{
+ return xfrm4_rcv_encap(skb, 0);
+}
+
+EXPORT_SYMBOL(xfrm4_rcv);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index a2f2e6a5ec5..9963700e74c 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -85,6 +85,8 @@ static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->saddr = x->props.saddr.a4;
top_iph->daddr = x->id.daddr.a4;
+ skb->protocol = htons(ETH_P_IP);
+
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
return 0;
}
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 56851030455..9275c79119b 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -109,3 +109,4 @@ static void __exit ipip_fini(void)
module_init(ipip_init);
module_exit(ipip_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET, XFRM_PROTO_IPIP);
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 8e5d54f23b4..eb0b8085949 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -109,7 +109,7 @@ config INET6_IPCOMP
If unsure, say Y.
config IPV6_MIP6
- bool "IPv6: Mobility (EXPERIMENTAL)"
+ tristate "IPv6: Mobility (EXPERIMENTAL)"
depends on IPV6 && EXPERIMENTAL
select XFRM
---help---
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index bb33309044c..87c23a73d28 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -14,7 +14,6 @@ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
xfrm6_output.o
ipv6-$(CONFIG_NETFILTER) += netfilter.o
ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
-ipv6-$(CONFIG_IPV6_MIP6) += mip6.o
ipv6-$(CONFIG_PROC_FS) += proc.o
ipv6-objs += $(ipv6-y)
@@ -28,6 +27,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
+obj-$(CONFIG_IPV6_MIP6) += mip6.o
obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IPV6_SIT) += sit.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 329de679ac3..06012920912 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1034,7 +1034,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
}
/* Rule 4: Prefer home address */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
if (hiscore.rule < 4) {
if (ifa_result->flags & IFA_F_HOMEADDRESS)
hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
@@ -2154,6 +2154,15 @@ static void addrconf_dev_config(struct net_device *dev)
ASSERT_RTNL();
+ if ((dev->type != ARPHRD_ETHER) &&
+ (dev->type != ARPHRD_FDDI) &&
+ (dev->type != ARPHRD_IEEE802_TR) &&
+ (dev->type != ARPHRD_ARCNET) &&
+ (dev->type != ARPHRD_INFINIBAND)) {
+ /* Alas, we support only Ethernet autoconfiguration. */
+ return;
+ }
+
idev = addrconf_add_dev(dev);
if (idev == NULL)
return;
@@ -2241,36 +2250,16 @@ static void addrconf_ip6_tnl_config(struct net_device *dev)
ip6_tnl_add_linklocal(idev);
}
-static int ipv6_hwtype(struct net_device *dev)
-{
- if ((dev->type == ARPHRD_ETHER) ||
- (dev->type == ARPHRD_LOOPBACK) ||
- (dev->type == ARPHRD_SIT) ||
- (dev->type == ARPHRD_TUNNEL6) ||
- (dev->type == ARPHRD_FDDI) ||
- (dev->type == ARPHRD_IEEE802_TR) ||
- (dev->type == ARPHRD_ARCNET) ||
- (dev->type == ARPHRD_INFINIBAND))
- return 1;
-
- return 0;
-}
-
static int addrconf_notify(struct notifier_block *this, unsigned long event,
void * data)
{
struct net_device *dev = (struct net_device *) data;
- struct inet6_dev *idev;
+ struct inet6_dev *idev = __in6_dev_get(dev);
int run_pending = 0;
- if (!ipv6_hwtype(dev))
- return NOTIFY_OK;
-
- idev = __in6_dev_get(dev);
-
switch(event) {
case NETDEV_REGISTER:
- if (!idev) {
+ if (!idev && dev->mtu >= IPV6_MIN_MTU) {
idev = ipv6_add_dev(dev);
if (!idev)
printk(KERN_WARNING "IPv6: add_dev failed for %s\n",
@@ -2279,6 +2268,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
break;
case NETDEV_UP:
case NETDEV_CHANGE:
+ if (dev->flags & IFF_SLAVE)
+ break;
+
if (event == NETDEV_UP) {
if (!netif_carrier_ok(dev)) {
/* device is not ready yet. */
@@ -2483,6 +2475,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
write_unlock_bh(&idev->lock);
__ipv6_ifa_notify(RTM_DELADDR, ifa);
+ atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
in6_ifa_put(ifa);
write_lock_bh(&idev->lock);
@@ -2793,7 +2786,7 @@ static int if6_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations if6_seq_ops = {
+static const struct seq_operations if6_seq_ops = {
.start = if6_seq_start,
.next = if6_seq_next,
.show = if6_seq_show,
@@ -2843,7 +2836,7 @@ void if6_proc_exit(void)
}
#endif /* CONFIG_PROC_FS */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
/* Check if address is a home address configured on any interface. */
int ipv6_chk_home_addr(struct in6_addr *addr)
{
@@ -2990,7 +2983,7 @@ static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
return pfx;
}
-static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = {
+static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
[IFA_ADDRESS] = { .len = sizeof(struct in6_addr) },
[IFA_LOCAL] = { .len = sizeof(struct in6_addr) },
[IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
@@ -4251,7 +4244,6 @@ errout:
void __exit addrconf_cleanup(void)
{
struct net_device *dev;
- struct inet6_dev *idev;
struct inet6_ifaddr *ifa;
int i;
@@ -4269,7 +4261,7 @@ void __exit addrconf_cleanup(void)
*/
for_each_netdev(dev) {
- if ((idev = __in6_dev_get(dev)) == NULL)
+ if (__in6_dev_get(dev) == NULL)
continue;
addrconf_ifdown(dev, 1);
}
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6dd377253cf..eed09373a45 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -58,9 +58,6 @@
#ifdef CONFIG_IPV6_TUNNEL
#include <net/ip6_tunnel.h>
#endif
-#ifdef CONFIG_IPV6_MIP6
-#include <net/mip6.h>
-#endif
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -853,9 +850,6 @@ static int __init inet6_init(void)
ipv6_frag_init();
ipv6_nodata_init();
ipv6_destopt_init();
-#ifdef CONFIG_IPV6_MIP6
- mip6_init();
-#endif
/* Init v6 transport protocols. */
udpv6_init();
@@ -921,9 +915,7 @@ static void __exit inet6_exit(void)
/* Cleanup code parts. */
ipv6_packet_cleanup();
-#ifdef CONFIG_IPV6_MIP6
- mip6_fini();
-#endif
+
addrconf_cleanup();
ip6_flowlabel_cleanup();
ip6_route_cleanup();
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index b696c840120..53f46ab6af7 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -74,7 +74,7 @@ bad:
return 0;
}
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
/**
* ipv6_rearrange_destopt - rearrange IPv6 destination options header
* @iph: IPv6 header
@@ -132,6 +132,8 @@ static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *des
bad:
return;
}
+#else
+static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) {}
#endif
/**
@@ -189,10 +191,8 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
while (exthdr.raw < end) {
switch (nexthdr) {
case NEXTHDR_DEST:
-#ifdef CONFIG_IPV6_MIP6
if (dir == XFRM_POLICY_OUT)
ipv6_rearrange_destopt(iph, exthdr.opth);
-#endif
case NEXTHDR_HOP:
if (!zero_out_mutable_opts(exthdr.opth)) {
LIMIT_NETDEBUG(
@@ -228,7 +228,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
u8 nexthdr;
char tmp_base[8];
struct {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
struct in6_addr saddr;
#endif
struct in6_addr daddr;
@@ -247,7 +247,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
memcpy(tmp_base, top_iph, sizeof(tmp_base));
tmp_ext = NULL;
- extlen = skb_transport_offset(skb) + sizeof(struct ipv6hdr);
+ extlen = skb_transport_offset(skb) - sizeof(struct ipv6hdr);
if (extlen) {
extlen += sizeof(*tmp_ext);
tmp_ext = kmalloc(extlen, GFP_ATOMIC);
@@ -255,7 +255,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
err = -ENOMEM;
goto error;
}
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
memcpy(tmp_ext, &top_iph->saddr, extlen);
#else
memcpy(tmp_ext, &top_iph->daddr, extlen);
@@ -294,7 +294,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
memcpy(top_iph, tmp_base, sizeof(tmp_base));
if (tmp_ext) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
memcpy(&top_iph->saddr, tmp_ext, extlen);
#else
memcpy(&top_iph->daddr, tmp_ext, extlen);
@@ -554,3 +554,4 @@ module_init(ah6_init);
module_exit(ah6_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_AH);
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 9b81264eb78..b8c533fbdb6 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -539,7 +539,7 @@ static int ac6_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ac6_seq_ops = {
+static const struct seq_operations ac6_seq_ops = {
.start = ac6_seq_start,
.next = ac6_seq_next,
.stop = ac6_seq_stop,
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index b1fe7ac5dc9..fe0f49024a0 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -657,11 +657,10 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg);
switch (rthdr->type) {
- case IPV6_SRCRT_TYPE_0:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
-#endif
break;
+#endif
default:
err = -EINVAL;
goto exit_f;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 7107bb7e2e6..2db31ce3c7e 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -421,3 +421,4 @@ module_init(esp6_init);
module_exit(esp6_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 14be0b9b77a..c82d4d49f71 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -42,7 +42,7 @@
#include <net/ndisc.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
#include <net/xfrm.h>
#endif
@@ -90,6 +90,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
bad:
return -1;
}
+EXPORT_SYMBOL_GPL(ipv6_find_tlv);
/*
* Parsing tlv encoded headers.
@@ -196,7 +197,7 @@ bad:
Destination options header.
*****************************/
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
{
struct sk_buff *skb = *skbp;
@@ -270,7 +271,7 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
#endif
static struct tlvtype_proc tlvprocdestopt_lst[] = {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
{
.type = IPV6_TLV_HAO,
.func = ipv6_dest_hao,
@@ -283,7 +284,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
{
struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = IP6CB(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
__u16 dstbuf;
#endif
struct dst_entry *dst;
@@ -298,7 +299,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
}
opt->lastopt = opt->dst1 = skb_network_header_len(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
dstbuf = opt->dst1;
#endif
@@ -308,7 +309,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
skb = *skbp;
skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
opt = IP6CB(skb);
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
opt->nhoff = dstbuf;
#else
opt->nhoff = opt->dst1;
@@ -371,22 +372,13 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
struct rt0_hdr *rthdr;
int accept_source_route = ipv6_devconf.accept_source_route;
- if (accept_source_route < 0 ||
- ((idev = in6_dev_get(skb->dev)) == NULL)) {
- kfree_skb(skb);
- return -1;
- }
- if (idev->cnf.accept_source_route < 0) {
+ idev = in6_dev_get(skb->dev);
+ if (idev) {
+ if (accept_source_route > idev->cnf.accept_source_route)
+ accept_source_route = idev->cnf.accept_source_route;
in6_dev_put(idev);
- kfree_skb(skb);
- return -1;
}
- if (accept_source_route > idev->cnf.accept_source_route)
- accept_source_route = idev->cnf.accept_source_route;
-
- in6_dev_put(idev);
-
if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
!pskb_may_pull(skb, (skb_transport_offset(skb) +
((skb_transport_header(skb)[1] + 1) << 3)))) {
@@ -398,24 +390,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
- switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
- case IPV6_SRCRT_TYPE_2:
- break;
-#endif
- case IPV6_SRCRT_TYPE_0:
- if (accept_source_route > 0)
- break;
- kfree_skb(skb);
- return -1;
- default:
- IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
- IPSTATS_MIB_INHDRERRORS);
- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
- (&hdr->type) - skb_network_header(skb));
- return -1;
- }
-
if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
skb->pkt_type != PACKET_HOST) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -427,7 +401,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
looped_back:
if (hdr->segments_left == 0) {
switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
/* Silently discard type 2 header unless it was
* processed by own
@@ -453,18 +427,10 @@ looped_back:
}
switch (hdr->type) {
- case IPV6_SRCRT_TYPE_0:
- if (hdr->hdrlen & 0x01) {
- IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
- IPSTATS_MIB_INHDRERRORS);
- icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
- ((&hdr->hdrlen) -
- skb_network_header(skb)));
- return -1;
- }
- break;
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
+ if (accept_source_route < 0)
+ goto unknown_rh;
/* Silently discard invalid RTH type 2 */
if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
@@ -474,6 +440,8 @@ looped_back:
}
break;
#endif
+ default:
+ goto unknown_rh;
}
/*
@@ -520,7 +488,7 @@ looped_back:
addr += i - 1;
switch (hdr->type) {
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
(xfrm_address_t *)&ipv6_hdr(skb)->saddr,
@@ -577,6 +545,12 @@ looped_back:
skb_push(skb, skb->data - skb_network_header(skb));
dst_input(skb);
return -1;
+
+unknown_rh:
+ IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
+ icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
+ (&hdr->type) - skb_network_header(skb));
+ return -1;
}
static struct inet6_protocol rthdr_protocol = {
@@ -590,72 +564,6 @@ void __init ipv6_rthdr_init(void)
printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
};
-/*
- This function inverts received rthdr.
- NOTE: specs allow to make it automatically only if
- packet authenticated.
-
- I will not discuss it here (though, I am really pissed off at
- this stupid requirement making rthdr idea useless)
-
- Actually, it creates severe problems for us.
- Embryonic requests has no associated sockets,
- so that user have no control over it and
- cannot not only to set reply options, but
- even to know, that someone wants to connect
- without success. :-(
-
- For now we need to test the engine, so that I created
- temporary (or permanent) backdoor.
- If listening socket set IPV6_RTHDR to 2, then we invert header.
- --ANK (980729)
- */
-
-struct ipv6_txoptions *
-ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
-{
- /* Received rthdr:
-
- [ H1 -> H2 -> ... H_prev ] daddr=ME
-
- Inverted result:
- [ H_prev -> ... -> H1 ] daddr =sender
-
- Note, that IP output engine will rewrite this rthdr
- by rotating it left by one addr.
- */
-
- int n, i;
- struct rt0_hdr *rthdr = (struct rt0_hdr*)hdr;
- struct rt0_hdr *irthdr;
- struct ipv6_txoptions *opt;
- int hdrlen = ipv6_optlen(hdr);
-
- if (hdr->segments_left ||
- hdr->type != IPV6_SRCRT_TYPE_0 ||
- hdr->hdrlen & 0x01)
- return NULL;
-
- n = hdr->hdrlen >> 1;
- opt = sock_kmalloc(sk, sizeof(*opt) + hdrlen, GFP_ATOMIC);
- if (opt == NULL)
- return NULL;
- memset(opt, 0, sizeof(*opt));
- opt->tot_len = sizeof(*opt) + hdrlen;
- opt->srcrt = (void*)(opt+1);
- opt->opt_nflen = hdrlen;
-
- memcpy(opt->srcrt, hdr, sizeof(*hdr));
- irthdr = (struct rt0_hdr*)opt->srcrt;
- irthdr->reserved = 0;
- opt->srcrt->segments_left = n;
- for (i=0; i<n; i++)
- memcpy(irthdr->addr+i, rthdr->addr+(n-1-i), 16);
- return opt;
-}
-
-EXPORT_SYMBOL_GPL(ipv6_invert_rthdr);
-
/**********************************
Hop-by-hop options.
**********************************/
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index fc3882c9060..53b3998a486 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -157,7 +157,7 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
return 1;
}
-static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = {
+static const struct nla_policy fib6_rule_policy[FRA_MAX+1] = {
FRA_GENERIC_POLICY,
};
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index e9bcce9e7bd..6a6714d154e 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -272,7 +272,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st
return 0;
}
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
static void mip6_addr_swap(struct sk_buff *skb)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -604,7 +604,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info)
read_lock(&raw_v6_lock);
if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) {
- while((sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr,
+ while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr,
IP6CB(skb)->iif))) {
rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
sk = sk_next(sk);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index ca08ee88d07..662a7d9681f 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -619,14 +619,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
ins = &fn->leaf;
- if (fn->fn_flags&RTN_TL_ROOT &&
- fn->leaf == &ip6_null_entry &&
- !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
- fn->leaf = rt;
- rt->u.dst.rt6_next = NULL;
- goto out;
- }
-
for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) {
/*
* Search for duplicates
@@ -666,7 +658,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
* insert node
*/
-out:
rt->u.dst.rt6_next = iter;
*ins = rt;
rt->rt6i_node = fn;
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index c206a152ed9..413a4ebb195 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -648,7 +648,7 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ip6fl_seq_ops = {
+static const struct seq_operations ip6fl_seq_ops = {
.start = ip6fl_seq_start,
.next = ip6fl_seq_next,
.stop = ip6fl_seq_stop,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4704b5fc308..50d86e94d9e 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -521,6 +521,10 @@ 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)
+ to->nf_trace = from->nf_trace;
+#endif
skb_copy_secmark(to, from);
}
@@ -543,7 +547,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
found_rhdr = 1;
break;
case NEXTHDR_DEST:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
break;
#endif
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index a0902fbdb4e..281aee42d3f 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -883,8 +883,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
*/
max_headroom += LL_RESERVED_SPACE(tdev);
- if (skb_headroom(skb) < max_headroom ||
- skb_cloned(skb) || skb_shared(skb)) {
+ if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+ (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
struct sk_buff *new_skb;
if (!(new_skb = skb_realloc_headroom(skb, max_headroom)))
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 1ee50b5782e..473f165310e 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -500,4 +500,4 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IP Payload Compression Protocol (IPComp) for IPv6 - RFC3173");
MODULE_AUTHOR("Mitsuru KANDA <mk@linux-ipv6.org>");
-
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_COMP);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index aa3d07c52a8..d6846393182 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -123,7 +123,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
struct ipv6hdr *ipv6h;
struct inet6_protocol *ops;
- if (!(features & NETIF_F_HW_CSUM))
+ if (!(features & NETIF_F_V6_CSUM))
features &= ~NETIF_F_SG;
if (unlikely(skb_shinfo(skb)->gso_type &
@@ -336,16 +336,12 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
break;
case IPV6_RECVRTHDR:
- if (val < 0 || val > 2)
- goto e_inval;
- np->rxopt.bits.srcrt = val;
+ np->rxopt.bits.srcrt = valbool;
retv = 0;
break;
case IPV6_2292RTHDR:
- if (val < 0 || val > 2)
- goto e_inval;
- np->rxopt.bits.osrcrt = val;
+ np->rxopt.bits.osrcrt = valbool;
retv = 0;
break;
@@ -416,11 +412,10 @@ 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) {
- case IPV6_SRCRT_TYPE_0:
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPV6_SRCRT_TYPE_2:
-#endif
break;
+#endif
default:
goto sticky_done;
}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 3e308fb41b4..ae9881832a7 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2423,7 +2423,7 @@ static int igmp6_mc_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations igmp6_mc_seq_ops = {
+static const struct seq_operations igmp6_mc_seq_ops = {
.start = igmp6_mc_seq_start,
.next = igmp6_mc_seq_next,
.stop = igmp6_mc_seq_stop,
@@ -2597,7 +2597,7 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations igmp6_mcf_seq_ops = {
+static const struct seq_operations igmp6_mcf_seq_ops = {
.start = igmp6_mcf_seq_start,
.next = igmp6_mcf_seq_next,
.stop = igmp6_mcf_seq_stop,
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 13b7160fb89..8a1399ce38c 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -30,6 +30,7 @@
#include <net/sock.h>
#include <net/ipv6.h>
#include <net/ip6_checksum.h>
+#include <net/rawv6.h>
#include <net/xfrm.h>
#include <net/mip6.h>
@@ -86,7 +87,7 @@ static int mip6_mh_len(int type)
return len;
}
-int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
+static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
{
struct ip6_mh *mh;
@@ -471,7 +472,7 @@ static struct xfrm_type mip6_rthdr_type =
.remote_addr = mip6_xfrm_addr,
};
-int __init mip6_init(void)
+static int __init mip6_init(void)
{
printk(KERN_INFO "Mobile IPv6\n");
@@ -483,18 +484,35 @@ int __init mip6_init(void)
printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
goto mip6_rthdr_xfrm_fail;
}
+ if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
+ printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
+ goto mip6_rawv6_mh_fail;
+ }
+
+
return 0;
+ mip6_rawv6_mh_fail:
+ xfrm_unregister_type(&mip6_rthdr_type, AF_INET6);
mip6_rthdr_xfrm_fail:
xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
mip6_destopt_xfrm_fail:
return -EAGAIN;
}
-void __exit mip6_fini(void)
+static void __exit mip6_fini(void)
{
+ if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
+ printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
}
+
+module_init(mip6_init);
+module_exit(mip6_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_DSTOPTS);
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ROUTING);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index d8b36451bad..0358e6066a4 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1062,7 +1062,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
pref = ra_msg->icmph.icmp6_router_pref;
/* 10b is handled as if it were 00b (medium) */
if (pref == ICMPV6_ROUTER_PREF_INVALID ||
- in6_dev->cnf.accept_ra_rtr_pref)
+ !in6_dev->cnf.accept_ra_rtr_pref)
pref = ICMPV6_ROUTER_PREF_MEDIUM;
#endif
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 9aa62402668..aeda617246b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -96,13 +96,13 @@ ip6t_ext_hdr(u8 nexthdr)
}
/* Returns whether matches rule or not. */
-static inline int
+static inline bool
ip6_packet_match(const struct sk_buff *skb,
const char *indev,
const char *outdev,
const struct ip6t_ip6 *ip6info,
unsigned int *protoff,
- int *fragoff, int *hotdrop)
+ int *fragoff, bool *hotdrop)
{
size_t i;
unsigned long ret;
@@ -122,7 +122,7 @@ ip6_packet_match(const struct sk_buff *skb,
dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
- return 0;
+ return false;
}
/* Look for ifname matches; this should unroll nicely. */
@@ -136,7 +136,7 @@ ip6_packet_match(const struct sk_buff *skb,
dprintf("VIA in mismatch (%s vs %s).%s\n",
indev, ip6info->iniface,
ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
- return 0;
+ return false;
}
for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
@@ -149,7 +149,7 @@ ip6_packet_match(const struct sk_buff *skb,
dprintf("VIA out mismatch (%s vs %s).%s\n",
outdev, ip6info->outiface,
ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
- return 0;
+ return false;
}
/* ... might want to do something with class and flowlabel here ... */
@@ -162,8 +162,8 @@ ip6_packet_match(const struct sk_buff *skb,
protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
if (protohdr < 0) {
if (_frag_off == 0)
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
*fragoff = _frag_off;
@@ -174,34 +174,34 @@ ip6_packet_match(const struct sk_buff *skb,
if (ip6info->proto == protohdr) {
if(ip6info->invflags & IP6T_INV_PROTO) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* We need match for the '-p all', too! */
if ((ip6info->proto != 0) &&
!(ip6info->invflags & IP6T_INV_PROTO))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* should be ip6 safe */
-static inline int
+static inline bool
ip6_checkentry(const struct ip6t_ip6 *ipv6)
{
if (ipv6->flags & ~IP6T_F_MASK) {
duprintf("Unknown flag bits set: %08X\n",
ipv6->flags & ~IP6T_F_MASK);
- return 0;
+ return false;
}
if (ipv6->invflags & ~IP6T_INV_MASK) {
duprintf("Unknown invflag bits set: %08X\n",
ipv6->invflags & ~IP6T_INV_MASK);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static unsigned int
@@ -219,20 +219,20 @@ ip6t_error(struct sk_buff **pskb,
}
static inline
-int do_match(struct ip6t_entry_match *m,
- const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int offset,
- unsigned int protoff,
- int *hotdrop)
+bool do_match(struct ip6t_entry_match *m,
+ const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int offset,
+ unsigned int protoff,
+ bool *hotdrop)
{
/* Stop iteration if it doesn't match */
if (!m->u.kernel.match->match(skb, in, out, m->u.kernel.match, m->data,
offset, protoff, hotdrop))
- return 1;
+ return true;
else
- return 0;
+ return false;
}
static inline struct ip6t_entry *
@@ -241,6 +241,113 @@ get_entry(void *base, unsigned int offset)
return (struct ip6t_entry *)(base + offset);
}
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ip6t_ip6 *ipv6)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(*ipv6); i++)
+ if (((char *)ipv6)[i])
+ break;
+
+ return (i == sizeof(*ipv6));
+}
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+/* This cries for unification! */
+static const char *hooknames[] = {
+ [NF_IP6_PRE_ROUTING] = "PREROUTING",
+ [NF_IP6_LOCAL_IN] = "INPUT",
+ [NF_IP6_FORWARD] = "FORWARD",
+ [NF_IP6_LOCAL_OUT] = "OUTPUT",
+ [NF_IP6_POST_ROUTING] = "POSTROUTING",
+};
+
+enum nf_ip_trace_comments {
+ NF_IP6_TRACE_COMMENT_RULE,
+ NF_IP6_TRACE_COMMENT_RETURN,
+ NF_IP6_TRACE_COMMENT_POLICY,
+};
+
+static const char *comments[] = {
+ [NF_IP6_TRACE_COMMENT_RULE] = "rule",
+ [NF_IP6_TRACE_COMMENT_RETURN] = "return",
+ [NF_IP6_TRACE_COMMENT_POLICY] = "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+ .type = NF_LOG_TYPE_LOG,
+ .u = {
+ .log = {
+ .level = 4,
+ .logflags = NF_LOG_MASK,
+ },
+ },
+};
+
+static inline int
+get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
+ char *hookname, char **chainname,
+ char **comment, unsigned int *rulenum)
+{
+ struct ip6t_standard_target *t = (void *)ip6t_get_target(s);
+
+ if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
+ /* Head of user chain: ERROR target with chainname */
+ *chainname = t->target.data;
+ (*rulenum) = 0;
+ } else if (s == e) {
+ (*rulenum)++;
+
+ if (s->target_offset == sizeof(struct ip6t_entry)
+ && strcmp(t->target.u.kernel.target->name,
+ IP6T_STANDARD_TARGET) == 0
+ && t->verdict < 0
+ && unconditional(&s->ipv6)) {
+ /* Tail of chains: STANDARD target (return/policy) */
+ *comment = *chainname == hookname
+ ? (char *)comments[NF_IP6_TRACE_COMMENT_POLICY]
+ : (char *)comments[NF_IP6_TRACE_COMMENT_RETURN];
+ }
+ return 1;
+ } else
+ (*rulenum)++;
+
+ return 0;
+}
+
+static void trace_packet(struct sk_buff *skb,
+ unsigned int hook,
+ const struct net_device *in,
+ const struct net_device *out,
+ char *tablename,
+ struct xt_table_info *private,
+ struct ip6t_entry *e)
+{
+ void *table_base;
+ struct ip6t_entry *root;
+ char *hookname, *chainname, *comment;
+ unsigned int rulenum = 0;
+
+ table_base = (void *)private->entries[smp_processor_id()];
+ root = get_entry(table_base, private->hook_entry[hook]);
+
+ hookname = chainname = (char *)hooknames[hook];
+ comment = (char *)comments[NF_IP6_TRACE_COMMENT_RULE];
+
+ IP6T_ENTRY_ITERATE(root,
+ private->size - private->hook_entry[hook],
+ get_chainname_rulenum,
+ e, hookname, &chainname, &comment, &rulenum);
+
+ nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
+ "TRACE: %s:%s:%s:%u ",
+ tablename, chainname, comment, rulenum);
+}
+#endif
+
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
ip6t_do_table(struct sk_buff **pskb,
@@ -252,7 +359,7 @@ ip6t_do_table(struct sk_buff **pskb,
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
int offset = 0;
unsigned int protoff = 0;
- int hotdrop = 0;
+ bool hotdrop = false;
/* Initializing verdict to NF_DROP keeps gcc happy. */
unsigned int verdict = NF_DROP;
const char *indev, *outdev;
@@ -298,6 +405,14 @@ ip6t_do_table(struct sk_buff **pskb,
t = ip6t_get_target(e);
IP_NF_ASSERT(t->u.kernel.target);
+
+#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
+ defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+ /* The packet is traced: log it */
+ if (unlikely((*pskb)->nf_trace))
+ trace_packet(*pskb, hook, in, out,
+ table->name, private, e);
+#endif
/* Standard target? */
if (!t->u.kernel.target->target) {
int v;
@@ -377,19 +492,6 @@ ip6t_do_table(struct sk_buff **pskb,
#endif
}
-/* All zeroes == unconditional rule. */
-static inline int
-unconditional(const struct ip6t_ip6 *ipv6)
-{
- unsigned int i;
-
- for (i = 0; i < sizeof(*ipv6); i++)
- if (((char *)ipv6)[i])
- break;
-
- return (i == sizeof(*ipv6));
-}
-
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
@@ -1282,16 +1384,16 @@ void ip6t_unregister_table(struct xt_table *table)
}
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
-static inline int
+static inline bool
icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
u_int8_t type, u_int8_t code,
- int invert)
+ bool invert)
{
return (type == test_type && code >= min_code && code <= max_code)
^ invert;
}
-static int
+static bool
icmp6_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -1299,22 +1401,22 @@ icmp6_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
struct icmp6hdr _icmp, *ic;
const struct ip6t_icmp *icmpinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
- return 0;
+ return false;
ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
if (ic == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil ICMP tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
return icmp6_type_code_match(icmpinfo->type,
@@ -1325,7 +1427,7 @@ icmp6_match(const struct sk_buff *skb,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
icmp6_checkentry(const char *tablename,
const void *entry,
const struct xt_match *match,
@@ -1339,13 +1441,13 @@ icmp6_checkentry(const char *tablename,
}
/* The built-in targets: standard (NULL) and error. */
-static struct xt_target ip6t_standard_target = {
+static struct xt_target ip6t_standard_target __read_mostly = {
.name = IP6T_STANDARD_TARGET,
.targetsize = sizeof(int),
.family = AF_INET6,
};
-static struct xt_target ip6t_error_target = {
+static struct xt_target ip6t_error_target __read_mostly = {
.name = IP6T_ERROR_TARGET,
.target = ip6t_error,
.targetsize = IP6T_FUNCTION_MAXNAMELEN,
@@ -1362,7 +1464,7 @@ static struct nf_sockopt_ops ip6t_sockopts = {
.get = do_ip6t_get_ctl,
};
-static struct xt_match icmp6_matchstruct = {
+static struct xt_match icmp6_matchstruct __read_mostly = {
.name = "icmp6",
.match = &icmp6_match,
.matchsize = sizeof(struct ip6t_icmp),
@@ -1395,7 +1497,7 @@ static int __init ip6_tables_init(void)
if (ret < 0)
goto err5;
- printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
+ printk(KERN_INFO "ip6_tables: (C) 2000-2006 Netfilter Core Team\n");
return 0;
err5:
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index 4115a576ba2..ad4d94310b8 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -58,28 +58,28 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int ip6t_hl_checkentry(const char *tablename,
+static bool ip6t_hl_checkentry(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask)
{
- struct ip6t_HL_info *info = targinfo;
+ const struct ip6t_HL_info *info = targinfo;
if (info->mode > IP6T_HL_MAXMODE) {
printk(KERN_WARNING "ip6t_HL: invalid or unknown Mode %u\n",
info->mode);
- return 0;
+ return false;
}
- if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
+ if (info->mode != IP6T_HL_SET && info->hop_limit == 0) {
printk(KERN_WARNING "ip6t_HL: increment/decrement doesn't "
"make sense with value 0\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_target ip6t_HL = {
+static struct xt_target ip6t_HL __read_mostly = {
.name = "HL",
.family = AF_INET6,
.target = ip6t_hl_target,
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 5bb9cd34935..b05327ebd33 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -32,12 +32,6 @@ struct in_device;
#include <net/route.h>
#include <linux/netfilter_ipv6/ip6t_LOG.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Use lock to serialize, so printks don't overlap */
static DEFINE_SPINLOCK(log_lock);
@@ -48,7 +42,8 @@ static void dump_packet(const struct nf_loginfo *info,
{
u_int8_t currenthdr;
int fragment;
- struct ipv6hdr _ip6h, *ih;
+ struct ipv6hdr _ip6h;
+ const struct ipv6hdr *ih;
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int logflags;
@@ -78,7 +73,8 @@ static void dump_packet(const struct nf_loginfo *info,
ptr = ip6hoff + sizeof(struct ipv6hdr);
currenthdr = ih->nexthdr;
while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
- struct ipv6_opt_hdr _hdr, *hp;
+ struct ipv6_opt_hdr _hdr;
+ const struct ipv6_opt_hdr *hp;
hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
if (hp == NULL) {
@@ -92,7 +88,8 @@ static void dump_packet(const struct nf_loginfo *info,
switch (currenthdr) {
case IPPROTO_FRAGMENT: {
- struct frag_hdr _fhdr, *fh;
+ struct frag_hdr _fhdr;
+ const struct frag_hdr *fh;
printk("FRAG:");
fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
@@ -131,7 +128,8 @@ static void dump_packet(const struct nf_loginfo *info,
/* Max Length */
case IPPROTO_AH:
if (logflags & IP6T_LOG_IPOPT) {
- struct ip_auth_hdr _ahdr, *ah;
+ struct ip_auth_hdr _ahdr;
+ const struct ip_auth_hdr *ah;
/* Max length: 3 "AH " */
printk("AH ");
@@ -162,7 +160,8 @@ static void dump_packet(const struct nf_loginfo *info,
break;
case IPPROTO_ESP:
if (logflags & IP6T_LOG_IPOPT) {
- struct ip_esp_hdr _esph, *eh;
+ struct ip_esp_hdr _esph;
+ const struct ip_esp_hdr *eh;
/* Max length: 4 "ESP " */
printk("ESP ");
@@ -202,7 +201,8 @@ static void dump_packet(const struct nf_loginfo *info,
switch (currenthdr) {
case IPPROTO_TCP: {
- struct tcphdr _tcph, *th;
+ struct tcphdr _tcph;
+ const struct tcphdr *th;
/* Max length: 10 "PROTO=TCP " */
printk("PROTO=TCP ");
@@ -250,7 +250,8 @@ static void dump_packet(const struct nf_loginfo *info,
if ((logflags & IP6T_LOG_TCPOPT)
&& th->doff * 4 > sizeof(struct tcphdr)) {
- u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
+ u_int8_t _opt[60 - sizeof(struct tcphdr)];
+ const u_int8_t *op;
unsigned int i;
unsigned int optsize = th->doff * 4
- sizeof(struct tcphdr);
@@ -273,7 +274,8 @@ static void dump_packet(const struct nf_loginfo *info,
}
case IPPROTO_UDP:
case IPPROTO_UDPLITE: {
- struct udphdr _udph, *uh;
+ struct udphdr _udph;
+ const struct udphdr *uh;
if (currenthdr == IPPROTO_UDP)
/* Max length: 10 "PROTO=UDP " */
@@ -298,7 +300,8 @@ static void dump_packet(const struct nf_loginfo *info,
break;
}
case IPPROTO_ICMPV6: {
- struct icmp6hdr _icmp6h, *ic;
+ struct icmp6hdr _icmp6h;
+ const struct icmp6hdr *ic;
/* Max length: 13 "PROTO=ICMPv6 " */
printk("PROTO=ICMPv6 ");
@@ -448,27 +451,27 @@ ip6t_log_target(struct sk_buff **pskb,
}
-static int ip6t_log_checkentry(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool ip6t_log_checkentry(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
{
const struct ip6t_log_info *loginfo = targinfo;
if (loginfo->level >= 8) {
- DEBUGP("LOG: level %u >= 8\n", loginfo->level);
- return 0;
+ pr_debug("LOG: level %u >= 8\n", loginfo->level);
+ return false;
}
if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') {
- DEBUGP("LOG: prefix term %i\n",
- loginfo->prefix[sizeof(loginfo->prefix)-1]);
- return 0;
+ pr_debug("LOG: prefix term %i\n",
+ loginfo->prefix[sizeof(loginfo->prefix)-1]);
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_target ip6t_log_reg = {
+static struct xt_target ip6t_log_reg __read_mostly = {
.name = "LOG",
.family = AF_INET6,
.target = ip6t_log_target,
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index cb3d2415a06..2f487cda3b6 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -34,12 +34,6 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
MODULE_DESCRIPTION("IP6 tables REJECT target module");
MODULE_LICENSE("GPL");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Send RST reply */
static void send_reset(struct sk_buff *oldskb)
{
@@ -54,7 +48,7 @@ static void send_reset(struct sk_buff *oldskb)
if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
(!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
- DEBUGP("ip6t_REJECT: addr is not unicast.\n");
+ pr_debug("ip6t_REJECT: addr is not unicast.\n");
return;
}
@@ -62,16 +56,17 @@ static void send_reset(struct sk_buff *oldskb)
tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto);
if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
- DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
+ pr_debug("ip6t_REJECT: Can't get TCP header.\n");
return;
}
otcplen = oldskb->len - tcphoff;
/* IP header checks: fragment, too short. */
- if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
- DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
- proto, otcplen);
+ if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
+ pr_debug("ip6t_REJECT: proto(%d) != IPPROTO_TCP, "
+ "or too short. otcplen = %d\n",
+ proto, otcplen);
return;
}
@@ -80,14 +75,14 @@ static void send_reset(struct sk_buff *oldskb)
/* No RST for RST. */
if (otcph.rst) {
- DEBUGP("ip6t_REJECT: RST is set\n");
+ pr_debug("ip6t_REJECT: RST is set\n");
return;
}
/* Check checksum. */
if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
skb_checksum(oldskb, tcphoff, otcplen, 0))) {
- DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
+ pr_debug("ip6t_REJECT: TCP checksum is invalid\n");
return;
}
@@ -159,7 +154,7 @@ static void send_reset(struct sk_buff *oldskb)
tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
&ipv6_hdr(nskb)->daddr,
sizeof(struct tcphdr), IPPROTO_TCP,
- csum_partial((char *)tcph,
+ csum_partial(tcph,
sizeof(struct tcphdr), 0));
nf_ct_attach(nskb, oldskb);
@@ -186,7 +181,7 @@ static unsigned int reject6_target(struct sk_buff **pskb,
{
const struct ip6t_reject_info *reject = targinfo;
- DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
+ pr_debug("%s: medium point\n", __FUNCTION__);
/* WARNING: This code causes reentry within ip6tables.
This means that the ip6tables jump stack is now crap. We
must return an absolute verdict. --RR */
@@ -221,30 +216,30 @@ static unsigned int reject6_target(struct sk_buff **pskb,
return NF_DROP;
}
-static int check(const char *tablename,
- const void *entry,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool check(const char *tablename,
+ const void *entry,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
{
const struct ip6t_reject_info *rejinfo = targinfo;
const struct ip6t_entry *e = entry;
if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
- return 0;
+ return false;
} else if (rejinfo->with == IP6T_TCP_RESET) {
/* Must specify that it's a TCP packet */
if (e->ipv6.proto != IPPROTO_TCP
|| (e->ipv6.invflags & XT_INV_PROTO)) {
- DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
- return 0;
+ printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
+ return false;
}
}
- return 1;
+ return true;
}
-static struct xt_target ip6t_reject_reg = {
+static struct xt_target ip6t_reject_reg __read_mostly = {
.name = "REJECT",
.family = AF_INET6,
.target = reject6_target,
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index d3c154371b4..2a25fe25e0e 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -23,25 +23,20 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IPv6 AH match");
MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
{
- int r=0;
- DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,spi,max);
+ bool r;
+
+ pr_debug("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",
+ invert ? '!' : ' ', min, spi, max);
r = (spi >= min && spi <= max) ^ invert;
- DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
+ pr_debug(" result %s\n", r ? "PASS" : "FAILED");
return r;
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -49,9 +44,10 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
- struct ip_auth_hdr *ah, _ah;
+ struct ip_auth_hdr _ah;
+ const struct ip_auth_hdr *ah;
const struct ip6t_ah *ahinfo = matchinfo;
unsigned int ptr;
unsigned int hdrlen = 0;
@@ -60,40 +56,40 @@ match(const struct sk_buff *skb,
err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
if (err < 0) {
if (err != -ENOENT)
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
if (ah == NULL) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
hdrlen = (ah->hdrlen + 2) << 2;
- DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
- DEBUGP("RES %04X ", ah->reserved);
- DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
-
- DEBUGP("IPv6 AH spi %02X ",
- (spi_match(ahinfo->spis[0], ahinfo->spis[1],
- ntohl(ah->spi),
- !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
- DEBUGP("len %02X %04X %02X ",
- ahinfo->hdrlen, hdrlen,
- (!ahinfo->hdrlen ||
- (ahinfo->hdrlen == hdrlen) ^
- !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
- DEBUGP("res %02X %04X %02X\n",
- ahinfo->hdrres, ah->reserved,
- !(ahinfo->hdrres && ah->reserved));
+ pr_debug("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
+ pr_debug("RES %04X ", ah->reserved);
+ pr_debug("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
+
+ pr_debug("IPv6 AH spi %02X ",
+ spi_match(ahinfo->spis[0], ahinfo->spis[1],
+ ntohl(ah->spi),
+ !!(ahinfo->invflags & IP6T_AH_INV_SPI)));
+ pr_debug("len %02X %04X %02X ",
+ ahinfo->hdrlen, hdrlen,
+ (!ahinfo->hdrlen ||
+ (ahinfo->hdrlen == hdrlen) ^
+ !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
+ pr_debug("res %02X %04X %02X\n",
+ ahinfo->hdrres, ah->reserved,
+ !(ahinfo->hdrres && ah->reserved));
return (ah != NULL)
&&
- (spi_match(ahinfo->spis[0], ahinfo->spis[1],
- ntohl(ah->spi),
- !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
+ spi_match(ahinfo->spis[0], ahinfo->spis[1],
+ ntohl(ah->spi),
+ !!(ahinfo->invflags & IP6T_AH_INV_SPI))
&&
(!ahinfo->hdrlen ||
(ahinfo->hdrlen == hdrlen) ^
@@ -103,7 +99,7 @@ match(const struct sk_buff *skb,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
checkentry(const char *tablename,
const void *entry,
const struct xt_match *match,
@@ -113,13 +109,13 @@ checkentry(const char *tablename,
const struct ip6t_ah *ahinfo = matchinfo;
if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
- DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
- return 0;
+ pr_debug("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match ah_match = {
+static struct xt_match ah_match __read_mostly = {
.name = "ah",
.family = AF_INET6,
.match = match,
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 0f3dd932f0a..34ba150bfe5 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -19,7 +19,7 @@ MODULE_DESCRIPTION("IPv6 EUI64 address checking match");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -27,16 +27,16 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
unsigned char eui64[8];
int i = 0;
if (!(skb_mac_header(skb) >= skb->head &&
- (skb_mac_header(skb) + ETH_HLEN) <= skb->data) &&
+ skb_mac_header(skb) + ETH_HLEN <= skb->data) &&
offset != 0) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
memset(eui64, 0, sizeof(eui64));
@@ -50,19 +50,19 @@ match(const struct sk_buff *skb,
eui64[0] |= 0x02;
i = 0;
- while ((ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i])
- && (i < 8))
+ while (ipv6_hdr(skb)->saddr.s6_addr[8 + i] == eui64[i]
+ && i < 8)
i++;
if (i == 8)
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
-static struct xt_match eui64_match = {
+static struct xt_match eui64_match __read_mostly = {
.name = "eui64",
.family = AF_INET6,
.match = match,
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 5a5da71321b..968aeba0207 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -22,25 +22,19 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IPv6 FRAG match");
MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Returns 1 if the id is matched by the range, 0 otherwise */
-static inline int
-id_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
+static inline bool
+id_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert)
{
- int r = 0;
- DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
- min, id, max);
+ bool r;
+ pr_debug("frag id_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
+ min, id, max);
r = (id >= min && id <= max) ^ invert;
- DEBUGP(" result %s\n", r ? "PASS" : "FAILED");
+ pr_debug(" result %s\n", r ? "PASS" : "FAILED");
return r;
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -48,9 +42,10 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
- struct frag_hdr _frag, *fh;
+ struct frag_hdr _frag;
+ const struct frag_hdr *fh;
const struct ip6t_frag *fraginfo = matchinfo;
unsigned int ptr;
int err;
@@ -58,53 +53,53 @@ match(const struct sk_buff *skb,
err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
if (err < 0) {
if (err != -ENOENT)
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
if (fh == NULL) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
- DEBUGP("INFO %04X ", fh->frag_off);
- DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
- DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
- DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF));
- DEBUGP("ID %u %08X\n", ntohl(fh->identification),
- ntohl(fh->identification));
-
- DEBUGP("IPv6 FRAG id %02X ",
- (id_match(fraginfo->ids[0], fraginfo->ids[1],
- ntohl(fh->identification),
- !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
- DEBUGP("res %02X %02X%04X %02X ",
- (fraginfo->flags & IP6T_FRAG_RES), fh->reserved,
- ntohs(fh->frag_off) & 0x6,
- !((fraginfo->flags & IP6T_FRAG_RES)
- && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
- DEBUGP("first %02X %02X %02X ",
- (fraginfo->flags & IP6T_FRAG_FST),
- ntohs(fh->frag_off) & ~0x7,
- !((fraginfo->flags & IP6T_FRAG_FST)
- && (ntohs(fh->frag_off) & ~0x7)));
- DEBUGP("mf %02X %02X %02X ",
- (fraginfo->flags & IP6T_FRAG_MF),
- ntohs(fh->frag_off) & IP6_MF,
- !((fraginfo->flags & IP6T_FRAG_MF)
- && !((ntohs(fh->frag_off) & IP6_MF))));
- DEBUGP("last %02X %02X %02X\n",
- (fraginfo->flags & IP6T_FRAG_NMF),
- ntohs(fh->frag_off) & IP6_MF,
- !((fraginfo->flags & IP6T_FRAG_NMF)
- && (ntohs(fh->frag_off) & IP6_MF)));
+ pr_debug("INFO %04X ", fh->frag_off);
+ pr_debug("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
+ pr_debug("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
+ pr_debug("MF %04X ", fh->frag_off & htons(IP6_MF));
+ pr_debug("ID %u %08X\n", ntohl(fh->identification),
+ ntohl(fh->identification));
+
+ pr_debug("IPv6 FRAG id %02X ",
+ id_match(fraginfo->ids[0], fraginfo->ids[1],
+ ntohl(fh->identification),
+ !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)));
+ pr_debug("res %02X %02X%04X %02X ",
+ fraginfo->flags & IP6T_FRAG_RES, fh->reserved,
+ ntohs(fh->frag_off) & 0x6,
+ !((fraginfo->flags & IP6T_FRAG_RES)
+ && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
+ pr_debug("first %02X %02X %02X ",
+ fraginfo->flags & IP6T_FRAG_FST,
+ ntohs(fh->frag_off) & ~0x7,
+ !((fraginfo->flags & IP6T_FRAG_FST)
+ && (ntohs(fh->frag_off) & ~0x7)));
+ pr_debug("mf %02X %02X %02X ",
+ fraginfo->flags & IP6T_FRAG_MF,
+ ntohs(fh->frag_off) & IP6_MF,
+ !((fraginfo->flags & IP6T_FRAG_MF)
+ && !((ntohs(fh->frag_off) & IP6_MF))));
+ pr_debug("last %02X %02X %02X\n",
+ fraginfo->flags & IP6T_FRAG_NMF,
+ ntohs(fh->frag_off) & IP6_MF,
+ !((fraginfo->flags & IP6T_FRAG_NMF)
+ && (ntohs(fh->frag_off) & IP6_MF)));
return (fh != NULL)
&&
- (id_match(fraginfo->ids[0], fraginfo->ids[1],
- ntohl(fh->identification),
- !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
+ id_match(fraginfo->ids[0], fraginfo->ids[1],
+ ntohl(fh->identification),
+ !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))
&&
!((fraginfo->flags & IP6T_FRAG_RES)
&& (fh->reserved || (ntohs(fh->frag_off) & 0x6)))
@@ -120,7 +115,7 @@ match(const struct sk_buff *skb,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
@@ -130,13 +125,13 @@ checkentry(const char *tablename,
const struct ip6t_frag *fraginfo = matchinfo;
if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
- DEBUGP("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
- return 0;
+ pr_debug("ip6t_frag: unknown flags %X\n", fraginfo->invflags);
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match frag_match = {
+static struct xt_match frag_match __read_mostly = {
.name = "frag",
.family = AF_INET6,
.match = match,
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index d2373c7cd35..e6ca6018b1e 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -25,12 +25,6 @@ MODULE_DESCRIPTION("IPv6 opts match");
MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
MODULE_ALIAS("ip6t_dst");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/*
* (Type & 0xC0) >> 6
* 0 -> ignorable
@@ -47,7 +41,7 @@ MODULE_ALIAS("ip6t_dst");
* 5 -> RTALERT 2 x x
*/
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -55,45 +49,48 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
- struct ipv6_opt_hdr _optsh, *oh;
+ struct ipv6_opt_hdr _optsh;
+ const struct ipv6_opt_hdr *oh;
const struct ip6t_opts *optinfo = matchinfo;
unsigned int temp;
unsigned int ptr;
unsigned int hdrlen = 0;
- unsigned int ret = 0;
- u8 _opttype, *tp = NULL;
- u8 _optlen, *lp = NULL;
+ bool ret = false;
+ u8 _opttype;
+ u8 _optlen;
+ const u_int8_t *tp = NULL;
+ const u_int8_t *lp = NULL;
unsigned int optlen;
int err;
err = ipv6_find_hdr(skb, &ptr, match->data, NULL);
if (err < 0) {
if (err != -ENOENT)
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
if (oh == NULL) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
hdrlen = ipv6_optlen(oh);
if (skb->len - ptr < hdrlen) {
/* Packet smaller than it's length field */
- return 0;
+ return false;
}
- DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
+ pr_debug("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
- DEBUGP("len %02X %04X %02X ",
- optinfo->hdrlen, hdrlen,
- (!(optinfo->flags & IP6T_OPTS_LEN) ||
- ((optinfo->hdrlen == hdrlen) ^
- !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
+ pr_debug("len %02X %04X %02X ",
+ optinfo->hdrlen, hdrlen,
+ (!(optinfo->flags & IP6T_OPTS_LEN) ||
+ ((optinfo->hdrlen == hdrlen) ^
+ !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
ret = (oh != NULL) &&
(!(optinfo->flags & IP6T_OPTS_LEN) ||
@@ -105,10 +102,10 @@ match(const struct sk_buff *skb,
if (!(optinfo->flags & IP6T_OPTS_OPTS)) {
return ret;
} else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
- DEBUGP("Not strict - not implemented");
+ pr_debug("Not strict - not implemented");
} else {
- DEBUGP("Strict ");
- DEBUGP("#%d ", optinfo->optsnr);
+ pr_debug("Strict ");
+ pr_debug("#%d ", optinfo->optsnr);
for (temp = 0; temp < optinfo->optsnr; temp++) {
/* type field exists ? */
if (hdrlen < 1)
@@ -120,12 +117,11 @@ match(const struct sk_buff *skb,
/* Type check */
if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) {
- DEBUGP("Tbad %02X %02X\n",
- *tp,
- (optinfo->opts[temp] & 0xFF00) >> 8);
- return 0;
+ pr_debug("Tbad %02X %02X\n", *tp,
+ (optinfo->opts[temp] & 0xFF00) >> 8);
+ return false;
} else {
- DEBUGP("Tok ");
+ pr_debug("Tok ");
}
/* Length check */
if (*tp) {
@@ -142,23 +138,23 @@ match(const struct sk_buff *skb,
spec_len = optinfo->opts[temp] & 0x00FF;
if (spec_len != 0x00FF && spec_len != *lp) {
- DEBUGP("Lbad %02X %04X\n", *lp,
- spec_len);
- return 0;
+ pr_debug("Lbad %02X %04X\n", *lp,
+ spec_len);
+ return false;
}
- DEBUGP("Lok ");
+ pr_debug("Lok ");
optlen = *lp + 2;
} else {
- DEBUGP("Pad1\n");
+ pr_debug("Pad1\n");
optlen = 1;
}
/* Step to the next */
- DEBUGP("len%04X \n", optlen);
+ pr_debug("len%04X \n", optlen);
if ((ptr > skb->len - optlen || hdrlen < optlen) &&
- (temp < optinfo->optsnr - 1)) {
- DEBUGP("new pointer is too large! \n");
+ temp < optinfo->optsnr - 1) {
+ pr_debug("new pointer is too large! \n");
break;
}
ptr += optlen;
@@ -167,14 +163,14 @@ match(const struct sk_buff *skb,
if (temp == optinfo->optsnr)
return ret;
else
- return 0;
+ return false;
}
- return 0;
+ return false;
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
checkentry(const char *tablename,
const void *entry,
const struct xt_match *match,
@@ -184,13 +180,13 @@ checkentry(const char *tablename,
const struct ip6t_opts *optsinfo = matchinfo;
if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
- DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
- return 0;
+ pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags);
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match opts_match[] = {
+static struct xt_match opts_match[] __read_mostly = {
{
.name = "hbh",
.family = AF_INET6,
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index d606c0e6d6f..ca29ec00dc1 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -19,37 +19,37 @@ MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
MODULE_DESCRIPTION("IP tables Hop Limit matching module");
MODULE_LICENSE("GPL");
-static int match(const struct sk_buff *skb,
- const struct net_device *in, const struct net_device *out,
- const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+static bool match(const struct sk_buff *skb,
+ const struct net_device *in, const struct net_device *out,
+ const struct xt_match *match, const void *matchinfo,
+ int offset, unsigned int protoff, bool *hotdrop)
{
const struct ip6t_hl_info *info = matchinfo;
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
switch (info->mode) {
case IP6T_HL_EQ:
- return (ip6h->hop_limit == info->hop_limit);
+ return ip6h->hop_limit == info->hop_limit;
break;
case IP6T_HL_NE:
- return (!(ip6h->hop_limit == info->hop_limit));
+ return ip6h->hop_limit != info->hop_limit;
break;
case IP6T_HL_LT:
- return (ip6h->hop_limit < info->hop_limit);
+ return ip6h->hop_limit < info->hop_limit;
break;
case IP6T_HL_GT:
- return (ip6h->hop_limit > info->hop_limit);
+ return ip6h->hop_limit > info->hop_limit;
break;
default:
printk(KERN_WARNING "ip6t_hl: unknown mode %d\n",
info->mode);
- return 0;
+ return false;
}
- return 0;
+ return false;
}
-static struct xt_match hl_match = {
+static struct xt_match hl_match __read_mostly = {
.name = "hl",
.family = AF_INET6,
.match = match,
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index fd6a0869099..2c65c2f9a4a 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -26,7 +26,7 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IPv6 headers match");
MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
-static int
+static bool
ipv6header_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -34,7 +34,7 @@ ipv6header_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct ip6t_ipv6header_info *info = matchinfo;
unsigned int temp;
@@ -58,7 +58,7 @@ ipv6header_match(const struct sk_buff *skb,
/* Is there enough space for the next ext header? */
if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
+ return false;
/* No more exthdr -> evaluate */
if (nexthdr == NEXTHDR_NONE) {
temp |= MASK_NONE;
@@ -74,9 +74,9 @@ ipv6header_match(const struct sk_buff *skb,
BUG_ON(hp == NULL);
/* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
+ if (nexthdr == NEXTHDR_FRAGMENT)
hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
+ else if (nexthdr == NEXTHDR_AUTH)
hdrlen = (hp->hdrlen + 2) << 2;
else
hdrlen = ipv6_optlen(hp);
@@ -99,7 +99,7 @@ ipv6header_match(const struct sk_buff *skb,
temp |= MASK_DSTOPTS;
break;
default:
- return 0;
+ return false;
break;
}
@@ -110,7 +110,7 @@ ipv6header_match(const struct sk_buff *skb,
break;
}
- if ((nexthdr != NEXTHDR_NONE) && (nexthdr != NEXTHDR_ESP))
+ if (nexthdr != NEXTHDR_NONE && nexthdr != NEXTHDR_ESP)
temp |= MASK_PROTO;
if (info->modeflag)
@@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb,
}
}
-static int
+static bool
ipv6header_checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
@@ -136,12 +136,12 @@ ipv6header_checkentry(const char *tablename,
/* invflags is 0 or 0xff in hard mode */
if ((!info->modeflag) && info->invflags != 0x00 &&
info->invflags != 0xFF)
- return 0;
+ return false;
- return 1;
+ return true;
}
-static struct xt_match ip6t_ipv6header_match = {
+static struct xt_match ip6t_ipv6header_match __read_mostly = {
.name = "ipv6header",
.family = AF_INET6,
.match = &ipv6header_match,
diff --git a/net/ipv6/netfilter/ip6t_mh.c b/net/ipv6/netfilter/ip6t_mh.c
index c2a909893a6..0fa714092dc 100644
--- a/net/ipv6/netfilter/ip6t_mh.c
+++ b/net/ipv6/netfilter/ip6t_mh.c
@@ -31,16 +31,13 @@ MODULE_LICENSE("GPL");
#endif
/* Returns 1 if the type is matched by the range, 0 otherwise */
-static inline int
-type_match(u_int8_t min, u_int8_t max, u_int8_t type, int invert)
+static inline bool
+type_match(u_int8_t min, u_int8_t max, u_int8_t type, bool invert)
{
- int ret;
-
- ret = (type >= min && type <= max) ^ invert;
- return ret;
+ return (type >= min && type <= max) ^ invert;
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -48,29 +45,30 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
- struct ip6_mh _mh, *mh;
+ struct ip6_mh _mh;
+ const struct ip6_mh *mh;
const struct ip6t_mh *mhinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
- return 0;
+ return false;
mh = skb_header_pointer(skb, protoff, sizeof(_mh), &_mh);
if (mh == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil MH tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
if (mh->ip6mh_proto != IPPROTO_NONE) {
duprintf("Dropping invalid MH Payload Proto: %u\n",
mh->ip6mh_proto);
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
return type_match(mhinfo->types[0], mhinfo->types[1], mh->ip6mh_type,
@@ -78,7 +76,7 @@ match(const struct sk_buff *skb,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
mh_checkentry(const char *tablename,
const void *entry,
const struct xt_match *match,
@@ -91,7 +89,7 @@ mh_checkentry(const char *tablename,
return !(mhinfo->invflags & ~IP6T_MH_INV_MASK);
}
-static struct xt_match mh_match = {
+static struct xt_match mh_match __read_mostly = {
.name = "mh",
.family = AF_INET6,
.checkentry = mh_checkentry,
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 43738bba00b..6036613aef3 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -23,7 +23,7 @@ MODULE_DESCRIPTION("IP6 tables owner matching module");
MODULE_LICENSE("GPL");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -31,29 +31,27 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct ip6t_owner_info *info = matchinfo;
if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
- return 0;
+ return false;
- if (info->match & IP6T_OWNER_UID) {
+ if (info->match & IP6T_OWNER_UID)
if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
!!(info->invert & IP6T_OWNER_UID))
- return 0;
- }
+ return false;
- if (info->match & IP6T_OWNER_GID) {
+ if (info->match & IP6T_OWNER_GID)
if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
!!(info->invert & IP6T_OWNER_GID))
- return 0;
- }
+ return false;
- return 1;
+ return true;
}
-static int
+static bool
checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
@@ -65,12 +63,12 @@ checkentry(const char *tablename,
if (info->match & (IP6T_OWNER_PID | IP6T_OWNER_SID)) {
printk("ipt_owner: pid and sid matching "
"not supported anymore\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match owner_match = {
+static struct xt_match owner_match __read_mostly = {
.name = "owner",
.family = AF_INET6,
.match = match,
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 81ab00d8c18..357cea703bd 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -24,25 +24,19 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IPv6 RT match");
MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Returns 1 if the id is matched by the range, 0 otherwise */
-static inline int
-segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
+static inline bool
+segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, bool invert)
{
- int r = 0;
- DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",
- invert ? '!' : ' ', min, id, max);
+ bool r;
+ pr_debug("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",
+ invert ? '!' : ' ', min, id, max);
r = (id >= min && id <= max) ^ invert;
- DEBUGP(" result %s\n", r ? "PASS" : "FAILED");
+ pr_debug(" result %s\n", r ? "PASS" : "FAILED");
return r;
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -50,59 +44,61 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
- struct ipv6_rt_hdr _route, *rh;
+ struct ipv6_rt_hdr _route;
+ const struct ipv6_rt_hdr *rh;
const struct ip6t_rt *rtinfo = matchinfo;
unsigned int temp;
unsigned int ptr;
unsigned int hdrlen = 0;
- unsigned int ret = 0;
- struct in6_addr *ap, _addr;
+ bool ret = false;
+ struct in6_addr _addr;
+ const struct in6_addr *ap;
int err;
err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
if (err < 0) {
if (err != -ENOENT)
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
if (rh == NULL) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
hdrlen = ipv6_optlen(rh);
if (skb->len - ptr < hdrlen) {
/* Pcket smaller than its length field */
- return 0;
+ return false;
}
- DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
- DEBUGP("TYPE %04X ", rh->type);
- DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
-
- DEBUGP("IPv6 RT segsleft %02X ",
- (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
- rh->segments_left,
- !!(rtinfo->invflags & IP6T_RT_INV_SGS))));
- DEBUGP("type %02X %02X %02X ",
- rtinfo->rt_type, rh->type,
- (!(rtinfo->flags & IP6T_RT_TYP) ||
- ((rtinfo->rt_type == rh->type) ^
- !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
- DEBUGP("len %02X %04X %02X ",
- rtinfo->hdrlen, hdrlen,
- (!(rtinfo->flags & IP6T_RT_LEN) ||
- ((rtinfo->hdrlen == hdrlen) ^
- !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
- DEBUGP("res %02X %02X %02X ",
- (rtinfo->flags & IP6T_RT_RES),
- ((struct rt0_hdr *)rh)->reserved,
- !((rtinfo->flags & IP6T_RT_RES) &&
- (((struct rt0_hdr *)rh)->reserved)));
+ pr_debug("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
+ pr_debug("TYPE %04X ", rh->type);
+ pr_debug("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
+
+ pr_debug("IPv6 RT segsleft %02X ",
+ segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
+ rh->segments_left,
+ !!(rtinfo->invflags & IP6T_RT_INV_SGS)));
+ pr_debug("type %02X %02X %02X ",
+ rtinfo->rt_type, rh->type,
+ (!(rtinfo->flags & IP6T_RT_TYP) ||
+ ((rtinfo->rt_type == rh->type) ^
+ !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
+ pr_debug("len %02X %04X %02X ",
+ rtinfo->hdrlen, hdrlen,
+ !(rtinfo->flags & IP6T_RT_LEN) ||
+ ((rtinfo->hdrlen == hdrlen) ^
+ !!(rtinfo->invflags & IP6T_RT_INV_LEN)));
+ pr_debug("res %02X %02X %02X ",
+ rtinfo->flags & IP6T_RT_RES,
+ ((const struct rt0_hdr *)rh)->reserved,
+ !((rtinfo->flags & IP6T_RT_RES) &&
+ (((const struct rt0_hdr *)rh)->reserved)));
ret = (rh != NULL)
&&
@@ -129,18 +125,18 @@ match(const struct sk_buff *skb,
ret = (*rp == 0);
}
- DEBUGP("#%d ", rtinfo->addrnr);
+ pr_debug("#%d ", rtinfo->addrnr);
if (!(rtinfo->flags & IP6T_RT_FST)) {
return ret;
} else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) {
- DEBUGP("Not strict ");
+ pr_debug("Not strict ");
if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) {
- DEBUGP("There isn't enough space\n");
- return 0;
+ pr_debug("There isn't enough space\n");
+ return false;
} else {
unsigned int i = 0;
- DEBUGP("#%d ", rtinfo->addrnr);
+ pr_debug("#%d ", rtinfo->addrnr);
for (temp = 0;
temp < (unsigned int)((hdrlen - 8) / 16);
temp++) {
@@ -154,25 +150,25 @@ match(const struct sk_buff *skb,
BUG_ON(ap == NULL);
if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) {
- DEBUGP("i=%d temp=%d;\n", i, temp);
+ pr_debug("i=%d temp=%d;\n", i, temp);
i++;
}
if (i == rtinfo->addrnr)
break;
}
- DEBUGP("i=%d #%d\n", i, rtinfo->addrnr);
+ pr_debug("i=%d #%d\n", i, rtinfo->addrnr);
if (i == rtinfo->addrnr)
return ret;
else
- return 0;
+ return false;
}
} else {
- DEBUGP("Strict ");
+ pr_debug("Strict ");
if (rtinfo->addrnr > (unsigned int)((hdrlen - 8) / 16)) {
- DEBUGP("There isn't enough space\n");
- return 0;
+ pr_debug("There isn't enough space\n");
+ return false;
} else {
- DEBUGP("#%d ", rtinfo->addrnr);
+ pr_debug("#%d ", rtinfo->addrnr);
for (temp = 0; temp < rtinfo->addrnr; temp++) {
ap = skb_header_pointer(skb,
ptr
@@ -185,20 +181,20 @@ match(const struct sk_buff *skb,
if (!ipv6_addr_equal(ap, &rtinfo->addrs[temp]))
break;
}
- DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr);
- if ((temp == rtinfo->addrnr) &&
- (temp == (unsigned int)((hdrlen - 8) / 16)))
+ pr_debug("temp=%d #%d\n", temp, rtinfo->addrnr);
+ if (temp == rtinfo->addrnr &&
+ temp == (unsigned int)((hdrlen - 8) / 16))
return ret;
else
- return 0;
+ return false;
}
}
- return 0;
+ return false;
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
checkentry(const char *tablename,
const void *entry,
const struct xt_match *match,
@@ -208,21 +204,21 @@ checkentry(const char *tablename,
const struct ip6t_rt *rtinfo = matchinfo;
if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
- DEBUGP("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
- return 0;
+ pr_debug("ip6t_rt: unknown flags %X\n", rtinfo->invflags);
+ return false;
}
if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) &&
(!(rtinfo->flags & IP6T_RT_TYP) ||
(rtinfo->rt_type != 0) ||
(rtinfo->invflags & IP6T_RT_INV_TYP))) {
- DEBUGP("`--rt-type 0' required before `--rt-0-*'");
- return 0;
+ pr_debug("`--rt-type 0' required before `--rt-0-*'");
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match rt_match = {
+static struct xt_match rt_match __read_mostly = {
.name = "rt",
.family = AF_INET6,
.match = match,
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index f2d26495f41..f0a9efa67fb 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -21,12 +21,6 @@ MODULE_DESCRIPTION("ip6tables mangle table");
(1 << NF_IP6_LOCAL_OUT) | \
(1 << NF_IP6_POST_ROUTING))
-#if 0
-#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
static struct
{
struct ip6t_replace repl;
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 0acda45d455..ec290e4ebdd 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -8,12 +8,6 @@
#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
-#if 0
-#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
static struct
{
struct ip6t_replace repl;
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 6d2a0820511..36df2218b66 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -26,12 +26,6 @@
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
@@ -92,7 +86,7 @@ static int ipv6_print_conntrack(struct seq_file *s,
* - Note also special handling of AUTH header. Thanks to IPsec wizards.
*/
-int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp,
+int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
int len)
{
u8 nexthdr = *nexthdrp;
@@ -123,22 +117,25 @@ int nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp,
return start;
}
-static int
-ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
- u_int8_t *protonum)
+static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
+ unsigned int *dataoff, u_int8_t *protonum)
{
- unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
- unsigned char pnum = ipv6_hdr(*pskb)->nexthdr;
- int protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
- (*pskb)->len - extoff);
+ unsigned int extoff = nhoff + sizeof(struct ipv6hdr);
+ unsigned char pnum;
+ int protoff;
+
+ if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr),
+ &pnum, sizeof(pnum)) != 0) {
+ pr_debug("ip6_conntrack_core: can't get nexthdr\n");
+ return -NF_ACCEPT;
+ }
+ protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff);
/*
- * (protoff == (*pskb)->len) mean that the packet doesn't have no data
+ * (protoff == skb->len) mean that the packet doesn't have no data
* except of IPv6 & ext headers. but it's tracked anyway. - YK
*/
- if ((protoff < 0) || (protoff > (*pskb)->len)) {
- DEBUGP("ip6_conntrack_core: can't find proto in pkt\n");
- NF_CT_STAT_INC_ATOMIC(error);
- NF_CT_STAT_INC_ATOMIC(invalid);
+ if ((protoff < 0) || (protoff > skb->len)) {
+ pr_debug("ip6_conntrack_core: can't find proto in pkt\n");
return -NF_ACCEPT;
}
@@ -147,11 +144,6 @@ ipv6_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
return NF_ACCEPT;
}
-static u_int32_t ipv6_get_features(const struct nf_conntrack_tuple *tuple)
-{
- return NF_CT_F_BASIC;
-}
-
static unsigned int ipv6_confirm(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
@@ -160,6 +152,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
{
struct nf_conn *ct;
struct nf_conn_help *help;
+ struct nf_conntrack_helper *helper;
enum ip_conntrack_info ctinfo;
unsigned int ret, protoff;
unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
@@ -172,18 +165,21 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
goto out;
help = nfct_help(ct);
- if (!help || !help->helper)
+ if (!help)
+ goto out;
+ /* rcu_read_lock()ed by nf_hook_slow */
+ helper = rcu_dereference(help->helper);
+ if (!helper)
goto out;
protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
(*pskb)->len - extoff);
- if (protoff < 0 || protoff > (*pskb)->len ||
- pnum == NEXTHDR_FRAGMENT) {
- DEBUGP("proto header not found\n");
+ if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) {
+ pr_debug("proto header not found\n");
return NF_ACCEPT;
}
- ret = help->helper->help(pskb, protoff, ct, ctinfo);
+ ret = helper->help(pskb, protoff, ct, ctinfo);
if (ret != NF_ACCEPT)
return ret;
out:
@@ -377,14 +373,14 @@ static int ipv6_nfattr_to_tuple(struct nfattr *tb[],
}
#endif
-struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
+struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
.l3proto = PF_INET6,
.name = "ipv6",
.pkt_to_tuple = ipv6_pkt_to_tuple,
.invert_tuple = ipv6_invert_tuple,
.print_tuple = ipv6_print_tuple,
.print_conntrack = ipv6_print_conntrack,
- .prepare = ipv6_prepare,
+ .get_l4proto = ipv6_get_l4proto,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
.tuple_to_nfattr = ipv6_tuple_to_nfattr,
.nfattr_to_tuple = ipv6_nfattr_to_tuple,
@@ -393,7 +389,6 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = {
.ctl_table_path = nf_net_netfilter_sysctl_path,
.ctl_table = nf_ct_ipv6_sysctl_table,
#endif
- .get_features = ipv6_get_features,
.me = THIS_MODULE,
};
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 0be790d250f..ab154fb9001 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -27,12 +27,6 @@
static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ;
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
static int icmpv6_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
@@ -125,8 +119,8 @@ static int icmpv6_new(struct nf_conn *conntrack,
if (type < 0 || type >= sizeof(valid_new) || !valid_new[type]) {
/* Can't create a new ICMPv6 `conn' with this. */
- DEBUGP("icmpv6: can't create new conn with type %u\n",
- type + 128);
+ pr_debug("icmpv6: can't create new conn with type %u\n",
+ type + 128);
NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
return 0;
}
@@ -142,61 +136,36 @@ icmpv6_error_message(struct sk_buff *skb,
{
struct nf_conntrack_tuple intuple, origtuple;
struct nf_conntrack_tuple_hash *h;
- struct icmp6hdr _hdr, *hp;
- unsigned int inip6off;
struct nf_conntrack_l4proto *inproto;
- u_int8_t inprotonum;
- unsigned int inprotoff;
NF_CT_ASSERT(skb->nfct == NULL);
- hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr);
- if (hp == NULL) {
- DEBUGP("icmpv6_error: Can't get ICMPv6 hdr.\n");
- return -NF_ACCEPT;
- }
-
- inip6off = icmp6off + sizeof(_hdr);
- if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr),
- &inprotonum, sizeof(inprotonum)) != 0) {
- DEBUGP("icmpv6_error: Can't get nexthdr in inner IPv6 header.\n");
- return -NF_ACCEPT;
- }
- inprotoff = nf_ct_ipv6_skip_exthdr(skb,
- inip6off + sizeof(struct ipv6hdr),
- &inprotonum,
- skb->len - inip6off
- - sizeof(struct ipv6hdr));
-
- if ((inprotoff < 0) || (inprotoff > skb->len) ||
- (inprotonum == NEXTHDR_FRAGMENT)) {
- DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n");
+ /* Are they talking about one of our connections? */
+ if (!nf_ct_get_tuplepr(skb,
+ skb_network_offset(skb)
+ + sizeof(struct ipv6hdr)
+ + sizeof(struct icmp6hdr),
+ PF_INET6, &origtuple)) {
+ pr_debug("icmpv6_error: Can't get tuple\n");
return -NF_ACCEPT;
}
/* rcu_read_lock()ed by nf_hook_slow */
- inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum);
-
- /* Are they talking about one of our connections? */
- if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
- &origtuple, &nf_conntrack_l3proto_ipv6, inproto)) {
- DEBUGP("icmpv6_error: Can't get tuple\n");
- return -NF_ACCEPT;
- }
+ inproto = __nf_ct_l4proto_find(PF_INET6, origtuple.dst.protonum);
/* Ordinarily, we'd expect the inverted tupleproto, but it's
been preserved inside the ICMP. */
if (!nf_ct_invert_tuple(&intuple, &origtuple,
&nf_conntrack_l3proto_ipv6, inproto)) {
- DEBUGP("icmpv6_error: Can't invert tuple\n");
+ pr_debug("icmpv6_error: Can't invert tuple\n");
return -NF_ACCEPT;
}
*ctinfo = IP_CT_RELATED;
- h = nf_conntrack_find_get(&intuple, NULL);
+ h = nf_conntrack_find_get(&intuple);
if (!h) {
- DEBUGP("icmpv6_error: no match\n");
+ pr_debug("icmpv6_error: no match\n");
return -NF_ACCEPT;
} else {
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
@@ -307,7 +276,7 @@ static struct ctl_table icmpv6_sysctl_table[] = {
};
#endif /* CONFIG_SYSCTL */
-struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
{
.l3proto = PF_INET6,
.l4proto = IPPROTO_ICMPV6,
@@ -328,5 +297,3 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
.ctl_table = icmpv6_sysctl_table,
#endif
};
-
-EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6);
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 347ab760823..25442a8c1ba 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -44,12 +44,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
#define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */
#define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */
#define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT
@@ -343,7 +337,7 @@ nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, str
struct nf_ct_frag6_queue *fq;
if ((fq = frag_alloc_queue()) == NULL) {
- DEBUGP("Can't alloc new queue\n");
+ pr_debug("Can't alloc new queue\n");
goto oom;
}
@@ -393,7 +387,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
int offset, end;
if (fq->last_in & COMPLETE) {
- DEBUGP("Allready completed\n");
+ pr_debug("Allready completed\n");
goto err;
}
@@ -402,7 +396,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1)));
if ((unsigned int)end > IPV6_MAXPLEN) {
- DEBUGP("offset is too large.\n");
+ pr_debug("offset is too large.\n");
return -1;
}
@@ -420,7 +414,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
*/
if (end < fq->len ||
((fq->last_in & LAST_IN) && end != fq->len)) {
- DEBUGP("already received last fragment\n");
+ pr_debug("already received last fragment\n");
goto err;
}
fq->last_in |= LAST_IN;
@@ -433,13 +427,13 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
/* RFC2460 says always send parameter problem in
* this case. -DaveM
*/
- DEBUGP("the end of this fragment is not rounded to 8 bytes.\n");
+ pr_debug("end of fragment not rounded to 8 bytes.\n");
return -1;
}
if (end > fq->len) {
/* Some bits beyond end -> corruption. */
if (fq->last_in & LAST_IN) {
- DEBUGP("last packet already reached.\n");
+ pr_debug("last packet already reached.\n");
goto err;
}
fq->len = end;
@@ -451,11 +445,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
/* Point into the IP datagram 'data' part. */
if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data)) {
- DEBUGP("queue: message is too short.\n");
+ pr_debug("queue: message is too short.\n");
goto err;
}
if (pskb_trim_rcsum(skb, end - offset)) {
- DEBUGP("Can't trim\n");
+ pr_debug("Can't trim\n");
goto err;
}
@@ -480,11 +474,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
if (i > 0) {
offset += i;
if (end <= offset) {
- DEBUGP("overlap\n");
+ pr_debug("overlap\n");
goto err;
}
if (!pskb_pull(skb, i)) {
- DEBUGP("Can't pull\n");
+ pr_debug("Can't pull\n");
goto err;
}
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
@@ -503,7 +497,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
/* Eat head of the next overlapped fragment
* and leave the loop. The next ones cannot overlap.
*/
- DEBUGP("Eat head of the overlapped parts.: %d", i);
+ pr_debug("Eat head of the overlapped parts.: %d", i);
if (!pskb_pull(next, i))
goto err;
@@ -586,13 +580,13 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
sizeof(struct ipv6hdr) + fq->len -
sizeof(struct frag_hdr));
if (payload_len > IPV6_MAXPLEN) {
- DEBUGP("payload len is too large.\n");
+ pr_debug("payload len is too large.\n");
goto out_oversize;
}
/* Head of list must not be cloned. */
if (skb_cloned(head) && pskb_expand_head(head, 0, 0, GFP_ATOMIC)) {
- DEBUGP("skb is cloned but can't expand head");
+ pr_debug("skb is cloned but can't expand head");
goto out_oom;
}
@@ -604,7 +598,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
int i, plen = 0;
if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL) {
- DEBUGP("Can't alloc skb\n");
+ pr_debug("Can't alloc skb\n");
goto out_oom;
}
clone->next = head->next;
@@ -719,11 +713,11 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff)
return -1;
}
if (len < (int)sizeof(struct ipv6_opt_hdr)) {
- DEBUGP("too short\n");
+ pr_debug("too short\n");
return -1;
}
if (nexthdr == NEXTHDR_NONE) {
- DEBUGP("next header is none\n");
+ pr_debug("next header is none\n");
return -1;
}
if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
@@ -764,7 +758,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
/* Jumbo payload inhibits frag. header */
if (ipv6_hdr(skb)->payload_len == 0) {
- DEBUGP("payload len = 0\n");
+ pr_debug("payload len = 0\n");
return skb;
}
@@ -773,14 +767,14 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
clone = skb_clone(skb, GFP_ATOMIC);
if (clone == NULL) {
- DEBUGP("Can't clone skb\n");
+ pr_debug("Can't clone skb\n");
return skb;
}
NFCT_FRAG6_CB(clone)->orig = skb;
if (!pskb_may_pull(clone, fhoff + sizeof(*fhdr))) {
- DEBUGP("message is too short.\n");
+ pr_debug("message is too short.\n");
goto ret_orig;
}
@@ -789,7 +783,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
fhdr = (struct frag_hdr *)skb_transport_header(clone);
if (!(fhdr->frag_off & htons(0xFFF9))) {
- DEBUGP("Invalid fragment offset\n");
+ pr_debug("Invalid fragment offset\n");
/* It is not a fragmented frame */
goto ret_orig;
}
@@ -799,7 +793,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr);
if (fq == NULL) {
- DEBUGP("Can't find and can't create new queue\n");
+ pr_debug("Can't find and can't create new queue\n");
goto ret_orig;
}
@@ -807,7 +801,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
if (nf_ct_frag6_queue(fq, clone, fhdr, nhoff) < 0) {
spin_unlock(&fq->lock);
- DEBUGP("Can't insert skb to queue\n");
+ pr_debug("Can't insert skb to queue\n");
fq_put(fq, NULL);
goto ret_orig;
}
@@ -815,7 +809,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb)
if (fq->last_in == (FIRST_IN|LAST_IN) && fq->meat == fq->len) {
ret_skb = nf_ct_frag6_reasm(fq, dev);
if (ret_skb == NULL)
- DEBUGP("Can't reassemble fragmented packets\n");
+ pr_debug("Can't reassemble fragmented packets\n");
}
spin_unlock(&fq->lock);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index a58459a7668..e27383d855d 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -49,7 +49,7 @@
#include <net/udp.h>
#include <net/inet_common.h>
#include <net/tcp_states.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
#include <net/mip6.h>
#endif
@@ -137,6 +137,28 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
return 0;
}
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+static int (*mh_filter)(struct sock *sock, struct sk_buff *skb);
+
+int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
+ struct sk_buff *skb))
+{
+ rcu_assign_pointer(mh_filter, filter);
+ return 0;
+}
+EXPORT_SYMBOL(rawv6_mh_filter_register);
+
+int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
+ struct sk_buff *skb))
+{
+ rcu_assign_pointer(mh_filter, NULL);
+ synchronize_rcu();
+ return 0;
+}
+EXPORT_SYMBOL(rawv6_mh_filter_unregister);
+
+#endif
+
/*
* demultiplex raw sockets.
* (should consider queueing the skb in the sock receive_queue
@@ -178,16 +200,22 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
case IPPROTO_ICMPV6:
filtered = icmpv6_filter(sk, skb);
break;
-#ifdef CONFIG_IPV6_MIP6
+
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPPROTO_MH:
+ {
/* XXX: To validate MH only once for each packet,
* this is placed here. It should be after checking
* xfrm policy, however it doesn't. The checking xfrm
* policy is placed in rawv6_rcv() because it is
* required for each socket.
*/
- filtered = mip6_mh_filter(sk, skb);
+ int (*filter)(struct sock *sock, struct sk_buff *skb);
+
+ filter = rcu_dereference(mh_filter);
+ filtered = filter ? filter(sk, skb) : 0;
break;
+ }
#endif
default:
filtered = 0;
@@ -611,9 +639,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
struct iovec *iov;
u8 __user *type = NULL;
u8 __user *code = NULL;
-#ifdef CONFIG_IPV6_MIP6
u8 len = 0;
-#endif
int probed = 0;
int i;
@@ -646,7 +672,6 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
probed = 1;
}
break;
-#ifdef CONFIG_IPV6_MIP6
case IPPROTO_MH:
if (iov->iov_base && iov->iov_len < 1)
break;
@@ -660,7 +685,6 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
len += iov->iov_len;
break;
-#endif
default:
probed = 1;
break;
@@ -1256,7 +1280,7 @@ static int raw6_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations raw6_seq_ops = {
+static const struct seq_operations raw6_seq_ops = {
.start = raw6_seq_start,
.next = raw6_seq_next,
.stop = raw6_seq_stop,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1324b06796c..fe8d9837f9f 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1999,7 +1999,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu)
fib6_clean_all(rt6_mtu_change_route, 0, &arg);
}
-static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = {
+static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_GATEWAY] = { .len = sizeof(struct in6_addr) },
[RTA_OIF] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 },
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1efa95a99f4..eb20bb690ab 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -532,7 +532,8 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
*/
max_headroom = LL_RESERVED_SPACE(tdev)+sizeof(struct iphdr);
- if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) {
+ if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
+ (skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom);
if (!new_skb) {
ip_rt_put(rt);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 4f06a51ad4f..d67fb1ef751 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -484,17 +484,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
if (dst == NULL) {
opt = np->opt;
- if (opt == NULL &&
- np->rxopt.bits.osrcrt == 2 &&
- treq->pktopts) {
- struct sk_buff *pktopts = treq->pktopts;
- struct inet6_skb_parm *rxopt = IP6CB(pktopts);
- if (rxopt->srcrt)
- opt = ipv6_invert_rthdr(sk,
- (struct ipv6_rt_hdr *)(skb_network_header(pktopts) +
- rxopt->srcrt));
- }
-
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
@@ -590,6 +579,7 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer,
kfree(newkey);
return -ENOMEM;
}
+ sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
}
tcp_alloc_md5sig_pool();
if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) {
@@ -724,6 +714,7 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
return -ENOMEM;
tp->md5sig_info = p;
+ sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
}
newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
@@ -1389,15 +1380,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (sk_acceptq_is_full(sk))
goto out_overflow;
- if (np->rxopt.bits.osrcrt == 2 &&
- opt == NULL && treq->pktopts) {
- struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
- if (rxopt->srcrt)
- opt = ipv6_invert_rthdr(sk,
- (struct ipv6_rt_hdr *)(skb_network_header(treq->pktopts) +
- rxopt->srcrt));
- }
-
if (dst == NULL) {
struct in6_addr *final_p = NULL, final;
struct flowi fl;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index d1fbddd172e..4210951edb6 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -52,28 +52,9 @@
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
-static int ipv6_rcv_saddr_any(const struct sock *sk)
-{
- struct ipv6_pinfo *np = inet6_sk(sk);
-
- return ipv6_addr_any(&np->rcv_saddr);
-}
-
-static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
- const struct sock *sk)
-{
- return port;
-}
-
-const struct udp_get_port_ops udp_ipv6_ops = {
- .saddr_cmp = ipv6_rcv_saddr_equal,
- .saddr_any = ipv6_rcv_saddr_any,
- .hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
-};
-
static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
{
- return udp_get_port(sk, snum, &udp_ipv6_ops);
+ return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
}
static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 36b0c11a28a..6e252f318f7 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -6,8 +6,6 @@
#include <net/addrconf.h>
#include <net/inet_common.h>
-extern const struct udp_get_port_ops udp_ipv6_ops;
-
extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
int , int , int , __be32 , struct hlist_head []);
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index c40a51362f8..f54016a5500 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -37,7 +37,7 @@ static struct inet6_protocol udplitev6_protocol = {
static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
{
- return udplite_get_port(sk, snum, &udp_ipv6_ops);
+ return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
}
struct proto udplitev6_prot = {
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index d7ed8aa56ec..c858537cec4 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -104,10 +104,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi)
nf_reset(skb);
if (decaps) {
- if (!(skb->dev->flags&IFF_LOOPBACK)) {
- dst_release(skb->dst);
- skb->dst = NULL;
- }
+ dst_release(skb->dst);
+ skb->dst = NULL;
netif_rx(skb);
return -1;
} else {
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index a6c0cdf46ad..9fc95bc6509 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -80,6 +80,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+ skb->protocol = htons(ETH_P_IPV6);
return 0;
}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 1faa2ea80af..3ec0c4770ee 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -18,7 +18,7 @@
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/ip6_route.h>
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
#include <net/mip6.h>
#endif
@@ -318,7 +318,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
fl->proto = nexthdr;
return;
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
case IPPROTO_MH:
if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
struct ip6_mh *mh;
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index baa461b9f74..cdadb484746 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -65,7 +65,7 @@ __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
goto end;
/* Rule 2: select MIPv6 RO or inbound trigger */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
for (i = 0; i < n; i++) {
if (src[i] &&
(src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
@@ -130,7 +130,7 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
goto end;
/* Rule 2: select MIPv6 RO or inbound trigger */
-#ifdef CONFIG_IPV6_MIP6
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
for (i = 0; i < n; i++) {
if (src[i] &&
(src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 5502cc948df..6f87dd568de 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -379,3 +379,4 @@ static void __exit xfrm6_tunnel_fini(void)
module_init(xfrm6_tunnel_init);
module_exit(xfrm6_tunnel_fini);
MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_IPV6);
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c
index db32ac8e79b..4226e71ae1e 100644
--- a/net/ipx/ipx_proc.c
+++ b/net/ipx/ipx_proc.c
@@ -286,21 +286,21 @@ out:
return 0;
}
-static struct seq_operations ipx_seq_interface_ops = {
+static const struct seq_operations ipx_seq_interface_ops = {
.start = ipx_seq_interface_start,
.next = ipx_seq_interface_next,
.stop = ipx_seq_interface_stop,
.show = ipx_seq_interface_show,
};
-static struct seq_operations ipx_seq_route_ops = {
+static const struct seq_operations ipx_seq_route_ops = {
.start = ipx_seq_route_start,
.next = ipx_seq_route_next,
.stop = ipx_seq_route_stop,
.show = ipx_seq_route_show,
};
-static struct seq_operations ipx_seq_socket_ops = {
+static const struct seq_operations ipx_seq_socket_ops = {
.start = ipx_seq_socket_start,
.next = ipx_seq_socket_next,
.stop = ipx_seq_interface_stop,
diff --git a/net/irda/Makefile b/net/irda/Makefile
index d1366c2a39c..187f6c563a4 100644
--- a/net/irda/Makefile
+++ b/net/irda/Makefile
@@ -10,6 +10,6 @@ obj-$(CONFIG_IRCOMM) += ircomm/
irda-y := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \
irttp.o irda_device.o irias_object.o wrapper.o af_irda.o \
- discovery.o parameters.o irmod.o
+ discovery.o parameters.o irnetlink.o irmod.o
irda-$(CONFIG_PROC_FS) += irproc.o
irda-$(CONFIG_SYSCTL) += irsysctl.o
diff --git a/net/irda/discovery.c b/net/irda/discovery.c
index f0973412867..af0cea721d2 100644
--- a/net/irda/discovery.c
+++ b/net/irda/discovery.c
@@ -395,7 +395,7 @@ static int discovery_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations discovery_seq_ops = {
+static const struct seq_operations discovery_seq_ops = {
.start = discovery_seq_start,
.next = discovery_seq_next,
.stop = discovery_seq_stop,
diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c
index 4749f8f5539..2d63fa8e155 100644
--- a/net/irda/ircomm/ircomm_core.c
+++ b/net/irda/ircomm/ircomm_core.c
@@ -562,7 +562,7 @@ static int ircomm_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ircomm_seq_ops = {
+static const struct seq_operations ircomm_seq_ops = {
.start = ircomm_seq_start,
.next = ircomm_seq_next,
.stop = ircomm_seq_stop,
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 915d9384f36..774eb707940 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -1066,7 +1066,7 @@ static int irias_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations irias_seq_ops = {
+static const struct seq_operations irias_seq_ops = {
.start = irias_seq_start,
.next = irias_seq_next,
.stop = irias_seq_stop,
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index ed69773b0f8..f5778ef3ccc 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -1217,7 +1217,7 @@ static int irlan_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations irlan_seq_ops = {
+static const struct seq_operations irlan_seq_ops = {
.start = irlan_seq_start,
.next = irlan_seq_next,
.stop = irlan_seq_stop,
diff --git a/net/irda/irlap.c b/net/irda/irlap.c
index d93ebd11431..2fc9f518f89 100644
--- a/net/irda/irlap.c
+++ b/net/irda/irlap.c
@@ -1210,7 +1210,7 @@ static int irlap_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations irlap_seq_ops = {
+static const struct seq_operations irlap_seq_ops = {
.start = irlap_seq_start,
.next = irlap_seq_next,
.stop = irlap_seq_stop,
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c
index 0b02073ffdf..a8b8873aa26 100644
--- a/net/irda/irlap_event.c
+++ b/net/irda/irlap_event.c
@@ -317,23 +317,6 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
}
/*
- * Function irlap_next_state (self, state)
- *
- * Switches state and provides debug information
- *
- */
-static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state)
-{
- /*
- if (!self || self->magic != LAP_MAGIC)
- return;
-
- IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]);
- */
- self->state = state;
-}
-
-/*
* Function irlap_state_ndm (event, skb, frame)
*
* NDM (Normal Disconnected Mode) state
@@ -1086,7 +1069,6 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event,
} else {
/* Final packet of window */
irlap_send_data_primary_poll(self, skb);
- irlap_next_state(self, LAP_NRM_P);
/*
* Make sure state machine does not try to send
@@ -1436,14 +1418,14 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
*/
self->remote_busy = FALSE;
+ /* Stop final timer */
+ del_timer(&self->final_timer);
+
/*
* Nr as expected?
*/
ret = irlap_validate_nr_received(self, info->nr);
if (ret == NR_EXPECTED) {
- /* Stop final timer */
- del_timer(&self->final_timer);
-
/* Update Nr received */
irlap_update_nr_received(self, info->nr);
@@ -1475,14 +1457,12 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event,
/* Resend rejected frames */
irlap_resend_rejected_frames(self, CMD_FRAME);
-
- /* Final timer ??? Jean II */
+ irlap_start_final_timer(self, self->final_timeout * 2);
irlap_next_state(self, LAP_NRM_P);
} else if (ret == NR_INVALID) {
IRDA_DEBUG(1, "%s(), Received RR with "
"invalid nr !\n", __FUNCTION__);
- del_timer(&self->final_timer);
irlap_next_state(self, LAP_RESET_WAIT);
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c
index 3c5a68e3641..25a3444a923 100644
--- a/net/irda/irlap_frame.c
+++ b/net/irda/irlap_frame.c
@@ -101,6 +101,13 @@ void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb)
irlap_insert_info(self, skb);
+ if (unlikely(self->mode & IRDA_MODE_MONITOR)) {
+ IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __FUNCTION__,
+ self->netdev->name);
+ dev_kfree_skb(skb);
+ return;
+ }
+
dev_queue_xmit(skb);
}
@@ -798,16 +805,19 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
self->vs = (self->vs + 1) % 8;
self->ack_required = FALSE;
+ irlap_next_state(self, LAP_NRM_P);
irlap_send_i_frame(self, tx_skb, CMD_FRAME);
} else {
IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__);
if (self->ack_required) {
irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);
+ irlap_next_state(self, LAP_NRM_P);
irlap_send_rr_frame(self, CMD_FRAME);
self->ack_required = FALSE;
} else {
skb->data[1] |= PF_BIT;
+ irlap_next_state(self, LAP_NRM_P);
irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);
}
}
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 9df0461b6d1..24a5e3f2377 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -1994,7 +1994,7 @@ static int irlmp_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations irlmp_seq_ops = {
+static const struct seq_operations irlmp_seq_ops = {
.start = irlmp_seq_start,
.next = irlmp_seq_next,
.stop = irlmp_seq_stop,
diff --git a/net/irda/irmod.c b/net/irda/irmod.c
index c7fad2c5b9f..1900937b332 100644
--- a/net/irda/irmod.c
+++ b/net/irda/irmod.c
@@ -88,16 +88,23 @@ EXPORT_SYMBOL(irda_notify_init);
*/
static int __init irda_init(void)
{
+ int ret = 0;
+
IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
/* Lower layer of the stack */
irlmp_init();
irlap_init();
+ /* Driver/dongle support */
+ irda_device_init();
+
/* Higher layers of the stack */
iriap_init();
irttp_init();
- irsock_init();
+ ret = irsock_init();
+ if (ret < 0)
+ goto out_err_1;
/* Add IrDA packet type (Start receiving packets) */
dev_add_pack(&irda_packet_type);
@@ -107,13 +114,44 @@ static int __init irda_init(void)
irda_proc_register();
#endif
#ifdef CONFIG_SYSCTL
- irda_sysctl_register();
+ ret = irda_sysctl_register();
+ if (ret < 0)
+ goto out_err_2;
#endif
- /* Driver/dongle support */
- irda_device_init();
+ ret = irda_nl_register();
+ if (ret < 0)
+ goto out_err_3;
return 0;
+
+ out_err_3:
+#ifdef CONFIG_SYSCTL
+ irda_sysctl_unregister();
+#endif
+ out_err_2:
+#ifdef CONFIG_PROC_FS
+ irda_proc_unregister();
+#endif
+
+ /* Remove IrDA packet type (stop receiving packets) */
+ dev_remove_pack(&irda_packet_type);
+
+ /* Remove higher layers */
+ irsock_cleanup();
+ out_err_1:
+ irttp_cleanup();
+ iriap_cleanup();
+
+ /* Remove lower layers */
+ irda_device_cleanup();
+ irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */
+
+ /* Remove middle layer */
+ irlmp_cleanup();
+
+
+ return ret;
}
/*
@@ -125,6 +163,8 @@ static int __init irda_init(void)
static void __exit irda_cleanup(void)
{
/* Remove External APIs */
+ irda_nl_unregister();
+
#ifdef CONFIG_SYSCTL
irda_sysctl_unregister();
#endif
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
new file mode 100644
index 00000000000..db716580e1a
--- /dev/null
+++ b/net/irda/irnetlink.c
@@ -0,0 +1,170 @@
+/*
+ * IrDA netlink layer, for stack configuration.
+ *
+ * Copyright (c) 2007 Samuel Ortiz <samuel@sortiz>
+ *
+ * Partly based on the 802.11 nelink implementation
+ * (see net/wireless/nl80211.c) which is:
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * 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/socket.h>
+#include <linux/irda.h>
+#include <net/sock.h>
+#include <net/irda/irda.h>
+#include <net/irda/irlap.h>
+#include <net/genetlink.h>
+
+
+
+static struct genl_family irda_nl_family = {
+ .id = GENL_ID_GENERATE,
+ .name = IRDA_NL_NAME,
+ .hdrsize = 0,
+ .version = IRDA_NL_VERSION,
+ .maxattr = IRDA_NL_CMD_MAX,
+};
+
+static struct net_device * ifname_to_netdev(struct genl_info *info)
+{
+ char * ifname;
+
+ if (!info->attrs[IRDA_NL_ATTR_IFNAME])
+ return NULL;
+
+ ifname = nla_data(info->attrs[IRDA_NL_ATTR_IFNAME]);
+
+ IRDA_DEBUG(5, "%s(): Looking for %s\n", __FUNCTION__, ifname);
+
+ return dev_get_by_name(ifname);
+}
+
+static int irda_nl_set_mode(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net_device * dev;
+ struct irlap_cb * irlap;
+ u32 mode;
+
+ if (!info->attrs[IRDA_NL_ATTR_MODE])
+ return -EINVAL;
+
+ mode = nla_get_u32(info->attrs[IRDA_NL_ATTR_MODE]);
+
+ IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __FUNCTION__, mode);
+
+ dev = ifname_to_netdev(info);
+ if (!dev)
+ return -ENODEV;
+
+ irlap = (struct irlap_cb *)dev->atalk_ptr;
+ if (!irlap) {
+ dev_put(dev);
+ return -ENODEV;
+ }
+
+ irlap->mode = mode;
+
+ dev_put(dev);
+
+ return 0;
+}
+
+static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net_device * dev;
+ struct irlap_cb * irlap;
+ struct sk_buff *msg;
+ void *hdr;
+ int ret = -ENOBUFS;
+
+ dev = ifname_to_netdev(info);
+ if (!dev)
+ return -ENODEV;
+
+ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
+ if (!msg) {
+ dev_put(dev);
+ return -ENOMEM;
+ }
+
+ irlap = (struct irlap_cb *)dev->atalk_ptr;
+ if (!irlap) {
+ ret = -ENODEV;
+ goto err_out;
+ }
+
+ hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
+ &irda_nl_family, 0, IRDA_NL_CMD_GET_MODE);
+ if (IS_ERR(hdr)) {
+ ret = PTR_ERR(hdr);
+ goto err_out;
+ }
+
+ if(nla_put_string(msg, IRDA_NL_ATTR_IFNAME,
+ dev->name));
+ goto err_out;
+
+ if(nla_put_u32(msg, IRDA_NL_ATTR_MODE, irlap->mode))
+ goto err_out;
+
+ genlmsg_end(msg, hdr);
+
+ return genlmsg_unicast(msg, info->snd_pid);
+
+ err_out:
+ nlmsg_free(msg);
+ dev_put(dev);
+
+ return ret;
+}
+
+static struct nla_policy irda_nl_policy[IRDA_NL_ATTR_MAX + 1] = {
+ [IRDA_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING,
+ .len = IFNAMSIZ-1 },
+ [IRDA_NL_ATTR_MODE] = { .type = NLA_U32 },
+};
+
+static struct genl_ops irda_nl_ops[] = {
+ {
+ .cmd = IRDA_NL_CMD_SET_MODE,
+ .doit = irda_nl_set_mode,
+ .policy = irda_nl_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = IRDA_NL_CMD_GET_MODE,
+ .doit = irda_nl_get_mode,
+ .policy = irda_nl_policy,
+ /* can be retrieved by unprivileged users */
+ },
+
+};
+
+int irda_nl_register(void)
+{
+ int err, i;
+
+ err = genl_register_family(&irda_nl_family);
+ if (err)
+ return err;
+
+ for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) {
+ err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]);
+ if (err)
+ goto err_out;
+ }
+ return 0;
+ err_out:
+ genl_unregister_family(&irda_nl_family);
+ return err;
+}
+
+void irda_nl_unregister(void)
+{
+ genl_unregister_family(&irda_nl_family);
+}
diff --git a/net/irda/irttp.c b/net/irda/irttp.c
index 7069e4a5825..7f50832a2cd 100644
--- a/net/irda/irttp.c
+++ b/net/irda/irttp.c
@@ -369,6 +369,20 @@ static int irttp_param_max_sdu_size(void *instance, irda_param_t *param,
/* Everything is happily mixed up. Waiting for next clean up - Jean II */
/*
+ * Initialization, that has to be done on new tsap
+ * instance allocation and on duplication
+ */
+static void irttp_init_tsap(struct tsap_cb *tsap)
+{
+ spin_lock_init(&tsap->lock);
+ init_timer(&tsap->todo_timer);
+
+ skb_queue_head_init(&tsap->rx_queue);
+ skb_queue_head_init(&tsap->tx_queue);
+ skb_queue_head_init(&tsap->rx_fragments);
+}
+
+/*
* Function irttp_open_tsap (stsap, notify)
*
* Create TSAP connection endpoint,
@@ -395,10 +409,11 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__);
return NULL;
}
- spin_lock_init(&self->lock);
+
+ /* Initialize internal objects */
+ irttp_init_tsap(self);
/* Initialise todo timer */
- init_timer(&self->todo_timer);
self->todo_timer.data = (unsigned long) self;
self->todo_timer.function = &irttp_todo_expired;
@@ -418,9 +433,6 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
self->magic = TTP_TSAP_MAGIC;
self->connected = FALSE;
- skb_queue_head_init(&self->rx_queue);
- skb_queue_head_init(&self->tx_queue);
- skb_queue_head_init(&self->rx_fragments);
/*
* Create LSAP at IrLMP layer
*/
@@ -1455,12 +1467,9 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
/* Not everything should be copied */
new->notify.instance = instance;
- spin_lock_init(&new->lock);
- init_timer(&new->todo_timer);
- skb_queue_head_init(&new->rx_queue);
- skb_queue_head_init(&new->tx_queue);
- skb_queue_head_init(&new->rx_fragments);
+ /* Initialize internal objects */
+ irttp_init_tsap(new);
/* This is locked */
hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL);
@@ -1866,7 +1875,7 @@ static int irttp_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations irttp_seq_ops = {
+static const struct seq_operations irttp_seq_ops = {
.start = irttp_seq_start,
.next = irttp_seq_next,
.stop = irttp_seq_stop,
diff --git a/net/iucv/Kconfig b/net/iucv/Kconfig
index f8fcc3d1032..16ce9cd4f39 100644
--- a/net/iucv/Kconfig
+++ b/net/iucv/Kconfig
@@ -1,13 +1,13 @@
config IUCV
- tristate "IUCV support (VM only)"
+ tristate "IUCV support (S390 - z/VM only)"
depends on S390
help
- Select this option if you want to use inter-user communication under
- VM or VIF sockets. If you run on z/VM, say "Y" to enable a fast
+ Select this option if you want to use inter-user communication
+ under VM or VIF. If you run on z/VM, say "Y" to enable a fast
communication link between VM guests.
config AFIUCV
- tristate "AF_IUCV support (VM only)"
+ tristate "AF_IUCV support (S390 - z/VM only)"
depends on IUCV
help
Select this option if you want to use inter-user communication under
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index d9e9ddb8eac..53ae14c35f7 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -219,6 +219,7 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio)
sock_init_data(sock, sk);
INIT_LIST_HEAD(&iucv_sk(sk)->accept_q);
+ spin_lock_init(&iucv_sk(sk)->accept_q_lock);
skb_queue_head_init(&iucv_sk(sk)->send_skb_q);
skb_queue_head_init(&iucv_sk(sk)->backlog_skb_q);
iucv_sk(sk)->send_tag = 0;
@@ -274,15 +275,25 @@ void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *sk)
void iucv_accept_enqueue(struct sock *parent, struct sock *sk)
{
+ unsigned long flags;
+ struct iucv_sock *par = iucv_sk(parent);
+
sock_hold(sk);
- list_add_tail(&iucv_sk(sk)->accept_q, &iucv_sk(parent)->accept_q);
+ spin_lock_irqsave(&par->accept_q_lock, flags);
+ list_add_tail(&iucv_sk(sk)->accept_q, &par->accept_q);
+ spin_unlock_irqrestore(&par->accept_q_lock, flags);
iucv_sk(sk)->parent = parent;
parent->sk_ack_backlog++;
}
void iucv_accept_unlink(struct sock *sk)
{
+ unsigned long flags;
+ struct iucv_sock *par = iucv_sk(iucv_sk(sk)->parent);
+
+ spin_lock_irqsave(&par->accept_q_lock, flags);
list_del_init(&iucv_sk(sk)->accept_q);
+ spin_unlock_irqrestore(&par->accept_q_lock, flags);
iucv_sk(sk)->parent->sk_ack_backlog--;
iucv_sk(sk)->parent = NULL;
sock_put(sk);
@@ -298,8 +309,8 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock)
lock_sock(sk);
if (sk->sk_state == IUCV_CLOSED) {
- release_sock(sk);
iucv_accept_unlink(sk);
+ release_sock(sk);
continue;
}
@@ -879,6 +890,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
/* Find out if this path belongs to af_iucv. */
read_lock(&iucv_sk_list.lock);
iucv = NULL;
+ sk = NULL;
sk_for_each(sk, node, &iucv_sk_list.head)
if (sk->sk_state == IUCV_LISTEN &&
!memcmp(&iucv_sk(sk)->src_name, src_name, 8)) {
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index b7333061016..ad5150b8dfa 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -1494,7 +1494,10 @@ static void iucv_tasklet_fn(unsigned long ignored)
struct iucv_irq_list *p, *n;
/* Serialize tasklet, iucv_path_sever and iucv_path_connect. */
- spin_lock(&iucv_table_lock);
+ if (!spin_trylock(&iucv_table_lock)) {
+ tasklet_schedule(&iucv_tasklet);
+ return;
+ }
iucv_active_cpu = smp_processor_id();
spin_lock_irq(&iucv_queue_lock);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index d302ddae580..0f8304b0246 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1682,6 +1682,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
unsigned proto;
struct km_event c;
struct xfrm_audit audit_info;
+ int err;
proto = pfkey_satype2proto(hdr->sadb_msg_satype);
if (proto == 0)
@@ -1689,7 +1690,9 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
audit_info.loginuid = audit_get_loginuid(current->audit_context);
audit_info.secid = 0;
- xfrm_state_flush(proto, &audit_info);
+ err = xfrm_state_flush(proto, &audit_info);
+ if (err)
+ return err;
c.data.proto = proto;
c.seq = hdr->sadb_msg_seq;
c.pid = hdr->sadb_msg_pid;
@@ -2683,10 +2686,13 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg
{
struct km_event c;
struct xfrm_audit audit_info;
+ int err;
audit_info.loginuid = audit_get_loginuid(current->audit_context);
audit_info.secid = 0;
- xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+ err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
+ if (err)
+ return err;
c.data.type = XFRM_POLICY_TYPE_MAIN;
c.event = XFRM_MSG_FLUSHPOLICY;
c.pid = hdr->sadb_msg_pid;
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c
index 3ab9d9f8b17..49be6c902c8 100644
--- a/net/llc/llc_proc.c
+++ b/net/llc/llc_proc.c
@@ -184,14 +184,14 @@ out:
return 0;
}
-static struct seq_operations llc_seq_socket_ops = {
+static const struct seq_operations llc_seq_socket_ops = {
.start = llc_seq_start,
.next = llc_seq_next,
.stop = llc_seq_stop,
.show = llc_seq_socket_show,
};
-static struct seq_operations llc_seq_core_ops = {
+static const struct seq_operations llc_seq_core_ops = {
.start = llc_seq_start,
.next = llc_seq_next,
.stop = llc_seq_stop,
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index bb6c0feb2d4..476c8486f78 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -112,7 +112,7 @@ DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
local->wep_iv & 0xffffff);
DEBUGFS_READONLY_FILE(tx_power_reduction, 20, "%d.%d dBm",
local->hw.conf.tx_power_reduction / 10,
- local->hw.conf.tx_power_reduction & 10);
+ local->hw.conf.tx_power_reduction % 10);
DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 9e3964638ba..a3e01d76d50 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -118,7 +118,7 @@ static ssize_t ieee80211_if_fmt_flags(
sdata->u.sta.authenticated ? "AUTH\n" : "",
sdata->u.sta.associated ? "ASSOC\n" : "",
sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
- sdata->u.sta.use_protection ? "CTS prot\n" : "");
+ sdata->use_protection ? "CTS prot\n" : "");
}
__IEEE80211_IF_FILE(flags);
diff --git a/net/mac80211/hostapd_ioctl.h b/net/mac80211/hostapd_ioctl.h
index 34fa128e987..52da513f060 100644
--- a/net/mac80211/hostapd_ioctl.h
+++ b/net/mac80211/hostapd_ioctl.h
@@ -26,24 +26,16 @@
* mess shall be deleted completely. */
enum {
PRISM2_PARAM_IEEE_802_1X = 23,
- PRISM2_PARAM_ANTSEL_TX = 24,
- PRISM2_PARAM_ANTSEL_RX = 25,
/* Instant802 additions */
PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES = 1001,
- PRISM2_PARAM_DROP_UNENCRYPTED = 1002,
PRISM2_PARAM_PREAMBLE = 1003,
PRISM2_PARAM_SHORT_SLOT_TIME = 1006,
PRISM2_PARAM_NEXT_MODE = 1008,
- PRISM2_PARAM_CLEAR_KEYS = 1009,
PRISM2_PARAM_RADIO_ENABLED = 1010,
PRISM2_PARAM_ANTENNA_MODE = 1013,
PRISM2_PARAM_STAT_TIME = 1016,
PRISM2_PARAM_STA_ANTENNA_SEL = 1017,
- PRISM2_PARAM_FORCE_UNICAST_RATE = 1018,
- PRISM2_PARAM_RATE_CTRL_NUM_UP = 1019,
- PRISM2_PARAM_RATE_CTRL_NUM_DOWN = 1020,
- PRISM2_PARAM_MAX_RATECTRL_RATE = 1021,
PRISM2_PARAM_TX_POWER_REDUCTION = 1022,
PRISM2_PARAM_KEY_TX_RX_THRESHOLD = 1024,
PRISM2_PARAM_DEFAULT_WEP_ONLY = 1026,
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 6e36df67f8d..2ddf4ef4065 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -24,6 +24,7 @@
#include <linux/compiler.h>
#include <linux/bitmap.h>
#include <net/cfg80211.h>
+#include <asm/unaligned.h>
#include "ieee80211_common.h"
#include "ieee80211_i.h"
@@ -56,6 +57,17 @@ static const unsigned char eapol_header[] =
{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8e };
+/*
+ * For seeing transmitted packets on monitor interfaces
+ * we have a radiotap header too.
+ */
+struct ieee80211_tx_status_rtap_hdr {
+ struct ieee80211_radiotap_header hdr;
+ __le16 tx_flags;
+ u8 data_retries;
+} __attribute__ ((packed));
+
+
static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata,
struct ieee80211_hdr *hdr)
{
@@ -430,7 +442,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
if (!tx->u.tx.rate)
return TXRX_DROP;
if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
- tx->local->cts_protect_erp_frames && tx->fragmented &&
+ tx->sdata->use_protection && tx->fragmented &&
extra.nonerp) {
tx->u.tx.last_frag_rate = tx->u.tx.rate;
tx->u.tx.probe_last_frag = extra.probe ? 1 : 0;
@@ -528,7 +540,7 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
/* reserve enough extra head and tail room for possible
* encryption */
frag = frags[i] =
- dev_alloc_skb(tx->local->hw.extra_tx_headroom +
+ dev_alloc_skb(tx->local->tx_headroom +
frag_threshold +
IEEE80211_ENCRYPT_HEADROOM +
IEEE80211_ENCRYPT_TAILROOM);
@@ -537,8 +549,8 @@ ieee80211_tx_h_fragment(struct ieee80211_txrx_data *tx)
/* Make sure that all fragments use the same priority so
* that they end up using the same TX queue */
frag->priority = first->priority;
- skb_reserve(frag, tx->local->hw.extra_tx_headroom +
- IEEE80211_ENCRYPT_HEADROOM);
+ skb_reserve(frag, tx->local->tx_headroom +
+ IEEE80211_ENCRYPT_HEADROOM);
fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);
memcpy(fhdr, first->data, hdrlen);
if (i == num_fragm - 2)
@@ -856,8 +868,7 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
* for the frame. */
if (mode->mode == MODE_IEEE80211G &&
(tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
- tx->u.tx.unicast &&
- tx->local->cts_protect_erp_frames &&
+ tx->u.tx.unicast && tx->sdata->use_protection &&
!(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
@@ -1118,7 +1129,138 @@ ieee80211_tx_h_ps_buf(struct ieee80211_txrx_data *tx)
}
-static void inline
+/*
+ * deal with packet injection down monitor interface
+ * with Radiotap Header -- only called for monitor mode interface
+ */
+
+static ieee80211_txrx_result
+__ieee80211_parse_tx_radiotap(
+ struct ieee80211_txrx_data *tx,
+ struct sk_buff *skb, struct ieee80211_tx_control *control)
+{
+ /*
+ * this is the moment to interpret and discard the radiotap header that
+ * must be at the start of the packet injected in Monitor mode
+ *
+ * Need to take some care with endian-ness since radiotap
+ * args are little-endian
+ */
+
+ struct ieee80211_radiotap_iterator iterator;
+ struct ieee80211_radiotap_header *rthdr =
+ (struct ieee80211_radiotap_header *) skb->data;
+ struct ieee80211_hw_mode *mode = tx->local->hw.conf.mode;
+ int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
+
+ /*
+ * default control situation for all injected packets
+ * FIXME: this does not suit all usage cases, expand to allow control
+ */
+
+ control->retry_limit = 1; /* no retry */
+ control->key_idx = -1; /* no encryption key */
+ control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
+ IEEE80211_TXCTL_USE_CTS_PROTECT);
+ control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT |
+ IEEE80211_TXCTL_NO_ACK;
+ control->antenna_sel_tx = 0; /* default to default antenna */
+
+ /*
+ * for every radiotap entry that is present
+ * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
+ * entries present, or -EINVAL on error)
+ */
+
+ while (!ret) {
+ int i, target_rate;
+
+ ret = ieee80211_radiotap_iterator_next(&iterator);
+
+ if (ret)
+ continue;
+
+ /* see if this argument is something we can use */
+ switch (iterator.this_arg_index) {
+ /*
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned. Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ */
+ case IEEE80211_RADIOTAP_RATE:
+ /*
+ * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps
+ * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps
+ */
+ target_rate = (*iterator.this_arg) * 5;
+ for (i = 0; i < mode->num_rates; i++) {
+ struct ieee80211_rate *r = &mode->rates[i];
+
+ if (r->rate > target_rate)
+ continue;
+
+ control->rate = r;
+
+ if (r->flags & IEEE80211_RATE_PREAMBLE2)
+ control->tx_rate = r->val2;
+ else
+ control->tx_rate = r->val;
+
+ /* end on exact match */
+ if (r->rate == target_rate)
+ i = mode->num_rates;
+ }
+ break;
+
+ case IEEE80211_RADIOTAP_ANTENNA:
+ /*
+ * radiotap uses 0 for 1st ant, mac80211 is 1 for
+ * 1st ant
+ */
+ control->antenna_sel_tx = (*iterator.this_arg) + 1;
+ break;
+
+ case IEEE80211_RADIOTAP_DBM_TX_POWER:
+ control->power_level = *iterator.this_arg;
+ break;
+
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
+ /*
+ * this indicates that the skb we have been
+ * handed has the 32-bit FCS CRC at the end...
+ * we should react to that by snipping it off
+ * because it will be recomputed and added
+ * on transmission
+ */
+ if (skb->len < (iterator.max_length + FCS_LEN))
+ return TXRX_DROP;
+
+ skb_trim(skb, skb->len - FCS_LEN);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
+ return TXRX_DROP;
+
+ /*
+ * remove the radiotap header
+ * iterator->max_length was sanity-checked against
+ * skb->len by iterator init
+ */
+ skb_pull(skb, iterator.max_length);
+
+ return TXRX_CONTINUE;
+}
+
+
+static ieee80211_txrx_result inline
__ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
struct sk_buff *skb,
struct net_device *dev,
@@ -1126,6 +1268,9 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_sub_if_data *sdata;
+ ieee80211_txrx_result res = TXRX_CONTINUE;
+
int hdrlen;
memset(tx, 0, sizeof(*tx));
@@ -1135,7 +1280,32 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
tx->sta = sta_info_get(local, hdr->addr1);
tx->fc = le16_to_cpu(hdr->frame_control);
+
+ /*
+ * set defaults for things that can be set by
+ * injected radiotap headers
+ */
control->power_level = local->hw.conf.power_level;
+ control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
+ if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta)
+ control->antenna_sel_tx = tx->sta->antenna_sel_tx;
+
+ /* process and remove the injection radiotap header */
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (unlikely(sdata->type == IEEE80211_IF_TYPE_MNTR)) {
+ if (__ieee80211_parse_tx_radiotap(tx, skb, control) ==
+ TXRX_DROP) {
+ return TXRX_DROP;
+ }
+ /*
+ * we removed the radiotap header after this point,
+ * we filled control with what we could use
+ * set to the actual ieee header now
+ */
+ hdr = (struct ieee80211_hdr *) skb->data;
+ res = TXRX_QUEUED; /* indication it was monitor packet */
+ }
+
tx->u.tx.control = control;
tx->u.tx.unicast = !is_multicast_ether_addr(hdr->addr1);
if (is_multicast_ether_addr(hdr->addr1))
@@ -1152,9 +1322,6 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
control->flags |= IEEE80211_TXCTL_CLEAR_DST_MASK;
tx->sta->clear_dst_mask = 0;
}
- control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
- if (local->sta_antenna_sel != STA_ANTENNA_SEL_AUTO && tx->sta)
- control->antenna_sel_tx = tx->sta->antenna_sel_tx;
hdrlen = ieee80211_get_hdrlen(tx->fc);
if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
@@ -1162,6 +1329,7 @@ __ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
}
control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
+ return res;
}
static int inline is_ieee80211_device(struct net_device *dev,
@@ -1274,7 +1442,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
struct sta_info *sta;
ieee80211_tx_handler *handler;
struct ieee80211_txrx_data tx;
- ieee80211_txrx_result res = TXRX_DROP;
+ ieee80211_txrx_result res = TXRX_DROP, res_prepare;
int ret, i;
WARN_ON(__ieee80211_queue_pending(local, control->queue));
@@ -1284,15 +1452,26 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
return 0;
}
- __ieee80211_tx_prepare(&tx, skb, dev, control);
+ res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);
+
+ if (res_prepare == TXRX_DROP) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
sta = tx.sta;
tx.u.tx.mgmt_interface = mgmt;
tx.u.tx.mode = local->hw.conf.mode;
- for (handler = local->tx_handlers; *handler != NULL; handler++) {
- res = (*handler)(&tx);
- if (res != TXRX_CONTINUE)
- break;
+ if (res_prepare == TXRX_QUEUED) { /* if it was an injected packet */
+ res = TXRX_CONTINUE;
+ } else {
+ for (handler = local->tx_handlers; *handler != NULL;
+ handler++) {
+ res = (*handler)(&tx);
+ if (res != TXRX_CONTINUE)
+ break;
+ }
}
skb = tx.skb; /* handlers are allowed to change skb */
@@ -1467,8 +1646,7 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb,
}
osdata = IEEE80211_DEV_TO_SUB_IF(odev);
- headroom = osdata->local->hw.extra_tx_headroom +
- IEEE80211_ENCRYPT_HEADROOM;
+ headroom = osdata->local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM;
if (skb_headroom(skb) < headroom) {
if (pskb_expand_head(skb, headroom, 0, GFP_ATOMIC)) {
dev_kfree_skb(skb);
@@ -1494,6 +1672,56 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb,
}
+int ieee80211_monitor_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_tx_packet_data *pkt_data;
+ struct ieee80211_radiotap_header *prthdr =
+ (struct ieee80211_radiotap_header *)skb->data;
+ u16 len;
+
+ /*
+ * there must be a radiotap header at the
+ * start in this case
+ */
+ if (unlikely(prthdr->it_version)) {
+ /* only version 0 is supported */
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ skb->dev = local->mdev;
+
+ pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
+ memset(pkt_data, 0, sizeof(*pkt_data));
+ pkt_data->ifindex = dev->ifindex;
+ pkt_data->mgmt_iface = 0;
+ pkt_data->do_not_encrypt = 1;
+
+ /* above needed because we set skb device to master */
+
+ /*
+ * fix up the pointers accounting for the radiotap
+ * header still being in there. We are being given
+ * a precooked IEEE80211 header so no need for
+ * normal processing
+ */
+ len = le16_to_cpu(get_unaligned(&prthdr->it_len));
+ skb_set_mac_header(skb, len);
+ skb_set_network_header(skb, len + sizeof(struct ieee80211_hdr));
+ skb_set_transport_header(skb, len + sizeof(struct ieee80211_hdr));
+
+ /*
+ * pass the radiotap header up to
+ * the next stage intact
+ */
+ dev_queue_xmit(skb);
+
+ return NETDEV_TX_OK;
+}
+
+
/**
* ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
* subinterfaces (wlan#, WDS, and VLAN interfaces)
@@ -1509,8 +1737,8 @@ static int ieee80211_master_start_xmit(struct sk_buff *skb,
* encapsulated packet will then be passed to master interface, wlan#.11, for
* transmission (through low-level driver).
*/
-static int ieee80211_subif_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
+int ieee80211_subif_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_tx_packet_data *pkt_data;
@@ -1619,7 +1847,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,
* build in headroom in __dev_alloc_skb() (linux/skbuff.h) and
* alloc_skb() (net/core/skbuff.c)
*/
- head_need = hdrlen + encaps_len + local->hw.extra_tx_headroom;
+ head_need = hdrlen + encaps_len + local->tx_headroom;
head_need -= skb_headroom(skb);
/* We are going to modify skb data, so make a copy of it if happens to
@@ -1658,7 +1886,7 @@ static int ieee80211_subif_start_xmit(struct sk_buff *skb,
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
- pkt_data->ifindex = sdata->dev->ifindex;
+ pkt_data->ifindex = dev->ifindex;
pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
pkt_data->do_not_encrypt = no_encrypt;
@@ -1706,9 +1934,9 @@ ieee80211_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
- if (skb_headroom(skb) < sdata->local->hw.extra_tx_headroom) {
- if (pskb_expand_head(skb,
- sdata->local->hw.extra_tx_headroom, 0, GFP_ATOMIC)) {
+ if (skb_headroom(skb) < sdata->local->tx_headroom) {
+ if (pskb_expand_head(skb, sdata->local->tx_headroom,
+ 0, GFP_ATOMIC)) {
dev_kfree_skb(skb);
return 0;
}
@@ -1847,12 +2075,12 @@ struct sk_buff * ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,
bh_len = ap->beacon_head_len;
bt_len = ap->beacon_tail_len;
- skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+ skb = dev_alloc_skb(local->tx_headroom +
bh_len + bt_len + 256 /* maximum TIM len */);
if (!skb)
return NULL;
- skb_reserve(skb, local->hw.extra_tx_headroom);
+ skb_reserve(skb, local->tx_headroom);
memcpy(skb_put(skb, bh_len), b_head, bh_len);
ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
@@ -2376,8 +2604,7 @@ static void ieee80211_start_hard_monitor(struct ieee80211_local *local)
struct ieee80211_if_init_conf conf;
if (local->open_count && local->open_count == local->monitors &&
- !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) &&
- local->ops->add_interface) {
+ !(local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER)) {
conf.if_id = -1;
conf.type = IEEE80211_IF_TYPE_MNTR;
conf.mac_addr = NULL;
@@ -2420,21 +2647,14 @@ static int ieee80211_open(struct net_device *dev)
}
ieee80211_start_soft_monitor(local);
- if (local->ops->add_interface) {
- conf.if_id = dev->ifindex;
- conf.type = sdata->type;
- conf.mac_addr = dev->dev_addr;
- res = local->ops->add_interface(local_to_hw(local), &conf);
- if (res) {
- if (sdata->type == IEEE80211_IF_TYPE_MNTR)
- ieee80211_start_hard_monitor(local);
- return res;
- }
- } else {
- if (sdata->type != IEEE80211_IF_TYPE_STA)
- return -EOPNOTSUPP;
- if (local->open_count > 0)
- return -ENOBUFS;
+ conf.if_id = dev->ifindex;
+ conf.type = sdata->type;
+ conf.mac_addr = dev->dev_addr;
+ res = local->ops->add_interface(local_to_hw(local), &conf);
+ if (res) {
+ if (sdata->type == IEEE80211_IF_TYPE_MNTR)
+ ieee80211_start_hard_monitor(local);
+ return res;
}
if (local->open_count == 0) {
@@ -2474,6 +2694,8 @@ static int ieee80211_open(struct net_device *dev)
if (sdata->type == IEEE80211_IF_TYPE_STA &&
!local->user_space_mlme)
netif_carrier_off(dev);
+ else
+ netif_carrier_on(dev);
netif_start_queue(dev);
return 0;
@@ -2939,34 +3161,6 @@ int ieee80211_radar_status(struct ieee80211_hw *hw, int channel,
}
EXPORT_SYMBOL(ieee80211_radar_status);
-int ieee80211_set_aid_for_sta(struct ieee80211_hw *hw, u8 *peer_address,
- u16 aid)
-{
- struct sk_buff *skb;
- struct ieee80211_msg_set_aid_for_sta *msg;
- struct ieee80211_local *local = hw_to_local(hw);
-
- /* unlikely because if this event only happens for APs,
- * which require an open ap device. */
- if (unlikely(!local->apdev))
- return 0;
-
- skb = dev_alloc_skb(sizeof(struct ieee80211_frame_info) +
- sizeof(struct ieee80211_msg_set_aid_for_sta));
-
- if (!skb)
- return -ENOMEM;
- skb_reserve(skb, sizeof(struct ieee80211_frame_info));
-
- msg = (struct ieee80211_msg_set_aid_for_sta *)
- skb_put(skb, sizeof(struct ieee80211_msg_set_aid_for_sta));
- memcpy(msg->sta_address, peer_address, ETH_ALEN);
- msg->aid = aid;
-
- ieee80211_rx_mgmt(local, skb, NULL, ieee80211_msg_set_aid_for_sta);
- return 0;
-}
-EXPORT_SYMBOL(ieee80211_set_aid_for_sta);
static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
{
@@ -3278,8 +3472,10 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
return TXRX_DROP;
}
}
- while ((skb = __skb_dequeue(&entry->skb_list)))
+ while ((skb = __skb_dequeue(&entry->skb_list))) {
memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len);
+ dev_kfree_skb(skb);
+ }
/* Complete frame has been reassembled - process it now */
rx->fragmented = 1;
@@ -4280,6 +4476,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_local *local = hw_to_local(hw);
u16 frag, type;
u32 msg_type;
+ struct ieee80211_tx_status_rtap_hdr *rthdr;
+ struct ieee80211_sub_if_data *sdata;
+ int monitors;
if (!status) {
printk(KERN_ERR
@@ -4391,27 +4590,100 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
local->dot11FailedCount++;
}
- if (!(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS)
- || unlikely(!local->apdev)) {
+ msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ?
+ ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail;
+
+ /* this was a transmitted frame, but now we want to reuse it */
+ skb_orphan(skb);
+
+ if ((status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS) &&
+ local->apdev) {
+ if (local->monitors) {
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ } else {
+ skb2 = skb;
+ skb = NULL;
+ }
+
+ if (skb2)
+ /* Send frame to hostapd */
+ ieee80211_rx_mgmt(local, skb2, NULL, msg_type);
+
+ if (!skb)
+ return;
+ }
+
+ if (!local->monitors) {
dev_kfree_skb(skb);
return;
}
- msg_type = (status->flags & IEEE80211_TX_STATUS_ACK) ?
- ieee80211_msg_tx_callback_ack : ieee80211_msg_tx_callback_fail;
+ /* send frame to monitor interfaces now */
- /* skb was the original skb used for TX. Clone it and give the clone
- * to netif_rx(). Free original skb. */
- skb2 = skb_copy(skb, GFP_ATOMIC);
- if (!skb2) {
+ if (skb_headroom(skb) < sizeof(*rthdr)) {
+ printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
dev_kfree_skb(skb);
return;
}
- dev_kfree_skb(skb);
- skb = skb2;
- /* Send frame to hostapd */
- ieee80211_rx_mgmt(local, skb, NULL, msg_type);
+ rthdr = (struct ieee80211_tx_status_rtap_hdr*)
+ skb_push(skb, sizeof(*rthdr));
+
+ memset(rthdr, 0, sizeof(*rthdr));
+ rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr));
+ rthdr->hdr.it_present =
+ cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
+ (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
+
+ if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
+ !is_multicast_ether_addr(hdr->addr1))
+ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
+
+ if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
+ (status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
+ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
+ else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
+ rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
+
+ rthdr->data_retries = status->retry_count;
+
+ read_lock(&local->sub_if_lock);
+ monitors = local->monitors;
+ list_for_each_entry(sdata, &local->sub_if_list, list) {
+ /*
+ * Using the monitors counter is possibly racy, but
+ * if the value is wrong we simply either clone the skb
+ * once too much or forget sending it to one monitor iface
+ * The latter case isn't nice but fixing the race is much
+ * more complicated.
+ */
+ if (!monitors || !skb)
+ goto out;
+
+ if (sdata->type == IEEE80211_IF_TYPE_MNTR) {
+ if (!netif_running(sdata->dev))
+ continue;
+ monitors--;
+ if (monitors)
+ skb2 = skb_clone(skb, GFP_KERNEL);
+ else
+ skb2 = NULL;
+ skb->dev = sdata->dev;
+ /* XXX: is this sufficient for BPF? */
+ skb_set_mac_header(skb, 0);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = htons(ETH_P_802_2);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+ skb = skb2;
+ break;
+ }
+ }
+ out:
+ read_unlock(&local->sub_if_lock);
+ if (skb)
+ dev_kfree_skb(skb);
}
EXPORT_SYMBOL(ieee80211_tx_status);
@@ -4615,6 +4887,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
((sizeof(struct ieee80211_local) +
NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
+ BUG_ON(!ops->tx);
+ BUG_ON(!ops->config);
+ BUG_ON(!ops->add_interface);
local->ops = ops;
/* for now, mdev needs sub_if_data :/ */
@@ -4643,8 +4918,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->short_retry_limit = 7;
local->long_retry_limit = 4;
local->hw.conf.radio_enabled = 1;
- local->rate_ctrl_num_up = RATE_CONTROL_NUM_UP;
- local->rate_ctrl_num_down = RATE_CONTROL_NUM_DOWN;
local->enabled_modes = (unsigned int) -1;
@@ -4708,6 +4981,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
goto fail_workqueue;
}
+ /*
+ * The hardware needs headroom for sending the frame,
+ * and we need some headroom for passing the frame to monitor
+ * interfaces, but never both at the same time.
+ */
+ local->tx_headroom = max(local->hw.extra_tx_headroom,
+ sizeof(struct ieee80211_tx_status_rtap_hdr));
+
debugfs_hw_add(local);
local->hw.conf.beacon_int = 1000;
diff --git a/net/mac80211/ieee80211_common.h b/net/mac80211/ieee80211_common.h
index b9a73e7f5f7..77c6afb7f6a 100644
--- a/net/mac80211/ieee80211_common.h
+++ b/net/mac80211/ieee80211_common.h
@@ -47,21 +47,16 @@ enum ieee80211_msg_type {
ieee80211_msg_normal = 0,
ieee80211_msg_tx_callback_ack = 1,
ieee80211_msg_tx_callback_fail = 2,
- ieee80211_msg_passive_scan = 3,
+ /* hole at 3, was ieee80211_msg_passive_scan but unused */
ieee80211_msg_wep_frame_unknown_key = 4,
ieee80211_msg_michael_mic_failure = 5,
/* hole at 6, was monitor but never sent to userspace */
ieee80211_msg_sta_not_assoc = 7,
- ieee80211_msg_set_aid_for_sta = 8 /* used by Intersil MVC driver */,
+ /* 8 was ieee80211_msg_set_aid_for_sta */
ieee80211_msg_key_threshold_notification = 9,
ieee80211_msg_radar = 11,
};
-struct ieee80211_msg_set_aid_for_sta {
- char sta_address[ETH_ALEN];
- u16 aid;
-};
-
struct ieee80211_msg_key_notification {
int tx_rx_count;
char ifname[IFNAMSIZ];
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index af4d14d0b96..055a2a91218 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -99,6 +99,12 @@ struct ieee80211_sta_bss {
int probe_resp;
unsigned long last_update;
+ /* during assocation, we save an ERP value from a probe response so
+ * that we can feed ERP info to the driver when handling the
+ * association completes. these fields probably won't be up-to-date
+ * otherwise, you probably don't want to use them. */
+ int has_erp_value;
+ u8 erp_value;
};
@@ -235,7 +241,6 @@ struct ieee80211_if_sta {
unsigned int authenticated:1;
unsigned int associated:1;
unsigned int probereq_poll:1;
- unsigned int use_protection:1;
unsigned int create_ibss:1;
unsigned int mixed_cell:1;
unsigned int wmm_enabled:1;
@@ -278,6 +283,7 @@ struct ieee80211_sub_if_data {
int mc_count;
unsigned int allmulti:1;
unsigned int promisc:1;
+ unsigned int use_protection:1; /* CTS protect ERP frames */
struct net_device_stats stats;
int drop_unencrypted;
@@ -392,6 +398,7 @@ struct ieee80211_local {
int monitors;
struct iw_statistics wstats;
u8 wstats_flags;
+ int tx_headroom; /* required headroom for hardware/radiotap */
enum {
IEEE80211_DEV_UNINITIALIZED = 0,
@@ -437,7 +444,6 @@ struct ieee80211_local {
int *basic_rates[NUM_IEEE80211_MODES];
int rts_threshold;
- int cts_protect_erp_frames;
int fragmentation_threshold;
int short_retry_limit; /* dot11ShortRetryLimit */
int long_retry_limit; /* dot11LongRetryLimit */
@@ -513,8 +519,6 @@ struct ieee80211_local {
STA_ANTENNA_SEL_SW_CTRL_DEBUG = 2
} sta_antenna_sel;
- int rate_ctrl_num_up, rate_ctrl_num_down;
-
#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
/* TX/RX handler statistics */
unsigned int tx_handlers_drop;
@@ -719,6 +723,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local,
struct ieee80211_hw_mode *mode);
void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
+int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
+int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
void ieee80211_if_setup(struct net_device *dev);
void ieee80211_if_mgmt_setup(struct net_device *dev);
int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
index cf0f32e8c2a..8532a5ccdd1 100644
--- a/net/mac80211/ieee80211_iface.c
+++ b/net/mac80211/ieee80211_iface.c
@@ -157,6 +157,8 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
int oldtype = sdata->type;
+ dev->hard_start_xmit = ieee80211_subif_start_xmit;
+
sdata->type = type;
switch (type) {
case IEEE80211_IF_TYPE_WDS:
@@ -196,6 +198,7 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
}
case IEEE80211_IF_TYPE_MNTR:
dev->type = ARPHRD_IEEE80211_RADIOTAP;
+ dev->hard_start_xmit = ieee80211_monitor_start_xmit;
break;
default:
printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 352f03bd8a3..5918dd079e1 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -345,6 +345,8 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct iw_range *range = (struct iw_range *) extra;
+ struct ieee80211_hw_mode *mode = NULL;
+ int c = 0;
data->length = sizeof(struct iw_range);
memset(range, 0, sizeof(struct iw_range));
@@ -378,6 +380,29 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+ list_for_each_entry(mode, &local->modes_list, list) {
+ int i = 0;
+
+ if (!(local->enabled_modes & (1 << mode->mode)) ||
+ (local->hw_modes & local->enabled_modes &
+ (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B))
+ continue;
+
+ while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) {
+ struct ieee80211_channel *chan = &mode->channels[i];
+
+ if (chan->flag & IEEE80211_CHAN_W_SCAN) {
+ range->freq[c].i = chan->chan;
+ range->freq[c].m = chan->freq * 100000;
+ range->freq[c].e = 1;
+ c++;
+ }
+ i++;
+ }
+ }
+ range->num_channels = c;
+ range->num_frequency = c;
+
IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
@@ -838,6 +863,67 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev,
}
+static int ieee80211_ioctl_siwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra)
+{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_hw_mode *mode;
+ int i;
+ u32 target_rate = rate->value / 100000;
+ struct ieee80211_sub_if_data *sdata;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (!sdata->bss)
+ return -ENODEV;
+ mode = local->oper_hw_mode;
+ /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
+ * target_rate = X, rate->fixed = 1 means only rate X
+ * target_rate = X, rate->fixed = 0 means all rates <= X */
+ sdata->bss->max_ratectrl_rateidx = -1;
+ sdata->bss->force_unicast_rateidx = -1;
+ if (rate->value < 0)
+ return 0;
+ for (i=0; i< mode->num_rates; i++) {
+ struct ieee80211_rate *rates = &mode->rates[i];
+ int this_rate = rates->rate;
+
+ if (mode->mode == MODE_ATHEROS_TURBO ||
+ mode->mode == MODE_ATHEROS_TURBOG)
+ this_rate *= 2;
+ if (target_rate == this_rate) {
+ sdata->bss->max_ratectrl_rateidx = i;
+ if (rate->fixed)
+ sdata->bss->force_unicast_rateidx = i;
+ break;
+ }
+ }
+ return 0;
+}
+
+static int ieee80211_ioctl_giwrate(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rate, char *extra)
+{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct sta_info *sta;
+ struct ieee80211_sub_if_data *sdata;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (sdata->type == IEEE80211_IF_TYPE_STA)
+ sta = sta_info_get(local, sdata->u.sta.bssid);
+ else
+ return -EOPNOTSUPP;
+ if (!sta)
+ return -ENODEV;
+ if (sta->txrate < local->oper_hw_mode->num_rates)
+ rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000;
+ else
+ rate->value = 0;
+ sta_info_put(sta);
+ return 0;
+}
+
static int ieee80211_ioctl_siwrts(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *rts, char *extra)
@@ -970,118 +1056,6 @@ static int ieee80211_ioctl_giwretry(struct net_device *dev,
return 0;
}
-static int ieee80211_ioctl_clear_keys(struct net_device *dev)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_key_conf key;
- int i;
- u8 addr[ETH_ALEN];
- struct ieee80211_key_conf *keyconf;
- struct ieee80211_sub_if_data *sdata;
- struct sta_info *sta;
-
- memset(addr, 0xff, ETH_ALEN);
- read_lock(&local->sub_if_lock);
- list_for_each_entry(sdata, &local->sub_if_list, list) {
- for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- keyconf = NULL;
- if (sdata->keys[i] &&
- !sdata->keys[i]->force_sw_encrypt &&
- local->ops->set_key &&
- (keyconf = ieee80211_key_data2conf(local,
- sdata->keys[i])))
- local->ops->set_key(local_to_hw(local),
- DISABLE_KEY, addr,
- keyconf, 0);
- kfree(keyconf);
- ieee80211_key_free(sdata->keys[i]);
- sdata->keys[i] = NULL;
- }
- sdata->default_key = NULL;
- }
- read_unlock(&local->sub_if_lock);
-
- spin_lock_bh(&local->sta_lock);
- list_for_each_entry(sta, &local->sta_list, list) {
- keyconf = NULL;
- if (sta->key && !sta->key->force_sw_encrypt &&
- local->ops->set_key &&
- (keyconf = ieee80211_key_data2conf(local, sta->key)))
- local->ops->set_key(local_to_hw(local), DISABLE_KEY,
- sta->addr, keyconf, sta->aid);
- kfree(keyconf);
- ieee80211_key_free(sta->key);
- sta->key = NULL;
- }
- spin_unlock_bh(&local->sta_lock);
-
- memset(&key, 0, sizeof(key));
- if (local->ops->set_key &&
- local->ops->set_key(local_to_hw(local), REMOVE_ALL_KEYS,
- NULL, &key, 0))
- printk(KERN_DEBUG "%s: failed to remove hwaccel keys\n",
- dev->name);
-
- return 0;
-}
-
-
-static int
-ieee80211_ioctl_force_unicast_rate(struct net_device *dev,
- struct ieee80211_sub_if_data *sdata,
- int rate)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_hw_mode *mode;
- int i;
-
- if (sdata->type != IEEE80211_IF_TYPE_AP)
- return -ENOENT;
-
- if (rate == 0) {
- sdata->u.ap.force_unicast_rateidx = -1;
- return 0;
- }
-
- mode = local->oper_hw_mode;
- for (i = 0; i < mode->num_rates; i++) {
- if (mode->rates[i].rate == rate) {
- sdata->u.ap.force_unicast_rateidx = i;
- return 0;
- }
- }
- return -EINVAL;
-}
-
-
-static int
-ieee80211_ioctl_max_ratectrl_rate(struct net_device *dev,
- struct ieee80211_sub_if_data *sdata,
- int rate)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_hw_mode *mode;
- int i;
-
- if (sdata->type != IEEE80211_IF_TYPE_AP)
- return -ENOENT;
-
- if (rate == 0) {
- sdata->u.ap.max_ratectrl_rateidx = -1;
- return 0;
- }
-
- mode = local->oper_hw_mode;
- for (i = 0; i < mode->num_rates; i++) {
- if (mode->rates[i].rate == rate) {
- sdata->u.ap.max_ratectrl_rateidx = i;
- return 0;
- }
- }
- return -EINVAL;
-}
-
-
static void ieee80211_key_enable_hwaccel(struct ieee80211_local *local,
struct ieee80211_key *key)
{
@@ -1205,24 +1179,11 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev,
sdata->ieee802_1x = value;
break;
- case PRISM2_PARAM_ANTSEL_TX:
- local->hw.conf.antenna_sel_tx = value;
- if (ieee80211_hw_config(local))
- ret = -EINVAL;
- break;
-
- case PRISM2_PARAM_ANTSEL_RX:
- local->hw.conf.antenna_sel_rx = value;
- if (ieee80211_hw_config(local))
- ret = -EINVAL;
- break;
-
case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
- local->cts_protect_erp_frames = value;
- break;
-
- case PRISM2_PARAM_DROP_UNENCRYPTED:
- sdata->drop_unencrypted = value;
+ if (sdata->type != IEEE80211_IF_TYPE_AP)
+ ret = -ENOENT;
+ else
+ sdata->use_protection = value;
break;
case PRISM2_PARAM_PREAMBLE:
@@ -1251,10 +1212,6 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev,
local->next_mode = value;
break;
- case PRISM2_PARAM_CLEAR_KEYS:
- ret = ieee80211_ioctl_clear_keys(dev);
- break;
-
case PRISM2_PARAM_RADIO_ENABLED:
ret = ieee80211_ioctl_set_radio_enabled(dev, value);
break;
@@ -1269,22 +1226,6 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev,
local->sta_antenna_sel = value;
break;
- case PRISM2_PARAM_FORCE_UNICAST_RATE:
- ret = ieee80211_ioctl_force_unicast_rate(dev, sdata, value);
- break;
-
- case PRISM2_PARAM_MAX_RATECTRL_RATE:
- ret = ieee80211_ioctl_max_ratectrl_rate(dev, sdata, value);
- break;
-
- case PRISM2_PARAM_RATE_CTRL_NUM_UP:
- local->rate_ctrl_num_up = value;
- break;
-
- case PRISM2_PARAM_RATE_CTRL_NUM_DOWN:
- local->rate_ctrl_num_down = value;
- break;
-
case PRISM2_PARAM_TX_POWER_REDUCTION:
if (value < 0)
ret = -EINVAL;
@@ -1364,20 +1305,8 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
*param = sdata->ieee802_1x;
break;
- case PRISM2_PARAM_ANTSEL_TX:
- *param = local->hw.conf.antenna_sel_tx;
- break;
-
- case PRISM2_PARAM_ANTSEL_RX:
- *param = local->hw.conf.antenna_sel_rx;
- break;
-
case PRISM2_PARAM_CTS_PROTECT_ERP_FRAMES:
- *param = local->cts_protect_erp_frames;
- break;
-
- case PRISM2_PARAM_DROP_UNENCRYPTED:
- *param = sdata->drop_unencrypted;
+ *param = sdata->use_protection;
break;
case PRISM2_PARAM_PREAMBLE:
@@ -1403,14 +1332,6 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
*param = local->sta_antenna_sel;
break;
- case PRISM2_PARAM_RATE_CTRL_NUM_UP:
- *param = local->rate_ctrl_num_up;
- break;
-
- case PRISM2_PARAM_RATE_CTRL_NUM_DOWN:
- *param = local->rate_ctrl_num_down;
- break;
-
case PRISM2_PARAM_TX_POWER_REDUCTION:
*param = local->hw.conf.tx_power_reduction;
break;
@@ -1778,8 +1699,8 @@ static const iw_handler ieee80211_handler[] =
(iw_handler) NULL, /* SIOCGIWNICKN */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) NULL, /* SIOCSIWRATE */
- (iw_handler) NULL, /* SIOCGIWRATE */
+ (iw_handler) ieee80211_ioctl_siwrate, /* SIOCSIWRATE */
+ (iw_handler) ieee80211_ioctl_giwrate, /* SIOCGIWRATE */
(iw_handler) ieee80211_ioctl_siwrts, /* SIOCSIWRTS */
(iw_handler) ieee80211_ioctl_giwrts, /* SIOCGIWRTS */
(iw_handler) ieee80211_ioctl_siwfrag, /* SIOCSIWFRAG */
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 3e07e9d6fa4..ba2bf8f0a34 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -76,33 +76,36 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
/* Parsed Information Elements */
struct ieee802_11_elems {
+ /* pointers to IEs */
u8 *ssid;
- u8 ssid_len;
u8 *supp_rates;
- u8 supp_rates_len;
u8 *fh_params;
- u8 fh_params_len;
u8 *ds_params;
- u8 ds_params_len;
u8 *cf_params;
- u8 cf_params_len;
u8 *tim;
- u8 tim_len;
u8 *ibss_params;
- u8 ibss_params_len;
u8 *challenge;
- u8 challenge_len;
u8 *wpa;
- u8 wpa_len;
u8 *rsn;
- u8 rsn_len;
u8 *erp_info;
- u8 erp_info_len;
u8 *ext_supp_rates;
- u8 ext_supp_rates_len;
u8 *wmm_info;
- u8 wmm_info_len;
u8 *wmm_param;
+
+ /* length of them, respectively */
+ u8 ssid_len;
+ u8 supp_rates_len;
+ u8 fh_params_len;
+ u8 ds_params_len;
+ u8 cf_params_len;
+ u8 tim_len;
+ u8 ibss_params_len;
+ u8 challenge_len;
+ u8 wpa_len;
+ u8 rsn_len;
+ u8 erp_info_len;
+ u8 ext_supp_rates_len;
+ u8 wmm_info_len;
u8 wmm_param_len;
};
@@ -311,6 +314,25 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
}
+static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+ int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+
+ if (use_protection != sdata->use_protection) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
+ MAC_FMT ")\n",
+ dev->name,
+ use_protection ? "enabled" : "disabled",
+ MAC_ARG(ifsta->bssid));
+ }
+ sdata->use_protection = use_protection;
+ }
+}
+
+
static void ieee80211_sta_send_associnfo(struct net_device *dev,
struct ieee80211_if_sta *ifsta)
{
@@ -366,6 +388,7 @@ static void ieee80211_set_associated(struct net_device *dev,
struct ieee80211_if_sta *ifsta, int assoc)
{
union iwreq_data wrqu;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (ifsta->associated == assoc)
return;
@@ -374,9 +397,18 @@ static void ieee80211_set_associated(struct net_device *dev,
if (assoc) {
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_sta_bss *bss;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type != IEEE80211_IF_TYPE_STA)
return;
+
+ bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+ if (bss) {
+ if (bss->has_erp_value)
+ ieee80211_handle_erp_ie(dev, bss->erp_value);
+ ieee80211_rx_bss_put(dev, bss);
+ }
+
netif_carrier_on(dev);
ifsta->prev_bssid_set = 1;
memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
@@ -384,6 +416,7 @@ static void ieee80211_set_associated(struct net_device *dev,
ieee80211_sta_send_associnfo(dev, ifsta);
} else {
netif_carrier_off(dev);
+ sdata->use_protection = 0;
memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
}
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -1155,6 +1188,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
if (status_code != WLAN_STATUS_SUCCESS) {
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
dev->name, status_code);
+ if (status_code == WLAN_STATUS_REASSOC_NO_ASSOC)
+ ifsta->prev_bssid_set = 0;
return;
}
@@ -1172,6 +1207,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
return;
}
+ /* it probably doesn't, but if the frame includes an ERP value then
+ * update our stored copy */
+ if (elems.erp_info && elems.erp_info_len >= 1) {
+ struct ieee80211_sta_bss *bss
+ = ieee80211_rx_bss_get(dev, ifsta->bssid);
+ if (bss) {
+ bss->erp_value = elems.erp_info[0];
+ bss->has_erp_value = 1;
+ ieee80211_rx_bss_put(dev, bss);
+ }
+ }
+
printk(KERN_DEBUG "%s: associated\n", dev->name);
ifsta->aid = aid;
ifsta->ap_capab = capab_info;
@@ -1494,6 +1541,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
return;
}
+ /* save the ERP value so that it is available at association time */
+ if (elems.erp_info && elems.erp_info_len >= 1) {
+ bss->erp_value = elems.erp_info[0];
+ bss->has_erp_value = 1;
+ }
+
bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
@@ -1609,10 +1662,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
size_t len,
struct ieee80211_rx_status *rx_status)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_if_sta *ifsta;
- int use_protection;
size_t baselen;
struct ieee802_11_elems elems;
@@ -1636,23 +1687,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
&elems) == ParseFailed)
return;
- use_protection = 0;
- if (elems.erp_info && elems.erp_info_len >= 1) {
- use_protection =
- (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
- }
-
- if (use_protection != !!ifsta->use_protection) {
- if (net_ratelimit()) {
- printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
- MAC_FMT ")\n",
- dev->name,
- use_protection ? "enabled" : "disabled",
- MAC_ARG(ifsta->bssid));
- }
- ifsta->use_protection = use_protection ? 1 : 0;
- local->cts_protect_erp_frames = use_protection;
- }
+ if (elems.erp_info && elems.erp_info_len >= 1)
+ ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
if (elems.wmm_param && ifsta->wmm_enabled) {
ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
@@ -2590,11 +2626,17 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
read_lock(&local->sub_if_lock);
list_for_each_entry(sdata, &local->sub_if_list, list) {
+
+ /* No need to wake the master device. */
+ if (sdata->dev == local->mdev)
+ continue;
+
if (sdata->type == IEEE80211_IF_TYPE_STA) {
if (sdata->u.sta.associated)
ieee80211_send_nullfunc(local, sdata, 0);
ieee80211_sta_timer((unsigned long)sdata);
}
+
netif_wake_queue(sdata->dev);
}
read_unlock(&local->sub_if_lock);
@@ -2736,6 +2778,12 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
read_lock(&local->sub_if_lock);
list_for_each_entry(sdata, &local->sub_if_list, list) {
+
+ /* Don't stop the master interface, otherwise we can't transmit
+ * probes! */
+ if (sdata->dev == local->mdev)
+ continue;
+
netif_stop_queue(sdata->dev);
if (sdata->type == IEEE80211_IF_TYPE_STA &&
sdata->u.sta.associated)
@@ -2995,7 +3043,7 @@ struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta;
- struct ieee80211_sub_if_data *sdata = NULL;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
/* TODO: Could consider removing the least recently used entry and
* allow new one to be added. */
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
index 2048cfd1ca7..f6780d63b34 100644
--- a/net/mac80211/rc80211_simple.c
+++ b/net/mac80211/rc80211_simple.c
@@ -187,9 +187,13 @@ static void rate_control_simple_tx_status(void *priv, struct net_device *dev,
}
#endif
- if (per_failed > local->rate_ctrl_num_down) {
+ /*
+ * XXX: Make these configurable once we have an
+ * interface to the rate control algorithms
+ */
+ if (per_failed > RATE_CONTROL_NUM_DOWN) {
rate_control_rate_dec(local, sta);
- } else if (per_failed < local->rate_ctrl_num_up) {
+ } else if (per_failed < RATE_CONTROL_NUM_UP) {
rate_control_rate_inc(local, sta);
}
srctrl->tx_avg_rate_sum += status->control.rate->rate;
@@ -283,14 +287,16 @@ static void rate_control_simple_rate_init(void *priv, void *priv_sta,
int i;
sta->txrate = 0;
mode = local->oper_hw_mode;
- /* TODO: what is a good starting rate for STA? About middle? Maybe not
- * the lowest or the highest rate.. Could consider using RSSI from
- * previous packets? Need to have IEEE 802.1X auth succeed immediately
- * after assoc.. */
+ /* TODO: This routine should consider using RSSI from previous packets
+ * as we need to have IEEE 802.1X auth succeed immediately after assoc..
+ * Until that method is implemented, we will use the lowest supported rate
+ * as a workaround, */
for (i = 0; i < mode->num_rates; i++) {
if ((sta->supp_rates & BIT(i)) &&
- (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
+ (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) {
sta->txrate = i;
+ break;
+ }
}
}
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index a567dae8e5f..3ac39f1ec77 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -102,6 +102,16 @@ config NF_CT_PROTO_SCTP
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+config NF_CT_PROTO_UDPLITE
+ tristate 'UDP-Lite protocol connection tracking support (EXPERIMENTAL)'
+ depends on EXPERIMENTAL && NF_CONNTRACK
+ help
+ With this option enabled, the layer 3 independent connection
+ tracking code will be able to do state tracking on UDP-Lite
+ connections.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NF_CONNTRACK_AMANDA
tristate "Amanda backup protocol support"
depends on NF_CONNTRACK
@@ -343,6 +353,18 @@ config NETFILTER_XT_TARGET_NOTRACK
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+config NETFILTER_XT_TARGET_TRACE
+ tristate '"TRACE" target support'
+ depends on NETFILTER_XTABLES
+ depends on IP_NF_RAW || IP6_NF_RAW
+ help
+ The TRACE target allows you to mark packets so that the kernel
+ will log every rule which match the packets as those traverse
+ the tables, chains, rules.
+
+ If you want to compile it as a module, say M here and read
+ <file:Documentation/modules.txt>. If unsure, say `N'.
+
config NETFILTER_XT_TARGET_SECMARK
tristate '"SECMARK" target support'
depends on NETFILTER_XTABLES && NETWORK_SECMARK
@@ -411,6 +433,13 @@ config NETFILTER_XT_MATCH_CONNBYTES
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+config NETFILTER_XT_MATCH_CONNLIMIT
+ tristate '"connlimit" match support"'
+ depends on NETFILTER_XTABLES
+ ---help---
+ This match allows you to match against the number of parallel
+ connections to a server per client IP address (or address block).
+
config NETFILTER_XT_MATCH_CONNMARK
tristate '"connmark" connection mark match support'
depends on NETFILTER_XTABLES
@@ -635,6 +664,19 @@ config NETFILTER_XT_MATCH_TCPMSS
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_MATCH_U32
+ tristate '"u32" match support'
+ depends on NETFILTER_XTABLES
+ ---help---
+ u32 allows you to extract quantities of up to 4 bytes from a packet,
+ AND them with specified masks, shift them by specified amounts and
+ test whether the results are in any of a set of specified ranges.
+ The specification of what to extract is general enough to skip over
+ headers with lengths stored in the packet, as in IP or TCP header
+ lengths.
+
+ Details and examples are in the kernel module source.
+
config NETFILTER_XT_MATCH_HASHLIMIT
tristate '"hashlimit" match support'
depends on NETFILTER_XTABLES && (IP6_NF_IPTABLES || IP6_NF_IPTABLES=n)
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index b2b5c7566b2..0c054bf2797 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,6 +1,6 @@
netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
-nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
+nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o
nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
obj-$(CONFIG_NETFILTER) = netfilter.o
@@ -16,6 +16,7 @@ obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
# SCTP protocol connection tracking
obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
# netlink interface for nf_conntrack
obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
@@ -44,6 +45,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
@@ -51,6 +53,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
# matches
obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
@@ -72,4 +75,5 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index a84478ee2de..381a77cf0c9 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -203,7 +203,9 @@ int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len)
return 0;
/* Not exclusive use of packet? Must copy. */
- if (skb_shared(*pskb) || skb_cloned(*pskb))
+ if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len))
+ goto copy_skb;
+ if (skb_shared(*pskb))
goto copy_skb;
return pskb_may_pull(*pskb, writable_len);
@@ -229,13 +231,13 @@ void nf_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
{
__be32 diff[] = { ~from, to };
if (skb->ip_summed != CHECKSUM_PARTIAL) {
- *sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
+ *sum = csum_fold(csum_partial(diff, sizeof(diff),
~csum_unfold(*sum)));
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
- skb->csum = ~csum_partial((char *)diff, sizeof(diff),
+ skb->csum = ~csum_partial(diff, sizeof(diff),
~skb->csum);
} else if (pseudohdr)
- *sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff),
+ *sum = ~csum_fold(csum_partial(diff, sizeof(diff),
csum_unfold(*sum)));
}
EXPORT_SYMBOL(nf_proto_csum_replace4);
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c
index b8869eab765..e42ab230ad8 100644
--- a/net/netfilter/nf_conntrack_amanda.c
+++ b/net/netfilter/nf_conntrack_amanda.c
@@ -142,23 +142,22 @@ static int amanda_help(struct sk_buff **pskb,
if (port == 0 || len > 5)
break;
- exp = nf_conntrack_expect_alloc(ct);
+ exp = nf_ct_expect_alloc(ct);
if (exp == NULL) {
ret = NF_DROP;
goto out;
}
tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
- nf_conntrack_expect_init(exp, family,
- &tuple->src.u3, &tuple->dst.u3,
- IPPROTO_TCP, NULL, &port);
+ nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+ IPPROTO_TCP, NULL, &port);
nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
ret = nf_nat_amanda(pskb, ctinfo, off - dataoff,
len, exp);
- else if (nf_conntrack_expect_related(exp) != 0)
+ else if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
}
out:
@@ -175,9 +174,6 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
.tuple.src.l3num = AF_INET,
.tuple.src.u.udp.port = __constant_htons(10080),
.tuple.dst.protonum = IPPROTO_UDP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.udp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
},
{
.name = "amanda",
@@ -188,9 +184,6 @@ static struct nf_conntrack_helper amanda_helper[2] __read_mostly = {
.tuple.src.l3num = AF_INET6,
.tuple.src.u.udp.port = __constant_htons(10080),
.tuple.dst.protonum = IPPROTO_UDP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.udp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
},
};
@@ -208,13 +201,14 @@ static int __init nf_conntrack_amanda_init(void)
{
int ret, i;
- ret = -ENOMEM;
for (i = 0; i < ARRAY_SIZE(search); i++) {
search[i].ts = textsearch_prepare(ts_algo, search[i].string,
search[i].len,
GFP_KERNEL, TS_AUTOLOAD);
- if (search[i].ts == NULL)
+ if (IS_ERR(search[i].ts)) {
+ ret = PTR_ERR(search[i].ts);
goto err1;
+ }
}
ret = nf_conntrack_helper_register(&amanda_helper[0]);
if (ret < 0)
@@ -227,10 +221,9 @@ static int __init nf_conntrack_amanda_init(void)
err2:
nf_conntrack_helper_unregister(&amanda_helper[0]);
err1:
- for (; i >= 0; i--) {
- if (search[i].ts)
- textsearch_destroy(search[i].ts);
- }
+ while (--i >= 0)
+ textsearch_destroy(search[i].ts);
+
return ret;
}
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 483e927a9ca..8cce814f6be 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -36,15 +36,10 @@
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
#define NF_CONNTRACK_VERSION "0.5.0"
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
DEFINE_RWLOCK(nf_conntrack_lock);
EXPORT_SYMBOL_GPL(nf_conntrack_lock);
@@ -52,57 +47,27 @@ EXPORT_SYMBOL_GPL(nf_conntrack_lock);
atomic_t nf_conntrack_count = ATOMIC_INIT(0);
EXPORT_SYMBOL_GPL(nf_conntrack_count);
-void (*nf_conntrack_destroyed)(struct nf_conn *conntrack);
-EXPORT_SYMBOL_GPL(nf_conntrack_destroyed);
-
unsigned int nf_conntrack_htable_size __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
int nf_conntrack_max __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_max);
-struct list_head *nf_conntrack_hash __read_mostly;
+struct hlist_head *nf_conntrack_hash __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_hash);
struct nf_conn nf_conntrack_untracked __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_untracked);
unsigned int nf_ct_log_invalid __read_mostly;
-LIST_HEAD(unconfirmed);
+HLIST_HEAD(unconfirmed);
static int nf_conntrack_vmalloc __read_mostly;
-
+static struct kmem_cache *nf_conntrack_cachep __read_mostly;
static unsigned int nf_conntrack_next_id;
DEFINE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
EXPORT_PER_CPU_SYMBOL(nf_conntrack_stat);
-/*
- * This scheme offers various size of "struct nf_conn" dependent on
- * features(helper, nat, ...)
- */
-
-#define NF_CT_FEATURES_NAMELEN 256
-static struct {
- /* name of slab cache. printed in /proc/slabinfo */
- char *name;
-
- /* size of slab cache */
- size_t size;
-
- /* slab cache pointer */
- struct kmem_cache *cachep;
-
- /* allocated slab cache + modules which uses this slab cache */
- int use;
-
-} nf_ct_cache[NF_CT_F_NUM];
-
-/* protect members of nf_ct_cache except of "use" */
-DEFINE_RWLOCK(nf_ct_cache_lock);
-
-/* This avoids calling kmem_cache_create() with same name simultaneously */
-static DEFINE_MUTEX(nf_ct_cache_mutex);
-
static int nf_conntrack_hash_rnd_initted;
static unsigned int nf_conntrack_hash_rnd;
@@ -125,122 +90,6 @@ static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)
nf_conntrack_hash_rnd);
}
-int nf_conntrack_register_cache(u_int32_t features, const char *name,
- size_t size)
-{
- int ret = 0;
- char *cache_name;
- struct kmem_cache *cachep;
-
- DEBUGP("nf_conntrack_register_cache: features=0x%x, name=%s, size=%d\n",
- features, name, size);
-
- if (features < NF_CT_F_BASIC || features >= NF_CT_F_NUM) {
- DEBUGP("nf_conntrack_register_cache: invalid features.: 0x%x\n",
- features);
- return -EINVAL;
- }
-
- mutex_lock(&nf_ct_cache_mutex);
-
- write_lock_bh(&nf_ct_cache_lock);
- /* e.g: multiple helpers are loaded */
- if (nf_ct_cache[features].use > 0) {
- DEBUGP("nf_conntrack_register_cache: already resisterd.\n");
- if ((!strncmp(nf_ct_cache[features].name, name,
- NF_CT_FEATURES_NAMELEN))
- && nf_ct_cache[features].size == size) {
- DEBUGP("nf_conntrack_register_cache: reusing.\n");
- nf_ct_cache[features].use++;
- ret = 0;
- } else
- ret = -EBUSY;
-
- write_unlock_bh(&nf_ct_cache_lock);
- mutex_unlock(&nf_ct_cache_mutex);
- return ret;
- }
- write_unlock_bh(&nf_ct_cache_lock);
-
- /*
- * The memory space for name of slab cache must be alive until
- * cache is destroyed.
- */
- cache_name = kmalloc(sizeof(char)*NF_CT_FEATURES_NAMELEN, GFP_ATOMIC);
- if (cache_name == NULL) {
- DEBUGP("nf_conntrack_register_cache: can't alloc cache_name\n");
- ret = -ENOMEM;
- goto out_up_mutex;
- }
-
- if (strlcpy(cache_name, name, NF_CT_FEATURES_NAMELEN)
- >= NF_CT_FEATURES_NAMELEN) {
- printk("nf_conntrack_register_cache: name too long\n");
- ret = -EINVAL;
- goto out_free_name;
- }
-
- cachep = kmem_cache_create(cache_name, size, 0, 0,
- NULL, NULL);
- if (!cachep) {
- printk("nf_conntrack_register_cache: Can't create slab cache "
- "for the features = 0x%x\n", features);
- ret = -ENOMEM;
- goto out_free_name;
- }
-
- write_lock_bh(&nf_ct_cache_lock);
- nf_ct_cache[features].use = 1;
- nf_ct_cache[features].size = size;
- nf_ct_cache[features].cachep = cachep;
- nf_ct_cache[features].name = cache_name;
- write_unlock_bh(&nf_ct_cache_lock);
-
- goto out_up_mutex;
-
-out_free_name:
- kfree(cache_name);
-out_up_mutex:
- mutex_unlock(&nf_ct_cache_mutex);
- return ret;
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_register_cache);
-
-/* FIXME: In the current, only nf_conntrack_cleanup() can call this function. */
-void nf_conntrack_unregister_cache(u_int32_t features)
-{
- struct kmem_cache *cachep;
- char *name;
-
- /*
- * This assures that kmem_cache_create() isn't called before destroying
- * slab cache.
- */
- DEBUGP("nf_conntrack_unregister_cache: 0x%04x\n", features);
- mutex_lock(&nf_ct_cache_mutex);
-
- write_lock_bh(&nf_ct_cache_lock);
- if (--nf_ct_cache[features].use > 0) {
- write_unlock_bh(&nf_ct_cache_lock);
- mutex_unlock(&nf_ct_cache_mutex);
- return;
- }
- cachep = nf_ct_cache[features].cachep;
- name = nf_ct_cache[features].name;
- nf_ct_cache[features].cachep = NULL;
- nf_ct_cache[features].name = NULL;
- nf_ct_cache[features].size = 0;
- write_unlock_bh(&nf_ct_cache_lock);
-
- synchronize_net();
-
- kmem_cache_destroy(cachep);
- kfree(name);
-
- mutex_unlock(&nf_ct_cache_mutex);
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_unregister_cache);
-
int
nf_ct_get_tuple(const struct sk_buff *skb,
unsigned int nhoff,
@@ -264,6 +113,36 @@ nf_ct_get_tuple(const struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
+int nf_ct_get_tuplepr(const struct sk_buff *skb,
+ unsigned int nhoff,
+ u_int16_t l3num,
+ struct nf_conntrack_tuple *tuple)
+{
+ struct nf_conntrack_l3proto *l3proto;
+ struct nf_conntrack_l4proto *l4proto;
+ unsigned int protoff;
+ u_int8_t protonum;
+ int ret;
+
+ rcu_read_lock();
+
+ l3proto = __nf_ct_l3proto_find(l3num);
+ ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum);
+ if (ret != NF_ACCEPT) {
+ rcu_read_unlock();
+ return 0;
+ }
+
+ l4proto = __nf_ct_l4proto_find(l3num, protonum);
+
+ ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple,
+ l3proto, l4proto);
+
+ rcu_read_unlock();
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr);
+
int
nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig,
@@ -286,9 +165,9 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
static void
clean_from_lists(struct nf_conn *ct)
{
- DEBUGP("clean_from_lists(%p)\n", ct);
- list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
- list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
+ pr_debug("clean_from_lists(%p)\n", ct);
+ hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
+ hlist_del(&ct->tuplehash[IP_CT_DIR_REPLY].hnode);
/* Destroy all pending expectations */
nf_ct_remove_expectations(ct);
@@ -299,9 +178,8 @@ destroy_conntrack(struct nf_conntrack *nfct)
{
struct nf_conn *ct = (struct nf_conn *)nfct;
struct nf_conntrack_l4proto *l4proto;
- typeof(nf_conntrack_destroyed) destroyed;
- DEBUGP("destroy_conntrack(%p)\n", ct);
+ pr_debug("destroy_conntrack(%p)\n", ct);
NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
NF_CT_ASSERT(!timer_pending(&ct->timeout));
@@ -317,9 +195,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
if (l4proto && l4proto->destroy)
l4proto->destroy(ct);
- destroyed = rcu_dereference(nf_conntrack_destroyed);
- if (destroyed)
- destroyed(ct);
+ nf_ct_ext_destroy(ct);
rcu_read_unlock();
@@ -332,8 +208,8 @@ destroy_conntrack(struct nf_conntrack *nfct)
/* We overload first tuple to link into unconfirmed list. */
if (!nf_ct_is_confirmed(ct)) {
- BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list));
- list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+ BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode));
+ hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
}
NF_CT_STAT_INC(delete);
@@ -342,7 +218,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
if (ct->master)
nf_ct_put(ct->master);
- DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
+ pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct);
nf_conntrack_free(ct);
}
@@ -350,9 +226,15 @@ static void death_by_timeout(unsigned long ul_conntrack)
{
struct nf_conn *ct = (void *)ul_conntrack;
struct nf_conn_help *help = nfct_help(ct);
+ struct nf_conntrack_helper *helper;
- if (help && help->helper && help->helper->destroy)
- help->helper->destroy(ct);
+ if (help) {
+ rcu_read_lock();
+ helper = rcu_dereference(help->helper);
+ if (helper && helper->destroy)
+ helper->destroy(ct);
+ rcu_read_unlock();
+ }
write_lock_bh(&nf_conntrack_lock);
/* Inside lock so preempt is disabled on module removal path.
@@ -368,9 +250,10 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack)
{
struct nf_conntrack_tuple_hash *h;
+ struct hlist_node *n;
unsigned int hash = hash_conntrack(tuple);
- list_for_each_entry(h, &nf_conntrack_hash[hash], list) {
+ hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) {
if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
nf_ct_tuple_equal(tuple, &h->tuple)) {
NF_CT_STAT_INC(found);
@@ -385,13 +268,12 @@ EXPORT_SYMBOL_GPL(__nf_conntrack_find);
/* Find a connection corresponding to a tuple. */
struct nf_conntrack_tuple_hash *
-nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
- const struct nf_conn *ignored_conntrack)
+nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_tuple_hash *h;
read_lock_bh(&nf_conntrack_lock);
- h = __nf_conntrack_find(tuple, ignored_conntrack);
+ h = __nf_conntrack_find(tuple, NULL);
if (h)
atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use);
read_unlock_bh(&nf_conntrack_lock);
@@ -405,10 +287,10 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct,
unsigned int repl_hash)
{
ct->id = ++nf_conntrack_next_id;
- list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
- &nf_conntrack_hash[hash]);
- list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list,
- &nf_conntrack_hash[repl_hash]);
+ hlist_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
+ &nf_conntrack_hash[hash]);
+ hlist_add_head(&ct->tuplehash[IP_CT_DIR_REPLY].hnode,
+ &nf_conntrack_hash[repl_hash]);
}
void nf_conntrack_hash_insert(struct nf_conn *ct)
@@ -432,6 +314,7 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
struct nf_conntrack_tuple_hash *h;
struct nf_conn *ct;
struct nf_conn_help *help;
+ struct hlist_node *n;
enum ip_conntrack_info ctinfo;
ct = nf_ct_get(*pskb, &ctinfo);
@@ -454,24 +337,24 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
/* No external references means noone else could have
confirmed us. */
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
- DEBUGP("Confirming conntrack %p\n", ct);
+ pr_debug("Confirming conntrack %p\n", ct);
write_lock_bh(&nf_conntrack_lock);
/* See if there's one in the list already, including reverse:
NAT could have grabbed it without realizing, since we're
not in the hash. If there is, we lost race. */
- list_for_each_entry(h, &nf_conntrack_hash[hash], list)
+ hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode)
if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
&h->tuple))
goto out;
- list_for_each_entry(h, &nf_conntrack_hash[repl_hash], list)
+ hlist_for_each_entry(h, n, &nf_conntrack_hash[repl_hash], hnode)
if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
&h->tuple))
goto out;
/* Remove from unconfirmed list */
- list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
+ hlist_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode);
__nf_conntrack_hash_insert(ct, hash, repl_hash);
/* Timer relative to confirmation time, not original
@@ -518,24 +401,33 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
}
EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken);
+#define NF_CT_EVICTION_RANGE 8
+
/* There's a small race here where we may free a just-assured
connection. Too bad: we're in trouble anyway. */
-static int early_drop(struct list_head *chain)
+static int early_drop(unsigned int hash)
{
- /* Traverse backwards: gives us oldest, which is roughly LRU */
+ /* Use oldest entry, which is roughly LRU */
struct nf_conntrack_tuple_hash *h;
struct nf_conn *ct = NULL, *tmp;
+ struct hlist_node *n;
+ unsigned int i, cnt = 0;
int dropped = 0;
read_lock_bh(&nf_conntrack_lock);
- list_for_each_entry_reverse(h, chain, list) {
- tmp = nf_ct_tuplehash_to_ctrack(h);
- if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) {
- ct = tmp;
- atomic_inc(&ct->ct_general.use);
- break;
+ for (i = 0; i < nf_conntrack_htable_size; i++) {
+ hlist_for_each_entry(h, n, &nf_conntrack_hash[hash], hnode) {
+ tmp = nf_ct_tuplehash_to_ctrack(h);
+ if (!test_bit(IPS_ASSURED_BIT, &tmp->status))
+ ct = tmp;
+ cnt++;
}
+ if (ct || cnt >= NF_CT_EVICTION_RANGE)
+ break;
+ hash = (hash + 1) % nf_conntrack_htable_size;
}
+ if (ct)
+ atomic_inc(&ct->ct_general.use);
read_unlock_bh(&nf_conntrack_lock);
if (!ct)
@@ -550,14 +442,10 @@ static int early_drop(struct list_head *chain)
return dropped;
}
-static struct nf_conn *
-__nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
- const struct nf_conntrack_tuple *repl,
- const struct nf_conntrack_l3proto *l3proto,
- u_int32_t features)
+struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_tuple *repl)
{
struct nf_conn *conntrack = NULL;
- struct nf_conntrack_helper *helper;
if (unlikely(!nf_conntrack_hash_rnd_initted)) {
get_random_bytes(&nf_conntrack_hash_rnd, 4);
@@ -570,8 +458,7 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
if (nf_conntrack_max
&& atomic_read(&nf_conntrack_count) > nf_conntrack_max) {
unsigned int hash = hash_conntrack(orig);
- /* Try dropping from this hash chain. */
- if (!early_drop(&nf_conntrack_hash[hash])) {
+ if (!early_drop(hash)) {
atomic_dec(&nf_conntrack_count);
if (net_ratelimit())
printk(KERN_WARNING
@@ -581,72 +468,28 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
}
}
- /* find features needed by this conntrack. */
- features |= l3proto->get_features(orig);
-
- /* FIXME: protect helper list per RCU */
- read_lock_bh(&nf_conntrack_lock);
- helper = __nf_ct_helper_find(repl);
- /* NAT might want to assign a helper later */
- if (helper || features & NF_CT_F_NAT)
- features |= NF_CT_F_HELP;
- read_unlock_bh(&nf_conntrack_lock);
-
- DEBUGP("nf_conntrack_alloc: features=0x%x\n", features);
-
- read_lock_bh(&nf_ct_cache_lock);
-
- if (unlikely(!nf_ct_cache[features].use)) {
- DEBUGP("nf_conntrack_alloc: not supported features = 0x%x\n",
- features);
- goto out;
- }
-
- conntrack = kmem_cache_alloc(nf_ct_cache[features].cachep, GFP_ATOMIC);
+ conntrack = kmem_cache_zalloc(nf_conntrack_cachep, GFP_ATOMIC);
if (conntrack == NULL) {
- DEBUGP("nf_conntrack_alloc: Can't alloc conntrack from cache\n");
- goto out;
+ pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
+ atomic_dec(&nf_conntrack_count);
+ return ERR_PTR(-ENOMEM);
}
- memset(conntrack, 0, nf_ct_cache[features].size);
- conntrack->features = features;
atomic_set(&conntrack->ct_general.use, 1);
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
/* Don't set timer yet: wait for confirmation */
setup_timer(&conntrack->timeout, death_by_timeout,
(unsigned long)conntrack);
- read_unlock_bh(&nf_ct_cache_lock);
return conntrack;
-out:
- read_unlock_bh(&nf_ct_cache_lock);
- atomic_dec(&nf_conntrack_count);
- return conntrack;
-}
-
-struct nf_conn *nf_conntrack_alloc(const struct nf_conntrack_tuple *orig,
- const struct nf_conntrack_tuple *repl)
-{
- struct nf_conntrack_l3proto *l3proto;
- struct nf_conn *ct;
-
- rcu_read_lock();
- l3proto = __nf_ct_l3proto_find(orig->src.l3num);
- ct = __nf_conntrack_alloc(orig, repl, l3proto, 0);
- rcu_read_unlock();
-
- return ct;
}
EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
void nf_conntrack_free(struct nf_conn *conntrack)
{
- u_int32_t features = conntrack->features;
- NF_CT_ASSERT(features >= NF_CT_F_BASIC && features < NF_CT_F_NUM);
- DEBUGP("nf_conntrack_free: features = 0x%x, conntrack=%p\n", features,
- conntrack);
- kmem_cache_free(nf_ct_cache[features].cachep, conntrack);
+ nf_ct_ext_free(conntrack);
+ kmem_cache_free(nf_conntrack_cachep, conntrack);
atomic_dec(&nf_conntrack_count);
}
EXPORT_SYMBOL_GPL(nf_conntrack_free);
@@ -661,44 +504,41 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
unsigned int dataoff)
{
struct nf_conn *conntrack;
+ struct nf_conn_help *help;
struct nf_conntrack_tuple repl_tuple;
struct nf_conntrack_expect *exp;
- u_int32_t features = 0;
if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
- DEBUGP("Can't invert tuple.\n");
+ pr_debug("Can't invert tuple.\n");
return NULL;
}
- read_lock_bh(&nf_conntrack_lock);
- exp = __nf_conntrack_expect_find(tuple);
- if (exp && exp->helper)
- features = NF_CT_F_HELP;
- read_unlock_bh(&nf_conntrack_lock);
-
- conntrack = __nf_conntrack_alloc(tuple, &repl_tuple, l3proto, features);
+ conntrack = nf_conntrack_alloc(tuple, &repl_tuple);
if (conntrack == NULL || IS_ERR(conntrack)) {
- DEBUGP("Can't allocate conntrack.\n");
+ pr_debug("Can't allocate conntrack.\n");
return (struct nf_conntrack_tuple_hash *)conntrack;
}
if (!l4proto->new(conntrack, skb, dataoff)) {
nf_conntrack_free(conntrack);
- DEBUGP("init conntrack: can't track with proto module\n");
+ pr_debug("init conntrack: can't track with proto module\n");
return NULL;
}
write_lock_bh(&nf_conntrack_lock);
- exp = find_expectation(tuple);
-
+ exp = nf_ct_find_expectation(tuple);
if (exp) {
- DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
- conntrack, exp);
+ pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
+ conntrack, exp);
/* Welcome, Mr. Bond. We've been expecting you... */
__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
conntrack->master = exp->master;
- if (exp->helper)
- nfct_help(conntrack)->helper = exp->helper;
+ if (exp->helper) {
+ help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC);
+ if (help)
+ rcu_assign_pointer(help->helper, exp->helper);
+ }
+
#ifdef CONFIG_NF_CONNTRACK_MARK
conntrack->mark = exp->master->mark;
#endif
@@ -708,22 +548,27 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
nf_conntrack_get(&conntrack->master->ct_general);
NF_CT_STAT_INC(expect_new);
} else {
- struct nf_conn_help *help = nfct_help(conntrack);
+ struct nf_conntrack_helper *helper;
- if (help)
- help->helper = __nf_ct_helper_find(&repl_tuple);
+ helper = __nf_ct_helper_find(&repl_tuple);
+ if (helper) {
+ help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC);
+ if (help)
+ rcu_assign_pointer(help->helper, helper);
+ }
NF_CT_STAT_INC(new);
}
/* Overload tuple linked list to put us in unconfirmed list. */
- list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
+ hlist_add_head(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].hnode,
+ &unconfirmed);
write_unlock_bh(&nf_conntrack_lock);
if (exp) {
if (exp->expectfn)
exp->expectfn(conntrack, exp);
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
}
return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
@@ -747,12 +592,12 @@ resolve_normal_ct(struct sk_buff *skb,
if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
dataoff, l3num, protonum, &tuple, l3proto,
l4proto)) {
- DEBUGP("resolve_normal_ct: Can't get tuple\n");
+ pr_debug("resolve_normal_ct: Can't get tuple\n");
return NULL;
}
/* look for tuple match */
- h = nf_conntrack_find_get(&tuple, NULL);
+ h = nf_conntrack_find_get(&tuple);
if (!h) {
h = init_conntrack(&tuple, l3proto, l4proto, skb, dataoff);
if (!h)
@@ -770,13 +615,14 @@ resolve_normal_ct(struct sk_buff *skb,
} else {
/* Once we've had two way comms, always ESTABLISHED. */
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
- DEBUGP("nf_conntrack_in: normal packet for %p\n", ct);
+ pr_debug("nf_conntrack_in: normal packet for %p\n", ct);
*ctinfo = IP_CT_ESTABLISHED;
} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
- DEBUGP("nf_conntrack_in: related packet for %p\n", ct);
+ pr_debug("nf_conntrack_in: related packet for %p\n",
+ ct);
*ctinfo = IP_CT_RELATED;
} else {
- DEBUGP("nf_conntrack_in: new packet for %p\n", ct);
+ pr_debug("nf_conntrack_in: new packet for %p\n", ct);
*ctinfo = IP_CT_NEW;
}
*set_reply = 0;
@@ -806,9 +652,12 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
/* rcu_read_lock()ed by nf_hook_slow */
l3proto = __nf_ct_l3proto_find((u_int16_t)pf);
-
- if ((ret = l3proto->prepare(pskb, hooknum, &dataoff, &protonum)) <= 0) {
- DEBUGP("not prepared to track yet or error occured\n");
+ ret = l3proto->get_l4proto(*pskb, skb_network_offset(*pskb),
+ &dataoff, &protonum);
+ if (ret <= 0) {
+ pr_debug("not prepared to track yet or error occured\n");
+ NF_CT_STAT_INC_ATOMIC(error);
+ NF_CT_STAT_INC_ATOMIC(invalid);
return -ret;
}
@@ -844,7 +693,7 @@ nf_conntrack_in(int pf, unsigned int hooknum, struct sk_buff **pskb)
if (ret < 0) {
/* Invalid: inverse of the return code tells
* the netfilter core what to do */
- DEBUGP("nf_conntrack_in: Can't track with proto module\n");
+ pr_debug("nf_conntrack_in: Can't track with proto module\n");
nf_conntrack_put((*pskb)->nfct);
(*pskb)->nfct = NULL;
NF_CT_STAT_INC_ATOMIC(invalid);
@@ -879,22 +728,36 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
const struct nf_conntrack_tuple *newreply)
{
struct nf_conn_help *help = nfct_help(ct);
+ struct nf_conntrack_helper *helper;
write_lock_bh(&nf_conntrack_lock);
/* Should be unconfirmed, so not in hash table yet */
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
- DEBUGP("Altering reply tuple of %p to ", ct);
+ pr_debug("Altering reply tuple of %p to ", ct);
NF_CT_DUMP_TUPLE(newreply);
ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
- if (!ct->master && help && help->expecting == 0) {
- struct nf_conntrack_helper *helper;
- helper = __nf_ct_helper_find(newreply);
- if (helper)
- memset(&help->help, 0, sizeof(help->help));
- help->helper = helper;
+ if (ct->master || (help && help->expecting != 0))
+ goto out;
+
+ helper = __nf_ct_helper_find(newreply);
+ if (helper == NULL) {
+ if (help)
+ rcu_assign_pointer(help->helper, NULL);
+ goto out;
+ }
+
+ if (help == NULL) {
+ help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
+ if (help == NULL)
+ goto out;
+ } else {
+ memset(&help->help, 0, sizeof(help->help));
}
+
+ rcu_assign_pointer(help->helper, helper);
+out:
write_unlock_bh(&nf_conntrack_lock);
}
EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
@@ -1038,16 +901,17 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
{
struct nf_conntrack_tuple_hash *h;
struct nf_conn *ct;
+ struct hlist_node *n;
write_lock_bh(&nf_conntrack_lock);
for (; *bucket < nf_conntrack_htable_size; (*bucket)++) {
- list_for_each_entry(h, &nf_conntrack_hash[*bucket], list) {
+ hlist_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnode) {
ct = nf_ct_tuplehash_to_ctrack(h);
if (iter(ct, data))
goto found;
}
}
- list_for_each_entry(h, &unconfirmed, list) {
+ hlist_for_each_entry(h, n, &unconfirmed, hnode) {
ct = nf_ct_tuplehash_to_ctrack(h);
if (iter(ct, data))
set_bit(IPS_DYING_BIT, &ct->status);
@@ -1082,14 +946,15 @@ static int kill_all(struct nf_conn *i, void *data)
return 1;
}
-static void free_conntrack_hash(struct list_head *hash, int vmalloced, int size)
+void nf_ct_free_hashtable(struct hlist_head *hash, int vmalloced, int size)
{
if (vmalloced)
vfree(hash);
else
free_pages((unsigned long)hash,
- get_order(sizeof(struct list_head) * size));
+ get_order(sizeof(struct hlist_head) * size));
}
+EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
void nf_conntrack_flush(void)
{
@@ -1101,8 +966,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_flush);
supposed to kill the mall. */
void nf_conntrack_cleanup(void)
{
- int i;
-
rcu_assign_pointer(ip_ct_attach, NULL);
/* This makes sure all current packets have passed through
@@ -1123,49 +986,46 @@ void nf_conntrack_cleanup(void)
rcu_assign_pointer(nf_ct_destroy, NULL);
- for (i = 0; i < NF_CT_F_NUM; i++) {
- if (nf_ct_cache[i].use == 0)
- continue;
-
- NF_CT_ASSERT(nf_ct_cache[i].use == 1);
- nf_ct_cache[i].use = 1;
- nf_conntrack_unregister_cache(i);
- }
- kmem_cache_destroy(nf_conntrack_expect_cachep);
- free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
- nf_conntrack_htable_size);
+ kmem_cache_destroy(nf_conntrack_cachep);
+ nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
+ nf_conntrack_htable_size);
nf_conntrack_proto_fini();
+ nf_conntrack_helper_fini();
+ nf_conntrack_expect_fini();
}
-static struct list_head *alloc_hashtable(int size, int *vmalloced)
+struct hlist_head *nf_ct_alloc_hashtable(int *sizep, int *vmalloced)
{
- struct list_head *hash;
- unsigned int i;
+ struct hlist_head *hash;
+ unsigned int size, i;
*vmalloced = 0;
+
+ size = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_head));
hash = (void*)__get_free_pages(GFP_KERNEL,
- get_order(sizeof(struct list_head)
+ get_order(sizeof(struct hlist_head)
* size));
if (!hash) {
*vmalloced = 1;
printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
- hash = vmalloc(sizeof(struct list_head) * size);
+ hash = vmalloc(sizeof(struct hlist_head) * size);
}
if (hash)
for (i = 0; i < size; i++)
- INIT_LIST_HEAD(&hash[i]);
+ INIT_HLIST_HEAD(&hash[i]);
return hash;
}
+EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable);
int set_hashsize(const char *val, struct kernel_param *kp)
{
int i, bucket, hashsize, vmalloced;
int old_vmalloced, old_size;
int rnd;
- struct list_head *hash, *old_hash;
+ struct hlist_head *hash, *old_hash;
struct nf_conntrack_tuple_hash *h;
/* On boot, we can set this without any fancy locking. */
@@ -1176,7 +1036,7 @@ int set_hashsize(const char *val, struct kernel_param *kp)
if (!hashsize)
return -EINVAL;
- hash = alloc_hashtable(hashsize, &vmalloced);
+ hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced);
if (!hash)
return -ENOMEM;
@@ -1186,12 +1046,12 @@ int set_hashsize(const char *val, struct kernel_param *kp)
write_lock_bh(&nf_conntrack_lock);
for (i = 0; i < nf_conntrack_htable_size; i++) {
- while (!list_empty(&nf_conntrack_hash[i])) {
- h = list_entry(nf_conntrack_hash[i].next,
- struct nf_conntrack_tuple_hash, list);
- list_del(&h->list);
+ while (!hlist_empty(&nf_conntrack_hash[i])) {
+ h = hlist_entry(nf_conntrack_hash[i].first,
+ struct nf_conntrack_tuple_hash, hnode);
+ hlist_del(&h->hnode);
bucket = __hash_conntrack(&h->tuple, hashsize, rnd);
- list_add_tail(&h->list, &hash[bucket]);
+ hlist_add_head(&h->hnode, &hash[bucket]);
}
}
old_size = nf_conntrack_htable_size;
@@ -1204,7 +1064,7 @@ int set_hashsize(const char *val, struct kernel_param *kp)
nf_conntrack_hash_rnd = rnd;
write_unlock_bh(&nf_conntrack_lock);
- free_conntrack_hash(old_hash, old_vmalloced, old_size);
+ nf_ct_free_hashtable(old_hash, old_vmalloced, old_size);
return 0;
}
@@ -1213,50 +1073,58 @@ module_param_call(hashsize, set_hashsize, param_get_uint,
int __init nf_conntrack_init(void)
{
+ int max_factor = 8;
int ret;
/* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB
- * machine has 256 buckets. >= 1GB machines have 8192 buckets. */
+ * machine has 512 buckets. >= 1GB machines have 16384 buckets. */
if (!nf_conntrack_htable_size) {
nf_conntrack_htable_size
= (((num_physpages << PAGE_SHIFT) / 16384)
- / sizeof(struct list_head));
+ / sizeof(struct hlist_head));
if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
- nf_conntrack_htable_size = 8192;
- if (nf_conntrack_htable_size < 16)
- nf_conntrack_htable_size = 16;
+ nf_conntrack_htable_size = 16384;
+ if (nf_conntrack_htable_size < 32)
+ nf_conntrack_htable_size = 32;
+
+ /* Use a max. factor of four by default to get the same max as
+ * with the old struct list_heads. When a table size is given
+ * we use the old value of 8 to avoid reducing the max.
+ * entries. */
+ max_factor = 4;
}
- nf_conntrack_max = 8 * nf_conntrack_htable_size;
-
- printk("nf_conntrack version %s (%u buckets, %d max)\n",
- NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
- nf_conntrack_max);
-
- nf_conntrack_hash = alloc_hashtable(nf_conntrack_htable_size,
- &nf_conntrack_vmalloc);
+ nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
+ &nf_conntrack_vmalloc);
if (!nf_conntrack_hash) {
printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
goto err_out;
}
- ret = nf_conntrack_register_cache(NF_CT_F_BASIC, "nf_conntrack:basic",
- sizeof(struct nf_conn));
- if (ret < 0) {
+ nf_conntrack_max = max_factor * nf_conntrack_htable_size;
+
+ printk("nf_conntrack version %s (%u buckets, %d max)\n",
+ NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
+ nf_conntrack_max);
+
+ nf_conntrack_cachep = kmem_cache_create("nf_conntrack",
+ sizeof(struct nf_conn),
+ 0, 0, NULL, NULL);
+ if (!nf_conntrack_cachep) {
printk(KERN_ERR "Unable to create nf_conn slab cache\n");
goto err_free_hash;
}
- nf_conntrack_expect_cachep = kmem_cache_create("nf_conntrack_expect",
- sizeof(struct nf_conntrack_expect),
- 0, 0, NULL, NULL);
- if (!nf_conntrack_expect_cachep) {
- printk(KERN_ERR "Unable to create nf_expect slab cache\n");
+ ret = nf_conntrack_proto_init();
+ if (ret < 0)
goto err_free_conntrack_slab;
- }
- ret = nf_conntrack_proto_init();
+ ret = nf_conntrack_expect_init();
+ if (ret < 0)
+ goto out_fini_proto;
+
+ ret = nf_conntrack_helper_init();
if (ret < 0)
- goto out_free_expect_slab;
+ goto out_fini_expect;
/* For use by REJECT target */
rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach);
@@ -1270,13 +1138,15 @@ int __init nf_conntrack_init(void)
return ret;
-out_free_expect_slab:
- kmem_cache_destroy(nf_conntrack_expect_cachep);
+out_fini_expect:
+ nf_conntrack_expect_fini();
+out_fini_proto:
+ nf_conntrack_proto_fini();
err_free_conntrack_slab:
- nf_conntrack_unregister_cache(NF_CT_F_BASIC);
+ kmem_cache_destroy(nf_conntrack_cachep);
err_free_hash:
- free_conntrack_hash(nf_conntrack_hash, nf_conntrack_vmalloc,
- nf_conntrack_htable_size);
+ nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_vmalloc,
+ nf_conntrack_htable_size);
err_out:
return -ENOMEM;
}
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 6bd421df2db..83c41ac3505 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -26,8 +26,8 @@
ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
EXPORT_SYMBOL_GPL(nf_conntrack_chain);
-ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain);
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_chain);
+ATOMIC_NOTIFIER_HEAD(nf_ct_expect_chain);
+EXPORT_SYMBOL_GPL(nf_ct_expect_chain);
DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache);
EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
@@ -103,14 +103,14 @@ int nf_conntrack_unregister_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
-int nf_conntrack_expect_register_notifier(struct notifier_block *nb)
+int nf_ct_expect_register_notifier(struct notifier_block *nb)
{
- return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_register(&nf_ct_expect_chain, nb);
}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_register_notifier);
+EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier);
-int nf_conntrack_expect_unregister_notifier(struct notifier_block *nb)
+int nf_ct_expect_unregister_notifier(struct notifier_block *nb)
{
- return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, nb);
+ return atomic_notifier_chain_unregister(&nf_ct_expect_chain, nb);
}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_unregister_notifier);
+EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 117cbfdb910..2191fe008f6 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -19,6 +19,7 @@
#include <linux/err.h>
#include <linux/percpu.h>
#include <linux/kernel.h>
+#include <linux/jhash.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
@@ -26,11 +27,20 @@
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_tuple.h>
-LIST_HEAD(nf_conntrack_expect_list);
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_list);
+struct hlist_head *nf_ct_expect_hash __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
-struct kmem_cache *nf_conntrack_expect_cachep __read_mostly;
-static unsigned int nf_conntrack_expect_next_id;
+unsigned int nf_ct_expect_hsize __read_mostly;
+EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
+
+static unsigned int nf_ct_expect_hash_rnd __read_mostly;
+static unsigned int nf_ct_expect_count;
+unsigned int nf_ct_expect_max __read_mostly;
+static int nf_ct_expect_hash_rnd_initted __read_mostly;
+static int nf_ct_expect_vmalloc;
+
+static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
+static unsigned int nf_ct_expect_next_id;
/* nf_conntrack_expect helper functions */
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
@@ -40,60 +50,83 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
NF_CT_ASSERT(master_help);
NF_CT_ASSERT(!timer_pending(&exp->timeout));
- list_del(&exp->list);
- NF_CT_STAT_INC(expect_delete);
+ hlist_del(&exp->hnode);
+ nf_ct_expect_count--;
+
+ hlist_del(&exp->lnode);
master_help->expecting--;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
+
+ NF_CT_STAT_INC(expect_delete);
}
EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);
-static void expectation_timed_out(unsigned long ul_expect)
+static void nf_ct_expectation_timed_out(unsigned long ul_expect)
{
struct nf_conntrack_expect *exp = (void *)ul_expect;
write_lock_bh(&nf_conntrack_lock);
nf_ct_unlink_expect(exp);
write_unlock_bh(&nf_conntrack_lock);
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
+}
+
+static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple)
+{
+ if (unlikely(!nf_ct_expect_hash_rnd_initted)) {
+ get_random_bytes(&nf_ct_expect_hash_rnd, 4);
+ nf_ct_expect_hash_rnd_initted = 1;
+ }
+
+ return jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all),
+ (((tuple->dst.protonum ^ tuple->src.l3num) << 16) |
+ tuple->dst.u.all) ^ nf_ct_expect_hash_rnd) %
+ nf_ct_expect_hsize;
}
struct nf_conntrack_expect *
-__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple)
+__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *i;
+ struct hlist_node *n;
+ unsigned int h;
+
+ if (!nf_ct_expect_count)
+ return NULL;
- list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+ h = nf_ct_expect_dst_hash(tuple);
+ hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
return i;
}
return NULL;
}
-EXPORT_SYMBOL_GPL(__nf_conntrack_expect_find);
+EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
/* Just find a expectation corresponding to a tuple. */
struct nf_conntrack_expect *
-nf_conntrack_expect_find_get(const struct nf_conntrack_tuple *tuple)
+nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *i;
read_lock_bh(&nf_conntrack_lock);
- i = __nf_conntrack_expect_find(tuple);
+ i = __nf_ct_expect_find(tuple);
if (i)
atomic_inc(&i->use);
read_unlock_bh(&nf_conntrack_lock);
return i;
}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_find_get);
+EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
/* If an expectation for this connection is found, it gets delete from
* global list then returned. */
struct nf_conntrack_expect *
-find_expectation(const struct nf_conntrack_tuple *tuple)
+nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_expect *exp;
- exp = __nf_conntrack_expect_find(tuple);
+ exp = __nf_ct_expect_find(tuple);
if (!exp)
return NULL;
@@ -119,17 +152,18 @@ find_expectation(const struct nf_conntrack_tuple *tuple)
/* delete all expectations for this conntrack */
void nf_ct_remove_expectations(struct nf_conn *ct)
{
- struct nf_conntrack_expect *i, *tmp;
struct nf_conn_help *help = nfct_help(ct);
+ struct nf_conntrack_expect *exp;
+ struct hlist_node *n, *next;
/* Optimization: most connection never expect any others. */
if (!help || help->expecting == 0)
return;
- list_for_each_entry_safe(i, tmp, &nf_conntrack_expect_list, list) {
- if (i->master == ct && del_timer(&i->timeout)) {
- nf_ct_unlink_expect(i);
- nf_conntrack_expect_put(i);
+ hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
+ if (del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_ct_expect_put(exp);
}
}
}
@@ -141,25 +175,16 @@ static inline int expect_clash(const struct nf_conntrack_expect *a,
{
/* Part covered by intersection of masks must be unequal,
otherwise they clash */
- struct nf_conntrack_tuple intersect_mask;
+ struct nf_conntrack_tuple_mask intersect_mask;
int count;
- intersect_mask.src.l3num = a->mask.src.l3num & b->mask.src.l3num;
intersect_mask.src.u.all = a->mask.src.u.all & b->mask.src.u.all;
- intersect_mask.dst.u.all = a->mask.dst.u.all & b->mask.dst.u.all;
- intersect_mask.dst.protonum = a->mask.dst.protonum
- & b->mask.dst.protonum;
for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
intersect_mask.src.u3.all[count] =
a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
}
- for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
- intersect_mask.dst.u3.all[count] =
- a->mask.dst.u3.all[count] & b->mask.dst.u3.all[count];
- }
-
return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
}
@@ -168,36 +193,29 @@ static inline int expect_matches(const struct nf_conntrack_expect *a,
{
return a->master == b->master
&& nf_ct_tuple_equal(&a->tuple, &b->tuple)
- && nf_ct_tuple_equal(&a->mask, &b->mask);
+ && nf_ct_tuple_mask_equal(&a->mask, &b->mask);
}
/* Generally a bad idea to call this: could have matched already. */
-void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp)
+void nf_ct_unexpect_related(struct nf_conntrack_expect *exp)
{
- struct nf_conntrack_expect *i;
-
write_lock_bh(&nf_conntrack_lock);
- /* choose the oldest expectation to evict */
- list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
- if (expect_matches(i, exp) && del_timer(&i->timeout)) {
- nf_ct_unlink_expect(i);
- write_unlock_bh(&nf_conntrack_lock);
- nf_conntrack_expect_put(i);
- return;
- }
+ if (del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_ct_expect_put(exp);
}
write_unlock_bh(&nf_conntrack_lock);
}
-EXPORT_SYMBOL_GPL(nf_conntrack_unexpect_related);
+EXPORT_SYMBOL_GPL(nf_ct_unexpect_related);
/* We don't increase the master conntrack refcount for non-fulfilled
* conntracks. During the conntrack destruction, the expectations are
* always killed before the conntrack itself */
-struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me)
+struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
{
struct nf_conntrack_expect *new;
- new = kmem_cache_alloc(nf_conntrack_expect_cachep, GFP_ATOMIC);
+ new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC);
if (!new)
return NULL;
@@ -205,12 +223,12 @@ struct nf_conntrack_expect *nf_conntrack_expect_alloc(struct nf_conn *me)
atomic_set(&new->use, 1);
return new;
}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_alloc);
+EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
-void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family,
- union nf_conntrack_address *saddr,
- union nf_conntrack_address *daddr,
- u_int8_t proto, __be16 *src, __be16 *dst)
+void nf_ct_expect_init(struct nf_conntrack_expect *exp, int family,
+ union nf_conntrack_address *saddr,
+ union nf_conntrack_address *daddr,
+ u_int8_t proto, __be16 *src, __be16 *dst)
{
int len;
@@ -224,8 +242,6 @@ void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family,
exp->helper = NULL;
exp->tuple.src.l3num = family;
exp->tuple.dst.protonum = proto;
- exp->mask.src.l3num = 0xFFFF;
- exp->mask.dst.protonum = 0xFF;
if (saddr) {
memcpy(&exp->tuple.src.u3, saddr, len);
@@ -242,21 +258,6 @@ void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family,
memset(&exp->mask.src.u3, 0x00, sizeof(exp->mask.src.u3));
}
- if (daddr) {
- memcpy(&exp->tuple.dst.u3, daddr, len);
- if (sizeof(exp->tuple.dst.u3) > len)
- /* address needs to be cleared for nf_ct_tuple_equal */
- memset((void *)&exp->tuple.dst.u3 + len, 0x00,
- sizeof(exp->tuple.dst.u3) - len);
- memset(&exp->mask.dst.u3, 0xFF, len);
- if (sizeof(exp->mask.dst.u3) > len)
- memset((void *)&exp->mask.dst.u3 + len, 0x00,
- sizeof(exp->mask.dst.u3) - len);
- } else {
- memset(&exp->tuple.dst.u3, 0x00, sizeof(exp->tuple.dst.u3));
- memset(&exp->mask.dst.u3, 0x00, sizeof(exp->mask.dst.u3));
- }
-
if (src) {
exp->tuple.src.u.all = (__force u16)*src;
exp->mask.src.u.all = 0xFFFF;
@@ -265,36 +266,42 @@ void nf_conntrack_expect_init(struct nf_conntrack_expect *exp, int family,
exp->mask.src.u.all = 0;
}
- if (dst) {
- exp->tuple.dst.u.all = (__force u16)*dst;
- exp->mask.dst.u.all = 0xFFFF;
- } else {
- exp->tuple.dst.u.all = 0;
- exp->mask.dst.u.all = 0;
- }
+ memcpy(&exp->tuple.dst.u3, daddr, len);
+ if (sizeof(exp->tuple.dst.u3) > len)
+ /* address needs to be cleared for nf_ct_tuple_equal */
+ memset((void *)&exp->tuple.dst.u3 + len, 0x00,
+ sizeof(exp->tuple.dst.u3) - len);
+
+ exp->tuple.dst.u.all = (__force u16)*dst;
}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_init);
+EXPORT_SYMBOL_GPL(nf_ct_expect_init);
-void nf_conntrack_expect_put(struct nf_conntrack_expect *exp)
+void nf_ct_expect_put(struct nf_conntrack_expect *exp)
{
if (atomic_dec_and_test(&exp->use))
- kmem_cache_free(nf_conntrack_expect_cachep, exp);
+ kmem_cache_free(nf_ct_expect_cachep, exp);
}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_put);
+EXPORT_SYMBOL_GPL(nf_ct_expect_put);
-static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
+static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
{
struct nf_conn_help *master_help = nfct_help(exp->master);
+ unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
atomic_inc(&exp->use);
+
+ hlist_add_head(&exp->lnode, &master_help->expectations);
master_help->expecting++;
- list_add(&exp->list, &nf_conntrack_expect_list);
- setup_timer(&exp->timeout, expectation_timed_out, (unsigned long)exp);
+ hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]);
+ nf_ct_expect_count++;
+
+ setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
+ (unsigned long)exp);
exp->timeout.expires = jiffies + master_help->helper->timeout * HZ;
add_timer(&exp->timeout);
- exp->id = ++nf_conntrack_expect_next_id;
+ exp->id = ++nf_ct_expect_next_id;
atomic_inc(&exp->use);
NF_CT_STAT_INC(expect_create);
}
@@ -302,16 +309,16 @@ static void nf_conntrack_expect_insert(struct nf_conntrack_expect *exp)
/* Race with expectations being used means we could have none to find; OK. */
static void evict_oldest_expect(struct nf_conn *master)
{
- struct nf_conntrack_expect *i;
+ struct nf_conn_help *master_help = nfct_help(master);
+ struct nf_conntrack_expect *exp = NULL;
+ struct hlist_node *n;
- list_for_each_entry_reverse(i, &nf_conntrack_expect_list, list) {
- if (i->master == master) {
- if (del_timer(&i->timeout)) {
- nf_ct_unlink_expect(i);
- nf_conntrack_expect_put(i);
- }
- break;
- }
+ hlist_for_each_entry(exp, n, &master_help->expectations, lnode)
+ ; /* nothing */
+
+ if (exp && del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_ct_expect_put(exp);
}
}
@@ -327,17 +334,24 @@ static inline int refresh_timer(struct nf_conntrack_expect *i)
return 1;
}
-int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
+int nf_ct_expect_related(struct nf_conntrack_expect *expect)
{
struct nf_conntrack_expect *i;
struct nf_conn *master = expect->master;
struct nf_conn_help *master_help = nfct_help(master);
+ struct hlist_node *n;
+ unsigned int h;
int ret;
NF_CT_ASSERT(master_help);
write_lock_bh(&nf_conntrack_lock);
- list_for_each_entry(i, &nf_conntrack_expect_list, list) {
+ if (!master_help->helper) {
+ ret = -ESHUTDOWN;
+ goto out;
+ }
+ h = nf_ct_expect_dst_hash(&expect->tuple);
+ hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
if (expect_matches(i, expect)) {
/* Refresh timer: if it's dying, ignore.. */
if (refresh_timer(i)) {
@@ -354,57 +368,86 @@ int nf_conntrack_expect_related(struct nf_conntrack_expect *expect)
master_help->expecting >= master_help->helper->max_expected)
evict_oldest_expect(master);
- nf_conntrack_expect_insert(expect);
- nf_conntrack_expect_event(IPEXP_NEW, expect);
+ if (nf_ct_expect_count >= nf_ct_expect_max) {
+ if (net_ratelimit())
+ printk(KERN_WARNING
+ "nf_conntrack: expectation table full");
+ ret = -EMFILE;
+ goto out;
+ }
+
+ nf_ct_expect_insert(expect);
+ nf_ct_expect_event(IPEXP_NEW, expect);
ret = 0;
out:
write_unlock_bh(&nf_conntrack_lock);
return ret;
}
-EXPORT_SYMBOL_GPL(nf_conntrack_expect_related);
+EXPORT_SYMBOL_GPL(nf_ct_expect_related);
#ifdef CONFIG_PROC_FS
-static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_expect_iter_state {
+ unsigned int bucket;
+};
+
+static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
{
- struct list_head *e = &nf_conntrack_expect_list;
- loff_t i;
+ struct ct_expect_iter_state *st = seq->private;
- /* strange seq_file api calls stop even if we fail,
- * thus we need to grab lock since stop unlocks */
- read_lock_bh(&nf_conntrack_lock);
+ for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
+ if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
+ return nf_ct_expect_hash[st->bucket].first;
+ }
+ return NULL;
+}
- if (list_empty(e))
- return NULL;
+static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
+ struct hlist_node *head)
+{
+ struct ct_expect_iter_state *st = seq->private;
- for (i = 0; i <= *pos; i++) {
- e = e->next;
- if (e == &nf_conntrack_expect_list)
+ head = head->next;
+ while (head == NULL) {
+ if (++st->bucket >= nf_ct_expect_hsize)
return NULL;
+ head = nf_ct_expect_hash[st->bucket].first;
}
- return e;
+ return head;
}
-static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
{
- struct list_head *e = v;
+ struct hlist_node *head = ct_expect_get_first(seq);
- ++*pos;
- e = e->next;
+ if (head)
+ while (pos && (head = ct_expect_get_next(seq, head)))
+ pos--;
+ return pos ? NULL : head;
+}
- if (e == &nf_conntrack_expect_list)
- return NULL;
+static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ read_lock_bh(&nf_conntrack_lock);
+ return ct_expect_get_idx(seq, *pos);
+}
- return e;
+static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ (*pos)++;
+ return ct_expect_get_next(seq, v);
}
-static void exp_seq_stop(struct seq_file *s, void *v)
+static void exp_seq_stop(struct seq_file *seq, void *v)
{
read_unlock_bh(&nf_conntrack_lock);
}
static int exp_seq_show(struct seq_file *s, void *v)
{
- struct nf_conntrack_expect *expect = v;
+ struct nf_conntrack_expect *expect;
+ struct hlist_node *n = v;
+
+ expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
if (expect->timeout.function)
seq_printf(s, "%ld ", timer_pending(&expect->timeout)
@@ -421,7 +464,7 @@ static int exp_seq_show(struct seq_file *s, void *v)
return seq_putc(s, '\n');
}
-static struct seq_operations exp_seq_ops = {
+static const struct seq_operations exp_seq_ops = {
.start = exp_seq_start,
.next = exp_seq_next,
.stop = exp_seq_stop,
@@ -430,14 +473,96 @@ static struct seq_operations exp_seq_ops = {
static int exp_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &exp_seq_ops);
+ struct seq_file *seq;
+ struct ct_expect_iter_state *st;
+ int ret;
+
+ st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
+ if (st == NULL)
+ return -ENOMEM;
+ ret = seq_open(file, &exp_seq_ops);
+ if (ret)
+ goto out_free;
+ seq = file->private_data;
+ seq->private = st;
+ memset(st, 0, sizeof(struct ct_expect_iter_state));
+ return ret;
+out_free:
+ kfree(st);
+ return ret;
}
-const struct file_operations exp_file_ops = {
+static const struct file_operations exp_file_ops = {
.owner = THIS_MODULE,
.open = exp_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release
+ .release = seq_release_private,
};
#endif /* CONFIG_PROC_FS */
+
+static int __init exp_proc_init(void)
+{
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc;
+
+ proc = proc_net_fops_create("nf_conntrack_expect", 0440, &exp_file_ops);
+ if (!proc)
+ return -ENOMEM;
+#endif /* CONFIG_PROC_FS */
+ return 0;
+}
+
+static void exp_proc_remove(void)
+{
+#ifdef CONFIG_PROC_FS
+ proc_net_remove("nf_conntrack_expect");
+#endif /* CONFIG_PROC_FS */
+}
+
+module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
+
+int __init nf_conntrack_expect_init(void)
+{
+ int err = -ENOMEM;
+
+ if (!nf_ct_expect_hsize) {
+ nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
+ if (!nf_ct_expect_hsize)
+ nf_ct_expect_hsize = 1;
+ }
+ nf_ct_expect_max = nf_ct_expect_hsize * 4;
+
+ nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
+ &nf_ct_expect_vmalloc);
+ if (nf_ct_expect_hash == NULL)
+ goto err1;
+
+ nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
+ sizeof(struct nf_conntrack_expect),
+ 0, 0, NULL, NULL);
+ if (!nf_ct_expect_cachep)
+ goto err2;
+
+ err = exp_proc_init();
+ if (err < 0)
+ goto err3;
+
+ return 0;
+
+err3:
+ nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
+ nf_ct_expect_hsize);
+err2:
+ kmem_cache_destroy(nf_ct_expect_cachep);
+err1:
+ return err;
+}
+
+void nf_conntrack_expect_fini(void)
+{
+ exp_proc_remove();
+ kmem_cache_destroy(nf_ct_expect_cachep);
+ nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
+ nf_ct_expect_hsize);
+}
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
new file mode 100644
index 00000000000..a1a65a1313b
--- /dev/null
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -0,0 +1,195 @@
+/* Structure dynamic extension infrastructure
+ * Copyright (C) 2004 Rusty Russell IBM Corporation
+ * Copyright (C) 2007 Netfilter Core Team <coreteam@netfilter.org>
+ * Copyright (C) 2007 USAGI/WIDE Project <http://www.linux-ipv6.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.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/rcupdate.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM];
+static DEFINE_MUTEX(nf_ct_ext_type_mutex);
+
+/* Horrible trick to figure out smallest amount worth kmallocing. */
+#define CACHE(x) (x) + 0 *
+enum {
+ NF_CT_EXT_MIN_SIZE =
+#include <linux/kmalloc_sizes.h>
+ 1 };
+#undef CACHE
+
+void __nf_ct_ext_destroy(struct nf_conn *ct)
+{
+ unsigned int i;
+ struct nf_ct_ext_type *t;
+
+ for (i = 0; i < NF_CT_EXT_NUM; i++) {
+ if (!nf_ct_ext_exist(ct, i))
+ continue;
+
+ rcu_read_lock();
+ t = rcu_dereference(nf_ct_ext_types[i]);
+
+ /* Here the nf_ct_ext_type might have been unregisterd.
+ * I.e., it has responsible to cleanup private
+ * area in all conntracks when it is unregisterd.
+ */
+ if (t && t->destroy)
+ t->destroy(ct);
+ rcu_read_unlock();
+ }
+}
+EXPORT_SYMBOL(__nf_ct_ext_destroy);
+
+static void *
+nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
+{
+ unsigned int off, len, real_len;
+ struct nf_ct_ext_type *t;
+
+ rcu_read_lock();
+ t = rcu_dereference(nf_ct_ext_types[id]);
+ BUG_ON(t == NULL);
+ off = ALIGN(sizeof(struct nf_ct_ext), t->align);
+ len = off + t->len;
+ real_len = t->alloc_size;
+ rcu_read_unlock();
+
+ *ext = kzalloc(real_len, gfp);
+ if (!*ext)
+ return NULL;
+
+ (*ext)->offset[id] = off;
+ (*ext)->len = len;
+ (*ext)->real_len = real_len;
+
+ return (void *)(*ext) + off;
+}
+
+void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
+{
+ struct nf_ct_ext *new;
+ int i, newlen, newoff;
+ struct nf_ct_ext_type *t;
+
+ if (!ct->ext)
+ return nf_ct_ext_create(&ct->ext, id, gfp);
+
+ if (nf_ct_ext_exist(ct, id))
+ return NULL;
+
+ rcu_read_lock();
+ t = rcu_dereference(nf_ct_ext_types[id]);
+ BUG_ON(t == NULL);
+
+ newoff = ALIGN(ct->ext->len, t->align);
+ newlen = newoff + t->len;
+ rcu_read_unlock();
+
+ if (newlen >= ct->ext->real_len) {
+ new = kmalloc(newlen, gfp);
+ if (!new)
+ return NULL;
+
+ memcpy(new, ct->ext, ct->ext->len);
+
+ for (i = 0; i < NF_CT_EXT_NUM; i++) {
+ if (!nf_ct_ext_exist(ct, i))
+ continue;
+
+ rcu_read_lock();
+ t = rcu_dereference(nf_ct_ext_types[i]);
+ if (t && t->move)
+ t->move(ct, ct->ext + ct->ext->offset[id]);
+ rcu_read_unlock();
+ }
+ kfree(ct->ext);
+ new->real_len = newlen;
+ ct->ext = new;
+ }
+
+ ct->ext->offset[id] = newoff;
+ ct->ext->len = newlen;
+ memset((void *)ct->ext + newoff, 0, newlen - newoff);
+ return (void *)ct->ext + newoff;
+}
+EXPORT_SYMBOL(__nf_ct_ext_add);
+
+static void update_alloc_size(struct nf_ct_ext_type *type)
+{
+ int i, j;
+ struct nf_ct_ext_type *t1, *t2;
+ enum nf_ct_ext_id min = 0, max = NF_CT_EXT_NUM - 1;
+
+ /* unnecessary to update all types */
+ if ((type->flags & NF_CT_EXT_F_PREALLOC) == 0) {
+ min = type->id;
+ max = type->id;
+ }
+
+ /* This assumes that extended areas in conntrack for the types
+ whose NF_CT_EXT_F_PREALLOC bit set are allocated in order */
+ for (i = min; i <= max; i++) {
+ t1 = nf_ct_ext_types[i];
+ if (!t1)
+ continue;
+
+ t1->alloc_size = sizeof(struct nf_ct_ext)
+ + ALIGN(sizeof(struct nf_ct_ext), t1->align)
+ + t1->len;
+ for (j = 0; j < NF_CT_EXT_NUM; j++) {
+ t2 = nf_ct_ext_types[j];
+ if (t2 == NULL || t2 == t1 ||
+ (t2->flags & NF_CT_EXT_F_PREALLOC) == 0)
+ continue;
+
+ t1->alloc_size = ALIGN(t1->alloc_size, t2->align)
+ + t2->len;
+ }
+ if (t1->alloc_size < NF_CT_EXT_MIN_SIZE)
+ t1->alloc_size = NF_CT_EXT_MIN_SIZE;
+ }
+}
+
+/* This MUST be called in process context. */
+int nf_ct_extend_register(struct nf_ct_ext_type *type)
+{
+ int ret = 0;
+
+ mutex_lock(&nf_ct_ext_type_mutex);
+ if (nf_ct_ext_types[type->id]) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* This ensures that nf_ct_ext_create() can allocate enough area
+ before updating alloc_size */
+ type->alloc_size = ALIGN(sizeof(struct nf_ct_ext), type->align)
+ + type->len;
+ rcu_assign_pointer(nf_ct_ext_types[type->id], type);
+ update_alloc_size(type);
+out:
+ mutex_unlock(&nf_ct_ext_type_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(nf_ct_extend_register);
+
+/* This MUST be called in process context. */
+void nf_ct_extend_unregister(struct nf_ct_ext_type *type)
+{
+ mutex_lock(&nf_ct_ext_type_mutex);
+ rcu_assign_pointer(nf_ct_ext_types[type->id], NULL);
+ update_alloc_size(type);
+ mutex_unlock(&nf_ct_ext_type_mutex);
+ synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 82db2aa53bf..c763ee74ea0 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -51,12 +51,6 @@ unsigned int (*nf_nat_ftp_hook)(struct sk_buff **pskb,
struct nf_conntrack_expect *exp);
EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char);
static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char);
static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
@@ -138,13 +132,13 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[],
if (*data == term && i == array_size - 1)
return len;
- DEBUGP("Char %u (got %u nums) `%u' unexpected\n",
- len, i, *data);
+ pr_debug("Char %u (got %u nums) `%u' unexpected\n",
+ len, i, *data);
return 0;
}
}
- DEBUGP("Failed to fill %u numbers separated by %c\n", array_size, sep);
-
+ pr_debug("Failed to fill %u numbers separated by %c\n",
+ array_size, sep);
return 0;
}
@@ -178,13 +172,13 @@ static int get_port(const char *data, int start, size_t dlen, char delim,
if (tmp_port == 0)
break;
*port = htons(tmp_port);
- DEBUGP("get_port: return %d\n", tmp_port);
+ pr_debug("get_port: return %d\n", tmp_port);
return i + 1;
}
else if (data[i] >= '0' && data[i] <= '9')
tmp_port = tmp_port*10 + data[i] - '0';
else { /* Some other crap */
- DEBUGP("get_port: invalid char.\n");
+ pr_debug("get_port: invalid char.\n");
break;
}
}
@@ -201,22 +195,22 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
/* First character is delimiter, then "1" for IPv4 or "2" for IPv6,
then delimiter again. */
if (dlen <= 3) {
- DEBUGP("EPRT: too short\n");
+ pr_debug("EPRT: too short\n");
return 0;
}
delim = data[0];
if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) {
- DEBUGP("try_eprt: invalid delimitter.\n");
+ pr_debug("try_eprt: invalid delimitter.\n");
return 0;
}
if ((cmd->l3num == PF_INET && data[1] != '1') ||
(cmd->l3num == PF_INET6 && data[1] != '2')) {
- DEBUGP("EPRT: invalid protocol number.\n");
+ pr_debug("EPRT: invalid protocol number.\n");
return 0;
}
- DEBUGP("EPRT: Got %c%c%c\n", delim, data[1], delim);
+ pr_debug("EPRT: Got %c%c%c\n", delim, data[1], delim);
if (data[1] == '1') {
u_int32_t array[4];
@@ -234,7 +228,7 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
if (length == 0)
return 0;
- DEBUGP("EPRT: Got IP address!\n");
+ pr_debug("EPRT: Got IP address!\n");
/* Start offset includes initial "|1|", and trailing delimiter */
return get_port(data, 3 + length + 1, dlen, delim, &cmd->u.tcp.port);
}
@@ -267,7 +261,7 @@ static int find_pattern(const char *data, size_t dlen,
{
size_t i;
- DEBUGP("find_pattern `%s': dlen = %u\n", pattern, dlen);
+ pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen);
if (dlen == 0)
return 0;
@@ -282,17 +276,17 @@ static int find_pattern(const char *data, size_t dlen,
#if 0
size_t i;
- DEBUGP("ftp: string mismatch\n");
+ pr_debug("ftp: string mismatch\n");
for (i = 0; i < plen; i++) {
- DEBUGP("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
- i, data[i], data[i],
- pattern[i], pattern[i]);
+ pr_debug("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
+ i, data[i], data[i],
+ pattern[i], pattern[i]);
}
#endif
return 0;
}
- DEBUGP("Pattern matches!\n");
+ pr_debug("Pattern matches!\n");
/* Now we've found the constant string, try to skip
to the 'skip' character */
for (i = plen; data[i] != skip; i++)
@@ -301,14 +295,14 @@ static int find_pattern(const char *data, size_t dlen,
/* Skip over the last character */
i++;
- DEBUGP("Skipped up to `%c'!\n", skip);
+ pr_debug("Skipped up to `%c'!\n", skip);
*numoff = i;
*numlen = getnum(data + i, dlen - i, cmd, term);
if (!*numlen)
return -1;
- DEBUGP("Match succeeded!\n");
+ pr_debug("Match succeeded!\n");
return 1;
}
@@ -364,6 +358,7 @@ static int help(struct sk_buff **pskb,
unsigned int matchlen, matchoff;
struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
struct nf_conntrack_expect *exp;
+ union nf_conntrack_address *daddr;
struct nf_conntrack_man cmd = {};
unsigned int i;
int found = 0, ends_in_nl;
@@ -372,7 +367,7 @@ static int help(struct sk_buff **pskb,
/* Until there's been traffic both ways, don't look in packets. */
if (ctinfo != IP_CT_ESTABLISHED
&& ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
- DEBUGP("ftp: Conntrackinfo = %u\n", ctinfo);
+ pr_debug("ftp: Conntrackinfo = %u\n", ctinfo);
return NF_ACCEPT;
}
@@ -383,8 +378,8 @@ static int help(struct sk_buff **pskb,
dataoff = protoff + th->doff * 4;
/* No data? */
if (dataoff >= (*pskb)->len) {
- DEBUGP("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
- (*pskb)->len);
+ pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
+ (*pskb)->len);
return NF_ACCEPT;
}
datalen = (*pskb)->len - dataoff;
@@ -399,11 +394,11 @@ static int help(struct sk_buff **pskb,
/* Look up to see if we're just after a \n. */
if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
/* Now if this ends in \n, update ftp info. */
- DEBUGP("nf_conntrack_ftp_help: wrong seq pos %s(%u) or %s(%u)\n",
- ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
- ct_ftp_info->seq_aft_nl[dir][0],
- ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
- ct_ftp_info->seq_aft_nl[dir][1]);
+ pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n",
+ ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
+ ct_ftp_info->seq_aft_nl[dir][0],
+ ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
+ ct_ftp_info->seq_aft_nl[dir][1]);
ret = NF_ACCEPT;
goto out_update_nl;
}
@@ -441,11 +436,11 @@ static int help(struct sk_buff **pskb,
goto out_update_nl;
}
- DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
- (int)matchlen, fb_ptr + matchoff,
- matchlen, ntohl(th->seq) + matchoff);
+ pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
+ matchlen, fb_ptr + matchoff,
+ matchlen, ntohl(th->seq) + matchoff);
- exp = nf_conntrack_expect_alloc(ct);
+ exp = nf_ct_expect_alloc(ct);
if (exp == NULL) {
ret = NF_DROP;
goto out;
@@ -454,7 +449,7 @@ static int help(struct sk_buff **pskb,
/* We refer to the reverse direction ("!dir") tuples here,
* because we're expecting something in the other direction.
* Doesn't matter unless NAT is happening. */
- exp->tuple.dst.u3 = ct->tuplehash[!dir].tuple.dst.u3;
+ daddr = &ct->tuplehash[!dir].tuple.dst.u3;
/* Update the ftp info */
if ((cmd.l3num == ct->tuplehash[dir].tuple.src.l3num) &&
@@ -465,14 +460,16 @@ static int help(struct sk_buff **pskb,
different IP address. Simply don't record it for
NAT. */
if (cmd.l3num == PF_INET) {
- DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n",
- NIPQUAD(cmd.u3.ip),
- NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
+ pr_debug("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT
+ " != " NIPQUAD_FMT "\n",
+ NIPQUAD(cmd.u3.ip),
+ NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip));
} else {
- DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n",
- NIP6(*((struct in6_addr *)cmd.u3.ip6)),
- NIP6(*((struct in6_addr *)ct->tuplehash[dir]
- .tuple.src.u3.ip6)));
+ pr_debug("conntrack_ftp: NOT RECORDING: " NIP6_FMT
+ " != " NIP6_FMT "\n",
+ NIP6(*((struct in6_addr *)cmd.u3.ip6)),
+ NIP6(*((struct in6_addr *)
+ ct->tuplehash[dir].tuple.src.u3.ip6)));
}
/* Thanks to Cristiano Lincoln Mattos
@@ -483,37 +480,12 @@ static int help(struct sk_buff **pskb,
ret = NF_ACCEPT;
goto out_put_expect;
}
- memcpy(&exp->tuple.dst.u3, &cmd.u3.all,
- sizeof(exp->tuple.dst.u3));
- }
-
- exp->tuple.src.u3 = ct->tuplehash[!dir].tuple.src.u3;
- exp->tuple.src.l3num = cmd.l3num;
- exp->tuple.src.u.tcp.port = 0;
- exp->tuple.dst.u.tcp.port = cmd.u.tcp.port;
- exp->tuple.dst.protonum = IPPROTO_TCP;
-
- exp->mask = (struct nf_conntrack_tuple)
- { .src = { .l3num = 0xFFFF,
- .u = { .tcp = { 0 }},
- },
- .dst = { .protonum = 0xFF,
- .u = { .tcp = { __constant_htons(0xFFFF) }},
- },
- };
- if (cmd.l3num == PF_INET) {
- exp->mask.src.u3.ip = htonl(0xFFFFFFFF);
- exp->mask.dst.u3.ip = htonl(0xFFFFFFFF);
- } else {
- memset(exp->mask.src.u3.ip6, 0xFF,
- sizeof(exp->mask.src.u3.ip6));
- memset(exp->mask.dst.u3.ip6, 0xFF,
- sizeof(exp->mask.src.u3.ip6));
+ daddr = &cmd.u3;
}
- exp->expectfn = NULL;
- exp->helper = NULL;
- exp->flags = 0;
+ nf_ct_expect_init(exp, cmd.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, daddr,
+ IPPROTO_TCP, NULL, &cmd.u.tcp.port);
/* Now, NAT might want to mangle the packet, and register the
* (possibly changed) expectation itself. */
@@ -523,14 +495,14 @@ static int help(struct sk_buff **pskb,
matchoff, matchlen, exp);
else {
/* Can't expect this? Best to drop packet now. */
- if (nf_conntrack_expect_related(exp) != 0)
+ if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
else
ret = NF_ACCEPT;
}
out_put_expect:
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
out_update_nl:
/* Now if this ends in \n, update ftp info. Seq may have been
@@ -542,8 +514,8 @@ out_update_nl:
return ret;
}
-static struct nf_conntrack_helper ftp[MAX_PORTS][2];
-static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")];
+static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
+static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly;
/* don't make this __exit, since it's called from __init ! */
static void nf_conntrack_ftp_fini(void)
@@ -554,9 +526,9 @@ static void nf_conntrack_ftp_fini(void)
if (ftp[i][j].me == NULL)
continue;
- DEBUGP("nf_ct_ftp: unregistering helper for pf: %d "
- "port: %d\n",
- ftp[i][j].tuple.src.l3num, ports[i]);
+ pr_debug("nf_ct_ftp: unregistering helper for pf: %d "
+ "port: %d\n",
+ ftp[i][j].tuple.src.l3num, ports[i]);
nf_conntrack_helper_unregister(&ftp[i][j]);
}
}
@@ -584,9 +556,6 @@ static int __init nf_conntrack_ftp_init(void)
for (j = 0; j < 2; j++) {
ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
- ftp[i][j].mask.src.l3num = 0xFFFF;
- ftp[i][j].mask.src.u.tcp.port = htons(0xFFFF);
- ftp[i][j].mask.dst.protonum = 0xFF;
ftp[i][j].max_expected = 1;
ftp[i][j].timeout = 5 * 60; /* 5 Minutes */
ftp[i][j].me = THIS_MODULE;
@@ -598,9 +567,9 @@ static int __init nf_conntrack_ftp_init(void)
sprintf(tmpname, "ftp-%d", ports[i]);
ftp[i][j].name = tmpname;
- DEBUGP("nf_ct_ftp: registering helper for pf: %d "
- "port: %d\n",
- ftp[i][j].tuple.src.l3num, ports[i]);
+ pr_debug("nf_ct_ftp: registering helper for pf: %d "
+ "port: %d\n",
+ ftp[i][j].tuple.src.l3num, ports[i]);
ret = nf_conntrack_helper_register(&ftp[i][j]);
if (ret) {
printk("nf_ct_ftp: failed to register helper "
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
index f6fad713d48..a869403b229 100644
--- a/net/netfilter/nf_conntrack_h323_asn1.c
+++ b/net/netfilter/nf_conntrack_h323_asn1.c
@@ -518,7 +518,7 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
CHECK_BOUND(bs, 2);
len = get_len(bs);
CHECK_BOUND(bs, len);
- if (!base) {
+ if (!base || !(son->attr & DECODE)) {
PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
" ", son->name);
bs->cur += len;
@@ -555,15 +555,6 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
/* Decode the extension components */
for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
- if (i < f->ub && son->attr & STOP) {
- PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
- son->name);
- return H323_ERROR_STOP;
- }
-
- if (!((0x80000000 >> opt) & bmp2)) /* Not present */
- continue;
-
/* Check Range */
if (i >= f->ub) { /* Newer Version? */
CHECK_BOUND(bs, 2);
@@ -573,6 +564,15 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
continue;
}
+ if (son->attr & STOP) {
+ PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
+ son->name);
+ return H323_ERROR_STOP;
+ }
+
+ if (!((0x80000000 >> opt) & bmp2)) /* Not present */
+ continue;
+
CHECK_BOUND(bs, 2);
len = get_len(bs);
CHECK_BOUND(bs, len);
@@ -704,6 +704,8 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
} else {
ext = 0;
type = get_bits(bs, f->sz);
+ if (type >= f->lb)
+ return H323_ERROR_RANGE;
}
/* Write Type */
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index a1b95acad29..a8a9dfbe7a6 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -31,12 +31,6 @@
#include <net/netfilter/nf_conntrack_helper.h>
#include <linux/netfilter/nf_conntrack_h323.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Parameters */
static unsigned int default_rrq_ttl __read_mostly = 300;
module_param(default_rrq_ttl, uint, 0600);
@@ -150,9 +144,9 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff,
if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
/* Netmeeting sends TPKT header and data separately */
if (info->tpkt_len[dir] > 0) {
- DEBUGP("nf_ct_h323: previous packet "
- "indicated separate TPKT data of %hu "
- "bytes\n", info->tpkt_len[dir]);
+ pr_debug("nf_ct_h323: previous packet "
+ "indicated separate TPKT data of %hu "
+ "bytes\n", info->tpkt_len[dir]);
if (info->tpkt_len[dir] <= tcpdatalen) {
/* Yes, there was a TPKT header
* received */
@@ -163,9 +157,7 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff,
}
/* Fragmented TPKT */
- if (net_ratelimit())
- printk("nf_ct_h323: "
- "fragmented TPKT\n");
+ pr_debug("nf_ct_h323: fragmented TPKT\n");
goto clear_out;
}
@@ -192,9 +184,9 @@ static int get_tpkt_data(struct sk_buff **pskb, unsigned int protoff,
if (tpktlen > tcpdatalen) {
if (tcpdatalen == 4) { /* Separate TPKT header */
/* Netmeeting sends TPKT header and data separately */
- DEBUGP("nf_ct_h323: separate TPKT header indicates "
- "there will be TPKT data of %hu bytes\n",
- tpktlen - 4);
+ pr_debug("nf_ct_h323: separate TPKT header indicates "
+ "there will be TPKT data of %hu bytes\n",
+ tpktlen - 4);
info->tpkt_len[dir] = tpktlen - 4;
return 0;
}
@@ -282,22 +274,22 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
rtcp_port = htons(ntohs(port) + 1);
/* Create expect for RTP */
- if ((rtp_exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ if ((rtp_exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_conntrack_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
- &ct->tuplehash[!dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3,
- IPPROTO_UDP, NULL, &rtp_port);
+ nf_ct_expect_init(rtp_exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_UDP, NULL, &rtp_port);
/* Create expect for RTCP */
- if ((rtcp_exp = nf_conntrack_expect_alloc(ct)) == NULL) {
- nf_conntrack_expect_put(rtp_exp);
+ if ((rtcp_exp = nf_ct_expect_alloc(ct)) == NULL) {
+ nf_ct_expect_put(rtp_exp);
return -1;
}
- nf_conntrack_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
- &ct->tuplehash[!dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3,
- IPPROTO_UDP, NULL, &rtcp_port);
+ nf_ct_expect_init(rtcp_exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_UDP, NULL, &rtcp_port);
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
&ct->tuplehash[!dir].tuple.dst.u3,
@@ -308,22 +300,22 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
taddr, port, rtp_port, rtp_exp, rtcp_exp);
} else { /* Conntrack only */
- if (nf_conntrack_expect_related(rtp_exp) == 0) {
- if (nf_conntrack_expect_related(rtcp_exp) == 0) {
- DEBUGP("nf_ct_h323: expect RTP ");
+ if (nf_ct_expect_related(rtp_exp) == 0) {
+ if (nf_ct_expect_related(rtcp_exp) == 0) {
+ pr_debug("nf_ct_h323: expect RTP ");
NF_CT_DUMP_TUPLE(&rtp_exp->tuple);
- DEBUGP("nf_ct_h323: expect RTCP ");
+ pr_debug("nf_ct_h323: expect RTCP ");
NF_CT_DUMP_TUPLE(&rtcp_exp->tuple);
} else {
- nf_conntrack_unexpect_related(rtp_exp);
+ nf_ct_unexpect_related(rtp_exp);
ret = -1;
}
} else
ret = -1;
}
- nf_conntrack_expect_put(rtp_exp);
- nf_conntrack_expect_put(rtcp_exp);
+ nf_ct_expect_put(rtp_exp);
+ nf_ct_expect_put(rtcp_exp);
return ret;
}
@@ -349,12 +341,12 @@ static int expect_t120(struct sk_buff **pskb,
return 0;
/* Create expect for T.120 connections */
- if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
- &ct->tuplehash[!dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3,
- IPPROTO_TCP, NULL, &port);
+ nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple channels */
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -366,14 +358,14 @@ static int expect_t120(struct sk_buff **pskb,
ret = nat_t120(pskb, ct, ctinfo, data, dataoff, taddr,
port, exp);
} else { /* Conntrack only */
- if (nf_conntrack_expect_related(exp) == 0) {
- DEBUGP("nf_ct_h323: expect T.120 ");
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_h323: expect T.120 ");
NF_CT_DUMP_TUPLE(&exp->tuple);
} else
ret = -1;
}
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return ret;
}
@@ -415,7 +407,7 @@ static int process_olc(struct sk_buff **pskb, struct nf_conn *ct,
{
int ret;
- DEBUGP("nf_ct_h323: OpenLogicalChannel\n");
+ pr_debug("nf_ct_h323: OpenLogicalChannel\n");
if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
@@ -475,7 +467,7 @@ static int process_olca(struct sk_buff **pskb, struct nf_conn *ct,
H2250LogicalChannelAckParameters *ack;
int ret;
- DEBUGP("nf_ct_h323: OpenLogicalChannelAck\n");
+ pr_debug("nf_ct_h323: OpenLogicalChannelAck\n");
if ((olca->options &
eOpenLogicalChannelAck_reverseLogicalChannelParameters) &&
@@ -546,8 +538,8 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct,
return process_olc(pskb, ct, ctinfo, data, dataoff,
&mscm->request.openLogicalChannel);
}
- DEBUGP("nf_ct_h323: H.245 Request %d\n",
- mscm->request.choice);
+ pr_debug("nf_ct_h323: H.245 Request %d\n",
+ mscm->request.choice);
break;
case eMultimediaSystemControlMessage_response:
if (mscm->response.choice ==
@@ -556,11 +548,11 @@ static int process_h245(struct sk_buff **pskb, struct nf_conn *ct,
&mscm->response.
openLogicalChannelAck);
}
- DEBUGP("nf_ct_h323: H.245 Response %d\n",
- mscm->response.choice);
+ pr_debug("nf_ct_h323: H.245 Response %d\n",
+ mscm->response.choice);
break;
default:
- DEBUGP("nf_ct_h323: H.245 signal %d\n", mscm->choice);
+ pr_debug("nf_ct_h323: H.245 signal %d\n", mscm->choice);
break;
}
@@ -582,24 +574,23 @@ static int h245_help(struct sk_buff **pskb, unsigned int protoff,
ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
return NF_ACCEPT;
}
- DEBUGP("nf_ct_h245: skblen = %u\n", (*pskb)->len);
+ pr_debug("nf_ct_h245: skblen = %u\n", (*pskb)->len);
spin_lock_bh(&nf_h323_lock);
/* Process each TPKT */
while (get_tpkt_data(pskb, protoff, ct, ctinfo,
&data, &datalen, &dataoff)) {
- DEBUGP("nf_ct_h245: TPKT len=%d ", datalen);
+ pr_debug("nf_ct_h245: TPKT len=%d ", datalen);
NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
/* Decode H.245 signal */
ret = DecodeMultimediaSystemControlMessage(data, datalen,
&mscm);
if (ret < 0) {
- if (net_ratelimit())
- printk("nf_ct_h245: decoding error: %s\n",
- ret == H323_ERROR_BOUND ?
- "out of bound" : "out of range");
+ pr_debug("nf_ct_h245: decoding error: %s\n",
+ ret == H323_ERROR_BOUND ?
+ "out of bound" : "out of range");
/* We don't drop when decoding error */
break;
}
@@ -626,8 +617,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_h245 __read_mostly = {
.max_expected = H323_RTP_CHANNEL_MAX * 4 + 2 /* T.120 */,
.timeout = 240,
.tuple.dst.protonum = IPPROTO_UDP,
- .mask.src.u.udp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
.help = h245_help
};
@@ -684,12 +673,12 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct,
return 0;
/* Create expect for h245 connection */
- if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
- &ct->tuplehash[!dir].tuple.src.u3,
- &ct->tuplehash[!dir].tuple.dst.u3,
- IPPROTO_TCP, NULL, &port);
+ nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_TCP, NULL, &port);
exp->helper = &nf_conntrack_helper_h245;
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -701,14 +690,14 @@ static int expect_h245(struct sk_buff **pskb, struct nf_conn *ct,
ret = nat_h245(pskb, ct, ctinfo, data, dataoff, taddr,
port, exp);
} else { /* Conntrack only */
- if (nf_conntrack_expect_related(exp) == 0) {
- DEBUGP("nf_ct_q931: expect H.245 ");
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_q931: expect H.245 ");
NF_CT_DUMP_TUPLE(&exp->tuple);
} else
ret = -1;
}
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return ret;
}
@@ -791,16 +780,16 @@ static int expect_callforwarding(struct sk_buff **pskb,
if (callforward_filter &&
callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3,
ct->tuplehash[!dir].tuple.src.l3num)) {
- DEBUGP("nf_ct_q931: Call Forwarding not tracked\n");
+ pr_debug("nf_ct_q931: Call Forwarding not tracked\n");
return 0;
}
/* Create expect for the second call leg */
- if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
- &ct->tuplehash[!dir].tuple.src.u3, &addr,
- IPPROTO_TCP, NULL, &port);
+ nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
exp->helper = nf_conntrack_helper_q931;
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -812,14 +801,14 @@ static int expect_callforwarding(struct sk_buff **pskb,
ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
taddr, port, exp);
} else { /* Conntrack only */
- if (nf_conntrack_expect_related(exp) == 0) {
- DEBUGP("nf_ct_q931: expect Call Forwarding ");
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_q931: expect Call Forwarding ");
NF_CT_DUMP_TUPLE(&exp->tuple);
} else
ret = -1;
}
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return ret;
}
@@ -837,7 +826,7 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
union nf_conntrack_address addr;
typeof(set_h225_addr_hook) set_h225_addr;
- DEBUGP("nf_ct_q931: Setup\n");
+ pr_debug("nf_ct_q931: Setup\n");
if (setup->options & eSetup_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -852,11 +841,11 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
get_h225_addr(ct, *data, &setup->destCallSignalAddress,
&addr, &port) &&
memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
- DEBUGP("nf_ct_q931: set destCallSignalAddress "
- NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
- NIP6(*(struct in6_addr *)&addr), ntohs(port),
- NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
- ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
+ pr_debug("nf_ct_q931: set destCallSignalAddress "
+ NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
+ NIP6(*(struct in6_addr *)&addr), ntohs(port),
+ NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.src.u3),
+ ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
ret = set_h225_addr(pskb, data, dataoff,
&setup->destCallSignalAddress,
&ct->tuplehash[!dir].tuple.src.u3,
@@ -870,11 +859,11 @@ static int process_setup(struct sk_buff **pskb, struct nf_conn *ct,
get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
&addr, &port) &&
memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
- DEBUGP("nf_ct_q931: set sourceCallSignalAddress "
- NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
- NIP6(*(struct in6_addr *)&addr), ntohs(port),
- NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
- ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
+ pr_debug("nf_ct_q931: set sourceCallSignalAddress "
+ NIP6_FMT ":%hu->" NIP6_FMT ":%hu\n",
+ NIP6(*(struct in6_addr *)&addr), ntohs(port),
+ NIP6(*(struct in6_addr *)&ct->tuplehash[!dir].tuple.dst.u3),
+ ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
ret = set_h225_addr(pskb, data, dataoff,
&setup->sourceCallSignalAddress,
&ct->tuplehash[!dir].tuple.dst.u3,
@@ -905,7 +894,7 @@ static int process_callproceeding(struct sk_buff **pskb,
int ret;
int i;
- DEBUGP("nf_ct_q931: CallProceeding\n");
+ pr_debug("nf_ct_q931: CallProceeding\n");
if (callproc->options & eCallProceeding_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -935,7 +924,7 @@ static int process_connect(struct sk_buff **pskb, struct nf_conn *ct,
int ret;
int i;
- DEBUGP("nf_ct_q931: Connect\n");
+ pr_debug("nf_ct_q931: Connect\n");
if (connect->options & eConnect_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -965,7 +954,7 @@ static int process_alerting(struct sk_buff **pskb, struct nf_conn *ct,
int ret;
int i;
- DEBUGP("nf_ct_q931: Alerting\n");
+ pr_debug("nf_ct_q931: Alerting\n");
if (alert->options & eAlerting_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -995,7 +984,7 @@ static int process_facility(struct sk_buff **pskb, struct nf_conn *ct,
int ret;
int i;
- DEBUGP("nf_ct_q931: Facility\n");
+ pr_debug("nf_ct_q931: Facility\n");
if (facility->reason.choice == eFacilityReason_callForwarded) {
if (facility->options & eFacility_UUIE_alternativeAddress)
@@ -1034,7 +1023,7 @@ static int process_progress(struct sk_buff **pskb, struct nf_conn *ct,
int ret;
int i;
- DEBUGP("nf_ct_q931: Progress\n");
+ pr_debug("nf_ct_q931: Progress\n");
if (progress->options & eProgress_UUIE_h245Address) {
ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
@@ -1091,8 +1080,8 @@ static int process_q931(struct sk_buff **pskb, struct nf_conn *ct,
&pdu->h323_message_body.progress);
break;
default:
- DEBUGP("nf_ct_q931: Q.931 signal %d\n",
- pdu->h323_message_body.choice);
+ pr_debug("nf_ct_q931: Q.931 signal %d\n",
+ pdu->h323_message_body.choice);
break;
}
@@ -1126,23 +1115,22 @@ static int q931_help(struct sk_buff **pskb, unsigned int protoff,
ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
return NF_ACCEPT;
}
- DEBUGP("nf_ct_q931: skblen = %u\n", (*pskb)->len);
+ pr_debug("nf_ct_q931: skblen = %u\n", (*pskb)->len);
spin_lock_bh(&nf_h323_lock);
/* Process each TPKT */
while (get_tpkt_data(pskb, protoff, ct, ctinfo,
&data, &datalen, &dataoff)) {
- DEBUGP("nf_ct_q931: TPKT len=%d ", datalen);
+ pr_debug("nf_ct_q931: TPKT len=%d ", datalen);
NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
/* Decode Q.931 signal */
ret = DecodeQ931(data, datalen, &q931);
if (ret < 0) {
- if (net_ratelimit())
- printk("nf_ct_q931: decoding error: %s\n",
- ret == H323_ERROR_BOUND ?
- "out of bound" : "out of range");
+ pr_debug("nf_ct_q931: decoding error: %s\n",
+ ret == H323_ERROR_BOUND ?
+ "out of bound" : "out of range");
/* We don't drop when decoding error */
break;
}
@@ -1173,9 +1161,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
.tuple.src.l3num = AF_INET,
.tuple.src.u.tcp.port = __constant_htons(Q931_PORT),
.tuple.dst.protonum = IPPROTO_TCP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.tcp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
.help = q931_help
},
{
@@ -1187,9 +1172,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
.tuple.src.l3num = AF_INET6,
.tuple.src.u.tcp.port = __constant_htons(Q931_PORT),
.tuple.dst.protonum = IPPROTO_TCP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.tcp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
.help = q931_help
},
};
@@ -1225,7 +1207,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
tuple.dst.u.tcp.port = port;
tuple.dst.protonum = IPPROTO_TCP;
- exp = __nf_conntrack_expect_find(&tuple);
+ exp = __nf_ct_expect_find(&tuple);
if (exp && exp->master == ct)
return exp;
return NULL;
@@ -1271,14 +1253,13 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct,
return 0;
/* Create expect for Q.931 */
- if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
- gkrouted_only ? /* only accept calls from GK? */
- &ct->tuplehash[!dir].tuple.src.u3 :
- NULL,
- &ct->tuplehash[!dir].tuple.dst.u3,
- IPPROTO_TCP, NULL, &port);
+ nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ gkrouted_only ? /* only accept calls from GK? */
+ &ct->tuplehash[!dir].tuple.src.u3 : NULL,
+ &ct->tuplehash[!dir].tuple.dst.u3,
+ IPPROTO_TCP, NULL, &port);
exp->helper = nf_conntrack_helper_q931;
exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */
@@ -1286,8 +1267,8 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct,
if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */
ret = nat_q931(pskb, ct, ctinfo, data, taddr, i, port, exp);
} else { /* Conntrack only */
- if (nf_conntrack_expect_related(exp) == 0) {
- DEBUGP("nf_ct_ras: expect Q.931 ");
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_ras: expect Q.931 ");
NF_CT_DUMP_TUPLE(&exp->tuple);
/* Save port for looking up expect in processing RCF */
@@ -1296,7 +1277,7 @@ static int expect_q931(struct sk_buff **pskb, struct nf_conn *ct,
ret = -1;
}
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return ret;
}
@@ -1308,7 +1289,7 @@ static int process_grq(struct sk_buff **pskb, struct nf_conn *ct,
{
typeof(set_ras_addr_hook) set_ras_addr;
- DEBUGP("nf_ct_ras: GRQ\n");
+ pr_debug("nf_ct_ras: GRQ\n");
set_ras_addr = rcu_dereference(set_ras_addr_hook);
if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */
@@ -1328,7 +1309,7 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct,
union nf_conntrack_address addr;
struct nf_conntrack_expect *exp;
- DEBUGP("nf_ct_ras: GCF\n");
+ pr_debug("nf_ct_ras: GCF\n");
if (!get_h225_addr(ct, *data, &gcf->rasAddress, &addr, &port))
return 0;
@@ -1343,20 +1324,20 @@ static int process_gcf(struct sk_buff **pskb, struct nf_conn *ct,
return 0;
/* Need new expect */
- if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
- &ct->tuplehash[!dir].tuple.src.u3, &addr,
- IPPROTO_UDP, NULL, &port);
+ nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_UDP, NULL, &port);
exp->helper = nf_conntrack_helper_ras;
- if (nf_conntrack_expect_related(exp) == 0) {
- DEBUGP("nf_ct_ras: expect RAS ");
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_ras: expect RAS ");
NF_CT_DUMP_TUPLE(&exp->tuple);
} else
ret = -1;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return ret;
}
@@ -1370,7 +1351,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct,
int ret;
typeof(set_ras_addr_hook) set_ras_addr;
- DEBUGP("nf_ct_ras: RRQ\n");
+ pr_debug("nf_ct_ras: RRQ\n");
ret = expect_q931(pskb, ct, ctinfo, data,
rrq->callSignalAddress.item,
@@ -1388,7 +1369,7 @@ static int process_rrq(struct sk_buff **pskb, struct nf_conn *ct,
}
if (rrq->options & eRegistrationRequest_timeToLive) {
- DEBUGP("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
+ pr_debug("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
info->timeout = rrq->timeToLive;
} else
info->timeout = default_rrq_ttl;
@@ -1407,7 +1388,7 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
struct nf_conntrack_expect *exp;
typeof(set_sig_addr_hook) set_sig_addr;
- DEBUGP("nf_ct_ras: RCF\n");
+ pr_debug("nf_ct_ras: RCF\n");
set_sig_addr = rcu_dereference(set_sig_addr_hook);
if (set_sig_addr && ct->status & IPS_NAT_MASK) {
@@ -1419,14 +1400,13 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
}
if (rcf->options & eRegistrationConfirm_timeToLive) {
- DEBUGP("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
+ pr_debug("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
info->timeout = rcf->timeToLive;
}
if (info->timeout > 0) {
- DEBUGP
- ("nf_ct_ras: set RAS connection timeout to %u seconds\n",
- info->timeout);
+ pr_debug("nf_ct_ras: set RAS connection timeout to "
+ "%u seconds\n", info->timeout);
nf_ct_refresh(ct, *pskb, info->timeout * HZ);
/* Set expect timeout */
@@ -1434,9 +1414,9 @@ static int process_rcf(struct sk_buff **pskb, struct nf_conn *ct,
exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
info->sig_port[!dir]);
if (exp) {
- DEBUGP("nf_ct_ras: set Q.931 expect "
- "timeout to %u seconds for",
- info->timeout);
+ pr_debug("nf_ct_ras: set Q.931 expect "
+ "timeout to %u seconds for",
+ info->timeout);
NF_CT_DUMP_TUPLE(&exp->tuple);
set_expect_timeout(exp, info->timeout);
}
@@ -1456,7 +1436,7 @@ static int process_urq(struct sk_buff **pskb, struct nf_conn *ct,
int ret;
typeof(set_sig_addr_hook) set_sig_addr;
- DEBUGP("nf_ct_ras: URQ\n");
+ pr_debug("nf_ct_ras: URQ\n");
set_sig_addr = rcu_dereference(set_sig_addr_hook);
if (set_sig_addr && ct->status & IPS_NAT_MASK) {
@@ -1489,7 +1469,7 @@ static int process_arq(struct sk_buff **pskb, struct nf_conn *ct,
union nf_conntrack_address addr;
typeof(set_h225_addr_hook) set_h225_addr;
- DEBUGP("nf_ct_ras: ARQ\n");
+ pr_debug("nf_ct_ras: ARQ\n");
set_h225_addr = rcu_dereference(set_h225_addr_hook);
if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
@@ -1532,7 +1512,7 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct,
struct nf_conntrack_expect *exp;
typeof(set_sig_addr_hook) set_sig_addr;
- DEBUGP("nf_ct_ras: ACF\n");
+ pr_debug("nf_ct_ras: ACF\n");
if (!get_h225_addr(ct, *data, &acf->destCallSignalAddress,
&addr, &port))
@@ -1548,21 +1528,21 @@ static int process_acf(struct sk_buff **pskb, struct nf_conn *ct,
}
/* Need new expect */
- if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
- &ct->tuplehash[!dir].tuple.src.u3, &addr,
- IPPROTO_TCP, NULL, &port);
+ nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT;
exp->helper = nf_conntrack_helper_q931;
- if (nf_conntrack_expect_related(exp) == 0) {
- DEBUGP("nf_ct_ras: expect Q.931 ");
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_ras: expect Q.931 ");
NF_CT_DUMP_TUPLE(&exp->tuple);
} else
ret = -1;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return ret;
}
@@ -1574,7 +1554,7 @@ static int process_lrq(struct sk_buff **pskb, struct nf_conn *ct,
{
typeof(set_ras_addr_hook) set_ras_addr;
- DEBUGP("nf_ct_ras: LRQ\n");
+ pr_debug("nf_ct_ras: LRQ\n");
set_ras_addr = rcu_dereference(set_ras_addr_hook);
if (set_ras_addr && ct->status & IPS_NAT_MASK)
@@ -1594,28 +1574,28 @@ static int process_lcf(struct sk_buff **pskb, struct nf_conn *ct,
union nf_conntrack_address addr;
struct nf_conntrack_expect *exp;
- DEBUGP("nf_ct_ras: LCF\n");
+ pr_debug("nf_ct_ras: LCF\n");
if (!get_h225_addr(ct, *data, &lcf->callSignalAddress,
&addr, &port))
return 0;
/* Need new expect for call signal */
- if ((exp = nf_conntrack_expect_alloc(ct)) == NULL)
+ if ((exp = nf_ct_expect_alloc(ct)) == NULL)
return -1;
- nf_conntrack_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
- &ct->tuplehash[!dir].tuple.src.u3, &addr,
- IPPROTO_TCP, NULL, &port);
+ nf_ct_expect_init(exp, ct->tuplehash[!dir].tuple.src.l3num,
+ &ct->tuplehash[!dir].tuple.src.u3, &addr,
+ IPPROTO_TCP, NULL, &port);
exp->flags = NF_CT_EXPECT_PERMANENT;
exp->helper = nf_conntrack_helper_q931;
- if (nf_conntrack_expect_related(exp) == 0) {
- DEBUGP("nf_ct_ras: expect Q.931 ");
+ if (nf_ct_expect_related(exp) == 0) {
+ pr_debug("nf_ct_ras: expect Q.931 ");
NF_CT_DUMP_TUPLE(&exp->tuple);
} else
ret = -1;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
/* Ignore rasAddress */
@@ -1631,7 +1611,7 @@ static int process_irr(struct sk_buff **pskb, struct nf_conn *ct,
typeof(set_ras_addr_hook) set_ras_addr;
typeof(set_sig_addr_hook) set_sig_addr;
- DEBUGP("nf_ct_ras: IRR\n");
+ pr_debug("nf_ct_ras: IRR\n");
set_ras_addr = rcu_dereference(set_ras_addr_hook);
if (set_ras_addr && ct->status & IPS_NAT_MASK) {
@@ -1690,7 +1670,7 @@ static int process_ras(struct sk_buff **pskb, struct nf_conn *ct,
return process_irr(pskb, ct, ctinfo, data,
&ras->infoRequestResponse);
default:
- DEBUGP("nf_ct_ras: RAS message %d\n", ras->choice);
+ pr_debug("nf_ct_ras: RAS message %d\n", ras->choice);
break;
}
@@ -1706,7 +1686,7 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff,
int datalen = 0;
int ret;
- DEBUGP("nf_ct_ras: skblen = %u\n", (*pskb)->len);
+ pr_debug("nf_ct_ras: skblen = %u\n", (*pskb)->len);
spin_lock_bh(&nf_h323_lock);
@@ -1714,16 +1694,15 @@ static int ras_help(struct sk_buff **pskb, unsigned int protoff,
data = get_udp_data(pskb, protoff, &datalen);
if (data == NULL)
goto accept;
- DEBUGP("nf_ct_ras: RAS message len=%d ", datalen);
+ pr_debug("nf_ct_ras: RAS message len=%d ", datalen);
NF_CT_DUMP_TUPLE(&ct->tuplehash[CTINFO2DIR(ctinfo)].tuple);
/* Decode RAS message */
ret = DecodeRasMessage(data, datalen, &ras);
if (ret < 0) {
- if (net_ratelimit())
- printk("nf_ct_ras: decoding error: %s\n",
- ret == H323_ERROR_BOUND ?
- "out of bound" : "out of range");
+ pr_debug("nf_ct_ras: decoding error: %s\n",
+ ret == H323_ERROR_BOUND ?
+ "out of bound" : "out of range");
goto accept;
}
@@ -1752,9 +1731,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
.tuple.src.l3num = AF_INET,
.tuple.src.u.udp.port = __constant_htons(RAS_PORT),
.tuple.dst.protonum = IPPROTO_UDP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.udp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
.help = ras_help,
},
{
@@ -1765,9 +1741,6 @@ static struct nf_conntrack_helper nf_conntrack_helper_ras[] __read_mostly = {
.tuple.src.l3num = AF_INET6,
.tuple.src.u.udp.port = __constant_htons(RAS_PORT),
.tuple.dst.protonum = IPPROTO_UDP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.udp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
.help = ras_help,
},
};
@@ -1780,7 +1753,7 @@ static void __exit nf_conntrack_h323_fini(void)
nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[1]);
nf_conntrack_helper_unregister(&nf_conntrack_helper_q931[0]);
kfree(h323_buffer);
- DEBUGP("nf_ct_h323: fini\n");
+ pr_debug("nf_ct_h323: fini\n");
}
/****************************************************************************/
@@ -1803,7 +1776,7 @@ static int __init nf_conntrack_h323_init(void)
ret = nf_conntrack_helper_register(&nf_conntrack_helper_ras[1]);
if (ret < 0)
goto err4;
- DEBUGP("nf_ct_h323: init success\n");
+ pr_debug("nf_ct_h323: init success\n");
return 0;
err4:
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 0743be4434b..b1179dd3d8c 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -26,23 +26,43 @@
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_extend.h>
-static __read_mostly LIST_HEAD(helpers);
+static struct hlist_head *nf_ct_helper_hash __read_mostly;
+static unsigned int nf_ct_helper_hsize __read_mostly;
+static unsigned int nf_ct_helper_count __read_mostly;
+static int nf_ct_helper_vmalloc;
+
+
+/* Stupid hash, but collision free for the default registrations of the
+ * helpers currently in the kernel. */
+static unsigned int helper_hash(const struct nf_conntrack_tuple *tuple)
+{
+ return (((tuple->src.l3num << 8) | tuple->dst.protonum) ^
+ tuple->src.u.all) % nf_ct_helper_hsize;
+}
struct nf_conntrack_helper *
__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
{
- struct nf_conntrack_helper *h;
+ struct nf_conntrack_helper *helper;
+ struct nf_conntrack_tuple_mask mask = { .src.u.all = htons(0xFFFF) };
+ struct hlist_node *n;
+ unsigned int h;
+
+ if (!nf_ct_helper_count)
+ return NULL;
- list_for_each_entry(h, &helpers, list) {
- if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
- return h;
+ h = helper_hash(tuple);
+ hlist_for_each_entry(helper, n, &nf_ct_helper_hash[h], hnode) {
+ if (nf_ct_tuple_src_mask_cmp(tuple, &helper->tuple, &mask))
+ return helper;
}
return NULL;
}
struct nf_conntrack_helper *
-nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple)
+nf_ct_helper_find_get(const struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_helper *helper;
@@ -75,16 +95,32 @@ struct nf_conntrack_helper *
__nf_conntrack_helper_find_byname(const char *name)
{
struct nf_conntrack_helper *h;
+ struct hlist_node *n;
+ unsigned int i;
- list_for_each_entry(h, &helpers, list) {
- if (!strcmp(h->name, name))
- return h;
+ for (i = 0; i < nf_ct_helper_hsize; i++) {
+ hlist_for_each_entry(h, n, &nf_ct_helper_hash[i], hnode) {
+ if (!strcmp(h->name, name))
+ return h;
+ }
}
-
return NULL;
}
EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname);
+struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+ struct nf_conn_help *help;
+
+ help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, gfp);
+ if (help)
+ INIT_HLIST_HEAD(&help->expectations);
+ else
+ pr_debug("failed to add helper extension area");
+ return help;
+}
+EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
+
static inline int unhelp(struct nf_conntrack_tuple_hash *i,
const struct nf_conntrack_helper *me)
{
@@ -93,27 +129,20 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i,
if (help && help->helper == me) {
nf_conntrack_event(IPCT_HELPER, ct);
- help->helper = NULL;
+ rcu_assign_pointer(help->helper, NULL);
}
return 0;
}
int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
{
- int size, ret;
+ unsigned int h = helper_hash(&me->tuple);
BUG_ON(me->timeout == 0);
- size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_help)) +
- sizeof(struct nf_conn_help);
- ret = nf_conntrack_register_cache(NF_CT_F_HELP, "nf_conntrack:help",
- size);
- if (ret < 0) {
- printk(KERN_ERR "nf_conntrack_helper_register: Unable to create slab cache for conntracks\n");
- return ret;
- }
write_lock_bh(&nf_conntrack_lock);
- list_add(&me->list, &helpers);
+ hlist_add_head(&me->hnode, &nf_ct_helper_hash[h]);
+ nf_ct_helper_count++;
write_unlock_bh(&nf_conntrack_lock);
return 0;
@@ -122,29 +151,34 @@ EXPORT_SYMBOL_GPL(nf_conntrack_helper_register);
void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
{
- unsigned int i;
struct nf_conntrack_tuple_hash *h;
- struct nf_conntrack_expect *exp, *tmp;
+ struct nf_conntrack_expect *exp;
+ struct hlist_node *n, *next;
+ unsigned int i;
/* Need write lock here, to delete helper. */
write_lock_bh(&nf_conntrack_lock);
- list_del(&me->list);
+ hlist_del(&me->hnode);
+ nf_ct_helper_count--;
/* Get rid of expectations */
- list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
- struct nf_conn_help *help = nfct_help(exp->master);
- if ((help->helper == me || exp->helper == me) &&
- del_timer(&exp->timeout)) {
- nf_ct_unlink_expect(exp);
- nf_conntrack_expect_put(exp);
+ for (i = 0; i < nf_ct_expect_hsize; i++) {
+ hlist_for_each_entry_safe(exp, n, next,
+ &nf_ct_expect_hash[i], hnode) {
+ struct nf_conn_help *help = nfct_help(exp->master);
+ if ((help->helper == me || exp->helper == me) &&
+ del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_ct_expect_put(exp);
+ }
}
}
/* Get rid of expecteds, set helpers to NULL. */
- list_for_each_entry(h, &unconfirmed, list)
+ hlist_for_each_entry(h, n, &unconfirmed, hnode)
unhelp(h, me);
for (i = 0; i < nf_conntrack_htable_size; i++) {
- list_for_each_entry(h, &nf_conntrack_hash[i], list)
+ hlist_for_each_entry(h, n, &nf_conntrack_hash[i], hnode)
unhelp(h, me);
}
write_unlock_bh(&nf_conntrack_lock);
@@ -153,3 +187,38 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
synchronize_net();
}
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
+
+static struct nf_ct_ext_type helper_extend __read_mostly = {
+ .len = sizeof(struct nf_conn_help),
+ .align = __alignof__(struct nf_conn_help),
+ .id = NF_CT_EXT_HELPER,
+};
+
+int nf_conntrack_helper_init()
+{
+ int err;
+
+ nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
+ nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize,
+ &nf_ct_helper_vmalloc);
+ if (!nf_ct_helper_hash)
+ return -ENOMEM;
+
+ err = nf_ct_extend_register(&helper_extend);
+ if (err < 0)
+ goto err1;
+
+ return 0;
+
+err1:
+ nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
+ nf_ct_helper_hsize);
+ return err;
+}
+
+void nf_conntrack_helper_fini()
+{
+ nf_ct_extend_unregister(&helper_extend);
+ nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
+ nf_ct_helper_hsize);
+}
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 43ccd0e2e8a..1562ca97a34 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -12,6 +12,7 @@
#include <linux/moduleparam.h>
#include <linux/skbuff.h>
#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netfilter.h>
@@ -55,13 +56,6 @@ static const char *dccprotos[] = {
#define MINMATCHLEN 5
-#if 0
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s:" format, \
- __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* tries to get the ip_addr and port out of a dcc command
* return value: -1 on failure, 0 on success
* data pointer to first byte of DCC command data
@@ -99,6 +93,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
struct nf_conn *ct, enum ip_conntrack_info ctinfo)
{
unsigned int dataoff;
+ struct iphdr *iph;
struct tcphdr _tcph, *th;
char *data, *data_limit, *ib_ptr;
int dir = CTINFO2DIR(ctinfo);
@@ -148,9 +143,10 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
data += 5;
/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
- DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
- NIPQUAD(iph->saddr), ntohs(th->source),
- NIPQUAD(iph->daddr), ntohs(th->dest));
+ iph = ip_hdr(*pskb);
+ pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n",
+ NIPQUAD(iph->saddr), ntohs(th->source),
+ NIPQUAD(iph->daddr), ntohs(th->dest));
for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
@@ -158,18 +154,18 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
continue;
}
data += strlen(dccprotos[i]);
- DEBUGP("DCC %s detected\n", dccprotos[i]);
+ pr_debug("DCC %s detected\n", dccprotos[i]);
/* we have at least
* (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
* data left (== 14/13 bytes) */
if (parse_dcc((char *)data, data_limit, &dcc_ip,
&dcc_port, &addr_beg_p, &addr_end_p)) {
- DEBUGP("unable to parse dcc command\n");
+ pr_debug("unable to parse dcc command\n");
continue;
}
- DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n",
- HIPQUAD(dcc_ip), dcc_port);
+ pr_debug("DCC bound ip/port: %u.%u.%u.%u:%u\n",
+ HIPQUAD(dcc_ip), dcc_port);
/* dcc_ip can be the internal OR external (NAT'ed) IP */
tuple = &ct->tuplehash[dir].tuple;
@@ -184,16 +180,16 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
continue;
}
- exp = nf_conntrack_expect_alloc(ct);
+ exp = nf_ct_expect_alloc(ct);
if (exp == NULL) {
ret = NF_DROP;
goto out;
}
tuple = &ct->tuplehash[!dir].tuple;
port = htons(dcc_port);
- nf_conntrack_expect_init(exp, tuple->src.l3num,
- NULL, &tuple->dst.u3,
- IPPROTO_TCP, NULL, &port);
+ nf_ct_expect_init(exp, tuple->src.l3num,
+ NULL, &tuple->dst.u3,
+ IPPROTO_TCP, NULL, &port);
nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
if (nf_nat_irc && ct->status & IPS_NAT_MASK)
@@ -201,9 +197,9 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
addr_beg_p - ib_ptr,
addr_end_p - addr_beg_p,
exp);
- else if (nf_conntrack_expect_related(exp) != 0)
+ else if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
goto out;
}
}
@@ -239,9 +235,6 @@ static int __init nf_conntrack_irc_init(void)
irc[i].tuple.src.l3num = AF_INET;
irc[i].tuple.src.u.tcp.port = htons(ports[i]);
irc[i].tuple.dst.protonum = IPPROTO_TCP;
- irc[i].mask.src.l3num = 0xFFFF;
- irc[i].mask.src.u.tcp.port = htons(0xFFFF);
- irc[i].mask.dst.protonum = 0xFF;
irc[i].max_expected = max_dcc_channels;
irc[i].timeout = dcc_timeout;
irc[i].me = THIS_MODULE;
diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c
index cbd96f3c1b8..991c52c9a28 100644
--- a/net/netfilter/nf_conntrack_l3proto_generic.c
+++ b/net/netfilter/nf_conntrack_l3proto_generic.c
@@ -31,12 +31,6 @@
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
@@ -67,29 +61,21 @@ static int generic_print_conntrack(struct seq_file *s,
return 0;
}
-static int
-generic_prepare(struct sk_buff **pskb, unsigned int hooknum,
- unsigned int *dataoff, u_int8_t *protonum)
+static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
+ unsigned int *dataoff, u_int8_t *protonum)
{
/* Never track !!! */
return -NF_ACCEPT;
}
-static u_int32_t generic_get_features(const struct nf_conntrack_tuple *tuple)
-
-{
- return NF_CT_F_BASIC;
-}
-
-struct nf_conntrack_l3proto nf_conntrack_l3proto_generic = {
+struct nf_conntrack_l3proto nf_conntrack_l3proto_generic __read_mostly = {
.l3proto = PF_UNSPEC,
.name = "unknown",
.pkt_to_tuple = generic_pkt_to_tuple,
.invert_tuple = generic_invert_tuple,
.print_tuple = generic_print_tuple,
.print_conntrack = generic_print_conntrack,
- .prepare = generic_prepare,
- .get_features = generic_get_features,
+ .get_l4proto = generic_get_l4proto,
};
EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic);
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index 1093478cc00..1d59fabeb5f 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -74,7 +74,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
if (mask == 0)
goto out;
- exp = nf_conntrack_expect_alloc(ct);
+ exp = nf_ct_expect_alloc(ct);
if (exp == NULL)
goto out;
@@ -83,16 +83,13 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
exp->mask.src.u3.ip = mask;
exp->mask.src.u.udp.port = htons(0xFFFF);
- exp->mask.dst.u3.ip = htonl(0xFFFFFFFF);
- exp->mask.dst.u.udp.port = htons(0xFFFF);
- exp->mask.dst.protonum = 0xFF;
exp->expectfn = NULL;
exp->flags = NF_CT_EXPECT_PERMANENT;
exp->helper = NULL;
- nf_conntrack_expect_related(exp);
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_related(exp);
+ nf_ct_expect_put(exp);
nf_ct_refresh(ct, *pskb, timeout * HZ);
out:
@@ -104,9 +101,6 @@ static struct nf_conntrack_helper helper __read_mostly = {
.tuple.src.l3num = AF_INET,
.tuple.src.u.udp.port = __constant_htons(NMBD_PORT),
.tuple.dst.protonum = IPPROTO_UDP,
- .mask.src.l3num = 0xFFFF,
- .mask.src.u.udp.port = __constant_htons(0xFFFF),
- .mask.dst.protonum = 0xFF,
.max_expected = 1,
.me = THIS_MODULE,
.help = help,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index d6d39e24132..6f89b105a20 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -171,21 +171,29 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
{
struct nfattr *nest_helper;
const struct nf_conn_help *help = nfct_help(ct);
+ struct nf_conntrack_helper *helper;
- if (!help || !help->helper)
+ if (!help)
return 0;
+ rcu_read_lock();
+ helper = rcu_dereference(help->helper);
+ if (!helper)
+ goto out;
+
nest_helper = NFA_NEST(skb, CTA_HELP);
- NFA_PUT(skb, CTA_HELP_NAME, strlen(help->helper->name), help->helper->name);
+ NFA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);
- if (help->helper->to_nfattr)
- help->helper->to_nfattr(skb, ct);
+ if (helper->to_nfattr)
+ helper->to_nfattr(skb, ct);
NFA_NEST_END(skb, nest_helper);
-
+out:
+ rcu_read_unlock();
return 0;
nfattr_failure:
+ rcu_read_unlock();
return -1;
}
@@ -420,7 +428,7 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
{
struct nf_conn *ct, *last;
struct nf_conntrack_tuple_hash *h;
- struct list_head *i;
+ struct hlist_node *n;
struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
u_int8_t l3proto = nfmsg->nfgen_family;
@@ -428,8 +436,8 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
last = (struct nf_conn *)cb->args[1];
for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
restart:
- list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
- h = (struct nf_conntrack_tuple_hash *) i;
+ hlist_for_each_entry(h, n, &nf_conntrack_hash[cb->args[0]],
+ hnode) {
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
continue;
ct = nf_ct_tuplehash_to_ctrack(h);
@@ -681,7 +689,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
- h = nf_conntrack_find_get(&tuple, NULL);
+ h = nf_conntrack_find_get(&tuple);
if (!h)
return -ENOENT;
@@ -736,7 +744,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
- h = nf_conntrack_find_get(&tuple, NULL);
+ h = nf_conntrack_find_get(&tuple);
if (!h)
return -ENOENT;
@@ -842,31 +850,30 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
if (help && help->helper) {
/* we had a helper before ... */
nf_ct_remove_expectations(ct);
- help->helper = NULL;
+ rcu_assign_pointer(help->helper, NULL);
}
return 0;
}
- if (!help) {
- /* FIXME: we need to reallocate and rehash */
- return -EBUSY;
- }
-
helper = __nf_conntrack_helper_find_byname(helpname);
if (helper == NULL)
return -EINVAL;
- if (help->helper == helper)
- return 0;
-
- if (help->helper)
- /* we had a helper before ... */
- nf_ct_remove_expectations(ct);
+ if (help) {
+ if (help->helper == helper)
+ return 0;
+ if (help->helper)
+ return -EBUSY;
+ /* need to zero data of old helper */
+ memset(&help->help, 0, sizeof(help->help));
+ } else {
+ help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
+ if (help == NULL)
+ return -ENOMEM;
+ }
- /* need to zero data of old helper */
- memset(&help->help, 0, sizeof(help->help));
- help->helper = helper;
+ rcu_assign_pointer(help->helper, helper);
return 0;
}
@@ -950,6 +957,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
struct nf_conn *ct;
int err = -EINVAL;
struct nf_conn_help *help;
+ struct nf_conntrack_helper *helper;
ct = nf_conntrack_alloc(otuple, rtuple);
if (ct == NULL || IS_ERR(ct))
@@ -979,15 +987,23 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
ct->mark = ntohl(*(__be32 *)NFA_DATA(cda[CTA_MARK-1]));
#endif
- help = nfct_help(ct);
- if (help)
- help->helper = nf_ct_helper_find_get(rtuple);
+ helper = nf_ct_helper_find_get(rtuple);
+ if (helper) {
+ help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
+ if (help == NULL) {
+ nf_ct_helper_put(helper);
+ err = -ENOMEM;
+ goto err;
+ }
+ /* not in hash table yet so not strictly necessary */
+ rcu_assign_pointer(help->helper, helper);
+ }
add_timer(&ct->timeout);
nf_conntrack_hash_insert(ct);
- if (help && help->helper)
- nf_ct_helper_put(help->helper);
+ if (helper)
+ nf_ct_helper_put(helper);
return 0;
@@ -1078,22 +1094,29 @@ nfattr_failure:
static inline int
ctnetlink_exp_dump_mask(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple,
- const struct nf_conntrack_tuple *mask)
+ const struct nf_conntrack_tuple_mask *mask)
{
int ret;
struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto;
- struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+ struct nf_conntrack_tuple m;
+ struct nfattr *nest_parms;
+
+ memset(&m, 0xFF, sizeof(m));
+ m.src.u.all = mask->src.u.all;
+ memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
+
+ nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
- ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
+ ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
nf_ct_l3proto_put(l3proto);
if (unlikely(ret < 0))
goto nfattr_failure;
l4proto = nf_ct_l4proto_find_get(tuple->src.l3num, tuple->dst.protonum);
- ret = ctnetlink_dump_tuples_proto(skb, mask, l4proto);
+ ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
nf_ct_l4proto_put(l4proto);
if (unlikely(ret < 0))
goto nfattr_failure;
@@ -1212,32 +1235,52 @@ nfattr_failure:
return NOTIFY_DONE;
}
#endif
+static int ctnetlink_exp_done(struct netlink_callback *cb)
+{
+ if (cb->args[1])
+ nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]);
+ return 0;
+}
static int
ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct nf_conntrack_expect *exp = NULL;
- struct list_head *i;
- u_int32_t *id = (u_int32_t *) &cb->args[0];
+ struct nf_conntrack_expect *exp, *last;
struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+ struct hlist_node *n;
u_int8_t l3proto = nfmsg->nfgen_family;
read_lock_bh(&nf_conntrack_lock);
- list_for_each_prev(i, &nf_conntrack_expect_list) {
- exp = (struct nf_conntrack_expect *) i;
- if (l3proto && exp->tuple.src.l3num != l3proto)
- continue;
- if (exp->id <= *id)
- continue;
- if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- IPCTNL_MSG_EXP_NEW,
- 1, exp) < 0)
- goto out;
- *id = exp->id;
+ last = (struct nf_conntrack_expect *)cb->args[1];
+ for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) {
+restart:
+ hlist_for_each_entry(exp, n, &nf_ct_expect_hash[cb->args[0]],
+ hnode) {
+ if (l3proto && exp->tuple.src.l3num != l3proto)
+ continue;
+ if (cb->args[1]) {
+ if (exp != last)
+ continue;
+ cb->args[1] = 0;
+ }
+ if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ IPCTNL_MSG_EXP_NEW,
+ 1, exp) < 0) {
+ atomic_inc(&exp->use);
+ cb->args[1] = (unsigned long)exp;
+ goto out;
+ }
+ }
+ if (cb->args[1]) {
+ cb->args[1] = 0;
+ goto restart;
+ }
}
out:
read_unlock_bh(&nf_conntrack_lock);
+ if (last)
+ nf_ct_expect_put(last);
return skb->len;
}
@@ -1264,7 +1307,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (nlh->nlmsg_flags & NLM_F_DUMP) {
return netlink_dump_start(ctnl, skb, nlh,
ctnetlink_exp_dump_table,
- ctnetlink_done);
+ ctnetlink_exp_done);
}
if (cda[CTA_EXPECT_MASTER-1])
@@ -1275,14 +1318,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (err < 0)
return err;
- exp = nf_conntrack_expect_find_get(&tuple);
+ exp = nf_ct_expect_find_get(&tuple);
if (!exp)
return -ENOENT;
if (cda[CTA_EXPECT_ID-1]) {
__be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
if (exp->id != ntohl(id)) {
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return -ENOENT;
}
}
@@ -1298,14 +1341,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if (err <= 0)
goto free;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
free:
kfree_skb(skb2);
out:
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return err;
}
@@ -1313,11 +1356,13 @@ static int
ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
struct nlmsghdr *nlh, struct nfattr *cda[])
{
- struct nf_conntrack_expect *exp, *tmp;
+ struct nf_conntrack_expect *exp;
struct nf_conntrack_tuple tuple;
struct nf_conntrack_helper *h;
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ struct hlist_node *n, *next;
u_int8_t u3 = nfmsg->nfgen_family;
+ unsigned int i;
int err;
if (nfattr_bad_size(cda, CTA_EXPECT_MAX, cta_min_exp))
@@ -1330,25 +1375,26 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return err;
/* bump usage count to 2 */
- exp = nf_conntrack_expect_find_get(&tuple);
+ exp = nf_ct_expect_find_get(&tuple);
if (!exp)
return -ENOENT;
if (cda[CTA_EXPECT_ID-1]) {
__be32 id = *(__be32 *)NFA_DATA(cda[CTA_EXPECT_ID-1]);
if (exp->id != ntohl(id)) {
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return -ENOENT;
}
}
/* after list removal, usage count == 1 */
- nf_conntrack_unexpect_related(exp);
+ nf_ct_unexpect_related(exp);
/* have to put what we 'get' above.
* after this line usage count == 0 */
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
} else if (cda[CTA_EXPECT_HELP_NAME-1]) {
char *name = NFA_DATA(cda[CTA_EXPECT_HELP_NAME-1]);
+ struct nf_conn_help *m_help;
/* delete all expectations for this helper */
write_lock_bh(&nf_conntrack_lock);
@@ -1357,24 +1403,30 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
write_unlock_bh(&nf_conntrack_lock);
return -EINVAL;
}
- list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
- list) {
- struct nf_conn_help *m_help = nfct_help(exp->master);
- if (m_help->helper == h
- && del_timer(&exp->timeout)) {
- nf_ct_unlink_expect(exp);
- nf_conntrack_expect_put(exp);
+ for (i = 0; i < nf_ct_expect_hsize; i++) {
+ hlist_for_each_entry_safe(exp, n, next,
+ &nf_ct_expect_hash[i],
+ hnode) {
+ m_help = nfct_help(exp->master);
+ if (m_help->helper == h
+ && del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_ct_expect_put(exp);
+ }
}
}
write_unlock_bh(&nf_conntrack_lock);
} else {
/* This basically means we have to flush everything*/
write_lock_bh(&nf_conntrack_lock);
- list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list,
- list) {
- if (del_timer(&exp->timeout)) {
- nf_ct_unlink_expect(exp);
- nf_conntrack_expect_put(exp);
+ for (i = 0; i < nf_ct_expect_hsize; i++) {
+ hlist_for_each_entry_safe(exp, n, next,
+ &nf_ct_expect_hash[i],
+ hnode) {
+ if (del_timer(&exp->timeout)) {
+ nf_ct_unlink_expect(exp);
+ nf_ct_expect_put(exp);
+ }
}
}
write_unlock_bh(&nf_conntrack_lock);
@@ -1410,7 +1462,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
return err;
/* Look for master conntrack of this expectation */
- h = nf_conntrack_find_get(&master_tuple, NULL);
+ h = nf_conntrack_find_get(&master_tuple);
if (!h)
return -ENOENT;
ct = nf_ct_tuplehash_to_ctrack(h);
@@ -1422,7 +1474,7 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
goto out;
}
- exp = nf_conntrack_expect_alloc(ct);
+ exp = nf_ct_expect_alloc(ct);
if (!exp) {
err = -ENOMEM;
goto out;
@@ -1433,10 +1485,11 @@ ctnetlink_create_expect(struct nfattr *cda[], u_int8_t u3)
exp->master = ct;
exp->helper = NULL;
memcpy(&exp->tuple, &tuple, sizeof(struct nf_conntrack_tuple));
- memcpy(&exp->mask, &mask, sizeof(struct nf_conntrack_tuple));
+ memcpy(&exp->mask.src.u3, &mask.src.u3, sizeof(exp->mask.src.u3));
+ exp->mask.src.u.all = mask.src.u.all;
- err = nf_conntrack_expect_related(exp);
- nf_conntrack_expect_put(exp);
+ err = nf_ct_expect_related(exp);
+ nf_ct_expect_put(exp);
out:
nf_ct_put(nf_ct_tuplehash_to_ctrack(h));
@@ -1466,7 +1519,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
return err;
write_lock_bh(&nf_conntrack_lock);
- exp = __nf_conntrack_expect_find(&tuple);
+ exp = __nf_ct_expect_find(&tuple);
if (!exp) {
write_unlock_bh(&nf_conntrack_lock);
@@ -1556,7 +1609,7 @@ static int __init ctnetlink_init(void)
goto err_unreg_exp_subsys;
}
- ret = nf_conntrack_expect_register_notifier(&ctnl_notifier_exp);
+ ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp);
if (ret < 0) {
printk("ctnetlink_init: cannot expect register notifier.\n");
goto err_unreg_notifier;
@@ -1582,7 +1635,7 @@ static void __exit ctnetlink_exit(void)
printk("ctnetlink: unregistering from nfnetlink.\n");
#ifdef CONFIG_NF_CONNTRACK_EVENTS
- nf_conntrack_expect_unregister_notifier(&ctnl_notifier_exp);
+ nf_ct_expect_unregister_notifier(&ctnl_notifier_exp);
nf_conntrack_unregister_notifier(&ctnl_notifier);
#endif
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 115bcb5d5a7..b0804199ab5 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -65,7 +65,7 @@ void
struct nf_conntrack_expect *exp) __read_mostly;
EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_expectfn);
-#if 0
+#ifdef DEBUG
/* PptpControlMessageType names */
const char *pptp_msg_name[] = {
"UNKNOWN_MESSAGE",
@@ -86,9 +86,6 @@ const char *pptp_msg_name[] = {
"SET_LINK_INFO"
};
EXPORT_SYMBOL(pptp_msg_name);
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
-#else
-#define DEBUGP(format, args...)
#endif
#define SECS *HZ
@@ -102,7 +99,7 @@ static void pptp_expectfn(struct nf_conn *ct,
struct nf_conntrack_expect *exp)
{
typeof(nf_nat_pptp_hook_expectfn) nf_nat_pptp_expectfn;
- DEBUGP("increasing timeouts\n");
+ pr_debug("increasing timeouts\n");
/* increase timeout of GRE data channel conntrack entry */
ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
@@ -121,17 +118,17 @@ static void pptp_expectfn(struct nf_conn *ct,
/* obviously this tuple inversion only works until you do NAT */
nf_ct_invert_tuplepr(&inv_t, &exp->tuple);
- DEBUGP("trying to unexpect other dir: ");
+ pr_debug("trying to unexpect other dir: ");
NF_CT_DUMP_TUPLE(&inv_t);
- exp_other = nf_conntrack_expect_find_get(&inv_t);
+ exp_other = nf_ct_expect_find_get(&inv_t);
if (exp_other) {
/* delete other expectation. */
- DEBUGP("found\n");
- nf_conntrack_unexpect_related(exp_other);
- nf_conntrack_expect_put(exp_other);
+ pr_debug("found\n");
+ nf_ct_unexpect_related(exp_other);
+ nf_ct_expect_put(exp_other);
} else {
- DEBUGP("not found\n");
+ pr_debug("not found\n");
}
}
rcu_read_unlock();
@@ -143,13 +140,13 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
struct nf_conntrack_expect *exp;
struct nf_conn *sibling;
- DEBUGP("trying to timeout ct or exp for tuple ");
+ pr_debug("trying to timeout ct or exp for tuple ");
NF_CT_DUMP_TUPLE(t);
- h = nf_conntrack_find_get(t, NULL);
+ h = nf_conntrack_find_get(t);
if (h) {
sibling = nf_ct_tuplehash_to_ctrack(h);
- DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
+ pr_debug("setting timeout of conntrack %p to 0\n", sibling);
sibling->proto.gre.timeout = 0;
sibling->proto.gre.stream_timeout = 0;
if (del_timer(&sibling->timeout))
@@ -157,11 +154,11 @@ static int destroy_sibling_or_exp(const struct nf_conntrack_tuple *t)
nf_ct_put(sibling);
return 1;
} else {
- exp = nf_conntrack_expect_find_get(t);
+ exp = nf_ct_expect_find_get(t);
if (exp) {
- DEBUGP("unexpect_related of expect %p\n", exp);
- nf_conntrack_unexpect_related(exp);
- nf_conntrack_expect_put(exp);
+ pr_debug("unexpect_related of expect %p\n", exp);
+ nf_ct_unexpect_related(exp);
+ nf_ct_expect_put(exp);
return 1;
}
}
@@ -182,7 +179,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
if (!destroy_sibling_or_exp(&t))
- DEBUGP("failed to timeout original pns->pac ct/exp\n");
+ pr_debug("failed to timeout original pns->pac ct/exp\n");
/* try reply (pac->pns) tuple */
memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
@@ -190,7 +187,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id;
t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id;
if (!destroy_sibling_or_exp(&t))
- DEBUGP("failed to timeout reply pac->pns ct/exp\n");
+ pr_debug("failed to timeout reply pac->pns ct/exp\n");
}
/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
@@ -201,36 +198,36 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
int ret = 1;
typeof(nf_nat_pptp_hook_exp_gre) nf_nat_pptp_exp_gre;
- exp_orig = nf_conntrack_expect_alloc(ct);
+ exp_orig = nf_ct_expect_alloc(ct);
if (exp_orig == NULL)
goto out;
- exp_reply = nf_conntrack_expect_alloc(ct);
+ exp_reply = nf_ct_expect_alloc(ct);
if (exp_reply == NULL)
goto out_put_orig;
/* original direction, PNS->PAC */
dir = IP_CT_DIR_ORIGINAL;
- nf_conntrack_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
- &ct->tuplehash[dir].tuple.src.u3,
- &ct->tuplehash[dir].tuple.dst.u3,
- IPPROTO_GRE, &peer_callid, &callid);
+ nf_ct_expect_init(exp_orig, ct->tuplehash[dir].tuple.src.l3num,
+ &ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[dir].tuple.dst.u3,
+ IPPROTO_GRE, &peer_callid, &callid);
exp_orig->expectfn = pptp_expectfn;
/* reply direction, PAC->PNS */
dir = IP_CT_DIR_REPLY;
- nf_conntrack_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
- &ct->tuplehash[dir].tuple.src.u3,
- &ct->tuplehash[dir].tuple.dst.u3,
- IPPROTO_GRE, &callid, &peer_callid);
+ nf_ct_expect_init(exp_reply, ct->tuplehash[dir].tuple.src.l3num,
+ &ct->tuplehash[dir].tuple.src.u3,
+ &ct->tuplehash[dir].tuple.dst.u3,
+ IPPROTO_GRE, &callid, &peer_callid);
exp_reply->expectfn = pptp_expectfn;
nf_nat_pptp_exp_gre = rcu_dereference(nf_nat_pptp_hook_exp_gre);
if (nf_nat_pptp_exp_gre && ct->status & IPS_NAT_MASK)
nf_nat_pptp_exp_gre(exp_orig, exp_reply);
- if (nf_conntrack_expect_related(exp_orig) != 0)
+ if (nf_ct_expect_related(exp_orig) != 0)
goto out_put_both;
- if (nf_conntrack_expect_related(exp_reply) != 0)
+ if (nf_ct_expect_related(exp_reply) != 0)
goto out_unexpect_orig;
/* Add GRE keymap entries */
@@ -243,16 +240,16 @@ static int exp_gre(struct nf_conn *ct, __be16 callid, __be16 peer_callid)
ret = 0;
out_put_both:
- nf_conntrack_expect_put(exp_reply);
+ nf_ct_expect_put(exp_reply);
out_put_orig:
- nf_conntrack_expect_put(exp_orig);
+ nf_ct_expect_put(exp_orig);
out:
return ret;
out_unexpect_both:
- nf_conntrack_unexpect_related(exp_reply);
+ nf_ct_unexpect_related(exp_reply);
out_unexpect_orig:
- nf_conntrack_unexpect_related(exp_orig);
+ nf_ct_unexpect_related(exp_orig);
goto out_put_both;
}
@@ -270,7 +267,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
typeof(nf_nat_pptp_hook_inbound) nf_nat_pptp_inbound;
msg = ntohs(ctlh->messageType);
- DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
+ pr_debug("inbound control message %s\n", pptp_msg_name[msg]);
switch (msg) {
case PPTP_START_SESSION_REPLY:
@@ -305,8 +302,8 @@ pptp_inbound_pkt(struct sk_buff **pskb,
pcid = pptpReq->ocack.peersCallID;
if (info->pns_call_id != pcid)
goto invalid;
- DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
- ntohs(cid), ntohs(pcid));
+ pr_debug("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
+ ntohs(cid), ntohs(pcid));
if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) {
info->cstate = PPTP_CALL_OUT_CONF;
@@ -322,7 +319,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
goto invalid;
cid = pptpReq->icreq.callID;
- DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+ pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
info->cstate = PPTP_CALL_IN_REQ;
info->pac_call_id = cid;
break;
@@ -341,7 +338,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
if (info->pns_call_id != pcid)
goto invalid;
- DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
+ pr_debug("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid));
info->cstate = PPTP_CALL_IN_CONF;
/* we expect a GRE connection from PAC to PNS */
@@ -351,7 +348,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
case PPTP_CALL_DISCONNECT_NOTIFY:
/* server confirms disconnect */
cid = pptpReq->disc.callID;
- DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+ pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
info->cstate = PPTP_CALL_NONE;
/* untrack this call id, unexpect GRE packets */
@@ -374,11 +371,11 @@ pptp_inbound_pkt(struct sk_buff **pskb,
return NF_ACCEPT;
invalid:
- DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
- "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
- msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
- msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
- ntohs(info->pns_call_id), ntohs(info->pac_call_id));
+ pr_debug("invalid %s: type=%d cid=%u pcid=%u "
+ "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
+ msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
+ msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
+ ntohs(info->pns_call_id), ntohs(info->pac_call_id));
return NF_ACCEPT;
}
@@ -396,7 +393,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
typeof(nf_nat_pptp_hook_outbound) nf_nat_pptp_outbound;
msg = ntohs(ctlh->messageType);
- DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
+ pr_debug("outbound control message %s\n", pptp_msg_name[msg]);
switch (msg) {
case PPTP_START_SESSION_REQUEST:
@@ -418,7 +415,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
info->cstate = PPTP_CALL_OUT_REQ;
/* track PNS call id */
cid = pptpReq->ocreq.callID;
- DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
+ pr_debug("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid));
info->pns_call_id = cid;
break;
@@ -432,8 +429,8 @@ pptp_outbound_pkt(struct sk_buff **pskb,
pcid = pptpReq->icack.peersCallID;
if (info->pac_call_id != pcid)
goto invalid;
- DEBUGP("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
- ntohs(cid), ntohs(pcid));
+ pr_debug("%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
+ ntohs(cid), ntohs(pcid));
if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) {
/* part two of the three-way handshake */
@@ -469,11 +466,11 @@ pptp_outbound_pkt(struct sk_buff **pskb,
return NF_ACCEPT;
invalid:
- DEBUGP("invalid %s: type=%d cid=%u pcid=%u "
- "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
- msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
- msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
- ntohs(info->pns_call_id), ntohs(info->pac_call_id));
+ pr_debug("invalid %s: type=%d cid=%u pcid=%u "
+ "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
+ msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
+ msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate,
+ ntohs(info->pns_call_id), ntohs(info->pac_call_id));
return NF_ACCEPT;
}
@@ -524,7 +521,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
if (!pptph) {
- DEBUGP("no full PPTP header, can't track\n");
+ pr_debug("no full PPTP header, can't track\n");
return NF_ACCEPT;
}
nexthdr_off += sizeof(_pptph);
@@ -533,7 +530,7 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
/* if it's not a control message we can't do anything with it */
if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
- DEBUGP("not a control packet\n");
+ pr_debug("not a control packet\n");
return NF_ACCEPT;
}
@@ -569,8 +566,8 @@ conntrack_pptp_help(struct sk_buff **pskb, unsigned int protoff,
/* server -> client (PAC -> PNS) */
ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
ctinfo);
- DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
- oldsstate, info->sstate, oldcstate, info->cstate);
+ pr_debug("sstate: %d->%d, cstate: %d->%d\n",
+ oldsstate, info->sstate, oldcstate, info->cstate);
spin_unlock_bh(&nf_pptp_lock);
return ret;
@@ -585,9 +582,6 @@ static struct nf_conntrack_helper pptp __read_mostly = {
.tuple.src.l3num = AF_INET,
.tuple.src.u.tcp.port = __constant_htons(PPTP_CONTROL_PORT),
.tuple.dst.protonum = IPPROTO_TCP,
- .mask.src.l3num = 0xffff,
- .mask.src.u.tcp.port = __constant_htons(0xffff),
- .mask.dst.protonum = 0xff,
.help = conntrack_pptp_help,
.destroy = pptp_destroy_siblings,
};
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index 6faf1bed722..d8b501878d9 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -98,7 +98,7 @@ static struct ctl_table generic_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif /* CONFIG_SYSCTL */
-struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
{
.l3proto = PF_UNSPEC,
.l4proto = 0,
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 5434472420f..bdbead8a7a8 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -40,12 +40,6 @@
#define GRE_TIMEOUT (30 * HZ)
#define GRE_STREAM_TIMEOUT (180 * HZ)
-#if 0
-#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
-#else
-#define DEBUGP(x, args...)
-#endif
-
static DEFINE_RWLOCK(nf_ct_gre_lock);
static LIST_HEAD(gre_keymap_list);
@@ -87,7 +81,7 @@ static __be16 gre_keymap_lookup(struct nf_conntrack_tuple *t)
}
read_unlock_bh(&nf_ct_gre_lock);
- DEBUGP("lookup src key 0x%x for ", key);
+ pr_debug("lookup src key 0x%x for ", key);
NF_CT_DUMP_TUPLE(t);
return key;
@@ -100,7 +94,6 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
struct nf_conn_help *help = nfct_help(ct);
struct nf_ct_gre_keymap **kmp, *km;
- BUG_ON(strcmp(help->helper->name, "pptp"));
kmp = &help->help.ct_pptp_info.keymap[dir];
if (*kmp) {
/* check whether it's a retransmission */
@@ -108,8 +101,8 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
if (gre_key_cmpfn(km, t) && km == *kmp)
return 0;
}
- DEBUGP("trying to override keymap_%s for ct %p\n",
- dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
+ pr_debug("trying to override keymap_%s for ct %p\n",
+ dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
return -EEXIST;
}
@@ -119,7 +112,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
memcpy(&km->tuple, t, sizeof(*t));
*kmp = km;
- DEBUGP("adding new entry %p: ", km);
+ pr_debug("adding new entry %p: ", km);
NF_CT_DUMP_TUPLE(&km->tuple);
write_lock_bh(&nf_ct_gre_lock);
@@ -136,14 +129,13 @@ void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
struct nf_conn_help *help = nfct_help(ct);
enum ip_conntrack_dir dir;
- DEBUGP("entering for ct %p\n", ct);
- BUG_ON(strcmp(help->helper->name, "pptp"));
+ pr_debug("entering for ct %p\n", ct);
write_lock_bh(&nf_ct_gre_lock);
for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
if (help->help.ct_pptp_info.keymap[dir]) {
- DEBUGP("removing %p from list\n",
- help->help.ct_pptp_info.keymap[dir]);
+ pr_debug("removing %p from list\n",
+ help->help.ct_pptp_info.keymap[dir]);
list_del(&help->help.ct_pptp_info.keymap[dir]->list);
kfree(help->help.ct_pptp_info.keymap[dir]);
help->help.ct_pptp_info.keymap[dir] = NULL;
@@ -188,7 +180,7 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb,
return 1;
if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
- DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
+ pr_debug("GRE_VERSION_PPTP but unknown proto\n");
return 0;
}
@@ -244,7 +236,7 @@ static int gre_packet(struct nf_conn *ct,
static int gre_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff)
{
- DEBUGP(": ");
+ pr_debug(": ");
NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
/* initialize to sane value. Ideally a conntrack helper
@@ -260,16 +252,16 @@ static int gre_new(struct nf_conn *ct, const struct sk_buff *skb,
static void gre_destroy(struct nf_conn *ct)
{
struct nf_conn *master = ct->master;
- DEBUGP(" entering\n");
+ pr_debug(" entering\n");
if (!master)
- DEBUGP("no master !?!\n");
+ pr_debug("no master !?!\n");
else
nf_ct_gre_keymap_destroy(master);
}
/* protocol helper struct */
-static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = {
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
.l3proto = AF_INET,
.l4proto = IPPROTO_GRE,
.name = "gre",
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index 0d3254b974c..04192acc7c4 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -25,12 +25,6 @@
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
-#if 0
-#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Protects conntrack->proto.sctp */
static DEFINE_RWLOCK(sctp_lock);
@@ -151,9 +145,6 @@ static int sctp_pkt_to_tuple(const struct sk_buff *skb,
{
sctp_sctphdr_t _hdr, *hp;
- DEBUGP(__FUNCTION__);
- DEBUGP("\n");
-
/* Actually only need first 8 bytes. */
hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
if (hp == NULL)
@@ -167,9 +158,6 @@ static int sctp_pkt_to_tuple(const struct sk_buff *skb,
static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
- DEBUGP(__FUNCTION__);
- DEBUGP("\n");
-
tuple->src.u.sctp.port = orig->dst.u.sctp.port;
tuple->dst.u.sctp.port = orig->src.u.sctp.port;
return 1;
@@ -179,9 +167,6 @@ static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
static int sctp_print_tuple(struct seq_file *s,
const struct nf_conntrack_tuple *tuple)
{
- DEBUGP(__FUNCTION__);
- DEBUGP("\n");
-
return seq_printf(s, "sport=%hu dport=%hu ",
ntohs(tuple->src.u.sctp.port),
ntohs(tuple->dst.u.sctp.port));
@@ -193,9 +178,6 @@ static int sctp_print_conntrack(struct seq_file *s,
{
enum sctp_conntrack state;
- DEBUGP(__FUNCTION__);
- DEBUGP("\n");
-
read_lock_bh(&sctp_lock);
state = conntrack->proto.sctp.state;
read_unlock_bh(&sctp_lock);
@@ -219,13 +201,10 @@ static int do_basic_checks(struct nf_conn *conntrack,
sctp_chunkhdr_t _sch, *sch;
int flag;
- DEBUGP(__FUNCTION__);
- DEBUGP("\n");
-
flag = 0;
for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
- DEBUGP("Chunk Num: %d Type: %d\n", count, sch->type);
+ pr_debug("Chunk Num: %d Type: %d\n", count, sch->type);
if (sch->type == SCTP_CID_INIT
|| sch->type == SCTP_CID_INIT_ACK
@@ -242,7 +221,7 @@ static int do_basic_checks(struct nf_conn *conntrack,
|| sch->type == SCTP_CID_COOKIE_ECHO
|| flag)
&& count !=0) || !sch->length) {
- DEBUGP("Basic checks failed\n");
+ pr_debug("Basic checks failed\n");
return 1;
}
@@ -251,7 +230,7 @@ static int do_basic_checks(struct nf_conn *conntrack,
}
}
- DEBUGP("Basic checks passed\n");
+ pr_debug("Basic checks passed\n");
return count == 0;
}
@@ -261,50 +240,47 @@ static int new_state(enum ip_conntrack_dir dir,
{
int i;
- DEBUGP(__FUNCTION__);
- DEBUGP("\n");
-
- DEBUGP("Chunk type: %d\n", chunk_type);
+ pr_debug("Chunk type: %d\n", chunk_type);
switch (chunk_type) {
case SCTP_CID_INIT:
- DEBUGP("SCTP_CID_INIT\n");
+ pr_debug("SCTP_CID_INIT\n");
i = 0; break;
case SCTP_CID_INIT_ACK:
- DEBUGP("SCTP_CID_INIT_ACK\n");
+ pr_debug("SCTP_CID_INIT_ACK\n");
i = 1; break;
case SCTP_CID_ABORT:
- DEBUGP("SCTP_CID_ABORT\n");
+ pr_debug("SCTP_CID_ABORT\n");
i = 2; break;
case SCTP_CID_SHUTDOWN:
- DEBUGP("SCTP_CID_SHUTDOWN\n");
+ pr_debug("SCTP_CID_SHUTDOWN\n");
i = 3; break;
case SCTP_CID_SHUTDOWN_ACK:
- DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
+ pr_debug("SCTP_CID_SHUTDOWN_ACK\n");
i = 4; break;
case SCTP_CID_ERROR:
- DEBUGP("SCTP_CID_ERROR\n");
+ pr_debug("SCTP_CID_ERROR\n");
i = 5; break;
case SCTP_CID_COOKIE_ECHO:
- DEBUGP("SCTP_CID_COOKIE_ECHO\n");
+ pr_debug("SCTP_CID_COOKIE_ECHO\n");
i = 6; break;
case SCTP_CID_COOKIE_ACK:
- DEBUGP("SCTP_CID_COOKIE_ACK\n");
+ pr_debug("SCTP_CID_COOKIE_ACK\n");
i = 7; break;
case SCTP_CID_SHUTDOWN_COMPLETE:
- DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
+ pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n");
i = 8; break;
default:
/* Other chunks like DATA, SACK, HEARTBEAT and
its ACK do not cause a change in state */
- DEBUGP("Unknown chunk type, Will stay in %s\n",
- sctp_conntrack_names[cur_state]);
+ pr_debug("Unknown chunk type, Will stay in %s\n",
+ sctp_conntrack_names[cur_state]);
return cur_state;
}
- DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
- dir, sctp_conntrack_names[cur_state], chunk_type,
- sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
+ pr_debug("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
+ dir, sctp_conntrack_names[cur_state], chunk_type,
+ sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
return sctp_conntracks[dir][i][cur_state];
}
@@ -323,9 +299,6 @@ static int sctp_packet(struct nf_conn *conntrack,
u_int32_t offset, count;
char map[256 / sizeof (char)] = {0};
- DEBUGP(__FUNCTION__);
- DEBUGP("\n");
-
sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
if (sh == NULL)
return -1;
@@ -340,7 +313,7 @@ static int sctp_packet(struct nf_conn *conntrack,
&& !test_bit(SCTP_CID_ABORT, (void *)map)
&& !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
&& (sh->vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
- DEBUGP("Verification tag check failed\n");
+ pr_debug("Verification tag check failed\n");
return -1;
}
@@ -385,8 +358,9 @@ static int sctp_packet(struct nf_conn *conntrack,
/* Invalid */
if (newconntrack == SCTP_CONNTRACK_MAX) {
- DEBUGP("nf_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
- CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
+ pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
+ "conntrack=%u\n",
+ CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
write_unlock_bh(&sctp_lock);
return -1;
}
@@ -402,8 +376,8 @@ static int sctp_packet(struct nf_conn *conntrack,
write_unlock_bh(&sctp_lock);
return -1;
}
- DEBUGP("Setting vtag %x for dir %d\n",
- ih->init_tag, !CTINFO2DIR(ctinfo));
+ pr_debug("Setting vtag %x for dir %d\n",
+ ih->init_tag, !CTINFO2DIR(ctinfo));
conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
}
@@ -418,7 +392,7 @@ static int sctp_packet(struct nf_conn *conntrack,
if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
&& CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
&& newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
- DEBUGP("Setting assured bit\n");
+ pr_debug("Setting assured bit\n");
set_bit(IPS_ASSURED_BIT, &conntrack->status);
nf_conntrack_event_cache(IPCT_STATUS, skb);
}
@@ -436,9 +410,6 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
u_int32_t offset, count;
char map[256 / sizeof (char)] = {0};
- DEBUGP(__FUNCTION__);
- DEBUGP("\n");
-
sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
if (sh == NULL)
return 0;
@@ -460,8 +431,9 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
SCTP_CONNTRACK_NONE, sch->type);
/* Invalid: delete conntrack */
- if (newconntrack == SCTP_CONNTRACK_MAX) {
- DEBUGP("nf_conntrack_sctp: invalid new deleting.\n");
+ if (newconntrack == SCTP_CONNTRACK_NONE ||
+ newconntrack == SCTP_CONNTRACK_MAX) {
+ pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
return 0;
}
@@ -475,8 +447,8 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
if (ih == NULL)
return 0;
- DEBUGP("Setting vtag %x for new conn\n",
- ih->init_tag);
+ pr_debug("Setting vtag %x for new conn\n",
+ ih->init_tag);
conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
ih->init_tag;
@@ -488,8 +460,8 @@ static int sctp_new(struct nf_conn *conntrack, const struct sk_buff *skb,
/* If it is a shutdown ack OOTB packet, we expect a return
shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
else {
- DEBUGP("Setting vtag %x for new conn OOTB\n",
- sh->vtag);
+ pr_debug("Setting vtag %x for new conn OOTB\n",
+ sh->vtag);
conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
}
@@ -629,7 +601,7 @@ static struct ctl_table sctp_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif
-struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
.l3proto = PF_INET,
.l4proto = IPPROTO_SCTP,
.name = "sctp",
@@ -650,7 +622,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
#endif
};
-struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = {
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
.l3proto = PF_INET6,
.l4proto = IPPROTO_SCTP,
.name = "sctp",
@@ -688,8 +660,6 @@ int __init nf_conntrack_proto_sctp_init(void)
cleanup_sctp4:
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
out:
- DEBUGP("SCTP conntrack module loading %s\n",
- ret ? "failed": "succeeded");
return ret;
}
@@ -697,7 +667,6 @@ void __exit nf_conntrack_proto_sctp_fini(void)
{
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
- DEBUGP("SCTP conntrack module unloaded\n");
}
module_init(nf_conntrack_proto_sctp_init);
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index ccdd5d231e0..87ad3ccf8af 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -26,13 +26,6 @@
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
-#if 0
-#define DEBUGP printk
-#define DEBUGP_VARS
-#else
-#define DEBUGP(format, args...)
-#endif
-
/* Protects conntrack->proto.tcp */
static DEFINE_RWLOCK(tcp_lock);
@@ -496,7 +489,8 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
}
}
-static int tcp_in_window(struct ip_ct_tcp *state,
+static int tcp_in_window(struct nf_conn *ct,
+ struct ip_ct_tcp *state,
enum ip_conntrack_dir dir,
unsigned int index,
const struct sk_buff *skb,
@@ -506,6 +500,7 @@ static int tcp_in_window(struct ip_ct_tcp *state,
{
struct ip_ct_tcp_state *sender = &state->seen[dir];
struct ip_ct_tcp_state *receiver = &state->seen[!dir];
+ struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
__u32 seq, ack, sack, end, win, swin;
int res;
@@ -520,18 +515,17 @@ static int tcp_in_window(struct ip_ct_tcp *state,
if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
tcp_sack(skb, dataoff, tcph, &sack);
- DEBUGP("tcp_in_window: START\n");
- DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
- "seq=%u ack=%u sack=%u win=%u end=%u\n",
- NIPQUAD(iph->saddr), ntohs(tcph->source),
- NIPQUAD(iph->daddr), ntohs(tcph->dest),
- seq, ack, sack, win, end);
- DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
- "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
- sender->td_end, sender->td_maxend, sender->td_maxwin,
- sender->td_scale,
- receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
- receiver->td_scale);
+ pr_debug("tcp_in_window: START\n");
+ pr_debug("tcp_in_window: ");
+ NF_CT_DUMP_TUPLE(tuple);
+ pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n",
+ seq, ack, sack, win, end);
+ pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+ "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+ sender->td_end, sender->td_maxend, sender->td_maxwin,
+ sender->td_scale,
+ receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+ receiver->td_scale);
if (sender->td_end == 0) {
/*
@@ -609,23 +603,22 @@ static int tcp_in_window(struct ip_ct_tcp *state,
*/
seq = end = sender->td_end;
- DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
- "seq=%u ack=%u sack =%u win=%u end=%u\n",
- NIPQUAD(iph->saddr), ntohs(tcph->source),
- NIPQUAD(iph->daddr), ntohs(tcph->dest),
- seq, ack, sack, win, end);
- DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
- "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
- sender->td_end, sender->td_maxend, sender->td_maxwin,
- sender->td_scale,
- receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
- receiver->td_scale);
-
- DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
- before(seq, sender->td_maxend + 1),
- after(end, sender->td_end - receiver->td_maxwin - 1),
- before(sack, receiver->td_end + 1),
- after(ack, receiver->td_end - MAXACKWINDOW(sender)));
+ pr_debug("tcp_in_window: ");
+ NF_CT_DUMP_TUPLE(tuple);
+ pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n",
+ seq, ack, sack, win, end);
+ pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+ "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+ sender->td_end, sender->td_maxend, sender->td_maxwin,
+ sender->td_scale,
+ receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+ receiver->td_scale);
+
+ pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
+ before(seq, sender->td_maxend + 1),
+ after(end, sender->td_end - receiver->td_maxwin - 1),
+ before(sack, receiver->td_end + 1),
+ after(ack, receiver->td_end - MAXACKWINDOW(sender)));
if (before(seq, sender->td_maxend + 1) &&
after(end, sender->td_end - receiver->td_maxwin - 1) &&
@@ -694,10 +687,10 @@ static int tcp_in_window(struct ip_ct_tcp *state,
: "SEQ is over the upper bound (over the window of the receiver)");
}
- DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
- "receiver end=%u maxend=%u maxwin=%u\n",
- res, sender->td_end, sender->td_maxend, sender->td_maxwin,
- receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
+ pr_debug("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
+ "receiver end=%u maxend=%u maxwin=%u\n",
+ res, sender->td_end, sender->td_maxend, sender->td_maxwin,
+ receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
return res;
}
@@ -711,11 +704,9 @@ void nf_conntrack_tcp_update(struct sk_buff *skb,
int dir)
{
struct tcphdr *tcph = (void *)skb->data + dataoff;
- __u32 end;
-#ifdef DEBUGP_VARS
struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir];
struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir];
-#endif
+ __u32 end;
end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph);
@@ -727,12 +718,12 @@ void nf_conntrack_tcp_update(struct sk_buff *skb,
conntrack->proto.tcp.seen[dir].td_end = end;
conntrack->proto.tcp.last_end = end;
write_unlock_bh(&tcp_lock);
- DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
- "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
- sender->td_end, sender->td_maxend, sender->td_maxwin,
- sender->td_scale,
- receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
- receiver->td_scale);
+ pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
+ "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+ sender->td_end, sender->td_maxend, sender->td_maxwin,
+ sender->td_scale,
+ receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+ receiver->td_scale);
}
EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update);
#endif
@@ -823,6 +814,7 @@ static int tcp_packet(struct nf_conn *conntrack,
int pf,
unsigned int hooknum)
{
+ struct nf_conntrack_tuple *tuple;
enum tcp_conntrack new_state, old_state;
enum ip_conntrack_dir dir;
struct tcphdr *th, _tcph;
@@ -837,6 +829,7 @@ static int tcp_packet(struct nf_conn *conntrack,
dir = CTINFO2DIR(ctinfo);
index = get_conntrack_index(th);
new_state = tcp_conntracks[dir][index][old_state];
+ tuple = &conntrack->tuplehash[dir].tuple;
switch (new_state) {
case TCP_CONNTRACK_IGNORE:
@@ -880,9 +873,8 @@ static int tcp_packet(struct nf_conn *conntrack,
return NF_ACCEPT;
case TCP_CONNTRACK_MAX:
/* Invalid packet */
- DEBUGP("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
- dir, get_conntrack_index(th),
- old_state);
+ pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
+ dir, get_conntrack_index(th), old_state);
write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
@@ -933,7 +925,7 @@ static int tcp_packet(struct nf_conn *conntrack,
break;
}
- if (!tcp_in_window(&conntrack->proto.tcp, dir, index,
+ if (!tcp_in_window(conntrack, &conntrack->proto.tcp, dir, index,
skb, dataoff, th, pf)) {
write_unlock_bh(&tcp_lock);
return -NF_ACCEPT;
@@ -942,13 +934,12 @@ static int tcp_packet(struct nf_conn *conntrack,
/* From now on we have got in-window packets */
conntrack->proto.tcp.last_index = index;
- DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
- "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
- NIPQUAD(iph->saddr), ntohs(th->source),
- NIPQUAD(iph->daddr), ntohs(th->dest),
- (th->syn ? 1 : 0), (th->ack ? 1 : 0),
- (th->fin ? 1 : 0), (th->rst ? 1 : 0),
- old_state, new_state);
+ pr_debug("tcp_conntracks: ");
+ NF_CT_DUMP_TUPLE(tuple);
+ pr_debug("syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
+ (th->syn ? 1 : 0), (th->ack ? 1 : 0),
+ (th->fin ? 1 : 0), (th->rst ? 1 : 0),
+ old_state, new_state);
conntrack->proto.tcp.state = new_state;
if (old_state != new_state
@@ -997,10 +988,8 @@ static int tcp_new(struct nf_conn *conntrack,
{
enum tcp_conntrack new_state;
struct tcphdr *th, _tcph;
-#ifdef DEBUGP_VARS
struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1];
-#endif
th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
BUG_ON(th == NULL);
@@ -1012,7 +1001,7 @@ static int tcp_new(struct nf_conn *conntrack,
/* Invalid: delete conntrack */
if (new_state >= TCP_CONNTRACK_MAX) {
- DEBUGP("nf_ct_tcp: invalid new deleting.\n");
+ pr_debug("nf_ct_tcp: invalid new deleting.\n");
return 0;
}
@@ -1065,12 +1054,12 @@ static int tcp_new(struct nf_conn *conntrack,
conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
conntrack->proto.tcp.last_index = TCP_NONE_SET;
- DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
- "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
- sender->td_end, sender->td_maxend, sender->td_maxwin,
- sender->td_scale,
- receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
- receiver->td_scale);
+ pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
+ "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+ sender->td_end, sender->td_maxend, sender->td_maxwin,
+ sender->td_scale,
+ receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+ receiver->td_scale);
return 1;
}
@@ -1383,7 +1372,7 @@ static struct ctl_table tcp_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif /* CONFIG_SYSCTL */
-struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly =
{
.l3proto = PF_INET,
.l4proto = IPPROTO_TCP,
@@ -1412,7 +1401,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 =
};
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_tcp4);
-struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly =
{
.l3proto = PF_INET6,
.l4proto = IPPROTO_TCP,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 3620ecc095f..13d94a02572 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -191,7 +191,7 @@ static struct ctl_table udp_compat_sysctl_table[] = {
#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
#endif /* CONFIG_SYSCTL */
-struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
{
.l3proto = PF_INET,
.l4proto = IPPROTO_UDP,
@@ -218,7 +218,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 =
};
EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_udp4);
-struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 =
+struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
{
.l3proto = PF_INET6,
.l4proto = IPPROTO_UDP,
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
new file mode 100644
index 00000000000..93e747b5396
--- /dev/null
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -0,0 +1,266 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * 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/types.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/udp.h>
+#include <linux/seq_file.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+
+static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
+static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
+
+static int udplite_pkt_to_tuple(const struct sk_buff *skb,
+ unsigned int dataoff,
+ struct nf_conntrack_tuple *tuple)
+{
+ struct udphdr _hdr, *hp;
+
+ hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ if (hp == NULL)
+ return 0;
+
+ tuple->src.u.udp.port = hp->source;
+ tuple->dst.u.udp.port = hp->dest;
+ return 1;
+}
+
+static int udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_tuple *orig)
+{
+ tuple->src.u.udp.port = orig->dst.u.udp.port;
+ tuple->dst.u.udp.port = orig->src.u.udp.port;
+ return 1;
+}
+
+/* Print out the per-protocol part of the tuple. */
+static int udplite_print_tuple(struct seq_file *s,
+ const struct nf_conntrack_tuple *tuple)
+{
+ return seq_printf(s, "sport=%hu dport=%hu ",
+ ntohs(tuple->src.u.udp.port),
+ ntohs(tuple->dst.u.udp.port));
+}
+
+/* Print out the private part of the conntrack. */
+static int udplite_print_conntrack(struct seq_file *s,
+ const struct nf_conn *conntrack)
+{
+ return 0;
+}
+
+/* Returns verdict for packet, and may modify conntracktype */
+static int udplite_packet(struct nf_conn *conntrack,
+ const struct sk_buff *skb,
+ unsigned int dataoff,
+ enum ip_conntrack_info ctinfo,
+ int pf,
+ unsigned int hooknum)
+{
+ /* If we've seen traffic both ways, this is some kind of UDP
+ stream. Extend timeout. */
+ if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+ nf_ct_refresh_acct(conntrack, ctinfo, skb,
+ nf_ct_udplite_timeout_stream);
+ /* Also, more likely to be important, and not a probe */
+ if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status))
+ nf_conntrack_event_cache(IPCT_STATUS, skb);
+ } else
+ nf_ct_refresh_acct(conntrack, ctinfo, skb,
+ nf_ct_udplite_timeout);
+
+ return NF_ACCEPT;
+}
+
+/* Called when a new connection for this protocol found. */
+static int udplite_new(struct nf_conn *conntrack, const struct sk_buff *skb,
+ unsigned int dataoff)
+{
+ return 1;
+}
+
+static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
+ enum ip_conntrack_info *ctinfo,
+ int pf,
+ unsigned int hooknum)
+{
+ unsigned int udplen = skb->len - dataoff;
+ struct udphdr _hdr, *hdr;
+ unsigned int cscov;
+
+ /* Header is too small? */
+ hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+ if (hdr == NULL) {
+ if (LOG_INVALID(IPPROTO_UDPLITE))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ "nf_ct_udplite: short packet ");
+ return -NF_ACCEPT;
+ }
+
+ cscov = ntohs(hdr->len);
+ if (cscov == 0)
+ cscov = udplen;
+ else if (cscov < sizeof(*hdr) || cscov > udplen) {
+ if (LOG_INVALID(IPPROTO_UDPLITE))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ "nf_ct_udplite: invalid checksum coverage ");
+ return -NF_ACCEPT;
+ }
+
+ /* UDPLITE mandates checksums */
+ if (!hdr->check) {
+ if (LOG_INVALID(IPPROTO_UDPLITE))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ "nf_ct_udplite: checksum missing ");
+ return -NF_ACCEPT;
+ }
+
+ /* Checksum invalid? Ignore. */
+ if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) &&
+ ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
+ (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))) {
+ if (pf == PF_INET) {
+ struct iphdr *iph = ip_hdr(skb);
+
+ skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+ udplen, IPPROTO_UDPLITE, 0);
+ } else {
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ __wsum hsum = skb_checksum(skb, 0, dataoff, 0);
+
+ skb->csum = ~csum_unfold(
+ csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
+ udplen, IPPROTO_UDPLITE,
+ csum_sub(0, hsum)));
+ }
+
+ skb->ip_summed = CHECKSUM_NONE;
+ if (__skb_checksum_complete_head(skb, dataoff + cscov)) {
+ if (LOG_INVALID(IPPROTO_UDPLITE))
+ nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+ "nf_ct_udplite: bad UDPLite "
+ "checksum ");
+ return -NF_ACCEPT;
+ }
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+
+ return NF_ACCEPT;
+}
+
+#ifdef CONFIG_SYSCTL
+static unsigned int udplite_sysctl_table_users;
+static struct ctl_table_header *udplite_sysctl_header;
+static struct ctl_table udplite_sysctl_table[] = {
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_udplite_timeout",
+ .data = &nf_ct_udplite_timeout,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_udplite_timeout_stream",
+ .data = &nf_ct_udplite_timeout_stream,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ },
+ {
+ .ctl_name = 0
+ }
+};
+#endif /* CONFIG_SYSCTL */
+
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
+{
+ .l3proto = PF_INET,
+ .l4proto = IPPROTO_UDPLITE,
+ .name = "udplite",
+ .pkt_to_tuple = udplite_pkt_to_tuple,
+ .invert_tuple = udplite_invert_tuple,
+ .print_tuple = udplite_print_tuple,
+ .print_conntrack = udplite_print_conntrack,
+ .packet = udplite_packet,
+ .new = udplite_new,
+ .error = udplite_error,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &udplite_sysctl_table_users,
+ .ctl_table_header = &udplite_sysctl_header,
+ .ctl_table = udplite_sysctl_table,
+#endif
+};
+
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
+{
+ .l3proto = PF_INET6,
+ .l4proto = IPPROTO_UDPLITE,
+ .name = "udplite",
+ .pkt_to_tuple = udplite_pkt_to_tuple,
+ .invert_tuple = udplite_invert_tuple,
+ .print_tuple = udplite_print_tuple,
+ .print_conntrack = udplite_print_conntrack,
+ .packet = udplite_packet,
+ .new = udplite_new,
+ .error = udplite_error,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+ .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr,
+ .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple,
+#endif
+#ifdef CONFIG_SYSCTL
+ .ctl_table_users = &udplite_sysctl_table_users,
+ .ctl_table_header = &udplite_sysctl_header,
+ .ctl_table = udplite_sysctl_table,
+#endif
+};
+
+static int __init nf_conntrack_proto_udplite_init(void)
+{
+ int err;
+
+ err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4);
+ if (err < 0)
+ goto err1;
+ err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
+ if (err < 0)
+ goto err2;
+ return 0;
+err2:
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+err1:
+ return err;
+}
+
+static void __exit nf_conntrack_proto_udplite_exit(void)
+{
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
+ nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+}
+
+module_init(nf_conntrack_proto_udplite_init);
+module_exit(nf_conntrack_proto_udplite_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/net/netfilter/nf_conntrack_sane.c b/net/netfilter/nf_conntrack_sane.c
index eb2d1dc46d4..355d371bac9 100644
--- a/net/netfilter/nf_conntrack_sane.c
+++ b/net/netfilter/nf_conntrack_sane.c
@@ -40,12 +40,6 @@ static u_int16_t ports[MAX_PORTS];
static unsigned int ports_c;
module_param_array(ports, ushort, &ports_c, 0400);
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
struct sane_request {
__be32 RPC_code;
#define SANE_NET_START 7 /* RPC code */
@@ -125,15 +119,15 @@ static int help(struct sk_buff **pskb,
ct_sane_info->state = SANE_STATE_NORMAL;
if (datalen < sizeof(struct sane_reply_net_start)) {
- DEBUGP("nf_ct_sane: NET_START reply too short\n");
+ pr_debug("nf_ct_sane: NET_START reply too short\n");
goto out;
}
reply = (struct sane_reply_net_start *)sb_ptr;
if (reply->status != htonl(SANE_STATUS_SUCCESS)) {
/* saned refused the command */
- DEBUGP("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
- ntohl(reply->status));
+ pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
+ ntohl(reply->status));
goto out;
}
@@ -141,35 +135,32 @@ static int help(struct sk_buff **pskb,
if (reply->zero != 0)
goto out;
- exp = nf_conntrack_expect_alloc(ct);
+ exp = nf_ct_expect_alloc(ct);
if (exp == NULL) {
ret = NF_DROP;
goto out;
}
tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
- nf_conntrack_expect_init(exp, family,
- &tuple->src.u3, &tuple->dst.u3,
- IPPROTO_TCP,
- NULL, &reply->port);
+ nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+ IPPROTO_TCP, NULL, &reply->port);
- DEBUGP("nf_ct_sane: expect: ");
+ pr_debug("nf_ct_sane: expect: ");
NF_CT_DUMP_TUPLE(&exp->tuple);
- NF_CT_DUMP_TUPLE(&exp->mask);
/* Can't expect this? Best to drop packet now. */
- if (nf_conntrack_expect_related(exp) != 0)
+ if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
out:
spin_unlock_bh(&nf_sane_lock);
return ret;
}
-static struct nf_conntrack_helper sane[MAX_PORTS][2];
-static char sane_names[MAX_PORTS][2][sizeof("sane-65535")];
+static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
+static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly;
/* don't make this __exit, since it's called from __init ! */
static void nf_conntrack_sane_fini(void)
@@ -178,9 +169,9 @@ static void nf_conntrack_sane_fini(void)
for (i = 0; i < ports_c; i++) {
for (j = 0; j < 2; j++) {
- DEBUGP("nf_ct_sane: unregistering helper for pf: %d "
- "port: %d\n",
- sane[i][j].tuple.src.l3num, ports[i]);
+ pr_debug("nf_ct_sane: unregistering helper for pf: %d "
+ "port: %d\n",
+ sane[i][j].tuple.src.l3num, ports[i]);
nf_conntrack_helper_unregister(&sane[i][j]);
}
}
@@ -208,8 +199,6 @@ static int __init nf_conntrack_sane_init(void)
for (j = 0; j < 2; j++) {
sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
- sane[i][j].mask.src.u.tcp.port = 0xFFFF;
- sane[i][j].mask.dst.protonum = 0xFF;
sane[i][j].max_expected = 1;
sane[i][j].timeout = 5 * 60; /* 5 Minutes */
sane[i][j].me = THIS_MODULE;
@@ -221,9 +210,9 @@ static int __init nf_conntrack_sane_init(void)
sprintf(tmpname, "sane-%d", ports[i]);
sane[i][j].name = tmpname;
- DEBUGP("nf_ct_sane: registering helper for pf: %d "
- "port: %d\n",
- sane[i][j].tuple.src.l3num, ports[i]);
+ pr_debug("nf_ct_sane: registering helper for pf: %d "
+ "port: %d\n",
+ sane[i][j].tuple.src.l3num, ports[i]);
ret = nf_conntrack_helper_register(&sane[i][j]);
if (ret) {
printk(KERN_ERR "nf_ct_sane: failed to "
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 7aaa8c91b29..1276a442f10 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -21,12 +21,6 @@
#include <net/netfilter/nf_conntrack_helper.h>
#include <linux/netfilter/nf_conntrack_sip.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
MODULE_DESCRIPTION("SIP connection tracking helper");
@@ -285,7 +279,7 @@ static int epaddr_len(struct nf_conn *ct, const char *dptr,
const char *aux = dptr;
if (!parse_addr(ct, dptr, &dptr, &addr, limit)) {
- DEBUGP("ip: %s parse failed.!\n", dptr);
+ pr_debug("ip: %s parse failed.!\n", dptr);
return 0;
}
@@ -344,8 +338,8 @@ int ct_sip_get_info(struct nf_conn *ct,
ct_sip_lnlen(dptr, limit),
hnfo->case_sensitive);
if (!aux) {
- DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
- hnfo->lname);
+ pr_debug("'%s' not found in '%s'.\n", hnfo->ln_str,
+ hnfo->lname);
return -1;
}
aux += hnfo->ln_strlen;
@@ -356,11 +350,11 @@ int ct_sip_get_info(struct nf_conn *ct,
*matchoff = (aux - k) + shift;
- DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname,
- *matchlen);
+ pr_debug("%s match succeeded! - len: %u\n", hnfo->lname,
+ *matchlen);
return 1;
}
- DEBUGP("%s header not found.\n", hnfo->lname);
+ pr_debug("%s header not found.\n", hnfo->lname);
return 0;
}
EXPORT_SYMBOL_GPL(ct_sip_get_info);
@@ -378,23 +372,23 @@ static int set_expected_rtp(struct sk_buff **pskb,
int ret;
typeof(nf_nat_sdp_hook) nf_nat_sdp;
- exp = nf_conntrack_expect_alloc(ct);
+ exp = nf_ct_expect_alloc(ct);
if (exp == NULL)
return NF_DROP;
- nf_conntrack_expect_init(exp, family,
- &ct->tuplehash[!dir].tuple.src.u3, addr,
- IPPROTO_UDP, NULL, &port);
+ nf_ct_expect_init(exp, family,
+ &ct->tuplehash[!dir].tuple.src.u3, addr,
+ IPPROTO_UDP, NULL, &port);
nf_nat_sdp = rcu_dereference(nf_nat_sdp_hook);
if (nf_nat_sdp && ct->status & IPS_NAT_MASK)
ret = nf_nat_sdp(pskb, ctinfo, exp, dptr);
else {
- if (nf_conntrack_expect_related(exp) != 0)
+ if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
else
ret = NF_ACCEPT;
}
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
return ret;
}
@@ -424,7 +418,7 @@ static int sip_help(struct sk_buff **pskb,
if (!skb_is_nonlinear(*pskb))
dptr = (*pskb)->data + dataoff;
else {
- DEBUGP("Copy of skbuff not supported yet.\n");
+ pr_debug("Copy of skbuff not supported yet.\n");
goto out;
}
@@ -442,6 +436,9 @@ static int sip_help(struct sk_buff **pskb,
/* RTP info only in some SDP pkts */
if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+ memcmp(dptr, "UPDATE", sizeof("UPDATE") - 1) != 0 &&
+ memcmp(dptr, "SIP/2.0 180", sizeof("SIP/2.0 180") - 1) != 0 &&
+ memcmp(dptr, "SIP/2.0 183", sizeof("SIP/2.0 183") - 1) != 0 &&
memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
goto out;
}
@@ -503,9 +500,6 @@ static int __init nf_conntrack_sip_init(void)
for (j = 0; j < 2; j++) {
sip[i][j].tuple.dst.protonum = IPPROTO_UDP;
sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
- sip[i][j].mask.src.l3num = 0xFFFF;
- sip[i][j].mask.src.u.udp.port = htons(0xFFFF);
- sip[i][j].mask.dst.protonum = 0xFF;
sip[i][j].max_expected = 2;
sip[i][j].timeout = 3 * 60; /* 3 minutes */
sip[i][j].me = THIS_MODULE;
@@ -518,7 +512,7 @@ static int __init nf_conntrack_sip_init(void)
sprintf(tmpname, "sip-%u", i);
sip[i][j].name = tmpname;
- DEBUGP("port #%u: %u\n", i, ports[i]);
+ pr_debug("port #%u: %u\n", i, ports[i]);
ret = nf_conntrack_helper_register(&sip[i][j]);
if (ret) {
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 45baeb0e30f..ffb6ff8c352 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -25,12 +25,6 @@
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h>
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
MODULE_LICENSE("GPL");
#ifdef CONFIG_PROC_FS
@@ -60,35 +54,36 @@ struct ct_iter_state {
unsigned int bucket;
};
-static struct list_head *ct_get_first(struct seq_file *seq)
+static struct hlist_node *ct_get_first(struct seq_file *seq)
{
struct ct_iter_state *st = seq->private;
for (st->bucket = 0;
st->bucket < nf_conntrack_htable_size;
st->bucket++) {
- if (!list_empty(&nf_conntrack_hash[st->bucket]))
- return nf_conntrack_hash[st->bucket].next;
+ if (!hlist_empty(&nf_conntrack_hash[st->bucket]))
+ return nf_conntrack_hash[st->bucket].first;
}
return NULL;
}
-static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+static struct hlist_node *ct_get_next(struct seq_file *seq,
+ struct hlist_node *head)
{
struct ct_iter_state *st = seq->private;
head = head->next;
- while (head == &nf_conntrack_hash[st->bucket]) {
+ while (head == NULL) {
if (++st->bucket >= nf_conntrack_htable_size)
return NULL;
- head = nf_conntrack_hash[st->bucket].next;
+ head = nf_conntrack_hash[st->bucket].first;
}
return head;
}
-static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
+static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos)
{
- struct list_head *head = ct_get_first(seq);
+ struct hlist_node *head = ct_get_first(seq);
if (head)
while (pos && (head = ct_get_next(seq, head)))
@@ -190,7 +185,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
return 0;
}
-static struct seq_operations ct_seq_ops = {
+static const struct seq_operations ct_seq_ops = {
.start = ct_seq_start,
.next = ct_seq_next,
.stop = ct_seq_stop,
@@ -294,7 +289,7 @@ static int ct_cpu_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations ct_cpu_seq_ops = {
+static const struct seq_operations ct_cpu_seq_ops = {
.start = ct_cpu_seq_start,
.next = ct_cpu_seq_next,
.stop = ct_cpu_seq_stop,
@@ -371,7 +366,14 @@ static ctl_table nf_ct_sysctl_table[] = {
.extra1 = &log_invalid_proto_min,
.extra2 = &log_invalid_proto_max,
},
-
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "nf_conntrack_expect_max",
+ .data = &nf_ct_expect_max,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
{ .ctl_name = 0 }
};
@@ -410,7 +412,7 @@ EXPORT_SYMBOL_GPL(nf_ct_log_invalid);
static int __init nf_conntrack_standalone_init(void)
{
#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+ struct proc_dir_entry *proc, *proc_stat;
#endif
int ret = 0;
@@ -422,13 +424,9 @@ static int __init nf_conntrack_standalone_init(void)
proc = proc_net_fops_create("nf_conntrack", 0440, &ct_file_ops);
if (!proc) goto cleanup_init;
- proc_exp = proc_net_fops_create("nf_conntrack_expect", 0440,
- &exp_file_ops);
- if (!proc_exp) goto cleanup_proc;
-
proc_stat = create_proc_entry("nf_conntrack", S_IRUGO, proc_net_stat);
if (!proc_stat)
- goto cleanup_proc_exp;
+ goto cleanup_proc;
proc_stat->proc_fops = &ct_cpu_seq_fops;
proc_stat->owner = THIS_MODULE;
@@ -448,8 +446,6 @@ static int __init nf_conntrack_standalone_init(void)
#endif
#ifdef CONFIG_PROC_FS
remove_proc_entry("nf_conntrack", proc_net_stat);
- cleanup_proc_exp:
- proc_net_remove("nf_conntrack_expect");
cleanup_proc:
proc_net_remove("nf_conntrack");
cleanup_init:
@@ -465,7 +461,6 @@ static void __exit nf_conntrack_standalone_fini(void)
#endif
#ifdef CONFIG_PROC_FS
remove_proc_entry("nf_conntrack", proc_net_stat);
- proc_net_remove("nf_conntrack_expect");
proc_net_remove("nf_conntrack");
#endif /* CNFIG_PROC_FS */
nf_conntrack_cleanup();
diff --git a/net/netfilter/nf_conntrack_tftp.c b/net/netfilter/nf_conntrack_tftp.c
index 37c4542e311..cc19506cf2f 100644
--- a/net/netfilter/nf_conntrack_tftp.c
+++ b/net/netfilter/nf_conntrack_tftp.c
@@ -29,13 +29,6 @@ static int ports_c;
module_param_array(ports, ushort, &ports_c, 0400);
MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
-#if 0
-#define DEBUGP(format, args...) printk("%s:%s:" format, \
- __FILE__, __FUNCTION__ , ## args)
-#else
-#define DEBUGP(format, args...)
-#endif
-
unsigned int (*nf_nat_tftp_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
struct nf_conntrack_expect *exp) __read_mostly;
@@ -62,39 +55,35 @@ static int tftp_help(struct sk_buff **pskb,
case TFTP_OPCODE_READ:
case TFTP_OPCODE_WRITE:
/* RRQ and WRQ works the same way */
- DEBUGP("");
NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
- exp = nf_conntrack_expect_alloc(ct);
+ exp = nf_ct_expect_alloc(ct);
if (exp == NULL)
return NF_DROP;
tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
- nf_conntrack_expect_init(exp, family,
- &tuple->src.u3, &tuple->dst.u3,
- IPPROTO_UDP,
- NULL, &tuple->dst.u.udp.port);
+ nf_ct_expect_init(exp, family, &tuple->src.u3, &tuple->dst.u3,
+ IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
- DEBUGP("expect: ");
+ pr_debug("expect: ");
NF_CT_DUMP_TUPLE(&exp->tuple);
- NF_CT_DUMP_TUPLE(&exp->mask);
nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
ret = nf_nat_tftp(pskb, ctinfo, exp);
- else if (nf_conntrack_expect_related(exp) != 0)
+ else if (nf_ct_expect_related(exp) != 0)
ret = NF_DROP;
- nf_conntrack_expect_put(exp);
+ nf_ct_expect_put(exp);
break;
case TFTP_OPCODE_DATA:
case TFTP_OPCODE_ACK:
- DEBUGP("Data/ACK opcode\n");
+ pr_debug("Data/ACK opcode\n");
break;
case TFTP_OPCODE_ERROR:
- DEBUGP("Error opcode\n");
+ pr_debug("Error opcode\n");
break;
default:
- DEBUGP("Unknown opcode\n");
+ pr_debug("Unknown opcode\n");
}
return ret;
}
@@ -128,9 +117,6 @@ static int __init nf_conntrack_tftp_init(void)
for (j = 0; j < 2; j++) {
tftp[i][j].tuple.dst.protonum = IPPROTO_UDP;
tftp[i][j].tuple.src.u.udp.port = htons(ports[i]);
- tftp[i][j].mask.src.l3num = 0xFFFF;
- tftp[i][j].mask.dst.protonum = 0xFF;
- tftp[i][j].mask.src.u.udp.port = htons(0xFFFF);
tftp[i][j].max_expected = 1;
tftp[i][j].timeout = 5 * 60; /* 5 minutes */
tftp[i][j].me = THIS_MODULE;
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 91b220cf5a1..94985792b79 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -140,7 +140,7 @@ static int seq_show(struct seq_file *s, void *v)
return seq_printf(s, "%2lld %s\n", *pos, logger->name);
}
-static struct seq_operations nflog_seq_ops = {
+static const struct seq_operations nflog_seq_ops = {
.start = seq_start,
.next = seq_next,
.stop = seq_stop,
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index b1f2ace96f6..a481a349f7b 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -17,7 +17,7 @@
*/
static struct nf_queue_handler *queue_handler[NPROTO];
-static DEFINE_RWLOCK(queue_handler_lock);
+static DEFINE_MUTEX(queue_handler_mutex);
/* return EBUSY when somebody else is registered, return EEXIST if the
* same handler is registered, return 0 in case of success. */
@@ -28,30 +28,37 @@ int nf_register_queue_handler(int pf, struct nf_queue_handler *qh)
if (pf >= NPROTO)
return -EINVAL;
- write_lock_bh(&queue_handler_lock);
+ mutex_lock(&queue_handler_mutex);
if (queue_handler[pf] == qh)
ret = -EEXIST;
else if (queue_handler[pf])
ret = -EBUSY;
else {
- queue_handler[pf] = qh;
+ rcu_assign_pointer(queue_handler[pf], qh);
ret = 0;
}
- write_unlock_bh(&queue_handler_lock);
+ mutex_unlock(&queue_handler_mutex);
return ret;
}
EXPORT_SYMBOL(nf_register_queue_handler);
/* The caller must flush their queue before this */
-int nf_unregister_queue_handler(int pf)
+int nf_unregister_queue_handler(int pf, struct nf_queue_handler *qh)
{
if (pf >= NPROTO)
return -EINVAL;
- write_lock_bh(&queue_handler_lock);
- queue_handler[pf] = NULL;
- write_unlock_bh(&queue_handler_lock);
+ mutex_lock(&queue_handler_mutex);
+ if (queue_handler[pf] != qh) {
+ mutex_unlock(&queue_handler_mutex);
+ return -EINVAL;
+ }
+
+ rcu_assign_pointer(queue_handler[pf], NULL);
+ mutex_unlock(&queue_handler_mutex);
+
+ synchronize_rcu();
return 0;
}
@@ -61,12 +68,14 @@ void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
{
int pf;
- write_lock_bh(&queue_handler_lock);
+ mutex_lock(&queue_handler_mutex);
for (pf = 0; pf < NPROTO; pf++) {
if (queue_handler[pf] == qh)
- queue_handler[pf] = NULL;
+ rcu_assign_pointer(queue_handler[pf], NULL);
}
- write_unlock_bh(&queue_handler_lock);
+ mutex_unlock(&queue_handler_mutex);
+
+ synchronize_rcu();
}
EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
@@ -89,18 +98,21 @@ static int __nf_queue(struct sk_buff *skb,
struct net_device *physoutdev = NULL;
#endif
struct nf_afinfo *afinfo;
+ struct nf_queue_handler *qh;
/* QUEUE == DROP if noone is waiting, to be safe. */
- read_lock(&queue_handler_lock);
- if (!queue_handler[pf]) {
- read_unlock(&queue_handler_lock);
+ rcu_read_lock();
+
+ qh = rcu_dereference(queue_handler[pf]);
+ if (!qh) {
+ rcu_read_unlock();
kfree_skb(skb);
return 1;
}
afinfo = nf_get_afinfo(pf);
if (!afinfo) {
- read_unlock(&queue_handler_lock);
+ rcu_read_unlock();
kfree_skb(skb);
return 1;
}
@@ -110,7 +122,7 @@ static int __nf_queue(struct sk_buff *skb,
if (net_ratelimit())
printk(KERN_ERR "OOM queueing packet %p\n",
skb);
- read_unlock(&queue_handler_lock);
+ rcu_read_unlock();
kfree_skb(skb);
return 1;
}
@@ -120,7 +132,7 @@ static int __nf_queue(struct sk_buff *skb,
/* If it's going away, ignore hook. */
if (!try_module_get(info->elem->owner)) {
- read_unlock(&queue_handler_lock);
+ rcu_read_unlock();
kfree(info);
return 0;
}
@@ -138,10 +150,9 @@ static int __nf_queue(struct sk_buff *skb,
}
#endif
afinfo->saveroute(skb, info);
- status = queue_handler[pf]->outfn(skb, info, queuenum,
- queue_handler[pf]->data);
+ status = qh->outfn(skb, info, queuenum, qh->data);
- read_unlock(&queue_handler_lock);
+ rcu_read_unlock();
if (status < 0) {
/* James M doesn't say fuck enough. */
@@ -308,18 +319,18 @@ static int seq_show(struct seq_file *s, void *v)
loff_t *pos = v;
struct nf_queue_handler *qh;
- read_lock_bh(&queue_handler_lock);
- qh = queue_handler[*pos];
+ 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);
- read_unlock_bh(&queue_handler_lock);
+ rcu_read_unlock();
return ret;
}
-static struct seq_operations nfqueue_seq_ops = {
+static const struct seq_operations nfqueue_seq_ops = {
.start = seq_start,
.next = seq_next,
.stop = seq_stop,
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index e32e30e7a17..e185a5b5591 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -962,7 +962,7 @@ static int seq_show(struct seq_file *s, void *v)
inst->flushtimeout, atomic_read(&inst->use));
}
-static struct seq_operations nful_seq_ops = {
+static const struct seq_operations nful_seq_ops = {
.start = seq_start,
.next = seq_next,
.stop = seq_stop,
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7a97bec6772..bb65a38c816 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -913,9 +913,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
case NFQNL_CFG_CMD_PF_UNBIND:
QDEBUG("unregistering queue handler for pf=%u\n",
ntohs(cmd->pf));
- /* This is a bug and a feature. We can unregister
- * other handlers(!) */
- ret = nf_unregister_queue_handler(ntohs(cmd->pf));
+ ret = nf_unregister_queue_handler(ntohs(cmd->pf), &nfqh);
break;
default:
ret = -EINVAL;
@@ -1050,7 +1048,7 @@ static int seq_show(struct seq_file *s, void *v)
atomic_read(&inst->use));
}
-static struct seq_operations nfqnl_seq_ops = {
+static const struct seq_operations nfqnl_seq_ops = {
.start = seq_start,
.next = seq_next,
.stop = seq_stop,
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 0eb2504b89b..cc2baa6d5a7 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -320,8 +320,8 @@ int xt_check_match(const struct xt_match *match, unsigned short family,
return -EINVAL;
}
if (match->hooks && (hook_mask & ~match->hooks) != 0) {
- printk("%s_tables: %s match: bad hook_mask %u\n",
- xt_prefix[family], match->name, hook_mask);
+ printk("%s_tables: %s match: bad hook_mask %u/%u\n",
+ xt_prefix[family], match->name, hook_mask, match->hooks);
return -EINVAL;
}
if (match->proto && (match->proto != proto || inv_proto)) {
@@ -410,8 +410,9 @@ int xt_check_target(const struct xt_target *target, unsigned short family,
return -EINVAL;
}
if (target->hooks && (hook_mask & ~target->hooks) != 0) {
- printk("%s_tables: %s target: bad hook_mask %u\n",
- xt_prefix[family], target->name, hook_mask);
+ printk("%s_tables: %s target: bad hook_mask %u/%u\n",
+ xt_prefix[family], target->name, hook_mask,
+ target->hooks);
return -EINVAL;
}
if (target->proto && (target->proto != proto || inv_proto)) {
@@ -744,7 +745,7 @@ static int xt_name_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations xt_tgt_seq_ops = {
+static const struct seq_operations xt_tgt_seq_ops = {
.start = xt_tgt_seq_start,
.next = xt_tgt_seq_next,
.stop = xt_tgt_seq_stop,
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index 30884833e66..51942856682 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -39,7 +39,7 @@ target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static struct xt_target xt_classify_target[] = {
+static struct xt_target xt_classify_target[] __read_mostly = {
{
.family = AF_INET,
.name = "CLASSIFY",
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
index b03ce009d0b..5a00c544433 100644
--- a/net/netfilter/xt_CONNMARK.c
+++ b/net/netfilter/xt_CONNMARK.c
@@ -76,33 +76,33 @@ target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int
+static bool
checkentry(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask)
{
- struct xt_connmark_target_info *matchinfo = targinfo;
+ const struct xt_connmark_target_info *matchinfo = targinfo;
if (nf_ct_l3proto_try_module_get(target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", target->family);
- return 0;
+ return false;
}
if (matchinfo->mode == XT_CONNMARK_RESTORE) {
if (strcmp(tablename, "mangle") != 0) {
printk(KERN_WARNING "CONNMARK: restore can only be "
"called from \"mangle\" table, not \"%s\"\n",
tablename);
- return 0;
+ return false;
}
}
if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void
@@ -121,7 +121,7 @@ struct compat_xt_connmark_target_info {
static void compat_from_user(void *dst, void *src)
{
- struct compat_xt_connmark_target_info *cm = src;
+ const struct compat_xt_connmark_target_info *cm = src;
struct xt_connmark_target_info m = {
.mark = cm->mark,
.mask = cm->mask,
@@ -132,7 +132,7 @@ static void compat_from_user(void *dst, void *src)
static int compat_to_user(void __user *dst, void *src)
{
- struct xt_connmark_target_info *m = src;
+ const struct xt_connmark_target_info *m = src;
struct compat_xt_connmark_target_info cm = {
.mark = m->mark,
.mask = m->mask,
@@ -142,7 +142,7 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_target xt_connmark_target[] = {
+static struct xt_target xt_connmark_target[] __read_mostly = {
{
.name = "CONNMARK",
.family = AF_INET,
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 81c0c58bab4..63d73138c1b 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -33,7 +33,7 @@ MODULE_ALIAS("ip6t_CONNSECMARK");
* If the packet has a security mark and the connection does not, copy
* the security mark from the packet to the connection.
*/
-static void secmark_save(struct sk_buff *skb)
+static void secmark_save(const struct sk_buff *skb)
{
if (skb->secmark) {
struct nf_conn *ct;
@@ -85,16 +85,16 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
return XT_CONTINUE;
}
-static int checkentry(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
- struct xt_connsecmark_target_info *info = targinfo;
+ const struct xt_connsecmark_target_info *info = targinfo;
if (nf_ct_l3proto_try_module_get(target->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", target->family);
- return 0;
+ return false;
}
switch (info->mode) {
case CONNSECMARK_SAVE:
@@ -103,10 +103,10 @@ static int checkentry(const char *tablename, const void *entry,
default:
printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void
@@ -115,7 +115,7 @@ destroy(const struct xt_target *target, void *targinfo)
nf_ct_l3proto_module_put(target->family);
}
-static struct xt_target xt_connsecmark_target[] = {
+static struct xt_target xt_connsecmark_target[] __read_mostly = {
{
.name = "CONNSECMARK",
.family = AF_INET,
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 9f2f2201f6a..798ab731009 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -66,22 +66,22 @@ static unsigned int target6(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int checkentry(const char *tablename,
- const void *e_void,
- const struct xt_target *target,
- void *targinfo,
- unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+ const void *e_void,
+ const struct xt_target *target,
+ void *targinfo,
+ unsigned int hook_mask)
{
const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp;
- if ((dscp > XT_DSCP_MAX)) {
+ if (dscp > XT_DSCP_MAX) {
printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_target xt_dscp_target[] = {
+static struct xt_target xt_dscp_target[] __read_mostly = {
{
.name = "DSCP",
.family = AF_INET,
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
index 43817808d86..f30fe0baf7d 100644
--- a/net/netfilter/xt_MARK.c
+++ b/net/netfilter/xt_MARK.c
@@ -65,43 +65,43 @@ target_v1(struct sk_buff **pskb,
}
-static int
+static bool
checkentry_v0(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask)
{
- struct xt_mark_target_info *markinfo = targinfo;
+ const struct xt_mark_target_info *markinfo = targinfo;
if (markinfo->mark > 0xffffffff) {
printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int
+static bool
checkentry_v1(const char *tablename,
const void *entry,
const struct xt_target *target,
void *targinfo,
unsigned int hook_mask)
{
- struct xt_mark_target_info_v1 *markinfo = targinfo;
+ const struct xt_mark_target_info_v1 *markinfo = targinfo;
if (markinfo->mode != XT_MARK_SET
&& markinfo->mode != XT_MARK_AND
&& markinfo->mode != XT_MARK_OR) {
printk(KERN_WARNING "MARK: unknown mode %u\n",
markinfo->mode);
- return 0;
+ return false;
}
if (markinfo->mark > 0xffffffff) {
printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
#ifdef CONFIG_COMPAT
@@ -114,7 +114,7 @@ struct compat_xt_mark_target_info_v1 {
static void compat_from_user_v1(void *dst, void *src)
{
- struct compat_xt_mark_target_info_v1 *cm = src;
+ const struct compat_xt_mark_target_info_v1 *cm = src;
struct xt_mark_target_info_v1 m = {
.mark = cm->mark,
.mode = cm->mode,
@@ -124,7 +124,7 @@ static void compat_from_user_v1(void *dst, void *src)
static int compat_to_user_v1(void __user *dst, void *src)
{
- struct xt_mark_target_info_v1 *m = src;
+ const struct xt_mark_target_info_v1 *m = src;
struct compat_xt_mark_target_info_v1 cm = {
.mark = m->mark,
.mode = m->mode,
@@ -133,7 +133,7 @@ static int compat_to_user_v1(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_target xt_mark_target[] = {
+static struct xt_target xt_mark_target[] __read_mostly = {
{
.name = "MARK",
.family = AF_INET,
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
index 901ed7abaa1..d3594c7ccb2 100644
--- a/net/netfilter/xt_NFLOG.c
+++ b/net/netfilter/xt_NFLOG.c
@@ -38,21 +38,21 @@ nflog_target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static int
+static bool
nflog_checkentry(const char *tablename, const void *entry,
const struct xt_target *target, void *targetinfo,
unsigned int hookmask)
{
- struct xt_nflog_info *info = targetinfo;
+ const struct xt_nflog_info *info = targetinfo;
if (info->flags & ~XT_NFLOG_MASK)
- return 0;
+ return false;
if (info->prefix[sizeof(info->prefix) - 1] != '\0')
- return 0;
- return 1;
+ return false;
+ return true;
}
-static struct xt_target xt_nflog_target[] = {
+static struct xt_target xt_nflog_target[] __read_mostly = {
{
.name = "NFLOG",
.family = AF_INET,
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 201155b316e..13f59f3e8c3 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -36,7 +36,7 @@ target(struct sk_buff **pskb,
return NF_QUEUE_NR(tinfo->queuenum);
}
-static struct xt_target xt_nfqueue_target[] = {
+static struct xt_target xt_nfqueue_target[] __read_mostly = {
{
.name = "NFQUEUE",
.family = AF_INET,
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
index 5085fb3d1e2..b7d6312fccc 100644
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -33,7 +33,7 @@ target(struct sk_buff **pskb,
return XT_CONTINUE;
}
-static struct xt_target xt_notrack_target[] = {
+static struct xt_target xt_notrack_target[] __read_mostly = {
{
.name = "NOTRACK",
.family = AF_INET,
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 705f0e830a7..c83779a941a 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -51,7 +51,7 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
return XT_CONTINUE;
}
-static int checkentry_selinux(struct xt_secmark_target_info *info)
+static bool checkentry_selinux(struct xt_secmark_target_info *info)
{
int err;
struct xt_secmark_target_selinux_info *sel = &info->u.sel;
@@ -63,53 +63,53 @@ static int checkentry_selinux(struct xt_secmark_target_info *info)
if (err == -EINVAL)
printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
sel->selctx);
- return 0;
+ return false;
}
if (!sel->selsid) {
printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
sel->selctx);
- return 0;
+ return false;
}
err = selinux_relabel_packet_permission(sel->selsid);
if (err) {
printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int checkentry(const char *tablename, const void *entry,
- const struct xt_target *target, void *targinfo,
- unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
{
struct xt_secmark_target_info *info = targinfo;
if (mode && mode != info->mode) {
printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
"rules for mode %hu\n", mode, info->mode);
- return 0;
+ return false;
}
switch (info->mode) {
case SECMARK_MODE_SEL:
if (!checkentry_selinux(info))
- return 0;
+ return false;
break;
default:
printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
- return 0;
+ return false;
}
if (!mode)
mode = info->mode;
- return 1;
+ return true;
}
-static struct xt_target xt_secmark_target[] = {
+static struct xt_target xt_secmark_target[] __read_mostly = {
{
.name = "SECMARK",
.family = AF_INET,
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 15fe8f64951..d40f7e4b128 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -93,7 +93,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb,
return 0;
opt[i+2] = (newmss & 0xff00) >> 8;
- opt[i+3] = (newmss & 0x00ff);
+ opt[i+3] = newmss & 0x00ff;
nf_proto_csum_replace2(&tcph->check, *pskb,
htons(oldmss), htons(newmss), 0);
@@ -126,7 +126,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb,
opt[0] = TCPOPT_MSS;
opt[1] = TCPOLEN_MSS;
opt[2] = (newmss & 0xff00) >> 8;
- opt[3] = (newmss & 0x00ff);
+ opt[3] = newmss & 0x00ff;
nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
@@ -197,19 +197,19 @@ xt_tcpmss_target6(struct sk_buff **pskb,
#define TH_SYN 0x02
/* Must specify -p tcp --syn */
-static inline int find_syn_match(const struct xt_entry_match *m)
+static inline bool find_syn_match(const struct xt_entry_match *m)
{
const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data;
if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
tcpinfo->flg_cmp & TH_SYN &&
!(tcpinfo->invflags & XT_TCP_INV_FLAGS))
- return 1;
+ return true;
- return 0;
+ return false;
}
-static int
+static bool
xt_tcpmss_checkentry4(const char *tablename,
const void *entry,
const struct xt_target *target,
@@ -225,16 +225,16 @@ xt_tcpmss_checkentry4(const char *tablename,
(1 << NF_IP_POST_ROUTING))) != 0) {
printk("xt_TCPMSS: path-MTU clamping only supported in "
"FORWARD, OUTPUT and POSTROUTING hooks\n");
- return 0;
+ return false;
}
if (IPT_MATCH_ITERATE(e, find_syn_match))
- return 1;
+ return true;
printk("xt_TCPMSS: Only works on TCP SYN packets\n");
- return 0;
+ return false;
}
#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
-static int
+static bool
xt_tcpmss_checkentry6(const char *tablename,
const void *entry,
const struct xt_target *target,
@@ -250,16 +250,16 @@ xt_tcpmss_checkentry6(const char *tablename,
(1 << NF_IP6_POST_ROUTING))) != 0) {
printk("xt_TCPMSS: path-MTU clamping only supported in "
"FORWARD, OUTPUT and POSTROUTING hooks\n");
- return 0;
+ return false;
}
if (IP6T_MATCH_ITERATE(e, find_syn_match))
- return 1;
+ return true;
printk("xt_TCPMSS: Only works on TCP SYN packets\n");
- return 0;
+ return false;
}
#endif
-static struct xt_target xt_tcpmss_reg[] = {
+static struct xt_target xt_tcpmss_reg[] __read_mostly = {
{
.family = AF_INET,
.name = "TCPMSS",
diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
new file mode 100644
index 00000000000..4df2dedcc0b
--- /dev/null
+++ b/net/netfilter/xt_TRACE.c
@@ -0,0 +1,53 @@
+/* This is a module which is used to mark packets for tracing.
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_TRACE");
+MODULE_ALIAS("ip6t_TRACE");
+
+static unsigned int
+target(struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ unsigned int hooknum,
+ const struct xt_target *target,
+ const void *targinfo)
+{
+ (*pskb)->nf_trace = 1;
+ return XT_CONTINUE;
+}
+
+static struct xt_target xt_trace_target[] __read_mostly = {
+ {
+ .name = "TRACE",
+ .family = AF_INET,
+ .target = target,
+ .table = "raw",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "TRACE",
+ .family = AF_INET6,
+ .target = target,
+ .table = "raw",
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_trace_init(void)
+{
+ return xt_register_targets(xt_trace_target,
+ ARRAY_SIZE(xt_trace_target));
+}
+
+static void __exit xt_trace_fini(void)
+{
+ xt_unregister_targets(xt_trace_target, ARRAY_SIZE(xt_trace_target));
+}
+
+module_init(xt_trace_init);
+module_exit(xt_trace_fini);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
index 7db492d6522..64bcdb0fe1e 100644
--- a/net/netfilter/xt_comment.c
+++ b/net/netfilter/xt_comment.c
@@ -15,7 +15,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_comment");
MODULE_ALIAS("ip6t_comment");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -23,13 +23,13 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protooff,
- int *hotdrop)
+ bool *hotdrop)
{
/* We always match */
- return 1;
+ return true;
}
-static struct xt_match xt_comment_match[] = {
+static struct xt_match xt_comment_match[] __read_mostly = {
{
.name = "comment",
.family = AF_INET,
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 804afe55e14..dd4d79b8fc9 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -15,7 +15,7 @@ MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
MODULE_ALIAS("ipt_connbytes");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -23,10 +23,10 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_connbytes_info *sinfo = matchinfo;
- struct nf_conn *ct;
+ const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
u_int64_t what = 0; /* initialize to make gcc happy */
u_int64_t bytes = 0;
@@ -35,7 +35,7 @@ match(const struct sk_buff *skb,
ct = nf_ct_get(skb, &ctinfo);
if (!ct)
- return 0;
+ return false;
counters = ct->counters;
switch (sinfo->what) {
@@ -90,36 +90,36 @@ match(const struct sk_buff *skb,
}
if (sinfo->count.to)
- return (what <= sinfo->count.to && what >= sinfo->count.from);
+ return what <= sinfo->count.to && what >= sinfo->count.from;
else
- return (what >= sinfo->count.from);
+ return what >= sinfo->count.from;
}
-static int check(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool check(const char *tablename,
+ const void *ip,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask)
{
const struct xt_connbytes_info *sinfo = matchinfo;
if (sinfo->what != XT_CONNBYTES_PKTS &&
sinfo->what != XT_CONNBYTES_BYTES &&
sinfo->what != XT_CONNBYTES_AVGPKT)
- return 0;
+ return false;
if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
sinfo->direction != XT_CONNBYTES_DIR_BOTH)
- return 0;
+ return false;
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void
@@ -128,7 +128,7 @@ destroy(const struct xt_match *match, void *matchinfo)
nf_ct_l3proto_module_put(match->family);
}
-static struct xt_match xt_connbytes_match[] = {
+static struct xt_match xt_connbytes_match[] __read_mostly = {
{
.name = "connbytes",
.family = AF_INET,
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
new file mode 100644
index 00000000000..3335dd5be96
--- /dev/null
+++ b/net/netfilter/xt_connlimit.c
@@ -0,0 +1,313 @@
+/*
+ * netfilter module to limit the number of parallel tcp
+ * connections per IP address.
+ * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
+ * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
+ * only ignore TIME_WAIT or gone connections
+ * Copyright © Jan Engelhardt <jengelh@gmx.de>, 2007
+ *
+ * based on ...
+ *
+ * Kernel module to match connection tracking information.
+ * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
+ */
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/jhash.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/netfilter/nf_conntrack_tcp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_connlimit.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+/* we will save the tuples of all connections we care about */
+struct xt_connlimit_conn {
+ struct list_head list;
+ struct nf_conntrack_tuple tuple;
+};
+
+struct xt_connlimit_data {
+ struct list_head iphash[256];
+ spinlock_t lock;
+};
+
+static u_int32_t connlimit_rnd;
+static bool connlimit_rnd_inited;
+
+static inline unsigned int connlimit_iphash(u_int32_t addr)
+{
+ if (unlikely(!connlimit_rnd_inited)) {
+ get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
+ connlimit_rnd_inited = true;
+ }
+ return jhash_1word(addr, connlimit_rnd) & 0xFF;
+}
+
+static inline unsigned int
+connlimit_iphash6(const union nf_conntrack_address *addr,
+ const union nf_conntrack_address *mask)
+{
+ union nf_conntrack_address res;
+ unsigned int i;
+
+ if (unlikely(!connlimit_rnd_inited)) {
+ get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
+ connlimit_rnd_inited = true;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i)
+ res.ip6[i] = addr->ip6[i] & mask->ip6[i];
+
+ return jhash2(res.ip6, ARRAY_SIZE(res.ip6), connlimit_rnd) & 0xFF;
+}
+
+static inline bool already_closed(const struct nf_conn *conn)
+{
+ u_int16_t proto = conn->tuplehash[0].tuple.dst.protonum;
+
+ if (proto == IPPROTO_TCP)
+ return conn->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT;
+ else
+ return 0;
+}
+
+static inline unsigned int
+same_source_net(const union nf_conntrack_address *addr,
+ const union nf_conntrack_address *mask,
+ const union nf_conntrack_address *u3, unsigned int family)
+{
+ if (family == AF_INET) {
+ return (addr->ip & mask->ip) == (u3->ip & mask->ip);
+ } else {
+ union nf_conntrack_address lh, rh;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) {
+ lh.ip6[i] = addr->ip6[i] & mask->ip6[i];
+ rh.ip6[i] = u3->ip6[i] & mask->ip6[i];
+ }
+
+ return memcmp(&lh.ip6, &rh.ip6, sizeof(lh.ip6)) == 0;
+ }
+}
+
+static int count_them(struct xt_connlimit_data *data,
+ const struct nf_conntrack_tuple *tuple,
+ const union nf_conntrack_address *addr,
+ const union nf_conntrack_address *mask,
+ const struct xt_match *match)
+{
+ struct nf_conntrack_tuple_hash *found;
+ struct xt_connlimit_conn *conn;
+ struct xt_connlimit_conn *tmp;
+ struct nf_conn *found_ct;
+ struct list_head *hash;
+ bool addit = true;
+ int matches = 0;
+
+
+ if (match->family == AF_INET6)
+ hash = &data->iphash[connlimit_iphash6(addr, mask)];
+ else
+ hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)];
+
+ read_lock_bh(&nf_conntrack_lock);
+
+ /* check the saved connections */
+ list_for_each_entry_safe(conn, tmp, hash, list) {
+ found = __nf_conntrack_find(&conn->tuple, NULL);
+ found_ct = NULL;
+
+ if (found != NULL)
+ found_ct = nf_ct_tuplehash_to_ctrack(found);
+
+ if (found_ct != NULL &&
+ nf_ct_tuple_equal(&conn->tuple, tuple) &&
+ !already_closed(found_ct))
+ /*
+ * Just to be sure we have it only once in the list.
+ * We should not see tuples twice unless someone hooks
+ * this into a table without "-p tcp --syn".
+ */
+ addit = false;
+
+ if (found == NULL) {
+ /* this one is gone */
+ list_del(&conn->list);
+ kfree(conn);
+ continue;
+ }
+
+ if (already_closed(found_ct)) {
+ /*
+ * we do not care about connections which are
+ * closed already -> ditch it
+ */
+ list_del(&conn->list);
+ kfree(conn);
+ continue;
+ }
+
+ if (same_source_net(addr, mask, &conn->tuple.src.u3,
+ match->family))
+ /* same source network -> be counted! */
+ ++matches;
+ }
+
+ read_unlock_bh(&nf_conntrack_lock);
+
+ if (addit) {
+ /* save the new connection in our list */
+ conn = kzalloc(sizeof(*conn), GFP_ATOMIC);
+ if (conn == NULL)
+ return -ENOMEM;
+ conn->tuple = *tuple;
+ list_add(&conn->list, hash);
+ ++matches;
+ }
+
+ return matches;
+}
+
+static bool connlimit_match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo, int offset,
+ unsigned int protoff, bool *hotdrop)
+{
+ const struct xt_connlimit_info *info = matchinfo;
+ union nf_conntrack_address addr, mask;
+ struct nf_conntrack_tuple tuple;
+ const struct nf_conntrack_tuple *tuple_ptr = &tuple;
+ enum ip_conntrack_info ctinfo;
+ const struct nf_conn *ct;
+ int connections;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct != NULL)
+ tuple_ptr = &ct->tuplehash[0].tuple;
+ else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
+ match->family, &tuple))
+ goto hotdrop;
+
+ if (match->family == AF_INET6) {
+ const struct ipv6hdr *iph = ipv6_hdr(skb);
+ memcpy(&addr.ip6, &iph->saddr, sizeof(iph->saddr));
+ memcpy(&mask.ip6, info->v6_mask, sizeof(info->v6_mask));
+ } else {
+ const struct iphdr *iph = ip_hdr(skb);
+ addr.ip = iph->saddr;
+ mask.ip = info->v4_mask;
+ }
+
+ spin_lock_bh(&info->data->lock);
+ connections = count_them(info->data, tuple_ptr, &addr, &mask, match);
+ spin_unlock_bh(&info->data->lock);
+
+ if (connections < 0) {
+ /* kmalloc failed, drop it entirely */
+ *hotdrop = true;
+ return false;
+ }
+
+ return (connections > info->limit) ^ info->inverse;
+
+ hotdrop:
+ *hotdrop = true;
+ return false;
+}
+
+static bool connlimit_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
+{
+ struct xt_connlimit_info *info = matchinfo;
+ unsigned int i;
+
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "cannot load conntrack support for "
+ "address family %u\n", match->family);
+ return false;
+ }
+
+ /* init private data */
+ info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
+ if (info->data == NULL) {
+ nf_ct_l3proto_module_put(match->family);
+ return false;
+ }
+
+ spin_lock_init(&info->data->lock);
+ for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i)
+ INIT_LIST_HEAD(&info->data->iphash[i]);
+
+ return true;
+}
+
+static void connlimit_destroy(const struct xt_match *match, void *matchinfo)
+{
+ struct xt_connlimit_info *info = matchinfo;
+ struct xt_connlimit_conn *conn;
+ struct xt_connlimit_conn *tmp;
+ struct list_head *hash = info->data->iphash;
+ unsigned int i;
+
+ nf_ct_l3proto_module_put(match->family);
+
+ for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) {
+ list_for_each_entry_safe(conn, tmp, &hash[i], list) {
+ list_del(&conn->list);
+ kfree(conn);
+ }
+ }
+
+ kfree(info->data);
+}
+
+static struct xt_match connlimit_reg[] __read_mostly = {
+ {
+ .name = "connlimit",
+ .family = AF_INET,
+ .checkentry = connlimit_check,
+ .match = connlimit_match,
+ .matchsize = sizeof(struct xt_connlimit_info),
+ .destroy = connlimit_destroy,
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "connlimit",
+ .family = AF_INET6,
+ .checkentry = connlimit_check,
+ .match = connlimit_match,
+ .matchsize = sizeof(struct xt_connlimit_info),
+ .destroy = connlimit_destroy,
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_connlimit_init(void)
+{
+ return xt_register_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg));
+}
+
+static void __exit xt_connlimit_exit(void)
+{
+ xt_unregister_matches(connlimit_reg, ARRAY_SIZE(connlimit_reg));
+}
+
+module_init(xt_connlimit_init);
+module_exit(xt_connlimit_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter xt_connlimit match module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_connlimit");
+MODULE_ALIAS("ip6t_connlimit");
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index e1803256c79..e73fa9b46cf 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -30,7 +30,7 @@ MODULE_DESCRIPTION("IP tables connmark match module");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_connmark");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -38,38 +38,38 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_connmark_info *info = matchinfo;
- struct nf_conn *ct;
+ const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
ct = nf_ct_get(skb, &ctinfo);
if (!ct)
- return 0;
+ return false;
- return (((ct->mark) & info->mask) == info->mark) ^ info->invert;
+ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
}
-static int
+static bool
checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
void *matchinfo,
unsigned int hook_mask)
{
- struct xt_connmark_info *cm = matchinfo;
+ const struct xt_connmark_info *cm = matchinfo;
if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
printk(KERN_WARNING "connmark: only support 32bit mark\n");
- return 0;
+ return false;
}
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void
@@ -88,7 +88,7 @@ struct compat_xt_connmark_info {
static void compat_from_user(void *dst, void *src)
{
- struct compat_xt_connmark_info *cm = src;
+ const struct compat_xt_connmark_info *cm = src;
struct xt_connmark_info m = {
.mark = cm->mark,
.mask = cm->mask,
@@ -99,7 +99,7 @@ static void compat_from_user(void *dst, void *src)
static int compat_to_user(void __user *dst, void *src)
{
- struct xt_connmark_info *m = src;
+ const struct xt_connmark_info *m = src;
struct compat_xt_connmark_info cm = {
.mark = m->mark,
.mask = m->mask,
@@ -109,7 +109,7 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_match xt_connmark_match[] = {
+static struct xt_match xt_connmark_match[] __read_mostly = {
{
.name = "connmark",
.family = AF_INET,
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index 189ded5f378..ca4b69f020a 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -19,7 +19,7 @@ MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables connection tracking match module");
MODULE_ALIAS("ipt_conntrack");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -27,14 +27,14 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_conntrack_info *sinfo = matchinfo;
- struct nf_conn *ct;
+ const struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
unsigned int statebit;
- ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
+ ct = nf_ct_get(skb, &ctinfo);
#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
@@ -54,53 +54,53 @@ match(const struct sk_buff *skb,
}
if (FWINV((statebit & sinfo->statemask) == 0,
XT_CONNTRACK_STATE))
- return 0;
+ return false;
}
if (ct == NULL) {
if (sinfo->flags & ~XT_CONNTRACK_STATE)
- return 0;
- return 1;
+ return false;
+ return true;
}
if (sinfo->flags & XT_CONNTRACK_PROTO &&
FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum !=
sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum,
XT_CONNTRACK_PROTO))
- return 0;
+ return false;
if (sinfo->flags & XT_CONNTRACK_ORIGSRC &&
FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip &
sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
XT_CONNTRACK_ORIGSRC))
- return 0;
+ return false;
if (sinfo->flags & XT_CONNTRACK_ORIGDST &&
FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip &
sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) !=
sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
XT_CONNTRACK_ORIGDST))
- return 0;
+ return false;
if (sinfo->flags & XT_CONNTRACK_REPLSRC &&
FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip &
sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) !=
sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
XT_CONNTRACK_REPLSRC))
- return 0;
+ return false;
if (sinfo->flags & XT_CONNTRACK_REPLDST &&
FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip &
sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) !=
sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
XT_CONNTRACK_REPLDST))
- return 0;
+ return false;
if (sinfo->flags & XT_CONNTRACK_STATUS &&
FWINV((ct->status & sinfo->statusmask) == 0,
XT_CONNTRACK_STATUS))
- return 0;
+ return false;
if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
unsigned long expires = timer_pending(&ct->timeout) ?
@@ -109,12 +109,12 @@ match(const struct sk_buff *skb,
if (FWINV(!(expires >= sinfo->expires_min &&
expires <= sinfo->expires_max),
XT_CONNTRACK_EXPIRES))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int
+static bool
checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
@@ -124,9 +124,9 @@ checkentry(const char *tablename,
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void destroy(const struct xt_match *match, void *matchinfo)
@@ -150,7 +150,7 @@ struct compat_xt_conntrack_info
static void compat_from_user(void *dst, void *src)
{
- struct compat_xt_conntrack_info *cm = src;
+ const struct compat_xt_conntrack_info *cm = src;
struct xt_conntrack_info m = {
.statemask = cm->statemask,
.statusmask = cm->statusmask,
@@ -167,7 +167,7 @@ static void compat_from_user(void *dst, void *src)
static int compat_to_user(void __user *dst, void *src)
{
- struct xt_conntrack_info *m = src;
+ const struct xt_conntrack_info *m = src;
struct compat_xt_conntrack_info cm = {
.statemask = m->statemask,
.statusmask = m->statusmask,
@@ -183,7 +183,7 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif
-static struct xt_match conntrack_match = {
+static struct xt_match conntrack_match __read_mostly = {
.name = "conntrack",
.match = match,
.checkentry = checkentry,
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index 2c9c0dee8aa..83224ec89cc 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -31,40 +31,40 @@ MODULE_ALIAS("ipt_dccp");
static unsigned char *dccp_optbuf;
static DEFINE_SPINLOCK(dccp_buflock);
-static inline int
+static inline bool
dccp_find_option(u_int8_t option,
const struct sk_buff *skb,
unsigned int protoff,
const struct dccp_hdr *dh,
- int *hotdrop)
+ bool *hotdrop)
{
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
- unsigned char *op;
+ const unsigned char *op;
unsigned int optoff = __dccp_hdr_len(dh);
unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh);
unsigned int i;
if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
if (!optlen)
- return 0;
+ return false;
spin_lock_bh(&dccp_buflock);
op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf);
if (op == NULL) {
/* If we don't have the whole header, drop packet. */
spin_unlock_bh(&dccp_buflock);
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
for (i = 0; i < optlen; ) {
if (op[i] == option) {
spin_unlock_bh(&dccp_buflock);
- return 1;
+ return true;
}
if (op[i] < 2)
@@ -74,24 +74,24 @@ dccp_find_option(u_int8_t option,
}
spin_unlock_bh(&dccp_buflock);
- return 0;
+ return false;
}
-static inline int
+static inline bool
match_types(const struct dccp_hdr *dh, u_int16_t typemask)
{
- return (typemask & (1 << dh->dccph_type));
+ return typemask & (1 << dh->dccph_type);
}
-static inline int
+static inline bool
match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
- const struct dccp_hdr *dh, int *hotdrop)
+ const struct dccp_hdr *dh, bool *hotdrop)
{
return dccp_find_option(option, skb, protoff, dh, hotdrop);
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -99,25 +99,25 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_dccp_info *info = matchinfo;
struct dccp_hdr _dh, *dh;
if (offset)
- return 0;
+ return false;
dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
if (dh == NULL) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
- return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
- && (ntohs(dh->dccph_sport) <= info->spts[1])),
+ return DCCHECK(ntohs(dh->dccph_sport) >= info->spts[0]
+ && ntohs(dh->dccph_sport) <= info->spts[1],
XT_DCCP_SRC_PORTS, info->flags, info->invflags)
- && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0])
- && (ntohs(dh->dccph_dport) <= info->dpts[1])),
+ && DCCHECK(ntohs(dh->dccph_dport) >= info->dpts[0]
+ && ntohs(dh->dccph_dport) <= info->dpts[1],
XT_DCCP_DEST_PORTS, info->flags, info->invflags)
&& DCCHECK(match_types(dh, info->typemask),
XT_DCCP_TYPE, info->flags, info->invflags)
@@ -126,7 +126,7 @@ match(const struct sk_buff *skb,
XT_DCCP_OPTION, info->flags, info->invflags);
}
-static int
+static bool
checkentry(const char *tablename,
const void *inf,
const struct xt_match *match,
@@ -140,7 +140,7 @@ checkentry(const char *tablename,
&& !(info->invflags & ~info->flags);
}
-static struct xt_match xt_dccp_match[] = {
+static struct xt_match xt_dccp_match[] __read_mostly = {
{
.name = "dccp",
.family = AF_INET,
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index 56b247ecc28..dde6d66e0d3 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -22,14 +22,14 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_dscp");
MODULE_ALIAS("ip6t_dscp");
-static int match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
+static bool match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_dscp_info *info = matchinfo;
u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -37,14 +37,14 @@ static int match(const struct sk_buff *skb,
return (dscp == info->dscp) ^ !!info->invert;
}
-static int match6(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
+static bool match6(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_dscp_info *info = matchinfo;
u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
@@ -52,23 +52,23 @@ static int match6(const struct sk_buff *skb,
return (dscp == info->dscp) ^ !!info->invert;
}
-static int checkentry(const char *tablename,
- const void *info,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+ const void *info,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask)
{
const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp;
if (dscp > XT_DSCP_MAX) {
printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match xt_dscp_match[] = {
+static struct xt_match xt_dscp_match[] __read_mostly = {
{
.name = "dscp",
.family = AF_INET,
diff --git a/net/netfilter/xt_esp.c b/net/netfilter/xt_esp.c
index 7c95f149d94..b11378e001b 100644
--- a/net/netfilter/xt_esp.c
+++ b/net/netfilter/xt_esp.c
@@ -31,10 +31,10 @@ MODULE_ALIAS("ip6t_esp");
#endif
/* Returns 1 if the spi is matched by the range, 0 otherwise */
-static inline int
-spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
+static inline bool
+spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, bool invert)
{
- int r = 0;
+ bool r;
duprintf("esp spi_match:%c 0x%x <= 0x%x <= 0x%x", invert ? '!' : ' ',
min, spi, max);
r = (spi >= min && spi <= max) ^ invert;
@@ -42,7 +42,7 @@ spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
return r;
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -50,14 +50,14 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
struct ip_esp_hdr _esp, *eh;
const struct xt_esp *espinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
- return 0;
+ return false;
eh = skb_header_pointer(skb, protoff, sizeof(_esp), &_esp);
if (eh == NULL) {
@@ -65,8 +65,8 @@ match(const struct sk_buff *skb,
* can't. Hence, no choice but to drop.
*/
duprintf("Dropping evil ESP tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
return spi_match(espinfo->spis[0], espinfo->spis[1], ntohl(eh->spi),
@@ -74,7 +74,7 @@ match(const struct sk_buff *skb,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
checkentry(const char *tablename,
const void *ip_void,
const struct xt_match *match,
@@ -85,13 +85,13 @@ checkentry(const char *tablename,
if (espinfo->invflags & ~XT_ESP_INV_MASK) {
duprintf("xt_esp: unknown flags %X\n", espinfo->invflags);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match xt_esp_match[] = {
+static struct xt_match xt_esp_match[] __read_mostly = {
{
.name = "esp",
.family = AF_INET,
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index d3043fa32eb..d6b3d01975b 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -94,7 +94,8 @@ static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */
static HLIST_HEAD(hashlimit_htables);
static struct kmem_cache *hashlimit_cachep __read_mostly;
-static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
+static inline bool dst_cmp(const struct dsthash_ent *ent,
+ const struct dsthash_dst *b)
{
return !memcmp(&ent->dst, b, sizeof(ent->dst));
}
@@ -106,7 +107,8 @@ hash_dst(const struct xt_hashlimit_htable *ht, const struct dsthash_dst *dst)
}
static struct dsthash_ent *
-dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
+dsthash_find(const struct xt_hashlimit_htable *ht,
+ const struct dsthash_dst *dst)
{
struct dsthash_ent *ent;
struct hlist_node *pos;
@@ -122,7 +124,8 @@ dsthash_find(const struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
/* allocate dsthash_ent, initialize dst, put in htable and lock it */
static struct dsthash_ent *
-dsthash_alloc_init(struct xt_hashlimit_htable *ht, struct dsthash_dst *dst)
+dsthash_alloc_init(struct xt_hashlimit_htable *ht,
+ const struct dsthash_dst *dst)
{
struct dsthash_ent *ent;
@@ -227,19 +230,21 @@ static int htable_create(struct xt_hashlimit_info *minfo, int family)
return 0;
}
-static int select_all(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
+static bool select_all(const struct xt_hashlimit_htable *ht,
+ const struct dsthash_ent *he)
{
return 1;
}
-static int select_gc(struct xt_hashlimit_htable *ht, struct dsthash_ent *he)
+static bool select_gc(const struct xt_hashlimit_htable *ht,
+ const struct dsthash_ent *he)
{
- return (jiffies >= he->expires);
+ return jiffies >= he->expires;
}
static void htable_selective_cleanup(struct xt_hashlimit_htable *ht,
- int (*select)(struct xt_hashlimit_htable *ht,
- struct dsthash_ent *he))
+ bool (*select)(const struct xt_hashlimit_htable *ht,
+ const struct dsthash_ent *he))
{
unsigned int i;
@@ -282,7 +287,8 @@ static void htable_destroy(struct xt_hashlimit_htable *hinfo)
vfree(hinfo);
}
-static struct xt_hashlimit_htable *htable_find_get(char *name, int family)
+static struct xt_hashlimit_htable *htable_find_get(const char *name,
+ int family)
{
struct xt_hashlimit_htable *hinfo;
struct hlist_node *pos;
@@ -367,7 +373,8 @@ static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
}
static int
-hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst,
+hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
+ struct dsthash_dst *dst,
const struct sk_buff *skb, unsigned int protoff)
{
__be16 _ports[2], *ports;
@@ -432,7 +439,7 @@ hashlimit_init_dst(struct xt_hashlimit_htable *hinfo, struct dsthash_dst *dst,
return 0;
}
-static int
+static bool
hashlimit_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -440,10 +447,10 @@ hashlimit_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
- struct xt_hashlimit_info *r =
- ((struct xt_hashlimit_info *)matchinfo)->u.master;
+ const struct xt_hashlimit_info *r =
+ ((const struct xt_hashlimit_info *)matchinfo)->u.master;
struct xt_hashlimit_htable *hinfo = r->hinfo;
unsigned long now = jiffies;
struct dsthash_ent *dh;
@@ -478,20 +485,20 @@ hashlimit_match(const struct sk_buff *skb,
/* We're underlimit. */
dh->rateinfo.credit -= dh->rateinfo.cost;
spin_unlock_bh(&hinfo->lock);
- return 1;
+ return true;
}
spin_unlock_bh(&hinfo->lock);
/* default case: we're overlimit, thus don't match */
- return 0;
+ return false;
hotdrop:
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
-static int
+static bool
hashlimit_checkentry(const char *tablename,
const void *inf,
const struct xt_match *match,
@@ -505,20 +512,20 @@ hashlimit_checkentry(const char *tablename,
user2credits(r->cfg.avg * r->cfg.burst) < user2credits(r->cfg.avg)) {
printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
r->cfg.avg, r->cfg.burst);
- return 0;
+ return false;
}
if (r->cfg.mode == 0 ||
r->cfg.mode > (XT_HASHLIMIT_HASH_DPT |
XT_HASHLIMIT_HASH_DIP |
XT_HASHLIMIT_HASH_SIP |
XT_HASHLIMIT_HASH_SPT))
- return 0;
+ return false;
if (!r->cfg.gc_interval)
- return 0;
+ return false;
if (!r->cfg.expire)
- return 0;
+ return false;
if (r->name[sizeof(r->name) - 1] != '\0')
- return 0;
+ return false;
/* This is the best we've got: We cannot release and re-grab lock,
* since checkentry() is called before x_tables.c grabs xt_mutex.
@@ -530,19 +537,19 @@ hashlimit_checkentry(const char *tablename,
r->hinfo = htable_find_get(r->name, match->family);
if (!r->hinfo && htable_create(r, match->family) != 0) {
mutex_unlock(&hlimit_mutex);
- return 0;
+ return false;
}
mutex_unlock(&hlimit_mutex);
/* Ugly hack: For SMP, we only want to use one set */
r->u.master = r;
- return 1;
+ return true;
}
static void
hashlimit_destroy(const struct xt_match *match, void *matchinfo)
{
- struct xt_hashlimit_info *r = matchinfo;
+ const struct xt_hashlimit_info *r = matchinfo;
htable_put(r->hinfo);
}
@@ -571,7 +578,7 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif
-static struct xt_match xt_hashlimit[] = {
+static struct xt_match xt_hashlimit[] __read_mostly = {
{
.name = "hashlimit",
.family = AF_INET,
@@ -694,7 +701,7 @@ static int dl_seq_show(struct seq_file *s, void *v)
return 0;
}
-static struct seq_operations dl_seq_ops = {
+static const struct seq_operations dl_seq_ops = {
.start = dl_seq_start,
.next = dl_seq_next,
.stop = dl_seq_stop,
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
index c139b2f43a1..0a1f4c6bcde 100644
--- a/net/netfilter/xt_helper.c
+++ b/net/netfilter/xt_helper.c
@@ -22,13 +22,8 @@ MODULE_DESCRIPTION("iptables helper match module");
MODULE_ALIAS("ipt_helper");
MODULE_ALIAS("ip6t_helper");
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -36,61 +31,51 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_helper_info *info = matchinfo;
- struct nf_conn *ct;
- struct nf_conn_help *master_help;
+ const struct nf_conn *ct;
+ const struct nf_conn_help *master_help;
+ const struct nf_conntrack_helper *helper;
enum ip_conntrack_info ctinfo;
- int ret = info->invert;
+ bool ret = info->invert;
- ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
- if (!ct) {
- DEBUGP("xt_helper: Eek! invalid conntrack?\n");
+ ct = nf_ct_get(skb, &ctinfo);
+ if (!ct || !ct->master)
return ret;
- }
-
- if (!ct->master) {
- DEBUGP("xt_helper: conntrack %p has no master\n", ct);
- return ret;
- }
- read_lock_bh(&nf_conntrack_lock);
master_help = nfct_help(ct->master);
- if (!master_help || !master_help->helper) {
- DEBUGP("xt_helper: master ct %p has no helper\n",
- exp->expectant);
- goto out_unlock;
- }
+ if (!master_help)
+ return ret;
- DEBUGP("master's name = %s , info->name = %s\n",
- ct->master->helper->name, info->name);
+ /* rcu_read_lock()ed by nf_hook_slow */
+ helper = rcu_dereference(master_help->helper);
+ if (!helper)
+ return ret;
if (info->name[0] == '\0')
- ret ^= 1;
+ ret = !ret;
else
ret ^= !strncmp(master_help->helper->name, info->name,
strlen(master_help->helper->name));
-out_unlock:
- read_unlock_bh(&nf_conntrack_lock);
return ret;
}
-static int check(const char *tablename,
- const void *inf,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool check(const char *tablename,
+ const void *inf,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_helper_info *info = matchinfo;
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
- return 0;
+ return false;
}
info->name[29] = '\0';
- return 1;
+ return true;
}
static void
@@ -99,7 +84,7 @@ destroy(const struct xt_match *match, void *matchinfo)
nf_ct_l3proto_module_put(match->family);
}
-static struct xt_match xt_helper_match[] = {
+static struct xt_match xt_helper_match[] __read_mostly = {
{
.name = "helper",
.family = AF_INET,
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
index 77288c5ada7..3dad173d973 100644
--- a/net/netfilter/xt_length.c
+++ b/net/netfilter/xt_length.c
@@ -20,7 +20,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_length");
MODULE_ALIAS("ip6t_length");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_length_info *info = matchinfo;
u_int16_t pktlen = ntohs(ip_hdr(skb)->tot_len);
@@ -36,7 +36,7 @@ match(const struct sk_buff *skb,
return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
}
-static int
+static bool
match6(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -44,16 +44,16 @@ match6(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_length_info *info = matchinfo;
- const u_int16_t pktlen = (ntohs(ipv6_hdr(skb)->payload_len) +
- sizeof(struct ipv6hdr));
+ const u_int16_t pktlen = ntohs(ipv6_hdr(skb)->payload_len) +
+ sizeof(struct ipv6hdr);
return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
}
-static struct xt_match xt_length_match[] = {
+static struct xt_match xt_length_match[] __read_mostly = {
{
.name = "length",
.family = AF_INET,
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 571a72ab89a..4fcca797150 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -57,7 +57,7 @@ static DEFINE_SPINLOCK(limit_lock);
#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
-static int
+static bool
ipt_limit_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -65,9 +65,10 @@ ipt_limit_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
- struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master;
+ struct xt_rateinfo *r =
+ ((const struct xt_rateinfo *)matchinfo)->master;
unsigned long now = jiffies;
spin_lock_bh(&limit_lock);
@@ -79,11 +80,11 @@ ipt_limit_match(const struct sk_buff *skb,
/* We're not limited. */
r->credit -= r->cost;
spin_unlock_bh(&limit_lock);
- return 1;
+ return true;
}
spin_unlock_bh(&limit_lock);
- return 0;
+ return false;
}
/* Precision saver. */
@@ -98,7 +99,7 @@ user2credits(u_int32_t user)
return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
}
-static int
+static bool
ipt_limit_checkentry(const char *tablename,
const void *inf,
const struct xt_match *match,
@@ -112,7 +113,7 @@ ipt_limit_checkentry(const char *tablename,
|| user2credits(r->avg * r->burst) < user2credits(r->avg)) {
printk("Overflow in xt_limit, try lower: %u/%u\n",
r->avg, r->burst);
- return 0;
+ return false;
}
/* For SMP, we only want to use one set of counters. */
@@ -125,7 +126,7 @@ ipt_limit_checkentry(const char *tablename,
r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
r->cost = user2credits(r->avg);
}
- return 1;
+ return true;
}
#ifdef CONFIG_COMPAT
@@ -144,7 +145,7 @@ struct compat_xt_rateinfo {
* master pointer, which does not need to be preserved. */
static void compat_from_user(void *dst, void *src)
{
- struct compat_xt_rateinfo *cm = src;
+ const struct compat_xt_rateinfo *cm = src;
struct xt_rateinfo m = {
.avg = cm->avg,
.burst = cm->burst,
@@ -158,7 +159,7 @@ static void compat_from_user(void *dst, void *src)
static int compat_to_user(void __user *dst, void *src)
{
- struct xt_rateinfo *m = src;
+ const struct xt_rateinfo *m = src;
struct compat_xt_rateinfo cm = {
.avg = m->avg,
.burst = m->burst,
@@ -172,7 +173,7 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_match xt_limit_match[] = {
+static struct xt_match xt_limit_match[] __read_mostly = {
{
.name = "limit",
.family = AF_INET,
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
index 1d3a1d98b88..00490d777a0 100644
--- a/net/netfilter/xt_mac.c
+++ b/net/netfilter/xt_mac.c
@@ -24,7 +24,7 @@ MODULE_DESCRIPTION("iptables mac matching module");
MODULE_ALIAS("ipt_mac");
MODULE_ALIAS("ip6t_mac");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -32,19 +32,19 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_mac_info *info = matchinfo;
/* Is mac pointer valid? */
- return (skb_mac_header(skb) >= skb->head &&
- (skb_mac_header(skb) + ETH_HLEN) <= skb->data
- /* If so, compare... */
- && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
- ^ info->invert));
+ return skb_mac_header(skb) >= skb->head &&
+ skb_mac_header(skb) + ETH_HLEN <= skb->data
+ /* If so, compare... */
+ && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
+ ^ info->invert);
}
-static struct xt_match xt_mac_match[] = {
+static struct xt_match xt_mac_match[] __read_mostly = {
{
.name = "mac",
.family = AF_INET,
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 39911dddb01..c02a7f8f392 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -19,7 +19,7 @@ MODULE_DESCRIPTION("iptables mark matching module");
MODULE_ALIAS("ipt_mark");
MODULE_ALIAS("ip6t_mark");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -27,14 +27,14 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_mark_info *info = matchinfo;
return ((skb->mark & info->mask) == info->mark) ^ info->invert;
}
-static int
+static bool
checkentry(const char *tablename,
const void *entry,
const struct xt_match *match,
@@ -45,9 +45,9 @@ checkentry(const char *tablename,
if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
printk(KERN_WARNING "mark: only supports 32bit mark\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
#ifdef CONFIG_COMPAT
@@ -60,7 +60,7 @@ struct compat_xt_mark_info {
static void compat_from_user(void *dst, void *src)
{
- struct compat_xt_mark_info *cm = src;
+ const struct compat_xt_mark_info *cm = src;
struct xt_mark_info m = {
.mark = cm->mark,
.mask = cm->mask,
@@ -71,7 +71,7 @@ static void compat_from_user(void *dst, void *src)
static int compat_to_user(void __user *dst, void *src)
{
- struct xt_mark_info *m = src;
+ const struct xt_mark_info *m = src;
struct compat_xt_mark_info cm = {
.mark = m->mark,
.mask = m->mask,
@@ -81,7 +81,7 @@ static int compat_to_user(void __user *dst, void *src)
}
#endif /* CONFIG_COMPAT */
-static struct xt_match xt_mark_match[] = {
+static struct xt_match xt_mark_match[] __read_mostly = {
{
.name = "mark",
.family = AF_INET,
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index 4dce2a81702..e8ae10284ac 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -33,24 +33,24 @@ MODULE_ALIAS("ip6t_multiport");
#endif
/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
+static inline bool
ports_match(const u_int16_t *portlist, enum xt_multiport_flags flags,
u_int8_t count, u_int16_t src, u_int16_t dst)
{
unsigned int i;
for (i = 0; i < count; i++) {
if (flags != XT_MULTIPORT_DESTINATION && portlist[i] == src)
- return 1;
+ return true;
if (flags != XT_MULTIPORT_SOURCE && portlist[i] == dst)
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Returns 1 if the port is matched by the test, 0 otherwise. */
-static inline int
+static inline bool
ports_match_v1(const struct xt_multiport_v1 *minfo,
u_int16_t src, u_int16_t dst)
{
@@ -67,34 +67,34 @@ ports_match_v1(const struct xt_multiport_v1 *minfo,
if (minfo->flags == XT_MULTIPORT_SOURCE
&& src >= s && src <= e)
- return 1 ^ minfo->invert;
+ return true ^ minfo->invert;
if (minfo->flags == XT_MULTIPORT_DESTINATION
&& dst >= s && dst <= e)
- return 1 ^ minfo->invert;
+ return true ^ minfo->invert;
if (minfo->flags == XT_MULTIPORT_EITHER
&& ((dst >= s && dst <= e)
|| (src >= s && src <= e)))
- return 1 ^ minfo->invert;
+ return true ^ minfo->invert;
} else {
/* exact port matching */
duprintf("src or dst matches with %d?\n", s);
if (minfo->flags == XT_MULTIPORT_SOURCE
&& src == s)
- return 1 ^ minfo->invert;
+ return true ^ minfo->invert;
if (minfo->flags == XT_MULTIPORT_DESTINATION
&& dst == s)
- return 1 ^ minfo->invert;
+ return true ^ minfo->invert;
if (minfo->flags == XT_MULTIPORT_EITHER
&& (src == s || dst == s))
- return 1 ^ minfo->invert;
+ return true ^ minfo->invert;
}
}
return minfo->invert;
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -102,13 +102,13 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
__be16 _ports[2], *pptr;
const struct xt_multiport *multiinfo = matchinfo;
if (offset)
- return 0;
+ return false;
pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
if (pptr == NULL) {
@@ -116,8 +116,8 @@ match(const struct sk_buff *skb,
* can't. Hence, no choice but to drop.
*/
duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
return ports_match(multiinfo->ports,
@@ -125,7 +125,7 @@ match(const struct sk_buff *skb,
ntohs(pptr[0]), ntohs(pptr[1]));
}
-static int
+static bool
match_v1(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -133,13 +133,13 @@ match_v1(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
__be16 _ports[2], *pptr;
const struct xt_multiport_v1 *multiinfo = matchinfo;
if (offset)
- return 0;
+ return false;
pptr = skb_header_pointer(skb, protoff, sizeof(_ports), _ports);
if (pptr == NULL) {
@@ -147,14 +147,14 @@ match_v1(const struct sk_buff *skb,
* can't. Hence, no choice but to drop.
*/
duprintf("xt_multiport: Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
}
-static inline int
+static inline bool
check(u_int16_t proto,
u_int8_t ip_invflags,
u_int8_t match_flags,
@@ -172,7 +172,7 @@ check(u_int16_t proto,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
checkentry(const char *tablename,
const void *info,
const struct xt_match *match,
@@ -186,7 +186,7 @@ checkentry(const char *tablename,
multiinfo->count);
}
-static int
+static bool
checkentry_v1(const char *tablename,
const void *info,
const struct xt_match *match,
@@ -200,7 +200,7 @@ checkentry_v1(const char *tablename,
multiinfo->count);
}
-static int
+static bool
checkentry6(const char *tablename,
const void *info,
const struct xt_match *match,
@@ -214,7 +214,7 @@ checkentry6(const char *tablename,
multiinfo->count);
}
-static int
+static bool
checkentry6_v1(const char *tablename,
const void *info,
const struct xt_match *match,
@@ -228,7 +228,7 @@ checkentry6_v1(const char *tablename,
multiinfo->count);
}
-static struct xt_match xt_multiport_match[] = {
+static struct xt_match xt_multiport_match[] __read_mostly = {
{
.name = "multiport",
.family = AF_INET,
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 35a0fe200c3..f47cab7a696 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -14,8 +14,6 @@
#include <linux/netfilter/xt_physdev.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter_bridge.h>
-#define MATCH 1
-#define NOMATCH 0
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
@@ -23,7 +21,7 @@ MODULE_DESCRIPTION("iptables bridge physical device match module");
MODULE_ALIAS("ipt_physdev");
MODULE_ALIAS("ip6t_physdev");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -31,14 +29,14 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
int i;
static const char nulldevname[IFNAMSIZ];
const struct xt_physdev_info *info = matchinfo;
- unsigned int ret;
+ bool ret;
const char *indev, *outdev;
- struct nf_bridge_info *nf_bridge;
+ const struct nf_bridge_info *nf_bridge;
/* Not a bridged IP packet or no info available yet:
* LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
@@ -47,61 +45,61 @@ match(const struct sk_buff *skb,
/* Return MATCH if the invert flags of the used options are on */
if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
!(info->invert & XT_PHYSDEV_OP_BRIDGED))
- return NOMATCH;
+ return false;
if ((info->bitmask & XT_PHYSDEV_OP_ISIN) &&
!(info->invert & XT_PHYSDEV_OP_ISIN))
- return NOMATCH;
+ return false;
if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) &&
!(info->invert & XT_PHYSDEV_OP_ISOUT))
- return NOMATCH;
+ return false;
if ((info->bitmask & XT_PHYSDEV_OP_IN) &&
!(info->invert & XT_PHYSDEV_OP_IN))
- return NOMATCH;
+ return false;
if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
!(info->invert & XT_PHYSDEV_OP_OUT))
- return NOMATCH;
- return MATCH;
+ return false;
+ return true;
}
/* This only makes sense in the FORWARD and POSTROUTING chains */
if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
(!!(nf_bridge->mask & BRNF_BRIDGED) ^
!(info->invert & XT_PHYSDEV_OP_BRIDGED)))
- return NOMATCH;
+ return false;
if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
(!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
(info->bitmask & XT_PHYSDEV_OP_ISOUT &&
(!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
- return NOMATCH;
+ return false;
if (!(info->bitmask & XT_PHYSDEV_OP_IN))
goto match_outdev;
indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
- for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+ for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) {
ret |= (((const unsigned int *)indev)[i]
^ ((const unsigned int *)info->physindev)[i])
& ((const unsigned int *)info->in_mask)[i];
}
- if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN))
- return NOMATCH;
+ if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN))
+ return false;
match_outdev:
if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
- return MATCH;
+ return true;
outdev = nf_bridge->physoutdev ?
nf_bridge->physoutdev->name : nulldevname;
- for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+ for (i = 0, ret = false; i < IFNAMSIZ/sizeof(unsigned int); i++) {
ret |= (((const unsigned int *)outdev)[i]
^ ((const unsigned int *)info->physoutdev)[i])
& ((const unsigned int *)info->out_mask)[i];
}
- return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
+ return ret ^ !(info->invert & XT_PHYSDEV_OP_OUT);
}
-static int
+static bool
checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
@@ -112,7 +110,7 @@ checkentry(const char *tablename,
if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
info->bitmask & ~XT_PHYSDEV_OP_MASK)
- return 0;
+ return false;
if (info->bitmask & XT_PHYSDEV_OP_OUT &&
(!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
info->invert & XT_PHYSDEV_OP_BRIDGED) &&
@@ -122,12 +120,12 @@ checkentry(const char *tablename,
"OUTPUT, FORWARD and POSTROUTING chains for non-bridged "
"traffic is not supported anymore.\n");
if (hook_mask & (1 << NF_IP_LOCAL_OUT))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match xt_physdev_match[] = {
+static struct xt_match xt_physdev_match[] __read_mostly = {
{
.name = "physdev",
.family = AF_INET,
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
index e1409fc5c28..a52925f12f3 100644
--- a/net/netfilter/xt_pkttype.c
+++ b/net/netfilter/xt_pkttype.c
@@ -21,29 +21,29 @@ MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
MODULE_ALIAS("ipt_pkttype");
MODULE_ALIAS("ip6t_pkttype");
-static int match(const struct sk_buff *skb,
+static bool match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct xt_match *match,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
u_int8_t type;
const struct xt_pkttype_info *info = matchinfo;
if (skb->pkt_type == PACKET_LOOPBACK)
- type = (MULTICAST(ip_hdr(skb)->daddr)
+ type = MULTICAST(ip_hdr(skb)->daddr)
? PACKET_MULTICAST
- : PACKET_BROADCAST);
+ : PACKET_BROADCAST;
else
type = skb->pkt_type;
return (type == info->pkttype) ^ info->invert;
}
-static struct xt_match xt_pkttype_match[] = {
+static struct xt_match xt_pkttype_match[] __read_mostly = {
{
.name = "pkttype",
.family = AF_INET,
diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c
index 15b45a95ec1..6d6d3b7fcbb 100644
--- a/net/netfilter/xt_policy.c
+++ b/net/netfilter/xt_policy.c
@@ -20,7 +20,7 @@ MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_DESCRIPTION("Xtables IPsec policy matching module");
MODULE_LICENSE("GPL");
-static inline int
+static inline bool
xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m,
const union xt_policy_addr *a2, unsigned short family)
{
@@ -30,11 +30,11 @@ xt_addr_cmp(const union xt_policy_addr *a1, const union xt_policy_addr *m,
case AF_INET6:
return !ipv6_masked_addr_cmp(&a1->a6, &m->a6, &a2->a6);
}
- return 0;
+ return false;
}
-static inline int
-match_xfrm_state(struct xfrm_state *x, const struct xt_policy_elem *e,
+static inline bool
+match_xfrm_state(const struct xfrm_state *x, const struct xt_policy_elem *e,
unsigned short family)
{
#define MATCH_ADDR(x,y,z) (!e->match.x || \
@@ -55,7 +55,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info,
unsigned short family)
{
const struct xt_policy_elem *e;
- struct sec_path *sp = skb->sp;
+ const struct sec_path *sp = skb->sp;
int strict = info->flags & XT_POLICY_MATCH_STRICT;
int i, pos;
@@ -85,7 +85,7 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info,
unsigned short family)
{
const struct xt_policy_elem *e;
- struct dst_entry *dst = skb->dst;
+ const struct dst_entry *dst = skb->dst;
int strict = info->flags & XT_POLICY_MATCH_STRICT;
int i, pos;
@@ -108,14 +108,14 @@ match_policy_out(const struct sk_buff *skb, const struct xt_policy_info *info,
return strict ? i == info->len : 0;
}
-static int match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
+static bool match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_policy_info *info = matchinfo;
int ret;
@@ -126,45 +126,45 @@ static int match(const struct sk_buff *skb,
ret = match_policy_out(skb, info, match->family);
if (ret < 0)
- ret = info->flags & XT_POLICY_MATCH_NONE ? 1 : 0;
+ ret = info->flags & XT_POLICY_MATCH_NONE ? true : false;
else if (info->flags & XT_POLICY_MATCH_NONE)
- ret = 0;
+ ret = false;
return ret;
}
-static int checkentry(const char *tablename, const void *ip_void,
- const struct xt_match *match,
- void *matchinfo, unsigned int hook_mask)
+static bool checkentry(const char *tablename, const void *ip_void,
+ const struct xt_match *match,
+ void *matchinfo, unsigned int hook_mask)
{
struct xt_policy_info *info = matchinfo;
if (!(info->flags & (XT_POLICY_MATCH_IN|XT_POLICY_MATCH_OUT))) {
printk(KERN_ERR "xt_policy: neither incoming nor "
"outgoing policy selected\n");
- return 0;
+ return false;
}
/* hook values are equal for IPv4 and IPv6 */
if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
&& info->flags & XT_POLICY_MATCH_OUT) {
printk(KERN_ERR "xt_policy: output policy not valid in "
"PRE_ROUTING and INPUT\n");
- return 0;
+ return false;
}
if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
&& info->flags & XT_POLICY_MATCH_IN) {
printk(KERN_ERR "xt_policy: input policy not valid in "
"POST_ROUTING and OUTPUT\n");
- return 0;
+ return false;
}
if (info->len > XT_POLICY_MAX_ELEM) {
printk(KERN_ERR "xt_policy: too many policy elements\n");
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static struct xt_match xt_policy_match[] = {
+static struct xt_match xt_policy_match[] __read_mostly = {
{
.name = "policy",
.family = AF_INET,
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
index bfdde06ca0b..dae97445b87 100644
--- a/net/netfilter/xt_quota.c
+++ b/net/netfilter/xt_quota.c
@@ -16,19 +16,20 @@ MODULE_ALIAS("ip6t_quota");
static DEFINE_SPINLOCK(quota_lock);
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+ int offset, unsigned int protoff, bool *hotdrop)
{
- struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master;
- int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0;
+ struct xt_quota_info *q =
+ ((const struct xt_quota_info *)matchinfo)->master;
+ bool ret = q->flags & XT_QUOTA_INVERT;
spin_lock_bh(&quota_lock);
if (q->quota >= skb->len) {
q->quota -= skb->len;
- ret ^= 1;
+ ret = !ret;
} else {
/* we do not allow even small packets from now on */
q->quota = 0;
@@ -38,21 +39,21 @@ match(const struct sk_buff *skb,
return ret;
}
-static int
+static bool
checkentry(const char *tablename, const void *entry,
const struct xt_match *match, void *matchinfo,
unsigned int hook_mask)
{
- struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
+ struct xt_quota_info *q = matchinfo;
if (q->flags & ~XT_QUOTA_MASK)
- return 0;
+ return false;
/* For SMP, we only want to use one set of counters. */
q->master = q;
- return 1;
+ return true;
}
-static struct xt_match xt_quota_match[] = {
+static struct xt_match xt_quota_match[] __read_mostly = {
{
.name = "quota",
.family = AF_INET,
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
index c2017f8af9c..cc3e76d77a9 100644
--- a/net/netfilter/xt_realm.c
+++ b/net/netfilter/xt_realm.c
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("X_tables realm match");
MODULE_ALIAS("ipt_realm");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -29,15 +29,15 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_realm_info *info = matchinfo;
- struct dst_entry *dst = skb->dst;
+ const struct dst_entry *dst = skb->dst;
return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
}
-static struct xt_match realm_match = {
+static struct xt_match realm_match __read_mostly = {
.name = "realm",
.match = match,
.matchsize = sizeof(struct xt_realm_info),
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index f86d8d769d4..c002153b80a 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -23,7 +23,7 @@ MODULE_ALIAS("ipt_sctp");
#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
|| (!!((invflag) & (option)) ^ (cond)))
-static int
+static bool
match_flags(const struct xt_sctp_flag_info *flag_info,
const int flag_count,
u_int8_t chunktype,
@@ -31,23 +31,21 @@ match_flags(const struct xt_sctp_flag_info *flag_info,
{
int i;
- for (i = 0; i < flag_count; i++) {
- if (flag_info[i].chunktype == chunktype) {
+ for (i = 0; i < flag_count; i++)
+ if (flag_info[i].chunktype == chunktype)
return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
- }
- }
- return 1;
+ return true;
}
-static inline int
+static inline bool
match_packet(const struct sk_buff *skb,
unsigned int offset,
const u_int32_t *chunkmap,
int chunk_match_type,
const struct xt_sctp_flag_info *flag_info,
const int flag_count,
- int *hotdrop)
+ bool *hotdrop)
{
u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
sctp_chunkhdr_t _sch, *sch;
@@ -56,16 +54,15 @@ match_packet(const struct sk_buff *skb,
int i = 0;
#endif
- if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
+ if (chunk_match_type == SCTP_CHUNK_MATCH_ALL)
SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
- }
do {
sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
if (sch == NULL || sch->length == 0) {
duprintf("Dropping invalid SCTP packet.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
@@ -80,28 +77,26 @@ match_packet(const struct sk_buff *skb,
case SCTP_CHUNK_MATCH_ANY:
if (match_flags(flag_info, flag_count,
sch->type, sch->flags)) {
- return 1;
+ return true;
}
break;
case SCTP_CHUNK_MATCH_ALL:
if (match_flags(flag_info, flag_count,
- sch->type, sch->flags)) {
+ sch->type, sch->flags))
SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
- }
break;
case SCTP_CHUNK_MATCH_ONLY:
if (!match_flags(flag_info, flag_count,
- sch->type, sch->flags)) {
- return 0;
- }
+ sch->type, sch->flags))
+ return false;
break;
}
} else {
switch (chunk_match_type) {
case SCTP_CHUNK_MATCH_ONLY:
- return 0;
+ return false;
}
}
} while (offset < skb->len);
@@ -110,16 +105,16 @@ match_packet(const struct sk_buff *skb,
case SCTP_CHUNK_MATCH_ALL:
return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
case SCTP_CHUNK_MATCH_ANY:
- return 0;
+ return false;
case SCTP_CHUNK_MATCH_ONLY:
- return 1;
+ return true;
}
/* This will never be reached, but required to stop compiler whine */
- return 0;
+ return false;
}
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -127,29 +122,29 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_sctp_info *info = matchinfo;
sctp_sctphdr_t _sh, *sh;
if (offset) {
duprintf("Dropping non-first fragment.. FIXME\n");
- return 0;
+ return false;
}
sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
if (sh == NULL) {
duprintf("Dropping evil TCP offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
- return SCCHECK(((ntohs(sh->source) >= info->spts[0])
- && (ntohs(sh->source) <= info->spts[1])),
+ return SCCHECK(ntohs(sh->source) >= info->spts[0]
+ && ntohs(sh->source) <= info->spts[1],
XT_SCTP_SRC_PORTS, info->flags, info->invflags)
- && SCCHECK(((ntohs(sh->dest) >= info->dpts[0])
- && (ntohs(sh->dest) <= info->dpts[1])),
+ && SCCHECK(ntohs(sh->dest) >= info->dpts[0]
+ && ntohs(sh->dest) <= info->dpts[1],
XT_SCTP_DEST_PORTS, info->flags, info->invflags)
&& SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t),
info->chunkmap, info->chunk_match_type,
@@ -158,7 +153,7 @@ match(const struct sk_buff *skb,
XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
}
-static int
+static bool
checkentry(const char *tablename,
const void *inf,
const struct xt_match *match,
@@ -177,7 +172,7 @@ checkentry(const char *tablename,
| SCTP_CHUNK_MATCH_ONLY)));
}
-static struct xt_match xt_sctp_match[] = {
+static struct xt_match xt_sctp_match[] __read_mostly = {
{
.name = "sctp",
.family = AF_INET,
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
index 149294f7df7..e0a528df19a 100644
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -20,7 +20,7 @@ MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module");
MODULE_ALIAS("ipt_state");
MODULE_ALIAS("ip6t_state");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_state_info *sinfo = matchinfo;
enum ip_conntrack_info ctinfo;
@@ -44,18 +44,18 @@ match(const struct sk_buff *skb,
return (sinfo->statemask & statebit);
}
-static int check(const char *tablename,
- const void *inf,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool check(const char *tablename,
+ const void *inf,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask)
{
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load conntrack support for "
"proto=%d\n", match->family);
- return 0;
+ return false;
}
- return 1;
+ return true;
}
static void
@@ -64,7 +64,7 @@ destroy(const struct xt_match *match, void *matchinfo)
nf_ct_l3proto_module_put(match->family);
}
-static struct xt_match xt_state_match[] = {
+static struct xt_match xt_state_match[] __read_mostly = {
{
.name = "state",
.family = AF_INET,
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
index 091a9f89f5d..4089dae4e28 100644
--- a/net/netfilter/xt_statistic.c
+++ b/net/netfilter/xt_statistic.c
@@ -24,26 +24,26 @@ MODULE_ALIAS("ip6t_statistic");
static DEFINE_SPINLOCK(nth_lock);
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+ int offset, unsigned int protoff, bool *hotdrop)
{
struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
- int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0;
+ bool ret = info->flags & XT_STATISTIC_INVERT;
switch (info->mode) {
case XT_STATISTIC_MODE_RANDOM:
if ((net_random() & 0x7FFFFFFF) < info->u.random.probability)
- ret ^= 1;
+ ret = !ret;
break;
case XT_STATISTIC_MODE_NTH:
info = info->master;
spin_lock_bh(&nth_lock);
if (info->u.nth.count++ == info->u.nth.every) {
info->u.nth.count = 0;
- ret ^= 1;
+ ret = !ret;
}
spin_unlock_bh(&nth_lock);
break;
@@ -52,21 +52,21 @@ match(const struct sk_buff *skb,
return ret;
}
-static int
+static bool
checkentry(const char *tablename, const void *entry,
const struct xt_match *match, void *matchinfo,
unsigned int hook_mask)
{
- struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+ struct xt_statistic_info *info = matchinfo;
if (info->mode > XT_STATISTIC_MODE_MAX ||
info->flags & ~XT_STATISTIC_MASK)
- return 0;
+ return false;
info->master = info;
- return 1;
+ return true;
}
-static struct xt_match xt_statistic_match[] = {
+static struct xt_match xt_statistic_match[] __read_mostly = {
{
.name = "statistic",
.family = AF_INET,
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 999a005dbd0..864133442cd 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -21,14 +21,14 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_string");
MODULE_ALIAS("ip6t_string");
-static int match(const struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- const struct xt_match *match,
- const void *matchinfo,
- int offset,
- unsigned int protoff,
- int *hotdrop)
+static bool match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo,
+ int offset,
+ unsigned int protoff,
+ bool *hotdrop)
{
const struct xt_string_info *conf = matchinfo;
struct ts_state state;
@@ -42,30 +42,30 @@ static int match(const struct sk_buff *skb,
#define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
-static int checkentry(const char *tablename,
- const void *ip,
- const struct xt_match *match,
- void *matchinfo,
- unsigned int hook_mask)
+static bool checkentry(const char *tablename,
+ const void *ip,
+ const struct xt_match *match,
+ void *matchinfo,
+ unsigned int hook_mask)
{
struct xt_string_info *conf = matchinfo;
struct ts_config *ts_conf;
/* Damn, can't handle this case properly with iptables... */
if (conf->from_offset > conf->to_offset)
- return 0;
+ return false;
if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0')
- return 0;
+ return false;
if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE)
- return 0;
+ return false;
ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
GFP_KERNEL, TS_AUTOLOAD);
if (IS_ERR(ts_conf))
- return 0;
+ return false;
conf->config = ts_conf;
- return 1;
+ return true;
}
static void destroy(const struct xt_match *match, void *matchinfo)
@@ -73,7 +73,7 @@ static void destroy(const struct xt_match *match, void *matchinfo)
textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
}
-static struct xt_match xt_string_match[] = {
+static struct xt_match xt_string_match[] __read_mostly = {
{
.name = "string",
.family = AF_INET,
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
index 80571d0749f..cd5f6d758c6 100644
--- a/net/netfilter/xt_tcpmss.c
+++ b/net/netfilter/xt_tcpmss.c
@@ -23,7 +23,7 @@ MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables TCP MSS match module");
MODULE_ALIAS("ipt_tcpmss");
-static int
+static bool
match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -31,7 +31,7 @@ match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
const struct xt_tcpmss_match_info *info = matchinfo;
struct tcphdr _tcph, *th;
@@ -77,11 +77,11 @@ out:
return info->invert;
dropit:
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
-static struct xt_match xt_tcpmss_match[] = {
+static struct xt_match xt_tcpmss_match[] __read_mostly = {
{
.name = "tcpmss",
.family = AF_INET,
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
index 46414b562a1..ab7d845224f 100644
--- a/net/netfilter/xt_tcpudp.c
+++ b/net/netfilter/xt_tcpudp.c
@@ -27,22 +27,19 @@ MODULE_ALIAS("ip6t_tcp");
/* Returns 1 if the port is matched by the range, 0 otherwise */
-static inline int
-port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
+static inline bool
+port_match(u_int16_t min, u_int16_t max, u_int16_t port, bool invert)
{
- int ret;
-
- ret = (port >= min && port <= max) ^ invert;
- return ret;
+ return (port >= min && port <= max) ^ invert;
}
-static int
+static bool
tcp_find_option(u_int8_t option,
const struct sk_buff *skb,
unsigned int protoff,
unsigned int optlen,
- int invert,
- int *hotdrop)
+ bool invert,
+ bool *hotdrop)
{
/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
@@ -57,8 +54,8 @@ tcp_find_option(u_int8_t option,
op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr),
optlen, _opt);
if (op == NULL) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
for (i = 0; i < optlen; ) {
@@ -70,7 +67,7 @@ tcp_find_option(u_int8_t option,
return invert;
}
-static int
+static bool
tcp_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -78,7 +75,7 @@ tcp_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
struct tcphdr _tcph, *th;
const struct xt_tcp *tcpinfo = matchinfo;
@@ -92,51 +89,51 @@ tcp_match(const struct sk_buff *skb,
*/
if (offset == 1) {
duprintf("Dropping evil TCP offset=1 frag.\n");
- *hotdrop = 1;
+ *hotdrop = true;
}
/* Must not be a fragment. */
- return 0;
+ return false;
}
-#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
+#define FWINVTCP(bool, invflg) ((bool) ^ !!(tcpinfo->invflags & (invflg)))
th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
if (th == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil TCP offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
ntohs(th->source),
!!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
- return 0;
+ return false;
if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
ntohs(th->dest),
!!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
- return 0;
+ return false;
if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
== tcpinfo->flg_cmp,
XT_TCP_INV_FLAGS))
- return 0;
+ return false;
if (tcpinfo->option) {
if (th->doff * 4 < sizeof(_tcph)) {
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
if (!tcp_find_option(tcpinfo->option, skb, protoff,
th->doff*4 - sizeof(_tcph),
tcpinfo->invflags & XT_TCP_INV_OPTION,
hotdrop))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
tcp_checkentry(const char *tablename,
const void *info,
const struct xt_match *match,
@@ -149,7 +146,7 @@ tcp_checkentry(const char *tablename,
return !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
}
-static int
+static bool
udp_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
@@ -157,22 +154,22 @@ udp_match(const struct sk_buff *skb,
const void *matchinfo,
int offset,
unsigned int protoff,
- int *hotdrop)
+ bool *hotdrop)
{
struct udphdr _udph, *uh;
const struct xt_udp *udpinfo = matchinfo;
/* Must not be a fragment. */
if (offset)
- return 0;
+ return false;
uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
if (uh == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil UDP tinygram.\n");
- *hotdrop = 1;
- return 0;
+ *hotdrop = true;
+ return false;
}
return port_match(udpinfo->spts[0], udpinfo->spts[1],
@@ -184,7 +181,7 @@ udp_match(const struct sk_buff *skb,
}
/* Called when user tries to insert an entry of this type. */
-static int
+static bool
udp_checkentry(const char *tablename,
const void *info,
const struct xt_match *match,
@@ -197,7 +194,7 @@ udp_checkentry(const char *tablename,
return !(udpinfo->invflags & ~XT_UDP_INV_MASK);
}
-static struct xt_match xt_tcpudp_match[] = {
+static struct xt_match xt_tcpudp_match[] __read_mostly = {
{
.name = "tcp",
.family = AF_INET,
diff --git a/net/netfilter/xt_u32.c b/net/netfilter/xt_u32.c
new file mode 100644
index 00000000000..04b677ae8da
--- /dev/null
+++ b/net/netfilter/xt_u32.c
@@ -0,0 +1,135 @@
+/*
+ * xt_u32 - kernel module to match u32 packet content
+ *
+ * Original author: Don Cohen <don@isis.cs3-inc.com>
+ * © Jan Engelhardt <jengelh@gmx.de>, 2007
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_u32.h>
+
+static bool u32_match_it(const struct xt_u32 *data,
+ const struct sk_buff *skb)
+{
+ const struct xt_u32_test *ct;
+ unsigned int testind;
+ unsigned int nnums;
+ unsigned int nvals;
+ unsigned int i;
+ u_int32_t pos;
+ u_int32_t val;
+ u_int32_t at;
+ int ret;
+
+ /*
+ * Small example: "0 >> 28 == 4 && 8 & 0xFF0000 >> 16 = 6, 17"
+ * (=IPv4 and (TCP or UDP)). Outer loop runs over the "&&" operands.
+ */
+ for (testind = 0; testind < data->ntests; ++testind) {
+ ct = &data->tests[testind];
+ at = 0;
+ pos = ct->location[0].number;
+
+ if (skb->len < 4 || pos > skb->len - 4);
+ return false;
+
+ ret = skb_copy_bits(skb, pos, &val, sizeof(val));
+ BUG_ON(ret < 0);
+ val = ntohl(val);
+ nnums = ct->nnums;
+
+ /* Inner loop runs over "&", "<<", ">>" and "@" operands */
+ for (i = 1; i < nnums; ++i) {
+ u_int32_t number = ct->location[i].number;
+ switch (ct->location[i].nextop) {
+ case XT_U32_AND:
+ val &= number;
+ break;
+ case XT_U32_LEFTSH:
+ val <<= number;
+ break;
+ case XT_U32_RIGHTSH:
+ val >>= number;
+ break;
+ case XT_U32_AT:
+ if (at + val < at)
+ return false;
+ at += val;
+ pos = number;
+ if (at + 4 < at || skb->len < at + 4 ||
+ pos > skb->len - at - 4)
+ return false;
+
+ ret = skb_copy_bits(skb, at + pos, &val,
+ sizeof(val));
+ BUG_ON(ret < 0);
+ val = ntohl(val);
+ break;
+ }
+ }
+
+ /* Run over the "," and ":" operands */
+ nvals = ct->nvalues;
+ for (i = 0; i < nvals; ++i)
+ if (ct->value[i].min <= val && val <= ct->value[i].max)
+ break;
+
+ if (i >= ct->nvalues)
+ return false;
+ }
+
+ return true;
+}
+
+static bool u32_match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match, const void *matchinfo,
+ int offset, unsigned int protoff, bool *hotdrop)
+{
+ const struct xt_u32 *data = matchinfo;
+ bool ret;
+
+ ret = u32_match_it(data, skb);
+ return ret ^ data->invert;
+}
+
+static struct xt_match u32_reg[] __read_mostly = {
+ {
+ .name = "u32",
+ .family = AF_INET,
+ .match = u32_match,
+ .matchsize = sizeof(struct xt_u32),
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "u32",
+ .family = AF_INET6,
+ .match = u32_match,
+ .matchsize = sizeof(struct xt_u32),
+ .me = THIS_MODULE,
+ },
+};
+
+static int __init xt_u32_init(void)
+{
+ return xt_register_matches(u32_reg, ARRAY_SIZE(u32_reg));
+}
+
+static void __exit xt_u32_exit(void)
+{
+ xt_unregister_matches(u32_reg, ARRAY_SIZE(u32_reg));
+}
+
+module_init(xt_u32_init);
+module_exit(xt_u32_exit);
+MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
+MODULE_DESCRIPTION("netfilter u32 match module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_u32");
+MODULE_ALIAS("ip6t_u32");
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 07e47dbcb0a..24b660f16ce 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -59,7 +59,7 @@ static struct genl_family netlbl_cipsov4_gnl_family = {
};
/* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
+static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1] = {
[NLBL_CIPSOV4_A_DOI] = { .type = NLA_U32 },
[NLBL_CIPSOV4_A_MTYPE] = { .type = NLA_U32 },
[NLBL_CIPSOV4_A_TAG] = { .type = NLA_U8 },
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index f2535e7f286..b165712aaa7 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -246,19 +246,18 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
/**
* netlbl_socket_setattr - Label a socket using the correct protocol
- * @sock: the socket to label
+ * @sk: the socket to label
* @secattr: the security attributes
*
* Description:
* Attach the correct label to the given socket using the security attributes
- * specified in @secattr. This function requires exclusive access to
- * @sock->sk, which means it either needs to be in the process of being
- * created or locked via lock_sock(sock->sk). Returns zero on success,
- * negative values on failure.
+ * specified in @secattr. This function requires exclusive access to @sk,
+ * which means it either needs to be in the process of being created or locked.
+ * Returns zero on success, negative values on failure.
*
*/
-int netlbl_socket_setattr(const struct socket *sock,
- const struct netlbl_lsm_secattr *secattr)
+int netlbl_sock_setattr(struct sock *sk,
+ const struct netlbl_lsm_secattr *secattr)
{
int ret_val = -ENOENT;
struct netlbl_dom_map *dom_entry;
@@ -269,9 +268,9 @@ int netlbl_socket_setattr(const struct socket *sock,
goto socket_setattr_return;
switch (dom_entry->type) {
case NETLBL_NLTYPE_CIPSOV4:
- ret_val = cipso_v4_socket_setattr(sock,
- dom_entry->type_def.cipsov4,
- secattr);
+ ret_val = cipso_v4_sock_setattr(sk,
+ dom_entry->type_def.cipsov4,
+ secattr);
break;
case NETLBL_NLTYPE_UNLABELED:
ret_val = 0;
@@ -309,30 +308,6 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
}
/**
- * netlbl_socket_getattr - Determine the security attributes of a socket
- * @sock: the socket
- * @secattr: the security attributes
- *
- * Description:
- * Examines the given socket to see any NetLabel style labeling has been
- * applied to the socket, if so it parses the socket label and returns the
- * security attributes in @secattr. Returns zero on success, negative values
- * on failure.
- *
- */
-int netlbl_socket_getattr(const struct socket *sock,
- struct netlbl_lsm_secattr *secattr)
-{
- int ret_val;
-
- ret_val = cipso_v4_socket_getattr(sock, secattr);
- if (ret_val == 0)
- return 0;
-
- return netlbl_unlabel_getattr(secattr);
-}
-
-/**
* netlbl_skbuff_getattr - Determine the security attributes of a packet
* @skb: the packet
* @secattr: the security attributes
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index e8c80f33f3d..e00fc219c72 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -59,7 +59,7 @@ static struct genl_family netlbl_mgmt_gnl_family = {
};
/* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
+static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
[NLBL_MGMT_A_DOMAIN] = { .type = NLA_NUL_STRING },
[NLBL_MGMT_A_PROTOCOL] = { .type = NLA_U32 },
[NLBL_MGMT_A_VERSION] = { .type = NLA_U32 },
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index b931edee4b8..5c303c68af1 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -61,7 +61,7 @@ static struct genl_family netlbl_unlabel_gnl_family = {
};
/* NetLabel Netlink attribute policy */
-static struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
+static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = {
[NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 },
};
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1f15821c8da..a3c8e692f49 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1713,7 +1713,7 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations netlink_seq_ops = {
+static const struct seq_operations netlink_seq_ops = {
.start = netlink_seq_start,
.next = netlink_seq_next,
.stop = netlink_seq_stop,
diff --git a/net/netlink/attr.c b/net/netlink/attr.c
index df5f820a4c3..e4d7bed99c2 100644
--- a/net/netlink/attr.c
+++ b/net/netlink/attr.c
@@ -24,9 +24,9 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = {
};
static int validate_nla(struct nlattr *nla, int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
- struct nla_policy *pt;
+ const struct nla_policy *pt;
int minlen = 0, attrlen = nla_len(nla);
if (nla->nla_type <= 0 || nla->nla_type > maxtype)
@@ -72,6 +72,17 @@ static int validate_nla(struct nlattr *nla, int maxtype,
return -ERANGE;
break;
+ case NLA_NESTED_COMPAT:
+ if (attrlen < pt->len)
+ return -ERANGE;
+ if (attrlen < NLA_ALIGN(pt->len))
+ break;
+ if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN)
+ return -ERANGE;
+ nla = nla_data(nla) + NLA_ALIGN(pt->len);
+ if (attrlen < NLA_ALIGN(pt->len) + NLA_HDRLEN + nla_len(nla))
+ return -ERANGE;
+ break;
default:
if (pt->len)
minlen = pt->len;
@@ -99,7 +110,7 @@ static int validate_nla(struct nlattr *nla, int maxtype,
* Returns 0 on success or a negative error code.
*/
int nla_validate(struct nlattr *head, int len, int maxtype,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
struct nlattr *nla;
int rem, err;
@@ -130,7 +141,7 @@ errout:
* Returns 0 on success or a negative error code.
*/
int nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, int len,
- struct nla_policy *policy)
+ const struct nla_policy *policy)
{
struct nlattr *nla;
int rem, err;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 6e31234a419..b9ab62f938d 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -472,7 +472,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
return skb;
}
-static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] __read_mostly = {
+static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
[CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
.len = GENL_NAMSIZ - 1 },
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 5d4a26c2aa0..5d66490dd29 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1328,7 +1328,7 @@ static int nr_info_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations nr_info_seqops = {
+static const struct seq_operations nr_info_seqops = {
.start = nr_info_start,
.next = nr_info_next,
.stop = nr_info_stop,
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 2f76e062609..24fe4a66d29 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -922,7 +922,7 @@ static int nr_node_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations nr_node_seqops = {
+static const struct seq_operations nr_node_seqops = {
.start = nr_node_start,
.next = nr_node_next,
.stop = nr_node_stop,
@@ -1006,7 +1006,7 @@ static int nr_neigh_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations nr_neigh_seqops = {
+static const struct seq_operations nr_neigh_seqops = {
.start = nr_neigh_start,
.next = nr_neigh_next,
.stop = nr_neigh_stop,
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 02e401cd683..7c27bd389b7 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -83,22 +83,6 @@
#include <net/inet_common.h>
#endif
-#define CONFIG_SOCK_PACKET 1
-
-/*
- Proposed replacement for SIOC{ADD,DEL}MULTI and
- IFF_PROMISC, IFF_ALLMULTI flags.
-
- It is more expensive, but I believe,
- it is really correct solution: reentereble, safe and fault tolerant.
-
- IFF_PROMISC/IFF_ALLMULTI/SIOC{ADD/DEL}MULTI are faked by keeping
- reference count and global flag, so that real status is
- (gflag|(count != 0)), so that we can use obsolete faulty interface
- not harming clever users.
- */
-#define CONFIG_PACKET_MULTICAST 1
-
/*
Assumptions:
- if device has no dev->hard_header routine, it adds and removes ll header
@@ -159,7 +143,6 @@ static atomic_t packet_socks_nr;
/* Private packet socket structures. */
-#ifdef CONFIG_PACKET_MULTICAST
struct packet_mclist
{
struct packet_mclist *next;
@@ -179,7 +162,7 @@ struct packet_mreq_max
unsigned short mr_alen;
unsigned char mr_address[MAX_ADDR_LEN];
};
-#endif
+
#ifdef CONFIG_PACKET_MMAP
static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing);
#endif
@@ -205,9 +188,7 @@ struct packet_sock {
origdev:1;
int ifindex; /* bound device */
__be16 num;
-#ifdef CONFIG_PACKET_MULTICAST
struct packet_mclist *mclist;
-#endif
#ifdef CONFIG_PACKET_MMAP
atomic_t mapped;
unsigned int pg_vec_order;
@@ -263,7 +244,6 @@ static void packet_sock_destruct(struct sock *sk)
static const struct proto_ops packet_ops;
-#ifdef CONFIG_SOCK_PACKET
static const struct proto_ops packet_ops_spkt;
static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
@@ -435,7 +415,6 @@ out_unlock:
dev_put(dev);
return err;
}
-#endif
static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
unsigned int res)
@@ -851,9 +830,7 @@ static int packet_release(struct socket *sock)
__sock_put(sk);
}
-#ifdef CONFIG_PACKET_MULTICAST
packet_flush_mclist(sk);
-#endif
#ifdef CONFIG_PACKET_MMAP
if (po->pg_vec) {
@@ -936,8 +913,6 @@ out_unlock:
* Bind a packet socket to a device
*/
-#ifdef CONFIG_SOCK_PACKET
-
static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk=sock->sk;
@@ -960,7 +935,6 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr, int add
}
return err;
}
-#endif
static int packet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
@@ -1012,11 +986,8 @@ static int packet_create(struct socket *sock, int protocol)
if (!capable(CAP_NET_RAW))
return -EPERM;
- if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW
-#ifdef CONFIG_SOCK_PACKET
- && sock->type != SOCK_PACKET
-#endif
- )
+ if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW &&
+ sock->type != SOCK_PACKET)
return -ESOCKTNOSUPPORT;
sock->state = SS_UNCONNECTED;
@@ -1027,10 +998,9 @@ static int packet_create(struct socket *sock, int protocol)
goto out;
sock->ops = &packet_ops;
-#ifdef CONFIG_SOCK_PACKET
if (sock->type == SOCK_PACKET)
sock->ops = &packet_ops_spkt;
-#endif
+
sock_init_data(sock, sk);
po = pkt_sk(sk);
@@ -1046,10 +1016,10 @@ static int packet_create(struct socket *sock, int protocol)
spin_lock_init(&po->bind_lock);
po->prot_hook.func = packet_rcv;
-#ifdef CONFIG_SOCK_PACKET
+
if (sock->type == SOCK_PACKET)
po->prot_hook.func = packet_rcv_spkt;
-#endif
+
po->prot_hook.af_packet_priv = sk;
if (proto) {
@@ -1169,7 +1139,6 @@ out:
return err;
}
-#ifdef CONFIG_SOCK_PACKET
static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
@@ -1190,7 +1159,6 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
return 0;
}
-#endif
static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
@@ -1221,7 +1189,6 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
return 0;
}
-#ifdef CONFIG_PACKET_MULTICAST
static void packet_dev_mc(struct net_device *dev, struct packet_mclist *i, int what)
{
switch (i->type) {
@@ -1349,7 +1316,6 @@ static void packet_flush_mclist(struct sock *sk)
}
rtnl_unlock();
}
-#endif
static int
packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, int optlen)
@@ -1362,7 +1328,6 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
return -ENOPROTOOPT;
switch(optname) {
-#ifdef CONFIG_PACKET_MULTICAST
case PACKET_ADD_MEMBERSHIP:
case PACKET_DROP_MEMBERSHIP:
{
@@ -1383,7 +1348,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
ret = packet_mc_drop(sk, &mreq);
return ret;
}
-#endif
+
#ifdef CONFIG_PACKET_MMAP
case PACKET_RX_RING:
{
@@ -1506,11 +1471,10 @@ static int packet_notifier(struct notifier_block *this, unsigned long msg, void
switch (msg) {
case NETDEV_UNREGISTER:
-#ifdef CONFIG_PACKET_MULTICAST
if (po->mclist)
packet_dev_mclist(dev, po->mclist, -1);
- // fallthrough
-#endif
+ /* fallthrough */
+
case NETDEV_DOWN:
if (dev->ifindex == po->ifindex) {
spin_lock(&po->bind_lock);
@@ -1856,7 +1820,6 @@ out:
#endif
-#ifdef CONFIG_SOCK_PACKET
static const struct proto_ops packet_ops_spkt = {
.family = PF_PACKET,
.owner = THIS_MODULE,
@@ -1877,7 +1840,6 @@ static const struct proto_ops packet_ops_spkt = {
.mmap = sock_no_mmap,
.sendpage = sock_no_sendpage,
};
-#endif
static const struct proto_ops packet_ops = {
.family = PF_PACKET,
@@ -1966,7 +1928,7 @@ static int packet_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations packet_seq_ops = {
+static const struct seq_operations packet_seq_ops = {
.start = packet_seq_start,
.next = packet_seq_next,
.stop = packet_seq_stop,
diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c
index e5c840c3028..230e35c5978 100644
--- a/net/rfkill/rfkill-input.c
+++ b/net/rfkill/rfkill-input.c
@@ -55,7 +55,7 @@ static void rfkill_task_handler(struct work_struct *work)
static void rfkill_schedule_toggle(struct rfkill_task *task)
{
- unsigned int flags;
+ unsigned long flags;
spin_lock_irqsave(&task->lock, flags);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index d476c43d521..f4d3aba0080 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1454,7 +1454,7 @@ static int rose_info_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations rose_info_seqops = {
+static const struct seq_operations rose_info_seqops = {
.start = rose_info_start,
.next = rose_info_next,
.stop = rose_info_stop,
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index 929a784a86d..bbcbad1da0d 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -1118,7 +1118,7 @@ static int rose_node_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations rose_node_seqops = {
+static const struct seq_operations rose_node_seqops = {
.start = rose_node_start,
.next = rose_node_next,
.stop = rose_node_stop,
@@ -1200,7 +1200,7 @@ static int rose_neigh_show(struct seq_file *seq, void *v)
}
-static struct seq_operations rose_neigh_seqops = {
+static const struct seq_operations rose_neigh_seqops = {
.start = rose_neigh_start,
.next = rose_neigh_next,
.stop = rose_neigh_stop,
@@ -1284,7 +1284,7 @@ static int rose_route_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations rose_route_seqops = {
+static const struct seq_operations rose_route_seqops = {
.start = rose_route_start,
.next = rose_route_next,
.stop = rose_route_stop,
diff --git a/net/rxrpc/ar-connection.c b/net/rxrpc/ar-connection.c
index 43cb3e051ec..482750efc23 100644
--- a/net/rxrpc/ar-connection.c
+++ b/net/rxrpc/ar-connection.c
@@ -211,7 +211,7 @@ static struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
conn->header_size = sizeof(struct rxrpc_header);
}
- _leave(" = %p{%d}", conn, conn->debug_id);
+ _leave(" = %p{%d}", conn, conn ? conn->debug_id : 0);
return conn;
}
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c
index 591c4422205..cc9102c5b58 100644
--- a/net/rxrpc/ar-output.c
+++ b/net/rxrpc/ar-output.c
@@ -640,6 +640,7 @@ static int rxrpc_send_data(struct kiocb *iocb,
goto efault;
sp->remain -= copy;
skb->mark += copy;
+ copied += copy;
len -= copy;
segment -= copy;
@@ -709,6 +710,8 @@ static int rxrpc_send_data(struct kiocb *iocb,
} while (segment > 0);
+success:
+ ret = copied;
out:
call->tx_pending = skb;
_leave(" = %d", ret);
@@ -725,7 +728,7 @@ call_aborted:
maybe_error:
if (copied)
- ret = copied;
+ goto success;
goto out;
efault:
diff --git a/net/rxrpc/ar-proc.c b/net/rxrpc/ar-proc.c
index 1c0be0e77b1..2e83ce325d1 100644
--- a/net/rxrpc/ar-proc.c
+++ b/net/rxrpc/ar-proc.c
@@ -30,31 +30,13 @@ static const char *rxrpc_conn_states[] = {
*/
static void *rxrpc_call_seq_start(struct seq_file *seq, loff_t *_pos)
{
- struct list_head *_p;
- loff_t pos = *_pos;
-
read_lock(&rxrpc_call_lock);
- if (!pos)
- return SEQ_START_TOKEN;
- pos--;
-
- list_for_each(_p, &rxrpc_calls)
- if (!pos--)
- break;
-
- return _p != &rxrpc_calls ? _p : NULL;
+ return seq_list_start_head(&rxrpc_calls, *_pos);
}
static void *rxrpc_call_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct list_head *_p;
-
- (*pos)++;
-
- _p = v;
- _p = (v == SEQ_START_TOKEN) ? rxrpc_calls.next : _p->next;
-
- return _p != &rxrpc_calls ? _p : NULL;
+ return seq_list_next(v, &rxrpc_calls, pos);
}
static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
@@ -68,7 +50,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
struct rxrpc_call *call;
char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
- if (v == SEQ_START_TOKEN) {
+ if (v == &rxrpc_calls) {
seq_puts(seq,
"Proto Local Remote "
" SvID ConnID CallID End Use State Abort "
@@ -104,7 +86,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations rxrpc_call_seq_ops = {
+static const struct seq_operations rxrpc_call_seq_ops = {
.start = rxrpc_call_seq_start,
.next = rxrpc_call_seq_next,
.stop = rxrpc_call_seq_stop,
@@ -129,32 +111,14 @@ struct file_operations rxrpc_call_seq_fops = {
*/
static void *rxrpc_connection_seq_start(struct seq_file *seq, loff_t *_pos)
{
- struct list_head *_p;
- loff_t pos = *_pos;
-
read_lock(&rxrpc_connection_lock);
- if (!pos)
- return SEQ_START_TOKEN;
- pos--;
-
- list_for_each(_p, &rxrpc_connections)
- if (!pos--)
- break;
-
- return _p != &rxrpc_connections ? _p : NULL;
+ return seq_list_start_head(&rxrpc_connections, *_pos);
}
static void *rxrpc_connection_seq_next(struct seq_file *seq, void *v,
loff_t *pos)
{
- struct list_head *_p;
-
- (*pos)++;
-
- _p = v;
- _p = (v == SEQ_START_TOKEN) ? rxrpc_connections.next : _p->next;
-
- return _p != &rxrpc_connections ? _p : NULL;
+ return seq_list_next(v, &rxrpc_connections, pos);
}
static void rxrpc_connection_seq_stop(struct seq_file *seq, void *v)
@@ -168,7 +132,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
struct rxrpc_transport *trans;
char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
- if (v == SEQ_START_TOKEN) {
+ if (v == &rxrpc_connections) {
seq_puts(seq,
"Proto Local Remote "
" SvID ConnID Calls End Use State Key "
@@ -206,7 +170,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations rxrpc_connection_seq_ops = {
+static const struct seq_operations rxrpc_connection_seq_ops = {
.start = rxrpc_connection_seq_start,
.next = rxrpc_connection_seq_next,
.stop = rxrpc_connection_seq_stop,
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 475df8449be..d3f7c3f9407 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -111,6 +111,17 @@ config NET_SCH_PRIO
To compile this code as a module, choose M here: the
module will be called sch_prio.
+config NET_SCH_RR
+ tristate "Multi Band Round Robin Queuing (RR)"
+ select NET_SCH_PRIO
+ ---help---
+ Say Y here if you want to use an n-band round robin packet
+ scheduler.
+
+ The module uses sch_prio for its framework and is aliased as
+ sch_rr, so it will load sch_prio, although it is referred
+ to using sch_rr.
+
config NET_SCH_RED
tristate "Random Early Detection (RED)"
---help---
@@ -275,7 +286,6 @@ config CLS_U32_MARK
config NET_CLS_RSVP
tristate "IPv4 Resource Reservation Protocol (RSVP)"
select NET_CLS
- select NET_ESTIMATOR
---help---
The Resource Reservation Protocol (RSVP) permits end systems to
request a minimum and maximum data flow rate for a connection; this
@@ -290,7 +300,6 @@ config NET_CLS_RSVP
config NET_CLS_RSVP6
tristate "IPv6 Resource Reservation Protocol (RSVP6)"
select NET_CLS
- select NET_ESTIMATOR
---help---
The Resource Reservation Protocol (RSVP) permits end systems to
request a minimum and maximum data flow rate for a connection; this
@@ -382,7 +391,6 @@ config NET_EMATCH_TEXT
config NET_CLS_ACT
bool "Actions"
- select NET_ESTIMATOR
---help---
Say Y here if you want to use traffic control actions. Actions
get attached to classifiers and are invoked after a successful
@@ -464,13 +472,12 @@ config NET_ACT_SIMP
config NET_CLS_POLICE
bool "Traffic Policing (obsolete)"
- depends on NET_CLS_ACT!=y
- select NET_ESTIMATOR
+ select NET_CLS_ACT
+ select NET_ACT_POLICE
---help---
Say Y here if you want to do traffic policing, i.e. strict
- bandwidth limiting. This option is obsoleted by the traffic
- policer implemented as action, it stays here for compatibility
- reasons.
+ bandwidth limiting. This option is obsolete and just selects
+ the option replacing it. It will be removed in the future.
config NET_CLS_IND
bool "Incoming device classification"
@@ -480,14 +487,6 @@ config NET_CLS_IND
classification based on the incoming device. This option is
likely to disappear in favour of the metadata ematch.
-config NET_ESTIMATOR
- bool "Rate estimator"
- ---help---
- Say Y here to allow using rate estimators to estimate the current
- rate-of-flow for network devices, queues, etc. This module is
- automatically selected if needed but can be selected manually for
- statistical purposes.
-
endif # NET_SCHED
endmenu
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 020767a204d..b67c36f65cf 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o
obj-$(CONFIG_NET_CLS) += cls_api.o
obj-$(CONFIG_NET_CLS_ACT) += act_api.o
obj-$(CONFIG_NET_ACT_POLICE) += act_police.o
-obj-$(CONFIG_NET_CLS_POLICE) += act_police.o
obj-$(CONFIG_NET_ACT_GACT) += act_gact.o
obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o
obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 711dd26c95c..feef366cad5 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -11,23 +11,13 @@
*
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/kmod.h>
-#include <net/sock.h>
#include <net/sch_generic.h>
#include <net/act_api.h>
#include <net/netlink.h>
@@ -42,10 +32,8 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
write_lock_bh(hinfo->lock);
*p1p = p->tcfc_next;
write_unlock_bh(hinfo->lock);
-#ifdef CONFIG_NET_ESTIMATOR
gen_kill_estimator(&p->tcfc_bstats,
&p->tcfc_rate_est);
-#endif
kfree(p);
return;
}
@@ -232,15 +220,12 @@ struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, struct tc_acti
p->tcfc_bindcnt = 1;
spin_lock_init(&p->tcfc_lock);
- p->tcfc_stats_lock = &p->tcfc_lock;
p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo);
p->tcfc_tm.install = jiffies;
p->tcfc_tm.lastuse = jiffies;
-#ifdef CONFIG_NET_ESTIMATOR
if (est)
gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est,
- p->tcfc_stats_lock, est);
-#endif
+ &p->tcfc_lock, est);
a->priv = (void *) p;
return p;
}
@@ -599,12 +584,12 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
if (compat_mode) {
if (a->type == TCA_OLD_COMPAT)
err = gnet_stats_start_copy_compat(skb, 0,
- TCA_STATS, TCA_XSTATS, h->tcf_stats_lock, &d);
+ TCA_STATS, TCA_XSTATS, &h->tcf_lock, &d);
else
return 0;
} else
err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
- h->tcf_stats_lock, &d);
+ &h->tcf_lock, &d);
if (err < 0)
goto errout;
@@ -614,9 +599,7 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
goto errout;
if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
gnet_stats_copy_rate_est(&d, &h->tcf_rate_est) < 0 ||
-#endif
gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0)
goto errout;
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 7517f379154..a9631e426d9 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -10,26 +10,15 @@
*
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/proc_fs.h>
#include <net/netlink.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
#include <linux/tc_act/tc_gact.h>
#include <net/tc_act/tc_gact.h>
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 00b05f422d4..6b407ece953 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -11,27 +11,15 @@
* Copyright: Jamal Hadi Salim (2002-4)
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/kmod.h>
#include <net/netlink.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
#include <linux/tc_act/tc_ipt.h>
#include <net/tc_act/tc_ipt.h>
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index de21c92faaa..579578944ae 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -12,31 +12,19 @@
*
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/proc_fs.h>
#include <net/netlink.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
#include <linux/tc_act/tc_mirred.h>
#include <net/tc_act/tc_mirred.h>
-#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#define MIRRED_TAB_MASK 7
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 45b3cda86a2..b46fab5fb32 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -9,26 +9,15 @@
* Authors: Jamal Hadi Salim (2002-4)
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/proc_fs.h>
#include <net/netlink.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
#include <linux/tc_act/tc_pedit.h>
#include <net/tc_act/tc_pedit.h>
@@ -164,8 +153,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
printk("offset must be on 32 bit boundaries\n");
goto bad;
}
- if (skb->len < 0 ||
- (offset > 0 && offset > skb->len)) {
+ if (offset > 0 && offset > skb->len) {
printk("offset %d cant exceed pkt length %d\n",
offset, skb->len);
goto bad;
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 616f465f407..bf90e60f841 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -10,25 +10,15 @@
* J Hadi Salim (action changes)
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/module.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
-#include <net/sock.h>
#include <net/act_api.h>
#include <net/netlink.h>
@@ -60,7 +50,6 @@ struct tc_police_compat
/* Each policer is serialized by its individual spinlock */
-#ifdef CONFIG_NET_CLS_ACT
static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
int type, struct tc_action *a)
{
@@ -106,9 +95,8 @@ rtattr_failure:
nlmsg_trim(skb, r);
goto done;
}
-#endif
-void tcf_police_destroy(struct tcf_police *p)
+static void tcf_police_destroy(struct tcf_police *p)
{
unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
struct tcf_common **p1p;
@@ -118,10 +106,8 @@ void tcf_police_destroy(struct tcf_police *p)
write_lock_bh(&police_lock);
*p1p = p->tcf_next;
write_unlock_bh(&police_lock);
-#ifdef CONFIG_NET_ESTIMATOR
gen_kill_estimator(&p->tcf_bstats,
&p->tcf_rate_est);
-#endif
if (p->tcfp_R_tab)
qdisc_put_rtab(p->tcfp_R_tab);
if (p->tcfp_P_tab)
@@ -133,7 +119,6 @@ void tcf_police_destroy(struct tcf_police *p)
BUG_TRAP(0);
}
-#ifdef CONFIG_NET_CLS_ACT
static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
struct tc_action *a, int ovr, int bind)
{
@@ -185,7 +170,6 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
ret = ACT_P_CREATED;
police->tcf_refcnt = 1;
spin_lock_init(&police->tcf_lock);
- police->tcf_stats_lock = &police->tcf_lock;
if (bind)
police->tcf_bindcnt = 1;
override:
@@ -227,15 +211,13 @@ override:
police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
police->tcf_action = parm->action;
-#ifdef CONFIG_NET_ESTIMATOR
if (tb[TCA_POLICE_AVRATE-1])
police->tcfp_ewma_rate =
*(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
if (est)
gen_replace_estimator(&police->tcf_bstats,
&police->tcf_rate_est,
- police->tcf_stats_lock, est);
-#endif
+ &police->tcf_lock, est);
spin_unlock_bh(&police->tcf_lock);
if (ret != ACT_P_CREATED)
@@ -262,10 +244,19 @@ failure:
static int tcf_act_police_cleanup(struct tc_action *a, int bind)
{
struct tcf_police *p = a->priv;
+ int ret = 0;
- if (p != NULL)
- return tcf_police_release(p, bind);
- return 0;
+ if (p != NULL) {
+ if (bind)
+ p->tcf_bindcnt--;
+
+ p->tcf_refcnt--;
+ if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) {
+ tcf_police_destroy(p);
+ ret = 1;
+ }
+ }
+ return ret;
}
static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
@@ -281,14 +272,12 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
police->tcf_bstats.bytes += skb->len;
police->tcf_bstats.packets++;
-#ifdef CONFIG_NET_ESTIMATOR
if (police->tcfp_ewma_rate &&
police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
police->tcf_qstats.overlimits++;
spin_unlock(&police->tcf_lock);
return police->tcf_action;
}
-#endif
if (skb->len <= police->tcfp_mtu) {
if (police->tcfp_R_tab == NULL) {
@@ -348,10 +337,8 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
if (police->tcfp_result)
RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
&police->tcfp_result);
-#ifdef CONFIG_NET_ESTIMATOR
if (police->tcfp_ewma_rate)
RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
-#endif
return skb->len;
rtattr_failure:
@@ -391,240 +378,3 @@ police_cleanup_module(void)
module_init(police_init_module);
module_exit(police_cleanup_module);
-
-#else /* CONFIG_NET_CLS_ACT */
-
-static struct tcf_common *tcf_police_lookup(u32 index)
-{
- struct tcf_hashinfo *hinfo = &police_hash_info;
- struct tcf_common *p;
-
- read_lock(hinfo->lock);
- for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p;
- p = p->tcfc_next) {
- if (p->tcfc_index == index)
- break;
- }
- read_unlock(hinfo->lock);
-
- return p;
-}
-
-static u32 tcf_police_new_index(void)
-{
- u32 *idx_gen = &police_idx_gen;
- u32 val = *idx_gen;
-
- do {
- if (++val == 0)
- val = 1;
- } while (tcf_police_lookup(val));
-
- return (*idx_gen = val);
-}
-
-struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est)
-{
- unsigned int h;
- struct tcf_police *police;
- struct rtattr *tb[TCA_POLICE_MAX];
- struct tc_police *parm;
- int size;
-
- if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
- return NULL;
-
- if (tb[TCA_POLICE_TBF-1] == NULL)
- return NULL;
- size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
- if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
- return NULL;
-
- parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
-
- if (parm->index) {
- struct tcf_common *pc;
-
- pc = tcf_police_lookup(parm->index);
- if (pc) {
- police = to_police(pc);
- police->tcf_refcnt++;
- return police;
- }
- }
- police = kzalloc(sizeof(*police), GFP_KERNEL);
- if (unlikely(!police))
- return NULL;
-
- police->tcf_refcnt = 1;
- spin_lock_init(&police->tcf_lock);
- police->tcf_stats_lock = &police->tcf_lock;
- if (parm->rate.rate) {
- police->tcfp_R_tab =
- qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]);
- if (police->tcfp_R_tab == NULL)
- goto failure;
- if (parm->peakrate.rate) {
- police->tcfp_P_tab =
- qdisc_get_rtab(&parm->peakrate,
- tb[TCA_POLICE_PEAKRATE-1]);
- if (police->tcfp_P_tab == NULL)
- goto failure;
- }
- }
- if (tb[TCA_POLICE_RESULT-1]) {
- if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32))
- goto failure;
- police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
- }
-#ifdef CONFIG_NET_ESTIMATOR
- if (tb[TCA_POLICE_AVRATE-1]) {
- if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32))
- goto failure;
- police->tcfp_ewma_rate =
- *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
- }
-#endif
- police->tcfp_toks = police->tcfp_burst = parm->burst;
- police->tcfp_mtu = parm->mtu;
- if (police->tcfp_mtu == 0) {
- police->tcfp_mtu = ~0;
- if (police->tcfp_R_tab)
- police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log;
- }
- if (police->tcfp_P_tab)
- police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
- police->tcfp_t_c = psched_get_time();
- police->tcf_index = parm->index ? parm->index :
- tcf_police_new_index();
- police->tcf_action = parm->action;
-#ifdef CONFIG_NET_ESTIMATOR
- if (est)
- gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est,
- police->tcf_stats_lock, est);
-#endif
- h = tcf_hash(police->tcf_index, POL_TAB_MASK);
- write_lock_bh(&police_lock);
- police->tcf_next = tcf_police_ht[h];
- tcf_police_ht[h] = &police->common;
- write_unlock_bh(&police_lock);
- return police;
-
-failure:
- if (police->tcfp_R_tab)
- qdisc_put_rtab(police->tcfp_R_tab);
- kfree(police);
- return NULL;
-}
-
-int tcf_police(struct sk_buff *skb, struct tcf_police *police)
-{
- psched_time_t now;
- long toks;
- long ptoks = 0;
-
- spin_lock(&police->tcf_lock);
-
- police->tcf_bstats.bytes += skb->len;
- police->tcf_bstats.packets++;
-
-#ifdef CONFIG_NET_ESTIMATOR
- if (police->tcfp_ewma_rate &&
- police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
- police->tcf_qstats.overlimits++;
- spin_unlock(&police->tcf_lock);
- return police->tcf_action;
- }
-#endif
- if (skb->len <= police->tcfp_mtu) {
- if (police->tcfp_R_tab == NULL) {
- spin_unlock(&police->tcf_lock);
- return police->tcfp_result;
- }
-
- now = psched_get_time();
- toks = psched_tdiff_bounded(now, police->tcfp_t_c,
- police->tcfp_burst);
- if (police->tcfp_P_tab) {
- ptoks = toks + police->tcfp_ptoks;
- if (ptoks > (long)L2T_P(police, police->tcfp_mtu))
- ptoks = (long)L2T_P(police, police->tcfp_mtu);
- ptoks -= L2T_P(police, skb->len);
- }
- toks += police->tcfp_toks;
- if (toks > (long)police->tcfp_burst)
- toks = police->tcfp_burst;
- toks -= L2T(police, skb->len);
- if ((toks|ptoks) >= 0) {
- police->tcfp_t_c = now;
- police->tcfp_toks = toks;
- police->tcfp_ptoks = ptoks;
- spin_unlock(&police->tcf_lock);
- return police->tcfp_result;
- }
- }
-
- police->tcf_qstats.overlimits++;
- spin_unlock(&police->tcf_lock);
- return police->tcf_action;
-}
-EXPORT_SYMBOL(tcf_police);
-
-int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police)
-{
- unsigned char *b = skb_tail_pointer(skb);
- struct tc_police opt;
-
- opt.index = police->tcf_index;
- opt.action = police->tcf_action;
- opt.mtu = police->tcfp_mtu;
- opt.burst = police->tcfp_burst;
- if (police->tcfp_R_tab)
- opt.rate = police->tcfp_R_tab->rate;
- else
- memset(&opt.rate, 0, sizeof(opt.rate));
- if (police->tcfp_P_tab)
- opt.peakrate = police->tcfp_P_tab->rate;
- else
- memset(&opt.peakrate, 0, sizeof(opt.peakrate));
- RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
- if (police->tcfp_result)
- RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
- &police->tcfp_result);
-#ifdef CONFIG_NET_ESTIMATOR
- if (police->tcfp_ewma_rate)
- RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
-#endif
- return skb->len;
-
-rtattr_failure:
- nlmsg_trim(skb, b);
- return -1;
-}
-
-int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police)
-{
- struct gnet_dump d;
-
- if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
- TCA_XSTATS, police->tcf_stats_lock,
- &d) < 0)
- goto errout;
-
- if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
- gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 ||
-#endif
- gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0)
- goto errout;
-
- if (gnet_stats_finish_copy(&d) < 0)
- goto errout;
-
- return 0;
-
-errout:
- return -1;
-}
-
-#endif /* CONFIG_NET_CLS_ACT */
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 36e1edad599..fb84ef33d14 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <net/netlink.h>
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index ebf94edf047..5f0fbca7393 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -14,26 +14,16 @@
*
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/kmod.h>
#include <linux/netlink.h>
#include <net/netlink.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
#include <net/pkt_cls.h>
@@ -468,11 +458,6 @@ tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts)
tcf_action_destroy(exts->action, TCA_ACT_UNBIND);
exts->action = NULL;
}
-#elif defined CONFIG_NET_CLS_POLICE
- if (exts->police) {
- tcf_police_release(exts->police, TCA_ACT_UNBIND);
- exts->police = NULL;
- }
#endif
}
@@ -506,17 +491,6 @@ tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb,
exts->action = act;
}
}
-#elif defined CONFIG_NET_CLS_POLICE
- if (map->police && tb[map->police-1]) {
- struct tcf_police *p;
-
- p = tcf_police_locate(tb[map->police-1], rate_tlv);
- if (p == NULL)
- return -EINVAL;
-
- exts->police = p;
- } else if (map->action && tb[map->action-1])
- return -EOPNOTSUPP;
#else
if ((map->action && tb[map->action-1]) ||
(map->police && tb[map->police-1]))
@@ -539,15 +513,6 @@ tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
if (act)
tcf_action_destroy(act, TCA_ACT_UNBIND);
}
-#elif defined CONFIG_NET_CLS_POLICE
- if (src->police) {
- struct tcf_police *p;
- tcf_tree_lock(tp);
- p = xchg(&dst->police, src->police);
- tcf_tree_unlock(tp);
- if (p)
- tcf_police_release(p, TCA_ACT_UNBIND);
- }
#endif
}
@@ -576,17 +541,6 @@ tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
}
}
-#elif defined CONFIG_NET_CLS_POLICE
- if (map->police && exts->police) {
- struct rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb);
-
- RTA_PUT(skb, map->police, 0, NULL);
-
- if (tcf_police_dump(skb, exts->police) < 0)
- goto rtattr_failure;
-
- p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta;
- }
#endif
return 0;
rtattr_failure: __attribute__ ((unused))
@@ -601,10 +555,6 @@ tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
if (exts->action)
if (tcf_action_copy_stats(skb, exts->action, 1) < 0)
goto rtattr_failure;
-#elif defined CONFIG_NET_CLS_POLICE
- if (exts->police)
- if (tcf_police_dump_stats(skb, exts->police) < 0)
- goto rtattr_failure;
#endif
return 0;
rtattr_failure: __attribute__ ((unused))
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index c885412d79d..8dbcf2771a4 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -13,7 +13,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index bbec4a0d4dc..8adbd6a37d1 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -19,29 +19,12 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <linux/netfilter.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
#include <net/act_api.h>
#include <net/pkt_cls.h>
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index cc941d0ee3a..0a8409c1d28 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -10,28 +10,14 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <net/netlink.h>
#include <net/act_api.h>
#include <net/pkt_cls.h>
diff --git a/net/sched/cls_rsvp.c b/net/sched/cls_rsvp.c
index 0a683c07c64..cbb5e0d600f 100644
--- a/net/sched/cls_rsvp.c
+++ b/net/sched/cls_rsvp.c
@@ -10,27 +10,12 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/ip.h>
#include <net/netlink.h>
#include <net/act_api.h>
#include <net/pkt_cls.h>
diff --git a/net/sched/cls_rsvp6.c b/net/sched/cls_rsvp6.c
index 93b6abed57d..dd08aea2aee 100644
--- a/net/sched/cls_rsvp6.c
+++ b/net/sched/cls_rsvp6.c
@@ -10,28 +10,12 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
#include <linux/ipv6.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
#include <net/act_api.h>
#include <net/pkt_cls.h>
#include <net/netlink.h>
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 47ac0c55642..2314820a080 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -9,12 +9,9 @@
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <net/ip.h>
#include <net/act_api.h>
#include <net/netlink.h>
#include <net/pkt_cls.h>
-#include <net/route.h>
/*
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index c7a347bd6d7..8dbe36912ec 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -30,30 +30,14 @@
* nfmark match added by Catalin(ux aka Dino) BOIE <catab at umbrella.ro>
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
#include <linux/rtnetlink.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
#include <net/act_api.h>
#include <net/pkt_cls.h>
@@ -798,9 +782,6 @@ static int __init init_u32(void)
#ifdef CONFIG_CLS_U32_PERF
printk(" Performance counters on\n");
#endif
-#ifdef CONFIG_NET_CLS_POLICE
- printk(" OLD policer on \n");
-#endif
#ifdef CONFIG_NET_CLS_IND
printk(" input device check on \n");
#endif
diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c
index 8d6dacd8190..cc49c932641 100644
--- a/net/sched/em_cmp.c
+++ b/net/sched/em_cmp.c
@@ -98,3 +98,4 @@ MODULE_LICENSE("GPL");
module_init(init_em_cmp);
module_exit(exit_em_cmp);
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_CMP);
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 60acf8cdb27..650f09c8bd6 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -848,3 +848,5 @@ MODULE_LICENSE("GPL");
module_init(init_em_meta);
module_exit(exit_em_meta);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_META);
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c
index b4b36efce29..370a1b2ea31 100644
--- a/net/sched/em_nbyte.c
+++ b/net/sched/em_nbyte.c
@@ -76,3 +76,5 @@ MODULE_LICENSE("GPL");
module_init(init_em_nbyte);
module_exit(exit_em_nbyte);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_NBYTE);
diff --git a/net/sched/em_text.c b/net/sched/em_text.c
index e8f46169449..d5cd86efb7d 100644
--- a/net/sched/em_text.c
+++ b/net/sched/em_text.c
@@ -150,3 +150,5 @@ MODULE_LICENSE("GPL");
module_init(init_em_text);
module_exit(exit_em_text);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_TEXT);
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c
index 0a2a7fe08de..112796e4a7c 100644
--- a/net/sched/em_u32.c
+++ b/net/sched/em_u32.c
@@ -60,3 +60,5 @@ MODULE_LICENSE("GPL");
module_init(init_em_u32);
module_exit(exit_em_u32);
+
+MODULE_ALIAS_TCF_EMATCH(TCF_EM_U32);
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 63146d339d8..f3a104e323b 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -84,9 +84,7 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/mm.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <net/pkt_cls.h>
@@ -224,6 +222,19 @@ static int tcf_em_validate(struct tcf_proto *tp,
if (em->ops == NULL) {
err = -ENOENT;
+#ifdef CONFIG_KMOD
+ __rtnl_unlock();
+ request_module("ematch-kind-%u", em_hdr->kind);
+ rtnl_lock();
+ em->ops = tcf_em_lookup(em_hdr->kind);
+ if (em->ops) {
+ /* We dropped the RTNL mutex in order to
+ * perform the module load. Tell the caller
+ * to replay the request. */
+ module_put(em->ops->owner);
+ err = -EAGAIN;
+ }
+#endif
goto errout;
}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index bec600af03c..13c09bc32aa 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -19,30 +19,18 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/kmod.h>
#include <linux/list.h>
-#include <linux/bitops.h>
#include <linux/hrtimer.h>
#include <net/netlink.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid,
struct Qdisc *old, struct Qdisc *new);
static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n,
@@ -290,11 +278,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
wd->qdisc->flags &= ~TCQ_F_THROTTLED;
smp_wmb();
- if (spin_trylock(&dev->queue_lock)) {
- qdisc_run(dev);
- spin_unlock(&dev->queue_lock);
- } else
- netif_schedule(dev);
+ netif_schedule(dev);
return HRTIMER_NORESTART;
}
@@ -515,7 +499,6 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
sch->handle = handle;
if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
-#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1]) {
err = gen_new_estimator(&sch->bstats, &sch->rate_est,
sch->stats_lock,
@@ -531,7 +514,6 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
goto err_out3;
}
}
-#endif
qdisc_lock_tree(dev);
list_add_tail(&sch->list, &dev->qdisc_list);
qdisc_unlock_tree(dev);
@@ -559,11 +541,9 @@ static int qdisc_change(struct Qdisc *sch, struct rtattr **tca)
if (err)
return err;
}
-#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1])
gen_replace_estimator(&sch->bstats, &sch->rate_est,
sch->stats_lock, tca[TCA_RATE-1]);
-#endif
return 0;
}
@@ -839,9 +819,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
goto rtattr_failure;
if (gnet_stats_copy_basic(&d, &q->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
-#endif
gnet_stats_copy_queue(&d, &q->qstats) < 0)
goto rtattr_failure;
@@ -1167,47 +1145,57 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
to this qdisc, (optionally) tests for protocol and asks
specific classifiers.
*/
+int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
+ struct tcf_result *res)
+{
+ __be16 protocol = skb->protocol;
+ int err = 0;
+
+ for (; tp; tp = tp->next) {
+ if ((tp->protocol == protocol ||
+ tp->protocol == htons(ETH_P_ALL)) &&
+ (err = tp->classify(skb, tp, res)) >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+ if (err != TC_ACT_RECLASSIFY && skb->tc_verd)
+ skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0);
+#endif
+ return err;
+ }
+ }
+ return -1;
+}
+EXPORT_SYMBOL(tc_classify_compat);
+
int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
- struct tcf_result *res)
+ struct tcf_result *res)
{
int err = 0;
- __be16 protocol = skb->protocol;
+ __be16 protocol;
#ifdef CONFIG_NET_CLS_ACT
struct tcf_proto *otp = tp;
reclassify:
#endif
protocol = skb->protocol;
- for ( ; tp; tp = tp->next) {
- if ((tp->protocol == protocol ||
- tp->protocol == htons(ETH_P_ALL)) &&
- (err = tp->classify(skb, tp, res)) >= 0) {
+ err = tc_classify_compat(skb, tp, res);
#ifdef CONFIG_NET_CLS_ACT
- if ( TC_ACT_RECLASSIFY == err) {
- __u32 verd = (__u32) G_TC_VERD(skb->tc_verd);
- tp = otp;
-
- if (MAX_REC_LOOP < verd++) {
- printk("rule prio %d protocol %02x reclassify is buggy packet dropped\n",
- tp->prio&0xffff, ntohs(tp->protocol));
- return TC_ACT_SHOT;
- }
- skb->tc_verd = SET_TC_VERD(skb->tc_verd,verd);
- goto reclassify;
- } else {
- if (skb->tc_verd)
- skb->tc_verd = SET_TC_VERD(skb->tc_verd,0);
- return err;
- }
-#else
-
- return err;
-#endif
+ if (err == TC_ACT_RECLASSIFY) {
+ u32 verd = G_TC_VERD(skb->tc_verd);
+ tp = otp;
+
+ if (verd++ >= MAX_REC_LOOP) {
+ printk("rule prio %u protocol %02x reclassify loop, "
+ "packet dropped\n",
+ tp->prio&0xffff, ntohs(tp->protocol));
+ return TC_ACT_SHOT;
}
-
+ skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd);
+ goto reclassify;
}
- return -1;
+#endif
+ return err;
}
+EXPORT_SYMBOL(tc_classify);
void tcf_destroy(struct tcf_proto *tp)
{
@@ -1274,4 +1262,3 @@ EXPORT_SYMBOL(qdisc_get_rtab);
EXPORT_SYMBOL(qdisc_put_rtab);
EXPORT_SYMBOL(register_qdisc);
EXPORT_SYMBOL(unregister_qdisc);
-EXPORT_SYMBOL(tc_classify);
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index be7d299acd7..417ec8fb7f1 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -2,24 +2,19 @@
/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
-#include <linux/interrupt.h>
#include <linux/atmdev.h>
#include <linux/atmclip.h>
-#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
-#include <linux/file.h> /* for fput */
+#include <linux/file.h> /* for fput */
#include <net/netlink.h>
#include <net/pkt_sched.h>
-#include <net/sock.h>
-
-extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */
+extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */
#if 0 /* control */
#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
@@ -33,7 +28,6 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */
#define D2PRINTK(format,args...)
#endif
-
/*
* The ATM queuing discipline provides a framework for invoking classifiers
* (aka "filters"), which in turn select classes of this queuing discipline.
@@ -55,23 +49,21 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */
* - should lock the flow while there is data in the queue (?)
*/
-
#define PRIV(sch) qdisc_priv(sch)
#define VCC2FLOW(vcc) ((struct atm_flow_data *) ((vcc)->user_back))
-
struct atm_flow_data {
- struct Qdisc *q; /* FIFO, TBF, etc. */
+ struct Qdisc *q; /* FIFO, TBF, etc. */
struct tcf_proto *filter_list;
- struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */
- void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* chaining */
+ struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */
+ void (*old_pop)(struct atm_vcc *vcc,
+ struct sk_buff * skb); /* chaining */
struct atm_qdisc_data *parent; /* parent qdisc */
struct socket *sock; /* for closing */
u32 classid; /* x:y type ID */
int ref; /* reference count */
struct gnet_stats_basic bstats;
struct gnet_stats_queue qstats;
- spinlock_t *stats_lock;
struct atm_flow_data *next;
struct atm_flow_data *excess; /* flow for excess traffic;
NULL to set CLP instead */
@@ -86,76 +78,74 @@ struct atm_qdisc_data {
struct tasklet_struct task; /* requeue tasklet */
};
-
/* ------------------------- Class/flow operations ------------------------- */
-
-static int find_flow(struct atm_qdisc_data *qdisc,struct atm_flow_data *flow)
+static int find_flow(struct atm_qdisc_data *qdisc, struct atm_flow_data *flow)
{
struct atm_flow_data *walk;
- DPRINTK("find_flow(qdisc %p,flow %p)\n",qdisc,flow);
+ DPRINTK("find_flow(qdisc %p,flow %p)\n", qdisc, flow);
for (walk = qdisc->flows; walk; walk = walk->next)
- if (walk == flow) return 1;
+ if (walk == flow)
+ return 1;
DPRINTK("find_flow: not found\n");
return 0;
}
-
-static __inline__ struct atm_flow_data *lookup_flow(struct Qdisc *sch,
- u32 classid)
+static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid)
{
struct atm_qdisc_data *p = PRIV(sch);
struct atm_flow_data *flow;
for (flow = p->flows; flow; flow = flow->next)
- if (flow->classid == classid) break;
+ if (flow->classid == classid)
+ break;
return flow;
}
-
-static int atm_tc_graft(struct Qdisc *sch,unsigned long arg,
- struct Qdisc *new,struct Qdisc **old)
+static int atm_tc_graft(struct Qdisc *sch, unsigned long arg,
+ struct Qdisc *new, struct Qdisc **old)
{
struct atm_qdisc_data *p = PRIV(sch);
- struct atm_flow_data *flow = (struct atm_flow_data *) arg;
-
- DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",sch,
- p,flow,new,old);
- if (!find_flow(p,flow)) return -EINVAL;
- if (!new) new = &noop_qdisc;
- *old = xchg(&flow->q,new);
- if (*old) qdisc_reset(*old);
+ struct atm_flow_data *flow = (struct atm_flow_data *)arg;
+
+ DPRINTK("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",
+ sch, p, flow, new, old);
+ if (!find_flow(p, flow))
+ return -EINVAL;
+ if (!new)
+ new = &noop_qdisc;
+ *old = xchg(&flow->q, new);
+ if (*old)
+ qdisc_reset(*old);
return 0;
}
-
-static struct Qdisc *atm_tc_leaf(struct Qdisc *sch,unsigned long cl)
+static struct Qdisc *atm_tc_leaf(struct Qdisc *sch, unsigned long cl)
{
- struct atm_flow_data *flow = (struct atm_flow_data *) cl;
+ struct atm_flow_data *flow = (struct atm_flow_data *)cl;
- DPRINTK("atm_tc_leaf(sch %p,flow %p)\n",sch,flow);
+ DPRINTK("atm_tc_leaf(sch %p,flow %p)\n", sch, flow);
return flow ? flow->q : NULL;
}
-
-static unsigned long atm_tc_get(struct Qdisc *sch,u32 classid)
+static unsigned long atm_tc_get(struct Qdisc *sch, u32 classid)
{
- struct atm_qdisc_data *p __attribute__((unused)) = PRIV(sch);
+ struct atm_qdisc_data *p __maybe_unused = PRIV(sch);
struct atm_flow_data *flow;
- DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
- flow = lookup_flow(sch,classid);
- if (flow) flow->ref++;
- DPRINTK("atm_tc_get: flow %p\n",flow);
- return (unsigned long) flow;
+ DPRINTK("atm_tc_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
+ flow = lookup_flow(sch, classid);
+ if (flow)
+ flow->ref++;
+ DPRINTK("atm_tc_get: flow %p\n", flow);
+ return (unsigned long)flow;
}
-
static unsigned long atm_tc_bind_filter(struct Qdisc *sch,
- unsigned long parent, u32 classid)
+ unsigned long parent, u32 classid)
{
- return atm_tc_get(sch,classid);
+ return atm_tc_get(sch, classid);
}
/*
@@ -163,72 +153,75 @@ static unsigned long atm_tc_bind_filter(struct Qdisc *sch,
* requested (atm_tc_destroy, etc.). The assumption here is that we never drop
* anything that still seems to be in use.
*/
-
static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
{
struct atm_qdisc_data *p = PRIV(sch);
- struct atm_flow_data *flow = (struct atm_flow_data *) cl;
+ struct atm_flow_data *flow = (struct atm_flow_data *)cl;
struct atm_flow_data **prev;
- DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n",sch,p,flow);
- if (--flow->ref) return;
+ DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+ if (--flow->ref)
+ return;
DPRINTK("atm_tc_put: destroying\n");
for (prev = &p->flows; *prev; prev = &(*prev)->next)
- if (*prev == flow) break;
+ if (*prev == flow)
+ break;
if (!*prev) {
- printk(KERN_CRIT "atm_tc_put: class %p not found\n",flow);
+ printk(KERN_CRIT "atm_tc_put: class %p not found\n", flow);
return;
}
*prev = flow->next;
- DPRINTK("atm_tc_put: qdisc %p\n",flow->q);
+ DPRINTK("atm_tc_put: qdisc %p\n", flow->q);
qdisc_destroy(flow->q);
tcf_destroy_chain(flow->filter_list);
if (flow->sock) {
DPRINTK("atm_tc_put: f_count %d\n",
- file_count(flow->sock->file));
+ file_count(flow->sock->file));
flow->vcc->pop = flow->old_pop;
sockfd_put(flow->sock);
}
- if (flow->excess) atm_tc_put(sch,(unsigned long) flow->excess);
- if (flow != &p->link) kfree(flow);
+ if (flow->excess)
+ atm_tc_put(sch, (unsigned long)flow->excess);
+ if (flow != &p->link)
+ kfree(flow);
/*
* If flow == &p->link, the qdisc no longer works at this point and
* needs to be removed. (By the caller of atm_tc_put.)
*/
}
-
-static void sch_atm_pop(struct atm_vcc *vcc,struct sk_buff *skb)
+static void sch_atm_pop(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent;
- D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n",vcc,skb,p);
- VCC2FLOW(vcc)->old_pop(vcc,skb);
+ D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n", vcc, skb, p);
+ VCC2FLOW(vcc)->old_pop(vcc, skb);
tasklet_schedule(&p->task);
}
static const u8 llc_oui_ip[] = {
- 0xaa, /* DSAP: non-ISO */
- 0xaa, /* SSAP: non-ISO */
- 0x03, /* Ctrl: Unnumbered Information Command PDU */
- 0x00, /* OUI: EtherType */
+ 0xaa, /* DSAP: non-ISO */
+ 0xaa, /* SSAP: non-ISO */
+ 0x03, /* Ctrl: Unnumbered Information Command PDU */
+ 0x00, /* OUI: EtherType */
0x00, 0x00,
- 0x08, 0x00 }; /* Ethertype IP (0800) */
+ 0x08, 0x00
+}; /* Ethertype IP (0800) */
static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
- struct rtattr **tca, unsigned long *arg)
+ struct rtattr **tca, unsigned long *arg)
{
struct atm_qdisc_data *p = PRIV(sch);
- struct atm_flow_data *flow = (struct atm_flow_data *) *arg;
+ struct atm_flow_data *flow = (struct atm_flow_data *)*arg;
struct atm_flow_data *excess = NULL;
- struct rtattr *opt = tca[TCA_OPTIONS-1];
+ struct rtattr *opt = tca[TCA_OPTIONS - 1];
struct rtattr *tb[TCA_ATM_MAX];
struct socket *sock;
- int fd,error,hdr_len;
+ int fd, error, hdr_len;
void *hdr;
DPRINTK("atm_tc_change(sch %p,[qdisc %p],classid %x,parent %x,"
- "flow %p,opt %p)\n",sch,p,classid,parent,flow,opt);
+ "flow %p,opt %p)\n", sch, p, classid, parent, flow, opt);
/*
* The concept of parents doesn't apply for this qdisc.
*/
@@ -241,33 +234,36 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
* class needs to be removed and a new one added. (This may be changed
* later.)
*/
- if (flow) return -EBUSY;
+ if (flow)
+ return -EBUSY;
if (opt == NULL || rtattr_parse_nested(tb, TCA_ATM_MAX, opt))
return -EINVAL;
- if (!tb[TCA_ATM_FD-1] || RTA_PAYLOAD(tb[TCA_ATM_FD-1]) < sizeof(fd))
+ if (!tb[TCA_ATM_FD - 1] || RTA_PAYLOAD(tb[TCA_ATM_FD - 1]) < sizeof(fd))
return -EINVAL;
- fd = *(int *) RTA_DATA(tb[TCA_ATM_FD-1]);
- DPRINTK("atm_tc_change: fd %d\n",fd);
- if (tb[TCA_ATM_HDR-1]) {
- hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR-1]);
- hdr = RTA_DATA(tb[TCA_ATM_HDR-1]);
- }
- else {
+ fd = *(int *)RTA_DATA(tb[TCA_ATM_FD - 1]);
+ DPRINTK("atm_tc_change: fd %d\n", fd);
+ if (tb[TCA_ATM_HDR - 1]) {
+ hdr_len = RTA_PAYLOAD(tb[TCA_ATM_HDR - 1]);
+ hdr = RTA_DATA(tb[TCA_ATM_HDR - 1]);
+ } else {
hdr_len = RFC1483LLC_LEN;
- hdr = NULL; /* default LLC/SNAP for IP */
+ hdr = NULL; /* default LLC/SNAP for IP */
}
- if (!tb[TCA_ATM_EXCESS-1]) excess = NULL;
+ if (!tb[TCA_ATM_EXCESS - 1])
+ excess = NULL;
else {
- if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS-1]) != sizeof(u32))
+ if (RTA_PAYLOAD(tb[TCA_ATM_EXCESS - 1]) != sizeof(u32))
return -EINVAL;
- excess = (struct atm_flow_data *) atm_tc_get(sch,
- *(u32 *) RTA_DATA(tb[TCA_ATM_EXCESS-1]));
- if (!excess) return -ENOENT;
+ excess = (struct atm_flow_data *)
+ atm_tc_get(sch, *(u32 *)RTA_DATA(tb[TCA_ATM_EXCESS - 1]));
+ if (!excess)
+ return -ENOENT;
}
DPRINTK("atm_tc_change: type %d, payload %d, hdr_len %d\n",
- opt->rta_type,RTA_PAYLOAD(opt),hdr_len);
- if (!(sock = sockfd_lookup(fd,&error))) return error; /* f_count++ */
- DPRINTK("atm_tc_change: f_count %d\n",file_count(sock->file));
+ opt->rta_type, RTA_PAYLOAD(opt), hdr_len);
+ if (!(sock = sockfd_lookup(fd, &error)))
+ return error; /* f_count++ */
+ DPRINTK("atm_tc_change: f_count %d\n", file_count(sock->file));
if (sock->ops->family != PF_ATMSVC && sock->ops->family != PF_ATMPVC) {
error = -EPROTOTYPE;
goto err_out;
@@ -280,37 +276,37 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
error = -EINVAL;
goto err_out;
}
- if (find_flow(p,flow)) {
+ if (find_flow(p, flow)) {
error = -EEXIST;
goto err_out;
}
- }
- else {
+ } else {
int i;
unsigned long cl;
for (i = 1; i < 0x8000; i++) {
- classid = TC_H_MAKE(sch->handle,0x8000 | i);
- if (!(cl = atm_tc_get(sch,classid))) break;
- atm_tc_put(sch,cl);
+ classid = TC_H_MAKE(sch->handle, 0x8000 | i);
+ if (!(cl = atm_tc_get(sch, classid)))
+ break;
+ atm_tc_put(sch, cl);
}
}
- DPRINTK("atm_tc_change: new id %x\n",classid);
- flow = kmalloc(sizeof(struct atm_flow_data)+hdr_len,GFP_KERNEL);
- DPRINTK("atm_tc_change: flow %p\n",flow);
+ DPRINTK("atm_tc_change: new id %x\n", classid);
+ flow = kmalloc(sizeof(struct atm_flow_data) + hdr_len, GFP_KERNEL);
+ DPRINTK("atm_tc_change: flow %p\n", flow);
if (!flow) {
error = -ENOBUFS;
goto err_out;
}
- memset(flow,0,sizeof(*flow));
+ memset(flow, 0, sizeof(*flow));
flow->filter_list = NULL;
- if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,classid)))
+ if (!(flow->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid)))
flow->q = &noop_qdisc;
- DPRINTK("atm_tc_change: qdisc %p\n",flow->q);
+ DPRINTK("atm_tc_change: qdisc %p\n", flow->q);
flow->sock = sock;
- flow->vcc = ATM_SD(sock); /* speedup */
+ flow->vcc = ATM_SD(sock); /* speedup */
flow->vcc->user_back = flow;
- DPRINTK("atm_tc_change: vcc %p\n",flow->vcc);
+ DPRINTK("atm_tc_change: vcc %p\n", flow->vcc);
flow->old_pop = flow->vcc->pop;
flow->parent = p;
flow->vcc->pop = sch_atm_pop;
@@ -321,50 +317,53 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
p->link.next = flow;
flow->hdr_len = hdr_len;
if (hdr)
- memcpy(flow->hdr,hdr,hdr_len);
+ memcpy(flow->hdr, hdr, hdr_len);
else
- memcpy(flow->hdr,llc_oui_ip,sizeof(llc_oui_ip));
- *arg = (unsigned long) flow;
+ memcpy(flow->hdr, llc_oui_ip, sizeof(llc_oui_ip));
+ *arg = (unsigned long)flow;
return 0;
err_out:
- if (excess) atm_tc_put(sch,(unsigned long) excess);
+ if (excess)
+ atm_tc_put(sch, (unsigned long)excess);
sockfd_put(sock);
return error;
}
-
-static int atm_tc_delete(struct Qdisc *sch,unsigned long arg)
+static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
{
struct atm_qdisc_data *p = PRIV(sch);
- struct atm_flow_data *flow = (struct atm_flow_data *) arg;
+ struct atm_flow_data *flow = (struct atm_flow_data *)arg;
- DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n",sch,p,flow);
- if (!find_flow(PRIV(sch),flow)) return -EINVAL;
- if (flow->filter_list || flow == &p->link) return -EBUSY;
+ DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
+ if (!find_flow(PRIV(sch), flow))
+ return -EINVAL;
+ if (flow->filter_list || flow == &p->link)
+ return -EBUSY;
/*
* Reference count must be 2: one for "keepalive" (set at class
* creation), and one for the reference held when calling delete.
*/
if (flow->ref < 2) {
- printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n",flow->ref);
+ printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n", flow->ref);
return -EINVAL;
}
- if (flow->ref > 2) return -EBUSY; /* catch references via excess, etc.*/
- atm_tc_put(sch,arg);
+ if (flow->ref > 2)
+ return -EBUSY; /* catch references via excess, etc. */
+ atm_tc_put(sch, arg);
return 0;
}
-
-static void atm_tc_walk(struct Qdisc *sch,struct qdisc_walker *walker)
+static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker)
{
struct atm_qdisc_data *p = PRIV(sch);
struct atm_flow_data *flow;
- DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker);
- if (walker->stop) return;
+ DPRINTK("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+ if (walker->stop)
+ return;
for (flow = p->flows; flow; flow = flow->next) {
if (walker->count >= walker->skip)
- if (walker->fn(sch,(unsigned long) flow,walker) < 0) {
+ if (walker->fn(sch, (unsigned long)flow, walker) < 0) {
walker->stop = 1;
break;
}
@@ -372,73 +371,71 @@ static void atm_tc_walk(struct Qdisc *sch,struct qdisc_walker *walker)
}
}
-
-static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch,unsigned long cl)
+static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch, unsigned long cl)
{
struct atm_qdisc_data *p = PRIV(sch);
- struct atm_flow_data *flow = (struct atm_flow_data *) cl;
+ struct atm_flow_data *flow = (struct atm_flow_data *)cl;
- DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n",sch,p,flow);
+ DPRINTK("atm_tc_find_tcf(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
return flow ? &flow->filter_list : &p->link.filter_list;
}
-
/* --------------------------- Qdisc operations ---------------------------- */
-
-static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch)
+static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct atm_qdisc_data *p = PRIV(sch);
- struct atm_flow_data *flow = NULL ; /* @@@ */
+ struct atm_flow_data *flow = NULL; /* @@@ */
struct tcf_result res;
int result;
int ret = NET_XMIT_POLICED;
- D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
- result = TC_POLICE_OK; /* be nice to gcc */
+ D2PRINTK("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+ result = TC_POLICE_OK; /* be nice to gcc */
if (TC_H_MAJ(skb->priority) != sch->handle ||
- !(flow = (struct atm_flow_data *) atm_tc_get(sch,skb->priority)))
+ !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority)))
for (flow = p->flows; flow; flow = flow->next)
if (flow->filter_list) {
- result = tc_classify(skb,flow->filter_list,
- &res);
- if (result < 0) continue;
- flow = (struct atm_flow_data *) res.class;
- if (!flow) flow = lookup_flow(sch,res.classid);
+ result = tc_classify_compat(skb,
+ flow->filter_list,
+ &res);
+ if (result < 0)
+ continue;
+ flow = (struct atm_flow_data *)res.class;
+ if (!flow)
+ flow = lookup_flow(sch, res.classid);
break;
}
- if (!flow) flow = &p->link;
+ if (!flow)
+ flow = &p->link;
else {
if (flow->vcc)
ATM_SKB(skb)->atm_options = flow->vcc->atm_options;
- /*@@@ looks good ... but it's not supposed to work :-)*/
-#ifdef CONFIG_NET_CLS_POLICE
+ /*@@@ looks good ... but it's not supposed to work :-) */
+#ifdef CONFIG_NET_CLS_ACT
switch (result) {
- case TC_POLICE_SHOT:
- kfree_skb(skb);
- break;
- case TC_POLICE_RECLASSIFY:
- if (flow->excess) flow = flow->excess;
- else {
- ATM_SKB(skb)->atm_options |=
- ATM_ATMOPT_CLP;
- break;
- }
- /* fall through */
- case TC_POLICE_OK:
- /* fall through */
- default:
- break;
+ case TC_ACT_QUEUED:
+ case TC_ACT_STOLEN:
+ kfree_skb(skb);
+ return NET_XMIT_SUCCESS;
+ case TC_ACT_SHOT:
+ kfree_skb(skb);
+ goto drop;
+ case TC_POLICE_RECLASSIFY:
+ if (flow->excess)
+ flow = flow->excess;
+ else
+ ATM_SKB(skb)->atm_options |= ATM_ATMOPT_CLP;
+ break;
}
#endif
}
- if (
-#ifdef CONFIG_NET_CLS_POLICE
- result == TC_POLICE_SHOT ||
-#endif
- (ret = flow->q->enqueue(skb,flow->q)) != 0) {
+
+ if ((ret = flow->q->enqueue(skb, flow->q)) != 0) {
+drop: __maybe_unused
sch->qstats.drops++;
- if (flow) flow->qstats.drops++;
+ if (flow)
+ flow->qstats.drops++;
return ret;
}
sch->bstats.bytes += skb->len;
@@ -462,7 +459,6 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch)
return NET_XMIT_BYPASS;
}
-
/*
* Dequeue packets and send them over ATM. Note that we quite deliberately
* avoid checking net_device's flow control here, simply because sch_atm
@@ -470,166 +466,163 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch)
* non-ATM interfaces.
*/
-
static void sch_atm_dequeue(unsigned long data)
{
- struct Qdisc *sch = (struct Qdisc *) data;
+ struct Qdisc *sch = (struct Qdisc *)data;
struct atm_qdisc_data *p = PRIV(sch);
struct atm_flow_data *flow;
struct sk_buff *skb;
- D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n",sch,p);
+ D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p);
for (flow = p->link.next; flow; flow = flow->next)
/*
* If traffic is properly shaped, this won't generate nasty
* little bursts. Otherwise, it may ... (but that's okay)
*/
while ((skb = flow->q->dequeue(flow->q))) {
- if (!atm_may_send(flow->vcc,skb->truesize)) {
- (void) flow->q->ops->requeue(skb,flow->q);
+ if (!atm_may_send(flow->vcc, skb->truesize)) {
+ (void)flow->q->ops->requeue(skb, flow->q);
break;
}
- D2PRINTK("atm_tc_dequeue: sending on class %p\n",flow);
+ D2PRINTK("atm_tc_dequeue: sending on class %p\n", flow);
/* remove any LL header somebody else has attached */
skb_pull(skb, skb_network_offset(skb));
if (skb_headroom(skb) < flow->hdr_len) {
struct sk_buff *new;
- new = skb_realloc_headroom(skb,flow->hdr_len);
+ new = skb_realloc_headroom(skb, flow->hdr_len);
dev_kfree_skb(skb);
- if (!new) continue;
+ if (!new)
+ continue;
skb = new;
}
D2PRINTK("sch_atm_dequeue: ip %p, data %p\n",
skb_network_header(skb), skb->data);
ATM_SKB(skb)->vcc = flow->vcc;
- memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
- flow->hdr_len);
+ memcpy(skb_push(skb, flow->hdr_len), flow->hdr,
+ flow->hdr_len);
atomic_add(skb->truesize,
&sk_atm(flow->vcc)->sk_wmem_alloc);
/* atm.atm_options are already set by atm_tc_enqueue */
- (void) flow->vcc->send(flow->vcc,skb);
+ flow->vcc->send(flow->vcc, skb);
}
}
-
static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch)
{
struct atm_qdisc_data *p = PRIV(sch);
struct sk_buff *skb;
- D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n",sch,p);
+ D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n", sch, p);
tasklet_schedule(&p->task);
skb = p->link.q->dequeue(p->link.q);
- if (skb) sch->q.qlen--;
+ if (skb)
+ sch->q.qlen--;
return skb;
}
-
-static int atm_tc_requeue(struct sk_buff *skb,struct Qdisc *sch)
+static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch)
{
struct atm_qdisc_data *p = PRIV(sch);
int ret;
- D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
- ret = p->link.q->ops->requeue(skb,p->link.q);
+ D2PRINTK("atm_tc_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+ ret = p->link.q->ops->requeue(skb, p->link.q);
if (!ret) {
- sch->q.qlen++;
- sch->qstats.requeues++;
- } else {
+ sch->q.qlen++;
+ sch->qstats.requeues++;
+ } else {
sch->qstats.drops++;
p->link.qstats.drops++;
}
return ret;
}
-
static unsigned int atm_tc_drop(struct Qdisc *sch)
{
struct atm_qdisc_data *p = PRIV(sch);
struct atm_flow_data *flow;
unsigned int len;
- DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n",sch,p);
+ DPRINTK("atm_tc_drop(sch %p,[qdisc %p])\n", sch, p);
for (flow = p->flows; flow; flow = flow->next)
if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q)))
return len;
return 0;
}
-
-static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt)
+static int atm_tc_init(struct Qdisc *sch, struct rtattr *opt)
{
struct atm_qdisc_data *p = PRIV(sch);
- DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
+ DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
p->flows = &p->link;
- if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,
- sch->handle)))
+ if (!(p->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
+ sch->handle)))
p->link.q = &noop_qdisc;
- DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q);
+ DPRINTK("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
p->link.filter_list = NULL;
p->link.vcc = NULL;
p->link.sock = NULL;
p->link.classid = sch->handle;
p->link.ref = 1;
p->link.next = NULL;
- tasklet_init(&p->task,sch_atm_dequeue,(unsigned long) sch);
+ tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch);
return 0;
}
-
static void atm_tc_reset(struct Qdisc *sch)
{
struct atm_qdisc_data *p = PRIV(sch);
struct atm_flow_data *flow;
- DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n",sch,p);
- for (flow = p->flows; flow; flow = flow->next) qdisc_reset(flow->q);
+ DPRINTK("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
+ for (flow = p->flows; flow; flow = flow->next)
+ qdisc_reset(flow->q);
sch->q.qlen = 0;
}
-
static void atm_tc_destroy(struct Qdisc *sch)
{
struct atm_qdisc_data *p = PRIV(sch);
struct atm_flow_data *flow;
- DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p);
+ DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
/* races ? */
while ((flow = p->flows)) {
tcf_destroy_chain(flow->filter_list);
+ flow->filter_list = NULL;
if (flow->ref > 1)
- printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow,
- flow->ref);
- atm_tc_put(sch,(unsigned long) flow);
+ printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow,
+ flow->ref);
+ atm_tc_put(sch, (unsigned long)flow);
if (p->flows == flow) {
printk(KERN_ERR "atm_destroy: putting flow %p didn't "
- "kill it\n",flow);
- p->flows = flow->next; /* brute force */
+ "kill it\n", flow);
+ p->flows = flow->next; /* brute force */
break;
}
}
tasklet_kill(&p->task);
}
-
static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
- struct sk_buff *skb, struct tcmsg *tcm)
+ struct sk_buff *skb, struct tcmsg *tcm)
{
struct atm_qdisc_data *p = PRIV(sch);
- struct atm_flow_data *flow = (struct atm_flow_data *) cl;
+ struct atm_flow_data *flow = (struct atm_flow_data *)cl;
unsigned char *b = skb_tail_pointer(skb);
struct rtattr *rta;
DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
- sch,p,flow,skb,tcm);
- if (!find_flow(p,flow)) return -EINVAL;
+ sch, p, flow, skb, tcm);
+ if (!find_flow(p, flow))
+ return -EINVAL;
tcm->tcm_handle = flow->classid;
tcm->tcm_info = flow->q->handle;
- rta = (struct rtattr *) b;
- RTA_PUT(skb,TCA_OPTIONS,0,NULL);
- RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr);
+ rta = (struct rtattr *)b;
+ RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ RTA_PUT(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr);
if (flow->vcc) {
struct sockaddr_atmpvc pvc;
int state;
@@ -638,16 +631,16 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1;
pvc.sap_addr.vpi = flow->vcc->vpi;
pvc.sap_addr.vci = flow->vcc->vci;
- RTA_PUT(skb,TCA_ATM_ADDR,sizeof(pvc),&pvc);
+ RTA_PUT(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc);
state = ATM_VF2VS(flow->vcc->flags);
- RTA_PUT(skb,TCA_ATM_STATE,sizeof(state),&state);
+ RTA_PUT(skb, TCA_ATM_STATE, sizeof(state), &state);
}
if (flow->excess)
- RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(u32),&flow->classid);
+ RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(u32), &flow->classid);
else {
static u32 zero;
- RTA_PUT(skb,TCA_ATM_EXCESS,sizeof(zero),&zero);
+ RTA_PUT(skb, TCA_ATM_EXCESS, sizeof(zero), &zero);
}
rta->rta_len = skb_tail_pointer(skb) - b;
return skb->len;
@@ -658,9 +651,9 @@ rtattr_failure:
}
static int
atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
- struct gnet_dump *d)
+ struct gnet_dump *d)
{
- struct atm_flow_data *flow = (struct atm_flow_data *) arg;
+ struct atm_flow_data *flow = (struct atm_flow_data *)arg;
flow->qstats.qlen = flow->q->q.qlen;
@@ -677,38 +670,35 @@ static int atm_tc_dump(struct Qdisc *sch, struct sk_buff *skb)
}
static struct Qdisc_class_ops atm_class_ops = {
- .graft = atm_tc_graft,
- .leaf = atm_tc_leaf,
- .get = atm_tc_get,
- .put = atm_tc_put,
- .change = atm_tc_change,
- .delete = atm_tc_delete,
- .walk = atm_tc_walk,
- .tcf_chain = atm_tc_find_tcf,
- .bind_tcf = atm_tc_bind_filter,
- .unbind_tcf = atm_tc_put,
- .dump = atm_tc_dump_class,
- .dump_stats = atm_tc_dump_class_stats,
+ .graft = atm_tc_graft,
+ .leaf = atm_tc_leaf,
+ .get = atm_tc_get,
+ .put = atm_tc_put,
+ .change = atm_tc_change,
+ .delete = atm_tc_delete,
+ .walk = atm_tc_walk,
+ .tcf_chain = atm_tc_find_tcf,
+ .bind_tcf = atm_tc_bind_filter,
+ .unbind_tcf = atm_tc_put,
+ .dump = atm_tc_dump_class,
+ .dump_stats = atm_tc_dump_class_stats,
};
static struct Qdisc_ops atm_qdisc_ops = {
- .next = NULL,
- .cl_ops = &atm_class_ops,
- .id = "atm",
- .priv_size = sizeof(struct atm_qdisc_data),
- .enqueue = atm_tc_enqueue,
- .dequeue = atm_tc_dequeue,
- .requeue = atm_tc_requeue,
- .drop = atm_tc_drop,
- .init = atm_tc_init,
- .reset = atm_tc_reset,
- .destroy = atm_tc_destroy,
- .change = NULL,
- .dump = atm_tc_dump,
- .owner = THIS_MODULE,
+ .cl_ops = &atm_class_ops,
+ .id = "atm",
+ .priv_size = sizeof(struct atm_qdisc_data),
+ .enqueue = atm_tc_enqueue,
+ .dequeue = atm_tc_dequeue,
+ .requeue = atm_tc_requeue,
+ .drop = atm_tc_drop,
+ .init = atm_tc_init,
+ .reset = atm_tc_reset,
+ .destroy = atm_tc_destroy,
+ .dump = atm_tc_dump,
+ .owner = THIS_MODULE,
};
-
static int __init atm_init(void)
{
return register_qdisc(&atm_qdisc_ops);
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c
index cb0c456aa34..f914fc43a12 100644
--- a/net/sched/sch_blackhole.c
+++ b/net/sched/sch_blackhole.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/pkt_sched.h>
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index a294542cb8e..e38c2839b25 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -11,28 +11,12 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
#include <net/pkt_sched.h>
@@ -98,7 +82,7 @@ struct cbq_class
unsigned char priority2; /* priority to be used after overlimit */
unsigned char ewma_log; /* time constant for idle time calculation */
unsigned char ovl_strategy;
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
unsigned char police;
#endif
@@ -148,7 +132,6 @@ struct cbq_class
struct gnet_stats_basic bstats;
struct gnet_stats_queue qstats;
struct gnet_stats_rate_est rate_est;
- spinlock_t *stats_lock;
struct tc_cbq_xstats xstats;
struct tcf_proto *filter_list;
@@ -171,7 +154,7 @@ struct cbq_sched_data
struct cbq_class *active[TC_CBQ_MAXPRIO+1]; /* List of all classes
with backlog */
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
struct cbq_class *rx_class;
#endif
struct cbq_class *tx_class;
@@ -213,7 +196,7 @@ cbq_class_lookup(struct cbq_sched_data *q, u32 classid)
return NULL;
}
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
static struct cbq_class *
cbq_reclassify(struct sk_buff *skb, struct cbq_class *this)
@@ -264,7 +247,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
/*
* Step 2+n. Apply classifier.
*/
- if (!head->filter_list || (result = tc_classify(skb, head->filter_list, &res)) < 0)
+ if (!head->filter_list ||
+ (result = tc_classify_compat(skb, head->filter_list, &res)) < 0)
goto fallback;
if ((cl = (void*)res.class) == NULL) {
@@ -284,15 +268,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
*qerr = NET_XMIT_SUCCESS;
case TC_ACT_SHOT:
return NULL;
- }
-#elif defined(CONFIG_NET_CLS_POLICE)
- switch (result) {
- case TC_POLICE_RECLASSIFY:
+ case TC_ACT_RECLASSIFY:
return cbq_reclassify(skb, cl);
- case TC_POLICE_SHOT:
- return NULL;
- default:
- break;
}
#endif
if (cl->level == 0)
@@ -406,7 +383,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
int ret;
struct cbq_class *cl = cbq_classify(skb, sch, &ret);
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
q->rx_class = cl;
#endif
if (cl == NULL) {
@@ -416,7 +393,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
return ret;
}
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
cl->q->__parent = sch;
#endif
if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) {
@@ -451,7 +428,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch)
cbq_mark_toplevel(q, cl);
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
q->rx_class = cl;
cl->q->__parent = sch;
#endif
@@ -686,9 +663,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
return HRTIMER_NORESTART;
}
-
-#ifdef CONFIG_NET_CLS_POLICE
-
+#ifdef CONFIG_NET_CLS_ACT
static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child)
{
int len = skb->len;
@@ -1381,7 +1356,7 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl)
return 0;
}
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
static int cbq_set_police(struct cbq_class *cl, struct tc_cbq_police *p)
{
cl->police = p->police;
@@ -1442,7 +1417,6 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
q->link.ewma_log = TC_CBQ_DEF_EWMA;
q->link.avpkt = q->link.allot/2;
q->link.minidle = -0x7FFFFFFF;
- q->link.stats_lock = &sch->dev->queue_lock;
qdisc_watchdog_init(&q->watchdog, sch);
hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
@@ -1550,7 +1524,7 @@ rtattr_failure:
return -1;
}
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl)
{
unsigned char *b = skb_tail_pointer(skb);
@@ -1576,7 +1550,7 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl)
cbq_dump_rate(skb, cl) < 0 ||
cbq_dump_wrr(skb, cl) < 0 ||
cbq_dump_ovl(skb, cl) < 0 ||
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
cbq_dump_police(skb, cl) < 0 ||
#endif
cbq_dump_fopt(skb, cl) < 0)
@@ -1653,9 +1627,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
cl->xstats.undertime = cl->undertime - q->now;
if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
-#endif
gnet_stats_copy_queue(d, &cl->qstats) < 0)
return -1;
@@ -1673,7 +1645,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
cl->classid)) == NULL)
return -ENOBUFS;
} else {
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
if (cl->police == TC_POLICE_RECLASSIFY)
new->reshape_fail = cbq_reshape_fail;
#endif
@@ -1726,9 +1698,7 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
tcf_destroy_chain(cl->filter_list);
qdisc_destroy(cl->q);
qdisc_put_rtab(cl->R_tab);
-#ifdef CONFIG_NET_ESTIMATOR
gen_kill_estimator(&cl->bstats, &cl->rate_est);
-#endif
if (cl != &q->link)
kfree(cl);
}
@@ -1740,7 +1710,7 @@ cbq_destroy(struct Qdisc* sch)
struct cbq_class *cl;
unsigned h;
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
q->rx_class = NULL;
#endif
/*
@@ -1748,10 +1718,12 @@ cbq_destroy(struct Qdisc* sch)
* classes from root to leafs which means that filters can still
* be bound to classes which have been destroyed already. --TGR '04
*/
- for (h = 0; h < 16; h++)
- for (cl = q->classes[h]; cl; cl = cl->next)
+ for (h = 0; h < 16; h++) {
+ for (cl = q->classes[h]; cl; cl = cl->next) {
tcf_destroy_chain(cl->filter_list);
-
+ cl->filter_list = NULL;
+ }
+ }
for (h = 0; h < 16; h++) {
struct cbq_class *next;
@@ -1767,7 +1739,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg)
struct cbq_class *cl = (struct cbq_class*)arg;
if (--cl->refcnt == 0) {
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
struct cbq_sched_data *q = qdisc_priv(sch);
spin_lock_bh(&sch->dev->queue_lock);
@@ -1815,7 +1787,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
RTA_PAYLOAD(tb[TCA_CBQ_WRROPT-1]) < sizeof(struct tc_cbq_wrropt))
return -EINVAL;
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
if (tb[TCA_CBQ_POLICE-1] &&
RTA_PAYLOAD(tb[TCA_CBQ_POLICE-1]) < sizeof(struct tc_cbq_police))
return -EINVAL;
@@ -1858,7 +1830,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
if (tb[TCA_CBQ_OVL_STRATEGY-1])
cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1]));
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
if (tb[TCA_CBQ_POLICE-1])
cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1]));
#endif
@@ -1871,11 +1843,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
sch_tree_unlock(sch);
-#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1])
gen_replace_estimator(&cl->bstats, &cl->rate_est,
- cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+ &sch->dev->queue_lock,
+ tca[TCA_RATE-1]);
return 0;
}
@@ -1933,7 +1904,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
cl->allot = parent->allot;
cl->quantum = cl->allot;
cl->weight = cl->R_tab->rate.rate;
- cl->stats_lock = &sch->dev->queue_lock;
sch_tree_lock(sch);
cbq_link_class(cl);
@@ -1953,7 +1923,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
cl->overlimit = cbq_ovl_classic;
if (tb[TCA_CBQ_OVL_STRATEGY-1])
cbq_set_overlimit(cl, RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY-1]));
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
if (tb[TCA_CBQ_POLICE-1])
cbq_set_police(cl, RTA_DATA(tb[TCA_CBQ_POLICE-1]));
#endif
@@ -1961,11 +1931,9 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
cbq_set_fopt(cl, RTA_DATA(tb[TCA_CBQ_FOPT-1]));
sch_tree_unlock(sch);
-#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1])
gen_new_estimator(&cl->bstats, &cl->rate_est,
- cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+ &sch->dev->queue_lock, tca[TCA_RATE-1]);
*arg = (unsigned long)cl;
return 0;
@@ -1999,7 +1967,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
q->tx_class = NULL;
q->tx_borrowed = NULL;
}
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
if (q->rx_class == cl)
q->rx_class = NULL;
#endif
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 3c6fd181263..60f89199e3d 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -9,7 +9,6 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
-#include <linux/netdevice.h> /* for pkt_sched */
#include <linux/rtnetlink.h>
#include <net/pkt_sched.h>
#include <net/dsfield.h>
@@ -238,25 +237,23 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
D2PRINTK("result %d class 0x%04x\n", result, res.classid);
switch (result) {
-#ifdef CONFIG_NET_CLS_POLICE
- case TC_POLICE_SHOT:
- kfree_skb(skb);
- sch->qstats.drops++;
- return NET_XMIT_POLICED;
-#if 0
- case TC_POLICE_RECLASSIFY:
- /* FIXME: what to do here ??? */
+#ifdef CONFIG_NET_CLS_ACT
+ case TC_ACT_QUEUED:
+ case TC_ACT_STOLEN:
+ kfree_skb(skb);
+ return NET_XMIT_SUCCESS;
+ case TC_ACT_SHOT:
+ kfree_skb(skb);
+ sch->qstats.drops++;
+ return NET_XMIT_BYPASS;
#endif
-#endif
- case TC_POLICE_OK:
- skb->tc_index = TC_H_MIN(res.classid);
- break;
- case TC_POLICE_UNSPEC:
- /* fall through */
- default:
- if (p->default_index != NO_DEFAULT_INDEX)
- skb->tc_index = p->default_index;
- break;
+ case TC_ACT_OK:
+ skb->tc_index = TC_H_MIN(res.classid);
+ break;
+ default:
+ if (p->default_index != NO_DEFAULT_INDEX)
+ skb->tc_index = p->default_index;
+ break;
}
}
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index c2689f4ba8d..c264308f17c 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -13,7 +13,6 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/pkt_sched.h>
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index cbefe225581..c81649cf0b9 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -11,27 +11,19 @@
* - Ingress support
*/
-#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/init.h>
#include <linux/rcupdate.h>
#include <linux/list.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
/* Main transmission queue. */
@@ -59,122 +51,143 @@ void qdisc_unlock_tree(struct net_device *dev)
spin_unlock_bh(&dev->queue_lock);
}
-/*
- dev->queue_lock serializes queue accesses for this device
- AND dev->qdisc pointer itself.
+static inline int qdisc_qlen(struct Qdisc *q)
+{
+ return q->q.qlen;
+}
- netif_tx_lock serializes accesses to device driver.
+static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev,
+ struct Qdisc *q)
+{
+ if (unlikely(skb->next))
+ dev->gso_skb = skb;
+ else
+ q->ops->requeue(skb, q);
- dev->queue_lock and netif_tx_lock are mutually exclusive,
- if one is grabbed, another must be free.
- */
+ netif_schedule(dev);
+ return 0;
+}
+static inline struct sk_buff *dev_dequeue_skb(struct net_device *dev,
+ struct Qdisc *q)
+{
+ struct sk_buff *skb;
-/* Kick device.
+ if ((skb = dev->gso_skb))
+ dev->gso_skb = NULL;
+ else
+ skb = q->dequeue(q);
- Returns: 0 - queue is empty or throttled.
- >0 - queue is not empty.
+ return skb;
+}
- NOTE: Called under dev->queue_lock with locally disabled BH.
-*/
+static inline int handle_dev_cpu_collision(struct sk_buff *skb,
+ struct net_device *dev,
+ struct Qdisc *q)
+{
+ int ret;
+ if (unlikely(dev->xmit_lock_owner == smp_processor_id())) {
+ /*
+ * Same CPU holding the lock. It may be a transient
+ * configuration error, when hard_start_xmit() recurses. We
+ * detect it by checking xmit owner and drop the packet when
+ * deadloop is detected. Return OK to try the next skb.
+ */
+ kfree_skb(skb);
+ if (net_ratelimit())
+ printk(KERN_WARNING "Dead loop on netdevice %s, "
+ "fix it urgently!\n", dev->name);
+ ret = qdisc_qlen(q);
+ } else {
+ /*
+ * Another cpu is holding lock, requeue & delay xmits for
+ * some time.
+ */
+ __get_cpu_var(netdev_rx_stat).cpu_collision++;
+ ret = dev_requeue_skb(skb, dev, q);
+ }
+
+ return ret;
+}
+
+/*
+ * NOTE: Called under dev->queue_lock with locally disabled BH.
+ *
+ * __LINK_STATE_QDISC_RUNNING guarantees only one CPU can process this
+ * device at a time. dev->queue_lock serializes queue accesses for
+ * this device AND dev->qdisc pointer itself.
+ *
+ * netif_tx_lock serializes accesses to device driver.
+ *
+ * dev->queue_lock and netif_tx_lock are mutually exclusive,
+ * if one is grabbed, another must be free.
+ *
+ * Note, that this procedure can be called by a watchdog timer
+ *
+ * Returns to the caller:
+ * 0 - queue is empty or throttled.
+ * >0 - queue is not empty.
+ *
+ */
static inline int qdisc_restart(struct net_device *dev)
{
struct Qdisc *q = dev->qdisc;
struct sk_buff *skb;
+ unsigned lockless;
+ int ret;
/* Dequeue packet */
- if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
- unsigned nolock = (dev->features & NETIF_F_LLTX);
+ if (unlikely((skb = dev_dequeue_skb(dev, q)) == NULL))
+ return 0;
+
+ /*
+ * When the driver has LLTX set, it does its own locking in
+ * start_xmit. These checks are worth it because even uncongested
+ * locks can be quite expensive. The driver can do a trylock, as
+ * is being done here; in case of lock contention it should return
+ * NETDEV_TX_LOCKED and the packet will be requeued.
+ */
+ lockless = (dev->features & NETIF_F_LLTX);
- dev->gso_skb = NULL;
+ if (!lockless && !netif_tx_trylock(dev)) {
+ /* Another CPU grabbed the driver tx lock */
+ return handle_dev_cpu_collision(skb, dev, q);
+ }
- /*
- * When the driver has LLTX set it does its own locking
- * in start_xmit. No need to add additional overhead by
- * locking again. These checks are worth it because
- * even uncongested locks can be quite expensive.
- * The driver can do trylock like here too, in case
- * of lock congestion it should return -1 and the packet
- * will be requeued.
- */
- if (!nolock) {
- if (!netif_tx_trylock(dev)) {
- collision:
- /* So, someone grabbed the driver. */
-
- /* It may be transient configuration error,
- when hard_start_xmit() recurses. We detect
- it by checking xmit owner and drop the
- packet when deadloop is detected.
- */
- if (dev->xmit_lock_owner == smp_processor_id()) {
- kfree_skb(skb);
- if (net_ratelimit())
- printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
- goto out;
- }
- __get_cpu_var(netdev_rx_stat).cpu_collision++;
- goto requeue;
- }
- }
+ /* And release queue */
+ spin_unlock(&dev->queue_lock);
- {
- /* And release queue */
- spin_unlock(&dev->queue_lock);
-
- if (!netif_queue_stopped(dev)) {
- int ret;
-
- ret = dev_hard_start_xmit(skb, dev);
- if (ret == NETDEV_TX_OK) {
- if (!nolock) {
- netif_tx_unlock(dev);
- }
- spin_lock(&dev->queue_lock);
- q = dev->qdisc;
- goto out;
- }
- if (ret == NETDEV_TX_LOCKED && nolock) {
- spin_lock(&dev->queue_lock);
- q = dev->qdisc;
- goto collision;
- }
- }
+ ret = dev_hard_start_xmit(skb, dev);
- /* NETDEV_TX_BUSY - we need to requeue */
- /* Release the driver */
- if (!nolock) {
- netif_tx_unlock(dev);
- }
- spin_lock(&dev->queue_lock);
- q = dev->qdisc;
- }
+ if (!lockless)
+ netif_tx_unlock(dev);
- /* Device kicked us out :(
- This is possible in three cases:
+ spin_lock(&dev->queue_lock);
+ q = dev->qdisc;
- 0. driver is locked
- 1. fastroute is enabled
- 2. device cannot determine busy state
- before start of transmission (f.e. dialout)
- 3. device is buggy (ppp)
- */
+ switch (ret) {
+ case NETDEV_TX_OK:
+ /* Driver sent out skb successfully */
+ ret = qdisc_qlen(q);
+ break;
-requeue:
- if (unlikely(q == &noop_qdisc))
- kfree_skb(skb);
- else if (skb->next)
- dev->gso_skb = skb;
- else
- q->ops->requeue(skb, q);
- netif_schedule(dev);
+ case NETDEV_TX_LOCKED:
+ /* Driver try lock failed */
+ ret = handle_dev_cpu_collision(skb, dev, q);
+ break;
+
+ default:
+ /* Driver returned NETDEV_TX_BUSY - requeue skb */
+ if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit()))
+ printk(KERN_WARNING "BUG %s code %d qlen %d\n",
+ dev->name, ret, q->q.qlen);
+
+ ret = dev_requeue_skb(skb, dev, q);
+ break;
}
- return 0;
-out:
- BUG_ON((int) q->q.qlen < 0);
- return q->q.qlen;
+ return ret;
}
void __qdisc_run(struct net_device *dev)
@@ -224,7 +237,8 @@ void __netdev_watchdog_up(struct net_device *dev)
if (dev->tx_timeout) {
if (dev->watchdog_timeo <= 0)
dev->watchdog_timeo = 5*HZ;
- if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo))
+ if (!mod_timer(&dev->watchdog_timer,
+ round_jiffies(jiffies + dev->watchdog_timeo)))
dev_hold(dev);
}
}
@@ -492,9 +506,7 @@ void qdisc_destroy(struct Qdisc *qdisc)
return;
list_del(&qdisc->list);
-#ifdef CONFIG_NET_ESTIMATOR
gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
-#endif
if (ops->reset)
ops->reset(qdisc);
if (ops->destroy)
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index fa1b4fe7a5f..3cc6dda02e2 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -21,7 +21,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/pkt_sched.h>
#include <net/red.h>
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 9d124c4ee3a..55e7e4530f4 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -53,7 +53,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/jiffies.h>
#include <linux/compiler.h>
#include <linux/spinlock.h>
#include <linux/skbuff.h>
@@ -62,13 +61,11 @@
#include <linux/list.h>
#include <linux/rbtree.h>
#include <linux/init.h>
-#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/pkt_sched.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
#include <net/pkt_cls.h>
-#include <asm/system.h>
#include <asm/div64.h>
/*
@@ -122,7 +119,6 @@ struct hfsc_class
struct gnet_stats_basic bstats;
struct gnet_stats_queue qstats;
struct gnet_stats_rate_est rate_est;
- spinlock_t *stats_lock;
unsigned int level; /* class level in hierarchy */
struct tcf_proto *filter_list; /* filter list */
unsigned int filter_cnt; /* filter count */
@@ -1054,11 +1050,10 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
}
sch_tree_unlock(sch);
-#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1])
gen_replace_estimator(&cl->bstats, &cl->rate_est,
- cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+ &sch->dev->queue_lock,
+ tca[TCA_RATE-1]);
return 0;
}
@@ -1098,7 +1093,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
if (cl->qdisc == NULL)
cl->qdisc = &noop_qdisc;
- cl->stats_lock = &sch->dev->queue_lock;
INIT_LIST_HEAD(&cl->children);
cl->vt_tree = RB_ROOT;
cl->cf_tree = RB_ROOT;
@@ -1112,11 +1106,9 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
cl->cl_pcvtoff = parent->cl_cvtoff;
sch_tree_unlock(sch);
-#ifdef CONFIG_NET_ESTIMATOR
if (tca[TCA_RATE-1])
gen_new_estimator(&cl->bstats, &cl->rate_est,
- cl->stats_lock, tca[TCA_RATE-1]);
-#endif
+ &sch->dev->queue_lock, tca[TCA_RATE-1]);
*arg = (unsigned long)cl;
return 0;
}
@@ -1128,9 +1120,7 @@ hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl)
tcf_destroy_chain(cl->filter_list);
qdisc_destroy(cl->qdisc);
-#ifdef CONFIG_NET_ESTIMATOR
gen_kill_estimator(&cl->bstats, &cl->rate_est);
-#endif
if (cl != &q->root)
kfree(cl);
}
@@ -1184,9 +1174,6 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
case TC_ACT_SHOT:
return NULL;
}
-#elif defined(CONFIG_NET_CLS_POLICE)
- if (result == TC_POLICE_SHOT)
- return NULL;
#endif
if ((cl = (struct hfsc_class *)res.class) == NULL) {
if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
@@ -1384,9 +1371,7 @@ hfsc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
xstats.rtwork = cl->cl_cumul;
if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
-#ifdef CONFIG_NET_ESTIMATOR
gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
-#endif
gnet_stats_copy_queue(d, &cl->qstats) < 0)
return -1;
@@ -1448,8 +1433,6 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
return -EINVAL;
qopt = RTA_DATA(opt);
- sch->stats_lock = &sch->dev->queue_lock;
-
q->defcls = qopt->defcls;
for (i = 0; i < HFSC_HSIZE; i++)
INIT_LIST_HEAD(&q->clhash[i]);
@@ -1464,7 +1447,6 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
sch->handle);
if (q->root.qdisc == NULL)
q->root.qdisc = &noop_qdisc;
- q->root.stats_lock = &sch->dev->queue_lock;
INIT_LIST_HEAD(&q->root.children);
q->root.vt_tree = RB_ROOT;
q->root.cf_tree = RB_ROOT;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 035788c5b7f..246a2f9765f 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -28,32 +28,16 @@
* $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
#include <linux/skbuff.h>
#include <linux/list.h>
#include <linux/compiler.h>
+#include <linux/rbtree.h>
#include <net/netlink.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
-#include <linux/rbtree.h>
/* HTB algorithm.
Author: devik@cdi.cz
@@ -69,8 +53,6 @@
*/
#define HTB_HSIZE 16 /* classid hash size */
-#define HTB_EWMAC 2 /* rate average over HTB_EWMAC*HTB_HSIZE sec */
-#define HTB_RATECM 1 /* whether to use rate computer */
#define HTB_HYSTERESIS 1 /* whether to use mode hysteresis for speedup */
#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */
@@ -95,12 +77,6 @@ struct htb_class {
struct tc_htb_xstats xstats; /* our special stats */
int refcnt; /* usage count of this class */
-#ifdef HTB_RATECM
- /* rate measurement counters */
- unsigned long rate_bytes, sum_bytes;
- unsigned long rate_packets, sum_packets;
-#endif
-
/* topology */
int level; /* our level (see above) */
struct htb_class *parent; /* parent class */
@@ -153,15 +129,12 @@ struct htb_class {
/* of un.leaf originals should be done. */
};
-/* TODO: maybe compute rate when size is too large .. or drop ? */
static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate,
int size)
{
int slot = size >> rate->rate.cell_log;
- if (slot > 255) {
- cl->xstats.giants++;
- slot = 255;
- }
+ if (slot > 255)
+ return (rate->data[255]*(slot >> 8) + rate->data[slot & 0xFF]);
return rate->data[slot];
}
@@ -194,10 +167,6 @@ struct htb_sched {
int rate2quantum; /* quant = rate / rate2quantum */
psched_time_t now; /* cached dequeue time */
struct qdisc_watchdog watchdog;
-#ifdef HTB_RATECM
- struct timer_list rttim; /* rate computer timer */
- int recmp_bucket; /* which hash bucket to recompute next */
-#endif
/* non shaped skbs; let them go directly thru */
struct sk_buff_head direct_queue;
@@ -280,9 +249,6 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
case TC_ACT_SHOT:
return NULL;
}
-#elif defined(CONFIG_NET_CLS_POLICE)
- if (result == TC_POLICE_SHOT)
- return HTB_DIRECT;
#endif
if ((cl = (void *)res.class) == NULL) {
if (res.classid == sch->handle)
@@ -634,13 +600,14 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
cl->qstats.drops++;
return NET_XMIT_DROP;
} else {
- cl->bstats.packets++;
+ cl->bstats.packets +=
+ skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
cl->bstats.bytes += skb->len;
htb_activate(q, cl);
}
sch->q.qlen++;
- sch->bstats.packets++;
+ sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
sch->bstats.bytes += skb->len;
return NET_XMIT_SUCCESS;
}
@@ -677,34 +644,6 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch)
return NET_XMIT_SUCCESS;
}
-#ifdef HTB_RATECM
-#define RT_GEN(D,R) R+=D-(R/HTB_EWMAC);D=0
-static void htb_rate_timer(unsigned long arg)
-{
- struct Qdisc *sch = (struct Qdisc *)arg;
- struct htb_sched *q = qdisc_priv(sch);
- struct hlist_node *p;
- struct htb_class *cl;
-
-
- /* lock queue so that we can muck with it */
- spin_lock_bh(&sch->dev->queue_lock);
-
- q->rttim.expires = jiffies + HZ;
- add_timer(&q->rttim);
-
- /* scan and recompute one bucket at time */
- if (++q->recmp_bucket >= HTB_HSIZE)
- q->recmp_bucket = 0;
-
- hlist_for_each_entry(cl,p, q->hash + q->recmp_bucket, hlist) {
- RT_GEN(cl->sum_bytes, cl->rate_bytes);
- RT_GEN(cl->sum_packets, cl->rate_packets);
- }
- spin_unlock_bh(&sch->dev->queue_lock);
-}
-#endif
-
/**
* htb_charge_class - charges amount "bytes" to leaf and ancestors
*
@@ -717,8 +656,9 @@ static void htb_rate_timer(unsigned long arg)
* In such case we remove class from event queue first.
*/
static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
- int level, int bytes)
+ int level, struct sk_buff *skb)
{
+ int bytes = skb->len;
long toks, diff;
enum htb_cmode old_mode;
@@ -750,16 +690,12 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
if (cl->cmode != HTB_CAN_SEND)
htb_add_to_wait_tree(q, cl, diff);
}
-#ifdef HTB_RATECM
- /* update rate counters */
- cl->sum_bytes += bytes;
- cl->sum_packets++;
-#endif
/* update byte stats except for leaves which are already updated */
if (cl->level) {
cl->bstats.bytes += bytes;
- cl->bstats.packets++;
+ cl->bstats.packets += skb_is_gso(skb)?
+ skb_shinfo(skb)->gso_segs:1;
}
cl = cl->parent;
}
@@ -943,7 +879,7 @@ next:
gives us slightly better performance */
if (!cl->un.leaf.q->q.qlen)
htb_deactivate(q, cl);
- htb_charge_class(q, cl, level, skb->len);
+ htb_charge_class(q, cl, level, skb);
}
return skb;
}
@@ -1095,13 +1031,6 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt)
if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */
q->direct_qlen = 2;
-#ifdef HTB_RATECM
- init_timer(&q->rttim);
- q->rttim.function = htb_rate_timer;
- q->rttim.data = (unsigned long)sch;
- q->rttim.expires = jiffies + HZ;
- add_timer(&q->rttim);
-#endif
if ((q->rate2quantum = gopt->rate2quantum) < 1)
q->rate2quantum = 1;
q->defcls = gopt->defcls;
@@ -1175,11 +1104,6 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
{
struct htb_class *cl = (struct htb_class *)arg;
-#ifdef HTB_RATECM
- cl->rate_est.bps = cl->rate_bytes / (HTB_EWMAC * HTB_HSIZE);
- cl->rate_est.pps = cl->rate_packets / (HTB_EWMAC * HTB_HSIZE);
-#endif
-
if (!cl->level && cl->un.leaf.q)
cl->qstats.qlen = cl->un.leaf.q->q.qlen;
cl->xstats.tokens = cl->tokens;
@@ -1277,6 +1201,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
BUG_TRAP(cl->un.leaf.q);
qdisc_destroy(cl->un.leaf.q);
}
+ gen_kill_estimator(&cl->bstats, &cl->rate_est);
qdisc_put_rtab(cl->rate);
qdisc_put_rtab(cl->ceil);
@@ -1305,9 +1230,6 @@ static void htb_destroy(struct Qdisc *sch)
struct htb_sched *q = qdisc_priv(sch);
qdisc_watchdog_cancel(&q->watchdog);
-#ifdef HTB_RATECM
- del_timer_sync(&q->rttim);
-#endif
/* This line used to be after htb_destroy_class call below
and surprisingly it worked in 2.4. But it must precede it
because filter need its target class alive to be able to call
@@ -1403,6 +1325,20 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
if (!cl) { /* new class */
struct Qdisc *new_q;
int prio;
+ struct {
+ struct rtattr rta;
+ struct gnet_estimator opt;
+ } est = {
+ .rta = {
+ .rta_len = RTA_LENGTH(sizeof(est.opt)),
+ .rta_type = TCA_RATE,
+ },
+ .opt = {
+ /* 4s interval, 16s averaging constant */
+ .interval = 2,
+ .ewma_log = 2,
+ },
+ };
/* check for valid classid */
if (!classid || TC_H_MAJ(classid ^ sch->handle)
@@ -1418,6 +1354,9 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
goto failure;
+ gen_new_estimator(&cl->bstats, &cl->rate_est,
+ &sch->dev->queue_lock,
+ tca[TCA_RATE-1] ? : &est.rta);
cl->refcnt = 1;
INIT_LIST_HEAD(&cl->sibling);
INIT_HLIST_NODE(&cl->hlist);
@@ -1469,8 +1408,13 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
hlist_add_head(&cl->hlist, q->hash + htb_hash(classid));
list_add_tail(&cl->sibling,
parent ? &parent->children : &q->root);
- } else
+ } else {
+ if (tca[TCA_RATE-1])
+ gen_replace_estimator(&cl->bstats, &cl->rate_est,
+ &sch->dev->queue_lock,
+ tca[TCA_RATE-1]);
sch_tree_lock(sch);
+ }
/* it used to be a nasty bug here, we have to check that node
is really leaf before changing cl->un.leaf ! */
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index f8b9f1cdf73..51f16b0af19 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -9,21 +9,14 @@
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/list.h>
#include <linux/skbuff.h>
-#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/netfilter.h>
-#include <linux/smp.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-#include <linux/kmod.h>
-#include <linux/stat.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
#undef DEBUG_INGRESS
@@ -171,31 +164,12 @@ static int ingress_enqueue(struct sk_buff *skb,struct Qdisc *sch)
result = TC_ACT_OK;
break;
}
-/* backward compat */
-#else
-#ifdef CONFIG_NET_CLS_POLICE
- switch (result) {
- case TC_POLICE_SHOT:
- result = NF_DROP;
- sch->qstats.drops++;
- break;
- case TC_POLICE_RECLASSIFY: /* DSCP remarking here ? */
- case TC_POLICE_OK:
- case TC_POLICE_UNSPEC:
- default:
- sch->bstats.packets++;
- sch->bstats.bytes += skb->len;
- result = NF_ACCEPT;
- break;
- }
-
#else
D2PRINTK("Overriding result to ACCEPT\n");
result = NF_ACCEPT;
sch->bstats.packets++;
sch->bstats.bytes += skb->len;
#endif
-#endif
return result;
}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 5d9d8bc9cc3..9e5e87e81f0 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -14,11 +14,9 @@
*/
#include <linux/module.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 6d7542c26e4..2d8c08493d6 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -12,37 +12,23 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
#include <linux/skbuff.h>
#include <net/netlink.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
struct prio_sched_data
{
int bands;
+ int curband; /* for round-robin */
struct tcf_proto *filter_list;
u8 prio2band[TC_PRIO_MAX+1];
struct Qdisc *queues[TCQ_PRIO_BANDS];
+ int mq;
};
@@ -70,14 +56,17 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
#endif
if (TC_H_MAJ(band))
band = 0;
- return q->queues[q->prio2band[band&TC_PRIO_MAX]];
+ band = q->prio2band[band&TC_PRIO_MAX];
+ goto out;
}
band = res.classid;
}
band = TC_H_MIN(band) - 1;
if (band >= q->bands)
- return q->queues[q->prio2band[0]];
-
+ band = q->prio2band[0];
+out:
+ if (q->mq)
+ skb_set_queue_mapping(skb, band);
return q->queues[band];
}
@@ -144,17 +133,58 @@ prio_dequeue(struct Qdisc* sch)
struct Qdisc *qdisc;
for (prio = 0; prio < q->bands; prio++) {
- qdisc = q->queues[prio];
- skb = qdisc->dequeue(qdisc);
- if (skb) {
- sch->q.qlen--;
- return skb;
+ /* Check if the target subqueue is available before
+ * pulling an skb. This way we avoid excessive requeues
+ * for slower queues.
+ */
+ if (!netif_subqueue_stopped(sch->dev, (q->mq ? prio : 0))) {
+ qdisc = q->queues[prio];
+ skb = qdisc->dequeue(qdisc);
+ if (skb) {
+ sch->q.qlen--;
+ return skb;
+ }
}
}
return NULL;
}
+static struct sk_buff *rr_dequeue(struct Qdisc* sch)
+{
+ struct sk_buff *skb;
+ struct prio_sched_data *q = qdisc_priv(sch);
+ struct Qdisc *qdisc;
+ int bandcount;
+
+ /* Only take one pass through the queues. If nothing is available,
+ * return nothing.
+ */
+ for (bandcount = 0; bandcount < q->bands; bandcount++) {
+ /* Check if the target subqueue is available before
+ * pulling an skb. This way we avoid excessive requeues
+ * for slower queues. If the queue is stopped, try the
+ * next queue.
+ */
+ if (!netif_subqueue_stopped(sch->dev,
+ (q->mq ? q->curband : 0))) {
+ qdisc = q->queues[q->curband];
+ skb = qdisc->dequeue(qdisc);
+ if (skb) {
+ sch->q.qlen--;
+ q->curband++;
+ if (q->curband >= q->bands)
+ q->curband = 0;
+ return skb;
+ }
+ }
+ q->curband++;
+ if (q->curband >= q->bands)
+ q->curband = 0;
+ }
+ return NULL;
+}
+
static unsigned int prio_drop(struct Qdisc* sch)
{
struct prio_sched_data *q = qdisc_priv(sch);
@@ -198,21 +228,41 @@ prio_destroy(struct Qdisc* sch)
static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
{
struct prio_sched_data *q = qdisc_priv(sch);
- struct tc_prio_qopt *qopt = RTA_DATA(opt);
+ struct tc_prio_qopt *qopt;
+ struct rtattr *tb[TCA_PRIO_MAX];
int i;
- if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+ if (rtattr_parse_nested_compat(tb, TCA_PRIO_MAX, opt, qopt,
+ sizeof(*qopt)))
return -EINVAL;
- if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2)
+ q->bands = qopt->bands;
+ /* If we're multiqueue, make sure the number of incoming bands
+ * matches the number of queues on the device we're associating with.
+ * If the number of bands requested is zero, then set q->bands to
+ * dev->egress_subqueue_count.
+ */
+ q->mq = RTA_GET_FLAG(tb[TCA_PRIO_MQ - 1]);
+ if (q->mq) {
+ if (sch->handle != TC_H_ROOT)
+ return -EINVAL;
+ if (netif_is_multiqueue(sch->dev)) {
+ if (q->bands == 0)
+ q->bands = sch->dev->egress_subqueue_count;
+ else if (q->bands != sch->dev->egress_subqueue_count)
+ return -EINVAL;
+ } else
+ return -EOPNOTSUPP;
+ }
+
+ if (q->bands > TCQ_PRIO_BANDS || q->bands < 2)
return -EINVAL;
for (i=0; i<=TC_PRIO_MAX; i++) {
- if (qopt->priomap[i] >= qopt->bands)
+ if (qopt->priomap[i] >= q->bands)
return -EINVAL;
}
sch_tree_lock(sch);
- q->bands = qopt->bands;
memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
for (i=q->bands; i<TCQ_PRIO_BANDS; i++) {
@@ -268,11 +318,17 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct prio_sched_data *q = qdisc_priv(sch);
unsigned char *b = skb_tail_pointer(skb);
+ struct rtattr *nest;
struct tc_prio_qopt opt;
opt.bands = q->bands;
memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1);
- RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+ nest = RTA_NEST_COMPAT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+ if (q->mq)
+ RTA_PUT_FLAG(skb, TCA_PRIO_MQ);
+ RTA_NEST_COMPAT_END(skb, nest);
+
return skb->len;
rtattr_failure:
@@ -443,17 +499,44 @@ static struct Qdisc_ops prio_qdisc_ops = {
.owner = THIS_MODULE,
};
+static struct Qdisc_ops rr_qdisc_ops = {
+ .next = NULL,
+ .cl_ops = &prio_class_ops,
+ .id = "rr",
+ .priv_size = sizeof(struct prio_sched_data),
+ .enqueue = prio_enqueue,
+ .dequeue = rr_dequeue,
+ .requeue = prio_requeue,
+ .drop = prio_drop,
+ .init = prio_init,
+ .reset = prio_reset,
+ .destroy = prio_destroy,
+ .change = prio_tune,
+ .dump = prio_dump,
+ .owner = THIS_MODULE,
+};
+
static int __init prio_module_init(void)
{
- return register_qdisc(&prio_qdisc_ops);
+ int err;
+
+ err = register_qdisc(&prio_qdisc_ops);
+ if (err < 0)
+ return err;
+ err = register_qdisc(&rr_qdisc_ops);
+ if (err < 0)
+ unregister_qdisc(&prio_qdisc_ops);
+ return err;
}
static void __exit prio_module_exit(void)
{
unregister_qdisc(&prio_qdisc_ops);
+ unregister_qdisc(&rr_qdisc_ops);
}
module_init(prio_module_init)
module_exit(prio_module_exit)
MODULE_LICENSE("GPL");
+MODULE_ALIAS("sch_rr");
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 00db53eb815..9b95fefb70f 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -17,7 +17,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/pkt_sched.h>
#include <net/inet_ecn.h>
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 96dfdf78d32..95795730985 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -10,31 +10,17 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
#include <linux/init.h>
-#include <net/ip.h>
-#include <net/netlink.h>
#include <linux/ipv6.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/ip.h>
+#include <net/netlink.h>
#include <net/pkt_sched.h>
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 53862953baa..8c2639af4c6 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -13,29 +13,12 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/jiffies.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/netlink.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
+#include <net/netlink.h>
#include <net/pkt_sched.h>
@@ -142,7 +125,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
if (skb->len > q->max_size) {
sch->qstats.drops++;
-#ifdef CONFIG_NET_CLS_POLICE
+#ifdef CONFIG_NET_CLS_ACT
if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
#endif
kfree_skb(skb);
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index f05ad9a30b4..0968184ea6b 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -9,30 +9,17 @@
*/
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
#include <linux/init.h>
-#include <net/ip.h>
-#include <net/route.h>
#include <linux/skbuff.h>
#include <linux/moduleparam.h>
-#include <net/sock.h>
+#include <net/dst.h>
+#include <net/neighbour.h>
#include <net/pkt_sched.h>
/*
@@ -225,7 +212,6 @@ static int teql_qdisc_init(struct Qdisc *sch, struct rtattr *opt)
return 0;
}
-/* "teql*" netdevice routines */
static int
__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev)
@@ -277,6 +263,7 @@ static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
int busy;
int nores;
int len = skb->len;
+ int subq = skb->queue_mapping;
struct sk_buff *skb_res = NULL;
start = master->slaves;
@@ -293,7 +280,9 @@ restart:
if (slave->qdisc_sleeping != q)
continue;
- if (netif_queue_stopped(slave) || ! netif_running(slave)) {
+ if (netif_queue_stopped(slave) ||
+ netif_subqueue_stopped(slave, subq) ||
+ !netif_running(slave)) {
busy = 1;
continue;
}
@@ -302,6 +291,7 @@ restart:
case 0:
if (netif_tx_trylock(slave)) {
if (!netif_queue_stopped(slave) &&
+ !netif_subqueue_stopped(slave, subq) &&
slave->hard_start_xmit(skb, slave) == 0) {
netif_tx_unlock(slave);
master->slaves = NEXT_SLAVE(q);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index df94e3cdfba..498edb0cd4e 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1231,6 +1231,10 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
/* Get the lowest pmtu of all the transports. */
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, struct sctp_transport, transports);
+ if (t->pmtu_pending && t->dst) {
+ sctp_transport_update_pmtu(t, dst_mtu(t->dst));
+ t->pmtu_pending = 0;
+ }
if (!pmtu || (t->pathmtu < pmtu))
pmtu = t->pathmtu;
}
diff --git a/net/sctp/debug.c b/net/sctp/debug.c
index e8c0f7435d7..80f70aa5338 100644
--- a/net/sctp/debug.c
+++ b/net/sctp/debug.c
@@ -77,8 +77,6 @@ static const char *sctp_cid_tbl[SCTP_NUM_BASE_CHUNK_TYPES] = {
/* Lookup "chunk type" debug name. */
const char *sctp_cname(const sctp_subtype_t cid)
{
- if (cid.chunk < 0)
- return "illegal chunk id";
if (cid.chunk <= SCTP_CID_BASE_MAX)
return sctp_cid_tbl[cid.chunk];
@@ -146,8 +144,6 @@ static const char *sctp_primitive_tbl[SCTP_NUM_PRIMITIVE_TYPES] = {
/* Lookup primitive debug name. */
const char *sctp_pname(const sctp_subtype_t id)
{
- if (id.primitive < 0)
- return "illegal primitive";
if (id.primitive <= SCTP_EVENT_PRIMITIVE_MAX)
return sctp_primitive_tbl[id.primitive];
return "unknown_primitive";
@@ -161,8 +157,6 @@ static const char *sctp_other_tbl[] = {
/* Lookup "other" debug name. */
const char *sctp_oname(const sctp_subtype_t id)
{
- if (id.other < 0)
- return "illegal 'other' event";
if (id.other <= SCTP_EVENT_OTHER_MAX)
return sctp_other_tbl[id.other];
return "unknown 'other' event";
@@ -184,8 +178,6 @@ static const char *sctp_timer_tbl[] = {
/* Lookup timer debug name. */
const char *sctp_tname(const sctp_subtype_t id)
{
- if (id.timeout < 0)
- return "illegal 'timer' event";
if (id.timeout <= SCTP_EVENT_TIMEOUT_MAX)
return sctp_timer_tbl[id.timeout];
return "unknown_timer";
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 885109fb3dd..d57ff7f3c57 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -367,24 +367,18 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
struct sctp_transport *t, __u32 pmtu)
{
- if (sock_owned_by_user(sk) || !t || (t->pathmtu == pmtu))
+ if (!t || (t->pathmtu == pmtu))
return;
+ if (sock_owned_by_user(sk)) {
+ asoc->pmtu_pending = 1;
+ t->pmtu_pending = 1;
+ return;
+ }
+
if (t->param_flags & SPP_PMTUD_ENABLE) {
- if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
- printk(KERN_WARNING "%s: Reported pmtu %d too low, "
- "using default minimum of %d\n",
- __FUNCTION__, pmtu,
- SCTP_DEFAULT_MINSEGMENT);
- /* Use default minimum segment size and disable
- * pmtu discovery on this transport.
- */
- t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
- t->param_flags = (t->param_flags & ~SPP_PMTUD) |
- SPP_PMTUD_DISABLE;
- } else {
- t->pathmtu = pmtu;
- }
+ /* Update transports view of the MTU */
+ sctp_transport_update_pmtu(t, pmtu);
/* Update association pmtu. */
sctp_assoc_sync_pmtu(asoc);
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 84cd53635fe..2c29394fd92 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -844,6 +844,10 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
dev = dev_get_by_index(addr->v6.sin6_scope_id);
if (!dev)
return 0;
+ if (!ipv6_chk_addr(&addr->v6.sin6_addr, dev, 0)) {
+ dev_put(dev);
+ return 0;
+ }
dev_put(dev);
}
af = opt->pf->af;
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 2f12bf2d8d3..e4cd841a22e 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -250,7 +250,7 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations sctp_eps_ops = {
+static const struct seq_operations sctp_eps_ops = {
.start = sctp_eps_seq_start,
.next = sctp_eps_seq_next,
.stop = sctp_eps_seq_stop,
@@ -361,7 +361,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static struct seq_operations sctp_assoc_ops = {
+static const struct seq_operations sctp_assoc_ops = {
.start = sctp_assocs_seq_start,
.next = sctp_assocs_seq_next,
.stop = sctp_assocs_seq_stop,
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 523071c7902..70a91ece3c4 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -960,7 +960,7 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
if (state > SCTP_STATE_MAX)
return &bug;
- if (cid >= 0 && cid <= SCTP_CID_BASE_MAX)
+ if (cid <= SCTP_CID_BASE_MAX)
return &chunk_event_table[cid][state];
if (sctp_prsctp_enable) {
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 4dcdabf5647..b1917f68723 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -333,12 +333,19 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
if (!sp->pf->bind_verify(sp, addr))
return -EADDRNOTAVAIL;
- /* We must either be unbound, or bind to the same port. */
- if (bp->port && (snum != bp->port)) {
- SCTP_DEBUG_PRINTK("sctp_do_bind:"
+ /* We must either be unbound, or bind to the same port.
+ * It's OK to allow 0 ports if we are already bound.
+ * We'll just inhert an already bound port in this case
+ */
+ if (bp->port) {
+ if (!snum)
+ snum = bp->port;
+ else if (snum != bp->port) {
+ SCTP_DEBUG_PRINTK("sctp_do_bind:"
" New port %d does not match existing port "
"%d.\n", snum, bp->port);
- return -EINVAL;
+ return -EINVAL;
+ }
}
if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
@@ -973,6 +980,7 @@ static int __sctp_connect(struct sock* sk,
union sctp_addr *sa_addr;
void *addr_buf;
unsigned short port;
+ unsigned int f_flags = 0;
sp = sctp_sk(sk);
ep = sp->ep;
@@ -1099,7 +1107,14 @@ static int __sctp_connect(struct sock* sk,
af->to_sk_daddr(&to, sk);
sk->sk_err = 0;
- timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
+ /* in-kernel sockets don't generally have a file allocated to them
+ * if all they do is call sock_create_kern().
+ */
+ if (sk->sk_socket->file)
+ f_flags = sk->sk_socket->file->f_flags;
+
+ timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
+
err = sctp_wait_for_connect(asoc, &timeo);
/* Don't free association on exit. */
@@ -1655,6 +1670,9 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
goto out_free;
}
+ if (asoc->pmtu_pending)
+ sctp_assoc_pending_pmtu(asoc);
+
/* If fragmentation is disabled and the message length exceeds the
* association fragmentation point, return EMSGSIZE. The I-D
* does not specify what this error is, but this looks like
@@ -3365,12 +3383,13 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
sctp_assoc_t associd;
int retval = 0;
- if (len != sizeof(status)) {
+ if (len < sizeof(status)) {
retval = -EINVAL;
goto out;
}
- if (copy_from_user(&status, optval, sizeof(status))) {
+ len = sizeof(status);
+ if (copy_from_user(&status, optval, len)) {
retval = -EFAULT;
goto out;
}
@@ -3442,12 +3461,13 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
struct sctp_transport *transport;
int retval = 0;
- if (len != sizeof(pinfo)) {
+ if (len < sizeof(pinfo)) {
retval = -EINVAL;
goto out;
}
- if (copy_from_user(&pinfo, optval, sizeof(pinfo))) {
+ len = sizeof(pinfo);
+ if (copy_from_user(&pinfo, optval, len)) {
retval = -EFAULT;
goto out;
}
@@ -3513,8 +3533,11 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
int __user *optlen)
{
- if (len != sizeof(struct sctp_event_subscribe))
+ if (len < sizeof(struct sctp_event_subscribe))
return -EINVAL;
+ len = sizeof(struct sctp_event_subscribe);
+ if (put_user(len, optlen))
+ return -EFAULT;
if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len))
return -EFAULT;
return 0;
@@ -3536,9 +3559,12 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv
/* Applicable to UDP-style socket only */
if (sctp_style(sk, TCP))
return -EOPNOTSUPP;
- if (len != sizeof(int))
+ if (len < sizeof(int))
return -EINVAL;
- if (copy_to_user(optval, &sctp_sk(sk)->autoclose, len))
+ len = sizeof(int);
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &sctp_sk(sk)->autoclose, sizeof(int)))
return -EFAULT;
return 0;
}
@@ -3550,6 +3576,7 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
struct sock *sk = asoc->base.sk;
struct socket *sock;
struct inet_sock *inetsk;
+ struct sctp_af *af;
int err = 0;
/* An association cannot be branched off from an already peeled-off
@@ -3571,8 +3598,9 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
/* Make peeled-off sockets more like 1-1 accepted sockets.
* Set the daddr and initialize id to something more random
*/
+ af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family);
+ af->to_sk_daddr(&asoc->peer.primary_addr, sk);
inetsk = inet_sk(sock->sk);
- inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
inetsk->id = asoc->next_tsn ^ jiffies;
*sockp = sock;
@@ -3587,8 +3615,9 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
int retval = 0;
struct sctp_association *asoc;
- if (len != sizeof(sctp_peeloff_arg_t))
+ if (len < sizeof(sctp_peeloff_arg_t))
return -EINVAL;
+ len = sizeof(sctp_peeloff_arg_t);
if (copy_from_user(&peeloff, optval, len))
return -EFAULT;
@@ -3616,6 +3645,8 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
/* Return the fd mapped to the new socket. */
peeloff.sd = retval;
+ if (put_user(len, optlen))
+ return -EFAULT;
if (copy_to_user(optval, &peeloff, len))
retval = -EFAULT;
@@ -3724,9 +3755,9 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
struct sctp_association *asoc = NULL;
struct sctp_sock *sp = sctp_sk(sk);
- if (len != sizeof(struct sctp_paddrparams))
+ if (len < sizeof(struct sctp_paddrparams))
return -EINVAL;
-
+ len = sizeof(struct sctp_paddrparams);
if (copy_from_user(&params, optval, len))
return -EFAULT;
@@ -3825,9 +3856,11 @@ static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len,
struct sctp_association *asoc = NULL;
struct sctp_sock *sp = sctp_sk(sk);
- if (len != sizeof(struct sctp_assoc_value))
+ if (len < sizeof(struct sctp_assoc_value))
return - EINVAL;
+ len = sizeof(struct sctp_assoc_value);
+
if (copy_from_user(&params, optval, len))
return -EFAULT;
@@ -3876,8 +3909,11 @@ static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len,
*/
static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, int __user *optlen)
{
- if (len != sizeof(struct sctp_initmsg))
+ if (len < sizeof(struct sctp_initmsg))
return -EINVAL;
+ len = sizeof(struct sctp_initmsg);
+ if (put_user(len, optlen))
+ return -EFAULT;
if (copy_to_user(optval, &sctp_sk(sk)->initmsg, len))
return -EFAULT;
return 0;
@@ -3892,7 +3928,7 @@ static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len,
struct list_head *pos;
int cnt = 0;
- if (len != sizeof(sctp_assoc_t))
+ if (len < sizeof(sctp_assoc_t))
return -EINVAL;
if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
@@ -3928,10 +3964,12 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
struct sctp_sock *sp = sctp_sk(sk);
int addrlen;
- if (len != sizeof(struct sctp_getaddrs_old))
+ if (len < sizeof(struct sctp_getaddrs_old))
return -EINVAL;
- if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old)))
+ len = sizeof(struct sctp_getaddrs_old);
+
+ if (copy_from_user(&getaddrs, optval, len))
return -EFAULT;
if (getaddrs.addr_num <= 0) return -EINVAL;
@@ -3954,7 +3992,9 @@ static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
if (cnt >= getaddrs.addr_num) break;
}
getaddrs.addr_num = cnt;
- if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old)))
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &getaddrs, len))
return -EFAULT;
return 0;
@@ -3987,8 +4027,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
return -EINVAL;
to = optval + offsetof(struct sctp_getaddrs,addrs);
- space_left = len - sizeof(struct sctp_getaddrs) -
- offsetof(struct sctp_getaddrs,addrs);
+ space_left = len - offsetof(struct sctp_getaddrs,addrs);
list_for_each(pos, &asoc->peer.transport_addr_list) {
from = list_entry(pos, struct sctp_transport, transports);
@@ -4025,7 +4064,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
rwlock_t *addr_lock;
int cnt = 0;
- if (len != sizeof(sctp_assoc_t))
+ if (len < sizeof(sctp_assoc_t))
return -EINVAL;
if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
@@ -4139,7 +4178,7 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
to += addrlen;
cnt ++;
space_left -= addrlen;
- bytes_copied += addrlen;
+ *bytes_copied += addrlen;
}
return cnt;
@@ -4167,10 +4206,11 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
void *buf;
int bytes_copied = 0;
- if (len != sizeof(struct sctp_getaddrs_old))
+ if (len < sizeof(struct sctp_getaddrs_old))
return -EINVAL;
- if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old)))
+ len = sizeof(struct sctp_getaddrs_old);
+ if (copy_from_user(&getaddrs, optval, len))
return -EFAULT;
if (getaddrs.addr_num <= 0) return -EINVAL;
@@ -4242,7 +4282,7 @@ copy_getaddrs:
/* copy the leading structure back to user */
getaddrs.addr_num = cnt;
- if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old)))
+ if (copy_to_user(optval, &getaddrs, len))
err = -EFAULT;
error:
@@ -4270,7 +4310,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
void *addrs;
void *buf;
- if (len <= sizeof(struct sctp_getaddrs))
+ if (len < sizeof(struct sctp_getaddrs))
return -EINVAL;
if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs)))
@@ -4294,8 +4334,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
}
to = optval + offsetof(struct sctp_getaddrs,addrs);
- space_left = len - sizeof(struct sctp_getaddrs) -
- offsetof(struct sctp_getaddrs,addrs);
+ space_left = len - offsetof(struct sctp_getaddrs,addrs);
+
addrs = kmalloc(space_left, GFP_KERNEL);
if (!addrs)
return -ENOMEM;
@@ -4343,11 +4383,12 @@ copy_getaddrs:
err = -EFAULT;
goto error;
}
- if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num))
- return -EFAULT;
+ if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num)) {
+ err = -EFAULT;
+ goto error;
+ }
if (put_user(bytes_copied, optlen))
- return -EFAULT;
-
+ err = -EFAULT;
error:
kfree(addrs);
return err;
@@ -4366,10 +4407,12 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
struct sctp_association *asoc;
struct sctp_sock *sp = sctp_sk(sk);
- if (len != sizeof(struct sctp_prim))
+ if (len < sizeof(struct sctp_prim))
return -EINVAL;
- if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))
+ len = sizeof(struct sctp_prim);
+
+ if (copy_from_user(&prim, optval, len))
return -EFAULT;
asoc = sctp_id2assoc(sk, prim.ssp_assoc_id);
@@ -4385,7 +4428,9 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
(union sctp_addr *)&prim.ssp_addr);
- if (copy_to_user(optval, &prim, sizeof(struct sctp_prim)))
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &prim, len))
return -EFAULT;
return 0;
@@ -4402,10 +4447,15 @@ static int sctp_getsockopt_adaptation_layer(struct sock *sk, int len,
{
struct sctp_setadaptation adaptation;
- if (len != sizeof(struct sctp_setadaptation))
+ if (len < sizeof(struct sctp_setadaptation))
return -EINVAL;
+ len = sizeof(struct sctp_setadaptation);
+
adaptation.ssb_adaptation_ind = sctp_sk(sk)->adaptation_ind;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
if (copy_to_user(optval, &adaptation, len))
return -EFAULT;
@@ -4439,9 +4489,12 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
struct sctp_association *asoc;
struct sctp_sock *sp = sctp_sk(sk);
- if (len != sizeof(struct sctp_sndrcvinfo))
+ if (len < sizeof(struct sctp_sndrcvinfo))
return -EINVAL;
- if (copy_from_user(&info, optval, sizeof(struct sctp_sndrcvinfo)))
+
+ len = sizeof(struct sctp_sndrcvinfo);
+
+ if (copy_from_user(&info, optval, len))
return -EFAULT;
asoc = sctp_id2assoc(sk, info.sinfo_assoc_id);
@@ -4462,7 +4515,9 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
info.sinfo_timetolive = sp->default_timetolive;
}
- if (copy_to_user(optval, &info, sizeof(struct sctp_sndrcvinfo)))
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &info, len))
return -EFAULT;
return 0;
@@ -4513,10 +4568,12 @@ static int sctp_getsockopt_rtoinfo(struct sock *sk, int len,
struct sctp_rtoinfo rtoinfo;
struct sctp_association *asoc;
- if (len != sizeof (struct sctp_rtoinfo))
+ if (len < sizeof (struct sctp_rtoinfo))
return -EINVAL;
- if (copy_from_user(&rtoinfo, optval, sizeof (struct sctp_rtoinfo)))
+ len = sizeof(struct sctp_rtoinfo);
+
+ if (copy_from_user(&rtoinfo, optval, len))
return -EFAULT;
asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
@@ -4568,11 +4625,12 @@ static int sctp_getsockopt_associnfo(struct sock *sk, int len,
struct list_head *pos;
int cnt = 0;
- if (len != sizeof (struct sctp_assocparams))
+ if (len < sizeof (struct sctp_assocparams))
return -EINVAL;
- if (copy_from_user(&assocparams, optval,
- sizeof (struct sctp_assocparams)))
+ len = sizeof(struct sctp_assocparams);
+
+ if (copy_from_user(&assocparams, optval, len))
return -EFAULT;
asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
@@ -4658,9 +4716,11 @@ static int sctp_getsockopt_context(struct sock *sk, int len,
struct sctp_sock *sp;
struct sctp_association *asoc;
- if (len != sizeof(struct sctp_assoc_value))
+ if (len < sizeof(struct sctp_assoc_value))
return -EINVAL;
+ len = sizeof(struct sctp_assoc_value);
+
if (copy_from_user(&params, optval, len))
return -EFAULT;
@@ -6071,8 +6131,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
* queued to the backlog. This prevents a potential race between
* backlog processing on the old socket and new-packet processing
* on the new socket.
+ *
+ * The caller has just allocated newsk so we can guarantee that other
+ * paths won't try to lock it and then oldsk.
*/
- sctp_lock_sock(newsk);
+ lock_sock_nested(newsk, SINGLE_DEPTH_NESTING);
sctp_assoc_migrate(assoc, newsk);
/* If the association on the newsk is already closed before accept()
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 961df275d5b..5f467c914f8 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -241,6 +241,45 @@ void sctp_transport_pmtu(struct sctp_transport *transport)
transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
}
+/* this is a complete rip-off from __sk_dst_check
+ * the cookie is always 0 since this is how it's used in the
+ * pmtu code
+ */
+static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
+{
+ struct dst_entry *dst = t->dst;
+
+ if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) {
+ dst_release(t->dst);
+ t->dst = NULL;
+ return NULL;
+ }
+
+ return dst;
+}
+
+void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
+{
+ struct dst_entry *dst;
+
+ if (unlikely(pmtu < SCTP_DEFAULT_MINSEGMENT)) {
+ printk(KERN_WARNING "%s: Reported pmtu %d too low, "
+ "using default minimum of %d\n",
+ __FUNCTION__, pmtu,
+ SCTP_DEFAULT_MINSEGMENT);
+ /* Use default minimum segment size and disable
+ * pmtu discovery on this transport.
+ */
+ t->pathmtu = SCTP_DEFAULT_MINSEGMENT;
+ } else {
+ t->pathmtu = pmtu;
+ }
+
+ dst = sctp_transport_dst_check(t);
+ if (dst)
+ dst->ops->update_pmtu(dst, pmtu);
+}
+
/* Caches the dst entry and source address for a transport's destination
* address.
*/
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 9527f2bb174..aa55d0a03e6 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -13,17 +13,22 @@
#include <linux/errno.h>
#include <linux/sunrpc/clnt.h>
#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
-static struct rpc_authops * auth_flavors[RPC_AUTH_MAXFLAVOR] = {
+static DEFINE_SPINLOCK(rpc_authflavor_lock);
+static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
&authnull_ops, /* AUTH_NULL */
&authunix_ops, /* AUTH_UNIX */
NULL, /* others can be loadable modules */
};
+static LIST_HEAD(cred_unused);
+static unsigned long number_cred_unused;
+
static u32
pseudoflavor_to_flavor(u32 flavor) {
if (flavor >= RPC_AUTH_MAXFLAVOR)
@@ -32,55 +37,67 @@ pseudoflavor_to_flavor(u32 flavor) {
}
int
-rpcauth_register(struct rpc_authops *ops)
+rpcauth_register(const struct rpc_authops *ops)
{
rpc_authflavor_t flavor;
+ int ret = -EPERM;
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
return -EINVAL;
- if (auth_flavors[flavor] != NULL)
- return -EPERM; /* what else? */
- auth_flavors[flavor] = ops;
- return 0;
+ spin_lock(&rpc_authflavor_lock);
+ if (auth_flavors[flavor] == NULL) {
+ auth_flavors[flavor] = ops;
+ ret = 0;
+ }
+ spin_unlock(&rpc_authflavor_lock);
+ return ret;
}
int
-rpcauth_unregister(struct rpc_authops *ops)
+rpcauth_unregister(const struct rpc_authops *ops)
{
rpc_authflavor_t flavor;
+ int ret = -EPERM;
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
return -EINVAL;
- if (auth_flavors[flavor] != ops)
- return -EPERM; /* what else? */
- auth_flavors[flavor] = NULL;
- return 0;
+ spin_lock(&rpc_authflavor_lock);
+ if (auth_flavors[flavor] == ops) {
+ auth_flavors[flavor] = NULL;
+ ret = 0;
+ }
+ spin_unlock(&rpc_authflavor_lock);
+ return ret;
}
struct rpc_auth *
rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
{
struct rpc_auth *auth;
- struct rpc_authops *ops;
+ const struct rpc_authops *ops;
u32 flavor = pseudoflavor_to_flavor(pseudoflavor);
auth = ERR_PTR(-EINVAL);
if (flavor >= RPC_AUTH_MAXFLAVOR)
goto out;
- /* FIXME - auth_flavors[] really needs an rw lock,
- * and module refcounting. */
#ifdef CONFIG_KMOD
if ((ops = auth_flavors[flavor]) == NULL)
request_module("rpc-auth-%u", flavor);
#endif
- if ((ops = auth_flavors[flavor]) == NULL)
+ spin_lock(&rpc_authflavor_lock);
+ ops = auth_flavors[flavor];
+ if (ops == NULL || !try_module_get(ops->owner)) {
+ spin_unlock(&rpc_authflavor_lock);
goto out;
+ }
+ spin_unlock(&rpc_authflavor_lock);
auth = ops->create(clnt, pseudoflavor);
+ module_put(ops->owner);
if (IS_ERR(auth))
return auth;
if (clnt->cl_auth)
- rpcauth_destroy(clnt->cl_auth);
+ rpcauth_release(clnt->cl_auth);
clnt->cl_auth = auth;
out:
@@ -88,7 +105,7 @@ out:
}
void
-rpcauth_destroy(struct rpc_auth *auth)
+rpcauth_release(struct rpc_auth *auth)
{
if (!atomic_dec_and_test(&auth->au_count))
return;
@@ -97,11 +114,31 @@ rpcauth_destroy(struct rpc_auth *auth)
static DEFINE_SPINLOCK(rpc_credcache_lock);
+static void
+rpcauth_unhash_cred_locked(struct rpc_cred *cred)
+{
+ hlist_del_rcu(&cred->cr_hash);
+ smp_mb__before_clear_bit();
+ clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
+}
+
+static void
+rpcauth_unhash_cred(struct rpc_cred *cred)
+{
+ spinlock_t *cache_lock;
+
+ cache_lock = &cred->cr_auth->au_credcache->lock;
+ spin_lock(cache_lock);
+ if (atomic_read(&cred->cr_count) == 0)
+ rpcauth_unhash_cred_locked(cred);
+ spin_unlock(cache_lock);
+}
+
/*
* Initialize RPC credential cache
*/
int
-rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
+rpcauth_init_credcache(struct rpc_auth *auth)
{
struct rpc_cred_cache *new;
int i;
@@ -111,8 +148,7 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
return -ENOMEM;
for (i = 0; i < RPC_CREDCACHE_NR; i++)
INIT_HLIST_HEAD(&new->hashtable[i]);
- new->expire = expire;
- new->nextgc = jiffies + (expire >> 1);
+ spin_lock_init(&new->lock);
auth->au_credcache = new;
return 0;
}
@@ -121,13 +157,13 @@ rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
* Destroy a list of credentials
*/
static inline
-void rpcauth_destroy_credlist(struct hlist_head *head)
+void rpcauth_destroy_credlist(struct list_head *head)
{
struct rpc_cred *cred;
- while (!hlist_empty(head)) {
- cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
- hlist_del_init(&cred->cr_hash);
+ while (!list_empty(head)) {
+ cred = list_entry(head->next, struct rpc_cred, cr_lru);
+ list_del_init(&cred->cr_lru);
put_rpccred(cred);
}
}
@@ -137,58 +173,95 @@ void rpcauth_destroy_credlist(struct hlist_head *head)
* that are not referenced.
*/
void
-rpcauth_free_credcache(struct rpc_auth *auth)
+rpcauth_clear_credcache(struct rpc_cred_cache *cache)
{
- struct rpc_cred_cache *cache = auth->au_credcache;
- HLIST_HEAD(free);
- struct hlist_node *pos, *next;
+ LIST_HEAD(free);
+ struct hlist_head *head;
struct rpc_cred *cred;
int i;
spin_lock(&rpc_credcache_lock);
+ spin_lock(&cache->lock);
for (i = 0; i < RPC_CREDCACHE_NR; i++) {
- hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
- cred = hlist_entry(pos, struct rpc_cred, cr_hash);
- __hlist_del(&cred->cr_hash);
- hlist_add_head(&cred->cr_hash, &free);
+ head = &cache->hashtable[i];
+ while (!hlist_empty(head)) {
+ cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
+ get_rpccred(cred);
+ if (!list_empty(&cred->cr_lru)) {
+ list_del(&cred->cr_lru);
+ number_cred_unused--;
+ }
+ list_add_tail(&cred->cr_lru, &free);
+ rpcauth_unhash_cred_locked(cred);
}
}
+ spin_unlock(&cache->lock);
spin_unlock(&rpc_credcache_lock);
rpcauth_destroy_credlist(&free);
}
-static void
-rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
+/*
+ * Destroy the RPC credential cache
+ */
+void
+rpcauth_destroy_credcache(struct rpc_auth *auth)
{
- if (atomic_read(&cred->cr_count) != 1)
- return;
- if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
- if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
- __hlist_del(&cred->cr_hash);
- hlist_add_head(&cred->cr_hash, free);
+ struct rpc_cred_cache *cache = auth->au_credcache;
+
+ if (cache) {
+ auth->au_credcache = NULL;
+ rpcauth_clear_credcache(cache);
+ kfree(cache);
}
}
/*
* Remove stale credentials. Avoid sleeping inside the loop.
*/
-static void
-rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free)
+static int
+rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
{
- struct rpc_cred_cache *cache = auth->au_credcache;
- struct hlist_node *pos, *next;
- struct rpc_cred *cred;
- int i;
+ spinlock_t *cache_lock;
+ struct rpc_cred *cred;
- dprintk("RPC: gc'ing RPC credentials for auth %p\n", auth);
- for (i = 0; i < RPC_CREDCACHE_NR; i++) {
- hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
- cred = hlist_entry(pos, struct rpc_cred, cr_hash);
- rpcauth_prune_expired(auth, cred, free);
+ while (!list_empty(&cred_unused)) {
+ cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
+ list_del_init(&cred->cr_lru);
+ number_cred_unused--;
+ if (atomic_read(&cred->cr_count) != 0)
+ continue;
+ cache_lock = &cred->cr_auth->au_credcache->lock;
+ spin_lock(cache_lock);
+ if (atomic_read(&cred->cr_count) == 0) {
+ get_rpccred(cred);
+ list_add_tail(&cred->cr_lru, free);
+ rpcauth_unhash_cred_locked(cred);
+ nr_to_scan--;
}
+ spin_unlock(cache_lock);
+ if (nr_to_scan == 0)
+ break;
}
- cache->nextgc = jiffies + cache->expire;
+ return nr_to_scan;
+}
+
+/*
+ * Run memory cache shrinker.
+ */
+static int
+rpcauth_cache_shrinker(int nr_to_scan, gfp_t gfp_mask)
+{
+ LIST_HEAD(free);
+ int res;
+
+ if (list_empty(&cred_unused))
+ return 0;
+ spin_lock(&rpc_credcache_lock);
+ nr_to_scan = rpcauth_prune_expired(&free, nr_to_scan);
+ res = (number_cred_unused / 100) * sysctl_vfs_cache_pressure;
+ spin_unlock(&rpc_credcache_lock);
+ rpcauth_destroy_credlist(&free);
+ return res;
}
/*
@@ -198,53 +271,56 @@ struct rpc_cred *
rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
int flags)
{
+ LIST_HEAD(free);
struct rpc_cred_cache *cache = auth->au_credcache;
- HLIST_HEAD(free);
- struct hlist_node *pos, *next;
- struct rpc_cred *new = NULL,
- *cred = NULL;
+ struct hlist_node *pos;
+ struct rpc_cred *cred = NULL,
+ *entry, *new;
int nr = 0;
if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
nr = acred->uid & RPC_CREDCACHE_MASK;
-retry:
- spin_lock(&rpc_credcache_lock);
- if (time_before(cache->nextgc, jiffies))
- rpcauth_gc_credcache(auth, &free);
- hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
- struct rpc_cred *entry;
- entry = hlist_entry(pos, struct rpc_cred, cr_hash);
- if (entry->cr_ops->crmatch(acred, entry, flags)) {
- hlist_del(&entry->cr_hash);
- cred = entry;
- break;
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
+ if (!entry->cr_ops->crmatch(acred, entry, flags))
+ continue;
+ spin_lock(&cache->lock);
+ if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
+ spin_unlock(&cache->lock);
+ continue;
}
- rpcauth_prune_expired(auth, entry, &free);
+ cred = get_rpccred(entry);
+ spin_unlock(&cache->lock);
+ break;
}
- if (new) {
- if (cred)
- hlist_add_head(&new->cr_hash, &free);
- else
- cred = new;
- }
- if (cred) {
- hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
- get_rpccred(cred);
- }
- spin_unlock(&rpc_credcache_lock);
+ rcu_read_unlock();
- rpcauth_destroy_credlist(&free);
+ if (cred != NULL)
+ goto found;
- if (!cred) {
- new = auth->au_ops->crcreate(auth, acred, flags);
- if (!IS_ERR(new)) {
-#ifdef RPC_DEBUG
- new->cr_magic = RPCAUTH_CRED_MAGIC;
-#endif
- goto retry;
- } else
- cred = new;
- } else if ((cred->cr_flags & RPCAUTH_CRED_NEW)
+ new = auth->au_ops->crcreate(auth, acred, flags);
+ if (IS_ERR(new)) {
+ cred = new;
+ goto out;
+ }
+
+ spin_lock(&cache->lock);
+ hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
+ if (!entry->cr_ops->crmatch(acred, entry, flags))
+ continue;
+ cred = get_rpccred(entry);
+ break;
+ }
+ if (cred == NULL) {
+ cred = new;
+ set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
+ hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
+ } else
+ list_add_tail(&new->cr_lru, &free);
+ spin_unlock(&cache->lock);
+found:
+ if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
&& cred->cr_ops->cr_init != NULL
&& !(flags & RPCAUTH_LOOKUP_NEW)) {
int res = cred->cr_ops->cr_init(auth, cred);
@@ -253,8 +329,9 @@ retry:
cred = ERR_PTR(res);
}
}
-
- return (struct rpc_cred *) cred;
+ rpcauth_destroy_credlist(&free);
+out:
+ return cred;
}
struct rpc_cred *
@@ -275,10 +352,27 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags)
return ret;
}
+void
+rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
+ struct rpc_auth *auth, const struct rpc_credops *ops)
+{
+ INIT_HLIST_NODE(&cred->cr_hash);
+ INIT_LIST_HEAD(&cred->cr_lru);
+ atomic_set(&cred->cr_count, 1);
+ cred->cr_auth = auth;
+ cred->cr_ops = ops;
+ cred->cr_expire = jiffies;
+#ifdef RPC_DEBUG
+ cred->cr_magic = RPCAUTH_CRED_MAGIC;
+#endif
+ cred->cr_uid = acred->uid;
+}
+EXPORT_SYMBOL(rpcauth_init_cred);
+
struct rpc_cred *
rpcauth_bindcred(struct rpc_task *task)
{
- struct rpc_auth *auth = task->tk_auth;
+ struct rpc_auth *auth = task->tk_client->cl_auth;
struct auth_cred acred = {
.uid = current->fsuid,
.gid = current->fsgid,
@@ -288,7 +382,7 @@ rpcauth_bindcred(struct rpc_task *task)
int flags = 0;
dprintk("RPC: %5u looking up %s cred\n",
- task->tk_pid, task->tk_auth->au_ops->au_name);
+ task->tk_pid, task->tk_client->cl_auth->au_ops->au_name);
get_group_info(acred.group_info);
if (task->tk_flags & RPC_TASK_ROOTCREDS)
flags |= RPCAUTH_LOOKUP_ROOTCREDS;
@@ -304,19 +398,42 @@ rpcauth_bindcred(struct rpc_task *task)
void
rpcauth_holdcred(struct rpc_task *task)
{
- dprintk("RPC: %5u holding %s cred %p\n",
- task->tk_pid, task->tk_auth->au_ops->au_name,
- task->tk_msg.rpc_cred);
- if (task->tk_msg.rpc_cred)
- get_rpccred(task->tk_msg.rpc_cred);
+ struct rpc_cred *cred = task->tk_msg.rpc_cred;
+ if (cred != NULL) {
+ get_rpccred(cred);
+ dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid,
+ cred->cr_auth->au_ops->au_name, cred);
+ }
}
void
put_rpccred(struct rpc_cred *cred)
{
- cred->cr_expire = jiffies;
+ /* Fast path for unhashed credentials */
+ if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
+ goto need_lock;
+
if (!atomic_dec_and_test(&cred->cr_count))
return;
+ goto out_destroy;
+need_lock:
+ if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
+ return;
+ if (!list_empty(&cred->cr_lru)) {
+ number_cred_unused--;
+ list_del_init(&cred->cr_lru);
+ }
+ if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
+ rpcauth_unhash_cred(cred);
+ else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
+ cred->cr_expire = jiffies;
+ list_add_tail(&cred->cr_lru, &cred_unused);
+ number_cred_unused++;
+ spin_unlock(&rpc_credcache_lock);
+ return;
+ }
+ spin_unlock(&rpc_credcache_lock);
+out_destroy:
cred->cr_ops->crdestroy(cred);
}
@@ -326,7 +443,7 @@ rpcauth_unbindcred(struct rpc_task *task)
struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %5u releasing %s cred %p\n",
- task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+ task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
put_rpccred(cred);
task->tk_msg.rpc_cred = NULL;
@@ -338,7 +455,7 @@ rpcauth_marshcred(struct rpc_task *task, __be32 *p)
struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %5u marshaling %s cred %p\n",
- task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+ task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
return cred->cr_ops->crmarshal(task, p);
}
@@ -349,7 +466,7 @@ rpcauth_checkverf(struct rpc_task *task, __be32 *p)
struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %5u validating %s cred %p\n",
- task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+ task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
return cred->cr_ops->crvalidate(task, p);
}
@@ -359,13 +476,17 @@ rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
__be32 *data, void *obj)
{
struct rpc_cred *cred = task->tk_msg.rpc_cred;
+ int ret;
dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
task->tk_pid, cred->cr_ops->cr_name, cred);
if (cred->cr_ops->crwrap_req)
return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
/* By default, we encode the arguments normally. */
- return encode(rqstp, data, obj);
+ lock_kernel();
+ ret = encode(rqstp, data, obj);
+ unlock_kernel();
+ return ret;
}
int
@@ -373,6 +494,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
__be32 *data, void *obj)
{
struct rpc_cred *cred = task->tk_msg.rpc_cred;
+ int ret;
dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
task->tk_pid, cred->cr_ops->cr_name, cred);
@@ -380,7 +502,10 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
data, obj);
/* By default, we decode the arguments normally. */
- return decode(rqstp, data, obj);
+ lock_kernel();
+ ret = decode(rqstp, data, obj);
+ unlock_kernel();
+ return ret;
}
int
@@ -390,7 +515,7 @@ rpcauth_refreshcred(struct rpc_task *task)
int err;
dprintk("RPC: %5u refreshing %s cred %p\n",
- task->tk_pid, task->tk_auth->au_ops->au_name, cred);
+ task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
err = cred->cr_ops->crrefresh(task);
if (err < 0)
@@ -401,17 +526,34 @@ rpcauth_refreshcred(struct rpc_task *task)
void
rpcauth_invalcred(struct rpc_task *task)
{
+ struct rpc_cred *cred = task->tk_msg.rpc_cred;
+
dprintk("RPC: %5u invalidating %s cred %p\n",
- task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
- spin_lock(&rpc_credcache_lock);
- if (task->tk_msg.rpc_cred)
- task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
- spin_unlock(&rpc_credcache_lock);
+ task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+ if (cred)
+ clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
}
int
rpcauth_uptodatecred(struct rpc_task *task)
{
- return !(task->tk_msg.rpc_cred) ||
- (task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
+ struct rpc_cred *cred = task->tk_msg.rpc_cred;
+
+ return cred == NULL ||
+ test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
+}
+
+
+static struct shrinker *rpc_cred_shrinker;
+
+void __init rpcauth_init_module(void)
+{
+ rpc_init_authunix();
+ rpc_cred_shrinker = set_shrinker(DEFAULT_SEEKS, rpcauth_cache_shrinker);
+}
+
+void __exit rpcauth_remove_module(void)
+{
+ if (rpc_cred_shrinker != NULL)
+ remove_shrinker(rpc_cred_shrinker);
}
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 4e4ccc5b6fe..baf4096d52d 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -54,9 +54,10 @@
#include <linux/sunrpc/gss_api.h>
#include <asm/uaccess.h>
-static struct rpc_authops authgss_ops;
+static const struct rpc_authops authgss_ops;
-static struct rpc_credops gss_credops;
+static const struct rpc_credops gss_credops;
+static const struct rpc_credops gss_nullops;
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
@@ -64,7 +65,6 @@ static struct rpc_credops gss_credops;
#define NFS_NGROUPS 16
-#define GSS_CRED_EXPIRE (60 * HZ) /* XXX: reasonable? */
#define GSS_CRED_SLACK 1024 /* XXX: unused */
/* length of a krb5 verifier (48), plus data added before arguments when
* using integrity (two 4-byte integers): */
@@ -79,19 +79,16 @@ static struct rpc_credops gss_credops;
/* dump the buffer in `emacs-hexl' style */
#define isprint(c) ((c > 0x1f) && (c < 0x7f))
-static DEFINE_RWLOCK(gss_ctx_lock);
-
struct gss_auth {
+ struct kref kref;
struct rpc_auth rpc_auth;
struct gss_api_mech *mech;
enum rpc_gss_svc service;
- struct list_head upcalls;
struct rpc_clnt *client;
struct dentry *dentry;
- spinlock_t lock;
};
-static void gss_destroy_ctx(struct gss_cl_ctx *);
+static void gss_free_ctx(struct gss_cl_ctx *);
static struct rpc_pipe_ops gss_upcall_ops;
static inline struct gss_cl_ctx *
@@ -105,20 +102,24 @@ static inline void
gss_put_ctx(struct gss_cl_ctx *ctx)
{
if (atomic_dec_and_test(&ctx->count))
- gss_destroy_ctx(ctx);
+ gss_free_ctx(ctx);
}
+/* gss_cred_set_ctx:
+ * called by gss_upcall_callback and gss_create_upcall in order
+ * to set the gss context. The actual exchange of an old context
+ * and a new one is protected by the inode->i_lock.
+ */
static void
gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
{
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
struct gss_cl_ctx *old;
- write_lock(&gss_ctx_lock);
+
old = gss_cred->gc_ctx;
- gss_cred->gc_ctx = ctx;
- cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
- cred->cr_flags &= ~RPCAUTH_CRED_NEW;
- write_unlock(&gss_ctx_lock);
+ rcu_assign_pointer(gss_cred->gc_ctx, ctx);
+ set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+ clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags);
if (old)
gss_put_ctx(old);
}
@@ -129,10 +130,10 @@ gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
int res = 0;
- read_lock(&gss_ctx_lock);
- if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx)
+ rcu_read_lock();
+ if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) && gss_cred->gc_ctx)
res = 1;
- read_unlock(&gss_ctx_lock);
+ rcu_read_unlock();
return res;
}
@@ -171,10 +172,10 @@ gss_cred_get_ctx(struct rpc_cred *cred)
struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
struct gss_cl_ctx *ctx = NULL;
- read_lock(&gss_ctx_lock);
+ rcu_read_lock();
if (gss_cred->gc_ctx)
ctx = gss_get_ctx(gss_cred->gc_ctx);
- read_unlock(&gss_ctx_lock);
+ rcu_read_unlock();
return ctx;
}
@@ -269,10 +270,10 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
}
static struct gss_upcall_msg *
-__gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
+__gss_find_upcall(struct rpc_inode *rpci, uid_t uid)
{
struct gss_upcall_msg *pos;
- list_for_each_entry(pos, &gss_auth->upcalls, list) {
+ list_for_each_entry(pos, &rpci->in_downcall, list) {
if (pos->uid != uid)
continue;
atomic_inc(&pos->count);
@@ -290,24 +291,24 @@ __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
static inline struct gss_upcall_msg *
gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
{
+ struct inode *inode = gss_auth->dentry->d_inode;
+ struct rpc_inode *rpci = RPC_I(inode);
struct gss_upcall_msg *old;
- spin_lock(&gss_auth->lock);
- old = __gss_find_upcall(gss_auth, gss_msg->uid);
+ spin_lock(&inode->i_lock);
+ old = __gss_find_upcall(rpci, gss_msg->uid);
if (old == NULL) {
atomic_inc(&gss_msg->count);
- list_add(&gss_msg->list, &gss_auth->upcalls);
+ list_add(&gss_msg->list, &rpci->in_downcall);
} else
gss_msg = old;
- spin_unlock(&gss_auth->lock);
+ spin_unlock(&inode->i_lock);
return gss_msg;
}
static void
__gss_unhash_msg(struct gss_upcall_msg *gss_msg)
{
- if (list_empty(&gss_msg->list))
- return;
list_del_init(&gss_msg->list);
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
wake_up_all(&gss_msg->waitqueue);
@@ -318,10 +319,14 @@ static void
gss_unhash_msg(struct gss_upcall_msg *gss_msg)
{
struct gss_auth *gss_auth = gss_msg->auth;
+ struct inode *inode = gss_auth->dentry->d_inode;
- spin_lock(&gss_auth->lock);
- __gss_unhash_msg(gss_msg);
- spin_unlock(&gss_auth->lock);
+ if (list_empty(&gss_msg->list))
+ return;
+ spin_lock(&inode->i_lock);
+ if (!list_empty(&gss_msg->list))
+ __gss_unhash_msg(gss_msg);
+ spin_unlock(&inode->i_lock);
}
static void
@@ -330,16 +335,16 @@ gss_upcall_callback(struct rpc_task *task)
struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
struct gss_cred, gc_base);
struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
+ struct inode *inode = gss_msg->auth->dentry->d_inode;
- BUG_ON(gss_msg == NULL);
+ spin_lock(&inode->i_lock);
if (gss_msg->ctx)
gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
else
task->tk_status = gss_msg->msg.errno;
- spin_lock(&gss_msg->auth->lock);
gss_cred->gc_upcall = NULL;
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
- spin_unlock(&gss_msg->auth->lock);
+ spin_unlock(&inode->i_lock);
gss_release_msg(gss_msg);
}
@@ -386,11 +391,12 @@ static inline int
gss_refresh_upcall(struct rpc_task *task)
{
struct rpc_cred *cred = task->tk_msg.rpc_cred;
- struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
+ struct gss_auth *gss_auth = container_of(cred->cr_auth,
struct gss_auth, rpc_auth);
struct gss_cred *gss_cred = container_of(cred,
struct gss_cred, gc_base);
struct gss_upcall_msg *gss_msg;
+ struct inode *inode = gss_auth->dentry->d_inode;
int err = 0;
dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid,
@@ -400,7 +406,7 @@ gss_refresh_upcall(struct rpc_task *task)
err = PTR_ERR(gss_msg);
goto out;
}
- spin_lock(&gss_auth->lock);
+ spin_lock(&inode->i_lock);
if (gss_cred->gc_upcall != NULL)
rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
@@ -411,7 +417,7 @@ gss_refresh_upcall(struct rpc_task *task)
rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
} else
err = gss_msg->msg.errno;
- spin_unlock(&gss_auth->lock);
+ spin_unlock(&inode->i_lock);
gss_release_msg(gss_msg);
out:
dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n",
@@ -422,6 +428,7 @@ out:
static inline int
gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
{
+ struct inode *inode = gss_auth->dentry->d_inode;
struct rpc_cred *cred = &gss_cred->gc_base;
struct gss_upcall_msg *gss_msg;
DEFINE_WAIT(wait);
@@ -435,12 +442,11 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
}
for (;;) {
prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
- spin_lock(&gss_auth->lock);
+ spin_lock(&inode->i_lock);
if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
- spin_unlock(&gss_auth->lock);
break;
}
- spin_unlock(&gss_auth->lock);
+ spin_unlock(&inode->i_lock);
if (signalled()) {
err = -ERESTARTSYS;
goto out_intr;
@@ -451,6 +457,7 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
else
err = gss_msg->msg.errno;
+ spin_unlock(&inode->i_lock);
out_intr:
finish_wait(&gss_msg->waitqueue, &wait);
gss_release_msg(gss_msg);
@@ -489,12 +496,11 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
const void *p, *end;
void *buf;
struct rpc_clnt *clnt;
- struct gss_auth *gss_auth;
- struct rpc_cred *cred;
struct gss_upcall_msg *gss_msg;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct gss_cl_ctx *ctx;
uid_t uid;
- int err = -EFBIG;
+ ssize_t err = -EFBIG;
if (mlen > MSG_BUF_MAXSIZE)
goto out;
@@ -503,7 +509,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
if (!buf)
goto out;
- clnt = RPC_I(filp->f_path.dentry->d_inode)->private;
+ clnt = RPC_I(inode)->private;
err = -EFAULT;
if (copy_from_user(buf, src, mlen))
goto err;
@@ -519,43 +525,38 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
ctx = gss_alloc_context();
if (ctx == NULL)
goto err;
- err = 0;
- gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
- p = gss_fill_context(p, end, ctx, gss_auth->mech);
+
+ err = -ENOENT;
+ /* Find a matching upcall */
+ spin_lock(&inode->i_lock);
+ gss_msg = __gss_find_upcall(RPC_I(inode), uid);
+ if (gss_msg == NULL) {
+ spin_unlock(&inode->i_lock);
+ goto err_put_ctx;
+ }
+ list_del_init(&gss_msg->list);
+ spin_unlock(&inode->i_lock);
+
+ p = gss_fill_context(p, end, ctx, gss_msg->auth->mech);
if (IS_ERR(p)) {
err = PTR_ERR(p);
- if (err != -EACCES)
- goto err_put_ctx;
- }
- spin_lock(&gss_auth->lock);
- gss_msg = __gss_find_upcall(gss_auth, uid);
- if (gss_msg) {
- if (err == 0 && gss_msg->ctx == NULL)
- gss_msg->ctx = gss_get_ctx(ctx);
- gss_msg->msg.errno = err;
- __gss_unhash_msg(gss_msg);
- spin_unlock(&gss_auth->lock);
- gss_release_msg(gss_msg);
- } else {
- struct auth_cred acred = { .uid = uid };
- spin_unlock(&gss_auth->lock);
- cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
- if (IS_ERR(cred)) {
- err = PTR_ERR(cred);
- goto err_put_ctx;
- }
- gss_cred_set_ctx(cred, gss_get_ctx(ctx));
+ gss_msg->msg.errno = (err == -EACCES) ? -EACCES : -EAGAIN;
+ goto err_release_msg;
}
- gss_put_ctx(ctx);
- kfree(buf);
- dprintk("RPC: gss_pipe_downcall returning length %Zu\n", mlen);
- return mlen;
+ gss_msg->ctx = gss_get_ctx(ctx);
+ err = mlen;
+
+err_release_msg:
+ spin_lock(&inode->i_lock);
+ __gss_unhash_msg(gss_msg);
+ spin_unlock(&inode->i_lock);
+ gss_release_msg(gss_msg);
err_put_ctx:
gss_put_ctx(ctx);
err:
kfree(buf);
out:
- dprintk("RPC: gss_pipe_downcall returning %d\n", err);
+ dprintk("RPC: gss_pipe_downcall returning %Zd\n", err);
return err;
}
@@ -563,27 +564,21 @@ static void
gss_pipe_release(struct inode *inode)
{
struct rpc_inode *rpci = RPC_I(inode);
- struct rpc_clnt *clnt;
- struct rpc_auth *auth;
- struct gss_auth *gss_auth;
+ struct gss_upcall_msg *gss_msg;
- clnt = rpci->private;
- auth = clnt->cl_auth;
- gss_auth = container_of(auth, struct gss_auth, rpc_auth);
- spin_lock(&gss_auth->lock);
- while (!list_empty(&gss_auth->upcalls)) {
- struct gss_upcall_msg *gss_msg;
+ spin_lock(&inode->i_lock);
+ while (!list_empty(&rpci->in_downcall)) {
- gss_msg = list_entry(gss_auth->upcalls.next,
+ gss_msg = list_entry(rpci->in_downcall.next,
struct gss_upcall_msg, list);
gss_msg->msg.errno = -EPIPE;
atomic_inc(&gss_msg->count);
__gss_unhash_msg(gss_msg);
- spin_unlock(&gss_auth->lock);
+ spin_unlock(&inode->i_lock);
gss_release_msg(gss_msg);
- spin_lock(&gss_auth->lock);
+ spin_lock(&inode->i_lock);
}
- spin_unlock(&gss_auth->lock);
+ spin_unlock(&inode->i_lock);
}
static void
@@ -637,18 +632,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
if (gss_auth->service == 0)
goto err_put_mech;
- INIT_LIST_HEAD(&gss_auth->upcalls);
- spin_lock_init(&gss_auth->lock);
auth = &gss_auth->rpc_auth;
auth->au_cslack = GSS_CRED_SLACK >> 2;
auth->au_rslack = GSS_VERF_SLACK >> 2;
auth->au_ops = &authgss_ops;
auth->au_flavor = flavor;
atomic_set(&auth->au_count, 1);
-
- err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
- if (err)
- goto err_put_mech;
+ kref_init(&gss_auth->kref);
gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
@@ -657,7 +647,13 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
goto err_put_mech;
}
+ err = rpcauth_init_credcache(auth);
+ if (err)
+ goto err_unlink_pipe;
+
return auth;
+err_unlink_pipe:
+ rpc_unlink(gss_auth->dentry);
err_put_mech:
gss_mech_put(gss_auth->mech);
err_free:
@@ -668,6 +664,25 @@ out_dec:
}
static void
+gss_free(struct gss_auth *gss_auth)
+{
+ rpc_unlink(gss_auth->dentry);
+ gss_auth->dentry = NULL;
+ gss_mech_put(gss_auth->mech);
+
+ kfree(gss_auth);
+ module_put(THIS_MODULE);
+}
+
+static void
+gss_free_callback(struct kref *kref)
+{
+ struct gss_auth *gss_auth = container_of(kref, struct gss_auth, kref);
+
+ gss_free(gss_auth);
+}
+
+static void
gss_destroy(struct rpc_auth *auth)
{
struct gss_auth *gss_auth;
@@ -675,23 +690,51 @@ gss_destroy(struct rpc_auth *auth)
dprintk("RPC: destroying GSS authenticator %p flavor %d\n",
auth, auth->au_flavor);
+ rpcauth_destroy_credcache(auth);
+
gss_auth = container_of(auth, struct gss_auth, rpc_auth);
- rpc_unlink(gss_auth->dentry);
- gss_auth->dentry = NULL;
- gss_mech_put(gss_auth->mech);
+ kref_put(&gss_auth->kref, gss_free_callback);
+}
- rpcauth_free_credcache(auth);
- kfree(gss_auth);
- module_put(THIS_MODULE);
+/*
+ * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call
+ * to the server with the GSS control procedure field set to
+ * RPC_GSS_PROC_DESTROY. This should normally cause the server to release
+ * all RPCSEC_GSS state associated with that context.
+ */
+static int
+gss_destroying_context(struct rpc_cred *cred)
+{
+ struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+ struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
+ struct rpc_task *task;
+
+ if (gss_cred->gc_ctx == NULL ||
+ gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY)
+ return 0;
+
+ gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY;
+ cred->cr_ops = &gss_nullops;
+
+ /* Take a reference to ensure the cred will be destroyed either
+ * by the RPC call or by the put_rpccred() below */
+ get_rpccred(cred);
+
+ task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
+ if (!IS_ERR(task))
+ rpc_put_task(task);
+
+ put_rpccred(cred);
+ return 1;
}
-/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure
+/* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure
* to create a new cred or context, so they check that things have been
* allocated before freeing them. */
static void
-gss_destroy_ctx(struct gss_cl_ctx *ctx)
+gss_do_free_ctx(struct gss_cl_ctx *ctx)
{
- dprintk("RPC: gss_destroy_ctx\n");
+ dprintk("RPC: gss_free_ctx\n");
if (ctx->gc_gss_ctx)
gss_delete_sec_context(&ctx->gc_gss_ctx);
@@ -701,15 +744,46 @@ gss_destroy_ctx(struct gss_cl_ctx *ctx)
}
static void
-gss_destroy_cred(struct rpc_cred *rc)
+gss_free_ctx_callback(struct rcu_head *head)
{
- struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
+ struct gss_cl_ctx *ctx = container_of(head, struct gss_cl_ctx, gc_rcu);
+ gss_do_free_ctx(ctx);
+}
- dprintk("RPC: gss_destroy_cred \n");
+static void
+gss_free_ctx(struct gss_cl_ctx *ctx)
+{
+ call_rcu(&ctx->gc_rcu, gss_free_ctx_callback);
+}
- if (cred->gc_ctx)
- gss_put_ctx(cred->gc_ctx);
- kfree(cred);
+static void
+gss_free_cred(struct gss_cred *gss_cred)
+{
+ dprintk("RPC: gss_free_cred %p\n", gss_cred);
+ kfree(gss_cred);
+}
+
+static void
+gss_free_cred_callback(struct rcu_head *head)
+{
+ struct gss_cred *gss_cred = container_of(head, struct gss_cred, gc_base.cr_rcu);
+ gss_free_cred(gss_cred);
+}
+
+static void
+gss_destroy_cred(struct rpc_cred *cred)
+{
+ struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
+ struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
+ struct gss_cl_ctx *ctx = gss_cred->gc_ctx;
+
+ if (gss_destroying_context(cred))
+ return;
+ rcu_assign_pointer(gss_cred->gc_ctx, NULL);
+ call_rcu(&cred->cr_rcu, gss_free_cred_callback);
+ if (ctx)
+ gss_put_ctx(ctx);
+ kref_put(&gss_auth->kref, gss_free_callback);
}
/*
@@ -734,16 +808,14 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
goto out_err;
- atomic_set(&cred->gc_count, 1);
- cred->gc_uid = acred->uid;
+ rpcauth_init_cred(&cred->gc_base, acred, auth, &gss_credops);
/*
* Note: in order to force a call to call_refresh(), we deliberately
* fail to flag the credential as RPCAUTH_CRED_UPTODATE.
*/
- cred->gc_flags = 0;
- cred->gc_base.cr_ops = &gss_credops;
- cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
+ cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW;
cred->gc_service = gss_auth->service;
+ kref_get(&gss_auth->kref);
return &cred->gc_base;
out_err:
@@ -774,7 +846,7 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
* we don't really care if the credential has expired or not,
* since the caller should be prepared to reinitialise it.
*/
- if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
+ if ((flags & RPCAUTH_LOOKUP_NEW) && test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags))
goto out;
/* Don't match with creds that have expired. */
if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
@@ -830,7 +902,7 @@ gss_marshal(struct rpc_task *task, __be32 *p)
mic.data = (u8 *)(p + 1);
maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
} else if (maj_stat != 0) {
printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
goto out_put_ctx;
@@ -855,6 +927,13 @@ gss_refresh(struct rpc_task *task)
return 0;
}
+/* Dummy refresh routine: used only when destroying the context */
+static int
+gss_refresh_null(struct rpc_task *task)
+{
+ return -EACCES;
+}
+
static __be32 *
gss_validate(struct rpc_task *task, __be32 *p)
{
@@ -883,12 +962,15 @@ gss_validate(struct rpc_task *task, __be32 *p)
maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
if (maj_stat == GSS_S_CONTEXT_EXPIRED)
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
- if (maj_stat)
+ clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+ if (maj_stat) {
+ dprintk("RPC: %5u gss_validate: gss_verify_mic returned"
+ "error 0x%08x\n", task->tk_pid, maj_stat);
goto out_bad;
+ }
/* We leave it to unwrap to calculate au_rslack. For now we just
* calculate the length of the verifier: */
- task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2;
+ cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2;
gss_put_ctx(ctx);
dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n",
task->tk_pid);
@@ -917,7 +999,9 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
*p++ = htonl(rqstp->rq_seqno);
+ lock_kernel();
status = encode(rqstp, p, obj);
+ unlock_kernel();
if (status)
return status;
@@ -937,7 +1021,7 @@ gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
status = -EIO; /* XXX? */
if (maj_stat == GSS_S_CONTEXT_EXPIRED)
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
else if (maj_stat)
return status;
q = xdr_encode_opaque(p, NULL, mic.len);
@@ -1011,7 +1095,9 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
*p++ = htonl(rqstp->rq_seqno);
+ lock_kernel();
status = encode(rqstp, p, obj);
+ unlock_kernel();
if (status)
return status;
@@ -1036,7 +1122,7 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
* done anyway, so it's safe to put the request on the wire: */
if (maj_stat == GSS_S_CONTEXT_EXPIRED)
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
else if (maj_stat)
return status;
@@ -1070,12 +1156,16 @@ gss_wrap_req(struct rpc_task *task,
/* The spec seems a little ambiguous here, but I think that not
* wrapping context destruction requests makes the most sense.
*/
+ lock_kernel();
status = encode(rqstp, p, obj);
+ unlock_kernel();
goto out;
}
switch (gss_cred->gc_service) {
case RPC_GSS_SVC_NONE:
+ lock_kernel();
status = encode(rqstp, p, obj);
+ unlock_kernel();
break;
case RPC_GSS_SVC_INTEGRITY:
status = gss_wrap_req_integ(cred, ctx, encode,
@@ -1123,7 +1213,7 @@ gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
if (maj_stat == GSS_S_CONTEXT_EXPIRED)
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
if (maj_stat != GSS_S_COMPLETE)
return status;
return 0;
@@ -1148,7 +1238,7 @@ gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
if (maj_stat == GSS_S_CONTEXT_EXPIRED)
- cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
if (maj_stat != GSS_S_COMPLETE)
return status;
if (ntohl(*(*p)++) != rqstp->rq_seqno)
@@ -1188,10 +1278,12 @@ gss_unwrap_resp(struct rpc_task *task,
break;
}
/* take into account extra slack for integrity and privacy cases: */
- task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp)
+ cred->cr_auth->au_rslack = cred->cr_auth->au_verfsize + (p - savedp)
+ (savedlen - head->iov_len);
out_decode:
+ lock_kernel();
status = decode(rqstp, p, obj);
+ unlock_kernel();
out:
gss_put_ctx(ctx);
dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid,
@@ -1199,7 +1291,7 @@ out:
return status;
}
-static struct rpc_authops authgss_ops = {
+static const struct rpc_authops authgss_ops = {
.owner = THIS_MODULE,
.au_flavor = RPC_AUTH_GSS,
#ifdef RPC_DEBUG
@@ -1211,7 +1303,7 @@ static struct rpc_authops authgss_ops = {
.crcreate = gss_create_cred
};
-static struct rpc_credops gss_credops = {
+static const struct rpc_credops gss_credops = {
.cr_name = "AUTH_GSS",
.crdestroy = gss_destroy_cred,
.cr_init = gss_cred_init,
@@ -1223,6 +1315,17 @@ static struct rpc_credops gss_credops = {
.crunwrap_resp = gss_unwrap_resp,
};
+static const struct rpc_credops gss_nullops = {
+ .cr_name = "AUTH_GSS",
+ .crdestroy = gss_destroy_cred,
+ .crmatch = gss_match,
+ .crmarshal = gss_marshal,
+ .crrefresh = gss_refresh_null,
+ .crvalidate = gss_validate,
+ .crwrap_req = gss_wrap_req,
+ .crunwrap_resp = gss_unwrap_resp,
+};
+
static struct rpc_pipe_ops gss_upcall_ops = {
.upcall = gss_pipe_upcall,
.downcall = gss_pipe_downcall,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 7b194321705..71b9daefdff 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -201,7 +201,7 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
kfree(kctx);
}
-static struct gss_api_ops gss_kerberos_ops = {
+static const struct gss_api_ops gss_kerberos_ops = {
.gss_import_sec_context = gss_import_sec_context_kerberos,
.gss_get_mic = gss_get_mic_kerberos,
.gss_verify_mic = gss_verify_mic_kerberos,
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 7e15aa68ae6..577d590e755 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -202,7 +202,7 @@ gss_get_mic_spkm3(struct gss_ctx *ctx,
return err;
}
-static struct gss_api_ops gss_spkm3_ops = {
+static const struct gss_api_ops gss_spkm3_ops = {
.gss_import_sec_context = gss_import_sec_context_spkm3,
.gss_get_mic = gss_get_mic_spkm3,
.gss_verify_mic = gss_verify_mic_spkm3,
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 099a983797d..c094583386f 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -853,7 +853,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
u32 priv_len, maj_stat;
int pad, saved_len, remaining_len, offset;
- rqstp->rq_sendfile_ok = 0;
+ rqstp->rq_splice_ok = 0;
priv_len = svc_getnl(&buf->head[0]);
if (rqstp->rq_deferred) {
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index 3df9fccab2f..537d0e8589d 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -76,7 +76,7 @@ nul_marshal(struct rpc_task *task, __be32 *p)
static int
nul_refresh(struct rpc_task *task)
{
- task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
+ set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
return 0;
}
@@ -101,7 +101,7 @@ nul_validate(struct rpc_task *task, __be32 *p)
return p;
}
-struct rpc_authops authnull_ops = {
+const struct rpc_authops authnull_ops = {
.owner = THIS_MODULE,
.au_flavor = RPC_AUTH_NULL,
#ifdef RPC_DEBUG
@@ -122,7 +122,7 @@ struct rpc_auth null_auth = {
};
static
-struct rpc_credops null_credops = {
+const struct rpc_credops null_credops = {
.cr_name = "AUTH_NULL",
.crdestroy = nul_destroy_cred,
.crmatch = nul_match,
@@ -133,9 +133,11 @@ struct rpc_credops null_credops = {
static
struct rpc_cred null_cred = {
+ .cr_lru = LIST_HEAD_INIT(null_cred.cr_lru),
+ .cr_auth = &null_auth,
.cr_ops = &null_credops,
.cr_count = ATOMIC_INIT(1),
- .cr_flags = RPCAUTH_CRED_UPTODATE,
+ .cr_flags = 1UL << RPCAUTH_CRED_UPTODATE,
#ifdef RPC_DEBUG
.cr_magic = RPCAUTH_CRED_MAGIC,
#endif
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index 4e7733aee36..5ed91e5bcee 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -20,11 +20,6 @@ struct unx_cred {
gid_t uc_gids[NFS_NGROUPS];
};
#define uc_uid uc_base.cr_uid
-#define uc_count uc_base.cr_count
-#define uc_flags uc_base.cr_flags
-#define uc_expire uc_base.cr_expire
-
-#define UNX_CRED_EXPIRE (60 * HZ)
#define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2))
@@ -34,15 +29,14 @@ struct unx_cred {
static struct rpc_auth unix_auth;
static struct rpc_cred_cache unix_cred_cache;
-static struct rpc_credops unix_credops;
+static const struct rpc_credops unix_credops;
static struct rpc_auth *
unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
{
dprintk("RPC: creating UNIX authenticator for client %p\n",
clnt);
- if (atomic_inc_return(&unix_auth.au_count) == 0)
- unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
+ atomic_inc(&unix_auth.au_count);
return &unix_auth;
}
@@ -50,7 +44,7 @@ static void
unx_destroy(struct rpc_auth *auth)
{
dprintk("RPC: destroying UNIX authenticator %p\n", auth);
- rpcauth_free_credcache(auth);
+ rpcauth_clear_credcache(auth->au_credcache);
}
/*
@@ -74,8 +68,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
return ERR_PTR(-ENOMEM);
- atomic_set(&cred->uc_count, 1);
- cred->uc_flags = RPCAUTH_CRED_UPTODATE;
+ rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
+ cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
if (flags & RPCAUTH_LOOKUP_ROOTCREDS) {
cred->uc_uid = 0;
cred->uc_gid = 0;
@@ -85,22 +79,34 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
if (groups > NFS_NGROUPS)
groups = NFS_NGROUPS;
- cred->uc_uid = acred->uid;
cred->uc_gid = acred->gid;
for (i = 0; i < groups; i++)
cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
if (i < NFS_NGROUPS)
cred->uc_gids[i] = NOGROUP;
}
- cred->uc_base.cr_ops = &unix_credops;
- return (struct rpc_cred *) cred;
+ return &cred->uc_base;
+}
+
+static void
+unx_free_cred(struct unx_cred *unx_cred)
+{
+ dprintk("RPC: unx_free_cred %p\n", unx_cred);
+ kfree(unx_cred);
+}
+
+static void
+unx_free_cred_callback(struct rcu_head *head)
+{
+ struct unx_cred *unx_cred = container_of(head, struct unx_cred, uc_base.cr_rcu);
+ unx_free_cred(unx_cred);
}
static void
unx_destroy_cred(struct rpc_cred *cred)
{
- kfree(cred);
+ call_rcu(&cred->cr_rcu, unx_free_cred_callback);
}
/*
@@ -111,7 +117,7 @@ unx_destroy_cred(struct rpc_cred *cred)
static int
unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
{
- struct unx_cred *cred = (struct unx_cred *) rcred;
+ struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base);
int i;
if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) {
@@ -142,7 +148,7 @@ static __be32 *
unx_marshal(struct rpc_task *task, __be32 *p)
{
struct rpc_clnt *clnt = task->tk_client;
- struct unx_cred *cred = (struct unx_cred *) task->tk_msg.rpc_cred;
+ struct unx_cred *cred = container_of(task->tk_msg.rpc_cred, struct unx_cred, uc_base);
__be32 *base, *hold;
int i;
@@ -175,7 +181,7 @@ unx_marshal(struct rpc_task *task, __be32 *p)
static int
unx_refresh(struct rpc_task *task)
{
- task->tk_msg.rpc_cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
+ set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
return 0;
}
@@ -198,13 +204,18 @@ unx_validate(struct rpc_task *task, __be32 *p)
printk("RPC: giant verf size: %u\n", size);
return NULL;
}
- task->tk_auth->au_rslack = (size >> 2) + 2;
+ task->tk_msg.rpc_cred->cr_auth->au_rslack = (size >> 2) + 2;
p += (size >> 2);
return p;
}
-struct rpc_authops authunix_ops = {
+void __init rpc_init_authunix(void)
+{
+ spin_lock_init(&unix_cred_cache.lock);
+}
+
+const struct rpc_authops authunix_ops = {
.owner = THIS_MODULE,
.au_flavor = RPC_AUTH_UNIX,
#ifdef RPC_DEBUG
@@ -218,7 +229,6 @@ struct rpc_authops authunix_ops = {
static
struct rpc_cred_cache unix_cred_cache = {
- .expire = UNX_CRED_EXPIRE,
};
static
@@ -232,7 +242,7 @@ struct rpc_auth unix_auth = {
};
static
-struct rpc_credops unix_credops = {
+const struct rpc_credops unix_credops = {
.cr_name = "AUTH_UNIX",
.crdestroy = unx_destroy_cred,
.crmatch = unx_match,
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 543b085ae2c..01c3c410520 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1210,7 +1210,7 @@ static int c_show(struct seq_file *m, void *p)
return cd->cache_show(m, cd, cp);
}
-static struct seq_operations cache_content_op = {
+static const struct seq_operations cache_content_op = {
.start = c_start,
.next = c_next,
.stop = c_stop,
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d8fbee40a19..52429b1ffcc 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -44,6 +44,12 @@
dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \
__FUNCTION__, t->tk_status)
+/*
+ * All RPC clients are linked into this list
+ */
+static LIST_HEAD(all_clients);
+static DEFINE_SPINLOCK(rpc_client_lock);
+
static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
@@ -66,6 +72,21 @@ static void call_connect_status(struct rpc_task *task);
static __be32 * call_header(struct rpc_task *task);
static __be32 * call_verify(struct rpc_task *task);
+static int rpc_ping(struct rpc_clnt *clnt, int flags);
+
+static void rpc_register_client(struct rpc_clnt *clnt)
+{
+ spin_lock(&rpc_client_lock);
+ list_add(&clnt->cl_clients, &all_clients);
+ spin_unlock(&rpc_client_lock);
+}
+
+static void rpc_unregister_client(struct rpc_clnt *clnt)
+{
+ spin_lock(&rpc_client_lock);
+ list_del(&clnt->cl_clients);
+ spin_unlock(&rpc_client_lock);
+}
static int
rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
@@ -111,6 +132,9 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
dprintk("RPC: creating %s client for %s (xprt %p)\n",
program->name, servname, xprt);
+ err = rpciod_up();
+ if (err)
+ goto out_no_rpciod;
err = -EINVAL;
if (!xprt)
goto out_no_xprt;
@@ -121,8 +145,6 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
if (!clnt)
goto out_err;
- atomic_set(&clnt->cl_users, 0);
- atomic_set(&clnt->cl_count, 1);
clnt->cl_parent = clnt;
clnt->cl_server = clnt->cl_inline_name;
@@ -148,6 +170,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
if (clnt->cl_metrics == NULL)
goto out_no_stats;
clnt->cl_program = program;
+ INIT_LIST_HEAD(&clnt->cl_tasks);
+ spin_lock_init(&clnt->cl_lock);
if (!xprt_bound(clnt->cl_xprt))
clnt->cl_autobind = 1;
@@ -155,6 +179,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
clnt->cl_rtt = &clnt->cl_rtt_default;
rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval);
+ kref_init(&clnt->cl_kref);
+
err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
if (err < 0)
goto out_no_path;
@@ -172,6 +198,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
if (clnt->cl_nodelen > UNX_MAXNODENAME)
clnt->cl_nodelen = UNX_MAXNODENAME;
memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen);
+ rpc_register_client(clnt);
return clnt;
out_no_auth:
@@ -188,6 +215,8 @@ out_no_stats:
out_err:
xprt_put(xprt);
out_no_xprt:
+ rpciod_down();
+out_no_rpciod:
return ERR_PTR(err);
}
@@ -205,13 +234,32 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
{
struct rpc_xprt *xprt;
struct rpc_clnt *clnt;
+ struct rpc_xprtsock_create xprtargs = {
+ .proto = args->protocol,
+ .srcaddr = args->saddress,
+ .dstaddr = args->address,
+ .addrlen = args->addrsize,
+ .timeout = args->timeout
+ };
+ char servername[20];
- xprt = xprt_create_transport(args->protocol, args->address,
- args->addrsize, args->timeout);
+ xprt = xprt_create_transport(&xprtargs);
if (IS_ERR(xprt))
return (struct rpc_clnt *)xprt;
/*
+ * If the caller chooses not to specify a hostname, whip
+ * up a string representation of the passed-in address.
+ */
+ if (args->servername == NULL) {
+ struct sockaddr_in *addr =
+ (struct sockaddr_in *) &args->address;
+ snprintf(servername, sizeof(servername), NIPQUAD_FMT,
+ NIPQUAD(addr->sin_addr.s_addr));
+ args->servername = servername;
+ }
+
+ /*
* By default, kernel RPC client connects from a reserved port.
* CAP_NET_BIND_SERVICE will not be set for unprivileged requesters,
* but it is always enabled for rpciod, which handles the connect
@@ -245,8 +293,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
clnt->cl_intr = 1;
if (args->flags & RPC_CLNT_CREATE_AUTOBIND)
clnt->cl_autobind = 1;
- if (args->flags & RPC_CLNT_CREATE_ONESHOT)
- clnt->cl_oneshot = 1;
if (args->flags & RPC_CLNT_CREATE_DISCRTRY)
clnt->cl_discrtry = 1;
@@ -268,24 +314,25 @@ rpc_clone_client(struct rpc_clnt *clnt)
new = kmemdup(clnt, sizeof(*new), GFP_KERNEL);
if (!new)
goto out_no_clnt;
- atomic_set(&new->cl_count, 1);
- atomic_set(&new->cl_users, 0);
+ new->cl_parent = clnt;
+ /* Turn off autobind on clones */
+ new->cl_autobind = 0;
+ INIT_LIST_HEAD(&new->cl_tasks);
+ spin_lock_init(&new->cl_lock);
+ rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
new->cl_metrics = rpc_alloc_iostats(clnt);
if (new->cl_metrics == NULL)
goto out_no_stats;
+ kref_init(&new->cl_kref);
err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
if (err != 0)
goto out_no_path;
- new->cl_parent = clnt;
- atomic_inc(&clnt->cl_count);
- new->cl_xprt = xprt_get(clnt->cl_xprt);
- /* Turn off autobind on clones */
- new->cl_autobind = 0;
- new->cl_oneshot = 0;
- new->cl_dead = 0;
- rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
if (new->cl_auth)
atomic_inc(&new->cl_auth->au_count);
+ xprt_get(clnt->cl_xprt);
+ kref_get(&clnt->cl_kref);
+ rpc_register_client(new);
+ rpciod_up();
return new;
out_no_path:
rpc_free_iostats(new->cl_metrics);
@@ -298,86 +345,86 @@ out_no_clnt:
/*
* Properly shut down an RPC client, terminating all outstanding
- * requests. Note that we must be certain that cl_oneshot and
- * cl_dead are cleared, or else the client would be destroyed
- * when the last task releases it.
+ * requests.
*/
-int
-rpc_shutdown_client(struct rpc_clnt *clnt)
+void rpc_shutdown_client(struct rpc_clnt *clnt)
{
- dprintk("RPC: shutting down %s client for %s, tasks=%d\n",
- clnt->cl_protname, clnt->cl_server,
- atomic_read(&clnt->cl_users));
-
- while (atomic_read(&clnt->cl_users) > 0) {
- /* Don't let rpc_release_client destroy us */
- clnt->cl_oneshot = 0;
- clnt->cl_dead = 0;
+ dprintk("RPC: shutting down %s client for %s\n",
+ clnt->cl_protname, clnt->cl_server);
+
+ while (!list_empty(&clnt->cl_tasks)) {
rpc_killall_tasks(clnt);
wait_event_timeout(destroy_wait,
- !atomic_read(&clnt->cl_users), 1*HZ);
- }
-
- if (atomic_read(&clnt->cl_users) < 0) {
- printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n",
- clnt, atomic_read(&clnt->cl_users));
-#ifdef RPC_DEBUG
- rpc_show_tasks();
-#endif
- BUG();
+ list_empty(&clnt->cl_tasks), 1*HZ);
}
- return rpc_destroy_client(clnt);
+ rpc_release_client(clnt);
}
/*
- * Delete an RPC client
+ * Free an RPC client
*/
-int
-rpc_destroy_client(struct rpc_clnt *clnt)
+static void
+rpc_free_client(struct kref *kref)
{
- if (!atomic_dec_and_test(&clnt->cl_count))
- return 1;
- BUG_ON(atomic_read(&clnt->cl_users) != 0);
+ struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
dprintk("RPC: destroying %s client for %s\n",
clnt->cl_protname, clnt->cl_server);
- if (clnt->cl_auth) {
- rpcauth_destroy(clnt->cl_auth);
- clnt->cl_auth = NULL;
- }
if (!IS_ERR(clnt->cl_dentry)) {
rpc_rmdir(clnt->cl_dentry);
rpc_put_mount();
}
if (clnt->cl_parent != clnt) {
- rpc_destroy_client(clnt->cl_parent);
+ rpc_release_client(clnt->cl_parent);
goto out_free;
}
if (clnt->cl_server != clnt->cl_inline_name)
kfree(clnt->cl_server);
out_free:
+ rpc_unregister_client(clnt);
rpc_free_iostats(clnt->cl_metrics);
clnt->cl_metrics = NULL;
xprt_put(clnt->cl_xprt);
+ rpciod_down();
kfree(clnt);
- return 0;
}
/*
- * Release an RPC client
+ * Free an RPC client
+ */
+static void
+rpc_free_auth(struct kref *kref)
+{
+ struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
+
+ if (clnt->cl_auth == NULL) {
+ rpc_free_client(kref);
+ return;
+ }
+
+ /*
+ * Note: RPCSEC_GSS may need to send NULL RPC calls in order to
+ * release remaining GSS contexts. This mechanism ensures
+ * that it can do so safely.
+ */
+ kref_init(kref);
+ rpcauth_release(clnt->cl_auth);
+ clnt->cl_auth = NULL;
+ kref_put(kref, rpc_free_client);
+}
+
+/*
+ * Release reference to the RPC client
*/
void
rpc_release_client(struct rpc_clnt *clnt)
{
- dprintk("RPC: rpc_release_client(%p, %d)\n",
- clnt, atomic_read(&clnt->cl_users));
+ dprintk("RPC: rpc_release_client(%p)\n", clnt);
- if (!atomic_dec_and_test(&clnt->cl_users))
- return;
- wake_up(&destroy_wait);
- if (clnt->cl_oneshot || clnt->cl_dead)
- rpc_destroy_client(clnt);
+ if (list_empty(&clnt->cl_tasks))
+ wake_up(&destroy_wait);
+ kref_put(&clnt->cl_kref, rpc_free_auth);
}
/**
@@ -468,82 +515,96 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
rpc_restore_sigmask(oldset);
}
-/*
- * New rpc_call implementation
+static
+struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt,
+ struct rpc_message *msg,
+ int flags,
+ const struct rpc_call_ops *ops,
+ void *data)
+{
+ struct rpc_task *task, *ret;
+ sigset_t oldset;
+
+ task = rpc_new_task(clnt, flags, ops, data);
+ if (task == NULL) {
+ rpc_release_calldata(ops, data);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */
+ rpc_task_sigmask(task, &oldset);
+ if (msg != NULL) {
+ rpc_call_setup(task, msg, 0);
+ if (task->tk_status != 0) {
+ ret = ERR_PTR(task->tk_status);
+ rpc_put_task(task);
+ goto out;
+ }
+ }
+ atomic_inc(&task->tk_count);
+ rpc_execute(task);
+ ret = task;
+out:
+ rpc_restore_sigmask(&oldset);
+ return ret;
+}
+
+/**
+ * rpc_call_sync - Perform a synchronous RPC call
+ * @clnt: pointer to RPC client
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
*/
int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
{
struct rpc_task *task;
- sigset_t oldset;
- int status;
-
- /* If this client is slain all further I/O fails */
- if (clnt->cl_dead)
- return -EIO;
+ int status;
BUG_ON(flags & RPC_TASK_ASYNC);
- task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL);
- if (task == NULL)
- return -ENOMEM;
-
- /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
- rpc_task_sigmask(task, &oldset);
-
- /* Set up the call info struct and execute the task */
- rpc_call_setup(task, msg, 0);
- if (task->tk_status == 0) {
- atomic_inc(&task->tk_count);
- rpc_execute(task);
- }
+ task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
status = task->tk_status;
rpc_put_task(task);
- rpc_restore_sigmask(&oldset);
return status;
}
-/*
- * New rpc_call implementation
+/**
+ * rpc_call_async - Perform an asynchronous RPC call
+ * @clnt: pointer to RPC client
+ * @msg: RPC call parameters
+ * @flags: RPC call flags
+ * @ops: RPC call ops
+ * @data: user call data
*/
int
rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
const struct rpc_call_ops *tk_ops, void *data)
{
struct rpc_task *task;
- sigset_t oldset;
- int status;
-
- /* If this client is slain all further I/O fails */
- status = -EIO;
- if (clnt->cl_dead)
- goto out_release;
-
- flags |= RPC_TASK_ASYNC;
-
- /* Create/initialize a new RPC task */
- status = -ENOMEM;
- if (!(task = rpc_new_task(clnt, flags, tk_ops, data)))
- goto out_release;
-
- /* Mask signals on GSS_AUTH upcalls */
- rpc_task_sigmask(task, &oldset);
- rpc_call_setup(task, msg, 0);
-
- /* Set up the call info struct and execute the task */
- status = task->tk_status;
- if (status == 0)
- rpc_execute(task);
- else
- rpc_put_task(task);
-
- rpc_restore_sigmask(&oldset);
- return status;
-out_release:
- rpc_release_calldata(tk_ops, data);
- return status;
+ task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data);
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+ rpc_put_task(task);
+ return 0;
}
+/**
+ * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
+ * @clnt: pointer to RPC client
+ * @flags: RPC flags
+ * @ops: RPC call ops
+ * @data: user call data
+ */
+struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
+ const struct rpc_call_ops *tk_ops,
+ void *data)
+{
+ return rpc_do_run_task(clnt, NULL, flags, tk_ops, data);
+}
+EXPORT_SYMBOL(rpc_run_task);
void
rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
@@ -745,7 +806,7 @@ call_reserveresult(struct rpc_task *task)
static void
call_allocate(struct rpc_task *task)
{
- unsigned int slack = task->tk_auth->au_cslack;
+ unsigned int slack = task->tk_msg.rpc_cred->cr_auth->au_cslack;
struct rpc_rqst *req = task->tk_rqstp;
struct rpc_xprt *xprt = task->tk_xprt;
struct rpc_procinfo *proc = task->tk_msg.rpc_proc;
@@ -843,10 +904,8 @@ call_encode(struct rpc_task *task)
if (encode == NULL)
return;
- lock_kernel();
task->tk_status = rpcauth_wrap_req(task, encode, req, p,
task->tk_msg.rpc_argp);
- unlock_kernel();
if (task->tk_status == -ENOMEM) {
/* XXX: Is this sane? */
rpc_delay(task, 3*HZ);
@@ -1177,10 +1236,8 @@ call_decode(struct rpc_task *task)
task->tk_action = rpc_exit_task;
if (decode) {
- lock_kernel();
task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
task->tk_msg.rpc_resp);
- unlock_kernel();
}
dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
task->tk_status);
@@ -1273,9 +1330,9 @@ call_verify(struct rpc_task *task)
* - if it isn't pointer subtraction in the NFS client may give
* undefined results
*/
- printk(KERN_WARNING
- "call_verify: XDR representation not a multiple of"
- " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len);
+ dprintk("RPC: %5u %s: XDR representation not a multiple of"
+ " 4 bytes: 0x%x\n", task->tk_pid, __FUNCTION__,
+ task->tk_rqstp->rq_rcv_buf.len);
goto out_eio;
}
if ((len -= 3) < 0)
@@ -1283,7 +1340,8 @@ call_verify(struct rpc_task *task)
p += 1; /* skip XID */
if ((n = ntohl(*p++)) != RPC_REPLY) {
- printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n);
+ dprintk("RPC: %5u %s: not an RPC reply: %x\n",
+ task->tk_pid, __FUNCTION__, n);
goto out_garbage;
}
if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
@@ -1334,7 +1392,8 @@ call_verify(struct rpc_task *task)
"authentication.\n", task->tk_client->cl_server);
break;
default:
- printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
+ dprintk("RPC: %5u %s: unknown auth error: %x\n",
+ task->tk_pid, __FUNCTION__, n);
error = -EIO;
}
dprintk("RPC: %5u %s: call rejected %d\n",
@@ -1342,7 +1401,8 @@ call_verify(struct rpc_task *task)
goto out_err;
}
if (!(p = rpcauth_checkverf(task, p))) {
- printk(KERN_WARNING "call_verify: auth check failed\n");
+ dprintk("RPC: %5u %s: auth check failed\n",
+ task->tk_pid, __FUNCTION__);
goto out_garbage; /* bad verifier, retry */
}
len = p - (__be32 *)iov->iov_base - 1;
@@ -1381,7 +1441,8 @@ call_verify(struct rpc_task *task)
task->tk_pid, __FUNCTION__);
break; /* retry */
default:
- printk(KERN_WARNING "call_verify: server accept status: %x\n", n);
+ dprintk("RPC: %5u %s: server accept status: %x\n",
+ task->tk_pid, __FUNCTION__, n);
/* Also retry */
}
@@ -1395,14 +1456,16 @@ out_garbage:
out_retry:
return ERR_PTR(-EAGAIN);
}
- printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__);
out_eio:
error = -EIO;
out_err:
rpc_exit(task, error);
+ dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid,
+ __FUNCTION__, error);
return ERR_PTR(error);
out_overflow:
- printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
+ dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid,
+ __FUNCTION__);
goto out_garbage;
}
@@ -1421,7 +1484,7 @@ static struct rpc_procinfo rpcproc_null = {
.p_decode = rpcproc_decode_null,
};
-int rpc_ping(struct rpc_clnt *clnt, int flags)
+static int rpc_ping(struct rpc_clnt *clnt, int flags)
{
struct rpc_message msg = {
.rpc_proc = &rpcproc_null,
@@ -1432,3 +1495,51 @@ int rpc_ping(struct rpc_clnt *clnt, int flags)
put_rpccred(msg.rpc_cred);
return err;
}
+
+struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags)
+{
+ struct rpc_message msg = {
+ .rpc_proc = &rpcproc_null,
+ .rpc_cred = cred,
+ };
+ return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL);
+}
+EXPORT_SYMBOL(rpc_call_null);
+
+#ifdef RPC_DEBUG
+void rpc_show_tasks(void)
+{
+ struct rpc_clnt *clnt;
+ struct rpc_task *t;
+
+ spin_lock(&rpc_client_lock);
+ if (list_empty(&all_clients))
+ goto out;
+ printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
+ "-rpcwait -action- ---ops--\n");
+ list_for_each_entry(clnt, &all_clients, cl_clients) {
+ if (list_empty(&clnt->cl_tasks))
+ continue;
+ spin_lock(&clnt->cl_lock);
+ list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
+ const char *rpc_waitq = "none";
+
+ if (RPC_IS_QUEUED(t))
+ rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
+
+ printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
+ t->tk_pid,
+ (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
+ t->tk_flags, t->tk_status,
+ t->tk_client,
+ (t->tk_client ? t->tk_client->cl_prog : 0),
+ t->tk_rqstp, t->tk_timeout,
+ rpc_waitq,
+ t->tk_action, t->tk_ops);
+ }
+ spin_unlock(&clnt->cl_lock);
+ }
+out:
+ spin_unlock(&rpc_client_lock);
+}
+#endif
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 5887457dc93..e787b6a43ee 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -344,7 +344,7 @@ rpc_info_open(struct inode *inode, struct file *file)
mutex_lock(&inode->i_mutex);
clnt = RPC_I(inode)->private;
if (clnt) {
- atomic_inc(&clnt->cl_users);
+ kref_get(&clnt->cl_kref);
m->private = clnt;
} else {
single_release(inode, file);
@@ -448,6 +448,15 @@ void rpc_put_mount(void)
simple_release_fs(&rpc_mount, &rpc_mount_count);
}
+static int rpc_delete_dentry(struct dentry *dentry)
+{
+ return 1;
+}
+
+static struct dentry_operations rpc_dentry_operations = {
+ .d_delete = rpc_delete_dentry,
+};
+
static int
rpc_lookup_parent(char *path, struct nameidata *nd)
{
@@ -506,7 +515,7 @@ rpc_get_inode(struct super_block *sb, int mode)
* FIXME: This probably has races.
*/
static void
-rpc_depopulate(struct dentry *parent)
+rpc_depopulate(struct dentry *parent, int start, int eof)
{
struct inode *dir = parent->d_inode;
struct list_head *pos, *next;
@@ -518,6 +527,10 @@ repeat:
spin_lock(&dcache_lock);
list_for_each_safe(pos, next, &parent->d_subdirs) {
dentry = list_entry(pos, struct dentry, d_u.d_child);
+ if (!dentry->d_inode ||
+ dentry->d_inode->i_ino < start ||
+ dentry->d_inode->i_ino >= eof)
+ continue;
spin_lock(&dentry->d_lock);
if (!d_unhashed(dentry)) {
dget_locked(dentry);
@@ -533,11 +546,11 @@ repeat:
if (n) {
do {
dentry = dvec[--n];
- if (dentry->d_inode) {
- rpc_close_pipes(dentry->d_inode);
+ if (S_ISREG(dentry->d_inode->i_mode))
simple_unlink(dir, dentry);
- }
- inode_dir_notify(dir, DN_DELETE);
+ else if (S_ISDIR(dentry->d_inode->i_mode))
+ simple_rmdir(dir, dentry);
+ d_delete(dentry);
dput(dentry);
} while (n);
goto repeat;
@@ -560,6 +573,7 @@ rpc_populate(struct dentry *parent,
dentry = d_alloc_name(parent, files[i].name);
if (!dentry)
goto out_bad;
+ dentry->d_op = &rpc_dentry_operations;
mode = files[i].mode;
inode = rpc_get_inode(dir->i_sb, mode);
if (!inode) {
@@ -607,21 +621,14 @@ static int
__rpc_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
-
- shrink_dcache_parent(dentry);
- if (d_unhashed(dentry))
- return 0;
- if ((error = simple_rmdir(dir, dentry)) != 0)
- return error;
- if (!error) {
- inode_dir_notify(dir, DN_DELETE);
- d_drop(dentry);
- }
- return 0;
+ error = simple_rmdir(dir, dentry);
+ if (!error)
+ d_delete(dentry);
+ return error;
}
static struct dentry *
-rpc_lookup_create(struct dentry *parent, const char *name, int len)
+rpc_lookup_create(struct dentry *parent, const char *name, int len, int exclusive)
{
struct inode *dir = parent->d_inode;
struct dentry *dentry;
@@ -630,7 +637,9 @@ rpc_lookup_create(struct dentry *parent, const char *name, int len)
dentry = lookup_one_len(name, parent, len);
if (IS_ERR(dentry))
goto out_err;
- if (dentry->d_inode) {
+ if (!dentry->d_inode)
+ dentry->d_op = &rpc_dentry_operations;
+ else if (exclusive) {
dput(dentry);
dentry = ERR_PTR(-EEXIST);
goto out_err;
@@ -649,7 +658,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd)
if ((error = rpc_lookup_parent(path, nd)) != 0)
return ERR_PTR(error);
- dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len);
+ dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len, 1);
if (IS_ERR(dentry))
rpc_release_path(nd);
return dentry;
@@ -681,7 +690,7 @@ out:
rpc_release_path(&nd);
return dentry;
err_depopulate:
- rpc_depopulate(dentry);
+ rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
__rpc_rmdir(dir, dentry);
err_dput:
dput(dentry);
@@ -701,7 +710,7 @@ rpc_rmdir(struct dentry *dentry)
parent = dget_parent(dentry);
dir = parent->d_inode;
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
- rpc_depopulate(dentry);
+ rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
error = __rpc_rmdir(dir, dentry);
dput(dentry);
mutex_unlock(&dir->i_mutex);
@@ -716,10 +725,21 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi
struct inode *dir, *inode;
struct rpc_inode *rpci;
- dentry = rpc_lookup_create(parent, name, strlen(name));
+ dentry = rpc_lookup_create(parent, name, strlen(name), 0);
if (IS_ERR(dentry))
return dentry;
dir = parent->d_inode;
+ if (dentry->d_inode) {
+ rpci = RPC_I(dentry->d_inode);
+ if (rpci->private != private ||
+ rpci->ops != ops ||
+ rpci->flags != flags) {
+ dput (dentry);
+ dentry = ERR_PTR(-EBUSY);
+ }
+ rpci->nkern_readwriters++;
+ goto out;
+ }
inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR);
if (!inode)
goto err_dput;
@@ -730,6 +750,7 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi
rpci->private = private;
rpci->flags = flags;
rpci->ops = ops;
+ rpci->nkern_readwriters = 1;
inode_dir_notify(dir, DN_CREATE);
dget(dentry);
out:
@@ -754,13 +775,11 @@ rpc_unlink(struct dentry *dentry)
parent = dget_parent(dentry);
dir = parent->d_inode;
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
- if (!d_unhashed(dentry)) {
- d_drop(dentry);
- if (dentry->d_inode) {
- rpc_close_pipes(dentry->d_inode);
- error = simple_unlink(dir, dentry);
- }
- inode_dir_notify(dir, DN_DELETE);
+ if (--RPC_I(dentry->d_inode)->nkern_readwriters == 0) {
+ rpc_close_pipes(dentry->d_inode);
+ error = simple_unlink(dir, dentry);
+ if (!error)
+ d_delete(dentry);
}
dput(dentry);
mutex_unlock(&dir->i_mutex);
@@ -833,6 +852,7 @@ init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
rpci->nreaders = 0;
rpci->nwriters = 0;
INIT_LIST_HEAD(&rpci->in_upcall);
+ INIT_LIST_HEAD(&rpci->in_downcall);
INIT_LIST_HEAD(&rpci->pipe);
rpci->pipelen = 0;
init_waitqueue_head(&rpci->waitq);
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 6c7aa8a1f0c..d1740dbab99 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -12,6 +12,8 @@
* Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
*/
+#include <linux/module.h>
+
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/kernel.h>
@@ -184,8 +186,8 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
.program = &rpcb_program,
.version = version,
.authflavor = RPC_AUTH_UNIX,
- .flags = (RPC_CLNT_CREATE_ONESHOT |
- RPC_CLNT_CREATE_NOPING),
+ .flags = (RPC_CLNT_CREATE_NOPING |
+ RPC_CLNT_CREATE_INTR),
};
((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
@@ -238,6 +240,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
error = rpc_call_sync(rpcb_clnt, &msg, 0);
+ rpc_shutdown_client(rpcb_clnt);
if (error < 0)
printk(KERN_WARNING "RPC: failed to contact local rpcbind "
"server (errno %d).\n", -error);
@@ -246,21 +249,20 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
return error;
}
-#ifdef CONFIG_ROOT_NFS
/**
- * rpcb_getport_external - obtain the port for an RPC service on a given host
+ * rpcb_getport_sync - obtain the port for an RPC service on a given host
* @sin: address of remote peer
* @prog: RPC program number to bind
* @vers: RPC version number to bind
* @prot: transport protocol to use to make this request
*
* Called from outside the RPC client in a synchronous task context.
+ * Uses default timeout parameters specified by underlying transport.
*
- * For now, this supports only version 2 queries, but is used only by
- * mount_clnt for NFS_ROOT.
+ * XXX: Needs to support IPv6, and rpcbind versions 3 and 4
*/
-int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
- __u32 vers, int prot)
+int rpcb_getport_sync(struct sockaddr_in *sin, __u32 prog,
+ __u32 vers, int prot)
{
struct rpcbind_args map = {
.r_prog = prog,
@@ -277,15 +279,16 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
char hostname[40];
int status;
- dprintk("RPC: rpcb_getport_external(%u.%u.%u.%u, %u, %u, %d)\n",
- NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
+ dprintk("RPC: %s(" NIPQUAD_FMT ", %u, %u, %d)\n",
+ __FUNCTION__, NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
- sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
+ sprintf(hostname, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr));
rpcb_clnt = rpcb_create(hostname, (struct sockaddr *)sin, prot, 2, 0);
if (IS_ERR(rpcb_clnt))
return PTR_ERR(rpcb_clnt);
status = rpc_call_sync(rpcb_clnt, &msg, 0);
+ rpc_shutdown_client(rpcb_clnt);
if (status >= 0) {
if (map.r_port != 0)
@@ -294,16 +297,16 @@ int rpcb_getport_external(struct sockaddr_in *sin, __u32 prog,
}
return status;
}
-#endif
+EXPORT_SYMBOL_GPL(rpcb_getport_sync);
/**
- * rpcb_getport - obtain the port for a given RPC service on a given host
+ * rpcb_getport_async - obtain the port for a given RPC service on a given host
* @task: task that is waiting for portmapper request
*
* This one can be called for an ongoing RPC request, and can be used in
* an async (rpciod) context.
*/
-void rpcb_getport(struct rpc_task *task)
+void rpcb_getport_async(struct rpc_task *task)
{
struct rpc_clnt *clnt = task->tk_client;
int bind_version;
@@ -314,17 +317,17 @@ void rpcb_getport(struct rpc_task *task)
struct sockaddr addr;
int status;
- dprintk("RPC: %5u rpcb_getport(%s, %u, %u, %d)\n",
- task->tk_pid, clnt->cl_server,
- clnt->cl_prog, clnt->cl_vers, xprt->prot);
+ dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
+ task->tk_pid, __FUNCTION__,
+ clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
/* Autobind on cloned rpc clients is discouraged */
BUG_ON(clnt->cl_parent != clnt);
if (xprt_test_and_set_binding(xprt)) {
status = -EACCES; /* tell caller to check again */
- dprintk("RPC: %5u rpcb_getport waiting for another binder\n",
- task->tk_pid);
+ dprintk("RPC: %5u %s: waiting for another binder\n",
+ task->tk_pid, __FUNCTION__);
goto bailout_nowake;
}
@@ -335,27 +338,28 @@ void rpcb_getport(struct rpc_task *task)
/* Someone else may have bound if we slept */
if (xprt_bound(xprt)) {
status = 0;
- dprintk("RPC: %5u rpcb_getport already bound\n", task->tk_pid);
+ dprintk("RPC: %5u %s: already bound\n",
+ task->tk_pid, __FUNCTION__);
goto bailout_nofree;
}
if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) {
xprt->bind_index = 0;
status = -EACCES; /* tell caller to try again later */
- dprintk("RPC: %5u rpcb_getport no more getport versions "
- "available\n", task->tk_pid);
+ dprintk("RPC: %5u %s: no more getport versions available\n",
+ task->tk_pid, __FUNCTION__);
goto bailout_nofree;
}
bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
- dprintk("RPC: %5u rpcb_getport trying rpcbind version %u\n",
- task->tk_pid, bind_version);
+ dprintk("RPC: %5u %s: trying rpcbind version %u\n",
+ task->tk_pid, __FUNCTION__, bind_version);
map = kzalloc(sizeof(struct rpcbind_args), GFP_ATOMIC);
if (!map) {
status = -ENOMEM;
- dprintk("RPC: %5u rpcb_getport no memory available\n",
- task->tk_pid);
+ dprintk("RPC: %5u %s: no memory available\n",
+ task->tk_pid, __FUNCTION__);
goto bailout_nofree;
}
map->r_prog = clnt->cl_prog;
@@ -373,16 +377,17 @@ void rpcb_getport(struct rpc_task *task)
rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
if (IS_ERR(rpcb_clnt)) {
status = PTR_ERR(rpcb_clnt);
- dprintk("RPC: %5u rpcb_getport rpcb_create failed, error %ld\n",
- task->tk_pid, PTR_ERR(rpcb_clnt));
+ dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n",
+ task->tk_pid, __FUNCTION__, PTR_ERR(rpcb_clnt));
goto bailout;
}
child = rpc_run_task(rpcb_clnt, RPC_TASK_ASYNC, &rpcb_getport_ops, map);
+ rpc_release_client(rpcb_clnt);
if (IS_ERR(child)) {
status = -EIO;
- dprintk("RPC: %5u rpcb_getport rpc_run_task failed\n",
- task->tk_pid);
+ dprintk("RPC: %5u %s: rpc_run_task failed\n",
+ task->tk_pid, __FUNCTION__);
goto bailout_nofree;
}
rpc_put_task(child);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 944d75396fb..2ac43c41c3a 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -25,7 +25,6 @@
#ifdef RPC_DEBUG
#define RPCDBG_FACILITY RPCDBG_SCHED
#define RPC_TASK_MAGIC_ID 0xf00baa
-static int rpc_task_id;
#endif
/*
@@ -40,7 +39,6 @@ static mempool_t *rpc_task_mempool __read_mostly;
static mempool_t *rpc_buffer_mempool __read_mostly;
static void __rpc_default_timer(struct rpc_task *task);
-static void rpciod_killall(void);
static void rpc_async_schedule(struct work_struct *);
static void rpc_release_task(struct rpc_task *task);
@@ -50,23 +48,13 @@ static void rpc_release_task(struct rpc_task *task);
static RPC_WAITQ(delay_queue, "delayq");
/*
- * All RPC tasks are linked into this list
- */
-static LIST_HEAD(all_tasks);
-
-/*
* rpciod-related stuff
*/
static DEFINE_MUTEX(rpciod_mutex);
-static unsigned int rpciod_users;
+static atomic_t rpciod_users = ATOMIC_INIT(0);
struct workqueue_struct *rpciod_workqueue;
/*
- * Spinlock for other critical sections of code.
- */
-static DEFINE_SPINLOCK(rpc_sched_lock);
-
-/*
* Disable the timer for a given RPC task. Should be called with
* queue->lock and bh_disabled in order to avoid races within
* rpc_run_timer().
@@ -267,18 +255,33 @@ static int rpc_wait_bit_interruptible(void *word)
return 0;
}
+#ifdef RPC_DEBUG
+static void rpc_task_set_debuginfo(struct rpc_task *task)
+{
+ static atomic_t rpc_pid;
+
+ task->tk_magic = RPC_TASK_MAGIC_ID;
+ task->tk_pid = atomic_inc_return(&rpc_pid);
+}
+#else
+static inline void rpc_task_set_debuginfo(struct rpc_task *task)
+{
+}
+#endif
+
static void rpc_set_active(struct rpc_task *task)
{
+ struct rpc_clnt *clnt;
if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0)
return;
- spin_lock(&rpc_sched_lock);
-#ifdef RPC_DEBUG
- task->tk_magic = RPC_TASK_MAGIC_ID;
- task->tk_pid = rpc_task_id++;
-#endif
+ rpc_task_set_debuginfo(task);
/* Add to global list of all tasks */
- list_add_tail(&task->tk_task, &all_tasks);
- spin_unlock(&rpc_sched_lock);
+ clnt = task->tk_client;
+ if (clnt != NULL) {
+ spin_lock(&clnt->cl_lock);
+ list_add_tail(&task->tk_task, &clnt->cl_tasks);
+ spin_unlock(&clnt->cl_lock);
+ }
}
/*
@@ -818,6 +821,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
if (tk_ops->rpc_call_prepare != NULL)
task->tk_action = rpc_prepare_task;
task->tk_calldata = calldata;
+ INIT_LIST_HEAD(&task->tk_task);
/* Initialize retry counters */
task->tk_garb_retry = 2;
@@ -830,7 +834,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
task->tk_workqueue = rpciod_workqueue;
if (clnt) {
- atomic_inc(&clnt->cl_users);
+ kref_get(&clnt->cl_kref);
if (clnt->cl_softrtry)
task->tk_flags |= RPC_TASK_SOFT;
if (!clnt->cl_intr)
@@ -860,9 +864,7 @@ static void rpc_free_task(struct rcu_head *rcu)
}
/*
- * Create a new task for the specified client. We have to
- * clean up after an allocation failure, as the client may
- * have specified "oneshot".
+ * Create a new task for the specified client.
*/
struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata)
{
@@ -870,7 +872,7 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc
task = rpc_alloc_task();
if (!task)
- goto cleanup;
+ goto out;
rpc_init_task(task, clnt, flags, tk_ops, calldata);
@@ -878,16 +880,6 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc
task->tk_flags |= RPC_TASK_DYNAMIC;
out:
return task;
-
-cleanup:
- /* Check whether to release the client */
- if (clnt) {
- printk("rpc_new_task: failed, users=%d, oneshot=%d\n",
- atomic_read(&clnt->cl_users), clnt->cl_oneshot);
- atomic_inc(&clnt->cl_users); /* pretend we were used ... */
- rpc_release_client(clnt);
- }
- goto out;
}
@@ -920,11 +912,13 @@ static void rpc_release_task(struct rpc_task *task)
#endif
dprintk("RPC: %5u release task\n", task->tk_pid);
- /* Remove from global task list */
- spin_lock(&rpc_sched_lock);
- list_del(&task->tk_task);
- spin_unlock(&rpc_sched_lock);
-
+ if (!list_empty(&task->tk_task)) {
+ struct rpc_clnt *clnt = task->tk_client;
+ /* Remove from client task list */
+ spin_lock(&clnt->cl_lock);
+ list_del(&task->tk_task);
+ spin_unlock(&clnt->cl_lock);
+ }
BUG_ON (RPC_IS_QUEUED(task));
/* Synchronously delete any running timer */
@@ -939,29 +933,6 @@ static void rpc_release_task(struct rpc_task *task)
rpc_put_task(task);
}
-/**
- * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it
- * @clnt: pointer to RPC client
- * @flags: RPC flags
- * @ops: RPC call ops
- * @data: user call data
- */
-struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags,
- const struct rpc_call_ops *ops,
- void *data)
-{
- struct rpc_task *task;
- task = rpc_new_task(clnt, flags, ops, data);
- if (task == NULL) {
- rpc_release_calldata(ops, data);
- return ERR_PTR(-ENOMEM);
- }
- atomic_inc(&task->tk_count);
- rpc_execute(task);
- return task;
-}
-EXPORT_SYMBOL(rpc_run_task);
-
/*
* Kill all tasks for the given client.
* XXX: kill their descendants as well?
@@ -969,44 +940,25 @@ EXPORT_SYMBOL(rpc_run_task);
void rpc_killall_tasks(struct rpc_clnt *clnt)
{
struct rpc_task *rovr;
- struct list_head *le;
- dprintk("RPC: killing all tasks for client %p\n", clnt);
+ if (list_empty(&clnt->cl_tasks))
+ return;
+ dprintk("RPC: killing all tasks for client %p\n", clnt);
/*
* Spin lock all_tasks to prevent changes...
*/
- spin_lock(&rpc_sched_lock);
- alltask_for_each(rovr, le, &all_tasks) {
+ spin_lock(&clnt->cl_lock);
+ list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) {
if (! RPC_IS_ACTIVATED(rovr))
continue;
- if (!clnt || rovr->tk_client == clnt) {
+ if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
rovr->tk_flags |= RPC_TASK_KILLED;
rpc_exit(rovr, -EIO);
rpc_wake_up_task(rovr);
}
}
- spin_unlock(&rpc_sched_lock);
-}
-
-static void rpciod_killall(void)
-{
- unsigned long flags;
-
- while (!list_empty(&all_tasks)) {
- clear_thread_flag(TIF_SIGPENDING);
- rpc_killall_tasks(NULL);
- flush_workqueue(rpciod_workqueue);
- if (!list_empty(&all_tasks)) {
- dprintk("RPC: rpciod_killall: waiting for tasks "
- "to exit\n");
- yield();
- }
- }
-
- spin_lock_irqsave(&current->sighand->siglock, flags);
- recalc_sigpending();
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ spin_unlock(&clnt->cl_lock);
}
/*
@@ -1018,28 +970,27 @@ rpciod_up(void)
struct workqueue_struct *wq;
int error = 0;
+ if (atomic_inc_not_zero(&rpciod_users))
+ return 0;
+
mutex_lock(&rpciod_mutex);
- dprintk("RPC: rpciod_up: users %u\n", rpciod_users);
- rpciod_users++;
- if (rpciod_workqueue)
- goto out;
- /*
- * If there's no pid, we should be the first user.
- */
- if (rpciod_users > 1)
- printk(KERN_WARNING "rpciod_up: no workqueue, %u users??\n", rpciod_users);
+
+ /* Guard against races with rpciod_down() */
+ if (rpciod_workqueue != NULL)
+ goto out_ok;
/*
* Create the rpciod thread and wait for it to start.
*/
+ dprintk("RPC: creating workqueue rpciod\n");
error = -ENOMEM;
wq = create_workqueue("rpciod");
- if (wq == NULL) {
- printk(KERN_WARNING "rpciod_up: create workqueue failed, error=%d\n", error);
- rpciod_users--;
+ if (wq == NULL)
goto out;
- }
+
rpciod_workqueue = wq;
error = 0;
+out_ok:
+ atomic_inc(&rpciod_users);
out:
mutex_unlock(&rpciod_mutex);
return error;
@@ -1048,59 +999,19 @@ out:
void
rpciod_down(void)
{
+ if (!atomic_dec_and_test(&rpciod_users))
+ return;
+
mutex_lock(&rpciod_mutex);
- dprintk("RPC: rpciod_down sema %u\n", rpciod_users);
- if (rpciod_users) {
- if (--rpciod_users)
- goto out;
- } else
- printk(KERN_WARNING "rpciod_down: no users??\n");
+ dprintk("RPC: destroying workqueue rpciod\n");
- if (!rpciod_workqueue) {
- dprintk("RPC: rpciod_down: Nothing to do!\n");
- goto out;
+ if (atomic_read(&rpciod_users) == 0 && rpciod_workqueue != NULL) {
+ destroy_workqueue(rpciod_workqueue);
+ rpciod_workqueue = NULL;
}
- rpciod_killall();
-
- destroy_workqueue(rpciod_workqueue);
- rpciod_workqueue = NULL;
- out:
mutex_unlock(&rpciod_mutex);
}
-#ifdef RPC_DEBUG
-void rpc_show_tasks(void)
-{
- struct list_head *le;
- struct rpc_task *t;
-
- spin_lock(&rpc_sched_lock);
- if (list_empty(&all_tasks)) {
- spin_unlock(&rpc_sched_lock);
- return;
- }
- printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
- "-rpcwait -action- ---ops--\n");
- alltask_for_each(t, le, &all_tasks) {
- const char *rpc_waitq = "none";
-
- if (RPC_IS_QUEUED(t))
- rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
-
- printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
- t->tk_pid,
- (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
- t->tk_flags, t->tk_status,
- t->tk_client,
- (t->tk_client ? t->tk_client->cl_prog : 0),
- t->tk_rqstp, t->tk_timeout,
- rpc_waitq,
- t->tk_action, t->tk_ops);
- }
- spin_unlock(&rpc_sched_lock);
-}
-#endif
-
void
rpc_destroy_mempool(void)
{
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 73075dec83c..384c4ad5ab8 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -28,15 +28,11 @@ EXPORT_SYMBOL(rpc_init_task);
EXPORT_SYMBOL(rpc_sleep_on);
EXPORT_SYMBOL(rpc_wake_up_next);
EXPORT_SYMBOL(rpc_wake_up_task);
-EXPORT_SYMBOL(rpciod_down);
-EXPORT_SYMBOL(rpciod_up);
-EXPORT_SYMBOL(rpc_new_task);
EXPORT_SYMBOL(rpc_wake_up_status);
/* RPC client functions */
EXPORT_SYMBOL(rpc_clone_client);
EXPORT_SYMBOL(rpc_bind_new_program);
-EXPORT_SYMBOL(rpc_destroy_client);
EXPORT_SYMBOL(rpc_shutdown_client);
EXPORT_SYMBOL(rpc_killall_tasks);
EXPORT_SYMBOL(rpc_call_sync);
@@ -61,7 +57,7 @@ EXPORT_SYMBOL(rpcauth_unregister);
EXPORT_SYMBOL(rpcauth_create);
EXPORT_SYMBOL(rpcauth_lookupcred);
EXPORT_SYMBOL(rpcauth_lookup_credcache);
-EXPORT_SYMBOL(rpcauth_free_credcache);
+EXPORT_SYMBOL(rpcauth_destroy_credcache);
EXPORT_SYMBOL(rpcauth_init_credcache);
EXPORT_SYMBOL(put_rpccred);
@@ -156,6 +152,7 @@ init_sunrpc(void)
cache_register(&ip_map_cache);
cache_register(&unix_gid_cache);
init_socket_xprt();
+ rpcauth_init_module();
out:
return err;
}
@@ -163,6 +160,7 @@ out:
static void __exit
cleanup_sunrpc(void)
{
+ rpcauth_remove_module();
cleanup_socket_xprt();
unregister_rpc_pipefs();
rpc_destroy_mempool();
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e673ef99390..55ea6df069d 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -814,7 +814,7 @@ svc_process(struct svc_rqst *rqstp)
rqstp->rq_res.tail[0].iov_base = NULL;
rqstp->rq_res.tail[0].iov_len = 0;
/* Will be turned off only in gss privacy case: */
- rqstp->rq_sendfile_ok = 1;
+ rqstp->rq_splice_ok = 1;
/* tcp needs a space for the record length... */
if (rqstp->rq_prot == IPPROTO_TCP)
svc_putnl(resv, 0);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 5baf48de255..64b9b8c743c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -644,6 +644,7 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
struct msghdr msg = {
.msg_flags = MSG_DONTWAIT,
};
+ struct sockaddr *sin;
int len;
len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
@@ -654,6 +655,19 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
rqstp->rq_addrlen = svsk->sk_remotelen;
+ /* Destination address in request is needed for binding the
+ * source address in RPC callbacks later.
+ */
+ sin = (struct sockaddr *)&svsk->sk_local;
+ switch (sin->sa_family) {
+ case AF_INET:
+ rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
+ break;
+ case AF_INET6:
+ rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
+ break;
+ }
+
dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
svsk, iov[0].iov_base, iov[0].iov_len, len);
@@ -1064,6 +1078,12 @@ svc_tcp_accept(struct svc_sock *svsk)
goto failed;
memcpy(&newsvsk->sk_remote, sin, slen);
newsvsk->sk_remotelen = slen;
+ err = kernel_getsockname(newsock, sin, &slen);
+ if (unlikely(err < 0)) {
+ dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err);
+ slen = offsetof(struct sockaddr, sa_data);
+ }
+ memcpy(&newsvsk->sk_local, sin, slen);
svc_sock_received(newsvsk);
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 5b05b73e4c1..c8c2edccad7 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -127,7 +127,7 @@ static void xprt_clear_locked(struct rpc_xprt *xprt)
clear_bit(XPRT_LOCKED, &xprt->state);
smp_mb__after_clear_bit();
} else
- schedule_work(&xprt->task_cleanup);
+ queue_work(rpciod_workqueue, &xprt->task_cleanup);
}
/*
@@ -515,7 +515,7 @@ xprt_init_autodisconnect(unsigned long data)
if (xprt_connecting(xprt))
xprt_release_write(xprt, NULL);
else
- schedule_work(&xprt->task_cleanup);
+ queue_work(rpciod_workqueue, &xprt->task_cleanup);
return;
out_abort:
spin_unlock(&xprt->transport_lock);
@@ -886,27 +886,24 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i
/**
* xprt_create_transport - create an RPC transport
- * @proto: requested transport protocol
- * @ap: remote peer address
- * @size: length of address
- * @to: timeout parameters
+ * @args: rpc transport creation arguments
*
*/
-struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to)
+struct rpc_xprt *xprt_create_transport(struct rpc_xprtsock_create *args)
{
struct rpc_xprt *xprt;
struct rpc_rqst *req;
- switch (proto) {
+ switch (args->proto) {
case IPPROTO_UDP:
- xprt = xs_setup_udp(ap, size, to);
+ xprt = xs_setup_udp(args);
break;
case IPPROTO_TCP:
- xprt = xs_setup_tcp(ap, size, to);
+ xprt = xs_setup_tcp(args);
break;
default:
printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n",
- proto);
+ args->proto);
return ERR_PTR(-EIO);
}
if (IS_ERR(xprt)) {
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index cc33c5880ab..4ae7eed7f61 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -235,6 +235,7 @@ struct sock_xprt {
* Connection of transports
*/
struct delayed_work connect_worker;
+ struct sockaddr_storage addr;
unsigned short port;
/*
@@ -653,8 +654,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
dprintk("RPC: xs_destroy xprt %p\n", xprt);
- cancel_delayed_work(&transport->connect_worker);
- flush_scheduled_work();
+ cancel_rearming_delayed_work(&transport->connect_worker);
xprt_disconnect(xprt);
xs_close(xprt);
@@ -1001,7 +1001,7 @@ static void xs_tcp_state_change(struct sock *sk)
/* Try to schedule an autoclose RPC calls */
set_bit(XPRT_CLOSE_WAIT, &xprt->state);
if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
- schedule_work(&xprt->task_cleanup);
+ queue_work(rpciod_workqueue, &xprt->task_cleanup);
default:
xprt_disconnect(xprt);
}
@@ -1146,31 +1146,36 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
sap->sin_port = htons(port);
}
-static int xs_bindresvport(struct sock_xprt *transport, struct socket *sock)
+static int xs_bind(struct sock_xprt *transport, struct socket *sock)
{
struct sockaddr_in myaddr = {
.sin_family = AF_INET,
};
+ struct sockaddr_in *sa;
int err;
unsigned short port = transport->port;
+ if (!transport->xprt.resvport)
+ port = 0;
+ sa = (struct sockaddr_in *)&transport->addr;
+ myaddr.sin_addr = sa->sin_addr;
do {
myaddr.sin_port = htons(port);
err = kernel_bind(sock, (struct sockaddr *) &myaddr,
sizeof(myaddr));
+ if (!transport->xprt.resvport)
+ break;
if (err == 0) {
transport->port = port;
- dprintk("RPC: xs_bindresvport bound to port %u\n",
- port);
- return 0;
+ break;
}
if (port <= xprt_min_resvport)
port = xprt_max_resvport;
else
port--;
} while (err == -EADDRINUSE && port != transport->port);
-
- dprintk("RPC: can't bind to reserved port (%d).\n", -err);
+ dprintk("RPC: xs_bind "NIPQUAD_FMT":%u: %s (%d)\n",
+ NIPQUAD(myaddr.sin_addr), port, err ? "failed" : "ok", err);
return err;
}
@@ -1229,7 +1234,7 @@ static void xs_udp_connect_worker(struct work_struct *work)
}
xs_reclassify_socket(sock);
- if (xprt->resvport && xs_bindresvport(transport, sock) < 0) {
+ if (xs_bind(transport, sock)) {
sock_release(sock);
goto out;
}
@@ -1316,7 +1321,7 @@ static void xs_tcp_connect_worker(struct work_struct *work)
}
xs_reclassify_socket(sock);
- if (xprt->resvport && xs_bindresvport(transport, sock) < 0) {
+ if (xs_bind(transport, sock)) {
sock_release(sock);
goto out;
}
@@ -1410,18 +1415,16 @@ static void xs_connect(struct rpc_task *task)
dprintk("RPC: xs_connect delayed xprt %p for %lu "
"seconds\n",
xprt, xprt->reestablish_timeout / HZ);
- schedule_delayed_work(&transport->connect_worker,
- xprt->reestablish_timeout);
+ queue_delayed_work(rpciod_workqueue,
+ &transport->connect_worker,
+ xprt->reestablish_timeout);
xprt->reestablish_timeout <<= 1;
if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
} else {
dprintk("RPC: xs_connect scheduled xprt %p\n", xprt);
- schedule_delayed_work(&transport->connect_worker, 0);
-
- /* flush_scheduled_work can sleep... */
- if (!RPC_IS_ASYNC(task))
- flush_scheduled_work();
+ queue_delayed_work(rpciod_workqueue,
+ &transport->connect_worker, 0);
}
}
@@ -1476,7 +1479,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
.set_buffer_size = xs_udp_set_buffer_size,
.reserve_xprt = xprt_reserve_xprt_cong,
.release_xprt = xprt_release_xprt_cong,
- .rpcbind = rpcb_getport,
+ .rpcbind = rpcb_getport_async,
.set_port = xs_set_port,
.connect = xs_connect,
.buf_alloc = rpc_malloc,
@@ -1493,7 +1496,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
static struct rpc_xprt_ops xs_tcp_ops = {
.reserve_xprt = xprt_reserve_xprt,
.release_xprt = xs_tcp_release_xprt,
- .rpcbind = rpcb_getport,
+ .rpcbind = rpcb_getport_async,
.set_port = xs_set_port,
.connect = xs_connect,
.buf_alloc = rpc_malloc,
@@ -1505,12 +1508,12 @@ static struct rpc_xprt_ops xs_tcp_ops = {
.print_stats = xs_tcp_print_stats,
};
-static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, unsigned int slot_table_size)
+static struct rpc_xprt *xs_setup_xprt(struct rpc_xprtsock_create *args, unsigned int slot_table_size)
{
struct rpc_xprt *xprt;
struct sock_xprt *new;
- if (addrlen > sizeof(xprt->addr)) {
+ if (args->addrlen > sizeof(xprt->addr)) {
dprintk("RPC: xs_setup_xprt: address too large\n");
return ERR_PTR(-EBADF);
}
@@ -1532,8 +1535,10 @@ static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, uns
return ERR_PTR(-ENOMEM);
}
- memcpy(&xprt->addr, addr, addrlen);
- xprt->addrlen = addrlen;
+ memcpy(&xprt->addr, args->dstaddr, args->addrlen);
+ xprt->addrlen = args->addrlen;
+ if (args->srcaddr)
+ memcpy(&new->addr, args->srcaddr, args->addrlen);
new->port = xs_get_random_port();
return xprt;
@@ -1541,22 +1546,20 @@ static struct rpc_xprt *xs_setup_xprt(struct sockaddr *addr, size_t addrlen, uns
/**
* xs_setup_udp - Set up transport to use a UDP socket
- * @addr: address of remote server
- * @addrlen: length of address in bytes
- * @to: timeout parameters
+ * @args: rpc transport creation arguments
*
*/
-struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_udp(struct rpc_xprtsock_create *args)
{
struct rpc_xprt *xprt;
struct sock_xprt *transport;
- xprt = xs_setup_xprt(addr, addrlen, xprt_udp_slot_table_entries);
+ xprt = xs_setup_xprt(args, xprt_udp_slot_table_entries);
if (IS_ERR(xprt))
return xprt;
transport = container_of(xprt, struct sock_xprt, xprt);
- if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
+ if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0)
xprt_set_bound(xprt);
xprt->prot = IPPROTO_UDP;
@@ -1572,8 +1575,8 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_
xprt->ops = &xs_udp_ops;
- if (to)
- xprt->timeout = *to;
+ if (args->timeout)
+ xprt->timeout = *args->timeout;
else
xprt_set_timeout(&xprt->timeout, 5, 5 * HZ);
@@ -1586,22 +1589,20 @@ struct rpc_xprt *xs_setup_udp(struct sockaddr *addr, size_t addrlen, struct rpc_
/**
* xs_setup_tcp - Set up transport to use a TCP socket
- * @addr: address of remote server
- * @addrlen: length of address in bytes
- * @to: timeout parameters
+ * @args: rpc transport creation arguments
*
*/
-struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_timeout *to)
+struct rpc_xprt *xs_setup_tcp(struct rpc_xprtsock_create *args)
{
struct rpc_xprt *xprt;
struct sock_xprt *transport;
- xprt = xs_setup_xprt(addr, addrlen, xprt_tcp_slot_table_entries);
+ xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries);
if (IS_ERR(xprt))
return xprt;
transport = container_of(xprt, struct sock_xprt, xprt);
- if (ntohs(((struct sockaddr_in *)addr)->sin_port) != 0)
+ if (ntohs(((struct sockaddr_in *)args->dstaddr)->sin_port) != 0)
xprt_set_bound(xprt);
xprt->prot = IPPROTO_TCP;
@@ -1616,8 +1617,8 @@ struct rpc_xprt *xs_setup_tcp(struct sockaddr *addr, size_t addrlen, struct rpc_
xprt->ops = &xs_tcp_ops;
- if (to)
- xprt->timeout = *to;
+ if (args->timeout)
+ xprt->timeout = *args->timeout;
else
xprt_set_timeout(&xprt->timeout, 2, 60 * HZ);
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 77d2d9ce896..711ca4b1f05 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -1,8 +1,8 @@
/*
* net/tipc/eth_media.c: Ethernet bearer support for TIPC
*
- * Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2001-2007, Ericsson AB
+ * Copyright (c) 2005-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -87,6 +87,9 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
/**
* recv_msg - handle incoming TIPC message from an Ethernet interface
*
+ * Accept only packets explicitly sent to this node, or broadcast packets;
+ * ignores packets sent using Ethernet multicast, and traffic sent to other
+ * nodes (which can happen if interface is running in promiscuous mode).
* Routine truncates any Ethernet padding/CRC appended to the message,
* and ensures message size matches actual length
*/
@@ -98,9 +101,7 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
u32 size;
if (likely(eb_ptr->bearer)) {
- if (likely(!dev->promiscuity) ||
- !memcmp(skb_mac_header(buf), dev->dev_addr, ETH_ALEN) ||
- !memcmp(skb_mac_header(buf), dev->broadcast, ETH_ALEN)) {
+ if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
size = msg_size((struct tipc_msg *)buf->data);
skb_trim(buf, size);
if (likely(buf->len == size)) {
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2124f32ef29..5adfdfd49d6 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1,8 +1,8 @@
/*
* net/tipc/link.c: TIPC link code
*
- * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2004-2006, Wind River Systems
+ * Copyright (c) 1996-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1260,7 +1260,7 @@ again:
* (Must not hold any locks while building message.)
*/
- res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
+ res = msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,
!sender->user_port, &buf);
read_lock_bh(&tipc_net_lock);
@@ -1271,7 +1271,7 @@ again:
if (likely(l_ptr)) {
if (likely(buf)) {
res = link_send_buf_fast(l_ptr, buf,
- &sender->max_pkt);
+ &sender->publ.max_pkt);
if (unlikely(res < 0))
buf_discard(buf);
exit:
@@ -1299,12 +1299,12 @@ exit:
* then re-try fast path or fragment the message
*/
- sender->max_pkt = link_max_pkt(l_ptr);
+ sender->publ.max_pkt = link_max_pkt(l_ptr);
tipc_node_unlock(node);
read_unlock_bh(&tipc_net_lock);
- if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
+ if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt)
goto again;
return link_send_sections_long(sender, msg_sect,
@@ -1357,7 +1357,7 @@ static int link_send_sections_long(struct port *sender,
again:
fragm_no = 1;
- max_pkt = sender->max_pkt - INT_H_SIZE;
+ max_pkt = sender->publ.max_pkt - INT_H_SIZE;
/* leave room for tunnel header in case of link changeover */
fragm_sz = max_pkt - INT_H_SIZE;
/* leave room for fragmentation header in each fragment */
@@ -1463,7 +1463,7 @@ error:
goto reject;
}
if (link_max_pkt(l_ptr) < max_pkt) {
- sender->max_pkt = link_max_pkt(l_ptr);
+ sender->publ.max_pkt = link_max_pkt(l_ptr);
tipc_node_unlock(node);
for (; buf_chain; buf_chain = buf) {
buf = buf_chain->next;
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 4cdafa2d1d4..6a7f7b4c259 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -60,7 +60,7 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
rep_nlh = nlmsg_hdr(rep_buf);
memcpy(rep_nlh, req_nlh, hdr_space);
rep_nlh->nlmsg_len = rep_buf->len;
- genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid);
+ genlmsg_unicast(rep_buf, NETLINK_CB(skb).pid);
}
return 0;
diff --git a/net/tipc/port.c b/net/tipc/port.c
index bcd5da00737..5d2b9ce84d0 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -1,8 +1,8 @@
/*
* net/tipc/port.c: TIPC port code
*
- * Copyright (c) 1992-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 1992-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -239,6 +239,8 @@ u32 tipc_createport_raw(void *usr_handle,
}
tipc_port_lock(ref);
+ p_ptr->publ.usr_handle = usr_handle;
+ p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
p_ptr->publ.ref = ref;
msg = &p_ptr->publ.phdr;
msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0);
@@ -248,11 +250,9 @@ u32 tipc_createport_raw(void *usr_handle,
msg_set_importance(msg,importance);
p_ptr->last_in_seqno = 41;
p_ptr->sent = 1;
- p_ptr->publ.usr_handle = usr_handle;
INIT_LIST_HEAD(&p_ptr->wait_list);
INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
p_ptr->congested_link = NULL;
- p_ptr->max_pkt = MAX_PKT_DEFAULT;
p_ptr->dispatcher = dispatcher;
p_ptr->wakeup = wakeup;
p_ptr->user_port = NULL;
@@ -1243,7 +1243,7 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
res = TIPC_OK;
exit:
tipc_port_unlock(p_ptr);
- p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
+ p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref);
return res;
}
diff --git a/net/tipc/port.h b/net/tipc/port.h
index 7ef4d64b32f..e5f8c16429b 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -1,8 +1,8 @@
/*
* net/tipc/port.h: Include file for TIPC port code
*
- * Copyright (c) 1994-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 1994-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -81,7 +81,6 @@ struct user_port {
* @acked:
* @publications: list of publications for port
* @pub_count: total # of publications port has made during its lifetime
- * @max_pkt: maximum packet size "hint" used when building messages sent by port
* @probing_state:
* @probing_interval:
* @last_in_seqno:
@@ -102,7 +101,6 @@ struct port {
u32 acked;
struct list_head publications;
u32 pub_count;
- u32 max_pkt;
u32 probing_state;
u32 probing_interval;
u32 last_in_seqno;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 45832fb75ea..4a8f37f4876 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1,8 +1,8 @@
/*
* net/tipc/socket.c: TIPC socket API
*
- * Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2004-2006, Wind River Systems
+ * Copyright (c) 2001-2007, Ericsson AB
+ * Copyright (c) 2004-2007, Wind River Systems
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -607,23 +607,24 @@ exit:
static int send_stream(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, size_t total_len)
{
+ struct tipc_port *tport;
struct msghdr my_msg;
struct iovec my_iov;
struct iovec *curr_iov;
int curr_iovlen;
char __user *curr_start;
+ u32 hdr_size;
int curr_left;
int bytes_to_send;
int bytes_sent;
int res;
- if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
- return send_packet(iocb, sock, m, total_len);
-
- /* Can only send large data streams if already connected */
+ /* Handle special cases where there is no connection */
if (unlikely(sock->state != SS_CONNECTED)) {
- if (sock->state == SS_DISCONNECTING)
+ if (sock->state == SS_UNCONNECTED)
+ return send_packet(iocb, sock, m, total_len);
+ else if (sock->state == SS_DISCONNECTING)
return -EPIPE;
else
return -ENOTCONN;
@@ -648,17 +649,25 @@ static int send_stream(struct kiocb *iocb, struct socket *sock,
my_msg.msg_name = NULL;
bytes_sent = 0;
+ tport = tipc_sk(sock->sk)->p;
+ hdr_size = msg_hdr_sz(&tport->phdr);
+
while (curr_iovlen--) {
curr_start = curr_iov->iov_base;
curr_left = curr_iov->iov_len;
while (curr_left) {
- bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE)
- ? curr_left : TIPC_MAX_USER_MSG_SIZE;
+ bytes_to_send = tport->max_pkt - hdr_size;
+ if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE)
+ bytes_to_send = TIPC_MAX_USER_MSG_SIZE;
+ if (curr_left < bytes_to_send)
+ bytes_to_send = curr_left;
my_iov.iov_base = curr_start;
my_iov.iov_len = bytes_to_send;
if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
- return bytes_sent ? bytes_sent : res;
+ if (bytes_sent != 0)
+ res = bytes_sent;
+ return res;
}
curr_left -= bytes_to_send;
curr_start += bytes_to_send;
@@ -1600,33 +1609,6 @@ static int getsockopt(struct socket *sock,
}
/**
- * Placeholders for non-implemented functionality
- *
- * Returns error code (POSIX-compliant where defined)
- */
-
-static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
-{
- return -EINVAL;
-}
-
-static int no_mmap(struct file *file, struct socket *sock,
- struct vm_area_struct *vma)
-{
- return -EINVAL;
-}
-static ssize_t no_sendpage(struct socket *sock, struct page *page,
- int offset, size_t size, int flags)
-{
- return -EINVAL;
-}
-
-static int no_skpair(struct socket *s1, struct socket *s2)
-{
- return -EOPNOTSUPP;
-}
-
-/**
* Protocol switches for the various types of TIPC sockets
*/
@@ -1636,19 +1618,19 @@ static struct proto_ops msg_ops = {
.release = release,
.bind = bind,
.connect = connect,
- .socketpair = no_skpair,
+ .socketpair = sock_no_socketpair,
.accept = accept,
.getname = get_name,
.poll = poll,
- .ioctl = ioctl,
+ .ioctl = sock_no_ioctl,
.listen = listen,
.shutdown = shutdown,
.setsockopt = setsockopt,
.getsockopt = getsockopt,
.sendmsg = send_msg,
.recvmsg = recv_msg,
- .mmap = no_mmap,
- .sendpage = no_sendpage
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage
};
static struct proto_ops packet_ops = {
@@ -1657,19 +1639,19 @@ static struct proto_ops packet_ops = {
.release = release,
.bind = bind,
.connect = connect,
- .socketpair = no_skpair,
+ .socketpair = sock_no_socketpair,
.accept = accept,
.getname = get_name,
.poll = poll,
- .ioctl = ioctl,
+ .ioctl = sock_no_ioctl,
.listen = listen,
.shutdown = shutdown,
.setsockopt = setsockopt,
.getsockopt = getsockopt,
.sendmsg = send_packet,
.recvmsg = recv_msg,
- .mmap = no_mmap,
- .sendpage = no_sendpage
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage
};
static struct proto_ops stream_ops = {
@@ -1678,19 +1660,19 @@ static struct proto_ops stream_ops = {
.release = release,
.bind = bind,
.connect = connect,
- .socketpair = no_skpair,
+ .socketpair = sock_no_socketpair,
.accept = accept,
.getname = get_name,
.poll = poll,
- .ioctl = ioctl,
+ .ioctl = sock_no_ioctl,
.listen = listen,
.shutdown = shutdown,
.setsockopt = setsockopt,
.getsockopt = getsockopt,
.sendmsg = send_stream,
.recvmsg = recv_stream,
- .mmap = no_mmap,
- .sendpage = no_sendpage
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage
};
static struct net_proto_family tipc_family_ops = {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index fc12ba51c1f..65ebccc0a69 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -174,11 +174,11 @@ static struct sock *unix_peer_get(struct sock *s)
{
struct sock *peer;
- unix_state_rlock(s);
+ unix_state_lock(s);
peer = unix_peer(s);
if (peer)
sock_hold(peer);
- unix_state_runlock(s);
+ unix_state_unlock(s);
return peer;
}
@@ -369,7 +369,7 @@ static int unix_release_sock (struct sock *sk, int embrion)
unix_remove_socket(sk);
/* Clear state */
- unix_state_wlock(sk);
+ unix_state_lock(sk);
sock_orphan(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
dentry = u->dentry;
@@ -378,7 +378,7 @@ static int unix_release_sock (struct sock *sk, int embrion)
u->mnt = NULL;
state = sk->sk_state;
sk->sk_state = TCP_CLOSE;
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
wake_up_interruptible_all(&u->peer_wait);
@@ -386,12 +386,12 @@ static int unix_release_sock (struct sock *sk, int embrion)
if (skpair!=NULL) {
if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) {
- unix_state_wlock(skpair);
+ unix_state_lock(skpair);
/* No more writes */
skpair->sk_shutdown = SHUTDOWN_MASK;
if (!skb_queue_empty(&sk->sk_receive_queue) || embrion)
skpair->sk_err = ECONNRESET;
- unix_state_wunlock(skpair);
+ unix_state_unlock(skpair);
skpair->sk_state_change(skpair);
read_lock(&skpair->sk_callback_lock);
sk_wake_async(skpair,1,POLL_HUP);
@@ -448,7 +448,7 @@ static int unix_listen(struct socket *sock, int backlog)
err = -EINVAL;
if (!u->addr)
goto out; /* No listens on an unbound socket */
- unix_state_wlock(sk);
+ unix_state_lock(sk);
if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN)
goto out_unlock;
if (backlog > sk->sk_max_ack_backlog)
@@ -462,7 +462,7 @@ static int unix_listen(struct socket *sock, int backlog)
err = 0;
out_unlock:
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
out:
return err;
}
@@ -592,7 +592,8 @@ static struct sock * unix_create1(struct socket *sock)
u->dentry = NULL;
u->mnt = NULL;
spin_lock_init(&u->lock);
- atomic_set(&u->inflight, sock ? 0 : -1);
+ atomic_set(&u->inflight, 0);
+ INIT_LIST_HEAD(&u->link);
mutex_init(&u->readlock); /* single task reading lock */
init_waitqueue_head(&u->peer_wait);
unix_insert_socket(unix_sockets_unbound, sk);
@@ -858,6 +859,31 @@ out_mknod_parent:
goto out_up;
}
+static void unix_state_double_lock(struct sock *sk1, struct sock *sk2)
+{
+ if (unlikely(sk1 == sk2) || !sk2) {
+ unix_state_lock(sk1);
+ return;
+ }
+ if (sk1 < sk2) {
+ unix_state_lock(sk1);
+ unix_state_lock_nested(sk2);
+ } else {
+ unix_state_lock(sk2);
+ unix_state_lock_nested(sk1);
+ }
+}
+
+static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2)
+{
+ if (unlikely(sk1 == sk2) || !sk2) {
+ unix_state_unlock(sk1);
+ return;
+ }
+ unix_state_unlock(sk1);
+ unix_state_unlock(sk2);
+}
+
static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
int alen, int flags)
{
@@ -877,11 +903,19 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
!unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
goto out;
+restart:
other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
if (!other)
goto out;
- unix_state_wlock(sk);
+ unix_state_double_lock(sk, other);
+
+ /* Apparently VFS overslept socket death. Retry. */
+ if (sock_flag(other, SOCK_DEAD)) {
+ unix_state_double_unlock(sk, other);
+ sock_put(other);
+ goto restart;
+ }
err = -EPERM;
if (!unix_may_send(sk, other))
@@ -896,7 +930,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
* 1003.1g breaking connected state with AF_UNSPEC
*/
other = NULL;
- unix_state_wlock(sk);
+ unix_state_double_lock(sk, other);
}
/*
@@ -905,19 +939,19 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
if (unix_peer(sk)) {
struct sock *old_peer = unix_peer(sk);
unix_peer(sk)=other;
- unix_state_wunlock(sk);
+ unix_state_double_unlock(sk, other);
if (other != old_peer)
unix_dgram_disconnected(sk, old_peer);
sock_put(old_peer);
} else {
unix_peer(sk)=other;
- unix_state_wunlock(sk);
+ unix_state_double_unlock(sk, other);
}
return 0;
out_unlock:
- unix_state_wunlock(sk);
+ unix_state_double_unlock(sk, other);
sock_put(other);
out:
return err;
@@ -936,7 +970,7 @@ static long unix_wait_for_peer(struct sock *other, long timeo)
(skb_queue_len(&other->sk_receive_queue) >
other->sk_max_ack_backlog);
- unix_state_runlock(other);
+ unix_state_unlock(other);
if (sched)
timeo = schedule_timeout(timeo);
@@ -994,11 +1028,11 @@ restart:
goto out;
/* Latch state of peer */
- unix_state_rlock(other);
+ unix_state_lock(other);
/* Apparently VFS overslept socket death. Retry. */
if (sock_flag(other, SOCK_DEAD)) {
- unix_state_runlock(other);
+ unix_state_unlock(other);
sock_put(other);
goto restart;
}
@@ -1048,18 +1082,18 @@ restart:
goto out_unlock;
}
- unix_state_wlock_nested(sk);
+ unix_state_lock_nested(sk);
if (sk->sk_state != st) {
- unix_state_wunlock(sk);
- unix_state_runlock(other);
+ unix_state_unlock(sk);
+ unix_state_unlock(other);
sock_put(other);
goto restart;
}
err = security_unix_stream_connect(sock, other->sk_socket, newsk);
if (err) {
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
goto out_unlock;
}
@@ -1096,23 +1130,20 @@ restart:
smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */
unix_peer(sk) = newsk;
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
/* take ten and and send info to listening sock */
spin_lock(&other->sk_receive_queue.lock);
__skb_queue_tail(&other->sk_receive_queue, skb);
- /* Undo artificially decreased inflight after embrion
- * is installed to listening socket. */
- atomic_inc(&newu->inflight);
spin_unlock(&other->sk_receive_queue.lock);
- unix_state_runlock(other);
+ unix_state_unlock(other);
other->sk_data_ready(other, 0);
sock_put(other);
return 0;
out_unlock:
if (other)
- unix_state_runlock(other);
+ unix_state_unlock(other);
out:
if (skb)
@@ -1178,10 +1209,10 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
wake_up_interruptible(&unix_sk(sk)->peer_wait);
/* attach accepted sock to socket */
- unix_state_wlock(tsk);
+ unix_state_lock(tsk);
newsock->state = SS_CONNECTED;
sock_graft(tsk, newsock);
- unix_state_wunlock(tsk);
+ unix_state_unlock(tsk);
return 0;
out:
@@ -1208,7 +1239,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
}
u = unix_sk(sk);
- unix_state_rlock(sk);
+ unix_state_lock(sk);
if (!u->addr) {
sunaddr->sun_family = AF_UNIX;
sunaddr->sun_path[0] = 0;
@@ -1219,7 +1250,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
*uaddr_len = addr->len;
memcpy(sunaddr, addr->name, *uaddr_len);
}
- unix_state_runlock(sk);
+ unix_state_unlock(sk);
sock_put(sk);
out:
return err;
@@ -1337,7 +1368,7 @@ restart:
goto out_free;
}
- unix_state_rlock(other);
+ unix_state_lock(other);
err = -EPERM;
if (!unix_may_send(sk, other))
goto out_unlock;
@@ -1347,20 +1378,20 @@ restart:
* Check with 1003.1g - what should
* datagram error
*/
- unix_state_runlock(other);
+ unix_state_unlock(other);
sock_put(other);
err = 0;
- unix_state_wlock(sk);
+ unix_state_lock(sk);
if (unix_peer(sk) == other) {
unix_peer(sk)=NULL;
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
unix_dgram_disconnected(sk, other);
sock_put(other);
err = -ECONNREFUSED;
} else {
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
}
other = NULL;
@@ -1397,14 +1428,14 @@ restart:
}
skb_queue_tail(&other->sk_receive_queue, skb);
- unix_state_runlock(other);
+ unix_state_unlock(other);
other->sk_data_ready(other, len);
sock_put(other);
scm_destroy(siocb->scm);
return len;
out_unlock:
- unix_state_runlock(other);
+ unix_state_unlock(other);
out_free:
kfree_skb(skb);
out:
@@ -1494,14 +1525,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto out_err;
}
- unix_state_rlock(other);
+ unix_state_lock(other);
if (sock_flag(other, SOCK_DEAD) ||
(other->sk_shutdown & RCV_SHUTDOWN))
goto pipe_err_free;
skb_queue_tail(&other->sk_receive_queue, skb);
- unix_state_runlock(other);
+ unix_state_unlock(other);
other->sk_data_ready(other, size);
sent+=size;
}
@@ -1512,7 +1543,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
return sent;
pipe_err_free:
- unix_state_runlock(other);
+ unix_state_unlock(other);
kfree_skb(skb);
pipe_err:
if (sent==0 && !(msg->msg_flags&MSG_NOSIGNAL))
@@ -1641,7 +1672,7 @@ static long unix_stream_data_wait(struct sock * sk, long timeo)
{
DEFINE_WAIT(wait);
- unix_state_rlock(sk);
+ unix_state_lock(sk);
for (;;) {
prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
@@ -1654,14 +1685,14 @@ static long unix_stream_data_wait(struct sock * sk, long timeo)
break;
set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
- unix_state_runlock(sk);
+ unix_state_unlock(sk);
timeo = schedule_timeout(timeo);
- unix_state_rlock(sk);
+ unix_state_lock(sk);
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
}
finish_wait(sk->sk_sleep, &wait);
- unix_state_runlock(sk);
+ unix_state_unlock(sk);
return timeo;
}
@@ -1711,20 +1742,23 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
int chunk;
struct sk_buff *skb;
+ unix_state_lock(sk);
skb = skb_dequeue(&sk->sk_receive_queue);
if (skb==NULL)
{
if (copied >= target)
- break;
+ goto unlock;
/*
* POSIX 1003.1g mandates this order.
*/
if ((err = sock_error(sk)) != 0)
- break;
+ goto unlock;
if (sk->sk_shutdown & RCV_SHUTDOWN)
- break;
+ goto unlock;
+
+ unix_state_unlock(sk);
err = -EAGAIN;
if (!timeo)
break;
@@ -1738,7 +1772,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
}
mutex_lock(&u->readlock);
continue;
+ unlock:
+ unix_state_unlock(sk);
+ break;
}
+ unix_state_unlock(sk);
if (check_creds) {
/* Never glue messages from different writers */
@@ -1816,12 +1854,12 @@ static int unix_shutdown(struct socket *sock, int mode)
mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
if (mode) {
- unix_state_wlock(sk);
+ unix_state_lock(sk);
sk->sk_shutdown |= mode;
other=unix_peer(sk);
if (other)
sock_hold(other);
- unix_state_wunlock(sk);
+ unix_state_unlock(sk);
sk->sk_state_change(sk);
if (other &&
@@ -1833,9 +1871,9 @@ static int unix_shutdown(struct socket *sock, int mode)
peer_mode |= SEND_SHUTDOWN;
if (mode&SEND_SHUTDOWN)
peer_mode |= RCV_SHUTDOWN;
- unix_state_wlock(other);
+ unix_state_lock(other);
other->sk_shutdown |= peer_mode;
- unix_state_wunlock(other);
+ unix_state_unlock(other);
other->sk_state_change(other);
read_lock(&other->sk_callback_lock);
if (peer_mode == SHUTDOWN_MASK)
@@ -1973,7 +2011,7 @@ static int unix_seq_show(struct seq_file *seq, void *v)
else {
struct sock *s = v;
struct unix_sock *u = unix_sk(s);
- unix_state_rlock(s);
+ unix_state_lock(s);
seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu",
s,
@@ -2001,14 +2039,14 @@ static int unix_seq_show(struct seq_file *seq, void *v)
for ( ; i < len; i++)
seq_putc(seq, u->addr->name->sun_path[i]);
}
- unix_state_runlock(s);
+ unix_state_unlock(s);
seq_putc(seq, '\n');
}
return 0;
}
-static struct seq_operations unix_seq_ops = {
+static const struct seq_operations unix_seq_ops = {
.start = unix_seq_start,
.next = unix_seq_next,
.stop = unix_seq_stop,
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index f20b7ea7c55..406b6433e46 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -62,6 +62,10 @@
* AV 1 Mar 1999
* Damn. Added missing check for ->dead in listen queues scanning.
*
+ * Miklos Szeredi 25 Jun 2007
+ * Reimplement with a cycle collecting algorithm. This should
+ * solve several problems with the previous code, like being racy
+ * wrt receive and holding up unrelated socket operations.
*/
#include <linux/kernel.h>
@@ -84,10 +88,9 @@
/* Internal data structures and random procedures: */
-#define GC_HEAD ((struct sock *)(-1))
-#define GC_ORPHAN ((struct sock *)(-3))
-
-static struct sock *gc_current = GC_HEAD; /* stack of objects to mark */
+static LIST_HEAD(gc_inflight_list);
+static LIST_HEAD(gc_candidates);
+static DEFINE_SPINLOCK(unix_gc_lock);
atomic_t unix_tot_inflight = ATOMIC_INIT(0);
@@ -122,8 +125,16 @@ void unix_inflight(struct file *fp)
{
struct sock *s = unix_get_socket(fp);
if(s) {
- atomic_inc(&unix_sk(s)->inflight);
+ struct unix_sock *u = unix_sk(s);
+ spin_lock(&unix_gc_lock);
+ if (atomic_inc_return(&u->inflight) == 1) {
+ BUG_ON(!list_empty(&u->link));
+ list_add_tail(&u->link, &gc_inflight_list);
+ } else {
+ BUG_ON(list_empty(&u->link));
+ }
atomic_inc(&unix_tot_inflight);
+ spin_unlock(&unix_gc_lock);
}
}
@@ -131,182 +142,218 @@ void unix_notinflight(struct file *fp)
{
struct sock *s = unix_get_socket(fp);
if(s) {
- atomic_dec(&unix_sk(s)->inflight);
+ struct unix_sock *u = unix_sk(s);
+ spin_lock(&unix_gc_lock);
+ BUG_ON(list_empty(&u->link));
+ if (atomic_dec_and_test(&u->inflight))
+ list_del_init(&u->link);
atomic_dec(&unix_tot_inflight);
+ spin_unlock(&unix_gc_lock);
}
}
+static inline struct sk_buff *sock_queue_head(struct sock *sk)
+{
+ return (struct sk_buff *) &sk->sk_receive_queue;
+}
-/*
- * Garbage Collector Support Functions
- */
+#define receive_queue_for_each_skb(sk, next, skb) \
+ for (skb = sock_queue_head(sk)->next, next = skb->next; \
+ skb != sock_queue_head(sk); skb = next, next = skb->next)
-static inline struct sock *pop_stack(void)
+static void scan_inflight(struct sock *x, void (*func)(struct sock *),
+ struct sk_buff_head *hitlist)
{
- struct sock *p = gc_current;
- gc_current = unix_sk(p)->gc_tree;
- return p;
+ struct sk_buff *skb;
+ struct sk_buff *next;
+
+ spin_lock(&x->sk_receive_queue.lock);
+ receive_queue_for_each_skb(x, next, skb) {
+ /*
+ * Do we have file descriptors ?
+ */
+ if (UNIXCB(skb).fp) {
+ bool hit = false;
+ /*
+ * Process the descriptors of this socket
+ */
+ int nfd = UNIXCB(skb).fp->count;
+ struct file **fp = UNIXCB(skb).fp->fp;
+ while (nfd--) {
+ /*
+ * Get the socket the fd matches
+ * if it indeed does so
+ */
+ struct sock *sk = unix_get_socket(*fp++);
+ if(sk) {
+ hit = true;
+ func(sk);
+ }
+ }
+ if (hit && hitlist != NULL) {
+ __skb_unlink(skb, &x->sk_receive_queue);
+ __skb_queue_tail(hitlist, skb);
+ }
+ }
+ }
+ spin_unlock(&x->sk_receive_queue.lock);
}
-static inline int empty_stack(void)
+static void scan_children(struct sock *x, void (*func)(struct sock *),
+ struct sk_buff_head *hitlist)
{
- return gc_current == GC_HEAD;
+ if (x->sk_state != TCP_LISTEN)
+ scan_inflight(x, func, hitlist);
+ else {
+ struct sk_buff *skb;
+ struct sk_buff *next;
+ struct unix_sock *u;
+ LIST_HEAD(embryos);
+
+ /*
+ * For a listening socket collect the queued embryos
+ * and perform a scan on them as well.
+ */
+ spin_lock(&x->sk_receive_queue.lock);
+ receive_queue_for_each_skb(x, next, skb) {
+ u = unix_sk(skb->sk);
+
+ /*
+ * An embryo cannot be in-flight, so it's safe
+ * to use the list link.
+ */
+ BUG_ON(!list_empty(&u->link));
+ list_add_tail(&u->link, &embryos);
+ }
+ spin_unlock(&x->sk_receive_queue.lock);
+
+ while (!list_empty(&embryos)) {
+ u = list_entry(embryos.next, struct unix_sock, link);
+ scan_inflight(&u->sk, func, hitlist);
+ list_del_init(&u->link);
+ }
+ }
}
-static void maybe_unmark_and_push(struct sock *x)
+static void dec_inflight(struct sock *sk)
{
- struct unix_sock *u = unix_sk(x);
+ atomic_dec(&unix_sk(sk)->inflight);
+}
- if (u->gc_tree != GC_ORPHAN)
- return;
- sock_hold(x);
- u->gc_tree = gc_current;
- gc_current = x;
+static void inc_inflight(struct sock *sk)
+{
+ atomic_inc(&unix_sk(sk)->inflight);
}
+static void inc_inflight_move_tail(struct sock *sk)
+{
+ struct unix_sock *u = unix_sk(sk);
+
+ atomic_inc(&u->inflight);
+ /*
+ * If this is still a candidate, move it to the end of the
+ * list, so that it's checked even if it was already passed
+ * over
+ */
+ if (u->gc_candidate)
+ list_move_tail(&u->link, &gc_candidates);
+}
/* The external entry point: unix_gc() */
void unix_gc(void)
{
- static DEFINE_MUTEX(unix_gc_sem);
- int i;
- struct sock *s;
- struct sk_buff_head hitlist;
- struct sk_buff *skb;
+ static bool gc_in_progress = false;
- /*
- * Avoid a recursive GC.
- */
+ struct unix_sock *u;
+ struct unix_sock *next;
+ struct sk_buff_head hitlist;
+ struct list_head cursor;
- if (!mutex_trylock(&unix_gc_sem))
- return;
+ spin_lock(&unix_gc_lock);
- spin_lock(&unix_table_lock);
+ /* Avoid a recursive GC. */
+ if (gc_in_progress)
+ goto out;
- forall_unix_sockets(i, s)
- {
- unix_sk(s)->gc_tree = GC_ORPHAN;
- }
+ gc_in_progress = true;
/*
- * Everything is now marked
- */
-
- /* Invariant to be maintained:
- - everything unmarked is either:
- -- (a) on the stack, or
- -- (b) has all of its children unmarked
- - everything on the stack is always unmarked
- - nothing is ever pushed onto the stack twice, because:
- -- nothing previously unmarked is ever pushed on the stack
+ * First, select candidates for garbage collection. Only
+ * in-flight sockets are considered, and from those only ones
+ * which don't have any external reference.
+ *
+ * Holding unix_gc_lock will protect these candidates from
+ * being detached, and hence from gaining an external
+ * reference. This also means, that since there are no
+ * possible receivers, the receive queues of these sockets are
+ * static during the GC, even though the dequeue is done
+ * before the detach without atomicity guarantees.
*/
+ list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
+ int total_refs;
+ int inflight_refs;
+
+ total_refs = file_count(u->sk.sk_socket->file);
+ inflight_refs = atomic_read(&u->inflight);
+
+ BUG_ON(inflight_refs < 1);
+ BUG_ON(total_refs < inflight_refs);
+ if (total_refs == inflight_refs) {
+ list_move_tail(&u->link, &gc_candidates);
+ u->gc_candidate = 1;
+ }
+ }
/*
- * Push root set
+ * Now remove all internal in-flight reference to children of
+ * the candidates.
*/
-
- forall_unix_sockets(i, s)
- {
- int open_count = 0;
-
- /*
- * If all instances of the descriptor are not
- * in flight we are in use.
- *
- * Special case: when socket s is embrion, it may be
- * hashed but still not in queue of listening socket.
- * In this case (see unix_create1()) we set artificial
- * negative inflight counter to close race window.
- * It is trick of course and dirty one.
- */
- if (s->sk_socket && s->sk_socket->file)
- open_count = file_count(s->sk_socket->file);
- if (open_count > atomic_read(&unix_sk(s)->inflight))
- maybe_unmark_and_push(s);
- }
+ list_for_each_entry(u, &gc_candidates, link)
+ scan_children(&u->sk, dec_inflight, NULL);
/*
- * Mark phase
+ * Restore the references for children of all candidates,
+ * which have remaining references. Do this recursively, so
+ * only those remain, which form cyclic references.
+ *
+ * Use a "cursor" link, to make the list traversal safe, even
+ * though elements might be moved about.
*/
+ list_add(&cursor, &gc_candidates);
+ while (cursor.next != &gc_candidates) {
+ u = list_entry(cursor.next, struct unix_sock, link);
- while (!empty_stack())
- {
- struct sock *x = pop_stack();
- struct sock *sk;
-
- spin_lock(&x->sk_receive_queue.lock);
- skb = skb_peek(&x->sk_receive_queue);
-
- /*
- * Loop through all but first born
- */
+ /* Move cursor to after the current position. */
+ list_move(&cursor, &u->link);
- while (skb && skb != (struct sk_buff *)&x->sk_receive_queue) {
- /*
- * Do we have file descriptors ?
- */
- if(UNIXCB(skb).fp)
- {
- /*
- * Process the descriptors of this socket
- */
- int nfd=UNIXCB(skb).fp->count;
- struct file **fp = UNIXCB(skb).fp->fp;
- while(nfd--)
- {
- /*
- * Get the socket the fd matches if
- * it indeed does so
- */
- if((sk=unix_get_socket(*fp++))!=NULL)
- {
- maybe_unmark_and_push(sk);
- }
- }
- }
- /* We have to scan not-yet-accepted ones too */
- if (x->sk_state == TCP_LISTEN)
- maybe_unmark_and_push(skb->sk);
- skb=skb->next;
+ if (atomic_read(&u->inflight) > 0) {
+ list_move_tail(&u->link, &gc_inflight_list);
+ u->gc_candidate = 0;
+ scan_children(&u->sk, inc_inflight_move_tail, NULL);
}
- spin_unlock(&x->sk_receive_queue.lock);
- sock_put(x);
}
+ list_del(&cursor);
+ /*
+ * Now gc_candidates contains only garbage. Restore original
+ * inflight counters for these as well, and remove the skbuffs
+ * which are creating the cycle(s).
+ */
skb_queue_head_init(&hitlist);
+ list_for_each_entry(u, &gc_candidates, link)
+ scan_children(&u->sk, inc_inflight, &hitlist);
- forall_unix_sockets(i, s)
- {
- struct unix_sock *u = unix_sk(s);
+ spin_unlock(&unix_gc_lock);
- if (u->gc_tree == GC_ORPHAN) {
- struct sk_buff *nextsk;
+ /* Here we are. Hitlist is filled. Die. */
+ __skb_queue_purge(&hitlist);
- spin_lock(&s->sk_receive_queue.lock);
- skb = skb_peek(&s->sk_receive_queue);
- while (skb &&
- skb != (struct sk_buff *)&s->sk_receive_queue) {
- nextsk = skb->next;
- /*
- * Do we have file descriptors ?
- */
- if (UNIXCB(skb).fp) {
- __skb_unlink(skb,
- &s->sk_receive_queue);
- __skb_queue_tail(&hitlist, skb);
- }
- skb = nextsk;
- }
- spin_unlock(&s->sk_receive_queue.lock);
- }
- u->gc_tree = GC_ORPHAN;
- }
- spin_unlock(&unix_table_lock);
+ spin_lock(&unix_gc_lock);
- /*
- * Here we are. Hitlist is filled. Die.
- */
+ /* All candidates should have been detached by now. */
+ BUG_ON(!list_empty(&gc_candidates));
+ gc_in_progress = false;
- __skb_queue_purge(&hitlist);
- mutex_unlock(&unix_gc_sem);
+ out:
+ spin_unlock(&unix_gc_lock);
}
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 7a19e0ede28..849cc06bd91 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -454,7 +454,7 @@ static int wanrouter_device_setup(struct wan_device *wandev,
}
if (conf->data_size && conf->data) {
- if (conf->data_size > 128000 || conf->data_size < 0) {
+ if (conf->data_size > 128000) {
printk(KERN_INFO
"%s: ERROR, Invalid firmware data size %i !\n",
wandev->name, conf->data_size);
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c
index 205106521ec..236e7eaf1b7 100644
--- a/net/wanrouter/wanproc.c
+++ b/net/wanrouter/wanproc.c
@@ -164,14 +164,14 @@ static int status_show(struct seq_file *m, void *v)
return 0;
}
-static struct seq_operations config_op = {
+static const struct seq_operations config_op = {
.start = r_start,
.next = r_next,
.stop = r_stop,
.show = config_show,
};
-static struct seq_operations status_op = {
+static const struct seq_operations status_op = {
.start = r_start,
.next = r_next,
.stop = r_stop,
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 3a96ae60271..092116e390b 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_WIRELESS_EXT) += wext.o
obj-$(CONFIG_CFG80211) += cfg80211.o
-cfg80211-y += core.o sysfs.o
+cfg80211-y += core.o sysfs.o radiotap.o
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
new file mode 100644
index 00000000000..68c11d09991
--- /dev/null
+++ b/net/wireless/radiotap.c
@@ -0,0 +1,257 @@
+/*
+ * Radiotap parser
+ *
+ * Copyright 2007 Andy Green <andy@warmcat.com>
+ */
+
+#include <net/cfg80211.h>
+#include <net/ieee80211_radiotap.h>
+#include <asm/unaligned.h>
+
+/* function prototypes and related defs are in include/net/cfg80211.h */
+
+/**
+ * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
+ * @iterator: radiotap_iterator to initialize
+ * @radiotap_header: radiotap header to parse
+ * @max_length: total length we can parse into (eg, whole packet length)
+ *
+ * Returns: 0 or a negative error code if there is a problem.
+ *
+ * This function initializes an opaque iterator struct which can then
+ * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
+ * argument which is present in the header. It knows about extended
+ * present headers and handles them.
+ *
+ * How to use:
+ * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
+ * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
+ * checking for a good 0 return code. Then loop calling
+ * __ieee80211_radiotap_iterator_next()... it returns either 0,
+ * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
+ * The iterator's @this_arg member points to the start of the argument
+ * associated with the current argument index that is present, which can be
+ * found in the iterator's @this_arg_index member. This arg index corresponds
+ * to the IEEE80211_RADIOTAP_... defines.
+ *
+ * Radiotap header length:
+ * You can find the CPU-endian total radiotap header length in
+ * iterator->max_length after executing ieee80211_radiotap_iterator_init()
+ * successfully.
+ *
+ * Alignment Gotcha:
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned. Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ *
+ * Example code:
+ * See Documentation/networking/radiotap-headers.txt
+ */
+
+int ieee80211_radiotap_iterator_init(
+ struct ieee80211_radiotap_iterator *iterator,
+ struct ieee80211_radiotap_header *radiotap_header,
+ int max_length)
+{
+ /* Linux only supports version 0 radiotap format */
+ if (radiotap_header->it_version)
+ return -EINVAL;
+
+ /* sanity check for allowed length and radiotap length field */
+ if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
+ return -EINVAL;
+
+ iterator->rtheader = radiotap_header;
+ iterator->max_length = le16_to_cpu(get_unaligned(
+ &radiotap_header->it_len));
+ iterator->arg_index = 0;
+ iterator->bitmap_shifter = le32_to_cpu(get_unaligned(
+ &radiotap_header->it_present));
+ iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
+ iterator->this_arg = NULL;
+
+ /* find payload start allowing for extended bitmap(s) */
+
+ if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
+ while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) &
+ (1<<IEEE80211_RADIOTAP_EXT)) {
+ iterator->arg += sizeof(u32);
+
+ /*
+ * check for insanity where the present bitmaps
+ * keep claiming to extend up to or even beyond the
+ * stated radiotap header length
+ */
+
+ if (((ulong)iterator->arg -
+ (ulong)iterator->rtheader) > iterator->max_length)
+ return -EINVAL;
+ }
+
+ iterator->arg += sizeof(u32);
+
+ /*
+ * no need to check again for blowing past stated radiotap
+ * header length, because ieee80211_radiotap_iterator_next
+ * checks it before it is dereferenced
+ */
+ }
+
+ /* we are all initialized happily */
+
+ return 0;
+}
+EXPORT_SYMBOL(ieee80211_radiotap_iterator_init);
+
+
+/**
+ * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
+ * @iterator: radiotap_iterator to move to next arg (if any)
+ *
+ * Returns: 0 if there is an argument to handle,
+ * -ENOENT if there are no more args or -EINVAL
+ * if there is something else wrong.
+ *
+ * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
+ * in @this_arg_index and sets @this_arg to point to the
+ * payload for the field. It takes care of alignment handling and extended
+ * present fields. @this_arg can be changed by the caller (eg,
+ * incremented to move inside a compound argument like
+ * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in
+ * little-endian format whatever the endianess of your CPU.
+ *
+ * Alignment Gotcha:
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned. Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ */
+
+int ieee80211_radiotap_iterator_next(
+ struct ieee80211_radiotap_iterator *iterator)
+{
+
+ /*
+ * small length lookup table for all radiotap types we heard of
+ * starting from b0 in the bitmap, so we can walk the payload
+ * area of the radiotap header
+ *
+ * There is a requirement to pad args, so that args
+ * of a given length must begin at a boundary of that length
+ * -- but note that compound args are allowed (eg, 2 x u16
+ * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
+ * a reliable indicator of alignment requirement.
+ *
+ * upper nybble: content alignment for arg
+ * lower nybble: content length for arg
+ */
+
+ static const u8 rt_sizes[] = {
+ [IEEE80211_RADIOTAP_TSFT] = 0x88,
+ [IEEE80211_RADIOTAP_FLAGS] = 0x11,
+ [IEEE80211_RADIOTAP_RATE] = 0x11,
+ [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
+ [IEEE80211_RADIOTAP_FHSS] = 0x22,
+ [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
+ [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
+ [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
+ [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
+ [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
+ [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
+ [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
+ [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
+ [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11
+ /*
+ * add more here as they are defined in
+ * include/net/ieee80211_radiotap.h
+ */
+ };
+
+ /*
+ * for every radiotap entry we can at
+ * least skip (by knowing the length)...
+ */
+
+ while (iterator->arg_index < sizeof(rt_sizes)) {
+ int hit = 0;
+ int pad;
+
+ if (!(iterator->bitmap_shifter & 1))
+ goto next_entry; /* arg not present */
+
+ /*
+ * arg is present, account for alignment padding
+ * 8-bit args can be at any alignment
+ * 16-bit args must start on 16-bit boundary
+ * 32-bit args must start on 32-bit boundary
+ * 64-bit args must start on 64-bit boundary
+ *
+ * note that total arg size can differ from alignment of
+ * elements inside arg, so we use upper nybble of length
+ * table to base alignment on
+ *
+ * also note: these alignments are ** relative to the
+ * start of the radiotap header **. There is no guarantee
+ * that the radiotap header itself is aligned on any
+ * kind of boundary.
+ *
+ * the above is why get_unaligned() is used to dereference
+ * multibyte elements from the radiotap area
+ */
+
+ pad = (((ulong)iterator->arg) -
+ ((ulong)iterator->rtheader)) &
+ ((rt_sizes[iterator->arg_index] >> 4) - 1);
+
+ if (pad)
+ iterator->arg +=
+ (rt_sizes[iterator->arg_index] >> 4) - pad;
+
+ /*
+ * this is what we will return to user, but we need to
+ * move on first so next call has something fresh to test
+ */
+ iterator->this_arg_index = iterator->arg_index;
+ iterator->this_arg = iterator->arg;
+ hit = 1;
+
+ /* internally move on the size of this arg */
+ iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
+
+ /*
+ * check for insanity where we are given a bitmap that
+ * claims to have more arg content than the length of the
+ * radiotap section. We will normally end up equalling this
+ * max_length on the last arg, never exceeding it.
+ */
+
+ if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
+ iterator->max_length)
+ return -EINVAL;
+
+ next_entry:
+ iterator->arg_index++;
+ if (unlikely((iterator->arg_index & 31) == 0)) {
+ /* completed current u32 bitmap */
+ if (iterator->bitmap_shifter & 1) {
+ /* b31 was set, there is more */
+ /* move to next u32 bitmap */
+ iterator->bitmap_shifter = le32_to_cpu(
+ get_unaligned(iterator->next_bitmap));
+ iterator->next_bitmap++;
+ } else
+ /* no more bitmaps: end */
+ iterator->arg_index = sizeof(rt_sizes);
+ } else /* just try the next bit */
+ iterator->bitmap_shifter >>= 1;
+
+ /* if we found a valid arg earlier, return it now */
+ if (hit)
+ return 0;
+ }
+
+ /* we don't know how to handle any more args, we're done */
+ return -ENOENT;
+}
+EXPORT_SYMBOL(ieee80211_radiotap_iterator_next);
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c
index 3ebae144296..88aaacd9f82 100644
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -33,7 +33,7 @@ static ssize_t _show_permaddr(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- char *addr = dev_to_rdev(dev)->wiphy.perm_addr;
+ unsigned char *addr = dev_to_rdev(dev)->wiphy.perm_addr;
return sprintf(buf, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c
index 96001f0c64f..7405b9c5b7f 100644
--- a/net/x25/x25_proc.c
+++ b/net/x25/x25_proc.c
@@ -234,21 +234,21 @@ out:
return 0;
}
-static struct seq_operations x25_seq_route_ops = {
+static const struct seq_operations x25_seq_route_ops = {
.start = x25_seq_route_start,
.next = x25_seq_route_next,
.stop = x25_seq_route_stop,
.show = x25_seq_route_show,
};
-static struct seq_operations x25_seq_socket_ops = {
+static const struct seq_operations x25_seq_socket_ops = {
.start = x25_seq_socket_start,
.next = x25_seq_socket_next,
.stop = x25_seq_socket_stop,
.show = x25_seq_socket_show,
};
-static struct seq_operations x25_seq_forward_ops = {
+static const struct seq_operations x25_seq_forward_ops = {
.start = x25_seq_forward_start,
.next = x25_seq_forward_next,
.stop = x25_seq_forward_stop,
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b8bab89616a..157bfbd250b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -26,10 +26,11 @@
#include <net/xfrm.h>
#include <net/ip.h>
#include <linux/audit.h>
+#include <linux/cache.h>
#include "xfrm_hash.h"
-int sysctl_xfrm_larval_drop;
+int sysctl_xfrm_larval_drop __read_mostly;
DEFINE_MUTEX(xfrm_cfg_mutex);
EXPORT_SYMBOL(xfrm_cfg_mutex);
@@ -833,11 +834,67 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
}
EXPORT_SYMBOL(xfrm_policy_byid);
-void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
{
- int dir;
+ int dir, err = 0;
+
+ for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
+ struct xfrm_policy *pol;
+ struct hlist_node *entry;
+ int i;
+
+ hlist_for_each_entry(pol, entry,
+ &xfrm_policy_inexact[dir], bydst) {
+ if (pol->type != type)
+ continue;
+ err = security_xfrm_policy_delete(pol);
+ if (err) {
+ xfrm_audit_log(audit_info->loginuid,
+ audit_info->secid,
+ AUDIT_MAC_IPSEC_DELSPD, 0,
+ pol, NULL);
+ return err;
+ }
+ }
+ for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
+ hlist_for_each_entry(pol, entry,
+ xfrm_policy_bydst[dir].table + i,
+ bydst) {
+ if (pol->type != type)
+ continue;
+ err = security_xfrm_policy_delete(pol);
+ if (err) {
+ xfrm_audit_log(audit_info->loginuid,
+ audit_info->secid,
+ AUDIT_MAC_IPSEC_DELSPD,
+ 0, pol, NULL);
+ return err;
+ }
+ }
+ }
+ }
+ return err;
+}
+#else
+static inline int
+xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
+{
+ return 0;
+}
+#endif
+
+int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
+{
+ int dir, err = 0;
write_lock_bh(&xfrm_policy_lock);
+
+ err = xfrm_policy_flush_secctx_check(type, audit_info);
+ if (err)
+ goto out;
+
for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
struct xfrm_policy *pol;
struct hlist_node *entry;
@@ -890,7 +947,9 @@ void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
xfrm_policy_count[dir] -= killed;
}
atomic_inc(&flow_cache_genid);
+out:
write_unlock_bh(&xfrm_policy_lock);
+ return err;
}
EXPORT_SYMBOL(xfrm_policy_flush);
@@ -2582,4 +2641,3 @@ restore_state:
}
EXPORT_SYMBOL(xfrm_migrate);
#endif
-
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 9955ff4da0a..e070c3f938f 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -21,18 +21,21 @@
#include <linux/cache.h>
#include <asm/uaccess.h>
#include <linux/audit.h>
+#include <linux/cache.h>
#include "xfrm_hash.h"
struct sock *xfrm_nl;
EXPORT_SYMBOL(xfrm_nl);
-u32 sysctl_xfrm_aevent_etime = XFRM_AE_ETIME;
+u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME;
EXPORT_SYMBOL(sysctl_xfrm_aevent_etime);
-u32 sysctl_xfrm_aevent_rseqth = XFRM_AE_SEQT_SIZE;
+u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE;
EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth);
+u32 sysctl_xfrm_acq_expires __read_mostly = 30;
+
/* Each xfrm_state may be linked to two tables:
1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl)
@@ -388,12 +391,48 @@ int xfrm_state_delete(struct xfrm_state *x)
}
EXPORT_SYMBOL(xfrm_state_delete);
-void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
{
- int i;
- int err = 0;
+ int i, err = 0;
+
+ for (i = 0; i <= xfrm_state_hmask; i++) {
+ struct hlist_node *entry;
+ struct xfrm_state *x;
+
+ hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) {
+ if (xfrm_id_proto_match(x->id.proto, proto) &&
+ (err = security_xfrm_state_delete(x)) != 0) {
+ xfrm_audit_log(audit_info->loginuid,
+ audit_info->secid,
+ AUDIT_MAC_IPSEC_DELSA,
+ 0, NULL, x);
+
+ return err;
+ }
+ }
+ }
+
+ return err;
+}
+#else
+static inline int
+xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
+{
+ return 0;
+}
+#endif
+
+int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info)
+{
+ int i, err = 0;
spin_lock_bh(&xfrm_state_lock);
+ err = xfrm_state_flush_secctx_check(proto, audit_info);
+ if (err)
+ goto out;
+
for (i = 0; i <= xfrm_state_hmask; i++) {
struct hlist_node *entry;
struct xfrm_state *x;
@@ -416,8 +455,12 @@ restart:
}
}
}
+ err = 0;
+
+out:
spin_unlock_bh(&xfrm_state_lock);
wake_up(&km_waitq);
+ return err;
}
EXPORT_SYMBOL(xfrm_state_flush);
@@ -622,8 +665,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family);
hlist_add_head(&x->byspi, xfrm_state_byspi+h);
}
- x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
- x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
+ x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
+ x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
add_timer(&x->timer);
xfrm_state_num++;
xfrm_hash_grow_check(x->bydst.next != NULL);
@@ -643,6 +686,37 @@ out:
return x;
}
+struct xfrm_state *
+xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
+ unsigned short family, u8 mode, u8 proto, u32 reqid)
+{
+ unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family);
+ struct xfrm_state *rx = NULL, *x = NULL;
+ struct hlist_node *entry;
+
+ spin_lock(&xfrm_state_lock);
+ hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) {
+ if (x->props.family == family &&
+ x->props.reqid == reqid &&
+ !(x->props.flags & XFRM_STATE_WILDRECV) &&
+ xfrm_state_addr_check(x, daddr, saddr, family) &&
+ mode == x->props.mode &&
+ proto == x->id.proto &&
+ x->km.state == XFRM_STATE_VALID) {
+ rx = x;
+ break;
+ }
+ }
+
+ if (rx)
+ xfrm_state_hold(rx);
+ spin_unlock(&xfrm_state_lock);
+
+
+ return rx;
+}
+EXPORT_SYMBOL(xfrm_stateonly_find);
+
static void __xfrm_state_insert(struct xfrm_state *x)
{
unsigned int h;
@@ -772,9 +846,9 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re
x->props.family = family;
x->props.mode = mode;
x->props.reqid = reqid;
- x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES;
+ x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires;
xfrm_state_hold(x);
- x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ;
+ x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ;
add_timer(&x->timer);
hlist_add_head(&x->bydst, xfrm_state_bydst+h);
h = xfrm_src_hash(daddr, saddr, family);
@@ -1686,7 +1760,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
x->type && x->type->get_mtu)
res = x->type->get_mtu(x, mtu);
else
- res = mtu;
+ res = mtu - x->props.header_len;
spin_unlock_bh(&x->lock);
return res;
}
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index b14c7e590c3..c06883bf620 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1418,10 +1418,13 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct km_event c;
struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
struct xfrm_audit audit_info;
+ int err;
audit_info.loginuid = NETLINK_CB(skb).loginuid;
audit_info.secid = NETLINK_CB(skb).sid;
- xfrm_state_flush(p->proto, &audit_info);
+ err = xfrm_state_flush(p->proto, &audit_info);
+ if (err)
+ return err;
c.data.proto = p->proto;
c.event = nlh->nlmsg_type;
c.seq = nlh->nlmsg_seq;
@@ -1582,7 +1585,9 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
audit_info.loginuid = NETLINK_CB(skb).loginuid;
audit_info.secid = NETLINK_CB(skb).sid;
- xfrm_policy_flush(type, &audit_info);
+ err = xfrm_policy_flush(type, &audit_info);
+ if (err)
+ return err;
c.data.type = type;
c.event = nlh->nlmsg_type;
c.seq = nlh->nlmsg_seq;
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index 8cd63014a0d..f98d772aac8 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -108,7 +108,7 @@ quiet_cmd_mkdir = MKDIR $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
quiet_cmd_gen = GEN $(patsubst $(INSTALL_HDR_PATH)/%,%,$@)
cmd_gen = \
-FNAME=$(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$@) \
+FNAME=$(patsubst $(INSTALL_HDR_PATH)/$(_dst)/%,%,$@); \
STUBDEF=__ASM_STUB_`echo $$FNAME | tr a-z.- A-Z__`; \
(echo "/* File autogenerated by 'make headers_install' */" ; \
echo "\#ifndef $$STUBDEF" ; \
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
new file mode 100755
index 00000000000..277c32647f3
--- /dev/null
+++ b/scripts/checkpatch.pl
@@ -0,0 +1,982 @@
+#!/usr/bin/perl -w
+# (c) 2001, Dave Jones. <davej@codemonkey.org.uk> (the file handling bit)
+# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
+# (c) 2007, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite, etc)
+# Licensed under the terms of the GNU GPL License version 2
+
+use strict;
+
+my $P = $0;
+$P =~ s@.*/@@g;
+
+my $V = '0.06';
+
+use Getopt::Long qw(:config no_auto_abbrev);
+
+my $quiet = 0;
+my $tree = 1;
+my $chk_signoff = 1;
+my $chk_patch = 1;
+my $tst_type = 0;
+GetOptions(
+ 'q|quiet' => \$quiet,
+ 'tree!' => \$tree,
+ 'signoff!' => \$chk_signoff,
+ 'patch!' => \$chk_patch,
+ 'test-type!' => \$tst_type,
+) or exit;
+
+my $exit = 0;
+
+if ($#ARGV < 0) {
+ print "usage: $P [options] patchfile\n";
+ print "version: $V\n";
+ print "options: -q => quiet\n";
+ print " --no-tree => run without a kernel tree\n";
+ exit(1);
+}
+
+if ($tree && !top_of_kernel_tree()) {
+ print "Must be run from the top-level dir. of a kernel tree\n";
+ exit(2);
+}
+
+my @dep_includes = ();
+my @dep_functions = ();
+my $removal = 'Documentation/feature-removal-schedule.txt';
+if ($tree && -f $removal) {
+ open(REMOVE, "<$removal") || die "$P: $removal: open failed - $!\n";
+ while (<REMOVE>) {
+ if (/^Files:\s+(.*\S)/) {
+ for my $file (split(/[, ]+/, $1)) {
+ if ($file =~ m@include/(.*)@) {
+ push(@dep_includes, $1);
+ }
+ }
+
+ } elsif (/^Funcs:\s+(.*\S)/) {
+ for my $func (split(/[, ]+/, $1)) {
+ push(@dep_functions, $func);
+ }
+ }
+ }
+}
+
+my @rawlines = ();
+while (<>) {
+ chomp;
+ push(@rawlines, $_);
+ if (eof(ARGV)) {
+ if (!process($ARGV, @rawlines)) {
+ $exit = 1;
+ }
+ @rawlines = ();
+ }
+}
+
+exit($exit);
+
+sub top_of_kernel_tree {
+ if ((-f "COPYING") && (-f "CREDITS") && (-f "Kbuild") &&
+ (-f "MAINTAINERS") && (-f "Makefile") && (-f "README") &&
+ (-d "Documentation") && (-d "arch") && (-d "include") &&
+ (-d "drivers") && (-d "fs") && (-d "init") && (-d "ipc") &&
+ (-d "kernel") && (-d "lib") && (-d "scripts")) {
+ return 1;
+ }
+ return 0;
+}
+
+sub expand_tabs {
+ my ($str) = @_;
+
+ my $res = '';
+ my $n = 0;
+ for my $c (split(//, $str)) {
+ if ($c eq "\t") {
+ $res .= ' ';
+ $n++;
+ for (; ($n % 8) != 0; $n++) {
+ $res .= ' ';
+ }
+ next;
+ }
+ $res .= $c;
+ $n++;
+ }
+
+ return $res;
+}
+
+sub line_stats {
+ my ($line) = @_;
+
+ # Drop the diff line leader and expand tabs
+ $line =~ s/^.//;
+ $line = expand_tabs($line);
+
+ # Pick the indent from the front of the line.
+ my ($white) = ($line =~ /^(\s*)/);
+
+ return (length($line), length($white));
+}
+
+sub sanitise_line {
+ my ($line) = @_;
+
+ my $res = '';
+ my $l = '';
+
+ my $quote = '';
+
+ foreach my $c (split(//, $line)) {
+ if ($l ne "\\" && ($c eq "'" || $c eq '"')) {
+ if ($quote eq '') {
+ $quote = $c;
+ $res .= $c;
+ $l = $c;
+ next;
+ } elsif ($quote eq $c) {
+ $quote = '';
+ }
+ }
+ if ($quote && $c ne "\t") {
+ $res .= "X";
+ } else {
+ $res .= $c;
+ }
+
+ $l = $c;
+ }
+
+ return $res;
+}
+
+sub ctx_block_get {
+ my ($linenr, $remain, $outer, $open, $close) = @_;
+ my $line;
+ my $start = $linenr - 1;
+ my $blk = '';
+ my @o;
+ my @c;
+ my @res = ();
+
+ for ($line = $start; $remain > 0; $line++) {
+ next if ($rawlines[$line] =~ /^-/);
+ $remain--;
+
+ $blk .= $rawlines[$line];
+
+ @o = ($blk =~ /$open/g);
+ @c = ($blk =~ /$close/g);
+
+ if (!$outer || (scalar(@o) - scalar(@c)) == 1) {
+ push(@res, $rawlines[$line]);
+ }
+
+ last if (scalar(@o) == scalar(@c));
+ }
+
+ return @res;
+}
+sub ctx_block_outer {
+ my ($linenr, $remain) = @_;
+
+ return ctx_block_get($linenr, $remain, 1, '\{', '\}');
+}
+sub ctx_block {
+ my ($linenr, $remain) = @_;
+
+ return ctx_block_get($linenr, $remain, 0, '\{', '\}');
+}
+sub ctx_statement {
+ my ($linenr, $remain) = @_;
+
+ return ctx_block_get($linenr, $remain, 0, '\(', '\)');
+}
+
+sub ctx_locate_comment {
+ my ($first_line, $end_line) = @_;
+
+ # Catch a comment on the end of the line itself.
+ my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*$@);
+ return $current_comment if (defined $current_comment);
+
+ # Look through the context and try and figure out if there is a
+ # comment.
+ my $in_comment = 0;
+ $current_comment = '';
+ for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
+ my $line = $rawlines[$linenr - 1];
+ #warn " $line\n";
+ if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
+ $in_comment = 1;
+ }
+ if ($line =~ m@/\*@) {
+ $in_comment = 1;
+ }
+ if (!$in_comment && $current_comment ne '') {
+ $current_comment = '';
+ }
+ $current_comment .= $line . "\n" if ($in_comment);
+ if ($line =~ m@\*/@) {
+ $in_comment = 0;
+ }
+ }
+
+ chomp($current_comment);
+ return($current_comment);
+}
+sub ctx_has_comment {
+ my ($first_line, $end_line) = @_;
+ my $cmt = ctx_locate_comment($first_line, $end_line);
+
+ ##print "LINE: $rawlines[$end_line - 1 ]\n";
+ ##print "CMMT: $cmt\n";
+
+ return ($cmt ne '');
+}
+
+sub cat_vet {
+ my ($vet) = @_;
+
+ $vet =~ s/\t/^I/;
+ $vet =~ s/$/\$/;
+
+ return $vet;
+}
+
+sub process {
+ my $filename = shift;
+ my @lines = @_;
+
+ my $linenr=0;
+ my $prevline="";
+ my $stashline="";
+
+ my $length;
+ my $indent;
+ my $previndent=0;
+ my $stashindent=0;
+
+ my $clean = 1;
+ my $signoff = 0;
+ my $is_patch = 0;
+
+ # Trace the real file/line as we go.
+ my $realfile = '';
+ my $realline = 0;
+ my $realcnt = 0;
+ my $here = '';
+ my $in_comment = 0;
+ my $first_line = 0;
+
+ my $Ident = qr{[A-Za-z\d_]+};
+ my $Storage = qr{extern|static};
+ my $Sparse = qr{__user|__kernel|__force|__iomem};
+ my $NonptrType = qr{
+ \b
+ (?:const\s+)?
+ (?:unsigned\s+)?
+ (?:
+ void|
+ char|
+ short|
+ int|
+ long|
+ unsigned|
+ float|
+ double|
+ long\s+int|
+ long\s+long|
+ long\s+long\s+int|
+ struct\s+$Ident|
+ union\s+$Ident|
+ ${Ident}_t
+ )
+ (?:\s+$Sparse)*
+ \b
+ }x;
+ my $Type = qr{
+ \b$NonptrType\b
+ (?:\s*\*+\s*const|\s*\*+)?
+ }x;
+ my $Declare = qr{(?:$Storage\s+)?$Type};
+ my $Attribute = qr{__read_mostly|__init|__initdata};
+
+ foreach my $line (@lines) {
+ $linenr++;
+
+ my $rawline = $line;
+
+#extract the filename as it passes
+ if ($line=~/^\+\+\+\s+(\S+)/) {
+ $realfile=$1;
+ $realfile =~ s@^[^/]*/@@;
+ $in_comment = 0;
+ next;
+ }
+#extract the line range in the file after the patch is applied
+ if ($line=~/^\@\@ -\d+,\d+ \+(\d+)(,(\d+))? \@\@/) {
+ $is_patch = 1;
+ $first_line = $linenr + 1;
+ $in_comment = 0;
+ $realline=$1-1;
+ if (defined $2) {
+ $realcnt=$3+1;
+ } else {
+ $realcnt=1+1;
+ }
+ next;
+ }
+
+# track the line number as we move through the hunk, note that
+# new versions of GNU diff omit the leading space on completely
+# blank context lines so we need to count that too.
+ if ($line =~ /^( |\+|$)/) {
+ $realline++;
+ $realcnt-- if ($realcnt != 0);
+
+ # track any sort of multi-line comment. Obviously if
+ # the added text or context do not include the whole
+ # comment we will not see it. Such is life.
+ #
+ # Guestimate if this is a continuing comment. If this
+ # is the start of a diff block and this line starts
+ # ' *' then it is very likely a comment.
+ if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
+ $in_comment = 1;
+ }
+ if ($line =~ m@/\*@) {
+ $in_comment = 1;
+ }
+ if ($line =~ m@\*/@) {
+ $in_comment = 0;
+ }
+
+ # Measure the line length and indent.
+ ($length, $indent) = line_stats($line);
+
+ # Track the previous line.
+ ($prevline, $stashline) = ($stashline, $line);
+ ($previndent, $stashindent) = ($stashindent, $indent);
+ } elsif ($realcnt == 1) {
+ $realcnt--;
+ }
+
+#make up the handle for any error we report on this line
+ $here = "#$linenr: ";
+ $here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
+
+ my $hereline = "$here\n$line\n";
+ my $herecurr = "$here\n$line\n\n";
+ my $hereprev = "$here\n$prevline\n$line\n\n";
+
+#check the patch for a signoff:
+ if ($line =~ /^\s*signed-off-by:/i) {
+ # This is a signoff, if ugly, so do not double report.
+ $signoff++;
+ if (!($line =~ /^\s*Signed-off-by:/)) {
+ print "Signed-off-by: is the preferred form\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ if ($line =~ /^\s*signed-off-by:\S/i) {
+ print "need space after Signed-off-by:\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+
+# Check for wrappage within a valid hunk of the file
+ if ($realcnt != 0 && $line !~ m{^(?:\+|-| |$)}) {
+ print "patch seems to be corrupt (line wrapped?) [$realcnt]\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+#ignore lines being removed
+ if ($line=~/^-/) {next;}
+
+# check we are in a valid source file if not then ignore this hunk
+ next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
+
+#trailing whitespace
+ if ($line =~ /^\+.*\S\s+$/ || $line =~ /^\+\s+$/) {
+ my $herevet = "$here\n" . cat_vet($line) . "\n\n";
+ print "trailing whitespace\n";
+ print "$herevet";
+ $clean = 0;
+ }
+#80 column limit
+ if ($line =~ /^\+/ && !($prevline=~/\/\*\*/) && $length > 80) {
+ print "line over 80 characters\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# check we are in a valid source file *.[hc] if not then ignore this hunk
+ next if ($realfile !~ /\.[hc]$/);
+
+# at the beginning of a line any tabs must come first and anything
+# more than 8 must use tabs.
+ if ($line=~/^\+\s* \t\s*\S/ or $line=~/^\+\s* \s*/) {
+ my $herevet = "$here\n" . cat_vet($line) . "\n\n";
+ print "use tabs not spaces\n";
+ print "$herevet";
+ $clean = 0;
+ }
+
+ #
+ # The rest of our checks refer specifically to C style
+ # only apply those _outside_ comments.
+ #
+ next if ($in_comment);
+
+# Remove comments from the line before processing.
+ $line =~ s@/\*.*\*/@@g;
+ $line =~ s@/\*.*@@;
+ $line =~ s@.*\*/@@;
+
+# Standardise the strings and chars within the input to simplify matching.
+ $line = sanitise_line($line);
+
+#
+# Checks which may be anchored in the context.
+#
+
+# Check for switch () and associated case and default
+# statements should be at the same indent.
+ if ($line=~/\bswitch\s*\(.*\)/) {
+ my $err = '';
+ my $sep = '';
+ my @ctx = ctx_block_outer($linenr, $realcnt);
+ shift(@ctx);
+ for my $ctx (@ctx) {
+ my ($clen, $cindent) = line_stats($ctx);
+ if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
+ $indent != $cindent) {
+ $err .= "$sep$ctx\n";
+ $sep = '';
+ } else {
+ $sep = "[...]\n";
+ }
+ }
+ if ($err ne '') {
+ print "switch and case should be at the same indent\n";
+ print "$here\n$line\n$err\n";
+ $clean = 0;
+ }
+ }
+
+#ignore lines not being added
+ if ($line=~/^[^\+]/) {next;}
+
+# TEST: allow direct testing of the type matcher.
+ if ($tst_type && $line =~ /^.$Declare$/) {
+ print "TEST: is type $Declare\n";
+ print "$herecurr";
+ $clean = 0;
+ next;
+ }
+
+#
+# Checks which are anchored on the added line.
+#
+
+# check for malformed paths in #include statements (uses RAW line)
+ if ($rawline =~ m{^.#\s*include\s+[<"](.*)[">]}) {
+ my $path = $1;
+ if ($path =~ m{//}) {
+ print "malformed #include filename\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ # Sanitise this special form of string.
+ $path = 'X' x length($path);
+ $line =~ s{\<.*\>}{<$path>};
+ }
+
+# no C99 // comments
+ if ($line =~ m{//}) {
+ print "do not use C99 // comments\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ # Remove C99 comments.
+ $line =~ s@//.*@@;
+
+#EXPORT_SYMBOL should immediately follow its function closing }.
+ if (($line =~ /EXPORT_SYMBOL.*\((.*)\)/) ||
+ ($line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+ my $name = $1;
+ if (($prevline !~ /^}/) &&
+ ($prevline !~ /^\+}/) &&
+ ($prevline !~ /^ }/) &&
+ ($prevline !~ /\s$name(?:\s+$Attribute)?\s*(?:;|=)/)) {
+ print "EXPORT_SYMBOL(foo); should immediately follow its function/variable\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+
+# check for static initialisers.
+ if ($line=~/\s*static\s.*=\s+(0|NULL);/) {
+ print "do not initialise statics to 0 or NULL\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# check for new typedefs, only function parameters and sparse annotations
+# make sense.
+ if ($line =~ /\btypedef\s/ &&
+ $line !~ /\btypedef\s+$Type\s+\(\s*$Ident\s*\)\s*\(/ &&
+ $line !~ /\b__bitwise(?:__|)\b/) {
+ print "do not add new typedefs\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# * goes on variable not on type
+ if ($line =~ m{\($NonptrType(\*+)(?:\s+const)?\)}) {
+ print "\"(foo$1)\" should be \"(foo $1)\"\n";
+ print "$herecurr";
+ $clean = 0;
+
+ } elsif ($line =~ m{\($NonptrType\s+(\*+)(?!\s+const)\s+\)}) {
+ print "\"(foo $1 )\" should be \"(foo $1)\"\n";
+ print "$herecurr";
+ $clean = 0;
+
+ } elsif ($line =~ m{$NonptrType(\*+)(?:\s+const)?\s+[A-Za-z\d_]+}) {
+ print "\"foo$1 bar\" should be \"foo $1bar\"\n";
+ print "$herecurr";
+ $clean = 0;
+
+ } elsif ($line =~ m{$NonptrType\s+(\*+)(?!\s+const)\s+[A-Za-z\d_]+}) {
+ print "\"foo $1 bar\" should be \"foo $1bar\"\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# # no BUG() or BUG_ON()
+# if ($line =~ /\b(BUG|BUG_ON)\b/) {
+# print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
+# print "$herecurr";
+# $clean = 0;
+# }
+
+# printk should use KERN_* levels. Note that follow on printk's on the
+# same line do not need a level, so we use the current block context
+# to try and find and validate the current printk. In summary the current
+# printk includes all preceeding printk's which have no newline on the end.
+# we assume the first bad printk is the one to report.
+ if ($line =~ /\bprintk\((?!KERN_)/) {
+ my $ok = 0;
+ for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
+ #print "CHECK<$lines[$ln - 1]\n";
+ # we have a preceeding printk if it ends
+ # with "\n" ignore it, else it is to blame
+ if ($lines[$ln - 1] =~ m{\bprintk\(}) {
+ if ($rawlines[$ln - 1] !~ m{\\n"}) {
+ $ok = 1;
+ }
+ last;
+ }
+ }
+ if ($ok == 0) {
+ print "printk() should include KERN_ facility level\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+
+# function brace can't be on same line, except for #defines of do while,
+# or if closed on same line
+ if (($line=~/$Type\s*[A-Za-z\d_]+\(.*\).* {/) and
+ !($line=~/\#define.*do\s{/) and !($line=~/}/)) {
+ print "braces following function declarations go on the next line\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# Check operator spacing.
+ # Note we expand the line with the leading + as the real
+ # line will be displayed with the leading + and the tabs
+ # will therefore also expand that way.
+ my $opline = $line;
+ $opline = expand_tabs($opline);
+ $opline =~ s/^./ /;
+ if (!($line=~/\#\s*include/)) {
+ my @elements = split(/(<<=|>>=|<=|>=|==|!=|\+=|-=|\*=|\/=|%=|\^=|\|=|&=|->|<<|>>|<|>|=|!|~|&&|\|\||,|\^|\+\+|--|;|&|\||\+|-|\*|\/\/|\/)/, $opline);
+ my $off = 0;
+ for (my $n = 0; $n < $#elements; $n += 2) {
+ $off += length($elements[$n]);
+
+ my $a = '';
+ $a = 'V' if ($elements[$n] ne '');
+ $a = 'W' if ($elements[$n] =~ /\s$/);
+ $a = 'B' if ($elements[$n] =~ /(\[|\()$/);
+ $a = 'O' if ($elements[$n] eq '');
+ $a = 'E' if ($elements[$n] eq '' && $n == 0);
+
+ my $op = $elements[$n + 1];
+
+ my $c = '';
+ if (defined $elements[$n + 2]) {
+ $c = 'V' if ($elements[$n + 2] ne '');
+ $c = 'W' if ($elements[$n + 2] =~ /^\s/);
+ $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
+ $c = 'O' if ($elements[$n + 2] eq '');
+ } else {
+ $c = 'E';
+ }
+
+ # Pick up the preceeding and succeeding characters.
+ my $ca = substr($opline, $off - 1, 1);
+ my $cc = '';
+ if (length($opline) >= ($off + length($elements[$n + 1]))) {
+ $cc = substr($opline, $off + length($elements[$n + 1]));
+ }
+
+ my $ctx = "${a}x${c}";
+
+ my $at = "(ctx:$ctx)";
+
+ my $ptr = (" " x $off) . "^";
+ my $hereptr = "$hereline$ptr\n\n";
+
+ ##print "<$s1:$op:$s2> <$elements[$n]:$elements[$n + 1]:$elements[$n + 2]>\n";
+
+ # ; should have either the end of line or a space or \ after it
+ if ($op eq ';') {
+ if ($ctx !~ /.x[WE]/ && $cc !~ /^\\/) {
+ print "need space after that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # // is a comment
+ } elsif ($op eq '//') {
+
+ # -> should have no spaces
+ } elsif ($op eq '->') {
+ if ($ctx =~ /Wx.|.xW/) {
+ print "no spaces around that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # , must have a space on the right.
+ } elsif ($op eq ',') {
+ if ($ctx !~ /.xW|.xE/ && $cc !~ /^}/) {
+ print "need space after that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # unary ! and unary ~ are allowed no space on the right
+ } elsif ($op eq '!' or $op eq '~') {
+ if ($ctx !~ /[WOEB]x./) {
+ print "need space before that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+ if ($ctx =~ /.xW/) {
+ print "no space after that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # unary ++ and unary -- are allowed no space on one side.
+ } elsif ($op eq '++' or $op eq '--') {
+ if ($ctx !~ /[WOB]x[^W]/ && $ctx !~ /[^W]x[WOBE]/) {
+ print "need space one side of that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+ if ($ctx =~ /Wx./ && $cc =~ /^;/) {
+ print "no space before that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # & is both unary and binary
+ # unary:
+ # a &b
+ # binary (consistent spacing):
+ # a&b OK
+ # a & b OK
+ #
+ # boiling down to: if there is a space on the right then there
+ # should be one on the left.
+ #
+ # - is the same
+ #
+ } elsif ($op eq '&' or $op eq '-') {
+ if ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]/) {
+ print "need space before that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # * is the same as & only adding:
+ # type:
+ # (foo *)
+ # (foo **)
+ #
+ } elsif ($op eq '*') {
+ if ($ca eq '*') {
+ if ($cc =~ /^\s(?!\s*const)/) {
+ print "no space after that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+ } elsif ($ctx !~ /VxV|[EW]x[WE]|[EWB]x[VO]|OxV|WxB|BxB/) {
+ print "need space before that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # << and >> may either have or not have spaces both sides
+ } elsif ($op eq '<<' or $op eq '>>' or $op eq '+' or $op eq '/' or
+ $op eq '^' or $op eq '|')
+ {
+ if ($ctx !~ /VxV|WxW|VxE|WxE/) {
+ print "need consistent spacing around '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+
+ # All the others need spaces both sides.
+ } elsif ($ctx !~ /[EW]x[WE]/) {
+ print "need spaces around that '$op' $at\n";
+ print "$hereptr";
+ $clean = 0;
+ }
+ $off += length($elements[$n + 1]);
+ }
+ }
+
+#need space before brace following if, while, etc
+ if ($line=~/\(.*\){/) {
+ print "need a space before the brace\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+#goto labels aren't indented, allow a single space however
+ if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
+ !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
+ print "labels should not be indented\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# Need a space before open parenthesis after if, while etc
+ if ($line=~/\b(if|while|for|switch)\(/) {
+ print "need a space before the open parenthesis\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# Check for illegal assignment in if conditional.
+ if ($line=~/\bif\s*\(.*[^<>!=]=[^=].*\)/) {
+ #next if ($line=~/\".*\Q$op\E.*\"/ or $line=~/\'\Q$op\E\'/);
+ print "do not use assignment in if condition\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+ # Check for }<nl>else {, these must be at the same
+ # indent level to be relevant to each other.
+ if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
+ $previndent == $indent) {
+ print "else should follow close brace\n";
+ print "$hereprev";
+ $clean = 0;
+ }
+
+#studly caps, commented out until figure out how to distinguish between use of existing and adding new
+# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
+# print "No studly caps, use _\n";
+# print "$herecurr";
+# $clean = 0;
+# }
+
+#no spaces allowed after \ in define
+ if ($line=~/\#define.*\\\s$/) {
+ print("Whitepspace after \\ makes next lines useless\n");
+ print "$herecurr";
+ $clean = 0;
+ }
+
+#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
+ if ($tree && $rawline =~ m{^.\#\s*include\s*\<asm\/(.*)\.h\>}) {
+ my $checkfile = "include/linux/$1.h";
+ if (-f $checkfile) {
+ print "Use #include <linux/$1.h> instead of <asm/$1.h>\n";
+ print $herecurr;
+ $clean = 0;
+ }
+ }
+
+# if/while/etc brace do not go on next line, unless defining a do while loop,
+# or if that brace on the next line is for something else
+ if ($prevline=~/\b(?:(if|while|for|switch)\s*\(|do\b|else\b)/) {
+ my @opened = $prevline=~/\(/g;
+ my @closed = $prevline=~/\)/g;
+ my $nr_line = $linenr;
+ my $remaining = $realcnt - 1;
+ my $next_line = $line;
+ my $extra_lines = 0;
+ my $display_segment = $prevline;
+
+ while ($remaining > 0 && scalar @opened > scalar @closed) {
+ $prevline .= $next_line;
+ $display_segment .= "\n" . $next_line;
+ $next_line = $lines[$nr_line];
+ $nr_line++;
+ $remaining--;
+
+ @opened = $prevline=~/\(/g;
+ @closed = $prevline=~/\)/g;
+ }
+
+ if (($prevline=~/\b(?:(if|while|for|switch)\s*\(.*\)|do|else)\s*$/) and ($next_line=~/{/) and
+ !($next_line=~/\b(?:if|while|for|switch|do|else)\b/) and !($next_line=~/\#define.*do.*while/)) {
+ print "That { should be on the previous line\n";
+ print "$here\n$display_segment\n$next_line\n\n";
+ $clean = 0;
+ }
+ }
+
+# if and else should not have general statements after it
+ if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/ &&
+ $1 !~ /^\s*(?:\sif|{|$)/) {
+ print "trailing statements should be on next line\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# multi-statement macros should be enclosed in a do while loop, grab the
+# first statement and ensure its the whole macro if its not enclosed
+# in a known goot container
+ if (($prevline=~/\#define.*\\/) and
+ !($prevline=~/do\s+{/) and !($prevline=~/\(\{/) and
+ !($line=~/do.*{/) and !($line=~/\(\{/) and
+ !($line=~/^.\s*$Declare\s/)) {
+ # Grab the first statement, if that is the entire macro
+ # its ok. This may start either on the #define line
+ # or the one below.
+ my $ln = $linenr;
+ my $cnt = $realcnt;
+
+ # If the macro starts on the define line start there.
+ if ($prevline !~ m{^.#\s*define\s*$Ident(?:\([^\)]*\))?\s*\\\s*$}) {
+ $ln--;
+ $cnt++;
+ }
+ my $ctx = join('', ctx_statement($ln, $cnt));
+
+ if ($ctx =~ /\\$/) {
+ if ($ctx =~ /;/) {
+ print "Macros with multiple statements should be enclosed in a do - while loop\n";
+ } else {
+ print "Macros with complex values should be enclosed in parenthesis\n";
+ }
+ print "$hereprev";
+ $clean = 0;
+ }
+ }
+
+# don't include deprecated include files (uses RAW line)
+ for my $inc (@dep_includes) {
+ if ($rawline =~ m@\#\s*include\s*\<$inc>@) {
+ print "Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+
+# don't use deprecated functions
+ for my $func (@dep_functions) {
+ if ($line =~ /\b$func\b/) {
+ print "Don't use $func(): see Documentation/feature-removal-schedule.txt\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+
+# no volatiles please
+ if ($line =~ /\bvolatile\b/ && $line !~ /\basm\s+volatile\b/) {
+ print "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# warn about #if 0
+ if ($line =~ /^.#\s*if\s+0\b/) {
+ print "#if 0 -- if this code redundant remove it\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+# warn about #ifdefs in C files
+# if ($line =~ /^.#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
+# print "#ifdef in C files should be avoided\n";
+# print "$herecurr";
+# $clean = 0;
+# }
+
+# check for spinlock_t definitions without a comment.
+ if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/) {
+ my $which = $1;
+ if (!ctx_has_comment($first_line, $linenr)) {
+ print "$1 definition without comment\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+# check for memory barriers without a comment.
+ if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
+ if (!ctx_has_comment($first_line, $linenr)) {
+ print "memory barrier without comment\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+# check of hardware specific defines
+ if ($line =~ m@^.#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@) {
+ print "architecture specific defines should be avoided\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+
+ if ($line =~ /$Type\s+(?:inline|__always_inline)\b/ ||
+ $line =~ /\b(?:inline|always_inline)\s+$Storage/) {
+ print "inline keyword should sit between storage class and type\n";
+ print "$herecurr";
+ $clean = 0;
+ }
+ }
+
+ if ($chk_patch && !$is_patch) {
+ $clean = 0;
+ print "Does not appear to be a unified-diff format patch\n";
+ }
+ if ($is_patch && $chk_signoff && $signoff == 0) {
+ $clean = 0;
+ print "Missing Signed-off-by: line(s)\n";
+ }
+
+ if ($clean == 1 && $quiet == 0) {
+ print "Your patch has no obvious style problems and is ready for submission.\n"
+ }
+ if ($clean == 0 && $quiet == 0) {
+ print "Your patch has style problems, please review. If any of these errors\n";
+ print "are false positives report them to the maintainer, see\n";
+ print "CHECKPATCH in MAINTAINERS.\n";
+ }
+ return $clean;
+}
diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh
index f98171f5a3d..0dcc01ce45a 100755
--- a/scripts/checksyscalls.sh
+++ b/scripts/checksyscalls.sh
@@ -99,6 +99,11 @@ cat << EOF
#define __IGNORE_setfsuid32
#define __IGNORE_setfsgid32
+/* sync_file_range had a stupid ABI. Allow sync_file_range2 instead */
+#ifdef __NR_sync_file_range2
+#define __IGNORE_sync_file_range
+#endif
+
/* Unmerged syscalls for AFS, STREAMS, etc. */
#define __IGNORE_afs_syscall
#define __IGNORE_getpmsg
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 8e5610d428c..3645e980da7 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1052,6 +1052,7 @@ static int init_section_ref_ok(const char *name)
".plt", /* seen on ARCH=um build on x86_64. Harmless */
"__ftr_fixup", /* powerpc cpu feature fixup */
"__fw_ftr_fixup", /* powerpc firmware feature fixup */
+ ".cranges", /* used by sh64 */
NULL
};
/* Start of section names */
@@ -1132,6 +1133,7 @@ static int exit_section_ref_ok(const char *name)
".fixup",
".smp_locks",
".plt", /* seen on ARCH=um build on x86_64. Harmless */
+ ".cranges", /* used by sh64 */
NULL
};
/* Start of section names */
diff --git a/security/dummy.c b/security/dummy.c
index 8ffd76405b5..d6a112ce297 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -420,8 +420,12 @@ static int dummy_file_ioctl (struct file *file, unsigned int command,
static int dummy_file_mmap (struct file *file, unsigned long reqprot,
unsigned long prot,
- unsigned long flags)
+ unsigned long flags,
+ unsigned long addr,
+ unsigned long addr_only)
{
+ if (addr < mmap_min_addr)
+ return -EACCES;
return 0;
}
diff --git a/security/security.c b/security/security.c
index fc8601b2b7a..27e5863d30f 100644
--- a/security/security.c
+++ b/security/security.c
@@ -24,6 +24,7 @@ extern struct security_operations dummy_security_ops;
extern void security_fixup_ops(struct security_operations *ops);
struct security_operations *security_ops; /* Initialized to NULL */
+unsigned long mmap_min_addr; /* 0 means no protection */
static inline int verify(struct security_operations *ops)
{
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index e4396a89edc..78c408fd2b0 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -586,7 +586,7 @@ void avc_audit(u32 ssid, u32 tsid,
}
}
if (inode)
- audit_log_format(ab, " dev=%s ino=%ld",
+ audit_log_format(ab, " dev=%s ino=%lu",
inode->i_sb->s_id,
inode->i_ino);
break;
@@ -832,6 +832,7 @@ int avc_ss_reset(u32 seqno)
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions, interpreted based on @tclass
+ * @flags: AVC_STRICT or 0
* @avd: access vector decisions
*
* Check the AVC to determine whether the @requested permissions are granted
@@ -846,8 +847,9 @@ int avc_ss_reset(u32 seqno)
* should be released for the auditing.
*/
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
- u16 tclass, u32 requested,
- struct av_decision *avd)
+ u16 tclass, u32 requested,
+ unsigned flags,
+ struct av_decision *avd)
{
struct avc_node *node;
struct avc_entry entry, *p_ae;
@@ -874,7 +876,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
denied = requested & ~(p_ae->avd.allowed);
if (!requested || denied) {
- if (selinux_enforcing)
+ if (selinux_enforcing || (flags & AVC_STRICT))
rc = -EACCES;
else
if (node)
@@ -909,7 +911,7 @@ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
struct av_decision avd;
int rc;
- rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
+ rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
return rc;
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ad8dd4e8657..78c3f98fcdc 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1592,9 +1592,10 @@ static int selinux_vm_enough_memory(long pages)
rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
if (rc == 0)
rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
- SECCLASS_CAPABILITY,
- CAP_TO_MASK(CAP_SYS_ADMIN),
- NULL);
+ SECCLASS_CAPABILITY,
+ CAP_TO_MASK(CAP_SYS_ADMIN),
+ 0,
+ NULL);
if (rc == 0)
cap_sys_admin = 1;
@@ -2568,12 +2569,16 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
}
static int selinux_file_mmap(struct file *file, unsigned long reqprot,
- unsigned long prot, unsigned long flags)
+ unsigned long prot, unsigned long flags,
+ unsigned long addr, unsigned long addr_only)
{
- int rc;
+ int rc = 0;
+ u32 sid = ((struct task_security_struct*)(current->security))->sid;
- rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
- if (rc)
+ if (addr < mmap_min_addr)
+ rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
+ MEMPROTECT__MMAP_ZERO, NULL);
+ if (rc || addr_only)
return rc;
if (selinux_checkreqprot)
@@ -4626,7 +4631,7 @@ static int selinux_setprocattr(struct task_struct *p,
if (p->ptrace & PT_PTRACED) {
error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
SECCLASS_PROCESS,
- PROCESS__PTRACE, &avd);
+ PROCESS__PTRACE, 0, &avd);
if (!error)
tsec->sid = sid;
task_unlock(p);
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index b83e74012a9..049bf69429b 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -158,3 +158,4 @@
S_(SECCLASS_KEY, KEY__CREATE, "create")
S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
+ S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 5fee1735bff..eda89a2ec63 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -823,3 +823,4 @@
#define DCCP_SOCKET__NAME_BIND 0x00200000UL
#define DCCP_SOCKET__NODE_BIND 0x00400000UL
#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL
+#define MEMPROTECT__MMAP_ZERO 0x00000001UL
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 6ed10c3d333..e145f6e13b0 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -102,9 +102,11 @@ void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *auditdata);
+#define AVC_STRICT 1 /* Ignore permissive mode. */
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
- u16 tclass, u32 requested,
- struct av_decision *avd);
+ u16 tclass, u32 requested,
+ unsigned flags,
+ struct av_decision *avd);
int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index 37879906844..e77de0e62ea 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -63,3 +63,4 @@
S_("key")
S_(NULL)
S_("dccp_socket")
+ S_("memprotect")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index 35f309f4787..a9c2b20f14b 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -49,6 +49,7 @@
#define SECCLASS_PACKET 57
#define SECCLASS_KEY 58
#define SECCLASS_DCCP_SOCKET 60
+#define SECCLASS_MEMPROTECT 61
/*
* Security identifier indices for initial entities
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index b94378afea2..83bdd4d2a29 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -41,6 +41,7 @@ extern int selinux_mls_enabled;
int security_load_policy(void * data, size_t len);
+#define SEL_VEC_MAX 32
struct av_decision {
u32 allowed;
u32 decided;
@@ -87,6 +88,9 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
+int security_get_classes(char ***classes, int *nclasses);
+int security_get_permissions(char *class, char ***perms, int *nperms);
+
#define SECURITY_FS_USE_XATTR 1 /* use xattr */
#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index bf8750791dd..e64eca246f1 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -36,8 +36,8 @@
#include "security.h"
/**
- * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
- * @sock: the socket to label
+ * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
+ * @sk: the socket to label
* @sid: the SID to use
*
* Description:
@@ -47,17 +47,17 @@
* this function and rcu_read_unlock() after this function returns.
*
*/
-static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
+static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid)
{
int rc;
- struct sk_security_struct *sksec = sock->sk->sk_security;
+ struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr;
rc = security_netlbl_sid_to_secattr(sid, &secattr);
if (rc != 0)
return rc;
- rc = netlbl_socket_setattr(sock, &secattr);
+ rc = netlbl_sock_setattr(sk, &secattr);
if (rc == 0) {
spin_lock_bh(&sksec->nlbl_lock);
sksec->nlbl_state = NLBL_LABELED;
@@ -206,7 +206,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
/* Try to set the NetLabel on the socket to save time later, if we fail
* here we will pick up the pieces in later calls to
* selinux_netlbl_inode_permission(). */
- selinux_netlbl_socket_setsid(sock, sksec->sid);
+ selinux_netlbl_sock_setsid(sk, sksec->sid);
rcu_read_unlock();
}
@@ -223,14 +223,15 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
int selinux_netlbl_socket_post_create(struct socket *sock)
{
int rc = 0;
+ struct sock *sk = sock->sk;
struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
- struct sk_security_struct *sksec = sock->sk->sk_security;
+ struct sk_security_struct *sksec = sk->sk_security;
sksec->sclass = isec->sclass;
rcu_read_lock();
if (sksec->nlbl_state == NLBL_REQUIRE)
- rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
+ rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
rcu_read_unlock();
return rc;
@@ -251,14 +252,16 @@ int selinux_netlbl_socket_post_create(struct socket *sock)
int selinux_netlbl_inode_permission(struct inode *inode, int mask)
{
int rc;
- struct sk_security_struct *sksec;
+ struct sock *sk;
struct socket *sock;
+ struct sk_security_struct *sksec;
if (!S_ISSOCK(inode->i_mode) ||
((mask & (MAY_WRITE | MAY_APPEND)) == 0))
return 0;
sock = SOCKET_I(inode);
- sksec = sock->sk->sk_security;
+ sk = sock->sk;
+ sksec = sk->sk_security;
rcu_read_lock();
if (sksec->nlbl_state != NLBL_REQUIRE) {
@@ -266,9 +269,9 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
return 0;
}
local_bh_disable();
- bh_lock_sock_nested(sock->sk);
- rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
- bh_unlock_sock(sock->sk);
+ bh_lock_sock_nested(sk);
+ rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
+ bh_unlock_sock(sk);
local_bh_enable();
rcu_read_unlock();
@@ -345,14 +348,17 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
int optname)
{
int rc = 0;
- struct sk_security_struct *sksec = sock->sk->sk_security;
+ struct sock *sk = sock->sk;
+ struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr;
rcu_read_lock();
if (level == IPPROTO_IP && optname == IP_OPTIONS &&
sksec->nlbl_state == NLBL_LABELED) {
netlbl_secattr_init(&secattr);
- rc = netlbl_socket_getattr(sock, &secattr);
+ lock_sock(sk);
+ rc = netlbl_sock_getattr(sk, &secattr);
+ release_sock(sk);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
rc = -EACCES;
netlbl_secattr_destroy(&secattr);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index aca099aa2ed..c9e92daedee 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -67,6 +67,10 @@ static struct dentry *bool_dir = NULL;
static int bool_num = 0;
static int *bool_pending_values = NULL;
+/* global data for classes */
+static struct dentry *class_dir = NULL;
+static unsigned long last_class_ino;
+
extern void selnl_notify_setenforce(int val);
/* Check whether a task is allowed to use a security operation. */
@@ -106,6 +110,7 @@ static unsigned long sel_last_ino = SEL_INO_NEXT - 1;
#define SEL_INITCON_INO_OFFSET 0x01000000
#define SEL_BOOL_INO_OFFSET 0x02000000
+#define SEL_CLASS_INO_OFFSET 0x04000000
#define SEL_INO_MASK 0x00ffffff
#define TMPBUFLEN 12
@@ -237,6 +242,11 @@ static const struct file_operations sel_policyvers_ops = {
/* declaration for sel_write_load */
static int sel_make_bools(void);
+static int sel_make_classes(void);
+
+/* declaration for sel_make_class_dirs */
+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+ unsigned long *ino);
static ssize_t sel_read_mls(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
@@ -287,10 +297,18 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
goto out;
ret = sel_make_bools();
+ if (ret) {
+ length = ret;
+ goto out1;
+ }
+
+ ret = sel_make_classes();
if (ret)
length = ret;
else
length = count;
+
+out1:
audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
"policy loaded auid=%u",
audit_get_loginuid(current->audit_context));
@@ -940,9 +958,8 @@ static const struct file_operations sel_commit_bools_ops = {
.write = sel_commit_bools_write,
};
-/* delete booleans - partial revoke() from
- * fs/proc/generic.c proc_kill_inodes */
-static void sel_remove_bools(struct dentry *de)
+/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
+static void sel_remove_entries(struct dentry *de)
{
struct list_head *p, *node;
struct super_block *sb = de->d_sb;
@@ -998,7 +1015,7 @@ static int sel_make_bools(void)
kfree(bool_pending_values);
bool_pending_values = NULL;
- sel_remove_bools(dir);
+ sel_remove_entries(dir);
if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
return -ENOMEM;
@@ -1048,7 +1065,7 @@ out:
return ret;
err:
kfree(values);
- sel_remove_bools(dir);
+ sel_remove_entries(dir);
ret = -ENOMEM;
goto out;
}
@@ -1294,7 +1311,227 @@ out:
return ret;
}
-static int sel_make_dir(struct inode *dir, struct dentry *dentry)
+static inline unsigned int sel_div(unsigned long a, unsigned long b)
+{
+ return a / b - (a % b < 0);
+}
+
+static inline unsigned long sel_class_to_ino(u16 class)
+{
+ return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
+}
+
+static inline u16 sel_ino_to_class(unsigned long ino)
+{
+ return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
+}
+
+static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
+{
+ return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
+}
+
+static inline u32 sel_ino_to_perm(unsigned long ino)
+{
+ return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
+}
+
+static ssize_t sel_read_class(struct file * file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t rc, len;
+ char *page;
+ unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+
+ page = (char *)__get_free_page(GFP_KERNEL);
+ if (!page) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino));
+ rc = simple_read_from_buffer(buf, count, ppos, page, len);
+ free_page((unsigned long)page);
+out:
+ return rc;
+}
+
+static const struct file_operations sel_class_ops = {
+ .read = sel_read_class,
+};
+
+static ssize_t sel_read_perm(struct file * file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t rc, len;
+ char *page;
+ unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+
+ page = (char *)__get_free_page(GFP_KERNEL);
+ if (!page) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
+ rc = simple_read_from_buffer(buf, count, ppos, page, len);
+ free_page((unsigned long)page);
+out:
+ return rc;
+}
+
+static const struct file_operations sel_perm_ops = {
+ .read = sel_read_perm,
+};
+
+static int sel_make_perm_files(char *objclass, int classvalue,
+ struct dentry *dir)
+{
+ int i, rc = 0, nperms;
+ char **perms;
+
+ rc = security_get_permissions(objclass, &perms, &nperms);
+ if (rc)
+ goto out;
+
+ for (i = 0; i < nperms; i++) {
+ struct inode *inode;
+ struct dentry *dentry;
+
+ dentry = d_alloc_name(dir, perms[i]);
+ if (!dentry) {
+ rc = -ENOMEM;
+ goto out1;
+ }
+
+ inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+ if (!inode) {
+ rc = -ENOMEM;
+ goto out1;
+ }
+ inode->i_fop = &sel_perm_ops;
+ /* i+1 since perm values are 1-indexed */
+ inode->i_ino = sel_perm_to_ino(classvalue, i+1);
+ d_add(dentry, inode);
+ }
+
+out1:
+ for (i = 0; i < nperms; i++)
+ kfree(perms[i]);
+ kfree(perms);
+out:
+ return rc;
+}
+
+static int sel_make_class_dir_entries(char *classname, int index,
+ struct dentry *dir)
+{
+ struct dentry *dentry = NULL;
+ struct inode *inode = NULL;
+ int rc;
+
+ dentry = d_alloc_name(dir, "index");
+ if (!dentry) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+ if (!inode) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ inode->i_fop = &sel_class_ops;
+ inode->i_ino = sel_class_to_ino(index);
+ d_add(dentry, inode);
+
+ dentry = d_alloc_name(dir, "perms");
+ if (!dentry) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino);
+ if (rc)
+ goto out;
+
+ rc = sel_make_perm_files(classname, index, dentry);
+
+out:
+ return rc;
+}
+
+static void sel_remove_classes(void)
+{
+ struct list_head *class_node;
+
+ list_for_each(class_node, &class_dir->d_subdirs) {
+ struct dentry *class_subdir = list_entry(class_node,
+ struct dentry, d_u.d_child);
+ struct list_head *class_subdir_node;
+
+ list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
+ struct dentry *d = list_entry(class_subdir_node,
+ struct dentry, d_u.d_child);
+
+ if (d->d_inode)
+ if (d->d_inode->i_mode & S_IFDIR)
+ sel_remove_entries(d);
+ }
+
+ sel_remove_entries(class_subdir);
+ }
+
+ sel_remove_entries(class_dir);
+}
+
+static int sel_make_classes(void)
+{
+ int rc = 0, nclasses, i;
+ char **classes;
+
+ /* delete any existing entries */
+ sel_remove_classes();
+
+ rc = security_get_classes(&classes, &nclasses);
+ if (rc < 0)
+ goto out;
+
+ /* +2 since classes are 1-indexed */
+ last_class_ino = sel_class_to_ino(nclasses+2);
+
+ for (i = 0; i < nclasses; i++) {
+ struct dentry *class_name_dir;
+
+ class_name_dir = d_alloc_name(class_dir, classes[i]);
+ if (!class_name_dir) {
+ rc = -ENOMEM;
+ goto out1;
+ }
+
+ rc = sel_make_dir(class_dir->d_inode, class_name_dir,
+ &last_class_ino);
+ if (rc)
+ goto out1;
+
+ /* i+1 since class values are 1-indexed */
+ rc = sel_make_class_dir_entries(classes[i], i+1,
+ class_name_dir);
+ if (rc)
+ goto out1;
+ }
+
+out1:
+ for (i = 0; i < nclasses; i++)
+ kfree(classes[i]);
+ kfree(classes);
+out:
+ return rc;
+}
+
+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+ unsigned long *ino)
{
int ret = 0;
struct inode *inode;
@@ -1306,7 +1543,7 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry)
}
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
- inode->i_ino = ++sel_last_ino;
+ inode->i_ino = ++(*ino);
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inc_nlink(inode);
d_add(dentry, inode);
@@ -1352,7 +1589,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
goto err;
}
- ret = sel_make_dir(root_inode, dentry);
+ ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
if (ret)
goto err;
@@ -1385,7 +1622,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
goto err;
}
- ret = sel_make_dir(root_inode, dentry);
+ ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
if (ret)
goto err;
@@ -1399,7 +1636,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
goto err;
}
- ret = sel_make_dir(root_inode, dentry);
+ ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
if (ret)
goto err;
@@ -1407,6 +1644,18 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
if (ret)
goto err;
+ dentry = d_alloc_name(sb->s_root, "class");
+ if (!dentry) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
+ if (ret)
+ goto err;
+
+ class_dir = dentry;
+
out:
return ret;
err:
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0ac1021734c..f05f97a2bc3 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -21,6 +21,7 @@
*/
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -598,6 +599,7 @@ void policydb_destroy(struct policydb *p)
struct range_trans *rt, *lrt = NULL;
for (i = 0; i < SYM_NUM; i++) {
+ cond_resched();
hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
hashtab_destroy(p->symtab[i].table);
}
@@ -612,6 +614,7 @@ void policydb_destroy(struct policydb *p)
avtab_destroy(&p->te_avtab);
for (i = 0; i < OCON_NUM; i++) {
+ cond_resched();
c = p->ocontexts[i];
while (c) {
ctmp = c;
@@ -623,6 +626,7 @@ void policydb_destroy(struct policydb *p)
g = p->genfs;
while (g) {
+ cond_resched();
kfree(g->fstype);
c = g->head;
while (c) {
@@ -639,18 +643,21 @@ void policydb_destroy(struct policydb *p)
cond_policydb_destroy(p);
for (tr = p->role_tr; tr; tr = tr->next) {
+ cond_resched();
kfree(ltr);
ltr = tr;
}
kfree(ltr);
for (ra = p->role_allow; ra; ra = ra -> next) {
+ cond_resched();
kfree(lra);
lra = ra;
}
kfree(lra);
for (rt = p->range_tr; rt; rt = rt -> next) {
+ cond_resched();
if (lrt) {
ebitmap_destroy(&lrt->target_range.level[0].cat);
ebitmap_destroy(&lrt->target_range.level[1].cat);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 40660ffd49b..b5f017f07a7 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1587,19 +1587,18 @@ int security_get_user_sids(u32 fromsid,
u32 *nel)
{
struct context *fromcon, usercon;
- u32 *mysids, *mysids2, sid;
+ u32 *mysids = NULL, *mysids2, sid;
u32 mynel = 0, maxnel = SIDS_NEL;
struct user_datum *user;
struct role_datum *role;
- struct av_decision avd;
struct ebitmap_node *rnode, *tnode;
int rc = 0, i, j;
- if (!ss_initialized) {
- *sids = NULL;
- *nel = 0;
+ *sids = NULL;
+ *nel = 0;
+
+ if (!ss_initialized)
goto out;
- }
POLICY_RDLOCK;
@@ -1635,17 +1634,9 @@ int security_get_user_sids(u32 fromsid,
if (mls_setup_user_range(fromcon, user, &usercon))
continue;
- rc = context_struct_compute_av(fromcon, &usercon,
- SECCLASS_PROCESS,
- PROCESS__TRANSITION,
- &avd);
- if (rc || !(avd.allowed & PROCESS__TRANSITION))
- continue;
rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
- if (rc) {
- kfree(mysids);
+ if (rc)
goto out_unlock;
- }
if (mynel < maxnel) {
mysids[mynel++] = sid;
} else {
@@ -1653,7 +1644,6 @@ int security_get_user_sids(u32 fromsid,
mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
if (!mysids2) {
rc = -ENOMEM;
- kfree(mysids);
goto out_unlock;
}
memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
@@ -1664,11 +1654,32 @@ int security_get_user_sids(u32 fromsid,
}
}
- *sids = mysids;
- *nel = mynel;
-
out_unlock:
POLICY_RDUNLOCK;
+ if (rc || !mynel) {
+ kfree(mysids);
+ goto out;
+ }
+
+ mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
+ if (!mysids2) {
+ rc = -ENOMEM;
+ kfree(mysids);
+ goto out;
+ }
+ for (i = 0, j = 0; i < mynel; i++) {
+ rc = avc_has_perm_noaudit(fromsid, mysids[i],
+ SECCLASS_PROCESS,
+ PROCESS__TRANSITION, AVC_STRICT,
+ NULL);
+ if (!rc)
+ mysids2[j++] = mysids[i];
+ cond_resched();
+ }
+ rc = 0;
+ kfree(mysids);
+ *sids = mysids2;
+ *nel = j;
out:
return rc;
}
@@ -1996,6 +2007,101 @@ out:
return rc;
}
+static int get_classes_callback(void *k, void *d, void *args)
+{
+ struct class_datum *datum = d;
+ char *name = k, **classes = args;
+ int value = datum->value - 1;
+
+ classes[value] = kstrdup(name, GFP_ATOMIC);
+ if (!classes[value])
+ return -ENOMEM;
+
+ return 0;
+}
+
+int security_get_classes(char ***classes, int *nclasses)
+{
+ int rc = -ENOMEM;
+
+ POLICY_RDLOCK;
+
+ *nclasses = policydb.p_classes.nprim;
+ *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
+ if (!*classes)
+ goto out;
+
+ rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+ *classes);
+ if (rc < 0) {
+ int i;
+ for (i = 0; i < *nclasses; i++)
+ kfree((*classes)[i]);
+ kfree(*classes);
+ }
+
+out:
+ POLICY_RDUNLOCK;
+ return rc;
+}
+
+static int get_permissions_callback(void *k, void *d, void *args)
+{
+ struct perm_datum *datum = d;
+ char *name = k, **perms = args;
+ int value = datum->value - 1;
+
+ perms[value] = kstrdup(name, GFP_ATOMIC);
+ if (!perms[value])
+ return -ENOMEM;
+
+ return 0;
+}
+
+int security_get_permissions(char *class, char ***perms, int *nperms)
+{
+ int rc = -ENOMEM, i;
+ struct class_datum *match;
+
+ POLICY_RDLOCK;
+
+ match = hashtab_search(policydb.p_classes.table, class);
+ if (!match) {
+ printk(KERN_ERR "%s: unrecognized class %s\n",
+ __FUNCTION__, class);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ *nperms = match->permissions.nprim;
+ *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC);
+ if (!*perms)
+ goto out;
+
+ if (match->comdatum) {
+ rc = hashtab_map(match->comdatum->permissions.table,
+ get_permissions_callback, *perms);
+ if (rc < 0)
+ goto err;
+ }
+
+ rc = hashtab_map(match->permissions.table, get_permissions_callback,
+ *perms);
+ if (rc < 0)
+ goto err;
+
+out:
+ POLICY_RDUNLOCK;
+ return rc;
+
+err:
+ POLICY_RDUNLOCK;
+ for (i = 0; i < *nperms; i++)
+ kfree((*perms)[i]);
+ kfree(*perms);
+ return rc;
+}
+
struct selinux_audit_rule {
u32 au_seqno;
struct context au_ctxt;
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 19c65a8d86a..7bc2767e158 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -361,7 +361,7 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
err:
if (card)
snd_card_free(card);
- if (CKEN & CKEN_AC97) {
+ if (CKEN & (1 << CKEN_AC97)) {
GCR |= GCR_ACLINK_OFF;
free_irq(IRQ_AC97, NULL);
pxa_set_cken(CKEN_AC97, 0);
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index c7e1b264619..e7ed868fa7c 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -987,7 +987,7 @@ static int __init sa11xx_uda1341_init(void)
if (platform_get_drvdata(device))
return 0;
platform_device_unregister(device);
- err = -ENODEV
+ err = -ENODEV;
} else
err = PTR_ERR(device);
platform_driver_unregister(&sa11xx_uda1341_driver);
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index ebb1bdac723..2025db5947a 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -1048,7 +1048,7 @@ static struct platform_driver snd_mts64_driver = {
/*********************************************************************
* module init stuff
*********************************************************************/
-static void __init_or_module snd_mts64_unregister_all(void)
+static void snd_mts64_unregister_all(void)
{
int i;
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 61a323cc0e4..4f6800b43b0 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -953,7 +953,7 @@ static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
static struct isa_driver snd_opl3sa2_isa_driver = {
.match = snd_opl3sa2_isa_match,
.probe = snd_opl3sa2_isa_probe,
- .remove = __devexit( snd_opl3sa2_isa_remove),
+ .remove = __devexit_p(snd_opl3sa2_isa_remove),
#ifdef CONFIG_PM
.suspend = snd_opl3sa2_isa_suspend,
.resume = snd_opl3sa2_isa_resume,
diff --git a/sound/oss/emu10k1/main.c b/sound/oss/emu10k1/main.c
index 16ac02540a3..5058411b752 100644
--- a/sound/oss/emu10k1/main.c
+++ b/sound/oss/emu10k1/main.c
@@ -1302,7 +1302,7 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev
goto err_irq;
}
- pci_read_config_byte(pci_dev, PCI_REVISION_ID, &card->chiprev);
+ card->chiprev = pci_dev->revision;
pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
printk(KERN_INFO "emu10k1: %s rev %d model %#04x found, IO at %#04lx-%#04lx, IRQ %d\n",
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index 593a3aac12c..52648573f60 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -2894,7 +2894,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
s->irq = pcidev->irq;
s->vendor = pcidev->vendor;
s->device = pcidev->device;
- pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+ s->rev = pcidev->revision;
s->codec->private_data = s;
s->codec->id = 0;
s->codec->codec_read = rdcodec;
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c
index 27acd6f29b9..7de18b58f2c 100644
--- a/sound/oss/sb_card.c
+++ b/sound/oss/sb_card.c
@@ -290,7 +290,7 @@ static struct pnp_card_driver sb_pnp_driver = {
MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table);
#endif /* CONFIG_PNP */
-static void __init_or_module sb_unregister_all(void)
+static void sb_unregister_all(void)
{
#ifdef CONFIG_PNP
if (pnp_registered)
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index e1ed59549c5..41543a4933e 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1250,7 +1250,7 @@ static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream,
evoice->substream = substream;
}
} else {
- if (!evoice) {
+ if (evoice) {
snd_ali_free_voice(codec, evoice);
pvoice->extra = evoice = NULL;
}
@@ -1267,7 +1267,7 @@ static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream)
struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL;
snd_pcm_lib_free_pages(substream);
- if (!evoice) {
+ if (evoice) {
snd_ali_free_voice(codec, evoice);
pvoice->extra = NULL;
}
@@ -1356,7 +1356,7 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream)
VOL,
CTRL,
EC);
- if (!evoice) {
+ if (evoice) {
evoice->count = pvoice->count;
evoice->eso = pvoice->count << 1;
ESO = evoice->eso - 1;
@@ -2218,7 +2218,7 @@ static int __devinit snd_ali_create(struct snd_card *card,
codec->card = card;
codec->pci = pci;
codec->irq = -1;
- pci_read_config_byte(pci, PCI_REVISION_ID, &codec->revision);
+ codec->revision = pci->revision;
codec->spdif_support = spdif_support;
if (pcm_streams < 1)
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 7d8053b5e8d..89184a42414 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1639,15 +1639,12 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
{
struct snd_card *card;
struct atiixp *chip;
- unsigned char revision;
int err;
card = snd_card_new(index, id, THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
- pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
-
strcpy(card->driver, spdif_aclink ? "ATIIXP" : "ATIIXP-SPDMA");
strcpy(card->shortname, "ATI IXP");
if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
@@ -1670,7 +1667,8 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
snd_atiixp_chip_start(chip);
snprintf(card->longname, sizeof(card->longname),
- "%s rev %x with %s at %#lx, irq %i", card->shortname, revision,
+ "%s rev %x with %s at %#lx, irq %i", card->shortname,
+ pci->revision,
chip->ac97[0] ? snd_ac97_get_short_name(chip->ac97[0]) : "?",
chip->addr, chip->irq);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 904023fe4f2..ce752f84457 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1283,15 +1283,12 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
{
struct snd_card *card;
struct atiixp_modem *chip;
- unsigned char revision;
int err;
card = snd_card_new(index, id, THIS_MODULE, 0);
if (card == NULL)
return -ENOMEM;
- pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
-
strcpy(card->driver, "ATIIXP-MODEM");
strcpy(card->shortname, "ATI IXP Modem");
if ((err = snd_atiixp_create(card, pci, &chip)) < 0)
@@ -1312,7 +1309,7 @@ static int __devinit snd_atiixp_probe(struct pci_dev *pci,
snd_atiixp_chip_start(chip);
sprintf(card->longname, "%s rev %x at 0x%lx, irq %i",
- card->shortname, revision, chip->addr, chip->irq);
+ card->shortname, pci->revision, chip->addr, chip->irq);
if ((err = snd_card_register(card)) < 0)
goto __error;
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 238154bb7a2..5ec1b6fcd54 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -341,11 +341,7 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
snd_card_free(card);
return err;
}
- if ((err = pci_read_config_byte(pci, PCI_REVISION_ID,
- &(chip->rev))) < 0) {
- snd_card_free(card);
- return err;
- }
+ chip->rev = pci->revision;
#ifdef CHIP_AU8830
if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
printk(KERN_ALERT
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index aaac6e5b476..a0420bc63f0 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -590,7 +590,6 @@ struct snd_ca0106 {
struct resource *res_port;
int irq;
- unsigned char revision; /* chip revision */
unsigned int serial; /* serial number */
unsigned short model; /* subsystem id */
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 48f3f17c517..9fd7b8a5b75 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1293,13 +1293,12 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
}
pci_set_master(pci);
- /* read revision & serial */
- pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
+ /* read serial */
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
#if 1
printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
- chip->revision, chip->serial);
+ pci->revision, chip->serial);
#endif
strcpy(card->driver, "CA0106");
strcpy(card->shortname, "CA0106");
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index dbc805c33fc..4a9b59ad8ab 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1511,7 +1511,6 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
struct snd_emu10k1 *emu;
int idx, err;
int is_audigy;
- unsigned char revision;
unsigned int silent_page;
const struct snd_emu_chip_details *c;
static struct snd_device_ops ops = {
@@ -1543,8 +1542,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
emu->synth = NULL;
emu->get_synth_voice = NULL;
/* read revision & serial */
- pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
- emu->revision = revision;
+ emu->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index bb0fec7f7e1..e4af7a9b808 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -942,7 +942,7 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card,
pci_set_master(pci);
/* read revision & serial */
- pci_read_config_byte(pci, PCI_REVISION_ID, &chip->revision);
+ chip->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
snd_printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 6a0ddcf0088..7c403965153 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2110,7 +2110,6 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
struct ensoniq ** rensoniq)
{
struct ensoniq *ensoniq;
- unsigned char cmdb;
int err;
static struct snd_device_ops ops = {
.dev_free = snd_ensoniq_dev_free,
@@ -2151,8 +2150,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
}
#endif
pci_set_master(pci);
- pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb);
- ensoniq->rev = cmdb;
+ ensoniq->rev = pci->revision;
#ifdef CHIP1370
#if 0
ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 6dc578bbeec..11015178e20 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1369,7 +1369,6 @@ static int __devinit snd_fm801_create(struct snd_card *card,
struct fm801 ** rchip)
{
struct fm801 *chip;
- unsigned char rev;
int err;
static struct snd_device_ops ops = {
.dev_free = snd_fm801_dev_free,
@@ -1405,8 +1404,7 @@ static int __devinit snd_fm801_create(struct snd_card *card,
pci_set_master(pci);
}
- pci_read_config_byte(pci, PCI_REVISION_ID, &rev);
- if (rev >= 0xb1) /* FM801-AU */
+ if (pci->revision >= 0xb1) /* FM801-AU */
chip->multichannel = 1;
snd_fm801_chip_init(chip, 0);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 8e89d56b640..f87f8f08895 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -713,6 +713,19 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
return info->amp_caps;
}
+int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
+ unsigned int caps)
+{
+ struct hda_amp_info *info;
+
+ info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, dir, 0));
+ if (!info)
+ return -EINVAL;
+ info->amp_caps = caps;
+ info->status |= INFO_AMP_CAPS;
+ return 0;
+}
+
/*
* read the current volume to info
* if the cache exists, read the cache value.
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index be12b8814c3..f91ea5ec9f6 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -277,5 +277,7 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
return codec->wcaps[nid - codec->start_nid];
}
+int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
+ unsigned int caps);
#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index a5a4b2bddf2..bef214bcddd 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -705,6 +705,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
.get = conexant_mux_enum_get,
.put = conexant_mux_enum_put,
},
+ /* Audio input controls */
+ HDA_CODEC_VOLUME("Input-1 Volume", 0x1a, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Input-1 Switch", 0x1a, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Input-2 Volume", 0x1a, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Input-2 Switch", 0x1a, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Input-3 Volume", 0x1a, 0x2, HDA_INPUT),
+ HDA_CODEC_MUTE("Input-3 Switch", 0x1a, 0x2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Input-4 Volume", 0x1a, 0x3, HDA_INPUT),
+ HDA_CODEC_MUTE("Input-4 Switch", 0x1a, 0x3, HDA_INPUT),
+ HDA_CODEC_VOLUME("Input-5 Volume", 0x1a, 0x4, HDA_INPUT),
+ HDA_CODEC_MUTE("Input-5 Switch", 0x1a, 0x4, HDA_INPUT),
{ } /* end */
};
@@ -947,6 +958,23 @@ static void cxt5047_hp_automute(struct hda_codec *codec)
snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
}
+/* mute internal speaker if HP is plugged */
+static void cxt5047_hp2_automute(struct hda_codec *codec)
+{
+ struct conexant_spec *spec = codec->spec;
+ unsigned int bits;
+
+ spec->hp_present = snd_hda_codec_read(codec, 0x13, 0,
+ AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+
+ bits = spec->hp_present ? 0x80 : 0;
+ snd_hda_codec_amp_update(codec, 0x1d, 0, HDA_OUTPUT, 0, 0x80, bits);
+ snd_hda_codec_amp_update(codec, 0x1d, 1, HDA_OUTPUT, 0, 0x80, bits);
+ /* Mute/Unmute PCM 2 for good measure - some systems need this */
+ snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0, 0x80, bits);
+ snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0, 0x80, bits);
+}
+
/* toggle input of built-in and mic jack appropriately */
static void cxt5047_hp_automic(struct hda_codec *codec)
{
@@ -985,6 +1013,21 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec,
}
}
+/* unsolicited event for HP jack sensing - non-EAPD systems */
+static void cxt5047_hp2_unsol_event(struct hda_codec *codec,
+ unsigned int res)
+{
+ res >>= 26;
+ switch (res) {
+ case CONEXANT_HP_EVENT:
+ cxt5047_hp2_automute(codec);
+ break;
+ case CONEXANT_MIC_EVENT:
+ cxt5047_hp_automic(codec);
+ break;
+ }
+}
+
static struct snd_kcontrol_new cxt5047_mixers[] = {
HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
@@ -1300,19 +1343,20 @@ static int patch_cxt5047(struct hda_codec *codec)
spec->channel_mode = cxt5047_modes,
codec->patch_ops = conexant_patch_ops;
- codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
cxt5047_models,
cxt5047_cfg_tbl);
switch (board_config) {
case CXT5047_LAPTOP:
+ codec->patch_ops.unsol_event = cxt5047_hp2_unsol_event;
break;
case CXT5047_LAPTOP_HP:
spec->input_mux = &cxt5047_hp_capture_source;
spec->num_init_verbs = 2;
spec->init_verbs[1] = cxt5047_hp_init_verbs;
spec->mixers[0] = cxt5047_hp_mixers;
+ codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
codec->patch_ops.init = cxt5047_hp_init;
break;
case CXT5047_LAPTOP_EAPD:
@@ -1320,12 +1364,14 @@ static int patch_cxt5047(struct hda_codec *codec)
spec->num_init_verbs = 2;
spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
spec->mixers[0] = cxt5047_toshiba_mixers;
+ codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
break;
#ifdef CONFIG_SND_DEBUG
case CXT5047_TEST:
spec->input_mux = &cxt5047_test_capture_source;
spec->mixers[0] = cxt5047_test_mixer;
spec->init_verbs[0] = cxt5047_test_init_verbs;
+ codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
#endif
}
return 0;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 34ac6346953..4776de93928 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6379,8 +6379,10 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
+ SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
@@ -6391,6 +6393,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
+ SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
@@ -8765,7 +8768,6 @@ static struct snd_pci_quirk alc861_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
- SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST),
SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
@@ -9473,6 +9475,7 @@ static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
+ SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST),
SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 6fcda9bcf0c..43f537ef40b 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -304,6 +304,8 @@ struct hda_codec_preset snd_hda_preset_si3054[] = {
{ .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 },
+ /* Asus A8J Modem (SM56) */
+ { .id = 0x15433155, .name = "Si3054", .patch = patch_si3054 },
{}
};
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a6a0a80edc3..e3964fc4c40 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -51,6 +51,7 @@ enum {
STAC_925x_REF,
STAC_M2_2,
STAC_MA6,
+ STAC_PA6,
STAC_925x_MODELS
};
@@ -152,6 +153,10 @@ static hda_nid_t stac925x_dac_nids[1] = {
0x02,
};
+static hda_nid_t stac925x_dmic_nids[1] = {
+ 0x15,
+};
+
static hda_nid_t stac922x_adc_nids[2] = {
0x06, 0x07,
};
@@ -469,6 +474,14 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = {
"Dell Precision M90", STAC_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d6,
"unknown Dell", STAC_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01d8,
+ "Dell Inspiron 640m", STAC_REF),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f5,
+ "Dell Inspiron 1501", STAC_REF),
+
+ /* Panasonic */
+ SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF),
+
{} /* terminator */
};
@@ -482,29 +495,38 @@ static unsigned int stac925x_MA6_pin_configs[8] = {
0x90a70320, 0x90100211, 0x400003f1, 0x9033032e,
};
+static unsigned int stac925x_PA6_pin_configs[8] = {
+ 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,
+ 0x50a103f0, 0x90100211, 0x400003f1, 0x9033032e,
+};
+
static unsigned int stac925xM2_2_pin_configs[8] = {
- 0x40c003f3, 0x424503f2, 0x041800f4, 0x02a19020,
- 0x50a103F0, 0x90100210, 0x400003f1, 0x9033032e,
+ 0x40c003f3, 0x424503f2, 0x04180011, 0x02a19020,
+ 0x50a103f0, 0x90100212, 0x400003f1, 0x9033032e,
};
static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
[STAC_REF] = ref925x_pin_configs,
[STAC_M2_2] = stac925xM2_2_pin_configs,
[STAC_MA6] = stac925x_MA6_pin_configs,
+ [STAC_PA6] = stac925x_PA6_pin_configs,
};
static const char *stac925x_models[STAC_925x_MODELS] = {
[STAC_REF] = "ref",
[STAC_M2_2] = "m2-2",
[STAC_MA6] = "m6",
+ [STAC_PA6] = "pa6",
};
static struct snd_pci_quirk stac925x_cfg_tbl[] = {
/* SigmaTel reference board */
SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
+ SND_PCI_QUIRK(0x8384, 0x7632, "Stac9202 Reference Board", STAC_REF),
SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_REF),
SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_REF),
SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_MA6),
+ SND_PCI_QUIRK(0x107b, 0x0681, "Gateway NX860", STAC_PA6),
SND_PCI_QUIRK(0x1002, 0x437b, "Gateway MX6453", STAC_M2_2),
{} /* terminator */
};
@@ -1742,6 +1764,21 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
+ if (pin_ctl & AC_PINCTL_IN_EN) {
+ /*
+ * we need to check the current set-up direction of
+ * shared input pins since they can be switched via
+ * "xxx as Output" mixer switch
+ */
+ struct sigmatel_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ if ((nid == cfg->input_pins[AUTO_PIN_LINE] &&
+ spec->line_switch) ||
+ (nid == cfg->input_pins[AUTO_PIN_MIC] &&
+ spec->mic_switch))
+ return;
+ }
+
/* if setting pin direction bits, clear the current
direction bits first */
if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))
@@ -1911,7 +1948,8 @@ static int patch_stac925x(struct hda_codec *codec)
stac925x_cfg_tbl);
again:
if (spec->board_config < 0) {
- snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x, using BIOS defaults\n");
+ snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
+ "using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
if (err < 0) {
stac92xx_free(codec);
@@ -1929,7 +1967,18 @@ static int patch_stac925x(struct hda_codec *codec)
spec->adc_nids = stac925x_adc_nids;
spec->mux_nids = stac925x_mux_nids;
spec->num_muxes = 1;
- spec->num_dmics = 0;
+ switch (codec->vendor_id) {
+ case 0x83847632: /* STAC9202 */
+ case 0x83847633: /* STAC9202D */
+ case 0x83847636: /* STAC9251 */
+ case 0x83847637: /* STAC9251D */
+ spec->num_dmics = 1;
+ spec->dmic_nids = stac925x_dmic_nids;
+ break;
+ default:
+ spec->num_dmics = 0;
+ break;
+ }
spec->init = stac925x_core_init;
spec->mixer = stac925x_mixer;
@@ -2110,6 +2159,13 @@ static int patch_stac927x(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
+ /* Fix Mux capture level; max to 2 */
+ snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT,
+ (0 << AC_AMPCAP_OFFSET_SHIFT) |
+ (2 << AC_AMPCAP_NUM_STEPS_SHIFT) |
+ (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) |
+ (0 << AC_AMPCAP_MUTE_SHIFT));
+
return 0;
}
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index f03c02c0774..4bae7305a79 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -705,7 +705,7 @@ static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,
}
-static const struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
+static struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "MIODIO IEC958 Capture Input",
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index a28992269f5..50c9f92cfd1 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2431,7 +2431,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
{
struct snd_card *card;
struct via82xx *chip;
- unsigned char revision;
int chip_type = 0, card_type;
unsigned int i;
int err;
@@ -2441,18 +2440,17 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
return -ENOMEM;
card_type = pci_id->driver_data;
- pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
switch (card_type) {
case TYPE_CARD_VIA686:
strcpy(card->driver, "VIA686A");
- sprintf(card->shortname, "VIA 82C686A/B rev%x", revision);
+ sprintf(card->shortname, "VIA 82C686A/B rev%x", pci->revision);
chip_type = TYPE_VIA686;
break;
case TYPE_CARD_VIA8233:
chip_type = TYPE_VIA8233;
- sprintf(card->shortname, "VIA 823x rev%x", revision);
+ sprintf(card->shortname, "VIA 823x rev%x", pci->revision);
for (i = 0; i < ARRAY_SIZE(via823x_cards); i++) {
- if (revision == via823x_cards[i].revision) {
+ if (pci->revision == via823x_cards[i].revision) {
chip_type = via823x_cards[i].type;
strcpy(card->shortname, via823x_cards[i].name);
break;
@@ -2460,7 +2458,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
}
if (chip_type != TYPE_VIA8233A) {
if (dxs_support == VIA_DXS_AUTO)
- dxs_support = check_dxs_list(pci, revision);
+ dxs_support = check_dxs_list(pci, pci->revision);
/* force to use VIA8233 or 8233A model according to
* dxs_support module option
*/
@@ -2471,7 +2469,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
}
if (chip_type == TYPE_VIA8233A)
strcpy(card->driver, "VIA8233A");
- else if (revision >= VIA_REV_8237)
+ else if (pci->revision >= VIA_REV_8237)
strcpy(card->driver, "VIA8237"); /* no slog assignment */
else
strcpy(card->driver, "VIA8233");
@@ -2482,7 +2480,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
goto __error;
}
- if ((err = snd_via82xx_create(card, pci, chip_type, revision,
+ if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision,
ac97_clock, &chip)) < 0)
goto __error;
card->private_data = chip;
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index b338e15db0d..8cbf8eba4ae 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1162,7 +1162,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
{
struct snd_card *card;
struct via82xx_modem *chip;
- unsigned char revision;
int chip_type = 0, card_type;
unsigned int i;
int err;
@@ -1172,7 +1171,6 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
return -ENOMEM;
card_type = pci_id->driver_data;
- pci_read_config_byte(pci, PCI_REVISION_ID, &revision);
switch (card_type) {
case TYPE_CARD_VIA82XX_MODEM:
strcpy(card->driver, "VIA82XX-MODEM");
@@ -1184,7 +1182,7 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
goto __error;
}
- if ((err = snd_via82xx_create(card, pci, chip_type, revision,
+ if ((err = snd_via82xx_create(card, pci, chip_type, pci->revision,
ac97_clock, &chip)) < 0)
goto __error;
card->private_data = chip;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index ea861bceadd..ab7a81c3570 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2404,7 +2404,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
chip->pci = pci;
chip->irq = -1;
chip->device_id = pci->device;
- pci_read_config_byte(pci, PCI_REVISION_ID, &chip->rev);
+ chip->rev = pci->revision;
chip->reg_area_phys = pci_resource_start(pci, 0);
chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000);
pci_set_master(pci);
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index 5f38f670102..a1aa89f2faf 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -118,7 +118,7 @@ static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type,
default: return -1;
}
- chip = dev->private;
+ chip = input_get_drvdata(dev);
if (! chip || (beep = chip->beep) == NULL)
return -1;
@@ -239,8 +239,8 @@ int __init snd_pmac_attach_beep(struct snd_pmac *chip)
input_dev->evbit[0] = BIT(EV_SND);
input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
input_dev->event = snd_pmac_beep_event;
- input_dev->private = chip;
- input_dev->cdev.dev = &chip->pdev->dev;
+ input_dev->dev.parent = &chip->pdev->dev;
+ input_set_drvdata(input_dev, chip);
beep->dev = input_dev;
beep->buf = dmabuf;
@@ -251,8 +251,8 @@ int __init snd_pmac_attach_beep(struct snd_pmac *chip)
err = snd_ctl_add(chip->card, beep_ctl);
if (err < 0)
goto fail1;
-
- chip->beep = beep;
+
+ chip->beep = beep;
err = input_register_device(beep->dev);
if (err)
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 5a2bef44a2f..7a22f0f3784 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -775,7 +775,8 @@ static int snd_pmac_free(struct snd_pmac *chip)
out_le32(&chip->awacs->control, in_le32(&chip->awacs->control) & 0xfff);
}
- snd_pmac_sound_feature(chip, 0);
+ if (chip->node)
+ snd_pmac_sound_feature(chip, 0);
/* clean up mixer if any */
if (chip->mixer_free)
@@ -925,6 +926,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
}
if (! sound) {
of_node_put(chip->node);
+ chip->node = NULL;
return -ENODEV;
}
prop = of_get_property(sound, "sub-frame", NULL);
@@ -937,7 +939,9 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
printk(KERN_INFO "snd-powermac no longer handles any "
"machines with a layout-id property "
"in the device-tree, use snd-aoa.\n");
+ of_node_put(sound);
of_node_put(chip->node);
+ chip->node = NULL;
return -ENODEV;
}
/* This should be verified on older screamers */
@@ -1297,8 +1301,6 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
return 0;
__error:
- if (chip->pdev)
- pci_dev_put(chip->pdev);
snd_pmac_free(chip);
return err;
}
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index b222755763e..129d851b315 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -300,7 +300,7 @@ static int pxa2xx_ac97_probe(struct platform_device *pdev)
return 0;
err:
- if (CKEN & CKEN_AC97) {
+ if (CKEN & (1 << CKEN_AC97)) {
GCR |= GCR_ACLINK_OFF;
free_irq(IRQ_AC97, NULL);
pxa_set_cken(CKEN_AC97, 0);
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 21dc6974d6a..bfbdc3cbd43 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -337,6 +337,8 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
if (prtd == NULL)
return -ENOMEM;
+ spin_lock_init(&prtd->lock);
+
runtime->private_data = prtd;
return 0;
}